The code in the `sort_layers` function was fully duplicated between
the HighlightIter and the QueryIter. This change adds a common
`sort_layers` function that accepts a layer Vec from both.
This is brings the fix from d5f17d3 to the QueryIter layers. A trait
for getting the cursor and sort-key from each layer helps cut down on
code duplicated between these iterators.
We call the rainbow_spans function introduced in the parent commits
over the largest node that contains the current viewport: we need to
reach far enough back in the document that we find the absolute
beginning for brackets. If we run rainbow_spans only over the current
viewport, we get a bug where the color of rainbow brackets changes as
we move the viewport.
This is an example usage of the query_iter introduced in the parent
commit: captures are returned in order across language layers. We
can use this iterator and a stack for the rainbow scopes to calculate
highlight spans that can be merged into the syntax highlights using
syntax::merge.
This can be used to calculate rainbow highlights (see the child commit)
or indents or textobjects and be accurate to the injected content
rather than just the root layer. This is useful for languages which
use injections heavily like Vue or JavaScript within HTML but are also
useful in common scenarios like within codeblocks in Markdown.
This iterator shares some code with the HighlightIter and
HighlightIterLayer but that iterator emits HighlightEvents, so it cares
about the beginnings and ends of highlight events rather than captures.
This option is similar to the `rulers` config: it can be set no the
editor key in config and also overridden for specific languages, so
you could enable rainbow brackets for lisps for example without
enabling it globally.
We clone this type very often in LSP pickers, for example diagnostics
and symbols. We can use a single Arc in many cases to avoid the
unnecessary clones.
The lsp location type has the lsp's URI type and a range. We can replace
that with a custom type private to the lsp commands module that uses the
core URI type instead.
We can't entirely replace the type with a new Location type in core.
That type might look like:
pub struct Location {
uri: crate::Uri,
range: crate::Range,
}
But we can't convert every `lsp::Location` to this type because for
definitions, references and diagnostics language servers send documents
which we haven't opened yet, so we don't have the information to convert
an `lsp::Range` (line+col) to a `helix_core::Range` (char indexing).
This cleans up the picker definitions in this file so that they can all
use helpers like `jump_to_location` and `location_to_file_location` for
the picker preview. It also removes the only use of the deprecated
`PathOrId::from_path_buf` function, allowing us to drop the owned
variant of that type in the child commit.
Whenever a document is changed helix maps various positions like the
cursor or diagnostics through the `ChangeSet` applied to the document.
Currently, this mapping handles replacements as follows:
* Move position to the left for `Assoc::Before` (start of selection)
* Move position to the right for `Assoc::After` (end of selection)
However, when text is exactly replaced this can produce weird results
where the cursor is moved when it shouldn't. For example if `foo` is
selected and a separate cursor is placed on each character (`s.<ret>`)
and the text is replaced (for example `rx`) then the cursors are moved
to the side instead of remaining in place.
This change adds a special case to the mapping code of replacements:
If the deleted and inserted text have the same (char) length then
the position is returned as if the replacement doesn't exist.
only keep selections invariant under replacement
Keeping selections unchanged if they are inside an exact replacement
is intuitive. However, for diagnostics this is not desirable as
helix would otherwise fail to remove diagnostics if replacing parts
of the document.
The `take_while` should limit the layers to those that can match the
input range so we don't always scan the entire `injection_layers`. We
can limit `depth == 1` layers to those that start before the search
`end`. Deeper layers overlap with shallower layers though so we need
to allow those layers as well in the `take_while`.
For example
```vue
<script setup lang="ts">
const foo = 'bar'.match(/foo/);
const bar = foo;
</script>
```
L2 and L3 are a typescript layer and the `/foo/` part is a small regex
layer. If you used `A-o` before the regex layer you would select the
entire typescript layer. The search in `layer_id_containing_byte_range`
would not consider the typescript layer since the regex layer comes
earlier in `injection_ranges` and that layer's start is after `end`.
The regex layer has a depth of `2` though so the change in this commit
allows scanning through that layer.
Co-authored-by: Pascal Kuthe <pascalkuthe@pm.me>
* feat(languages): update `just` grammar and queries
Bump the
* refactor(syntax): inject shebang by id not name
---------
Co-authored-by: Trevor Gross <tmgross@umich.edu>
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).
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>
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.
When parsing injections, we skip adding a new layer if there is an
existing layer covering the same range. When doing so we did not update
the parent layer ID, so some layers could have `parent` layer IDs that
pointed to a layer that no longer existed in the `layers` HopSlotMap
which could cause a panic when using `A-o`.
To fix this we update the `parent` pointer for both newly created
injection layers and reused ones.
This is useful for resetting multiple changes at once. For example you
might use 'maf' or even '%' to select a larger region and reset all
changes within.
The original behavior of resetting the change on the current line is
retained when the primary selection is 1-width since we look for chunks
in the line range of each selection.
It can be convenient to define project specific debugger templates, some of
which might not necessitate prompting the user to define completion.
This commit makes completion optional for debugger templates and starts the
dap immediately if undefined or empty.