This avoids costly conversions via byte_to_char (which are then
reversed back into bytes internally in Ropey).
Reduces time spent in slice/byte_to_char from ~24% to ~5%.
When the picker results output is empty, movement actions result in a panic:
```
thread 'main' panicked at 'attempt to calculate the remainder with a divisor of zero', helix-term/src/ui/picker.rs:420:31
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
```
This could be a no-op instead when the matches length is zero.
Currently match is finding the match based on the anchor rather than the
head (cursor) so this behavior is rather unexpected when user is doing
a match but a different item was matched instead when the selection is
more than one character.
This restores much of the behavior that existed before this PR:
helix will build the grammars when compiling. The difference is that
now fetching is also done during the build phase and is done much
more quickly - both shallow and in parallel.
This is a rather large refactor that moves most of the code for
loading, fetching, and building grammars into a new helix-loader
module. This works well with the [[grammars]] syntax for
languages.toml defined earlier: we only have to depend on the types
for GrammarConfiguration in helix-loader and can leave all the
[[language]] entries for helix-core.
The vision with 'use-grammars' is to allow the long-requested feature
of being able to declare your own set of grammars that you would like.
A simple schema with only/except grammar names controls the list
of grammars that is fetched and built. It does not (yet) control which
grammars may be loaded at runtime if they already exist.
build_grammars adapts the functionality that previously came from
helix-syntax to be used at runtime from the command line flags.
fetch_grammars wraps command-line git to perform the same actions
previously done in the scripts in #1560.
helix-syntax mostly existed for the sake of the build task which
checks and compiles the submodules. Since we won't be relying on
that process anymore, it doesn't end up making much sense to have
a very thin crate just for some functions that we could port to
helix-core.
The remaining build-related code is moved to helix-term which will
be able to provide grammar builds through the --build-grammars CLI
flag.
* Move runtime file location definitions to core
* Add basic --health command
* Add language specific --health
* Show summary for all langs with bare --health
* Use TsFeature from xtask for --health
* cargo fmt
Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
* Add arrow key mappings for tree-sitter parent/child/sibling nav
This helps my use case, where I use a non-qwerty layout with a
programmable mechanical keyboard, and use a layer switching key (think
fn) to send left down up right from the traditional hjkl positions.
* Add new bindings to docs
* Fix bug with auto replacing components in compositor
This was last known to be working with 5995568c at the
time of commit, but now doesn't work with latest rust
stable.
The issue probably stems from using
std::any::type_name() for finding a component in the
compositor, for which the docs explicitly warn against
considering it as a unique identifier for types.
`replace_or_push()` takes a boxed `Component` and
passes it to `find_id()` which compares this with a
bare Component. `type_name()` returns `Box<T>` for
the former and `T` for latter and we have a false
negative. This has been solved by using a generics
instead of trait objects to pass in a `T: Component`
and then use it for comparison.
I'm not exactly sure how this worked fine at the
time of commit of 5995568c; maybe the internal
implementation of `type_name()` changed to properly
indicate indirection with Box.
* Do not compare by type name in compositor find_id
* add basic completion replay
* use transaction as the last completion
* completion replay only on trigger position
* cache changes in CompletionAction
Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
* Implement buffer-close-all
* Implement buffer-close-others
* Refactor all buffer close variants to use shared logic
* Fix clippy lint
* Docgen for new commands
* Shorten error message for attempting to close buffers that don't exist
* Refactor shared buffer methods to pass only editor, not whole compositor
* Switch signature of bulk buffer closing to use slice of DocumentIds
Addresses feedback that accepting an IntoIterator implementor is too
much for an internal. Also possibly saves some moving?
* Show infobox to hint textobjects with `mi` and `ma`
* Add note to infobox than any pair of characters will work too
The wording could probably be a little more clear, but I wanted to
keep it short but still accurate.
* Don't allocate a vec for the static help text
* Fix bug where `mi<esc>` would swallow next input and persist infobox
* Better help text for arbitrary pair matching in textobject selection
* Add way to add fake pending key data below status, use with `mi`/`ma`
This is a bit hacky as it makes use of global state which will end
up managed in multiple places, but has precedent in the way autoinfo
works. There should probably be a bigger refactor to handle this
kind of state better.
* Return early on anything other than `mi` and `ma` for autoinfo
* Remove "ascii" from help text with `mi` and `ma`
* Update helix-term/src/ui/editor.rs
Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
* Refactor file picker filetype filter logic to remove panic, make clearer
An unwrap was unneccesarily present due to a prior contribution of mine
which was before I had any understanding of error handling in Rust. I've
also swapped a match for an if let, as was originally suggested in the
original pull request adding filetype filtering, but was merged before I
could address.
* Add some comments to the file picker code for clarity
* Switch to expect instead of ignoring type def error
* ignore Enter keypress when menu has no selection
supersedes #1622
Builds on the work in #1285. I want to allow Enter to create a newline
when there is no selection in the autocomplete menu.
This occurs somewhat often when using LSP autocomplete in Elixir which
uses `do/end` blocks (and I set the autocomplete menu delay to 0 which
exacerbates the problem):
```elixir
defmodule MyModule do
def do_foo(x) do
x
end
def other_function(y) do|
end
```
Here the cursor is `|` in insert mode. The LSP suggests `do_foo` but I
want to create a newline. Hitting Enter currently closes the menu,
so I end up having to hit Enter twice when the module contains any
local with a `do` prefix, which can be inconsistent. With this change,
we ignore the Enter keypress to end up creating the newline in this case.
* pop compositor layer when ignoring Enter keypress
* move closing function out of consumed event result closure
* explicitly label close_fn as an 'Option<Callback>'
* impl auto pairs config
Implements configuration for which pairs of tokens get auto completed.
In order to help with this, the logic for when *not* to auto complete
has been generalized from a specific hardcoded list of characters to
simply testing if the next/prev char is alphanumeric.
It is possible to configure a global list of pairs as well as at the
language level. The language config will take precedence over the
global config.
* rename AutoPair -> Pair
* clean up insert_char command
* remove Rc
* remove some explicit cloning with another impl
* fix lint
* review comments
* global auto-pairs = false takes precedence over language settings
* make clippy happy
* print out editor config on startup
* move auto pairs accessor into Document
* rearrange auto pair doc comment
* use pattern in Froms
* Add Event::Used to use event callback without consuming
* Close popup if contents ignored event
* collect event results before executing callbacks
* don't add new result variant, use Ignored(..) instead
* break in match cases
* Make auto_close configurable
* fix merge
* auto close hover popups
* fix formatting
Some users (including myself) want to turn off filtering of files
prefixed with `.`, as they are often useful to edit. For example, `.env`
files, configuration for linters `.eslint.json` and the like.
The unwrap (or '.ok()' rather) triggers for some errors but not
negative status codes. In the case where helix is being packaged
in an empty git repository, the existing mechanism will fail because
git init
git rev-parse HEAD
gives a negative exit code and prints to stderr
stderr: "fatal: ambiguous argument 'HEAD': unknown revision or path not in the working tree....
with a stdout of "HEAD\n" (too short to slice with [..8]).
* feat(commands): command palette
Add new command to display command pallete that can be used
to discover and execute available commands.
Fixes: https://github.com/helix-editor/helix/issues/559
* Make picker take the whole context, not just editor
* Bind command pallete
* Typable commands also in the palette
* Show key bindings for commands
* Fix tests, small refactor
* Refactor keymap mapping, fix typo
* Ignore sequence key bindings for now
* Apply suggestions
* Fix lint issues in tests
* Fix after rebase
Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
In order to implement this completer, the completion function needs to
be able to access the compositor's context (to allow it to get the
list of buffers currently open in the context's editor).
If building from source and the source is contained in a larger
repository, we'd contain the wrong version. It's also easy to
accidentally have a newer tag that would change the version.
This code:
let start = ensure_grapheme_boundary_next(text, text.byte_to_char(start));
let end = ensure_grapheme_boundary_next(text, text.byte_to_char(end));
Would convert byte to char index, but then internally immediately convert back
to byte index, operate on it, then convert it to char index.
This change reduces the amount of time spent in ensure_grapheme_boundary from
29% to 2%.
* add select_next_sibling and select_prev_sibling commands
* refactor objects to use higher order functions
* address clippy feedback
* move selection cloning into commands
* add default keybindings under left/right brackets
* use [+t,]+t for selecting sibling syntax nodes
* setup Alt-{j,k,h,l} default keymaps for syntax selection commands
* reduce boilerplate of select_next/prev_sibling in commands
* import tree-sitter Node type in commands
* add show_subtree command for viewing tree-sitter subtree in Popup
* remove '.slice(..)' from show_subtree command
* name docs and subtree Popups 'hover'
* feat(commands): shrink_selection
Add `shrink_selection` command that can be used to shrink
previously expanded selection.
To make `shrink_selection` work it was necessary to add
selection history to the Document since we want to shrink
the selection towards the syntax tree node that was initially
selected.
Selection history is cleared any time the user changes
selection other way than by `expand_selection`. This ensures
that we don't get some funky edge cases when user calls
`shrink_selection`.
Related: https://github.com/helix-editor/helix/discussions/1328
* Refactor shrink_selection, move history to view
* Remove useless comment
* Add default key mapping for extend&shrink selection
* Rework contains_selection method
* Shrink selection without expand selects first child
* feat(commands): ensure_selections_forward
Add command that ensures that selections are in forward direction.
Fixes: https://github.com/helix-editor/helix/issues/1332
* Add keybinding for ensure_selections_forward
Add `A-:` keybinding for the ensure_selections_forward command.
* Re-use range.flip for flip_selections command
* feat: Update settings at runtime
fix the clippy warning
* update the documentation
* use to_value instead of to_vec+from_value
* drop the equal
* remove an useless comment
* apply suggestion
* feat(ui): file encoding in statusline
Display file encoding in statusline if the encoding
isn't UTF-8.
* Re-export encoding_rs from core
From there it can be imported by other mods
that rely on it.
* feat(lsp): configurable diagnostic severity
Allow severity of diagnostic messages to be configured.
E.g. allow turning of Hint level diagnostics.
Fixes: https://github.com/helix-editor/helix/issues/1007
* Use language_config() method
* Add documentation for diagnostic_severity
* Use unreachable for unknown severity level
* fix: documentation for diagnostic_severity config
* tmp add code for dedent
* finish normal_mode with dedent behavior
* use function pointer
* rebase from origin
* check dedent condition inside normal_mode implementation
* using if let...
* fix check
* using char_is_whitespace instead of ch.is_whitespace
* fix clippy
* abstract restore_indent function
* Add auto pairs for same-char pairs
* Add unit tests for all existing functionality
* Add auto pairs for same-char pairs (quotes, etc). Account for
apostrophe in prose by requiring both sides of the cursor to be
non-pair chars or whitespace. This also incidentally will work for
avoiding a double single quote in lifetime annotations, at least until
<> is added
* Slight factor of moving the cursor transform of the selection to
inside the hooks. This will enable doing auto pairing with selections,
and fixing the bug where auto pairs destroy the selection.
Fixes#1014
* Move `runtime/themes/base16_default_terminal.toml` to
`base16_theme.toml` alongside `theme.toml`
* Use `terminfo` crate to detect whether the terminal supports true
color and, if the user has no theme configured and their terminal does
not support true color, load the alt default theme instead of the
normal default.
Remove `terminfo` dependency, use `COLORTERM` env instead
Prevent user from switching to an unsupported theme
Add `true-color-override` option
If the terminal is wrongly detected to not support true color,
`true-color-override = true` will override the detection.
Rename `true-color-override` to `true-color`
* Macros WIP
`helix_term::compositor::Callback` changed to take a `&mut Context` as
a parameter for use by `play_macro`
* Default to `@` register for macros
* Import `KeyEvent`
* Special-case shift-tab -> backtab in `KeyEvent` conversion
* Move key recording to the compositor
* Add comment
* Add persistent display of macro recording status
When macro recording is active, the pending keys display will be shifted
3 characters left, and the register being recorded to will be displayed
between brackets — e.g., `[@]` — right of the pending keys display.
* Fix/add documentation
Following the addition of `xtask`, `cargo run` has multiple possible
targets, necessitating the usage of `cargo run --bin hx` to run Helix
during development. This allows `cargo run` to be used to run `hx`.