* Split helix_core::find_root and helix_loader::find_local_config_dirs
The documentation of find_root described the following priority for
detecting a project root:
- Top-most folder containing a root marker in current git repository
- Git repository root if no marker detected
- Top-most folder containing a root marker if not git repository detected
- Current working directory as fallback
The commit contained in https://github.com/helix-editor/helix/pull/1249
extracted and changed the implementation of find_root in find_root_impl,
actually reversing its result order (since that is the order that made
sense for the local configuration merge, from innermost to outermost
ancestors).
Since the two uses of find_root_impl have different requirements (and
it's not a matter of reversing the order of results since, e.g., the top
repository dir should be used by find_root only if there's not marker in
other dirs), this PR splits the two implementations in two different
specialized functions.
In doing so, find_root_impl is removed and the implementation is moved
back in find_root, moving it closer to the documented behaviour thus
making it easier to verify it's actually correct
* helix-core: remove Option from find_root return type
It always returns some result, so Option is not needed
* Improve keymap errors from command typos
Currently, opening helix with a config containing a bad command mapping
fails with a cryptic error. For example, say we have a config (bad.toml)
with a command name that doesn't exist:
[keys.normal]
b = "buffer_close" # should be ":buffer-close"
When we `hx -c bad.toml`, we get...
> Bad config: data did not match any variant of untagged enum KeyTrie for key `keys.normal` at line 1 column 1
> Press <ENTER> to continue with default config
This is because of the way that Serde tries to deserialize untagged
enums such as `helix_term::keymap::KeyTrie`. From the Serde docs[^1]:
> Serde will try to match the data against each variant in order and the
> first one that deserializes successfully is the one returned.
`MappableCommand::deserialize` fails (returns an Err variant) when a
command does not exist. Serde interprets this as the `KeyTrie::Leaf`
variant failing to match and declares that the input data doesn't
"match any variant of untagged enum KeyTrie."
Luckily the variants of KeyTrie are orthogonal in structure: we can tell
them apart by the type hints from a `serde:🇩🇪:Visitor`. This change
uses a custom Deserialize implementation along with a Visitor that
discerns which variant of the KeyTrie applies. With this change, the
above failure becomes:
> Bad config: No command named 'buffer_close' for key `keys.normal.b` at line 2 column 5
> Press <ENTER> to continue with default config
We also provide more explicit information about the expectations on
the field. A config with an unexpected type produces a message with
that information and the expectation:
[keys.normal]
b = 1
> Bad config: invalid type: integer `1`, expected a command, list of commands, or sub-keymap for key `keys.normal.b` at line 2 column 5
> Press <ENTER> to continue with default config
[^1]: https://serde.rs/enum-representations.html#untagged
* Update helix-term/src/keymap.rs
Co-authored-by: Ivan Tham <pickfire@riseup.net>
Co-authored-by: Ivan Tham <pickfire@riseup.net>
* Add command line parameter to specify log file
I had the logs of my debug helix mixed in with the logs from the
production helix.
Add a `--log` command line argument to redirect any logs to other
files, making my debugging easier :-)
* Update completion files with `--log` argument
The tutor file is loaded as .txt which can potentially spawn a
language server. Then the path is unset, but the LS remains active.
This can cause panics since updates are now submitted for a doc
with no path.
As a quick workaround we remove the extension which should avoid
detection.
Fixes#3730
* Don't change config to default when refreshing invalid config
* Propely handle theme errors with config-reload
* Extract refresh theme into seperate function
Helix is first and foremost a modal editor. Willingness to support non-modal
editing is there, but it is not one that should be encouraged with the default
settings. There are an increasing number of users who are stumbling because
they are trying to use Helix as a non-modal editor, so this is an effort to
encourage new users to stop and take notice that Helix has a different paradigm
than VSCode, Sublime, etc. Users can still add these bindings back to their own
configs if they wish.
`extend_line_above` (and `extend_line` when facing backwards) skip
a line when the current range does not fully cover a line.
Before this change:
foo
b#[|a]#r
baz
With `extend_line_above` or `extend_line` selected the line above.
#[|foo
bar]#
baz
Which is inconsistent with `extend_line_below`. This commit changes
the behavior to select the current line when it is not already
selected.
foo
#[|bar]#
baz
Then further calls of `extend_line_above` extend the selection up
line-wise.
* 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>
It was starting to diverge as the normal exit code was restoring the prompt but the panic code
wasn't, and the panic code was disabling bracketed paste but the normal code wasn't.
This changes the panic path slightly in that we won't disable raw mode if exiting alternate screen
and disabling bracketed paste fails. If that happens, things are so busted I don't think it matters
anyway.
Fixes a panic with a config like:
[keys.normal.space]
x = [":buffer-close"]
by bailing out of the command-execution handling if the document
doesn't exist after handling a command.
This refactor changes the overall structure of the goto_ts_object_impl
command without removing any functionality from its behavior. The
refactored motion:
* acts on all selections instead of reducing to one selection
* may be repeated with the `repeat_last_motion` (A-.) command
* informs the user when the syntax-tree is not accessible in the current buffer
This is invalid according to the [LSP spec]:
> In addition the server is not allowed to send any requests
> or notifications to the client until it has responded with an
> InitializeResult, with the exception that during the initialize
> request the server is allowed to send the notifications
> window/showMessage, window/logMessage and telemetry/event as well
> as the window/showMessageRequest request to the client.
So we should discard the message when the language server is not
yet initialized. This can happen if the server sends
textDocument/publishDiagnostics before responding to the initialize
request. clojure-lsp appears to exhibit this behavior in the wild.
[LSP Spec]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#initialize
This change adds documents to the view's document history Vec.
(This is used by `ga` for example to access the last buffer.)
Previously, a sequence like so would have confusing behavior:
1. Open file A: any document with an active language server
2. Find some definition that lives in another file - file B - with `gd`
3. Jump back in the jumplist with `C-o` to file A
4. Use `ga` intending to switch back to file B
The behavior prior to this change was that `ga` would switch to file
A: you could not use `ga` to switch to file B.
When changing focus, the lookup with `current!` may change the
view and end up executing mode transition hooks on the newly
focused view. We should use the same view and document to execute
mode transition hooks so that switching away from a view triggers
history save points.
* Derive Document language name from `languages.toml` `name` key
This changes switches from deriving the language name from the
`languages.toml` `scope` key to `name` (`language_id` in the
`LanguageConfiguration` type). For the most part it works to derive the
language name from scope by chopping off `source.` or `rsplit_once` on
`.` but for some languages we have now like html (`text.html.basic`),
it doesn't. This also should be a more accurate fallback for the
`language_id` method which is used in LSP and currently uses the
`rsplit_once` strategy.
Here we expose the language's name as `language_name` on `Document` and
replace ad-hoc calculations of the language name with the new method.
This is most impactful for the `file-type` statusline element which is
using `language_id`.
* Use `Document::language_name` for the `file-type` statusline element
The `file-type` indicator element in the statusline was using
`Document::language_id` which is meant to be used to for telling
Language Servers what language we're using. That works for languages
with `language-server` configurations in `languages.toml` but shows
text otherwise. The new `Document::language_name` method from the
parent commit is a more accurate way to determine the language.
* let extend-line respect range direction
* fix extend above logic
* keep `x` existing binding
* Update book/src/keymap.md
Co-authored-by: Ivan Tham <pickfire@riseup.net>
Co-authored-by: Ivan Tham <pickfire@riseup.net>
* Update description of `m` textobject to its actual functionality
Sometime recently the functionality of `m` was changed to match the
nearest pair to the cursor, rather than the former functionality of
matching the pair only if the cursor was on one of the brace characters
directly.
* Rename surround methods to reflect that they work on pairs
The current naming suggests that they may work generally on any
textobject, whereas their implementation really focuses on pairs.
* Change description of m textobject to match actual functionality
The current implementation of `m` no longer merely looks at the pair
character the cursor is on, but actually will search for the pair
(defined in helix-core/src/surround.rs) that encloses the cursor, and
not the entire selection.
* Accept suggested wording change
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
* Prefix pair surround for consistency
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
Ported over from 61365dfbf3 in the `gui` branch. This will allow
adding our own events, most notably an idle timer event (useful
for adding debounced input in [dynamic pickers][1] used by interactive
global search and workspace symbols).
[1]: https://github.com/helix-editor/helix/pull/3110
Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
These are read-line-like bindings which we'd like to minimize in
insert mode in general.
In particular these two are troublesome if you have a low
`editor.idle-timeout` config and are using LSP completions: the
behavior of C-n/C-p switches from moving down/up lines to moving
down/up the completion menu, so if you hit C-n too quickly
expecting to be in the completion menu, you'll end up moving down
a line instead. Using C-p moves you back up the line but doesn't
re-trigger the completion menu. This kind of timing related change
to behavior isn't realistically that big of a deal but it can be
annoying.
* Fix tab highlight when tab is partially visible
* Make it style based, and not truncation based
Dealing with truncating is a mess, especially when it comes to wide
unicode graphemes. This way it should work no matter what.
* Inline style calculation into branches
* Fix incorrect indent guide styling
Before the indent guides on top of whitespace inherited the theme
from them. Now they do not.
* Fix dark_plus theme indent_guides
* Use whitespace style as fallback for indent-guide
* Fix dark_plus theme indent_guides
* Move indent_guide style patching out of loop
* Avoid setting stdin handle when not necessary
Avoid setting the stdin handle in `shell_impl` when the input argument
is None.
This permits to run commands with no stdin with :sh
* refactoring to avoid code duplication
* making clippy happy
* Process variable name fix
Indent style may change when choosing a language with `:set-language`.
Line-endings most likely will not change, but `:set-language` should
have a similar effect as reloading a file (`:reload`), plus the two
are currently grouped in the implementation and line-ending detection
is not particularly expensive.
* Change default formatter for any language
* Fix clippy error
* Close stdin for Stdio formatters
* Better indentation and pattern matching
* Return Result<Option<...>> for fn format instead of Option
* Remove unwrap for stdin
* Handle FormatterErrors instead of Result<Option<...>>
* Use Transaction instead of LspFormatting
* Use Transaction directly in Document::format
* Perform stdin type formatting asynchronously
* Rename formatter.type values to kebab-case
* Debug format for displaying io::ErrorKind (msrv fix)
* Solve conflict?
* Use only stdio type formatters
* Remove FormatterType enum
* Remove old comment
* Check if the formatter exited correctly
* Add formatter configuration to the book
* Avoid allocations when writing to stdin and formatting errors
* Remove unused import
Co-authored-by: Gokul Soumya <gokulps15@gmail.com>
The language server sends a char offset range within the
signature help label text to highlight as the current parameter,
but helix uses byte offset ranges for rendering highlights. This
was brought up in the [review of the original signature help PR][1],
but the ranges were being highlighted correctly, and there were no
out of bound or indexing panics. Turns out rust-analyzer was
[incorrectly sending byte offsets] instead of char offsets and this
made it seem like all was well and good with offsets in helix during
initial testing.
[1]: https://github.com/helix-editor/helix/pull/1755#discussion_r906715371
[2]: https://github.com/rust-lang/rust-analyzer/pull/12272
* auto pair-removal
Fixes https://github.com/helix-editor/helix/issues/1673
* autopairs removal: use doc autopairs
* autopairs-removal: limit to one-char selections
* use single_grapheme() to check if range is one char
* fix errouneous deletes of " and other symmetric autopairs when at buffer start
Co-authored-by: Houkime <>
* add statusline element to display file line endings
* run cargo fmt --all
* change the word *ending* from plural to singular
* support for the unicode-lines feature flag
* Add lsp signature help
* Do not move signature help popup on multiple triggers
* Highlight current parameter in signature help
* Auto close signature help
* Position signature help above to not block completion
* Update signature help on backspace/insert mode delete
* Add lsp.auto-signature-help config option
* Add serde default annotation for LspConfig
* Show LSP inactive message only if signature help is invoked manually
* Do not assume valid signature help response from LSP
Malformed LSP responses are common, and these should not crash the
editor.
* Check signature help capability before sending request
* Reuse Open enum for PositionBias in popup
* Close signature popup and exit insert mode on escape
* Add config to control signature help docs display
* Use new Margin api in signature help
* Invoke signature help on changing to insert mode
* feat(statusline): add the file type (language id) to the status line
* refactor(statusline): move the statusline implementation into an own struct
* refactor(statusline): split the statusline implementation into different functions
* refactor(statusline): Append elements using a consistent API
This is a preparation for the configurability which is about to be
implemented.
* refactor(statusline): implement render_diagnostics()
This avoid cluttering the render() function and will simplify
configurability.
* feat(statusline): make the status line configurable
* refactor(statusline): make clippy happy
* refactor(statusline): avoid intermediate StatusLineObject
Use a more functional approach to obtain render functions and write to
the buffers, and avoid an intermediate StatusLineElement object.
* fix(statusline): avoid rendering the left elements twice
* refactor(statusline): make clippy happy again
* refactor(statusline): rename `buffer` into `parts`
* refactor(statusline): ensure the match is exhaustive
* fix(statusline): avoid an overflow when calculating the maximal center width
* chore(statusline): Describe the statusline configurability in the book
* chore(statusline): Correct and add documentation
* refactor(statusline): refactor some code following the code review
Avoid very small helper functions for the diagnositcs and inline them
instead.
Rename the config field `status_line` to `statusline` to remain
consistent with `bufferline`.
* chore(statusline): adjust documentation following the config field refactoring
* revert(statusline): revert regression introduced by c0a1870
* chore(statusline): slight adjustment in the configuration documentation
* feat(statusline): integrate changes from #2676 after rebasing
* refactor(statusline): remove the StatusLine struct
Because none of the functions need `Self` and all of them are in an own
file, there is no explicit need for the struct.
* fix(statusline): restore the configurability of color modes
The configuration was ignored after reintegrating the changes of #2676
in 8d28f95.
* fix(statusline): remove the spinner padding
* refactor(statusline): remove unnecessary format!()