Compare commits

...

1693 Commits

Author SHA1 Message Date
Michael Davis
61491af15e Remove unused Result wrapper for Path->Url conversion 2024-12-20 13:33:47 -05:00
Michael Davis
a36806e326 Handle conversion to/from new LSP URL type 2024-12-20 13:33:46 -05:00
Michael Davis
b84c9a893c Replace url::Url with a String wrapper 2024-12-20 13:33:46 -05:00
Michael Davis
652e316925 LSP: Use PathBufs for workspace folders
Internally the LSP client should hold workspace folders as paths. Using
URLs for this type is inconvenient (since we compare it to paths) and
might cause mismatches because of URLs not being normalized. The URLs
must be paths anyways so we can convert these types lazily when we need
to send them to a server.
2024-12-20 13:33:46 -05:00
Nikita Revenco
ba6e6dc3dd Colors for items in the completion menu (#12299) 2024-12-20 10:16:15 -06:00
cornishon
a91263d604 Odin textobjects (#12302)
Co-authored-by: Adam Zadrożny <zadroznyadam@protonmail.com>
2024-12-20 09:59:28 -06:00
Ian Hobson
06d0f33c94 Add Koto language support (#12307) 2024-12-20 09:56:13 -06:00
Eduardo Rittner Coelho
eaff0c3cd6 Document diagnostic severity levels (#12306) 2024-12-20 09:47:06 -06:00
uncenter
1e9412269a Sync Catppuccin theme changes (#12304) 2024-12-20 09:43:45 -06:00
Nikita Revenco
355e381626 feat: use ui.text.directory for path completion item if its a folder (#12295) 2024-12-19 14:36:54 -06:00
Tobias Hunger
cbc06d1f15 chore: Update slint tree-sitter grammar to version 1.9 (#12297) 2024-12-19 10:16:12 -06:00
Eduardo Rittner Coelho
9e4da4b950 Show parser availability in --health [LANG] (#12228) 2024-12-18 11:21:58 -06:00
Christian Schneider
13e5a2ee5a Outdent array literals for php [] (#12286)
Co-authored-by: Christian Schneider <schneider@search.ch>
2024-12-18 08:52:20 -06:00
David Else
0134bb7063 Update dark_plus theme for inactive text and improve jump label (#12289) 2024-12-18 08:32:41 -06:00
Peter Ingram
ec65cc4913 Adds colored directories to everforest themes (#12287)
Co-authored-by: Peter Ingram <p.ingram@mrx.technology>
2024-12-18 08:31:40 -06:00
Nikita Revenco
91a5d407da Allow theming directory prompt completions (#12205) 2024-12-17 21:13:42 -06:00
Michael Davis
6eb186eb7b helix-lsp-types: use bitflags::bitflags rather than extern crate
This seems to be a historical artifact in `lsp_types` - we can use a
regular `use` statement to pull in the `bitflags!` macro rather than
an external crate definition. This fixes rust-analyzer's ability to find
the macro at least on rust-analyzer 2024-02-26.
2024-12-17 15:42:36 -05:00
Michael Davis
1980bd5992 helix-lsp-types: Prefer crate::Url to url::Url
This is a cosmetic change to replace all direct `use`s of the `url::Url`
type in the `helix-lsp-types` crate with `use crate::Url;`. The types
are the same type currently: this refactor will make a future
replacement of the Url type less noisy.

Connects https://github.com/helix-editor/helix/pull/11889
2024-12-17 15:42:28 -05:00
Tim Sampson
cc3b77b584 dockerfile: bump tree-sitter grammar to gain support for heredocs (#12230) 2024-12-17 13:26:49 -06:00
Christian Schneider
fcded6ce1e Trim trailing colons from paths to allow copy/pasting git grep -n output (#9963)
Co-authored-by: Christian Schneider <schneider@search.ch>
2024-12-17 13:02:06 -06:00
Pascal Kuthe
1badd9e434 implement snippet tabstop support 2024-12-17 13:34:40 -05:00
Pascal Kuthe
66fb1e67c0 add fallback onNextKey
adds a variant of on_next_key callbacks that are only called when no other
mapping matches a key
2024-12-17 13:34:40 -05:00
Pascal Kuthe
609c29bf7e add DocumentFocusLost event 2024-12-17 13:34:40 -05:00
Pascal Kuthe
5537e68b5e add changes and ghost_transaction to DocumentDidChange events 2024-12-17 13:34:40 -05:00
Pascal Kuthe
c8c0d04168 add snippet system to helix core 2024-12-17 13:34:39 -05:00
Pascal Kuthe
db959274d4 Add range type to helix stdx 2024-12-17 13:34:39 -05:00
dependabot[bot]
312c64f0c2 build(deps): bump the rust-dependencies group with 10 updates (#12277)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-16 18:48:13 -06:00
André Sá
67535804a5 Fix build from source with Spade tree-sitter grammar (#12276) 2024-12-16 14:44:28 -06:00
Michael Davis
bae6a58c3c Add block-comment-tokens configuration for Java
Ref https://github.com/helix-editor/helix/pull/12266#issuecomment-2546370787
2024-12-16 14:02:35 -05:00
Integral
250d9fa8fe Avoid allocating the --help message (#12243) 2024-12-16 11:16:48 -06:00
Aaalibaba
3b36cf1a15 Expand tildes in :read command (#12271) 2024-12-16 11:10:35 -06:00
Nikita Revenco
99fdbce566 docs: remove mention that - requires special handling (#12250) 2024-12-16 10:01:14 -06:00
David Else
9b14750e56 Add ltex-ls-plus language server (#12251) 2024-12-16 09:37:49 -06:00
TornaxO7
4e5b0644a2 language: add comment token for java files (#12266) 2024-12-16 09:24:04 -06:00
Takumi Matsuura
e14c346ee7 Fix panic in kill_to_end_of_line when handling multibyte characters (#12237) 2024-12-13 14:04:52 -06:00
RoloEdits
617f538d41 feat(highlights): add COMPLIANCE to error (#12244) 2024-12-13 13:26:08 -06:00
Yuki Kobayashi
ce133a2889 languages(v): use vlang/v-analyzer instead of v-analyzer/v-analyzer (#12236)
* use vlang/v-analyzer instead of v-analyzer/v-analyzer

* revert rev, because CI failed (couldn't repro working query-check locally, so not sure if this will work)
2024-12-13 12:09:24 +09:00
TornaxO7
89a7cde2f0 Fix continuing comment token for first line (#12215) 2024-12-10 13:24:34 -06:00
TornaxO7
51ac3e05e0 doc: fix default value in doc for continue-comments (#12235) 2024-12-10 13:19:31 -06:00
TornaxO7
5005c14e99 Add config option for continue commenting (#12213)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-12-09 17:31:41 -06:00
Michael Davis
2f74530328 helix-lsp-types: Remove Cargo.lock
This lockfile is unused since this crate was added to the workspace and
can be removed.

Closes #12227
2024-12-09 17:14:38 -05:00
Tshepang Mbambo
a1a5faebef typo (#12224) 2024-12-09 12:23:30 -06:00
Nikita Revenco
db1d84256f fix: report correct amount of files opened and improved error message when Helix can't parse directory as file (#12199)
* feat: improve information on the amount of files loaded

* refactor: naming consitency Doc and not Buf

* fix: correct name of method

* chore: appease clippy

* feat: more human error information when Helix cannot start

* refatcor: use if guard on match arm
2024-12-08 20:14:29 +09:00
Michael Davis
271c32f2e6 Support bindings with the Super (Cmd/Win/Meta) modifier (#6592)
Terminals which support the enhanced keyboard protocol send events for
keys pressed with the Super modifier (Windows/Linux key or the Command
key). The only changes that are needed to support this in Helix are:

* Mapping the modifier from crossterm's KeyModifiers to Helix's
  KeyModifiers.
* Representing and parsing the modifier from the KeyEvent text
  representation.
* Documenting the ability to remap it.

When writing keybindings, use 'Meta-', 'Cmd-' or 'Win-' which are all
synonymous. For example:

    [keys.normal]
    Cmd-s = ":write"

will trigger for the Windows or Linux keys and the Command key plus 's'.
2024-12-08 12:35:14 +09:00
Tomas Zemanovic
fc9968bd4b fix: allow to parse "-" as a key code (#12191)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-12-06 08:46:38 -06:00
Michael Davis
28953ef40f Simplify change_current_directory and remove extra allocs 2024-12-05 18:50:31 -05:00
Nikita Revenco
93deb1f6ae feat: :cd - changes to the previous working directory (#12194)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-12-05 17:40:37 -06:00
Allemand Instable
a6f80c5bd9 Fix mojo LSP configuration to conform to magic introduction (#12195)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-12-05 16:54:10 -06:00
David Crespo
cd1f6e8239 Add static commands to documentation (#11950)
Co-authored-by: Adam Perkowski <adas1per@protonmail.com>
2024-12-05 11:13:00 -06:00
Michael Davis
fd3e889927 Add integration tests for line comment continuation 2024-12-05 20:53:53 +09:00
Michael Davis
1e6fe00001 Trim all trailing whitespace on insert_newline 2024-12-05 20:53:53 +09:00
Ian Hobson
4c8175ca04 Draw each message line separately in draw_eol_diagnostic
`set_string_truncated` renders the entire string while ignoring
newlines, so if the diagnostic's message contains multiple lines it
produces messages like 'first linesecond line'.

To avoid these run-ons, this commit renders each line separately,
inserting double spaces for disambiguation.
2024-12-04 18:23:30 -06:00
Ian Hobson
715a13b2d3 Remove an incorrect comment
This was copied from the function above (set_style). I don't know enough
about the function to suggest an alternative.
2024-12-04 18:23:30 -06:00
Kieran Moy
e670970dd8 Change default comment token to # for unrecognized files (#12080)
* Change the default comment token

* update test

* keep the original
2024-12-05 01:11:39 +01:00
Nikita Revenco
565bfbba25 feat: :cd with no args changes to home directory (#12042) 2024-12-04 18:09:33 -06:00
rojebd
5bdf14110f add Vintage theme (#9361)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-12-04 17:12:21 -06:00
rojebd
8a7006dd57 update voxed theme (#9328) 2024-12-04 17:03:45 -06:00
barsoosayque
cd972ae77d Add support for Teal language (#12081)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-12-04 14:59:11 -06:00
Michael Davis
07e7e7534d theme: Include key names in style parsing warnings
This should make it easier to figure out why the theme-check CI job
fails. Previously the message didn't include the failing key so you
were left searching or guessing where the error occurred.
2024-12-04 10:24:42 -05:00
Tomasz Zurkowski
7a2afdc080 Show an error when formatter is not available (#12183) 2024-12-04 08:27:54 -06:00
Michael Davis
085c4fe4c8 docs: Eliminate improper use of "LSP" term
Sometimes we used "LSP" to mean "language server". This change
eliminates the improper "LSP" usage.

Ref https://github.com/helix-editor/helix/pull/12183#discussion_r1868436105
2024-12-03 18:29:44 -05:00
Michael Davis
fa68bac391 contributing: Add steps for updating the MSRV 2024-12-03 10:07:59 -05:00
Michael Davis
403aaa8cf3 CI: Use an env var for MSRV
This just reduces duplication in the build workflow - no functional
change - to make updating the MSRV easier in the future.
2024-12-03 10:07:59 -05:00
dependabot[bot]
cf81e15315 build(deps): bump the rust-dependencies group with 3 updates (#12181)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-02 18:27:49 -06:00
Nikita Revenco
c0bfdd7bfe fix: catppuccin theme colors for checked and unchecked lists (#12167) 2024-12-02 12:37:01 -06:00
Michael Davis
ec1628c07f registers: Use saved values for clipboard providers which can't read
This fixes reading from the clipboard when using the termcode provider.
Reading isn't implemented for the termcode provider so `get_contents`
returns `ClipboardError::ReadingNotSupported`. `read_from_clipboard`
needs to recognize this case and use the saved values instead of
emitting an error log and returning nothing.

Follow-up of #10839
Also see #12142
2024-12-02 10:16:17 -05:00
uncenter
548f04fe26 Add support for the Vento template language (#12147)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-12-02 09:03:11 -06:00
xiabo
44c1d51d8c add bufferline highlighting for flexoki themes (#12146) 2024-12-02 09:01:00 -06:00
Poliorcetics
83fe23ce75 just: bump grammar support to Just 1.37.0 (#12141) 2024-12-02 08:45:46 -06:00
Jaakko Paju
b1bdbc6789 Fix language configuration for .conf files (#12156) 2024-12-02 08:27:08 -06:00
Michael Davis
191b0f08a9 Remove unnecessary clippy allow for old false positive
The clippy version after the recent MSRV bump no longer emits
`redundant_clone` warnings for these lines. We allowed these previously
since they were emitted as false positives.
2024-12-02 09:23:42 -05:00
RoloEdits
5ba97ba41e fix(clippy): clippy 1.83 lints (#12150) 2024-12-02 08:23:32 -06:00
Poliorcetics
e1d1a5c5a1 cleanup: remove pr.md introduced in #11448 (#12140) 2024-11-27 13:24:57 -06:00
Poliorcetics
0f4729289b fix: Remove leftover debug println! (#12138)
Introduced in dc941d6d24
2024-11-27 20:05:18 +09:00
Milan Vaško
7676106960 Search selection with word boundary detection (#12126)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-11-26 13:30:53 -06:00
Ronan Desplanques
95e6c11ebc Improve language support for Ada (#12131)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-11-26 12:43:34 -06:00
dependabot[bot]
80709cee61 build(deps): bump the rust-dependencies group with 4 updates (#12129)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-25 18:06:54 -06:00
Michael Davis
dbd3b251d8 CI: Pin mdbook to 0.4.43
This should prevent future surprising changes to the site from newly
published mdbook versions with breaking changes. For example mdbook
0.4.41 introduced some changes that needed the `index.hbs` file to be
updated. See the parent commit.
2024-11-25 17:56:17 -05:00
Michael Davis
436855ad6f book: Copy over index.hbs from mdbook 0.4.43
0.4.41 introduced some breaking changes for those using custom themes
so we need to re-vendor the file. This file is taken from mdbook
0.4.43:

    mdbook init --theme

In a tmp directory, and then a reset of the line that adds Colibri as
a selectable theme.
2024-11-25 17:53:13 -05:00
RoloEdits
cbbeca6c52 fix(clippy): suppress unused lint on windows (#12107) 2024-11-22 08:10:11 -06:00
Ryan Roden-Corrent
46ffec3fd4 Add WORKSPACE.bzlmod to starlark file-types (#12103) 2024-11-22 07:57:20 -06:00
Michael Davis
fbe216e11c CI: Match rust-toolchain action to MSRV version 2024-11-22 08:39:37 -05:00
Rolo
f07c1cc9f5 chore(msrv): bump MSRV from 1.70 to 1.76 2024-11-22 01:17:08 -08:00
Philipp Mildenberger
dc941d6d24 Add support for path completion (#2608)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
Co-authored-by: Pascal Kuthe <pascalkuthe@pm.me>
2024-11-21 21:12:36 -06:00
Lens0021 / Leslie
f305c7299d Add support for Amber-lang (#12021)
Co-authored-by: Phoenix Himself <pkaras.it@gmail.com>
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-11-21 10:09:42 -06:00
Valentin B.
9e0d2d0a19 chore(solidity): add highlight queries (#12102)
Add highlights for `hex` and `unicode` string prefixes and YUL booleans
2024-11-21 07:58:14 -06:00
Niklas Gruhn
b8313da5a8 Add language support for Quint (#11898)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-11-20 17:56:24 -06:00
Egor Afanasin
32ff0fce4a Add Sunset theme (#12093) 2024-11-20 17:26:44 -06:00
yehor
9e171e7d1d Add default-yank-register option (#11430)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-11-20 17:24:55 -06:00
Teemu Säilynoja
b92e8abfb3 Update Snakemake language config (#11936) 2024-11-20 17:20:51 -06:00
PORTALSURFER
8807dbfc40 Update current hex themes, add a new hex theme (#10849) 2024-11-20 17:20:04 -06:00
Arthur
15b478d433 hyprlang: add hyprls language server (#11056)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-11-20 17:16:49 -06:00
Michael Davis
467fad51b1 clipboard: Sway builtin provider yank and paste commands
The configuration here is not super intuitive - in order to yank from
a clipboard provider we want it to paste the clipboard and in order to
paste to the clipboard we want it to yank the contents we pass.

This swaps the programs for yank and paste to align with that.

Ref #10839
2024-11-20 18:10:46 -05:00
Michael Davis
b855cd0cda clipboard: Fix builtin_names for x-clip, x-sel, win-32-yank
Copy/paste error from #10839
2024-11-20 18:10:31 -05:00
spx01
6101b3a7a3 fix: simplify text reflowing strategy to improve language compatibility (#12048) 2024-11-20 16:40:43 -06:00
Yerlan
887bbbc375 Adding NestedText language support (#11987)
Co-authored-by: Yerlan Sergaziyev <yerlan.sergaziyev@rms-consult.de>
2024-11-20 16:39:34 -06:00
Ricardo Fernández Serrata
7ee66c0658 suggest *.desktop for AppImage (#10823)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-11-20 16:39:06 -06:00
Heath Stewart
843c058f0b Use latest tree-sitter-bicep, support bicepparams (#11525)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-11-20 16:38:15 -06:00
Travis Harmon
ed7e5bd8dc Use bold statusline for mode indicator in onedarker theme (#11958) 2024-11-20 16:36:59 -06:00
Krishan
b501a300e9 Update Zig's comment tokens (#12049) 2024-11-20 16:36:28 -06:00
Frans Skarman
310bc04f23 Add spade support (#11448)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-11-20 16:35:49 -06:00
Thomas Aarholt
2f6a113fbe Docs Key-Remapping: Move Commands to top as introduction (#11953) 2024-11-20 16:35:06 -06:00
Alexis Mousset
8c6ca3c0fc Update modus themes to 4.6.0 (#11949) 2024-11-20 16:30:35 -06:00
Michael Davis
b97c745631 docs: Improve display of inline-diagnostics config sample
Closes https://github.com/helix-editor/helix/issues/11591
2024-11-20 17:28:44 -05:00
Adam Chalmers
d8e2aab201 Document how to use modifier keys in macro remaps (#11930) 2024-11-20 16:26:46 -06:00
Michael Davis
188f701f50 docs: Remove invalid '--path helix-term' from build instructions
Fixes https://github.com/helix-editor/helix/issues/11557
2024-11-20 17:25:40 -05:00
Robert Edmonds
83f1b98e80 languages: Add ssh_config.d/*.conf as a glob for sshclientconfig (#11947) 2024-11-20 16:20:59 -06:00
Keir Lawson
4dc46f9472 Make Spacebones theme picker selection more legible (#12064) 2024-11-20 16:20:21 -06:00
Javier Goday
4d0b7e57b1 Set tags color in monokai theme (#11917) 2024-11-20 16:19:58 -06:00
Yuki Kobayashi
548fd57489 fix(languages): treat tsconfig.json as jsonc (#12031) 2024-11-20 16:19:23 -06:00
blt-r
8ed8d52e9d Treat .clangd and .clang-format as YAML (#12032) 2024-11-20 16:19:06 -06:00
Elizabeth
eeb5b7bbdd fix: added .DS_Store to gitignore 2024-11-20 16:18:42 -06:00
Elizabeth
d95b21ddd3 fix(swift): disabled auto-format & added .swift-format highlighting 2024-11-20 16:18:42 -06:00
zetashift
56bb366f7e Update Unison grammar and queries (#12039) 2024-11-20 16:18:18 -06:00
Aidan Gauland
06d5b88dee feat(languages): add .livemd Markdown extension (#12034) 2024-11-20 16:17:40 -06:00
Eamon Caton
e2d79c1891 Add Carbonfox theme (#11558) 2024-11-20 16:16:05 -06:00
mesmere
5b3e0b64f0 Add new "Eiffel" theme (#11679) 2024-11-20 16:15:38 -06:00
Michael McClintock
07262f5170 Add yo themes (#11703) 2024-11-20 16:15:13 -06:00
pacien
6ec510d58f queries/nix: add injections for nim writers (#11837) 2024-11-20 16:14:56 -06:00
Veesh Goldman
4d3612125b chore: update perl + pod parsers (#11848) 2024-11-20 16:14:39 -06:00
Sebastian Neubauer
f9ac1f1ff1 Bump tree-sitter llvm grammars (#11851) 2024-11-20 16:14:15 -06:00
Grenier Célestin
2dbecd3c80 Bump tree-sitter-nasm (#11795) 2024-11-20 16:13:27 -06:00
eh
aa10b1fd11 Theme: Seoul256 dark & light (#11466) 2024-11-20 16:10:46 -06:00
Freddie Gilbraith
07968880e6 update to newest rescript treesitter library and queries (#11165)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
Co-authored-by: Freddie Ridell <freddie@Gilbraith-MacBook-Pro.local>
2024-11-20 16:08:38 -06:00
Raghu Saxena
4e2faa0be9 Add :config-reload to configuration docs (#11086)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-11-20 16:08:06 -06:00
AbrA-K
0fca0d057e Theme: add adwaita-light theme (#10869)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
Co-authored-by: abra <abra@KadaZen.fritz.box>
2024-11-20 16:07:31 -06:00
Alfie Richards
68ee87695b Add clipboard provider configuration (#10839) 2024-11-20 16:06:23 -06:00
RoloEdits
b6e555a2ed feat(highlights): add INVARIANT to error tag (#12094) 2024-11-20 16:04:43 -06:00
Jaakko Paju
48e15f77f7 Add package.json and (and tsconfig.json) for TS/JS language config roots (#10652)
* Add package.json and tsconfig.json for TS/JS language config roots

* Add root to Javascript
2024-11-20 16:03:46 -06:00
Michael Davis
59b020ec91 Save an undo checkpoint before paste in insert mode (#8121) 2024-11-20 16:02:10 -06:00
Mark Stosberg
239262e094 docs: Document what directory file_picker opens from (#10816) 2024-11-20 15:58:50 -06:00
Eduardo Rittner Coelho
23600e3ecb Add correct source file for TypableCommandList (#11839)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-11-20 15:58:24 -06:00
Sam Kagan
287e412780 docs(keymap): add select_all_children (#11972)
Co-authored-by: Sam Kagan <skagan@nrao.edu>
2024-11-20 15:58:00 -06:00
stefanvi
bc18dc2c0c Pluralize 'parenthesis' in the tutorial (#12015) 2024-11-20 15:57:42 -06:00
Sebastian Dörner
3fd7ca334e Add support for textproto language. (#11874) 2024-11-20 15:57:30 -06:00
Oren Mittman
6373027c9e chore: add "ui.virtual.jump-label" to serika-dark theme (#11911) 2024-11-20 15:57:15 -06:00
dependabot[bot]
f06f481ad9 build(deps): bump the rust-dependencies group with 5 updates (#12088)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-20 15:56:56 -06:00
dependabot[bot]
a219d5aabb build(deps): bump unicode-general-category from 0.6.0 to 1.0.0 (#12089)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-20 11:41:07 -06:00
Michael Davis
d489c03c4f helix-term: Use workspace thiserror dep 2024-11-20 11:40:45 -06:00
dependabot[bot]
f621423e7d build(deps): bump thiserror from 1.0.64 to 2.0.3
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.64 to 2.0.3.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.64...2.0.3)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-20 11:40:45 -06:00
dependabot[bot]
35802cb025 build(deps): bump which from 6.0.3 to 7.0.0 (#12090)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-11-20 11:40:00 -06:00
Michael Davis
6cca98264f Re-vendor encoding_rs test data
This fixes a test (`helix_view::document::gb18030_decode`) since
encoding_rs updated its gb18030 encoding to match GB18030-2022 (was
GB18030-2005).

The newly vendored files update the license line and I've included the
referenced license in the `encoding/` directory.
2024-11-13 15:30:17 +09:00
Michael Davis
9806ca08b1 Fix breaking change in gix Tree::loop_entry_by_path 2024-11-13 15:30:17 +09:00
dependabot[bot]
b5d56e57a6 build(deps): bump the rust-dependencies group across 1 directory with 11 updates
Bumps the rust-dependencies group with 10 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [regex](https://github.com/rust-lang/regex) | `1.11.0` | `1.11.1` |
| [url](https://github.com/servo/rust-url) | `2.5.2` | `2.5.3` |
| [serde](https://github.com/serde-rs/serde) | `1.0.210` | `1.0.215` |
| [encoding_rs](https://github.com/hsivonen/encoding_rs) | `0.8.34` | `0.8.35` |
| [anyhow](https://github.com/dtolnay/anyhow) | `1.0.90` | `1.0.93` |
| [tempfile](https://github.com/Stebalien/tempfile) | `3.13.0` | `3.14.0` |
| [tokio](https://github.com/tokio-rs/tokio) | `1.40.0` | `1.41.1` |
| [libc](https://github.com/rust-lang/libc) | `0.2.161` | `0.2.162` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.1.31` | `1.1.37` |
| [gix](https://github.com/GitoxideLabs/gitoxide) | `0.66.0` | `0.67.0` |



Updates `regex` from 1.11.0 to 1.11.1
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.11.0...1.11.1)

Updates `url` from 2.5.2 to 2.5.3
- [Release notes](https://github.com/servo/rust-url/releases)
- [Commits](https://github.com/servo/rust-url/compare/v2.5.2...v2.5.3)

Updates `serde` from 1.0.210 to 1.0.215
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.210...v1.0.215)

Updates `encoding_rs` from 0.8.34 to 0.8.35
- [Commits](https://github.com/hsivonen/encoding_rs/compare/v0.8.34...v0.8.35)

Updates `anyhow` from 1.0.90 to 1.0.93
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.90...1.0.93)

Updates `tempfile` from 3.13.0 to 3.14.0
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.13.0...v3.14.0)

Updates `tokio` from 1.40.0 to 1.41.1
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.40.0...tokio-1.41.1)

Updates `libc` from 0.2.161 to 0.2.162
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.162/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.161...0.2.162)

Updates `rustix` from 0.38.37 to 0.38.40
- [Release notes](https://github.com/bytecodealliance/rustix/releases)
- [Changelog](https://github.com/bytecodealliance/rustix/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bytecodealliance/rustix/compare/v0.38.37...v0.38.40)

Updates `cc` from 1.1.31 to 1.1.37
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.31...cc-v1.1.37)

Updates `gix` from 0.66.0 to 0.67.0
- [Release notes](https://github.com/GitoxideLabs/gitoxide/releases)
- [Changelog](https://github.com/GitoxideLabs/gitoxide/blob/main/CHANGELOG.md)
- [Commits](https://github.com/GitoxideLabs/gitoxide/compare/gix-v0.66.0...gix-v0.67.0)

---
updated-dependencies:
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: url
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: encoding_rs
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: tempfile
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: libc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: rustix
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: gix
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-13 15:30:17 +09:00
Elizabeth
10c3502a89 fix: removed explict default config file from swift-format (#12052) 2024-11-11 12:30:55 +09:00
Yuki Kobayashi
b53dafe326 Treat .prettierrc as YAML (#11997) 2024-11-05 16:09:49 +09:00
Poliorcetics
c0920e779d just: update tree-sitter-grammar to support 1.36.0 (#11606)
Release notes:

- https://github.com/casey/just/releases/tag/1.35.0
- https://github.com/casey/just/releases/tag/1.36.0

Notably, this adds `[private]` attributes on modules, which the current version of the grammar cannot parse,
as well as unicode codepoint escape sequences.
2024-11-05 16:09:20 +09:00
Elliot Fontaine
38faf74feb feat: Add support for cylc configuration files (#11830)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-10-30 13:39:24 -05:00
dependabot[bot]
101a74bf6e build(deps): bump the rust-dependencies group with 6 updates (#11924)
Bumps the rust-dependencies group with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [serde_json](https://github.com/serde-rs/json) | `1.0.128` | `1.0.132` |
| [anyhow](https://github.com/dtolnay/anyhow) | `1.0.89` | `1.0.90` |
| [libc](https://github.com/rust-lang/libc) | `0.2.159` | `0.2.161` |
| [fern](https://github.com/daboross/fern) | `0.6.2` | `0.7.0` |
| [pulldown-cmark](https://github.com/raphlinus/pulldown-cmark) | `0.12.1` | `0.12.2` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.1.30` | `1.1.31` |


Updates `serde_json` from 1.0.128 to 1.0.132
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/1.0.128...1.0.132)

Updates `anyhow` from 1.0.89 to 1.0.90
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.89...1.0.90)

Updates `libc` from 0.2.159 to 0.2.161
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.161/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.159...0.2.161)

Updates `fern` from 0.6.2 to 0.7.0
- [Release notes](https://github.com/daboross/fern/releases)
- [Changelog](https://github.com/daboross/fern/blob/main/CHANGELOG.md)
- [Commits](https://github.com/daboross/fern/compare/fern-0.6.2...fern-0.7.0)

Updates `pulldown-cmark` from 0.12.1 to 0.12.2
- [Release notes](https://github.com/raphlinus/pulldown-cmark/releases)
- [Commits](https://github.com/raphlinus/pulldown-cmark/compare/v0.12.1...v0.12.2)

Updates `cc` from 1.1.30 to 1.1.31
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.30...cc-v1.1.31)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: libc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: fern
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: pulldown-cmark
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-23 22:34:20 +09:00
Michael Davis
6d64e6288a Bump flake dependencies
`nix flake update`
2024-10-21 11:27:46 +09:00
Michael Davis
f371dcaa4e flake: Include --cfg tokio_unstable in Rust flags
The flake sets `RUSTFLAGS` and that overwrites the setting in
`.cargo/config.toml`. We need to add the `--cfg tokio_unstable` flag to
enable integration tests to run when called from the devShell.
2024-10-21 11:27:46 +09:00
TornaxO7
be2884d800 Continue line comments (#10996) 2024-10-19 05:48:07 -04:00
Sebastian Dall
a1453350df Adding snakemake to language (#11858)
* feat: snakemake language

* feat: snakemake syntax highlighting

* doc: xtask docgen - snakemake

* Addressed feedback: removed redundant grammar

* fixed indentation

* removed has-ancestor predicate

---------

Co-authored-by: “SebastianDall” <“semoda@bio.auu.dk”>
2024-10-18 23:12:36 +02:00
karei
855a43a266 Bump jjdescription grammar revision (#11857) 2024-10-18 13:09:11 +09:00
Ivan B.
5ab1f1eb5a docs(themes): place ui.highlight.frameline and ui.highlight together (#11896)
* docs(themes): place `ui.highlight.frameline` and `ui.highlight` together

* docs(themes): small fix
2024-10-18 13:08:54 +09:00
langurmonkey
1437ba1e5a Add glsl_analyzer as default language server for GLSL (#11891)
* Add glsl_analyzer as default language server for GLSL

* Generate docs
2024-10-18 11:17:25 +09:00
dependabot[bot]
d1b8129491 build(deps): bump cc in the rust-dependencies group (#11890)
Bumps the rust-dependencies group with 1 update: [cc](https://github.com/rust-lang/cc-rs).


Updates `cc` from 1.1.28 to 1.1.30
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.28...cc-v1.1.30)

---
updated-dependencies:
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-16 17:52:14 +09:00
David Else
f2d54db24f Update repology URL after change from helix to helix-editor (#11877)
* Update repology URL after change from helix to helix-editor

* Update book/src/package-managers.md

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-10-16 01:53:59 +09:00
Dmitry Marakasov
e4f3483bd1 Fix repology badge (#11895) 2024-10-16 01:52:50 +09:00
dependabot[bot]
a7651f5bf0 build(deps): bump the rust-dependencies group with 4 updates (#11850)
Bumps the rust-dependencies group with 4 updates: [once_cell](https://github.com/matklad/once_cell), [futures-util](https://github.com/rust-lang/futures-rs), [futures-executor](https://github.com/rust-lang/futures-rs) and [cc](https://github.com/rust-lang/cc-rs).


Updates `once_cell` from 1.20.1 to 1.20.2
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.20.1...v1.20.2)

Updates `futures-util` from 0.3.30 to 0.3.31
- [Release notes](https://github.com/rust-lang/futures-rs/releases)
- [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.30...0.3.31)

Updates `futures-executor` from 0.3.30 to 0.3.31
- [Release notes](https://github.com/rust-lang/futures-rs/releases)
- [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.30...0.3.31)

Updates `cc` from 1.1.23 to 1.1.28
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.23...cc-v1.1.28)

---
updated-dependencies:
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: futures-util
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: futures-executor
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-11 16:38:21 +09:00
dependabot[bot]
761f70d611 build(deps): bump cachix/install-nix-action from 29 to 30 (#11852)
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 29 to 30.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/v29...v30)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-08 16:23:36 +09:00
rhogenson
f55f1f8b43 Remove auto-pair for single quote in SML. (#11838)
Similar to OCaml and other ML languages, single quote is a normal
character that can appear in identifiers and is also used in type
parameters. It is not used for strings or character literals, which both
use double quote.

Co-authored-by: Rose Hogenson <rosehogenson@posteo.net>
2024-10-07 11:56:54 +09:00
Christopher Kaster
048973fc55 Add support for dune project language (#11829) 2024-10-06 21:53:12 +02:00
RoloEdits
f6d39cbc1d refactor(lsp): handle out-of-range active_signature (#11825) 2024-10-06 08:54:17 -05:00
Pascal Kuthe
162028d444 Merge pull request #11486 from helix-editor/lsp-location-refactor
Replace uses of `lsp::Location` with a custom Location type
2024-10-04 03:33:35 +02:00
Skyler Hawthorne
02b6f1488a fix git repo detection on symlinks (#11732) 2024-10-03 12:08:06 -05:00
Ian Hobson
57ec3b7330 Add a highlight for the keyword.storage scope to the onedark theme (#11802)
Rust highlight queries make use of keyword.storage for keywords like
`struct`, `enum`, and also for modifiers like `mut` and `ref`.

Using a color that's different to the one used for
`"variable.parameter"` (red) improves differentiation for mutable
function arguments.
2024-10-01 10:05:45 +09:00
Akseli
083bb0118f Fix some odin highlights (#11804)
Some of the odin highlights seemed wrong or lacking, like the import names were not being matched:

```odin

// color both "rl" here to same value
import rl "vendor:raylib"

...

rl.Vector3
```

Import color was also not being used correctly
2024-10-01 10:05:28 +09:00
dependabot[bot]
cb9307bb03 build(deps): bump the rust-dependencies group with 5 updates (#11805)
Bumps the rust-dependencies group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [once_cell](https://github.com/matklad/once_cell) | `1.19.0` | `1.20.1` |
| [regex](https://github.com/rust-lang/regex) | `1.10.6` | `1.11.0` |
| [tempfile](https://github.com/Stebalien/tempfile) | `3.12.0` | `3.13.0` |
| [libc](https://github.com/rust-lang/libc) | `0.2.158` | `0.2.159` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.1.21` | `1.1.23` |


Updates `once_cell` from 1.19.0 to 1.20.1
- [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md)
- [Commits](https://github.com/matklad/once_cell/compare/v1.19.0...v1.20.1)

Updates `regex` from 1.10.6 to 1.11.0
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.10.6...1.11.0)

Updates `tempfile` from 3.12.0 to 3.13.0
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.12.0...v3.13.0)

Updates `libc` from 0.2.158 to 0.2.159
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.159/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.158...0.2.159)

Updates `cc` from 1.1.21 to 1.1.23
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.21...cc-v1.1.23)

---
updated-dependencies:
- dependency-name: once_cell
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: tempfile
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: libc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-01 10:05:07 +09:00
dependabot[bot]
e28b0da1fb build(deps): bump cachix/install-nix-action from V28 to 29 (#11806)
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from V28 to 29. This release includes the previously tagged commit.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/V28...v29)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-10-01 10:04:21 +09:00
offsetcyan
e5dd60f794 Add Erlang Language Platform (ELP) support to Erlang (#11499)
* Add ELP LSP to Erlang

* generate docs

---------

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2024-09-30 11:06:45 +09:00
Denis Krienbühl
d103248cb8 Small bogster theme improvements (#11353)
* Add a distinct jump-label to bogster theme

* Make the primary label visible in the bogster theme
2024-09-30 11:06:33 +09:00
David Crespo
42453786a0 add key concepts to usage.md (#11485) 2024-09-30 11:06:24 +09:00
Oren Mittman
e1cacd149c chore: add "ui.virtual.jump-label" to gruber-darker theme (#11547) 2024-09-30 11:02:19 +09:00
David Else
5975e53600 Add vale language server (#11636)
Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2024-09-30 11:02:02 +09:00
RoloEdits
24f24299f2 feat(languages): add superhtml as lsp for html (#11609) 2024-09-30 11:01:49 +09:00
chtenb
5ffd4ae529 Add undocumented keybindings to book (#11662) 2024-09-30 11:01:36 +09:00
chtenb
8cdce9212c Improve tree-sitter-subtree (#11663)
* Make unnamed nodes visible in subtree view

* Refine command description

* Update generated docs

* Update unit test expected output
2024-09-30 10:59:31 +09:00
Axlefublr
48b89d4dcf fix: fish builtin functions are highlighted as such (#11792)
* fix: fish builtin functions are highlighted as such

* fix: single-character commands recognized as builtins

???? how did that query even happen

* fix: update builtins to fish 3.7.1

* fix: add back `alias` and `isatty`

they are builtins, but aren't reported by builtin -n for some reason
2024-09-30 10:59:03 +09:00
Dmitriy Sokolov
dd45ae1289 languages.toml: recognize ldtk files (#11793) 2024-09-30 10:58:54 +09:00
Ian J Sikes
2c3a00e96a Fix typo in tutor ch 13.5 (#11765)
It said "split" instead of "swap"
2024-09-30 10:58:19 +09:00
jneem
2ce4c6d5fa Bump tree-sitter-nickel (#11771) 2024-09-29 14:30:50 +02:00
Tim
82dd963693 Add: validation of bundled themes in build workflow (#11627)
* Add: xtask to check themes for validation warnings

* Update: tidied up runtime paths

* Update: test build workflow

* Update: address clippy lints

* Revert: only trigger workflow on push to master branch

* Add: Theme::from_keys factory method to construct theme from Toml keys

* Update: returning validation failures in Loader.load method

* Update: commented out invalid keys from affected themes

* Update: correct invalid keys so that valid styles still applied

* Update: include default and base16_default themes in check

* Update: renamed validation_failures to load_errors

* Update: introduce load_with_warnings helper function and centralise logging of theme warnings

* Update: use consistent naming throughout
2024-09-28 13:52:09 +02:00
Konstantin Munteanu
70bbc9d526 Add .rbs files to ruby language (#11786) 2024-09-28 13:22:13 +09:00
Akseli
b18a471ed1 Remove "true" from odinfmt line (#11759)
The `-stdin` in `odinfmt` does not take any arguments, the `true` part here just confuses the formatter, and makes it ignore `odinfmt.json` file.

Removing it fixes the issue.
2024-09-25 15:24:11 +09:00
Tobias Hunger
f49b18d157 chore: Update slint tree-sitter grammar to version 1.8 (#11757)
Bump the commit to the tree-sitter corresponding to the
latest Slint release.
2024-09-25 15:23:52 +09:00
Lukas Knuth
50ba848b59 Update HCL grammar (#11749)
* Point HCL grammer to newest

This adds support for provider-defined function calls in Terraform.

* Update HCL grammar repo

The repository was moved from the original authors personal GitHub to the `tree-sitter-grammars` organization.

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-09-25 15:23:38 +09:00
dependabot[bot]
30aa375f2d build(deps): bump the rust-dependencies group with 2 updates (#11761)
Bumps the rust-dependencies group with 2 updates: [thiserror](https://github.com/dtolnay/thiserror) and [cc](https://github.com/rust-lang/cc-rs).


Updates `thiserror` from 1.0.63 to 1.0.64
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.63...1.0.64)

Updates `cc` from 1.1.19 to 1.1.21
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.19...cc-v1.1.21)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-25 02:39:41 +09:00
rhogenson
73deabaa40 Fix panic when drawing at the edge of the screen. (#11737)
When pressing tab at the edge of the screen, Helix panics in debug mode
subtracting position.col - self.offset.col.

To correctly account for graphemes that are partially visible,
column_in_bounds takes a width and returns whether the whole range is
in bounds.

Co-authored-by: Rose Hogenson <rosehogenson@posteo.net>
2024-09-23 02:17:02 +09:00
rhogenson
8b1764d164 Join single-line comments with J. (#11742)
Fixes #8565.

Co-authored-by: Rose Hogenson <rosehogenson@posteo.net>
2024-09-23 02:16:24 +09:00
James Munger
d6eb10d9f9 Update README.md (#11665)
Readability Clarification
2024-09-21 19:26:01 +02:00
Théo Daron
896bf47d8d adding support for jujutsu VCS inside find_workspace resolution (#11685) 2024-09-21 19:22:50 +02:00
Thor 🪁
c850b90f67 add circom tree-sitter, syntax-highlighting, and lsp support (#11676)
* add circom tree-sitter and lsp support

* add circom syntax highlighting queries

* cargo xtask docgen

* updated highlights to reflect helix themes typing

* bugfix: ~= operator causing issues

* minor adjustment: add = and ; operator and delimiter
2024-09-21 19:13:02 +02:00
Mykyta
274c660a0e small fix syntax highlighting in vue.js files (#11706)
* small fix syntax highlighting in vue.js files

* changes after review by mikedavis
2024-09-21 19:12:39 +02:00
rhogenson
5717aa8e35 Fix Rope.starts_with. (#11739)
Co-authored-by: Rose Hogenson <rosehogenson@posteo.net>
2024-09-21 23:05:17 +09:00
timd
9f93de5a4b fix(themes): fix diagnostics in snazzy (#11731)
* fix(themes): fix diagnostics in snazzy

Before this change, the color scheme makes most diagnostics difficult
to read. This fix makes diagnostic much less obtrusive when using
snazzy.

* chore(fmt): nicely format snazzy theme file
2024-09-19 10:15:51 +09:00
Ayoub Benali
b85e824ba9 Handle window/showMessage and display it bellow status line (#5535)
* Handle window/showMessage and display it bellow status line

* Enable `editor.lsp.display_messages` by default

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-09-18 21:43:06 +02:00
Nicolas Karolak
a7b8b27abf chore: add ruff and jedi lsp servers (#11630)
* chore: add ruff lsp server

Ruff provide a `server` command that starts a LSP server:
https://docs.astral.sh/ruff/editors/#language-server-protocol

* chore: add jedi lsp server

[jedi-language-server](https://github.com/pappasam/jedi-language-server) is a Python LSP server based the popular [jedi](https://jedi.readthedocs.io/en/latest/) library.

* docs: add ruff and jedi as python lsp servers
2024-09-18 12:12:31 +09:00
Jesús González
84fbadbdde Update picker headers styling in Darcula themes (#11620)
* Apply styling to picker headers in Darcula themes

* Add background to active picker column in Darcula.
2024-09-17 11:34:10 +09:00
ves
f4df4bf5f2 Stylize horizon-dark picker v2 columns (#11649) 2024-09-17 11:33:21 +09:00
dependabot[bot]
c754949454 build(deps): bump the rust-dependencies group with 4 updates (#11712)
Bumps the rust-dependencies group with 4 updates: [unicode-segmentation](https://github.com/unicode-rs/unicode-segmentation), [anyhow](https://github.com/dtolnay/anyhow), [rustix](https://github.com/bytecodealliance/rustix) and [cc](https://github.com/rust-lang/cc-rs).


Updates `unicode-segmentation` from 1.11.0 to 1.12.0
- [Commits](https://github.com/unicode-rs/unicode-segmentation/compare/v1.11.0...v1.12.0)

Updates `anyhow` from 1.0.87 to 1.0.89
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.87...1.0.89)

Updates `rustix` from 0.38.36 to 0.38.37
- [Release notes](https://github.com/bytecodealliance/rustix/releases)
- [Changelog](https://github.com/bytecodealliance/rustix/blob/main/CHANGELOG.md)
- [Commits](https://github.com/bytecodealliance/rustix/compare/v0.38.36...v0.38.37)

Updates `cc` from 1.1.18 to 1.1.19
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.18...cc-v1.1.19)

---
updated-dependencies:
- dependency-name: unicode-segmentation
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: rustix
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-17 11:32:26 +09:00
dependabot[bot]
9851edf477 build(deps): bump cachix/install-nix-action from V27 to 28 (#11713)
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from V27 to 28. This release includes the previously tagged commit.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/V27...V28)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-17 11:31:36 +09:00
Niklas Gruhn
5ce77de0dc fix: Lean language server consuming excessive memory (#11683)
The Lean process, spawned by the language server, might use excessive
memory in certain situation, causing the entire system to freeze. See:

   https://github.com/leanprover/lean4/issues/5321

The language server accepts a CLI flag for limiting memory use. I set
it to 1024MB, which might be a bit arbitrary, but definitly prevents
the system from crashing.
2024-09-15 19:08:35 +09:00
dependabot[bot]
237cbe4bca build(deps): bump the rust-dependencies group with 4 updates (#11669)
Bumps the rust-dependencies group with 4 updates: [globset](https://github.com/BurntSushi/ripgrep), [ignore](https://github.com/BurntSushi/ripgrep), [grep-regex](https://github.com/BurntSushi/ripgrep) and [grep-searcher](https://github.com/BurntSushi/ripgrep).


Updates `globset` from 0.4.14 to 0.4.15
- [Release notes](https://github.com/BurntSushi/ripgrep/releases)
- [Changelog](https://github.com/BurntSushi/ripgrep/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BurntSushi/ripgrep/compare/globset-0.4.14...ignore-0.4.15)

Updates `ignore` from 0.4.22 to 0.4.23
- [Release notes](https://github.com/BurntSushi/ripgrep/releases)
- [Changelog](https://github.com/BurntSushi/ripgrep/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BurntSushi/ripgrep/commits)

Updates `grep-regex` from 0.1.12 to 0.1.13
- [Release notes](https://github.com/BurntSushi/ripgrep/releases)
- [Changelog](https://github.com/BurntSushi/ripgrep/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BurntSushi/ripgrep/compare/grep-regex-0.1.12...0.1.13)

Updates `grep-searcher` from 0.1.13 to 0.1.14
- [Release notes](https://github.com/BurntSushi/ripgrep/releases)
- [Changelog](https://github.com/BurntSushi/ripgrep/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BurntSushi/ripgrep/compare/grep-searcher-0.1.13...0.1.14)

---
updated-dependencies:
- dependency-name: globset
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: ignore
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: grep-regex
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: grep-searcher
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-10 22:59:03 +09:00
Skyler Hawthorne
6309cc71cc cargo update (#11651) 2024-09-08 13:08:49 +09:00
RoloEdits
c5083ef952 fix(clippy): doc_lazy_continuation (#11642) 2024-09-07 12:31:14 +09:00
dependabot[bot]
6d0a73f8e5 build(deps): bump gix-path from 0.10.10 to 0.10.11 (#11648)
Bumps [gix-path](https://github.com/Byron/gitoxide) from 0.10.10 to 0.10.11.
- [Release notes](https://github.com/Byron/gitoxide/releases)
- [Changelog](https://github.com/Byron/gitoxide/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Byron/gitoxide/compare/gix-path-v0.10.10...gix-path-v0.10.11)

---
updated-dependencies:
- dependency-name: gix-path
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-07 12:31:04 +09:00
dependabot[bot]
41db5d735e build(deps): bump the rust-dependencies group with 2 updates (#11622)
Bumps the rust-dependencies group with 2 updates: [tokio](https://github.com/tokio-rs/tokio) and [rustix](https://github.com/bytecodealliance/rustix).


Updates `tokio` from 1.39.3 to 1.40.0
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.39.3...tokio-1.40.0)

Updates `rustix` from 0.38.34 to 0.38.35
- [Release notes](https://github.com/bytecodealliance/rustix/releases)
- [Commits](https://github.com/bytecodealliance/rustix/compare/v0.38.34...v0.38.35)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: rustix
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-04 21:22:45 +09:00
Michael Davis
da2b0a7484 Make helix_core::Uri cheap to clone
We clone this type very often in LSP pickers, for example diagnostics
and symbols. We can use a single Arc in many cases to avoid the
unnecessary clones.
2024-09-03 09:50:31 -04:00
Michael Davis
48e9357788 picker: Removed owned variant of PathOrId
The only caller of `from_path_buf` was removed in the parent commit
allowing us to drop owned variant of path's `Cow`. With this change we
never need to allocate in the picker preview callback.
2024-09-03 09:48:32 -04:00
Michael Davis
606b957172 Replace uses of lsp::Location with a custom Location type
The lsp location type has the lsp's URI type and a range. We can replace
that with a custom type private to the lsp commands module that uses the
core URI type instead.

We can't entirely replace the type with a new Location type in core.
That type might look like:

    pub struct Location {
        uri: crate::Uri,
        range: crate::Range,
    }

But we can't convert every `lsp::Location` to this type because for
definitions, references and diagnostics language servers send documents
which we haven't opened yet, so we don't have the information to convert
an `lsp::Range` (line+col) to a `helix_core::Range` (char indexing).

This cleans up the picker definitions in this file so that they can all
use helpers like `jump_to_location` and `location_to_file_location` for
the picker preview. It also removes the only use of the deprecated
`PathOrId::from_path_buf` function, allowing us to drop the owned
variant of that type in the child commit.
2024-09-03 09:48:32 -04:00
viyic
90f978d5af Change primary selection cursor color for naysayer (#11617) 2024-09-03 14:37:17 +09:00
dependabot[bot]
1b5295a3f3 build(deps): bump the rust-dependencies group with 4 updates (#11585)
Bumps the rust-dependencies group with 4 updates: [serde](https://github.com/serde-rs/serde), [serde_json](https://github.com/serde-rs/json), [cc](https://github.com/rust-lang/cc-rs) and [gix](https://github.com/Byron/gitoxide).


Updates `serde` from 1.0.208 to 1.0.209
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.208...v1.0.209)

Updates `serde_json` from 1.0.125 to 1.0.127
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/1.0.125...1.0.127)

Updates `cc` from 1.1.13 to 1.1.15
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.13...cc-v1.1.15)

Updates `gix` from 0.64.0 to 0.66.0
- [Release notes](https://github.com/Byron/gitoxide/releases)
- [Changelog](https://github.com/Byron/gitoxide/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Byron/gitoxide/compare/gix-v0.64.0...gix-v0.66.0)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: gix
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-28 23:56:28 +09:00
Lennard Hofmann
af7a1fd20c lsp: Gracefully ignore invalid diagnostic severity (#11569) 2024-08-25 14:27:10 -05:00
Yavorski
620dfceb84 Add cshtml to html file-types (#11540) 2024-08-23 17:28:36 +09:00
dependabot[bot]
38e6fcd5c5 build(deps): bump the rust-dependencies group with 7 updates (#11530)
Bumps the rust-dependencies group with 7 updates:

| Package | From | To |
| --- | --- | --- |
| [serde](https://github.com/serde-rs/serde) | `1.0.207` | `1.0.208` |
| [serde_json](https://github.com/serde-rs/json) | `1.0.124` | `1.0.125` |
| [tokio](https://github.com/tokio-rs/tokio) | `1.39.2` | `1.39.3` |
| [libc](https://github.com/rust-lang/libc) | `0.2.155` | `0.2.158` |
| [pulldown-cmark](https://github.com/raphlinus/pulldown-cmark) | `0.11.0` | `0.12.0` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.1.10` | `1.1.13` |
| [which](https://github.com/harryfei/which-rs) | `6.0.2` | `6.0.3` |


Updates `serde` from 1.0.207 to 1.0.208
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.207...v1.0.208)

Updates `serde_json` from 1.0.124 to 1.0.125
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.124...1.0.125)

Updates `tokio` from 1.39.2 to 1.39.3
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.39.2...tokio-1.39.3)

Updates `libc` from 0.2.155 to 0.2.158
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Changelog](https://github.com/rust-lang/libc/blob/0.2.158/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.155...0.2.158)

Updates `pulldown-cmark` from 0.11.0 to 0.12.0
- [Release notes](https://github.com/raphlinus/pulldown-cmark/releases)
- [Commits](https://github.com/raphlinus/pulldown-cmark/compare/v0.11.0...v0.12.0)

Updates `cc` from 1.1.10 to 1.1.13
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.10...cc-v1.1.13)

Updates `which` from 6.0.2 to 6.0.3
- [Release notes](https://github.com/harryfei/which-rs/releases)
- [Changelog](https://github.com/harryfei/which-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/harryfei/which-rs/compare/6.0.2...6.0.3)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: libc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: pulldown-cmark
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: which
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-21 09:41:49 +09:00
0rphee
9e7c488ee3 Update gruvbox themes (#11477) 2024-08-19 18:38:46 -05:00
RoloEdits
4e729dea02 fix: ensure view is initiated for jump_* commands (#11529) 2024-08-20 00:28:59 +02:00
nryz
e290479474 copy shell completion to nix output (#11518) 2024-08-19 15:45:38 -05:00
Jaakko Paju
b90ec5c779 Add/improve textobject queries (#11513)
* Add textobject queries for YAML

* Add textobject queries for SQL

* Add textobject queries for HOCON

* Add textobject queries for git-config

* Add textobject queries for env

* Add textobject queries for Dockerfile

* Add textobject queries for docker-compose

* Add textobject queries for prisma

* Add entry textobject queries for hcl

* Add entry textobject queries for Nix

* Update docs
2024-08-17 19:27:50 +02:00
Per-Gunnar
ff33b07756 Clarify lesson 10.1 wording (#11478)
Co-authored-by: Per-gunnar Eriksson <per-gunnar.eriksson@fortnox.se>
2024-08-14 19:44:44 +02:00
Frans Skarman
f9aae99379 Highlight types and enum members in the rust prelude (#8535)
* Add some rust builtins

* rust queries: Add everything in the 2021 prelude

* Update runtime/queries/rust/highlights.scm

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-08-14 19:43:31 +02:00
0rphee
f65ec32a1c Update everforest themes (#11459) 2024-08-13 13:53:03 +02:00
dependabot[bot]
112b2878ae build(deps): bump the rust-dependencies group with 4 updates (#11476)
Bumps the rust-dependencies group with 4 updates: [serde](https://github.com/serde-rs/serde), [serde_json](https://github.com/serde-rs/json), [tempfile](https://github.com/Stebalien/tempfile) and [cc](https://github.com/rust-lang/cc-rs).


Updates `serde` from 1.0.204 to 1.0.207
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.204...v1.0.207)

Updates `serde_json` from 1.0.122 to 1.0.124
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.122...v1.0.124)

Updates `tempfile` from 3.11.0 to 3.12.0
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/commits)

Updates `cc` from 1.1.7 to 1.1.10
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.7...cc-v1.1.10)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: tempfile
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-08-13 07:59:42 +02:00
RoloEdits
e46cedfc26 refactor(commands): trim_end of sh output (#11161) 2024-08-11 10:24:51 -05:00
Samy AB
91e642ce50 Add gherkin syntax highlighting (#11083)
Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2024-08-10 08:25:31 +09:00
Pascal Kuthe
e604d9f8e0 keep (cursor) position when exactly replacing text (#5930)
Whenever a document is changed helix maps various positions like the
cursor or diagnostics through the `ChangeSet` applied to the document.

Currently, this mapping handles replacements as follows:

* Move position to the left for `Assoc::Before` (start of selection)
* Move position to the right for `Assoc::After` (end of selection)

However, when text is exactly replaced this can produce weird results
where the cursor is moved when it shouldn't. For example if `foo` is
selected and a separate cursor is placed on each character (`s.<ret>`)
and the text is replaced (for example `rx`) then the cursors are moved
to the side instead of remaining in place.

This change adds a special case to the mapping code of replacements:
If the deleted and inserted text have the same (char) length then
the position is returned as if the replacement doesn't exist.

only keep selections invariant under replacement

Keeping selections unchanged if they are inside an exact replacement
is intuitive. However, for diagnostics this is not desirable as
helix would otherwise fail to remove diagnostics if replacing parts
of the document.
2024-08-10 00:40:34 +09:00
Michael Davis
7e85fd5b77 Add documentation for static/typable/macro commands 2024-08-10 00:39:47 +09:00
Michael Davis
b7820ee668 Disallow macro keybindings within command sequences
This is a temporary limitation because of the way that command sequences
are executed. Each command is currently executed back-to-back
synchronously, but macros are by design queued up for the compositor.
So macros mixed into a command sequence will behave undesirably: they
will be executed after the rest of the static and/or typable commands
in the sequence.

This is pending a larger refactor of how we handle commands.
<https://redirect.github.com/helix-editor/helix/issues/5555> has
further details and <https://redirect.github.com/helix-editor/helix/issues/4508>
discusses a similar problem faced by the command palette.
2024-08-10 00:39:47 +09:00
Michael Davis
1098a348aa Parse and execute macro mappable commands 2024-08-10 00:39:47 +09:00
Timothy Hutz
bb43a90b86 removed duplicate in lang-support MD file with vector dedup. (#10563) 2024-08-10 00:36:47 +09:00
Chromo-residuum-opec
9daf5c6f8b feat: add iceberg light/dark themes (#10674)
* feat: add iceberg light/dark themes

* set ui.virtual and ui.virtual.ruler

* quote ui.menu.selected key
2024-08-10 00:35:41 +09:00
Kiara Grouwstra
3b306fa022 Update languages.toml - add nixd, closes #10734 (#10767) 2024-08-10 00:35:29 +09:00
chtenb
e884daea41 Document completion menu bindings (#10994)
* Update keymap.md

* Update keymap.md

* Update keymap.md
2024-08-10 00:34:29 +09:00
Eduard Bardají Puig
779ce41a1f Provide more details on runtime directory (#11026)
* Provide more details on runtime directory

* Improve pre-built binaries description
2024-08-10 00:34:18 +09:00
Sampo Siltanen
2e90868a37 Update fsharp tree sitter repo reference (#11061)
The repository reference used here was a fork from the actual
repository, which has now been moved under ionide organization, where it is
in active maintenance and development.

The commit SHA is the currently latest commit from main branch.

The injections.scm is copied as is from the fsharp treesitter repo
[queries](https://github.com/ionide/tree-sitter-fsharp/blame/main/queries).

The locals.scm is copied from the repo and the capture names are to follow
the standard names:
- Replace @local.definition.var @local.definition.function, and @local.definition.parameter with @local.definition
- Remove (#set! "definition.function.scope" "parent")

The highlights.scm is copied as well from the fsharp
treesitter repo, but modified here to match helix highlight scopes based
on my best guesstimates. The changes made:

- Remove @spell scopes
- Split @comment into @comment.line and @comment.block
- Replace @comment.documentation with @comment.block.documentation
- Replace @character.special with @special
- Replace @variable.member with @variable.other.member
- Replace @type.definition with @type
- Replace @function.member with @function.method
- Replace @module with @namespace
- Replace @constant.macro with @function.macro
- Replace @property with @variable.other.member
- Replace @variable.member with @variable.other.member
- Replace @variable.parameter.builtin with @variable.builtin
- Replace @function.call with @function
- Replace @number with @constant.numeric.integer and @constant.numeric.float
- Replace @boolean with @constant.builtin.boolean
- Replace @keyword.conditional with @keyword.control.conditional
- Replace @keyword.return with @keyword.control.return
- Replace @keyword.repeate with @keyword.control.repeat
- Replace @keyword.import with @keyword.control.import
- Replace @keyword.modifier with @keyword.storage.modifier
- Replace @keyword.type with @keyword.storage.type
- Replace @keyword.exception with @keyword.control.exception
- Replace @module.builtin with @namespace
2024-08-10 00:34:08 +09:00
kanielrkirby
f0282689da Use try_lock in diff_handle for Diff gutter (#11092)
* Use `try_lock` in `diff_handle` for Diff gutter
- Add the method `try_load() -> Option<Diff>` to `DiffHandle`, using `try_lock` to avoid deadlocks.
- Use said method in `gutter.rs diff()`, which will use a blank `GutterFn` instead when met with a locked `Diff`.

* Revert changes

* Replace `Mutex` with `RwLock` in `Diff`

---------

Co-authored-by: Kaniel Kirby <pirate7007@runbox.com>
2024-08-10 00:32:46 +09:00
麦芽糖
aaaafb8f5f feat: add thrift hightlight (#11367) 2024-08-10 00:26:58 +09:00
Poliorcetics
68f495b023 just: Use updated grammar with recent language changes and correct highlighting (#11380) 2024-08-10 00:26:48 +09:00
lefp
8851031449 add verilog comment textobjects (#11388) 2024-08-10 00:26:34 +09:00
Val Packett
2f60c21727 Add jq language support (#11393)
jq is a language for manipulating JSON data: https://jqlang.github.io/jq/
2024-08-10 00:26:28 +09:00
David Else
931ddbb077 Update HTML highlights (#11400)
* Update HTML highlights

* Update after review comments
2024-08-10 00:26:19 +09:00
RoloEdits
f52251960a fix(picker): no longer trim search pattern (#11406) 2024-08-10 00:26:09 +09:00
Heath Stewart
d6431f41d9 Add TypeSpec support (#11412)
* Add TypeSpec support

Adds support for TypeSpec <https://typespec.io> in helix.

* Resolve PR comments

* Pull in LICENSE

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-08-10 00:25:06 +09:00
bilabila
c9c4452824 Support i3wm and sway config (#11424)
* Support i3wm and sway config

better syntax highlight and fix comment string

* typo
2024-08-10 00:24:19 +09:00
David Else
f8f056d82f dark_plus: add picker highlights, update underlined modifier syntax, and tweak a few settings (#11415) 2024-08-10 00:23:58 +09:00
Raph
ca47b3c140 Added mesonlsp as the default LSP for Meson (#11416)
* defaulted meson to JCWasmx86/mesonlsp

* generated docs for mesonlsp
2024-08-10 00:23:42 +09:00
yehor
9678c3fe60 Add .svn as workspace root marker (#11429)
* add .svn as workspace-root marker

* cargo fmt
2024-08-10 00:23:27 +09:00
Jefta
518425e055 Add commands for movement by subwords (#8147)
* Allow moving by subword
* Add tests for subword movement
2024-08-08 13:57:59 -05:00
Blaž Hrastnik
0929704699 stdx: ...and this cast is now unnecessary 2024-08-07 07:29:35 +09:00
Blaž Hrastnik
7d017d8fd6 stdx: PSID now sits under Win32::Foundation 2024-08-07 07:21:50 +09:00
Blaž Hrastnik
8f6793a181 stdx: Include all required windows-sys APIs 2024-08-07 07:18:43 +09:00
Blaž Hrastnik
6ba46e5cbf Fix crossterm compilation on macOS 2024-08-07 06:46:59 +09:00
Blaž Hrastnik
70918570a9 tui: Port improvement from ratatui on crossterm 0.28 (https://github.com/ratatui-org/ratatui/pull/1072) 2024-08-07 04:30:38 +09:00
dependabot[bot]
92a87dbc31 build(deps): bump the rust-dependencies group with 9 updates
Bumps the rust-dependencies group with 9 updates:

| Package | From | To |
| --- | --- | --- |
| [regex](https://github.com/rust-lang/regex) | `1.10.5` | `1.10.6` |
| [dunce](https://gitlab.com/kornelski/dunce) | `1.0.4` | `1.0.5` |
| [serde_json](https://github.com/serde-rs/json) | `1.0.121` | `1.0.122` |
| [toml](https://github.com/toml-rs/toml) | `0.8.16` | `0.8.19` |
| [crossterm](https://github.com/crossterm-rs/crossterm) | `0.27.0` | `0.28.1` |
| [tempfile](https://github.com/Stebalien/tempfile) | `3.10.1` | `3.11.0` |
| [serde_repr](https://github.com/dtolnay/serde-repr) | `0.1.12` | `0.1.19` |
| [which](https://github.com/harryfei/which-rs) | `6.0.1` | `6.0.2` |
| [windows-sys](https://github.com/microsoft/windows-rs) | `0.52.0` | `0.59.0` |

Updates `regex` from 1.10.5 to 1.10.6
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.10.5...1.10.6)

Updates `dunce` from 1.0.4 to 1.0.5
- [Commits](https://gitlab.com/kornelski/dunce/compare/v1.0.4...v1.0.5)

Updates `serde_json` from 1.0.121 to 1.0.122
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.121...v1.0.122)

Updates `toml` from 0.8.16 to 0.8.19
- [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.16...toml-v0.8.19)

Updates `crossterm` from 0.27.0 to 0.28.1
- [Release notes](https://github.com/crossterm-rs/crossterm/releases)
- [Changelog](https://github.com/crossterm-rs/crossterm/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crossterm-rs/crossterm/commits)

Updates `tempfile` from 3.10.1 to 3.11.0
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.10.1...v3.11.0)

Updates `serde_repr` from 0.1.12 to 0.1.19
- [Release notes](https://github.com/dtolnay/serde-repr/releases)
- [Commits](https://github.com/dtolnay/serde-repr/compare/0.1.12...0.1.19)

Updates `which` from 6.0.1 to 6.0.2
- [Release notes](https://github.com/harryfei/which-rs/releases)
- [Changelog](https://github.com/harryfei/which-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/harryfei/which-rs/compare/6.0.1...6.0.2)

Updates `windows-sys` from 0.52.0 to 0.59.0
- [Release notes](https://github.com/microsoft/windows-rs/releases)
- [Commits](https://github.com/microsoft/windows-rs/compare/0.52.0...0.59.0)

---
updated-dependencies:
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: dunce
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: toml
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: crossterm
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: tempfile
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: serde_repr
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: which
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: windows-sys
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-07 04:27:05 +09:00
dependabot[bot]
6d123aa549 build(deps): bump bitflags from 1.3.2 to 2.6.0
Bumps [bitflags](https://github.com/bitflags/bitflags) from 1.3.2 to 2.6.0.
- [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.6.0)

---
updated-dependencies:
- dependency-name: bitflags
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-07 04:20:20 +09:00
Philip Giuliani
b8c968fe47 Update Gleam tree sitter to support label shorthand syntax (#11427) 2024-08-07 04:16:44 +09:00
André Carneiro
0a4432b104 Add statusline errors when nothing is selected with s, K, A-K (#11370) 2024-08-02 21:04:19 +09:00
RoloEdits
cfe80acb6f output stderr in :sh popup if shell commands fail (#11239)
* refactor(commands): output `stderr` in `:sh` popup

* refactor(commands): switch to `from_utf8_lossy`

This way something is always displayed.

* refactor: no longer log stderr output on failure
2024-08-01 01:29:14 +02:00
TheoCorn
63953e0b9e fix :move panic when starting a new language server (#11387)
* fix move panic

* change location of is initialized check
2024-08-01 06:40:00 +09:00
RoloEdits
86aecc96a1 chore: clean up clippy lints (#11377)
Using clippy 1.80.0. Also cleans up some that were windows only.
2024-08-01 06:39:46 +09:00
Pascal Kuthe
3fcf168c33 Merge pull request #11355 from helix-editor/helix-lsp-types
Vendor `lsp-types`
2024-07-31 02:02:15 +02:00
Erasin Wang
b19551b11b Updated Godot support (#11235)
- update gdscript highlights
- add godot-resource textobjects
2024-07-31 05:52:47 +09:00
Andrew Chou
a4cfcff284 update language configuration for Tcl (#11236)
The primary executable that comes with Tcl is `tclsh`. Not really sure what `tclish` is, as I initially thought it was a typo. However, there seems to be references to it based on a quick search (e.g. [here](https://wiki.tcl-lang.org/page/Tclish) and [here](https://tclish.sourceforge.net/)), so maybe it's a valid executable that I just haven't been aware of. I was hesitant to replace it and instead opted to just add `tclsh`.
2024-07-31 05:52:36 +09:00
Michael Davis
22c1a40725 Fix finding injection layer in tree cursor with nested layers (#11365)
The `take_while` should limit the layers to those that can match the
input range so we don't always scan the entire `injection_layers`. We
can limit `depth == 1` layers to those that start before the search
`end`. Deeper layers overlap with shallower layers though so we need
to allow those layers as well in the `take_while`.

For example

```vue
<script setup lang="ts">
const foo = 'bar'.match(/foo/);
const bar = foo;
</script>
```

L2 and L3 are a typescript layer and the `/foo/` part is a small regex
layer. If you used `A-o` before the regex layer you would select the
entire typescript layer. The search in `layer_id_containing_byte_range`
would not consider the typescript layer since the regex layer comes
earlier in `injection_ranges` and that layer's start is after `end`.
The regex layer has a depth of `2` though so the change in this commit
allows scanning through that layer.

Co-authored-by: Pascal Kuthe <pascalkuthe@pm.me>
2024-07-31 05:29:31 +09:00
dependabot[bot]
ce809fb9ef build(deps): bump the rust-dependencies group with 6 updates (#11371) 2024-07-29 21:10:47 -05:00
麦芽糖
08ac37d295 Add theme keys for the picker header area (#11343)
* feat: pertty header

* 更新 themes.md

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-07-29 16:52:15 +02:00
Pascal Kuthe
8e041c99df stable sort lsp edits (#11357) 2024-07-29 06:22:28 +09:00
Skyler Hawthorne
fa13b2bd0d reduce log noise on file writes (#11361) 2024-07-28 15:59:21 -05:00
dnaq
2a2bc79335 Remove unnecessary .as_mut() call and fix log messages (#11358)
These are changes that fell out of commit:
d7a3cdea65ef321d53b8dc8417175781b5272049
2024-07-28 19:30:07 +02:00
lynn pepin
29439116b8 Documented ulimit fix for error during integration tests (#11356) 2024-07-28 18:40:50 +02:00
dnaq
f5950196d9 Fix panic when starting helix tutor (#11352)
Closes #11351

Also fixed some minor issues related to log
message contents, and removed unnecessary use
of `.as_mut()` as per code review comments on
the PR.
2024-07-28 18:29:26 +02:00
Michael Jones
fade4b218c new theme named ao (#11063)
* new theme named ao

* Update runtime/themes/ao.toml

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-07-28 17:23:46 +02:00
Poliorcetics
9e55e8a416 contrib: nushell: also complete available languages with --health (#11346) 2024-07-28 16:52:20 +02:00
Michael Davis
af2ac551ba Resolve unclosed HTML tag doc warning 2024-07-28 10:41:29 -04:00
Michael Davis
981e5cd737 helix-lsp-types: Resolve clippy lints in tests 2024-07-28 10:41:29 -04:00
Michael Davis
3963969b89 'cargo fmt' 2024-07-28 10:41:29 -04:00
Michael Davis
e21e4eb825 Replace lsp-types in helix-lsp with helix-lsp-types 2024-07-28 10:41:29 -04:00
Michael Davis
7793031aa6 Rename lsp-types crate to helix-lsp-types 2024-07-28 10:41:29 -04:00
Michael Davis
1ccdc55db9 Add helix-lsp-types to workspace 2024-07-28 10:41:29 -04:00
Michael Davis
2900bc03cf Vendor the lsp-types crate 2024-07-28 10:41:28 -04:00
RoloEdits
6eae846197 feat(languages): update just grammar and queries (#11306)
* feat(languages): update `just` grammar and queries

Bump the

* refactor(syntax): inject shebang by id not name

---------

Co-authored-by: Trevor Gross <tmgross@umich.edu>
2024-07-28 15:54:10 +02:00
Michael Davis
ae72a1dc42 Tombstone LSP clients stopped with :lsp-stop
We use the empty vec in `inner_by_name` as a tombstone value. When the
vec is empty `get` should not automatically restart the server.
2024-07-28 22:16:39 +09:00
Michael Davis
59429e18d6 Lower log level for message about removing clients from the registry
Servers stopped with `:lsp-stop` will show this message when the server
exits. If the client isn't in the registry there isn't any work to do
to remove it so this branch is benign.
2024-07-28 22:16:39 +09:00
Skyler Hawthorne
face6a3268 Disable hard link integration test on Android
Non-rooted Android typically doesn't have permission to use hard links
at all, so this test fails on Android.
2024-07-27 22:34:41 -04:00
Pascal Kuthe
30fb63cc3d Update helix-core/Cargo.toml
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-07-28 03:29:52 +01:00
Pascal Kuthe
2824e692a7 lock unicode width
Cargo automatically pumbs the patch version when installed with `cargo install`
without the locked flag which creates weird rendering artifacts
2024-07-28 03:29:52 +01:00
Kirawi
e5372b04a1 Fix writing hardlinks (#11340)
* don't use backup files with hardlinks

* check if the inodes remain the same in the test

* move funcs to faccess and use AsRawHandle

* use a copy as a backup for hardlinks

* delete backup after copy
2024-07-27 12:21:52 -05:00
Nikolay Minaev
0813147b97 Use fs' mtime to avoid saving problem on out-of-synced network fs (#11142)
In the case of network file systems, if the server time is ahead
of the local system time, then helix could annoy with messages
that the file has already been modified by another application.
2024-07-27 10:47:23 -05:00
Remo Senekowitsch
229784ccc7 Improve scrolloff behavior (#11323)
* Allow perfect centering of cursor

* Fix horizontal scrolloff

* Fix copypasta in comment
2024-07-26 17:20:33 +02:00
Michael Davis
a1e20a3426 Reorganize Document::apply_impl (#11304)
These changes are ported from
<https://redirect.github.com/helix-editor/helix/pull/9801>. It's a
cleanup of `Document::apply_impl` that uses some early returns to
reduce nesting and some reordering of the steps. The early returns
bail out of `apply_impl` early if the transaction fails to apply or
if the changes are empty (in which case we emit the SelectionDidChange
event). It's a somewhat cosmetic refactor that makes the function easier
to reason about but it also makes it harder to introduce bugs by mapping
positions through empty changesets for example.

Co-authored-by: Pascal Kuthe <pascalkuthe@pm.me>
2024-07-26 09:32:02 +02:00
Damir Vandic
9b65448f53 Fix example query in pickers.md (#11322)
Co-authored-by: Pascal Kuthe <pascalkuthe@pm.me>
2024-07-25 16:23:08 -05:00
Jimmy Zelinskie
5e945c327f languages: add mdx to markdown filetypes (#11122) 2024-07-25 23:22:35 +02:00
dependabot[bot]
d48b6904f2 build(deps): bump gix-attributes from 0.22.2 to 0.22.3 (#11318)
Bumps [gix-attributes](https://github.com/Byron/gitoxide) from 0.22.2 to 0.22.3.
- [Release notes](https://github.com/Byron/gitoxide/releases)
- [Changelog](https://github.com/Byron/gitoxide/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Byron/gitoxide/compare/gix-attributes-v0.22.2...gix-attributes-v0.22.3)

---
updated-dependencies:
- dependency-name: gix-attributes
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-25 21:41:53 +02:00
karei
f34dca797c Add support for jjdescription files (#11271) 2024-07-25 23:12:55 +09:00
Luca Saccarola
ef4a4ff3c5 Make bash completion behave normally (#11246) 2024-07-24 18:25:25 +02:00
Ryan Roden-Corrent
5d3f05cbe1 Document use of filter columns in pickers (#11218)
* Document use of filter columns in pickers.

Filtering on columns was implemented in #9647.
The only documentation I could find on this feature
was the PR itself, and the video demo used a different syntax.

* Note that column filters are space-separated.

* Note that picker filters can be abbreviated.

* Specify correct picker in docs.

* Clarify picker filter prefix shortenting.

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Move picker docs to their own section.

* Update book/src/pickers.md

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Improve docs on picker registers, keybinds, and syntax.

* Clarify wording around picker queries.

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

---------

Co-authored-by: Ryan Roden-Corrent <ryan@rcorre.net>
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-07-24 18:25:00 +02:00
RoloEdits
7c5e5f4e41 fix(lsp): find_completion_range off-by-one (#11266) 2024-07-24 10:34:20 -05:00
1adept
9d21b8fa85 just module extension (#11286)
Co-authored-by: adept <adept@noreply.codeberg.org>
2024-07-24 16:34:34 +02:00
Rich Robinson
182b26bebc Fix typos in 2-character label jump Tutor entry (#11298) 2024-07-24 16:14:46 +02:00
JR
4c1835504b Add tutor entry about 2-character label jump (#11273)
* Add tutor entry about 2-character label jump

* Move gw tutor to chapter 9

* Do not explicitely say which labels are shown following gw
2024-07-23 21:49:22 +02:00
Ingrid
1d0a3d49d3 Consistently maintain view position (#10559)
* replicate t-monaghan's changes

* remove View.offset in favour of Document.view_data.view_position

* improve access patterns for Document.view_data

* better borrow checker wrangling with doc_mut!()

* reintroduce ensure_cursor_in_view in handle_config_events

since we sorted out the borrow checker issues using partial borrows,
there's nothing stopping us from going back to the simpler implementation

* introduce helper functions on Document .view_offset, set_view_offset

* fix rebase breakage
2024-07-23 19:54:00 +02:00
dependabot[bot]
0d62656c98 build(deps): bump the rust-dependencies group with 5 updates (#11281)
Bumps the rust-dependencies group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [thiserror](https://github.com/dtolnay/thiserror) | `1.0.62` | `1.0.63` |
| [toml](https://github.com/toml-rs/toml) | `0.8.14` | `0.8.15` |
| [tokio](https://github.com/tokio-rs/tokio) | `1.38.0` | `1.38.1` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.1.5` | `1.1.6` |
| [libloading](https://github.com/nagisa/rust_libloading) | `0.8.4` | `0.8.5` |


Updates `thiserror` from 1.0.62 to 1.0.63
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.62...1.0.63)

Updates `toml` from 0.8.14 to 0.8.15
- [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.14...toml-v0.8.15)

Updates `tokio` from 1.38.0 to 1.38.1
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.38.0...tokio-1.38.1)

Updates `cc` from 1.1.5 to 1.1.6
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.5...cc-v1.1.6)

Updates `libloading` from 0.8.4 to 0.8.5
- [Commits](https://github.com/nagisa/rust_libloading/compare/0.8.4...0.8.5)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: toml
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: libloading
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-23 17:05:34 +02:00
Michael Davis
86795a9dc7 Return document display name from the '%' special register (#11275) 2024-07-23 06:56:26 +09:00
karei
d47e085fe0 Revert kanagawa diff colour change from #11187 (#11270) 2024-07-23 06:54:52 +09:00
Hamir Mahal
f5231196bc fix: usage of node12 which is deprecated (#11277)
* chore: changes from formatting on save

* fix: usage of `node12 which is deprecated`
2024-07-22 20:23:16 +02:00
Trevor Gross
70a9477ec8 Add :mv as an alias for :move (#11256)
`mv` is the familiar shell command to move or rename a file. Add this to
Helix as an alias for `:move`.
2024-07-22 16:55:12 +02:00
Poliorcetics
6c0a7f60eb contrib: add nushell completions (#11262) 2024-07-22 09:47:27 -05:00
Michael Davis
dbaa636683 Picker: Skip dynamic query debounce for pastes (#11211)
Pastes are probably the last edit one means to make before the query
should run so it doesn't need to be debounced.
This makes global search much snappier for example when accepting the
history suggestion from the '/' register or pasting a pattern from the
clipboard or a register.
2024-07-19 17:44:55 +09:00
Tobias Hunger
748a9cf022 tree-sitter: Update SHA of parser fro the slint language (#11224)
There has been a new release with a few minor tweaks to the parser. The queries
are fine still.
2024-07-18 23:10:10 +09:00
Michael Davis
b927985cd0 global_search: Save only the primary query to the history register (#11216)
Two changes from the parent commit:

* Save only the `Picker::primary_query` - so you don't save other parts
  of the query, for example `%path foo.rs` while in `global_search`.
* Move the saving out of the `if let Some(option) = self.selection()`
  block. So when you hit enter you save to history whether you have a
  selection or not. If you want to close the picker without saving to
  the register you can use C-c or Esc instead.
2024-07-18 11:08:39 +09:00
Michael Davis
c9d829a26d global_search: Save search when accepting an option (#11209)
The Prompt is set up to push the current line to history when hitting
Enter but the Picker doesn't pass the Enter event down to the Prompt
(for good reason: we don't want the Prompt's behavior of changing
completions when we hit a path separator). We should save the Prompt's
line to its configured history register when hitting Enter when there
is a selection in the Picker.

This currently only applies to `global_search`'s Picker since it's the
only Picker to use `Picker::with_history_register`.
2024-07-17 22:41:57 +09:00
karei
bd5e893149 Bring kanagawa colours better in line with neovim version (#11187)
- Fixes some colours not matching their counterpart in neovim.
- Adds `ui.debug` colours
- Fix for separators in inactive statuslines
2024-07-17 16:36:01 +09:00
irkill
72e0f6301b Fix a typo in the tutor (#11201) 2024-07-17 16:34:41 +09:00
Michael Davis
22a051408a Update release docs (#11182)
These haven't been updated in a little while. The original plan was to
update the version (in `Cargo.toml`) after a release to the next
planned release date but the way we release now is to update the version
as a part of the release process (just before tagging). Typically this
is all taken care of in the CHANGELOG-updating branch along with the
other documentation changes like the appdata file. The workflow now is
basically just to merge the changelog/release branch, pull, tag and push.
2024-07-16 12:31:29 +09:00
Leandro Braga
aac81424cd Fix select_all_children command (#11195) 2024-07-16 12:30:45 +09:00
RoloEdits
535351067c fix(commands): change pipe-like output trimming (#11183) 2024-07-16 12:29:44 +09:00
Adam Perkowski
850c9f691e Fixed headings (# / ##) to match other docs (#11192) 2024-07-16 12:29:00 +09:00
dependabot[bot]
884b53c767 build(deps): bump the rust-dependencies group with 3 updates (#11194)
Bumps the rust-dependencies group with 3 updates: [thiserror](https://github.com/dtolnay/thiserror), [open](https://github.com/Byron/open-rs) and [cc](https://github.com/rust-lang/cc-rs).


Updates `thiserror` from 1.0.61 to 1.0.62
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.61...1.0.62)

Updates `open` from 5.2.0 to 5.3.0
- [Release notes](https://github.com/Byron/open-rs/releases)
- [Changelog](https://github.com/Byron/open-rs/blob/main/changelog.md)
- [Commits](https://github.com/Byron/open-rs/compare/v5.2.0...v5.3.0)

Updates `cc` from 1.0.106 to 1.1.5
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.106...cc-v1.1.5)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: open
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-16 12:28:41 +09:00
Masanori Ogino
6b947518c6 Regenerate documentation (#11196) 2024-07-16 12:27:45 +09:00
jyn
b0cf86d31b add :edit and :e as aliases for :open (#11186)
Vim supports these, and i can't think of any reason helix would want to have a different meaning for `:edit` than `:open`.

docs: https://vimhelp.org/editing.txt.html#%3Aedit
2024-07-15 21:39:05 +02:00
Blaž Hrastnik
107cdf3e43 Merge pull request #6417 from pascalkuthe/inline-diagnostics 2024-07-16 00:28:34 +09:00
Pascal Kuthe
386fa371d7 gracefully handle lack of tokio runtime 2024-07-15 16:36:33 +02:00
Pascal Kuthe
7283ef881f only show inline diagnostics after a delay 2024-07-15 16:36:29 +02:00
Pascal Kuthe
d8a115641d fix scrolling/movement for multiline virtual text 2024-07-15 16:35:31 +02:00
Pascal Kuthe
a17b008b42 ignore empty virtual text layers 2024-07-15 16:35:31 +02:00
Pascal Kuthe
3abc07a79e use correct position for cursor in doc popup 2024-07-15 16:35:31 +02:00
Pascal Kuthe
7e133167ca remove redudant/incorrect view bound check 2024-07-15 16:35:30 +02:00
Pascal Kuthe
6d051d7084 render diagnostic inline 2024-07-15 16:35:30 +02:00
Pascal Kuthe
39b3d81abf stable sort diagnostics to avoid flickering 2024-07-15 16:35:30 +02:00
Pascal Kuthe
839f4d758d fix typo in doc_formatter.rs 2024-07-15 16:35:30 +02:00
Pascal Kuthe
2c0506aa96 streamline text decoration API
This commit brings the text decoration API inline with the
LineAnnotation API (so they are consistent) resulting in a single
streamlined API instead of multiple ADHOK callbacks.
2024-07-15 16:35:26 +02:00
Pascal Kuthe
9a93240d27 correctly wrap at text-width 2024-07-15 16:34:14 +02:00
Pascal Kuthe
4c7cdb8fea Improve line annotation API
The line annotation as implemented in #5420 had two shortcomings:
* It required the height of virtual text lines to be known ahead time
* It checked for line anchors at every grapheme

The first problem made the API impractical to use in practice because
almost all virtual text needs to be softwrapped. For example inline
diagnostics should be softwrapped to avoid cutting off the diagnostic
message (as no scrolling is possible). While more complex virtual text
like side by side diffs must dynamically calculate the number of empty
lines two align two documents (which requires taking account both
softwrap and virtual text). To address this, the API has been
refactored to use a trait.

The second issue caused some performance overhead and unnecessarily
complicated the `DocumentFormatter`. It was addressed by only calling
the trait mentioned above at line breaks (instead of always). This
allows offers additional flexibility to annotations as it offers
the flexibility to align lines (needed for side by side diffs).
2024-07-15 16:34:14 +02:00
Pascal Kuthe
e15626a00a track char_idx in DocFormatter 2024-07-15 16:34:13 +02:00
Pascal Kuthe
2023445a08 ensure highlight scopes are skipped properly 2024-07-15 16:34:13 +02:00
Pascal Kuthe
22dfad605a implement Add/Sub for position
being able to add/subtract positions is very handy when writing rendering code
2024-07-15 16:34:10 +02:00
Blaž Hrastnik
08ee8b9443 Merge pull request #9647 from helix-editor/pickers-v2
`Picker`s "v2"
2024-07-15 23:30:58 +09:00
Michael Davis
9de5f5cefa Picker: Highlight the currently active column
We can track the ranges in the input text that correspond to each column
and use this information during rendering to apply a new theme key that
makes the "active column" stand out. This makes it easier to tell at
a glance which column you're entering.
2024-07-15 10:03:35 -04:00
FlorianNAdam
6345b78409 Keep editor from switching to normal mode when loading a Document (#11176) 2024-07-15 22:48:37 +09:00
Michael Davis
a7777b3c11 Accept 'IntoIterator<Item = Column<T, D>>' for picker columns
This allows us to replace any `vec![..]`s of columns where all columns
are static with static slices `[..]`.
2024-07-15 09:31:33 -04:00
Michael Davis
009bbdaf8d Picker: Reset the cursor on prompt change 2024-07-15 09:31:33 -04:00
Michael Davis
8555248b01 Accept 'IntoIterator<Item = T>' for Picker::new options
`Picker::new` loops through the input options to inject each of them, so
there's no need to collect into an intermediary Vec. This removes some
unnecessary collections. Also, pickers that start with no initial
options can now pass an empty slice instead of an empty Vec.

Co-authored-by: Luis Useche <useche@gmail.com>
2024-07-15 09:31:33 -04:00
Michael Davis
3906f6605f Avoid allocations in Picker file preview callback
The `FileLocation` and `PathOrId` types can borrow paths rather than
requiring them to be owned. This takes a refactor of the preview
functions and preview internals within `Picker`. With this change we
avoid an unnecessary `PathBuf` clone per render for any picker with a
file preview function (i.e. most pickers).

This refactor is not fully complete. The `PathOrId` is _sometimes_ an
owned `PathBuf`. This is for pragmatic reasons rather than technical
ones. We need a further refactor to introduce more core types like
`Location` in order to eliminate the Cow and only use `&Path`s within
`PathOrId`. This is left for future work as it will be a larger refactor
almost entirely fitting into the LSP commands module and helix-core -
i.e. mostly unrelated to refactoring the `Picker` code itself.

Co-authored-by: Pascal Kuthe <pascalkuthe@pm.me>
2024-07-15 09:31:33 -04:00
Michael Davis
f4a433f855 Convert LSP URIs into custom URIs
This introduces a custom URI type in core meant to be extended later
if we want to support other schemes. For now it's just a wrapper over a
PathBuf. We use this new URI type to firewall `lsp::Url`. This was
previously done in 8141a4a but using a custom URI type is more flexible
and will improve the way Pickers handle paths for previews in the child
commit(s).

Co-authored-by: soqb <cb.setho@gmail.com>
2024-07-15 09:31:33 -04:00
Pascal Kuthe
408282097f avoid collecting columns to a temporary vec 2024-07-15 09:31:33 -04:00
Michael Davis
6ccbfe9bdf Request a UI redraw on Drop of an Injector
This fixes the changed files picker when used against a clean worktree
for example. Without it the running indicator does not disappear. It
also simplifies the dynamic query handler's implementation so that it
doesn't need to request a redraw explicitly.

Co-authored-by: Pascal Kuthe <pascalkuthe@pm.me>
2024-07-15 09:31:33 -04:00
Michael Davis
6492f17e7d Add a hidden column for the global search line contents
We could expand on this in the future to have different preview modes
that you can toggle between with C-t. Currently that binding just hides
the preview but it could switch between different preview modes and in
one mode hide the path and just show the line contents.
2024-07-15 09:31:32 -04:00
Michael Davis
7b1131adf6 global_search: Suggest latest '/' register value 2024-07-15 09:31:32 -04:00
Michael Davis
1d023b05ac Refactor global_search as a dynamic Picker 2024-07-15 09:31:32 -04:00
Michael Davis
5622db6798 Remove sym_picker helper fun
The parent commit split out the workspace symbol picker to an inline
definition so the `workspace` parameter is never passed as `true`. We
should consolidate this picker definition into the symbol_picker
function.
2024-07-15 09:31:32 -04:00
Michael Davis
9e31ba5475 Consolidate DynamicPicker into Picker
DynamicPicker is a thin wrapper over Picker that holds some additional
state, similar to the old FilePicker type. Like with FilePicker, we want
to fold the two types together, having Picker optionally hold that
extra state.

The DynamicPicker is a little more complicated than FilePicker was
though - it holds a query callback and current query string in state and
provides some debounce for queries using the IdleTimeout event.
We can move all of that state and debounce logic into an AsyncHook
implementation, introduced here as `DynamicQueryHandler`. The hook
receives updates to the primary query and debounces those events so
that once a query has been idle for a short time (275ms) we re-run
the query.

A standard Picker created through `new` for example can be promoted into
a Dynamic picker by chaining the new `with_dynamic_query` function, very
similar to FilePicker's replacement `with_preview`.

The workspace symbol picker has been migrated to the new way of writing
dynamic pickers as an example. The child commit will promote global
search into a dynamic Picker as well.
2024-07-15 09:31:32 -04:00
Michael Davis
11f809c177 Bump nucleo to v0.4.1
We will use this in the child commit to improve the picker's running
indicator. Nucleo 0.4.0 includes an `active_injectors` member that we
can use to detect if anything can push to the picker. When that count
drops to zero we can remove the running indicator.

Nucleo 0.4.1 contains a fix for crashes with interactive global search
on a large directory.
2024-07-15 09:31:32 -04:00
Michael Davis
2c9f5b3efb Implement Error for InjectorShutdown 2024-07-15 09:31:32 -04:00
Michael Davis
53ac833efb Replace picker shutdown bool with version number
This works nicely for dynamic pickers: we stop any running jobs like
global search that are pushing to the injector by incrementing the
version number when we start a new request. The boolean only allowed
us to shut the picker down once, but with a usize a picker can have
multiple "sessions" / "life-cycles" where it receives new options
from an injector.
2024-07-15 09:31:32 -04:00
Michael Davis
385b398808 Add column configurations for existing pickers
This removes the menu::Item implementations for picker item types and
adds `Vec<Column<T, D>>` configurations.
2024-07-15 09:31:32 -04:00
Michael Davis
c4c17c693d Add a special query syntax for Pickers to select columns
Now that the picker is defined as a table, we need a way to provide
input for each field in the picker. We introduce a small query syntax
that supports multiple columns without being too verbose. Fields are
specified as `%field pattern`. The default column for a picker doesn't
need the `%field` prefix. The field name may be selected by a prefix
of the field, for example `%p foo.rs` rather than `%path foo.rs`.

Co-authored-by: ItsEthra <107059409+ItsEthra@users.noreply.github.com>
2024-07-15 09:31:31 -04:00
Michael Davis
f40fca88e0 Refactor Picker in terms of columns
`menu::Item` is replaced with column configurations for each picker
which control how a column is displayed and whether it is passed to
nucleo for filtering. (This is used for dynamic pickers so that we can
filter those items with the dynamic picker callback rather than nucleo.)

The picker has a new lucene-like syntax that can be used to filter the
picker only on certain criteria. If a filter is not specified, the text
in the prompt applies to the picker's configured "primary" column.

Adding column configurations for each picker is left for the child
commit.
2024-07-15 09:31:31 -04:00
Michael Davis
dae3841a75 Use an AsyncHook for picker preview highlighting
The picker previously used the IdleTimeout event as a trigger for
syntax-highlighting the currently selected document in the preview pane.
This is a bit ad-hoc now that the event system has landed and we can
refactor towards an AsyncHook (like those used for LSP completion and
signature-help). This should resolve some odd scenarios where the
preview did not highlight because of a race between the idle timeout
and items appearing in the picker.
2024-07-15 09:31:31 -04:00
Emran Ramezan
702a96d417 Update highlights.scm and injections.scm for blade.php files (#11138)
* Update highlights.scm for blade.php files

* Update injections.scm to add tree-sitter-comment injection

* Fixed the injection issues  regarding blade parameters
2024-07-15 22:29:14 +09:00
Masanori Ogino
7f77d95c79 Inject the comment grammar into Hare (#11173) 2024-07-15 22:28:23 +09:00
arcofx
1bad3b0dd4 Make format_selections respect document configuration (#11169) 2024-07-15 22:27:42 +09:00
Blaž Hrastnik
079f544260 Adjust the ruler color of the default theme 2024-07-15 01:19:09 +09:00
Michael Davis
b2cc7d8fea Add changelog notes for 24.07 (#10731)
* Changelog 2024-05-02

checkpoint: 31273c69e0

* Changelog 2024-05-06

checkpoint: 61818996c6

* Changelog 2024-05-11

checkpoint: 00e9e5eade

* Bump version to 24.05

* Add 24.05 release to AppImage metadata

* Fix release number in changelog

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>

* Update release numbers to 24.07

* Changelog 2024-06-15

* Changelog 2024-07-14

checkpoint: c9b484097b

* Linkify

---------

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2024-07-15 01:17:49 +09:00
Masanori Ogino
c9b484097b Exclude EOL repos from the Repology badge (#11159) 2024-07-14 11:31:33 +09:00
eh
e6bf97b843 Theme: Kanagawa Dragon (#10172)
Implements the Dragon variant of the Kanagawa theme.
https://github.com/rebelot/kanagawa.nvim?tab=readme-ov-file
2024-07-14 03:01:58 +09:00
Michael Davis
44d2fc2ab3 Commit an undo checkpoint before each write (#11062)
This fixes the modification indicator when saving from insert mode with
a config such as

    [keys.insert]
    C-s = ":write"

Previously the modification indicator would be stuck showing modified
even if the buffer contents matched the disk contents when writing after
some changes in insert mode with this binding. In insert mode we do not
eagerly write undo checkpoints so that all changes made become one
checkpoint as you exit insert mode. When saving, `Document`s `changes`
`ChangeSet` would be non-empty and when there are changes we show the
buffer as modified. Then switching to normal mode would append the
changes to history, bumping the current revision past what it was when
last saved. Since the last saved revision and current revision were then
unsynced, the modification indicator would always show modified.

This matches [Kakoune's behavior]. Kakoune has a different architecture
for writes but a very similar system for history, transactions and undo
checkpoints (what it calls "undo groups"). Upon saving Kakoune creates
an undo checkpoint if there are any uncommitted changes. It does this
after the write has gone through since its writing system is different.
For our writing system it's cleaner to make the undo checkpoint before
performing the save so that the history revision increments before we
send the save event.

[Kakoune's behavior]: 80fcfebca8/src/buffer.cc (L565-L566)
2024-07-14 02:59:47 +09:00
Lukas Grassauer
35f1c2a55f Update tree-sitter-todotxt (#11097)
Update to latest commit that allows any non-whitespace character for projects, and contexts.
2024-07-14 02:59:21 +09:00
David Else
928e3f0d85 Add regex injections into bash (#11112) 2024-07-14 02:59:07 +09:00
Masanori Ogino
ec0bdb3976 Update Hare grammar (#11130)
This change uses <https://git.sr.ht/~ecs/tree-sitter-hare/> that is
up-to-date and linked from the official documentation.
2024-07-14 02:58:22 +09:00
Antonin
b0f3fe7556 Include .yml files in Helm chart templates (#11135) 2024-07-14 02:58:06 +09:00
RoloEdits
fd7b1a3e37 refactor(commands): trim end of pipe-like output (#10952) 2024-07-13 10:44:48 +09:00
David Else
a75b1cf51e Fix ZSH completions (#11133) 2024-07-12 11:55:10 +09:00
David Else
501af93c92 Documentation: Convert links in the .desktop file to absolute paths (#11115) 2024-07-12 03:16:55 +02:00
Branch Vincent
2d1ac0f699 Add {pdm,uv}.lock, git/ignore, npmrc to languages (#11131) 2024-07-12 03:15:40 +02:00
David Else
8229a40da8 Add space back to main text in the tutor after chapter 11 (#11117) 2024-07-11 15:47:49 +09:00
David Else
9d75385062 Update ZSH completions (#11120) 2024-07-11 09:06:50 +09:00
baiyang1919813
649bd4501e Add basedpyright langserver (#11121) 2024-07-10 19:28:11 +02:00
Yuntao Zhao
86982ab33c feat: improve hx fish completion (#10853)
* feat: improve hx fish completion

- add -w and --working-dir options
- shorten option description
- dynamically call hx --health

* feat: improve health check completion

- remove header
- remove check/x characters

* feat: use hx --health languages in completion
2024-07-10 12:41:12 +09:00
Michael Davis
15a26b87c9 Expand tilde for selected paths in goto_file (#10964)
Previously `gf` on `~/.config/helix` for example would error if the
entire path was selected but succeed and open a picker for the directory
contents if the selection was one one-width cursor. We need to expand
tildes for all paths instead of just the auto-detected paths.

This also refactors the `goto_file` blocks a little so that we construct
`paths` once instead of creating the Vec and immediately clearing it
when the selection is one single-width cursor.
2024-07-10 12:40:43 +09:00
q
bfb7023656 Update fleet_dark.toml (#11046) 2024-07-10 12:40:03 +09:00
kanielrkirby
86e4b51416 Add changes for undo in insert mode (#11090)
* Add changes before insert mode undo
Fixes #11077

* Address edge cases for undo like Kakoune does

---------

Co-authored-by: Kaniel Kirby <pirate7007@runbox.com>
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-07-10 12:38:50 +09:00
David Else
71df2428ee Fix heredoc and add ansi_c_string highlights in bash queries (#11118) 2024-07-10 12:37:25 +09:00
dependabot[bot]
348c0ebeb4 build(deps): bump the rust-dependencies group with 5 updates (#11113)
Bumps the rust-dependencies group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [serde](https://github.com/serde-rs/serde) | `1.0.203` | `1.0.204` |
| [imara-diff](https://github.com/pascalkuthe/imara-diff) | `0.1.5` | `0.1.6` |
| [clipboard-win](https://github.com/DoumanAsh/clipboard-win) | `5.3.1` | `5.4.0` |
| [open](https://github.com/Byron/open-rs) | `5.1.4` | `5.2.0` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.0.104` | `1.0.106` |


Updates `serde` from 1.0.203 to 1.0.204
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.203...v1.0.204)

Updates `imara-diff` from 0.1.5 to 0.1.6
- [Release notes](https://github.com/pascalkuthe/imara-diff/releases)
- [Changelog](https://github.com/pascalkuthe/imara-diff/blob/master/CHANGELOG.md)
- [Commits](https://github.com/pascalkuthe/imara-diff/compare/v0.1.5...v0.1.6)

Updates `clipboard-win` from 5.3.1 to 5.4.0
- [Commits](https://github.com/DoumanAsh/clipboard-win/commits)

Updates `open` from 5.1.4 to 5.2.0
- [Release notes](https://github.com/Byron/open-rs/releases)
- [Changelog](https://github.com/Byron/open-rs/blob/main/changelog.md)
- [Commits](https://github.com/Byron/open-rs/compare/v5.1.4...v5.2.0)

Updates `cc` from 1.0.104 to 1.0.106
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.104...cc-v1.0.106)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: imara-diff
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: clipboard-win
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: open
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-09 19:40:22 +09:00
Ricardo Fernández Serrata
6997ee9151 &Option<T> -> Option<&T> (#11091)
* refactor `starting_request_args` to only `ref` non-`Copy`

* refactor `needs_recompile` to only `ref` non-`Copy`

* refactor `add_workspace_folder` to only `ref` `Some`

---------

Co-authored-by: Rudxain <rudxain@localhost.localdomain>
2024-07-09 18:34:28 +09:00
Salman Farooq
0c8d51ee36 add cursorcolumn and cursorline to base16_transparent theme (#11099) 2024-07-07 11:24:04 +09:00
Matt Armstrong
8b7c33d00d Minor improvements to comments in selection.rs (#11101) 2024-07-07 02:40:23 +09:00
Michael Davis
1fb99ec3b2 Fix language server ID type in lsp_workspace_command (#11105) 2024-07-07 02:39:55 +09:00
Schmiddiii
06d8fee048 Allow multiple language server with lsp-workspace-command (#10176)
This fix allows for multiple language servers at once which support
workspace commands. This was previously broken as just the first
language server supporting workspace commands was queried when listing
allowed worspace commands.

The fix is in two parts. Firstly, querying all workspace commands from
all language servers available and using them when actually running the
command in `lsp_workspace_command`. Secondly, doing the same in
`completers::lsp_workspace_command` such that completion still works as
expected.

The fix has one remaining issue, which I am unsure how to handle in the
best way possible, but which I also don't think should happen often:
Multiple language servers may register commands with the same name. This
will lead to that command being listed in the popup menu and in the
completion list multiple times, which can be possibly confusing. One
could disambigue them in the popover menu, but I am not sure the same
can be done for completion. When running `lsp-workspace-command` with
parameters, this behavior is "fixed" by displaying an error in that
case. I am unsure if this is the best fix for this issue in that case,
but could not find a better one.
2024-07-06 10:34:33 -05:00
Charlie Moog
fc97ecc3e3 Add hsc filetype to haskell (#11074) 2024-07-02 17:36:29 +09:00
adriaan
3524060ee8 Override far too dark cursorline (#11071) 2024-07-02 09:56:55 +09:00
Robin
64f8660d3e Tell language servers that Helix can request formatting (#11064)
Without providing the formatting capability, the language server might not advertise its ability to format in return, causing the :format command to be broken.
2024-07-02 09:42:51 +09:00
Christopher Smyth
ed761fbe7c Bump time from broken version (0.3.23) (#11065) 2024-07-02 09:38:30 +09:00
Lucas @ StarkWare
0c6ffe192b chore: update cairo tree sitter + queries (#11067) 2024-07-02 09:37:49 +09:00
dependabot[bot]
9c4c66d417 build(deps): bump the rust-dependencies group with 3 updates (#11072)
Bumps the rust-dependencies group with 3 updates: [log](https://github.com/rust-lang/log), [serde_json](https://github.com/serde-rs/json) and [cc](https://github.com/rust-lang/cc-rs).


Updates `log` from 0.4.21 to 0.4.22
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.21...0.4.22)

Updates `serde_json` from 1.0.117 to 1.0.120
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.117...v1.0.120)

Updates `cc` from 1.0.100 to 1.0.104
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.0.100...cc-v1.0.104)

---
updated-dependencies:
- dependency-name: log
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-02 09:37:33 +09:00
Mark Murphy
21fd654cc6 Fix homebrew formula link (#11058)
Co-authored-by: Mark Murphy <mail@markmurphydev.com>
2024-06-30 16:07:57 +09:00
Chris44442
c6dbb9c270 VHDL highlights.scm improvement (#10845) 2024-06-29 15:30:38 +09:00
Michael Davis
dca952c03a Delay auto-save until exiting insert mode (#11047)
Saving while in insert mode causes issues with the modification
indicator and this is very easy to reproduce with the current state of
the auto-save hook. We can tweak the hook slightly to await the mode
switch out of insert mode to perform the save.

The debounce is preserved: if you save and then immediately exit insert
mode the debounce will be respected. If the debounce lapses while you
are in insert mode, the save occurs as you switch out of insert mode
immediately.
2024-06-29 11:08:21 +09:00
Chirikumbrah
b4811f7d2e Large Gruvbox refactoring (#10773)
* gruvbox refactoring

* removed unnecessary lines

* set purple1 for operators

* changed diagnostics colors

* removed some unnecessary lines

* set diff.delta color to yellow

* removed some tag colors
2024-06-26 23:05:01 +02:00
Michael Jones
0e46f56f30 Add new color theme 'iroaseta' (#10381)
* Add new color theme 'iroaseta'

* Update runtime/themes/iroaseta.toml

Co-authored-by: postsolar <120750161+postsolar@users.noreply.github.com>

* Update iroaseta.toml

Add virtual jump label theme setting

* Update runtime/themes/iroaseta.toml

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Update iroaseta.toml

update storage. keyword.storage. according to suggestion, and update color.

* Update iroaseta.toml

remove unused palette

* Update iroaseta.toml

add missing setting for bufferline

* Update iroaseta.toml

update diagnostic fg color

* Update iroaseta.toml

I made the config more comprehensive and took all available themes settings from the manual. Some are commented out though.

* Update iroaseta.toml

add missing colors

* Update iroaseta.toml

Made some final adjustments to the color theme to improve visibility and reduce eye strain.

* Update runtime/themes/iroaseta.toml

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Update runtime/themes/iroaseta.toml

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Update iroaseta.toml

remove redundant settings

* Update iroaseta.toml

update color name

---------

Co-authored-by: postsolar <120750161+postsolar@users.noreply.github.com>
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-06-26 23:04:17 +02:00
Thomas Schafer
6ed0d0cd39 Only pluralise "buffer" when required (#11018)
* Only pluralise buffer when required

* Use == 1 instead of != 1
2024-06-26 23:03:21 +02:00
dependabot[bot]
b05ed9bf85 build(deps): bump the rust-dependencies group with 4 updates (#11032)
Bumps the rust-dependencies group with 4 updates: [bitflags](https://github.com/bitflags/bitflags), [url](https://github.com/servo/rust-url), [cc](https://github.com/rust-lang/cc-rs) and [libloading](https://github.com/nagisa/rust_libloading).


Updates `bitflags` from 2.5.0 to 2.6.0
- [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/2.5.0...2.6.0)

Updates `url` from 2.5.1 to 2.5.2
- [Release notes](https://github.com/servo/rust-url/releases)
- [Commits](https://github.com/servo/rust-url/compare/v2.5.1...v2.5.2)

Updates `cc` from 1.0.99 to 1.0.100
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/cc-rs/compare/1.0.99...cc-v1.0.100)

Updates `libloading` from 0.8.3 to 0.8.4
- [Commits](https://github.com/nagisa/rust_libloading/compare/0.8.3...0.8.4)

---
updated-dependencies:
- dependency-name: bitflags
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: url
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: libloading
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-25 23:22:20 +09:00
Ashley Vaughn
a982e5ce26 add ruler at 101 and text-width at 100 to lean in languages.toml (#10969) 2024-06-23 10:09:39 +09:00
Alejandro Gastón Alvarez
b894cf087b Add "jsonl" as filetype for JSON lang (#11004) 2024-06-23 10:08:20 +09:00
tingerrr
3706c0dc85 Add block comment tokens for typst (#10955) 2024-06-23 10:07:46 +09:00
J. Dekker
3b5f2e66fc base16_default: add styles to newer unthemed features (#10858)
* base16_default: add `ui.statusline` for `color-modes`

Signed-off-by: J. Dekker <jdek@itanimul.li>

* base16_default: add `ui.virtual` default

Previously virtual text such as LSP inlay was impossible to distinguish
from 'real' text by default.

Signed-off-by: J. Dekker <jdek@itanimul.li>

---------

Signed-off-by: J. Dekker <jdek@itanimul.li>
2024-06-23 10:07:13 +09:00
Michael Davis
44e113cb76 tree-sitter: Update parent links on reused injection layers (#10978)
When parsing injections, we skip adding a new layer if there is an
existing layer covering the same range. When doing so we did not update
the parent layer ID, so some layers could have `parent` layer IDs that
pointed to a layer that no longer existed in the `layers` HopSlotMap
which could cause a panic when using `A-o`.

To fix this we update the `parent` pointer for both newly created
injection layers and reused ones.
2024-06-23 10:06:15 +09:00
Kirawi
b55cb3aa11 Revert "Replace unicode-general-category with icu-properties (#10989)" (#11006)
This reverts commit 9b7dffbd61.
2024-06-23 10:05:53 +09:00
Kirawi
9b7dffbd61 Replace unicode-general-category with icu-properties (#10989) 2024-06-18 18:19:05 +02:00
blt-r
0edf60964d Update tree-sitter-rust (#10973)
Update to latest commit on master to include fix for a bug that doesn't
allow spaces in the shebang line.
2024-06-18 18:14:41 +02:00
TiredTumblrina
94a9c81eb0 Prevent improper files (like /dev/random) from being used as file arguments (#10733)
* Implement check before adding path to files

* fix problem where directories were removed from args.files

* Revert "Implement check before adding path to files"

This reverts commit c123944d9b.

* Dissallow opening of irregular non-symlink files

* Fixed issue with creating new file from command line

* Fixed linting error.

* Optimized regularity check as suggested in review

* Created DocumentOpenError Sum Type to switch on in Application

* Forgot cargo fmt

* Update helix-term/src/application.rs

Accept suggestion in review.

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Moved thiserror version configuration to the workspace instead of the individual packages.

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-06-18 18:14:17 +02:00
David Else
d70f58da10 Fix multiple broken links in the documentation (#10953)
* Fix multiple broken links in the documentation

* Apply code review suggestion

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-06-18 10:43:36 +02:00
Thomas Schafer
668f1239a9 Fix jump_backwards behaviour when jumplist is at capacity (#10968)
* Fix jump_backwards behaviour when jumplist is at capacity

* Decrement self.current while popping from front

* Fix issue with conflicting updates to self.current

* Realised that truncate is intentional

* Use saturating_sub when decrementing current

* Fix naming of previous jump, and remove unneeded comment change

* Remove unnecessary changes in push

* Return num elements removed from front, and use in backward method

* Hide num_removed from public interface and tidy up jump location check
2024-06-18 10:42:46 +02:00
adiabatic
69acf66cd8 Add curly single and double quotes to BRACKETS (#10971) 2024-06-18 10:40:19 +02:00
Meris Bahtijaragic
afe9049a0e improve jump colors for github_dark themes (#10946) 2024-06-18 10:39:56 +02:00
Shaun_Sheep
bc73dd19d3 Make prompt use cursor set for Insert mode (#10945)
* Resolve issue #10874

* cargo fmt
2024-06-18 10:38:56 +02:00
slawomirlech
dbacaaddca DAP: Deserialize number IDs (#10943)
* Fix deserialization of id

* Removing external dependencies

This reverts commit 27962afc16.

* Fix incorrect import

* Adding tests

* Moved tests

---------

Co-authored-by: Sławomir Lech <slawomir.lech@bluesoft.com>
2024-06-15 16:05:04 +09:00
uncenter
43cc30d225 Sync latest Catppuccin themes changes (#10954) 2024-06-15 11:34:33 +09:00
Michael Davis
8eda96de6d Downgrade unicode-width to 0.1.12 (#10963)
unicode-width 0.1.13 contains some fixes that change the widths of line
endings, which breaks some assumptions in helix-tui, causing some
rendering artifacts. We can downgrade to remove the rendering errors
for now.
2024-06-15 10:58:14 +09:00
RoloEdits
9c479e6d2d fix(editor): prevent overflow in count modifier (#10930) 2024-06-13 03:24:24 +02:00
Sebastian Poeplau
62655e97f1 Optional history for rename_symbol (#10932)
Fix #10560 by accepting an optional history register for the
rename_symbol command.
2024-06-12 16:44:47 +02:00
Lucas @ StarkWare
9123d3fbb8 feat(cairo): update tree-sitter grammar and queries (#10919)
* feat(cairo): update tree-sitter grammar and queries

* fix suggestions
2024-06-12 09:20:13 +09:00
dependabot[bot]
8a549b767b build(deps): bump the rust-dependencies group across 1 directory with 5 updates (#10926)
* build(deps): bump the rust-dependencies group across 1 directory with 5 updates

Bumps the rust-dependencies group with 5 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [unicode-width](https://github.com/unicode-rs/unicode-width) | `0.1.12` | `0.1.13` |
| [regex](https://github.com/rust-lang/regex) | `1.10.4` | `1.10.5` |
| [url](https://github.com/servo/rust-url) | `2.5.0` | `2.5.1` |
| [open](https://github.com/Byron/open-rs) | `5.1.3` | `5.1.4` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.0.98` | `1.0.99` |



Updates `unicode-width` from 0.1.12 to 0.1.13
- [Commits](https://github.com/unicode-rs/unicode-width/compare/v0.1.12...v0.1.13)

Updates `regex` from 1.10.4 to 1.10.5
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.10.4...1.10.5)

Updates `url` from 2.5.0 to 2.5.1
- [Release notes](https://github.com/servo/rust-url/releases)
- [Commits](https://github.com/servo/rust-url/compare/v2.5.0...v2.5.1)

Updates `open` from 5.1.3 to 5.1.4
- [Release notes](https://github.com/Byron/open-rs/releases)
- [Changelog](https://github.com/Byron/open-rs/blob/main/changelog.md)
- [Commits](https://github.com/Byron/open-rs/compare/v5.1.3...v5.1.4)

Updates `cc` from 1.0.98 to 1.0.99
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Commits](https://github.com/rust-lang/cc-rs/compare/1.0.98...1.0.99)

---
updated-dependencies:
- dependency-name: unicode-width
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: url
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: open
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>

* helix-tui: Use zero-width-space for zero-width grapheme test

The update of unicode-width 0.1.13 in the parent commit changed the
width of the U+1 codepoint to 1 from 0, causing the test to fail. We
can switch to a well known zero-width codepoint of U+200B to fix the
behavior.

---------

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>
2024-06-12 01:08:50 +09:00
emilylime
a64dbf825f Improve readability of virtual text with 'noctis' theme (#10910) 2024-06-11 08:16:54 -05:00
Hendrik Wolff
265608a3d8 Auto Save All Buffers After A Delay (#10899)
* auto save after delay

* configable

* clearer names

* init

* working with some odd behaviour

* working with greater consistency

* Apply reviewer suggestions

- Remove unneccessary field
- Remove blocking save

* Improve auto-save configuration

Auto save can be configured to trigger on focus loss:
```toml
auto-save.focus-lost = true|false
```

and after a time delay (in milli seconds) since last keypress:
```toml
auto-save.after-delay.enable = true|false
auto-save.after-delay.timeout = [0, u64::MAX] # default: 3000
```

* Remove boilerplate and unnecessary types

* Remove more useless types

* Update docs for auto-save.after-delay

* Fix wording of (doc) comments relating to auto-save

* book: Move auto-save descriptions to separate section

---------

Co-authored-by: Miguel Perez <miguelvojito@gmail.com>
Co-authored-by: Miguel Perez <perezoji@cs.fsu.edu>
2024-06-11 00:39:06 +02:00
Asger Juul Brunshøj
a1cda3c19e in flake mkShell default RUSTFLAGS to an empty string if unset (#10880) 2024-06-10 17:08:39 +02:00
Chris Pyles
03813bbc2e Remove special handling of line ending characters in selection replacement (#10786)
* Remove special-casing of line ending characters in selection replacement

* Refactor line ending handling and integration test to address code review comments
2024-06-10 17:07:43 +02:00
Arturs Krumins
aa1630a41a Update Swift Grammar and Queries (#10802) 2024-06-07 12:29:42 -05:00
Zoey Hewll
44504b720b add elisp support (#10644)
* add elisp support

* update queries for some constants
2024-06-07 13:02:27 +09:00
tingerrr
80e0e98e45 Add py, hs, rs and typ injection regexes (#10785)
* Add `py` as valid python injection regex

* Add `hs` and `rs` for `haskell` and `rust`

* Add `typ` injection regex for `typst`
2024-06-07 12:58:26 +09:00
Ricardo Fernández Serrata
3a03109a99 "it's" -> "its", in crossterm.rs (#10860) 2024-06-07 12:51:40 +09:00
Ryan Roden-Corrent
886d307b9e Fix logic to update version when HEAD changes. (#10896) 2024-06-07 08:24:33 +09:00
Michael Davis
6f1437e9f3 LSP: Resolve completion items when any info is missing (#10873) 2024-06-06 13:28:10 +09:00
Marty
c39cde8fc2 Flush pending writes before suspend (#10797)
* flush saves before suspending

* review suggestion

Co-authored-by: Kirawi <67773714+kirawi@users.noreply.github.com>

* review changes

---------

Co-authored-by: PotatoesFall <martyk@tuta.io>
Co-authored-by: Kirawi <67773714+kirawi@users.noreply.github.com>
2024-06-05 18:47:15 +02:00
dependabot[bot]
31bcde360c build(deps): bump toml in the rust-dependencies group (#10879)
Bumps the rust-dependencies group with 1 update: [toml](https://github.com/toml-rs/toml).


Updates `toml` from 0.8.13 to 0.8.14
- [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.13...toml-v0.8.14)

---
updated-dependencies:
- dependency-name: toml
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-04 10:28:17 +09:00
Gaëtan Lehmann
a801044152 update tree-sitter-earthfile to 0.5.3 (#10779) 2024-06-03 08:40:30 -05:00
dependabot[bot]
6dbab51f4a build(deps): bump the rust-dependencies group across 1 directory with 10 updates (#10871)
Bumps the rust-dependencies group with 10 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [serde](https://github.com/serde-rs/serde) | `1.0.201` | `1.0.203` |
| [toml](https://github.com/toml-rs/toml) | `0.8.12` | `0.8.13` |
| [parking_lot](https://github.com/Amanieu/parking_lot) | `0.12.2` | `0.12.3` |
| [anyhow](https://github.com/dtolnay/anyhow) | `1.0.83` | `1.0.86` |
| [tokio](https://github.com/tokio-rs/tokio) | `1.37.0` | `1.38.0` |
| [libc](https://github.com/rust-lang/libc) | `0.2.154` | `0.2.155` |
| [pulldown-cmark](https://github.com/raphlinus/pulldown-cmark) | `0.10.3` | `0.11.0` |
| [open](https://github.com/Byron/open-rs) | `5.1.2` | `5.1.3` |
| [thiserror](https://github.com/dtolnay/thiserror) | `1.0.60` | `1.0.61` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.0.97` | `1.0.98` |



Updates `serde` from 1.0.201 to 1.0.203
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.201...v1.0.203)

Updates `toml` from 0.8.12 to 0.8.13
- [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.12...toml-v0.8.13)

Updates `parking_lot` from 0.12.2 to 0.12.3
- [Changelog](https://github.com/Amanieu/parking_lot/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Amanieu/parking_lot/compare/0.12.2...0.12.3)

Updates `anyhow` from 1.0.83 to 1.0.86
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.83...1.0.86)

Updates `tokio` from 1.37.0 to 1.38.0
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.37.0...tokio-1.38.0)

Updates `libc` from 0.2.154 to 0.2.155
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.154...0.2.155)

Updates `pulldown-cmark` from 0.10.3 to 0.11.0
- [Release notes](https://github.com/raphlinus/pulldown-cmark/releases)
- [Commits](https://github.com/raphlinus/pulldown-cmark/compare/v0.10.3...v0.11.0)

Updates `open` from 5.1.2 to 5.1.3
- [Release notes](https://github.com/Byron/open-rs/releases)
- [Changelog](https://github.com/Byron/open-rs/blob/main/changelog.md)
- [Commits](https://github.com/Byron/open-rs/compare/v5.1.2...v5.1.3)

Updates `thiserror` from 1.0.60 to 1.0.61
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.60...1.0.61)

Updates `cc` from 1.0.97 to 1.0.98
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Commits](https://github.com/rust-lang/cc-rs/compare/1.0.97...1.0.98)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: toml
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: parking_lot
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: libc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: pulldown-cmark
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: open
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-03 17:08:51 +09:00
Poliorcetics
972265640d fix: correctly reset inlay hints when stopping or restarting LSPs for a document (#10741) 2024-06-02 10:39:48 -05:00
Christopher Bayliss
179673568d avoid cnorm on certain terminals (#10769)
using a terminfo's cnorm doesn't reset the cursor for many terminals,
see issue: #10089
2024-05-28 13:15:53 +02:00
Mark Stosberg
730e684d1d Correct typo in "current buffer's directory" (#10814) 2024-05-27 10:22:40 +09:00
Yorick Peterse
f1c9580e4b tree-sitter: update Inko grammar (#10805) 2024-05-24 12:09:56 +09:00
dependabot[bot]
4dbb4eeba1 --- (#10804)
updated-dependencies:
- dependency-name: gix
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-24 12:08:20 +09:00
dependabot[bot]
41dec92b0f --- (#10798)
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-22 01:22:06 +09:00
dependabot[bot]
a789f72a88 --- (#10799)
updated-dependencies:
- dependency-name: cachix/cachix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-22 01:21:53 +09:00
Kirawi
5b9f5f9fdb Handle relative symlinks on write (#10790)
try again

try

wip
2024-05-21 06:46:24 +09:00
Blaž Hrastnik
dfcd814389 tui: Constify functions, shrink Margin representation 2024-05-21 04:34:36 +09:00
Blaž Hrastnik
e94735bbd3 tui: Port https://github.com/ratatui-org/ratatui/pull/1036 2024-05-21 03:50:54 +09:00
Pascal Kuthe
8444f52e9a correctly handle opening helix inside symlinked directory (#10728)
* correctly handle opening helix inside symlinked directory

* Update helix-stdx/src/env.rs

---------

Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2024-05-20 21:44:53 +09:00
Michael Davis
ff6aca12b7 Reset all changes overlapped by selections in ':reset-diff-change' (#10178)
This is useful for resetting multiple changes at once. For example you
might use 'maf' or even '%' to select a larger region and reset all
changes within.

The original behavior of resetting the change on the current line is
retained when the primary selection is 1-width since we look for chunks
in the line range of each selection.
2024-05-20 21:40:55 +09:00
Krishan
2301430e37 fix match bracket matching (#10777) 2024-05-16 13:50:01 -05:00
Dmitry Salin
889bbefeb3 Add support for Mojo (#10743)
* Add support for Mojo

* Update grammar

* Fix queries

* Fix docs

* Use inheritance for some files
2024-05-15 16:24:57 +02:00
dependabot[bot]
e76020ddb9 build(deps): bump the rust-dependencies group with 2 updates (#10756)
Bumps the rust-dependencies group with 2 updates: [serde](https://github.com/serde-rs/serde) and [serde_json](https://github.com/serde-rs/json).


Updates `serde` from 1.0.200 to 1.0.201
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.200...v1.0.201)

Updates `serde_json` from 1.0.116 to 1.0.117
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.116...v1.0.117)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-14 17:54:17 +09:00
Valentin B
380c7adcc0 feat(solidity): add missing operators for highlights (#10757)
* feat(solidity): add missing operators for highlights

* fix(solidity): remove invalid operator from highlight queries

* Revert "fix(solidity): remove invalid operator from highlight queries"

This reverts commit 466f38350c.

* feat(solidity): add highlight query for revert statements with custom errors

* feat(solidity): more precise matching for revert statements
2024-05-14 17:53:59 +09:00
Michael Davis
855568fa34 Synchronize files after writing (#10735)
fsync(2) is a somewhat expensive operation that flushes writes to the
underlying disk/SSD. It's typically used by databases to ensure that
writes survive very hard failure scenarios like your cat kicking the
plug out of the wall. Synchronizing isn't automatically done by
`flush`ing (from the `std::io::Write` or `tokio::io::AsyncWriteExt`
traits). From the [`tokio::fs::File`] moduledocs:

> To ensure that a file is closed immediately when it is dropped, you
> should call `flush` before dropping it. Note that this does not ensure
> that the file has been fully written to disk; the operating system
> might keep the changes around in an in-memory buffer. See the
> `sync_all` method for telling the OS to write the data to disk.

[`tokio::fs::File`]: https://docs.rs/tokio/latest/tokio/fs/struct.File.html
2024-05-14 01:37:35 +02:00
Tobias Hunger
5fea7cd0cc tree-sitter: Update slint grammar (#10749) 2024-05-13 18:42:34 +02:00
Felix Richter
00e9e5eade docs/src/package-managers: update nixos link to official wiki (#10718)
This commit updates the the link from the former, unofficial
nixos wiki page to the new https://wiki.nixos.org

ref: https://github.com/NixOS/foundation/issues/113
2024-05-10 06:43:07 +09:00
Aral Balkan
f4a61006bf Remove outdated comment about key binding being disabled (#10717)
I just used the `=` binding to format a selection in a CSS file in helix 23.10 (5931a46c) so removing this comment as outdated.
2024-05-08 21:49:44 +09:00
dependabot[bot]
f656b4f3a7 build(deps): bump the rust-dependencies group across 1 directory with 11 updates (#10715)
Bumps the rust-dependencies group with 11 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [tree-sitter](https://github.com/tree-sitter/tree-sitter) | `0.22.5` | `0.22.6` |
| [unicode-width](https://github.com/unicode-rs/unicode-width) | `0.1.11` | `0.1.12` |
| [hashbrown](https://github.com/rust-lang/hashbrown) | `0.14.3` | `0.14.5` |
| [serde](https://github.com/serde-rs/serde) | `1.0.198` | `1.0.200` |
| [parking_lot](https://github.com/Amanieu/parking_lot) | `0.12.1` | `0.12.2` |
| [anyhow](https://github.com/dtolnay/anyhow) | `1.0.82` | `1.0.83` |
| [libc](https://github.com/rust-lang/libc) | `0.2.153` | `0.2.154` |
| [rustix](https://github.com/bytecodealliance/rustix) | `0.38.32` | `0.38.34` |
| [pulldown-cmark](https://github.com/raphlinus/pulldown-cmark) | `0.10.0` | `0.10.3` |
| [thiserror](https://github.com/dtolnay/thiserror) | `1.0.58` | `1.0.60` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.0.95` | `1.0.97` |



Updates `tree-sitter` from 0.22.5 to 0.22.6
- [Release notes](https://github.com/tree-sitter/tree-sitter/releases)
- [Changelog](https://github.com/tree-sitter/tree-sitter/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tree-sitter/tree-sitter/compare/v0.22.5...v0.22.6)

Updates `unicode-width` from 0.1.11 to 0.1.12
- [Commits](https://github.com/unicode-rs/unicode-width/compare/v0.1.11...v0.1.12)

Updates `hashbrown` from 0.14.3 to 0.14.5
- [Changelog](https://github.com/rust-lang/hashbrown/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/hashbrown/compare/v0.14.3...v0.14.5)

Updates `serde` from 1.0.198 to 1.0.200
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.198...v1.0.200)

Updates `parking_lot` from 0.12.1 to 0.12.2
- [Changelog](https://github.com/Amanieu/parking_lot/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Amanieu/parking_lot/compare/0.12.1...0.12.2)

Updates `anyhow` from 1.0.82 to 1.0.83
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.82...1.0.83)

Updates `libc` from 0.2.153 to 0.2.154
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.153...0.2.154)

Updates `rustix` from 0.38.32 to 0.38.34
- [Release notes](https://github.com/bytecodealliance/rustix/releases)
- [Commits](https://github.com/bytecodealliance/rustix/compare/v0.38.32...v0.38.34)

Updates `pulldown-cmark` from 0.10.0 to 0.10.3
- [Release notes](https://github.com/raphlinus/pulldown-cmark/releases)
- [Commits](https://github.com/raphlinus/pulldown-cmark/compare/v0.10.0...v0.10.3)

Updates `thiserror` from 1.0.58 to 1.0.60
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.58...1.0.60)

Updates `cc` from 1.0.95 to 1.0.97
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Commits](https://github.com/rust-lang/cc-rs/compare/1.0.95...1.0.97)

---
updated-dependencies:
- dependency-name: tree-sitter
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: unicode-width
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: hashbrown
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: parking_lot
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: libc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: rustix
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: pulldown-cmark
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-07 21:43:40 +02:00
Michael Davis
5c11af1479 cargo fmt 2024-05-07 15:15:52 -04:00
Michael Davis
9dd51e75e0 Resolve new Clippy lints 2024-05-07 15:15:52 -04:00
Michael Davis
3cf2a91a25 Bump MSRV to 1.74.0 2024-05-07 15:15:52 -04:00
Jeremia
2bc0d036e7 Added missing colors to dark_high_contrast (#10705)
I'd been using this theme quite a while because it looks the nicest to
my dyslexia. That said, when I open up XML or HTML documents, they
pretty much always show up in complete white, except for attribute
values.

Finally decided to take a look at why, and added the two colors
(`tag` & `attribute`) needed to make the theme actually usable with the
two formats.
2024-05-07 19:09:34 +02:00
Chris
81d4cbc66e Update Odin tree sitter grammar (#10698)
* Replace Odin grammar source

* Update Odin highlights

* Update Odin indents

* Update Odin injections
2024-05-07 18:14:55 +02:00
Christopher Smyth
5e3de68591 FIx incorrectly spelled cfg options (#10703)
* Fix incorrect cfg key for wasm32

* Fix unicode-lines cfg in helix-view not not being used
2024-05-07 18:14:02 +02:00
Pascal Kuthe
5b8b2f4b9b improve match bracket matching (#10613) 2024-05-07 09:26:04 -05:00
Ryan Roden-Corrent
0432d9cf14 lang(starlark): Add WORKSPACE glob. (#10713)
In addition to BUILD files, bazel repositories contain a WORKSPACE file,
which is also written in starlark.
See https://bazel.build/reference/be/workspace.
2024-05-07 23:10:51 +09:00
Szabin
beb5afcbef Revert "Refactor statusline elements to build Spans (#9122)" (#10642) 2024-05-07 01:51:20 +09:00
Matt Moriarity
e16a4f8a2c Expose all flake outputs through flake-compat (#10673) 2024-05-07 01:33:59 +09:00
Yorick Peterse
b437b8b0ee Add support for Inko (#10656)
This adds formatting and Tree-sitter support for Inko
(https://inko-lang.org/).
2024-05-06 18:04:32 +02:00
Arthur D
295a9a95ce feat: add support for gjs and gts (#9940) 2024-05-06 18:04:08 +02:00
David Else
a959c0ef9b Improve the structure of the documentation (#10619) 2024-05-06 17:39:06 +02:00
François Laignel
f86f350d5d Debugger template: allow missing or empty completion list (#10332)
It can be convenient to define project specific debugger templates, some of
which might not necessitate prompting the user to define completion.

This commit makes completion optional for debugger templates and starts the
dap immediately if undefined or empty.
2024-05-06 17:37:04 +02:00
Vladyslav Karasov
6876f923d5 lang(json): make field key highlighting consistent with toml and yaml (#10676) 2024-05-06 17:11:09 +02:00
Guilherme Salustiano
50b13d1aea docs[install/pre-build binaries]: add runtime setup (#10693) 2024-05-06 10:09:21 -05:00
Silvan Schmidt
7d1e5f18a2 fix: update link in adding_languages.md (#10677)
Previously, the link would point to the now moved "How to install the default language servers" page. The link now directly points to the up-to-date page.
2024-05-06 17:07:34 +02:00
Ashley Vaughn
61818996c6 remove ' and add ⟨⟩ in lean autopairs (#10688) 2024-05-05 22:48:50 +09:00
Matthew Pomes
7e13213e74 Add is not and not in to python syntax (#10647) 2024-05-03 12:39:02 +02:00
Hichem
cfca30887c signature: use the suggested LSP signature when changed (#10655)
some LSPs does update the active signature and some not. To make both
worlds happy, make the active signature more intelligent.

1. SignatureHelp store now the suggested lsp_signature
2. if the lsp_signature changes then use it
3. otherwise use the last signature from the old popup
4. in case the old signature doesn't exist anymore, show the last signature

Signed-off-by: Ben Fekih, Hichem <hichem.f@live.de>
2024-05-03 03:53:07 +02:00
Ryan Roden-Corrent
31273c69e0 Add completion/signature bindings to keymap.md (#10654)
* Add completion/signature bindings to keymap.md

PR #9974 added alt-p/alt-n keybindings to scroll through signatures.
This wasn't very discoverable, as it's not in the docs or the command palette.

This also removes a broken link for "comment mode" in the table of contents.

* Update keymap.md
2024-05-02 12:25:15 +02:00
Luv-Ray
752ed8eb15 add try keyword to rust highlights (#10641) 2024-04-30 13:13:27 +09:00
TobiEiss
d8701bfd1e add textobjects queries for hurl (#10594)
* add textobjects queries comment and function

* update doc for hurl lang support

* switch entry.inner to entry.outer

* switch to function.inside

---------

Co-authored-by: Tobias Eiß <te@clarilab.de>
2024-04-29 18:17:46 +02:00
tingerrr
eeb8782c54 Add comment injection to typst queries (#10628) 2024-04-29 17:44:20 +02:00
Erasin Wang
724a96abc8 Add pest support (#10616)
Support [pest-parser](https://github.com/pest-parser)

- [pest-language-server](https://github.com/pest-parser/pest-ide-tools)
- [tree-sitter-pest](https://github.com/pest-parser/tree-sitter-pest)

close #7878
2024-04-29 17:44:03 +02:00
Kitsu
ec224798e7 fix: do not stop at first url at goto_file (#10622) 2024-04-29 08:18:58 -05:00
Kitsu
8db93013fb fix: avoid child area overflow on split (#10620) 2024-04-29 08:18:05 -05:00
Pascal Kuthe
e2594b64c0 move popup when cursor line changes
Co-authored-by: Ben Fekih, Hichem" <hichem.f@live.de>
2024-04-28 11:21:50 -04:00
Pascal Kuthe
93e8c16614 fix required_size implementation of signature help
Trunctation should always be handled by the parent. Returning None is
only supposed to indicate a missing implementation

Co-authored-by: Ben Fekih, Hichem" <hichem.f@live.de>
2024-04-28 11:21:50 -04:00
Pascal Kuthe
2d6d876a23 fix popup size calculation
Co-authored-by: ath3 <ha05190@protonmail.com>
2024-04-28 11:21:50 -04:00
Pascal Kuthe
a1d7997fe3 fix lsp restart (#10614) 2024-04-28 12:11:17 +09:00
Elizabeth
bc03b6b5fe Fixed ECMAScript private member highlighting (#10554) 2024-04-27 21:55:12 +02:00
Alexis (Poliorcetics) Bourget
615d34a237 nit: remove unused ceiling_dir param 2024-04-27 12:51:15 -04:00
Alexis (Poliorcetics) Bourget
f1461b49fa cleanup: remove useless Git struct, using free functions instead 2024-04-27 12:51:15 -04:00
Alexis (Poliorcetics) Bourget
918dd3fa37 cleanup: remove dummy diff provider, it's the exact same as not having one 2024-04-27 12:51:15 -04:00
Diogenesoftoronto
5ee7411450 Change cursor color per mode for default (#10608) 2024-04-26 16:50:29 -05:00
Keir Lawson
31248d4e2f Enable metals inlay hints (#10597) 2024-04-26 16:48:23 -05:00
David Else
109f53fb60 Add debug highlights to the dark plus theme (#10593) 2024-04-25 07:48:14 -05:00
woojiq
839ec4ad39 test: match around closest pair tree-sitter version 2024-04-24 16:36:13 -04:00
woojiq
81dc8e8d6b feat: find closest pair using tree-sitter 2024-04-24 16:36:13 -04:00
Yoav Lavi
50c90cb47c Add support for highlighting any .*ignore file (#10579) 2024-04-24 07:06:19 -05:00
David Else
22960e0d70 Refactor Dark Plus and add new maintainer (#10574)
* Make dark_plus.toml more accurate to VSCode

* theme(dark_plus): make type.builtin blue

* Refactor dark_plus and add myself as new maintainer

Co-authored-by: NAME <NAME@EXAMPLE.COM>

---------

Co-authored-by: Luca Saccarola <96259932+saccarosium@users.noreply.github.com>
Co-authored-by: Luca Saccarola <github.e41mv@aleeas.com>
Co-authored-by: NAME <NAME@EXAMPLE.COM>
2024-04-24 11:40:04 +02:00
Krishan
89a9f2be78 specify direction for select_prev_sibling and select_next_sibling (#10542)
* specify direction for select_prev_sibling and select_next_sibling

* fix failing integration-test
2024-04-23 08:41:03 -05:00
Kirawi
e18b772654 Remove kirawi from dark_plus maintainer list (#10543) 2024-04-21 23:53:31 -04:00
Pascal Kuthe
38ee845b05 don't overload LS with completion resolve requests
While moving completion resolve to the event system in #9668 we introduced what
is essentially a "DOS attack" on slow LSPs. Completion resolve requests were
made in the render loop and debounced with a timeout. Once the timeout expired
the resolve request was made. The problem is the next frame would immediately
request a new completion resolve request (and mark the old one as obsolete but
because LSP has no notion of cancelation the server would still process it). So
we were in essence sending one completion request to the server every 150ms and
only stopped if the server managed to respond before we rendered a new frame.
This caused overload on slower machines/with slower LS.

In this PR I revamped the resolve handler so that a request is only ever
resolved once. Both by checking if a request is already in-flight and by marking
failed resolve requests as resolved.
2024-04-22 12:27:47 +09:00
Pascal Kuthe
b834806dbc use newtype parttern for langauge server id 2024-04-22 12:27:47 +09:00
Matouš Dzivjak
d140072fdc feat(themes): jump-label for modus themes (#10538)
Add styling for jump-labels for modus themes. I couldn't find
any official approach here so picking `yello-cooler`. `cooler` is
used for other meta highlights by modus and yellow seems to be
used the least - only warnings, so there's little chance of colliding
with other highlights.
2024-04-21 09:42:50 -05:00
Simran Kedia
26d9610e78 Ignore .svn version control files (#10536)
Co-authored-by: Simran Kedia <simk@fb.com>
2024-04-21 12:00:30 +09:00
Triton171
efae85ec20 Simplify first-in-line computation for indent queries. (#10527) 2024-04-20 18:58:54 -04:00
dependabot[bot]
35b6aef5fb build(deps): bump the rust-dependencies group with 8 updates (#10532)
Bumps the rust-dependencies group with 8 updates:

| Package | From | To |
| --- | --- | --- |
| [tree-sitter](https://github.com/tree-sitter/tree-sitter) | `0.22.2` | `0.22.5` |
| [serde](https://github.com/serde-rs/serde) | `1.0.197` | `1.0.198` |
| [serde_json](https://github.com/serde-rs/json) | `1.0.115` | `1.0.116` |
| [encoding_rs](https://github.com/hsivonen/encoding_rs) | `0.8.33` | `0.8.34` |
| [chrono](https://github.com/chronotope/chrono) | `0.4.37` | `0.4.38` |
| [anyhow](https://github.com/dtolnay/anyhow) | `1.0.81` | `1.0.82` |
| [clipboard-win](https://github.com/DoumanAsh/clipboard-win) | `5.3.0` | `5.3.1` |
| [cc](https://github.com/rust-lang/cc-rs) | `1.0.90` | `1.0.95` |


Updates `tree-sitter` from 0.22.2 to 0.22.5
- [Release notes](https://github.com/tree-sitter/tree-sitter/releases)
- [Changelog](https://github.com/tree-sitter/tree-sitter/blob/master/CHANGELOG.md)
- [Commits](https://github.com/tree-sitter/tree-sitter/compare/v0.22.2...v0.22.5)

Updates `serde` from 1.0.197 to 1.0.198
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.197...v1.0.198)

Updates `serde_json` from 1.0.115 to 1.0.116
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.115...v1.0.116)

Updates `encoding_rs` from 0.8.33 to 0.8.34
- [Commits](https://github.com/hsivonen/encoding_rs/compare/v0.8.33...v0.8.34)

Updates `chrono` from 0.4.37 to 0.4.38
- [Release notes](https://github.com/chronotope/chrono/releases)
- [Changelog](https://github.com/chronotope/chrono/blob/main/CHANGELOG.md)
- [Commits](https://github.com/chronotope/chrono/compare/v0.4.37...v0.4.38)

Updates `anyhow` from 1.0.81 to 1.0.82
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.81...1.0.82)

Updates `clipboard-win` from 5.3.0 to 5.3.1
- [Commits](https://github.com/DoumanAsh/clipboard-win/commits)

Updates `cc` from 1.0.90 to 1.0.95
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Commits](https://github.com/rust-lang/cc-rs/compare/1.0.90...1.0.95)

---
updated-dependencies:
- dependency-name: tree-sitter
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: encoding_rs
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: chrono
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: clipboard-win
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-20 23:49:01 +09:00
Chris Sergienko
345e687573 feat: update bash grammar to latest tree-sitter-bash rev (#10526) 2024-04-20 07:41:55 -05:00
Ben Fekih, Hichem
4b8bcd2773 popup: call required_size only once while rendering
to speed up the rendering a little

Signed-off-by: Ben Fekih, Hichem <hichem.f@live.de>
2024-04-20 08:39:12 -04:00
Ben Fekih, Hichem
af4ff80524 Improve popup position
Make the popup positions more consistent.
Improvements:
1. if the signature popup content is bigger than the available space,
   then the popup is always shown under the cursor, even if there more
   space above the cursor than below
2. There is no mutation anymore inside required_size. Maybe in the future
   we can update all widgets to have no mutations and change the trait

Signed-off-by: Ben Fekih, Hichem <hichem.f@live.de>
2024-04-20 08:39:12 -04:00
Michael Davis
211f368064 Respect mode when starting a search (#10505)
Currently the editor mode has no effect on the behavior of `search` and
`rsearch`. We can pass in the right movement for the editor mode to make
the behavior or `search` and `rsearch` match `search_next` and
`search_prev` in select mode.
2024-04-20 10:25:11 +09:00
Kevin Vigor
18d5cacea6 Override crossterm's support for NO_COLOR. (#10514)
Since helix isn't usable without color support, honoring this does
nobody any good.
2024-04-20 10:19:12 +09:00
RoloEdits
94405f3d07 refactor(themes): gruvbox warnings to yellow1 (#10506) 2024-04-19 23:22:55 +09:00
urly3
98b4df23a3 theme: everblush (#10394)
changed the statusline colors for SELECT mode
  the previous colours seem to be incorrect and quite ugly (sorry).
  I chose the magenta over the cyan that (colors that were already present) as it has
  more contrast with the existing INSERT colour.
  the statusline colours are now inline with eachother, all having the background be the 'background'
  colour, with varying foregrounds.

Co-authored-by: urly3 <u@rl.yyy>
2024-04-19 10:29:49 +09:00
Nuke
2209effb02 Update lang-support.md for new wiki page name (#10508)
The prior URL invites you to create a new wiki page. I think https://github.com/helix-editor/helix/wiki/Language-Server-Configurations is the correct place to point to now.

There might be more issues related to changes in wiki structure that are not caught by some CI link check because of this (it's a valid URL, just not what you want to direct to lol)
2024-04-19 10:26:04 +09:00
Rolo
34291f0f3b feat(themes): add ui.virtual.ruler for base16_default_dark 2024-04-18 11:50:23 -04:00
Rolo
4e16956007 feat(themes): add ui.virtual.ruler for base16_default_light 2024-04-18 11:50:23 -04:00
Rolo
bb57686854 feat(themes): add ui.virtual.ruler for base16_terminal 2024-04-18 11:50:23 -04:00
Rolo
ccb0c40b5e feat(themes): add ui.virtual.ruler for mellow 2024-04-18 11:50:23 -04:00
Rolo
785d09e38f feat(themes): add ui.virtual.ruler for poimandres
This change also propagates to `poimandres-storm`
2024-04-18 11:50:23 -04:00
Rolo
6fdc1d6a95 feat(themes): add ui.virtual.ruler for varua 2024-04-18 11:50:23 -04:00
Rolo
c0aadfd4ce feat(themes): add ui.virtual.ruler for vim_dark_high_contrast 2024-04-18 11:50:23 -04:00
Rolo
368b29ca72 feat(themes): add ui.virtual.ruler for base16_default 2024-04-18 11:50:23 -04:00
Rolo
be8dc22272 feat(themes): add ui.virtual.ruler for horizon-dark 2024-04-18 11:50:23 -04:00
Rolo
a5a9827f32 fix(themes): correct typo in theme.toml 2024-04-18 11:50:23 -04:00
Rolo
88da9e857c feat(themes): add ui.virtual.ruler for default 2024-04-18 11:50:23 -04:00
Rolo
4713eb06b1 refactor(themes): change solarized_* ruler to bg
Also changed the colors to better blend with the theme.
2024-04-18 11:50:23 -04:00
Rolo
6bdc6f460e refactor(themes): removed ui.highlight effects from solarized_light
This now matches `solarized_dark` changes from #10261
2024-04-18 11:50:23 -04:00
ves
97f683b336 Improve HTML highlighting (#10503) 2024-04-18 15:57:26 +09:00
Blaž Hrastnik
8924691c5d minor: Update docs 2024-04-18 14:59:46 +09:00
Blaž Hrastnik
f06a166962 Add Move language support 2024-04-18 14:57:23 +09:00
Daniel O'Brien
1d23796ad1 Fix kanagawa theme when using cursorline (#10500) 2024-04-17 17:58:33 -05:00
Sean Perry
30baff907d Implement read command (#10447)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
Co-authored-by: Ibrahim Dursun <ibrahim@dursun.cc>
2024-04-17 17:57:57 -05:00
ath3
521accaf00 Include "change" in textobject autoinfo (#10496) 2024-04-17 17:29:28 +02:00
Gaëtan Lehmann
ab203b5f53 update earthfile grammar and highlight queries (#10489) 2024-04-17 20:15:16 +09:00
Pascal Kuthe
1cce693bef correctly describe behavior of C in tutor (#10465) 2024-04-17 09:06:05 +09:00
Clara Smyth
43dff1c772 Fix: Svelte queries (#10487) 2024-04-16 23:56:43 +02:00
Jonathan Lebon
36ee9ba7d6 languages/rust: add rust-script and cargo shebangs (#10484)
The former is one of the more popular forks of the original idea:

https://rust-script.org/

The latter is an RFC for folding that functionality into cargo itself,
available on nightly:

https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#script
2024-04-16 22:47:18 +02:00
Hichem
69e08d9e91 allow cycling through function signatures/overloads (#9974)
implement handle_event to cycle through the function signatures.

To change the signature press alt+p/n .

Signed-off-by: Ben Fekih, Hichem <hichem.f@live.de>
2024-04-16 20:57:22 +02:00
Rowan Lovejoy
7775b35cba Add a warning in docs about conflicts with terminal default key bindings (#10380)
Add a warning about conflicts with terminal default key bindings.
2024-04-16 09:13:02 -05:00
Kieran Moy
50470f755f Add missing hyprlang support (#10383) 2024-04-16 16:11:01 +02:00
Idobenhamo
68765f51c9 Support Typst 0.11 (#10321)
* Update the tree sitter to support Typst 0.11 and changed the lsp to Tinymist

* Fixed

* Added typst-lsp & tinymist

---------

Co-authored-by: Idobenhamo <idobenhamo@users.noreply.github.com>
2024-04-16 16:00:13 +02:00
Matthew Bourke
8e161723ee Enabled traversing multiple buffers at once (#10463)
* Enable traversing multiple buffers at once

* run cargo fmt

* simplify iterator call
2024-04-16 15:59:45 +02:00
Alexis-Lapierre
8256ca7bc3 Add support for Xena OpenAutomation files (#10448)
Add support for .xtc/.xoa/.xpc files

* XTC stand for Xena Traffic Configuration
* XOA stand for Xena OpenAutomation
* XPC stand for Xena Port Configuration

Theses three file time seems to be the most common file extension I
encountered in the wild
2024-04-16 15:33:50 +02:00
blinxen
70459b2b66 Update gix to version 0.62 (#10451)
This update contains a security fix for
https://rustsec.org/advisories/RUSTSEC-2024-0335.html
2024-04-15 14:44:00 -05:00
Pedro Fedricci
0546273570 chore: update tree-sitter-rust to v0.21.0 (#10365)
* chore: update tree-sitter-rust to 0.21.0

* fix: pretty print and textobject tests
2024-04-15 18:07:15 +02:00
Sufian
1245760595 Add bufferline and cursorline colors to vim dark theme (#10444) 2024-04-15 10:08:55 -05:00
Christopher Kaster
9df1266376 Add lldb-dap debugger support for Odin (#10175) 2024-04-14 02:34:57 +02:00
Matthew Toohey
081f7d0bd8 Update tree-sitter-ld and highlights (#10379) 2024-04-13 02:32:24 +02:00
Kirawi
6d363a978d Read symlink when writing files (#10339)
Co-authored-by: Pascal Kuthe <pascalkuthe@pm.me>
2024-04-11 20:49:16 -05:00
Arthur
c9ae694aff fix(languages/helm): recognize _*.tpl as helm (#10344) 2024-04-11 17:59:00 +02:00
Alexander Brevig
009a5498ca add LDIF support (#10330)
* feat(lang): add LDIF support

* style: no unnecessary glob

* Update runtime/queries/ldif/highlights.scm

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-04-11 17:17:44 +02:00
Blaž Hrastnik
4fc0a4dafc Improve solidity highlighting 2024-04-11 16:16:47 +09:00
Josh Robson Chase
34c7eb4bd4 themes/monokai: add inlay-hint style (#10334)
Matching comment styling so that it doesn't get confused for actual
code.
2024-04-10 10:36:37 -05:00
Pascal Kuthe
73d26d0d97 don't manually grapheme align ts highlights (#10310) 2024-04-11 00:14:08 +09:00
blt-r
b974716b92 Hightlight meson.options as meson file (#10323) 2024-04-09 20:17:52 +02:00
Pascal Kuthe
f601b7c278 fix char/byte index mixup in overlay rendering (#10317) 2024-04-10 01:49:30 +09:00
VKondakoff
c5e257b81c Update nord.toml (#10307)
When "nord2" color is used in ui.selection it is almost invisible
if cursorline highlighting is enabled. Changing the color to "nord3" fixes the issue.
2024-04-09 16:43:21 +02:00
Valentin B
b8ddb2f114 feat(solidity): add textobject queries for solidity (#10318)
* feat: add textobject queries for solidity

* feat(solidity): add parameter textobject query for call expressions

* feat(solidity): add more textobject queries for parameters

* feat(solidity): add yul function textobject query

* feat(solidity): add textobject query for emit statement arguments

* feat(solidity): add textobject query for revert call arguments

* feat(solidity): update tree-sitter grammar and fix typo

* docs: update auto-generated docs

* fix(solidity): fix identifiers highlight query priority

* feat(solidity): add "abstract" to keywords list

* feat(solidity): add highlight query for type alias

* feat(solidity): add variable builtin highlight queries
2024-04-09 16:42:51 +02:00
Skyler Hawthorne
c99c333337 Use new in-crate TreeCursor 2024-04-09 10:33:15 -04:00
Skyler Hawthorne
fa67c5c474 feat(command): select_all_children 2024-04-09 10:33:15 -04:00
Skyler Hawthorne
87c4161732 feat(command): select_all_siblings 2024-04-09 10:33:15 -04:00
Skyler Hawthorne
cf9b88f9bd add Range::{from_node,into_byte_range} 2024-04-09 10:33:15 -04:00
Evgeniy Tatarkin
07cb24abdd Respect lsp definition order for code actions (#9590) 2024-04-09 09:28:54 -05:00
Yomain
cf99615b43 material theme: fix statusline color (#10308) 2024-04-09 09:44:49 +09:00
dependabot[bot]
55346f32b5 build(deps): bump peaceiris/actions-mdbook from 1 to 2 (#10314)
Bumps [peaceiris/actions-mdbook](https://github.com/peaceiris/actions-mdbook) from 1 to 2.
- [Release notes](https://github.com/peaceiris/actions-mdbook/releases)
- [Changelog](https://github.com/peaceiris/actions-mdbook/blob/main/CHANGELOG.md)
- [Commits](https://github.com/peaceiris/actions-mdbook/compare/v1...v2)

---
updated-dependencies:
- dependency-name: peaceiris/actions-mdbook
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-09 09:41:41 +09:00
dependabot[bot]
cf259e37c8 build(deps): bump peaceiris/actions-gh-pages from 3 to 4 (#10313)
Bumps [peaceiris/actions-gh-pages](https://github.com/peaceiris/actions-gh-pages) from 3 to 4.
- [Release notes](https://github.com/peaceiris/actions-gh-pages/releases)
- [Changelog](https://github.com/peaceiris/actions-gh-pages/blob/main/CHANGELOG.md)
- [Commits](https://github.com/peaceiris/actions-gh-pages/compare/v3...v4)

---
updated-dependencies:
- dependency-name: peaceiris/actions-gh-pages
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-09 09:41:11 +09:00
RoloEdits
ae85f5ff71 refactor(themes): removed ui.highlight effects from solarized_dark (#10261) 2024-04-08 20:02:02 +02:00
RoloEdits
c499f9aa55 feat(themes): add ruler for adwaita-dark (#10260) 2024-04-08 20:01:40 +02:00
Alexander Brevig
be8afe1bfe chore: remove unused xtask themelint (#10294)
* chore: remove unused xtask themelint

* chore(clippy): remove unused themes
2024-04-08 18:15:31 +02:00
Hichem
ea2a4858b7 Fix scrolling to the end within a popup (#10181)
when the available height for the popup is low/small, then it is not
possible to scroll until the end

Signed-off-by: Ben Fekih, Hichem <hichem.f@live.de>
2024-04-08 10:41:03 -05:00
Diego
92338bc207 fix mouse right click selection (#10067) 2024-04-08 10:20:53 -05:00
Bertrand Bousquet
d180395461 Varua theme jump label support (#10299) 2024-04-08 22:53:10 +09:00
Yomain
1e7c01d75b material theme: add diagnostics and other missing stuff (#10290) 2024-04-08 14:47:44 +09:00
Pascal Kuthe
6f5ea6be58 fix off by one error for completion-replace option (#10279) 2024-04-08 12:31:23 +09:00
Gary Miller
0da809c981 feat: Add ADL language support (#10029)
* feat: Add ADL language support

* removed error match & change captures to match https://docs.helix-editor.com/master/themes.html\#syntax-highlighting

* fixes to grammar, highlight changes based on PR and grammar fixes
2024-04-08 04:45:20 +02:00
Pebrianz
e663dafcd8 Add angular language server (#10166) 2024-04-08 04:32:29 +02:00
TornaxO7
e69292e5eb Improve goto_file_impl (#9065) 2024-04-06 16:27:29 -05:00
Slug
97afd67fca Add jump-label style for dark high contrast (#10102) 2024-04-06 16:49:14 +09:00
Michael Davis
3f2de21342 Handle partial failure when sending textDocument/didSave (#10168) 2024-04-06 13:38:51 +09:00
Eduardo Farinati
d3bfa3e063 Fix crash on lsp text edits with invalid ranges (#9649) 2024-04-06 04:17:22 +02:00
Ricardo Fernández Serrata
1ba5763a0c recognize more files and shebangs (#10120)
* recognize `.node_repl_history` as JS

* recognize `bun` shebang

also add comments explaining Deno & Bun history files

* recognize `.python_history` file and `python3` shebang

* recognize more shells

* rm Py3 shebang

Co-authored-by: ath3 <45574139+ath3@users.noreply.github.com>

* rm non-standard deno/bun hist recognition

---------

Co-authored-by: ath3 <45574139+ath3@users.noreply.github.com>
2024-04-05 22:44:39 +02:00
Matthew Toohey
a2ee2e66f2 Add koka language server and update grammar (#10119) 2024-04-05 18:53:07 +09:00
Michael Davis
f240d896a4 Merge unnecessary/deprecated diagnostic highlights separately (#10084)
Previously unnecessary/deprecated diagnostic tags replaced the highlight
for the severity of a diagnostic. This could cause either the severity
or unnecessary/deprecated scopes to disappear when diagnostic ranges
overlapped though. Plus the severity highlight can be interesting in
addition to the unnecessary/deprecated highlight.

So this change separates the unnecessary and deprecated highlights from
the severity highlights, so each is merged separately and when they
overlap, the highlights are combined.
2024-04-05 14:50:41 +09:00
Karem Abdul-Samad
d053886fe3 Add new keyword as per PEP 695 (#10165) 2024-04-05 02:22:41 +02:00
Aito Stukas
5f44890176 Remove duplicate keyword highlight for Python 'and' (#10160) 2024-04-04 19:12:19 -05:00
Harishankar G
962c714185 Use an enum to represent yank decision during deletion of a selection (#10148) 2024-04-05 00:18:48 +09:00
Tshepang Mbambo
3e2b85c61b remove redundant imports (#10154) 2024-04-04 23:28:44 +09:00
Michael Davis
1539312558 Add a serializer for the jump alphabet config option (#10156)
Without a serializer, we drop the custom alphabet when making config
modifications like with `:set`. For example before this commit,
`:set mouse false` would reset a custom alphabet to the default.
2024-04-04 23:28:31 +09:00
Blaž Hrastnik
5fece0054d Disable todotxt grammar for files named "todo.txt"
The file name is too common and can unintentionally conflict. Users
should manually opt in.

Fixes #10113
2024-04-04 10:35:44 +09:00
Eloi Torrents
88f2931153 Add tcl highlighting (#9837)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-04-04 03:31:00 +02:00
André Sá
f16380d418 Add jumb label color to ayu themes (#10133) 2024-04-04 10:17:51 +09:00
Jens Getreu
fa79ce59a0 Autumn theme: add jump label (#10134) 2024-04-04 10:17:40 +09:00
Harishankar G
f773972241 Use a boolean to indicate whether to yank during deletion of a selection (#10132) 2024-04-03 12:40:55 -05:00
Takumi Matsuura
84cc42e5ee typofix (#10125) 2024-04-03 23:05:48 +09:00
Evgeniy Tatarkin
e54e3f07cb feat(languages): Tiltfile as starlark language (#10072) 2024-04-03 10:32:12 +09:00
Angus Dippenaar
e0ec34421b languages: update templ (#10114) 2024-04-03 10:31:44 +09:00
Gaëtan Lehmann
226b2755fb add earthfile language configuration (#10111) 2024-04-03 10:30:15 +09:00
Sampo Siltanen
54844241ce Add fsharp block comment tokens to languages.toml (#10108) 2024-04-03 10:29:30 +09:00
Jesús González
96f7d73f3d Add jump label support to Darcula themes (#10116) 2024-04-02 16:38:22 -05:00
Luis Useche
190fbf66d4 reconfigure tree properly after closing view (#10004)
This patch merges the last child of a container node to the parent. This
avoids the bug where uneven spaced Views would be created. To reproduce:
1. `vsplit`
2. `split`
3. `quit`
4. `vsplit`

With this patch the bug cannot be seen anymore.
2024-04-02 17:29:57 +02:00
woojiq
cc8290f393 show newest options in jumplist picker first, fix docs (#10095)
* docs: mention `<space>g` changed file picker

* picker(jumplist): show jumps in order from latest to oldest
2024-04-02 16:39:44 +02:00
Henrik Tjäder
e63ed0579d Theme: PaperColor: Tune jump-label (#10104) 2024-04-02 15:59:29 +02:00
Clément Delafargue
545ff1aac6 add support for jump labels in tokyonight themes (#10106) 2024-04-02 08:15:12 -05:00
dependabot[bot]
bb0bfa23f3 build(deps): bump the rust-dependencies group with 3 updates (#10099)
Bumps the rust-dependencies group with 3 updates: [serde_json](https://github.com/serde-rs/json), [chrono](https://github.com/chronotope/chrono) and [tokio](https://github.com/tokio-rs/tokio).


Updates `serde_json` from 1.0.114 to 1.0.115
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.114...v1.0.115)

Updates `chrono` from 0.4.35 to 0.4.37
- [Release notes](https://github.com/chronotope/chrono/releases)
- [Changelog](https://github.com/chronotope/chrono/blob/main/CHANGELOG.md)
- [Commits](https://github.com/chronotope/chrono/compare/v0.4.35...v0.4.37)

Updates `tokio` from 1.36.0 to 1.37.0
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.36.0...tokio-1.37.0)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: chrono
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-02 11:26:28 +09:00
RoloEdits
b24c465a08 uswd lldb-dab instead of lldb-dap in the default dap configuration (#10091)
`LLVM v18.0.0` changed the name here: llvm/llvm-project#69264

Current users of `lldb-vscode` not able to upgrade will have to create a
symlink so that `lldb-dap` links to `lldb-vscode`.

BREAKING CHANGE: debugger looks for `lldb-dap` rather than `lldb-vscode`

closes: #9964
2024-04-02 02:49:26 +02:00
Manuel Mendez
4b236f30db Add Buildkite command/commands support to yaml injections (#10090)
* Use any-of instead of match in yaml injections

Go back to original intent when this code was first written now that the
tree-sitter version used supports any-of?.

* yaml/injections: Add injection for Buildkite

Buildkite uses `command` (`commands` is an alias) to define the
command(s) to run for the step.
2024-04-02 02:48:08 +02:00
Maksym Pavlenko
8635913f0e Dim primary selection in kanagawa (#10094)
* [kanagawa] Change selection color

Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>

* [kanagawa] Use less brigh selection color

Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>

---------

Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
2024-04-02 00:40:40 +02:00
Pawel Grzybek
d56f3fb755 Add jump-label styling for base16 themes (#10076)
* add jump-label styling for base16_transparent theme

* keep the change consistent with other themes from base16 family

* update jump-labels color to blue and make them bold
2024-04-01 18:45:55 +02:00
Kirawi
88d455afeb Use a temporary file for writes (#9236)
Co-authored-by: Pascal Kuthe <pascalkuthe@pm.me>
2024-03-31 17:43:09 -05:00
Jonathan LEI
a224ee5079 Changed file picker (#5645)
Co-authored-by: WJH <hou32hou@gmail.com>
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
Co-authored-by: Pascal Kuthe <pascalkuthe@pm.me>
2024-03-31 17:36:28 -05:00
Daniel S Poulin
1abb64e48d Add textobject for entries/elements of list-like things (#8150) 2024-03-31 11:53:15 -05:00
Krishan
47ef9f0ca2 add new theme keys for LSP diagnostic tags (#10064) 2024-03-31 16:00:14 +02:00
ftqo
2f4572d91e add flexoki theme (#10002)
* add flexoki theme

* change ruler color to bg-2
2024-03-31 14:50:37 +02:00
Ni
0c3bc46ac4 added ../gleam/injections.scm (#10062)
Co-authored-by: Ni <ni@superboring.net>
2024-03-31 14:48:29 +02:00
Gokul Soumya
957d030be9 Support scrolling popup contents using mouse (#10053)
* Extract popup scrolling code into named functions

* Scroll popup contents on mouse scroll event

* Ignore mouse events outside the popup

* Remove unneeded return statement
2024-03-31 14:47:13 +02:00
Erasin Wang
0da5865695 feat(themes): add jump-label for oneLight theme (#10061) 2024-03-31 14:16:48 +02:00
Pascal Eberhard
9a80f7203d add initial support for bitbake language (#10010)
Signed-off-by: Pascal Eberhard <pascal.eberhard@se.com>
2024-03-31 14:16:19 +02:00
Skyler Hawthorne
f5991657f4 Factor out line ending handling in integration tests (#9921)
Prior to this change, every integration test which wanted its line
endings to be handled transparently across platforms, i.e. test with
the same input that has its platform's line feed characters, converting
the line endings was up to each individual test by calling the
`platform_line` helper function. This significantly increases the amount
of boilerplate one has to copy between all the tests.

However, there are some test cases that need to exert strict control
over the exact input text without being manipulated behind the scenes by
the test framework.

So, with this change, the line feed conversions are factored into
the `TestCase` struct. By default, line endings of the input text
are converted to the platform's native line feed ending, but one can
explicitly specify in their test case when the input text should be left
alone and tested as is.
2024-03-31 07:12:17 -05:00
Matouš Dzivjak
2533b08f64 feat(languages): .mkdn as markdown extension (#10065)
GitHub recognizes `.mkdn` as markdown files. Add `.mkdn` as a valid
file type for Markdown.
2024-03-31 07:03:05 -05:00
Tshepang Mbambo
8b7cbf5280 typo (#10060) 2024-03-31 13:59:46 +02:00
Abderrahmane TAHRI JOUTI
25d8e9445c Add jump-label (#10058) 2024-03-31 00:49:49 +01:00
Dawid Ciężarkiewicz
825ae74b9e chore: add "ui.virtual.jump-label" to solarized colorschemes (#10056) 2024-03-31 00:49:16 +01:00
Pedro Fedricci
96220cb632 feat(themes): add jump-label style for nightfox (#10052) 2024-03-30 22:58:16 +01:00
blt-r
3d6f34c270 Make Helix.appdata.xml spec-compliant (#10051)
- The <description> tag shouldn't be translated, but instead the
  individual paragraphs.
- The <developer> tag is required.
- The <requires> tag actually means that the app can't even be installed
  without that control. What this should be is <recommends>.
2024-03-30 19:51:46 +01:00
Michael Davis
2cadec0b11 Add changelog notes for 24.03 (#9946)
* changelog: Checkpoint 2024-03-20

commit: b8e79c0ef5

* Bump the version to 24.3.0

* changelog: Checkpoint 2024-03-25

commit: 614a744d24

* Address review comments

* changelog: Checkpoint 2024-03-30

commit: 64c1de1988

* Adjust release day to 2024-03-30

* Linkify
2024-03-30 22:28:02 +09:00
Chris
64c1de1988 Add main.odin to Odin roots (#9968) 2024-03-30 07:40:38 -05:00
Yannic Nuwenhof
787a237f8b Add JetBrains default dark theme (#9967) 2024-03-30 19:45:38 +09:00
Yomain
381976a04c fix: cursor line on material themes (#10043) 2024-03-30 19:43:53 +09:00
Daniel Flanagan
527cbe656c chore: update tree-sitter-markdown (#10039) 2024-03-29 08:31:27 -05:00
Joe
7ec509e2f9 Add injections for GraphQL and ERB in Ruby (#10036) 2024-03-29 10:45:17 +09:00
mlemesle
c69ad7b3bf Add jump-label to Kanagawa theme + format (#10030)
* Add jump-label to Kanagawa theme + format

* Remove bg color for jump-label

* Remove values alignment
2024-03-28 09:58:50 -05:00
Vladyslav Karasov
f21efc7a2f fix: don't highlight colons (:) in comments (#10014) 2024-03-27 14:31:35 +01:00
Michael Davis
cb286b7a5d Fix rustc warnings about unused 'pub use's (#10011) 2024-03-27 14:34:47 +09:00
RoloEdits
a6c6fa4c8e feat(themes): add jump-label for gruvbox themes (#10012) 2024-03-26 20:48:08 +01:00
Ben Lee-Cohen
cef839e477 feat: add jump format for monokai family (#10009)
Co-authored-by: Ben Lee-Cohen <ben@lee-cohen.com>
2024-03-26 17:18:13 +01:00
Ben Lee-Cohen
1e50fb8b55 Adding jump styles for Nord and Nord Light (#10008)
Co-authored-by: Ben Lee-Cohen <ben@lee-cohen.com>
2024-03-26 15:51:53 +01:00
Michael Davis
07e21a10f0 Revert "helix-term: allow to backspace out-of the command prompt (#9828)" (#10005)
This reverts commit 0dc67ff885.

See the post-merge discussion in #9828. The old behavior was less
surprising and we have other ways to abort from a prompt, so let's
revert the behavior change.
2024-03-26 14:49:39 +09:00
Blaž Hrastnik
a0d6566140 Fix regression in color-modes
Fixes #10006
2024-03-26 14:46:56 +09:00
dependabot[bot]
3205bc4132 build(deps): bump the rust-dependencies group with 6 updates (#10007)
Bumps the rust-dependencies group with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [smallvec](https://github.com/servo/rust-smallvec) | `1.13.1` | `1.13.2` |
| [arc-swap](https://github.com/vorner/arc-swap) | `1.7.0` | `1.7.1` |
| [regex](https://github.com/rust-lang/regex) | `1.10.3` | `1.10.4` |
| [indoc](https://github.com/dtolnay/indoc) | `2.0.4` | `2.0.5` |
| [rustix](https://github.com/bytecodealliance/rustix) | `0.38.31` | `0.38.32` |
| [which](https://github.com/harryfei/which-rs) | `6.0.0` | `6.0.1` |


Updates `smallvec` from 1.13.1 to 1.13.2
- [Release notes](https://github.com/servo/rust-smallvec/releases)
- [Commits](https://github.com/servo/rust-smallvec/compare/v1.13.1...v1.13.2)

Updates `arc-swap` from 1.7.0 to 1.7.1
- [Changelog](https://github.com/vorner/arc-swap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vorner/arc-swap/commits)

Updates `regex` from 1.10.3 to 1.10.4
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.10.3...1.10.4)

Updates `indoc` from 2.0.4 to 2.0.5
- [Release notes](https://github.com/dtolnay/indoc/releases)
- [Commits](https://github.com/dtolnay/indoc/compare/2.0.4...2.0.5)

Updates `rustix` from 0.38.31 to 0.38.32
- [Release notes](https://github.com/bytecodealliance/rustix/releases)
- [Commits](https://github.com/bytecodealliance/rustix/compare/v0.38.31...v0.38.32)

Updates `which` from 6.0.0 to 6.0.1
- [Release notes](https://github.com/harryfei/which-rs/releases)
- [Changelog](https://github.com/harryfei/which-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/harryfei/which-rs/compare/6.0.0...6.0.1)

---
updated-dependencies:
- dependency-name: smallvec
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: arc-swap
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: indoc
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: rustix
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: which
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-26 12:55:58 +09:00
Yomain
d4b467090b doc: small formatting corrections (#9986) 2024-03-26 01:08:42 +01:00
Mo
1d1087822a Use the OS path separator instead of / (#10000) 2024-03-26 00:59:33 +09:00
Quentin
614a744d24 Add narrow no-break space support (#9604) 2024-03-25 10:29:36 +09:00
Novus Nota
2d9e336f64 feat: Add Ohm language support (#9991)
* feat: Add `Ohm` language support

Hope this commit makes it into release :)

* Update runtime/queries/ohm/highlights.scm

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* chore: final newline

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-03-24 23:30:59 +01:00
Armando Pérez Marqués
47995bfb0c Add jump label color ("rosewater") to catppuccin themes (#9983) 2024-03-24 16:02:26 +09:00
Tobias Brunner
7bce9530d3 Add jump label color to rose-pine themes (#9981) 2024-03-24 11:42:57 +09:00
Florent Nuttens
da2dec174a feat: add jump label color to onedark theme 2024-03-24 11:42:35 +09:00
Florent Nuttens
628dcd5c56 feat: add jump label color to dark plus theme 2024-03-24 11:42:35 +09:00
Florent Nuttens
2178adfe93 feat: add jump label color to catppuccin themes 2024-03-24 11:42:35 +09:00
ves
54fab657be Add jump label color to horizon-dark theme (#9984) 2024-03-24 11:42:01 +09:00
Yomain
8f65bfe089 feat: add jump label color to dracula themes (#9973) 2024-03-23 13:40:19 +01:00
Pascal Kuthe
b46064b8c4 Add an Amp-like jump command
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-03-23 15:35:25 +09:00
Pascal Kuthe
3001f22b31 add reverse rope grapheme iterator 2024-03-23 15:35:25 +09:00
Pascal Kuthe
66b9ff1d2a dismiss pending keys properly for mouse/paste 2024-03-23 15:35:25 +09:00
Pascal Kuthe
69e07ab61e use slices instead of Rc for virtual text 2024-03-23 15:35:25 +09:00
Michael Davis
68b21578ac Reimplement tree motions in terms of syntax::TreeCursor
This uses the new TreeCursor type from the parent commit to reimplement
the tree-sitter motions (`A-p/o/i/n`). Other tree-sitter related
features like textobjects are not touched with this change and will
need a different, unrelated approach to solve.
2024-03-23 15:32:34 +09:00
Michael Davis
b1222f0664 Add a TreeCursor type that travels over injection layers
This uses the layer parentage information from the parent commit to
traverse the layers. It's a similar API to `tree_sitter:TreeCursor`
but internally it does not use a `tree_sitter::TreeCursor` currently
because that interface is behaving very unexpectedly. Using the
`next_sibling`/`prev_sibling`/`parent` API on `tree_sitter::Node`
reflects the previous code's behavior so this should result in no
surprising changes.
2024-03-23 15:32:34 +09:00
Michael Davis
6dd46bfe1c syntax: Track parent LanguageLayer IDs
This commit adds a `parent` field to the `LanguageLayer`. This
information is conveniently already available when we parse injections.
This will be used in the child commit to create a type that can
traverse injection layers using this information.
2024-03-23 15:32:34 +09:00
Jaakko Paju
d5c2973cd1 Fix repeat last motion for goto next/prev diagnostic (#9966) 2024-03-23 15:25:08 +09:00
Carter Watson
be307a4204 fix: undefined bufferline colors (#9960) 2024-03-21 23:07:47 +01:00
David Else
c9e34c556b Add rclone.conf as a glob to make it behave as an ini file (#9959) 2024-03-21 16:10:16 -05:00
Michael Davis
f5d95de227 C++: Improve parameter highlighting
This adds parameter highlighting for reference parameters and defaulted
parameters. For example:

```cpp
auto strip_prefix_only(std::string& s,
                       Hidden_Homonym skip_hidden_homonym = {}) const
    -> Affixing_Result<Prefix>;
```

Previously both parameters were only highlighted as variables.
2024-03-22 00:20:29 +09:00
Michael Davis
c099dde2a7 Rust: Highlight extern crate aliases
For example `extern crate alloc as myalloc;`
2024-03-22 00:20:29 +09:00
Michael Davis
9ceeea5a83 Update tree-sitter-gleam and highlights
This contains a few syntax fixes. The highlights have been updated as
well for reserved identifiers and escape sequences
2024-03-22 00:20:29 +09:00
Michael Davis
fdcd461e65 Update tree-sitter-erlang and highlights
A few changes:

* 0-arity type specs like the following previously would not have the
  expected 'variable.parameter' highlighting for the return type:

    -spec foo() -> Value when Value :: term().

* Highlight module, type and function docs as documentation comments
  and inject markdown into them.

* Replace `#match?` predicates with `#any-of?` where possible.

* Remove custom auto-pairs. Now that Erlang uses markdown for
  documentation, the asciidoc-style backtick-singlequote pair is no
  longer useful.
2024-03-22 00:20:29 +09:00
Michael Davis
459eb9a4c1 Recognize 'mmd' as mermaid 2024-03-22 00:20:29 +09:00
Michael Davis
961025433d Update tree-sitter-git-commit
This commit has partial support for escapes within strings.
2024-03-22 00:20:29 +09:00
JR
51739f1290 Create a tutor entry for using splits (#9417)
* WIP

* WIP

* WIP

* Update runtime/tutor

Co-authored-by: David Else <12832280+David-Else@users.noreply.github.com>

* WIP

* WIP

* WIP

* Fix typos

* Fix typos

* Minor updates

* Update runtime/tutor

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Update runtime/tutor

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Update runtime/tutor

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Update runtime/tutor

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Update runtime/tutor

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Update runtime/tutor

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Remove mention of arrows in split tutorial

* Do not mention starting in normal mode

* Fix right drift of titles

* Update runtime/tutor

Co-authored-by: David Else <12832280+David-Else@users.noreply.github.com>

* Update runtime/tutor

Co-authored-by: David Else <12832280+David-Else@users.noreply.github.com>

* Update runtime/tutor

Co-authored-by: David Else <12832280+David-Else@users.noreply.github.com>

* Update runtime/tutor

Co-authored-by: David Else <12832280+David-Else@users.noreply.github.com>

* Update runtime/tutor

Co-authored-by: David Else <12832280+David-Else@users.noreply.github.com>

* Update runtime/tutor

Co-authored-by: David Else <12832280+David-Else@users.noreply.github.com>

* Update runtime/tutor

Co-authored-by: David Else <12832280+David-Else@users.noreply.github.com>

* Update runtime/tutor

Co-authored-by: David Else <12832280+David-Else@users.noreply.github.com>

* Update runtime/tutor

Co-authored-by: David Else <12832280+David-Else@users.noreply.github.com>

* Update runtime/tutor

Co-authored-by: David Else <12832280+David-Else@users.noreply.github.com>

* Update runtime/tutor

Co-authored-by: David Else <12832280+David-Else@users.noreply.github.com>

* Reflow paragraphs

* Update runtime/tutor

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Update runtime/tutor

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Update runtime/tutor

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Update runtime/tutor

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Update runtime/tutor

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Update runtime/tutor

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Update runtime/tutor

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

---------

Co-authored-by: David Else <12832280+David-Else@users.noreply.github.com>
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-03-21 14:37:08 +01:00
Jordan Reger
5ba36fe9b3 Update rasmus.toml (#9939)
* Update rasmus.toml

Remove "ui.virtual" setting as it selects seemingly random characters to highlight.

* Add ui.virtual.ruler
2024-03-21 12:35:34 +09:00
Michael Davis
7f5fd63835 Evenly space statusline areas when there isn't space to align middle (#9950)
The refactor in bcf7b263 introduced a possible subtraction with overflow
when the statusline is layed out so that the left or right sides are
larger than the padding it would take to align the center area to the
middle.

When the left or right areas are too large, we can evenly space the
elements rather than trying to align the center area to the middle.
This prevents possible underflows and makes sense visually - it's
still easy to tell the areas apart at a glance.
2024-03-21 09:16:58 +09:00
David Else
52a0734120 Add new theme keys for LSP diagnostic tags for dark_plus (#9949) 2024-03-21 00:31:48 +01:00
Hendrik Norkowski
b8e79c0ef5 fix(languages): specify correct comment-token for PKGBUILD files (#9943) 2024-03-20 08:09:45 -04:00
Szabin
bcf7b26393 Refactor statusline elements to build Spans (#9122)
* Refactor statusline elements to return Spans

* Split render fn to build Spans and blit to Surface
2024-03-19 17:31:39 +01:00
Arthur Deierlein
427dd2f383 Add support for ember.js templates (#9902)
* feat: add support for ember .hbs (glimmer) templates

* adjust highlights to helix

* highlight this correctly in block statements

* correctly highlight attributes

* correctly highlight hash_pair

* add newline to highlights.scm

* refactor: use #any-of and #eq instead of #match

* chore: add newline to languages.toml
2024-03-19 17:26:50 +01:00
Kirawi
d9de809a57 add register completion (#9936) 2024-03-19 17:26:32 +01:00
Tobias Hunger
1d1806c85a Ignore more version control systems (#9935)
Ignore `.pijul` and `.jj` as well as `.git`. This makes hx so much more
usable with VCSes other than git!
2024-03-19 15:08:50 +01:00
Arthur Deierlein
4b4947639a feat: add suport for helm charts (#9900) 2024-03-19 15:07:44 +01:00
Cyrill Schenkel
5b8bfc5476 Prevent shell_keep_pipe from stopping on nonzero exit status code (#9817)
The `shell_impl` and `shell_impl_async` functions no longer return
`success` because it was always `true`. If the command didn't succeed
both functions would return an `Err`.

This was also the reason, why `shell_keep_pipe` didn't work. It relied
upon the value of `success` and aborted in case of an `Err`.
It now removes any selection for which `shell_impl` returns `Err`.

If the command always fails, the selections are preserved and an error
message is displayed in the status bar.
2024-03-19 07:30:34 -05:00
Damian Zaręba
485c5cf0b8 Initial Ada language support (after stale) (#9908)
* Adding initial support for ada language, based off #7790 PR from tomekw

* More translation to helix-specific tree-sitter scm labels, add ada gpr switch to ada LSP

* Generate ada in lang-support.md using cargo xtask docgen

* Update tree-sitter definitions according to comments

* Remove .gpr glob from languages.toml

* Fix unit in languages.toml for ada, update locals.scm to helix needs
2024-03-19 13:28:15 +01:00
Arthur Deierlein
0b6dea6dc2 Enhance support for PKGBUILDS (#9909)
* enhance support for PKGBUILDS

* run cargo xtask docgen
2024-03-19 13:27:46 +01:00
Luis Useche
6a22d7d1ca Do not stop reloading docs on error (#9870)
In the `reload-all` command, we should not stop reloading the documents
if one error is found. Instead, we should report the error and continue
trying to reload the current open documents. This is useful in cases
where a backing file does not exist temporarily (e.g. when editing a git
patch in the outstanding chain that doesn't have a file just yet).

This change also remove the error messages in the cases where the
backing is `None`, like in new docs or `tutor`.
2024-03-19 12:16:30 +01:00
Khang Nguyen Duy
4d2282cbcc Respect undercurl config even with no terminfo (#9897)
I have just found out that my recent Windows Terminal version
supported rendering undercurl (see
https://devblogs.microsoft.com/commandline/windows-terminal-preview-1-20-release
). However, looking at the source, terminfo is required for helix to
emit the undercurl control code, which isn't available on Windows AFAIK.

This commit make helix respects the `editor.undercurl` option when
there is no terminfo.

Tested on Windows Terminal Preview 1.20

Signed-off-by: Khang Nguyen <khang.nguyenduycse@hcmut.edu.vn>
2024-03-19 12:12:37 +01:00
dependabot[bot]
3d4889ce9a build(deps): bump the rust-dependencies group with 3 updates (#9929)
Bumps the rust-dependencies group with 3 updates: [bitflags](https://github.com/bitflags/bitflags), [toml](https://github.com/toml-rs/toml) and [lsp-types](https://github.com/gluon-lang/lsp-types).


Updates `bitflags` from 2.4.2 to 2.5.0
- [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/2.4.2...2.5.0)

Updates `toml` from 0.8.10 to 0.8.12
- [Commits](https://github.com/toml-rs/toml/compare/toml-v0.8.10...toml-v0.8.12)

Updates `lsp-types` from 0.95.0 to 0.95.1
- [Changelog](https://github.com/gluon-lang/lsp-types/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gluon-lang/lsp-types/compare/v0.95.0...v0.95.1)

---
updated-dependencies:
- dependency-name: bitflags
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust-dependencies
- dependency-name: toml
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
- dependency-name: lsp-types
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-19 15:47:05 +09:00
mo8it
0f5430ab9e Optimize get_truncated_path 2024-03-19 14:39:46 +09:00
mo8it
e91ec8e880 Optimize getting a relative path 2024-03-19 14:39:46 +09:00
mo8it
6ed93b6e49 Optimize fold_home_dir 2024-03-19 14:39:46 +09:00
mo8it
6607938bf8 Call as_ref only once 2024-03-19 14:39:46 +09:00
Blaž Hrastnik
13533cb99c ci: Group minor rust dependency dependabot updates
https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#groups
2024-03-19 14:28:15 +09:00
dependabot[bot]
df8352ec05 build(deps): bump tokio-stream from 0.1.14 to 0.1.15 (#9926)
Bumps [tokio-stream](https://github.com/tokio-rs/tokio) from 0.1.14 to 0.1.15.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-stream-0.1.14...tokio-stream-0.1.15)

---
updated-dependencies:
- dependency-name: tokio-stream
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-19 14:14:09 +09:00
dependabot[bot]
ef797acf0d build(deps): bump anyhow from 1.0.80 to 1.0.81 (#9925)
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.80 to 1.0.81.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.80...1.0.81)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-19 14:13:35 +09:00
dependabot[bot]
7ef583bea7 build(deps): bump gix from 0.58.0 to 0.61.0 (#9924)
Bumps [gix](https://github.com/Byron/gitoxide) from 0.58.0 to 0.61.0.
- [Release notes](https://github.com/Byron/gitoxide/releases)
- [Changelog](https://github.com/Byron/gitoxide/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Byron/gitoxide/compare/gix-v0.58.0...gix-v0.61.0)

---
updated-dependencies:
- dependency-name: gix
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-19 14:13:28 +09:00
dependabot[bot]
326c078356 build(deps): bump thiserror from 1.0.57 to 1.0.58 (#9923)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.57 to 1.0.58.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.57...1.0.58)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-19 14:08:43 +09:00
dependabot[bot]
8dc50bded9 build(deps): bump clipboard-win from 5.2.0 to 5.3.0 (#9922)
Bumps [clipboard-win](https://github.com/DoumanAsh/clipboard-win) from 5.2.0 to 5.3.0.
- [Commits](https://github.com/DoumanAsh/clipboard-win/commits)

---
updated-dependencies:
- dependency-name: clipboard-win
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-19 14:08:36 +09:00
Jaakko Paju
58022586a0 Add yaml LSP for docker compose (#9916)
* Add yaml LSP for docker compose

* Change docs
2024-03-18 20:39:32 +01:00
Matthew Toohey
2e4653ea31 add koka language support (#8727)
Co-authored-by: Pascal Kuthe <pascal.kuthe@semimod.de>
2024-03-18 13:14:10 +01:00
Phil
94d210c9bf Add initial support for SuperCollider (#9329) 2024-03-18 13:13:23 +01:00
Michael Davis
4ffe993533 Fix malformed predicates in highlighting queries 2024-03-18 10:34:53 +09:00
Michael Davis
38af99f05f Bump tree-sitter to 0.22.2 2024-03-18 10:34:53 +09:00
Joey Hain
476e6baf8f Add textobject queries for vala (#8541) 2024-03-18 00:11:28 +01:00
Leonardo Eugênio
d99b6177c2 Add blade support (#9513)
* Add php-only language config and queries

php-only is required enabling php injections like in blade templates

* Add blade templates support
2024-03-18 00:07:09 +01:00
Carsten Führmann
eead105f94 Fix selected text background in toykonight (#9789)
Before the fix, the color that the original (Neovim) tokyonight uses for
Neovim's visual mode was used in Helix for highlighting the selected
item in the picker. But for the highlighting of selected _text_ in
Helix (corresponding to Neovim's visual mode), a much darker background
was used. This made it very hard to pick out selected text, in
particular in suboptimal lighting conditions.

I swapped the two colors, so that text selection now looks like in
Neovim, while selected items in the picker are highlighted a bit less
strongly. (But still easy to see because the whole line is highlighted.)
2024-03-18 00:06:23 +01:00
Erasin Wang
64389f97fe Updated grammar for hurl 4 (#9775) 2024-03-18 00:01:25 +01:00
Benedikt Ritter
f7913c1a3b Extend groovy support (#9677)
* Extend groovy support

Use more complete parser introduced in nvm-treesitter in
d4dac523d2

* Update runtime/queries/groovy/locals.scm

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Drop indent.scm for groovy

It was copied from the tree-sitter repository but is not
compatiblw with the way indent queries are implemented
in Helix.

* Adapt groovy highlights to helix syntax

* Update documentation

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-03-18 00:01:11 +01:00
Alexis Mousset
8457652da1 Update to modus-themes 4.4.0 (#9912) 2024-03-17 23:56:33 +01:00
Jonas De Vuyst
0301d01e78 Fix URL in doc chapter about Textobject queries (#5773)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-03-17 23:56:17 +01:00
Dan Cardamore
3890376a23 add 'file-absolute-path' to statusline (#4535)
* feat: add 'file-abs-path' to statusline (#4434)

* cleanup implementation

* rename to be non-abbreviated names

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-03-17 23:55:49 +01:00
George "Riye" Hollister
e36774c2c8 Add Support for JSONC (#9906)
* Added `jsonc` language with support for comments

The `vscode-json-language-server` accepts `jsonc` as a language id.
Allowing the use of comments within JSON files.

* fix: Update `injdection-rejex` to be unique

* fix: use includes to remove redundant queries

* ci: Generate language-support docs
2024-03-17 23:54:05 +01:00
Arthur Deierlein
9ec0271873 Add support for hyprland config (#9899)
* feat: add hyprland config language

* adjust indents to helix

* adjust highlights to helix
2024-03-17 23:53:30 +01:00
Arthur Deierlein
61f7d9ce2f fix typo "braket" in jsx highlights (#9910) 2024-03-17 17:36:54 -05:00
Emi
761df60077 Keybind for Extend/shrink selection up and down (#9080)
* implement another selection modifying command

* Selection feels more ergonomic in case of swapping the direction. This also fixes a problem when starting at an empty line.

* rename select_line_up/down to select_line_above/below

* apply clippy suggestion of using cmp instead of if-chain

* revert `Extent` implementing `Clone/Copy`

* move select_line functions below extend_line implementations

* implement help add function, which saturates at the number of text lines

---------

Co-authored-by: Emi <emanuel.boehm@gmail.com>
2024-03-17 23:06:24 +01:00
Nick
6fea7876a4 Fix comment key bind behaviour in OCaml (#9894) 2024-03-16 08:50:47 -04:00
Michael Davis
9282f1b8e5 Handle starting and continuing the count separately (#9887) 2024-03-16 08:52:57 +09:00
Mike Trinkala
b961acf746 Update regex-cursor (#9891) 2024-03-15 14:44:08 -05:00
Kirawi
0c51ab16d0 Add a yank diagnostic command (#9640)
* yank diagnostic command

* improve success message

* move to a typed command

* docgen
2024-03-15 17:38:22 +01:00
Michael Davis
6c4d986c1b Use non-deprecated chrono Duration functions 2024-03-14 14:13:56 +09:00
dependabot[bot]
b44b627b14 build(deps): bump chrono from 0.4.34 to 0.4.35
Bumps [chrono](https://github.com/chronotope/chrono) from 0.4.34 to 0.4.35.
- [Release notes](https://github.com/chronotope/chrono/releases)
- [Changelog](https://github.com/chronotope/chrono/blob/main/CHANGELOG.md)
- [Commits](https://github.com/chronotope/chrono/compare/v0.4.34...v0.4.35)

---
updated-dependencies:
- dependency-name: chrono
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-14 14:13:56 +09:00
dependabot[bot]
e01a558294 build(deps): bump log from 0.4.20 to 0.4.21 (#9856)
Bumps [log](https://github.com/rust-lang/log) from 0.4.20 to 0.4.21.
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.20...0.4.21)

---
updated-dependencies:
- dependency-name: log
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-14 14:13:36 +09:00
fnuttens
3915b04bd9 fix(themes-catppuccin): make inlay hints more legible (#9859) 2024-03-13 13:47:55 +09:00
dependabot[bot]
2d15acdf60 build(deps): bump libloading from 0.8.2 to 0.8.3 (#9857)
Bumps [libloading](https://github.com/nagisa/rust_libloading) from 0.8.2 to 0.8.3.
- [Commits](https://github.com/nagisa/rust_libloading/compare/0.8.2...0.8.3)

---
updated-dependencies:
- dependency-name: libloading
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-12 14:45:44 +09:00
dependabot[bot]
ab61874efb build(deps): bump cc from 1.0.88 to 1.0.90 (#9855)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.0.88 to 1.0.90.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Commits](https://github.com/rust-lang/cc-rs/compare/1.0.88...1.0.90)

---
updated-dependencies:
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-12 14:41:48 +09:00
dependabot[bot]
2e2a1d6f61 build(deps): bump open from 5.0.1 to 5.1.2 (#9854)
Bumps [open](https://github.com/Byron/open-rs) from 5.0.1 to 5.1.2.
- [Release notes](https://github.com/Byron/open-rs/releases)
- [Changelog](https://github.com/Byron/open-rs/blob/main/changelog.md)
- [Commits](https://github.com/Byron/open-rs/compare/v5.0.1...v5.1.2)

---
updated-dependencies:
- dependency-name: open
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-12 14:41:40 +09:00
dependabot[bot]
2d589e74f0 build(deps): bump cachix/install-nix-action from 25 to 26 (#9851)
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 25 to 26.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/v25...v26)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-12 14:38:19 +09:00
Kalpaj Chaudhari
c145999bff treesitter: Add textobjects for native funcs and constructors (#9806)
This allows native functions and constructors to be accessible as part
of goto_{next,prev}_func.

Change-Id: Ia1234004e8b38e1c5871331a38fcf4f267da935e
2024-03-10 12:23:33 +09:00
Aidan Gauland
3bd493299f Use Nu language for NUON files (#9839) 2024-03-10 12:22:04 +09:00
Markus F.X.J. Oberhumer
0dc67ff885 helix-term: allow to backspace out-of the command prompt (#9828) 2024-03-09 17:02:43 +09:00
Matthew Toohey
e3c6c82828 add linker script language (#9835) 2024-03-09 16:59:56 +09:00
Alexander Brevig
fd89c3c833 fix: close #9771 fix comments with ( and ) (#9800)
* fix: close #9771 update OCaml

* fix: no longer match on ( ) as the underlying grammar handles these

* fix: implement excellent corrections from review

* fix: module -> namespace to match theme scopes
2024-03-08 10:54:17 +09:00
Chris
301dfb07cc Add PowerShell highlighting (#9827) 2024-03-07 23:39:00 +01:00
Mike Trinkala
e27b04735c Fix panic in select_textobject_around (#9832)
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.
2024-03-07 13:37:01 -06:00
Mike Trinkala
cb01e52cd8 Fix panic in surround_replace/delete nested multi-cursor (#9815)
Test Document
-------------
```
{{

}
}

```

Steps To Reproduce
------------------
1. 2j  # move_visual_line_down
1. C   # copy_selection_on_next_line
1. mdm # surround_delete

Debug
-----
`assertion failed: last <= from', transaction.rs:597:13`

Release
-------
`called `Result::unwrap()` on an `Err` value: Char range out of bounds:
char range 18446744073709551614..18446744073709551615,
Rope/RopeSlice char length 7', ropey-1.6.1/src/rope.rs:546:37`

Description
-----------

Processing the surrounding pairs in order violates the assertion the
ranges are ordered. To handle nested surrounds all positions have to
be sorted. Also surround_replace has to track the proper replacement
character for each position.
2024-03-08 02:20:07 +09:00
dependabot[bot]
b93fae9c8b build(deps): bump mio from 0.8.9 to 0.8.11 (#9808) 2024-03-06 11:10:59 +09:00
dependabot[bot]
4e5f19df53 build(deps): bump clipboard-win from 5.1.0 to 5.2.0 (#9811) 2024-03-06 11:10:24 +09:00
dependabot[bot]
7a473c7494 build(deps): bump ahash from 0.8.9 to 0.8.11 (#9813) 2024-03-06 11:09:13 +09:00
dependabot[bot]
ea0b244644 build(deps): bump libloading from 0.8.1 to 0.8.2 (#9810) 2024-03-06 11:08:40 +09:00
dependabot[bot]
7d8c86e403 build(deps): bump arc-swap from 1.6.0 to 1.7.0 (#9809) 2024-03-06 11:08:07 +09:00
varris1
3f98891e79 flake.lock: Bump flake inputs to prevent a warning message (#9816) 2024-03-06 00:00:34 +09:00
RoloEdits
cc43e3521e feat(languages): add support for *.Dockerfile file-types naming convention (#9772)
Current `file-types` only supports up to a `Dockerfile.frontend` naming scheme.

With these changes `frontend.Dockerfile` now gives proper highlights and lsp actions.
2024-03-03 18:56:18 +01:00
Mike Trinkala
9267343830 Fix panic when using surround_replace/delete (#9796)
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.
2024-03-03 18:55:09 +01:00
Mike Trinkala
5bd007266a Fix panic when using join_selections_space (#9783)
Joining lines with Alt-J does not properly select the inserted spaces
when the selection contains blank lines. In the worst case it panics
with an out of bounds index.

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value:
Char index out of bounds: char index 11, Rope/RopeSlice char length 10'

Steps to reproduce:
* Create a new document
    ```
    a

    b

    c

    d

    e
    ```
* % (Select all)
* Alt-J (join and select the spaces)
2024-03-02 15:05:58 +01:00
Michael Davis
d769fadde0 Fix precedence of svelte typescript injection (#9777) 2024-03-02 16:47:24 +09:00
Malpha
f04dafa2e2 languages.toml: add elvish shebang (#9779) 2024-03-02 16:47:10 +09:00
Michael Davis
5ca6a448e9 Support LSP diagnostic tags (#9780) 2024-03-02 13:37:11 +09:00
Marcin Drzymala
1d6db30acf Fix bug 9703 by commenting out the wrong command (#9778)
* Fix bug 9703 by commenting out the wrong command

This fixes issue https://github.com/helix-editor/helix/issues/9703 by removing the wrong formatting command for justfiles.

* Fix indentation width for justfile
2024-03-02 11:05:17 +09:00
Felix Zeller
062fb819a2 feat: Add markdown-oxide language server (#9758) 2024-03-01 09:10:49 -06:00
Dawid Ciężarkiewicz
44db25939c Document embracing smart-tab navigation. (#9762)
Re #4443
2024-03-01 02:57:31 +01:00
Keir Lawson
d0bb774471 Mark GTK builder ui files as XML (#9754) 2024-02-29 19:09:29 +09:00
JJ
e51a1e4e2a Switch Nim tree-sitter queries to alaviss/tree-sitter-nim (#9722) 2024-02-29 10:49:10 +09:00
Pascal Kuthe
1143f47954 fix split_on_newline (#9756) 2024-02-29 10:47:41 +09:00
Brian Dorsey
f03b91d1b7 update languages.toml: tree-sitter-lua grammar (#9727)
* update languages.toml: tree-sitter-lua grammar

repo has moved, use new URL and the rev of the latest release (v0.0.19)

* update highlight queries

a novice attempt to port query updates from the
source repo to Helix captures and ordering

* Apply suggestions from code review

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-02-28 20:55:17 +01:00
Chris
083a9e775d Add support for pde files (#9741) 2024-02-28 13:18:00 +01:00
Mo
00653c772e Avoid cloning the whole paragraph content just for rendering (#9739)
* Avoid cloning the whole paragraph content just for rendering

* Fix tests
2024-02-27 18:24:05 +01:00
Gabriel Dinner-David
26b3dc29be toggling of block comments (#4718) 2024-02-27 22:36:25 +09:00
dependabot[bot]
f46a09ab4f build(deps): bump cc from 1.0.85 to 1.0.88 (#9734)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.0.85 to 1.0.88.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Commits](https://github.com/rust-lang/cc-rs/compare/1.0.85...1.0.88)

---
updated-dependencies:
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-27 02:06:37 +01:00
巢鹏
358ac6bc1f add fidl support (#9713) 2024-02-27 01:41:50 +01:00
dependabot[bot]
1a82aeeae9 build(deps): bump serde from 1.0.196 to 1.0.197 (#9736)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.196 to 1.0.197.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.196...v1.0.197)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-27 01:26:24 +01:00
dependabot[bot]
ea95c68775 build(deps): bump serde_json from 1.0.113 to 1.0.114 (#9735)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.113 to 1.0.114.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.113...v1.0.114)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-27 01:25:52 +01:00
dependabot[bot]
d0f8261141 build(deps): bump tempfile from 3.10.0 to 3.10.1 (#9733)
Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.10.0 to 3.10.1.
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.10.0...v3.10.1)

---
updated-dependencies:
- dependency-name: tempfile
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-27 01:25:17 +01:00
dependabot[bot]
b43d9aa306 build(deps): bump ahash from 0.8.6 to 0.8.9 (#9737)
Bumps [ahash](https://github.com/tkaitchuck/ahash) from 0.8.6 to 0.8.9.
- [Release notes](https://github.com/tkaitchuck/ahash/releases)
- [Commits](https://github.com/tkaitchuck/ahash/commits/v0.8.9)

---
updated-dependencies:
- dependency-name: ahash
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-27 01:22:00 +01:00
Pascal Kuthe
cd02976fa3 switch to regex-cursor (#9422) 2024-02-26 16:45:20 +09:00
Tobias Hunger
c68ec92c5e slint: Update SHA of tree-sitter parser (#9698) 2024-02-26 16:08:31 +09:00
Carsten Führmann
a876148585 Fix colors of tokyonight diagnostic undercurls (#9724) 2024-02-26 10:53:59 +09:00
Michael Davis
928bf80d9a LSP: Normalize diagnostic file paths 2024-02-26 00:12:43 +09:00
Michael Davis
8141a4a1ab LSP: Key diagnostics off file path instead of URI
URIs need to be normalized to be comparable. For example a language
server could send a URI for a path containing '+' as '%2B' but we might
encode this in something like 'Document::url' as just '+'. We can
normalize the URI straight into a PathBuf though since this is the only
value we compare these diagnostics URIs against. This also covers
edge-cases like windows drive letter capitalization.
2024-02-26 00:12:43 +09:00
Ryan Mehri
dfa5382c51 Don't run scheduled builds on forks (#9718) 2024-02-25 19:37:54 +09:00
Mo
6db666fce1 Optimization of tilde expansion (#9709)
* Use next and avoid a redundant prefix strip

* Avoid allocations

Especially when `expand_tilde` is claled on a path
that doesn't contain a tilde.

* Add a test

* Use Into<Cow<…>>

* Put the expand_tilde test at the end of the file

* Remove unused importsw
2024-02-24 16:59:11 +01:00
DS/Charlie
ec9efdef3b Bump tree-sitter-sql (#9634) 2024-02-24 12:28:25 +09:00
wr7
38484f33e5 Completely fix bash autocomplete handling of filenames with spaces (#9708) 2024-02-24 11:54:40 +09:00
Jake Low
03623f2f40 Add osm and osc extensions to xml language filetypes (#9697) 2024-02-24 11:53:16 +09:00
wr7
7100ed4efc Properly handle spaces in filenames in bash autocomplete (#9702) 2024-02-23 16:46:41 +01:00
Michael Davis
b7b6f30084 Use a hook for resolving completion items
Previously we used the IdleTimeout event to trigger LSP
`completion/resolveItem` requests. We can now refactor this to use an
event system hook instead and lower the timeout.
2024-02-22 22:37:23 -05:00
Abderrahmane TAHRI JOUTI
98ebeeebd8 Cyan Light theme : Add License and Author (#9688)
* Cyan Light theme : Add License and Author

* Add License

Copy  license from https://github.com/OlyaB/CyanTheme/blob/master/LICENSE

* better credits to original author
2024-02-21 23:47:14 +09:00
Benedikt Ritter
eca537615a Use groovy support when editing Gradle files (#9681)
The Gradle build tool provides two DSLs for configuring builds. On is
based on Groovy and Gradle build files written in Gradle Groovy DSL use
*.gradle file ending.

This change adds `gradle` to the supported file types of the groovy
language configuration.
2024-02-21 23:46:31 +09:00
dependabot[bot]
cad0209e20 build(deps): bump textwrap from 0.16.0 to 0.16.1 (#9674)
Bumps [textwrap](https://github.com/mgeisler/textwrap) from 0.16.0 to 0.16.1.
- [Release notes](https://github.com/mgeisler/textwrap/releases)
- [Changelog](https://github.com/mgeisler/textwrap/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mgeisler/textwrap/compare/0.16.0...0.16.1)

---
updated-dependencies:
- dependency-name: textwrap
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-20 17:07:16 +01:00
dependabot[bot]
d2aacb3e36 build(deps): bump anyhow from 1.0.79 to 1.0.80 (#9675)
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.79 to 1.0.80.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.79...1.0.80)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-20 17:06:58 +01:00
dependabot[bot]
27335476ed build(deps): bump chrono from 0.4.33 to 0.4.34 (#9673)
Bumps [chrono](https://github.com/chronotope/chrono) from 0.4.33 to 0.4.34.
- [Release notes](https://github.com/chronotope/chrono/releases)
- [Changelog](https://github.com/chronotope/chrono/blob/main/CHANGELOG.md)
- [Commits](https://github.com/chronotope/chrono/compare/v0.4.33...v0.4.34)

---
updated-dependencies:
- dependency-name: chrono
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-20 17:06:40 +01:00
Volodymyr Chernetskyi
990378a46b Add Groovy grammar (#9350)
* Add Groovy grammar

* Rewrite Neovim captures into Helix for Groovy

* Simplify Groovy injections

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Remove Neovim's spell from Groovy highlights

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Apply suggestions to languages.toml

* Escape backslash in groovy highlights.scm

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-02-19 18:37:02 +01:00
Jonathan LEI
cdef4f8a70 Make mouse click extend selection in select mode (#5436)
* Make mouse click extend selection in select mode

* chore: better readability with `Option::take()`
2024-02-19 14:08:26 +01:00
nkitsaini
787cc36092 fix LSP ComplitionTriggerKind value for TriggerKind::Auto (#9660) 2024-02-19 13:58:17 +01:00
Jaakko Paju
ebf155d635 Add textobject queries for HCL (#9658)
* Add textobject queries for HCL

* Add to lang-support.md
2024-02-19 00:46:32 +01:00
Jaakko Paju
2dc9ce68ec Add textobject queries for Nix (#9659)
* Add textobject queries for Nix

* Add to lang-support.md
2024-02-19 00:46:13 +01:00
Malpha
c72426cc87 Add docker-compose language (#9661)
* languages: add docker-compose language

it uses docker-compose-langserver as lsp
And yaml for syntax highlighting, indents and injections

* languages: add luajit as a shebang of lua

This helps to provide syntax highlighting and
other lua goodies when writing luajit

* book(update): run cargo xtask docgen

* since #8006 full filenames uses glob
2024-02-19 00:19:44 +01:00
Jimmy Zelinskie
b950dea003 add monokai soda theme (#9651) 2024-02-19 00:19:26 +01:00
AlexanderDickie
9ab3f9d01a Scroll cursor and page together (neovim-like scrolling) (#8015)
* neovim like scroll function

* clear line annotations outside of move_vertically/_visual

* add nvim scroll function to commands

* assign nvim-scroll to C-d and C-u (half page scrolls)

* dont remove backspace and space mapping

* move non-softwrap logic to seperate function, call this in nvim-scroll fn

* Revert "move non-softwrap logic to seperate function, call this in nvim-scroll fn"

This reverts commit e4905729c3.

* Revert "clear line annotations outside of move_vertically/_visual"

This reverts commit 1df3fefe55.

* add TODO for when inline diagnostics gets merged

* move nvim-scroll logic into scroll(), dont respect scrolloff

* run cargo fmt

* run cargo clippy

* update documenation for Ctrl-d and Ctrl-u remap
2024-02-19 00:13:04 +01:00
Vince Varga
6432669822 Add tmux.conf as a bash file type (#9653)
* Add conf as a bash file type

Tmux and tmux.conf is used widely in software developer circles.

Having the tmux.conf file not have any syntax highlighting by default is (IMO) not ideal for an editor that otherwise "just works".

* Use tmux.conf glob instead of simply conf for tmux

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-02-18 15:55:21 +01:00
melted-brownie
78c34194b5 Improve textobjects for parameter/argument for Dart (#9644)
Co-authored-by: Sébastien Blondiau <sebastien.blondiau@iot-d.com>
2024-02-17 17:09:21 +01:00
Vivek Kethineni
3e963b3c1b Add Rust fields as argument textobject (#9637)
* added field_declaration_list and field_initializer_list as parameter textobjects

* removed field_declaration_listt from textobjects.scm
2024-02-17 17:08:44 +01:00
Nick Condron
6ffe09e873 Fix Sonokai theme to better match original (#5379)
* Make sonokai palette perfectfully faithful

* Amend theme to better match original sonokai

Changes based on the following references:
(1) https://www.sainnhe.dev/post/contributing-guide/#sonokai
(2) https://github.com/sainnhe/sonokai/blob/master/colors/sonokai.vim

* Make constants white (1)
* Make builtin variables purple (1)
* Make members orange (1)
* Make labels red (2)
* Make operators red (1)
* Make all punctuation grey (2)
* Make builtin functions and macros green (2)
* Make diff delta blue (2)
* Make cursor match bg4 (2)
* Make visible whitespace bg4 (2)

* Make Sonokai special punctuation yellow
2024-02-17 17:08:18 +01:00
Matt
76e512f944 Remove unwrap on line option, preventing DAP crash (#9632)
* Remove unwrap on line option, preventing DAP crash, ref #4683

* Update to fall back to existing values for option fields
2024-02-16 15:43:14 +01:00
Michael Davis
59369d99e2 Bump tree-sitter-erlang, add *.app.src file-type (#9627) 2024-02-15 01:55:55 +09:00
Mehdi Abedi
4df08ddbe0 Allow numbers as second input event (#8471)
* Make sure pending key list is empty when count handling

This will allow using numbers as second key event.

* count handling; add an exception for 'g'

* Lookup the key event before considering a number as count

* Avoid the allocation of another vec for the pending keys

---------

Co-authored-by: x <x@torrent>
2024-02-14 11:53:15 +01:00
Mihir Gadgil
c59f29921d Add changes to history when paste-replacing (#9625) 2024-02-13 10:16:23 -06:00
kyfanc
fe869e5dc7 fix lsp config reload (#9415)
`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>
2024-02-13 11:58:53 +01:00
dependabot[bot]
7934ac7714 build(deps): bump cc from 1.0.83 to 1.0.85 (#9618)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-13 09:58:23 +09:00
dependabot[bot]
36ad70e4c7 build(deps): bump unicode-segmentation from 1.10.1 to 1.11.0 (#9617)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-13 09:57:37 +09:00
dependabot[bot]
c55bf72d25 build(deps): bump clipboard-win from 5.0.0 to 5.1.0 (#9616)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-13 09:57:22 +09:00
dependabot[bot]
caad87e999 build(deps): bump thiserror from 1.0.56 to 1.0.57 (#9615)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-13 09:57:12 +09:00
ves
fd7b722dfb theme: horizon-dark fix constructor color (#9493)
* theme: add horizon-dark

* fix whitespace color and gutter selected

* taplo fmt

* markup and color tweaks

markup colors
diff colors
better comment and menu colors

* horizon-dark: fix constructor color

makes Some and None to look better and more like the vscode theme
2024-02-13 01:49:42 +09:00
Chris
661e123152 Add support for Odin's formatter (#9537) 2024-02-13 01:49:04 +09:00
dependabot[bot]
c111e28a6f build(deps): bump toml from 0.7.6 to 0.8.10 (#9539)
Bumps [toml](https://github.com/toml-rs/toml) from 0.7.6 to 0.8.10.
- [Commits](https://github.com/toml-rs/toml/compare/toml-v0.7.6...toml-v0.8.10)

---
updated-dependencies:
- dependency-name: toml
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-13 01:48:45 +09:00
Gagan Janjua
d232e7a985 Adding Curzon theme (#9553)
* adding Curzon theme

* Adding cursive strings
2024-02-13 01:48:18 +09:00
Mark Stosberg
0516337abb docs: Document that what the diff gutter symbol does (#9587)
Before there was no document about what the `diff` gutter is displaying
or what the colors mean.

These docs clarify it's a `git` diff and makes it easier to
cross-reference the theme if you aren't sure what the colors mean or
want to change them.
2024-02-13 01:48:10 +09:00
Tom Manner
bb1e2ddcd8 Added "zon" file type to zig language section. (#9582)
`build.zig.zon` is what 0.11.0 uses for external dependencies.  The syntax is a subset of zig and can be highlighted and formatted like normal zig code.
2024-02-13 01:47:52 +09:00
kpbaks
78ed3aded3 feat(languages): use fish_indent as the formatter for fish 2024-02-13 01:47:36 +09:00
kpbaks
0eec518ff6 feat(languages): add formatter for just 2024-02-13 01:47:36 +09:00
Chirikumbrah
45ee568b98 Dracula whitespace color changes (#9588)
* added color to render whitespace characters

* made some alphabet sort
2024-02-13 01:47:08 +09:00
iko
d7c7589fd5 Add Hoon (#9190)
* Added Hoon

* Added highlights.scm

* Updated docs

* Update runtime/queries/hoon/highlights.scm

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-02-12 16:36:14 +01:00
Blaž Hrastnik
ad7b7bc804 minor: Fix compilation 2024-02-12 12:01:17 +09:00
ontley
6a90166d0a Add required-root-patterns for situational lsp activation (#8696)
* 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.
2024-02-12 02:35:25 +01:00
HumanEntity
ac8d1f62a1 sonokai: Add color modes support and change contrast between ruler and bg (#9376)
* Added `editor.color-modes` option support

* Less contrast between bg and ruler
2024-02-12 02:29:49 +01:00
Jimmy Zelinskie
d9f7aaacaf languages: add CEL, SpiceDB schema language (#9296)
* languages: add CEL language and grammar

* languages: add spicedb schema language

* chore: docgen

* runtime/queries: refine spicedb & cel highlights

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* languages: update spicedb

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-02-12 02:28:52 +01:00
dependabot[bot]
7d8ce1a400 build(deps): bump tempfile from 3.9.0 to 3.10.0 (#9538)
Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.9.0 to 3.10.0.
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.9.0...v3.10.0)

---
updated-dependencies:
- dependency-name: tempfile
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-12 02:23:24 +01:00
7ombie
204c3707b0 Updated Swift grammar, adding 'any' and 'await' keywords. (#9586) 2024-02-12 02:17:44 +01:00
dependabot[bot]
13b9885084 build(deps): bump tokio from 1.35.1 to 1.36.0 (#9540)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.35.1 to 1.36.0.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.35.1...tokio-1.36.0)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-12 02:17:02 +01:00
Kirawi
786b5c533e follow neovim's truecolor detection (#9577) 2024-02-11 18:38:09 +01:00
Galen Abell
581a1ebf5d Add glob file type support (#8006)
* 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>
2024-02-11 18:24:20 +01:00
Android789515
d570c29ce3 expand upon the arch linux install instructions (#9574)
Signed-off-by: Android789515 <derflug@mailfence.com>
2024-02-09 08:29:11 -06:00
Matouš Dzivjak
d137a08231 feat(languages): pkl (#9515)
* feat(languages): pkl

Add [pkl](https://github.com/apple/pkl) language.
Official documentation: https://pkl-lang.org/

* remove branch indent
2024-02-09 11:44:46 +01:00
ath3
f8e2d822ba Fix scroll track (#9508) 2024-02-09 03:24:45 +01:00
Tobias Hunger
a1272bdb17 slint: Update treesitter parser and queries (#9551)
* slint: Update treesitter parser and queries

* slint: Port over suggestions from nvim review
2024-02-07 19:36:29 +01:00
Michael Davis
bbcc89241f Fix pulldown_cmark breaking changes to tag types
* Tags and TagEnd are now separate enums since
  <https://redirect.github.com/raphlinus/pulldown-cmark/pull/517>.
* The `Tag::Heading` member has been changed from a tuple variant to a
  struct variant.
2024-02-07 23:53:51 +09:00
dependabot[bot]
630d91168a build(deps): bump pulldown-cmark from 0.9.6 to 0.10.0
Bumps [pulldown-cmark](https://github.com/raphlinus/pulldown-cmark) from 0.9.6 to 0.10.0.
- [Release notes](https://github.com/raphlinus/pulldown-cmark/releases)
- [Commits](https://github.com/raphlinus/pulldown-cmark/compare/v0.9.6...v0.10.0)

---
updated-dependencies:
- dependency-name: pulldown-cmark
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-07 23:53:51 +09:00
dependabot[bot]
72c508de24 build(deps): bump libc from 0.2.152 to 0.2.153 (#9541)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-07 17:34:49 +09:00
Bogdan Agica
c64a0e615b Revert "build(deps): bump cc from 1.0.83 to 1.0.84 (#8809)" (#9548) 2024-02-07 16:50:14 +09:00
eh
28a39e6efc Fix cursorline Zed OneDark (#9549)
Co-authored-by: e4 <eric.correia@dronesense.com>
2024-02-07 01:47:13 +09:00
Diego
a37af2dcbf fix division by zero when prompt completion area is too small (#9524) 2024-02-06 22:45:57 +09:00
eh
1d87c6a999 Update colors used for zed themes (#9544)
Official colors used is now publically available: https://github.com/zed-industries/zed/blob/main/assets/themes/one/one.json
Modified the theme to more accurately reflect the actual colors being used.

Co-authored-by: e4 <eric.correia@dronesense.com>
2024-02-06 15:13:20 +09:00
Matouš Dzivjak
0975d9c5e7 feat(languages): golang comments and numeric types (#9525) 2024-02-06 09:55:56 +09:00
Doug Kelkhoff
5c567f31e2 Adding two themes using only colors from 16-color terminal themes (#9477)
* adding 16-color terminal themes

* minor consistency update

* minor consistency update

* rename to be more consistent with other helix theme name conventions

* fixing improper theme inherits name
2024-02-04 02:11:20 +01:00
zetashift
6e3ed7f0fa Update Unison tree-sitter grammar for type changes and add indent queries (#9505)
* Update Unison tree-sitter grammar for type changes

* Add indent queries for Unison

* Improve Unison indent queries
2024-02-04 02:10:20 +01:00
Jaakko Paju
75d61d8149 Improve tree-sitter queries for Scala (#9475)
- Simplify function highlighting
- Highlight extension methods
- Textobject query (mia/maa) for class/trait constructor parameters/arguments
- Textobject query (mif/maf) for Scala 3 braceless lambdas
2024-02-04 02:09:42 +01:00
Novus Nota
d1054de3ce feat: Add Tact language support (#9512)
Re-submitting
2024-02-04 02:09:11 +01:00
Devyn Cairns
3f380722fb Update grammars for Nushell to rev 358c4f50 (#9502) 2024-02-04 02:04:51 +01:00
Matouš Dzivjak
d545452819 feat(queries): regex injection for golang (#9510) 2024-02-04 00:27:40 +01:00
Shoyu Vanilla
81ae768a4e Use gix pipeline filter instead of manual crlf implementation (#9503) 2024-02-03 12:23:33 -06:00
dependabot[bot]
70cea93bff build(deps): bump serde_json from 1.0.111 to 1.0.113 (#9471) 2024-02-02 10:34:49 -07:00
dependabot[bot]
aa4241c973 build(deps): bump chrono from 0.4.32 to 0.4.33 (#9472) 2024-02-02 10:34:24 -07:00
dependabot[bot]
5ec9565ddb build(deps): bump serde from 1.0.195 to 1.0.196 (#9473) 2024-02-02 10:34:05 -07:00
dependabot[bot]
dd59602809 build(deps): bump pulldown-cmark from 0.9.3 to 0.9.6 (#9474) 2024-02-02 10:33:46 -07:00
Andrew Carter
dbac78bb3c Set ui.virtual.ruler background for GitHub themes (#9487)
Turning on a ruler does not show a visible ruler
line for the GitHub themes. This change renders
rulers using the `canvas.subtle` color. This
matches the color used for the `cursorline` and
creates a visible ruler that fits the theme.
2024-02-01 02:18:53 +01:00
Waleed Dahshan
cf4492174d Use range positions to determine insert_newline motion (#9448)
* use anchor and head positions to determine motion

* use range cursor to decide extending or shifting

* add condition to cursor moving back on normal
2024-01-30 06:58:33 +09:00
Pascal Kuthe
87a720c3a1 make path changes LSP spec conform (#8949)
Currently, helix implements operations which change the paths of files
incorrectly and inconsistently. This PR ensures that we do the following
whenever a buffer is renamed (`:move` and workspace edits)

* always send did_open/did_close notifications
* send will_rename/did_rename requests correctly
  * send them to all LSP servers not just those that are active for a
    buffer
  * also send these requests for paths that are not yet open in a buffer (if
    triggered from workspace edit).
  * only send these if the server registered interests in the path
* autodetect language, indent, line ending, ..

This PR also centralizes the infrastructure for path setting and
therefore `:w <path>` benefits from similar fixed (but without didRename)
2024-01-29 01:34:45 +09:00
sogaiu
f5b67d9acb Use janet-simple grammar for Janet (#9247)
* Use janet-simple grammar for Janet

* Update book

* Tweak language name and related

* Rename janet-simple to janet in book

* Remove spurious language section for janet

* Drop quote_lit and qq_lit related highlighting

---------

Co-authored-by: sogaiu <983021772@users.noreply.github.com>
Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2024-01-28 19:17:46 +09:00
NitinKM
4ab7029535 Add icon to Windows executable (#9104)
* injecting the icon through a resource file, no extra deps

* formatted

* scripted rc compilation

* formatted and restructured

* simplified conditional func call
2024-01-28 18:31:10 +09:00
Twinkle
eb3c4e9f00 feat: add hard/soft contrast for gruvbox light mode (#9266) 2024-01-28 18:20:51 +09:00
Ryan Roden-Corrent
fe44391016 Add argument to textobject in gdscript. (#9288)
Currently `maa` only selects parameters in a function definition.
Allow it to also select arguments inside a function call.
2024-01-28 18:19:25 +09:00
Jaakko Paju
ee68fd09ac highlight(scala): highlight abstract methods in traits and classes (#9340) 2024-01-28 18:18:35 +09:00
Abderrahmane TAHRI JOUTI
0328fa4d02 adjust color darkness on ruler & inlay-hints (#9375) 2024-01-28 18:14:12 +09:00
Michael Davis
035b8eabdb Respect injections in movement::move_parent_node_end 2024-01-28 18:13:33 +09:00
Michael Davis
8b6565c839 Respect injections in :tree-sitter-highlight-name 2024-01-28 18:13:33 +09:00
Michael Davis
5e0b3cc28b Use injection syntax trees for bracket matching
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.
2024-01-28 18:13:33 +09:00
Jaakko Paju
9978d421fe Include interpolated SQL strings in Scala injection queries (#9428)
* Change Scala injection queries to include SQL strings

* Include block comments in comment injection

* Change #match predicate to #any-of

Co-authored-by: Kirawi <67773714+kirawi@users.noreply.github.com>

---------

Co-authored-by: Kirawi <67773714+kirawi@users.noreply.github.com>
2024-01-28 18:12:07 +09:00
Travis Harmon
f0be0c6d4a Make status line modes bold for theme onedark (#9435)
* Make status line modes bold

* Revert change to onedarker
2024-01-28 18:11:31 +09:00
Chirikumbrah
1616021a5a Make status line modes bold (#9449) 2024-01-28 18:11:05 +09:00
Poliorcetics
0d09fb4f55 lang(git-ignore): add helix/ignore to git-ignore file types (#9447) 2024-01-27 13:17:37 -06:00
blinxen
2661e05b34 Update some grammars to a commit where the license file is included (#9279)
Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-01-25 14:12:17 +09:00
Nick
d8b8d2fda6 Fix error message shown for goto references (#9382) 2024-01-25 14:11:12 +09:00
Michael Davis
cda8ea991e highlighting: Gate multiple captures behind #is-not? local predicates (#9390) 2024-01-25 14:10:58 +09:00
Blaž Hrastnik
83f09ecbff minor: Silence noisy language server not found error in log 2024-01-24 16:00:21 +09:00
Michael Davis
cb25d13028 Improve error handling for which::which failures
Co-authored-by: Pascal Kuthe <pascalkuthe@pm.me>
2024-01-24 15:47:49 +09:00
Michael Davis
6d724a8f33 Re-export which from helix-stdx::env
We use `which::which` in many crates, so `which` was a separate
dependency across all of them. We can centralize `which` into the
stdx crate so it's easy for all crates to depend on it.

I also moved the rest of `helix-view/src/env.rs` into helix-stdx's
`env` module since it only contained a thin wrapper around `which`
and `std::env`.
2024-01-24 15:47:49 +09:00
Blaž Hrastnik
6bfe1ddc53 minor: Silence noisy set_error log
Outside of debugging tests, it makes no sense to log this.
2024-01-24 15:31:16 +09:00
dependabot[bot]
b606c05246 build(deps): bump actions/cache from 3 to 4 (#9402)
Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-23 20:23:39 +01:00
Idobenhamo
299bcce481 Update Typst Tree-Sitter grammar (#9403)
Co-authored-by: Idobenhamo <idobenhamo@users.noreply.github.com>
2024-01-23 18:27:46 +01:00
melted-brownie
2058b3732c Add text object queries for dart (#9411)
* Add text object queries for dart

* Update runtime/queries/dart/textobjects.scm

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Clean up internal capture name

---------

Co-authored-by: Sébastien Blondiau <sebastien.blondiau@iot-d.com>
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-01-23 18:27:09 +01:00
dependabot[bot]
7caae13465 build(deps): bump gix from 0.57.1 to 0.58.0 (#9407)
Bumps [gix](https://github.com/Byron/gitoxide) from 0.57.1 to 0.58.0.
- [Release notes](https://github.com/Byron/gitoxide/releases)
- [Changelog](https://github.com/Byron/gitoxide/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Byron/gitoxide/compare/gix-v0.57.1...gix-v0.58.0)

---
updated-dependencies:
- dependency-name: gix
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-23 16:56:16 +01:00
dependabot[bot]
cbd8602018 build(deps): bump smallvec from 1.12.0 to 1.13.1 (#9405)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-23 23:19:36 +09:00
Jaakko Paju
4168864572 Add bufferline config for onedark & onedarker themes (#9397) 2024-01-23 23:19:22 +09:00
dependabot[bot]
ae8042bb83 build(deps): bump bitflags from 2.4.1 to 2.4.2 (#9404)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-23 11:24:38 +09:00
dependabot[bot]
e85507ccac build(deps): bump regex from 1.10.2 to 1.10.3 (#9408)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-23 11:24:29 +09:00
dependabot[bot]
960cda60ab build(deps): bump chrono from 0.4.31 to 0.4.32 (#9409)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-23 11:22:42 +09:00
Pascal Kuthe
8e592a151f refactor completion and signature help using hooks 2024-01-23 11:20:19 +09:00
Pascal Kuthe
13ed4f6c47 Add hook/event system 2024-01-23 11:20:19 +09:00
Boris Verkhovskiy
7d7ace551c Highlight .bash_history as bash (#9401) 2024-01-23 00:19:28 +01:00
Jaakko Paju
9ed3dc52e0 Update Scala tree-sitter grammar (#9348)
* Update Scala tree-sitter grammar

* Support block comments

Modify comment handling in textobjects and highlights to support new TS-scala node type 'block_comment'
2024-01-22 19:51:56 +01:00
woojiq
52a43bcdfc bash, make, css: highlight and indent queries improvement (#9393)
* highlights(bash): rework keywords section

* Use more specified scope when possible for keywords like @keyword.repeat.
* Add more keywords like "local" or "unsetenv".

Limitation:
* Bash doesn't allow you to have a local variable outside of a function, so maybe we need to have better queries to not highlight the local in this case.
* If we name a function with a keyword (such as unset or local), it will use the highlight scope "keyword" instead of "function".

* indents(css, make): add basic queries

* Despite the fact that queries look simple, they improve indentation in some edge cases that helix couldn't handle correctly by default.
2024-01-22 19:51:12 +01:00
Matthew Toohey
f5f08becef Fix typo in string representation of GotoReference (#9395) 2024-01-22 23:06:20 +09:00
Ahmed Hagi
9c56afeff3 Handle failure when enabling bracketed paste (#9353)
* match instead of crash

* pulling bracketedpaste out, refactor, tracking for bracketed paste

* sending disable bracketed paste only when supports true

* move disable bracketed paste to throwaway
2024-01-18 13:34:06 +01:00
Michael Davis
1bc7aac780 Use helix-stdx tilde expansion and normalization for HELIX_RUNTIME paths
Previously this wasn't possible since helix-core depends on helix-loader,
so helix-loader couldn't use helix-core's path extensions.

We use the path normalization/canonicalization for the runtime directory
provided by the HELIX_RUNTIME environment variable. This improves a
scenario where you set a path containing a tilde. Now that path will be
expanded and normalized.
2024-01-18 10:57:53 +09:00
Michael Davis
1f916e65cf Create helix-stdx crate for stdlib extensions
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).
2024-01-18 10:57:53 +09:00
Daniel Sedlak
af8e524a7d Address clippy lints (#9371) 2024-01-17 12:40:45 -06:00
Matouš Dzivjak
c60ba4ba04 feat(lsp): implement show document request (#8865)
* feat(lsp): implement show document request

Implement [window.showDocument](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#window_showDocument)
LSP server-sent request.

This PR builds on top of helix-editor#5820,
moves the external-URL opening functionality into shared crate-level
function that returns a callback that is now used by both the
`open_file` command as well as the window.showDocument handler if
the URL is marked as external.

* add return

* use vertical split

* refactor

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-01-17 18:24:38 +01:00
HumanEntity
6754acd83f Made inlay-hints not look like normal code (#9370)
Added `"ui.virtual.whitespace" = { fg = "grey_dim" }` line
2024-01-17 18:23:46 +01:00
Ben Dennis
dcdecaab22 Exit a language server if it sends a message with invalid json (#9332)
* Keep lsp event listener thread alive when malformed json is encountered from the lsp server

* Update unexpected error flow in recv() to close outstanding requests and close the language server

* Log malformed notifications as info instead of error

* Make close_language_server a nested function inside recv, similar to what's done in send

* Update malformed notification log text

* Clean up new log text a bit

* Initialize recv_buffer closer to where it's used

* Use "exit" instead of "close"

* Remove whitespace

* Remove the need for a helper method to exit the language server

* Match on Unhandled error explicitly and keep catch-all error case around
2024-01-17 15:49:25 +01:00
Jeremy Brudvik
f41727cc9c Support PureScript's new spago.yaml configs (#9362) 2024-01-17 23:15:38 +09:00
Kirawi
6339a8c95a Delete .ignore (#9363)
This isn't being used for anything anymore.
2024-01-17 15:15:09 +01:00
Kirawi
44cb8e5475 update tempfile dev-dependency to 3.9 (#9359) 2024-01-16 18:32:05 -06:00
dependabot[bot]
eef46b1aed build(deps): bump cachix/cachix-action from 13 to 14 (#9347)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-16 14:13:12 +09:00
dependabot[bot]
bd9eef1f90 build(deps): bump cachix/install-nix-action from 24 to 25 (#9346)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-16 14:13:04 +09:00
dependabot[bot]
0e7f5d604e build(deps): bump thiserror from 1.0.52 to 1.0.56 (#9345)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-16 14:12:39 +09:00
dependabot[bot]
fa1d8dfabc build(deps): bump anyhow from 1.0.78 to 1.0.79 (#9344)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-16 14:12:32 +09:00
dependabot[bot]
2d8d16ff5e build(deps): bump rustix from 0.38.28 to 0.38.30 (#9342)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-16 14:12:25 +09:00
dependabot[bot]
8a00620a71 build(deps): bump smallvec from 1.11.2 to 1.12.0 (#9341)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-16 14:12:15 +09:00
JR
6ce57b7924 Fix export instructions in installation doc (#9306) 2024-01-15 21:43:23 +01:00
Michael Davis
eca3ccff76 Select subtree within injections in :tree-sitter-subtree (#9309)
`: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.
2024-01-15 15:34:38 +09:00
Michael Davis
3011df4f35 Bump tree-sitter to latest master (#9317)
* query capture names now return `&str`s rather than `String`s
* the `#any-of?` predicate is now supported
2024-01-15 15:33:26 +09:00
Pascal Kuthe
445f7a273a ignore empty TS nodes in match bracket 2024-01-15 15:32:07 +09:00
Pascal Kuthe
2fb7e50b54 don't crash in plaintext bracket match (mm) on empty file 2024-01-15 15:32:07 +09:00
woojiq
3f88a3f4e6 Change path normalization strategy to not resolve symlinks (#9330) 2024-01-14 08:46:32 -06:00
Sebastian Zivota
a0b02106c3 Make nix flake respect unused grammars (#9326)
* Make nix flake respect unused grammars

* Use default value

* Refactor

* Take use-grammars.only into account

---------

Co-authored-by: Sebastian Zivota <sebastian.zivota@mailbox.org>
2024-01-14 15:11:40 +01:00
jw013
054ce3961a Fallback to filename for +arg (#9333) 2024-01-14 15:11:18 +01:00
Michael Davis
17dd102e5c Remove sourcehut tree-sitter grammars from default build (#9316)
Sourcehut has outages occasionally that cause the CI and from-source
builds to fail. It also doesn't setup redirects when a user renames
themselves, so if a user that publishes a tree-sitter grammar we use
changes their sourcehut name then it breaks the build and any prior
builds using that grammar.

For now let's remove them from the default build. It's a bandaid over
a larger reliability and trust problem with the grammar repositories
but it should fix the build for now.
2024-01-11 09:26:25 -06:00
Pascal Kuthe
7739d3ece1 Revert "build(deps): bump ahash from 0.8.6 to 0.8.7" (#9294) 2024-01-11 22:13:39 +09:00
Gabriel Dinner-David
84e24b33dc make sure to sync views when applying edits to unfocused views (#9173) 2024-01-09 10:21:16 +09:00
Sammo98
65d0412880 health - add formatter to display (#7986) 2024-01-09 10:15:50 +09:00
Michael Davis
305d6e9c89 Normalize S-<lower-ascii> keymaps to uppercase ascii (#9213) 2024-01-09 10:04:34 +09:00
Philipp Mildenberger
41ca46cf8c Initialize diagnostics when opening a document (#8873) 2024-01-09 10:01:04 +09:00
rojebd
46ecc102ba added voxed theme (#9164) 2024-01-09 09:57:14 +09:00
Kirawi
7af78c7788 update comment grammar (#9253) 2024-01-09 09:56:51 +09:00
Pascal Kuthe
48c49f0227 update history of a newly focused view (#9271) 2024-01-09 09:56:09 +09:00
Michael Davis
0cbd8d3df1 Check for rename support before showing LSP rename prompt (#9277) 2024-01-09 09:55:11 +09:00
Pascal Kuthe
4da6191a1c don't automatically dismiss zero width diagnostics (#9280) 2024-01-09 09:54:55 +09:00
dependabot[bot]
20b91fd99a build(deps): bump serde_json from 1.0.109 to 1.0.111 (#9284)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-09 09:52:36 +09:00
dependabot[bot]
97145eaae6 build(deps): bump ignore from 0.4.21 to 0.4.22 (#9283)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-09 09:52:25 +09:00
dependabot[bot]
bad10a5ddd build(deps): bump libc from 0.2.151 to 0.2.152 (#9282)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-09 09:51:58 +09:00
dependabot[bot]
f4212421da build(deps): bump ahash from 0.8.6 to 0.8.7 (#9281)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-09 09:51:38 +09:00
dependabot[bot]
e2e8d2739a build(deps): bump serde from 1.0.193 to 1.0.195 (#9285)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-09 09:51:25 +09:00
Tomas
77ab792ac7 runtime/themes: adding "ttox" theme (#8524)
* runtime/themes: adding 'ttox' theme

* Improving primary selections
2024-01-08 03:57:04 +01:00
Greedwolf DSS
918bd9c2b0 feat: update wren tree-sitter grammar (#8544)
Co-authored-by: masai.dss <masai.dss@bytedance.com>
2024-01-08 03:54:16 +01:00
NitinKM
e46fb58595 Info on how to skip grammar build when building from source (#8698)
* info: no grammar compile

Added instructions on how to compile without compiling grammars

* Update book/src/install.md

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-01-08 03:46:53 +01:00
jw013
00d681cc69 Update goto_file docs (#8563) (#9001)
Make the pluralization of files and selections consistent to emphasize
the 1-to-1 relation between files and selections. The prior wording
with plural "files" and singular "selection" can mislead users into
thinking the command can open multiple files from a single selection.
2024-01-08 03:11:18 +01:00
Ryan Roden-Corrent
c8e58304bf Add textobject queries for protobuf grammar. (#9184)
Given `message Foo {string s = 1;}`
- `mat` selects `message Foo {string s = 1}`
- `mit` selects `{string s = 1;}`

Given `service SearchService { rpc Search(Req) returns (Resp); }
- `mit` or `mat` selects `Req` or `Resp`
- `mif` or `maf` selects `rpc Search(Req) returns (Resp);`
- `mit` selects { rpc Search(Req) returns (Resp); }`
- `mat` selects `service SearchService { rpc Search(Req) returns (Resp); }`
2024-01-08 03:08:41 +01:00
Paul Graydon
154d9b6ed1 Update tokyonight themes (#9099) 2024-01-08 03:08:20 +01:00
Jaakko Paju
73deba7044 Add textobject queries for Scala (#9191) 2024-01-08 03:05:10 +01:00
Jaakko Paju
a32d537d0a Add HOCON language support (#9203)
* Add HOCON language support

* Remove error query

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Change include query

* Fix query error

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2024-01-08 03:04:43 +01:00
DuckDuckWhale
f8ae2bc61b Fix: misleading active tab color in monokai_pro* (#9148) 2024-01-08 03:03:56 +01:00
petrak@
7e389b67c2 Add auto-pairs to scheme language support (#9232)
Currently, typing a single quote in a `.scm` file "helpfully" auto-
completes a closing quote. This is because there is no auto-pairs
section in the languages.toml. This commit adds that.
2024-01-04 14:49:50 -06:00
Tshepang Mbambo
da4afaf3da remove build warnings (#9180) 2024-01-04 15:51:00 +09:00
dependabot[bot]
8f2e611b7e build(deps): bump serde_json from 1.0.108 to 1.0.109 (#9201)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.108 to 1.0.109.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.108...v1.0.109)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-04 15:38:12 +09:00
dependabot[bot]
2e3f330b12 build(deps): bump tempfile from 3.8.1 to 3.9.0 (#9199)
Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.8.1 to 3.9.0.
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.8.1...v3.9.0)

---
updated-dependencies:
- dependency-name: tempfile
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-04 15:38:05 +09:00
dependabot[bot]
b908abae2d build(deps): bump anyhow from 1.0.76 to 1.0.78 (#9200)
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.76 to 1.0.78.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.76...1.0.78)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-04 15:37:49 +09:00
dependabot[bot]
78d85eb13f build(deps): bump futures-executor from 0.3.29 to 0.3.30 (#9168)
Bumps [futures-executor](https://github.com/rust-lang/futures-rs) from 0.3.29 to 0.3.30.
- [Release notes](https://github.com/rust-lang/futures-rs/releases)
- [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.29...0.3.30)

---
updated-dependencies:
- dependency-name: futures-executor
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-04 15:37:41 +09:00
dependabot[bot]
5876b763e1 build(deps): bump gix from 0.57.0 to 0.57.1 (#9202)
Bumps [gix](https://github.com/Byron/gitoxide) from 0.57.0 to 0.57.1.
- [Release notes](https://github.com/Byron/gitoxide/releases)
- [Changelog](https://github.com/Byron/gitoxide/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Byron/gitoxide/compare/gix-v0.57.0...gix-v0.57.1)

---
updated-dependencies:
- dependency-name: gix
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-01-04 15:37:22 +09:00
Jaakko Paju
a6ed104ea2 Add .prettierrc to json file types (#9214) 2024-01-02 17:47:59 -05:00
Manuel Mendez
efc4865c78 Reduce logo sizes even more (#9211)
* Reduce logo.svg even more

While reading through commits to helix I saw
https://github.com/helix-editor/helix/pull/9106 and wondered if the
relatively-new-to-me svgo would do better than -95B diff, indeed it
does. Seeing as this file is "a minified file we're basically treating
as binary" anyway I figured might as well minify it further.

* Minimize all the svg logos
2024-01-02 23:16:37 +01:00
Rose Hudson
a680b2e409 rust highlights: clean up constructor logic (#8957)
Enum variants and (tuple) structs are indistinguishable in general, so we
mark any PascalCase pattern or expression as a "constructor", which
covers all three.
2024-01-02 16:38:13 +01:00
Gabriel Lopes Rodrigues
7fd266efa9 Avoid crashing with 2 instances of the same LSP (#9134) 2024-01-02 09:29:22 -06:00
Sebastian Thiel
85fce2f5b6 build(deps): bump gix from 0.56.0 to 0.57.0 (#9188) 2023-12-29 13:46:01 -06:00
Pascal Kuthe
783ff27b1b consistent diagnostic sorting 2023-12-27 15:28:14 +09:00
Pascal Kuthe
515ef17207 make diagnostics stick to word boundaries
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.
2023-12-27 15:28:14 +09:00
Pascal Kuthe
8653e1b02f Add config to mark diagnostic sources as persistent 2023-12-27 15:28:14 +09:00
dependabot[bot]
c874a896a5 build(deps): bump tokio from 1.35.0 to 1.35.1 (#9169)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.35.0 to 1.35.1.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.35.0...tokio-1.35.1)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-27 13:34:58 +09:00
dependabot[bot]
0036782059 build(deps): bump anyhow from 1.0.75 to 1.0.76 (#9170)
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.75 to 1.0.76.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.75...1.0.76)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-27 13:33:46 +09:00
dependabot[bot]
2ec4d5004d build(deps): bump futures-util from 0.3.29 to 0.3.30 (#9171)
Bumps [futures-util](https://github.com/rust-lang/futures-rs) from 0.3.29 to 0.3.30.
- [Release notes](https://github.com/rust-lang/futures-rs/releases)
- [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.29...0.3.30)

---
updated-dependencies:
- dependency-name: futures-util
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-27 13:33:23 +09:00
dependabot[bot]
1fc20cd02b build(deps): bump thiserror from 1.0.51 to 1.0.52 (#9172)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.51 to 1.0.52.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.51...1.0.52)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-27 13:33:08 +09:00
goyalyashpal
d5e6749fa2 Reduce logo.svg size (-93B) (#9106)
* chore(logo): PrettyPrint to reduce size by 93B ...

  * Current size:  2,755 B
  * Original size: 2,848 B
  * Add file's final newline (linux convention)
  * Remove tag separator spaces
  * Add newlines
  * Add tab indentation (instead of 2/4 spaces)
  * Prettify root svg's attribs

* style(logo): Bring style attrb to front

* chore(logo): Remove tab characters

* chore(logo): Remove \n, use LF as final newline

* chore(logo): Minify logo.svg ...

  * Remove final newline too
2023-12-22 13:52:53 +09:00
Sharpened Blade
7b0f92bb3a Add markup styling to nord theme (#9135)
Fixes https://github.com/helix-editor/helix/issues/9131
2023-12-22 13:52:26 +09:00
romi
ab50299efa Add .glif to XML file-types (#9130)
`.glif` files are standard files in the type design industry. From the
Unified Font Object specification website:

The Glyph Interchange Format (GLIF) is a simple and clear XML
representation of a single glyph. GLIF files typically have a .glif
extension.
https://unifiedfontobject.org/versions/ufo3/glyphs/glif/
2023-12-22 13:51:21 +09:00
Michael Davis
585402d9ff Update upload/download-artifact actions to v4 (#9120) 2023-12-21 14:09:26 +09:00
0rphee
5f04d09f03 theme: update noctis (#9123) 2023-12-20 17:09:35 +09:00
Evan Richter
a98b8ddd1a add smali language support (#9089) 2023-12-20 00:31:27 +01:00
dependabot[bot]
63218a5126 build(deps): bump lsp-types from 0.94.1 to 0.95.0 (#9117)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2023-12-20 00:30:46 +09:00
Passw
8736ce3889 Update README.md to add link to Kakoune and Neovim (#9119) 2023-12-19 15:50:39 +01:00
ath3
9ba691cd3a Support drawing popup frame (#4313)
Co-authored-by: Blaž Hrastnik <blaz@mxxn.io>
2023-12-19 10:17:12 +09:00
ves
06d7dc628e theme: add horizon-dark (#9008) 2023-12-19 10:06:20 +09:00
Lucas Wagler
970f9e6333 Add Avro schema file support (#9113) 2023-12-19 10:05:58 +09:00
0rphee
0a83d85124 Add haskell-language-server as lsp for cabal files (#9111) 2023-12-19 10:05:55 +09:00
Matouš Dzivjak
80dd585966 feat(themes): add modus vivendi theme(s) (#8894) 2023-12-19 10:03:26 +09:00
dependabot[bot]
c1ab94bbef build(deps): bump thiserror from 1.0.50 to 1.0.51 (#9116)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-19 10:01:10 +09:00
Gabriel Dinner-David
f27fdb2bf4 when text document sync capability is only kind send didSave without text (#9101)
see https://github.com/microsoft/language-server-protocol/issues/288 for details
2023-12-17 15:59:04 -06:00
Novus Nota
a1a20d231f book: Describe usage of .ignore and helix-specific ignore files in [editor.file-picker] section (#9102) 2023-12-17 22:40:29 +01:00
JJ
c56cd6ee8b Add support for Agda (#8285)
* agda language support (wip)

* improve highlights

* disable agda-language-server

* minor addendum to documentation

* cargo xtask docgen

* oh i can just do this neat

* minor comment cleanup

* upstream updated

* imports: missed a spot

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2023-12-16 05:29:26 +01:00
TornaxO7
914c83420b fix :indent-style crash (#9087)
* removing unreachable statement in `:indent-style`

* update checks when setting indent line and update docs

* `cargo xtask docgen`
2023-12-15 19:05:04 +01:00
Daniel Ebert
33d85606cf Add alignment indent queries for binary & ternary expressions in C. 2023-12-15 15:59:54 +09:00
Daniel Ebert
723a132bdf Simplify implementation of add_indent_level.
Increase hybrid indent heuristic attempt limit to 4.
Clarify the fallback logic in indent heuristic docs.
2023-12-15 15:59:54 +09:00
Daniel Ebert
3e79a35656 Align arguments in a function call in C.
Since the tree-sitter grammar is not very good
at parsing function calls while they're being written,
this is not yet super useful.
However, it prevents the new `hybrid` indent heuristic
from choosing these lines as a baseline, making it
more robust.
2023-12-15 15:59:54 +09:00
Daniel Ebert
a5acfdbf10 Add documentation for new indent computation 2023-12-15 15:59:54 +09:00
Daniel Ebert
938a710904 Make the indent heuristic configurable 2023-12-15 15:59:54 +09:00
Daniel Ebert
559bfc1f5e Improve relative indent computation.
Add tests to ensure that relative & absolute indent computation are consistent.
2023-12-15 15:59:54 +09:00
Daniel Ebert
d29a66f267 Implement relative indent queries,
i.e. also take into account the indentation of a previous
line when computing the indentation for a new line.
2023-12-15 15:59:54 +09:00
Susheel Thapa
23fd145a56 fix: typo in scm files inside runtime/queries/ (#8630) 2023-12-15 15:58:27 +09:00
JR
e332c7d875 Add tutor for match mode (#8751)
* Add tutor for match mode

* Improve the surround tutor

* Add missing == in header

* Reflow

* Update runtime/tutor

Co-authored-by: David Else <12832280+David-Else@users.noreply.github.com>

* Update runtime/tutor

Co-authored-by: David Else <12832280+David-Else@users.noreply.github.com>

* Update runtime/tutor

Co-authored-by: David Else <12832280+David-Else@users.noreply.github.com>

* Apply feedback

---------

Co-authored-by: David Else <12832280+David-Else@users.noreply.github.com>
2023-12-15 15:57:28 +09:00
Jesús González
f1e34ce5a2 Specify BG and FG cursor colors in Darcula themes (#9002) 2023-12-15 15:54:59 +09:00
Matthew Toohey
11856329bf Change R markdown language name to fix language server detection (#9012) 2023-12-15 15:54:43 +09:00
Phil
b4571c292e Add initial support for janet-lang (#9081)
* Add initial support for janet-lang

* Use default roots for janet-lang
2023-12-15 15:54:25 +09:00
dependabot[bot]
437fbee425 build(deps): bump zerocopy from 0.7.20 to 0.7.31 (#9092)
Bumps [zerocopy](https://github.com/google/zerocopy) from 0.7.20 to 0.7.31.
- [Release notes](https://github.com/google/zerocopy/releases)
- [Changelog](https://github.com/google/zerocopy/blob/main/CHANGELOG.md)
- [Commits](https://github.com/google/zerocopy/compare/v0.7.20...v0.7.31)

---
updated-dependencies:
- dependency-name: zerocopy
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-15 15:52:58 +09:00
Valerii Petryniak
7c55190806 Update keymap.md: improve grammar (#9069)
* Update keymap.md: improve grammar

* Update keymap.md

Co-authored-by: David Else <12832280+David-Else@users.noreply.github.com>

---------

Co-authored-by: David Else <12832280+David-Else@users.noreply.github.com>
2023-12-13 17:37:12 +01:00
Michal Rostecki
c2591445c9 chore: Update tree-sitter-d (#9021)
One of the included changes is gdamore/tree-sitter-d#22 which
fixes the build of Helix when using clang as `CC`.
2023-12-13 02:37:03 +01:00
dependabot[bot]
49dffa7d24 build(deps): bump gix from 0.55.2 to 0.56.0 (#9055)
* build(deps): bump gix from 0.55.2 to 0.56.0

Bumps [gix](https://github.com/Byron/gitoxide) from 0.55.2 to 0.56.0.
- [Release notes](https://github.com/Byron/gitoxide/releases)
- [Changelog](https://github.com/Byron/gitoxide/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Byron/gitoxide/compare/gix-v0.55.2...gix-v0.56.0)

---
updated-dependencies:
- dependency-name: gix
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Adapt to changes in gix EntryMode/EntryKind

The rest of the gix codebase now calls `.kind()` on the mode and uses
the renamed `EntryKind` enum.

---------

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>
2023-12-13 02:29:43 +01:00
dependabot[bot]
f036451a0e build(deps): bump rustix from 0.38.26 to 0.38.28 (#9054)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-12 22:46:21 +09:00
dependabot[bot]
7f44a6ad50 build(deps): bump once_cell from 1.18.0 to 1.19.0 (#9053)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-12 22:46:11 +09:00
dependabot[bot]
3e249829ee build(deps): bump libc from 0.2.150 to 0.2.151 (#9056)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-12 11:05:20 +09:00
dependabot[bot]
53ad0f72a5 build(deps): bump tokio from 1.34.0 to 1.35.0 (#9057)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-12 11:05:10 +09:00
Tanguy
510928618d Fix version of Nix package (#9013) 2023-12-09 03:04:09 +09:00
TornaxO7
b81aacc5e1 Join empty lines with only one space in join_selections (#8989)
* fix: #8977

fixes the issue that lines with only spaces are getting
joined as well

* reverting some renamings

* improve empty line check

* adding integration test

* reverting code block

* fix conditon check for line end

* applying suggested style
2023-12-06 16:19:54 +01:00
Frederick Schwalbe
c3cb1795bf Update gleam grammar and queries (#9003) 2023-12-05 22:54:00 +09:00
dependabot[bot]
4c2bd4905e build(deps): bump open from 5.0.0 to 5.0.1 (#8992)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-05 12:28:32 +09:00
Skyler Hawthorne
bf7c4e1659 use workspace inheritance for common version (#8925) 2023-12-05 10:54:18 +09:00
Jesús González
44c3d48a94 Add more accurate to official theme type highlighting to Darcula themes (#8738) 2023-12-05 10:46:23 +09:00
Niklas Alexander Shern
ab763b3111 fix: update rose_pine to be identical to main repo (#8946) 2023-12-05 10:45:50 +09:00
Manuel Mendez
9fcfb88132 Add .envrc.local and .envrc.private to env file-types (#8988) 2023-12-05 10:45:41 +09:00
dependabot[bot]
8532cec01c build(deps): bump grep-searcher from 0.1.12 to 0.1.13 (#8998)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-05 10:45:18 +09:00
dependabot[bot]
fa7a8ffc50 build(deps): bump cachix/cachix-action from 12 to 13 (#8997)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-05 10:45:01 +09:00
dependabot[bot]
0d890ef0f7 build(deps): bump ignore from 0.4.20 to 0.4.21 (#8996)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-05 10:44:51 +09:00
dependabot[bot]
00d565bf74 build(deps): bump cachix/install-nix-action from 23 to 24 (#8995)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-05 10:43:43 +09:00
dependabot[bot]
58daa31523 build(deps): bump slotmap from 1.0.6 to 1.0.7 (#8994)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-05 10:43:35 +09:00
dependabot[bot]
aad44f6dd0 build(deps): bump rustix from 0.38.25 to 0.38.26 (#8993)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-05 10:41:50 +09:00
dependabot[bot]
79965a238d build(deps): bump url from 2.4.1 to 2.5.0 (#8991)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-05 10:41:30 +09:00
Skyler Hawthorne
fcd564fddf upgrade tree-sitter-python (#8976)
supports new syntaxes from Python 3.12
2023-12-04 17:26:11 +09:00
Evan Richter
455b206a8c nix: update flake inputs (#8943)
* removed non-existent crane flake input overrides
2023-12-04 01:46:17 +01:00
Nan Zhong
466b87c8e5 languages: update rescript grammar (#8962)
This bump fixes a build failure of the grammer with clang.
2023-12-04 01:46:00 +01:00
Tshepang Mbambo
86023cf1e6 use canonical name (#8960)
I do not find anywhere where the option omits the 's'
2023-12-01 14:07:31 +09:00
Michael Davis
0c81ef73e1 direnv: Watch the rust-toolchain file (#8921) 2023-11-29 11:01:12 +09:00
Tudyx
f8d261cd20 add log tree-sitter (#8916)
* add log tree-sitter

* better highlight queries
2023-11-29 02:42:59 +01:00
A-Walrus
0739d13b03 Add musicxml to xml extensions (#8935) 2023-11-29 02:41:35 +01:00
dependabot[bot]
0d9145a1bf build(deps): bump grep-regex from 0.1.11 to 0.1.12 (#8930)
Bumps [grep-regex](https://github.com/BurntSushi/ripgrep) from 0.1.11 to 0.1.12.
- [Release notes](https://github.com/BurntSushi/ripgrep/releases)
- [Changelog](https://github.com/BurntSushi/ripgrep/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BurntSushi/ripgrep/compare/grep-regex-0.1.11...0.1.12)

---
updated-dependencies:
- dependency-name: grep-regex
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-29 02:41:10 +01:00
Hendrik Norkowski
b023faacf8 fix(ui): use crossterm cursor when at the end of the rope (#8934) 2023-11-29 00:11:23 +09:00
Blaž Hrastnik
6d168eda27 fix CI: tree-sitter-gemini user renamed 2023-11-28 14:38:15 +09:00
dependabot[bot]
3e451f0d53 build(deps): bump serde from 1.0.192 to 1.0.193 (#8931)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-28 09:54:35 +09:00
dependabot[bot]
008208fcfb build(deps): bump grep-searcher from 0.1.11 to 0.1.12 (#8929)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-28 09:54:16 +09:00
dependabot[bot]
b30451f776 build(deps): bump hashbrown from 0.14.2 to 0.14.3 (#8928)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-28 09:53:53 +09:00
dependabot[bot]
4bc43347a1 build(deps): bump clipboard-win from 4.5.0 to 5.0.0 (#8927)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-28 09:52:46 +09:00
dependabot[bot]
8de8a66182 build(deps): bump globset from 0.4.13 to 0.4.14 (#8926)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-28 09:51:45 +09:00
Hendrik Norkowski
71fd85894b use crossterm cursor in editor when out of focus (#6858)
Use crossterm cursor in the editor when the terminal is out of focus to achieve consistent out-of-focus cursor behaviour
2023-11-27 20:11:16 +01:00
Fomalhaut Weisszwerg
b7f98d1d99 set Cargo feature resolver to v2 (#8917)
* fix: version of Cargo feature resolver.

This commit solve the ambiguity to determin the version of resolver.
To get more detail, see the following two documents:

- https://doc.rust-lang.org/cargo/reference/resolver.html#resolver-versions
- https://doc.rust-lang.org/edition-guide/rust-2021/default-cargo-resolver.html

* unified: Rust edition in all workspaces.

Now, the Rust 2021 is available in all workspaces.

* fined up: Cargo.toml by using workspace inheritance.

To get more detail of the `workspace.package` table, see a following document:

- https://doc.rust-lang.org/cargo/reference/workspaces.html#the-package-table
2023-11-27 13:24:57 +01:00
Davide Ferrero
3f9788daaa update which crate to 5.0.0 (#8902)
* update which crate to 5.0.0

* update which crate to 5.0.0
2023-11-26 01:37:00 +09:00
chtenb
8c68074fa6 Fix precedence of ui.virtual.whitespace (#8879)
* Revert "Revert "Fix precedence of ui.virtual.whitespace (#8750)""

This reverts commit 811d62d3b3.

* Fix ui.text overwriting the syntax highlighting

Adjust ui.text description
2023-11-25 14:27:31 +01:00
Cole Helbling
8b0ae3d279 bump MSRV to 1.70.0 (#8877)
* 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
2023-11-25 13:55:49 +01:00
Alexis Mousset
090ed97e00 Add modus operandi themes (#8728) 2023-11-22 19:04:10 +01:00
ghashy
ff095ebd9b DBML Language support (#8860)
* DBML language support

* DBML language support, highlights.scm added

* DBML support

* Update runtime/queries/dbml/highlights.scm

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Update runtime/queries/dbml/highlights.scm

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Update runtime/queries/dbml/highlights.scm

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* remove unnecessary block highlight

* remove unnecessary line

* remove index_block query

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2023-11-22 18:27:25 +01:00
Ethan Brierley
f1b9c19fa9 add LSP for nushell (#8878) 2023-11-22 18:24:34 +01:00
chtenb
db83eb0c50 Document the bufferline scopes (#8880)
* Document the bufferline scopes

* Update book/src/themes.md

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2023-11-22 14:07:26 +01:00
Blaž Hrastnik
811d62d3b3 Revert "Fix precedence of ui.virtual.whitespace (#8750)"
This reverts commit 41b307b673.
2023-11-22 16:00:28 +09:00
chtenb
41b307b673 Fix precedence of ui.virtual.whitespace (#8750) 2023-11-22 11:42:40 +09:00
Bjorn Ove Hay Andersen
47b6c4bc78 Resolve args.files before changing directory (#8676)
* Resolve args.files before changing directory

* Removed the open_cwd work-around now that the path is full

* If -w is specified, use that as the working directory

* Open the remaining files in the argument list, also when the first is a directory

* Use an iterator access the files argument
2023-11-21 12:07:00 +01:00
Matouš Dzivjak
3052050ee0 open urls with goto_file command (#5820)
* feat(commands): open urls with goto_file command

Add capability for `goto_file` command to open an URL under cursor.

Fixes: https://github.com/helix-editor/helix/issues/1472
Superseds: https://github.com/helix-editor/helix/pull/4398

* open files inside helix

* address code review

* bump deps

* fix based on code review comments
2023-11-21 12:04:20 +01:00
dependabot[bot]
bfd60a5b39 build(deps): bump rustix from 0.38.22 to 0.38.25 (#8874)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-21 09:31:12 +09:00
blinxen
a0e5bb8520 [themes] Add missing license files for recently added themes 2023-11-19 14:44:02 -06:00
blinxen
b16752306c [themes] Mention license files in README 2023-11-19 14:44:02 -06:00
Dan Field
b306b25e82 GN language support (#6969)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2023-11-18 17:11:18 +09:00
Ryan Mehri
6bf5548dbd make increment/decrement exit select mode 2023-11-18 01:07:57 -06:00
Ryan Mehri
09c78e8b4e make switch case commands exit select mode 2023-11-18 01:07:57 -06:00
Ryan Mehri
d4a0eba1a7 make align exit select mode 2023-11-18 01:07:57 -06:00
Ryan Mehri
5913073733 make replace with clipboard commands exit select mode 2023-11-18 01:07:57 -06:00
Ryan Mehri
1271a50a82 make paste commands exit select mode 2023-11-18 01:07:57 -06:00
Ryan Mehri
34de1cab62 make indent/unindent exit select mode 2023-11-18 01:07:57 -06:00
Niklas Alexander Shern
2acf5e365e theme: show active selection and buffer for naysayer theme (#8838) 2023-11-18 10:44:01 +09:00
blinxen
39aa6fa646 Update some grammars to a commit where the license file is included (#8691) 2023-11-18 10:24:59 +09:00
WuerfelDev
2579bca21c Book: fix formatting of some default values (#8837) 2023-11-18 00:34:17 +01:00
crozbo
7868136a18 Theme: Papercolor: Add inlay-hint style (#8827) 2023-11-18 00:32:06 +01:00
Luca Saccarola
5889b81fc7 docs: add docs for soft-wrap in languages.toml (#8836) 2023-11-17 15:57:15 -06:00
Seth Maurice-Brant
73ca2d5f84 Change Fedora installation to the new official Helix package (#8762)
Remove COPR install in favour of official Helix package
2023-11-17 15:54:30 -06:00
Eemil Haapanen
3c8bf9df4a theme: add starlight (#8787) 2023-11-17 01:34:56 +01:00
dependabot[bot]
2040444da9 build(deps): bump rustix from 0.38.21 to 0.38.22 (#8807)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-15 20:21:00 +01:00
dependabot[bot]
40959bb449 build(deps): bump cc from 1.0.83 to 1.0.84 (#8809)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-14 12:15:50 +09:00
dependabot[bot]
e5d02cd4bd build(deps): bump serde from 1.0.191 to 1.0.192 (#8810)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-14 12:15:37 +09:00
Michael Davis
69a0df929a Remove 'roots' keys with default value from languages.toml 2023-11-14 11:56:53 +09:00
Michael Davis
8b2d97eb56 Default 'roots' field of language config
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.
2023-11-14 11:56:53 +09:00
dependabot[bot]
13386a4786 build(deps): bump smallvec from 1.11.1 to 1.11.2 (#8808)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-14 11:56:13 +09:00
dependabot[bot]
5ec53c0222 build(deps): bump tokio from 1.33.0 to 1.34.0 (#8811)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-14 11:55:57 +09:00
Ambuj Singh
23fea46815 theme: Add Theme poimandres (#8759)
* theme: Add Theme poimandres

* theme: inherit `poimandres_storm` from `poimandres` with minor tweaks

* fix(theme): rename `crossed-out` to `crossed_out`

* fix(theme:poimandres): improve contrast of selection color for regular variant
2023-11-12 23:04:36 +01:00
blt__
172ef2fa9f Highlight meson_options.txt as a meson file (#8794) 2023-11-12 23:04:03 +01:00
mydumpfire
6ab774da0b grammars.nix: allow the user to apply overlays (#8749)
You can now apply overlays to the grammar derivations via
`grammarOverlays`. Also, the `src` in the derivation is now properly
unpacked to the build directory, allowing the user to mutate the source
files if they want to.
2023-11-09 09:56:57 +01:00
dependabot[bot]
4229583631 build(deps): bump futures-executor from 0.3.28 to 0.3.29 (#8743)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-09 11:13:32 +09:00
dependabot[bot]
aac7bd9b08 build(deps): bump libc from 0.2.149 to 0.2.150 (#8741)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-09 11:13:03 +09:00
dependabot[bot]
91bdceb8b6 build(deps): bump serde_json from 1.0.107 to 1.0.108 (#8744)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-09 11:12:54 +09:00
dependabot[bot]
676ab0c1f3 build(deps): bump serde from 1.0.190 to 1.0.191 (#8740)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-09 11:12:45 +09:00
Triton171
cb0bc25a9f Add indent queries for scheme (and reuse them for common-lisp & racket). (#8720) 2023-11-08 20:53:07 +01:00
Yomain
e868678139 Add command to move files with LSP support (#8584)
* Added rename command

* Added an error if the new path already exists

* Fixed wrong command name being used

* fixed clippy suggestions

* removed didRenameFiles call, fixed early return due to path Err

* added ':rnm' alias to ':rename'

* code cleanup

* formatting

* removed debug line

* cargo fmt

* Improved new buffer error message

Co-authored-by: Pascal Kuthe <pascal.kuthe@semimod.de>

* Removed unnecessary path normalizing

Co-authored-by: Pascal Kuthe <pascal.kuthe@semimod.de>

* Update helix-term/src/commands/typed.rs

Co-authored-by: Pascal Kuthe <pascal.kuthe@semimod.de>

* Update helix-term/src/commands/typed.rs

Co-authored-by: Pascal Kuthe <pascal.kuthe@semimod.de>

* Update helix-term/src/commands/typed.rs

Co-authored-by: Pascal Kuthe <pascal.kuthe@semimod.de>

* Update helix-term/src/commands/typed.rs

Co-authored-by: Pascal Kuthe <pascal.kuthe@semimod.de>

* feat: change `rename` command to `move`

* feat: add multi lsp support when moving files

* feat: allow lsp calls with a custom timeout

* feat: sending lsp file_changed event once file has moved

---------

Co-authored-by: ontley <theontley@gmail.com>
Co-authored-by: ontley <67148677+ontley@users.noreply.github.com>
Co-authored-by: Pascal Kuthe <pascal.kuthe@semimod.de>
2023-11-08 12:38:17 -06:00
Henrik Tjäder
7bc564d3dc Theme: Papercolor: Add type.parameter (#8735) 2023-11-06 15:33:18 -06:00
Joey Hain
f73e9a8d15 highlights: add type.parameter scope to several more languages (#8718)
* typescript

* go

* haskell

* ocaml

* kotlin (+ bugfix)
2023-11-06 02:54:25 +01:00
postsolar
a98ad137f9 Update PureScript grammar (#8712) 2023-11-05 14:16:25 +01:00
MDeiml
2fddc2a4fc Update markdown grammar to v0.1.6 2023-11-05 07:31:19 -05:00
Skyler Hawthorne
10b178e94b swap yank command registers (#8708)
#8703 swapped the `+` and `*` registers, but did not swap them in the
corresponding yank commands.
2023-11-04 09:35:38 +09:00
Michael Davis
8dc197721b Add an installation method field to the bug report template (#8711)
We can guess the installation method from the version tag and platform
in some cases but it would be useful to have this be explicit for the
sake of debugging packager-specific problems.
2023-11-04 09:34:54 +09:00
cgahr
5c325fe342 replace kdl tree-sitter to fix highlighting (#8652)
* replace kdl tree-sitter

* kdl: adopt highlights for new tree-sitter

* kdl: add indent queries

* kdl: add textobjects

* kdl: improve syntax highlighting

* kdl: update lang-support

* kdl: make indents more concise

---------

Co-authored-by: Constantin Gahr <constantin.gahr@ipp.mpg.de>
2023-11-03 22:21:54 +01:00
Joey Hain
70bbbd7d19 add highlight scope for type parameters (#8660)
* rust: add highlight scope for type parameters

* handle optional type parameters
2023-11-03 22:21:01 +01:00
Arkady Rost
ae6a0a9cfd Adjusted ui.virtual.inlay-hint color for everblush theme (#8705)
Co-authored-by: Arkady Rost <1239844+arkrost@users.noreply.github.com>
2023-11-03 09:51:22 +09:00
Omnikar
1755c61d08 Swap system and primary clipboard registers (#8703) 2023-11-03 09:51:10 +09:00
blinxen
a069b92897 Add missing license files for themes (#8684) 2023-10-31 17:09:48 -05:00
dependabot[bot]
53bb62b318 build(deps): bump tempfile from 3.8.0 to 3.8.1 (#8672)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-31 16:57:03 +09:00
dependabot[bot]
d32e052e0e build(deps): bump ahash from 0.8.5 to 0.8.6 (#8669)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-31 16:56:23 +09:00
dependabot[bot]
d171e23f72 build(deps): bump futures-util from 0.3.28 to 0.3.29 (#8673)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-31 12:27:15 +09:00
dependabot[bot]
403a1739cf build(deps): bump serde from 1.0.189 to 1.0.190 (#8670)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-31 12:27:07 +09:00
Blaž Hrastnik
ccc3085ad0 ci: Use a shared cache across build workflow steps 2023-10-31 11:55:34 +09:00
dependabot[bot]
566f41635e build(deps): bump rustix from 0.38.20 to 0.38.21 (#8671)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-31 11:38:41 +09:00
Ryan Mehri
d0430f1c81 Only render preview if picker has a preview function (#8667) 2023-10-30 15:03:38 -05:00
Jeffrey Gelens
7d7ed78681 Add MacPorts as installation option for MacOS (#8663)
* Added MacPorts as installation option for MacOS

* Added macports to ToC
2023-10-30 19:28:55 +01:00
John Careaga
992b7a0c39 Update idle-timeout in docs (#8661) 2023-10-29 19:28:06 -05:00
Angus Dippenaar
44e03fa414 add golangci-lint-langserver (#8656)
* languages add golangci-lint-langserver

* update docs
2023-10-29 17:53:15 +01:00
Triton171
ef0c31db02 Fix precedence order of @align captures in indent computation (#8659)
precedence when multiple occur on the same line in an indent query.
2023-10-29 17:48:58 +01:00
RoloEdits
f992c3b597 feat(highlights): add more comment highlights (#8564) 2023-10-27 01:41:09 +02:00
blt__
ab266b99e6 Say "unindent" instead of "outdent" in tutor (#8623) 2023-10-27 01:40:49 +02:00
Mehedi Rifat
99bf62a560 Theme: Add gruber-darker theme (#8598) 2023-10-27 01:40:33 +02:00
Gabriel Dinner-David
4f1d414d9c switch to tree-sitter-ron (#8624) 2023-10-27 01:40:16 +02:00
Ryan Mehri
553ffbcaa0 Use terminfo to reset terminal cursor style (#8591) 2023-10-26 18:36:34 -05:00
Frans Skarman
9eec9adb8f Add LPF tree sitter (#8536)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2023-10-27 01:32:49 +02:00
Alexander Brevig
2906660119 Add typst language and lsp (#7474)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2023-10-27 01:27:42 +02:00
Michael Davis
ef1f4f31b6 CI: Publish stable book before master (#8621) 2023-10-26 23:07:36 +09:00
Blaž Hrastnik
5ce1c30f77 Revert "Pin tree-sitter to the 0.20.10 release (#8396)"
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.
2023-10-26 15:58:10 +09:00
Ryan Mehri
c24a67c0e4 Add rust html injection query (#8603) 2023-10-26 11:39:22 +09:00
Blaž Hrastnik
f6021dd0cd ci: Disable riscv release build (currently broken) 2023-10-26 01:37:27 +09:00
Michael Davis
c7e15dd87e Add changelog notes for 23.10 (#8086)
Co-authored-by: Pascal Kuthe <pascal.kuthe@semimod.de>
2023-10-26 01:10:45 +09:00
Michael Davis
2ebcc4dbeb Pin tree-sitter to the 0.20.10 release (#8396) 2023-10-26 01:08:46 +09:00
Skyler Hawthorne
b5d691a5d7 Add optional runtime fallback directory (#8610) 2023-10-26 01:08:01 +09:00
dependabot[bot]
68c7537de5 build(deps): bump ahash from 0.8.3 to 0.8.5 (#8597)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-24 17:59:38 +09:00
dependabot[bot]
9dbf882808 build(deps): bump thiserror from 1.0.49 to 1.0.50 (#8596)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-24 14:14:18 +09:00
dependabot[bot]
25ea6b8152 build(deps): bump rustix from 0.38.19 to 0.38.20 (#8595)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-24 14:14:09 +09:00
dependabot[bot]
6acbb07ca9 build(deps): bump hashbrown from 0.14.1 to 0.14.2 (#8594)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-24 14:14:00 +09:00
dependabot[bot]
fef4d5321b build(deps): bump ropey from 1.6.0 to 1.6.1 (#8593)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-24 14:13:46 +09:00
Abderrahmane TAHRI JOUTI
88bc52a570 Theme cyan light diff colors (#8587) 2023-10-24 00:10:42 +09:00
Stephen Seo
31f50bf5bf don't break on hyphen with :reflow (#8569) 2023-10-21 07:58:36 -05:00
rsteube
764715a6c0 languages: add templ (#8540) 2023-10-21 14:15:18 +02:00
Paul Olteanu
8d44459c6a Add helix-specific ignore files (#8099) 2023-10-21 04:20:29 -05:00
dependabot[bot]
6d598d3239 build(deps): bump rustix from 0.38.18 to 0.38.19 (#8556)
Bumps [rustix](https://github.com/bytecodealliance/rustix) from 0.38.18 to 0.38.19.
- [Release notes](https://github.com/bytecodealliance/rustix/releases)
- [Commits](https://github.com/bytecodealliance/rustix/compare/v0.38.18...v0.38.19)

---
updated-dependencies:
- dependency-name: rustix
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-20 22:56:28 +09:00
dependabot[bot]
ac8759c0c9 build(deps): bump bitflags from 2.4.0 to 2.4.1 (#8555)
Bumps [bitflags](https://github.com/bitflags/bitflags) from 2.4.0 to 2.4.1.
- [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/2.4.0...2.4.1)

---
updated-dependencies:
- dependency-name: bitflags
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-20 22:56:07 +09:00
dependabot[bot]
7d5bc9b878 build(deps): bump serde from 1.0.188 to 1.0.189 (#8554)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.188 to 1.0.189.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.188...v1.0.189)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-20 22:55:42 +09:00
Bjorn Ove Hay Andersen
e6d2835b09 Fixed issue when the first file specified as an argument was a relative directory (#8520) 2023-10-18 10:45:05 +02:00
Joe-Zer0
fc16449efe Add nord night theme (#8549) 2023-10-17 05:46:28 -05:00
dependabot[bot]
83ce8d0c5d build(deps): bump regex from 1.9.6 to 1.10.2 (#8557)
Bumps [regex](https://github.com/rust-lang/regex) from 1.9.6 to 1.10.2.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.9.6...1.10.2)

---
updated-dependencies:
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-17 12:20:20 +02:00
Ryan Mehri
814cf177d4 bump tree-sitter-haskell and update queries (#8558) 2023-10-17 12:19:57 +02:00
Yomain
cd591647ec fix(lsp): ensure we only highlight diagnostics for lsp with the feature enabled (#8551) 2023-10-17 05:07:00 -05:00
Lorenzo Bellina
d9d7f67898 Add support for showing all LSPs in --health (#7315)
* Add support for showing all LSPs in --health <lang>

* Add support for showing all LSPs in --health languages

* Use available/configured in --health languages

* Apply @AlexanderBrevig suggestion in --health

* Update `--health <language>`

Better output (inspired by #8156).

Handle the case where no LSPs are configured.

* Display all LSPs in `--health languages` instead of x/x

Displays all LSPs as a list in the table generated wih `--health languages`

* Make check_binary accept Optional references to str

Avoids some calls to .clone()

* Apply @the-mikedavis suggestions

* Avoid useless collecting and cloning

* Use for loop instead of .try_for_each()
2023-10-16 11:42:25 +02:00
Michael Davis
7c98b1c829 Fix 'Tree::lookup_entry_by_path' usage 2023-10-16 12:43:00 +09:00
Michael Davis
a6ab062b2d Re-lock 'time' dep at 0.3.23
Co-authored-by: Gabriel Dinner-David <gabydinnerdavid@gmail.com>
2023-10-16 12:43:00 +09:00
dependabot[bot]
c6854e5135 build(deps): bump gix from 0.48.0 to 0.51.0
Bumps [gix](https://github.com/Byron/gitoxide) from 0.48.0 to 0.51.0.
- [Release notes](https://github.com/Byron/gitoxide/releases)
- [Changelog](https://github.com/Byron/gitoxide/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Byron/gitoxide/compare/gix-v0.48.0...gix-v0.51.0)

---
updated-dependencies:
- dependency-name: gix
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-16 12:43:00 +09:00
Petr Gajdůšek
9f6e9a1512 Add 'while_statement' to bash indents (#8528) 2023-10-13 17:08:56 +02:00
NomisIV
1ef7f24dae Update purescript-tree-sitter grammar (#8527) 2023-10-13 17:08:27 +02:00
Bjorn Ove Hay Andersen
574f821308 Make parse_macro work for "-" outside "<..>" (#8475)
* Translate  to   when a part of the outher string in

* Changed the if a little
2023-10-12 14:09:57 +02:00
Bjorn Ove Hay Andersen
07a006d1d5 Add +N CLI argument to jump to first file's line number (#8521)
* Accept +num flag for opening at line number

* Update +N argument feature according to feedback in original PR #5603

* Only override the line number of the first file if +N is specified

---------

Co-authored-by: Nachum Barcohen <38861757+nabaco@users.noreply.github.com>
2023-10-12 10:35:43 +02:00
dependabot[bot]
1852292451 build(deps): bump libc from 0.2.148 to 0.2.149 (#8503)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-10 18:47:25 +09:00
dependabot[bot]
d8f059cbcc build(deps): bump rustix from 0.38.15 to 0.38.18 (#8502)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-10 18:47:15 +09:00
dependabot[bot]
ca0382b75b build(deps): bump tokio from 1.32.0 to 1.33.0 (#8501)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-10 18:47:04 +09:00
dependabot[bot]
e0d5b79a73 build(deps): bump hashbrown from 0.14.0 to 0.14.1 (#8500)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-10 18:46:51 +09:00
Bjorn Ove Hay Andersen
a857480561 Set the working directory before loading the config (#8498) 2023-10-09 11:38:09 -05:00
Kasper Juul Hermansen
5cb76e74f9 add lsp for graphql (#8492)
graphql-lsp has quite the strange name upstream, the project is technically called graphql-language-service,
but the binary shipped is called graphql-lsp hence the strange naming scheme

Signed-off-by: kjuulh <contact@kjuulh.io>
2023-10-09 17:30:27 +02:00
DS/Charlie
96bbfb7c2e bump tree-sitter-sql (#8464)
* bump tree-sitter-sql

* update highlights classes to helix flavour

* replace lua-match with match
2023-10-09 17:29:30 +02:00
Laurent Wandrebeck
bdf7937a59 Add ansible-language-server for yaml (#7973)
* Update languages.toml

Add ansible support to yaml.

* cargo xtask docgen
2023-10-08 12:34:21 +02:00
DS/Charlie
93e54fa0c8 add support for json5 (#8473)
* add json5 language

* docgen
2023-10-07 00:29:42 +02:00
David Else
68fce3e160 Add tailwindcss language server (#8442) 2023-10-04 19:00:43 +09:00
Lloyd Bond
75c0a5ceb3 enable starting hx with a working directory (#8223)
* added working path arg to cli and help menu

* improve working path cli arg handling

* enable hx to set the working path

* applied cargo formatting

* improved code from cargo clippy suggestion

* improved code from follow up review

* fix for -w <path> is set but args.files is empty

* improved formatting of --help output
2023-10-03 10:18:27 +09:00
Gabriel Dinner-David
1756ba4436 update with new mdbook index.hbs (#8445) 2023-10-03 10:17:32 +09:00
dependabot[bot]
e122add561 build(deps): bump thiserror from 1.0.48 to 1.0.49 (#8447)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.48 to 1.0.49.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.48...1.0.49)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-03 10:17:03 +09:00
dependabot[bot]
a42b5f011e build(deps): bump libloading from 0.8.0 to 0.8.1 (#8448)
Bumps [libloading](https://github.com/nagisa/rust_libloading) from 0.8.0 to 0.8.1.
- [Commits](https://github.com/nagisa/rust_libloading/compare/0.8.0...0.8.1)

---
updated-dependencies:
- dependency-name: libloading
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-03 10:16:51 +09:00
dependabot[bot]
7dddbca558 build(deps): bump rustix from 0.38.14 to 0.38.15 (#8449)
Bumps [rustix](https://github.com/bytecodealliance/rustix) from 0.38.14 to 0.38.15.
- [Release notes](https://github.com/bytecodealliance/rustix/releases)
- [Commits](https://github.com/bytecodealliance/rustix/compare/v0.38.14...v0.38.15)

---
updated-dependencies:
- dependency-name: rustix
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-03 10:16:30 +09:00
dependabot[bot]
588363c2c1 build(deps): bump regex from 1.9.5 to 1.9.6 (#8451)
Bumps [regex](https://github.com/rust-lang/regex) from 1.9.5 to 1.9.6.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.9.5...1.9.6)

---
updated-dependencies:
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-03 10:16:00 +09:00
Mathis Brossier
7fbfec766c book: Fix broken link (#8441) 2023-10-02 16:10:29 +02:00
Michael Davis
6abaf3d24f LSP: Fix codeAction/resolve server capability check (#8421)
Previously we accidentally checked the server's _completion_ resolve
capability rather than the code action resolve capability.
2023-10-02 12:32:27 +09:00
David Else
0e13db2832 Add validation to CSS and JSON language servers (#8433) 2023-10-02 00:41:54 +02:00
Yoav Lavi
893802d5a2 Add VSCode file associations (#8388)
* Add VSCode file associations

* Update languages.toml

Co-authored-by: Robert Clover <robert@clover.gdn>

* Change cpp *.in files to suffixes

---------

Co-authored-by: Robert Clover <robert@clover.gdn>
2023-10-02 00:40:47 +02:00
Pascal Kuthe
4e86d1c35a fix multicursor snippet placeholder directions (#8423) 2023-09-30 12:28:25 +09:00
Jonah Lund
1297d924e7 improve nord theme (#8414) 2023-09-29 21:19:57 +02:00
boofexxx
77fe8f214b refine darcula and darcula-solid themes (#8412) 2023-09-28 09:29:02 +02:00
Lucas Zebrowsky
ba06371499 Fix missing HTML tag colorization in onedark theme (#8409) 2023-09-26 22:19:52 +02:00
Ken Micklas
0c879d4edc Add shebangs for Makefiles (#8410)
For example, this is standard for Debian rules files: https://www.debian.org/doc/manuals/maint-guide/dreq.en.html#defaultrules
2023-09-26 22:19:24 +02:00
woojiq
080a085fa7 Filter out language servers which fail to spawn (#8374) 2023-09-26 15:12:19 -05:00
Ben Haines
2776233a6f update go highlight queries (#8399) 2023-09-26 18:05:42 +02:00
Michael Davis
01e281ce10 markdown: Recognize <code> tags with attributes as code (#8397) 2023-09-26 11:05:19 +09:00
dependabot[bot]
b495ca429a build(deps): bump rustix from 0.38.13 to 0.38.14 (#8395)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-26 11:04:48 +09:00
dependabot[bot]
d7b38e3e4a build(deps): bump smallvec from 1.11.0 to 1.11.1 (#8394)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-26 11:04:16 +09:00
dependabot[bot]
35cbe26f21 build(deps): bump unicode-width from 0.1.10 to 0.1.11 (#8393)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-26 11:03:59 +09:00
A-Walrus
f520b16fca Style Bold/Italic/Strikethrough markdown in docs (#8385)
* Style Bold/Italic/Strikthrough markdown in docs

* Flatten to single match
2023-09-25 17:42:42 +02:00
nerohd
0252c7b162 add polkit rules files to javascript detection (#8370) 2023-09-25 10:44:35 +09:00
zefr0x
17edbacfbd Improve and complete Arabic translation for meta information (#8380) 2023-09-25 10:18:26 +09:00
nerohd
7702e130ba add polkit policy files to xml detection (#8369)
polkit policy files are just xml files, https://www.freedesktop.org/software/polkit/docs/latest/polkit.8.html for more info
2023-09-24 13:33:43 +02:00
zefr0x
842687e845 Add .webmanifest as supported JSON files (#8342)
Closes #8310
2023-09-23 10:50:44 +09:00
Alexis Mousset
2284bce970 Allow specifying a different style for diff indicator in vcs gutter. (#8343)
This allows using a background in diff style
(for nice patch file coloring) while keeping the
gutter indicator nice (and using appropriate colors).
2023-09-21 00:28:36 +02:00
postsolar
651fd1ca72 Add Unicode support to PureScript's highlight queries (#8338) 2023-09-21 00:26:40 +02:00
dependabot[bot]
1c88432efc build(deps): bump serde_json from 1.0.105 to 1.0.107 (#8330)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.105 to 1.0.107.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.105...v1.0.107)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-19 11:30:34 +09:00
dependabot[bot]
3640623b45 build(deps): bump chrono from 0.4.30 to 0.4.31 (#8328)
Bumps [chrono](https://github.com/chronotope/chrono) from 0.4.30 to 0.4.31.
- [Release notes](https://github.com/chronotope/chrono/releases)
- [Changelog](https://github.com/chronotope/chrono/blob/main/CHANGELOG.md)
- [Commits](https://github.com/chronotope/chrono/compare/v0.4.30...v0.4.31)

---
updated-dependencies:
- dependency-name: chrono
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-19 11:30:13 +09:00
dependabot[bot]
312c175aec build(deps): bump indoc from 2.0.3 to 2.0.4 (#8329)
Bumps [indoc](https://github.com/dtolnay/indoc) from 2.0.3 to 2.0.4.
- [Release notes](https://github.com/dtolnay/indoc/releases)
- [Commits](https://github.com/dtolnay/indoc/compare/2.0.3...2.0.4)

---
updated-dependencies:
- dependency-name: indoc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-19 11:29:46 +09:00
dependabot[bot]
53500f6ebd build(deps): bump libc from 0.2.147 to 0.2.148 (#8327)
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.147 to 0.2.148.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.147...0.2.148)

---
updated-dependencies:
- dependency-name: libc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-19 11:29:30 +09:00
zetashift
7fa5f341e9 Update Unison highlights (#8315) 2023-09-17 13:23:19 -05:00
NomisIV
cb39242783 Use Maskhjarnas tree-sitter-purescript (#8306) 2023-09-17 18:50:58 +02:00
Yoav Lavi
ca9a7d506e add .babelrc highlighting (#8309) 2023-09-17 10:29:14 -05:00
Yoav Lavi
8b076e3851 Add .editorconfig highlighting as INI (#8308) 2023-09-16 15:31:19 -05:00
pacien
37e48f4307 queries/nix: align match start for language comments
This rule failed to override other ones because it started its
matching later.
2023-09-16 15:09:07 -05:00
pacien
b4494e1dc5 queries/nix: add injection rule for python test scripts 2023-09-16 15:09:07 -05:00
Yoav Lavi
0e556484b7 Add JSON highlighting for flake.lock files (#8304) 2023-09-16 14:27:50 -05:00
Cyrill Schenkel
941dc6c614 add GNU assembler (gas) support #8291) 2023-09-16 02:04:44 +02:00
Abderrahmane TAHRI JOUTI
19d44b6fde add cyan_light theme (#8293)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2023-09-16 00:22:40 +02:00
Pascal Kuthe
13d4463e41 correctly center items in picker preview 2023-09-14 11:00:28 +09:00
Pascal Kuthe
e9d0bd7aef fix crash in picker preview for invalid ranges 2023-09-14 11:00:28 +09:00
Anton Romanov
e41bee6ac6 [theme] Fix zenburn theme inlay hint color (#8278) 2023-09-14 00:38:14 +02:00
Henrik Tjäder
764172d5bc Theme: Papercolor: Cleanup, linting and using inheritance (#8276) 2023-09-14 00:37:53 +02:00
Em Zhan
fe6b556f51 Fix search highlighting for the default docs theme (#8270) 2023-09-13 16:37:39 +02:00
Chirikumbrah
729f32de21 Better indent line color for Dracula theme. (#8266) 2023-09-12 23:06:21 +02:00
Bannerets
e4ba237258 Disable auto-pairing ` in OCaml (#8260) 2023-09-12 12:51:54 -05:00
dependabot[bot]
ccabfee381 build(deps): bump rustix from 0.38.11 to 0.38.13 (#8249)
Bumps [rustix](https://github.com/bytecodealliance/rustix) from 0.38.11 to 0.38.13.
- [Release notes](https://github.com/bytecodealliance/rustix/releases)
- [Commits](https://github.com/bytecodealliance/rustix/compare/v0.38.11...v0.38.13)

---
updated-dependencies:
- dependency-name: rustix
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-12 02:47:31 +02:00
dependabot[bot]
e3d537cee5 build(deps): bump url from 2.4.0 to 2.4.1 (#8250)
Bumps [url](https://github.com/servo/rust-url) from 2.4.0 to 2.4.1.
- [Release notes](https://github.com/servo/rust-url/releases)
- [Commits](https://github.com/servo/rust-url/compare/v2.4.0...v2.4.1)

---
updated-dependencies:
- dependency-name: url
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-12 02:21:14 +02:00
dependabot[bot]
719ef3f879 build(deps): bump chrono from 0.4.26 to 0.4.30 (#8247)
Bumps [chrono](https://github.com/chronotope/chrono) from 0.4.26 to 0.4.30.
- [Release notes](https://github.com/chronotope/chrono/releases)
- [Changelog](https://github.com/chronotope/chrono/blob/main/CHANGELOG.md)
- [Commits](https://github.com/chronotope/chrono/compare/v0.4.26...v0.4.30)

---
updated-dependencies:
- dependency-name: chrono
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-12 02:18:35 +02:00
dependabot[bot]
d46127fb2e build(deps): bump which from 4.4.0 to 4.4.1 (#8251)
Bumps [which](https://github.com/harryfei/which-rs) from 4.4.0 to 4.4.1.
- [Changelog](https://github.com/harryfei/which-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/harryfei/which-rs/compare/4.4.0...4.4.1)

---
updated-dependencies:
- dependency-name: which
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-11 19:11:17 -05:00
dependabot[bot]
a8449afbfe build(deps): bump thiserror from 1.0.47 to 1.0.48 (#8252)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.47 to 1.0.48.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.47...1.0.48)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-11 19:09:27 -05:00
Em Zhan
7090555dab Add insert-final-newline config option (#8157)
Co-authored-by: Xalfer <64538944+Xalfer@users.noreply.github.com>
2023-09-11 19:06:25 -05:00
Blaž Hrastnik
ef23847957 scheme: Highlight abbreviations 2023-09-11 13:15:58 +09:00
Blaž Hrastnik
95e994ab38 Add more shebangs to languages 2023-09-11 13:15:45 +09:00
Blaž Hrastnik
060e73a711 Lower idle-timeout to 250ms
The aim is to make it slow enough it only triggers during a typing
pause, but not too slow. Initial value was chosen as a safe slow
default but I've been using 250 for a while.
2023-09-11 13:14:41 +09:00
Galen Abell
acef759a5e Add additional YAML injections (#8217) 2023-09-10 22:49:28 +02:00
Alexis Mousset
83ac53a109 Fix various typos (#8233) 2023-09-10 15:31:12 -05:00
Yhya
6f3a6575dc add material theme collection (#8211)
* Create material theme files

* Add material deep ocean pallete

* Add primary theme properties to material deep ocean theme

* Fix material deep ocean theme

* Ad syntax highlighting to material deep ocean theme

* Make material oceanic theme

* Make material darker theme

* Remove material lighter theme

* Make material palenight theme

* Make other material themes inherit material deep ocean theme

* Add virtual ruler background to the material theme collection
2023-09-10 21:27:56 +02:00
Jesse Luehrs
81d6d3ff0e re-add indent and textobject queries for perl (#7947)
* bump tree-sitter-perl version

need some grammar tweaks for the indent queries to function properly

* add indent queries for perl

* add textobject queries for perl
2023-09-10 21:27:04 +02:00
Alexis Mousset
829db76563 Add feed-related formats as xml (#8232) 2023-09-10 13:54:34 -05:00
Ross Manchester
0d986fce76 chore: add additional ignore file highlights (#8220)
* chore: add additional ignore file highlights

Various files use the same syntax highlighting as `.gitignore` and
similarly tell different tools what files/folders to ignore. Update the
languages file so that other ignore type files use the same highlighting
as gitignore. The files added are:

- `.ignore`
- `.prettierignore`
- `.eslintignore`
- `.npmignore`

* chore: add highlighting for codeowners files

Add `CODEOWNERS` as an additional file type for `git-ignore` in the
language file. `CODEOWNERS`'s grammar is close enough to that of
`.gitignore`, this can be used to avoid making a new grammar
specifically for `CODEOWNERS` files.
2023-09-10 13:53:15 -05:00
Luke Halasy
b959162ceb Add tree-sitter-highlight-name command (#8170)
* adds treesitter-highlight-name command

* commit documentation changes

* moves the get_highlight_name function into core/syntax

* rename get_highlight_name function to get_highlight_for_node_at_position

* addresses pr comments: moves fn into helper fn, simplifies a lot

* commit updated documentation changes

* changes scope method to return &str so that callers can decide whether or not to own
2023-09-10 14:57:44 +02:00
Jaden
528a5e3aff Update EdgedDB (ESDL) grammar (#8222) 2023-09-09 21:58:28 +02:00
Pascal Kuthe
eb9c37844c fix syntax highlights in dynamic picker (#8206) 2023-09-09 13:41:49 +09:00
Theodore Gregory
14401ff75b docs: fix link to document formatting requests (#8166) 2023-09-08 19:15:42 +02:00
Weiyuan Wu
8017bb2999 add redraw command (#6949)
Co-authored-by: Roberto Vidal <vidal.roberto.j@gmail.com>
2023-09-08 10:46:36 +09:00
Michael Davis
c0fd8bc61b Fix Clone definition for Injector (#8194) 2023-09-07 11:10:00 +09:00
Pascal Kuthe
e6cdc5f9d3 Don't use word splitting during fuzzy matching (#8192) 2023-09-06 23:03:48 +09:00
Pascal Kuthe
0cfd46c14f Do not show (running) when opening picker (#8148)
* only stream from background thread if necessary

If the file transversal is longer shorter 30ms it will now be performed
on the main thread. Spawning a thread can take a while (or rather it
takes a while until that thread is scheduled) so the files can actually
take a while to show up. This prevents the `(running)` indicator from
briefly showing up when opening the file picker in a small directory.

* run partial cargo update
2023-09-06 14:01:56 +09:00
Jonathan LEI
8778083b5a Detect tmux clipboard provider on macOS (#8182) 2023-09-06 14:01:32 +09:00
dependabot[bot]
48b7520bca build(deps): bump actions/checkout from 3 to 4 (#8173)
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-05 08:51:19 -05:00
dependabot[bot]
65c3cca3cc build(deps): bump serde_json from 1.0.104 to 1.0.105 (#8177)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-05 14:02:40 +02:00
dependabot[bot]
4dbdcaebba build(deps): bump regex from 1.9.4 to 1.9.5 (#8175)
Bumps [regex](https://github.com/rust-lang/regex) from 1.9.4 to 1.9.5.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.9.4...1.9.5)

---
updated-dependencies:
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-05 10:02:34 +09:00
dependabot[bot]
761cdf124a build(deps): bump serde from 1.0.185 to 1.0.188 (#8176)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.185 to 1.0.188.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.185...v1.0.188)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-05 10:02:04 +09:00
dependabot[bot]
10e7ca819b build(deps): bump cachix/install-nix-action from 22 to 23 (#8172)
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 22 to 23.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/v22...v23)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-05 10:01:37 +09:00
dependabot[bot]
9b397c9e68 build(deps): bump rustix from 0.38.8 to 0.38.11 (#8174)
Bumps [rustix](https://github.com/bytecodealliance/rustix) from 0.38.8 to 0.38.11.
- [Release notes](https://github.com/bytecodealliance/rustix/releases)
- [Commits](https://github.com/bytecodealliance/rustix/compare/v0.38.8...v0.38.11)

---
updated-dependencies:
- dependency-name: rustix
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-05 10:01:17 +09:00
John Scarrott
61814fea7f Nord Theme: Fix missing ui text focus, use undercurls for diagnostics (#8165) 2023-09-04 12:21:18 -05:00
Ivan Molodetskikh
9d7f66574d Update tree-sitter-blueprint (#8161) 2023-09-04 18:50:42 +02:00
Lorenzo Bellina
e8fc77fe98 Maintain the current cursor's position and view in the vsplit/hsplit commands too (#8109)
Co-authored-by: Benjamin Bouvier <public@benj.me>
2023-09-04 12:39:48 +09:00
woojiq
bb3e6998e6 Fix find commands for buffers with non-LF line-endings (#8111) 2023-09-03 23:12:38 +02:00
Pascal Kuthe
a38ec6d6ca avoid excessive memory consumption in picker (#8127)
* avoid excessive memory consumption from file picker

* fix typos

Co-authored-by: Chris <75008413+cd-a@users.noreply.github.com>

---------

Co-authored-by: Chris <75008413+cd-a@users.noreply.github.com>
2023-09-01 09:13:36 +09:00
Michael Davis
7cf775d512 Build flake packages with stable Rust (#8133)
We can continue to use the MSRV for local development and checks while
building release executables with the latest stable Rust, as we do in
CI.
2023-09-01 08:57:38 +09:00
Michael Davis
48373d4a2b Clear completion when switching windows via click (#8118)
The completion component assumes that it operates on the same View but
it's possible to break this assumption by switching windows through
left-clicking. I believe we should clear the completion menu when
switching windows to fix this.

This change fixes a panic for this scenario:

* Open a buffer with LSP completion available
* Split the window (for example '<C-w>v')
* Enter insert mode and trigger the completion menu
* Select a completion candidate (for example with '<C-n>')
* Switch to the original window by left-clicking in its area
* Enter insert mode and make edits (for example 'o<backspace>')

This will trip the 'assert_eq' in Document::restore.
2023-08-31 15:12:32 +09:00
Michael Davis
a2767269d0 crossterm: Handle 'hidden' modifier (#8120)
Crossterm supports the 'hidden' SGR parameter but we previously didn't
set the attribute when the "hidden" modifier was specified in a theme.
2023-08-31 15:11:01 +09:00
Ezekiel Warren
6bef982f2d use which on formatter command (#8064) 2023-08-30 16:51:03 +02:00
chtenb
7fffc0a5d1 Rename reset to default (#8114)
Use `default` instead of `reset`, as this is the conventional name for ANSI codes 39/49. The word `reset` should be reserved for ANSI code `0`, which resets both fg and bg colors at once, while also removing all modifiers. While the code uses the value name `Reset`, this is misleading and should not leak into the user space.
2023-08-30 16:38:29 +09:00
Pascal Kuthe
0cb595e226 transition to nucleo for fuzzy matching (#7814)
* 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>
2023-08-30 13:26:21 +09:00
Tanguy
40d7e6c9c8 Copy desktop and icon files to Nix output (#7979) 2023-08-29 16:22:03 +09:00
woojiq
b67d2c3a68 fix: line numbers remain relative when helix loses focus (#7955)
* fix: line numbers remain relative when helix loses focus

If `line number = relative` and a new window is opened in helix, lines inside unfocused windows will be `absolute`. This commit adds the same thing when helix becomes unfocused in a terminal emulator.

* partial rebase
2023-08-29 16:00:55 +09:00
West
82cd445715 add reset to the color palette (#8083) 2023-08-29 15:18:27 +09:00
dependabot[bot]
3ac2ac6dd6 build(deps): bump log from 0.4.19 to 0.4.20 (#8103)
Bumps [log](https://github.com/rust-lang/log) from 0.4.19 to 0.4.20.
- [Release notes](https://github.com/rust-lang/log/releases)
- [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/log/compare/0.4.19...0.4.20)

---
updated-dependencies:
- dependency-name: log
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-29 13:13:50 +09:00
dependabot[bot]
d71e58c1ba build(deps): bump encoding_rs from 0.8.32 to 0.8.33 (#8104)
Bumps [encoding_rs](https://github.com/hsivonen/encoding_rs) from 0.8.32 to 0.8.33.
- [Commits](https://github.com/hsivonen/encoding_rs/compare/v0.8.32...v0.8.33)

---
updated-dependencies:
- dependency-name: encoding_rs
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-29 13:13:27 +09:00
dependabot[bot]
92652638be build(deps): bump tokio from 1.31.0 to 1.32.0 (#8105)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.31.0 to 1.32.0.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.31.0...tokio-1.32.0)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-29 13:12:00 +09:00
dependabot[bot]
bcbad25e78 build(deps): bump regex from 1.9.3 to 1.9.4 (#8106)
Bumps [regex](https://github.com/rust-lang/regex) from 1.9.3 to 1.9.4.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.9.3...1.9.4)

---
updated-dependencies:
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-29 13:11:45 +09:00
Damir Vandic
79c0425154 Sync latest catppuccin theme changes (#8102) 2023-08-29 01:03:54 +02:00
Michael Davis
072e1eae92 Update tree-sitter-gleam, enable auto-format (#8085) 2023-08-28 18:44:49 +09:00
sigmaSd
992c858369 chore: update strace tree sitter grammar (#8087) 2023-08-28 18:44:28 +09:00
Álan Crístoffer
9f843e4f56 highlight(matlab): bumps grammar after some improvements (#8040) 2023-08-28 03:07:51 +02:00
Sol Fisher Romanoff
aeaeb09f48 add gemini language support (#8070) 2023-08-27 00:43:18 +02:00
David Else
c9694f680f Add ltex-ls language server (#7838) 2023-08-23 14:03:19 -05:00
arslee07
75c5a33028 Highlight Dart 3 sealed and base keywords (#7974) 2023-08-23 21:41:51 +05:30
Michael Davis
546c8ca344 Handle switch from crossterm::Result to io::Result 2023-08-23 05:17:17 +09:00
Michael Davis
050c019ccb Translate new ScrollLeft/ScrollRight crossterm mouse events 2023-08-23 05:17:17 +09:00
Michael Davis
e8fef6b6fc Bump crossterm to 0.27 in helix-term on macos 2023-08-23 05:17:17 +09:00
dependabot[bot]
c3442f3a18 build(deps): bump crossterm from 0.26.1 to 0.27.0
Bumps [crossterm](https://github.com/crossterm-rs/crossterm) from 0.26.1 to 0.27.0.
- [Release notes](https://github.com/crossterm-rs/crossterm/releases)
- [Changelog](https://github.com/crossterm-rs/crossterm/blob/master/CHANGELOG.md)
- [Commits](https://github.com/crossterm-rs/crossterm/compare/0.26.1...0.27.0)

---
updated-dependencies:
- dependency-name: crossterm
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-08-23 05:17:17 +09:00
dependabot[bot]
4ac4055fd5 build(deps): bump serde from 1.0.183 to 1.0.185 (#8034)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-22 16:57:19 +02:00
dependabot[bot]
2123b993fc build(deps): bump thiserror from 1.0.44 to 1.0.47 (#8039)
Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.44 to 1.0.47.
- [Release notes](https://github.com/dtolnay/thiserror/releases)
- [Commits](https://github.com/dtolnay/thiserror/compare/1.0.44...1.0.47)

---
updated-dependencies:
- dependency-name: thiserror
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-22 12:49:28 +09:00
dependabot[bot]
10f75ac67a build(deps): bump tempfile from 3.7.1 to 3.8.0 (#8038)
Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.7.1 to 3.8.0.
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.7.1...v3.8.0)

---
updated-dependencies:
- dependency-name: tempfile
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-22 12:49:15 +09:00
dependabot[bot]
52d5bc0eef build(deps): bump cc from 1.0.79 to 1.0.83 (#8037)
Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.0.79 to 1.0.83.
- [Release notes](https://github.com/rust-lang/cc-rs/releases)
- [Commits](https://github.com/rust-lang/cc-rs/compare/1.0.79...1.0.83)

---
updated-dependencies:
- dependency-name: cc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-22 12:49:01 +09:00
dependabot[bot]
d7e4d07943 build(deps): bump anyhow from 1.0.72 to 1.0.75 (#8035)
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.72 to 1.0.75.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.72...1.0.75)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-22 12:47:29 +09:00
Pascal Kuthe
e5f8d8ef04 create separate timer for redraw requests (#8023)
* create separate timer for redraw requests

* Update helix-view/src/editor.rs

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2023-08-22 06:24:30 +09:00
David Else
454b61cb21 Update pyright config to avoid time-outs (#8032) 2023-08-21 21:26:32 +02:00
Mike
0cc94cd87a goto_file_impl: use relative path to open file (#7965)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2023-08-21 11:15:45 -05:00
kaashyapan
75342968e2 update fsharp tree-sitter (#8024) 2023-08-21 16:38:21 +02:00
nkitsaini
22f4f313f1 Remove unnecessary Err from get_canonicalized_path (#8009)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2023-08-20 21:11:32 +02:00
nkitsaini
2767459f89 Remove path completions for :new command (#8010) 2023-08-20 12:51:08 -05:00
Michael Davis
01a1e5ec2a Update tree-sitter to latest master (#7998) 2023-08-20 00:21:18 +09:00
dastrukar
e4c95f65a6 Nord theme: Update ruler to set bg instead of fg (#7995) 2023-08-18 16:34:35 -05:00
Tomas Sandven
18a79aa3bf Update tree-sitter-robot (#7970)
* Update tree-sitter-robot

* Update Robot highlights query for Helix

* Change @comment.single to @comment

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2023-08-18 22:48:47 +02:00
Jack Allison
2b7e7c80eb Update Monokai bufferline theming to be distinguish active buffers (#7983)
* Update OneDark theme to use light-gray for inlay hints.

* fix monokai tab themeing to be more distinguishing
2023-08-17 14:14:59 -04:00
Pham Huy Hoang
56ccaedffb markdown.inline: Add injection.combined to html tag (#7960)
Problem: Closing tags for markdown is sometimes not highlighted
Solution: Add `injection.combined` to create a valid syntax tree for
highlighting
2023-08-16 11:28:07 -05:00
Bjorn Ove Hay Andersen
0a45fb4371 document a-ret picker keybinding (#7884) 2023-08-15 16:22:39 +02:00
Jens Getreu
61ccf4eded autumn theme: improve readability of comments (#7939)
* Improve readability of comments

* Rename color

* Rename color

* Sort variables
2023-08-15 09:41:26 +02:00
David Bell
567eda88ef add .star as starlark file extension (#7922)
In addition to the other defined extensions, `.star` is a frequently used extension for starlark files. This can be demonstrated through a cursory search of github for files ending in `.star` here: https://github.com/search?q=path%3A%2F.star%24%2F&type=code
2023-08-15 09:39:37 +02:00
sigmaSd
cbfe8eef89 add strace highlighting (#7928)
* feat: add strace tree sitter

* f
2023-08-15 09:38:57 +02:00
Andrés Cabero
090a225f28 goto_file: open picker if a directory is selected (#7909)
* feat: open file picker on directories using goto_file (gf)

* remove helper and call to canonicalize
2023-08-15 09:37:44 +02:00
N
7b2f3f533c Recognize more filenames for zsh (#7930)
Including `zshrc` et al. since this is convention in dotfiles repos
2023-08-15 09:31:30 +02:00
Dillard Robertson
ea88677394 Stop Terminal::drop from overriding work of Terminal::restore. (#7931)
When Application::run is exiting, either Terminal::restore or
Terminal::force_restore will be called depending
on if a panic occured or not.
Both of these functions will reset the cursor to terminal's default.

After this is done, Terminal::drop will be called.
If terminal.cursor_kind == Hidden, then
the cursor will be reset to a CursorKind::Block,
undoing the work of restore or force_restore.

This commit just removes the drop implementation,
as its job is already better handled in restore and force_restore.
2023-08-15 12:19:24 +09:00
dependabot[bot]
2756f70dfc build(deps): bump rustix from 0.38.4 to 0.38.8 (#7946)
Bumps [rustix](https://github.com/bytecodealliance/rustix) from 0.38.4 to 0.38.8.
- [Release notes](https://github.com/bytecodealliance/rustix/releases)
- [Commits](https://github.com/bytecodealliance/rustix/compare/v0.38.4...v0.38.8)

---
updated-dependencies:
- dependency-name: rustix
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-15 09:33:40 +09:00
dependabot[bot]
a1c50056bf build(deps): bump regex from 1.9.1 to 1.9.3 (#7945)
Bumps [regex](https://github.com/rust-lang/regex) from 1.9.1 to 1.9.3.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.9.1...1.9.3)

---
updated-dependencies:
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-15 09:33:31 +09:00
dependabot[bot]
e9a807a48f build(deps): bump bitflags from 2.3.3 to 2.4.0 (#7943)
Bumps [bitflags](https://github.com/bitflags/bitflags) from 2.3.3 to 2.4.0.
- [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/2.3.3...2.4.0)

---
updated-dependencies:
- dependency-name: bitflags
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-15 09:33:22 +09:00
dependabot[bot]
0b2e96885f build(deps): bump tokio from 1.29.1 to 1.31.0 (#7944)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.29.1 to 1.31.0.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.29.1...tokio-1.31.0)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-15 09:33:07 +09:00
Jonathan LEI
3a162e2bef Make editor remember the latest search register (#5244) 2023-08-14 18:59:49 -05:00
quantonganh
085706e0cd Include completions for git-ignored files in debugger prompt (#7936) 2023-08-14 08:46:06 -05:00
theteachr
d6bb1092c7 Update stale comments
Obsoleted by https://github.com/helix-editor/helix/pull/4731
2023-08-14 07:48:53 -04:00
Jesse Luehrs
d56638ba9a fix formatting in the rust textobject query file
looks like two lines were unintentionally joined - it doesn't appear to
affect the functionality, but it's confusing to read
2023-08-14 07:45:58 -04:00
Erasin Wang
19dff5c3a4 Update slint grammar (#7893) 2023-08-13 09:18:57 +02:00
Noob Zhang
b0c270f8e6 Added some LSP servers and updated python's roots (#7897)
* Add csharp-ls for possible c-sharp LSP

See https://github.com/razzmatazz/csharp-language-server for more info
about it.

* Add pyright for possible python LSP

It may be prefered than pylsp by someone.
According to https://github.com/helix-editor/helix/issues/5479, I don't
make it default for everyone. Just for people who need this.

* Update roots of python

Using some known filenames to detect correct project root.

* Add pylyzer for possible python LSP

Co-authored-by: zetashift <rskaraya@gmail.com>

---------

Co-authored-by: zetashift <rskaraya@gmail.com>
2023-08-13 09:17:56 +02:00
Jesse Luehrs
2caca1c4e9 Add pod highlighting (#7907) 2023-08-12 20:14:18 -05:00
Dillard Robertson
01776e6851 Prevent GraphemeStrs created from Strings from leaking (#7920) 2023-08-12 20:13:06 -05:00
Daniel Ebert
ee3171cc54 Document @align indent capture. 2023-08-11 23:44:02 +09:00
Daniel Ebert
b315901cbb Run indentation tests on a part of the Helix source code.
Add C++ indent test file.
2023-08-11 23:44:02 +09:00
Daniel Ebert
155cedc5c8 Fix broken indentation that causes the indentation tests to fail.
For some reason, `cargo fmt` does not change the indentation in
these places (maybe it isn't sure about what the correct formatting
should be).
2023-08-11 23:44:02 +09:00
Daniel Ebert
36a59e4482 Improve C, Rust & Python indent queries & add @align captures. 2023-08-11 23:44:02 +09:00
Daniel Ebert
eab0d4fa4b Implement @align (and @anchor) indent query. 2023-08-11 23:44:02 +09:00
Skyler Hawthorne
929eb0c39e expand indents guide 2023-08-11 06:22:22 +09:00
Skyler Hawthorne
7078e84007 Fix YAML auto indent
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
2023-08-11 06:22:22 +09:00
Ivan Isekeev
57f093d836 Jinja language family syntax support (#7233)
* feat: add jinja language support

* feat: add nunjucks language support

* feat: add to lang support book jinja and nunjucks languages
2023-08-09 16:26:58 +02:00
Jan9103
c0eae84073 feat: add todo.txt tree-sitter (#7835) 2023-08-09 15:35:29 +02:00
Gaël
cb9b08d650 Add new Yellowed theme to default themes (#7849)
* added new Yellowed theme to default themes

* syntax typo and missing color fix
2023-08-09 14:02:30 +02:00
Artemiy
1077630834 Update tree-sitter grammar for nu (#7873)
* Update tree-sitter grammar for nu

Change tree-sitter grammar for nushell to 'officially' maintained
by nushell project https://github.com/nushell/tree-sitter-nu. Update
to the latest version. Replace queries with supported

* Restore injection queries for nu

Restore injection.scm queries for nushell tree-sitter grammar
2023-08-09 14:00:59 +02:00
Alex Vinyals
48eb0d4792 Enhance :toggle to support cycling numbers (#7877) 2023-08-08 20:56:55 -05:00
zetashift
294aa669a2 Add Unison support (#7724) 2023-08-08 20:50:49 +02:00
Michael Davis
f01ca107fb Detect non-existent files as non-readonly (#7875) 2023-08-09 03:28:53 +09:00
Tshepang Mbambo
cefc33e3df use AND operator when searching (#7839)
This makes search results less surprising, because it is how major web search engines behave
2023-08-08 15:22:52 +02:00
dependabot[bot]
1c1df42cc0 build(deps): bump globset from 0.4.12 to 0.4.13 (#7864)
Bumps [globset](https://github.com/BurntSushi/ripgrep) from 0.4.12 to 0.4.13.
- [Release notes](https://github.com/BurntSushi/ripgrep/releases)
- [Changelog](https://github.com/BurntSushi/ripgrep/blob/master/CHANGELOG.md)
- [Commits](https://github.com/BurntSushi/ripgrep/compare/globset-0.4.12...globset-0.4.13)

---
updated-dependencies:
- dependency-name: globset
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-08 15:21:16 +02:00
dependabot[bot]
f7c0ca7e0c build(deps): bump tempfile from 3.7.0 to 3.7.1 (#7862)
Bumps [tempfile](https://github.com/Stebalien/tempfile) from 3.7.0 to 3.7.1.
- [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Stebalien/tempfile/compare/v3.7.0...v3.7.1)

---
updated-dependencies:
- dependency-name: tempfile
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-08 15:20:49 +02:00
dependabot[bot]
942852b933 build(deps): bump lsp-types from 0.94.0 to 0.94.1 (#7861)
Bumps [lsp-types](https://github.com/gluon-lang/lsp-types) from 0.94.0 to 0.94.1.
- [Changelog](https://github.com/gluon-lang/lsp-types/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gluon-lang/lsp-types/compare/v0.94.0...v0.94.1)

---
updated-dependencies:
- dependency-name: lsp-types
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-08 15:19:40 +02:00
woojiq
aa4d84a0b3 Align view for background buffer opened with alt-ret (#7691)
* 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>
2023-08-08 15:17:29 +02:00
dependabot[bot]
c1c71bb90e build(deps): bump serde from 1.0.180 to 1.0.183 (#7860)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-08 14:52:44 +02:00
Connortsui20
fcbac485f8 Show whether file readonly in statusline (#7740) 2023-08-08 14:51:34 +02:00
Jesse Luehrs
a7a145ad3d Center the picker preview selection using visual lines (#7837)
this way the preview always shows the selection even if lines were
wrapped
2023-08-07 20:06:51 -05:00
Anshul Dalal
c7e9e94f00 Skip rendering gutters when gutter width exceeds view width (#7821) 2023-08-07 19:13:10 -05:00
woojiq
7cda5b8592 build(tree-sitter): update javascript, typescript and tsx (#7852)
* build(tree-sitter): update javascript, typescript and tsx

* update revision of tree-sitter parsers for these languages.
* rename `?.` to `optional_chain`, introduced in tree-sitter/tree-sitter-javascript@186f2adbf7.

* fix(highlight): change jsx queries to match latest tree-sitter

Latest tree-sitter/tree-sitter-javascript@bb1f97b643 added some breaking changes that broke highlighting.
* Remove some queries with `nested_identifier`.
* Remove deprecated `jsx_fragment` from indent query.
* Count `</` and `/>` as a single token.
2023-08-07 14:07:56 -05:00
Petr Gajdůšek
7af37bb3b9 Add tree-sitter textobjects queries for bash (#7764)
This implements function, (calling) argument and comment captures for use
in the textobject selections in bash.

This also updates the generated docs after adding the textobjects for bash.
2023-08-08 03:27:35 +09:00
Michael Davis
d6c799fb30 Update tree-sitter-git-commit (#7831)
This fixes a problem parsing the "On branch _branch_" part of the
commit comment when the branch contains a slash.
2023-08-08 03:27:16 +09:00
Michael Davis
86fc203197 CI: Remove the aarch64 appimage build steps from release (#7832)
The steps mistakenly produce a x86_64 appimage and call it aarch64.
linuxdeploy doesn't currently support producing aarch64 appimages so
we should just remove these steps for aarch64-linux.
2023-08-08 03:16:05 +09:00
Blaž Hrastnik
57071513a8 Only use tsq for tsq files
This makes our highlight files more plain but it correctly highlights
scheme :/
2023-08-07 23:46:16 +09:00
Blaž Hrastnik
979933b514 Update tree-sitter-scheme 2023-08-07 23:46:16 +09:00
woojiq
1d189820a1 feat(indent): add basic java indentation queries (#7844) 2023-08-07 08:48:54 -05:00
Mohamed Imrane Chehabi
80d2599f9c Add new moon theme to default themes (#7834)
* Add new moon theme to default themes

* Remove .DS_Store
2023-08-05 00:24:50 +02:00
Jummit
f19793c2f8 Improve wren support (#7819) 2023-08-04 16:25:36 +02:00
Christoph Sax
5a51036bc1 Update t32 language queries to version 2.2.1 (#7811)
Version 2.2.1 of the grammar adds extended support for HLL (C, C++,..)
expressions. Quite a few node types were added, renamed or removed in
the process.

This change brings the highlight queries in sync with the ones found in
the repository of the grammar. The highlighting tests "look" okay after
updating the queries.

Recently, Codeberg had some reliability issues. That is why the language
is now using the mirror repository on GitLab as source instead.

Co-authored-by: Christoph Sax <christoph.sax@mailbox.org>
2023-08-04 16:20:12 +02:00
J. Brock
286e44050d Bump the version of Hare's grammar (#7784) 2023-08-04 16:19:26 +02:00
dependabot[bot]
d5af4ae6b3 build(deps): bump serde from 1.0.175 to 1.0.180 (#7794)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.175 to 1.0.180.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.175...v1.0.180)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-04 22:44:04 +09:00
Austin L Wolfgram
5535ba8b7d fix range formatting error message typo (#7823) 2023-08-04 04:33:30 -04:00
voroskoi
bc737404e8 Update tree-sitter-zig (#7803) 2023-08-02 21:22:28 +02:00
Jimmy Zelinskie
325692a154 languages: add protobuf language servers (#7796)
* languages: add bufls protobuf language server

* languages: add pbkit protobuf language server
2023-08-02 20:12:31 +02:00
Skyler Hawthorne
15e07d4db8 feat: smart_tab
Implement `smart_tab`, which optionally makes the tab key run the
`move_parent_node_start` command when the cursor has non- whitespace to
its left.
2023-08-01 09:41:42 -05:00
Skyler Hawthorne
93acb53812 add node boundary movement 2023-08-01 09:41:42 -05:00
Zoey Hewll
1d702ea191 update yanked dependency (#7800) 2023-08-01 22:21:46 +09:00
dependabot[bot]
99413558b9 build(deps): bump serde_json from 1.0.103 to 1.0.104 (#7793)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-01 02:28:44 +02:00
dependabot[bot]
0eea76c415 build(deps): bump globset from 0.4.11 to 0.4.12 (#7795)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-01 02:28:25 +02:00
Michael Davis
d4f9716fbc Add yank_to_clipboard commands, bind to <space>y by default
The clipboard special registers are able to retain multiple selections
and also join the value when copying it to the clipboard. So by default
we should yank regularly to the '*' and '+' registers. That will have
the same behavior for the clipboards but will allow pasting multiple
selections if the clipboard doesn't change between yanks.
2023-07-31 15:05:38 +09:00
Michael Davis
4555a6b433 Reimplement clipboard commands in terms of special regs
Since the clipboard provider now lives on the Registers type, we want
to eliminate it from the Editor. We can do that and clean up the
commands that interact with the clipboard by calling regular yank,
paste and replace impls on the clipboard special registers.

Eventually the clipboard commands could be removed once macro keybinding
is supported.
2023-07-31 15:05:38 +09:00
Michael Davis
2d838d729c Preview the latest value for regular registers
This fixes a discrepancy between regular registers which are used for
yanking multiple values (for example via `"ay`) and regular registers
that store a history of values (for example `"a*`).

Previously, the preview shown in `select_register`'s infobox would show
the oldest value in history. It's intuitive and useful to see the most
recent value pushed to the history though.

We cannot simply switch the preview line from `values.first()`
to `values.last()`: that would fix the preview for registers
used for history but break the preview for registers used to yank
multiple values. We could push to the beginning of the values with
`Registers::push` but this is wasteful from a performance perspective.
Instead we can have `Registers::read` return an iterator that
returns elements in the reverse order and reverse the values in
`Register::write`. This effectively means that `push` adds elements to
the beginning of the register's values. For the sake of the preview, we
can switch to `values.last()` and that is then correct for both usage-
styles. This also needs a change to call-sites that read the latest
history value to switch from `last` to `first`.
2023-07-31 15:05:38 +09:00
Michael Davis
86a1f0177c book: Document default and special registers 2023-07-31 15:05:38 +09:00
Michael Davis
a23b70182c commands: Allow using selected register where hardcoded
These snippets use hardcoded registers but it can be useful to be able
to specify a register for these commands.
2023-07-31 15:05:38 +09:00
Michael Davis
baceb02a09 Use refactored Registers type
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.
2023-07-31 15:05:38 +09:00
Michael Davis
0f19f282cf Add system & primary clipboards as special registers
These special registers join and copy the values to the clipboards with
'*' corresponding to the system clipboard and '+' to the primary as
they are in Vim. This also uses the trick from PR6889 to save the values
in the register and re-use them without joining into one value when
pasting a value which was yanked and not changed.

These registers are not implemented in Kakoune but Kakoune also does
not have a built-in clipboard integration.

Co-authored-by: CcydtN <51289140+CcydtN@users.noreply.github.com>
Co-authored-by: Pascal Kuthe <pascal.kuthe@semimod.de>
2023-07-31 15:05:38 +09:00
Michael Davis
32d071a392 Add the '%' (current filename) register
This register also comes from Kakoune. It's read-only and produces the
current document's name, defaulting to the scratch buffer name
constant.

(Also see PR5577.)

Co-authored-by: Ivan Tham <pickfire@riseup.net>
2023-07-31 15:05:38 +09:00
Michael Davis
da2afe7353 Add '#' and '.' special registers
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.
2023-07-31 15:05:38 +09:00
Michael Davis
5eb1a25d8a Refactor Registers to take Editor
This sets up a new Registers type that will allow us to expand support
for special registers. (See the child commits.)

We start simple with the regular (`Vec<String>`) registers and the
simplest special register, the black hole. In the child commits we
will expand these match arms with more special registers.

The upcoming special registers will need a few things that aren't
possible with the current Registers type in helix-core:

* Access to the `Editor`. This is only necessary when reading from
  registers, so the `&Editor` parameter is only added to
  `Registers::read`.
* Returning owned values. Registers in helix-core returns references
  to the values backed by the `Vec<String>` but future special registers
  will need to return owned values. We refactor the return value of the
  read operations to give `Cow<str>`s and iterators over those.
* Returning a `Result` for write/push functions. This will be used by
  the clipboard special registers.
2023-07-31 15:05:38 +09:00
lydiandy
57952c46a4 replace new lsp for vlang (#7760)
* fix vlang grammar fetch and build fail

* update highlights.scm for v-analyzer

* Update languages.toml

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* Update runtime/queries/v/highlights.scm

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* update scm for new lsp

* gen doc lang-support.md

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2023-07-31 01:04:55 +02:00
Jesse Luehrs
d5571968fa add new theme based on the default vim dark theme (#7785) 2023-07-30 16:53:42 +02:00
Mateusz S. Szczygieł
13e7edab19 Register .gltf file type for JSON (#7781) 2023-07-29 18:57:33 +02:00
Matthias Q
224fd5fa29 feat: update prql parser (#7771) 2023-07-28 23:01:06 +02:00
Jummit
9a4890f62b Add wren support (#7765) 2023-07-28 18:13:51 +02:00
Michael Davis
d6856cfeec Refactor Nix flake to use crane (#7763)
This resolves a build issue with nci/dream2nix and git dependencies.
We can keep most of the helix-specific parts of the flake, we just need
to switch from configuring nci to calling craneLib functions.

We also switch to flake-utils from flake-parts:

* Using rust-overlay with flake-parts directly is unergonomic
  (see https://github.com/hercules-ci/flake-parts/discussions/83).
* Removing flake-parts reduces the overall dependencies: rust-overlay
  already depends on flake-utils.
2023-07-28 13:30:26 +09:00
Philipp Mildenberger
8a28f30593 Reformat with nightly rustfmt for better let-else formatting (#7721) 2023-07-27 11:57:19 +09:00
Pascal Kuthe
262a595e53 pin TS to unreleased git revision to fix freezes (#7737) 2023-07-27 11:50:40 +09:00
Michael Davis
953073a679 highlighted_code_block: Take input text as &str
This removes a handful of allocations for functions calling into the
function, which is nice because the prompt may call this function on
every keypress.
2023-07-27 11:50:19 +09:00
Michael Davis
98ef05d768 Prefer RopeSlice to &Rope in helix_core::syntax
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>
2023-07-27 11:50:19 +09:00
Michael Davis
f0b877e258 Tune regex highlights for usage in prompts
Since regex is almost always injected into other languages,
`pattern_character`s will inherit the highlight for the structure that
injects them (for example `/foo/` in JavaScript or `~r/foo/` in Elixir).
This removes the string highlight when used in the prompt.

We also add `ERROR` node highlighting so that errors in regex syntax
appear in the prompt. This resolves a TODO in the `regex_prompt`
function about highlighting errors in the regex.
2023-07-27 11:50:19 +09:00
Michael Davis
0dc3753eb2 Syntax-highlight regex prompts
We can use tree-sitter-regex highlighting in prompts for entering
regexes, like `search` or `global_search`. The `highlighted_code_block`
function from the markdown component makes this a very small change.

This could be improved in the future by leaving the parsed syntax tree
on the prompt, allowing incremental updates. Prompt lines are usually so
short though and tree-sitter-regex is rather small and uncomplicated,
so that improvement probably wouldn't make a big difference.
2023-07-27 11:50:19 +09:00
Michael Davis
6a431afc4e Save an undo checkpoint before accepting completion (#7747) 2023-07-27 11:48:16 +09:00
eh
dea6894f92 Theme Pop-Dark: Increase Diagnostics clarity (#7702) 2023-07-26 22:33:10 +02:00
saltlakrits
5a52897014 Update everforest_dark.toml to add missing color definitions (#7739) 2023-07-26 15:31:35 +02:00
Pham Huy Hoang
75239a938f fix incorrect predicate in comment highlights (#7732) 2023-07-25 23:56:02 +02:00
Federico Stra
a188282b37 Update soft-wrap indicator in gruvbox themes (#7736) 2023-07-25 23:55:02 +02:00
dependabot[bot]
b266628c17 build(deps): bump signal-hook from 0.3.16 to 0.3.17 (#7728)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-25 03:04:01 +02:00
dependabot[bot]
00dc205108 build(deps): bump thiserror from 1.0.43 to 1.0.44 (#7730)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-25 03:03:50 +02:00
dependabot[bot]
7295340119 build(deps): bump serde from 1.0.171 to 1.0.175 (#7727)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-25 03:03:16 +02:00
dependabot[bot]
46251a1411 build(deps): bump tempfile from 3.6.0 to 3.7.0 (#7726)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-25 03:03:03 +02:00
sigmaSd
5ec126d3e2 Fix docs for default statusline config (#7720) 2023-07-24 08:51:35 -05:00
Ravi Shekhar Jethani
48d57dad47 Fix selection highlighting in remaining gruvbox derived themes (#7717) 2023-07-23 16:45:13 +09:00
Jonas Tepe
505213d41b Drop mut from variable to silence linter (#7704) 2023-07-22 23:31:24 +09:00
Ryan Fowler
5c41f22c2a Add support for LSP DidChangeWatchedFiles (#7665)
* Add initial support for LSP DidChangeWatchedFiles

* Move file event Handler to helix-lsp

* Simplify file event handling

* Refactor file event handling

* Block on future within LSP file event handler

* Fully qualify uses of the file_event::Handler type

* Rename ops field to options

* Revert newline removal from helix-view/Cargo.toml

* Ensure file event Handler is cleaned up when lsp client is shutdown
2023-07-22 00:21:21 +02:00
sigmaSd
8977123f25 feat: resolve code action (#7677) 2023-07-21 14:50:08 -05:00
Thales Ramos
d52b790379 Add Kaolin Dark, Light and Valley Dark themes (#7151)
Add some missing keys

Inherit themes from kaolin-dark and override diverging keys
2023-07-19 11:14:28 +09:00
Christian Holman
579f68b52d allow for higher F keys to be used (#7672) 2023-07-19 11:05:32 +09:00
dependabot[bot]
b47519ab11 build(deps): bump signal-hook from 0.3.15 to 0.3.16 (#7664)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-18 10:49:19 +09:00
dependabot[bot]
b87858b7b4 build(deps): bump indoc from 2.0.2 to 2.0.3 (#7663)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-18 10:49:11 +09:00
dependabot[bot]
1478a0d3a6 build(deps): bump anyhow from 1.0.71 to 1.0.72 (#7662)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-18 10:49:03 +09:00
dependabot[bot]
6d4fd77315 build(deps): bump serde_json from 1.0.100 to 1.0.103 (#7661)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-18 10:48:58 +09:00
J. Brock
2fa576b177 Remove snap aliasing instructions (#7657)
The helix snap now gets aliased to hx by default at installation time,
so manual aliasing should no longer be required.

Signed-off-by: Joseph Brock <joseph.brock@protonmail.com>
2023-07-17 09:09:30 -05:00
Jesse Luehrs
e7f60611ac switch to https://github.com/tree-sitter-perl/tree-sitter-perl (#7644) 2023-07-17 14:09:38 +09:00
Jake Langford
ad2061bab6 Update my name README.md (#7656) 2023-07-17 14:09:19 +09:00
Pascal Kuthe
8f1c6456f3 Clear statusline while prompt is visible (#7646) 2023-07-17 14:09:07 +09:00
Pascal Kuthe
68a98ac36b use a single query for injections
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.
2023-07-17 14:08:50 +09:00
Pascal Kuthe
2d5ff9ec8f fix crash when encountering overlapping injections 2023-07-17 14:08:50 +09:00
Doug Kelkhoff
79a8fd6249 Add a more file types for R (#7633) 2023-07-16 01:48:09 +02:00
kaashyapan
2ace6032e7 Add fsharp language support (#7619) 2023-07-15 22:58:17 +02:00
Michael Goodness
86bf0e00fe feat: add Brewfile to Ruby file-types (#7629) 2023-07-14 18:57:36 +02:00
woojiq
ab819ede9a docs(install): add how to install helix from snap (#7625) 2023-07-14 10:05:49 -05:00
Erasin Wang
2cb00bcbc4 Support inlay-hints for svelteserver. (#7622) 2023-07-14 21:56:28 +09:00
Jeppe Christiansen
bc4f08febf Update Typescript, TSX and Svelte grammar, to latest tag (#6874)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2023-07-14 11:42:07 +09:00
Alex Vinyals
843ae97120 enhanced surround_replace to provide visual feedback (#7588) 2023-07-13 22:01:44 +09:00
Nick Saika
9551e4e111 runtime/themes: Add "naysayer" theme (#7570) 2023-07-13 12:01:48 +09:00
Jonathan
0e0501c510 Fix piping to Helix on macOS (#5468) 2023-07-13 12:01:17 +09:00
Karim Mk
e86bb64b63 Change dark_plus inlay-hints colors to more pleasant colors (#7611)
* Changing code_dark inlay-hints colors.

* Using dark_plus_experimental inlay hints is better ;)
2023-07-12 21:18:47 +02:00
Arian Dehghani
a5f7190614 Register systemd files as ini (#7592) 2023-07-12 13:40:58 +09:00
Jorge Santiago
9259c52606 Add shebang for nushell files (#7606) 2023-07-12 13:40:36 +09:00
Tudyx
9893a1fbcc Auto indent change if selection is linewise (#7316) 2023-07-11 14:01:48 -05:00
Yomain
8afc0282f2 Fix crash when cwd is deleted (#7185) 2023-07-11 19:51:04 +02:00
Pascal Kuthe
1adb19464f search buffer contents during global search (#5652) 2023-07-11 21:26:11 +09:00
dependabot[bot]
541d2b76d6 build(deps): bump serde_json from 1.0.99 to 1.0.100 (#7598)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-11 10:27:13 +09:00
dependabot[bot]
ac57e93583 build(deps): bump smallvec from 1.10.0 to 1.11.0 (#7597)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-11 10:26:00 +09:00
dependabot[bot]
1790097d59 build(deps): bump regex from 1.8.4 to 1.9.1 (#7596)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-11 10:25:44 +09:00
dependabot[bot]
57babd9456 build(deps): bump serde from 1.0.166 to 1.0.171 (#7595)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-11 10:25:32 +09:00
dependabot[bot]
62b2b6360d build(deps): bump toml from 0.7.5 to 0.7.6 (#7594)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-11 10:25:18 +09:00
dependabot[bot]
66a0b64853 build(deps): bump thiserror from 1.0.40 to 1.0.43 (#7593)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-11 10:25:09 +09:00
Queyrouzec
f68956a306 Update dart commit in languages.toml (#7576) 2023-07-10 11:29:20 +09:00
Gabriel Hansson
c1488267e5 (Updated) Apply motion API refinements (#6078)
* _apply_motion generalization where possible

API encourages users to not forget setting `editor.last_motion` when
applying a motion. But also not setting `last_motion` without applying a
motion first.

* (rename) will_find_char -> find_char

method name makes it sound like it would be returning a boolean.

* use _apply_motion in find_char

Feature that falls out from this is that repetitions of t,T,f,F are
saved with the context extention/move and count. (Not defaulting to extend
by 1 count).

* Finalize apply_motion API

last_motion is now a private field and can only be set by calling
Editor.apply_motion(). Removing need (and possibility) of writing:

`motion(editor); editor.last_motion = motion`

Now it's just: `editor.apply_motion(motion)`

* editor.last_message: rm Box wrap around Arc

* Use pre-existing `Direction` rather than custom `SearchDirection`.

* `LastMotion` type alias for `Option<Arc<dyn Fn(&mut Editor)>>`

* Take motion rather than cloning it.

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* last_motion as Option<Motion>.

* Use `Box` over `Arc` for `last_motion`.

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2023-07-09 16:50:24 -04:00
Em Zhan
9a324f337a docs: Update mdBook theme and improve maintainability (#7524) 2023-07-09 19:20:38 +02:00
Borys Lykah
7c338429f8 Add language support for persistent library syntax (#7261) 2023-07-09 19:17:01 +02:00
Sharpened Blade
c33795e770 Update the Nord theme to follow the Nord style guide (#7490) 2023-07-09 18:36:30 +02:00
Gammut
607b426e26 Refactor queries for ecma based languages (#7207) 2023-07-09 18:35:32 +02:00
Alex Vinyals
28452e1f2a Initialize log and config files right after parsing arguments (#7585) 2023-07-09 11:30:43 -05:00
Álan Crístoffer
550192826b highlight(matlab): Better UTF-8 handling. (#7532) 2023-07-09 17:08:29 +02:00
Ryan Fowler
828c7432e3 Implement the wa! command (#7577) 2023-07-09 09:38:50 -05:00
Alex Vinyals
1698992de6 Fix :log-open when --log is specified (#7573) 2023-07-09 16:35:07 +02:00
Alberto Romero
507dd50860 Add filename completer for shell prompt (#7569) 2023-07-08 18:12:28 +02:00
Pascal Kuthe
618620b369 use redraw handle for debouncing LSP messages (#7538) 2023-07-08 06:46:34 +09:00
Tom Taylor
dc50263ed0 Fix incorrect gutter bail message (#7534) 2023-07-07 09:20:48 -05:00
Erin van der Veen
3fb430257e Update Nickel grammar (#7551) 2023-07-06 18:53:10 +02:00
zer0-x
9ccca81305 book: Rename Arch Linux's repository from community to extra (#7543) 2023-07-05 17:50:16 +02:00
dependabot[bot]
57e538d07b build(deps): bump gix from 0.47.0 to 0.48.0 (#7531)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-04 03:06:16 +02:00
dependabot[bot]
c091f9a37c build(deps): bump serde from 1.0.164 to 1.0.166 (#7527)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.164 to 1.0.166.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.164...v1.0.166)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-03 19:57:54 -05:00
dependabot[bot]
9840422281 build(deps): bump bitflags from 2.3.2 to 2.3.3 (#7530)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-04 02:14:52 +02:00
dependabot[bot]
83e59197ac build(deps): bump indoc from 2.0.1 to 2.0.2 (#7529)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-04 02:13:58 +02:00
dependabot[bot]
d908a6ed19 build(deps): bump tokio from 1.28.2 to 1.29.1 (#7528)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-04 02:13:39 +02:00
Álan Crístoffer
457b389395 highlight(matlab): Many bug fixes and improvements (#7511) 2023-07-03 09:43:17 -05:00
Álan Crístoffer
a9849ebee4 highlight(matlab): Fix string's single-quote's color (#7493) 2023-06-30 17:39:17 -05:00
Chris Heyes
aec1b997dd Add .cppm file type to cpp language configuration (#7492) 2023-06-30 23:56:39 +02:00
Tshepang Mbambo
9546e0c0a7 docs: align content with parent paragraph (#7488) 2023-06-30 17:09:42 +02:00
Álan Crístoffer
78505e0149 Update tree-sitter-matlab (#7491) 2023-06-30 10:06:34 -05:00
Michael Davis
e0bb032f0e LSP: Forcefully shutdown uninitialized servers (#7449)
The LSP spec has this to say about initialize:

> Until the server has responded to the `initialize` request with an
> `InitializeResult`, the client must not send any additional requests
> or notifications to the server.

(https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#initialize)

The spec is not really explicit about how to handle this scenario.
Before a client sends the 'initialize' request we are allowed to send an
'exit' notification, but after 'initialize' we can't send any requests
(like shutdown) or notifications (like exit). So my intepretation is
that we should forcefully close the server in this state.

This matches the behavior of Neovim's built-in LSP client:
5ceb2238d3/runtime/lua/vim/lsp.lua (L1610-L1628)
2023-06-30 00:25:23 +09:00
gobraves
b745fb2551 update OneDarker theme to use light-gray for inlay hints. (#7433) 2023-06-30 00:25:07 +09:00
Michael Davis
4fab60030f LSP: Use negotiated position encoding for workspace edits (#7469)
Previously this was hard-coded to UTF-8 but we might have negotiated
another position encoding.
2023-06-30 00:24:13 +09:00
Michael Davis
d3f8e0592b LSP: Discard publishDiagnostic from uninitialized servers (#7467)
The spec explicitly disallows publishDiagnostic to be sent before
the initialize response:

> ... the server is not allowed to send any requests or notifications to
> the client until it has responded with an InitializeResult ...

(https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#initialize)

But if a non-compliant server sends this we currently panic because we
'.expect()' the server capabilities to be known to fetch the position
encoding. Instead of panicking we can discard the notification and log
the non-compliant behavior.
2023-06-28 16:59:13 -04:00
Pascal Kuthe
4a2337d828 correctly map unsorted positions (#7471)
* correctly map unsorted positions

* Fix typo

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2023-06-28 23:35:31 +09:00
dependabot[bot]
d8f9b901dd build(deps): bump libc from 0.2.146 to 0.2.147 (#7463)
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.146 to 0.2.147.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.146...0.2.147)

---
updated-dependencies:
- dependency-name: libc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-27 15:37:22 +02:00
dependabot[bot]
b68b3608a6 build(deps): bump serde_json from 1.0.97 to 1.0.99 (#7462)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.97 to 1.0.99.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.97...v1.0.99)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-27 14:09:27 +09:00
dependabot[bot]
dcad5cddd1 build(deps): bump toml from 0.7.4 to 0.7.5 (#7461)
Bumps [toml](https://github.com/toml-rs/toml) from 0.7.4 to 0.7.5.
- [Commits](https://github.com/toml-rs/toml/compare/toml-v0.7.4...toml-v0.7.5)

---
updated-dependencies:
- dependency-name: toml
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-27 14:08:58 +09:00
dependabot[bot]
ad04b9125d build(deps): bump gix from 0.46.0 to 0.47.0 (#7460)
Bumps [gix](https://github.com/Byron/gitoxide) from 0.46.0 to 0.47.0.
- [Release notes](https://github.com/Byron/gitoxide/releases)
- [Changelog](https://github.com/Byron/gitoxide/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Byron/gitoxide/compare/gix-v0.46.0...gix-v0.47.0)

---
updated-dependencies:
- dependency-name: gix
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-27 14:08:46 +09:00
Michael Davis
636c91c76b Mark buffers created from stdin as modified (#7431)
This resolves some confusing behavior where a scratch document created
by piping into hx is discarded when navigating away from that document.

We discard any scratch documents that are not modified and the original
`Editor::new_file_from_stdin` would create unmodified documents. We
refactor this function to create an empty document first and then to
apply the text from stdin as a change.
2023-06-26 11:17:04 -04:00
Blaž Hrastnik
8d39a81aa8 fix: Regression from d491e234f4 2023-06-26 22:20:20 +09:00
Pascal Kuthe
b33516fb16 move normalize fastpath into normalize function 2023-06-26 01:32:31 +09:00
Pascal Kuthe
d491e234f4 map positions through changes in O(N) 2023-06-26 01:32:31 +09:00
Branch Vincent
6c6923c39e feat(toml): highlight table headers (#7441) 2023-06-24 08:27:49 -05:00
Álan Crístoffer
08c0a23b79 highlight(matlab): Bumps tree-sitter-matlab commit. (#7442) 2023-06-24 15:20:42 +02:00
Scott Driggers
93ac706844 Allow any indent size from 1 to 16 (#7429) 2023-06-23 23:36:02 +09:00
Álan Crístoffer
2c5288dafb Replace MATLAB grammar (#7388) 2023-06-23 00:19:40 +02:00
eh
842518ccb7 Theme: port of Zed's OneDark and OneLight themes (#7250) 2023-06-22 23:48:02 +02:00
Pascal Kuthe
a0359f7f22 make TS matching fallback to plaintext 2023-06-22 16:00:08 +09:00
Pascal Kuthe
5dba649d81 Avoid false positives in non-fuzzy bracket match 2023-06-22 16:00:08 +09:00
Pascal Kuthe
37058e0401 match pairs which don't form a standalone TS node 2023-06-22 16:00:08 +09:00
A-Walrus
eb81cf3c01 Fix tree sitter chunking (#7417)
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...
2023-06-21 09:52:42 -05:00
dependabot[bot]
18160a667b build(deps): bump bitflags from 2.3.1 to 2.3.2 (#7394)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-20 18:53:26 +02:00
dependabot[bot]
00e819cfd4 build(deps): bump serde_json from 1.0.96 to 1.0.97 (#7393)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.96 to 1.0.97.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.96...v1.0.97)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-20 15:48:51 +02:00
dependabot[bot]
293a55ad2b build(deps): bump cachix/install-nix-action from 21 to 22 (#7392)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-20 15:24:46 +02:00
Kirawi
b0cdc2d6e1 remove mention of Wasm from vision.md (#7395) 2023-06-19 23:10:50 -05:00
LeoniePhiline
48ad9ae1bb highlight(sql): Update tree-sitter-sql to 98a7fc9 (#7387)
* highlight(sql): Update tree-sitter-sql to 92018a3

* highlight(sql): Update tree-sitter-sql to 98a7fc9
2023-06-20 00:04:40 +02:00
Michael Davis
9690e0b733 Fix Component implementations for Picker (#7382) 2023-06-19 18:55:46 +09:00
Pascal Kuthe
06d63d6ac1 Merge pull request #7264 from the-mikedavis/merge-picker-and-filepicker
Merge FilePicker into Picker
2023-06-19 04:18:42 +02:00
tomleb
29638babea Allow ANSI colors in themes (#5119) 2023-06-19 11:02:34 +09:00
Gokul Soumya
f18acadbd0 Completely remove old Picker and rename FilePicker to Picker 2023-06-18 12:28:26 -05:00
Michael Davis
545acfda88 Make file preview callback optional
When Picker and FilePicker are merged, not all Pickers will be able to
show a preview.

Co-authored-by: Gokul Soumya <gokulps15@gmail.com>
2023-06-18 12:28:16 -05:00
Gokul Soumya
fc111213b5 Move FilePicker struct def closer to impl block 2023-06-18 12:14:41 -05:00
Gokul Soumya
15cc09fc81 Render the preview in FilePicker 2023-06-18 12:14:09 -05:00
Gokul Soumya
34c8f9ab73 Move Picker::render into FilePicker::render 2023-06-18 12:11:24 -05:00
Gokul Soumya
49fbf8df53 Move Component methods except render() to FilePicker 2023-06-18 12:10:00 -05:00
Gokul Soumya
1e66e9198c Move handle_event methods from Picker to FilePicker 2023-06-18 12:07:38 -05:00
Gokul Soumya
8516f43837 Move navigation methods from Picker to FilePicker 2023-06-18 12:05:59 -05:00
Gokul Soumya
7a058c7361 Move scoring functions from Picker to FilePicker 2023-06-18 12:05:17 -05:00
Gokul Soumya
104036bd7f Copy struct fields and new() from Picker to FilePicker 2023-06-18 12:01:16 -05:00
Gokul Soumya
40916dff63 Move FilePicker::render from Component impl to normal impl
Merges the code for the Picker and FilePicker into a single Picker that
can show a file preview if a preview callback is provided. This change
was mainly made to facilitate refactoring out a simple skeleton of a
picker that does not do any filtering to be reused in a normal Picker
and a DynamicPicker (see #5714; in particular [mikes-comment] and
[gokuls-comment]).

The crux of the issue is that a picker maintains a list of predefined
options (eg. list of files in the directory) and (re-)filters them every
time the picker prompt changes, while a dynamic picker (eg. interactive
global search, #4687) recalculates the full list of options on every
prompt change. Using a filtering picker to drive a dynamic picker hence
does duplicate work of filtering thousands of matches for no reason. It
could also cause problems like interfering with the regex pattern in the
global search.

I tried to directly extract a PickerBase to be reused in Picker and
FilePicker and DynamicPicker, but the problem is that DynamicPicker is
actually a DynamicFilePicker (i.e. it can preview file contents) which
means we would need PickerBase, Picker, FilePicker, DynamicPicker and
DynamicFilePicker and then another way of sharing the previewing code
between a FilePicker and a DynamicFilePicker. By merging Picker and
FilePicker into Picker, we only need PickerBase, Picker and
DynamicPicker.

[gokuls-comment]: https://github.com/helix-editor/helix/issues/5714#issuecomment-1410949578
[mikes-comment]: https://github.com/helix-editor/helix/issues/5714#issuecomment-1407451963
2023-06-18 11:34:13 -05:00
Alex
d5af6031f6 Use default line ending in open command (#7357) 2023-06-17 14:36:36 -05:00
Alexander Brevig
b4fe31cad6 Add forth-lsp and update tree-sitter-forth (#7334)
* feat: add forth lsp and update tree sitter

* fix: update highlights
2023-06-16 23:12:29 +02:00
spectre256
d8b7232a47 Add yank_joined command (#7195)
Resolves issue #6888 by adding a command to join all selections and yank
them to the specified register. The typed command takes an argument as
the separator to use when joining the selections.
2023-06-16 21:13:23 +02:00
Alex
3fb9fafb2a Add config for default line ending (#5621) 2023-06-16 12:02:15 -05:00
Ivan Svoboda
df094909d1 Webc language support (#7290)
* feat: add webc language support

* feat: add to lang-support book webc
2023-06-13 17:41:30 +02:00
Thomas Aarholt
cbe2308210 Explain how to enter Select mode in keymap (#7333)
* Explain how to enter Select mode

Also added an equivalent explanation that Insert mode is the default, with how to return to it.

* Fix glarious typo
2023-06-13 17:07:12 +02:00
A-Walrus
4d8c9a394e Preview scratch buffers in jumplist picker (#7331) 2023-06-13 16:05:01 +02:00
A-Walrus
a4a86120e8 Fix next/prev tree-sitter inconsistency (#7332)
* 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
2023-06-13 16:04:11 +02:00
Jorge Santiago
d249639114 Add merionette theme (#7186) 2023-06-13 16:01:02 +02:00
Zisulin Morbrot
fbd22afe29 Add rl and rla aliasses for reload and reload-all commands (#7158) 2023-06-13 08:50:50 -05:00
Robert
015c079acc Add reverse_selection_contents (#7329) 2023-06-13 08:36:28 -05:00
kazimir malevich
37fcd160db Clarify the runtime directory location in installation docs (#6624)
* runtime config made clearer

* following Unix FHS

* we probably want to install Helix as a regular user without sudo access

* suggestions adopted from @the-mikedavis

* attempted to synthesise comments given

* capitalisation of second header

* required changes hopefully made

* we should have a match now

* Linux windows dir match
2023-06-13 03:35:12 +02:00
dependabot[bot]
0e42e4e193 build(deps): bump libc from 0.2.145 to 0.2.146 (#7327)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-13 09:52:06 +09:00
dependabot[bot]
66ed5bd013 build(deps): bump gix from 0.44.1 to 0.46.0 (#7325)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-13 09:51:47 +09:00
dependabot[bot]
0d998c99d4 build(deps): bump tempfile from 3.5.0 to 3.6.0 (#7326)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-13 09:51:34 +09:00
dependabot[bot]
3c23ea5d15 build(deps): bump serde from 1.0.163 to 1.0.164 (#7328)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-13 09:51:25 +09:00
dependabot[bot]
a6fd32eef4 build(deps): bump log from 0.4.18 to 0.4.19 (#7324)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-13 09:51:11 +09:00
Philipp Mildenberger
2a11fb485d Fix underflow when repeating a completion that has a negative shift position (#7322) 2023-06-13 01:37:47 +09:00
Michael Davis
25ad534d64 Check for 'git' before fetching/building grammars (#7320)
Previously the error message for this potential failure-case was
confusing: "no such file or directory". `hx -g fetch`, `hx -g build` and
the helix-term builder should bail early if the git binary is not
available.
2023-06-12 17:32:36 +02:00
Selwyn
18e07addfd Use Vue language server based on Volar (#7312) 2023-06-12 00:46:47 +09:00
0xHiro / ヒロ
8c6eb88c6a fix: add file argument in help text (#7307) 2023-06-10 18:40:39 +02:00
lefp
a197ce869a Add Fortran comment injections (#7305) 2023-06-11 00:27:46 +09:00
Vitalii Solodilov
a981a2525d Support core mode for delve debugger (#7300) 2023-06-10 02:31:02 +02:00
Luca Schlecker
dbd248fdfa add config option for instant completion entry preview (defaulting to true).
Signed-off-by: Luca Schlecker <luca.schlecker@hotmail.com>
2023-06-09 13:23:29 -04:00
spectre256
00b152facd Add register statusline element (#7222) 2023-06-08 14:34:07 -05:00
Alex
993c68ad6f Auto indent on insert_at_line_start (#5837) 2023-06-08 19:11:40 +02:00
Tshepang Mbambo
e2a1678436 Fix book configuration for edit template (#7278) 2023-06-08 17:12:36 +09:00
Michael Davis
b0129b552d Fix style overwriting in table rows with multiple cells (#7281) 2023-06-08 13:28:26 +09:00
Tshepang Mbambo
27891cdc8d misc doc fixes/improvements (#7282) 2023-06-08 13:27:58 +09:00
Michael Davis
d4427125eb Bail if no language servers support workspace symbols (#7286) 2023-06-08 09:48:11 +09:00
Dimitri Sabadie
31b8b728a2 Fix C++ queries and update tree-sitter-cpp (#7285) 2023-06-07 18:13:39 -05:00
broke
ef5bcd5060 theme: added gruvbox dark soft variant (#7139) 2023-06-07 18:13:08 -05:00
Christoph Sax
d324feb072 Add support for language t32 (#7140)
Co-authored-by: Christoph Sax <christoph.sax@mailbox.org>
2023-06-07 18:01:25 -05:00
vwkd
352d1574a6 add move_prev_long_word_end and extend_prev_long_word_end (#6905) 2023-06-08 00:41:35 +02:00
Tshepang Mbambo
2f9b63999f Break long sentence in book configuration footnote (#7279) 2023-06-07 23:19:55 +02:00
Michael Davis
b3949979ae Propagate the count and register to command palette commands
Previously a count or register selection would be lost while opening
the command palette. This change allows using a register selection or
count in any command chosen from the command palette.
2023-06-08 00:48:25 +09:00
Michael Davis
0e083497a5 Persist register selection in pending keymaps
Previously the register selection (via `"`) would be lost in the middle
of any key sequence longer than one key. For example, `<space>f` would
clear the register selection after the `<space>` making it inaccessible
for the `file_picker` command.

This behavior does not currently have any effect in the default keymap
but might affect custom keymaps. This change aligns the behavior of the
register with count. Making this change allows propagating the register
to the `command_palette` (see the child commit) or other pickers should
we decide to use registers in those in the future. (Interactive global
search for example.)
2023-06-08 00:48:25 +09:00
Ilya Sovtsov
77e9a22aff Add check for a non-zero value for tab width (#7178) 2023-06-07 17:51:29 +09:00
Alex Vinyals
204bac1706 commands(toggle): use pattern matching on the Value enum (#7240) 2023-06-07 17:50:16 +09:00
blt__
ba691f4fb0 Fix verilog grammar source repo and revision (#7262) 2023-06-07 17:49:52 +09:00
Jens Getreu
3e927ac578 Autumn theme: style "soft-wrap indicator" + maintenance (#7229)
Co-authored-by: Jens Getreu <getreu@getreu@web.de>
2023-06-07 17:49:39 +09:00
gibbz00
9926c2d292 Remove Keymap(KeyTrie) and simply use KeyTrie. 2023-06-07 10:11:13 +09:00
gibbz00
b8563685ec Move keymap.reverse_keymap() to Keytrie:
The plan is let `Keymaps` simply store `KeyTrie`s, as the `Keymap(Keytrie)` wrapping serves little to no purpose.
2023-06-07 10:11:13 +09:00
gibbz00
eda4c79f2f Remove pub keymap.name();
`keymap.name` is only used internally.
2023-06-07 10:11:13 +09:00
gibbz00
3d0bc72099 Place Info::from_keymap() contents in keymap.infobox():
This makes it easier later control the order in which the key events
are presented.
2023-06-07 10:11:13 +09:00
gibbz00
19326d23d1 Keymap infobox: Idiomatic body tuple.
Does not change any behavior other than making the tuple slightly
more idiomatic.  Keymap infobox shows key events, then the respective
description. This commit makes sure that order is used from the get go,
rather than flipping it midway.
2023-06-07 10:11:13 +09:00
gibbz00
3a0892f793 Exclude config no_op bindings in command palette. 2023-06-07 10:11:13 +09:00
gibbz00
39773e48d3 Remove superfluous command description pruning for keymap infobox:
Exist under the wrong (possibly just outdated) assumption that command
descriptions are written with their `KeyTrie` name prefixed
2023-06-07 10:11:13 +09:00
gibbz00
d20c1632a7 helix_term::keymap: Remove one-liner solely used for a test. 2023-06-07 10:11:13 +09:00
gibbz00
f7df53c948 Make Keymap a tuple struct. 2023-06-07 10:11:13 +09:00
gibbz00
daea97a89f keymap: Rename KeyTrie::Leaf -> KeyTrie::MapppableCommand
The variant Sequence is technically also a leaf.
2023-06-07 10:11:13 +09:00
gibbz00
a56af221d7 keymap: Derive Default for KeyTrieNode 2023-06-07 10:11:13 +09:00
Alexander Brevig
78e8695420 Add support for Forth (#7256) 2023-06-06 08:14:34 -05:00
Tobias Clasen
71688a387b Recognize 'make' file-type as Makefile (#7212) 2023-06-06 08:13:27 -05:00
dependabot[bot]
9f5b965627 build(deps): bump regex from 1.8.3 to 1.8.4 (#7249)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-06 12:26:44 +09:00
dependabot[bot]
6deb0e4ef7 build(deps): bump once_cell from 1.17.2 to 1.18.0 (#7248)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-06 11:14:36 +09:00
dependabot[bot]
a56222cd0e build(deps): bump url from 2.3.1 to 2.4.0 (#7247)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-06 11:14:22 +09:00
dependabot[bot]
a8c99fb24c build(deps): bump hashbrown from 0.13.2 to 0.14.0 (#7246)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-06 11:14:05 +09:00
dependabot[bot]
1d114ecb6e build(deps): bump chrono from 0.4.25 to 0.4.26 (#7245)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-06 11:13:43 +09:00
dependabot[bot]
cd01dc886a build(deps): bump libc from 0.2.144 to 0.2.145 (#7244)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-06 11:13:28 +09:00
Alex Vinyals
a2b8cfdb8c feat(core): add plaintext matching fallback to tree-sitter matching (#4288) 2023-06-05 23:13:00 +09:00
Michael Davis
428d33ab50 Exit gracefully on termination signals (#7236) 2023-06-05 22:27:57 +09:00
Alex Vinyals
d5707a4696 feat(commands): allows cycling option values at runtime (#4411) 2023-06-05 22:22:05 +09:00
Ivan Tkachuk
2022e6175b Add blueprint language (#7213)
* Add blueprint tree-sitter support

* Add blueprint lsp support

* Run cargo xtask docgen
2023-06-05 10:40:14 +02:00
Rich Seymour
751da01303 Update install.md instructions regarding symlinks (#7231)
* Update install.md

Fixes `ln` command line bug that could hit users moving from packaged to source builds.

* Remove extra 'how to' command example
2023-06-05 02:06:25 +02:00
avaunit02
232d9f96a0 Fix textobject keybindings in usage docs (#7197) 2023-06-04 17:20:54 +02:00
Pascal Kuthe
de0ef8af15 fix UB in diff gutter (#7227) 2023-06-04 17:20:04 +02:00
Zisulin Morbrot
d511122279 Add description for 'ui.text.focus' in theme docs (#7177) 2023-05-31 06:57:17 +08:00
zetashift
92380540b8 chore: update scala tree-sitter grammar (#7147)
* chore: update scala tree-sitter grammar

* Add locals.scm for Scala
2023-05-30 13:29:43 +02:00
dependabot[bot]
a726799a4e build(deps): bump log from 0.4.17 to 0.4.18 (#7175)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-30 09:52:41 +09:00
dependabot[bot]
8bd841136a build(deps): bump once_cell from 1.17.1 to 1.17.2 (#7174)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-30 09:52:18 +09:00
dependabot[bot]
825e7c4976 build(deps): bump tokio from 1.28.1 to 1.28.2 (#7173)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-30 09:52:10 +09:00
dependabot[bot]
f694c24ac8 build(deps): bump regex from 1.8.2 to 1.8.3 (#7172)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-30 09:51:27 +09:00
dependabot[bot]
d62fb8c8d7 build(deps): bump chrono from 0.4.24 to 0.4.25 (#7171)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-30 09:51:13 +09:00
dependabot[bot]
a367a713ef build(deps): bump cachix/install-nix-action from 20 to 21 (#7170)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-30 09:49:45 +09:00
Ethan Wilkes
3334e7e4b2 fixed repeat_last_motion extends selection (#7159) 2023-05-29 00:51:22 +09:00
yvt
3a8592abdb feat(languages): recognise .gir as XML (#7152) 2023-05-27 09:01:50 -05:00
Jimmy Zelinskie
b107814e39 languages: add .zimrc to bash filetypes (#7146) 2023-05-27 00:55:25 +02:00
Gammut
86ef389c0d Highlight query improvements for java and typescript (#7145)
* Add missing queries to java highlights

* Fix generic type bracket highlights in typescript
2023-05-26 23:37:19 +02:00
Martin Weinelt
61a89956e3 book: Mention Helix package in nixpkgs (#7064) 2023-05-26 04:33:20 -05:00
Ravi Shekhar Jethani
6e647e83ed Update spacebones_light.toml (#7125)
Better contrast between type variable and its members
2023-05-26 10:47:03 +02:00
Casper Rogild Storm
1dd1735909 Correct selection color (#7138) 2023-05-26 10:46:07 +02:00
Ikko Eltociear Ashimine
349e2b5f0e Fix typo in syntax.rs (#7114)
seperator -> separator
2023-05-26 10:45:15 +02:00
William Etheredge
a2e11af608 Support hidden justfiles (#7088) 2023-05-26 10:43:48 +02:00
Brandon Sprague
16375cd94a Treat 'Vagrantfile' files as Ruby code (#7112)
`Vagrantfile`s are configuration files for the [vagrant](https://www.vagrantup.com/) tool, and they are written in Ruby. Even as vagrant [is ported to Go](https://www.hashicorp.com/blog/toward-vagrant-3-0), `Vagrantfile`s [will be written in Ruby](https://developer.hashicorp.com/vagrant/docs/experimental/vagrant_go)

When a Vangrantfile is created, it starts with these lines:

```
```

But since Helix (quite reasonably) doesn't change editor behavior based on file contents, adding this to `languages.toml` seems like a reasonable way to get this functionality.
2023-05-26 10:43:15 +02:00
Viktor Kleen
0c21c227e1 Update languages.toml for Nickel (#7059) 2023-05-26 02:23:15 -05:00
Blaž Hrastnik
0266ec6ba3 Update language support doc 2023-05-26 13:43:41 +09:00
Blaž Hrastnik
591629ec11 fix compilation 2023-05-26 13:35:03 +09:00
Blaž Hrastnik
c6d1430243 Drop old cairo grammar, alias to rust for now 2023-05-26 11:17:30 +09:00
Matthew Toohey
207829eefe Fix off-by-one in select symbol references (#7132) 2023-05-25 14:01:56 +02:00
Poliorcetics
8e2660b5cc Update diagnostics correctly on LSP exit (#7111)
* chore: avoid format! call with argument when useless

* feat: also clear diagnostics for unopened documents when exiting an LSP

* feat: we already worked on `self.editor.diagnostics` no need to redo the checks
2023-05-23 12:33:01 +02:00
dependabot[bot]
6043c3c3db build(deps): bump bitflags from 2.2.1 to 2.3.1 (#7117)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-23 14:19:50 +09:00
dependabot[bot]
a66e287654 build(deps): bump toml from 0.7.3 to 0.7.4 (#7120)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-23 14:19:07 +09:00
dependabot[bot]
16275db817 build(deps): bump regex from 1.8.1 to 1.8.2 (#7119)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-23 14:18:51 +09:00
dependabot[bot]
d765132426 build(deps): bump pulldown-cmark from 0.9.2 to 0.9.3 (#7118)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-23 14:18:38 +09:00
yvt
16e0340b4a feat(languages): recognise Cargo.lock as TOML 2023-05-21 22:51:33 -04:00
Chris
d3cca0f357 Recognise XAML files as XML (#7083) 2023-05-20 02:38:55 +02:00
LeoniePhiline
41f52d74fe fix(docs): Remove config from language configuration docs (#7082) 2023-05-19 19:27:21 -05:00
Szabin
70e4cdbd8e Add command to merge non-consecutive ranges (#7053)
* 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`
2023-05-20 01:31:39 +02:00
Charles Hall
e4a9bec562 fix off-by-one git-commit rulers (#7072)
Characters should maximally reside *inside* the ruler, not on top of it.
2023-05-20 01:29:06 +02:00
Yt
ff442eecd0 nix: add overlay for convenient package usage (#7078) 2023-05-19 22:21:05 +09:00
Blaž Hrastnik
53f47bc477 Merge pull request #2507 from Philipp-M/multiple-language-servers
Add support for multiple language servers per language
2023-05-19 09:39:35 +09:00
Philipp Mildenberger
2a512f7c48 Rebase cleanup/fixes and use lsp::CompletionItem in item_to_transaction directly 2023-05-18 22:25:32 +02:00
Philipp Mildenberger
f8fa0d8a10 Clarify language-servers documentation for mergeable LSP features (diagnostics, code-action, completion, document-symbols and workspace-symbols) 2023-05-18 22:11:38 +02:00
Philipp Mildenberger
b6d0e26814 Sort language servers table in languages.toml and rename language server 'R' to 'r' 2023-05-18 22:11:37 +02:00
Philipp Mildenberger
f45bbf165e Apply all review suggestions (doc_id -> id, error message, unnecessary if)
Co-authored-by: Pascal Kuthe <pascal.kuthe@semimod.de>
2023-05-18 22:04:49 +02:00
Philipp Mildenberger
656ee24966 Simplify gutter diagnostics rendering by using partition_point instead of binary search
Co-authored-by: Pascal Kuthe <pascal.kuthe@semimod.de>
2023-05-18 22:04:49 +02:00
Philipp Mildenberger
2b746ea6fa Some minor clarity/cosmetic improvements
Co-authored-by: Pascal Kuthe <pascal.kuthe@semimod.de>
2023-05-18 22:04:49 +02:00
Philipp Mildenberger
39b9a4bba2 Add function Editor::language_server_by_id and refactor/simplify related code, also don't 'crash' in completion menu if language_server somehow disappeared 2023-05-18 22:04:47 +02:00
Philipp Mildenberger
521cdec5a1 Remove TODO comment in helix_lsp::Registry::restart and add doc-comment on top of function instead 2023-05-18 21:58:17 +02:00
Philipp Mildenberger
dcb07673f8 Reorder id generation for Clients to stay close to the old behavior 2023-05-18 21:58:17 +02:00
Philipp Mildenberger
56748509bd Reduce boilerplate by 'use lsp::*' in Client::supports_feature, and remove TODO comment 2023-05-18 21:58:17 +02:00
Philipp Mildenberger
3e4bac1d96 Fix lsp_restart across multiple different document scopes (language servers weren't restarted, if not of the same scope id), and fix some smaller rebase issues 2023-05-18 21:58:17 +02:00
Philipp Mildenberger
2a21b939c4 Fix crash with filtered diagnostics in gutter (e.g. when diagnostics aren't visible) 2023-05-18 21:58:17 +02:00
Philipp Mildenberger
93fd79a949 Remove offset_encoding in CodeActionOrCommandItem, as it can be retrieved on demand 2023-05-18 21:58:17 +02:00
Philipp Mildenberger
073000e54d Maintain language servers TOML array order in doc.language_servers 2023-05-18 21:58:17 +02:00
Philipp Mildenberger
ff26208427 Filter language servers also by capabilities in doc.language_servers_with_feature
* 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`
2023-05-18 21:58:17 +02:00
Philipp Mildenberger
9d089c27c7 Fix docgen again 2023-05-18 21:58:17 +02:00
Philipp Mildenberger
451fe528bb Filter out already seen language servers in requests that can be sent to multiple language servers (code-action, completion, symbol pickers) 2023-05-18 21:58:17 +02:00
Philipp Mildenberger
8ee599942a Optimize gutter diagnostics and simplify shown_diagnostics 2023-05-18 21:58:17 +02:00
Philipp Mildenberger
8ab6d7be5e Use let else instead of variable and fix some error messages
Co-authored-by: Pascal Kuthe <pascal.kuthe@semimod.de>
2023-05-18 21:58:17 +02:00
Philipp Mildenberger
1d5d5dab47 Remove offset_encoding in CompletionItem 2023-05-18 21:58:15 +02:00
Philipp Mildenberger
2eeac10755 Refactor doc language servers to a HashMap, and the config to use a Vec to retain order 2023-05-18 21:48:32 +02:00
Philipp Mildenberger
b1199c552b Remove symbol picker is_empty check 2023-05-18 21:48:32 +02:00
Philipp Mildenberger
58c913ce45 Simplify 'lsp_stop' command 2023-05-18 21:48:32 +02:00
Philipp Mildenberger
7d20740b5b Fix docgen and lsp-stop documentation 2023-05-18 21:48:32 +02:00
Philipp Mildenberger
60a6af1fea Remove boilerplate in the goto methods by generically composing functions 2023-05-18 21:48:32 +02:00
Philipp Mildenberger
d963050621 Format/fix language docs a bit 2023-05-18 21:48:32 +02:00
Philipp Mildenberger
9639f42766 Refactor doc.shown_diagnostics to avoid an extra HashSet
Co-authored-by: Pascal Kuthe <pascal.kuthe@semimod.de>
2023-05-18 21:48:32 +02:00
Philipp Mildenberger
1122928c2a Add method doc.supports_language_server for better readability 2023-05-18 21:48:32 +02:00
Philipp Mildenberger
ec2f9091a0 Simplify Display implementation for LanguageServerFeature 2023-05-18 21:48:32 +02:00
Philipp Mildenberger
76b5cab524 Refactored doc.language_servers and doc.language_servers_with_feature to return an iterator and refactor LanguageServerFeature handling to a HashMap (language server name maps to features)
Co-authored-by: Pascal Kuthe <pascal.kuthe@semimod.de>
2023-05-18 21:48:32 +02:00
Philipp Mildenberger
0637691eb1 Use DoubleEndedIterator instead of collect to Vec for reversing
Co-authored-by: Pascal Kuthe <pascal.kuthe@semimod.de>
2023-05-18 21:48:32 +02:00
Philipp Mildenberger
dd2f74794a Fix error messages when no language server is available
Co-authored-by: Skyler Hawthorne <skyler@dead10ck.com>
2023-05-18 21:48:32 +02:00
Philipp Mildenberger
19f88fc577 Simplify Display implementation of LanguageServerFeature
Co-authored-by: Ivan Tham <pickfire@riseup.net>
2023-05-18 21:48:32 +02:00
Philipp Mildenberger
f9b08656f4 Fix sorting issues of the editor wide diagnostics and apply diagnostics related review suggestions
Co-authored-by: Pascal Kuthe <pascal.kuthe@semimod.de>
2023-05-18 21:48:32 +02:00
Philipp Mildenberger
4da6d8ccc7 str instead of String 2023-05-18 21:48:32 +02:00
Philipp Mildenberger
b6c60beb2d Remove unnecessary completion support check (likely an artifact) 2023-05-18 21:48:32 +02:00
Philipp Mildenberger
44b2b40190 Fix issue with ltex-ls, filtering params is not what we want here 2023-05-18 21:48:32 +02:00
Philipp Mildenberger
05583f8cc9 Fix hardcoded offset_encoding 2023-05-18 21:48:32 +02:00
Philipp Mildenberger
74e21e1b25 Fix some lints/docgen hints 2023-05-18 21:48:32 +02:00
Philipp Mildenberger
7d4f7eb4bd Fix 'WorkspaceConfiguration' request with empty configuration section strings 2023-05-18 21:48:32 +02:00
Philipp Mildenberger
71551d395b Adds support for multiple language servers per language.
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.
2023-05-18 21:48:30 +02:00
Michael Davis
7f5940be80 Add 23.05 to the AppData 2023-05-18 16:01:26 +09:00
Michael Davis
59f8f5e6d4 Add changelog notes for the 23.05 release 2023-05-18 16:01:26 +09:00
Michael Davis
04fbf30488 Bump the version to 23.05 2023-05-18 16:01:26 +09:00
Ivan Gulakov
2cccb3f09c Fix completion on paths containing spaces (#6779)
There was an issue with autocompletion of a path with a space in it.

Before:

:o test\ dir -> <TAB> -> test\ dirfile1

After:

:o test\ dir -> <TAB> -> test\ dir\file1
2023-05-18 15:27:29 +09:00
Pascal Kuthe
b0705337be automatically disable TS when parsing takes longer than 500ms 2023-05-18 15:23:37 +09:00
Pascal Kuthe
2f2306475c async picker syntax highlighting 2023-05-18 15:23:37 +09:00
Pascal Kuthe
c6f169b1f8 cleanup integration tests 2023-05-18 15:20:55 +09:00
Pascal Kuthe
25d4ebe30d don't move cursor while forward deleting in append mode
Currently, when forward deleting (`delete_char_forward` bound to `del`,
`delete_word_forward`, `kill_to_line_end`) the cursor is moved to the
left in append mode (or generally when the cursor is at the end of the
selection). For example in a document `|abc|def`  (|indicates selection)
if enter append mode the cursor is moved to `c` and the selection
becomes: `|abcd|ef`. When deleting forward (`del`) `d` is deleted. The
expectation would be that the selection doesn't shrink so that `del`
again deletes `e` and then `f`. This would look as follows:

`|abcd|ef`
`|abce|f`
`|abcf|`
`|abc |`

This is inline with how other editors like kakoune work.
However, helix currently moves the selection backwards leading to the
following behavior:

`|abcd|ef`
`|abc|ef`
`|ab|ef`
`ef`

This means that `delete_char_forward` essentially acts like
`delete_char_backward` after deleting the first character in append
mode.

To fix the problem the cursor must be moved to the right while deleting
forward (first fix in this commit). Furthermore, when the EOF char is
reached a newline char must be inserted (just like when entering
appendmode) to prevent the cursor from moving to the right
2023-05-18 15:20:55 +09:00
Pascal Kuthe
2c3ccc3e8b cleanup delete_by_selection_insert_mode function 2023-05-18 15:20:55 +09:00
Pascal Kuthe
f8225ed921 fix panic when deleting overlapping ranges
Some deletion operations (especially those that use indentation)
can generate overlapping deletion ranges when using multiple cursors.
To fix that problem a new `Transaction::delete` and
`Transaction:delete_by_selection` function were added. These functions
merge overlapping deletion ranges instead of generating an invalid
transaction. This merging of changes is only possible for deletions
and not for other changes and therefore require its own function.

The function has been used in all commands that currently delete
text by using `Transaction::change_by_selection`.
2023-05-18 15:20:55 +09:00
Pascal Kuthe
6842fd4c36 clarify comments about completion savepoints
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2023-05-18 15:16:50 +09:00
Pascal Kuthe
28b730381c only resolve completion items once 2023-05-18 15:16:50 +09:00
Pascal Kuthe
bcb8c3d34d deduplicate savepoints 2023-05-18 15:16:50 +09:00
Pascal Kuthe
9c558fc470 ensure correct trigger/start completion offset
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
2023-05-18 15:16:50 +09:00
Pascal Kuthe
30ff7f8db2 resolve completions before applying transactions 2023-05-18 15:16:50 +09:00
Pascal Kuthe
5406e9f629 correctly handle completion rerequest 2023-05-18 15:16:50 +09:00
Jan Scheer
91da0dc172 Update nightfox theme (#7061)
* theme: nightfox - fix subselection highlighting

This fixes an issue with subselect highlighting on the same line as
reported here: https://github.com/helix-editor/helix/discussions/5158

* theme: nightfox - update bufferline colors

This uses `ui.bufferline` to make it easier to distinguish
between (in-)active tabs/buffers.
2023-05-18 03:16:25 +02:00
gibbz00
6f135e58a3 languages.toml: recognize gml files. (#7055) 2023-05-16 13:02:22 +09:00
gibbz00
e9efcebdb0 languages.toml: recognize geojson files. (#7054) 2023-05-16 13:01:27 +09:00
dependabot[bot]
4b9dba8217 build(deps): bump serde from 1.0.162 to 1.0.163 (#7056)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.162 to 1.0.163.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.162...v1.0.163)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-16 10:26:16 +09:00
dependabot[bot]
b50032ee85 build(deps): bump tokio from 1.28.0 to 1.28.1 (#7057)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.28.0 to 1.28.1.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.28.0...tokio-1.28.1)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-16 10:26:05 +09:00
A-Walrus
d5fe08ddb8 Replace DAP vars popup, instead of adding new (#7034) 2023-05-13 10:44:25 -05:00
lefp
06d7f5d100 Add comment injections for Odin (#7027) 2023-05-12 16:53:07 +02:00
Vitalii Solodilov
5938e2c0dc fix: update upstream tree-sitter-dockerfile (#6895)
* fix: update upstream tree-sitter-dockerfile

Fixes: #6797

* fix: review

* fix: review
2023-05-12 03:29:06 +02:00
ZJPzjp
3b8c15618f Fix warnings from clippy (#7013)
* Fix warnings from clippy

* revert MAIN_SEPARATOR_STR
2023-05-11 14:44:52 +09:00
Blaž Hrastnik
1e5997dc98 nix: Update flake dependencies 2023-05-11 11:30:46 +09:00
John Kelly
87da58578f Add better error message for file save failure due to parent not existing (#7014)
Fixes #5229
2023-05-11 04:35:43 +09:00
Kitsu
92c328c088 Add wbc and wbc! commands (#6947) 2023-05-09 22:21:29 +02:00
Ollie Charles
8424f387b5 Remove tree-sitter-cabal (#6996) 2023-05-09 21:31:22 +02:00
David Else
69332ae3b2 Add Flathub as third party repository (#6994) 2023-05-09 15:38:36 +02:00
dependabot[bot]
7089bc20f0 build(deps): bump serde from 1.0.160 to 1.0.162 (#7002)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.160 to 1.0.162.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.160...1.0.162)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-09 09:30:35 +09:00
dependabot[bot]
9cca80bd53 build(deps): bump libc from 0.2.142 to 0.2.144 (#7000)
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.142 to 0.2.144.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.142...0.2.144)

---
updated-dependencies:
- dependency-name: libc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-09 09:30:11 +09:00
dependabot[bot]
301d45b34b build(deps): bump termini from 0.1.4 to 1.0.0 (#7001)
Bumps [termini](https://github.com/pascalkuthe/termini) from 0.1.4 to 1.0.0.
- [Release notes](https://github.com/pascalkuthe/termini/releases)
- [Commits](https://github.com/pascalkuthe/termini/compare/v0.1.4...v1.0.0)

---
updated-dependencies:
- dependency-name: termini
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-09 09:29:43 +09:00
Chirikumbrah
3fb0562e7b Update dracula menu colors (#6987) 2023-05-08 19:12:15 +02:00
Andrius Pukšta
3a9e77934b Treat .sty and .cls files as latex (#6986) 2023-05-08 19:11:23 +02:00
Dave Powers
5ae30f1993 Fix keymap select / extend mode anchor link (#6974) 2023-05-05 09:43:56 -05:00
Diego Pontoriero
fc1e9a6ff9 languages: add build.gradle.kts to java and scala roots (#6970)
Gradle scripts written in kotlin use a .kts extension:

https://docs.gradle.org/current/userguide/kotlin_dsl.html#sec:scripts
2023-05-05 10:02:19 +09:00
Gagan Janjua
c6228825fd Add Amberwood theme (#6924) 2023-05-03 10:22:54 -05:00
taupiqueur
c49faf5681 Add language server command for Crystal (#6948) 2023-05-03 09:43:37 +09:00
dependabot[bot]
d1a4bd876b build(deps): bump tokio from 1.27.0 to 1.28.0 (#6935)
Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.27.0 to 1.28.0.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.27.0...tokio-1.28.0)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-02 10:17:59 +09:00
dependabot[bot]
7ea5965bd5 build(deps): bump tokio-stream from 0.1.12 to 0.1.14 (#6934)
Bumps [tokio-stream](https://github.com/tokio-rs/tokio) from 0.1.12 to 0.1.14.
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Changelog](https://github.com/tokio-rs/tokio/blob/tokio-0.1.14/CHANGELOG.md)
- [Commits](https://github.com/tokio-rs/tokio/compare/tokio-stream-0.1.12...tokio-0.1.14)

---
updated-dependencies:
- dependency-name: tokio-stream
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-02 09:59:05 +09:00
dependabot[bot]
d3e535b697 build(deps): bump gix from 0.44.0 to 0.44.1 (#6933)
Bumps [gix](https://github.com/Byron/gitoxide) from 0.44.0 to 0.44.1.
- [Release notes](https://github.com/Byron/gitoxide/releases)
- [Changelog](https://github.com/Byron/gitoxide/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Byron/gitoxide/compare/gix-v0.44.0...gix-v0.44.1)

---
updated-dependencies:
- dependency-name: gix
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-02 09:58:06 +09:00
dependabot[bot]
d9a7bd3bc1 build(deps): bump anyhow from 1.0.70 to 1.0.71 (#6932)
Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.70 to 1.0.71.
- [Release notes](https://github.com/dtolnay/anyhow/releases)
- [Commits](https://github.com/dtolnay/anyhow/compare/1.0.70...1.0.71)

---
updated-dependencies:
- dependency-name: anyhow
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-02 09:57:53 +09:00
dependabot[bot]
1b3923374a build(deps): bump etcetera from 0.7.1 to 0.8.0 (#6931)
Bumps [etcetera](https://github.com/lunacookies/etcetera) from 0.7.1 to 0.8.0.
- [Release notes](https://github.com/lunacookies/etcetera/releases)
- [Commits](https://github.com/lunacookies/etcetera/compare/v0.7.1...v0.8.0)

---
updated-dependencies:
- dependency-name: etcetera
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-02 09:57:45 +09:00
Chirikumbrah
2701781db7 Dracula theme: change variable and menu colors (#6855) 2023-05-01 23:51:35 +02:00
Scott Stevenson
015623720c Recognise Jupyter notebooks as JSON documents (#6927) 2023-05-01 16:21:30 +02:00
Scott Stevenson
d7878238c1 Recognise poetry.lock as TOML (#6928) 2023-05-01 16:21:10 +02:00
Pascal Kuthe
75f62bc86f fix didChange notifaction offset encoding 2023-04-30 20:26:40 -04:00
Alexis-Lapierre
b0b3f45b80 Conserve BOM and properly support UTF16 (#6497) 2023-05-01 00:40:06 +02:00
Rafael Madriz
efd09b6c7c tutor: Delete space between shorthand (#6920) 2023-04-30 23:35:34 +02:00
Rafael Madriz
5dcc891996 tutor: Trim trailing white space (#6919) 2023-04-30 14:26:38 -05:00
sscheele
f52e81b1f3 Update docs for move_visual_line_* (#6918) 2023-04-30 14:26:18 -05:00
Pascal Kuthe
77da0ae8ce downgrade gix log level to info (#6915) 2023-04-30 23:20:13 +09:00
0rphee
f2ccc03332 [Theme - noctis] Change color for whitespace rendering and indent guides 2023-04-30 09:44:26 +09:00
0rphee
96720e7b84 [Theme - noctis] Refine multiple cursor highlighting
Improve clarity when using multiple cursors
2023-04-30 09:44:26 +09:00
Evgeniy Tatarkin
6a1bb81f10 Sort the buffer picker by most recent access (#2980) 2023-04-28 11:05:14 -05:00
Timothy DeHerrera
9c6c63a2be inject language based on file extension & shebang (#3970)
* inject language based on file extension

Nodes can now be captured with "injection.filename". If this capture
contains a valid file extension known to Helix, then the content will
be highlighted as that language.

* inject language by shebang

Nodes can now be captured with "injection.shebang". If this capture
contains a valid shebang line known to Helix, then the content will
be highlighted as the language the shebang calls for.

* add documentation for language injection

* nix: fix highlights

The `@` is now highlighted properly on either side of the function arg.

Also, extending the phases with `buildPhase = prev.buildPhase + ''''`
is now highlighted properly.

Fix highlighting of `''$` style escapes (requires tree-sitter-nix bump)

Fix `inherit` highlighting.

* simplify injection_for_match

Split out injection pair logic into its own method to make the overall
flow easier to follow.

Also transform the top-level function into a method on a
HighlightConfiguration.

* markdown: add shebang injection query
2023-04-28 18:21:34 +09:00
jorge
204d1eba4b feat(commands): add clear-register typable command (#5695)
Co-authored-by: Jorge <chorcheus@tutanota.com>
2023-04-27 21:57:05 +02:00
ap29600
9cdc6b2e8a Change Odin grammar to ap29600/tree-sitter-odin (#6766)
* Change Odin grammar to `ap29600/tree-sitter-odin`

The previously adopted grammar, `MineBill/tree-sitter-odin`, is unmaintained and mentions my repository as an alternative source.

* update queries

* docgen

* fix queries

* Update runtime/queries/odin/highlights.scm

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

* remove `ERROR` query for `odin`

* track the latest rev in `ap29600/tree-sitter-odin`

* runtime/queries/odin/highlights.scm: update rune highlight class

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>

---------

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2023-04-27 16:32:21 +02:00
Vitalii Solodilov
2836ea2ac4 feat: add a config option to exclude declaration from LSP references (#6886)
* feat: added the config option to exclude declaration from reference query

Fixes: #5344

* fix: review

* fix: review
2023-04-27 16:30:15 +02:00
Sebastian Thiel
222be0f1e7 upgrade gitoxide to v0.44 and change repository discovery to worktree-only (#6867) (#6890) 2023-04-27 14:38:07 +09:00
Cole Helbling
6dd5054da4 Highlight sqlx's query_scalar{,_unchecked} macros as SQL (#6793)
* Highlight sqlx's `query_scalar{,_unchecked}` macros as SQL

* Update injections.scm

* fixup copy-pasta
2023-04-27 14:37:17 +09:00
Pascal Kuthe
8f1671eaaa fix panic in inlay hint computation when view anchor is out of bounds (#6883) 2023-04-27 09:38:20 +09:00
Wesley
903bdaae87 Set PerlNavigator as the language server for Perl (#6860) 2023-04-27 01:28:54 +02:00
Daniel Martí
488707c7c8 add go.work and remove Gopkg.toml as Go roots (#6884)
Gopkg.toml was used by dep, Go's original dependency management tool.
It was an experiment that culminated in official and built-in support
for Go modules in mid 2018, and dep was deprecated and archived
in mid 2020 per https://github.com/golang/go/issues/38158.

Now, in 2023, Gopkg.toml files are incredibly rare in actively developed
Go projects, as people use go.mod with Go modules instead.

While here, also add go.work as a root file, since that is used by
Go module workspaces, added in Go 1.18 in early 2022.
gopls or commands like `go build` work inside either go.work or go.mod.
These two root files are the same ones used by gopls integrations with
other editors like vim or neovim.
2023-04-26 22:51:04 +09:00
Timothy DeHerrera
080f85c34f fix(nix): fix superflous / that breaks the build (#6880)
Resolves #1779
2023-04-26 10:15:16 +09:00
Daniel Martí
e7f25d88ca Avoid extra indentation on Go switches (#6817)
Unlike other languages, in Go, switches themselves are not indented;
it's just each case body which is indented by one level:

   switch foo {
   case "bar":
      baz()
   }

As such, we shouldn't `@indent` for type_switch_statement nor
expression_switch_statement, as otherwise inserted lines show up as:

   switch foo {
      // inserted with "o"
   case "bar":
         // inserted with "o"
      baz()
   }

With the fix, the inserted lines are indented properly:

   switch foo {
   // inserted with "o"
   case "bar":
      // inserted with "o"
      baz()
   }

I also verified that indentation on selects similarly works well.

Thanks to Triton171 for helping with this fix.
2023-04-25 18:05:23 -05:00
Dimitri Sabadie
096ed0ced4 Add extend_to_first_nonwhitespace (#6837)
Closes #6836
2023-04-25 19:14:06 +02:00
dependabot[bot]
0097e191bb build(deps): bump etcetera from 0.5.0 to 0.7.1 (#6873)
Bumps [etcetera](https://github.com/lunacookies/etcetera) from 0.5.0 to 0.7.1.
- [Release notes](https://github.com/lunacookies/etcetera/releases)
- [Commits](https://github.com/lunacookies/etcetera/compare/v0.5.0...v0.7.1)

---
updated-dependencies:
- dependency-name: etcetera
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-25 11:52:17 +09:00
dependabot[bot]
d45af96fc4 build(deps): bump libc from 0.2.141 to 0.2.142 (#6872)
Bumps [libc](https://github.com/rust-lang/libc) from 0.2.141 to 0.2.142.
- [Release notes](https://github.com/rust-lang/libc/releases)
- [Commits](https://github.com/rust-lang/libc/compare/0.2.141...0.2.142)

---
updated-dependencies:
- dependency-name: libc
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-25 11:51:43 +09:00
dependabot[bot]
f47f8d538d build(deps): bump regex from 1.7.3 to 1.8.1 (#6871)
Bumps [regex](https://github.com/rust-lang/regex) from 1.7.3 to 1.8.1.
- [Release notes](https://github.com/rust-lang/regex/releases)
- [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rust-lang/regex/compare/1.7.3...1.8.1)

---
updated-dependencies:
- dependency-name: regex
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-25 11:51:35 +09:00
dependabot[bot]
11e3fdd153 build(deps): bump dunce from 1.0.3 to 1.0.4 (#6870)
Bumps [dunce](https://gitlab.com/kornelski/dunce) from 1.0.3 to 1.0.4.
- [Release notes](https://gitlab.com/kornelski/dunce/tags)
- [Commits](https://gitlab.com/kornelski/dunce/compare/v1.0.3...v1.0.4)

---
updated-dependencies:
- dependency-name: dunce
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-25 11:51:25 +09:00
dependabot[bot]
fd1b3dc499 build(deps): bump bitflags from 2.1.0 to 2.2.1 (#6869)
Bumps [bitflags](https://github.com/bitflags/bitflags) from 2.1.0 to 2.2.1.
- [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/2.1.0...2.2.1)

---
updated-dependencies:
- dependency-name: bitflags
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-25 11:51:12 +09:00
ymgyt
61ff2bc094 return early if soft wrap is invalid (#6856) 2023-04-23 08:24:17 -05:00
Atticus Sebastiani
228a4af35f make :u alias :update (#6835)
* Gave the command update the alias u

* Re added trailing newline

* generated docs
2023-04-23 04:07:34 +02:00
Pascal Kuthe
b7c62e200e fix windows builds (#6845) 2023-04-22 19:38:25 +09:00
Michael T. Mordowanec
a1044a6c68 Change soft-wrap.wrap_at_text_width to kebab case in documentation (#6842)
Solves #6803.
2023-04-21 16:45:50 -05:00
Michael Davis
ee7413a3fd tui: Allow toggling mouse capture at runtime (#6675)
This picks up changes to the `editor.mouse` option at runtime - either
through `:set-option` or `:config-reload`. When the value changes, we
tell the terminal to enable or disable mouse capture sequences.
2023-04-21 12:53:27 +09:00
Paul Lange
78088ac185 Ayu dark improvements (#6622)
* theme(ayu_dark): Differentiate primary cursor

* theme(ayu_dark): Color statusline mode field

* theme(ayu): Adapt other ayu themes as well
2023-04-21 12:53:04 +09:00
Chirikumbrah
2342807364 another refactoring of dracula theme (#6767) 2023-04-21 12:51:47 +09:00
Ollie Charles
5aedf11493 Replace *.cabal in Haskell roots with cabal.project (#6828)
`roots` doesn't support wildcards. As such this root is dropped, and `cabal.project` is added, which is probably the best we can do for Cabal-based projects for now.
2023-04-21 12:51:17 +09:00
Pascal Kuthe
c3e2db77f7 flip symbol range in LSP goto commands (#6794) 2023-04-21 12:50:37 +09:00
Pascal Kuthe
13cc44c65e fix windows build (#6834) 2023-04-21 12:49:27 +09:00
Pascal Kuthe
b336cd76a7 update dependencies (#6808) 2023-04-20 14:53:38 +09:00
Pascal Kuthe
f5d38cee17 produce error when grammar build fails (#6795)
* produce error when grammar build fails

* print which grammar build failed
2023-04-20 14:53:16 +09:00
David Else
83c307a66a Improve and update the installation documentation (#6809) 2023-04-20 00:56:18 +02:00
Lakshya Singh
4f03c03556 update tree-sitter-markdown (#6785)
* chore: fix bump tree-sitter-markdown

Signed-off-by: Lakshya Singh <lakshay.singh1108@gmail.com>

* chore: bump markdown_inline to latest rev

Signed-off-by: Lakshya Singh <lakshay.singh1108@gmail.com>

---------

Signed-off-by: Lakshya Singh <lakshay.singh1108@gmail.com>
2023-04-19 01:21:15 +02:00
Pascal Kuthe
ca65d312e7 always build grammars with c++14 and c11 (#6792) 2023-04-18 10:10:19 +09:00
dependabot[bot]
2ccb5b75d0 build(deps): bump libloading from 0.7.4 to 0.8.0 (#6801)
Bumps [libloading](https://github.com/nagisa/rust_libloading) from 0.7.4 to 0.8.0.
- [Release notes](https://github.com/nagisa/rust_libloading/releases)
- [Commits](https://github.com/nagisa/rust_libloading/compare/0.7.4...0.8.0)

---
updated-dependencies:
- dependency-name: libloading
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-18 10:06:08 +09:00
dependabot[bot]
6f972e5da2 build(deps): bump serde from 1.0.159 to 1.0.160 (#6800)
Bumps [serde](https://github.com/serde-rs/serde) from 1.0.159 to 1.0.160.
- [Release notes](https://github.com/serde-rs/serde/releases)
- [Commits](https://github.com/serde-rs/serde/compare/v1.0.159...v1.0.160)

---
updated-dependencies:
- dependency-name: serde
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-18 10:05:31 +09:00
dependabot[bot]
3f72792033 build(deps): bump serde_json from 1.0.95 to 1.0.96 (#6799)
Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.95 to 1.0.96.
- [Release notes](https://github.com/serde-rs/json/releases)
- [Commits](https://github.com/serde-rs/json/compare/v1.0.95...v1.0.96)

---
updated-dependencies:
- dependency-name: serde_json
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-18 10:05:03 +09:00
dependabot[bot]
a333f6fed7 build(deps): bump etcetera from 0.4.0 to 0.5.0 (#6798)
Bumps [etcetera](https://github.com/lunacookies/etcetera) from 0.4.0 to 0.5.0.
- [Release notes](https://github.com/lunacookies/etcetera/releases)
- [Commits](https://github.com/lunacookies/etcetera/commits)

---
updated-dependencies:
- dependency-name: etcetera
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-18 10:04:48 +09:00
A-Walrus
8839eb0af4 Fix unwrap bug in DAP (#6786) 2023-04-17 15:36:04 -05:00
shem
1b016a89d5 Fix crash on opening from suspend state (#6764)
* Fix crash on opening from suspend state (#6725)

* Fix code style

* revert using of the imperative code style. Add panic if couldn't set terminal raw mode

* remove redundant import of core::panic macros

* small refactoring
2023-04-16 23:07:00 +02:00
Aleksey Kuznetsov
7706ff77eb make :toggle-option print the new value (#6774)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2023-04-16 20:44:12 +02:00
karei
7607727483 Add inlay-hint colours to Kanagawa
Makes the LSP hints more legible against the background colour
and more in line with the normal colours in the theme.
2023-04-16 19:49:51 +02:00
dylrich
523e9e4573 ferra: fix ruler overriding foreground style
Ferra's current ruler styling overrides the foreground style, which is
an odd look only for characters in the ruler column. This commit removes
the foreground styling for the ruler rule. This is more in line with
what other themes do for the ruler.
2023-04-16 18:32:56 +02:00
Matthew Toohey
99a8b6159c Fix go locals query for var_spec identifiers 2023-04-16 18:32:00 +02:00
VuiMuich
4cdba7cccd Add standalone language support for just (#6453)
Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
2023-04-14 17:03:21 +02:00
Pascal Kuthe
896404c7ea emit cargo metadata duiring build scripts to avoid outdated buildscript outputs (#6743)
* rebuild on revision change
* rerun grammar build if grammars change
2023-04-14 09:59:52 -05:00
908 changed files with 69316 additions and 19683 deletions

View File

@@ -1,3 +1,17 @@
# we use tokio_unstable to enable runtime::Handle::id so we can separate
# globals from multiple parallel tests. If that function ever does get removed
# its possible to replace (with some additional overhead and effort)
# Annoyingly build.rustflags doesn't work here because it gets overwritten
# if people have their own global target.<..> config (for example to enable mold)
# specifying flags this way is more robust as they get merged
# This still gets overwritten by RUST_FLAGS though, luckily it shouldn't be necessary
# to set those most of the time. If downstream does overwrite this its not a huge
# deal since it will only break tests anyway
[target."cfg(all())"]
rustflags = ["--cfg", "tokio_unstable", "-C", "target-feature=-crt-static"]
[alias] [alias]
xtask = "run --package xtask --" xtask = "run --package xtask --"
integration-test = "test --features integration --profile integration --workspace --test integration" integration-test = "test --features integration --profile integration --workspace --test integration"

1
.envrc
View File

@@ -1,5 +1,6 @@
watch_file shell.nix watch_file shell.nix
watch_file flake.lock watch_file flake.lock
watch_file rust-toolchain.toml
# try to use flakes, if it fails use normal nix (ie. shell.nix) # try to use flakes, if it fails use normal nix (ie. shell.nix)
use flake || use nix use flake || use nix

View File

@@ -55,6 +55,16 @@ body:
placeholder: wezterm 20220101-133340-7edc5b5a placeholder: wezterm 20220101-133340-7edc5b5a
validations: validations:
required: true required: true
- type: input
id: installation-method
attributes:
label: Installation Method
description: >
How you installed Helix - from a package manager like Homebrew or the
AUR, built from source, downloaded a binary from the releases page, etc.
placeholder: "source / brew / nixpkgs / flake / releases page"
validations:
required: true
- type: input - type: input
id: helix-version id: helix-version
attributes: attributes:

View File

@@ -7,6 +7,14 @@ updates:
directory: "/" directory: "/"
schedule: schedule:
interval: "weekly" interval: "weekly"
groups:
tree-sitter:
patterns:
- "tree-sitter*"
rust-dependencies:
update-types:
- "minor"
- "patch"
- package-ecosystem: "github-actions" - package-ecosystem: "github-actions"
directory: "/" directory: "/"

View File

@@ -6,22 +6,28 @@ on:
- master - master
merge_group: merge_group:
schedule: schedule:
- cron: '00 01 * * *' - cron: "00 01 * * *"
env:
MSRV: "1.76"
jobs: jobs:
check: check:
name: Check (msrv) name: Check (msrv)
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.repository == 'helix-editor/helix' || github.event_name != 'schedule'
steps: steps:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Install stable toolchain
uses: helix-editor/rust-toolchain@v1 - name: Install MSRV toolchain
uses: dtolnay/rust-toolchain@master
with: with:
profile: minimal toolchain: ${{ env.MSRV }}
override: true
- uses: Swatinem/rust-cache@v2 - uses: Swatinem/rust-cache@v2
with:
shared-key: "build"
- name: Run cargo check - name: Run cargo check
run: cargo check run: cargo check
@@ -29,20 +35,25 @@ jobs:
test: test:
name: Test Suite name: Test Suite
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
if: github.repository == 'helix-editor/helix' || github.event_name != 'schedule'
env: env:
RUST_BACKTRACE: 1 RUST_BACKTRACE: 1
HELIX_LOG_LEVEL: info HELIX_LOG_LEVEL: info
steps: steps:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Install stable toolchain - name: Install MSRV toolchain
uses: dtolnay/rust-toolchain@1.65 uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.MSRV }}
- uses: Swatinem/rust-cache@v2 - uses: Swatinem/rust-cache@v2
with:
shared-key: "build"
- name: Cache test tree-sitter grammar - name: Cache test tree-sitter grammar
uses: actions/cache@v3 uses: actions/cache@v4
with: with:
path: runtime/grammars path: runtime/grammars
key: ${{ runner.os }}-stable-v${{ env.CACHE_VERSION }}-tree-sitter-grammars-${{ hashFiles('languages.toml') }} key: ${{ runner.os }}-stable-v${{ env.CACHE_VERSION }}-tree-sitter-grammars-${{ hashFiles('languages.toml') }}
@@ -61,16 +72,20 @@ jobs:
lints: lints:
name: Lints name: Lints
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.repository == 'helix-editor/helix' || github.event_name != 'schedule'
steps: steps:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Install stable toolchain - name: Install MSRV toolchain
uses: dtolnay/rust-toolchain@1.65 uses: dtolnay/rust-toolchain@master
with: with:
toolchain: ${{ env.MSRV }}
components: rustfmt, clippy components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2 - uses: Swatinem/rust-cache@v2
with:
shared-key: "build"
- name: Run cargo fmt - name: Run cargo fmt
run: cargo fmt --all --check run: cargo fmt --all --check
@@ -86,18 +101,26 @@ jobs:
docs: docs:
name: Docs name: Docs
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.repository == 'helix-editor/helix' || github.event_name != 'schedule'
steps: steps:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Install stable toolchain - name: Install MSRV toolchain
uses: dtolnay/rust-toolchain@1.65 uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ env.MSRV }}
- uses: Swatinem/rust-cache@v2 - uses: Swatinem/rust-cache@v2
with:
shared-key: "build"
- name: Validate queries - name: Validate queries
run: cargo xtask query-check run: cargo xtask query-check
- name: Validate themes
run: cargo xtask theme-check
- name: Generate docs - name: Generate docs
run: cargo xtask docgen run: cargo xtask docgen
@@ -107,4 +130,3 @@ jobs:
git diff-files --quiet \ git diff-files --quiet \
|| (echo "Run 'cargo xtask docgen', commit the changes and push again" \ || (echo "Run 'cargo xtask docgen', commit the changes and push again" \
&& exit 1) && exit 1)

View File

@@ -11,13 +11,13 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Install nix - name: Install nix
uses: cachix/install-nix-action@v20 uses: cachix/install-nix-action@v30
- name: Authenticate with Cachix - name: Authenticate with Cachix
uses: cachix/cachix-action@v12 uses: cachix/cachix-action@v15
with: with:
name: helix name: helix
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}

View File

@@ -11,13 +11,13 @@ jobs:
deploy: deploy:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Setup mdBook - name: Setup mdBook
uses: peaceiris/actions-mdbook@v1 uses: peaceiris/actions-mdbook@v2
with: with:
mdbook-version: 'latest' # mdbook-version: 'latest'
# mdbook-version: '0.4.8' mdbook-version: '0.4.43'
- run: mdbook build book - run: mdbook build book
@@ -26,16 +26,16 @@ jobs:
OUTDIR=$(basename ${{ github.ref }}) OUTDIR=$(basename ${{ github.ref }})
echo "OUTDIR=$OUTDIR" >> $GITHUB_ENV echo "OUTDIR=$OUTDIR" >> $GITHUB_ENV
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./book/book
destination_dir: ./${{ env.OUTDIR }}
- name: Deploy stable - name: Deploy stable
uses: peaceiris/actions-gh-pages@v3 uses: peaceiris/actions-gh-pages@v4
if: startswith(github.ref, 'refs/tags/') if: startswith(github.ref, 'refs/tags/')
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./book/book publish_dir: ./book/book
- name: Deploy
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./book/book
destination_dir: ./${{ env.OUTDIR }}

View File

@@ -23,7 +23,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Install stable toolchain - name: Install stable toolchain
uses: dtolnay/rust-toolchain@stable uses: dtolnay/rust-toolchain@stable
@@ -36,7 +36,7 @@ jobs:
- name: Bundle grammars - name: Bundle grammars
run: tar cJf grammars.tar.xz -C runtime/grammars/sources . run: tar cJf grammars.tar.xz -C runtime/grammars/sources .
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v4
with: with:
name: grammars name: grammars
path: grammars.tar.xz path: grammars.tar.xz
@@ -70,11 +70,11 @@ jobs:
rust: stable rust: stable
target: aarch64-unknown-linux-gnu target: aarch64-unknown-linux-gnu
cross: true cross: true
- build: riscv64-linux # - build: riscv64-linux
os: ubuntu-latest # os: ubuntu-latest
rust: stable # rust: stable
target: riscv64gc-unknown-linux-gnu # target: riscv64gc-unknown-linux-gnu
cross: true # cross: true
- build: x86_64-macos - build: x86_64-macos
os: macos-latest os: macos-latest
rust: stable rust: stable
@@ -103,10 +103,10 @@ jobs:
steps: steps:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Download grammars - name: Download grammars
uses: actions/download-artifact@v3 uses: actions/download-artifact@v4
- name: Move grammars under runtime - name: Move grammars under runtime
if: "!startsWith(matrix.os, 'windows')" if: "!startsWith(matrix.os, 'windows')"
@@ -160,7 +160,7 @@ jobs:
- name: Build AppImage - name: Build AppImage
shell: bash shell: bash
if: matrix.build == 'aarch64-linux' || matrix.build == 'x86_64-linux' if: matrix.build == 'x86_64-linux'
run: | run: |
# Required as of 22.x https://github.com/AppImage/AppImageKit/wiki/FUSE # Required as of 22.x https://github.com/AppImage/AppImageKit/wiki/FUSE
sudo add-apt-repository universe sudo add-apt-repository universe
@@ -220,7 +220,7 @@ jobs:
fi fi
cp -r runtime dist cp -r runtime dist
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v4
with: with:
name: bins-${{ matrix.build }} name: bins-${{ matrix.build }}
path: dist path: dist
@@ -231,9 +231,9 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout sources - name: Checkout sources
uses: actions/checkout@v3 uses: actions/checkout@v4
- uses: actions/download-artifact@v3 - uses: actions/download-artifact@v4
- name: Build archive - name: Build archive
shell: bash shell: bash
@@ -263,7 +263,7 @@ jobs:
mv bins-$platform/hx$exe $pkgname mv bins-$platform/hx$exe $pkgname
chmod +x $pkgname/hx$exe chmod +x $pkgname/hx$exe
if [[ "$platform" = "aarch64-linux" || "$platform" = "x86_64-linux" ]]; then if [[ "$platform" = "x86_64-linux" ]]; then
mv bins-$platform/helix-*.AppImage* dist/ mv bins-$platform/helix-*.AppImage* dist/
fi fi
@@ -288,7 +288,7 @@ jobs:
overwrite: true overwrite: true
- name: Upload binaries as artifact - name: Upload binaries as artifact
uses: actions/upload-artifact@v3 uses: actions/upload-artifact@v4
if: env.preview == 'true' if: env.preview == 'true'
with: with:
name: release name: release

1
.gitignore vendored
View File

@@ -3,3 +3,4 @@ target
helix-term/rustfmt.toml helix-term/rustfmt.toml
result result
runtime/grammars runtime/grammars
.DS_Store

View File

@@ -1,5 +0,0 @@
# Things that we don't want ripgrep to search that we do want in git
# https://github.com/BurntSushi/ripgrep/blob/master/GUIDE.md#automatic-filtering
# Minified JS vendored from mdbook
book/theme/highlight.js

View File

@@ -1,3 +1,837 @@
# 24.07 (2024-07-14)
Thanks to all of the contributors! This release has changes from 160 contributors.
Breaking changes:
Features:
- Add a textobject for entries/elements of list-like things ([#8150](https://github.com/helix-editor/helix/pull/8150))
- Add a picker showing files changed in VCS ([#5645](https://github.com/helix-editor/helix/pull/5645))
- Use a temporary file for writes ([#9236](https://github.com/helix-editor/helix/pull/9236), [#10339](https://github.com/helix-editor/helix/pull/10339), [#10790](https://github.com/helix-editor/helix/pull/10790))
- Allow cycling through LSP signature-help signatures with `A-n`/`A-p` ([#9974](https://github.com/helix-editor/helix/pull/9974), [#10654](https://github.com/helix-editor/helix/pull/10654), [#10655](https://github.com/helix-editor/helix/pull/10655))
- Use tree-sitter when finding matching brackets and closest pairs ([#8294](https://github.com/helix-editor/helix/pull/8294), [#10613](https://github.com/helix-editor/helix/pull/10613), [#10777](https://github.com/helix-editor/helix/pull/10777))
- Auto-save all buffers after a delay ([#10899](https://github.com/helix-editor/helix/pull/10899), [#11047](https://github.com/helix-editor/helix/pull/11047))
Commands:
- `select_all_siblings` (`A-a`) - select all siblings of each selection ([87c4161](https://github.com/helix-editor/helix/commit/87c4161))
- `select_all_children` (`A-I`) - select all children of each selection ([fa67c5c](https://github.com/helix-editor/helix/commit/fa67c5c))
- `:read` - insert the contents of the given file at each selection ([#10447](https://github.com/helix-editor/helix/pull/10447))
Usability improvements:
- Support scrolling popup contents using the mouse ([#10053](https://github.com/helix-editor/helix/pull/10053))
- Sort the jumplist picker so that most recent items come first ([#10095](https://github.com/helix-editor/helix/pull/10095))
- Improve `goto_file`'s (`gf`) automatic path detection strategy ([#9065](https://github.com/helix-editor/helix/pull/9065))
- Respect language server definition order in code action menu ([#9590](https://github.com/helix-editor/helix/pull/9590))
- Allow using a count with `goto_next_buffer` (`gn`) and `goto_previous_buffer` (`gp`) ([#10463](https://github.com/helix-editor/helix/pull/10463))
- Improve the positioning of popups ([#10257](https://github.com/helix-editor/helix/pull/10257), [#10573](https://github.com/helix-editor/helix/pull/10573))
- Reset all changes overlapped by selections in `:reset-diff-change` ([#10728](https://github.com/helix-editor/helix/pull/10728))
- Await pending writes in the `suspend` command (`C-z`) ([#10797](https://github.com/helix-editor/helix/pull/10797))
- Remove special handling of line ending characters in `replace` (`r`) ([#10786](https://github.com/helix-editor/helix/pull/10786))
- Use the selected register as a history register for `rename_symbol` (`<space>r`) ([#10932](https://github.com/helix-editor/helix/pull/10932))
- Use the configured insert-mode cursor for prompt entry ([#10945](https://github.com/helix-editor/helix/pull/10945))
- Add tilted quotes to the matching brackets list ([#10971](https://github.com/helix-editor/helix/pull/10971))
- Prevent improper files like `/dev/urandom` from being used as file arguments ([#10733](https://github.com/helix-editor/helix/pull/10733))
- Allow multiple language servers to provide `:lsp-workspace-command`s ([#10176](https://github.com/helix-editor/helix/pull/10176), [#11105](https://github.com/helix-editor/helix/pull/11105))
- Trim output of commands executed through `:pipe` ([#10952](https://github.com/helix-editor/helix/pull/10952))
Fixes:
- Use `lldb-dap` instead of `lldb-vscode` in default DAP configuration ([#10091](https://github.com/helix-editor/helix/pull/10091))
- Fix creation of uneven splits when closing windows ([#10004](https://github.com/helix-editor/helix/pull/10004))
- Avoid setting a register in `delete_selection_noyank`, fixing the command's use in command sequences ([#10050](https://github.com/helix-editor/helix/pull/10050), [#10148](https://github.com/helix-editor/helix/pull/10148))
- Fix jump alphabet config resetting when using `:config-reload` ([#10156](https://github.com/helix-editor/helix/pull/10156))
- Overlay LSP unnecessary/deprecated diagnostic tag highlights onto regular diagnostic highlights ([#10084](https://github.com/helix-editor/helix/pull/10084))
- Fix crash on LSP text edits with invalid ranges ([#9649](https://github.com/helix-editor/helix/pull/9649))
- Handle partial failure when sending multiple LSP `textDocument/didSave` notifications ([#10168](https://github.com/helix-editor/helix/pull/10168))
- Fix off-by-one error for completion-replace option ([#10279](https://github.com/helix-editor/helix/pull/10279))
- Fix mouse right-click selection behavior ([#10067](https://github.com/helix-editor/helix/pull/10067))
- Fix scrolling to the end within a popup ([#10181](https://github.com/helix-editor/helix/pull/10181))
- Fix jump label highlight locations when jumping in non-ascii text ([#10317](https://github.com/helix-editor/helix/pull/10317))
- Fix crashes from tree-sitter query captures that return non-grapheme aligned ranges ([#10310](https://github.com/helix-editor/helix/pull/10310))
- Include VCS change in `mi`/`ma` textobject infobox ([#10496](https://github.com/helix-editor/helix/pull/10496))
- Override crossterm's support for `NO_COLOR` ([#10514](https://github.com/helix-editor/helix/pull/10514))
- Respect mode when starting a search ([#10505](https://github.com/helix-editor/helix/pull/10505))
- Simplify first-in-line computation for indent queries ([#10527](https://github.com/helix-editor/helix/pull/10527))
- Ignore .svn version controlled files in file pickers ([#10536](https://github.com/helix-editor/helix/pull/10536))
- Fix overloading language servers with `completionItem/resolve` requests ([38ee845](https://github.com/helix-editor/helix/commit/38ee845), [#10873](https://github.com/helix-editor/helix/pull/10873))
- Specify direction for `select_next_sibling` / `select_prev_sibling` ([#10542](https://github.com/helix-editor/helix/pull/10542))
- Fix restarting language servers ([#10614](https://github.com/helix-editor/helix/pull/10614))
- Don't stop at the first URL in `goto_file` ([#10622](https://github.com/helix-editor/helix/pull/10622))
- Fix overflows in window size calculations for small terminals ([#10620](https://github.com/helix-editor/helix/pull/10620))
- Allow missing or empty completion lists in DAP ([#10332](https://github.com/helix-editor/helix/pull/10332))
- Revert statusline refactor that could cause the statusline to blank out on files with long paths ([#10642](https://github.com/helix-editor/helix/pull/10642))
- Synchronize files after writing ([#10735](https://github.com/helix-editor/helix/pull/10735))
- Avoid `cnorm` for cursor-type detection in certain terminals ([#10769](https://github.com/helix-editor/helix/pull/10769))
- Reset inlay hints when stopping or restarting a language server ([#10741](https://github.com/helix-editor/helix/pull/10741))
- Fix logic for updating `--version` when development VCS HEAD changes ([#10896](https://github.com/helix-editor/helix/pull/10896))
- Set a max value for the count ([#10930](https://github.com/helix-editor/helix/pull/10930))
- Deserialize number IDs in DAP module types ([#10943](https://github.com/helix-editor/helix/pull/10943))
- Fix the behavior of `jump_backwords` when the jumplist is at capacity ([#10968](https://github.com/helix-editor/helix/pull/10968))
- Fix injection layer heritage tracking for reused tree-sitter injection layers ([#1098](https://github.com/helix-editor/helix/pull/1098))
- Fix pluralization of "buffers" in the statusline for `:q`, `:q!`, `:wq` ([#11018](https://github.com/helix-editor/helix/pull/11018))
- Declare LSP formatting client capabilities ([#11064](https://github.com/helix-editor/helix/pull/11064))
- Commit uncommitted changes before attempting undo/earlier ([#11090](https://github.com/helix-editor/helix/pull/11090))
- Expand tilde for selected paths in `goto_file` ([#10964](https://github.com/helix-editor/helix/pull/10964))
- Commit undo checkpoints before `:write[-all]`, fixing the modification indicator ([#11062](https://github.com/helix-editor/helix/pull/11062))
Themes:
- Add jump label styles to `nightfox` ([#10052](https://github.com/helix-editor/helix/pull/10052))
- Add jump label styles to Solarized themes ([#10056](https://github.com/helix-editor/helix/pull/10056))
- Add jump label styles to `cyan_light` ([#10058](https://github.com/helix-editor/helix/pull/10058))
- Add jump label styles to `onelight` ([#10061](https://github.com/helix-editor/helix/pull/10061))
- Add `flexoki-dark` and `flexoki-light` ([#10002](https://github.com/helix-editor/helix/pull/10002))
- Add default theme keys for LSP diagnostics tags to existing themes ([#10064](https://github.com/helix-editor/helix/pull/10064))
- Add jump label styles to base16 themes ([#10076](https://github.com/helix-editor/helix/pull/10076))
- Dim primary selection in `kanagawa` ([#10094](https://github.com/helix-editor/helix/pull/10094), [#10500](https://github.com/helix-editor/helix/pull/10500))
- Add jump label styles to tokyonight themes ([#10106](https://github.com/helix-editor/helix/pull/10106))
- Add jump label styles to papercolor themes ([#10104](https://github.com/helix-editor/helix/pull/10104))
- Add jump label styles to Darcula themes ([#10116](https://github.com/helix-editor/helix/pull/10116))
- Add jump label styles to `autumn` ([#10134](https://github.com/helix-editor/helix/pull/10134))
- Add jump label styles to Ayu themes ([#10133](https://github.com/helix-editor/helix/pull/10133))
- Add jump label styles to `dark_high_contrast` ([#10133](https://github.com/helix-editor/helix/pull/10133))
- Update material themes ([#10290](https://github.com/helix-editor/helix/pull/10290))
- Add jump label styles to `varua` ([#10299](https://github.com/helix-editor/helix/pull/10299))
- Add ruler style to `adwaita-dark` ([#10260](https://github.com/helix-editor/helix/pull/10260))
- Remove `ui.highlight` effects from `solarized_dark` ([#10261](https://github.com/helix-editor/helix/pull/10261))
- Fix statusline color in material themes ([#10308](https://github.com/helix-editor/helix/pull/10308))
- Brighten `nord` selection highlight ([#10307](https://github.com/helix-editor/helix/pull/10307))
- Add inlay-hint styles to monokai themes ([#10334](https://github.com/helix-editor/helix/pull/10334))
- Add bufferline and cursorline colors to `vim_dark_high_contrast` ([#10444](https://github.com/helix-editor/helix/pull/10444))
- Switch themes with foreground rulers to background ([#10309](https://github.com/helix-editor/helix/pull/10309))
- Fix statusline colors for `everblush` ([#10394](https://github.com/helix-editor/helix/pull/10394))
- Use `yellow1` for `gruvbox` warning diagnostics ([#10506](https://github.com/helix-editor/helix/pull/10506))
- Add jump label styles to Modus themes ([#10538](https://github.com/helix-editor/helix/pull/10538))
- Refactor `dark_plus` and switch maintainers ([#10543](https://github.com/helix-editor/helix/pull/10543), [#10574](https://github.com/helix-editor/helix/pull/10574))
- Add debug highlights to `dark_plus` ([#10593](https://github.com/helix-editor/helix/pull/10593))
- Fix per-mode cursor colors in the default theme ([#10608](https://github.com/helix-editor/helix/pull/10608))
- Add `tag` and `attribute` highlights to `dark_high_contrast` ([#10705](https://github.com/helix-editor/helix/pull/10705))
- Improve readability of virtual text with `noctis` theme ([#10910](https://github.com/helix-editor/helix/pull/10910))
- Sync `catppuccin` themes with upstream ([#10954](https://github.com/helix-editor/helix/pull/10954))
- Improve jump colors for `github_dark` themes ([#10946](https://github.com/helix-editor/helix/pull/10946))
- Add modeline and default virtual highlights to `base16_default` ([#10858](https://github.com/helix-editor/helix/pull/10858))
- Add `iroaseta` ([#10381](https://github.com/helix-editor/helix/pull/10381))
- Refactor `gruvbox` ([#10773](https://github.com/helix-editor/helix/pull/10773), [#11071](https://github.com/helix-editor/helix/pull/11071))
- Add cursorcolumn and cursorline to `base16_transparent` ([#11099](https://github.com/helix-editor/helix/pull/11099))
- Update cursorline color for `fleet_dark` ([#11046](https://github.com/helix-editor/helix/pull/11046))
- Add `kanagawa-dragon` ([#10172](https://github.com/helix-editor/helix/pull/10172))
New languages:
- BitBake ([#10010](https://github.com/helix-editor/helix/pull/10010))
- Earthfile ([#10111](https://github.com/helix-editor/helix/pull/10111), [#10489](https://github.com/helix-editor/helix/pull/10489), [#10779](https://github.com/helix-editor/helix/pull/10779))
- TCL ([#9837](https://github.com/helix-editor/helix/pull/9837))
- ADL ([#10029](https://github.com/helix-editor/helix/pull/10029))
- LDIF ([#10330](https://github.com/helix-editor/helix/pull/10330))
- XTC ([#10448](https://github.com/helix-editor/helix/pull/10448))
- Move ([f06a166](https://github.com/helix-editor/helix/commit/f06a166))
- Pest ([#10616](https://github.com/helix-editor/helix/pull/10616))
- GJS/GTS ([#9940](https://github.com/helix-editor/helix/pull/9940))
- Inko ([#10656](https://github.com/helix-editor/helix/pull/10656))
- Mojo ([#10743](https://github.com/helix-editor/helix/pull/10743))
- Elisp ([#10644](https://github.com/helix-editor/helix/pull/10644))
Updated languages and queries:
- Recognize `mkdn` files as markdown ([#10065](https://github.com/helix-editor/helix/pull/10065))
- Add comment injections for Gleam ([#10062](https://github.com/helix-editor/helix/pull/10062))
- Recognize BuildKite commands in YAML injections ([#10090](https://github.com/helix-editor/helix/pull/10090))
- Add F# block comment token configuration ([#10108](https://github.com/helix-editor/helix/pull/10108))
- Update tree-sitter-templ and queries ([#10114](https://github.com/helix-editor/helix/pull/10114))
- Recognize `Tiltfile` as Starlark ([#10072](https://github.com/helix-editor/helix/pull/10072))
- Remove `todo.txt` from files recognized as todotxt ([5fece00](https://github.com/helix-editor/helix/commit/5fece00))
- Highlight `type` keyword in Python from PEP695 ([#10165](https://github.com/helix-editor/helix/pull/10165))
- Update tree-sitter-koka, add language server config ([#10119](https://github.com/helix-editor/helix/pull/10119))
- Recognize node and Python history files ([#10120](https://github.com/helix-editor/helix/pull/10120))
- Recognize more shell files as bash ([#10120](https://github.com/helix-editor/helix/pull/10120))
- Recognize the bun shebang as typescript ([#10120](https://github.com/helix-editor/helix/pull/10120))
- Add a configuration for the angular language server ([#10166](https://github.com/helix-editor/helix/pull/10166))
- Add textobject queries for Solidity ([#10318](https://github.com/helix-editor/helix/pull/10318))
- Recognize `meson.options` as Meson ([#10323](https://github.com/helix-editor/helix/pull/10323))
- Improve Solidity highlighting ([4fc0a4d](https://github.com/helix-editor/helix/commit/4fc0a4d))
- Recognize `_.tpl` files as Helm ([#10344](https://github.com/helix-editor/helix/pull/10344))
- Update tree-sitter-ld and highlights ([#10379](https://github.com/helix-editor/helix/pull/10379))
- Add `lldb-dap` configuration for Odin ([#10175](https://github.com/helix-editor/helix/pull/10175))
- Update tree-sitter-rust ([#10365](https://github.com/helix-editor/helix/pull/10365))
- Update tree-sitter-typst ([#10321](https://github.com/helix-editor/helix/pull/10321))
- Recognize `hyprpaper.conf`, `hypridle.conf` and `hyprlock.conf` as Hyprlang ([#10383](https://github.com/helix-editor/helix/pull/10383))
- Improve HTML highlighting ([#10503](https://github.com/helix-editor/helix/pull/10503))
- Add `rust-script` and `cargo` as shebangs for Rust ([#10484](https://github.com/helix-editor/helix/pull/10484))
- Fix precedence of tag highlights in Svelte ([#10487](https://github.com/helix-editor/helix/pull/10487))
- Update tree-sitter-bash ([#10526](https://github.com/helix-editor/helix/pull/10526))
- Recognize `*.ignore` files as ignore ([#10579](https://github.com/helix-editor/helix/pull/10579))
- Add configuration to enable inlay hints in metals ([#10597](https://github.com/helix-editor/helix/pull/10597))
- Enable highlighting private members in ECMA languages ([#10554](https://github.com/helix-editor/helix/pull/10554))
- Add comment injection to typst queries ([#10628](https://github.com/helix-editor/helix/pull/10628))
- Add textobject queries for Hurl ([#10594](https://github.com/helix-editor/helix/pull/10594))
- Add `try` keyword to Rust ([#10641](https://github.com/helix-editor/helix/pull/10641))
- Add `is not` and `not in` to Python highlights ([#10647](https://github.com/helix-editor/helix/pull/10647))
- Remove ' and ⟨⟩ from Lean autopair configuration ([#10688](https://github.com/helix-editor/helix/pull/10688))
- Match TOML/YAML highlights for JSON keys ([#10676](https://github.com/helix-editor/helix/pull/10676))
- Recognize WORKSPACE files as Starlark ([#10713](https://github.com/helix-editor/helix/pull/10713))
- Switch Odin tree-sitter grammar and highlights ([#10698](https://github.com/helix-editor/helix/pull/10698))
- Update `tree-sitter-slint` ([#10749](https://github.com/helix-editor/helix/pull/10749))
- Add missing operators for Solidity highlights ([#10735](https://github.com/helix-editor/helix/pull/10735))
- Update `tree-sitter-inko` ([#10805](https://github.com/helix-editor/helix/pull/10805))
- Add `py`, `hs`, `rs` and `typ` injection regexes ([#10785](https://github.com/helix-editor/helix/pull/10785))
- Update Swift grammar and queries ([#10802](https://github.com/helix-editor/helix/pull/10802))
- Update Cairo grammar and queries ([#10919](https://github.com/helix-editor/helix/pull/10919), [#11067](https://github.com/helix-editor/helix/pull/11067))
- Update Rust grammar ([#10973](https://github.com/helix-editor/helix/pull/10973))
- Add block comment tokens for typst ([#10955](https://github.com/helix-editor/helix/pull/10955))
- Recognize `jsonl` as JSON ([#11004](https://github.com/helix-editor/helix/pull/11004))
- Add rulers and text-width at 100 columns for Lean language ([#10969](https://github.com/helix-editor/helix/pull/10969))
- Improve VDHL highlights ([#10845](https://github.com/helix-editor/helix/pull/10845))
- Recognize `hsc` as Haskell ([#11074](https://github.com/helix-editor/helix/pull/11074))
- Fix heredoc and `$'<ansi_string>'` highlights in Bash ([#11118](https://github.com/helix-editor/helix/pull/11118))
- Add LSP configuration for `basedpyright` ([#11121](https://github.com/helix-editor/helix/pull/11121))
- Recognize `npmrc` and `.nmprc` files as INI ([#11131](https://github.com/helix-editor/helix/pull/11131))
- Recognize `~/.config/git/ignore` as git-ignore ([#11131](https://github.com/helix-editor/helix/pull/11131))
- Recognize `pdm.lock` and `uv.lock` as TOML ([#11131](https://github.com/helix-editor/helix/pull/11131))
- Recognize `.yml` as well as `.yaml` for Helm chart templates ([#11135](https://github.com/helix-editor/helix/pull/11135))
- Add regex injections for Bash ([#11112](https://github.com/helix-editor/helix/pull/11112))
- Update tree-sitter-todo ([#11097](https://github.com/helix-editor/helix/pull/11097))
Packaging:
- Make `Helix.appdata.xml` spec-compliant ([#10051](https://github.com/helix-editor/helix/pull/10051))
- Expose all flake outputs through flake-compat ([#10673](https://github.com/helix-editor/helix/pull/10673))
- Bump the MSRV to 1.74.0 ([#10714](https://github.com/helix-editor/helix/pull/10714))
- Improve FiSH completions ([#10853](https://github.com/helix-editor/helix/pull/10853))
- Improve ZSH completions ([#10853](https://github.com/helix-editor/helix/pull/10853))
# 24.03 (2024-03-30)
As always, a big thank you to all of the contributors! This release saw changes from 125 contributors.
Breaking changes:
- `suffix` file-types in the `file-types` key in language configuration have been removed ([#8006](https://github.com/helix-editor/helix/pull/8006))
- The `file-types` key in language configuration no longer matches full filenames without a glob pattern ([#8006](https://github.com/helix-editor/helix/pull/8006))
Features:
- Open URLs with the `goto_file` command ([#5820](https://github.com/helix-editor/helix/pull/5820))
- Support drawing a border around popups and menus ([#4313](https://github.com/helix-editor/helix/pull/4313), [#9508](https://github.com/helix-editor/helix/pull/9508))
- Track long lived diagnostic sources like Clippy or `rustc` ([#6447](https://github.com/helix-editor/helix/pull/6447), [#9280](https://github.com/helix-editor/helix/pull/9280))
- This improves the handling of diagnostics from sources that only update the diagnostic positions on save.
- Add support for LSP `window/showDocument` requests ([#8865](https://github.com/helix-editor/helix/pull/8865))
- Refactor ad-hoc hooks to use a new generic event system ([#8021](https://github.com/helix-editor/helix/pull/8021), [#9668](https://github.com/helix-editor/helix/pull/9668), [#9660](https://github.com/helix-editor/helix/pull/9660))
- This improves the behavior of autocompletions. For example navigating in insert mode no longer automatically triggers completions.
- Allow using globs in the language configuration `file-types` key ([#8006](https://github.com/helix-editor/helix/pull/8006))
- Allow specifying required roots for situational LSP activation ([#8696](https://github.com/helix-editor/helix/pull/8696))
- Extend selections using mouse clicks in select mode ([#5436](https://github.com/helix-editor/helix/pull/5436))
- Toggle block comments ([#4718](https://github.com/helix-editor/helix/pull/4718), [#9894](https://github.com/helix-editor/helix/pull/9894))
- Support LSP diagnostic tags ([#9780](https://github.com/helix-editor/helix/pull/9780))
- Add a `file-absolute-path` statusline element ([#4535](https://github.com/helix-editor/helix/pull/4535))
- Cross injection layers in tree-sitter motions (`A-p`/`A-o`/`A-i`/`A-n`) ([#5176](https://github.com/helix-editor/helix/pull/5176))
- Add a Amp-editor-like jumping command ([#8875](https://github.com/helix-editor/helix/pull/8875))
Commands:
- `:move` - move buffers with LSP support ([#8584](https://github.com/helix-editor/helix/pull/8584))
- Also see [#8949](https://github.com/helix-editor/helix/pull/8949) which made path changes conform to the LSP spec and fixed the behavior of this command.
- `page_cursor_up`, `page_cursor_down`, `page_cursor_half_up`, `page_cursor_half_down` - commands for scrolling the cursor and page together ([#8015](https://github.com/helix-editor/helix/pull/8015))
- `:yank-diagnostic` - yank the diagnostic(s) under the primary cursor ([#9640](https://github.com/helix-editor/helix/pull/9640))
- `select_line_above` / `select_line_below` - extend or shrink a selection based on the direction and anchor ([#9080](https://github.com/helix-editor/helix/pull/9080))
Usability improvements:
- Make `roots` key of `[[language]]` entries in `languages.toml` configuration optional ([#8803](https://github.com/helix-editor/helix/pull/8803))
- Exit select mode in commands that modify the buffer ([#8689](https://github.com/helix-editor/helix/pull/8689))
- Use crossterm cursor when out of focus ([#6858](https://github.com/helix-editor/helix/pull/6858), [#8934](https://github.com/helix-editor/helix/pull/8934))
- Join empty lines with only one space in `join_selections` ([#8989](https://github.com/helix-editor/helix/pull/8989))
- Introduce a hybrid tree-sitter and contextual indentation heuristic ([#8307](https://github.com/helix-editor/helix/pull/8307))
- Allow configuring the indentation heuristic ([#8307](https://github.com/helix-editor/helix/pull/8307))
- Check for LSP rename support before showing rename prompt ([#9277](https://github.com/helix-editor/helix/pull/9277))
- Normalize `S-<lower-ascii>` keymaps to uppercase ascii ([#9213](https://github.com/helix-editor/helix/pull/9213))
- Add formatter status to `--health` output ([#7986](https://github.com/helix-editor/helix/pull/7986))
- Change path normalization strategy to not resolve symlinks ([#9330](https://github.com/helix-editor/helix/pull/9330))
- Select subtree within injections in `:tree-sitter-subtree` ([#9309](https://github.com/helix-editor/helix/pull/9309))
- Use tilde expansion and normalization for `$HELIX_RUNTIME` paths ([1bc7aac](https://github.com/helix-editor/helix/commit/1bc7aac))
- Improve failure message for LSP goto references ([#9382](https://github.com/helix-editor/helix/pull/9382))
- Use injection syntax trees for bracket matching ([5e0b3cc](https://github.com/helix-editor/helix/commit/5e0b3cc))
- Respect injections in `:tree-sitter-highlight-name` ([8b6565c](https://github.com/helix-editor/helix/commit/8b6565c))
- Respect injections in `move_parent_node_end` ([035b8ea](https://github.com/helix-editor/helix/commit/035b8ea))
- Use `gix` pipeline filter instead of manual CRLF implementation ([#9503](https://github.com/helix-editor/helix/pull/9503))
- Follow Neovim's truecolor detection ([#9577](https://github.com/helix-editor/helix/pull/9577))
- Reload language configuration with `:reload`, SIGHUP ([#9415](https://github.com/helix-editor/helix/pull/9415))
- Allow numbers as bindings ([#8471](https://github.com/helix-editor/helix/pull/8471), [#9887](https://github.com/helix-editor/helix/pull/9887))
- Respect undercurl config when terminfo is not available ([#9897](https://github.com/helix-editor/helix/pull/9897))
- Ignore `.pijul`, `.hg`, `.jj` in addition to `.git` in file pickers configured to show hidden files ([#9935](https://github.com/helix-editor/helix/pull/9935))
- Add completion for registers to `:clear-register` and `:yank-diagnostic` ([#9936](https://github.com/helix-editor/helix/pull/9936))
- Repeat last motion for goto next/prev diagnostic ([#9966](https://github.com/helix-editor/helix/pull/9966))
- Allow configuring a character to use when rendering narrow no-breaking space ([#9604](https://github.com/helix-editor/helix/pull/9604))
- Switch to a streaming regex engine (regex-cursor crate) to significantly speed up regex-based commands and features ([#9422](https://github.com/helix-editor/helix/pull/9422), [#9756](https://github.com/helix-editor/helix/pull/9756), [#9891](https://github.com/helix-editor/helix/pull/9891))
Fixes:
- Swap `*` and `+` registers ([#8703](https://github.com/helix-editor/helix/pull/8703), [#8708](https://github.com/helix-editor/helix/pull/8708))
- Use terminfo to reset terminal cursor style ([#8591](https://github.com/helix-editor/helix/pull/8591))
- Fix precedence of `@align` captures in indentat computation ([#8659](https://github.com/helix-editor/helix/pull/8659))
- Only render the preview if a Picker has a preview function ([#8667](https://github.com/helix-editor/helix/pull/8667))
- Fix the precedence of `ui.virtual.whitespace` ([#8750](https://github.com/helix-editor/helix/pull/8750), [#8879](https://github.com/helix-editor/helix/pull/8879))
- Fix crash in `:indent-style` ([#9087](https://github.com/helix-editor/helix/pull/9087))
- Fix `didSave` text inclusion when sync capability is a kind variant ([#9101](https://github.com/helix-editor/helix/pull/9101))
- Update the history of newly focused views ([#9271](https://github.com/helix-editor/helix/pull/9271))
- Initialize diagnostics when opening a document ([#8873](https://github.com/helix-editor/helix/pull/8873))
- Sync views when applying edits to unfocused views ([#9173](https://github.com/helix-editor/helix/pull/9173))
- This fixes crashes that could occur from LSP workspace edits or `:write-all`.
- Treat non-numeric `+arg`s passed in the CLI args as filenames ([#9333](https://github.com/helix-editor/helix/pull/9333))
- Fix crash when using `mm` on an empty plaintext file ([2fb7e50](https://github.com/helix-editor/helix/commit/2fb7e50))
- Ignore empty tree-sitter nodes in match bracket ([445f7a2](https://github.com/helix-editor/helix/commit/445f7a2))
- Exit a language server if it sends a message with invalid JSON ([#9332](https://github.com/helix-editor/helix/pull/9332))
- Handle failures to enable bracketed paste ([#9353](https://github.com/helix-editor/helix/pull/9353))
- Gate all captures in a pattern behind `#is-not? local` predicates ([#9390](https://github.com/helix-editor/helix/pull/9390))
- Make path changes LSP spec conformant ([#8949](https://github.com/helix-editor/helix/pull/8949))
- Use range positions to determine `insert_newline` motion ([#9448](https://github.com/helix-editor/helix/pull/9448))
- Fix division by zero when prompt completion area is too small ([#9524](https://github.com/helix-editor/helix/pull/9524))
- Add changes to history in clipboard replacement typable commands ([#9625](https://github.com/helix-editor/helix/pull/9625))
- Fix a crash in DAP with an unspecified `line` in breakpoints ([#9632](https://github.com/helix-editor/helix/pull/9632))
- Fix space handling for filenames in bash completion ([#9702](https://github.com/helix-editor/helix/pull/9702), [#9708](https://github.com/helix-editor/helix/pull/9708))
- Key diagnostics off of paths instead of LSP URIs ([#7367](https://github.com/helix-editor/helix/pull/7367))
- Fix panic when using `join_selections_space` ([#9783](https://github.com/helix-editor/helix/pull/9783))
- Fix panic when using `surround_replace`, `surround_delete` ([#9796](https://github.com/helix-editor/helix/pull/9796))
- Fix panic in `surround_replace`, `surround_delete` with nested surrounds and multiple cursors ([#9815](https://github.com/helix-editor/helix/pull/9815))
- Fix panic in `select_textobject_around` ([#9832](https://github.com/helix-editor/helix/pull/9832))
- Don't stop reloading documents when reloading fails in `:reload-all` ([#9870](https://github.com/helix-editor/helix/pull/9870))
- Prevent `shell_keep_pipe` from stopping on nonzero exit status codes ([#9817](https://github.com/helix-editor/helix/pull/9817))
Themes:
- Add `gruber-dark` ([#8598](https://github.com/helix-editor/helix/pull/8598))
- Update `everblush` ([#8705](https://github.com/helix-editor/helix/pull/8705))
- Update `papercolor` ([#8718](https://github.com/helix-editor/helix/pull/8718), [#8827](https://github.com/helix-editor/helix/pull/8827))
- Add `polmandres` ([#8759](https://github.com/helix-editor/helix/pull/8759))
- Add `starlight` ([#8787](https://github.com/helix-editor/helix/pull/8787))
- Update `naysayer` ([#8838](https://github.com/helix-editor/helix/pull/8838))
- Add modus operandi themes ([#8728](https://github.com/helix-editor/helix/pull/8728), [#9912](https://github.com/helix-editor/helix/pull/9912))
- Update `rose_pine` ([#8946](https://github.com/helix-editor/helix/pull/8946))
- Update `darcula` ([#8738](https://github.com/helix-editor/helix/pull/8738), [#9002](https://github.com/helix-editor/helix/pull/9002), [#9449](https://github.com/helix-editor/helix/pull/9449), [#9588](https://github.com/helix-editor/helix/pull/9588))
- Add modus vivendi themes ([#8894](https://github.com/helix-editor/helix/pull/8894), [#9912](https://github.com/helix-editor/helix/pull/9912))
- Add `horizon-dark` ([#9008](https://github.com/helix-editor/helix/pull/9008), [#9493](https://github.com/helix-editor/helix/pull/9493))
- Update `noctis` ([#9123](https://github.com/helix-editor/helix/pull/9123))
- Update `nord` ([#9135](https://github.com/helix-editor/helix/pull/9135))
- Update monokai pro themes ([#9148](https://github.com/helix-editor/helix/pull/9148))
- Update tokyonight themes ([#9099](https://github.com/helix-editor/helix/pull/9099), [#9724](https://github.com/helix-editor/helix/pull/9724), [#9789](https://github.com/helix-editor/helix/pull/9789))
- Add `ttox` ([#8524](https://github.com/helix-editor/helix/pull/8524))
- Add `voxed` ([#9164](https://github.com/helix-editor/helix/pull/9164))
- Update `sonokai` ([#9370](https://github.com/helix-editor/helix/pull/9370), [#9376](https://github.com/helix-editor/helix/pull/9376), [#5379](https://github.com/helix-editor/helix/pull/5379))
- Update `onedark`, `onedarker` ([#9397](https://github.com/helix-editor/helix/pull/9397))
- Update `cyan_light` ([#9375](https://github.com/helix-editor/helix/pull/9375), [#9688](https://github.com/helix-editor/helix/pull/9688))
- Add `gruvbox_light_soft`, `gruvbox_light_hard` ([#9266](https://github.com/helix-editor/helix/pull/9266))
- Update GitHub themes ([#9487](https://github.com/helix-editor/helix/pull/9487))
- Add `term16_dark`, `term16_light` ([#9477](https://github.com/helix-editor/helix/pull/9477))
- Update Zed themes ([#9544](https://github.com/helix-editor/helix/pull/9544), [#9549](https://github.com/helix-editor/helix/pull/9549))
- Add `curzon` ([#9553](https://github.com/helix-editor/helix/pull/9553))
- Add `monokai_soda` ([#9651](https://github.com/helix-editor/helix/pull/9651))
- Update catppuccin themes ([#9859](https://github.com/helix-editor/helix/pull/9859))
- Update `rasmus` ([#9939](https://github.com/helix-editor/helix/pull/9939))
- Update `dark_plus` ([#9949](https://github.com/helix-editor/helix/pull/9949), [628dcd5](https://github.com/helix-editor/helix/commit/628dcd5))
- Update gruvbox themes ([#9960](https://github.com/helix-editor/helix/pull/9960))
- Add jump label theming to `dracula` ([#9973](https://github.com/helix-editor/helix/pull/9973))
- Add jump label theming to `horizon-dark` ([#9984](https://github.com/helix-editor/helix/pull/9984))
- Add jump label theming to catppuccin themes ([2178adf](https://github.com/helix-editor/helix/commit/2178adf), [#9983](https://github.com/helix-editor/helix/pull/9983))
- Add jump label theming to `onedark` themes ([da2dec1](https://github.com/helix-editor/helix/commit/da2dec1))
- Add jump label theming to rose-pine themes ([#9981](https://github.com/helix-editor/helix/pull/9981))
- Add jump label theming to Nord themes ([#10008](https://github.com/helix-editor/helix/pull/10008))
- Add jump label theming to Monokai themes ([#10009](https://github.com/helix-editor/helix/pull/10009))
- Add jump label theming to gruvbox themes ([#10012](https://github.com/helix-editor/helix/pull/10012))
- Add jump label theming to `kanagawa` ([#10030](https://github.com/helix-editor/helix/pull/10030))
- Update material themes ([#10043](https://github.com/helix-editor/helix/pull/10043))
- Add `jetbrains_dark` ([#9967](https://github.com/helix-editor/helix/pull/9967))
New languages:
- Typst ([#7474](https://github.com/helix-editor/helix/pull/7474))
- LPF ([#8536](https://github.com/helix-editor/helix/pull/8536))
- GN ([#6969](https://github.com/helix-editor/helix/pull/6969))
- DBML ([#8860](https://github.com/helix-editor/helix/pull/8860))
- log ([#8916](https://github.com/helix-editor/helix/pull/8916))
- Janet ([#9081](https://github.com/helix-editor/helix/pull/9081), [#9247](https://github.com/helix-editor/helix/pull/9247))
- Agda ([#8285](https://github.com/helix-editor/helix/pull/8285))
- Avro ([#9113](https://github.com/helix-editor/helix/pull/9113))
- Smali ([#9089](https://github.com/helix-editor/helix/pull/9089))
- HOCON ([#9203](https://github.com/helix-editor/helix/pull/9203))
- Tact ([#9512](https://github.com/helix-editor/helix/pull/9512))
- PKL ([#9515](https://github.com/helix-editor/helix/pull/9515))
- CEL ([#9296](https://github.com/helix-editor/helix/pull/9296))
- SpiceDB ([#9296](https://github.com/helix-editor/helix/pull/9296))
- Hoon ([#9190](https://github.com/helix-editor/helix/pull/9190))
- DockerCompose ([#9661](https://github.com/helix-editor/helix/pull/9661), [#9916](https://github.com/helix-editor/helix/pull/9916))
- Groovy ([#9350](https://github.com/helix-editor/helix/pull/9350), [#9681](https://github.com/helix-editor/helix/pull/9681), [#9677](https://github.com/helix-editor/helix/pull/9677))
- FIDL ([#9713](https://github.com/helix-editor/helix/pull/9713))
- Powershell ([#9827](https://github.com/helix-editor/helix/pull/9827))
- ld ([#9835](https://github.com/helix-editor/helix/pull/9835))
- Hyperland config ([#9899](https://github.com/helix-editor/helix/pull/9899))
- JSONC ([#9906](https://github.com/helix-editor/helix/pull/9906))
- PHP Blade ([#9513](https://github.com/helix-editor/helix/pull/9513))
- SuperCollider ([#9329](https://github.com/helix-editor/helix/pull/9329))
- Koka ([#8727](https://github.com/helix-editor/helix/pull/8727))
- PKGBUILD ([#9909](https://github.com/helix-editor/helix/pull/9909), [#9943](https://github.com/helix-editor/helix/pull/9943))
- Ada ([#9908](https://github.com/helix-editor/helix/pull/9908))
- Helm charts ([#9900](https://github.com/helix-editor/helix/pull/9900))
- Ember.js templates ([#9902](https://github.com/helix-editor/helix/pull/9902))
- Ohm ([#9991](https://github.com/helix-editor/helix/pull/9991))
Updated languages and queries:
- Add HTML injection queries for Rust ([#8603](https://github.com/helix-editor/helix/pull/8603))
- Switch to tree-sitter-ron for RON ([#8624](https://github.com/helix-editor/helix/pull/8624))
- Update and improve comment highlighting ([#8564](https://github.com/helix-editor/helix/pull/8564), [#9253](https://github.com/helix-editor/helix/pull/9253), [#9800](https://github.com/helix-editor/helix/pull/9800), [#10014](https://github.com/helix-editor/helix/pull/10014))
- Highlight type parameters in Rust ([#8660](https://github.com/helix-editor/helix/pull/8660))
- Change KDL tree-sitter parsers ([#8652](https://github.com/helix-editor/helix/pull/8652))
- Update tree-sitter-markdown ([#8721](https://github.com/helix-editor/helix/pull/8721), [#10039](https://github.com/helix-editor/helix/pull/10039))
- Update tree-sitter-purescript ([#8712](https://github.com/helix-editor/helix/pull/8712))
- Add type parameter highlighting to TypeScript, Go, Haskell, OCaml and Kotlin ([#8718](https://github.com/helix-editor/helix/pull/8718))
- Add indentation queries for Scheme and lisps using tree-sitter-scheme ([#8720](https://github.com/helix-editor/helix/pull/8720))
- Recognize `meson_options.txt` as Meson ([#8794](https://github.com/helix-editor/helix/pull/8794))
- Add language server configuration for Nushell ([#8878](https://github.com/helix-editor/helix/pull/8878))
- Recognize `musicxml` as XML ([#8935](https://github.com/helix-editor/helix/pull/8935))
- Update tree-sitter-rescript ([#8962](https://github.com/helix-editor/helix/pull/8962))
- Update tree-sitter-python ([#8976](https://github.com/helix-editor/helix/pull/8976))
- Recognize `.envrc.local` and `.envrc.private` as env ([#8988](https://github.com/helix-editor/helix/pull/8988))
- Update tree-sitter-gleam ([#9003](https://github.com/helix-editor/helix/pull/9003), [9ceeea5](https://github.com/helix-editor/helix/commit/9ceeea5))
- Update tree-sitter-d ([#9021](https://github.com/helix-editor/helix/pull/9021))
- Fix R-markdown language name for LSP detection ([#9012](https://github.com/helix-editor/helix/pull/9012))
- Add haskell-language-server LSP configuration ([#9111](https://github.com/helix-editor/helix/pull/9111))
- Recognize `glif` as XML ([#9130](https://github.com/helix-editor/helix/pull/9130))
- Recognize `.prettierrc` as JSON ([#9214](https://github.com/helix-editor/helix/pull/9214))
- Add auto-pairs configuration for scheme ([#9232](https://github.com/helix-editor/helix/pull/9232))
- Add textobject queries for Scala ([#9191](https://github.com/helix-editor/helix/pull/9191))
- Add textobject queries for Protobuf ([#9184](https://github.com/helix-editor/helix/pull/9184))
- Update tree-sitter-wren ([#8544](https://github.com/helix-editor/helix/pull/8544))
- Add `spago.yaml` as an LSP root for PureScript ([#9362](https://github.com/helix-editor/helix/pull/9362))
- Improve highlight and indent queries for Bash, Make and CSS ([#9393](https://github.com/helix-editor/helix/pull/9393))
- Update tree-sitter-scala ([#9348](https://github.com/helix-editor/helix/pull/9348), [#9340](https://github.com/helix-editor/helix/pull/9340), [#9475](https://github.com/helix-editor/helix/pull/9475))
- Recognize `.bash_history` as Bash ([#9401](https://github.com/helix-editor/helix/pull/9401))
- Recognize Helix ignore files as ignore ([#9447](https://github.com/helix-editor/helix/pull/9447))
- Inject SQL into Scala SQL strings ([#9428](https://github.com/helix-editor/helix/pull/9428))
- Update gdscript textobjects ([#9288](https://github.com/helix-editor/helix/pull/9288))
- Update Go queries ([#9510](https://github.com/helix-editor/helix/pull/9510), [#9525](https://github.com/helix-editor/helix/pull/9525))
- Update tree-sitter-nushell ([#9502](https://github.com/helix-editor/helix/pull/9502))
- Update tree-sitter-unison, add indent queries ([#9505](https://github.com/helix-editor/helix/pull/9505))
- Update tree-sitter-slint ([#9551](https://github.com/helix-editor/helix/pull/9551), [#9698](https://github.com/helix-editor/helix/pull/9698))
- Update tree-sitter-swift ([#9586](https://github.com/helix-editor/helix/pull/9586))
- Add `fish_indent` as formatter for fish ([78ed3ad](https://github.com/helix-editor/helix/commit/78ed3ad))
- Recognize `zon` as Zig ([#9582](https://github.com/helix-editor/helix/pull/9582))
- Add a formatter for Odin ([#9537](https://github.com/helix-editor/helix/pull/9537))
- Update tree-sitter-erlang ([#9627](https://github.com/helix-editor/helix/pull/9627), [fdcd461](https://github.com/helix-editor/helix/commit/fdcd461))
- Capture Rust fields as argument textobjects ([#9637](https://github.com/helix-editor/helix/pull/9637))
- Improve Dart textobjects ([#9644](https://github.com/helix-editor/helix/pull/9644))
- Recognize `tmux.conf` as a bash file-type ([#9653](https://github.com/helix-editor/helix/pull/9653))
- Add textobjects queries for Nix ([#9659](https://github.com/helix-editor/helix/pull/9659))
- Add textobjects queries for HCL ([#9658](https://github.com/helix-editor/helix/pull/9658))
- Recognize osm and osc extensions as XML ([#9697](https://github.com/helix-editor/helix/pull/9697))
- Update tree-sitter-sql ([#9634](https://github.com/helix-editor/helix/pull/9634))
- Recognize pde Processing files as Java ([#9741](https://github.com/helix-editor/helix/pull/9741))
- Update tree-sitter-lua ([#9727](https://github.com/helix-editor/helix/pull/9727))
- Switch tree-sitter-nim parsers ([#9722](https://github.com/helix-editor/helix/pull/9722))
- Recognize GTK builder ui files as XML ([#9754](https://github.com/helix-editor/helix/pull/9754))
- Add configuration for markdown-oxide language server ([#9758](https://github.com/helix-editor/helix/pull/9758))
- Add a shebang for elvish ([#9779](https://github.com/helix-editor/helix/pull/9779))
- Fix precedence of Svelte TypeScript injection ([#9777](https://github.com/helix-editor/helix/pull/9777))
- Recognize common Dockerfile file types ([#9772](https://github.com/helix-editor/helix/pull/9772))
- Recognize NUON files as Nu ([#9839](https://github.com/helix-editor/helix/pull/9839))
- Add textobjects for Java native functions and constructors ([#9806](https://github.com/helix-editor/helix/pull/9806))
- Fix "braket" typeo in JSX highlights ([#9910](https://github.com/helix-editor/helix/pull/9910))
- Update tree-sitter-hurl ([#9775](https://github.com/helix-editor/helix/pull/9775))
- Add textobjects queries for Vala ([#8541](https://github.com/helix-editor/helix/pull/8541))
- Update tree-sitter-git-config ([9610254](https://github.com/helix-editor/helix/commit/9610254))
- Recognize 'mmd' as Mermaid ([459eb9a](https://github.com/helix-editor/helix/commit/459eb9a))
- Highlight Rust extern crate aliases ([c099dde](https://github.com/helix-editor/helix/commit/c099dde))
- Improve parameter highlighting in C++ ([f5d95de](https://github.com/helix-editor/helix/commit/f5d95de))
- Recognize 'rclone.conf' as INI ([#9959](https://github.com/helix-editor/helix/pull/9959))
- Add injections for GraphQL and ERB in Ruby heredocs ([#10036](https://github.com/helix-editor/helix/pull/10036))
- Add `main.odin` to Odin LSP roots ([#9968](https://github.com/helix-editor/helix/pull/9968))
Packaging:
- Allow user overlays in Nix grammars build ([#8749](https://github.com/helix-editor/helix/pull/8749))
- Set Cargo feature resolver to v2 ([#8917](https://github.com/helix-editor/helix/pull/8917))
- Use workspace inheritance for common Cargo metadata ([#8925](https://github.com/helix-editor/helix/pull/8925))
- Remove sourcehut-based tree-sitter grammars from default build ([#9316](https://github.com/helix-editor/helix/pull/9316), [#9326](https://github.com/helix-editor/helix/pull/9326))
- Add icon to Windows executable ([#9104](https://github.com/helix-editor/helix/pull/9104))
# 23.10 (2023-10-24)
A big shout out to all the contributors! We had 118 contributors in this release.
Breaking changes:
- Support multiple language servers per language ([#2507](https://github.com/helix-editor/helix/pull/2507))
- This is a breaking change to language configuration
Features:
- Support multiple language servers per language ([#2507](https://github.com/helix-editor/helix/pull/2507), [#7082](https://github.com/helix-editor/helix/pull/7082), [#7286](https://github.com/helix-editor/helix/pull/7286), [#8374](https://github.com/helix-editor/helix/pull/8374))
- Add a statusline element for the selected register ([#7222](https://github.com/helix-editor/helix/pull/7222))
- Add `%`, `#`, `.`, `*` and `+` special registers ([#6985](https://github.com/helix-editor/helix/pull/6985))
- Add initial support for LSP DidChangeWatchedFiles notifications ([#7665](https://github.com/helix-editor/helix/pull/7665))
- Search buffer contents in `global_search` ([#5652](https://github.com/helix-editor/helix/pull/5652))
- Add a "smart tab" command that intelligently jumps the cursor on tab ([#4443](https://github.com/helix-editor/helix/pull/4443))
- Add a statusline element for whether a file is read-only ([#7222](https://github.com/helix-editor/helix/pull/7222), [#7875](https://github.com/helix-editor/helix/pull/7875))
- Syntax highlight regex prompts ([#7738](https://github.com/helix-editor/helix/pull/7738))
- Allow defining alignment in indent queries ([#5355](https://github.com/helix-editor/helix/pull/5355))
- Show visual feedback in `surround_replace` ([#7588](https://github.com/helix-editor/helix/pull/7588))
- Switch to Nucleo for fuzzy matching ([#7814](https://github.com/helix-editor/helix/pull/7814), [#8148](https://github.com/helix-editor/helix/pull/8148), [#8192](https://github.com/helix-editor/helix/pull/8192), [#8194](https://github.com/helix-editor/helix/pull/8194))
- Insert a trailing newline on write ([#8157](https://github.com/helix-editor/helix/pull/8157))
- Add a `-w`/`--working-dir` CLI flag for specifying a working directory on startup ([#8223](https://github.com/helix-editor/helix/pull/8223), [#8498](https://github.com/helix-editor/helix/pull/8498), [#8520](https://github.com/helix-editor/helix/pull/8520))
- Accept a `+N` CLI argument to set the first file's line number ([#8521](https://github.com/helix-editor/helix/pull/8521))
- Accept Helix-specific ignore files in `.helix/ignore` and `~/.config/helix/ignore` ([#8099](https://github.com/helix-editor/helix/pull/8099))
Commands:
- `merge_selections` (`A-minus`) - merge all selections into one selection that covers all ranges ([#7053](https://github.com/helix-editor/helix/pull/7053))
- `move_prev_long_word_end` and `extend_prev_long_word_end` - move/extend to the end of the previous WORD ([#6905](https://github.com/helix-editor/helix/pull/6905))
- `reverse_selection_contents` - swaps the values of each selection so they are reversed ([#7329](https://github.com/helix-editor/helix/pull/7329))
- Add `:rl` and `:rla` aliases for `:reload` and `:reload-all` ([#7158](https://github.com/helix-editor/helix/pull/7158))
- `yank_joined` - join the selections and yank to the selected register ([#7195](https://github.com/helix-editor/helix/pull/7195))
- `:write-all!` (`:wa!`) - forcibly write all buffers to disk and create any necessary subdirectories ([#7577](https://github.com/helix-editor/helix/pull/7577))
- `:redraw` - clear re-render the UI ([#6949](https://github.com/helix-editor/helix/pull/6949))
- `:tree-sitter-highlight-name` - show the theme scope name of the highlight under the cursor ([#8170](https://github.com/helix-editor/helix/pull/8170))
Usability improvements:
- Allow cycling option values at runtime ([#4411](https://github.com/helix-editor/helix/pull/4411), [#7240](https://github.com/helix-editor/helix/pull/7240), [#7877](https://github.com/helix-editor/helix/pull/7877))
- Exit gracefully on termination signals ([#7236](https://github.com/helix-editor/helix/pull/7236))
- Add plaintext matching fallback to tree-sitter pair matching ([#4288](https://github.com/helix-editor/helix/pull/4288))
- Persist register selection in pending keymaps ([0e08349](https://github.com/helix-editor/helix/commit/0e08349))
- Propagate the count and register to command palette commands ([b394997](https://github.com/helix-editor/helix/commit/b394997))
- Auto indent on `insert_at_line_start` ([#5837](https://github.com/helix-editor/helix/pull/5837))
- Add a config option to control whether LSP completions are automatically inserted on preview ([#7189](https://github.com/helix-editor/helix/pull/7189))
- Add a config option for default line endings ([#5621](https://github.com/helix-editor/helix/pull/5621), [#7357](https://github.com/helix-editor/helix/pull/7357))
- Allow ANSI colors in themes ([#5119](https://github.com/helix-editor/helix/pull/5119))
- Match pairs that don't form a standalone tree-sitter node ([#7242](https://github.com/helix-editor/helix/pull/7242))
- Allow indent sizes of up to 16 columns ([#7429](https://github.com/helix-editor/helix/pull/7429))
- Improve performance of mapping positions through changes ([#7408](https://github.com/helix-editor/helix/pull/7408), [8d39a81](https://github.com/helix-editor/helix/commit/8d39a81), [#7471](https://github.com/helix-editor/helix/pull/7471))
- Mark buffers created from stdin as modified ([#7431](https://github.com/helix-editor/helix/pull/7431))
- Forcibly shut down uninitialized language servers ([#7449](https://github.com/helix-editor/helix/pull/7449))
- Add filename completer for shell prompts ([#7569](https://github.com/helix-editor/helix/pull/7569))
- Allow binding F13-F24 ([#7672](https://github.com/helix-editor/helix/pull/7672))
- Resolve LSP code actions ([#7677](https://github.com/helix-editor/helix/pull/7677), [#8421](https://github.com/helix-editor/helix/pull/8421))
- Save an undo checkpoint before accepting completions ([#7747](https://github.com/helix-editor/helix/pull/7747))
- Include gitignored files in debugger completions ([#7936](https://github.com/helix-editor/helix/pull/7936))
- Make editor remember the last search register ([#5244](https://github.com/helix-editor/helix/pull/5244))
- Open directories with `goto_file` ([#7909](https://github.com/helix-editor/helix/pull/7909))
- Use relative path to open buffer in `goto_file` (`gf`) ([#7965](https://github.com/helix-editor/helix/pull/7965))
- Support `default` color in themes ([#8083](https://github.com/helix-editor/helix/pull/8083), [#8114](https://github.com/helix-editor/helix/pull/8114))
- Toggle between relative and absolute line numbers when the terminal loses focus ([#7955](https://github.com/helix-editor/helix/pull/7955))
- Lower default idle-timeout to 250ms ([060e73a](https://github.com/helix-editor/helix/commit/060e73a))
- Allow theming diff gutters separately from other diff colors ([#8343](https://github.com/helix-editor/helix/pull/8343))
- Style bold/italic/strikethrough in markdown doc popups ([#8385](https://github.com/helix-editor/helix/pull/8385))
- Maintain the cursor position and view when splitting with `:hsplit`/`:vsplit` ([#8109](https://github.com/helix-editor/helix/pull/8109))
- Accept `-` in macros outside of `<`/`>` ([#8475](https://github.com/helix-editor/helix/pull/8475))
- Show all language servers for each language in `--health` ([#7315](https://github.com/helix-editor/helix/pull/7315))
- Don't break on hyphens in `:reflow` ([#8569](https://github.com/helix-editor/helix/pull/8569))
Fixes:
- Update diagnostics correctly on language server exit ([#7111](https://github.com/helix-editor/helix/pull/7111))
- Fix off-by-one in `select_references_to_symbol_under_cursor` ([#7132](https://github.com/helix-editor/helix/pull/7132))
- Extend selection with repeat-last-motion only if the original motion extended the selection ([#7159](https://github.com/helix-editor/helix/pull/7159))
- Fix undefined behavior in the diff gutter ([#7227](https://github.com/helix-editor/helix/pull/7227))
- Check that tab width is non-zero ([#7178](https://github.com/helix-editor/helix/pull/7178))
- Fix styles being overwritten in table rows with multiple cells ([#7281](https://github.com/helix-editor/helix/pull/7281))
- Add file for `--log` CLI arg in help text ([#7307](https://github.com/helix-editor/helix/pull/7307))
- Fix underflow when repeating a completion that has a negative shift position ([#7322](https://github.com/helix-editor/helix/pull/7322))
- Prefer longer matches in `select_next_sibling` and `select_prev_sibling` ([#7332](https://github.com/helix-editor/helix/pull/7332))
- Preview scratch buffers in the jumplist picker ([#7331](https://github.com/helix-editor/helix/pull/7331))
- Fix chunking by bytes in tree-sitter parsing ([#7417](https://github.com/helix-editor/helix/pull/7417))
- Discard LSP publishDiagnostic from uninitialized servers ([#7467](https://github.com/helix-editor/helix/pull/7467))
- Use negotiated position encoding for LSP workspace edits ([#7469](https://github.com/helix-editor/helix/pull/7469))
- Fix error message for unknown gutter types in config ([#7534](https://github.com/helix-editor/helix/pull/7534))
- Fix `:log-open` when `--log` CLI arg is specified ([#7573](https://github.com/helix-editor/helix/pull/7573), [#7585](https://github.com/helix-editor/helix/pull/7585))
- Fix debouncing of LSP messages to fix the last message sticking around ([#7538](https://github.com/helix-editor/helix/pull/7538), [#8023](https://github.com/helix-editor/helix/pull/8023))
- Fix crash when the current working directory is deleted ([#7185](https://github.com/helix-editor/helix/pull/7185))
- Fix piping to Helix on macOS ([#5468](https://github.com/helix-editor/helix/pull/5468))
- Fix crash when parsing overlapping injections ([#7621](https://github.com/helix-editor/helix/pull/7621))
- Clear the statusline when the prompt is visible ([#7646](https://github.com/helix-editor/helix/pull/7646))
- Fix range formatting error message typo ([#7823](https://github.com/helix-editor/helix/pull/7823))
- Skip rendering gutters when gutter width exceeds view width ([#7821](https://github.com/helix-editor/helix/pull/7821))
- Center the picker preview using visual lines ([#7837](https://github.com/helix-editor/helix/pull/7837))
- Align view correctly for background buffers opened with `A-ret` ([#7691](https://github.com/helix-editor/helix/pull/7691))
- Fix cursor resetting to block when quitting via a keybind ([#7931](https://github.com/helix-editor/helix/pull/7931))
- Remove path completions for the `:new` command ([#8010](https://github.com/helix-editor/helix/pull/8010))
- Use binary path resolved by `which` for formatter commands ([#8064](https://github.com/helix-editor/helix/pull/8064))
- Handle crossterm's `hidden` modifier ([#8120](https://github.com/helix-editor/helix/pull/8120))
- Clear completion when switching between windows with the mouse ([#8118](https://github.com/helix-editor/helix/pull/8118))
- Eagerly remove the last picker (`<space>'`) when the picker has many items ([#8127](https://github.com/helix-editor/helix/pull/8127))
- Fix find commands for buffers with non-LF line-endings ([#8111](https://github.com/helix-editor/helix/pull/8111))
- Detect the tmux clipboard provider on macOS ([#8182](https://github.com/helix-editor/helix/pull/8182))
- Fix syntax highlighting in dynamic picker preview pane ([#8206](https://github.com/helix-editor/helix/pull/8206))
- Recognize HTML code tags with attributes as code in markdown previews ([#8397](https://github.com/helix-editor/helix/pull/8397))
- Fix multicursor snippet placeholder directions ([#8423](https://github.com/helix-editor/helix/pull/8423))
- Only show diagnostic highlights when diagnostics are enabled for a language server ([#8551](https://github.com/helix-editor/helix/pull/8551))
Themes:
- Improve the selection color in `ferra` ([#7138](https://github.com/helix-editor/helix/pull/7138))
- Add `variable.other.member` theming to `spacebones_light` ([#7125](https://github.com/helix-editor/helix/pull/7125))
- Update `autumn` and theme the soft-wrap indicator ([#7229](https://github.com/helix-editor/helix/pull/7229))
- Add `gruvbox_dark_soft` ([#7139](https://github.com/helix-editor/helix/pull/7139))
- Add `merionette` ([#7186](https://github.com/helix-editor/helix/pull/7186))
- Add `zed_onedark` and `zed_onelight` ([#7250](https://github.com/helix-editor/helix/pull/7250))
- Use light-gray for `onedarker` inlay hint theming ([#7433](https://github.com/helix-editor/helix/pull/7433))
- Update the Nord theme to follow the style guidelines ([#7490](https://github.com/helix-editor/helix/pull/7490))
- Tune `dark_plus` inlay hint colors ([#7611](https://github.com/helix-editor/helix/pull/7611))
- Add `naysayer` ([#7570](https://github.com/helix-editor/helix/pull/7570))
- Add `kaolin-dark`, `kaolin-light` and `kaolin-valley-dark` ([#7151](https://github.com/helix-editor/helix/pull/7151))
- Fix selection highlighting in gruvbox variants ([#7717](https://github.com/helix-editor/helix/pull/7717))
- Add soft-wrap indicator to `gruvbox` ([#7736](https://github.com/helix-editor/helix/pull/7736))
- Add missing palette definitions in `everforest_dark` ([#7739](https://github.com/helix-editor/helix/pull/7739))
- Increase diagnostics clarity in `pop-dark` ([#7702](https://github.com/helix-editor/helix/pull/7702))
- Add `vim_dark_high_contrast` ([#7785](https://github.com/helix-editor/helix/pull/7785))
- Add `new_moon` ([#7834](https://github.com/helix-editor/helix/pull/7834))
- Add `yellowed` ([#7849](https://github.com/helix-editor/helix/pull/7849))
- Improve comment readability for `autumn` ([#7939](https://github.com/helix-editor/helix/pull/7939))
- Distinguish active bufferline buffer in `monokai` ([#7983](https://github.com/helix-editor/helix/pull/7983))
- Update ruler colors in `nord` ([#7995](https://github.com/helix-editor/helix/pull/7995))
- Update Catppuccin themes ([#8102](https://github.com/helix-editor/helix/pull/8102))
- Add text focus scope and diagnostics undercurls for `nord` ([#8165](https://github.com/helix-editor/helix/pull/8165))
- Add material theme collection ([#8211](https://github.com/helix-editor/helix/pull/8211))
- Improve indent line color in `dracula` ([#8266](https://github.com/helix-editor/helix/pull/8266))
- Clean up and refactor `papercolor` to use inheritance ([#8276](https://github.com/helix-editor/helix/pull/8276))
- Fix `zenburn` inlay hint color ([#8278](https://github.com/helix-editor/helix/pull/8278)a)
- Fix picker crash when previewing an invalid range ([e9d0bd7](https://github.com/helix-editor/helix/commit/e9d0bd7))
- Correctly center items in the picker preview ([13d4463](https://github.com/helix-editor/helix/commit/13d4463))
- Add `cyan_light` ([#8293](https://github.com/helix-editor/helix/pull/8293), [#8587](https://github.com/helix-editor/helix/pull/8587))
- Theme HTML tags in `onedark` ([#8409](https://github.com/helix-editor/helix/pull/8409))
- Refine `darcula` and `darcula-solid` themes ([#8412](https://github.com/helix-editor/helix/pull/8412))
- Improve `nord` highlights ([#8414](https://github.com/helix-editor/helix/pull/8414))
- Add `nord-night` ([#8549](https://github.com/helix-editor/helix/pull/8549))
New languages:
- Blueprint ([#7213](https://github.com/helix-editor/helix/pull/7213), [#8161](https://github.com/helix-editor/helix/pull/8161))
- Forth ([#7256](https://github.com/helix-editor/helix/pull/7256), [#7334](https://github.com/helix-editor/helix/pull/7334))
- t32 ([#7140](https://github.com/helix-editor/helix/pull/7140), [#7811](https://github.com/helix-editor/helix/pull/7811))
- WebC ([#7290](https://github.com/helix-editor/helix/pull/7290))
- Persistent DSL for Haskell ([#7261](https://github.com/helix-editor/helix/pull/7261))
- F# ([#7619](https://github.com/helix-editor/helix/pull/7619), [#8024](https://github.com/helix-editor/helix/pull/8024))
- Wren ([#7765](https://github.com/helix-editor/helix/pull/7765), [#7819](https://github.com/helix-editor/helix/pull/7819))
- Unison ([#7724](https://github.com/helix-editor/helix/pull/7724))
- Todo.txt ([#7835](https://github.com/helix-editor/helix/pull/7835))
- Jinja and Handlebars ([#7233](https://github.com/helix-editor/helix/pull/7233))
- Pod ([#7907](https://github.com/helix-editor/helix/pull/7907))
- Strace ([#7928](https://github.com/helix-editor/helix/pull/7928))
- Gemini ([#8070](https://github.com/helix-editor/helix/pull/8070))
- GNU Assembler (GAS) ([#8291](https://github.com/helix-editor/helix/pull/8291))
- JSON5 ([#8473](https://github.com/helix-editor/helix/pull/8473))
- TEMPL ([#8540](https://github.com/helix-editor/helix/pull/8540))
Updated languages and queries:
- Add one to the ruler numbers for git-commit ([#7072](https://github.com/helix-editor/helix/pull/7072))
- Recognize XAML files as XML ([#7083](https://github.com/helix-editor/helix/pull/7083))
- Recognize `Cargo.lock` as TOML ([#7095](https://github.com/helix-editor/helix/pull/7095))
- Use Rust grammar for Cairo ([c6d1430](https://github.com/helix-editor/helix/commit/c6d1430))
- Update tree-sitter-nickel ([#7059](https://github.com/helix-editor/helix/pull/7059), [#7551](https://github.com/helix-editor/helix/pull/7551))
- Tune auto-pair characters for Nickel ([#7059](https://github.com/helix-editor/helix/pull/7059))
- Recognize `Vagrantfile` as Ruby ([#7112](https://github.com/helix-editor/helix/pull/7112))
- Recognize hidden justfiles as Just ([#7088](https://github.com/helix-editor/helix/pull/7088))
- Update Java and TypeScript highlight queries ([#7145](https://github.com/helix-editor/helix/pull/7145))
- Recognize `.zimrc` as Bash ([#7146](https://github.com/helix-editor/helix/pull/7146))
- Recognize `.gir` as XML ([#7152](https://github.com/helix-editor/helix/pull/7152))
- Update tree-sitter-scala ([#7147](https://github.com/helix-editor/helix/pull/7147))
- Recognize make file-type as Makefile ([#7212](https://github.com/helix-editor/helix/pull/7212))
- Update tree-sitter-verilog ([#7262](https://github.com/helix-editor/helix/pull/7262))
- Update tree-sitter-cpp ([#7285](https://github.com/helix-editor/helix/pull/7285))
- Support core mode for delve debugger ([#7300](https://github.com/helix-editor/helix/pull/7300))
- Add Fortran comment injections ([#7305](https://github.com/helix-editor/helix/pull/7305))
- Switch Vue language server to `vue-language-server` ([#7312](https://github.com/helix-editor/helix/pull/7312))
- Update tree-sitter-sql ([#7387](https://github.com/helix-editor/helix/pull/7387), [#8464](https://github.com/helix-editor/helix/pull/8464))
- Replace the MATLAB tre-sitter grammar ([#7388](https://github.com/helix-editor/helix/pull/7388), [#7442](https://github.com/helix-editor/helix/pull/7442), [#7491](https://github.com/helix-editor/helix/pull/7491), [#7493](https://github.com/helix-editor/helix/pull/7493), [#7511](https://github.com/helix-editor/helix/pull/7511), [#7532](https://github.com/helix-editor/helix/pull/7532), [#8040](https://github.com/helix-editor/helix/pull/8040))
- Highlight TOML table headers ([#7441](https://github.com/helix-editor/helix/pull/7441))
- Recognize `cppm` file-type as C++ ([#7492](https://github.com/helix-editor/helix/pull/7492))
- Refactor ecma language queries into private and public queries ([#7207](https://github.com/helix-editor/helix/pull/7207))
- Update tree-sitter-dart ([#7576](https://github.com/helix-editor/helix/pull/7576))
- Add shebang for nushell files ([#7606](https://github.com/helix-editor/helix/pull/7606))
- Recognize systemd files as INI ([#7592](https://github.com/helix-editor/helix/pull/7592))
- Update TypeScript, TSX and Svelte grammars ([#6874](https://github.com/helix-editor/helix/pull/6874))
- Enable inlay hints in the Svelte language server ([#7622](https://github.com/helix-editor/helix/pull/7622))
- Recognize `Brewfile`s as Ruby ([#7629](https://github.com/helix-editor/helix/pull/7629))
- Add more file-types for R ([#7633](https://github.com/helix-editor/helix/pull/7633))
- Switch tree-sitter-perl to official upstream parser ([#7644](https://github.com/helix-editor/helix/pull/7644), [#7947](https://github.com/helix-editor/helix/pull/7947))
- Fix predicate typo in comment highlights ([#7732](https://github.com/helix-editor/helix/pull/7732))
- Update tree-sitter-prql ([#7771](https://github.com/helix-editor/helix/pull/7771))
- Recognize `.gitf` as JSON ([#7781](https://github.com/helix-editor/helix/pull/7781))
- Switch V language server to `v-analyzer` ([#7760](https://github.com/helix-editor/helix/pull/7760))
- Add protobuf language servers ([#7796](https://github.com/helix-editor/helix/pull/7796))
- Update tree-sitter-zig ([#7803](https://github.com/helix-editor/helix/pull/7803))
- Update tree-sitter-hare ([#7784](https://github.com/helix-editor/helix/pull/7784))
- Add Java indent queries ([#7844](https://github.com/helix-editor/helix/pull/7844))
- Update tree-sitter-scheme ([979933b](https://github.com/helix-editor/helix/commit/979933b))
- Recognize `scm` as Scheme instead of TSQ ([5707151](https://github.com/helix-editor/helix/commit/5707151))
- Update tree-sitter-git-commit ([#7831](https://github.com/helix-editor/helix/pull/7831))
- Update JavaScript, TypeScript and TSX grammars ([#7852](https://github.com/helix-editor/helix/pull/7852))
- Update tree-sitter-nu ([#7873](https://github.com/helix-editor/helix/pull/7873))
- Fix YAML indentation ([#6768](https://github.com/helix-editor/helix/pull/6768))
- Add `csharp-ls`, Pyright, Pylyzer and add roots for Python ([#7897](https://github.com/helix-editor/helix/pull/7897), [#8032](https://github.com/helix-editor/helix/pull/8032))
- Update tree-sitter-slint ([#7893](https://github.com/helix-editor/helix/pull/7893))
- Recognize more ZSH file-types as Bash ([#7930](https://github.com/helix-editor/helix/pull/7930))
- Recognize `star` extension as Starlark ([#7922](https://github.com/helix-editor/helix/pull/7922))
- Fix inline HTML tag highlighting in markdown ([#7960](https://github.com/helix-editor/helix/pull/7960))
- Update tree-sitter-robot ([#7970](https://github.com/helix-editor/helix/pull/7970))
- Highlight Dart 3 `sealed` and `base` keywords ([#7974](https://github.com/helix-editor/helix/pull/7974))
- Add configuration for `ltex-ls` to the default `languages.toml` ([#7838](https://github.com/helix-editor/helix/pull/7838))
- Update tree-sitter-strace ([#8087](https://github.com/helix-editor/helix/pull/8087))
- Update tree-sitter-gleam, enable auto-format ([#8085](https://github.com/helix-editor/helix/pull/8085))
- Update tree-sitter-esdl ([#8222](https://github.com/helix-editor/helix/pull/8222))
- Expand ignore file-types ([#8220](https://github.com/helix-editor/helix/pull/8220))
- Recognize feed related formats as XML ([#8232](https://github.com/helix-editor/helix/pull/8232))
- Improve YAML injections ([#8217](https://github.com/helix-editor/helix/pull/8217))
- Add shebangs for TypeScript, Julia, Java and OCaml ([95e994a](https://github.com/helix-editor/helix/commit/95e994a))
- Highlight abbreviations in Scheme ([ef23847](https://github.com/helix-editor/helix/commit/ef23847))
- Remove backtic auto-pair in OCaml ([#8260](https://github.com/helix-editor/helix/pull/8260))
- Recognize `flake.lock` as JSON ([#8304](https://github.com/helix-editor/helix/pull/8304))
- Add Python test script injection for Nix ([b4494e1](https://github.com/helix-editor/helix/commit/b4494e1))
- Fix Nix comment injection precedence ([37e48f4](https://github.com/helix-editor/helix/commit/37e48f4))
- Recognize editorconfig files as INI ([#8308](https://github.com/helix-editor/helix/pull/8308))
- Recognize `.babelrc` as JSON ([#8309](https://github.com/helix-editor/helix/pull/8309))
- Switch Purescript to its own tree-sitter parser ([#8306](https://github.com/helix-editor/helix/pull/8306), [#8338](https://github.com/helix-editor/helix/pull/8338), [#8527](https://github.com/helix-editor/helix/pull/8527))
- Update Unison highlights ([#8315](https://github.com/helix-editor/helix/pull/8315))
- Recognize `.webmanifest` as JSON ([#8342](https://github.com/helix-editor/helix/pull/8342))
- Recognize polkit policy files as XML ([#8369](https://github.com/helix-editor/helix/pull/8369))
- Recognize polkit rules files as JavaScript ([#8370](https://github.com/helix-editor/helix/pull/8370))
- Update Go highlight queries ([#8399](https://github.com/helix-editor/helix/pull/8399))
- Add shebangs for Makefiles ([#8410](https://github.com/helix-editor/helix/pull/8410))
- Add file-type associations from VSCode ([#8388](https://github.com/helix-editor/helix/pull/8388))
- Add validation to JSON/CSS language server configs ([#8433](https://github.com/helix-editor/helix/pull/8433))
- Add a configuration for the tailwind language server ([#8442](https://github.com/helix-editor/helix/pull/8442))
- Add a configuration for the ansible language server ([#7973](https://github.com/helix-editor/helix/pull/7973))
- Add a configuration for the GraphQL language server ([#8492](https://github.com/helix-editor/helix/pull/8492))
- Indent while statements in Bash ([#8528](https://github.com/helix-editor/helix/pull/8528))
- Update tree-sitter-haskell and queries ([#8558](https://github.com/helix-editor/helix/pull/8558))
Packaging:
- Add an overlay to the Nix flake ([#7078](https://github.com/helix-editor/helix/pull/7078))
- Check for `git` before fetching or building grammars ([#7320](https://github.com/helix-editor/helix/pull/7320))
- Refactor Nix flake to use Crane ([#7763](https://github.com/helix-editor/helix/pull/7763))
- Remove the aarch64 appimage from the release CI ([#7832](https://github.com/helix-editor/helix/pull/7832))
- Add desktop and icon files to Nix flake output ([#7979](https://github.com/helix-editor/helix/pull/7979))
- Build flake packages with the latest stable Rust ([#8133](https://github.com/helix-editor/helix/pull/8133))
# 23.05 (2023-05-18)
23.05 is a smaller release focusing on fixes. There were 88 contributors in this release. Thank you all!
Features:
- Add a config option to exclude declaration from LSP references request ([#6886](https://github.com/helix-editor/helix/pull/6886))
- Enable injecting languages based on their file extension and shebang ([#3970](https://github.com/helix-editor/helix/pull/3970))
- Sort the buffer picker by most recent access ([#2980](https://github.com/helix-editor/helix/pull/2980))
- Perform syntax highlighting in the picker asynchronously ([#7028](https://github.com/helix-editor/helix/pull/7028))
Commands:
- `:update` is now aliased as `:u` ([#6835](https://github.com/helix-editor/helix/pull/6835))
- Add `extend_to_first_nonwhitespace` which acts the same as `goto_first_nonwhitespace` but always extends ([#6837](https://github.com/helix-editor/helix/pull/6837))
- Add `:clear-register` for clearing the given register or all registers ([#5695](https://github.com/helix-editor/helix/pull/5695))
- Add `:write-buffer-close` and `:write-buffer-close!` ([#6947](https://github.com/helix-editor/helix/pull/6947))
Fixes:
- Normalize LSP workspace paths ([#6517](https://github.com/helix-editor/helix/pull/6517))
- Robustly handle invalid LSP ranges ([#6512](https://github.com/helix-editor/helix/pull/6512))
- Fix line number display for LSP goto pickers ([#6559](https://github.com/helix-editor/helix/pull/6559))
- Fix toggling of `soft-wrap.enable` option ([#6656](https://github.com/helix-editor/helix/pull/6656), [58e457a](https://github.com/helix-editor/helix/commit/58e457a), [#6742](https://github.com/helix-editor/helix/pull/6742))
- Handle `workspace/configuration` requests from stopped language servers ([#6693](https://github.com/helix-editor/helix/pull/6693))
- Fix possible crash from opening the jumplist picker ([#6672](https://github.com/helix-editor/helix/pull/6672))
- Fix theme preview returning to current theme on line and word deletions ([#6694](https://github.com/helix-editor/helix/pull/6694))
- Re-run crate build scripts on changes to revision and grammar repositories ([#6743](https://github.com/helix-editor/helix/pull/6743))
- Fix crash on opening from suspended state ([#6764](https://github.com/helix-editor/helix/pull/6764))
- Fix unwrap bug in DAP ([#6786](https://github.com/helix-editor/helix/pull/6786))
- Always build tree-sitter parsers with C++14 and C11 ([#6792](https://github.com/helix-editor/helix/pull/6792), [#6834](https://github.com/helix-editor/helix/pull/6834), [#6845](https://github.com/helix-editor/helix/pull/6845))
- Exit with a non-zero statuscode when tree-sitter parser builds fail ([#6795](https://github.com/helix-editor/helix/pull/6795))
- Flip symbol range in LSP goto commands ([#6794](https://github.com/helix-editor/helix/pull/6794))
- Fix runtime toggling of the `mouse` option ([#6675](https://github.com/helix-editor/helix/pull/6675))
- Fix panic in inlay hint computation when view anchor is out of bounds ([#6883](https://github.com/helix-editor/helix/pull/6883))
- Significantly improve performance of git discovery on slow file systems ([#6890](https://github.com/helix-editor/helix/pull/6890))
- Downgrade gix log level to info ([#6915](https://github.com/helix-editor/helix/pull/6915))
- Conserve BOM and properly support saving UTF16 files ([#6497](https://github.com/helix-editor/helix/pull/6497))
- Correctly handle completion re-request ([#6594](https://github.com/helix-editor/helix/pull/6594))
- Fix offset encoding in LSP `didChange` notifications ([#6921](https://github.com/helix-editor/helix/pull/6921))
- Change `gix` logging level to info ([#6915](https://github.com/helix-editor/helix/pull/6915))
- Improve error message when writes fail because parent directories do not exist ([#7014](https://github.com/helix-editor/helix/pull/7014))
- Replace DAP variables popup instead of pushing more popups ([#7034](https://github.com/helix-editor/helix/pull/7034))
- Disable tree-sitter for files after parsing for 500ms ([#7028](https://github.com/helix-editor/helix/pull/7028))
- Fix crash when deleting with multiple cursors ([#6024](https://github.com/helix-editor/helix/pull/6024))
- Fix selection sliding when deleting forwards in append mode ([#6024](https://github.com/helix-editor/helix/pull/6024))
- Fix completion on paths containing spaces ([#6779](https://github.com/helix-editor/helix/pull/6779))
Themes:
- Style inlay hints in `dracula` theme ([#6515](https://github.com/helix-editor/helix/pull/6515))
- Style inlay hints in `onedark` theme ([#6503](https://github.com/helix-editor/helix/pull/6503))
- Style inlay hints and the soft-wrap indicator in `varua` ([#6568](https://github.com/helix-editor/helix/pull/6568), [#6589](https://github.com/helix-editor/helix/pull/6589))
- Style inlay hints in `emacs` theme ([#6569](https://github.com/helix-editor/helix/pull/6569))
- Update `base16_transparent` and `dark_high_contrast` themes ([#6577](https://github.com/helix-editor/helix/pull/6577))
- Style inlay hints for `mellow` and `rasmus` themes ([#6583](https://github.com/helix-editor/helix/pull/6583))
- Dim pane divider for `base16_transparent` theme ([#6534](https://github.com/helix-editor/helix/pull/6534))
- Style inlay hints in `zenburn` theme ([#6593](https://github.com/helix-editor/helix/pull/6593))
- Style inlay hints in `boo_berry` theme ([#6625](https://github.com/helix-editor/helix/pull/6625))
- Add `ferra` theme ([#6619](https://github.com/helix-editor/helix/pull/6619), [#6776](https://github.com/helix-editor/helix/pull/6776))
- Style inlay hints in `nightfox` theme ([#6655](https://github.com/helix-editor/helix/pull/6655))
- Fix `ayu` theme family markup code block background ([#6538](https://github.com/helix-editor/helix/pull/6538))
- Improve whitespace and search match colors in `rose_pine` theme ([#6679](https://github.com/helix-editor/helix/pull/6679))
- Highlight selected items in `base16_transparent` theme ([#6716](https://github.com/helix-editor/helix/pull/6716))
- Adjust everforest to resemble original more closely ([#5866](https://github.com/helix-editor/helix/pull/5866))
- Refactor `dracula` theme ([#6552](https://github.com/helix-editor/helix/pull/6552), [#6767](https://github.com/helix-editor/helix/pull/6767), [#6855](https://github.com/helix-editor/helix/pull/6855), [#6987](https://github.com/helix-editor/helix/pull/6987))
- Style inlay hints in `darcula` theme ([#6732](https://github.com/helix-editor/helix/pull/6732))
- Style inlay hints in `kanagawa` theme ([#6773](https://github.com/helix-editor/helix/pull/6773))
- Improve `ayu_dark` theme ([#6622](https://github.com/helix-editor/helix/pull/6622))
- Refactor `noctis` theme multiple cursor highlighting ([96720e7](https://github.com/helix-editor/helix/commit/96720e7))
- Refactor `noctis` theme whitespace rendering and indent guides ([f2ccc03](https://github.com/helix-editor/helix/commit/f2ccc03))
- Add `amberwood` theme ([#6924](https://github.com/helix-editor/helix/pull/6924))
- Update `nightfox` theme ([#7061](https://github.com/helix-editor/helix/pull/7061))
Language support:
- R language server: use the `--no-echo` flag to silence output ([#6570](https://github.com/helix-editor/helix/pull/6570))
- Recognize CUDA files as C++ ([#6521](https://github.com/helix-editor/helix/pull/6521))
- Add support for Hurl ([#6450](https://github.com/helix-editor/helix/pull/6450))
- Add textobject queries for Julia ([#6588](https://github.com/helix-editor/helix/pull/6588))
- Update Ruby highlight queries ([#6587](https://github.com/helix-editor/helix/pull/6587))
- Add xsd to XML file-types ([#6631](https://github.com/helix-editor/helix/pull/6631))
- Support Robot Framework ([#6611](https://github.com/helix-editor/helix/pull/6611))
- Update Gleam tree-sitter parser ([#6641](https://github.com/helix-editor/helix/pull/6641))
- Update git-commit tree-sitter parser ([#6692](https://github.com/helix-editor/helix/pull/6692))
- Update Haskell tree-sitter parser ([#6317](https://github.com/helix-editor/helix/pull/6317))
- Add injection queries for Haskell quasiquotes ([#6474](https://github.com/helix-editor/helix/pull/6474))
- Highlight C/C++ escape sequences ([#6724](https://github.com/helix-editor/helix/pull/6724))
- Support Markdoc ([#6432](https://github.com/helix-editor/helix/pull/6432))
- Support OpenCL ([#6473](https://github.com/helix-editor/helix/pull/6473))
- Support DTD ([#6644](https://github.com/helix-editor/helix/pull/6644))
- Fix constant highlighting in Python queries ([#6751](https://github.com/helix-editor/helix/pull/6751))
- Support Just ([#6453](https://github.com/helix-editor/helix/pull/6453))
- Fix Go locals query for `var_spec` identifiers ([#6763](https://github.com/helix-editor/helix/pull/6763))
- Update Markdown tree-sitter parser ([#6785](https://github.com/helix-editor/helix/pull/6785))
- Fix Haskell workspace root for cabal projects ([#6828](https://github.com/helix-editor/helix/pull/6828))
- Avoid extra indentation in Go switches ([#6817](https://github.com/helix-editor/helix/pull/6817))
- Fix Go workspace roots ([#6884](https://github.com/helix-editor/helix/pull/6884))
- Set PerlNavigator as the default Perl language server ([#6860](https://github.com/helix-editor/helix/pull/6860))
- Highlight more sqlx macros in Rust ([#6793](https://github.com/helix-editor/helix/pull/6793))
- Switch Odin tree-sitter grammar ([#6766](https://github.com/helix-editor/helix/pull/6766))
- Recognize `poetry.lock` as TOML ([#6928](https://github.com/helix-editor/helix/pull/6928))
- Recognize Jupyter notebooks as JSON ([#6927](https://github.com/helix-editor/helix/pull/6927))
- Add language server configuration for Crystal ([#6948](https://github.com/helix-editor/helix/pull/6948))
- Add `build.gradle.kts` to Java and Scala roots ([#6970](https://github.com/helix-editor/helix/pull/6970))
- Recognize `sty` and `cls` files as latex ([#6986](https://github.com/helix-editor/helix/pull/6986))
- Update Dockerfile tree-sitter grammar ([#6895](https://github.com/helix-editor/helix/pull/6895))
- Add comment injections for Odin ([#7027](https://github.com/helix-editor/helix/pull/7027))
- Recognize `gml` as XML ([#7055](https://github.com/helix-editor/helix/pull/7055))
- Recognize `geojson` as JSON ([#7054](https://github.com/helix-editor/helix/pull/7054))
Packaging:
- Update the Nix flake dependencies, remove a deprecated option ([#6546](https://github.com/helix-editor/helix/pull/6546))
- Fix and re-enable aarch64-macos release binary builds ([#6504](https://github.com/helix-editor/helix/pull/6504))
- The git dependency on `tree-sitter` has been replaced with a regular crates.io dependency ([#6608](https://github.com/helix-editor/helix/pull/6608))
# 23.03 (2023-03-31) # 23.03 (2023-03-31)
23.03 brings some long-awaited and exciting features. Thank you to everyone involved! This release saw changes from 102 contributors. 23.03 brings some long-awaited and exciting features. Thank you to everyone involved! This release saw changes from 102 contributors.
@@ -1479,7 +2313,7 @@ to distinguish it in bug reports..
- The `runtime/` directory is now properly detected on binary releases and - The `runtime/` directory is now properly detected on binary releases and
on cargo run. `~/.config/helix/runtime` can also be used. on cargo run. `~/.config/helix/runtime` can also be used.
- Registers can now be selected via " (for example `"ay`) - Registers can now be selected via " (for example, `"ay`)
- Support for Nix files was added - Support for Nix files was added
- Movement is now fully tested and matches Kakoune implementation - Movement is now fully tested and matches Kakoune implementation
- A per-file LSP symbol picker was added to space+s - A per-file LSP symbol picker was added to space+s

2342
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,18 @@
[workspace] [workspace]
resolver = "2"
members = [ members = [
"helix-core", "helix-core",
"helix-view", "helix-view",
"helix-term", "helix-term",
"helix-tui", "helix-tui",
"helix-lsp-types",
"helix-lsp", "helix-lsp",
"helix-event",
"helix-dap", "helix-dap",
"helix-loader", "helix-loader",
"helix-vcs", "helix-vcs",
"helix-parsec", "helix-parsec",
"helix-stdx",
"xtask", "xtask",
] ]
@@ -32,3 +36,20 @@ inherits = "test"
package.helix-core.opt-level = 2 package.helix-core.opt-level = 2
package.helix-tui.opt-level = 2 package.helix-tui.opt-level = 2
package.helix-term.opt-level = 2 package.helix-term.opt-level = 2
[workspace.dependencies]
tree-sitter = { version = "0.22" }
nucleo = "0.5.0"
slotmap = "1.0.7"
thiserror = "2.0"
percent-encoding = "2.3"
[workspace.package]
version = "24.7.0"
edition = "2021"
authors = ["Blaž Hrastnik <blaz@mxxn.io>"]
categories = ["editor"]
repository = "https://github.com/helix-editor/helix"
homepage = "https://helix-editor.com"
license = "MPL-2.0"
rust-version = "1.76"

View File

@@ -18,7 +18,7 @@
![Screenshot](./screenshot.png) ![Screenshot](./screenshot.png)
A Kakoune / Neovim inspired editor, written in Rust. A [Kakoune](https://github.com/mawww/kakoune) / [Neovim](https://github.com/neovim/neovim) inspired editor, written in Rust.
The editing model is very heavily based on Kakoune; during development I found The editing model is very heavily based on Kakoune; during development I found
myself agreeing with most of Kakoune's design decisions. myself agreeing with most of Kakoune's design decisions.
@@ -37,8 +37,8 @@ All shortcuts/keymaps can be found [in the documentation on the website](https:/
- Built-in language server support - Built-in language server support
- Smart, incremental syntax highlighting and code editing via tree-sitter - Smart, incremental syntax highlighting and code editing via tree-sitter
It's a terminal-based editor first, but I'd like to explore a custom renderer Although it's primarily a terminal-based editor, I am interested in exploring
(similar to Emacs) in wgpu or skulpin. a custom renderer (similar to Emacs) using wgpu or skulpin.
Note: Only certain languages have indentation definitions at the moment. Check Note: Only certain languages have indentation definitions at the moment. Check
`runtime/queries/<lang>/` for `indents.scm`. `runtime/queries/<lang>/` for `indents.scm`.
@@ -47,7 +47,7 @@ Note: Only certain languages have indentation definitions at the moment. Check
[Installation documentation](https://docs.helix-editor.com/install.html). [Installation documentation](https://docs.helix-editor.com/install.html).
[![Packaging status](https://repology.org/badge/vertical-allrepos/helix.svg)](https://repology.org/project/helix/versions) [![Packaging status](https://repology.org/badge/vertical-allrepos/helix-editor.svg?exclude_unsupported=1)](https://repology.org/project/helix-editor/versions)
# Contributing # Contributing
@@ -61,4 +61,4 @@ Discuss the project on the community [Matrix Space](https://matrix.to/#/#helix-c
# Credits # Credits
Thanks to [@JakeHL](https://github.com/JakeHL) for designing the logo! Thanks to [@jakenvac](https://github.com/jakenvac) for designing the logo!

View File

@@ -1 +0,0 @@
23.03

View File

@@ -28,6 +28,11 @@
"label" = "magenta" "label" = "magenta"
"namespace" = "magenta" "namespace" = "magenta"
"ui.help" = { fg = "white", bg = "black" } "ui.help" = { fg = "white", bg = "black" }
"ui.statusline.insert" = { fg = "black", bg = "green" }
"ui.statusline.select" = { fg = "black", bg = "blue" }
"ui.virtual" = { fg = "gray", modifiers = ["italic"] }
"ui.virtual.jump-label" = { fg = "blue", modifiers = ["bold", "underlined"] }
"ui.virtual.ruler" = { bg = "black" }
"markup.heading" = "blue" "markup.heading" = "blue"
"markup.list" = "red" "markup.list" = "red"

View File

@@ -3,10 +3,14 @@ authors = ["Blaž Hrastnik"]
language = "en" language = "en"
multilingual = false multilingual = false
src = "src" src = "src"
edit-url-template = "https://github.com/helix-editor/helix/tree/master/book/{path}?mode=edit"
[output.html] [output.html]
cname = "docs.helix-editor.com" cname = "docs.helix-editor.com"
default-theme = "colibri" default-theme = "colibri"
preferred-dark-theme = "colibri" preferred-dark-theme = "colibri"
git-repository-url = "https://github.com/helix-editor/helix" git-repository-url = "https://github.com/helix-editor/helix"
edit-url-template = "https://github.com/helix-editor/helix/edit/master/book/{path}"
additional-css = ["custom.css"]
[output.html.search]
use-boolean-and = true

231
book/custom.css Normal file
View File

@@ -0,0 +1,231 @@
html {
font-family: "Inter", sans-serif;
}
.sidebar .sidebar-scrollbox {
padding: 0;
}
.chapter {
margin: 0.25rem 0;
}
.chapter li.chapter-item {
line-height: initial;
margin: 0;
padding: 1rem 1.5rem;
}
.chapter .section li.chapter-item {
line-height: inherit;
padding: .5rem .5rem 0 .5rem;
}
.content {
overflow-y: auto;
padding: 0 15px;
padding-bottom: 50px;
}
/* 2 1.75 1.5 1.25 1 .875 */
.content h1 { font-size: 2em }
.content h2 { font-size: 1.75em }
.content h3 { font-size: 1.5em }
.content h4 { font-size: 1.25em }
.content h5 { font-size: 1em }
.content h6 { font-size: .875em }
.content h1,
.content h2,
.content h3,
.content h4 {
font-weight: 500;
margin-top: 1.275em;
margin-bottom: .875em;
}
.content p,
.content ol,
.content ul,
.content table {
margin-top: 0;
margin-bottom: .875em;
}
.content ul li {
margin-bottom: .25rem;
}
.content ul {
list-style-type: square;
}
.content ul ul,
.content ol ul {
margin-bottom: .5rem;
}
.content li p {
margin-bottom: .5em;
}
blockquote {
margin: 1.5rem 0;
padding: 1rem 1.5rem;
color: var(--fg);
opacity: .9;
background-color: var(--quote-bg);
border-left: 4px solid var(--quote-border);
border-top: none;
border-bottom: none;
}
blockquote *:last-child {
margin-bottom: 0;
}
table {
width: 100%;
}
table thead th {
padding: .75rem;
text-align: left;
font-weight: 500;
line-height: 1.5;
width: auto;
}
table td {
padding: .75rem;
border: none;
}
table thead tr {
border: none;
border-bottom: 2px var(--table-border-color) solid;
}
table tbody tr {
border-bottom: 1px var(--table-border-line) solid;
}
table tbody tr:nth-child(2n) {
background: unset;
}
pre code.hljs {
display: block;
overflow-x: auto;
padding: 1em;
}
code.hljs {
padding: 3px 5px;
}
.colibri {
--bg: #3b224c;
--fg: #bcbdd0;
--heading-fg: #fff;
--sidebar-bg: #281733;
--sidebar-fg: #c8c9db;
--sidebar-non-existent: #505274;
--sidebar-active: #a4a0e8;
--sidebar-spacer: #2d334f;
--scrollbar: var(--sidebar-fg);
--icons: #737480;
--icons-hover: #b7b9cc;
/* --links: #a4a0e8; */
--links: #ECCDBA;
--inline-code-color: hsl(48.7, 7.8%, 70%);
--theme-popup-bg: #161923;
--theme-popup-border: #737480;
--theme-hover: rgba(0, 0, 0, .2);
--quote-bg: #281733;
--quote-border: hsl(226, 15%, 22%);
--table-border-color: hsl(226, 23%, 76%);
--table-header-bg: hsla(226, 23%, 31%, 0);
--table-alternate-bg: hsl(226, 23%, 14%);
--table-border-line: hsla(201deg, 20%, 92%, 0.2);
--searchbar-border-color: #aaa;
--searchbar-bg: #aeaec6;
--searchbar-fg: #000;
--searchbar-shadow-color: #aaa;
--searchresults-header-fg: #5f5f71;
--searchresults-border-color: #5c5c68;
--searchresults-li-bg: #242430;
--search-mark-bg: #a2cff5;
}
.colibri .content .header {
color: #fff;
}
/* highlight.js theme, :where() is used to avoid increasing specificity */
:where(.colibri) .hljs {
background: #2f1e2e;
color: #a39e9b;
}
:where(.colibri) .hljs-comment,
:where(.colibri) .hljs-quote {
color: #8d8687;
}
:where(.colibri) .hljs-link,
:where(.colibri) .hljs-meta,
:where(.colibri) .hljs-name,
:where(.colibri) .hljs-regexp,
:where(.colibri) .hljs-selector-class,
:where(.colibri) .hljs-selector-id,
:where(.colibri) .hljs-tag,
:where(.colibri) .hljs-template-variable,
:where(.colibri) .hljs-variable {
color: #ef6155;
}
:where(.colibri) .hljs-built_in,
:where(.colibri) .hljs-deletion,
:where(.colibri) .hljs-literal,
:where(.colibri) .hljs-number,
:where(.colibri) .hljs-params,
:where(.colibri) .hljs-type {
color: #f99b15;
}
:where(.colibri) .hljs-attribute,
:where(.colibri) .hljs-section,
:where(.colibri) .hljs-title {
color: #fec418;
}
:where(.colibri) .hljs-addition,
:where(.colibri) .hljs-bullet,
:where(.colibri) .hljs-string,
:where(.colibri) .hljs-symbol {
color: #48b685;
}
:where(.colibri) .hljs-keyword,
:where(.colibri) .hljs-selector-tag {
color: #815ba4;
}
:where(.colibri) .hljs-emphasis {
font-style: italic;
}
:where(.colibri) .hljs-strong {
font-weight: 700;
}

View File

@@ -3,12 +3,20 @@
[Helix](./title-page.md) [Helix](./title-page.md)
- [Installation](./install.md) - [Installation](./install.md)
- [Package Managers](./package-managers.md)
- [Building from source](./building-from-source.md)
- [Usage](./usage.md) - [Usage](./usage.md)
- [Registers](./registers.md)
- [Surround](./surround.md)
- [Textobjects](./textobjects.md)
- [Syntax aware motions](./syntax-aware-motions.md)
- [Pickers](./pickers.md)
- [Keymap](./keymap.md) - [Keymap](./keymap.md)
- [Commands](./commands.md) - [Commands](./commands.md)
- [Language support](./lang-support.md) - [Language support](./lang-support.md)
- [Migrating from Vim](./from-vim.md) - [Migrating from Vim](./from-vim.md)
- [Configuration](./configuration.md) - [Configuration](./configuration.md)
- [Editor](./editor.md)
- [Themes](./themes.md) - [Themes](./themes.md)
- [Key remapping](./remapping.md) - [Key remapping](./remapping.md)
- [Languages](./languages.md) - [Languages](./languages.md)
@@ -16,3 +24,4 @@
- [Adding languages](./guides/adding_languages.md) - [Adding languages](./guides/adding_languages.md)
- [Adding textobject queries](./guides/textobject.md) - [Adding textobject queries](./guides/textobject.md)
- [Adding indent queries](./guides/indent.md) - [Adding indent queries](./guides/indent.md)
- [Adding injection queries](./guides/injection.md)

View File

@@ -0,0 +1,164 @@
## Building from source
- [Configuring Helix's runtime files](#configuring-helixs-runtime-files)
- [Linux and macOS](#linux-and-macos)
- [Windows](#windows)
- [Multiple runtime directories](#multiple-runtime-directories)
- [Note to packagers](#note-to-packagers)
- [Validating the installation](#validating-the-installation)
- [Configure the desktop shortcut](#configure-the-desktop-shortcut)
Requirements:
Clone the Helix GitHub repository into a directory of your choice. The
examples in this documentation assume installation into either `~/src/` on
Linux and macOS, or `%userprofile%\src\` on Windows.
- The [Rust toolchain](https://www.rust-lang.org/tools/install)
- The [Git version control system](https://git-scm.com/)
- A C++14 compatible compiler to build the tree-sitter grammars, for example GCC or Clang
If you are using the `musl-libc` standard library instead of `glibc` the following environment variable must be set during the build to ensure tree-sitter grammars can be loaded correctly:
```sh
RUSTFLAGS="-C target-feature=-crt-static"
```
1. Clone the repository:
```sh
git clone https://github.com/helix-editor/helix
cd helix
```
2. Compile from source:
```sh
cargo install --path helix-term --locked
```
This command will create the `hx` executable and construct the tree-sitter
grammars in the local `runtime` folder.
> 💡 If you do not want to fetch or build grammars, set an environment variable `HELIX_DISABLE_AUTO_GRAMMAR_BUILD`
> 💡 Tree-sitter grammars can be fetched and compiled if not pre-packaged. Fetch
> grammars with `hx --grammar fetch` and compile them with
> `hx --grammar build`. This will install them in
> the `runtime` directory within the user's helix config directory (more
> [details below](#multiple-runtime-directories)).
### Configuring Helix's runtime files
#### Linux and macOS
The **runtime** directory is one below the Helix source, so either export a
`HELIX_RUNTIME` environment variable to point to that directory and add it to
your `~/.bashrc` or equivalent:
```sh
export HELIX_RUNTIME=~/src/helix/runtime
```
Or, create a symbolic link:
```sh
ln -Ts $PWD/runtime ~/.config/helix/runtime
```
If the above command fails to create a symbolic link because the file exists either move `~/.config/helix/runtime` to a new location or delete it, then run the symlink command above again.
#### Windows
Either set the `HELIX_RUNTIME` environment variable to point to the runtime files using the Windows setting (search for
`Edit environment variables for your account`) or use the `setx` command in
Cmd:
```sh
setx HELIX_RUNTIME "%userprofile%\source\repos\helix\runtime"
```
> 💡 `%userprofile%` resolves to your user directory like
> `C:\Users\Your-Name\` for example.
Or, create a symlink in `%appdata%\helix\` that links to the source code directory:
| Method | Command |
| ---------- | -------------------------------------------------------------------------------------- |
| PowerShell | `New-Item -ItemType Junction -Target "runtime" -Path "$Env:AppData\helix\runtime"` |
| Cmd | `cd %appdata%\helix` <br/> `mklink /D runtime "%userprofile%\src\helix\runtime"` |
> 💡 On Windows, creating a symbolic link may require running PowerShell or
> Cmd as an administrator.
#### Multiple runtime directories
When Helix finds multiple runtime directories it will search through them for files in the
following order:
1. `runtime/` sibling directory to `$CARGO_MANIFEST_DIR` directory (this is intended for
developing and testing helix only).
2. `runtime/` subdirectory of OS-dependent helix user config directory.
3. `$HELIX_RUNTIME`
4. Distribution-specific fallback directory (set at compile time—not run time—
with the `HELIX_DEFAULT_RUNTIME` environment variable)
5. `runtime/` subdirectory of path to Helix executable.
This order also sets the priority for selecting which file will be used if multiple runtime
directories have files with the same name.
#### Note to packagers
If you are making a package of Helix for end users, to provide a good out of
the box experience, you should set the `HELIX_DEFAULT_RUNTIME` environment
variable at build time (before invoking `cargo build`) to a directory which
will store the final runtime files after installation. For example, say you want
to package the runtime into `/usr/lib/helix/runtime`. The rough steps a build
script could follow are:
1. `export HELIX_DEFAULT_RUNTIME=/usr/lib/helix/runtime`
1. `cargo build --profile opt --locked`
1. `cp -r runtime $BUILD_DIR/usr/lib/helix/`
1. `cp target/opt/hx $BUILD_DIR/usr/bin/hx`
This way the resulting `hx` binary will always look for its runtime directory in
`/usr/lib/helix/runtime` if the user has no custom runtime in `~/.config/helix`
or `HELIX_RUNTIME`.
### Validating the installation
To make sure everything is set up as expected you should run the Helix health
check:
```sh
hx --health
```
For more information on the health check results refer to
[Health check](https://github.com/helix-editor/helix/wiki/Healthcheck).
### Configure the desktop shortcut
If your desktop environment supports the
[XDG desktop menu](https://specifications.freedesktop.org/menu-spec/menu-spec-latest.html)
you can configure Helix to show up in the application menu by copying the
provided `.desktop` and icon files to their correct folders:
```sh
cp contrib/Helix.desktop ~/.local/share/applications
cp contrib/helix.png ~/.icons # or ~/.local/share/icons
```
It is recommended to convert the links in the `.desktop` file to absolute paths to avoid potential problems:
```sh
sed -i -e "s|Exec=hx %F|Exec=$(readlink -f ~/.cargo/bin/hx) %F|g" \
-e "s|Icon=helix|Icon=$(readlink -f ~/.icons/helix.png)|g" ~/.local/share/applications/Helix.desktop
```
To use another terminal than the system default, you can modify the `.desktop`
file. For example, to use `kitty`:
```sh
sed -i "s|Exec=hx %F|Exec=kitty hx %F|g" ~/.local/share/applications/Helix.desktop
sed -i "s|Terminal=true|Terminal=false|g" ~/.local/share/applications/Helix.desktop
```

View File

@@ -1,5 +1,16 @@
# Commands # Commands
Command mode can be activated by pressing `:`. The built-in commands are: - [Typable commands](#typable-commands)
- [Static commands](#static-commands)
## Typable commands
Typable commands are used from command mode and may take arguments. Command mode can be activated by pressing `:`. The built-in typable commands are:
{{#include ./generated/typable-cmd.md}} {{#include ./generated/typable-cmd.md}}
## Static Commands
Static commands take no arguments and can be bound to keys. Static commands can also be executed from the command picker (`<space>?`). The built-in static commands are:
{{#include ./generated/static-cmd.md}}

View File

@@ -27,319 +27,9 @@ hidden = false
You can use a custom configuration file by specifying it with the `-c` or You can use a custom configuration file by specifying it with the `-c` or
`--config` command line argument, for example `hx -c path/to/custom-config.toml`. `--config` command line argument, for example `hx -c path/to/custom-config.toml`.
Additionally, you can reload the configuration file by sending the USR1 You can reload the config file by issuing the `:config-reload` command. Alternatively, on Unix operating systems, you can reload it by sending the USR1
signal to the Helix process on Unix operating systems, such as by using the command `pkill -USR1 hx`. signal to the Helix process, such as by using the command `pkill -USR1 hx`.
Finally, you can have a `config.toml` local to a project by putting it under a `.helix` directory in your repository. Finally, you can have a `config.toml` local to a project by putting it under a `.helix` directory in your repository.
Its settings will be merged with the configuration directory `config.toml` and the built-in configuration. Its settings will be merged with the configuration directory `config.toml` and the built-in configuration.
## Editor
### `[editor]` Section
| Key | Description | Default |
|--|--|---------|
| `scrolloff` | Number of lines of padding around the edge of the screen when scrolling | `5` |
| `mouse` | Enable mouse mode | `true` |
| `middle-click-paste` | Middle click paste support | `true` |
| `scroll-lines` | Number of lines to scroll per scroll wheel step | `3` |
| `shell` | Shell to use when running external commands | Unix: `["sh", "-c"]`<br/>Windows: `["cmd", "/C"]` |
| `line-number` | Line number display: `absolute` simply shows each line's number, while `relative` shows the distance from the current line. When unfocused or in insert mode, `relative` will still show absolute line numbers | `absolute` |
| `cursorline` | Highlight all lines with a cursor | `false` |
| `cursorcolumn` | Highlight all columns with a cursor | `false` |
| `gutters` | Gutters to display: Available are `diagnostics` and `diff` and `line-numbers` and `spacer`, note that `diagnostics` also includes other features like breakpoints, 1-width padding will be inserted if gutters is non-empty | `["diagnostics", "spacer", "line-numbers", "spacer", "diff"]` |
| `auto-completion` | Enable automatic pop up of auto-completion | `true` |
| `auto-format` | Enable automatic formatting on save | `true` |
| `auto-save` | Enable automatic saving on the focus moving away from Helix. Requires [focus event support](https://github.com/helix-editor/helix/wiki/Terminal-Support) from your terminal | `false` |
| `idle-timeout` | Time in milliseconds since last keypress before idle timers trigger. Used for autocompletion, set to 0 for instant | `400` |
| `completion-trigger-len` | The min-length of word under cursor to trigger autocompletion | `2` |
| `completion-replace` | Set to `true` to make completions always replace the entire word and not just the part before the cursor | `false` |
| `auto-info` | Whether to display info boxes | `true` |
| `true-color` | Set to `true` to override automatic detection of terminal truecolor support in the event of a false negative | `false` |
| `undercurl` | Set to `true` to override automatic detection of terminal undercurl support in the event of a false negative | `false` |
| `rulers` | List of column positions at which to display the rulers. Can be overridden by language specific `rulers` in `languages.toml` file | `[]` |
| `bufferline` | Renders a line at the top of the editor displaying open buffers. Can be `always`, `never` or `multiple` (only shown if more than one buffer is in use) | `never` |
| `color-modes` | Whether to color the mode indicator with different colors depending on the mode itself | `false` |
| `text-width` | Maximum line length. Used for the `:reflow` command and soft-wrapping if `soft-wrap.wrap_at_text_width` is set | `80` |
| `workspace-lsp-roots` | Directories relative to the workspace root that are treated as LSP roots. Should only be set in `.helix/config.toml` | `[]` |
### `[editor.statusline]` Section
Allows configuring the statusline at the bottom of the editor.
The configuration distinguishes between three areas of the status line:
`[ ... ... LEFT ... ... | ... ... ... ... CENTER ... ... ... ... | ... ... RIGHT ... ... ]`
Statusline elements can be defined as follows:
```toml
[editor.statusline]
left = ["mode", "spinner"]
center = ["file-name"]
right = ["diagnostics", "selections", "position", "file-encoding", "file-line-ending", "file-type"]
separator = "│"
mode.normal = "NORMAL"
mode.insert = "INSERT"
mode.select = "SELECT"
```
The `[editor.statusline]` key takes the following sub-keys:
| Key | Description | Default |
| --- | --- | --- |
| `left` | A list of elements aligned to the left of the statusline | `["mode", "spinner", "file-name"]` |
| `center` | A list of elements aligned to the middle of the statusline | `[]` |
| `right` | A list of elements aligned to the right of the statusline | `["diagnostics", "selections", "position", "file-encoding"]` |
| `separator` | The character used to separate elements in the statusline | `"│"` |
| `mode.normal` | The text shown in the `mode` element for normal mode | `"NOR"` |
| `mode.insert` | The text shown in the `mode` element for insert mode | `"INS"` |
| `mode.select` | The text shown in the `mode` element for select mode | `"SEL"` |
The following statusline elements can be configured:
| Key | Description |
| ------ | ----------- |
| `mode` | The current editor mode (`mode.normal`/`mode.insert`/`mode.select`) |
| `spinner` | A progress spinner indicating LSP activity |
| `file-name` | The path/name of the opened file |
| `file-base-name` | The basename of the opened file |
| `file-modification-indicator` | The indicator to show whether the file is modified (a `[+]` appears when there are unsaved changes) |
| `file-encoding` | The encoding of the opened file if it differs from UTF-8 |
| `file-line-ending` | The file line endings (CRLF or LF) |
| `total-line-numbers` | The total line numbers of the opened file |
| `file-type` | The type of the opened file |
| `diagnostics` | The number of warnings and/or errors |
| `workspace-diagnostics` | The number of warnings and/or errors on workspace |
| `selections` | The number of active selections |
| `primary-selection-length` | The number of characters currently in primary selection |
| `position` | The cursor position |
| `position-percentage` | The cursor position as a percentage of the total number of lines |
| `separator` | The string defined in `editor.statusline.separator` (defaults to `"│"`) |
| `spacer` | Inserts a space between elements (multiple/contiguous spacers may be specified) |
| `version-control` | The current branch name or detached commit hash of the opened workspace |
### `[editor.lsp]` Section
| Key | Description | Default |
| --- | ----------- | ------- |
| `enable` | Enables LSP integration. Setting to false will completely disable language servers regardless of language settings.| `true` |
| `display-messages` | Display LSP progress messages below statusline[^1] | `false` |
| `auto-signature-help` | Enable automatic popup of signature help (parameter hints) | `true` |
| `display-inlay-hints` | Display inlay hints[^2] | `false` |
| `display-signature-help-docs` | Display docs under signature help popup | `true` |
| `snippets` | Enables snippet completions. Requires a server restart (`:lsp-restart`) to take effect after `:config-reload`/`:set`. | `true` |
[^1]: By default, a progress spinner is shown in the statusline beside the file path.
[^2]: You may also have to activate them in the LSP config for them to appear, not just in Helix.
Inlay hints in Helix are still being improved on and may be a little bit laggy/janky under some circumstances, please report any bugs you see so we can fix them!
### `[editor.cursor-shape]` Section
Defines the shape of cursor in each mode.
Valid values for these options are `block`, `bar`, `underline`, or `hidden`.
> 💡 Due to limitations of the terminal environment, only the primary cursor can
> change shape.
| Key | Description | Default |
| --- | ----------- | ------- |
| `normal` | Cursor shape in [normal mode][normal mode] | `block` |
| `insert` | Cursor shape in [insert mode][insert mode] | `block` |
| `select` | Cursor shape in [select mode][select mode] | `block` |
[normal mode]: ./keymap.md#normal-mode
[insert mode]: ./keymap.md#insert-mode
[select mode]: ./keymap.md#select--extend-mode
### `[editor.file-picker]` Section
Set options for file picker and global search. Ignoring a file means it is
not visible in the Helix file picker and global search.
All git related options are only enabled in a git repository.
| Key | Description | Default |
|--|--|---------|
|`hidden` | Enables ignoring hidden files | true
|`follow-symlinks` | Follow symlinks instead of ignoring them | true
|`deduplicate-links` | Ignore symlinks that point at files already shown in the picker | true
|`parents` | Enables reading ignore files from parent directories | true
|`ignore` | Enables reading `.ignore` files | true
|`git-ignore` | Enables reading `.gitignore` files | true
|`git-global` | Enables reading global `.gitignore`, whose path is specified in git's config: `core.excludefile` option | true
|`git-exclude` | Enables reading `.git/info/exclude` files | true
|`max-depth` | Set with an integer value for maximum depth to recurse | Defaults to `None`.
### `[editor.auto-pairs]` Section
Enables automatic insertion of pairs to parentheses, brackets, etc. Can be a
simple boolean value, or a specific mapping of pairs of single characters.
To disable auto-pairs altogether, set `auto-pairs` to `false`:
```toml
[editor]
auto-pairs = false # defaults to `true`
```
The default pairs are <code>(){}[]''""``</code>, but these can be customized by
setting `auto-pairs` to a TOML table:
```toml
[editor.auto-pairs]
'(' = ')'
'{' = '}'
'[' = ']'
'"' = '"'
'`' = '`'
'<' = '>'
```
Additionally, this setting can be used in a language config. Unless
the editor setting is `false`, this will override the editor config in
documents with this language.
Example `languages.toml` that adds <> and removes ''
```toml
[[language]]
name = "rust"
[language.auto-pairs]
'(' = ')'
'{' = '}'
'[' = ']'
'"' = '"'
'`' = '`'
'<' = '>'
```
### `[editor.search]` Section
Search specific options.
| Key | Description | Default |
|--|--|---------|
| `smart-case` | Enable smart case regex searching (case-insensitive unless pattern contains upper case characters) | `true` |
| `wrap-around`| Whether the search should wrap after depleting the matches | `true` |
### `[editor.whitespace]` Section
Options for rendering whitespace with visible characters. Use `:set whitespace.render all` to temporarily enable visible whitespace.
| Key | Description | Default |
|-----|-------------|---------|
| `render` | Whether to render whitespace. May either be `"all"` or `"none"`, or a table with sub-keys `space`, `nbsp`, `tab`, and `newline` | `"none"` |
| `characters` | Literal characters to use when rendering whitespace. Sub-keys may be any of `tab`, `space`, `nbsp`, `newline` or `tabpad` | See example below |
Example
```toml
[editor.whitespace]
render = "all"
# or control each character
[editor.whitespace.render]
space = "all"
tab = "all"
newline = "none"
[editor.whitespace.characters]
space = "·"
nbsp = "⍽"
tab = "→"
newline = "⏎"
tabpad = "·" # Tabs will look like "→···" (depending on tab width)
```
### `[editor.indent-guides]` Section
Options for rendering vertical indent guides.
| Key | Description | Default |
| --- | --- | --- |
| `render` | Whether to render indent guides | `false` |
| `character` | Literal character to use for rendering the indent guide | `│` |
| `skip-levels` | Number of indent levels to skip | `0` |
Example:
```toml
[editor.indent-guides]
render = true
character = "╎" # Some characters that work well: "▏", "┆", "┊", "⸽"
skip-levels = 1
```
### `[editor.gutters]` Section
For simplicity, `editor.gutters` accepts an array of gutter types, which will
use default settings for all gutter components.
```toml
[editor]
gutters = ["diff", "diagnostics", "line-numbers", "spacer"]
```
To customize the behavior of gutters, the `[editor.gutters]` section must
be used. This section contains top level settings, as well as settings for
specific gutter components as subsections.
| Key | Description | Default |
| --- | --- | --- |
| `layout` | A vector of gutters to display | `["diagnostics", "spacer", "line-numbers", "spacer", "diff"]` |
Example:
```toml
[editor.gutters]
layout = ["diff", "diagnostics", "line-numbers", "spacer"]
```
#### `[editor.gutters.line-numbers]` Section
Options for the line number gutter
| Key | Description | Default |
| --- | --- | --- |
| `min-width` | The minimum number of characters to use | `3` |
Example:
```toml
[editor.gutters.line-numbers]
min-width = 1
```
#### `[editor.gutters.diagnostics]` Section
Currently unused
#### `[editor.gutters.diff]` Section
Currently unused
#### `[editor.gutters.spacer]` Section
Currently unused
### `[editor.soft-wrap]` Section
Options for soft wrapping lines that exceed the view width:
| Key | Description | Default |
| --- | --- | --- |
| `enable` | Whether soft wrapping is enabled. | `false` |
| `max-wrap` | Maximum free space left at the end of the line. | `20` |
| `max-indent-retain` | Maximum indentation to carry over when soft wrapping a line. | `40` |
| `wrap-indicator` | Text inserted before soft wrapped lines, highlighted with `ui.virtual.wrap` | `↪ ` |
| `wrap-at-text-width` | Soft wrap at `text-width` instead of using the full viewport size. | `false` |
Example:
```toml
[editor.soft-wrap]
enable = true
max-wrap = 25 # increase value to reduce forced mid-word wrapping
max-indent-retain = 0
wrap-indicator = "" # set wrap-indicator to "" to hide it
```

465
book/src/editor.md Normal file
View File

@@ -0,0 +1,465 @@
## Editor
- [`[editor]` Section](#editor-section)
- [`[editor.statusline]` Section](#editorstatusline-section)
- [`[editor.lsp]` Section](#editorlsp-section)
- [`[editor.cursor-shape]` Section](#editorcursor-shape-section)
- [`[editor.file-picker]` Section](#editorfile-picker-section)
- [`[editor.auto-pairs]` Section](#editorauto-pairs-section)
- [`[editor.search]` Section](#editorsearch-section)
- [`[editor.whitespace]` Section](#editorwhitespace-section)
- [`[editor.indent-guides]` Section](#editorindent-guides-section)
- [`[editor.gutters]` Section](#editorgutters-section)
- [`[editor.gutters.line-numbers]` Section](#editorguttersline-numbers-section)
- [`[editor.gutters.diagnostics]` Section](#editorguttersdiagnostics-section)
- [`[editor.gutters.diff]` Section](#editorguttersdiff-section)
- [`[editor.gutters.spacer]` Section](#editorguttersspacer-section)
- [`[editor.soft-wrap]` Section](#editorsoft-wrap-section)
- [`[editor.smart-tab]` Section](#editorsmart-tab-section)
- [`[editor.inline-diagnostics]` Section](#editorinline-diagnostics-section)
### `[editor]` Section
| Key | Description | Default |
|--|--|---------|
| `scrolloff` | Number of lines of padding around the edge of the screen when scrolling | `5` |
| `mouse` | Enable mouse mode | `true` |
| `default-yank-register` | Default register used for yank/paste | `"` |
| `middle-click-paste` | Middle click paste support | `true` |
| `scroll-lines` | Number of lines to scroll per scroll wheel step | `3` |
| `shell` | Shell to use when running external commands | Unix: `["sh", "-c"]`<br/>Windows: `["cmd", "/C"]` |
| `line-number` | Line number display: `absolute` simply shows each line's number, while `relative` shows the distance from the current line. When unfocused or in insert mode, `relative` will still show absolute line numbers | `absolute` |
| `cursorline` | Highlight all lines with a cursor | `false` |
| `cursorcolumn` | Highlight all columns with a cursor | `false` |
| `continue-comments` | if helix should automatically add a line comment token if you create a new line inside a comment. | `true` |
| `gutters` | Gutters to display: Available are `diagnostics` and `diff` and `line-numbers` and `spacer`, note that `diagnostics` also includes other features like breakpoints, 1-width padding will be inserted if gutters is non-empty | `["diagnostics", "spacer", "line-numbers", "spacer", "diff"]` |
| `auto-completion` | Enable automatic pop up of auto-completion | `true` |
| `path-completion` | Enable filepath completion. Show files and directories if an existing path at the cursor was recognized, either absolute or relative to the current opened document or current working directory (if the buffer is not yet saved). Defaults to true. | `true` |
| `auto-format` | Enable automatic formatting on save | `true` |
| `idle-timeout` | Time in milliseconds since last keypress before idle timers trigger. | `250` |
| `completion-timeout` | Time in milliseconds after typing a word character before completions are shown, set to 5 for instant. | `250` |
| `preview-completion-insert` | Whether to apply completion item instantly when selected | `true` |
| `completion-trigger-len` | The min-length of word under cursor to trigger autocompletion | `2` |
| `completion-replace` | Set to `true` to make completions always replace the entire word and not just the part before the cursor | `false` |
| `auto-info` | Whether to display info boxes | `true` |
| `true-color` | Set to `true` to override automatic detection of terminal truecolor support in the event of a false negative | `false` |
| `undercurl` | Set to `true` to override automatic detection of terminal undercurl support in the event of a false negative | `false` |
| `rulers` | List of column positions at which to display the rulers. Can be overridden by language specific `rulers` in `languages.toml` file | `[]` |
| `bufferline` | Renders a line at the top of the editor displaying open buffers. Can be `always`, `never` or `multiple` (only shown if more than one buffer is in use) | `never` |
| `color-modes` | Whether to color the mode indicator with different colors depending on the mode itself | `false` |
| `text-width` | Maximum line length. Used for the `:reflow` command and soft-wrapping if `soft-wrap.wrap-at-text-width` is set | `80` |
| `workspace-lsp-roots` | Directories relative to the workspace root that are treated as LSP roots. Should only be set in `.helix/config.toml` | `[]` |
| `default-line-ending` | The line ending to use for new documents. Can be `native`, `lf`, `crlf`, `ff`, `cr` or `nel`. `native` uses the platform's native line ending (`crlf` on Windows, otherwise `lf`). | `native` |
| `insert-final-newline` | Whether to automatically insert a trailing line-ending on write if missing | `true` |
| `popup-border` | Draw border around `popup`, `menu`, `all`, or `none` | `none` |
| `indent-heuristic` | How the indentation for a newly inserted line is computed: `simple` just copies the indentation level from the previous line, `tree-sitter` computes the indentation based on the syntax tree and `hybrid` combines both approaches. If the chosen heuristic is not available, a different one will be used as a fallback (the fallback order being `hybrid` -> `tree-sitter` -> `simple`). | `hybrid`
| `jump-label-alphabet` | The characters that are used to generate two character jump labels. Characters at the start of the alphabet are used first. | `"abcdefghijklmnopqrstuvwxyz"`
| `end-of-line-diagnostics` | Minimum severity of diagnostics to render at the end of the line. Set to `disable` to disable entirely. Refer to the setting about `inline-diagnostics` for more details | "disable"
| `clipboard-provider` | Which API to use for clipboard interaction. One of `pasteboard` (MacOS), `wayland`, `x-clip`, `x-sel`, `win-32-yank`, `termux`, `tmux`, `windows`, `termcode`, `none`, or a custom command set. | Platform and environment specific. |
### `[editor.clipboard-provider]` Section
Helix can be configured either to use a builtin clipboard configuration or to use
a provided command.
For instance, setting it to use OSC 52 termcodes, the configuration would be:
```toml
[editor]
clipboard-provider = "termcode"
```
Alternatively, Helix can be configured to use arbitary commands for clipboard integration:
```toml
[editor.clipboard-provider.custom]
yank = { command = "cat", args = ["test.txt"] }
paste = { command = "tee", args = ["test.txt"] }
primary-yank = { command = "cat", args = ["test-primary.txt"] } # optional
primary-paste = { command = "tee", args = ["test-primary.txt"] } # optional
```
For custom commands the contents of the yank/paste is communicated over stdin/stdout.
### `[editor.statusline]` Section
Allows configuring the statusline at the bottom of the editor.
The configuration distinguishes between three areas of the status line:
`[ ... ... LEFT ... ... | ... ... ... CENTER ... ... ... | ... ... RIGHT ... ... ]`
Statusline elements can be defined as follows:
```toml
[editor.statusline]
left = ["mode", "spinner"]
center = ["file-name"]
right = ["diagnostics", "selections", "position", "file-encoding", "file-line-ending", "file-type"]
separator = "│"
mode.normal = "NORMAL"
mode.insert = "INSERT"
mode.select = "SELECT"
```
The `[editor.statusline]` key takes the following sub-keys:
| Key | Description | Default |
| --- | --- | --- |
| `left` | A list of elements aligned to the left of the statusline | `["mode", "spinner", "file-name", "read-only-indicator", "file-modification-indicator"]` |
| `center` | A list of elements aligned to the middle of the statusline | `[]` |
| `right` | A list of elements aligned to the right of the statusline | `["diagnostics", "selections", "register", "position", "file-encoding"]` |
| `separator` | The character used to separate elements in the statusline | `"│"` |
| `mode.normal` | The text shown in the `mode` element for normal mode | `"NOR"` |
| `mode.insert` | The text shown in the `mode` element for insert mode | `"INS"` |
| `mode.select` | The text shown in the `mode` element for select mode | `"SEL"` |
The following statusline elements can be configured:
| Key | Description |
| ------ | ----------- |
| `mode` | The current editor mode (`mode.normal`/`mode.insert`/`mode.select`) |
| `spinner` | A progress spinner indicating LSP activity |
| `file-name` | The path/name of the opened file |
| `file-absolute-path` | The absolute path/name of the opened file |
| `file-base-name` | The basename of the opened file |
| `file-modification-indicator` | The indicator to show whether the file is modified (a `[+]` appears when there are unsaved changes) |
| `file-encoding` | The encoding of the opened file if it differs from UTF-8 |
| `file-line-ending` | The file line endings (CRLF or LF) |
| `read-only-indicator` | An indicator that shows `[readonly]` when a file cannot be written |
| `total-line-numbers` | The total line numbers of the opened file |
| `file-type` | The type of the opened file |
| `diagnostics` | The number of warnings and/or errors |
| `workspace-diagnostics` | The number of warnings and/or errors on workspace |
| `selections` | The number of active selections |
| `primary-selection-length` | The number of characters currently in primary selection |
| `position` | The cursor position |
| `position-percentage` | The cursor position as a percentage of the total number of lines |
| `separator` | The string defined in `editor.statusline.separator` (defaults to `"│"`) |
| `spacer` | Inserts a space between elements (multiple/contiguous spacers may be specified) |
| `version-control` | The current branch name or detached commit hash of the opened workspace |
| `register` | The current selected register |
### `[editor.lsp]` Section
| Key | Description | Default |
| --- | ----------- | ------- |
| `enable` | Enables LSP integration. Setting to false will completely disable language servers regardless of language settings.| `true` |
| `display-messages` | Display LSP progress messages below statusline[^1] | `false` |
| `auto-signature-help` | Enable automatic popup of signature help (parameter hints) | `true` |
| `display-inlay-hints` | Display inlay hints[^2] | `false` |
| `display-signature-help-docs` | Display docs under signature help popup | `true` |
| `snippets` | Enables snippet completions. Requires a server restart (`:lsp-restart`) to take effect after `:config-reload`/`:set`. | `true` |
| `goto-reference-include-declaration` | Include declaration in the goto references popup. | `true` |
[^1]: By default, a progress spinner is shown in the statusline beside the file path.
[^2]: You may also have to activate them in the language server config for them to appear, not just in Helix. Inlay hints in Helix are still being improved on and may be a little bit laggy/janky under some circumstances. Please report any bugs you see so we can fix them!
### `[editor.cursor-shape]` Section
Defines the shape of cursor in each mode.
Valid values for these options are `block`, `bar`, `underline`, or `hidden`.
> 💡 Due to limitations of the terminal environment, only the primary cursor can
> change shape.
| Key | Description | Default |
| --- | ----------- | ------- |
| `normal` | Cursor shape in [normal mode][normal mode] | `block` |
| `insert` | Cursor shape in [insert mode][insert mode] | `block` |
| `select` | Cursor shape in [select mode][select mode] | `block` |
[normal mode]: ./keymap.md#normal-mode
[insert mode]: ./keymap.md#insert-mode
[select mode]: ./keymap.md#select--extend-mode
### `[editor.file-picker]` Section
Set options for file picker and global search. Ignoring a file means it is
not visible in the Helix file picker and global search.
All git related options are only enabled in a git repository.
| Key | Description | Default |
|--|--|---------|
|`hidden` | Enables ignoring hidden files | `true`
|`follow-symlinks` | Follow symlinks instead of ignoring them | `true`
|`deduplicate-links` | Ignore symlinks that point at files already shown in the picker | `true`
|`parents` | Enables reading ignore files from parent directories | `true`
|`ignore` | Enables reading `.ignore` files | `true`
|`git-ignore` | Enables reading `.gitignore` files | `true`
|`git-global` | Enables reading global `.gitignore`, whose path is specified in git's config: `core.excludesfile` option | `true`
|`git-exclude` | Enables reading `.git/info/exclude` files | `true`
|`max-depth` | Set with an integer value for maximum depth to recurse | Unset by default
Ignore files can be placed locally as `.ignore` or put in your home directory as `~/.ignore`. They support the usual ignore and negative ignore (unignore) rules used in `.gitignore` files.
Additionally, you can use Helix-specific ignore files by creating a local `.helix/ignore` file in the current workspace or a global `ignore` file located in your Helix config directory:
- Linux and Mac: `~/.config/helix/ignore`
- Windows: `%AppData%\helix\ignore`
Example:
```ini
# unignore in file picker and global search
!.github/
!.gitignore
!.gitattributes
```
### `[editor.auto-pairs]` Section
Enables automatic insertion of pairs to parentheses, brackets, etc. Can be a
simple boolean value, or a specific mapping of pairs of single characters.
To disable auto-pairs altogether, set `auto-pairs` to `false`:
```toml
[editor]
auto-pairs = false # defaults to `true`
```
The default pairs are <code>(){}[]''""``</code>, but these can be customized by
setting `auto-pairs` to a TOML table:
```toml
[editor.auto-pairs]
'(' = ')'
'{' = '}'
'[' = ']'
'"' = '"'
'`' = '`'
'<' = '>'
```
Additionally, this setting can be used in a language config. Unless
the editor setting is `false`, this will override the editor config in
documents with this language.
Example `languages.toml` that adds `<>` and removes `''`
```toml
[[language]]
name = "rust"
[language.auto-pairs]
'(' = ')'
'{' = '}'
'[' = ']'
'"' = '"'
'`' = '`'
'<' = '>'
```
### `[editor.auto-save]` Section
Control auto save behavior.
| Key | Description | Default |
|--|--|---------|
| `focus-lost` | Enable automatic saving on the focus moving away from Helix. Requires [focus event support](https://github.com/helix-editor/helix/wiki/Terminal-Support) from your terminal | `false` |
| `after-delay.enable` | Enable automatic saving after `auto-save.after-delay.timeout` milliseconds have passed since last edit. | `false` |
| `after-delay.timeout` | Time in milliseconds since last edit before auto save timer triggers. | `3000` |
### `[editor.search]` Section
Search specific options.
| Key | Description | Default |
|--|--|---------|
| `smart-case` | Enable smart case regex searching (case-insensitive unless pattern contains upper case characters) | `true` |
| `wrap-around`| Whether the search should wrap after depleting the matches | `true` |
### `[editor.whitespace]` Section
Options for rendering whitespace with visible characters. Use `:set whitespace.render all` to temporarily enable visible whitespace.
| Key | Description | Default |
|-----|-------------|---------|
| `render` | Whether to render whitespace. May either be `all` or `none`, or a table with sub-keys `space`, `nbsp`, `nnbsp`, `tab`, and `newline` | `none` |
| `characters` | Literal characters to use when rendering whitespace. Sub-keys may be any of `tab`, `space`, `nbsp`, `nnbsp`, `newline` or `tabpad` | See example below |
Example
```toml
[editor.whitespace]
render = "all"
# or control each character
[editor.whitespace.render]
space = "all"
tab = "all"
nbsp = "none"
nnbsp = "none"
newline = "none"
[editor.whitespace.characters]
space = "·"
nbsp = "⍽"
nnbsp = "␣"
tab = "→"
newline = "⏎"
tabpad = "·" # Tabs will look like "→···" (depending on tab width)
```
### `[editor.indent-guides]` Section
Options for rendering vertical indent guides.
| Key | Description | Default |
| --- | --- | --- |
| `render` | Whether to render indent guides | `false` |
| `character` | Literal character to use for rendering the indent guide | `│` |
| `skip-levels` | Number of indent levels to skip | `0` |
Example:
```toml
[editor.indent-guides]
render = true
character = "╎" # Some characters that work well: "▏", "┆", "┊", "⸽"
skip-levels = 1
```
### `[editor.gutters]` Section
For simplicity, `editor.gutters` accepts an array of gutter types, which will
use default settings for all gutter components.
```toml
[editor]
gutters = ["diff", "diagnostics", "line-numbers", "spacer"]
```
To customize the behavior of gutters, the `[editor.gutters]` section must
be used. This section contains top level settings, as well as settings for
specific gutter components as subsections.
| Key | Description | Default |
| --- | --- | --- |
| `layout` | A vector of gutters to display | `["diagnostics", "spacer", "line-numbers", "spacer", "diff"]` |
Example:
```toml
[editor.gutters]
layout = ["diff", "diagnostics", "line-numbers", "spacer"]
```
#### `[editor.gutters.line-numbers]` Section
Options for the line number gutter
| Key | Description | Default |
| --- | --- | --- |
| `min-width` | The minimum number of characters to use | `3` |
Example:
```toml
[editor.gutters.line-numbers]
min-width = 1
```
#### `[editor.gutters.diagnostics]` Section
Currently unused
#### `[editor.gutters.diff]` Section
The `diff` gutter option displays colored bars indicating whether a `git` diff represents that a line was added, removed or changed.
These colors are controlled by the theme attributes `diff.plus`, `diff.minus` and `diff.delta`.
Other diff providers will eventually be supported by a future plugin system.
There are currently no options for this section.
#### `[editor.gutters.spacer]` Section
Currently unused
### `[editor.soft-wrap]` Section
Options for soft wrapping lines that exceed the view width:
| Key | Description | Default |
| --- | --- | --- |
| `enable` | Whether soft wrapping is enabled. | `false` |
| `max-wrap` | Maximum free space left at the end of the line. | `20` |
| `max-indent-retain` | Maximum indentation to carry over when soft wrapping a line. | `40` |
| `wrap-indicator` | Text inserted before soft wrapped lines, highlighted with `ui.virtual.wrap` | `↪ ` |
| `wrap-at-text-width` | Soft wrap at `text-width` instead of using the full viewport size. | `false` |
Example:
```toml
[editor.soft-wrap]
enable = true
max-wrap = 25 # increase value to reduce forced mid-word wrapping
max-indent-retain = 0
wrap-indicator = "" # set wrap-indicator to "" to hide it
```
### `[editor.smart-tab]` Section
Options for navigating and editing using tab key.
| Key | Description | Default |
|------------|-------------|---------|
| `enable` | If set to true, then when the cursor is in a position with non-whitespace to its left, instead of inserting a tab, it will run `move_parent_node_end`. If there is only whitespace to the left, then it inserts a tab as normal. With the default bindings, to explicitly insert a tab character, press Shift-tab. | `true` |
| `supersede-menu` | Normally, when a menu is on screen, such as when auto complete is triggered, the tab key is bound to cycling through the items. This means when menus are on screen, one cannot use the tab key to trigger the `smart-tab` command. If this option is set to true, the `smart-tab` command always takes precedence, which means one cannot use the tab key to cycle through menu items. One of the other bindings must be used instead, such as arrow keys or `C-n`/`C-p`. | `false` |
Due to lack of support for S-tab in some terminals, the default keybindings don't fully embrace smart-tab editing experience. If you enjoy smart-tab navigation and a terminal that supports the [Enhanced Keyboard protocol](https://github.com/helix-editor/helix/wiki/Terminal-Support#enhanced-keyboard-protocol), consider setting extra keybindings:
```
[keys.normal]
tab = "move_parent_node_end"
S-tab = "move_parent_node_start"
[keys.insert]
S-tab = "move_parent_node_start"
[keys.select]
tab = "extend_parent_node_end"
S-tab = "extend_parent_node_start"
```
### `[editor.inline-diagnostics]` Section
Options for rendering diagnostics inside the text like shown below
```
fn main() {
let foo = bar;
└─ no such value in this scope
}
````
| Key | Description | Default |
|------------|-------------|---------|
| `cursor-line` | The minimum severity that a diagnostic must have to be shown inline on the line that contains the primary cursor. Set to `disable` to not show any diagnostics inline. This option does not have any effect when in insert-mode and will only take effect 350ms after moving the cursor to a different line. | `"disable"` |
| `other-lines` | The minimum severity that a diagnostic must have to be shown inline on a line that does not contain the cursor-line. Set to `disable` to not show any diagnostics inline. | `"disable"` |
| `prefix-len` | How many horizontal bars `─` are rendered before the diagnostic text. | `1` |
| `max-wrap` | Equivalent of the `editor.soft-wrap.max-wrap` option for diagnostics. | `20` |
| `max-diagnostics` | Maximum number of diagnostics to render inline for a given line | `10` |
The allowed values for `cursor-line` and `other-lines` are: `error`, `warning`, `info`, `hint`.
The (first) diagnostic with the highest severity that is not shown inline is rendered at the end of the line (as long as its severity is higher than the `end-of-line-diagnostics` config option):
```
fn main() {
let baz = 1;
let foo = bar; a local variable with a similar name exists: baz
└─ no such value in this scope
}
```
The new diagnostic rendering is not yet enabled by default. As soon as end of line or inline diagnostics are enabled the old diagnostics rendering is automatically disabled. The recommended default setting are:
```toml
[editor]
end-of-line-diagnostics = "hint"
[editor.inline-diagnostics]
cursor-line = "warning" # show warnings and errors on the cursorline inline
```

View File

@@ -1,122 +1,180 @@
| Language | Syntax Highlighting | Treesitter Textobjects | Auto Indent | Default LSP | | Language | Syntax Highlighting | Treesitter Textobjects | Auto Indent | Default language servers |
| --- | --- | --- | --- | --- | | --- | --- | --- | --- | --- |
| ada | ✓ | ✓ | | `ada_language_server` |
| adl | ✓ | ✓ | ✓ | |
| agda | ✓ | | | |
| amber | ✓ | | | |
| astro | ✓ | | | | | astro | ✓ | | | |
| awk | ✓ | ✓ | | `awk-language-server` | | awk | ✓ | ✓ | | `awk-language-server` |
| bash | ✓ | | ✓ | `bash-language-server` | | bash | ✓ | | ✓ | `bash-language-server` |
| bass | ✓ | | | `bass` | | bass | ✓ | | | `bass` |
| beancount | ✓ | | | | | beancount | ✓ | | | |
| bibtex | ✓ | | | `texlab` | | bibtex | ✓ | | | `texlab` |
| bicep | ✓ | | | `bicep-langserver` | | bicep | ✓ | | | `bicep-langserver` |
| bitbake | ✓ | | | `bitbake-language-server` |
| blade | ✓ | | | |
| blueprint | ✓ | | | `blueprint-compiler` |
| c | ✓ | ✓ | ✓ | `clangd` | | c | ✓ | ✓ | ✓ | `clangd` |
| c-sharp | ✓ | ✓ | | `OmniSharp` | | c-sharp | ✓ | ✓ | | `OmniSharp` |
| cabal | | | | | | cabal | | | | `haskell-language-server-wrapper` |
| cairo | ✓ | | | | | cairo | ✓ | | | `cairo-language-server` |
| capnp | ✓ | | ✓ | | | capnp | ✓ | | ✓ | |
| cel | ✓ | | | |
| circom | ✓ | | | `circom-lsp` |
| clojure | ✓ | | | `clojure-lsp` | | clojure | ✓ | | | `clojure-lsp` |
| cmake | ✓ | ✓ | ✓ | `cmake-language-server` | | cmake | ✓ | ✓ | ✓ | `cmake-language-server` |
| comment | ✓ | | | | | comment | ✓ | | | |
| common-lisp | ✓ | | | `cl-lsp` | | common-lisp | ✓ | | | `cl-lsp` |
| cpon | ✓ | | ✓ | | | cpon | ✓ | | ✓ | |
| cpp | ✓ | ✓ | ✓ | `clangd` | | cpp | ✓ | ✓ | ✓ | `clangd` |
| crystal | ✓ | ✓ | | | | crystal | ✓ | ✓ | | `crystalline` |
| css | ✓ | | | `vscode-css-language-server` | | css | ✓ | | | `vscode-css-language-server` |
| cue | ✓ | | | `cuelsp` | | cue | ✓ | | | `cuelsp` |
| cylc | ✓ | ✓ | ✓ | |
| d | ✓ | ✓ | ✓ | `serve-d` | | d | ✓ | ✓ | ✓ | `serve-d` |
| dart | ✓ | | ✓ | `dart` | | dart | ✓ | | ✓ | `dart` |
| dbml | ✓ | | | |
| devicetree | ✓ | | | | | devicetree | ✓ | | | |
| dhall | ✓ | ✓ | | `dhall-lsp-server` | | dhall | ✓ | ✓ | | `dhall-lsp-server` |
| diff | ✓ | | | | | diff | ✓ | | | |
| dockerfile | ✓ | | | `docker-langserver` | | docker-compose | ✓ | | | `docker-compose-langserver`, `yaml-language-server` |
| dockerfile | ✓ | ✓ | | `docker-langserver` |
| dot | ✓ | | | `dot-language-server` | | dot | ✓ | | | `dot-language-server` |
| dtd | ✓ | | | | | dtd | ✓ | | | |
| dune | ✓ | | | |
| earthfile | ✓ | ✓ | ✓ | `earthlyls` |
| edoc | ✓ | | | | | edoc | ✓ | | | |
| eex | ✓ | | | | | eex | ✓ | | | |
| ejs | ✓ | | | | | ejs | ✓ | | | |
| elisp | ✓ | | | |
| elixir | ✓ | ✓ | ✓ | `elixir-ls` | | elixir | ✓ | ✓ | ✓ | `elixir-ls` |
| elm | ✓ | ✓ | | `elm-language-server` | | elm | ✓ | ✓ | | `elm-language-server` |
| elvish | ✓ | | | `elvish` | | elvish | ✓ | | | `elvish` |
| env | ✓ | | | | | env | ✓ | | | |
| erb | ✓ | | | | | erb | ✓ | | | |
| erlang | ✓ | ✓ | | `erlang_ls` | | erlang | ✓ | ✓ | | `erlang_ls`, `elp` |
| esdl | ✓ | | | | | esdl | ✓ | | | |
| fidl | ✓ | | | |
| fish | ✓ | ✓ | ✓ | | | fish | ✓ | ✓ | ✓ | |
| forth | ✓ | | | `forth-lsp` |
| fortran | ✓ | | ✓ | `fortls` | | fortran | ✓ | | ✓ | `fortls` |
| fsharp | ✓ | | | `fsautocomplete` |
| gas | ✓ | ✓ | | |
| gdscript | ✓ | ✓ | ✓ | | | gdscript | ✓ | ✓ | ✓ | |
| gemini | ✓ | | | |
| gherkin | ✓ | | | |
| git-attributes | ✓ | | | | | git-attributes | ✓ | | | |
| git-commit | ✓ | ✓ | | | | git-commit | ✓ | ✓ | | |
| git-config | ✓ | | | | | git-config | ✓ | | | |
| git-ignore | ✓ | | | | | git-ignore | ✓ | | | |
| git-rebase | ✓ | | | | | git-rebase | ✓ | | | |
| gjs | ✓ | ✓ | ✓ | `typescript-language-server`, `vscode-eslint-language-server`, `ember-language-server` |
| gleam | ✓ | ✓ | | `gleam` | | gleam | ✓ | ✓ | | `gleam` |
| glsl | ✓ | ✓ | | | | glimmer | ✓ | | | `ember-language-server` |
| go | ✓ | ✓ | ✓ | `gopls` | | glsl | ✓ | ✓ | ✓ | `glsl_analyzer` |
| godot-resource | ✓ | | | | | gn | ✓ | | | |
| go | ✓ | ✓ | ✓ | `gopls`, `golangci-lint-langserver` |
| godot-resource | ✓ | ✓ | | |
| gomod | ✓ | | | `gopls` | | gomod | ✓ | | | `gopls` |
| gotmpl | ✓ | | | `gopls` | | gotmpl | ✓ | | | `gopls` |
| gowork | ✓ | | | `gopls` | | gowork | ✓ | | | `gopls` |
| graphql | ✓ | | | | | gpr | ✓ | | | `ada_language_server` |
| graphql | ✓ | ✓ | | `graphql-lsp` |
| groovy | ✓ | | | |
| gts | ✓ | ✓ | ✓ | `typescript-language-server`, `vscode-eslint-language-server`, `ember-language-server` |
| hare | ✓ | | | | | hare | ✓ | | | |
| haskell | ✓ | ✓ | | `haskell-language-server-wrapper` | | haskell | ✓ | ✓ | | `haskell-language-server-wrapper` |
| hcl | ✓ | | | `terraform-ls` | | haskell-persistent | ✓ | | | |
| hcl | ✓ | ✓ | ✓ | `terraform-ls` |
| heex | ✓ | ✓ | | `elixir-ls` | | heex | ✓ | ✓ | | `elixir-ls` |
| helm | ✓ | | | `helm_ls` |
| hocon | ✓ | ✓ | ✓ | |
| hoon | ✓ | | | |
| hosts | ✓ | | | | | hosts | ✓ | | | |
| html | ✓ | | | `vscode-html-language-server` | | html | ✓ | | | `vscode-html-language-server`, `superhtml` |
| hurl | ✓ | | ✓ | | | hurl | ✓ | | ✓ | |
| hyprlang | ✓ | | ✓ | `hyprls` |
| idris | | | | `idris2-lsp` | | idris | | | | `idris2-lsp` |
| iex | ✓ | | | | | iex | ✓ | | | |
| ini | ✓ | | | | | ini | ✓ | | | |
| java | ✓ | ✓ | | `jdtls` | | inko | ✓ | ✓ | | |
| janet | ✓ | | | |
| java | ✓ | ✓ | ✓ | `jdtls` |
| javascript | ✓ | ✓ | ✓ | `typescript-language-server` | | javascript | ✓ | ✓ | ✓ | `typescript-language-server` |
| jinja | ✓ | | | |
| jjdescription | ✓ | | | |
| jq | ✓ | ✓ | | `jq-lsp` |
| jsdoc | ✓ | | | | | jsdoc | ✓ | | | |
| json | ✓ | | ✓ | `vscode-json-language-server` | | json | ✓ | | ✓ | `vscode-json-language-server` |
| json5 | ✓ | | | |
| jsonc | ✓ | | ✓ | `vscode-json-language-server` |
| jsonnet | ✓ | | | `jsonnet-language-server` | | jsonnet | ✓ | | | `jsonnet-language-server` |
| jsx | ✓ | ✓ | ✓ | `typescript-language-server` | | jsx | ✓ | ✓ | ✓ | `typescript-language-server` |
| julia | ✓ | ✓ | ✓ | `julia` | | julia | ✓ | ✓ | ✓ | `julia` |
| kdl | ✓ | | | | | just | ✓ | ✓ | | |
| kdl | ✓ | ✓ | ✓ | |
| koka | ✓ | | ✓ | `koka` |
| kotlin | ✓ | | | `kotlin-language-server` | | kotlin | ✓ | | | `kotlin-language-server` |
| koto | ✓ | ✓ | ✓ | `koto-ls` |
| latex | ✓ | ✓ | | `texlab` | | latex | ✓ | ✓ | | `texlab` |
| ld | ✓ | | ✓ | |
| ldif | ✓ | | | |
| lean | ✓ | | | `lean` | | lean | ✓ | | | `lean` |
| ledger | ✓ | | | | | ledger | ✓ | | | |
| llvm | ✓ | ✓ | ✓ | | | llvm | ✓ | ✓ | ✓ | |
| llvm-mir | ✓ | ✓ | ✓ | | | llvm-mir | ✓ | ✓ | ✓ | |
| llvm-mir-yaml | ✓ | | ✓ | | | llvm-mir-yaml | ✓ | | ✓ | |
| log | ✓ | | | |
| lpf | ✓ | | | |
| lua | ✓ | ✓ | ✓ | `lua-language-server` | | lua | ✓ | ✓ | ✓ | `lua-language-server` |
| make | ✓ | | | | | make | ✓ | | | |
| markdoc | ✓ | | | `markdoc-ls` | | markdoc | ✓ | | | `markdoc-ls` |
| markdown | ✓ | | | `marksman` | | markdown | ✓ | | | `marksman`, `markdown-oxide` |
| markdown.inline | ✓ | | | | | markdown.inline | ✓ | | | |
| matlab | ✓ | | | | | matlab | ✓ | | | |
| mermaid | ✓ | | | | | mermaid | ✓ | | | |
| meson | ✓ | | ✓ | | | meson | ✓ | | ✓ | `mesonlsp` |
| mint | | | | `mint` | | mint | | | | `mint` |
| mojo | ✓ | ✓ | ✓ | `magic` |
| move | ✓ | | | |
| msbuild | ✓ | | ✓ | | | msbuild | ✓ | | ✓ | |
| nasm | ✓ | ✓ | | | | nasm | ✓ | ✓ | | |
| nestedtext | ✓ | ✓ | ✓ | |
| nickel | ✓ | | ✓ | `nls` | | nickel | ✓ | | ✓ | `nls` |
| nim | ✓ | ✓ | ✓ | `nimlangserver` | | nim | ✓ | ✓ | ✓ | `nimlangserver` |
| nix | ✓ | | | `nil` | | nix | ✓ | | | `nil`, `nixd` |
| nu | ✓ | | | | | nu | ✓ | | | `nu` |
| nunjucks | ✓ | | | |
| ocaml | ✓ | | ✓ | `ocamllsp` | | ocaml | ✓ | | ✓ | `ocamllsp` |
| ocaml-interface | ✓ | | | `ocamllsp` | | ocaml-interface | ✓ | | | `ocamllsp` |
| odin | ✓ | | | `ols` | | odin | ✓ | | | `ols` |
| ohm | ✓ | ✓ | ✓ | |
| opencl | ✓ | ✓ | ✓ | `clangd` | | opencl | ✓ | ✓ | ✓ | `clangd` |
| openscad | ✓ | | | `openscad-lsp` | | openscad | ✓ | | | `openscad-lsp` |
| org | ✓ | | | | | org | ✓ | | | |
| pascal | ✓ | ✓ | | `pasls` | | pascal | ✓ | ✓ | | `pasls` |
| passwd | ✓ | | | | | passwd | ✓ | | | |
| pem | ✓ | | | | | pem | ✓ | | | |
| perl | ✓ | ✓ | ✓ | | | perl | ✓ | ✓ | ✓ | `perlnavigator` |
| pest | ✓ | ✓ | ✓ | `pest-language-server` |
| php | ✓ | ✓ | ✓ | `intelephense` | | php | ✓ | ✓ | ✓ | `intelephense` |
| php-only | ✓ | | | |
| pkgbuild | ✓ | ✓ | ✓ | `pkgbuild-language-server`, `bash-language-server` |
| pkl | ✓ | | ✓ | |
| po | ✓ | ✓ | | | | po | ✓ | ✓ | | |
| pod | ✓ | | | |
| ponylang | ✓ | ✓ | ✓ | | | ponylang | ✓ | ✓ | ✓ | |
| prisma | ✓ | | | `prisma-language-server` | | powershell | ✓ | | | |
| prisma | ✓ | ✓ | | `prisma-language-server` |
| prolog | | | | `swipl` | | prolog | | | | `swipl` |
| protobuf | ✓ | | ✓ | | | protobuf | ✓ | | ✓ | `bufls`, `pb` |
| prql | ✓ | | | | | prql | ✓ | | | |
| purescript | ✓ | | | `purescript-language-server` | | purescript | ✓ | | | `purescript-language-server` |
| python | ✓ | ✓ | ✓ | `pylsp` | | python | ✓ | ✓ | ✓ | `ruff`, `jedi-language-server`, `pylsp` |
| qml | ✓ | | ✓ | `qmlls` | | qml | ✓ | | ✓ | `qmlls` |
| quint | ✓ | | | `quint-language-server` |
| r | ✓ | | | `R` | | r | ✓ | | | `R` |
| racket | ✓ | | | `racket` | | racket | ✓ | | | `racket` |
| regex | ✓ | | | | | regex | ✓ | | | |
| rego | ✓ | | | `regols` | | rego | ✓ | | | `regols` |
| rescript | ✓ | ✓ | | `rescript-language-server` | | rescript | ✓ | ✓ | | `rescript-language-server` |
@@ -127,41 +185,62 @@
| ruby | ✓ | ✓ | ✓ | `solargraph` | | ruby | ✓ | ✓ | ✓ | `solargraph` |
| rust | ✓ | ✓ | ✓ | `rust-analyzer` | | rust | ✓ | ✓ | ✓ | `rust-analyzer` |
| sage | ✓ | ✓ | | | | sage | ✓ | ✓ | | |
| scala | ✓ | | ✓ | `metals` | | scala | ✓ | | ✓ | `metals` |
| scheme | ✓ | | | | | scheme | ✓ | | | |
| scss | ✓ | | | `vscode-css-language-server` | | scss | ✓ | | | `vscode-css-language-server` |
| slint | ✓ | | ✓ | `slint-lsp` | | slint | ✓ | | ✓ | `slint-lsp` |
| smali | ✓ | | ✓ | |
| smithy | ✓ | | | `cs` | | smithy | ✓ | | | `cs` |
| sml | ✓ | | | | | sml | ✓ | | | |
| solidity | ✓ | | | `solc` | | snakemake | ✓ | | | `pylsp` |
| sql | ✓ | | | | | solidity | ✓ | | | `solc` |
| spade | ✓ | | ✓ | `spade-language-server` |
| spicedb | ✓ | | | |
| sql | ✓ | ✓ | | |
| sshclientconfig | ✓ | | | | | sshclientconfig | ✓ | | | |
| starlark | ✓ | ✓ | | | | starlark | ✓ | ✓ | | |
| svelte | ✓ | | | `svelteserver` | | strace | ✓ | | | |
| supercollider | ✓ | | | |
| svelte | ✓ | | ✓ | `svelteserver` |
| sway | ✓ | ✓ | ✓ | `forc` | | sway | ✓ | ✓ | ✓ | `forc` |
| swift | ✓ | | | `sourcekit-lsp` | | swift | ✓ | | | `sourcekit-lsp` |
| t32 | ✓ | | | |
| tablegen | ✓ | ✓ | ✓ | | | tablegen | ✓ | ✓ | ✓ | |
| tact | ✓ | ✓ | ✓ | |
| task | ✓ | | | | | task | ✓ | | | |
| tcl | ✓ | | ✓ | |
| teal | ✓ | | | |
| templ | ✓ | | | `templ` |
| textproto | ✓ | ✓ | ✓ | |
| tfvars | ✓ | | ✓ | `terraform-ls` | | tfvars | ✓ | | ✓ | `terraform-ls` |
| toml | ✓ | | | `taplo` | | thrift | ✓ | | | |
| todotxt | ✓ | | | |
| toml | ✓ | ✓ | | `taplo` |
| tsq | ✓ | | | | | tsq | ✓ | | | |
| tsx | ✓ | ✓ | ✓ | `typescript-language-server` | | tsx | ✓ | ✓ | ✓ | `typescript-language-server` |
| twig | ✓ | | | | | twig | ✓ | | | |
| typescript | ✓ | ✓ | ✓ | `typescript-language-server` | | typescript | ✓ | ✓ | ✓ | `typescript-language-server` |
| typespec | ✓ | ✓ | ✓ | `tsp-server` |
| typst | ✓ | | | `tinymist`, `typst-lsp` |
| ungrammar | ✓ | | | | | ungrammar | ✓ | | | |
| unison | ✓ | ✓ | ✓ | |
| uxntal | ✓ | | | | | uxntal | ✓ | | | |
| v | ✓ | ✓ | ✓ | `v` | | v | ✓ | ✓ | ✓ | `v-analyzer` |
| vala | ✓ | | | `vala-language-server` | | vala | ✓ | | | `vala-language-server` |
| vento | ✓ | | | |
| verilog | ✓ | ✓ | | `svlangserver` | | verilog | ✓ | ✓ | | `svlangserver` |
| vhdl | ✓ | | | `vhdl_ls` | | vhdl | ✓ | | | `vhdl_ls` |
| vhs | ✓ | | | | | vhs | ✓ | | | |
| vue | ✓ | | | `vls` | | vue | ✓ | | | `vue-language-server` |
| wast | ✓ | | | | | wast | ✓ | | | |
| wat | ✓ | | | | | wat | ✓ | | | |
| webc | ✓ | | | |
| wgsl | ✓ | | | `wgsl_analyzer` | | wgsl | ✓ | | | `wgsl_analyzer` |
| wit | ✓ | | ✓ | | | wit | ✓ | | ✓ | |
| wren | ✓ | ✓ | ✓ | |
| xit | ✓ | | | | | xit | ✓ | | | |
| xml | ✓ | | ✓ | | | xml | ✓ | | ✓ | |
| yaml | ✓ | | | `yaml-language-server` | | xtc | ✓ | | | |
| yaml | ✓ | ✓ | ✓ | `yaml-language-server`, `ansible-language-server` |
| yuck | ✓ | | | | | yuck | ✓ | | | |
| zig | ✓ | ✓ | ✓ | `zls` | | zig | ✓ | ✓ | ✓ | `zls` |

View File

@@ -0,0 +1,296 @@
| Name | Description | Default keybinds |
| --- | --- | --- |
| `no_op` | Do nothing | |
| `move_char_left` | Move left | normal: `` h ``, `` <left> ``, insert: `` <left> `` |
| `move_char_right` | Move right | normal: `` l ``, `` <right> ``, insert: `` <right> `` |
| `move_line_up` | Move up | normal: `` gk `` |
| `move_line_down` | Move down | normal: `` gj `` |
| `move_visual_line_up` | Move up | normal: `` k ``, `` <up> ``, insert: `` <up> `` |
| `move_visual_line_down` | Move down | normal: `` j ``, `` <down> ``, insert: `` <down> `` |
| `extend_char_left` | Extend left | select: `` h ``, `` <left> `` |
| `extend_char_right` | Extend right | select: `` l ``, `` <right> `` |
| `extend_line_up` | Extend up | select: `` gk `` |
| `extend_line_down` | Extend down | select: `` gj `` |
| `extend_visual_line_up` | Extend up | select: `` k ``, `` <up> `` |
| `extend_visual_line_down` | Extend down | select: `` j ``, `` <down> `` |
| `copy_selection_on_next_line` | Copy selection on next line | normal: `` C ``, select: `` C `` |
| `copy_selection_on_prev_line` | Copy selection on previous line | normal: `` <A-C> ``, select: `` <A-C> `` |
| `move_next_word_start` | Move to start of next word | normal: `` w `` |
| `move_prev_word_start` | Move to start of previous word | normal: `` b `` |
| `move_next_word_end` | Move to end of next word | normal: `` e `` |
| `move_prev_word_end` | Move to end of previous word | |
| `move_next_long_word_start` | Move to start of next long word | normal: `` W `` |
| `move_prev_long_word_start` | Move to start of previous long word | normal: `` B `` |
| `move_next_long_word_end` | Move to end of next long word | normal: `` E `` |
| `move_prev_long_word_end` | Move to end of previous long word | |
| `move_next_sub_word_start` | Move to start of next sub word | |
| `move_prev_sub_word_start` | Move to start of previous sub word | |
| `move_next_sub_word_end` | Move to end of next sub word | |
| `move_prev_sub_word_end` | Move to end of previous sub word | |
| `move_parent_node_end` | Move to end of the parent node | normal: `` <A-e> `` |
| `move_parent_node_start` | Move to beginning of the parent node | normal: `` <A-b> `` |
| `extend_next_word_start` | Extend to start of next word | select: `` w `` |
| `extend_prev_word_start` | Extend to start of previous word | select: `` b `` |
| `extend_next_word_end` | Extend to end of next word | select: `` e `` |
| `extend_prev_word_end` | Extend to end of previous word | |
| `extend_next_long_word_start` | Extend to start of next long word | select: `` W `` |
| `extend_prev_long_word_start` | Extend to start of previous long word | select: `` B `` |
| `extend_next_long_word_end` | Extend to end of next long word | select: `` E `` |
| `extend_prev_long_word_end` | Extend to end of prev long word | |
| `extend_next_sub_word_start` | Extend to start of next sub word | |
| `extend_prev_sub_word_start` | Extend to start of previous sub word | |
| `extend_next_sub_word_end` | Extend to end of next sub word | |
| `extend_prev_sub_word_end` | Extend to end of prev sub word | |
| `extend_parent_node_end` | Extend to end of the parent node | select: `` <A-e> `` |
| `extend_parent_node_start` | Extend to beginning of the parent node | select: `` <A-b> `` |
| `find_till_char` | Move till next occurrence of char | normal: `` t `` |
| `find_next_char` | Move to next occurrence of char | normal: `` f `` |
| `extend_till_char` | Extend till next occurrence of char | select: `` t `` |
| `extend_next_char` | Extend to next occurrence of char | select: `` f `` |
| `till_prev_char` | Move till previous occurrence of char | normal: `` T `` |
| `find_prev_char` | Move to previous occurrence of char | normal: `` F `` |
| `extend_till_prev_char` | Extend till previous occurrence of char | select: `` T `` |
| `extend_prev_char` | Extend to previous occurrence of char | select: `` F `` |
| `repeat_last_motion` | Repeat last motion | normal: `` <A-.> ``, select: `` <A-.> `` |
| `replace` | Replace with new char | normal: `` r ``, select: `` r `` |
| `switch_case` | Switch (toggle) case | normal: `` ~ ``, select: `` ~ `` |
| `switch_to_uppercase` | Switch to uppercase | normal: `` <A-`> ``, select: `` <A-`> `` |
| `switch_to_lowercase` | Switch to lowercase | normal: `` ` ``, select: `` ` `` |
| `page_up` | Move page up | normal: `` <C-b> ``, `` Z<C-b> ``, `` z<C-b> ``, `` <pageup> ``, `` Z<pageup> ``, `` z<pageup> ``, select: `` <C-b> ``, `` Z<C-b> ``, `` z<C-b> ``, `` <pageup> ``, `` Z<pageup> ``, `` z<pageup> ``, insert: `` <pageup> `` |
| `page_down` | Move page down | normal: `` <C-f> ``, `` Z<C-f> ``, `` z<C-f> ``, `` <pagedown> ``, `` Z<pagedown> ``, `` z<pagedown> ``, select: `` <C-f> ``, `` Z<C-f> ``, `` z<C-f> ``, `` <pagedown> ``, `` Z<pagedown> ``, `` z<pagedown> ``, insert: `` <pagedown> `` |
| `half_page_up` | Move half page up | |
| `half_page_down` | Move half page down | |
| `page_cursor_up` | Move page and cursor up | |
| `page_cursor_down` | Move page and cursor down | |
| `page_cursor_half_up` | Move page and cursor half up | normal: `` <C-u> ``, `` Z<C-u> ``, `` z<C-u> ``, `` Z<backspace> ``, `` z<backspace> ``, select: `` <C-u> ``, `` Z<C-u> ``, `` z<C-u> ``, `` Z<backspace> ``, `` z<backspace> `` |
| `page_cursor_half_down` | Move page and cursor half down | normal: `` <C-d> ``, `` Z<C-d> ``, `` z<C-d> ``, `` Z<space> ``, `` z<space> ``, select: `` <C-d> ``, `` Z<C-d> ``, `` z<C-d> ``, `` Z<space> ``, `` z<space> `` |
| `select_all` | Select whole document | normal: `` % ``, select: `` % `` |
| `select_regex` | Select all regex matches inside selections | normal: `` s ``, select: `` s `` |
| `split_selection` | Split selections on regex matches | normal: `` S ``, select: `` S `` |
| `split_selection_on_newline` | Split selection on newlines | normal: `` <A-s> ``, select: `` <A-s> `` |
| `merge_selections` | Merge selections | normal: `` <A-minus> ``, select: `` <A-minus> `` |
| `merge_consecutive_selections` | Merge consecutive selections | normal: `` <A-_> ``, select: `` <A-_> `` |
| `search` | Search for regex pattern | normal: `` / ``, `` Z/ ``, `` z/ ``, select: `` / ``, `` Z/ ``, `` z/ `` |
| `rsearch` | Reverse search for regex pattern | normal: `` ? ``, `` Z? ``, `` z? ``, select: `` ? ``, `` Z? ``, `` z? `` |
| `search_next` | Select next search match | normal: `` n ``, `` Zn ``, `` zn ``, select: `` Zn ``, `` zn `` |
| `search_prev` | Select previous search match | normal: `` N ``, `` ZN ``, `` zN ``, select: `` ZN ``, `` zN `` |
| `extend_search_next` | Add next search match to selection | select: `` n `` |
| `extend_search_prev` | Add previous search match to selection | select: `` N `` |
| `search_selection` | Use current selection as search pattern | normal: `` <A-*> ``, select: `` <A-*> `` |
| `search_selection_detect_word_boundaries` | Use current selection as the search pattern, automatically wrapping with `\b` on word boundaries | normal: `` * ``, select: `` * `` |
| `make_search_word_bounded` | Modify current search to make it word bounded | |
| `global_search` | Global search in workspace folder | normal: `` <space>/ ``, select: `` <space>/ `` |
| `extend_line` | Select current line, if already selected, extend to another line based on the anchor | |
| `extend_line_below` | Select current line, if already selected, extend to next line | normal: `` x ``, select: `` x `` |
| `extend_line_above` | Select current line, if already selected, extend to previous line | |
| `select_line_above` | Select current line, if already selected, extend or shrink line above based on the anchor | |
| `select_line_below` | Select current line, if already selected, extend or shrink line below based on the anchor | |
| `extend_to_line_bounds` | Extend selection to line bounds | normal: `` X ``, select: `` X `` |
| `shrink_to_line_bounds` | Shrink selection to line bounds | normal: `` <A-x> ``, select: `` <A-x> `` |
| `delete_selection` | Delete selection | normal: `` d ``, select: `` d `` |
| `delete_selection_noyank` | Delete selection without yanking | normal: `` <A-d> ``, select: `` <A-d> `` |
| `change_selection` | Change selection | normal: `` c ``, select: `` c `` |
| `change_selection_noyank` | Change selection without yanking | normal: `` <A-c> ``, select: `` <A-c> `` |
| `collapse_selection` | Collapse selection into single cursor | normal: `` ; ``, select: `` ; `` |
| `flip_selections` | Flip selection cursor and anchor | normal: `` <A-;> ``, select: `` <A-;> `` |
| `ensure_selections_forward` | Ensure all selections face forward | normal: `` <A-:> ``, select: `` <A-:> `` |
| `insert_mode` | Insert before selection | normal: `` i ``, select: `` i `` |
| `append_mode` | Append after selection | normal: `` a ``, select: `` a `` |
| `command_mode` | Enter command mode | normal: `` : ``, select: `` : `` |
| `file_picker` | Open file picker | normal: `` <space>f ``, select: `` <space>f `` |
| `file_picker_in_current_buffer_directory` | Open file picker at current buffer's directory | |
| `file_picker_in_current_directory` | Open file picker at current working directory | normal: `` <space>F ``, select: `` <space>F `` |
| `code_action` | Perform code action | normal: `` <space>a ``, select: `` <space>a `` |
| `buffer_picker` | Open buffer picker | normal: `` <space>b ``, select: `` <space>b `` |
| `jumplist_picker` | Open jumplist picker | normal: `` <space>j ``, select: `` <space>j `` |
| `symbol_picker` | Open symbol picker | normal: `` <space>s ``, select: `` <space>s `` |
| `changed_file_picker` | Open changed file picker | normal: `` <space>g ``, select: `` <space>g `` |
| `select_references_to_symbol_under_cursor` | Select symbol references | normal: `` <space>h ``, select: `` <space>h `` |
| `workspace_symbol_picker` | Open workspace symbol picker | normal: `` <space>S ``, select: `` <space>S `` |
| `diagnostics_picker` | Open diagnostic picker | normal: `` <space>d ``, select: `` <space>d `` |
| `workspace_diagnostics_picker` | Open workspace diagnostic picker | normal: `` <space>D ``, select: `` <space>D `` |
| `last_picker` | Open last picker | normal: `` <space>' ``, select: `` <space>' `` |
| `insert_at_line_start` | Insert at start of line | normal: `` I ``, select: `` I `` |
| `insert_at_line_end` | Insert at end of line | normal: `` A ``, select: `` A `` |
| `open_below` | Open new line below selection | normal: `` o ``, select: `` o `` |
| `open_above` | Open new line above selection | normal: `` O ``, select: `` O `` |
| `normal_mode` | Enter normal mode | normal: `` <esc> ``, select: `` v ``, insert: `` <esc> `` |
| `select_mode` | Enter selection extend mode | normal: `` v `` |
| `exit_select_mode` | Exit selection mode | select: `` <esc> `` |
| `goto_definition` | Goto definition | normal: `` gd ``, select: `` gd `` |
| `goto_declaration` | Goto declaration | normal: `` gD ``, select: `` gD `` |
| `add_newline_above` | Add newline above | normal: `` [<space> ``, select: `` [<space> `` |
| `add_newline_below` | Add newline below | normal: `` ]<space> ``, select: `` ]<space> `` |
| `goto_type_definition` | Goto type definition | normal: `` gy ``, select: `` gy `` |
| `goto_implementation` | Goto implementation | normal: `` gi ``, select: `` gi `` |
| `goto_file_start` | Goto line number <n> else file start | normal: `` gg ``, select: `` gg `` |
| `goto_file_end` | Goto file end | |
| `goto_file` | Goto files/URLs in selections | normal: `` gf ``, select: `` gf `` |
| `goto_file_hsplit` | Goto files in selections (hsplit) | normal: `` <C-w>f ``, `` <space>wf ``, select: `` <C-w>f ``, `` <space>wf `` |
| `goto_file_vsplit` | Goto files in selections (vsplit) | normal: `` <C-w>F ``, `` <space>wF ``, select: `` <C-w>F ``, `` <space>wF `` |
| `goto_reference` | Goto references | normal: `` gr ``, select: `` gr `` |
| `goto_window_top` | Goto window top | normal: `` gt ``, select: `` gt `` |
| `goto_window_center` | Goto window center | normal: `` gc ``, select: `` gc `` |
| `goto_window_bottom` | Goto window bottom | normal: `` gb ``, select: `` gb `` |
| `goto_last_accessed_file` | Goto last accessed file | normal: `` ga ``, select: `` ga `` |
| `goto_last_modified_file` | Goto last modified file | normal: `` gm ``, select: `` gm `` |
| `goto_last_modification` | Goto last modification | normal: `` g. ``, select: `` g. `` |
| `goto_line` | Goto line | normal: `` G ``, select: `` G `` |
| `goto_last_line` | Goto last line | normal: `` ge ``, select: `` ge `` |
| `goto_first_diag` | Goto first diagnostic | normal: `` [D ``, select: `` [D `` |
| `goto_last_diag` | Goto last diagnostic | normal: `` ]D ``, select: `` ]D `` |
| `goto_next_diag` | Goto next diagnostic | normal: `` ]d ``, select: `` ]d `` |
| `goto_prev_diag` | Goto previous diagnostic | normal: `` [d ``, select: `` [d `` |
| `goto_next_change` | Goto next change | normal: `` ]g ``, select: `` ]g `` |
| `goto_prev_change` | Goto previous change | normal: `` [g ``, select: `` [g `` |
| `goto_first_change` | Goto first change | normal: `` [G ``, select: `` [G `` |
| `goto_last_change` | Goto last change | normal: `` ]G ``, select: `` ]G `` |
| `goto_line_start` | Goto line start | normal: `` gh ``, `` <home> ``, select: `` gh ``, insert: `` <home> `` |
| `goto_line_end` | Goto line end | normal: `` gl ``, `` <end> ``, select: `` gl `` |
| `goto_next_buffer` | Goto next buffer | normal: `` gn ``, select: `` gn `` |
| `goto_previous_buffer` | Goto previous buffer | normal: `` gp ``, select: `` gp `` |
| `goto_line_end_newline` | Goto newline at line end | insert: `` <end> `` |
| `goto_first_nonwhitespace` | Goto first non-blank in line | normal: `` gs ``, select: `` gs `` |
| `trim_selections` | Trim whitespace from selections | normal: `` _ ``, select: `` _ `` |
| `extend_to_line_start` | Extend to line start | select: `` <home> `` |
| `extend_to_first_nonwhitespace` | Extend to first non-blank in line | |
| `extend_to_line_end` | Extend to line end | select: `` <end> `` |
| `extend_to_line_end_newline` | Extend to line end | |
| `signature_help` | Show signature help | |
| `smart_tab` | Insert tab if all cursors have all whitespace to their left; otherwise, run a separate command. | insert: `` <tab> `` |
| `insert_tab` | Insert tab char | insert: `` <S-tab> `` |
| `insert_newline` | Insert newline char | insert: `` <C-j> ``, `` <ret> `` |
| `delete_char_backward` | Delete previous char | insert: `` <C-h> ``, `` <backspace> ``, `` <S-backspace> `` |
| `delete_char_forward` | Delete next char | insert: `` <C-d> ``, `` <del> `` |
| `delete_word_backward` | Delete previous word | insert: `` <C-w> ``, `` <A-backspace> `` |
| `delete_word_forward` | Delete next word | insert: `` <A-d> ``, `` <A-del> `` |
| `kill_to_line_start` | Delete till start of line | insert: `` <C-u> `` |
| `kill_to_line_end` | Delete till end of line | insert: `` <C-k> `` |
| `undo` | Undo change | normal: `` u ``, select: `` u `` |
| `redo` | Redo change | normal: `` U ``, select: `` U `` |
| `earlier` | Move backward in history | normal: `` <A-u> ``, select: `` <A-u> `` |
| `later` | Move forward in history | normal: `` <A-U> ``, select: `` <A-U> `` |
| `commit_undo_checkpoint` | Commit changes to new checkpoint | insert: `` <C-s> `` |
| `yank` | Yank selection | normal: `` y ``, select: `` y `` |
| `yank_to_clipboard` | Yank selections to clipboard | normal: `` <space>y ``, select: `` <space>y `` |
| `yank_to_primary_clipboard` | Yank selections to primary clipboard | |
| `yank_joined` | Join and yank selections | |
| `yank_joined_to_clipboard` | Join and yank selections to clipboard | |
| `yank_main_selection_to_clipboard` | Yank main selection to clipboard | normal: `` <space>Y ``, select: `` <space>Y `` |
| `yank_joined_to_primary_clipboard` | Join and yank selections to primary clipboard | |
| `yank_main_selection_to_primary_clipboard` | Yank main selection to primary clipboard | |
| `replace_with_yanked` | Replace with yanked text | normal: `` R ``, select: `` R `` |
| `replace_selections_with_clipboard` | Replace selections by clipboard content | normal: `` <space>R ``, select: `` <space>R `` |
| `replace_selections_with_primary_clipboard` | Replace selections by primary clipboard | |
| `paste_after` | Paste after selection | normal: `` p ``, select: `` p `` |
| `paste_before` | Paste before selection | normal: `` P ``, select: `` P `` |
| `paste_clipboard_after` | Paste clipboard after selections | normal: `` <space>p ``, select: `` <space>p `` |
| `paste_clipboard_before` | Paste clipboard before selections | normal: `` <space>P ``, select: `` <space>P `` |
| `paste_primary_clipboard_after` | Paste primary clipboard after selections | |
| `paste_primary_clipboard_before` | Paste primary clipboard before selections | |
| `indent` | Indent selection | normal: `` <gt> ``, select: `` <gt> `` |
| `unindent` | Unindent selection | normal: `` <lt> ``, select: `` <lt> `` |
| `format_selections` | Format selection | normal: `` = ``, select: `` = `` |
| `join_selections` | Join lines inside selection | normal: `` J ``, select: `` J `` |
| `join_selections_space` | Join lines inside selection and select spaces | normal: `` <A-J> ``, select: `` <A-J> `` |
| `keep_selections` | Keep selections matching regex | normal: `` K ``, select: `` K `` |
| `remove_selections` | Remove selections matching regex | normal: `` <A-K> ``, select: `` <A-K> `` |
| `align_selections` | Align selections in column | normal: `` & ``, select: `` & `` |
| `keep_primary_selection` | Keep primary selection | normal: `` , ``, select: `` , `` |
| `remove_primary_selection` | Remove primary selection | normal: `` <A-,> ``, select: `` <A-,> `` |
| `completion` | Invoke completion popup | insert: `` <C-x> `` |
| `hover` | Show docs for item under cursor | normal: `` <space>k ``, select: `` <space>k `` |
| `toggle_comments` | Comment/uncomment selections | normal: `` <C-c> ``, `` <space>c ``, select: `` <C-c> ``, `` <space>c `` |
| `toggle_line_comments` | Line comment/uncomment selections | normal: `` <space><A-c> ``, select: `` <space><A-c> `` |
| `toggle_block_comments` | Block comment/uncomment selections | normal: `` <space>C ``, select: `` <space>C `` |
| `rotate_selections_forward` | Rotate selections forward | normal: `` ) ``, select: `` ) `` |
| `rotate_selections_backward` | Rotate selections backward | normal: `` ( ``, select: `` ( `` |
| `rotate_selection_contents_forward` | Rotate selection contents forward | normal: `` <A-)> ``, select: `` <A-)> `` |
| `rotate_selection_contents_backward` | Rotate selections contents backward | normal: `` <A-(> ``, select: `` <A-(> `` |
| `reverse_selection_contents` | Reverse selections contents | |
| `expand_selection` | Expand selection to parent syntax node | normal: `` <A-o> ``, `` <A-up> ``, select: `` <A-o> ``, `` <A-up> `` |
| `shrink_selection` | Shrink selection to previously expanded syntax node | normal: `` <A-i> ``, `` <A-down> ``, select: `` <A-i> ``, `` <A-down> `` |
| `select_next_sibling` | Select next sibling in the syntax tree | normal: `` <A-n> ``, `` <A-right> ``, select: `` <A-n> ``, `` <A-right> `` |
| `select_prev_sibling` | Select previous sibling the in syntax tree | normal: `` <A-p> ``, `` <A-left> ``, select: `` <A-p> ``, `` <A-left> `` |
| `select_all_siblings` | Select all siblings of the current node | normal: `` <A-a> ``, select: `` <A-a> `` |
| `select_all_children` | Select all children of the current node | normal: `` <A-I> ``, `` <S-A-down> ``, select: `` <A-I> ``, `` <S-A-down> `` |
| `jump_forward` | Jump forward on jumplist | normal: `` <C-i> ``, `` <tab> ``, select: `` <C-i> ``, `` <tab> `` |
| `jump_backward` | Jump backward on jumplist | normal: `` <C-o> ``, select: `` <C-o> `` |
| `save_selection` | Save current selection to jumplist | normal: `` <C-s> ``, select: `` <C-s> `` |
| `jump_view_right` | Jump to right split | normal: `` <C-w>l ``, `` <space>wl ``, `` <C-w><C-l> ``, `` <C-w><right> ``, `` <space>w<C-l> ``, `` <space>w<right> ``, select: `` <C-w>l ``, `` <space>wl ``, `` <C-w><C-l> ``, `` <C-w><right> ``, `` <space>w<C-l> ``, `` <space>w<right> `` |
| `jump_view_left` | Jump to left split | normal: `` <C-w>h ``, `` <space>wh ``, `` <C-w><C-h> ``, `` <C-w><left> ``, `` <space>w<C-h> ``, `` <space>w<left> ``, select: `` <C-w>h ``, `` <space>wh ``, `` <C-w><C-h> ``, `` <C-w><left> ``, `` <space>w<C-h> ``, `` <space>w<left> `` |
| `jump_view_up` | Jump to split above | normal: `` <C-w>k ``, `` <C-w><up> ``, `` <space>wk ``, `` <C-w><C-k> ``, `` <space>w<up> ``, `` <space>w<C-k> ``, select: `` <C-w>k ``, `` <C-w><up> ``, `` <space>wk ``, `` <C-w><C-k> ``, `` <space>w<up> ``, `` <space>w<C-k> `` |
| `jump_view_down` | Jump to split below | normal: `` <C-w>j ``, `` <space>wj ``, `` <C-w><C-j> ``, `` <C-w><down> ``, `` <space>w<C-j> ``, `` <space>w<down> ``, select: `` <C-w>j ``, `` <space>wj ``, `` <C-w><C-j> ``, `` <C-w><down> ``, `` <space>w<C-j> ``, `` <space>w<down> `` |
| `swap_view_right` | Swap with right split | normal: `` <C-w>L ``, `` <space>wL ``, select: `` <C-w>L ``, `` <space>wL `` |
| `swap_view_left` | Swap with left split | normal: `` <C-w>H ``, `` <space>wH ``, select: `` <C-w>H ``, `` <space>wH `` |
| `swap_view_up` | Swap with split above | normal: `` <C-w>K ``, `` <space>wK ``, select: `` <C-w>K ``, `` <space>wK `` |
| `swap_view_down` | Swap with split below | normal: `` <C-w>J ``, `` <space>wJ ``, select: `` <C-w>J ``, `` <space>wJ `` |
| `transpose_view` | Transpose splits | normal: `` <C-w>t ``, `` <space>wt ``, `` <C-w><C-t> ``, `` <space>w<C-t> ``, select: `` <C-w>t ``, `` <space>wt ``, `` <C-w><C-t> ``, `` <space>w<C-t> `` |
| `rotate_view` | Goto next window | normal: `` <C-w>w ``, `` <space>ww ``, `` <C-w><C-w> ``, `` <space>w<C-w> ``, select: `` <C-w>w ``, `` <space>ww ``, `` <C-w><C-w> ``, `` <space>w<C-w> `` |
| `rotate_view_reverse` | Goto previous window | |
| `hsplit` | Horizontal bottom split | normal: `` <C-w>s ``, `` <space>ws ``, `` <C-w><C-s> ``, `` <space>w<C-s> ``, select: `` <C-w>s ``, `` <space>ws ``, `` <C-w><C-s> ``, `` <space>w<C-s> `` |
| `hsplit_new` | Horizontal bottom split scratch buffer | normal: `` <C-w>ns ``, `` <space>wns ``, `` <C-w>n<C-s> ``, `` <space>wn<C-s> ``, select: `` <C-w>ns ``, `` <space>wns ``, `` <C-w>n<C-s> ``, `` <space>wn<C-s> `` |
| `vsplit` | Vertical right split | normal: `` <C-w>v ``, `` <space>wv ``, `` <C-w><C-v> ``, `` <space>w<C-v> ``, select: `` <C-w>v ``, `` <space>wv ``, `` <C-w><C-v> ``, `` <space>w<C-v> `` |
| `vsplit_new` | Vertical right split scratch buffer | normal: `` <C-w>nv ``, `` <space>wnv ``, `` <C-w>n<C-v> ``, `` <space>wn<C-v> ``, select: `` <C-w>nv ``, `` <space>wnv ``, `` <C-w>n<C-v> ``, `` <space>wn<C-v> `` |
| `wclose` | Close window | normal: `` <C-w>q ``, `` <space>wq ``, `` <C-w><C-q> ``, `` <space>w<C-q> ``, select: `` <C-w>q ``, `` <space>wq ``, `` <C-w><C-q> ``, `` <space>w<C-q> `` |
| `wonly` | Close windows except current | normal: `` <C-w>o ``, `` <space>wo ``, `` <C-w><C-o> ``, `` <space>w<C-o> ``, select: `` <C-w>o ``, `` <space>wo ``, `` <C-w><C-o> ``, `` <space>w<C-o> `` |
| `select_register` | Select register | normal: `` " ``, select: `` " `` |
| `insert_register` | Insert register | insert: `` <C-r> `` |
| `align_view_middle` | Align view middle | normal: `` Zm ``, `` zm ``, select: `` Zm ``, `` zm `` |
| `align_view_top` | Align view top | normal: `` Zt ``, `` zt ``, select: `` Zt ``, `` zt `` |
| `align_view_center` | Align view center | normal: `` Zc ``, `` Zz ``, `` zc ``, `` zz ``, select: `` Zc ``, `` Zz ``, `` zc ``, `` zz `` |
| `align_view_bottom` | Align view bottom | normal: `` Zb ``, `` zb ``, select: `` Zb ``, `` zb `` |
| `scroll_up` | Scroll view up | normal: `` Zk ``, `` zk ``, `` Z<up> ``, `` z<up> ``, select: `` Zk ``, `` zk ``, `` Z<up> ``, `` z<up> `` |
| `scroll_down` | Scroll view down | normal: `` Zj ``, `` zj ``, `` Z<down> ``, `` z<down> ``, select: `` Zj ``, `` zj ``, `` Z<down> ``, `` z<down> `` |
| `match_brackets` | Goto matching bracket | normal: `` mm ``, select: `` mm `` |
| `surround_add` | Surround add | normal: `` ms ``, select: `` ms `` |
| `surround_replace` | Surround replace | normal: `` mr ``, select: `` mr `` |
| `surround_delete` | Surround delete | normal: `` md ``, select: `` md `` |
| `select_textobject_around` | Select around object | normal: `` ma ``, select: `` ma `` |
| `select_textobject_inner` | Select inside object | normal: `` mi ``, select: `` mi `` |
| `goto_next_function` | Goto next function | normal: `` ]f ``, select: `` ]f `` |
| `goto_prev_function` | Goto previous function | normal: `` [f ``, select: `` [f `` |
| `goto_next_class` | Goto next type definition | normal: `` ]t ``, select: `` ]t `` |
| `goto_prev_class` | Goto previous type definition | normal: `` [t ``, select: `` [t `` |
| `goto_next_parameter` | Goto next parameter | normal: `` ]a ``, select: `` ]a `` |
| `goto_prev_parameter` | Goto previous parameter | normal: `` [a ``, select: `` [a `` |
| `goto_next_comment` | Goto next comment | normal: `` ]c ``, select: `` ]c `` |
| `goto_prev_comment` | Goto previous comment | normal: `` [c ``, select: `` [c `` |
| `goto_next_test` | Goto next test | normal: `` ]T ``, select: `` ]T `` |
| `goto_prev_test` | Goto previous test | normal: `` [T ``, select: `` [T `` |
| `goto_next_entry` | Goto next pairing | normal: `` ]e ``, select: `` ]e `` |
| `goto_prev_entry` | Goto previous pairing | normal: `` [e ``, select: `` [e `` |
| `goto_next_paragraph` | Goto next paragraph | normal: `` ]p ``, select: `` ]p `` |
| `goto_prev_paragraph` | Goto previous paragraph | normal: `` [p ``, select: `` [p `` |
| `dap_launch` | Launch debug target | normal: `` <space>Gl ``, select: `` <space>Gl `` |
| `dap_restart` | Restart debugging session | normal: `` <space>Gr ``, select: `` <space>Gr `` |
| `dap_toggle_breakpoint` | Toggle breakpoint | normal: `` <space>Gb ``, select: `` <space>Gb `` |
| `dap_continue` | Continue program execution | normal: `` <space>Gc ``, select: `` <space>Gc `` |
| `dap_pause` | Pause program execution | normal: `` <space>Gh ``, select: `` <space>Gh `` |
| `dap_step_in` | Step in | normal: `` <space>Gi ``, select: `` <space>Gi `` |
| `dap_step_out` | Step out | normal: `` <space>Go ``, select: `` <space>Go `` |
| `dap_next` | Step to next | normal: `` <space>Gn ``, select: `` <space>Gn `` |
| `dap_variables` | List variables | normal: `` <space>Gv ``, select: `` <space>Gv `` |
| `dap_terminate` | End debug session | normal: `` <space>Gt ``, select: `` <space>Gt `` |
| `dap_edit_condition` | Edit breakpoint condition on current line | normal: `` <space>G<C-c> ``, select: `` <space>G<C-c> `` |
| `dap_edit_log` | Edit breakpoint log message on current line | normal: `` <space>G<C-l> ``, select: `` <space>G<C-l> `` |
| `dap_switch_thread` | Switch current thread | normal: `` <space>Gst ``, select: `` <space>Gst `` |
| `dap_switch_stack_frame` | Switch stack frame | normal: `` <space>Gsf ``, select: `` <space>Gsf `` |
| `dap_enable_exceptions` | Enable exception breakpoints | normal: `` <space>Ge ``, select: `` <space>Ge `` |
| `dap_disable_exceptions` | Disable exception breakpoints | normal: `` <space>GE ``, select: `` <space>GE `` |
| `shell_pipe` | Pipe selections through shell command | normal: `` \| ``, select: `` \| `` |
| `shell_pipe_to` | Pipe selections into shell command ignoring output | normal: `` <A-\|> ``, select: `` <A-\|> `` |
| `shell_insert_output` | Insert shell command output before selections | normal: `` ! ``, select: `` ! `` |
| `shell_append_output` | Append shell command output after selections | normal: `` <A-!> ``, select: `` <A-!> `` |
| `shell_keep_pipe` | Filter selections with shell predicate | normal: `` $ ``, select: `` $ `` |
| `suspend` | Suspend and return to shell | normal: `` <C-z> ``, select: `` <C-z> `` |
| `rename_symbol` | Rename symbol | normal: `` <space>r ``, select: `` <space>r `` |
| `increment` | Increment item under cursor | normal: `` <C-a> ``, select: `` <C-a> `` |
| `decrement` | Decrement item under cursor | normal: `` <C-x> ``, select: `` <C-x> `` |
| `record_macro` | Record macro | normal: `` Q ``, select: `` Q `` |
| `replay_macro` | Replay macro | normal: `` q ``, select: `` q `` |
| `command_palette` | Open command palette | normal: `` <space>? ``, select: `` <space>? `` |
| `goto_word` | Jump to a two-character label | normal: `` gw `` |
| `extend_to_word` | Extend to a two-character label | select: `` gw `` |
| `goto_next_tabstop` | goto next snippet placeholder | |
| `goto_prev_tabstop` | goto next snippet placeholder | |

View File

@@ -2,7 +2,7 @@
| --- | --- | | --- | --- |
| `:quit`, `:q` | Close the current view. | | `:quit`, `:q` | Close the current view. |
| `:quit!`, `:q!` | Force close the current view, ignoring unsaved changes. | | `:quit!`, `:q!` | Force close the current view, ignoring unsaved changes. |
| `:open`, `:o` | Open a file from disk into the current view. | | `:open`, `:o`, `:edit`, `:e` | Open a file from disk into the current view. |
| `:buffer-close`, `:bc`, `:bclose` | Close the current buffer. | | `:buffer-close`, `:bc`, `:bclose` | Close the current buffer. |
| `:buffer-close!`, `:bc!`, `:bclose!` | Close the current buffer forcefully, ignoring unsaved changes. | | `:buffer-close!`, `:bc!`, `:bclose!` | Close the current buffer forcefully, ignoring unsaved changes. |
| `:buffer-close-others`, `:bco`, `:bcloseother` | Close all buffers but the currently focused one. | | `:buffer-close-others`, `:bco`, `:bcloseother` | Close all buffers but the currently focused one. |
@@ -12,16 +12,19 @@
| `:buffer-next`, `:bn`, `:bnext` | Goto next buffer. | | `:buffer-next`, `:bn`, `:bnext` | Goto next buffer. |
| `:buffer-previous`, `:bp`, `:bprev` | Goto previous buffer. | | `:buffer-previous`, `:bp`, `:bprev` | Goto previous buffer. |
| `:write`, `:w` | Write changes to disk. Accepts an optional path (:write some/path.txt) | | `:write`, `:w` | Write changes to disk. Accepts an optional path (:write some/path.txt) |
| `:write!`, `:w!` | Force write changes to disk creating necessary subdirectories. Accepts an optional path (:write some/path.txt) | | `:write!`, `:w!` | Force write changes to disk creating necessary subdirectories. Accepts an optional path (:write! some/path.txt) |
| `:write-buffer-close`, `:wbc` | Write changes to disk and closes the buffer. Accepts an optional path (:write-buffer-close some/path.txt) |
| `:write-buffer-close!`, `:wbc!` | Force write changes to disk creating necessary subdirectories and closes the buffer. Accepts an optional path (:write-buffer-close! some/path.txt) |
| `:new`, `:n` | Create a new scratch buffer. | | `:new`, `:n` | Create a new scratch buffer. |
| `:format`, `:fmt` | Format the file using the LSP formatter. | | `:format`, `:fmt` | Format the file using an external formatter or language server. |
| `:indent-style` | Set the indentation style for editing. ('t' for tabs or 1-8 for number of spaces.) | | `:indent-style` | Set the indentation style for editing. ('t' for tabs or 1-16 for number of spaces.) |
| `:line-ending` | Set the document's default line ending. Options: crlf, lf. | | `:line-ending` | Set the document's default line ending. Options: crlf, lf. |
| `:earlier`, `:ear` | Jump back to an earlier point in edit history. Accepts a number of steps or a time span. | | `:earlier`, `:ear` | Jump back to an earlier point in edit history. Accepts a number of steps or a time span. |
| `:later`, `:lat` | Jump to a later point in edit history. Accepts a number of steps or a time span. | | `:later`, `:lat` | Jump to a later point in edit history. Accepts a number of steps or a time span. |
| `:write-quit`, `:wq`, `:x` | Write changes to disk and close the current view. Accepts an optional path (:wq some/path.txt) | | `:write-quit`, `:wq`, `:x` | Write changes to disk and close the current view. Accepts an optional path (:wq some/path.txt) |
| `:write-quit!`, `:wq!`, `:x!` | Write changes to disk and close the current view forcefully. Accepts an optional path (:wq! some/path.txt) | | `:write-quit!`, `:wq!`, `:x!` | Write changes to disk and close the current view forcefully. Accepts an optional path (:wq! some/path.txt) |
| `:write-all`, `:wa` | Write changes from all buffers to disk. | | `:write-all`, `:wa` | Write changes from all buffers to disk. |
| `:write-all!`, `:wa!` | Forcefully write changes from all buffers to disk creating necessary subdirectories. |
| `:write-quit-all`, `:wqa`, `:xa` | Write changes from all buffers to disk and close all views. | | `:write-quit-all`, `:wqa`, `:xa` | Write changes from all buffers to disk and close all views. |
| `:write-quit-all!`, `:wqa!`, `:xa!` | Write changes from all buffers to disk and close all views forcefully (ignoring unsaved changes). | | `:write-quit-all!`, `:wqa!`, `:xa!` | Write changes from all buffers to disk and close all views forcefully (ignoring unsaved changes). |
| `:quit-all`, `:qa` | Close all views. | | `:quit-all`, `:qa` | Close all views. |
@@ -29,6 +32,7 @@
| `:cquit`, `:cq` | Quit with exit code (default 1). Accepts an optional integer exit code (:cq 2). | | `:cquit`, `:cq` | Quit with exit code (default 1). Accepts an optional integer exit code (:cq 2). |
| `:cquit!`, `:cq!` | Force quit with exit code (default 1) ignoring unsaved changes. Accepts an optional integer exit code (:cq! 2). | | `:cquit!`, `:cq!` | Force quit with exit code (default 1) ignoring unsaved changes. Accepts an optional integer exit code (:cq! 2). |
| `:theme` | Change the editor theme (show current theme if no name specified). | | `:theme` | Change the editor theme (show current theme if no name specified). |
| `:yank-join` | Yank joined selections. A separator can be provided as first argument. Default value is newline. |
| `:clipboard-yank` | Yank main selection into system clipboard. | | `:clipboard-yank` | Yank main selection into system clipboard. |
| `:clipboard-yank-join` | Yank joined selections into system clipboard. A separator can be provided as first argument. Default value is newline. | | `:clipboard-yank-join` | Yank joined selections into system clipboard. A separator can be provided as first argument. Default value is newline. |
| `:primary-clipboard-yank` | Yank main selection into system primary clipboard. | | `:primary-clipboard-yank` | Yank main selection into system primary clipboard. |
@@ -44,13 +48,14 @@
| `:show-directory`, `:pwd` | Show the current working directory. | | `:show-directory`, `:pwd` | Show the current working directory. |
| `:encoding` | Set encoding. Based on `https://encoding.spec.whatwg.org`. | | `:encoding` | Set encoding. Based on `https://encoding.spec.whatwg.org`. |
| `:character-info`, `:char` | Get info about the character under the primary cursor. | | `:character-info`, `:char` | Get info about the character under the primary cursor. |
| `:reload` | Discard changes and reload from the source file. | | `:reload`, `:rl` | Discard changes and reload from the source file. |
| `:reload-all` | Discard changes and reload all documents from the source files. | | `:reload-all`, `:rla` | Discard changes and reload all documents from the source files. |
| `:update` | Write changes only if the file has been modified. | | `:update`, `:u` | Write changes only if the file has been modified. |
| `:lsp-workspace-command` | Open workspace command picker | | `:lsp-workspace-command` | Open workspace command picker |
| `:lsp-restart` | Restarts the Language Server that is in use by the current doc | | `:lsp-restart` | Restarts the language servers used by the current doc |
| `:lsp-stop` | Stops the Language Server that is in use by the current doc | | `:lsp-stop` | Stops the language servers that are used by the current doc |
| `:tree-sitter-scopes` | Display tree sitter scopes, primarily for theming and development. | | `:tree-sitter-scopes` | Display tree sitter scopes, primarily for theming and development. |
| `:tree-sitter-highlight-name` | Display name of tree-sitter highlight scope under the cursor. |
| `:debug-start`, `:dbg` | Start a debug session from a given template with given parameters. | | `:debug-start`, `:dbg` | Start a debug session from a given template with given parameters. |
| `:debug-remote`, `:dbg-tcp` | Connect to a debug adapter by TCP address and start a debugging session from a given template with given parameters. | | `:debug-remote`, `:dbg-tcp` | Connect to a debug adapter by TCP address and start a debugging session from a given template with given parameters. |
| `:debug-eval` | Evaluate expression in current debug context. | | `:debug-eval` | Evaluate expression in current debug context. |
@@ -67,7 +72,7 @@
| `:sort` | Sort ranges in selection. | | `:sort` | Sort ranges in selection. |
| `:rsort` | Sort ranges in selection in reverse order. | | `:rsort` | Sort ranges in selection in reverse order. |
| `:reflow` | Hard-wrap the current selection of lines to a given width. | | `:reflow` | Hard-wrap the current selection of lines to a given width. |
| `:tree-sitter-subtree`, `:ts-subtree` | Display tree sitter subtree under cursor, primarily for debugging queries. | | `:tree-sitter-subtree`, `:ts-subtree` | Display the smallest tree-sitter subtree that spans the primary selection, primarily for debugging queries. |
| `:config-reload` | Refresh user config. | | `:config-reload` | Refresh user config. |
| `:config-open` | Open the user config.toml file. | | `:config-open` | Open the user config.toml file. |
| `:config-open-workspace` | Open the workspace config.toml file. | | `:config-open-workspace` | Open the workspace config.toml file. |
@@ -78,3 +83,8 @@
| `:pipe-to` | Pipe each selection to the shell command, ignoring output. | | `:pipe-to` | Pipe each selection to the shell command, ignoring output. |
| `:run-shell-command`, `:sh` | Run a shell command | | `:run-shell-command`, `:sh` | Run a shell command |
| `:reset-diff-change`, `:diffget`, `:diffg` | Reset the diff change at the cursor position. | | `:reset-diff-change`, `:diffget`, `:diffg` | Reset the diff change at the cursor position. |
| `:clear-register` | Clear given register. If no argument is provided, clear all registers. |
| `:redraw` | Clear and re-render the whole UI |
| `:move`, `:mv` | Move the current buffer and its corresponding file to a different path |
| `:yank-diagnostic` | Yank diagnostic(s) under primary cursor to register, or clipboard by default |
| `:read`, `:r` | Load a file into buffer |

View File

@@ -1,4 +1,4 @@
# Adding new languages to Helix ## Adding new languages to Helix
In order to add a new language to Helix, you will need to follow the steps In order to add a new language to Helix, you will need to follow the steps
below. below.
@@ -9,13 +9,14 @@ below.
necessary configuration for the new language. For more information on necessary configuration for the new language. For more information on
language configuration, refer to the language configuration, refer to the
[language configuration section](../languages.md) of the documentation. [language configuration section](../languages.md) of the documentation.
A new language server can be added by extending the `[language-server]` table in the same file.
2. If you are adding a new language or updating an existing language server 2. If you are adding a new language or updating an existing language server
configuration, run the command `cargo xtask docgen` to update the configuration, run the command `cargo xtask docgen` to update the
[Language Support](../lang-support.md) documentation. [Language Support](../lang-support.md) documentation.
> 💡 If you are adding a new Language Server configuration, make sure to update > 💡 If you are adding a new Language Server configuration, make sure to update
> the > the
> [Language Server Wiki](https://github.com/helix-editor/helix/wiki/How-to-install-the-default-language-servers) > [Language Server Wiki](https://github.com/helix-editor/helix/wiki/Language-Server-Configurations)
> with the installation instructions. > with the installation instructions.
## Grammar configuration ## Grammar configuration
@@ -35,6 +36,7 @@ below.
3. Refer to the 3. Refer to the
[tree-sitter website](https://tree-sitter.github.io/tree-sitter/syntax-highlighting#queries) [tree-sitter website](https://tree-sitter.github.io/tree-sitter/syntax-highlighting#queries)
for more information on writing queries. for more information on writing queries.
4. A list of highlight captures can be found [on the themes page](https://docs.helix-editor.com/themes.html#scopes).
> 💡 In Helix, the first matching query takes precedence when evaluating > 💡 In Helix, the first matching query takes precedence when evaluating
> queries, which is different from other editors such as Neovim where the last > queries, which is different from other editors such as Neovim where the last
@@ -50,3 +52,4 @@ below.
grammars. grammars.
- If a parser is causing a segfault, or you want to remove it, make sure to - If a parser is causing a segfault, or you want to remove it, make sure to
remove the compiled parser located at `runtime/grammars/<name>.so`. remove the compiled parser located at `runtime/grammars/<name>.so`.
- If you are attempting to add queries and Helix is unable to locate them, ensure that the environment variable `HELIX_RUNTIME` is set to the location of the `runtime` folder you're developing in.

View File

@@ -1,76 +1,308 @@
# Adding indent queries ## Adding indent queries
Helix uses tree-sitter to correctly indent new lines. This requires Helix uses tree-sitter to correctly indent new lines. This requires a tree-
a tree-sitter grammar and an `indent.scm` query file placed in sitter grammar and an `indent.scm` query file placed in `runtime/queries/
`runtime/queries/{language}/indents.scm`. The indentation for a line {language}/indents.scm`. The indentation for a line is calculated by traversing
is calculated by traversing the syntax tree from the lowest node at the the syntax tree from the lowest node at the beginning of the new line (see
beginning of the new line. Each of these nodes contributes to the total [Indent queries](#indent-queries)). Each of these nodes contributes to the total
indent when it is captured by the query (in what way depends on the name indent when it is captured by the query (in what way depends on the name of
of the capture). the capture.
Note that it matters where these added indents begin. For example, Note that it matters where these added indents begin. For example,
multiple indent level increases that start on the same line only increase multiple indent level increases that start on the same line only increase
the total indent level by 1. the total indent level by 1. See [Capture types](#capture-types).
## Scopes By default, Helix uses the `hybrid` indentation heuristic. This means that
indent queries are not used to compute the expected absolute indentation of a
line but rather the expected difference in indentation between the new and an
already existing line. This difference is then added to the actual indentation
of the already existing line. Since this makes errors in the indent queries
harder to find, it is recommended to disable it when testing via
`:set indent-heuristic tree-sitter`. The rest of this guide assumes that
the `tree-sitter` heuristic is used.
Added indents don't always apply to the whole node. For example, in most ## Indent queries
cases when a node should be indented, we actually only want everything
except for its first line to be indented. For this, there are several
scopes (more scopes may be added in the future if required):
- `all`: When Helix is inserting a new line through `o`, `O`, or `<ret>`, to determine
This scope applies to the whole captured node. This is only different from the indent level for the new line, the query in `indents.scm` is run on the
`tail` when the captured node is the first node on its line. document. The starting position of the query is the end of the line above where
a new line will be inserted.
- `tail`: For `o`, the inserted line is the line below the cursor, so that starting
This scope applies to everything except for the first line of the position of the query is the end of the current line.
captured node.
Every capture type has a default scope which should do the right thing ```rust
in most situations. When a different scope is required, this can be fn need_hero(some_hero: Hero, life: Life) -> {
changed by using a `#set!` declaration anywhere in the pattern: matches!(some_hero, Hero { // ←─────────────────╮
```scm strong: true,//←╮ ↑ ↑ │
(assignment_expression fast: true, // │ │ ╰── query start │
right: (_) @indent sure: true, // │ ╰───── cursor ├─ traversal
(#set! "scope" "all")) soon: true, // ╰──────── new line inserted │ start node
}) && // │
// ↑ │
// ╰───────────────────────────────────────────────╯
some_hero > life
}
``` ```
## Capture types For `O`, the newly inserted line is the *current* line, so the starting position
of the query is the end of the line above the cursor.
```rust
fn need_hero(some_hero: Hero, life: Life) -> { // ←─╮
matches!(some_hero, Hero { // ←╮ ↑ │
strong: true,// ↑ ╭───╯ │ │
fast: true, // │ │ query start ─╯ │
sure: true, // ╰───┼ cursor ├─ traversal
soon: true, // ╰ new line inserted │ start node
}) && // │
some_hero > life // │
} // ←──────────────────────────────────────────────╯
```
From this starting node, the syntax tree is traversed up until the root node.
Each indent capture is collected along the way, and then combined according to
their [capture types](#capture-types) and [scopes](#scopes) to a final indent
level for the line.
### Capture types
- `@indent` (default scope `tail`): - `@indent` (default scope `tail`):
Increase the indent level by 1. Multiple occurrences in the same line Increase the indent level by 1. Multiple occurrences in the same line *do not*
don't stack. If there is at least one `@indent` and one `@outdent` stack. If there is at least one `@indent` and one `@outdent` capture on the
capture on the same line, the indent level isn't changed at all. same line, the indent level isn't changed at all.
- `@outdent` (default scope `all`): - `@outdent` (default scope `all`):
Decrease the indent level by 1. The same rules as for `@indent` apply. Decrease the indent level by 1. The same rules as for `@indent` apply.
- `@indent.always` (default scope `tail`):
Increase the indent level by 1. Multiple occurrences on the same line *do*
stack. The final indent level is `@indent.always` `@outdent.always`. If
an `@indent` and an `@indent.always` are on the same line, the `@indent` is
ignored.
- `@outdent.always` (default scope `all`):
Decrease the indent level by 1. The same rules as for `@indent.always` apply.
- `@align` (default scope `all`):
Align everything inside this node to some anchor. The anchor is given
by the start of the node captured by `@anchor` in the same pattern.
Every pattern with an `@align` should contain exactly one `@anchor`.
Indent (and outdent) for nodes below (in terms of their starting line)
the `@align` node is added to the indentation required for alignment.
- `@extend`: - `@extend`:
Extend the range of this node to the end of the line and to lines that Extend the range of this node to the end of the line and to lines that are
are indented more than the line that this node starts on. This is useful indented more than the line that this node starts on. This is useful for
for languages like Python, where for the purpose of indentation some nodes languages like Python, where for the purpose of indentation some nodes (like
(like functions or classes) should also contain indented lines that follow them. functions or classes) should also contain indented lines that follow them.
- `@extend.prevent-once`: - `@extend.prevent-once`:
Prevents the first extension of an ancestor of this node. For example, in Python Prevents the first extension of an ancestor of this node. For example, in Python
a return expression always ends the block that it is in. Note that this only stops the a return expression always ends the block that it is in. Note that this only
extension of the next `@extend` capture. If multiple ancestors are captured, stops the extension of the next `@extend` capture. If multiple ancestors are
only the extension of the innermost one is prevented. All other ancestors are unaffected captured, only the extension of the innermost one is prevented. All other
(regardless of whether the innermost ancestor would actually have been extended). ancestors are unaffected (regardless of whether the innermost ancestor would
actually have been extended).
#### `@indent` / `@outdent`
Consider this example:
```rust
fn shout(things: Vec<Thing>) {
// ↑
// ├───────────────────────╮ indent level
// @indent ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄
// │
let it_all = |out| { things.filter(|thing| { // │ 1
// ↑ ↑ │
// ├───────────────────────┼─────┼┄┄┄┄┄┄┄┄┄┄┄┄┄┄
// @indent @indent
// │ 2
thing.can_do_with(out) // │
})}; // ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄
//↑↑↑ │ 1
} //╰┼┴──────────────────────────────────────────────┴┄┄┄┄┄┄┄┄┄┄┄┄┄┄
// 3x @outdent
```
```scm
((block) @indent)
["}" ")"] @outdent
```
Note how on the second line, we have two blocks begin on the same line. In this
case, since both captures occur on the same line, they are combined and only
result in a net increase of 1. Also note that the closing `}`s are part of the
`@indent` captures, but the 3 `@outdent`s also combine into 1 and result in that
line losing one indent level.
#### `@extend` / `@extend.prevent-once`
For an example of where `@extend` can be useful, consider Python, which is
whitespace-sensitive.
```scm
]
(parenthesized_expression)
(function_definition)
(class_definition)
] @indent
```
```python
class Hero:
def __init__(self, strong, fast, sure, soon):# ←─╮
self.is_strong = strong # │
self.is_fast = fast # ╭─── query start │
self.is_sure = sure # │ ╭─ cursor │
self.is_soon = soon # │ │ │
# ↑ ↑ │ │ │
# │ ╰──────╯ │ │
# ╰─────────────────────╯ │
# ├─ traversal
def need_hero(self, life): # │ start node
return ( # │
self.is_strong # │
and self.is_fast # │
and self.is_sure # │
and self.is_soon # │
and self > life # │
) # ←─────────────────────────────────────────╯
```
Without braces to catch the scope of the function, the smallest descendant of
the cursor on a line feed ends up being the entire inside of the class. Because
of this, it will miss the entire function node and its indent capture, leading
to an indent level one too small.
To address this case, `@extend` tells helix to "extend" the captured node's span
to the line feed and every consecutive line that has a greater indent level than
the line of the node.
```scm
(parenthesized_expression) @indent
]
(function_definition)
(class_definition)
] @indent @extend
```
```python
class Hero:
def __init__(self, strong, fast, sure, soon):# ←─╮
self.is_strong = strong # │
self.is_fast = fast # ╭─── query start ├─ traversal
self.is_sure = sure # │ ╭─ cursor │ start node
self.is_soon = soon # │ │ ←───────────────╯
# ↑ ↑ │ │
# │ ╰──────╯ │
# ╰─────────────────────╯
def need_hero(self, life):
return (
self.is_strong
and self.is_fast
and self.is_sure
and self.is_soon
and self > life
)
```
Furthermore, there are some cases where extending to everything with a greater
indent level may not be desirable. Consider the `need_hero` function above. If
our cursor is on the last line of the returned expression.
```python
class Hero:
def __init__(self, strong, fast, sure, soon):
self.is_strong = strong
self.is_fast = fast
self.is_sure = sure
self.is_soon = soon
def need_hero(self, life):
return (
self.is_strong
and self.is_fast
and self.is_sure
and self.is_soon
and self > life
) # ←─── cursor
#←────────── where cursor should go on new line
```
In Python, the are a few tokens that will always end a scope, such as a return
statement. Since the scope ends, so should the indent level. But because the
function span is extended to every line with a greater indent level, a new line
would just continue on the same level. And an `@outdent` would not help us here
either, since it would cause everything in the parentheses to become outdented
as well.
To help, we need to signal an end to the extension. We can do this with
`@extend.prevent-once`.
```scm
(parenthesized_expression) @indent
]
(function_definition)
(class_definition)
] @indent @extend
(return_statement) @extend.prevent-once
```
#### `@indent.always` / `@outdent.always`
As mentioned before, normally if there is more than one `@indent` or `@outdent`
capture on the same line, they are combined.
Sometimes, there are cases when you may want to ensure that every indent capture
is additive, regardless of how many occur on the same line. Consider this
example in YAML.
```yaml
- foo: bar
# ↑ ↑
# │ ╰─────────────── start of map
# ╰───────────────── start of list element
baz: quux # ←─── cursor
# ←───────────── where the cursor should go on a new line
garply: waldo
- quux:
bar: baz
xyzzy: thud
fred: plugh
```
In YAML, you often have lists of maps. In these cases, the syntax is such that
the list element and the map both start on the same line. But we really do want
to start an indentation for each of these so that subsequent keys in the map
hang over the list and align properly. This is where `@indent.always` helps.
```scm
((block_sequence_item) @item @indent.always @extend
(#not-one-line? @item))
((block_mapping_pair
key: (_) @key
value: (_) @val
(#not-same-line? @key @val)
) @indent.always @extend
)
```
## Predicates ## Predicates
In some cases, an S-expression cannot express exactly what pattern should be matched. In some cases, an S-expression cannot express exactly what pattern should be matched.
For that, tree-sitter allows for predicates to appear anywhere within a pattern, For that, tree-sitter allows for predicates to appear anywhere within a pattern,
similar to how `#set!` declarations work: similar to how `#set!` declarations work:
```scm ```scm
(some_kind (some_kind
(child_kind) @indent (child_kind) @indent
(#predicate? arg1 arg2 ...) (#predicate? arg1 arg2 ...)
) )
``` ```
The number of arguments depends on the predicate that's used. The number of arguments depends on the predicate that's used.
Each argument is either a capture (`@name`) or a string (`"some string"`). Each argument is either a capture (`@name`) or a string (`"some string"`).
The following predicates are supported by tree-sitter: The following predicates are supported by tree-sitter:
@@ -83,6 +315,10 @@ The first argument (a capture) must/must not be equal to the second argument
The first argument (a capture) must/must not match the regex given in the The first argument (a capture) must/must not match the regex given in the
second argument (a string). second argument (a string).
- `#any-of?`/`#not-any-of?`:
The first argument (a capture) must/must not be one of the other arguments
(strings).
Additionally, we support some custom predicates for indent queries: Additionally, we support some custom predicates for indent queries:
- `#not-kind-eq?`: - `#not-kind-eq?`:
@@ -91,3 +327,47 @@ argument (a string).
- `#same-line?`/`#not-same-line?`: - `#same-line?`/`#not-same-line?`:
The captures given by the 2 arguments must/must not start on the same line. The captures given by the 2 arguments must/must not start on the same line.
- `#one-line?`/`#not-one-line?`:
The captures given by the fist argument must/must span a total of one line.
### Scopes
Added indents don't always apply to the whole node. For example, in most
cases when a node should be indented, we actually only want everything
except for its first line to be indented. For this, there are several
scopes (more scopes may be added in the future if required):
- `tail`:
This scope applies to everything except for the first line of the
captured node.
- `all`:
This scope applies to the whole captured node. This is only different from
`tail` when the captured node is the first node on its line.
For example, imagine we have the following function
```rust
fn aha() { // ←─────────────────────────────────────╮
let take = "on me"; // ←──────────────╮ scope: │
let take = "me on"; // ├─ "tail" ├─ (block) @indent
let ill = be_gone_days(1 || 2); // │ │
} // ←───────────────────────────────────┴──────────┴─ "}" @outdent
// scope: "all"
```
We can write the following query with the `#set!` declaration:
```scm
((block) @indent
(#set! "scope" "tail"))
("}" @outdent
(#set! "scope" "all"))
```
As we can see, the "tail" scope covers the node, except for the first line.
Everything up to and including the closing brace gets an indent level of 1.
Then, on the closing brace, we encounter an outdent with a scope of "all", which
means the first line is included, and the indent level is cancelled out on this
line. (Note these scopes are the defaults for `@indent` and `@outdent`—they are
written explicitly for demonstration.)

View File

@@ -0,0 +1,60 @@
## Adding Injection Queries
Writing language injection queries allows one to highlight a specific node as a different language.
In addition to the [standard][upstream-docs] language injection options used by tree-sitter, there
are a few Helix specific extensions that allow for more control.
And example of a simple query that would highlight all strings as bash in Nix:
```scm
((string_expression (string_fragment) @injection.content)
(#set! injection.language "bash"))
```
## Capture Types
- `@injection.language` (standard):
The captured node may contain the language name used to highlight the node captured by
`@injection.content`.
- `@injection.content` (standard):
Marks the content to be highlighted as the language captured with `@injection.language` _et al_.
- `@injection.filename` (extension):
The captured node may contain a filename with a file-extension known to Helix,
highlighting `@injection.content` as that language. This uses the language extensions defined in
both the default languages.toml distributed with Helix, as well as user defined languages.
- `@injection.shebang` (extension):
The captured node may contain a shebang used to choose a language to highlight as. This also uses
the shebangs defined in the default and user `languages.toml`.
## Settings
- `injection.combined` (standard):
Indicates that all the matching nodes in the tree should have their content parsed as one
nested document.
- `injection.language` (standard):
Forces the captured content to be highlighted as the given language
- `injection.include-children` (standard):
Indicates that the content nodes entire text should be re-parsed, including the text of its child
nodes. By default, child nodes text will be excluded from the injected document.
- `injection.include-unnamed-children` (extension):
Same as `injection.include-children` but only for unnamed child nodes.
## Predicates
- `#eq?` (standard):
The first argument (a capture) must be equal to the second argument
(a capture or a string).
- `#match?` (standard):
The first argument (a capture) must match the regex given in the
second argument (a string).
- `#any-of?` (standard):
The first argument (a capture) must be one of the other arguments (strings).
[upstream-docs]: http://tree-sitter.github.io/tree-sitter/syntax-highlighting#language-injection

View File

@@ -1,4 +1,4 @@
# Adding textobject queries ## Adding textobject queries
Helix supports textobjects that are language specific, such as functions, classes, etc. Helix supports textobjects that are language specific, such as functions, classes, etc.
These textobjects require an accompanying tree-sitter grammar and a `textobjects.scm` query file These textobjects require an accompanying tree-sitter grammar and a `textobjects.scm` query file
@@ -25,6 +25,8 @@ The following [captures][tree-sitter-captures] are recognized:
| `parameter.inside` | | `parameter.inside` |
| `comment.inside` | | `comment.inside` |
| `comment.around` | | `comment.around` |
| `entry.inside` |
| `entry.around` |
[Example query files][textobject-examples] can be found in the helix GitHub repository. [Example query files][textobject-examples] can be found in the helix GitHub repository.
@@ -44,4 +46,4 @@ doesn't make sense in a navigation context.
[tree-sitter-queries]: https://tree-sitter.github.io/tree-sitter/using-parsers#query-syntax [tree-sitter-queries]: https://tree-sitter.github.io/tree-sitter/using-parsers#query-syntax
[tree-sitter-captures]: https://tree-sitter.github.io/tree-sitter/using-parsers#capturing-nodes [tree-sitter-captures]: https://tree-sitter.github.io/tree-sitter/using-parsers#capturing-nodes
[textobject-examples]: https://github.com/search?q=repo%3Ahelix-editor%2Fhelix+filename%3Atextobjects.scm&type=Code&ref=advsearch&l=&l= [textobject-examples]: https://github.com/search?q=repo%3Ahelix-editor%2Fhelix+path%3A%2A%2A/textobjects.scm&type=Code&ref=advsearch&l=&l=

View File

@@ -1,32 +1,10 @@
# Installing Helix # Installing Helix
<!--toc:start-->
- [Pre-built binaries](#pre-built-binaries)
- [Linux, macOS, Windows and OpenBSD packaging status](#linux-macos-windows-and-openbsd-packaging-status)
- [Linux](#linux)
- [Ubuntu](#ubuntu)
- [Fedora/RHEL](#fedorarhel)
- [Arch Linux community](#arch-linux-community)
- [NixOS](#nixos)
- [AppImage](#appimage)
- [macOS](#macos)
- [Homebrew Core](#homebrew-core)
- [Windows](#windows)
- [Winget](#winget)
- [Scoop](#scoop)
- [Chocolatey](#chocolatey)
- [MSYS2](#msys2)
- [Building from source](#building-from-source)
- [Configuring Helix's runtime files](#configuring-helixs-runtime-files)
- [Validating the installation](#validating-the-installation)
- [Configure the desktop shortcut](#configure-the-desktop-shortcut)
<!--toc:end-->
To install Helix, follow the instructions specific to your operating system. To install Helix, follow the instructions specific to your operating system.
Note that: Note that:
- To get the latest nightly version of Helix, you need to - To get the latest nightly version of Helix, you need to
[build from source](#building-from-source). [build from source](./building-from-source.md).
- To take full advantage of Helix, install the language servers for your - To take full advantage of Helix, install the language servers for your
preferred programming languages. See the preferred programming languages. See the
@@ -35,225 +13,11 @@ Note that:
## Pre-built binaries ## Pre-built binaries
Download pre-built binaries from the Download pre-built binaries from the [GitHub Releases page](https://github.com/helix-editor/helix/releases).
[GitHub Releases page](https://github.com/helix-editor/helix/releases). Add the binary to your system's `$PATH` to use it from the command The tarball contents include an `hx` binary and a `runtime` directory.
line. To set up Helix:
## Linux, macOS, Windows and OpenBSD packaging status 1. Add the `hx` binary to your system's `$PATH` to allow it to be used from the command line.
2. Copy the `runtime` directory to a location that `hx` searches for runtime files. A typical location on Linux/macOS is `~/.config/helix/runtime`.
Helix is available for Linux, macOS and Windows via the official repositories listed below. To see the runtime directories that `hx` searches, run `hx --health`. If necessary, you can override the default runtime location by setting the `HELIX_RUNTIME` environment variable.
[![Packaging status](https://repology.org/badge/vertical-allrepos/helix.svg)](https://repology.org/project/helix/versions)
## Linux
The following third party repositories are available:
### Ubuntu
Helix is available via [Maveonair's PPA](https://launchpad.net/~maveonair/+archive/ubuntu/helix-editor):
```sh
sudo add-apt-repository ppa:maveonair/helix-editor
sudo apt update
sudo apt install helix
```
### Fedora/RHEL
Helix is available via `copr`:
```sh
sudo dnf copr enable varlad/helix
sudo dnf install helix
```
### Arch Linux community
Releases are available in the `community` repository:
```sh
sudo pacman -S helix
```
Additionally, a [helix-git](https://aur.archlinux.org/packages/helix-git/) package is available
in the AUR, which builds the master branch.
### NixOS
Helix is available as a [flake](https://nixos.wiki/wiki/Flakes) in the project
root. Use `nix develop` to spin up a reproducible development shell. Outputs are
cached for each push to master using [Cachix](https://www.cachix.org/). The
flake is configured to automatically make use of this cache assuming the user
accepts the new settings on first use.
If you are using a version of Nix without flakes enabled,
[install Cachix CLI](https://docs.cachix.org/installation) and use
`cachix use helix` to configure Nix to use cached outputs when possible.
### AppImage
Install Helix using [AppImage](https://appimage.org/).
Download Helix AppImage from the [latest releases](https://github.com/helix-editor/helix/releases/latest) page.
```sh
chmod +x helix-*.AppImage # change permission for executable mode
./helix-*.AppImage # run helix
```
## macOS
### Homebrew Core
```sh
brew install helix
```
## Windows
Install on Windows using [Winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/), [Scoop](https://scoop.sh/), [Chocolatey](https://chocolatey.org/)
or [MSYS2](https://msys2.org/).
### Winget
Windows Package Manager winget command-line tool is by default available on Windows 11 and modern versions of Windows 10 as a part of the App Installer.
You can get [App Installer from the Microsoft Store](https://www.microsoft.com/p/app-installer/9nblggh4nns1#activetab=pivot:overviewtab). If it's already installed, make sure it is updated with the latest version.
```sh
winget install Helix.Helix
```
### Scoop
```sh
scoop install helix
```
### Chocolatey
```sh
choco install helix
```
### MSYS2
For 64-bit Windows 8.1 or above:
```sh
pacman -S mingw-w64-ucrt-x86_64-helix
```
## Building from source
Clone the repository:
```sh
git clone https://github.com/helix-editor/helix
cd helix
```
Compile from source:
```sh
cargo install --path helix-term --locked
```
This command will create the `hx` executable and construct the tree-sitter
grammars in the local `runtime` folder. To build the tree-sitter grammars requires
a c++ compiler to be installed, for example `gcc-c++`.
> 💡 If you are using the musl-libc instead of glibc the following environment variable must be set during the build
> to ensure tree-sitter grammars can be loaded correctly:
>
> ```sh
> RUSTFLAGS="-C target-feature=-crt-static"
> ```
> 💡 Tree-sitter grammars can be fetched and compiled if not pre-packaged. Fetch
> grammars with `hx --grammar fetch` (requires `git`) and compile them with
> `hx --grammar build` (requires a C++ compiler). This will install them in
> the `runtime` directory within the user's helix config directory (more
> [details below](#multiple-runtime-directories)).
### Configuring Helix's runtime files
#### Linux and macOS
Either set the `HELIX_RUNTIME` environment variable to point to the runtime files and add it to your `~/.bashrc` or equivalent:
```sh
HELIX_RUNTIME=/home/user-name/src/helix/runtime
```
Or, create a symlink in `~/.config/helix` that links to the source code directory:
```sh
ln -s $PWD/runtime ~/.config/helix/runtime
```
#### Windows
Either set the `HELIX_RUNTIME` environment variable to point to the runtime files using the Windows setting (search for
`Edit environment variables for your account`) or use the `setx` command in
Cmd:
```sh
setx HELIX_RUNTIME "%userprofile%\source\repos\helix\runtime"
```
> 💡 `%userprofile%` resolves to your user directory like
> `C:\Users\Your-Name\` for example.
Or, create a symlink in `%appdata%\helix\` that links to the source code directory:
| Method | Command |
| ---------- | -------------------------------------------------------------------------------------- |
| PowerShell | `New-Item -ItemType Junction -Target "runtime" -Path "$Env:AppData\helix\runtime"` |
| Cmd | `cd %appdata%\helix` <br/> `mklink /D runtime "%userprofile%\src\helix\runtime"` |
> 💡 On Windows, creating a symbolic link may require running PowerShell or
> Cmd as an administrator.
#### Multiple runtime directories
When Helix finds multiple runtime directories it will search through them for files in the
following order:
1. `runtime/` sibling directory to `$CARGO_MANIFEST_DIR` directory (this is intended for
developing and testing helix only).
2. `runtime/` subdirectory of OS-dependent helix user config directory.
3. `$HELIX_RUNTIME`.
4. `runtime/` subdirectory of path to Helix executable.
This order also sets the priority for selecting which file will be used if multiple runtime
directories have files with the same name.
### Validating the installation
To make sure everything is set up as expected you should run the Helix health
check:
```sh
hx --health
```
For more information on the health check results refer to
[Health check](https://github.com/helix-editor/helix/wiki/Healthcheck).
### Configure the desktop shortcut
If your desktop environment supports the
[XDG desktop menu](https://specifications.freedesktop.org/menu-spec/menu-spec-latest.html)
you can configure Helix to show up in the application menu by copying the
provided `.desktop` and icon files to their correct folders:
```sh
cp contrib/Helix.desktop ~/.local/share/applications
cp contrib/helix.png ~/.icons # or ~/.local/share/icons
```
To use another terminal than the system default, you can modify the `.desktop`
file. For example, to use `kitty`:
```sh
sed -i "s|Exec=hx %F|Exec=kitty hx %F|g" ~/.local/share/applications/Helix.desktop
sed -i "s|Terminal=true|Terminal=false|g" ~/.local/share/applications/Helix.desktop
```

View File

@@ -1,4 +1,4 @@
# Keymap ## Keymap
- [Normal mode](#normal-mode) - [Normal mode](#normal-mode)
- [Movement](#movement) - [Movement](#movement)
@@ -13,9 +13,11 @@
- [Window mode](#window-mode) - [Window mode](#window-mode)
- [Space mode](#space-mode) - [Space mode](#space-mode)
- [Popup](#popup) - [Popup](#popup)
- [Completion Menu](#completion-menu)
- [Signature-help Popup](#signature-help-popup)
- [Unimpaired](#unimpaired) - [Unimpaired](#unimpaired)
- [Insert mode](#insert-mode) - [Insert mode](#insert-mode)
- [Select / extend mode](#select-extend-mode) - [Select / extend mode](#select--extend-mode)
- [Picker](#picker) - [Picker](#picker)
- [Prompt](#prompt) - [Prompt](#prompt)
@@ -23,8 +25,12 @@
> 💡 Mappings marked (**TS**) require a tree-sitter grammar for the file type. > 💡 Mappings marked (**TS**) require a tree-sitter grammar for the file type.
> ⚠️ Some terminals' default key mappings conflict with Helix's. If any of the mappings described on this page do not work as expected, check your terminal's mappings to ensure they do not conflict. See the [wiki](https://github.com/helix-editor/helix/wiki/Terminal-Support) for known conflicts.
## Normal mode ## Normal mode
Normal mode is the default mode when you launch helix. You can return to it from other modes by pressing the `Escape` key.
### Movement ### Movement
> NOTE: Unlike Vim, `f`, `F`, `t` and `T` are not confined to the current line. > NOTE: Unlike Vim, `f`, `F`, `t` and `T` are not confined to the current line.
@@ -32,8 +38,8 @@
| Key | Description | Command | | Key | Description | Command |
| ----- | ----------- | ------- | | ----- | ----------- | ------- |
| `h`, `Left` | Move left | `move_char_left` | | `h`, `Left` | Move left | `move_char_left` |
| `j`, `Down` | Move down | `move_line_down` | | `j`, `Down` | Move down | `move_visual_line_down` |
| `k`, `Up` | Move up | `move_line_up` | | `k`, `Up` | Move up | `move_visual_line_up` |
| `l`, `Right` | Move right | `move_char_right` | | `l`, `Right` | Move right | `move_char_right` |
| `w` | Move next word start | `move_next_word_start` | | `w` | Move next word start | `move_next_word_start` |
| `b` | Move previous word start | `move_prev_word_start` | | `b` | Move previous word start | `move_prev_word_start` |
@@ -46,13 +52,13 @@
| `T` | Find 'till previous char | `till_prev_char` | | `T` | Find 'till previous char | `till_prev_char` |
| `F` | Find previous char | `find_prev_char` | | `F` | Find previous char | `find_prev_char` |
| `G` | Go to line number `<n>` | `goto_line` | | `G` | Go to line number `<n>` | `goto_line` |
| `Alt-.` | Repeat last motion (`f`, `t` or `m`) | `repeat_last_motion` | | `Alt-.` | Repeat last motion (`f`, `t`, `m`, `[` or `]`) | `repeat_last_motion` |
| `Home` | Move to the start of the line | `goto_line_start` | | `Home` | Move to the start of the line | `goto_line_start` |
| `End` | Move to the end of the line | `goto_line_end` | | `End` | Move to the end of the line | `goto_line_end` |
| `Ctrl-b`, `PageUp` | Move page up | `page_up` | | `Ctrl-b`, `PageUp` | Move page up | `page_up` |
| `Ctrl-f`, `PageDown` | Move page down | `page_down` | | `Ctrl-f`, `PageDown` | Move page down | `page_down` |
| `Ctrl-u` | Move half page up | `half_page_up` | | `Ctrl-u` | Move cursor and page half page up | `page_cursor_half_up` |
| `Ctrl-d` | Move half page down | `half_page_down` | | `Ctrl-d` | Move cursor and page half page down | `page_cursor_half_down` |
| `Ctrl-i` | Jump forward on the jumplist | `jump_forward` | | `Ctrl-i` | Jump forward on the jumplist | `jump_forward` |
| `Ctrl-o` | Jump backward on the jumplist | `jump_backward` | | `Ctrl-o` | Jump backward on the jumplist | `jump_backward` |
| `Ctrl-s` | Save the current selection to the jumplist | `save_selection` | | `Ctrl-s` | Save the current selection to the jumplist | `save_selection` |
@@ -83,7 +89,7 @@
| `"` `<reg>` | Select a register to yank to or paste from | `select_register` | | `"` `<reg>` | Select a register to yank to or paste from | `select_register` |
| `>` | Indent selection | `indent` | | `>` | Indent selection | `indent` |
| `<` | Unindent selection | `unindent` | | `<` | Unindent selection | `unindent` |
| `=` | Format selection (currently nonfunctional/disabled) (**LSP**) | `format_selections` | | `=` | Format selection (**LSP**) | `format_selections` |
| `d` | Delete selection | `delete_selection` | | `d` | Delete selection | `delete_selection` |
| `Alt-d` | Delete selection, without yanking | `delete_selection_noyank` | | `Alt-d` | Delete selection, without yanking | `delete_selection_noyank` |
| `c` | Change selection (delete and enter insert mode) | `change_selection` | | `c` | Change selection (delete and enter insert mode) | `change_selection` |
@@ -106,38 +112,43 @@
### Selection manipulation ### Selection manipulation
| Key | Description | Command | | Key | Description | Command |
| ----- | ----------- | ------- | | ----- | ----------- | ------- |
| `s` | Select all regex matches inside selections | `select_regex` | | `s` | Select all regex matches inside selections | `select_regex` |
| `S` | Split selection into sub selections on regex matches | `split_selection` | | `S` | Split selection into sub selections on regex matches | `split_selection` |
| `Alt-s` | Split selection on newlines | `split_selection_on_newline` | | `Alt-s` | Split selection on newlines | `split_selection_on_newline` |
| `Alt-_ ` | Merge consecutive selections | `merge_consecutive_selections` | | `Alt-minus` | Merge selections | `merge_selections` |
| `&` | Align selection in columns | `align_selections` | | `Alt-_` | Merge consecutive selections | `merge_consecutive_selections` |
| `_` | Trim whitespace from the selection | `trim_selections` | | `&` | Align selection in columns | `align_selections` |
| `;` | Collapse selection onto a single cursor | `collapse_selection` | | `_` | Trim whitespace from the selection | `trim_selections` |
| `Alt-;` | Flip selection cursor and anchor | `flip_selections` | | `;` | Collapse selection onto a single cursor | `collapse_selection` |
| `Alt-:` | Ensures the selection is in forward direction | `ensure_selections_forward` | | `Alt-;` | Flip selection cursor and anchor | `flip_selections` |
| `,` | Keep only the primary selection | `keep_primary_selection` | | `Alt-:` | Ensures the selection is in forward direction | `ensure_selections_forward` |
| `Alt-,` | Remove the primary selection | `remove_primary_selection` | | `,` | Keep only the primary selection | `keep_primary_selection` |
| `C` | Copy selection onto the next line (Add cursor below) | `copy_selection_on_next_line` | | `Alt-,` | Remove the primary selection | `remove_primary_selection` |
| `Alt-C` | Copy selection onto the previous line (Add cursor above) | `copy_selection_on_prev_line` | | `C` | Copy selection onto the next line (Add cursor below) | `copy_selection_on_next_line` |
| `(` | Rotate main selection backward | `rotate_selections_backward` | | `Alt-C` | Copy selection onto the previous line (Add cursor above) | `copy_selection_on_prev_line` |
| `)` | Rotate main selection forward | `rotate_selections_forward` | | `(` | Rotate main selection backward | `rotate_selections_backward` |
| `Alt-(` | Rotate selection contents backward | `rotate_selection_contents_backward` | | `)` | Rotate main selection forward | `rotate_selections_forward` |
| `Alt-)` | Rotate selection contents forward | `rotate_selection_contents_forward` | | `Alt-(` | Rotate selection contents backward | `rotate_selection_contents_backward` |
| `%` | Select entire file | `select_all` | | `Alt-)` | Rotate selection contents forward | `rotate_selection_contents_forward` |
| `x` | Select current line, if already selected, extend to next line | `extend_line_below` | | `%` | Select entire file | `select_all` |
| `X` | Extend selection to line bounds (line-wise selection) | `extend_to_line_bounds` | | `x` | Select current line, if already selected, extend to next line | `extend_line_below` |
| `Alt-x` | Shrink selection to line bounds (line-wise selection) | `shrink_to_line_bounds` | | `X` | Extend selection to line bounds (line-wise selection) | `extend_to_line_bounds` |
| `J` | Join lines inside selection | `join_selections` | | `Alt-x` | Shrink selection to line bounds (line-wise selection) | `shrink_to_line_bounds` |
| `Alt-J` | Join lines inside selection and select the inserted space | `join_selections_space` | | `J` | Join lines inside selection | `join_selections` |
| `K` | Keep selections matching the regex | `keep_selections` | | `Alt-J` | Join lines inside selection and select the inserted space | `join_selections_space` |
| `Alt-K` | Remove selections matching the regex | `remove_selections` | | `K` | Keep selections matching the regex | `keep_selections` |
| `Ctrl-c` | Comment/uncomment the selections | `toggle_comments` | | `Alt-K` | Remove selections matching the regex | `remove_selections` |
| `Alt-o`, `Alt-up` | Expand selection to parent syntax node (**TS**) | `expand_selection` | | `Ctrl-c` | Comment/uncomment the selections | `toggle_comments` |
| `Alt-i`, `Alt-down` | Shrink syntax tree object selection (**TS**) | `shrink_selection` | | `Alt-o`, `Alt-up` | Expand selection to parent syntax node (**TS**) | `expand_selection` |
| `Alt-p`, `Alt-left` | Select previous sibling node in syntax tree (**TS**) | `select_prev_sibling` | | `Alt-i`, `Alt-down` | Shrink syntax tree object selection (**TS**) | `shrink_selection` |
| `Alt-n`, `Alt-right` | Select next sibling node in syntax tree (**TS**) | `select_next_sibling` | | `Alt-p`, `Alt-left` | Select previous sibling node in syntax tree (**TS**) | `select_prev_sibling` |
| `Alt-n`, `Alt-right` | Select next sibling node in syntax tree (**TS**) | `select_next_sibling` |
| `Alt-a` | Select all sibling nodes in syntax tree (**TS**) | `select_all_siblings` |
| `Alt-I`, `Alt-Shift-down`| Select all children nodes in syntax tree (**TS**) | `select_all_children` |
| `Alt-e` | Move to end of parent node in syntax tree (**TS**) | `move_parent_node_end` |
| `Alt-b` | Move to start of parent node in syntax tree (**TS**) | `move_parent_node_start` |
### Search ### Search
@@ -149,7 +160,8 @@ Search commands all operate on the `/` register by default. To use a different r
| `?` | Search for previous pattern | `rsearch` | | `?` | Search for previous pattern | `rsearch` |
| `n` | Select next search match | `search_next` | | `n` | Select next search match | `search_next` |
| `N` | Select previous search match | `search_prev` | | `N` | Select previous search match | `search_prev` |
| `*` | Use current selection as the search pattern | `search_selection` | | `*` | Use current selection as the search pattern, automatically wrapping with `\b` on word boundaries | `search_selection_detect_word_boundaries` |
| `Alt-*` | Use current selection as the search pattern | `search_selection` |
### Minor modes ### Minor modes
@@ -179,18 +191,18 @@ normal mode) is persistent and can be exited using the escape key. This is
useful when you're simply looking over text and not actively editing it. useful when you're simply looking over text and not actively editing it.
| Key | Description | Command | | Key | Description | Command |
| ----- | ----------- | ------- | | ----- | ----------- | ------- |
| `z`, `c` | Vertically center the line | `align_view_center` | | `z`, `c` | Vertically center the line | `align_view_center` |
| `t` | Align the line to the top of the screen | `align_view_top` | | `t` | Align the line to the top of the screen | `align_view_top` |
| `b` | Align the line to the bottom of the screen | `align_view_bottom` | | `b` | Align the line to the bottom of the screen | `align_view_bottom` |
| `m` | Align the line to the middle of the screen (horizontally) | `align_view_middle` | | `m` | Align the line to the middle of the screen (horizontally) | `align_view_middle` |
| `j`, `down` | Scroll the view downwards | `scroll_down` | | `j`, `down` | Scroll the view downwards | `scroll_down` |
| `k`, `up` | Scroll the view upwards | `scroll_up` | | `k`, `up` | Scroll the view upwards | `scroll_up` |
| `Ctrl-f`, `PageDown` | Move page down | `page_down` | | `Ctrl-f`, `PageDown` | Move page down | `page_down` |
| `Ctrl-b`, `PageUp` | Move page up | `page_up` | | `Ctrl-b`, `PageUp` | Move page up | `page_up` |
| `Ctrl-d` | Move half page down | `half_page_down` | | `Ctrl-u` | Move cursor and page half page up | `page_cursor_half_up` |
| `Ctrl-u` | Move half page up | `half_page_up` | | `Ctrl-d` | Move cursor and page half page down | `page_cursor_half_down` |
#### Goto mode #### Goto mode
@@ -202,7 +214,7 @@ Jumps to various locations.
| ----- | ----------- | ------- | | ----- | ----------- | ------- |
| `g` | Go to line number `<n>` else start of file | `goto_file_start` | | `g` | Go to line number `<n>` else start of file | `goto_file_start` |
| `e` | Go to the end of the file | `goto_last_line` | | `e` | Go to the end of the file | `goto_last_line` |
| `f` | Go to files in the selection | `goto_file` | | `f` | Go to files in the selections | `goto_file` |
| `h` | Go to the start of the line | `goto_line_start` | | `h` | Go to the start of the line | `goto_line_start` |
| `l` | Go to the end of the line | `goto_line_end` | | `l` | Go to the end of the line | `goto_line_end` |
| `s` | Go to first non-whitespace character of the line | `goto_first_nonwhitespace` | | `s` | Go to first non-whitespace character of the line | `goto_first_nonwhitespace` |
@@ -218,13 +230,15 @@ Jumps to various locations.
| `n` | Go to next buffer | `goto_next_buffer` | | `n` | Go to next buffer | `goto_next_buffer` |
| `p` | Go to previous buffer | `goto_previous_buffer` | | `p` | Go to previous buffer | `goto_previous_buffer` |
| `.` | Go to last modification in current file | `goto_last_modification` | | `.` | Go to last modification in current file | `goto_last_modification` |
| `j` | Move down textual (instead of visual) line | `move_line_down` |
| `k` | Move up textual (instead of visual) line | `move_line_up` |
| `w` | Show labels at each word and select the word that belongs to the entered labels | `goto_word` |
#### Match mode #### Match mode
Accessed by typing `m` in [normal mode](#normal-mode). Accessed by typing `m` in [normal mode](#normal-mode).
See the relevant section in [Usage](./usage.md) for an explanation about Please refer to the relevant sections for detailed explanations about [surround](./surround.md) and [textobjects](./textobjects.md).
[surround](./usage.md#surround) and [textobject](./usage.md#navigating-using-tree-sitter-textobjects) usage.
| Key | Description | Command | | Key | Description | Command |
| ----- | ----------- | ------- | | ----- | ----------- | ------- |
@@ -248,8 +262,8 @@ This layer is similar to Vim keybindings as Kakoune does not support windows.
| `w`, `Ctrl-w` | Switch to next window | `rotate_view` | | `w`, `Ctrl-w` | Switch to next window | `rotate_view` |
| `v`, `Ctrl-v` | Vertical right split | `vsplit` | | `v`, `Ctrl-v` | Vertical right split | `vsplit` |
| `s`, `Ctrl-s` | Horizontal bottom split | `hsplit` | | `s`, `Ctrl-s` | Horizontal bottom split | `hsplit` |
| `f` | Go to files in the selection in horizontal splits | `goto_file` | | `f` | Go to files in the selections in horizontal splits | `goto_file` |
| `F` | Go to files in the selection in vertical splits | `goto_file` | | `F` | Go to files in the selections in vertical splits | `goto_file` |
| `h`, `Ctrl-h`, `Left` | Move to left split | `jump_view_left` | | `h`, `Ctrl-h`, `Left` | Move to left split | `jump_view_left` |
| `j`, `Ctrl-j`, `Down` | Move to split below | `jump_view_down` | | `j`, `Ctrl-j`, `Down` | Move to split below | `jump_view_down` |
| `k`, `Ctrl-k`, `Up` | Move to split above | `jump_view_up` | | `k`, `Ctrl-k`, `Up` | Move to split above | `jump_view_up` |
@@ -269,11 +283,12 @@ This layer is a kludge of mappings, mostly pickers.
| Key | Description | Command | | Key | Description | Command |
| ----- | ----------- | ------- | | ----- | ----------- | ------- |
| `f` | Open file picker | `file_picker` | | `f` | Open file picker at LSP workspace root | `file_picker` |
| `F` | Open file picker at current working directory | `file_picker_in_current_directory` | | `F` | Open file picker at current working directory | `file_picker_in_current_directory` |
| `b` | Open buffer picker | `buffer_picker` | | `b` | Open buffer picker | `buffer_picker` |
| `j` | Open jumplist picker | `jumplist_picker` | | `j` | Open jumplist picker | `jumplist_picker` |
| `g` | Debug (experimental) | N/A | | `g` | Open changed file picker | `changed_file_picker` |
| `G` | Debug (experimental) | N/A |
| `k` | Show documentation for item under cursor in a [popup](#popup) (**LSP**) | `hover` | | `k` | Show documentation for item under cursor in a [popup](#popup) (**LSP**) | `hover` |
| `s` | Open document symbol picker (**LSP**) | `symbol_picker` | | `s` | Open document symbol picker (**LSP**) | `symbol_picker` |
| `S` | Open workspace symbol picker (**LSP**) | `workspace_symbol_picker` | | `S` | Open workspace symbol picker (**LSP**) | `workspace_symbol_picker` |
@@ -284,9 +299,12 @@ This layer is a kludge of mappings, mostly pickers.
| `h` | Select symbol references (**LSP**) | `select_references_to_symbol_under_cursor` | | `h` | Select symbol references (**LSP**) | `select_references_to_symbol_under_cursor` |
| `'` | Open last fuzzy picker | `last_picker` | | `'` | Open last fuzzy picker | `last_picker` |
| `w` | Enter [window mode](#window-mode) | N/A | | `w` | Enter [window mode](#window-mode) | N/A |
| `c` | Comment/uncomment selections | `toggle_comments` |
| `C` | Block comment/uncomment selections | `toggle_block_comments` |
| `Alt-c` | Line comment/uncomment selections | `toggle_line_comments` |
| `p` | Paste system clipboard after selections | `paste_clipboard_after` | | `p` | Paste system clipboard after selections | `paste_clipboard_after` |
| `P` | Paste system clipboard before selections | `paste_clipboard_before` | | `P` | Paste system clipboard before selections | `paste_clipboard_before` |
| `y` | Join and yank selections to clipboard | `yank_joined_to_clipboard` | | `y` | Yank selections to clipboard | `yank_to_clipboard` |
| `Y` | Yank main selection to clipboard | `yank_main_selection_to_clipboard` | | `Y` | Yank main selection to clipboard | `yank_main_selection_to_clipboard` |
| `R` | Replace selections by clipboard contents | `replace_selections_with_clipboard` | | `R` | Replace selections by clipboard contents | `replace_selections_with_clipboard` |
| `/` | Global search in workspace folder | `global_search` | | `/` | Global search in workspace folder | `global_search` |
@@ -296,13 +314,35 @@ This layer is a kludge of mappings, mostly pickers.
##### Popup ##### Popup
Displays documentation for item under cursor. Displays documentation for item under cursor. Remapping currently not supported.
| Key | Description | | Key | Description |
| ---- | ----------- | | ---- | ----------- |
| `Ctrl-u` | Scroll up | | `Ctrl-u` | Scroll up |
| `Ctrl-d` | Scroll down | | `Ctrl-d` | Scroll down |
##### Completion Menu
Displays documentation for the selected completion item. Remapping currently not supported.
| Key | Description |
| ---- | ----------- |
| `Shift-Tab`, `Ctrl-p`, `Up` | Previous entry |
| `Tab`, `Ctrl-n`, `Down` | Next entry |
| `Enter` | Close menu and accept completion |
| `Ctrl-c` | Close menu and reject completion |
Any other keypresses result in the completion being accepted.
##### Signature-help Popup
Displays the signature of the selected completion item. Remapping currently not supported.
| Key | Description |
| ---- | ----------- |
| `Alt-p` | Previous signature |
| `Alt-n` | Next signature |
#### Unimpaired #### Unimpaired
These mappings are in the style of [vim-unimpaired](https://github.com/tpope/vim-unimpaired). These mappings are in the style of [vim-unimpaired](https://github.com/tpope/vim-unimpaired).
@@ -334,6 +374,8 @@ These mappings are in the style of [vim-unimpaired](https://github.com/tpope/vim
## Insert mode ## Insert mode
Accessed by typing `i` in [normal mode](#normal-mode).
Insert mode bindings are minimal by default. Helix is designed to Insert mode bindings are minimal by default. Helix is designed to
be a modal editor, and this is reflected in the user experience and internal be a modal editor, and this is reflected in the user experience and internal
mechanics. Changes to the text are only saved for undos when mechanics. Changes to the text are only saved for undos when
@@ -387,9 +429,11 @@ end = "no_op"
## Select / extend mode ## Select / extend mode
Accessed by typing `v` in [normal mode](#normal-mode).
Select mode echoes Normal mode, but changes any movements to extend Select mode echoes Normal mode, but changes any movements to extend
selections rather than replace them. Goto motions are also changed to selections rather than replace them. Goto motions are also changed to
extend, so that `vgl` for example extends the selection to the end of extend, so that `vgl`, for example, extends the selection to the end of
the line. the line.
Search is also affected. By default, `n` and `N` will remove the current Search is also affected. By default, `n` and `N` will remove the current
@@ -401,20 +445,23 @@ you to selectively add search terms to your selections.
## Picker ## Picker
Keys to use within picker. Remapping currently not supported. Keys to use within picker. Remapping currently not supported.
See the documentation page on [pickers](./pickers.md) for more info.
[Prompt](#prompt) keybinds also work in pickers, except where they conflict with picker keybinds.
| Key | Description | | Key | Description |
| ----- | ------------- | | ----- | ------------- |
| `Shift-Tab`, `Up`, `Ctrl-p` | Previous entry | | `Shift-Tab`, `Up`, `Ctrl-p` | Previous entry |
| `Tab`, `Down`, `Ctrl-n` | Next entry | | `Tab`, `Down`, `Ctrl-n` | Next entry |
| `PageUp`, `Ctrl-u` | Page up | | `PageUp`, `Ctrl-u` | Page up |
| `PageDown`, `Ctrl-d` | Page down | | `PageDown`, `Ctrl-d` | Page down |
| `Home` | Go to first entry | | `Home` | Go to first entry |
| `End` | Go to last entry | | `End` | Go to last entry |
| `Enter` | Open selected | | `Enter` | Open selected |
| `Ctrl-s` | Open horizontally | | `Alt-Enter` | Open selected in the background without closing the picker |
| `Ctrl-v` | Open vertically | | `Ctrl-s` | Open horizontally |
| `Ctrl-t` | Toggle preview | | `Ctrl-v` | Open vertically |
| `Escape`, `Ctrl-c` | Close picker | | `Ctrl-t` | Toggle preview |
| `Escape`, `Ctrl-c` | Close picker |
## Prompt ## Prompt

View File

@@ -1,7 +1,7 @@
# Language Support ## Language Support
The following languages and Language Servers are supported. To use The following languages and Language Servers are supported. To use
Language Server features, you must first [install][lsp-install-wiki] the Language Server features, you must first [configure][lsp-config-wiki] the
appropriate Language Server. appropriate Language Server.
You can check the language support in your installed helix version with `hx --health`. You can check the language support in your installed helix version with `hx --health`.
@@ -11,6 +11,6 @@ Languages][adding-languages] guide for more language configuration information.
{{#include ./generated/lang-support.md}} {{#include ./generated/lang-support.md}}
[lsp-install-wiki]: https://github.com/helix-editor/helix/wiki/How-to-install-the-default-language-servers [lsp-config-wiki]: https://github.com/helix-editor/helix/wiki/Language-Server-Configurations
[lang-config]: ./languages.md [lang-config]: ./languages.md
[adding-languages]: ./guides/adding_languages.md [adding-languages]: ./guides/adding_languages.md

View File

@@ -1,4 +1,4 @@
# Languages ## Languages
Language-specific settings and settings for language servers are configured Language-specific settings and settings for language servers are configured
in `languages.toml` files. in `languages.toml` files.
@@ -7,21 +7,24 @@ in `languages.toml` files.
There are three possible locations for a `languages.toml` file: There are three possible locations for a `languages.toml` file:
1. In the Helix source code, this lives in the 1. In the Helix source code, which lives in the
[Helix repository](https://github.com/helix-editor/helix/blob/master/languages.toml). [Helix repository](https://github.com/helix-editor/helix/blob/master/languages.toml).
It provides the default configurations for languages and language servers. It provides the default configurations for languages and language servers.
2. In your [configuration directory](./configuration.md). This overrides values 2. In your [configuration directory](./configuration.md). This overrides values
from the built-in language configuration. For example to disable from the built-in language configuration. For example, to disable
auto-LSP-formatting in Rust: auto-formatting for Rust:
```toml ```toml
# in <config_dir>/helix/languages.toml # in <config_dir>/helix/languages.toml
[[language]] [language-server.mylang-lsp]
name = "rust" command = "mylang-lsp"
auto-format = false
``` [[language]]
name = "rust"
auto-format = false
```
3. In a `.helix` folder in your project. Language configuration may also be 3. In a `.helix` folder in your project. Language configuration may also be
overridden local to a project by creating a `languages.toml` file in a overridden local to a project by creating a `languages.toml` file in a
@@ -39,10 +42,10 @@ name = "mylang"
scope = "source.mylang" scope = "source.mylang"
injection-regex = "mylang" injection-regex = "mylang"
file-types = ["mylang", "myl"] file-types = ["mylang", "myl"]
comment-token = "#" comment-tokens = "#"
indent = { tab-width = 2, unit = " " } indent = { tab-width = 2, unit = " " }
language-server = { command = "mylang-lsp", args = ["--stdio"], environment = { "ENV1" = "value1", "ENV2" = "value2" } }
formatter = { command = "mylang-formatter" , args = ["--stdin"] } formatter = { command = "mylang-formatter" , args = ["--stdin"] }
language-servers = [ "mylang-lsp" ]
``` ```
These configuration keys are available: These configuration keys are available:
@@ -50,21 +53,25 @@ These configuration keys are available:
| Key | Description | | Key | Description |
| ---- | ----------- | | ---- | ----------- |
| `name` | The name of the language | | `name` | The name of the language |
| `language-id` | The language-id for language servers, checkout the table at [TextDocumentItem](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentItem) for the right id |
| `scope` | A string like `source.js` that identifies the language. Currently, we strive to match the scope names used by popular TextMate grammars and by the Linguist library. Usually `source.<name>` or `text.<name>` in case of markup languages | | `scope` | A string like `source.js` that identifies the language. Currently, we strive to match the scope names used by popular TextMate grammars and by the Linguist library. Usually `source.<name>` or `text.<name>` in case of markup languages |
| `injection-regex` | regex pattern that will be tested against a language name in order to determine whether this language should be used for a potential [language injection][treesitter-language-injection] site. | | `injection-regex` | regex pattern that will be tested against a language name in order to determine whether this language should be used for a potential [language injection][treesitter-language-injection] site. |
| `file-types` | The filetypes of the language, for example `["yml", "yaml"]`. See the file-type detection section below. | | `file-types` | The filetypes of the language, for example `["yml", "yaml"]`. See the file-type detection section below. |
| `shebangs` | The interpreters from the shebang line, for example `["sh", "bash"]` | | `shebangs` | The interpreters from the shebang line, for example `["sh", "bash"]` |
| `roots` | A set of marker files to look for when trying to find the workspace root. For example `Cargo.lock`, `yarn.lock` | | `roots` | A set of marker files to look for when trying to find the workspace root. For example `Cargo.lock`, `yarn.lock` |
| `auto-format` | Whether to autoformat this language when saving | | `auto-format` | Whether to autoformat this language when saving |
| `diagnostic-severity` | Minimal severity of diagnostic for it to be displayed. (Allowed values: `Error`, `Warning`, `Info`, `Hint`) | | `diagnostic-severity` | Minimal severity of diagnostic for it to be displayed. (Allowed values: `error`, `warning`, `info`, `hint`) |
| `comment-token` | The token to use as a comment-token | | `comment-tokens` | The tokens to use as a comment token, either a single token `"//"` or an array `["//", "///", "//!"]` (the first token will be used for commenting). Also configurable as `comment-token` for backwards compatibility|
| `block-comment-tokens`| The start and end tokens for a multiline comment either an array or single table of `{ start = "/*", end = "*/"}`. The first set of tokens will be used for commenting, any pairs in the array can be uncommented |
| `indent` | The indent to use. Has sub keys `unit` (the text inserted into the document when indenting; usually set to N spaces or `"\t"` for tabs) and `tab-width` (the number of spaces rendered for a tab) | | `indent` | The indent to use. Has sub keys `unit` (the text inserted into the document when indenting; usually set to N spaces or `"\t"` for tabs) and `tab-width` (the number of spaces rendered for a tab) |
| `language-server` | The Language Server to run. See the Language Server configuration section below. | | `language-servers` | The Language Servers used for this language. See below for more information in the section [Configuring Language Servers for a language](#configuring-language-servers-for-a-language) |
| `config` | Language Server configuration |
| `grammar` | The tree-sitter grammar to use (defaults to the value of `name`) | | `grammar` | The tree-sitter grammar to use (defaults to the value of `name`) |
| `formatter` | The formatter for the language, it will take precedence over the lsp when defined. The formatter must be able to take the original file as input from stdin and write the formatted file to stdout | | `formatter` | The formatter for the language, it will take precedence over the lsp when defined. The formatter must be able to take the original file as input from stdin and write the formatted file to stdout |
| `text-width` | Maximum line length. Used for the `:reflow` command and soft-wrapping if `soft-wrap.wrap_at_text_width` is set, defaults to `editor.text-width` | | `soft-wrap` | [editor.softwrap](./configuration.md#editorsoft-wrap-section)
| `text-width` | Maximum line length. Used for the `:reflow` command and soft-wrapping if `soft-wrap.wrap-at-text-width` is set, defaults to `editor.text-width` |
| `path-completion` | Overrides the `editor.path-completion` config key for the language. |
| `workspace-lsp-roots` | Directories relative to the workspace root that are treated as LSP roots. Should only be set in `.helix/config.toml`. Overwrites the setting of the same name in `config.toml` if set. | | `workspace-lsp-roots` | Directories relative to the workspace root that are treated as LSP roots. Should only be set in `.helix/config.toml`. Overwrites the setting of the same name in `config.toml` if set. |
| `persistent-diagnostic-sources` | An array of LSP diagnostic sources assumed unchanged when the language server resends the same set of diagnostics. Helix can track the position for these diagnostics internally instead. Useful for diagnostics that are recomputed on save.
### File-type detection and the `file-types` key ### File-type detection and the `file-types` key
@@ -73,50 +80,126 @@ from the above section. `file-types` is a list of strings or tables, for
example: example:
```toml ```toml
file-types = ["Makefile", "toml", { suffix = ".git/config" }] file-types = ["toml", { glob = "Makefile" }, { glob = ".git/config" }, { glob = ".github/workflows/*.yaml" } ]
``` ```
When determining a language configuration to use, Helix searches the file-types When determining a language configuration to use, Helix searches the file-types
with the following priorities: with the following priorities:
1. Exact match: if the filename of a file is an exact match of a string in a 1. Glob: values in `glob` tables are checked against the full path of the given
`file-types` list, that language wins. In the example above, `"Makefile"` file. Globs are standard Unix-style path globs (e.g. the kind you use in Shell)
will match against `Makefile` files. and can be used to match paths for a specific prefix, suffix, directory, etc.
2. Extension: if there are no exact matches, any `file-types` string that In the above example, the `{ glob = "Makefile" }` config would match files
matches the file extension of a given file wins. In the example above, the with the name `Makefile`, the `{ glob = ".git/config" }` config would match
`"toml"` matches files like `Cargo.toml` or `languages.toml`. `config` files in `.git` directories, and the `{ glob = ".github/workflows/*.yaml" }`
3. Suffix: if there are still no matches, any values in `suffix` tables config would match any `yaml` files in `.github/workflow` directories. Note
are checked against the full path of the given file. In the example above, that globs should always use the Unix path separator `/` even on Windows systems;
the `{ suffix = ".git/config" }` would match against any `config` files the matcher will automatically take the machine-specific separators into account.
in `.git` directories. Note: `/` is used as the directory separator but is If the glob isn't an absolute path or doesn't already start with a glob prefix,
replaced at runtime with the appropriate path separator for the operating `*/` will automatically be added to ensure it matches for any subdirectory.
system, so this rule would match against `.git\config` files on Windows. 2. Extension: if there are no glob matches, any `file-types` string that matches
the file extension of a given file wins. In the example above, the `"toml"`
config matches files like `Cargo.toml` or `languages.toml`.
### Language Server configuration ## Language Server configuration
The `language-server` field takes the following keys: Language servers are configured separately in the table `language-server` in the same file as the languages `languages.toml`
| Key | Description | For example:
| --- | ----------- |
| `command` | The name of the language server binary to execute. Binaries must be in `$PATH` |
| `args` | A list of arguments to pass to the language server binary |
| `timeout` | The maximum time a request to the language server may take, in seconds. Defaults to `20` |
| `language-id` | The language name to pass to the language server. Some language servers support multiple languages and use this field to determine which one is being served in a buffer |
| `environment` | Any environment variables that will be used when starting the language server `{ "KEY1" = "Value1", "KEY2" = "Value2" }` |
The top-level `config` field is used to configure the LSP initialization options. A `format` ```toml
sub-table within `config` can be used to pass extra formatting options to [language-server.mylang-lsp]
[Document Formatting Requests](https://github.com/microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-16.md#document-formatting-request--leftwards_arrow_with_hook). command = "mylang-lsp"
For example with typescript: args = ["--stdio"]
config = { provideFormatter = true }
environment = { "ENV1" = "value1", "ENV2" = "value2" }
[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 } ] }
```
These are the available options for a language server.
| Key | Description |
| ---- | ----------- |
| `command` | The name or path of the language server binary to execute. Binaries must be in `$PATH` |
| `args` | A list of arguments to pass to the language server binary |
| `config` | Language server initialization options |
| `timeout` | The maximum time a request to the language server may take, in seconds. Defaults to `20` |
| `environment` | Any environment variables that will be used when starting the language server `{ "KEY1" = "Value1", "KEY2" = "Value2" }` |
| `required-root-patterns` | A list of `glob` patterns to look for in the working directory. The language server is started if at least one of them is found. |
A `format` sub-table within `config` can be used to pass extra formatting options to
[Document Formatting Requests](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_formatting).
For example, with typescript:
```toml
[language-server.typescript-language-server]
# pass format options according to https://github.com/typescript-language-server/typescript-language-server#workspacedidchangeconfiguration omitting the "[language].format." prefix.
config = { format = { "semicolons" = "insert", "insertSpaceBeforeFunctionParenthesis" = true } }
```
### Configuring Language Servers for a language
The `language-servers` attribute in a language tells helix which language servers are used for this language.
They have to be defined in the `[language-server]` table as described in the previous section.
Different languages can use the same language server instance, e.g. `typescript-language-server` is used for javascript, jsx, tsx and typescript by default.
The definition order of language servers affects the order in the results list of code action menu.
In case multiple language servers are specified in the `language-servers` attribute of a `language`,
it's often useful to only enable/disable certain language-server features for these language servers.
As an example, `efm-lsp-prettier` of the previous example is used only with a formatting command `prettier`,
so everything else should be handled by the `typescript-language-server` (which is configured by default).
The language configuration for typescript could look like this:
```toml ```toml
[[language]] [[language]]
name = "typescript" name = "typescript"
auto-format = true language-servers = [ { name = "efm-lsp-prettier", only-features = [ "format" ] }, "typescript-language-server" ]
# pass format options according to https://github.com/typescript-language-server/typescript-language-server#workspacedidchangeconfiguration omitting the "[language].format." prefix.
config = { format = { "semicolons" = "insert", "insertSpaceBeforeFunctionParenthesis" = true } }
``` ```
or equivalent:
```toml
[[language]]
name = "typescript"
language-servers = [ { name = "typescript-language-server", except-features = [ "format" ] }, "efm-lsp-prettier" ]
```
Each requested LSP feature is prioritized 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`).
The features `diagnostics`, `code-action`, `completion`, `document-symbols` and `workspace-symbols` are an exception to that rule, as they are working for all language servers at the same time and are merged together, if enabled for the language.
If no `except-features` or `only-features` is given, all features for the language server are enabled.
If a language server itself doesn't support a feature, the next language server array entry will be tried (and so on).
The list of supported features is:
- `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`
## Tree-sitter grammar configuration ## Tree-sitter grammar configuration
The source for a language's tree-sitter grammar is specified in a `[[grammar]]` The source for a language's tree-sitter grammar is specified in a `[[grammar]]`

View File

@@ -0,0 +1,158 @@
## Package managers
- [Linux](#linux)
- [Ubuntu](#ubuntu)
- [Fedora/RHEL](#fedorarhel)
- [Arch Linux extra](#arch-linux-extra)
- [NixOS](#nixos)
- [Flatpak](#flatpak)
- [Snap](#snap)
- [AppImage](#appimage)
- [macOS](#macos)
- [Homebrew Core](#homebrew-core)
- [MacPorts](#macports)
- [Windows](#windows)
- [Winget](#winget)
- [Scoop](#scoop)
- [Chocolatey](#chocolatey)
- [MSYS2](#msys2)
[![Packaging status](https://repology.org/badge/vertical-allrepos/helix-editor.svg)](https://repology.org/project/helix-editor/versions)
## Linux
The following third party repositories are available:
### Ubuntu
Add the `PPA` for Helix:
```sh
sudo add-apt-repository ppa:maveonair/helix-editor
sudo apt update
sudo apt install helix
```
### Fedora/RHEL
```sh
sudo dnf install helix
```
### Arch Linux extra
Releases are available in the `extra` repository:
```sh
sudo pacman -S helix
```
> 💡 When installed from the `extra` repository, run Helix with `helix` instead of `hx`.
>
> For example:
> ```sh
> helix --health
> ```
> to check health
Additionally, a [helix-git](https://aur.archlinux.org/packages/helix-git/) package is available
in the AUR, which builds the master branch.
### NixOS
Helix is available in [nixpkgs](https://github.com/nixos/nixpkgs) through the `helix` attribute,
the unstable channel usually carries the latest release.
Helix is also available as a [flake](https://wiki.nixos.org/wiki/Flakes) in the project
root. Use `nix develop` to spin up a reproducible development shell. Outputs are
cached for each push to master using [Cachix](https://www.cachix.org/). The
flake is configured to automatically make use of this cache assuming the user
accepts the new settings on first use.
If you are using a version of Nix without flakes enabled,
[install Cachix CLI](https://docs.cachix.org/installation) and use
`cachix use helix` to configure Nix to use cached outputs when possible.
### Flatpak
Helix is available on [Flathub](https://flathub.org/en-GB/apps/com.helix_editor.Helix):
```sh
flatpak install flathub com.helix_editor.Helix
flatpak run com.helix_editor.Helix
```
### Snap
Helix is available on [Snapcraft](https://snapcraft.io/helix) and can be installed with:
```sh
snap install --classic helix
```
This will install Helix as both `/snap/bin/helix` and `/snap/bin/hx`, so make sure `/snap/bin` is in your `PATH`.
### AppImage
Install Helix using the Linux [AppImage](https://appimage.org/) format.
Download the official Helix AppImage from the [latest releases](https://github.com/helix-editor/helix/releases/latest) page.
```sh
chmod +x helix-*.AppImage # change permission for executable mode
./helix-*.AppImage # run helix
```
You can optionally [add the `.desktop` file](./building-from-source.md#configure-the-desktop-shortcut). Helix must be installed in `PATH` with the name `hx`. For example:
```sh
mkdir -p "$HOME/.local/bin"
mv helix-*.AppImage "$HOME/.local/bin/hx"
```
and make sure `~/.local/bin` is in your `PATH`.
## macOS
### Homebrew Core
```sh
brew install helix
```
### MacPorts
```sh
port install helix
```
## Windows
Install on Windows using [Winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/), [Scoop](https://scoop.sh/), [Chocolatey](https://chocolatey.org/)
or [MSYS2](https://msys2.org/).
### Winget
Windows Package Manager winget command-line tool is by default available on Windows 11 and modern versions of Windows 10 as a part of the App Installer.
You can get [App Installer from the Microsoft Store](https://www.microsoft.com/p/app-installer/9nblggh4nns1#activetab=pivot:overviewtab). If it's already installed, make sure it is updated with the latest version.
```sh
winget install Helix.Helix
```
### Scoop
```sh
scoop install helix
```
### Chocolatey
```sh
choco install helix
```
### MSYS2
For 64-bit Windows 8.1 or above:
```sh
pacman -S mingw-w64-ucrt-x86_64-helix
```

11
book/src/pickers.md Normal file
View File

@@ -0,0 +1,11 @@
## Using pickers
Helix has a variety of pickers, which are interactive windows used to select various kinds of items. These include a file picker, global search picker, and more. Most pickers are accessed via keybindings in [space mode](./keymap.md#space-mode). Pickers have their own [keymap](./keymap.md#picker) for navigation.
### Filtering Picker Results
Most pickers perform fuzzy matching using [fzf syntax](https://github.com/junegunn/fzf?tab=readme-ov-file#search-syntax). Two exceptions are the global search picker, which uses regex, and the workspace symbol picker, which passes search terms to the language server. Note that OR operations (`|`) are not currently supported.
If a picker shows multiple columns, you may apply the filter to a specific column by prefixing the column name with `%`. Column names can be shortened to any prefix, so `%p`, `%pa` or `%pat` all mean the same as `%path`. For example, a query of `helix %p .toml !lang` in the global search picker searches for the term "helix" within files with paths ending in ".toml" but not including "lang".
You can insert the contents of a [register](./registers.md) using `Ctrl-r` followed by a register name. For example, one could insert the currently selected text using `Ctrl-r`-`.`, or the directory of the current file using `Ctrl-r`-`%` followed by `Ctrl-w` to remove the last path section. The global search picker will use the contents of the [search register](./registers.md#default-registers) if you press `Enter` without typing a filter. For example, pressing `*`-`Space-/`-`Enter` will start a global search for the currently selected text.

54
book/src/registers.md Normal file
View File

@@ -0,0 +1,54 @@
## Registers
- [User-defined registers](#user-defined-registers)
- [Default registers](#default-registers)
- [Special registers](#special-registers)
In Helix, registers are storage locations for text and other data, such as the
result of a search. Registers can be used to cut, copy, and paste text, similar
to the clipboard in other text editors. Usage is similar to Vim, with `"` being
used to select a register.
### User-defined registers
Helix allows you to create your own named registers for storing text, for
example:
- `"ay` - Yank the current selection to register `a`.
- `"op` - Paste the text in register `o` after the selection.
If a register is selected before invoking a change or delete command, the selection will be stored in the register and the action will be carried out:
- `"hc` - Store the selection in register `h` and then change it (delete and enter insert mode).
- `"md` - Store the selection in register `m` and delete it.
### Default registers
Commands that use registers, like yank (`y`), use a default register if none is specified.
These registers are used as defaults:
| Register character | Contains |
| --- | --- |
| `/` | Last search |
| `:` | Last executed command |
| `"` | Last yanked text |
| `@` | Last recorded macro |
### Special registers
Some registers have special behavior when read from and written to.
| Register character | When read | When written |
| --- | --- | --- |
| `_` | No values are returned | All values are discarded |
| `#` | Selection indices (first selection is `1`, second is `2`, etc.) | This register is not writable |
| `.` | Contents of the current selections | This register is not writable |
| `%` | Name of the current file | This register is not writable |
| `+` | Reads from the system clipboard | Joins and yanks to the system clipboard |
| `*` | Reads from the primary clipboard | Joins and yanks to the primary clipboard |
When yanking multiple selections to the clipboard registers, the selections
are joined with newlines. Pasting from these registers will paste multiple
selections if the clipboard was last yanked to by the Helix session. Otherwise
the clipboard contents are pasted as one selection.

View File

@@ -1,13 +1,34 @@
# Key remapping ## Key remapping
Helix currently supports one-way key remapping through a simple TOML configuration Helix currently supports one-way key remapping through a simple TOML configuration
file. (More powerful solutions such as rebinding via commands will be file. (More powerful solutions such as rebinding via commands will be
available in the future). available in the future).
There are three kinds of commands that can be used in keymaps:
* Static commands: commands like `move_char_right` which are usually bound to
keys and used for movement and editing. A list of static commands is
available in the [Keymap](./keymap.html) documentation and in the source code
in [`helix-term/src/commands.rs`](https://github.com/helix-editor/helix/blob/master/helix-term/src/commands.rs)
at the invocation of `static_commands!` macro.
* Typable commands: commands that can be executed from command mode (`:`), for
example `:write!`. See the [Commands](./commands.html) documentation for a
list of available typeable commands or the `TypableCommandList` declaration in
the source code at [`helix-term/src/commands/typed.rs`](https://github.com/helix-editor/helix/blob/master/helix-term/src/commands/typed.rs).
* Macros: sequences of keys that are executed in order. These keybindings
start with `@` and then list any number of keys to be executed. For example
`@miw` can be used to select the surrounding word. For now, macro keybindings
are not allowed in keybinding sequences due to limitations in the way that
command sequences are executed. Modifier keys (e.g. Alt+o) can be used
like `"<A-o>"`, e.g. `"@miw<A-o>"`
To remap keys, create a `config.toml` file in your `helix` configuration To remap keys, create a `config.toml` file in your `helix` configuration
directory (default `~/.config/helix` on Linux systems) with a structure like directory (default `~/.config/helix` on Linux systems) with a structure like
this: this:
> 💡 To set a modifier + key as a keymap, type `A-X = ...` or `C-X = ...` for Alt + X or Ctrl + X. Combine with Shift using a dash, e.g. `C-S-esc`.
> Within macros, wrap them in `<>`, e.g. `<A-X>` and `<C-X>` to distinguish from the `A` or `C` keys.
```toml ```toml
# At most one section each of 'keys.normal', 'keys.insert' and 'keys.select' # At most one section each of 'keys.normal', 'keys.insert' and 'keys.select'
[keys.normal] [keys.normal]
@@ -18,6 +39,7 @@ w = "move_line_up" # Maps the 'w' key move_line_up
"C-S-esc" = "extend_line" # Maps Ctrl-Shift-Escape to extend_line "C-S-esc" = "extend_line" # Maps Ctrl-Shift-Escape to extend_line
g = { a = "code_action" } # Maps `ga` to show possible code actions g = { a = "code_action" } # Maps `ga` to show possible code actions
"ret" = ["open_below", "normal_mode"] # Maps the enter key to open_below then re-enter normal mode "ret" = ["open_below", "normal_mode"] # Maps the enter key to open_below then re-enter normal mode
"A-x" = "@x<A-d>" # Maps Alt-x to a macro selecting the whole line and deleting it without yanking it
[keys.insert] [keys.insert]
"A-x" = "normal_mode" # Maps Alt-X to enter normal mode "A-x" = "normal_mode" # Maps Alt-X to enter normal mode
@@ -50,15 +72,28 @@ t = ":run-shell-command cargo test"
## Special keys and modifiers ## Special keys and modifiers
Ctrl, Shift and Alt modifiers are encoded respectively with the prefixes Ctrl, Shift and Alt modifiers are encoded respectively with the prefixes `C-`, `S-` and `A-`.
`C-`, `S-` and `A-`. Special keys are encoded as follows:
The [Super key](https://en.wikipedia.org/wiki/Super_key_(keyboard_button)) - the Windows/Linux
key or the Command key on Mac keyboards - is also supported when using a terminal emulator that
supports the [enhanced keyboard protocol](https://github.com/helix-editor/helix/wiki/Terminal-Support#enhanced-keyboard-protocol).
The super key is encoded with prefixes `Meta-`, `Cmd-` or `Win-`. These are all synonyms for the
super modifier - binding a key with a `Win-` modifier will mean it can be used with the
Windows/Linux key or the Command key.
```toml
[keys.normal]
C-s = ":write" # Ctrl and 's' to write
Cmd-s = ":write" # Cmd or Win or Meta and 's' to write
```
Special keys are encoded as follows:
| Key name | Representation | | Key name | Representation |
| --- | --- | | --- | --- |
| Backspace | `"backspace"` | | Backspace | `"backspace"` |
| Space | `"space"` | | Space | `"space"` |
| Return/Enter | `"ret"` | | Return/Enter | `"ret"` |
| \- | `"minus"` |
| Left | `"left"` | | Left | `"left"` |
| Right | `"right"` | | Right | `"right"` |
| Up | `"up"` | | Up | `"up"` |
@@ -75,5 +110,13 @@ Ctrl, Shift and Alt modifiers are encoded respectively with the prefixes
Keys can be disabled by binding them to the `no_op` command. Keys can be disabled by binding them to the `no_op` command.
A list of commands is available in the [Keymap](https://docs.helix-editor.com/keymap.html) documentation All other keys such as `?`, `!`, `-` etc. can be used literally:
and in the source code at [`helix-term/src/commands.rs`](https://github.com/helix-editor/helix/blob/master/helix-term/src/commands.rs) at the invocation of `static_commands!` macro and the `TypableCommandList`.
```toml
[keys.normal]
"?" = ":write"
"!" = ":write"
"-" = ":write"
```
Note: `-` can't be used when combined with a modifier, for example `Alt` + `-` should be written as `A-minus`. `A--` is not accepted.

24
book/src/surround.md Normal file
View File

@@ -0,0 +1,24 @@
## Surround
Helix includes built-in functionality similar to [vim-surround](https://github.com/tpope/vim-surround).
The keymappings have been inspired from [vim-sandwich](https://github.com/machakann/vim-sandwich):
![Surround demo](https://user-images.githubusercontent.com/23398472/122865801-97073180-d344-11eb-8142-8f43809982c6.gif)
| Key Sequence | Action |
| --------------------------------- | --------------------------------------- |
| `ms<char>` (after selecting text) | Add surround characters to selection |
| `mr<char_to_replace><new_char>` | Replace the closest surround characters |
| `md<char_to_delete>` | Delete the closest surround characters |
You can use counts to act on outer pairs.
Surround can also act on multiple selections. For example, to change every occurrence of `(use)` to `[use]`:
1. `%` to select the whole file
2. `s` to split the selections on a search term
3. Input `use` and hit Enter
4. `mr([` to replace the parentheses with square brackets
Multiple characters are currently not supported, but planned for future release.

View File

@@ -0,0 +1,66 @@
## Moving the selection with syntax-aware motions
`Alt-p`, `Alt-o`, `Alt-i`, and `Alt-n` (or `Alt` and arrow keys) allow you to move the
selection according to its location in the syntax tree. For example, many languages have the
following syntax for function calls:
```js
func(arg1, arg2, arg3);
```
A function call might be parsed by tree-sitter into a tree like the following.
```tsq
(call
function: (identifier) ; func
arguments:
(arguments ; (arg1, arg2, arg3)
(identifier) ; arg1
(identifier) ; arg2
(identifier))) ; arg3
```
Use `:tree-sitter-subtree` to view the syntax tree of the primary selection. In
a more intuitive tree format:
```
┌────┐
│call│
┌─────┴────┴─────┐
│ │
┌─────▼────┐ ┌────▼────┐
│identifier│ │arguments│
│ "func" │ ┌────┴───┬─────┴───┐
└──────────┘ │ │ │
│ │ │
┌─────────▼┐ ┌────▼─────┐ ┌▼─────────┐
│identifier│ │identifier│ │identifier│
│ "arg1" │ │ "arg2" │ │ "arg3" │
└──────────┘ └──────────┘ └──────────┘
```
If you have a selection that wraps `arg1` (see the tree above), and you use
`Alt-n`, it will select the next sibling in the syntax tree: `arg2`.
```js
// before
func([arg1], arg2, arg3)
// after
func(arg1, [arg2], arg3);
```
Similarly, `Alt-o` will expand the selection to the parent node, in this case, the
arguments node.
```js
func[(arg1, arg2, arg3)];
```
There is also some nuanced behavior that prevents you from getting stuck on a
node with no sibling. When using `Alt-p` with a selection on `arg1`, the previous
child node will be selected. In the event that `arg1` does not have a previous
sibling, the selection will move up the syntax tree and select the previous
element. As a result, using `Alt-p` with a selection on `arg1` will move the
selection to the "func" `identifier`.
[lang-support]: ./lang-support.md

47
book/src/textobjects.md Normal file
View File

@@ -0,0 +1,47 @@
## Selecting and manipulating text with textobjects
In Helix, textobjects are a way to select, manipulate and operate on a piece of
text in a structured way. They allow you to refer to blocks of text based on
their structure or purpose, such as a word, sentence, paragraph, or even a
function or block of code.
![Textobject demo](https://user-images.githubusercontent.com/23398472/124231131-81a4bb00-db2d-11eb-9d10-8e577ca7b177.gif)
![Textobject tree-sitter demo](https://user-images.githubusercontent.com/23398472/132537398-2a2e0a54-582b-44ab-a77f-eb818942203d.gif)
- `ma` - Select around the object (`va` in Vim, `<alt-a>` in Kakoune)
- `mi` - Select inside the object (`vi` in Vim, `<alt-i>` in Kakoune)
| Key after `mi` or `ma` | Textobject selected |
| --- | --- |
| `w` | Word |
| `W` | WORD |
| `p` | Paragraph |
| `(`, `[`, `'`, etc. | Specified surround pairs |
| `m` | The closest surround pair |
| `f` | Function |
| `t` | Type (or Class) |
| `a` | Argument/parameter |
| `c` | Comment |
| `T` | Test |
| `g` | Change |
> 💡 `f`, `t`, etc. need a tree-sitter grammar active for the current
document and a special tree-sitter query file to work properly. [Only
some grammars](./lang-support.md) currently have the query file implemented.
Contributions are welcome!
## Navigating using tree-sitter textobjects
Navigating between functions, classes, parameters, and other elements is
possible using tree-sitter and textobject queries. For
example to move to the next function use `]f`, to move to previous
type use `[t`, and so on.
![Tree-sitter-nav-demo](https://user-images.githubusercontent.com/23398472/152332550-7dfff043-36a2-4aec-b8f2-77c13eb56d6f.gif)
For the full reference see the [unimpaired](./keymap.html#unimpaired) section of the key bind
documentation.
> 💡 This feature relies on tree-sitter textobjects
> and requires the corresponding query file to work properly.

View File

@@ -1,4 +1,4 @@
# Themes ## Themes
To use a theme add `theme = "<name>"` to the top of your [`config.toml`](./configuration.md) file, or select it during runtime using `:theme <name>`. To use a theme add `theme = "<name>"` to the top of your [`config.toml`](./configuration.md) file, or select it during runtime using `:theme <name>`.
@@ -36,13 +36,6 @@ For inspiration, you can find the default `theme.toml`
user-submitted themes user-submitted themes
[here](https://github.com/helix-editor/helix/blob/master/runtime/themes). [here](https://github.com/helix-editor/helix/blob/master/runtime/themes).
### Using the linter
Use the supplied linting tool to check for errors and missing scopes:
```sh
cargo xtask themelint onedark # replace onedark with <name>
```
## The details of theme creation ## The details of theme creation
@@ -70,6 +63,7 @@ over it and is merged into the default palette.
| Color Name | | Color Name |
| --- | | --- |
| `default` |
| `black` | | `black` |
| `red` | | `red` |
| `green` | | `green` |
@@ -154,6 +148,7 @@ We use a similar set of scopes as
- `type` - Types - `type` - Types
- `builtin` - Primitive types provided by the language (`int`, `usize`) - `builtin` - Primitive types provided by the language (`int`, `usize`)
- `parameter` - Generic type parameters (`T`)
- `enum` - `enum`
- `variant` - `variant`
- `constructor` - `constructor`
@@ -184,6 +179,7 @@ We use a similar set of scopes as
- `parameter` - Function parameters - `parameter` - Function parameters
- `other` - `other`
- `member` - Fields of composite data types (e.g. structs, unions) - `member` - Fields of composite data types (e.g. structs, unions)
- `private` - Private fields that use a unique syntax (currently just ECMAScript-based languages)
- `label` - `label`
@@ -211,6 +207,7 @@ We use a similar set of scopes as
- `function` - `function`
- `builtin` - `builtin`
- `method` - `method`
- `private` - Private methods that use a unique syntax (currently just ECMAScript-based languages)
- `macro` - `macro`
- `special` (preprocessor in C) - `special` (preprocessor in C)
@@ -244,9 +241,13 @@ We use a similar set of scopes as
- `diff` - version control changes - `diff` - version control changes
- `plus` - additions - `plus` - additions
- `gutter` - gutter indicator
- `minus` - deletions - `minus` - deletions
- `gutter` - gutter indicator
- `delta` - modifications - `delta` - modifications
- `moved` - renamed or moved files/changes - `moved` - renamed or moved files/changes
- `conflict` - merge conflicts
- `gutter` - gutter indicator
#### Interface #### Interface
@@ -282,7 +283,6 @@ These scopes are used for theming the editor interface:
| `ui.debug.active` | Indicator for the line at which debugging execution is paused at, found in the gutter | | `ui.debug.active` | Indicator for the line at which debugging execution is paused at, found in the gutter |
| `ui.gutter` | Gutter | | `ui.gutter` | Gutter |
| `ui.gutter.selected` | Gutter for the line the cursor is on | | `ui.gutter.selected` | Gutter for the line the cursor is on |
| `ui.highlight.frameline` | Line at which debugging execution is paused at |
| `ui.linenr` | Line numbers | | `ui.linenr` | Line numbers |
| `ui.linenr.selected` | Line number for the line the cursor is on | | `ui.linenr.selected` | Line number for the line the cursor is on |
| `ui.statusline` | Statusline | | `ui.statusline` | Statusline |
@@ -291,27 +291,36 @@ These scopes are used for theming the editor interface:
| `ui.statusline.insert` | Statusline mode during insert mode ([only if `editor.color-modes` is enabled][editor-section]) | | `ui.statusline.insert` | Statusline mode during insert mode ([only if `editor.color-modes` is enabled][editor-section]) |
| `ui.statusline.select` | Statusline mode during select mode ([only if `editor.color-modes` is enabled][editor-section]) | | `ui.statusline.select` | Statusline mode during select mode ([only if `editor.color-modes` is enabled][editor-section]) |
| `ui.statusline.separator` | Separator character in statusline | | `ui.statusline.separator` | Separator character in statusline |
| `ui.bufferline` | Style for the buffer line |
| `ui.bufferline.active` | Style for the active buffer in buffer line |
| `ui.bufferline.background` | Style for bufferline background |
| `ui.popup` | Documentation popups (e.g. Space + k) | | `ui.popup` | Documentation popups (e.g. Space + k) |
| `ui.popup.info` | Prompt for multiple key options | | `ui.popup.info` | Prompt for multiple key options |
| `ui.picker.header` | Header row area in pickers with multiple columns |
| `ui.picker.header.column` | Column names in pickers with multiple columns |
| `ui.picker.header.column.active` | The column name in pickers with multiple columns where the cursor is entering into. |
| `ui.window` | Borderlines separating splits | | `ui.window` | Borderlines separating splits |
| `ui.help` | Description box for commands | | `ui.help` | Description box for commands |
| `ui.text` | Command prompts, popup text, etc. | | `ui.text` | Default text style, command prompts, popup text, etc. |
| `ui.text.focus` | | | `ui.text.focus` | The currently selected line in the picker |
| `ui.text.inactive` | Same as `ui.text` but when the text is inactive (e.g. suggestions) | | `ui.text.inactive` | Same as `ui.text` but when the text is inactive (e.g. suggestions) |
| `ui.text.info` | The key: command text in `ui.popup.info` boxes | | `ui.text.info` | The key: command text in `ui.popup.info` boxes |
| `ui.text.directory` | Directory names in prompt completion |
| `ui.virtual.ruler` | Ruler columns (see the [`editor.rulers` config][editor-section]) | | `ui.virtual.ruler` | Ruler columns (see the [`editor.rulers` config][editor-section]) |
| `ui.virtual.whitespace` | Visible whitespace characters | | `ui.virtual.whitespace` | Visible whitespace characters |
| `ui.virtual.indent-guide` | Vertical indent width guides | | `ui.virtual.indent-guide` | Vertical indent width guides |
| `ui.virtual.inlay-hint` | Default style for inlay hints of all kinds | | `ui.virtual.inlay-hint` | Default style for inlay hints of all kinds |
| `ui.virtual.inlay-hint.parameter` | Style for inlay hints of kind `parameter` (LSPs are not required to set a kind) | | `ui.virtual.inlay-hint.parameter` | Style for inlay hints of kind `parameter` (language servers are not required to set a kind) |
| `ui.virtual.inlay-hint.type` | Style for inlay hints of kind `type` (LSPs are not required to set a kind) | | `ui.virtual.inlay-hint.type` | Style for inlay hints of kind `type` (language servers are not required to set a kind) |
| `ui.virtual.wrap` | Soft-wrap indicator (see the [`editor.soft-wrap` config][editor-section]) | | `ui.virtual.wrap` | Soft-wrap indicator (see the [`editor.soft-wrap` config][editor-section]) |
| `ui.virtual.jump-label` | Style for virtual jump labels |
| `ui.menu` | Code and command completion menus | | `ui.menu` | Code and command completion menus |
| `ui.menu.selected` | Selected autocomplete item | | `ui.menu.selected` | Selected autocomplete item |
| `ui.menu.scroll` | `fg` sets thumb color, `bg` sets track color of scrollbar | | `ui.menu.scroll` | `fg` sets thumb color, `bg` sets track color of scrollbar |
| `ui.selection` | For selections in the editing area | | `ui.selection` | For selections in the editing area |
| `ui.selection.primary` | | | `ui.selection.primary` | |
| `ui.highlight` | Highlighted lines in the picker preview | | `ui.highlight` | Highlighted lines in the picker preview |
| `ui.highlight.frameline` | Line at which debugging execution is paused at |
| `ui.cursorline.primary` | The line of the primary cursor ([if cursorline is enabled][editor-section]) | | `ui.cursorline.primary` | The line of the primary cursor ([if cursorline is enabled][editor-section]) |
| `ui.cursorline.secondary` | The lines of any other cursors ([if cursorline is enabled][editor-section]) | | `ui.cursorline.secondary` | The lines of any other cursors ([if cursorline is enabled][editor-section]) |
| `ui.cursorcolumn.primary` | The column of the primary cursor ([if cursorcolumn is enabled][editor-section]) | | `ui.cursorcolumn.primary` | The column of the primary cursor ([if cursorcolumn is enabled][editor-section]) |
@@ -325,5 +334,7 @@ These scopes are used for theming the editor interface:
| `diagnostic.info` | Diagnostics info (editing area) | | `diagnostic.info` | Diagnostics info (editing area) |
| `diagnostic.warning` | Diagnostics warning (editing area) | | `diagnostic.warning` | Diagnostics warning (editing area) |
| `diagnostic.error` | Diagnostics error (editing area) | | `diagnostic.error` | Diagnostics error (editing area) |
| `diagnostic.unnecessary` | Diagnostics with unnecessary tag (editing area) |
| `diagnostic.deprecated` | Diagnostics with deprecated tag (editing area) |
[editor-section]: ./configuration.md#editor-section [editor-section]: ./configuration.md#editor-section

View File

@@ -1,15 +1,5 @@
# Using Helix # Using Helix
<!--toc:start-->
- [Registers](#registers)
- [User-defined registers](#user-defined-registers)
- [Special registers](#special-registers)
- [Surround](#surround)
- [Selecting and manipulating text with textobjects](#selecting-and-manipulating-text-with-textobjects)
- [Navigating using tree-sitter textobjects](#navigating-using-tree-sitter-textobjects)
- [Moving the selection with syntax-aware motions](#moving-the-selection-with-syntax-aware-motions)
<!--toc:end-->
For a full interactive introduction to Helix, refer to the For a full interactive introduction to Helix, refer to the
[tutor](https://github.com/helix-editor/helix/blob/master/runtime/tutor) which [tutor](https://github.com/helix-editor/helix/blob/master/runtime/tutor) which
can be accessed via the command `hx --tutor` or `:tutor`. can be accessed via the command `hx --tutor` or `:tutor`.
@@ -17,176 +7,27 @@ can be accessed via the command `hx --tutor` or `:tutor`.
> 💡 Currently, not all functionality is fully documented, please refer to the > 💡 Currently, not all functionality is fully documented, please refer to the
> [key mappings](./keymap.md) list. > [key mappings](./keymap.md) list.
## Registers ## Modes
In Helix, registers are storage locations for text and other data, such as the Helix is a modal editor, meaning it has different modes for different tasks. The main modes are:
result of a search. Registers can be used to cut, copy, and paste text, similar
to the clipboard in other text editors. Usage is similar to Vim, with `"` being
used to select a register.
### User-defined registers * [Normal mode](./keymap.md#normal-mode): For navigation and editing commands. This is the default mode.
* [Insert mode](./keymap.md#insert-mode): For typing text directly into the document. Access by typing `i` in normal mode.
* [Select/extend mode](./keymap.md#select--extend-mode): For making selections and performing operations on them. Access by typing `v` in normal mode.
Helix allows you to create your own named registers for storing text, for ## Buffers
example:
- `"ay` - Yank the current selection to register `a`. Buffers are in-memory representations of files. You can have multiple buffers open at once. Use [pickers](./pickers.md) or commands like `:buffer-next` and `:buffer-previous` to open buffers or switch between them.
- `"op` - Paste the text in register `o` after the selection.
If a register is selected before invoking a change or delete command, the selection will be stored in the register and the action will be carried out: ## Selection-first editing
- `"hc` - Store the selection in register `h` and then change it (delete and enter insert mode). Inspired by [Kakoune](http://kakoune.org/), Helix follows the `selection → action` model. This means that whatever you are going to act on (a word, a paragraph, a line, etc.) is selected first and the action itself (delete, change, yank, etc.) comes second. A cursor is simply a single width selection.
- `"md` - Store the selection in register `m` and delete it.
### Special registers ## Multiple selections
| Register character | Contains | Also inspired by Kakoune, multiple selections are a core mode of interaction in Helix. For example, the standard way of replacing multiple instance of a word is to first select all instances (so there is one selection per instance) and then use the change action (`c`) to edit them all at the same time.
| --- | --- |
| `/` | Last search |
| `:` | Last executed command |
| `"` | Last yanked text |
| `_` | Black hole |
The system clipboard is not directly supported by a special register. Instead, special commands and keybindings are provided. Refer to the ## Motions
[key map](keymap.md#space-mode) for more details.
The black hole register is a no-op register, meaning that no data will be read or written to it. Motions are commands that move the cursor or modify selections. They're used for navigation and text manipulation. Examples include `w` to move to the next word, or `f` to find a character. See the [Movement](./keymap.md#movement) section of the keymap for more motions.
## Surround
Helix includes built-in functionality similar to [vim-surround](https://github.com/tpope/vim-surround).
The keymappings have been inspired from [vim-sandwich](https://github.com/machakann/vim-sandwich):
![Surround demo](https://user-images.githubusercontent.com/23398472/122865801-97073180-d344-11eb-8142-8f43809982c6.gif)
| Key Sequence | Action |
| --------------------------------- | --------------------------------------- |
| `ms<char>` (after selecting text) | Add surround characters to selection |
| `mr<char_to_replace><new_char>` | Replace the closest surround characters |
| `md<char_to_delete>` | Delete the closest surround characters |
You can use counts to act on outer pairs.
Surround can also act on multiple selections. For example, to change every occurrence of `(use)` to `[use]`:
1. `%` to select the whole file
2. `s` to split the selections on a search term
3. Input `use` and hit Enter
4. `mr([` to replace the parentheses with square brackets
Multiple characters are currently not supported, but planned for future release.
## Selecting and manipulating text with textobjects
In Helix, textobjects are a way to select, manipulate and operate on a piece of
text in a structured way. They allow you to refer to blocks of text based on
their structure or purpose, such as a word, sentence, paragraph, or even a
function or block of code.
![Textobject demo](https://user-images.githubusercontent.com/23398472/124231131-81a4bb00-db2d-11eb-9d10-8e577ca7b177.gif)
![Textobject tree-sitter demo](https://user-images.githubusercontent.com/23398472/132537398-2a2e0a54-582b-44ab-a77f-eb818942203d.gif)
- `ma` - Select around the object (`va` in Vim, `<alt-a>` in Kakoune)
- `mi` - Select inside the object (`vi` in Vim, `<alt-i>` in Kakoune)
| Key after `mi` or `ma` | Textobject selected |
| --- | --- |
| `w` | Word |
| `W` | WORD |
| `p` | Paragraph |
| `(`, `[`, `'`, etc. | Specified surround pairs |
| `m` | The closest surround pair |
| `f` | Function |
| `c` | Class |
| `a` | Argument/parameter |
| `o` | Comment |
| `t` | Test |
| `g` | Change |
> 💡 `f`, `c`, etc. need a tree-sitter grammar active for the current
document and a special tree-sitter query file to work properly. [Only
some grammars][lang-support] currently have the query file implemented.
Contributions are welcome!
## Navigating using tree-sitter textobjects
Navigating between functions, classes, parameters, and other elements is
possible using tree-sitter and textobject queries. For
example to move to the next function use `]f`, to move to previous
class use `[c`, and so on.
![Tree-sitter-nav-demo][tree-sitter-nav-demo]
For the full reference see the [unimpaired][unimpaired-keybinds] section of the key bind
documentation.
> 💡 This feature relies on tree-sitter textobjects
> and requires the corresponding query file to work properly.
## Moving the selection with syntax-aware motions
`Alt-p`, `Alt-o`, `Alt-i`, and `Alt-n` (or `Alt` and arrow keys) allow you to move the
selection according to its location in the syntax tree. For example, many languages have the
following syntax for function calls:
```js
func(arg1, arg2, arg3);
```
A function call might be parsed by tree-sitter into a tree like the following.
```tsq
(call
function: (identifier) ; func
arguments:
(arguments ; (arg1, arg2, arg3)
(identifier) ; arg1
(identifier) ; arg2
(identifier))) ; arg3
```
Use `:tree-sitter-subtree` to view the syntax tree of the primary selection. In
a more intuitive tree format:
```
┌────┐
│call│
┌─────┴────┴─────┐
│ │
┌─────▼────┐ ┌────▼────┐
│identifier│ │arguments│
│ "func" │ ┌────┴───┬─────┴───┐
└──────────┘ │ │ │
│ │ │
┌─────────▼┐ ┌────▼─────┐ ┌▼─────────┐
│identifier│ │identifier│ │identifier│
│ "arg1" │ │ "arg2" │ │ "arg3" │
└──────────┘ └──────────┘ └──────────┘
```
If you have a selection that wraps `arg1` (see the tree above), and you use
`Alt-n`, it will select the next sibling in the syntax tree: `arg2`.
```js
// before
func([arg1], arg2, arg3)
// after
func(arg1, [arg2], arg3);
```
Similarly, `Alt-o` will expand the selection to the parent node, in this case, the
arguments node.
```js
func[(arg1, arg2, arg3)];
```
There is also some nuanced behavior that prevents you from getting stuck on a
node with no sibling. When using `Alt-p` with a selection on `arg1`, the previous
child node will be selected. In the event that `arg1` does not have a previous
sibling, the selection will move up the syntax tree and select the previous
element. As a result, using `Alt-p` with a selection on `arg1` will move the
selection to the "func" `identifier`.
[lang-support]: ./lang-support.md
[unimpaired-keybinds]: ./keymap.md#unimpaired
[tree-sitter-nav-demo]: https://user-images.githubusercontent.com/23398472/152332550-7dfff043-36a2-4aec-b8f2-77c13eb56d6f.gif

View File

@@ -1,660 +0,0 @@
"use strict";
// Fix back button cache problem
window.onunload = function () { };
// Global variable, shared between modules
function playground_text(playground) {
let code_block = playground.querySelector("code");
if (window.ace && code_block.classList.contains("editable")) {
let editor = window.ace.edit(code_block);
return editor.getValue();
} else {
return code_block.textContent;
}
}
(function codeSnippets() {
function fetch_with_timeout(url, options, timeout = 6000) {
return Promise.race([
fetch(url, options),
new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), timeout))
]);
}
var playgrounds = Array.from(document.querySelectorAll(".playground"));
if (playgrounds.length > 0) {
fetch_with_timeout("https://play.rust-lang.org/meta/crates", {
headers: {
'Content-Type': "application/json",
},
method: 'POST',
mode: 'cors',
})
.then(response => response.json())
.then(response => {
// get list of crates available in the rust playground
let playground_crates = response.crates.map(item => item["id"]);
playgrounds.forEach(block => handle_crate_list_update(block, playground_crates));
});
}
function handle_crate_list_update(playground_block, playground_crates) {
// update the play buttons after receiving the response
update_play_button(playground_block, playground_crates);
// and install on change listener to dynamically update ACE editors
if (window.ace) {
let code_block = playground_block.querySelector("code");
if (code_block.classList.contains("editable")) {
let editor = window.ace.edit(code_block);
editor.addEventListener("change", function (e) {
update_play_button(playground_block, playground_crates);
});
// add Ctrl-Enter command to execute rust code
editor.commands.addCommand({
name: "run",
bindKey: {
win: "Ctrl-Enter",
mac: "Ctrl-Enter"
},
exec: _editor => run_rust_code(playground_block)
});
}
}
}
// updates the visibility of play button based on `no_run` class and
// used crates vs ones available on http://play.rust-lang.org
function update_play_button(pre_block, playground_crates) {
var play_button = pre_block.querySelector(".play-button");
// skip if code is `no_run`
if (pre_block.querySelector('code').classList.contains("no_run")) {
play_button.classList.add("hidden");
return;
}
// get list of `extern crate`'s from snippet
var txt = playground_text(pre_block);
var re = /extern\s+crate\s+([a-zA-Z_0-9]+)\s*;/g;
var snippet_crates = [];
var item;
while (item = re.exec(txt)) {
snippet_crates.push(item[1]);
}
// check if all used crates are available on play.rust-lang.org
var all_available = snippet_crates.every(function (elem) {
return playground_crates.indexOf(elem) > -1;
});
if (all_available) {
play_button.classList.remove("hidden");
} else {
play_button.classList.add("hidden");
}
}
function run_rust_code(code_block) {
var result_block = code_block.querySelector(".result");
if (!result_block) {
result_block = document.createElement('code');
result_block.className = 'result hljs language-bash';
code_block.append(result_block);
}
let text = playground_text(code_block);
let classes = code_block.querySelector('code').classList;
let has_2018 = classes.contains("edition2018");
let edition = has_2018 ? "2018" : "2015";
var params = {
version: "stable",
optimize: "0",
code: text,
edition: edition
};
if (text.indexOf("#![feature") !== -1) {
params.version = "nightly";
}
result_block.innerText = "Running...";
fetch_with_timeout("https://play.rust-lang.org/evaluate.json", {
headers: {
'Content-Type': "application/json",
},
method: 'POST',
mode: 'cors',
body: JSON.stringify(params)
})
.then(response => response.json())
.then(response => result_block.innerText = response.result)
.catch(error => result_block.innerText = "Playground Communication: " + error.message);
}
// Syntax highlighting Configuration
hljs.configure({
tabReplace: ' ', // 4 spaces
languages: [], // Languages used for auto-detection
});
let code_nodes = Array
.from(document.querySelectorAll('code'))
// Don't highlight `inline code` blocks in headers.
.filter(function (node) {return !node.parentElement.classList.contains("header"); });
if (window.ace) {
// language-rust class needs to be removed for editable
// blocks or highlightjs will capture events
Array
.from(document.querySelectorAll('code.editable'))
.forEach(function (block) { block.classList.remove('language-rust'); });
Array
.from(document.querySelectorAll('code:not(.editable)'))
.forEach(function (block) { hljs.highlightBlock(block); });
} else {
code_nodes.forEach(function (block) { hljs.highlightBlock(block); });
}
// Adding the hljs class gives code blocks the color css
// even if highlighting doesn't apply
code_nodes.forEach(function (block) { block.classList.add('hljs'); });
Array.from(document.querySelectorAll("code.language-rust")).forEach(function (block) {
var lines = Array.from(block.querySelectorAll('.boring'));
// If no lines were hidden, return
if (!lines.length) { return; }
block.classList.add("hide-boring");
var buttons = document.createElement('div');
buttons.className = 'buttons';
buttons.innerHTML = "<button class=\"fa fa-eye\" title=\"Show hidden lines\" aria-label=\"Show hidden lines\"></button>";
// add expand button
var pre_block = block.parentNode;
pre_block.insertBefore(buttons, pre_block.firstChild);
pre_block.querySelector('.buttons').addEventListener('click', function (e) {
if (e.target.classList.contains('fa-eye')) {
e.target.classList.remove('fa-eye');
e.target.classList.add('fa-eye-slash');
e.target.title = 'Hide lines';
e.target.setAttribute('aria-label', e.target.title);
block.classList.remove('hide-boring');
} else if (e.target.classList.contains('fa-eye-slash')) {
e.target.classList.remove('fa-eye-slash');
e.target.classList.add('fa-eye');
e.target.title = 'Show hidden lines';
e.target.setAttribute('aria-label', e.target.title);
block.classList.add('hide-boring');
}
});
});
if (window.playground_copyable) {
Array.from(document.querySelectorAll('pre code')).forEach(function (block) {
var pre_block = block.parentNode;
if (!pre_block.classList.contains('playground')) {
var buttons = pre_block.querySelector(".buttons");
if (!buttons) {
buttons = document.createElement('div');
buttons.className = 'buttons';
pre_block.insertBefore(buttons, pre_block.firstChild);
}
var clipButton = document.createElement('button');
clipButton.className = 'fa fa-copy clip-button';
clipButton.title = 'Copy to clipboard';
clipButton.setAttribute('aria-label', clipButton.title);
clipButton.innerHTML = '<i class=\"tooltiptext\"></i>';
buttons.insertBefore(clipButton, buttons.firstChild);
}
});
}
// Process playground code blocks
Array.from(document.querySelectorAll(".playground")).forEach(function (pre_block) {
// Add play button
var buttons = pre_block.querySelector(".buttons");
if (!buttons) {
buttons = document.createElement('div');
buttons.className = 'buttons';
pre_block.insertBefore(buttons, pre_block.firstChild);
}
var runCodeButton = document.createElement('button');
runCodeButton.className = 'fa fa-play play-button';
runCodeButton.hidden = true;
runCodeButton.title = 'Run this code';
runCodeButton.setAttribute('aria-label', runCodeButton.title);
buttons.insertBefore(runCodeButton, buttons.firstChild);
runCodeButton.addEventListener('click', function (e) {
run_rust_code(pre_block);
});
if (window.playground_copyable) {
var copyCodeClipboardButton = document.createElement('button');
copyCodeClipboardButton.className = 'fa fa-copy clip-button';
copyCodeClipboardButton.innerHTML = '<i class="tooltiptext"></i>';
copyCodeClipboardButton.title = 'Copy to clipboard';
copyCodeClipboardButton.setAttribute('aria-label', copyCodeClipboardButton.title);
buttons.insertBefore(copyCodeClipboardButton, buttons.firstChild);
}
let code_block = pre_block.querySelector("code");
if (window.ace && code_block.classList.contains("editable")) {
var undoChangesButton = document.createElement('button');
undoChangesButton.className = 'fa fa-history reset-button';
undoChangesButton.title = 'Undo changes';
undoChangesButton.setAttribute('aria-label', undoChangesButton.title);
buttons.insertBefore(undoChangesButton, buttons.firstChild);
undoChangesButton.addEventListener('click', function () {
let editor = window.ace.edit(code_block);
editor.setValue(editor.originalCode);
editor.clearSelection();
});
}
});
})();
(function themes() {
var html = document.querySelector('html');
var themeToggleButton = document.getElementById('theme-toggle');
var themePopup = document.getElementById('theme-list');
var themeColorMetaTag = document.querySelector('meta[name="theme-color"]');
var stylesheets = {
ayuHighlight: document.querySelector("[href$='ayu-highlight.css']"),
tomorrowNight: document.querySelector("[href$='tomorrow-night.css']"),
highlight: document.querySelector("[href$='highlight.css']"),
};
function showThemes() {
themePopup.style.display = 'block';
themeToggleButton.setAttribute('aria-expanded', true);
themePopup.querySelector("button#" + get_theme()).focus();
}
function hideThemes() {
themePopup.style.display = 'none';
themeToggleButton.setAttribute('aria-expanded', false);
themeToggleButton.focus();
}
function get_theme() {
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch (e) { }
if (theme === null || theme === undefined) {
return default_theme;
} else {
return theme;
}
}
function set_theme(theme, store = true) {
let ace_theme;
if (theme == 'coal' || theme == 'navy') {
stylesheets.ayuHighlight.disabled = true;
stylesheets.tomorrowNight.disabled = false;
stylesheets.highlight.disabled = true;
ace_theme = "ace/theme/tomorrow_night";
} else if (theme == 'ayu') {
stylesheets.ayuHighlight.disabled = false;
stylesheets.tomorrowNight.disabled = true;
stylesheets.highlight.disabled = true;
ace_theme = "ace/theme/tomorrow_night";
} else {
stylesheets.ayuHighlight.disabled = true;
stylesheets.tomorrowNight.disabled = true;
stylesheets.highlight.disabled = false;
ace_theme = "ace/theme/dawn";
}
setTimeout(function () {
themeColorMetaTag.content = getComputedStyle(document.body).backgroundColor;
}, 1);
if (window.ace && window.editors) {
window.editors.forEach(function (editor) {
editor.setTheme(ace_theme);
});
}
var previousTheme = get_theme();
if (store) {
try { localStorage.setItem('mdbook-theme', theme); } catch (e) { }
}
html.classList.remove(previousTheme);
html.classList.add(theme);
}
// Set theme
var theme = get_theme();
set_theme(theme, false);
themeToggleButton.addEventListener('click', function () {
if (themePopup.style.display === 'block') {
hideThemes();
} else {
showThemes();
}
});
themePopup.addEventListener('click', function (e) {
var theme = e.target.id || e.target.parentElement.id;
set_theme(theme);
});
themePopup.addEventListener('focusout', function(e) {
// e.relatedTarget is null in Safari and Firefox on macOS (see workaround below)
if (!!e.relatedTarget && !themeToggleButton.contains(e.relatedTarget) && !themePopup.contains(e.relatedTarget)) {
hideThemes();
}
});
// Should not be needed, but it works around an issue on macOS & iOS: https://github.com/rust-lang/mdBook/issues/628
document.addEventListener('click', function(e) {
if (themePopup.style.display === 'block' && !themeToggleButton.contains(e.target) && !themePopup.contains(e.target)) {
hideThemes();
}
});
document.addEventListener('keydown', function (e) {
if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) { return; }
if (!themePopup.contains(e.target)) { return; }
switch (e.key) {
case 'Escape':
e.preventDefault();
hideThemes();
break;
case 'ArrowUp':
e.preventDefault();
var li = document.activeElement.parentElement;
if (li && li.previousElementSibling) {
li.previousElementSibling.querySelector('button').focus();
}
break;
case 'ArrowDown':
e.preventDefault();
var li = document.activeElement.parentElement;
if (li && li.nextElementSibling) {
li.nextElementSibling.querySelector('button').focus();
}
break;
case 'Home':
e.preventDefault();
themePopup.querySelector('li:first-child button').focus();
break;
case 'End':
e.preventDefault();
themePopup.querySelector('li:last-child button').focus();
break;
}
});
})();
(function sidebar() {
var html = document.querySelector("html");
var sidebar = document.getElementById("sidebar");
var sidebarLinks = document.querySelectorAll('#sidebar a');
var sidebarToggleButton = document.getElementById("sidebar-toggle");
var sidebarResizeHandle = document.getElementById("sidebar-resize-handle");
var firstContact = null;
function showSidebar() {
html.classList.remove('sidebar-hidden')
html.classList.add('sidebar-visible');
Array.from(sidebarLinks).forEach(function (link) {
link.setAttribute('tabIndex', 0);
});
sidebarToggleButton.setAttribute('aria-expanded', true);
sidebar.setAttribute('aria-hidden', false);
try { localStorage.setItem('mdbook-sidebar', 'visible'); } catch (e) { }
}
var sidebarAnchorToggles = document.querySelectorAll('#sidebar a.toggle');
function toggleSection(ev) {
ev.currentTarget.parentElement.classList.toggle('expanded');
}
Array.from(sidebarAnchorToggles).forEach(function (el) {
el.addEventListener('click', toggleSection);
});
function hideSidebar() {
html.classList.remove('sidebar-visible')
html.classList.add('sidebar-hidden');
Array.from(sidebarLinks).forEach(function (link) {
link.setAttribute('tabIndex', -1);
});
sidebarToggleButton.setAttribute('aria-expanded', false);
sidebar.setAttribute('aria-hidden', true);
try { localStorage.setItem('mdbook-sidebar', 'hidden'); } catch (e) { }
}
// Toggle sidebar
sidebarToggleButton.addEventListener('click', function sidebarToggle() {
if (html.classList.contains("sidebar-hidden")) {
var current_width = parseInt(
document.documentElement.style.getPropertyValue('--sidebar-width'), 10);
if (current_width < 150) {
document.documentElement.style.setProperty('--sidebar-width', '150px');
}
showSidebar();
} else if (html.classList.contains("sidebar-visible")) {
hideSidebar();
} else {
if (getComputedStyle(sidebar)['transform'] === 'none') {
hideSidebar();
} else {
showSidebar();
}
}
});
sidebarResizeHandle.addEventListener('mousedown', initResize, false);
function initResize(e) {
window.addEventListener('mousemove', resize, false);
window.addEventListener('mouseup', stopResize, false);
html.classList.add('sidebar-resizing');
}
function resize(e) {
var pos = (e.clientX - sidebar.offsetLeft);
if (pos < 20) {
hideSidebar();
} else {
if (html.classList.contains("sidebar-hidden")) {
showSidebar();
}
pos = Math.min(pos, window.innerWidth - 100);
document.documentElement.style.setProperty('--sidebar-width', pos + 'px');
}
}
//on mouseup remove windows functions mousemove & mouseup
function stopResize(e) {
html.classList.remove('sidebar-resizing');
window.removeEventListener('mousemove', resize, false);
window.removeEventListener('mouseup', stopResize, false);
}
document.addEventListener('touchstart', function (e) {
firstContact = {
x: e.touches[0].clientX,
time: Date.now()
};
}, { passive: true });
document.addEventListener('touchmove', function (e) {
if (!firstContact)
return;
var curX = e.touches[0].clientX;
var xDiff = curX - firstContact.x,
tDiff = Date.now() - firstContact.time;
if (tDiff < 250 && Math.abs(xDiff) >= 150) {
if (xDiff >= 0 && firstContact.x < Math.min(document.body.clientWidth * 0.25, 300))
showSidebar();
else if (xDiff < 0 && curX < 300)
hideSidebar();
firstContact = null;
}
}, { passive: true });
// Scroll sidebar to current active section
var activeSection = document.getElementById("sidebar").querySelector(".active");
if (activeSection) {
// https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView
activeSection.scrollIntoView({ block: 'center' });
}
})();
(function chapterNavigation() {
document.addEventListener('keydown', function (e) {
if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) { return; }
if (window.search && window.search.hasFocus()) { return; }
switch (e.key) {
case 'ArrowRight':
e.preventDefault();
var nextButton = document.querySelector('.nav-chapters.next');
if (nextButton) {
window.location.href = nextButton.href;
}
break;
case 'ArrowLeft':
e.preventDefault();
var previousButton = document.querySelector('.nav-chapters.previous');
if (previousButton) {
window.location.href = previousButton.href;
}
break;
}
});
})();
(function clipboard() {
var clipButtons = document.querySelectorAll('.clip-button');
function hideTooltip(elem) {
elem.firstChild.innerText = "";
elem.className = 'fa fa-copy clip-button';
}
function showTooltip(elem, msg) {
elem.firstChild.innerText = msg;
elem.className = 'fa fa-copy tooltipped';
}
var clipboardSnippets = new ClipboardJS('.clip-button', {
text: function (trigger) {
hideTooltip(trigger);
let playground = trigger.closest("pre");
return playground_text(playground);
}
});
Array.from(clipButtons).forEach(function (clipButton) {
clipButton.addEventListener('mouseout', function (e) {
hideTooltip(e.currentTarget);
});
});
clipboardSnippets.on('success', function (e) {
e.clearSelection();
showTooltip(e.trigger, "Copied!");
});
clipboardSnippets.on('error', function (e) {
showTooltip(e.trigger, "Clipboard error!");
});
})();
(function scrollToTop () {
var menuTitle = document.querySelector('.menu-title');
menuTitle.addEventListener('click', function () {
document.scrollingElement.scrollTo({ top: 0, behavior: 'smooth' });
});
})();
(function controlMenu() {
var menu = document.getElementById('menu-bar');
(function controlPosition() {
var scrollTop = document.scrollingElement.scrollTop;
var prevScrollTop = scrollTop;
var minMenuY = -menu.clientHeight - 50;
// When the script loads, the page can be at any scroll (e.g. if you reforesh it).
menu.style.top = scrollTop + 'px';
// Same as parseInt(menu.style.top.slice(0, -2), but faster
var topCache = menu.style.top.slice(0, -2);
menu.classList.remove('sticky');
var stickyCache = false; // Same as menu.classList.contains('sticky'), but faster
document.addEventListener('scroll', function () {
scrollTop = Math.max(document.scrollingElement.scrollTop, 0);
// `null` means that it doesn't need to be updated
var nextSticky = null;
var nextTop = null;
var scrollDown = scrollTop > prevScrollTop;
var menuPosAbsoluteY = topCache - scrollTop;
if (scrollDown) {
nextSticky = false;
if (menuPosAbsoluteY > 0) {
nextTop = prevScrollTop;
}
} else {
if (menuPosAbsoluteY > 0) {
nextSticky = true;
} else if (menuPosAbsoluteY < minMenuY) {
nextTop = prevScrollTop + minMenuY;
}
}
if (nextSticky === true && stickyCache === false) {
menu.classList.add('sticky');
stickyCache = true;
} else if (nextSticky === false && stickyCache === true) {
menu.classList.remove('sticky');
stickyCache = false;
}
if (nextTop !== null) {
menu.style.top = nextTop + 'px';
topCache = nextTop;
}
prevScrollTop = scrollTop;
}, { passive: true });
})();
(function controlBorder() {
menu.classList.remove('bordered');
document.addEventListener('scroll', function () {
if (menu.offsetTop === 0) {
menu.classList.remove('bordered');
} else {
menu.classList.add('bordered');
}
}, { passive: true });
})();
})();

View File

@@ -1,499 +0,0 @@
/* CSS for UI elements (a.k.a. chrome) */
@import 'variables.css';
::-webkit-scrollbar {
background: var(--bg);
}
::-webkit-scrollbar-thumb {
background: var(--scrollbar);
}
html {
scrollbar-color: var(--scrollbar) var(--bg);
}
#searchresults a,
.content a:link,
a:visited,
a > .hljs {
color: var(--links);
}
.content a:hover {
text-decoration: underline;
}
/* Menu Bar */
#menu-bar,
#menu-bar-hover-placeholder {
z-index: 101;
margin: auto calc(0px - var(--page-padding));
}
#menu-bar {
position: relative;
display: flex;
flex-wrap: wrap;
background-color: var(--bg);
border-bottom-color: var(--bg);
border-bottom-width: 1px;
border-bottom-style: solid;
}
#menu-bar.sticky,
.js #menu-bar-hover-placeholder:hover + #menu-bar,
.js #menu-bar:hover,
.js.sidebar-visible #menu-bar {
position: -webkit-sticky;
position: sticky;
top: 0 !important;
}
#menu-bar-hover-placeholder {
position: sticky;
position: -webkit-sticky;
top: 0;
height: var(--menu-bar-height);
}
#menu-bar.bordered {
border-bottom-color: var(--table-border-color);
}
#menu-bar i, #menu-bar .icon-button {
position: relative;
padding: 0 8px;
z-index: 10;
line-height: var(--menu-bar-height);
cursor: pointer;
transition: color 0.5s;
}
@media only screen and (max-width: 420px) {
#menu-bar i, #menu-bar .icon-button {
padding: 0 5px;
}
}
.icon-button {
border: none;
background: none;
padding: 0;
color: inherit;
}
.icon-button i {
margin: 0;
}
.right-buttons {
margin: 0 15px;
}
.right-buttons a {
text-decoration: none;
}
.left-buttons {
display: flex;
margin: 0 5px;
}
.no-js .left-buttons {
display: none;
}
.menu-title {
display: inline-block;
font-weight: 200;
font-size: 2.4rem;
line-height: var(--menu-bar-height);
text-align: center;
margin: 0;
flex: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.js .menu-title {
cursor: pointer;
}
.menu-bar,
.menu-bar:visited,
.nav-chapters,
.nav-chapters:visited,
.mobile-nav-chapters,
.mobile-nav-chapters:visited,
.menu-bar .icon-button,
.menu-bar a i {
color: var(--icons);
}
.menu-bar i:hover,
.menu-bar .icon-button:hover,
.nav-chapters:hover,
.mobile-nav-chapters i:hover {
color: var(--icons-hover);
}
/* Nav Icons */
.nav-chapters {
font-size: 2.5em;
text-align: center;
text-decoration: none;
position: fixed;
top: 0;
bottom: 0;
margin: 0;
max-width: 150px;
min-width: 90px;
display: flex;
justify-content: center;
align-content: center;
flex-direction: column;
transition: color 0.5s, background-color 0.5s;
}
.nav-chapters:hover {
text-decoration: none;
background-color: var(--theme-hover);
transition: background-color 0.15s, color 0.15s;
}
.nav-wrapper {
margin-top: 50px;
display: none;
}
.mobile-nav-chapters {
font-size: 2.5em;
text-align: center;
text-decoration: none;
width: 90px;
border-radius: 5px;
background-color: var(--sidebar-bg);
}
.previous {
float: left;
}
.next {
float: right;
right: var(--page-padding);
}
@media only screen and (max-width: 1080px) {
.nav-wide-wrapper { display: none; }
.nav-wrapper { display: block; }
}
@media only screen and (max-width: 1380px) {
.sidebar-visible .nav-wide-wrapper { display: none; }
.sidebar-visible .nav-wrapper { display: block; }
}
/* Inline code */
:not(pre) > .hljs {
display: inline;
padding: 0.1em 0.3em;
border-radius: 3px;
}
:not(pre):not(a):not(td):not(p) > .hljs {
color: var(--inline-code-color);
overflow-x: initial;
}
a:hover > .hljs {
text-decoration: underline;
}
pre {
position: relative;
}
pre > .buttons {
position: absolute;
z-index: 100;
right: 5px;
top: 5px;
color: var(--sidebar-fg);
cursor: pointer;
}
pre > .buttons :hover {
color: var(--sidebar-active);
}
pre > .buttons i {
margin-left: 8px;
}
pre > .buttons button {
color: inherit;
background: transparent;
border: none;
cursor: inherit;
}
pre > .result {
margin-top: 10px;
}
/* Search */
#searchresults a {
text-decoration: none;
}
mark {
border-radius: 2px;
padding: 0 3px 1px 3px;
margin: 0 -3px -1px -3px;
background-color: var(--search-mark-bg);
transition: background-color 300ms linear;
cursor: pointer;
}
mark.fade-out {
background-color: rgba(0,0,0,0) !important;
cursor: auto;
}
.searchbar-outer {
margin-left: auto;
margin-right: auto;
max-width: var(--content-max-width);
}
#searchbar {
width: 100%;
margin: 5px auto 0px auto;
padding: 10px 16px;
transition: box-shadow 300ms ease-in-out;
border: 1px solid var(--searchbar-border-color);
border-radius: 3px;
background-color: var(--searchbar-bg);
color: var(--searchbar-fg);
}
#searchbar:focus,
#searchbar.active {
box-shadow: 0 0 3px var(--searchbar-shadow-color);
}
.searchresults-header {
font-weight: bold;
font-size: 1em;
padding: 18px 0 0 5px;
color: var(--searchresults-header-fg);
}
.searchresults-outer {
margin-left: auto;
margin-right: auto;
max-width: var(--content-max-width);
border-bottom: 1px dashed var(--searchresults-border-color);
}
ul#searchresults {
list-style: none;
padding-left: 20px;
}
ul#searchresults li {
margin: 10px 0px;
padding: 2px;
border-radius: 2px;
}
ul#searchresults li.focus {
background-color: var(--searchresults-li-bg);
}
ul#searchresults span.teaser {
display: block;
clear: both;
margin: 5px 0 0 20px;
font-size: 0.8em;
}
ul#searchresults span.teaser em {
font-weight: bold;
font-style: normal;
}
/* Sidebar */
.sidebar {
position: fixed;
left: 0;
top: 0;
bottom: 0;
width: var(--sidebar-width);
font-size: 0.875em;
box-sizing: border-box;
-webkit-overflow-scrolling: touch;
overscroll-behavior-y: contain;
background-color: var(--sidebar-bg);
color: var(--sidebar-fg);
}
.sidebar-resizing {
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
}
.js:not(.sidebar-resizing) .sidebar {
transition: transform 0.3s; /* Animation: slide away */
}
.sidebar code {
line-height: 2em;
}
.sidebar .sidebar-scrollbox {
overflow-y: auto;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.sidebar .sidebar-resize-handle {
position: absolute;
cursor: col-resize;
width: 0;
right: 0;
top: 0;
bottom: 0;
}
.js .sidebar .sidebar-resize-handle {
cursor: col-resize;
width: 5px;
}
.sidebar-hidden .sidebar {
transform: translateX(calc(0px - var(--sidebar-width)));
}
.sidebar::-webkit-scrollbar {
background: var(--sidebar-bg);
}
.sidebar::-webkit-scrollbar-thumb {
background: var(--scrollbar);
}
.sidebar-visible .page-wrapper {
transform: translateX(var(--sidebar-width));
}
@media only screen and (min-width: 620px) {
.sidebar-visible .page-wrapper {
transform: none;
margin-left: var(--sidebar-width);
}
}
.chapter {
list-style: none outside none;
padding-left: 0;
margin: .25rem 0;
}
.chapter ol {
width: 100%;
}
.chapter li {
display: flex;
color: var(--sidebar-non-existent);
}
.chapter li a {
display: block;
text-decoration: none;
color: var(--sidebar-fg);
}
.chapter li a:hover {
color: var(--sidebar-active);
}
.chapter li a.active {
color: var(--sidebar-active);
}
.chapter li > a.toggle {
cursor: pointer;
display: block;
margin-left: auto;
padding: 0 10px;
user-select: none;
opacity: 0.68;
}
.chapter li > a.toggle div {
transition: transform 0.5s;
}
/* collapse the section */
.chapter li:not(.expanded) + li > ol {
display: none;
}
.chapter li.chapter-item {
padding: 1rem 1.5rem;
}
.chapter .section li.chapter-item {
padding: .5rem .5rem 0 .5rem;
}
.chapter li.expanded > a.toggle div {
transform: rotate(90deg);
}
.spacer {
width: 100%;
height: 3px;
margin: 5px 0px;
}
.chapter .spacer {
background-color: var(--sidebar-spacer);
}
@media (-moz-touch-enabled: 1), (pointer: coarse) {
.chapter li a { padding: 5px 0; }
.spacer { margin: 10px 0; }
}
.section {
list-style: none outside none;
padding-left: 2rem;
line-height: 1.9em;
}
/* Theme Menu Popup */
.theme-popup {
position: absolute;
left: 10px;
top: var(--menu-bar-height);
z-index: 1000;
border-radius: 4px;
font-size: 0.7em;
color: var(--fg);
background: var(--theme-popup-bg);
border: 1px solid var(--theme-popup-border);
margin: 0;
padding: 0;
list-style: none;
display: none;
}
.theme-popup .default {
color: var(--icons);
}
.theme-popup .theme {
width: 100%;
border: 0;
margin: 0;
padding: 2px 10px;
line-height: 25px;
white-space: nowrap;
text-align: left;
cursor: pointer;
color: inherit;
background: inherit;
font-size: inherit;
}
.theme-popup .theme:hover {
background-color: var(--theme-hover);
}
.theme-popup .theme:hover:first-child,
.theme-popup .theme:hover:last-child {
border-top-left-radius: inherit;
border-top-right-radius: inherit;
}

View File

@@ -1,233 +0,0 @@
/* Base styles and content styles */
@import 'variables.css';
:root {
/* Browser default font-size is 16px, this way 1 rem = 10px */
font-size: 62.5%;
}
/* TODO: replace with self hosted fonts */
html {
font-family: "Inter", sans-serif;
color: var(--fg);
background-color: var(--bg);
text-size-adjust: none;
}
/* @supports (font-variation-settings: normal) { */
/* html { font-family: 'Inter var', sans-serif; } */
/* } */
body {
margin: 0;
font-size: 1.6rem;
overflow-x: hidden;
}
code {
font-family: "Source Code Pro", Consolas, "Ubuntu Mono", Menlo, "DejaVu Sans Mono", monospace, monospace !important;
font-size: 0.875em; /* please adjust the ace font size accordingly in editor.js */
}
/* Don't change font size in headers. */
h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
font-size: unset;
}
.left { float: left; }
.right { float: right; }
.boring { opacity: 0.6; }
.hide-boring .boring { display: none; }
.hidden { display: none !important; }
h2, h3 { margin-top: 2.5em; }
h4, h5 { margin-top: 2em; }
.header + .header h3,
.header + .header h4,
.header + .header h5 {
margin-top: 1em;
}
h1:target::before,
h2:target::before,
h3:target::before,
h4:target::before,
h5:target::before,
h6:target::before {
display: inline-block;
content: "»";
margin-left: -30px;
width: 30px;
}
/* This is broken on Safari as of version 14, but is fixed
in Safari Technology Preview 117 which I think will be Safari 14.2.
https://bugs.webkit.org/show_bug.cgi?id=218076
*/
:target {
scroll-margin-top: calc(var(--menu-bar-height) + 0.5em);
}
.page {
outline: 0;
padding: 0 var(--page-padding);
margin-top: calc(0px - var(--menu-bar-height)); /* Compensate for the #menu-bar-hover-placeholder */
}
.page-wrapper {
box-sizing: border-box;
}
.js:not(.sidebar-resizing) .page-wrapper {
transition: margin-left 0.3s ease, transform 0.3s ease; /* Animation: slide away */
}
.content {
overflow-y: auto;
padding: 0 15px;
padding-bottom: 50px;
}
.content main {
margin-left: auto;
margin-right: auto;
max-width: var(--content-max-width);
}
/* 2 1.75 1.5 1.25 1 .875 */
.content h1 { font-size: 2em }
.content h2 { font-size: 1.75em }
.content h3 { font-size: 1.5em }
.content h4 { font-size: 1.25em }
.content h5 { font-size: 1em }
.content h6 { font-size: .875em }
.content h1, .content h2, .content h3, .content h4 {
font-weight: 500;
margin-top: 1.275em;
margin-bottom: .875em;
}
.content p, .content ol, .content ul, .content table {
margin-top: 0;
margin-bottom: .875em;
}
.content ul li {
margin-bottom: .25rem;
}
.content ul {
list-style-type: square;
}
.content ul ul, .content ol ul {
margin-bottom: .5rem;
}
.content li p {
margin-bottom: .5em;
}
.content p { line-height: 1.45em; }
.content ol { line-height: 1.45em; }
.content ul { line-height: 1.45em; }
.content a { text-decoration: none; }
.content a:hover { text-decoration: underline; }
.content img { max-width: 100%; }
.content .header:link,
.content .header:visited {
color: var(--fg);
color: var(--heading-fg);
}
.content .header:link,
.content .header:visited:hover {
text-decoration: none;
}
table {
margin: 0 auto;
border-collapse: collapse;
width: 100%;
}
table td {
padding: .75rem;
width: auto;
}
table thead {
background: var(--table-header-bg);
}
table thead td {
font-weight: 700;
border: none;
}
table thead th {
padding: .75rem;
text-align: left;
font-weight: 500;
line-height: 1.5;
width: auto;
}
table thead tr {
border-bottom: 2px var(--table-border-color) solid;
}
table tbody tr {
border-bottom: 1px var(--table-border-line) solid;
}
/* Alternate background colors for rows */
table tbody tr:nth-child(2n) {
/* background: var(--table-alternate-bg); */
}
blockquote {
margin: 1.5rem 0;
padding: 1rem 1.5rem;
color: var(--fg);
opacity: .9;
background-color: var(--quote-bg);
border-left: 4px solid var(--quote-border);
}
blockquote *:last-child {
margin-bottom: 0;
}
:not(.footnote-definition) + .footnote-definition,
.footnote-definition + :not(.footnote-definition) {
margin-top: 2em;
}
.footnote-definition {
font-size: 0.9em;
margin: 0.5em 0;
}
.footnote-definition p {
display: inline;
}
.tooltiptext {
position: absolute;
visibility: hidden;
color: #fff;
background-color: #333;
transform: translateX(-50%); /* Center by moving tooltip 50% of its width left */
left: -8px; /* Half of the width of the icon */
top: -35px;
font-size: 0.8em;
text-align: center;
border-radius: 6px;
padding: 5px 8px;
margin: 5px;
z-index: 1000;
}
.tooltipped .tooltiptext {
visibility: visible;
}
.chapter li.part-title {
color: var(--sidebar-fg);
margin: 5px 0px;
font-weight: bold;
}
.result-no-output {
font-style: italic;
}

View File

@@ -1,54 +0,0 @@
#sidebar,
#menu-bar,
.nav-chapters,
.mobile-nav-chapters {
display: none;
}
#page-wrapper.page-wrapper {
transform: none;
margin-left: 0px;
overflow-y: initial;
}
#content {
max-width: none;
margin: 0;
padding: 0;
}
.page {
overflow-y: initial;
}
code {
background-color: #666666;
border-radius: 5px;
/* Force background to be printed in Chrome */
-webkit-print-color-adjust: exact;
}
pre > .buttons {
z-index: 2;
}
a, a:visited, a:active, a:hover {
color: #4183c4;
text-decoration: none;
}
h1, h2, h3, h4, h5, h6 {
page-break-inside: avoid;
page-break-after: avoid;
}
pre, code {
page-break-inside: avoid;
white-space: pre-wrap;
}
.fa {
display: none !important;
}

View File

@@ -1,411 +0,0 @@
/* Globals */
:root {
--sidebar-width: 300px;
--page-padding: 15px;
--content-max-width: 750px;
--menu-bar-height: 50px;
}
/* Themes */
.ayu {
--bg: hsl(210, 25%, 8%);
--fg: #c5c5c5;
--sidebar-bg: #14191f;
--sidebar-fg: #c8c9db;
--sidebar-non-existent: #5c6773;
--sidebar-active: #ffb454;
--sidebar-spacer: #2d334f;
--scrollbar: var(--sidebar-fg);
--icons: #737480;
--icons-hover: #b7b9cc;
--links: #0096cf;
--inline-code-color: #ffb454;
--theme-popup-bg: #14191f;
--theme-popup-border: #5c6773;
--theme-hover: #191f26;
--quote-bg: hsl(226, 15%, 17%);
--quote-border: hsl(226, 15%, 22%);
--table-border-color: hsl(210, 25%, 13%);
--table-header-bg: hsl(210, 25%, 28%);
--table-alternate-bg: hsl(210, 25%, 11%);
--searchbar-border-color: #848484;
--searchbar-bg: #424242;
--searchbar-fg: #fff;
--searchbar-shadow-color: #d4c89f;
--searchresults-header-fg: #666;
--searchresults-border-color: #888;
--searchresults-li-bg: #252932;
--search-mark-bg: #e3b171;
--hljs-background: #191f26;
--hljs-color: #e6e1cf;
--hljs-quote: #5c6773;
--hljs-variable: #ff7733;
--hljs-type: #ffee99;
--hljs-title: #b8cc52;
--hljs-symbol: #ffb454;
--hljs-selector-tag: #ff7733;
--hljs-selector-tag: #36a3d9;
--hljs-selector-tag: #00568d;
--hljs-selector-tag: #91b362;
--hljs-selector-tag: #d96c75;
}
.coal {
--bg: hsl(200, 7%, 8%);
--fg: #98a3ad;
--sidebar-bg: #292c2f;
--sidebar-fg: #a1adb8;
--sidebar-non-existent: #505254;
--sidebar-active: #3473ad;
--sidebar-spacer: #393939;
--scrollbar: var(--sidebar-fg);
--icons: #43484d;
--icons-hover: #b3c0cc;
--links: #2b79a2;
--inline-code-color: #c5c8c6;
--theme-popup-bg: #141617;
--theme-popup-border: #43484d;
--theme-hover: #1f2124;
--quote-bg: hsl(234, 21%, 18%);
--quote-border: hsl(234, 21%, 23%);
--table-border-color: hsl(200, 7%, 13%);
--table-header-bg: hsl(200, 7%, 28%);
--table-alternate-bg: hsl(200, 7%, 11%);
--searchbar-border-color: #aaa;
--searchbar-bg: #b7b7b7;
--searchbar-fg: #000;
--searchbar-shadow-color: #aaa;
--searchresults-header-fg: #666;
--searchresults-border-color: #98a3ad;
--searchresults-li-bg: #2b2b2f;
--search-mark-bg: #355c7d;
--hljs-background: #969896;
--hljs-color: #cc6666;
--hljs-quote: #de935f;
--hljs-variable: #f0c674;
--hljs-type: #b5bd68;
--hljs-title: #8abeb7;
--hljs-symbol: #81a2be;
--hljs-selector-tag: #b294bb;
--hljs-selector-tag: #1d1f21;
--hljs-selector-tag: #c5c8c6;
--hljs-selector-tag: #718c00;
--hljs-selector-tag: #c82829;
}
.light {
--bg: hsl(0, 0%, 100%);
--fg: hsl(0, 0%, 0%);
--sidebar-bg: #fafafa;
--sidebar-fg: hsl(0, 0%, 0%);
--sidebar-non-existent: #aaaaaa;
--sidebar-active: #1f1fff;
--sidebar-spacer: #f4f4f4;
--scrollbar: #8F8F8F;
--icons: #747474;
--icons-hover: #000000;
--links: #20609f;
--inline-code-color: #301900;
--theme-popup-bg: #fafafa;
--theme-popup-border: #cccccc;
--theme-hover: #e6e6e6;
--quote-bg: hsl(197, 37%, 96%);
--quote-border: hsl(197, 37%, 91%);
--table-border-color: hsl(0, 0%, 95%);
--table-header-bg: hsl(0, 0%, 80%);
--table-alternate-bg: hsl(0, 0%, 97%);
--searchbar-border-color: #aaa;
--searchbar-bg: #fafafa;
--searchbar-fg: #000;
--searchbar-shadow-color: #aaa;
--searchresults-header-fg: #666;
--searchresults-border-color: #888;
--searchresults-li-bg: #e4f2fe;
--search-mark-bg: #a2cff5;
--hljs-background: #f6f7f6;
--hljs-color: #000;
--hljs-quote: #575757;
--hljs-variable: #d70025;
--hljs-type: #b21e00;
--hljs-title: #0030f2;
--hljs-symbol: #008200;
--hljs-selector-tag: #9d00ec;
}
.navy {
--bg: hsl(226, 23%, 11%);
--fg: #bcbdd0;
--sidebar-bg: #282d3f;
--sidebar-fg: #c8c9db;
--sidebar-non-existent: #505274;
--sidebar-active: #2b79a2;
--sidebar-spacer: #2d334f;
--scrollbar: var(--sidebar-fg);
--icons: #737480;
--icons-hover: #b7b9cc;
--links: #2b79a2;
--inline-code-color: #c5c8c6;
--theme-popup-bg: #161923;
--theme-popup-border: #737480;
--theme-hover: #282e40;
--quote-bg: hsl(226, 15%, 17%);
--quote-border: hsl(226, 15%, 22%);
--table-border-color: hsl(226, 23%, 16%);
--table-header-bg: hsl(226, 23%, 31%);
--table-alternate-bg: hsl(226, 23%, 14%);
--searchbar-border-color: #aaa;
--searchbar-bg: #aeaec6;
--searchbar-fg: #000;
--searchbar-shadow-color: #aaa;
--searchresults-header-fg: #5f5f71;
--searchresults-border-color: #5c5c68;
--searchresults-li-bg: #242430;
--search-mark-bg: #a2cff5;
--hljs-background: #969896;
--hljs-color: #cc6666;
--hljs-quote: #de935f;
--hljs-variable: #f0c674;
--hljs-type: #b5bd68;
--hljs-title: #8abeb7;
--hljs-symbol: #81a2be;
--hljs-selector-tag: #b294bb;
--hljs-selector-tag: #1d1f21;
--hljs-selector-tag: #c5c8c6;
--hljs-selector-tag: #718c00;
--hljs-selector-tag: #c82829;
}
.rust {
--bg: hsl(60, 9%, 87%);
--fg: #262625;
--sidebar-bg: #3b2e2a;
--sidebar-fg: #c8c9db;
--sidebar-non-existent: #505254;
--sidebar-active: #e69f67;
--sidebar-spacer: #45373a;
--scrollbar: var(--sidebar-fg);
--icons: #737480;
--icons-hover: #262625;
--links: #2b79a2;
--inline-code-color: #6e6b5e;
--theme-popup-bg: #e1e1db;
--theme-popup-border: #b38f6b;
--theme-hover: #99908a;
--quote-bg: hsl(60, 5%, 75%);
--quote-border: hsl(60, 5%, 70%);
--table-border-color: hsl(60, 9%, 82%);
--table-header-bg: #b3a497;
--table-alternate-bg: hsl(60, 9%, 84%);
--searchbar-border-color: #aaa;
--searchbar-bg: #fafafa;
--searchbar-fg: #000;
--searchbar-shadow-color: #aaa;
--searchresults-header-fg: #666;
--searchresults-border-color: #888;
--searchresults-li-bg: #dec2a2;
--search-mark-bg: #e69f67;
--hljs-background: #f6f7f6;
--hljs-color: #000;
--hljs-quote: #575757;
--hljs-variable: #d70025;
--hljs-type: #b21e00;
--hljs-title: #0030f2;
--hljs-symbol: #008200;
--hljs-selector-tag: #9d00ec;
}
@media (prefers-color-scheme: dark) {
.light.no-js {
--bg: hsl(200, 7%, 8%);
--fg: #98a3ad;
--sidebar-bg: #292c2f;
--sidebar-fg: #a1adb8;
--sidebar-non-existent: #505254;
--sidebar-active: #3473ad;
--sidebar-spacer: #393939;
--scrollbar: var(--sidebar-fg);
--icons: #43484d;
--icons-hover: #b3c0cc;
--links: #2b79a2;
--inline-code-color: #c5c8c6;
--theme-popup-bg: #141617;
--theme-popup-border: #43484d;
--theme-hover: #1f2124;
--quote-bg: hsl(234, 21%, 18%);
--quote-border: hsl(234, 21%, 23%);
--table-border-color: hsl(200, 7%, 13%);
--table-header-bg: hsl(200, 7%, 28%);
--table-alternate-bg: hsl(200, 7%, 11%);
--searchbar-border-color: #aaa;
--searchbar-bg: #b7b7b7;
--searchbar-fg: #000;
--searchbar-shadow-color: #aaa;
--searchresults-header-fg: #666;
--searchresults-border-color: #98a3ad;
--searchresults-li-bg: #2b2b2f;
--search-mark-bg: #355c7d;
}
}
.colibri {
--bg: #3b224c;
--fg: #bcbdd0;
--heading-fg: #fff;
--sidebar-bg: #281733;
--sidebar-fg: #c8c9db;
--sidebar-non-existent: #505274;
--sidebar-active: #a4a0e8;
--sidebar-spacer: #2d334f;
--scrollbar: var(--sidebar-fg);
--icons: #737480;
--icons-hover: #b7b9cc;
/* --links: #a4a0e8; */
--links: #ECCDBA;
--inline-code-color: hsl(48.7, 7.8%, 70%);
--theme-popup-bg: #161923;
--theme-popup-border: #737480;
--theme-hover: rgba(0,0,0, .2);
--quote-bg: #281733;
--quote-border: hsl(226, 15%, 22%);
--table-border-color: hsl(226, 23%, 76%);
--table-header-bg: hsla(226, 23%, 31%, 0);
--table-alternate-bg: hsl(226, 23%, 14%);
--table-border-line: hsla(201deg, 20%, 92%, 0.2);
--searchbar-border-color: #aaa;
--searchbar-bg: #aeaec6;
--searchbar-fg: #000;
--searchbar-shadow-color: #aaa;
--searchresults-header-fg: #5f5f71;
--searchresults-border-color: #5c5c68;
--searchresults-li-bg: #242430;
--search-mark-bg: #acff5;
--hljs-background: #2f1e2e;
--hljs-color: #a39e9b;
--hljs-quote: #8d8687;
--hljs-variable: #ef6155;
--hljs-type: #f99b15;
--hljs-title: #fec418;
--hljs-symbol: #48b685;
--hljs-selector-tag: #815ba4;
}
.colibri {
/*
--bg: #ffffff;
--fg: #452859;
--fg: #5a5977;
--heading-fg: #281733;
--sidebar-bg: #281733;
--sidebar-fg: #c8c9db;
--sidebar-non-existent: #505274;
--sidebar-active: #a4a0e8;
--sidebar-spacer: #2d334f;
--scrollbar: var(--sidebar-fg);
--icons: #737480;
--icons-hover: #b7b9cc;
--links: #6F44F0;
--inline-code-color: #a39e9b;
--theme-popup-bg: #161923;
--theme-popup-border: #737480;
--theme-hover: rgba(0,0,0, .2);
--quote-bg: rgba(0, 0, 0, 0);
--quote-border: hsl(226, 15%, 75%);
--table-border-color: #5a5977;
--table-border-color: hsl(201deg 10% 67%);
--table-header-bg: hsl(0, 0%, 100%);
--table-alternate-bg: hsl(0, 0%, 97%);
--table-border-line: hsl(201deg, 20%, 92%);
--searchbar-border-color: #aaa;
--searchbar-bg: #aeaec6;
--searchbar-fg: #000;
--searchbar-shadow-color: #aaa;
--searchresults-header-fg: #5f5f71;
--searchresults-border-color: #5c5c68;
--searchresults-li-bg: #242430;
--search-mark-bg: #a2cff5;
--hljs-background: #TODO;
--hljs-color: #TODO;
--hljs-quote: #TODO;
--hljs-variable: #TODO;
--hljs-type: #TODO;
--hljs-title: #TODO;
--hljs-symbol: #TODO;
--hljs-selector-tag: #TODO;
*/
}

View File

@@ -1,56 +0,0 @@
pre code.hljs {
display:block;
overflow-x:auto;
padding:1em
}
code.hljs {
padding:3px 5px
}
.hljs {
background: var(--hljs-background);
color: var(--hljs-color);
}
.hljs-comment,
.hljs-quote {
color: var(--hljs-quote)
}
.hljs-link,
.hljs-meta,
.hljs-name,
.hljs-regexp,
.hljs-selector-class,
.hljs-selector-id,
.hljs-tag,
.hljs-template-variable,
.hljs-variable {
color: var(--hljs-variable)
}
.hljs-built_in,
.hljs-deletion,
.hljs-literal,
.hljs-number,
.hljs-params,
.hljs-type {
color: var(--hljs-type)
}
.hljs-attribute,
.hljs-section,
.hljs-title {
color: var(--hljs-title)
}
.hljs-addition,
.hljs-bullet,
.hljs-string,
.hljs-symbol {
color: var(--hljs-symbol)
}
.hljs-keyword,
.hljs-selector-tag {
color: var(--hljs-selector-tag)
}
.hljs-emphasis {
font-style:italic
}
.hljs-strong {
font-weight:700
}

File diff suppressed because one or more lines are too long

View File

@@ -1,11 +1,11 @@
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html lang="{{ language }}" class="sidebar-visible no-js {{ default_theme }}"> <html lang="{{ language }}" class="{{ default_theme }} sidebar-visible" dir="{{ text_direction }}">
<head> <head>
<!-- Book generated using mdBook --> <!-- Book generated using mdBook -->
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>{{ title }}</title> <title>{{ title }}</title>
{{#if is_print }} {{#if is_print }}
<meta name="robots" content="noindex" /> <meta name="robots" content="noindex">
{{/if}} {{/if}}
{{#if base_url}} {{#if base_url}}
<base href="{{ base_url }}"> <base href="{{ base_url }}">
@@ -15,10 +15,9 @@
<!-- Custom HTML head --> <!-- Custom HTML head -->
{{> head}} {{> head}}
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="{{ description }}"> <meta name="description" content="{{ description }}">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" /> <meta name="theme-color" content="#ffffff">
{{#if favicon_svg}} {{#if favicon_svg}}
<link rel="icon" href="{{ path_to_root }}favicon.svg"> <link rel="icon" href="{{ path_to_root }}favicon.svg">
@@ -35,8 +34,6 @@
<!-- Fonts --> <!-- Fonts -->
<link rel="stylesheet" href="{{ path_to_root }}FontAwesome/css/font-awesome.css"> <link rel="stylesheet" href="{{ path_to_root }}FontAwesome/css/font-awesome.css">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@200;400;500;700&display=swap" rel="stylesheet">
{{#if copy_fonts}} {{#if copy_fonts}}
<link rel="stylesheet" href="{{ path_to_root }}fonts/fonts.css"> <link rel="stylesheet" href="{{ path_to_root }}fonts/fonts.css">
{{/if}} {{/if}}
@@ -53,18 +50,21 @@
{{#if mathjax_support}} {{#if mathjax_support}}
<!-- MathJax --> <!-- MathJax -->
<script async type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> <script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
{{/if}} {{/if}}
</head>
<body>
<!-- Provide site root to javascript --> <!-- Provide site root to javascript -->
<script type="text/javascript"> <script>
var path_to_root = "{{ path_to_root }}"; var path_to_root = "{{ path_to_root }}";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "{{ preferred_dark_theme }}" : "{{ default_theme }}"; var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "{{ preferred_dark_theme }}" : "{{ default_theme }}";
</script> </script>
<!-- Start loading toc.js asap -->
<script src="{{ path_to_root }}toc.js"></script>
</head>
<body>
<div id="body-container">
<!-- Work around some values being stored in localStorage wrapped in quotes --> <!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript"> <script>
try { try {
var theme = localStorage.getItem('mdbook-theme'); var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar'); var sidebar = localStorage.getItem('mdbook-sidebar');
@@ -80,34 +80,42 @@
</script> </script>
<!-- Set the theme before any content is loaded, prevents flash --> <!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript"> <script>
var theme; var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { } try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; } if (theme === null || theme === undefined) { theme = default_theme; }
var html = document.querySelector('html'); const html = document.documentElement;
html.classList.remove('no-js')
html.classList.remove('{{ default_theme }}') html.classList.remove('{{ default_theme }}')
html.classList.add(theme); html.classList.add(theme);
html.classList.add('js'); html.classList.add("js");
</script> </script>
<input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
<!-- Hide / unhide sidebar before it is displayed --> <!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript"> <script>
var html = document.querySelector('html'); var sidebar = null;
var sidebar = 'hidden'; var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
if (document.body.clientWidth >= 1080) { if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { } try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible'; sidebar = sidebar || 'visible';
} else {
sidebar = 'hidden';
} }
sidebar_toggle.checked = sidebar === 'visible';
html.classList.remove('sidebar-visible'); html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar); html.classList.add("sidebar-" + sidebar);
</script> </script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents"> <nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox"> <!-- populated by js -->
{{#toc}}{{/toc}} <mdbook-sidebar-scrollbox class="sidebar-scrollbox"></mdbook-sidebar-scrollbox>
<noscript>
<iframe class="sidebar-iframe-outer" src="{{ path_to_root }}toc.html"></iframe>
</noscript>
<div id="sidebar-resize-handle" class="sidebar-resize-handle">
<div class="sidebar-resize-indicator"></div>
</div> </div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav> </nav>
<div id="page-wrapper" class="page-wrapper"> <div id="page-wrapper" class="page-wrapper">
@@ -115,21 +123,21 @@
<div class="page"> <div class="page">
{{> header}} {{> header}}
<div id="menu-bar-hover-placeholder"></div> <div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky bordered"> <div id="menu-bar" class="menu-bar sticky">
<div class="left-buttons"> <div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar"> <label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i> <i class="fa fa-bars"></i>
</button> </label>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list"> <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i> <i class="fa fa-paint-brush"></i>
</button> </button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu"> <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">{{ theme_option "Light" }}</button></li> <li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">{{ theme_option "Rust" }}</button></li> <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">{{ theme_option "Coal" }}</button></li> <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">{{ theme_option "Navy" }}</button></li> <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">{{ theme_option "Ayu" }}</button></li> <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
<li role="none"><button role="menuitem" class="theme" id="colibri">{{ theme_option "Colibri" }}</button></li> <li role="none"><button role="menuitem" class="theme" id="colibri">Colibri</button></li>
</ul> </ul>
{{#if search_enabled}} {{#if search_enabled}}
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar"> <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
@@ -151,13 +159,19 @@
<i id="git-repository-button" class="fa {{git_repository_icon}}"></i> <i id="git-repository-button" class="fa {{git_repository_icon}}"></i>
</a> </a>
{{/if}} {{/if}}
{{#if git_repository_edit_url}}
<a href="{{git_repository_edit_url}}" title="Suggest an edit" aria-label="Suggest an edit">
<i id="git-edit-button" class="fa fa-edit"></i>
</a>
{{/if}}
</div> </div>
</div> </div>
{{#if search_enabled}} {{#if search_enabled}}
<div id="search-wrapper" class="hidden"> <div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer"> <form id="searchbar-outer" class="searchbar-outer">
<input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header"> <input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form> </form>
<div id="searchresults-outer" class="searchresults-outer hidden"> <div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div> <div id="searchresults-header" class="searchresults-header"></div>
@@ -168,7 +182,7 @@
{{/if}} {{/if}}
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM --> <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript"> <script>
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible'); document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible'); document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) { Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
@@ -190,7 +204,7 @@
{{/previous}} {{/previous}}
{{#next}} {{#next}}
<a rel="next" href="{{ path_to_root }}{{link}}" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right"> <a rel="next prefetch" href="{{ path_to_root }}{{link}}" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i> <i class="fa fa-angle-right"></i>
</a> </a>
{{/next}} {{/next}}
@@ -208,7 +222,7 @@
{{/previous}} {{/previous}}
{{#next}} {{#next}}
<a rel="next" href="{{ path_to_root }}{{link}}" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right"> <a rel="next prefetch" href="{{ path_to_root }}{{link}}" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i> <i class="fa fa-angle-right"></i>
</a> </a>
{{/next}} {{/next}}
@@ -216,10 +230,12 @@
</div> </div>
{{#if livereload}} {{#if live_reload_endpoint}}
<!-- Livereload script (if served using the cli tool) --> <!-- Livereload script (if served using the cli tool) -->
<script type="text/javascript"> <script>
var socket = new WebSocket("{{{livereload}}}"); const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
const wsAddress = wsProtocol + "//" + location.host + "/" + "{{{live_reload_endpoint}}}";
const socket = new WebSocket(wsAddress);
socket.onmessage = function (event) { socket.onmessage = function (event) {
if (event.data === "reload") { if (event.data === "reload") {
socket.close(); socket.close();
@@ -235,7 +251,7 @@
{{#if google_analytics}} {{#if google_analytics}}
<!-- Google Analytics Tag --> <!-- Google Analytics Tag -->
<script type="text/javascript"> <script>
var localAddrs = ["localhost", "127.0.0.1", ""]; var localAddrs = ["localhost", "127.0.0.1", ""];
// make sure we don't activate google analytics if the developer is // make sure we don't activate google analytics if the developer is
@@ -253,43 +269,43 @@
{{/if}} {{/if}}
{{#if playground_line_numbers}} {{#if playground_line_numbers}}
<script type="text/javascript"> <script>
window.playground_line_numbers = true; window.playground_line_numbers = true;
</script> </script>
{{/if}} {{/if}}
{{#if playground_copyable}} {{#if playground_copyable}}
<script type="text/javascript"> <script>
window.playground_copyable = true; window.playground_copyable = true;
</script> </script>
{{/if}} {{/if}}
{{#if playground_js}} {{#if playground_js}}
<script src="{{ path_to_root }}ace.js" type="text/javascript" charset="utf-8"></script> <script src="{{ path_to_root }}ace.js"></script>
<script src="{{ path_to_root }}editor.js" type="text/javascript" charset="utf-8"></script> <script src="{{ path_to_root }}editor.js"></script>
<script src="{{ path_to_root }}mode-rust.js" type="text/javascript" charset="utf-8"></script> <script src="{{ path_to_root }}mode-rust.js"></script>
<script src="{{ path_to_root }}theme-dawn.js" type="text/javascript" charset="utf-8"></script> <script src="{{ path_to_root }}theme-dawn.js"></script>
<script src="{{ path_to_root }}theme-tomorrow_night.js" type="text/javascript" charset="utf-8"></script> <script src="{{ path_to_root }}theme-tomorrow_night.js"></script>
{{/if}} {{/if}}
{{#if search_js}} {{#if search_js}}
<script src="{{ path_to_root }}elasticlunr.min.js" type="text/javascript" charset="utf-8"></script> <script src="{{ path_to_root }}elasticlunr.min.js"></script>
<script src="{{ path_to_root }}mark.min.js" type="text/javascript" charset="utf-8"></script> <script src="{{ path_to_root }}mark.min.js"></script>
<script src="{{ path_to_root }}searcher.js" type="text/javascript" charset="utf-8"></script> <script src="{{ path_to_root }}searcher.js"></script>
{{/if}} {{/if}}
<script src="{{ path_to_root }}clipboard.min.js" type="text/javascript" charset="utf-8"></script> <script src="{{ path_to_root }}clipboard.min.js"></script>
<script src="{{ path_to_root }}highlight.js" type="text/javascript" charset="utf-8"></script> <script src="{{ path_to_root }}highlight.js"></script>
<script src="{{ path_to_root }}book.js" type="text/javascript" charset="utf-8"></script> <script src="{{ path_to_root }}book.js"></script>
<!-- Custom JS scripts --> <!-- Custom JS scripts -->
{{#each additional_js}} {{#each additional_js}}
<script type="text/javascript" src="{{ ../path_to_root }}{{this}}"></script> <script src="{{ ../path_to_root }}{{this}}"></script>
{{/each}} {{/each}}
{{#if is_print}} {{#if is_print}}
{{#if mathjax_support}} {{#if mathjax_support}}
<script type="text/javascript"> <script>
window.addEventListener('load', function() { window.addEventListener('load', function() {
MathJax.Hub.Register.StartupHook('End', function() { MathJax.Hub.Register.StartupHook('End', function() {
window.setTimeout(window.print, 100); window.setTimeout(window.print, 100);
@@ -297,7 +313,7 @@
}); });
</script> </script>
{{else}} {{else}}
<script type="text/javascript"> <script>
window.addEventListener('load', function() { window.addEventListener('load', function() {
window.setTimeout(window.print, 100); window.setTimeout(window.print, 100);
}); });
@@ -305,5 +321,6 @@
{{/if}} {{/if}}
{{/if}} {{/if}}
</div>
</body> </body>
</html> </html>

View File

@@ -5,16 +5,27 @@
<project_license>MPL-2.0</project_license> <project_license>MPL-2.0</project_license>
<name>Helix</name> <name>Helix</name>
<summary>A post-modern text editor</summary> <summary>A post-modern text editor</summary>
<summary xml:lang="ar">مُحَرِّرُ نُصُوصٍ سَابِقٌ لِعَهدِه</summary>
<developer id="com.helix_editor">
<name>Blaž Hrastnik</name>
</developer>
<description> <description>
<p> <p>
Helix is a terminal-based text editor inspired by Kakoune / Neovim and written in Rust. Helix is a terminal-based text editor inspired by Kakoune / Neovim and written in Rust.
</p> </p>
<p xml:lang="ar">
مُحَرِّرُ نُصُوصٍ يَعمَلُ فِي الطَّرَفِيَّة، مُستَلهَمٌ مِن Kakoune وَ Neovim وَمَكتُوبٌ بِلُغَةِ رَست البَرمَجِيَّة.
</p>
<ul> <ul>
<li>Vim-like modal editing</li> <li>Vim-like modal editing</li>
<li xml:lang="ar">تَحرِيرٌ وَضعِيٌّ شَبيهٌ بِـVim</li>
<li>Multiple selections</li> <li>Multiple selections</li>
<li xml:lang="ar">تَحدِيدَاتٌ لِلنَّصِ مُتَعَدِّدَة</li>
<li>Built-in language server support</li> <li>Built-in language server support</li>
<li xml:lang="ar">دَعْمٌ مُدمَجٌ لِخَوادِمِ اللُّغَات</li>
<li>Smart, incremental syntax highlighting and code editing via tree-sitter</li> <li>Smart, incremental syntax highlighting and code editing via tree-sitter</li>
<li xml:lang="ar">تَحرِيرُ التَّعلِيمَاتِ البَّرمَجِيَّةِ مَعَ تَمييزٍ لِلتَّركِيبِ النَّحُويِّ بِواسِطَةِ tree-sitter</li>
</ul> </ul>
</description> </description>
@@ -36,6 +47,18 @@
<content_rating type="oars-1.1" /> <content_rating type="oars-1.1" />
<releases> <releases>
<release version="24.07" date="2024-07-14">
<url>https://github.com/helix-editor/helix/releases/tag/24.07</url>
</release>
<release version="24.03" date="2024-03-30">
<url>https://helix-editor.com/news/release-24-03-highlights/</url>
</release>
<release version="23.10" date="2023-10-24">
<url>https://helix-editor.com/news/release-23-10-highlights/</url>
</release>
<release version="23.05" date="2023-05-18">
<url>https://github.com/helix-editor/helix/releases/tag/23.05</url>
</release>
<release version="23.03" date="2023-03-31"> <release version="23.03" date="2023-03-31">
<url>https://helix-editor.com/news/release-23-03-highlights/</url> <url>https://helix-editor.com/news/release-23-03-highlights/</url>
</release> </release>
@@ -53,9 +76,9 @@
</release> </release>
</releases> </releases>
<requires> <recommends>
<control>keyboard</control> <control>keyboard</control>
</requires> </recommends>
<categories> <categories>
<category>Utility</category> <category>Utility</category>

View File

@@ -1,6 +1,7 @@
[Desktop Entry] [Desktop Entry]
Name=Helix Name=Helix
GenericName=Text Editor GenericName=Text Editor
GenericName[ar]=مُحَرِّرُ نُصُوص
GenericName[de]=Texteditor GenericName[de]=Texteditor
GenericName[fr]=Éditeur de texte GenericName[fr]=Éditeur de texte
GenericName[ru]=Текстовый редактор GenericName[ru]=Текстовый редактор
@@ -9,7 +10,7 @@ GenericName[tr]=Metin Düzenleyici
Comment=Edit text files Comment=Edit text files
Comment[af]=Redigeer tekslêers Comment[af]=Redigeer tekslêers
Comment[am]=የጽሑፍ ፋይሎች ያስተካክሉ Comment[am]=የጽሑፍ ፋይሎች ያስተካክሉ
Comment[ar]=حرّر ملفات نصية Comment[ar]=مُحَرِّرُ مِلَفَّاتٍ نَصِّيَّة
Comment[az]=Mətn fayllarını redaktə edin Comment[az]=Mətn fayllarını redaktə edin
Comment[be]=Рэдагаваньне тэкставых файлаў Comment[be]=Рэдагаваньне тэкставых файлаў
Comment[bg]=Редактиране на текстови файлове Comment[bg]=Редактиране на текстови файлове
@@ -79,6 +80,7 @@ Exec=hx %F
Terminal=true Terminal=true
Type=Application Type=Application
Keywords=Text;editor; Keywords=Text;editor;
Keywords[ar]=نص;نصوص;محرر;
Keywords[fr]=Texte;éditeur; Keywords[fr]=Texte;éditeur;
Keywords[ru]=текст;текстовый редактор; Keywords[ru]=текст;текстовый редактор;
Keywords[sr]=Текст;едитор; Keywords[sr]=Текст;едитор;

View File

@@ -2,22 +2,31 @@
# Bash completion script for Helix editor # Bash completion script for Helix editor
_hx() { _hx() {
# $1 command name local cur prev languages
# $2 word being completed COMPREPLY=()
# $3 word preceding cur="${COMP_WORDS[COMP_CWORD]}"
COMPREPLY=() prev="${COMP_WORDS[COMP_CWORD - 1]}"
case "$3" in case "$prev" in
-g | --grammar) -g | --grammar)
COMPREPLY=($(compgen -W "fetch build" -- $2)) COMPREPLY=($(compgen -W 'fetch build' -- "$cur"))
;; return 0
--health) ;;
local languages=$(hx --health |tail -n '+7' |awk '{print $1}' |sed 's/\x1b\[[0-9;]*m//g') --health)
COMPREPLY=($(compgen -W "$languages" -- $2)) languages=$(hx --health | tail -n '+7' | awk '{print $1}' | sed 's/\x1b\[[0-9;]*m//g')
;; COMPREPLY=($(compgen -W """$languages""" -- "$cur"))
*) return 0
COMPREPLY=($(compgen -fd -W "-h --help --tutor -V --version -v -vv -vvv --health -g --grammar --vsplit --hsplit -c --config --log" -- $2)) ;;
;; esac
esac
case "$2" in
-*)
COMPREPLY=($(compgen -W "-h --help --tutor -V --version -v -vv -vvv --health -g --grammar --vsplit --hsplit -c --config --log" -- """$2"""))
return 0
;;
*)
COMPREPLY=($(compgen -fd -- """$2"""))
return 0
;;
esac
} && complete -o filenames -F _hx hx } && complete -o filenames -F _hx hx

View File

@@ -1,15 +1,18 @@
#!/usr/bin/env fish #!/usr/bin/env fish
# Fish completion script for Helix editor # Fish completion script for Helix editor
set -l langs (hx --health |tail -n '+7' |awk '{print $1}' |sed 's/\x1b\[[0-9;]*m//g')
complete -c hx -s h -l help -d "Prints help information" complete -c hx -s h -l help -d "Prints help information"
complete -c hx -l tutor -d "Loads the tutorial" complete -c hx -l tutor -d "Loads the tutorial"
complete -c hx -l health -x -a "$langs" -d "Checks for errors in editor setup" complete -c hx -l health -xa "(__hx_langs_ops)" -d "Checks for errors"
complete -c hx -s g -l grammar -x -a "fetch build" -d "Fetches or builds tree-sitter grammars" complete -c hx -s g -l grammar -x -a "fetch build" -d "Fetch or build tree-sitter grammars"
complete -c hx -s v -o vv -o vvv -d "Increases logging verbosity" complete -c hx -s v -o vv -o vvv -d "Increases logging verbosity"
complete -c hx -s V -l version -d "Prints version information" complete -c hx -s V -l version -d "Prints version information"
complete -c hx -l vsplit -d "Splits all given files vertically into different windows" complete -c hx -l vsplit -d "Splits all given files vertically"
complete -c hx -l hsplit -d "Splits all given files horizontally into different windows" complete -c hx -l hsplit -d "Splits all given files horizontally"
complete -c hx -s c -l config -r -d "Specifies a file to use for completion" complete -c hx -s c -l config -r -d "Specifies a file to use for config"
complete -c hx -l log -r -d "Specifies a file to write log data into" complete -c hx -l log -r -d "Specifies a file to use for logging"
complete -c hx -s w -l working-dir -d "Specify initial working directory" -xa "(__fish_complete_directories)"
function __hx_langs_ops
hx --health languages | tail -n '+2' | string replace -fr '^(\S+) .*' '$1'
end

29
contrib/completion/hx.nu Normal file
View File

@@ -0,0 +1,29 @@
# Completions for Helix: <https://github.com/helix-editor/helix>
#
# NOTE: the `+N` syntax is not supported in Nushell (https://github.com/nushell/nushell/issues/13418)
# so it has not been specified here and will not be proposed in the autocompletion of Nushell.
# The help message won't be overriden though, so it will still be present here
def health_categories [] {
let languages = ^hx --health languages | detect columns | get Language | filter { $in != null }
let completions = [ "all", "clipboard", "languages" ] | append $languages
return $completions
}
def grammar_categories [] { ["fetch", "build"] }
# A post-modern text editor.
export extern hx [
--help(-h), # Prints help information
--tutor, # Loads the tutorial
--health: string@health_categories, # Checks for potential errors in editor setup
--grammar(-g): string@grammar_categories, # Fetches or builds tree-sitter grammars listed in `languages.toml`
--config(-c): glob, # Specifies a file to use for configuration
-v, # Increases logging verbosity each use for up to 3 times
--log: glob, # Specifies a file to use for logging
--version(-V), # Prints version information
--vsplit, # Splits all given files vertically into different windows
--hsplit, # Splits all given files horizontally into different windows
--working-dir(-w): glob, # Specify an initial working directory
...files: glob, # Sets the input file to use, position can also be specified via file[:row[:col]]
]

View File

@@ -14,16 +14,18 @@ _hx() {
"--health[Checks for errors in editor setup]:language:->health" \ "--health[Checks for errors in editor setup]:language:->health" \
"-g[Fetches or builds tree-sitter grammars]:action:->grammar" \ "-g[Fetches or builds tree-sitter grammars]:action:->grammar" \
"--grammar[Fetches or builds tree-sitter grammars]:action:->grammar" \ "--grammar[Fetches or builds tree-sitter grammars]:action:->grammar" \
"--vsplit[Splits all given files vertically into different windows]" \ "--vsplit[Splits all given files vertically]" \
"--hsplit[Splits all given files horizontally into different windows]" \ "--hsplit[Splits all given files horizontally]" \
"-c[Specifies a file to use for configuration]" \ "-c[Specifies a file to use for configuration]" \
"--config[Specifies a file to use for configuration]" \ "--config[Specifies a file to use for configuration]" \
"--log[Specifies a file to write log data into]" \ "-w[Specify initial working directory]" \
"--working-dir[Specify initial working directory]" \
"--log[Specifies a file to use for logging]" \
"*:file:_files" "*:file:_files"
case "$state" in case "$state" in
health) health)
local languages=($(hx --health |tail -n '+7' |awk '{print $1}' |sed 's/\x1b\[[0-9;]*m//g')) local languages=($(hx --health | tail -n '+11' | awk '{print $1}' | sed 's/\x1b\[[0-9;]*m//g;s/[✘✓]//g'))
_values 'language' $languages _values 'language' $languages
;; ;;
grammar) grammar)
@@ -31,4 +33,3 @@ _hx() {
;; ;;
esac esac
} }

BIN
contrib/helix-256p.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

View File

@@ -5,4 +5,4 @@ let
sha256 = "sha256:1qc703yg0babixi6wshn5wm2kgl5y1drcswgszh4xxzbrwkk9sv7"; sha256 = "sha256:1qc703yg0babixi6wshn5wm2kgl5y1drcswgszh4xxzbrwkk9sv7";
}; };
in in
(import compat {src = ./.;}).defaultNix.default (import compat {src = ./.;}).defaultNix

View File

@@ -29,9 +29,15 @@ files, run
cargo xtask docgen cargo xtask docgen
``` ```
inside the project. We use [xtask][xtask] as an ad-hoc task runner and inside the project. We use [xtask][xtask] as an ad-hoc task runner.
thus do not require any dependencies other than `cargo` (You don't have
to `cargo install` anything either). To preview the book itself, install [mdbook][mdbook]. Then, run
```shell
mdbook serve book
```
and visit [http://localhost:3000](http://localhost:3000).
# Testing # Testing
@@ -47,15 +53,26 @@ Existing tests can be used as examples. Helpers can be found in
[helpers.rs][helpers.rs]. The log level can be set with the `HELIX_LOG_LEVEL` [helpers.rs][helpers.rs]. The log level can be set with the `HELIX_LOG_LEVEL`
environment variable, e.g. `HELIX_LOG_LEVEL=debug cargo integration-test`. environment variable, e.g. `HELIX_LOG_LEVEL=debug cargo integration-test`.
Contributors using MacOS might encounter `Too many open files (os error 24)`
failures while running integration tests. This can be resolved by increasing
the default value (e.g. to `10240` from `256`) by running `ulimit -n 10240`.
## Minimum Stable Rust Version (MSRV) Policy ## Minimum Stable Rust Version (MSRV) Policy
Helix follows the MSRV of Firefox. Helix keeps an intentionally low MSRV for the sake of easy building and packaging
The current MSRV and future changes to the MSRV are listed in the [Firefox documentation]. downstream. We follow [Firefox's MSRV policy]. Once Firefox's MSRV increases we
may bump ours as well, but be sure to check that popular distributions like Ubuntu
package the new MSRV version. When increasing the MSRV, update these three places:
[Firefox documentation]: https://firefox-source-docs.mozilla.org/writing-rust-code/update-policy.html * the `workspace.package.rust-version` key in `Cargo.toml` in the repository root
* the `env.MSRV` key at the top of `.github/workflows/build.yml`
* the `toolchain.channel` key in `rust-toolchain.toml`
[Firefox's MSRV policy]: https://firefox-source-docs.mozilla.org/writing-rust-code/update-policy.html
[good-first-issue]: https://github.com/helix-editor/helix/labels/E-easy [good-first-issue]: https://github.com/helix-editor/helix/labels/E-easy
[log-file]: https://github.com/helix-editor/helix/wiki/FAQ#access-the-log-file [log-file]: https://github.com/helix-editor/helix/wiki/FAQ#access-the-log-file
[architecture.md]: ./architecture.md [architecture.md]: ./architecture.md
[docs]: https://docs.helix-editor.com/ [docs]: https://docs.helix-editor.com/
[xtask]: https://github.com/matklad/cargo-xtask [xtask]: https://github.com/matklad/cargo-xtask
[mdbook]: https://rust-lang.github.io/mdBook/guide/installation.html
[helpers.rs]: ../helix-term/tests/test/helpers.rs [helpers.rs]: ../helix-term/tests/test/helpers.rs

View File

@@ -1,13 +1,14 @@
| Crate | Description | | Crate | Description |
| ----------- | ----------- | | ----------- | ----------- |
| helix-core | Core editing primitives, functional. | | helix-core | Core editing primitives, functional. |
| helix-lsp | Language server client | | helix-lsp | Language server client |
| helix-dap | Debug Adapter Protocol (DAP) client | | helix-lsp-types | Language Server Protocol type definitions |
| helix-loader | Functions for building, fetching, and loading external resources | | helix-dap | Debug Adapter Protocol (DAP) client |
| helix-view | UI abstractions for use in backends, imperative shell. | | helix-loader | Functions for building, fetching, and loading external resources |
| helix-term | Terminal UI | | helix-view | UI abstractions for use in backends, imperative shell. |
| helix-tui | TUI primitives, forked from tui-rs, inspired by Cursive | | helix-term | Terminal UI |
| helix-tui | TUI primitives, forked from tui-rs, inspired by Cursive |
This document contains a high-level overview of Helix internals. This document contains a high-level overview of Helix internals.

View File

@@ -1,16 +1,22 @@
## Checklist ## Checklist
Helix releases are versioned in the Calendar Versioning scheme: Helix releases are versioned in the Calendar Versioning scheme:
`YY.0M(.MICRO)`, for example `22.05` for May of 2022. In these instructions `YY.0M(.MICRO)`, for example, `22.05` for May of 2022, or in a patch release,
we'll use `<tag>` as a placeholder for the tag being published. `22.05.1`. In these instructions we'll use `<tag>` as a placeholder for the tag
being published.
* Merge the changelog PR * Merge the PR with the release updates. That branch should:
* Add new `<release>` entry in `contrib/Helix.appdata.xml` with release information according to the [AppStream spec](https://www.freedesktop.org/software/appstream/docs/sect-Metadata-Releases.html) * Update the version:
* Update the `workspace.package.version` key in `Cargo.toml`. Cargo only accepts
SemVer versions so a CalVer version of `22.07` for example must be formatted
as `22.7.0`. Patch/bugfix releases should increment the SemVer patch number. A
patch release for 22.07 would be `22.7.1`.
* Run `cargo check` and commit the resulting change to `Cargo.lock`
* Add changelog notes to `CHANGELOG.md`
* Add new `<release>` entry in `contrib/Helix.appdata.xml` with release information according to the [AppStream spec](https://www.freedesktop.org/software/appstream/docs/sect-Metadata-Releases.html)
* Tag and push * Tag and push
* `git tag -s -m "<tag>" -a <tag> && git push` * Switch to master and pull
* Make sure to switch to master and pull first * `git tag -s -m "<tag>" -a <tag> && git push` (note the `-s` which signs the tag)
* Edit the `VERSION` file and change the date to the next planned release
* Releases are planned to happen every two months, so `22.05` would change to `22.07`
* Wait for the Release CI to finish * Wait for the Release CI to finish
* It will automatically turn the git tag into a GitHub release when it uploads artifacts * It will automatically turn the git tag into a GitHub release when it uploads artifacts
* Edit the new release * Edit the new release
@@ -24,13 +30,13 @@ we'll use `<tag>` as a placeholder for the tag being published.
* Post to reddit * Post to reddit
* [Example post](https://www.reddit.com/r/rust/comments/uzp5ze/helix_editor_2205_released/) * [Example post](https://www.reddit.com/r/rust/comments/uzp5ze/helix_editor_2205_released/)
[homebrew formula]: https://github.com/Homebrew/homebrew-core/blob/master/Formula/helix.rb [homebrew formula]: https://github.com/Homebrew/homebrew-core/blob/master/Formula/h/helix.rb
## Changelog Curation ## Changelog Curation
The changelog is currently created manually by reading through commits in the The changelog is currently created manually by reading through commits in the
log since the last release. GitHub's compare view is a nice way to approach log since the last release. GitHub's compare view is a nice way to approach
this. For example when creating the 22.07 release notes, this compare link this. For example, when creating the 22.07 release notes, this compare link
may be used may be used
``` ```
@@ -57,4 +63,4 @@ versions for convenience:
> release. For the full log, check out the git log. > release. For the full log, check out the git log.
Typically, small changes like dependencies or documentation updates, refactors, Typically, small changes like dependencies or documentation updates, refactors,
or meta changes like GitHub Actions work are left out. or meta changes like GitHub Actions work are left out.

View File

@@ -20,5 +20,5 @@ Vision statements are all well and good, but are also vague and subjective. Her
* **Built-in tools** for working with code bases efficiently. Most projects aren't a single file, and an editor should handle that as a first-class use case. In Helix's case, this means (among other things) a fuzzy-search file navigator and LSP support. * **Built-in tools** for working with code bases efficiently. Most projects aren't a single file, and an editor should handle that as a first-class use case. In Helix's case, this means (among other things) a fuzzy-search file navigator and LSP support.
* **Edit anything** that comes up when coding, within reason. Whether it's a 200 MB XML file, a megabyte of minified javascript on a single line, or Japanese text encoded in ShiftJIS, you should be able to open it and edit it without problems. (Note: this doesn't mean handle every esoteric use case. Sometimes you do just need a specialized tool, and Helix isn't that.) * **Edit anything** that comes up when coding, within reason. Whether it's a 200 MB XML file, a megabyte of minified javascript on a single line, or Japanese text encoded in ShiftJIS, you should be able to open it and edit it without problems. (Note: this doesn't mean handle every esoteric use case. Sometimes you do just need a specialized tool, and Helix isn't that.)
* **Configurable**, within reason. Although the defaults should be good, not everyone will agree on what "good" is. Within the bounds of Helix's core interaction models, it should be reasonably configurable so that it can be "good" for more people. This means, for example, custom key maps among other things. * **Configurable**, within reason. Although the defaults should be good, not everyone will agree on what "good" is. Within the bounds of Helix's core interaction models, it should be reasonably configurable so that it can be "good" for more people. This means, for example, custom key maps among other things.
* **Extensible**, within reason. Although we want Helix to be productive out-of-the-box, it's not practical or desirable to cram every useful feature and use case into the core editor. The basics should be built-in, but you should be able to extend it with additional functionality as needed. Right now we're thinking Wasm-based plugins. * **Extensible**, within reason. Although we want Helix to be productive out-of-the-box, it's not practical or desirable to cram every useful feature and use case into the core editor. The basics should be built-in, but you should be able to extend it with additional functionality as needed.
* **Clean code base.** Sometimes other factors (e.g. significant performance gains, important features, correctness, etc.) will trump strict readability, but we nevertheless want to keep the code base straightforward and easy to understand to the extent we can. * **Clean code base.** Sometimes other factors (e.g. significant performance gains, important features, correctness, etc.) will trump strict readability, but we nevertheless want to keep the code base straightforward and easy to understand to the extent we can.

273
flake.lock generated
View File

@@ -1,13 +1,12 @@
{ {
"nodes": { "nodes": {
"crane": { "crane": {
"flake": false,
"locked": { "locked": {
"lastModified": 1670900067, "lastModified": 1727974419,
"narHash": "sha256-VXVa+KBfukhmWizaiGiHRVX/fuk66P8dgSFfkVN4/MY=", "narHash": "sha256-WD0//20h+2/yPGkO88d2nYbb23WMWYvnRyDQ9Dx4UHg=",
"owner": "ipetkov", "owner": "ipetkov",
"repo": "crane", "repo": "crane",
"rev": "59b31b41a589c0a65e4a1f86b0e5eac68081468b", "rev": "37e4f9f0976cb9281cd3f0c70081e5e0ecaee93f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -16,177 +15,31 @@
"type": "github" "type": "github"
} }
}, },
"dream2nix": {
"inputs": {
"all-cabal-json": [
"nci"
],
"crane": "crane",
"devshell": [
"nci"
],
"drv-parts": "drv-parts",
"flake-compat": "flake-compat",
"flake-parts": [
"nci",
"parts"
],
"flake-utils-pre-commit": [
"nci"
],
"ghc-utils": [
"nci"
],
"gomod2nix": [
"nci"
],
"mach-nix": [
"nci"
],
"nix-pypi-fetcher": [
"nci"
],
"nixpkgs": [
"nci",
"nixpkgs"
],
"nixpkgsV1": "nixpkgsV1",
"poetry2nix": [
"nci"
],
"pre-commit-hooks": [
"nci"
],
"pruned-racket-catalog": [
"nci"
]
},
"locked": {
"lastModified": 1680258209,
"narHash": "sha256-lEo50RXI/17/a9aCIun8Hz62ZJ5JM5RGeTgclIP+Lgc=",
"owner": "nix-community",
"repo": "dream2nix",
"rev": "6f512b5a220fdb26bd3c659f7b55e4f052ec8b35",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "dream2nix",
"type": "github"
}
},
"drv-parts": {
"inputs": {
"flake-compat": [
"nci",
"dream2nix",
"flake-compat"
],
"flake-parts": [
"nci",
"dream2nix",
"flake-parts"
],
"nixpkgs": [
"nci",
"dream2nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1680172861,
"narHash": "sha256-QMyI338xRxaHFDlCXdLCtgelGQX2PdlagZALky4ZXJ8=",
"owner": "davhau",
"repo": "drv-parts",
"rev": "ced8a52f62b0a94244713df2225c05c85b416110",
"type": "github"
},
"original": {
"owner": "davhau",
"repo": "drv-parts",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1673956053,
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-utils": { "flake-utils": {
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"mk-naked-shell": {
"flake": false,
"locked": {
"lastModified": 1676572903,
"narHash": "sha256-oQoDHHUTxNVSURfkFcYLuAK+btjs30T4rbEUtCUyKy8=",
"owner": "yusdacra",
"repo": "mk-naked-shell",
"rev": "aeca9f8aa592f5e8f71f407d081cb26fd30c5a57",
"type": "github"
},
"original": {
"owner": "yusdacra",
"repo": "mk-naked-shell",
"type": "github"
}
},
"nci": {
"inputs": { "inputs": {
"dream2nix": "dream2nix", "systems": "systems"
"mk-naked-shell": "mk-naked-shell",
"nixpkgs": [
"nixpkgs"
],
"parts": "parts",
"rust-overlay": [
"rust-overlay"
]
}, },
"locked": { "locked": {
"lastModified": 1680329418, "lastModified": 1726560853,
"narHash": "sha256-+KN0eQLSZvL1J0kDO8/fxv0UCHTyZCADLmpIfeeiSGo=", "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=",
"owner": "yusdacra", "owner": "numtide",
"repo": "nix-cargo-integration", "repo": "flake-utils",
"rev": "98c1d2ff5155f0fee5d290f6b982cb990839d540", "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "yusdacra", "owner": "numtide",
"repo": "nix-cargo-integration", "repo": "flake-utils",
"type": "github" "type": "github"
} }
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1680213900, "lastModified": 1728018373,
"narHash": "sha256-cIDr5WZIj3EkKyCgj/6j3HBH4Jj1W296z7HTcWj1aMA=", "narHash": "sha256-NOiTvBbRLIOe5F6RbHaAh6++BNjsb149fGZd1T4+KBg=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "e3652e0735fbec227f342712f180f4f21f0594f2", "rev": "bc947f541ae55e999ffdb4013441347d83b00feb",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -196,99 +49,26 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs-lib": {
"locked": {
"dir": "lib",
"lastModified": 1678375444,
"narHash": "sha256-XIgHfGvjFvZQ8hrkfocanCDxMefc/77rXeHvYdzBMc8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "130fa0baaa2b93ec45523fdcde942f6844ee9f6e",
"type": "github"
},
"original": {
"dir": "lib",
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgsV1": {
"locked": {
"lastModified": 1678500271,
"narHash": "sha256-tRBLElf6f02HJGG0ZR7znMNFv/Uf7b2fFInpTHiHaSE=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "5eb98948b66de29f899c7fe27ae112a47964baf8",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-22.11",
"type": "indirect"
}
},
"parts": {
"inputs": {
"nixpkgs-lib": [
"nci",
"nixpkgs"
]
},
"locked": {
"lastModified": 1679737941,
"narHash": "sha256-srSD9CwsVPnUMsIZ7Kt/UegkKUEBcTyU1Rev7mO45S0=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "3502ee99d6dade045bdeaf7b0cd8ec703484c25c",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"parts_2": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1679737941,
"narHash": "sha256-srSD9CwsVPnUMsIZ7Kt/UegkKUEBcTyU1Rev7mO45S0=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "3502ee99d6dade045bdeaf7b0cd8ec703484c25c",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"root": { "root": {
"inputs": { "inputs": {
"nci": "nci", "crane": "crane",
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs",
"parts": "parts_2",
"rust-overlay": "rust-overlay" "rust-overlay": "rust-overlay"
} }
}, },
"rust-overlay": { "rust-overlay": {
"inputs": { "inputs": {
"flake-utils": "flake-utils",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
] ]
}, },
"locked": { "locked": {
"lastModified": 1680315536, "lastModified": 1728268235,
"narHash": "sha256-0AsBuKssJMbcRcw4HJQwJsUHhZxR5+gaf6xPQayhR44=", "narHash": "sha256-lJMFnMO4maJuNO6PQ5fZesrTmglze3UFTTBuKGwR1Nw=",
"owner": "oxalica", "owner": "oxalica",
"repo": "rust-overlay", "repo": "rust-overlay",
"rev": "5c8c151bdd639074a0051325c16df1a64ee23497", "rev": "25685cc2c7054efc31351c172ae77b21814f2d42",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -296,6 +76,21 @@
"repo": "rust-overlay", "repo": "rust-overlay",
"type": "github" "type": "github"
} }
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
} }
}, },
"root": "root", "root": "root",

318
flake.nix
View File

@@ -3,162 +3,186 @@
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils";
rust-overlay = { rust-overlay = {
url = "github:oxalica/rust-overlay"; url = "github:oxalica/rust-overlay";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
nci = { crane.url = "github:ipetkov/crane";
url = "github:yusdacra/nix-cargo-integration";
inputs.nixpkgs.follows = "nixpkgs";
inputs.rust-overlay.follows = "rust-overlay";
};
parts.url = "github:hercules-ci/flake-parts";
}; };
outputs = inp: let outputs = {
mkRootPath = rel: self,
builtins.path { nixpkgs,
path = "${toString ./.}/${rel}"; crane,
name = rel; flake-utils,
rust-overlay,
...
}:
flake-utils.lib.eachDefaultSystem (system: let
pkgs = import nixpkgs {
inherit system;
overlays = [(import rust-overlay)];
}; };
filteredSource = let mkRootPath = rel:
pathsToIgnore = [ builtins.path {
".envrc" path = "${toString ./.}/${rel}";
".ignore" name = rel;
".github"
".gitignore"
"logo.svg"
"logo_dark.svg"
"logo_light.svg"
"rust-toolchain.toml"
"rustfmt.toml"
"runtime"
"screenshot.png"
"book"
"contrib"
"docs"
"README.md"
"CHANGELOG.md"
"shell.nix"
"default.nix"
"grammars.nix"
"flake.nix"
"flake.lock"
];
ignorePaths = path: type: let
inherit (inp.nixpkgs) lib;
# split the nix store path into its components
components = lib.splitString "/" path;
# drop off the `/nix/hash-source` section from the path
relPathComponents = lib.drop 4 components;
# reassemble the path components
relPath = lib.concatStringsSep "/" relPathComponents;
in
lib.all (p: ! (lib.hasPrefix p relPath)) pathsToIgnore;
in
builtins.path {
name = "helix-source";
path = toString ./.;
# filter out unnecessary paths
filter = ignorePaths;
};
in
inp.parts.lib.mkFlake {inputs = inp;} {
imports = [inp.nci.flakeModule];
systems = [
"x86_64-linux"
"x86_64-darwin"
"aarch64-linux"
"aarch64-darwin"
"i686-linux"
];
perSystem = {
config,
pkgs,
lib,
...
}: let
makeOverridableHelix = old: config: let
grammars = pkgs.callPackage ./grammars.nix config;
runtimeDir = pkgs.runCommand "helix-runtime" {} ''
mkdir -p $out
ln -s ${mkRootPath "runtime"}/* $out
rm -r $out/grammars
ln -s ${grammars} $out/grammars
'';
helix-wrapped =
pkgs.runCommand
old.name
{
inherit (old) pname version;
meta = old.meta or {};
passthru =
(old.passthru or {})
// {
unwrapped = old;
};
nativeBuildInputs = [pkgs.makeWrapper];
makeWrapperArgs = config.makeWrapperArgs or [];
}
''
cp -rs --no-preserve=mode,ownership ${old} $out
wrapProgram "$out/bin/hx" ''${makeWrapperArgs[@]} --set HELIX_RUNTIME "${runtimeDir}"
'';
in
helix-wrapped
// {
override = makeOverridableHelix old;
passthru =
helix-wrapped.passthru
// {
wrapper = old: makeOverridableHelix old config;
};
};
stdenv =
if pkgs.stdenv.isLinux
then pkgs.stdenv
else pkgs.clangStdenv;
rustFlagsEnv =
if stdenv.isLinux
then ''$RUSTFLAGS -C link-arg=-fuse-ld=lld -C target-cpu=native -Clink-arg=-Wl,--no-rosegment''
else "$RUSTFLAGS";
in {
nci.projects."helix-project".relPath = "";
nci.crates."helix-term" = {
overrides = {
add-meta.override = _: {meta.mainProgram = "hx";};
add-inputs.overrideAttrs = prev: {
buildInputs = (prev.buildInputs or []) ++ [stdenv.cc.cc.lib];
};
disable-grammar-builds = {
# disable fetching and building of tree-sitter grammars in the helix-term build.rs
HELIX_DISABLE_AUTO_GRAMMAR_BUILD = "1";
};
disable-tests = {checkPhase = ":";};
set-stdenv.override = _: {inherit stdenv;};
set-filtered-src.override = _: {src = filteredSource;};
};
}; };
filteredSource = let
packages.helix-unwrapped = config.nci.outputs."helix-term".packages.release; pathsToIgnore = [
packages.helix-unwrapped-dev = config.nci.outputs."helix-term".packages.dev; ".envrc"
packages.helix = makeOverridableHelix config.packages.helix-unwrapped {}; ".ignore"
packages.helix-dev = makeOverridableHelix config.packages.helix-unwrapped-dev {}; ".github"
packages.default = config.packages.helix; ".gitignore"
"logo_dark.svg"
devShells.default = config.nci.outputs."helix-project".devShell.overrideAttrs (old: { "logo_light.svg"
nativeBuildInputs = "rust-toolchain.toml"
(old.nativeBuildInputs or []) "rustfmt.toml"
++ (with pkgs; [lld_13 cargo-flamegraph rust-analyzer]) "runtime"
++ (lib.optional (stdenv.isx86_64 && stdenv.isLinux) pkgs.cargo-tarpaulin) "screenshot.png"
++ (lib.optional stdenv.isLinux pkgs.lldb) "book"
++ (lib.optional stdenv.isDarwin pkgs.darwin.apple_sdk.frameworks.CoreFoundation); "docs"
shellHook = '' "README.md"
export HELIX_RUNTIME="$PWD/runtime" "CHANGELOG.md"
export RUST_BACKTRACE="1" "shell.nix"
export RUSTFLAGS="${rustFlagsEnv}" "default.nix"
"grammars.nix"
"flake.nix"
"flake.lock"
];
ignorePaths = path: type: let
inherit (nixpkgs) lib;
# split the nix store path into its components
components = lib.splitString "/" path;
# drop off the `/nix/hash-source` section from the path
relPathComponents = lib.drop 4 components;
# reassemble the path components
relPath = lib.concatStringsSep "/" relPathComponents;
in
lib.all (p: ! (lib.hasPrefix p relPath)) pathsToIgnore;
in
builtins.path {
name = "helix-source";
path = toString ./.;
# filter out unnecessary paths
filter = ignorePaths;
};
makeOverridableHelix = old: config: let
grammars = pkgs.callPackage ./grammars.nix config;
runtimeDir = pkgs.runCommand "helix-runtime" {} ''
mkdir -p $out
ln -s ${mkRootPath "runtime"}/* $out
rm -r $out/grammars
ln -s ${grammars} $out/grammars
'';
helix-wrapped =
pkgs.runCommand
old.name
{
inherit (old) pname version;
meta = old.meta or {};
passthru =
(old.passthru or {})
// {
unwrapped = old;
};
nativeBuildInputs = [pkgs.makeWrapper];
makeWrapperArgs = config.makeWrapperArgs or [];
}
''
cp -rs --no-preserve=mode,ownership ${old} $out
wrapProgram "$out/bin/hx" ''${makeWrapperArgs[@]} --set HELIX_RUNTIME "${runtimeDir}"
''; '';
}); in
helix-wrapped
// {
override = makeOverridableHelix old;
passthru =
helix-wrapped.passthru
// {
wrapper = old: makeOverridableHelix old config;
};
};
stdenv =
if pkgs.stdenv.isLinux
then pkgs.stdenv
else pkgs.clangStdenv;
rustFlagsEnv = pkgs.lib.optionalString stdenv.isLinux "-C link-arg=-fuse-ld=lld -C target-cpu=native -Clink-arg=-Wl,--no-rosegment --cfg tokio_unstable";
rustToolchain = pkgs.pkgsBuildHost.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml;
craneLibMSRV = (crane.mkLib pkgs).overrideToolchain rustToolchain;
craneLibStable = (crane.mkLib pkgs).overrideToolchain pkgs.pkgsBuildHost.rust-bin.stable.latest.default;
commonArgs = {
inherit stdenv;
inherit (craneLibMSRV.crateNameFromCargoToml {cargoToml = ./helix-term/Cargo.toml;}) pname;
inherit (craneLibMSRV.crateNameFromCargoToml {cargoToml = ./Cargo.toml;}) version;
src = filteredSource;
# disable fetching and building of tree-sitter grammars in the helix-term build.rs
HELIX_DISABLE_AUTO_GRAMMAR_BUILD = "1";
buildInputs = [stdenv.cc.cc.lib];
nativeBuildInputs = [pkgs.installShellFiles];
# disable tests
doCheck = false;
meta.mainProgram = "hx";
};
cargoArtifacts = craneLibMSRV.buildDepsOnly commonArgs;
in {
packages = {
helix-unwrapped = craneLibStable.buildPackage (commonArgs
// {
cargoArtifacts = craneLibStable.buildDepsOnly commonArgs;
postInstall = ''
mkdir -p $out/share/applications $out/share/icons/hicolor/scalable/apps $out/share/icons/hicolor/256x256/apps
cp contrib/Helix.desktop $out/share/applications
cp logo.svg $out/share/icons/hicolor/scalable/apps/helix.svg
cp contrib/helix.png $out/share/icons/hicolor/256x256/apps
installShellCompletion contrib/completion/hx.{bash,fish,zsh}
'';
});
helix = makeOverridableHelix self.packages.${system}.helix-unwrapped {};
default = self.packages.${system}.helix;
};
checks = {
# Build the crate itself
inherit (self.packages.${system}) helix;
clippy = craneLibMSRV.cargoClippy (commonArgs
// {
inherit cargoArtifacts;
cargoClippyExtraArgs = "--all-targets -- --deny warnings";
});
fmt = craneLibMSRV.cargoFmt commonArgs;
doc = craneLibMSRV.cargoDoc (commonArgs
// {
inherit cargoArtifacts;
});
test = craneLibMSRV.cargoTest (commonArgs
// {
inherit cargoArtifacts;
});
};
devShells.default = pkgs.mkShell {
inputsFrom = builtins.attrValues self.checks.${system};
nativeBuildInputs = with pkgs;
[lld_13 cargo-flamegraph rust-analyzer]
++ (lib.optional (stdenv.isx86_64 && stdenv.isLinux) pkgs.cargo-tarpaulin)
++ (lib.optional stdenv.isLinux pkgs.lldb)
++ (lib.optional stdenv.isDarwin pkgs.darwin.apple_sdk.frameworks.CoreFoundation);
shellHook = ''
export HELIX_RUNTIME="$PWD/runtime"
export RUST_BACKTRACE="1"
export RUSTFLAGS="''${RUSTFLAGS:-""} ${rustFlagsEnv}"
'';
};
})
// {
overlays.default = final: prev: {
inherit (self.packages.${final.system}) helix;
}; };
}; };

View File

@@ -5,6 +5,7 @@
runCommand, runCommand,
yj, yj,
includeGrammarIf ? _: true, includeGrammarIf ? _: true,
grammarOverlays ? [],
... ...
}: let }: let
# HACK: nix < 2.6 has a bug in the toml parser, so we convert to JSON # HACK: nix < 2.6 has a bug in the toml parser, so we convert to JSON
@@ -27,7 +28,17 @@
owner = builtins.elemAt match 0; owner = builtins.elemAt match 0;
repo = builtins.elemAt match 1; repo = builtins.elemAt match 1;
}; };
gitGrammars = builtins.filter isGitGrammar languagesConfig.grammar; # If `use-grammars.only` is set, use only those grammars.
# If `use-grammars.except` is set, use all other grammars.
# Otherwise use all grammars.
useGrammar = grammar:
if languagesConfig?use-grammars.only then
builtins.elem grammar.name languagesConfig.use-grammars.only
else if languagesConfig?use-grammars.except then
!(builtins.elem grammar.name languagesConfig.use-grammars.except)
else true;
grammarsToUse = builtins.filter useGrammar languagesConfig.grammar;
gitGrammars = builtins.filter isGitGrammar grammarsToUse;
buildGrammar = grammar: let buildGrammar = grammar: let
gh = toGitHubFetcher grammar.source.git; gh = toGitHubFetcher grammar.source.git;
sourceGit = builtins.fetchTree { sourceGit = builtins.fetchTree {
@@ -48,22 +59,22 @@
then sourceGitHub then sourceGitHub
else sourceGit; else sourceGit;
in in
stdenv.mkDerivation rec { stdenv.mkDerivation {
# see https://github.com/NixOS/nixpkgs/blob/fbdd1a7c0bc29af5325e0d7dd70e804a972eb465/pkgs/development/tools/parsing/tree-sitter/grammar.nix # see https://github.com/NixOS/nixpkgs/blob/fbdd1a7c0bc29af5325e0d7dd70e804a972eb465/pkgs/development/tools/parsing/tree-sitter/grammar.nix
pname = "helix-tree-sitter-${grammar.name}"; pname = "helix-tree-sitter-${grammar.name}";
version = grammar.source.rev; version = grammar.source.rev;
src = src = source;
if builtins.hasAttr "subpath" grammar.source sourceRoot = if builtins.hasAttr "subpath" grammar.source then
then "${source}/${grammar.source.subpath}" "source/${grammar.source.subpath}"
else source; else
"source";
dontUnpack = true;
dontConfigure = true; dontConfigure = true;
FLAGS = [ FLAGS = [
"-I${src}/src" "-Isrc"
"-g" "-g"
"-O3" "-O3"
"-fPIC" "-fPIC"
@@ -76,13 +87,13 @@
buildPhase = '' buildPhase = ''
runHook preBuild runHook preBuild
if [[ -e "$src/src/scanner.cc" ]]; then if [[ -e src/scanner.cc ]]; then
$CXX -c "$src/src/scanner.cc" -o scanner.o $FLAGS $CXX -c src/scanner.cc -o scanner.o $FLAGS
elif [[ -e "$src/src/scanner.c" ]]; then elif [[ -e src/scanner.c ]]; then
$CC -c "$src/src/scanner.c" -o scanner.o $FLAGS $CC -c src/scanner.c -o scanner.o $FLAGS
fi fi
$CC -c "$src/src/parser.c" -o parser.o $FLAGS $CC -c src/parser.c -o parser.o $FLAGS
$CXX -shared -o $NAME.so *.o $CXX -shared -o $NAME.so *.o
ls -al ls -al
@@ -105,15 +116,17 @@
''; '';
}; };
grammarsToBuild = builtins.filter includeGrammarIf gitGrammars; grammarsToBuild = builtins.filter includeGrammarIf gitGrammars;
builtGrammars = builtGrammars = builtins.map (grammar: {
builtins.map (grammar: { inherit (grammar) name;
inherit (grammar) name; value = buildGrammar grammar;
artifact = buildGrammar grammar; }) grammarsToBuild;
}) extensibleGrammars =
grammarsToBuild; lib.makeExtensible (self: builtins.listToAttrs builtGrammars);
grammarLinks = overlayedGrammars = lib.pipe extensibleGrammars
builtins.map (grammar: "ln -s ${grammar.artifact}/${grammar.name}.so $out/${grammar.name}.so") (builtins.map (overlay: grammar: grammar.extend overlay) grammarOverlays);
builtGrammars; grammarLinks = lib.mapAttrsToList
(name: artifact: "ln -s ${artifact}/${name}.so $out/${name}.so")
(lib.filterAttrs (n: v: lib.isDerivation v) overlayedGrammars);
in in
runCommand "consolidated-helix-grammars" {} '' runCommand "consolidated-helix-grammars" {} ''
mkdir -p $out mkdir -p $out

View File

@@ -1,53 +1,67 @@
[package] [package]
name = "helix-core" name = "helix-core"
version = "0.6.0"
authors = ["Blaž Hrastnik <blaz@mxxn.io>"]
edition = "2021"
license = "MPL-2.0"
description = "Helix editor core editing primitives" description = "Helix editor core editing primitives"
categories = ["editor"]
repository = "https://github.com/helix-editor/helix"
homepage = "https://helix-editor.com"
include = ["src/**/*", "README.md"] include = ["src/**/*", "README.md"]
version.workspace = true
authors.workspace = true
edition.workspace = true
license.workspace = true
rust-version.workspace = true
categories.workspace = true
repository.workspace = true
homepage.workspace = true
[features] [features]
unicode-lines = ["ropey/unicode_lines"] unicode-lines = ["ropey/unicode_lines"]
integration = [] integration = []
[dependencies] [dependencies]
helix-loader = { version = "0.6", path = "../helix-loader" } helix-stdx = { path = "../helix-stdx" }
helix-loader = { path = "../helix-loader" }
helix-parsec = { path = "../helix-parsec" }
ropey = { version = "1.6.0", default-features = false, features = ["simd"] } ropey = { version = "1.6.1", default-features = false, features = ["simd"] }
smallvec = "1.10" smallvec = "1.13"
smartstring = "1.0.1" smartstring = "1.0.1"
unicode-segmentation = "1.10" unicode-segmentation = "1.12"
unicode-width = "0.1" # unicode-width is changing width definitions
unicode-general-category = "0.6" # that both break our logic and disagree with common
# slab = "0.4.2" # width definitions in terminals, we need to replace it.
slotmap = "1.0" # For now lets lock the version to avoid rendering glitches
tree-sitter = "0.20" # when installing without `--locked`
once_cell = "1.17" unicode-width = "=0.1.12"
unicode-general-category = "1.0"
slotmap.workspace = true
tree-sitter.workspace = true
once_cell = "1.20"
arc-swap = "1" arc-swap = "1"
regex = "1" regex = "1"
bitflags = "2.1" bitflags = "2.6"
ahash = "0.8.3" ahash = "0.8.11"
hashbrown = { version = "0.13.2", features = ["raw"] } hashbrown = { version = "0.14.5", features = ["raw"] }
dunce = "1.0" dunce = "1.0"
percent-encoding.workspace = true
log = "0.4" log = "0.4"
anyhow = "1.0"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
toml = "0.7" toml = "0.8"
imara-diff = "0.1.0" imara-diff = "0.1.7"
encoding_rs = "0.8" encoding_rs = "0.8"
chrono = { version = "0.4", default-features = false, features = ["alloc", "std"] } chrono = { version = "0.4", default-features = false, features = ["alloc", "std"] }
etcetera = "0.4" etcetera = "0.8"
textwrap = "0.16.0" textwrap = "0.16.1"
nucleo.workspace = true
parking_lot = "0.12"
globset = "0.4.15"
regex-cursor = "0.1.4"
[dev-dependencies] [dev-dependencies]
quickcheck = { version = "1", default-features = false } quickcheck = { version = "1", default-features = false }
indoc = "2.0.1" indoc = "2.0.5"

View File

@@ -75,9 +75,9 @@ impl From<(&char, &char)> for Pair {
impl AutoPairs { impl AutoPairs {
/// Make a new AutoPairs set with the given pairs and default conditions. /// Make a new AutoPairs set with the given pairs and default conditions.
pub fn new<'a, V: 'a, A>(pairs: V) -> Self pub fn new<'a, V, A>(pairs: V) -> Self
where where
V: IntoIterator<Item = A>, V: IntoIterator<Item = A> + 'a,
A: Into<Pair>, A: Into<Pair>,
{ {
let mut auto_pairs = HashMap::new(); let mut auto_pairs = HashMap::new();

View File

@@ -0,0 +1,69 @@
use crate::Tendril;
// todo: should this be grapheme aware?
pub fn to_pascal_case(text: impl Iterator<Item = char>) -> Tendril {
let mut res = Tendril::new();
to_pascal_case_with(text, &mut res);
res
}
pub fn to_pascal_case_with(text: impl Iterator<Item = char>, buf: &mut Tendril) {
let mut at_word_start = true;
for c in text {
// we don't count _ as a word char here so case conversions work well
if !c.is_alphanumeric() {
at_word_start = true;
continue;
}
if at_word_start {
at_word_start = false;
buf.extend(c.to_uppercase());
} else {
buf.push(c)
}
}
}
pub fn to_upper_case_with(text: impl Iterator<Item = char>, buf: &mut Tendril) {
for c in text {
for c in c.to_uppercase() {
buf.push(c)
}
}
}
pub fn to_lower_case_with(text: impl Iterator<Item = char>, buf: &mut Tendril) {
for c in text {
for c in c.to_lowercase() {
buf.push(c)
}
}
}
pub fn to_camel_case(text: impl Iterator<Item = char>) -> Tendril {
let mut res = Tendril::new();
to_camel_case_with(text, &mut res);
res
}
pub fn to_camel_case_with(mut text: impl Iterator<Item = char>, buf: &mut Tendril) {
for c in &mut text {
if c.is_alphanumeric() {
buf.extend(c.to_lowercase())
}
}
let mut at_word_start = false;
for c in text {
// we don't count _ as a word char here so case conversions work well
if !c.is_alphanumeric() {
at_word_start = true;
continue;
}
if at_word_start {
at_word_start = false;
buf.extend(c.to_uppercase());
} else {
buf.push(c)
}
}
}

View File

@@ -1,11 +1,32 @@
//! This module contains the functionality toggle comments on lines over the selection //! This module contains the functionality toggle comments on lines over the selection
//! using the comment character defined in the user's `languages.toml` //! using the comment character defined in the user's `languages.toml`
use smallvec::SmallVec;
use crate::{ use crate::{
find_first_non_whitespace_char, Change, Rope, RopeSlice, Selection, Tendril, Transaction, syntax::BlockCommentToken, Change, Range, Rope, RopeSlice, Selection, Tendril, Transaction,
}; };
use helix_stdx::rope::RopeSliceExt;
use std::borrow::Cow; use std::borrow::Cow;
pub const DEFAULT_COMMENT_TOKEN: &str = "#";
/// Returns the longest matching comment token of the given line (if it exists).
pub fn get_comment_token<'a, S: AsRef<str>>(
text: RopeSlice,
tokens: &'a [S],
line_num: usize,
) -> Option<&'a str> {
let line = text.line(line_num);
let start = line.first_non_whitespace_char()?;
tokens
.iter()
.map(AsRef::as_ref)
.filter(|token| line.slice(start..).starts_with(token))
.max_by_key(|token| token.len())
}
/// Given text, a comment token, and a set of line indices, returns the following: /// Given text, a comment token, and a set of line indices, returns the following:
/// - Whether the given lines should be considered commented /// - Whether the given lines should be considered commented
/// - If any of the lines are uncommented, all lines are considered as such. /// - If any of the lines are uncommented, all lines are considered as such.
@@ -22,24 +43,23 @@ fn find_line_comment(
) -> (bool, Vec<usize>, usize, usize) { ) -> (bool, Vec<usize>, usize, usize) {
let mut commented = true; let mut commented = true;
let mut to_change = Vec::new(); let mut to_change = Vec::new();
let mut min = usize::MAX; // minimum col for find_first_non_whitespace_char let mut min = usize::MAX; // minimum col for first_non_whitespace_char
let mut margin = 1; let mut margin = 1;
let token_len = token.chars().count(); let token_len = token.chars().count();
for line in lines { for line in lines {
let line_slice = text.line(line); let line_slice = text.line(line);
if let Some(pos) = find_first_non_whitespace_char(line_slice) { if let Some(pos) = line_slice.first_non_whitespace_char() {
let len = line_slice.len_chars(); let len = line_slice.len_chars();
if pos < min { min = std::cmp::min(min, pos);
min = pos;
}
// line can be shorter than pos + token len // line can be shorter than pos + token len
let fragment = Cow::from(line_slice.slice(pos..std::cmp::min(pos + token.len(), len))); let fragment = Cow::from(line_slice.slice(pos..std::cmp::min(pos + token.len(), len)));
// as soon as one of the non-blank lines doesn't have a comment, the whole block is
// considered uncommented.
if fragment != token { if fragment != token {
// as soon as one of the non-blank lines doesn't have a comment, the whole block is
// considered uncommented.
commented = false; commented = false;
} }
@@ -53,6 +73,7 @@ fn find_line_comment(
to_change.push(line); to_change.push(line);
} }
} }
(commented, to_change, min, margin) (commented, to_change, min, margin)
} }
@@ -60,7 +81,7 @@ fn find_line_comment(
pub fn toggle_line_comments(doc: &Rope, selection: &Selection, token: Option<&str>) -> Transaction { pub fn toggle_line_comments(doc: &Rope, selection: &Selection, token: Option<&str>) -> Transaction {
let text = doc.slice(..); let text = doc.slice(..);
let token = token.unwrap_or("//"); let token = token.unwrap_or(DEFAULT_COMMENT_TOKEN);
let comment = Tendril::from(format!("{} ", token)); let comment = Tendril::from(format!("{} ", token));
let mut lines: Vec<usize> = Vec::with_capacity(selection.len()); let mut lines: Vec<usize> = Vec::with_capacity(selection.len());
@@ -94,59 +115,376 @@ pub fn toggle_line_comments(doc: &Rope, selection: &Selection, token: Option<&st
Transaction::change(doc, changes.into_iter()) Transaction::change(doc, changes.into_iter())
} }
#[derive(Debug, PartialEq, Eq)]
pub enum CommentChange {
Commented {
range: Range,
start_pos: usize,
end_pos: usize,
start_margin: bool,
end_margin: bool,
start_token: String,
end_token: String,
},
Uncommented {
range: Range,
start_pos: usize,
end_pos: usize,
start_token: String,
end_token: String,
},
Whitespace {
range: Range,
},
}
pub fn find_block_comments(
tokens: &[BlockCommentToken],
text: RopeSlice,
selection: &Selection,
) -> (bool, Vec<CommentChange>) {
let mut commented = true;
let mut only_whitespace = true;
let mut comment_changes = Vec::with_capacity(selection.len());
let default_tokens = tokens.first().cloned().unwrap_or_default();
let mut start_token = default_tokens.start.clone();
let mut end_token = default_tokens.end.clone();
let mut tokens = tokens.to_vec();
// sort the tokens by length, so longer tokens will match first
tokens.sort_by(|a, b| {
if a.start.len() == b.start.len() {
b.end.len().cmp(&a.end.len())
} else {
b.start.len().cmp(&a.start.len())
}
});
for range in selection {
let selection_slice = range.slice(text);
if let (Some(start_pos), Some(end_pos)) = (
selection_slice.first_non_whitespace_char(),
selection_slice.last_non_whitespace_char(),
) {
let mut line_commented = false;
let mut after_start = 0;
let mut before_end = 0;
let len = (end_pos + 1) - start_pos;
for BlockCommentToken { start, end } in &tokens {
let start_len = start.chars().count();
let end_len = end.chars().count();
after_start = start_pos + start_len;
before_end = end_pos.saturating_sub(end_len);
if len >= start_len + end_len {
let start_fragment = selection_slice.slice(start_pos..after_start);
let end_fragment = selection_slice.slice(before_end + 1..end_pos + 1);
// block commented with these tokens
if start_fragment == start.as_str() && end_fragment == end.as_str() {
start_token = start.to_string();
end_token = end.to_string();
line_commented = true;
break;
}
}
}
if !line_commented {
comment_changes.push(CommentChange::Uncommented {
range: *range,
start_pos,
end_pos,
start_token: default_tokens.start.clone(),
end_token: default_tokens.end.clone(),
});
commented = false;
} else {
comment_changes.push(CommentChange::Commented {
range: *range,
start_pos,
end_pos,
start_margin: selection_slice
.get_char(after_start)
.map_or(false, |c| c == ' '),
end_margin: after_start != before_end
&& selection_slice
.get_char(before_end)
.map_or(false, |c| c == ' '),
start_token: start_token.to_string(),
end_token: end_token.to_string(),
});
}
only_whitespace = false;
} else {
comment_changes.push(CommentChange::Whitespace { range: *range });
}
}
if only_whitespace {
commented = false;
}
(commented, comment_changes)
}
#[must_use]
pub fn create_block_comment_transaction(
doc: &Rope,
selection: &Selection,
commented: bool,
comment_changes: Vec<CommentChange>,
) -> (Transaction, SmallVec<[Range; 1]>) {
let mut changes: Vec<Change> = Vec::with_capacity(selection.len() * 2);
let mut ranges: SmallVec<[Range; 1]> = SmallVec::with_capacity(selection.len());
let mut offs = 0;
for change in comment_changes {
if commented {
if let CommentChange::Commented {
range,
start_pos,
end_pos,
start_token,
end_token,
start_margin,
end_margin,
} = change
{
let from = range.from();
changes.push((
from + start_pos,
from + start_pos + start_token.len() + start_margin as usize,
None,
));
changes.push((
from + end_pos - end_token.len() - end_margin as usize + 1,
from + end_pos + 1,
None,
));
}
} else {
// uncommented so manually map ranges through changes
match change {
CommentChange::Uncommented {
range,
start_pos,
end_pos,
start_token,
end_token,
} => {
let from = range.from();
changes.push((
from + start_pos,
from + start_pos,
Some(Tendril::from(format!("{} ", start_token))),
));
changes.push((
from + end_pos + 1,
from + end_pos + 1,
Some(Tendril::from(format!(" {}", end_token))),
));
let offset = start_token.chars().count() + end_token.chars().count() + 2;
ranges.push(
Range::new(from + offs, from + offs + end_pos + 1 + offset)
.with_direction(range.direction()),
);
offs += offset;
}
CommentChange::Commented { range, .. } | CommentChange::Whitespace { range } => {
ranges.push(Range::new(range.from() + offs, range.to() + offs));
}
}
}
}
(Transaction::change(doc, changes.into_iter()), ranges)
}
#[must_use]
pub fn toggle_block_comments(
doc: &Rope,
selection: &Selection,
tokens: &[BlockCommentToken],
) -> Transaction {
let text = doc.slice(..);
let (commented, comment_changes) = find_block_comments(tokens, text, selection);
let (mut transaction, ranges) =
create_block_comment_transaction(doc, selection, commented, comment_changes);
if !commented {
transaction = transaction.with_selection(Selection::new(ranges, selection.primary_index()));
}
transaction
}
pub fn split_lines_of_selection(text: RopeSlice, selection: &Selection) -> Selection {
let mut ranges = SmallVec::new();
for range in selection.ranges() {
let (line_start, line_end) = range.line_range(text.slice(..));
let mut pos = text.line_to_char(line_start);
for line in text.slice(pos..text.line_to_char(line_end + 1)).lines() {
let start = pos;
pos += line.len_chars();
ranges.push(Range::new(start, pos));
}
}
Selection::new(ranges, 0)
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
mod find_line_comment {
use super::*;
#[test]
fn not_commented() {
// four lines, two space indented, except for line 1 which is blank.
let doc = Rope::from(" 1\n\n 2\n 3");
let text = doc.slice(..);
let res = find_line_comment("//", text, 0..3);
// (commented = false, to_change = [line 0, line 2], min = col 2, margin = 0)
assert_eq!(res, (false, vec![0, 2], 2, 0));
}
#[test]
fn is_commented() {
// three lines where the second line is empty.
let doc = Rope::from("// hello\n\n// there");
let res = find_line_comment("//", doc.slice(..), 0..3);
// (commented = true, to_change = [line 0, line 2], min = col 0, margin = 1)
assert_eq!(res, (true, vec![0, 2], 0, 1));
}
}
// TODO: account for uncommenting with uneven comment indentation
mod toggle_line_comment {
use super::*;
#[test]
fn comment() {
// four lines, two space indented, except for line 1 which is blank.
let mut doc = Rope::from(" 1\n\n 2\n 3");
// select whole document
let selection = Selection::single(0, doc.len_chars() - 1);
let transaction = toggle_line_comments(&doc, &selection, None);
transaction.apply(&mut doc);
assert_eq!(doc, " # 1\n\n # 2\n # 3");
}
#[test]
fn uncomment() {
let mut doc = Rope::from(" # 1\n\n # 2\n # 3");
let mut selection = Selection::single(0, doc.len_chars() - 1);
let transaction = toggle_line_comments(&doc, &selection, None);
transaction.apply(&mut doc);
selection = selection.map(transaction.changes());
assert_eq!(doc, " 1\n\n 2\n 3");
assert!(selection.len() == 1); // to ignore the selection unused warning
}
#[test]
fn uncomment_0_margin_comments() {
let mut doc = Rope::from(" #1\n\n #2\n #3");
let mut selection = Selection::single(0, doc.len_chars() - 1);
let transaction = toggle_line_comments(&doc, &selection, None);
transaction.apply(&mut doc);
selection = selection.map(transaction.changes());
assert_eq!(doc, " 1\n\n 2\n 3");
assert!(selection.len() == 1); // to ignore the selection unused warning
}
#[test]
fn uncomment_0_margin_comments_with_no_space() {
let mut doc = Rope::from("#");
let mut selection = Selection::single(0, doc.len_chars() - 1);
let transaction = toggle_line_comments(&doc, &selection, None);
transaction.apply(&mut doc);
selection = selection.map(transaction.changes());
assert_eq!(doc, "");
assert!(selection.len() == 1); // to ignore the selection unused warning
}
}
#[test] #[test]
fn test_find_line_comment() { fn test_find_block_comments() {
// four lines, two space indented, except for line 1 which is blank. // three lines 5 characters.
let mut doc = Rope::from(" 1\n\n 2\n 3"); let mut doc = Rope::from("1\n2\n3");
// select whole document // select whole document
let mut selection = Selection::single(0, doc.len_chars() - 1); let selection = Selection::single(0, doc.len_chars());
let text = doc.slice(..); let text = doc.slice(..);
let res = find_line_comment("//", text, 0..3); let res = find_block_comments(&[BlockCommentToken::default()], text, &selection);
// (commented = true, to_change = [line 0, line 2], min = col 2, margin = 0)
assert_eq!(res, (false, vec![0, 2], 2, 0)); assert_eq!(
res,
(
false,
vec![CommentChange::Uncommented {
range: Range::new(0, 5),
start_pos: 0,
end_pos: 4,
start_token: "/*".to_string(),
end_token: "*/".to_string(),
}]
)
);
// comment // comment
let transaction = toggle_line_comments(&doc, &selection, None); let transaction = toggle_block_comments(&doc, &selection, &[BlockCommentToken::default()]);
transaction.apply(&mut doc); transaction.apply(&mut doc);
selection = selection.map(transaction.changes());
assert_eq!(doc, " // 1\n\n // 2\n // 3"); assert_eq!(doc, "/* 1\n2\n3 */");
// uncomment // uncomment
let transaction = toggle_line_comments(&doc, &selection, None); let selection = Selection::single(0, doc.len_chars());
let transaction = toggle_block_comments(&doc, &selection, &[BlockCommentToken::default()]);
transaction.apply(&mut doc); transaction.apply(&mut doc);
selection = selection.map(transaction.changes()); assert_eq!(doc, "1\n2\n3");
assert_eq!(doc, " 1\n\n 2\n 3");
assert!(selection.len() == 1); // to ignore the selection unused warning
// 0 margin comments // don't panic when there is just a space in comment
doc = Rope::from(" //1\n\n //2\n //3"); doc = Rope::from("/* */");
// reset the selection. let selection = Selection::single(0, doc.len_chars());
selection = Selection::single(0, doc.len_chars() - 1); let transaction = toggle_block_comments(&doc, &selection, &[BlockCommentToken::default()]);
let transaction = toggle_line_comments(&doc, &selection, None);
transaction.apply(&mut doc); transaction.apply(&mut doc);
selection = selection.map(transaction.changes());
assert_eq!(doc, " 1\n\n 2\n 3");
assert!(selection.len() == 1); // to ignore the selection unused warning
// 0 margin comments, with no space
doc = Rope::from("//");
// reset the selection.
selection = Selection::single(0, doc.len_chars() - 1);
let transaction = toggle_line_comments(&doc, &selection, None);
transaction.apply(&mut doc);
selection = selection.map(transaction.changes());
assert_eq!(doc, ""); assert_eq!(doc, "");
assert!(selection.len() == 1); // to ignore the selection unused warning }
// TODO: account for uncommenting with uneven comment indentation /// Test, if `get_comment_tokens` works, even if the content of the file includes chars, whose
/// byte size unequal the amount of chars
#[test]
fn test_get_comment_with_char_boundaries() {
let rope = Rope::from("··");
let tokens = ["//", "///"];
assert_eq!(
super::get_comment_token(rope.slice(..), tokens.as_slice(), 0),
None
);
}
/// Test for `get_comment_token`.
///
/// Assuming the comment tokens are stored as `["///", "//"]`, `get_comment_token` should still
/// return `///` instead of `//` if the user is in a doc-comment section.
#[test]
fn test_use_longest_comment() {
let text = Rope::from(" /// amogus");
let tokens = ["///", "//"];
assert_eq!(
super::get_comment_token(text.slice(..), tokens.as_slice(), 0),
Some("///")
);
} }
} }

View File

@@ -0,0 +1,12 @@
use std::borrow::Cow;
use crate::Transaction;
#[derive(Debug, PartialEq, Clone)]
pub struct CompletionItem {
pub transaction: Transaction,
pub label: Cow<'static, str>,
pub kind: Cow<'static, str>,
/// Containing Markdown
pub documentation: String,
}

View File

@@ -1,10 +1,45 @@
/// Syntax configuration loader based on built-in languages.toml. use crate::syntax::{Configuration, Loader, LoaderError};
pub fn default_syntax_loader() -> crate::syntax::Configuration {
/// Language configuration based on built-in languages.toml.
pub fn default_lang_config() -> Configuration {
helix_loader::config::default_lang_config() helix_loader::config::default_lang_config()
.try_into() .try_into()
.expect("Could not serialize built-in languages.toml") .expect("Could not deserialize built-in languages.toml")
} }
/// Syntax configuration loader based on user configured languages.toml.
pub fn user_syntax_loader() -> Result<crate::syntax::Configuration, toml::de::Error> { /// Language configuration loader based on built-in languages.toml.
pub fn default_lang_loader() -> Loader {
Loader::new(default_lang_config()).expect("Could not compile loader for default config")
}
#[derive(Debug)]
pub enum LanguageLoaderError {
DeserializeError(toml::de::Error),
LoaderError(LoaderError),
}
impl std::fmt::Display for LanguageLoaderError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::DeserializeError(err) => write!(f, "Failed to parse language config: {err}"),
Self::LoaderError(err) => write!(f, "Failed to compile language config: {err}"),
}
}
}
impl std::error::Error for LanguageLoaderError {}
/// Language configuration based on user configured languages.toml.
pub fn user_lang_config() -> Result<Configuration, toml::de::Error> {
helix_loader::config::user_lang_config()?.try_into() helix_loader::config::user_lang_config()?.try_into()
} }
/// Language configuration loader based on user configured languages.toml.
pub fn user_lang_loader() -> Result<Loader, LanguageLoaderError> {
let config: Configuration = helix_loader::config::user_lang_config()
.map_err(LanguageLoaderError::DeserializeError)?
.try_into()
.map_err(LanguageLoaderError::DeserializeError)?;
Loader::new(config).map_err(LanguageLoaderError::LoaderError)
}

View File

@@ -1,8 +1,12 @@
//! LSP diagnostic utility types. //! LSP diagnostic utility types.
use std::fmt;
pub use helix_stdx::range::Range;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
/// Describes the severity level of a [`Diagnostic`]. /// Describes the severity level of a [`Diagnostic`].
#[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Deserialize, Serialize)] #[derive(Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Severity { pub enum Severity {
Hint, Hint,
Info, Info,
@@ -16,13 +20,6 @@ impl Default for Severity {
} }
} }
/// A range of `char`s within the text.
#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq)]
pub struct Range {
pub start: usize,
pub end: usize,
}
#[derive(Debug, Eq, Hash, PartialEq, Clone, Deserialize, Serialize)] #[derive(Debug, Eq, Hash, PartialEq, Clone, Deserialize, Serialize)]
pub enum NumberOrString { pub enum NumberOrString {
Number(i32), Number(i32),
@@ -39,11 +36,40 @@ pub enum DiagnosticTag {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Diagnostic { pub struct Diagnostic {
pub range: Range, pub range: Range,
// whether this diagnostic ends at the end of(or inside) a word
pub ends_at_word: bool,
pub starts_at_word: bool,
pub zero_width: bool,
pub line: usize, pub line: usize,
pub message: String, pub message: String,
pub severity: Option<Severity>, pub severity: Option<Severity>,
pub code: Option<NumberOrString>, pub code: Option<NumberOrString>,
pub provider: DiagnosticProvider,
pub tags: Vec<DiagnosticTag>, pub tags: Vec<DiagnosticTag>,
pub source: Option<String>, pub source: Option<String>,
pub data: Option<serde_json::Value>, pub data: Option<serde_json::Value>,
} }
// TODO turn this into an enum + feature flag when lsp becomes optional
pub type DiagnosticProvider = LanguageServerId;
// while I would prefer having this in helix-lsp that necessitates a bunch of
// conversions I would rather not add. I think its fine since this just a very
// trivial newtype wrapper and we would need something similar once we define
// completions in core
slotmap::new_key_type! {
pub struct LanguageServerId;
}
impl fmt::Display for LanguageServerId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self.0)
}
}
impl Diagnostic {
#[inline]
pub fn severity(&self) -> Severity {
self.severity.unwrap_or(Severity::Warning)
}
}

View File

@@ -10,8 +10,9 @@
//! called a "block" and the caller must advance it as needed. //! called a "block" and the caller must advance it as needed.
use std::borrow::Cow; use std::borrow::Cow;
use std::cmp::Ordering;
use std::fmt::Debug; use std::fmt::Debug;
use std::mem::{replace, take}; use std::mem::replace;
#[cfg(test)] #[cfg(test)]
mod test; mod test;
@@ -37,52 +38,104 @@ pub enum GraphemeSource {
}, },
} }
#[derive(Debug, Clone)] impl GraphemeSource {
pub struct FormattedGrapheme<'a> { /// Returns whether this grapheme is virtual inline text
pub grapheme: Grapheme<'a>, pub fn is_virtual(self) -> bool {
pub source: GraphemeSource, matches!(self, GraphemeSource::VirtualText { .. })
}
pub fn is_eof(self) -> bool {
// all doc chars except the EOF char have non-zero codepoints
matches!(self, GraphemeSource::Document { codepoints: 0 })
}
pub fn doc_chars(self) -> usize {
match self {
GraphemeSource::Document { codepoints } => codepoints as usize,
GraphemeSource::VirtualText { .. } => 0,
}
}
} }
impl<'a> FormattedGrapheme<'a> { #[derive(Debug, Clone)]
pub fn new( pub struct FormattedGrapheme<'a> {
pub raw: Grapheme<'a>,
pub source: GraphemeSource,
pub visual_pos: Position,
/// Document line at the start of the grapheme
pub line_idx: usize,
/// Document char position at the start of the grapheme
pub char_idx: usize,
}
impl FormattedGrapheme<'_> {
pub fn is_virtual(&self) -> bool {
self.source.is_virtual()
}
pub fn doc_chars(&self) -> usize {
self.source.doc_chars()
}
pub fn is_whitespace(&self) -> bool {
self.raw.is_whitespace()
}
pub fn width(&self) -> usize {
self.raw.width()
}
pub fn is_word_boundary(&self) -> bool {
self.raw.is_word_boundary()
}
}
#[derive(Debug, Clone)]
struct GraphemeWithSource<'a> {
grapheme: Grapheme<'a>,
source: GraphemeSource,
}
impl<'a> GraphemeWithSource<'a> {
fn new(
g: GraphemeStr<'a>, g: GraphemeStr<'a>,
visual_x: usize, visual_x: usize,
tab_width: u16, tab_width: u16,
source: GraphemeSource, source: GraphemeSource,
) -> FormattedGrapheme<'a> { ) -> GraphemeWithSource<'a> {
FormattedGrapheme { GraphemeWithSource {
grapheme: Grapheme::new(g, visual_x, tab_width), grapheme: Grapheme::new(g, visual_x, tab_width),
source, source,
} }
} }
/// Returns whether this grapheme is virtual inline text fn placeholder() -> Self {
pub fn is_virtual(&self) -> bool { GraphemeWithSource {
matches!(self.source, GraphemeSource::VirtualText { .. })
}
pub fn placeholder() -> Self {
FormattedGrapheme {
grapheme: Grapheme::Other { g: " ".into() }, grapheme: Grapheme::Other { g: " ".into() },
source: GraphemeSource::Document { codepoints: 0 }, source: GraphemeSource::Document { codepoints: 0 },
} }
} }
pub fn doc_chars(&self) -> usize { fn doc_chars(&self) -> usize {
match self.source { self.source.doc_chars()
GraphemeSource::Document { codepoints } => codepoints as usize,
GraphemeSource::VirtualText { .. } => 0,
}
} }
pub fn is_whitespace(&self) -> bool { fn is_whitespace(&self) -> bool {
self.grapheme.is_whitespace() self.grapheme.is_whitespace()
} }
pub fn width(&self) -> usize { fn is_newline(&self) -> bool {
matches!(self.grapheme, Grapheme::Newline)
}
fn is_eof(&self) -> bool {
self.source.is_eof()
}
fn width(&self) -> usize {
self.grapheme.width() self.grapheme.width()
} }
pub fn is_word_boundary(&self) -> bool { fn is_word_boundary(&self) -> bool {
self.grapheme.is_word_boundary() self.grapheme.is_word_boundary()
} }
} }
@@ -96,6 +149,7 @@ pub struct TextFormat {
pub wrap_indicator: Box<str>, pub wrap_indicator: Box<str>,
pub wrap_indicator_highlight: Option<Highlight>, pub wrap_indicator_highlight: Option<Highlight>,
pub viewport_width: u16, pub viewport_width: u16,
pub soft_wrap_at_text_width: bool,
} }
// test implementation is basically only used for testing or when softwrap is always disabled // test implementation is basically only used for testing or when softwrap is always disabled
@@ -109,6 +163,7 @@ impl Default for TextFormat {
wrap_indicator: Box::from(" "), wrap_indicator: Box::from(" "),
viewport_width: 17, viewport_width: 17,
wrap_indicator_highlight: None, wrap_indicator_highlight: None,
soft_wrap_at_text_width: false,
} }
} }
} }
@@ -116,7 +171,7 @@ impl Default for TextFormat {
#[derive(Debug)] #[derive(Debug)]
pub struct DocumentFormatter<'t> { pub struct DocumentFormatter<'t> {
text_fmt: &'t TextFormat, text_fmt: &'t TextFormat,
annotations: &'t TextAnnotations, annotations: &'t TextAnnotations<'t>,
/// The visual position at the end of the last yielded word boundary /// The visual position at the end of the last yielded word boundary
visual_pos: Position, visual_pos: Position,
@@ -127,10 +182,7 @@ pub struct DocumentFormatter<'t> {
line_pos: usize, line_pos: usize,
exhausted: bool, exhausted: bool,
/// Line breaks to be reserved for virtual text inline_annotation_graphemes: Option<(Graphemes<'t>, Option<Highlight>)>,
/// at the next line break
virtual_lines: usize,
inline_anntoation_graphemes: Option<(Graphemes<'t>, Option<Highlight>)>,
// softwrap specific // softwrap specific
/// The indentation of the current line /// The indentation of the current line
@@ -139,9 +191,9 @@ pub struct DocumentFormatter<'t> {
indent_level: Option<usize>, indent_level: Option<usize>,
/// In case a long word needs to be split a single grapheme might need to be wrapped /// In case a long word needs to be split a single grapheme might need to be wrapped
/// while the rest of the word stays on the same line /// while the rest of the word stays on the same line
peeked_grapheme: Option<(FormattedGrapheme<'t>, usize)>, peeked_grapheme: Option<GraphemeWithSource<'t>>,
/// A first-in first-out (fifo) buffer for the Graphemes of any given word /// A first-in first-out (fifo) buffer for the Graphemes of any given word
word_buf: Vec<FormattedGrapheme<'t>>, word_buf: Vec<GraphemeWithSource<'t>>,
/// The index of the next grapheme that will be yielded from the `word_buf` /// The index of the next grapheme that will be yielded from the `word_buf`
word_i: usize, word_i: usize,
} }
@@ -157,35 +209,35 @@ impl<'t> DocumentFormatter<'t> {
text_fmt: &'t TextFormat, text_fmt: &'t TextFormat,
annotations: &'t TextAnnotations, annotations: &'t TextAnnotations,
char_idx: usize, char_idx: usize,
) -> (Self, usize) { ) -> Self {
// TODO divide long lines into blocks to avoid bad performance for long lines // TODO divide long lines into blocks to avoid bad performance for long lines
let block_line_idx = text.char_to_line(char_idx.min(text.len_chars())); let block_line_idx = text.char_to_line(char_idx.min(text.len_chars()));
let block_char_idx = text.line_to_char(block_line_idx); let block_char_idx = text.line_to_char(block_line_idx);
annotations.reset_pos(block_char_idx); annotations.reset_pos(block_char_idx);
(
DocumentFormatter { DocumentFormatter {
text_fmt, text_fmt,
annotations, annotations,
visual_pos: Position { row: 0, col: 0 }, visual_pos: Position { row: 0, col: 0 },
graphemes: RopeGraphemes::new(text.slice(block_char_idx..)), graphemes: RopeGraphemes::new(text.slice(block_char_idx..)),
char_pos: block_char_idx, char_pos: block_char_idx,
exhausted: false, exhausted: false,
virtual_lines: 0, indent_level: None,
indent_level: None, peeked_grapheme: None,
peeked_grapheme: None, word_buf: Vec::with_capacity(64),
word_buf: Vec::with_capacity(64), word_i: 0,
word_i: 0, line_pos: block_line_idx,
line_pos: block_line_idx, inline_annotation_graphemes: None,
inline_anntoation_graphemes: None, }
},
block_char_idx,
)
} }
fn next_inline_annotation_grapheme(&mut self) -> Option<(&'t str, Option<Highlight>)> { fn next_inline_annotation_grapheme(
&mut self,
char_pos: usize,
) -> Option<(&'t str, Option<Highlight>)> {
loop { loop {
if let Some(&mut (ref mut annotation, highlight)) = if let Some(&mut (ref mut annotation, highlight)) =
self.inline_anntoation_graphemes.as_mut() self.inline_annotation_graphemes.as_mut()
{ {
if let Some(grapheme) = annotation.next() { if let Some(grapheme) = annotation.next() {
return Some((grapheme, highlight)); return Some((grapheme, highlight));
@@ -193,9 +245,9 @@ impl<'t> DocumentFormatter<'t> {
} }
if let Some((annotation, highlight)) = if let Some((annotation, highlight)) =
self.annotations.next_inline_annotation_at(self.char_pos) self.annotations.next_inline_annotation_at(char_pos)
{ {
self.inline_anntoation_graphemes = Some(( self.inline_annotation_graphemes = Some((
UnicodeSegmentation::graphemes(&*annotation.text, true), UnicodeSegmentation::graphemes(&*annotation.text, true),
highlight, highlight,
)) ))
@@ -205,21 +257,19 @@ impl<'t> DocumentFormatter<'t> {
} }
} }
fn advance_grapheme(&mut self, col: usize) -> Option<FormattedGrapheme<'t>> { fn advance_grapheme(&mut self, col: usize, char_pos: usize) -> Option<GraphemeWithSource<'t>> {
let (grapheme, source) = let (grapheme, source) =
if let Some((grapheme, highlight)) = self.next_inline_annotation_grapheme() { if let Some((grapheme, highlight)) = self.next_inline_annotation_grapheme(char_pos) {
(grapheme.into(), GraphemeSource::VirtualText { highlight }) (grapheme.into(), GraphemeSource::VirtualText { highlight })
} else if let Some(grapheme) = self.graphemes.next() { } else if let Some(grapheme) = self.graphemes.next() {
self.virtual_lines += self.annotations.annotation_lines_at(self.char_pos);
let codepoints = grapheme.len_chars() as u32; let codepoints = grapheme.len_chars() as u32;
let overlay = self.annotations.overlay_at(self.char_pos); let overlay = self.annotations.overlay_at(char_pos);
let grapheme = match overlay { let grapheme = match overlay {
Some((overlay, _)) => overlay.grapheme.as_str().into(), Some((overlay, _)) => overlay.grapheme.as_str().into(),
None => Cow::from(grapheme).into(), None => Cow::from(grapheme).into(),
}; };
self.char_pos += codepoints as usize;
(grapheme, GraphemeSource::Document { codepoints }) (grapheme, GraphemeSource::Document { codepoints })
} else { } else {
if self.exhausted { if self.exhausted {
@@ -228,19 +278,19 @@ impl<'t> DocumentFormatter<'t> {
self.exhausted = true; self.exhausted = true;
// EOF grapheme is required for rendering // EOF grapheme is required for rendering
// and correct position computations // and correct position computations
return Some(FormattedGrapheme { return Some(GraphemeWithSource {
grapheme: Grapheme::Other { g: " ".into() }, grapheme: Grapheme::Other { g: " ".into() },
source: GraphemeSource::Document { codepoints: 0 }, source: GraphemeSource::Document { codepoints: 0 },
}); });
}; };
let grapheme = FormattedGrapheme::new(grapheme, col, self.text_fmt.tab_width, source); let grapheme = GraphemeWithSource::new(grapheme, col, self.text_fmt.tab_width, source);
Some(grapheme) Some(grapheme)
} }
/// Move a word to the next visual line /// Move a word to the next visual line
fn wrap_word(&mut self, virtual_lines_before_word: usize) -> usize { fn wrap_word(&mut self) -> usize {
// softwrap this word to the next line // softwrap this word to the next line
let indent_carry_over = if let Some(indent) = self.indent_level { let indent_carry_over = if let Some(indent) = self.indent_level {
if indent as u16 <= self.text_fmt.max_indent_retain { if indent as u16 <= self.text_fmt.max_indent_retain {
@@ -254,15 +304,17 @@ impl<'t> DocumentFormatter<'t> {
0 0
}; };
let virtual_lines =
self.annotations
.virtual_lines_at(self.char_pos, self.visual_pos, self.line_pos);
self.visual_pos.col = indent_carry_over as usize; self.visual_pos.col = indent_carry_over as usize;
self.virtual_lines -= virtual_lines_before_word; self.visual_pos.row += 1 + virtual_lines;
self.visual_pos.row += 1 + virtual_lines_before_word;
let mut i = 0; let mut i = 0;
let mut word_width = 0; let mut word_width = 0;
let wrap_indicator = UnicodeSegmentation::graphemes(&*self.text_fmt.wrap_indicator, true) let wrap_indicator = UnicodeSegmentation::graphemes(&*self.text_fmt.wrap_indicator, true)
.map(|g| { .map(|g| {
i += 1; i += 1;
let grapheme = FormattedGrapheme::new( let grapheme = GraphemeWithSource::new(
g.into(), g.into(),
self.visual_pos.col + word_width, self.visual_pos.col + word_width,
self.text_fmt.tab_width, self.text_fmt.tab_width,
@@ -282,46 +334,71 @@ impl<'t> DocumentFormatter<'t> {
.change_position(visual_x, self.text_fmt.tab_width); .change_position(visual_x, self.text_fmt.tab_width);
word_width += grapheme.width(); word_width += grapheme.width();
} }
if let Some(grapheme) = &mut self.peeked_grapheme {
let visual_x = self.visual_pos.col + word_width;
grapheme
.grapheme
.change_position(visual_x, self.text_fmt.tab_width);
}
word_width word_width
} }
fn peek_grapheme(&mut self, col: usize, char_pos: usize) -> Option<&GraphemeWithSource<'t>> {
if self.peeked_grapheme.is_none() {
self.peeked_grapheme = self.advance_grapheme(col, char_pos);
}
self.peeked_grapheme.as_ref()
}
fn next_grapheme(&mut self, col: usize, char_pos: usize) -> Option<GraphemeWithSource<'t>> {
self.peek_grapheme(col, char_pos);
self.peeked_grapheme.take()
}
fn advance_to_next_word(&mut self) { fn advance_to_next_word(&mut self) {
self.word_buf.clear(); self.word_buf.clear();
let mut word_width = 0; let mut word_width = 0;
let virtual_lines_before_word = self.virtual_lines; let mut word_chars = 0;
let mut virtual_lines_before_grapheme = self.virtual_lines;
if self.exhausted {
return;
}
loop { loop {
// softwrap word if necessary let mut col = self.visual_pos.col + word_width;
if word_width + self.visual_pos.col >= self.text_fmt.viewport_width as usize { let char_pos = self.char_pos + word_chars;
// wrapping this word would move too much text to the next line match col.cmp(&(self.text_fmt.viewport_width as usize)) {
// split the word at the line end instead // The EOF char and newline chars are always selectable in helix. That means
if word_width > self.text_fmt.max_wrap as usize { // that wrapping happens "too-early" if a word fits a line perfectly. This
// Usually we stop accomulating graphemes as soon as softwrapping becomes necessary. // is intentional so that all selectable graphemes are always visisble (and
// However if the last grapheme is multiple columns wide it might extend beyond the EOL. // therefore the cursor never dissapears). However if the user manually set a
// The condition below ensures that this grapheme is not cutoff and instead wrapped to the next line // lower softwrap width then this is undesirable. Just increasing the viewport-
if word_width + self.visual_pos.col > self.text_fmt.viewport_width as usize { // width by one doesn't work because if a line is wrapped multiple times then
self.peeked_grapheme = self.word_buf.pop().map(|grapheme| { // some words may extend past the specified width.
(grapheme, self.virtual_lines - virtual_lines_before_grapheme) //
}); // So we special case a word that ends exactly at line bounds and is followed
self.virtual_lines = virtual_lines_before_grapheme; // by a newline/eof character here.
} Ordering::Equal
if self.text_fmt.soft_wrap_at_text_width
&& self.peek_grapheme(col, char_pos).map_or(false, |grapheme| {
grapheme.is_newline() || grapheme.is_eof()
}) => {}
Ordering::Equal if word_width > self.text_fmt.max_wrap as usize => return,
Ordering::Greater if word_width > self.text_fmt.max_wrap as usize => {
self.peeked_grapheme = self.word_buf.pop();
return; return;
} }
Ordering::Equal | Ordering::Greater => {
word_width = self.wrap_word(virtual_lines_before_word); word_width = self.wrap_word();
col = self.visual_pos.col + word_width;
}
Ordering::Less => (),
} }
virtual_lines_before_grapheme = self.virtual_lines; let Some(grapheme) = self.next_grapheme(col, char_pos) else {
let grapheme = if let Some((grapheme, virtual_lines)) = self.peeked_grapheme.take() {
self.virtual_lines += virtual_lines;
grapheme
} else if let Some(grapheme) = self.advance_grapheme(self.visual_pos.col + word_width) {
grapheme
} else {
return; return;
}; };
word_chars += grapheme.doc_chars();
// Track indentation // Track indentation
if !grapheme.is_whitespace() && self.indent_level.is_none() { if !grapheme.is_whitespace() && self.indent_level.is_none() {
@@ -340,19 +417,18 @@ impl<'t> DocumentFormatter<'t> {
} }
} }
/// returns the document line pos of the **next** grapheme that will be yielded /// returns the char index at the end of the last yielded grapheme
pub fn line_pos(&self) -> usize { pub fn next_char_pos(&self) -> usize {
self.line_pos self.char_pos
} }
/// returns the visual position at the end of the last yielded grapheme
/// returns the visual pos of the **next** grapheme that will be yielded pub fn next_visual_pos(&self) -> Position {
pub fn visual_pos(&self) -> Position {
self.visual_pos self.visual_pos
} }
} }
impl<'t> Iterator for DocumentFormatter<'t> { impl<'t> Iterator for DocumentFormatter<'t> {
type Item = (FormattedGrapheme<'t>, Position); type Item = FormattedGrapheme<'t>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
let grapheme = if self.text_fmt.soft_wrap { let grapheme = if self.text_fmt.soft_wrap {
@@ -362,23 +438,40 @@ impl<'t> Iterator for DocumentFormatter<'t> {
} }
let grapheme = replace( let grapheme = replace(
self.word_buf.get_mut(self.word_i)?, self.word_buf.get_mut(self.word_i)?,
FormattedGrapheme::placeholder(), GraphemeWithSource::placeholder(),
); );
self.word_i += 1; self.word_i += 1;
grapheme grapheme
} else { } else {
self.advance_grapheme(self.visual_pos.col)? self.advance_grapheme(self.visual_pos.col, self.char_pos)?
}; };
let pos = self.visual_pos; let grapheme = FormattedGrapheme {
if grapheme.grapheme == Grapheme::Newline { raw: grapheme.grapheme,
self.visual_pos.row += 1; source: grapheme.source,
self.visual_pos.row += take(&mut self.virtual_lines); visual_pos: self.visual_pos,
line_idx: self.line_pos,
char_idx: self.char_pos,
};
self.char_pos += grapheme.doc_chars();
if !grapheme.is_virtual() {
self.annotations.process_virtual_text_anchors(&grapheme);
}
if grapheme.raw == Grapheme::Newline {
// move to end of newline char
self.visual_pos.col += 1;
let virtual_lines =
self.annotations
.virtual_lines_at(self.char_pos, self.visual_pos, self.line_pos);
self.visual_pos.row += 1 + virtual_lines;
self.visual_pos.col = 0; self.visual_pos.col = 0;
self.line_pos += 1; if !grapheme.is_virtual() {
self.line_pos += 1;
}
} else { } else {
self.visual_pos.col += grapheme.width(); self.visual_pos.col += grapheme.width();
} }
Some((grapheme, pos)) Some(grapheme)
} }
} }

View File

@@ -1,5 +1,3 @@
use std::rc::Rc;
use crate::doc_formatter::{DocumentFormatter, TextFormat}; use crate::doc_formatter::{DocumentFormatter, TextFormat};
use crate::text_annotations::{InlineAnnotation, Overlay, TextAnnotations}; use crate::text_annotations::{InlineAnnotation, Overlay, TextAnnotations};
@@ -14,6 +12,7 @@ impl TextFormat {
wrap_indicator_highlight: None, wrap_indicator_highlight: None,
// use a prime number to allow lining up too often with repeat // use a prime number to allow lining up too often with repeat
viewport_width: 17, viewport_width: 17,
soft_wrap_at_text_width: false,
} }
} }
} }
@@ -23,20 +22,23 @@ impl<'t> DocumentFormatter<'t> {
use std::fmt::Write; use std::fmt::Write;
let mut res = String::new(); let mut res = String::new();
let viewport_width = self.text_fmt.viewport_width; let viewport_width = self.text_fmt.viewport_width;
let soft_wrap_at_text_width = self.text_fmt.soft_wrap_at_text_width;
let mut line = 0; let mut line = 0;
for (grapheme, pos) in self { for grapheme in self {
if pos.row != line { if grapheme.visual_pos.row != line {
line += 1; line += 1;
assert_eq!(pos.row, line); assert_eq!(grapheme.visual_pos.row, line);
write!(res, "\n{}", ".".repeat(pos.col)).unwrap(); write!(res, "\n{}", ".".repeat(grapheme.visual_pos.col)).unwrap();
}
if !soft_wrap_at_text_width {
assert!( assert!(
pos.col <= viewport_width as usize, grapheme.visual_pos.col <= viewport_width as usize,
"softwrapped failed {}<={viewport_width}", "softwrapped failed {}<={viewport_width}",
pos.col grapheme.visual_pos.col
); );
} }
write!(res, "{}", grapheme.grapheme).unwrap(); write!(res, "{}", grapheme.raw).unwrap();
} }
res res
@@ -50,7 +52,6 @@ fn softwrap_text(text: &str) -> String {
&TextAnnotations::default(), &TextAnnotations::default(),
0, 0,
) )
.0
.collect_to_str() .collect_to_str()
} }
@@ -101,14 +102,29 @@ fn long_word_softwrap() {
); );
} }
fn softwrap_text_at_text_width(text: &str) -> String {
let mut text_fmt = TextFormat::new_test(true);
text_fmt.soft_wrap_at_text_width = true;
let annotations = TextAnnotations::default();
let mut formatter =
DocumentFormatter::new_at_prev_checkpoint(text.into(), &text_fmt, &annotations, 0);
formatter.collect_to_str()
}
#[test]
fn long_word_softwrap_text_width() {
assert_eq!(
softwrap_text_at_text_width("xxxxxxxx1xxxx2xxx\nxxxxxxxx1xxxx2xxx"),
"xxxxxxxx1xxxx2xxx \nxxxxxxxx1xxxx2xxx "
);
}
fn overlay_text(text: &str, char_pos: usize, softwrap: bool, overlays: &[Overlay]) -> String { fn overlay_text(text: &str, char_pos: usize, softwrap: bool, overlays: &[Overlay]) -> String {
DocumentFormatter::new_at_prev_checkpoint( DocumentFormatter::new_at_prev_checkpoint(
text.into(), text.into(),
&TextFormat::new_test(softwrap), &TextFormat::new_test(softwrap),
TextAnnotations::default().add_overlay(overlays.into(), None), TextAnnotations::default().add_overlay(overlays, None),
char_pos, char_pos,
) )
.0
.collect_to_str() .collect_to_str()
} }
@@ -142,10 +158,9 @@ fn annotate_text(text: &str, softwrap: bool, annotations: &[InlineAnnotation]) -
DocumentFormatter::new_at_prev_checkpoint( DocumentFormatter::new_at_prev_checkpoint(
text.into(), text.into(),
&TextFormat::new_test(softwrap), &TextFormat::new_test(softwrap),
TextAnnotations::default().add_inline_annotations(annotations.into(), None), TextAnnotations::default().add_inline_annotations(annotations, None),
0, 0,
) )
.0
.collect_to_str() .collect_to_str()
} }
@@ -164,18 +179,26 @@ fn annotation() {
"foo foo foo foo \n.foo foo foo foo \n.foo foo foo " "foo foo foo foo \n.foo foo foo foo \n.foo foo foo "
); );
} }
#[test] #[test]
fn annotation_and_overlay() { fn annotation_and_overlay() {
let annotations = [InlineAnnotation {
char_idx: 0,
text: "fooo".into(),
}];
let overlay = [Overlay {
char_idx: 0,
grapheme: "\t".into(),
}];
assert_eq!( assert_eq!(
DocumentFormatter::new_at_prev_checkpoint( DocumentFormatter::new_at_prev_checkpoint(
"bbar".into(), "bbar".into(),
&TextFormat::new_test(false), &TextFormat::new_test(false),
TextAnnotations::default() TextAnnotations::default()
.add_inline_annotations(Rc::new([InlineAnnotation::new(0, "fooo")]), None) .add_inline_annotations(annotations.as_slice(), None)
.add_overlay(Rc::new([Overlay::new(0, "\t")]), None), .add_overlay(overlay.as_slice(), None),
0, 0,
) )
.0
.collect_to_str(), .collect_to_str(),
"fooo bar " "fooo bar "
); );

49
helix-core/src/fuzzy.rs Normal file
View File

@@ -0,0 +1,49 @@
use std::ops::DerefMut;
use nucleo::pattern::{Atom, AtomKind, CaseMatching, Normalization};
use nucleo::Config;
use parking_lot::Mutex;
pub struct LazyMutex<T> {
inner: Mutex<Option<T>>,
init: fn() -> T,
}
impl<T> LazyMutex<T> {
pub const fn new(init: fn() -> T) -> Self {
Self {
inner: Mutex::new(None),
init,
}
}
pub fn lock(&self) -> impl DerefMut<Target = T> + '_ {
parking_lot::MutexGuard::map(self.inner.lock(), |val| val.get_or_insert_with(self.init))
}
}
pub static MATCHER: LazyMutex<nucleo::Matcher> = LazyMutex::new(nucleo::Matcher::default);
/// convenience function to easily fuzzy match
/// on a (relatively small list of inputs). This is not recommended for building a full tui
/// application that can match large numbers of matches as all matching is done on the current
/// thread, effectively blocking the UI
pub fn fuzzy_match<T: AsRef<str>>(
pattern: &str,
items: impl IntoIterator<Item = T>,
path: bool,
) -> Vec<(T, u16)> {
let mut matcher = MATCHER.lock();
matcher.config = Config::DEFAULT;
if path {
matcher.config.set_match_paths();
}
let pattern = Atom::new(
pattern,
CaseMatching::Smart,
Normalization::Smart,
AtomKind::Fuzzy,
false,
);
pattern.match_list(items, &mut matcher)
}

View File

@@ -28,6 +28,11 @@ pub enum Grapheme<'a> {
} }
impl<'a> Grapheme<'a> { impl<'a> Grapheme<'a> {
pub fn new_decoration(g: &'static str) -> Grapheme<'a> {
assert_ne!(g, "\t");
Grapheme::new(g.into(), 0, 0)
}
pub fn new(g: GraphemeStr<'a>, visual_x: usize, tab_width: u16) -> Grapheme<'a> { pub fn new(g: GraphemeStr<'a>, visual_x: usize, tab_width: u16) -> Grapheme<'a> {
match g { match g {
g if g == "\t" => Grapheme::Tab { g if g == "\t" => Grapheme::Tab {
@@ -278,23 +283,6 @@ pub fn ensure_grapheme_boundary_prev(slice: RopeSlice, char_idx: usize) -> usize
} }
} }
/// Returns the passed byte index if it's already a grapheme boundary,
/// or the next grapheme boundary byte index if not.
#[must_use]
#[inline]
pub fn ensure_grapheme_boundary_next_byte(slice: RopeSlice, byte_idx: usize) -> usize {
if byte_idx == 0 {
byte_idx
} else {
// TODO: optimize so we're not constructing grapheme cursor twice
if is_grapheme_boundary_byte(slice, byte_idx) {
byte_idx
} else {
next_grapheme_boundary_byte(slice, byte_idx)
}
}
}
/// Returns whether the given char position is a grapheme boundary. /// Returns whether the given char position is a grapheme boundary.
#[must_use] #[must_use]
pub fn is_grapheme_boundary(slice: RopeSlice, char_idx: usize) -> bool { pub fn is_grapheme_boundary(slice: RopeSlice, char_idx: usize) -> bool {
@@ -358,7 +346,7 @@ pub struct RopeGraphemes<'a> {
cursor: GraphemeCursor, cursor: GraphemeCursor,
} }
impl<'a> fmt::Debug for RopeGraphemes<'a> { impl fmt::Debug for RopeGraphemes<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RopeGraphemes") f.debug_struct("RopeGraphemes")
.field("text", &self.text) .field("text", &self.text)
@@ -370,7 +358,7 @@ impl<'a> fmt::Debug for RopeGraphemes<'a> {
} }
} }
impl<'a> RopeGraphemes<'a> { impl RopeGraphemes<'_> {
#[must_use] #[must_use]
pub fn new(slice: RopeSlice) -> RopeGraphemes { pub fn new(slice: RopeSlice) -> RopeGraphemes {
let mut chunks = slice.chunks(); let mut chunks = slice.chunks();
@@ -425,6 +413,85 @@ impl<'a> Iterator for RopeGraphemes<'a> {
} }
} }
/// An iterator over the graphemes of a `RopeSlice` in reverse.
#[derive(Clone)]
pub struct RevRopeGraphemes<'a> {
text: RopeSlice<'a>,
chunks: Chunks<'a>,
cur_chunk: &'a str,
cur_chunk_start: usize,
cursor: GraphemeCursor,
}
impl fmt::Debug for RevRopeGraphemes<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("RevRopeGraphemes")
.field("text", &self.text)
.field("chunks", &self.chunks)
.field("cur_chunk", &self.cur_chunk)
.field("cur_chunk_start", &self.cur_chunk_start)
// .field("cursor", &self.cursor)
.finish()
}
}
impl RevRopeGraphemes<'_> {
#[must_use]
pub fn new(slice: RopeSlice) -> RevRopeGraphemes {
let (mut chunks, mut cur_chunk_start, _, _) = slice.chunks_at_byte(slice.len_bytes());
chunks.reverse();
let first_chunk = chunks.next().unwrap_or("");
cur_chunk_start -= first_chunk.len();
RevRopeGraphemes {
text: slice,
chunks,
cur_chunk: first_chunk,
cur_chunk_start,
cursor: GraphemeCursor::new(slice.len_bytes(), slice.len_bytes(), true),
}
}
}
impl<'a> Iterator for RevRopeGraphemes<'a> {
type Item = RopeSlice<'a>;
fn next(&mut self) -> Option<RopeSlice<'a>> {
let a = self.cursor.cur_cursor();
let b;
loop {
match self
.cursor
.prev_boundary(self.cur_chunk, self.cur_chunk_start)
{
Ok(None) => {
return None;
}
Ok(Some(n)) => {
b = n;
break;
}
Err(GraphemeIncomplete::PrevChunk) => {
self.cur_chunk = self.chunks.next().unwrap_or("");
self.cur_chunk_start -= self.cur_chunk.len();
}
Err(GraphemeIncomplete::PreContext(idx)) => {
let (chunk, byte_idx, _, _) = self.text.chunk_at_byte(idx.saturating_sub(1));
self.cursor.provide_context(chunk, byte_idx);
}
_ => unreachable!(),
}
}
if a >= self.cur_chunk_start + self.cur_chunk.len() {
Some(self.text.byte_slice(b..a))
} else {
let a2 = a - self.cur_chunk_start;
let b2 = b - self.cur_chunk_start;
Some((&self.cur_chunk[b2..a2]).into())
}
}
}
/// A highly compressed Cow<'a, str> that holds /// A highly compressed Cow<'a, str> that holds
/// atmost u31::MAX bytes and is readonly /// atmost u31::MAX bytes and is readonly
pub struct GraphemeStr<'a> { pub struct GraphemeStr<'a> {
@@ -475,13 +542,13 @@ impl<'a> From<&'a str> for GraphemeStr<'a> {
} }
} }
impl<'a> From<String> for GraphemeStr<'a> { impl From<String> for GraphemeStr<'_> {
fn from(g: String) -> Self { fn from(g: String) -> Self {
let len = g.len(); let len = g.len();
let ptr = Box::into_raw(g.into_bytes().into_boxed_slice()) as *mut u8; let ptr = Box::into_raw(g.into_bytes().into_boxed_slice()) as *mut u8;
GraphemeStr { GraphemeStr {
ptr: unsafe { NonNull::new_unchecked(ptr) }, ptr: unsafe { NonNull::new_unchecked(ptr) },
len: i32::try_from(len).unwrap() as u32, len: (i32::try_from(len).unwrap() as u32) | Self::MASK_OWNED,
phantom: PhantomData, phantom: PhantomData,
} }
} }

View File

@@ -72,8 +72,8 @@ impl Default for History {
revisions: vec![Revision { revisions: vec![Revision {
parent: 0, parent: 0,
last_child: None, last_child: None,
transaction: Transaction::from(ChangeSet::new(&Rope::new())), transaction: Transaction::from(ChangeSet::new("".into())),
inversion: Transaction::from(ChangeSet::new(&Rope::new())), inversion: Transaction::from(ChangeSet::new("".into())),
timestamp: Instant::now(), timestamp: Instant::now(),
}], }],
current: 0, current: 0,

View File

@@ -27,7 +27,7 @@ pub fn increment(selected_text: &str, amount: i64) -> Option<String> {
let date_time = NaiveDateTime::parse_from_str(date_time, format.fmt).ok()?; let date_time = NaiveDateTime::parse_from_str(date_time, format.fmt).ok()?;
Some( Some(
date_time date_time
.checked_add_signed(Duration::minutes(amount))? .checked_add_signed(Duration::try_minutes(amount)?)?
.format(format.fmt) .format(format.fmt)
.to_string(), .to_string(),
) )
@@ -35,14 +35,15 @@ pub fn increment(selected_text: &str, amount: i64) -> Option<String> {
(true, false) => { (true, false) => {
let date = NaiveDate::parse_from_str(date_time, format.fmt).ok()?; let date = NaiveDate::parse_from_str(date_time, format.fmt).ok()?;
Some( Some(
date.checked_add_signed(Duration::days(amount))? date.checked_add_signed(Duration::try_days(amount)?)?
.format(format.fmt) .format(format.fmt)
.to_string(), .to_string(),
) )
} }
(false, true) => { (false, true) => {
let time = NaiveTime::parse_from_str(date_time, format.fmt).ok()?; let time = NaiveTime::parse_from_str(date_time, format.fmt).ok()?;
let (adjusted_time, _) = time.overflowing_add_signed(Duration::minutes(amount)); let (adjusted_time, _) =
time.overflowing_add_signed(Duration::try_minutes(amount)?);
Some(adjusted_time.format(format.fmt).to_string()) Some(adjusted_time.format(format.fmt).to_string())
} }
(false, false) => None, (false, false) => None,

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,15 @@
pub use encoding_rs as encoding; pub use encoding_rs as encoding;
pub mod auto_pairs; pub mod auto_pairs;
pub mod case_conversion;
pub mod chars; pub mod chars;
pub mod comment; pub mod comment;
pub mod completion;
pub mod config; pub mod config;
pub mod diagnostic; pub mod diagnostic;
pub mod diff; pub mod diff;
pub mod doc_formatter; pub mod doc_formatter;
pub mod fuzzy;
pub mod graphemes; pub mod graphemes;
pub mod history; pub mod history;
pub mod increment; pub mod increment;
@@ -16,18 +19,18 @@ pub mod macros;
pub mod match_brackets; pub mod match_brackets;
pub mod movement; pub mod movement;
pub mod object; pub mod object;
pub mod path;
mod position; mod position;
pub mod register;
pub mod search; pub mod search;
pub mod selection; pub mod selection;
pub mod shellwords; pub mod shellwords;
pub mod snippets;
pub mod surround; pub mod surround;
pub mod syntax; pub mod syntax;
pub mod test; pub mod test;
pub mod text_annotations; pub mod text_annotations;
pub mod textobject; pub mod textobject;
mod transaction; mod transaction;
pub mod uri;
pub mod wrap; pub mod wrap;
pub mod unicode { pub mod unicode {
@@ -38,10 +41,9 @@ pub mod unicode {
pub use helix_loader::find_workspace; pub use helix_loader::find_workspace;
pub fn find_first_non_whitespace_char(line: RopeSlice) -> Option<usize> { mod rope_reader;
line.chars().position(|ch| !ch.is_whitespace())
}
pub use rope_reader::RopeReader;
pub use ropey::{self, str_utils, Rope, RopeBuilder, RopeSlice}; pub use ropey::{self, str_utils, Rope, RopeBuilder, RopeSlice};
// pub use tendril::StrTendril as Tendril; // pub use tendril::StrTendril as Tendril;
@@ -54,8 +56,8 @@ pub use {regex, tree_sitter};
pub use graphemes::RopeGraphemes; pub use graphemes::RopeGraphemes;
pub use position::{ pub use position::{
char_idx_at_visual_offset, coords_at_pos, pos_at_coords, visual_offset_from_anchor, char_idx_at_visual_offset, coords_at_pos, pos_at_coords, softwrapped_dimensions,
visual_offset_from_block, Position, VisualOffsetError, visual_offset_from_anchor, visual_offset_from_block, Position, VisualOffsetError,
}; };
#[allow(deprecated)] #[allow(deprecated)]
pub use position::{pos_at_visual_coords, visual_coords_at_pos}; pub use position::{pos_at_visual_coords, visual_coords_at_pos};
@@ -64,7 +66,10 @@ pub use selection::{Range, Selection};
pub use smallvec::{smallvec, SmallVec}; pub use smallvec::{smallvec, SmallVec};
pub use syntax::Syntax; pub use syntax::Syntax;
pub use completion::CompletionItem;
pub use diagnostic::Diagnostic; pub use diagnostic::Diagnostic;
pub use line_ending::{LineEnding, DEFAULT_LINE_ENDING}; pub use line_ending::{LineEnding, NATIVE_LINE_ENDING};
pub use transaction::{Assoc, Change, ChangeSet, Operation, Transaction}; pub use transaction::{Assoc, Change, ChangeSet, Deletion, Operation, Transaction};
pub use uri::Uri;

View File

@@ -1,9 +1,9 @@
use crate::{Rope, RopeSlice}; use crate::{Rope, RopeSlice};
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
pub const DEFAULT_LINE_ENDING: LineEnding = LineEnding::Crlf; pub const NATIVE_LINE_ENDING: LineEnding = LineEnding::Crlf;
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
pub const DEFAULT_LINE_ENDING: LineEnding = LineEnding::LF; pub const NATIVE_LINE_ENDING: LineEnding = LineEnding::LF;
/// Represents one of the valid Unicode line endings. /// Represents one of the valid Unicode line endings.
#[derive(PartialEq, Eq, Copy, Clone, Debug)] #[derive(PartialEq, Eq, Copy, Clone, Debug)]

View File

@@ -1,28 +1,54 @@
use std::iter;
use ropey::RopeSlice;
use tree_sitter::Node; use tree_sitter::Node;
use crate::{Rope, Syntax}; use crate::movement::Direction::{self, Backward, Forward};
use crate::Syntax;
const PAIRS: &[(char, char)] = &[ const MAX_PLAINTEXT_SCAN: usize = 10000;
const MATCH_LIMIT: usize = 16;
pub const BRACKETS: [(char, char); 9] = [
('(', ')'), ('(', ')'),
('{', '}'), ('{', '}'),
('[', ']'), ('[', ']'),
('<', '>'), ('<', '>'),
('\'', '\''), ('', ''),
('\"', '\"'), ('', ''),
('«', '»'),
('「', '」'),
('', ''),
]; ];
// limit matching pairs to only ( ) { } [ ] < > ' ' " " // The difference between BRACKETS and PAIRS is that we can find matching
// BRACKETS in a plain text file, but we can't do the same for PAIRs.
// PAIRS also contains all BRACKETS.
pub const PAIRS: [(char, char); BRACKETS.len() + 3] = {
let mut pairs = [(' ', ' '); BRACKETS.len() + 3];
let mut idx = 0;
while idx < BRACKETS.len() {
pairs[idx] = BRACKETS[idx];
idx += 1;
}
pairs[idx] = ('"', '"');
pairs[idx + 1] = ('\'', '\'');
pairs[idx + 2] = ('`', '`');
pairs
};
// Returns the position of the matching bracket under cursor. /// Returns the position of the matching bracket under cursor.
// ///
// If the cursor is one the opening bracket, the position of /// If the cursor is on the opening bracket, the position of
// the closing bracket is returned. If the cursor in the closing /// the closing bracket is returned. If the cursor on the closing
// bracket, the position of the opening bracket is returned. /// bracket, the position of the opening bracket is returned.
// ///
// If the cursor is not on a bracket, `None` is returned. /// If the cursor is not on a bracket, `None` is returned.
///
/// If no matching bracket is found, `None` is returned.
#[must_use] #[must_use]
pub fn find_matching_bracket(syntax: &Syntax, doc: &Rope, pos: usize) -> Option<usize> { pub fn find_matching_bracket(syntax: &Syntax, doc: RopeSlice, pos: usize) -> Option<usize> {
if pos >= doc.len_chars() || !is_valid_bracket(doc.char(pos)) { if pos >= doc.len_chars() || !is_valid_pair(doc.char(pos)) {
return None; return None;
} }
find_pair(syntax, doc, pos, false) find_pair(syntax, doc, pos, false)
@@ -39,54 +65,284 @@ pub fn find_matching_bracket(syntax: &Syntax, doc: &Rope, pos: usize) -> Option<
// //
// If no surrounding scope is found, the function returns `None`. // If no surrounding scope is found, the function returns `None`.
#[must_use] #[must_use]
pub fn find_matching_bracket_fuzzy(syntax: &Syntax, doc: &Rope, pos: usize) -> Option<usize> { pub fn find_matching_bracket_fuzzy(syntax: &Syntax, doc: RopeSlice, pos: usize) -> Option<usize> {
find_pair(syntax, doc, pos, true) find_pair(syntax, doc, pos, true)
} }
fn find_pair(syntax: &Syntax, doc: &Rope, pos: usize, traverse_parents: bool) -> Option<usize> { fn find_pair(
let tree = syntax.tree(); syntax: &Syntax,
let pos = doc.char_to_byte(pos); doc: RopeSlice,
pos_: usize,
traverse_parents: bool,
) -> Option<usize> {
let pos = doc.char_to_byte(pos_);
let mut node = tree.root_node().named_descendant_for_byte_range(pos, pos)?; let root = syntax.tree_for_byte_range(pos, pos).root_node();
let mut node = root.descendant_for_byte_range(pos, pos)?;
loop { loop {
let (start_byte, end_byte) = surrounding_bytes(doc, &node)?; if node.is_named() && node.child_count() >= 2 {
let (start_char, end_char) = (doc.byte_to_char(start_byte), doc.byte_to_char(end_byte)); let open = node.child(0).unwrap();
let close = node.child(node.child_count() - 1).unwrap();
if is_valid_pair(doc, start_char, end_char) { if let (Some((start_pos, open)), Some((end_pos, close))) =
if end_byte == pos { (as_char(doc, &open), as_char(doc, &close))
return Some(start_char); {
if PAIRS.contains(&(open, close)) {
if end_pos == pos_ {
return Some(start_pos);
}
// We return the end char if the cursor is either on the start char
// or at some arbitrary position between start and end char.
if traverse_parents || start_pos == pos_ {
return Some(end_pos);
}
}
}
}
// this node itselt wasn't a pair but maybe its siblings are
if let Some((start_char, end_char)) = as_close_pair(doc, &node) {
if let Some(pair_start) =
find_pair_end(doc, node.prev_sibling(), start_char, end_char, Backward)
{
return Some(pair_start);
}
}
if let Some((start_char, end_char)) = as_open_pair(doc, &node) {
if let Some(pair_end) =
find_pair_end(doc, node.next_sibling(), start_char, end_char, Forward)
{
return Some(pair_end);
} }
// We return the end char if the cursor is either on the start char
// or at some arbitrary position between start and end char.
return Some(end_char);
} }
if traverse_parents { if traverse_parents {
node = node.parent()?; for sibling in
} else { iter::successors(node.next_sibling(), |node| node.next_sibling()).take(MATCH_LIMIT)
return None; {
let Some((start_char, end_char)) = as_close_pair(doc, &sibling) else {
continue;
};
if find_pair_end(doc, sibling.prev_sibling(), start_char, end_char, Backward)
.is_some()
{
return doc.try_byte_to_char(sibling.start_byte()).ok();
}
}
} else if node.is_named() {
break;
} }
let Some(parent) = node.parent() else {
break;
};
node = parent;
} }
let node = root.named_descendant_for_byte_range(pos, pos + 1)?;
if node.child_count() != 0 {
return None;
}
let node_start = doc.byte_to_char(node.start_byte());
find_matching_bracket_plaintext(doc.byte_slice(node.byte_range()), pos_ - node_start)
.map(|pos| pos + node_start)
} }
fn is_valid_bracket(c: char) -> bool { /// Returns the position of the matching bracket under cursor.
PAIRS.iter().any(|(l, r)| *l == c || *r == c) /// This function works on plain text and ignores tree-sitter grammar.
} /// The search is limited to `MAX_PLAINTEXT_SCAN` characters
///
fn is_valid_pair(doc: &Rope, start_char: usize, end_char: usize) -> bool { /// If the cursor is on the opening bracket, the position of
PAIRS.contains(&(doc.char(start_char), doc.char(end_char))) /// the closing bracket is returned. If the cursor on the closing
} /// bracket, the position of the opening bracket is returned.
///
fn surrounding_bytes(doc: &Rope, node: &Node) -> Option<(usize, usize)> { /// If the cursor is not on a bracket, `None` is returned.
let len = doc.len_bytes(); ///
/// If no matching bracket is found, `None` is returned.
let start_byte = node.start_byte(); #[must_use]
let end_byte = node.end_byte().saturating_sub(1); pub fn find_matching_bracket_plaintext(doc: RopeSlice, cursor_pos: usize) -> Option<usize> {
let bracket = doc.get_char(cursor_pos)?;
if start_byte >= len || end_byte >= len { let matching_bracket = {
let pair = get_pair(bracket);
if pair.0 == bracket {
pair.1
} else {
pair.0
}
};
// Don't do anything when the cursor is not on top of a bracket.
if !is_valid_bracket(bracket) {
return None; return None;
} }
Some((start_byte, end_byte)) // Determine the direction of the matching.
let is_fwd = is_open_bracket(bracket);
let chars_iter = if is_fwd {
doc.chars_at(cursor_pos + 1)
} else {
doc.chars_at(cursor_pos).reversed()
};
let mut open_cnt = 1;
for (i, candidate) in chars_iter.take(MAX_PLAINTEXT_SCAN).enumerate() {
if candidate == bracket {
open_cnt += 1;
} else if candidate == matching_bracket {
// Return when all pending brackets have been closed.
if open_cnt == 1 {
return Some(if is_fwd {
cursor_pos + i + 1
} else {
cursor_pos - i - 1
});
}
open_cnt -= 1;
}
}
None
}
/// Returns the open and closing chars pair. If not found in
/// [`BRACKETS`] returns (ch, ch).
///
/// ```
/// use helix_core::match_brackets::get_pair;
///
/// assert_eq!(get_pair('['), ('[', ']'));
/// assert_eq!(get_pair('}'), ('{', '}'));
/// assert_eq!(get_pair('"'), ('"', '"'));
/// ```
pub fn get_pair(ch: char) -> (char, char) {
PAIRS
.iter()
.find(|(open, close)| *open == ch || *close == ch)
.copied()
.unwrap_or((ch, ch))
}
pub fn is_open_bracket(ch: char) -> bool {
BRACKETS.iter().any(|(l, _)| *l == ch)
}
pub fn is_close_bracket(ch: char) -> bool {
BRACKETS.iter().any(|(_, r)| *r == ch)
}
pub fn is_valid_bracket(ch: char) -> bool {
BRACKETS.iter().any(|(l, r)| *l == ch || *r == ch)
}
pub fn is_open_pair(ch: char) -> bool {
PAIRS.iter().any(|(l, _)| *l == ch)
}
pub fn is_close_pair(ch: char) -> bool {
PAIRS.iter().any(|(_, r)| *r == ch)
}
pub fn is_valid_pair(ch: char) -> bool {
PAIRS.iter().any(|(l, r)| *l == ch || *r == ch)
}
/// Tests if this node is a pair close char and returns the expected open char
/// and close char contained in this node
fn as_close_pair(doc: RopeSlice, node: &Node) -> Option<(char, char)> {
let close = as_char(doc, node)?.1;
PAIRS
.iter()
.find_map(|&(open, close_)| (close_ == close).then_some((close, open)))
}
/// Checks if `node` or its siblings (at most MATCH_LIMIT nodes) is the specified closing char
///
/// # Returns
///
/// The position of the found node or `None` otherwise
fn find_pair_end(
doc: RopeSlice,
node: Option<Node>,
start_char: char,
end_char: char,
direction: Direction,
) -> Option<usize> {
let advance = match direction {
Forward => Node::next_sibling,
Backward => Node::prev_sibling,
};
let mut depth = 0;
iter::successors(node, advance)
.take(MATCH_LIMIT)
.find_map(|node| {
let (pos, c) = as_char(doc, &node)?;
if c == end_char {
if depth == 0 {
return Some(pos);
}
depth -= 1;
} else if c == start_char {
depth += 1;
}
None
})
}
/// Tests if this node is a pair open char and returns the expected close char
/// and open char contained in this node
fn as_open_pair(doc: RopeSlice, node: &Node) -> Option<(char, char)> {
let open = as_char(doc, node)?.1;
PAIRS
.iter()
.find_map(|&(open_, close)| (open_ == open).then_some((open, close)))
}
/// If node is a single char return it (and its char position)
fn as_char(doc: RopeSlice, node: &Node) -> Option<(usize, char)> {
// TODO: multi char/non ASCII pairs
if node.byte_range().len() != 1 {
return None;
}
let pos = doc.try_byte_to_char(node.start_byte()).ok()?;
Some((pos, doc.char(pos)))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn find_matching_bracket_empty_file() {
let actual = find_matching_bracket_plaintext("".into(), 0);
assert_eq!(actual, None);
}
#[test]
fn test_find_matching_bracket_current_line_plaintext() {
let assert = |input: &str, pos, expected| {
let input = RopeSlice::from(input);
let actual = find_matching_bracket_plaintext(input, pos);
assert_eq!(expected, actual.unwrap());
let actual = find_matching_bracket_plaintext(input, expected);
assert_eq!(pos, actual.unwrap(), "expected symmetrical behaviour");
};
assert("(hello)", 0, 6);
assert("((hello))", 0, 8);
assert("((hello))", 1, 7);
assert("(((hello)))", 2, 8);
assert("key: ${value}", 6, 12);
assert("key: ${value} # (some comment)", 16, 29);
assert("(paren (paren {bracket}))", 0, 24);
assert("(paren (paren {bracket}))", 7, 23);
assert("(paren (paren {bracket}))", 14, 22);
assert("(prev line\n ) (middle) ( \n next line)", 0, 12);
assert("(prev line\n ) (middle) ( \n next line)", 14, 21);
assert("(prev line\n ) (middle) ( \n next line)", 23, 36);
}
} }

View File

@@ -1,4 +1,4 @@
use std::iter; use std::{cmp::Reverse, iter};
use ropey::iter::Chars; use ropey::iter::Chars;
use tree_sitter::{Node, QueryCursor}; use tree_sitter::{Node, QueryCursor};
@@ -16,7 +16,7 @@ use crate::{
syntax::LanguageConfiguration, syntax::LanguageConfiguration,
text_annotations::TextAnnotations, text_annotations::TextAnnotations,
textobject::TextObject, textobject::TextObject,
visual_offset_from_block, Range, RopeSlice, visual_offset_from_block, Range, RopeSlice, Selection, Syntax,
}; };
#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[derive(Debug, Copy, Clone, PartialEq, Eq)]
@@ -62,7 +62,7 @@ pub fn move_vertically_visual(
annotations: &mut TextAnnotations, annotations: &mut TextAnnotations,
) -> Range { ) -> Range {
if !text_fmt.soft_wrap { if !text_fmt.soft_wrap {
move_vertically(slice, range, dir, count, behaviour, text_fmt, annotations); return move_vertically(slice, range, dir, count, behaviour, text_fmt, annotations);
} }
annotations.clear_line_annotations(); annotations.clear_line_annotations();
let pos = range.cursor(slice); let pos = range.cursor(slice);
@@ -79,19 +79,19 @@ pub fn move_vertically_visual(
Direction::Backward => -(count as isize), Direction::Backward => -(count as isize),
}; };
// TODO how to handle inline annotations that span an entire visual line (very unlikely).
// Compute visual offset relative to block start to avoid trasversing the block twice // Compute visual offset relative to block start to avoid trasversing the block twice
row_off += visual_pos.row as isize; row_off += visual_pos.row as isize;
let new_pos = char_idx_at_visual_offset( let (mut new_pos, virtual_rows) = char_idx_at_visual_offset(
slice, slice,
block_off, block_off,
row_off, row_off,
new_col as usize, new_col as usize,
text_fmt, text_fmt,
annotations, annotations,
) );
.0; if dir == Direction::Forward {
new_pos += (virtual_rows != 0) as usize;
}
// Special-case to avoid moving to the end of the last non-empty line. // Special-case to avoid moving to the end of the last non-empty line.
if behaviour == Movement::Extend && slice.line(slice.char_to_line(new_pos)).len_chars() == 0 { if behaviour == Movement::Extend && slice.line(slice.char_to_line(new_pos)).len_chars() == 0 {
@@ -177,6 +177,10 @@ pub fn move_prev_word_start(slice: RopeSlice, range: Range, count: usize) -> Ran
word_move(slice, range, count, WordMotionTarget::PrevWordStart) word_move(slice, range, count, WordMotionTarget::PrevWordStart)
} }
pub fn move_prev_word_end(slice: RopeSlice, range: Range, count: usize) -> Range {
word_move(slice, range, count, WordMotionTarget::PrevWordEnd)
}
pub fn move_next_long_word_start(slice: RopeSlice, range: Range, count: usize) -> Range { pub fn move_next_long_word_start(slice: RopeSlice, range: Range, count: usize) -> Range {
word_move(slice, range, count, WordMotionTarget::NextLongWordStart) word_move(slice, range, count, WordMotionTarget::NextLongWordStart)
} }
@@ -189,8 +193,24 @@ pub fn move_prev_long_word_start(slice: RopeSlice, range: Range, count: usize) -
word_move(slice, range, count, WordMotionTarget::PrevLongWordStart) word_move(slice, range, count, WordMotionTarget::PrevLongWordStart)
} }
pub fn move_prev_word_end(slice: RopeSlice, range: Range, count: usize) -> Range { pub fn move_prev_long_word_end(slice: RopeSlice, range: Range, count: usize) -> Range {
word_move(slice, range, count, WordMotionTarget::PrevWordEnd) word_move(slice, range, count, WordMotionTarget::PrevLongWordEnd)
}
pub fn move_next_sub_word_start(slice: RopeSlice, range: Range, count: usize) -> Range {
word_move(slice, range, count, WordMotionTarget::NextSubWordStart)
}
pub fn move_next_sub_word_end(slice: RopeSlice, range: Range, count: usize) -> Range {
word_move(slice, range, count, WordMotionTarget::NextSubWordEnd)
}
pub fn move_prev_sub_word_start(slice: RopeSlice, range: Range, count: usize) -> Range {
word_move(slice, range, count, WordMotionTarget::PrevSubWordStart)
}
pub fn move_prev_sub_word_end(slice: RopeSlice, range: Range, count: usize) -> Range {
word_move(slice, range, count, WordMotionTarget::PrevSubWordEnd)
} }
fn word_move(slice: RopeSlice, range: Range, count: usize, target: WordMotionTarget) -> Range { fn word_move(slice: RopeSlice, range: Range, count: usize, target: WordMotionTarget) -> Range {
@@ -198,7 +218,10 @@ fn word_move(slice: RopeSlice, range: Range, count: usize, target: WordMotionTar
target, target,
WordMotionTarget::PrevWordStart WordMotionTarget::PrevWordStart
| WordMotionTarget::PrevLongWordStart | WordMotionTarget::PrevLongWordStart
| WordMotionTarget::PrevSubWordStart
| WordMotionTarget::PrevWordEnd | WordMotionTarget::PrevWordEnd
| WordMotionTarget::PrevLongWordEnd
| WordMotionTarget::PrevSubWordEnd
); );
// Special-case early-out. // Special-case early-out.
@@ -377,6 +400,13 @@ pub enum WordMotionTarget {
NextLongWordStart, NextLongWordStart,
NextLongWordEnd, NextLongWordEnd,
PrevLongWordStart, PrevLongWordStart,
PrevLongWordEnd,
// A sub word is similar to a regular word, except it is also delimited by
// underscores and transitions from lowercase to uppercase.
NextSubWordStart,
NextSubWordEnd,
PrevSubWordStart,
PrevSubWordEnd,
} }
pub trait CharHelpers { pub trait CharHelpers {
@@ -392,7 +422,10 @@ impl CharHelpers for Chars<'_> {
target, target,
WordMotionTarget::PrevWordStart WordMotionTarget::PrevWordStart
| WordMotionTarget::PrevLongWordStart | WordMotionTarget::PrevLongWordStart
| WordMotionTarget::PrevSubWordStart
| WordMotionTarget::PrevWordEnd | WordMotionTarget::PrevWordEnd
| WordMotionTarget::PrevLongWordEnd
| WordMotionTarget::PrevSubWordEnd
); );
// Reverse the iterator if needed for the motion direction. // Reverse the iterator if needed for the motion direction.
@@ -469,6 +502,25 @@ fn is_long_word_boundary(a: char, b: char) -> bool {
} }
} }
fn is_sub_word_boundary(a: char, b: char, dir: Direction) -> bool {
match (categorize_char(a), categorize_char(b)) {
(CharCategory::Word, CharCategory::Word) => {
if (a == '_') != (b == '_') {
return true;
}
// Subword boundaries are directional: in 'fooBar', there is a
// boundary between 'o' and 'B', but not between 'B' and 'a'.
match dir {
Direction::Forward => a.is_lowercase() && b.is_uppercase(),
Direction::Backward => a.is_uppercase() && b.is_lowercase(),
}
}
(a, b) if a != b => true,
_ => false,
}
}
fn reached_target(target: WordMotionTarget, prev_ch: char, next_ch: char) -> bool { fn reached_target(target: WordMotionTarget, prev_ch: char, next_ch: char) -> bool {
match target { match target {
WordMotionTarget::NextWordStart | WordMotionTarget::PrevWordEnd => { WordMotionTarget::NextWordStart | WordMotionTarget::PrevWordEnd => {
@@ -479,7 +531,7 @@ fn reached_target(target: WordMotionTarget, prev_ch: char, next_ch: char) -> boo
is_word_boundary(prev_ch, next_ch) is_word_boundary(prev_ch, next_ch)
&& (!prev_ch.is_whitespace() || char_is_line_ending(next_ch)) && (!prev_ch.is_whitespace() || char_is_line_ending(next_ch))
} }
WordMotionTarget::NextLongWordStart => { WordMotionTarget::NextLongWordStart | WordMotionTarget::PrevLongWordEnd => {
is_long_word_boundary(prev_ch, next_ch) is_long_word_boundary(prev_ch, next_ch)
&& (char_is_line_ending(next_ch) || !next_ch.is_whitespace()) && (char_is_line_ending(next_ch) || !next_ch.is_whitespace())
} }
@@ -487,6 +539,22 @@ fn reached_target(target: WordMotionTarget, prev_ch: char, next_ch: char) -> boo
is_long_word_boundary(prev_ch, next_ch) is_long_word_boundary(prev_ch, next_ch)
&& (!prev_ch.is_whitespace() || char_is_line_ending(next_ch)) && (!prev_ch.is_whitespace() || char_is_line_ending(next_ch))
} }
WordMotionTarget::NextSubWordStart => {
is_sub_word_boundary(prev_ch, next_ch, Direction::Forward)
&& (char_is_line_ending(next_ch) || !(next_ch.is_whitespace() || next_ch == '_'))
}
WordMotionTarget::PrevSubWordEnd => {
is_sub_word_boundary(prev_ch, next_ch, Direction::Backward)
&& (char_is_line_ending(next_ch) || !(next_ch.is_whitespace() || next_ch == '_'))
}
WordMotionTarget::NextSubWordEnd => {
is_sub_word_boundary(prev_ch, next_ch, Direction::Forward)
&& (!(prev_ch.is_whitespace() || prev_ch == '_') || char_is_line_ending(next_ch))
}
WordMotionTarget::PrevSubWordStart => {
is_sub_word_boundary(prev_ch, next_ch, Direction::Backward)
&& (!(prev_ch.is_whitespace() || prev_ch == '_') || char_is_line_ending(next_ch))
}
} }
} }
@@ -520,10 +588,10 @@ pub fn goto_treesitter_object(
let node = match dir { let node = match dir {
Direction::Forward => nodes Direction::Forward => nodes
.filter(|n| n.start_byte() > byte_pos) .filter(|n| n.start_byte() > byte_pos)
.min_by_key(|n| n.start_byte())?, .min_by_key(|n| (n.start_byte(), Reverse(n.end_byte())))?,
Direction::Backward => nodes Direction::Backward => nodes
.filter(|n| n.end_byte() < byte_pos) .filter(|n| n.end_byte() < byte_pos)
.max_by_key(|n| n.end_byte())?, .max_by_key(|n| (n.end_byte(), Reverse(n.start_byte())))?,
}; };
let len = slice.len_bytes(); let len = slice.len_bytes();
@@ -549,6 +617,80 @@ pub fn goto_treesitter_object(
last_range last_range
} }
fn find_parent_start(mut node: Node) -> Option<Node> {
let start = node.start_byte();
while node.start_byte() >= start || !node.is_named() {
node = node.parent()?;
}
Some(node)
}
pub fn move_parent_node_end(
syntax: &Syntax,
text: RopeSlice,
selection: Selection,
dir: Direction,
movement: Movement,
) -> Selection {
selection.transform(|range| {
let start_from = text.char_to_byte(range.from());
let start_to = text.char_to_byte(range.to());
let mut node = match syntax.named_descendant_for_byte_range(start_from, start_to) {
Some(node) => node,
None => {
log::debug!(
"no descendant found for byte range: {} - {}",
start_from,
start_to
);
return range;
}
};
let mut end_head = match dir {
// moving forward, we always want to move one past the end of the
// current node, so use the end byte of the current node, which is an exclusive
// end of the range
Direction::Forward => text.byte_to_char(node.end_byte()),
// moving backward, we want the cursor to land on the start char of
// the current node, or if it is already at the start of a node, to traverse up to
// the parent
Direction::Backward => {
let end_head = text.byte_to_char(node.start_byte());
// if we're already on the beginning, look up to the parent
if end_head == range.cursor(text) {
node = find_parent_start(node).unwrap_or(node);
text.byte_to_char(node.start_byte())
} else {
end_head
}
}
};
if movement == Movement::Move {
// preserve direction of original range
if range.direction() == Direction::Forward {
Range::new(end_head, end_head + 1)
} else {
Range::new(end_head + 1, end_head)
}
} else {
// if we end up with a forward range, then adjust it to be one past
// where we want
if end_head >= range.anchor {
end_head += 1;
}
Range::new(range.anchor, end_head)
}
})
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use ropey::Rope; use ropey::Rope;
@@ -931,6 +1073,178 @@ mod test {
} }
} }
#[test]
fn test_behaviour_when_moving_to_start_of_next_sub_words() {
let tests = [
(
"NextSubwordStart",
vec![
(1, Range::new(0, 0), Range::new(0, 4)),
(1, Range::new(4, 4), Range::new(4, 11)),
],
),
(
"next_subword_start",
vec![
(1, Range::new(0, 0), Range::new(0, 5)),
(1, Range::new(4, 4), Range::new(5, 13)),
],
),
(
"Next_Subword_Start",
vec![
(1, Range::new(0, 0), Range::new(0, 5)),
(1, Range::new(4, 4), Range::new(5, 13)),
],
),
(
"NEXT_SUBWORD_START",
vec![
(1, Range::new(0, 0), Range::new(0, 5)),
(1, Range::new(4, 4), Range::new(5, 13)),
],
),
(
"next subword start",
vec![
(1, Range::new(0, 0), Range::new(0, 5)),
(1, Range::new(4, 4), Range::new(5, 13)),
],
),
(
"Next Subword Start",
vec![
(1, Range::new(0, 0), Range::new(0, 5)),
(1, Range::new(4, 4), Range::new(5, 13)),
],
),
(
"NEXT SUBWORD START",
vec![
(1, Range::new(0, 0), Range::new(0, 5)),
(1, Range::new(4, 4), Range::new(5, 13)),
],
),
(
"next__subword__start",
vec![
(1, Range::new(0, 0), Range::new(0, 6)),
(1, Range::new(4, 4), Range::new(4, 6)),
(1, Range::new(5, 5), Range::new(6, 15)),
],
),
(
"Next__Subword__Start",
vec![
(1, Range::new(0, 0), Range::new(0, 6)),
(1, Range::new(4, 4), Range::new(4, 6)),
(1, Range::new(5, 5), Range::new(6, 15)),
],
),
(
"NEXT__SUBWORD__START",
vec![
(1, Range::new(0, 0), Range::new(0, 6)),
(1, Range::new(4, 4), Range::new(4, 6)),
(1, Range::new(5, 5), Range::new(6, 15)),
],
),
];
for (sample, scenario) in tests {
for (count, begin, expected_end) in scenario.into_iter() {
let range = move_next_sub_word_start(Rope::from(sample).slice(..), begin, count);
assert_eq!(range, expected_end, "Case failed: [{}]", sample);
}
}
}
#[test]
fn test_behaviour_when_moving_to_end_of_next_sub_words() {
let tests = [
(
"NextSubwordEnd",
vec![
(1, Range::new(0, 0), Range::new(0, 4)),
(1, Range::new(4, 4), Range::new(4, 11)),
],
),
(
"next subword end",
vec![
(1, Range::new(0, 0), Range::new(0, 4)),
(1, Range::new(4, 4), Range::new(4, 12)),
],
),
(
"Next Subword End",
vec![
(1, Range::new(0, 0), Range::new(0, 4)),
(1, Range::new(4, 4), Range::new(4, 12)),
],
),
(
"NEXT SUBWORD END",
vec![
(1, Range::new(0, 0), Range::new(0, 4)),
(1, Range::new(4, 4), Range::new(4, 12)),
],
),
(
"next_subword_end",
vec![
(1, Range::new(0, 0), Range::new(0, 4)),
(1, Range::new(4, 4), Range::new(4, 12)),
],
),
(
"Next_Subword_End",
vec![
(1, Range::new(0, 0), Range::new(0, 4)),
(1, Range::new(4, 4), Range::new(4, 12)),
],
),
(
"NEXT_SUBWORD_END",
vec![
(1, Range::new(0, 0), Range::new(0, 4)),
(1, Range::new(4, 4), Range::new(4, 12)),
],
),
(
"next__subword__end",
vec![
(1, Range::new(0, 0), Range::new(0, 4)),
(1, Range::new(4, 4), Range::new(4, 13)),
(1, Range::new(5, 5), Range::new(5, 13)),
],
),
(
"Next__Subword__End",
vec![
(1, Range::new(0, 0), Range::new(0, 4)),
(1, Range::new(4, 4), Range::new(4, 13)),
(1, Range::new(5, 5), Range::new(5, 13)),
],
),
(
"NEXT__SUBWORD__END",
vec![
(1, Range::new(0, 0), Range::new(0, 4)),
(1, Range::new(4, 4), Range::new(4, 13)),
(1, Range::new(5, 5), Range::new(5, 13)),
],
),
];
for (sample, scenario) in tests {
for (count, begin, expected_end) in scenario.into_iter() {
let range = move_next_sub_word_end(Rope::from(sample).slice(..), begin, count);
assert_eq!(range, expected_end, "Case failed: [{}]", sample);
}
}
}
#[test] #[test]
fn test_behaviour_when_moving_to_start_of_next_long_words() { fn test_behaviour_when_moving_to_start_of_next_long_words() {
let tests = [ let tests = [
@@ -1100,6 +1414,92 @@ mod test {
} }
} }
#[test]
fn test_behaviour_when_moving_to_start_of_previous_sub_words() {
let tests = [
(
"PrevSubwordEnd",
vec![
(1, Range::new(13, 13), Range::new(14, 11)),
(1, Range::new(11, 11), Range::new(11, 4)),
],
),
(
"prev subword end",
vec![
(1, Range::new(15, 15), Range::new(16, 13)),
(1, Range::new(12, 12), Range::new(13, 5)),
],
),
(
"Prev Subword End",
vec![
(1, Range::new(15, 15), Range::new(16, 13)),
(1, Range::new(12, 12), Range::new(13, 5)),
],
),
(
"PREV SUBWORD END",
vec![
(1, Range::new(15, 15), Range::new(16, 13)),
(1, Range::new(12, 12), Range::new(13, 5)),
],
),
(
"prev_subword_end",
vec![
(1, Range::new(15, 15), Range::new(16, 13)),
(1, Range::new(12, 12), Range::new(13, 5)),
],
),
(
"Prev_Subword_End",
vec![
(1, Range::new(15, 15), Range::new(16, 13)),
(1, Range::new(12, 12), Range::new(13, 5)),
],
),
(
"PREV_SUBWORD_END",
vec![
(1, Range::new(15, 15), Range::new(16, 13)),
(1, Range::new(12, 12), Range::new(13, 5)),
],
),
(
"prev__subword__end",
vec![
(1, Range::new(17, 17), Range::new(18, 15)),
(1, Range::new(13, 13), Range::new(14, 6)),
(1, Range::new(14, 14), Range::new(15, 6)),
],
),
(
"Prev__Subword__End",
vec![
(1, Range::new(17, 17), Range::new(18, 15)),
(1, Range::new(13, 13), Range::new(14, 6)),
(1, Range::new(14, 14), Range::new(15, 6)),
],
),
(
"PREV__SUBWORD__END",
vec![
(1, Range::new(17, 17), Range::new(18, 15)),
(1, Range::new(13, 13), Range::new(14, 6)),
(1, Range::new(14, 14), Range::new(15, 6)),
],
),
];
for (sample, scenario) in tests {
for (count, begin, expected_end) in scenario.into_iter() {
let range = move_prev_sub_word_start(Rope::from(sample).slice(..), begin, count);
assert_eq!(range, expected_end, "Case failed: [{}]", sample);
}
}
}
#[test] #[test]
fn test_behaviour_when_moving_to_start_of_previous_long_words() { fn test_behaviour_when_moving_to_start_of_previous_long_words() {
let tests = [ let tests = [
@@ -1363,6 +1763,92 @@ mod test {
} }
} }
#[test]
fn test_behaviour_when_moving_to_end_of_previous_sub_words() {
let tests = [
(
"PrevSubwordEnd",
vec![
(1, Range::new(13, 13), Range::new(14, 11)),
(1, Range::new(11, 11), Range::new(11, 4)),
],
),
(
"prev subword end",
vec![
(1, Range::new(15, 15), Range::new(16, 12)),
(1, Range::new(12, 12), Range::new(12, 4)),
],
),
(
"Prev Subword End",
vec![
(1, Range::new(15, 15), Range::new(16, 12)),
(1, Range::new(12, 12), Range::new(12, 4)),
],
),
(
"PREV SUBWORD END",
vec![
(1, Range::new(15, 15), Range::new(16, 12)),
(1, Range::new(12, 12), Range::new(12, 4)),
],
),
(
"prev_subword_end",
vec![
(1, Range::new(15, 15), Range::new(16, 12)),
(1, Range::new(12, 12), Range::new(12, 4)),
],
),
(
"Prev_Subword_End",
vec![
(1, Range::new(15, 15), Range::new(16, 12)),
(1, Range::new(12, 12), Range::new(12, 4)),
],
),
(
"PREV_SUBWORD_END",
vec![
(1, Range::new(15, 15), Range::new(16, 12)),
(1, Range::new(12, 12), Range::new(12, 4)),
],
),
(
"prev__subword__end",
vec![
(1, Range::new(17, 17), Range::new(18, 13)),
(1, Range::new(13, 13), Range::new(13, 4)),
(1, Range::new(14, 14), Range::new(15, 13)),
],
),
(
"Prev__Subword__End",
vec![
(1, Range::new(17, 17), Range::new(18, 13)),
(1, Range::new(13, 13), Range::new(13, 4)),
(1, Range::new(14, 14), Range::new(15, 13)),
],
),
(
"PREV__SUBWORD__END",
vec![
(1, Range::new(17, 17), Range::new(18, 13)),
(1, Range::new(13, 13), Range::new(13, 4)),
(1, Range::new(14, 14), Range::new(15, 13)),
],
),
];
for (sample, scenario) in tests {
for (count, begin, expected_end) in scenario.into_iter() {
let range = move_prev_sub_word_end(Rope::from(sample).slice(..), begin, count);
assert_eq!(range, expected_end, "Case failed: [{}]", sample);
}
}
}
#[test] #[test]
fn test_behaviour_when_moving_to_end_of_next_long_words() { fn test_behaviour_when_moving_to_end_of_next_long_words() {
let tests = [ let tests = [
@@ -1445,6 +1931,100 @@ mod test {
} }
} }
#[test]
fn test_behaviour_when_moving_to_end_of_prev_long_words() {
let tests = [
(
"Basic backward motion from the middle of a word",
vec![(1, Range::new(3, 3), Range::new(4, 0))],
),
("Starting from after boundary retreats the anchor",
vec![(1, Range::new(0, 9), Range::new(8, 0))],
),
(
"Jump to end of a word succeeded by whitespace",
vec![(1, Range::new(10, 10), Range::new(10, 4))],
),
(
" Jump to start of line from end of word preceded by whitespace",
vec![(1, Range::new(3, 4), Range::new(4, 0))],
),
("Previous anchor is irrelevant for backward motions",
vec![(1, Range::new(12, 5), Range::new(6, 0))]),
(
" Starting from whitespace moves to first space in sequence",
vec![(1, Range::new(0, 4), Range::new(4, 0))],
),
("Identifiers_with_underscores are considered a single word",
vec![(1, Range::new(0, 20), Range::new(20, 0))]),
(
"Jumping\n \nback through a newline selects whitespace",
vec![(1, Range::new(0, 13), Range::new(12, 8))],
),
(
"Jumping to start of word from the end selects the word",
vec![(1, Range::new(6, 7), Range::new(7, 0))],
),
(
"alphanumeric.!,and.?=punctuation are treated exactly the same",
vec![(1, Range::new(29, 30), Range::new(30, 0))],
),
(
"... ... punctuation and spaces behave as expected",
vec![
(1, Range::new(0, 10), Range::new(9, 3)),
(1, Range::new(10, 6), Range::new(7, 3)),
],
),
(".._.._ punctuation is joined by underscores into a single block",
vec![(1, Range::new(0, 6), Range::new(6, 0))]),
(
"Newlines\n\nare bridged seamlessly.",
vec![(1, Range::new(0, 10), Range::new(8, 0))],
),
(
"Jumping \n\n\n\n\nback from within a newline group selects previous block",
vec![(1, Range::new(0, 13), Range::new(11, 7))],
),
(
"Failed motions do not modify the range",
vec![(0, Range::new(3, 0), Range::new(3, 0))],
),
(
"Multiple motions at once resolve correctly",
vec![(3, Range::new(19, 19), Range::new(8, 0))],
),
(
"Excessive motions are performed partially",
vec![(999, Range::new(40, 40), Range::new(9, 0))],
),
(
"", // Edge case of moving backwards in empty string
vec![(1, Range::new(0, 0), Range::new(0, 0))],
),
(
"\n\n\n\n\n", // Edge case of moving backwards in all newlines
vec![(1, Range::new(5, 5), Range::new(0, 0))],
),
(" \n \nJumping back through alternated space blocks and newlines selects the space blocks",
vec![
(1, Range::new(0, 8), Range::new(7, 4)),
(1, Range::new(7, 4), Range::new(3, 0)),
]),
("ヒーリ..クス multibyte characters behave as normal characters, including when interacting with punctuation",
vec![
(1, Range::new(0, 8), Range::new(7, 0)),
]),
];
for (sample, scenario) in tests {
for (count, begin, expected_end) in scenario.into_iter() {
let range = move_prev_long_word_end(Rope::from(sample).slice(..), begin, count);
assert_eq!(range, expected_end, "Case failed: [{}]", sample);
}
}
}
#[test] #[test]
fn test_behaviour_when_moving_to_prev_paragraph_single() { fn test_behaviour_when_moving_to_prev_paragraph_single() {
let tests = [ let tests = [

View File

@@ -1,76 +1,137 @@
use crate::{Range, RopeSlice, Selection, Syntax}; use crate::{movement::Direction, syntax::TreeCursor, Range, RopeSlice, Selection, Syntax};
use tree_sitter::Node;
pub fn expand_selection(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection { pub fn expand_selection(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection {
select_node_impl(syntax, text, selection, |mut node, from, to| { let cursor = &mut syntax.walk();
while node.start_byte() == from && node.end_byte() == to {
node = node.parent()?; selection.transform(|range| {
let from = text.char_to_byte(range.from());
let to = text.char_to_byte(range.to());
let byte_range = from..to;
cursor.reset_to_byte_range(from, to);
while cursor.node().byte_range() == byte_range {
if !cursor.goto_parent() {
break;
}
} }
Some(node)
let node = cursor.node();
let from = text.byte_to_char(node.start_byte());
let to = text.byte_to_char(node.end_byte());
Range::new(to, from).with_direction(range.direction())
}) })
} }
pub fn shrink_selection(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection { pub fn shrink_selection(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection {
select_node_impl(syntax, text, selection, |descendant, _from, _to| { select_node_impl(
descendant.child(0).or(Some(descendant)) syntax,
text,
selection,
|cursor| {
cursor.goto_first_child();
},
None,
)
}
pub fn select_next_sibling(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection {
select_node_impl(
syntax,
text,
selection,
|cursor| {
while !cursor.goto_next_sibling() {
if !cursor.goto_parent() {
break;
}
}
},
Some(Direction::Forward),
)
}
pub fn select_all_siblings(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection {
selection.transform_iter(|range| {
let mut cursor = syntax.walk();
let (from, to) = range.into_byte_range(text);
cursor.reset_to_byte_range(from, to);
if !cursor.goto_parent_with(|parent| parent.child_count() > 1) {
return vec![range].into_iter();
}
select_children(&mut cursor, text, range).into_iter()
}) })
} }
pub fn select_sibling<F>( pub fn select_all_children(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection {
syntax: &Syntax, selection.transform_iter(|range| {
let mut cursor = syntax.walk();
let (from, to) = range.into_byte_range(text);
cursor.reset_to_byte_range(from, to);
select_children(&mut cursor, text, range).into_iter()
})
}
fn select_children<'n>(
cursor: &'n mut TreeCursor<'n>,
text: RopeSlice, text: RopeSlice,
selection: Selection, range: Range,
sibling_fn: &F, ) -> Vec<Range> {
) -> Selection let children = cursor
where .named_children()
F: Fn(Node) -> Option<Node>, .map(|child| Range::from_node(child, text, range.direction()))
{ .collect::<Vec<_>>();
select_node_impl(syntax, text, selection, |descendant, _from, _to| {
find_sibling_recursive(descendant, sibling_fn) if !children.is_empty() {
}) children
} else {
vec![range]
}
} }
fn find_sibling_recursive<F>(node: Node, sibling_fn: F) -> Option<Node> pub fn select_prev_sibling(syntax: &Syntax, text: RopeSlice, selection: Selection) -> Selection {
where select_node_impl(
F: Fn(Node) -> Option<Node>, syntax,
{ text,
sibling_fn(node).or_else(|| { selection,
node.parent() |cursor| {
.and_then(|node| find_sibling_recursive(node, sibling_fn)) while !cursor.goto_prev_sibling() {
}) if !cursor.goto_parent() {
break;
}
}
},
Some(Direction::Backward),
)
} }
fn select_node_impl<F>( fn select_node_impl<F>(
syntax: &Syntax, syntax: &Syntax,
text: RopeSlice, text: RopeSlice,
selection: Selection, selection: Selection,
select_fn: F, motion: F,
direction: Option<Direction>,
) -> Selection ) -> Selection
where where
F: Fn(Node, usize, usize) -> Option<Node>, F: Fn(&mut TreeCursor),
{ {
let tree = syntax.tree(); let cursor = &mut syntax.walk();
selection.transform(|range| { selection.transform(|range| {
let from = text.char_to_byte(range.from()); let from = text.char_to_byte(range.from());
let to = text.char_to_byte(range.to()); let to = text.char_to_byte(range.to());
let node = match tree cursor.reset_to_byte_range(from, to);
.root_node()
.descendant_for_byte_range(from, to)
.and_then(|node| select_fn(node, from, to))
{
Some(node) => node,
None => return range,
};
motion(cursor);
let node = cursor.node();
let from = text.byte_to_char(node.start_byte()); let from = text.byte_to_char(node.start_byte());
let to = text.byte_to_char(node.end_byte()); let to = text.byte_to_char(node.end_byte());
if range.head < range.anchor { Range::new(from, to).with_direction(direction.unwrap_or_else(|| range.direction()))
Range::new(to, from)
} else {
Range::new(from, to)
}
}) })
} }

View File

@@ -1,164 +0,0 @@
use etcetera::home_dir;
use std::path::{Component, Path, PathBuf};
/// Replaces users home directory from `path` with tilde `~` if the directory
/// is available, otherwise returns the path unchanged.
pub fn fold_home_dir(path: &Path) -> PathBuf {
if let Ok(home) = home_dir() {
if let Ok(stripped) = path.strip_prefix(&home) {
return PathBuf::from("~").join(stripped);
}
}
path.to_path_buf()
}
/// Expands tilde `~` into users home directory if available, otherwise returns the path
/// unchanged. The tilde will only be expanded when present as the first component of the path
/// and only slash follows it.
pub fn expand_tilde(path: &Path) -> PathBuf {
let mut components = path.components().peekable();
if let Some(Component::Normal(c)) = components.peek() {
if c == &"~" {
if let Ok(home) = home_dir() {
// it's ok to unwrap, the path starts with `~`
return home.join(path.strip_prefix("~").unwrap());
}
}
}
path.to_path_buf()
}
/// Normalize a path, removing things like `.` and `..`.
///
/// CAUTION: This does not resolve symlinks (unlike
/// [`std::fs::canonicalize`]). This may cause incorrect or surprising
/// behavior at times. This should be used carefully. Unfortunately,
/// [`std::fs::canonicalize`] can be hard to use correctly, since it can often
/// fail, or on Windows returns annoying device paths. This is a problem Cargo
/// needs to improve on.
/// Copied from cargo: <https://github.com/rust-lang/cargo/blob/070e459c2d8b79c5b2ac5218064e7603329c92ae/crates/cargo-util/src/paths.rs#L81>
pub fn get_normalized_path(path: &Path) -> PathBuf {
// normalization strategy is to canonicalize first ancestor path that exists (i.e., canonicalize as much as possible),
// then run handrolled normalization on the non-existent remainder
let (base, path) = path
.ancestors()
.find_map(|base| {
let canonicalized_base = dunce::canonicalize(base).ok()?;
let remainder = path.strip_prefix(base).ok()?.into();
Some((canonicalized_base, remainder))
})
.unwrap_or_else(|| (PathBuf::new(), PathBuf::from(path)));
if path.as_os_str().is_empty() {
return base;
}
let mut components = path.components().peekable();
let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() {
components.next();
PathBuf::from(c.as_os_str())
} else {
PathBuf::new()
};
for component in components {
match component {
Component::Prefix(..) => unreachable!(),
Component::RootDir => {
ret.push(component.as_os_str());
}
Component::CurDir => {}
Component::ParentDir => {
ret.pop();
}
Component::Normal(c) => {
ret.push(c);
}
}
}
base.join(ret)
}
/// Returns the canonical, absolute form of a path with all intermediate components normalized.
///
/// This function is used instead of `std::fs::canonicalize` because we don't want to verify
/// here if the path exists, just normalize it's components.
pub fn get_canonicalized_path(path: &Path) -> std::io::Result<PathBuf> {
let path = expand_tilde(path);
let path = if path.is_relative() {
std::env::current_dir().map(|current_dir| current_dir.join(path))?
} else {
path
};
Ok(get_normalized_path(path.as_path()))
}
pub fn get_relative_path(path: &Path) -> PathBuf {
let path = PathBuf::from(path);
let path = if path.is_absolute() {
let cwdir = std::env::current_dir()
.map(|path| get_normalized_path(&path))
.expect("couldn't determine current directory");
get_normalized_path(&path)
.strip_prefix(cwdir)
.map(PathBuf::from)
.unwrap_or(path)
} else {
path
};
fold_home_dir(&path)
}
/// Returns a truncated filepath where the basepart of the path is reduced to the first
/// char of the folder and the whole filename appended.
///
/// Also strip the current working directory from the beginning of the path.
/// Note that this function does not check if the truncated path is unambiguous.
///
/// ```
/// use helix_core::path::get_truncated_path;
/// use std::path::Path;
///
/// assert_eq!(
/// get_truncated_path("/home/cnorris/documents/jokes.txt").as_path(),
/// Path::new("/h/c/d/jokes.txt")
/// );
/// assert_eq!(
/// get_truncated_path("jokes.txt").as_path(),
/// Path::new("jokes.txt")
/// );
/// assert_eq!(
/// get_truncated_path("/jokes.txt").as_path(),
/// Path::new("/jokes.txt")
/// );
/// assert_eq!(
/// get_truncated_path("/h/c/d/jokes.txt").as_path(),
/// Path::new("/h/c/d/jokes.txt")
/// );
/// assert_eq!(get_truncated_path("").as_path(), Path::new(""));
/// ```
///
pub fn get_truncated_path<P: AsRef<Path>>(path: P) -> PathBuf {
let cwd = std::env::current_dir().unwrap_or_default();
let path = path
.as_ref()
.strip_prefix(cwd)
.unwrap_or_else(|_| path.as_ref());
let file = path.file_name().unwrap_or_default();
let base = path.parent().unwrap_or_else(|| Path::new(""));
let mut ret = PathBuf::new();
for d in base {
ret.push(
d.to_string_lossy()
.chars()
.next()
.unwrap_or_default()
.to_string(),
);
}
ret.push(file);
ret
}

View File

@@ -1,4 +1,8 @@
use std::{borrow::Cow, cmp::Ordering}; use std::{
borrow::Cow,
cmp::Ordering,
ops::{Add, AddAssign, Sub, SubAssign},
};
use crate::{ use crate::{
chars::char_is_line_ending, chars::char_is_line_ending,
@@ -16,6 +20,38 @@ pub struct Position {
pub col: usize, pub col: usize,
} }
impl AddAssign for Position {
fn add_assign(&mut self, rhs: Self) {
self.row += rhs.row;
self.col += rhs.col;
}
}
impl SubAssign for Position {
fn sub_assign(&mut self, rhs: Self) {
self.row -= rhs.row;
self.col -= rhs.col;
}
}
impl Sub for Position {
type Output = Position;
fn sub(mut self, rhs: Self) -> Self::Output {
self -= rhs;
self
}
}
impl Add for Position {
type Output = Position;
fn add(mut self, rhs: Self) -> Self::Output {
self += rhs;
self
}
}
impl Position { impl Position {
pub const fn new(row: usize, col: usize) -> Self { pub const fn new(row: usize, col: usize) -> Self {
Self { row, col } Self { row, col }
@@ -121,22 +157,31 @@ pub fn visual_offset_from_block(
annotations: &TextAnnotations, annotations: &TextAnnotations,
) -> (Position, usize) { ) -> (Position, usize) {
let mut last_pos = Position::default(); let mut last_pos = Position::default();
let (formatter, block_start) = let mut formatter =
DocumentFormatter::new_at_prev_checkpoint(text, text_fmt, annotations, anchor); DocumentFormatter::new_at_prev_checkpoint(text, text_fmt, annotations, anchor);
let mut char_pos = block_start; let block_start = formatter.next_char_pos();
for (grapheme, vpos) in formatter { while let Some(grapheme) = formatter.next() {
last_pos = vpos; last_pos = grapheme.visual_pos;
char_pos += grapheme.doc_chars(); if formatter.next_char_pos() > pos {
return (grapheme.visual_pos, block_start);
if char_pos > pos {
return (last_pos, block_start);
} }
} }
(last_pos, block_start) (last_pos, block_start)
} }
/// Returns the height of the given text when softwrapping
pub fn softwrapped_dimensions(text: RopeSlice, text_fmt: &TextFormat) -> (usize, u16) {
let last_pos =
visual_offset_from_block(text, 0, usize::MAX, text_fmt, &TextAnnotations::default()).0;
if last_pos.row == 0 {
(1, last_pos.col as u16)
} else {
(last_pos.row + 1, text_fmt.viewport_width)
}
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)] #[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum VisualOffsetError { pub enum VisualOffsetError {
PosBeforeAnchorRow, PosBeforeAnchorRow,
@@ -153,22 +198,21 @@ pub fn visual_offset_from_anchor(
annotations: &TextAnnotations, annotations: &TextAnnotations,
max_rows: usize, max_rows: usize,
) -> Result<(Position, usize), VisualOffsetError> { ) -> Result<(Position, usize), VisualOffsetError> {
let (formatter, block_start) = let mut formatter =
DocumentFormatter::new_at_prev_checkpoint(text, text_fmt, annotations, anchor); DocumentFormatter::new_at_prev_checkpoint(text, text_fmt, annotations, anchor);
let mut char_pos = block_start;
let mut anchor_line = None; let mut anchor_line = None;
let mut found_pos = None; let mut found_pos = None;
let mut last_pos = Position::default(); let mut last_pos = Position::default();
let block_start = formatter.next_char_pos();
if pos < block_start { if pos < block_start {
return Err(VisualOffsetError::PosBeforeAnchorRow); return Err(VisualOffsetError::PosBeforeAnchorRow);
} }
for (grapheme, vpos) in formatter { while let Some(grapheme) = formatter.next() {
last_pos = vpos; last_pos = grapheme.visual_pos;
char_pos += grapheme.doc_chars();
if char_pos > pos { if formatter.next_char_pos() > pos {
if let Some(anchor_line) = anchor_line { if let Some(anchor_line) = anchor_line {
last_pos.row -= anchor_line; last_pos.row -= anchor_line;
return Ok((last_pos, block_start)); return Ok((last_pos, block_start));
@@ -176,7 +220,7 @@ pub fn visual_offset_from_anchor(
found_pos = Some(last_pos); found_pos = Some(last_pos);
} }
} }
if char_pos > anchor && anchor_line.is_none() { if formatter.next_char_pos() > anchor && anchor_line.is_none() {
if let Some(mut found_pos) = found_pos { if let Some(mut found_pos) = found_pos {
return if found_pos.row == last_pos.row { return if found_pos.row == last_pos.row {
found_pos.row = 0; found_pos.row = 0;
@@ -190,7 +234,7 @@ pub fn visual_offset_from_anchor(
} }
if let Some(anchor_line) = anchor_line { if let Some(anchor_line) = anchor_line {
if vpos.row >= anchor_line + max_rows { if grapheme.visual_pos.row >= anchor_line + max_rows {
return Err(VisualOffsetError::PosAfterMaxRow); return Err(VisualOffsetError::PosAfterMaxRow);
} }
} }
@@ -368,39 +412,43 @@ pub fn char_idx_at_visual_block_offset(
text_fmt: &TextFormat, text_fmt: &TextFormat,
annotations: &TextAnnotations, annotations: &TextAnnotations,
) -> (usize, usize) { ) -> (usize, usize) {
let (formatter, mut char_idx) = let mut formatter =
DocumentFormatter::new_at_prev_checkpoint(text, text_fmt, annotations, anchor); DocumentFormatter::new_at_prev_checkpoint(text, text_fmt, annotations, anchor);
let mut last_char_idx = char_idx; let mut last_char_idx = formatter.next_char_pos();
let mut last_char_idx_on_line = None; let mut found_non_virtual_on_row = false;
let mut last_row = 0; let mut last_row = 0;
for (grapheme, grapheme_pos) in formatter { for grapheme in &mut formatter {
match grapheme_pos.row.cmp(&row) { match grapheme.visual_pos.row.cmp(&row) {
Ordering::Equal => { Ordering::Equal => {
if grapheme_pos.col + grapheme.width() > column { if grapheme.visual_pos.col + grapheme.width() > column {
if !grapheme.is_virtual() { if !grapheme.is_virtual() {
return (char_idx, 0); return (grapheme.char_idx, 0);
} else if let Some(char_idx) = last_char_idx_on_line { } else if found_non_virtual_on_row {
return (char_idx, 0); return (last_char_idx, 0);
} }
} else if !grapheme.is_virtual() { } else if !grapheme.is_virtual() {
last_char_idx_on_line = Some(char_idx) found_non_virtual_on_row = true;
last_char_idx = grapheme.char_idx;
} }
} }
Ordering::Greater if found_non_virtual_on_row => return (last_char_idx, 0),
Ordering::Greater => return (last_char_idx, row - last_row), Ordering::Greater => return (last_char_idx, row - last_row),
_ => (), Ordering::Less => {
if !grapheme.is_virtual() {
last_row = grapheme.visual_pos.row;
last_char_idx = grapheme.char_idx;
}
}
} }
last_char_idx = char_idx;
last_row = grapheme_pos.row;
char_idx += grapheme.doc_chars();
} }
(char_idx, 0) (formatter.next_char_pos(), 0)
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*; use super::*;
use crate::text_annotations::InlineAnnotation;
use crate::Rope; use crate::Rope;
#[test] #[test]
@@ -761,6 +809,30 @@ mod test {
assert_eq!(pos_at_visual_coords(slice, (10, 10).into(), 4), 0); assert_eq!(pos_at_visual_coords(slice, (10, 10).into(), 4), 0);
} }
#[test]
fn test_char_idx_at_visual_row_offset_inline_annotation() {
let text = Rope::from("foo\nbar");
let slice = text.slice(..);
let mut text_fmt = TextFormat::default();
let annotations = [InlineAnnotation {
text: "x".repeat(100).into(),
char_idx: 3,
}];
text_fmt.soft_wrap = true;
assert_eq!(
char_idx_at_visual_offset(
slice,
0,
1,
0,
&text_fmt,
TextAnnotations::default().add_inline_annotations(&annotations, None)
),
(2, 1)
);
}
#[test] #[test]
fn test_char_idx_at_visual_row_offset() { fn test_char_idx_at_visual_row_offset() {
let text = Rope::from("ḧëḷḷö\nẅöṛḷḋ\nfoo"); let text = Rope::from("ḧëḷḷö\nẅöṛḷḋ\nfoo");

View File

@@ -1,81 +0,0 @@
use std::collections::HashMap;
#[derive(Debug)]
pub struct Register {
name: char,
values: Vec<String>,
}
impl Register {
pub const fn new(name: char) -> Self {
Self {
name,
values: Vec::new(),
}
}
pub fn new_with_values(name: char, values: Vec<String>) -> Self {
Self { name, values }
}
pub const fn name(&self) -> char {
self.name
}
pub fn read(&self) -> &[String] {
&self.values
}
pub fn write(&mut self, values: Vec<String>) {
self.values = values;
}
pub fn push(&mut self, value: String) {
self.values.push(value);
}
}
/// Currently just wraps a `HashMap` of `Register`s
#[derive(Debug, Default)]
pub struct Registers {
inner: HashMap<char, Register>,
}
impl Registers {
pub fn get(&self, name: char) -> Option<&Register> {
self.inner.get(&name)
}
pub fn read(&self, name: char) -> Option<&[String]> {
self.get(name).map(|reg| reg.read())
}
pub fn write(&mut self, name: char, values: Vec<String>) {
if name != '_' {
self.inner
.insert(name, Register::new_with_values(name, values));
}
}
pub fn push(&mut self, name: char, value: String) {
if name != '_' {
if let Some(r) = self.inner.get_mut(&name) {
r.push(value);
} else {
self.write(name, vec![value]);
}
}
}
pub fn first(&self, name: char) -> Option<&String> {
self.read(name).and_then(|entries| entries.first())
}
pub fn last(&self, name: char) -> Option<&String> {
self.read(name).and_then(|entries| entries.last())
}
pub fn inner(&self) -> &HashMap<char, Register> {
&self.inner
}
}

View File

@@ -0,0 +1,37 @@
use std::io;
use ropey::iter::Chunks;
use ropey::RopeSlice;
pub struct RopeReader<'a> {
current_chunk: &'a [u8],
chunks: Chunks<'a>,
}
impl<'a> RopeReader<'a> {
pub fn new(rope: RopeSlice<'a>) -> RopeReader<'a> {
RopeReader {
current_chunk: &[],
chunks: rope.chunks(),
}
}
}
impl io::Read for RopeReader<'_> {
fn read(&mut self, mut buf: &mut [u8]) -> io::Result<usize> {
let buf_len = buf.len();
loop {
let read_bytes = self.current_chunk.read(buf)?;
buf = &mut buf[read_bytes..];
if buf.is_empty() {
return Ok(buf_len);
}
if let Some(next_chunk) = self.chunks.next() {
self.current_chunk = next_chunk.as_bytes();
} else {
return Ok(buf_len - buf.len());
}
}
}
}

View File

@@ -7,11 +7,15 @@ use crate::{
ensure_grapheme_boundary_next, ensure_grapheme_boundary_prev, next_grapheme_boundary, ensure_grapheme_boundary_next, ensure_grapheme_boundary_prev, next_grapheme_boundary,
prev_grapheme_boundary, prev_grapheme_boundary,
}, },
line_ending::get_line_ending,
movement::Direction, movement::Direction,
Assoc, ChangeSet, RopeGraphemes, RopeSlice, Assoc, ChangeSet, RopeGraphemes, RopeSlice,
}; };
use helix_stdx::range::is_subset;
use helix_stdx::rope::{self, RopeSliceExt};
use smallvec::{smallvec, SmallVec}; use smallvec::{smallvec, SmallVec};
use std::borrow::Cow; use std::{borrow::Cow, iter, slice};
use tree_sitter::Node;
/// A single selection range. /// A single selection range.
/// ///
@@ -71,6 +75,12 @@ impl Range {
Self::new(head, head) Self::new(head, head)
} }
pub fn from_node(node: Node, text: RopeSlice, direction: Direction) -> Self {
let from = text.byte_to_char(node.start_byte());
let to = text.byte_to_char(node.end_byte());
Range::new(from, to).with_direction(direction)
}
/// Start of the range. /// Start of the range.
#[inline] #[inline]
#[must_use] #[must_use]
@@ -113,7 +123,7 @@ impl Range {
} }
/// `Direction::Backward` when head < anchor. /// `Direction::Backward` when head < anchor.
/// `Direction::Backward` otherwise. /// `Direction::Forward` otherwise.
#[inline] #[inline]
#[must_use] #[must_use]
pub fn direction(&self) -> Direction { pub fn direction(&self) -> Direction {
@@ -161,34 +171,35 @@ impl Range {
self.from() <= pos && pos < self.to() self.from() <= pos && pos < self.to()
} }
/// Map a range through a set of changes. Returns a new range representing the same position /// Map a range through a set of changes. Returns a new range representing
/// after the changes are applied. /// the same position after the changes are applied. Note that this
pub fn map(self, changes: &ChangeSet) -> Self { /// function runs in O(N) (N is number of changes) and can therefore
/// cause performance problems if run for a large number of ranges as the
/// complexity is then O(MN) (for multicuror M=N usually). Instead use
/// [Selection::map] or [ChangeSet::update_positions].
pub fn map(mut self, changes: &ChangeSet) -> Self {
use std::cmp::Ordering; use std::cmp::Ordering;
let (anchor, head) = match self.anchor.cmp(&self.head) { if changes.is_empty() {
Ordering::Equal => ( return self;
changes.map_pos(self.anchor, Assoc::After),
changes.map_pos(self.head, Assoc::After),
),
Ordering::Less => (
changes.map_pos(self.anchor, Assoc::After),
changes.map_pos(self.head, Assoc::Before),
),
Ordering::Greater => (
changes.map_pos(self.anchor, Assoc::Before),
changes.map_pos(self.head, Assoc::After),
),
};
// We want to return a new `Range` with `horiz == None` every time,
// even if the anchor and head haven't changed, because we don't
// know if the *visual* position hasn't changed due to
// character-width or grapheme changes earlier in the text.
Self {
anchor,
head,
old_visual_position: None,
} }
let positions_to_map = match self.anchor.cmp(&self.head) {
Ordering::Equal => [
(&mut self.anchor, Assoc::AfterSticky),
(&mut self.head, Assoc::AfterSticky),
],
Ordering::Less => [
(&mut self.anchor, Assoc::AfterSticky),
(&mut self.head, Assoc::BeforeSticky),
],
Ordering::Greater => [
(&mut self.head, Assoc::AfterSticky),
(&mut self.anchor, Assoc::BeforeSticky),
],
};
changes.update_positions(positions_to_map.into_iter());
self.old_visual_position = None;
self
} }
/// Extend the range to cover at least `from` `to`. /// Extend the range to cover at least `from` `to`.
@@ -373,6 +384,12 @@ impl Range {
let second = graphemes.next(); let second = graphemes.next();
first.is_some() && second.is_none() first.is_some() && second.is_none()
} }
/// Converts this char range into an in order byte range, discarding
/// direction.
pub fn into_byte_range(&self, text: RopeSlice) -> (usize, usize) {
(text.char_to_byte(self.from()), text.char_to_byte(self.to()))
}
} }
impl From<(usize, usize)> for Range { impl From<(usize, usize)> for Range {
@@ -385,6 +402,15 @@ impl From<(usize, usize)> for Range {
} }
} }
impl From<Range> for helix_stdx::Range {
fn from(range: Range) -> Self {
Self {
start: range.from(),
end: range.to(),
}
}
}
/// A selection consists of one or more selection ranges. /// A selection consists of one or more selection ranges.
/// invariant: A selection can never be empty (always contains at least primary range). /// invariant: A selection can never be empty (always contains at least primary range).
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
@@ -451,23 +477,56 @@ impl Selection {
/// Map selections over a set of changes. Useful for adjusting the selection position after /// Map selections over a set of changes. Useful for adjusting the selection position after
/// applying changes to a document. /// applying changes to a document.
pub fn map(self, changes: &ChangeSet) -> Self { pub fn map(self, changes: &ChangeSet) -> Self {
self.map_no_normalize(changes).normalize()
}
/// Map selections over a set of changes. Useful for adjusting the selection position after
/// applying changes to a document. Doesn't normalize the selection
pub fn map_no_normalize(mut self, changes: &ChangeSet) -> Self {
if changes.is_empty() { if changes.is_empty() {
return self; return self;
} }
Self::new( let positions_to_map = self.ranges.iter_mut().flat_map(|range| {
self.ranges use std::cmp::Ordering;
.into_iter() range.old_visual_position = None;
.map(|range| range.map(changes)) match range.anchor.cmp(&range.head) {
.collect(), Ordering::Equal => [
self.primary_index, (&mut range.anchor, Assoc::AfterSticky),
) (&mut range.head, Assoc::AfterSticky),
],
Ordering::Less => [
(&mut range.anchor, Assoc::AfterSticky),
(&mut range.head, Assoc::BeforeSticky),
],
Ordering::Greater => [
(&mut range.head, Assoc::AfterSticky),
(&mut range.anchor, Assoc::BeforeSticky),
],
}
});
changes.update_positions(positions_to_map);
self
} }
pub fn ranges(&self) -> &[Range] { pub fn ranges(&self) -> &[Range] {
&self.ranges &self.ranges
} }
/// Returns an iterator over the line ranges of each range in the selection.
///
/// Adjacent and overlapping line ranges of the [Range]s in the selection are merged.
pub fn line_ranges<'a>(&'a self, text: RopeSlice<'a>) -> LineRangeIter<'a> {
LineRangeIter {
ranges: self.ranges.iter().peekable(),
text,
}
}
pub fn range_bounds(&self) -> impl Iterator<Item = helix_stdx::Range> + '_ {
self.ranges.iter().map(|&range| range.into())
}
pub fn primary_index(&self) -> usize { pub fn primary_index(&self) -> usize {
self.primary_index self.primary_index
} }
@@ -496,7 +555,12 @@ impl Selection {
} }
/// Normalizes a `Selection`. /// Normalizes a `Selection`.
///
/// Ranges are sorted by [Range::from], with overlapping ranges merged.
fn normalize(mut self) -> Self { fn normalize(mut self) -> Self {
if self.len() < 2 {
return self;
}
let mut primary = self.ranges[self.primary_index]; let mut primary = self.ranges[self.primary_index];
self.ranges.sort_unstable_by_key(Range::from); self.ranges.sort_unstable_by_key(Range::from);
@@ -522,7 +586,14 @@ impl Selection {
self self
} }
// Merges all ranges that are consecutive /// Replaces ranges with one spanning from first to last range.
pub fn merge_ranges(self) -> Self {
let first = self.ranges.first().unwrap();
let last = self.ranges.last().unwrap();
Selection::new(smallvec![first.merge(*last)], 0)
}
/// Merges all ranges that are consecutive.
pub fn merge_consecutive_ranges(mut self) -> Self { pub fn merge_consecutive_ranges(mut self) -> Self {
let mut primary = self.ranges[self.primary_index]; let mut primary = self.ranges[self.primary_index];
@@ -554,17 +625,12 @@ impl Selection {
assert!(!ranges.is_empty()); assert!(!ranges.is_empty());
debug_assert!(primary_index < ranges.len()); debug_assert!(primary_index < ranges.len());
let mut selection = Self { let selection = Self {
ranges, ranges,
primary_index, primary_index,
}; };
if selection.ranges.len() > 1 { selection.normalize()
// TODO: only normalize if needed (any ranges out of order)
selection = selection.normalize();
}
selection
} }
/// Takes a closure and maps each `Range` over the closure. /// Takes a closure and maps each `Range` over the closure.
@@ -605,11 +671,19 @@ impl Selection {
self.transform(|range| Range::point(range.cursor(text))) self.transform(|range| Range::point(range.cursor(text)))
} }
pub fn fragments<'a>(&'a self, text: RopeSlice<'a>) -> impl Iterator<Item = Cow<str>> + 'a { pub fn fragments<'a>(
&'a self,
text: RopeSlice<'a>,
) -> impl DoubleEndedIterator<Item = Cow<'a, str>> + ExactSizeIterator<Item = Cow<'a, str>>
{
self.ranges.iter().map(move |range| range.fragment(text)) self.ranges.iter().map(move |range| range.fragment(text))
} }
pub fn slices<'a>(&'a self, text: RopeSlice<'a>) -> impl Iterator<Item = RopeSlice> + 'a { pub fn slices<'a>(
&'a self,
text: RopeSlice<'a>,
) -> impl DoubleEndedIterator<Item = RopeSlice<'a>> + ExactSizeIterator<Item = RopeSlice<'a>> + 'a
{
self.ranges.iter().map(move |range| range.slice(text)) self.ranges.iter().map(move |range| range.slice(text))
} }
@@ -623,32 +697,9 @@ impl Selection {
self.ranges.len() self.ranges.len()
} }
// returns true if self ⊇ other /// returns true if self ⊇ other
pub fn contains(&self, other: &Selection) -> bool { pub fn contains(&self, other: &Selection) -> bool {
let (mut iter_self, mut iter_other) = (self.iter(), other.iter()); is_subset::<true>(self.range_bounds(), other.range_bounds())
let (mut ele_self, mut ele_other) = (iter_self.next(), iter_other.next());
loop {
match (ele_self, ele_other) {
(Some(ra), Some(rb)) => {
if !ra.contains_range(rb) {
// `self` doesn't contain next element from `other`, advance `self`, we need to match all from `other`
ele_self = iter_self.next();
} else {
// matched element from `other`, advance `other`
ele_other = iter_other.next();
};
}
(None, Some(_)) => {
// exhausted `self`, we can't match the reminder of `other`
return false;
}
(_, None) => {
// no elements from `other` left to match, `self` contains `other`
return true;
}
}
}
} }
} }
@@ -670,17 +721,53 @@ impl IntoIterator for Selection {
} }
} }
impl From<Range> for Selection {
fn from(range: Range) -> Self {
Self {
ranges: smallvec![range],
primary_index: 0,
}
}
}
pub struct LineRangeIter<'a> {
ranges: iter::Peekable<slice::Iter<'a, Range>>,
text: RopeSlice<'a>,
}
impl Iterator for LineRangeIter<'_> {
type Item = (usize, usize);
fn next(&mut self) -> Option<Self::Item> {
let (start, mut end) = self.ranges.next()?.line_range(self.text);
while let Some((next_start, next_end)) =
self.ranges.peek().map(|range| range.line_range(self.text))
{
// Merge overlapping and adjacent ranges.
// This subtraction cannot underflow because the ranges are sorted.
if next_start - end <= 1 {
end = next_end;
self.ranges.next();
} else {
break;
}
}
Some((start, end))
}
}
// TODO: checkSelection -> check if valid for doc length && sorted // TODO: checkSelection -> check if valid for doc length && sorted
pub fn keep_or_remove_matches( pub fn keep_or_remove_matches(
text: RopeSlice, text: RopeSlice,
selection: &Selection, selection: &Selection,
regex: &crate::regex::Regex, regex: &rope::Regex,
remove: bool, remove: bool,
) -> Option<Selection> { ) -> Option<Selection> {
let result: SmallVec<_> = selection let result: SmallVec<_> = selection
.iter() .iter()
.filter(|range| regex.is_match(&range.fragment(text)) ^ remove) .filter(|range| regex.is_match(text.regex_input_at(range.from()..range.to())) ^ remove)
.copied() .copied()
.collect(); .collect();
@@ -691,25 +778,20 @@ pub fn keep_or_remove_matches(
None None
} }
// TODO: support to split on capture #N instead of whole match
pub fn select_on_matches( pub fn select_on_matches(
text: RopeSlice, text: RopeSlice,
selection: &Selection, selection: &Selection,
regex: &crate::regex::Regex, regex: &rope::Regex,
) -> Option<Selection> { ) -> Option<Selection> {
let mut result = SmallVec::with_capacity(selection.len()); let mut result = SmallVec::with_capacity(selection.len());
for sel in selection { for sel in selection {
// TODO: can't avoid occasional allocations since Regex can't operate on chunks yet for mat in regex.find_iter(text.regex_input_at(sel.from()..sel.to())) {
let fragment = sel.fragment(text);
let sel_start = sel.from();
let start_byte = text.char_to_byte(sel_start);
for mat in regex.find_iter(&fragment) {
// TODO: retain range direction // TODO: retain range direction
let start = text.byte_to_char(start_byte + mat.start()); let start = text.byte_to_char(mat.start());
let end = text.byte_to_char(start_byte + mat.end()); let end = text.byte_to_char(mat.end());
let range = Range::new(start, end); let range = Range::new(start, end);
// Make sure the match is not right outside of the selection. // Make sure the match is not right outside of the selection.
@@ -728,12 +810,7 @@ pub fn select_on_matches(
None None
} }
// TODO: support to split on capture #N instead of whole match pub fn split_on_newline(text: RopeSlice, selection: &Selection) -> Selection {
pub fn split_on_matches(
text: RopeSlice,
selection: &Selection,
regex: &crate::regex::Regex,
) -> Selection {
let mut result = SmallVec::with_capacity(selection.len()); let mut result = SmallVec::with_capacity(selection.len());
for sel in selection { for sel in selection {
@@ -743,21 +820,49 @@ pub fn split_on_matches(
continue; continue;
} }
// TODO: can't avoid occasional allocations since Regex can't operate on chunks yet
let fragment = sel.fragment(text);
let sel_start = sel.from(); let sel_start = sel.from();
let sel_end = sel.to(); let sel_end = sel.to();
let start_byte = text.char_to_byte(sel_start);
let mut start = sel_start; let mut start = sel_start;
for mat in regex.find_iter(&fragment) { for line in sel.slice(text).lines() {
let Some(line_ending) = get_line_ending(&line) else {
break;
};
let line_end = start + line.len_chars();
// TODO: retain range direction // TODO: retain range direction
let end = text.byte_to_char(start_byte + mat.start()); result.push(Range::new(start, line_end - line_ending.len_chars()));
start = line_end;
}
if start < sel_end {
result.push(Range::new(start, sel_end));
}
}
// TODO: figure out a new primary index
Selection::new(result, 0)
}
pub fn split_on_matches(text: RopeSlice, selection: &Selection, regex: &rope::Regex) -> Selection {
let mut result = SmallVec::with_capacity(selection.len());
for sel in selection {
// Special case: zero-width selection.
if sel.from() == sel.to() {
result.push(*sel);
continue;
}
let sel_start = sel.from();
let sel_end = sel.to();
let mut start = sel_start;
for mat in regex.find_iter(text.regex_input_at(sel_start..sel_end)) {
// TODO: retain range direction
let end = text.byte_to_char(mat.start());
result.push(Range::new(start, end)); result.push(Range::new(start, end));
start = text.byte_to_char(start_byte + mat.end()); start = text.byte_to_char(mat.end());
} }
if start < sel_end { if start < sel_end {
@@ -988,14 +1093,12 @@ mod test {
#[test] #[test]
fn test_select_on_matches() { fn test_select_on_matches() {
use crate::regex::{Regex, RegexBuilder};
let r = Rope::from_str("Nobody expects the Spanish inquisition"); let r = Rope::from_str("Nobody expects the Spanish inquisition");
let s = r.slice(..); let s = r.slice(..);
let selection = Selection::single(0, r.len_chars()); let selection = Selection::single(0, r.len_chars());
assert_eq!( assert_eq!(
select_on_matches(s, &selection, &Regex::new(r"[A-Z][a-z]*").unwrap()), select_on_matches(s, &selection, &rope::Regex::new(r"[A-Z][a-z]*").unwrap()),
Some(Selection::new( Some(Selection::new(
smallvec![Range::new(0, 6), Range::new(19, 26)], smallvec![Range::new(0, 6), Range::new(19, 26)],
0 0
@@ -1005,8 +1108,14 @@ mod test {
let r = Rope::from_str("This\nString\n\ncontains multiple\nlines"); let r = Rope::from_str("This\nString\n\ncontains multiple\nlines");
let s = r.slice(..); let s = r.slice(..);
let start_of_line = RegexBuilder::new(r"^").multi_line(true).build().unwrap(); let start_of_line = rope::RegexBuilder::new()
let end_of_line = RegexBuilder::new(r"$").multi_line(true).build().unwrap(); .syntax(rope::Config::new().multi_line(true))
.build(r"^")
.unwrap();
let end_of_line = rope::RegexBuilder::new()
.syntax(rope::Config::new().multi_line(true))
.build(r"$")
.unwrap();
// line without ending // line without ending
assert_eq!( assert_eq!(
@@ -1044,9 +1153,9 @@ mod test {
select_on_matches( select_on_matches(
s, s,
&Selection::single(0, s.len_chars()), &Selection::single(0, s.len_chars()),
&RegexBuilder::new(r"^[a-z ]*$") &rope::RegexBuilder::new()
.multi_line(true) .syntax(rope::Config::new().multi_line(true))
.build() .build(r"^[a-z ]*$")
.unwrap() .unwrap()
), ),
Some(Selection::new( Some(Selection::new(
@@ -1086,6 +1195,32 @@ mod test {
assert_eq!(Range::new(12, 0).line_range(s), (0, 2)); assert_eq!(Range::new(12, 0).line_range(s), (0, 2));
} }
#[test]
fn selection_line_ranges() {
let (text, selection) = crate::test::print(
r#" L0
#[|these]# line #(|ranges)# are #(|merged)# L1
L2
single one-line #(|range)# L3
L4
single #(|multiline L5
range)# L6
L7
these #(|multiline L8
ranges)# are #(|also L9
merged)# L10
L11
adjacent #(|ranges)# L12
are merged #(|the same way)# L13
"#,
);
let rope = Rope::from_str(&text);
assert_eq!(
vec![(1, 1), (3, 3), (5, 6), (8, 10), (12, 13)],
selection.line_ranges(rope.slice(..)).collect::<Vec<_>>(),
);
}
#[test] #[test]
fn test_cursor() { fn test_cursor() {
let r = Rope::from_str("\r\nHi\r\nthere!"); let r = Rope::from_str("\r\nHi\r\nthere!");
@@ -1138,13 +1273,15 @@ mod test {
#[test] #[test]
fn test_split_on_matches() { fn test_split_on_matches() {
use crate::regex::Regex;
let text = Rope::from(" abcd efg wrs xyz 123 456"); let text = Rope::from(" abcd efg wrs xyz 123 456");
let selection = Selection::new(smallvec![Range::new(0, 9), Range::new(11, 20),], 0); let selection = Selection::new(smallvec![Range::new(0, 9), Range::new(11, 20),], 0);
let result = split_on_matches(text.slice(..), &selection, &Regex::new(r"\s+").unwrap()); let result = split_on_matches(
text.slice(..),
&selection,
&rope::Regex::new(r"\s+").unwrap(),
);
assert_eq!( assert_eq!(
result.ranges(), result.ranges(),

View File

@@ -0,0 +1,13 @@
mod active;
mod elaborate;
mod parser;
mod render;
#[derive(PartialEq, Eq, Hash, Debug, PartialOrd, Ord, Clone, Copy)]
pub struct TabstopIdx(usize);
pub const LAST_TABSTOP_IDX: TabstopIdx = TabstopIdx(usize::MAX);
pub use active::ActiveSnippet;
pub use elaborate::{Snippet, SnippetElement, Transform};
pub use render::RenderedSnippet;
pub use render::SnippetRenderCtx;

View File

@@ -0,0 +1,255 @@
use std::ops::{Index, IndexMut};
use hashbrown::HashSet;
use helix_stdx::range::{is_exact_subset, is_subset};
use helix_stdx::Range;
use ropey::Rope;
use crate::movement::Direction;
use crate::snippets::render::{RenderedSnippet, Tabstop};
use crate::snippets::TabstopIdx;
use crate::{Assoc, ChangeSet, Selection, Transaction};
pub struct ActiveSnippet {
ranges: Vec<Range>,
active_tabstops: HashSet<TabstopIdx>,
current_tabstop: TabstopIdx,
tabstops: Vec<Tabstop>,
}
impl Index<TabstopIdx> for ActiveSnippet {
type Output = Tabstop;
fn index(&self, index: TabstopIdx) -> &Tabstop {
&self.tabstops[index.0]
}
}
impl IndexMut<TabstopIdx> for ActiveSnippet {
fn index_mut(&mut self, index: TabstopIdx) -> &mut Tabstop {
&mut self.tabstops[index.0]
}
}
impl ActiveSnippet {
pub fn new(snippet: RenderedSnippet) -> Option<Self> {
let snippet = Self {
ranges: snippet.ranges,
tabstops: snippet.tabstops,
active_tabstops: HashSet::new(),
current_tabstop: TabstopIdx(0),
};
(snippet.tabstops.len() != 1).then_some(snippet)
}
pub fn is_valid(&self, new_selection: &Selection) -> bool {
is_subset::<false>(self.ranges.iter().copied(), new_selection.range_bounds())
}
pub fn tabstops(&self) -> impl Iterator<Item = &Tabstop> {
self.tabstops.iter()
}
pub fn delete_placeholder(&self, doc: &Rope) -> Transaction {
Transaction::delete(
doc,
self[self.current_tabstop]
.ranges
.iter()
.map(|range| (range.start, range.end)),
)
}
/// maps the active snippets through a `ChangeSet` updating all tabstop ranges
pub fn map(&mut self, changes: &ChangeSet) -> bool {
let positions_to_map = self.ranges.iter_mut().flat_map(|range| {
[
(&mut range.start, Assoc::After),
(&mut range.end, Assoc::Before),
]
});
changes.update_positions(positions_to_map);
for (i, tabstop) in self.tabstops.iter_mut().enumerate() {
if self.active_tabstops.contains(&TabstopIdx(i)) {
let positions_to_map = tabstop.ranges.iter_mut().flat_map(|range| {
let end_assoc = if range.start == range.end {
Assoc::Before
} else {
Assoc::After
};
[
(&mut range.start, Assoc::Before),
(&mut range.end, end_assoc),
]
});
changes.update_positions(positions_to_map);
} else {
let positions_to_map = tabstop.ranges.iter_mut().flat_map(|range| {
let end_assoc = if range.start == range.end {
Assoc::After
} else {
Assoc::Before
};
[
(&mut range.start, Assoc::After),
(&mut range.end, end_assoc),
]
});
changes.update_positions(positions_to_map);
}
let mut snippet_ranges = self.ranges.iter();
let mut snippet_range = snippet_ranges.next().unwrap();
let mut tabstop_i = 0;
let mut prev = Range { start: 0, end: 0 };
let num_ranges = tabstop.ranges.len() / self.ranges.len();
tabstop.ranges.retain_mut(|range| {
if tabstop_i == num_ranges {
snippet_range = snippet_ranges.next().unwrap();
tabstop_i = 0;
}
tabstop_i += 1;
let retain = snippet_range.start <= snippet_range.end;
if retain {
range.start = range.start.max(snippet_range.start);
range.end = range.end.max(range.start).min(snippet_range.end);
// guaranteed by assoc
debug_assert!(prev.start <= range.start);
debug_assert!(range.start <= range.end);
if prev.end > range.start {
// not really sure what to do in this case. It shouldn't
// really occur in practice, the below just ensures
// our invariants hold
range.start = prev.end;
range.end = range.end.max(range.start)
}
prev = *range;
}
retain
});
}
self.ranges.iter().all(|range| range.end <= range.start)
}
pub fn next_tabstop(&mut self, current_selection: &Selection) -> (Selection, bool) {
let primary_idx = self.primary_idx(current_selection);
while self.current_tabstop.0 + 1 < self.tabstops.len() {
self.current_tabstop.0 += 1;
if self.activate_tabstop() {
let selection = self.tabstop_selection(primary_idx, Direction::Forward);
return (selection, self.current_tabstop.0 + 1 == self.tabstops.len());
}
}
(
self.tabstop_selection(primary_idx, Direction::Forward),
true,
)
}
pub fn prev_tabstop(&mut self, current_selection: &Selection) -> Option<Selection> {
let primary_idx = self.primary_idx(current_selection);
while self.current_tabstop.0 != 0 {
self.current_tabstop.0 -= 1;
if self.activate_tabstop() {
return Some(self.tabstop_selection(primary_idx, Direction::Forward));
}
}
None
}
// computes the primary idx adjusted for the number of cursors in the current tabstop
fn primary_idx(&self, current_selection: &Selection) -> usize {
let primary: Range = current_selection.primary().into();
let res = self
.ranges
.iter()
.position(|&range| range.contains(primary));
res.unwrap_or_else(|| {
unreachable!(
"active snippet must be valid {current_selection:?} {:?}",
self.ranges
)
})
}
fn activate_tabstop(&mut self) -> bool {
let tabstop = &self[self.current_tabstop];
if tabstop.has_placeholder() && tabstop.ranges.iter().all(|range| range.is_empty()) {
return false;
}
self.active_tabstops.clear();
self.active_tabstops.insert(self.current_tabstop);
let mut parent = self[self.current_tabstop].parent;
while let Some(tabstop) = parent {
self.active_tabstops.insert(tabstop);
parent = self[tabstop].parent;
}
true
// TODO: if the user removes the selection(s) in one snippet (but
// there are still other cursors in other snippets) and jumps to the
// next tabstop the selection in that tabstop is restored (at the
// next tabstop). This could be annoying since its not possible to
// remove a snippet cursor until the snippet is complete. On the other
// hand it may be useful since the user may just have meant to edit
// a subselection (like with s) of the tabstops and so the selection
// removal was just temporary. Potentially this could have some sort of
// separate keymap
}
pub fn tabstop_selection(&self, primary_idx: usize, direction: Direction) -> Selection {
let tabstop = &self[self.current_tabstop];
tabstop.selection(direction, primary_idx, self.ranges.len())
}
pub fn insert_subsnippet(mut self, snippet: RenderedSnippet) -> Option<Self> {
if snippet.ranges.len() % self.ranges.len() != 0
|| !is_exact_subset(self.ranges.iter().copied(), snippet.ranges.iter().copied())
{
log::warn!("number of subsnippets did not match, discarding outer snippet");
return ActiveSnippet::new(snippet);
}
let mut cnt = 0;
let parent = self[self.current_tabstop].parent;
let tabstops = snippet.tabstops.into_iter().map(|mut tabstop| {
cnt += 1;
if let Some(parent) = &mut tabstop.parent {
parent.0 += self.current_tabstop.0;
} else {
tabstop.parent = parent;
}
tabstop
});
self.tabstops
.splice(self.current_tabstop.0..=self.current_tabstop.0, tabstops);
self.activate_tabstop();
Some(self)
}
}
#[cfg(test)]
mod tests {
use std::iter::{self};
use ropey::Rope;
use crate::snippets::{ActiveSnippet, Snippet, SnippetRenderCtx};
use crate::{Selection, Transaction};
#[test]
fn fully_remove() {
let snippet = Snippet::parse("foo(${1:bar})$0").unwrap();
let mut doc = Rope::from("bar.\n");
let (transaction, _, snippet) = snippet.render(
&doc,
&Selection::point(4),
|_| (4, 4),
&mut SnippetRenderCtx::test_ctx(),
);
assert!(transaction.apply(&mut doc));
assert_eq!(doc, "bar.foo(bar)\n");
let mut snippet = ActiveSnippet::new(snippet).unwrap();
let edit = Transaction::change(&doc, iter::once((4, 12, None)));
assert!(edit.apply(&mut doc));
snippet.map(edit.changes());
assert!(!snippet.is_valid(&Selection::point(4)))
}
}

View File

@@ -0,0 +1,378 @@
use std::mem::swap;
use std::ops::Index;
use std::sync::Arc;
use anyhow::{anyhow, Result};
use helix_stdx::rope::RopeSliceExt;
use helix_stdx::Range;
use regex_cursor::engines::meta::Builder as RegexBuilder;
use regex_cursor::engines::meta::Regex;
use regex_cursor::regex_automata::util::syntax::Config as RegexConfig;
use ropey::RopeSlice;
use crate::case_conversion::to_lower_case_with;
use crate::case_conversion::to_upper_case_with;
use crate::case_conversion::{to_camel_case_with, to_pascal_case_with};
use crate::snippets::parser::{self, CaseChange, FormatItem};
use crate::snippets::{TabstopIdx, LAST_TABSTOP_IDX};
use crate::Tendril;
#[derive(Debug)]
pub struct Snippet {
elements: Vec<SnippetElement>,
tabstops: Vec<Tabstop>,
}
impl Snippet {
pub fn parse(snippet: &str) -> Result<Self> {
let parsed_snippet = parser::parse(snippet)
.map_err(|rest| anyhow!("Failed to parse snippet. Remaining input: {}", rest))?;
Ok(Snippet::new(parsed_snippet))
}
pub fn new(elements: Vec<parser::SnippetElement>) -> Snippet {
let mut res = Snippet {
elements: Vec::new(),
tabstops: Vec::new(),
};
res.elements = res.elaborate(elements, None).into();
res.fixup_tabstops();
res.ensure_last_tabstop();
res.renumber_tabstops();
res
}
pub fn elements(&self) -> &[SnippetElement] {
&self.elements
}
pub fn tabstops(&self) -> impl Iterator<Item = &Tabstop> {
self.tabstops.iter()
}
fn renumber_tabstops(&mut self) {
Self::renumber_tabstops_in(&self.tabstops, &mut self.elements);
for i in 0..self.tabstops.len() {
if let Some(parent) = self.tabstops[i].parent {
let parent = self
.tabstops
.binary_search_by_key(&parent, |tabstop| tabstop.idx)
.expect("all tabstops have been resolved");
self.tabstops[i].parent = Some(TabstopIdx(parent));
}
let tabstop = &mut self.tabstops[i];
if let TabstopKind::Placeholder { default } = &tabstop.kind {
let mut default = default.clone();
tabstop.kind = TabstopKind::Empty;
Self::renumber_tabstops_in(&self.tabstops, Arc::get_mut(&mut default).unwrap());
self.tabstops[i].kind = TabstopKind::Placeholder { default };
}
}
}
fn renumber_tabstops_in(tabstops: &[Tabstop], elements: &mut [SnippetElement]) {
for elem in elements {
match elem {
SnippetElement::Tabstop { idx } => {
idx.0 = tabstops
.binary_search_by_key(&*idx, |tabstop| tabstop.idx)
.expect("all tabstops have been resolved")
}
SnippetElement::Variable { default, .. } => {
if let Some(default) = default {
Self::renumber_tabstops_in(tabstops, default);
}
}
SnippetElement::Text(_) => (),
}
}
}
fn fixup_tabstops(&mut self) {
self.tabstops.sort_by_key(|tabstop| tabstop.idx);
self.tabstops.dedup_by(|tabstop1, tabstop2| {
if tabstop1.idx != tabstop2.idx {
return false;
}
// use the first non empty tabstop for all multicursor tabstops
if tabstop2.kind.is_empty() {
swap(tabstop2, tabstop1)
}
true
})
}
fn ensure_last_tabstop(&mut self) {
if matches!(self.tabstops.last(), Some(tabstop) if tabstop.idx == LAST_TABSTOP_IDX) {
return;
}
self.tabstops.push(Tabstop {
idx: LAST_TABSTOP_IDX,
parent: None,
kind: TabstopKind::Empty,
});
self.elements.push(SnippetElement::Tabstop {
idx: LAST_TABSTOP_IDX,
})
}
fn elaborate(
&mut self,
default: Vec<parser::SnippetElement>,
parent: Option<TabstopIdx>,
) -> Box<[SnippetElement]> {
default
.into_iter()
.map(|val| match val {
parser::SnippetElement::Tabstop {
tabstop,
transform: None,
} => SnippetElement::Tabstop {
idx: self.elaborate_placeholder(tabstop, parent, Vec::new()),
},
parser::SnippetElement::Tabstop {
tabstop,
transform: Some(transform),
} => SnippetElement::Tabstop {
idx: self.elaborate_transform(tabstop, parent, transform),
},
parser::SnippetElement::Placeholder { tabstop, value } => SnippetElement::Tabstop {
idx: self.elaborate_placeholder(tabstop, parent, value),
},
parser::SnippetElement::Choice { tabstop, choices } => SnippetElement::Tabstop {
idx: self.elaborate_choice(tabstop, parent, choices),
},
parser::SnippetElement::Variable {
name,
default,
transform,
} => SnippetElement::Variable {
name,
default: default.map(|default| self.elaborate(default, parent)),
// TODO: error for invalid transforms
transform: transform.and_then(Transform::new).map(Box::new),
},
parser::SnippetElement::Text(text) => SnippetElement::Text(text),
})
.collect()
}
fn elaborate_choice(
&mut self,
idx: usize,
parent: Option<TabstopIdx>,
choices: Vec<Tendril>,
) -> TabstopIdx {
let idx = TabstopIdx::elaborate(idx);
self.tabstops.push(Tabstop {
idx,
parent,
kind: TabstopKind::Choice {
choices: choices.into(),
},
});
idx
}
fn elaborate_placeholder(
&mut self,
idx: usize,
parent: Option<TabstopIdx>,
default: Vec<parser::SnippetElement>,
) -> TabstopIdx {
let idx = TabstopIdx::elaborate(idx);
let default = self.elaborate(default, Some(idx));
self.tabstops.push(Tabstop {
idx,
parent,
kind: TabstopKind::Placeholder {
default: default.into(),
},
});
idx
}
fn elaborate_transform(
&mut self,
idx: usize,
parent: Option<TabstopIdx>,
transform: parser::Transform,
) -> TabstopIdx {
let idx = TabstopIdx::elaborate(idx);
if let Some(transform) = Transform::new(transform) {
self.tabstops.push(Tabstop {
idx,
parent,
kind: TabstopKind::Transform(Arc::new(transform)),
})
} else {
// TODO: proper error
self.tabstops.push(Tabstop {
idx,
parent,
kind: TabstopKind::Empty,
})
}
idx
}
}
impl Index<TabstopIdx> for Snippet {
type Output = Tabstop;
fn index(&self, index: TabstopIdx) -> &Tabstop {
&self.tabstops[index.0]
}
}
#[derive(Debug)]
pub enum SnippetElement {
Tabstop {
idx: TabstopIdx,
},
Variable {
name: Tendril,
default: Option<Box<[SnippetElement]>>,
transform: Option<Box<Transform>>,
},
Text(Tendril),
}
#[derive(Debug)]
pub struct Tabstop {
idx: TabstopIdx,
pub parent: Option<TabstopIdx>,
pub kind: TabstopKind,
}
#[derive(Debug)]
pub enum TabstopKind {
Choice { choices: Arc<[Tendril]> },
Placeholder { default: Arc<[SnippetElement]> },
Empty,
Transform(Arc<Transform>),
}
impl TabstopKind {
pub fn is_empty(&self) -> bool {
matches!(self, TabstopKind::Empty)
}
}
#[derive(Debug)]
pub struct Transform {
regex: Regex,
regex_str: Box<str>,
global: bool,
replacement: Box<[FormatItem]>,
}
impl PartialEq for Transform {
fn eq(&self, other: &Self) -> bool {
self.replacement == other.replacement
&& self.global == other.global
// doens't compare m and i setting but close enough
&& self.regex_str == other.regex_str
}
}
impl Transform {
fn new(transform: parser::Transform) -> Option<Transform> {
let mut config = RegexConfig::new();
let mut global = false;
let mut invalid_config = false;
for c in transform.options.chars() {
match c {
'i' => {
config = config.case_insensitive(true);
}
'm' => {
config = config.multi_line(true);
}
'g' => {
global = true;
}
// we ignore 'u' since we always want to
// do unicode aware matching
_ => invalid_config = true,
}
}
if invalid_config {
log::error!("invalid transform configuration characters {transform:?}");
}
let regex = match RegexBuilder::new().syntax(config).build(&transform.regex) {
Ok(regex) => regex,
Err(err) => {
log::error!("invalid transform {err} {transform:?}");
return None;
}
};
Some(Transform {
regex,
regex_str: transform.regex.as_str().into(),
global,
replacement: transform.replacement.into(),
})
}
pub fn apply(&self, mut doc: RopeSlice<'_>, range: Range) -> Tendril {
let mut buf = Tendril::new();
let it = self
.regex
.captures_iter(doc.regex_input_at(range))
.enumerate();
doc = doc.slice(range);
let mut last_match = 0;
for (_, cap) in it {
// unwrap on 0 is OK because captures only reports matches
let m = cap.get_group(0).unwrap();
buf.extend(doc.byte_slice(last_match..m.start).chunks());
last_match = m.end;
for fmt in &*self.replacement {
match *fmt {
FormatItem::Text(ref text) => {
buf.push_str(text);
}
FormatItem::Capture(i) => {
if let Some(cap) = cap.get_group(i) {
buf.extend(doc.byte_slice(cap.range()).chunks());
}
}
FormatItem::CaseChange(i, change) => {
if let Some(cap) = cap.get_group(i).filter(|i| !i.is_empty()) {
let mut chars = doc.byte_slice(cap.range()).chars();
match change {
CaseChange::Upcase => to_upper_case_with(chars, &mut buf),
CaseChange::Downcase => to_lower_case_with(chars, &mut buf),
CaseChange::Capitalize => {
let first_char = chars.next().unwrap();
buf.extend(first_char.to_uppercase());
buf.extend(chars);
}
CaseChange::PascalCase => to_pascal_case_with(chars, &mut buf),
CaseChange::CamelCase => to_camel_case_with(chars, &mut buf),
}
}
}
FormatItem::Conditional(i, ref if_, ref else_) => {
if cap.get_group(i).map_or(true, |mat| mat.is_empty()) {
buf.push_str(else_)
} else {
buf.push_str(if_)
}
}
}
}
if !self.global {
break;
}
}
buf.extend(doc.byte_slice(last_match..).chunks());
buf
}
}
impl TabstopIdx {
fn elaborate(idx: usize) -> Self {
TabstopIdx(idx.wrapping_sub(1))
}
}

View File

@@ -0,0 +1,922 @@
/*!
A parser for LSP/VSCode style snippet syntax
See <https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#snippet_syntax>.
``` text
any ::= tabstop | placeholder | choice | variable | text
tabstop ::= '$' int | '${' int '}'
placeholder ::= '${' int ':' any '}'
choice ::= '${' int '|' text (',' text)* '|}'
variable ::= '$' var | '${' var }'
| '${' var ':' any '}'
| '${' var '/' regex '/' (format | text)+ '/' options '}'
format ::= '$' int | '${' int '}'
| '${' int ':' '/upcase' | '/downcase' | '/capitalize' '}'
| '${' int ':+' if '}'
| '${' int ':?' if ':' else '}'
| '${' int ':-' else '}' | '${' int ':' else '}'
regex ::= Regular Expression value (ctor-string)
options ::= Regular Expression option (ctor-options)
var ::= [_a-zA-Z] [_a-zA-Z0-9]*
int ::= [0-9]+
text ::= .*
if ::= text
else ::= text
```
*/
use crate::Tendril;
use helix_parsec::*;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum CaseChange {
Upcase,
Downcase,
Capitalize,
PascalCase,
CamelCase,
}
#[derive(Debug, PartialEq, Eq)]
pub enum FormatItem {
Text(Tendril),
Capture(usize),
CaseChange(usize, CaseChange),
Conditional(usize, Tendril, Tendril),
}
#[derive(Debug, PartialEq, Eq)]
pub struct Transform {
pub regex: Tendril,
pub replacement: Vec<FormatItem>,
pub options: Tendril,
}
#[derive(Debug, PartialEq, Eq)]
pub enum SnippetElement {
Tabstop {
tabstop: usize,
transform: Option<Transform>,
},
Placeholder {
tabstop: usize,
value: Vec<SnippetElement>,
},
Choice {
tabstop: usize,
choices: Vec<Tendril>,
},
Variable {
name: Tendril,
default: Option<Vec<SnippetElement>>,
transform: Option<Transform>,
},
Text(Tendril),
}
pub fn parse(s: &str) -> Result<Vec<SnippetElement>, &str> {
snippet().parse(s).and_then(|(remainder, snippet)| {
if remainder.is_empty() {
Ok(snippet)
} else {
Err(remainder)
}
})
}
fn var<'a>() -> impl Parser<'a, Output = &'a str> {
// var = [_a-zA-Z][_a-zA-Z0-9]*
move |input: &'a str| {
input
.char_indices()
.take_while(|(p, c)| {
*c == '_'
|| if *p == 0 {
c.is_ascii_alphabetic()
} else {
c.is_ascii_alphanumeric()
}
})
.last()
.map(|(index, c)| {
let index = index + c.len_utf8();
(&input[index..], &input[0..index])
})
.ok_or(input)
}
}
const TEXT_ESCAPE_CHARS: &[char] = &['\\', '}', '$'];
const CHOICE_TEXT_ESCAPE_CHARS: &[char] = &['\\', '|', ','];
fn text<'a>(
escape_chars: &'static [char],
term_chars: &'static [char],
) -> impl Parser<'a, Output = Tendril> {
move |input: &'a str| {
let mut chars = input.char_indices().peekable();
let mut res = Tendril::new();
while let Some((i, c)) = chars.next() {
match c {
'\\' => {
if let Some(&(_, c)) = chars.peek() {
if escape_chars.contains(&c) {
chars.next();
res.push(c);
continue;
}
}
res.push('\\');
}
c if term_chars.contains(&c) => return Ok((&input[i..], res)),
c => res.push(c),
}
}
Ok(("", res))
}
}
fn digit<'a>() -> impl Parser<'a, Output = usize> {
filter_map(take_while(|c| c.is_ascii_digit()), |s| s.parse().ok())
}
fn case_change<'a>() -> impl Parser<'a, Output = CaseChange> {
use CaseChange::*;
choice!(
map("upcase", |_| Upcase),
map("downcase", |_| Downcase),
map("capitalize", |_| Capitalize),
map("pascalcase", |_| PascalCase),
map("camelcase", |_| CamelCase),
)
}
fn format<'a>() -> impl Parser<'a, Output = FormatItem> {
use FormatItem::*;
choice!(
// '$' int
map(right("$", digit()), Capture),
// '${' int '}'
map(seq!("${", digit(), "}"), |seq| Capture(seq.1)),
// '${' int ':' '/upcase' | '/downcase' | '/capitalize' '}'
map(seq!("${", digit(), ":/", case_change(), "}"), |seq| {
CaseChange(seq.1, seq.3)
}),
// '${' int ':+' if '}'
map(
seq!("${", digit(), ":+", text(TEXT_ESCAPE_CHARS, &['}']), "}"),
|seq| { Conditional(seq.1, seq.3, Tendril::new()) }
),
// '${' int ':?' if ':' else '}'
map(
seq!(
"${",
digit(),
":?",
text(TEXT_ESCAPE_CHARS, &[':']),
":",
text(TEXT_ESCAPE_CHARS, &['}']),
"}"
),
|seq| { Conditional(seq.1, seq.3, seq.5) }
),
// '${' int ':-' else '}' | '${' int ':' else '}'
map(
seq!(
"${",
digit(),
":",
optional("-"),
text(TEXT_ESCAPE_CHARS, &['}']),
"}"
),
|seq| { Conditional(seq.1, Tendril::new(), seq.4) }
),
)
}
fn regex<'a>() -> impl Parser<'a, Output = Transform> {
map(
seq!(
"/",
// TODO parse as ECMAScript and convert to rust regex
text(&['/'], &['/']),
"/",
zero_or_more(choice!(
format(),
// text doesn't parse $, if format fails we just accept the $ as text
map("$", |_| FormatItem::Text("$".into())),
map(text(&['\\', '/'], &['/', '$']), FormatItem::Text),
)),
"/",
// vscode really doesn't allow escaping } here
// so it's impossible to write a regex escape containing a }
// we can consider deviating here and allowing the escape
text(&[], &['}']),
),
|(_, value, _, replacement, _, options)| Transform {
regex: value,
replacement,
options,
},
)
}
fn tabstop<'a>() -> impl Parser<'a, Output = SnippetElement> {
map(
or(
map(right("$", digit()), |i| (i, None)),
map(
seq!("${", digit(), optional(regex()), "}"),
|(_, i, transform, _)| (i, transform),
),
),
|(tabstop, transform)| SnippetElement::Tabstop { tabstop, transform },
)
}
fn placeholder<'a>() -> impl Parser<'a, Output = SnippetElement> {
map(
seq!(
"${",
digit(),
":",
// according to the grammar there is just a single anything here.
// However in the prose it is explained that placeholders can be nested.
// The example there contains both a placeholder text and a nested placeholder
// which indicates a list. Looking at the VSCode sourcecode, the placeholder
// is indeed parsed as zero_or_more so the grammar is simply incorrect here
zero_or_more(anything(TEXT_ESCAPE_CHARS, true)),
"}"
),
|seq| SnippetElement::Placeholder {
tabstop: seq.1,
value: seq.3,
},
)
}
fn choice<'a>() -> impl Parser<'a, Output = SnippetElement> {
map(
seq!(
"${",
digit(),
"|",
sep(text(CHOICE_TEXT_ESCAPE_CHARS, &['|', ',']), ","),
"|}",
),
|seq| SnippetElement::Choice {
tabstop: seq.1,
choices: seq.3,
},
)
}
fn variable<'a>() -> impl Parser<'a, Output = SnippetElement> {
choice!(
// $var
map(right("$", var()), |name| SnippetElement::Variable {
name: name.into(),
default: None,
transform: None,
}),
// ${var}
map(seq!("${", var(), "}",), |values| SnippetElement::Variable {
name: values.1.into(),
default: None,
transform: None,
}),
// ${var:default}
map(
seq!(
"${",
var(),
":",
zero_or_more(anything(TEXT_ESCAPE_CHARS, true)),
"}",
),
|values| SnippetElement::Variable {
name: values.1.into(),
default: Some(values.3),
transform: None,
}
),
// ${var/value/format/options}
map(seq!("${", var(), regex(), "}"), |values| {
SnippetElement::Variable {
name: values.1.into(),
default: None,
transform: Some(values.2),
}
}),
)
}
fn anything<'a>(
escape_chars: &'static [char],
end_at_brace: bool,
) -> impl Parser<'a, Output = SnippetElement> {
let term_chars: &[_] = if end_at_brace { &['$', '}'] } else { &['$'] };
move |input: &'a str| {
let parser = choice!(
tabstop(),
placeholder(),
choice(),
variable(),
map("$", |_| SnippetElement::Text("$".into())),
map(text(escape_chars, term_chars), SnippetElement::Text),
);
parser.parse(input)
}
}
fn snippet<'a>() -> impl Parser<'a, Output = Vec<SnippetElement>> {
one_or_more(anything(TEXT_ESCAPE_CHARS, false))
}
#[cfg(test)]
mod test {
use crate::snippets::{Snippet, SnippetRenderCtx};
use super::SnippetElement::*;
use super::*;
#[test]
fn empty_string_is_error() {
assert_eq!(Err(""), parse(""));
}
#[test]
fn parse_placeholders_in_function_call() {
assert_eq!(
Ok(vec![
Text("match(".into()),
Placeholder {
tabstop: 1,
value: vec![Text("Arg1".into())],
},
Text(")".into()),
]),
parse("match(${1:Arg1})")
)
}
#[test]
fn unterminated_placeholder() {
assert_eq!(
Ok(vec![
Text("match(".into()),
Text("$".into()),
Text("{1:)".into())
]),
parse("match(${1:)")
)
}
#[test]
fn parse_empty_placeholder() {
assert_eq!(
Ok(vec![
Text("match(".into()),
Placeholder {
tabstop: 1,
value: vec![],
},
Text(")".into()),
]),
parse("match(${1:})")
)
}
#[test]
fn parse_placeholders_in_statement() {
assert_eq!(
Ok(vec![
Text("local ".into()),
Placeholder {
tabstop: 1,
value: vec![Text("var".into())],
},
Text(" = ".into()),
Placeholder {
tabstop: 1,
value: vec![Text("value".into())],
},
]),
parse("local ${1:var} = ${1:value}")
)
}
#[test]
fn parse_tabstop_nested_in_placeholder() {
assert_eq!(
Ok(vec![Placeholder {
tabstop: 1,
value: vec![
Text("var, ".into()),
Tabstop {
tabstop: 2,
transform: None
}
],
}]),
parse("${1:var, $2}")
)
}
#[test]
fn parse_placeholder_nested_in_placeholder() {
assert_eq!(
Ok({
vec![Placeholder {
tabstop: 1,
value: vec![
Text("foo ".into()),
Placeholder {
tabstop: 2,
value: vec![Text("bar".into())],
},
],
}]
}),
parse("${1:foo ${2:bar}}")
)
}
#[test]
fn parse_all() {
assert_eq!(
Ok(vec![
Text("hello ".into()),
Tabstop {
tabstop: 1,
transform: None
},
Tabstop {
tabstop: 2,
transform: None
},
Text(" ".into()),
Choice {
tabstop: 1,
choices: vec!["one".into(), "two".into(), "three".into()],
},
Text(" ".into()),
Variable {
name: "name".into(),
default: Some(vec![Text("foo".into())]),
transform: None,
},
Text(" ".into()),
Variable {
name: "var".into(),
default: None,
transform: None,
},
Text(" ".into()),
Variable {
name: "TM".into(),
default: None,
transform: None,
},
]),
parse("hello $1${2} ${1|one,two,three|} ${name:foo} $var $TM")
);
}
#[test]
fn regex_capture_replace() {
assert_eq!(
Ok({
vec![Variable {
name: "TM_FILENAME".into(),
default: None,
transform: Some(Transform {
regex: "(.*).+$".into(),
replacement: vec![FormatItem::Capture(1), FormatItem::Text("$".into())],
options: Tendril::new(),
}),
}]
}),
parse("${TM_FILENAME/(.*).+$/$1$/}")
);
}
#[test]
fn rust_macro() {
assert_eq!(
Ok({
vec![
Text("macro_rules! ".into()),
Tabstop {
tabstop: 1,
transform: None,
},
Text(" {\n (".into()),
Tabstop {
tabstop: 2,
transform: None,
},
Text(") => {\n ".into()),
Tabstop {
tabstop: 0,
transform: None,
},
Text("\n };\n}".into()),
]
}),
parse("macro_rules! $1 {\n ($2) => {\n $0\n };\n}")
);
}
fn assert_text(snippet: &str, parsed_text: &str) {
let snippet = Snippet::parse(snippet).unwrap();
let mut rendered_snippet = snippet.prepare_render();
let rendered_text = snippet
.render_at(
&mut rendered_snippet,
"".into(),
false,
&mut SnippetRenderCtx::test_ctx(),
0,
)
.0;
assert_eq!(rendered_text, parsed_text)
}
#[test]
fn robust_parsing() {
assert_text("$", "$");
assert_text("\\\\$", "\\$");
assert_text("{", "{");
assert_text("\\}", "}");
assert_text("\\abc", "\\abc");
assert_text("foo${f:\\}}bar", "foo}bar");
assert_text("\\{", "\\{");
assert_text("I need \\\\\\$", "I need \\$");
assert_text("\\", "\\");
assert_text("\\{{", "\\{{");
assert_text("{{", "{{");
assert_text("{{dd", "{{dd");
assert_text("}}", "}}");
assert_text("ff}}", "ff}}");
assert_text("farboo", "farboo");
assert_text("far{{}}boo", "far{{}}boo");
assert_text("far{{123}}boo", "far{{123}}boo");
assert_text("far\\{{123}}boo", "far\\{{123}}boo");
assert_text("far{{id:bern}}boo", "far{{id:bern}}boo");
assert_text("far{{id:bern {{basel}}}}boo", "far{{id:bern {{basel}}}}boo");
assert_text(
"far{{id:bern {{id:basel}}}}boo",
"far{{id:bern {{id:basel}}}}boo",
);
assert_text(
"far{{id:bern {{id2:basel}}}}boo",
"far{{id:bern {{id2:basel}}}}boo",
);
assert_text("${}$\\a\\$\\}\\\\", "${}$\\a$}\\");
assert_text("farboo", "farboo");
assert_text("far{{}}boo", "far{{}}boo");
assert_text("far{{123}}boo", "far{{123}}boo");
assert_text("far\\{{123}}boo", "far\\{{123}}boo");
assert_text("far`123`boo", "far`123`boo");
assert_text("far\\`123\\`boo", "far\\`123\\`boo");
assert_text("\\$far-boo", "$far-boo");
}
fn assert_snippet(snippet: &str, expect: &[SnippetElement]) {
let elements = parse(snippet).unwrap();
assert_eq!(elements, expect.to_owned())
}
#[test]
fn parse_variable() {
use SnippetElement::*;
assert_snippet(
"$far-boo",
&[
Variable {
name: "far".into(),
default: None,
transform: None,
},
Text("-boo".into()),
],
);
assert_snippet(
"far$farboo",
&[
Text("far".into()),
Variable {
name: "farboo".into(),
transform: None,
default: None,
},
],
);
assert_snippet(
"far${farboo}",
&[
Text("far".into()),
Variable {
name: "farboo".into(),
transform: None,
default: None,
},
],
);
assert_snippet(
"$123",
&[Tabstop {
tabstop: 123,
transform: None,
}],
);
assert_snippet(
"$farboo",
&[Variable {
name: "farboo".into(),
transform: None,
default: None,
}],
);
assert_snippet(
"$far12boo",
&[Variable {
name: "far12boo".into(),
transform: None,
default: None,
}],
);
assert_snippet(
"000_${far}_000",
&[
Text("000_".into()),
Variable {
name: "far".into(),
transform: None,
default: None,
},
Text("_000".into()),
],
);
}
#[test]
fn parse_variable_transform() {
assert_snippet(
"${foo///}",
&[Variable {
name: "foo".into(),
transform: Some(Transform {
regex: Tendril::new(),
replacement: Vec::new(),
options: Tendril::new(),
}),
default: None,
}],
);
assert_snippet(
"${foo/regex/format/gmi}",
&[Variable {
name: "foo".into(),
transform: Some(Transform {
regex: "regex".into(),
replacement: vec![FormatItem::Text("format".into())],
options: "gmi".into(),
}),
default: None,
}],
);
assert_snippet(
"${foo/([A-Z][a-z])/format/}",
&[Variable {
name: "foo".into(),
transform: Some(Transform {
regex: "([A-Z][a-z])".into(),
replacement: vec![FormatItem::Text("format".into())],
options: Tendril::new(),
}),
default: None,
}],
);
// invalid regex TODO: reneable tests once we actually parse this regex flavor
// assert_text(
// "${foo/([A-Z][a-z])/format/GMI}",
// "${foo/([A-Z][a-z])/format/GMI}",
// );
// assert_text(
// "${foo/([A-Z][a-z])/format/funky}",
// "${foo/([A-Z][a-z])/format/funky}",
// );
// assert_text("${foo/([A-Z][a-z]/format/}", "${foo/([A-Z][a-z]/format/}");
assert_text(
"${foo/regex\\/format/options}",
"${foo/regex\\/format/options}",
);
// tricky regex
assert_snippet(
"${foo/m\\/atch/$1/i}",
&[Variable {
name: "foo".into(),
transform: Some(Transform {
regex: "m/atch".into(),
replacement: vec![FormatItem::Capture(1)],
options: "i".into(),
}),
default: None,
}],
);
// incomplete
assert_text("${foo///", "${foo///");
assert_text("${foo/regex/format/options", "${foo/regex/format/options");
// format string
assert_snippet(
"${foo/.*/${0:fooo}/i}",
&[Variable {
name: "foo".into(),
transform: Some(Transform {
regex: ".*".into(),
replacement: vec![FormatItem::Conditional(0, Tendril::new(), "fooo".into())],
options: "i".into(),
}),
default: None,
}],
);
assert_snippet(
"${foo/.*/${1}/i}",
&[Variable {
name: "foo".into(),
transform: Some(Transform {
regex: ".*".into(),
replacement: vec![FormatItem::Capture(1)],
options: "i".into(),
}),
default: None,
}],
);
assert_snippet(
"${foo/.*/$1/i}",
&[Variable {
name: "foo".into(),
transform: Some(Transform {
regex: ".*".into(),
replacement: vec![FormatItem::Capture(1)],
options: "i".into(),
}),
default: None,
}],
);
assert_snippet(
"${foo/.*/This-$1-encloses/i}",
&[Variable {
name: "foo".into(),
transform: Some(Transform {
regex: ".*".into(),
replacement: vec![
FormatItem::Text("This-".into()),
FormatItem::Capture(1),
FormatItem::Text("-encloses".into()),
],
options: "i".into(),
}),
default: None,
}],
);
assert_snippet(
"${foo/.*/complex${1:else}/i}",
&[Variable {
name: "foo".into(),
transform: Some(Transform {
regex: ".*".into(),
replacement: vec![
FormatItem::Text("complex".into()),
FormatItem::Conditional(1, Tendril::new(), "else".into()),
],
options: "i".into(),
}),
default: None,
}],
);
assert_snippet(
"${foo/.*/complex${1:-else}/i}",
&[Variable {
name: "foo".into(),
transform: Some(Transform {
regex: ".*".into(),
replacement: vec![
FormatItem::Text("complex".into()),
FormatItem::Conditional(1, Tendril::new(), "else".into()),
],
options: "i".into(),
}),
default: None,
}],
);
assert_snippet(
"${foo/.*/complex${1:+if}/i}",
&[Variable {
name: "foo".into(),
transform: Some(Transform {
regex: ".*".into(),
replacement: vec![
FormatItem::Text("complex".into()),
FormatItem::Conditional(1, "if".into(), Tendril::new()),
],
options: "i".into(),
}),
default: None,
}],
);
assert_snippet(
"${foo/.*/complex${1:?if:else}/i}",
&[Variable {
name: "foo".into(),
transform: Some(Transform {
regex: ".*".into(),
replacement: vec![
FormatItem::Text("complex".into()),
FormatItem::Conditional(1, "if".into(), "else".into()),
],
options: "i".into(),
}),
default: None,
}],
);
assert_snippet(
"${foo/.*/complex${1:/upcase}/i}",
&[Variable {
name: "foo".into(),
transform: Some(Transform {
regex: ".*".into(),
replacement: vec![
FormatItem::Text("complex".into()),
FormatItem::CaseChange(1, CaseChange::Upcase),
],
options: "i".into(),
}),
default: None,
}],
);
assert_snippet(
"${TM_DIRECTORY/src\\//$1/}",
&[Variable {
name: "TM_DIRECTORY".into(),
transform: Some(Transform {
regex: "src/".into(),
replacement: vec![FormatItem::Capture(1)],
options: Tendril::new(),
}),
default: None,
}],
);
assert_snippet(
"${TM_SELECTED_TEXT/a/\\/$1/g}",
&[Variable {
name: "TM_SELECTED_TEXT".into(),
transform: Some(Transform {
regex: "a".into(),
replacement: vec![FormatItem::Text("/".into()), FormatItem::Capture(1)],
options: "g".into(),
}),
default: None,
}],
);
assert_snippet(
"${TM_SELECTED_TEXT/a/in\\/$1ner/g}",
&[Variable {
name: "TM_SELECTED_TEXT".into(),
transform: Some(Transform {
regex: "a".into(),
replacement: vec![
FormatItem::Text("in/".into()),
FormatItem::Capture(1),
FormatItem::Text("ner".into()),
],
options: "g".into(),
}),
default: None,
}],
);
assert_snippet(
"${TM_SELECTED_TEXT/a/end\\//g}",
&[Variable {
name: "TM_SELECTED_TEXT".into(),
transform: Some(Transform {
regex: "a".into(),
replacement: vec![FormatItem::Text("end/".into())],
options: "g".into(),
}),
default: None,
}],
);
}
// TODO port more tests from https://github.com/microsoft/vscode/blob/dce493cb6e36346ef2714e82c42ce14fc461b15c/src/vs/editor/contrib/snippet/test/browser/snippetParser.test.ts
}

View File

@@ -0,0 +1,355 @@
use std::borrow::Cow;
use std::ops::{Index, IndexMut};
use std::sync::Arc;
use helix_stdx::Range;
use ropey::{Rope, RopeSlice};
use smallvec::SmallVec;
use crate::indent::{normalize_indentation, IndentStyle};
use crate::movement::Direction;
use crate::snippets::elaborate;
use crate::snippets::TabstopIdx;
use crate::snippets::{Snippet, SnippetElement, Transform};
use crate::{selection, Selection, Tendril, Transaction};
#[derive(Debug, Clone, PartialEq)]
pub enum TabstopKind {
Choice { choices: Arc<[Tendril]> },
Placeholder,
Empty,
Transform(Arc<Transform>),
}
#[derive(Debug, PartialEq)]
pub struct Tabstop {
pub ranges: SmallVec<[Range; 1]>,
pub parent: Option<TabstopIdx>,
pub kind: TabstopKind,
}
impl Tabstop {
pub fn has_placeholder(&self) -> bool {
matches!(
self.kind,
TabstopKind::Choice { .. } | TabstopKind::Placeholder
)
}
pub fn selection(
&self,
direction: Direction,
primary_idx: usize,
snippet_ranges: usize,
) -> Selection {
Selection::new(
self.ranges
.iter()
.map(|&range| {
let mut range = selection::Range::new(range.start, range.end);
if direction == Direction::Backward {
range = range.flip()
}
range
})
.collect(),
primary_idx * (self.ranges.len() / snippet_ranges),
)
}
}
#[derive(Debug, Default, PartialEq)]
pub struct RenderedSnippet {
pub tabstops: Vec<Tabstop>,
pub ranges: Vec<Range>,
}
impl RenderedSnippet {
pub fn first_selection(&self, direction: Direction, primary_idx: usize) -> Selection {
self.tabstops[0].selection(direction, primary_idx, self.ranges.len())
}
}
impl Index<TabstopIdx> for RenderedSnippet {
type Output = Tabstop;
fn index(&self, index: TabstopIdx) -> &Tabstop {
&self.tabstops[index.0]
}
}
impl IndexMut<TabstopIdx> for RenderedSnippet {
fn index_mut(&mut self, index: TabstopIdx) -> &mut Tabstop {
&mut self.tabstops[index.0]
}
}
impl Snippet {
pub fn prepare_render(&self) -> RenderedSnippet {
let tabstops =
self.tabstops()
.map(|tabstop| Tabstop {
ranges: SmallVec::new(),
parent: tabstop.parent,
kind: match &tabstop.kind {
elaborate::TabstopKind::Choice { choices } => TabstopKind::Choice {
choices: choices.clone(),
},
// start out as empty: the first non-empty placeholder will change this to
// a placeholder automatically
elaborate::TabstopKind::Empty
| elaborate::TabstopKind::Placeholder { .. } => TabstopKind::Empty,
elaborate::TabstopKind::Transform(transform) => {
TabstopKind::Transform(transform.clone())
}
},
})
.collect();
RenderedSnippet {
tabstops,
ranges: Vec::new(),
}
}
pub fn render_at(
&self,
snippet: &mut RenderedSnippet,
indent: RopeSlice<'_>,
at_newline: bool,
ctx: &mut SnippetRenderCtx,
pos: usize,
) -> (Tendril, usize) {
let mut ctx = SnippetRender {
dst: snippet,
src: self,
indent,
text: Tendril::new(),
off: pos,
ctx,
at_newline,
};
ctx.render_elements(self.elements());
let end = ctx.off;
let text = ctx.text;
snippet.ranges.push(Range { start: pos, end });
(text, end - pos)
}
pub fn render(
&self,
doc: &Rope,
selection: &Selection,
change_range: impl FnMut(&selection::Range) -> (usize, usize),
ctx: &mut SnippetRenderCtx,
) -> (Transaction, Selection, RenderedSnippet) {
let mut snippet = self.prepare_render();
let mut off = 0;
let (transaction, selection) = Transaction::change_by_selection_ignore_overlapping(
doc,
selection,
change_range,
|replacement_start, replacement_end| {
let line_idx = doc.char_to_line(replacement_start);
let line_start = doc.line_to_char(line_idx);
let prefix = doc.slice(line_start..replacement_start);
let indent_len = prefix.chars().take_while(|c| c.is_whitespace()).count();
let indent = prefix.slice(..indent_len);
let at_newline = indent_len == replacement_start - line_start;
let (replacement, replacement_len) = self.render_at(
&mut snippet,
indent,
at_newline,
ctx,
(replacement_start as i128 + off) as usize,
);
off +=
replacement_start as i128 - replacement_end as i128 + replacement_len as i128;
Some(replacement)
},
);
(transaction, selection, snippet)
}
}
pub type VariableResolver = dyn FnMut(&str) -> Option<Cow<str>>;
pub struct SnippetRenderCtx {
pub resolve_var: Box<VariableResolver>,
pub tab_width: usize,
pub indent_style: IndentStyle,
pub line_ending: &'static str,
}
impl SnippetRenderCtx {
#[cfg(test)]
pub(super) fn test_ctx() -> SnippetRenderCtx {
SnippetRenderCtx {
resolve_var: Box::new(|_| None),
tab_width: 4,
indent_style: IndentStyle::Spaces(4),
line_ending: "\n",
}
}
}
struct SnippetRender<'a> {
ctx: &'a mut SnippetRenderCtx,
dst: &'a mut RenderedSnippet,
src: &'a Snippet,
indent: RopeSlice<'a>,
text: Tendril,
off: usize,
at_newline: bool,
}
impl SnippetRender<'_> {
fn render_elements(&mut self, elements: &[SnippetElement]) {
for element in elements {
self.render_element(element)
}
}
fn render_element(&mut self, element: &SnippetElement) {
match *element {
SnippetElement::Tabstop { idx } => self.render_tabstop(idx),
SnippetElement::Variable {
ref name,
ref default,
ref transform,
} => {
// TODO: allow resolve_var access to the doc and make it return rope slice
// so we can access selections and other document content without allocating
if let Some(val) = (self.ctx.resolve_var)(name) {
if let Some(transform) = transform {
self.push_multiline_str(&transform.apply(
(&*val).into(),
Range {
start: 0,
end: val.chars().count(),
},
));
} else {
self.push_multiline_str(&val)
}
} else if let Some(default) = default {
self.render_elements(default)
}
}
SnippetElement::Text(ref text) => self.push_multiline_str(text),
}
}
fn push_multiline_str(&mut self, text: &str) {
let mut lines = text
.split('\n')
.map(|line| line.strip_suffix('\r').unwrap_or(line));
let first_line = lines.next().unwrap();
self.push_str(first_line, self.at_newline);
for line in lines {
self.push_newline();
self.push_str(line, true);
}
}
fn push_str(&mut self, mut text: &str, at_newline: bool) {
if at_newline {
let old_len = self.text.len();
let old_indent_len = normalize_indentation(
self.indent,
text.into(),
&mut self.text,
self.ctx.indent_style,
self.ctx.tab_width,
);
// this is ok because indentation can only be ascii chars (' ' and '\t')
self.off += self.text.len() - old_len;
text = &text[old_indent_len..];
if text.is_empty() {
self.at_newline = true;
return;
}
}
self.text.push_str(text);
self.off += text.chars().count();
}
fn push_newline(&mut self) {
self.off += self.ctx.line_ending.chars().count() + self.indent.len_chars();
self.text.push_str(self.ctx.line_ending);
self.text.extend(self.indent.chunks());
}
fn render_tabstop(&mut self, tabstop: TabstopIdx) {
let start = self.off;
let end = match &self.src[tabstop].kind {
elaborate::TabstopKind::Placeholder { default } if !default.is_empty() => {
self.render_elements(default);
self.dst[tabstop].kind = TabstopKind::Placeholder;
self.off
}
_ => start,
};
self.dst[tabstop].ranges.push(Range { start, end });
}
}
#[cfg(test)]
mod tests {
use helix_stdx::Range;
use crate::snippets::render::Tabstop;
use crate::snippets::{Snippet, SnippetRenderCtx};
use super::TabstopKind;
fn assert_snippet(snippet: &str, expect: &str, tabstops: &[Tabstop]) {
let snippet = Snippet::parse(snippet).unwrap();
let mut rendered_snippet = snippet.prepare_render();
let rendered_text = snippet
.render_at(
&mut rendered_snippet,
"\t".into(),
false,
&mut SnippetRenderCtx::test_ctx(),
0,
)
.0;
assert_eq!(rendered_text, expect);
assert_eq!(&rendered_snippet.tabstops, tabstops);
assert_eq!(
rendered_snippet.ranges.last().unwrap().end,
rendered_text.chars().count()
);
assert_eq!(rendered_snippet.ranges.last().unwrap().start, 0)
}
#[test]
fn rust_macro() {
assert_snippet(
"macro_rules! ${1:name} {\n\t($3) => {\n\t\t$2\n\t};\n}",
"macro_rules! name {\n\t () => {\n\t \n\t };\n\t}",
&[
Tabstop {
ranges: vec![Range { start: 13, end: 17 }].into(),
parent: None,
kind: TabstopKind::Placeholder,
},
Tabstop {
ranges: vec![Range { start: 42, end: 42 }].into(),
parent: None,
kind: TabstopKind::Empty,
},
Tabstop {
ranges: vec![Range { start: 26, end: 26 }].into(),
parent: None,
kind: TabstopKind::Empty,
},
Tabstop {
ranges: vec![Range { start: 53, end: 53 }].into(),
parent: None,
kind: TabstopKind::Empty,
},
],
);
}
}

View File

@@ -1,18 +1,16 @@
use std::fmt::Display; use std::fmt::Display;
use crate::{movement::Direction, search, Range, Selection}; use crate::{
graphemes::next_grapheme_boundary,
match_brackets::{
find_matching_bracket, find_matching_bracket_fuzzy, get_pair, is_close_bracket,
is_open_bracket,
},
movement::Direction,
search, Range, Selection, Syntax,
};
use ropey::RopeSlice; use ropey::RopeSlice;
pub const PAIRS: &[(char, char)] = &[
('(', ')'),
('[', ']'),
('{', '}'),
('<', '>'),
('«', '»'),
('「', '」'),
('', ''),
];
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub enum Error { pub enum Error {
PairNotFound, PairNotFound,
@@ -34,32 +32,68 @@ impl Display for Error {
type Result<T> = std::result::Result<T, Error>; type Result<T> = std::result::Result<T, Error>;
/// Given any char in [PAIRS], return the open and closing chars. If not found in /// Finds the position of surround pairs of any [`crate::match_brackets::PAIRS`]
/// [PAIRS] return (ch, ch). /// using tree-sitter when possible.
/// ///
/// ``` /// # Returns
/// use helix_core::surround::get_pair;
/// ///
/// assert_eq!(get_pair('['), ('[', ']')); /// Tuple `(anchor, head)`, meaning it is not always ordered.
/// assert_eq!(get_pair('}'), ('{', '}')); pub fn find_nth_closest_pairs_pos(
/// assert_eq!(get_pair('"'), ('"', '"')); syntax: Option<&Syntax>,
/// ``` text: RopeSlice,
pub fn get_pair(ch: char) -> (char, char) { range: Range,
PAIRS skip: usize,
.iter() ) -> Result<(usize, usize)> {
.find(|(open, close)| *open == ch || *close == ch) match syntax {
.copied() Some(syntax) => find_nth_closest_pairs_ts(syntax, text, range, skip),
.unwrap_or((ch, ch)) None => find_nth_closest_pairs_plain(text, range, skip),
}
} }
pub fn find_nth_closest_pairs_pos( fn find_nth_closest_pairs_ts(
syntax: &Syntax,
text: RopeSlice, text: RopeSlice,
range: Range, range: Range,
mut skip: usize, mut skip: usize,
) -> Result<(usize, usize)> { ) -> Result<(usize, usize)> {
let is_open_pair = |ch| PAIRS.iter().any(|(open, _)| *open == ch); let mut opening = range.from();
let is_close_pair = |ch| PAIRS.iter().any(|(_, close)| *close == ch); // We want to expand the selection if we are already on the found pair,
// otherwise we would need to subtract "-1" from "range.to()".
let mut closing = range.to();
while skip > 0 {
closing = find_matching_bracket_fuzzy(syntax, text, closing).ok_or(Error::PairNotFound)?;
opening = find_matching_bracket(syntax, text, closing).ok_or(Error::PairNotFound)?;
// If we're already on a closing bracket "find_matching_bracket_fuzzy" will return
// the position of the opening bracket.
if closing < opening {
(opening, closing) = (closing, opening);
}
// In case found brackets are partially inside current selection.
if range.from() < opening || closing < range.to() - 1 {
closing = next_grapheme_boundary(text, closing);
} else {
skip -= 1;
if skip != 0 {
closing = next_grapheme_boundary(text, closing);
}
}
}
// Keep the original direction.
if let Direction::Forward = range.direction() {
Ok((opening, closing))
} else {
Ok((closing, opening))
}
}
fn find_nth_closest_pairs_plain(
text: RopeSlice,
range: Range,
mut skip: usize,
) -> Result<(usize, usize)> {
let mut stack = Vec::with_capacity(2); let mut stack = Vec::with_capacity(2);
let pos = range.from(); let pos = range.from();
let mut close_pos = pos.saturating_sub(1); let mut close_pos = pos.saturating_sub(1);
@@ -67,7 +101,7 @@ pub fn find_nth_closest_pairs_pos(
for ch in text.chars_at(pos) { for ch in text.chars_at(pos) {
close_pos += 1; close_pos += 1;
if is_open_pair(ch) { if is_open_bracket(ch) {
// Track open pairs encountered so that we can step over // Track open pairs encountered so that we can step over
// the corresponding close pairs that will come up further // the corresponding close pairs that will come up further
// down the loop. We want to find a lone close pair whose // down the loop. We want to find a lone close pair whose
@@ -76,7 +110,7 @@ pub fn find_nth_closest_pairs_pos(
continue; continue;
} }
if !is_close_pair(ch) { if !is_close_bracket(ch) {
// We don't care if this character isn't a brace pair item, // We don't care if this character isn't a brace pair item,
// so short circuit here. // so short circuit here.
continue; continue;
@@ -157,7 +191,11 @@ pub fn find_nth_pairs_pos(
) )
}; };
Option::zip(open, close).ok_or(Error::PairNotFound) // preserve original direction
match range.direction() {
Direction::Forward => Option::zip(open, close).ok_or(Error::PairNotFound),
Direction::Backward => Option::zip(close, open).ok_or(Error::PairNotFound),
}
} }
fn find_nth_open_pair( fn find_nth_open_pair(
@@ -167,6 +205,10 @@ fn find_nth_open_pair(
mut pos: usize, mut pos: usize,
n: usize, n: usize,
) -> Option<usize> { ) -> Option<usize> {
if pos >= text.len_chars() {
return None;
}
let mut chars = text.chars_at(pos + 1); let mut chars = text.chars_at(pos + 1);
// Adjusts pos for the first iteration, and handles the case of the // Adjusts pos for the first iteration, and handles the case of the
@@ -245,6 +287,7 @@ fn find_nth_close_pair(
/// are automatically detected around each cursor (note that this may result /// are automatically detected around each cursor (note that this may result
/// in them selecting different surround characters for each selection). /// in them selecting different surround characters for each selection).
pub fn get_surround_pos( pub fn get_surround_pos(
syntax: Option<&Syntax>,
text: RopeSlice, text: RopeSlice,
selection: &Selection, selection: &Selection,
ch: Option<char>, ch: Option<char>,
@@ -253,14 +296,19 @@ pub fn get_surround_pos(
let mut change_pos = Vec::new(); let mut change_pos = Vec::new();
for &range in selection { for &range in selection {
let (open_pos, close_pos) = match ch { let (open_pos, close_pos) = {
Some(ch) => find_nth_pairs_pos(text, ch, range, skip)?, let range_raw = match ch {
None => find_nth_closest_pairs_pos(text, range, skip)?, Some(ch) => find_nth_pairs_pos(text, ch, range, skip)?,
None => find_nth_closest_pairs_pos(syntax, text, range, skip)?,
};
let range = Range::new(range_raw.0, range_raw.1);
(range.from(), range.to())
}; };
if change_pos.contains(&open_pos) || change_pos.contains(&close_pos) { if change_pos.contains(&open_pos) || change_pos.contains(&close_pos) {
return Err(Error::CursorOverlap); return Err(Error::CursorOverlap);
} }
change_pos.extend_from_slice(&[open_pos, close_pos]); // ensure the positions are always paired in the forward direction
change_pos.extend_from_slice(&[open_pos.min(close_pos), close_pos.max(open_pos)]);
} }
Ok(change_pos) Ok(change_pos)
} }
@@ -283,7 +331,7 @@ mod test {
); );
assert_eq!( assert_eq!(
get_surround_pos(doc.slice(..), &selection, Some('('), 1).unwrap(), get_surround_pos(None, doc.slice(..), &selection, Some('('), 1).unwrap(),
expectations expectations
); );
} }
@@ -298,7 +346,7 @@ mod test {
); );
assert_eq!( assert_eq!(
get_surround_pos(doc.slice(..), &selection, Some('('), 1), get_surround_pos(None, doc.slice(..), &selection, Some('('), 1),
Err(Error::PairNotFound) Err(Error::PairNotFound)
); );
} }
@@ -313,7 +361,7 @@ mod test {
); );
assert_eq!( assert_eq!(
get_surround_pos(doc.slice(..), &selection, Some('('), 1), get_surround_pos(None, doc.slice(..), &selection, Some('('), 1),
Err(Error::PairNotFound) // overlapping surround chars Err(Error::PairNotFound) // overlapping surround chars
); );
} }
@@ -328,7 +376,7 @@ mod test {
); );
assert_eq!( assert_eq!(
get_surround_pos(doc.slice(..), &selection, Some('['), 1), get_surround_pos(None, doc.slice(..), &selection, Some('['), 1),
Err(Error::CursorOverlap) Err(Error::CursorOverlap)
); );
} }
@@ -382,6 +430,21 @@ mod test {
) )
} }
#[test]
fn test_find_nth_closest_pairs_pos_index_range_panic() {
#[rustfmt::skip]
let (doc, selection, _) =
rope_with_selections_and_expectations(
"(a)c)",
"^^^^^"
);
assert_eq!(
find_nth_closest_pairs_pos(None, doc.slice(..), selection.primary(), 1),
Err(Error::PairNotFound)
)
}
// Create a Rope and a matching Selection using a specification language. // Create a Rope and a matching Selection using a specification language.
// ^ is a single-point selection. // ^ is a single-point selection.
// _ is an expected index. These are returned as a Vec<usize> for use in assertions. // _ is an expected index. These are returned as a Vec<usize> for use in assertions.
@@ -397,15 +460,10 @@ mod test {
let selections: SmallVec<[Range; 1]> = spec let selections: SmallVec<[Range; 1]> = spec
.match_indices('^') .match_indices('^')
.into_iter()
.map(|(i, _)| Range::point(i)) .map(|(i, _)| Range::point(i))
.collect(); .collect();
let expectations: Vec<usize> = spec let expectations: Vec<usize> = spec.match_indices('_').map(|(i, _)| i).collect();
.match_indices('_')
.into_iter()
.map(|(i, _)| i)
.collect();
(rope, Selection::new(selections, 0), expectations) (rope, Selection::new(selections, 0), expectations)
} }

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,264 @@
use std::{cmp::Reverse, ops::Range};
use super::{LanguageLayer, LayerId};
use slotmap::HopSlotMap;
use tree_sitter::Node;
/// The byte range of an injection layer.
///
/// Injection ranges may overlap, but all overlapping parts are subsets of their parent ranges.
/// This allows us to sort the ranges ahead of time in order to efficiently find a range that
/// contains a point with maximum depth.
#[derive(Debug)]
struct InjectionRange {
start: usize,
end: usize,
layer_id: LayerId,
depth: u32,
}
pub struct TreeCursor<'a> {
layers: &'a HopSlotMap<LayerId, LanguageLayer>,
root: LayerId,
current: LayerId,
injection_ranges: Vec<InjectionRange>,
// TODO: Ideally this would be a `tree_sitter::TreeCursor<'a>` but
// that returns very surprising results in testing.
cursor: Node<'a>,
}
impl<'a> TreeCursor<'a> {
pub(super) fn new(layers: &'a HopSlotMap<LayerId, LanguageLayer>, root: LayerId) -> Self {
let mut injection_ranges = Vec::new();
for (layer_id, layer) in layers.iter() {
// Skip the root layer
if layer.parent.is_none() {
continue;
}
for byte_range in layer.ranges.iter() {
let range = InjectionRange {
start: byte_range.start_byte,
end: byte_range.end_byte,
layer_id,
depth: layer.depth,
};
injection_ranges.push(range);
}
}
injection_ranges.sort_unstable_by_key(|range| (range.end, Reverse(range.depth)));
let cursor = layers[root].tree().root_node();
Self {
layers,
root,
current: root,
injection_ranges,
cursor,
}
}
pub fn node(&self) -> Node<'a> {
self.cursor
}
pub fn goto_parent(&mut self) -> bool {
if let Some(parent) = self.node().parent() {
self.cursor = parent;
return true;
}
// If we are already on the root layer, we cannot ascend.
if self.current == self.root {
return false;
}
// Ascend to the parent layer.
let range = self.node().byte_range();
let parent_id = self.layers[self.current]
.parent
.expect("non-root layers have a parent");
self.current = parent_id;
let root = self.layers[self.current].tree().root_node();
self.cursor = root
.descendant_for_byte_range(range.start, range.end)
.unwrap_or(root);
true
}
pub fn goto_parent_with<P>(&mut self, predicate: P) -> bool
where
P: Fn(&Node) -> bool,
{
while self.goto_parent() {
if predicate(&self.node()) {
return true;
}
}
false
}
/// Finds the injection layer that has exactly the same range as the given `range`.
fn layer_id_of_byte_range(&self, search_range: Range<usize>) -> Option<LayerId> {
let start_idx = self
.injection_ranges
.partition_point(|range| range.end < search_range.end);
self.injection_ranges[start_idx..]
.iter()
.take_while(|range| range.end == search_range.end)
.find_map(|range| (range.start == search_range.start).then_some(range.layer_id))
}
fn goto_first_child_impl(&mut self, named: bool) -> bool {
// Check if the current node's range is an exact injection layer range.
if let Some(layer_id) = self
.layer_id_of_byte_range(self.node().byte_range())
.filter(|&layer_id| layer_id != self.current)
{
// Switch to the child layer.
self.current = layer_id;
self.cursor = self.layers[self.current].tree().root_node();
return true;
}
let child = if named {
self.cursor.named_child(0)
} else {
self.cursor.child(0)
};
if let Some(child) = child {
// Otherwise descend in the current tree.
self.cursor = child;
true
} else {
false
}
}
pub fn goto_first_child(&mut self) -> bool {
self.goto_first_child_impl(false)
}
pub fn goto_first_named_child(&mut self) -> bool {
self.goto_first_child_impl(true)
}
fn goto_next_sibling_impl(&mut self, named: bool) -> bool {
let sibling = if named {
self.cursor.next_named_sibling()
} else {
self.cursor.next_sibling()
};
if let Some(sibling) = sibling {
self.cursor = sibling;
true
} else {
false
}
}
pub fn goto_next_sibling(&mut self) -> bool {
self.goto_next_sibling_impl(false)
}
pub fn goto_next_named_sibling(&mut self) -> bool {
self.goto_next_sibling_impl(true)
}
fn goto_prev_sibling_impl(&mut self, named: bool) -> bool {
let sibling = if named {
self.cursor.prev_named_sibling()
} else {
self.cursor.prev_sibling()
};
if let Some(sibling) = sibling {
self.cursor = sibling;
true
} else {
false
}
}
pub fn goto_prev_sibling(&mut self) -> bool {
self.goto_prev_sibling_impl(false)
}
pub fn goto_prev_named_sibling(&mut self) -> bool {
self.goto_prev_sibling_impl(true)
}
/// Finds the injection layer that contains the given start-end range.
fn layer_id_containing_byte_range(&self, start: usize, end: usize) -> LayerId {
let start_idx = self
.injection_ranges
.partition_point(|range| range.end < end);
self.injection_ranges[start_idx..]
.iter()
.take_while(|range| range.start < end || range.depth > 1)
.find_map(|range| (range.start <= start).then_some(range.layer_id))
.unwrap_or(self.root)
}
pub fn reset_to_byte_range(&mut self, start: usize, end: usize) {
self.current = self.layer_id_containing_byte_range(start, end);
let root = self.layers[self.current].tree().root_node();
self.cursor = root.descendant_for_byte_range(start, end).unwrap_or(root);
}
/// Returns an iterator over the children of the node the TreeCursor is on
/// at the time this is called.
pub fn children(&'a mut self) -> ChildIter<'a> {
let parent = self.node();
ChildIter {
cursor: self,
parent,
named: false,
}
}
/// Returns an iterator over the named children of the node the TreeCursor is on
/// at the time this is called.
pub fn named_children(&'a mut self) -> ChildIter<'a> {
let parent = self.node();
ChildIter {
cursor: self,
parent,
named: true,
}
}
}
pub struct ChildIter<'n> {
cursor: &'n mut TreeCursor<'n>,
parent: Node<'n>,
named: bool,
}
impl<'n> Iterator for ChildIter<'n> {
type Item = Node<'n>;
fn next(&mut self) -> Option<Self::Item> {
// first iteration, just visit the first child
if self.cursor.node() == self.parent {
self.cursor
.goto_first_child_impl(self.named)
.then(|| self.cursor.node())
} else {
self.cursor
.goto_next_sibling_impl(self.named)
.then(|| self.cursor.node())
}
}
}

View File

@@ -1,9 +1,12 @@
use std::cell::Cell; use std::cell::Cell;
use std::cmp::Ordering;
use std::fmt::Debug;
use std::ops::Range; use std::ops::Range;
use std::rc::Rc; use std::ptr::NonNull;
use crate::doc_formatter::FormattedGrapheme;
use crate::syntax::Highlight; use crate::syntax::Highlight;
use crate::Tendril; use crate::{Position, Tendril};
/// An inline annotation is continuous text shown /// An inline annotation is continuous text shown
/// on the screen before the grapheme that starts at /// on the screen before the grapheme that starts at
@@ -76,39 +79,118 @@ impl Overlay {
} }
} }
/// Line annotations allow for virtual text between normal /// Line annotations allow inserting virtual text lines between normal text
/// text lines. They cause `height` empty lines to be inserted /// lines. These lines can be filled with text in the rendering code as their
/// below the document line that contains `anchor_char_idx`. /// contents have no effect beyond visual appearance.
/// ///
/// These lines can be filled with text in the rendering code /// The height of virtual text is usually not known ahead of time as virtual
/// as their contents have no effect beyond visual appearance. /// text often requires softwrapping. Furthermore the height of some virtual
/// text like side-by-side diffs depends on the height of the text (again
/// influenced by softwrap) and other virtual text. Therefore line annotations
/// are computed on the fly instead of ahead of time like other annotations.
/// ///
/// To insert a line after a document line simply set /// The core of this trait `insert_virtual_lines` function. It is called at the
/// `anchor_char_idx` to `doc.line_to_char(line_idx)` /// end of every visual line and allows the `LineAnnotation` to insert empty
#[derive(Debug, Clone)] /// virtual lines. Apart from that the `LineAnnotation` trait has multiple
pub struct LineAnnotation { /// methods that allow it to track anchors in the document.
pub anchor_char_idx: usize, ///
pub height: usize, /// When a new traversal of a document starts `reset_pos` is called. Afterwards
/// the other functions are called with indices that are larger then the
/// one passed to `reset_pos`. This allows performing a binary search (use
/// `partition_point`) in `reset_pos` once and then to only look at the next
/// anchor during each method call.
///
/// The `reset_pos`, `skip_conceal` and `process_anchor` functions all return a
/// `char_idx` anchor. This anchor is stored when transversing the document and
/// when the grapheme at the anchor is traversed the `process_anchor` function
/// is called.
///
/// # Note
///
/// All functions only receive immutable references to `self`.
/// `LineAnnotation`s that want to store an internal position or
/// state of some kind should use `Cell`. Using interior mutability for
/// caches is preferable as otherwise a lot of lifetimes become invariant
/// which complicates APIs a lot.
pub trait LineAnnotation {
/// Resets the internal position to `char_idx`. This function is called
/// when a new traversal of a document starts.
///
/// All `char_idx` passed to `insert_virtual_lines` are strictly monotonically increasing
/// with the first `char_idx` greater or equal to the `char_idx`
/// passed to this function.
///
/// # Returns
///
/// The `char_idx` of the next anchor this `LineAnnotation` is interested in,
/// replaces the currently registered anchor. Return `usize::MAX` to ignore
fn reset_pos(&mut self, _char_idx: usize) -> usize {
usize::MAX
}
/// Called when a text is concealed that contains an anchor registered by this `LineAnnotation`.
/// In this case the line decorations **must** ensure that virtual text anchored within that
/// char range is skipped.
///
/// # Returns
///
/// The `char_idx` of the next anchor this `LineAnnotation` is interested in,
/// **after the end of conceal_end_char_idx**
/// replaces the currently registered anchor. Return `usize::MAX` to ignore
fn skip_concealed_anchors(&mut self, conceal_end_char_idx: usize) -> usize {
self.reset_pos(conceal_end_char_idx)
}
/// Process an anchor (horizontal position is provided) and returns the next anchor.
///
/// # Returns
///
/// The `char_idx` of the next anchor this `LineAnnotation` is interested in,
/// replaces the currently registered anchor. Return `usize::MAX` to ignore
fn process_anchor(&mut self, _grapheme: &FormattedGrapheme) -> usize {
usize::MAX
}
/// This function is called at the end of a visual line to insert virtual text
///
/// # Returns
///
/// The number of additional virtual lines to reserve
///
/// # Note
///
/// The `line_end_visual_pos` parameter indicates the visual vertical distance
/// from the start of block where the traversal starts. This includes the offset
/// from other `LineAnnotations`. This allows inline annotations to consider
/// the height of the text and "align" two different documents (like for side
/// by side diffs). These annotations that want to "align" two documents should
/// therefore be added last so that other virtual text is also considered while aligning
fn insert_virtual_lines(
&mut self,
line_end_char_idx: usize,
line_end_visual_pos: Position,
doc_line: usize,
) -> Position;
} }
#[derive(Debug)] #[derive(Debug)]
struct Layer<A, M> { struct Layer<'a, A, M> {
annotations: Rc<[A]>, annotations: &'a [A],
current_index: Cell<usize>, current_index: Cell<usize>,
metadata: M, metadata: M,
} }
impl<A, M: Clone> Clone for Layer<A, M> { impl<A, M: Clone> Clone for Layer<'_, A, M> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Layer { Layer {
annotations: self.annotations.clone(), annotations: self.annotations,
current_index: self.current_index.clone(), current_index: self.current_index.clone(),
metadata: self.metadata.clone(), metadata: self.metadata.clone(),
} }
} }
} }
impl<A, M> Layer<A, M> { impl<A, M> Layer<'_, A, M> {
pub fn reset_pos(&self, char_idx: usize, get_char_idx: impl Fn(&A) -> usize) { pub fn reset_pos(&self, char_idx: usize, get_char_idx: impl Fn(&A) -> usize) {
let new_index = self let new_index = self
.annotations .annotations
@@ -128,8 +210,8 @@ impl<A, M> Layer<A, M> {
} }
} }
impl<A, M> From<(Rc<[A]>, M)> for Layer<A, M> { impl<'a, A, M> From<(&'a [A], M)> for Layer<'a, A, M> {
fn from((annotations, metadata): (Rc<[A]>, M)) -> Layer<A, M> { fn from((annotations, metadata): (&'a [A], M)) -> Layer<'a, A, M> {
Layer { Layer {
annotations, annotations,
current_index: Cell::new(0), current_index: Cell::new(0),
@@ -144,23 +226,78 @@ fn reset_pos<A, M>(layers: &[Layer<A, M>], pos: usize, get_pos: impl Fn(&A) -> u
} }
} }
/// Annotations that change that is displayed when the document is render. /// Safety: We store LineAnnotation in a NonNull pointer. This is necessary to work
/// Also commonly called virtual text. /// around an unfortunate inconsistency in rusts variance system that unnnecesarily
#[derive(Default, Debug, Clone)] /// makes the lifetime invariant if implemented with safe code. This makes the
pub struct TextAnnotations { /// DocFormatter API very cumbersome/basically impossible to work with.
inline_annotations: Vec<Layer<InlineAnnotation, Option<Highlight>>>, ///
overlays: Vec<Layer<Overlay, Option<Highlight>>>, /// Normally object types `dyn Foo + 'a` are covariant so if we used `Box<dyn LineAnnotation + 'a>` below
line_annotations: Vec<Layer<LineAnnotation, ()>>, /// everything would be alright. However we want to use `Cell<Box<dyn LineAnnotation + 'a>>`
/// to be able to call the mutable function on `LineAnnotation`. The problem is that
/// some types like `Cell` make all their arguments invariant. This is important for soundness
/// normally for the same reasons that `&'a mut T` is invariant over `T`
/// (see <https://doc.rust-lang.org/nomicon/subtyping.html>). However for `&'a mut` (`dyn Foo + 'b`)
/// there is a specical rule in the language to make `'b` covariant (otherwise trait objects would be
/// super annoying to use). See <https://users.rust-lang.org/t/solved-variance-of-dyn-trait-a> for
/// why this is sound. Sadly that rule doesn't apply to `Cell<Box<(dyn Foo + 'a)>`
/// (or other invariant types like `UnsafeCell` or `*mut (dyn Foo + 'a)`).
///
/// We sidestep the problem by using `NonNull` which is covariant. In the
/// special case of trait objects this is sound (easily checked by adding a
/// `PhantomData<&'a mut Foo + 'a)>` field). We don't need an explicit `Cell`
/// type here because we never hand out any refereces to the trait objects. That
/// means any reference to the pointer can create a valid multable reference
/// that is covariant over `'a` (or in other words it's a raw pointer, as long as
/// we don't hand out references we are free to do whatever we want).
struct RawBox<T: ?Sized>(NonNull<T>);
impl<T: ?Sized> RawBox<T> {
/// Safety: Only a single mutable reference
/// created by this function may exist at a given time.
#[allow(clippy::mut_from_ref)]
unsafe fn get(&self) -> &mut T {
&mut *self.0.as_ptr()
}
}
impl<T: ?Sized> From<Box<T>> for RawBox<T> {
fn from(box_: Box<T>) -> Self {
// obviously safe because Box::into_raw never returns null
unsafe { Self(NonNull::new_unchecked(Box::into_raw(box_))) }
}
} }
impl TextAnnotations { impl<T: ?Sized> Drop for RawBox<T> {
fn drop(&mut self) {
unsafe { drop(Box::from_raw(self.0.as_ptr())) }
}
}
/// Annotations that change that is displayed when the document is render.
/// Also commonly called virtual text.
#[derive(Default)]
pub struct TextAnnotations<'a> {
inline_annotations: Vec<Layer<'a, InlineAnnotation, Option<Highlight>>>,
overlays: Vec<Layer<'a, Overlay, Option<Highlight>>>,
line_annotations: Vec<(Cell<usize>, RawBox<dyn LineAnnotation + 'a>)>,
}
impl Debug for TextAnnotations<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TextAnnotations")
.field("inline_annotations", &self.inline_annotations)
.field("overlays", &self.overlays)
.finish_non_exhaustive()
}
}
impl<'a> TextAnnotations<'a> {
/// Prepare the TextAnnotations for iteration starting at char_idx /// Prepare the TextAnnotations for iteration starting at char_idx
pub fn reset_pos(&self, char_idx: usize) { pub fn reset_pos(&self, char_idx: usize) {
reset_pos(&self.inline_annotations, char_idx, |annot| annot.char_idx); reset_pos(&self.inline_annotations, char_idx, |annot| annot.char_idx);
reset_pos(&self.overlays, char_idx, |annot| annot.char_idx); reset_pos(&self.overlays, char_idx, |annot| annot.char_idx);
reset_pos(&self.line_annotations, char_idx, |annot| { for (next_anchor, layer) in &self.line_annotations {
annot.anchor_char_idx next_anchor.set(unsafe { layer.get().reset_pos(char_idx) });
}); }
} }
pub fn collect_overlay_highlights( pub fn collect_overlay_highlights(
@@ -194,10 +331,12 @@ impl TextAnnotations {
/// the annotations that belong to the layers added first will be shown first. /// the annotations that belong to the layers added first will be shown first.
pub fn add_inline_annotations( pub fn add_inline_annotations(
&mut self, &mut self,
layer: Rc<[InlineAnnotation]>, layer: &'a [InlineAnnotation],
highlight: Option<Highlight>, highlight: Option<Highlight>,
) -> &mut Self { ) -> &mut Self {
self.inline_annotations.push((layer, highlight).into()); if !layer.is_empty() {
self.inline_annotations.push((layer, highlight).into());
}
self self
} }
@@ -211,8 +350,10 @@ impl TextAnnotations {
/// ///
/// If multiple layers contain overlay at the same position /// If multiple layers contain overlay at the same position
/// the overlay from the layer added last will be show. /// the overlay from the layer added last will be show.
pub fn add_overlay(&mut self, layer: Rc<[Overlay]>, highlight: Option<Highlight>) -> &mut Self { pub fn add_overlay(&mut self, layer: &'a [Overlay], highlight: Option<Highlight>) -> &mut Self {
self.overlays.push((layer, highlight).into()); if !layer.is_empty() {
self.overlays.push((layer, highlight).into());
}
self self
} }
@@ -220,8 +361,9 @@ impl TextAnnotations {
/// ///
/// The line annotations **must be sorted** by their `char_idx`. /// The line annotations **must be sorted** by their `char_idx`.
/// Multiple line annotations with the same `char_idx` **are not allowed**. /// Multiple line annotations with the same `char_idx` **are not allowed**.
pub fn add_line_annotation(&mut self, layer: Rc<[LineAnnotation]>) -> &mut Self { pub fn add_line_annotation(&mut self, layer: Box<dyn LineAnnotation + 'a>) -> &mut Self {
self.line_annotations.push((layer, ()).into()); self.line_annotations
.push((Cell::new(usize::MAX), layer.into()));
self self
} }
@@ -251,21 +393,35 @@ impl TextAnnotations {
overlay overlay
} }
pub(crate) fn annotation_lines_at(&self, char_idx: usize) -> usize { pub(crate) fn process_virtual_text_anchors(&self, grapheme: &FormattedGrapheme) {
self.line_annotations for (next_anchor, layer) in &self.line_annotations {
.iter() loop {
.map(|layer| { match next_anchor.get().cmp(&grapheme.char_idx) {
let mut lines = 0; Ordering::Less => next_anchor
while let Some(annot) = layer.annotations.get(layer.current_index.get()) { .set(unsafe { layer.get().skip_concealed_anchors(grapheme.char_idx) }),
if annot.anchor_char_idx == char_idx { Ordering::Equal => {
layer.current_index.set(layer.current_index.get() + 1); next_anchor.set(unsafe { layer.get().process_anchor(grapheme) })
lines += annot.height
} else {
break;
} }
} Ordering::Greater => break,
lines };
}) }
.sum() }
}
pub(crate) fn virtual_lines_at(
&self,
char_idx: usize,
line_end_visual_pos: Position,
doc_line: usize,
) -> usize {
let mut virt_off = Position::new(0, 0);
for (_, layer) in &self.line_annotations {
virt_off += unsafe {
layer
.get()
.insert_virtual_lines(char_idx, line_end_visual_pos + virt_off, doc_line)
};
}
virt_off.row
} }
} }

View File

@@ -7,9 +7,9 @@ use crate::chars::{categorize_char, char_is_whitespace, CharCategory};
use crate::graphemes::{next_grapheme_boundary, prev_grapheme_boundary}; use crate::graphemes::{next_grapheme_boundary, prev_grapheme_boundary};
use crate::line_ending::rope_is_line_ending; use crate::line_ending::rope_is_line_ending;
use crate::movement::Direction; use crate::movement::Direction;
use crate::surround;
use crate::syntax::LanguageConfiguration; use crate::syntax::LanguageConfiguration;
use crate::Range; use crate::Range;
use crate::{surround, Syntax};
fn find_word_boundary(slice: RopeSlice, mut pos: usize, direction: Direction, long: bool) -> usize { fn find_word_boundary(slice: RopeSlice, mut pos: usize, direction: Direction, long: bool) -> usize {
use CharCategory::{Eol, Whitespace}; use CharCategory::{Eol, Whitespace};
@@ -199,25 +199,28 @@ pub fn textobject_paragraph(
} }
pub fn textobject_pair_surround( pub fn textobject_pair_surround(
syntax: Option<&Syntax>,
slice: RopeSlice, slice: RopeSlice,
range: Range, range: Range,
textobject: TextObject, textobject: TextObject,
ch: char, ch: char,
count: usize, count: usize,
) -> Range { ) -> Range {
textobject_pair_surround_impl(slice, range, textobject, Some(ch), count) textobject_pair_surround_impl(syntax, slice, range, textobject, Some(ch), count)
} }
pub fn textobject_pair_surround_closest( pub fn textobject_pair_surround_closest(
syntax: Option<&Syntax>,
slice: RopeSlice, slice: RopeSlice,
range: Range, range: Range,
textobject: TextObject, textobject: TextObject,
count: usize, count: usize,
) -> Range { ) -> Range {
textobject_pair_surround_impl(slice, range, textobject, None, count) textobject_pair_surround_impl(syntax, slice, range, textobject, None, count)
} }
fn textobject_pair_surround_impl( fn textobject_pair_surround_impl(
syntax: Option<&Syntax>,
slice: RopeSlice, slice: RopeSlice,
range: Range, range: Range,
textobject: TextObject, textobject: TextObject,
@@ -226,8 +229,7 @@ fn textobject_pair_surround_impl(
) -> Range { ) -> Range {
let pair_pos = match ch { let pair_pos = match ch {
Some(ch) => surround::find_nth_pairs_pos(slice, ch, range, count), Some(ch) => surround::find_nth_pairs_pos(slice, ch, range, count),
// Automatically find the closest surround pairs None => surround::find_nth_closest_pairs_pos(syntax, slice, range, count),
None => surround::find_nth_closest_pairs_pos(slice, range, count),
}; };
pair_pos pair_pos
.map(|(anchor, head)| match textobject { .map(|(anchor, head)| match textobject {
@@ -574,7 +576,8 @@ mod test {
let slice = doc.slice(..); let slice = doc.slice(..);
for &case in scenario { for &case in scenario {
let (pos, objtype, expected_range, ch, count) = case; let (pos, objtype, expected_range, ch, count) = case;
let result = textobject_pair_surround(slice, Range::point(pos), objtype, ch, count); let result =
textobject_pair_surround(None, slice, Range::point(pos), objtype, ch, count);
assert_eq!( assert_eq!(
result, result,
expected_range.into(), expected_range.into(),

Some files were not shown because too many files have changed in this diff Show More