Test Document
-------------
```
a)b
```
Steps to Reproduce
------------------
1. % # select_all
1. ms( # surround_add
1. mam # select_textobject_around
Debug and Release
-----------------
`thread 'main' panicked at 'Attempt to index past end of RopeSlice:
char index 7, RopeSlice char length 6', ropey-1.6.1/src/slice.rs:796:13`
Description
-----------
An index was selected beyond the end of the slice with chars_at. The fix
adds a guard check to `find_nth_open_pair`, like in the other find_nth*
functions.
1. Create a document containing `{A}`
1. C-w v # vsplit
1. gl # goto_line_end
1. b # move_prev_word_start
1. ` # switch_to_lowercase
1. mrm( # surround replace
1. C-w v # vsplit
In the debug build surround_replace/delete will immedately assert with
`assertion failed: last <= from', transaction.rs:597:13`. The splits and
lowercase conversion are not needed to trigger the bug.
In the release build the surround becomes `)a(` and the last vsplit
causes the transaction to panic.
`internal error: entered unreachable code:
(Some(Retain(18446744073709551573)))', transaction.rs:185:46`
Since the selection direction is backwards get_surround_pos returns the
pairs reversed but the downstream code assumes they are in the forward
direction.
`syn_loader` was replaced rather than interior value being replace,
old value was still being referenced and not updated after `:config-refresh`.
By using `ArcSwap` like for `config`, each `.load()` call will return the most
updated value.
Co-authored-by: kyfan <kyfan@email>
* Added required-root-patterns for situational lsp activation using globbing
* Replaced filter_map with flatten
* updated book to include required-root-patterns option
* fixed wrong function name for path
* Added globset to helix-core. Moved globset building to config parsing.
* Normalize implements AsRef
* cargo fmt
* Revert "cargo fmt"
This reverts commit ca8ce123e8.
* Replace FileType::Suffix with FileType::Glob
Suffix is rather limited and cannot be used to match files which have
semantic meaning based on location + file type (for example, Github
Action workflow files). This patch adds support for a Glob FileType to
replace Suffix, which encompasses the existing behavior & adds
additional file matching functionality.
Globs are standard Unix-style path globs, which are matched against the
absolute path of the file. If the configured glob for a language is a
relative glob (that is, it isn't an absolute path or already starts with
a glob pattern), a glob pattern will be prepended to allow matching
relative paths from any directory.
The order of file type matching is also updated to first match on globs
and then on extension. This is necessary as most cases where
glob-matching is useful will have already been matched by an extension
if glob matching is done last.
* Convert file-types suffixes to globs
* Use globs for filename matching
Trying to match the file-type raw strings against both filename and
extension leads to files with the same name as the extension having the
incorrect syntax.
* Match dockerfiles with suffixes
It's common practice to add a suffix to dockerfiles based on their
context, e.g. `Dockerfile.dev`, `Dockerfile.prod`, etc.
* Make env filetype matching more generic
Match on `.env` or any `.env.*` files.
* Update docs
* Use GlobSet to match all file type globs at once
* Update todo.txt glob patterns
* Consolidate language Configuration and Loader creation
This is a refactor that improves the error handling for creating
the `helix_core::syntax::Loader` from the default and user language
configuration.
* Fix integration tests
* Add additional starlark file-type glob
---------
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
Previously we used the root syntax tree for bracket matching. We can use
the new functionality in `Syntax` for finding the correct syntax tree
for a given byte range though so we use the correct syntax tree within
injections. This improves bracket matching behavior within HTML
injections like script or style tags for example.
helix-stdx is meant to carry extensions to the stdlib or low-level
dependencies that are useful in all other crates. This commit starts
with all of the path functions from helix-core and the CWD tracking that
lived in helix-loader.
The CWD tracking in helix-loader was previously unable to call the
canonicalization functions in helix-core. Switching to our custom
canonicalization code should make no noticeable difference though
since `std::env::current_dir` returns a canonicalized path with
symlinks resolved (at least on unix).
`:tree-sitter-subtree` could previously only print subtrees of nodes
in the root injection layer. We can improve on that by finding the layer
that contains the given byte range and printing the subtree within that
layer. That gives more useful results when a selection is within an
injection layer.
Diagnostics are currently extended if text is inserted at their end. This is
desirable when inserting text after an identifier. For example consider:
let foo = 2;
--- unused variable
Renaming the identifier should extend the diagnostic:
let foobar = 2;
------ unused variable
This is currently implemented in helix but as a consequence adding whitespaces
or a type hint also extends the diagnostic:
let foo = 2;
-------- unused variable
let foo: Bar = 2;
-------- unused variable
In these cases the diagnostic should remain unchanged:
let foo = 2;
--- unused variable
let foo: Bar = 2;
--- unused variable
As a heuristic helix will now only extend diagnostics that end on a word char
if new chars are appended to the word (so not for punctuation/ whitespace).
The idea for this mapping was inspired for the word level tracking vscode uses
for many positions. While VSCode doesn't currently update diagnostics after
receiving publishDiagnostic it does use this system for inlay hints for example.
Similarly, the new association mechanism implemented here can be used for word
level tracking of inlay hints.
A similar mapping function is implemented for word starts. Together
these can be used to make a diagnostic stick to a word. If that word
is removed that diagnostic is automatically removed too. This is the exact
same behavior VSCode inlay hints eixibit.
* rust-toolchain.toml: bump MSRV to 1.70.0
With Firefox 120 released on 21 November 2023, the MSRV is now 1.70.0.
* Fix cargo fmt with Rust 1.70.0
* Fix cargo clippy with Rust 1.70.0
* Fix cargo doc with Rust 1.70.0
* rust-toolchain.toml: add clippy component
* .github: bump dtolnay/rust-toolchain to 1.70
* helix-term: bump rust-version to 1.70
* helix-view/gutter: use checked_ilog10 to count digits
* helix-core/syntax: use MAIN_SEPARATOR_STR constant
* helix-view/handlers/dap: use Display impl for displaying process spawn error
* WIP: helix-term/commands: use checked math to assert ranges cannot overlap
Previously roots needed to be specified by every language and `[]` was
used as an explicit default. Root files don't make sense for every
language (for example TOML) so I think we should allow languages to
not explicitly mention the key and have the `[]` default automatically.
We only reverted so that the latest release would use a stable
tree-sitter version hosted on crates.io. We do want the improvements
on nightly.
This reverts commit 2ebcc4dbeb.
* transition to nucleo for fuzzy matching
* drop flakey test case
since the picker streams in results now any test that relies
on the picker containing results is potentially flakely
* use crates.io version of nucleo
* Fix typo in commands.rs
Co-authored-by: Skyler Hawthorne <skyler@dead10ck.com>
---------
Co-authored-by: Skyler Hawthorne <skyler@dead10ck.com>
YAML indents queries are tweaked to fix auto indent behavior.
A new capture type `indent.always` is introduced to address use cases
where combining indent captures on a single line is desired.
Fixes#6661
This is an unfortunately noisy change: we need to update virtually all
callsites that access the registers. For reads this means passing in the
Editor and for writes this means handling potential failure when we
can't write to a clipboard register.
These come from Kakoune:
* '#' is the selection index register. It's read-only and produces the
selection index numbers, 1-indexed.
* '.' is the selection contents register. It is also read-only and
mirrors the contents of the current selections when read.
We switch the iterators returned from Selection's `fragments` and
`slices` methods to ExactSizeIterators because:
* The selection contents register can simply return the fragments
iterator.
* ExactSizeIterator is already implemented for iterators over Vecs, so
it's essentially free.
* The `len` method can be useful on its own.
Pascal and I discussed this and we think it's generally better to
take a 'RopeSlice' rather than a '&Rope'. The code block rendering
function in the markdown component module is a good example for how
this can be useful: we can remove an allocation of a rope and instead
directly turn a '&str' into a 'RopeSlice' which is very cheap.
A change to prefer 'RopeSlice' to '&Rope' whenever the rope isn't
modified would be nice, but it would be a very large diff (around 500+
500-). Starting off with just the syntax functions seems like a nice
middle-ground, and we can remove a Rope allocation because of it.
Co-authored-by: Pascal Kuthe <pascal.kuthe@semimod.de>
In the past we used two separate queries for combined and normal injections. There was no real reason for this (except historical/slightly easier implementation). Instead, we now use a single query and simply check if an injection corresponds to a combined injection or not.
* correctly map unsorted positions
* Fix typo
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
---------
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
Call as bytes before slicing, that way you can take bytes that aren't
aligned to chars. Should technically also be slightly faster since you
don't have to check alignment...
* Fix next/prev tree-sitter inconsistency
Before there where different results going to next or previous due to
sorting not dealing with multiple captures that start/end at the same
pos. I chose to prefer longer matches.
* Revert unnecessary change
* Add command for merging non-consecutive ranges
* Add `merge_selections` command to book
* Simplify `merge_ranges`
Heeded the advice of @the-mikedavis to stop iterating over all ranges and simply merge the first and the last range, as the invariants of `Selection` guarantee that the list of ranges is always sorted and never empty.
* Clarify doc comment of `merge_ranges`
Language Servers are now configured in a separate table in `languages.toml`:
```toml
[langauge-server.mylang-lsp]
command = "mylang-lsp"
args = ["--stdio"]
config = { provideFormatter = true }
[language-server.efm-lsp-prettier]
command = "efm-langserver"
[language-server.efm-lsp-prettier.config]
documentFormatting = true
languages = { typescript = [ { formatCommand ="prettier --stdin-filepath ${INPUT}", formatStdin = true } ] }
```
The language server for a language is configured like this (`typescript-language-server` is configured by default):
```toml
[[language]]
name = "typescript"
language-servers = [ { name = "efm-lsp-prettier", only-features = [ "format" ] }, "typescript-language-server" ]
```
or equivalent:
```toml
[[language]]
name = "typescript"
language-servers = [ { name = "typescript-language-server", except-features = [ "format" ] }, "efm-lsp-prettier" ]
```
Each requested LSP feature is priorized in the order of the `language-servers` array.
For example the first `goto-definition` supported language server (in this case `typescript-language-server`) will be taken for the relevant LSP request (command `goto_definition`).
If no `except-features` or `only-features` is given all features for the language server are enabled, as long as the language server supports these. If it doesn't the next language server which supports the feature is tried.
The list of supported features are:
- `format`
- `goto-definition`
- `goto-declaration`
- `goto-type-definition`
- `goto-reference`
- `goto-implementation`
- `signature-help`
- `hover`
- `document-highlight`
- `completion`
- `code-action`
- `workspace-command`
- `document-symbols`
- `workspace-symbols`
- `diagnostics`
- `rename-symbol`
- `inlay-hints`
Another side-effect/difference that comes with this PR, is that only one language server instance is started if different languages use the same language server.