Merge branch 'master' into force_move

This commit is contained in:
5-pebbles 2024-09-01 11:59:34 -04:00
commit 84ff01ed48
69 changed files with 2260 additions and 448 deletions

280
Cargo.lock generated
View File

@ -136,9 +136,12 @@ checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
[[package]]
name = "cc"
version = "1.1.7"
version = "1.1.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc"
checksum = "57b6a275aa2903740dc87da01c62040406b8812552e97129a63ea8850a17c6e6"
dependencies = [
"shlex",
]
[[package]]
name = "cfg-if"
@ -271,6 +274,7 @@ dependencies = [
"crossterm_winapi",
"filedescriptor",
"futures-core",
"libc",
"mio",
"parking_lot",
"rustix",
@ -345,15 +349,6 @@ dependencies = [
"parking_lot_core",
]
[[package]]
name = "deranged"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
dependencies = [
"powerfmt",
]
[[package]]
name = "dunce"
version = "1.0.5"
@ -541,9 +536,9 @@ checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e"
[[package]]
name = "gix"
version = "0.64.0"
version = "0.66.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d78414d29fcc82329080166077e0f7689f4016551fdb334d787c3d040fe2634f"
checksum = "9048b8d1ae2104f045cb37e5c450fc49d5d8af22609386bfc739c11ba88995eb"
dependencies = [
"gix-actor",
"gix-attributes",
@ -563,7 +558,6 @@ dependencies = [
"gix-ignore",
"gix-index",
"gix-lock",
"gix-macros",
"gix-object",
"gix-odb",
"gix-pack",
@ -590,9 +584,9 @@ dependencies = [
[[package]]
name = "gix-actor"
version = "0.31.5"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0e454357e34b833cc3a00b6efbbd3dd4d18b24b9fb0c023876ec2645e8aa3f2"
checksum = "fc19e312cd45c4a66cd003f909163dc2f8e1623e30a0c0c6df3776e89b308665"
dependencies = [
"bstr",
"gix-date",
@ -604,9 +598,9 @@ dependencies = [
[[package]]
name = "gix-attributes"
version = "0.22.3"
version = "0.22.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e37ce99c7e81288c28b703641b6d5d119aacc45c1a6b247156e6249afa486257"
checksum = "ebccbf25aa4a973dd352564a9000af69edca90623e8a16dad9cbc03713131311"
dependencies = [
"bstr",
"gix-glob",
@ -639,9 +633,9 @@ dependencies = [
[[package]]
name = "gix-command"
version = "0.3.8"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d76867867da891cbe32021ad454e8cae90242f6afb06762e4dd0d357afd1d7b"
checksum = "dff2e692b36bbcf09286c70803006ca3fd56551a311de450be317a0ab8ea92e7"
dependencies = [
"bstr",
"gix-path",
@ -665,9 +659,9 @@ dependencies = [
[[package]]
name = "gix-config"
version = "0.38.0"
version = "0.40.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28f53fd03d1bf09ebcc2c8654f08969439c4556e644ca925f27cf033bc43e658"
checksum = "78e797487e6ca3552491de1131b4f72202f282fb33f198b1c34406d765b42bb0"
dependencies = [
"bstr",
"gix-config-value",
@ -686,9 +680,9 @@ dependencies = [
[[package]]
name = "gix-config-value"
version = "0.14.7"
version = "0.14.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b328997d74dd15dc71b2773b162cb4af9a25c424105e4876e6d0686ab41c383e"
checksum = "03f76169faa0dec598eac60f83d7fcdd739ec16596eca8fb144c88973dbe6f8c"
dependencies = [
"bitflags 2.6.0",
"bstr",
@ -699,21 +693,21 @@ dependencies = [
[[package]]
name = "gix-date"
version = "0.8.7"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9eed6931f21491ee0aeb922751bd7ec97b4b2fe8fbfedcb678e2a2dce5f3b8c0"
checksum = "35c84b7af01e68daf7a6bb8bb909c1ff5edb3ce4326f1f43063a5a96d3c3c8a5"
dependencies = [
"bstr",
"itoa",
"jiff",
"thiserror",
"time",
]
[[package]]
name = "gix-diff"
version = "0.44.1"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1996d5c8a305b59709467d80617c9fde48d9d75fd1f4179ea970912630886c9d"
checksum = "92c9afd80fff00f8b38b1c1928442feb4cd6d2232a6ed806b6b193151a3d336c"
dependencies = [
"bstr",
"gix-command",
@ -731,9 +725,9 @@ dependencies = [
[[package]]
name = "gix-dir"
version = "0.6.0"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c975679aa00dd2d757bfd3ddb232e8a188c0094c3306400575a0813858b1365"
checksum = "0ed3a9076661359a1c5a27c12ad6c3ebe2dd96b8b3c0af6488ab7c128b7bdd98"
dependencies = [
"bstr",
"gix-discover",
@ -751,9 +745,9 @@ dependencies = [
[[package]]
name = "gix-discover"
version = "0.33.0"
version = "0.35.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67662731cec3cb31ba3ed2463809493f76d8e5d6c6d245de8b0560438c13450e"
checksum = "0577366b9567376bc26e815fd74451ebd0e6218814e242f8e5b7072c58d956d2"
dependencies = [
"bstr",
"dunce",
@ -786,9 +780,9 @@ dependencies = [
[[package]]
name = "gix-filter"
version = "0.11.3"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6547738da28275f4dff4e9f3a0f28509f53f94dd6bd822733c91cb306bca61a"
checksum = "4121790ae140066e5b953becc72e7496278138d19239be2e63b5067b0843119e"
dependencies = [
"bstr",
"encoding_rs",
@ -807,9 +801,9 @@ dependencies = [
[[package]]
name = "gix-fs"
version = "0.11.2"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6adf99c27cdf17b1c4d77680c917e0d94d8783d4e1c73d3be0d1d63107163d7a"
checksum = "f2bfe6249cfea6d0c0e0990d5226a4cb36f030444ba9e35e0639275db8f98575"
dependencies = [
"fastrand",
"gix-features",
@ -818,9 +812,9 @@ dependencies = [
[[package]]
name = "gix-glob"
version = "0.16.4"
version = "0.16.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa7df15afa265cc8abe92813cd354d522f1ac06b29ec6dfa163ad320575cb447"
checksum = "74908b4bbc0a0a40852737e5d7889f676f081e340d5451a16e5b4c50d592f111"
dependencies = [
"bitflags 2.6.0",
"bstr",
@ -851,9 +845,9 @@ dependencies = [
[[package]]
name = "gix-ignore"
version = "0.11.3"
version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e6afb8f98e314d4e1adc822449389ada863c174b5707cedd327d67b84dba527"
checksum = "e447cd96598460f5906a0f6c75e950a39f98c2705fc755ad2f2020c9e937fab7"
dependencies = [
"bstr",
"gix-glob",
@ -864,9 +858,9 @@ dependencies = [
[[package]]
name = "gix-index"
version = "0.33.1"
version = "0.35.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a9a44eb55bd84bb48f8a44980e951968ced21e171b22d115d1cdcef82a7d73f"
checksum = "0cd4203244444017682176e65fd0180be9298e58ed90bd4a8489a357795ed22d"
dependencies = [
"bitflags 2.6.0",
"bstr",
@ -901,22 +895,11 @@ dependencies = [
"thiserror",
]
[[package]]
name = "gix-macros"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "999ce923619f88194171a67fb3e6d613653b8d4d6078b529b15a765da0edcc17"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.48",
]
[[package]]
name = "gix-object"
version = "0.42.3"
version = "0.44.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25da2f46b4e7c2fa7b413ce4dffb87f69eaf89c2057e386491f4c55cadbfe386"
checksum = "2f5b801834f1de7640731820c2df6ba88d95480dc4ab166a5882f8ff12b88efa"
dependencies = [
"bstr",
"gix-actor",
@ -933,9 +916,9 @@ dependencies = [
[[package]]
name = "gix-odb"
version = "0.61.1"
version = "0.63.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20d384fe541d93d8a3bb7d5d5ef210780d6df4f50c4e684ccba32665a5e3bc9b"
checksum = "a3158068701c17df54f0ab2adda527f5a6aca38fd5fd80ceb7e3c0a2717ec747"
dependencies = [
"arc-swap",
"gix-date",
@ -953,9 +936,9 @@ dependencies = [
[[package]]
name = "gix-pack"
version = "0.51.1"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e0594491fffe55df94ba1c111a6566b7f56b3f8d2e1efc750e77d572f5f5229"
checksum = "3223aa342eee21e1e0e403cad8ae9caf9edca55ef84c347738d10681676fd954"
dependencies = [
"clru",
"gix-chunk",
@ -971,9 +954,9 @@ dependencies = [
[[package]]
name = "gix-packetline-blocking"
version = "0.17.4"
version = "0.17.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c31d42378a3d284732e4d589979930d0d253360eccf7ec7a80332e5ccb77e14a"
checksum = "b9802304baa798dd6f5ff8008a2b6516d54b74a69ca2d3a2b9e2d6c3b5556b40"
dependencies = [
"bstr",
"faster-hex",
@ -983,9 +966,9 @@ dependencies = [
[[package]]
name = "gix-path"
version = "0.10.9"
version = "0.10.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d23d5bbda31344d8abc8de7c075b3cf26e5873feba7c4a15d916bce67382bd9"
checksum = "38d5b8722112fa2fa87135298780bc833b0e9f6c56cc82795d209804b3a03484"
dependencies = [
"bstr",
"gix-trace",
@ -996,9 +979,9 @@ dependencies = [
[[package]]
name = "gix-pathspec"
version = "0.7.6"
version = "0.7.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d307d1b8f84dc8386c4aa20ce0cf09242033840e15469a3ecba92f10cfb5c046"
checksum = "5d23bf239532b4414d0e63b8ab3a65481881f7237ed9647bb10c1e3cc54c5ceb"
dependencies = [
"bitflags 2.6.0",
"bstr",
@ -1022,9 +1005,9 @@ dependencies = [
[[package]]
name = "gix-ref"
version = "0.45.0"
version = "0.47.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "636e96a0a5562715153fee098c217110c33a6f8218f08f4687ff99afde159bb5"
checksum = "ae0d8406ebf9aaa91f55a57f053c5a1ad1a39f60fdf0303142b7be7ea44311e5"
dependencies = [
"gix-actor",
"gix-features",
@ -1043,9 +1026,9 @@ dependencies = [
[[package]]
name = "gix-refspec"
version = "0.23.1"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6868f8cd2e62555d1f7c78b784bece43ace40dd2a462daf3b588d5416e603f37"
checksum = "ebb005f82341ba67615ffdd9f7742c87787544441c88090878393d0682869ca6"
dependencies = [
"bstr",
"gix-hash",
@ -1057,9 +1040,9 @@ dependencies = [
[[package]]
name = "gix-revision"
version = "0.27.2"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01b13e43c2118c4b0537ddac7d0821ae0dfa90b7b8dbf20c711e153fb749adce"
checksum = "ba4621b219ac0cdb9256883030c3d56a6c64a6deaa829a92da73b9a576825e1e"
dependencies = [
"bstr",
"gix-date",
@ -1071,9 +1054,9 @@ dependencies = [
[[package]]
name = "gix-revwalk"
version = "0.13.2"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b030ccaab71af141f537e0225f19b9e74f25fefdba0372246b844491cab43e0"
checksum = "b41e72544b93084ee682ef3d5b31b1ba4d8fa27a017482900e5e044d5b1b3984"
dependencies = [
"gix-commitgraph",
"gix-date",
@ -1086,9 +1069,9 @@ dependencies = [
[[package]]
name = "gix-sec"
version = "0.10.7"
version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1547d26fa5693a7f34f05b4a3b59a90890972922172653bcb891ab3f09f436df"
checksum = "0fe4d52f30a737bbece5276fab5d3a8b276dc2650df963e293d0673be34e7a5f"
dependencies = [
"bitflags 2.6.0",
"gix-path",
@ -1098,9 +1081,9 @@ dependencies = [
[[package]]
name = "gix-status"
version = "0.11.0"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83f7b084cb65c3d007ce6bb479755ca13d602ca3cd91c4f08d7e59904de33736"
checksum = "f70d35ba639f0c16a6e4cca81aa374a05f07b23fa36ee8beb72c100d98b4ffea"
dependencies = [
"bstr",
"filetime",
@ -1121,9 +1104,9 @@ dependencies = [
[[package]]
name = "gix-submodule"
version = "0.12.0"
version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f2e0f69aa00805e39d39ec80472a7e9da20ed5d73318b27925a2cc198e854fd"
checksum = "529d0af78cc2f372b3218f15eb1e3d1635a21c8937c12e2dd0b6fc80c2ca874b"
dependencies = [
"bstr",
"gix-config",
@ -1156,9 +1139,9 @@ checksum = "f924267408915fddcd558e3f37295cc7d6a3e50f8bd8b606cee0808c3915157e"
[[package]]
name = "gix-traverse"
version = "0.39.2"
version = "0.41.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e499a18c511e71cf4a20413b743b9f5bcf64b3d9e81e9c3c6cd399eae55a8840"
checksum = "030da39af94e4df35472e9318228f36530989327906f38e27807df305fccb780"
dependencies = [
"bitflags 2.6.0",
"gix-commitgraph",
@ -1173,9 +1156,9 @@ dependencies = [
[[package]]
name = "gix-url"
version = "0.27.4"
version = "0.27.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2eb9b35bba92ea8f0b5ab406fad3cf6b87f7929aa677ff10aa042c6da621156"
checksum = "fd280c5e84fb22e128ed2a053a0daeacb6379469be6a85e3d518a0636e160c89"
dependencies = [
"bstr",
"gix-features",
@ -1198,9 +1181,9 @@ dependencies = [
[[package]]
name = "gix-validate"
version = "0.8.5"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82c27dd34a49b1addf193c92070bcbf3beaf6e10f16a78544de6372e146a0acf"
checksum = "81f2badbb64e57b404593ee26b752c26991910fd0d81fe6f9a71c1a8309b6c86"
dependencies = [
"bstr",
"thiserror",
@ -1208,9 +1191,9 @@ dependencies = [
[[package]]
name = "gix-worktree"
version = "0.34.1"
version = "0.36.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26f7326ebe0b9172220694ea69d344c536009a9b98fb0f9de092c440f3efe7a6"
checksum = "c312ad76a3f2ba8e865b360d5cb3aa04660971d16dec6dd0ce717938d903149a"
dependencies = [
"bstr",
"gix-attributes",
@ -1668,6 +1651,31 @@ version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]]
name = "jiff"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ef8bc400f8312944a9f879db116fed372c4f0859af672eba2a80f79c767dd19"
dependencies = [
"jiff-tzdb-platform",
"windows-sys 0.59.0",
]
[[package]]
name = "jiff-tzdb"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05fac328b3df1c0f18a3c2ab6cb7e06e4e549f366017d796e3e66b6d6889abe6"
[[package]]
name = "jiff-tzdb-platform"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8da387d5feaf355954c2c122c194d6df9c57d865125a67984bb453db5336940"
dependencies = [
"jiff-tzdb",
]
[[package]]
name = "js-sys"
version = "0.3.61"
@ -1688,9 +1696,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.155"
version = "0.2.158"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
[[package]]
name = "libloading"
@ -1699,7 +1707,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
dependencies = [
"cfg-if",
"windows-targets 0.48.0",
"windows-targets 0.52.6",
]
[[package]]
@ -1800,12 +1808,6 @@ dependencies = [
"unicode-segmentation",
]
[[package]]
name = "num-conv"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
[[package]]
name = "num-traits"
version = "0.2.15"
@ -1825,15 +1827,6 @@ dependencies = [
"libc",
]
[[package]]
name = "num_threads"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
dependencies = [
"libc",
]
[[package]]
name = "object"
version = "0.31.1"
@ -1913,12 +1906,6 @@ version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265"
[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "proc-macro2"
version = "1.0.76"
@ -1936,9 +1923,9 @@ checksum = "744a264d26b88a6a7e37cbad97953fa233b94d585236310bcbc88474b4092d79"
[[package]]
name = "pulldown-cmark"
version = "0.11.0"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8746739f11d39ce5ad5c2520a9b75285310dbfe78c541ccf832d38615765aec0"
checksum = "4d31cbfcd94884c3a67ec210c83efb06cb43674043458b0ad59f6947f8462c23"
dependencies = [
"bitflags 2.6.0",
"memchr",
@ -2121,18 +2108,18 @@ checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1"
[[package]]
name = "serde"
version = "1.0.204"
version = "1.0.209"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.204"
version = "1.0.209"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170"
dependencies = [
"proc-macro2",
"quote",
@ -2141,9 +2128,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.122"
version = "1.0.127"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "784b6203951c57ff748476b126ccb5e8e2959a5c19e5c617ab1956be3dbc68da"
checksum = "8043c06d9f82bd7271361ed64f415fe5e12a77fdb52e573e7f06a516dea329ad"
dependencies = [
"itoa",
"memchr",
@ -2183,6 +2170,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "signal-hook"
version = "0.3.17"
@ -2312,15 +2305,15 @@ dependencies = [
[[package]]
name = "tempfile"
version = "3.11.0"
version = "3.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8fcd239983515c23a32fb82099f97d0b11b8c72f654ed659363a95c3dad7a53"
checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64"
dependencies = [
"cfg-if",
"fastrand",
"once_cell",
"rustix",
"windows-sys 0.52.0",
"windows-sys 0.59.0",
]
[[package]]
@ -2381,39 +2374,6 @@ dependencies = [
"num_cpus",
]
[[package]]
name = "time"
version = "0.3.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
dependencies = [
"deranged",
"itoa",
"libc",
"num-conv",
"num_threads",
"powerfmt",
"serde",
"time-core",
"time-macros",
]
[[package]]
name = "time-core"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "time-macros"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"
dependencies = [
"num-conv",
"time-core",
]
[[package]]
name = "tinyvec"
version = "1.6.0"
@ -2431,9 +2391,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]]
name = "tokio"
version = "1.39.2"
version = "1.39.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1"
checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5"
dependencies = [
"backtrace",
"bytes",
@ -2663,9 +2623,9 @@ checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
[[package]]
name = "which"
version = "6.0.2"
version = "6.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d9c5ed668ee1f17edb3b627225343d210006a90bb1e3745ce1f30b1fb115075"
checksum = "b4ee928febd44d98f2f459a4a79bd4d928591333a494a10a868418ac1b39cf1f"
dependencies = [
"either",
"home",

View File

@ -1,6 +1,6 @@
| Language | Syntax Highlighting | Treesitter Textobjects | Auto Indent | Default LSP |
| --- | --- | --- | --- | --- |
| ada | ✓ | ✓ | | `ada_language_server`, `ada_language_server` |
| ada | ✓ | ✓ | | `ada_language_server` |
| adl | ✓ | ✓ | ✓ | |
| agda | ✓ | | | |
| astro | ✓ | | | |
@ -34,8 +34,8 @@
| devicetree | ✓ | | | |
| dhall | ✓ | ✓ | | `dhall-lsp-server` |
| diff | ✓ | | | |
| docker-compose | ✓ | | ✓ | `docker-compose-langserver`, `yaml-language-server` |
| dockerfile | ✓ | | | `docker-langserver` |
| docker-compose | ✓ | | ✓ | `docker-compose-langserver`, `yaml-language-server` |
| dockerfile | ✓ | | | `docker-langserver` |
| dot | ✓ | | | `dot-language-server` |
| dtd | ✓ | | | |
| earthfile | ✓ | ✓ | ✓ | `earthlyls` |
@ -46,7 +46,7 @@
| elixir | ✓ | ✓ | ✓ | `elixir-ls` |
| elm | ✓ | ✓ | | `elm-language-server` |
| elvish | ✓ | | | `elvish` |
| env | ✓ | | | |
| env | ✓ | | | |
| erb | ✓ | | | |
| erlang | ✓ | ✓ | | `erlang_ls` |
| esdl | ✓ | | | |
@ -58,9 +58,10 @@
| gas | ✓ | ✓ | | |
| gdscript | ✓ | ✓ | ✓ | |
| gemini | ✓ | | | |
| gherkin | ✓ | | | |
| git-attributes | ✓ | | | |
| git-commit | ✓ | ✓ | | |
| git-config | ✓ | | | |
| git-config | ✓ | | | |
| git-ignore | ✓ | | | |
| git-rebase | ✓ | | | |
| gjs | ✓ | ✓ | ✓ | `typescript-language-server`, `vscode-eslint-language-server`, `ember-language-server` |
@ -82,7 +83,7 @@
| hcl | ✓ | ✓ | ✓ | `terraform-ls` |
| heex | ✓ | ✓ | | `elixir-ls` |
| helm | ✓ | | | `helm_ls` |
| hocon | ✓ | | ✓ | |
| hocon | ✓ | | ✓ | |
| hoon | ✓ | | | |
| hosts | ✓ | | | |
| html | ✓ | | | `vscode-html-language-server` |
@ -97,6 +98,7 @@
| javascript | ✓ | ✓ | ✓ | `typescript-language-server` |
| jinja | ✓ | | | |
| jjdescription | ✓ | | | |
| jq | ✓ | ✓ | | `jq-lsp` |
| jsdoc | ✓ | | | |
| json | ✓ | ✓ | ✓ | `vscode-json-language-server` |
| json5 | ✓ | | | |
@ -125,7 +127,7 @@
| markdown.inline | ✓ | | | |
| matlab | ✓ | ✓ | ✓ | |
| mermaid | ✓ | | | |
| meson | ✓ | | ✓ | |
| meson | ✓ | | ✓ | `mesonlsp` |
| mint | | | | `mint` |
| mojo | ✓ | ✓ | ✓ | `mojo-lsp-server` |
| move | ✓ | | | |
@ -133,7 +135,7 @@
| nasm | ✓ | ✓ | | |
| nickel | ✓ | | ✓ | `nls` |
| nim | ✓ | ✓ | ✓ | `nimlangserver` |
| nix | ✓ | ✓ | | `nil` |
| nix | ✓ | ✓ | | `nil`, `nixd` |
| nu | ✓ | | | `nu` |
| nunjucks | ✓ | | | |
| ocaml | ✓ | | ✓ | `ocamllsp` |
@ -156,7 +158,7 @@
| pod | ✓ | | | |
| ponylang | ✓ | ✓ | ✓ | |
| powershell | ✓ | | | |
| prisma | ✓ | | | `prisma-language-server` |
| prisma | ✓ | | | `prisma-language-server` |
| prolog | | | | `swipl` |
| protobuf | ✓ | ✓ | ✓ | `bufls`, `pb` |
| prql | ✓ | | | |
@ -184,7 +186,7 @@
| sml | ✓ | | | |
| solidity | ✓ | ✓ | | `solc` |
| spicedb | ✓ | | | |
| sql | ✓ | | | |
| sql | ✓ | | | |
| sshclientconfig | ✓ | | | |
| starlark | ✓ | ✓ | | |
| strace | ✓ | | | |
@ -199,12 +201,14 @@
| tcl | ✓ | | ✓ | |
| templ | ✓ | | | `templ` |
| tfvars | ✓ | | ✓ | `terraform-ls` |
| thrift | ✓ | | | |
| todotxt | ✓ | | | |
| toml | ✓ | ✓ | | `taplo` |
| tsq | ✓ | | | |
| tsx | ✓ | ✓ | ✓ | `typescript-language-server` |
| twig | ✓ | | | |
| typescript | ✓ | ✓ | ✓ | `typescript-language-server` |
| typespec | ✓ | ✓ | ✓ | `tsp-server` |
| typst | ✓ | | | `tinymist`, `typst-lsp` |
| ungrammar | ✓ | | | |
| unison | ✓ | | ✓ | |
@ -224,6 +228,6 @@
| xit | ✓ | | | |
| xml | ✓ | | ✓ | |
| xtc | ✓ | | | |
| yaml | ✓ | | ✓ | `yaml-language-server`, `ansible-language-server` |
| yaml | ✓ | | ✓ | `yaml-language-server`, `ansible-language-server` |
| yuck | ✓ | | | |
| zig | ✓ | ✓ | ✓ | `zls` |

View File

@ -14,6 +14,10 @@ # Installing Helix
## Pre-built binaries
Download pre-built binaries from the [GitHub Releases page](https://github.com/helix-editor/helix/releases).
Add the `hx` binary to your system's `$PATH` to use it from the command line, and copy the `runtime` directory into the config directory (for example `~/.config/helix/runtime` on Linux/macOS).
The runtime location can be overriden via the HELIX_RUNTIME environment variable.
The tarball contents include an `hx` binary and a `runtime` directory.
To set up Helix:
1. Add the `hx` binary to your system's `$PATH` to allow it to be used from the command line.
2. Copy the `runtime` directory to a location that `hx` searches for runtime files. A typical location on Linux/macOS is `~/.config/helix/runtime`.
To see the runtime directories that `hx` searches, run `hx --health`. If necessary, you can override the default runtime location by setting the `HELIX_RUNTIME` environment variable.

View File

@ -320,10 +320,14 @@ ##### Completion Menu
Displays documentation for the selected completion item. Remapping currently not supported.
| Key | Description |
| ---- | ----------- |
| `Shift-Tab`, `Ctrl-p`, `Up` | Previous entry |
| `Tab`, `Ctrl-n`, `Down` | Next entry |
| Key | Description |
| ---- | ----------- |
| `Shift-Tab`, `Ctrl-p`, `Up` | Previous entry |
| `Tab`, `Ctrl-n`, `Down` | Next entry |
| `Enter` | Close menu and accept completion |
| `Ctrl-c` | Close menu and reject completion |
Any other keypresses result in the completion being accepted.
##### Signature-help Popup

View File

@ -75,5 +75,20 @@ ## Special keys and modifiers
Keys can be disabled by binding them to the `no_op` command.
A list of commands is available in the [Keymap](https://docs.helix-editor.com/keymap.html) documentation
and in the source code at [`helix-term/src/commands.rs`](https://github.com/helix-editor/helix/blob/master/helix-term/src/commands.rs) at the invocation of `static_commands!` macro and the `TypableCommandList`.
## Commands
There are three kinds of commands that can be used in keymaps:
* Static commands: commands like `move_char_right` which are usually bound to
keys and used for movement and editing. A list of static commands is
available in the [Keymap](./keymap.html) documentation and in the source code
in [`helix-term/src/commands.rs`](https://github.com/helix-editor/helix/blob/master/helix-term/src/commands.rs)
at the invocation of `static_commands!` macro and the `TypableCommandList`.
* Typable commands: commands that can be executed from command mode (`:`), for
example `:write!`. See the [Commands](./commands.html) documentation for a
list of available typeable commands.
* Macros: sequences of keys that are executed in order. These keybindings
start with `@` and then list any number of keys to be executed. For example
`@miw` can be used to select the surrounding word. For now, macro keybindings
are not allowed in keybinding sequences due to limitations in the way that
command sequences are executed.

View File

@ -126,6 +126,7 @@
# disable fetching and building of tree-sitter grammars in the helix-term build.rs
HELIX_DISABLE_AUTO_GRAMMAR_BUILD = "1";
buildInputs = [stdenv.cc.cc.lib];
nativeBuildInputs = [pkgs.installShellFiles];
# disable tests
doCheck = false;
meta.mainProgram = "hx";
@ -141,6 +142,7 @@
cp contrib/Helix.desktop $out/share/applications
cp logo.svg $out/share/icons/hicolor/scalable/apps/helix.svg
cp contrib/helix.png $out/share/icons/hicolor/256x256/apps
installShellCompletion contrib/completion/hx.{bash,fish,zsh}
'';
});
helix = makeOverridableHelix self.packages.${system}.helix-unwrapped {};

View File

@ -197,13 +197,31 @@ pub fn move_prev_long_word_end(slice: RopeSlice, range: Range, count: usize) ->
word_move(slice, range, count, WordMotionTarget::PrevLongWordEnd)
}
pub fn move_next_sub_word_start(slice: RopeSlice, range: Range, count: usize) -> Range {
word_move(slice, range, count, WordMotionTarget::NextSubWordStart)
}
pub fn move_next_sub_word_end(slice: RopeSlice, range: Range, count: usize) -> Range {
word_move(slice, range, count, WordMotionTarget::NextSubWordEnd)
}
pub fn move_prev_sub_word_start(slice: RopeSlice, range: Range, count: usize) -> Range {
word_move(slice, range, count, WordMotionTarget::PrevSubWordStart)
}
pub fn move_prev_sub_word_end(slice: RopeSlice, range: Range, count: usize) -> Range {
word_move(slice, range, count, WordMotionTarget::PrevSubWordEnd)
}
fn word_move(slice: RopeSlice, range: Range, count: usize, target: WordMotionTarget) -> Range {
let is_prev = matches!(
target,
WordMotionTarget::PrevWordStart
| WordMotionTarget::PrevLongWordStart
| WordMotionTarget::PrevSubWordStart
| WordMotionTarget::PrevWordEnd
| WordMotionTarget::PrevLongWordEnd
| WordMotionTarget::PrevSubWordEnd
);
// Special-case early-out.
@ -383,6 +401,12 @@ pub enum WordMotionTarget {
NextLongWordEnd,
PrevLongWordStart,
PrevLongWordEnd,
// A sub word is similar to a regular word, except it is also delimited by
// underscores and transitions from lowercase to uppercase.
NextSubWordStart,
NextSubWordEnd,
PrevSubWordStart,
PrevSubWordEnd,
}
pub trait CharHelpers {
@ -398,8 +422,10 @@ fn range_to_target(&mut self, target: WordMotionTarget, origin: Range) -> Range
target,
WordMotionTarget::PrevWordStart
| WordMotionTarget::PrevLongWordStart
| WordMotionTarget::PrevSubWordStart
| WordMotionTarget::PrevWordEnd
| WordMotionTarget::PrevLongWordEnd
| WordMotionTarget::PrevSubWordEnd
);
// Reverse the iterator if needed for the motion direction.
@ -476,6 +502,25 @@ fn is_long_word_boundary(a: char, b: char) -> bool {
}
}
fn is_sub_word_boundary(a: char, b: char, dir: Direction) -> bool {
match (categorize_char(a), categorize_char(b)) {
(CharCategory::Word, CharCategory::Word) => {
if (a == '_') != (b == '_') {
return true;
}
// Subword boundaries are directional: in 'fooBar', there is a
// boundary between 'o' and 'B', but not between 'B' and 'a'.
match dir {
Direction::Forward => a.is_lowercase() && b.is_uppercase(),
Direction::Backward => a.is_uppercase() && b.is_lowercase(),
}
}
(a, b) if a != b => true,
_ => false,
}
}
fn reached_target(target: WordMotionTarget, prev_ch: char, next_ch: char) -> bool {
match target {
WordMotionTarget::NextWordStart | WordMotionTarget::PrevWordEnd => {
@ -494,6 +539,22 @@ fn reached_target(target: WordMotionTarget, prev_ch: char, next_ch: char) -> boo
is_long_word_boundary(prev_ch, next_ch)
&& (!prev_ch.is_whitespace() || char_is_line_ending(next_ch))
}
WordMotionTarget::NextSubWordStart => {
is_sub_word_boundary(prev_ch, next_ch, Direction::Forward)
&& (char_is_line_ending(next_ch) || !(next_ch.is_whitespace() || next_ch == '_'))
}
WordMotionTarget::PrevSubWordEnd => {
is_sub_word_boundary(prev_ch, next_ch, Direction::Backward)
&& (char_is_line_ending(next_ch) || !(next_ch.is_whitespace() || next_ch == '_'))
}
WordMotionTarget::NextSubWordEnd => {
is_sub_word_boundary(prev_ch, next_ch, Direction::Forward)
&& (!(prev_ch.is_whitespace() || prev_ch == '_') || char_is_line_ending(next_ch))
}
WordMotionTarget::PrevSubWordStart => {
is_sub_word_boundary(prev_ch, next_ch, Direction::Backward)
&& (!(prev_ch.is_whitespace() || prev_ch == '_') || char_is_line_ending(next_ch))
}
}
}
@ -1012,6 +1073,178 @@ fn test_behaviour_when_moving_to_start_of_next_words() {
}
}
#[test]
fn test_behaviour_when_moving_to_start_of_next_sub_words() {
let tests = [
(
"NextSubwordStart",
vec![
(1, Range::new(0, 0), Range::new(0, 4)),
(1, Range::new(4, 4), Range::new(4, 11)),
],
),
(
"next_subword_start",
vec![
(1, Range::new(0, 0), Range::new(0, 5)),
(1, Range::new(4, 4), Range::new(5, 13)),
],
),
(
"Next_Subword_Start",
vec![
(1, Range::new(0, 0), Range::new(0, 5)),
(1, Range::new(4, 4), Range::new(5, 13)),
],
),
(
"NEXT_SUBWORD_START",
vec![
(1, Range::new(0, 0), Range::new(0, 5)),
(1, Range::new(4, 4), Range::new(5, 13)),
],
),
(
"next subword start",
vec![
(1, Range::new(0, 0), Range::new(0, 5)),
(1, Range::new(4, 4), Range::new(5, 13)),
],
),
(
"Next Subword Start",
vec![
(1, Range::new(0, 0), Range::new(0, 5)),
(1, Range::new(4, 4), Range::new(5, 13)),
],
),
(
"NEXT SUBWORD START",
vec![
(1, Range::new(0, 0), Range::new(0, 5)),
(1, Range::new(4, 4), Range::new(5, 13)),
],
),
(
"next__subword__start",
vec![
(1, Range::new(0, 0), Range::new(0, 6)),
(1, Range::new(4, 4), Range::new(4, 6)),
(1, Range::new(5, 5), Range::new(6, 15)),
],
),
(
"Next__Subword__Start",
vec![
(1, Range::new(0, 0), Range::new(0, 6)),
(1, Range::new(4, 4), Range::new(4, 6)),
(1, Range::new(5, 5), Range::new(6, 15)),
],
),
(
"NEXT__SUBWORD__START",
vec![
(1, Range::new(0, 0), Range::new(0, 6)),
(1, Range::new(4, 4), Range::new(4, 6)),
(1, Range::new(5, 5), Range::new(6, 15)),
],
),
];
for (sample, scenario) in tests {
for (count, begin, expected_end) in scenario.into_iter() {
let range = move_next_sub_word_start(Rope::from(sample).slice(..), begin, count);
assert_eq!(range, expected_end, "Case failed: [{}]", sample);
}
}
}
#[test]
fn test_behaviour_when_moving_to_end_of_next_sub_words() {
let tests = [
(
"NextSubwordEnd",
vec![
(1, Range::new(0, 0), Range::new(0, 4)),
(1, Range::new(4, 4), Range::new(4, 11)),
],
),
(
"next subword end",
vec![
(1, Range::new(0, 0), Range::new(0, 4)),
(1, Range::new(4, 4), Range::new(4, 12)),
],
),
(
"Next Subword End",
vec![
(1, Range::new(0, 0), Range::new(0, 4)),
(1, Range::new(4, 4), Range::new(4, 12)),
],
),
(
"NEXT SUBWORD END",
vec![
(1, Range::new(0, 0), Range::new(0, 4)),
(1, Range::new(4, 4), Range::new(4, 12)),
],
),
(
"next_subword_end",
vec![
(1, Range::new(0, 0), Range::new(0, 4)),
(1, Range::new(4, 4), Range::new(4, 12)),
],
),
(
"Next_Subword_End",
vec![
(1, Range::new(0, 0), Range::new(0, 4)),
(1, Range::new(4, 4), Range::new(4, 12)),
],
),
(
"NEXT_SUBWORD_END",
vec![
(1, Range::new(0, 0), Range::new(0, 4)),
(1, Range::new(4, 4), Range::new(4, 12)),
],
),
(
"next__subword__end",
vec![
(1, Range::new(0, 0), Range::new(0, 4)),
(1, Range::new(4, 4), Range::new(4, 13)),
(1, Range::new(5, 5), Range::new(5, 13)),
],
),
(
"Next__Subword__End",
vec![
(1, Range::new(0, 0), Range::new(0, 4)),
(1, Range::new(4, 4), Range::new(4, 13)),
(1, Range::new(5, 5), Range::new(5, 13)),
],
),
(
"NEXT__SUBWORD__END",
vec![
(1, Range::new(0, 0), Range::new(0, 4)),
(1, Range::new(4, 4), Range::new(4, 13)),
(1, Range::new(5, 5), Range::new(5, 13)),
],
),
];
for (sample, scenario) in tests {
for (count, begin, expected_end) in scenario.into_iter() {
let range = move_next_sub_word_end(Rope::from(sample).slice(..), begin, count);
assert_eq!(range, expected_end, "Case failed: [{}]", sample);
}
}
}
#[test]
fn test_behaviour_when_moving_to_start_of_next_long_words() {
let tests = [
@ -1181,6 +1414,92 @@ fn test_behaviour_when_moving_to_start_of_previous_words() {
}
}
#[test]
fn test_behaviour_when_moving_to_start_of_previous_sub_words() {
let tests = [
(
"PrevSubwordEnd",
vec![
(1, Range::new(13, 13), Range::new(14, 11)),
(1, Range::new(11, 11), Range::new(11, 4)),
],
),
(
"prev subword end",
vec![
(1, Range::new(15, 15), Range::new(16, 13)),
(1, Range::new(12, 12), Range::new(13, 5)),
],
),
(
"Prev Subword End",
vec![
(1, Range::new(15, 15), Range::new(16, 13)),
(1, Range::new(12, 12), Range::new(13, 5)),
],
),
(
"PREV SUBWORD END",
vec![
(1, Range::new(15, 15), Range::new(16, 13)),
(1, Range::new(12, 12), Range::new(13, 5)),
],
),
(
"prev_subword_end",
vec![
(1, Range::new(15, 15), Range::new(16, 13)),
(1, Range::new(12, 12), Range::new(13, 5)),
],
),
(
"Prev_Subword_End",
vec![
(1, Range::new(15, 15), Range::new(16, 13)),
(1, Range::new(12, 12), Range::new(13, 5)),
],
),
(
"PREV_SUBWORD_END",
vec![
(1, Range::new(15, 15), Range::new(16, 13)),
(1, Range::new(12, 12), Range::new(13, 5)),
],
),
(
"prev__subword__end",
vec![
(1, Range::new(17, 17), Range::new(18, 15)),
(1, Range::new(13, 13), Range::new(14, 6)),
(1, Range::new(14, 14), Range::new(15, 6)),
],
),
(
"Prev__Subword__End",
vec![
(1, Range::new(17, 17), Range::new(18, 15)),
(1, Range::new(13, 13), Range::new(14, 6)),
(1, Range::new(14, 14), Range::new(15, 6)),
],
),
(
"PREV__SUBWORD__END",
vec![
(1, Range::new(17, 17), Range::new(18, 15)),
(1, Range::new(13, 13), Range::new(14, 6)),
(1, Range::new(14, 14), Range::new(15, 6)),
],
),
];
for (sample, scenario) in tests {
for (count, begin, expected_end) in scenario.into_iter() {
let range = move_prev_sub_word_start(Rope::from(sample).slice(..), begin, count);
assert_eq!(range, expected_end, "Case failed: [{}]", sample);
}
}
}
#[test]
fn test_behaviour_when_moving_to_start_of_previous_long_words() {
let tests = [
@ -1444,6 +1763,92 @@ fn test_behaviour_when_moving_to_end_of_previous_words() {
}
}
#[test]
fn test_behaviour_when_moving_to_end_of_previous_sub_words() {
let tests = [
(
"PrevSubwordEnd",
vec![
(1, Range::new(13, 13), Range::new(14, 11)),
(1, Range::new(11, 11), Range::new(11, 4)),
],
),
(
"prev subword end",
vec![
(1, Range::new(15, 15), Range::new(16, 12)),
(1, Range::new(12, 12), Range::new(12, 4)),
],
),
(
"Prev Subword End",
vec![
(1, Range::new(15, 15), Range::new(16, 12)),
(1, Range::new(12, 12), Range::new(12, 4)),
],
),
(
"PREV SUBWORD END",
vec![
(1, Range::new(15, 15), Range::new(16, 12)),
(1, Range::new(12, 12), Range::new(12, 4)),
],
),
(
"prev_subword_end",
vec![
(1, Range::new(15, 15), Range::new(16, 12)),
(1, Range::new(12, 12), Range::new(12, 4)),
],
),
(
"Prev_Subword_End",
vec![
(1, Range::new(15, 15), Range::new(16, 12)),
(1, Range::new(12, 12), Range::new(12, 4)),
],
),
(
"PREV_SUBWORD_END",
vec![
(1, Range::new(15, 15), Range::new(16, 12)),
(1, Range::new(12, 12), Range::new(12, 4)),
],
),
(
"prev__subword__end",
vec![
(1, Range::new(17, 17), Range::new(18, 13)),
(1, Range::new(13, 13), Range::new(13, 4)),
(1, Range::new(14, 14), Range::new(15, 13)),
],
),
(
"Prev__Subword__End",
vec![
(1, Range::new(17, 17), Range::new(18, 13)),
(1, Range::new(13, 13), Range::new(13, 4)),
(1, Range::new(14, 14), Range::new(15, 13)),
],
),
(
"PREV__SUBWORD__END",
vec![
(1, Range::new(17, 17), Range::new(18, 13)),
(1, Range::new(13, 13), Range::new(13, 4)),
(1, Range::new(14, 14), Range::new(15, 13)),
],
),
];
for (sample, scenario) in tests {
for (count, begin, expected_end) in scenario.into_iter() {
let range = move_prev_sub_word_end(Rope::from(sample).slice(..), begin, count);
assert_eq!(range, expected_end, "Case failed: [{}]", sample);
}
}
}
#[test]
fn test_behaviour_when_moving_to_end_of_next_long_words() {
let tests = [

View File

@ -184,16 +184,16 @@ pub fn map(mut self, changes: &ChangeSet) -> Self {
let positions_to_map = match self.anchor.cmp(&self.head) {
Ordering::Equal => [
(&mut self.anchor, Assoc::After),
(&mut self.head, Assoc::After),
(&mut self.anchor, Assoc::AfterSticky),
(&mut self.head, Assoc::AfterSticky),
],
Ordering::Less => [
(&mut self.anchor, Assoc::After),
(&mut self.head, Assoc::Before),
(&mut self.anchor, Assoc::AfterSticky),
(&mut self.head, Assoc::BeforeSticky),
],
Ordering::Greater => [
(&mut self.head, Assoc::After),
(&mut self.anchor, Assoc::Before),
(&mut self.head, Assoc::AfterSticky),
(&mut self.anchor, Assoc::BeforeSticky),
],
};
changes.update_positions(positions_to_map.into_iter());
@ -482,16 +482,16 @@ pub fn map_no_normalize(mut self, changes: &ChangeSet) -> Self {
range.old_visual_position = None;
match range.anchor.cmp(&range.head) {
Ordering::Equal => [
(&mut range.anchor, Assoc::After),
(&mut range.head, Assoc::After),
(&mut range.anchor, Assoc::AfterSticky),
(&mut range.head, Assoc::AfterSticky),
],
Ordering::Less => [
(&mut range.anchor, Assoc::After),
(&mut range.head, Assoc::Before),
(&mut range.anchor, Assoc::AfterSticky),
(&mut range.head, Assoc::BeforeSticky),
],
Ordering::Greater => [
(&mut range.head, Assoc::After),
(&mut range.anchor, Assoc::Before),
(&mut range.head, Assoc::AfterSticky),
(&mut range.anchor, Assoc::BeforeSticky),
],
}
});

View File

@ -29,6 +29,12 @@ pub enum Assoc {
/// Acts like `Before` if a word character is inserted
/// before the position, otherwise acts like `After`
BeforeWord,
/// Acts like `Before` but if the position is within an exact replacement
/// (exact size) the offset to the start of the replacement is kept
BeforeSticky,
/// Acts like `After` but if the position is within an exact replacement
/// (exact size) the offset to the start of the replacement is kept
AfterSticky,
}
impl Assoc {
@ -40,13 +46,17 @@ fn stay_at_gaps(self) -> bool {
fn insert_offset(self, s: &str) -> usize {
let chars = s.chars().count();
match self {
Assoc::After => chars,
Assoc::After | Assoc::AfterSticky => chars,
Assoc::AfterWord => s.chars().take_while(|&c| char_is_word(c)).count(),
// return position before inserted text
Assoc::Before => 0,
Assoc::Before | Assoc::BeforeSticky => 0,
Assoc::BeforeWord => chars - s.chars().rev().take_while(|&c| char_is_word(c)).count(),
}
}
pub fn sticky(self) -> bool {
matches!(self, Assoc::BeforeSticky | Assoc::AfterSticky)
}
}
#[derive(Debug, Default, Clone, PartialEq, Eq)]
@ -456,8 +466,14 @@ macro_rules! map {
if pos == old_pos && assoc.stay_at_gaps() {
new_pos
} else {
// place to end of insert
new_pos + assoc.insert_offset(s)
let ins = assoc.insert_offset(s);
// if the deleted and inserted text have the exact same size
// keep the relative offset into the new text
if *len == ins && assoc.sticky() {
new_pos + (pos - old_pos)
} else {
new_pos + assoc.insert_offset(s)
}
}
}),
i

View File

@ -30,7 +30,7 @@ log = "0.4"
# cloning/compiling tree-sitter grammars
cc = { version = "1" }
threadpool = { version = "1.0" }
tempfile = "3.11.0"
tempfile = "3.12.0"
dunce = "1.0.5"
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]

View File

@ -225,13 +225,16 @@ fn get_name(v: &Value) -> Option<&str> {
/// Used as a ceiling dir for LSP root resolution, the filepicker and potentially as a future filewatching root
///
/// This function starts searching the FS upward from the CWD
/// and returns the first directory that contains either `.git` or `.helix`.
/// and returns the first directory that contains either `.git`, `.svn` or `.helix`.
/// If no workspace was found returns (CWD, true).
/// Otherwise (workspace, false) is returned
pub fn find_workspace() -> (PathBuf, bool) {
let current_dir = current_working_dir();
for ancestor in current_dir.ancestors() {
if ancestor.join(".git").exists() || ancestor.join(".helix").exists() {
if ancestor.join(".git").exists()
|| ancestor.join(".svn").exists()
|| ancestor.join(".helix").exists()
{
return (ancestor.to_owned(), false);
}
}

View File

@ -22,8 +22,8 @@ license = "MIT"
[dependencies]
bitflags = "2.6.0"
serde = { version = "1.0.34", features = ["derive"] }
serde_json = "1.0.122"
serde = { version = "1.0.209", features = ["derive"] }
serde_json = "1.0.127"
serde_repr = "0.1"
url = {version = "2.0.0", features = ["serde"]}

View File

@ -20,10 +20,10 @@ regex-cursor = "0.1.4"
bitflags = "2.6"
[target.'cfg(windows)'.dependencies]
windows-sys = { version = "0.59", features = ["Win32_Security", "Win32_Security_Authorization", "Win32_System_Threading"] }
windows-sys = { version = "0.59", features = ["Win32_Foundation", "Win32_Security", "Win32_Security_Authorization", "Win32_Storage_FileSystem", "Win32_System_Threading"] }
[target.'cfg(unix)'.dependencies]
rustix = { version = "0.38", features = ["fs"] }
[dev-dependencies]
tempfile = "3.11"
tempfile = "3.12"

View File

@ -85,7 +85,7 @@ pub fn hardlink_count(p: &Path) -> std::io::Result<u64> {
#[cfg(windows)]
mod imp {
use windows_sys::Win32::Foundation::{CloseHandle, LocalFree, ERROR_SUCCESS, HANDLE, PSID};
use windows_sys::Win32::Foundation::{CloseHandle, LocalFree, ERROR_SUCCESS, HANDLE};
use windows_sys::Win32::Security::Authorization::{
GetNamedSecurityInfoW, SetNamedSecurityInfoW, SE_FILE_OBJECT,
};
@ -95,7 +95,7 @@ mod imp {
SecurityImpersonation, ACCESS_ALLOWED_CALLBACK_ACE, ACL, ACL_SIZE_INFORMATION,
DACL_SECURITY_INFORMATION, GENERIC_MAPPING, GROUP_SECURITY_INFORMATION, INHERITED_ACE,
LABEL_SECURITY_INFORMATION, OBJECT_SECURITY_INFORMATION, OWNER_SECURITY_INFORMATION,
PRIVILEGE_SET, PROTECTED_DACL_SECURITY_INFORMATION, PSECURITY_DESCRIPTOR,
PRIVILEGE_SET, PROTECTED_DACL_SECURITY_INFORMATION, PSECURITY_DESCRIPTOR, PSID,
SID_IDENTIFIER_AUTHORITY, TOKEN_DUPLICATE, TOKEN_QUERY,
};
use windows_sys::Win32::Storage::FileSystem::{
@ -419,7 +419,7 @@ pub fn copy_metadata(from: &Path, to: &Path) -> io::Result<()> {
pub fn hardlink_count(p: &Path) -> std::io::Result<u64> {
let file = std::fs::File::open(p)?;
let handle = file.as_raw_handle() as isize;
let handle = file.as_raw_handle();
let mut info: BY_HANDLE_FILE_INFORMATION = unsafe { std::mem::zeroed() };
if unsafe { GetFileInformationByHandle(handle, &mut info) } == 0 {

View File

@ -53,7 +53,7 @@ log = "0.4"
nucleo.workspace = true
ignore = "0.4"
# markdown doc rendering
pulldown-cmark = { version = "0.11", default-features = false }
pulldown-cmark = { version = "0.12", default-features = false }
# file type detection
content_inspector = "0.2.4"
thiserror = "1.0"
@ -74,10 +74,10 @@ grep-searcher = "0.1.13"
[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.155"
libc = "0.2.158"
[target.'cfg(target_os = "macos")'.dependencies]
crossterm = { version = "0.28", features = ["event-stream", "use-dev-tty"] }
crossterm = { version = "0.28", features = ["event-stream", "use-dev-tty", "libc"] }
[build-dependencies]
helix-loader = { path = "../helix-loader" }
@ -85,5 +85,5 @@ helix-loader = { path = "../helix-loader" }
[dev-dependencies]
smallvec = "1.13"
indoc = "2.0.5"
tempfile = "3.11.0"
tempfile = "3.12.0"
same-file = "1.0.1"

View File

@ -176,9 +176,16 @@ fn make_job_callback<T, F>(
use helix_view::{align_view, Align};
/// A MappableCommand is either a static command like "jump_view_up" or a Typable command like
/// :format. It causes a side-effect on the state (usually by creating and applying a transaction).
/// Both of these types of commands can be mapped with keybindings in the config.toml.
/// MappableCommands are commands that can be bound to keys, executable in
/// normal, insert or select mode.
///
/// There are three kinds:
///
/// * Static: commands usually bound to keys and used for editing, movement,
/// etc., for example `move_char_left`.
/// * Typable: commands executable from command mode, prefixed with a `:`,
/// for example `:write!`.
/// * Macro: a sequence of keys to execute, for example `@miw`.
#[derive(Clone)]
pub enum MappableCommand {
Typable {
@ -191,6 +198,10 @@ pub enum MappableCommand {
fun: fn(cx: &mut Context),
doc: &'static str,
},
Macro {
name: String,
keys: Vec<KeyEvent>,
},
}
macro_rules! static_commands {
@ -227,6 +238,23 @@ pub fn execute(&self, cx: &mut Context) {
}
}
Self::Static { fun, .. } => (fun)(cx),
Self::Macro { keys, .. } => {
// Protect against recursive macros.
if cx.editor.macro_replaying.contains(&'@') {
cx.editor.set_error(
"Cannot execute macro because the [@] register is already playing a macro",
);
return;
}
cx.editor.macro_replaying.push('@');
let keys = keys.clone();
cx.callback.push(Box::new(move |compositor, cx| {
for key in keys.into_iter() {
compositor.handle_event(&compositor::Event::Key(key), cx);
}
cx.editor.macro_replaying.pop();
}));
}
}
}
@ -234,6 +262,7 @@ pub fn name(&self) -> &str {
match &self {
Self::Typable { name, .. } => name,
Self::Static { name, .. } => name,
Self::Macro { name, .. } => name,
}
}
@ -241,6 +270,7 @@ pub fn doc(&self) -> &str {
match &self {
Self::Typable { doc, .. } => doc,
Self::Static { doc, .. } => doc,
Self::Macro { name, .. } => name,
}
}
@ -269,6 +299,10 @@ pub fn doc(&self) -> &str {
move_prev_long_word_start, "Move to start of previous long word",
move_next_long_word_end, "Move to end of next long word",
move_prev_long_word_end, "Move to end of previous long word",
move_next_sub_word_start, "Move to start of next sub word",
move_prev_sub_word_start, "Move to start of previous sub word",
move_next_sub_word_end, "Move to end of next sub word",
move_prev_sub_word_end, "Move to end of previous sub word",
move_parent_node_end, "Move to end of the parent node",
move_parent_node_start, "Move to beginning of the parent node",
extend_next_word_start, "Extend to start of next word",
@ -279,6 +313,10 @@ pub fn doc(&self) -> &str {
extend_prev_long_word_start, "Extend to start of previous long word",
extend_next_long_word_end, "Extend to end of next long word",
extend_prev_long_word_end, "Extend to end of prev long word",
extend_next_sub_word_start, "Extend to start of next sub word",
extend_prev_sub_word_start, "Extend to start of previous sub word",
extend_next_sub_word_end, "Extend to end of next sub word",
extend_prev_sub_word_end, "Extend to end of prev sub word",
extend_parent_node_end, "Extend to end of the parent node",
extend_parent_node_start, "Extend to beginning of the parent node",
find_till_char, "Move till next occurrence of char",
@ -543,6 +581,11 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
.field(name)
.field(args)
.finish(),
MappableCommand::Macro { name, keys, .. } => f
.debug_tuple("MappableCommand")
.field(name)
.field(keys)
.finish(),
}
}
}
@ -573,6 +616,11 @@ fn from_str(s: &str) -> Result<Self, Self::Err> {
args,
})
.ok_or_else(|| anyhow!("No TypableCommand named '{}'", s))
} else if let Some(suffix) = s.strip_prefix('@') {
helix_view::input::parse_macro(suffix).map(|keys| Self::Macro {
name: s.to_string(),
keys,
})
} else {
MappableCommand::STATIC_COMMAND_LIST
.iter()
@ -1126,6 +1174,22 @@ fn move_next_long_word_end(cx: &mut Context) {
move_word_impl(cx, movement::move_next_long_word_end)
}
fn move_next_sub_word_start(cx: &mut Context) {
move_word_impl(cx, movement::move_next_sub_word_start)
}
fn move_prev_sub_word_start(cx: &mut Context) {
move_word_impl(cx, movement::move_prev_sub_word_start)
}
fn move_prev_sub_word_end(cx: &mut Context) {
move_word_impl(cx, movement::move_prev_sub_word_end)
}
fn move_next_sub_word_end(cx: &mut Context) {
move_word_impl(cx, movement::move_next_sub_word_end)
}
fn goto_para_impl<F>(cx: &mut Context, move_fn: F)
where
F: Fn(RopeSlice, Range, usize, Movement) -> Range + 'static,
@ -1362,6 +1426,22 @@ fn extend_next_long_word_end(cx: &mut Context) {
extend_word_impl(cx, movement::move_next_long_word_end)
}
fn extend_next_sub_word_start(cx: &mut Context) {
extend_word_impl(cx, movement::move_next_sub_word_start)
}
fn extend_prev_sub_word_start(cx: &mut Context) {
extend_word_impl(cx, movement::move_prev_sub_word_start)
}
fn extend_prev_sub_word_end(cx: &mut Context) {
extend_word_impl(cx, movement::move_prev_sub_word_end)
}
fn extend_next_sub_word_end(cx: &mut Context) {
extend_word_impl(cx, movement::move_next_sub_word_end)
}
/// Separate branch to find_char designed only for `<ret>` char.
//
// This is necessary because the one document can have different line endings inside. And we
@ -3145,6 +3225,9 @@ pub fn command_palette(cx: &mut Context) {
ui::PickerColumn::new("name", |item, _| match item {
MappableCommand::Typable { name, .. } => format!(":{name}").into(),
MappableCommand::Static { name, .. } => (*name).into(),
MappableCommand::Macro { .. } => {
unreachable!("macros aren't included in the command palette")
}
}),
ui::PickerColumn::new(
"bindings",
@ -5055,6 +5138,8 @@ fn jump_forward(cx: &mut Context) {
}
doc.set_selection(view.id, selection);
// Document we switch to might not have been opened in the view before
doc.ensure_view_init(view.id);
view.ensure_cursor_in_view_center(doc, config.scrolloff);
};
}
@ -5075,6 +5160,8 @@ fn jump_backward(cx: &mut Context) {
}
doc.set_selection(view.id, selection);
// Document we switch to might not have been opened in the view before
doc.ensure_view_init(view.id);
view.ensure_cursor_in_view_center(doc, config.scrolloff);
};
}

View File

@ -2300,7 +2300,7 @@ fn run_shell_command(
move |editor: &mut Editor, compositor: &mut Compositor| {
if !output.is_empty() {
let contents = ui::Markdown::new(
format!("```sh\n{}\n```", output),
format!("```sh\n{}\n```", output.trim_end()),
editor.syn_loader.clone(),
);
let popup = Popup::new("shell", contents).position(Some(

View File

@ -177,6 +177,19 @@ fn visit_seq<S>(self, mut seq: S) -> Result<Self::Value, S::Error>
.map_err(serde::de::Error::custom)?,
)
}
// Prevent macro keybindings from being used in command sequences.
// This is meant to be a temporary restriction pending a larger
// refactor of how command sequences are executed.
if commands
.iter()
.any(|cmd| matches!(cmd, MappableCommand::Macro { .. }))
{
return Err(serde::de::Error::custom(
"macro keybindings may not be used in command sequences",
));
}
Ok(KeyTrie::Sequence(commands))
}
@ -199,6 +212,7 @@ pub fn reverse_map(&self) -> ReverseKeymap {
// recursively visit all nodes in keymap
fn map_node(cmd_map: &mut ReverseKeymap, node: &KeyTrie, keys: &mut Vec<KeyEvent>) {
match node {
KeyTrie::MappableCommand(MappableCommand::Macro { .. }) => {}
KeyTrie::MappableCommand(cmd) => {
let name = cmd.name();
if name != "no_op" {

View File

@ -58,11 +58,16 @@ macro_rules! finish_field {
() => {
let key = field.take().unwrap_or(primary_field);
// Trims one space from the end, enabling leading and trailing
// spaces in search patterns, while also retaining spaces as separators
// between column filters.
let pat = text.strip_suffix(' ').unwrap_or(&text);
if let Some(pattern) = fields.get_mut(key) {
pattern.push(' ');
pattern.push_str(text.trim());
pattern.push_str(pat);
} else {
fields.insert(key.clone(), text.trim().to_string());
fields.insert(key.clone(), pat.to_string());
}
text.clear();
};

View File

@ -19,7 +19,7 @@ tokio = { version = "1", features = ["rt", "rt-multi-thread", "time", "sync", "p
parking_lot = "0.12"
arc-swap = { version = "1.7.1" }
gix = { version = "0.64.0", features = ["attributes", "status"], default-features = false, optional = true }
gix = { version = "0.66.0", features = ["attributes", "status"], default-features = false, optional = true }
imara-diff = "0.1.7"
anyhow = "1"
@ -29,4 +29,4 @@ log = "0.4"
git = ["gix"]
[dev-dependencies]
tempfile = "3.11"
tempfile = "3.12"

View File

@ -5,7 +5,7 @@
use helix_core::Rope;
use helix_event::RenderLockGuard;
use imara_diff::Algorithm;
use parking_lot::{Mutex, MutexGuard};
use parking_lot::{RwLock, RwLockReadGuard};
use tokio::sync::mpsc::{unbounded_channel, UnboundedSender};
use tokio::task::JoinHandle;
use tokio::time::Instant;
@ -37,7 +37,7 @@ struct DiffInner {
#[derive(Clone, Debug)]
pub struct DiffHandle {
channel: UnboundedSender<Event>,
diff: Arc<Mutex<DiffInner>>,
diff: Arc<RwLock<DiffInner>>,
inverted: bool,
}
@ -48,7 +48,7 @@ pub fn new(diff_base: Rope, doc: Rope) -> DiffHandle {
fn new_with_handle(diff_base: Rope, doc: Rope) -> (DiffHandle, JoinHandle<()>) {
let (sender, receiver) = unbounded_channel();
let diff: Arc<Mutex<DiffInner>> = Arc::default();
let diff: Arc<RwLock<DiffInner>> = Arc::default();
let worker = DiffWorker {
channel: receiver,
diff: diff.clone(),
@ -70,7 +70,7 @@ pub fn invert(&mut self) {
pub fn load(&self) -> Diff {
Diff {
diff: self.diff.lock(),
diff: self.diff.read(),
inverted: self.inverted,
}
}
@ -164,7 +164,7 @@ pub fn is_pure_removal(&self) -> bool {
/// non-overlapping order
#[derive(Debug)]
pub struct Diff<'a> {
diff: MutexGuard<'a, DiffInner>,
diff: RwLockReadGuard<'a, DiffInner>,
inverted: bool,
}

View File

@ -4,7 +4,7 @@
use helix_core::{Rope, RopeSlice};
use imara_diff::intern::InternedInput;
use parking_lot::Mutex;
use parking_lot::RwLock;
use tokio::sync::mpsc::UnboundedReceiver;
use tokio::sync::Notify;
use tokio::time::{timeout, timeout_at, Duration};
@ -21,7 +21,7 @@
pub(super) struct DiffWorker {
pub channel: UnboundedReceiver<Event>,
pub diff: Arc<Mutex<DiffInner>>,
pub diff: Arc<RwLock<DiffInner>>,
pub new_hunks: Vec<Hunk>,
pub diff_finished_notify: Arc<Notify>,
}
@ -73,7 +73,7 @@ pub async fn run(mut self, diff_base: Rope, doc: Rope) {
/// `self.new_hunks` is always empty after this function runs.
/// To improve performance this function tries to reuse the allocation of the old diff previously stored in `self.line_diffs`
fn apply_hunks(&mut self, diff_base: Rope, doc: Rope) {
let mut diff = self.diff.lock();
let mut diff = self.diff.write();
diff.diff_base = diff_base;
diff.doc = doc;
swap(&mut diff.hunks, &mut self.new_hunks);

View File

@ -12,7 +12,7 @@ async fn into_diff(self, handle: JoinHandle<()>) -> Vec<Hunk> {
// dropping the channel terminates the task
drop(self.channel);
handle.await.unwrap();
let diff = diff.lock();
let diff = diff.read();
Vec::clone(&diff.hunks)
}
}

View File

@ -28,7 +28,7 @@ bitflags = "2.6"
anyhow = "1"
crossterm = { version = "0.28", optional = true }
tempfile = "3.11"
tempfile = "3.12"
# Conversion traits
once_cell = "1.19"

View File

@ -1920,12 +1920,15 @@ pub fn lsp_diagnostic_to_diagnostic(
return None;
};
let severity = diagnostic.severity.map(|severity| match severity {
lsp::DiagnosticSeverity::ERROR => Error,
lsp::DiagnosticSeverity::WARNING => Warning,
lsp::DiagnosticSeverity::INFORMATION => Info,
lsp::DiagnosticSeverity::HINT => Hint,
severity => unreachable!("unrecognized diagnostic severity: {:?}", severity),
let severity = diagnostic.severity.and_then(|severity| match severity {
lsp::DiagnosticSeverity::ERROR => Some(Error),
lsp::DiagnosticSeverity::WARNING => Some(Warning),
lsp::DiagnosticSeverity::INFORMATION => Some(Info),
lsp::DiagnosticSeverity::HINT => Some(Hint),
severity => {
log::error!("unrecognized diagnostic severity: {:?}", severity);
None
}
});
if let Some(lang_conf) = language_config {

View File

@ -44,6 +44,7 @@ haskell-language-server = { command = "haskell-language-server-wrapper", args =
idris2-lsp = { command = "idris2-lsp" }
intelephense = { command = "intelephense", args = ["--stdio"] }
jdtls = { command = "jdtls" }
jq-lsp = { command = "jq-lsp" }
jsonnet-language-server = { command = "jsonnet-language-server", args= ["-t", "--lint"] }
julia = { command = "julia", timeout = 60, args = [ "--startup-file=no", "--history-file=no", "--quiet", "-e", "using LanguageServer; runserver()", ] }
koka = { command = "koka", args = ["--language-server", "--lsstdio"] }
@ -54,11 +55,13 @@ markdoc-ls = { command = "markdoc-ls", args = ["--stdio"] }
markdown-oxide = { command = "markdown-oxide" }
marksman = { command = "marksman", args = ["server"] }
metals = { command = "metals", config = { "isHttpEnabled" = true, metals = { inlayHints = { typeParameters = {enable = true} , hintsInPatternMatch = {enable = true} } } } }
mesonlsp = { command = "mesonlsp", args = ["--lsp"] }
mint = { command = "mint", args = ["ls"] }
mojo-lsp = { command = "mojo-lsp-server" }
nil = { command = "nil" }
nimlangserver = { command = "nimlangserver" }
nimlsp = { command = "nimlsp" }
nixd = { command = "nixd" }
nls = { command = "nls" }
nu-lsp = { command = "nu", args = [ "--lsp" ] }
ocamllsp = { command = "ocamllsp" }
@ -93,6 +96,7 @@ taplo = { command = "taplo", args = ["lsp", "stdio"] }
templ = { command = "templ", args = ["lsp"] }
terraform-ls = { command = "terraform-ls", args = ["serve"] }
texlab = { command = "texlab" }
typespec = { command = "tsp-server", args = ["--stdio"] }
vala-language-server = { command = "vala-language-server" }
vhdl_ls = { command = "vhdl_ls", args = [] }
vlang-language-server = { command = "v-analyzer" }
@ -766,6 +770,23 @@ indent = { tab-width = 2, unit = " " }
name = "typescript"
source = { git = "https://github.com/tree-sitter/tree-sitter-typescript", rev = "b1bf4825d9eaa0f3bdeb1e52f099533328acfbdf", subpath = "typescript" }
[[language]]
name = "typespec"
scope = "source.typespec"
injection-regex = "(tsp|typespec)"
language-id = "typespec"
file-types = ["tsp"]
roots = ["tspconfig.yaml"]
auto-format = true
comment-token = "//"
block-comment-tokens = { start = "/*", end = "*/" }
language-servers = ["typespec"]
indent = { tab-width = 2, unit = " " }
[[grammar]]
name = "typespec"
source = { git = "https://github.com/happenslol/tree-sitter-typespec", rev = "0ee05546d73d8eb64635ed8125de6f35c77759fe" }
[[language]]
name = "tsx"
scope = "source.tsx"
@ -813,7 +834,7 @@ source = { git = "https://github.com/serenadeai/tree-sitter-scss", rev = "c478c6
name = "html"
scope = "text.html.basic"
injection-regex = "html"
file-types = ["html", "htm", "shtml", "xhtml", "xht", "jsp", "asp", "aspx", "jshtm", "volt", "rhtml"]
file-types = ["html", "htm", "shtml", "xhtml", "xht", "jsp", "asp", "aspx", "jshtm", "volt", "rhtml", "cshtml"]
block-comment-tokens = { start = "<!--", end = "-->" }
language-servers = [ "vscode-html-language-server" ]
auto-format = true
@ -866,7 +887,7 @@ injection-regex = "nix"
file-types = ["nix"]
shebangs = []
comment-token = "#"
language-servers = [ "nil" ]
language-servers = [ "nil", "nixd" ]
indent = { tab-width = 2, unit = " " }
[[grammar]]
@ -948,6 +969,8 @@ file-types = [
"tcshrc",
"bashrc_Apple_Terminal",
"zshrc_Apple_Terminal",
{ glob = "i3/config" },
{ glob = "sway/config" },
{ glob = "tmux.conf" },
{ glob = ".bash_history" },
{ glob = ".bash_login" },
@ -2143,6 +2166,7 @@ injection-regex = "meson"
file-types = [{ glob = "meson.build" }, { glob = "meson.options" }, { glob = "meson_options.txt" }]
comment-token = "#"
indent = { tab-width = 2, unit = " " }
language-servers = ["mesonlsp"]
[[grammar]]
name = "meson"
@ -3082,7 +3106,7 @@ indent = { tab-width = 4, unit = " " }
[[grammar]]
name = "just"
source = { git = "https://github.com/IndianBoy42/tree-sitter-just", rev = "379fbe36d1e441bc9414ea050ad0c85c9d6935ea" }
source = { git = "https://github.com/poliorcetics/tree-sitter-just", rev = "f58a8fd869035ac4653081401e6c2030251240ab" }
[[language]]
name = "gn"
@ -3139,7 +3163,7 @@ language-servers = ["fsharp-ls"]
[[grammar]]
name = "fsharp"
source = { git = "https://github.com/kaashyapan/tree-sitter-fsharp", rev = "18da392fd9bd5e79f357abcce13f61f3a15e3951" }
source = { git = "https://github.com/ionide/tree-sitter-fsharp", rev = "996ea9982bd4e490029f84682016b6793940113b" }
[[language]]
name = "t32"
@ -3216,6 +3240,19 @@ text-width = 72
name = "jjdescription"
source = { git = "https://github.com/kareigu/tree-sitter-jjdescription", rev = "2ddec6cad07b366aee276a608e1daa2c29d3caf2" }
[[language]]
name = "jq"
scope = "source.jq"
injection-regex = "jq"
file-types = ["jq"]
comment-token = "#"
language-servers = ["jq-lsp"]
indent = { tab-width = 2, unit = " " }
[[grammar]]
name = "jq"
source = { git = "https://github.com/flurie/tree-sitter-jq", rev = "13990f530e8e6709b7978503da9bc8701d366791" }
[[grammar]]
name = "wren"
source = { git = "https://git.sr.ht/~jummit/tree-sitter-wren", rev = "6748694be32f11e7ec6b5faeb1b48ca6156d4e06" }
@ -3726,3 +3763,26 @@ grammar = "typescript"
"{" = "}"
"(" = ")"
'"' = '"'
[[language]]
name = "gherkin"
scope = "source.feature"
file-types = ["feature"]
comment-token = "#"
indent = { tab-width = 2, unit = " " }
[[grammar]]
name = "gherkin"
source = { git = "https://github.com/SamyAB/tree-sitter-gherkin", rev = "43873ee8de16476635b48d52c46f5b6407cb5c09" }
[[language]]
name = "thrift"
scope = "source.thrift"
file-types = ["thrift"]
comment-token = "//"
block-comment-tokens = { start = "/*", end = "*/" }
indent = { tab-width = 2, unit = " " }
[[grammar]]
name = "thrift"
source = { git = "https://github.com/tree-sitter-grammars/tree-sitter-thrift" , rev = "68fd0d80943a828d9e6f49c58a74be1e9ca142cf" }

View File

@ -0,0 +1 @@
; inherits: yaml

View File

@ -0,0 +1,4 @@
(comment) @comment.inside
(comment)+ @comment.around

6
runtime/queries/env/textobjects.scm vendored Normal file
View File

@ -0,0 +1,6 @@
(comment) @comment.inside
(comment)+ @comment.around
(variable_assignment
(_) @entry.inside) @entry.around

View File

@ -1,16 +1,176 @@
;; ----------------------------------------------------------------------------
;; Literals and comments
[
(line_comment)
(block_comment)
(block_comment_content)
] @comment
(line_comment) @comment.line
(block_comment) @comment.block
(xml_doc) @comment.block.documentation
(const
[
(_) @constant
(unit) @constant.builtin
])
(primary_constr_args (_) @variable.parameter)
((identifier_pattern (long_identifier (identifier) @special))
(#match? @special "^\_.*"))
((long_identifier
(identifier)+
.
(identifier) @variable.other.member))
;; ----------------------------------------------------------------------------
;; Punctuation
(wildcard_pattern) @string.special
(type_name type_name: (_) @type)
[
(type)
(atomic_type)
] @type
(member_signature
.
(identifier) @function.method
(curried_spec
(arguments_spec
"*"* @operator
(argument_spec
(argument_name_spec
"?"? @special
name: (_) @variable.parameter)))))
(union_type_case) @constant
(rules
(rule
pattern: (_) @constant
block: (_)))
(identifier_pattern
.
(_) @constant
.
(_) @variable)
(fsi_directive_decl . (string) @namespace)
(import_decl . (_) @namespace)
(named_module
name: (_) @namespace)
(namespace
name: (_) @namespace)
(module_defn
.
(_) @namespace)
(ce_expression
.
(_) @function.macro)
(field_initializer
field: (_) @variable.other.member)
(record_fields
(record_field
.
(identifier) @variable.other.member))
(dot_expression
base: (_) @namespace
field: (_) @variable.other.member)
(value_declaration_left . (_) @variable)
(function_declaration_left
. (_) @function
[
(argument_patterns)
(argument_patterns (long_identifier (identifier)))
] @variable.parameter)
(member_defn
(method_or_prop_defn
[
(property_or_ident) @function
(property_or_ident
instance: (identifier) @variable.builtin
method: (identifier) @function.method)
]
args: (_)* @variable.parameter))
(application_expression
.
[
(long_identifier_or_op [
(long_identifier (identifier)* (identifier) @function)
(identifier) @function
])
(typed_expression . (long_identifier_or_op (long_identifier (identifier)* . (identifier) @function.call)))
(dot_expression base: (_) @variable.other.member field: (_) @function)
] @function)
((infix_expression
.
(_)
.
(infix_op) @operator
.
(_) @function
)
(#eq? @operator "|>")
)
((infix_expression
.
(_) @function
.
(infix_op) @operator
.
(_)
)
(#eq? @operator "<|")
)
[
(xint)
(int)
(int16)
(uint16)
(int32)
(uint32)
(int64)
(uint64)
(nativeint)
(unativeint)
] @constant.numeric.integer
[
(ieee32)
(ieee64)
(float)
(decimal)
] @constant.numeric.float
(bool) @constant.builtin.boolean
([
(string)
(triple_quoted_string)
(verbatim_string)
(char)
] @string)
(compiler_directive_decl) @keyword.directive
(attribute) @attribute
[
"("
")"
@ -20,31 +180,40 @@
"]"
"[|"
"|]"
"{|"
"|}"
"[<"
">]"
] @punctuation.bracket
(format_string_eval
[
"{"
"}"
] @punctuation.special)
[
","
","
";"
] @punctuation.delimiter
[
"|"
"|"
"="
">"
"<"
"-"
"~"
"->"
"<-"
"&&"
"||"
":>"
":?>"
(infix_op)
(prefix_op)
(symbolic_op)
] @operator
(attribute) @attribute
[
"if"
"then"
@ -53,22 +222,29 @@
"when"
"match"
"match!"
] @keyword.control.conditional
[
"and"
"or"
"&&"
"||"
"then"
] @keyword.control.conditional
"not"
"upcast"
"downcast"
] @keyword.operator
[
"return"
"return!"
"yield"
"yield!"
] @keyword.control.return
[
"for"
"while"
] @keyword.control.return
"downto"
"to"
] @keyword.control.repeat
[
@ -82,115 +258,93 @@
"delegate"
"static"
"inline"
"internal"
"mutable"
"override"
"private"
"public"
"rec"
"global"
(access_modifier)
] @keyword.storage.modifier
[
"enum"
"let"
"let!"
"use"
"use!"
"member"
"module"
"namespace"
] @keyword.function
[
"enum"
"type"
] @keyword.storage
"inherit"
"interface"
] @keyword.storage.type
(try_expression
[
"try"
"with"
"finally"
] @keyword.control.exception)
((identifier) @keyword.control.exception
(#any-of? @keyword.control.exception "failwith" "failwithf" "raise" "reraise"))
[
"as"
"assert"
"begin"
"end"
"done"
"default"
"in"
"do"
"do!"
"done"
"downcast"
"downto"
"end"
"event"
"field"
"finally"
"fun"
"function"
"get"
"global"
"inherit"
"interface"
"set"
"lazy"
"new"
"not"
"null"
"of"
"param"
"property"
"set"
"struct"
"try"
"upcast"
"use"
"use!"
"val"
"module"
"namespace"
"with"
"yield"
"yield!"
] @keyword
[
"true"
"false"
"unit"
] @constant.builtin
"null"
] @constant.builtin
[
(type)
(const)
] @constant
(match_expression "with" @keyword.control.conditional)
[
(union_type_case)
(rules (rule (identifier_pattern)))
] @type.enum
((type
(long_identifier (identifier) @type.builtin))
(#any-of? @type.builtin "bool" "byte" "sbyte" "int16" "uint16" "int" "uint" "int64" "uint64" "nativeint" "unativeint" "decimal" "float" "double" "float32" "single" "char" "string" "unit"))
(fsi_directive_decl (string) @namespace)
(preproc_if
[
"#if" @keyword.directive
"#endif" @keyword.directive
]
condition: (_)? @keyword.directive)
[
(import_decl (long_identifier))
(named_module (long_identifier))
(namespace (long_identifier))
(named_module
name: (long_identifier) )
(namespace
name: (long_identifier) )
] @namespace
(preproc_else
"#else" @keyword.directive)
((long_identifier
(identifier)+ @namespace
.
(identifier)))
(dot_expression
base: (long_identifier_or_op) @variable.other.member
field: (long_identifier_or_op) @function)
[
;;(value_declaration_left (identifier_pattern) )
(function_declaration_left (identifier) )
(call_expression (long_identifier_or_op (long_identifier)))
;;(application_expression (long_identifier_or_op (long_identifier)))
] @function
[
(string)
(triple_quoted_string)
] @string
[
(int)
(int16)
(int32)
(int64)
(float)
(decimal)
] @constant.numeric
(long_identifier_or_op
(op_identifier) @operator)
((identifier) @namespace
(#any-of? @namespace "Array" "Async" "Directory" "File" "List" "Option" "Path" "Map" "Set" "Lazy" "Seq" "Task" "String" "Result" ))

View File

@ -0,0 +1,8 @@
([
(line_comment)
(block_comment_content)
] @injection.content
(#set! injection.language "comment"))
((xml_doc (xml_doc_content) @injection.content)
(#set! injection.language "xml"))

View File

@ -1,25 +1,32 @@
; Scopes
;-------
(identifier) @local.reference
[
(ce_expression)
(module_defn)
(for_expression)
(do_expression)
(fun_expression)
(function_expression)
(try_expression)
(match_expression)
(elif_expression)
(if_expression)
(namespace)
(named_module)
(function_or_value_defn)
] @local.scope
; Definitions
;------------
(value_declaration_left
.
[
(_ (identifier) @local.definition)
(_ (_ (identifier) @local.definition))
(_ (_ (_ (identifier) @local.definition)))
(_ (_ (_ (_ (identifier) @local.definition))))
(_ (_ (_ (_ (_ (identifier) @local.definition)))))
(_ (_ (_ (_ (_ (_ (identifier) @local.definition))))))
])
(function_or_value_defn) @local.definition
; References
;-----------
(identifier) @local.reference
(function_declaration_left
.
((_) @local.definition)
((argument_patterns
[
(_ (identifier) @local.definition)
(_ (_ (identifier) @local.definition))
(_ (_ (_ (identifier) @local.definition)))
(_ (_ (_ (_ (identifier) @local.definition))))
(_ (_ (_ (_ (_ (identifier) @local.definition)))))
(_ (_ (_ (_ (_ (_ (identifier) @local.definition))))))
])
))

View File

@ -0,0 +1,17 @@
[
(feature_keyword)
(rule_keyword)
(background_keyword)
(scenario_keyword)
(given_keyword)
(when_keyword)
(then_keyword)
(and_keyword)
(but_keyword)
(asterisk_keyword)
] @keyword
(tag) @function
(doc_string) @string
(data_table) @special
(comment) @comment

View File

@ -0,0 +1,6 @@
(comment) @comment.inside
(comment)+ @comment.around
(variable
(_) @entry.inside) @entry.around

View File

@ -4,3 +4,8 @@
(function_arguments
((_) @parameter.inside . ","? @parameter.around) @parameter.around)
(attribute
(_) @entry.inside) @entry.around
(tuple
(_) @entry.around)

View File

@ -0,0 +1,10 @@
(comment) @comment.inside
(comment)+ @comment.around
(pair
(_) @entry.inside) @entry.around
(array
(_) @entry.around)

View File

@ -1,13 +1,39 @@
(tag_name) @tag
(erroneous_end_tag_name) @tag.error
(erroneous_end_tag_name) @error
(doctype) @constant
(attribute_name) @attribute
(comment) @comment
[
"\""
(attribute_value)
] @string
((attribute
(attribute_name) @_attr
(quoted_attribute_value (attribute_value) @markup.link.url))
(#any-of? @_attr "href" "src"))
((element
(start_tag
(tag_name) @_tag)
(text) @markup.link.label)
(#eq? @_tag "a"))
(attribute [(attribute_value) (quoted_attribute_value)] @string)
((element
(start_tag
(tag_name) @_tag)
(text) @markup.bold)
(#any-of? @_tag "strong" "b"))
((element
(start_tag
(tag_name) @_tag)
(text) @markup.italic)
(#any-of? @_tag "em" "i"))
((element
(start_tag
(tag_name) @_tag)
(text) @markup.strikethrough)
(#any-of? @_tag "s" "del"))
[
"<"

View File

@ -0,0 +1,160 @@
;; From nvim-treesitter, contributed by @ObserverOfTime et al.
; Variables
(variable) @variable
((variable) @constant.builtin
(#eq? @constant.builtin "$ENV"))
((variable) @constant.builtin
(#eq? @constant.builtin "$__loc__"))
; Properties
(index
(identifier) @variable.other.member)
; Labels
(query
label: (variable) @label)
(query
break_statement: (variable) @label)
; Literals
(number) @constant.numeric
(string) @string
[
"true"
"false"
] @constant.builtin.boolean
"null" @type.builtin
; Interpolation
[
"\\("
")"
] @special
; Format
(format) @attribute
; Functions
(funcdef
(identifier) @function)
(funcdefargs
(identifier) @variable.parameter)
[
"reduce"
"foreach"
] @function.builtin
((funcname) @function
.
"(")
; jq -n 'builtins | map(split("/")[0]) | unique | .[]'
((funcname) @function.builtin
(#any-of? @function.builtin
"IN" "INDEX" "JOIN" "abs" "acos" "acosh" "add" "all" "any" "arrays" "ascii_downcase"
"ascii_upcase" "asin" "asinh" "atan" "atan2" "atanh" "booleans" "bsearch" "builtins" "capture"
"cbrt" "ceil" "combinations" "contains" "copysign" "cos" "cosh" "debug" "del" "delpaths" "drem"
"empty" "endswith" "env" "erf" "erfc" "error" "exp" "exp10" "exp2" "explode" "expm1" "fabs"
"fdim" "finites" "first" "flatten" "floor" "fma" "fmax" "fmin" "fmod" "format" "frexp"
"from_entries" "fromdate" "fromdateiso8601" "fromjson" "fromstream" "gamma" "get_jq_origin"
"get_prog_origin" "get_search_list" "getpath" "gmtime" "group_by" "gsub" "halt" "halt_error"
"has" "hypot" "implode" "in" "index" "indices" "infinite" "input" "input_filename"
"input_line_number" "inputs" "inside" "isempty" "isfinite" "isinfinite" "isnan" "isnormal"
"iterables" "j0" "j1" "jn" "join" "keys" "keys_unsorted" "last" "ldexp" "length" "lgamma"
"lgamma_r" "limit" "localtime" "log" "log10" "log1p" "log2" "logb" "ltrimstr" "map" "map_values"
"match" "max" "max_by" "min" "min_by" "mktime" "modf" "modulemeta" "nan" "nearbyint" "nextafter"
"nexttoward" "normals" "not" "now" "nth" "nulls" "numbers" "objects" "path" "paths" "pick" "pow"
"pow10" "range" "recurse" "remainder" "repeat" "reverse" "rindex" "rint" "round" "rtrimstr"
"scalars" "scalb" "scalbln" "scan" "select" "setpath" "significand" "sin" "sinh" "sort"
"sort_by" "split" "splits" "sqrt" "startswith" "stderr" "strflocaltime" "strftime" "strings"
"strptime" "sub" "tan" "tanh" "test" "tgamma" "to_entries" "todate" "todateiso8601" "tojson"
"tonumber" "tostream" "tostring" "transpose" "trunc" "truncate_stream" "type" "unique"
"unique_by" "until" "utf8bytelength" "values" "walk" "while" "with_entries" "y0" "y1" "yn"))
; Keywords
[
"def"
"as"
"label"
"module"
"break"
] @keyword
[
"import"
"include"
] @keyword.control.import
[
"if"
"then"
"elif"
"else"
"end"
] @keyword.control.conditional
[
"try"
"catch"
] @keyword.control.exception
[
"or"
"and"
] @keyword.operator
; Operators
[
"."
"=="
"!="
">"
">="
"<="
"<"
"="
"+"
"-"
"*"
"/"
"%"
"+="
"-="
"*="
"/="
"%="
"//="
"|"
"?"
"//"
"?//"
(recurse) ; ".."
] @operator
; Punctuation
[
";"
","
":"
] @punctuation.delimiter
[
"["
"]"
"{"
"}"
"("
")"
] @punctuation.bracket
; Comments
(comment) @comment.line

View File

@ -0,0 +1,25 @@
;; From nvim-treesitter, contributed by @ObserverOfTime et al.
((comment) @injection.content
(#set! injection.language "comment"))
; test(val)
(query
((funcname) @_function
(#any-of? @_function "test" "match" "capture" "scan" "split" "splits" "sub" "gsub"))
(args
.
(query
(string) @injection.content
(#set! injection.language "regex"))))
; test(regex; flags)
(query
((funcname) @_function
(#any-of? @_function "test" "match" "capture" "scan" "split" "splits" "sub" "gsub"))
(args
.
(args
(query
(string) @injection.content
(#set! injection.language "regex")))))

View File

@ -0,0 +1,12 @@
;; From nvim-treesitter, contributed by @ObserverOfTime et al.
(funcdef
(identifier) @local.definition)
(funcdefargs
(identifier) @local.definition)
(funcname) @local.reference
(index
(identifier) @local.reference)

View File

@ -0,0 +1,8 @@
(comment) @comment.inside
(comment)+ @comment.around
(funcdef
(query) @function.inside) @function.around
(objectkeyval
(_) @entry.inside) @entry.around

View File

@ -1,5 +1,3 @@
; From <https://github.com/IndianBoy42/tree-sitter-just/blob/6c2f018ab1d90946c0ce029bb2f7d57f56895dff/queries-flavored/helix/folds.scm>
; Define collapse points
([

View File

@ -1,5 +1,3 @@
; From <https://github.com/IndianBoy42/tree-sitter-just/blob/6c2f018ab1d90946c0ce029bb2f7d57f56895dff/queries-flavored/helix/highlights.scm>
; This file specifies how matched syntax patterns should be highlighted
[
@ -26,35 +24,57 @@
(identifier) @variable)
(alias
left: (identifier) @variable)
name: (identifier) @variable)
(assignment
left: (identifier) @variable)
name: (identifier) @variable)
(shell_variable_name) @variable
; Functions
(recipe_header
(recipe
name: (identifier) @function)
(dependency
name: (identifier) @function)
(dependency_expression
name: (identifier) @function)
(recipe_dependency
name: (identifier) @function.call)
(function_call
name: (identifier) @function)
name: (identifier) @function.builtin)
; Parameters
(parameter
(recipe_parameter
name: (identifier) @variable.parameter)
; Namespaces
(module
(mod
name: (identifier) @namespace)
; Paths
(mod
(path) @string.special.path)
(import
(path) @string.special.path)
; Shebangs
(shebang_line) @keyword.directive
(shebang_line
(shebang_shell) @string.special)
(shell_expanded_string
[
(expansion_short_start)
(expansion_long_start)
(expansion_long_middle)
(expansion_long_end)
] @punctuation.special)
; Operators
[
@ -95,55 +115,31 @@
; Literals
(boolean) @constant.builtin.boolean
; Booleans are not allowed anywhere except in settings
(setting
(boolean) @constant.builtin.boolean)
[
(string)
(external_command)
] @string
(escape_sequence) @constant.character.escape
[
(escape_sequence)
(escape_variable_end)
] @constant.character.escape
; Comments
(comment) @comment.line
(shebang) @keyword.directive
; highlight known settings (filtering does not always work)
; highlight known settings
(setting
left: (identifier) @keyword
(#any-of? @keyword
"allow-duplicate-recipes"
"dotenv-filename"
"dotenv-load"
"dotenv-path"
"export"
"fallback"
"ignore-comments"
"positional-arguments"
"shell"
"tempdi"
"windows-powershell"
"windows-shell"))
name: (_) @keyword.function)
; highlight known attributes (filtering does not always work)
; highlight known attributes
(attribute
(identifier) @attribute
(#any-of? @attribute
"private"
"allow-duplicate-recipes"
"dotenv-filename"
"dotenv-load"
"dotenv-path"
"export"
"fallback"
"ignore-comments"
"positional-arguments"
"shell"
"tempdi"
"windows-powershell"
"windows-shell"))
name: (identifier) @attribute)
; Numbers are part of the syntax tree, even if disallowed
(numeric_error) @error

View File

@ -1,5 +1,3 @@
; From <https://github.com/IndianBoy42/tree-sitter-just/blob/6c2f018ab1d90946c0ce029bb2f7d57f56895dff/queries-flavored/helix/indents.scm>
;
; This query specifies how to auto-indent logical blocks.
;
; Better documentation with diagrams is in https://docs.helix-editor.com/guides/indent.html

View File

@ -1,5 +1,3 @@
; From <https://github.com/IndianBoy42/tree-sitter-just/blob/6c2f018ab1d90946c0ce029bb2f7d57f56895dff/queries-flavored/helix/injections.scm>
;
; Specify nested languages that live within a `justfile`
; ================ Always applicable ================
@ -8,7 +6,7 @@
(#set! injection.language "comment"))
; Highlight the RHS of `=~` as regex
((regex_literal
((regex
(_) @injection.content)
(#set! injection.language "regex"))
@ -21,7 +19,7 @@
(#set! injection.include-children)) @injection.content
(external_command
(command_body) @injection.content
(content) @injection.content
(#set! injection.language "bash"))
; ================ Global language specified ================
@ -43,7 +41,7 @@
; they default to bash. Limitations...
; See https://github.com/tree-sitter/tree-sitter/issues/880 for more on that.
(source_file
(file
(setting "shell" ":=" "[" (string) @_langstr
(#match? @_langstr ".*(powershell|pwsh|cmd).*")
(#set! injection.language "powershell"))
@ -57,10 +55,10 @@
(expression
(value
(external_command
(command_body) @injection.content))))
(content) @injection.content))))
])
(source_file
(file
(setting "shell" ":=" "[" (string) @injection.language
(#not-match? @injection.language ".*(powershell|pwsh|cmd).*"))
[
@ -73,12 +71,12 @@
(expression
(value
(external_command
(command_body) @injection.content))))
(content) @injection.content))))
])
; ================ Recipe language specified - Helix only ================
; Set highlighting for recipes that specify a language using builtin shebang matching
(recipe_body
(shebang) @injection.shebang
(shebang_line) @injection.shebang
(#set! injection.include-children)) @injection.content

View File

@ -1,5 +1,3 @@
; From <https://github.com/IndianBoy42/tree-sitter-just/blob/6c2f018ab1d90946c0ce029bb2f7d57f56895dff/queries-flavored/helix/locals.scm>
;
; This file tells us about the scope of variables so e.g. local
; variables override global functions with the same name
@ -10,32 +8,29 @@
; Definitions
(alias
left: (identifier) @local.definition)
name: (identifier) @local.definition)
(assignment
left: (identifier) @local.definition)
(module
name: (identifier) @local.definition)
(parameter
(mod
name: (identifier) @local.definition)
(recipe_header
(recipe_parameter
name: (identifier) @local.definition)
(recipe
name: (identifier) @local.definition)
; References
(alias
right: (identifier) @local.reference)
name: (identifier) @local.reference)
(function_call
name: (identifier) @local.reference)
(dependency
name: (identifier) @local.reference)
(dependency_expression
(recipe_dependency
name: (identifier) @local.reference)
(value

View File

@ -1,18 +1,19 @@
; From <https://github.com/IndianBoy42/tree-sitter-just/blob/6c2f018ab1d90946c0ce029bb2f7d57f56895dff/queries-flavored/helix/textobjects.scm>
;
; Specify how to navigate around logical blocks in code
(assert_parameters
((_) @parameter.inside . ","? @parameter.around)) @parameter.around
(recipe
(recipe_body) @function.inside) @function.around
(parameters
(recipe_parameters
((_) @parameter.inside . ","? @parameter.around)) @parameter.around
(dependency_expression
(recipe_dependency
(_) @parameter.inside) @parameter.around
(function_call
arguments: (sequence
(expression) @parameter.inside) @parameter.around) @function.around
(function_parameters
((_) @parameter.inside . ","? @parameter.around)) @parameter.around) @function.around
(comment) @comment.around

View File

@ -7,3 +7,6 @@
(function_expression
body: (_) @function.inside) @function.around
(binding
(_) @entry.inside) @entry.around

View File

@ -0,0 +1,17 @@
(model_declaration
((statement_block) @class.inside)) @class.around
(call_expression
(arguments (_) @parameter.inside . ","? @parameter.around) @parameter.around)
(column_declaration) @entry.around
(array (_) @entry.around)
(assignment_expression
(_) @entry.inside) @entry.around
(developer_comment) @comment.inside
(developer_comment)+ @comment.around

View File

@ -55,6 +55,55 @@
"'" @label
(identifier) @label)
; ---
; Prelude
; ---
((identifier) @type.enum.variant.builtin
(#any-of? @type.enum.variant.builtin "Some" "None" "Ok" "Err"))
((type_identifier) @type.builtin
(#any-of?
@type.builtin
"Send"
"Sized"
"Sync"
"Unpin"
"Drop"
"Fn"
"FnMut"
"FnOnce"
"AsMut"
"AsRef"
"From"
"Into"
"DoubleEndedIterator"
"ExactSizeIterator"
"Extend"
"IntoIterator"
"Iterator"
"Option"
"Result"
"Clone"
"Copy"
"Debug"
"Default"
"Eq"
"Hash"
"Ord"
"PartialEq"
"PartialOrd"
"ToOwned"
"Box"
"String"
"ToString"
"Vec"
"FromIterator"
"TryFrom"
"TryInto"))
; ---
; Punctuation
; ---

View File

@ -0,0 +1,4 @@
(comment) @comment.inside
(comment)+ @comment.around

View File

@ -0,0 +1,12 @@
[
(annotation_definition)
(enum_definition)
(exception_definition)
(function_definition)
(senum_definition)
(service_definition)
(struct_definition)
(union_definition)
(comment)
] @fold

View File

@ -0,0 +1,211 @@
; Variables
((identifier) @variable)
; Includes
[
"include"
"cpp_include"
] @keyword
; Function
(function_definition
(identifier) @function)
; Fields
(field (identifier) @variable.other.member)
; Parameters
(function_definition
(parameters
(parameter (identifier) @variable.parameter)))
(throws
(parameters
(parameter (identifier) @keyword.control.exception)))
; Types
(typedef_identifier) @type
(struct_definition
"struct" (identifier) @type)
(union_definition
"union" (identifier) @type)
(exception_definition
"exception" (identifier) @type)
(service_definition
"service" (identifier) @type)
(interaction_definition
"interaction" (identifier) @type)
(type
type: (identifier) @type)
(definition_type
type: (identifier) @type)
; Constants
(const_definition (identifier) @constant)
(enum_definition "enum"
. (identifier) @type
"{" (identifier) @constant "}")
; Builtin Types
(primitive) @type.builtin
[
"list"
"map"
"set"
"sink"
"stream"
"void"
] @type.builtin
; Namespace
(namespace_declaration
(namespace_scope) @tag
[(namespace) @namespace (_ (identifier) @namespace)])
; Attributes
(annotation_definition
(annotation_identifier (identifier) @attribute))
(fb_annotation_definition
"@" @attribute (annotation_identifier (identifier) @attribute)
(identifier)? @attribute)
(namespace_uri (string) @attribute)
; Operators
[
"="
"&"
] @operator
; Exceptions
[
"throws"
] @keyword.control.exception
; Keywords
[
"enum"
"exception"
"extends"
"interaction"
"namespace"
"senum"
"service"
"struct"
"typedef"
"union"
"uri"
] @keyword
; Deprecated Keywords
[
"cocoa_prefix"
"cpp_namespace"
"csharp_namespace"
"delphi_namespace"
"java_package"
"perl_package"
"php_namespace"
"py_module"
"ruby_namespace"
"smalltalk_category"
"smalltalk_prefix"
"xsd_all"
"xsd_attrs"
"xsd_namespace"
"xsd_nillable"
"xsd_optional"
] @keyword
; Extended Kewords
[
"package"
"performs"
] @keyword
[
"async"
"oneway"
] @keyword
; Qualifiers
[
"client"
"const"
"idempotent"
"optional"
"permanent"
"readonly"
"required"
"safe"
"server"
"stateful"
"transient"
] @type.directive
; Literals
(string) @string
(escape_sequence) @constant.character.escape
(namespace_uri
(string) @string.special)
(number) @constant.numeric.integer
(double) @constant.numeric.float
(boolean) @constant.builtin.boolean
; Typedefs
(typedef_identifier) @type.definition
; Punctuation
[
"*"
] @punctuation.special
["{" "}"] @punctuation.bracket
["(" ")"] @punctuation.bracket
["[" "]"] @punctuation.bracket
["<" ">"] @punctuation.bracket
[
"."
","
";"
":"
] @punctuation.delimiter
; Comments
(comment) @comment

View File

@ -0,0 +1,2 @@
((comment) @injection.content
(#set! injection.language "comment"))

View File

@ -0,0 +1,51 @@
; Scopes
[
(document)
(definition)
] @local.scope
; References
(identifier) @local.reference
; Definitions
(annotation_identifier) @local.definition
; (const_definition (identifier) @definition.constant)
; (enum_definition "enum"
; . (identifier) @definition.enum
; "{" (identifier) @definition.constant "}")
; (senum_definition "senum"
; . (identifier) @definition.enum)
; (field (identifier) @definition.field)
; (function_definition (identifier) @definition.function)
; (namespace_declaration
; "namespace" (namespace_scope)
; . (_) @definition.namespace
; (namespace_uri)?)
; (parameter (identifier) @definition.parameter)
; (struct_definition
; "struct" . (identifier) @definition.type)
; (union_definition
; "union" . (identifier) @definition.type)
; (exception_definition
; "exception" . (identifier) @definition.type)
; (service_definition
; "service" . (identifier) @definition.type)
; (interaction_definition
; "interaction" . (identifier) @definition.type)
; (typedef_identifier) @definition.type

View File

@ -0,0 +1,177 @@
; Keywords
[
"is"
"extends"
"valueof"
] @keyword.operator
[
"namespace"
"scalar"
"interface"
"alias"
] @keyword
[
"model"
"enum"
"union"
] @keyword.storage.type
[
"op"
"fn"
"dec"
] @keyword.function
"extern" @keyword.storage.modifier
[
"import"
"using"
] @keyword.control.import
[
"("
")"
"{"
"}"
"<"
">"
"["
"]"
] @punctuation.bracket
[
","
";"
"."
":"
] @punctuation.delimiter
[
"|"
"&"
"="
"..."
] @operator
"?" @punctuation.special
; Imports
(import_statement
(quoted_string_literal) @string.special.path)
; Namespaces
(using_statement
module: (identifier_or_member_expression) @namespace)
(namespace_statement
name: (identifier_or_member_expression) @namespace)
; Comments
[
(single_line_comment)
] @comment.line
[
(multi_line_comment)
] @comment.block
; Decorators
(decorator
"@" @attribute
name: (identifier_or_member_expression) @attribute)
(augment_decorator_statement
name: (identifier_or_member_expression) @attribute)
(decorator
(decorator_arguments) @variable.parameter)
; Scalars
(scalar_statement
name: (identifier) @type)
; Models
(model_statement
name: (identifier) @type)
(model_property
name: (identifier) @variable.other.member)
; Operations
(operation_statement
name: (identifier) @function.method)
(operation_arguments
(model_property
name: (identifier) @variable.parameter))
(template_parameter
name: (identifier) @type.parameter)
(function_parameter
name: (identifier) @variable.parameter)
; Interfaces
(interface_statement
name: (identifier) @type)
(interface_statement
(interface_body
(interface_member
(identifier) @function.method)))
; Enums
(enum_statement
name: (identifier) @type.enum)
(enum_member
name: (identifier) @constant)
; Unions
(union_statement
name: (identifier) @type)
(union_variant
name: (identifier) @type.enum.variant)
; Aliases
(alias_statement
name: (identifier) @type)
; Built-in types
[
(quoted_string_literal)
(triple_quoted_string_literal)
] @string
(escape_sequence) @constant.character.escape
(boolean_literal) @constant.builtin.boolean
[
(decimal_literal)
(hex_integer_literal)
(binary_integer_literal)
] @constant.numeric.integer
(builtin_type) @type.builtin
; Identifiers
(identifier_or_member_expression) @type

View File

@ -0,0 +1,18 @@
[
(model_expression)
(tuple_expression)
(namespace_body)
(interface_body)
(union_body)
(enum_body)
(template_arguments)
(template_parameters)
(operation_arguments)
] @indent.begin
[
"}"
")"
">"
"]"
] @indent.end

View File

@ -0,0 +1,5 @@
([
(single_line_comment)
(multi_line_comment)
] @injection.content
(#set! injection.language "comment"))

View File

@ -0,0 +1,51 @@
; Classes
(enum_statement
(enum_body) @class.inside) @class.around
(model_statement
(model_expression) @class.inside) @class.around
(union_statement
(union_body) @class.inside) @class.around
; Interfaces
(interface_statement
(interface_body
(interface_member) @function.around) @class.inside) @class.around
; Comments
[
(single_line_comment)
(multi_line_comment)
] @comment.inside
[
(single_line_comment)
(multi_line_comment)
]+ @comment.around
; Functions
[
(decorator)
(decorator_declaration_statement)
(function_declaration_statement)
(operation_statement)
] @function.around
(function_parameter_list
(function_parameter)? @parameter.inside)* @function.inside
(decorator_arguments
(expression_list
(_) @parameter.inside)*) @function.inside
(operation_arguments
(model_property)? @parameter.inside)* @function.inside
(template_parameters
(template_parameter_list
(template_parameter) @parameter.inside)) @function.inside

View File

@ -3,4 +3,8 @@
(function_body_declaration
(function_identifier
(function_identifier
(simple_identifier) @function.inside)))) @function.around
(simple_identifier) @function.inside)))) @function.around
(comment) @comment.inside
(comment)+ @comment.around

View File

@ -0,0 +1,7 @@
(comment) @comment.inside
(comment)+ @comment.around
(block_mapping_pair
(_) @entry.inside) @entry.around

View File

@ -1,7 +1,7 @@
# Author: David Else <12832280+David-Else@users.noreply.github.com>
# SYNTAX
"attribute" = "fn_declaration"
"attribute" = "variable"
"comment" = "dark_green"
"constant" = "constant"
"constant.builtin" = "blue2"
@ -39,10 +39,10 @@
# MARKUP
"markup.heading" = { fg = "blue2", modifiers = ["bold"] }
"markup.list" = "blue3"
"markup.bold" = { fg = "blue2", modifiers = ["bold"] }
"markup.bold" = { modifiers = ["bold"] }
"markup.italic" = { modifiers = ["italic"] }
"markup.strikethrough" = { modifiers = ["crossed_out"] }
"markup.link.url" = { modifiers = ["underlined"] }
"markup.link.url" = { underline.style= "line" }
"markup.link.text" = "orange"
"markup.quote" = "dark_green"
"markup.raw" = "orange"
@ -57,7 +57,7 @@
# TODO: Alternate bg colour for `ui.cursor.match` and `ui.selection`.
"ui.cursor" = { fg = "cursor", modifiers = ["reversed"] }
"ui.cursor.primary" = { fg = "cursor", modifiers = ["reversed"] }
"ui.cursor.match" = { bg = "#3a3d41", modifiers = ["underlined"] }
"ui.cursor.match" = { bg = "#3a3d41", underline.style = "line" }
"ui.selection" = { bg = "#3a3d41" }
"ui.selection.primary" = { bg = "dark_blue" }
"ui.linenr" = { fg = "dark_gray" }
@ -80,6 +80,8 @@
"ui.highlight.frameline" = { bg = "#4b4b18" }
"ui.debug.active" = { fg = "#ffcc00" }
"ui.debug.breakpoint" = { fg = "#e51400" }
"ui.picker.header.column" = { underline.style = "line" }
"ui.picker.header.column.active" = { fg ="white", underline.style = "line" }
"warning" = { fg = "gold2" }
"error" = { fg = "red" }
"info" = { fg = "light_blue" }

View File

@ -65,7 +65,7 @@
"diff.minus" = "red"
"ui.background" = { bg = "bg0" }
"ui.background.separator" = "bg_visual"
"ui.background.separator" = "grey0"
"ui.cursor" = { fg = "bg1", bg = "grey2" }
"ui.cursor.insert" = { fg = "bg0", bg = "grey1" }
"ui.cursor.select" = { fg = "bg0", bg = "blue" }
@ -90,6 +90,7 @@
"bold",
] }
"ui.popup" = { fg = "grey2", bg = "bg2" }
"ui.picker.header" = { modifiers = ["bold", "underlined"] }
"ui.window" = { fg = "bg4", bg = "bg_dim" }
"ui.help" = { fg = "fg", bg = "bg2" }
"ui.text" = "fg"

View File

@ -64,7 +64,7 @@
"diff.minus" = "red"
"ui.background" = { bg = "bg0" }
"ui.background.separator" = "bg_visual"
"ui.background.separator" = "grey0"
"ui.cursor" = { fg = "bg1", bg = "grey2" }
"ui.cursor.insert" = { fg = "bg0", bg = "grey1" }
"ui.cursor.select" = { fg = "bg0", bg = "blue" }
@ -89,6 +89,7 @@
"bold",
] }
"ui.popup" = { fg = "grey2", bg = "bg2" }
"ui.picker.header" = { modifiers = ["bold", "underlined"] }
"ui.window" = { fg = "bg4", bg = "bg_dim" }
"ui.help" = { fg = "fg", bg = "bg2" }
"ui.text" = "fg"

View File

@ -94,6 +94,8 @@
"ui.menu" = { fg = "fg1", bg = "bg2" }
"ui.menu.selected" = { fg = "bg2", bg = "blue1", modifiers = ["bold"] }
"ui.popup" = { bg = "bg1" }
"ui.picker.header.column" = { underline.style = "line" }
"ui.picker.header.column.active" = { modifiers = ["bold"], underline.style = "line" }
"ui.selection" = { bg = "bg2" }
"ui.selection.primary" = { bg = "bg3" }

View File

@ -0,0 +1,128 @@
# Author : Chromo-residuum-opec <development.0extl@simplelogin.com>
"attribute" = { fg = "green" }
"boolean" = { fg = "purple" }
"character" = { fg = "purple" }
"comment" = { fg = "comment_fg" }
"conditional" = { fg = "blue" }
"constant" = { fg = "purple" }
"constructor" = { fg = "blue" }
"diagnostic.deprecated" = { modifiers = ["crossed_out"] }
"diagnostic.error" = { underline = { style = "curl", color = "red" } }
"diagnostic.hint" = { underline = { style = "curl", color = "comment_fg" } }
"diagnostic.info" = { underline = { style = "curl", color = "cyan" } }
"diagnostic.unnecessary" = { modifiers = ["dim"] }
"diagnostic.warning" = { underline = { style = "curl", color = "orange" } }
"diff.delta" = { fg = "blue" }
"diff.delta.gutter" = { fg = "cyan", bg = "linenr_bg" }
"diff.minus" = { fg = "red" }
"diff.minus.gutter" = { fg = "red", bg = "linenr_bg" }
"diff.plus" = { fg = "green" }
"diff.plus.gutter" = { fg = "green", bg = "linenr_bg" }
"error" = { fg = "red" }
"exception" = { fg = "blue" }
"field" = { fg = "background_fg" }
"float" = { fg = "purple" }
"function" = { fg = "pale" }
"function.macro" = { fg = "green" }
"hint" = { fg = "comment_fg" }
"identifier" = { fg = "blue" }
"info" = { fg = "cyan" }
"keyword" = { fg = "blue" }
"keyword.directive" = { fg = "green" }
"keyword.import" = { fg = "pale" }
"label" = { fg = "green" }
"markup.bold" = { modifiers = ["bold"] }
"markup.heading" = { fg = "blue", modifiers = ["bold"] }
"markup.italic" = { modifiers = ["italic"] }
"markup.link" = { fg = "blue", underline = { style = "line" } }
"markup.link.label" = { fg = "cyan" }
"markup.link.text" = { fg = "cyan" }
"markup.link.url" = { underline = { style = "line" } }
"markup.list" = { fg = "orange", modifiers = ["bold"] }
"markup.raw" = { fg = "cyan" }
"markup.raw.inline" = { bg = "black", fg = "blue" }
"markup.strikethrough" = { modifiers = ["crossed_out"] }
"method" = { fg = "pale" }
"namespace" = { fg = "blue" }
"number" = { fg = "purple" }
"operator" = { fg = "blue" }
"parameter" = { fg = "background_fg" }
"property" = { fg = "background_fg" }
"punctuation.bracket" = { fg = "background_fg" }
"punctuation.delimiter" = { fg = "background_fg" }
"punctuation.special" = { fg = "green" }
"repeat" = { fg = "blue" }
"special" = { fg = "green" }
"string" = { fg = "cyan" }
"string.escape" = { fg = "green" }
"string.special" = { fg = "green" }
"tag" = { fg = "blue" }
"tag.attribute" = { fg = "purple" }
"text" = { fg = "background_fg" }
"type" = { fg = "blue" }
"ui.background" = { fg = "background_fg", bg = "background_bg" }
"ui.background.separator" = { fg = "comment_fg" }
"ui.bufferline.active" = { fg = "pale" }
"ui.cursor.match" = { fg = "background_fg", bg = "matchparen_bg" }
"ui.cursor.normal" = { bg = "gray" }
"ui.cursor.primary" = { modifiers = ["reversed"] }
"ui.cursor.select" = { bg = "gray" }
"ui.gutter" = { fg = "linenr_fg", bg = "linenr_bg" }
"ui.help" = { fg = "background_fg", bg = "cursorlinenr_bg" }
"ui.linenr" = { fg = "linenr_fg", bg = "linenr_bg" }
"ui.menu" = { fg = "background_fg", bg = "cursorlinenr_bg" }
"ui.menu.border" = { fg = "comment_fg" }
"ui.menu.selected" = { fg = "menusel_fg", bg = "menusel_bg" }
"ui.popup" = { fg = "background_fg", bg = "cursorlinenr_bg" }
"ui.popup.info" = { fg = "blue" }
"ui.selection" = { bg = "sel_bg" }
"ui.statusline" = { bg = "statusline_bg", fg = "statusline_fg" }
"ui.statusline.insert" = { fg = "black", bg = "blue" }
"ui.statusline.select" = { fg = "black", bg = "green" }
"ui.text.focus" = { fg = "orange" }
"ui.virtual" = { fg = "linenr_fg" }
"ui.virtual.indent-guide" = { fg = "linenr_fg" }
"ui.virtual.jump-label" = { fg = "orange", modifiers = ["bold"] }
"ui.virtual.ruler" = { bg = "linenr_bg" }
"ui.virtual.whitespace" = { fg = "sel_bg" }
"ui.window" = { fg = "comment_fg", modifiers = ["bold"] }
"variable" = { fg = "background_fg" }
"variable.builtin" = { fg = "blue" }
"warning" = { fg = "orange" }
[palette]
orange = "#e2a578"
pale = "#a4aecc"
purple = "#a093c8"
black = "#1e2132"
gray = "#6b7089"
red = "#e27878"
light-red = "#e98989"
green = "#b5bf82"
light-green = "#c0ca8e"
yellow = "#e2a478"
light-yellow = "#e9b189"
blue = "#85a0c7"
light-blue = "#91acd1"
magenta = "#a093c7"
light-magenta = "#ada0d3"
cyan = "#89b9c2"
light-cyan = "#95c4ce"
white = "#c6c8d1"
light-gray = "#d2d4de"
background_bg = "#161822"
background_fg = "#c7c9d1"
comment_fg = "#6c7189"
cursorlinenr_bg = "#3d425c"
linenr_bg = "#1f2233"
linenr_fg = "#454d73"
matchparen_bg = "#3f455f"
menusel_bg = "#5c638a"
menusel_fg = "#f0f1f5"
sel_bg = "#282d43"
statusline_bg = "#0f1117"
statusline_fg = "#828597"

View File

@ -0,0 +1,39 @@
# Author : Chromo-residuum-opec <development.0extl@simplelogin.com>
inherits = "iceberg-dark"
"ui.menu.selected" = { fg = "background_fg", bg = "menusel_bg" }
[palette]
orange = "#c67439"
pale = "#505695"
purple = "#785ab5"
black = "#dcdfe7"
gray = "#8389a3"
red = "#cd517a"
light-red = "#cc3768"
green = "#668f3d"
light-green = "#598030"
yellow = "#c57339"
light-yellow = "#b6662d"
blue = "#2e539e"
light-blue = "#22478e"
magenta = "#7759b4"
light-magenta = "#6845ad"
cyan = "#3f84a6"
light-cyan = "#327698"
white = "#33374c"
light-gray = "#262a3f"
background_bg = "#e9e9ed"
background_fg = "#33374d"
comment_fg = "#8489a4"
cursorlinenr_bg = "#cccfe0"
linenr_bg = "#dddfe9"
linenr_fg = "#a0a5c0"
matchparen_bg = "#bec0ca"
menusel_bg = "#a9afd1"
sel_bg = "#cacdd8"
statusline_bg = "#cad0de"
statusline_fg = "#757da3"

View File

@ -1044,8 +1044,8 @@ lines.
1. Move the cursor to the line marked '-->' below.
2. Select both lines with xx or 2x.
3. Type s to select, type "would" and enter.
4. Use ( and ) to cycle the primary selection and remove the
very second "would" with Alt-, .
4. Use ( and ) to cycle the primary selection and deselect
the second "would" with Alt-, .
5. Type c "wood" to change the remaining "would"s to "wood".
--> How much would would a wouldchuck chuck

View File

@ -1,9 +1,9 @@
use crate::helpers;
use crate::path;
use crate::DynError;
use helix_term::commands::TYPABLE_COMMAND_LIST;
use helix_term::health::TsFeature;
use std::collections::HashSet;
use std::fs;
pub const TYPABLE_COMMANDS_MD_OUTPUT: &str = "typable-cmd.md";
@ -95,14 +95,25 @@ pub fn lang_features() -> Result<String, DynError> {
.to_owned(),
);
}
row.push(
lc.language_servers
.iter()
.filter_map(|ls| config.language_server.get(&ls.name))
.map(|s| md_mono(&s.command.clone()))
.collect::<Vec<_>>()
.join(", "),
);
let mut seen_commands = HashSet::new();
let mut commands = String::new();
for ls_config in lc
.language_servers
.iter()
.filter_map(|ls| config.language_server.get(&ls.name))
{
let command = &ls_config.command;
if !seen_commands.insert(command) {
continue;
}
if !commands.is_empty() {
commands.push_str(", ");
}
commands.push_str(&md_mono(command));
}
row.push(commands);
md.push_str(&md_table_row(&row));
row.clear();