Pastes are probably the last edit one means to make before the query
should run so it doesn't need to be debounced.
This makes global search much snappier for example when accepting the
history suggestion from the '/' register or pasting a pattern from the
clipboard or a register.
Two changes from the parent commit:
* Save only the `Picker::primary_query` - so you don't save other parts
of the query, for example `%path foo.rs` while in `global_search`.
* Move the saving out of the `if let Some(option) = self.selection()`
block. So when you hit enter you save to history whether you have a
selection or not. If you want to close the picker without saving to
the register you can use C-c or Esc instead.
The Prompt is set up to push the current line to history when hitting
Enter but the Picker doesn't pass the Enter event down to the Prompt
(for good reason: we don't want the Prompt's behavior of changing
completions when we hit a path separator). We should save the Prompt's
line to its configured history register when hitting Enter when there
is a selection in the Picker.
This currently only applies to `global_search`'s Picker since it's the
only Picker to use `Picker::with_history_register`.
These haven't been updated in a little while. The original plan was to
update the version (in `Cargo.toml`) after a release to the next
planned release date but the way we release now is to update the version
as a part of the release process (just before tagging). Typically this
is all taken care of in the CHANGELOG-updating branch along with the
other documentation changes like the appdata file. The workflow now is
basically just to merge the changelog/release branch, pull, tag and push.
This commit brings the text decoration API inline with the
LineAnnotation API (so they are consistent) resulting in a single
streamlined API instead of multiple ADHOK callbacks.
The line annotation as implemented in #5420 had two shortcomings:
* It required the height of virtual text lines to be known ahead time
* It checked for line anchors at every grapheme
The first problem made the API impractical to use in practice because
almost all virtual text needs to be softwrapped. For example inline
diagnostics should be softwrapped to avoid cutting off the diagnostic
message (as no scrolling is possible). While more complex virtual text
like side by side diffs must dynamically calculate the number of empty
lines two align two documents (which requires taking account both
softwrap and virtual text). To address this, the API has been
refactored to use a trait.
The second issue caused some performance overhead and unnecessarily
complicated the `DocumentFormatter`. It was addressed by only calling
the trait mentioned above at line breaks (instead of always). This
allows offers additional flexibility to annotations as it offers
the flexibility to align lines (needed for side by side diffs).
We can track the ranges in the input text that correspond to each column
and use this information during rendering to apply a new theme key that
makes the "active column" stand out. This makes it easier to tell at
a glance which column you're entering.
`Picker::new` loops through the input options to inject each of them, so
there's no need to collect into an intermediary Vec. This removes some
unnecessary collections. Also, pickers that start with no initial
options can now pass an empty slice instead of an empty Vec.
Co-authored-by: Luis Useche <useche@gmail.com>
The `FileLocation` and `PathOrId` types can borrow paths rather than
requiring them to be owned. This takes a refactor of the preview
functions and preview internals within `Picker`. With this change we
avoid an unnecessary `PathBuf` clone per render for any picker with a
file preview function (i.e. most pickers).
This refactor is not fully complete. The `PathOrId` is _sometimes_ an
owned `PathBuf`. This is for pragmatic reasons rather than technical
ones. We need a further refactor to introduce more core types like
`Location` in order to eliminate the Cow and only use `&Path`s within
`PathOrId`. This is left for future work as it will be a larger refactor
almost entirely fitting into the LSP commands module and helix-core -
i.e. mostly unrelated to refactoring the `Picker` code itself.
Co-authored-by: Pascal Kuthe <pascalkuthe@pm.me>
This introduces a custom URI type in core meant to be extended later
if we want to support other schemes. For now it's just a wrapper over a
PathBuf. We use this new URI type to firewall `lsp::Url`. This was
previously done in 8141a4a but using a custom URI type is more flexible
and will improve the way Pickers handle paths for previews in the child
commit(s).
Co-authored-by: soqb <cb.setho@gmail.com>
This fixes the changed files picker when used against a clean worktree
for example. Without it the running indicator does not disappear. It
also simplifies the dynamic query handler's implementation so that it
doesn't need to request a redraw explicitly.
Co-authored-by: Pascal Kuthe <pascalkuthe@pm.me>
We could expand on this in the future to have different preview modes
that you can toggle between with C-t. Currently that binding just hides
the preview but it could switch between different preview modes and in
one mode hide the path and just show the line contents.
The parent commit split out the workspace symbol picker to an inline
definition so the `workspace` parameter is never passed as `true`. We
should consolidate this picker definition into the symbol_picker
function.
DynamicPicker is a thin wrapper over Picker that holds some additional
state, similar to the old FilePicker type. Like with FilePicker, we want
to fold the two types together, having Picker optionally hold that
extra state.
The DynamicPicker is a little more complicated than FilePicker was
though - it holds a query callback and current query string in state and
provides some debounce for queries using the IdleTimeout event.
We can move all of that state and debounce logic into an AsyncHook
implementation, introduced here as `DynamicQueryHandler`. The hook
receives updates to the primary query and debounces those events so
that once a query has been idle for a short time (275ms) we re-run
the query.
A standard Picker created through `new` for example can be promoted into
a Dynamic picker by chaining the new `with_dynamic_query` function, very
similar to FilePicker's replacement `with_preview`.
The workspace symbol picker has been migrated to the new way of writing
dynamic pickers as an example. The child commit will promote global
search into a dynamic Picker as well.
We will use this in the child commit to improve the picker's running
indicator. Nucleo 0.4.0 includes an `active_injectors` member that we
can use to detect if anything can push to the picker. When that count
drops to zero we can remove the running indicator.
Nucleo 0.4.1 contains a fix for crashes with interactive global search
on a large directory.
This works nicely for dynamic pickers: we stop any running jobs like
global search that are pushing to the injector by incrementing the
version number when we start a new request. The boolean only allowed
us to shut the picker down once, but with a usize a picker can have
multiple "sessions" / "life-cycles" where it receives new options
from an injector.
Now that the picker is defined as a table, we need a way to provide
input for each field in the picker. We introduce a small query syntax
that supports multiple columns without being too verbose. Fields are
specified as `%field pattern`. The default column for a picker doesn't
need the `%field` prefix. The field name may be selected by a prefix
of the field, for example `%p foo.rs` rather than `%path foo.rs`.
Co-authored-by: ItsEthra <107059409+ItsEthra@users.noreply.github.com>
`menu::Item` is replaced with column configurations for each picker
which control how a column is displayed and whether it is passed to
nucleo for filtering. (This is used for dynamic pickers so that we can
filter those items with the dynamic picker callback rather than nucleo.)
The picker has a new lucene-like syntax that can be used to filter the
picker only on certain criteria. If a filter is not specified, the text
in the prompt applies to the picker's configured "primary" column.
Adding column configurations for each picker is left for the child
commit.