This commit addresses an issue where Helix could open duplicate tabs for
the same file if that file was accessed via a symlinked path and an LSP
server (e.g., pyright) returned a fully resolved (canonical) path for
"go to definition" or similar actions. This was particularly problematic
when the entire workspace root was under a symlink.
I've implemented the following changes:
1. **Canonicalize LSP Client Root URIs (`helix-lsp`):**
- I modified `helix-lsp/src/lib.rs` (specifically `find_lsp_workspace`
and `start_client`) and `helix-lsp/src/client.rs`
(`Client::try_add_doc`) to ensure that the LSP client's
`root_path`, `root_uri`, and `workspace_folders` are stored in
their fully canonicalized (symlink-resolved) forms. This ensures
the LSP client operates with a canonical understanding of its
workspace root(s).
2. **Canonicalize Incoming LSP URIs (`helix-core`):**
- I modified `helix-core/src/uri.rs` in the `convert_url_to_uri`
function. When a `url::Url` with a `file://` scheme is converted
to a `Uri::File`, the path is now processed using
`helix_stdx::path::canonicalize` instead of
`helix_stdx::path::normalize`. This ensures URIs from LSP messages
are also in canonical form.
3. **Verified Document Path Storage (`helix-view`):**
- I confirmed that `Document::set_path` (in `helix-view/src/document.rs`)
already uses `helix_stdx::path::canonicalize`. This means
`Document` objects store their paths canonically.
4. **Verified URI Comparisons (`helix-view`):**
- I confirmed that lookups like `Editor::document_by_path` (in
`helix-view/src/editor.rs`) correctly compare canonical paths,
which, due to the above changes, should ensure consistent matching.
These changes collectively ensure that paths/URIs from different sources
(your input, LSP client configuration, LSP messages) are all resolved to
their canonical forms before comparison or use in lookups, preventing
the erroneous opening of duplicate buffers for symlinked files.
I wrote an integration test (`lsp_goto_definition_symlinked_workspace` in
`helix-term/tests/symlink_lsp_workspace_test.rs`) to
specifically cover the symlinked workspace root scenario. However,
persistent compilation timeouts in the testing environment prevented
this test from being run and validated.
* 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
* fix(picker): `alt-ret' changes cursor pos of current file, not new one
Closes#7673
* fix other pickers
* symbol pickers
* diagnostick pickers
This is done using the already patched `jump_to_location` method.
* fix global and jumplist pickers
* use `view` as old_id; make `align_view` method of `Action`
* test(picker): basic <alt-ret> functionality
* fix: picker integrational test
* fix nit
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
---------
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
When force quitting, we need to block on the pending writes to ensure
that write commands succeed before exiting, and also to avoid a crash
when all the views are gone before the auto format call returns from
the LS.
* fix: Recalculate completion when going through prompt history
* Update completion when the prompt line is changed
It should not be possible to update the line without also updating the
completion since the completion holds an index into the line.
* Fix Prompt::with_line recalculate completion
with_line was the last function where recalculate completion had to be
done manually. This function now also recalculates the completion so
that it's impossible to forget.
* Exit selection when recalculating completion
Keeping the selection index when the completion has been recalculated
doesn't make sense. This clears the selection automatically, removing
most needs to manually clear it.
* Remove &mut on save_filter
Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
When a new View of a Document is created, a default cursor of 0, 0 is
created, and it does not get normalized to a single width cursor until
at least one movement of the cursor happens. This appears to have no
practical negative effect that I could find, but it makes tests difficult
to work with, since the initial selection is not what you expect it to be.
This changes the initial selection of a new View to be the width of the
first grapheme in the text.
* Use new macro syntax for encoding sequences of keys
* Make convenience helpers for common test pattern
* Use indoc for inline indented raw strings
* Add feature flag for integration testing to disable rendering