on master help sign in
191 files changed+7727−2283
since splitsnapshots
unifiedsplit
.envrc+1 .github/ISSUE_TEMPLATE/bug_report.yaml+10 .github/workflows/build.yml+11−3 .github/workflows/cachix.yml+2−2 .github/workflows/gh-pages.yml+4−4 .github/workflows/release.yml+10−10 CHANGELOG.md+260 Cargo.lock+419−598 Cargo.toml+11 README.md+1−1 VERSION−1 book/custom.css+1−1 book/src/configuration.md+27−9 book/src/generated/lang-support.md+22−11 book/src/generated/typable-cmd.md+4−1 book/src/guides/adding_languages.md+2 book/src/guides/indent.md+9 book/src/guides/injection.md+1−1 book/src/install.md+30−6 book/src/keymap.md+1−1 book/src/languages.md+3−1 book/src/themes.md+8−1 book/src/usage.md+2−2 book/theme/index.hbs+18−15 contrib/Helix.appdata.xml+15 contrib/Helix.desktop+3−1 docs/CONTRIBUTING.md+10−3 docs/releases.md+12−5 flake.lock+12−35 flake.nix+12−14 grammars.nix+24−21 helix-core/Cargo.toml+14−13 helix-core/src/diagnostic.rs+4 helix-core/src/fuzzy.rs+3−3 helix-core/src/indent.rs+316−103 helix-core/src/syntax.rs+22−6 helix-core/src/transaction.rs+73−14 helix-core/src/wrap.rs+3−1 helix-core/tests/indent.rs+2−2 helix-dap/Cargo.toml+11−9 helix-event/Cargo.toml+8−7 helix-loader/Cargo.toml+12−11 helix-loader/build.rs+14−4 helix-loader/src/lib.rs+13−4 helix-lsp/Cargo.toml+15−14 helix-lsp/src/client.rs+87−13 helix-lsp/src/lib.rs+32−28 helix-parsec/Cargo.toml+8−7 helix-term/Cargo.toml+27−23 helix-term/src/application.rs+100−47 helix-term/src/args.rs+29 helix-term/src/commands.rs+193−97 helix-term/src/commands/dap.rs+7−2 helix-term/src/commands/lsp.rs+12−2 helix-term/src/commands/typed.rs+254−42 helix-term/src/compositor.rs+6 helix-term/src/health.rs+44−16 helix-term/src/main.rs+17−1 helix-term/src/ui/completion.rs+17−1 helix-term/src/ui/document.rs+60−24 helix-term/src/ui/editor.rs+77−44 helix-term/src/ui/lsp.rs+3−1 helix-term/src/ui/markdown.rs+12−5 helix-term/src/ui/menu.rs+37−16 helix-term/src/ui/mod.rs+24−7 helix-term/src/ui/picker.rs+51−24 helix-term/src/ui/popup.rs+27−7 helix-term/tests/test/commands.rs+46 helix-term/tests/test/commands/write.rs+122−3 helix-term/tests/test/helpers.rs+9−1 helix-term/tests/test/splits.rs+3−3 helix-tui/Cargo.toml+13−13 helix-tui/src/backend/crossterm.rs+18−2 helix-tui/src/buffer.rs+2−2 helix-vcs/Cargo.toml+12−11 helix-vcs/src/git.rs+5−5 helix-view/Cargo.toml+19−17 helix-view/src/document.rs+58−21 helix-view/src/editor.rs+88−56 helix-view/src/gutter.rs+4−5 helix-view/src/handlers/dap.rs+1−3 helix-view/src/input.rs+59−1 helix-view/src/register.rs+10−10 helix-view/src/theme.rs+5 languages.toml+394−193 logo.svg+1−1 runtime/queries/_typescript/highlights.scm+5−3 runtime/queries/_typescript/locals.scm+17 runtime/queries/agda/highlights.scm+124 runtime/queries/bash/indents.scm+1 runtime/queries/c/indents.scm+13 runtime/queries/comment/highlights.scm+8−8 runtime/queries/common-lisp/indents.scm+1 runtime/queries/dbml/highlights.scm+44 runtime/queries/gas/highlights.scm+21 runtime/queries/gas/injections.scm+2 runtime/queries/gas/textobjects.scm+2 runtime/queries/gleam/highlights.scm+16−5 runtime/queries/gn/highlights.scm+42 runtime/queries/gn/injections.scm+15 runtime/queries/gn/locals.scm+16 runtime/queries/go/highlights.scm+13−5 runtime/queries/go/locals.scm+10−2 runtime/queries/haskell/highlights.scm+24−11 runtime/queries/janet/highlights.scm+1 runtime/queries/json5/highlights.scm+11 runtime/queries/kdl/highlights.scm+4−4 runtime/queries/kdl/indents.scm+3 runtime/queries/kdl/textobjects.scm+27 runtime/queries/kotlin/highlights.scm+4−1 runtime/queries/kotlin/locals.scm+15 runtime/queries/log/highlights.scm+10 runtime/queries/lpf/highlights.scm+19 runtime/queries/nix/injections.scm+14 runtime/queries/ocaml/highlights.scm+2 runtime/queries/perl/indents.scm+29 runtime/queries/perl/textobjects.scm+14 runtime/queries/purescript/highlights.scm+164−1 runtime/queries/purescript/injections.scm+2−1 runtime/queries/purescript/locals.scm+4−1 runtime/queries/purescript/textobjects.scm+13 runtime/queries/python/highlights.scm+6 runtime/queries/racket/indents.scm+1 runtime/queries/ron/highlights.scm+43−1 runtime/queries/ron/indents.scm+12−1 runtime/queries/ron/injections.scm+2−1 runtime/queries/rust/highlights.scm+7 runtime/queries/rust/injections.scm+6 runtime/queries/rust/locals.scm+14−1 runtime/queries/scheme/highlights.scm+5 runtime/queries/scheme/indents.scm+43 runtime/queries/smali/folds.scm+12 runtime/queries/smali/highlights.scm+216 runtime/queries/smali/indents.scm+31 runtime/queries/smali/injections.scm+2 runtime/queries/smali/locals.scm+42 runtime/queries/sql/highlights.scm+317−231 runtime/queries/templ/highlights.scm+99 runtime/queries/templ/injections.scm+4 runtime/queries/typst/highlights.scm+77 runtime/queries/typst/injections.scm+6 runtime/queries/unison/highlights.scm+21−6 runtime/queries/yaml/injections.scm+52 runtime/queries/yuck/highlights.scm+1−1 runtime/themes/README.md+8 runtime/themes/cyan_light.toml+154 runtime/themes/darcula-solid.toml+1−4 runtime/themes/darcula.toml+10−4 runtime/themes/dracula.toml+2 runtime/themes/everblush.toml+1 runtime/themes/gruber-darker.toml+114 runtime/themes/horizon-dark.toml+80 runtime/themes/jellybeans.toml+1−1 runtime/themes/licenses/everforest.LICENSE+21 runtime/themes/licenses/modus_vivendi.LICENSE+5 runtime/themes/licenses/modus_vivendi_deuteranopia.LICENSE+5 runtime/themes/licenses/modus_vivendi_tinted.LICENSE+5 runtime/themes/licenses/modus_vivendi_tritanopia.LICENSE+5 runtime/themes/licenses/poimandres.LICENSE+21 runtime/themes/licenses/serika-syntax.LICENSE+21 runtime/themes/licenses/sonokai.LICENSE+21 runtime/themes/licenses/starlight.LICENSE+24 runtime/themes/material_darker.toml+20 runtime/themes/material_deep_ocean.toml+123 runtime/themes/material_oceanic.toml+21 runtime/themes/material_palenight.toml+19 runtime/themes/modus_operandi.toml+194 runtime/themes/modus_operandi_deuteranopia.toml+46 runtime/themes/modus_operandi_tinted.toml+45 runtime/themes/modus_operandi_tritanopia.toml+73 runtime/themes/modus_vivendi.toml+242 runtime/themes/modus_vivendi_deuteranopia.toml+158 runtime/themes/modus_vivendi_tinted.toml+144 runtime/themes/modus_vivendi_tritanopia.toml+186 runtime/themes/molokai.toml+1−1 runtime/themes/naysayer.toml+2−2 runtime/themes/nightfox.toml+2−2 runtime/themes/noctis.toml+26−26 runtime/themes/nord-night.toml+23 runtime/themes/nord.toml+16−7 runtime/themes/onedark.toml+1 runtime/themes/papercolor-dark.toml+67−116 runtime/themes/papercolor-light.toml+194−103 runtime/themes/poimandres.toml+113 runtime/themes/poimandres_storm.toml+19 runtime/themes/rose_pine.toml+31−29 runtime/themes/starlight.toml+113 runtime/themes/zenburn.toml+1−1 runtime/tutor+157−3 rust-toolchain.toml+2−2 xtask/Cargo.toml+12−6
.envrc+1
@@ -1,5 +1,6 @@
11watch_file shell.nix
22watch_file flake.lock
3+watch_file rust-toolchain.toml
34
45# try to use flakes, if it fails use normal nix (ie. shell.nix)
56use flake || use nix
.github/ISSUE_TEMPLATE/bug_report.yaml+10
@@ -55,6 +55,16 @@ body:
5555 placeholder: wezterm 20220101-133340-7edc5b5a
5656 validations:
5757 required: true
58+ - type: input
59+ id: installation-method
60+ attributes:
61+ label: Installation Method
62+ description: >
63+ How you installed Helix - from a package manager like Homebrew or the
64+ AUR, built from source, downloaded a binary from the releases page, etc.
65+ placeholder: "source / brew / nixpkgs / flake / releases page"
66+ validations:
67+ required: true
5868 - type: input
5969 id: helix-version
6070 attributes:
.github/workflows/build.yml+11−3
@@ -22,6 +22,8 @@ jobs:
2222 override: true
2323
2424 - uses: Swatinem/rust-cache@v2
25+ with:
26+ shared-key: "build"
2527
2628 - name: Run cargo check
2729 run: cargo check
@@ -37,9 +39,11 @@ jobs:
3739 uses: actions/checkout@v4
3840
3941 - name: Install stable toolchain
40− uses: dtolnay/rust-toolchain@1.65
42+ uses: dtolnay/rust-toolchain@1.70
4143
4244 - uses: Swatinem/rust-cache@v2
45+ with:
46+ shared-key: "build"
4347
4448 - name: Cache test tree-sitter grammar
4549 uses: actions/cache@v3
@@ -66,11 +70,13 @@ jobs:
6670 uses: actions/checkout@v4
6771
6872 - name: Install stable toolchain
69− uses: dtolnay/rust-toolchain@1.65
73+ uses: dtolnay/rust-toolchain@1.70
7074 with:
7175 components: rustfmt, clippy
7276
7377 - uses: Swatinem/rust-cache@v2
78+ with:
79+ shared-key: "build"
7480
7581 - name: Run cargo fmt
7682 run: cargo fmt --all --check
@@ -91,9 +97,11 @@ jobs:
9197 uses: actions/checkout@v4
9298
9399 - name: Install stable toolchain
94− uses: dtolnay/rust-toolchain@1.65
100+ uses: dtolnay/rust-toolchain@1.70
95101
96102 - uses: Swatinem/rust-cache@v2
103+ with:
104+ shared-key: "build"
97105
98106 - name: Validate queries
99107 run: cargo xtask query-check
.github/workflows/cachix.yml+2−2
@@ -14,10 +14,10 @@ jobs:
1414 uses: actions/checkout@v4
1515
1616 - name: Install nix
17− uses: cachix/install-nix-action@v23
17+ uses: cachix/install-nix-action@v24
1818
1919 - name: Authenticate with Cachix
20− uses: cachix/cachix-action@v12
20+ uses: cachix/cachix-action@v13
2121 with:
2222 name: helix
2323 authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
.github/workflows/gh-pages.yml+4−4
@@ -26,16 +26,16 @@ jobs:
2626 OUTDIR=$(basename ${{ github.ref }})
2727 echo "OUTDIR=$OUTDIR" >> $GITHUB_ENV
2828
29− - name: Deploy
29+ - name: Deploy stable
3030 uses: peaceiris/actions-gh-pages@v3
31+ if: startswith(github.ref, 'refs/tags/')
3132 with:
3233 github_token: ${{ secrets.GITHUB_TOKEN }}
3334 publish_dir: ./book/book
34− destination_dir: ./${{ env.OUTDIR }}
3535
36− - name: Deploy stable
36+ - name: Deploy
3737 uses: peaceiris/actions-gh-pages@v3
38− if: startswith(github.ref, 'refs/tags/')
3938 with:
4039 github_token: ${{ secrets.GITHUB_TOKEN }}
4140 publish_dir: ./book/book
41+ destination_dir: ./${{ env.OUTDIR }}
.github/workflows/release.yml+10−10
@@ -36,7 +36,7 @@ jobs:
3636 - name: Bundle grammars
3737 run: tar cJf grammars.tar.xz -C runtime/grammars/sources .
3838
39− - uses: actions/upload-artifact@v3
39+ - uses: actions/upload-artifact@v4
4040 with:
4141 name: grammars
4242 path: grammars.tar.xz
@@ -70,11 +70,11 @@ jobs:
7070 rust: stable
7171 target: aarch64-unknown-linux-gnu
7272 cross: true
73− - build: riscv64-linux
74− os: ubuntu-latest
75− rust: stable
76− target: riscv64gc-unknown-linux-gnu
77− cross: true
73+ # - build: riscv64-linux
74+ # os: ubuntu-latest
75+ # rust: stable
76+ # target: riscv64gc-unknown-linux-gnu
77+ # cross: true
7878 - build: x86_64-macos
7979 os: macos-latest
8080 rust: stable
@@ -106,7 +106,7 @@ jobs:
106106 uses: actions/checkout@v4
107107
108108 - name: Download grammars
109− uses: actions/download-artifact@v3
109+ uses: actions/download-artifact@v4
110110
111111 - name: Move grammars under runtime
112112 if: "!startsWith(matrix.os, 'windows')"
@@ -220,7 +220,7 @@ jobs:
220220 fi
221221 cp -r runtime dist
222222
223− - uses: actions/upload-artifact@v3
223+ - uses: actions/upload-artifact@v4
224224 with:
225225 name: bins-${{ matrix.build }}
226226 path: dist
@@ -233,7 +233,7 @@ jobs:
233233 - name: Checkout sources
234234 uses: actions/checkout@v4
235235
236− - uses: actions/download-artifact@v3
236+ - uses: actions/download-artifact@v4
237237
238238 - name: Build archive
239239 shell: bash
@@ -288,7 +288,7 @@ jobs:
288288 overwrite: true
289289
290290 - name: Upload binaries as artifact
291− uses: actions/upload-artifact@v3
291+ uses: actions/upload-artifact@v4
292292 if: env.preview == 'true'
293293 with:
294294 name: release
CHANGELOG.md+260
@@ -1,3 +1,263 @@
1+# 23.10 (2023-10-24)
2+
3+A big shout out to all the contributors! We had 118 contributors in this release.
4+
5+Breaking changes:
6+
7+- Support multiple language servers per language ([#2507](https://github.com/helix-editor/helix/pull/2507))
8+ - This is a breaking change to language configuration
9+
10+Features:
11+
12+- 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))
13+- Add a statusline element for the selected register ([#7222](https://github.com/helix-editor/helix/pull/7222))
14+- Add `%`, `#`, `.`, `*` and `+` special registers ([#6985](https://github.com/helix-editor/helix/pull/6985))
15+- Add initial support for LSP DidChangeWatchedFiles notifications ([#7665](https://github.com/helix-editor/helix/pull/7665))
16+- Search buffer contents in `global_search` ([#5652](https://github.com/helix-editor/helix/pull/5652))
17+- Add a "smart tab" command that intelligently jumps the cursor on tab ([#4443](https://github.com/helix-editor/helix/pull/4443))
18+- 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))
19+- Syntax highlight regex prompts ([#7738](https://github.com/helix-editor/helix/pull/7738))
20+- Allow defining alignment in indent queries ([#5355](https://github.com/helix-editor/helix/pull/5355))
21+- Show visual feedback in `surround_replace` ([#7588](https://github.com/helix-editor/helix/pull/7588))
22+- 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))
23+- Insert a trailing newline on write ([#8157](https://github.com/helix-editor/helix/pull/8157))
24+- 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))
25+- Accept a `+N` CLI argument to set the first file's line number ([#8521](https://github.com/helix-editor/helix/pull/8521))
26+- Accept Helix-specific ignore files in `.helix/ignore` and `~/.config/helix/ignore` ([#8099](https://github.com/helix-editor/helix/pull/8099))
27+
28+Commands:
29+
30+- `merge_selections` (`A-minus`) - merge all selections into one selection that covers all ranges ([#7053](https://github.com/helix-editor/helix/pull/7053))
31+- `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))
32+- `reverse_selection_contents` - swaps the values of each selection so they are reversed ([#7329](https://github.com/helix-editor/helix/pull/7329))
33+- Add `:rl` and `:rla` aliases for `:reload` and `:reload-all` ([#7158](https://github.com/helix-editor/helix/pull/7158))
34+- `yank_joined` - join the selections and yank to the selected register ([#7195](https://github.com/helix-editor/helix/pull/7195))
35+- `:write-all!` (`:wa!`) - forcibly write all buffers to disk and create any necessary subdirectories ([#7577](https://github.com/helix-editor/helix/pull/7577))
36+- `:redraw` - clear re-render the UI ([#6949](https://github.com/helix-editor/helix/pull/6949))
37+- `:tree-sitter-highlight-name` - show the theme scope name of the highlight under the cursor ([#8170](https://github.com/helix-editor/helix/pull/8170))
38+
39+Usability improvements:
40+
41+- 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))
42+- Exit gracefully on termination signals ([#7236](https://github.com/helix-editor/helix/pull/7236))
43+- Add plaintext matching fallback to tree-sitter pair matching ([#4288](https://github.com/helix-editor/helix/pull/4288))
44+- Persist register selection in pending keymaps ([0e08349](https://github.com/helix-editor/helix/commit/0e08349))
45+- Propagate the count and register to command palette commands ([b394997](https://github.com/helix-editor/helix/commit/b394997))
46+- Auto indent on `insert_at_line_start` ([#5837](https://github.com/helix-editor/helix/pull/5837))
47+- Add a config option to control whether LSP completions are automatically inserted on preview ([#7189](https://github.com/helix-editor/helix/pull/7189))
48+- 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))
49+- Allow ANSI colors in themes ([#5119](https://github.com/helix-editor/helix/pull/5119))
50+- Match pairs that don't form a standalone tree-sitter node ([#7242](https://github.com/helix-editor/helix/pull/7242))
51+- Allow indent sizes of up to 16 columns ([#7429](https://github.com/helix-editor/helix/pull/7429))
52+- 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))
53+- Mark buffers created from stdin as modified ([#7431](https://github.com/helix-editor/helix/pull/7431))
54+- Forcibly shut down uninitialized language servers ([#7449](https://github.com/helix-editor/helix/pull/7449))
55+- Add filename completer for shell prompts ([#7569](https://github.com/helix-editor/helix/pull/7569))
56+- Allow binding F13-F24 ([#7672](https://github.com/helix-editor/helix/pull/7672))
57+- Resolve LSP code actions ([#7677](https://github.com/helix-editor/helix/pull/7677), [#8421](https://github.com/helix-editor/helix/pull/8421))
58+- Save an undo checkpoint before accepting completions ([#7747](https://github.com/helix-editor/helix/pull/7747))
59+- Include gitignored files in debugger completions ([#7936](https://github.com/helix-editor/helix/pull/7936))
60+- Make editor remember the last search register ([#5244](https://github.com/helix-editor/helix/pull/5244))
61+- Open directories with `goto_file` ([#7909](https://github.com/helix-editor/helix/pull/7909))
62+- Use relative path to open buffer in `goto_file` (`gf`) ([#7965](https://github.com/helix-editor/helix/pull/7965))
63+- Support `default` color in themes ([#8083](https://github.com/helix-editor/helix/pull/8083), [#8114](https://github.com/helix-editor/helix/pull/8114))
64+- Toggle between relative and absolute line numbers when the terminal loses focus ([#7955](https://github.com/helix-editor/helix/pull/7955))
65+- Lower default idle-timeout to 250ms ([060e73a](https://github.com/helix-editor/helix/commit/060e73a))
66+- Allow theming diff gutters separately from other diff colors ([#8343](https://github.com/helix-editor/helix/pull/8343))
67+- Style bold/italic/strikethrough in markdown doc popups ([#8385](https://github.com/helix-editor/helix/pull/8385))
68+- Maintain the cursor position and view when splitting with `:hsplit`/`:vsplit` ([#8109](https://github.com/helix-editor/helix/pull/8109))
69+- Accept `-` in macros outside of `<`/`>` ([#8475](https://github.com/helix-editor/helix/pull/8475))
70+- Show all language servers for each language in `--health` ([#7315](https://github.com/helix-editor/helix/pull/7315))
71+- Don't break on hyphens in `:reflow` ([#8569](https://github.com/helix-editor/helix/pull/8569))
72+
73+Fixes:
74+
75+- Update diagnostics correctly on language server exit ([#7111](https://github.com/helix-editor/helix/pull/7111))
76+- Fix off-by-one in `select_references_to_symbol_under_cursor` ([#7132](https://github.com/helix-editor/helix/pull/7132))
77+- Extend selection with repeat-last-motion only if the original motion extended the selection ([#7159](https://github.com/helix-editor/helix/pull/7159))
78+- Fix undefined behavior in the diff gutter ([#7227](https://github.com/helix-editor/helix/pull/7227))
79+- Check that tab width is non-zero ([#7178](https://github.com/helix-editor/helix/pull/7178))
80+- Fix styles being overwritten in table rows with multiple cells ([#7281](https://github.com/helix-editor/helix/pull/7281))
81+- Add file for `--log` CLI arg in help text ([#7307](https://github.com/helix-editor/helix/pull/7307))
82+- Fix underflow when repeating a completion that has a negative shift position ([#7322](https://github.com/helix-editor/helix/pull/7322))
83+- Prefer longer matches in `select_next_sibling` and `select_prev_sibling` ([#7332](https://github.com/helix-editor/helix/pull/7332))
84+- Preview scratch buffers in the jumplist picker ([#7331](https://github.com/helix-editor/helix/pull/7331))
85+- Fix chunking by bytes in tree-sitter parsing ([#7417](https://github.com/helix-editor/helix/pull/7417))
86+- Discard LSP publishDiagnostic from uninitialized servers ([#7467](https://github.com/helix-editor/helix/pull/7467))
87+- Use negotiated position encoding for LSP workspace edits ([#7469](https://github.com/helix-editor/helix/pull/7469))
88+- Fix error message for unknown gutter types in config ([#7534](https://github.com/helix-editor/helix/pull/7534))
89+- 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))
90+- 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))
91+- Fix crash when the current working directory is deleted ([#7185](https://github.com/helix-editor/helix/pull/7185))
92+- Fix piping to Helix on macOS ([#5468](https://github.com/helix-editor/helix/pull/5468))
93+- Fix crash when parsing overlapping injections ([#7621](https://github.com/helix-editor/helix/pull/7621))
94+- Clear the statusline when the prompt is visible ([#7646](https://github.com/helix-editor/helix/pull/7646))
95+- Fix range formatting error message typo ([#7823](https://github.com/helix-editor/helix/pull/7823))
96+- Skip rendering gutters when gutter width exceeds view width ([#7821](https://github.com/helix-editor/helix/pull/7821))
97+- Center the picker preview using visual lines ([#7837](https://github.com/helix-editor/helix/pull/7837))
98+- Align view correctly for background buffers opened with `A-ret` ([#7691](https://github.com/helix-editor/helix/pull/7691))
99+- Fix cursor resetting to block when quitting via a keybind ([#7931](https://github.com/helix-editor/helix/pull/7931))
100+- Remove path completions for the `:new` command ([#8010](https://github.com/helix-editor/helix/pull/8010))
101+- Use binary path resolved by `which` for formatter commands ([#8064](https://github.com/helix-editor/helix/pull/8064))
102+- Handle crossterm's `hidden` modifier ([#8120](https://github.com/helix-editor/helix/pull/8120))
103+- Clear completion when switching between windows with the mouse ([#8118](https://github.com/helix-editor/helix/pull/8118))
104+- Eagerly remove the last picker (`<space>'`) when the picker has many items ([#8127](https://github.com/helix-editor/helix/pull/8127))
105+- Fix find commands for buffers with non-LF line-endings ([#8111](https://github.com/helix-editor/helix/pull/8111))
106+- Detect the tmux clipboard provider on macOS ([#8182](https://github.com/helix-editor/helix/pull/8182))
107+- Fix syntax highlighting in dynamic picker preview pane ([#8206](https://github.com/helix-editor/helix/pull/8206))
108+- Recognize HTML code tags with attributes as code in markdown previews ([#8397](https://github.com/helix-editor/helix/pull/8397))
109+- Fix multicursor snippet placeholder directions ([#8423](https://github.com/helix-editor/helix/pull/8423))
110+- Only show diagnostic highlights when diagnostics are enabled for a language server ([#8551](https://github.com/helix-editor/helix/pull/8551))
111+
112+Themes:
113+
114+- Improve the selection color in `ferra` ([#7138](https://github.com/helix-editor/helix/pull/7138))
115+- Add `variable.other.member` theming to `spacebones_light` ([#7125](https://github.com/helix-editor/helix/pull/7125))
116+- Update `autumn` and theme the soft-wrap indicator ([#7229](https://github.com/helix-editor/helix/pull/7229))
117+- Add `gruvbox_dark_soft` ([#7139](https://github.com/helix-editor/helix/pull/7139))
118+- Add `merionette` ([#7186](https://github.com/helix-editor/helix/pull/7186))
119+- Add `zed_onedark` and `zed_onelight` ([#7250](https://github.com/helix-editor/helix/pull/7250))
120+- Use light-gray for `onedarker` inlay hint theming ([#7433](https://github.com/helix-editor/helix/pull/7433))
121+- Update the Nord theme to follow the style guidelines ([#7490](https://github.com/helix-editor/helix/pull/7490))
122+- Tune `dark_plus` inlay hint colors ([#7611](https://github.com/helix-editor/helix/pull/7611))
123+- Add `naysayer` ([#7570](https://github.com/helix-editor/helix/pull/7570))
124+- Add `kaolin-dark`, `kaolin-light` and `kaolin-valley-dark` ([#7151](https://github.com/helix-editor/helix/pull/7151))
125+- Fix selection highlighting in gruvbox variants ([#7717](https://github.com/helix-editor/helix/pull/7717))
126+- Add soft-wrap indicator to `gruvbox` ([#7736](https://github.com/helix-editor/helix/pull/7736))
127+- Add missing palette definitions in `everforest_dark` ([#7739](https://github.com/helix-editor/helix/pull/7739))
128+- Increase diagnostics clarity in `pop-dark` ([#7702](https://github.com/helix-editor/helix/pull/7702))
129+- Add `vim_dark_high_contrast` ([#7785](https://github.com/helix-editor/helix/pull/7785))
130+- Add `new_moon` ([#7834](https://github.com/helix-editor/helix/pull/7834))
131+- Add `yellowed` ([#7849](https://github.com/helix-editor/helix/pull/7849))
132+- Improve comment readability for `autumn` ([#7939](https://github.com/helix-editor/helix/pull/7939))
133+- Distinguish active bufferline buffer in `monokai` ([#7983](https://github.com/helix-editor/helix/pull/7983))
134+- Update ruler colors in `nord` ([#7995](https://github.com/helix-editor/helix/pull/7995))
135+- Update Catppuccin themes ([#8102](https://github.com/helix-editor/helix/pull/8102))
136+- Add text focus scope and diagnostics undercurls for `nord` ([#8165](https://github.com/helix-editor/helix/pull/8165))
137+- Add material theme collection ([#8211](https://github.com/helix-editor/helix/pull/8211))
138+- Improve indent line color in `dracula` ([#8266](https://github.com/helix-editor/helix/pull/8266))
139+- Clean up and refactor `papercolor` to use inheritance ([#8276](https://github.com/helix-editor/helix/pull/8276))
140+- Fix `zenburn` inlay hint color ([#8278](https://github.com/helix-editor/helix/pull/8278)a)
141+- Fix picker crash when previewing an invalid range ([e9d0bd7](https://github.com/helix-editor/helix/commit/e9d0bd7))
142+- Correctly center items in the picker preview ([13d4463](https://github.com/helix-editor/helix/commit/13d4463))
143+- Add `cyan_light` ([#8293](https://github.com/helix-editor/helix/pull/8293), [#8587](https://github.com/helix-editor/helix/pull/8587))
144+- Theme HTML tags in `onedark` ([#8409](https://github.com/helix-editor/helix/pull/8409))
145+- Refine `darcula` and `darcula-solid` themes ([#8412](https://github.com/helix-editor/helix/pull/8412))
146+- Improve `nord` highlights ([#8414](https://github.com/helix-editor/helix/pull/8414))
147+- Add `nord-night` ([#8549](https://github.com/helix-editor/helix/pull/8549))
148+
149+New languages:
150+
151+- Blueprint ([#7213](https://github.com/helix-editor/helix/pull/7213), [#8161](https://github.com/helix-editor/helix/pull/8161))
152+- Forth ([#7256](https://github.com/helix-editor/helix/pull/7256), [#7334](https://github.com/helix-editor/helix/pull/7334))
153+- t32 ([#7140](https://github.com/helix-editor/helix/pull/7140), [#7811](https://github.com/helix-editor/helix/pull/7811))
154+- WebC ([#7290](https://github.com/helix-editor/helix/pull/7290))
155+- Persistent DSL for Haskell ([#7261](https://github.com/helix-editor/helix/pull/7261))
156+- F# ([#7619](https://github.com/helix-editor/helix/pull/7619), [#8024](https://github.com/helix-editor/helix/pull/8024))
157+- Wren ([#7765](https://github.com/helix-editor/helix/pull/7765), [#7819](https://github.com/helix-editor/helix/pull/7819))
158+- Unison ([#7724](https://github.com/helix-editor/helix/pull/7724))
159+- Todo.txt ([#7835](https://github.com/helix-editor/helix/pull/7835))
160+- Jinja and Handlebars ([#7233](https://github.com/helix-editor/helix/pull/7233))
161+- Pod ([#7907](https://github.com/helix-editor/helix/pull/7907))
162+- Strace ([#7928](https://github.com/helix-editor/helix/pull/7928))
163+- Gemini ([#8070](https://github.com/helix-editor/helix/pull/8070))
164+- GNU Assembler (GAS) ([#8291](https://github.com/helix-editor/helix/pull/8291))
165+- JSON5 ([#8473](https://github.com/helix-editor/helix/pull/8473))
166+- TEMPL ([#8540](https://github.com/helix-editor/helix/pull/8540))
167+
168+Updated languages and queries:
169+
170+- Add one to the ruler numbers for git-commit ([#7072](https://github.com/helix-editor/helix/pull/7072))
171+- Recognize XAML files as XML ([#7083](https://github.com/helix-editor/helix/pull/7083))
172+- Recognize `Cargo.lock` as TOML ([#7095](https://github.com/helix-editor/helix/pull/7095))
173+- Use Rust grammar for Cairo ([c6d1430](https://github.com/helix-editor/helix/commit/c6d1430))
174+- Update tree-sitter-nickel ([#7059](https://github.com/helix-editor/helix/pull/7059), [#7551](https://github.com/helix-editor/helix/pull/7551))
175+- Tune auto-pair characters for Nickel ([#7059](https://github.com/helix-editor/helix/pull/7059))
176+- Recognize `Vagrantfile` as Ruby ([#7112](https://github.com/helix-editor/helix/pull/7112))
177+- Recognize hidden justfiles as Just ([#7088](https://github.com/helix-editor/helix/pull/7088))
178+- Update Java and TypeScript highlight queries ([#7145](https://github.com/helix-editor/helix/pull/7145))
179+- Recognize `.zimrc` as Bash ([#7146](https://github.com/helix-editor/helix/pull/7146))
180+- Recognize `.gir` as XML ([#7152](https://github.com/helix-editor/helix/pull/7152))
181+- Update tree-sitter-scala ([#7147](https://github.com/helix-editor/helix/pull/7147))
182+- Recognize make file-type as Makefile ([#7212](https://github.com/helix-editor/helix/pull/7212))
183+- Update tree-sitter-verilog ([#7262](https://github.com/helix-editor/helix/pull/7262))
184+- Update tree-sitter-cpp ([#7285](https://github.com/helix-editor/helix/pull/7285))
185+- Support core mode for delve debugger ([#7300](https://github.com/helix-editor/helix/pull/7300))
186+- Add Fortran comment injections ([#7305](https://github.com/helix-editor/helix/pull/7305))
187+- Switch Vue language server to `vue-language-server` ([#7312](https://github.com/helix-editor/helix/pull/7312))
188+- Update tree-sitter-sql ([#7387](https://github.com/helix-editor/helix/pull/7387), [#8464](https://github.com/helix-editor/helix/pull/8464))
189+- 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))
190+- Highlight TOML table headers ([#7441](https://github.com/helix-editor/helix/pull/7441))
191+- Recognize `cppm` file-type as C++ ([#7492](https://github.com/helix-editor/helix/pull/7492))
192+- Refactor ecma language queries into private and public queries ([#7207](https://github.com/helix-editor/helix/pull/7207))
193+- Update tree-sitter-dart ([#7576](https://github.com/helix-editor/helix/pull/7576))
194+- Add shebang for nushell files ([#7606](https://github.com/helix-editor/helix/pull/7606))
195+- Recognize systemd files as INI ([#7592](https://github.com/helix-editor/helix/pull/7592))
196+- Update TypeScript, TSX and Svelte grammars ([#6874](https://github.com/helix-editor/helix/pull/6874))
197+- Enable inlay hints in the Svelte language server ([#7622](https://github.com/helix-editor/helix/pull/7622))
198+- Recognize `Brewfile`s as Ruby ([#7629](https://github.com/helix-editor/helix/pull/7629))
199+- Add more file-types for R ([#7633](https://github.com/helix-editor/helix/pull/7633))
200+- 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))
201+- Fix predicate typo in comment highlights ([#7732](https://github.com/helix-editor/helix/pull/7732))
202+- Update tree-sitter-prql ([#7771](https://github.com/helix-editor/helix/pull/7771))
203+- Recognize `.gitf` as JSON ([#7781](https://github.com/helix-editor/helix/pull/7781))
204+- Switch V language server to `v-analyzer` ([#7760](https://github.com/helix-editor/helix/pull/7760))
205+- Add protobuf language servers ([#7796](https://github.com/helix-editor/helix/pull/7796))
206+- Update tree-sitter-zig ([#7803](https://github.com/helix-editor/helix/pull/7803))
207+- Update tree-sitter-hare ([#7784](https://github.com/helix-editor/helix/pull/7784))
208+- Add Java indent queries ([#7844](https://github.com/helix-editor/helix/pull/7844))
209+- Update tree-sitter-scheme ([979933b](https://github.com/helix-editor/helix/commit/979933b))
210+- Recognize `scm` as Scheme instead of TSQ ([5707151](https://github.com/helix-editor/helix/commit/5707151))
211+- Update tree-sitter-git-commit ([#7831](https://github.com/helix-editor/helix/pull/7831))
212+- Update JavaScript, TypeScript and TSX grammars ([#7852](https://github.com/helix-editor/helix/pull/7852))
213+- Update tree-sitter-nu ([#7873](https://github.com/helix-editor/helix/pull/7873))
214+- Fix YAML indentation ([#6768](https://github.com/helix-editor/helix/pull/6768))
215+- 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))
216+- Update tree-sitter-slint ([#7893](https://github.com/helix-editor/helix/pull/7893))
217+- Recognize more ZSH file-types as Bash ([#7930](https://github.com/helix-editor/helix/pull/7930))
218+- Recognize `star` extension as Starlark ([#7922](https://github.com/helix-editor/helix/pull/7922))
219+- Fix inline HTML tag highlighting in markdown ([#7960](https://github.com/helix-editor/helix/pull/7960))
220+- Update tree-sitter-robot ([#7970](https://github.com/helix-editor/helix/pull/7970))
221+- Highlight Dart 3 `sealed` and `base` keywords ([#7974](https://github.com/helix-editor/helix/pull/7974))
222+- Add configuration for `ltex-ls` to the default `languages.toml` ([#7838](https://github.com/helix-editor/helix/pull/7838))
223+- Update tree-sitter-strace ([#8087](https://github.com/helix-editor/helix/pull/8087))
224+- Update tree-sitter-gleam, enable auto-format ([#8085](https://github.com/helix-editor/helix/pull/8085))
225+- Update tree-sitter-esdl ([#8222](https://github.com/helix-editor/helix/pull/8222))
226+- Expand ignore file-types ([#8220](https://github.com/helix-editor/helix/pull/8220))
227+- Recognize feed related formats as XML ([#8232](https://github.com/helix-editor/helix/pull/8232))
228+- Improve YAML injections ([#8217](https://github.com/helix-editor/helix/pull/8217))
229+- Add shebangs for TypeScript, Julia, Java and OCaml ([95e994a](https://github.com/helix-editor/helix/commit/95e994a))
230+- Highlight abbreviations in Scheme ([ef23847](https://github.com/helix-editor/helix/commit/ef23847))
231+- Remove backtic auto-pair in OCaml ([#8260](https://github.com/helix-editor/helix/pull/8260))
232+- Recognize `flake.lock` as JSON ([#8304](https://github.com/helix-editor/helix/pull/8304))
233+- Add Python test script injection for Nix ([b4494e1](https://github.com/helix-editor/helix/commit/b4494e1))
234+- Fix Nix comment injection precedence ([37e48f4](https://github.com/helix-editor/helix/commit/37e48f4))
235+- Recognize editorconfig files as INI ([#8308](https://github.com/helix-editor/helix/pull/8308))
236+- Recognize `.babelrc` as JSON ([#8309](https://github.com/helix-editor/helix/pull/8309))
237+- 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))
238+- Update Unison highlights ([#8315](https://github.com/helix-editor/helix/pull/8315))
239+- Recognize `.webmanifest` as JSON ([#8342](https://github.com/helix-editor/helix/pull/8342))
240+- Recognize polkit policy files as XML ([#8369](https://github.com/helix-editor/helix/pull/8369))
241+- Recognize polkit rules files as JavaScript ([#8370](https://github.com/helix-editor/helix/pull/8370))
242+- Update Go highlight queries ([#8399](https://github.com/helix-editor/helix/pull/8399))
243+- Add shebangs for Makefiles ([#8410](https://github.com/helix-editor/helix/pull/8410))
244+- Add file-type associations from VSCode ([#8388](https://github.com/helix-editor/helix/pull/8388))
245+- Add validation to JSON/CSS language server configs ([#8433](https://github.com/helix-editor/helix/pull/8433))
246+- Add a configuration for the tailwind language server ([#8442](https://github.com/helix-editor/helix/pull/8442))
247+- Add a configuration for the ansible language server ([#7973](https://github.com/helix-editor/helix/pull/7973))
248+- Add a configuration for the GraphQL language server ([#8492](https://github.com/helix-editor/helix/pull/8492))
249+- Indent while statements in Bash ([#8528](https://github.com/helix-editor/helix/pull/8528))
250+- Update tree-sitter-haskell and queries ([#8558](https://github.com/helix-editor/helix/pull/8558))
251+
252+Packaging:
253+
254+- Add an overlay to the Nix flake ([#7078](https://github.com/helix-editor/helix/pull/7078))
255+- Check for `git` before fetching or building grammars ([#7320](https://github.com/helix-editor/helix/pull/7320))
256+- Refactor Nix flake to use Crane ([#7763](https://github.com/helix-editor/helix/pull/7763))
257+- Remove the aarch64 appimage from the release CI ([#7832](https://github.com/helix-editor/helix/pull/7832))
258+- Add desktop and icon files to Nix flake output ([#7979](https://github.com/helix-editor/helix/pull/7979))
259+- Build flake packages with the latest stable Rust ([#8133](https://github.com/helix-editor/helix/pull/8133))
260+
1261# 23.05 (2023-05-18)
2262
326323.05 is a smaller release focusing on fixes. There were 88 contributors in this release. Thank you all!
Cargo.lock+419−598
@@ -19,41 +19,22 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
1919
2020[[package]]
2121name = "ahash"
22−version = "0.7.6"
23−source = "registry+https://github.com/rust-lang/crates.io-index"
24−checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
25−dependencies = [
26− "getrandom",
27− "once_cell",
28− "version_check",
29−]
30−
31−[[package]]
32−name = "ahash"
33−version = "0.8.3"
22+version = "0.8.6"
3423source = "registry+https://github.com/rust-lang/crates.io-index"
35−checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
24+checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a"
3625dependencies = [
3726 "cfg-if",
3827 "getrandom",
3928 "once_cell",
4029 "version_check",
30+ "zerocopy",
4131]
4232
4333[[package]]
4434name = "aho-corasick"
45−version = "0.7.20"
35+version = "1.1.2"
4636source = "registry+https://github.com/rust-lang/crates.io-index"
47−checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
48−dependencies = [
49− "memchr",
50−]
51−
52−[[package]]
53−name = "aho-corasick"
54−version = "1.0.2"
55−source = "registry+https://github.com/rust-lang/crates.io-index"
56−checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
37+checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
5738dependencies = [
5839 "memchr",
5940]
@@ -81,9 +62,9 @@ dependencies = [
8162
8263[[package]]
8364name = "anyhow"
84−version = "1.0.75"
65+version = "1.0.76"
8566source = "registry+https://github.com/rust-lang/crates.io-index"
86−checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
67+checksum = "59d2a3357dde987206219e78ecfbbb6e8dad06cbb65292758d3270e6254f7355"
8768
8869[[package]]
8970name = "arc-swap"
@@ -107,7 +88,7 @@ dependencies = [
10788 "cc",
10889 "cfg-if",
10990 "libc",
110− "miniz_oxide 0.7.1",
91+ "miniz_oxide",
11192 "object",
11293 "rustc-demangle",
11394]
@@ -120,15 +101,15 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
120101
121102[[package]]
122103name = "bitflags"
123−version = "2.4.0"
104+version = "2.4.1"
124105source = "registry+https://github.com/rust-lang/crates.io-index"
125−checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
106+checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
126107
127108[[package]]
128109name = "bstr"
129−version = "1.6.0"
110+version = "1.8.0"
130111source = "registry+https://github.com/rust-lang/crates.io-index"
131−checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05"
112+checksum = "542f33a8835a0884b006a0c3df3dadd99c0c3f296ed26c2fdc8028e01ad6230c"
132113dependencies = [
133114 "memchr",
134115 "regex-automata",
@@ -150,12 +131,6 @@ version = "3.12.0"
150131source = "registry+https://github.com/rust-lang/crates.io-index"
151132checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
152133
153−[[package]]
154−name = "bytecount"
155−version = "0.6.3"
156−source = "registry+https://github.com/rust-lang/crates.io-index"
157−checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c"
158−
159134[[package]]
160135name = "bytes"
161136version = "1.4.0"
@@ -170,9 +145,9 @@ checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
170145
171146[[package]]
172147name = "cc"
173−version = "1.0.83"
148+version = "1.0.84"
174149source = "registry+https://github.com/rust-lang/crates.io-index"
175−checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
150+checksum = "0f8e7c90afad890484a21653d08b6e209ae34770fb5ee298f9c699fcc1e5c856"
176151dependencies = [
177152 "libc",
178153]
@@ -196,25 +171,23 @@ dependencies = [
196171
197172[[package]]
198173name = "chrono"
199−version = "0.4.26"
174+version = "0.4.31"
200175source = "registry+https://github.com/rust-lang/crates.io-index"
201−checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5"
176+checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
202177dependencies = [
203178 "android-tzdata",
204179 "iana-time-zone",
205180 "num-traits",
206− "winapi",
181+ "windows-targets 0.48.0",
207182]
208183
209184[[package]]
210185name = "clipboard-win"
211−version = "4.5.0"
186+version = "5.0.0"
212187source = "registry+https://github.com/rust-lang/crates.io-index"
213−checksum = "7191c27c2357d9b7ef96baac1773290d4ca63b24205b82a3fd8a0637afcf0362"
188+checksum = "c57002a5d9be777c1ef967e33674dac9ebd310d8893e4e3437b14d5f0f6372cc"
214189dependencies = [
215190 "error-code",
216− "str-buf",
217− "winapi",
218191]
219192
220193[[package]]
@@ -312,7 +285,7 @@ version = "0.27.0"
312285source = "registry+https://github.com/rust-lang/crates.io-index"
313286checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df"
314287dependencies = [
315− "bitflags 2.4.0",
288+ "bitflags 2.4.1",
316289 "crossterm_winapi",
317290 "filedescriptor",
318291 "futures-core",
@@ -357,7 +330,7 @@ dependencies = [
357330 "proc-macro2",
358331 "quote",
359332 "scratch",
360− "syn 2.0.28",
333+ "syn 2.0.38",
361334]
362335
363336[[package]]
@@ -374,7 +347,7 @@ checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5"
374347dependencies = [
375348 "proc-macro2",
376349 "quote",
377− "syn 2.0.28",
350+ "syn 2.0.38",
378351]
379352
380353[[package]]
@@ -415,34 +388,19 @@ checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1"
415388
416389[[package]]
417390name = "errno"
418−version = "0.3.1"
419−source = "registry+https://github.com/rust-lang/crates.io-index"
420−checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
421−dependencies = [
422− "errno-dragonfly",
423− "libc",
424− "windows-sys 0.48.0",
425−]
426−
427−[[package]]
428−name = "errno-dragonfly"
429−version = "0.1.2"
391+version = "0.3.8"
430392source = "registry+https://github.com/rust-lang/crates.io-index"
431−checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
393+checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
432394dependencies = [
433− "cc",
434395 "libc",
396+ "windows-sys 0.52.0",
435397]
436398
437399[[package]]
438400name = "error-code"
439−version = "2.3.1"
401+version = "3.0.0"
440402source = "registry+https://github.com/rust-lang/crates.io-index"
441−checksum = "64f18991e7bf11e7ffee451b5318b5c1a73c52d0d0ada6e5a3017c8c1ced6a21"
442−dependencies = [
443− "libc",
444− "str-buf",
445−]
403+checksum = "281e452d3bad4005426416cdba5ccfd4f5c1280e10099e21db27f7c1c28347fc"
446404
447405[[package]]
448406name = "etcetera"
@@ -455,6 +413,15 @@ dependencies = [
455413 "windows-sys 0.48.0",
456414]
457415
416+[[package]]
417+name = "faster-hex"
418+version = "0.9.0"
419+source = "registry+https://github.com/rust-lang/crates.io-index"
420+checksum = "a2a2b11eda1d40935b26cf18f6833c526845ae8c41e58d09af6adeb6f0269183"
421+dependencies = [
422+ "serde",
423+]
424+
458425[[package]]
459426name = "fastrand"
460427version = "2.0.0"
@@ -481,54 +448,36 @@ dependencies = [
481448 "winapi",
482449]
483450
484−[[package]]
485−name = "filetime"
486−version = "0.2.21"
487−source = "registry+https://github.com/rust-lang/crates.io-index"
488−checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153"
489−dependencies = [
490− "cfg-if",
491− "libc",
492− "redox_syscall 0.2.16",
493− "windows-sys 0.48.0",
494−]
495−
496451[[package]]
497452name = "flate2"
498−version = "1.0.25"
453+version = "1.0.27"
499454source = "registry+https://github.com/rust-lang/crates.io-index"
500−checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
455+checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010"
501456dependencies = [
502457 "crc32fast",
503− "miniz_oxide 0.6.2",
458+ "miniz_oxide",
504459]
505460
506−[[package]]
507−name = "fnv"
508−version = "1.0.7"
509−source = "registry+https://github.com/rust-lang/crates.io-index"
510−checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
511−
512461[[package]]
513462name = "form_urlencoded"
514−version = "1.2.0"
463+version = "1.2.1"
515464source = "registry+https://github.com/rust-lang/crates.io-index"
516−checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
465+checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
517466dependencies = [
518467 "percent-encoding",
519468]
520469
521470[[package]]
522471name = "futures-core"
523−version = "0.3.28"
472+version = "0.3.30"
524473source = "registry+https://github.com/rust-lang/crates.io-index"
525−checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
474+checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
526475
527476[[package]]
528477name = "futures-executor"
529−version = "0.3.28"
478+version = "0.3.29"
530479source = "registry+https://github.com/rust-lang/crates.io-index"
531−checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"
480+checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc"
532481dependencies = [
533482 "futures-core",
534483 "futures-task",
@@ -537,15 +486,15 @@ dependencies = [
537486
538487[[package]]
539488name = "futures-task"
540−version = "0.3.28"
489+version = "0.3.30"
541490source = "registry+https://github.com/rust-lang/crates.io-index"
542−checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
491+checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
543492
544493[[package]]
545494name = "futures-util"
546−version = "0.3.28"
495+version = "0.3.30"
547496source = "registry+https://github.com/rust-lang/crates.io-index"
548−checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
497+checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
549498dependencies = [
550499 "futures-core",
551500 "futures-task",
@@ -573,15 +522,13 @@ checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e"
573522
574523[[package]]
575524name = "gix"
576−version = "0.48.0"
525+version = "0.57.0"
577526source = "registry+https://github.com/rust-lang/crates.io-index"
578−checksum = "c1e74cea676de7f53a79f3c0365812b11f6814b81e671b8ee4abae6ca09c7881"
527+checksum = "721c7497ab24b665ed5a1eb2b3526936aa60068e61ba260651f7e77c52feec69"
579528dependencies = [
580529 "gix-actor",
581− "gix-attributes",
582530 "gix-commitgraph",
583531 "gix-config",
584− "gix-credentials",
585532 "gix-date",
586533 "gix-diff",
587534 "gix-discover",
@@ -590,19 +537,16 @@ dependencies = [
590537 "gix-glob",
591538 "gix-hash",
592539 "gix-hashtable",
593− "gix-ignore",
594− "gix-index",
595540 "gix-lock",
596− "gix-mailmap",
597− "gix-negotiate",
541+ "gix-macros",
598542 "gix-object",
599543 "gix-odb",
600544 "gix-pack",
601545 "gix-path",
602− "gix-prompt",
603546 "gix-ref",
604547 "gix-refspec",
605548 "gix-revision",
549+ "gix-revwalk",
606550 "gix-sec",
607551 "gix-tempfile",
608552 "gix-trace",
@@ -610,10 +554,8 @@ dependencies = [
610554 "gix-url",
611555 "gix-utils",
612556 "gix-validate",
613− "gix-worktree",
614− "log",
615557 "once_cell",
616− "signal-hook",
558+ "parking_lot",
617559 "smallvec",
618560 "thiserror",
619561 "unicode-normalization",
@@ -621,81 +563,46 @@ dependencies = [
621563
622564[[package]]
623565name = "gix-actor"
624−version = "0.23.0"
566+version = "0.29.0"
625567source = "registry+https://github.com/rust-lang/crates.io-index"
626−checksum = "1969b77b9ee4cc1755c841987ec6f7622aaca95e952bcafb76973ae59d1b8716"
568+checksum = "886014c4865b93ce268f1d3eddd4fd3261242c3f3ee61eb36009f913016a9059"
627569dependencies = [
628570 "bstr",
629571 "btoi",
630572 "gix-date",
631573 "itoa",
632− "nom",
633− "thiserror",
634−]
635−
636−[[package]]
637−name = "gix-attributes"
638−version = "0.14.1"
639−source = "registry+https://github.com/rust-lang/crates.io-index"
640−checksum = "e3772b0129dcd1fc73e985bbd08a1482d082097d2915cb1ee31ce8092b8e4434"
641−dependencies = [
642− "bstr",
643− "gix-glob",
644− "gix-path",
645− "gix-quote",
646− "kstring",
647− "log",
648− "smallvec",
649− "thiserror",
650− "unicode-bom",
651−]
652−
653−[[package]]
654−name = "gix-bitmap"
655−version = "0.2.5"
656−source = "registry+https://github.com/rust-lang/crates.io-index"
657−checksum = "311e2fa997be6560c564b070c5da2d56d038b645a94e1e5796d5d85a350da33c"
658−dependencies = [
659574 "thiserror",
575+ "winnow 0.5.28",
660576]
661577
662578[[package]]
663579name = "gix-chunk"
664−version = "0.4.3"
580+version = "0.4.6"
665581source = "registry+https://github.com/rust-lang/crates.io-index"
666−checksum = "39db5ed0fc0a2e9b1b8265993f7efdbc30379dec268f3b91b7af0c2de4672fdd"
582+checksum = "2ade37ef69870de0ed966b97c57a3a947a22ff3482a52c3b99b205f77bcb08fb"
667583dependencies = [
668584 "thiserror",
669585]
670586
671−[[package]]
672−name = "gix-command"
673−version = "0.2.6"
674−source = "registry+https://github.com/rust-lang/crates.io-index"
675−checksum = "bb49ab557a37b0abb2415bca2b10e541277dff0565deb5bd5e99fd95f93f51eb"
676−dependencies = [
677− "bstr",
678−]
679−
680587[[package]]
681588name = "gix-commitgraph"
682−version = "0.17.1"
589+version = "0.23.0"
683590source = "registry+https://github.com/rust-lang/crates.io-index"
684−checksum = "ed42baa50075d41c1a0931074ce1a97c5797c7c6fe7591d9f1f2dcd448532c26"
591+checksum = "e7559ea9cefee188cd88b05afcc8e3ef7a3cb4a5c647bccf06b981e591b02b77"
685592dependencies = [
686593 "bstr",
687594 "gix-chunk",
688595 "gix-features",
689596 "gix-hash",
690− "memmap2 0.7.1",
597+ "memmap2",
691598 "thiserror",
692599]
693600
694601[[package]]
695602name = "gix-config"
696−version = "0.25.1"
603+version = "0.33.0"
697604source = "registry+https://github.com/rust-lang/crates.io-index"
698−checksum = "817688c7005a716d9363e267913526adea402dabd947f4ba63842d10cc5132af"
605+checksum = "9c35dc7f9c00a42bbc9cfa1ca2ec0a78ad1b76ff0736d3d35dfd612962244467"
699606dependencies = [
700607 "bstr",
701608 "gix-config-value",
@@ -704,49 +611,32 @@ dependencies = [
704611 "gix-path",
705612 "gix-ref",
706613 "gix-sec",
707− "log",
708614 "memchr",
709− "nom",
710615 "once_cell",
711616 "smallvec",
712617 "thiserror",
713618 "unicode-bom",
619+ "winnow 0.5.28",
714620]
715621
716622[[package]]
717623name = "gix-config-value"
718−version = "0.12.3"
624+version = "0.14.2"
719625source = "registry+https://github.com/rust-lang/crates.io-index"
720−checksum = "83960be5e99266bcf55dae5a24731bbd39f643bfb68f27e939d6b06836b5b87d"
626+checksum = "39f388cb2396aee82d6f460a2e7770659bdf8854e9e5478f7d2b1324a9698284"
721627dependencies = [
722− "bitflags 2.4.0",
628+ "bitflags 2.4.1",
723629 "bstr",
724630 "gix-path",
725631 "libc",
726632 "thiserror",
727633]
728634
729−[[package]]
730−name = "gix-credentials"
731−version = "0.16.1"
732−source = "registry+https://github.com/rust-lang/crates.io-index"
733−checksum = "75a75565e0e6e7f80cfa4eb1b05cc448c6846ddd48dcf413a28875fbc11ee9af"
734−dependencies = [
735− "bstr",
736− "gix-command",
737− "gix-config-value",
738− "gix-path",
739− "gix-prompt",
740− "gix-sec",
741− "gix-url",
742− "thiserror",
743−]
744−
745635[[package]]
746636name = "gix-date"
747−version = "0.7.0"
637+version = "0.8.2"
748638source = "registry+https://github.com/rust-lang/crates.io-index"
749−checksum = "8e9a04a1d2387c955ec91059d56b673000dd24f3c07cad08ed253e36381782bf"
639+checksum = "9d85f4a01e0d05c3de585e28bae514d4baf01655e3fc3f14ce6f30bf62405345"
750640dependencies = [
751641 "bstr",
752642 "itoa",
@@ -756,21 +646,21 @@ dependencies = [
756646
757647[[package]]
758648name = "gix-diff"
759−version = "0.32.0"
649+version = "0.39.0"
760650source = "registry+https://github.com/rust-lang/crates.io-index"
761−checksum = "aaf5d9b9b521b284ebe53ee69eee33341835ec70edc314f36b2100ea81396121"
651+checksum = "ac0e75f5afd2f6c47c800b6b0a000a08045739d0450d20482e8faa42543f62d1"
762652dependencies = [
653+ "bstr",
763654 "gix-hash",
764655 "gix-object",
765− "imara-diff",
766656 "thiserror",
767657]
768658
769659[[package]]
770660name = "gix-discover"
771−version = "0.21.1"
661+version = "0.28.0"
772662source = "registry+https://github.com/rust-lang/crates.io-index"
773−checksum = "272aad20dc63dedba76615373dd8885fb5aebe4795e5b5b0aa2a24e63c82085c"
663+checksum = "f0b63ce2ad81632ac1a84ac370f85a5e580c3261580bd85ea17ff35d3a0bba18"
774664dependencies = [
775665 "bstr",
776666 "dunce",
@@ -783,9 +673,9 @@ dependencies = [
783673
784674[[package]]
785675name = "gix-features"
786−version = "0.31.1"
676+version = "0.37.0"
787677source = "registry+https://github.com/rust-lang/crates.io-index"
788−checksum = "06142d8cff5d17509399b04052b64d2f9b3a311d5cff0b1a32b220f62cd0d595"
678+checksum = "befe7edea299a824504b5acc96d7a3a538125b38c42f3a8379f6912a29c90c81"
789679dependencies = [
790680 "crc32fast",
791681 "flate2",
@@ -801,20 +691,20 @@ dependencies = [
801691
802692[[package]]
803693name = "gix-fs"
804−version = "0.3.0"
694+version = "0.9.0"
805695source = "registry+https://github.com/rust-lang/crates.io-index"
806−checksum = "bb15956bc0256594c62a2399fcf6958a02a11724217eddfdc2b49b21b6292496"
696+checksum = "007017ce93b819ea52c0ec68306f7d72212a2d307c3d70f1548c7141c015d0a1"
807697dependencies = [
808698 "gix-features",
809699]
810700
811701[[package]]
812702name = "gix-glob"
813−version = "0.9.1"
703+version = "0.15.0"
814704source = "registry+https://github.com/rust-lang/crates.io-index"
815−checksum = "c18bdff83143d61e7d60da6183b87542a870d026b2a2d0b30170b8e9c0cd321a"
705+checksum = "61fb116c2516d3a1170e010118f639944a6389872c875a008960cdab2a44ac72"
816706dependencies = [
817− "bitflags 2.4.0",
707+ "bitflags 2.4.1",
818708 "bstr",
819709 "gix-features",
820710 "gix-path",
@@ -822,64 +712,30 @@ dependencies = [
822712
823713[[package]]
824714name = "gix-hash"
825−version = "0.11.3"
715+version = "0.14.0"
826716source = "registry+https://github.com/rust-lang/crates.io-index"
827−checksum = "a0dd58cdbe7ffa4032fc111864c80d5f8cecd9a2c9736c97ae7e5be834188272"
717+checksum = "c52c3170a17b6031833cd2eb4ad7bc23f2755d06e6e70f78dec21d42e8fe1b30"
828718dependencies = [
829− "hex",
719+ "faster-hex",
830720 "thiserror",
831721]
832722
833723[[package]]
834724name = "gix-hashtable"
835−version = "0.2.3"
725+version = "0.5.0"
836726source = "registry+https://github.com/rust-lang/crates.io-index"
837−checksum = "9e133bc56d938eaec1c675af7c681a51de9662b0ada779f45607b967a10da77a"
727+checksum = "40a838e6366a5e5b84668b6997ce0981b833136468e8ba949f424c0ef2927eba"
838728dependencies = [
839729 "gix-hash",
840− "hashbrown 0.14.0",
730+ "hashbrown 0.14.3",
841731 "parking_lot",
842732]
843733
844−[[package]]
845−name = "gix-ignore"
846−version = "0.4.1"
847−source = "registry+https://github.com/rust-lang/crates.io-index"
848−checksum = "ca801f2d0535210f77b33e2c067d565aedecacc82f1b3dbce26da1388ebc4634"
849−dependencies = [
850− "bstr",
851− "gix-glob",
852− "gix-path",
853− "unicode-bom",
854−]
855−
856−[[package]]
857−name = "gix-index"
858−version = "0.20.0"
859−source = "registry+https://github.com/rust-lang/crates.io-index"
860−checksum = "68099abdf6ee50ae3c897e8b05de96871cbe54d52a37cdf559101f911b883562"
861−dependencies = [
862− "bitflags 2.4.0",
863− "bstr",
864− "btoi",
865− "filetime",
866− "gix-bitmap",
867− "gix-features",
868− "gix-hash",
869− "gix-lock",
870− "gix-object",
871− "gix-traverse",
872− "itoa",
873− "memmap2 0.7.1",
874− "smallvec",
875− "thiserror",
876−]
877−
878734[[package]]
879735name = "gix-lock"
880−version = "7.0.0"
736+version = "12.0.0"
881737source = "registry+https://github.com/rust-lang/crates.io-index"
882−checksum = "328f50aad713ab606caeaf834459ef915ccdfbb9133ac6cd54616d601aa9249f"
738+checksum = "6cf112ddee94223c119a8534dad027740dc3aba3365ac5edeef8a7f6660c74db"
883739dependencies = [
884740 "gix-tempfile",
885741 "gix-utils",
@@ -887,38 +743,21 @@ dependencies = [
887743]
888744
889745[[package]]
890−name = "gix-mailmap"
891−version = "0.15.0"
892−source = "registry+https://github.com/rust-lang/crates.io-index"
893−checksum = "1787e3c37fc43b1f7c0e3be6196c6837b3ba5f869190dfeaa444b816f0a7f34b"
894−dependencies = [
895− "bstr",
896− "gix-actor",
897− "gix-date",
898− "thiserror",
899−]
900−
901−[[package]]
902−name = "gix-negotiate"
903−version = "0.4.0"
746+name = "gix-macros"
747+version = "0.1.2"
904748source = "registry+https://github.com/rust-lang/crates.io-index"
905−checksum = "4e7bce64d4452dd609f44d04b14b29da2e0ad2c45fcdf4ce1472a5f5f8ec21c2"
749+checksum = "fc207b64189cf71bcb17fc841ab99a5d63d0845546b611e2703ce467f659323a"
906750dependencies = [
907− "bitflags 2.4.0",
908− "gix-commitgraph",
909− "gix-date",
910− "gix-hash",
911− "gix-object",
912− "gix-revwalk",
913− "smallvec",
914− "thiserror",
751+ "proc-macro2",
752+ "quote",
753+ "syn 2.0.38",
915754]
916755
917756[[package]]
918757name = "gix-object"
919−version = "0.32.0"
758+version = "0.40.0"
920759source = "registry+https://github.com/rust-lang/crates.io-index"
921−checksum = "a953f3d7ffad16734aa3ab1d05807972c80e339d1bd9dde03e0198716b99e2a6"
760+checksum = "e4c77e47ffba92127faf632a841fce23d19547e269bd8b88e68961a70eab4e93"
922761dependencies = [
923762 "bstr",
924763 "btoi",
@@ -927,18 +766,17 @@ dependencies = [
927766 "gix-features",
928767 "gix-hash",
929768 "gix-validate",
930− "hex",
931769 "itoa",
932− "nom",
933770 "smallvec",
934771 "thiserror",
772+ "winnow 0.5.28",
935773]
936774
937775[[package]]
938776name = "gix-odb"
939−version = "0.49.1"
777+version = "0.56.0"
940778source = "registry+https://github.com/rust-lang/crates.io-index"
941−checksum = "f6418cff00ecc2713b58c8e04bff30dda808fbba1a080e7248b299d069894a01"
779+checksum = "a3254f2005cc7553ea78e85e816a09150c6f7a64e6b7627b8d1fdc56721bea73"
942780dependencies = [
943781 "arc-swap",
944782 "gix-date",
@@ -955,21 +793,19 @@ dependencies = [
955793
956794[[package]]
957795name = "gix-pack"
958−version = "0.39.1"
796+version = "0.46.0"
959797source = "registry+https://github.com/rust-lang/crates.io-index"
960−checksum = "414935138d90043ea5898de7a93f02c2558e52652492719470e203ef26a8fd0a"
798+checksum = "02ebc8cd657eec207d82d8f876ca402361308ecd3c87a47935b0299506257b4f"
961799dependencies = [
962800 "clru",
963801 "gix-chunk",
964− "gix-diff",
965802 "gix-features",
966803 "gix-hash",
967804 "gix-hashtable",
968805 "gix-object",
969806 "gix-path",
970807 "gix-tempfile",
971− "gix-traverse",
972− "memmap2 0.7.1",
808+ "memmap2",
973809 "parking_lot",
974810 "smallvec",
975811 "thiserror",
@@ -977,9 +813,9 @@ dependencies = [
977813
978814[[package]]
979815name = "gix-path"
980−version = "0.8.3"
816+version = "0.10.2"
981817source = "registry+https://github.com/rust-lang/crates.io-index"
982−checksum = "dfca182d2575ded2ed38280f1ebf75cd5d3790b77e0872de07854cf085821fbe"
818+checksum = "10931652a3da126990ac93bce1b1c600cc99d7c268d712b6360ed52174ce1b68"
983819dependencies = [
984820 "bstr",
985821 "gix-trace",
@@ -988,24 +824,11 @@ dependencies = [
988824 "thiserror",
989825]
990826
991−[[package]]
992−name = "gix-prompt"
993−version = "0.5.2"
994−source = "registry+https://github.com/rust-lang/crates.io-index"
995−checksum = "8dfd363fd89a40c1e7bff9c9c1b136cd2002480f724b0c627c1bc771cd5480ec"
996−dependencies = [
997− "gix-command",
998− "gix-config-value",
999− "parking_lot",
1000− "rustix 0.37.15",
1001− "thiserror",
1002−]
1003−
1004827[[package]]
1005828name = "gix-quote"
1006−version = "0.4.5"
829+version = "0.4.9"
1007830source = "registry+https://github.com/rust-lang/crates.io-index"
1008−checksum = "3874de636c2526de26a3405b8024b23ef1a327bebf4845d770d00d48700b6a40"
831+checksum = "6c43530cb94a7759807e6f8d180e17ac9c65673b891645c6c433831dc0cf4342"
1009832dependencies = [
1010833 "bstr",
1011834 "btoi",
@@ -1014,9 +837,9 @@ dependencies = [
1014837
1015838[[package]]
1016839name = "gix-ref"
1017−version = "0.32.1"
840+version = "0.40.0"
1018841source = "registry+https://github.com/rust-lang/crates.io-index"
1019−checksum = "39453f4e5f23cddc2e6e4cca2ba20adfdbec29379e3ca829714dfe98ae068ccd"
842+checksum = "baa951b3b850d6d1be4f900768e49af20b76bf9505beac22af723d57249a2f1d"
1020843dependencies = [
1021844 "gix-actor",
1022845 "gix-date",
@@ -1028,16 +851,16 @@ dependencies = [
1028851 "gix-path",
1029852 "gix-tempfile",
1030853 "gix-validate",
1031− "memmap2 0.7.1",
1032− "nom",
854+ "memmap2",
1033855 "thiserror",
856+ "winnow 0.5.28",
1034857]
1035858
1036859[[package]]
1037860name = "gix-refspec"
1038−version = "0.13.0"
861+version = "0.21.0"
1039862source = "registry+https://github.com/rust-lang/crates.io-index"
1040−checksum = "b8e76ff1f82fba295a121e31ab02f69642994e532c45c0c899aa393f4b740302"
863+checksum = "88c61f849d58c06e3068a0b601cf10127d2a07cdad00a725ed66cf303f76f6b3"
1041864dependencies = [
1042865 "bstr",
1043866 "gix-hash",
@@ -1049,9 +872,9 @@ dependencies = [
1049872
1050873[[package]]
1051874name = "gix-revision"
1052−version = "0.17.0"
875+version = "0.25.0"
1053876source = "registry+https://github.com/rust-lang/crates.io-index"
1054−checksum = "237428a7d3978e8572964e1e45d984027c2acc94df47e594baa6c4b0da7c9922"
877+checksum = "bcbbf91f4200c5c76802ef5f057b96f5a336827508881fe55a780be71a794d22"
1055878dependencies = [
1056879 "bstr",
1057880 "gix-date",
@@ -1059,14 +882,15 @@ dependencies = [
1059882 "gix-hashtable",
1060883 "gix-object",
1061884 "gix-revwalk",
885+ "gix-trace",
1062886 "thiserror",
1063887]
1064888
1065889[[package]]
1066890name = "gix-revwalk"
1067−version = "0.3.0"
891+version = "0.11.0"
1068892source = "registry+https://github.com/rust-lang/crates.io-index"
1069−checksum = "028d50fcaf8326a8f79a359490d9ca9fb4e2b51ac9ac86503560d0bcc888d2eb"
893+checksum = "33ab66354d83f70f2730391747d0c75f94ef3c3dd40ebde2e206db9faaf7a0a7"
1070894dependencies = [
1071895 "gix-commitgraph",
1072896 "gix-date",
@@ -1079,42 +903,40 @@ dependencies = [
1079903
1080904[[package]]
1081905name = "gix-sec"
1082−version = "0.8.3"
906+version = "0.10.2"
1083907source = "registry+https://github.com/rust-lang/crates.io-index"
1084−checksum = "ede298863db2a0574a14070991710551e76d1f47c9783b62d4fcbca17f56371c"
908+checksum = "a9963f38a42144253ed4d571882d7db5ef644c12e6726e4b75135597cc9d0e1a"
1085909dependencies = [
1086− "bitflags 2.4.0",
910+ "bitflags 2.4.1",
1087911 "gix-path",
1088912 "libc",
1089− "windows",
913+ "windows 0.52.0",
1090914]
1091915
1092916[[package]]
1093917name = "gix-tempfile"
1094−version = "7.0.0"
918+version = "12.0.0"
1095919source = "registry+https://github.com/rust-lang/crates.io-index"
1096−checksum = "4fac8310c17406ea619af72f42ee46dac795110f68f41b4f4fa231b69889c6a2"
920+checksum = "e76a494bd530e1a1309188ff971825a24f159c76c2db0bf71fa5dfb469a2c915"
1097921dependencies = [
1098922 "gix-fs",
1099923 "libc",
1100924 "once_cell",
1101925 "parking_lot",
1102− "signal-hook",
1103− "signal-hook-registry",
1104926 "tempfile",
1105927]
1106928
1107929[[package]]
1108930name = "gix-trace"
1109−version = "0.1.2"
931+version = "0.1.5"
1110932source = "registry+https://github.com/rust-lang/crates.io-index"
1111−checksum = "103eac621617be3ebe0605c9065ca51a223279a23218aaf67d10daa6e452f663"
933+checksum = "bda62acb44dd86a40c7c3762a5403cfc1ac789ea559df54085cedf79864f809e"
1112934
1113935[[package]]
1114936name = "gix-traverse"
1115−version = "0.29.0"
937+version = "0.36.0"
1116938source = "registry+https://github.com/rust-lang/crates.io-index"
1117−checksum = "e3cdfd54598db4fae57d5ae6f52958422b2d13382d2745796bfe5c8015ffa86e"
939+checksum = "8661fab39985c9214e56d81a63ceb5886ac948cec2fba76c39494d1e0e307ea8"
1118940dependencies = [
1119941 "gix-commitgraph",
1120942 "gix-date",
@@ -1128,9 +950,9 @@ dependencies = [
1128950
1129951[[package]]
1130952name = "gix-url"
1131−version = "0.20.1"
953+version = "0.26.0"
1132954source = "registry+https://github.com/rust-lang/crates.io-index"
1133−checksum = "beaede6dbc83f408b19adfd95bb52f1dbf01fb8862c3faf6c6243e2e67fcdfa1"
955+checksum = "10a0129c1e8b52736d7c5128300a4485dbc85863001371e2771ac1754bd89fd7"
1134956dependencies = [
1135957 "bstr",
1136958 "gix-features",
@@ -1142,94 +964,71 @@ dependencies = [
1142964
1143965[[package]]
1144966name = "gix-utils"
1145−version = "0.1.4"
967+version = "0.1.7"
1146968source = "registry+https://github.com/rust-lang/crates.io-index"
1147−checksum = "7058c94f4164fcf5b8457d35f6d8f6e1007f9f7f938c9c7684a7e01d23c6ddde"
969+checksum = "ab9277a5e32e85d53f738096d872a4a9b76067ad471894ad31bd99c8fa2da1dc"
1148970dependencies = [
1149971 "fastrand",
1150972]
1151973
1152974[[package]]
1153975name = "gix-validate"
1154−version = "0.7.6"
976+version = "0.8.2"
1155977source = "registry+https://github.com/rust-lang/crates.io-index"
1156−checksum = "8d092b594c8af00a3a31fe526d363ee8a51a6f29d8496cdb991ed2f01ec0ec13"
978+checksum = "f805ebbdbaa4bfd98e2ee43e6d14099b8a4d9141f5d7b8202fea4d48e44263e7"
1157979dependencies = [
1158980 "bstr",
1159981 "thiserror",
1160982]
1161983
1162−[[package]]
1163−name = "gix-worktree"
1164−version = "0.21.1"
1165−source = "registry+https://github.com/rust-lang/crates.io-index"
1166−checksum = "c1363b9aa66b9e14412ac04e1f759827203f491729d92172535a8ce6cde02efa"
1167−dependencies = [
1168− "bstr",
1169− "filetime",
1170− "gix-attributes",
1171− "gix-features",
1172− "gix-fs",
1173− "gix-glob",
1174− "gix-hash",
1175− "gix-ignore",
1176− "gix-index",
1177− "gix-object",
1178− "gix-path",
1179− "io-close",
1180− "thiserror",
1181−]
1182−
1183984[[package]]
1184985name = "globset"
1185−version = "0.4.13"
986+version = "0.4.14"
1186987source = "registry+https://github.com/rust-lang/crates.io-index"
1187−checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d"
988+checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1"
1188989dependencies = [
1189− "aho-corasick 1.0.2",
990+ "aho-corasick",
1190991 "bstr",
1191− "fnv",
1192992 "log",
1193− "regex",
993+ "regex-automata",
994+ "regex-syntax",
1194995]
1195996
1196997[[package]]
1197998name = "grep-matcher"
1198−version = "0.1.6"
999+version = "0.1.7"
11991000source = "registry+https://github.com/rust-lang/crates.io-index"
1200−checksum = "3902ca28f26945fe35cad349d776f163981d777fee382ccd6ef451126f51b319"
1001+checksum = "47a3141a10a43acfedc7c98a60a834d7ba00dfe7bec9071cbfc19b55b292ac02"
12011002dependencies = [
12021003 "memchr",
12031004]
12041005
12051006[[package]]
12061007name = "grep-regex"
1207−version = "0.1.11"
1008+version = "0.1.12"
12081009source = "registry+https://github.com/rust-lang/crates.io-index"
1209−checksum = "997598b41d53a37a2e3fc5300d5c11d825368c054420a9c65125b8fe1078463f"
1010+checksum = "f748bb135ca835da5cbc67ca0e6955f968db9c5df74ca4f56b18e1ddbc68230d"
12101011dependencies = [
1211− "aho-corasick 0.7.20",
12121012 "bstr",
12131013 "grep-matcher",
12141014 "log",
1215− "regex",
1216− "regex-syntax 0.6.29",
1217− "thread_local",
1015+ "regex-automata",
1016+ "regex-syntax",
12181017]
12191018
12201019[[package]]
12211020name = "grep-searcher"
1222−version = "0.1.11"
1021+version = "0.1.13"
12231022source = "registry+https://github.com/rust-lang/crates.io-index"
1224−checksum = "5601c4b9f480f0c9ebb40b1f6cbf447b8a50c5369223937a6c5214368c58779f"
1023+checksum = "ba536ae4f69bec62d8839584dd3153d3028ef31bb229f04e09fb5a9e5a193c54"
12251024dependencies = [
12261025 "bstr",
1227− "bytecount",
12281026 "encoding_rs",
12291027 "encoding_rs_io",
12301028 "grep-matcher",
12311029 "log",
1232− "memmap2 0.5.10",
1030+ "memchr",
1031+ "memmap2",
12331032]
12341033
12351034[[package]]
@@ -1237,32 +1036,29 @@ name = "hashbrown"
12371036version = "0.12.3"
12381037source = "registry+https://github.com/rust-lang/crates.io-index"
12391038checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
1240−dependencies = [
1241− "ahash 0.7.6",
1242−]
12431039
12441040[[package]]
12451041name = "hashbrown"
1246−version = "0.14.0"
1042+version = "0.14.3"
12471043source = "registry+https://github.com/rust-lang/crates.io-index"
1248−checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
1044+checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
12491045dependencies = [
1250− "ahash 0.8.3",
1046+ "ahash",
12511047 "allocator-api2",
12521048]
12531049
12541050[[package]]
12551051name = "helix-core"
1256−version = "0.6.0"
1052+version = "23.10.0"
12571053dependencies = [
1258− "ahash 0.8.3",
1054+ "ahash",
12591055 "arc-swap",
1260− "bitflags 2.4.0",
1056+ "bitflags 2.4.1",
12611057 "chrono",
12621058 "dunce",
12631059 "encoding_rs",
12641060 "etcetera",
1265− "hashbrown 0.14.0",
1061+ "hashbrown 0.14.3",
12661062 "helix-loader",
12671063 "imara-diff",
12681064 "indoc",
@@ -1288,7 +1084,7 @@ dependencies = [
12881084
12891085[[package]]
12901086name = "helix-dap"
1291−version = "0.6.0"
1087+version = "23.10.0"
12921088dependencies = [
12931089 "anyhow",
12941090 "fern",
@@ -1303,7 +1099,7 @@ dependencies = [
13031099
13041100[[package]]
13051101name = "helix-event"
1306−version = "0.6.0"
1102+version = "23.10.0"
13071103dependencies = [
13081104 "parking_lot",
13091105 "tokio",
@@ -1311,7 +1107,7 @@ dependencies = [
13111107
13121108[[package]]
13131109name = "helix-loader"
1314−version = "0.6.0"
1110+version = "23.10.0"
13151111dependencies = [
13161112 "anyhow",
13171113 "cc",
@@ -1330,7 +1126,7 @@ dependencies = [
13301126
13311127[[package]]
13321128name = "helix-lsp"
1333−version = "0.6.0"
1129+version = "23.10.0"
13341130dependencies = [
13351131 "anyhow",
13361132 "futures-executor",
@@ -1352,11 +1148,11 @@ dependencies = [
13521148
13531149[[package]]
13541150name = "helix-parsec"
1355−version = "0.6.0"
1151+version = "23.10.0"
13561152
13571153[[package]]
13581154name = "helix-term"
1359−version = "0.6.0"
1155+version = "23.10.0"
13601156dependencies = [
13611157 "anyhow",
13621158 "arc-swap",
@@ -1381,6 +1177,7 @@ dependencies = [
13811177 "log",
13821178 "nucleo",
13831179 "once_cell",
1180+ "open",
13841181 "pulldown-cmark",
13851182 "serde",
13861183 "serde_json",
@@ -1391,14 +1188,15 @@ dependencies = [
13911188 "tokio",
13921189 "tokio-stream",
13931190 "toml",
1191+ "url",
13941192 "which",
13951193]
13961194
13971195[[package]]
13981196name = "helix-tui"
1399−version = "0.6.0"
1197+version = "23.10.0"
14001198dependencies = [
1401− "bitflags 2.4.0",
1199+ "bitflags 2.4.1",
14021200 "cassowary",
14031201 "crossterm",
14041202 "helix-core",
@@ -1412,7 +1210,7 @@ dependencies = [
14121210
14131211[[package]]
14141212name = "helix-vcs"
1415−version = "0.6.0"
1213+version = "23.10.0"
14161214dependencies = [
14171215 "anyhow",
14181216 "arc-swap",
@@ -1428,11 +1226,11 @@ dependencies = [
14281226
14291227[[package]]
14301228name = "helix-view"
1431−version = "0.6.0"
1229+version = "23.10.0"
14321230dependencies = [
14331231 "anyhow",
14341232 "arc-swap",
1435− "bitflags 2.4.0",
1233+ "bitflags 2.4.1",
14361234 "chardetng",
14371235 "clipboard-win",
14381236 "crossterm",
@@ -1448,7 +1246,7 @@ dependencies = [
14481246 "log",
14491247 "once_cell",
14501248 "parking_lot",
1451− "rustix 0.38.11",
1249+ "rustix",
14521250 "serde",
14531251 "serde_json",
14541252 "slotmap",
@@ -1468,25 +1266,13 @@ dependencies = [
14681266 "libc",
14691267]
14701268
1471−[[package]]
1472−name = "hermit-abi"
1473−version = "0.3.2"
1474−source = "registry+https://github.com/rust-lang/crates.io-index"
1475−checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
1476−
1477−[[package]]
1478−name = "hex"
1479−version = "0.4.3"
1480−source = "registry+https://github.com/rust-lang/crates.io-index"
1481−checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
1482−
14831269[[package]]
14841270name = "home"
1485−version = "0.5.4"
1271+version = "0.5.5"
14861272source = "registry+https://github.com/rust-lang/crates.io-index"
1487−checksum = "747309b4b440c06d57b0b25f2aee03ee9b5e5397d288c60e21fc709bb98a7408"
1273+checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb"
14881274dependencies = [
1489− "winapi",
1275+ "windows-sys 0.48.0",
14901276]
14911277
14921278[[package]]
@@ -1500,7 +1286,7 @@ dependencies = [
15001286 "iana-time-zone-haiku",
15011287 "js-sys",
15021288 "wasm-bindgen",
1503− "windows",
1289+ "windows 0.48.0",
15041290]
15051291
15061292[[package]]
@@ -1515,9 +1301,9 @@ dependencies = [
15151301
15161302[[package]]
15171303name = "idna"
1518−version = "0.4.0"
1304+version = "0.5.0"
15191305source = "registry+https://github.com/rust-lang/crates.io-index"
1520−checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
1306+checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
15211307dependencies = [
15221308 "unicode-bidi",
15231309 "unicode-normalization",
@@ -1525,17 +1311,16 @@ dependencies = [
15251311
15261312[[package]]
15271313name = "ignore"
1528−version = "0.4.20"
1314+version = "0.4.21"
15291315source = "registry+https://github.com/rust-lang/crates.io-index"
1530−checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492"
1316+checksum = "747ad1b4ae841a78e8aba0d63adbfbeaea26b517b63705d47856b73015d27060"
15311317dependencies = [
1318+ "crossbeam-deque",
15321319 "globset",
1533− "lazy_static",
15341320 "log",
15351321 "memchr",
1536− "regex",
1322+ "regex-automata",
15371323 "same-file",
1538− "thread_local",
15391324 "walkdir",
15401325 "winapi-util",
15411326]
@@ -1546,7 +1331,7 @@ version = "0.1.5"
15461331source = "registry+https://github.com/rust-lang/crates.io-index"
15471332checksum = "e98c1d0ad70fc91b8b9654b1f33db55e59579d3b3de2bffdced0fdb810570cb8"
15481333dependencies = [
1549− "ahash 0.8.3",
1334+ "ahash",
15501335 "hashbrown 0.12.3",
15511336]
15521337
@@ -1557,34 +1342,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
15571342checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d"
15581343dependencies = [
15591344 "equivalent",
1560− "hashbrown 0.14.0",
1345+ "hashbrown 0.14.3",
15611346]
15621347
15631348[[package]]
15641349name = "indoc"
1565−version = "2.0.3"
1350+version = "2.0.4"
15661351source = "registry+https://github.com/rust-lang/crates.io-index"
1567−checksum = "2c785eefb63ebd0e33416dfcb8d6da0bf27ce752843a45632a67bf10d4d4b5c4"
1352+checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8"
15681353
15691354[[package]]
1570−name = "io-close"
1571−version = "0.3.7"
1355+name = "is-docker"
1356+version = "0.2.0"
15721357source = "registry+https://github.com/rust-lang/crates.io-index"
1573−checksum = "9cadcf447f06744f8ce713d2d6239bb5bde2c357a452397a9ed90c625da390bc"
1358+checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3"
15741359dependencies = [
1575− "libc",
1576− "winapi",
1360+ "once_cell",
15771361]
15781362
15791363[[package]]
1580−name = "io-lifetimes"
1581−version = "1.0.10"
1364+name = "is-wsl"
1365+version = "0.4.0"
15821366source = "registry+https://github.com/rust-lang/crates.io-index"
1583−checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
1367+checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5"
15841368dependencies = [
1585− "hermit-abi 0.3.2",
1586− "libc",
1587− "windows-sys 0.48.0",
1369+ "is-docker",
1370+ "once_cell",
15881371]
15891372
15901373[[package]]
@@ -1602,32 +1385,17 @@ dependencies = [
16021385 "wasm-bindgen",
16031386]
16041387
1605−[[package]]
1606−name = "kstring"
1607−version = "2.0.0"
1608−source = "registry+https://github.com/rust-lang/crates.io-index"
1609−checksum = "ec3066350882a1cd6d950d055997f379ac37fd39f81cd4d8ed186032eb3c5747"
1610−dependencies = [
1611− "static_assertions",
1612−]
1613−
1614−[[package]]
1615−name = "lazy_static"
1616−version = "1.4.0"
1617−source = "registry+https://github.com/rust-lang/crates.io-index"
1618−checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
1619−
16201388[[package]]
16211389name = "libc"
1622−version = "0.2.147"
1390+version = "0.2.151"
16231391source = "registry+https://github.com/rust-lang/crates.io-index"
1624−checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3"
1392+checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
16251393
16261394[[package]]
16271395name = "libloading"
1628−version = "0.8.0"
1396+version = "0.8.1"
16291397source = "registry+https://github.com/rust-lang/crates.io-index"
1630−checksum = "d580318f95776505201b28cf98eb1fa5e4be3b689633ba6a3e6cd880ff22d8cb"
1398+checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161"
16311399dependencies = [
16321400 "cfg-if",
16331401 "windows-sys 0.48.0",
@@ -1644,15 +1412,9 @@ dependencies = [
16441412
16451413[[package]]
16461414name = "linux-raw-sys"
1647−version = "0.3.4"
1648−source = "registry+https://github.com/rust-lang/crates.io-index"
1649−checksum = "36eb31c1778188ae1e64398743890d0877fef36d11521ac60406b42016e8c2cf"
1650−
1651−[[package]]
1652−name = "linux-raw-sys"
1653−version = "0.4.3"
1415+version = "0.4.11"
16541416source = "registry+https://github.com/rust-lang/crates.io-index"
1655−checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0"
1417+checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829"
16561418
16571419[[package]]
16581420name = "lock_api"
@@ -1672,9 +1434,9 @@ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
16721434
16731435[[package]]
16741436name = "lsp-types"
1675−version = "0.94.1"
1437+version = "0.95.0"
16761438source = "registry+https://github.com/rust-lang/crates.io-index"
1677−checksum = "c66bfd44a06ae10647fe3f8214762e9369fd4248df1350924b4ef9e770a85ea1"
1439+checksum = "158c1911354ef73e8fe42da6b10c0484cb65c7f1007f28022e847706c1ab6984"
16781440dependencies = [
16791441 "bitflags 1.3.2",
16801442 "serde",
@@ -1691,18 +1453,9 @@ checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c"
16911453
16921454[[package]]
16931455name = "memmap2"
1694−version = "0.5.10"
1695−source = "registry+https://github.com/rust-lang/crates.io-index"
1696−checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327"
1697−dependencies = [
1698− "libc",
1699−]
1700−
1701−[[package]]
1702−name = "memmap2"
1703−version = "0.7.1"
1456+version = "0.9.0"
17041457source = "registry+https://github.com/rust-lang/crates.io-index"
1705−checksum = "f49388d20533534cd19360ad3d6a7dadc885944aa802ba3995040c5ec11288c6"
1458+checksum = "deaba38d7abf1d4cca21cc89e932e542ba2b9258664d2a9ef0e61512039c9375"
17061459dependencies = [
17071460 "libc",
17081461]
@@ -1716,21 +1469,6 @@ dependencies = [
17161469 "autocfg",
17171470]
17181471
1719−[[package]]
1720−name = "minimal-lexical"
1721−version = "0.2.1"
1722−source = "registry+https://github.com/rust-lang/crates.io-index"
1723−checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
1724−
1725−[[package]]
1726−name = "miniz_oxide"
1727−version = "0.6.2"
1728−source = "registry+https://github.com/rust-lang/crates.io-index"
1729−checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
1730−dependencies = [
1731− "adler",
1732−]
1733−
17341472[[package]]
17351473name = "miniz_oxide"
17361474version = "0.7.1"
@@ -1742,31 +1480,21 @@ dependencies = [
17421480
17431481[[package]]
17441482name = "mio"
1745−version = "0.8.6"
1483+version = "0.8.9"
17461484source = "registry+https://github.com/rust-lang/crates.io-index"
1747−checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
1485+checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0"
17481486dependencies = [
17491487 "libc",
17501488 "log",
17511489 "wasi",
1752− "windows-sys 0.45.0",
1753−]
1754−
1755−[[package]]
1756−name = "nom"
1757−version = "7.1.3"
1758−source = "registry+https://github.com/rust-lang/crates.io-index"
1759−checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
1760−dependencies = [
1761− "memchr",
1762− "minimal-lexical",
1490+ "windows-sys 0.48.0",
17631491]
17641492
17651493[[package]]
17661494name = "nucleo"
1767−version = "0.2.0"
1495+version = "0.2.1"
17681496source = "registry+https://github.com/rust-lang/crates.io-index"
1769−checksum = "0ccab936f2c8ad271bb31430944d98d358f74153566ea323265497f5639b11b6"
1497+checksum = "ae5331f4bcce475cf28cb29c95366c3091af4b0aa7703f1a6bc858f29718fdf3"
17701498dependencies = [
17711499 "nucleo-matcher",
17721500 "parking_lot",
@@ -1799,7 +1527,7 @@ version = "1.15.0"
17991527source = "registry+https://github.com/rust-lang/crates.io-index"
18001528checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
18011529dependencies = [
1802− "hermit-abi 0.2.6",
1530+ "hermit-abi",
18031531 "libc",
18041532]
18051533
@@ -1823,9 +1551,20 @@ dependencies = [
18231551
18241552[[package]]
18251553name = "once_cell"
1826−version = "1.18.0"
1554+version = "1.19.0"
1555+source = "registry+https://github.com/rust-lang/crates.io-index"
1556+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
1557+
1558+[[package]]
1559+name = "open"
1560+version = "5.0.1"
18271561source = "registry+https://github.com/rust-lang/crates.io-index"
1828−checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
1562+checksum = "90878fb664448b54c4e592455ad02831e23a3f7e157374a8b95654731aac7349"
1563+dependencies = [
1564+ "is-wsl",
1565+ "libc",
1566+ "pathdiff",
1567+]
18291568
18301569[[package]]
18311570name = "parking_lot"
@@ -1850,11 +1589,17 @@ dependencies = [
18501589 "windows-sys 0.45.0",
18511590]
18521591
1592+[[package]]
1593+name = "pathdiff"
1594+version = "0.2.1"
1595+source = "registry+https://github.com/rust-lang/crates.io-index"
1596+checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
1597+
18531598[[package]]
18541599name = "percent-encoding"
1855−version = "2.3.0"
1600+version = "2.3.1"
18561601source = "registry+https://github.com/rust-lang/crates.io-index"
1857−checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
1602+checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
18581603
18591604[[package]]
18601605name = "pin-project-lite"
@@ -1870,18 +1615,18 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
18701615
18711616[[package]]
18721617name = "proc-macro2"
1873−version = "1.0.63"
1618+version = "1.0.69"
18741619source = "registry+https://github.com/rust-lang/crates.io-index"
1875−checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb"
1620+checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
18761621dependencies = [
18771622 "unicode-ident",
18781623]
18791624
18801625[[package]]
18811626name = "prodash"
1882−version = "25.0.0"
1627+version = "28.0.0"
18831628source = "registry+https://github.com/rust-lang/crates.io-index"
1884−checksum = "3236ce1618b6da4c7b618e0143c4d5b5dc190f75f81c49f248221382f7e9e9ae"
1629+checksum = "744a264d26b88a6a7e37cbad97953fa233b94d585236310bcbc88474b4092d79"
18851630
18861631[[package]]
18871632name = "pulldown-cmark"
@@ -1963,53 +1708,47 @@ dependencies = [
19631708
19641709[[package]]
19651710name = "redox_syscall"
1966−version = "0.3.5"
1711+version = "0.4.1"
19671712source = "registry+https://github.com/rust-lang/crates.io-index"
1968−checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
1713+checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
19691714dependencies = [
19701715 "bitflags 1.3.2",
19711716]
19721717
19731718[[package]]
19741719name = "regex"
1975−version = "1.9.5"
1720+version = "1.10.2"
19761721source = "registry+https://github.com/rust-lang/crates.io-index"
1977−checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47"
1722+checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
19781723dependencies = [
1979− "aho-corasick 1.0.2",
1724+ "aho-corasick",
19801725 "memchr",
19811726 "regex-automata",
1982− "regex-syntax 0.7.5",
1727+ "regex-syntax",
19831728]
19841729
19851730[[package]]
19861731name = "regex-automata"
1987−version = "0.3.8"
1732+version = "0.4.3"
19881733source = "registry+https://github.com/rust-lang/crates.io-index"
1989−checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795"
1734+checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
19901735dependencies = [
1991− "aho-corasick 1.0.2",
1736+ "aho-corasick",
19921737 "memchr",
1993− "regex-syntax 0.7.5",
1738+ "regex-syntax",
19941739]
19951740
19961741[[package]]
19971742name = "regex-syntax"
1998−version = "0.6.29"
1999−source = "registry+https://github.com/rust-lang/crates.io-index"
2000−checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
2001−
2002−[[package]]
2003−name = "regex-syntax"
2004−version = "0.7.5"
1743+version = "0.8.2"
20051744source = "registry+https://github.com/rust-lang/crates.io-index"
2006−checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
1745+checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
20071746
20081747[[package]]
20091748name = "ropey"
2010−version = "1.6.0"
1749+version = "1.6.1"
20111750source = "registry+https://github.com/rust-lang/crates.io-index"
2012−checksum = "53ce7a2c43a32e50d666e33c5a80251b31147bb4b49024bcab11fb6f20c671ed"
1751+checksum = "93411e420bcd1a75ddd1dc3caf18c23155eda2c090631a85af21ba19e97093b5"
20131752dependencies = [
20141753 "smallvec",
20151754 "str_indices",
@@ -2023,29 +1762,15 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
20231762
20241763[[package]]
20251764name = "rustix"
2026−version = "0.37.15"
2027−source = "registry+https://github.com/rust-lang/crates.io-index"
2028−checksum = "a0661814f891c57c930a610266415528da53c4933e6dea5fb350cbfe048a9ece"
2029−dependencies = [
2030− "bitflags 1.3.2",
2031− "errno",
2032− "io-lifetimes",
2033− "libc",
2034− "linux-raw-sys 0.3.4",
2035− "windows-sys 0.48.0",
2036−]
2037−
2038−[[package]]
2039−name = "rustix"
2040−version = "0.38.11"
1765+version = "0.38.28"
20411766source = "registry+https://github.com/rust-lang/crates.io-index"
2042−checksum = "c0c3dde1fc030af041adc40e79c0e7fbcf431dd24870053d187d7c66e4b87453"
1767+checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316"
20431768dependencies = [
2044− "bitflags 2.4.0",
1769+ "bitflags 2.4.1",
20451770 "errno",
20461771 "libc",
2047− "linux-raw-sys 0.4.3",
2048− "windows-sys 0.48.0",
1772+ "linux-raw-sys",
1773+ "windows-sys 0.52.0",
20491774]
20501775
20511776[[package]]
@@ -2077,29 +1802,29 @@ checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1"
20771802
20781803[[package]]
20791804name = "serde"
2080−version = "1.0.188"
1805+version = "1.0.193"
20811806source = "registry+https://github.com/rust-lang/crates.io-index"
2082−checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
1807+checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
20831808dependencies = [
20841809 "serde_derive",
20851810]
20861811
20871812[[package]]
20881813name = "serde_derive"
2089−version = "1.0.188"
1814+version = "1.0.193"
20901815source = "registry+https://github.com/rust-lang/crates.io-index"
2091−checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
1816+checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
20921817dependencies = [
20931818 "proc-macro2",
20941819 "quote",
2095− "syn 2.0.28",
1820+ "syn 2.0.38",
20961821]
20971822
20981823[[package]]
20991824name = "serde_json"
2100−version = "1.0.105"
1825+version = "1.0.108"
21011826source = "registry+https://github.com/rust-lang/crates.io-index"
2102−checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360"
1827+checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
21031828dependencies = [
21041829 "itoa",
21051830 "ryu",
@@ -2114,7 +1839,7 @@ checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab"
21141839dependencies = [
21151840 "proc-macro2",
21161841 "quote",
2117− "syn 2.0.28",
1842+ "syn 2.0.38",
21181843]
21191844
21201845[[package]]
@@ -2185,18 +1910,18 @@ dependencies = [
21851910
21861911[[package]]
21871912name = "slotmap"
2188−version = "1.0.6"
1913+version = "1.0.7"
21891914source = "registry+https://github.com/rust-lang/crates.io-index"
2190−checksum = "e1e08e261d0e8f5c43123b7adf3e4ca1690d655377ac93a03b2c9d3e98de1342"
1915+checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a"
21911916dependencies = [
21921917 "version_check",
21931918]
21941919
21951920[[package]]
21961921name = "smallvec"
2197−version = "1.11.0"
1922+version = "1.11.2"
21981923source = "registry+https://github.com/rust-lang/crates.io-index"
2199−checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
1924+checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
22001925
22011926[[package]]
22021927name = "smartstring"
@@ -2217,9 +1942,9 @@ checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043"
22171942
22181943[[package]]
22191944name = "socket2"
2220−version = "0.5.3"
1945+version = "0.5.5"
22211946source = "registry+https://github.com/rust-lang/crates.io-index"
2222−checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877"
1947+checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
22231948dependencies = [
22241949 "libc",
22251950 "windows-sys 0.48.0",
@@ -2231,12 +1956,6 @@ version = "1.1.0"
22311956source = "registry+https://github.com/rust-lang/crates.io-index"
22321957checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
22331958
2234−[[package]]
2235−name = "str-buf"
2236−version = "1.0.6"
2237−source = "registry+https://github.com/rust-lang/crates.io-index"
2238−checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0"
2239−
22401959[[package]]
22411960name = "str_indices"
22421961version = "0.4.1"
@@ -2256,9 +1975,9 @@ dependencies = [
22561975
22571976[[package]]
22581977name = "syn"
2259−version = "2.0.28"
1978+version = "2.0.38"
22601979source = "registry+https://github.com/rust-lang/crates.io-index"
2261−checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567"
1980+checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b"
22621981dependencies = [
22631982 "proc-macro2",
22641983 "quote",
@@ -2267,14 +1986,14 @@ dependencies = [
22671986
22681987[[package]]
22691988name = "tempfile"
2270−version = "3.8.0"
1989+version = "3.8.1"
22711990source = "registry+https://github.com/rust-lang/crates.io-index"
2272−checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef"
1991+checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5"
22731992dependencies = [
22741993 "cfg-if",
22751994 "fastrand",
2276− "redox_syscall 0.3.5",
2277− "rustix 0.38.11",
1995+ "redox_syscall 0.4.1",
1996+ "rustix",
22781997 "windows-sys 0.48.0",
22791998]
22801999
@@ -2309,32 +2028,22 @@ dependencies = [
23092028
23102029[[package]]
23112030name = "thiserror"
2312−version = "1.0.47"
2031+version = "1.0.52"
23132032source = "registry+https://github.com/rust-lang/crates.io-index"
2314−checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f"
2033+checksum = "83a48fd946b02c0a526b2e9481c8e2a17755e47039164a86c4070446e3a4614d"
23152034dependencies = [
23162035 "thiserror-impl",
23172036]
23182037
23192038[[package]]
23202039name = "thiserror-impl"
2321−version = "1.0.47"
2040+version = "1.0.52"
23222041source = "registry+https://github.com/rust-lang/crates.io-index"
2323−checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b"
2042+checksum = "e7fbe9b594d6568a6a1443250a7e67d80b74e1e96f6d1715e1e21cc1888291d3"
23242043dependencies = [
23252044 "proc-macro2",
23262045 "quote",
2327− "syn 2.0.28",
2328−]
2329−
2330−[[package]]
2331−name = "thread_local"
2332−version = "1.1.7"
2333−source = "registry+https://github.com/rust-lang/crates.io-index"
2334−checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
2335−dependencies = [
2336− "cfg-if",
2337− "once_cell",
2046+ "syn 2.0.38",
23382047]
23392048
23402049[[package]]
@@ -2348,9 +2057,9 @@ dependencies = [
23482057
23492058[[package]]
23502059name = "time"
2351−version = "0.3.20"
2060+version = "0.3.23"
23522061source = "registry+https://github.com/rust-lang/crates.io-index"
2353−checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890"
2062+checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446"
23542063dependencies = [
23552064 "itoa",
23562065 "libc",
@@ -2362,15 +2071,15 @@ dependencies = [
23622071
23632072[[package]]
23642073name = "time-core"
2365−version = "0.1.0"
2074+version = "0.1.1"
23662075source = "registry+https://github.com/rust-lang/crates.io-index"
2367−checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
2076+checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
23682077
23692078[[package]]
23702079name = "time-macros"
2371−version = "0.2.8"
2080+version = "0.2.10"
23722081source = "registry+https://github.com/rust-lang/crates.io-index"
2373−checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36"
2082+checksum = "96ba15a897f3c86766b757e5ac7221554c6750054d74d5b28844fce5fb36a6c4"
23742083dependencies = [
23752084 "time-core",
23762085]
@@ -2392,9 +2101,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
23922101
23932102[[package]]
23942103name = "tokio"
2395−version = "1.32.0"
2104+version = "1.35.1"
23962105source = "registry+https://github.com/rust-lang/crates.io-index"
2397−checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9"
2106+checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104"
23982107dependencies = [
23992108 "backtrace",
24002109 "bytes",
@@ -2411,13 +2120,13 @@ dependencies = [
24112120
24122121[[package]]
24132122name = "tokio-macros"
2414−version = "2.1.0"
2123+version = "2.2.0"
24152124source = "registry+https://github.com/rust-lang/crates.io-index"
2416−checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
2125+checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
24172126dependencies = [
24182127 "proc-macro2",
24192128 "quote",
2420− "syn 2.0.28",
2129+ "syn 2.0.38",
24212130]
24222131
24232132[[package]]
@@ -2462,7 +2171,7 @@ dependencies = [
24622171 "serde",
24632172 "serde_spanned",
24642173 "toml_datetime",
2465− "winnow",
2174+ "winnow 0.4.6",
24662175]
24672176
24682177[[package]]
@@ -2509,13 +2218,9 @@ checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
25092218
25102219[[package]]
25112220name = "unicode-linebreak"
2512−version = "0.1.4"
2221+version = "0.1.5"
25132222source = "registry+https://github.com/rust-lang/crates.io-index"
2514−checksum = "c5faade31a542b8b35855fff6e8def199853b2da8da256da52f52f1316ee3137"
2515−dependencies = [
2516− "hashbrown 0.12.3",
2517− "regex",
2518−]
2223+checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
25192224
25202225[[package]]
25212226name = "unicode-normalization"
@@ -2534,15 +2239,15 @@ checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
25342239
25352240[[package]]
25362241name = "unicode-width"
2537−version = "0.1.10"
2242+version = "0.1.11"
25382243source = "registry+https://github.com/rust-lang/crates.io-index"
2539−checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
2244+checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
25402245
25412246[[package]]
25422247name = "url"
2543−version = "2.4.0"
2248+version = "2.5.0"
25442249source = "registry+https://github.com/rust-lang/crates.io-index"
2545−checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb"
2250+checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
25462251dependencies = [
25472252 "form_urlencoded",
25482253 "idna",
@@ -2558,9 +2263,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
25582263
25592264[[package]]
25602265name = "walkdir"
2561−version = "2.3.3"
2266+version = "2.4.0"
25622267source = "registry+https://github.com/rust-lang/crates.io-index"
2563−checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
2268+checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
25642269dependencies = [
25652270 "same-file",
25662271 "winapi-util",
@@ -2628,13 +2333,15 @@ checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
26282333
26292334[[package]]
26302335name = "which"
2631−version = "4.4.0"
2336+version = "5.0.0"
26322337source = "registry+https://github.com/rust-lang/crates.io-index"
2633−checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
2338+checksum = "9bf3ea8596f3a0dd5980b46430f2058dfe2c36a27ccfbb1845d6fbfcd9ba6e14"
26342339dependencies = [
26352340 "either",
2636− "libc",
2341+ "home",
26372342 "once_cell",
2343+ "rustix",
2344+ "windows-sys 0.48.0",
26382345]
26392346
26402347[[package]]
@@ -2677,6 +2384,25 @@ dependencies = [
26772384 "windows-targets 0.48.0",
26782385]
26792386
2387+[[package]]
2388+name = "windows"
2389+version = "0.52.0"
2390+source = "registry+https://github.com/rust-lang/crates.io-index"
2391+checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
2392+dependencies = [
2393+ "windows-core",
2394+ "windows-targets 0.52.0",
2395+]
2396+
2397+[[package]]
2398+name = "windows-core"
2399+version = "0.52.0"
2400+source = "registry+https://github.com/rust-lang/crates.io-index"
2401+checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
2402+dependencies = [
2403+ "windows-targets 0.52.0",
2404+]
2405+
26802406[[package]]
26812407name = "windows-sys"
26822408version = "0.45.0"
@@ -2695,6 +2421,15 @@ dependencies = [
26952421 "windows-targets 0.48.0",
26962422]
26972423
2424+[[package]]
2425+name = "windows-sys"
2426+version = "0.52.0"
2427+source = "registry+https://github.com/rust-lang/crates.io-index"
2428+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
2429+dependencies = [
2430+ "windows-targets 0.52.0",
2431+]
2432+
26982433[[package]]
26992434name = "windows-targets"
27002435version = "0.42.2"
@@ -2725,6 +2460,21 @@ dependencies = [
27252460 "windows_x86_64_msvc 0.48.0",
27262461]
27272462
2463+[[package]]
2464+name = "windows-targets"
2465+version = "0.52.0"
2466+source = "registry+https://github.com/rust-lang/crates.io-index"
2467+checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
2468+dependencies = [
2469+ "windows_aarch64_gnullvm 0.52.0",
2470+ "windows_aarch64_msvc 0.52.0",
2471+ "windows_i686_gnu 0.52.0",
2472+ "windows_i686_msvc 0.52.0",
2473+ "windows_x86_64_gnu 0.52.0",
2474+ "windows_x86_64_gnullvm 0.52.0",
2475+ "windows_x86_64_msvc 0.52.0",
2476+]
2477+
27282478[[package]]
27292479name = "windows_aarch64_gnullvm"
27302480version = "0.42.2"
@@ -2737,6 +2487,12 @@ version = "0.48.0"
27372487source = "registry+https://github.com/rust-lang/crates.io-index"
27382488checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
27392489
2490+[[package]]
2491+name = "windows_aarch64_gnullvm"
2492+version = "0.52.0"
2493+source = "registry+https://github.com/rust-lang/crates.io-index"
2494+checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
2495+
27402496[[package]]
27412497name = "windows_aarch64_msvc"
27422498version = "0.42.2"
@@ -2749,6 +2505,12 @@ version = "0.48.0"
27492505source = "registry+https://github.com/rust-lang/crates.io-index"
27502506checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
27512507
2508+[[package]]
2509+name = "windows_aarch64_msvc"
2510+version = "0.52.0"
2511+source = "registry+https://github.com/rust-lang/crates.io-index"
2512+checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
2513+
27522514[[package]]
27532515name = "windows_i686_gnu"
27542516version = "0.42.2"
@@ -2761,6 +2523,12 @@ version = "0.48.0"
27612523source = "registry+https://github.com/rust-lang/crates.io-index"
27622524checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
27632525
2526+[[package]]
2527+name = "windows_i686_gnu"
2528+version = "0.52.0"
2529+source = "registry+https://github.com/rust-lang/crates.io-index"
2530+checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
2531+
27642532[[package]]
27652533name = "windows_i686_msvc"
27662534version = "0.42.2"
@@ -2773,6 +2541,12 @@ version = "0.48.0"
27732541source = "registry+https://github.com/rust-lang/crates.io-index"
27742542checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
27752543
2544+[[package]]
2545+name = "windows_i686_msvc"
2546+version = "0.52.0"
2547+source = "registry+https://github.com/rust-lang/crates.io-index"
2548+checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
2549+
27762550[[package]]
27772551name = "windows_x86_64_gnu"
27782552version = "0.42.2"
@@ -2785,6 +2559,12 @@ version = "0.48.0"
27852559source = "registry+https://github.com/rust-lang/crates.io-index"
27862560checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
27872561
2562+[[package]]
2563+name = "windows_x86_64_gnu"
2564+version = "0.52.0"
2565+source = "registry+https://github.com/rust-lang/crates.io-index"
2566+checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
2567+
27882568[[package]]
27892569name = "windows_x86_64_gnullvm"
27902570version = "0.42.2"
@@ -2797,6 +2577,12 @@ version = "0.48.0"
27972577source = "registry+https://github.com/rust-lang/crates.io-index"
27982578checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
27992579
2580+[[package]]
2581+name = "windows_x86_64_gnullvm"
2582+version = "0.52.0"
2583+source = "registry+https://github.com/rust-lang/crates.io-index"
2584+checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
2585+
28002586[[package]]
28012587name = "windows_x86_64_msvc"
28022588version = "0.42.2"
@@ -2809,6 +2595,12 @@ version = "0.48.0"
28092595source = "registry+https://github.com/rust-lang/crates.io-index"
28102596checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
28112597
2598+[[package]]
2599+name = "windows_x86_64_msvc"
2600+version = "0.52.0"
2601+source = "registry+https://github.com/rust-lang/crates.io-index"
2602+checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
2603+
28122604[[package]]
28132605name = "winnow"
28142606version = "0.4.6"
@@ -2818,9 +2610,18 @@ dependencies = [
28182610 "memchr",
28192611]
28202612
2613+[[package]]
2614+name = "winnow"
2615+version = "0.5.28"
2616+source = "registry+https://github.com/rust-lang/crates.io-index"
2617+checksum = "6c830786f7720c2fd27a1a0e27a709dbd3c4d009b56d098fc742d4f4eab91fe2"
2618+dependencies = [
2619+ "memchr",
2620+]
2621+
28212622[[package]]
28222623name = "xtask"
2823−version = "0.6.0"
2624+version = "23.10.0"
28242625dependencies = [
28252626 "helix-core",
28262627 "helix-loader",
@@ -2828,3 +2629,23 @@ dependencies = [
28282629 "helix-view",
28292630 "toml",
28302631]
2632+
2633+[[package]]
2634+name = "zerocopy"
2635+version = "0.7.31"
2636+source = "registry+https://github.com/rust-lang/crates.io-index"
2637+checksum = "1c4061bedbb353041c12f413700357bec76df2c7e2ca8e4df8bac24c6bf68e3d"
2638+dependencies = [
2639+ "zerocopy-derive",
2640+]
2641+
2642+[[package]]
2643+name = "zerocopy-derive"
2644+version = "0.7.31"
2645+source = "registry+https://github.com/rust-lang/crates.io-index"
2646+checksum = "b3c129550b3e6de3fd0ba67ba5c81818f9805e58b8d7fee80a3a59d2c9fc601a"
2647+dependencies = [
2648+ "proc-macro2",
2649+ "quote",
2650+ "syn 2.0.38",
2651+]
Cargo.toml+11
@@ -1,4 +1,5 @@
11[workspace]
2+resolver = "2"
23members = [
34 "helix-core",
45 "helix-view",
@@ -37,3 +38,13 @@ package.helix-term.opt-level = 2
3738[workspace.dependencies]
3839tree-sitter = { version = "0.20", git = "https://github.com/tree-sitter/tree-sitter", rev = "ab09ae20d640711174b8da8a654f6b3dec93da1a" }
3940nucleo = "0.2.0"
41+
42+[workspace.package]
43+version = "23.10.0"
44+edition = "2021"
45+authors = ["Blaž Hrastnik <blaz@mxxn.io>"]
46+categories = ["editor"]
47+repository = "https://github.com/helix-editor/helix"
48+homepage = "https://helix-editor.com"
49+license = "MPL-2.0"
50+rust-version = "1.70"
README.md+1−1
@@ -18,7 +18,7 @@
1818
1919![Screenshot](./screenshot.png)
2020
21−A Kakoune / Neovim inspired editor, written in Rust.
21+A [Kakoune](https://github.com/mawww/kakoune) / [Neovim](https://github.com/neovim/neovim) inspired editor, written in Rust.
2222
2323The editing model is very heavily based on Kakoune; during development I found
2424myself agreeing with most of Kakoune's design decisions.
VERSIONdeleted−1
@@ -1 +0,0 @@
1−23.05
book/custom.css+1−1
@@ -164,7 +164,7 @@ code.hljs {
164164 --searchresults-header-fg: #5f5f71;
165165 --searchresults-border-color: #5c5c68;
166166 --searchresults-li-bg: #242430;
167− --search-mark-bg: #acff5;
167+ --search-mark-bg: #a2cff5;
168168}
169169
170170.colibri .content .header {
book/src/configuration.md+27−9
@@ -51,7 +51,7 @@ Its settings will be merged with the configuration directory `config.toml` and t
5151| `auto-completion` | Enable automatic pop up of auto-completion | `true` |
5252| `auto-format` | Enable automatic formatting on save | `true` |
5353| `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` |
54−| `idle-timeout` | Time in milliseconds since last keypress before idle timers trigger. Used for autocompletion, set to 0 for instant | `400` |
54+| `idle-timeout` | Time in milliseconds since last keypress before idle timers trigger. Used for autocompletion, set to 0 for instant | `250` |
5555| `preview-completion-insert` | Whether to apply completion item instantly when selected | `true` |
5656| `completion-trigger-len` | The min-length of word under cursor to trigger autocompletion | `2` |
5757| `completion-replace` | Set to `true` to make completions always replace the entire word and not just the part before the cursor | `false` |
@@ -64,6 +64,9 @@ Its settings will be merged with the configuration directory `config.toml` and t
6464| `text-width` | Maximum line length. Used for the `:reflow` command and soft-wrapping if `soft-wrap.wrap-at-text-width` is set | `80` |
6565| `workspace-lsp-roots` | Directories relative to the workspace root that are treated as LSP roots. Should only be set in `.helix/config.toml` | `[]` |
6666| `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` |
67+| `insert-final-newline` | Whether to automatically insert a trailing line-ending on write if missing | `true` |
68+| `popup-border` | Draw border around `popup`, `menu`, `all`, or `none` | `none` |
69+| `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`
6770
6871### `[editor.statusline]` Section
6972
@@ -165,16 +168,31 @@ All git related options are only enabled in a git repository.
165168
166169| Key | Description | Default |
167170|--|--|---------|
168−|`hidden` | Enables ignoring hidden files | true
169−|`follow-symlinks` | Follow symlinks instead of ignoring them | true
170−|`deduplicate-links` | Ignore symlinks that point at files already shown in the picker | true
171−|`parents` | Enables reading ignore files from parent directories | true
172−|`ignore` | Enables reading `.ignore` files | true
173−|`git-ignore` | Enables reading `.gitignore` files | true
174−|`git-global` | Enables reading global `.gitignore`, whose path is specified in git's config: `core.excludefile` option | true
175−|`git-exclude` | Enables reading `.git/info/exclude` files | true
171+|`hidden` | Enables ignoring hidden files | `true`
172+|`follow-symlinks` | Follow symlinks instead of ignoring them | `true`
173+|`deduplicate-links` | Ignore symlinks that point at files already shown in the picker | `true`
174+|`parents` | Enables reading ignore files from parent directories | `true`
175+|`ignore` | Enables reading `.ignore` files | `true`
176+|`git-ignore` | Enables reading `.gitignore` files | `true`
177+|`git-global` | Enables reading global `.gitignore`, whose path is specified in git's config: `core.excludesfile` option | `true`
178+|`git-exclude` | Enables reading `.git/info/exclude` files | `true`
176179|`max-depth` | Set with an integer value for maximum depth to recurse | Defaults to `None`.
177180
181+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.
182+
183+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:
184+- Linux and Mac: `~/.config/helix/ignore`
185+- Windows: `%AppData%\helix\ignore`
186+
187+Example:
188+
189+```ini
190+# unignore in file picker and global search
191+!.github/
192+!.gitignore
193+!.gitattributes
194+```
195+
178196### `[editor.auto-pairs]` Section
179197
180198Enables automatic insertion of pairs to parentheses, brackets, etc. Can be a
book/src/generated/lang-support.md+22−11
@@ -1,5 +1,6 @@
11| Language | Syntax Highlighting | Treesitter Textobjects | Auto Indent | Default LSP |
22| --- | --- | --- | --- | --- |
3+| agda | ✓ | | | |
34| astro | ✓ | | | |
45| awk | ✓ | ✓ | | `awk-language-server` |
56| bash | ✓ | ✓ | ✓ | `bash-language-server` |
@@ -10,13 +11,13 @@
1011| blueprint | ✓ | | | `blueprint-compiler` |
1112| c | ✓ | ✓ | ✓ | `clangd` |
1213| c-sharp | ✓ | ✓ | | `OmniSharp` |
13−| cabal | | | | |
14+| cabal | | | | `haskell-language-server-wrapper` |
1415| cairo | ✓ | ✓ | ✓ | `cairo-language-server` |
1516| capnp | ✓ | | ✓ | |
1617| clojure | ✓ | | | `clojure-lsp` |
1718| cmake | ✓ | ✓ | ✓ | `cmake-language-server` |
1819| comment | ✓ | | | |
19−| common-lisp | ✓ | | | `cl-lsp` |
20+| common-lisp | ✓ | | ✓ | `cl-lsp` |
2021| cpon | ✓ | | ✓ | |
2122| cpp | ✓ | ✓ | ✓ | `clangd` |
2223| crystal | ✓ | ✓ | | `crystalline` |
@@ -24,6 +25,7 @@
2425| cue | ✓ | | | `cuelsp` |
2526| d | ✓ | ✓ | ✓ | `serve-d` |
2627| dart | ✓ | | ✓ | `dart` |
28+| dbml | ✓ | | | |
2729| devicetree | ✓ | | | |
2830| dhall | ✓ | ✓ | | `dhall-lsp-server` |
2931| diff | ✓ | | | |
@@ -44,6 +46,7 @@
4446| forth | ✓ | | | `forth-lsp` |
4547| fortran | ✓ | | ✓ | `fortls` |
4648| fsharp | ✓ | | | `fsautocomplete` |
49+| gas | ✓ | ✓ | | |
4750| gdscript | ✓ | ✓ | ✓ | |
4851| gemini | ✓ | | | |
4952| git-attributes | ✓ | | | |
@@ -53,12 +56,13 @@
5356| git-rebase | ✓ | | | |
5457| gleam | ✓ | ✓ | | `gleam` |
5558| glsl | ✓ | ✓ | ✓ | |
56−| go | ✓ | ✓ | ✓ | `gopls` |
59+| gn | ✓ | | | |
60+| go | ✓ | ✓ | ✓ | `gopls`, `golangci-lint-langserver` |
5761| godot-resource | ✓ | | | |
5862| gomod | ✓ | | | `gopls` |
5963| gotmpl | ✓ | | | `gopls` |
6064| gowork | ✓ | | | `gopls` |
61−| graphql | ✓ | | | |
65+| graphql | ✓ | | | `graphql-lsp` |
6266| hare | ✓ | | | |
6367| haskell | ✓ | ✓ | | `haskell-language-server-wrapper` |
6468| haskell-persistent | ✓ | | | |
@@ -70,16 +74,18 @@
7074| idris | | | | `idris2-lsp` |
7175| iex | ✓ | | | |
7276| ini | ✓ | | | |
77+| janet | ✓ | | | |
7378| java | ✓ | ✓ | ✓ | `jdtls` |
7479| javascript | ✓ | ✓ | ✓ | `typescript-language-server` |
7580| jinja | ✓ | | | |
7681| jsdoc | ✓ | | | |
7782| json | ✓ | | ✓ | `vscode-json-language-server` |
83+| json5 | ✓ | | | |
7884| jsonnet | ✓ | | | `jsonnet-language-server` |
7985| jsx | ✓ | ✓ | ✓ | `typescript-language-server` |
8086| julia | ✓ | ✓ | ✓ | `julia` |
8187| just | ✓ | ✓ | ✓ | |
82−| kdl | ✓ | | | |
88+| kdl | ✓ | ✓ | ✓ | |
8389| kotlin | ✓ | | | `kotlin-language-server` |
8490| latex | ✓ | ✓ | | `texlab` |
8591| lean | ✓ | | | `lean` |
@@ -87,6 +93,8 @@
8793| llvm | ✓ | ✓ | ✓ | |
8894| llvm-mir | ✓ | ✓ | ✓ | |
8995| llvm-mir-yaml | ✓ | | ✓ | |
96+| log | ✓ | | | |
97+| lpf | ✓ | | | |
9098| lua | ✓ | ✓ | ✓ | `lua-language-server` |
9199| make | ✓ | | | |
92100| markdoc | ✓ | | | `markdoc-ls` |
@@ -101,7 +109,7 @@
101109| nickel | ✓ | | ✓ | `nls` |
102110| nim | ✓ | ✓ | ✓ | `nimlangserver` |
103111| nix | ✓ | | | `nil` |
104−| nu | ✓ | | | |
112+| nu | ✓ | | | `nu` |
105113| nunjucks | ✓ | | | |
106114| ocaml | ✓ | | ✓ | `ocamllsp` |
107115| ocaml-interface | ✓ | | | `ocamllsp` |
@@ -112,7 +120,7 @@
112120| pascal | ✓ | ✓ | | `pasls` |
113121| passwd | ✓ | | | |
114122| pem | ✓ | | | |
115−| perl | ✓ | | | `perlnavigator` |
123+| perl | ✓ | ✓ | ✓ | `perlnavigator` |
116124| php | ✓ | ✓ | ✓ | `intelephense` |
117125| po | ✓ | ✓ | | |
118126| pod | ✓ | | | |
@@ -121,11 +129,11 @@
121129| prolog | | | | `swipl` |
122130| protobuf | ✓ | | ✓ | `bufls`, `pb` |
123131| prql | ✓ | | | |
124−| purescript | ✓ | | | `purescript-language-server` |
132+| purescript | ✓ | ✓ | | `purescript-language-server` |
125133| python | ✓ | ✓ | ✓ | `pylsp` |
126134| qml | ✓ | | ✓ | `qmlls` |
127135| r | ✓ | | | `R` |
128−| racket | ✓ | | | `racket` |
136+| racket | ✓ | | ✓ | `racket` |
129137| regex | ✓ | | | |
130138| rego | ✓ | | | `regols` |
131139| rescript | ✓ | ✓ | | `rescript-language-server` |
@@ -137,9 +145,10 @@
137145| rust | ✓ | ✓ | ✓ | `rust-analyzer` |
138146| sage | ✓ | ✓ | | |
139147| scala | ✓ | | ✓ | `metals` |
140−| scheme | ✓ | | | |
148+| scheme | ✓ | | ✓ | |
141149| scss | ✓ | | | `vscode-css-language-server` |
142150| slint | ✓ | | ✓ | `slint-lsp` |
151+| smali | ✓ | | ✓ | |
143152| smithy | ✓ | | | `cs` |
144153| sml | ✓ | | | |
145154| solidity | ✓ | | | `solc` |
@@ -153,6 +162,7 @@
153162| t32 | ✓ | | | |
154163| tablegen | ✓ | ✓ | ✓ | |
155164| task | ✓ | | | |
165+| templ | ✓ | | | `templ` |
156166| tfvars | ✓ | | ✓ | `terraform-ls` |
157167| todotxt | ✓ | | | |
158168| toml | ✓ | | | `taplo` |
@@ -160,6 +170,7 @@
160170| tsx | ✓ | ✓ | ✓ | `typescript-language-server` |
161171| twig | ✓ | | | |
162172| typescript | ✓ | ✓ | ✓ | `typescript-language-server` |
173+| typst | ✓ | | | `typst-lsp` |
163174| ungrammar | ✓ | | | |
164175| unison | ✓ | | | |
165176| uxntal | ✓ | | | |
@@ -177,6 +188,6 @@
177188| wren | ✓ | ✓ | ✓ | |
178189| xit | ✓ | | | |
179190| xml | ✓ | | ✓ | |
180−| yaml | ✓ | | ✓ | `yaml-language-server` |
191+| yaml | ✓ | | ✓ | `yaml-language-server`, `ansible-language-server` |
181192| yuck | ✓ | | | |
182193| zig | ✓ | ✓ | ✓ | `zls` |
book/src/generated/typable-cmd.md+4−1
@@ -17,7 +17,7 @@
1717| `: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) |
1818| `:new`, `:n` | Create a new scratch buffer. |
1919| `:format`, `:fmt` | Format the file using the LSP formatter. |
20−| `:indent-style` | Set the indentation style for editing. ('t' for tabs or 1-8 for number of spaces.) |
20+| `:indent-style` | Set the indentation style for editing. ('t' for tabs or 1-16 for number of spaces.) |
2121| `:line-ending` | Set the document's default line ending. Options: crlf, lf. |
2222| `:earlier`, `:ear` | Jump back to an earlier point in edit history. Accepts a number of steps or a time span. |
2323| `:later`, `:lat` | Jump to a later point in edit history. Accepts a number of steps or a time span. |
@@ -55,6 +55,7 @@
5555| `:lsp-restart` | Restarts the language servers used by the current doc |
5656| `:lsp-stop` | Stops the language servers that are used by the current doc |
5757| `:tree-sitter-scopes` | Display tree sitter scopes, primarily for theming and development. |
58+| `:tree-sitter-highlight-name` | Display name of tree-sitter highlight scope under the cursor. |
5859| `:debug-start`, `:dbg` | Start a debug session from a given template with given parameters. |
5960| `:debug-remote`, `:dbg-tcp` | Connect to a debug adapter by TCP address and start a debugging session from a given template with given parameters. |
6061| `:debug-eval` | Evaluate expression in current debug context. |
@@ -83,3 +84,5 @@
8384| `:run-shell-command`, `:sh` | Run a shell command |
8485| `:reset-diff-change`, `:diffget`, `:diffg` | Reset the diff change at the cursor position. |
8586| `:clear-register` | Clear given register. If no argument is provided, clear all registers. |
87+| `:redraw` | Clear and re-render the whole UI |
88+| `:move` | Move the current buffer and its corresponding file to a different path |
book/src/guides/adding_languages.md+2
@@ -36,6 +36,7 @@ below.
36363. Refer to the
3737 [tree-sitter website](https://tree-sitter.github.io/tree-sitter/syntax-highlighting#queries)
3838 for more information on writing queries.
39+4. A list of highlight captures can be found [on the themes page](https://docs.helix-editor.com/themes.html#scopes).
3940
4041> 💡 In Helix, the first matching query takes precedence when evaluating
4142> queries, which is different from other editors such as Neovim where the last
@@ -51,3 +52,4 @@ below.
5152 grammars.
5253- If a parser is causing a segfault, or you want to remove it, make sure to
5354 remove the compiled parser located at `runtime/grammars/<name>.so`.
55+- 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.
book/src/guides/indent.md+9
@@ -12,6 +12,15 @@ Note that it matters where these added indents begin. For example,
1212multiple indent level increases that start on the same line only increase
1313the total indent level by 1. See [Capture types](#capture-types).
1414
15+By default, Helix uses the `hybrid` indentation heuristic. This means that
16+indent queries are not used to compute the expected absolute indentation of a
17+line but rather the expected difference in indentation between the new and an
18+already existing line. This difference is then added to the actual indentation
19+of the already existing line. Since this makes errors in the indent queries
20+harder to find, it is recommended to disable it when testing via
21+`:set indent-heuristic tree-sitter`. The rest of this guide assumes that
22+the `tree-sitter` heuristic is used.
23+
1524## Indent queries
1625
1726When Helix is inserting a new line through `o`, `O`, or `<ret>`, to determine
book/src/guides/injection.md+1−1
@@ -1,7 +1,7 @@
11# Adding Injection Queries
22
33Writing language injection queries allows one to highlight a specific node as a different language.
4−In addition to the [standard](upstream-docs) language injection options used by tree-sitter, there
4+In addition to the [standard][upstream-docs] language injection options used by tree-sitter, there
55are a few Helix specific extensions that allow for more control.
66
77And example of a simple query that would highlight all strings as bash in Nix:
book/src/install.md+30−6
@@ -13,6 +13,7 @@
1313 - [AppImage](#appimage)
1414- [macOS](#macos)
1515 - [Homebrew Core](#homebrew-core)
16+ - [MacPorts](#macports)
1617- [Windows](#windows)
1718 - [Winget](#winget)
1819 - [Scoop](#scoop)
@@ -64,10 +65,7 @@ sudo apt install helix
6465
6566### Fedora/RHEL
6667
67−Enable the `COPR` repository for Helix:
68−
6968```sh
70−sudo dnf copr enable varlad/helix
7169sudo dnf install helix
7270```
7371
@@ -133,6 +131,12 @@ chmod +x helix-*.AppImage # change permission for executable mode
133131brew install helix
134132```
135133
134+### MacPorts
135+
136+```sh
137+port install helix
138+```
139+
136140## Windows
137141
138142Install on Windows using [Winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/), [Scoop](https://scoop.sh/), [Chocolatey](https://chocolatey.org/)
@@ -224,7 +228,7 @@ Or, create a symbolic link:
224228ln -Ts $PWD/runtime ~/.config/helix/runtime
225229```
226230
227−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.
231+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.
228232
229233#### Windows
230234
@@ -257,12 +261,32 @@ following order:
2572611. `runtime/` sibling directory to `$CARGO_MANIFEST_DIR` directory (this is intended for
258262 developing and testing helix only).
2592632. `runtime/` subdirectory of OS-dependent helix user config directory.
260−3. `$HELIX_RUNTIME`.
261−4. `runtime/` subdirectory of path to Helix executable.
264+3. `$HELIX_RUNTIME`
265+4. Distribution-specific fallback directory (set at compile time—not run time—
266+ with the `HELIX_DEFAULT_RUNTIME` environment variable)
267+5. `runtime/` subdirectory of path to Helix executable.
262268
263269This order also sets the priority for selecting which file will be used if multiple runtime
264270directories have files with the same name.
265271
272+#### Note to packagers
273+
274+If you are making a package of Helix for end users, to provide a good out of
275+the box experience, you should set the `HELIX_DEFAULT_RUNTIME` environment
276+variable at build time (before invoking `cargo build`) to a directory which
277+will store the final runtime files after installation. For example, say you want
278+to package the runtime into `/usr/lib/helix/runtime`. The rough steps a build
279+script could follow are:
280+
281+1. `export HELIX_DEFAULT_RUNTIME=/usr/lib/helix/runtime`
282+1. `cargo build --profile opt --locked --path helix-term`
283+1. `cp -r runtime $BUILD_DIR/usr/lib/helix/`
284+1. `cp target/opt/hx $BUILD_DIR/usr/bin/hx`
285+
286+This way the resulting `hx` binary will always look for its runtime directory in
287+`/usr/lib/helix/runtime` if the user has no custom runtime in `~/.config/helix`
288+or `HELIX_RUNTIME`.
289+
266290### Validating the installation
267291
268292To make sure everything is set up as expected you should run the Helix health
book/src/keymap.md+1−1
@@ -25,7 +25,7 @@
2525
2626## Normal mode
2727
28−Normal mode is the default mode when you launch helix. Return to it from other modes by typing `Escape`.
28+Normal mode is the default mode when you launch helix. You can return to it from other modes by pressing the `Escape` key.
2929
3030### Movement
3131
book/src/languages.md+3−1
@@ -66,8 +66,10 @@ These configuration keys are available:
6666| `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) |
6767| `grammar` | The tree-sitter grammar to use (defaults to the value of `name`) |
6868| `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 |
69+| `soft-wrap` | [editor.softwrap](./configuration.md#editorsoft-wrap-section)
6970| `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` |
7071| `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. |
72+| `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.
7173
7274### File-type detection and the `file-types` key
7375
@@ -127,7 +129,7 @@ These are the available options for a language server.
127129| `environment` | Any environment variables that will be used when starting the language server `{ "KEY1" = "Value1", "KEY2" = "Value2" }` |
128130
129131A `format` sub-table within `config` can be used to pass extra formatting options to
130−[Document Formatting Requests](https://github.com/microsoft/language-server-protocol/blob/gh-pages/_specifications/specification-3-17.md#document-formatting-request--leftwards_arrow_with_hook).
132+[Document Formatting Requests](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_formatting).
131133For example, with typescript:
132134
133135```toml
book/src/themes.md+8−1
@@ -155,6 +155,7 @@ We use a similar set of scopes as
155155
156156- `type` - Types
157157 - `builtin` - Primitive types provided by the language (`int`, `usize`)
158+ - `parameter` - Generic type parameters (`T`)
158159 - `enum`
159160 - `variant`
160161- `constructor`
@@ -245,9 +246,12 @@ We use a similar set of scopes as
245246
246247- `diff` - version control changes
247248 - `plus` - additions
249+ - `gutter` - gutter indicator
248250 - `minus` - deletions
251+ - `gutter` - gutter indicator
249252 - `delta` - modifications
250253 - `moved` - renamed or moved files/changes
254+ - `gutter` - gutter indicator
251255
252256#### Interface
253257
@@ -292,11 +296,14 @@ These scopes are used for theming the editor interface:
292296| `ui.statusline.insert` | Statusline mode during insert mode ([only if `editor.color-modes` is enabled][editor-section]) |
293297| `ui.statusline.select` | Statusline mode during select mode ([only if `editor.color-modes` is enabled][editor-section]) |
294298| `ui.statusline.separator` | Separator character in statusline |
299+| `ui.bufferline` | Style for the buffer line |
300+| `ui.bufferline.active` | Style for the active buffer in buffer line |
301+| `ui.bufferline.background` | Style for bufferline background |
295302| `ui.popup` | Documentation popups (e.g. Space + k) |
296303| `ui.popup.info` | Prompt for multiple key options |
297304| `ui.window` | Borderlines separating splits |
298305| `ui.help` | Description box for commands |
299−| `ui.text` | Command prompts, popup text, etc. |
306+| `ui.text` | Default text style, command prompts, popup text, etc. |
300307| `ui.text.focus` | The currently selected line in the picker |
301308| `ui.text.inactive` | Same as `ui.text` but when the text is inactive (e.g. suggestions) |
302309| `ui.text.info` | The key: command text in `ui.popup.info` boxes |
book/src/usage.md+2−2
@@ -59,8 +59,8 @@ Some registers have special behavior when read from and written to.
5959| `#` | Selection indices (first selection is `1`, second is `2`, etc.) | This register is not writable |
6060| `.` | Contents of the current selections | This register is not writable |
6161| `%` | Name of the current file | This register is not writable |
62−| `*` | Reads from the system clipboard | Joins and yanks to the system clipboard |
63−| `+` | Reads from the primary clipboard | Joins and yanks to the primary clipboard |
62+| `+` | Reads from the system clipboard | Joins and yanks to the system clipboard |
63+| `*` | Reads from the primary clipboard | Joins and yanks to the primary clipboard |
6464
6565When yanking multiple selections to the clipboard registers, the selections
6666are joined with newlines. Pasting from these registers will paste multiple
book/theme/index.hbs+18−15
@@ -1,11 +1,11 @@
11<!DOCTYPE HTML>
2−<html lang="{{ language }}" class="sidebar-visible no-js {{ default_theme }}">
2+<html lang="{{ language }}" class="{{ default_theme }}" dir="{{ text_direction }}">
33 <head>
44 <!-- Book generated using mdBook -->
55 <meta charset="UTF-8">
66 <title>{{ title }}</title>
77 {{#if is_print }}
8− <meta name="robots" content="noindex" />
8+ <meta name="robots" content="noindex">
99 {{/if}}
1010 {{#if base_url}}
1111 <base href="{{ base_url }}">
@@ -17,7 +17,7 @@
1717
1818 <meta name="description" content="{{ description }}">
1919 <meta name="viewport" content="width=device-width, initial-scale=1">
20− <meta name="theme-color" content="#ffffff" />
20+ <meta name="theme-color" content="#ffffff">
2121
2222 {{#if favicon_svg}}
2323 <link rel="icon" href="{{ path_to_root }}favicon.svg">
@@ -34,8 +34,6 @@
3434
3535 <!-- Fonts -->
3636 <link rel="stylesheet" href="{{ path_to_root }}FontAwesome/css/font-awesome.css">
37− <link rel="preconnect" href="https://fonts.gstatic.com">
38− <link href="https://fonts.googleapis.com/css2?family=Inter:wght@200;400;500;700&display=swap" rel="stylesheet">
3937 {{#if copy_fonts}}
4038 <link rel="stylesheet" href="{{ path_to_root }}fonts/fonts.css">
4139 {{/if}}
@@ -55,7 +53,7 @@
5553 <script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
5654 {{/if}}
5755 </head>
58− <body>
56+ <body class="sidebar-visible no-js">
5957 <div id="body-container">
6058 <!-- Provide site root to javascript -->
6159 <script>
@@ -85,24 +83,29 @@
8583 try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
8684 if (theme === null || theme === undefined) { theme = default_theme; }
8785 var html = document.querySelector('html');
88− html.classList.remove('no-js')
8986 html.classList.remove('{{ default_theme }}')
9087 html.classList.add(theme);
91− html.classList.add('js');
88+ var body = document.querySelector('body');
89+ body.classList.remove('no-js')
90+ body.classList.add('js');
9291 </script>
9392
93+ <input type="checkbox" id="sidebar-toggle-anchor" class="hidden">
94+
9495 <!-- Hide / unhide sidebar before it is displayed -->
9596 <script>
96− var html = document.querySelector('html');
97+ var body = document.querySelector('body');
9798 var sidebar = null;
99+ var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
98100 if (document.body.clientWidth >= 1080) {
99101 try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
100102 sidebar = sidebar || 'visible';
101103 } else {
102104 sidebar = 'hidden';
103105 }
104− html.classList.remove('sidebar-visible');
105− html.classList.add("sidebar-" + sidebar);
106+ sidebar_toggle.checked = sidebar === 'visible';
107+ body.classList.remove('sidebar-visible');
108+ body.classList.add("sidebar-" + sidebar);
106109 </script>
107110
108111 <nav id="sidebar" class="sidebar" aria-label="Table of contents">
@@ -141,9 +144,9 @@
141144 <div id="menu-bar-hover-placeholder"></div>
142145 <div id="menu-bar" class="menu-bar sticky">
143146 <div class="left-buttons">
144− <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
147+ <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">
145148 <i class="fa fa-bars"></i>
146− </button>
149+ </label>
147150 <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">
148151 <i class="fa fa-paint-brush"></i>
149152 </button>
@@ -220,7 +223,7 @@
220223 {{/previous}}
221224
222225 {{#next}}
223− <a rel="next" href="{{ path_to_root }}{{link}}" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
226+ <a rel="next prefetch" href="{{ path_to_root }}{{link}}" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
224227 <i class="fa fa-angle-right"></i>
225228 </a>
226229 {{/next}}
@@ -238,7 +241,7 @@
238241 {{/previous}}
239242
240243 {{#next}}
241− <a rel="next" href="{{ path_to_root }}{{link}}" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
244+ <a rel="next prefetch" href="{{ path_to_root }}{{link}}" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
242245 <i class="fa fa-angle-right"></i>
243246 </a>
244247 {{/next}}
contrib/Helix.appdata.xml+15
@@ -5,6 +5,7 @@
55 <project_license>MPL-2.0</project_license>
66 <name>Helix</name>
77 <summary>A post-modern text editor</summary>
8+ <summary xml:lang="ar">مُحَرِّرُ نُصُوصٍ سَابِقٌ لِعَهدِه</summary>
89
910 <description>
1011 <p>
@@ -17,6 +18,17 @@
1718 <li>Smart, incremental syntax highlighting and code editing via tree-sitter</li>
1819 </ul>
1920 </description>
21+ <description xml:lang="ar">
22+ <p>
23+ مُحَرِّرُ نُصُوصٍ يَعمَلُ فِي الطَّرَفِيَّة، مُستَلهَمٌ مِن Kakoune وَ Neovim وَمَكتُوبٌ بِلُغَةِ رَست البَرمَجِيَّة.
24+ </p>
25+ <ul>
26+ <li>تَحرِيرٌ وَضعِيٌّ شَبيهٌ بِـVim</li>
27+ <li>تَحدِيدَاتٌ لِلنَّصِ مُتَعَدِّدَة</li>
28+ <li>دَعْمٌ مُدمَجٌ لِخَوادِمِ اللُّغَات</li>
29+ <li>تَحرِيرُ التَّعلِيمَاتِ البَّرمَجِيَّةِ مَعَ تَمييزٍ لِلتَّركِيبِ النَّحُويِّ بِواسِطَةِ tree-sitter</li>
30+ </ul>
31+ </description>
2032
2133 <launchable type="desktop-id">Helix.desktop</launchable>
2234
@@ -36,6 +48,9 @@
3648 <content_rating type="oars-1.1" />
3749
3850 <releases>
51+ <release version="23.10" date="2023-10-24">
52+ <url>https://helix-editor.com/news/release-23-10-highlights/</url>
53+ </release>
3954 <release version="23.05" date="2023-05-18">
4055 <url>https://github.com/helix-editor/helix/releases/tag/23.05</url>
4156 </release>
contrib/Helix.desktop+3−1
@@ -1,6 +1,7 @@
11[Desktop Entry]
22Name=Helix
33GenericName=Text Editor
4+GenericName[ar]=مُحَرِّرُ نُصُوص
45GenericName[de]=Texteditor
56GenericName[fr]=Éditeur de texte
67GenericName[ru]=Текстовый редактор
@@ -9,7 +10,7 @@ GenericName[tr]=Metin Düzenleyici
910Comment=Edit text files
1011Comment[af]=Redigeer tekslêers
1112Comment[am]=የጽሑፍ ፋይሎች ያስተካክሉ
12−Comment[ar]=حرّر ملفات نصية
13+Comment[ar]=مُحَرِّرُ مِلَفَّاتٍ نَصِّيَّة
1314Comment[az]=Mətn fayllarını redaktə edin
1415Comment[be]=Рэдагаваньне тэкставых файлаў
1516Comment[bg]=Редактиране на текстови файлове
@@ -79,6 +80,7 @@ Exec=hx %F
7980Terminal=true
8081Type=Application
8182Keywords=Text;editor;
83+Keywords[ar]=نص;نصوص;محرر;
8284Keywords[fr]=Texte;éditeur;
8385Keywords[ru]=текст;текстовый редактор;
8486Keywords[sr]=Текст;едитор;
docs/CONTRIBUTING.md+10−3
@@ -29,9 +29,15 @@ files, run
2929cargo xtask docgen
3030```
3131
32−inside the project. We use [xtask][xtask] as an ad-hoc task runner and
33−thus do not require any dependencies other than `cargo` (You don't have
34−to `cargo install` anything either).
32+inside the project. We use [xtask][xtask] as an ad-hoc task runner.
33+
34+To preview the book itself, install [mdbook][mdbook]. Then, run
35+
36+```shell
37+mdbook serve book
38+```
39+
40+and visit [http://localhost:3000](http://localhost:3000).
3541
3642# Testing
3743
@@ -58,4 +64,5 @@ The current MSRV and future changes to the MSRV are listed in the [Firefox docum
5864[architecture.md]: ./architecture.md
5965[docs]: https://docs.helix-editor.com/
6066[xtask]: https://github.com/matklad/cargo-xtask
67+[mdbook]: https://rust-lang.github.io/mdBook/guide/installation.html
6168[helpers.rs]: ../helix-term/tests/test/helpers.rs
docs/releases.md+12−5
@@ -1,16 +1,23 @@
11## Checklist
22
33Helix releases are versioned in the Calendar Versioning scheme:
4−`YY.0M(.MICRO)`, for example, `22.05` for May of 2022. In these instructions
5−we'll use `<tag>` as a placeholder for the tag being published.
4+`YY.0M(.MICRO)`, for example, `22.05` for May of 2022, or in a patch release,
5+`22.05.1`. In these instructions we'll use `<tag>` as a placeholder for the tag
6+being published.
67
78* Merge the changelog PR
89* 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)
910* Tag and push
1011 * `git tag -s -m "<tag>" -a <tag> && git push`
1112 * Make sure to switch to master and pull first
12−* Edit the `VERSION` file and change the date to the next planned release
13− * Releases are planned to happen every two months, so `22.05` would change to `22.07`
13+* Edit the `Cargo.toml` file and change the date in the `version` field to the next planned release
14+ * Due to Cargo having a strict requirement on SemVer with 3 or more version
15+ numbers, a `0` is required in the micro version; however, unless we are
16+ publishing a patch release after a major release, the `.0` is dropped in
17+ the user facing version.
18+ * Releases are planned to happen every two months, so `22.05.0` would change to `22.07.0`
19+ * If we are pushing a patch/bugfix release in the same month as the previous
20+ release, bump the micro version, e.g. `22.07.0` to `22.07.1`
1421* Wait for the Release CI to finish
1522 * It will automatically turn the git tag into a GitHub release when it uploads artifacts
1623* Edit the new release
@@ -57,4 +64,4 @@ versions for convenience:
5764> release. For the full log, check out the git log.
5865
5966Typically, small changes like dependencies or documentation updates, refactors,
60−or meta changes like GitHub Actions work are left out.
67+or meta changes like GitHub Actions work are left out.
flake.lock+12−35
@@ -2,23 +2,16 @@
22 "nodes": {
33 "crane": {
44 "inputs": {
5− "flake-compat": "flake-compat",
6− "flake-utils": [
7− "flake-utils"
8− ],
95 "nixpkgs": [
106 "nixpkgs"
11− ],
12− "rust-overlay": [
13− "rust-overlay"
147 ]
158 },
169 "locked": {
17− "lastModified": 1688772518,
18− "narHash": "sha256-ol7gZxwvgLnxNSZwFTDJJ49xVY5teaSvF7lzlo3YQfM=",
10+ "lastModified": 1701025348,
11+ "narHash": "sha256-42GHmYH+GF7VjwGSt+fVT1CQuNpGanJbNgVHTAZppUM=",
1912 "owner": "ipetkov",
2013 "repo": "crane",
21− "rev": "8b08e96c9af8c6e3a2b69af5a7fa168750fcf88e",
14+ "rev": "42afaeb1a0325194a7cdb526332d2cb92fddd07b",
2215 "type": "github"
2316 },
2417 "original": {
@@ -27,32 +20,16 @@
2720 "type": "github"
2821 }
2922 },
30− "flake-compat": {
31− "flake": false,
32− "locked": {
33− "lastModified": 1673956053,
34− "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
35− "owner": "edolstra",
36− "repo": "flake-compat",
37− "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
38− "type": "github"
39− },
40− "original": {
41− "owner": "edolstra",
42− "repo": "flake-compat",
43− "type": "github"
44− }
45− },
4623 "flake-utils": {
4724 "inputs": {
4825 "systems": "systems"
4926 },
5027 "locked": {
51− "lastModified": 1689068808,
52− "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=",
28+ "lastModified": 1694529238,
29+ "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
5330 "owner": "numtide",
5431 "repo": "flake-utils",
55− "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4",
32+ "rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
5633 "type": "github"
5734 },
5835 "original": {
@@ -63,11 +40,11 @@
6340 },
6441 "nixpkgs": {
6542 "locked": {
66− "lastModified": 1690272529,
67− "narHash": "sha256-MakzcKXEdv/I4qJUtq/k/eG+rVmyOZLnYNC2w1mB59Y=",
43+ "lastModified": 1700794826,
44+ "narHash": "sha256-RyJTnTNKhO0yqRpDISk03I/4A67/dp96YRxc86YOPgU=",
6845 "owner": "nixos",
6946 "repo": "nixpkgs",
70− "rev": "ef99fa5c5ed624460217c31ac4271cfb5cb2502c",
47+ "rev": "5a09cb4b393d58f9ed0d9ca1555016a8543c2ac8",
7148 "type": "github"
7249 },
7350 "original": {
@@ -95,11 +72,11 @@
9572 ]
9673 },
9774 "locked": {
98− "lastModified": 1690424156,
99− "narHash": "sha256-Bpml+L280tHTQpwpC5/BJbU4HSvEzMvW8IZ4gAXimhE=",
75+ "lastModified": 1701137803,
76+ "narHash": "sha256-0LcPAdql5IhQSUXJx3Zna0dYTgdIoYO7zUrsKgiBd04=",
10077 "owner": "oxalica",
10178 "repo": "rust-overlay",
102− "rev": "f335a0213504c7e6481c359dc1009be9cf34432c",
79+ "rev": "9dd940c967502f844eacea52a61e9596268d4f70",
10380 "type": "github"
10481 },
10582 "original": {
flake.nix+12−14
@@ -13,8 +13,6 @@
1313 };
1414 crane = {
1515 url = "github:ipetkov/crane";
16− inputs.rust-overlay.follows = "rust-overlay";
17− inputs.flake-utils.follows = "flake-utils";
1816 inputs.nixpkgs.follows = "nixpkgs";
1917 };
2018 };
@@ -123,18 +121,18 @@
123121 rustToolchain = pkgs.pkgsBuildHost.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml;
124122 craneLibMSRV = (crane.mkLib pkgs).overrideToolchain rustToolchain;
125123 craneLibStable = (crane.mkLib pkgs).overrideToolchain pkgs.pkgsBuildHost.rust-bin.stable.latest.default;
126− commonArgs =
127− {
128− inherit stdenv;
129− src = filteredSource;
130− # disable fetching and building of tree-sitter grammars in the helix-term build.rs
131− HELIX_DISABLE_AUTO_GRAMMAR_BUILD = "1";
132− buildInputs = [stdenv.cc.cc.lib];
133− # disable tests
134− doCheck = false;
135− meta.mainProgram = "hx";
136− }
137− // craneLibMSRV.crateNameFromCargoToml {cargoToml = ./helix-term/Cargo.toml;};
124+ commonArgs = {
125+ inherit stdenv;
126+ inherit (craneLibMSRV.crateNameFromCargoToml {cargoToml = ./helix-term/Cargo.toml;}) pname;
127+ inherit (craneLibMSRV.crateNameFromCargoToml {cargoToml = ./Cargo.toml;}) version;
128+ src = filteredSource;
129+ # disable fetching and building of tree-sitter grammars in the helix-term build.rs
130+ HELIX_DISABLE_AUTO_GRAMMAR_BUILD = "1";
131+ buildInputs = [stdenv.cc.cc.lib];
132+ # disable tests
133+ doCheck = false;
134+ meta.mainProgram = "hx";
135+ };
138136 cargoArtifacts = craneLibMSRV.buildDepsOnly commonArgs;
139137 in {
140138 packages = {
grammars.nix+24−21
@@ -5,6 +5,7 @@
55 runCommand,
66 yj,
77 includeGrammarIf ? _: true,
8+ grammarOverlays ? [],
89 ...
910}: let
1011 # HACK: nix < 2.6 has a bug in the toml parser, so we convert to JSON
@@ -48,22 +49,22 @@
4849 then sourceGitHub
4950 else sourceGit;
5051 in
51− stdenv.mkDerivation rec {
52+ stdenv.mkDerivation {
5253 # see https://github.com/NixOS/nixpkgs/blob/fbdd1a7c0bc29af5325e0d7dd70e804a972eb465/pkgs/development/tools/parsing/tree-sitter/grammar.nix
5354
5455 pname = "helix-tree-sitter-${grammar.name}";
5556 version = grammar.source.rev;
5657
57− src =
58− if builtins.hasAttr "subpath" grammar.source
59− then "${source}/${grammar.source.subpath}"
60− else source;
58+ src = source;
59+ sourceRoot = if builtins.hasAttr "subpath" grammar.source then
60+ "source/${grammar.source.subpath}"
61+ else
62+ "source";
6163
62− dontUnpack = true;
6364 dontConfigure = true;
6465
6566 FLAGS = [
66− "-I${src}/src"
67+ "-Isrc"
6768 "-g"
6869 "-O3"
6970 "-fPIC"
@@ -76,13 +77,13 @@
7677 buildPhase = ''
7778 runHook preBuild
7879
79− if [[ -e "$src/src/scanner.cc" ]]; then
80− $CXX -c "$src/src/scanner.cc" -o scanner.o $FLAGS
81− elif [[ -e "$src/src/scanner.c" ]]; then
82− $CC -c "$src/src/scanner.c" -o scanner.o $FLAGS
80+ if [[ -e src/scanner.cc ]]; then
81+ $CXX -c src/scanner.cc -o scanner.o $FLAGS
82+ elif [[ -e src/scanner.c ]]; then
83+ $CC -c src/scanner.c -o scanner.o $FLAGS
8384 fi
8485
85− $CC -c "$src/src/parser.c" -o parser.o $FLAGS
86+ $CC -c src/parser.c -o parser.o $FLAGS
8687 $CXX -shared -o $NAME.so *.o
8788
8889 ls -al
@@ -105,15 +106,17 @@
105106 '';
106107 };
107108 grammarsToBuild = builtins.filter includeGrammarIf gitGrammars;
108− builtGrammars =
109− builtins.map (grammar: {
110− inherit (grammar) name;
111− artifact = buildGrammar grammar;
112− })
113− grammarsToBuild;
114− grammarLinks =
115− builtins.map (grammar: "ln -s ${grammar.artifact}/${grammar.name}.so $out/${grammar.name}.so")
116− builtGrammars;
109+ builtGrammars = builtins.map (grammar: {
110+ inherit (grammar) name;
111+ value = buildGrammar grammar;
112+ }) grammarsToBuild;
113+ extensibleGrammars =
114+ lib.makeExtensible (self: builtins.listToAttrs builtGrammars);
115+ overlayedGrammars = lib.pipe extensibleGrammars
116+ (builtins.map (overlay: grammar: grammar.extend overlay) grammarOverlays);
117+ grammarLinks = lib.mapAttrsToList
118+ (name: artifact: "ln -s ${artifact}/${name}.so $out/${name}.so")
119+ (lib.filterAttrs (n: v: lib.isDerivation v) overlayedGrammars);
117120in
118121 runCommand "consolidated-helix-grammars" {} ''
119122 mkdir -p $out
helix-core/Cargo.toml+14−13
@@ -1,23 +1,24 @@
11[package]
22name = "helix-core"
3−version = "0.6.0"
4−authors = ["Blaž Hrastnik <blaz@mxxn.io>"]
5−edition = "2021"
6−license = "MPL-2.0"
73description = "Helix editor core editing primitives"
8−categories = ["editor"]
9−repository = "https://github.com/helix-editor/helix"
10−homepage = "https://helix-editor.com"
114include = ["src/**/*", "README.md"]
5+version.workspace = true
6+authors.workspace = true
7+edition.workspace = true
8+license.workspace = true
9+rust-version.workspace = true
10+categories.workspace = true
11+repository.workspace = true
12+homepage.workspace = true
1213
1314[features]
1415unicode-lines = ["ropey/unicode_lines"]
1516integration = []
1617
1718[dependencies]
18−helix-loader = { version = "0.6", path = "../helix-loader" }
19+helix-loader = { path = "../helix-loader" }
1920
20−ropey = { version = "1.6.0", default-features = false, features = ["simd"] }
21+ropey = { version = "1.6.1", default-features = false, features = ["simd"] }
2122smallvec = "1.11"
2223smartstring = "1.0.1"
2324unicode-segmentation = "1.10"
@@ -26,12 +27,12 @@ unicode-general-category = "0.6"
2627# slab = "0.4.2"
2728slotmap = "1.0"
2829tree-sitter.workspace = true
29−once_cell = "1.18"
30+once_cell = "1.19"
3031arc-swap = "1"
3132regex = "1"
3233bitflags = "2.4"
33−ahash = "0.8.3"
34−hashbrown = { version = "0.14.0", features = ["raw"] }
34+ahash = "0.8.6"
35+hashbrown = { version = "0.14.3", features = ["raw"] }
3536dunce = "1.0"
3637
3738log = "0.4"
@@ -53,4 +54,4 @@ parking_lot = "0.12"
5354
5455[dev-dependencies]
5556quickcheck = { version = "1", default-features = false }
56−indoc = "2.0.3"
57+indoc = "2.0.4"
helix-core/src/diagnostic.rs+4
@@ -39,6 +39,10 @@ pub enum DiagnosticTag {
3939#[derive(Debug, Clone)]
4040pub struct Diagnostic {
4141 pub range: Range,
42+ // whether this diagnostic ends at the end of(or inside) a word
43+ pub ends_at_word: bool,
44+ pub starts_at_word: bool,
45+ pub zero_width: bool,
4246 pub line: usize,
4347 pub message: String,
4448 pub severity: Option<Severity>,
helix-core/src/fuzzy.rs+3−3
@@ -1,6 +1,6 @@
11use std::ops::DerefMut;
22
3−use nucleo::pattern::{AtomKind, CaseMatching, Pattern};
3+use nucleo::pattern::{Atom, AtomKind, CaseMatching};
44use nucleo::Config;
55use parking_lot::Mutex;
66
@@ -32,12 +32,12 @@ pub fn fuzzy_match<T: AsRef<str>>(
3232 pattern: &str,
3333 items: impl IntoIterator<Item = T>,
3434 path: bool,
35−) -> Vec<(T, u32)> {
35+) -> Vec<(T, u16)> {
3636 let mut matcher = MATCHER.lock();
3737 matcher.config = Config::DEFAULT;
3838 if path {
3939 matcher.config.set_match_paths();
4040 }
41− let pattern = Pattern::new(pattern, CaseMatching::Smart, AtomKind::Fuzzy);
41+ let pattern = Atom::new(pattern, CaseMatching::Smart, AtomKind::Fuzzy, false);
4242 pattern.match_list(items, &mut matcher)
4343}
helix-core/src/indent.rs+316−103
@@ -4,10 +4,11 @@ use tree_sitter::{Query, QueryCursor, QueryPredicateArg};
44
55use crate::{
66 chars::{char_is_line_ending, char_is_whitespace},
7+ find_first_non_whitespace_char,
78 graphemes::{grapheme_width, tab_width_at},
8− syntax::{LanguageConfiguration, RopeProvider, Syntax},
9+ syntax::{IndentationHeuristic, LanguageConfiguration, RopeProvider, Syntax},
910 tree_sitter::Node,
10− Rope, RopeGraphemes, RopeSlice,
11+ Position, Rope, RopeGraphemes, RopeSlice,
1112};
1213
1314/// Enum representing indentation style.
@@ -21,7 +22,7 @@ pub enum IndentStyle {
2122
2223// 16 spaces
2324const INDENTS: &str = " ";
24−const MAX_INDENT: u8 = 16;
25+pub const MAX_INDENT: u8 = 16;
2526
2627impl IndentStyle {
2728 /// Creates an `IndentStyle` from an indentation string.
@@ -196,6 +197,56 @@ pub fn indent_level_for_line(line: RopeSlice, tab_width: usize, indent_width: us
196197 len / indent_width
197198}
198199
200+/// Create a string of tabs & spaces that has the same visual width as the given RopeSlice (independent of the tab width).
201+fn whitespace_with_same_width(text: RopeSlice) -> String {
202+ let mut s = String::new();
203+ for grapheme in RopeGraphemes::new(text) {
204+ if grapheme == "\t" {
205+ s.push('\t');
206+ } else {
207+ s.extend(std::iter::repeat(' ').take(grapheme_width(&Cow::from(grapheme))));
208+ }
209+ }
210+ s
211+}
212+
213+fn add_indent_level(
214+ mut base_indent: String,
215+ added_indent_level: isize,
216+ indent_style: &IndentStyle,
217+ tab_width: usize,
218+) -> String {
219+ if added_indent_level >= 0 {
220+ // Adding a non-negative indent is easy, we can simply append the indent string
221+ base_indent.push_str(&indent_style.as_str().repeat(added_indent_level as usize));
222+ base_indent
223+ } else {
224+ // In this case, we want to return a prefix of `base_indent`.
225+ // Since the width of a tab depends on its offset, we cannot simply iterate over
226+ // the chars of `base_indent` in reverse until we have the desired indent reduction,
227+ // instead we iterate over them twice in forward direction.
228+ let base_indent_rope = RopeSlice::from(base_indent.as_str());
229+ #[allow(deprecated)]
230+ let base_indent_width =
231+ crate::visual_coords_at_pos(base_indent_rope, base_indent_rope.len_chars(), tab_width)
232+ .col;
233+ let target_indent_width = base_indent_width
234+ .saturating_sub((-added_indent_level) as usize * indent_style.indent_width(tab_width));
235+ #[allow(deprecated)]
236+ let char_end_idx = crate::pos_at_visual_coords(
237+ base_indent_rope,
238+ Position {
239+ row: 0,
240+ col: target_indent_width,
241+ },
242+ tab_width,
243+ );
244+ let byte_end_idx = base_indent_rope.char_to_byte(char_end_idx);
245+ base_indent.truncate(byte_end_idx);
246+ base_indent
247+ }
248+}
249+
199250/// Computes for node and all ancestors whether they are the first node on their line.
200251/// The first entry in the return value represents the root node, the last one the node itself
201252fn get_first_in_line(mut node: Node, new_line_byte_pos: Option<usize>) -> Vec<bool> {
@@ -241,21 +292,21 @@ fn get_first_in_line(mut node: Node, new_line_byte_pos: Option<usize>) -> Vec<bo
241292/// - max(0, indent - outdent) tabs, if tabs are used for indentation
242293/// - max(0, indent - outdent)*indent_width spaces, if spaces are used for indentation
243294#[derive(Default, Debug, PartialEq, Eq, Clone)]
244−pub struct Indentation {
295+pub struct Indentation<'a> {
245296 indent: usize,
246297 indent_always: usize,
247298 outdent: usize,
248299 outdent_always: usize,
249300 /// The alignment, as a string containing only tabs & spaces. Storing this as a string instead of e.g.
250301 /// the (visual) width ensures that the alignment is preserved even if the tab width changes.
251− align: Option<String>,
302+ align: Option<RopeSlice<'a>>,
252303}
253304
254−impl Indentation {
305+impl<'a> Indentation<'a> {
255306 /// Add some other [Indentation] to this.
256307 /// The added indent should be the total added indent from one line.
257308 /// Indent should always be added starting from the bottom (or equivalently, the innermost tree-sitter node).
258− fn add_line(&mut self, added: Indentation) {
309+ fn add_line(&mut self, added: Indentation<'a>) {
259310 // Align overrides the indent from outer scopes.
260311 if self.align.is_some() {
261312 return;
@@ -271,8 +322,10 @@ impl Indentation {
271322 }
272323
273324 /// Add an indent capture to this indent.
274− /// All the captures that are added in this way should be on the same line.
275− fn add_capture(&mut self, added: IndentCaptureType) {
325+ /// Only captures that apply to the same line should be added together in this way (otherwise use `add_line`)
326+ /// and the captures should be added starting from the innermost tree-sitter node (currently this only matters
327+ /// if multiple `@align` patterns occur on the same line).
328+ fn add_capture(&mut self, added: IndentCaptureType<'a>) {
276329 match added {
277330 IndentCaptureType::Indent => {
278331 if self.indent_always == 0 {
@@ -295,47 +348,68 @@ impl Indentation {
295348 self.outdent = 0;
296349 }
297350 IndentCaptureType::Align(align) => {
298− self.align = Some(align);
351+ if self.align.is_none() {
352+ self.align = Some(align);
353+ }
299354 }
300355 }
301356 }
302− fn into_string(self, indent_style: &IndentStyle) -> String {
303− let indent = self.indent_always + self.indent;
304− let outdent = self.outdent_always + self.outdent;
305−
306− let indent_level = if indent >= outdent {
307− indent - outdent
308− } else {
309− log::warn!("Encountered more outdent than indent nodes while calculating indentation: {} outdent, {} indent", self.outdent, self.indent);
310− 0
311− };
312− let mut indent_string = if let Some(align) = self.align {
313− align
357+ fn net_indent(&self) -> isize {
358+ (self.indent + self.indent_always) as isize
359+ - ((self.outdent + self.outdent_always) as isize)
360+ }
361+ /// Convert `self` into a string, taking into account the computed and actual indentation of some other line.
362+ fn relative_indent(
363+ &self,
364+ other_computed_indent: &Self,
365+ other_leading_whitespace: RopeSlice,
366+ indent_style: &IndentStyle,
367+ tab_width: usize,
368+ ) -> Option<String> {
369+ if self.align == other_computed_indent.align {
370+ // If self and baseline are either not aligned to anything or both aligned the same way,
371+ // we can simply take `other_leading_whitespace` and add some indent / outdent to it (in the second
372+ // case, the alignment should already be accounted for in `other_leading_whitespace`).
373+ let indent_diff = self.net_indent() - other_computed_indent.net_indent();
374+ Some(add_indent_level(
375+ String::from(other_leading_whitespace),
376+ indent_diff,
377+ indent_style,
378+ tab_width,
379+ ))
314380 } else {
315− String::new()
316− };
317− indent_string.push_str(&indent_style.as_str().repeat(indent_level));
318− indent_string
381+ // If the alignment of both lines is different, we cannot compare their indentation in any meaningful way
382+ None
383+ }
384+ }
385+ pub fn to_string(&self, indent_style: &IndentStyle, tab_width: usize) -> String {
386+ add_indent_level(
387+ self.align
388+ .map_or_else(String::new, whitespace_with_same_width),
389+ self.net_indent(),
390+ indent_style,
391+ tab_width,
392+ )
319393 }
320394}
321395
322396/// An indent definition which corresponds to a capture from the indent query
323397#[derive(Debug)]
324−struct IndentCapture {
325− capture_type: IndentCaptureType,
398+struct IndentCapture<'a> {
399+ capture_type: IndentCaptureType<'a>,
326400 scope: IndentScope,
327401}
328402#[derive(Debug, Clone, PartialEq)]
329−enum IndentCaptureType {
403+enum IndentCaptureType<'a> {
330404 Indent,
331405 IndentAlways,
332406 Outdent,
333407 OutdentAlways,
334408 /// Alignment given as a string of whitespace
335− Align(String),
409+ Align(RopeSlice<'a>),
336410}
337411
338−impl IndentCaptureType {
412+impl<'a> IndentCaptureType<'a> {
339413 fn default_scope(&self) -> IndentScope {
340414 match self {
341415 IndentCaptureType::Indent | IndentCaptureType::IndentAlways => IndentScope::Tail,
@@ -367,8 +441,8 @@ enum ExtendCapture {
367441/// each node (identified by its ID) the relevant captures (already filtered
368442/// by predicates).
369443#[derive(Debug)]
370−struct IndentQueryResult {
371− indent_captures: HashMap<usize, Vec<IndentCapture>>,
444+struct IndentQueryResult<'a> {
445+ indent_captures: HashMap<usize, Vec<IndentCapture<'a>>>,
372446 extend_captures: HashMap<usize, Vec<ExtendCapture>>,
373447}
374448
@@ -389,14 +463,14 @@ fn get_node_end_line(node: Node, new_line_byte_pos: Option<usize>) -> usize {
389463 node_line
390464}
391465
392−fn query_indents(
466+fn query_indents<'a>(
393467 query: &Query,
394468 syntax: &Syntax,
395469 cursor: &mut QueryCursor,
396− text: RopeSlice,
470+ text: RopeSlice<'a>,
397471 range: std::ops::Range<usize>,
398472 new_line_byte_pos: Option<usize>,
399−) -> IndentQueryResult {
473+) -> IndentQueryResult<'a> {
400474 let mut indent_captures: HashMap<usize, Vec<IndentCapture>> = HashMap::new();
401475 let mut extend_captures: HashMap<usize, Vec<ExtendCapture>> = HashMap::new();
402476 cursor.set_byte_range(range);
@@ -484,7 +558,7 @@ fn query_indents(
484558 "outdent" => IndentCaptureType::Outdent,
485559 "outdent.always" => IndentCaptureType::OutdentAlways,
486560 // The alignment will be updated to the correct value at the end, when the anchor is known.
487− "align" => IndentCaptureType::Align(String::from("")),
561+ "align" => IndentCaptureType::Align(RopeSlice::from("")),
488562 "anchor" => {
489563 if anchor.is_some() {
490564 log::error!("Invalid indent query: Encountered more than one @anchor in the same match.")
@@ -556,22 +630,10 @@ fn query_indents(
556630 }
557631 Some(anchor) => anchor,
558632 };
559− // Create a string of tabs & spaces that should have the same width
560− // as the string that precedes the anchor (independent of the tab width).
561− let mut align = String::new();
562− for grapheme in RopeGraphemes::new(
633+ capture.capture_type = IndentCaptureType::Align(
563634 text.line(anchor.start_position().row)
564635 .byte_slice(0..anchor.start_position().column),
565− ) {
566− if grapheme == "\t" {
567− align.push('\t');
568− } else {
569− align.extend(
570− std::iter::repeat(' ').take(grapheme_width(&Cow::from(grapheme))),
571− );
572− }
573− }
574− capture.capture_type = IndentCaptureType::Align(align);
636+ );
575637 }
576638 indent_captures
577639 .entry(node_id)
@@ -657,56 +719,20 @@ fn extend_nodes<'a>(
657719 }
658720}
659721
660−/// Use the syntax tree to determine the indentation for a given position.
661−/// This can be used in 2 ways:
662−///
663−/// - To get the correct indentation for an existing line (new_line=false), not necessarily equal to the current indentation.
664−/// - In this case, pos should be inside the first tree-sitter node on that line.
665−/// In most cases, this can just be the first non-whitespace on that line.
666−/// - To get the indentation for a new line (new_line=true). This behaves like the first usecase if the part of the current line
667−/// after pos were moved to a new line.
668−///
669−/// The indentation is determined by traversing all the tree-sitter nodes containing the position.
670−/// Each of these nodes produces some [Indentation] for:
671−///
672−/// - The line of the (beginning of the) node. This is defined by the scope `all` if this is the first node on its line.
673−/// - The line after the node. This is defined by:
674−/// - The scope `tail`.
675−/// - The scope `all` if this node is not the first node on its line.
676−/// Intuitively, `all` applies to everything contained in this node while `tail` applies to everything except for the first line of the node.
677−/// The indents from different nodes for the same line are then combined.
678−/// The result [Indentation] is simply the sum of the [Indentation] for all lines.
679−///
680−/// Specifying which line exactly an [Indentation] applies to is important because indents on the same line combine differently than indents on different lines:
681−/// ```ignore
682−/// some_function(|| {
683−/// // Both the function parameters as well as the contained block should be indented.
684−/// // Because they are on the same line, this only yields one indent level
685−/// });
686−/// ```
687−///
688−/// ```ignore
689−/// some_function(
690−/// param1,
691−/// || {
692−/// // Here we get 2 indent levels because the 'parameters' and the 'block' node begin on different lines
693−/// },
694−/// );
695−/// ```
722+/// Prepare an indent query by computing:
723+/// - The node from which to start the query (this is non-trivial due to `@extend` captures)
724+/// - The indent captures for all relevant nodes.
696725#[allow(clippy::too_many_arguments)]
697−pub fn treesitter_indent_for_pos(
726+fn init_indent_query<'a, 'b>(
698727 query: &Query,
699− syntax: &Syntax,
700− indent_style: &IndentStyle,
728+ syntax: &'a Syntax,
729+ text: RopeSlice<'b>,
701730 tab_width: usize,
702731 indent_width: usize,
703− text: RopeSlice,
704732 line: usize,
705− pos: usize,
706− new_line: bool,
707−) -> Option<String> {
708− let byte_pos = text.char_to_byte(pos);
709− let new_line_byte_pos = new_line.then_some(byte_pos);
733+ byte_pos: usize,
734+ new_line_byte_pos: Option<usize>,
735+) -> Option<(Node<'a>, HashMap<usize, Vec<IndentCapture<'b>>>)> {
710736 // The innermost tree-sitter node which is considered for the indent
711737 // computation. It may change if some predeceding node is extended
712738 let mut node = syntax
@@ -750,7 +776,6 @@ pub fn treesitter_indent_for_pos(
750776 (query_result, deepest_preceding)
751777 })
752778 };
753− let mut indent_captures = query_result.indent_captures;
754779 let extend_captures = query_result.extend_captures;
755780
756781 // Check for extend captures, potentially changing the node that the indent calculation starts with
@@ -765,6 +790,68 @@ pub fn treesitter_indent_for_pos(
765790 indent_width,
766791 );
767792 }
793+ Some((node, query_result.indent_captures))
794+}
795+
796+/// Use the syntax tree to determine the indentation for a given position.
797+/// This can be used in 2 ways:
798+///
799+/// - To get the correct indentation for an existing line (new_line=false), not necessarily equal to the current indentation.
800+/// - In this case, pos should be inside the first tree-sitter node on that line.
801+/// In most cases, this can just be the first non-whitespace on that line.
802+/// - To get the indentation for a new line (new_line=true). This behaves like the first usecase if the part of the current line
803+/// after pos were moved to a new line.
804+///
805+/// The indentation is determined by traversing all the tree-sitter nodes containing the position.
806+/// Each of these nodes produces some [Indentation] for:
807+///
808+/// - The line of the (beginning of the) node. This is defined by the scope `all` if this is the first node on its line.
809+/// - The line after the node. This is defined by:
810+/// - The scope `tail`.
811+/// - The scope `all` if this node is not the first node on its line.
812+/// Intuitively, `all` applies to everything contained in this node while `tail` applies to everything except for the first line of the node.
813+/// The indents from different nodes for the same line are then combined.
814+/// The result [Indentation] is simply the sum of the [Indentation] for all lines.
815+///
816+/// Specifying which line exactly an [Indentation] applies to is important because indents on the same line combine differently than indents on different lines:
817+/// ```ignore
818+/// some_function(|| {
819+/// // Both the function parameters as well as the contained block should be indented.
820+/// // Because they are on the same line, this only yields one indent level
821+/// });
822+/// ```
823+///
824+/// ```ignore
825+/// some_function(
826+/// param1,
827+/// || {
828+/// // Here we get 2 indent levels because the 'parameters' and the 'block' node begin on different lines
829+/// },
830+/// );
831+/// ```
832+#[allow(clippy::too_many_arguments)]
833+pub fn treesitter_indent_for_pos<'a>(
834+ query: &Query,
835+ syntax: &Syntax,
836+ tab_width: usize,
837+ indent_width: usize,
838+ text: RopeSlice<'a>,
839+ line: usize,
840+ pos: usize,
841+ new_line: bool,
842+) -> Option<Indentation<'a>> {
843+ let byte_pos = text.char_to_byte(pos);
844+ let new_line_byte_pos = new_line.then_some(byte_pos);
845+ let (mut node, mut indent_captures) = init_indent_query(
846+ query,
847+ syntax,
848+ text,
849+ tab_width,
850+ indent_width,
851+ line,
852+ byte_pos,
853+ new_line_byte_pos,
854+ )?;
768855 let mut first_in_line = get_first_in_line(node, new_line.then_some(byte_pos));
769856
770857 let mut result = Indentation::default();
@@ -832,7 +919,7 @@ pub fn treesitter_indent_for_pos(
832919 break;
833920 }
834921 }
835− Some(result.into_string(indent_style))
922+ Some(result)
836923}
837924
838925/// Returns the indentation for a new line.
@@ -841,6 +928,7 @@ pub fn treesitter_indent_for_pos(
841928pub fn indent_for_newline(
842929 language_config: Option<&LanguageConfiguration>,
843930 syntax: Option<&Syntax>,
931+ indent_heuristic: &IndentationHeuristic,
844932 indent_style: &IndentStyle,
845933 tab_width: usize,
846934 text: RopeSlice,
@@ -849,14 +937,18 @@ pub fn indent_for_newline(
849937 current_line: usize,
850938) -> String {
851939 let indent_width = indent_style.indent_width(tab_width);
852− if let (Some(query), Some(syntax)) = (
940+ if let (
941+ IndentationHeuristic::TreeSitter | IndentationHeuristic::Hybrid,
942+ Some(query),
943+ Some(syntax),
944+ ) = (
945+ indent_heuristic,
853946 language_config.and_then(|config| config.indent_query()),
854947 syntax,
855948 ) {
856949 if let Some(indent) = treesitter_indent_for_pos(
857950 query,
858951 syntax,
859− indent_style,
860952 tab_width,
861953 indent_width,
862954 text,
@@ -864,9 +956,57 @@ pub fn indent_for_newline(
864956 line_before_end_pos,
865957 true,
866958 ) {
867− return indent;
959+ if *indent_heuristic == IndentationHeuristic::Hybrid {
960+ // We want to compute the indentation not only based on the
961+ // syntax tree but also on the actual indentation of a previous
962+ // line. This makes indentation computation more resilient to
963+ // incomplete queries, incomplete source code & differing indentation
964+ // styles for the same language.
965+ // However, using the indent of a previous line as a baseline may not
966+ // make sense, e.g. if it has a different alignment than the new line.
967+ // In order to prevent edge cases with long running times, we only try
968+ // a constant number of (non-empty) lines.
969+ const MAX_ATTEMPTS: usize = 4;
970+ let mut num_attempts = 0;
971+ for line_idx in (0..=line_before).rev() {
972+ let line = text.line(line_idx);
973+ let first_non_whitespace_char = match find_first_non_whitespace_char(line) {
974+ Some(i) => i,
975+ None => {
976+ continue;
977+ }
978+ };
979+ if let Some(indent) = (|| {
980+ let computed_indent = treesitter_indent_for_pos(
981+ query,
982+ syntax,
983+ tab_width,
984+ indent_width,
985+ text,
986+ line_idx,
987+ text.line_to_char(line_idx) + first_non_whitespace_char,
988+ false,
989+ )?;
990+ let leading_whitespace = line.slice(0..first_non_whitespace_char);
991+ indent.relative_indent(
992+ &computed_indent,
993+ leading_whitespace,
994+ indent_style,
995+ tab_width,
996+ )
997+ })() {
998+ return indent;
999+ }
1000+ num_attempts += 1;
1001+ if num_attempts == MAX_ATTEMPTS {
1002+ break;
1003+ }
1004+ }
1005+ }
1006+ return indent.to_string(indent_style, tab_width);
8681007 };
8691008 }
1009+ // Fallback in case we either don't have indent queries or they failed for some reason
8701010 let indent_level = indent_level_for_line(text.line(current_line), tab_width, indent_width);
8711011 indent_style.as_str().repeat(indent_level)
8721012}
@@ -958,10 +1098,13 @@ mod test {
9581098 ..Default::default()
9591099 };
9601100
961− let add_capture = |mut indent: Indentation, capture| {
1101+ fn add_capture<'a>(
1102+ mut indent: Indentation<'a>,
1103+ capture: IndentCaptureType<'a>,
1104+ ) -> Indentation<'a> {
9621105 indent.add_capture(capture);
9631106 indent
964− };
1107+ }
9651108
9661109 // adding an indent to no indent makes an indent
9671110 assert_eq!(
@@ -1056,4 +1199,74 @@ mod test {
10561199 )
10571200 );
10581201 }
1202+
1203+ #[test]
1204+ fn test_relative_indent() {
1205+ let indent_style = IndentStyle::Spaces(4);
1206+ let tab_width: usize = 4;
1207+ let no_align = [
1208+ Indentation::default(),
1209+ Indentation {
1210+ indent: 1,
1211+ ..Default::default()
1212+ },
1213+ Indentation {
1214+ indent: 5,
1215+ outdent: 1,
1216+ ..Default::default()
1217+ },
1218+ ];
1219+ let align = no_align.clone().map(|indent| Indentation {
1220+ align: Some(RopeSlice::from("12345")),
1221+ ..indent
1222+ });
1223+ let different_align = Indentation {
1224+ align: Some(RopeSlice::from("123456")),
1225+ ..Default::default()
1226+ };
1227+
1228+ // Check that relative and absolute indentation computation are the same when the line we compare to is
1229+ // indented as we expect.
1230+ let check_consistency = |indent: &Indentation, other: &Indentation| {
1231+ assert_eq!(
1232+ indent.relative_indent(
1233+ other,
1234+ RopeSlice::from(other.to_string(&indent_style, tab_width).as_str()),
1235+ &indent_style,
1236+ tab_width
1237+ ),
1238+ Some(indent.to_string(&indent_style, tab_width))
1239+ );
1240+ };
1241+ for a in &no_align {
1242+ for b in &no_align {
1243+ check_consistency(a, b);
1244+ }
1245+ }
1246+ for a in &align {
1247+ for b in &align {
1248+ check_consistency(a, b);
1249+ }
1250+ }
1251+
1252+ // Relative indent computation makes no sense if the alignment differs
1253+ assert_eq!(
1254+ align[0].relative_indent(
1255+ &no_align[0],
1256+ RopeSlice::from(" "),
1257+ &indent_style,
1258+ tab_width
1259+ ),
1260+ None
1261+ );
1262+ assert_eq!(
1263+ align[0].relative_indent(
1264+ &different_align,
1265+ RopeSlice::from(" "),
1266+ &indent_style,
1267+ tab_width
1268+ ),
1269+ None
1270+ );
1271+ }
10591272}
helix-core/src/syntax.rs+22−6
@@ -101,7 +101,8 @@ pub struct LanguageConfiguration {
101101 pub file_types: Vec<FileType>, // filename extension or ends_with? <Gemfile, rb, etc>
102102 #[serde(default)]
103103 pub shebangs: Vec<String>, // interpreter(s) associated with language
104− pub roots: Vec<String>, // these indicate project roots <.git, Cargo.toml>
104+ #[serde(default)]
105+ pub roots: Vec<String>, // these indicate project roots <.git, Cargo.toml>
105106 pub comment_token: Option<String>,
106107 pub text_width: Option<usize>,
107108 pub soft_wrap: Option<SoftWrap>,
@@ -154,6 +155,8 @@ pub struct LanguageConfiguration {
154155 /// Hardcoded LSP root directories relative to the workspace root, like `examples` or `tools/fuzz`.
155156 /// Falling back to the current working directory if none are configured.
156157 pub workspace_lsp_roots: Option<Vec<PathBuf>>,
158+ #[serde(default)]
159+ pub persistent_diagnostic_sources: Vec<String>,
157160}
158161
159162#[derive(Debug, PartialEq, Eq, Hash)]
@@ -211,10 +214,7 @@ impl<'de> Deserialize<'de> for FileType {
211214 {
212215 match map.next_entry::<String, String>()? {
213216 Some((key, suffix)) if key == "suffix" => Ok(FileType::Suffix({
214− // FIXME: use `suffix.replace('/', std::path::MAIN_SEPARATOR_STR)`
215− // if MSRV is updated to 1.68
216− let mut separator = [0; 1];
217− suffix.replace('/', std::path::MAIN_SEPARATOR.encode_utf8(&mut separator))
217+ suffix.replace('/', std::path::MAIN_SEPARATOR_STR)
218218 })),
219219 Some((key, _value)) => Err(serde::de::Error::custom(format!(
220220 "unknown key in `file-types` list: {}",
@@ -444,6 +444,22 @@ pub struct IndentationConfiguration {
444444 pub unit: String,
445445}
446446
447+/// How the indentation for a newly inserted line should be determined.
448+/// If the selected heuristic is not available (e.g. because the current
449+/// language has no tree-sitter indent queries), a simpler one will be used.
450+#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
451+#[serde(rename_all = "kebab-case")]
452+pub enum IndentationHeuristic {
453+ /// Just copy the indentation of the line that the cursor is currently on.
454+ Simple,
455+ /// Use tree-sitter indent queries to compute the expected absolute indentation level of the new line.
456+ TreeSitter,
457+ /// Use tree-sitter indent queries to compute the expected difference in indentation between the new line
458+ /// and the line before. Add this to the actual indentation level of the line before.
459+ #[default]
460+ Hybrid,
461+}
462+
447463/// Configuration for auto pairs
448464#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
449465#[serde(rename_all = "kebab-case", deny_unknown_fields, untagged)]
@@ -962,7 +978,7 @@ impl Syntax {
962978 let res = syntax.update(source, source, &ChangeSet::new(source));
963979
964980 if res.is_err() {
965− log::error!("TS parser failed, disabeling TS for the current buffer: {res:?}");
981+ log::error!("TS parser failed, disabling TS for the current buffer: {res:?}");
966982 return None;
967983 }
968984 Some(syntax)
helix-core/src/transaction.rs+73−14
@@ -1,7 +1,7 @@
11use ropey::RopeSlice;
22use smallvec::SmallVec;
33
4−use crate::{Range, Rope, Selection, Tendril};
4+use crate::{chars::char_is_word, Range, Rope, Selection, Tendril};
55use std::{borrow::Cow, iter::once};
66
77/// (from, to, replacement)
@@ -23,6 +23,30 @@ pub enum Operation {
2323pub enum Assoc {
2424 Before,
2525 After,
26+ /// Acts like `After` if a word character is inserted
27+ /// after the position, otherwise acts like `Before`
28+ AfterWord,
29+ /// Acts like `Before` if a word character is inserted
30+ /// before the position, otherwise acts like `After`
31+ BeforeWord,
32+}
33+
34+impl Assoc {
35+ /// Whether to stick to gaps
36+ fn stay_at_gaps(self) -> bool {
37+ !matches!(self, Self::BeforeWord | Self::AfterWord)
38+ }
39+
40+ fn insert_offset(self, s: &str) -> usize {
41+ let chars = s.chars().count();
42+ match self {
43+ Assoc::After => chars,
44+ Assoc::AfterWord => s.chars().take_while(|&c| char_is_word(c)).count(),
45+ // return position before inserted text
46+ Assoc::Before => 0,
47+ Assoc::BeforeWord => chars - s.chars().rev().take_while(|&c| char_is_word(c)).count(),
48+ }
49+ }
2650}
2751
2852#[derive(Debug, Default, Clone, PartialEq, Eq)]
@@ -415,8 +439,6 @@ impl ChangeSet {
415439 map!(|pos, _| (old_end > pos).then_some(new_pos), i);
416440 }
417441 Insert(s) => {
418− let ins = s.chars().count();
419−
420442 // a subsequent delete means a replace, consume it
421443 if let Some((_, Delete(len))) = iter.peek() {
422444 iter.next();
@@ -424,13 +446,13 @@ impl ChangeSet {
424446 old_end = old_pos + len;
425447 // in range of replaced text
426448 map!(
427− |pos, assoc| (old_end > pos).then(|| {
449+ |pos, assoc: Assoc| (old_end > pos).then(|| {
428450 // at point or tracking before
429− if pos == old_pos || assoc == Assoc::Before {
451+ if pos == old_pos && assoc.stay_at_gaps() {
430452 new_pos
431453 } else {
432454 // place to end of insert
433− new_pos + ins
455+ new_pos + assoc.insert_offset(s)
434456 }
435457 }),
436458 i
@@ -438,20 +460,15 @@ impl ChangeSet {
438460 } else {
439461 // at insert point
440462 map!(
441− |pos, assoc| (old_pos == pos).then(|| {
463+ |pos, assoc: Assoc| (old_pos == pos).then(|| {
442464 // return position before inserted text
443− if assoc == Assoc::Before {
444− new_pos
445− } else {
446− // after text
447− new_pos + ins
448− }
465+ new_pos + assoc.insert_offset(s)
449466 }),
450467 i
451468 );
452469 }
453470
454− new_pos += ins;
471+ new_pos += s.chars().count();
455472 }
456473 }
457474 old_pos = old_end;
@@ -884,6 +901,48 @@ mod test {
884901 let mut positions = [4, 2];
885902 cs.update_positions(positions.iter_mut().map(|pos| (pos, Assoc::After)));
886903 assert_eq!(positions, [4, 2]);
904+ // stays at word boundary
905+ let cs = ChangeSet {
906+ changes: vec![
907+ Retain(2), // <space><space>
908+ Insert(" ab".into()),
909+ Retain(2), // cd
910+ Insert("de ".into()),
911+ ],
912+ len: 4,
913+ len_after: 10,
914+ };
915+ assert_eq!(cs.map_pos(2, Assoc::BeforeWord), 3);
916+ assert_eq!(cs.map_pos(4, Assoc::AfterWord), 9);
917+ let cs = ChangeSet {
918+ changes: vec![
919+ Retain(1), // <space>
920+ Insert(" b".into()),
921+ Delete(1), // c
922+ Retain(1), // d
923+ Insert("e ".into()),
924+ Delete(1), // <space>
925+ ],
926+ len: 5,
927+ len_after: 7,
928+ };
929+ assert_eq!(cs.map_pos(1, Assoc::BeforeWord), 2);
930+ assert_eq!(cs.map_pos(3, Assoc::AfterWord), 5);
931+ let cs = ChangeSet {
932+ changes: vec![
933+ Retain(1), // <space>
934+ Insert("a".into()),
935+ Delete(2), // <space>b
936+ Retain(1), // d
937+ Insert("e".into()),
938+ Delete(1), // f
939+ Retain(1), // <space>
940+ ],
941+ len: 5,
942+ len_after: 7,
943+ };
944+ assert_eq!(cs.map_pos(2, Assoc::BeforeWord), 1);
945+ assert_eq!(cs.map_pos(4, Assoc::AfterWord), 4);
887946 }
888947
889948 #[test]
helix-core/src/wrap.rs+3−1
@@ -1,7 +1,9 @@
11use smartstring::{LazyCompact, SmartString};
2+use textwrap::{Options, WordSplitter::NoHyphenation};
23
34/// Given a slice of text, return the text re-wrapped to fit it
45/// within the given width.
56pub fn reflow_hard_wrap(text: &str, text_width: usize) -> SmartString<LazyCompact> {
6− textwrap::refill(text, text_width).into()
7+ let options = Options::new(text_width).word_splitter(NoHyphenation);
8+ textwrap::refill(text, options).into()
79}
helix-core/tests/indent.rs+2−2
@@ -210,7 +210,6 @@ fn test_treesitter_indent(
210210 let suggested_indent = treesitter_indent_for_pos(
211211 indent_query,
212212 &syntax,
213− &indent_style,
214213 tab_width,
215214 indent_style.indent_width(tab_width),
216215 text,
@@ -218,7 +217,8 @@ fn test_treesitter_indent(
218217 text.line_to_char(i) + pos,
219218 false,
220219 )
221− .unwrap();
220+ .unwrap()
221+ .to_string(&indent_style, tab_width);
222222 assert!(
223223 line.get_slice(..pos).map_or(false, |s| s == suggested_indent),
224224 "Wrong indentation for file {:?} on line {}:\n\"{}\" (original line)\n\"{}\" (suggested indentation)\n",
helix-dap/Cargo.toml+11−9
@@ -1,25 +1,27 @@
11[package]
22name = "helix-dap"
3−version = "0.6.0"
4−authors = ["Blaž Hrastnik <blaz@mxxn.io>"]
5−edition = "2018"
6−license = "MPL-2.0"
73description = "DAP client implementation for Helix project"
8−categories = ["editor"]
9−repository = "https://github.com/helix-editor/helix"
10−homepage = "https://helix-editor.com"
4+version.workspace = true
5+authors.workspace = true
6+edition.workspace = true
7+license.workspace = true
8+rust-version.workspace = true
9+categories.workspace = true
10+repository.workspace = true
11+homepage.workspace = true
1112
1213# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1314
1415[dependencies]
15−helix-core = { version = "0.6", path = "../helix-core" }
16+helix-core = { path = "../helix-core" }
17+
1618anyhow = "1.0"
1719log = "0.4"
1820serde = { version = "1.0", features = ["derive"] }
1921serde_json = "1.0"
2022thiserror = "1.0"
2123tokio = { version = "1", features = ["rt", "rt-multi-thread", "io-util", "io-std", "time", "process", "macros", "fs", "parking_lot", "net", "sync"] }
22−which = "4.4"
24+which = "5.0.0"
2325
2426[dev-dependencies]
2527fern = "0.6"
helix-event/Cargo.toml+8−7
@@ -1,12 +1,13 @@
11[package]
22name = "helix-event"
3−version = "0.6.0"
4−authors = ["Blaž Hrastnik <blaz@mxxn.io>"]
5−edition = "2021"
6−license = "MPL-2.0"
7−categories = ["editor"]
8−repository = "https://github.com/helix-editor/helix"
9−homepage = "https://helix-editor.com"
3+version.workspace = true
4+authors.workspace = true
5+edition.workspace = true
6+license.workspace = true
7+rust-version.workspace = true
8+categories.workspace = true
9+repository.workspace = true
10+homepage.workspace = true
1011
1112# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1213
helix-loader/Cargo.toml+12−11
@@ -1,13 +1,14 @@
11[package]
22name = "helix-loader"
3−version = "0.6.0"
4−description = "A post-modern text editor."
5−authors = ["Blaž Hrastnik <blaz@mxxn.io>"]
6−edition = "2021"
7−license = "MPL-2.0"
8−categories = ["editor"]
9−repository = "https://github.com/helix-editor/helix"
10−homepage = "https://helix-editor.com"
3+description = "Build bootstrapping for Helix crates"
4+version.workspace = true
5+authors.workspace = true
6+edition.workspace = true
7+license.workspace = true
8+rust-version.workspace = true
9+categories.workspace = true
10+repository.workspace = true
11+homepage.workspace = true
1112
1213[[bin]]
1314name = "hx-loader"
@@ -19,16 +20,16 @@ serde = { version = "1.0", features = ["derive"] }
1920toml = "0.7"
2021etcetera = "0.8"
2122tree-sitter.workspace = true
22−once_cell = "1.18"
23+once_cell = "1.19"
2324log = "0.4"
24−which = "4.4"
25+which = "5.0.0"
2526
2627# TODO: these two should be on !wasm32 only
2728
2829# cloning/compiling tree-sitter grammars
2930cc = { version = "1" }
3031threadpool = { version = "1.0" }
31−tempfile = "3.8.0"
32+tempfile = "3.8.1"
3233dunce = "1.0.4"
3334
3435[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
helix-loader/build.rs+14−4
@@ -2,7 +2,17 @@ use std::borrow::Cow;
22use std::path::Path;
33use std::process::Command;
44
5−const VERSION: &str = include_str!("../VERSION");
5+const MAJOR: &str = env!("CARGO_PKG_VERSION_MAJOR");
6+const MINOR: &str = env!("CARGO_PKG_VERSION_MINOR");
7+const PATCH: &str = env!("CARGO_PKG_VERSION_PATCH");
8+
9+fn get_calver() -> String {
10+ if PATCH == "0" {
11+ format!("{MAJOR}.{MINOR}")
12+ } else {
13+ format!("{MAJOR}.{MINOR}.{PATCH}")
14+ }
15+}
616
717fn main() {
818 let git_hash = Command::new("git")
@@ -12,9 +22,10 @@ fn main() {
1222 .filter(|output| output.status.success())
1323 .and_then(|x| String::from_utf8(x.stdout).ok());
1424
25+ let calver = get_calver();
1526 let version: Cow<_> = match &git_hash {
16− Some(git_hash) => format!("{} ({})", VERSION, &git_hash[..8]).into(),
17− None => VERSION.into(),
27+ Some(git_hash) => format!("{} ({})", calver, &git_hash[..8]).into(),
28+ None => calver.into(),
1829 };
1930
2031 println!(
@@ -22,7 +33,6 @@ fn main() {
2233 std::env::var("TARGET").unwrap()
2334 );
2435
25− println!("cargo:rerun-if-changed=../VERSION");
2636 println!("cargo:rustc-env=VERSION_AND_GIT_HASH={}", version);
2737
2838 if git_hash.is_none() {
helix-loader/src/lib.rs+13−4
@@ -33,9 +33,9 @@ pub fn current_working_dir() -> PathBuf {
3333 path
3434}
3535
36−pub fn set_current_working_dir(path: PathBuf) -> std::io::Result<()> {
36+pub fn set_current_working_dir(path: impl AsRef<Path>) -> std::io::Result<()> {
3737 let path = dunce::canonicalize(path)?;
38− std::env::set_current_dir(path.clone())?;
38+ std::env::set_current_dir(&path)?;
3939 let mut cwd = CWD.write().unwrap();
4040 *cwd = Some(path);
4141 Ok(())
@@ -60,7 +60,8 @@ pub fn initialize_log_file(specified_file: Option<PathBuf>) {
6060/// 1. sibling directory to `CARGO_MANIFEST_DIR` (if environment variable is set)
6161/// 2. subdirectory of user config directory (always included)
6262/// 3. `HELIX_RUNTIME` (if environment variable is set)
63−/// 4. subdirectory of path to helix executable (always included)
63+/// 4. `HELIX_DEFAULT_RUNTIME` (if environment variable is set *at build time*)
64+/// 5. subdirectory of path to helix executable (always included)
6465///
6566/// Postcondition: returns at least two paths (they might not exist).
6667fn prioritize_runtime_dirs() -> Vec<PathBuf> {
@@ -81,6 +82,14 @@ fn prioritize_runtime_dirs() -> Vec<PathBuf> {
8182 rt_dirs.push(dir.into());
8283 }
8384
85+ // If this variable is set during build time, it will always be included
86+ // in the lookup list. This allows downstream packagers to set a fallback
87+ // directory to a location that is conventional on their distro so that they
88+ // need not resort to a wrapper script or a global environment variable.
89+ if let Some(dir) = std::option_env!("HELIX_DEFAULT_RUNTIME") {
90+ rt_dirs.push(dir.into());
91+ }
92+
8493 // fallback to location of the executable being run
8594 // canonicalize the path in case the executable is symlinked
8695 let exe_rt_dir = std::env::current_exe()
@@ -280,7 +289,7 @@ mod merge_toml_tests {
280289 let cwd = current_working_dir();
281290 assert_ne!(cwd, new_path);
282291
283− set_current_working_dir(new_path.clone()).expect("Couldn't set new path");
292+ set_current_working_dir(&new_path).expect("Couldn't set new path");
284293
285294 let cwd = current_working_dir();
286295 assert_eq!(cwd, new_path);
helix-lsp/Cargo.toml+15−14
@@ -1,31 +1,32 @@
11[package]
22name = "helix-lsp"
3−version = "0.6.0"
4−authors = ["Blaž Hrastnik <blaz@mxxn.io>"]
5−edition = "2021"
6−license = "MPL-2.0"
73description = "LSP client implementation for Helix project"
8−categories = ["editor"]
9−repository = "https://github.com/helix-editor/helix"
10−homepage = "https://helix-editor.com"
4+version.workspace = true
5+authors.workspace = true
6+edition.workspace = true
7+license.workspace = true
8+rust-version.workspace = true
9+categories.workspace = true
10+repository.workspace = true
11+homepage.workspace = true
1112
1213# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1314
1415[dependencies]
15−helix-core = { version = "0.6", path = "../helix-core" }
16−helix-loader = { version = "0.6", path = "../helix-loader" }
17−helix-parsec = { version = "0.6", path = "../helix-parsec" }
16+helix-core = { path = "../helix-core" }
17+helix-loader = { path = "../helix-loader" }
18+helix-parsec = { path = "../helix-parsec" }
1819
1920anyhow = "1.0"
2021futures-executor = "0.3"
2122futures-util = { version = "0.3", features = ["std", "async-await"], default-features = false }
22−globset = "0.4.13"
23+globset = "0.4.14"
2324log = "0.4"
24−lsp-types = { version = "0.94" }
25+lsp-types = { version = "0.95" }
2526serde = { version = "1.0", features = ["derive"] }
2627serde_json = "1.0"
2728thiserror = "1.0"
28−tokio = { version = "1.32", features = ["rt", "rt-multi-thread", "io-util", "io-std", "time", "process", "macros", "fs", "parking_lot", "sync"] }
29+tokio = { version = "1.35", features = ["rt", "rt-multi-thread", "io-util", "io-std", "time", "process", "macros", "fs", "parking_lot", "sync"] }
2930tokio-stream = "0.1.14"
30−which = "4.4"
31+which = "5.0.0"
3132parking_lot = "0.12.1"
helix-lsp/src/client.rs+87−13
@@ -401,12 +401,22 @@ impl Client {
401401 &self,
402402 params: R::Params,
403403 ) -> impl Future<Output = Result<Value>>
404+ where
405+ R::Params: serde::Serialize,
406+ {
407+ self.call_with_timeout::<R>(params, self.req_timeout)
408+ }
409+
410+ fn call_with_timeout<R: lsp::request::Request>(
411+ &self,
412+ params: R::Params,
413+ timeout_secs: u64,
414+ ) -> impl Future<Output = Result<Value>>
404415 where
405416 R::Params: serde::Serialize,
406417 {
407418 let server_tx = self.server_tx.clone();
408419 let id = self.next_request_id();
409− let timeout_secs = self.req_timeout;
410420
411421 async move {
412422 use std::time::Duration;
@@ -548,6 +558,11 @@ impl Client {
548558 dynamic_registration: Some(true),
549559 relative_pattern_support: Some(false),
550560 }),
561+ file_operations: Some(lsp::WorkspaceFileOperationsClientCapabilities {
562+ will_rename: Some(true),
563+ did_rename: Some(true),
564+ ..Default::default()
565+ }),
551566 ..Default::default()
552567 }),
553568 text_document: Some(lsp::TextDocumentClientCapabilities {
@@ -652,6 +667,7 @@ impl Client {
652667 version: Some(String::from(VERSION_AND_GIT_HASH)),
653668 }),
654669 locale: None, // TODO
670+ work_done_progress_params: lsp::WorkDoneProgressParams::default(),
655671 };
656672
657673 self.request::<lsp::request::Initialize>(params).await
@@ -700,6 +716,65 @@ impl Client {
700716 })
701717 }
702718
719+ pub fn prepare_file_rename(
720+ &self,
721+ old_uri: &lsp::Url,
722+ new_uri: &lsp::Url,
723+ ) -> Option<impl Future<Output = Result<lsp::WorkspaceEdit>>> {
724+ let capabilities = self.capabilities.get().unwrap();
725+
726+ // Return early if the server does not support willRename feature
727+ match &capabilities.workspace {
728+ Some(workspace) => match &workspace.file_operations {
729+ Some(op) => {
730+ op.will_rename.as_ref()?;
731+ }
732+ _ => return None,
733+ },
734+ _ => return None,
735+ }
736+
737+ let files = vec![lsp::FileRename {
738+ old_uri: old_uri.to_string(),
739+ new_uri: new_uri.to_string(),
740+ }];
741+ let request = self.call_with_timeout::<lsp::request::WillRenameFiles>(
742+ lsp::RenameFilesParams { files },
743+ 5,
744+ );
745+
746+ Some(async move {
747+ let json = request.await?;
748+ let response: Option<lsp::WorkspaceEdit> = serde_json::from_value(json)?;
749+ Ok(response.unwrap_or_default())
750+ })
751+ }
752+
753+ pub fn did_file_rename(
754+ &self,
755+ old_uri: &lsp::Url,
756+ new_uri: &lsp::Url,
757+ ) -> Option<impl Future<Output = std::result::Result<(), Error>>> {
758+ let capabilities = self.capabilities.get().unwrap();
759+
760+ // Return early if the server does not support DidRename feature
761+ match &capabilities.workspace {
762+ Some(workspace) => match &workspace.file_operations {
763+ Some(op) => {
764+ op.did_rename.as_ref()?;
765+ }
766+ _ => return None,
767+ },
768+ _ => return None,
769+ }
770+
771+ let files = vec![lsp::FileRename {
772+ old_uri: old_uri.to_string(),
773+ new_uri: new_uri.to_string(),
774+ }];
775+ Some(self.notify::<lsp::notification::DidRenameFiles>(lsp::RenameFilesParams { files }))
776+ }
777+
703778 // -------------------------------------------------------------------------------------------
704779 // Text document
705780 // -------------------------------------------------------------------------------------------
@@ -895,20 +970,19 @@ impl Client {
895970 ) -> Option<impl Future<Output = Result<()>>> {
896971 let capabilities = self.capabilities.get().unwrap();
897972
898− let include_text = match &capabilities.text_document_sync {
899− Some(lsp::TextDocumentSyncCapability::Options(lsp::TextDocumentSyncOptions {
900− save: Some(options),
973+ let include_text = match &capabilities.text_document_sync.as_ref()? {
974+ lsp::TextDocumentSyncCapability::Options(lsp::TextDocumentSyncOptions {
975+ save: options,
901976 ..
902− })) => match options {
977+ }) => match options.as_ref()? {
903978 lsp::TextDocumentSyncSaveOptions::Supported(true) => false,
904979 lsp::TextDocumentSyncSaveOptions::SaveOptions(lsp_types::SaveOptions {
905980 include_text,
906981 }) => include_text.unwrap_or(false),
907− // Supported(false)
908− _ => return None,
982+ lsp::TextDocumentSyncSaveOptions::Supported(false) => return None,
909983 },
910− // unsupported
911− _ => return None,
984+ // see: https://github.com/microsoft/language-server-protocol/issues/288
985+ lsp::TextDocumentSyncCapability::Kind(..) => false,
912986 };
913987
914988 Some(self.notify::<lsp::notification::DidSaveTextDocument>(
@@ -971,12 +1045,12 @@ impl Client {
9711045 ) -> Option<impl Future<Output = Result<Value>>> {
9721046 let capabilities = self.capabilities.get().unwrap();
9731047
974− // Return early if the server does not support resolving code action.
975− match capabilities.completion_provider {
976− Some(lsp::CompletionOptions {
1048+ // Return early if the server does not support resolving code actions.
1049+ match capabilities.code_action_provider {
1050+ Some(lsp::CodeActionProviderCapability::Options(lsp::CodeActionOptions {
9771051 resolve_provider: Some(true),
9781052 ..
979− }) => (),
1053+ })) => (),
9801054 _ => return None,
9811055 }
9821056
helix-lsp/src/lib.rs+32−28
@@ -445,36 +445,36 @@ pub mod util {
445445 // the tabstop closest to the range simply replaces `head` while anchor remains in place
446446 // the remaining tabstops receive their own single-width cursor
447447 if range.head < range.anchor {
448− let first_tabstop = tabstop_anchor + tabstops[0].1;
448+ let last_idx = tabstops.len() - 1;
449+ let last_tabstop = tabstop_anchor + tabstops[last_idx].0;
449450
450451 // if selection is forward but was moved to the right it is
451452 // contained entirely in the replacement text, just do a point
452453 // selection (fallback below)
453− if range.anchor >= first_tabstop {
454− let range = Range::new(range.anchor, first_tabstop);
454+ if range.anchor > last_tabstop {
455+ let range = Range::new(range.anchor, last_tabstop);
455456 mapped_selection.push(range);
456− let rem_tabstops = tabstops[1..]
457+ let rem_tabstops = tabstops[..last_idx]
457458 .iter()
458− .map(|tabstop| Range::point(tabstop_anchor + tabstop.1));
459+ .map(|tabstop| Range::point(tabstop_anchor + tabstop.0));
459460 mapped_selection.extend(rem_tabstops);
460461 continue;
461462 }
462463 } else {
463− let last_idx = tabstops.len() - 1;
464− let last_tabstop = tabstop_anchor + tabstops[last_idx].1;
464+ let first_tabstop = tabstop_anchor + tabstops[0].0;
465465
466466 // if selection is forward but was moved to the right it is
467467 // contained entirely in the replacement text, just do a point
468468 // selection (fallback below)
469− if range.anchor <= last_tabstop {
469+ if range.anchor < first_tabstop {
470470 // we can't properly compute the the next grapheme
471471 // here because the transaction hasn't been applied yet
472472 // that is not a problem because the range gets grapheme aligned anyway
473473 // tough so just adding one will always cause head to be grapheme
474474 // aligned correctly when applied to the document
475− let range = Range::new(range.anchor, last_tabstop + 1);
475+ let range = Range::new(range.anchor, first_tabstop + 1);
476476 mapped_selection.push(range);
477− let rem_tabstops = tabstops[..last_idx]
477+ let rem_tabstops = tabstops[1..]
478478 .iter()
479479 .map(|tabstop| Range::point(tabstop_anchor + tabstop.0));
480480 mapped_selection.extend(rem_tabstops);
@@ -749,36 +749,40 @@ impl Registry {
749749 }
750750 }
751751
752− pub fn get(
753− &mut self,
754− language_config: &LanguageConfiguration,
755− doc_path: Option<&std::path::PathBuf>,
756− root_dirs: &[PathBuf],
752+ pub fn get<'a>(
753+ &'a mut self,
754+ language_config: &'a LanguageConfiguration,
755+ doc_path: Option<&'a std::path::PathBuf>,
756+ root_dirs: &'a [PathBuf],
757757 enable_snippets: bool,
758− ) -> Result<HashMap<LanguageServerName, Arc<Client>>> {
759− language_config
760− .language_servers
761− .iter()
762− .map(|LanguageServerFeatures { name, .. }| {
758+ ) -> impl Iterator<Item = (LanguageServerName, Result<Arc<Client>>)> + 'a {
759+ language_config.language_servers.iter().map(
760+ move |LanguageServerFeatures { name, .. }| {
763761 if let Some(clients) = self.inner.get(name) {
764762 if let Some((_, client)) = clients.iter().enumerate().find(|(i, client)| {
765763 client.try_add_doc(&language_config.roots, root_dirs, doc_path, *i == 0)
766764 }) {
767− return Ok((name.to_owned(), client.clone()));
765+ return (name.to_owned(), Ok(client.clone()));
768766 }
769767 }
770− let client = self.start_client(
768+ match self.start_client(
771769 name.clone(),
772770 language_config,
773771 doc_path,
774772 root_dirs,
775773 enable_snippets,
776− )?;
777− let clients = self.inner.entry(name.clone()).or_default();
778− clients.push(client.clone());
779− Ok((name.clone(), client))
780− })
781− .collect()
774+ ) {
775+ Ok(client) => {
776+ self.inner
777+ .entry(name.to_owned())
778+ .or_default()
779+ .push(client.clone());
780+ (name.clone(), Ok(client))
781+ }
782+ Err(err) => (name.to_owned(), Err(err)),
783+ }
784+ },
785+ )
782786 }
783787
784788 pub fn iter_clients(&self) -> impl Iterator<Item = &Arc<Client>> {
helix-parsec/Cargo.toml+8−7
@@ -1,13 +1,14 @@
11[package]
22name = "helix-parsec"
3−version = "0.6.0"
4−authors = ["Blaž Hrastnik <blaz@mxxn.io>"]
5−edition = "2021"
6−license = "MPL-2.0"
73description = "Parser combinators for Helix"
8−categories = ["editor"]
9−repository = "https://github.com/helix-editor/helix"
10−homepage = "https://helix-editor.com"
114include = ["src/**/*", "README.md"]
5+version.workspace = true
6+authors.workspace = true
7+edition.workspace = true
8+license.workspace = true
9+rust-version.workspace = true
10+categories.workspace = true
11+repository.workspace = true
12+homepage.workspace = true
1213
1314[dependencies]
helix-term/Cargo.toml+27−23
@@ -1,16 +1,16 @@
11[package]
22name = "helix-term"
3−version = "0.6.0"
43description = "A post-modern text editor."
5−authors = ["Blaž Hrastnik <blaz@mxxn.io>"]
6−edition = "2021"
7−license = "MPL-2.0"
8−categories = ["editor", "command-line-utilities"]
9−repository = "https://github.com/helix-editor/helix"
10−homepage = "https://helix-editor.com"
114include = ["src/**/*", "README.md"]
125default-run = "hx"
13−rust-version = "1.65"
6+version.workspace = true
7+authors.workspace = true
8+edition.workspace = true
9+license.workspace = true
10+rust-version.workspace = true
11+categories.workspace = true
12+repository.workspace = true
13+homepage.workspace = true
1414
1515[features]
1616default = ["git"]
@@ -23,18 +23,18 @@ name = "hx"
2323path = "src/main.rs"
2424
2525[dependencies]
26−helix-core = { version = "0.6", path = "../helix-core" }
27−helix-event = { version = "0.6", path = "../helix-event" }
28−helix-view = { version = "0.6", path = "../helix-view" }
29−helix-lsp = { version = "0.6", path = "../helix-lsp" }
30−helix-dap = { version = "0.6", path = "../helix-dap" }
31−helix-vcs = { version = "0.6", path = "../helix-vcs" }
32−helix-loader = { version = "0.6", path = "../helix-loader" }
26+helix-core = { path = "../helix-core" }
27+helix-event = { path = "../helix-event" }
28+helix-view = { path = "../helix-view" }
29+helix-lsp = { path = "../helix-lsp" }
30+helix-dap = { path = "../helix-dap" }
31+helix-vcs = { path = "../helix-vcs" }
32+helix-loader = { path = "../helix-loader" }
3333
3434anyhow = "1"
35−once_cell = "1.18"
35+once_cell = "1.19"
3636
37−which = "4.4"
37+which = "5.0.0"
3838
3939tokio = { version = "1", features = ["rt", "rt-multi-thread", "io-util", "io-std", "time", "process", "macros", "fs", "parking_lot"] }
4040tui = { path = "../helix-tui", package = "helix-tui", default-features = false, features = ["crossterm"] }
@@ -57,6 +57,10 @@ pulldown-cmark = { version = "0.9", default-features = false }
5757# file type detection
5858content_inspector = "0.2.4"
5959
60+# opening URLs
61+open = "5.0.1"
62+url = "2.5.0"
63+
6064# config
6165toml = "0.7"
6266
@@ -64,20 +68,20 @@ serde_json = "1.0"
6468serde = { version = "1.0", features = ["derive"] }
6569
6670# ripgrep for global search
67−grep-regex = "0.1.11"
68−grep-searcher = "0.1.11"
71+grep-regex = "0.1.12"
72+grep-searcher = "0.1.13"
6973
7074[target.'cfg(not(windows))'.dependencies] # https://github.com/vorner/signal-hook/issues/100
7175signal-hook-tokio = { version = "0.3", features = ["futures-v0_3"] }
72−libc = "0.2.147"
76+libc = "0.2.151"
7377
7478[target.'cfg(target_os = "macos")'.dependencies]
7579crossterm = { version = "0.27", features = ["event-stream", "use-dev-tty"] }
7680
7781[build-dependencies]
78−helix-loader = { version = "0.6", path = "../helix-loader" }
82+helix-loader = { path = "../helix-loader" }
7983
8084[dev-dependencies]
8185smallvec = "1.11"
82−indoc = "2.0.3"
83−tempfile = "3.8.0"
86+indoc = "2.0.4"
87+tempfile = "3.8.1"
helix-term/src/application.rs+100−47
@@ -1,6 +1,7 @@
11use arc_swap::{access::Map, ArcSwap};
22use futures_util::Stream;
33use helix_core::{
4+ chars::char_is_word,
45 diagnostic::{DiagnosticTag, NumberOrString},
56 path::get_relative_path,
67 pos_at_coords, syntax, Selection,
@@ -162,15 +163,19 @@ impl Application {
162163 // Unset path to prevent accidentally saving to the original tutor file.
163164 doc_mut!(editor).set_path(None);
164165 } else if !args.files.is_empty() {
165− let first = &args.files[0].0; // we know it's not empty
166− if first.is_dir() {
167− helix_loader::set_current_working_dir(first.clone())?;
168− editor.new_file(Action::VerticalSplit);
169− let picker = ui::file_picker(".".into(), &config.load().editor);
166+ let mut files_it = args.files.into_iter().peekable();
167+
168+ // If the first file is a directory, skip it and open a picker
169+ if let Some((first, _)) = files_it.next_if(|(p, _)| p.is_dir()) {
170+ let picker = ui::file_picker(first, &config.load().editor);
170171 compositor.push(Box::new(overlaid(picker)));
171− } else {
172− let nr_of_files = args.files.len();
173− for (i, (file, pos)) in args.files.into_iter().enumerate() {
172+ }
173+
174+ // If there are any more files specified, open them
175+ if files_it.peek().is_some() {
176+ let mut nr_of_files = 0;
177+ for (file, pos) in files_it {
178+ nr_of_files += 1;
174179 if file.is_dir() {
175180 return Err(anyhow::anyhow!(
176181 "expected a path to file, found a directory. (to open a directory pass it as first argument)"
@@ -182,7 +187,7 @@ impl Application {
182187 // option. If neither of those two arguments are passed
183188 // in, just load the files normally.
184189 let action = match args.split {
185− _ if i == 0 => Action::VerticalSplit,
190+ _ if nr_of_files == 1 => Action::VerticalSplit,
186191 Some(Layout::Vertical) => Action::VerticalSplit,
187192 Some(Layout::Horizontal) => Action::HorizontalSplit,
188193 None => Action::Load,
@@ -209,6 +214,8 @@ impl Application {
209214 // does not affect views without pos since it is at the top
210215 let (view, doc) = current!(editor);
211216 align_view(doc, view, Align::Center);
217+ } else {
218+ editor.new_file(Action::VerticalSplit);
212219 }
213220 } else if stdin().is_tty() || cfg!(feature = "integration") {
214221 editor.new_file(Action::VerticalSplit);
@@ -251,6 +258,11 @@ impl Application {
251258 }
252259
253260 async fn render(&mut self) {
261+ if self.compositor.full_redraw {
262+ self.terminal.clear().expect("Cannot clear the terminal");
263+ self.compositor.full_redraw = false;
264+ }
265+
254266 let mut cx = crate::compositor::Context {
255267 editor: &mut self.editor,
256268 jobs: &mut self.jobs,
@@ -706,7 +718,7 @@ impl Application {
706718 ));
707719 }
708720 }
709− Notification::PublishDiagnostics(params) => {
721+ Notification::PublishDiagnostics(mut params) => {
710722 let path = match params.uri.to_file_path() {
711723 Ok(path) => path,
712724 Err(_) => {
@@ -720,31 +732,69 @@ impl Application {
720732 return;
721733 }
722734 let offset_encoding = language_server.offset_encoding();
723− let doc = self.editor.document_by_path_mut(&path).filter(|doc| {
724− if let Some(version) = params.version {
725− if version != doc.version() {
726− log::info!("Version ({version}) is out of date for {path:?} (expected ({}), dropping PublishDiagnostic notification", doc.version());
727− return false;
735+ // have to inline the function because of borrow checking...
736+ let doc = self.editor.documents.values_mut()
737+ .find(|doc| doc.path().map(|p| p == &path).unwrap_or(false))
738+ .filter(|doc| {
739+ if let Some(version) = params.version {
740+ if version != doc.version() {
741+ log::info!("Version ({version}) is out of date for {path:?} (expected ({}), dropping PublishDiagnostic notification", doc.version());
742+ return false;
743+ }
728744 }
729− }
730−
731− true
732− });
745+ true
746+ });
733747
734748 if let Some(doc) = doc {
735− let lang_conf = doc.language_config();
736− let text = doc.text();
749+ let lang_conf = doc.language.clone();
750+ let text = doc.text().clone();
751+
752+ let mut unchaged_diag_sources_ = Vec::new();
753+ if let Some(lang_conf) = &lang_conf {
754+ if let Some(old_diagnostics) =
755+ self.editor.diagnostics.get(&params.uri)
756+ {
757+ if !lang_conf.persistent_diagnostic_sources.is_empty() {
758+ // Sort diagnostics first by severity and then by line numbers.
759+ // Note: The `lsp::DiagnosticSeverity` enum is already defined in decreasing order
760+ params
761+ .diagnostics
762+ .sort_unstable_by_key(|d| (d.severity, d.range.start));
763+ }
764+ for source in &lang_conf.persistent_diagnostic_sources {
765+ let new_diagnostics = params
766+ .diagnostics
767+ .iter()
768+ .filter(|d| d.source.as_ref() == Some(source));
769+ let old_diagnostics = old_diagnostics
770+ .iter()
771+ .filter(|(d, d_server)| {
772+ *d_server == server_id
773+ && d.source.as_ref() == Some(source)
774+ })
775+ .map(|(d, _)| d);
776+ if new_diagnostics.eq(old_diagnostics) {
777+ unchaged_diag_sources_.push(source.clone())
778+ }
779+ }
780+ }
781+ }
737782
738− let diagnostics = params
739− .diagnostics
740− .iter()
741− .filter_map(|diagnostic| {
783+ let unchaged_diag_sources = &unchaged_diag_sources_;
784+ let diagnostics =
785+ params.diagnostics.iter().filter_map(move |diagnostic| {
742786 use helix_core::diagnostic::{Diagnostic, Range, Severity::*};
743787 use lsp::DiagnosticSeverity;
744788
789+ if diagnostic.source.as_ref().map_or(false, |source| {
790+ unchaged_diag_sources.contains(source)
791+ }) {
792+ return None;
793+ }
794+
745795 // TODO: convert inside server
746796 let start = if let Some(start) = lsp_pos_to_pos(
747− text,
797+ &text,
748798 diagnostic.range.start,
749799 offset_encoding,
750800 ) {
@@ -755,14 +805,13 @@ impl Application {
755805 };
756806
757807 let end = if let Some(end) =
758− lsp_pos_to_pos(text, diagnostic.range.end, offset_encoding)
808+ lsp_pos_to_pos(&text, diagnostic.range.end, offset_encoding)
759809 {
760810 end
761811 } else {
762812 log::warn!("lsp position out of bounds - {:?}", diagnostic);
763813 return None;
764814 };
765−
766815 let severity =
767816 diagnostic.severity.map(|severity| match severity {
768817 DiagnosticSeverity::ERROR => Error,
@@ -775,7 +824,7 @@ impl Application {
775824 ),
776825 });
777826
778− if let Some(lang_conf) = lang_conf {
827+ if let Some(lang_conf) = &lang_conf {
779828 if let Some(severity) = severity {
780829 if severity < lang_conf.diagnostic_severity {
781830 return None;
@@ -814,8 +863,17 @@ impl Application {
814863 Vec::new()
815864 };
816865
866+ let ends_at_word = start != end
867+ && end != 0
868+ && text.get_char(end - 1).map_or(false, char_is_word);
869+ let starts_at_word = start != end
870+ && text.get_char(start).map_or(false, char_is_word);
871+
817872 Some(Diagnostic {
818873 range: Range { start, end },
874+ ends_at_word,
875+ starts_at_word,
876+ zero_width: start == end,
819877 line: diagnostic.range.start.line as usize,
820878 message: diagnostic.message.clone(),
821879 severity,
@@ -825,38 +883,33 @@ impl Application {
825883 data: diagnostic.data.clone(),
826884 language_server_id: server_id,
827885 })
828− })
829− .collect();
886+ });
830887
831− doc.replace_diagnostics(diagnostics, server_id);
888+ doc.replace_diagnostics(diagnostics, unchaged_diag_sources, server_id);
832889 }
833890
834− let mut diagnostics = params
835− .diagnostics
836− .into_iter()
837− .map(|d| (d, server_id))
838− .collect();
891+ let diagnostics = params.diagnostics.into_iter().map(|d| (d, server_id));
839892
840893 // Insert the original lsp::Diagnostics here because we may have no open document
841894 // for diagnosic message and so we can't calculate the exact position.
842895 // When using them later in the diagnostics picker, we calculate them on-demand.
843− match self.editor.diagnostics.entry(params.uri) {
896+ let diagnostics = match self.editor.diagnostics.entry(params.uri) {
844897 Entry::Occupied(o) => {
845898 let current_diagnostics = o.into_mut();
846899 // there may entries of other language servers, which is why we can't overwrite the whole entry
847900 current_diagnostics.retain(|(_, lsp_id)| *lsp_id != server_id);
848− current_diagnostics.append(&mut diagnostics);
849− // Sort diagnostics first by severity and then by line numbers.
850− // Note: The `lsp::DiagnosticSeverity` enum is already defined in decreasing order
901+ current_diagnostics.extend(diagnostics);
851902 current_diagnostics
852− .sort_unstable_by_key(|(d, _)| (d.severity, d.range.start));
853− }
854− Entry::Vacant(v) => {
855− diagnostics
856− .sort_unstable_by_key(|(d, _)| (d.severity, d.range.start));
857− v.insert(diagnostics);
903+ // Sort diagnostics first by severity and then by line numbers.
858904 }
905+ Entry::Vacant(v) => v.insert(diagnostics.collect()),
859906 };
907+
908+ // Sort diagnostics first by severity and then by line numbers.
909+ // Note: The `lsp::DiagnosticSeverity` enum is already defined in decreasing order
910+ diagnostics.sort_unstable_by_key(|(d, server_id)| {
911+ (d.severity, d.range.start, *server_id)
912+ });
860913 }
861914 Notification::ShowMessage(params) => {
862915 log::warn!("unhandled window/showMessage: {:?}", params);
helix-term/src/args.rs+29
@@ -17,12 +17,14 @@ pub struct Args {
1717 pub log_file: Option<PathBuf>,
1818 pub config_file: Option<PathBuf>,
1919 pub files: Vec<(PathBuf, Position)>,
20+ pub working_directory: Option<PathBuf>,
2021}
2122
2223impl Args {
2324 pub fn parse_args() -> Result<Args> {
2425 let mut args = Args::default();
2526 let mut argv = std::env::args().peekable();
27+ let mut line_number = 0;
2628
2729 argv.next(); // skip the program, we don't care about that
2830
@@ -59,6 +61,20 @@ impl Args {
5961 Some(path) => args.log_file = Some(path.into()),
6062 None => anyhow::bail!("--log must specify a path to write"),
6163 },
64+ "-w" | "--working-dir" => match argv.next().as_deref() {
65+ Some(path) => {
66+ args.working_directory = if Path::new(path).is_dir() {
67+ Some(PathBuf::from(path))
68+ } else {
69+ anyhow::bail!(
70+ "--working-dir specified does not exist or is not a directory"
71+ )
72+ }
73+ }
74+ None => {
75+ anyhow::bail!("--working-dir must specify an initial working directory")
76+ }
77+ },
6278 arg if arg.starts_with("--") => {
6379 anyhow::bail!("unexpected double dash argument: {}", arg)
6480 }
@@ -73,6 +89,13 @@ impl Args {
7389 }
7490 }
7591 }
92+ arg if arg.starts_with('+') => {
93+ let arg = &arg[1..];
94+ line_number = match arg.parse::<usize>() {
95+ Ok(n) => n.saturating_sub(1),
96+ _ => anyhow::bail!("bad line number after +"),
97+ };
98+ }
7699 arg => args.files.push(parse_file(arg)),
77100 }
78101 }
@@ -82,6 +105,12 @@ impl Args {
82105 args.files.push(parse_file(&arg));
83106 }
84107
108+ if let Some(file) = args.files.first_mut() {
109+ if line_number != 0 {
110+ file.1.row = line_number;
111+ }
112+ }
113+
85114 Ok(args)
86115 }
87116}
helix-term/src/commands.rs+193−97
@@ -60,8 +60,13 @@ use crate::{
6060
6161use crate::job::{self, Jobs};
6262use futures_util::{stream::FuturesUnordered, TryStreamExt};
63−use std::{collections::HashMap, fmt, future::Future};
64−use std::{collections::HashSet, num::NonZeroUsize};
63+use std::{
64+ collections::{HashMap, HashSet},
65+ fmt,
66+ future::Future,
67+ io::Read,
68+ num::NonZeroUsize,
69+};
6570
6671use std::{
6772 borrow::Cow,
@@ -70,6 +75,7 @@ use std::{
7075
7176use once_cell::sync::Lazy;
7277use serde::de::{self, Deserialize, Deserializer};
78+use url::Url;
7379
7480use grep_regex::RegexMatcherBuilder;
7581use grep_searcher::{sinks, BinaryDetection, SearcherBuilder};
@@ -331,7 +337,7 @@ impl MappableCommand {
331337 goto_implementation, "Goto implementation",
332338 goto_file_start, "Goto line number <n> else file start",
333339 goto_file_end, "Goto file end",
334− goto_file, "Goto files in selection",
340+ goto_file, "Goto files/URLs in selection",
335341 goto_file_hsplit, "Goto files in selection (hsplit)",
336342 goto_file_vsplit, "Goto files in selection (vsplit)",
337343 goto_reference, "Goto references",
@@ -984,6 +990,7 @@ fn align_selections(cx: &mut Context) {
984990
985991 let transaction = Transaction::change(doc.text(), changes.into_iter());
986992 doc.apply(&transaction, view.id);
993+ exit_select_mode(cx);
987994}
988995
989996fn goto_window(cx: &mut Context, align: Align) {
@@ -1189,10 +1196,53 @@ fn goto_file_impl(cx: &mut Context, action: Action) {
11891196 .to_string(),
11901197 );
11911198 }
1199+
11921200 for sel in paths {
11931201 let p = sel.trim();
1194− if !p.is_empty() {
1195− let path = &rel_path.join(p);
1202+ if p.is_empty() {
1203+ continue;
1204+ }
1205+
1206+ if let Ok(url) = Url::parse(p) {
1207+ return open_url(cx, url, action);
1208+ }
1209+
1210+ let path = &rel_path.join(p);
1211+ if path.is_dir() {
1212+ let picker = ui::file_picker(path.into(), &cx.editor.config());
1213+ cx.push_layer(Box::new(overlaid(picker)));
1214+ } else if let Err(e) = cx.editor.open(path, action) {
1215+ cx.editor.set_error(format!("Open file failed: {:?}", e));
1216+ }
1217+ }
1218+}
1219+
1220+/// Opens the given url. If the URL points to a valid textual file it is open in helix.
1221+// Otherwise, the file is open using external program.
1222+fn open_url(cx: &mut Context, url: Url, action: Action) {
1223+ let doc = doc!(cx.editor);
1224+ let rel_path = doc
1225+ .relative_path()
1226+ .map(|path| path.parent().unwrap().to_path_buf())
1227+ .unwrap_or_default();
1228+
1229+ if url.scheme() != "file" {
1230+ return open_external_url(cx, url);
1231+ }
1232+
1233+ let content_type = std::fs::File::open(url.path()).and_then(|file| {
1234+ // Read up to 1kb to detect the content type
1235+ let mut read_buffer = Vec::new();
1236+ let n = file.take(1024).read_to_end(&mut read_buffer)?;
1237+ Ok(content_inspector::inspect(&read_buffer[..n]))
1238+ });
1239+
1240+ // we attempt to open binary files - files that can't be open in helix - using external
1241+ // program as well, e.g. pdf files or images
1242+ match content_type {
1243+ Ok(content_inspector::ContentType::BINARY) => open_external_url(cx, url),
1244+ Ok(_) | Err(_) => {
1245+ let path = &rel_path.join(url.path());
11961246 if path.is_dir() {
11971247 let picker = ui::file_picker(path.into(), &cx.editor.config());
11981248 cx.push_layer(Box::new(overlaid(picker)));
@@ -1203,6 +1253,23 @@ fn goto_file_impl(cx: &mut Context, action: Action) {
12031253 }
12041254}
12051255
1256+/// Opens URL in external program.
1257+fn open_external_url(cx: &mut Context, url: Url) {
1258+ let commands = open::commands(url.as_str());
1259+ cx.jobs.callback(async {
1260+ for cmd in commands {
1261+ let mut command = tokio::process::Command::new(cmd.get_program());
1262+ command.args(cmd.get_args());
1263+ if command.output().await.is_ok() {
1264+ return Ok(job::Callback::Editor(Box::new(|_| {})));
1265+ }
1266+ }
1267+ Ok(job::Callback::Editor(Box::new(move |editor| {
1268+ editor.set_error("Opening URL in external program failed")
1269+ })))
1270+ });
1271+}
1272+
12061273fn extend_word_impl<F>(cx: &mut Context, extend_fn: F)
12071274where
12081275 F: Fn(RopeSlice, Range, usize) -> Range,
@@ -1251,7 +1318,7 @@ fn extend_next_long_word_end(cx: &mut Context) {
12511318 extend_word_impl(cx, movement::move_next_long_word_end)
12521319}
12531320
1254−/// Separate branch to find_char designed only for <ret> char.
1321+/// Separate branch to find_char designed only for `<ret>` char.
12551322//
12561323// This is necessary because the one document can have different line endings inside. And we
12571324// cannot predict what character to find when <ret> is pressed. On the current line it can be `lf`
@@ -1527,6 +1594,7 @@ where
15271594 });
15281595
15291596 doc.apply(&transaction, view.id);
1597+ exit_select_mode(cx);
15301598}
15311599
15321600fn switch_case(cx: &mut Context) {
@@ -2184,7 +2252,10 @@ fn global_search(cx: &mut Context) {
21842252 let searcher = SearcherBuilder::new()
21852253 .binary_detection(BinaryDetection::quit(b'\x00'))
21862254 .build();
2187− WalkBuilder::new(search_root)
2255+
2256+ let mut walk_builder = WalkBuilder::new(search_root);
2257+
2258+ walk_builder
21882259 .hidden(file_picker_config.hidden)
21892260 .parents(file_picker_config.parents)
21902261 .ignore(file_picker_config.ignore)
@@ -2195,73 +2266,77 @@ fn global_search(cx: &mut Context) {
21952266 .max_depth(file_picker_config.max_depth)
21962267 .filter_entry(move |entry| {
21972268 filter_picker_entry(entry, &absolute_root, dedup_symlinks)
2198− })
2199− .build_parallel()
2200− .run(|| {
2201− let mut searcher = searcher.clone();
2202− let matcher = matcher.clone();
2203− let injector = injector_.clone();
2204− let documents = &documents;
2205− Box::new(move |entry: Result<DirEntry, ignore::Error>| -> WalkState {
2206− let entry = match entry {
2207− Ok(entry) => entry,
2208− Err(_) => return WalkState::Continue,
2209− };
2210−
2211− match entry.file_type() {
2212− Some(entry) if entry.is_file() => {}
2213− // skip everything else
2214− _ => return WalkState::Continue,
2215− };
2216−
2217− let mut stop = false;
2218− let sink = sinks::UTF8(|line_num, _| {
2219− stop = injector
2220− .push(FileResult::new(entry.path(), line_num as usize - 1))
2221− .is_err();
2222−
2223− Ok(!stop)
2224− });
2225− let doc = documents.iter().find(|&(doc_path, _)| {
2226− doc_path
2227− .as_ref()
2228− .map_or(false, |doc_path| doc_path == entry.path())
2229− });
2230−
2231− let result = if let Some((_, doc)) = doc {
2232− // there is already a buffer for this file
2233− // search the buffer instead of the file because it's faster
2234− // and captures new edits without requiring a save
2235− if searcher.multi_line_with_matcher(&matcher) {
2236− // in this case a continous buffer is required
2237− // convert the rope to a string
2238− let text = doc.to_string();
2239− searcher.search_slice(&matcher, text.as_bytes(), sink)
2240− } else {
2241− searcher.search_reader(
2242− &matcher,
2243− RopeReader::new(doc.slice(..)),
2244− sink,
2245− )
2246− }
2247− } else {
2248− searcher.search_path(&matcher, entry.path(), sink)
2249− };
2269+ });
22502270
2251− if let Err(err) = result {
2252− log::error!(
2253− "Global search error: {}, {}",
2254− entry.path().display(),
2255− err
2256− );
2257− }
2258− if stop {
2259− WalkState::Quit
2271+ walk_builder
2272+ .add_custom_ignore_filename(helix_loader::config_dir().join("ignore"));
2273+ walk_builder.add_custom_ignore_filename(".helix/ignore");
2274+
2275+ walk_builder.build_parallel().run(|| {
2276+ let mut searcher = searcher.clone();
2277+ let matcher = matcher.clone();
2278+ let injector = injector_.clone();
2279+ let documents = &documents;
2280+ Box::new(move |entry: Result<DirEntry, ignore::Error>| -> WalkState {
2281+ let entry = match entry {
2282+ Ok(entry) => entry,
2283+ Err(_) => return WalkState::Continue,
2284+ };
2285+
2286+ match entry.file_type() {
2287+ Some(entry) if entry.is_file() => {}
2288+ // skip everything else
2289+ _ => return WalkState::Continue,
2290+ };
2291+
2292+ let mut stop = false;
2293+ let sink = sinks::UTF8(|line_num, _| {
2294+ stop = injector
2295+ .push(FileResult::new(entry.path(), line_num as usize - 1))
2296+ .is_err();
2297+
2298+ Ok(!stop)
2299+ });
2300+ let doc = documents.iter().find(|&(doc_path, _)| {
2301+ doc_path
2302+ .as_ref()
2303+ .map_or(false, |doc_path| doc_path == entry.path())
2304+ });
2305+
2306+ let result = if let Some((_, doc)) = doc {
2307+ // there is already a buffer for this file
2308+ // search the buffer instead of the file because it's faster
2309+ // and captures new edits without requiring a save
2310+ if searcher.multi_line_with_matcher(&matcher) {
2311+ // in this case a continous buffer is required
2312+ // convert the rope to a string
2313+ let text = doc.to_string();
2314+ searcher.search_slice(&matcher, text.as_bytes(), sink)
22602315 } else {
2261− WalkState::Continue
2316+ searcher.search_reader(
2317+ &matcher,
2318+ RopeReader::new(doc.slice(..)),
2319+ sink,
2320+ )
22622321 }
2263− })
2264− });
2322+ } else {
2323+ searcher.search_path(&matcher, entry.path(), sink)
2324+ };
2325+
2326+ if let Err(err) = result {
2327+ log::error!(
2328+ "Global search error: {}, {}",
2329+ entry.path().display(),
2330+ err
2331+ );
2332+ }
2333+ if stop {
2334+ WalkState::Quit
2335+ } else {
2336+ WalkState::Continue
2337+ }
2338+ })
2339+ });
22652340 });
22662341
22672342 cx.jobs.callback(async move {
@@ -2978,6 +3053,7 @@ fn insert_with_indent(cx: &mut Context, cursor_fallback: IndentFallbackPos) {
29783053 let indent = indent::indent_for_newline(
29793054 language_config,
29803055 syntax,
3056+ &doc.config.load().indent_heuristic,
29813057 &doc.indent_style,
29823058 tab_width,
29833059 text,
@@ -3106,6 +3182,7 @@ fn open(cx: &mut Context, open: Open) {
31063182 let indent = indent::indent_for_newline(
31073183 doc.language_config(),
31083184 doc.syntax(),
3185+ &doc.config.load().indent_heuristic,
31093186 &doc.indent_style,
31103187 doc.tab_width(),
31113188 text,
@@ -3645,6 +3722,7 @@ pub mod insert {
36453722 let indent = indent::indent_for_newline(
36463723 doc.language_config(),
36473724 doc.syntax(),
3725+ &doc.config.load().indent_heuristic,
36483726 &doc.indent_style,
36493727 doc.tab_width(),
36503728 text,
@@ -3890,12 +3968,12 @@ fn yank(cx: &mut Context) {
38903968}
38913969
38923970fn yank_to_clipboard(cx: &mut Context) {
3893− yank_impl(cx.editor, '*');
3971+ yank_impl(cx.editor, '+');
38943972 exit_select_mode(cx);
38953973}
38963974
38973975fn yank_to_primary_clipboard(cx: &mut Context) {
3898− yank_impl(cx.editor, '+');
3976+ yank_impl(cx.editor, '*');
38993977 exit_select_mode(cx);
39003978}
39013979
@@ -3952,13 +4030,13 @@ fn yank_joined(cx: &mut Context) {
39524030
39534031fn yank_joined_to_clipboard(cx: &mut Context) {
39544032 let line_ending = doc!(cx.editor).line_ending;
3955− yank_joined_impl(cx.editor, line_ending.as_str(), '*');
4033+ yank_joined_impl(cx.editor, line_ending.as_str(), '+');
39564034 exit_select_mode(cx);
39574035}
39584036
39594037fn yank_joined_to_primary_clipboard(cx: &mut Context) {
39604038 let line_ending = doc!(cx.editor).line_ending;
3961− yank_joined_impl(cx.editor, line_ending.as_str(), '+');
4039+ yank_joined_impl(cx.editor, line_ending.as_str(), '*');
39624040 exit_select_mode(cx);
39634041}
39644042
@@ -3975,12 +4053,12 @@ fn yank_primary_selection_impl(editor: &mut Editor, register: char) {
39754053}
39764054
39774055fn yank_main_selection_to_clipboard(cx: &mut Context) {
3978− yank_primary_selection_impl(cx.editor, '*');
4056+ yank_primary_selection_impl(cx.editor, '+');
39794057 exit_select_mode(cx);
39804058}
39814059
39824060fn yank_main_selection_to_primary_clipboard(cx: &mut Context) {
3983− yank_primary_selection_impl(cx.editor, '+');
4061+ yank_primary_selection_impl(cx.editor, '*');
39844062 exit_select_mode(cx);
39854063}
39864064
@@ -4078,22 +4156,27 @@ pub(crate) fn paste_bracketed_value(cx: &mut Context, contents: String) {
40784156 };
40794157 let (view, doc) = current!(cx.editor);
40804158 paste_impl(&[contents], doc, view, paste, count, cx.editor.mode);
4159+ exit_select_mode(cx);
40814160}
40824161
40834162fn paste_clipboard_after(cx: &mut Context) {
4084− paste(cx.editor, '*', Paste::After, cx.count());
4163+ paste(cx.editor, '+', Paste::After, cx.count());
4164+ exit_select_mode(cx);
40854165}
40864166
40874167fn paste_clipboard_before(cx: &mut Context) {
4088− paste(cx.editor, '*', Paste::Before, cx.count());
4168+ paste(cx.editor, '+', Paste::Before, cx.count());
4169+ exit_select_mode(cx);
40894170}
40904171
40914172fn paste_primary_clipboard_after(cx: &mut Context) {
4092− paste(cx.editor, '+', Paste::After, cx.count());
4173+ paste(cx.editor, '*', Paste::After, cx.count());
4174+ exit_select_mode(cx);
40934175}
40944176
40954177fn paste_primary_clipboard_before(cx: &mut Context) {
4096− paste(cx.editor, '+', Paste::Before, cx.count());
4178+ paste(cx.editor, '*', Paste::Before, cx.count());
4179+ exit_select_mode(cx);
40974180}
40984181
40994182fn replace_with_yanked(cx: &mut Context) {
@@ -4131,11 +4214,13 @@ fn replace_with_yanked_impl(editor: &mut Editor, register: char, count: usize) {
41314214}
41324215
41334216fn replace_selections_with_clipboard(cx: &mut Context) {
4134− replace_with_yanked_impl(cx.editor, '*', cx.count());
4217+ replace_with_yanked_impl(cx.editor, '+', cx.count());
4218+ exit_select_mode(cx);
41354219}
41364220
41374221fn replace_selections_with_primary_clipboard(cx: &mut Context) {
4138− replace_with_yanked_impl(cx.editor, '+', cx.count());
4222+ replace_with_yanked_impl(cx.editor, '*', cx.count());
4223+ exit_select_mode(cx);
41394224}
41404225
41414226fn paste(editor: &mut Editor, register: char, pos: Paste, count: usize) {
@@ -4153,6 +4238,7 @@ fn paste_after(cx: &mut Context) {
41534238 Paste::After,
41544239 cx.count(),
41554240 );
4241+ exit_select_mode(cx);
41564242}
41574243
41584244fn paste_before(cx: &mut Context) {
@@ -4162,6 +4248,7 @@ fn paste_before(cx: &mut Context) {
41624248 Paste::Before,
41634249 cx.count(),
41644250 );
4251+ exit_select_mode(cx);
41654252}
41664253
41674254fn get_lines(doc: &Document, view_id: ViewId) -> Vec<usize> {
@@ -4200,6 +4287,7 @@ fn indent(cx: &mut Context) {
42004287 }),
42014288 );
42024289 doc.apply(&transaction, view.id);
4290+ exit_select_mode(cx);
42034291}
42044292
42054293fn unindent(cx: &mut Context) {
@@ -4239,6 +4327,7 @@ fn unindent(cx: &mut Context) {
42394327 let transaction = Transaction::change(doc.text(), changes.into_iter());
42404328
42414329 doc.apply(&transaction, view.id);
4330+ exit_select_mode(cx);
42424331}
42434332
42444333fn format_selections(cx: &mut Context) {
@@ -4305,10 +4394,9 @@ fn join_selections_impl(cx: &mut Context, select_space: bool) {
43054394 use movement::skip_while;
43064395 let (view, doc) = current!(cx.editor);
43074396 let text = doc.text();
4308− let slice = doc.text().slice(..);
4397+ let slice = text.slice(..);
43094398
43104399 let mut changes = Vec::new();
4311− let fragment = Tendril::from(" ");
43124400
43134401 for selection in doc.selection(view.id) {
43144402 let (start, mut end) = selection.line_range(slice);
@@ -4324,9 +4412,13 @@ fn join_selections_impl(cx: &mut Context, select_space: bool) {
43244412 let mut end = text.line_to_char(line + 1);
43254413 end = skip_while(slice, end, |ch| matches!(ch, ' ' | '\t')).unwrap_or(end);
43264414
4327− // need to skip from start, not end
4328− let change = (start, end, Some(fragment.clone()));
4329− changes.push(change);
4415+ let separator = if end == line_end_char_index(&slice, line + 1) {
4416+ // the joining line contains only space-characters => don't include a whitespace when joining
4417+ None
4418+ } else {
4419+ Some(Tendril::from(" "))
4420+ };
4421+ changes.push((start, end, separator));
43304422 }
43314423 }
43324424
@@ -4338,9 +4430,6 @@ fn join_selections_impl(cx: &mut Context, select_space: bool) {
43384430 changes.sort_unstable_by_key(|(from, _to, _text)| *from);
43394431 changes.dedup();
43404432
4341− // TODO: joining multiple empty lines should be replaced by a single space.
4342− // need to merge change ranges that touch
4343−
43444433 // select inserted spaces
43454434 let transaction = if select_space {
43464435 let ranges: SmallVec<_> = changes
@@ -4352,9 +4441,9 @@ fn join_selections_impl(cx: &mut Context, select_space: bool) {
43524441 })
43534442 .collect();
43544443 let selection = Selection::new(ranges, 0);
4355− Transaction::change(doc.text(), changes.into_iter()).with_selection(selection)
4444+ Transaction::change(text, changes.into_iter()).with_selection(selection)
43564445 } else {
4357− Transaction::change(doc.text(), changes.into_iter())
4446+ Transaction::change(text, changes.into_iter())
43584447 };
43594448
43604449 doc.apply(&transaction, view.id);
@@ -5520,12 +5609,18 @@ fn shell(cx: &mut compositor::Context, cmd: &str, behavior: &ShellBehavior) {
55205609 };
55215610
55225611 // These `usize`s cannot underflow because selection ranges cannot overlap.
5523− // Once the MSRV is 1.66.0 (mixed_integer_ops is stabilized), we can use checked
5524− // arithmetic to assert this.
5525− let anchor = (to as isize + offset - deleted_len as isize) as usize;
5612+ let anchor = to
5613+ .checked_add_signed(offset)
5614+ .expect("Selection ranges cannot overlap")
5615+ .checked_sub(deleted_len)
5616+ .expect("Selection ranges cannot overlap");
55265617 let new_range = Range::new(anchor, anchor + output_len).with_direction(range.direction());
55275618 ranges.push(new_range);
5528− offset = offset + output_len as isize - deleted_len as isize;
5619+ offset = offset
5620+ .checked_add_unsigned(output_len)
5621+ .expect("Selection ranges cannot overlap")
5622+ .checked_sub_unsigned(deleted_len)
5623+ .expect("Selection ranges cannot overlap");
55295624
55305625 changes.push((from, to, Some(output)));
55315626 }
@@ -5664,6 +5759,7 @@ fn increment_impl(cx: &mut Context, increment_direction: IncrementDirection) {
56645759 let transaction = Transaction::change(doc.text(), changes.into_iter());
56655760 let transaction = transaction.with_selection(new_selection);
56665761 doc.apply(&transaction, view.id);
5762+ exit_select_mode(cx);
56675763 }
56685764}
56695765
helix-term/src/commands/dap.rs+7−2
@@ -8,7 +8,7 @@ use dap::{StackFrame, Thread, ThreadStates};
88use helix_core::syntax::{DebugArgumentValue, DebugConfigCompletion, DebugTemplate};
99use helix_dap::{self as dap, Client};
1010use helix_lsp::block_on;
11−use helix_view::editor::Breakpoint;
11+use helix_view::{editor::Breakpoint, graphics::Margin};
1212
1313use serde_json::{to_value, Value};
1414use tokio_stream::wrappers::UnboundedReceiverStream;
@@ -581,7 +581,12 @@ pub fn dap_variables(cx: &mut Context) {
581581 }
582582
583583 let contents = Text::from(tui::text::Text::from(variables));
584− let popup = Popup::new("dap-variables", contents);
584+ let margin = if cx.editor.popup_border() {
585+ Margin::all(1)
586+ } else {
587+ Margin::none()
588+ };
589+ let popup = Popup::new("dap-variables", contents).margin(margin);
585590 cx.replace_or_push_layer("dap-variables", popup);
586591}
587592
helix-term/src/commands/lsp.rs+12−2
@@ -23,6 +23,7 @@ use helix_core::{
2323use helix_view::{
2424 document::{DocumentInlayHints, DocumentInlayHintsId, Mode},
2525 editor::Action,
26+ graphics::Margin,
2627 theme::Style,
2728 Document, View,
2829};
@@ -49,7 +50,7 @@ use std::{
4950/// If there is no configured language server that supports the feature, this displays a status message.
5051/// Using this macro in a context where the editor automatically queries the LSP
5152/// (instead of when the user explicitly does so via a keybind like `gd`)
52−/// will spam the "No configured language server supports <feature>" status message confusingly.
53+/// will spam the "No configured language server supports \<feature>" status message confusingly.
5354#[macro_export]
5455macro_rules! language_server_with_feature {
5556 ($editor:expr, $doc:expr, $feature:expr) => {{
@@ -744,7 +745,16 @@ pub fn code_action(cx: &mut Context) {
744745 });
745746 picker.move_down(); // pre-select the first item
746747
747− let popup = Popup::new("code-action", picker).with_scrollbar(false);
748+ let margin = if editor.menu_border() {
749+ Margin::vertical(1)
750+ } else {
751+ Margin::none()
752+ };
753+
754+ let popup = Popup::new("code-action", picker)
755+ .with_scrollbar(false)
756+ .margin(margin);
757+
748758 compositor.replace_or_push("code-action", popup);
749759 };
750760
helix-term/src/commands/typed.rs+254−42
@@ -6,7 +6,9 @@ use crate::job::Job;
66use super::*;
77
88use helix_core::fuzzy::fuzzy_match;
9−use helix_core::{encoding, shellwords::Shellwords};
9+use helix_core::indent::MAX_INDENT;
10+use helix_core::{encoding, line_ending, path::get_canonicalized_path, shellwords::Shellwords};
11+use helix_lsp::{OffsetEncoding, Url};
1012use helix_view::document::DEFAULT_LANGUAGE_NAME;
1113use helix_view::editor::{Action, CloseError, ConfigEvent};
1214use serde_json::Value;
@@ -330,12 +332,16 @@ fn write_impl(
330332 path: Option<&Cow<str>>,
331333 force: bool,
332334) -> anyhow::Result<()> {
333− let editor_auto_fmt = cx.editor.config().auto_format;
335+ let config = cx.editor.config();
334336 let jobs = &mut cx.jobs;
335337 let (view, doc) = current!(cx.editor);
336338 let path = path.map(AsRef::as_ref);
337339
338− let fmt = if editor_auto_fmt {
340+ if config.insert_final_newline {
341+ insert_final_newline(doc, view);
342+ }
343+
344+ let fmt = if config.auto_format {
339345 doc.auto_format().map(|fmt| {
340346 let callback = make_format_callback(
341347 doc.id(),
@@ -359,6 +365,16 @@ fn write_impl(
359365 Ok(())
360366}
361367
368+fn insert_final_newline(doc: &mut Document, view: &mut View) {
369+ let text = doc.text();
370+ if line_ending::get_line_ending(&text.slice(..)).is_none() {
371+ let eof = Selection::point(text.len_chars());
372+ let insert = Transaction::insert(text, &eof, doc.line_ending.as_str().into());
373+ doc.apply(&insert, view.id);
374+ doc.append_changes_to_history(view);
375+ }
376+}
377+
362378fn write(
363379 cx: &mut compositor::Context,
364380 args: &[Cow<str>],
@@ -461,8 +477,7 @@ fn set_indent_style(
461477 cx.editor.set_status(match style {
462478 Tabs => "tabs".to_owned(),
463479 Spaces(1) => "1 space".to_owned(),
464− Spaces(n) if (2..=8).contains(&n) => format!("{} spaces", n),
465− _ => unreachable!(), // Shouldn't happen.
480+ Spaces(n) => format!("{} spaces", n),
466481 });
467482 return Ok(());
468483 }
@@ -474,7 +489,7 @@ fn set_indent_style(
474489 Some(arg) => arg
475490 .parse::<u8>()
476491 .ok()
477− .filter(|n| (1..=8).contains(n))
492+ .filter(|n| (1..=MAX_INDENT).contains(n))
478493 .map(Spaces),
479494 _ => None,
480495 };
@@ -559,7 +574,6 @@ fn set_line_ending(
559574
560575 Ok(())
561576}
562−
563577fn earlier(
564578 cx: &mut compositor::Context,
565579 args: &[Cow<str>],
@@ -658,11 +672,10 @@ pub fn write_all_impl(
658672 write_scratch: bool,
659673) -> anyhow::Result<()> {
660674 let mut errors: Vec<&'static str> = Vec::new();
661− let auto_format = cx.editor.config().auto_format;
675+ let config = cx.editor.config();
662676 let jobs = &mut cx.jobs;
663677 let current_view = view!(cx.editor);
664678
665− // save all documents
666679 let saves: Vec<_> = cx
667680 .editor
668681 .documents
@@ -693,32 +706,35 @@ pub fn write_all_impl(
693706 current_view.id
694707 };
695708
696− let fmt = if auto_format {
697− doc.auto_format().map(|fmt| {
698− let callback = make_format_callback(
699− doc.id(),
700− doc.version(),
701− target_view,
702− fmt,
703− Some((None, force)),
704− );
705− jobs.add(Job::with_callback(callback).wait_before_exiting());
706− })
707− } else {
708− None
709− };
709+ Some((doc.id(), target_view))
710+ })
711+ .collect();
710712
711− if fmt.is_none() {
712− return Some(doc.id());
713− }
713+ for (doc_id, target_view) in saves {
714+ let doc = doc_mut!(cx.editor, &doc_id);
714715
716+ if config.insert_final_newline {
717+ insert_final_newline(doc, view_mut!(cx.editor, target_view));
718+ }
719+
720+ let fmt = if config.auto_format {
721+ doc.auto_format().map(|fmt| {
722+ let callback = make_format_callback(
723+ doc_id,
724+ doc.version(),
725+ target_view,
726+ fmt,
727+ Some((None, force)),
728+ );
729+ jobs.add(Job::with_callback(callback).wait_before_exiting());
730+ })
731+ } else {
715732 None
716− })
717− .collect();
733+ };
718734
719− // manually call save for the rest of docs that don't have a formatter
720− for id in saves {
721− cx.editor.save::<PathBuf>(id, None, force)?;
735+ if fmt.is_none() {
736+ cx.editor.save::<PathBuf>(doc_id, None, force)?;
737+ }
722738 }
723739
724740 if !errors.is_empty() && !force {
@@ -905,7 +921,7 @@ fn yank_main_selection_to_clipboard(
905921 return Ok(());
906922 }
907923
908− yank_primary_selection_impl(cx.editor, '*');
924+ yank_primary_selection_impl(cx.editor, '+');
909925 Ok(())
910926}
911927
@@ -940,7 +956,7 @@ fn yank_joined_to_clipboard(
940956 let doc = doc!(cx.editor);
941957 let default_sep = Cow::Borrowed(doc.line_ending.as_str());
942958 let separator = args.first().unwrap_or(&default_sep);
943− yank_joined_impl(cx.editor, separator, '*');
959+ yank_joined_impl(cx.editor, separator, '+');
944960 Ok(())
945961}
946962
@@ -953,7 +969,7 @@ fn yank_main_selection_to_primary_clipboard(
953969 return Ok(());
954970 }
955971
956− yank_primary_selection_impl(cx.editor, '+');
972+ yank_primary_selection_impl(cx.editor, '*');
957973 Ok(())
958974}
959975
@@ -969,7 +985,7 @@ fn yank_joined_to_primary_clipboard(
969985 let doc = doc!(cx.editor);
970986 let default_sep = Cow::Borrowed(doc.line_ending.as_str());
971987 let separator = args.first().unwrap_or(&default_sep);
972− yank_joined_impl(cx.editor, separator, '+');
988+ yank_joined_impl(cx.editor, separator, '*');
973989 Ok(())
974990}
975991
@@ -982,7 +998,7 @@ fn paste_clipboard_after(
982998 return Ok(());
983999 }
9841000
985− paste(cx.editor, '*', Paste::After, 1);
1001+ paste(cx.editor, '+', Paste::After, 1);
9861002 Ok(())
9871003}
9881004
@@ -995,7 +1011,7 @@ fn paste_clipboard_before(
9951011 return Ok(());
9961012 }
9971013
998− paste(cx.editor, '*', Paste::Before, 1);
1014+ paste(cx.editor, '+', Paste::Before, 1);
9991015 Ok(())
10001016}
10011017
@@ -1008,7 +1024,7 @@ fn paste_primary_clipboard_after(
10081024 return Ok(());
10091025 }
10101026
1011− paste(cx.editor, '+', Paste::After, 1);
1027+ paste(cx.editor, '*', Paste::After, 1);
10121028 Ok(())
10131029}
10141030
@@ -1021,7 +1037,7 @@ fn paste_primary_clipboard_before(
10211037 return Ok(());
10221038 }
10231039
1024− paste(cx.editor, '+', Paste::Before, 1);
1040+ paste(cx.editor, '*', Paste::Before, 1);
10251041 Ok(())
10261042}
10271043
@@ -1034,7 +1050,7 @@ fn replace_selections_with_clipboard(
10341050 return Ok(());
10351051 }
10361052
1037− replace_with_yanked_impl(cx.editor, '*', 1);
1053+ replace_with_yanked_impl(cx.editor, '+', 1);
10381054 Ok(())
10391055}
10401056
@@ -1047,7 +1063,7 @@ fn replace_selections_with_primary_clipboard(
10471063 return Ok(());
10481064 }
10491065
1050− replace_with_yanked_impl(cx.editor, '+', 1);
1066+ replace_with_yanked_impl(cx.editor, '*', 1);
10511067 Ok(())
10521068}
10531069
@@ -1527,6 +1543,84 @@ fn tree_sitter_scopes(
15271543 Ok(())
15281544}
15291545
1546+fn tree_sitter_highlight_name(
1547+ cx: &mut compositor::Context,
1548+ _args: &[Cow<str>],
1549+ event: PromptEvent,
1550+) -> anyhow::Result<()> {
1551+ fn find_highlight_at_cursor(
1552+ cx: &mut compositor::Context<'_>,
1553+ ) -> Option<helix_core::syntax::Highlight> {
1554+ use helix_core::syntax::HighlightEvent;
1555+
1556+ let (view, doc) = current!(cx.editor);
1557+ let syntax = doc.syntax()?;
1558+ let text = doc.text().slice(..);
1559+ let cursor = doc.selection(view.id).primary().cursor(text);
1560+ let byte = text.char_to_byte(cursor);
1561+ let node = syntax
1562+ .tree()
1563+ .root_node()
1564+ .descendant_for_byte_range(byte, byte)?;
1565+ // Query the same range as the one used in syntax highlighting.
1566+ let range = {
1567+ // Calculate viewport byte ranges:
1568+ let row = text.char_to_line(view.offset.anchor.min(text.len_chars()));
1569+ // Saturating subs to make it inclusive zero indexing.
1570+ let last_line = text.len_lines().saturating_sub(1);
1571+ let height = view.inner_area(doc).height;
1572+ let last_visible_line = (row + height as usize).saturating_sub(1).min(last_line);
1573+ let start = text.line_to_byte(row.min(last_line));
1574+ let end = text.line_to_byte(last_visible_line + 1);
1575+
1576+ start..end
1577+ };
1578+
1579+ let mut highlight = None;
1580+
1581+ for event in syntax.highlight_iter(text, Some(range), None) {
1582+ match event.unwrap() {
1583+ HighlightEvent::Source { start, end }
1584+ if start == node.start_byte() && end == node.end_byte() =>
1585+ {
1586+ return highlight;
1587+ }
1588+ HighlightEvent::HighlightStart(hl) => {
1589+ highlight = Some(hl);
1590+ }
1591+ _ => (),
1592+ }
1593+ }
1594+
1595+ None
1596+ }
1597+
1598+ if event != PromptEvent::Validate {
1599+ return Ok(());
1600+ }
1601+
1602+ let Some(highlight) = find_highlight_at_cursor(cx) else {
1603+ return Ok(());
1604+ };
1605+
1606+ let content = cx.editor.theme.scope(highlight.0).to_string();
1607+
1608+ let callback = async move {
1609+ let call: job::Callback = Callback::EditorCompositor(Box::new(
1610+ move |editor: &mut Editor, compositor: &mut Compositor| {
1611+ let content = ui::Markdown::new(content, editor.syn_loader.clone());
1612+ let popup = Popup::new("hover", content).auto_close(true);
1613+ compositor.replace_or_push("hover", popup);
1614+ },
1615+ ));
1616+ Ok(call)
1617+ };
1618+
1619+ cx.jobs.callback(callback);
1620+
1621+ Ok(())
1622+}
1623+
15301624fn vsplit(
15311625 cx: &mut compositor::Context,
15321626 args: &[Cow<str>],
@@ -2291,6 +2385,103 @@ fn clear_register(
22912385 Ok(())
22922386}
22932387
2388+fn redraw(
2389+ cx: &mut compositor::Context,
2390+ _args: &[Cow<str>],
2391+ event: PromptEvent,
2392+) -> anyhow::Result<()> {
2393+ if event != PromptEvent::Validate {
2394+ return Ok(());
2395+ }
2396+
2397+ let callback = Box::pin(async move {
2398+ let call: job::Callback =
2399+ job::Callback::EditorCompositor(Box::new(|_editor, compositor| {
2400+ compositor.need_full_redraw();
2401+ }));
2402+
2403+ Ok(call)
2404+ });
2405+
2406+ cx.jobs.callback(callback);
2407+
2408+ Ok(())
2409+}
2410+
2411+fn move_buffer(
2412+ cx: &mut compositor::Context,
2413+ args: &[Cow<str>],
2414+ event: PromptEvent,
2415+) -> anyhow::Result<()> {
2416+ if event != PromptEvent::Validate {
2417+ return Ok(());
2418+ }
2419+
2420+ ensure!(args.len() == 1, format!(":move takes one argument"));
2421+ let doc = doc!(cx.editor);
2422+
2423+ let new_path = get_canonicalized_path(&PathBuf::from(args.first().unwrap().to_string()));
2424+ let old_path = doc
2425+ .path()
2426+ .ok_or_else(|| anyhow!("Scratch buffer cannot be moved. Use :write instead"))?
2427+ .clone();
2428+ let old_path_as_url = doc.url().unwrap();
2429+ let new_path_as_url = Url::from_file_path(&new_path).unwrap();
2430+
2431+ let edits: Vec<(
2432+ helix_lsp::Result<helix_lsp::lsp::WorkspaceEdit>,
2433+ OffsetEncoding,
2434+ String,
2435+ )> = doc
2436+ .language_servers()
2437+ .map(|lsp| {
2438+ (
2439+ lsp.prepare_file_rename(&old_path_as_url, &new_path_as_url),
2440+ lsp.offset_encoding(),
2441+ lsp.name().to_owned(),
2442+ )
2443+ })
2444+ .filter(|(f, _, _)| f.is_some())
2445+ .map(|(f, encoding, name)| (helix_lsp::block_on(f.unwrap()), encoding, name))
2446+ .collect();
2447+
2448+ for (lsp_reply, encoding, name) in edits {
2449+ match lsp_reply {
2450+ Ok(edit) => {
2451+ if let Err(e) = apply_workspace_edit(cx.editor, encoding, &edit) {
2452+ log::error!(
2453+ ":move command failed to apply edits from lsp {}: {:?}",
2454+ name,
2455+ e
2456+ );
2457+ };
2458+ }
2459+ Err(e) => {
2460+ log::error!("LSP {} failed to treat willRename request: {:?}", name, e);
2461+ }
2462+ };
2463+ }
2464+
2465+ let doc = doc_mut!(cx.editor);
2466+
2467+ doc.set_path(Some(new_path.as_path()));
2468+ if let Err(e) = std::fs::rename(&old_path, &new_path) {
2469+ doc.set_path(Some(old_path.as_path()));
2470+ bail!("Could not move file: {}", e);
2471+ };
2472+
2473+ doc.language_servers().for_each(|lsp| {
2474+ lsp.did_file_rename(&old_path_as_url, &new_path_as_url);
2475+ });
2476+
2477+ cx.editor
2478+ .language_servers
2479+ .file_event_handler
2480+ .file_changed(new_path);
2481+
2482+ Ok(())
2483+}
2484+
22942485pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
22952486 TypableCommand {
22962487 name: "quit",
@@ -2414,7 +2605,7 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
24142605 TypableCommand {
24152606 name: "indent-style",
24162607 aliases: &[],
2417− doc: "Set the indentation style for editing. ('t' for tabs or 1-8 for number of spaces.)",
2608+ doc: "Set the indentation style for editing. ('t' for tabs or 1-16 for number of spaces.)",
24182609 fun: set_indent_style,
24192610 signature: CommandSignature::none(),
24202611 },
@@ -2680,6 +2871,13 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
26802871 fun: tree_sitter_scopes,
26812872 signature: CommandSignature::none(),
26822873 },
2874+ TypableCommand {
2875+ name: "tree-sitter-highlight-name",
2876+ aliases: &[],
2877+ doc: "Display name of tree-sitter highlight scope under the cursor.",
2878+ fun: tree_sitter_highlight_name,
2879+ signature: CommandSignature::none(),
2880+ },
26832881 TypableCommand {
26842882 name: "debug-start",
26852883 aliases: &["dbg"],
@@ -2877,6 +3075,20 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
28773075 fun: clear_register,
28783076 signature: CommandSignature::none(),
28793077 },
3078+ TypableCommand {
3079+ name: "redraw",
3080+ aliases: &[],
3081+ doc: "Clear and re-render the whole UI",
3082+ fun: redraw,
3083+ signature: CommandSignature::none(),
3084+ },
3085+ TypableCommand {
3086+ name: "move",
3087+ aliases: &[],
3088+ doc: "Move the current buffer and its corresponding file to a different path",
3089+ fun: move_buffer,
3090+ signature: CommandSignature::positional(&[completers::filename]),
3091+ },
28803092];
28813093
28823094pub static TYPABLE_COMMAND_MAP: Lazy<HashMap<&'static str, &'static TypableCommand>> =
helix-term/src/compositor.rs+6
@@ -80,6 +80,7 @@ pub struct Compositor {
8080 area: Rect,
8181
8282 pub(crate) last_picker: Option<Box<dyn Component>>,
83+ pub(crate) full_redraw: bool,
8384}
8485
8586impl Compositor {
@@ -88,6 +89,7 @@ impl Compositor {
8889 layers: Vec::new(),
8990 area,
9091 last_picker: None,
92+ full_redraw: false,
9193 }
9294 }
9395
@@ -206,6 +208,10 @@ impl Compositor {
206208 .find(|component| component.id() == Some(id))
207209 .and_then(|component| component.as_any_mut().downcast_mut())
208210 }
211+
212+ pub fn need_full_redraw(&mut self) {
213+ self.full_redraw = true;
214+ }
209215}
210216
211217// View casting, taken straight from Cursive
helix-term/src/health.rs+44−16
@@ -181,8 +181,8 @@ pub fn languages_all() -> std::io::Result<()> {
181181 .language
182182 .sort_unstable_by_key(|l| l.language_id.clone());
183183
184− let check_binary = |cmd: Option<String>| match cmd {
185− Some(cmd) => match which::which(&cmd) {
184+ let check_binary = |cmd: Option<&str>| match cmd {
185+ Some(cmd) => match which::which(cmd) {
186186 Ok(_) => column(&format!("✓ {}", cmd), Color::Green),
187187 Err(_) => column(&format!("✘ {}", cmd), Color::Red),
188188 },
@@ -192,17 +192,15 @@ pub fn languages_all() -> std::io::Result<()> {
192192 for lang in &syn_loader_conf.language {
193193 column(&lang.language_id, Color::Reset);
194194
195− // TODO multiple language servers (check binary for each supported language server, not just the first)
196−
197− let lsp = lang.language_servers.first().and_then(|ls| {
195+ let mut cmds = lang.language_servers.iter().filter_map(|ls| {
198196 syn_loader_conf
199197 .language_server
200198 .get(&ls.name)
201− .map(|config| config.command.clone())
199+ .map(|config| config.command.as_str())
202200 });
203− check_binary(lsp);
201+ check_binary(cmds.next());
204202
205− let dap = lang.debugger.as_ref().map(|dap| dap.command.to_string());
203+ let dap = lang.debugger.as_ref().map(|dap| dap.command.as_str());
206204 check_binary(dap);
207205
208206 for ts_feat in TsFeature::all() {
@@ -213,6 +211,12 @@ pub fn languages_all() -> std::io::Result<()> {
213211 }
214212
215213 writeln!(stdout)?;
214+
215+ for cmd in cmds {
216+ column("", Color::Reset);
217+ check_binary(Some(cmd));
218+ writeln!(stdout)?;
219+ }
216220 }
217221
218222 Ok(())
@@ -268,15 +272,12 @@ pub fn language(lang_str: String) -> std::io::Result<()> {
268272 }
269273 };
270274
271− // TODO multiple language servers
272− probe_protocol(
275+ probe_protocols(
273276 "language server",
274− lang.language_servers.first().and_then(|ls| {
275− syn_loader_conf
276− .language_server
277− .get(&ls.name)
278− .map(|config| config.command.clone())
279− }),
277+ lang.language_servers
278+ .iter()
279+ .filter_map(|ls| syn_loader_conf.language_server.get(&ls.name))
280+ .map(|config| config.command.as_str()),
280281 )?;
281282
282283 probe_protocol(
@@ -291,6 +292,33 @@ pub fn language(lang_str: String) -> std::io::Result<()> {
291292 Ok(())
292293}
293294
295+/// Display diagnostics about multiple LSPs and DAPs.
296+fn probe_protocols<'a, I: Iterator<Item = &'a str> + 'a>(
297+ protocol_name: &str,
298+ server_cmds: I,
299+) -> std::io::Result<()> {
300+ let stdout = std::io::stdout();
301+ let mut stdout = stdout.lock();
302+ let mut server_cmds = server_cmds.peekable();
303+
304+ write!(stdout, "Configured {}s:", protocol_name)?;
305+ if server_cmds.peek().is_none() {
306+ writeln!(stdout, "{}", " None".yellow())?;
307+ return Ok(());
308+ }
309+ writeln!(stdout)?;
310+
311+ for cmd in server_cmds {
312+ let (path, icon) = match which::which(cmd) {
313+ Ok(path) => (path.display().to_string().green(), "✓".green()),
314+ Err(_) => (format!("'{}' not found in $PATH", cmd).red(), "✘".red()),
315+ };
316+ writeln!(stdout, " {} {}: {}", icon, cmd, path)?;
317+ }
318+
319+ Ok(())
320+}
321+
294322/// Display diagnostics about LSP and DAP.
295323fn probe_protocol(protocol_name: &str, server_cmd: Option<String>) -> std::io::Result<()> {
296324 let stdout = std::io::stdout();
helix-term/src/main.rs+17−1
@@ -66,6 +66,8 @@ FLAGS:
6666 -V, --version Prints version information
6767 --vsplit Splits all given files vertically into different windows
6868 --hsplit Splits all given files horizontally into different windows
69+ -w, --working-dir <path> Specify an initial working directory
70+ +N Open the first given file at line number N
6971",
7072 env!("CARGO_PKG_NAME"),
7173 VERSION_AND_GIT_HASH,
@@ -74,7 +76,7 @@ FLAGS:
7476 helix_loader::default_log_file().display(),
7577 );
7678
77− let args = Args::parse_args().context("could not parse arguments")?;
79+ let mut args = Args::parse_args().context("could not parse arguments")?;
7880
7981 helix_loader::initialize_config_file(args.config_file.clone());
8082 helix_loader::initialize_log_file(args.log_file.clone());
@@ -114,6 +116,20 @@ FLAGS:
114116
115117 setup_logging(args.verbosity).context("failed to initialize logging")?;
116118
119+ // Before setting the working directory, resolve all the paths in args.files
120+ for (path, _) in args.files.iter_mut() {
121+ *path = helix_core::path::get_canonicalized_path(path);
122+ }
123+
124+ // NOTE: Set the working directory early so the correct configuration is loaded. Be aware that
125+ // Application::new() depends on this logic so it must be updated if this changes.
126+ if let Some(path) = &args.working_directory {
127+ helix_loader::set_current_working_dir(path)?;
128+ } else if let Some((path, _)) = args.files.first().filter(|p| p.0.is_dir()) {
129+ // If the first file is a directory, it will be the working directory unless -w was specified
130+ helix_loader::set_current_working_dir(path)?;
131+ }
132+
117133 let config = match Config::load_default() {
118134 Ok(config) => config,
119135 Err(ConfigLoadError::Error(err)) if err.kind() == std::io::ErrorKind::NotFound => {
helix-term/src/ui/completion.rs+17−1
@@ -2,6 +2,7 @@ use crate::compositor::{Component, Context, Event, EventResult};
22use helix_view::{
33 document::SavePoint,
44 editor::CompleteAction,
5+ graphics::Margin,
56 theme::{Modifier, Style},
67 ViewId,
78};
@@ -326,9 +327,18 @@ impl Completion {
326327 }
327328 };
328329 });
330+
331+ let margin = if editor.menu_border() {
332+ Margin::vertical(1)
333+ } else {
334+ Margin::none()
335+ };
336+
329337 let popup = Popup::new(Self::ID, menu)
330338 .with_scrollbar(false)
331− .ignore_escape_key(true);
339+ .ignore_escape_key(true)
340+ .margin(margin);
341+
332342 let mut completion = Self {
333343 popup,
334344 start_offset,
@@ -569,6 +579,12 @@ impl Component for Completion {
569579 // clear area
570580 let background = cx.editor.theme.get("ui.popup");
571581 surface.clear_with(doc_area, background);
582+
583+ if cx.editor.popup_border() {
584+ use tui::widgets::{Block, Borders, Widget};
585+ Widget::render(Block::default().borders(Borders::ALL), doc_area, surface);
586+ }
587+
572588 markdown_doc.render(doc_area, surface, cx);
573589 }
574590}
helix-term/src/ui/document.rs+60−24
@@ -97,7 +97,8 @@ pub fn render_document(
9797 doc: &Document,
9898 offset: ViewPosition,
9999 doc_annotations: &TextAnnotations,
100− highlight_iter: impl Iterator<Item = HighlightEvent>,
100+ syntax_highlight_iter: impl Iterator<Item = HighlightEvent>,
101+ overlay_highlight_iter: impl Iterator<Item = HighlightEvent>,
101102 theme: &Theme,
102103 line_decoration: &mut [Box<dyn LineDecoration + '_>],
103104 translated_positions: &mut [TranslatedPosition],
@@ -109,7 +110,8 @@ pub fn render_document(
109110 offset,
110111 &doc.text_format(viewport.width, Some(theme)),
111112 doc_annotations,
112− highlight_iter,
113+ syntax_highlight_iter,
114+ overlay_highlight_iter,
113115 theme,
114116 line_decoration,
115117 translated_positions,
@@ -157,7 +159,8 @@ pub fn render_text<'t>(
157159 offset: ViewPosition,
158160 text_fmt: &TextFormat,
159161 text_annotations: &TextAnnotations,
160− highlight_iter: impl Iterator<Item = HighlightEvent>,
162+ syntax_highlight_iter: impl Iterator<Item = HighlightEvent>,
163+ overlay_highlight_iter: impl Iterator<Item = HighlightEvent>,
161164 theme: &Theme,
162165 line_decorations: &mut [Box<dyn LineDecoration + '_>],
163166 translated_positions: &mut [TranslatedPosition],
@@ -178,10 +181,16 @@ pub fn render_text<'t>(
178181
179182 let (mut formatter, mut first_visible_char_idx) =
180183 DocumentFormatter::new_at_prev_checkpoint(text, text_fmt, text_annotations, offset.anchor);
181− let mut styles = StyleIter {
184+ let mut syntax_styles = StyleIter {
182185 text_style: renderer.text_style,
183186 active_highlights: Vec::with_capacity(64),
184− highlight_iter,
187+ highlight_iter: syntax_highlight_iter,
188+ theme,
189+ };
190+ let mut overlay_styles = StyleIter {
191+ text_style: Style::default(),
192+ active_highlights: Vec::with_capacity(64),
193+ highlight_iter: overlay_highlight_iter,
185194 theme,
186195 };
187196
@@ -193,7 +202,10 @@ pub fn render_text<'t>(
193202 };
194203 let mut is_in_indent_area = true;
195204 let mut last_line_indent_level = 0;
196− let mut style_span = styles
205+ let mut syntax_style_span = syntax_styles
206+ .next()
207+ .unwrap_or_else(|| (Style::default(), usize::MAX));
208+ let mut overlay_style_span = overlay_styles
197209 .next()
198210 .unwrap_or_else(|| (Style::default(), usize::MAX));
199211
@@ -221,9 +233,16 @@ pub fn render_text<'t>(
221233
222234 // skip any graphemes on visual lines before the block start
223235 if pos.row < row_off {
224− if char_pos >= style_span.1 {
225− style_span = if let Some(style_span) = styles.next() {
226− style_span
236+ if char_pos >= syntax_style_span.1 {
237+ syntax_style_span = if let Some(syntax_style_span) = syntax_styles.next() {
238+ syntax_style_span
239+ } else {
240+ break;
241+ }
242+ }
243+ if char_pos >= overlay_style_span.1 {
244+ overlay_style_span = if let Some(overlay_style_span) = overlay_styles.next() {
245+ overlay_style_span
227246 } else {
228247 break;
229248 }
@@ -260,8 +279,15 @@ pub fn render_text<'t>(
260279 }
261280
262281 // acquire the correct grapheme style
263− if char_pos >= style_span.1 {
264− style_span = styles.next().unwrap_or((Style::default(), usize::MAX));
282+ if char_pos >= syntax_style_span.1 {
283+ syntax_style_span = syntax_styles
284+ .next()
285+ .unwrap_or((Style::default(), usize::MAX));
286+ }
287+ if char_pos >= overlay_style_span.1 {
288+ overlay_style_span = overlay_styles
289+ .next()
290+ .unwrap_or((Style::default(), usize::MAX));
265291 }
266292 char_pos += grapheme.doc_chars();
267293
@@ -275,22 +301,25 @@ pub fn render_text<'t>(
275301 pos,
276302 );
277303
278− let grapheme_style = if let GraphemeSource::VirtualText { highlight } = grapheme.source {
279− let style = renderer.text_style;
280− if let Some(highlight) = highlight {
281− style.patch(theme.highlight(highlight.0))
304+ let (syntax_style, overlay_style) =
305+ if let GraphemeSource::VirtualText { highlight } = grapheme.source {
306+ let mut style = renderer.text_style;
307+ if let Some(highlight) = highlight {
308+ style = style.patch(theme.highlight(highlight.0))
309+ }
310+ (style, Style::default())
282311 } else {
283− style
284− }
285− } else {
286− style_span.0
287− };
312+ (syntax_style_span.0, overlay_style_span.0)
313+ };
288314
289− let virt = grapheme.is_virtual();
315+ let is_virtual = grapheme.is_virtual();
290316 renderer.draw_grapheme(
291317 grapheme.grapheme,
292− grapheme_style,
293− virt,
318+ GraphemeStyle {
319+ syntax_style,
320+ overlay_style,
321+ },
322+ is_virtual,
294323 &mut last_line_indent_level,
295324 &mut is_in_indent_area,
296325 pos,
@@ -322,6 +351,11 @@ pub struct TextRenderer<'a> {
322351 pub viewport: Rect,
323352}
324353
354+pub struct GraphemeStyle {
355+ syntax_style: Style,
356+ overlay_style: Style,
357+}
358+
325359impl<'a> TextRenderer<'a> {
326360 pub fn new(
327361 surface: &'a mut Surface,
@@ -395,7 +429,7 @@ impl<'a> TextRenderer<'a> {
395429 pub fn draw_grapheme(
396430 &mut self,
397431 grapheme: Grapheme,
398− mut style: Style,
432+ grapheme_style: GraphemeStyle,
399433 is_virtual: bool,
400434 last_indent_level: &mut usize,
401435 is_in_indent_area: &mut bool,
@@ -405,9 +439,11 @@ impl<'a> TextRenderer<'a> {
405439 let is_whitespace = grapheme.is_whitespace();
406440
407441 // TODO is it correct to apply the whitespace style to all unicode white spaces?
442+ let mut style = grapheme_style.syntax_style;
408443 if is_whitespace {
409444 style = style.patch(self.whitespace_style);
410445 }
446+ style = style.patch(grapheme_style.overlay_style);
411447
412448 let width = grapheme.width();
413449 let space = if is_virtual { " " } else { &self.space };
helix-term/src/ui/editor.rs+77−44
@@ -124,16 +124,20 @@ impl EditorView {
124124 line_decorations.push(Box::new(line_decoration));
125125 }
126126
127− let mut highlights =
127+ let syntax_highlights =
128128 Self::doc_syntax_highlights(doc, view.offset.anchor, inner.height, theme);
129− let overlay_highlights = Self::overlay_syntax_highlights(
129+
130+ let mut overlay_highlights =
131+ Self::empty_highlight_iter(doc, view.offset.anchor, inner.height);
132+ let overlay_syntax_highlights = Self::overlay_syntax_highlights(
130133 doc,
131134 view.offset.anchor,
132135 inner.height,
133136 &text_annotations,
134137 );
135− if !overlay_highlights.is_empty() {
136− highlights = Box::new(syntax::merge(highlights, overlay_highlights));
138+ if !overlay_syntax_highlights.is_empty() {
139+ overlay_highlights =
140+ Box::new(syntax::merge(overlay_highlights, overlay_syntax_highlights));
137141 }
138142
139143 for diagnostic in Self::doc_diagnostics_highlights(doc, theme) {
@@ -142,29 +146,28 @@ impl EditorView {
142146 if diagnostic.is_empty() {
143147 continue;
144148 }
145− highlights = Box::new(syntax::merge(highlights, diagnostic));
149+ overlay_highlights = Box::new(syntax::merge(overlay_highlights, diagnostic));
146150 }
147151
148− let highlights: Box<dyn Iterator<Item = HighlightEvent>> = if is_focused {
152+ if is_focused {
149153 let highlights = syntax::merge(
150− highlights,
154+ overlay_highlights,
151155 Self::doc_selection_highlights(
152156 editor.mode(),
153157 doc,
154158 view,
155159 theme,
156160 &config.cursor_shape,
161+ self.terminal_focused,
157162 ),
158163 );
159164 let focused_view_elements = Self::highlight_focused_view_elements(view, doc, theme);
160165 if focused_view_elements.is_empty() {
161− Box::new(highlights)
166+ overlay_highlights = Box::new(highlights)
162167 } else {
163− Box::new(syntax::merge(highlights, focused_view_elements))
168+ overlay_highlights = Box::new(syntax::merge(highlights, focused_view_elements))
164169 }
165− } else {
166− Box::new(highlights)
167− };
170+ }
168171
169172 let gutter_overflow = view.gutter_offset(doc) == 0;
170173 if !gutter_overflow {
@@ -197,7 +200,8 @@ impl EditorView {
197200 doc,
198201 view.offset,
199202 &text_annotations,
200− highlights,
203+ syntax_highlights,
204+ overlay_highlights,
201205 theme,
202206 &mut line_decorations,
203207 &mut translated_positions,
@@ -257,27 +261,39 @@ impl EditorView {
257261 .for_each(|area| surface.set_style(area, ruler_theme))
258262 }
259263
260− pub fn overlay_syntax_highlights(
264+ fn viewport_byte_range(
265+ text: helix_core::RopeSlice,
266+ row: usize,
267+ height: u16,
268+ ) -> std::ops::Range<usize> {
269+ // Calculate viewport byte ranges:
270+ // Saturating subs to make it inclusive zero indexing.
271+ let last_line = text.len_lines().saturating_sub(1);
272+ let last_visible_line = (row + height as usize).saturating_sub(1).min(last_line);
273+ let start = text.line_to_byte(row.min(last_line));
274+ let end = text.line_to_byte(last_visible_line + 1);
275+
276+ start..end
277+ }
278+
279+ pub fn empty_highlight_iter(
261280 doc: &Document,
262281 anchor: usize,
263282 height: u16,
264− text_annotations: &TextAnnotations,
265− ) -> Vec<(usize, std::ops::Range<usize>)> {
283+ ) -> Box<dyn Iterator<Item = HighlightEvent>> {
266284 let text = doc.text().slice(..);
267285 let row = text.char_to_line(anchor.min(text.len_chars()));
268286
269− let range = {
270− // Calculate viewport byte ranges:
271− // Saturating subs to make it inclusive zero indexing.
272− let last_line = text.len_lines().saturating_sub(1);
273− let last_visible_line = (row + height as usize).saturating_sub(1).min(last_line);
274− let start = text.line_to_byte(row.min(last_line));
275− let end = text.line_to_byte(last_visible_line + 1);
276−
277− start..end
278− };
279−
280− text_annotations.collect_overlay_highlights(range)
287+ // Calculate viewport byte ranges:
288+ // Saturating subs to make it inclusive zero indexing.
289+ let range = Self::viewport_byte_range(text, row, height);
290+ Box::new(
291+ [HighlightEvent::Source {
292+ start: text.byte_to_char(range.start),
293+ end: text.byte_to_char(range.end),
294+ }]
295+ .into_iter(),
296+ )
281297 }
282298
283299 /// Get syntax highlights for a document in a view represented by the first line
@@ -292,16 +308,7 @@ impl EditorView {
292308 let text = doc.text().slice(..);
293309 let row = text.char_to_line(anchor.min(text.len_chars()));
294310
295− let range = {
296− // Calculate viewport byte ranges:
297− // Saturating subs to make it inclusive zero indexing.
298− let last_line = text.len_lines().saturating_sub(1);
299− let last_visible_line = (row + height as usize).saturating_sub(1).min(last_line);
300− let start = text.line_to_byte(row.min(last_line));
301− let end = text.line_to_byte(last_visible_line + 1);
302−
303− start..end
304− };
311+ let range = Self::viewport_byte_range(text, row, height);
305312
306313 match doc.syntax() {
307314 Some(syntax) => {
@@ -334,6 +341,20 @@ impl EditorView {
334341 }
335342 }
336343
344+ pub fn overlay_syntax_highlights(
345+ doc: &Document,
346+ anchor: usize,
347+ height: u16,
348+ text_annotations: &TextAnnotations,
349+ ) -> Vec<(usize, std::ops::Range<usize>)> {
350+ let text = doc.text().slice(..);
351+ let row = text.char_to_line(anchor.min(text.len_chars()));
352+
353+ let range = Self::viewport_byte_range(text, row, height);
354+
355+ text_annotations.collect_overlay_highlights(range)
356+ }
357+
337358 /// Get highlight spans for document diagnostics
338359 pub fn doc_diagnostics_highlights(
339360 doc: &Document,
@@ -365,7 +386,7 @@ impl EditorView {
365386 let mut warning_vec = Vec::new();
366387 let mut error_vec = Vec::new();
367388
368− for diagnostic in doc.diagnostics() {
389+ for diagnostic in doc.shown_diagnostics() {
369390 // Separate diagnostics into different Vecs by severity.
370391 let (vec, scope) = match diagnostic.severity {
371392 Some(Severity::Info) => (&mut info_vec, info),
@@ -400,6 +421,7 @@ impl EditorView {
400421 view: &View,
401422 theme: &Theme,
402423 cursor_shape_config: &CursorShapeConfig,
424+ is_terminal_focused: bool,
403425 ) -> Vec<(usize, std::ops::Range<usize>)> {
404426 let text = doc.text().slice(..);
405427 let selection = doc.selection(view.id);
@@ -447,7 +469,7 @@ impl EditorView {
447469
448470 // Special-case: cursor at end of the rope.
449471 if range.head == range.anchor && range.head == text.len_chars() {
450− if !selection_is_primary || cursor_is_block {
472+ if !selection_is_primary || (cursor_is_block && is_terminal_focused) {
451473 // Bar and underline cursors are drawn by the terminal
452474 // BUG: If the editor area loses focus while having a bar or
453475 // underline cursor (eg. when a regex prompt has focus) then
@@ -470,13 +492,17 @@ impl EditorView {
470492 cursor_start
471493 };
472494 spans.push((selection_scope, range.anchor..selection_end));
473− if !selection_is_primary || cursor_is_block {
495+ // add block cursors
496+ // skip primary cursor if terminal is unfocused - crossterm cursor is used in that case
497+ if !selection_is_primary || (cursor_is_block && is_terminal_focused) {
474498 spans.push((cursor_scope, cursor_start..range.head));
475499 }
476500 } else {
477501 // Reverse case.
478502 let cursor_end = next_grapheme_boundary(text, range.head);
479− if !selection_is_primary || cursor_is_block {
503+ // add block cursors
504+ // skip primary cursor if terminal is unfocused - crossterm cursor is used in that case
505+ if !selection_is_primary || (cursor_is_block && is_terminal_focused) {
480506 spans.push((cursor_scope, range.head..cursor_end));
481507 }
482508 // non block cursors look like they exclude the cursor
@@ -1500,8 +1526,15 @@ impl Component for EditorView {
15001526
15011527 fn cursor(&self, _area: Rect, editor: &Editor) -> (Option<Position>, CursorKind) {
15021528 match editor.cursor() {
1503− // All block cursors are drawn manually
1504− (pos, CursorKind::Block) => (pos, CursorKind::Hidden),
1529+ // all block cursors are drawn manually
1530+ (pos, CursorKind::Block) => {
1531+ if self.terminal_focused {
1532+ (pos, CursorKind::Hidden)
1533+ } else {
1534+ // use crossterm cursor when terminal loses focus
1535+ (pos, CursorKind::Underline)
1536+ }
1537+ }
15051538 cursor => cursor,
15061539 }
15071540 }
helix-term/src/ui/lsp.rs+3−1
@@ -92,7 +92,9 @@ impl Component for SignatureHelp {
9292 Some(doc) => Markdown::new(doc.clone(), Arc::clone(&self.config_loader)),
9393 };
9494 let sig_doc = sig_doc.parse(Some(&cx.editor.theme));
95− let sig_doc_area = area.clip_top(sig_text_area.height + 2);
95+ let sig_doc_area = area
96+ .clip_top(sig_text_area.height + 2)
97+ .clip_bottom(u16::from(cx.editor.popup_border()));
9698 let sig_doc_para = Paragraph::new(sig_doc)
9799 .wrap(Wrap { trim: false })
98100 .scroll((cx.scroll.unwrap_or_default() as u16, 0));
helix-term/src/ui/markdown.rs+12−5
@@ -14,6 +14,7 @@ use helix_core::{
1414};
1515use helix_view::{
1616 graphics::{Margin, Rect, Style},
17+ theme::Modifier,
1718 Theme,
1819};
1920
@@ -183,7 +184,9 @@ impl Markdown {
183184 // Transform text in `<code>` blocks into `Event::Code`
184185 let mut in_code = false;
185186 let parser = parser.filter_map(|event| match event {
186− Event::Html(tag) if *tag == *"<code>" => {
187+ Event::Html(tag)
188+ if tag.starts_with("<code") && matches!(tag.chars().nth(5), Some(' ' | '>')) =>
189+ {
187190 in_code = true;
188191 None
189192 }
@@ -275,17 +278,21 @@ impl Markdown {
275278 );
276279 lines.extend(tui_text.lines.into_iter());
277280 } else {
278− let style = if let Some(Tag::Heading(level, ..)) = tags.last() {
279− match level {
281+ let style = match tags.last() {
282+ Some(Tag::Heading(level, ..)) => match level {
280283 HeadingLevel::H1 => heading_styles[0],
281284 HeadingLevel::H2 => heading_styles[1],
282285 HeadingLevel::H3 => heading_styles[2],
283286 HeadingLevel::H4 => heading_styles[3],
284287 HeadingLevel::H5 => heading_styles[4],
285288 HeadingLevel::H6 => heading_styles[5],
289+ },
290+ Some(Tag::Emphasis) => text_style.add_modifier(Modifier::ITALIC),
291+ Some(Tag::Strong) => text_style.add_modifier(Modifier::BOLD),
292+ Some(Tag::Strikethrough) => {
293+ text_style.add_modifier(Modifier::CROSSED_OUT)
286294 }
287− } else {
288− text_style
295+ _ => text_style,
289296 };
290297 spans.push(Span::styled(text, style));
291298 }
helix-term/src/ui/menu.rs+37−16
@@ -5,13 +5,20 @@ use crate::{
55 ctrl, key, shift,
66};
77use helix_core::fuzzy::MATCHER;
8−use nucleo::pattern::{AtomKind, CaseMatching, Pattern};
8+use nucleo::pattern::{Atom, AtomKind, CaseMatching};
99use nucleo::{Config, Utf32Str};
10−use tui::{buffer::Buffer as Surface, widgets::Table};
10+use tui::{
11+ buffer::Buffer as Surface,
12+ widgets::{Block, Borders, Table, Widget},
13+};
1114
1215pub use tui::widgets::{Cell, Row};
1316
14−use helix_view::{editor::SmartTabConfig, graphics::Rect, Editor};
17+use helix_view::{
18+ editor::SmartTabConfig,
19+ graphics::{Margin, Rect},
20+ Editor,
21+};
1522use tui::layout::Constraint;
1623
1724pub trait Item: Sync + Send + 'static {
@@ -94,13 +101,13 @@ impl<T: Item> Menu<T> {
94101 self.matches.clear();
95102 let mut matcher = MATCHER.lock();
96103 matcher.config = Config::DEFAULT;
97− let pattern = Pattern::new(pattern, CaseMatching::Ignore, AtomKind::Fuzzy);
104+ let pattern = Atom::new(pattern, CaseMatching::Ignore, AtomKind::Fuzzy, false);
98105 let mut buf = Vec::new();
99106 let matches = self.options.iter().enumerate().filter_map(|(i, option)| {
100107 let text = option.filter_text(&self.editor_data);
101108 pattern
102109 .score(Utf32Str::new(&text, &mut buf), &mut matcher)
103− .map(|score| (i as u32, score))
110+ .map(|score| (i as u32, score as u32))
104111 });
105112 self.matches.extend(matches);
106113 self.matches
@@ -322,6 +329,15 @@ impl<T: Item + 'static> Component for Menu<T> {
322329 let selected = theme.get("ui.menu.selected");
323330 surface.clear_with(area, style);
324331
332+ let render_borders = cx.editor.menu_border();
333+
334+ let area = if render_borders {
335+ Widget::render(Block::default().borders(Borders::ALL), area, surface);
336+ area.inner(&Margin::vertical(1))
337+ } else {
338+ area
339+ };
340+
325341 let scroll = self.scroll;
326342
327343 let options: Vec<_> = self
@@ -362,15 +378,19 @@ impl<T: Item + 'static> Component for Menu<T> {
362378 false,
363379 );
364380
365− if let Some(cursor) = self.cursor {
366− let offset_from_top = cursor - scroll;
367− let left = &mut surface[(area.left(), area.y + offset_from_top as u16)];
368− left.set_style(selected);
369− let right = &mut surface[(
370− area.right().saturating_sub(1),
371− area.y + offset_from_top as u16,
372− )];
373− right.set_style(selected);
381+ let render_borders = cx.editor.menu_border();
382+
383+ if !render_borders {
384+ if let Some(cursor) = self.cursor {
385+ let offset_from_top = cursor - scroll;
386+ let left = &mut surface[(area.left(), area.y + offset_from_top as u16)];
387+ left.set_style(selected);
388+ let right = &mut surface[(
389+ area.right().saturating_sub(1),
390+ area.y + offset_from_top as u16,
391+ )];
392+ right.set_style(selected);
393+ }
374394 }
375395
376396 let fits = len <= win_height;
@@ -385,12 +405,13 @@ impl<T: Item + 'static> Component for Menu<T> {
385405 for i in 0..win_height {
386406 cell = &mut surface[(area.right() - 1, area.top() + i as u16)];
387407
388− cell.set_symbol("▐"); // right half block
408+ let half_block = if render_borders { "▌" } else { "▐" };
389409
390410 if scroll_line <= i && i < scroll_line + scroll_height {
391411 // Draw scroll thumb
412+ cell.set_symbol(half_block);
392413 cell.set_fg(scroll_style.fg.unwrap_or(helix_view::theme::Color::Reset));
393− } else {
414+ } else if !render_borders {
394415 // Draw scroll track
395416 cell.set_fg(scroll_style.bg.unwrap_or(helix_view::theme::Color::Reset));
396417 }
helix-term/src/ui/mod.rs+24−7
@@ -177,6 +177,9 @@ pub fn file_picker(root: PathBuf, config: &helix_view::editor::Config) -> Picker
177177 .max_depth(config.file_picker.max_depth)
178178 .filter_entry(move |entry| filter_picker_entry(entry, &absolute_root, dedup_symlinks));
179179
180+ walk_builder.add_custom_ignore_filename(helix_loader::config_dir().join("ignore"));
181+ walk_builder.add_custom_ignore_filename(".helix/ignore");
182+
180183 // We want to exclude files that the editor can't handle yet
181184 let mut type_builder = TypesBuilder::new();
182185 type_builder
@@ -190,7 +193,7 @@ pub fn file_picker(root: PathBuf, config: &helix_view::editor::Config) -> Picker
190193 .build()
191194 .expect("failed to build excluded_types");
192195 walk_builder.types(excluded_types);
193− let files = walk_builder.build().filter_map(|entry| {
196+ let mut files = walk_builder.build().filter_map(|entry| {
194197 let entry = entry.ok()?;
195198 if !entry.file_type()?.is_file() {
196199 return None;
@@ -211,13 +214,27 @@ pub fn file_picker(root: PathBuf, config: &helix_view::editor::Config) -> Picker
211214 })
212215 .with_preview(|_editor, path| Some((path.clone().into(), None)));
213216 let injector = picker.injector();
214− std::thread::spawn(move || {
215− for file in files {
216− if injector.push(file).is_err() {
217− break;
218− }
217+ let timeout = std::time::Instant::now() + std::time::Duration::from_millis(30);
218+
219+ let mut hit_timeout = false;
220+ for file in &mut files {
221+ if injector.push(file).is_err() {
222+ break;
219223 }
220− });
224+ if std::time::Instant::now() >= timeout {
225+ hit_timeout = true;
226+ break;
227+ }
228+ }
229+ if hit_timeout {
230+ std::thread::spawn(move || {
231+ for file in files {
232+ if injector.push(file).is_err() {
233+ break;
234+ }
235+ }
236+ });
237+ }
221238 picker
222239}
223240
helix-term/src/ui/picker.rs+51−24
@@ -112,9 +112,9 @@ impl Preview<'_, '_> {
112112 /// Alternate text to show for the preview.
113113 fn placeholder(&self) -> &str {
114114 match *self {
115− Self::EditorDocument(_) => "<File preview>",
115+ Self::EditorDocument(_) => "<Invalid file location>",
116116 Self::Cached(preview) => match preview {
117− CachedPreview::Document(_) => "<File preview>",
117+ CachedPreview::Document(_) => "<Invalid file location>",
118118 CachedPreview::Binary => "<Binary file>",
119119 CachedPreview::LargeFile => "<File too large to preview>",
120120 CachedPreview::NotFound => "<File not found>",
@@ -156,7 +156,7 @@ impl<T: Item> Clone for Injector<T> {
156156 Injector {
157157 dst: self.dst.clone(),
158158 editor_data: self.editor_data.clone(),
159− shutown: Arc::new(AtomicBool::new(false)),
159+ shutown: self.shutown.clone(),
160160 }
161161 }
162162}
@@ -474,9 +474,13 @@ impl<T: Item + 'static> Picker<T> {
474474 log::info!("highlighting picker item failed");
475475 return;
476476 };
477− let Some(Overlay {
478− content: picker, ..
479− }) = compositor.find::<Overlay<Self>>()
477+ let picker = match compositor.find::<Overlay<Self>>() {
478+ Some(Overlay { content, .. }) => Some(content),
479+ None => compositor
480+ .find::<Overlay<DynamicPicker<T>>>()
481+ .map(|overlay| &mut overlay.content.file_picker),
482+ };
483+ let Some(picker) = picker
480484 else {
481485 log::info!("picker closed before syntax highlighting finished");
482486 return;
@@ -689,8 +693,14 @@ impl<T: Item + 'static> Picker<T> {
689693 if let Some((path, range)) = self.current_file(cx.editor) {
690694 let preview = self.get_preview(path, cx.editor);
691695 let doc = match preview.document() {
692− Some(doc) => doc,
693− None => {
696+ Some(doc)
697+ if range.map_or(true, |(start, end)| {
698+ start <= end && end <= doc.text().len_lines()
699+ }) =>
700+ {
701+ doc
702+ }
703+ _ => {
694704 let alt_text = preview.placeholder();
695705 let x = inner.x + inner.width.saturating_sub(alt_text.len() as u16) / 2;
696706 let y = inner.y + inner.height / 2;
@@ -700,31 +710,46 @@ impl<T: Item + 'static> Picker<T> {
700710 };
701711
702712 let mut offset = ViewPosition::default();
703− if let Some(range) = range {
704− let text_fmt = doc.text_format(inner.width, None);
705− let annotations = TextAnnotations::default();
706− (offset.anchor, offset.vertical_offset) = char_idx_at_visual_offset(
707− doc.text().slice(..),
708− doc.text().line_to_char(range.0),
709− // align to middle
710− -(inner.height as isize / 2),
711− 0,
712− &text_fmt,
713− &annotations,
714− );
713+ if let Some((start_line, end_line)) = range {
714+ let height = end_line - start_line;
715+ let text = doc.text().slice(..);
716+ let start = text.line_to_char(start_line);
717+ let middle = text.line_to_char(start_line + height / 2);
718+ if height < inner.height as usize {
719+ let text_fmt = doc.text_format(inner.width, None);
720+ let annotations = TextAnnotations::default();
721+ (offset.anchor, offset.vertical_offset) = char_idx_at_visual_offset(
722+ text,
723+ middle,
724+ // align to middle
725+ -(inner.height as isize / 2),
726+ 0,
727+ &text_fmt,
728+ &annotations,
729+ );
730+ if start < offset.anchor {
731+ offset.anchor = start;
732+ offset.vertical_offset = 0;
733+ }
734+ } else {
735+ offset.anchor = start;
736+ }
715737 }
716738
717− let mut highlights = EditorView::doc_syntax_highlights(
739+ let syntax_highlights = EditorView::doc_syntax_highlights(
718740 doc,
719741 offset.anchor,
720742 area.height,
721743 &cx.editor.theme,
722744 );
745+
746+ let mut overlay_highlights =
747+ EditorView::empty_highlight_iter(doc, offset.anchor, area.height);
723748 for spans in EditorView::doc_diagnostics_highlights(doc, &cx.editor.theme) {
724749 if spans.is_empty() {
725750 continue;
726751 }
727− highlights = Box::new(helix_core::syntax::merge(highlights, spans));
752+ overlay_highlights = Box::new(helix_core::syntax::merge(overlay_highlights, spans));
728753 }
729754 let mut decorations: Vec<Box<dyn LineDecoration>> = Vec::new();
730755
@@ -755,7 +780,8 @@ impl<T: Item + 'static> Picker<T> {
755780 offset,
756781 // TODO: compute text annotations asynchronously here (like inlay hints)
757782 &TextAnnotations::default(),
758− highlights,
783+ syntax_highlights,
784+ overlay_highlights,
759785 &cx.editor.theme,
760786 &mut decorations,
761787 &mut [],
@@ -773,7 +799,8 @@ impl<T: Item + 'static + Send + Sync> Component for Picker<T> {
773799 // | | | |
774800 // +---------+ +---------+
775801
776− let render_preview = self.show_preview && area.width > MIN_AREA_WIDTH_FOR_PREVIEW;
802+ let render_preview =
803+ self.show_preview && self.file_fn.is_some() && area.width > MIN_AREA_WIDTH_FOR_PREVIEW;
777804
778805 let picker_width = if render_preview {
779806 area.width / 2
helix-term/src/ui/popup.rs+27−7
@@ -3,7 +3,10 @@ use crate::{
33 compositor::{Callback, Component, Context, Event, EventResult},
44 ctrl, key,
55};
6−use tui::buffer::Buffer as Surface;
6+use tui::{
7+ buffer::Buffer as Surface,
8+ widgets::{Block, Borders, Widget},
9+};
710
811use helix_core::Position;
912use helix_view::{
@@ -252,13 +255,29 @@ impl<T: Component> Component for Popup<T> {
252255 let background = cx.editor.theme.get("ui.popup");
253256 surface.clear_with(area, background);
254257
255− let inner = area.inner(&self.margin);
258+ let render_borders = cx.editor.popup_border();
259+
260+ let inner = if self
261+ .contents
262+ .type_name()
263+ .starts_with("helix_term::ui::menu::Menu")
264+ {
265+ area
266+ } else {
267+ area.inner(&self.margin)
268+ };
269+
270+ let border = usize::from(render_borders);
271+ if render_borders {
272+ Widget::render(Block::default().borders(Borders::ALL), area, surface);
273+ }
274+
256275 self.contents.render(inner, surface, cx);
257276
258277 // render scrollbar if contents do not fit
259278 if self.has_scrollbar {
260− let win_height = inner.height as usize;
261− let len = self.child_size.1 as usize;
279+ let win_height = (inner.height as usize).saturating_sub(2 * border);
280+ let len = (self.child_size.1 as usize).saturating_sub(2 * border);
262281 let fits = len <= win_height;
263282 let scroll = self.scroll;
264283 let scroll_style = cx.editor.theme.get("ui.menu.scroll");
@@ -274,14 +293,15 @@ impl<T: Component> Component for Popup<T> {
274293
275294 let mut cell;
276295 for i in 0..win_height {
277− cell = &mut surface[(inner.right() - 1, inner.top() + i as u16)];
296+ cell = &mut surface[(inner.right() - 1, inner.top() + (border + i) as u16)];
278297
279− cell.set_symbol("▐"); // right half block
298+ let half_block = if render_borders { "▌" } else { "▐" };
280299
281300 if scroll_line <= i && i < scroll_line + scroll_height {
282301 // Draw scroll thumb
302+ cell.set_symbol(half_block);
283303 cell.set_fg(scroll_style.fg.unwrap_or(helix_view::theme::Color::Reset));
284− } else {
304+ } else if !render_borders {
285305 // Draw scroll track
286306 cell.set_fg(scroll_style.bg.unwrap_or(helix_view::theme::Color::Reset));
287307 }
helix-term/tests/test/commands.rs+46
@@ -480,3 +480,49 @@ fn bar() {#(\n|)#\
480480
481481 Ok(())
482482}
483+
484+#[tokio::test(flavor = "multi_thread")]
485+async fn test_join_selections() -> anyhow::Result<()> {
486+ // normal join
487+ test((
488+ platform_line(indoc! {"\
489+ #[a|]#bc
490+ def
491+ "}),
492+ "J",
493+ platform_line(indoc! {"\
494+ #[a|]#bc def
495+ "}),
496+ ))
497+ .await?;
498+
499+ // join with empty line
500+ test((
501+ platform_line(indoc! {"\
502+ #[a|]#bc
503+
504+ def
505+ "}),
506+ "JJ",
507+ platform_line(indoc! {"\
508+ #[a|]#bc def
509+ "}),
510+ ))
511+ .await?;
512+
513+ // join with additional space in non-empty line
514+ test((
515+ platform_line(indoc! {"\
516+ #[a|]#bc
517+
518+ def
519+ "}),
520+ "JJ",
521+ platform_line(indoc! {"\
522+ #[a|]#bc def
523+ "}),
524+ ))
525+ .await?;
526+
527+ Ok(())
528+}
helix-term/tests/test/commands/write.rs+122−3
@@ -93,7 +93,7 @@ async fn test_buffer_close_concurrent() -> anyhow::Result<()> {
9393 )
9494 .await?;
9595
96− helpers::assert_file_has_content(file.as_file_mut(), &RANGE.end().to_string())?;
96+ helpers::assert_file_has_content(file.as_file_mut(), &platform_line(&RANGE.end().to_string()))?;
9797
9898 Ok(())
9999}
@@ -209,7 +209,7 @@ async fn test_write_concurrent() -> anyhow::Result<()> {
209209
210210 let mut file_content = String::new();
211211 file.as_file_mut().read_to_string(&mut file_content)?;
212− assert_eq!(RANGE.end().to_string(), file_content);
212+ assert_eq!(platform_line(&RANGE.end().to_string()), file_content);
213213
214214 Ok(())
215215}
@@ -424,13 +424,132 @@ async fn test_write_utf_bom_file() -> anyhow::Result<()> {
424424 Ok(())
425425}
426426
427+#[tokio::test(flavor = "multi_thread")]
428+async fn test_write_insert_final_newline_added_if_missing() -> anyhow::Result<()> {
429+ let mut file = tempfile::NamedTempFile::new()?;
430+ let mut app = helpers::AppBuilder::new()
431+ .with_file(file.path(), None)
432+ .with_input_text("#[h|]#ave you tried chamomile tea?")
433+ .build()?;
434+
435+ test_key_sequence(&mut app, Some(":w<ret>"), None, false).await?;
436+
437+ helpers::assert_file_has_content(
438+ file.as_file_mut(),
439+ &helpers::platform_line("have you tried chamomile tea?\n"),
440+ )?;
441+
442+ Ok(())
443+}
444+
445+#[tokio::test(flavor = "multi_thread")]
446+async fn test_write_insert_final_newline_unchanged_if_not_missing() -> anyhow::Result<()> {
447+ let mut file = tempfile::NamedTempFile::new()?;
448+ let mut app = helpers::AppBuilder::new()
449+ .with_file(file.path(), None)
450+ .with_input_text(&helpers::platform_line("#[t|]#en minutes, please\n"))
451+ .build()?;
452+
453+ test_key_sequence(&mut app, Some(":w<ret>"), None, false).await?;
454+
455+ helpers::assert_file_has_content(
456+ file.as_file_mut(),
457+ &helpers::platform_line("ten minutes, please\n"),
458+ )?;
459+
460+ Ok(())
461+}
462+
463+#[tokio::test(flavor = "multi_thread")]
464+async fn test_write_insert_final_newline_unchanged_if_missing_and_false() -> anyhow::Result<()> {
465+ let mut file = tempfile::NamedTempFile::new()?;
466+ let mut app = helpers::AppBuilder::new()
467+ .with_config(Config {
468+ editor: helix_view::editor::Config {
469+ insert_final_newline: false,
470+ ..Default::default()
471+ },
472+ ..Default::default()
473+ })
474+ .with_file(file.path(), None)
475+ .with_input_text("#[t|]#he quiet rain continued through the night")
476+ .build()?;
477+
478+ test_key_sequence(&mut app, Some(":w<ret>"), None, false).await?;
479+
480+ helpers::assert_file_has_content(
481+ file.as_file_mut(),
482+ "the quiet rain continued through the night",
483+ )?;
484+
485+ Ok(())
486+}
487+
488+#[tokio::test(flavor = "multi_thread")]
489+async fn test_write_all_insert_final_newline_add_if_missing_and_modified() -> anyhow::Result<()> {
490+ let mut file1 = tempfile::NamedTempFile::new()?;
491+ let mut file2 = tempfile::NamedTempFile::new()?;
492+ let mut app = helpers::AppBuilder::new()
493+ .with_file(file1.path(), None)
494+ .with_input_text("#[w|]#e don't serve time travelers here")
495+ .build()?;
496+
497+ test_key_sequence(
498+ &mut app,
499+ Some(&format!(
500+ ":o {}<ret>ia time traveler walks into a bar<esc>:wa<ret>",
501+ file2.path().to_string_lossy()
502+ )),
503+ None,
504+ false,
505+ )
506+ .await?;
507+
508+ helpers::assert_file_has_content(
509+ file1.as_file_mut(),
510+ &helpers::platform_line("we don't serve time travelers here\n"),
511+ )?;
512+
513+ helpers::assert_file_has_content(
514+ file2.as_file_mut(),
515+ &helpers::platform_line("a time traveler walks into a bar\n"),
516+ )?;
517+
518+ Ok(())
519+}
520+
521+#[tokio::test(flavor = "multi_thread")]
522+async fn test_write_all_insert_final_newline_do_not_add_if_unmodified() -> anyhow::Result<()> {
523+ let mut file = tempfile::NamedTempFile::new()?;
524+ let mut app = helpers::AppBuilder::new()
525+ .with_file(file.path(), None)
526+ .build()?;
527+
528+ file.write_all(b"i lost on Jeopardy!")?;
529+ file.rewind()?;
530+
531+ test_key_sequence(&mut app, Some(":wa<ret>"), None, false).await?;
532+
533+ helpers::assert_file_has_content(file.as_file_mut(), "i lost on Jeopardy!")?;
534+
535+ Ok(())
536+}
537+
427538async fn edit_file_with_content(file_content: &[u8]) -> anyhow::Result<()> {
428539 let mut file = tempfile::NamedTempFile::new()?;
429540
430541 file.as_file_mut().write_all(&file_content)?;
431542
432543 helpers::test_key_sequence(
433− &mut helpers::AppBuilder::new().build()?,
544+ &mut helpers::AppBuilder::new()
545+ .with_config(Config {
546+ editor: helix_view::editor::Config {
547+ insert_final_newline: false,
548+ ..Default::default()
549+ },
550+ ..Default::default()
551+ })
552+ .build()?,
434553 Some(&format!(":o {}<ret>:x<ret>", file.path().to_string_lossy())),
435554 None,
436555 true,
helix-term/tests/test/helpers.rs+9−1
@@ -320,6 +320,14 @@ impl AppBuilder {
320320 }
321321
322322 pub fn build(self) -> anyhow::Result<Application> {
323+ if let Some(path) = &self.args.working_directory {
324+ bail!("Changing the working directory to {path:?} is not yet supported for integration tests");
325+ }
326+
327+ if let Some((path, _)) = self.args.files.first().filter(|p| p.0.is_dir()) {
328+ bail!("Having the directory {path:?} in args.files[0] is not yet supported for integration tests");
329+ }
330+
323331 let mut app = Application::new(self.args, self.config, self.syn_conf)?;
324332
325333 if let Some((text, selection)) = self.input {
@@ -350,7 +358,7 @@ pub fn assert_file_has_content(file: &mut File, content: &str) -> anyhow::Result
350358
351359 let mut file_content = String::new();
352360 file.read_to_string(&mut file_content)?;
353− assert_eq!(content, file_content);
361+ assert_eq!(file_content, content);
354362
355363 Ok(())
356364}
helix-term/tests/test/splits.rs+3−3
@@ -62,9 +62,9 @@ async fn test_split_write_quit_all() -> anyhow::Result<()> {
6262 )
6363 .await?;
6464
65− helpers::assert_file_has_content(file1.as_file_mut(), "hello1")?;
66− helpers::assert_file_has_content(file2.as_file_mut(), "hello2")?;
67− helpers::assert_file_has_content(file3.as_file_mut(), "hello3")?;
65+ helpers::assert_file_has_content(file1.as_file_mut(), &platform_line("hello1"))?;
66+ helpers::assert_file_has_content(file2.as_file_mut(), &platform_line("hello2"))?;
67+ helpers::assert_file_has_content(file3.as_file_mut(), &platform_line("hello3"))?;
6868
6969 Ok(())
7070}
helix-tui/Cargo.toml+13−13
@@ -1,28 +1,28 @@
11[package]
22name = "helix-tui"
3−version = "0.6.0"
4−authors = ["Blaž Hrastnik <blaz@mxxn.io>"]
5−description = """
6−A library to build rich terminal user interfaces or dashboards
7−"""
8−edition = "2021"
9−license = "MPL-2.0"
10−categories = ["editor"]
11−repository = "https://github.com/helix-editor/helix"
12−homepage = "https://helix-editor.com"
3+description = """A library to build rich terminal user interfaces or dashboards"""
134include = ["src/**/*", "README.md"]
5+version.workspace = true
6+authors.workspace = true
7+edition.workspace = true
8+license.workspace = true
9+rust-version.workspace = true
10+categories.workspace = true
11+repository.workspace = true
12+homepage.workspace = true
1413
1514[features]
1615default = ["crossterm"]
1716
1817[dependencies]
18+helix-view = { path = "../helix-view", features = ["term"] }
19+helix-core = { path = "../helix-core" }
20+
1921bitflags = "2.4"
2022cassowary = "0.3"
2123unicode-segmentation = "1.10"
2224crossterm = { version = "0.27", optional = true }
2325termini = "1.0"
2426serde = { version = "1", "optional" = true, features = ["derive"]}
25−once_cell = "1.18"
27+once_cell = "1.19"
2628log = "~0.4"
27−helix-view = { version = "0.6", path = "../helix-view", features = ["term"] }
28−helix-core = { version = "0.6", path = "../helix-core" }
helix-tui/src/backend/crossterm.rs+18−2
@@ -32,10 +32,21 @@ fn vte_version() -> Option<usize> {
3232}
3333
3434/// Describes terminal capabilities like extended underline, truecolor, etc.
35−#[derive(Copy, Clone, Debug, Default)]
35+#[derive(Clone, Debug)]
3636struct Capabilities {
3737 /// Support for undercurled, underdashed, etc.
3838 has_extended_underlines: bool,
39+ /// Support for resetting the cursor style back to normal.
40+ reset_cursor_command: String,
41+}
42+
43+impl Default for Capabilities {
44+ fn default() -> Self {
45+ Self {
46+ has_extended_underlines: false,
47+ reset_cursor_command: "\x1B[0 q".to_string(),
48+ }
49+ }
3950}
4051
4152impl Capabilities {
@@ -54,6 +65,10 @@ impl Capabilities {
5465 || t.extended_cap("Su").is_some()
5566 || vte_version() >= Some(5102)
5667 || matches!(term_program().as_deref(), Some("WezTerm")),
68+ reset_cursor_command: t
69+ .utf8_string_cap(termini::StringCapability::CursorNormal)
70+ .unwrap_or("\x1B[0 q")
71+ .to_string(),
5772 },
5873 }
5974 }
@@ -154,7 +169,8 @@ where
154169
155170 fn restore(&mut self, config: Config) -> io::Result<()> {
156171 // reset cursor shape
157− write!(self.buffer, "\x1B[0 q")?;
172+ self.buffer
173+ .write_all(self.capabilities.reset_cursor_command.as_bytes())?;
158174 if config.enable_mouse_capture {
159175 execute!(self.buffer, DisableMouseCapture)?;
160176 }
helix-tui/src/buffer.rs+2−2
@@ -213,7 +213,7 @@ impl Buffer {
213213 && y < self.area.bottom()
214214 }
215215
216− /// Returns the index in the Vec<Cell> for the given global (x, y) coordinates.
216+ /// Returns the index in the `Vec<Cell>` for the given global (x, y) coordinates.
217217 ///
218218 /// Global coordinates are offset by the Buffer's area offset (`x`/`y`).
219219 ///
@@ -242,7 +242,7 @@ impl Buffer {
242242 ((y - self.area.y) as usize) * (self.area.width as usize) + ((x - self.area.x) as usize)
243243 }
244244
245− /// Returns the index in the Vec<Cell> for the given global (x, y) coordinates,
245+ /// Returns the index in the `Vec<Cell>` for the given global (x, y) coordinates,
246246 /// or `None` if the coordinates are outside the buffer's area.
247247 fn index_of_opt(&self, x: u16, y: u16) -> Option<usize> {
248248 if self.in_bounds(x, y) {
helix-vcs/Cargo.toml+12−11
@@ -1,24 +1,25 @@
11[package]
22name = "helix-vcs"
3−version = "0.6.0"
4−authors = ["Blaž Hrastnik <blaz@mxxn.io>"]
5−edition = "2021"
6−license = "MPL-2.0"
7−categories = ["editor"]
8−repository = "https://github.com/helix-editor/helix"
9−homepage = "https://helix-editor.com"
3+version.workspace = true
4+authors.workspace = true
5+edition.workspace = true
6+license.workspace = true
7+rust-version.workspace = true
8+categories.workspace = true
9+repository.workspace = true
10+homepage.workspace = true
1011
1112# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1213
1314[dependencies]
14−helix-core = { version = "0.6", path = "../helix-core" }
15−helix-event = { version = "0.6", path = "../helix-event" }
15+helix-core = { path = "../helix-core" }
16+helix-event = { path = "../helix-event" }
1617
1718tokio = { version = "1", features = ["rt", "rt-multi-thread", "time", "sync", "parking_lot", "macros"] }
1819parking_lot = "0.12"
1920arc-swap = { version = "1.6.0" }
2021
21−gix = { version = "0.48.0", default-features = false , optional = true }
22+gix = { version = "0.57.0", default-features = false , optional = true }
2223imara-diff = "0.1.5"
2324anyhow = "1"
2425
@@ -28,4 +29,4 @@ log = "0.4"
2829git = ["gix"]
2930
3031[dev-dependencies]
31−tempfile = "3.8"
32+tempfile = "3.8"
helix-vcs/src/git.rs+5−5
@@ -3,7 +3,7 @@ use arc_swap::ArcSwap;
33use std::path::Path;
44use std::sync::Arc;
55
6−use gix::objs::tree::EntryMode;
6+use gix::objs::tree::EntryKind;
77use gix::sec::trust::DefaultForLevel;
88use gix::{Commit, ObjectId, Repository, ThreadSafeRepository};
99
@@ -126,14 +126,14 @@ fn find_file_in_commit(repo: &Repository, commit: &Commit, file: &Path) -> Resul
126126 let rel_path = file.strip_prefix(repo_dir)?;
127127 let tree = commit.tree()?;
128128 let tree_entry = tree
129− .lookup_entry_by_path(rel_path)?
129+ .lookup_entry_by_path(rel_path, &mut Vec::new())?
130130 .context("file is untracked")?;
131− match tree_entry.mode() {
131+ match tree_entry.mode().kind() {
132132 // not a file, everything is new, do not show diff
133− mode @ (EntryMode::Tree | EntryMode::Commit | EntryMode::Link) => {
133+ mode @ (EntryKind::Tree | EntryKind::Commit | EntryKind::Link) => {
134134 bail!("entry at {} is not a file but a {mode:?}", file.display())
135135 }
136136 // found a file
137− EntryMode::Blob | EntryMode::BlobExecutable => Ok(tree_entry.object_id()),
137+ EntryKind::Blob | EntryKind::BlobExecutable => Ok(tree_entry.object_id()),
138138 }
139139}
helix-view/Cargo.toml+19−17
@@ -1,32 +1,34 @@
11[package]
22name = "helix-view"
3−version = "0.6.0"
4−authors = ["Blaž Hrastnik <blaz@mxxn.io>"]
5−edition = "2021"
6−license = "MPL-2.0"
73description = "UI abstractions for use in backends"
8−categories = ["editor"]
9−repository = "https://github.com/helix-editor/helix"
10−homepage = "https://helix-editor.com"
4+version.workspace = true
5+authors.workspace = true
6+edition.workspace = true
7+license.workspace = true
8+rust-version.workspace = true
9+categories.workspace = true
10+repository.workspace = true
11+homepage.workspace = true
1112
1213[features]
1314default = []
1415term = ["crossterm"]
1516
1617[dependencies]
18+helix-core = { path = "../helix-core" }
19+helix-event = { path = "../helix-event" }
20+helix-loader = { path = "../helix-loader" }
21+helix-lsp = { path = "../helix-lsp" }
22+helix-dap = { path = "../helix-dap" }
23+helix-vcs = { path = "../helix-vcs" }
24+
1725bitflags = "2.4"
1826anyhow = "1"
19−helix-core = { version = "0.6", path = "../helix-core" }
20−helix-event = { version = "0.6", path = "../helix-event" }
21−helix-loader = { version = "0.6", path = "../helix-loader" }
22−helix-lsp = { version = "0.6", path = "../helix-lsp" }
23−helix-dap = { version = "0.6", path = "../helix-dap" }
2427crossterm = { version = "0.27", optional = true }
25−helix-vcs = { version = "0.6", path = "../helix-vcs" }
2628
2729# Conversion traits
28−once_cell = "1.18"
29−url = "2"
30+once_cell = "1.19"
31+url = "2.5.0"
3032
3133arc-swap = { version = "1.6.0" }
3234
@@ -43,12 +45,12 @@ serde_json = "1.0"
4345toml = "0.7"
4446log = "~0.4"
4547
46−which = "4.4"
48+which = "5.0.0"
4749parking_lot = "0.12.1"
4850
4951
5052[target.'cfg(windows)'.dependencies]
51−clipboard-win = { version = "4.5", features = ["std"] }
53+clipboard-win = { version = "5.0", features = ["std"] }
5254
5355[target.'cfg(unix)'.dependencies]
5456libc = "0.2"
helix-view/src/document.rs+58−21
@@ -1206,30 +1206,47 @@ impl Document {
12061206 transaction.changes(),
12071207 );
12081208 if res.is_err() {
1209− log::error!("TS parser failed, disabeling TS for the current buffer: {res:?}");
1209+ log::error!("TS parser failed, disabling TS for the current buffer: {res:?}");
12101210 self.syntax = None;
12111211 }
12121212 }
12131213
12141214 let changes = transaction.changes();
12151215
1216− changes.update_positions(
1217− self.diagnostics
1218− .iter_mut()
1219− .map(|diagnostic| (&mut diagnostic.range.start, Assoc::After)),
1220− );
1221− changes.update_positions(
1222− self.diagnostics
1223− .iter_mut()
1224− .map(|diagnostic| (&mut diagnostic.range.end, Assoc::After)),
1225− );
1226− // map state.diagnostics over changes::map_pos too
1227− for diagnostic in &mut self.diagnostics {
1216+ // map diagnostics over changes too
1217+ changes.update_positions(self.diagnostics.iter_mut().map(|diagnostic| {
1218+ let assoc = if diagnostic.starts_at_word {
1219+ Assoc::BeforeWord
1220+ } else {
1221+ Assoc::After
1222+ };
1223+ (&mut diagnostic.range.start, assoc)
1224+ }));
1225+ changes.update_positions(self.diagnostics.iter_mut().map(|diagnostic| {
1226+ let assoc = if diagnostic.ends_at_word {
1227+ Assoc::AfterWord
1228+ } else {
1229+ Assoc::Before
1230+ };
1231+ (&mut diagnostic.range.end, assoc)
1232+ }));
1233+ self.diagnostics.retain_mut(|diagnostic| {
1234+ if diagnostic.range.start > diagnostic.range.end
1235+ || (!diagnostic.zero_width && diagnostic.range.start == diagnostic.range.end)
1236+ {
1237+ return false;
1238+ }
12281239 diagnostic.line = self.text.char_to_line(diagnostic.range.start);
1229− }
1240+ true
1241+ });
12301242
1231− self.diagnostics
1232− .sort_unstable_by_key(|diagnostic| diagnostic.range);
1243+ self.diagnostics.sort_unstable_by_key(|diagnostic| {
1244+ (
1245+ diagnostic.range,
1246+ diagnostic.severity,
1247+ diagnostic.language_server_id,
1248+ )
1249+ });
12331250
12341251 // Update the inlay hint annotations' positions, helping ensure they are displayed in the proper place
12351252 let apply_inlay_hint_changes = |annotations: &mut Rc<[InlineAnnotation]>| {
@@ -1706,13 +1723,33 @@ impl Document {
17061723
17071724 pub fn replace_diagnostics(
17081725 &mut self,
1709− mut diagnostics: Vec<Diagnostic>,
1726+ diagnostics: impl IntoIterator<Item = Diagnostic>,
1727+ unchanged_sources: &[String],
17101728 language_server_id: usize,
17111729 ) {
1712− self.clear_diagnostics(language_server_id);
1713− self.diagnostics.append(&mut diagnostics);
1714− self.diagnostics
1715− .sort_unstable_by_key(|diagnostic| diagnostic.range);
1730+ if unchanged_sources.is_empty() {
1731+ self.clear_diagnostics(language_server_id);
1732+ } else {
1733+ self.diagnostics.retain(|d| {
1734+ if d.language_server_id != language_server_id {
1735+ return true;
1736+ }
1737+
1738+ if let Some(source) = &d.source {
1739+ unchanged_sources.contains(source)
1740+ } else {
1741+ false
1742+ }
1743+ });
1744+ }
1745+ self.diagnostics.extend(diagnostics);
1746+ self.diagnostics.sort_unstable_by_key(|diagnostic| {
1747+ (
1748+ diagnostic.range,
1749+ diagnostic.severity,
1750+ diagnostic.language_server_id,
1751+ )
1752+ });
17161753 }
17171754
17181755 pub fn clear_diagnostics(&mut self, language_server_id: usize) {
helix-view/src/editor.rs+88−56
@@ -42,10 +42,9 @@ use anyhow::{anyhow, bail, Error};
4242pub use helix_core::diagnostic::Severity;
4343use helix_core::{
4444 auto_pairs::AutoPairs,
45− syntax::{self, AutoPairConfig, SoftWrap},
46− Change, LineEnding, NATIVE_LINE_ENDING,
45+ syntax::{self, AutoPairConfig, IndentationHeuristic, SoftWrap},
46+ Change, LineEnding, Position, Selection, NATIVE_LINE_ENDING,
4747};
48−use helix_core::{Position, Selection};
4948use helix_dap as dap;
5049use helix_lsp::lsp;
5150
@@ -244,7 +243,7 @@ pub struct Config {
244243 /// Set a global text_width
245244 pub text_width: usize,
246245 /// Time in milliseconds since last keypress before idle timers trigger.
247− /// Used for autocompletion, set to 0 for instant. Defaults to 400ms.
246+ /// Used for autocompletion, set to 0 for instant. Defaults to 250ms.
248247 #[serde(
249248 serialize_with = "serialize_duration_millis",
250249 deserialize_with = "deserialize_duration_millis"
@@ -287,8 +286,15 @@ pub struct Config {
287286 pub workspace_lsp_roots: Vec<PathBuf>,
288287 /// Which line ending to choose for new documents. Defaults to `native`. i.e. `crlf` on Windows, otherwise `lf`.
289288 pub default_line_ending: LineEndingConfig,
289+ /// Whether to automatically insert a trailing line-ending on write if missing. Defaults to `true`.
290+ pub insert_final_newline: bool,
290291 /// Enables smart tab
291292 pub smart_tab: Option<SmartTabConfig>,
293+ /// Draw border around popups.
294+ pub popup_border: PopupBorderConfig,
295+ /// Which indent heuristic to use when a new line is inserted
296+ #[serde(default)]
297+ pub indent_heuristic: IndentationHeuristic,
292298}
293299
294300#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, Eq, PartialOrd, Ord)]
@@ -725,7 +731,7 @@ pub struct WhitespaceCharacters {
725731impl Default for WhitespaceCharacters {
726732 fn default() -> Self {
727733 Self {
728− space: '·', // U+00B7
734+ space: '·', // U+00B7
729735 nbsp: '⍽', // U+237D
730736 tab: '→', // U+2192
731737 newline: '⏎', // U+23CE
@@ -753,12 +759,13 @@ impl Default for IndentGuidesConfig {
753759}
754760
755761/// Line ending configuration.
756−#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
762+#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
757763#[serde(rename_all = "lowercase")]
758764pub enum LineEndingConfig {
759765 /// The platform's native line ending.
760766 ///
761767 /// `crlf` on Windows, otherwise `lf`.
768+ #[default]
762769 Native,
763770 /// Line feed.
764771 LF,
@@ -775,12 +782,6 @@ pub enum LineEndingConfig {
775782 Nel,
776783}
777784
778−impl Default for LineEndingConfig {
779− fn default() -> Self {
780− LineEndingConfig::Native
781− }
782−}
783−
784785impl From<LineEndingConfig> for LineEnding {
785786 fn from(line_ending: LineEndingConfig) -> Self {
786787 match line_ending {
@@ -797,6 +798,15 @@ impl From<LineEndingConfig> for LineEnding {
797798 }
798799}
799800
801+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
802+#[serde(rename_all = "kebab-case")]
803+pub enum PopupBorderConfig {
804+ None,
805+ All,
806+ Popup,
807+ Menu,
808+}
809+
800810impl Default for Config {
801811 fn default() -> Self {
802812 Self {
@@ -817,7 +827,7 @@ impl Default for Config {
817827 auto_completion: true,
818828 auto_format: true,
819829 auto_save: false,
820− idle_timeout: Duration::from_millis(400),
830+ idle_timeout: Duration::from_millis(250),
821831 preview_completion_insert: true,
822832 completion_trigger_len: 2,
823833 auto_info: true,
@@ -842,7 +852,10 @@ impl Default for Config {
842852 completion_replace: false,
843853 workspace_lsp_roots: Vec::new(),
844854 default_line_ending: LineEndingConfig::default(),
855+ insert_final_newline: true,
845856 smart_tab: Some(SmartTabConfig::default()),
857+ popup_border: PopupBorderConfig::None,
858+ indent_heuristic: IndentationHeuristic::default(),
846859 }
847860 }
848861}
@@ -1062,6 +1075,16 @@ impl Editor {
10621075 }
10631076 }
10641077
1078+ pub fn popup_border(&self) -> bool {
1079+ self.config().popup_border == PopupBorderConfig::All
1080+ || self.config().popup_border == PopupBorderConfig::Popup
1081+ }
1082+
1083+ pub fn menu_border(&self) -> bool {
1084+ self.config().popup_border == PopupBorderConfig::All
1085+ || self.config().popup_border == PopupBorderConfig::Menu
1086+ }
1087+
10651088 pub fn apply_motion<F: Fn(&mut Self) + 'static>(&mut self, motion: F) {
10661089 motion(self);
10671090 self.last_motion = Some(Box::new(motion));
@@ -1185,71 +1208,80 @@ impl Editor {
11851208 }
11861209
11871210 /// Refreshes the language server for a given document
1188− pub fn refresh_language_servers(&mut self, doc_id: DocumentId) -> Option<()> {
1211+ pub fn refresh_language_servers(&mut self, doc_id: DocumentId) {
11891212 self.launch_language_servers(doc_id)
11901213 }
11911214
11921215 /// Launch a language server for a given document
1193− fn launch_language_servers(&mut self, doc_id: DocumentId) -> Option<()> {
1216+ fn launch_language_servers(&mut self, doc_id: DocumentId) {
11941217 if !self.config().lsp.enable {
1195− return None;
1218+ return;
11961219 }
11971220 // if doc doesn't have a URL it's a scratch buffer, ignore it
1198− let doc = self.documents.get_mut(&doc_id)?;
1199− let doc_url = doc.url()?;
1221+ let Some(doc) = self.documents.get_mut(&doc_id) else {
1222+ return;
1223+ };
1224+ let Some(doc_url) = doc.url() else {
1225+ return;
1226+ };
12001227 let (lang, path) = (doc.language.clone(), doc.path().cloned());
12011228 let config = doc.config.load();
12021229 let root_dirs = &config.workspace_lsp_roots;
12031230
1204− // try to find language servers based on the language name
1205− let language_servers = lang.as_ref().and_then(|language| {
1231+ // store only successfully started language servers
1232+ let language_servers = lang.as_ref().map_or_else(HashMap::default, |language| {
12061233 self.language_servers
12071234 .get(language, path.as_ref(), root_dirs, config.lsp.snippets)
1208− .map_err(|e| {
1209− log::error!(
1210− "Failed to initialize the language servers for `{}` {{ {} }}",
1211− language.scope(),
1212− e
1213− )
1235+ .filter_map(|(lang, client)| match client {
1236+ Ok(client) => Some((lang, client)),
1237+ Err(err) => {
1238+ log::error!(
1239+ "Failed to initialize the language servers for `{}` - `{}` {{ {} }}",
1240+ language.scope(),
1241+ lang,
1242+ err
1243+ );
1244+ None
1245+ }
12141246 })
1215− .ok()
1247+ .collect::<HashMap<_, _>>()
12161248 });
12171249
1218− if let Some(language_servers) = language_servers {
1219− let language_id = doc.language_id().map(ToOwned::to_owned).unwrap_or_default();
1220−
1221− // only spawn new language servers if the servers aren't the same
1222−
1223− let doc_language_servers_not_in_registry =
1224− doc.language_servers.iter().filter(|(name, doc_ls)| {
1225− language_servers
1226− .get(*name)
1227− .map_or(true, |ls| ls.id() != doc_ls.id())
1228− });
1250+ if language_servers.is_empty() {
1251+ return;
1252+ }
12291253
1230− for (_, language_server) in doc_language_servers_not_in_registry {
1231− tokio::spawn(language_server.text_document_did_close(doc.identifier()));
1232− }
1254+ let language_id = doc.language_id().map(ToOwned::to_owned).unwrap_or_default();
12331255
1234− let language_servers_not_in_doc = language_servers.iter().filter(|(name, ls)| {
1235− doc.language_servers
1256+ // only spawn new language servers if the servers aren't the same
1257+ let doc_language_servers_not_in_registry =
1258+ doc.language_servers.iter().filter(|(name, doc_ls)| {
1259+ language_servers
12361260 .get(*name)
1237− .map_or(true, |doc_ls| ls.id() != doc_ls.id())
1261+ .map_or(true, |ls| ls.id() != doc_ls.id())
12381262 });
12391263
1240− for (_, language_server) in language_servers_not_in_doc {
1241− // TODO: this now races with on_init code if the init happens too quickly
1242− tokio::spawn(language_server.text_document_did_open(
1243− doc_url.clone(),
1244− doc.version(),
1245− doc.text(),
1246− language_id.clone(),
1247− ));
1248− }
1264+ for (_, language_server) in doc_language_servers_not_in_registry {
1265+ tokio::spawn(language_server.text_document_did_close(doc.identifier()));
1266+ }
1267+
1268+ let language_servers_not_in_doc = language_servers.iter().filter(|(name, ls)| {
1269+ doc.language_servers
1270+ .get(*name)
1271+ .map_or(true, |doc_ls| ls.id() != doc_ls.id())
1272+ });
12491273
1250− doc.language_servers = language_servers;
1274+ for (_, language_server) in language_servers_not_in_doc {
1275+ // TODO: this now races with on_init code if the init happens too quickly
1276+ tokio::spawn(language_server.text_document_did_open(
1277+ doc_url.clone(),
1278+ doc.version(),
1279+ doc.text(),
1280+ language_id.clone(),
1281+ ));
12511282 }
1252− Some(())
1283+
1284+ doc.language_servers = language_servers;
12531285 }
12541286
12551287 fn _refresh(&mut self) {
@@ -1451,7 +1483,7 @@ impl Editor {
14511483 doc.set_version_control_head(self.diff_providers.get_current_head_name(&path));
14521484
14531485 let id = self.new_document(doc);
1454− let _ = self.launch_language_servers(id);
1486+ self.launch_language_servers(id);
14551487
14561488 id
14571489 };
helix-view/src/gutter.rs+4−5
@@ -9,8 +9,7 @@ use crate::{
99};
1010
1111fn count_digits(n: usize) -> usize {
12− // TODO: use checked_log10 when MSRV reaches 1.67
13− std::iter::successors(Some(n), |&n| (n >= 10).then_some(n / 10)).count()
12+ (usize::checked_ilog10(n).unwrap_or(0) + 1) as usize
1413}
1514
1615pub type GutterFn<'doc> = Box<dyn FnMut(usize, bool, bool, &mut String) -> Option<Style> + 'doc>;
@@ -94,9 +93,9 @@ pub fn diff<'doc>(
9493 theme: &Theme,
9594 _is_focused: bool,
9695) -> GutterFn<'doc> {
97− let added = theme.get("diff.plus");
98− let deleted = theme.get("diff.minus");
99− let modified = theme.get("diff.delta");
96+ let added = theme.get("diff.plus.gutter");
97+ let deleted = theme.get("diff.minus.gutter");
98+ let modified = theme.get("diff.delta.gutter");
10099 if let Some(diff_handle) = doc.diff_handle() {
101100 let hunks = diff_handle.load();
102101 let mut hunk_i = 0;
helix-view/src/handlers/dap.rs+1−3
@@ -369,9 +369,7 @@ impl Editor {
369369 {
370370 Ok(process) => process,
371371 Err(err) => {
372− // TODO replace the pretty print {:?} with a regular format {}
373− // when the MSRV is raised to 1.60.0
374− self.set_error(format!("Error starting external terminal: {:?}", err));
372+ self.set_error(format!("Error starting external terminal: {}", err));
375373 return true;
376374 }
377375 };
helix-view/src/input.rs+59−1
@@ -549,7 +549,7 @@ pub fn parse_macro(keys_str: &str) -> anyhow::Result<Vec<KeyEvent>> {
549549 if c == ">" {
550550 keys_res = Err(anyhow!("Unmatched '>'"));
551551 } else if c != "<" {
552− keys.push(c);
552+ keys.push(if c == "-" { keys::MINUS } else { c });
553553 i += end_i;
554554 } else {
555555 match s.find('>').context("'>' expected") {
@@ -813,6 +813,64 @@ mod test {
813813 },
814814 ])
815815 );
816+
817+ assert_eq!(
818+ parse_macro(":w aa-bb.txt<ret>").ok(),
819+ Some(vec![
820+ KeyEvent {
821+ code: KeyCode::Char(':'),
822+ modifiers: KeyModifiers::NONE,
823+ },
824+ KeyEvent {
825+ code: KeyCode::Char('w'),
826+ modifiers: KeyModifiers::NONE,
827+ },
828+ KeyEvent {
829+ code: KeyCode::Char(' '),
830+ modifiers: KeyModifiers::NONE,
831+ },
832+ KeyEvent {
833+ code: KeyCode::Char('a'),
834+ modifiers: KeyModifiers::NONE,
835+ },
836+ KeyEvent {
837+ code: KeyCode::Char('a'),
838+ modifiers: KeyModifiers::NONE,
839+ },
840+ KeyEvent {
841+ code: KeyCode::Char('-'),
842+ modifiers: KeyModifiers::NONE,
843+ },
844+ KeyEvent {
845+ code: KeyCode::Char('b'),
846+ modifiers: KeyModifiers::NONE,
847+ },
848+ KeyEvent {
849+ code: KeyCode::Char('b'),
850+ modifiers: KeyModifiers::NONE,
851+ },
852+ KeyEvent {
853+ code: KeyCode::Char('.'),
854+ modifiers: KeyModifiers::NONE,
855+ },
856+ KeyEvent {
857+ code: KeyCode::Char('t'),
858+ modifiers: KeyModifiers::NONE,
859+ },
860+ KeyEvent {
861+ code: KeyCode::Char('x'),
862+ modifiers: KeyModifiers::NONE,
863+ },
864+ KeyEvent {
865+ code: KeyCode::Char('t'),
866+ modifiers: KeyModifiers::NONE,
867+ },
868+ KeyEvent {
869+ code: KeyCode::Enter,
870+ modifiers: KeyModifiers::NONE,
871+ },
872+ ])
873+ );
816874 }
817875
818876 #[test]
helix-view/src/register.rs+10−10
@@ -75,8 +75,8 @@ impl Registers {
7575 self.clipboard_provider.as_ref(),
7676 self.inner.get(&name),
7777 match name {
78− '*' => ClipboardType::Clipboard,
79− '+' => ClipboardType::Selection,
78+ '+' => ClipboardType::Clipboard,
79+ '*' => ClipboardType::Selection,
8080 _ => unreachable!(),
8181 },
8282 )),
@@ -95,8 +95,8 @@ impl Registers {
9595 self.clipboard_provider.set_contents(
9696 values.join(NATIVE_LINE_ENDING.as_str()),
9797 match name {
98− '*' => ClipboardType::Clipboard,
99− '+' => ClipboardType::Selection,
98+ '+' => ClipboardType::Clipboard,
99+ '*' => ClipboardType::Selection,
100100 _ => unreachable!(),
101101 },
102102 )?;
@@ -118,8 +118,8 @@ impl Registers {
118118 '#' | '.' | '%' => Err(anyhow::anyhow!("Register {name} does not support pushing")),
119119 '*' | '+' => {
120120 let clipboard_type = match name {
121− '*' => ClipboardType::Clipboard,
122− '+' => ClipboardType::Selection,
121+ '+' => ClipboardType::Clipboard,
122+ '*' => ClipboardType::Selection,
123123 _ => unreachable!(),
124124 };
125125 let contents = self.clipboard_provider.get_contents(clipboard_type)?;
@@ -172,8 +172,8 @@ impl Registers {
172172 ('#', "<selection indices>"),
173173 ('.', "<selection contents>"),
174174 ('%', "<document path>"),
175− ('*', "<system clipboard>"),
176− ('+', "<primary clipboard>"),
175+ ('+', "<system clipboard>"),
176+ ('*', "<primary clipboard>"),
177177 ]
178178 .iter()
179179 .copied(),
@@ -190,8 +190,8 @@ impl Registers {
190190 match name {
191191 '*' | '+' => {
192192 self.clear_clipboard(match name {
193− '*' => ClipboardType::Clipboard,
194− '+' => ClipboardType::Selection,
193+ '+' => ClipboardType::Clipboard,
194+ '*' => ClipboardType::Selection,
195195 _ => unreachable!(),
196196 });
197197 self.inner.remove(&name);
helix-view/src/theme.rs+5
@@ -297,6 +297,11 @@ impl Theme {
297297 self.highlights[index]
298298 }
299299
300+ #[inline]
301+ pub fn scope(&self, index: usize) -> &str {
302+ &self.scopes[index]
303+ }
304+
300305 pub fn name(&self) -> &str {
301306 &self.name
302307 }
languages.toml+394−193
@@ -3,6 +3,7 @@
33
44[language-server]
55
6+als = { command = "als" }
67awk-language-server = { command = "awk-language-server" }
78bash-language-server = { command = "bash-language-server", args = ["start"] }
89bass = { command = "bass", args = ["--lsp"] }
@@ -30,6 +31,7 @@ forth-lsp = { command = "forth-lsp" }
3031fortls = { command = "fortls", args = ["--lowercase_intrinsics"] }
3132fsharp-ls = { command = "fsautocomplete", config = { AutomaticWorkspaceInit = true } }
3233gleam = { command = "gleam", args = ["lsp"] }
34+graphql-language-service = { command = "graphql-lsp", args = ["server", "-m", "stream"] }
3335haskell-language-server = { command = "haskell-language-server-wrapper", args = ["--lsp"] }
3436idris2-lsp = { command = "idris2-lsp" }
3537intelephense = { command = "intelephense", args = ["--stdio"] }
@@ -46,6 +48,7 @@ mint = { command = "mint", args = ["ls"] }
4648nil = { command = "nil" }
4749nimlangserver = { command = "nimlangserver" }
4850nls = { command = "nls" }
51+nu-lsp = { command = "nu", args = [ "--lsp" ] }
4952ocamllsp = { command = "ocamllsp" }
5053ols = { command = "ols", args = [] }
5154omnisharp = { command = "OmniSharp", args = [ "--languageserver" ] }
@@ -71,24 +74,30 @@ solc = { command = "solc", args = ["--lsp"] }
7174sourcekit-lsp = { command = "sourcekit-lsp" }
7275svlangserver = { command = "svlangserver", args = [] }
7376swipl = { command = "swipl", args = [ "-g", "use_module(library(lsp_server))", "-g", "lsp_server:main", "-t", "halt", "--", "stdio" ] }
77+tailwindcss-ls = { command = "tailwindcss-language-server", args = ["--stdio"] }
7478taplo = { command = "taplo", args = ["lsp", "stdio"] }
79+templ = { command = "templ", args = ["lsp"] }
7580terraform-ls = { command = "terraform-ls", args = ["serve"] }
7681texlab = { command = "texlab" }
7782vala-language-server = { command = "vala-language-server" }
7883vhdl_ls = { command = "vhdl_ls", args = [] }
7984vlang-language-server = { command = "v-analyzer" }
80−vscode-css-language-server = { command = "vscode-css-language-server", args = ["--stdio"], config = { "provideFormatter" = true }}
85+vscode-css-language-server = { command = "vscode-css-language-server", args = ["--stdio"], config = { provideFormatter = true, css = { validate = { enable = true } } } }
8186vscode-html-language-server = { command = "vscode-html-language-server", args = ["--stdio"], config = { provideFormatter = true } }
82−vscode-json-language-server = { command = "vscode-json-language-server", args = ["--stdio"], config = { provideFormatter = true } }
87+vscode-json-language-server = { command = "vscode-json-language-server", args = ["--stdio"], config = { provideFormatter = true, json = { validate = { enable = true } } } }
8388vuels = { command = "vue-language-server", args = ["--stdio"], config = { typescript = { tsdk = "node_modules/typescript/lib/" } } }
8489wgsl_analyzer = { command = "wgsl_analyzer" }
8590yaml-language-server = { command = "yaml-language-server", args = ["--stdio"] }
8691zls = { command = "zls" }
8792blueprint-compiler = { command = "blueprint-compiler", args = ["lsp"] }
93+typst-lsp = { command = "typst-lsp" }
8894
95+[language-server.ansible-language-server]
96+command = "ansible-language-server"
97+args = ["--stdio"]
8998
9099[language-server.lua-language-server]
91−command = "lua-language-server"
100+command = "lua-language-server"
92101
93102[language-server.lua-language-server.config.Lua.hint]
94103enable = true
@@ -110,6 +119,12 @@ functionTypeParameters = true
110119parameterNames = true
111120rangeVariableTypes = true
112121
122+[language-server.golangci-lint-lsp]
123+command = "golangci-lint-langserver"
124+
125+[language-server.golangci-lint-lsp.config]
126+command = ["golangci-lint", "run", "--out-format", "json", "--issues-exit-code=1"]
127+
113128
114129[language-server.rust-analyzer]
115130command = "rust-analyzer"
@@ -176,6 +191,7 @@ auto-format = true
176191comment-token = "//"
177192language-servers = [ "rust-analyzer" ]
178193indent = { tab-width = 4, unit = " " }
194+persistent-diagnostic-sources = ["rustc", "clippy"]
179195
180196[language.auto-pairs]
181197'(' = ')'
@@ -236,7 +252,6 @@ name = "toml"
236252scope = "source.toml"
237253injection-regex = "toml"
238254file-types = ["toml", "poetry.lock", "Cargo.lock"]
239−roots = []
240255comment-token = "#"
241256language-servers = [ "taplo" ]
242257indent = { tab-width = 2, unit = " " }
@@ -250,7 +265,6 @@ name = "awk"
250265scope = "source.awk"
251266injection-regex = "awk"
252267file-types = ["awk", "gawk", "nawk", "mawk"]
253−roots = []
254268comment-token = "#"
255269language-servers = [ "awk-language-server" ]
256270indent = { tab-width = 2, unit = " " }
@@ -265,7 +279,6 @@ scope = "source.proto"
265279injection-regex = "protobuf"
266280file-types = ["proto"]
267281language-servers = [ "bufls", "pbkit" ]
268−roots = []
269282comment-token = "//"
270283indent = { tab-width = 2, unit = " " }
271284
@@ -294,7 +307,6 @@ scope = "source.fish"
294307injection-regex = "fish"
295308file-types = ["fish"]
296309shebangs = ["fish"]
297−roots = []
298310comment-token = "#"
299311indent = { tab-width = 4, unit = " " }
300312
@@ -308,7 +320,6 @@ scope = "source.mint"
308320injection-regex = "mint"
309321file-types = ["mint"]
310322shebangs = []
311−roots = []
312323comment-token = "//"
313324language-servers = [ "mint" ]
314325indent = { tab-width = 2, unit = " " }
@@ -317,8 +328,28 @@ indent = { tab-width = 2, unit = " " }
317328name = "json"
318329scope = "source.json"
319330injection-regex = "json"
320−file-types = ["json", "jsonc", "arb", "ipynb", "geojson", "gltf"]
321−roots = []
331+file-types = [
332+ "json",
333+ "jsonc",
334+ "arb",
335+ "ipynb",
336+ "geojson",
337+ "gltf",
338+ "webmanifest",
339+ "flake.lock",
340+ ".babelrc",
341+ ".bowerrc",
342+ ".jscrc",
343+ "js.map",
344+ "ts.map",
345+ "css.map",
346+ ".jslintrc",
347+ "jsonld",
348+ ".vuerc",
349+ "composer.lock",
350+ ".watchmanconfig",
351+ "avsc"
352+]
322353language-servers = [ "vscode-json-language-server" ]
323354auto-format = true
324355indent = { tab-width = 2, unit = " " }
@@ -327,12 +358,26 @@ indent = { tab-width = 2, unit = " " }
327358name = "json"
328359source = { git = "https://github.com/tree-sitter/tree-sitter-json", rev = "73076754005a460947cafe8e03a8cf5fa4fa2938" }
329360
361+
362+[[language]]
363+name = "json5"
364+scope = "source.json5"
365+injection-regex = "json5"
366+file-types = ["json5"]
367+language-servers = []
368+comment-token = "//"
369+indent = { tab-width = 4, unit = " " }
370+# https://json5.org
371+
372+[[grammar]]
373+name = "json5"
374+source = { git = "https://github.com/Joakker/tree-sitter-json5", rev = "c23f7a9b1ee7d45f516496b1e0e4be067264fa0d" }
375+
330376[[language]]
331377name = "c"
332378scope = "source.c"
333379injection-regex = "c"
334380file-types = ["c"] # TODO: ["h"]
335−roots = []
336381comment-token = "//"
337382language-servers = [ "clangd" ]
338383indent = { tab-width = 2, unit = " " }
@@ -368,8 +413,7 @@ source = { git = "https://github.com/tree-sitter/tree-sitter-c", rev = "7175a6dd
368413name = "cpp"
369414scope = "source.cpp"
370415injection-regex = "cpp"
371−file-types = ["cc", "hh", "c++", "cpp", "hpp", "h", "ipp", "tpp", "cxx", "hxx", "ixx", "txx", "ino", "C", "H", "cu", "cuh", "cppm"]
372−roots = []
416+file-types = ["cc", "hh", "c++", "cpp", "hpp", "h", "ipp", "tpp", "cxx", "hxx", "ixx", "txx", "ino", "C", "H", "cu", "cuh", "cppm", "h++", "ii", "inl", { suffix = ".hpp.in" }, { suffix = ".h.in" }]
373417comment-token = "//"
374418language-servers = [ "clangd" ]
375419indent = { tab-width = 2, unit = " " }
@@ -415,7 +459,7 @@ language-servers = [ "crystalline" ]
415459name = "c-sharp"
416460scope = "source.csharp"
417461injection-regex = "c-?sharp"
418−file-types = ["cs"]
462+file-types = ["cs", "csx", "cake"]
419463roots = ["sln", "csproj"]
420464comment-token = "//"
421465indent = { tab-width = 4, unit = "\t" }
@@ -452,7 +496,7 @@ file-types = ["go"]
452496roots = ["go.work", "go.mod"]
453497auto-format = true
454498comment-token = "//"
455−language-servers = [ "gopls" ]
499+language-servers = [ "gopls", "golangci-lint-lsp" ]
456500# TODO: gopls needs utf-8 offsets?
457501indent = { tab-width = 4, unit = "\t" }
458502
@@ -502,7 +546,6 @@ name = "gomod"
502546scope = "source.gomod"
503547injection-regex = "gomod"
504548file-types = ["go.mod"]
505−roots = []
506549auto-format = true
507550comment-token = "//"
508551language-servers = [ "gopls" ]
@@ -517,7 +560,6 @@ name = "gotmpl"
517560scope = "source.gotmpl"
518561injection-regex = "gotmpl"
519562file-types = ["gotmpl"]
520−roots = []
521563comment-token = "//"
522564language-servers = [ "gopls" ]
523565indent = { tab-width = 2, unit = " " }
@@ -531,7 +573,6 @@ name = "gowork"
531573scope = "source.gowork"
532574injection-regex = "gowork"
533575file-types = ["go.work"]
534−roots = []
535576auto-format = true
536577comment-token = "//"
537578language-servers = [ "gopls" ]
@@ -546,9 +587,8 @@ name = "javascript"
546587scope = "source.js"
547588injection-regex = "(js|javascript)"
548589language-id = "javascript"
549−file-types = ["js", "mjs", "cjs"]
590+file-types = ["js", "mjs", "cjs", "rules", "es6", "pac", "jakefile"]
550591shebangs = ["node"]
551−roots = []
552592comment-token = "//"
553593language-servers = [ "typescript-language-server" ]
554594indent = { tab-width = 2, unit = " " }
@@ -575,7 +615,6 @@ scope = "source.jsx"
575615injection-regex = "jsx"
576616language-id = "javascriptreact"
577617file-types = ["jsx"]
578−roots = []
579618comment-token = "//"
580619language-servers = [ "typescript-language-server" ]
581620indent = { tab-width = 2, unit = " " }
@@ -587,8 +626,7 @@ scope = "source.ts"
587626injection-regex = "(ts|typescript)"
588627file-types = ["ts", "mts", "cts"]
589628language-id = "typescript"
590−shebangs = []
591−roots = []
629+shebangs = ["deno", "ts-node"]
592630language-servers = [ "typescript-language-server" ]
593631indent = { tab-width = 2, unit = " " }
594632
@@ -602,7 +640,6 @@ scope = "source.tsx"
602640injection-regex = "(tsx)" # |typescript
603641language-id = "typescriptreact"
604642file-types = ["tsx"]
605−roots = []
606643language-servers = [ "typescript-language-server" ]
607644indent = { tab-width = 2, unit = " " }
608645
@@ -615,7 +652,6 @@ name = "css"
615652scope = "source.css"
616653injection-regex = "css"
617654file-types = ["css", "scss"]
618−roots = []
619655language-servers = [ "vscode-css-language-server" ]
620656auto-format = true
621657indent = { tab-width = 2, unit = " " }
@@ -629,7 +665,6 @@ name = "scss"
629665scope = "source.scss"
630666injection-regex = "scss"
631667file-types = ["scss"]
632−roots = []
633668language-servers = [ "vscode-css-language-server" ]
634669auto-format = true
635670indent = { tab-width = 2, unit = " " }
@@ -642,8 +677,7 @@ source = { git = "https://github.com/serenadeai/tree-sitter-scss", rev = "c478c6
642677name = "html"
643678scope = "text.html.basic"
644679injection-regex = "html"
645−file-types = ["html"]
646−roots = []
680+file-types = ["html", "htm", "shtml", "xhtml", "xht", "jsp", "asp", "aspx", "jshtm", "volt", "rhtml"]
647681language-servers = [ "vscode-html-language-server" ]
648682auto-format = true
649683indent = { tab-width = 2, unit = " " }
@@ -656,7 +690,7 @@ source = { git = "https://github.com/tree-sitter/tree-sitter-html", rev = "29f53
656690name = "python"
657691scope = "source.python"
658692injection-regex = "python"
659−file-types = ["py","pyi","py3","pyw","ptl",".pythonstartup",".pythonrc","SConstruct"]
693+file-types = ["py","pyi","py3","pyw","ptl",".pythonstartup",".pythonrc","SConstruct", "rpy", "cpy", "ipy", "pyt", "SConscript"]
660694shebangs = ["python"]
661695roots = ["pyproject.toml", "setup.py", "poetry.lock", "pyrightconfig.json"]
662696comment-token = "#"
@@ -666,7 +700,7 @@ indent = { tab-width = 4, unit = " " }
666700
667701[[grammar]]
668702name = "python"
669−source = { git = "https://github.com/tree-sitter/tree-sitter-python", rev = "de221eccf9a221f5b85474a553474a69b4b5784d" }
703+source = { git = "https://github.com/tree-sitter/tree-sitter-python", rev = "4bfdd9033a2225cc95032ce77066b7aeca9e2efc" }
670704
671705[[language]]
672706name = "nickel"
@@ -674,7 +708,6 @@ scope = "source.nickel"
674708injection-regex = "nickel"
675709file-types = ["ncl"]
676710shebangs = []
677−roots = []
678711comment-token = "#"
679712language-servers = [ "nls" ]
680713indent = { tab-width = 2, unit = " " }
@@ -695,7 +728,6 @@ scope = "source.nix"
695728injection-regex = "nix"
696729file-types = ["nix"]
697730shebangs = []
698−roots = []
699731comment-token = "#"
700732language-servers = [ "nil" ]
701733indent = { tab-width = 2, unit = " " }
@@ -708,9 +740,43 @@ source = { git = "https://github.com/nix-community/tree-sitter-nix", rev = "1b69
708740name = "ruby"
709741scope = "source.ruby"
710742injection-regex = "ruby"
711−file-types = ["rb", "rake", "rakefile", "irb", "gemfile", "gemspec", "Rakefile", "Gemfile", "rabl", "jbuilder", "jb", "Podfile", "podspec", "Vagrantfile", "Brewfile"]
743+file-types = [
744+ "rb",
745+ "rake",
746+ "rakefile",
747+ "irb",
748+ "gemfile",
749+ "gemspec",
750+ "Rakefile",
751+ "Gemfile",
752+ "rabl",
753+ "jbuilder",
754+ "jb",
755+ "Podfile",
756+ "podspec",
757+ "Vagrantfile",
758+ "Brewfile",
759+ "rjs",
760+ "rbi",
761+ "Guardfile",
762+ "Capfile",
763+ "Cheffile",
764+ "Hobofile",
765+ "Appraisals",
766+ "Rantfile",
767+ "Berksfile",
768+ "Berksfile.lock",
769+ "Thorfile",
770+ "Puppetfile",
771+ "Fastfile",
772+ "Appfile",
773+ "Deliverfile",
774+ "Matchfile",
775+ "Scanfile",
776+ "Snapfile",
777+ "Gymfile"
778+]
712779shebangs = ["ruby"]
713−roots = []
714780comment-token = "#"
715781language-servers = [ "solargraph" ]
716782indent = { tab-width = 2, unit = " " }
@@ -723,9 +789,48 @@ source = { git = "https://github.com/tree-sitter/tree-sitter-ruby", rev = "206c7
723789name = "bash"
724790scope = "source.bash"
725791injection-regex = "(shell|bash|zsh|sh)"
726−file-types = ["sh", "bash", "zsh", ".bash_login", ".bash_logout", ".bash_profile", ".bashrc", ".profile", ".zshenv", "zshenv", ".zlogin", "zlogin", ".zlogout", "zlogout", ".zprofile", "zprofile", ".zshrc", "zshrc", ".zimrc", "APKBUILD", "PKGBUILD", "eclass", "ebuild", "bazelrc", ".bash_aliases", "Renviron", ".Renviron"]
792+file-types = [
793+ "sh",
794+ "bash",
795+ "zsh",
796+ ".bash_login",
797+ ".bash_logout",
798+ ".bash_profile",
799+ ".bashrc",
800+ ".profile",
801+ ".zshenv",
802+ "zshenv",
803+ ".zlogin",
804+ "zlogin",
805+ ".zlogout",
806+ "zlogout",
807+ ".zprofile",
808+ "zprofile",
809+ ".zshrc",
810+ "zshrc",
811+ ".zimrc",
812+ "APKBUILD",
813+ "PKGBUILD",
814+ "eclass",
815+ "ebuild",
816+ "bazelrc",
817+ ".bash_aliases",
818+ "Renviron",
819+ ".Renviron",
820+ ".xprofile",
821+ ".xsession",
822+ ".xsessionrc",
823+ "zsh-theme",
824+ "ksh",
825+ "cshrc",
826+ "tcshrc",
827+ ".yashrc",
828+ ".yash_profile",
829+ ".hushlogin",
830+ "bashrc_Apple_Terminal",
831+ "zshrc_Apple_Terminal"
832+]
727833shebangs = ["sh", "bash", "dash", "zsh"]
728−roots = []
729834comment-token = "#"
730835language-servers = [ "bash-language-server" ]
731836indent = { tab-width = 2, unit = " " }
@@ -738,7 +843,7 @@ source = { git = "https://github.com/tree-sitter/tree-sitter-bash", rev = "275ef
738843name = "php"
739844scope = "source.php"
740845injection-regex = "php"
741−file-types = ["php", "inc"]
846+file-types = ["php", "inc", "php4", "php5", "phtml", "ctp"]
742847shebangs = ["php"]
743848roots = ["composer.json", "index.php"]
744849language-servers = [ "intelephense" ]
@@ -753,7 +858,6 @@ name = "twig"
753858scope = "source.twig"
754859injection-regex = "twig"
755860file-types = ["twig"]
756−roots = []
757861indent = { tab-width = 2, unit = " " }
758862
759863[[grammar]]
@@ -764,8 +868,7 @@ source = { git = "https://github.com/gbprod/tree-sitter-twig", rev = "807b293fec
764868name = "latex"
765869scope = "source.tex"
766870injection-regex = "tex"
767−file-types = ["tex", "sty", "cls", "Rd"]
768−roots = []
871+file-types = ["tex", "sty", "cls", "Rd", "bbx", "cbx"]
769872comment-token = "%"
770873language-servers = [ "texlab" ]
771874indent = { tab-width = 4, unit = "\t" }
@@ -779,7 +882,6 @@ name = "bibtex"
779882scope = "source.bib"
780883injection-regex = "bib"
781884file-types = ["bib"]
782−roots = []
783885comment-token = "%"
784886language-servers = [ "texlab" ]
785887indent = { tab-width = 4, unit = "\t" }
@@ -816,11 +918,23 @@ indent = { tab-width = 2, unit = " " }
816918name = "lean"
817919source = { git = "https://github.com/Julian/tree-sitter-lean", rev = "d98426109258b266e1e92358c5f11716d2e8f638" }
818920
921+
922+[[language]]
923+name = "lpf"
924+comment-token = "#"
925+scope = "source.lpf"
926+file-types = ["lpf"]
927+
928+[[grammar]]
929+name = "lpf"
930+source = { git = "https://gitlab.com/TheZoq2/tree-sitter-lpf", rev = "db7372e60c722ca7f12ab359e57e6bf7611ab126" }
931+
819932[[language]]
820933name = "julia"
821934scope = "source.julia"
822935injection-regex = "julia"
823936file-types = ["jl"]
937+shebangs = ["julia"]
824938roots = ["Manifest.toml", "Project.toml"]
825939comment-token = "#"
826940language-servers = [ "julia" ]
@@ -834,7 +948,7 @@ source = { git = "https://github.com/tree-sitter/tree-sitter-julia", rev = "8fb3
834948name = "java"
835949scope = "source.java"
836950injection-regex = "java"
837−file-types = ["java"]
951+file-types = ["java", "jav"]
838952roots = ["pom.xml", "build.gradle", "build.gradle.kts"]
839953language-servers = [ "jdtls" ]
840954indent = { tab-width = 2, unit = " " }
@@ -843,12 +957,24 @@ indent = { tab-width = 2, unit = " " }
843957name = "java"
844958source = { git = "https://github.com/tree-sitter/tree-sitter-java", rev = "09d650def6cdf7f479f4b78f595e9ef5b58ce31e" }
845959
960+[[language]]
961+name = "smali"
962+scope = "source.smali"
963+injection-regex = "smali"
964+file-types = ["smali"]
965+comment-token = "#"
966+roots = []
967+indent = { tab-width = 4, unit = " " }
968+
969+[[grammar]]
970+name = "smali"
971+source = { git = "https://github.com/amaanq/tree-sitter-smali", rev = "5ae51e15c4d1ac93cba6127caf3d1f0a072c140c" }
972+
846973[[language]]
847974name = "ledger"
848975scope = "source.ledger"
849976injection-regex = "ledger"
850977file-types = ["ldg", "ledger", "journal"]
851−roots = []
852978comment-token = ";"
853979indent = { tab-width = 4, unit = " " }
854980
@@ -861,21 +987,19 @@ name = "beancount"
861987scope = "source.beancount"
862988injection-regex = "beancount"
863989file-types = ["beancount", "bean"]
864−roots = []
865990comment-token = ";"
866991indent = { tab-width = 2, unit = " " }
867992
868993[[grammar]]
869994name = "beancount"
870−source = { git = "https://github.com/polarmutex/tree-sitter-beancount", rev = "4cbd1f09cd07c1f1fabf867c2cf354f9da53cc4c" }
995+source = { git = "https://github.com/polarmutex/tree-sitter-beancount", rev = "f3741a3a68ade59ec894ed84a64673494d2ba8f3" }
871996
872997[[language]]
873998name = "ocaml"
874999scope = "source.ocaml"
8751000injection-regex = "ocaml"
8761001file-types = ["ml"]
877−shebangs = []
878−roots = []
1002+shebangs = ["ocaml", "ocamlrun", "ocamlscript"]
8791003comment-token = "(**)"
8801004language-servers = [ "ocamllsp" ]
8811005indent = { tab-width = 2, unit = " " }
@@ -885,7 +1009,6 @@ indent = { tab-width = 2, unit = " " }
8851009'{' = '}'
8861010'[' = ']'
8871011'"' = '"'
888−'`' = '`'
8891012
8901013[[grammar]]
8911014name = "ocaml"
@@ -896,7 +1019,6 @@ name = "ocaml-interface"
8961019scope = "source.ocaml.interface"
8971020file-types = ["mli"]
8981021shebangs = []
899−roots = []
9001022comment-token = "(**)"
9011023language-servers = [ "ocamllsp" ]
9021024indent = { tab-width = 2, unit = " " }
@@ -906,7 +1028,6 @@ indent = { tab-width = 2, unit = " " }
9061028'{' = '}'
9071029'[' = ']'
9081030'"' = '"'
909−'`' = '`'
9101031
9111032[[grammar]]
9121033name = "ocaml-interface"
@@ -932,7 +1053,6 @@ name = "svelte"
9321053scope = "source.svelte"
9331054injection-regex = "svelte"
9341055file-types = ["svelte"]
935−roots = []
9361056indent = { tab-width = 2, unit = " " }
9371057language-servers = [ "svelteserver" ]
9381058
@@ -957,10 +1077,9 @@ source = { git = "https://github.com/ikatyang/tree-sitter-vue", rev = "91fe27547
9571077name = "yaml"
9581078scope = "source.yaml"
9591079file-types = ["yml", "yaml"]
960−roots = []
9611080comment-token = "#"
9621081indent = { tab-width = 2, unit = " " }
963−language-servers = [ "yaml-language-server" ]
1082+language-servers = [ "yaml-language-server", "ansible-language-server" ]
9641083injection-regex = "yml|yaml"
9651084
9661085[[grammar]]
@@ -979,13 +1098,12 @@ indent = { tab-width = 2, unit = " " }
9791098
9801099[[grammar]]
9811100name = "haskell"
982−source = { git = "https://github.com/tree-sitter/tree-sitter-haskell", rev = "98fc7f59049aeb713ab9b72a8ff25dcaaef81087" }
1101+source = { git = "https://github.com/tree-sitter/tree-sitter-haskell", rev = "d7ac98f49e3ed7e17541256fe3881a967d7ffdd3" }
9831102
9841103[[language]]
9851104name = "haskell-persistent"
9861105scope = "source.persistentmodels"
9871106file-types = ["persistentmodels"]
988−roots = []
9891107comment-token = "--"
9901108indent = { tab-width = 2, unit = " " }
9911109
@@ -1004,7 +1122,10 @@ language-servers = [ "purescript-language-server" ]
10041122indent = { tab-width = 2, unit = " " }
10051123auto-format = true
10061124formatter = { command = "purs-tidy", args = ["format"] }
1007−grammar = "haskell"
1125+
1126+[[grammar]]
1127+name = "purescript"
1128+source = { git = "https://github.com/postsolar/tree-sitter-purescript", rev = "5ef5592674ea42de75fc2792972e4ea0b6e3da6c" }
10081129
10091130[[language]]
10101131name = "zig"
@@ -1048,7 +1169,6 @@ source = { git = "https://github.com/maxxnino/tree-sitter-zig", rev = "0d08703e4
10481169[[language]]
10491170name = "prolog"
10501171scope = "source.prolog"
1051−roots = []
10521172file-types = ["pl", "prolog"]
10531173shebangs = ["swipl"]
10541174comment-token = "%"
@@ -1058,7 +1178,6 @@ language-servers = [ "swipl" ]
10581178name = "tsq"
10591179scope = "source.tsq"
10601180file-types = ["tsq"]
1061−roots = []
10621181comment-token = ";"
10631182injection-regex = "tsq"
10641183indent = { tab-width = 2, unit = " " }
@@ -1071,7 +1190,6 @@ source = { git = "https://github.com/the-mikedavis/tree-sitter-tsq", rev = "48b5
10711190name = "cmake"
10721191scope = "source.cmake"
10731192file-types = ["cmake", "CMakeLists.txt"]
1074−roots = []
10751193comment-token = "#"
10761194indent = { tab-width = 2, unit = " " }
10771195language-servers = [ "cmake-language-server" ]
@@ -1084,9 +1202,9 @@ source = { git = "https://github.com/uyha/tree-sitter-cmake", rev = "6e51463ef30
10841202[[language]]
10851203name = "make"
10861204scope = "source.make"
1087−file-types = ["Makefile", "makefile", "make", "mk"]
1205+file-types = ["Makefile", "makefile", "make", "mk", "mak", "GNUmakefile", "OCamlMakefile"]
1206+shebangs = ["make", "gmake"]
10881207injection-regex = "(make|makefile|Makefile|mk)"
1089−roots = []
10901208comment-token = "#"
10911209indent = { tab-width = 4, unit = "\t" }
10921210
@@ -1098,7 +1216,6 @@ source = { git = "https://github.com/alemuller/tree-sitter-make", rev = "a4b9187
10981216name = "glsl"
10991217scope = "source.glsl"
11001218file-types = ["glsl", "vert", "tesc", "tese", "geom", "frag", "comp" ]
1101−roots = []
11021219comment-token = "//"
11031220indent = { tab-width = 4, unit = " " }
11041221injection-regex = "glsl"
@@ -1110,22 +1227,20 @@ source = { git = "https://github.com/theHamsta/tree-sitter-glsl", rev = "88408ff
11101227[[language]]
11111228name = "perl"
11121229scope = "source.perl"
1113−file-types = ["pl", "pm", "t"]
1230+file-types = ["pl", "pm", "t", "psgi", "raku", "rakumod", "rakutest", "rakudoc", "nqp", "p6", "pl6", "pm6"]
11141231shebangs = ["perl"]
1115−roots = []
11161232comment-token = "#"
11171233language-servers = [ "perlnavigator" ]
11181234indent = { tab-width = 2, unit = " " }
11191235
11201236[[grammar]]
11211237name = "perl"
1122−source = { git = "https://github.com/tree-sitter-perl/tree-sitter-perl", rev = "ed21ecbcc128a6688770ebafd3ef68a1c9bc1ea9" }
1238+source = { git = "https://github.com/tree-sitter-perl/tree-sitter-perl", rev = "e99bb5283805db4cb86c964722d709df21b0ac16" }
11231239
11241240[[language]]
11251241name = "pod"
11261242scope = "source.pod"
11271243injection-regex = "pod"
1128−roots = []
11291244file-types = ["pod"]
11301245
11311246[[grammar]]
@@ -1135,17 +1250,16 @@ source = { git = "https://github.com/tree-sitter-perl/tree-sitter-pod", rev = "d
11351250[[language]]
11361251name = "racket"
11371252scope = "source.racket"
1138−roots = []
11391253file-types = ["rkt", "rktd", "rktl", "scrbl"]
11401254shebangs = ["racket"]
11411255comment-token = ";"
1256+indent = { tab-width = 2, unit = " " }
11421257language-servers = [ "racket" ]
11431258grammar = "scheme"
11441259
11451260[[language]]
11461261name = "common-lisp"
11471262scope = "source.lisp"
1148−roots = []
11491263file-types = ["lisp", "asd", "cl", "l", "lsp", "ny", "podsl", "sexp"]
11501264shebangs = ["lisp", "sbcl", "ccl", "clisp", "ecl"]
11511265comment-token = ";"
@@ -1162,19 +1276,17 @@ grammar = "scheme"
11621276[[language]]
11631277name = "comment"
11641278scope = "scope.comment"
1165−roots = []
11661279file-types = []
11671280injection-regex = "comment"
11681281
11691282[[grammar]]
11701283name = "comment"
1171−source = { git = "https://github.com/stsewd/tree-sitter-comment", rev = "5dd3c62f1bbe378b220fe16b317b85247898639e" }
1284+source = { git = "https://github.com/stsewd/tree-sitter-comment", rev = "a37ca370310ac6f89b6e0ebf2b86b2219780494e" }
11721285
11731286[[language]]
11741287name = "wgsl"
11751288scope = "source.wgsl"
11761289file-types = ["wgsl"]
1177−roots = []
11781290comment-token = "//"
11791291language-servers = [ "wgsl_analyzer" ]
11801292indent = { tab-width = 4, unit = " " }
@@ -1186,7 +1298,6 @@ source = { git = "https://github.com/szebniok/tree-sitter-wgsl", rev = "272e89ef
11861298[[language]]
11871299name = "llvm"
11881300scope = "source.llvm"
1189−roots = []
11901301file-types = ["ll"]
11911302comment-token = ";"
11921303indent = { tab-width = 2, unit = " " }
@@ -1194,12 +1305,11 @@ injection-regex = "llvm"
11941305
11951306[[grammar]]
11961307name = "llvm"
1197−source = { git = "https://github.com/benwilliamgraham/tree-sitter-llvm", rev = "3b213925b9c4f42c1acfe2e10bfbb438d9c6834d" }
1308+source = { git = "https://github.com/benwilliamgraham/tree-sitter-llvm", rev = "e9948edc41e9e5869af99dddb2b5ff5cc5581af6" }
11981309
11991310[[language]]
12001311name = "llvm-mir"
12011312scope = "source.llvm_mir"
1202−roots = []
12031313file-types = []
12041314comment-token = ";"
12051315indent = { tab-width = 2, unit = " " }
@@ -1215,7 +1325,6 @@ name = "llvm-mir-yaml"
12151325#
12161326# grammar = "yaml"
12171327scope = "source.yaml"
1218−roots = []
12191328file-types = ["mir"]
12201329comment-token = "#"
12211330indent = { tab-width = 2, unit = " " }
@@ -1223,7 +1332,6 @@ indent = { tab-width = 2, unit = " " }
12231332[[language]]
12241333name = "tablegen"
12251334scope = "source.tablegen"
1226−roots = []
12271335file-types = ["td"]
12281336comment-token = "//"
12291337indent = { tab-width = 2, unit = " " }
@@ -1237,26 +1345,25 @@ source = { git = "https://github.com/Flakebi/tree-sitter-tablegen", rev = "568dd
12371345name = "markdown"
12381346scope = "source.md"
12391347injection-regex = "md|markdown"
1240−file-types = ["md", "markdown", "PULLREQ_EDITMSG"]
1348+file-types = ["md", "markdown", "PULLREQ_EDITMSG", "mkd", "mdwn", "mdown", "markdn", "mdtxt", "mdtext", "workbook"]
12411349roots = [".marksman.toml"]
12421350language-servers = [ "marksman" ]
12431351indent = { tab-width = 2, unit = " " }
12441352
12451353[[grammar]]
12461354name = "markdown"
1247−source = { git = "https://github.com/MDeiml/tree-sitter-markdown", rev = "fa6bfd51727e4bef99f7eec5f43947f73d64ea7d", subpath = "tree-sitter-markdown" }
1355+source = { git = "https://github.com/MDeiml/tree-sitter-markdown", rev = "aaf76797aa8ecd9a5e78e0ec3681941de6c945ee", subpath = "tree-sitter-markdown" }
12481356
12491357[[language]]
12501358name = "markdown.inline"
12511359scope = "source.markdown.inline"
12521360injection-regex = "markdown\\.inline"
12531361file-types = []
1254−roots = []
12551362grammar = "markdown_inline"
12561363
12571364[[grammar]]
12581365name = "markdown_inline"
1259−source = { git = "https://github.com/MDeiml/tree-sitter-markdown", rev = "fa6bfd51727e4bef99f7eec5f43947f73d64ea7d", subpath = "tree-sitter-markdown-inline" }
1366+source = { git = "https://github.com/MDeiml/tree-sitter-markdown", rev = "aaf76797aa8ecd9a5e78e0ec3681941de6c945ee", subpath = "tree-sitter-markdown-inline" }
12601367
12611368[[language]]
12621369name = "dart"
@@ -1302,7 +1409,6 @@ source = { git = "https://github.com/camdencheek/tree-sitter-dockerfile", rev =
13021409[[language]]
13031410name = "git-commit"
13041411scope = "git.commitmsg"
1305−roots = []
13061412file-types = ["COMMIT_EDITMSG"]
13071413comment-token = "#"
13081414indent = { tab-width = 2, unit = " " }
@@ -1316,8 +1422,7 @@ source = { git = "https://github.com/the-mikedavis/tree-sitter-git-commit", rev
13161422[[language]]
13171423name = "diff"
13181424scope = "source.diff"
1319−roots = []
1320−file-types = ["diff", "patch"]
1425+file-types = ["diff", "patch", "rej"]
13211426injection-regex = "diff"
13221427comment-token = "#"
13231428indent = { tab-width = 2, unit = " " }
@@ -1329,7 +1434,6 @@ source = { git = "https://github.com/the-mikedavis/tree-sitter-diff", rev = "fd7
13291434[[language]]
13301435name = "git-rebase"
13311436scope = "source.gitrebase"
1332−roots = []
13331437file-types = ["git-rebase-todo"]
13341438injection-regex = "git-rebase"
13351439comment-token = "#"
@@ -1344,7 +1448,6 @@ name = "regex"
13441448scope = "source.regex"
13451449injection-regex = "regex"
13461450file-types = ["regex", ".Rbuildignore"]
1347−roots = []
13481451
13491452[[grammar]]
13501453name = "regex"
@@ -1353,7 +1456,6 @@ source = { git = "https://github.com/tree-sitter/tree-sitter-regex", rev = "e1cf
13531456[[language]]
13541457name = "git-config"
13551458scope = "source.gitconfig"
1356−roots = []
13571459file-types = [".gitmodules", ".gitconfig", { suffix = ".git/config" }, { suffix = ".config/git/config" }]
13581460injection-regex = "git-config"
13591461comment-token = "#"
@@ -1366,7 +1468,6 @@ source = { git = "https://github.com/the-mikedavis/tree-sitter-git-config", rev
13661468[[language]]
13671469name = "git-attributes"
13681470scope = "source.gitattributes"
1369−roots = []
13701471file-types = [".gitattributes"]
13711472injection-regex = "git-attributes"
13721473comment-token = "#"
@@ -1379,8 +1480,7 @@ source = { git = "https://github.com/mtoohey31/tree-sitter-gitattributes", rev =
13791480[[language]]
13801481name = "git-ignore"
13811482scope = "source.gitignore"
1382−roots = []
1383−file-types = [".gitignore", ".gitignore_global"]
1483+file-types = [".gitignore", ".gitignore_global", ".ignore", ".prettierignore", ".eslintignore", ".npmignore", "CODEOWNERS"]
13841484injection-regex = "git-ignore"
13851485comment-token = "#"
13861486grammar = "gitignore"
@@ -1394,7 +1494,7 @@ name = "graphql"
13941494scope = "source.graphql"
13951495injection-regex = "graphql"
13961496file-types = ["gql", "graphql", "graphqls"]
1397−roots = []
1497+language-servers = [ "graphql-language-service" ]
13981498indent = { tab-width = 2, unit = " " }
13991499
14001500[[grammar]]
@@ -1421,7 +1521,6 @@ name = "iex"
14211521scope = "source.iex"
14221522injection-regex = "iex"
14231523file-types = ["iex"]
1424−roots = []
14251524
14261525[[grammar]]
14271526name = "iex"
@@ -1440,7 +1539,7 @@ indent = { tab-width = 2, unit = " " }
14401539
14411540[[grammar]]
14421541name = "rescript"
1443−source = { git = "https://github.com/jaredramirez/tree-sitter-rescript", rev = "65609807c628477f3b94052e7ef895885ac51c3c" }
1542+source = { git = "https://github.com/jaredramirez/tree-sitter-rescript", rev = "467dcf99f68c47823d7b378779a6b282d7ef9782" }
14441543
14451544[[language]]
14461545name = "erlang"
@@ -1484,7 +1583,6 @@ scope = "source.hcl"
14841583injection-regex = "(hcl|tf|nomad)"
14851584language-id = "terraform"
14861585file-types = ["hcl", "tf", "nomad"]
1487−roots = []
14881586comment-token = "#"
14891587indent = { tab-width = 2, unit = " " }
14901588language-servers = [ "terraform-ls" ]
@@ -1499,7 +1597,6 @@ name = "tfvars"
14991597scope = "source.tfvars"
15001598language-id = "terraform-vars"
15011599file-types = ["tfvars"]
1502−roots = []
15031600comment-token = "#"
15041601indent = { tab-width = 2, unit = " " }
15051602language-servers = [ "terraform-ls" ]
@@ -1511,7 +1608,6 @@ name = "org"
15111608scope = "source.org"
15121609injection-regex = "org"
15131610file-types = ["org"]
1514−roots = []
15151611indent = { tab-width = 2, unit = " " }
15161612
15171613[[grammar]]
@@ -1523,7 +1619,6 @@ name = "solidity"
15231619scope = "source.sol"
15241620injection-regex = "(sol|solidity)"
15251621file-types = ["sol"]
1526−roots = []
15271622comment-token = "//"
15281623indent = { tab-width = 4, unit = " " }
15291624language-servers = [ "solc" ]
@@ -1545,17 +1640,19 @@ auto-format = true
15451640
15461641[[grammar]]
15471642name = "gleam"
1548−source = { git = "https://github.com/gleam-lang/tree-sitter-gleam", rev = "a59aadf3d7c11702cad244e7cd6b67b34ca9c16a" }
1643+source = { git = "https://github.com/gleam-lang/tree-sitter-gleam", rev = "b2afa4fd6bb41a7bf912b034c653c90af7ae5122" }
15491644
15501645[[language]]
15511646name = "ron"
15521647scope = "source.ron"
15531648injection-regex = "ron"
15541649file-types = ["ron"]
1555−roots = []
15561650comment-token = "//"
15571651indent = { tab-width = 4, unit = " " }
1558−grammar = "rust"
1652+
1653+[[grammar]]
1654+name = "ron"
1655+source = { git = "https://github.com/zee-editor/tree-sitter-ron", rev = "7762d709a0f7c1f9e269d0125a2e8a7a69006146" }
15591656
15601657[[language]]
15611658name = "robot"
@@ -1563,7 +1660,6 @@ scope = "source.robot"
15631660injection-regex = "robot"
15641661file-types = ["robot", "resource"]
15651662comment-token = "#"
1566−roots = []
15671663indent = { tab-width = 4, unit = " " }
15681664language-servers = [ "robotframework_ls" ]
15691665
@@ -1575,9 +1671,8 @@ source = { git = "https://github.com/Hubro/tree-sitter-robot", rev = "322e4cc657
15751671name = "r"
15761672scope = "source.r"
15771673injection-regex = "(r|R)"
1578−file-types = ["r", "R", ".Rprofile", "Rprofile.site"]
1674+file-types = ["r", "R", ".Rprofile", "Rprofile.site", ".RHistory"]
15791675shebangs = ["r", "R"]
1580−roots = []
15811676comment-token = "#"
15821677indent = { tab-width = 2, unit = " " }
15831678language-servers = [ "r" ]
@@ -1589,9 +1684,9 @@ source = { git = "https://github.com/r-lib/tree-sitter-r", rev = "cc04302e1bff76
15891684[[language]]
15901685name = "rmarkdown"
15911686scope = "source.rmd"
1687+language-id = "rmd"
15921688injection-regex = "(r|R)md"
15931689file-types = ["rmd", "Rmd"]
1594−roots = []
15951690indent = { tab-width = 2, unit = " " }
15961691grammar = "markdown"
15971692language-servers = [ "r" ]
@@ -1615,7 +1710,6 @@ name = "erb"
16151710scope = "text.html.erb"
16161711injection-regex = "erb"
16171712file-types = ["erb"]
1618−roots = []
16191713indent = { tab-width = 2, unit = " " }
16201714grammar = "embedded-template"
16211715
@@ -1624,7 +1718,6 @@ name = "ejs"
16241718scope = "text.html.ejs"
16251719injection-regex = "ejs"
16261720file-types = ["ejs"]
1627−roots = []
16281721indent = { tab-width = 2, unit = " " }
16291722grammar = "embedded-template"
16301723
@@ -1660,15 +1753,14 @@ source = { git = "https://github.com/phoenixframework/tree-sitter-heex", rev = "
16601753[[language]]
16611754name = "sql"
16621755scope = "source.sql"
1663−file-types = ["sql"]
1664−roots = []
1756+file-types = ["sql", "dsql"]
16651757comment-token = "--"
16661758indent = { tab-width = 4, unit = " " }
16671759injection-regex = "sql"
16681760
16691761[[grammar]]
16701762name = "sql"
1671−source = { git = "https://github.com/DerekStride/tree-sitter-sql", rev = "7cbac0472e5b8f8486ce64ffbcf1982d5cd5fc8d" }
1763+source = { git = "https://github.com/DerekStride/tree-sitter-sql", rev = "25be0b8f17e9189ad9e1b875869d025c5aec1286" }
16721764
16731765[[language]]
16741766name = "gdscript"
@@ -1707,9 +1799,9 @@ scope = "source.nu"
17071799injection-regex = "nu"
17081800file-types = ["nu"]
17091801shebangs = ["nu"]
1710−roots = []
17111802comment-token = "#"
17121803indent = { tab-width = 2, unit = " " }
1804+language-servers = [ "nu-lsp" ]
17131805
17141806[[grammar]]
17151807name = "nu"
@@ -1720,7 +1812,6 @@ name = "vala"
17201812scope = "source.vala"
17211813injection-regex = "vala"
17221814file-types = ["vala", "vapi"]
1723−roots = []
17241815comment-token = "//"
17251816indent = { tab-width = 2, unit = " " }
17261817language-servers = [ "vala-language-server" ]
@@ -1734,7 +1825,6 @@ name = "hare"
17341825scope = "source.hare"
17351826injection-regex = "hare"
17361827file-types = ["ha"]
1737−roots = []
17381828comment-token = "//"
17391829indent = { tab-width = 8, unit = "\t" }
17401830
@@ -1747,7 +1837,6 @@ name = "devicetree"
17471837scope = "source.devicetree"
17481838injection-regex = "(dtsi?|devicetree|fdt)"
17491839file-types = ["dts", "dtsi"]
1750−roots = []
17511840comment-token = "//"
17521841indent = { tab-width = 4, unit = "\t" }
17531842
@@ -1760,7 +1849,6 @@ name = "cairo"
17601849scope = "source.cairo"
17611850injection-regex = "cairo"
17621851file-types = ["cairo"]
1763−roots = []
17641852comment-token = "//"
17651853indent = { tab-width = 4, unit = " " }
17661854# auto-format = true
@@ -1772,7 +1860,6 @@ name = "cpon"
17721860scope = "scope.cpon"
17731861injection-regex = "cpon"
17741862file-types = ["cpon", "cp"]
1775−roots = []
17761863auto-format = true
17771864comment-token = "//"
17781865indent = { tab-width = 2, unit = " " }
@@ -1799,8 +1886,7 @@ source = { git = "https://github.com/ap29600/tree-sitter-odin", rev = "b219207e4
17991886name = "meson"
18001887scope = "source.meson"
18011888injection-regex = "meson"
1802−file-types = ["meson.build"]
1803−roots = []
1889+file-types = ["meson.build", "meson_options.txt"]
18041890comment-token = "#"
18051891indent = { tab-width = 2, unit = " " }
18061892
@@ -1812,7 +1898,6 @@ source = { git = "https://github.com/staysail/tree-sitter-meson", rev = "32a83e8
18121898name = "sshclientconfig"
18131899scope = "source.sshclientconfig"
18141900file-types = [{ suffix = ".ssh/config" }, { suffix = "/etc/ssh/ssh_config" }]
1815−roots = []
18161901comment-token = "#"
18171902
18181903[[grammar]]
@@ -1824,7 +1909,7 @@ name = "scheme"
18241909scope = "source.scheme"
18251910injection-regex = "scheme"
18261911file-types = ["ss", "scm"]
1827−roots = []
1912+shebangs = ["scheme", "guile", "chicken"]
18281913comment-token = ";"
18291914indent = { tab-width = 2, unit = " " }
18301915
@@ -1851,7 +1936,6 @@ source = {git = "https://github.com/v-analyzer/v-analyzer", subpath = "tree_sitt
18511936name = "verilog"
18521937scope = "source.verilog"
18531938file-types = ["v", "vh", "sv", "svh"]
1854−roots = []
18551939comment-token = "//"
18561940language-servers = [ "svlangserver" ]
18571941indent = { tab-width = 2, unit = " " }
@@ -1866,7 +1950,6 @@ name = "edoc"
18661950scope = "source.edoc"
18671951file-types = ["edoc", "edoc.in"]
18681952injection-regex = "edoc"
1869−roots = []
18701953indent = { tab-width = 4, unit = " " }
18711954
18721955[[grammar]]
@@ -1878,7 +1961,6 @@ name = "jsdoc"
18781961scope = "source.jsdoc"
18791962injection-regex = "jsdoc"
18801963file-types = ["jsdoc"]
1881−roots = []
18821964indent = { tab-width = 2, unit = " " }
18831965
18841966[[grammar]]
@@ -1890,7 +1972,6 @@ name = "openscad"
18901972scope = "source.openscad"
18911973injection-regex = "openscad"
18921974file-types = ["scad"]
1893−roots = []
18941975comment-token = "//"
18951976language-servers = [ "openscad-lsp" ]
18961977indent = { tab-width = 2, unit = "\t" }
@@ -1932,7 +2013,6 @@ name = "starlark"
19322013scope = "source.starlark"
19332014injection-regex = "(starlark|bzl|bazel)"
19342015file-types = ["bzl", "bazel", "BUILD", "star"]
1935−roots = []
19362016comment-token = "#"
19372017indent = { tab-width = 4, unit = " " }
19382018grammar = "python"
@@ -1941,7 +2021,6 @@ grammar = "python"
19412021name = "elvish"
19422022scope = "source.elvish"
19432023file-types = ["elv"]
1944−roots = []
19452024comment-token = "#"
19462025indent = { tab-width = 2, unit = " " }
19472026language-servers = [ "elvish" ]
@@ -1957,7 +2036,6 @@ scope = "source.idr"
19572036injection-regex = "idr"
19582037file-types = ["idr"]
19592038shebangs = []
1960−roots = []
19612039comment-token = "--"
19622040indent = { tab-width = 2, unit = " " }
19632041language-servers = [ "idris2-lsp" ]
@@ -1981,20 +2059,18 @@ name = "ungrammar"
19812059scope = "source.ungrammar"
19822060injection-regex = "ungrammar"
19832061file-types = ["ungram", "ungrammar"]
1984−roots = []
19852062comment-token = "//"
19862063indent = { tab-width = 2, unit = " " }
19872064
19882065[[grammar]]
19892066name = "ungrammar"
1990−source = { git = "https://github.com/Philipp-M/tree-sitter-ungrammar", rev = "0113de880a58ea14f2a75802e9b99fcc25003d9c" }
2067+source = { git = "https://github.com/Philipp-M/tree-sitter-ungrammar", rev = "a7e104629cff5a8b7367187610631e8f5eb7c6ea" }
19912068
19922069[[language]]
19932070name = "dot"
19942071scope = "source.dot"
19952072injection-regex = "dot"
19962073file-types = ["dot"]
1997−roots = []
19982074comment-token = "//"
19992075indent = { tab-width = 4, unit = " " }
20002076language-servers = [ "dot-language-server" ]
@@ -2024,7 +2100,6 @@ name = "slint"
20242100scope = "source.slint"
20252101injection-regex = "slint"
20262102file-types = ["slint"]
2027−roots = []
20282103comment-token = "//"
20292104indent = { tab-width = 4, unit = " " }
20302105language-servers = [ "slint-lsp" ]
@@ -2038,7 +2113,6 @@ name = "task"
20382113scope = "source.task"
20392114injection-regex = "task"
20402115file-types = ["task"]
2041−roots = []
20422116comment-token = "#"
20432117indent = { tab-width = 2, unit = " " }
20442118
@@ -2051,7 +2125,6 @@ name = "xit"
20512125scope = "source.xit"
20522126injection-regex = "xit"
20532127file-types = ["xit"]
2054−roots = []
20552128indent = { tab-width = 4, unit = " " }
20562129
20572130[[grammar]]
@@ -2069,14 +2142,13 @@ roots = ["edgedb.toml"]
20692142
20702143[[grammar]]
20712144name ="esdl"
2072−source = { git = "https://github.com/greym0uth/tree-sitter-esdl", rev = "b840c8a8028127e0a7c6e6c45141adade2bd75cf" }
2145+source = { git = "https://github.com/greym0uth/tree-sitter-esdl", rev = "df83acc8cacd0cfb139eecee0e718dc32c4f92e2" }
20732146
20742147[[language]]
20752148name = "pascal"
20762149scope = "source.pascal"
20772150injection-regex = "pascal"
20782151file-types = ["pas", "pp", "inc", "lpr", "lfm"]
2079−roots = []
20802152comment-token = "//"
20812153indent = { tab-width = 2, unit = " " }
20822154language-servers = [ "pasls" ]
@@ -2091,7 +2163,6 @@ scope = "source.sml"
20912163injection-regex = "sml"
20922164file-types = ["sml"]
20932165comment-token = "(*"
2094−roots = []
20952166
20962167[[grammar]]
20972168name = "sml"
@@ -2115,19 +2186,17 @@ name = "astro"
21152186scope = "source.astro"
21162187injection-regex = "astro"
21172188file-types = ["astro"]
2118−roots = []
21192189indent = { tab-width = 2, unit = " " }
21202190
21212191[[grammar]]
21222192name = "astro"
2123−source = { git = "https://github.com/virchau13/tree-sitter-astro", rev = "5f5c3e73c45967df9aa42f861fad2d77cd4e0900" }
2193+source = { git = "https://github.com/virchau13/tree-sitter-astro", rev = "947e93089e60c66e681eba22283f4037841451e7" }
21242194
21252195[[language]]
21262196name = "bass"
21272197scope = "source.bass"
21282198injection-regex = "bass"
21292199file-types = ["bass"]
2130−roots = []
21312200comment-token = ";"
21322201indent = { tab-width = 2, unit = " " }
21332202language-servers = [ "bass" ]
@@ -2141,7 +2210,6 @@ name = "wat"
21412210scope = "source.wat"
21422211comment-token = ";;"
21432212file-types = ["wat"]
2144−roots = []
21452213
21462214[[grammar]]
21472215name = "wat"
@@ -2152,7 +2220,6 @@ name = "wast"
21522220scope = "source.wast"
21532221comment-token = ";;"
21542222file-types = ["wast"]
2155−roots = []
21562223
21572224[[grammar]]
21582225name = "wast"
@@ -2162,7 +2229,6 @@ source = { git = "https://github.com/wasm-lsp/tree-sitter-wasm", rev = "2ca28a9f
21622229name = "d"
21632230scope = "source.d"
21642231file-types = [ "d", "dd" ]
2165−roots = []
21662232comment-token = "//"
21672233injection-regex = "d"
21682234indent = { tab-width = 4, unit = " "}
@@ -2171,13 +2237,12 @@ formatter = { command = "dfmt" }
21712237
21722238[[grammar]]
21732239name = "d"
2174−source = { git = "https://github.com/gdamore/tree-sitter-d", rev="601c4a1e8310fb2f3c43fa8a923d0d27497f3c04" }
2240+source = { git = "https://github.com/gdamore/tree-sitter-d", rev = "5566f8ce8fc24186fad06170bbb3c8d97c935d74" }
21752241
21762242[[language]]
21772243name = "vhs"
21782244scope = "source.vhs"
21792245file-types = ["tape"]
2180−roots = []
21812246comment-token = "#"
21822247indent = { tab-width = 2, unit = " " }
21832248grammar = "vhs"
@@ -2190,21 +2255,76 @@ source = { git = "https://github.com/charmbracelet/tree-sitter-vhs", rev = "c6d8
21902255name = "kdl"
21912256scope = "source.kdl"
21922257file-types = ["kdl"]
2193−roots = []
21942258comment-token = "//"
21952259injection-regex = "kdl"
21962260
21972261[[grammar]]
21982262name = "kdl"
2199−source = { git = "https://github.com/Unoqwy/tree-sitter-kdl", rev = "e1cd292c6d15df6610484e1d4b5c987ecad52373" }
2263+source = { git = "https://github.com/amaanq/tree-sitter-kdl", rev = "3ca569b9f9af43593c24f9e7a21f02f43a13bb88" }
22002264
22012265[[language]]
22022266name = "xml"
22032267scope = "source.xml"
22042268injection-regex = "xml"
2205−file-types = ["xml", "mobileconfig", "plist", "xib", "storyboard", "svg", "xsd", "gml", "xaml", "gir"]
2269+file-types = [
2270+ "xml",
2271+ "mobileconfig",
2272+ "plist",
2273+ "xib",
2274+ "storyboard",
2275+ "svg",
2276+ "xsd",
2277+ "gml",
2278+ "xaml",
2279+ "gir",
2280+ "rss",
2281+ "atom",
2282+ "opml",
2283+ "policy",
2284+ "ascx",
2285+ "axml",
2286+ "axaml",
2287+ "bpmn",
2288+ "cpt",
2289+ "csl",
2290+ "csproj.user",
2291+ "dita",
2292+ "ditamap",
2293+ "dtml",
2294+ "fxml",
2295+ "iml",
2296+ "isml",
2297+ "jmx",
2298+ "launch",
2299+ "menu",
2300+ "mxml",
2301+ "nuspec",
2302+ "pt",
2303+ "publishsettings",
2304+ "pubxml",
2305+ "pubxml.user",
2306+ "rbxlx",
2307+ "rbxmx",
2308+ "rng",
2309+ "shproj",
2310+ "tld",
2311+ "tmx",
2312+ "vbproj.user",
2313+ "vcxproj",
2314+ "vcxproj.filters",
2315+ "wsdl",
2316+ "wxi",
2317+ "wxs",
2318+ "xbl",
2319+ "xlf",
2320+ "xliff",
2321+ "xpdl",
2322+ "xul",
2323+ "xoml",
2324+ "musicxml",
2325+ "glif"
2326+]
22062327indent = { tab-width = 2, unit = " " }
2207−roots = []
22082328
22092329[language.auto-pairs]
22102330'(' = ')'
@@ -2225,7 +2345,6 @@ scope = "source.dtd"
22252345injection-regex = "dtd"
22262346file-types = ["dtd", "ent"]
22272347indent = {tab-width = 2, unit = " "}
2228−roots = []
22292348
22302349[language.auto-pairs]
22312350'(' = ')'
@@ -2243,7 +2362,6 @@ name = "wit"
22432362scope = "source.wit"
22442363injection-regex = "wit"
22452364file-types = ["wit"]
2246−roots = []
22472365comment-token = "//"
22482366indent = { tab-width = 2, unit = " " }
22492367
@@ -2262,11 +2380,10 @@ source = { git = "https://github.com/hh9527/tree-sitter-wit", rev = "c917790ab9a
22622380[[language]]
22632381name = "env"
22642382scope = "source.env"
2265−file-types = [".env", ".env.local", ".env.development", ".env.production", ".env.dist", ".envrc"]
2383+file-types = [".env", ".env.local", ".env.development", ".env.production", ".env.dist", ".envrc", ".envrc.local", ".envrc.private"]
22662384injection-regex = "env"
22672385comment-token = "#"
22682386indent = { tab-width = 4, unit = "\t" }
2269−roots = []
22702387grammar = "bash"
22712388
22722389[[language]]
@@ -2290,12 +2407,15 @@ file-types = [
22902407 "container",
22912408 "volume",
22922409 "kube",
2293− "network"
2410+ "network",
2411+ ".editorconfig",
2412+ "properties",
2413+ "cfg",
2414+ "directory"
22942415]
22952416injection-regex = "ini"
22962417comment-token = "#"
22972418indent = { tab-width = 4, unit = "\t" }
2298−roots = []
22992419
23002420[[grammar]]
23012421name = "ini"
@@ -2305,7 +2425,6 @@ source = { git = "https://github.com/justinmk/tree-sitter-ini", rev = "4d247fb87
23052425name = "bicep"
23062426scope = "source.bicep"
23072427file-types = ["bicep"]
2308−roots = []
23092428auto-format = true
23102429comment-token = "//"
23112430indent = { tab-width = 2, unit = " "}
@@ -2319,7 +2438,6 @@ source = { git = "https://github.com/the-mikedavis/tree-sitter-bicep", rev = "d8
23192438name = "qml"
23202439scope = "source.qml"
23212440file-types = ["qml"]
2322−roots = []
23232441language-servers = [ "qmlls" ]
23242442indent = { tab-width = 4, unit = " " }
23252443grammar = "qmljs"
@@ -2333,7 +2451,6 @@ name = "mermaid"
23332451scope = "source.mermaid"
23342452injection-regex = "mermaid"
23352453file-types = ["mermaid"]
2336−roots = []
23372454comment-token = "%%"
23382455indent = { tab-width = 4, unit = " " }
23392456
@@ -2347,7 +2464,6 @@ scope = "source.m"
23472464file-types = ["m"]
23482465comment-token = "%"
23492466shebangs = ["octave-cli", "matlab"]
2350−roots = []
23512467indent = { tab-width = 2, unit = " " }
23522468
23532469[[grammar]]
@@ -2372,7 +2488,6 @@ name = "dhall"
23722488scope = "source.dhall"
23732489injection-regex = "dhall"
23742490file-types = ["dhall"]
2375−roots = []
23762491comment-token = "--"
23772492indent = { tab-width = 2, unit = " " }
23782493language-servers = [ "dhall-lsp-server" ]
@@ -2387,7 +2502,6 @@ name = "sage"
23872502scope = "source.sage"
23882503file-types = ["sage"]
23892504injection-regex = "sage"
2390−roots = []
23912505comment-token = "#"
23922506indent = { tab-width = 4, unit = " " }
23932507grammar = "python"
@@ -2398,7 +2512,6 @@ scope = "source.msbuild"
23982512injection-regex = "msbuild"
23992513file-types = ["proj", "vbproj", "csproj", "fsproj", "targets", "props"]
24002514indent = { tab-width = 2, unit = " " }
2401−roots = []
24022515grammar = "xml"
24032516
24042517[language.auto-pairs]
@@ -2414,7 +2527,6 @@ name = "pem"
24142527scope = "source.pem"
24152528file-types = ["pem", "cert", "crt"]
24162529injection-regex = "pem"
2417−roots = []
24182530grammar = "pem"
24192531
24202532[[grammar]]
@@ -2425,7 +2537,6 @@ source = { git = "https://github.com/mtoohey31/tree-sitter-pem", rev = "be67a433
24252537name = "passwd"
24262538scope = "source.passwd"
24272539file-types = ["passwd"]
2428−roots = []
24292540
24302541[[grammar]]
24312542name = "passwd"
@@ -2435,7 +2546,6 @@ source = { git = "https://github.com/ath3/tree-sitter-passwd", rev = "20239395ea
24352546name = "hosts"
24362547scope = "source.hosts"
24372548file-types = ["hosts"]
2438−roots = []
24392549comment-token = "#"
24402550
24412551[[grammar]]
@@ -2447,20 +2557,18 @@ name = "uxntal"
24472557scope = "source.tal"
24482558injection-regex = "tal"
24492559file-types = ["tal"]
2450−roots = []
24512560auto-format = false
24522561comment-token = "("
24532562
24542563[[grammar]]
24552564name = "uxntal"
2456−source = { git = "https://github.com/Jummit/tree-sitter-uxntal", rev = "9297e95ef74380b0ad84c4fd98f91e9f6e4319e6" }
2565+source = { git = "https://github.com/Jummit/tree-sitter-uxntal", rev = "d68406066648cd6db4c6a2f11ec305af02079884" }
24572566
24582567[[language]]
24592568name = "yuck"
24602569scope = "source.yuck"
24612570injection-regex = "yuck"
24622571file-types = ["yuck"]
2463−roots = []
24642572comment-token = ";"
24652573indent = { tab-width = 2, unit = " " }
24662574
@@ -2473,7 +2581,6 @@ name = "prql"
24732581scope = "source.prql"
24742582injection-regex = "prql"
24752583file-types = ["prql"]
2476−roots = []
24772584comment-token = "#"
24782585indent = { tab-width = 4, unit = " " }
24792586
@@ -2485,7 +2592,6 @@ source = { git = "https://github.com/PRQL/tree-sitter-prql", rev = "09e158cd3650
24852592name = "po"
24862593scope = "source.po"
24872594file-types = ["po", "pot"]
2488−roots = []
24892595comment-token = "#"
24902596
24912597[[grammar]]
@@ -2495,9 +2601,8 @@ source = { git = "https://github.com/erasin/tree-sitter-po", rev = "417cee9abb20
24952601[[language]]
24962602name = "nasm"
24972603scope = "source.nasm"
2498−file-types = ["asm", "s", "S", "nasm"]
2604+file-types = ["asm", "S", "nasm"]
24992605injection-regex = "n?asm"
2500−roots = []
25012606comment-token = ";"
25022607indent = { tab-width = 8, unit = " " }
25032608
@@ -2505,12 +2610,23 @@ indent = { tab-width = 8, unit = " " }
25052610name = "nasm"
25062611source = { git = "https://github.com/naclsn/tree-sitter-nasm", rev = "a0db15db6fcfb1bf2cc8702500e55e558825c48b" }
25072612
2613+[[language]]
2614+name = "gas"
2615+scope = "source.gas"
2616+file-types = ["s"]
2617+injection-regex = "gas"
2618+comment-token = "#"
2619+indent = { tab-width = 8, unit = " " }
2620+
2621+[[grammar]]
2622+name = "gas"
2623+source = { git = "https://github.com/sirius94/tree-sitter-gas", rev = "60f443646b20edee3b7bf18f3a4fb91dc214259a" }
2624+
25082625[[language]]
25092626name = "rst"
25102627scope = "source.rst"
25112628comment-token = ".."
25122629file-types = ["rst"]
2513−roots = []
25142630
25152631[[grammar]]
25162632name = "rst"
@@ -2521,7 +2637,6 @@ name = "capnp"
25212637scope = "source.capnp"
25222638injection-regex = "capnp"
25232639file-types = ["capnp"]
2524−roots = []
25252640comment-token = "#"
25262641indent = { tab-width = 2, unit = " " }
25272642
@@ -2547,7 +2662,6 @@ source = { git = "https://github.com/indoorvivants/tree-sitter-smithy", rev = "c
25472662name = "vhdl"
25482663scope = "source.vhdl"
25492664file-types = ["vhd", "vhdl"]
2550−roots = []
25512665comment-token = "--"
25522666language-servers = [ "vhdl_ls" ]
25532667indent = { tab-width = 2, unit = " " }
@@ -2559,7 +2673,6 @@ source = { git = "https://github.com/teburd/tree-sitter-vhdl", rev = "c57313adee
25592673
25602674[[language]]
25612675name = "rego"
2562−roots = []
25632676scope = "source.rego"
25642677injection-regex = "rego"
25652678file-types = ["rego"]
@@ -2570,7 +2683,7 @@ grammar = "rego"
25702683
25712684[[grammar]]
25722685name = "rego"
2573−source = { git = "https://github.com/FallenAngel97/tree-sitter-rego", rev = "b2667c975f07b33be3ceb83bea5cfbad88095866" }
2686+source = { git = "https://github.com/FallenAngel97/tree-sitter-rego", rev = "9ac75e71b2d791e0aadeef68098319d86a2a14cf" }
25742687
25752688[[language]]
25762689name = "nim"
@@ -2578,7 +2691,6 @@ scope = "source.nim"
25782691injection-regex = "nim"
25792692file-types = ["nim", "nims", "nimble"]
25802693shebangs = []
2581−roots = []
25822694comment-token = "#"
25832695indent = { tab-width = 2, unit = " " }
25842696language-servers = [ "nimlangserver" ]
@@ -2602,13 +2714,13 @@ file-types = [ "cabal" ]
26022714roots = ["cabal.project", "Setup.hs"]
26032715indent = { tab-width = 2, unit = " " }
26042716comment-token = "--"
2717+language-servers = [ "haskell-language-server" ]
26052718
26062719[[language]]
26072720name = "hurl"
26082721scope = "source.hurl"
26092722injection-regex = "hurl"
26102723file-types = ["hurl"]
2611−roots = []
26122724comment-token = "#"
26132725indent = { tab-width = 2, unit = " " }
26142726
@@ -2619,7 +2731,6 @@ source = { git = "https://github.com/pfeiferj/tree-sitter-hurl", rev = "264c4206
26192731[[language]]
26202732name = "markdoc"
26212733scope = "text.markdoc"
2622−roots = []
26232734file-types = ["mdoc"]
26242735language-servers = [ "markdoc-ls" ]
26252736
@@ -2632,7 +2743,6 @@ name = "opencl"
26322743scope = "source.cl"
26332744injection-regex = "(cl|opencl)"
26342745file-types = ["cl"]
2635−roots = []
26362746comment-token = "//"
26372747language-servers = [ "clangd" ]
26382748
@@ -2645,7 +2755,6 @@ name = "just"
26452755scope = "source.just"
26462756file-types = ["justfile", "Justfile", ".justfile", ".Justfile"]
26472757injection-regex = "just"
2648−roots = []
26492758comment-token = "#"
26502759indent = { tab-width = 4, unit = "\t" }
26512760
@@ -2653,12 +2762,25 @@ indent = { tab-width = 4, unit = "\t" }
26532762name = "just"
26542763source = { git = "https://github.com/IndianBoy42/tree-sitter-just", rev = "8af0aab79854aaf25b620a52c39485849922f766" }
26552764
2765+[[language]]
2766+name = "gn"
2767+scope = "source.gn"
2768+injection-regex = "gn"
2769+file-types = ["gn", "gni"]
2770+roots = []
2771+comment-token = "#"
2772+indent = { tab-width = 2, unit = " " }
2773+formatter = { command = "gn", args = ["format", "--stdin"] }
2774+
2775+[[grammar]]
2776+name = "gn"
2777+source = { git = "https://github.com/willcassella/tree-sitter-gn", rev = "e18d6e36a79b20dafb58f19d407bd38b0e60260e" }
2778+
26562779[[language]]
26572780name = "blueprint"
26582781scope = "source.blueprint"
26592782injection-regex = "blueprint"
26602783file-types = ["blp"]
2661−roots = []
26622784comment-token = "//"
26632785language-servers = [ "blueprint-compiler" ]
26642786indent = { tab-width = 4, unit = " " }
@@ -2672,21 +2794,20 @@ name = "forth"
26722794scope = "source.forth"
26732795injection-regex = "forth"
26742796file-types = ["fs", "forth", "fth", "4th"]
2675−roots = []
26762797comment-token = "\\"
26772798language-servers = [ "forth-lsp" ]
26782799indent = { tab-width = 3, unit = " " }
26792800
26802801[[grammar]]
26812802name = "forth"
2682−source = { git = "https://github.com/alexanderbrevig/tree-sitter-forth", rev = "304ed77beb113e37af38b20ff14e3c37bf350d10" }
2803+source = { git = "https://github.com/alexanderbrevig/tree-sitter-forth", rev = "90189238385cf636b9ee99ce548b9e5b5e569d48" }
26832804
26842805[[language]]
26852806name = "fsharp"
26862807scope = "source.fs"
26872808roots = ["sln", "fsproj"]
26882809injection-regex = "fsharp"
2689−file-types = ["fs", "fsx"]
2810+file-types = ["fs", "fsx", "fsi", "fsscript"]
26902811comment-token = "//"
26912812indent = { tab-width = 4, unit = " " }
26922813auto-format = true
@@ -2701,7 +2822,6 @@ name = "t32"
27012822scope = "source.t32"
27022823injection-regex = "t32"
27032824file-types = ["cmm", "t32"]
2704−roots = []
27052825comment-token = ";"
27062826indent = { tab-width = 2, unit = " " }
27072827
@@ -2714,16 +2834,34 @@ name = "webc"
27142834scope = "text.html.webc"
27152835injection-regex = "webc"
27162836file-types = ["webc"]
2717−roots = []
27182837indent = { tab-width = 2, unit = " " }
27192838grammar = "html"
27202839
2840+[[language]]
2841+name = "typst"
2842+scope = "source.typst"
2843+injection-regex = "typst"
2844+file-types = ["typst", "typ"]
2845+comment-token = "//"
2846+language-servers = ["typst-lsp"]
2847+indent = { tab-width = 2, unit = " " }
2848+
2849+[language.auto-pairs]
2850+'(' = ')'
2851+'{' = '}'
2852+'[' = ']'
2853+'$' = '$'
2854+'"' = '"'
2855+
2856+[[grammar]]
2857+name = "typst"
2858+source = { git = "https://github.com/uben0/tree-sitter-typst", rev = "e35aa22395fdde82bbc4b5700c324ce346dfc9e5" }
2859+
27212860[[language]]
27222861name = "nunjucks"
27232862scope = "text.html.nunjucks"
27242863injection-regex = "nunjucks"
27252864file-types = ["njk"]
2726−roots = []
27272865indent = { tab-width = 2, unit = " " }
27282866grammar = "jinja2"
27292867
@@ -2732,7 +2870,6 @@ name = "jinja"
27322870scope = "text.html.jinja"
27332871injection-regex = "jinja"
27342872file-types = ["jinja", "jinja2", "j2"]
2735−roots = []
27362873indent = { tab-width = 2, unit = " " }
27372874grammar = "jinja2"
27382875
@@ -2749,7 +2886,6 @@ name = "wren"
27492886scope = "source.wren"
27502887injection-regex = "wren"
27512888file-types = ["wren"]
2752−roots = []
27532889indent = { tab-width = 2, unit = " "}
27542890
27552891[[language]]
@@ -2758,7 +2894,6 @@ scope = "source.unison"
27582894injection-regex = "unison"
27592895file-types = ["u"]
27602896shebangs = []
2761−roots = []
27622897auto-format = false
27632898comment-token = "--"
27642899indent = { tab-width = 4, unit = " " }
@@ -2778,7 +2913,6 @@ source = { git = "https://github.com/kylegoetz/tree-sitter-unison", rev = "98c4e
27782913name = "todotxt"
27792914scope = "text.todotxt"
27802915file-types = [{ suffix = ".todo.txt" }, "todotxt"]
2781−roots = []
27822916formatter = { command = "sort" }
27832917auto-format = true
27842918
@@ -2790,7 +2924,6 @@ source = { git = "https://github.com/arnarg/tree-sitter-todotxt", rev = "0207f6a
27902924name = "strace"
27912925scope = "source.strace"
27922926file-types = ["strace"]
2793−roots = []
27942927
27952928[[grammar]]
27962929name = "strace"
@@ -2800,8 +2933,76 @@ source = { git = "https://github.com/sigmaSd/tree-sitter-strace", rev = "2b18fdf
28002933name = "gemini"
28012934scope = "source.gmi"
28022935file-types = ["gmi"]
2803−roots = []
28042936
28052937[[grammar]]
28062938name = "gemini"
2807−source = { git = "https://git.sr.ht/~sfr/tree-sitter-gemini", rev = "3cc5e4bdf572d5df4277fc2e54d6299bd59a54b3" }
2939+source = { git = "https://git.sr.ht/~nbsp/tree-sitter-gemini", rev = "3cc5e4bdf572d5df4277fc2e54d6299bd59a54b3" }
2940+
2941+[[language]]
2942+name = "agda"
2943+scope = "source.agda"
2944+injection-regex = "agda"
2945+file-types = ["agda"]
2946+roots = []
2947+comment-token = "--"
2948+# language-servers = [ "als" ]
2949+# the agda language server is of questionable functionality.
2950+auto-format = false
2951+indent = { tab-width = 2, unit = " " }
2952+
2953+[language.auto-pairs]
2954+'"' = '"'
2955+"'" = "'"
2956+'{' = '}'
2957+'(' = ')'
2958+'[' = ']'
2959+
2960+# [language.debugger]
2961+# ?? can this be used for proof assistant support? explore
2962+
2963+[[grammar]]
2964+name = "agda"
2965+source = { git = "https://github.com/tree-sitter/tree-sitter-agda", rev = "c21c3a0f996363ed17b8ac99d827fe5a4821f217" }
2966+
2967+[[language]]
2968+name = "templ"
2969+scope = "source.templ"
2970+file-types = ["templ"]
2971+roots = ["go.work", "go.mod"]
2972+comment-token = "//"
2973+indent = { tab-width = 2, unit = " " }
2974+language-servers = [ "templ" ]
2975+
2976+[[grammar]]
2977+name = "templ"
2978+source = { git = "https://github.com/vrischmann/tree-sitter-templ", rev = "ea56ac0655243490a4929a988f4eaa91dfccc995" }
2979+
2980+[[language]]
2981+name = "dbml"
2982+scope = "source.dbml"
2983+injection-regex = "dbml"
2984+file-types = ["dbml"]
2985+comment-token = ";"
2986+indent = { tab-width = 2, unit = " " }
2987+
2988+[[grammar]]
2989+name = "dbml"
2990+source = { git = "https://github.com/dynamotn/tree-sitter-dbml", rev = "2e2fa5640268c33c3d3f27f7e676f631a9c68fd9" }
2991+
2992+[[language]]
2993+name = "log"
2994+scope = "source.log"
2995+file-types = ["log"]
2996+
2997+[[grammar]]
2998+name = "log"
2999+source = { git = "https://github.com/Tudyx/tree-sitter-log", rev = "62cfe307e942af3417171243b599cc7deac5eab9" }
3000+
3001+[[language]]
3002+name = "janet"
3003+scope = "source.janet"
3004+injection-regex = "janet"
3005+file-types = ["janet"]
3006+comment-token = "#"
3007+indent = { tab-width = 2, unit = " " }
3008+grammar = "clojure"
logo.svg+1−1
@@ -1 +1 @@
1−<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;" viewBox="663.38 37.57 575.35 903.75"> <g transform="matrix(1,0,0,1,-31352.7,-1817.25)"> <g transform="matrix(1,0,0,1,31062.7,-20.8972)"> <g transform="matrix(1,0,0,1,-130.173,0.00185558)"> <path d="M1083.58,1875.72L1635.06,2194.12C1649.8,2202.63 1658.88,2218.37 1658.88,2235.39C1658.88,2264.98 1658.88,2311.74 1658.88,2341.33C1658.88,2349.84 1656.61,2358.03 1652.5,2365.16C1652.5,2365.16 1214.7,2112.4 1107.2,2050.33C1092.58,2041.89 1083.58,2026.29 1083.58,2009.41C1083.58,1963.5 1083.58,1875.72 1083.58,1875.72Z" style="fill:#706bc8;"></path> </g> <g transform="matrix(1,0,0,1,-130.173,0.00185558)"> <path d="M1635.26,2604.84C1649.88,2613.28 1658.88,2628.87 1658.88,2645.75C1658.88,2691.67 1658.88,2779.44 1658.88,2779.44L1107.41,2461.05C1092.66,2452.53 1083.58,2436.8 1083.58,2419.78C1083.58,2390.19 1083.58,2343.42 1083.58,2313.84C1083.58,2305.32 1085.85,2297.13 1089.96,2290.01C1089.96,2290.01 1527.76,2542.77 1635.26,2604.84Z" style="fill:#55c5e4;"></path> </g> <g transform="matrix(1,0,0,1,216.062,984.098)"> <path d="M790.407,1432.56C785.214,1435.55 780.717,1439.9 777.509,1445.46C767.862,1462.16 773.473,1483.76 790.004,1493.59L789.998,1493.59L761.173,1476.95C746.427,1468.44 737.344,1452.71 737.344,1435.68C737.344,1406.09 737.344,1359.33 737.344,1329.74C737.344,1312.71 746.427,1296.98 761.173,1288.47L1259.59,1000.74L1259.83,1000.6C1264.92,997.617 1269.33,993.314 1272.48,987.844C1282.13,971.136 1276.52,949.544 1259.99,939.707L1260,939.707L1288.82,956.349C1303.57,964.862 1312.65,980.595 1312.65,997.622C1312.65,1027.21 1312.65,1073.97 1312.65,1103.56C1312.65,1120.59 1303.57,1136.32 1288.82,1144.83L1259.19,1161.94L1259.59,1161.68L790.407,1432.56Z" style="fill:#84ddea;"></path> </g> <g transform="matrix(1,0,0,1,216.062,984.098)"> <path d="M790.407,1686.24C785.214,1689.23 780.717,1693.58 777.509,1699.13C767.862,1715.84 773.473,1737.43 790.004,1747.27L789.998,1747.27L761.173,1730.63C746.427,1722.12 737.344,1706.38 737.344,1689.36C737.344,1659.77 737.344,1613.01 737.344,1583.42C737.344,1566.39 746.427,1550.66 761.173,1542.15L1259.59,1254.42L1259.83,1254.28C1264.92,1251.29 1269.33,1246.99 1272.48,1241.52C1282.13,1224.81 1276.52,1203.22 1259.99,1193.38L1260,1193.38L1288.82,1210.03C1303.57,1218.54 1312.65,1234.27 1312.65,1251.3C1312.65,1280.89 1312.65,1327.65 1312.65,1357.24C1312.65,1374.26 1303.57,1390 1288.82,1398.51L1259.19,1415.61L1259.59,1415.36L790.407,1686.24Z" style="fill:#997bc8;"></path></g></g></g> </svg>
1+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;" viewBox="663.38 37.57 575.35 903.75"><g transform="matrix(1,0,0,1,-31352.7,-1817.25)"><g transform="matrix(1,0,0,1,31062.7,-20.8972)"><g transform="matrix(1,0,0,1,-130.173,0.00185558)"><path style="fill:#706bc8;" d="M1083.58,1875.72L1635.06,2194.12C1649.8,2202.63 1658.88,2218.37 1658.88,2235.39C1658.88,2264.98 1658.88,2311.74 1658.88,2341.33C1658.88,2349.84 1656.61,2358.03 1652.5,2365.16C1652.5,2365.16 1214.7,2112.4 1107.2,2050.33C1092.58,2041.89 1083.58,2026.29 1083.58,2009.41C1083.58,1963.5 1083.58,1875.72 1083.58,1875.72Z"></path></g><g transform="matrix(1,0,0,1,-130.173,0.00185558)"><path style="fill:#55c5e4;" d="M1635.26,2604.84C1649.88,2613.28 1658.88,2628.87 1658.88,2645.75C1658.88,2691.67 1658.88,2779.44 1658.88,2779.44L1107.41,2461.05C1092.66,2452.53 1083.58,2436.8 1083.58,2419.78C1083.58,2390.19 1083.58,2343.42 1083.58,2313.84C1083.58,2305.32 1085.85,2297.13 1089.96,2290.01C1089.96,2290.01 1527.76,2542.77 1635.26,2604.84Z"></path></g><g transform="matrix(1,0,0,1,216.062,984.098)"><path style="fill:#84ddea;" d="M790.407,1432.56C785.214,1435.55 780.717,1439.9 777.509,1445.46C767.862,1462.16 773.473,1483.76 790.004,1493.59L789.998,1493.59L761.173,1476.95C746.427,1468.44 737.344,1452.71 737.344,1435.68C737.344,1406.09 737.344,1359.33 737.344,1329.74C737.344,1312.71 746.427,1296.98 761.173,1288.47L1259.59,1000.74L1259.83,1000.6C1264.92,997.617 1269.33,993.314 1272.48,987.844C1282.13,971.136 1276.52,949.544 1259.99,939.707L1260,939.707L1288.82,956.349C1303.57,964.862 1312.65,980.595 1312.65,997.622C1312.65,1027.21 1312.65,1073.97 1312.65,1103.56C1312.65,1120.59 1303.57,1136.32 1288.82,1144.83L1259.19,1161.94L1259.59,1161.68L790.407,1432.56Z"></path></g><g transform="matrix(1,0,0,1,216.062,984.098)"><path style="fill:#997bc8;" d="M790.407,1686.24C785.214,1689.23 780.717,1693.58 777.509,1699.13C767.862,1715.84 773.473,1737.43 790.004,1747.27L789.998,1747.27L761.173,1730.63C746.427,1722.12 737.344,1706.38 737.344,1689.36C737.344,1659.77 737.344,1613.01 737.344,1583.42C737.344,1566.39 746.427,1550.66 761.173,1542.15L1259.59,1254.42L1259.83,1254.28C1264.92,1251.29 1269.33,1246.99 1272.48,1241.52C1282.13,1224.81 1276.52,1203.22 1259.99,1193.38L1260,1193.38L1288.82,1210.03C1303.57,1218.54 1312.65,1234.27 1312.65,1251.3C1312.65,1280.89 1312.65,1327.65 1312.65,1357.24C1312.65,1374.26 1303.57,1390 1288.82,1398.51L1259.19,1415.61L1259.59,1415.36L790.407,1686.24Z"></path></g></g></g></svg>
runtime/queries/_typescript/highlights.scm+5−3
@@ -39,11 +39,11 @@
3939 (identifier) @variable.parameter))
4040
4141; (p?: t)
42−; (p?: t = 1) // Invalid but still posible to hihglight.
42+; (p?: t = 1) // Invalid but still possible to highlight.
4343(optional_parameter
4444 (identifier) @variable.parameter)
4545
46−; (...p?: t) // Invalid but still posible to hihglight.
46+; (...p?: t) // Invalid but still possible to highlight.
4747(optional_parameter
4848 (rest_pattern
4949 (identifier) @variable.parameter))
@@ -59,7 +59,7 @@
5959 (pair_pattern
6060 value: (identifier) @variable.parameter)))
6161
62−; ([ p ]?: t[]) // Invalid but still posible to hihglight.
62+; ([ p ]?: t[]) // Invalid but still possible to highlight.
6363(optional_parameter
6464 (array_pattern
6565 (identifier) @variable.parameter))
@@ -107,6 +107,8 @@
107107; Types
108108; -----
109109
110+(type_parameter
111+ name: (type_identifier) @type.parameter)
110112(type_identifier) @type
111113(predefined_type) @type.builtin
112114
runtime/queries/_typescript/locals.scm+17
@@ -1,6 +1,18 @@
1+; Scopes
2+;-------
3+
4+[
5+ (type_alias_declaration)
6+ (class_declaration)
7+ (interface_declaration)
8+] @local.scope
9+
110; Definitions
211;------------
312
13+(type_parameter
14+ name: (type_identifier) @local.definition)
15+
416; Javascript and Typescript Treesitter grammars deviate when defining the
517; tree structure for parameters, so we need to address them in each specific
618; language instead of ecma.
@@ -14,3 +26,8 @@
1426; (i?: t = 1) // Invalid but still posible to hihglight.
1527(optional_parameter
1628 (identifier) @local.definition)
29+
30+; References
31+;-----------
32+
33+(type_identifier) @local.reference
runtime/queries/agda/highlights.scmnew file+124
@@ -0,0 +1,124 @@
1+;; Punctuation
2+[ "." ";" ":"] @punctuation.delimiter
3+[ "(" ")" "{" "}" ] @punctuation.bracket
4+
5+;; Constants
6+(integer) @constant.numeric.integer
7+; (float) @constant.numeric.float
8+(literal) @string
9+
10+;; Pragmas and comments
11+(comment) @comment
12+(pragma) @attribute
13+(macro) @function.macro
14+
15+;; Imports
16+(module_name) @namespace
17+(import_directive (id) @namespace)
18+[(module) (import) (open)] @keyword.control.import
19+
20+;; Types
21+(typed_binding (expr) @type)
22+(record (expr) @type)
23+(data (expr) @type)
24+(signature (expr) @type)
25+(function (rhs (expr) @type))
26+; todo: these are too general. ideally, any nested (atom)
27+; https://github.com/tree-sitter/tree-sitter/issues/880
28+
29+;; Variables
30+(untyped_binding (atom) @variable)
31+(typed_binding (atom) @variable)
32+(field_name) @variable.other.member
33+
34+;; Functions
35+(function_name) @function
36+;(function (lhs
37+; . (atom) @function
38+; (atom) @variable.parameter))
39+; todo: currently fails to parse, upstream tree-sitter bug
40+
41+;; Data
42+[(data_name) (record_name)] @constructor
43+((atom) @constant.builtin.boolean
44+ (#any-of? @constant.builtin.boolean "true" "false" "True" "False"))
45+
46+"Set" @type.builtin
47+
48+; postulate
49+; type_signature
50+; pattern
51+; id
52+; bid
53+; typed_binding
54+; primitive
55+; private
56+; record_signature
57+; record_assignments
58+; field_assignment
59+; module_assignment
60+; renaming
61+; import_directive
62+; lambda
63+; let
64+; instance
65+; generalize
66+; record
67+; fields
68+; syntax
69+; hole_name
70+; data_signature
71+
72+;; Keywords
73+[
74+ "where"
75+ "data"
76+ "rewrite"
77+ "postulate"
78+ "public"
79+ "private"
80+ "tactic"
81+ "Prop"
82+ "quote"
83+ "renaming"
84+ "in"
85+ "hiding"
86+ "constructor"
87+ "abstract"
88+ "let"
89+ "field"
90+ "mutual"
91+ "infix"
92+ "infixl"
93+ "infixr"
94+ "record"
95+ "overlap"
96+ "instance"
97+ "do"
98+] @keyword
99+
100+[
101+ "="
102+] @operator
103+
104+; = | -> : ? \ .. ... λ ∀ →
105+; (_LAMBDA) (_FORALL) (_ARROW)
106+; "coinductive"
107+; "eta-equality"
108+; "field"
109+; "inductive"
110+; "interleaved"
111+; "macro"
112+; "no-eta-equality"
113+; "pattern"
114+; "primitive"
115+; "quoteTerm"
116+; "rewrite"
117+; "syntax"
118+; "unquote"
119+; "unquoteDecl"
120+; "unquoteDef"
121+; "using"
122+; "variable"
123+; "with"
124+
runtime/queries/bash/indents.scm+1
@@ -2,6 +2,7 @@
22 (function_definition)
33 (if_statement)
44 (for_statement)
5+ (while_statement)
56 (case_statement)
67 (pipeline)
78] @indent
runtime/queries/c/indents.scm+13
@@ -36,3 +36,16 @@
3636(parameter_list
3737 . (parameter_declaration) @anchor
3838 (#set! "scope" "tail")) @align
39+(argument_list
40+ . (_) @anchor
41+ (#set! "scope" "tail")) @align
42+; These are a bit opinionated since some people just indent binary/ternary expressions spanning multiple lines.
43+; Since they are only triggered when a newline is inserted into an already complete binary/ternary expression,
44+; this should happen rarely, so it is not a big deal either way.
45+; Additionally, adding these queries has the advantage of preventing such continuation lines from being used
46+; as the baseline when the `hybrid` indent heuristic is used (which is desirable since their indentation is so inconsistent).
47+(binary_expression
48+ (#set! "scope" "tail")) @anchor @align
49+(conditional_expression
50+ "?" @anchor
51+ (#set! "scope" "tail")) @align
runtime/queries/comment/highlights.scm+8−8
@@ -7,31 +7,31 @@
77
88; Hint level tags
99((tag (name) @hint)
10− (#match? @hint "^(HINT|MARK)$"))
10+ (#match? @hint "^(HINT|MARK|PASSED|STUB|MOCK)$"))
1111
1212("text" @hint
13− (#match? @hint "^(HINT|MARK)$"))
13+ (#match? @hint "^(HINT|MARK|PASSED|STUB|MOCK)$"))
1414
1515; Info level tags
1616((tag (name) @info)
17− (#match? @info "^(INFO|NOTE|TODO)$"))
17+ (#match? @info "^(INFO|NOTE|TODO|PERF|OPTIMIZE|PERFORMANCE|QUESTION|ASK)$"))
1818
1919("text" @info
20− (#match? @info "^(INFO|NOTE|TODO)$"))
20+ (#match? @info "^(INFO|NOTE|TODO|PERF|OPTIMIZE|PERFORMANCE|QUESTION|ASK)$"))
2121
2222; Warning level tags
2323((tag (name) @warning)
24− (#match? @warning "^(HACK|WARN|WARNING)$"))
24+ (#match? @warning "^(HACK|WARN|WARNING|TEST|TEMP)$"))
2525
2626("text" @warning
27− (#match? @warning "^(HACK|WARN|WARNING)$"))
27+ (#match? @warning "^(HACK|WARN|WARNING|TEST|TEMP)$"))
2828
2929; Error level tags
3030((tag (name) @error)
31− (#match? @error "^(BUG|FIXME|ISSUE|XXX)$"))
31+ (#match? @error "^(BUG|FIXME|ISSUE|XXX|FIX|SAFETY|FIXIT|FAILED|DEBUG)$"))
3232
3333("text" @error
34− (#match? @error "^(BUG|FIXME|ISSUE|XXX)$"))
34+ (#match? @error "^(BUG|FIXME|ISSUE|XXX|FIX|SAFETY|FIXIT|FAILED|DEBUG)$"))
3535
3636(tag
3737 (name) @ui.text
runtime/queries/common-lisp/indents.scmnew file+1
@@ -0,0 +1 @@
1+; inherits: scheme
runtime/queries/dbml/highlights.scmnew file+44
@@ -0,0 +1,44 @@
1+
2+; comments highlighting
3+(comment) @comment
4+
5+; keyword highlighting
6+(keyword_def) @keyword
7+(keyword_enum) @keyword
8+(keyword_ref) @keyword
9+
10+; identify blocks and definitions
11+(definition) @function
12+
13+; for identifiers
14+(identifier) @variable
15+(type) @keyword
16+
17+; Highlight special types for database/data types
18+("Project" ) @type
19+("Table" ) @type
20+("TableGroup" ) @type
21+("database_type" ) @variable
22+
23+; string and number constants
24+("'''") @constant.character.escape
25+(string) @string
26+(number) @constant.numeric
27+
28+; brackets
29+[
30+ "("
31+ ")"
32+ "{"
33+ "}"
34+ "["
35+ "]"
36+] @punctuation.bracket
37+
38+; brackets
39+[
40+ ":"
41+ "."
42+ ","
43+] @punctuation.delimiter
44+
runtime/queries/gas/highlights.scmnew file+21
@@ -0,0 +1,21 @@
1+(comment) @comment
2+(number) @constant.numeric
3+(directive_name) @keyword.directive
4+(symbol) @variable
5+(label) @function
6+(label)
7+(instruction_prefix) @keyword
8+(instruction_name) @function.special
9+(register) @constant.builtin
10+(string) @string
11+(char) @constant.character
12+(type) @type
13+(constant "$" @constant)
14+(operand_modifier) @attribute
15+
16+(expression
17+ ["-" "+" "*" "/" "="] @operator)
18+
19+["(" ")"] @punctuation.bracket
20+
21+["," ":"] @punctuation.delimiter
runtime/queries/gas/injections.scmnew file+2
@@ -0,0 +1,2 @@
1+((comment) @injection.content
2+ (#set! injection.language "comment"))
runtime/queries/gas/textobjects.scmnew file+2
@@ -0,0 +1,2 @@
1+(comment) @comment.inside
2+(comment)+ @comment.around
runtime/queries/gleam/highlights.scm+16−5
@@ -21,6 +21,8 @@
2121
2222; Functions
2323(unqualified_import (identifier) @function)
24+(unqualified_import "type" (type_identifier) @type)
25+(unqualified_import (type_identifier) @constructor)
2426(function
2527 name: (identifier) @function)
2628(external_function
@@ -43,6 +45,13 @@
4345(tuple_access
4446 index: (integer) @variable.other.member)
4547
48+; Attributes
49+(attribute
50+ "@" @attribute
51+ name: (identifier) @attribute)
52+
53+(attribute_value (identifier) @constant)
54+
4655; Type names
4756(remote_type_identifier) @type
4857(type_identifier) @type
@@ -60,10 +69,6 @@
6069(identifier) @variable
6170(discard) @comment.unused
6271
63−; Operators
64−(binary_expression
65− operator: _ @operator)
66−
6772; Keywords
6873[
6974 (visibility_modifier) ; "pub"
@@ -72,6 +77,7 @@
7277 "assert"
7378 "case"
7479 "const"
80+ ; DEPRECATED: 'external' was removed in v0.30.
7581 "external"
7682 "fn"
7783 "if"
@@ -79,11 +85,16 @@
7985 "let"
8086 "panic"
8187 "todo"
82− "try"
8388 "type"
8489 "use"
8590] @keyword
8691
92+; Operators
93+(binary_expression
94+ operator: _ @operator)
95+(boolean_negation "!" @operator)
96+(integer_negation "-" @operator)
97+
8798; Punctuation
8899[
89100 "("
runtime/queries/gn/highlights.scmnew file+42
@@ -0,0 +1,42 @@
1+; Copyright (C) 2021 Will Cassella (github@willcassella.com)
2+;
3+; Licensed under the Apache License, Version 2.0 (the "License");
4+; you may not use this file except in compliance with the License.
5+; You may obtain a copy of the License at
6+;
7+; http://www.apache.org/licenses/LICENSE-2.0
8+;
9+; Unless required by applicable law or agreed to in writing, software
10+; distributed under the License is distributed on an "AS IS" BASIS,
11+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+; See the License for the specific language governing permissions and
13+; limitations under the License.
14+
15+(identifier) @variable.builtin
16+
17+(scope_access field: (_) @variable.other.member)
18+
19+(call target: (_) @function)
20+
21+[ "if" "else" ] @keyword.control.conditional
22+
23+[
24+ (assign_op)
25+ (arithmetic_binary_op)
26+ (comparison_binary_op)
27+ (equivalence_binary_op)
28+ (logical_and_binary_op)
29+ (logical_or_binary_op)
30+ (negation_unary_op)
31+] @operator
32+
33+[ "(" ")" "[" "]" "{" "}" ] @punctuation.bracket
34+[ "." "," ] @punctuation.delimiter
35+
36+(string) @string
37+(string_escape) @constant.character.escape
38+(string_expansion [ "$" "${" "}" ] @constant.character.escape)
39+[ (integer) (hex) ] @constant.numeric
40+(boolean) @constant.builtin.boolean
41+
42+(comment) @comment
runtime/queries/gn/injections.scmnew file+15
@@ -0,0 +1,15 @@
1+; Copyright (C) 2021 Will Cassella (github@willcassella.com)
2+;
3+; Licensed under the Apache License, Version 2.0 (the "License");
4+; you may not use this file except in compliance with the License.
5+; You may obtain a copy of the License at
6+;
7+; http://www.apache.org/licenses/LICENSE-2.0
8+;
9+; Unless required by applicable law or agreed to in writing, software
10+; distributed under the License is distributed on an "AS IS" BASIS,
11+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+; See the License for the specific language governing permissions and
13+; limitations under the License.
14+
15+((comment) @injection.content (#set! injection.language "comment"))
runtime/queries/gn/locals.scmnew file+16
@@ -0,0 +1,16 @@
1+; Copyright (C) 2021 Will Cassella (github@willcassella.com)
2+;
3+; Licensed under the Apache License, Version 2.0 (the "License");
4+; you may not use this file except in compliance with the License.
5+; You may obtain a copy of the License at
6+;
7+; http://www.apache.org/licenses/LICENSE-2.0
8+;
9+; Unless required by applicable law or agreed to in writing, software
10+; distributed under the License is distributed on an "AS IS" BASIS,
11+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+; See the License for the specific language governing permissions and
13+; limitations under the License.
14+
15+(source_file) @local.scope
16+(assignment target: (identifier) @local.definition)
runtime/queries/go/highlights.scm+13−5
@@ -11,6 +11,18 @@
1111 function: (selector_expression
1212 field: (field_identifier) @function.method))
1313
14+
15+; Types
16+
17+(type_parameter_list
18+ (parameter_declaration
19+ name: (identifier) @type.parameter))
20+
21+((type_identifier) @type.builtin
22+ (match? @type.builtin "^(any|bool|byte|comparable|complex128|complex64|error|float32|float64|int|int16|int32|int64|int8|rune|string|uint|uint16|uint32|uint64|uint8|uintptr)$"))
23+
24+(type_identifier) @type
25+
1426; Function definitions
1527
1628(function_declaration
@@ -24,20 +36,16 @@
2436
2537; Identifiers
2638
27−((identifier) @constant (match? @constant "^[A-Z][A-Z\\d_]+$"))
2839(const_spec
2940 name: (identifier) @constant)
3041
3142(parameter_declaration (identifier) @variable.parameter)
3243(variadic_parameter_declaration (identifier) @variable.parameter)
3344
34−((type_identifier) @type.builtin
35− (match? @type.builtin "^(any|bool|byte|comparable|complex128|complex64|error|float32|float64|int|int16|int32|int64|int8|rune|string|uint|uint16|uint32|uint64|uint8|uintptr)$"))
36−
37−(type_identifier) @type
3845(type_spec
3946 name: (type_identifier) @constructor)
4047(field_identifier) @variable.other.member
48+(keyed_element (literal_element (identifier) @variable.other.member))
4149(identifier) @variable
4250(package_identifier) @namespace
4351
runtime/queries/go/locals.scm+10−2
@@ -1,9 +1,17 @@
11; Scopes
22
3−(block) @local.scope
3+[
4+ (function_declaration)
5+ (type_declaration)
6+ (block)
7+] @local.scope
48
59; Definitions
610
11+(type_parameter_list
12+ (parameter_declaration
13+ name: (identifier) @local.definition))
14+
715(parameter_declaration (identifier) @local.definition)
816(variadic_parameter_declaration (identifier) @local.definition)
917
@@ -27,4 +35,4 @@
2735
2836(identifier) @local.reference
2937(field_identifier) @local.reference
30−
38+(type_identifier) @local.reference
runtime/queries/haskell/highlights.scm+24−11
@@ -33,6 +33,11 @@
3333;; ----------------------------------------------------------------------------
3434;; Keywords, operators, includes
3535
36+[
37+ "forall"
38+ "∀"
39+] @keyword.control.repeat
40+
3641(pragma) @constant.macro
3742
3843[
@@ -68,10 +73,7 @@
6873 "@"
6974] @operator
7075
71−(qualified_module (module) @constructor)
72−(qualified_type (module) @namespace)
73−(qualified_variable (module) @namespace)
74−(import (module) @namespace)
76+(module) @namespace
7577
7678[
7779 (where)
@@ -92,8 +94,6 @@
9294 "do"
9395 "mdo"
9496 "rec"
95− "forall"
96− "∀"
9797 "infix"
9898 "infixl"
9999 "infixr"
@@ -104,22 +104,35 @@
104104;; Functions and variables
105105
106106(signature name: (variable) @type)
107−(function name: (variable) @function)
108−
109−(variable) @variable
110−"_" @variable.builtin
107+(function
108+ name: (variable) @function
109+ patterns: (patterns))
110+((signature (fun)) . (function (variable) @function))
111+((signature (context (fun))) . (function (variable) @function))
112+((signature (forall (context (fun)))) . (function (variable) @function))
111113
112114(exp_infix (variable) @operator) ; consider infix functions as operators
113115
114−("@" @namespace) ; "as" pattern operator, e.g. x@Constructor
116+(exp_infix (exp_name) @function)
117+(exp_apply . (exp_name (variable) @function))
118+(exp_apply . (exp_name (qualified_variable (variable) @function)))
115119
120+(variable) @variable
121+(pat_wildcard) @variable
116122
117123;; ----------------------------------------------------------------------------
118124;; Types
119125
120126(type) @type
127+(type_variable) @type.parameter
121128
122129(constructor) @constructor
123130
124131; True or False
125132((constructor) @_bool (#match? @_bool "(True|False)")) @constant.builtin.boolean
133+
134+;; ----------------------------------------------------------------------------
135+;; Quasi-quotes
136+
137+(quoter) @function
138+; Highlighting of quasiquote_body is handled by injections.scm
runtime/queries/janet/highlights.scmnew file+1
@@ -0,0 +1 @@
1+; inherits: clojure
runtime/queries/json5/highlights.scmnew file+11
@@ -0,0 +1,11 @@
1+(string) @string
2+
3+(identifier) @constant
4+
5+(number) @constant.numeric
6+
7+(null) @constant.builtin
8+
9+[(true) (false)] @constant.builtin.boolean
10+
11+(comment) @comment
runtime/queries/kdl/highlights.scm+4−4
@@ -1,12 +1,12 @@
1−(comment) @comment
21(single_line_comment) @comment
2+(multi_line_comment) @comment
33
44(node
5− name: (identifier) @function)
5+ (identifier) @variable)
6+
67(prop (identifier) @attribute)
7−(type) @type
88
9−(bare_identifier) @variable.other.member
9+(type (_) @type) @punctuation.bracket
1010
1111(keyword) @keyword
1212
runtime/queries/kdl/indents.scmnew file+3
@@ -0,0 +1,3 @@
1+(node_children) @indent
2+
3+ "}" @outdent
runtime/queries/kdl/textobjects.scmnew file+27
@@ -0,0 +1,27 @@
1+(type (_) @test.inside) @test.around
2+
3+(node
4+ children: (node_children)? @class.inside) @class.around
5+
6+(node
7+ children: (node_children)? @function.inside) @function.around
8+
9+(node (identifier) @function.movement)
10+
11+[
12+ (single_line_comment)
13+ (multi_line_comment)
14+] @comment.inside
15+
16+[
17+ (single_line_comment)+
18+ (multi_line_comment)+
19+] @comment.around
20+
21+[
22+ (prop)
23+ (value)
24+] @parameter.inside
25+
26+(value (type) ? (_) @parameter.inside @parameter.movement . ) @parameter.around
27+
runtime/queries/kotlin/highlights.scm+4−1
@@ -244,7 +244,10 @@
244244 . (identifier)) @namespace
245245
246246((type_identifier) @type.builtin
247− (#match? @function.builtin "^(Byte|Short|Int|Long|UByte|UShort|UInt|ULong|Float|Double|Boolean|Char|String|Array|ByteArray|ShortArray|IntArray|LongArray|UByteArray|UShortArray|UIntArray|ULongArray|FloatArray|DoubleArray|BooleanArray|CharArray|Map|Set|List|EmptyMap|EmptySet|EmptyList|MutableMap|MutableSet|MutableList)$"))
247+ (#match? @type.builtin "^(Byte|Short|Int|Long|UByte|UShort|UInt|ULong|Float|Double|Boolean|Char|String|Array|ByteArray|ShortArray|IntArray|LongArray|UByteArray|UShortArray|UIntArray|ULongArray|FloatArray|DoubleArray|BooleanArray|CharArray|Map|Set|List|EmptyMap|EmptySet|EmptyList|MutableMap|MutableSet|MutableList)$"))
248+
249+(type_parameter
250+ (type_identifier) @type.parameter)
248251
249252(type_identifier) @type
250253
runtime/queries/kotlin/locals.scmnew file+15
@@ -0,0 +1,15 @@
1+; Scopes
2+
3+[
4+ (class_declaration)
5+ (function_declaration)
6+] @local.scope
7+
8+; Definitions
9+
10+(type_parameter
11+ (type_identifier) @local.definition)
12+
13+; References
14+
15+(type_identifier) @local.reference
runtime/queries/log/highlights.scmnew file+10
@@ -0,0 +1,10 @@
1+(trace) @comment
2+(debug) @hint
3+(info) @info
4+(warn) @warning
5+(error) @error
6+(year_month_day) @keyword
7+(time) @constant
8+(string_literal) @string
9+(number) @constant.numeric
10+(constant) @constant.builtin
runtime/queries/lpf/highlights.scmnew file+19
@@ -0,0 +1,19 @@
1+[
2+ "SYSCONFIG"
3+ "BLOCK"
4+ "LOCATE"
5+ "COMP"
6+ "FREQUENCY"
7+ "PORT"
8+ "IOBUF"
9+] @keyword
10+
11+["SITE"] @keyword.storage
12+
13+["="] @operator
14+
15+((number) @constant.numeric)
16+
17+((string) @string)
18+((line_comment) @comment)
19+
runtime/queries/nix/injections.scm+14
@@ -5,6 +5,20 @@
55((((comment) @injection.language) .
66 (indented_string_expression (string_fragment) @injection.content))
77 (#set! injection.combined))
8+((binding
9+ (comment) @injection.language
10+ expression: (indented_string_expression (string_fragment) @injection.content))
11+ (#set! injection.combined))
12+
13+; Common attribute keys corresponding to Python scripts,
14+; such as those for NixOS VM tests in nixpkgs/nixos/tests.
15+((binding
16+ attrpath: (attrpath (identifier) @_path)
17+ expression: (indented_string_expression
18+ (string_fragment) @injection.content))
19+ (#match? @_path "(^|\\.)testScript$")
20+ (#set! injection.language "python")
21+ (#set! injection.combined))
822
923; Common attribute keys corresponding to scripts,
1024; such as those of stdenv.mkDerivation.
runtime/queries/ocaml/highlights.scm+2
@@ -8,6 +8,8 @@
88
99[(class_name) (class_type_name) (type_constructor)] @type
1010
11+(type_variable) @type.parameter
12+
1113[(constructor_name) (tag)] @constructor
1214
1315; Functions
runtime/queries/perl/indents.scmnew file+29
@@ -0,0 +1,29 @@
1+[
2+ (block)
3+ (conditional_statement)
4+ (loop_statement)
5+ (cstyle_for_statement)
6+ (for_statement)
7+ (elsif)
8+ (array_element_expression)
9+ (hash_element_expression)
10+ (coderef_call_expression)
11+ (anonymous_slice_expression)
12+ (slice_expression)
13+ (keyval_expression)
14+ (anonymous_array_expression)
15+ (anonymous_hash_expression)
16+ (stub_expression)
17+ (func0op_call_expression)
18+ (func1op_call_expression)
19+ (map_grep_expression)
20+ (function_call_expression)
21+ (method_call_expression)
22+ (attribute)
23+] @indent
24+
25+[
26+ "}"
27+ "]"
28+ ")"
29+] @outdent
runtime/queries/perl/textobjects.scmnew file+14
@@ -0,0 +1,14 @@
1+(subroutine_declaration_statement
2+ body: (_) @function.inside) @function.around
3+(anonymous_subroutine_expression
4+ body: (_) @function.inside) @function.around
5+
6+(package_statement) @class.around
7+(package_statement
8+ (block) @class.inside)
9+
10+(list_expression
11+ (_) @parameter.inside)
12+
13+(comment) @comment.around
14+(pod) @comment.around
runtime/queries/purescript/highlights.scm+164−1
@@ -1 +1,164 @@
1−; inherits: haskell
1+; ----------------------------------------------------------------------------
2+; Record fields would need to come before literal strings in order to be captured correctly
3+
4+ (record_accessor
5+ field: [ (variable)
6+ (string)
7+ (triple_quote_string)
8+ ] @variable.other.member)
9+
10+ (exp_record_access
11+ field: [ (variable)
12+ (string)
13+ (triple_quote_string)
14+ ] @variable.other.member)
15+
16+
17+; ----------------------------------------------------------------------------
18+; Literals and comments
19+
20+ (integer) @constant.numeric.integer
21+ (exp_negation) @constant.numeric.integer
22+ (exp_literal (number)) @constant.numeric.float
23+ (char) @constant.character
24+ [
25+ (string)
26+ (triple_quote_string)
27+ ] @string
28+
29+ (comment) @comment
30+
31+
32+; ----------------------------------------------------------------------------
33+; Punctuation
34+
35+ [
36+ "("
37+ ")"
38+ "{"
39+ "}"
40+ "["
41+ "]"
42+ ] @punctuation.bracket
43+
44+ [
45+ (comma)
46+ ";"
47+ ] @punctuation.delimiter
48+
49+
50+; ----------------------------------------------------------------------------
51+; Keywords, operators, includes
52+
53+ ; This needs to come before the other "else" in
54+ ; order to be highlighted correctly
55+ (class_instance "else" @keyword)
56+
57+ [
58+ "if"
59+ "then"
60+ "else"
61+ "case"
62+ "of"
63+ ] @keyword.control.conditional
64+
65+ [
66+ "import"
67+ "module"
68+ ] @keyword.control.import
69+
70+ [
71+ (operator)
72+ (constructor_operator)
73+ (type_operator)
74+ (qualified_module) ; grabs the `.` (dot), ex: import System.IO
75+ (all_names)
76+
77+ ; `_` wildcards in if-then-else and case-of expressions,
78+ ; as well as record updates and operator sections
79+ (wildcard)
80+ "="
81+ "|"
82+ "::"
83+ "∷"
84+ "=>"
85+ "⇒"
86+ "<="
87+ "⇐"
88+ "->"
89+ "→"
90+ "<-"
91+ "←"
92+ "\\"
93+ "`"
94+ "@"
95+ ] @operator
96+
97+ (qualified_module (module) @constructor)
98+ (module) @namespace
99+ (qualified_type (module) @namespace)
100+ (qualified_variable (module) @namespace)
101+ (import (module) @namespace)
102+
103+ [
104+ (where)
105+ "let"
106+ "in"
107+ "class"
108+ "instance"
109+ "derive"
110+ "foreign"
111+ "data"
112+ "newtype"
113+ "type"
114+ "as"
115+ "hiding"
116+ "do"
117+ "ado"
118+ "forall"
119+ "∀"
120+ "infix"
121+ "infixl"
122+ "infixr"
123+ ] @keyword
124+
125+ (type_role_declaration
126+ "role" @keyword
127+ role: (type_role) @keyword)
128+
129+ (hole) @label
130+
131+; ----------------------------------------------------------------------------
132+; Functions and variables
133+
134+ (row_field (field_name) @variable.other.member)
135+ (record_field (field_name) @variable.other.member)
136+ (record_field (field_pun) @variable.other.member)
137+
138+ (signature name: (variable) @type)
139+ (function name: (variable) @function)
140+ (class_instance (instance_name) @function)
141+ (derive_declaration (instance_name) @function)
142+
143+ ; true or false
144+ ((variable) @constant.builtin.boolean
145+ (#match? @constant.builtin.boolean "^(true|false)$"))
146+
147+ ; The former one works for `tree-sitter highlight` but not in Helix/Kakoune.
148+ ; The latter two work in Helix (but not Kakoune) and are a good compromise between not highlighting anything at all
149+ ; as an operator and leaving it to the child nodes, and highlighting everything as an operator.
150+ (exp_ticked (_) @operator)
151+ (exp_ticked (exp_name (variable) @operator))
152+ (exp_ticked (exp_name (qualified_variable (variable) @operator)))
153+
154+ (variable) @variable
155+
156+ ("@" @namespace) ; "as" pattern operator, e.g. x@Constructor
157+
158+; ----------------------------------------------------------------------------
159+; Types
160+
161+ (type) @type
162+
163+ (constructor) @constructor
164+
runtime/queries/purescript/injections.scm+2−1
@@ -1 +1,2 @@
1−; inherits: haskell
1+((comment) @injection.content
2+ (#set! injection.language "comment"))
runtime/queries/purescript/locals.scm+4−1
@@ -1 +1,4 @@
1−; inherits: haskell
1+(signature name: (variable)) @local.definition
2+(function name: (variable)) @local.definition
3+(pat_name (variable)) @local.definition
4+(exp_name (variable)) @local.reference
runtime/queries/purescript/textobjects.scmnew file+13
@@ -0,0 +1,13 @@
1+(comment) @comment.inside
2+
3+[
4+ (data)
5+ (type)
6+ (newtype)
7+] @class.around
8+
9+((signature)? (function rhs:(_) @function.inside)) @function.around
10+(exp_lambda) @function.around
11+
12+(data (type_variable) @parameter.inside)
13+(patterns (_) @parameter.inside)
runtime/queries/python/highlights.scm+6
@@ -134,14 +134,17 @@
134134 "//="
135135 "/="
136136 "&"
137+ "&="
137138 "%"
138139 "%="
139140 "^"
141+ "^="
140142 "+"
141143 "->"
142144 "+="
143145 "<"
144146 "<<"
147+ "<<="
145148 "<="
146149 "<>"
147150 "="
@@ -150,8 +153,11 @@
150153 ">"
151154 ">="
152155 ">>"
156+ ">>="
153157 "|"
158+ "|="
154159 "~"
160+ "@="
155161] @operator
156162
157163[
runtime/queries/racket/indents.scmnew file+1
@@ -0,0 +1 @@
1+; inherits: scheme
runtime/queries/ron/highlights.scm+43−1
@@ -1 +1,43 @@
1−; inherits: rust
1+; Literals
2+;------------
3+
4+(string) @string
5+(boolean) @constant.builtin.boolean
6+(integer) @constant.numeric.integer
7+(float) @constant.numeric.float
8+(char) @constant.character
9+
10+; Structs
11+;------------
12+
13+(enum_variant) @type.enum.variant
14+(struct_entry (_) @variable.other.member ":")
15+(struct_name (identifier)) @type
16+
17+
18+
19+
20+; Comments
21+;------------
22+
23+(line_comment) @comment.line
24+(block_comment) @comment.block
25+
26+
27+; Punctuation
28+;------------
29+
30+"," @punctuation.delimiter
31+":" @punctuation.delimiter
32+
33+"(" @punctuation.bracket
34+")" @punctuation.bracket
35+"[" @punctuation.bracket
36+"]" @punctuation.bracket
37+"{" @punctuation.bracket
38+"}" @punctuation.bracket
39+
40+
41+; Special
42+;------------
43+(escape_sequence) @constant.character.escape
runtime/queries/ron/indents.scm+12−1
@@ -1 +1,12 @@
1−; inherits: rust
1+[
2+ (array)
3+ (map)
4+ (tuple)
5+ (struct)
6+] @indent
7+
8+[
9+ "}"
10+ "]"
11+ ")"
12+] @outdent
runtime/queries/ron/injections.scm+2−1
@@ -1 +1,2 @@
1−; inherits: rust
1+([(line_comment) (block_comment)] @injection.content
2+ (#set! injection.language "comment"))
runtime/queries/rust/highlights.scm+7
@@ -9,6 +9,13 @@
99; Types
1010; -------
1111
12+(type_parameters
13+ (type_identifier) @type.parameter)
14+(constrained_type_parameter
15+ left: (type_identifier) @type.parameter)
16+(optional_type_parameter
17+ name: (type_identifier) @type.parameter)
18+
1219; ---
1320; Primitives
1421; ---
runtime/queries/rust/injections.scm+6
@@ -1,6 +1,12 @@
11([(line_comment) (block_comment)] @injection.content
22 (#set! injection.language "comment"))
33
4+((macro_invocation
5+ macro: (identifier) @_html (#eq? @_html "html")
6+ (token_tree) @injection.content)
7+ (#set! injection.language "html")
8+ (#set! injection.include-children))
9+
410((macro_invocation
511 (token_tree) @injection.content)
612 (#set! injection.language "rust")
runtime/queries/rust/locals.scm+14−1
@@ -2,6 +2,12 @@
22
33[
44 (function_item)
5+ (struct_item)
6+ (enum_item)
7+ (union_item)
8+ (type_item)
9+ (trait_item)
10+ (impl_item)
511 (closure_expression)
612 (block)
713] @local.scope
@@ -11,8 +17,15 @@
1117(parameter
1218 (identifier) @local.definition)
1319
20+(type_parameters
21+ (type_identifier) @local.definition)
22+(constrained_type_parameter
23+ left: (type_identifier) @local.definition)
24+(optional_type_parameter
25+ name: (type_identifier) @local.definition)
26+
1427(closure_parameters (identifier) @local.definition)
1528
1629; References
1730(identifier) @local.reference
18−
31+(type_identifier) @local.reference
runtime/queries/scheme/highlights.scm+5
@@ -97,3 +97,8 @@
9797
9898["(" ")" "[" "]" "{" "}"] @punctuation.bracket
9999
100+(quote "'") @operator
101+(unquote_splicing ",@") @operator
102+(unquote ",") @operator
103+(quasiquote "`") @operator
104+
runtime/queries/scheme/indents.scmnew file+43
@@ -0,0 +1,43 @@
1+; This roughly follows the description at: https://github.com/ds26gte/scmindent#how-subforms-are-indented
2+
3+; Exclude literals in the first patterns, since different rules apply for them.
4+; Similarly, exclude certain keywords (detected by a regular expression).
5+; If a list has 2 elements on the first line, it is aligned to the second element.
6+(list . (_) @first . (_) @anchor
7+ (#same-line? @first @anchor)
8+ (#set! "scope" "tail")
9+ (#not-kind-eq? @first "boolean") (#not-kind-eq? @first "character") (#not-kind-eq? @first "string") (#not-kind-eq? @first "number")
10+ (#not-match? @first "def.*|let.*|set!")) @align
11+; If the first element in a list is also a list and on a line by itself, the outer list is aligned to it
12+(list . (list) @anchor .
13+ (#set! "scope" "tail")
14+ (#not-kind-eq? @first "boolean") (#not-kind-eq? @first "character") (#not-kind-eq? @first "string") (#not-kind-eq? @first "number")) @align
15+(list . (list) @anchor . (_) @second
16+ (#not-same-line? @anchor @second)
17+ (#set! "scope" "tail")
18+ (#not-kind-eq? @first "boolean") (#not-kind-eq? @first "character") (#not-kind-eq? @first "string") (#not-kind-eq? @first "number")
19+ (#not-match? @first "def.*|let.*|set!")) @align
20+; If the first element in a list is not a list and on a line by itself, the outer list is aligned to
21+; it plus 1 additional space. This cannot currently be modelled exactly by our indent queries,
22+; but the following is equivalent, assuming that:
23+; - the indent width is 2 (the default for scheme)
24+; - There is no space between the opening parenthesis of the list and the first element
25+(list . (_) @first .
26+ (#not-kind-eq? @first "boolean") (#not-kind-eq? @first "character") (#not-kind-eq? @first "string") (#not-kind-eq? @first "number")
27+ (#not-match? @first "def.*|let.*|set!")) @indent
28+(list . (_) @first . (_) @second
29+ (#not-same-line? @first @second)
30+ (#not-kind-eq? @first "boolean") (#not-kind-eq? @first "character") (#not-kind-eq? @first "string") (#not-kind-eq? @first "number")
31+ (#not-match? @first "def.*|let.*|set!")) @indent
32+
33+; If the first element in a list is a literal, align the list to it
34+(list . [(boolean) (character) (string) (number)] @anchor
35+ (#set! "scope" "tail")) @align
36+
37+; If the first element is among a set of predefined keywords, align the list to this element
38+; plus 1 space (using the same workaround as above for now). This is a simplification since actually
39+; the second line of the list should be indented by 2 spaces more in some cases. Supporting this would
40+; be possible but require significantly more patterns.
41+(list . (symbol) @first
42+ (#match? @first "def.*|let.*|set!")) @indent
43+
runtime/queries/smali/folds.scmnew file+12
@@ -0,0 +1,12 @@
1+[
2+ (annotation_directive)
3+ (array_data_directive)
4+ (field_definition)
5+ (method_definition)
6+ (packed_switch_directive)
7+ (param_directive)
8+ (parameter_directive)
9+ (sparse_switch_directive)
10+ (subannotation_directive)
11+ (list)
12+] @fold
runtime/queries/smali/highlights.scmnew file+216
@@ -0,0 +1,216 @@
1+; Types
2+
3+(class_identifier
4+ (identifier) @type)
5+
6+(primitive_type) @type.builtin
7+
8+((class_identifier
9+ . (identifier) @_first @type.builtin
10+ (identifier) @type.builtin)
11+ (#match? @_first "^(android|dalvik|java|kotlinx)$"))
12+
13+((class_identifier
14+ . (identifier) @_first @type.builtin
15+ . (identifier) @_second @type.builtin
16+ (identifier) @type.builtin)
17+ (#eq? @_first "com")
18+ (#match? @_second "^(android|google)$"))
19+
20+; Methods
21+
22+(method_definition
23+ (method_signature (method_identifier) @function.method))
24+
25+(expression
26+ (opcode) @_invoke
27+ (body
28+ (full_method_signature
29+ (method_signature (method_identifier) @function.method)))
30+ (#match? @_invoke "^invoke"))
31+
32+(expression
33+ (opcode) @_field_access
34+ (body
35+ (field_identifier) @variable.other.member)
36+ (#match? @_field_access "^[is](get|put)-"))
37+
38+(method_handle
39+ (full_method_signature
40+ (method_signature (method_identifier) @function.method)))
41+
42+(custom_invoke
43+ . (identifier) @function.method
44+ (method_signature (method_identifier) @function.method))
45+
46+(annotation_value
47+ (body
48+ (method_signature (method_identifier) @function.method)))
49+
50+(annotation_value
51+ (body
52+ (full_method_signature
53+ (method_signature (method_identifier) @function.method))))
54+
55+(field_definition
56+ (body
57+ (method_signature (method_identifier) @function.method)))
58+
59+(field_definition
60+ (body
61+ (full_method_signature
62+ (method_signature (method_identifier) @function.method))))
63+
64+((method_identifier) @constructor
65+ (#match? @constructor "^(<init>|<clinit>)$"))
66+
67+"constructor" @constructor
68+
69+; Fields
70+
71+[
72+ (field_identifier)
73+ (annotation_key)
74+] @variable.other.member
75+
76+((field_identifier) @constant
77+ (#match? @constant "^[%u_]*$"))
78+
79+; Variables
80+
81+(variable) @variable.builtin
82+
83+(local_directive
84+ (identifier) @variable)
85+
86+; Parameters
87+
88+(parameter) @variable.parameter
89+(param_identifier) @variable.parameter
90+
91+; Labels
92+
93+[
94+ (label)
95+ (jmp_label)
96+] @label
97+
98+; Operators
99+
100+; (opcode) @keyword.operator
101+
102+((opcode) @keyword.control.return
103+ (#match? @keyword.control.return "^return"))
104+
105+((opcode) @keyword.control.conditional
106+ (#match? @keyword.control.conditional "^if"))
107+
108+((opcode) @keyword.control.conditional
109+ (#match? @keyword.control.conditional "^cmp"))
110+
111+((opcode) @keyword.control.exception
112+ (#match? @keyword.control.exception "^throw"))
113+
114+[
115+ "="
116+ ".."
117+] @operator
118+
119+; Keywords
120+
121+[
122+ ".class"
123+ ".super"
124+ ".implements"
125+ ".field"
126+ ".end field"
127+ ".annotation"
128+ ".end annotation"
129+ ".subannotation"
130+ ".end subannotation"
131+ ".param"
132+ ".end param"
133+ ".parameter"
134+ ".end parameter"
135+ ".local"
136+ ".end local"
137+ ".restart local"
138+ ".registers"
139+ ".packed-switch"
140+ ".end packed-switch"
141+ ".sparse-switch"
142+ ".end sparse-switch"
143+ ".array-data"
144+ ".end array-data"
145+ ".enum"
146+ (prologue_directive)
147+ (epilogue_directive)
148+] @keyword
149+
150+[
151+ ".source"
152+] @keyword.directive
153+
154+[
155+ ".method"
156+ ".end method"
157+] @keyword.function
158+
159+[
160+ ".catch"
161+ ".catchall"
162+] @keyword.control.exception
163+
164+; Literals
165+
166+(string) @string
167+(source_directive (string "\"" _ @string.special.url "\""))
168+(escape_sequence) @constant.character.escape
169+
170+(character) @constant.character
171+
172+"L" @punctuation
173+
174+(line_directive (number) @comment) @comment
175+(".locals" (number) @comment) @comment
176+
177+(number) @constant.numeric.integer
178+
179+[
180+ (float)
181+ (NaN)
182+ (Infinity)
183+] @constant.numeric.float
184+
185+(boolean) @constant.builtin.boolean
186+
187+(null) @constant.builtin
188+
189+; Misc
190+
191+(annotation_visibility) @keyword.storage.modifier
192+
193+(access_modifier) @keyword.storage.type
194+
195+(array_type
196+ "[" @punctuation.special)
197+
198+["{" "}"] @punctuation.bracket
199+
200+["(" ")"] @punctuation.bracket
201+
202+[
203+ "->"
204+ ","
205+ ":"
206+ ";"
207+ "@"
208+ "/"
209+] @punctuation.delimiter
210+
211+; Comments
212+
213+(comment) @comment
214+
215+(class_definition
216+ (comment) @comment.block.documentation)
runtime/queries/smali/indents.scmnew file+31
@@ -0,0 +1,31 @@
1+[
2+ (annotation_directive)
3+ (array_data_directive)
4+ (field_definition)
5+ (method_definition)
6+ (packed_switch_directive)
7+ (param_directive)
8+ (parameter_directive)
9+ (sparse_switch_directive)
10+ (subannotation_directive)
11+ (list)
12+ "\{"
13+] @indent
14+
15+[
16+ ".end annotation"
17+ ".end array-data"
18+ ".end field"
19+ ".end method"
20+ ".end packed-switch"
21+ ".end param"
22+ ".end parameter"
23+ ".end sparse-switch"
24+ ".end subannotation"
25+ "\}"
26+] @outdent
27+
28+[
29+ (ERROR)
30+ (comment)
31+] @indent.always
runtime/queries/smali/injections.scmnew file+2
@@ -0,0 +1,2 @@
1+((comment) @injection.content
2+ (#set! injection.language "comment"))
runtime/queries/smali/locals.scmnew file+42
@@ -0,0 +1,42 @@
1+[
2+ (class_directive)
3+ (expression)
4+ (annotation_directive)
5+ (array_data_directive)
6+ (method_definition)
7+ (packed_switch_directive)
8+ (sparse_switch_directive)
9+ (subannotation_directive)
10+] @local.scope
11+
12+[
13+ (identifier)
14+ (class_identifier)
15+ (label)
16+ (jmp_label)
17+] @local.reference
18+
19+(enum_reference
20+ (field_identifier) @local.definition)
21+
22+((field_definition
23+ (access_modifiers) @_mod
24+ (field_identifier) @local.definition)
25+ (#eq? @_mod "enum"))
26+
27+(field_definition
28+ (field_identifier) @local.definition
29+ (field_type) @local.definition)
30+
31+(annotation_key) @local.definition
32+
33+(method_definition
34+ (method_signature (method_identifier) @local.definition))
35+
36+(param_identifier) @local.definition
37+
38+(annotation_directive
39+ (class_identifier) @local.definition)
40+
41+(class_directive
42+ (class_identifier) @local.definition)
runtime/queries/sql/highlights.scm+317−231
@@ -1,134 +1,169 @@
1+(invocation
2+ (object_reference
3+ name: (identifier) @function.method))
14
25[
6+ (keyword_gist)
37 (keyword_btree)
48 (keyword_hash)
5− (keyword_gist)
69 (keyword_spgist)
710 (keyword_gin)
811 (keyword_brin)
9−
10− (cast)
11− (group_concat)
12− (invocation)
12+ (keyword_array)
1313] @function.builtin
14−
15−(table_reference
16− name: (identifier) @namespace)
1714
18−(relation
19− table_alias: (identifier) @variable.parameter)
20−
21−(field
15+(object_reference
2216 name: (identifier) @variable.other.member)
23−
17+
18+(relation
19+ alias: (identifier) @variable.parameter)
20+
2421(field
25− table_alias: (identifier) @variable.parameter
2622 name: (identifier) @variable.other.member)
2723
28−(comment) @comment
24+(term
25+ alias: (identifier) @variable.parameter)
2926
30−[
31− "("
32− ")"
33−] @punctuation.bracket
27+(term
28+ value: (cast
29+ name: (keyword_cast) @function.builtin
30+ parameter: [(literal)]?))
3431
35−[
36− ";"
37− ","
38− "."
39−] @punctuation.delimiter
32+(literal) @string
33+(comment) @comment.line
34+(marginalia) @comment.block
4035
41−(binary_expression
42− operator: _ @operator)
36+((literal) @constant.numeric.integer
37+ (#match? @constant.numeric.integer "^-?\\d+$"))
4338
44−(unary_expression
45− operator: _ @operator)
39+((literal) @constant.numeric.float
40+ (#match? @constant.numeric.float "^-?\\d*\\.\\d*$"))
4641
47−(all_fields) @special
42+(parameter) @variable.parameter
4843
4944[
50− (keyword_null)
51− (keyword_true)
52− (keyword_false)
53−] @constant.builtin
45+ (keyword_true)
46+ (keyword_false)
47+] @constant.builtin.boolean
5448
55−((literal) @constant.numeric
56− (#match? @constant.numeric "^-?\\d*\\.?\\d*$"))
49+[
50+ (keyword_asc)
51+ (keyword_desc)
52+ (keyword_terminated)
53+ (keyword_escaped)
54+ (keyword_unsigned)
55+ (keyword_nulls)
56+ (keyword_last)
57+ (keyword_delimited)
58+ (keyword_replication)
59+ (keyword_auto_increment)
60+ (keyword_default)
61+ (keyword_collate)
62+ (keyword_concurrently)
63+ (keyword_engine)
64+ (keyword_always)
65+ (keyword_generated)
66+ (keyword_preceding)
67+ (keyword_following)
68+ (keyword_first)
69+ (keyword_current_timestamp)
70+ (keyword_immutable)
71+ (keyword_atomic)
72+ (keyword_parallel)
73+ (keyword_leakproof)
74+ (keyword_safe)
75+ (keyword_cost)
76+ (keyword_strict)
77+] @attribute
5778
58−(literal) @string
79+[
80+ (keyword_materialized)
81+ (keyword_recursive)
82+ (keyword_temp)
83+ (keyword_temporary)
84+ (keyword_unlogged)
85+ (keyword_external)
86+ (keyword_parquet)
87+ (keyword_csv)
88+ (keyword_rcfile)
89+ (keyword_textfile)
90+ (keyword_orc)
91+ (keyword_avro)
92+ (keyword_jsonfile)
93+ (keyword_sequencefile)
94+ (keyword_volatile)
95+] @keyword.storage.type
96+
97+[
98+ (keyword_case)
99+ (keyword_when)
100+ (keyword_then)
101+ (keyword_else)
102+] @keyword.control.conditional
59103
60104[
61105 (keyword_select)
106+ (keyword_from)
107+ (keyword_where)
108+ (keyword_index)
109+ (keyword_join)
110+ (keyword_primary)
62111 (keyword_delete)
112+ (keyword_create)
63113 (keyword_insert)
114+ (keyword_merge)
115+ (keyword_distinct)
64116 (keyword_replace)
65117 (keyword_update)
66118 (keyword_into)
67119 (keyword_overwrite)
120+ (keyword_matched)
68121 (keyword_values)
122+ (keyword_value)
123+ (keyword_attribute)
69124 (keyword_set)
70− (keyword_from)
71125 (keyword_left)
72126 (keyword_right)
127+ (keyword_outer)
73128 (keyword_inner)
74129 (keyword_full)
75− (keyword_outer)
76− (keyword_cross)
77− (keyword_join)
78− (keyword_lateral)
79− (keyword_on)
80− (keyword_not)
81130 (keyword_order)
82− (keyword_group)
83131 (keyword_partition)
84− (keyword_by)
132+ (keyword_group)
133+ (keyword_with)
134+ (keyword_without)
135+ (keyword_as)
85136 (keyword_having)
86− (keyword_desc)
87− (keyword_asc)
88137 (keyword_limit)
89138 (keyword_offset)
90− (keyword_primary)
91− (keyword_create)
92− (keyword_alter)
93− (keyword_change)
94− (keyword_analyze)
95− (keyword_modify)
96− (keyword_drop)
97− (keyword_add)
98139 (keyword_table)
99140 (keyword_tables)
100− (keyword_view)
101− (keyword_materialized)
102− (keyword_column)
103141 (keyword_key)
104− (keyword_as)
105− (keyword_distinct)
142+ (keyword_references)
143+ (keyword_foreign)
106144 (keyword_constraint)
107− ; (keyword_cast)
108− ; (keyword_group_concat)
109− (keyword_separator)
110− (keyword_max)
111− (keyword_min)
112− (keyword_avg)
113− (keyword_end)
114145 (keyword_force)
115− (keyword_ignore)
116− (keyword_using)
117146 (keyword_use)
118− (keyword_index)
119147 (keyword_for)
120148 (keyword_if)
121149 (keyword_exists)
122− (keyword_auto_increment)
123− (keyword_generated)
124− (keyword_always)
125− (keyword_collate)
126− (keyword_character)
127− (keyword_engine)
128− (keyword_default)
129− (keyword_cascade)
130− (keyword_restrict)
131− (keyword_with)
150+ (keyword_max)
151+ (keyword_min)
152+ (keyword_avg)
153+ (keyword_column)
154+ (keyword_columns)
155+ (keyword_cross)
156+ (keyword_lateral)
157+ (keyword_natural)
158+ (keyword_alter)
159+ (keyword_drop)
160+ (keyword_add)
161+ (keyword_view)
162+ (keyword_end)
163+ (keyword_is)
164+ (keyword_using)
165+ (keyword_between)
166+ (keyword_window)
132167 (keyword_no)
133168 (keyword_data)
134169 (keyword_type)
@@ -136,208 +171,259 @@
136171 (keyword_to)
137172 (keyword_schema)
138173 (keyword_owner)
139− (keyword_temp)
140− (keyword_temporary)
141− (keyword_unlogged)
142− (keyword_union)
174+ (keyword_authorization)
143175 (keyword_all)
144176 (keyword_any)
145177 (keyword_some)
146− (keyword_except)
147− (keyword_intersect)
148178 (keyword_returning)
149179 (keyword_begin)
150180 (keyword_commit)
151181 (keyword_rollback)
152182 (keyword_transaction)
183+ (keyword_only)
184+ (keyword_like)
185+ (keyword_similar)
153186 (keyword_over)
154− (keyword_nulls)
155− (keyword_first)
187+ (keyword_change)
188+ (keyword_modify)
156189 (keyword_after)
157− (keyword_last)
158− (keyword_window)
190+ (keyword_before)
159191 (keyword_range)
160192 (keyword_rows)
161193 (keyword_groups)
162− (keyword_between)
163− (keyword_unbounded)
164− (keyword_preceding)
165− (keyword_following)
166194 (keyword_exclude)
167195 (keyword_current)
168− (keyword_row)
169196 (keyword_ties)
170197 (keyword_others)
171− (keyword_only)
172− (keyword_unique)
173− (keyword_foreign)
174− (keyword_references)
175− (keyword_concurrently)
176− ; (keyword_btree)
177− ; (keyword_hash)
178− ; (keyword_gist)
179− ; (keyword_spgist)
180− ; (keyword_gin)
181− ; (keyword_brin)
182− (keyword_like)
183− (keyword_similar)
184198 (keyword_preserve)
185− (keyword_unsigned)
186199 (keyword_zerofill)
187− (keyword_conflict)
188− (keyword_do)
189− (keyword_nothing)
190− (keyword_high_priority)
191− (keyword_low_priority)
192− (keyword_delayed)
193− (keyword_recursive)
194− (keyword_cascaded)
195− (keyword_local)
196− (keyword_current_timestamp)
197− (keyword_check)
198− (keyword_option)
200+ (keyword_format)
201+ (keyword_fields)
202+ (keyword_row)
203+ (keyword_sort)
204+ (keyword_compute)
205+ (keyword_comment)
206+ (keyword_location)
207+ (keyword_cached)
208+ (keyword_uncached)
209+ (keyword_lines)
210+ (keyword_stored)
211+ (keyword_virtual)
212+ (keyword_partitioned)
213+ (keyword_analyze)
214+ (keyword_explain)
215+ (keyword_verbose)
216+ (keyword_truncate)
217+ (keyword_rewrite)
218+ (keyword_optimize)
199219 (keyword_vacuum)
200− (keyword_wait)
201− (keyword_nowait)
202−
203− (keyword_trigger)
204− (keyword_function)
205− (keyword_returns)
206− (keyword_return)
207− (keyword_setof)
208− (keyword_atomic)
209− (keyword_declare)
210− ; (keyword_language)
220+ (keyword_cache)
221+ (keyword_language)
211222 (keyword_sql)
223+ (keyword_called)
224+ (keyword_conflict)
225+ (keyword_declare)
226+ (keyword_filter)
227+ (keyword_function)
228+ (keyword_input)
229+ (keyword_name)
230+ (keyword_oid)
231+ (keyword_oids)
232+ (keyword_options)
212233 (keyword_plpgsql)
213− (keyword_immutable)
214− (keyword_stable)
215− (keyword_volatile)
216− (keyword_leakproof)
217− (keyword_parallel)
218− (keyword_safe)
219− (keyword_unsafe)
234+ (keyword_precision)
235+ (keyword_regclass)
236+ (keyword_regnamespace)
237+ (keyword_regproc)
238+ (keyword_regtype)
220239 (keyword_restricted)
221− (keyword_called)
240+ (keyword_return)
222241 (keyword_returns)
223− (keyword_input)
224− (keyword_strict)
225− (keyword_cost)
226− (keyword_rows)
242+ (keyword_separator)
243+ (keyword_setof)
244+ (keyword_stable)
227245 (keyword_support)
228−
229− (keyword_external)
230− (keyword_stored)
231− (keyword_cached)
232− (keyword_uncached)
233− (keyword_replication)
234246 (keyword_tblproperties)
235− (keyword_options)
236− (keyword_compute)
237− (keyword_stats)
238− (keyword_statistics)
239− (keyword_optimize)
240− (keyword_rewrite)
241− (keyword_bin_pack)
242− (keyword_incremental)
243− (keyword_location)
244− (keyword_partitioned)
245− (keyword_comment)
246− (keyword_sort)
247− (keyword_format)
248− (keyword_delimited)
249− (keyword_fields)
250− (keyword_terminated)
251− (keyword_escaped)
252− (keyword_lines)
253− (keyword_cache)
254− (keyword_metadata)
255− (keyword_noscan)
256−
257− (keyword_parquet)
258− (keyword_rcfile)
259− (keyword_csv)
260− (keyword_textfile)
261− (keyword_avro)
262− (keyword_sequencefile)
263− (keyword_orc)
264− (keyword_avro)
265− (keyword_jsonfile)
266−
267− (keyword_precision)
268− (keyword_inet)
247+ (keyword_trigger)
248+ (keyword_unsafe)
249+ (keyword_admin)
250+ (keyword_connection)
251+ (keyword_cycle)
252+ (keyword_database)
253+ (keyword_encrypted)
254+ (keyword_increment)
255+ (keyword_logged)
256+ (keyword_none)
257+ (keyword_owned)
258+ (keyword_password)
259+ (keyword_reset)
260+ (keyword_role)
261+ (keyword_sequence)
262+ (keyword_start)
263+ (keyword_restart)
264+ (keyword_tablespace)
265+ (keyword_until)
266+ (keyword_user)
267+ (keyword_valid)
268+ (keyword_action)
269+ (keyword_definer)
270+ (keyword_invoker)
271+ (keyword_security)
272+ (keyword_extension)
273+ (keyword_version)
274+ (keyword_out)
275+ (keyword_inout)
276+ (keyword_variadic)
277+ (keyword_session)
278+ (keyword_isolation)
279+ (keyword_level)
280+ (keyword_serializable)
281+ (keyword_repeatable)
282+ (keyword_read)
283+ (keyword_write)
284+ (keyword_committed)
285+ (keyword_uncommitted)
286+ (keyword_deferrable)
287+ (keyword_names)
288+ (keyword_zone)
289+ (keyword_immediate)
290+ (keyword_deferred)
291+ (keyword_constraints)
292+ (keyword_snapshot)
293+ (keyword_characteristics)
294+ (keyword_off)
295+ (keyword_follows)
296+ (keyword_precedes)
297+ (keyword_each)
298+ (keyword_instead)
299+ (keyword_of)
300+ (keyword_initially)
301+ (keyword_old)
302+ (keyword_new)
303+ (keyword_referencing)
304+ (keyword_statement)
305+ (keyword_execute)
306+ (keyword_procedure)
269307] @keyword
270308
271309[
272− (keyword_case)
273− (keyword_when)
274− (keyword_then)
275− (keyword_else)
276− (keyword_where)
277−] @keyword.control.conditional
278−
279−[
280− (keyword_in)
281− (keyword_and)
282− (keyword_or)
283− (keyword_is)
284−] @keyword.operator
310+ (keyword_restrict)
311+ (keyword_unbounded)
312+ (keyword_unique)
313+ (keyword_cascade)
314+ (keyword_delayed)
315+ (keyword_high_priority)
316+ (keyword_low_priority)
317+ (keyword_ignore)
318+ (keyword_nothing)
319+ (keyword_check)
320+ (keyword_option)
321+ (keyword_local)
322+ (keyword_cascaded)
323+ (keyword_wait)
324+ (keyword_nowait)
325+ (keyword_metadata)
326+ (keyword_incremental)
327+ (keyword_bin_pack)
328+ (keyword_noscan)
329+ (keyword_stats)
330+ (keyword_statistics)
331+ (keyword_maxvalue)
332+ (keyword_minvalue)
333+] @keyword
285334
286335[
336+ (keyword_int)
337+ (keyword_null)
287338 (keyword_boolean)
288− (bit)
289339 (keyword_binary)
290−
340+ (keyword_varbinary)
341+ (keyword_image)
342+ (keyword_bit)
343+ (keyword_inet)
344+ (keyword_character)
291345 (keyword_smallserial)
292346 (keyword_serial)
293347 (keyword_bigserial)
294−
295− (tinyint)
296− (smallint)
297− (mediumint)
298− (int)
299− (bigint)
300− (decimal)
301− (numeric)
348+ (keyword_smallint)
349+ (keyword_mediumint)
350+ (keyword_bigint)
351+ (keyword_tinyint)
352+ (keyword_decimal)
353+ (keyword_float)
354+ (keyword_double)
355+ (keyword_numeric)
302356 (keyword_real)
303357 (double)
304− (float)
305−
306358 (keyword_money)
307−
308− (char)
309− (varchar)
310− (numeric)
311− (keyword_string)
359+ (keyword_smallmoney)
360+ (keyword_char)
361+ (keyword_nchar)
362+ (keyword_varchar)
363+ (keyword_nvarchar)
364+ (keyword_varying)
312365 (keyword_text)
313−
366+ (keyword_string)
314367 (keyword_uuid)
315−
316368 (keyword_json)
317369 (keyword_jsonb)
318370 (keyword_xml)
319−
320371 (keyword_bytea)
321− (keyword_inet)
322−
323− (enum)
324−
372+ (keyword_enum)
325373 (keyword_date)
326374 (keyword_datetime)
375+ (keyword_time)
376+ (keyword_datetime2)
377+ (keyword_datetimeoffset)
378+ (keyword_smalldatetime)
327379 (keyword_timestamp)
328380 (keyword_timestamptz)
329−
330− (keyword_interval)
331−
332381 (keyword_geometry)
333382 (keyword_geography)
334383 (keyword_box2d)
335384 (keyword_box3d)
336−
337− (keyword_oid)
338− (keyword_name)
339− (keyword_regclass)
340− (keyword_regnamespace)
341− (keyword_regproc)
342− (keyword_regtype)
385+ (keyword_interval)
343386] @type.builtin
387+
388+[
389+ (keyword_in)
390+ (keyword_and)
391+ (keyword_or)
392+ (keyword_not)
393+ (keyword_by)
394+ (keyword_on)
395+ (keyword_do)
396+ (keyword_union)
397+ (keyword_except)
398+ (keyword_intersect)
399+] @keyword.operator
400+
401+[
402+ "+"
403+ "-"
404+ "*"
405+ "/"
406+ "%"
407+ "^"
408+ ":="
409+ "="
410+ "<"
411+ "<="
412+ "!="
413+ ">="
414+ ">"
415+ "<>"
416+ (op_other)
417+ (op_unary_other)
418+] @operator
419+
420+[
421+ "("
422+ ")"
423+] @punctuation.bracket
424+
425+[
426+ ";"
427+ ","
428+ "."
429+] @punctuation.delimiter
runtime/queries/templ/highlights.scmnew file+99
@@ -0,0 +1,99 @@
1+(package_identifier) @namespace
2+
3+(parameter_declaration (identifier) @variable.parameter)
4+(variadic_parameter_declaration (identifier) @variable.parameter)
5+
6+(function_declaration
7+ name: (identifier) @function)
8+
9+(type_spec name: (type_identifier) @type)
10+(type_identifier) @type
11+(field_identifier) @variable.other.member
12+(identifier) @variable
13+
14+; Function calls
15+
16+(call_expression
17+ function: (identifier) @function)
18+
19+(call_expression
20+ function: (selector_expression
21+ field: (field_identifier) @function))
22+
23+;
24+; These are Templ specific
25+;
26+
27+(component_declaration
28+ name: (component_identifier) @function)
29+
30+(tag_start) @tag
31+(tag_end) @tag
32+(self_closing_tag) @tag
33+(style_element) @tag
34+
35+(attribute
36+ name: (attribute_name) @attribute)
37+(attribute
38+ value: (quoted_attribute_value) @string)
39+
40+(element_text) @string.special
41+(style_element_text) @string.special
42+
43+(css_property
44+ name: (css_property_name) @attribute)
45+
46+(expression) @function.method
47+(dynamic_class_attribute_value) @function.method
48+
49+(component_import
50+ name: (component_identifier) @function)
51+
52+(component_render) @function
53+
54+[
55+ "@"
56+] @operator
57+
58+[
59+ "func"
60+ "var"
61+ "const"
62+ "templ"
63+ "css"
64+ "type"
65+ "struct"
66+ "range"
67+ "script"
68+] @keyword.storage.type
69+
70+[
71+ "return"
72+] @keyword.control.return
73+
74+[
75+ "import"
76+ "package"
77+] @keyword.control.import
78+
79+[
80+ "else"
81+ "case"
82+ "switch"
83+ "if"
84+ "default"
85+] @keyword.control.conditional
86+
87+"for" @keyword.control.repeat
88+
89+[
90+ (interpreted_string_literal)
91+ (raw_string_literal)
92+ (rune_literal)
93+] @string
94+
95+; Comments
96+
97+(comment) @comment
98+
99+(element_comment) @comment
runtime/queries/templ/injections.scmnew file+4
@@ -0,0 +1,4 @@
1+((script_block_text) @injection.content (#set! injection.language "javascript"))
2+((script_element_text) @injection.content (#set! injection.language "javascript"))
3+
4+((style_element_text) @injection.content (#set! injection.language "css"))
runtime/queries/typst/highlights.scmnew file+77
@@ -0,0 +1,77 @@
1+(call
2+ item: (ident) @function)
3+(call
4+ item: (field field: (ident) @function.method))
5+(tagged field: (ident) @tag)
6+(field field: (ident) @tag)
7+(comment) @comment
8+
9+; CONTROL
10+(let "let" @keyword.storage.type)
11+(branch ["if" "else"] @keyword.control.conditional)
12+(while "while" @keyword.control.repeat)
13+(for ["for" "in"] @keyword.control.repeat)
14+(import "import" @keyword.control.import)
15+(as "as" @keyword.operator)
16+(include "include" @keyword.control.import)
17+(show "show" @keyword.control)
18+(set "set" @keyword.control)
19+(return "return" @keyword.control)
20+(flow ["break" "continue"] @keyword.control)
21+
22+; OPERATOR
23+(in ["in" "not"] @keyword.operator)
24+(and "and" @keyword.operator)
25+(or "or" @keyword.operator)
26+(not "not" @keyword.operator)
27+(sign ["+" "-"] @operator)
28+(add "+" @operator)
29+(sub "-" @operator)
30+(mul "*" @operator)
31+(div "/" @operator)
32+(cmp ["==" "<=" ">=" "!=" "<" ">"] @operator)
33+(fraction "/" @operator)
34+(fac "!" @operator)
35+(attach ["^" "_"] @operator)
36+(wildcard) @operator
37+
38+; VALUE
39+(raw_blck "```" @operator) @markup.raw.block
40+(raw_span "`" @operator) @markup.raw.block
41+(raw_blck lang: (ident) @tag)
42+(label) @tag
43+(ref) @tag
44+(number) @constant.numeric
45+(string) @string
46+(content ["[" "]"] @operator)
47+(bool) @constant.builtin.boolean
48+(builtin) @constant.builtin
49+(none) @constant.builtin
50+(auto) @constant.builtin
51+(ident) @variable
52+(call
53+ item: (builtin) @function.builtin)
54+
55+; MARKUP
56+(item "-" @markup.list)
57+(term ["/" ":"] @markup.list)
58+(heading ["=" "==" "===" "====" "====="] @markup.heading.marker) @markup.heading
59+(url) @tag
60+(emph) @markup.italic
61+(strong) @markup.bold
62+(symbol) @constant.character
63+(shorthand) @constant.builtin
64+(quote) @markup.quote
65+(align) @operator
66+(letter) @constant.character
67+(linebreak) @constant.builtin
68+
69+(math "$" @operator)
70+"#" @operator
71+"end" @operator
72+
73+(escape) @constant.character.escape
74+["(" ")" "{" "}"] @punctuation.bracket
75+["," ";" ".." ":" "sep"] @punctuation.delimiter
76+"assign" @punctuation
77+(field "." @punctuation)
runtime/queries/typst/injections.scmnew file+6
@@ -0,0 +1,6 @@
1+(raw_blck
2+ (blob) @injection.shebang @injection.content)
3+
4+(raw_blck
5+ lang: (ident) @injection.language
6+ (blob) @injection.content)
runtime/queries/unison/highlights.scm+21−6
@@ -10,14 +10,18 @@
1010[
1111 (kw_forall)
1212 (unique_kw)
13+ (structural_kw)
1314 (type_kw)
1415 (kw_equals)
1516 (do)
17+ (ability)
18+ (where)
1619] @keyword
1720
1821(kw_let) @keyword.function
1922(type_kw) @keyword.storage.type
2023(unique) @keyword.storage.modifier
24+(structural) @keyword.storage.modifier
2125("use") @keyword.control.import
2226
2327
@@ -31,6 +35,7 @@
3135 (arrow_symbol)
3236 (">")
3337 (or)
38+ (and)
3439 (bang)
3540] @operator
3641
@@ -47,13 +52,22 @@
4752
4853;; Types
4954(record_field name: (wordy_id) @variable.other.member type: (wordy_id) @type)
50−[
51− (type_name)
52− (type_signature)
53− (effect)
54−] @type
55+(type_constructor (type_name (wordy_id) @constructor))
56+(ability_declaration type_name: (wordy_id) @type type_arg: (wordy_id) @variable.parameter)
57+(effect (wordy_id) @special) ;; NOTE: an effect is just like a type, but in signature we special case it
58+
59+;; Namespaces
60+(path) @namespace
61+(namespace) @namespace
62+
63+;; Terms
64+(type_signature term_name: (path)? @variable term_name: (wordy_id) @variable)
65+(type_signature (wordy_id) @type)
66+(type_signature (delayed (wordy_id)) @type)
67+
68+(term_definition param: (wordy_id) @variable.parameter)
5569
56−(term_definition) @variable
70+(function_application function_name: (path)? function_name: (wordy_id) @function)
5771
5872;; Punctuation
5973[
@@ -70,3 +84,4 @@
7084 "]"
7185] @punctuation.bracket
7286
87+(test_watch_expression (wordy_id) @keyword.directive)
runtime/queries/yaml/injections.scm+52
@@ -1,2 +1,54 @@
11((comment) @injection.content
22 (#set! injection.language "comment"))
3+
4+; The remaining code in this file incorporates work covered by the following
5+; copyright and permission notice:
6+;
7+; Copyright 2023 the nvim-treesitter authors
8+;
9+; Licensed under the Apache License, Version 2.0 (the "License");
10+; you may not use this file except in compliance with the License.
11+; You may obtain a copy of the License at
12+;
13+; http://www.apache.org/licenses/LICENSE-2.0
14+;
15+; Unless required by applicable law or agreed to in writing, software
16+; distributed under the License is distributed on an "AS IS" BASIS,
17+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+; See the License for the specific language governing permissions and
19+; limitations under the License.
20+
21+; Modified for Helix from https://github.com/nvim-treesitter/nvim-treesitter/blob/master/queries/yaml/injections.scm
22+
23+;; Github actions ("run") / Gitlab CI ("scripts")
24+(block_mapping_pair
25+ key: (flow_node) @_run (#match? @_run "^(run|script|before_script|after_script)$")
26+ value: (flow_node
27+ (plain_scalar
28+ (string_scalar) @injection.content)
29+ (#set! injection.language "bash")))
30+
31+(block_mapping_pair
32+ key: (flow_node) @_run (#match? @_run "^(run|script|before_script|after_script)$")
33+ value: (block_node
34+ (block_scalar) @injection.content
35+ (#set! injection.language "bash")))
36+
37+(block_mapping_pair
38+ key: (flow_node) @_run (#match? @_run "^(run|script|before_script|after_script)$")
39+ value: (block_node
40+ (block_sequence
41+ (block_sequence_item
42+ (flow_node
43+ (plain_scalar
44+ (string_scalar) @injection.content))
45+ (#set! injection.language "bash")))))
46+
47+(block_mapping_pair
48+ key: (flow_node) @_run (#match? @_run "^(run|script|before_script|after_script)$")
49+ value: (block_node
50+ (block_sequence
51+ (block_sequence_item
52+ (block_node
53+ (block_scalar) @injection.content
54+ (#set! injection.language "bash"))))))
runtime/queries/yuck/highlights.scm+1−1
@@ -101,7 +101,7 @@
101101(list
102102 (symbol) @tag)
103103
104−; Other stuff that has not been catched by the previous queries yet
104+; Other stuff that has not been caught by the previous queries yet
105105
106106(ident) @variable
107107(index) @variable
runtime/themes/README.md+8
@@ -6,4 +6,12 @@ If you submit a theme, please include a comment at the top with your name and em
66# Author : Name <email@my.domain>
77```
88
9+If you are submitting a theme that is already published somewhere, then please
10+add the corresponding license file for it under `licenses/` with the following
11+name `theme_name.license` and add a comment at the top of the theme file:
12+
13+```toml
14+# License: <License specification>
15+```
16+
917We have a preview page for themes on our [wiki](https://github.com/helix-editor/helix/wiki/Themes)!
runtime/themes/cyan_light.tomlnew file+154
@@ -0,0 +1,154 @@
1+# An approximation/port of the Cyan Light Theme from Jetbrains
2+#
3+# Original Color Scheme here https://plugins.jetbrains.com/plugin/12102-cyan-light-theme
4+
5+"attribute" = "blue"
6+"type" = "shade07"
7+"type.enum.variant" = "purple"
8+"constructor" = "shade07"
9+
10+"constant" = "darker_blue"
11+"constant.builtin.boolean" = "blue"
12+"constant.character" = "blue"
13+"constant.character.escape" = "dark_red"
14+"constant.numeric" = "blue"
15+
16+"string" = "green"
17+"string.regexp" = "blue"
18+"string.special" = { fg = "dark_red", modifiers = ["underlined"] }
19+
20+"comment" = "comment_gray"
21+
22+"variable" = "green_blue"
23+"variable.builtin" = { fg = "darker_blue" }
24+"variable.parameter" = "purple"
25+"variable.other.member" = "purple"
26+
27+"label" = { fg = "darker_blue", modifiers = ["underlined"] }
28+"punctuation" = "shade06"
29+
30+"keyword" = "darker_blue"
31+"keyword.control.exception" = "darker_blue"
32+
33+"operator" = "shade06"
34+
35+"function" = "shade07"
36+"function.macro" = "yellow"
37+"function.builtin" = { fg = "shade07", modifiers = ["italic"] }
38+"function.special" = "dark_red"
39+"function.method" = "dark_yellow"
40+
41+"tag" = "darker_blue"
42+"special" = "shade06"
43+"namespace" = "darker_blue"
44+
45+"markup.bold" = { fg = "shade06", modifiers = ["bold"] }
46+"markup.italic" = { fg = "shade06", modifiers = ["italic"] }
47+"markup.strikethrough" = { fg = "shade06", modifiers = ["crossed_out"] }
48+"markup.heading" = { fg = "purple" }
49+"markup.list" = "darker_blue"
50+"markup.list.numbered" = "darker_blue"
51+"markup.list.unnumbered" = "darker_blue"
52+"markup.link.url" = "shade06"
53+"markup.link.text" = { fg = "dark_blue", modifiers = ['underlined'] }
54+"markup.link.label" = "dark_blue"
55+"markup.quote" = "green"
56+"markup.raw" = "green"
57+"markup.raw.inline" = "green"
58+"markup.raw.block" = "green"
59+
60+"diff.plus" = "green"
61+"diff.plus.gutter" = "gutter_green"
62+"diff.minus" = "red"
63+"diff.minus.gutter" = "gutter_red"
64+"diff.delta" = "blue"
65+"diff.delta.gutter" = "gutter_blue"
66+
67+# ui specific
68+"ui.background" = { bg = "shade00" }
69+"ui.cursor" = { bg = "shade02" }
70+"ui.cursor.primary" = { bg = "cursor_blue" }
71+"ui.cursor.match" = { fg = "shade00", bg = "shade04" }
72+"ui.cursor.primary.select" = { bg = "light_purple" }
73+"ui.cursor.primary.insert" = { bg = "light_green" }
74+
75+"ui.selection" = { bg = "lighter_blue" }
76+"ui.selection.primary" = { bg = "lighter_blue" }
77+
78+"ui.highlight" = { bg = "faint_blue" }
79+"ui.cursorline.primary" = { bg = "faint_blue" }
80+
81+"ui.linenr" = { fg = "shade03" }
82+"ui.linenr.selected" = { fg = "shade04", bg = "faint_blue", modifiers = [
83+ "bold",
84+] }
85+
86+"ui.statusline" = { fg = "shade06", bg = "shade02" }
87+"ui.statusline.inactive" = { fg = "shade04", bg = "shade01" }
88+"ui.statusline.normal" = { fg = "shade00", bg = "blue" }
89+"ui.statusline.insert" = { fg = "shade00", bg = "green" }
90+"ui.statusline.select" = { fg = "shade00", bg = "purple" }
91+
92+"ui.popup" = { bg = "shade01", fg = "shade04" }
93+"ui.window" = { bg = "shade00", fg = "shade04" }
94+"ui.help" = { fg = "shade06", bg = "shade01" }
95+"ui.text" = "shade05"
96+"ui.text.focus" = { fg = "shade07", bg = "light_blue" }
97+"ui.virtual" = "shade03"
98+"ui.virtual.ruler" = { bg = "shade04" }
99+"ui.menu" = { fg = "shade05", bg = "shade01" }
100+"ui.menu.selected" = { fg = "shade07", bg = "light_blue" }
101+
102+"hint" = "shade04"
103+"info" = "light_blue"
104+"warning" = "orange"
105+"error" = "red"
106+"diagnostic" = { modifiers = [] }
107+"diagnostic.hint" = { underline = { color = "shade04", style = "line" } }
108+"diagnostic.info" = { underline = { color = "light_blue", style = "line" } }
109+"diagnostic.warning" = { underline = { color = "orange", style = "curl" } }
110+"diagnostic.error" = { underline = { color = "red", style = "curl" } }
111+
112+[palette]
113+shade00 = "#f2f3f7"
114+shade01 = "#dadde8"
115+shade02 = "#c1c6d9"
116+shade03 = "#a9b0ca"
117+shade04 = "#525c85"
118+shade05 = "#434b6c"
119+shade06 = "#343a54"
120+shade07 = "#25293c"
121+
122+background = "#f2f3f7"
123+foreground = "#25293c"
124+
125+comment_gray = "#808080"
126+
127+gutter_blue = "#C3D6E8"
128+faint_blue = "#E8Eef1"
129+lighter_blue = "#d0eaff"
130+light_blue = "#99ccff"
131+cursor_blue = "#80bfff"
132+blue = "#0073E6"
133+dark_blue = "#185b93"
134+darker_blue = "#000080"
135+
136+
137+purple = "#660E7A"
138+light_purple = "#ED9CFF"
139+
140+gutter_green = "#C9DEC1"
141+green = "#00733B"
142+light_green = "#5DCE87"
143+green_blue = "#458383"
144+
145+
146+yellow = "#808000"
147+dark_yellow = "#7A7A43"
148+
149+light_orange = "#f9c881"
150+orange = "#F49810"
151+
152+gutter_red = "#EBBCBC"
153+red = "#d90016"
154+dark_red = "#7F0000"
runtime/themes/darcula-solid.toml+1−4
@@ -4,9 +4,8 @@ inherits = "darcula"
44
55"ui.background.separator" = { bg = "grey01" }
66"ui.menu.scroll" = { fg = "grey02", bg = "grey00" }
7−"ui.popup" = { fg = "grey03", bg = "grey02" }
7+"ui.popup" = { fg = "grey05", bg = "grey00" }
88"ui.window" = { bg = "grey00" }
9−"ui.selection" = { bg = "blue" }
109"ui.cursorline.secondary" = { bg = "grey03" }
1110
1211[palette]
@@ -15,5 +14,3 @@ grey01 = "#1f1f1f"
1514grey02 = "#323232"
1615grey03 = "#555555"
1716grey04 = "#a8a8a8"
18−
19−blue = "#104158"
runtime/themes/darcula.toml+10−4
@@ -8,13 +8,14 @@
88"ui.gutter" = { bg = "grey01" }
99"ui.popup" = { fg = "grey05", bg = "grey00" }
1010"ui.window" = { bg = "grey01" }
11−"ui.selection" = { bg = "grey03" }
11+"ui.selection" = { bg = "grey02" }
12+"ui.selection.primary" = { bg = "blue" }
1213"ui.statusline" = { fg = "grey04", bg = "grey02" }
1314"ui.statusline.insert" = { bg = "white", fg = "grey01" }
1415"ui.statusline.select" = { bg = "orange", fg = "grey01" }
1516"ui.help" = { fg = "grey04", bg = "grey01" }
1617"ui.cursor" = { fg = "grey04", modifiers = ["reversed"] }
17−"ui.cursor.primary" = { fg = "grey05", modifiers = ["reversed"] }
18+"ui.cursor.primary" = { fg = "grey02", bg = "grey05" }
1819"ui.cursor.match" = { fg = "white", modifiers = ["underlined"] }
1920"ui.cursorline.primary" = { bg = "grey02" }
2021"ui.cursorline.secondary" = { bg = "grey02" }
@@ -34,7 +35,11 @@
3435"constant.numeric" = "lightblue"
3536"constant.character.escape" = "white"
3637"attribute" = "yellow"
37−"type" = "orange"
38+"type" = "white"
39+"type.builtin" = "orange"
40+"type.parameter" = { fg = "white", modifiers = ["bold"] }
41+"type.enum" = "white"
42+"type.enum.variant" = "orange"
3843"string" = "darkgreen"
3944"function" = "yellow"
4045"function.macro" = "green"
@@ -61,7 +66,7 @@
6166"markup.link.url" = { fg = "lightblue", modifiers = ["underlined"] }
6267"markup.link.text" = "white"
6368"markup.quote" = "darkgreen"
64−"markup.raw" = "white"
69+"markup.raw" = "purple"
6570
6671"diff.plus" = "green"
6772"diff.delta" = "grey"
@@ -97,3 +102,4 @@ green = "#32cd32"
97102grey = "#808080"
98103darkgreen = "#629755"
99104lightblue = "#6897bb"
105+blue = "#104158"
runtime/themes/dracula.toml+2
@@ -90,6 +90,7 @@
9090"ui.virtual.whitespace" = { fg = "current_line" }
9191"ui.virtual.wrap" = { fg = "current_line" }
9292"ui.virtual.ruler" = { bg = "black" }
93+"ui.virtual.indent-guide" = { fg = "indent" }
9394"ui.virtual.inlay-hint" = { fg = "cyan" }
9495"ui.virtual.inlay-hint.parameter" = { fg = "cyan", modifiers = ["italic", "dim"] }
9596"ui.virtual.inlay-hint.type" = { fg = "cyan", modifiers = ["italic", "dim"] }
@@ -123,6 +124,7 @@ black = "#191A21"
123124grey = "#666771"
124125comment = "#6272A4"
125126current_line = "#44475a"
127+indent = "#56596a"
126128selection = "#363848"
127129red = "#ff5555"
128130orange = "#ffb86c"
runtime/themes/everblush.toml+1
@@ -68,6 +68,7 @@
6868"ui.virtual.whitespace" = { fg = "comment" }
6969"ui.virtual.wrap" = { fg = "comment" }
7070"ui.virtual.indent-guide" = { fg = "comment" }
71+"ui.virtual.inlay-hint" = { fg = "comment" }
7172"ui.window" = { fg = "black" }
7273
7374"error" = { fg = "red" }
runtime/themes/gruber-darker.tomlnew file+114
@@ -0,0 +1,114 @@
1+# Author : Mehedi Hasan <mehedi.r137@gmail.com>
2+# Based on : https://github.com/rexim/gruber-darker-theme
3+
4+"attribute" = "fg0"
5+"keyword" = { fg = "yellow0", modifiers = ["bold"] }
6+"keyword.directive" = "quartz"
7+"namespace" = "quartz"
8+"punctuation" = "fg0"
9+"punctuation.delimiter" = "fg0"
10+"operator" = "fg0"
11+"special" = { fg = "yellow0", modifiers = ["bold"] }
12+"variable" = "fg0"
13+"variable.builtin" = { fg = "yellow0", modifiers = ["bold"] }
14+"variable.parameter" = "fg0"
15+"type" = "quartz"
16+"type.builtin" = "yellow0"
17+"constructor" = { fg = "quartz" }
18+"function" = "niagara0"
19+"function.builtin" = "yellow0"
20+"tag" = "niagara0"
21+"comment" = { fg = "brown0" }
22+"constant.character" = { fg = "green0" }
23+"constant.character.escape" = { fg = "yellow0" }
24+"constant.builtin" = { fg = "yellow0", modifiers = ["bold"] }
25+"string" = "green0"
26+"constant.numeric" = "wisteria"
27+"label" = "fg0"
28+"module" = "aqua1"
29+
30+"diff.plus" = "green1"
31+"diff.delta" = "orange1"
32+"diff.minus" = "red0"
33+
34+"warning" = { fg = "orange1", modifiers = ["bold"] }
35+"error" = { fg = "red0", modifiers = ["bold"] }
36+"info" = { fg = "aqua1", modifiers = ["bold"] }
37+"hint" = { fg = "blue0", modifiers = ["bold"] }
38+
39+"ui.background" = { bg = "bg0" }
40+"ui.linenr" = { fg = "bg4" }
41+"ui.linenr.selected" = { fg = "yellow0" }
42+"ui.cursorline" = { bg = "bg1" }
43+
44+"ui.statusline" = { fg = "fg0", bg = "bg1" }
45+"ui.statusline.normal" = { fg = "bg1", bg = "yellow0", modifiers = ["bold"] }
46+"ui.statusline.insert" = { fg = "bg1", bg = "blue0", modifiers = ["bold"] }
47+"ui.statusline.select" = { fg = "bg1", bg = "wisteria", modifiers = ["bold"] }
48+"ui.statusline.inactive" = { fg = "fg3", bg = "bg1" }
49+
50+"ui.bufferline" = { fg = "fg3", bg = "bg6" }
51+"ui.bufferline.active" = { fg = "fg0", bg = "bg7" }
52+
53+"ui.popup" = { bg = "bg6" }
54+"ui.window" = { fg = "bg1" }
55+"ui.help" = { bg = "bg1", fg = "fg0" }
56+"ui.text" = { fg = "fg0" }
57+"ui.text.focus" = { bg = "bg5", modifiers = ["bold"] }
58+"ui.selection" = { bg = "bg2" }
59+"ui.selection.primary" = { bg = "bg5" }
60+"ui.cursor.primary" = { bg = "fg0", fg = "niagara1" }
61+"ui.cursor.match" = { bg = "yellow1" }
62+"ui.menu" = { fg = "fg0", bg = "bg6" }
63+"ui.menu.selected" = { fg = "fg0", bg = "bg5", modifiers = ["bold"] }
64+
65+"ui.virtual.whitespace" = "bg8"
66+"ui.virtual.indent-guide" = "bg8"
67+"ui.virtual.ruler" = { bg = "bg1" }
68+"ui.virtual.inlay-hint" = { fg = "bg7" }
69+"ui.virtual.wrap" = { fg = "bg2" }
70+
71+"diagnostic.warning" = { underline = { color = "orange1", style = "dashed" } }
72+"diagnostic.error" = { underline = { color = "red3", style = "dashed" } }
73+"diagnostic.info" = { underline = { color = "aqua1", style = "dashed" } }
74+"diagnostic.hint" = { underline = { color = "blue0", style = "dashed" } }
75+
76+"markup.heading" = { fg = "aqua1", modifiers = ["bold"] }
77+"markup.bold" = { modifiers = ["bold"] }
78+"markup.italic" = { modifiers = ["italic"] }
79+"markup.strikethrough" = { modifiers = ["crossed_out"] }
80+"markup.link.url" = { fg = "green1", modifiers = ["underlined"] }
81+"markup.link.text" = "red3"
82+"markup.raw" = { fg = "fg0", bg = "bg8", modifiers = ["bold"] }
83+
84+[palette]
85+fg0 = "#e4e4ef"
86+fg1 = "#f4f4ff"
87+fg2 = "#f5f5f5"
88+fg3 = "#a89984"
89+bg0 = "#181818"
90+bg1 = "#282828"
91+bg2 = "#453d41"
92+bg4 = "#52494e"
93+bg5 = "#404040"
94+bg6 = "#232323"
95+bg7 = "#3f3f3f"
96+bg8 = "#2c2c2c"
97+red0 = "#f43841"
98+red1 = "#ff4f58"
99+red2 = "#2B0A0B"
100+red3 = "#fb4934"
101+green0 = "#73c936"
102+green1 = "#b8bb26"
103+yellow0 = "#ffdd33"
104+yellow1 = "#655814"
105+blue0 = "#5292c8"
106+orange0 = "#d65d0e"
107+orange1 = "#fe8019"
108+brown0 = "#cc8c3c"
109+quartz = "#95a99f"
110+niagara0 = "#96a6c8"
111+niagara1 = "#303540"
112+wisteria = "#9e95c7"
113+aqua1 = "#8ec07c"
114+
runtime/themes/horizon-dark.tomlnew file+80
@@ -0,0 +1,80 @@
1+# Syntax
2+string = "orange"
3+constant = "purple"
4+"constant.numeric" = "orange"
5+"constant.builtin" = "orange"
6+variable = "red"
7+comment = "light-gray"
8+special = "purple"
9+"punctuation.bracket" = "purple"
10+keyword = "purple"
11+function = "blue"
12+label = "orange"
13+type = "orange"
14+namespace = "orange"
15+
16+# User Interface
17+"ui.background" = { bg = "bg", fg = "gray" }
18+"ui.background.separator" = "light-gray"
19+"ui.text" = "white"
20+"ui.text.focus" = "green"
21+"ui.text.inactive" = "selection"
22+"ui.text.info" = "orange"
23+"ui.cursor" = { modifiers = ["reversed"] }
24+"ui.cursor.primary" = { modifiers = ["reversed"] }
25+"ui.cursor.match" = { bg = "selection" }
26+"ui.gutter" = "gray"
27+"ui.gutter.selected" = "light-gray"
28+"ui.selection" = { bg = "selection" }
29+"ui.virtual.indent-guide" = { fg = "gray"}
30+"ui.virtual.whitespace" = { fg = "light-gray"}
31+"ui.statusline" = { bg = "dark-bg", fg = "light-gray" }
32+"ui.popup" = { bg = "dark-bg", fg = "orange" }
33+"ui.help" = { bg = "dark-bg", fg = "orange" }
34+"ui.menu" = { bg = "dark-bg", fg = "light-gray" }
35+"ui.menu.selected" = { bg = "selection", fg = "orange" }
36+"ui.window" = "selection"
37+"ui.bufferline" = { bg = "dark-bg", fg = "light-gray" }
38+"ui.bufferline.active" = { bg = "dark-bg", fg = "orange" }
39+
40+# Diagnostics
41+"diagnostic" = { underline = { style = "curl" } }
42+"diagnostic.hint" = { underline = { color = "green", style = "curl" } }
43+"diagnostic.info" = { underline = { color = "blue", style = "curl" } }
44+"diagnostics.error" = { underline = { color = "red", style = "curl"} }
45+"diagnostics.warning" = { underline = { color = "orange", style = "curl"} }
46+
47+warning = { fg = "orange", modifiers = ["bold"] }
48+error = { fg = "red", modifiers = ["bold"] }
49+info = { fg = "blue", modifiers = ["bold"] }
50+hint = { fg = "green", modifiers = ["bold"] }
51+
52+# Markup
53+"markup.heading" = "pink"
54+"markup.list" = "light-gray"
55+"markup.list.checked" = "green"
56+"markup.list.unchecked" = "light-gray"
57+"markup.bold" = { modifiers = ["bold"] }
58+"markup.italic" = { modifiers = ["italic"] }
59+"markup.strikethrough" = { modifiers = ["crossed_out"] }
60+"markup.link" = "blue"
61+"markup.quote" = "orange"
62+"markup.raw" = "orange"
63+
64+"diff.plus" = "green"
65+"diff.minus" = "red"
66+"diff.delta" = "orange"
67+
68+[palette]
69+white = "#D5D8DA"
70+gray = "#2E303E"
71+light-gray = "#6C6F93"
72+bg = "#1C1E26"
73+dark-bg = "#16161C"
74+pink = "#EE64AE"
75+selection = "#353747"
76+green = "#27D796"
77+orange = "#FAB795"
78+purple = "#B877DB"
79+red = "#E95678"
80+blue = "#25B2BC"
runtime/themes/jellybeans.toml+1−1
@@ -22,7 +22,7 @@
2222
2323"constant.builtin.boolean" = "yellow"
2424"constant.character" = "yellow"
25−"constant.characted.escape" = "red_error"
25+"constant.character.escape" = "red_error"
2626"constant.numeric" = "dark_orange"
2727"string" = "dark_green"
2828"string.regexp" = "light_purple"
runtime/themes/licenses/everforest.LICENSEnew file+21
@@ -0,0 +1,21 @@
1+MIT License
2+
3+Copyright (c) 2019 sainnhe
4+
5+Permission is hereby granted, free of charge, to any person obtaining a copy
6+of this software and associated documentation files (the "Software"), to deal
7+in the Software without restriction, including without limitation the rights
8+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+copies of the Software, and to permit persons to whom the Software is
10+furnished to do so, subject to the following conditions:
11+
12+The above copyright notice and this permission notice shall be included in all
13+copies or substantial portions of the Software.
14+
15+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+SOFTWARE.
runtime/themes/licenses/modus_vivendi.LICENSEnew file+5
@@ -0,0 +1,5 @@
1+Copyright (C) 2020-2023 Free Software Foundation, Inc.
2+
3+Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being “A GNU Manual,” and with the Back-Cover Texts as in (a) below. A copy of the license is included in the section entitled “GNU Free Documentation License.”
4+
5+(a) The FSF’s Back-Cover Text is: “You have the freedom to copy and modify this GNU manual.”
runtime/themes/licenses/modus_vivendi_deuteranopia.LICENSEnew file+5
@@ -0,0 +1,5 @@
1+Copyright (C) 2020-2023 Free Software Foundation, Inc.
2+
3+Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being “A GNU Manual,” and with the Back-Cover Texts as in (a) below. A copy of the license is included in the section entitled “GNU Free Documentation License.”
4+
5+(a) The FSF’s Back-Cover Text is: “You have the freedom to copy and modify this GNU manual.”
runtime/themes/licenses/modus_vivendi_tinted.LICENSEnew file+5
@@ -0,0 +1,5 @@
1+Copyright (C) 2020-2023 Free Software Foundation, Inc.
2+
3+Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being “A GNU Manual,” and with the Back-Cover Texts as in (a) below. A copy of the license is included in the section entitled “GNU Free Documentation License.”
4+
5+(a) The FSF’s Back-Cover Text is: “You have the freedom to copy and modify this GNU manual.”
runtime/themes/licenses/modus_vivendi_tritanopia.LICENSEnew file+5
@@ -0,0 +1,5 @@
1+Copyright (C) 2020-2023 Free Software Foundation, Inc.
2+
3+Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, with the Front-Cover Texts being “A GNU Manual,” and with the Back-Cover Texts as in (a) below. A copy of the license is included in the section entitled “GNU Free Documentation License.”
4+
5+(a) The FSF’s Back-Cover Text is: “You have the freedom to copy and modify this GNU manual.”
runtime/themes/licenses/poimandres.LICENSEnew file+21
@@ -0,0 +1,21 @@
1+MIT License
2+
3+Copyright (c) 2023 drcmda
4+
5+Permission is hereby granted, free of charge, to any person obtaining a copy
6+of this software and associated documentation files (the "Software"), to deal
7+in the Software without restriction, including without limitation the rights
8+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+copies of the Software, and to permit persons to whom the Software is
10+furnished to do so, subject to the following conditions:
11+
12+The above copyright notice and this permission notice shall be included in all
13+copies or substantial portions of the Software.
14+
15+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+SOFTWARE.
runtime/themes/licenses/serika-syntax.LICENSEnew file+21
@@ -0,0 +1,21 @@
1+MIT License
2+
3+Copyright (c) 2018 arturoalviar
4+
5+Permission is hereby granted, free of charge, to any person obtaining a copy
6+of this software and associated documentation files (the "Software"), to deal
7+in the Software without restriction, including without limitation the rights
8+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+copies of the Software, and to permit persons to whom the Software is
10+furnished to do so, subject to the following conditions:
11+
12+The above copyright notice and this permission notice shall be included in all
13+copies or substantial portions of the Software.
14+
15+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+SOFTWARE.
runtime/themes/licenses/sonokai.LICENSEnew file+21
@@ -0,0 +1,21 @@
1+MIT License
2+
3+Copyright (c) 2020 sainnhe
4+
5+Permission is hereby granted, free of charge, to any person obtaining a copy
6+of this software and associated documentation files (the "Software"), to deal
7+in the Software without restriction, including without limitation the rights
8+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+copies of the Software, and to permit persons to whom the Software is
10+furnished to do so, subject to the following conditions:
11+
12+The above copyright notice and this permission notice shall be included in all
13+copies or substantial portions of the Software.
14+
15+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+SOFTWARE.
runtime/themes/licenses/starlight.LICENSEnew file+24
@@ -0,0 +1,24 @@
1+This is free and unencumbered software released into the public domain.
2+
3+Anyone is free to copy, modify, publish, use, compile, sell, or
4+distribute this software, either in source code form or as a compiled
5+binary, for any purpose, commercial or non-commercial, and by any
6+means.
7+
8+In jurisdictions that recognize copyright laws, the author or authors
9+of this software dedicate any and all copyright interest in the
10+software to the public domain. We make this dedication for the benefit
11+of the public at large and to the detriment of our heirs and
12+successors. We intend this dedication to be an overt act of
13+relinquishment in perpetuity of all present and future rights to this
14+software under copyright law.
15+
16+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22+OTHER DEALINGS IN THE SOFTWARE.
23+
24+For more information, please refer to <https://unlicense.org>
runtime/themes/material_darker.tomlnew file+20
@@ -0,0 +1,20 @@
1+# Material Theme <https://material-theme.com/> for Helix Editor
2+
3+inherits = "material_deep_ocean"
4+
5+[palette]
6+bg = "#212121"
7+text = "#b0bec5"
8+
9+gray = "#616161"
10+error = "#ff5370"
11+
12+disabled = "#474747"
13+
14+accent = "#ff9800"
15+
16+highlight = "#3f3f3f"
17+
18+comment = "#616161"
19+
20+selection = "#404040"
runtime/themes/material_deep_ocean.tomlnew file+123
@@ -0,0 +1,123 @@
1+# Material Theme <https://material-theme.com/> for Helix Editor
2+
3+# Syntax Highlighting
4+
5+"type" = "purple"
6+
7+"constructor" = "blue"
8+
9+"constant" = "yellow"
10+
11+"string" = "green"
12+"string.regexp" = "yellow"
13+"string.special" = "blue"
14+
15+"comment" = { fg = "comment" }
16+
17+"variable" = "text"
18+"variable.parameter" = { fg = "orange" }
19+"variable.builtin" = "yellow"
20+
21+"label" = "orange"
22+
23+"punctuation" = "cyan"
24+
25+"keyword" = "purple"
26+"keyword.storage" = "cyan"
27+
28+"operator" = "cyan"
29+
30+"function" = "blue"
31+"function.macro" = "cyan"
32+
33+"tag" = "red"
34+"attribute" = "purple"
35+
36+"namespace" = { fg = "yellow" }
37+
38+"special" = "cyan"
39+
40+"markup.heading.marker" = { fg = "cyan", modifiers = ["bold"] }
41+"markup.heading.1" = "cyan"
42+"markup.heading.2" = "red"
43+"markup.heading.3" = "green"
44+"markup.heading.4" = "yellow"
45+"markup.heading.5" = "blue"
46+"markup.heading.6" = "orange"
47+"markup.list" = "purple"
48+"markup.bold" = { modifiers = ["bold"] }
49+"markup.italic" = { modifiers = ["italic"] }
50+"markup.strikethrough" = { modifiers = ["crossed_out"] }
51+"markup.link.url" = { fg = "green", modifiers = ["underlined"] }
52+"markup.link.text" = "blue"
53+"markup.raw" = "text"
54+
55+"diff.plus" = "green"
56+"diff.minus" = "red"
57+"diff.delta" = "blue"
58+
59+# User Interface
60+
61+"ui.background" = { bg = "bg", fg = "text" }
62+"ui.text" = { fg = "text" }
63+
64+"ui.statusline" = { bg = "bg", fg = "text" }
65+"ui.statusline.inactive" = { bg = "bg", fg = "disabled" }
66+"ui.statusline.normal" = { bg = "accent", fg = "text" }
67+"ui.statusline.insert" = { bg = "green", fg = "text" }
68+"ui.statusline.select" = { bg = "purple", fg = "text" }
69+
70+
71+"ui.selection" = { bg = "selection" }
72+
73+"ui.linenr" = { fg = "line-number" }
74+"ui.linenr.selected" = { fg = "accent" }
75+
76+"ui.cursor" = { bg = "highlight", fg = "white" }
77+
78+"ui.cursor.primary" = { bg = "white", fg = "gray" }
79+"ui.cursorline.primary" = { bg = "white" }
80+
81+"ui.virtual" = { fg = "gray" }
82+"ui.virtual.ruler" = { bg = "highlight" }
83+"ui.virtual.indent-guide" = { fg = "gray" }
84+
85+"ui.highlight" = { bg = "highlight" }
86+
87+"ui.menu" = { bg = "highlight", fg = "text" }
88+
89+"ui.help" = { bg = "highlight", fg = "text" }
90+
91+"ui.popup" = { bg = "highlight", fg = "text" }
92+
93+warning = "yellow"
94+error = "error"
95+info = "blue"
96+hint = "purple"
97+
98+[palette]
99+bg = "#0f111a"
100+text = "#a6accd"
101+
102+white = "#eeffff"
103+green = "#c3e88d"
104+yellow = "#ffcb6b"
105+blue = "#82aaff"
106+red = "#f07178"
107+purple = "#c792ea"
108+orange = "#f78c6c"
109+cyan = "#89ddff"
110+gray = "#717cb4"
111+error = "#ff5370"
112+
113+disabled = "#464b5d"
114+
115+accent = "#84ffff"
116+
117+highlight = "#1f2233"
118+
119+comment = "#464b5d"
120+
121+selection = "#1f2233"
122+
123+line-number = "#3b3f51"
runtime/themes/material_oceanic.tomlnew file+21
@@ -0,0 +1,21 @@
1+# Material Theme <https://material-theme.com/> for Helix Editor
2+
3+inherits = "material_deep_ocean"
4+
5+[palette]
6+bg = "#25363b"
7+text = "#b0bec5"
8+
9+gray = "#546e7a"
10+
11+disabled = "#415967"
12+
13+accent = "#009688"
14+
15+highlight = "#425b67"
16+
17+comment = "#546e7a"
18+
19+selection = "#395b65"
20+
21+line-number = "#355058"
runtime/themes/material_palenight.tomlnew file+19
@@ -0,0 +1,19 @@
1+# Material Theme <https://material-theme.com/> for Helix Editor
2+
3+inherits = "material_deep_ocean"
4+
5+[palette]
6+bg = "#292d3e"
7+text = "#a6accd"
8+
9+disabled = "#515772"
10+
11+accent = "#ab47bc"
12+
13+highlight = "#444267"
14+
15+comment = "#676e95"
16+
17+selection = "#444267"
18+
19+line-number = "#3a3f58"
runtime/themes/modus_operandi.tomlnew file+194
@@ -0,0 +1,194 @@
1+# Author: Alexis Mousset <contact@amousset.me>
2+# Adapted from https://protesilaos.com/emacs/modus-themes, by Protesilaos Stavrou
3+# Version 4.3.0
4+#
5+
6+# Syntax highlighting
7+# -------------------
8+"type" = "cyan-cooler"
9+"constructor" = "cyan-cooler"
10+
11+"constant" = "blue-cooler"
12+"constant.character.escape" = "magenta"
13+
14+"string" = "blue-warmer"
15+"string.regexp" = "magenta-faint"
16+"string.special" = "blue-faint" # used for colors in CSS
17+
18+"comment" = "fg-dim"
19+
20+"variable.parameter" = "cyan"
21+"variable.builtin" = "magenta-cooler"
22+"label" = "fg-dim" # used for language in markdown code blocks
23+"keyword" = "magenta-cooler"
24+"keyword.directive" = "red-cooler"
25+"function" = "magenta"
26+"function.macro" = "magenta-warmer"
27+
28+punctuation = "fg-dim"
29+"tag" = "magenta"
30+"attribute" = "cyan-cooler"
31+"namespace" = "blue-cooler"
32+"special" = "red-cooler"
33+
34+"markup.heading.marker" = "fg-dim"
35+"markup.heading.1" = { fg = "fg-main", modifiers = ["bold"] }
36+"markup.heading.2" = { fg = "yellow-faint", modifiers = ["bold"] }
37+"markup.heading.3" = { fg = "fg-alt", modifiers = ["bold"] }
38+"markup.heading.4" = { fg = "magenta", modifiers = ["bold"] }
39+"markup.heading.5" = { fg = "green-faint", modifiers = ["bold"] }
40+"markup.heading.6" = { fg = "red-faint", modifiers = ["bold"] }
41+"markup.list" = "fg-dim"
42+"markup.list.checked" = { fg = "yellow-warmer" }
43+"markup.list.unchecked" = { fg = "yellow-warmer" }
44+"markup.bold" = { modifiers = ["bold"] }
45+"markup.italic" = { modifiers = ["italic"] }
46+"markup.strikethrough" = { modifiers = ["crossed_out"] }
47+"markup.link.url" = { fg = "cyan" }
48+"markup.link.text" = { fg = "blue-warmer", modifiers = ["underlined"] }
49+"markup.raw.block" = { bg = "bg-dim" }
50+"markup.raw.inline" = { fg = "green-cooler" }
51+
52+"diff.plus" = { fg = "fg-added", bg = "bg-added" }
53+"diff.plus.gutter" = "green-intense"
54+"diff.minus" = { fg = "fg-removed", bg = "bg-removed" }
55+"diff.minus.gutter" = "red-intense"
56+"diff.delta" = { fg = "fg-changed", bg = "bg-changed" }
57+"diff.delta.gutter" = "yellow-intense"
58+
59+# User Interface
60+# --------------
61+
62+"ui.background" = { bg = "bg-main" }
63+
64+"ui.linenr" = { fg = "fg-dim", bg = "bg-dim" }
65+"ui.linenr.selected" = { fg = "fg-main", bg = "bg-active" }
66+
67+"ui.statusline" = { fg = "fg-mode-line-active", bg = "bg-mode-line-active" }
68+"ui.statusline.inactive" = { fg = "fg-mode-line-inactive", bg = "bg-mode-line-inactive" }
69+"ui.statusline.normal" = { fg = "blue-warmer" }
70+"ui.statusline.insert" = { fg = "green-warmer" }
71+"ui.statusline.select" = { fg = "magenta-warmer" }
72+
73+"ui.popup" = { fg = "fg-main", bg = "bg-dim" }
74+"ui.window" = { fg = "fg-dim" }
75+"ui.help" = { fg = "fg-main", bg = "bg-dim" }
76+"ui.gutter" = { bg = "bg-dim" }
77+"ui.text" = "fg-main"
78+"ui.text.focus" = { fg = "fg-main", bg = "bg-completion", modifiers = ["bold"] }
79+"ui.text.inactive" = { fg = "fg-dim" }
80+"ui.virtual" = "bg-active"
81+"ui.virtual.ruler" = { bg = "bg-dim" }
82+"ui.virtual.inlay-hint" = { fg = "fg-dim", modifiers = ["italic"] }
83+
84+"ui.selection" = { fg = "fg-main", bg = "bg-inactive" }
85+"ui.selection.primary" = { fg = "fg-main", bg = "bg-active" }
86+
87+"ui.cursor" = { fg = "bg-main", bg = "fg-main" }
88+"ui.cursor.primary" = { fg = "bg-main", bg = "fg-dim" }
89+"ui.cursor.match" = { bg = "bg-paren-match" }
90+"ui.cursorline.primary" = { bg = "bg-hl-line" }
91+
92+"ui.highlight" = { bg = "bg-hl-line" }
93+
94+"ui.menu" = { fg = "fg-main", bg = "bg-dim" }
95+"ui.menu.selected" = { fg = "fg-main", bg = "bg-completion", modifiers = ["bold"] }
96+"ui.menu.scroll" = { fg = "fg-dim", bg = "bg-cyan-intense" }
97+
98+"diagnostic.error" = { underline = { color = "red-intense", style = "curl" } }
99+"diagnostic.warning" = { underline = { color = "yellow-intense", style = "curl" } }
100+"diagnostic.info" = { underline = { color = "cyan-intense", style = "curl" } }
101+"diagnostic.hint" = { underline = { color = "blue-intense", style = "curl" } }
102+
103+error = "red"
104+warning = "yellow-warmer"
105+info = "cyan-cooler"
106+hint = "blue-cooler"
107+
108+[palette]
109+# Basic values
110+bg-main = "#ffffff"
111+bg-dim = "#f2f2f2"
112+fg-main = "#000000"
113+fg-dim = "#595959"
114+fg-alt = "#193668"
115+bg-active = "#c4c4c4"
116+bg-inactive = "#e0e0e0"
117+
118+# Common accent foregrounds
119+red = "#a60000"
120+red-warmer = "#972500"
121+red-cooler = "#a0132f"
122+red-faint = "#7f0000"
123+red-intense = "#d00000"
124+green = "#006800"
125+green-warmer = "#316500"
126+green-cooler = "#00663f"
127+green-faint = "#2a5045"
128+green-intense = "#008900"
129+yellow = "#6f5500"
130+yellow-warmer = "#884900"
131+yellow-cooler = "#7a4f2f"
132+yellow-faint = "#624416"
133+yellow-intense = "#808000"
134+blue = "#0031a9"
135+blue-warmer = "#354fcf"
136+blue-cooler = "#0000b0"
137+blue-faint = "#003497"
138+blue-intense = "#0000ff"
139+magenta = "#721045"
140+magenta-warmer = "#8f0075"
141+magenta-cooler = "#531ab6"
142+magenta-faint = "#7c318f"
143+magenta-intense = "#dd22dd"
144+cyan = "#005e8b"
145+cyan-warmer = "#3f578f"
146+cyan-cooler = "#005f5f"
147+cyan-faint = "#005077"
148+cyan-intense = "#008899"
149+
150+# Common accent backgrounds
151+bg-red-intense = "#ff8f88"
152+bg-green-intense = "#8adf80"
153+bg-yellow-intense = "#f3d000"
154+bg-blue-intense = "#bfc9ff"
155+bg-magenta-intense = "#dfa0f0"
156+bg-cyan-intense = "#a4d5f9"
157+
158+bg-red-subtle = "#ffcfbf"
159+bg-green-subtle = "#b3fabf"
160+bg-yellow-subtle = "#fff576"
161+bg-blue-subtle = "#ccdfff"
162+bg-magenta-subtle = "#ffddff"
163+bg-cyan-subtle = "#bfefff"
164+
165+bg-red-nuanced = "#fff1f0"
166+bg-green-nuanced = "#ecf7ed"
167+bg-yellow-nuanced = "#fff3da"
168+bg-blue-nuanced = "#f3f3ff"
169+bg-magenta-nuanced = "#fdf0ff"
170+bg-cyan-nuanced = "#ebf6fa"
171+
172+# Special purpose
173+bg-completion = "#c0deff"
174+bg-hl-line = "#dae5ec"
175+
176+bg-mode-line-active = "#c8c8c8"
177+fg-mode-line-active = "#000000"
178+bg-mode-line-inactive = "#e6e6e6"
179+fg-mode-line-inactive = "#585858"
180+
181+modeline-err = "#7f0000"
182+modeline-warning = "#5f0070"
183+modeline-info = "#002580"
184+
185+# Diffs
186+bg-added = "#c1f2d1"
187+fg-added = "#005000"
188+bg-changed = "#ffdfa9"
189+fg-changed = "#553d00"
190+bg-removed = "#ffd8d5"
191+fg-removed = "#8f1313"
192+
193+# Paren match
194+bg-paren-match = "#5fcfff"
runtime/themes/modus_operandi_deuteranopia.tomlnew file+46
@@ -0,0 +1,46 @@
1+# Author: Alexis Mousset <contact@amousset.me>
2+# modus_operandi.toml variant
3+#
4+# This variant is optimized for users with red-green color deficiency (deuteranopia)
5+
6+inherits = "modus_operandi"
7+
8+"constant.character.escape" = "magenta"
9+"comment" = "yellow-cooler"
10+"function" = "magenta"
11+"tag" = "magenta"
12+
13+"ui.cursor" = { fg = "bg-main", bg = "blue-intense" }
14+"ui.cursor.primary.normal" = { fg = "bg-main", bg = "blue-intense" }
15+
16+"diagnostic.error" = { underline = { color = "yellow-intense", style = "curl" } }
17+"diagnostic.warning" = { underline = { color = "magenta-faint", style = "curl" } }
18+"diagnostic.info" = { underline = { color = "cyan", style = "curl" } }
19+"diagnostic.hint" = { underline = { color = "blue", style = "curl" } }
20+
21+error = "yellow-intense"
22+warning = "magenta-faint"
23+info = "cyan"
24+hint = "blue"
25+
26+[palette]
27+
28+yellow = "#695500"
29+yellow-warmer = "#973300"
30+yellow-cooler = "#77492f"
31+
32+bg-mode-line-active = "#d0d6ff"
33+fg-mode-line-active = "#0f0f0f"
34+border-mode-line-active = "#4f4f74"
35+
36+modeline-err = "#603a00"
37+modeline-warning = "#454500"
38+modeline-info = "#023d92"
39+
40+# Diffs
41+bg-added = "#d5d7ff"
42+fg-added = "#303099"
43+bg-changed = "#eecfdf"
44+fg-changed = "#6f1343"
45+bg-removed = "#f4f099"
46+fg-removed = "#553d00"
runtime/themes/modus_operandi_tinted.tomlnew file+45
@@ -0,0 +1,45 @@
1+# Author: Alexis Mousset <contact@amousset.me>
2+# modus_operandi.toml variant
3+
4+inherits = "modus_operandi"
5+
6+"comment" = "red-faint"
7+
8+"ui.cursor.primary" = { fg = "bg-main", bg = "red" }
9+
10+[palette]
11+# Basic values
12+bg-main = "#fbf7f0"
13+bg-dim = "#efe9dd"
14+bg-active = "#c9b9b0"
15+bg-inactive = "#dfd5cf"
16+border = "#9f9690"
17+
18+# Common accent backgrounds
19+bg-red-nuanced = "#ffe8f0"
20+bg-green-nuanced = "#e0f5e0"
21+bg-yellow-nuanced = "#f9ead0"
22+bg-blue-nuanced = "#ebebff"
23+bg-magenta-nuanced = "#f6e7ff"
24+bg-cyan-nuanced = "#e1f3fc"
25+
26+# Special purpose
27+bg-completion = "#f0c1cf"
28+bg-hl-line = "#f1d5d0"
29+bg-region = "#c2bcb5"
30+
31+bg-mode-line-active = "#cab9b2"
32+border-mode-line-active = "#545454"
33+bg-mode-line-inactive = "#dfd9cf"
34+border-mode-line-inactive = "#a59a94"
35+
36+bg-tab-bar = "#e0d4ce"
37+bg-tab-current = "#fbf7f0"
38+bg-tab-other = "#c8b8b2"
39+
40+# Diffs
41+bg-added = "#c3ebc1"
42+bg-removed = "#f4d0cf"
43+
44+# Paren match
45+bg-paren-match = "#7fdfcf"
runtime/themes/modus_operandi_tritanopia.tomlnew file+73
@@ -0,0 +1,73 @@
1+# Author: Alexis Mousset <contact@amousset.me>
2+# modus_operandi.toml variant
3+#
4+# This variant is optimized for users with blue-yellow color deficiency (tritanopia)
5+
6+inherits = "modus_operandi"
7+
8+"type" = "blue-warmer"
9+"constructor" = "blue-warmer"
10+"constant" = "green-cooler"
11+"constant.character.escape" = "red-cooler"
12+"string" = "cyan"
13+"comment" = "red-faint"
14+"variable.parameter" = "cyan-cooler"
15+"keyword" = "red-cooler"
16+"keyword.directive" = "red-warmer"
17+"function" = "cyan-warmer"
18+"function.macro" = "magenta"
19+"tag" = "red-cooler"
20+
21+"markup.heading.2" = { fg = "red-faint", modifiers = ["bold"] }
22+"markup.heading.3" = { fg = "cyan-faint", modifiers = ["bold"] }
23+"markup.heading.6" = { fg = "magenta-faint", modifiers = ["bold"] }
24+"markup.link.url" = { fg = "cyan-cooler" }
25+"markup.link.text" = { fg = "cyan", modifiers = ["underlined"] }
26+
27+"ui.cursor" = { fg = "bg-main", bg = "red-intense" }
28+"ui.cursor.primary.normal" = { fg = "bg-main", bg = "red-intense" }
29+
30+"diagnostic.error" = { underline = { color = "red-warmer", style = "curl" } }
31+"diagnostic.warning" = { underline = { color = "magenta", style = "curl" } }
32+"diagnostic.info" = { underline = { color = "cyan", style = "curl" } }
33+"diagnostic.hint" = { underline = { color = "blue", style = "curl" } }
34+
35+error = "red-warmer"
36+warning = "magenta"
37+info = "cyan"
38+hint = "blue"
39+
40+[palette]
41+
42+# Common accent foregrounds
43+red-warmer = "#b21100"
44+red-faint = "#702000"
45+yellow = "#695500"
46+yellow-warmer = "#973300"
47+yellow-cooler = "#77492f"
48+magenta-intense = "#cd22bd"
49+cyan-faint = "#004f5f"
50+
51+# Special purpose
52+bg-completion = "#afdfef"
53+bg-hover = "#ffafbc"
54+bg-hover-secondary = "#9fdfff"
55+bg-hl-line = "#dfeaec"
56+
57+bg-char-0 = "#ff908f"
58+bg-char-1 = "#bfbfff"
59+bg-char-2 = "#5fcfdf"
60+
61+bg-mode-line-active = "#afe0f2"
62+fg-mode-line-active = "#0f0f0f"
63+border-mode-line-active = "#2f4f44"
64+
65+modeline-err = "#8f0000"
66+modeline-warning = "#6f306f"
67+modeline-info = "#00445f"
68+
69+# Diffs
70+bg-added = "#b5e7ff"
71+fg-added = "#005079"
72+bg-changed = "#eecfdf"
73+fg-changed = "#6f1343"
runtime/themes/modus_vivendi.tomlnew file+242
@@ -0,0 +1,242 @@
1+# Author: Matous Dzivjak <matousdzivjak@gmail.com>
2+# Adapted from https://protesilaos.com/emacs/modus-themes, by Protesilaos Stavrou
3+# Source: https://github.com/protesilaos/modus-themes/blob/main/modus-vivendi-theme.el
4+# Version 4.3.0
5+
6+# Syntax highlighting
7+# -------------------
8+"type" = "cyan-cooler"
9+"constructor" = "cyan-cooler"
10+
11+"constant" = "blue-cooler"
12+"constant.character.escape" = "magenta"
13+
14+"string" = "blue-warmer"
15+"string.regexp" = "magenta-faint"
16+"string.special" = "blue-faint" # used for colors in CSS
17+
18+"comment" = "fg-dim"
19+
20+"variable.parameter" = "cyan"
21+"variable.builtin" = "magenta-cooler"
22+"label" = "fg-dim" # used for language in markdown code blocks
23+"keyword" = "magenta-cooler"
24+"keyword.directive" = "red-cooler"
25+"function" = "magenta"
26+"function.macro" = "magenta-warmer"
27+
28+punctuation = "fg-dim"
29+"tag" = "magenta"
30+"attribute" = "cyan-cooler"
31+"namespace" = "blue-cooler"
32+"special" = "red-cooler"
33+
34+"markup.heading.marker" = "fg-dim"
35+"markup.heading.1" = { fg = "fg-main", modifiers = ["bold"] }
36+"markup.heading.2" = { fg = "yellow-faint", modifiers = ["bold"] }
37+"markup.heading.3" = { fg = "fg-alt", modifiers = ["bold"] }
38+"markup.heading.4" = { fg = "magenta", modifiers = ["bold"] }
39+"markup.heading.5" = { fg = "green-faint", modifiers = ["bold"] }
40+"markup.heading.6" = { fg = "red-faint", modifiers = ["bold"] }
41+"markup.list" = "fg-dim"
42+"markup.list.checked" = { fg = "yellow-warmer" }
43+"markup.list.unchecked" = { fg = "yellow-warmer" }
44+"markup.bold" = { modifiers = ["bold"] }
45+"markup.italic" = { modifiers = ["italic"] }
46+"markup.strikethrough" = { modifiers = ["crossed_out"] }
47+"markup.link.url" = { fg = "cyan" }
48+"markup.link.text" = { fg = "blue-warmer", modifiers = ["underlined"] }
49+"markup.raw.block" = { bg = "bg-dim" }
50+"markup.raw.inline" = { fg = "green-cooler" }
51+
52+"diff.plus" = { fg = "fg-added", bg = "bg-added" }
53+"diff.plus.gutter" = "green-intense"
54+"diff.minus" = { fg = "fg-removed", bg = "bg-removed" }
55+"diff.minus.gutter" = "red-intense"
56+"diff.delta" = { fg = "fg-changed", bg = "bg-changed" }
57+"diff.delta.gutter" = "yellow-intense"
58+
59+# User Interface
60+# --------------
61+
62+"ui.background" = { bg = "bg-main" }
63+
64+"ui.linenr" = { fg = "fg-dim", bg = "bg-dim" }
65+"ui.linenr.selected" = { fg = "fg-main", bg = "bg-active" }
66+
67+"ui.statusline" = { fg = "fg-mode-line-active", bg = "bg-mode-line-active" }
68+"ui.statusline.inactive" = { fg = "fg-mode-line-inactive", bg = "bg-mode-line-inactive" }
69+"ui.statusline.normal" = { fg = "blue-warmer" }
70+"ui.statusline.insert" = { fg = "green-warmer" }
71+"ui.statusline.select" = { fg = "magenta-warmer" }
72+
73+"ui.bufferline" = { bg = "bg-tab-bar" }
74+"ui.bufferline.active" = { bg = "bg-tab-current", fg = "fg-mode-line-active" }
75+
76+"ui.popup" = { fg = "fg-main", bg = "bg-dim" }
77+"ui.window" = { fg = "fg-dim" }
78+"ui.help" = { fg = "fg-main", bg = "bg-dim" }
79+"ui.gutter" = { bg = "bg-dim" }
80+"ui.text" = "fg-main"
81+"ui.text.focus" = { fg = "fg-main", bg = "bg-completion", modifiers = ["bold"] }
82+"ui.text.inactive" = { fg = "fg-dim" }
83+"ui.virtual" = "bg-active"
84+"ui.virtual.ruler" = { bg = "bg-dim" }
85+"ui.virtual.inlay-hint" = { fg = "fg-dim", modifiers = ["italic"] }
86+
87+"ui.selection" = { fg = "fg-main", bg = "bg-inactive" }
88+"ui.selection.primary" = { fg = "fg-main", bg = "bg-active" }
89+
90+"ui.cursor" = { fg = "bg-main", bg = "fg-main" }
91+"ui.cursor.primary" = { fg = "bg-main", bg = "fg-dim" }
92+"ui.cursor.match" = { bg = "bg-paren-match" }
93+"ui.cursorline.primary" = { bg = "bg-hl-line" }
94+
95+"ui.highlight" = { bg = "bg-hl-line" }
96+
97+"ui.menu" = { fg = "fg-main", bg = "bg-dim" }
98+"ui.menu.selected" = { fg = "fg-main", bg = "bg-completion", modifiers = ["bold"] }
99+"ui.menu.scroll" = { fg = "fg-dim", bg = "bg-cyan-intense" }
100+
101+"diagnostic.error" = { underline = { color = "red-intense", style = "curl" } }
102+"diagnostic.warning" = { underline = { color = "yellow-intense", style = "curl" } }
103+"diagnostic.info" = { underline = { color = "cyan-intense", style = "curl" } }
104+"diagnostic.hint" = { underline = { color = "blue-intense", style = "curl" } }
105+
106+error = "red"
107+warning = "yellow-warmer"
108+info = "cyan-cooler"
109+hint = "blue-cooler"
110+
111+[palette]
112+# Basic values
113+bg-main = "#000000"
114+bg-dim = "#1e1e1e"
115+fg-main = "#ffffff"
116+fg-dim = "#989898"
117+fg-alt = "#c6daff"
118+bg-active = "#535353"
119+bg-inactive = "#303030"
120+
121+# Common accent foregrounds
122+red = "#ff5f59"
123+red-warmer = "#ff6b55"
124+red-cooler = "#ff7f9f"
125+red-faint = "#ff9580"
126+red-intense = "#ff5f5f"
127+green = "#44bc44"
128+green-warmer = "#70b900"
129+green-cooler = "#00c06f"
130+green-faint = "#88ca9f"
131+green-intense = "#44df44"
132+yellow = "#d0bc00"
133+yellow-warmer = "#fec43f"
134+yellow-cooler = "#dfaf7a"
135+yellow-faint = "#d2b580"
136+yellow-intense = "#efef00"
137+blue = "#2fafff"
138+blue-warmer = "#79a8ff"
139+blue-cooler = "#00bcff"
140+blue-faint = "#82b0ec"
141+blue-intense = "#338fff"
142+magenta = "#feacd0"
143+magenta-warmer = "#f78fe7"
144+magenta-cooler = "#b6a0ff"
145+magenta-faint = "#caa6df"
146+magenta-intense = "#ff66ff"
147+cyan = "#00d3d0"
148+cyan-warmer = "#4ae2f0"
149+cyan-cooler = "#6ae4b9"
150+cyan-faint = "#9ac8e0"
151+cyan-intense = "#00eff0"
152+
153+# Uncommon accent foregrounds
154+rust = "#db7b5f"
155+gold = "#c0965b"
156+olive = "#9cbd6f"
157+slate = "#76afbf"
158+indigo = "#9099d9"
159+maroon = "#cf7fa7"
160+pink = "#d09dc0"
161+
162+# Common accent backgrounds
163+bg-red-intense = "#9d1f1f"
164+bg-green-intense = "#2f822f"
165+bg-yellow-intense = "#7a6100"
166+bg-blue-intense = "#1640b0"
167+bg-magenta-intense = "#7030af"
168+bg-cyan-intense = "#2266ae"
169+
170+bg-red-subtle = "#620f2a"
171+bg-green-subtle = "#00422a"
172+bg-yellow-subtle = "#4a4000"
173+bg-blue-subtle = "#242679"
174+bg-magenta-subtle = "#552f5f"
175+bg-cyan-subtle = "#004065"
176+
177+bg-red-nuanced = "#2c0614"
178+bg-green-nuanced = "#001904"
179+bg-yellow-nuanced = "#221000"
180+bg-blue-nuanced = "#0f0e39"
181+bg-magenta-nuanced = "#230631"
182+bg-cyan-nuanced = "#041529"
183+
184+# Uncommon accent backgrounds
185+bg-ochre = "#442c2f"
186+bg-lavender = "#38325c"
187+bg-sage = "#0f3d30"
188+
189+# Special purpose
190+bg-completion = "#2f447f"
191+bg-hover = "#45605e"
192+bg-hover-secondary = "#654a39"
193+bg-hl-line = "#2f3849"
194+bg-region = "#5a5a5a"
195+fg-region = "#ffffff"
196+
197+bg-char-0 = "#0050af"
198+bg-char-1 = "#7f1f7f"
199+bg-char-2 = "#625a00"
200+
201+bg-mode-line-active = "#505050"
202+fg-mode-line-active = "#ffffff"
203+border-mode-line-active = "#959595"
204+bg-mode-line-inactive = "#2d2d2d"
205+fg-mode-line-inactive = "#969696"
206+border-mode-line-inactive = "#606060"
207+
208+modeline-err = "#ffa9bf"
209+modeline-warning = "#dfcf43"
210+modeline-info = "#9fefff"
211+
212+bg-tab-bar = "#313131"
213+bg-tab-current = "#000000"
214+bg-tab-other = "#545454"
215+
216+# Diffs
217+bg-added = "#00381f"
218+bg-added-faint = "#002910"
219+bg-added-refine = "#034f2f"
220+bg-added-fringe = "#237f3f"
221+fg-added = "#a0e0a0"
222+fg-added-intense = "#80e080"
223+
224+bg-changed = "#363300"
225+bg-changed-faint = "#2a1f00"
226+bg-changed-refine = "#4a4a00"
227+bg-changed-fringe = "#8a7a00"
228+fg-changed = "#efef80"
229+fg-changed-intense = "#c0b05f"
230+
231+bg-removed = "#4f1119"
232+bg-removed-faint = "#380a0f"
233+bg-removed-refine = "#781a1f"
234+bg-removed-fringe = "#b81a1f"
235+fg-removed = "#ffbfbf"
236+fg-removed-intense = "#ff9095"
237+
238+bg-diff-context = "#1a1a1a"
239+
240+# Paren match
241+bg-paren-match = "#2f7f9f"
242+tg-paren-expression = "#453040"
runtime/themes/modus_vivendi_deuteranopia.tomlnew file+158
@@ -0,0 +1,158 @@
1+# Author: Matous Dzivjak <matousdzivjak@gmail.com>
2+# Adapted from https://protesilaos.com/emacs/modus-themes, by Protesilaos Stavrou
3+# Source: https://github.com/protesilaos/modus-themes/blob/main/modus-vivendi-deuteranopia-theme.el
4+# Version 4.3.0
5+
6+inherits = "modus_vivendi"
7+
8+"constant.character.escape" = "magenta"
9+"comment" = "yellow-cooler"
10+"function" = "magenta"
11+"tag" = "magenta"
12+
13+"ui.cursor" = { fg = "bg-main", bg = "blue-intense" }
14+"ui.cursor.primary.normal" = { fg = "bg-main", bg = "blue-intense" }
15+
16+"diagnostic.error" = { underline = { color = "yellow-intense", style = "curl" } }
17+"diagnostic.warning" = { underline = { color = "magenta-faint", style = "curl" } }
18+"diagnostic.info" = { underline = { color = "cyan", style = "curl" } }
19+"diagnostic.hint" = { underline = { color = "blue", style = "curl" } }
20+
21+error = "yellow-intense"
22+warning = "magenta-faint"
23+info = "cyan"
24+hint = "blue"
25+
26+[palette]
27+# Basic values
28+bg-main = "#000000"
29+bg-dim = "#1e1e1e"
30+fg-main = "#ffffff"
31+fg-dim = "#989898"
32+fg-alt = "#c6daff"
33+bg-active = "#535353"
34+bg-inactive = "#303030"
35+border = "#646464"
36+
37+# Common accent foregrounds
38+red = "#ff5f59"
39+red-warmer = "#ff6b55"
40+red-cooler = "#ff7f9f"
41+red-faint = "#ff9580"
42+red-intense = "#ff5f5f"
43+green = "#44bc44"
44+green-warmer = "#70b900"
45+green-cooler = "#00c06f"
46+green-faint = "#88ca9f"
47+green-intense = "#44df44"
48+yellow = "#cabf00"
49+yellow-warmer = "#ffa00f"
50+yellow-cooler = "#d8af7a"
51+yellow-faint = "#d2b580"
52+yellow-intense = "#efef00"
53+blue = "#2fafff"
54+blue-warmer = "#79a8ff"
55+blue-cooler = "#00bcff"
56+blue-faint = "#82b0ec"
57+blue-intense = "#338fff"
58+magenta = "#feacd0"
59+magenta-warmer = "#f78fe7"
60+magenta-cooler = "#b6a0ff"
61+magenta-faint = "#caa6df"
62+magenta-intense = "#ff66ff"
63+cyan = "#00d3d0"
64+cyan-warmer = "#4ae2f0"
65+cyan-cooler = "#6ae4b9"
66+cyan-faint = "#9ac8e0"
67+cyan-intense = "#00eff0"
68+
69+# Uncommon accent foregrounds
70+rust = "#db7b5f"
71+gold = "#c0965b"
72+olive = "#9cbd6f"
73+slate = "#76afbf"
74+indigo = "#9099d9"
75+maroon = "#cf7fa7"
76+pink = "#d09dc0"
77+
78+# Common accent backgrounds
79+bg-red-intense = "#9d1f1f"
80+bg-green-intense = "#2f822f"
81+bg-yellow-intense = "#7a6100"
82+bg-blue-intense = "#1640b0"
83+bg-magenta-intense = "#7030af"
84+bg-cyan-intense = "#2266ae"
85+
86+bg-red-subtle = "#620f2a"
87+bg-green-subtle = "#00422a"
88+bg-yellow-subtle = "#4a4000"
89+bg-blue-subtle = "#242679"
90+bg-magenta-subtle = "#552f5f"
91+bg-cyan-subtle = "#004065"
92+
93+bg-red-nuanced = "#2c0614"
94+bg-green-nuanced = "#001904"
95+bg-yellow-nuanced = "#221000"
96+bg-blue-nuanced = "#0f0e39"
97+bg-magenta-nuanced = "#230631"
98+bg-cyan-nuanced = "#041529"
99+
100+# Uncommon accent backgrounds
101+bg-ochre = "#442c2f"
102+bg-lavender = "#38325c"
103+bg-sage = "#0f3d30"
104+
105+# Special purpose
106+bg-completion = "#2f447f"
107+bg-hover = "#45605e"
108+bg-hover-secondary = "#654a39"
109+bg-hl-line = "#2f3849"
110+bg-region = "#5a5a5a"
111+fg-region = "#ffffff"
112+
113+bg-char-0 = "#0050af"
114+bg-char-1 = "#7f1f7f"
115+bg-char-2 = "#625a00"
116+
117+bg-mode-line-active = "#2a2a6a"
118+fg-mode-line-active = "#f0f0f0"
119+border-mode-line-active = "#8080a7"
120+bg-mode-line-inactive = "#2d2d2d"
121+fg-mode-line-inactive = "#969696"
122+border-mode-line-inactive = "#606060"
123+
124+modeline-err = "#e5bf00"
125+modeline-warning = "#c0cf35"
126+modeline-info = "#abeadf"
127+
128+bg-tab-bar = "#313131"
129+bg-tab-current = "#000000"
130+bg-tab-other = "#545454"
131+
132+# Diffs
133+bg-added = "#003066"
134+bg-added-faint = "#001a4f"
135+bg-added-refine = "#0f4a77"
136+bg-added-fringe = "#006fff"
137+fg-added = "#c4d5ff"
138+fg-added-intense = "#8080ff"
139+
140+bg-changed = "#2f123f"
141+bg-changed-faint = "#1f022f"
142+bg-changed-refine = "#3f325f"
143+bg-changed-fringe = "#7f55a0"
144+fg-changed = "#e3cfff"
145+fg-changed-intense = "#cf9fe2"
146+
147+bg-removed = "#3d3d00"
148+bg-removed-faint = "#281f00"
149+bg-removed-refine = "#555500"
150+bg-removed-fringe = "#d0c03f"
151+fg-removed = "#d4d48f"
152+fg-removed-intense = "#d0b05f"
153+
154+bg-diff-context = "#1a1a1a"
155+
156+# Paren match
157+bg-paren-match = "#2f7f9f"
158+bg-paren-expression = "#453040"
runtime/themes/modus_vivendi_tinted.tomlnew file+144
@@ -0,0 +1,144 @@
1+# Author: Matous Dzivjak <matousdzivjak@gmail.com>
2+# Adapted from: https://protesilaos.com/emacs/modus-themes, by Protesilaos Stavrou
3+# Source: https://github.com/protesilaos/modus-themes/blob/main/modus-vivendi-tinted-theme.el
4+# Version 4.3.0
5+
6+inherits = "modus_vivendi"
7+
8+"comment" = "red-faint"
9+
10+"ui.cursor.primary" = { fg = "bg-main", bg = "red" }
11+
12+[palette]
13+# Basic values
14+bg-main = "#0d0e1c"
15+bg-dim = "#1d2235"
16+fg-main = "#ffffff"
17+fg-dim = "#989898"
18+fg-alt = "#c6daff"
19+bg-active = "#4a4f69"
20+bg-inactive = "#2b3045"
21+border = "#61647a"
22+
23+# Common accent foregrounds
24+red = "#ff5f59"
25+red-warmer = "#ff6b55"
26+red-cooler = "#ff7f9f"
27+red-faint = "#ff9f80"
28+red-intense = "#ff5f5f"
29+green = "#44bc44"
30+green-warmer = "#70b900"
31+green-cooler = "#00c06f"
32+green-faint = "#88ca9f"
33+green-intense = "#44df44"
34+yellow = "#d0bc00"
35+yellow-warmer = "#fec43f"
36+yellow-cooler = "#dfaf7a"
37+yellow-faint = "#d2b580"
38+yellow-intense = "#efef00"
39+blue = "#2fafff"
40+blue-warmer = "#79a8ff"
41+blue-cooler = "#00bcff"
42+blue-faint = "#82b0ec"
43+blue-intense = "#338fff"
44+magenta = "#feacd0"
45+magenta-warmer = "#f78fe7"
46+magenta-cooler = "#b6a0ff"
47+magenta-faint = "#caa6df"
48+magenta-intense = "#ff66ff"
49+cyan = "#00d3d0"
50+cyan-warmer = "#4ae2f0"
51+cyan-cooler = "#6ae4b9"
52+cyan-faint = "#9ac8e0"
53+cyan-intense = "#00eff0"
54+
55+# Uncommon accent foregrounds
56+rust = "#db7b5f"
57+gold = "#c0965b"
58+olive = "#9cbd6f"
59+slate = "#76afbf"
60+indigo = "#9099d9"
61+maroon = "#cf7fa7"
62+pink = "#d09dc0"
63+
64+# Common accent backgrounds
65+bg-red-intense = "#9d1f1f"
66+bg-green-intense = "#2f822f"
67+bg-yellow-intense = "#7a6100"
68+bg-blue-intense = "#1640b0"
69+bg-magenta-intense = "#7030af"
70+bg-cyan-intense = "#2266ae"
71+
72+bg-red-subtle = "#620f2a"
73+bg-green-subtle = "#00422a"
74+bg-yellow-subtle = "#4a4000"
75+bg-blue-subtle = "#242679"
76+bg-magenta-subtle = "#552f5f"
77+bg-cyan-subtle = "#004065"
78+
79+bg-red-nuanced = "#350f14"
80+bg-green-nuanced = "#002718"
81+bg-yellow-nuanced = "#2c1f00"
82+bg-blue-nuanced = "#131c4d"
83+bg-magenta-nuanced = "#2f133f"
84+bg-cyan-nuanced = "#04253f"
85+
86+# Special purpose
87+bg-completion = "#483d8a"
88+bg-hover = "#45605e"
89+bg-hover-secondary = "#654a39"
90+bg-hl-line = "#303a6f"
91+bg-region = "#555a66"
92+fg-region = "#ffffff"
93+
94+bg-char-0 = "#0050af"
95+bg-char-1 = "#7f1f7f"
96+bg-char-2 = "#625a00"
97+
98+bg-mode-line-active = "#484d67"
99+fg-mode-line-active = "#ffffff"
100+border-mode-line-active = "#979797"
101+bg-mode-line-inactive = "#292d48"
102+fg-mode-line-inactive = "#969696"
103+border-mode-line-inactive = "#606270"
104+
105+modeline-err = "#ffa9bf"
106+modeline-warning = "#dfcf43"
107+modeline-info = "#9fefff"
108+
109+bg-tab-bar = "#2c3045"
110+bg-tab-current = "#0d0e1c"
111+bg-tab-other = "#4a4f6a"
112+
113+# Diffs
114+bg-added = "#003a2f"
115+bg-added-faint = "#002922"
116+bg-added-refine = "#035542"
117+bg-added-fringe = "#23884f"
118+fg-added = "#a0e0a0"
119+fg-added-intense = "#80e080"
120+
121+bg-changed = "#363300"
122+bg-changed-faint = "#2a1f00"
123+bg-changed-refine = "#4a4a00"
124+bg-changed-fringe = "#8f7a30"
125+fg-changed = "#efef80"
126+fg-changed-intense = "#c0b05f"
127+
128+bg-removed = "#4f1127"
129+bg-removed-faint = "#380a19"
130+bg-removed-refine = "#781a3a"
131+bg-removed-fringe = "#b81a26"
132+fg-removed = "#ffbfbf"
133+fg-removed-intense = "#ff9095"
134+
135+bg-diff-context = "#1a1f30"
136+
137+# Uncommon accent backgrounds
138+bg-ochre = "#442c2f"
139+bg-lavender = "#38325c"
140+bg-sage = "#0f3d30"
141+
142+# Paren match
143+bg-paren-match = "#2f7f9f"
144+bg-paren-expression = "#453040"
runtime/themes/modus_vivendi_tritanopia.tomlnew file+186
@@ -0,0 +1,186 @@
1+# Author: Matous Dzivjak <matousdzivjak@gmail.com>
2+# Adapted from https://protesilaos.com/emacs/modus-themes, by Protesilaos Stavrou
3+# Source: https://github.com/protesilaos/modus-themes/blob/main/modus-vivendi-tritanopia-theme.el
4+# Version 4.3.0
5+
6+inherits = "modus_vivendi"
7+
8+"type" = "blue-warmer"
9+"constructor" = "blue-warmer"
10+"constant" = "green-cooler"
11+"constant.character.escape" = "red-cooler"
12+"string" = "cyan"
13+"comment" = "red-faint"
14+"variable.parameter" = "cyan-cooler"
15+"keyword" = "red-cooler"
16+"keyword.directive" = "red-warmer"
17+"function" = "cyan-warmer"
18+"function.macro" = "magenta"
19+"tag" = "red-cooler"
20+
21+"markup.heading.2" = { fg = "red-faint", modifiers = ["bold"] }
22+"markup.heading.3" = { fg = "cyan-faint", modifiers = ["bold"] }
23+"markup.heading.6" = { fg = "magenta-faint", modifiers = ["bold"] }
24+"markup.link.url" = { fg = "cyan-cooler" }
25+"markup.link.text" = { fg = "cyan", modifiers = ["underlined"] }
26+
27+"ui.cursor" = { fg = "bg-main", bg = "red-intense" }
28+"ui.cursor.primary.normal" = { fg = "bg-main", bg = "red-intense" }
29+
30+"diagnostic.error" = { underline = { color = "red-warmer", style = "curl" } }
31+"diagnostic.warning" = { underline = { color = "magenta", style = "curl" } }
32+"diagnostic.info" = { underline = { color = "cyan", style = "curl" } }
33+"diagnostic.hint" = { underline = { color = "blue", style = "curl" } }
34+
35+error = "red-warmer"
36+warning = "magenta"
37+info = "cyan"
38+hint = "blue"
39+
40+[palette]
41+# Basic values
42+bg-main = "#000000"
43+bg-dim = "#1e1e1e"
44+fg-main = "#ffffff"
45+fg-dim = "#989898"
46+fg-alt = "#c6daff"
47+bg-active = "#535353"
48+bg-inactive = "#303030"
49+border = "#646464"
50+
51+# Common accent foregrounds
52+red = "#ff5f59"
53+red-warmer = "#ff6740"
54+red-cooler = "#ff6f9f"
55+red-faint = "#ff9070"
56+red-intense = "#ff5f5f"
57+green = "#44bc44"
58+green-warmer = "#70b900"
59+green-cooler = "#00c06f"
60+green-faint = "#88ca9f"
61+green-intense = "#44df44"
62+yellow = "#cabf00"
63+yellow-warmer = "#ffa00f"
64+yellow-cooler = "#d8af7a"
65+yellow-faint = "#d2b580"
66+yellow-intense = "#efef00"
67+blue = "#2fafff"
68+blue-warmer = "#79a8ff"
69+blue-cooler = "#00bcff"
70+blue-faint = "#82b0ec"
71+blue-intense = "#338fff"
72+magenta = "#feacd0"
73+magenta-warmer = "#f78fe7"
74+magenta-cooler = "#b6a0ff"
75+magenta-faint = "#caa6df"
76+magenta-intense = "#ef7fff"
77+cyan = "#00d3d0"
78+cyan-warmer = "#4ae2ff"
79+cyan-cooler = "#6ae4b9"
80+cyan-faint = "#7fdbdf"
81+cyan-intense = "#00eff0"
82+
83+# Uncommon accent foregrounds
84+rust = "#db7b5f"
85+gold = "#c0965b"
86+olive = "#9cbd6f"
87+slate = "#76afbf"
88+indigo = "#9099d9"
89+maroon = "#cf7fa7"
90+pink = "#d09dc0"
91+
92+# Common accent backgrounds
93+bg-red-intense = "#9d1f1f"
94+bg-green-intense = "#2f822f"
95+bg-yellow-intense = "#7a6100"
96+bg-blue-intense = "#1640b0"
97+bg-magenta-intense = "#7030af"
98+bg-cyan-intense = "#2266ae"
99+
100+bg-red-subtle = "#620f2a"
101+bg-green-subtle = "#00422a"
102+bg-yellow-subtle = "#4a4000"
103+bg-blue-subtle = "#242679"
104+bg-magenta-subtle = "#552f5f"
105+bg-cyan-subtle = "#004065"
106+
107+bg-red-nuanced = "#2c0614"
108+bg-green-nuanced = "#001904"
109+bg-yellow-nuanced = "#221000"
110+bg-blue-nuanced = "#0f0e39"
111+bg-magenta-nuanced = "#230631"
112+bg-cyan-nuanced = "#041529"
113+
114+# Uncommon accent backgrounds
115+bg-ochre = "#442c2f"
116+bg-lavender = "#38325c"
117+bg-sage = "#0f3d30"
118+
119+# Graphs
120+bg-graph-red-0 = "#b52c2c"
121+bg-graph-red-1 = "#702020"
122+bg-graph-green-0 = "#afd1c0"
123+bg-graph-green-1 = "#607a8f"
124+bg-graph-yellow-0 = "#facfd6"
125+bg-graph-yellow-1 = "#b57b85"
126+bg-graph-blue-0 = "#4f9fdf"
127+bg-graph-blue-1 = "#004559"
128+bg-graph-magenta-0 = "#b6427f"
129+bg-graph-magenta-1 = "#7f506f"
130+bg-graph-cyan-0 = "#57dfea"
131+bg-graph-cyan-1 = "#00808f"
132+
133+# Special purpose
134+bg-completion = "#004253"
135+bg-hover = "#8e3e3b"
136+bg-hover-secondary = "#00405f"
137+bg-hl-line = "#2f3849"
138+bg-region = "#5a5a5a"
139+fg-region = "#ffffff"
140+
141+bg-char-0 = "#922a00"
142+bg-char-1 = "#00709f"
143+bg-char-2 = "#5f3faf"
144+
145+bg-mode-line-active = "#003c52"
146+fg-mode-line-active = "#f0f0f0"
147+border-mode-line-active = "#5f8fb4"
148+bg-mode-line-inactive = "#2d2d2d"
149+fg-mode-line-inactive = "#969696"
150+border-mode-line-inactive = "#606060"
151+
152+modeline-err = "#ff7fbf"
153+modeline-warning = "#df9f93"
154+modeline-info = "#4fcfef"
155+
156+bg-tab-bar = "#313131"
157+bg-tab-current = "#000000"
158+bg-tab-other = "#545454"
159+
160+# Diffs
161+bg-added = "#004254"
162+bg-added-faint = "#003042"
163+bg-added-refine = "#004f7f"
164+bg-added-fringe = "#008fcf"
165+fg-added = "#9fdfdf"
166+fg-added-intense = "#50c0ef"
167+
168+bg-changed = "#2f123f"
169+bg-changed-faint = "#1f022f"
170+bg-changed-refine = "#3f325f"
171+bg-changed-fringe = "#7f55a0"
172+fg-changed = "#e3cfff"
173+fg-changed-intense = "#cf9fe2"
174+
175+bg-removed = "#4f1119"
176+bg-removed-faint = "#380a0f"
177+bg-removed-refine = "#781a1f"
178+bg-removed-fringe = "#b81a1f"
179+fg-removed = "#ffbfbf"
180+fg-removed-intense = "#ff9095"
181+
182+bg-diff-context = "#1a1a1a"
183+
184+# Paren match
185+bg-paren-match = "#2f7f9f"
186+bg-paren-expression = "#453040"
runtime/themes/molokai.toml+1−1
@@ -13,7 +13,7 @@ inherits = "monokai"
1313"keyword.storage.modifier" = { fg = "#fd971f", modifiers = ["italic"] }
1414"label" = "#e6db74"
1515"operator" = "keyword"
16−"punctuation.delimeter" = "#8f8f8f"
16+"punctuation.delimiter" = "#8f8f8f"
1717"type" = "light-blue"
1818"variable.builtin" = { fg = "#ae81ff", modifiers = ["bold"] }
1919"tag.builtin" = { fg = "#ae81ff", modifiers = ["bold"] }
runtime/themes/naysayer.toml+2−2
@@ -20,13 +20,13 @@
2020"ui.help" = { fg = "text", bg = "bg" }
2121"ui.popup" = { fg = "text", bg = "bg" }
2222"ui.menu" = { fg = "text", bg = "bg" }
23−"ui.menu.selected" = { fg = "text", bg = "bg" }
23+"ui.menu.selected" = { fg = "text", bg = "bg", modifiers = ['underlined'] }
2424"ui.window" = { bg = "bg" }
2525"diagnostic.error" = { bg = "error", fg = "text", modifiers = ["bold"] }
2626"diagnostic.warning" = { bg = "warning", fg = "text", modifiers = ["bold"] }
2727"diagnostic.hint" = { bg = "cyan", modifiers = ["bold"] }
2828"ui.bufferline" = { fg = "text", bg = "bg" }
29−"ui.bufferline.active" = { fg = "text", bg = "bg" }
29+"ui.bufferline.active" = { fg = "text", bg = "bg", modifiers = ['underlined'] }
3030"ui.gutter.selected" = { bg = "highlight-line", modifiers = ["bold"] }
3131"ui.highlight" = { bg = "highlight-line" }
3232
runtime/themes/nightfox.toml+2−2
@@ -125,7 +125,7 @@
125125"keyword.control.exception" = { fg = "magenta" } # `try`, `catch`, `raise`/`throw` and related.
126126"keyword.operator" = { fg = "fg2", modifiers = ["bold"] } # 'or', 'and', 'in'.
127127"keyword.directive" = { fg = "pink-bright" } # Preprocessor directives (#if in C...).
128−"keyword.function" = { fg = "red" } # The keyword to define a funtion: 'def', 'fun', 'fn'.
128+"keyword.function" = { fg = "red" } # The keyword to define a function: 'def', 'fun', 'fn'.
129129"keyword.storage" = { fg = "magenta" } # Keywords describing how things are stored
130130"keyword.storage.type" = { fg = "magenta" } # The type of something, class, function, var, let, etc.
131131"keyword.storage.modifier" = { fg = "yellow" } # Storage modifiers like static, mut, const, ref, etc.
@@ -183,6 +183,6 @@ bg4 = "#39506d" # Conceal, border fg
183183fg0 = "#d6d6d7" # Lighter fg
184184fg1 = "#cdcecf" # Default fg
185185fg2 = "#aeafb0" # Darker fg (status line)
186−fg3 = "#71839b" # Darker fg (line numbers, fold colums)
186+fg3 = "#71839b" # Darker fg (line numbers, fold columns)
187187sel0 = "#2b3b51" # Popup bg, visual selection bg
188188sel1 = "#3c5372" # Popup sel bg, search bg
runtime/themes/noctis.toml+26−26
@@ -7,8 +7,8 @@
77
88'property' = { fg = "red" } # Regex group names.
99"warning" = { fg ="yellow", modifiers = ["bold"] } # Editor warnings.
10−"error" = { bg = "mid-green", fg = "red", modifiers = ["bold"] } # Editor errors, like mis-typing a command.
11−"info" = { fg = "mid-blue", bg = "mid-green" } # Code diagnostic info in gutter (LSP).
10+"error" = { fg = "red", modifiers = ["bold"] } # Editor errors, like mis-typing a command.
11+"info" = { fg = "mid-blue" } # Code diagnostic info in gutter (LSP).
1212# ? Difference between info and hint ?
1313"hint" = { fg = "light-green", modifiers = ["bold"] } # Code diagnostics hint in gutter (LSP).
1414
@@ -21,14 +21,14 @@
2121# UI ==============================
2222# For styling helix itself.
2323
24−'ui.background' = { bg = "dark-green"} # Default background color.
24+'ui.background' = { fg = "autocomp-green", bg = "dark-green" } # Default background color.
2525'ui.window' = { fg = "mid-green" } # Window border between splits.
2626
2727'ui.gutter' = { } # Left gutter for diagnostics and breakpoints.
2828
2929'ui.text' = { fg = "white" } # Default text color.
3030'ui.text.focus' = { fg = "white", bg = "mid-green", modifiers = ["bold"] } # Selection highlight in buffer-picker or file-picker.
31−'ui.text.info' = { } # Info popup contents (space mode menu).
31+'ui.text.info' = { fg = "white" } # Info popup contents (space mode menu).
3232
3333'ui.cursor' = { fg = "dark-green", bg = "white" } # Fallback cursor colour, non-primary cursors when there are multiple (shift-c).
3434'ui.cursor.primary' = { fg = "dark-green", bg = "light-blue" } # The primary cursor when there are multiple (shift-c).
@@ -40,8 +40,8 @@
4040'ui.selection.primary' = { bg = "autocomp-green" } # The primary selection when there are multiple.
4141'ui.cursorline.primary' = { bg = 'mid-green' }
4242
43−'ui.linenr' = { bg = "dark-green", fg = "gray" } # Line numbers.
44−'ui.linenr.selected' = { bg = "mid-green", fg = "light-green", modifiers = [ "bold" ] } # Current line number.
43+'ui.linenr' = { fg = "gray" } # Line numbers.
44+'ui.linenr.selected' = { fg = "light-green", modifiers = [ "bold" ] } # Current line number.
4545
4646'ui.virtual' = { fg = "mid-green" } # Namespace for additions to the editing area.
4747'ui.virtual.ruler' = { bg = "mid-green" } # Vertical rulers (colored columns in editing area).
@@ -75,9 +75,9 @@
7575#'type.builtin' = { } # Primitive types of the language (string, int, float).
7676#'type.enum.variant' = { } # A variant of an enum.
7777
78−'constructor' = { fg = "mid-blue", modifiers = ["bold"]} # Constructor method for a class or struct. And in some cases applies to module names
78+'constructor' = { fg = "light-blue", modifiers = ["bold"]} # Constructor method for a class or struct. And in some cases applies to module names
7979
80−'constant' = { fg = "light-blue" } # Constant value
80+'constant' = { fg = "light-blue", modifiers = ["bold"] } # Constant value
8181'constant.builtin' = { fg = "mid-blue", modifiers = ["bold"] } # Special constants like `true`, `false`, `none`, etc.
8282'constant.builtin.boolean' = { } # True or False.
8383'constant.character' = { fg = "light-green"} # Constant of character type.
@@ -88,42 +88,41 @@
8888
8989'string' = { fg = "light-green" } # String literal.
9090'string.regexp' = { } # Regular expression literal.
91−'string.special' = { fg = "light-blue" } # Strings containing a path, URL, etc.
92−'string.special.path' = { } # String containing a file path.
93−'string.special.url' = { } # String containing a web URL.
94−'string.special.symbol' = { } # Erlang/Elixir atoms, Ruby symbols, Clojure keywords.
91+'string.special' = { fg = "red" } # Strings containing a path, URL, etc.
92+# 'string.special.path' = { } # String containing a file path.
93+# 'string.special.url' = { } # String containing a web URL.
94+# 'string.special.symbol' = { } # Erlang/Elixir atoms, Ruby symbols, Clojure keywords.
9595
9696'comment' = { fg = "gray", modifiers = ["italic"] } # This is a comment.
9797'comment.line' = { } # Line comments, like this.
9898'comment.block' = { } # Block comments, like /* this */ in some languages.
9999'comment.block.documentation' = { } # Doc comments, e.g '///' in rust.
100100
101−'variable' = { fg = "white" } # Variable names.
102−'variable.builtin' = { } # Language reserved variables: `this`, `self`, `super`, etc.
103−'variable.parameter' = { } # Funtion parameters.
104−'variable.other.member' = { } # Fields of composite data types (e.g. structs, unions).
105−'variable.function' = { } # ?
101+'variable' = { fg = "light-orange" } # Variable names.
102+# 'variable.builtin' = { } # Language reserved variables: `this`, `self`, `super`, etc.
103+# 'variable.parameter' = { } # Function parameters.
104+'variable.other.member' = { fg = "orange" } # Fields of composite data types (e.g. structs, unions).
106105
107106'label' = { fg = "purple" } # Loop labels in rust.
108107
109108'punctuation' = { fg = "yellow", modifiers = ["bold"] } # (){}[]:;,.
110−# 'punctuation.delimeter' = { fg = "yellow" } # Commas and colons.
109+# 'punctuation.delimiter' = { fg = "yellow" } # Commas and colons.
111110# 'punctuation.bracket' = { fg = "yellow" } # Parentheses, angle brackets, etc.
112111
113112'keyword' = { fg = "pink", modifiers = ["bold"] } # Language reserved keywords.
114113'keyword.control' = { fg = "pink", modifiers = ["bold"] } # Control keywords.
115114'keyword.control.conditional' = { fg = "pink", modifiers = ["bold"] } # 'if', 'else', 'elif'.
116−'keyword.control.repeat' = { } # 'for', 'while', 'loop'.
115+# 'keyword.control.repeat' = { } # 'for', 'while', 'loop'.
117116'keyword.control.import' = { fg = "pink", modifiers = ["italic"] } # 'import', 'export' ('use'?).
118−'keyword.control.return' = { } # 'return' in most languages.
117+# 'keyword.control.return' = { } # 'return' in most languages.
119118'keyword.control.exception' = {fg = "pink", modifiers = ["bold"] } # 'raise' in python.
120−'keyword.operator' = { } # 'or', 'and', 'in'.
119+'keyword.operator' = { fg = "pink" } # 'or', 'and', 'in'.
121120'keyword.directive' = { fg = "purple" } # Preprocessor directives (#if in C).
122−'keyword.function' = { } # The keyword to define a funtion: 'def', 'fun', 'fn'.
121+'keyword.function' = { fg= "red" } # The keyword to define a function: 'def', 'fun', 'fn'.
123122
124123'operator' = { fg = "pink", modifiers = ["bold"] } # Logical (&&, ||) and - I assume - Mathematical (+, %) operators
125124
126−'function' = { fg = "dark-blue"}
125+'function' = { fg = "mid-blue"}
127126'function.builtin' = { fg = "dark-blue" }
128127'function.method' = { fg = "dark-blue" } # Class / Struct methods.
129128'function.macro' = { fg = "purple" } # Like macros in rust.
@@ -181,8 +180,8 @@
181180# Version control changes.
182181
183182'diff.plus' = "light-green" # { } # Additions.
184−'diff.minus' = "yellow" # { } # Deletions.
185−'diff.delta' = "red" # { } # Modifications.
183+'diff.minus' = "red" # { } # Deletions.
184+'diff.delta' = "yellow" # { } # Modifications.
186185# 'diff.delta.moved' = { } # Renamed or moved files / changes.
187186
188187
@@ -197,8 +196,9 @@ yellow = "#ffd800"
197196purple = "#918cff"
198197white = "#b1cace"
199198orange = "#ffa864"
199+light-orange = "#fff2c5"
200200gray = "#5b858b" # mainly for comments/background text
201−light-gray = "#354e51" # used when whitespace rendering is enabled and for indent-guides
201+light-gray = "#2a3c41" # used when whitespace rendering is enabled and for indent-guides
202202red = "#e34e1b"
203203
204204dark-blue = "#19a2b7"
runtime/themes/nord-night.tomlnew file+23
@@ -0,0 +1,23 @@
1+# Nord Night
2+#
3+# Based on the Nord theme, with minor modifications.
4+# The Background and the Primary Text color have been slightly darkened.
5+# The Aurora color palette has been used more generously.
6+
7+inherits = 'nord'
8+
9+'constant' = 'nord13'
10+'constant.builtin.boolean' = 'nord13'
11+'constant.numeric' = 'nord13'
12+
13+'keyword.control' = 'nord11'
14+'keyword.control.conditional' = 'nord11'
15+'keyword.control.exception' = 'nord11'
16+'keyword.control.repeat' = 'nord11'
17+'keyword.control.return' = 'nord11'
18+
19+'variable.parameter' = 'nord15'
20+
21+[palette]
22+nord0 = '#252933'
23+nord4 = '#C0C5CF'
runtime/themes/nord.toml+16−7
@@ -50,7 +50,7 @@
5050"keyword.operator" = "nord9"
5151"keyword.return" = "nord9"
5252"keyword.storage.modifier" = "nord9"
53−"keyword.storage.type" = "nord7"
53+"keyword.storage.type" = "nord9"
5454
5555# Punctuation
5656"punctuation" = "nord6"
@@ -65,22 +65,22 @@
6565"string.special" = "nord13"
6666
6767# Types
68−"type" = "nord4"
68+"type" = "nord7"
6969"type.builtin" = "nord7"
7070
7171# Variables
7272"variable" = "nord4"
73−"variable.builint" = "nord9"
73+"variable.builtin" = "nord9"
7474"variable.other.member" = "nord4"
7575"variable.parameter" = "nord8"
76−"attribute" = "nord4"
76+"attribute" = "nord9"
7777
7878# Misc.
7979"label" = "nord7"
8080"namespace" = "nord4"
8181"operator" = "nord9"
82−"special" = "nord4"
83−"tag" = "nord4"
82+"special" = "nord9"
83+"tag" = "nord7"
8484"comment" = { fg = "nord3_bright", modifiers = ["italic"] }
8585
8686## EDITOR UI COLORS
@@ -134,6 +134,15 @@
134134"ui.bufferline" = { fg = "nord5", bg = "nord1" }
135135"ui.bufferline.active" = { fg = "nord6", bg = "nord2", underline = { color = "nord8", style = "line" }, modifiers = [ "italic" ] }
136136
137+# Markup
138+"markup.heading" = "nord8"
139+"markup.list" = "nord9"
140+"markup.bold" = { modifiers = ["bold"] }
141+"markup.italic" = { modifiers = ["italic"] }
142+"markup.strikethrough" = { modifiers = ["crossed_out"] }
143+"markup.link.text" = "nord8"
144+"markup.raw" = "nord7"
145+
137146[palette]
138147# Polar Night is made up of four darker colors that are commonly used for base elements like backgrounds or text color in bright ambiance designs.
139148#
@@ -165,7 +174,7 @@ nord8 = "#88C0D0"
165174# A more darkened and less saturated color reminiscent of arctic waters
166175nord9 = "#81A1C1"
167176# A dark and intensive color reminiscent of the deep arctic ocean
168− nord10 = "#5E81AC"
177+nord10 = "#5E81AC"
169178
170179# Aurora consists of five colorful components reminiscent of the "Aurora borealis", sometimes referred to as polar lights or northern lights.
171180#
runtime/themes/onedark.toml+1
@@ -1,5 +1,6 @@
11# Author : Gokul Soumya <gokulps15@gmail.com>
22
3+"tag" = { fg = "red" }
34"attribute" = { fg = "yellow" }
45"comment" = { fg = "light-gray", modifiers = ["italic"] }
56"constant" = { fg = "cyan" }
runtime/themes/papercolor-dark.toml+67−116
@@ -1,124 +1,75 @@
11# Palette based on https://github.com/NLKNguyen/papercolor-theme
22# Author: Soc Virnyl Estela <socvirnyl.estela@gmail.com>
33
4−"ui.linenr.selected" = { fg = "linenr_fg_selected" }
5−"ui.background" = {bg="background"}
6−"ui.text" = "foreground"
7−"ui.text.focus" = { fg = "selection_background", modifiers = ["bold"]}
8−"ui.selection" = {bg="selection_background", fg="selection_foreground"}
9−"ui.cursorline" = {bg="cursorline_background"}
10−"ui.highlight" = {bg="cursorline_background"}
11−"ui.statusline" = {bg="paper_bar_bg", fg="regular0"}
12−"ui.statusline.select" = {bg="background", fg="bright7"}
13−"ui.statusline.normal" = {bg="background", fg="bright3"}
14−"ui.statusline.inactive" = {bg="selection_foreground", fg="foreground"}
15−"ui.virtual.whitespace" = { fg = "regular5" }
16−"ui.virtual.ruler" = {bg="cursorline_background"}
17−"ui.cursor.match" = {bg = "regular5", fg = "regular0"}
18−"ui.cursor" = {bg = "regular5", fg = "background"}
19−"ui.window" = {bg = "#303030", fg = "bright2"}
20−"ui.help" = {bg = "background", fg = "bright2"}
21−"ui.popup" = {bg = "#303030", fg = "bright6"}
22−"ui.menu" = {bg = "#303030", fg = "bright6"}
23−"ui.menu.selected" = {bg = "#C6C6C6", fg="selection_foreground"}
4+inherits = "papercolor-light"
245
25−"markup.heading" = { fg = "regular4", modifiers = ["bold"] }
26−"markup.heading.1" = { fg = "bright2", modifiers = ["bold"] }
27−"markup.heading.2" = { fg = "bright5", modifiers = ["bold"] }
28−"markup.heading.3" = { fg = "bright3", modifiers = ["bold"] }
29−"markup.heading.4" = { fg = "bright5", modifiers = ["bold"] }
30−"markup.heading.5" = { fg = "bright5", modifiers = ["bold"] }
31−"markup.heading.6" = { fg = "bright5", modifiers = ["bold"] }
32−"markup.list" = "bright3"
33−"markup.bold" = { fg = "foreground", modifiers = ["bold"] }
34−"markup.italic" = { fg = "bright0", modifiers = ["italic"] }
35−"markup.strikethrough" = { modifiers = ["crossed_out"] }
36−"markup.link.url" = { fg = "bright6", modifiers = ["underlined"] }
37−"markup.link.text" = "bright2"
38−"markup.link.label" = { fg = "regular2", modifiers = ["bold"] }
39−"markup.raw" = "foreground"
40−
41−"string" = "foreground"
42−"attribute" = "bright7"
43−"keyword" = { fg = "regular4", modifiers = ["bold"]}
44−"keyword.directive" = "regular4"
45−"keyword.control.conditional" = "bright3"
46−"keyword.function" = "regular4"
47−"namespace" = "bright1"
48−"type" = "bright2"
49−"type.builtin" = { fg = "foreground", modifiers = ["bold"]}
50−"variable" = "foreground"
51−"variable.builtin" = "cyan"
52−"variable.other.member" = "cyan"
53−"variable.parameter" = "foreground"
54−
55−"special" = "#3E999F"
56−"function" = "bright6"
57−"constructor" = "regular4"
58−"function.builtin" = { fg = "foreground", modifiers = ["bold"]}
59−"function.macro" = { fg = "regular4", modifiers = ["bold"] }
60−"comment" = { fg = "#686868", modifiers = ["dim"] }
61−"ui.linenr" = { fg = "bright0" }
62−"module" = "regular4"
63−"constant" = "bright5"
64−"constant.builtin" = "bright6"
65−"constant.numeric" = "bright5"
66−"constant.character.escape" = { fg = "foreground", modifiers = ["bold"]}
67−"operator" = { fg = "regular4", modifiers = ["bold"]}
68−
69−"label" = { fg = "selection_background", modifiers = ["bold", "italic"] }
70−
71−"diff.plus" = "regular2"
72−"diff.delta" = "regular6"
73−"diff.minus" = "regular1"
6+[palette]
7+background = "#1c1c1c"
8+foreground = "#d0d0d0"
749
75−"warning" = "bright4"
76−"error" = "regular1"
77−"info" = "bright4"
10+regular0 = "#1c1c1c" # color00 "Background"
11+regular1 = "#af005f" # color01 "Negative"
12+regular2 = "#5faf00" # color02 "Positive"
13+regular3 = "#d7af5f" # color03 "Olive"
14+regular4 = "#5fafd7" # color04 "Neutral" / Aqua
15+regular5 = "#808080" # color05 "Comment"
16+regular6 = "#d7875f" # color06 "Navy"
17+regular7 = "#d0d0d0" # color07 "Foreground"
18+bright0 = "#585858" # color08 "Nontext"
19+bright1 = "#5faf5f" # color09 "Red"
20+bright2 = "#afd700" # color10 "Pink"
21+bright3 = "#af87d7" # color11 "Purple"
22+bright4 = "#ffaf00" # color12 "Accent"
23+bright5 = "#ff5faf" # color13 "Orange"
24+bright6 = "#00afaf" # color14 "Blue"
25+bright7 = "#5f8787" # color15 "Highlight"
7826
79−"diagnostic.warning".underline = { color = "bright4", style = "curl" }
80−"diagnostic.error".underline = { color = "regular1", style = "curl" }
81−"diagnostic.info".underline = { color = "bright4", style = "curl" }
82−"diagnostic.hint".underline = { color = "bright4", style = "curl" }
27+selection_fg = "#000000"
28+selection_bg = "#8787af"
29+selection_secondary_fg = "#333333"
30+selection_secondary_bg = "#707097"
31+special = "#3e999f"
8332
33+cursorline_bg = "#303030"
34+cursorline_secondary_bg = "#2a2a2a"
35+cursorcolumn_bg = "#303030"
36+cursorcolumn_secondary_bg = "#2a2a2a"
37+cursorlinenr_fg = "#ffff00"
38+popupmenu_fg = "#c6c6c6"
39+popupmenu_bg = "#303030"
40+linenumber_fg = "#585858"
41+vertsplit_fg = "#5f8787"
42+statusline_active_fg = "#1c1c1c"
43+statusline_active_bg = "#5f8787"
44+statusline_inactive_fg = "#bcbcbc"
45+statusline_inactive_bg = "#3a3a3a"
46+todo_fg = "#ff8700"
47+error_fg = "#af005f"
48+error_bg = "#5f0000"
49+matchparen_bg = "#4e4e4e"
50+matchparen_fg = "#c6c6c6"
51+wildmenu_fg = "#1c1c1c"
52+wildmenu_bg = "#afd700"
53+diffadd_fg = "#87d700"
54+diffadd_bg = "#005f00"
55+diffdelete_fg = "#af005f"
56+diffdelete_bg = "#5f0000"
57+diffchange_bg = "#005f5f"
8458
85−[palette]
86−background="#1c1c1c"
87−foreground="#d0d0d0"
88−regular0="#1c1c1c"
89−regular1="#af005f"
90−regular2="#5faf00"
91−regular3="#d7af5f"
92−regular4="#5fafd7"
93−regular5="#808080"
94−regular6="#d7875f"
95−regular7="#d0d0d0"
96−bright0="#585858"
97−bright1="#5faf5f"
98−bright2="#afd700"
99−bright3="#af87d7"
100−bright4="#FFAF00"
101−bright5="#ff5faf"
102−bright6="#00afaf"
103−bright7="#5f8787"
104−selection_foreground="#585858"
105−selection_background="#8787AF"
106−cursorline_background="#303030"
107−paper_bar_bg="#5F8787"
108−black="#1c1c1c"
109−red="#af005f"
110−green="#5faf00"
111−yellow="#d7af5f"
112−blue="#5fafd7"
113−magenta="#808080"
114−cyan="#d7875f"
115−gray="#d0d0d0"
116−light-red="#5faf5f"
117−light-green="#afd700"
118−light-yellow="#af87d7"
119−light-blue="#FFAF00"
120−light-magenta="#ff5faf"
121−light-cyan="#00afaf"
122−light-gray="#5f8787"
123−white="#808080"
124−linenr_fg_selected="#FFFF00"
59+# 16 bit ANSI color names
60+black = "#1c1c1c"
61+red = "#af005f"
62+green = "#5faf00"
63+yellow = "#d7af5f"
64+blue = "#5fafd7"
65+magenta = "#808080"
66+cyan = "#d7875f"
67+white = "#d0d0d0"
68+light-black = "#585858"
69+light-red = "#5faf5f"
70+light-green = "#afd700"
71+light-yellow = "#af87d7"
72+light-blue = "#ffaf00"
73+light-magenta = "#ff5faf"
74+light-cyan = "#00afaf"
75+light-white = "#5f8787"
runtime/themes/papercolor-light.toml+194−103
@@ -1,31 +1,128 @@
11# Palette based on https://github.com/NLKNguyen/papercolor-theme
22# Author: Soc Virnyl Estela <socvirnyl.estela@gmail.com>
33
4−"ui.linenr.selected" = { fg = "linenr_fg_selected" }
5−"ui.background" = {bg="background"}
4+"ui.linenr.selected" = { fg = "cursorlinenr_fg", modifiers = ["bold"] }
5+"ui.linenr" = { fg = "linenumber_fg" }
6+"ui.background" = { bg = "background" }
67"ui.text" = "foreground"
7−"ui.text.focus" = { fg = "selection_background", modifiers = ["bold"]}
8−"ui.selection" = {bg="selection_background", fg="selection_foreground"}
9−"ui.highlight" = {bg="cursorline_background"}
10−"ui.cursorline" = {bg="cursorline_background"}
11−"ui.statusline" = {bg="paper_bar_bg", fg="regular0"}
12−"ui.statusline.select" = {bg="background", fg="bright7"}
13−"ui.statusline.normal" = {bg="background", fg="bright3"}
14−"ui.statusline.inactive" = {bg="bright0", fg="foreground"}
15−"ui.virtual" = "indent"
8+"ui.text.focus" = { fg = "selection_bg", modifiers = ["bold"] }
9+"ui.selection" = { bg = "selection_secondary_bg", fg = "selection_secondary_fg" }
10+"ui.selection.primary" = { bg = "selection_bg", fg = "selection_fg" }
11+"ui.highlight" = { bg = "cursorline_bg" }
12+
13+"ui.cursorline" = { bg = "cursorline_bg" }
14+"ui.cursorline.secondary" = { bg = "cursorline_secondary_bg" }
15+"ui.cursorcolumn" = { bg = "cursorline_bg" }
16+"ui.cursorcolumn.secondary" = { bg = "cursorcolumn_secondary_bg" }
17+
18+"ui.statusline" = { bg = "statusline_active_bg", fg = "statusline_active_fg" }
19+"ui.statusline.inactive" = { bg = "statusline_inactive_bg", fg = "statusline_inactive_fg" }
20+"ui.statusline.normal" = { bg = "statusline_inactive_bg", fg = "bright6" }
21+"ui.statusline.insert" = { bg = "statusline_inactive_bg", fg = "bright4" }
22+"ui.statusline.select" = { bg = "statusline_inactive_bg", fg = "regular3" }
23+"ui.statusline.separator" = { bg = "statusline_active_bg", fg = "statusline_active_bg" }
24+
25+"ui.virtual" = { fg = "cursorlinenr_fg" }
1626"ui.virtual.whitespace" = { fg = "regular5" }
17−"ui.virtual.ruler" = {bg="cursorline_background"}
18−"ui.cursor.match" = {bg = "regular5", fg = "regular0"}
19−"ui.cursor" = {bg = "regular5", fg = "background"}
20−"ui.window" = {bg = "#D0D0D0", fg = "bright2"}
21−"ui.help" = {bg = "background", fg = "bright2"}
22−"ui.popup" = {bg = "#D0D0D0", fg = "bright7"}
23−"ui.menu" = {bg = "#D0D0D0", fg = "bright7"}
24−"ui.menu.selected" = {bg = "selection_background", fg="selection_foreground"}
25−
26−"markup.heading" = { fg = "bright7", modifiers = ["bold"] }
27+"ui.virtual.indent-guide" = { fg = "bright0" }
28+"ui.virtual.ruler" = { bg = "cursorline_secondary_bg", fg = "regular4" }
29+"ui.virtual.inlay-hint" = { fg = "regular5", modifiers = ["italic"] }
30+"ui.virtual.inlay-hint.parameter" = { fg = "regular5", modifiers = ["italic"] }
31+"ui.virtual.inlay-hint.type" = { fg = "regular5", modifiers = ["bold", "italic"] }
32+"ui.cursor.match" = { bg = "matchparen_bg", fg = "matchparen_fg" }
33+"ui.cursor" = { bg = "regular5", fg = "background" }
34+"ui.cursor.primary" = { bg = "foreground", fg = "background" }
35+"ui.window" = { fg = "vertsplit_fg" }
36+"ui.help" = { bg = "wildmenu_bg", fg = "wildmenu_fg" }
37+"ui.popup" = { bg = "popupmenu_bg", fg = "popupmenu_fg" }
38+"ui.popup.info" = { bg = "popupmenu_bg", fg = "bright7", modifiers = ["bold"] }
39+"ui.menu" = { bg = "popupmenu_bg", fg = "foreground" }
40+"ui.menu.selected" = { bg = "selection_bg", fg = "selection_fg" }
41+
42+"warning" = "bright5"
43+"error" = { bg = "error_bg", fg = "error_fg" }
44+"info" = "todo_fg"
45+
46+"diagnostic.warning" = { fg = "bright0", modifiers = [
47+ "dim",
48+], underline = { color = "bright5", style = "curl" } }
49+"diagnostic.error".underline = { color = "bright1", style = "curl" }
50+"diagnostic.info".underline = { color = "bright4", style = "curl" }
51+"diagnostic.hint".underline = { color = "bright6", style = "curl" }
52+
53+# Tree-sitter scopes for syntax highlighting
54+"attribute" = "bright4"
55+
56+"type" = { fg = "bright2", modifiers = ["bold"] }
57+"type.builtin" = { fg = "bright2", modifiers = ["bold"] }
58+"type.parameter" = { fg = "foreground" }
59+"type.enum" = { fg = "foreground" }
60+"type.enum.variant" = { fg = "foreground" }
61+
62+"constructor" = "foreground"
63+
64+"constant" = "bright5"
65+"constant.builtin" = "regular3"
66+"constant.builtin.boolean" = { fg = "regular2", modifiers = ["bold"] }
67+"constant.character.escape" = { fg = "bright3", modifiers = ["bold"] }
68+"constant.character" = { fg = "regular3" }
69+"constant.numeric" = "bright5"
70+
71+"string" = "regular3"
72+"string.regexp" = "bright3"
73+
74+"comment" = { fg = "regular5", modifiers = ["italic"] }
75+"comment.line" = { fg = "regular5", modifiers = ["italic"] }
76+"comment.block" = { fg = "regular5", modifiers = ["italic"] }
77+"comment.block.documentation" = { fg = "regular5", modifiers = ["bold"] }
78+
79+"variable" = "foreground"
80+"variable.builtin" = "bright5"
81+"variable.other.member" = "foreground"
82+"variable.parameter" = "foreground"
83+
84+"label" = { fg = "selection_bg", modifiers = ["bold", "italic"] }
85+
86+"punctuation" = { fg = "foreground" }
87+"punctuation.delimiter" = { fg = "regular4", modifiers = ["bold"] }
88+"punctuation.bracket" = { fg = "foreground" }
89+"punctuation.special" = { fg = "bright1", modifiers = ["bold"] }
90+
91+"keyword" = { fg = "bright2" }
92+"keyword.control" = "bright1"
93+"keyword.control.conditional" = { fg = "bright3", modifiers = ["bold"] }
94+"keyword.control.repeat" = { fg = "bright3", modifiers = ["bold"] }
95+"keyword.control.import" = { fg = "bright2" }
96+"keyword.control.return" = { fg = "bright2" }
97+"keyword.control.exception" = { fg = "bright1" }
98+
99+"keyword.operator" = { fg = "regular4", modifiers = ["bold"] }
100+"keyword.directive" = "regular4"
101+"keyword.function" = "bright2"
102+"keyword.storage" = "bright2"
103+"keyword.storage.type" = { fg = "regular4", modifiers = ["bold"] }
104+"keyword.storage.modifier" = { fg = "regular6", modifiers = ["bold"] }
105+"keyword.storage.modifier.ref" = { fg = "regular4", modifiers = ["bold"] }
106+"keyword.special" = "bright1"
107+
108+"operator" = { fg = "regular4", modifiers = ["bold"] }
109+
110+"function" = { fg = "foreground" }
111+"function.builtin" = { fg = "bright6" }
112+"function.method" = { fg = "foreground" }
113+"function.macro" = { fg = "regular3", modifiers = ["bold"] }
114+"function.special" = { fg = "bright4" }
115+
116+"tag" = { fg = "regular4" }
117+
118+"namespace" = "bright6"
119+
120+"special" = "special"
121+
122+"markup.heading" = { fg = "bright4", modifiers = ["bold"] }
123+"markup.heading.marker" = { fg = "bright2", modifiers = ["bold"] }
27124"markup.heading.1" = { fg = "bright2", modifiers = ["bold"] }
28−"markup.heading.2" = { fg = "bright4", modifiers = ["bold"] }
125+"markup.heading.2" = { fg = "bright5", modifiers = ["bold"] }
29126"markup.heading.3" = { fg = "bright3", modifiers = ["bold"] }
30127"markup.heading.4" = { fg = "bright4", modifiers = ["bold"] }
31128"markup.heading.5" = { fg = "bright4", modifiers = ["bold"] }
@@ -34,90 +131,84 @@
34131"markup.bold" = { fg = "foreground", modifiers = ["bold"] }
35132"markup.italic" = { modifiers = ["italic"] }
36133"markup.strikethrough" = { modifiers = ["crossed_out"] }
37−"markup.link.url" = { fg = "regular4", modifiers = ["underlined"] }
134+"markup.link.url" = { fg = "bright6", underline.style = "line" }
38135"markup.link.text" = "bright2"
39−"markup.link.label" = { fg = "regular7", modifiers = ["bold"] }
40−"markup.raw" = "foreground"
41−
42−"string" = "foreground"
43−"attribute" = "bright7"
44−"keyword" = { fg = "regular4", modifiers = ["bold"]}
45−"keyword.directive" = "regular1"
46−"namespace" = "regular1"
47−"type" = "bright2"
48−"type.builtin" = { fg = "regular4", modifiers = ["bold"]}
49−"variable" = "foreground"
50−"variable.builtin" = "cyan"
51−"variable.other.member" = "regular4"
52−"variable.parameter" = "foreground"
53−
54−"special" = "#3E999F"
55−"function" = "bright1"
56−"constructor" = "bright1"
57−"function.builtin" = { fg = "regular4", modifiers = ["bold"]}
58−"function.macro" = { fg = "regular1" }
59−"comment" = { fg = "bright0", modifiers = ["dim"] }
60−"ui.linenr" = { fg = "bright0" }
61−"module" = "#af0000"
62−"constant" = "#5f8700"
63−"constant.builtin" = "#5f8700"
64−"constant.numeric" = "#d75f00"
65−"constant.character.escape" = { fg = "#8700af", modifiers = ["bold"]}
66−"operator" = { fg = "regular4", modifiers = ["bold"]}
136+"markup.link.label" = { fg = "regular2", modifiers = ["bold"] }
137+"markup.quote" = "regular4"
138+# Both inline and block code
139+"markup.raw" = "regular3"
67140
68−"label" = { fg = "selection_background", modifiers = ["bold", "italic"] }
141+"diff.plus" = { bg = "diffadd_bg", fg = "diffadd_fg" }
142+"diff.delta" = { bg = "diffchange_bg" }
143+"diff.delta.moved" = { modifiers = ["italic"] }
144+"diff.minus" = { bg = "diffdelete_bg", fg = "diffdelete_fg" }
69145
70−"diff.plus" = "regular2"
71−"diff.delta" = "bright0"
72−"diff.minus" = "bright1"
73−
74−"warning" = "bright4"
75−"error" = "regular1"
76−"info" = "#FFAF00"
146+[palette]
147+background = "#eeeeee"
148+foreground = "#444444"
149+regular0 = "#eeeeee" # color00 "Background"
150+regular1 = "#af0000" # color01 "Negative"
151+regular2 = "#008700" # color02 "Positive"
152+regular3 = "#5f8700" # color03 "Olve"
153+regular4 = "#0087af" # color04 "Neutral" / Aqua
154+regular5 = "#878787" # color05 "Comment"
155+regular6 = "#005f87" # color06 "Navy"
156+regular7 = "#444444" # color07 "Foreground"
157+bright0 = "#bcbcbc" # color08 "Nontext"
158+bright1 = "#d70000" # color09 "Red"
159+bright2 = "#d70087" # color10 "Pink"
160+bright3 = "#8700af" # color11 "Purple"
161+bright4 = "#d75f00" # color12 "Accent"
162+bright5 = "#d75f00" # color13 "Orange"
163+bright6 = "#005faf" # color14 "Blue"
164+bright7 = "#005f87" # color15 "Highlight"
77165
78−"diagnostic.warning".underline = { color = "bright4", style = "curl" }
79−"diagnostic.error".underline = { color = "regular1", style = "curl" }
80−"diagnostic.info".underline = { color = "#FFAF00", style = "curl" }
81−"diagnostic.hint".underline = { color = "#FFAF00", style = "curl" }
166+selection_fg = "#eeeeee"
167+selection_bg = "#0087af"
168+selection_secondary_fg = "#d9d7d7"
169+selection_secondary_bg = "#2c687a"
170+special = "#3e999f"
82171
172+cursorline_bg = "#e4e4e4"
173+cursorline_secondary_bg = "#eaeaea"
174+cursorcolumn_bg = "#e4e4e4"
175+cursorcolumn_secondary_bg = "#eaeaea"
176+cursorlinenr_fg = "#af5f00"
177+popupmenu_fg = "#444444"
178+popupmenu_bg = "#d0d0d0"
179+linenumber_fg = "#b2b2b2"
180+vertsplit_fg = "#005f87"
181+statusline_active_fg = "#e4e4e4"
182+statusline_active_bg = "#005f87"
183+statusline_inactive_fg = "#444444"
184+statusline_inactive_bg = "#d0d0d0"
185+todo_fg = "#00af5f"
186+error_fg = "#af0000"
187+error_bg = "#ffd7ff"
188+matchparen_bg = "#c6c6c6"
189+matchparen_fg = "#005f87"
190+wildmenu_fg = "#444444"
191+wildmenu_bg = "#ffff00"
192+diffadd_fg = "#008700"
193+diffadd_bg = "#afffaf"
194+diffdelete_fg = "#af0000"
195+diffdelete_bg = "#ffd7ff"
196+diffchange_bg = "#ffd787"
83197
84−[palette]
85−background="#eeeeee"
86−foreground="#444444"
87−regular0="#eeeeee"
88−regular1="#af0000"
89−regular2="#008700"
90−regular3="#5f8700"
91−regular4="#0087af"
92−regular5="#878787"
93−regular6="#005f87"
94−regular7="#764e37"
95−bright0="#bcbcbc"
96−bright1="#d70000"
97−bright2="#d70087"
98−bright3="#8700af"
99−bright4="#d75f00"
100−bright5="#d75f00"
101−bright6="#4c7a5d"
102−bright7="#005faf"
103−selection_foreground="#eeeeee"
104−selection_background="#0087af"
105−cursorline_background="#fdfdfd"
106−paper_bar_bg="#005F87"
107−black="#eeeeee"
108−red="#d70000"
109−green="#008700"
110−yellow="#5f8700"
111−blue="#0087af"
112−magenta="#878787"
113−cyan="#005f87"
114−gray="#764e37"
115−light-red="#d70000"
116−light-green="#d70087"
117−light-yellow="#8700af"
118−light-blue="#d75f00"
119−light-magenta="#d75f00"
120−light-cyan="#4c7a4d"
121−light-gray="#005faf"
122−white="#444444"
123−linenr_fg_selected="#AF634D"
198+# 16 bit ANSI color names
199+black = "#eeeeee"
200+red = "#d70000"
201+green = "#008700"
202+yellow = "#5f8700"
203+blue = "#0087af"
204+magenta = "#878787"
205+cyan = "#005f87"
206+white = "#444444"
207+light-black = "#bcbcbc"
208+light-red = "#d70000"
209+light-green = "#d70087"
210+light-yellow = "#8700af"
211+light-blue = "#d75f00"
212+light-magenta = "#d75f00"
213+light-cyan = "#4c7a4d"
214+light-white = "#005faf"
runtime/themes/poimandres.tomlnew file+113
@@ -0,0 +1,113 @@
1+# Author: Ambuj Kumar <ambujs89@gmail.com>
2+# Ported from: https://github.com/drcmda/poimandres-theme
3+
4+attribute = { fg = "desaturatedBlue", modifiers = ["italic"] }
5+keyword = "brightMint"
6+"keyword.directive" = "gray"
7+"keyword.storage.type" = "desaturatedBlue"
8+"keyword.storage.modifier" = "lowerMint"
9+"keyword.other" = "brightMint"
10+"keyword.operator" = "desaturatedBlue"
11+namespace = "lightBlue"
12+punctuation = "gray"
13+"punctuation.bracket" = "desaturatedBlue"
14+operator = "desaturatedBlue"
15+special = "desaturatedBlue"
16+variable = "offWhite"
17+"variable.parameter" = { fg = "offWhite" }
18+"variable.builtin" = { fg = "lightBlue", modifiers = ["italic"] }
19+"variable.other" = "offWhite"
20+type = { fg = "gray.c0" }
21+"type.builtin" = { fg = "desaturatedBlue" }
22+constructor = "lightBlue"
23+function = "lightBlue"
24+"function.method" = { fg = "lightBlue" }
25+tag = "brightMint"
26+comment = { fg = "darkerGray.b0", modifiers = ["italic"] }
27+constant = "brightMint"
28+"constant.character.escape" = { fg = "offWhite" }
29+"constant.numeric" = { fg = "brightMint" }
30+"constant.builtin" = { fg = "hotRed" }
31+label = { fg = "gray.c0" }
32+string = { fg = "brightMint" }
33+
34+# Markup
35+"markup.heading" = { fg = "brightMint" }
36+"markup.bold" = { fg = "bluishGrayBrighter", modifiers = ["bold"] }
37+"markup.italic" = { fg = "bluishGrayBrighter", modifiers = ["italic"] }
38+"markup.strikethrough" = { modifiers = ["italic", "crossed_out"] }
39+
40+# UI
41+"markup.link.url" = { fg = "lightBlue", modifiers = ["underlined"] }
42+"markup.link.text" = { fg = "lightBlue", modifiers = ["underlined"] }
43+"markup.raw" = { fg = "lightBlue" }
44+
45+"ui.background" = { bg = "bg" }
46+"ui.background.separator" = { fg = "darkerGray" }
47+"ui.linenr" = "darkerGray.50"
48+"ui.linenr.selected" = "offWhite"
49+"ui.cursor" = { bg = "gray", fg = "bg" }
50+"ui.cursor.match" = { bg = "focus" }
51+"ui.cursorline" = { bg = "#242837" }
52+
53+"ui.popup" = { bg = "#20232d" }
54+"ui.window" = "gray"
55+
56+"ui.text" = "gray"
57+"ui.text.focus" = { fg = "offWhite", bg = "focus", modifiers = ["bold"] }
58+"ui.text.inactive" = "darkerGray"
59+"ui.virtual" = { fg = "darkerGray.b0" }
60+"ui.virtual.indent-guide" = "#303442"
61+
62+"ui.selection" = { bg = "focus" }
63+"ui.selection.primary" = { bg = "selection" }
64+
65+"ui.menu" = { fg = "offWhite", bg = "bg" }
66+"ui.menu.selected" = { fg = "bg", bg = "gray" }
67+"ui.menu.scroll" = { fg = "gray", bg = "bg" }
68+
69+"ui.statusline" = { fg = "offWhite", bg = "selection" }
70+"ui.statusline.inactive" = { fg = "lightBlue", bg = "bg" }
71+"ui.statusline.normal" = { bg = "lightBlue", fg = "bg", modifiers = ["bold"] }
72+"ui.statusline.insert" = { bg = "brightMint", fg = "bg", modifiers = ["bold"] }
73+"ui.statusline.select" = { bg = "hotRed", fg = "bg", modifiers = ["bold"] }
74+
75+"diagnostic.hint" = { underline = { color = "lowerMint", style = "curl" } }
76+"diagnostic.info" = { underline = { color = "lightBlue", style = "curl" } }
77+"diagnostic.warning" = { underline = { color = "brightYellow", style = "curl" } }
78+"diagnostic.error" = { underline = { color = "hotRed", style = "curl" } }
79+
80+hint = "lowerMint"
81+info = "lightBlue"
82+warning = "brightYellow"
83+error = "hotRed"
84+
85+# Version Control
86+"diff.plus" = "lowerMint"
87+"diff.minus" = "hotRed"
88+"diff.delta" = "lightBlue"
89+
90+[palette]
91+brightYellow = "#fffac2"
92+brightMint = "#5DE4c7"
93+lowerMint = "#5fb3a1"
94+blueishGreen = "#42675A"
95+lowerBlue = "#89ddff"
96+lightBlue = "#ADD7FF"
97+desaturatedBlue = "#91B4D5"
98+bluishGrayBrighter = "#7390AA"
99+hotRed = "#d0679d"
100+pink = "#f087bd"
101+gray = "#a6accd"
102+"gray.c0" = "#98a0c2"
103+darkerGray = "#767c9d"
104+"darkerGray.50" = "#404559"
105+"darkerGray.b0" = "#6c7494"
106+bluishGray = "#506477"
107+focus = "#303340"
108+bg = "#1b1e28"
109+offWhite = "#e4f0fb"
110+selection = "#30354a"
111+white = "#ffffff"
112+black = "#000000"
113+transparent = "#00000000"
runtime/themes/poimandres_storm.tomlnew file+19
@@ -0,0 +1,19 @@
1+# Author: Ambuj Kumar <ambujs89@gmail.com>
2+# Ported from: https://github.com/drcmda/poimandres-theme
3+
4+inherits = "poimandres"
5+
6+"ui.cursorline" = { bg = "#303747" }
7+"ui.popup" = { bg = "#2a303c" }
8+"ui.virtual.indent-guide" = "#3a4151"
9+
10+[palette]
11+"gray.c0" = "#98a2c4"
12+darkerGray = "#868cad"
13+"darkerGray.50" = "#4f576d"
14+"darkerGray.b0" = "#818cae"
15+bluishGray = "#607487"
16+focus = "#404350"
17+bg = "#252b37"
18+selection = "#3d455c"
19+black = "#101010"
runtime/themes/rose_pine.toml+31−29
@@ -10,7 +10,7 @@
1010"ui.cursor" = { fg = "text", bg = "highlight_high" }
1111# "ui.cursor.select" = {}
1212"ui.cursor.match" = { fg = "text", bg = "highlight_med" }
13−"ui.cursor.primary" = { fg = "text", bg = "muted"}
13+"ui.cursor.primary" = { fg = "text", bg = "muted" }
1414
1515# "ui.gutter" = {}
1616# "ui.gutter.selected" = {}
@@ -18,6 +18,8 @@
1818"ui.linenr" = { fg = "muted" }
1919"ui.linenr.selected" = { fg = "text" }
2020
21+"ui.bufferline" = { fg = "muted", bg = "base" }
22+"ui.bufferline.active" = { fg = "text", bg = "overlay" }
2123"ui.statusline" = { fg = "subtle", bg = "surface" }
2224"ui.statusline.inactive" = { fg = "muted", bg = "surface" }
2325"ui.statusline.normal" = { fg = "rose", bg = "rose_10" }
@@ -71,8 +73,8 @@
7173"constructor" = "foam"
7274
7375"constant" = "foam"
74−"constant.builtin" = "rose"
75−# "constant.builtin.boolean" = ""
76+"constant.builtin" = "love"
77+"constant.builtin.boolean" = "rose"
7678"constant.character" = "gold"
7779"constant.character.escape" = "pine"
7880"constant.numeric" = "gold"
@@ -86,16 +88,16 @@
8688# "string.special.url" = ""
8789# "string.special.symbol" = ""
8890
89−"comment" = { fg = "muted", modifiers = ["italic"]}
91+"comment" = { fg = "muted", modifiers = ["italic"] }
9092# "comment.line" = ""
9193# "comment.block" = ""
92−# "comment.block.documenation" = ""
94+# "comment.block.documentation" = ""
9395
9496"variable" = "text"
9597"variable.builtin" = "love"
9698"variable.parameter" = "iris"
9799# "variable.other" = ""
98−# "variable.other.member" = ""
100+"variable.other.member" = "foam"
99101
100102"label" = "foam"
101103
@@ -120,7 +122,7 @@
120122
121123"operator" = "subtle"
122124
123−"function" = "rose" # maybe pine
125+"function" = "rose" # maybe pine
124126"function.builtin" = "love"
125127# "function.method" = ""
126128# "function.macro" = ""
@@ -128,7 +130,7 @@
128130
129131"tag" = "foam"
130132
131−"namespace" = "iris"
133+"namespace" = "text"
132134
133135"markup.heading.marker" = "muted"
134136"markup.heading" = { fg = "iris", modifiers = ["bold"] }
@@ -147,7 +149,7 @@
147149"markup.italic" = { modifiers = ["italic"] }
148150"markup.strikethrough" = { modifiers = ["crossed_out"] }
149151"markup.link" = "iris"
150−"markup.link.url" = { fg = "iris", underline = { color = "iris", style = "line" } }
152+"markup.link.url" = { fg = "iris", underline = { color = "iris", style = "line" } }
151153"markup.link.label" = "subtle"
152154"markup.link.text" = "text"
153155"markup.quote" = "subtle"
@@ -167,24 +169,24 @@
167169# "diff.delta.moved" = ""
168170
169171[palette]
170−base = "#191724"
171−surface = "#1f1d2e"
172−overlay = "#26233a"
173−muted = "#6e6a86"
174−subtle = "#908caa"
175−text = "#e0def4"
176−love = "#eb6f92"
177−love_10 = "#311f30"
178−gold = "#f6c177"
179−gold_10 = "#30282c"
180−rose = "#ebbcba"
181−rose_10 = "#2f2834"
182−pine = "#31748f"
183−pine_10 = "#1a2030"
184−foam = "#9ccfd8"
185−foam_10 = "#252937"
186−iris = "#c4a7e7"
187−iris_10 = "#2b2539"
188−highlight_low = "#21202e"
189−highlight_med = "#403d52"
172+base = "#191724"
173+surface = "#1f1d2e"
174+overlay = "#26233a"
175+muted = "#6e6a86"
176+subtle = "#908caa"
177+text = "#e0def4"
178+love = "#eb6f92"
179+love_10 = "#311f30"
180+gold = "#f6c177"
181+gold_10 = "#30282c"
182+rose = "#ebbcba"
183+rose_10 = "#2f2834"
184+pine = "#31748f"
185+pine_10 = "#1a2030"
186+foam = "#9ccfd8"
187+foam_10 = "#252937"
188+iris = "#c4a7e7"
189+iris_10 = "#2b2539"
190+highlight_low = "#21202e"
191+highlight_med = "#403d52"
190192highlight_high = "#524f67"
runtime/themes/starlight.tomlnew file+113
@@ -0,0 +1,113 @@
1+# Author : eemilhaa <eemil.haapanen@gmail.com>
2+# Palette from : https://github.com/CosmicToast/starlight
3+
4+# Syntax
5+"function" = "green"
6+"constructor" = "green"
7+
8+"type" = "cyan"
9+"string.special" = "cyan"
10+"string.regexp" = "cyan"
11+"constant" = "cyan"
12+"punctuation.special" = "cyan"
13+
14+"namespace" = "white"
15+"module" = "white"
16+"variable" = "white"
17+
18+"attribute" = "magenta"
19+"variable.parameter" = "magenta"
20+"variable.other.member" = "magenta"
21+"type.parameter" = "magenta"
22+
23+"keyword" = "blue"
24+"variable.builtin" = "blue"
25+"label" = "blue"
26+"tag" = "blue"
27+"operator" = "blue"
28+"special" = "blue"
29+
30+"string" = "yellow"
31+
32+"punctuation" = "punct"
33+
34+"comment" = "dark-fg"
35+
36+# Markup
37+"markup.heading.marker" = { fg = "blue", modifiers = ["bold"] }
38+"markup.heading" = { fg = "white", modifiers = ["bold"] }
39+"markup.list" = "blue"
40+"markup.bold" = { fg = "magenta", modifiers = ["bold"] }
41+"markup.italic" = { fg = "magenta", modifiers = ["italic"] }
42+"markup.strikethrough" = "red"
43+"markup.link" = "cyan"
44+"markup.link.text" = "yellow"
45+"markup.quote" = "magenta"
46+"markup.raw" = "green"
47+
48+# UI
49+"diff.plus" = "green"
50+"diff.minus" = "red"
51+"diff.delta" = "blue"
52+
53+"ui.background" = { fg = "dark-fg", bg = "dark-bg" }
54+"ui.cursor" = { fg = "black", bg = "light-fg" }
55+"ui.cursor.primary" = { fg = "black", bg = "yellow" }
56+"ui.cursor.match" = { fg = "black", bg = "dark-blue", modifiers = ["bold"] }
57+"ui.linenr" = "dark-fg"
58+"ui.linenr.selected" = "yellow"
59+"ui.statusline" = { fg = "light-fg", bg = "light-bg" }
60+"ui.statusline.inactive" = { fg = "dark-fg", bg = "light-bg" }
61+"ui.statusline.insert" = { fg = "black", bg = "green" }
62+"ui.statusline.select" = { fg = "black", bg = "magenta" }
63+"ui.statusline.normal" = { fg = "black", bg = "blue" }
64+"ui.popup" = { fg = "dark-fg", bg = "light-bg" }
65+"ui.window" = { fg = "light-bg", bg = "dark-bg" }
66+"ui.help" = { fg = "light-fg", bg = "light-bg" }
67+"ui.text" = "light-fg"
68+"ui.text.focus" = { fg = "white", bg = "light-bg", modifiers = ["bold"] }
69+"ui.virtual" = "dark-fg"
70+"ui.virtual.ruler" = { bg = "medium-bg" }
71+"ui.virtual.indent-guide" = "indent"
72+"ui.virtual.whitespace" = "indent"
73+"ui.menu" = { fg = "light-fg", bg = "light-bg" }
74+"ui.menu.selected" = { fg = "white", bg = "dark-fg", modifiers = ["bold"] }
75+"ui.selection" = { fg = "light-fg", bg = "dark-fg" }
76+"ui.selection.primary" = { fg = "white", bg = "dark-blue" }
77+"ui.highlight" = { bg = "light-bg" }
78+"ui.cursorline.primary" = { bg = "black" }
79+"ui.cursorcolumn.primary" = { bg = "black" }
80+"ui.bufferline.background" = { bg = "dark-bg" }
81+"ui.bufferline" = { fg = "light-fg", bg = "light-bg" }
82+"ui.bufferline.active" = { fg = "white", bg = "dark-fg" }
83+
84+"diagnostic.error" = { underline = { color = "red", style = "curl" } }
85+"diagnostic.warning" = { underline = { color = "yellow", style = "curl" } }
86+"diagnostic.info" = { underline = { color = "blue", style = "curl" } }
87+"diagnostic.hint" = { underline = { color = "blue", style = "curl" } }
88+
89+"info" = "blue"
90+"hint" = "blue"
91+"warning" = "yellow"
92+"error" = "red"
93+
94+[palette]
95+# Colors
96+red = "#FF4D51"
97+green = "#35D450"
98+yellow = "#E9E836"
99+blue = "#5DC5F8"
100+dark-blue = "#24ACD4"
101+magenta = "#FEABF2"
102+cyan = "#24DFC4"
103+white = "#ffffff"
104+punct = "#C9C9C9"
105+
106+# Grays
107+black = "#1e1e1e"
108+dark-bg = "#242424"
109+medium-bg = "#2D2D2D"
110+light-bg = "#353535"
111+indent = "#616161"
112+dark-fg = "#929292"
113+light-fg = "#E6E6E6"
runtime/themes/zenburn.toml+1−1
@@ -9,7 +9,7 @@
99"ui.selection" = { bg = "#304a3d" }
1010"ui.selection.primary" = { bg = "#2f2f2f" }
1111"comment" = { fg = "comment" }
12−"ui.virtual.inlay-hint" = { fg = "comment" }
12+"ui.virtual.inlay-hint" = { fg = "#9f9f9f" }
1313"comment.block.documentation" = { fg = "black", modifiers = ["bold"] }
1414"ui.statusline" = { bg = "statusbg", fg = "#ccdc90" }
1515"ui.statusline.inactive" = { fg = '#2e3330', bg = '#88b090' }
runtime/tutor+157−3
@@ -794,11 +794,11 @@ lines.
794794= 7.3 INDENTING LINES =
795795=================================================================
796796
797− Type > to indent a line and < to outdent it.
797+ Type > to indent a line and < to unindent it.
798798
799799 1. Move the cursor to the line marked '-->' below.
800800 2. Move down to the second line and type > to indent it.
801− 3. Move to the third line and type < to outdent it.
801+ 3. Move to the third line and type < to unindent it.
802802
803803 --> These lines
804804 are indented
@@ -842,7 +842,7 @@ lines.
842842
843843 * Type J to join lines in selection.
844844
845− * Type < and > to indent / outdent lines.
845+ * Type > and < to indent / unindent lines.
846846
847847 * Press Ctrl-a to increment the selected number.
848848 * Press Ctrl-x to decrement the selected number.
@@ -1186,6 +1186,160 @@ multiple cursors, they won't be uncommented but commented again.
11861186
11871187
11881188
1189+=================================================================
1190+= 12.1 USING MATCH MODE JUMP =
1191+=================================================================
1192+
1193+To switch to match mode from normal mode, type m. This feature
1194+is particularly useful for handling bracket pairs and their
1195+contents.
1196+
1197+There are several actions that can be performed in match mode,
1198+as indicated by the help pop-up. To jump to a matching bracket pair,
1199+simply press mm. For example on the lines below (starting with
1200+-->), move the cursor in normal mode to (, and then press mm to jump
1201+to the matching ). You can do the same on the line below: for example
1202+move to ], and press mm to jump to [ .
1203+
1204+--> you can (jump between matching parenthesis)
1205+--> or between matching [ square brackets ]
1206+--> now { you know the drill: this works with brackets too }
1207+
1208+
1209+
1210+
1211+=================================================================
1212+= 12.2 USING MATCH MODE SELECT INSIDE =
1213+=================================================================
1214+
1215+Match mode also lets you select the "inside" content between a
1216+pair of brackets or other delimiters. In the lines below:
1217+
1218+- move to the --> line, put your cursor in normal mode at any
1219+location between the parenthesis, for example at 'x', and press
1220+mi( or mi) to select the whole content inside the parenthesis
1221+(parenthesis excluded). As usual, you can then do anything you want
1222+with the selection (for example, press c to change it)
1223+
1224+--> outside and (inside x parenthesis) - and outside again
1225+
1226+Test below that you can do the same with [], or {}, or with
1227+nested combinations of these (this will act on the immediately
1228+surrounding matching pair). This also works with "" and similar
1229+
1230+--> test [ with square brackets ] !
1231+--> try ( with nested [ pairs of ( parenthesis) and "brackets" ])
1232+
1233+=================================================================
1234+= 12.3 USING MATCH MODE SELECT AROUND =
1235+=================================================================
1236+
1237+You can also select the "around" content, i.e. both the inside
1238+content and the delimiters themselves, by using the ma select.
1239+For example, move to the line under, move your cursor in normal
1240+mode to any position between the (), and select the content of
1241+the (), including the surrounding (), by typing ma( or ma). As
1242+usual, you can do anything you want with the selection, for
1243+example delete it all with ma(d .
1244+
1245+--> you ( select x around ) to include delimiters in the select
1246+
1247+This naturally works with other delimiters too:
1248+
1249+--> try [ with 'square' brackets ] too!
1250+
1251+
1252+
1253+
1254+
1255+=================================================================
1256+= 12.4 USING MATCH MODE SURROUND =
1257+=================================================================
1258+
1259+The match mode can also be used to add surrounding around the
1260+current selection. For example, move to the line below, then:
1261+ * i) select the "select all of this" line segment (for example,
1262+move in normal mode the cursor to the start of select, then enter
1263+selection mode with v , then select the 4 next words with 4e ),
1264+ * ii) press ms( or ms) to surround the selection with a pair of
1265+parenthesis.
1266+
1267+--> so, select all of this, and surround it with ()
1268+
1269+You can do the same with other delimiters: for example, ms' on
1270+WORD below to surround it with a pair of ''. You can try also
1271+with adding a surrounding pair of "", or {}, or [].
1272+
1273+--> surround this WORD !
1274+
1275+
1276+
1277+=================================================================
1278+= 12.5 USING MATCH MODE DELETE SURROUND =
1279+=================================================================
1280+
1281+You can delete surrounding pair of delimiters with the md
1282+command. On the line below, move the cursor anywhere
1283+within the pair of (), for example to the 'x', then from there,
1284+in normal mode, press md( or md) to delete the surrounding
1285+pair of parenthesis.
1286+
1287+--> delete (the x pair of parenthesis) from within!
1288+
1289+You can naturally delete other kinds of surroundings:
1290+
1291+--> delete (nested [delimiters]): "this" will delete the nearest
1292+matching surrounding pair.
1293+--> delete "layers "of" quote marks" too: this will delete the
1294+nearest previous and following quote marks
1295+
1296+Trying to delete unexisting surrounding delimiters print an error
1297+at the bottom bar and does nothing.
1298+
1299+=================================================================
1300+= 12.6 USING MATCH MODE REPLACE SURROUND =
1301+=================================================================
1302+
1303+You can replace surrounding pairs of delimiters with the mr
1304+command. On the line below, move the cursor to
1305+anywhere within the pair of (), for example on the 'x', then in
1306+normal mode, press mr([ to replace the pair of () with a pair
1307+of [].
1308+
1309+--> replace the (pair from x within), with something else
1310+
1311+This command will act on the closest enclosing pair, so you
1312+can try replacing different surrounding in the following:
1313+
1314+--> some (nested surroundings [can be replaced])
1315+--> this "works with 'other surroundings' too"
1316+
1317+You can try to replace a non existing pair: this will show
1318+an error warning at the bottom bar and do nothing.
1319+
1320+
1321+=================================================================
1322+= CHAPTER 12 RECAP =
1323+=================================================================
1324+
1325+You can enter the match mode with the m key; this will show the
1326+actions available in a popup. This will allow you to:
1327+ * jump to matching pair of delimiters with mm (you must have a
1328+ delimiter belonging to a pair under your cursor)
1329+ * select inside a pair of delimiters surrounding your cursor
1330+ (i.e. select the content but not the delimiters) with mi(
1331+ and similar
1332+ * select around a pair of delimiters surrounding your cursor
1333+ (i.e. select the content and the delimiters) with ma( and
1334+ similar
1335+ * delete surrounding delimiters with md( and similar
1336+ * add surrounding delimiters around the selection with ms(
1337+ * replace a pair of delimiters surrounding your selection with
1338+ mr([ to replace for example surrounding () with []
1339+
1340+
1341+
1342+
11891343=================================================================
11901344 This tutorial is still a work-in-progress.
11911345 More sections are planned.
rust-toolchain.toml+2−2
@@ -1,3 +1,3 @@
11[toolchain]
2−channel = "1.65.0"
3−components = ["rustfmt", "rust-src"]
2+channel = "1.70.0"
3+components = ["rustfmt", "rust-src", "clippy"]
xtask/Cargo.toml+12−6
@@ -1,13 +1,19 @@
11[package]
22name = "xtask"
3−version = "0.6.0"
4−edition = "2021"
3+version.workspace = true
4+authors.workspace = true
5+edition.workspace = true
6+license.workspace = true
7+rust-version.workspace = true
8+categories.workspace = true
9+repository.workspace = true
10+homepage.workspace = true
511
612# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
713
814[dependencies]
9−helix-term = { version = "0.6", path = "../helix-term" }
10−helix-core = { version = "0.6", path = "../helix-core" }
11−helix-view = { version = "0.6", path = "../helix-view" }
12−helix-loader = { version = "0.6", path = "../helix-loader" }
15+helix-term = { path = "../helix-term" }
16+helix-core = { path = "../helix-core" }
17+helix-view = { path = "../helix-view" }
18+helix-loader = { path = "../helix-loader" }
1319toml = "0.7"