Unnamed repository; edit this file 'description' to name the repository.
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 @@ -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" @@ -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). | @@ -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": { @@ -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(®istration_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(®istration_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"] |