* Add `helix_lsp::client::Client::supports_feature(&self, LanguageServerFeature)`
* Extend `doc.language_servers_with_feature` to use this method as filter as well
* Add macro `language_server_with_feature!` to reduce boilerplate for non-mergeable language server requests (like goto-definition)
* Refactored most of the `find_map` code to use the either the macro or filter directly via `doc.language_servers_with_feature`
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.
When re requesting a completion that already has a selected item we
reuse that selections savepoint. However, the selection has likely
changed since that savepoint which requires us to use the selection
from that savepoint
Add new theme highlight keys, for setting the colour of the breakpoint
character and the current line at which execution has been paused at.
The two new keys are `ui.highlight.frameline` and `ui.debug.breakpoint`.
Highlight according to those keys, both the line at which debugging
is paused at and the breakpoint indicator.
Add an indicator for the current line at which execution is paused
at, themed by the `ui.debug.active` theme scope. Update various themes
to showcase how the new functionality works.
Better icons are dependent on #2869, and as such will be handled in the
future, once it lands.
Closes: #5952
Signed-off-by: Filip Dutescu <filip.dutescu@gmail.com>
The top of a view is marked by a char idx anchor. That char idx is
usually the first character of the visual line it's on. We use a char
index instead of a line index because the view may start in the middle
of a line with soft wrapping. However, it's possible to temporarily
endup in a state where this anchor is not the first character of the
first visual line. This is pretty rare because edits usually happen
inside/after the view. In most cases we handle this case correctly.
However, if the cursor is before the anchor (but still in view)
there can be crashes or visual artifacts. This is caused by the fact
that visual_offset_from_anchor (and the positioning code in view.rs)
incorrectly assumed that the (cursor) position is always after the
view anchor if the cursor is in view. But if the anchor is not the
first character of the first visual line this is not the case anymore.
In that case crashes and visual artifacts are possible. This commit
fixes that problem by changing `visual_offset_from_anchor` (and
callsites) to properly consider that case.
* build(deps): bump bitflags from 1.3.2 to 2.0.2
Bumps [bitflags](https://github.com/bitflags/bitflags) from 1.3.2 to 2.0.2.
- [Release notes](https://github.com/bitflags/bitflags/releases)
- [Changelog](https://github.com/bitflags/bitflags/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bitflags/bitflags/compare/1.3.2...2.0.2)
---
updated-dependencies:
- dependency-name: bitflags
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot] <support@github.com>
* deps: Resolve bitflags 2.0 breaking changes
Bitflags 2.0 release made some breaking changes requiring some small
changes to the Helix codebase.
Almost all of the necessary changes are to manually `#[derive(..)]`
trait implementations which are no longer automatically derived for
all bitflags. All of these were previously automatically derived:
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone, Copy]
I have derived the minimum traits for each bitflag type.
The other change was to the `.bits` field. This is now a `.bits()`
method so the usage of this has been updated in the `Borders` type.
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
* misc: missing inline, outdated link
* doc: Add new theme keys and config option to book
* fix: don't panic in Tree::try_get(view_id)
Necessary for later, where we could be receiving an LSP response
for a closed window, in which case we don't want to crash while
checking for its existence
* fix: reset idle timer on all mouse events
* refacto: Introduce Overlay::new and InlineAnnotation::new
* refacto: extract make_job_callback from Context::callback
* feat: add LSP display_inlay_hint option to config
* feat: communicate inlay hints support capabilities of helix to LSP server
* feat: Add function to request range of inlay hint from LSP
* feat: Save inlay hints in document, per view
* feat: Update inlay hints on document changes
* feat: Compute inlay hints on idle timeout
* nit: Add todo's about inlay hints for later
* fix: compute text annotations for current view in view.rs, not document.rs
* doc: Improve Document::text_annotations() description
* nit: getters don't use 'get_' in front
* fix: Drop inlay hints annotations on config refresh if necessary
* fix: padding theming for LSP inlay hints
* fix: tracking of outdated inlay hints should not be dependant on document revision (because of undos and such)
* fix: follow LSP spec and don't highlight padding as virtual text
* config: add some LSP inlay hint configs
* Generalised to multiple runtime directories with priorities
This is an implementation for #3346.
Previously, one of the following runtime directories were used:
1. `$HELIX_RUNTIME`
2. sibling directory to `$CARGO_MANIFEST_DIR`
3. subdirectory of user config directory
4. subdirectory of path to helix executable
The first directory provided / found to exist in this order was used as a
root for all runtime file searches (grammars, themes, queries).
This change lowers the priority of `$HELIX_RUNTIME` so that the user
config runtime has higher priority. More significantly, all of these
directories are now searched for runtime files, enabling a user to override
default or system-level runtime files. If the same file name appears
in multiple runtime directories, the following priority is now used:
1. sibling directory to `$CARGO_MANIFEST_DIR`
2. subdirectory of user config directory
3. `$HELIX_RUNTIME`
4. subdirectory of path to helix executable
One exception to this rule is that a user can have a `themes`
directory directly in the user config directory that has higher piority
to `themes` directories in runtime directories. That behaviour has been
preserved.
As part of implementing this feature `theme::Loader` was simplified
and the cycle detection logic of the theme inheritance was improved to
cover more cases and to be more explicit.
* Removed AsRef usage to avoid binary growth
* Health displaying ;-separated runtime dirs
* Changed HELIX_RUNTIME build from src instructions
* Updated doc for more detail on runtime directories
* Improved health symlink printing and theme cycle errors
The health display of runtime symlinks now prints both ends of the
link.
Separate errors are given when theme file is not found and when the
only theme file found would form an inheritence cycle.
* Satisfied clippy on passing Path
* Clarified highest priority runtime directory purpose
* Further clarified multiple runtime details in book
Also gave markdown headings to subsections.
Fixed a error with table indentation not building
table that also appears present on master.
---------
Co-authored-by: Paul Scott <paul.scott@anu.edu.au>
Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
Completion requests are computed asynchronously to avoid common micro
freezes while editing. This means that once a completion request
completes, the state of the editor might have changed. Currently,
there is a check to ensure we are still in insert mode. However,
we also need to ensure that the view and document hasn't changed
to avoid accidentally using a savepoint with the wrong view/document.
Furthermore, the editor might request a new completion while the
previous completion request hasn't complemented yet. This can
lead to weird flickering or an outdated completion request replacing
a newer completion that has already completed (the LSP server
is not required to process completion requests in order). This change
also needed to ensure determinism/linear ordering so that completion
popup always correspond to the last completion request.
Fixing autocomplete required moving the document savepoint before the
asynchronous completion request. However, this in turn causes new bugs:
If the completion popup is open, the savepoint is restored when the
popup closes (or another entry is selected). However, at that point
a new completion request might already have been created which
would have replaced the new savepoint (therefore leading to incorrectly
applied complies).
This commit fixes that bug by allowing in arbitrary number of
savepoints to be tracked on the document. The savepoints are reference
counted and therefore remain valid as long as any reference to them
remains. Weak reference are stored on the document and any reference
that can not be upgraded anymore (hence no strong reference remain)
are automatically discarded.
Currently, the selection is not saved/restored when completion
checkpoints are applied. This is usually fine because undoing changes
usually restores maps selections back in insert mode. But this is not
always the case and especially problematic in the presence of
multi-cursor completions (since completions are applied relative to
the selection/cursor) and snippets (which can change the selection)
* use max_line_width + 1 during softwrap to account for newline char
Helix softwrap implementation always wraps lines so that the newline
character doesn't get cut off so he line wraps one chars earlier then
in other editors. This is necessary, because newline chars are always
selecatble in helix and must never be hidden.
However That means that `max_line_width` currently wraps one char
earlier than expected. The typical definition of line width does not
include the newline character and other helix commands like `:reflow`
also don't count the newline character here.
This commit makes softwrap use `max_line_width + 1` instead of
`max_line_width` to correct the impedance missmatch.
* fix typos
Co-authored-by: Jonathan Lebon <jonathan@jlebon.com>
* Add text-width to config.toml
* text-width: update setting documentation
* rename leftover config item
* remove leftover max-line-length occurrences
* Make `text-width` optional in editor config
When it was only used for `:reflow` it made sense to have a default
value set to `80`, but now that soft-wrapping uses this setting, keeping
a default set to `80` would make soft-wrapping behave more aggressively.
* Allow softwrapping to ignore `text-width`
Softwrapping wraps by default to the viewport width or a configured
`text-width` (whichever's smaller). In some cases we only want to set
`text-width` to use for hard-wrapping and let longer lines flow if they
have enough space. This setting allows that.
* Revert "Make `text-width` optional in editor config"
This reverts commit b247d526d6.
* soft-wrap: allow per-language overrides
* Update book/src/configuration.md
Co-authored-by: Pascal Kuthe <pascal.kuthe@semimod.de>
* Update book/src/languages.md
Co-authored-by: Pascal Kuthe <pascal.kuthe@semimod.de>
* Update book/src/configuration.md
Co-authored-by: Pascal Kuthe <pascal.kuthe@semimod.de>
---------
Co-authored-by: Pascal Kuthe <pascal.kuthe@semimod.de>
Co-authored-by: Jonathan Lebon <jonathan@jlebon.com>
Co-authored-by: Alex Boehm <alexb@ozrunways.com>
Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
* Do not add intermediate lines to jumplist with :<linenum> command.
* Revert jumplist index changes.
* Reduce calculations during update cycle.
* Use jumplist for undo, set jumplist before preview.
* remove some debug logging
* Revert "remove some debug logging"
This reverts commit 5772c4327e.
* Revert "Use jumplist for undo, set jumplist before preview."
This reverts commit f73a1b2982.
* Add last_selection, update implementation.
* @pascalkuthe initial feedback
* Ensure ":goto 123" keybinding works as expected.
* fix clippies, prefer expect() for expect last_selection state
* Fix lack of space for popup crash
* Fix saturating -> wrapping
* Fix wrapping -> saturating (I am an idiot)
* Remove useless "mut" in helix-tui/src/buffer.rs
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
* Remove redundant bound-check
* Return bound-check back
* Add bound-check for set_style
* Remove set_style bound-check
* Revert bound-check
---------
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
Fixes a regression introduced in #5420 where a scrolloff of `x - 1`
was used instead if `x` at the bottom of the screen. This was
especially problematic if the scrolloff was set to `0` in that case
the scrolloff behaved as tough set to `-1` and the cursor disappeared
from the view if scrolled to the botoom.
Send a `Disconnect` DAP request if the `Terminated` event is received.
According to the specification, if the debugging session was started by
as `launch`, the debuggee should be terminated alongside the session. If
instead the session was started as `attach`, it should not be disposed of.
This default behaviour can be overriden if the `supportTerminateDebuggee`
capability is supported by the adapter, through the `Disconnect` request
`terminateDebuggee` argument, as described in
[the specification][discon-spec].
This also implies saving the starting command for a debug sessions, in
order to decide which behaviour should be used, as well as validating the
capabilities of the adapter, in order to decide what the disconnect should
do.
An additional change made is handling of the `Exited` event, showing a
message if the exit code is different than `0`, for the user to be aware
off the termination failure.
[discon-spec]: https://microsoft.github.io/debug-adapter-protocol/specification#Requests_DisconnectCloses: #4674
Signed-off-by: Filip Dutescu <filip.dutescu@gmail.com>
`:write` and other file-saving commands now check the file modification
time before writing to protect against overwriting external changes.
Co-authored-by: Gustavo Noronha Silva <gustavo@noronha.dev.br>
Co-authored-by: LeoniePhiline <22329650+LeoniePhiline@users.noreply.github.com>
Co-authored-by: Pascal Kuthe <pascal.kuthe@semimod.de>
* hide duplicate symlinks from the picker
* Apply suggestions from code review
Co-authored-by: g-re-g <123515925+g-re-g@users.noreply.github.com>
* minor stylistic fix
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
---------
Co-authored-by: g-re-g <123515925+g-re-g@users.noreply.github.com>
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
* rework positioning/rendering, enables softwrap/virtual text
This commit is a large rework of the core text positioning and
rendering code in helix to remove the assumption that on-screen
columns/lines correspond to text columns/lines.
A generic `DocFormatter` is introduced that positions graphemes on
and is used both for rendering and for movements/scrolling.
Both virtual text support (inline, grapheme overlay and multi-line)
and a capable softwrap implementation is included.
fix picker highlight
cleanup doc formatter, use word bondaries for wrapping
make visual vertical movement a seperate commnad
estimate line gutter width to improve performance
cache cursor position
cleanup and optimize doc formatter
cleanup documentation
fix typos
Co-authored-by: Daniel Hines <d4hines@gmail.com>
update documentation
fix panic in last_visual_line funciton
improve soft-wrap documentation
add extend_visual_line_up/down commands
fix non-visual vertical movement
streamline virtual text highlighting, add softwrap indicator
fix cursor position if softwrap is disabled
improve documentation of text_annotations module
avoid crashes if view anchor is out of bounds
fix: consider horizontal offset when traslation char_idx -> vpos
improve default configuration
fix: mixed up horizontal and vertical offset
reset view position after config reload
apply suggestions from review
disabled softwrap for very small screens to avoid endless spin
fix wrap_indicator setting
fix bar cursor disappearring on the EOF character
add keybinding for linewise vertical movement
fix: inconsistent gutter highlights
improve virtual text API
make scope idx lookup more ergonomic
allow overlapping overlays
correctly track char_pos for virtual text
adjust configuration
deprecate old position fucntions
fix infinite loop in highlight lookup
fix gutter style
fix formatting
document max-line-width interaction with softwrap
change wrap-indicator example to use empty string
fix: rare panic when view is in invalid state (bis)
* Apply suggestions from code review
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
* improve documentation for positoning functions
* simplify tests
* fix documentation of Grapheme::width
* Apply suggestions from code review
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
* add explicit drop invocation
* Add explicit MoveFn type alias
* add docuntation to Editor::cursor_cache
* fix a few typos
* explain use of allow(deprecated)
* make gj and gk extend in select mode
* remove unneded debug and TODO
* mark tab_width_at #[inline]
* add fast-path to move_vertically_visual in case softwrap is disabled
* rename first_line to first_visual_line
* simplify duplicate if/else
---------
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
The `From<Value>` implementation for `Theme` converted the Value to a
string and re-parsed the string to convert it to
`HashMap<String, Value>` which feels a bit wasteful. This change uses
the underlying `toml::map::Map` directly when the value is a table and
warns about the unexpected `Value` shape otherwise.
This is necessary because toml 0.6.0 changes the Display implementation
for Value::Table so that the `to_string` no longer encodes the value as
a Document, just a Value. So the parse of the Value fails to be decoded
as a HashMap.
The behavior for returning `Default::default` matches the previous
code's behavior except that it did not warn when the input Value was
failed to parse.
`toml::from_slice` has been removed. The CHANGELOG recommends using
`toml::from_str` instead and doing the byte-to-str conversion yourself.
The `toml::toml!` macro has also changed to return the type of the
value declared within the macro body. In the change in
`helix-view/src/theme.rs` this is a `toml::map::Map` (it was a
`toml::Value` previously) allowing us to skip the match and use the
map directly.
Co-authored-by: Pascal Kuthe <pascal.kuthe@semimod.de>
The error messages for a theme that failed to be deserialized (or
otherwise failed to load) were covered up by the context/with_context
calls:
* The log message for a bad theme configured in config.toml would only
say "Failed to deserilaize theme"
* Selecting a bad theme via :theme would show "Theme does not exist"
With these changes, we let the TOML deserializer errors bubble up, so
the error messages can now say the line number of a duplicated
key - and that key's name - when a theme fails to load because of a
duplicated key.
Providing a theme which does not exist to :theme still gives a helpful
error message: "No such file or directory."
* Reset mode when changing buffers
This is similar to the change in
e4c9d4082a139aac3aea4506918171b96e81f5b9: reset the editor to normal
mode when changing buffers. Usually the editor is already in normal
mode but it's possible to setup insert-mode keybindings that change
buffers.
* Move normal mode entering code to Editor
This should be called internally in the Editor when changing documents
(Editor::switch) or changing focuses (Editor::focus).
* Add `View::ensure_cursor_in_view_center` to adjust view after searching and jumping
Also `offset_coodrs_to_in_view` was refactored to reduce duplicated position calculations.
* Fix a wrong offset calculation in `offset_coords_to_in_view_center`
It ignored `scrolloff` if `centering` is false.
* Show (git) diff signs in gutter (#3890)
Avoid string allocation when git diffing
Incrementally diff using changesets
refactor diffs to be provider indepndent and improve git implementation
remove dependency on zlib-ng
switch to asynchronus diffing with similar
Update helix-vcs/Cargo.toml
fix toml formatting
Co-authored-by: Ivan Tham <pickfire@riseup.net>
fix typo in documentation
use ropey reexpors from helix-core
fix crash when creating new file
remove useless use if io::Cursor
fix spelling mistakes
implement suggested improvement to repository loading
improve git test isolation
remove lefover comments
Co-authored-by: univerz <univerz@fu-solution.com>
fixed spelling mistake
minor cosmetic changes
fix: set self.differ to None if decoding the diff_base fails
fixup formatting
Co-authored-by: Ivan Tham <pickfire@riseup.net>
reload diff_base when file is reloaded from disk
switch to imara-diff
Fixup formatting
Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
Redraw buffer whenever a diff is updated.
Only store hunks instead of changes for individual lines to easily allow
jumping between them
Update to latest gitoxide version
Change default diff gutter position
Only update gutter after timeout
* update diff gutter synchronously, with a timeout
* Apply suggestions from code review
Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
* address review comments and ensure lock is always aquired
* remove configuration for redraw timeout
Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
Media keys are sent despite `DISAMBIGUATE_ESCAPE_CODES` being unset.
Previously we panicked on these. This change translates the
disambiguated keys from crossterm so that they do not cause a panic.
Previously we removed selections for a closed view on only the
currently focused document. A view might have selections in other
documents though, so the view needs to be removed from all documents.
* Add a test case for updating jumplists across windows
* Apply transactions to all views on history changes
This ensures that jumplist selections follow changes in documents, even
when there are multiple views (for example a split where both windows
edit the same document).
* Leave TODOs for cleaning up View::apply
* Use Iterator::reduce to compose history transactions
Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
Previously, jumplists could grow unchecked. Every transaction is
applied to jumplist selections to ensure that they are up to date
and within document bounds, so this would cause every edit to become
more expensive as jumplist lengths increased throughout a session.
Setting a maximum number of entries limits the cost.
Vim and Neovim limit their jumplists:
* b298fe6cba/src/structs.h (L141)
* e8cc489acc/src/nvim/mark_defs.h (L57)
Notably, Kakoune does not. In Kakoune, changes are applied to jumplist
entries lazily as you hit `<C-o>`/`<C-i>` though, so Kakoune doesn't
have the same growing cost concerns. Kakoune also does not have a
concept of a View which limits the cost further.
Vim and Neovim limit to 100. This seems unreasonably high to me so I've
set this to 30 to start. We can increase if this is problematically
low.