Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--.github/dependabot.yml8
-rw-r--r--.github/workflows/release.yml10
-rw-r--r--Cargo.lock723
-rw-r--r--Cargo.toml6
-rw-r--r--book/src/editor.md40
-rw-r--r--book/src/generated/lang-support.md6
-rw-r--r--book/src/generated/typable-cmd.md8
-rw-r--r--flake.lock12
-rw-r--r--flake.nix11
-rw-r--r--helix-core/Cargo.toml7
-rw-r--r--helix-core/src/file_watcher.rs520
-rw-r--r--helix-core/src/lib.rs1
-rw-r--r--helix-core/src/position.rs9
-rw-r--r--helix-core/src/snippets.rs2
-rw-r--r--helix-core/src/syntax.rs43
-rw-r--r--helix-core/src/transaction.rs1
-rw-r--r--helix-dap/Cargo.toml2
-rw-r--r--helix-dap/src/client.rs6
-rw-r--r--helix-dap/src/lib.rs15
-rw-r--r--helix-dap/src/transport.rs8
-rw-r--r--helix-loader/src/lib.rs2
-rw-r--r--helix-lsp-types/src/code_action.rs24
-rw-r--r--helix-lsp-types/src/completion.rs2
-rw-r--r--helix-lsp-types/src/document_symbols.rs2
-rw-r--r--helix-lsp-types/src/lib.rs55
-rw-r--r--helix-lsp-types/src/semantic_tokens.rs8
-rw-r--r--helix-lsp-types/src/workspace_diagnostic.rs2
-rw-r--r--helix-lsp-types/src/workspace_symbols.rs20
-rw-r--r--helix-lsp/Cargo.toml6
-rw-r--r--helix-lsp/src/client.rs3
-rw-r--r--helix-lsp/src/file_event.rs300
-rw-r--r--helix-lsp/src/lib.rs113
-rw-r--r--helix-lsp/src/transport.rs10
-rw-r--r--helix-term/Cargo.toml15
-rw-r--r--helix-term/src/application.rs15
-rw-r--r--helix-term/src/args.rs1
-rw-r--r--helix-term/src/commands.rs9
-rw-r--r--helix-term/src/commands/typed.rs92
-rw-r--r--helix-term/src/events.rs2
-rw-r--r--helix-term/src/handlers.rs4
-rw-r--r--helix-term/src/handlers/auto_reload.rs117
-rw-r--r--helix-term/src/health.rs4
-rw-r--r--helix-term/src/main.rs3
-rw-r--r--helix-term/src/ui/editor.rs2
-rw-r--r--helix-term/src/ui/picker.rs34
-rw-r--r--helix-term/tests/test/commands/write.rs96
-rw-r--r--helix-vcs/Cargo.toml3
-rw-r--r--helix-vcs/src/git.rs2
-rw-r--r--helix-vcs/src/lib.rs14
-rw-r--r--helix-view/src/document.rs4
-rw-r--r--helix-view/src/editor.rs44
-rw-r--r--helix-view/src/handlers.rs8
-rw-r--r--helix-view/src/handlers/lsp.rs16
-rw-r--r--languages.toml135
-rw-r--r--runtime/queries/_javascript/tags.scm10
-rw-r--r--runtime/queries/bovex/highlights.scm88
-rw-r--r--runtime/queries/bovex/rainbows.scm11
-rw-r--r--runtime/queries/ecma/highlights.scm14
-rw-r--r--runtime/queries/ecma/injections.scm2
-rw-r--r--runtime/queries/ecma/locals.scm6
-rw-r--r--runtime/queries/ecma/textobjects.scm2
-rw-r--r--runtime/queries/jsonc/rainbows.scm1
-rw-r--r--runtime/queries/kcl/highlights.scm57
-rw-r--r--runtime/queries/kdl/highlights.scm14
-rw-r--r--runtime/queries/pest/highlights.scm11
-rw-r--r--runtime/queries/python/highlights.scm3
-rw-r--r--runtime/queries/python/locals.scm3
-rw-r--r--runtime/queries/rust/highlights.scm11
-rw-r--r--runtime/queries/scheme/highlights.scm62
-rw-r--r--runtime/queries/unison/rainbows.scm10
-rw-r--r--runtime/queries/unison/tags.scm10
-rw-r--r--runtime/themes/andromeda.toml186
-rw-r--r--runtime/themes/nord.toml47
-rw-r--r--runtime/themes/ttox_soft.toml37
-rw-r--r--runtime/tutor4
-rw-r--r--rust-toolchain.toml3
76 files changed, 1532 insertions, 1665 deletions
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index d972953e..0e460ebe 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -12,14 +12,6 @@ updates:
update-types:
- "minor"
- "patch"
- ignore:
- # MSRV: these deps use edition 2024 in their newest versions.
- # Once the MSRV reaches 1.85 these can be updated and unignored.
- - dependency-name: ignore
- - dependency-name: globset
- - dependency-name: grep-matcher
- # Now requires Rust 1.87:
- - dependency-name: etcetera
- package-ecosystem: "github-actions"
directory: "/"
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 7331a2dc..4020e505 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -36,7 +36,7 @@ jobs:
- name: Bundle grammars
run: tar cJf grammars.tar.xz -C runtime/grammars/sources .
- - uses: actions/upload-artifact@v5
+ - uses: actions/upload-artifact@v4
with:
name: grammars
path: grammars.tar.xz
@@ -107,7 +107,7 @@ jobs:
uses: actions/checkout@v5
- name: Download grammars
- uses: actions/download-artifact@v6
+ uses: actions/download-artifact@v5
- name: Move grammars under runtime
if: "!startsWith(matrix.os, 'windows')"
@@ -224,7 +224,7 @@ jobs:
fi
cp -r runtime dist
- - uses: actions/upload-artifact@v5
+ - uses: actions/upload-artifact@v4
with:
name: bins-${{ matrix.build }}
path: dist
@@ -237,7 +237,7 @@ jobs:
- name: Checkout sources
uses: actions/checkout@v5
- - uses: actions/download-artifact@v6
+ - uses: actions/download-artifact@v5
- name: Build archive
shell: bash
@@ -294,7 +294,7 @@ jobs:
overwrite: true
- name: Upload binaries as artifact
- uses: actions/upload-artifact@v5
+ uses: actions/upload-artifact@v4
if: env.preview == 'true'
with:
name: release
diff --git a/Cargo.lock b/Cargo.lock
index 257156a2..ae7cf739 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3,19 +3,27 @@
version = 3
[[package]]
-name = "ahash"
-version = "0.8.12"
+name = "addr2line"
+version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
+checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
dependencies = [
- "cfg-if",
- "getrandom 0.3.1",
- "once_cell",
- "version_check",
- "zerocopy",
+ "gimli",
]
[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
+name = "adler2"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
+
+[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -58,10 +66,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]]
+name = "backtrace"
+version = "0.3.73"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a"
+dependencies = [
+ "addr2line",
+ "cc",
+ "cfg-if",
+ "libc",
+ "miniz_oxide 0.7.4",
+ "object",
+ "rustc-demangle",
+]
+
+[[package]]
name = "bitflags"
-version = "2.10.0"
+version = "2.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
+checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394"
[[package]]
name = "block-buffer"
@@ -85,9 +108,9 @@ dependencies = [
[[package]]
name = "bumpalo"
-version = "3.19.0"
+version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
+checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "byteorder"
@@ -97,9 +120,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
-version = "1.10.1"
+version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
+checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50"
[[package]]
name = "cassowary"
@@ -109,9 +132,9 @@ checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
[[package]]
name = "cc"
-version = "1.2.43"
+version = "1.2.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "739eb0f94557554b3ca9a86d2d37bebd49c5e6d0c1d2bda35ba5bdac830befc2"
+checksum = "e1354349954c6fc9cb0deab020f27f783cf0b604e8bb754dc4658ecf0d29c35f"
dependencies = [
"find-msvc-tools",
"shlex",
@@ -186,9 +209,9 @@ dependencies = [
[[package]]
name = "crc32fast"
-version = "1.5.0"
+version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
+checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
dependencies = [
"cfg-if",
]
@@ -269,12 +292,6 @@ dependencies = [
]
[[package]]
-name = "diff"
-version = "0.1.13"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
-
-[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -302,6 +319,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
[[package]]
+name = "ecow"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78e4f79b296fbaab6ce2e22d52cb4c7f010fe0ebe7a32e34fa25885fd797bd02"
+
+[[package]]
name = "either"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -381,24 +404,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6"
[[package]]
-name = "faststr"
-version = "0.2.32"
+name = "fern"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baec6a0289d7f1fe5665586ef7340af82e3037207bef60f5785e57569776f0c8"
+checksum = "4316185f709b23713e41e3195f90edef7fb00c3ed4adc79769cf09cc762a3b29"
dependencies = [
- "bytes",
- "rkyv",
- "serde",
- "simdutf8",
+ "log",
]
[[package]]
-name = "fern"
-version = "0.7.1"
+name = "filesentry"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4316185f709b23713e41e3195f90edef7fb00c3ed4adc79769cf09cc762a3b29"
+checksum = "e78347b6abab87ab712230b933994b5611302f82d64747e681477adcf26dedbd"
dependencies = [
+ "bitflags",
+ "ecow",
+ "hashbrown 0.15.5",
+ "ignore",
"log",
+ "memchr",
+ "mio",
+ "papaya",
+ "rustix 1.1.2",
+ "walkdir",
]
[[package]]
@@ -415,9 +444,20 @@ dependencies = [
[[package]]
name = "find-msvc-tools"
-version = "0.1.4"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127"
+checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959"
+
+[[package]]
+name = "flate2"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
+dependencies = [
+ "crc32fast",
+ "libz-rs-sys",
+ "miniz_oxide 0.8.7",
+]
[[package]]
name = "fnv"
@@ -516,10 +556,16 @@ dependencies = [
]
[[package]]
+name = "gimli"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
+
+[[package]]
name = "gix"
-version = "0.74.1"
+version = "0.73.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5fd3a6fea165debe0e80648495f894aa2371a771e3ceb7a7dcc304f1c4344c43"
+checksum = "514c29cc879bdc0286b0cbc205585a49b252809eb86c69df4ce4f855ee75f635"
dependencies = [
"gix-actor",
"gix-attributes",
@@ -560,15 +606,16 @@ dependencies = [
"gix-utils",
"gix-validate",
"gix-worktree",
+ "once_cell",
"smallvec",
"thiserror",
]
[[package]]
name = "gix-actor"
-version = "0.35.6"
+version = "0.35.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "987a51a7e66db6ef4dc030418eb2a42af6b913a79edd8670766122d8af3ba59e"
+checksum = "58ebbb8f41071c7cf318a0b1db667c34e1df49db7bf387d282a4e61a3b97882c"
dependencies = [
"bstr",
"gix-date",
@@ -580,9 +627,9 @@ dependencies = [
[[package]]
name = "gix-attributes"
-version = "0.28.1"
+version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc6591add69314fc43db078076a8da6f07957c65abb0b21c3e1b6a3cf50aa18d"
+checksum = "45442188216d08a5959af195f659cb1f244a50d7d2d0c3873633b1cd7135f638"
dependencies = [
"bstr",
"gix-glob",
@@ -597,27 +644,27 @@ dependencies = [
[[package]]
name = "gix-bitmap"
-version = "0.2.15"
+version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e150161b8a75b5860521cb876b506879a3376d3adc857ec7a9d35e7c6a5e531"
+checksum = "b1db9765c69502650da68f0804e3dc2b5f8ccc6a2d104ca6c85bc40700d37540"
dependencies = [
"thiserror",
]
[[package]]
name = "gix-chunk"
-version = "0.4.12"
+version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c356b3825677cb6ff579551bb8311a81821e184453cbd105e2fc5311b288eeb"
+checksum = "0b1f1d8764958699dc764e3f727cef280ff4d1bd92c107bbf8acd85b30c1bd6f"
dependencies = [
"thiserror",
]
[[package]]
name = "gix-command"
-version = "0.6.3"
+version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "095c8367c9dc4872a7706fbc39c7f34271b88b541120a4365ff0e36366f66e62"
+checksum = "6b31b65ca48a352ae86312b27a514a0c661935f96b481ac8b4371f65815eb196"
dependencies = [
"bstr",
"gix-path",
@@ -628,9 +675,9 @@ dependencies = [
[[package]]
name = "gix-commitgraph"
-version = "0.30.1"
+version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "826994ff6c01f1ff00d6a1844d7506717810a91ffed143da71e3bf39369751ef"
+checksum = "6bb23121e952f43a5b07e3e80890336cb847297467a410475036242732980d06"
dependencies = [
"bstr",
"gix-chunk",
@@ -641,9 +688,9 @@ dependencies = [
[[package]]
name = "gix-config"
-version = "0.47.1"
+version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e74f57ea99025de9207db53488be4d59cf2000f617964c1b550880524fefbc3"
+checksum = "5dfb898c5b695fd4acfc3c0ab638525a65545d47706064dcf7b5ead6cdb136c0"
dependencies = [
"bstr",
"gix-config-value",
@@ -653,6 +700,7 @@ dependencies = [
"gix-ref",
"gix-sec",
"memchr",
+ "once_cell",
"smallvec",
"thiserror",
"unicode-bom",
@@ -661,9 +709,9 @@ dependencies = [
[[package]]
name = "gix-config-value"
-version = "0.15.3"
+version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c489abb061c74b0c3ad790e24a606ef968cebab48ec673d6a891ece7d5aef64"
+checksum = "9f012703eb67e263c6c1fc96649fec47694dd3e5d2a91abfc65e4a6a6dc85309"
dependencies = [
"bitflags",
"bstr",
@@ -674,9 +722,9 @@ dependencies = [
[[package]]
name = "gix-date"
-version = "0.10.7"
+version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "661245d045aa7c16ba4244daaabd823c562c3e45f1f25b816be2c57ee09f2171"
+checksum = "d7235bdf4d9d54a6901928e3a37f91c16f419e6957f520ed929c3d292b84226e"
dependencies = [
"bstr",
"itoa",
@@ -687,9 +735,9 @@ dependencies = [
[[package]]
name = "gix-diff"
-version = "0.54.1"
+version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd78d9da421baca219a650d71c797706117095635d7963f21bb6fdf2410abe04"
+checksum = "de854852010d44a317f30c92d67a983e691c9478c8a3fb4117c1f48626bcdea8"
dependencies = [
"bstr",
"gix-attributes",
@@ -711,9 +759,9 @@ dependencies = [
[[package]]
name = "gix-dir"
-version = "0.16.0"
+version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f99fb4dcba076453d791949bf3af977c5678a1cbd76740ec2cfe37e29431daf3"
+checksum = "dad34e4f373f94902df1ba1d2a1df3a1b29eacd15e316ac5972d842e31422dd7"
dependencies = [
"bstr",
"gix-discover",
@@ -731,9 +779,9 @@ dependencies = [
[[package]]
name = "gix-discover"
-version = "0.42.0"
+version = "0.41.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d24547153810634636471af88338240e6ab0831308cd41eb6ebfffea77811c6"
+checksum = "ffb180c91ca1a2cf53e828bb63d8d8f8fa7526f49b83b33d7f46cbeb5d79d30a"
dependencies = [
"bstr",
"dunce",
@@ -747,16 +795,16 @@ dependencies = [
[[package]]
name = "gix-features"
-version = "0.44.1"
+version = "0.43.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dfa64593d1586135102307fb57fb3a9d3868b6b1f45a4da1352cce5070f8916a"
+checksum = "9a92748623c201568785ee69a561f4eec06f745b4fac67dab1d44ca9891a57ee"
dependencies = [
"crc32fast",
+ "flate2",
"gix-path",
"gix-trace",
"gix-utils",
"libc",
- "libz-rs-sys",
"once_cell",
"prodash",
"thiserror",
@@ -765,9 +813,9 @@ dependencies = [
[[package]]
name = "gix-filter"
-version = "0.21.0"
+version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d1253452c9808da01eaaf9b1c4929b9982efec29ef0a668b3326b8046d9b8fb"
+checksum = "aa6571a3927e7ab10f64279a088e0dae08e8da05547771796d7389bbe28ad9ff"
dependencies = [
"bstr",
"encoding_rs",
@@ -786,9 +834,9 @@ dependencies = [
[[package]]
name = "gix-fs"
-version = "0.17.0"
+version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f1ecd896258cdc5ccd94d18386d17906b8de265ad2ecf68e3bea6b007f6a28f"
+checksum = "d793f71e955d18f228d20ec433dcce6d0e8577efcdfd11d72d09d7cc2758dfd1"
dependencies = [
"bstr",
"fastrand",
@@ -800,9 +848,9 @@ dependencies = [
[[package]]
name = "gix-glob"
-version = "0.22.1"
+version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74254992150b0a88fdb3ad47635ab649512dff2cbbefca7916bb459894fc9d56"
+checksum = "b947db8366823e7a750c254f6bb29e27e17f27e457bf336ba79b32423db62cd5"
dependencies = [
"bitflags",
"bstr",
@@ -812,9 +860,9 @@ dependencies = [
[[package]]
name = "gix-hash"
-version = "0.20.1"
+version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "826036a9bee95945b0be1e2394c64cd4289916c34a639818f8fd5153906985c1"
+checksum = "251fad79796a731a2a7664d9ea95ee29a9e99474de2769e152238d4fdb69d50e"
dependencies = [
"faster-hex",
"gix-features",
@@ -824,20 +872,20 @@ dependencies = [
[[package]]
name = "gix-hashtable"
-version = "0.10.0"
+version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a27d4a3ea9640da504a2657fef3419c517fd71f1767ad8935298bcc805edd195"
+checksum = "c35300b54896153e55d53f4180460931ccd69b7e8d2f6b9d6401122cdedc4f07"
dependencies = [
"gix-hash",
- "hashbrown 0.16.0",
+ "hashbrown 0.15.5",
"parking_lot",
]
[[package]]
name = "gix-ignore"
-version = "0.17.1"
+version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93b6a9679a1488123b7f2929684bacfd9cd2a24f286b52203b8752cbb8d7fc49"
+checksum = "564d6fddf46e2c981f571b23d6ad40cb08bddcaf6fc7458b1d49727ad23c2870"
dependencies = [
"bstr",
"gix-glob",
@@ -848,9 +896,9 @@ dependencies = [
[[package]]
name = "gix-index"
-version = "0.42.1"
+version = "0.41.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "31244542fb98ea4f3e964a4f8deafc2f4c77ad42bed58a1e8424bca1965fae99"
+checksum = "2af39fde3ce4ce11371d9ce826f2936ec347318f2d1972fe98c2e7134e267e25"
dependencies = [
"bitflags",
"bstr",
@@ -865,7 +913,7 @@ dependencies = [
"gix-traverse",
"gix-utils",
"gix-validate",
- "hashbrown 0.16.0",
+ "hashbrown 0.15.5",
"itoa",
"libc",
"memmap2",
@@ -876,9 +924,9 @@ dependencies = [
[[package]]
name = "gix-lock"
-version = "19.0.0"
+version = "18.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "729d7857429a66023bc0c29d60fa21d0d6ae8862f33c1937ba89e0f74dd5c67f"
+checksum = "b9fa71da90365668a621e184eb5b979904471af1b3b09b943a84bc50e8ad42ed"
dependencies = [
"gix-tempfile",
"gix-utils",
@@ -887,9 +935,9 @@ dependencies = [
[[package]]
name = "gix-object"
-version = "0.51.1"
+version = "0.50.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87ba1815638759c80d2318c8e98296fb396f577c2e588a3d9c13f9a5d5184051"
+checksum = "49664e3e212bc34f7060f5738ce7022247e4afd959b68a4f666b1fd29c00b23c"
dependencies = [
"bstr",
"gix-actor",
@@ -908,9 +956,9 @@ dependencies = [
[[package]]
name = "gix-odb"
-version = "0.71.1"
+version = "0.70.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6efc6736d3ea62640efe8c1be695fb0760af63614a7356d2091208a841f1a634"
+checksum = "9c9d7af10fda9df0bb4f7f9bd507963560b3c66cb15a5b825caf752e0eb109ac"
dependencies = [
"arc-swap",
"gix-date",
@@ -929,9 +977,9 @@ dependencies = [
[[package]]
name = "gix-pack"
-version = "0.61.1"
+version = "0.60.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "719c60524be76874f4769da20d525ad2c00a0e7059943cc4f31fcb65cfb6b260"
+checksum = "d8571df89bfca5abb49c3e3372393f7af7e6f8b8dbe2b96303593cef5b263019"
dependencies = [
"clru",
"gix-chunk",
@@ -947,9 +995,9 @@ dependencies = [
[[package]]
name = "gix-packetline"
-version = "0.19.3"
+version = "0.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64286a8b5148e76ab80932e72762dd27ccf6169dd7a134b027c8a262a8262fcf"
+checksum = "2592fbd36249a2fea11056f7055cc376301ef38d903d157de41998335bbf1f93"
dependencies = [
"bstr",
"faster-hex",
@@ -959,9 +1007,9 @@ dependencies = [
[[package]]
name = "gix-packetline-blocking"
-version = "0.19.3"
+version = "0.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89c59c3ad41e68cb38547d849e9ef5ccfc0d00f282244ba1441ae856be54d001"
+checksum = "fc4e706f328cd494cc8f932172e123a72b9a4711b0db5e411681432a89bd4c94"
dependencies = [
"bstr",
"faster-hex",
@@ -971,22 +1019,23 @@ dependencies = [
[[package]]
name = "gix-path"
-version = "0.10.21"
+version = "0.10.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0416b41cd00ff292af9b94b0660880c44bd2ed66828ddca9a2b333535cbb71b8"
+checksum = "c6279d323d925ad4790602105ae27df4b915e7a7d81e4cdba2603121c03ad111"
dependencies = [
"bstr",
"gix-trace",
"gix-validate",
"home",
+ "once_cell",
"thiserror",
]
[[package]]
name = "gix-pathspec"
-version = "0.13.0"
+version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d05e28457dca7c65a2dbe118869aab922a5bd382b7bb10cff5354f366845c128"
+checksum = "daedead611c9bd1f3640dc90a9012b45f790201788af4d659f28d94071da7fba"
dependencies = [
"bitflags",
"bstr",
@@ -999,9 +1048,9 @@ dependencies = [
[[package]]
name = "gix-protocol"
-version = "0.52.1"
+version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64f19873bbf924fd077580d4ccaaaeddb67c3b3c09a8ffb61e6b4cb67e3c9302"
+checksum = "12b4b807c47ffcf7c1e5b8119585368a56449f3493da93b931e1d4239364e922"
dependencies = [
"bstr",
"gix-date",
@@ -1018,9 +1067,9 @@ dependencies = [
[[package]]
name = "gix-quote"
-version = "0.6.1"
+version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e912ec04b7b1566a85ad486db0cab6b9955e3e32bcd3c3a734542ab3af084c5b"
+checksum = "4a375a75b4d663e8bafe3bf4940a18a23755644c13582fa326e99f8f987d83fd"
dependencies = [
"bstr",
"gix-utils",
@@ -1029,9 +1078,9 @@ dependencies = [
[[package]]
name = "gix-ref"
-version = "0.54.1"
+version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8881d262f28eda39c244e60ae968f4f6e56c747f65addd6f4100b25f75ed8b88"
+checksum = "4b7a23209d4e4cbdc2086d294f5f3f8707ac6286768847024d952d8cd3278c5b"
dependencies = [
"gix-actor",
"gix-features",
@@ -1050,9 +1099,9 @@ dependencies = [
[[package]]
name = "gix-refspec"
-version = "0.32.0"
+version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93147960f77695ba89b72019b789679278dd4dad6a0f9a4a5bf2fd07aba56912"
+checksum = "7d29cae1ae31108826e7156a5e60bffacab405f4413f5bc0375e19772cce0055"
dependencies = [
"bstr",
"gix-hash",
@@ -1064,9 +1113,9 @@ dependencies = [
[[package]]
name = "gix-revision"
-version = "0.36.1"
+version = "0.35.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13c5267e530d8762842be7d51b48d2b134c9dec5b650ca607f735a56a4b12413"
+checksum = "f651f2b1742f760bb8161d6743229206e962b73d9c33c41f4e4aefa6586cbd3d"
dependencies = [
"bstr",
"gix-commitgraph",
@@ -1079,9 +1128,9 @@ dependencies = [
[[package]]
name = "gix-revwalk"
-version = "0.22.0"
+version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02e2de4f91d712b1f6873477f769225fe430ffce2af8c7c85721c3ff955783b3"
+checksum = "06e74f91709729e099af6721bd0fa7d62f243f2005085152301ca5cdd86ec02c"
dependencies = [
"gix-commitgraph",
"gix-date",
@@ -1094,21 +1143,21 @@ dependencies = [
[[package]]
name = "gix-sec"
-version = "0.12.2"
+version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea9962ed6d9114f7f100efe038752f41283c225bb507a2888903ac593dffa6be"
+checksum = "09f7053ed7c66633b56c57bc6ed3377be3166eaf3dc2df9f1c5ec446df6fdf2c"
dependencies = [
"bitflags",
"gix-path",
"libc",
- "windows-sys 0.61.2",
+ "windows-sys 0.59.0",
]
[[package]]
name = "gix-shallow"
-version = "0.6.0"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2374692db1ee1ffa0eddcb9e86ec218f7c4cdceda800ebc5a9fdf73a8c08223"
+checksum = "d936745103243ae4c510f19e0760ce73fb0f08096588fdbe0f0d7fb7ce8944b7"
dependencies = [
"bstr",
"gix-hash",
@@ -1118,9 +1167,9 @@ dependencies = [
[[package]]
name = "gix-status"
-version = "0.21.1"
+version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c64039358f66c955a471432aef0ea1eeebc7afe0e0a4be7b6b737cc19925e3b"
+checksum = "2a4afff9b34eeececa8bdc32b42fb318434b6b1391d9f8d45fe455af08dc2d35"
dependencies = [
"bstr",
"filetime",
@@ -1141,9 +1190,9 @@ dependencies = [
[[package]]
name = "gix-submodule"
-version = "0.21.0"
+version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9bacc06333b50abc4fc06204622c2dd92850de2066bb5d421ac776d2bef7ae55"
+checksum = "657cc5dd43cbc7a14d9c5aaf02cfbe9c2a15d077cded3f304adb30ef78852d3e"
dependencies = [
"bstr",
"gix-config",
@@ -1156,28 +1205,29 @@ dependencies = [
[[package]]
name = "gix-tempfile"
-version = "19.0.1"
+version = "18.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e265fc6b54e57693232a79d84038381ebfda7b1a3b1b8a9320d4d5fe6e820086"
+checksum = "666c0041bcdedf5fa05e9bef663c897debab24b7dc1741605742412d1d47da57"
dependencies = [
"dashmap",
"gix-fs",
"libc",
+ "once_cell",
"parking_lot",
"tempfile",
]
[[package]]
name = "gix-trace"
-version = "0.1.15"
+version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d3f59a8de2934f6391b6b3a1a7654eae18961fcb9f9c843533fed34ad0f3457"
+checksum = "e2ccaf54b0b1743a695b482ca0ab9d7603744d8d10b2e5d1a332fef337bee658"
[[package]]
name = "gix-transport"
-version = "0.49.1"
+version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8da4a77922accb1e26e610c7a84ef7e6b34fd07112e6a84afd68d7f3e795957"
+checksum = "12f7cc0179fc89d53c54e1f9ce51229494864ab4bf136132d69db1b011741ca3"
dependencies = [
"bstr",
"gix-command",
@@ -1191,9 +1241,9 @@ dependencies = [
[[package]]
name = "gix-traverse"
-version = "0.48.0"
+version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "412126bade03a34f5d4125fd64878852718575b3b360eaae3b29970cb555e2a2"
+checksum = "c7cdc82509d792ba0ad815f86f6b469c7afe10f94362e96c4494525a6601bdd5"
dependencies = [
"bitflags",
"gix-commitgraph",
@@ -1208,9 +1258,9 @@ dependencies = [
[[package]]
name = "gix-url"
-version = "0.33.1"
+version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c79b07b48dd9285485eb10429696ddcd1bfe6fb942ec0e5efb401ae7e40238e5"
+checksum = "1b76a9d266254ad287ffd44467cd88e7868799b08f4d52e02d942b93e514d16f"
dependencies = [
"bstr",
"gix-features",
@@ -1222,9 +1272,9 @@ dependencies = [
[[package]]
name = "gix-utils"
-version = "0.3.1"
+version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "befcdbdfb1238d2854591f760a48711bed85e72d80a10e8f2f93f656746ef7c5"
+checksum = "5351af2b172caf41a3728eb4455326d84e0d70fe26fc4de74ab0bd37df4191c5"
dependencies = [
"bstr",
"fastrand",
@@ -1233,9 +1283,9 @@ dependencies = [
[[package]]
name = "gix-validate"
-version = "0.10.1"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b1e63a5b516e970a594f870ed4571a8fdcb8a344e7bd407a20db8bd61dbfde4"
+checksum = "77b9e00cacde5b51388d28ed746c493b18a6add1f19b5e01d686b3b9ece66d4d"
dependencies = [
"bstr",
"thiserror",
@@ -1243,9 +1293,9 @@ dependencies = [
[[package]]
name = "gix-worktree"
-version = "0.43.1"
+version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8df3dfc8b62b0eccc923c757b40f488abc357c85c03d798622edfc3eb5137e04"
+checksum = "55f625ac9126c19bef06dbc6d2703cdd7987e21e35b497bb265ac37d383877b1"
dependencies = [
"bstr",
"gix-attributes",
@@ -1366,11 +1416,14 @@ dependencies = [
"bitflags",
"chrono",
"encoding_rs",
+ "filesentry",
"foldhash 0.2.0",
"globset",
+ "helix-event",
"helix-loader",
"helix-parsec",
"helix-stdx",
+ "ignore",
"imara-diff 0.2.0",
"indoc",
"log",
@@ -1409,7 +1462,6 @@ dependencies = [
"serde",
"serde_json",
"slotmap",
- "sonic-rs",
"thiserror",
"tokio",
"tokio-stream",
@@ -1456,6 +1508,7 @@ dependencies = [
"futures-util",
"globset",
"helix-core",
+ "helix-event",
"helix-loader",
"helix-lsp-types",
"helix-stdx",
@@ -1464,7 +1517,6 @@ dependencies = [
"serde",
"serde_json",
"slotmap",
- "sonic-rs",
"thiserror",
"tokio",
"tokio-stream",
@@ -1499,7 +1551,7 @@ dependencies = [
"tempfile",
"unicode-segmentation",
"which",
- "windows-sys 0.61.2",
+ "windows-sys 0.61.1",
]
[[package]]
@@ -1514,7 +1566,6 @@ dependencies = [
"dashmap",
"fern",
"futures-util",
- "grep-matcher",
"grep-regex",
"grep-searcher",
"helix-core",
@@ -1548,7 +1599,6 @@ dependencies = [
"tokio",
"tokio-stream",
"toml",
- "tree-house",
"url",
]
@@ -1577,6 +1627,7 @@ dependencies = [
"gix",
"helix-core",
"helix-event",
+ "helix-stdx",
"imara-diff 0.2.0",
"log",
"parking_lot",
@@ -1835,9 +1886,9 @@ dependencies = [
[[package]]
name = "indexmap"
-version = "2.12.0"
+version = "2.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f"
+checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5"
dependencies = [
"equivalent",
"hashbrown 0.16.0",
@@ -1845,11 +1896,19 @@ dependencies = [
[[package]]
name = "indoc"
-version = "2.0.7"
+version = "2.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706"
+checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd"
+
+[[package]]
+name = "io-uring"
+version = "0.7.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013"
dependencies = [
- "rustversion",
+ "bitflags",
+ "cfg-if",
+ "libc",
]
[[package]]
@@ -1920,11 +1979,10 @@ dependencies = [
[[package]]
name = "js-sys"
-version = "0.3.80"
+version = "0.3.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "852f13bec5eba4ba9afbeb93fd7c13fe56147f055939ae21c43a29a0ecb2702e"
+checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a"
dependencies = [
- "once_cell",
"wasm-bindgen",
]
@@ -1939,9 +1997,9 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.177"
+version = "0.2.176"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
+checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174"
[[package]]
name = "libloading"
@@ -1966,9 +2024,9 @@ dependencies = [
[[package]]
name = "libz-rs-sys"
-version = "0.5.2"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "840db8cf39d9ec4dd794376f38acc40d0fc65eec2a8f484f7fd375b84602becd"
+checksum = "6489ca9bd760fe9642d7644e827b0c9add07df89857b0416ee15c1cc1a3b8c5a"
dependencies = [
"zlib-rs",
]
@@ -1993,10 +2051,11 @@ checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704"
[[package]]
name = "lock_api"
-version = "0.4.14"
+version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
+checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765"
dependencies = [
+ "autocfg",
"scopeguard",
]
@@ -2019,50 +2078,47 @@ dependencies = [
[[package]]
name = "memchr"
-version = "2.7.4"
+version = "2.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
[[package]]
name = "memmap2"
-version = "0.9.9"
+version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490"
+checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322"
dependencies = [
"libc",
]
[[package]]
-name = "mio"
-version = "1.0.2"
+name = "miniz_oxide"
+version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"
+checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
dependencies = [
- "hermit-abi",
- "libc",
- "log",
- "wasi 0.11.0+wasi-snapshot-preview1",
- "windows-sys 0.52.0",
+ "adler",
]
[[package]]
-name = "munge"
-version = "0.4.6"
+name = "miniz_oxide"
+version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d7feb0b48aa0a25f9fe0899482c6e1379ee7a11b24a53073eacdecb9adb6dc60"
+checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430"
dependencies = [
- "munge_macro",
+ "adler2",
]
[[package]]
-name = "munge_macro"
-version = "0.4.6"
+name = "mio"
+version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2e3795a5d2da581a8b252fec6022eee01aea10161a4d1bf237d4cbe47f7e988"
+checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c"
dependencies = [
- "proc-macro2",
- "quote",
- "syn",
+ "libc",
+ "log",
+ "wasi 0.11.0+wasi-snapshot-preview1",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -2106,6 +2162,15 @@ dependencies = [
]
[[package]]
+name = "object"
+version = "0.36.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2123,10 +2188,20 @@ dependencies = [
]
[[package]]
+name = "papaya"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f92dd0b07c53a0a0c764db2ace8c541dc47320dad97c2200c2a637ab9dd2328f"
+dependencies = [
+ "equivalent",
+ "seize",
+]
+
+[[package]]
name = "parking_lot"
-version = "0.12.5"
+version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
+checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13"
dependencies = [
"lock_api",
"parking_lot_core",
@@ -2134,15 +2209,15 @@ dependencies = [
[[package]]
name = "parking_lot_core"
-version = "0.9.12"
+version = "0.9.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
+checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
- "windows-link",
+ "windows-targets 0.52.6",
]
[[package]]
@@ -2185,16 +2260,6 @@ dependencies = [
]
[[package]]
-name = "pretty_assertions"
-version = "1.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d"
-dependencies = [
- "diff",
- "yansi",
-]
-
-[[package]]
name = "proc-macro2"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2213,26 +2278,6 @@ dependencies = [
]
[[package]]
-name = "ptr_meta"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe9e76f66d3f9606f44e45598d155cb13ecf09f4a28199e48daf8c8fc937ea90"
-dependencies = [
- "ptr_meta_derive",
-]
-
-[[package]]
-name = "ptr_meta_derive"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca414edb151b4c8d125c12566ab0d74dc9cdba36fb80eb7b848c15f495fd32d1"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
name = "pulldown-cmark"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2262,15 +2307,6 @@ dependencies = [
]
[[package]]
-name = "rancor"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "caf5f7161924b9d1cea0e4cabc97c372cea92b5f927fc13c6bca67157a0ad947"
-dependencies = [
- "ptr_meta",
-]
-
-[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2318,30 +2354,10 @@ dependencies = [
]
[[package]]
-name = "ref-cast"
-version = "1.0.24"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf"
-dependencies = [
- "ref-cast-impl",
-]
-
-[[package]]
-name = "ref-cast-impl"
-version = "1.0.24"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
name = "regex"
-version = "1.12.2"
+version = "1.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4"
+checksum = "8b5288124840bee7b386bc413c487869b360b2b4ec421ea56425128692f2a82c"
dependencies = [
"aho-corasick",
"memchr",
@@ -2351,9 +2367,9 @@ dependencies = [
[[package]]
name = "regex-automata"
-version = "0.4.13"
+version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c"
+checksum = "833eb9ce86d40ef33cb1306d8accf7bc8ec2bfea4355cbdebb3df68b40925cad"
dependencies = [
"aho-corasick",
"memchr",
@@ -2380,41 +2396,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
-name = "rend"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a35e8a6bf28cd121053a66aa2e6a2e3eaffad4a60012179f0e864aa5ffeff215"
-
-[[package]]
-name = "rkyv"
-version = "0.8.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19f5c3e5da784cd8c69d32cdc84673f3204536ca56e1fa01be31a74b92c932ac"
-dependencies = [
- "bytes",
- "hashbrown 0.15.5",
- "indexmap",
- "munge",
- "ptr_meta",
- "rancor",
- "rend",
- "rkyv_derive",
- "tinyvec",
- "uuid",
-]
-
-[[package]]
-name = "rkyv_derive"
-version = "0.8.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4270433626cffc9c4c1d3707dd681f2a2718d3d7b09ad754bec137acecda8d22"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
name = "ropey"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2425,6 +2406,12 @@ dependencies = [
]
[[package]]
+name = "rustc-demangle"
+version = "0.1.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
+
+[[package]]
name = "rustix"
version = "0.38.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2447,16 +2434,10 @@ dependencies = [
"errno",
"libc",
"linux-raw-sys 0.11.0",
- "windows-sys 0.61.2",
+ "windows-sys 0.61.1",
]
[[package]]
-name = "rustversion"
-version = "1.0.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
-
-[[package]]
name = "ryu"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2478,6 +2459,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
+name = "seize"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b55fb86dfd3a2f5f76ea78310a88f96c4ea21a3031f8d212443d56123fd0521"
+dependencies = [
+ "libc",
+ "windows-sys 0.61.1",
+]
+
+[[package]]
name = "serde"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2522,9 +2513,9 @@ dependencies = [
[[package]]
name = "serde_spanned"
-version = "1.0.3"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e24345aa0fe688594e73770a5f6d1b216508b4f93484c0026d521acd30134392"
+checksum = "2789234a13a53fc4be1b51ea1bab45a3c338bdb884862a257d10e5a74ae009e6"
dependencies = [
"serde_core",
]
@@ -2605,12 +2596,6 @@ dependencies = [
]
[[package]]
-name = "simdutf8"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
-
-[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2662,45 +2647,6 @@ dependencies = [
]
[[package]]
-name = "sonic-number"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8a74044c092f4f43ca7a6cfd62854cf9fb5ac8502b131347c990bf22bef1dfe"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
-name = "sonic-rs"
-version = "0.5.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22540d56ba14521e4878ad436d498518c59698c39a89d5905c694932f0bf7134"
-dependencies = [
- "ahash",
- "bumpalo",
- "bytes",
- "cfg-if",
- "faststr",
- "itoa",
- "ref-cast",
- "ryu",
- "serde",
- "simdutf8",
- "sonic-number",
- "sonic-simd",
- "thiserror",
-]
-
-[[package]]
-name = "sonic-simd"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b421f7b6aa4a5de8f685aaf398dfaa828346ee639d2b1c1061ab43d40baa6223"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2750,7 +2696,7 @@ dependencies = [
"getrandom 0.3.1",
"once_cell",
"rustix 1.1.2",
- "windows-sys 0.61.2",
+ "windows-sys 0.61.1",
]
[[package]]
@@ -2764,7 +2710,7 @@ dependencies = [
"parking_lot",
"rustix 1.1.2",
"signal-hook",
- "windows-sys 0.61.2",
+ "windows-sys 0.61.1",
]
[[package]]
@@ -2843,26 +2789,29 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
-version = "1.48.0"
+version = "1.47.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408"
+checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038"
dependencies = [
+ "backtrace",
"bytes",
+ "io-uring",
"libc",
"mio",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
+ "slab",
"socket2",
"tokio-macros",
- "windows-sys 0.61.2",
+ "windows-sys 0.59.0",
]
[[package]]
name = "tokio-macros"
-version = "2.6.0"
+version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
+checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
dependencies = [
"proc-macro2",
"quote",
@@ -2882,9 +2831,9 @@ dependencies = [
[[package]]
name = "toml"
-version = "0.9.8"
+version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0dc8b1fb61449e27716ec0e1bdf0f6b8f3e8f6b05391e8497b8b6d7804ea6d8"
+checksum = "ae2a4cf385da23d1d53bc15cdfa5c2109e93d8d362393c801e87da2f72f0e201"
dependencies = [
"indexmap",
"serde_core",
@@ -2897,27 +2846,27 @@ dependencies = [
[[package]]
name = "toml_datetime"
-version = "0.7.3"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f2cdb639ebbc97961c51720f858597f7f24c4fc295327923af55b74c3c724533"
+checksum = "a197c0ec7d131bfc6f7e82c8442ba1595aeab35da7adbf05b6b73cd06a16b6be"
dependencies = [
"serde_core",
]
[[package]]
name = "toml_parser"
-version = "1.0.4"
+version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0cbe268d35bdb4bb5a56a2de88d0ad0eb70af5384a99d648cd4b3d04039800e"
+checksum = "b551886f449aa90d4fe2bdaa9f4a2577ad2dde302c61ecf262d80b116db95c10"
dependencies = [
"winnow",
]
[[package]]
name = "toml_writer"
-version = "1.0.4"
+version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2"
+checksum = "fcc842091f2def52017664b53082ecbbeb5c7731092bad69d2c63050401dfd64"
[[package]]
name = "tree-house"
@@ -2929,13 +2878,11 @@ dependencies = [
"hashbrown 0.15.5",
"kstring",
"once_cell",
- "pretty_assertions",
"regex",
"regex-cursor",
"ropey",
"slab",
"tree-house-bindings",
- "unicode-width 0.1.12",
]
[[package]]
@@ -3042,16 +2989,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
[[package]]
-name = "uuid"
-version = "1.18.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2"
-dependencies = [
- "js-sys",
- "wasm-bindgen",
-]
-
-[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3084,25 +3021,24 @@ dependencies = [
[[package]]
name = "wasm-bindgen"
-version = "0.2.103"
+version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab10a69fbd0a177f5f649ad4d8d3305499c42bab9aef2f7ff592d0ec8f833819"
+checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5"
dependencies = [
"cfg-if",
"once_cell",
- "rustversion",
"wasm-bindgen-macro",
- "wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-backend"
-version = "0.2.103"
+version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bb702423545a6007bbc368fde243ba47ca275e549c8a28617f56f6ba53b1d1c"
+checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b"
dependencies = [
"bumpalo",
"log",
+ "once_cell",
"proc-macro2",
"quote",
"syn",
@@ -3111,9 +3047,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.103"
+version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc65f4f411d91494355917b605e1480033152658d71f722a90647f56a70c88a0"
+checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -3121,9 +3057,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.103"
+version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ffc003a991398a8ee604a401e194b6b3a39677b3173d6e74495eb51b82e99a32"
+checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836"
dependencies = [
"proc-macro2",
"quote",
@@ -3134,12 +3070,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.103"
+version = "0.2.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "293c37f4efa430ca14db3721dfbe48d8c33308096bd44d80ebaa775ab71ba1cf"
-dependencies = [
- "unicode-ident",
-]
+checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484"
[[package]]
name = "which"
@@ -3194,9 +3127,9 @@ dependencies = [
[[package]]
name = "windows-link"
-version = "0.2.1"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
+checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65"
[[package]]
name = "windows-sys"
@@ -3218,9 +3151,9 @@ dependencies = [
[[package]]
name = "windows-sys"
-version = "0.61.2"
+version = "0.61.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
+checksum = "6f109e41dd4a3c848907eb83d5a42ea98b3769495597450cf6d153507b166f0f"
dependencies = [
"windows-link",
]
@@ -3355,9 +3288,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
[[package]]
name = "winnow"
-version = "0.7.13"
+version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf"
+checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec"
dependencies = [
"memchr",
]
@@ -3401,12 +3334,6 @@ dependencies = [
]
[[package]]
-name = "yansi"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
-
-[[package]]
name = "yoke"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3431,26 +3358,6 @@ dependencies = [
]
[[package]]
-name = "zerocopy"
-version = "0.8.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
-dependencies = [
- "zerocopy-derive",
-]
-
-[[package]]
-name = "zerocopy-derive"
-version = "0.8.27"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
name = "zerofrom"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3495,6 +3402,6 @@ dependencies = [
[[package]]
name = "zlib-rs"
-version = "0.5.2"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f06ae92f42f5e5c42443fd094f245eb656abf56dd7cce9b8b263236565e00f2"
+checksum = "868b928d7949e09af2f6086dfc1e01936064cc7a819253bce650d4e2a2d63ba8"
diff --git a/Cargo.toml b/Cargo.toml
index 90542831..e6ace7de 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -42,7 +42,7 @@ nucleo = "0.5.0"
slotmap = "1.0.7"
thiserror = "2.0"
tempfile = "3.23.0"
-bitflags = "2.10"
+bitflags = "2.9"
unicode-segmentation = "1.2"
ropey = { version = "1.6.1", default-features = false, features = ["simd"] }
foldhash = "0.2"
@@ -52,9 +52,7 @@ futures-util = { version = "0.3", features = ["std", "async-await"], default-fea
tokio-stream = "0.1.17"
toml = "0.9"
termina = "0.1"
-sonic-rs = "0.5"
-# MSRV: update once the MSRV is >=1.85
-globset = "=0.4.16"
+ignore = "0.4"
[workspace.package]
version = "25.7.1"
diff --git a/book/src/editor.md b/book/src/editor.md
index 92e21f9c..101ace15 100644
--- a/book/src/editor.md
+++ b/book/src/editor.md
@@ -27,11 +27,11 @@
|--|--|---------|
| `scrolloff` | Number of lines of padding around the edge of the screen when scrolling | `5` |
| `mouse` | Enable mouse mode | `true` |
-| `default-yank-register` | Default register used for yank/paste | `'"'` |
+| `default-yank-register` | Default register used for yank/paste | `"` |
| `middle-click-paste` | Middle click paste support | `true` |
| `scroll-lines` | Number of lines to scroll per scroll wheel step | `3` |
| `shell` | Shell to use when running external commands | Unix: `["sh", "-c"]`<br/>Windows: `["cmd", "/C"]` |
-| `line-number` | Line number display: `absolute` simply shows each line's number, while `relative` shows the distance from the current line. When unfocused or in insert mode, `relative` will still show absolute line numbers | `"absolute"` |
+| `line-number` | Line number display: `absolute` simply shows each line's number, while `relative` shows the distance from the current line. When unfocused or in insert mode, `relative` will still show absolute line numbers | `absolute` |
| `cursorline` | Highlight all lines with a cursor | `false` |
| `cursorcolumn` | Highlight all columns with a cursor | `false` |
| `continue-comments` | if helix should automatically add a line comment token if you create a new line inside a comment. | `true` |
@@ -43,28 +43,28 @@
| `completion-timeout` | Time in milliseconds after typing a word character before completions are shown, set to 5 for instant. | `250` |
| `preview-completion-insert` | Whether to apply completion item instantly when selected | `true` |
| `completion-trigger-len` | The min-length of word under cursor to trigger autocompletion | `2` |
-| `completion-replace` | Whether to make completions always replace the entire word and not just the part before the cursor | `false` |
+| `completion-replace` | Set to `true` to make completions always replace the entire word and not just the part before the cursor | `false` |
| `auto-info` | Whether to display info boxes | `true` |
-| `true-color` | Whether to override automatic detection of terminal truecolor support in the event of a false negative | `false` |
-| `undercurl` | Whether to override automatic detection of terminal undercurl support in the event of a false negative | `false` |
+| `true-color` | Set to `true` to override automatic detection of terminal truecolor support in the event of a false negative | `false` |
+| `undercurl` | Set to `true` to override automatic detection of terminal undercurl support in the event of a false negative | `false` |
| `rulers` | List of column positions at which to display the rulers. Can be overridden by language specific `rulers` in `languages.toml` file | `[]` |
-| `bufferline` | Renders a line at the top of the editor displaying open buffers. Can be `always`, `never` or `multiple` (only shown if more than one buffer is in use) | `"never"` |
+| `bufferline` | Renders a line at the top of the editor displaying open buffers. Can be `always`, `never` or `multiple` (only shown if more than one buffer is in use) | `never` |
| `color-modes` | Whether to color the mode indicator with different colors depending on the mode itself | `false` |
| `text-width` | Maximum line length. Used for the `:reflow` command and soft-wrapping if `soft-wrap.wrap-at-text-width` is set | `80` |
| `workspace-lsp-roots` | Directories relative to the workspace root that are treated as LSP roots. Should only be set in `.helix/config.toml` | `[]` |
-| `default-line-ending` | The line ending to use for new documents. Can be `native`, `lf`, `crlf`, `ff`, `cr` or `nel`. `native` uses the platform's native line ending (`crlf` on Windows, otherwise `lf`). | `"native"` |
+| `default-line-ending` | The line ending to use for new documents. Can be `native`, `lf`, `crlf`, `ff`, `cr` or `nel`. `native` uses the platform's native line ending (`crlf` on Windows, otherwise `lf`). | `native` |
| `insert-final-newline` | Whether to automatically insert a trailing line-ending on write if missing | `true` |
| `atomic-save` | Whether to use atomic operations to write documents to disk. This prevents data loss if the editor is interrupted while writing the file, but may confuse some file watching/hot reloading programs. | `true` |
| `trim-final-newlines` | Whether to automatically remove line-endings after the final one on write | `false` |
| `trim-trailing-whitespace` | Whether to automatically remove whitespace preceding line endings on write | `false` |
-| `popup-border` | Draw border around `popup`, `menu`, `all`, or `none` | `"none"` |
-| `indent-heuristic` | How the indentation for a newly inserted line is computed: `simple` just copies the indentation level from the previous line, `tree-sitter` computes the indentation based on the syntax tree and `hybrid` combines both approaches. If the chosen heuristic is not available, a different one will be used as a fallback (the fallback order being `hybrid` -> `tree-sitter` -> `simple`). | `"hybrid"` |
-| `jump-label-alphabet` | The characters that are used to generate two character jump labels. Characters at the start of the alphabet are used first. | `"abcdefghijklmnopqrstuvwxyz"` |
-| `end-of-line-diagnostics` | Minimum severity of diagnostics to render at the end of the line. Set to `disable` to disable entirely. Refer to the setting about `inline-diagnostics` for more details | `"hint"` |
+| `popup-border` | Draw border around `popup`, `menu`, `all`, or `none` | `none` |
+| `indent-heuristic` | How the indentation for a newly inserted line is computed: `simple` just copies the indentation level from the previous line, `tree-sitter` computes the indentation based on the syntax tree and `hybrid` combines both approaches. If the chosen heuristic is not available, a different one will be used as a fallback (the fallback order being `hybrid` -> `tree-sitter` -> `simple`). | `hybrid`
+| `jump-label-alphabet` | The characters that are used to generate two character jump labels. Characters at the start of the alphabet are used first. | `"abcdefghijklmnopqrstuvwxyz"`
+| `end-of-line-diagnostics` | Minimum severity of diagnostics to render at the end of the line. Set to `disable` to disable entirely. Refer to the setting about `inline-diagnostics` for more details | `"hint"`
| `clipboard-provider` | Which API to use for clipboard interaction. One of `pasteboard` (MacOS), `wayland`, `x-clip`, `x-sel`, `win32-yank`, `termux`, `tmux`, `windows`, `termcode`, `none`, or a custom command set. | Platform and environment specific. |
| `editor-config` | Whether to read settings from [EditorConfig](https://editorconfig.org) files | `true` |
| `rainbow-brackets` | Whether to render rainbow colors for matching brackets. Requires tree-sitter `rainbows.scm` queries for the language. | `false` |
-| `kitty-keyboard-protocol` | Whether to enable Kitty Keyboard Protocol. Can be `enabled`, `disabled` or `auto` | `"auto"` |
+| `kitty-keyboard-protocol` | Whether to enable Kitty Keyboard Protocol. Can be `enabled`, `disabled` or `auto` | `auto` |
### `[editor.clipboard-provider]` Section
@@ -180,11 +180,11 @@ Valid values for these options are `block`, `bar`, `underline`, or `hidden`.
> 💡 Due to limitations of the terminal environment, only the primary cursor can
> change shape.
-| Key | Description | Default |
-| --- | ----------- | ------- |
-| `normal` | Cursor shape in [normal mode][normal mode] | `"block"` |
-| `insert` | Cursor shape in [insert mode][insert mode] | `"block"` |
-| `select` | Cursor shape in [select mode][select mode] | `"block"` |
+| Key | Description | Default |
+| --- | ----------- | ------- |
+| `normal` | Cursor shape in [normal mode][normal mode] | `block` |
+| `insert` | Cursor shape in [insert mode][insert mode] | `block` |
+| `select` | Cursor shape in [select mode][select mode] | `block` |
[normal mode]: ./keymap.md#normal-mode
[insert mode]: ./keymap.md#insert-mode
@@ -312,7 +312,7 @@ Options for rendering whitespace with visible characters. Use `:set whitespace.r
| Key | Description | Default |
|-----|-------------|---------|
-| `render` | Whether to render whitespace. May either be `all` or `none`, or a table with sub-keys `space`, `nbsp`, `nnbsp`, `tab`, and `newline` | `"none"` |
+| `render` | Whether to render whitespace. May either be `all` or `none`, or a table with sub-keys `space`, `nbsp`, `nnbsp`, `tab`, and `newline` | `none` |
| `characters` | Literal characters to use when rendering whitespace. Sub-keys may be any of `tab`, `space`, `nbsp`, `nnbsp`, `newline` or `tabpad` | See example below |
Example
@@ -344,7 +344,7 @@ Options for rendering vertical indent guides.
| Key | Description | Default |
| --- | --- | --- |
| `render` | Whether to render indent guides | `false` |
-| `character` | Literal character to use for rendering the indent guide | `"│"` |
+| `character` | Literal character to use for rendering the indent guide | `│` |
| `skip-levels` | Number of indent levels to skip | `0` |
Example:
@@ -422,7 +422,7 @@ Options for soft wrapping lines that exceed the view width:
| `enable` | Whether soft wrapping is enabled. | `false` |
| `max-wrap` | Maximum free space left at the end of the line. | `20` |
| `max-indent-retain` | Maximum indentation to carry over when soft wrapping a line. | `40` |
-| `wrap-indicator` | Text inserted before soft wrapped lines, highlighted with `ui.virtual.wrap` | `"↪ "` |
+| `wrap-indicator` | Text inserted before soft wrapped lines, highlighted with `ui.virtual.wrap` | `↪ ` |
| `wrap-at-text-width` | Soft wrap at `text-width` instead of using the full viewport size. | `false` |
Example:
diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md
index f753541a..67cd39c1 100644
--- a/book/src/generated/lang-support.md
+++ b/book/src/generated/lang-support.md
@@ -15,7 +15,6 @@
| bitbake | ✓ | | | | | `bitbake-language-server` |
| blade | ✓ | ✓ | | | ✓ | |
| blueprint | ✓ | | | | | `blueprint-compiler` |
-| bovex | ✓ | | | | ✓ | |
| c | ✓ | ✓ | ✓ | ✓ | ✓ | `clangd` |
| c-sharp | ✓ | ✓ | | ✓ | | `OmniSharp` |
| cabal | | | | | | `haskell-language-server-wrapper` |
@@ -137,12 +136,11 @@
| json | ✓ | ✓ | ✓ | | ✓ | `vscode-json-language-server` |
| json-ld | ✓ | ✓ | ✓ | | | `vscode-json-language-server` |
| json5 | ✓ | | | | | |
-| jsonc | ✓ | | ✓ | | ✓ | `vscode-json-language-server` |
+| jsonc | ✓ | | ✓ | | | `vscode-json-language-server` |
| jsonnet | ✓ | | | | | `jsonnet-language-server` |
| jsx | ✓ | ✓ | ✓ | ✓ | ✓ | `typescript-language-server` |
| julia | ✓ | ✓ | ✓ | | | `julia` |
| just | ✓ | ✓ | ✓ | ✓ | | `just-lsp` |
-| kcl | ✓ | | | | | `kcl-language-server` |
| kconfig | ✓ | | ✓ | | | |
| kdl | ✓ | ✓ | ✓ | ✓ | | |
| koka | ✓ | | ✓ | | | `koka` |
@@ -278,7 +276,7 @@
| typespec | ✓ | ✓ | ✓ | | | `tsp-server` |
| typst | ✓ | | | ✓ | | `tinymist` |
| ungrammar | ✓ | | | | | |
-| unison | ✓ | ✓ | ✓ | ✓ | ✓ | |
+| unison | ✓ | ✓ | ✓ | | | |
| uxntal | ✓ | | | | | |
| v | ✓ | ✓ | ✓ | | | `v-analyzer` |
| vala | ✓ | ✓ | | | | `vala-language-server` |
diff --git a/book/src/generated/typable-cmd.md b/book/src/generated/typable-cmd.md
index 3d2ce4e3..e416e813 100644
--- a/book/src/generated/typable-cmd.md
+++ b/book/src/generated/typable-cmd.md
@@ -1,7 +1,5 @@
| Name | Description |
| --- | --- |
-| `:exit`, `:x`, `:xit` | Write changes to disk if the buffer is modified and then quit. Accepts an optional path (:exit some/path.txt). |
-| `:exit!`, `:x!`, `:xit!` | Force write changes to disk, creating necessary subdirectories, if the buffer is modified and then quit. Accepts an optional path (:exit! some/path.txt). |
| `:quit`, `:q` | Close the current view. |
| `:quit!`, `:q!` | Force close the current view, ignoring unsaved changes. |
| `:open`, `:o`, `:edit`, `:e` | Open a file from disk into the current view. |
@@ -23,12 +21,12 @@
| `:line-ending` | Set the document's default line ending. Options: crlf, lf. |
| `:earlier`, `:ear` | Jump back to an earlier point in edit history. Accepts a number of steps or a time span. |
| `:later`, `:lat` | Jump to a later point in edit history. Accepts a number of steps or a time span. |
-| `:write-quit`, `:wq` | Write changes to disk and close the current view. Accepts an optional path (:wq some/path.txt) |
-| `:write-quit!`, `:wq!` | Write changes to disk and close the current view forcefully. Accepts an optional path (:wq! some/path.txt) |
+| `:write-quit`, `:wq`, `:x` | Write changes to disk and close the current view. Accepts an optional path (:wq some/path.txt) |
+| `:write-quit!`, `:wq!`, `:x!` | Write changes to disk and close the current view forcefully. Accepts an optional path (:wq! some/path.txt) |
| `:write-all`, `:wa` | Write changes from all buffers to disk. |
| `:write-all!`, `:wa!` | Forcefully write changes from all buffers to disk creating necessary subdirectories. |
| `:write-quit-all`, `:wqa`, `:xa` | Write changes from all buffers to disk and close all views. |
-| `:write-quit-all!`, `:wqa!`, `:xa!` | Forcefully write changes from all buffers to disk, creating necessary subdirectories, and close all views (ignoring unsaved changes). |
+| `:write-quit-all!`, `:wqa!`, `:xa!` | Write changes from all buffers to disk and close all views forcefully (ignoring unsaved changes). |
| `:quit-all`, `:qa` | Close all views. |
| `:quit-all!`, `:qa!` | Force close all views ignoring unsaved changes. |
| `:cquit`, `:cq` | Quit with exit code (default 1). Accepts an optional integer exit code (:cq 2). |
diff --git a/flake.lock b/flake.lock
index 867f2830..6490b760 100644
--- a/flake.lock
+++ b/flake.lock
@@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
- "lastModified": 1759381078,
- "narHash": "sha256-gTrEEp5gEspIcCOx9PD8kMaF1iEmfBcTbO0Jag2QhQs=",
+ "lastModified": 1740560979,
+ "narHash": "sha256-Vr3Qi346M+8CjedtbyUevIGDZW8LcA1fTG0ugPY/Hic=",
"owner": "nixos",
"repo": "nixpkgs",
- "rev": "7df7ff7d8e00218376575f0acdcc5d66741351ee",
+ "rev": "5135c59491985879812717f4c9fea69604e7f26f",
"type": "github"
},
"original": {
@@ -29,11 +29,11 @@
]
},
"locked": {
- "lastModified": 1759631821,
- "narHash": "sha256-V8A1L0FaU/aSXZ1QNJScxC12uP4hANeRBgI4YdhHeRM=",
+ "lastModified": 1740623427,
+ "narHash": "sha256-3SdPQrZoa4odlScFDUHd4CUPQ/R1gtH4Mq9u8CBiK8M=",
"owner": "oxalica",
"repo": "rust-overlay",
- "rev": "1d7cbdaad90f8a5255a89a6eddd8af24dc89cafe",
+ "rev": "d342e8b5fd88421ff982f383c853f0fc78a847ab",
"type": "github"
},
"original": {
diff --git a/flake.nix b/flake.nix
index 5672e62f..c3b4ce5d 100644
--- a/flake.nix
+++ b/flake.nix
@@ -16,7 +16,13 @@
...
}: let
inherit (nixpkgs) lib;
- eachSystem = lib.genAttrs lib.systems.flakeExposed;
+ systems = [
+ "x86_64-linux"
+ "aarch64-linux"
+ "x86_64-darwin"
+ "aarch64-darwin"
+ ];
+ eachSystem = lib.genAttrs systems;
pkgsFor = eachSystem (system:
import nixpkgs {
localSystem.system = system;
@@ -71,7 +77,8 @@
rust-bin.nightly.latest.rust-analyzer
]
++ (lib.optional (stdenv.isx86_64 && stdenv.isLinux) cargo-tarpaulin)
- ++ (lib.optional stdenv.isLinux lldb);
+ ++ (lib.optional stdenv.isLinux lldb)
+ ++ (lib.optional stdenv.isDarwin darwin.apple_sdk.frameworks.CoreFoundation);
shellHook = ''
export RUST_BACKTRACE="1"
export RUSTFLAGS="''${RUSTFLAGS:-""} ${commonRustFlagsEnv} ${platformRustFlagsEnv}"
diff --git a/helix-core/Cargo.toml b/helix-core/Cargo.toml
index 4309cc14..a9f6f02b 100644
--- a/helix-core/Cargo.toml
+++ b/helix-core/Cargo.toml
@@ -18,8 +18,11 @@ integration = []
[dependencies]
helix-stdx = { path = "../helix-stdx" }
helix-loader = { path = "../helix-loader" }
+helix-event = { path = "../helix-event" }
helix-parsec = { path = "../helix-parsec" }
+filesentry = "0.2.1"
+ignore.workspace = true
ropey.workspace = true
smallvec = "1.15"
smartstring = "1.0.1"
@@ -32,7 +35,7 @@ unicode-segmentation.workspace = true
unicode-width = "=0.1.12"
unicode-general-category = "1.1"
slotmap.workspace = true
-tree-house = { workspace = true, features = ["fixtures"] }
+tree-house.workspace = true
once_cell = "1.21"
arc-swap = "1"
regex = "1"
@@ -55,7 +58,7 @@ textwrap = "0.16.2"
nucleo.workspace = true
parking_lot.workspace = true
-globset.workspace = true
+globset = "0.4.16"
regex-cursor = "0.1.5"
[dev-dependencies]
diff --git a/helix-core/src/file_watcher.rs b/helix-core/src/file_watcher.rs
new file mode 100644
index 00000000..f0101368
--- /dev/null
+++ b/helix-core/src/file_watcher.rs
@@ -0,0 +1,520 @@
+use std::borrow::Borrow;
+use std::mem::replace;
+use std::path::{Path, PathBuf};
+use std::slice;
+use std::sync::Arc;
+
+pub use filesentry::{Event, EventType, Events};
+use filesentry::{Filter, ShutdownOnDrop};
+use helix_event::{dispatch, events};
+use ignore::gitignore::{Gitignore, GitignoreBuilder};
+use serde::{Deserialize, Serialize};
+
+events! {
+ FileSystemDidChange {
+ fs_events: Events
+ }
+}
+
+/// Config for file watching
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
+#[serde(rename_all = "kebab-case", default, deny_unknown_fields)]
+pub struct Config {
+ /// Enable file watching enable by default
+ pub enable: bool,
+ pub watch_vcs: bool,
+ /// Only enable the file watcher inside helix workspaces (VCS repos and directories with .helix
+ /// directory) this prevents watching large directories like $HOME by default
+ ///
+ /// Defaults to `true`
+ pub require_workspace: bool,
+ /// Enables ignoring hidden files.
+ /// Whether to hide hidden files in file picker and global search results. Defaults to true.
+ pub hidden: bool,
+ /// Enables reading `.ignore` files.
+ /// Whether to hide files listed in .ignore in file picker and global search results. Defaults to true.
+ pub ignore: bool,
+ /// Enables reading `.gitignore` files.
+ /// Whether to hide files listed in .gitignore in file picker and global search results. Defaults to true.
+ pub git_ignore: bool,
+ /// Enables reading global .gitignore, whose path is specified in git's config: `core.excludefile` option.
+ /// Whether to hide files listed in global .gitignore in file picker and global search results. Defaults to true.
+ pub git_global: bool,
+ // /// Enables reading `.git/info/exclude` files.
+ // /// Whether to hide files listed in .git/info/exclude in file picker and global search results. Defaults to true.
+ // pub git_exclude: bool,
+ /// Maximum Depth to recurse for filewatching
+ pub max_depth: Option<usize>,
+}
+
+impl Default for Config {
+ fn default() -> Self {
+ Config {
+ enable: true,
+ watch_vcs: true,
+ require_workspace: true,
+ hidden: true,
+ ignore: true,
+ git_ignore: true,
+ git_global: true,
+ max_depth: Some(10),
+ }
+ }
+}
+pub struct Watcher {
+ watcher: Option<(filesentry::Watcher, ShutdownOnDrop)>,
+ filter: Arc<WatchFilter>,
+ roots: Vec<(PathBuf, usize)>,
+ config: Config,
+}
+
+impl Watcher {
+ pub fn new(config: &Config) -> Watcher {
+ let mut watcher = Watcher {
+ watcher: None,
+ filter: Arc::new(WatchFilter {
+ filesentry_ignores: Gitignore::empty(),
+ ignore_files: Vec::new(),
+ global_ignores: Vec::new(),
+ hidden: true,
+ watch_vcs: true,
+ }),
+ roots: Vec::new(),
+ config: config.clone(),
+ };
+ watcher.reload(config);
+ watcher
+ }
+
+ pub fn reload(&mut self, config: &Config) {
+ let old_config = replace(&mut self.config, config.clone());
+ let (workspace, no_workspace) = helix_loader::find_workspace();
+ if !config.enable || config.require_workspace && no_workspace {
+ self.watcher = None;
+ return;
+ }
+ self.filter = Arc::new(WatchFilter::new(
+ config,
+ &workspace,
+ self.roots.iter().map(|(it, _)| &**it),
+ ));
+ let watcher = match &mut self.watcher {
+ Some((watcher, _)) => {
+ // TODO: more fine grained detection of when recrawl is nedded
+ watcher.set_filter(self.filter.clone(), old_config != self.config);
+ watcher
+ }
+ None => match filesentry::Watcher::new() {
+ Ok(watcher) => {
+ watcher.set_filter(self.filter.clone(), false);
+ watcher.add_handler(move |events| {
+ dispatch(FileSystemDidChange { fs_events: events });
+ true
+ });
+ let shutdown_guard = watcher.shutdown_guard();
+ &mut self.watcher.insert((watcher, shutdown_guard)).0
+ }
+ Err(err) => {
+ log::error!("failed to start file-watcher: {err}");
+ return;
+ }
+ },
+ };
+ if let Err(err) = watcher.add_root(&workspace, true, |_| ()) {
+ log::error!("failed to start file-watcher: {err}");
+ }
+ for (root, _) in &self.roots {
+ if let Err(err) = watcher.add_root(root, true, |_| ()) {
+ log::error!("failed to start file-watcher: {err}");
+ }
+ }
+ watcher.start();
+ }
+
+ pub fn remove_root(&mut self, root: PathBuf) {
+ let i = self.roots.partition_point(|(it, _)| it < &root);
+ if self.roots.get(i).is_none_or(|(it, _)| it != &root) {
+ log::error!("tried to remove root {root:?} from watch list that does not exist!");
+ return;
+ }
+ if self.roots[i].1 <= 1 {
+ self.roots.remove(i);
+ } else {
+ self.roots[i].1 -= 1;
+ }
+ }
+
+ pub fn add_root(&mut self, root: &Path) {
+ let root = match root.canonicalize() {
+ Ok(root) => root,
+ Err(err) => {
+ log::error!("failed to watch {root:?}: {err}");
+ return;
+ }
+ };
+ let i = self.roots.partition_point(|(it, _)| it < &root);
+ if let Some((_, refcnt)) = self.roots.get_mut(i).filter(|(path, _)| path == &root) {
+ *refcnt += 1;
+ return;
+ }
+ if self.roots[..i]
+ .iter()
+ .rev()
+ .find(|(it, _)| it.parent().is_none_or(|it| root.starts_with(it)))
+ .is_some_and(|(it, _)| root.starts_with(it))
+ && !self.filter.ignore_path_rec(&root, Some(true))
+ {
+ return;
+ }
+ let (workspace, _) = helix_loader::find_workspace();
+ if root.starts_with(&workspace) {
+ return;
+ }
+ self.roots.insert(i, (root.clone(), 1));
+ self.filter = Arc::new(WatchFilter::new(
+ &self.config,
+ &workspace,
+ self.roots.iter().map(|(it, _)| &**it),
+ ));
+ if let Some((watcher, _)) = &self.watcher {
+ watcher.set_filter(self.filter.clone(), false);
+ if let Err(err) = watcher.add_root(&root, true, |_| ()) {
+ log::error!("failed to watch {root:?}: {err}");
+ }
+ }
+ }
+}
+
+fn build_ignore(paths: impl IntoIterator<Item = PathBuf> + Clone, dir: &Path) -> Option<Gitignore> {
+ let mut builder = GitignoreBuilder::new(dir);
+ for path in paths.clone() {
+ if let Some(err) = builder.add(&path) {
+ if !err.is_io() {
+ log::error!("failed to read ignorefile at {path:?}: {err}");
+ }
+ }
+ }
+ match builder.build() {
+ Ok(ignore) => (!ignore.is_empty()).then_some(ignore),
+ Err(err) => {
+ if !err.is_io() {
+ log::error!(
+ "failed to read ignorefile at {:?}: {err}",
+ paths.into_iter().collect::<Vec<_>>()
+ );
+ }
+ None
+ }
+ }
+}
+
+struct IgnoreFiles {
+ root: PathBuf,
+ ignores: Vec<Arc<Gitignore>>,
+}
+
+impl IgnoreFiles {
+ fn new(
+ workspace_ignore: Option<Arc<Gitignore>>,
+ config: &Config,
+ root: &Path,
+ globals: &[Arc<Gitignore>],
+ ) -> Self {
+ let mut ignores = Vec::with_capacity(8);
+ // .helix/ignore
+ if let Some(workspace_ignore) = workspace_ignore {
+ ignores.push(workspace_ignore);
+ }
+ for ancestor in root.ancestors() {
+ let ignore = if config.ignore {
+ if config.git_ignore {
+ // the second path takes priority
+ build_ignore(
+ [ancestor.join(".gitignore"), ancestor.join(".ignore")],
+ ancestor,
+ )
+ } else {
+ build_ignore([ancestor.join(".ignore")], ancestor)
+ }
+ } else if config.git_ignore {
+ build_ignore([ancestor.join(".gitignore")], ancestor)
+ } else {
+ None
+ };
+ if let Some(ignore) = ignore {
+ ignores.push(Arc::new(ignore));
+ }
+ }
+ ignores.extend(globals.iter().cloned());
+ Self {
+ root: root.into(),
+ ignores,
+ }
+ }
+
+ fn shared_ignores(
+ workspace: &Path,
+ config: &Config,
+ ) -> (Vec<Arc<Gitignore>>, Option<Arc<Gitignore>>) {
+ let mut ignores = Vec::new();
+ let workspace_ignore = build_ignore(
+ [
+ helix_loader::config_dir().join("ignore"),
+ workspace.join(".helix/ignore"),
+ ],
+ workspace,
+ )
+ .map(Arc::new);
+ if config.git_global {
+ let (gitignore_global, err) = Gitignore::global();
+ if let Some(err) = err {
+ if !err.is_io() {
+ log::error!("failed to read global global ignorefile: {err}");
+ }
+ }
+ if !gitignore_global.is_empty() {
+ ignores.push(Arc::new(gitignore_global));
+ }
+ }
+ // if config.git_exclude {
+ // TODO git_exclude implementation, this isn't quite trivial unfortunaetly
+ // due to detached workspace etc.
+ // }
+ // TODO: git exclude
+ (ignores, workspace_ignore)
+ }
+
+ fn filesentry_ignores(workspace: &Path) -> Gitignore {
+ // the second path takes priority
+ build_ignore(
+ [
+ helix_loader::config_dir().join("filesentryignore"),
+ workspace.join(".helix/filesentryignore"),
+ ],
+ workspace,
+ )
+ .unwrap_or(Gitignore::empty())
+ }
+
+ fn is_ignored(
+ ignores: &[impl Borrow<Gitignore>],
+ path: &Path,
+ is_dir: Option<bool>,
+ ) -> Option<bool> {
+ match is_dir {
+ Some(is_dir) => {
+ for ignore in ignores {
+ match ignore.borrow().matched(path, is_dir) {
+ ignore::Match::None => continue,
+ ignore::Match::Ignore(_) => return Some(true),
+ ignore::Match::Whitelist(_) => return Some(false),
+ }
+ }
+ }
+ None => {
+ // if we don't know wether this is a directory (on windows)
+ // then we are conservative and allow the dirs
+ for ignore in ignores {
+ match ignore.borrow().matched(path, true) {
+ ignore::Match::None => continue,
+ ignore::Match::Ignore(glob) => {
+ if glob.is_only_dir() {
+ match ignore.borrow().matched(path, false) {
+ ignore::Match::None => continue,
+ ignore::Match::Ignore(_) => return Some(true),
+ ignore::Match::Whitelist(_) => return Some(false),
+ }
+ } else {
+ return Some(true);
+ }
+ }
+ ignore::Match::Whitelist(_) => return Some(false),
+ }
+ }
+ }
+ }
+ None
+ }
+}
+
+/// a filter to ignore hiddeng/ingored files. The point of this
+/// is to avoid overwhelming the watcher with watching a ton of
+/// files/directories (like the cargo target directory, node_modules or
+/// VCS files) so ignoring a file is a performance optimization.
+///
+/// By default we ignore ignored
+struct WatchFilter {
+ filesentry_ignores: Gitignore,
+ ignore_files: Vec<IgnoreFiles>,
+ global_ignores: Vec<Arc<Gitignore>>,
+ hidden: bool,
+ watch_vcs: bool,
+}
+
+impl WatchFilter {
+ fn new<'a>(
+ config: &Config,
+ workspace: &'a Path,
+ roots: impl Iterator<Item = &'a Path> + Clone,
+ ) -> WatchFilter {
+ let filesentry_ignores = IgnoreFiles::filesentry_ignores(workspace);
+ let (global_ignores, workspace_ignore) = IgnoreFiles::shared_ignores(workspace, config);
+ let ignore_files = roots
+ .chain([workspace])
+ .map(|root| IgnoreFiles::new(workspace_ignore.clone(), config, root, &global_ignores))
+ .collect();
+ WatchFilter {
+ filesentry_ignores,
+ ignore_files,
+ global_ignores,
+ hidden: config.hidden,
+ watch_vcs: config.watch_vcs,
+ }
+ }
+
+ fn ignore_path_impl(
+ &self,
+ path: &Path,
+ is_dir: Option<bool>,
+ ignore_files: &[Arc<Gitignore>],
+ ) -> bool {
+ if let Some(ignore) =
+ IgnoreFiles::is_ignored(slice::from_ref(&self.filesentry_ignores), path, is_dir)
+ {
+ return ignore;
+ }
+ if is_hardcoded_whitelist(path) {
+ return false;
+ }
+ if is_hardcoded_blacklist(path, is_dir.unwrap_or(false)) {
+ return true;
+ }
+ if let Some(ignore) = IgnoreFiles::is_ignored(ignore_files, path, is_dir) {
+ return ignore;
+ }
+ // ignore .git dircectory except .git/HEAD (and .git itself)
+ if is_vcs_ignore(path, self.watch_vcs) {
+ return true;
+ }
+ !self.hidden && is_hidden(path)
+ }
+}
+
+impl filesentry::Filter for WatchFilter {
+ fn ignore_path(&self, path: &Path, is_dir: Option<bool>) -> bool {
+ let i = self
+ .ignore_files
+ .partition_point(|ignore_files| path < ignore_files.root);
+ let (root, ignore_files) = self
+ .ignore_files
+ .get(i)
+ .map_or((Path::new(""), &self.global_ignores), |files| {
+ (&files.root, &files.ignores)
+ });
+ if path == root {
+ return false;
+ }
+ self.ignore_path_impl(path, is_dir, ignore_files)
+ }
+
+ fn ignore_path_rec(&self, mut path: &Path, is_dir: Option<bool>) -> bool {
+ let i = self
+ .ignore_files
+ .partition_point(|ignore_files| path < ignore_files.root);
+ let (root, ignore_files) = self
+ .ignore_files
+ .get(i)
+ .map_or((Path::new(""), &self.global_ignores), |files| {
+ (&files.root, &files.ignores)
+ });
+ loop {
+ if path == root {
+ return false;
+ }
+ if self.ignore_path_impl(path, is_dir, ignore_files) {
+ return true;
+ }
+ let Some(parent) = path.parent() else {
+ break;
+ };
+ path = parent;
+ }
+ false
+ }
+}
+
+fn is_hidden(path: &Path) -> bool {
+ path.file_name().is_some_and(|it| {
+ it.as_encoded_bytes().first() == Some(&b'.')
+ // handled by vcs ignore rules
+ && it != ".git"
+ })
+}
+
+// hidden directories we want to watch by default
+fn is_hardcoded_whitelist(path: &Path) -> bool {
+ path.ends_with(".helix")
+ | path.ends_with(".github")
+ | path.ends_with(".cargo")
+ | path.ends_with(".envrc")
+}
+
+fn is_hardcoded_blacklist(path: &Path, is_dir: bool) -> bool {
+ // don't descend into the cargo regstiry and similar
+ path.parent()
+ .is_some_and(|parent| parent.ends_with(".cargo"))
+ && is_dir
+}
+
+fn file_name(path: &Path) -> Option<&str> {
+ path.file_name().and_then(|it| it.to_str())
+}
+
+fn is_vcs_ignore(path: &Path, watch_vcs: bool) -> bool {
+ // ignore .git dircectory except .git/HEAD (and .git itself)
+ if watch_vcs
+ && path.parent().is_some_and(|it| it.ends_with(".git"))
+ && !path.ends_with(".git/HEAD")
+ {
+ return true;
+ }
+ match file_name(path) {
+ Some(".jj" | ".svn" | ".hg") => true,
+ Some(".git") => !watch_vcs,
+ _ => false,
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use std::path::Path;
+
+ use crate::file_watcher::{is_hardcoded_whitelist, is_hidden, is_vcs_ignore};
+
+ #[test]
+ fn test_vcs_ignore() {
+ assert!(!is_vcs_ignore(Path::new(".git"), true));
+ assert!(!is_vcs_ignore(Path::new(".git/HEAD"), true));
+ assert!(is_vcs_ignore(Path::new(".git/foo"), true));
+ assert!(is_vcs_ignore(Path::new(".git/foo/bar"), true));
+ assert!(!is_vcs_ignore(Path::new(".foo"), true));
+ assert!(is_vcs_ignore(Path::new(".jj"), true));
+ assert!(is_vcs_ignore(Path::new(".svn"), true));
+ assert!(is_vcs_ignore(Path::new(".hg"), true));
+ }
+
+ #[test]
+ fn test_hidden() {
+ assert!(is_hidden(Path::new(".foo")));
+ // handled by vcs ignore rules
+ assert!(!is_hidden(Path::new(".git")));
+ }
+
+ #[test]
+ fn test_whitelist() {
+ assert!(is_hardcoded_whitelist(Path::new(".git")));
+ assert!(is_hardcoded_whitelist(Path::new(".helix")));
+ assert!(is_hardcoded_whitelist(Path::new(".github")));
+ assert!(!is_hardcoded_whitelist(Path::new(".githup")));
+ }
+}
diff --git a/helix-core/src/lib.rs b/helix-core/src/lib.rs
index 09865ca4..1e25eafa 100644
--- a/helix-core/src/lib.rs
+++ b/helix-core/src/lib.rs
@@ -11,6 +11,7 @@ pub mod diagnostic;
pub mod diff;
pub mod doc_formatter;
pub mod editor_config;
+pub mod file_watcher;
pub mod fuzzy;
pub mod graphemes;
pub mod history;
diff --git a/helix-core/src/position.rs b/helix-core/src/position.rs
index e70cb949..3f888c57 100644
--- a/helix-core/src/position.rs
+++ b/helix-core/src/position.rs
@@ -262,14 +262,7 @@ pub fn visual_offset_from_anchor(
pub fn pos_at_coords(text: RopeSlice, coords: Position, limit_before_line_ending: bool) -> usize {
let Position { mut row, col } = coords;
if limit_before_line_ending {
- let lines = text.len_lines() - 1;
-
- row = row.min(if crate::line_ending::get_line_ending(&text).is_some() {
- // if the last line is empty, don't jump to it
- lines - 1
- } else {
- lines
- });
+ row = row.min(text.len_lines() - 1);
};
let line_start = text.line_to_char(row);
let line_end = if limit_before_line_ending {
diff --git a/helix-core/src/snippets.rs b/helix-core/src/snippets.rs
index 477c9e75..3dd3b9c3 100644
--- a/helix-core/src/snippets.rs
+++ b/helix-core/src/snippets.rs
@@ -1,6 +1,6 @@
mod active;
mod elaborate;
-pub mod parser;
+mod parser;
mod render;
#[derive(PartialEq, Eq, Hash, Debug, PartialOrd, Ord, Clone, Copy)]
diff --git a/helix-core/src/syntax.rs b/helix-core/src/syntax.rs
index 4bc177ef..325c47ac 100644
--- a/helix-core/src/syntax.rs
+++ b/helix-core/src/syntax.rs
@@ -90,7 +90,7 @@ impl LanguageData {
Ok(Some(config))
}
- pub fn syntax_config(&self, loader: &Loader) -> Option<&SyntaxConfig> {
+ fn syntax_config(&self, loader: &Loader) -> Option<&SyntaxConfig> {
self.syntax
.get_or_init(|| {
Self::compile_syntax_config(&self.config, loader)
@@ -238,7 +238,7 @@ impl LanguageData {
}
}
-pub fn reconfigure_highlights(config: &SyntaxConfig, recognized_names: &[String]) {
+fn reconfigure_highlights(config: &SyntaxConfig, recognized_names: &[String]) {
config.configure(move |capture_name| {
let capture_parts: Vec<_> = capture_name.split('.').collect();
@@ -512,7 +512,7 @@ impl FileTypeGlobMatcher {
#[derive(Debug)]
pub struct Syntax {
- pub inner: tree_house::Syntax,
+ inner: tree_house::Syntax,
}
const PARSE_TIMEOUT: Duration = Duration::from_millis(500); // half a second is pretty generous
@@ -1203,24 +1203,7 @@ mod test {
);
let language = LOADER.language_for_name("rust").unwrap();
- dbg!(language);
let grammar = LOADER.get_config(language).unwrap().grammar;
- dbg!(grammar);
- let syntax = Syntax::new(source.slice(..), language, &LOADER).unwrap();
- let mut h = syntax.highlighter(
- "fn main() { 4 + 2; }".into(),
- &LOADER,
- 0.."fn main() { 4 + 2; }".len() as u32,
- );
-
- for n in 0..5 {
- dbg!(h.active_highlights().collect::<Vec<_>>());
- dbg!(h.next_event_offset());
- let (e, h) = h.advance();
- dbg!(h.collect::<Vec<_>>(), e);
- // panic!()
- }
-
let query = Query::new(grammar, query_str, |_, _| Ok(())).unwrap();
let textobject = TextObjectQuery::new(query);
let syntax = Syntax::new(source.slice(..), language, &LOADER).unwrap();
@@ -1385,24 +1368,4 @@ mod test {
source.len(),
);
}
- #[test]
- fn highlight() {
- let source = Rope::from_str(r#"assert_eq!(0, Some(0));"#);
- let loader = crate::config::default_lang_loader();
- loader.set_scopes(vec!["punctuation".to_string()]);
- let language = loader.language_for_name("rust").unwrap();
-
- let syntax = Syntax::new(source.slice(..), language, &loader).unwrap();
- println!(
- "{}",
- tree_house::fixtures::highlighter_fixture(
- "",
- &loader,
- |_| "punct".to_string(),
- &syntax.inner,
- source.slice(..),
- ..,
- )
- );
- }
}
diff --git a/helix-core/src/transaction.rs b/helix-core/src/transaction.rs
index 37be2e2e..41faf8f7 100644
--- a/helix-core/src/transaction.rs
+++ b/helix-core/src/transaction.rs
@@ -361,7 +361,6 @@ impl ChangeSet {
pos += s.chars().count();
}
}
- println!("=>\n{text}");
}
true
}
diff --git a/helix-dap/Cargo.toml b/helix-dap/Cargo.toml
index 000ea5a8..8033c757 100644
--- a/helix-dap/Cargo.toml
+++ b/helix-dap/Cargo.toml
@@ -26,7 +26,7 @@ slotmap.workspace = true
futures-executor.workspace = true
futures-util.workspace = true
tokio-stream.workspace = true
-sonic-rs.workspace = true
+
[dev-dependencies]
fern = "0.7"
diff --git a/helix-dap/src/client.rs b/helix-dap/src/client.rs
index fe4af188..e5824a7f 100644
--- a/helix-dap/src/client.rs
+++ b/helix-dap/src/client.rs
@@ -231,11 +231,7 @@ impl Client {
}
fn next_request_id(&self) -> u64 {
- // > The `seq` for the first message sent by a client or debug adapter
- // > is 1, and for each subsequent message is 1 greater than the
- // > previous message sent by that actor
- // <https://microsoft.github.io/debug-adapter-protocol/specification#Base_Protocol_ProtocolMessage>
- self.request_counter.fetch_add(1, Ordering::Relaxed) + 1
+ self.request_counter.fetch_add(1, Ordering::Relaxed)
}
// Internal, called by specific DAP commands when resuming
diff --git a/helix-dap/src/lib.rs b/helix-dap/src/lib.rs
index 4cb95315..9f61f42d 100644
--- a/helix-dap/src/lib.rs
+++ b/helix-dap/src/lib.rs
@@ -9,11 +9,12 @@ pub use types::*;
use serde::de::DeserializeOwned;
+
use thiserror::Error;
#[derive(Error, Debug)]
pub enum Error {
#[error("failed to parse: {0}")]
- Parse(Box<dyn std::error::Error + Send + Sync>),
+ Parse(#[from] serde_json::Error),
#[error("IO Error: {0}")]
IO(#[from] std::io::Error),
#[error("request {0} timed out")]
@@ -29,18 +30,6 @@ pub enum Error {
}
pub type Result<T> = core::result::Result<T, Error>;
-impl From<serde_json::Error> for Error {
- fn from(value: serde_json::Error) -> Self {
- Self::Parse(Box::new(value))
- }
-}
-
-impl From<sonic_rs::Error> for Error {
- fn from(value: sonic_rs::Error) -> Self {
- Self::Parse(Box::new(value))
- }
-}
-
#[derive(Debug)]
pub enum Request {
RunInTerminal(<requests::RunInTerminal as types::Request>::Arguments),
diff --git a/helix-dap/src/transport.rs b/helix-dap/src/transport.rs
index fdd60226..8ca408df 100644
--- a/helix-dap/src/transport.rs
+++ b/helix-dap/src/transport.rs
@@ -125,14 +125,12 @@ impl Transport {
info!("[{}] <- DAP {}", id, msg);
- // NOTE: We avoid using `?` here, since it would return early on error
- // and skip clearing `content`. By returning the result directly instead,
- // we ensure `content.clear()` is always called.
- let output = sonic_rs::from_slice(content).map_err(Into::into);
+ // try parsing as output (server response) or call (server request)
+ let output: serde_json::Result<Payload> = serde_json::from_str(msg);
content.clear();
- output
+ Ok(output?)
}
async fn recv_server_error(
diff --git a/helix-loader/src/lib.rs b/helix-loader/src/lib.rs
index 705e016b..9872b77a 100644
--- a/helix-loader/src/lib.rs
+++ b/helix-loader/src/lib.rs
@@ -64,6 +64,7 @@ fn prioritize_runtime_dirs() -> Vec<PathBuf> {
if let Some(dir) = std::option_env!("HELIX_DEFAULT_RUNTIME") {
rt_dirs.push(dir.into());
}
+
// fallback to location of the executable being run
// canonicalize the path in case the executable is symlinked
let exe_rt_dir = std::env::current_exe()
@@ -72,7 +73,6 @@ fn prioritize_runtime_dirs() -> Vec<PathBuf> {
.and_then(|path| path.parent().map(|path| path.to_path_buf().join(RT_DIR)))
.unwrap();
rt_dirs.push(exe_rt_dir);
- rt_dirs.push(PathBuf::from("/usr/lib/helix/runtime/"));
rt_dirs
}
diff --git a/helix-lsp-types/src/code_action.rs b/helix-lsp-types/src/code_action.rs
index ed9532f0..b46327e8 100644
--- a/helix-lsp-types/src/code_action.rs
+++ b/helix-lsp-types/src/code_action.rs
@@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize};
use serde_json::Value;
-use std::{borrow::Cow, marker::StructuralPartialEq, ops::DerefPure};
+use std::borrow::Cow;
#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum CodeActionProviderCapability {
@@ -149,23 +149,8 @@ impl From<CodeAction> for CodeActionOrCommand {
}
}
-#[derive(Debug, Eq, PartialOrd, Hash, Clone, Deserialize, Serialize)]
-pub struct CodeActionKind(pub Cow<'static, str>);
-
-impl std::ops::Deref for CodeActionKind {
- type Target = str;
-
- fn deref(&self) -> &Self::Target {
- self.as_str()
- }
-}
-impl PartialEq for CodeActionKind {
- fn eq(&self, other: &Self) -> bool {
- self.0 == other.0
- }
-}
-impl StructuralPartialEq for CodeActionKind {}
-unsafe impl DerefPure for CodeActionKind {}
+#[derive(Debug, Eq, PartialEq, Hash, PartialOrd, Clone, Deserialize, Serialize)]
+pub struct CodeActionKind(Cow<'static, str>);
impl CodeActionKind {
/// Empty kind.
@@ -308,9 +293,6 @@ pub struct CodeAction {
/// @since 3.16.0
#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<Value>,
-
- #[serde(skip_serializing_if = "Option::is_none")]
- pub group: Option<String>,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
diff --git a/helix-lsp-types/src/completion.rs b/helix-lsp-types/src/completion.rs
index 793252de..7c006bdb 100644
--- a/helix-lsp-types/src/completion.rs
+++ b/helix-lsp-types/src/completion.rs
@@ -24,7 +24,7 @@ impl InsertTextFormat {
/// The kind of a completion entry.
#[derive(Eq, PartialEq, Clone, Copy, Serialize, Deserialize)]
#[serde(transparent)]
-pub struct CompletionItemKind(pub i32);
+pub struct CompletionItemKind(i32);
lsp_enum! {
impl CompletionItemKind {
pub const TEXT: CompletionItemKind = CompletionItemKind(1);
diff --git a/helix-lsp-types/src/document_symbols.rs b/helix-lsp-types/src/document_symbols.rs
index a88e7376..3f482e16 100644
--- a/helix-lsp-types/src/document_symbols.rs
+++ b/helix-lsp-types/src/document_symbols.rs
@@ -98,8 +98,6 @@ pub struct DocumentSymbol {
/// The range that should be selected and revealed when this symbol is being picked, e.g the name of a function.
/// Must be contained by the the `range`.
pub selection_range: Range,
- /// For sticky context. Default to selection_range.
- pub sticky_range: Option<Range>,
/// Children of this symbol, e.g. properties of a class.
#[serde(skip_serializing_if = "Option::is_none")]
pub children: Option<Vec<DocumentSymbol>>,
diff --git a/helix-lsp-types/src/lib.rs b/helix-lsp-types/src/lib.rs
index 187369ed..fd668de5 100644
--- a/helix-lsp-types/src/lib.rs
+++ b/helix-lsp-types/src/lib.rs
@@ -15,7 +15,8 @@ able to parse any URI, such as `urn:isbn:0451450523`.
*/
#![allow(non_upper_case_globals)]
-#![feature(deref_pure_trait, structural_match)]
+#![forbid(unsafe_code)]
+
use bitflags::bitflags;
use std::{collections::HashMap, fmt::Debug};
@@ -71,9 +72,6 @@ macro_rules! lsp_enum {
$(#[$attr])*
pub const $name: $enum_type = $value;
)*
- pub const ALL: &[$typ] = &[
- $($value,)+
- ];
}
impl std::fmt::Debug for $typ {
@@ -212,16 +210,6 @@ pub enum NumberOrString {
Number(i32),
String(String),
}
-impl From<i32> for NumberOrString {
- fn from(v: i32) -> Self {
- Self::Number(v)
- }
-}
-impl From<&i32> for NumberOrString {
- fn from(&v: &i32) -> Self {
- Self::Number(v)
- }
-}
/* ----------------- Cancel support ----------------- */
@@ -586,7 +574,7 @@ pub struct TextDocumentEdit {
///
/// @since 3.16.0 - support for AnnotatedTextEdit. This is guarded by the
/// client capability `workspace.workspaceEdit.changeAnnotationSupport`
- pub edits: Vec<SnippetTextEdit>,
+ pub edits: Vec<OneOf<TextEdit, AnnotatedTextEdit>>,
}
/// Additional information that describes document changes.
@@ -709,18 +697,6 @@ pub struct DeleteFile {
pub options: Option<DeleteFileOptions>,
}
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SnippetTextEdit {
- pub range: Range,
- pub new_text: String,
- #[serde(skip_serializing_if = "Option::is_none")]
- pub insert_text_format: Option<InsertTextFormat>,
- /// The annotation id if this is an annotated
- #[serde(skip_serializing_if = "Option::is_none")]
- pub annotation_id: Option<ChangeAnnotationIdentifier>,
-}
-
/// A workspace edit represents changes to many resources managed in the workspace.
/// The edit should either provide `changes` or `documentChanges`.
/// If the client can handle versioned document edits and if `documentChanges` are present,
@@ -1265,7 +1241,7 @@ pub enum FailureHandlingKind {
/// A symbol kind.
#[derive(Eq, PartialEq, Copy, Clone, Serialize, Deserialize)]
#[serde(transparent)]
-pub struct SymbolKind(pub i32);
+pub struct SymbolKind(i32);
lsp_enum! {
impl SymbolKind {
pub const FILE: SymbolKind = SymbolKind(1);
@@ -1294,19 +1270,6 @@ impl SymbolKind {
pub const EVENT: SymbolKind = SymbolKind(24);
pub const OPERATOR: SymbolKind = SymbolKind(25);
pub const TYPE_PARAMETER: SymbolKind = SymbolKind(26);
-
- pub const MACRO: SymbolKind = SymbolKind(50);
- pub const PROC_MACRO: SymbolKind = SymbolKind(51);
- pub const BUILTIN_ATTRIBUTE: SymbolKind = SymbolKind(52);
- pub const ATTRIBUTE: SymbolKind = SymbolKind(53);
- pub const DERIVE: SymbolKind = SymbolKind(54);
- pub const DERIVE_HELPER: SymbolKind = SymbolKind(55);
- pub const TYPE_ALIAS: SymbolKind = SymbolKind(56);
- pub const LOCAL: SymbolKind = SymbolKind(57);
- pub const LABEL: SymbolKind = SymbolKind(58);
- pub const LIFETIME: SymbolKind = SymbolKind(59);
- pub const VALUE: SymbolKind = SymbolKind(60);
-
}
}
@@ -2591,7 +2554,7 @@ impl PublishDiagnosticsParams {
}
}
-#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Clone, Hash)]
+#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Clone)]
#[serde(untagged)]
pub enum Documentation {
String(String),
@@ -2608,14 +2571,14 @@ pub enum Documentation {
/// <pre><code>```${language}
/// ${value}
/// ```</code></pre>
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize, Hash)]
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(untagged)]
pub enum MarkedString {
String(String),
LanguageString(LanguageString),
}
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize, Hash)]
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
pub struct LanguageString {
pub language: String,
pub value: String,
@@ -2734,7 +2697,7 @@ pub struct ApplyWorkspaceEditResponse {
///
/// Please note that `MarkupKinds` must not start with a `$`. This kinds
/// are reserved for internal usage.
-#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Clone, Hash)]
+#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Clone)]
#[serde(rename_all = "lowercase")]
pub enum MarkupKind {
/// Plain text is supported as a content format
@@ -2766,7 +2729,7 @@ pub enum MarkupKind {
///
/// Please *Note* that clients might sanitize the return markdown. A client could decide to
/// remove HTML from the markdown to avoid script execution.
-#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Clone, Hash)]
+#[derive(Debug, Eq, PartialEq, Deserialize, Serialize, Clone)]
pub struct MarkupContent {
pub kind: MarkupKind,
pub value: String,
diff --git a/helix-lsp-types/src/semantic_tokens.rs b/helix-lsp-types/src/semantic_tokens.rs
index b4448aa7..842558ba 100644
--- a/helix-lsp-types/src/semantic_tokens.rs
+++ b/helix-lsp-types/src/semantic_tokens.rs
@@ -153,7 +153,7 @@ pub struct SemanticToken {
}
impl SemanticToken {
- pub fn deserialize_tokens<'de, D>(deserializer: D) -> Result<Vec<SemanticToken>, D::Error>
+ fn deserialize_tokens<'de, D>(deserializer: D) -> Result<Vec<SemanticToken>, D::Error>
where
D: serde::Deserializer<'de>,
{
@@ -177,7 +177,7 @@ impl SemanticToken {
)
}
- pub fn serialize_tokens<S>(tokens: &[SemanticToken], serializer: S) -> Result<S::Ok, S::Error>
+ fn serialize_tokens<S>(tokens: &[SemanticToken], serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
@@ -192,7 +192,7 @@ impl SemanticToken {
seq.end()
}
- pub fn deserialize_tokens_opt<'de, D>(
+ fn deserialize_tokens_opt<'de, D>(
deserializer: D,
) -> Result<Option<Vec<SemanticToken>>, D::Error>
where
@@ -208,7 +208,7 @@ impl SemanticToken {
Ok(Option::<Wrapper>::deserialize(deserializer)?.map(|wrapper| wrapper.tokens))
}
- pub fn serialize_tokens_opt<S>(
+ fn serialize_tokens_opt<S>(
data: &Option<Vec<SemanticToken>>,
serializer: S,
) -> Result<S::Ok, S::Error>
diff --git a/helix-lsp-types/src/workspace_diagnostic.rs b/helix-lsp-types/src/workspace_diagnostic.rs
index c24690f0..485dcc2b 100644
--- a/helix-lsp-types/src/workspace_diagnostic.rs
+++ b/helix-lsp-types/src/workspace_diagnostic.rs
@@ -37,7 +37,7 @@ pub struct PreviousResultId {
/// Parameters of the workspace diagnostic request.
///
/// @since 3.17.0
-#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize, Default)]
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct WorkspaceDiagnosticParams {
/// The additional identifier provided during registration.
diff --git a/helix-lsp-types/src/workspace_symbols.rs b/helix-lsp-types/src/workspace_symbols.rs
index 68e78f83..9ba80895 100644
--- a/helix-lsp-types/src/workspace_symbols.rs
+++ b/helix-lsp-types/src/workspace_symbols.rs
@@ -36,8 +36,8 @@ pub struct WorkspaceSymbolClientCapabilities {
pub resolve_support: Option<WorkspaceSymbolResolveSupportCapability>,
}
+/// The parameters of a Workspace Symbol Request.
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
-#[serde(rename_all = "camelCase")]
pub struct WorkspaceSymbolParams {
#[serde(flatten)]
pub partial_result_params: PartialResultParams,
@@ -47,24 +47,6 @@ pub struct WorkspaceSymbolParams {
/// A non-empty query string
pub query: String,
-
- pub search_scope: Option<WorkspaceSymbolSearchScope>,
-
- pub search_kind: Option<WorkspaceSymbolSearchKind>,
-}
-
-#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
-#[serde(rename_all = "camelCase")]
-pub enum WorkspaceSymbolSearchScope {
- Workspace,
- WorkspaceAndDependencies,
-}
-
-#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
-#[serde(rename_all = "camelCase")]
-pub enum WorkspaceSymbolSearchKind {
- OnlyTypes,
- AllSymbols,
}
#[derive(Debug, Eq, PartialEq, Clone, Default, Deserialize, Serialize)]
diff --git a/helix-lsp/Cargo.toml b/helix-lsp/Cargo.toml
index 6156be9a..b2557c93 100644
--- a/helix-lsp/Cargo.toml
+++ b/helix-lsp/Cargo.toml
@@ -16,19 +16,19 @@ homepage.workspace = true
helix-stdx = { path = "../helix-stdx" }
helix-core = { path = "../helix-core" }
helix-loader = { path = "../helix-loader" }
+helix-event = { path = "../helix-event" }
helix-lsp-types = { path = "../helix-lsp-types" }
anyhow = "1.0"
futures-executor.workspace = true
futures-util.workspace = true
-globset.workspace = true
+globset = "0.4.16"
log = "0.4"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
-tokio = { version = "1.48", features = ["rt", "rt-multi-thread", "io-util", "io-std", "time", "process", "macros", "fs", "parking_lot", "sync"] }
+tokio = { version = "1.47", features = ["rt", "rt-multi-thread", "io-util", "io-std", "time", "process", "macros", "fs", "parking_lot", "sync"] }
tokio-stream.workspace = true
parking_lot.workspace = true
arc-swap = "1"
slotmap.workspace = true
thiserror.workspace = true
-sonic-rs.workspace = true
diff --git a/helix-lsp/src/client.rs b/helix-lsp/src/client.rs
index 22a8dd89..38a7266a 100644
--- a/helix-lsp/src/client.rs
+++ b/helix-lsp/src/client.rs
@@ -596,7 +596,7 @@ impl Client {
}),
did_change_watched_files: Some(lsp::DidChangeWatchedFilesClientCapabilities {
dynamic_registration: Some(true),
- relative_pattern_support: Some(false),
+ relative_pattern_support: Some(true),
}),
file_operations: Some(lsp::WorkspaceFileOperationsClientCapabilities {
will_rename: Some(true),
@@ -1503,7 +1503,6 @@ impl Client {
query,
work_done_progress_params: lsp::WorkDoneProgressParams::default(),
partial_result_params: lsp::PartialResultParams::default(),
- ..Default::default()
};
Some(self.call::<lsp::request::WorkspaceSymbolRequest>(params))
diff --git a/helix-lsp/src/file_event.rs b/helix-lsp/src/file_event.rs
index 5e7f8ca6..c07bfe80 100644
--- a/helix-lsp/src/file_event.rs
+++ b/helix-lsp/src/file_event.rs
@@ -1,16 +1,23 @@
+use std::collections::hash_map;
+use std::mem::take;
+use std::path::{is_separator, Path};
use std::{collections::HashMap, path::PathBuf, sync::Weak};
-use globset::{GlobBuilder, GlobSetBuilder};
+use globset::{Glob, GlobSet};
+use helix_core::file_watcher::{EventType, Events, FileSystemDidChange};
+use helix_event::register_hook;
+use helix_lsp_types::WatchKind;
use tokio::sync::mpsc;
use crate::{lsp, Client, LanguageServerId};
enum Event {
- FileChanged {
+ /// file written by helix, special cased to not wait on FS
+ FileWritten {
path: PathBuf,
},
+ FileWatcher(Events),
Register {
- client_id: LanguageServerId,
client: Weak<Client>,
registration_id: String,
options: lsp::DidChangeWatchedFilesRegistrationOptions,
@@ -24,10 +31,108 @@ enum Event {
},
}
-#[derive(Default)]
struct ClientState {
client: Weak<Client>,
- registered: HashMap<String, globset::GlobSet>,
+ registerations: HashMap<String, u32>,
+ pending: Vec<lsp::FileEvent>,
+}
+
+#[derive(Debug, Clone)]
+struct Interest {
+ glob: Glob,
+ server: LanguageServerId,
+ id: u32,
+ flags: WatchKind,
+}
+
+struct State {
+ clients: HashMap<LanguageServerId, ClientState>,
+ glob_matcher: GlobSet,
+ interest: Vec<Interest>,
+ // used for matching to avoid reallocation
+ candidates: Vec<usize>,
+}
+impl State {
+ fn notify<'a>(&mut self, events: impl Iterator<Item = (&'a Path, EventType)> + Clone) {
+ for (path, ty) in events {
+ let (interest_kind, notification_type) = match ty {
+ EventType::Create => (WatchKind::Create, lsp::FileChangeType::CREATED),
+ EventType::Delete => (WatchKind::Delete, lsp::FileChangeType::DELETED),
+ EventType::Modified => (WatchKind::Change, lsp::FileChangeType::CHANGED),
+ EventType::Tempfile => continue,
+ };
+ self.glob_matcher.matches_into(path, &mut self.candidates);
+ for interest in self.candidates.drain(..) {
+ let interest = &self.interest[interest];
+ if !interest.flags.contains(interest_kind) {
+ continue;
+ }
+ let Ok(uri) = lsp::Url::from_file_path(path) else {
+ continue;
+ };
+ let event = lsp::FileEvent {
+ uri,
+ typ: notification_type,
+ };
+ self.clients
+ .get_mut(&interest.server)
+ .unwrap()
+ .pending
+ .push(event);
+ }
+ }
+ for client_state in self.clients.values_mut() {
+ if client_state.pending.is_empty() {
+ continue;
+ }
+ let Some(client) = client_state.client.upgrade() else {
+ continue;
+ };
+ log::debug!(
+ "Sending didChangeWatchedFiles notification to client '{}'",
+ client.name()
+ );
+ client.did_change_watched_files(take(&mut client_state.pending));
+ }
+ }
+
+ fn purge_client(&mut self, id: LanguageServerId) {
+ self.clients.remove(&id);
+ let interest = self
+ .interest
+ .iter()
+ .filter(|it| it.server != id)
+ .cloned()
+ .collect();
+ self.rebuild_globmatcher(interest);
+ }
+
+ fn rebuild_globmatcher(&mut self, interest: Vec<Interest>) {
+ let mut builder = GlobSet::builder();
+ for interest in &interest {
+ builder.add(interest.glob.clone());
+ }
+ match builder.build() {
+ Ok(glob_matcher) => {
+ self.glob_matcher = glob_matcher;
+ self.interest = interest;
+ }
+ Err(err) => {
+ log::error!("failde to build glob matcher for file watching: ({err})",);
+ }
+ }
+ }
+}
+
+impl Default for State {
+ fn default() -> State {
+ State {
+ clients: Default::default(),
+ glob_matcher: Default::default(),
+ interest: Default::default(),
+ candidates: Vec::with_capacity(32),
+ }
+ }
}
/// The Handler uses a dedicated tokio task to respond to file change events by
@@ -54,18 +159,21 @@ impl Handler {
pub fn new() -> Self {
let (tx, rx) = mpsc::unbounded_channel();
tokio::spawn(Self::run(rx));
+ let tx_ = tx.clone();
+ register_hook!(move |event: &mut FileSystemDidChange| {
+ let _ = tx_.send(Event::FileWatcher(event.fs_events.clone()));
+ Ok(())
+ });
Self { tx }
}
pub fn register(
&self,
- client_id: LanguageServerId,
client: Weak<Client>,
registration_id: String,
options: lsp::DidChangeWatchedFilesRegistrationOptions,
) {
let _ = self.tx.send(Event::Register {
- client_id,
client,
registration_id,
options,
@@ -80,7 +188,7 @@ impl Handler {
}
pub fn file_changed(&self, path: PathBuf) {
- let _ = self.tx.send(Event::FileChanged { path });
+ let _ = self.tx.send(Event::FileWritten { path });
}
pub fn remove_client(&self, client_id: LanguageServerId) {
@@ -88,100 +196,144 @@ impl Handler {
}
async fn run(mut rx: mpsc::UnboundedReceiver<Event>) {
- let mut state: HashMap<LanguageServerId, ClientState> = HashMap::new();
+ let mut state = State::default();
while let Some(event) = rx.recv().await {
match event {
- Event::FileChanged { path } => {
+ Event::FileWatcher(events) => {
+ let events = events
+ .iter()
+ .map(|event| (event.path.as_std_path(), event.ty));
+ state.notify(events);
+ }
+ Event::FileWritten { path } => {
log::debug!("Received file event for {:?}", &path);
-
- state.retain(|id, client_state| {
- if !client_state
- .registered
- .values()
- .any(|glob| glob.is_match(&path))
- {
- return true;
- }
- let Some(client) = client_state.client.upgrade() else {
- log::warn!("LSP client was dropped: {id}");
- return false;
- };
- let Ok(uri) = lsp::Url::from_file_path(&path) else {
- return true;
- };
- log::debug!(
- "Sending didChangeWatchedFiles notification to client '{}'",
- client.name()
- );
- client.did_change_watched_files(vec![lsp::FileEvent {
- uri,
- // We currently always send the CHANGED state
- // since we don't actually have more context at
- // the moment.
- typ: lsp::FileChangeType::CHANGED,
- }]);
- true
- });
+ state.notify([(&*path, EventType::Modified)].iter().cloned());
}
Event::Register {
- client_id,
client,
registration_id,
options: ops,
} => {
+ let Some(client_) = client.upgrade() else {
+ continue;
+ };
log::debug!(
"Registering didChangeWatchedFiles for client '{}' with id '{}'",
- client_id,
+ client_.name(),
registration_id
);
- let entry = state.entry(client_id).or_default();
+ if !state
+ .clients
+ .get(&client_.id())
+ .is_some_and(|state| !state.client.ptr_eq(&client))
+ {
+ state.purge_client(client_.id());
+ }
+ let entry = state
+ .clients
+ .entry(client_.id())
+ .or_insert_with(|| ClientState {
+ client: client.clone(),
+ registerations: HashMap::with_capacity(8),
+ pending: Vec::with_capacity(32),
+ });
entry.client = client;
-
- let mut builder = GlobSetBuilder::new();
- for watcher in ops.watchers {
- if let lsp::GlobPattern::String(pattern) = watcher.glob_pattern {
- if let Ok(glob) = GlobBuilder::new(&pattern).build() {
- builder.add(glob);
- }
+ let next_id = u32::try_from(entry.registerations.len()).unwrap();
+ let (mut interest, id) = match entry.registerations.entry(registration_id) {
+ hash_map::Entry::Occupied(entry) => {
+ let id = *entry.get();
+ let mut interest = Vec::with_capacity(state.interest.len());
+ interest.extend(
+ state
+ .interest
+ .iter()
+ .filter(|it| it.server != client_.id() || it.id != id)
+ .cloned(),
+ );
+ (interest, id)
}
- }
- match builder.build() {
- Ok(globset) => {
- entry.registered.insert(registration_id, globset);
+ hash_map::Entry::Vacant(entry) => {
+ entry.insert(next_id);
+ (state.interest.clone(), next_id)
+ }
+ };
+ for watcher in ops.watchers {
+ if watcher.kind.is_some_and(|flags| flags.is_empty()) {
+ continue;
}
- Err(err) => {
- // Remove any old state for that registration id and
- // remove the entire client if it's now empty.
- entry.registered.remove(&registration_id);
- if entry.registered.is_empty() {
- state.remove(&client_id);
+ let glob = match watcher.glob_pattern {
+ helix_lsp_types::GlobPattern::String(pattern) => pattern,
+ helix_lsp_types::GlobPattern::Relative(relative_pattern) => {
+ let base_url = match relative_pattern.base_uri {
+ helix_lsp_types::OneOf::Left(folder) => folder.uri,
+ helix_lsp_types::OneOf::Right(url) => url,
+ };
+ let Ok(mut base_dir) = base_url.to_file_path() else {
+ log::error!(
+ "{} provided invalid URL for watching '{base_url}'",
+ client_.name(),
+ );
+ continue;
+ };
+ if let Ok(dir) = base_dir.canonicalize() {
+ base_dir = dir
+ }
+ let Ok(mut base_dir) = base_dir.into_os_string().into_string()
+ else {
+ log::error!(
+ "{} provided invalid URL for watching '{base_url}' (must be valid utf-8)",
+ client_.name(),
+ );
+ continue;
+ };
+ if !base_dir.chars().next_back().is_some_and(is_separator) {
+ base_dir.push('/');
+ }
+ base_dir.push_str(&relative_pattern.pattern);
+ base_dir
+ }
+ };
+ match Glob::new(&glob) {
+ Ok(glob) => {
+ interest.push(Interest {
+ glob,
+ server: client_.id(),
+ id,
+ flags: watcher.kind.unwrap_or(WatchKind::all()),
+ });
+ }
+ Err(err) => {
+ log::error!(
+ "{} provided invalid glob for watching '{glob}': ({err})",
+ client_.name(),
+ );
}
- log::warn!(
- "Unable to build globset for LSP didChangeWatchedFiles {err}"
- )
}
}
+ state.rebuild_globmatcher(interest);
}
Event::Unregister {
client_id,
registration_id,
} => {
- log::debug!(
- "Unregistering didChangeWatchedFiles with id '{}' for client '{}'",
- registration_id,
- client_id
- );
- if let Some(client_state) = state.get_mut(&client_id) {
- client_state.registered.remove(&registration_id);
- if client_state.registered.is_empty() {
- state.remove(&client_id);
- }
- }
+ let Some(client_state) = state.clients.get_mut(&client_id) else {
+ return;
+ };
+ let Some(id) = client_state.registerations.remove(&*registration_id) else {
+ return;
+ };
+ let interest = state
+ .interest
+ .iter()
+ .filter(|it| it.server != client_id || it.id != id)
+ .cloned()
+ .collect();
+ state.rebuild_globmatcher(interest);
}
Event::RemoveClient { client_id } => {
log::debug!("Removing LSP client: {client_id}");
- state.remove(&client_id);
+ state.purge_client(client_id);
}
}
}
diff --git a/helix-lsp/src/lib.rs b/helix-lsp/src/lib.rs
index 259980dd..450a3769 100644
--- a/helix-lsp/src/lib.rs
+++ b/helix-lsp/src/lib.rs
@@ -37,7 +37,7 @@ pub enum Error {
#[error("protocol error: {0}")]
Rpc(#[from] jsonrpc::Error),
#[error("failed to parse: {0}")]
- Parse(Box<dyn std::error::Error + Send + Sync>),
+ Parse(#[from] serde_json::Error),
#[error("IO Error: {0}")]
IO(#[from] std::io::Error),
#[error("request {0} timed out")]
@@ -52,18 +52,6 @@ pub enum Error {
Other(#[from] anyhow::Error),
}
-impl From<serde_json::Error> for Error {
- fn from(value: serde_json::Error) -> Self {
- Self::Parse(Box::new(value))
- }
-}
-
-impl From<sonic_rs::Error> for Error {
- fn from(value: sonic_rs::Error) -> Self {
- Self::Parse(Box::new(value))
- }
-}
-
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum OffsetEncoding {
/// UTF-8 code units aka bytes
@@ -1082,103 +1070,4 @@ mod tests {
assert!(transaction.apply(&mut source));
assert_eq!(source, "[\n \"🇺🇸\",\n \"🎄\",\n]");
}
- #[test]
- fn rahh() {
- use helix_lsp_types::*;
- let th = [
- TextEdit {
- range: Range {
- start: Position {
- line: 1,
- character: 0,
- },
- end: Position {
- line: 1,
- character: 4,
- },
- },
- new_text: "".into(),
- },
- TextEdit {
- range: Range {
- start: Position {
- line: 2,
- character: 0,
- },
- end: Position {
- line: 3,
- character: 1,
- },
- },
- new_text: "".into(),
- },
- TextEdit {
- range: Range {
- start: Position {
- line: 3,
- character: 9,
- },
- end: Position {
- line: 3,
- character: 9,
- },
- },
- new_text: "let new =\n".into(),
- },
- TextEdit {
- range: Range {
- start: Position {
- line: 3,
- character: 20,
- },
- end: Position {
- line: 3,
- character: 29,
- },
- },
- new_text: "".into(),
- },
- TextEdit {
- range: Range {
- start: Position {
- line: 3,
- character: 56,
- },
- end: Position {
- line: 4,
- character: 24,
- },
- },
- new_text: "".into(),
- },
- TextEdit {
- range: Range {
- start: Position {
- line: 6,
- character: 1,
- },
- end: Position {
- line: 6,
- character: 1,
- },
- },
- new_text: "\n".into(),
- },
- ];
- let mut source = Rope::from_str(
- "impl Editor { // 0
- pub fn open(f: &Path) { // 1
-// 2
- let new = std::fs::read_to_string(f) // 3
- .map_err(anyhow::Error::from)?; // 4
- }
-}",
- );
- println!("{}", source);
-
- let transaction =
- generate_transaction_from_edits(&source, th.to_vec(), OffsetEncoding::Utf8);
- assert!(transaction.apply(&mut source));
- println!("{}", source);
- }
}
diff --git a/helix-lsp/src/transport.rs b/helix-lsp/src/transport.rs
index fa4966c4..088c617b 100644
--- a/helix-lsp/src/transport.rs
+++ b/helix-lsp/src/transport.rs
@@ -98,7 +98,7 @@ impl Transport {
buffer.clear();
if reader.read_line(buffer).await? == 0 {
return Err(Error::StreamClosed);
- }
+ };
// debug!("<- header {:?}", buffer);
@@ -133,14 +133,12 @@ impl Transport {
info!("{language_server_name} <- {msg}");
- // NOTE: We avoid using `?` here, since it would return early on error
- // and skip clearing `content`. By returning the result directly instead,
- // we ensure `content.clear()` is always called.
- let output = sonic_rs::from_slice(content).map_err(Into::into);
+ // try parsing as output (server response) or call (server request)
+ let output: serde_json::Result<ServerMessage> = serde_json::from_str(msg);
content.clear();
- output
+ Ok(output?)
}
async fn recv_server_error(
diff --git a/helix-term/Cargo.toml b/helix-term/Cargo.toml
index ab9f166b..f49c5a89 100644
--- a/helix-term/Cargo.toml
+++ b/helix-term/Cargo.toml
@@ -61,7 +61,7 @@ tokio-stream = "0.1"
futures-util = { version = "0.3", features = ["std", "async-await"], default-features = false }
arc-swap = { version = "1.7.1" }
termini = "1"
-indexmap = "2.12"
+indexmap = "2.11"
# Logging
fern = "0.7"
@@ -70,11 +70,7 @@ log = "0.4"
# File picker
nucleo.workspace = true
-# MSRV: update once the MSRV is >=1.85
-ignore = "=0.4.23"
-grep-regex = "=0.1.13"
-grep-searcher = "=0.1.14"
-grep-matcher = "=0.1.7"
+ignore.workspace = true
# markdown doc rendering
pulldown-cmark = { version = "0.13", default-features = false }
# file type detection
@@ -91,15 +87,18 @@ toml.workspace = true
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
+# ripgrep for global search
+grep-regex = "0.1.13"
+grep-searcher = "0.1.14"
+
dashmap = "6.0"
-tree-house = { workspace = true, features = ["fixtures"] }
[target.'cfg(windows)'.dependencies]
crossterm = { version = "0.28", features = ["event-stream"] }
[target.'cfg(not(windows))'.dependencies] # https://github.com/vorner/signal-hook/issues/100
signal-hook-tokio = { version = "0.3", features = ["futures-v0_3"] }
-libc = "0.2.177"
+libc = "0.2.176"
[build-dependencies]
helix-loader = { path = "../helix-loader" }
diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs
index 8c1db649..4aabbe7a 100644
--- a/helix-term/src/application.rs
+++ b/helix-term/src/application.rs
@@ -1058,8 +1058,21 @@ impl Application {
continue;
}
};
+ for watch in &ops.watchers {
+ if let lsp::GlobPattern::Relative(pattern) =
+ &watch.glob_pattern
+ {
+ let base_url = match &pattern.base_uri {
+ lsp::OneOf::Left(folder) => &folder.uri,
+ lsp::OneOf::Right(url) => url,
+ };
+ let Ok(base_dir) = base_url.to_file_path() else {
+ continue;
+ };
+ self.editor.file_watcher.add_root(&base_dir);
+ }
+ }
self.editor.language_servers.file_event_handler.register(
- client.id(),
Arc::downgrade(client),
reg.id,
ops,
diff --git a/helix-term/src/args.rs b/helix-term/src/args.rs
index 090c1192..9b1b4409 100644
--- a/helix-term/src/args.rs
+++ b/helix-term/src/args.rs
@@ -102,7 +102,6 @@ impl Args {
}
}
}
- "+" => line_number = usize::MAX,
arg if arg.starts_with('+') => {
match arg[1..].parse::<usize>() {
Ok(n) => line_number = n.saturating_sub(1),
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index 430d4430..8edf5944 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -3870,7 +3870,6 @@ fn goto_column_impl(cx: &mut Context, movement: Movement) {
let pos = graphemes::nth_next_grapheme_boundary(text, line_start, count - 1).min(line_end);
range.put_cursor(text, pos, movement == Movement::Extend)
});
- push_jump(view, doc);
doc.set_selection(view.id, selection);
}
@@ -3892,7 +3891,6 @@ fn goto_last_modification(cx: &mut Context) {
.selection(view.id)
.clone()
.transform(|range| range.put_cursor(text, pos, cx.editor.mode == Mode::Select));
- push_jump(view, doc);
doc.set_selection(view.id, selection);
}
}
@@ -3944,7 +3942,6 @@ fn goto_first_diag(cx: &mut Context) {
Some(diag) => Selection::single(diag.range.start, diag.range.end),
None => return,
};
- push_jump(view, doc);
doc.set_selection(view.id, selection);
view.diagnostics_handler
.immediately_show_diagnostic(doc, view.id);
@@ -3956,7 +3953,6 @@ fn goto_last_diag(cx: &mut Context) {
Some(diag) => Selection::single(diag.range.start, diag.range.end),
None => return,
};
- push_jump(view, doc);
doc.set_selection(view.id, selection);
view.diagnostics_handler
.immediately_show_diagnostic(doc, view.id);
@@ -3980,7 +3976,6 @@ fn goto_next_diag(cx: &mut Context) {
Some(diag) => Selection::single(diag.range.start, diag.range.end),
None => return,
};
- push_jump(view, doc);
doc.set_selection(view.id, selection);
view.diagnostics_handler
.immediately_show_diagnostic(doc, view.id);
@@ -4010,7 +4005,6 @@ fn goto_prev_diag(cx: &mut Context) {
Some(diag) => Selection::single(diag.range.end, diag.range.start),
None => return,
};
- push_jump(view, doc);
doc.set_selection(view.id, selection);
view.diagnostics_handler
.immediately_show_diagnostic(doc, view.id);
@@ -4041,7 +4035,6 @@ fn goto_first_change_impl(cx: &mut Context, reverse: bool) {
};
if hunk != Hunk::NONE {
let range = hunk_range(hunk, doc.text().slice(..));
- push_jump(view, doc);
doc.set_selection(view.id, Selection::single(range.anchor, range.head));
}
}
@@ -4097,7 +4090,6 @@ fn goto_next_change_impl(cx: &mut Context, direction: Direction) {
}
});
- push_jump(view, doc);
doc.set_selection(view.id, selection)
};
cx.editor.apply_motion(motion);
@@ -5920,7 +5912,6 @@ fn goto_ts_object_impl(cx: &mut Context, object: &'static str, direction: Direct
}
});
- push_jump(view, doc);
doc.set_selection(view.id, selection);
} else {
editor.set_status("Syntax-tree is not available in current buffer");
diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs
index 867ca4ac..cf052be2 100644
--- a/helix-term/src/commands/typed.rs
+++ b/helix-term/src/commands/typed.rs
@@ -68,44 +68,6 @@ impl CommandCompleter {
}
}
-fn exit(cx: &mut compositor::Context, args: Args, event: PromptEvent) -> anyhow::Result<()> {
- if event != PromptEvent::Validate {
- return Ok(());
- }
-
- if doc!(cx.editor).is_modified() {
- write_impl(
- cx,
- args.first(),
- WriteOptions {
- force: false,
- auto_format: !args.has_flag(WRITE_NO_FORMAT_FLAG.name),
- },
- )?;
- }
- cx.block_try_flush_writes()?;
- quit(cx, Args::default(), event)
-}
-
-fn force_exit(cx: &mut compositor::Context, args: Args, event: PromptEvent) -> anyhow::Result<()> {
- if event != PromptEvent::Validate {
- return Ok(());
- }
-
- if doc!(cx.editor).is_modified() {
- write_impl(
- cx,
- args.first(),
- WriteOptions {
- force: true,
- auto_format: !args.has_flag(WRITE_NO_FORMAT_FLAG.name),
- },
- )?;
- }
- cx.block_try_flush_writes()?;
- quit(cx, Args::default(), event)
-}
-
fn quit(cx: &mut compositor::Context, _args: Args, event: PromptEvent) -> anyhow::Result<()> {
log::debug!("quitting...");
@@ -1438,11 +1400,13 @@ fn reload(cx: &mut compositor::Context, _args: Args, event: PromptEvent) -> anyh
doc.reload(view, &cx.editor.diff_providers).map(|_| {
view.ensure_cursor_in_view(doc, scrolloff);
})?;
- if let Some(path) = doc.path() {
- cx.editor
- .language_servers
- .file_event_handler
- .file_changed(path.clone());
+ if !cfg!(any(target_os = "linux", target_os = "android")) {
+ if let Some(path) = doc.path() {
+ cx.editor
+ .language_servers
+ .file_event_handler
+ .file_changed(path.clone());
+ }
}
Ok(())
}
@@ -1484,11 +1448,13 @@ fn reload_all(cx: &mut compositor::Context, _args: Args, event: PromptEvent) ->
continue;
}
- if let Some(path) = doc.path() {
- cx.editor
- .language_servers
- .file_event_handler
- .file_changed(path.clone());
+ if !cfg!(any(target_os = "linux", target_os = "android")) {
+ if let Some(path) = doc.path() {
+ cx.editor
+ .language_servers
+ .file_event_handler
+ .file_changed(path.clone());
+ }
}
for view_id in view_ids {
@@ -2715,30 +2681,6 @@ const WRITE_NO_FORMAT_FLAG: Flag = Flag {
pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
TypableCommand {
- name: "exit",
- aliases: &["x", "xit"],
- doc: "Write changes to disk if the buffer is modified and then quit. Accepts an optional path (:exit some/path.txt).",
- fun: exit,
- completer: CommandCompleter::positional(&[completers::filename]),
- signature: Signature {
- positionals: (0, Some(1)),
- flags: &[WRITE_NO_FORMAT_FLAG],
- ..Signature::DEFAULT
- },
- },
- TypableCommand {
- name: "exit!",
- aliases: &["x!", "xit!"],
- doc: "Force write changes to disk, creating necessary subdirectories, if the buffer is modified and then quit. Accepts an optional path (:exit! some/path.txt).",
- fun: force_exit,
- completer: CommandCompleter::positional(&[completers::filename]),
- signature: Signature {
- positionals: (0, Some(1)),
- flags: &[WRITE_NO_FORMAT_FLAG],
- ..Signature::DEFAULT
- },
- },
- TypableCommand {
name: "quit",
aliases: &["q"],
doc: "Close the current view.",
@@ -2972,7 +2914,7 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
},
TypableCommand {
name: "write-quit",
- aliases: &["wq"],
+ aliases: &["wq", "x"],
doc: "Write changes to disk and close the current view. Accepts an optional path (:wq some/path.txt)",
fun: write_quit,
completer: CommandCompleter::positional(&[completers::filename]),
@@ -2984,7 +2926,7 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
},
TypableCommand {
name: "write-quit!",
- aliases: &["wq!"],
+ aliases: &["wq!", "x!"],
doc: "Write changes to disk and close the current view forcefully. Accepts an optional path (:wq! some/path.txt)",
fun: force_write_quit,
completer: CommandCompleter::positional(&[completers::filename]),
@@ -3033,7 +2975,7 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
TypableCommand {
name: "write-quit-all!",
aliases: &["wqa!", "xa!"],
- doc: "Forcefully write changes from all buffers to disk, creating necessary subdirectories, and close all views (ignoring unsaved changes).",
+ doc: "Write changes from all buffers to disk and close all views forcefully (ignoring unsaved changes).",
fun: force_write_all_quit,
completer: CommandCompleter::none(),
signature: Signature {
diff --git a/helix-term/src/events.rs b/helix-term/src/events.rs
index b0a42298..d25a271e 100644
--- a/helix-term/src/events.rs
+++ b/helix-term/src/events.rs
@@ -1,3 +1,4 @@
+use helix_core::file_watcher::FileSystemDidChange;
use helix_event::{events, register_event};
use helix_view::document::Mode;
use helix_view::events::{
@@ -27,4 +28,5 @@ pub fn register() {
register_event::<LanguageServerInitialized>();
register_event::<LanguageServerExited>();
register_event::<ConfigDidChange>();
+ register_event::<FileSystemDidChange>();
}
diff --git a/helix-term/src/handlers.rs b/helix-term/src/handlers.rs
index 18297bfe..3d72505b 100644
--- a/helix-term/src/handlers.rs
+++ b/helix-term/src/handlers.rs
@@ -14,6 +14,7 @@ pub use helix_view::handlers::{word_index, Handlers};
use self::document_colors::DocumentColorsHandler;
+mod auto_reload;
mod auto_save;
pub mod completion;
pub mod diagnostics;
@@ -25,7 +26,7 @@ mod snippet;
pub fn setup(config: Arc<ArcSwap<Config>>) -> Handlers {
events::register();
- let event_tx = completion::CompletionHandler::new(config).spawn();
+ let event_tx = completion::CompletionHandler::new(config.clone()).spawn();
let signature_hints = SignatureHelpHandler::new().spawn();
let auto_save = AutoSaveHandler::new().spawn();
let document_colors = DocumentColorsHandler::default().spawn();
@@ -51,5 +52,6 @@ pub fn setup(config: Arc<ArcSwap<Config>>) -> Handlers {
snippet::register_hooks(&handlers);
document_colors::register_hooks(&handlers);
prompt::register_hooks(&handlers);
+ auto_reload::register_hooks(&config.load().editor);
handlers
}
diff --git a/helix-term/src/handlers/auto_reload.rs b/helix-term/src/handlers/auto_reload.rs
new file mode 100644
index 00000000..34080bce
--- /dev/null
+++ b/helix-term/src/handlers/auto_reload.rs
@@ -0,0 +1,117 @@
+use std::io;
+use std::sync::atomic::{self, AtomicBool};
+use std::sync::Arc;
+use std::time::SystemTime;
+
+use helix_core::file_watcher::{EventType, FileSystemDidChange};
+use helix_event::register_hook;
+use helix_view::editor::Config;
+use helix_view::events::ConfigDidChange;
+
+use crate::job;
+
+struct AutoReload {
+ enable: AtomicBool,
+ prompt_if_modified: AtomicBool,
+}
+
+impl AutoReload {
+ pub fn refresh_config(&self, config: &Config) {
+ self.enable
+ .store(config.file_watcher.enable, atomic::Ordering::Relaxed);
+ self.prompt_if_modified
+ .store(config.file_watcher.enable, atomic::Ordering::Relaxed);
+ }
+
+ fn on_file_did_change(&self, event: &mut FileSystemDidChange) {
+ if !self.enable.load(atomic::Ordering::Relaxed) {
+ return;
+ }
+ let fs_events = event.fs_events.clone();
+ if !fs_events
+ .iter()
+ .any(|event| event.ty == EventType::Modified)
+ {
+ return;
+ }
+ job::dispatch_blocking(move |editor, _| {
+ let config = editor.config();
+ let mut vcs_reload = false;
+ for fs_event in &*fs_events {
+ if fs_event.ty != EventType::Modified {
+ continue;
+ }
+ vcs_reload |= editor.diff_providers.needs_reload(fs_event);
+ let Some(doc_id) = editor.document_id_by_path(fs_event.path.as_std_path()) else {
+ return;
+ };
+ let doc = doc_mut!(editor, &doc_id);
+ let mtime = match doc.path().unwrap().metadata() {
+ Ok(meta) => meta.modified().unwrap_or(SystemTime::now()),
+ Err(err) if err.kind() == io::ErrorKind::NotFound => continue,
+ Err(_) => SystemTime::now(),
+ };
+ if mtime == doc.last_saved_time {
+ continue;
+ }
+ if doc.is_modified() {
+ let msg = format!(
+ "{} auto-reload failed due to unsaved changes, use :reload to refresh",
+ doc.relative_path().unwrap().display()
+ );
+ editor.set_warning(msg);
+ } else {
+ let scrolloff = config.scrolloff;
+ let view = view_mut!(editor);
+ match doc.reload(view, &editor.diff_providers) {
+ Ok(_) => {
+ view.ensure_cursor_in_view(doc, scrolloff);
+ let msg = format!(
+ "{} auto-reload external changes",
+ doc.relative_path().unwrap().display()
+ );
+ editor.set_status(msg);
+ }
+ Err(err) => {
+ let doc = doc!(editor, &doc_id);
+ let msg = format!(
+ "{} auto-reload failed: {err}",
+ doc.relative_path().unwrap().display()
+ );
+ editor.set_error(msg);
+ }
+ }
+ }
+ }
+ if vcs_reload {
+ for doc in editor.documents.values_mut() {
+ let Some(path) = doc.path() else {
+ continue;
+ };
+ match editor.diff_providers.get_diff_base(path) {
+ Some(diff_base) => doc.set_diff_base(diff_base),
+ None => doc.diff_handle = None,
+ }
+ }
+ }
+ });
+ }
+}
+
+pub(super) fn register_hooks(config: &Config) {
+ let handler = Arc::new(AutoReload {
+ enable: config.auto_reload.enable.into(),
+ prompt_if_modified: config.auto_reload.prompt_if_modified.into(),
+ });
+ let handler_ = handler.clone();
+ register_hook!(move |event: &mut ConfigDidChange<'_>| {
+ // when a document is initially opened, request colors for it
+ handler_.refresh_config(event.new);
+ Ok(())
+ });
+ register_hook!(move |event: &mut FileSystemDidChange| {
+ // when a document is initially opened, request colors for it
+ handler.on_file_did_change(event);
+ Ok(())
+ });
+}
diff --git a/helix-term/src/health.rs b/helix-term/src/health.rs
index 52112bf9..dbf25e60 100644
--- a/helix-term/src/health.rs
+++ b/helix-term/src/health.rs
@@ -365,8 +365,8 @@ fn probe_parser(grammar_name: &str) -> std::io::Result<()> {
write!(stdout, "Tree-sitter parser: ")?;
match helix_loader::grammar::get_language(grammar_name) {
- Ok(Some(_)) => writeln!(stdout, "{}", "✓".green()),
- Ok(None) | Err(_) => writeln!(stdout, "{}", "None".yellow()),
+ Ok(_) => writeln!(stdout, "{}", "✓".green()),
+ Err(_) => writeln!(stdout, "{}", "None".yellow()),
}
}
diff --git a/helix-term/src/main.rs b/helix-term/src/main.rs
index bdca0c01..ca12de2a 100644
--- a/helix-term/src/main.rs
+++ b/helix-term/src/main.rs
@@ -75,8 +75,7 @@ FLAGS:
--vsplit Split all given files vertically into different windows
--hsplit Split all given files horizontally into different windows
-w, --working-dir <path> Specify an initial working directory
- +[N] Open the first given file at line number N, or the last line, if
- N is not specified.
+ +N Open the first given file at line number N
",
env!("CARGO_PKG_NAME"),
VERSION_AND_GIT_HASH,
diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs
index b25af107..14c12aec 100644
--- a/helix-term/src/ui/editor.rs
+++ b/helix-term/src/ui/editor.rs
@@ -1569,6 +1569,8 @@ impl Component for EditorView {
use helix_view::editor::Severity;
let style = if *severity == Severity::Error {
cx.editor.theme.get("error")
+ } else if *severity == Severity::Warning {
+ cx.editor.theme.get("warning")
} else {
cx.editor.theme.get("ui.text")
};
diff --git a/helix-term/src/ui/picker.rs b/helix-term/src/ui/picker.rs
index 4f77f8b9..ee4a163d 100644
--- a/helix-term/src/ui/picker.rs
+++ b/helix-term/src/ui/picker.rs
@@ -1048,23 +1048,23 @@ impl<I: 'static + Send + Sync, D: 'static + Send + Sync> Component for Picker<I,
let close_fn = |picker: &mut Self| {
// if the picker is very large don't store it as last_picker to avoid
// excessive memory consumption
- let callback: compositor::Callback =
- if picker.matcher.snapshot().item_count() > 1_000_000 {
- Box::new(|compositor: &mut Compositor, _ctx| {
- // remove the layer
- compositor.pop();
- })
- } else {
- // stop streaming in new items in the background, really we should
- // be restarting the stream somehow once the picker gets
- // reopened instead (like for an FS crawl) that would also remove the
- // need for the special case above but that is pretty tricky
- picker.version.fetch_add(1, atomic::Ordering::Relaxed);
- Box::new(|compositor: &mut Compositor, _ctx| {
- // remove the layer
- compositor.last_picker = compositor.pop();
- })
- };
+ let callback: compositor::Callback = if picker.matcher.snapshot().item_count() > 100_000
+ {
+ Box::new(|compositor: &mut Compositor, _ctx| {
+ // remove the layer
+ compositor.pop();
+ })
+ } else {
+ // stop streaming in new items in the background, really we should
+ // be restarting the stream somehow once the picker gets
+ // reopened instead (like for an FS crawl) that would also remove the
+ // need for the special case above but that is pretty tricky
+ picker.version.fetch_add(1, atomic::Ordering::Relaxed);
+ Box::new(|compositor: &mut Compositor, _ctx| {
+ // remove the layer
+ compositor.last_picker = compositor.pop();
+ })
+ };
EventResult::Consumed(Some(callback))
};
diff --git a/helix-term/tests/test/commands/write.rs b/helix-term/tests/test/commands/write.rs
index 4f44cd36..0cf09e1e 100644
--- a/helix-term/tests/test/commands/write.rs
+++ b/helix-term/tests/test/commands/write.rs
@@ -10,100 +10,6 @@ use helix_view::doc;
use super::*;
#[tokio::test(flavor = "multi_thread")]
-async fn test_exit_w_buffer_w_path() -> anyhow::Result<()> {
- let mut file = tempfile::NamedTempFile::new()?;
- let mut app = helpers::AppBuilder::new()
- .with_file(file.path(), None)
- .build()?;
- // Check for write operation on given path and edited buffer
- test_key_sequence(
- &mut app,
- Some("iBecause of the obvious threat to untold numbers of citizens due to the crisis that is even now developing, this radio station will remain on the air day and night.<ret><esc>:x<ret>"),
- None,
- true,
- )
- .await?;
-
- reload_file(&mut file).unwrap();
- let mut file_content = String::new();
- file.as_file_mut().read_to_string(&mut file_content)?;
-
- assert_eq!(
- LineFeedHandling::Native.apply("Because of the obvious threat to untold numbers of citizens due to the crisis that is even now developing, this radio station will remain on the air day and night.\n"),
- file_content
- );
-
- Ok(())
-}
-
-#[tokio::test(flavor = "multi_thread")]
-async fn test_exit_wo_buffer_w_path() -> anyhow::Result<()> {
- let mut file = tempfile::NamedTempFile::new()?;
- let mut app = helpers::AppBuilder::new()
- .with_file(file.path(), None)
- .build()?;
-
- helpers::run_event_loop_until_idle(&mut app).await;
-
- file.as_file_mut()
- .write_all("extremely important content".as_bytes())?;
- file.as_file_mut().flush()?;
- file.as_file_mut().sync_all()?;
-
- test_key_sequence(&mut app, Some(":x<ret>"), None, true).await?;
-
- reload_file(&mut file).unwrap();
- let mut file_content = String::new();
- file.read_to_string(&mut file_content)?;
- // check that nothing is written to file
- assert_eq!("extremely important content", file_content);
-
- Ok(())
-}
-
-#[tokio::test(flavor = "multi_thread")]
-async fn test_exit_wo_buffer_wo_path() -> anyhow::Result<()> {
- test_key_sequence(
- &mut AppBuilder::new().build()?,
- Some(":x<ret>"),
- Some(&|app| {
- assert!(!app.editor.is_err());
- }),
- true,
- )
- .await?;
-
- Ok(())
-}
-
-#[tokio::test(flavor = "multi_thread")]
-async fn test_exit_w_buffer_wo_file() -> anyhow::Result<()> {
- let mut file = tempfile::NamedTempFile::new()?;
- test_key_sequence(
- // try to write without destination
- &mut AppBuilder::new().build()?,
- Some("itest<esc>:x<ret>"),
- None,
- false,
- )
- .await?;
- test_key_sequence(
- // try to write with path succeeds
- &mut AppBuilder::new().build()?,
- Some(format!("iMicCheck<esc>:x {}<ret>", file.path().to_string_lossy()).as_ref()),
- Some(&|app| {
- assert!(!app.editor.is_err());
- }),
- true,
- )
- .await?;
-
- helpers::assert_file_has_content(&mut file, &LineFeedHandling::Native.apply("MicCheck"))?;
-
- Ok(())
-}
-
-#[tokio::test(flavor = "multi_thread")]
async fn test_write_quit_fail() -> anyhow::Result<()> {
let file = helpers::new_readonly_tempfile()?;
let mut app = helpers::AppBuilder::new()
@@ -238,7 +144,7 @@ async fn test_overwrite_protection() -> anyhow::Result<()> {
file.as_file_mut().flush()?;
file.as_file_mut().sync_all()?;
- test_key_sequence(&mut app, Some("iOverwriteData<esc>:x<ret>"), None, false).await?;
+ test_key_sequence(&mut app, Some(":x<ret>"), None, false).await?;
reload_file(&mut file).unwrap();
let mut file_content = String::new();
diff --git a/helix-vcs/Cargo.toml b/helix-vcs/Cargo.toml
index 3c9b1c7f..d27dd240 100644
--- a/helix-vcs/Cargo.toml
+++ b/helix-vcs/Cargo.toml
@@ -12,12 +12,13 @@ homepage.workspace = true
[dependencies]
helix-core = { path = "../helix-core" }
helix-event = { path = "../helix-event" }
+helix-stdx = { path = "../helix-stdx" }
tokio = { version = "1", features = ["rt", "rt-multi-thread", "time", "sync", "parking_lot", "macros"] }
parking_lot.workspace = true
arc-swap = { version = "1.7.1" }
-gix = { version = "0.74.1", features = ["attributes", "status"], default-features = false, optional = true }
+gix = { version = "0.73.0", features = ["attributes", "status"], default-features = false, optional = true }
imara-diff = "0.2.0"
anyhow = "1"
diff --git a/helix-vcs/src/git.rs b/helix-vcs/src/git.rs
index 6544c35c..1be71afa 100644
--- a/helix-vcs/src/git.rs
+++ b/helix-vcs/src/git.rs
@@ -162,7 +162,7 @@ fn status(repo: &Repository, f: impl Fn(Result<FileChange>) -> bool) -> Result<(
} => {
let path = work_dir.join(rela_path.to_path()?);
match status {
- EntryStatus::Conflict { .. } => FileChange::Conflict { path },
+ EntryStatus::Conflict(_) => FileChange::Conflict { path },
EntryStatus::Change(Change::Removed) => FileChange::Deleted { path },
EntryStatus::Change(Change::Modification { .. }) => {
FileChange::Modified { path }
diff --git a/helix-vcs/src/lib.rs b/helix-vcs/src/lib.rs
index 4c5f2036..e38cba6f 100644
--- a/helix-vcs/src/lib.rs
+++ b/helix-vcs/src/lib.rs
@@ -57,6 +57,12 @@ impl DiffProviderRegistry {
})
}
+ pub fn needs_reload(&self, fs_event: &helix_core::file_watcher::Event) -> bool {
+ self.providers
+ .iter()
+ .any(|provider| provider.needs_reload(fs_event))
+ }
+
/// Fire-and-forget changed file iteration. Runs everything in a background task. Keeps
/// iteration until `on_change` returns `false`.
pub fn for_each_changed_file(
@@ -102,6 +108,14 @@ enum DiffProvider {
}
impl DiffProvider {
+ pub fn needs_reload(&self, fs_event: &helix_core::file_watcher::Event) -> bool {
+ match self {
+ #[cfg(feature = "git")]
+ DiffProvider::Git => fs_event.path.as_std_path().ends_with(".git/HEAD"),
+ DiffProvider::None => false,
+ }
+ }
+
fn get_diff_base(&self, file: &Path) -> Result<Vec<u8>> {
match self {
#[cfg(feature = "git")]
diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs
index e52dbe0f..ec20bb75 100644
--- a/helix-view/src/document.rs
+++ b/helix-view/src/document.rs
@@ -187,7 +187,7 @@ pub struct Document {
// Last time we wrote to the file. This will carry the time the file was last opened if there
// were no saves.
- last_saved_time: SystemTime,
+ pub last_saved_time: SystemTime,
last_saved_revision: usize,
version: i32, // should be usize?
@@ -196,7 +196,7 @@ pub struct Document {
pub(crate) diagnostics: Vec<Diagnostic>,
pub(crate) language_servers: HashMap<LanguageServerName, Arc<Client>>,
- diff_handle: Option<DiffHandle>,
+ pub diff_handle: Option<DiffHandle>,
version_control_head: Option<Arc<ArcSwap<Box<str>>>>,
// when document was used for most-recent-used buffer picker
diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs
index 7f8cff9c..5c8d2542 100644
--- a/helix-view/src/editor.rs
+++ b/helix-view/src/editor.rs
@@ -45,6 +45,7 @@ pub use helix_core::diagnostic::Severity;
use helix_core::{
auto_pairs::AutoPairs,
diagnostic::DiagnosticProvider,
+ file_watcher::{self, Watcher},
syntax::{
self,
config::{AutoPairConfig, IndentationHeuristic, LanguageServerFeature, SoftWrap},
@@ -427,6 +428,8 @@ pub struct Config {
pub rainbow_brackets: bool,
/// Whether to enable Kitty Keyboard Protocol
pub kitty_keyboard_protocol: KittyKeyboardProtocolConfig,
+ pub auto_reload: AutoReloadConfig,
+ pub file_watcher: file_watcher::Config,
}
#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize, Clone, Copy)]
@@ -440,6 +443,22 @@ pub enum KittyKeyboardProtocolConfig {
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, Eq, PartialOrd, Ord)]
#[serde(default, rename_all = "kebab-case", deny_unknown_fields)]
+pub struct AutoReloadConfig {
+ pub enable: bool,
+ pub prompt_if_modified: bool,
+}
+
+impl Default for AutoReloadConfig {
+ fn default() -> Self {
+ AutoReloadConfig {
+ enable: true,
+ prompt_if_modified: false,
+ }
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, Eq, PartialOrd, Ord)]
+#[serde(default, rename_all = "kebab-case", deny_unknown_fields)]
pub struct SmartTabConfig {
pub enable: bool,
pub supersede_menu: bool,
@@ -1118,6 +1137,8 @@ impl Default for Config {
editor_config: true,
rainbow_brackets: false,
kitty_keyboard_protocol: Default::default(),
+ file_watcher: file_watcher::Config::default(),
+ auto_reload: AutoReloadConfig::default(),
}
}
}
@@ -1219,6 +1240,7 @@ pub struct Editor {
pub mouse_down_range: Option<Range>,
pub cursor_cache: CursorCache,
+ pub file_watcher: Watcher,
}
pub type Motion = Box<dyn Fn(&mut Editor)>;
@@ -1340,6 +1362,7 @@ impl Editor {
handlers,
mouse_down_range: None,
cursor_cache: CursorCache::default(),
+ file_watcher: Watcher::new(&conf.file_watcher),
}
}
@@ -1544,12 +1567,15 @@ impl Editor {
}
ls.did_rename(old_path, &new_path, is_dir);
}
- self.language_servers
- .file_event_handler
- .file_changed(old_path.to_owned());
- self.language_servers
- .file_event_handler
- .file_changed(new_path);
+
+ if !cfg!(any(target_os = "linux", target_os = "android")) {
+ self.language_servers
+ .file_event_handler
+ .file_changed(old_path.to_owned());
+ self.language_servers
+ .file_event_handler
+ .file_changed(new_path);
+ }
Ok(())
}
@@ -2018,8 +2044,10 @@ impl Editor {
let handler = self.language_servers.file_event_handler.clone();
let future = async move {
let res = doc_save_future.await;
- if let Ok(event) = &res {
- handler.file_changed(event.path.clone());
+ if !cfg!(any(target_os = "linux", target_os = "android")) {
+ if let Ok(event) = &res {
+ handler.file_changed(event.path.clone());
+ }
}
res
};
diff --git a/helix-view/src/handlers.rs b/helix-view/src/handlers.rs
index 6f3ad1ed..e2fed147 100644
--- a/helix-view/src/handlers.rs
+++ b/helix-view/src/handlers.rs
@@ -1,7 +1,8 @@
use completion::{CompletionEvent, CompletionHandler};
-use helix_event::send_blocking;
+use helix_event::{register_hook, send_blocking};
use tokio::sync::mpsc::Sender;
+use crate::events::ConfigDidChange;
use crate::handlers::lsp::SignatureHelpInvoked;
use crate::{DocumentId, Editor, ViewId};
@@ -59,4 +60,9 @@ impl Handlers {
pub fn register_hooks(handlers: &Handlers) {
lsp::register_hooks(handlers);
word_index::register_hooks(handlers);
+ // must be done here because the file watcher is in helix-core
+ register_hook!(move |event: &mut ConfigDidChange<'_>| {
+ event.editor.file_watcher.reload(&event.new.file_watcher);
+ Ok(())
+ });
}
diff --git a/helix-view/src/handlers/lsp.rs b/helix-view/src/handlers/lsp.rs
index 96ab4626..771d4b3b 100644
--- a/helix-view/src/handlers/lsp.rs
+++ b/helix-view/src/handlers/lsp.rs
@@ -248,9 +248,11 @@ impl Editor {
}
fs::write(path, [])?;
- self.language_servers
- .file_event_handler
- .file_changed(path.to_path_buf());
+ if !cfg!(any(target_os = "linux", target_os = "android")) {
+ self.language_servers
+ .file_event_handler
+ .file_changed(path.to_path_buf());
+ }
}
}
ResourceOp::Delete(op) => {
@@ -268,11 +270,13 @@ impl Editor {
} else {
fs::remove_dir(path)?
}
- self.language_servers
- .file_event_handler
- .file_changed(path.to_path_buf());
} else if path.is_file() {
fs::remove_file(path)?;
+ if !cfg!(any(target_os = "linux", target_os = "android")) {
+ self.language_servers
+ .file_event_handler
+ .file_changed(path.to_path_buf());
+ }
}
}
ResourceOp::Rename(op) => {
diff --git a/languages.toml b/languages.toml
index 2d1074aa..1ebd15ac 100644
--- a/languages.toml
+++ b/languages.toml
@@ -284,10 +284,6 @@ args = ["lsp"]
command = "docker-language-server"
args = ["start", "--stdio"]
-[language-server.kcl-lsp]
-command = "kcl-language-server"
-args = ["server", "--stdio"]
-
[[language]]
name = "rust"
scope = "source.rust"
@@ -344,7 +340,7 @@ args = { attachCommands = [ "platform select remote-gdb-server", "platform conne
[[grammar]]
name = "rust"
-source = { git = "https://github.com/tree-sitter/tree-sitter-rust", rev = "261b20226c04ef601adbdf185a800512a5f66291" }
+source = { git = "https://github.com/tree-sitter/tree-sitter-rust", rev = "1f63b33efee17e833e0ea29266dd3d713e27e321" }
[[language]]
name = "sway"
@@ -665,7 +661,7 @@ args = { console = "internalConsole", attachCommands = [ "platform select remote
[[grammar]]
name = "c"
-source = { git = "https://github.com/tree-sitter/tree-sitter-c", rev = "7fa1be1b694b6e763686793d97da01f36a0e5c12" }
+source = { git = "https://github.com/tree-sitter/tree-sitter-c", rev = "7175a6dd5fc1cee660dce6fe23f6043d75af424a" }
[[language]]
name = "cpp"
@@ -910,7 +906,7 @@ args = { program = "{0}", skipFiles = [ "<node_internals>/**" ] }
[[grammar]]
name = "javascript"
-source = { git = "https://github.com/tree-sitter/tree-sitter-javascript", rev = "3a837b6f3658ca3618f2022f8707e29739c91364" }
+source = { git = "https://github.com/tree-sitter/tree-sitter-javascript", rev = "f772967f7b7bc7c28f845be2420a38472b16a8ee" }
[[language]]
name = "jsx"
@@ -940,7 +936,7 @@ indent = { tab-width = 2, unit = " " }
[[grammar]]
name = "typescript"
-source = { git = "https://github.com/tree-sitter/tree-sitter-typescript", rev = "75b3874edb2dc714fb1fd77a32013d0f8699989f", subpath = "typescript" }
+source = { git = "https://github.com/tree-sitter/tree-sitter-typescript", rev = "b1bf4825d9eaa0f3bdeb1e52f099533328acfbdf", subpath = "typescript" }
[[language]]
name = "typespec"
@@ -973,7 +969,7 @@ indent = { tab-width = 2, unit = " " }
[[grammar]]
name = "tsx"
-source = { git = "https://github.com/tree-sitter/tree-sitter-typescript", rev = "75b3874edb2dc714fb1fd77a32013d0f8699989f", subpath = "tsx" }
+source = { git = "https://github.com/tree-sitter/tree-sitter-typescript", rev = "b1bf4825d9eaa0f3bdeb1e52f099533328acfbdf", subpath = "tsx" }
[[language]]
name = "css"
@@ -1169,7 +1165,6 @@ file-types = [
{ glob = "sway/config" },
{ glob = ".tmux.conf" },
{ glob = "tmux.conf" },
- { glob = ".sh_history" },
{ glob = ".bash_history" },
{ glob = ".bash_login" },
{ glob = ".bash_logout" },
@@ -1184,9 +1179,6 @@ file-types = [
{ glob = ".zimrc" },
{ glob = "APKBUILD" },
{ glob = ".bash_aliases" },
- { glob = "bash_completion" },
- { glob = "bash-completion/completions/*" },
- { glob = "bash_completion.d/*" },
{ glob = ".Renviron" },
{ glob = ".xprofile" },
{ glob = ".xsession" },
@@ -1304,7 +1296,7 @@ name = "lean"
scope = "source.lean"
injection-regex = "lean"
file-types = ["lean"]
-roots = [ "lakefile.lean", "lakefile.toml" ]
+roots = [ "lakefile.lean" ]
comment-token = "--"
block-comment-tokens = { start = "/-", end = "-/" }
language-servers = [ "lean" ]
@@ -1541,7 +1533,6 @@ file-types = [
{ glob = ".gem/credentials" },
{ glob = ".kube/config" },
{ glob = ".kube/kuberc" },
- { glob = "yarn.lock" },
"sublime-syntax"
]
comment-token = "#"
@@ -1569,7 +1560,7 @@ name = "haskell"
scope = "source.haskell"
injection-regex = "hs|haskell"
file-types = ["hs", "hs-boot", "hsc"]
-roots = ["Setup.hs", "stack.yaml", "cabal.project", "hie.yaml"]
+roots = ["Setup.hs", "stack.yaml", "cabal.project"]
shebangs = ["runhaskell", "stack"]
comment-token = "--"
block-comment-tokens = { start = "{-", end = "-}" }
@@ -1761,8 +1752,8 @@ source = { git = "https://github.com/tree-sitter-perl/tree-sitter-pod", rev = "0
[[language]]
name = "racket"
scope = "source.racket"
-file-types = ["rkt", "rktd", "rktl", "scrbl", "zuo"]
-shebangs = ["racket", "zuo"]
+file-types = ["rkt", "rktd", "rktl", "scrbl"]
+shebangs = ["racket"]
comment-token = ";"
indent = { tab-width = 2, unit = " " }
block-comment-tokens = { start = "#|", end = "|#" }
@@ -2062,7 +2053,7 @@ source = { git = "https://github.com/tree-sitter/tree-sitter-regex", rev = "e1cf
[[language]]
name = "git-config"
scope = "source.gitconfig"
-file-types = ["gitconfig", { glob = ".gitmodules" }, { glob = "gitconfig" }, { glob = ".gitconfig" }, { glob = ".git/config" }, { glob = ".config/git/config" }]
+file-types = ["gitconfig", { glob = ".gitmodules" }, { glob = ".gitconfig" }, { glob = ".git/config" }, { glob = ".config/git/config" }]
injection-regex = "git-config"
comment-token = "#"
indent = { tab-width = 4, unit = "\t" }
@@ -3000,77 +2991,67 @@ name = "xml"
scope = "source.xml"
injection-regex = "xml"
file-types = [
- "ascx",
+ "xml",
+ "mobileconfig",
+ "plist",
+ "xib",
+ "storyboard",
+ "svg",
+ "xsd",
+ "gml",
+ "xaml",
+ "gir",
+ "rss",
"atom",
- "axaml",
+ "opml",
+ "policy",
+ "ascx",
"axml",
+ "axaml",
"bpmn",
- "checkstyle",
"cpt",
"csl",
"csproj.user",
"dita",
"ditamap",
"dtml",
- "fods",
- "fodt",
"fxml",
- "gir",
- "glif",
- "gml",
- "gpx",
"iml",
"isml",
"jmx",
- "kml",
"launch",
"menu",
- "mobileconfig",
- "mpd",
- "musicxml",
"mxml",
- "ncx",
"nuspec",
- "opml",
"osc",
"osm",
- "plist",
- "policy",
"pt",
"publishsettings",
"pubxml",
"pubxml.user",
"rbxlx",
"rbxmx",
- "resx",
"rng",
- "rss",
"shproj",
- "smil",
- "storyboard",
- "sublime-snippet",
- "svg",
"tld",
+ { glob = "*.tm[Tt]heme" },
"tmx",
- "ui",
"vbproj.user",
"vcxproj",
"vcxproj.filters",
- "wixproj",
"wsdl",
"wxi",
"wxs",
- "xaml",
"xbl",
- "xib",
"xlf",
"xliff",
- "xml",
- "xmp",
- "xoml",
"xpdl",
- "xrc",
- "xsd",
+ "xul",
+ "xoml",
+ "musicxml",
+ "glif",
+ "ui",
+ "sublime-snippet",
"xsl",
"mpd",
"smil",
@@ -3079,10 +3060,6 @@ file-types = [
"fods",
"itermcolors",
"terminal",
- "xul",
- { glob = "*.tm[Ll]anguage" },
- { glob = "*.tm[Pp]references" },
- { glob = "*.tm[Tt]heme" },
]
block-comment-tokens = { start = "<!--", end = "-->" }
indent = { tab-width = 2, unit = " " }
@@ -4232,7 +4209,7 @@ language-servers = ["pest-language-server"]
[[grammar]]
name = "pest"
-source = { git = "https://github.com/pest-parser/tree-sitter-pest", rev = "c19629a0c50e6ca2485c3b154b1dde841a08d169" }
+source = { git = "https://github.com/pest-parser/tree-sitter-pest", rev = "a8a98a824452b1ec4da7f508386a187a2f234b85" }
[[language]]
name = "elisp"
@@ -4263,7 +4240,7 @@ language-servers = [
"ember-language-server",
]
indent = { tab-width = 2, unit = " " }
-grammar = "glimmer-javascript"
+grammar = "javascript"
[language.auto-pairs]
'<' = '>'
@@ -4272,10 +4249,6 @@ grammar = "glimmer-javascript"
"(" = ")"
'"' = '"'
-[[grammar]]
-name = "glimmer-javascript"
-source = { git = "https://github.com/ember-tooling/tree-sitter-glimmer-javascript", rev = "5cc865a2a0a77cbfaf5062c8fcf2a9919bd54f87" }
-
[[language]]
name = "gts"
scope = "source.gts"
@@ -4291,7 +4264,7 @@ language-servers = [
"ember-language-server",
]
indent = { tab-width = 2, unit = " " }
-grammar = "glimmer-typescript"
+grammar = "typescript"
[language.auto-pairs]
'<' = '>'
@@ -4300,10 +4273,6 @@ grammar = "glimmer-typescript"
"(" = ")"
'"' = '"'
-[[grammar]]
-name = "glimmer-typescript"
-source = { git = "https://github.com/ember-tooling/tree-sitter-glimmer-typescript", rev = "12d98944c1d5077b957cbdb90d663a7c4d50118c" }
-
[[language]]
name = "gherkin"
scope = "source.feature"
@@ -4918,37 +4887,3 @@ indent = { tab-width = 2, unit = " " }
[[grammar]]
name = "nearley"
source = { git = "https://github.com/mi2ebi/tree-sitter-nearley", rev = "12d01113e194c8e83f6341aab8c2a5f21db9cac9" }
-
-[[language]]
-name = "kcl"
-scope = "source.kcl"
-injection-regex = "kcl"
-file-types = ["kcl"]
-comment-tokens = "//"
-indent = { tab-width = 2, unit = " " }
-formatter = { command = "zoo" , args = ["kcl", "fmt", "-"] }
-language-servers = [ "kcl-lsp" ]
-block-comment-tokens = { start = "/*", end = "*/"}
-
-[[grammar]]
-name = "kcl"
-source = { git = "https://github.com/KittyCAD/tree-sitter-kcl", rev = "8905e0bdbf5870b50bc3f24345f1af27746f42e8"}
-
-[[language]]
-name = "bovex"
-scope = "source.bovex"
-file-types = ["bovex", "bibvex"]
-comment-tokens = []
-block-comment-tokens = [{start = "(*", end = "*)"}, {start = "[*", end = "*]"}]
-indent = {tab-width = 2, unit = " "}
-[language.auto-pairs]
-'(' = ')'
-'[' = ']'
-'{' = '}'
-'"' = '"'
-'“' = '”'
-'‘' = '’'
-
-[[grammar]]
-name = "bovex"
-source = { git = "https://github.com/mi2ebi/tree-sitter-bovex", rev = "de7657a9cc3525b9b77c6d268da09dad5b1346b0" }
diff --git a/runtime/queries/_javascript/tags.scm b/runtime/queries/_javascript/tags.scm
index 9c350cd2..a7bbd311 100644
--- a/runtime/queries/_javascript/tags.scm
+++ b/runtime/queries/_javascript/tags.scm
@@ -25,7 +25,7 @@
(comment)* @doc
.
[
- (function_expression
+ (function
name: (identifier) @name)
(function_declaration
name: (identifier) @name)
@@ -44,7 +44,7 @@
(lexical_declaration
(variable_declarator
name: (identifier) @name
- value: [(arrow_function) (function_expression)]) @definition.function)
+ value: [(arrow_function) (function)]) @definition.function)
(#strip! @doc "^[\\s\\*/]+|^[\\s\\*/]$")
(#select-adjacent! @doc @definition.function)
)
@@ -55,7 +55,7 @@
(variable_declaration
(variable_declarator
name: (identifier) @name
- value: [(arrow_function) (function_expression)]) @definition.function)
+ value: [(arrow_function) (function)]) @definition.function)
(#strip! @doc "^[\\s\\*/]+|^[\\s\\*/]$")
(#select-adjacent! @doc @definition.function)
)
@@ -66,12 +66,12 @@
(member_expression
property: (property_identifier) @name)
]
- right: [(arrow_function) (function_expression)]
+ right: [(arrow_function) (function)]
) @definition.function
(pair
key: (property_identifier) @name
- value: [(arrow_function) (function_expression)]) @definition.function
+ value: [(arrow_function) (function)]) @definition.function
(
(call_expression
diff --git a/runtime/queries/bovex/highlights.scm b/runtime/queries/bovex/highlights.scm
deleted file mode 100644
index cc4ffe0a..00000000
--- a/runtime/queries/bovex/highlights.scm
+++ /dev/null
@@ -1,88 +0,0 @@
-[(code_comment) (layout_comment)] @comment.block
-
-(do_decl "do" @keyword.control)
-(val_decl "val" @keyword.storage.type)
-(fun_decl ["fun" "and"] @keyword.storage.type)
-(datatype_decl ["datatype" "and"] @keyword.storage.type)
-(datatype_arm "of" @keyword.storage.type)
-(object_decl ["object" "of"] @keyword.storage.type)
-(type_decl "type" @keyword.storage.type)
-(local_decl ["local" "in" "end"] @keyword.storage.modifier)
-(open_decl "open" @keyword.control)
-(import_decl "import" @keyword.control.import)
-(with_expr ["with" "without"] @keyword.operator)
-(orelse_expr ["orelse" "otherwise"] @keyword.operator)
-(andalso_expr ["andalso" "andthen"] @keyword.operator)
-(fn_expr ["fn" "as"] @keyword.function)
-(if_expr ["if" "then" "else"] @keyword.control.conditional)
-(case_expr ["case" "of"] @keyword.control)
-(fail_expr "fail" @keyword.control)
-(let_expr ["let" "in" "end"] @keyword.storage.modifier)
-(pat "as" @keyword.operator)
-
-(boolean_lit) @constant.builtin.boolean
-(numeric_lit) @constant.numeric.integer
-(float_lit) @constant.numeric.float
-(string_lit) @string.quoted.double
-(backslash_escape) @constant.character.escape
-
-["=" ":" ","] @punctuation.delimiter
-["->" "=>"] @operator
-["(" ")" "[" "]" "{" "}"] @punctuation.bracket
-
-[(ident) (label)] @variable.other
-(type_ident) @type
-(atomic_pat (ident) @variable.other)
-(pat (app_pat (atomic_pat (ident) @variable.parameter)))
-
-(type_var) @type.parameter
-(atomic_type (type_ident) @type.builtin)
-[(record_type) (product_type) (app_type) (arrow_type)] @type
-
-(atomic_expr (ident) @variable.other)
-(project_expr) @variable.member
-(field_binding (label) @variable.member.private)
-(field_binding (expr) @variable.other)
-(record_pat (ident) @variable.member.private)
-
-(app_expr
- (app_expr (atomic_expr (ident) @function.call))
- (atomic_expr))
-(app_expr
- _
- [":=" "@" "::" "o" "==" "!=" "==." "!=."
- "<" "<=" ">" ">=" "<." "<=." ">." ">=."
- "+" "-" "+." "-." "*" "*." "/" "/." "div" "mod"
- "shl" "shr" "andb" "xorb" "orb"] @operator
- _)
-
-(app_expr
- (app_expr (atomic_expr (ident) @function.builtin (#eq? @function.builtin "b")))
- (atomic_expr (layout_lit (layout_content (layout_text) @markup.bold))))
-(app_expr
- (app_expr (atomic_expr (ident) @function.builtin (#eq? @function.builtin "it")))
- (atomic_expr (layout_lit (layout_content (layout_text) @markup.italic))))
-(app_expr
- (app_expr (atomic_expr (ident) @function.builtin (#eq? @function.builtin "rm")))
- (atomic_expr (layout_lit)))
-(app_expr
- (app_expr (atomic_expr (ident) @function.builtin (#match? @function.builtin "^(tt|courier|fixedersys)$")))
- (atomic_expr (layout_lit (layout_content (layout_text) @markup.raw.inline))))
-(app_expr
- (app_expr (atomic_expr (ident) @function.builtin (#eq? @function.builtin "title")))
- (atomic_expr (layout_lit (layout_content (layout_text) @markup.heading.1))))
-(app_expr
- (app_expr (atomic_expr (ident) @function.builtin (#eq? @function.builtin "section")))
- (atomic_expr (layout_lit (layout_content (layout_text) @markup.heading.2))))
-(app_expr
- (app_expr (atomic_expr (ident) @function.builtin (#eq? @function.builtin "subsection")))
- (atomic_expr (layout_lit (layout_content (layout_text) @markup.heading.3))))
-(app_expr
- (app_expr (atomic_expr (ident) @function.builtin (#eq? @function.builtin "subsubsection")))
- (atomic_expr (layout_lit (layout_content (layout_text) @markup.heading.4))))
-(app_expr
- (app_expr (atomic_expr (ident) @function.builtin (#eq? @function.builtin "paragraph")))
- (atomic_expr (layout_lit (layout_content (layout_text) @markup.heading.5))))
-(app_expr
- (app_expr (atomic_expr (ident) @function.builtin (#eq? @function.builtin "blockquote")))
- (atomic_expr (layout_lit (layout_content (layout_text) @markup.quote))))
diff --git a/runtime/queries/bovex/rainbows.scm b/runtime/queries/bovex/rainbows.scm
deleted file mode 100644
index f00c454f..00000000
--- a/runtime/queries/bovex/rainbows.scm
+++ /dev/null
@@ -1,11 +0,0 @@
-["(" ")" "[" "]" "{" "}"] @rainbow.bracket
-[
- (tuple_expr)
- (record_expr)
- (layout_lit)
- (layout_antiquote)
- (tuple_pat)
- (record_pat)
- (atomic_type)
- (record_type)
-] @rainbow.scope
diff --git a/runtime/queries/ecma/highlights.scm b/runtime/queries/ecma/highlights.scm
index 4ba74a4b..67052596 100644
--- a/runtime/queries/ecma/highlights.scm
+++ b/runtime/queries/ecma/highlights.scm
@@ -161,7 +161,7 @@
; Function and method definitions
;--------------------------------
-(function_expression
+(function
name: (identifier) @function)
(function_declaration
name: (identifier) @function)
@@ -172,27 +172,27 @@
(pair
key: (property_identifier) @function.method
- value: [(function_expression) (arrow_function)])
+ value: [(function) (arrow_function)])
(pair
key: (private_property_identifier) @function.method.private
- value: [(function_expression) (arrow_function)])
+ value: [(function) (arrow_function)])
(assignment_expression
left: (member_expression
property: (property_identifier) @function.method)
- right: [(function_expression) (arrow_function)])
+ right: [(function) (arrow_function)])
(assignment_expression
left: (member_expression
property: (private_property_identifier) @function.method.private)
- right: [(function_expression) (arrow_function)])
+ right: [(function) (arrow_function)])
(variable_declarator
name: (identifier) @function
- value: [(function_expression) (arrow_function)])
+ value: [(function) (arrow_function)])
(assignment_expression
left: (identifier) @function
- right: [(function_expression) (arrow_function)])
+ right: [(function) (arrow_function)])
; Function and method parameters
;-------------------------------
diff --git a/runtime/queries/ecma/injections.scm b/runtime/queries/ecma/injections.scm
index 71163c5c..8430994d 100644
--- a/runtime/queries/ecma/injections.scm
+++ b/runtime/queries/ecma/injections.scm
@@ -26,7 +26,7 @@
((call_expression
function: (identifier) @_template_function_name
- arguments: (template_string (string_fragment) @injection.content))
+ arguments: (template_string) @injection.content)
(#eq? @_template_function_name "gql")
(#set! injection.language "graphql"))
diff --git a/runtime/queries/ecma/locals.scm b/runtime/queries/ecma/locals.scm
index 594a5f50..345cf177 100644
--- a/runtime/queries/ecma/locals.scm
+++ b/runtime/queries/ecma/locals.scm
@@ -3,14 +3,10 @@
[
(statement_block)
+ (function)
(arrow_function)
- (function_expression)
(function_declaration)
(method_definition)
- (for_statement)
- (for_in_statement)
- (catch_clause)
- (finally_clause)
] @local.scope
; Definitions
diff --git a/runtime/queries/ecma/textobjects.scm b/runtime/queries/ecma/textobjects.scm
index 08c0307b..a19eb25b 100644
--- a/runtime/queries/ecma/textobjects.scm
+++ b/runtime/queries/ecma/textobjects.scm
@@ -1,7 +1,7 @@
(function_declaration
body: (_) @function.inside) @function.around
-(function_expression
+(function
body: (_) @function.inside) @function.around
(arrow_function
diff --git a/runtime/queries/jsonc/rainbows.scm b/runtime/queries/jsonc/rainbows.scm
deleted file mode 100644
index 41269219..00000000
--- a/runtime/queries/jsonc/rainbows.scm
+++ /dev/null
@@ -1 +0,0 @@
-; inherits: json
diff --git a/runtime/queries/kcl/highlights.scm b/runtime/queries/kcl/highlights.scm
deleted file mode 100644
index 61c24ade..00000000
--- a/runtime/queries/kcl/highlights.scm
+++ /dev/null
@@ -1,57 +0,0 @@
-;; Maps AST nodes (left) to highlighting classes (right)
-;; See https://docs.helix-editor.com/themes.html#scopes
-;; for the supported scopes.
-;; Don't forget to run the command `hx --grammar fetch` to fetch the grammars,
-;; and `hx --grammar build` to build any out-of-date grammars.
-
-"fn" @keyword.function
-"return" @keyword.control.return
-"import" @keyword.control.import
-"export" @keyword.control.import
-[
- "if"
- "else"
- ] @keyword.control.conditional
-(identifier) @variable
-
-;; highlight type names
-(type_name
- (identifier) @type
-) @type
-
-(fn_call
- callee: (identifier) @function
- (labeledArg
- label: (identifier) @variable.parameter
- )
-)
-
-
-;; operators
-(binary_operator) @operator
-(prefix_operator) @operator
-
-;; punctuation
-
-; ".." @punctuation.special
-
-"(" @punctuation.bracket
-")" @punctuation.bracket
-"[" @punctuation.bracket
-"]" @punctuation.bracket
-"{" @punctuation.bracket
-"}" @punctuation.bracket
-
-; "." @punctuation.delimiter
-"," @punctuation.delimiter
-; ":" @punctuation.delimiter
-; ";" @punctuation.delimiter
-
-;; literals
-(boolean) @constant.builtin.boolean
-(string) @string
-(number) @constant.numeric
-
-;; comments
-(shebang) @keyword.directive
-(comment) @comment
diff --git a/runtime/queries/kdl/highlights.scm b/runtime/queries/kdl/highlights.scm
index 9ba420a9..78e5acf4 100644
--- a/runtime/queries/kdl/highlights.scm
+++ b/runtime/queries/kdl/highlights.scm
@@ -1,15 +1,5 @@
-[
- (single_line_comment)
- (multi_line_comment)
-
- (node_comment)
- (node_field_comment)
-
- ; these do not show up as comments in Helix as they are also highlighted as
- ; normal nodes
- (node . (node_comment))
- (node_field . (node_field_comment))
-] @comment
+(single_line_comment) @comment
+(multi_line_comment) @comment
(node
(identifier) @variable)
diff --git a/runtime/queries/pest/highlights.scm b/runtime/queries/pest/highlights.scm
index 430382c9..9d6f13c2 100644
--- a/runtime/queries/pest/highlights.scm
+++ b/runtime/queries/pest/highlights.scm
@@ -39,14 +39,11 @@
] @operator
[
- "ANY"
- "DROP"
- "EOI"
- "NEWLINE"
+ "PUSH"
"PEEK"
- "PEEK_ALL"
"POP"
- "POP_ALL"
- "PUSH"
"SOI"
+ "EOI"
+ "ANY"
] @keyword
+
diff --git a/runtime/queries/python/highlights.scm b/runtime/queries/python/highlights.scm
index ad45d495..a8ec18c8 100644
--- a/runtime/queries/python/highlights.scm
+++ b/runtime/queries/python/highlights.scm
@@ -75,9 +75,6 @@
(lambda_parameters
(identifier) @variable.parameter)
-(keyword_argument
- name: (identifier) @variable.parameter)
-
; - Builtin
((identifier) @variable.builtin
(#any-of? @variable.builtin "self" "cls"))
diff --git a/runtime/queries/python/locals.scm b/runtime/queries/python/locals.scm
index 955ebc52..24800870 100644
--- a/runtime/queries/python/locals.scm
+++ b/runtime/queries/python/locals.scm
@@ -45,6 +45,3 @@
(identifier) @local.reference
-; don't make the name of kwargs locals
-(keyword_argument
- name: (identifier) @variable.parameter)
diff --git a/runtime/queries/rust/highlights.scm b/runtime/queries/rust/highlights.scm
index cc8380cb..3a4448ba 100644
--- a/runtime/queries/rust/highlights.scm
+++ b/runtime/queries/rust/highlights.scm
@@ -79,7 +79,11 @@
; Types
; -------
-(type_parameter
+(type_parameters
+ (type_identifier) @type.parameter)
+(constrained_type_parameter
+ left: (type_identifier) @type.parameter)
+(optional_type_parameter
name: (type_identifier) @type.parameter)
((type_arguments (type_identifier) @constant)
(#match? @constant "^[A-Z_]+$"))
@@ -112,7 +116,6 @@
; Comments
; -------
-(shebang) @comment
(line_comment) @comment.line
(block_comment) @comment.block
@@ -240,6 +243,10 @@
(type_cast_expression "as" @keyword.operator)
+((generic_type
+ type: (type_identifier) @keyword)
+ (#eq? @keyword "use"))
+
[
(crate)
(super)
diff --git a/runtime/queries/scheme/highlights.scm b/runtime/queries/scheme/highlights.scm
index 288fcfe9..ea35be5e 100644
--- a/runtime/queries/scheme/highlights.scm
+++ b/runtime/queries/scheme/highlights.scm
@@ -33,37 +33,6 @@
.
(symbol) @function)
-(list
- .
- (symbol) @function.builtin
- (#any-of? @function.builtin
- "caar" "cadr" "call-with-input-file" "call-with-output-file" "cdar" "cddr" "list"
- "open-input-file" "open-output-file" "with-input-from-file" "with-output-to-file" "*" "+" "-"
- "/" "<" "<=" "=" ">" ">=" "abs" "acos" "angle" "append" "apply" "asin" "assoc" "assq" "assv"
- "atan" "boolean?" "caaaar" "caaadr" "caaar" "caadar" "caaddr" "caadr" "cadaar" "cadadr" "cadar"
- "caddar" "cadddr" "caddr" "call-with-current-continuation" "call-with-values" "car" "cdaaar"
- "cdaadr" "cdaar" "cdadar" "cdaddr" "cdadr" "cddaar" "cddadr" "cddar" "cdddar" "cddddr" "cdddr"
- "cdr" "ceiling" "char->integer" "char-alphabetic?" "char-ci<=?" "char-ci<?" "char-ci=?"
- "char-ci>=?" "char-ci>?" "char-downcase" "char-lower-case?" "char-numeric?" "char-ready?"
- "char-upcase" "char-upper-case?" "char-whitespace?" "char<=?" "char<?" "char=?" "char>=?"
- "char>?" "char?" "close-input-port" "close-output-port" "complex?" "cons" "cos"
- "current-error-port" "current-input-port" "current-output-port" "denominator" "display"
- "dynamic-wind" "eof-object?" "eq?" "equal?" "eqv?" "eval" "even?" "exact->inexact" "exact?" "exp"
- "expt" "floor" "flush-output" "for-each" "force" "gcd" "imag-part" "inexact->exact" "inexact?"
- "input-port?" "integer->char" "integer?" "interaction-environment" "lcm" "length" "list->string"
- "list->vector" "list-ref" "list-tail" "list?" "load" "log" "magnitude" "make-polar"
- "make-rectangular" "make-string" "make-vector" "map" "max" "member" "memq" "memv" "min" "modulo"
- "negative?" "newline" "not" "null-environment" "null?" "number->string" "number?" "numerator"
- "odd?" "output-port?" "pair?" "peek-char" "positive?" "procedure?" "quotient" "rational?"
- "rationalize" "read" "read-char" "real-part" "real?" "remainder" "reverse" "round"
- "scheme-report-environment" "set-car!" "set-cdr!" "sin" "sqrt" "string" "string->list"
- "string->number" "string->symbol" "string-append" "string-ci<=?" "string-ci<?" "string-ci=?"
- "string-ci>=?" "string-ci>?" "string-copy" "string-fill!" "string-length" "string-ref"
- "string-set!" "string<=?" "string<?" "string=?" "string>=?" "string>?" "string?" "substring"
- "symbol->string" "symbol?" "tan" "transcript-off" "transcript-on" "truncate" "values" "vector"
- "vector->list" "vector-fill!" "vector-length" "vector-ref" "vector-set!" "vector?" "write"
- "write-char" "zero?"))
-
; special forms
(list
@@ -136,3 +105,34 @@
"syntax-rules" "unquote" "begin" "quote" "let-syntax" "and" "if" "quasiquote" "letrec" "delay"
"or" "when" "unless" "identifier-syntax" "assert" "library" "export" "import" "rename" "only"
"except" "prefix" "define-values"))
+
+(list
+ .
+ (symbol) @function.builtin
+ (#any-of? @function.builtin
+ "caar" "cadr" "call-with-input-file" "call-with-output-file" "cdar" "cddr" "list"
+ "open-input-file" "open-output-file" "with-input-from-file" "with-output-to-file" "*" "+" "-"
+ "/" "<" "<=" "=" ">" ">=" "abs" "acos" "angle" "append" "apply" "asin" "assoc" "assq" "assv"
+ "atan" "boolean?" "caaaar" "caaadr" "caaar" "caadar" "caaddr" "caadr" "cadaar" "cadadr" "cadar"
+ "caddar" "cadddr" "caddr" "call-with-current-continuation" "call-with-values" "car" "cdaaar"
+ "cdaadr" "cdaar" "cdadar" "cdaddr" "cdadr" "cddaar" "cddadr" "cddar" "cdddar" "cddddr" "cdddr"
+ "cdr" "ceiling" "char->integer" "char-alphabetic?" "char-ci<=?" "char-ci<?" "char-ci=?"
+ "char-ci>=?" "char-ci>?" "char-downcase" "char-lower-case?" "char-numeric?" "char-ready?"
+ "char-upcase" "char-upper-case?" "char-whitespace?" "char<=?" "char<?" "char=?" "char>=?"
+ "char>?" "char?" "close-input-port" "close-output-port" "complex?" "cons" "cos"
+ "current-error-port" "current-input-port" "current-output-port" "denominator" "display"
+ "dynamic-wind" "eof-object?" "eq?" "equal?" "eqv?" "eval" "even?" "exact->inexact" "exact?" "exp"
+ "expt" "floor" "flush-output" "for-each" "force" "gcd" "imag-part" "inexact->exact" "inexact?"
+ "input-port?" "integer->char" "integer?" "interaction-environment" "lcm" "length" "list->string"
+ "list->vector" "list-ref" "list-tail" "list?" "load" "log" "magnitude" "make-polar"
+ "make-rectangular" "make-string" "make-vector" "map" "max" "member" "memq" "memv" "min" "modulo"
+ "negative?" "newline" "not" "null-environment" "null?" "number->string" "number?" "numerator"
+ "odd?" "output-port?" "pair?" "peek-char" "positive?" "procedure?" "quotient" "rational?"
+ "rationalize" "read" "read-char" "real-part" "real?" "remainder" "reverse" "round"
+ "scheme-report-environment" "set-car!" "set-cdr!" "sin" "sqrt" "string" "string->list"
+ "string->number" "string->symbol" "string-append" "string-ci<=?" "string-ci<?" "string-ci=?"
+ "string-ci>=?" "string-ci>?" "string-copy" "string-fill!" "string-length" "string-ref"
+ "string-set!" "string<=?" "string<?" "string=?" "string>=?" "string>?" "string?" "substring"
+ "symbol->string" "symbol?" "tan" "transcript-off" "transcript-on" "truncate" "values" "vector"
+ "vector->list" "vector-fill!" "vector-length" "vector-ref" "vector-set!" "vector?" "write"
+ "write-char" "zero?"))
diff --git a/runtime/queries/unison/rainbows.scm b/runtime/queries/unison/rainbows.scm
deleted file mode 100644
index 1721dc55..00000000
--- a/runtime/queries/unison/rainbows.scm
+++ /dev/null
@@ -1,10 +0,0 @@
-[
- (literal_list)
- (parenthesized_or_tuple_pattern)
-] @rainbow.scope
-
-[
- "(" ")"
- "{" "}"
- "[" "]"
-] @rainbow.bracket
diff --git a/runtime/queries/unison/tags.scm b/runtime/queries/unison/tags.scm
deleted file mode 100644
index 2834748a..00000000
--- a/runtime/queries/unison/tags.scm
+++ /dev/null
@@ -1,10 +0,0 @@
-(term_definition
- name: (regular_identifier) @name) @definition.function
-
-(type_declaration
- (type_kw)
- (type_constructor
- ((type_name (regular_identifier) @name)) @definition.type))
-
-(ability_declaration
- (ability_name) @type _) @definition.type
diff --git a/runtime/themes/andromeda.toml b/runtime/themes/andromeda.toml
deleted file mode 100644
index c9364e13..00000000
--- a/runtime/themes/andromeda.toml
+++ /dev/null
@@ -1,186 +0,0 @@
-
-# Interface colors
-"ui.background" = { bg = "background" }
-"ui.background.separator" = { fg = "muted" }
-"ui.cursor" = { fg = "background", bg = "cursor" }
-"ui.cursor.normal" = { fg = "background", bg = "cursor" }
-"ui.cursor.insert" = { fg = "background", bg = "accent" }
-"ui.cursor.select" = { fg = "background", bg = "purple" }
-"ui.cursor.match" = { fg = "background", bg = "yellow" }
-"ui.cursor.primary" = { fg = "background", bg = "cursor" }
-"ui.cursor.primary.normal" = { fg = "background", bg = "cursor" }
-"ui.cursor.primary.insert" = { fg = "background", bg = "accent" }
-"ui.cursor.primary.select" = { fg = "background", bg = "purple" }
-
-"ui.gutter" = { bg = "background" }
-"ui.gutter.selected" = { bg = "line_highlight" }
-"ui.linenr" = { fg = "line_numbers" }
-"ui.linenr.selected" = { fg = "accent", modifiers = ["bold"] }
-
-"ui.statusline" = { fg = "foreground", bg = "background" }
-"ui.statusline.inactive" = { fg = "muted", bg = "background" }
-"ui.statusline.normal" = { fg = "background", bg = "accent" }
-"ui.statusline.insert" = { fg = "background", bg = "green" }
-"ui.statusline.select" = { fg = "background", bg = "purple" }
-
-"ui.popup" = { fg = "foreground", bg = "popup_bg" }
-"ui.popup.info" = { fg = "foreground", bg = "popup_bg" }
-"ui.window" = { fg = "muted" }
-"ui.help" = { fg = "foreground", bg = "popup_bg" }
-
-"ui.text" = { fg = "foreground" }
-"ui.text.focus" = { fg = "accent", modifiers = ["bold"] }
-"ui.text.inactive" = { fg = "muted" }
-"ui.text.info" = { fg = "foreground" }
-
-"ui.virtual.ruler" = { bg = "line_highlight" }
-"ui.virtual.whitespace" = { fg = "muted" }
-"ui.virtual.indent-guide" = { fg = "muted" }
-"ui.virtual.inlay-hint" = { fg = "hint" }
-"ui.virtual.jump-label" = { fg = "white", bg = "background" }
-
-"ui.menu" = { fg = "foreground", bg = "popup_bg" }
-"ui.menu.selected" = { fg = "background", bg = "accent" }
-"ui.menu.scroll" = { fg = "muted", bg = "background" }
-
-"ui.selection" = { bg = "selection_background" }
-"ui.selection.primary" = { bg = "selection_background" }
-"ui.highlight" = { bg = "line_highlight" }
-"ui.cursorline.primary" = { bg = "line_highlight" }
-"ui.cursorline.secondary" = { bg = "line_highlight" }
-
-# Diagnostics
-"warning" = { fg = "warning" }
-"error" = { fg = "error" }
-"info" = { fg = "info" }
-"hint" = { fg = "hint" }
-"diagnostic" = { modifiers = ["underlined"] }
-"diagnostic.hint" = { fg = "hint", modifiers = ["underlined"] }
-"diagnostic.info" = { fg = "info", modifiers = ["underlined"] }
-"diagnostic.warning" = { fg = "warning", modifiers = ["underlined"] }
-"diagnostic.error" = { fg = "error", modifiers = ["underlined"] }
-"diagnostic.unnecessary" = { fg = "muted", modifiers = ["dim"] }
-
-# Syntax highlighting
-"comment" = { fg = "comment", modifiers = ["italic"] }
-"constant" = { fg = "red" }
-"constant.character" = { fg = "green" }
-"constant.character.escape" = { fg = "yellow" }
-"constant.numeric" = { fg = "orange" }
-"constant.builtin" = { fg = "red" }
-
-"string" = { fg = "green" }
-"string.regexp" = { fg = "blue" }
-"string.special" = { fg = "yellow" }
-
-"type" = { fg = "yellow" }
-"type.builtin" = { fg = "yellow" }
-"type.enum" = { fg = "yellow" }
-"type.parameter" = { fg = "orange" }
-
-"constructor" = { fg = "red" }
-"function" = { fg = "yellow" }
-"function.builtin" = { fg = "yellow" }
-"function.method" = { fg = "yellow" }
-"function.macro" = { fg = "purple" }
-
-"variable" = { fg = "cyan" }
-"variable.builtin" = { fg = "red" }
-"variable.parameter" = { fg = "orange" }
-"variable.other.member" = { fg = "cyan" }
-
-"keyword" = { fg = "purple" }
-"keyword.control" = { fg = "purple" }
-"keyword.control.conditional" = { fg = "purple" }
-"keyword.control.repeat" = { fg = "purple" }
-"keyword.control.import" = { fg = "purple" }
-"keyword.control.return" = { fg = "purple" }
-"keyword.control.exception" = { fg = "purple" }
-"keyword.operator" = { fg = "red" }
-"keyword.directive" = { fg = "purple" }
-"keyword.function" = { fg = "purple" }
-"keyword.storage" = { fg = "purple" }
-"keyword.storage.type" = { fg = "purple" }
-"keyword.storage.modifier" = { fg = "purple" }
-
-"operator" = { fg = "red" }
-"punctuation" = { fg = "foreground" }
-"punctuation.delimiter" = { fg = "foreground" }
-"punctuation.bracket" = { fg = "foreground" }
-"punctuation.special" = { fg = "hot_pink" }
-
-"tag" = { fg = "hot_pink" }
-"attribute" = { fg = "orange" }
-"namespace" = { fg = "yellow" }
-"module" = { fg = "yellow" }
-"special" = { fg = "hot_pink" }
-
-# Markup
-"markup.heading" = { fg = "hot_pink", modifiers = ["bold"] }
-"markup.heading.marker" = { fg = "hot_pink" }
-"markup.list" = { fg = "yellow" }
-"markup.list.marker" = { fg = "hot_pink" }
-"markup.bold" = { fg = "orange", modifiers = ["bold"] }
-"markup.italic" = { fg = "purple", modifiers = ["italic"] }
-"markup.strikethrough" = { modifiers = ["crossed_out"] }
-"markup.link.url" = { fg = "blue", modifiers = ["underlined"] }
-"markup.link.text" = { fg = "cyan" }
-"markup.quote" = { fg = "comment", modifiers = ["italic"] }
-"markup.raw" = { fg = "green" }
-"markup.raw.block" = { fg = "green" }
-
-# Diff
-"diff.plus" = { fg = "diff_add" }
-"diff.minus" = { fg = "diff_delete" }
-"diff.delta" = { fg = "diff_change" }
-
-# Color palette
-[palette]
-# Main colors
-white = "#FFFFFF"
-background = "#23262E"
-foreground = "#D5CED9"
-cursor = "#FFFFFF"
-
-# UI colors
-line_highlight = "#2e323d"
-selection_background = "#3D4352"
-line_numbers = "#746f77"
-muted = "#746f77"
-popup_bg = "#20232A"
-
-# Accent colors
-accent = "#00e8c6" # Cyan
-cyan = "#00e8c6" # Cyan
-orange = "#f39c12" # Orange
-yellow = "#FFE66D" # Yellow
-purple = "#c74ded" # Purple
-hot_pink = "#f92672" # Hot Pink
-blue = "#7cb7ff" # Blue
-red = "#ee5d43" # Red
-green = "#96E072" # Green
-
-# Syntax colors
-comment = "#A0A1A7"
-string = "#96E072"
-number = "#f39c12"
-keyword = "#c74ded"
-function = "#FFE66D"
-variable = "#00e8c6"
-type = "#FFE66D"
-constant = "#ee5d43"
-operator = "#ee5d43"
-tag = "#f92672"
-attribute = "#f39c12"
-punctuation = "#D5CED9"
-
-# Diagnostic colors
-error = "#FC644D"
-warning = "#FF9F2E"
-info = "#00b0ff"
-hint = "#746f77"
-
-# Diff colors
-diff_add = "#96E072"
-diff_delete = "#FC644D"
-diff_change = "#FFE66D"
diff --git a/runtime/themes/nord.toml b/runtime/themes/nord.toml
index db7b6190..e2872d4f 100644
--- a/runtime/themes/nord.toml
+++ b/runtime/themes/nord.toml
@@ -5,7 +5,7 @@
## SYNTAX HIGHLIGHTING
# Constants
-"constant" = "nord4"
+"constant" = "nord4"
"constant.builtin" = "nord9"
"constant.builtin.boolean" = "nord9"
"constant.builtin.character" = "nord15"
@@ -110,7 +110,7 @@
"ui.linenr.selected" = "nord5"
# Cursor
-"ui.cursor" = { fg = "nord4", modifiers = ["reversed"] }
+"ui.cursor" = { fg = "nord4", modifiers = [ "reversed" ] }
"ui.cursorcolumn.primary" = { bg = "nord1" }
"ui.cursorline.primary" = { bg = "nord1" }
"ui.cursor.match" = { bg = "nord3" }
@@ -119,7 +119,7 @@
"ui.highlight" = { fg = "nord8", bg = "nord2" }
# Statusline
-"ui.statusline" = { bg = "nord1" }
+"ui.statusline" = { bg = "nord1" }
"ui.statusline.inactive" = { fg = "nord8", bg = "nord1" }
"ui.statusline.insert" = { fg = "nord1", bg = "nord6" }
"ui.statusline.normal" = { fg = "nord1", bg = "nord8" }
@@ -136,9 +136,7 @@
# Bufferline
"ui.bufferline" = { fg = "nord5", bg = "nord1" }
-"ui.bufferline.active" = { fg = "nord6", bg = "nord2", underline = { color = "nord8", style = "line" }, modifiers = [
- "italic",
-] }
+"ui.bufferline.active" = { fg = "nord6", bg = "nord2", underline = { color = "nord8", style = "line" }, modifiers = [ "italic" ] }
# Markup
"markup.heading" = "nord8"
@@ -149,51 +147,48 @@
"markup.link.text" = "nord8"
"markup.raw" = "nord7"
-# Rainbow brackets
-rainbow = ["nord13", "nord15", "nord14", "nord12"]
-
[palette]
# 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.
#
# The origin color or the Polar Night palette
-nord0 = "#2e3440"
+nord0 = "#2e3440"
# A brighter shade color based on nord0
-nord1 = "#3B4252"
+nord1 = "#3B4252"
# An even more brighter shade color of nord0
-nord2 = "#434C5E"
+nord2 = "#434C5E"
# The brightest shade color based on nord0
-nord3 = "#4C566A"
+nord3 = "#4C566A"
# 10% brighter for comments, see https://github.com/nordtheme/nord/issues/94
-nord3_bright = "#616e88"
+nord3_bright = "#616e88"
# Snow Storm is made up of three bright colors that are commonly used for text colors or base UI elements in bright ambiance designs.
# The origin color or the Snow Storm palette
-nord4 = "#D8DEE9"
+nord4 = "#D8DEE9"
# A brighter shade color of nord4
-nord5 = "#E5E9F0"
+nord5 = "#E5E9F0"
# The brightest shade color based on nord4
-nord6 = "#ECEFF4"
+nord6 = "#ECEFF4"
# Frost can be described as the heart palette of Nord, a group of four bluish colors that are commonly used for primary UI component and text highlighting and essential code syntax elements.
#
# A calm and highly contrasted color reminiscent of frozen polar water
-nord7 = "#8FBCBB"
+nord7 = "#8FBCBB"
# The bright and shiny primary accent color reminiscent of pure and clear ice
-nord8 = "#88C0D0"
+nord8 = "#88C0D0"
# A more darkened and less saturated color reminiscent of arctic waters
-nord9 = "#81A1C1"
+nord9 = "#81A1C1"
# A dark and intensive color reminiscent of the deep arctic ocean
-nord10 = "#5E81AC"
+nord10 = "#5E81AC"
# Aurora consists of five colorful components reminiscent of the "Aurora borealis", sometimes referred to as polar lights or northern lights.
#
# Red
-nord11 = "#BF616A"
+nord11 = "#BF616A"
# Orange
-nord12 = "#D08770"
+nord12 = "#D08770"
# Yellow
-nord13 = "#EBCB8B"
+nord13 = "#EBCB8B"
# Green
-nord14 = "#A3BE8C"
+nord14 = "#A3BE8C"
# Purple
-nord15 = "#B48EAD"
+nord15 = "#B48EAD"
diff --git a/runtime/themes/ttox_soft.toml b/runtime/themes/ttox_soft.toml
deleted file mode 100644
index b4fe71cb..00000000
--- a/runtime/themes/ttox_soft.toml
+++ /dev/null
@@ -1,37 +0,0 @@
-# Author : Samuel Guyah <[email protected]>
-
-"ui.selection" = { fg = "white", bg = "gray" }
-"ui.cursor" = { fg = "black", bg = "light-gray" }
-"ui.cursor.primary" = { fg = "black", bg = "light-gray" }
-"ui.cursor.match" = { modifiers = ["underlined"] }
-"ui.background.separator" = "gray"
-"ui.linenr" = "gray"
-"ui.linenr.selected" = { fg = "white", bg = "gray" }
-"ui.statusline" = { bg = "black", fg = "white" }
-"ui.menu" = { fg = "white", bg = "black" }
-"ui.menu.selected" = { bg = "light-gray", fg = "black" }
-"ui.popup" = { fg = "white", bg = "black" }
-"ui.help" = { fg = "white", bg = "black" }
-"ui.virtual.ruler" = { underline = { style = "line" } }
-"ui.bufferline" = { fg = "white", bg = "black" }
-"ui.bufferline.active" = { fg = "black", bg = "white" }
-"ui.bufferline.background" = { bg = "black" }
-
-
-"string" = { fg = "light-green" }
-"constant" = { fg = "light-cyan" }
-"comment" = { fg = "light-magenta" }
-
-"diff.plus" = "green"
-"diff.minus" = "red"
-"diff.delta" = "gray"
-
-"warning" = { fg = "light-yellow" }
-"error" = { fg = "light-red" }
-"hint" = { fg = "light-blue" }
-
-"diagnostic.warning" = { fg = "light-yellow" }
-"diagnostic.error" = { fg = "light-red" }
-"diagnostic.hint" = { fg = "light-blue" }
-"diagnostic.unnecessary" = { modifiers = ["dim"] }
-"diagnostic.deprecated" = { modifiers = ["crossed_out"] }
diff --git a/runtime/tutor b/runtime/tutor
index 30c0f102..54a4dde2 100644
--- a/runtime/tutor
+++ b/runtime/tutor
@@ -337,7 +337,7 @@
1. Move the cursor to the line marked '-->' below.
2. Type 2w to move 2 words forward.
3. Type 3e to move to the end of the third word forward.
- 4. Type 2b to move 2 words backwards.
+ 4. Type 2b to move 2 words backwards
5. Try the above with different numbers.
--> This is just a line with words you can move around in.
@@ -755,7 +755,7 @@
1. Move the cursor to the line marked '-->' below.
2. Type w to select "watermelons" and then y to yank it.
3. Select "oranges" with w.
- 4. Type R to replace "oranges" with "watermelons".
+ 4. Type R to replace "oranges" with "watermelons"
--> I like watermelons because oranges are refreshing.
diff --git a/rust-toolchain.toml b/rust-toolchain.toml
new file mode 100644
index 00000000..74c6fc7a
--- /dev/null
+++ b/rust-toolchain.toml
@@ -0,0 +1,3 @@
+[toolchain]
+channel = "1.82.0"
+components = ["rustfmt", "rust-src", "clippy"]