mirror of
https://github.com/nvim-treesitter/nvim-treesitter.git
synced 2026-07-01 11:06:54 -04:00
Compare commits
1715 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4916d6592e | ||
|
|
234d76709e | ||
|
|
2098db61dc | ||
|
|
81295eb0c5 | ||
|
|
539abf6da5 | ||
|
|
6878ae017d | ||
|
|
c82bf96f0a | ||
|
|
90cd6580e7 | ||
|
|
7caec274fd | ||
|
|
da8bf82a53 | ||
|
|
f059649bc3 | ||
|
|
6620ae1c44 | ||
|
|
8755152551 | ||
|
|
0e0db770f2 | ||
|
|
e5f65e31a5 | ||
|
|
877f724846 | ||
|
|
53f6ce29df | ||
|
|
2b50ab5ccb | ||
|
|
2cc172c28e | ||
|
|
c9fea86a5a | ||
|
|
b9f9d692f1 | ||
|
|
ebc3201290 | ||
|
|
2f5d4c3f3c | ||
|
|
f873ec2955 | ||
|
|
88a217f570 | ||
|
|
eb1f8e80cb | ||
|
|
493890b87a | ||
|
|
5cb05e1b0f | ||
|
|
4110daee15 | ||
|
|
9fd4d998c3 | ||
|
|
ebe76eb800 | ||
|
|
1970f0d3bb | ||
|
|
544320a9cf | ||
|
|
972f378653 | ||
|
|
cb2cb74f3c | ||
|
|
995b75fd51 | ||
|
|
6bc51d020a | ||
|
|
ae2081cfcd | ||
|
|
b9171ede5d | ||
|
|
957f86ae3f | ||
|
|
8ada222612 | ||
|
|
eaa5caed2a | ||
|
|
0f5b204603 | ||
|
|
67d0fd3e0a | ||
|
|
c6d295e966 | ||
|
|
a8845121f0 | ||
|
|
d660b7c002 | ||
|
|
dc42c209f3 | ||
|
|
fcd51bbe92 | ||
|
|
3edb01f912 | ||
|
|
ecdae44bae | ||
|
|
23502d650a | ||
|
|
0211563445 | ||
|
|
2bd9b9b4f1 | ||
|
|
ca35dc5184 | ||
|
|
4d9466677a | ||
|
|
b032f66f0b | ||
|
|
88a8487378 | ||
|
|
9f2dad22ef | ||
|
|
45a07f869b | ||
|
|
92c9b016d1 | ||
|
|
70a9fecaf5 | ||
|
|
4967fa48b0 | ||
|
|
ac1d0ff910 | ||
|
|
19c729dae6 | ||
|
|
04ab807f8e | ||
|
|
cc12e37e5b | ||
|
|
5465196ba8 | ||
|
|
f8bbc3177d | ||
|
|
0ac55b85c6 | ||
|
|
568ede7e79 | ||
|
|
81aca2f981 | ||
|
|
67b3ce0529 | ||
|
|
275b9fe801 | ||
|
|
b67d29ce74 | ||
|
|
88f1dfc211 | ||
|
|
511e5ccf40 | ||
|
|
62dad2a60a | ||
|
|
61d3f5b186 | ||
|
|
0d1b8b026b | ||
|
|
ec03481377 | ||
|
|
e75c007f27 | ||
|
|
b9933f0e13 | ||
|
|
d9a5fb8484 | ||
|
|
3121570f07 | ||
|
|
d19def46c1 | ||
|
|
19261d56ed | ||
|
|
7c14161403 | ||
|
|
8aada0e394 | ||
|
|
15b3416cc1 | ||
|
|
c872ec85cc | ||
|
|
5a7e5638e7 | ||
|
|
6016f1232d | ||
|
|
2ba5ec1846 | ||
|
|
5e8652dbaf | ||
|
|
9177f2ff06 | ||
|
|
6feaebb456 | ||
|
|
de878155ca | ||
|
|
b033ab331c | ||
|
|
99dfc5acef | ||
|
|
31fc7e10cd | ||
|
|
300b906a95 | ||
|
|
4337799162 | ||
|
|
86cf4fb684 | ||
|
|
46c16d89a8 | ||
|
|
737088f857 | ||
|
|
1927c76aec | ||
|
|
efa5d1fa3a | ||
|
|
c6dd314086 | ||
|
|
d6ce707613 | ||
|
|
7efc1b58a8 | ||
|
|
36fcb4a423 | ||
|
|
45d08da7bb | ||
|
|
7ba26e7685 | ||
|
|
6e42d823ce | ||
|
|
8cdffc6d33 | ||
|
|
f795520371 | ||
|
|
e08ad49dbd | ||
|
|
4fc09bee78 | ||
|
|
cfdca13a5d | ||
|
|
fc21d3db8c | ||
|
|
846c7b50ee | ||
|
|
d0bf5ff2b0 | ||
|
|
568f2a3b7d | ||
|
|
d3218d988f | ||
|
|
74b119812e | ||
|
|
74d3999522 | ||
|
|
2979e048b3 | ||
|
|
b6271b678e | ||
|
|
186810d6ad | ||
|
|
02693ce64c | ||
|
|
a98a740c55 | ||
|
|
f47f549f74 | ||
|
|
93537d6998 | ||
|
|
bfc6c99540 | ||
|
|
20db421f5f | ||
|
|
9d47b2558b | ||
|
|
d2350758b3 | ||
|
|
d72fa25b54 | ||
|
|
41913a8d44 | ||
|
|
596923959a | ||
|
|
6f2121231a | ||
|
|
e0eec76dad | ||
|
|
75797cdd8a | ||
|
|
857fb97bb6 | ||
|
|
c5623d3486 | ||
|
|
e527584cf8 | ||
|
|
00c906abb9 | ||
|
|
17885756e6 | ||
|
|
d56ed0f7f9 | ||
|
|
c5871d9d87 | ||
|
|
d6ebbd5039 | ||
|
|
3bbae7b32e | ||
|
|
bb83a67612 | ||
|
|
c682a239a9 | ||
|
|
3a48d16c95 | ||
|
|
69c76488f7 | ||
|
|
0cfa599474 | ||
|
|
2696fb8326 | ||
|
|
2144e88dac | ||
|
|
0427eeb385 | ||
|
|
b50774079a | ||
|
|
f46e3a09bd | ||
|
|
0a6817bcbb | ||
|
|
81aec1e45d | ||
|
|
d97d226cfd | ||
|
|
5eca61b32a | ||
|
|
1ddb266477 | ||
|
|
896e92a7f6 | ||
|
|
53049d6678 | ||
|
|
65a266bf69 | ||
|
|
55820833a3 | ||
|
|
64f4755b9d | ||
|
|
fd2880e8bc | ||
|
|
a3b489680f | ||
|
|
2c30e515eb | ||
|
|
9ddd853e7e | ||
|
|
645f42e85d | ||
|
|
738d9ced4c | ||
|
|
c53bb10a71 | ||
|
|
98fe644cb3 | ||
|
|
9ee023538e | ||
|
|
400f38cc23 | ||
|
|
f2204e58db | ||
|
|
4a9f57971a | ||
|
|
eea5725822 | ||
|
|
8fecb46258 | ||
|
|
30c466ad57 | ||
|
|
71bf1665f8 | ||
|
|
846d51137b | ||
|
|
cdb5d5ef23 | ||
|
|
63fac0a576 | ||
|
|
4968877bb2 | ||
|
|
0606c7a9dc | ||
|
|
4b74045bbe | ||
|
|
09d50fd157 | ||
|
|
763f1e650b | ||
|
|
cbafde9925 | ||
|
|
de003000a2 | ||
|
|
3ab4f2d2d2 | ||
|
|
0594d1ba65 | ||
|
|
01ced7499f | ||
|
|
c579a8c0cf | ||
|
|
b4888ed9e8 | ||
|
|
b684696315 | ||
|
|
4709d4276c | ||
|
|
99bd52ba56 | ||
|
|
77362027f7 | ||
|
|
db50897909 | ||
|
|
9176343647 | ||
|
|
1df23c59d8 | ||
|
|
5a70b1eb8c | ||
|
|
53819acac2 | ||
|
|
6ac9f2e512 | ||
|
|
bd99d6bd2b | ||
|
|
a1d3efbdf5 | ||
|
|
20fc6b1270 | ||
|
|
c41b3b9841 | ||
|
|
1b8622a830 | ||
|
|
317a77affc | ||
|
|
8ab64a37ea | ||
|
|
1c760c1888 | ||
|
|
f4d22b96c5 | ||
|
|
030e979b23 | ||
|
|
7aa24acae3 | ||
|
|
682d083292 | ||
|
|
f6adaede57 | ||
|
|
f42378a959 | ||
|
|
7f8dd2e48b | ||
|
|
fee71c102c | ||
|
|
939556333f | ||
|
|
9addcdd015 | ||
|
|
802195d8f1 | ||
|
|
8fccdb3d49 | ||
|
|
cd64fd3f44 | ||
|
|
16da7ded58 | ||
|
|
8302d4f547 | ||
|
|
85ec015f3b | ||
|
|
37cec5ec59 | ||
|
|
35a124cb60 | ||
|
|
9f15c2b050 | ||
|
|
44e90ec66e | ||
|
|
6fd7117c1d | ||
|
|
2f28a14ed2 | ||
|
|
32cb9f9b9d | ||
|
|
cabbd52bb8 | ||
|
|
bf0234010a | ||
|
|
4d43480167 | ||
|
|
21da8ac251 | ||
|
|
42ea539243 | ||
|
|
13e3ce3bf4 | ||
|
|
9866036ec3 | ||
|
|
4eb35c0344 | ||
|
|
37bcfdc6eb | ||
|
|
4d9916e477 | ||
|
|
a4fa3e2d18 | ||
|
|
05f2910355 | ||
|
|
3561e1fb19 | ||
|
|
b26b425829 | ||
|
|
12be0e9f24 | ||
|
|
57aa15d4cc | ||
|
|
5d539943c6 | ||
|
|
40cca05b40 | ||
|
|
8c8742871a | ||
|
|
6b3bf164b2 | ||
|
|
3650b4ef6a | ||
|
|
d116118add | ||
|
|
f14b356d54 | ||
|
|
afe267b50e | ||
|
|
d6bce02b89 | ||
|
|
20d77c2e5b | ||
|
|
1e3b7562c2 | ||
|
|
a98e67ad40 | ||
|
|
fba060b623 | ||
|
|
61ec748ef7 | ||
|
|
a5edb0a274 | ||
|
|
992e9ef3d0 | ||
|
|
8d8ca0996c | ||
|
|
96f51adf71 | ||
|
|
6c2234f7ba | ||
|
|
c3ecec599b | ||
|
|
c9e4edc127 | ||
|
|
4eb12d7a1f | ||
|
|
3dc6834b30 | ||
|
|
4400990e73 | ||
|
|
0d32ec3c3e | ||
|
|
80281c19fd | ||
|
|
dafb3cb3cb | ||
|
|
04935dec42 | ||
|
|
1f069f1bc6 | ||
|
|
dbb63c8b7a | ||
|
|
4b2e9b049c | ||
|
|
5948977de4 | ||
|
|
2e8f8562e6 | ||
|
|
7110df63e1 | ||
|
|
77ba555cef | ||
|
|
98459ffcf7 | ||
|
|
1181cd9a25 | ||
|
|
13ddd4d752 | ||
|
|
6c50310371 | ||
|
|
2317241896 | ||
|
|
8867a9d6bf | ||
|
|
1bfa557b7d | ||
|
|
2a677dede2 | ||
|
|
7e6fbcaa20 | ||
|
|
9807487fe9 | ||
|
|
43b7f16c50 | ||
|
|
a64ef334be | ||
|
|
c29969e8ef | ||
|
|
0fb1c6e92e | ||
|
|
9c03c835fb | ||
|
|
c48b37a3c9 | ||
|
|
faf63903ff | ||
|
|
27d0bef81e | ||
|
|
f976acdc9c | ||
|
|
057e845518 | ||
|
|
fb9b2cfdc3 | ||
|
|
27b0bd487c | ||
|
|
6d54a47f44 | ||
|
|
3cad4eb434 | ||
|
|
9a51f860c1 | ||
|
|
01dd4b05cf | ||
|
|
fa0bb30ebd | ||
|
|
ff770d718b | ||
|
|
ce903fde5d | ||
|
|
0860b9b107 | ||
|
|
03c9048090 | ||
|
|
f9ab837ca1 | ||
|
|
c59004f1e0 | ||
|
|
71d2fd1bd4 | ||
|
|
024e6c5e46 | ||
|
|
0140c29b31 | ||
|
|
dd63d7141f | ||
|
|
61b0a05ec0 | ||
|
|
1043871ef4 | ||
|
|
c1dfc39285 | ||
|
|
0d60a09252 | ||
|
|
354c30d2a2 | ||
|
|
652831b231 | ||
|
|
c78594ce06 | ||
|
|
011f02936f | ||
|
|
d08cf75e1b | ||
|
|
b19b5ce171 | ||
|
|
40cbddedf7 | ||
|
|
168fe16cdd | ||
|
|
a663e69447 | ||
|
|
69371f0148 | ||
|
|
7a4a35de3e | ||
|
|
b0a20057b0 | ||
|
|
864e75a85d | ||
|
|
25f08b82af | ||
|
|
6b55bc0fab | ||
|
|
e8bfe271b0 | ||
|
|
a7ab4381ae | ||
|
|
f10bcac66b | ||
|
|
dc8f3415a7 | ||
|
|
18bb653917 | ||
|
|
53dccb3a77 | ||
|
|
4e906caca3 | ||
|
|
afaf01ebd3 | ||
|
|
75ee7ff2f0 | ||
|
|
a83f2d1417 | ||
|
|
3d0e642764 | ||
|
|
f7c5f7de55 | ||
|
|
11736494df | ||
|
|
44bb06bc12 | ||
|
|
53d7118483 | ||
|
|
bdc2e01958 | ||
|
|
522e0c6991 | ||
|
|
73adbe597e | ||
|
|
037ac775e1 | ||
|
|
ed1f573aae | ||
|
|
308c9b26c7 | ||
|
|
990110336c | ||
|
|
c13511c884 | ||
|
|
cbfe8a20c7 | ||
|
|
328ee3db54 | ||
|
|
9365cf8a97 | ||
|
|
12e0246e4f | ||
|
|
6fe0032640 | ||
|
|
02a1a0537c | ||
|
|
a9f34d5a76 | ||
|
|
188bbf7a09 | ||
|
|
aaf5b7fdf7 | ||
|
|
a2841d29d7 | ||
|
|
c5a8c9d01a | ||
|
|
83dae49a10 | ||
|
|
ab230eadd4 | ||
|
|
a8677385b7 | ||
|
|
214cfcf851 | ||
|
|
c17de56890 | ||
|
|
054080bf59 | ||
|
|
5a38df5627 | ||
|
|
8f8cf7144d | ||
|
|
c70daa36dc | ||
|
|
0bb981c876 | ||
|
|
421e2fb7b2 | ||
|
|
a8f5641ab3 | ||
|
|
429e6f446b | ||
|
|
039fe9095d | ||
|
|
be5f9b0eaa | ||
|
|
885c2960ef | ||
|
|
e77506bde3 | ||
|
|
178c6a84c1 | ||
|
|
5f2c6c0c83 | ||
|
|
59f5d64a61 | ||
|
|
efbc2a4b72 | ||
|
|
1bec16362f | ||
|
|
3966b8808b | ||
|
|
abcbe65b6e | ||
|
|
673fdccd21 | ||
|
|
b5a3f5c286 | ||
|
|
26302f412f | ||
|
|
f13420ccff | ||
|
|
dd6ec13268 | ||
|
|
b4c9c81a80 | ||
|
|
934b751f9d | ||
|
|
041f117fb1 | ||
|
|
bae77b87b1 | ||
|
|
f0a984347c | ||
|
|
c5152f3e83 | ||
|
|
68508631de | ||
|
|
5a70048116 | ||
|
|
37957d6bcf | ||
|
|
cd2c826972 | ||
|
|
9c0a99819c | ||
|
|
cde679e435 | ||
|
|
5aa2984a02 | ||
|
|
eb1b6ec542 | ||
|
|
5817ff01b5 | ||
|
|
692b051b09 | ||
|
|
310f0925ec | ||
|
|
628d5e442c | ||
|
|
b171f948da | ||
|
|
066fd65053 | ||
|
|
0484f881c6 | ||
|
|
28d480e062 | ||
|
|
94ea4f436d | ||
|
|
3b308861a8 | ||
|
|
4c7509e7b0 | ||
|
|
58dd149629 | ||
|
|
684eeac91e | ||
|
|
54fc8e311c | ||
|
|
7bbed4b548 | ||
|
|
0e21ee8df6 | ||
|
|
205faba176 | ||
|
|
e5c8398e44 | ||
|
|
523a9e1489 | ||
|
|
997288c552 | ||
|
|
30654ee72a | ||
|
|
36a7d010bb | ||
|
|
79a6192d47 | ||
|
|
69cb3aafb6 | ||
|
|
cfbbea187b | ||
|
|
288b4fb4d7 | ||
|
|
4b390e1e46 | ||
|
|
9be6836ebe | ||
|
|
9df671fda4 | ||
|
|
86768fdd00 | ||
|
|
aece106233 | ||
|
|
a70d883976 | ||
|
|
a3315b8c7f | ||
|
|
da5825bf70 | ||
|
|
85168f1580 | ||
|
|
e329e94a6a | ||
|
|
d26ce01266 | ||
|
|
9399bfd816 | ||
|
|
b454febfd9 | ||
|
|
652da0b40f | ||
|
|
20a7e40203 | ||
|
|
e70cb73e94 | ||
|
|
5f38dffb6a | ||
|
|
b10436b9fb | ||
|
|
bc728ecf25 | ||
|
|
d0a56e3677 | ||
|
|
c8c7924cc3 | ||
|
|
ff553df2f4 | ||
|
|
f09a2215b8 | ||
|
|
98a3fdd5d9 | ||
|
|
835f5c11b8 | ||
|
|
f8aaf5ce4e | ||
|
|
d76a8b6e1b | ||
|
|
da88ea477c | ||
|
|
845356a256 | ||
|
|
99ea6c5d43 | ||
|
|
2586ea65fa | ||
|
|
8b79cddc70 | ||
|
|
683816f147 | ||
|
|
178a68b7ff | ||
|
|
d96c52565c | ||
|
|
548ed98f8a | ||
|
|
6d1a8e6fdb | ||
|
|
1a314a58d6 | ||
|
|
db8689da4a | ||
|
|
cf0eabc16c | ||
|
|
833405d5a9 | ||
|
|
108302da0e | ||
|
|
38959800c2 | ||
|
|
feab1f19f8 | ||
|
|
afe977dadd | ||
|
|
f06adcf572 | ||
|
|
f840ab9f72 | ||
|
|
59573f9616 | ||
|
|
ffd284c470 | ||
|
|
f0c17dc859 | ||
|
|
ee8e149a4f | ||
|
|
71ac531a63 | ||
|
|
f22181a62c | ||
|
|
16e8e19771 | ||
|
|
794cf2f630 | ||
|
|
55c5c762fe | ||
|
|
2b0760dca2 | ||
|
|
a5a2845a86 | ||
|
|
c641ca8e05 | ||
|
|
1adcd57119 | ||
|
|
bf6028e00c | ||
|
|
186f35e168 | ||
|
|
8bf733ccce | ||
|
|
c1efc9a905 | ||
|
|
f56d2f6765 | ||
|
|
f37b1668a6 | ||
|
|
99487eb34a | ||
|
|
8bc635a25f | ||
|
|
376a46ccec | ||
|
|
28f76678ca | ||
|
|
00e797ea25 | ||
|
|
a83032cee1 | ||
|
|
89eed3572d | ||
|
|
8f87d28442 | ||
|
|
081a99b3be | ||
|
|
93ce9feb4f | ||
|
|
f0ff9f0e5d | ||
|
|
3b013b9ed4 | ||
|
|
9fcb3f7aa2 | ||
|
|
36c78ee572 | ||
|
|
225419160b | ||
|
|
e6d02ec9ef | ||
|
|
f2bd62c656 | ||
|
|
c08aa2fe3f | ||
|
|
5774e7d3da | ||
|
|
d0ba96c3dc | ||
|
|
4cf2da5c3a | ||
|
|
0cfe75d2a2 | ||
|
|
bf18d4dc8d | ||
|
|
d2ff400641 | ||
|
|
a15dd9280f | ||
|
|
cb8e810a1e | ||
|
|
36bbf51842 | ||
|
|
c32b59a8fd | ||
|
|
e5588abcfa | ||
|
|
b9a3588ee8 | ||
|
|
2c4c8c10ed | ||
|
|
1a6e42bb8c | ||
|
|
8c41b8b366 | ||
|
|
95648f9154 | ||
|
|
2cade9e3d1 | ||
|
|
b08ae25c47 | ||
|
|
38e46a6d7a | ||
|
|
00a513f87e | ||
|
|
80e6de9d24 | ||
|
|
6d957c22cb | ||
|
|
e411cf2c8a | ||
|
|
6108ba7a13 | ||
|
|
a840137349 | ||
|
|
6402fcb1e0 | ||
|
|
b39070f94d | ||
|
|
da89532f03 | ||
|
|
119a6f9e25 | ||
|
|
3973f53d7a | ||
|
|
48f7ce34ef | ||
|
|
1f36863a4e | ||
|
|
cbd48fac13 | ||
|
|
e8ccc339a3 | ||
|
|
6bc2c0fde8 | ||
|
|
62911c78a8 | ||
|
|
824bf8455f | ||
|
|
9e0b5e7f0d | ||
|
|
cced713b49 | ||
|
|
55ae574195 | ||
|
|
53a6b3993f | ||
|
|
7194ff9511 | ||
|
|
285ec45123 | ||
|
|
4e701776f8 | ||
|
|
73b68cb943 | ||
|
|
ca0e04ac31 | ||
|
|
16a51977dc | ||
|
|
1545e964e2 | ||
|
|
2497d9558d | ||
|
|
4988b70680 | ||
|
|
39bf51ff68 | ||
|
|
bcd0b26607 | ||
|
|
7e3942ceca | ||
|
|
110bdf91e3 | ||
|
|
ffa526e5aa | ||
|
|
019e8cb7b3 | ||
|
|
10f7a506ef | ||
|
|
aeaac6a208 | ||
|
|
7d28f8afc4 | ||
|
|
13f4346876 | ||
|
|
80c7af6d04 | ||
|
|
043d5fb150 | ||
|
|
2206739829 | ||
|
|
61a385d74f | ||
|
|
d34e62afd3 | ||
|
|
f3d7c0dafc | ||
|
|
dce7208593 | ||
|
|
51562d44fc | ||
|
|
6587a58868 | ||
|
|
4862ab0aca | ||
|
|
0c94de7e97 | ||
|
|
07bd1b53bf | ||
|
|
1c67567464 | ||
|
|
65c466178e | ||
|
|
0fb02ac5c3 | ||
|
|
82939d5941 | ||
|
|
8acafab2bc | ||
|
|
e8c5242f53 | ||
|
|
47b333e63d | ||
|
|
7edaaf9887 | ||
|
|
4d93fae5a3 | ||
|
|
1c77042243 | ||
|
|
87b1f25098 | ||
|
|
645d14f40f | ||
|
|
4423f30539 | ||
|
|
5da195ac3d | ||
|
|
b952a0ab6c | ||
|
|
fd59f98441 | ||
|
|
8758abeb4d | ||
|
|
a67a312e7b | ||
|
|
f0c928dbe9 | ||
|
|
984214ef8e | ||
|
|
e122b11d83 | ||
|
|
c7dc251cdd | ||
|
|
dc9bf52c1f | ||
|
|
097fb77312 | ||
|
|
29f96aafe1 | ||
|
|
9ef2e37e1b | ||
|
|
e1e2ad1448 | ||
|
|
5780226a4f | ||
|
|
306dd6e9dc | ||
|
|
057990eb24 | ||
|
|
6df6e80417 | ||
|
|
8ca76960ae | ||
|
|
10a9464a82 | ||
|
|
622a4a6ba7 | ||
|
|
958af94dd8 | ||
|
|
556ac68cd3 | ||
|
|
57713d079c | ||
|
|
fae21737be | ||
|
|
6935286b4e | ||
|
|
cfbc1c0e0f | ||
|
|
6cb4098d51 | ||
|
|
fc687f38d4 | ||
|
|
e947d35bbf | ||
|
|
5f78e98924 | ||
|
|
0a0e2e354b | ||
|
|
4b22291348 | ||
|
|
1087b183a7 | ||
|
|
f0f48e0290 | ||
|
|
f87c8956ae | ||
|
|
a295ba13d2 | ||
|
|
34d78baa86 | ||
|
|
7e0fcf0d45 | ||
|
|
22c86af7c8 | ||
|
|
5d18ef22dc | ||
|
|
eb3e850acf | ||
|
|
17678b00fa | ||
|
|
ac6a72a6f8 | ||
|
|
096babebf6 | ||
|
|
50947387c2 | ||
|
|
b4897f5a84 | ||
|
|
8119950998 | ||
|
|
caba7ef355 | ||
|
|
4d5a8e7006 | ||
|
|
2a75d8065c | ||
|
|
2405274937 | ||
|
|
fa915a30c5 | ||
|
|
102bc74e09 | ||
|
|
981ca7e353 | ||
|
|
c47d8d27d0 | ||
|
|
d20db847aa | ||
|
|
1d0a8b91d0 | ||
|
|
ad5ea0bbed | ||
|
|
54a29bf99d | ||
|
|
5cf3434c69 | ||
|
|
89ecadd2b1 | ||
|
|
7fee2c55e0 | ||
|
|
cfbbdd5eff | ||
|
|
33d2717387 | ||
|
|
2a496fa4e8 | ||
|
|
c97f14eed1 | ||
|
|
5874cac1b7 | ||
|
|
337b503688 | ||
|
|
c5c9f234b3 | ||
|
|
0c26a5c4bc | ||
|
|
3b8dee4293 | ||
|
|
894cb3cebb | ||
|
|
53e20aa728 | ||
|
|
be17791f86 | ||
|
|
c56507f6a1 | ||
|
|
acada1a685 | ||
|
|
046b8e9361 | ||
|
|
0aaf146590 | ||
|
|
b0fc560c75 | ||
|
|
3edea87978 | ||
|
|
b31188671d | ||
|
|
69170c9314 | ||
|
|
2444c8052f | ||
|
|
70d44dad70 | ||
|
|
454354e599 | ||
|
|
f6f159a293 | ||
|
|
427a90ae70 | ||
|
|
60b4c15e7c | ||
|
|
a0a1d7bb50 | ||
|
|
4d035005d3 | ||
|
|
02f8777252 | ||
|
|
afa0d2a9d0 | ||
|
|
8d4fdc5e47 | ||
|
|
cc292c869f | ||
|
|
28591731d8 | ||
|
|
d14bc4bd15 | ||
|
|
7930b5f983 | ||
|
|
b3752a311a | ||
|
|
efb2e9c607 | ||
|
|
3f377c0739 | ||
|
|
94853ae932 | ||
|
|
305c265bdb | ||
|
|
e05c280659 | ||
|
|
28a5dc06a8 | ||
|
|
731fbe9ac3 | ||
|
|
fcd2a5fea9 | ||
|
|
2d816bb49e | ||
|
|
2d5c122af9 | ||
|
|
eff88f4e8b | ||
|
|
1249b4cfce | ||
|
|
8a74ac9aea | ||
|
|
fb12c7f8a3 | ||
|
|
cd2acc803b | ||
|
|
14f5b15ef9 | ||
|
|
a3a732107f | ||
|
|
c50981479e | ||
|
|
37427012d1 | ||
|
|
20b86032f0 | ||
|
|
1c0cbdef44 | ||
|
|
20e10ca691 | ||
|
|
13c7caf8a6 | ||
|
|
06611c75fe | ||
|
|
6389ceb175 | ||
|
|
e1e3108cd2 | ||
|
|
88ed26a7e6 | ||
|
|
c5be87ad3e | ||
|
|
fba111f707 | ||
|
|
7646c1c12a | ||
|
|
bb06afa3f1 | ||
|
|
d105f2cb7b | ||
|
|
a069bb62a8 | ||
|
|
8e40904e49 | ||
|
|
0603b3e3d2 | ||
|
|
425b589683 | ||
|
|
eab2005cb5 | ||
|
|
c91122d201 | ||
|
|
0722f23886 | ||
|
|
98b3825999 | ||
|
|
ea3a37a975 | ||
|
|
b5cda6d731 | ||
|
|
7c5a4632c4 | ||
|
|
4b9a83f601 | ||
|
|
8b15ce58e4 | ||
|
|
f284ca27b5 | ||
|
|
0d3426a2e8 | ||
|
|
7dc8aabe86 | ||
|
|
604aa5a7c8 | ||
|
|
509d38fee8 | ||
|
|
dfd3207ed4 | ||
|
|
8fadb18430 | ||
|
|
d3d4c1411c | ||
|
|
dbf90fbfa6 | ||
|
|
01a92da438 | ||
|
|
98b46a647e | ||
|
|
3abe66556f | ||
|
|
9565149634 | ||
|
|
38c12cb9ac | ||
|
|
b065b59196 | ||
|
|
fb2d41ec59 | ||
|
|
92d2501d69 | ||
|
|
f9e9370a6f | ||
|
|
1c111e3e8f | ||
|
|
f26b5fb2ed | ||
|
|
0e65a9f272 | ||
|
|
39016abc99 | ||
|
|
278dd927e4 | ||
|
|
de70388626 | ||
|
|
00d2190683 | ||
|
|
a8b7da35e5 | ||
|
|
46a6587a23 | ||
|
|
674100c1fc | ||
|
|
0a9108a7e4 | ||
|
|
1d7c55f0bd | ||
|
|
48fc5d1dfe | ||
|
|
f6c5a58e3b | ||
|
|
d740b0ad92 | ||
|
|
377039daa2 | ||
|
|
649f6a1636 | ||
|
|
9210b9a4fa | ||
|
|
cfc6f2c117 | ||
|
|
bab7b0f20b | ||
|
|
a5c7a3f6b4 | ||
|
|
df20c04969 | ||
|
|
18cf02f5ef | ||
|
|
d53df0c987 | ||
|
|
3ba21f96a4 | ||
|
|
9a94cc23cb | ||
|
|
a3ca2e6056 | ||
|
|
68b2bdd99d | ||
|
|
03452942df | ||
|
|
92725df622 | ||
|
|
ed438691df | ||
|
|
8944dc64ef | ||
|
|
6115c3664c | ||
|
|
d912ede290 | ||
|
|
07d4f138cb | ||
|
|
584d96b46b | ||
|
|
37163336e2 | ||
|
|
6940055133 | ||
|
|
439fedf446 | ||
|
|
1a506b6007 | ||
|
|
f209410513 | ||
|
|
c729bb2487 | ||
|
|
25f11725d6 | ||
|
|
cbc0d1d96e | ||
|
|
b139d21726 | ||
|
|
596b16da17 | ||
|
|
d0f567251b | ||
|
|
da92610392 | ||
|
|
39904fd016 | ||
|
|
96290ae7ea | ||
|
|
ca7993e606 | ||
|
|
a8052a8819 | ||
|
|
049d42a31e | ||
|
|
8672843527 | ||
|
|
2953b6ae78 | ||
|
|
245ffff7ac | ||
|
|
5a2ff8b7ca | ||
|
|
19079207ba | ||
|
|
84bdd59c03 | ||
|
|
9b1e607298 | ||
|
|
9d2acd4997 | ||
|
|
009e981c30 | ||
|
|
86c10df7ef | ||
|
|
18adcafad0 | ||
|
|
45e0d66246 | ||
|
|
4f04fb7027 | ||
|
|
1bcdd79088 | ||
|
|
da7e9751f1 | ||
|
|
7821feb7e7 | ||
|
|
5bcc338c3d | ||
|
|
45386764cc | ||
|
|
cc2c11c403 | ||
|
|
98a33cc524 | ||
|
|
3af8476530 | ||
|
|
da61d31a3d | ||
|
|
ef52e44bb2 | ||
|
|
707e352df6 | ||
|
|
df0f8cb58e | ||
|
|
58c702c4d5 | ||
|
|
1a6fa428b8 | ||
|
|
d1e1f17cea | ||
|
|
140f534ce9 | ||
|
|
707313b80a | ||
|
|
1f2059f293 | ||
|
|
36b78d112b | ||
|
|
84836f08ef | ||
|
|
f027762845 | ||
|
|
679883ad31 | ||
|
|
a1b791604b | ||
|
|
0c8a582e47 | ||
|
|
6511cd984a | ||
|
|
160b1714ec | ||
|
|
621f5901f0 | ||
|
|
20b5cbfa92 | ||
|
|
2b2635551c | ||
|
|
929ca9c76e | ||
|
|
b8ad0473f4 | ||
|
|
1fbc25fc11 | ||
|
|
188b1a6d01 | ||
|
|
2b2ac30232 | ||
|
|
63c532fde5 | ||
|
|
12e339e370 | ||
|
|
45ee50d02b | ||
|
|
3c6af36794 | ||
|
|
4d94c24d6c | ||
|
|
cad9ff2fbc | ||
|
|
b9002f6fe6 | ||
|
|
5c42228e58 | ||
|
|
b7160e87aa | ||
|
|
399062d072 | ||
|
|
583395810e | ||
|
|
e0338f2b74 | ||
|
|
4af16a10b7 | ||
|
|
66a7655a5e | ||
|
|
b6a6d8997c | ||
|
|
d22166e3d8 | ||
|
|
2871a4a657 | ||
|
|
6a3c6a42a6 | ||
|
|
c436d45eee | ||
|
|
c9003a3cb1 | ||
|
|
f8bbb820a8 | ||
|
|
13ee7f8844 | ||
|
|
4770d9a1a7 | ||
|
|
58030e6d6f | ||
|
|
00f128dd73 | ||
|
|
ccbaee5954 | ||
|
|
093b29f2b4 | ||
|
|
bfe74a4899 | ||
|
|
3826d0c42a | ||
|
|
5b8b126de0 | ||
|
|
a1573a9135 | ||
|
|
e090c5b22d | ||
|
|
bbf1f3e546 | ||
|
|
2d8f0f37c4 | ||
|
|
4e47268c6d | ||
|
|
aa339f6ab6 | ||
|
|
749df30887 | ||
|
|
c7920f2bc5 | ||
|
|
628f53e4cb | ||
|
|
0b61eb4923 | ||
|
|
b33a34e883 | ||
|
|
64cc1ef764 | ||
|
|
fd9663acca | ||
|
|
95933209d4 | ||
|
|
9ac3931bf6 | ||
|
|
c15385281c | ||
|
|
ba921c9aef | ||
|
|
585860a186 | ||
|
|
7a64148896 | ||
|
|
39490604b0 | ||
|
|
5071ca777c | ||
|
|
2eb50352c0 | ||
|
|
aaa119cb1c | ||
|
|
7499f73794 | ||
|
|
54becf661a | ||
|
|
d0c5116fa0 | ||
|
|
86a9b67f1a | ||
|
|
f9b76256c3 | ||
|
|
397982d197 | ||
|
|
39023b61d2 | ||
|
|
bef7ec6f7a | ||
|
|
081dfa6e0f | ||
|
|
e085c614fc | ||
|
|
0f6be79962 | ||
|
|
04401b5dd1 | ||
|
|
8724e7d028 | ||
|
|
6ed65c3a1d | ||
|
|
0b8b78f9d0 | ||
|
|
0fd6d32482 | ||
|
|
6699eae8ba | ||
|
|
cfd2095e66 | ||
|
|
1e860567fb | ||
|
|
26e7fdb243 | ||
|
|
ec8776ed9e | ||
|
|
24ddf60d68 | ||
|
|
6d74da7f0a | ||
|
|
63e1337f1b | ||
|
|
59cc5f3565 | ||
|
|
bfb50de9cb | ||
|
|
3de418e73d | ||
|
|
db92f60ed0 | ||
|
|
047ce49ccf | ||
|
|
e5a05ba5e2 | ||
|
|
079af15600 | ||
|
|
8a966f32c9 | ||
|
|
4d0da6b5ac | ||
|
|
9a0db40403 | ||
|
|
c8f8dd1551 | ||
|
|
176e446473 | ||
|
|
3d1f5e7df8 | ||
|
|
a8535b2329 | ||
|
|
2e01c7104c | ||
|
|
da7b1189ea | ||
|
|
3e0feeb062 | ||
|
|
88aad97312 | ||
|
|
e28614cb1a | ||
|
|
9e66d5c72d | ||
|
|
c79b068f39 | ||
|
|
1aad04ecde | ||
|
|
558c7ad7bf | ||
|
|
d7353a6b72 | ||
|
|
a7a3b9c10e | ||
|
|
ddbcc38d46 | ||
|
|
09bad640e4 | ||
|
|
8453015093 | ||
|
|
110a50e371 | ||
|
|
d13f0183ba | ||
|
|
c67881c265 | ||
|
|
fcf79acfd1 | ||
|
|
929e4739cc | ||
|
|
65310b64ee | ||
|
|
8e569bc4b5 | ||
|
|
9f8c99e980 | ||
|
|
cc69a061fe | ||
|
|
a7ba147b4b | ||
|
|
8dbab59773 | ||
|
|
2d5133f674 | ||
|
|
45b3f7a8cf | ||
|
|
51bba660a8 | ||
|
|
88aa09e6e9 | ||
|
|
ed871c970a | ||
|
|
f97e0de005 | ||
|
|
7cec6219c4 | ||
|
|
2b4881286a | ||
|
|
886b496763 | ||
|
|
1899c8c8ec | ||
|
|
e265fec94c | ||
|
|
e0faad4a9e | ||
|
|
63be47f203 | ||
|
|
96c5cb2334 | ||
|
|
c760e4037c | ||
|
|
a0732ca9f0 | ||
|
|
b1e88723ee | ||
|
|
205102f372 | ||
|
|
9d252d0021 | ||
|
|
3fa183e34e | ||
|
|
820b14a34c | ||
|
|
803e5bd14d | ||
|
|
49452ab703 | ||
|
|
5f5077f8f7 | ||
|
|
c5b3560306 | ||
|
|
4ee9f12ff5 | ||
|
|
debf5816ee | ||
|
|
468f6ed66b | ||
|
|
4075376a25 | ||
|
|
dfd047d15f | ||
|
|
aca4432ef6 | ||
|
|
2883d0c03f | ||
|
|
002537a3e3 | ||
|
|
733fa85db2 | ||
|
|
aba69e495b | ||
|
|
625e7e58d0 | ||
|
|
667b9dbbfa | ||
|
|
e8d74461da | ||
|
|
b3c54c3188 | ||
|
|
4e387dd478 | ||
|
|
d9ea5035d4 | ||
|
|
0ffe627223 | ||
|
|
de8d91d0ef | ||
|
|
d78ab90f8e | ||
|
|
35fa869b53 | ||
|
|
874b99065b | ||
|
|
355af0c8ce | ||
|
|
c80d0d9ca9 | ||
|
|
0758155d4d | ||
|
|
dd7bb795c4 | ||
|
|
804a6473df | ||
|
|
f649c2ff75 | ||
|
|
7a38515741 | ||
|
|
14dff71d38 | ||
|
|
067415e971 | ||
|
|
0d5e1214a5 | ||
|
|
276c343b6b | ||
|
|
03883041b2 | ||
|
|
3076b9a98a | ||
|
|
4836c1df65 | ||
|
|
f16a775830 | ||
|
|
a8c1f36d2c | ||
|
|
d9aa422863 | ||
|
|
a6b2f4ecc8 | ||
|
|
7f4ac67877 | ||
|
|
972aa544ef | ||
|
|
465840f8c1 | ||
|
|
4068e1c096 | ||
|
|
656ac24233 | ||
|
|
d5969c481e | ||
|
|
e9ec8b4658 | ||
|
|
a64ce9f989 | ||
|
|
c1ad655b6a | ||
|
|
53c79ddc28 | ||
|
|
ebdffa78bd | ||
|
|
66ec1b3c4e | ||
|
|
55b30b908e | ||
|
|
b149008257 | ||
|
|
64f6f0ab4e | ||
|
|
b7c0dbbe7d | ||
|
|
adf6730dc5 | ||
|
|
b32fb41284 | ||
|
|
f9aa4f060e | ||
|
|
ad43c7f19e | ||
|
|
a8c082b4f5 | ||
|
|
74dc34a7fa | ||
|
|
2d917106d1 | ||
|
|
55a13862cd | ||
|
|
ee29084ce6 | ||
|
|
f197ce27d9 | ||
|
|
f7c05e3e05 | ||
|
|
f0dbe18000 | ||
|
|
f2f828c5e9 | ||
|
|
5d1646893a | ||
|
|
acc1708b96 | ||
|
|
fa611f612a | ||
|
|
caf275382f | ||
|
|
8a04f1aaa9 | ||
|
|
fe5c581ed5 | ||
|
|
7adae51ff3 | ||
|
|
f1a4a75005 | ||
|
|
0209151fd2 | ||
|
|
6cd4ce6cab | ||
|
|
e0d6c7643d | ||
|
|
495c93b0d4 | ||
|
|
ffd7725102 | ||
|
|
699766a0b9 | ||
|
|
4ee5fdd666 | ||
|
|
020c5bc03f | ||
|
|
5d2473d05c | ||
|
|
1e546c0f5e | ||
|
|
7ff0b8d3d2 | ||
|
|
acea74c514 | ||
|
|
533da572ae | ||
|
|
e70472794d | ||
|
|
58733401e3 | ||
|
|
f0e3b5c5fe | ||
|
|
fa19150d00 | ||
|
|
3e535e826d | ||
|
|
c11d49cbef | ||
|
|
f8d27e1abf | ||
|
|
ec6307e5b0 | ||
|
|
cf7baac35a | ||
|
|
984604288d | ||
|
|
8caffadee1 | ||
|
|
5373c90c55 | ||
|
|
173515a5d2 | ||
|
|
c723b87ef6 | ||
|
|
53b32a6aa3 | ||
|
|
d467f7d561 | ||
|
|
09700b88b4 | ||
|
|
0c7a0ddaf4 | ||
|
|
d4a888ae3c | ||
|
|
cebb7e7c5b | ||
|
|
9d80c1497e | ||
|
|
b5b64ac9fb | ||
|
|
0941c1147a | ||
|
|
c233773abf | ||
|
|
55d5772a6c | ||
|
|
9581d86f97 | ||
|
|
a8904e7f83 | ||
|
|
122b4d3db1 | ||
|
|
b967bbc27b | ||
|
|
7b04b398f8 | ||
|
|
66ae8748fd | ||
|
|
53881422f6 | ||
|
|
4bbd2e72f8 | ||
|
|
2e9c346aef | ||
|
|
c29989f5d7 | ||
|
|
09953e394b | ||
|
|
f7edd3f5f6 | ||
|
|
382c80b575 | ||
|
|
71a8e8b4b6 | ||
|
|
4d112977c7 | ||
|
|
c911f19d91 | ||
|
|
9916da1bfd | ||
|
|
47994d7e89 | ||
|
|
921763b23d | ||
|
|
9d68e876cc | ||
|
|
8dd40c7609 | ||
|
|
bb0eb73014 | ||
|
|
e5af2d7fdc | ||
|
|
cdc613c630 | ||
|
|
9636d5a3f4 | ||
|
|
26171d8f10 | ||
|
|
f29c2d9867 | ||
|
|
9a7ad2ff7a | ||
|
|
eb59a3df50 | ||
|
|
94f9a46b37 | ||
|
|
3b5704440f | ||
|
|
b47dde81a0 | ||
|
|
da7ea8f335 | ||
|
|
9ebc589329 | ||
|
|
3fc41e145c | ||
|
|
c1e1e24b64 | ||
|
|
c5cbd3ec74 | ||
|
|
3a74b58310 | ||
|
|
fc9ee79f64 | ||
|
|
49e4e2b4b6 | ||
|
|
69e41a2c14 | ||
|
|
5a8e9644c4 | ||
|
|
048c14140c | ||
|
|
512e2122e0 | ||
|
|
121bf634fe | ||
|
|
a80fe081b4 | ||
|
|
deb76a224a | ||
|
|
979beffc1a | ||
|
|
f9773e4a5e | ||
|
|
b7d50e59b1 | ||
|
|
f770df9c8c | ||
|
|
5c924407cf | ||
|
|
b91ae14fc3 | ||
|
|
5aadae3f54 | ||
|
|
ea2b137f35 | ||
|
|
aa02427dfe | ||
|
|
245da4eb2e | ||
|
|
d551bc70d5 | ||
|
|
ba149fa3b1 | ||
|
|
488e39a8f1 | ||
|
|
d3acd105bd | ||
|
|
78e11ab7ce | ||
|
|
6d56c5f404 | ||
|
|
298a9dd4f8 | ||
|
|
3e454836ce | ||
|
|
30de5e7e94 | ||
|
|
14db0433e1 | ||
|
|
7add411eba | ||
|
|
73fb37ed77 | ||
|
|
7c9c5bed83 | ||
|
|
d184407e33 | ||
|
|
ccfa76d4cb | ||
|
|
1eabe69bfa | ||
|
|
00a8cfd562 | ||
|
|
7b6aefa69a | ||
|
|
3d268f9db4 | ||
|
|
19ac9e8b5c | ||
|
|
4b8ea9fea6 | ||
|
|
4d9fb7d8b0 | ||
|
|
8012b55eee | ||
|
|
aa0c7dd296 | ||
|
|
c26cfc75bc | ||
|
|
f224fef9d2 | ||
|
|
3aa2e2f374 | ||
|
|
cd626dc48e | ||
|
|
14cd8c5db1 | ||
|
|
6f54846f2b | ||
|
|
925490e34d | ||
|
|
d5a1c2b0c8 | ||
|
|
0d2c80b4d0 | ||
|
|
c4f65272a9 | ||
|
|
6587d8e694 | ||
|
|
fa1515b015 | ||
|
|
d6dcfe8887 | ||
|
|
707b0dcf76 | ||
|
|
1b2f006703 | ||
|
|
9e1cda4e71 | ||
|
|
1be5aa99e3 | ||
|
|
3607d9c59c | ||
|
|
acefffae27 | ||
|
|
db03443582 | ||
|
|
da0efd7398 | ||
|
|
0319e6eef5 | ||
|
|
268611e3ec | ||
|
|
20b9a9845d | ||
|
|
fc7657a071 | ||
|
|
4b70dde727 | ||
|
|
73fdd31377 | ||
|
|
4e21361e15 | ||
|
|
c579d186be | ||
|
|
fed32362ad | ||
|
|
4ae2b452e9 | ||
|
|
440f177277 | ||
|
|
cbf9090a4c | ||
|
|
96defe1cbd | ||
|
|
b157b0d412 | ||
|
|
b659a6c2c3 | ||
|
|
7441b82fe5 | ||
|
|
c0c32abc51 | ||
|
|
b1f3f02027 | ||
|
|
99d3e799b4 | ||
|
|
9d5cee38b3 | ||
|
|
bbc67f736e | ||
|
|
ead283734b | ||
|
|
57476501e2 | ||
|
|
e99b79c9c1 | ||
|
|
60c2b084c2 | ||
|
|
46cac01880 | ||
|
|
c371992bcd | ||
|
|
9a47a523e3 | ||
|
|
f58cae6c22 | ||
|
|
f0a1a13316 | ||
|
|
1a4274c9e1 | ||
|
|
121d0c4c67 | ||
|
|
30ed7031af | ||
|
|
160e5d52c8 | ||
|
|
c3ab6a5903 | ||
|
|
19f69a5b43 | ||
|
|
223f8dd2e4 | ||
|
|
dbbaa3f66e | ||
|
|
eab58e9bff | ||
|
|
a95de26cd7 | ||
|
|
37ac5f1f9f | ||
|
|
0883ff0565 | ||
|
|
ab3b3ff010 | ||
|
|
01963961b5 | ||
|
|
75beaf3632 | ||
|
|
466da58e5b | ||
|
|
3ef8d25df2 | ||
|
|
19c6b0c4c9 | ||
|
|
df111f886c | ||
|
|
28a914eb57 | ||
|
|
876111c8df | ||
|
|
e245f09197 | ||
|
|
f0e91fd9b9 | ||
|
|
b04ccbd0e0 | ||
|
|
dc71d94fe2 | ||
|
|
c1d1b4084e | ||
|
|
46f8778fbf | ||
|
|
075b7594ca | ||
|
|
1e20226231 | ||
|
|
28aebb7308 | ||
|
|
9b1c2096e0 | ||
|
|
ea4f6d5175 | ||
|
|
a005f6fec9 | ||
|
|
eb93c3b2fb | ||
|
|
d8bf42b262 | ||
|
|
bc80862298 | ||
|
|
fea5808a58 | ||
|
|
dd0c118596 | ||
|
|
baaae36ac7 | ||
|
|
208d504421 | ||
|
|
3e10cffbb2 | ||
|
|
b350369740 | ||
|
|
037c6af78f | ||
|
|
4c84b83108 | ||
|
|
7099c9e531 | ||
|
|
2a95ff1476 | ||
|
|
1ba86026f7 | ||
|
|
40e8c92f99 | ||
|
|
d2f4c78303 | ||
|
|
86ac7e9274 | ||
|
|
497208692f | ||
|
|
bfa217af76 | ||
|
|
9a39ec072a | ||
|
|
78bfee7ddb | ||
|
|
65ce6fde2d | ||
|
|
f22f024e78 | ||
|
|
2c6ab9a09c | ||
|
|
f08a9d97f7 | ||
|
|
3e1d836e0e | ||
|
|
ef267f0c28 | ||
|
|
7e6b044be8 | ||
|
|
b0ac1135fe | ||
|
|
6ae470fd8f | ||
|
|
5c4892b055 | ||
|
|
b7339ffb9a | ||
|
|
2bad828b48 | ||
|
|
8253aac419 | ||
|
|
3af2d894d4 | ||
|
|
d90e11756d | ||
|
|
c16f66cca0 | ||
|
|
fbe76211f4 | ||
|
|
e9321bb914 | ||
|
|
46b587eb38 | ||
|
|
11a3584b81 | ||
|
|
53c48a9229 | ||
|
|
a2d6678bb2 | ||
|
|
e6cd337e30 | ||
|
|
00debd1fb1 | ||
|
|
8183bfa75e | ||
|
|
1b050206e4 | ||
|
|
8f444c9fcb | ||
|
|
5489e2150f | ||
|
|
4d4b63692f | ||
|
|
bf80e253a8 | ||
|
|
cc0e29727a | ||
|
|
be4d6e858f | ||
|
|
54cf9180a3 | ||
|
|
d31eb5442d | ||
|
|
30492e7e1c | ||
|
|
c51d503868 | ||
|
|
e4ba167af0 | ||
|
|
25ed904c75 | ||
|
|
0bfa0be5e4 | ||
|
|
3c996dc9fa | ||
|
|
ee2785ba6a | ||
|
|
905fedfa28 | ||
|
|
1d1d92e94a | ||
|
|
ff79725428 | ||
|
|
6e0b031ebb | ||
|
|
5127a84407 | ||
|
|
c65413f2ac | ||
|
|
f84887230a | ||
|
|
29f176c257 | ||
|
|
23ba63028c | ||
|
|
07a404570f | ||
|
|
aa8d8bc600 | ||
|
|
ac1742436c | ||
|
|
4ebf4ca4fa | ||
|
|
7d938c1c72 | ||
|
|
1c9a94bd60 | ||
|
|
3400788705 | ||
|
|
68ba579eb6 | ||
|
|
839dec615a | ||
|
|
3d473a4d5d | ||
|
|
7f31793159 | ||
|
|
1c3fb9eac2 | ||
|
|
aa31b8d4cc | ||
|
|
20042941df | ||
|
|
cf737c341d | ||
|
|
965f2e7239 | ||
|
|
7051a72755 | ||
|
|
33c9db832b | ||
|
|
8d9736cf3e | ||
|
|
aa6323e834 | ||
|
|
5e4f959d59 | ||
|
|
8532b1d941 | ||
|
|
b009aba903 | ||
|
|
a951dcb7ec | ||
|
|
e2ba4d2af1 | ||
|
|
6e7b41106e | ||
|
|
2205694d43 | ||
|
|
829f36b0b7 | ||
|
|
722617e672 | ||
|
|
c28396de30 | ||
|
|
3a92c540dd | ||
|
|
cf685ce85f | ||
|
|
f60b33c1e5 | ||
|
|
4d76587eec | ||
|
|
3686029591 | ||
|
|
93a9632b63 | ||
|
|
19b726f9ce | ||
|
|
5c1830262b | ||
|
|
03f650705c | ||
|
|
567a76780c | ||
|
|
2014f8285e | ||
|
|
e6d80e5efd | ||
|
|
6a2572c9ed | ||
|
|
c4e0f290d7 | ||
|
|
bb3dd60ebc | ||
|
|
143ca5ce17 | ||
|
|
df3e6a24ac | ||
|
|
3c7a0e9d94 | ||
|
|
5b8458c5aa | ||
|
|
53891f1492 | ||
|
|
f5062ebc8d | ||
|
|
8f5513a1f2 | ||
|
|
5d75359a9a | ||
|
|
dccf31f9b1 | ||
|
|
998b230a77 | ||
|
|
f878828584 | ||
|
|
b8f07b30ef | ||
|
|
16398a6c35 | ||
|
|
904f373fc4 | ||
|
|
3ae78f376c | ||
|
|
497fe685ff | ||
|
|
35c1a32b26 | ||
|
|
76f699dcc8 | ||
|
|
fec37b6f97 | ||
|
|
6576041660 | ||
|
|
e73c775aa9 | ||
|
|
8d3176cfbc | ||
|
|
9d39f00a95 | ||
|
|
b781fd0582 | ||
|
|
488bec0325 | ||
|
|
7ff51f53b0 | ||
|
|
57205313dd | ||
|
|
b4553bef58 | ||
|
|
9775d5d7c7 | ||
|
|
a0f18ee98c | ||
|
|
51d7c36e5f | ||
|
|
c09932bd2d | ||
|
|
cc6b108ea1 | ||
|
|
212b7a504c | ||
|
|
70f03829af | ||
|
|
e479db627c | ||
|
|
63ca90eaa3 | ||
|
|
3d08cdd741 | ||
|
|
8a9bef9327 | ||
|
|
9e1f3c3369 | ||
|
|
f8d4e5c1ba | ||
|
|
00bd760a0e | ||
|
|
533ad655ad | ||
|
|
99ddf57353 | ||
|
|
22c5a0d833 | ||
|
|
e3e5ff4ebd | ||
|
|
ada920f2a4 | ||
|
|
a47540fd73 | ||
|
|
cbaad1951e | ||
|
|
c2a265156d | ||
|
|
30a41f52f9 | ||
|
|
3ad0e410f8 | ||
|
|
8e349b1ea9 | ||
|
|
62b0bb4f24 | ||
|
|
84daea50b1 | ||
|
|
06b5fda797 | ||
|
|
4349af8a6e | ||
|
|
4a8901b0d5 | ||
|
|
d2f58c0b65 | ||
|
|
c5b19f66e0 | ||
|
|
15d521c923 | ||
|
|
31d0648055 | ||
|
|
db12bd416e | ||
|
|
18aa5ae3fd | ||
|
|
fad40f2010 | ||
|
|
6e2b56cbe7 | ||
|
|
6f1f407d71 | ||
|
|
ede5b461c9 | ||
|
|
9896ef5f70 | ||
|
|
c06292fdc6 | ||
|
|
adf72368f6 | ||
|
|
e105b5e67d | ||
|
|
e159a531e5 | ||
|
|
f148c8a766 | ||
|
|
31641d72a4 | ||
|
|
a29058fe8b | ||
|
|
9ecf980277 | ||
|
|
a8d2b54e28 | ||
|
|
19bf991be2 | ||
|
|
1398b1ba46 | ||
|
|
ebf0532d42 | ||
|
|
ca46eb3ac9 | ||
|
|
977d94975d | ||
|
|
7d1bab6546 | ||
|
|
71ae32c187 | ||
|
|
d1484a1507 | ||
|
|
455f6586ba | ||
|
|
01cdcfb216 | ||
|
|
c4c1f516ec | ||
|
|
6bd108a6f1 | ||
|
|
7eeb26e69c | ||
|
|
d87074a06b | ||
|
|
ea3ddedd83 | ||
|
|
1f6bd57192 | ||
|
|
917d696592 | ||
|
|
4b27f87fef | ||
|
|
e04ce8bcec | ||
|
|
5b3e9861a2 | ||
|
|
9bc21966f2 | ||
|
|
3a7b5a9fb4 | ||
|
|
b3e53e9423 | ||
|
|
4704d7ad60 | ||
|
|
f857a96774 | ||
|
|
d10e856c11 | ||
|
|
8e1df60b13 | ||
|
|
fef26b5eee | ||
|
|
5e4b657181 | ||
|
|
34cb6a474f | ||
|
|
13e4e75079 | ||
|
|
4640135fdf | ||
|
|
3f2f770aad | ||
|
|
bdff1ab16b | ||
|
|
9772dd19a5 | ||
|
|
097d6ffd5c | ||
|
|
f85b205e83 | ||
|
|
06d575ead4 | ||
|
|
c76e7e2a28 | ||
|
|
b3847b9551 | ||
|
|
4cb1595f5b | ||
|
|
2ba58a424c | ||
|
|
ab3ec330ec | ||
|
|
87bc770e60 | ||
|
|
c920b668f8 | ||
|
|
5d9e12ccf4 | ||
|
|
f75a5b4e14 | ||
|
|
42acc3f6e7 | ||
|
|
17d68ac13c | ||
|
|
eb1914bb10 | ||
|
|
47d013d025 | ||
|
|
504fe10432 | ||
|
|
581e87ba4e | ||
|
|
d49a8f82f1 | ||
|
|
bdaa6b817a | ||
|
|
1ea4a0afd5 | ||
|
|
e32ebdc01d | ||
|
|
e4a1cc6e8e | ||
|
|
69e4b99f13 | ||
|
|
d96bf9d522 | ||
|
|
5a5cabd712 | ||
|
|
883c72cddc | ||
|
|
7e9139db68 | ||
|
|
f6342874b1 | ||
|
|
1c72e797ba | ||
|
|
2b6020247d | ||
|
|
4416d21466 | ||
|
|
1843594962 | ||
|
|
02ff2220d3 | ||
|
|
10d79b5dbb | ||
|
|
10e8dffb79 | ||
|
|
b52b298669 | ||
|
|
0aa7131044 | ||
|
|
9860fceb73 | ||
|
|
96f190f7a1 | ||
|
|
6444286cbf | ||
|
|
143a342bd8 | ||
|
|
05962ae14a | ||
|
|
baf4581159 | ||
|
|
817ca60370 | ||
|
|
841dde702c | ||
|
|
8ec79c4785 | ||
|
|
aa805bf22f | ||
|
|
b8840a426e | ||
|
|
51d15ef5da | ||
|
|
6b93dcd15a | ||
|
|
95036477c1 | ||
|
|
3dbea103d8 | ||
|
|
0f3183dda8 | ||
|
|
f0d43eff13 | ||
|
|
4b00de5633 | ||
|
|
8812089919 | ||
|
|
8262ccf990 | ||
|
|
de4a651da7 | ||
|
|
bc07e58f42 | ||
|
|
01c159826e | ||
|
|
cab95b2f96 | ||
|
|
6d1ab048d2 | ||
|
|
76700e147b | ||
|
|
cbf0dfd92f | ||
|
|
b444afa1da | ||
|
|
3e71d65447 | ||
|
|
5973b617a9 | ||
|
|
3722d5d772 | ||
|
|
127cf25737 | ||
|
|
8d6192baa9 | ||
|
|
7bba891bae | ||
|
|
0d14299a9d | ||
|
|
4fbf150a16 | ||
|
|
140a486abe | ||
|
|
1cda98132a | ||
|
|
a536ecad57 | ||
|
|
b7e1a6c2cd | ||
|
|
9512582775 | ||
|
|
8b99311ca1 | ||
|
|
d2b4563230 | ||
|
|
e7ea07e42c | ||
|
|
f2119df35c | ||
|
|
7e4e92432d | ||
|
|
129f8b9742 | ||
|
|
5fca7ae496 | ||
|
|
13599375c3 | ||
|
|
515b00598a | ||
|
|
90327d9e73 | ||
|
|
6da205148f | ||
|
|
364b86ec8e | ||
|
|
45cde459b5 | ||
|
|
ba64547834 | ||
|
|
5f950cdcb8 | ||
|
|
e9602f4119 | ||
|
|
569d5dfadb | ||
|
|
59a295f76a | ||
|
|
e24dab6696 | ||
|
|
4ea1a4ffa8 | ||
|
|
d4dac523d2 | ||
|
|
95987ee2d6 | ||
|
|
b5736698be | ||
|
|
6f586875e3 | ||
|
|
458ce4d16c | ||
|
|
b4138891b3 | ||
|
|
2fb2100fed | ||
|
|
589fa77c23 | ||
|
|
cf13c96050 | ||
|
|
e0edcbb1d2 | ||
|
|
ed82d82b77 | ||
|
|
efda19a54a | ||
|
|
ffb19d5dee | ||
|
|
4bc1f9a4eb | ||
|
|
7b9973fca9 | ||
|
|
b7fd3d1db4 | ||
|
|
0b697429c9 | ||
|
|
cb79d24461 | ||
|
|
ce4adf11cf | ||
|
|
cc908cfcd7 | ||
|
|
fb91060f59 | ||
|
|
22025469b5 | ||
|
|
314fe31dc7 | ||
|
|
1d83fc08d4 | ||
|
|
4362b04a29 | ||
|
|
2c1eb02e92 | ||
|
|
10903b13d8 | ||
|
|
1bee80469d | ||
|
|
8166080035 | ||
|
|
d23192fb17 | ||
|
|
aa0c60ca5a | ||
|
|
c62874656e | ||
|
|
f72d9169f2 | ||
|
|
023a8ee9a2 | ||
|
|
ae7ceaadad | ||
|
|
a938e98cb4 | ||
|
|
527eb602ff | ||
|
|
55562407b6 | ||
|
|
37c808b8ce | ||
|
|
41128a7724 | ||
|
|
177a775fd8 | ||
|
|
ab23464393 | ||
|
|
cd4e090994 | ||
|
|
97997c928b | ||
|
|
94bd4bcc5b | ||
|
|
e0420e73c9 | ||
|
|
77e298e4de | ||
|
|
76ca66db38 | ||
|
|
051193acba | ||
|
|
6806d7a783 | ||
|
|
5d5eba78a7 | ||
|
|
4e0d1dd91f | ||
|
|
5cc5627487 | ||
|
|
64b3d5e569 | ||
|
|
a8fa3047b5 | ||
|
|
aeed349c04 | ||
|
|
88261266de | ||
|
|
1ce6000a95 | ||
|
|
c41d38b70e | ||
|
|
6548bb64c1 | ||
|
|
d198a75e2c | ||
|
|
f5a839d1e8 | ||
|
|
134a86f9ff | ||
|
|
1eb22367b9 | ||
|
|
4a4dbe1cb1 | ||
|
|
757b4f6afb | ||
|
|
505a0e74cb | ||
|
|
fa38f4e6f9 | ||
|
|
2f38c36294 | ||
|
|
4cd951d703 | ||
|
|
8c629a9327 | ||
|
|
76b85583e1 | ||
|
|
57a8acf0c4 | ||
|
|
79975d6557 | ||
|
|
edee83272e | ||
|
|
15de22a2e1 | ||
|
|
fc0fceb43a | ||
|
|
1ae9b0e455 | ||
|
|
10dd49958c | ||
|
|
17fae3f4a3 | ||
|
|
5b90ea2aba |
1962 changed files with 69663 additions and 42673 deletions
31
.emmyrc.json
Normal file
31
.emmyrc.json
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"$schema": "https://raw.githubusercontent.com/EmmyLuaLs/emmylua-analyzer-rust/refs/heads/main/crates/emmylua_code_analysis/resources/schema.json",
|
||||
"format": {
|
||||
"externalTool": {
|
||||
"program": "stylua",
|
||||
"args": [
|
||||
"-",
|
||||
"--stdin-filepath",
|
||||
"${file}"
|
||||
]
|
||||
}
|
||||
},
|
||||
"diagnostics": {
|
||||
"disable": [
|
||||
"unnecessary-if",
|
||||
"incomplete-signature-doc"
|
||||
],
|
||||
"enables": [
|
||||
"iter-variable-reassign",
|
||||
"non-literal-expressions-in-assert",
|
||||
"missing-global-doc"
|
||||
]
|
||||
},
|
||||
"codeAction": {
|
||||
"insertSpace": true
|
||||
},
|
||||
"strict": {
|
||||
"typeCall": true,
|
||||
"arrayIndex": true
|
||||
}
|
||||
}
|
||||
4
.gitattributes
vendored
Normal file
4
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
runtime/queries/**/*.scm linguist-language=tsq
|
||||
doc/*.txt linguist-documentation
|
||||
SUPPORTED_LANGUAGES.md linguist-generated
|
||||
lua/nvim-treesitter/async.lua linguist-vendored
|
||||
7
.github/CODEOWNERS
vendored
7
.github/CODEOWNERS
vendored
|
|
@ -1,7 +0,0 @@
|
|||
/lua/nvim-treesitter/textobjects/ @theHamsta
|
||||
/lua/nvim-treesitter/incremental_selection.lua @theHamsta
|
||||
|
||||
/lua/nvim-treesitter/fold.lua @vigoux
|
||||
/lua/nvim-treesitter/highlight.lua @vigoux
|
||||
|
||||
/lua/nvim-treesitter/refactor/ @steelsojka
|
||||
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
|
|
@ -1,2 +0,0 @@
|
|||
open_collective: "nvim-treesitter"
|
||||
github: "nvim-treesitter"
|
||||
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
2
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
|
|
@ -1,6 +1,6 @@
|
|||
name: Bug report
|
||||
description: Create a report to help us improve
|
||||
labels: [bug]
|
||||
type: 'bug'
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
|
|
|
|||
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
|
|
@ -2,7 +2,7 @@
|
|||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ""
|
||||
labels: enhancement
|
||||
type: enhancement
|
||||
assignees: ""
|
||||
---
|
||||
|
||||
|
|
|
|||
11
.github/ISSUE_TEMPLATE/highlighting_issue.yml
vendored
11
.github/ISSUE_TEMPLATE/highlighting_issue.yml
vendored
|
|
@ -1,5 +1,6 @@
|
|||
name: Highlighting issue
|
||||
description: Missing or incorrect highlights or you want to change the way something is highlighted
|
||||
type: 'bug'
|
||||
labels: [highlights]
|
||||
|
||||
body:
|
||||
|
|
@ -11,10 +12,10 @@ body:
|
|||
- I have updated my neovim version to latest _master_.
|
||||
- I have updated my plugin to the latest version.
|
||||
- I have run `:TSUpdate`.
|
||||
- I have inspected the syntax tree using https://github.com/nvim-treesitter/playground and made sure
|
||||
- I have inspected the syntax tree using `:InspectTree` and made sure
|
||||
that no `ERROR` nodes are in the syntax tree. nvim-treesitter can not guarantee correct highlighting in the
|
||||
presence of `ERROR`s -- in this case, please report the bug directly at corresponding parser's repository. (You can find all repository URLs in [README.md](https://github.com/nvim-treesitter/nvim-treesitter#supported-languages).)
|
||||
- I have used `:TSHighlightCapturesUnderCursor` from https://github.com/nvim-treesitter/playground to inspect which highlight groups Neovim is using and that legacy syntax highlighting is not interfering (i.e., what you are observing is actual tree-sitter highlighting).
|
||||
- I have used `:Inspect` to inspect which highlight groups Neovim is using and that legacy syntax highlighting is not interfering (i.e., what you are observing is actual tree-sitter highlighting).
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
|
|
@ -34,8 +35,8 @@ body:
|
|||
attributes:
|
||||
label: Tree-sitter parsing result
|
||||
description: |
|
||||
Please provide the output of `:TSPlaygroundToggle` from https://github.com/nvim-treesitter/playground
|
||||
(screenshot or plain text) with the following options enabled (pressing the key):
|
||||
Please provide the output of `:InspectTree` (screenshot or plain text)
|
||||
with the following options enabled (pressing the key):
|
||||
- `I` (name of the parsed language)
|
||||
- `t` (toggle injected languages)
|
||||
- `a` (show anonymous nodes)
|
||||
|
|
@ -66,7 +67,7 @@ body:
|
|||
description: |
|
||||
Please provide a screenshot of the current highlighting. Please also tell us the `:h colorscheme` you are using
|
||||
and how to install it. If applicable, you can also upload a screenshot with the contents of
|
||||
`:TSHighlightCapturesUnderCursor`.
|
||||
`:Inspect`.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
|
|
|
|||
47
.github/PULL_REQUEST_TEMPLATE/new_language.md
vendored
Normal file
47
.github/PULL_REQUEST_TEMPLATE/new_language.md
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
<!--
|
||||
Before proceeding, make sure you have read https://github.com/nvim-treesitter/nvim-treesitter/blob/main/CONTRIBUTING.md!
|
||||
Make sure to fill out all fields and read the checklist at the end.
|
||||
-->
|
||||
|
||||
# Name of language
|
||||
|
||||
<!-- Link to an official description of the language -->
|
||||
https://...
|
||||
|
||||
Language file extension, if applicable: (e.g. `.zu`)
|
||||
|
||||
<details>
|
||||
<summary>Representative code sample</summary>
|
||||
```
|
||||
max. 50 lines
|
||||
```
|
||||
</details>
|
||||
|
||||
## Parser repo
|
||||
|
||||
https://github.com/...
|
||||
|
||||
<details>
|
||||
<summary>Parsed tree for code sample</summary>
|
||||
```
|
||||
paste output of tree-sitter parse or :InspectTree here
|
||||
```
|
||||
</details>
|
||||
|
||||
## Queries
|
||||
|
||||
Source of queries: https://github.com/... (or "written from scratch")
|
||||
|
||||
<details>
|
||||
<summary>Screenshots of code sample</summary>
|
||||
<!-- paste screenshot of code sample using provided queries here -->
|
||||
</details>
|
||||
|
||||
<!--
|
||||
CHECKLIST: _Before_ submitting, make sure
|
||||
|
||||
* `./scripts/install-parsers.lua <language>` works without warnings
|
||||
* `./scripts/install-parsers.lua --generate <language>` works without warnings
|
||||
* `make query` works without warning
|
||||
* `make docs` is run
|
||||
-->
|
||||
16
.github/dependabot.yml
vendored
Normal file
16
.github/dependabot.yml
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
cooldown:
|
||||
default-days: 3
|
||||
commit-message:
|
||||
prefix: "ci"
|
||||
labels:
|
||||
- "CI"
|
||||
groups:
|
||||
actions:
|
||||
patterns: ["*"]
|
||||
|
||||
37
.github/mergify.yml
vendored
37
.github/mergify.yml
vendored
|
|
@ -1,37 +0,0 @@
|
|||
pull_request_rules:
|
||||
- name: Merge lockfile updates
|
||||
conditions:
|
||||
- "title=Update lockfile.json"
|
||||
actions:
|
||||
review:
|
||||
type: APPROVE
|
||||
message: Automatically approving lockfile updates
|
||||
merge:
|
||||
method: merge
|
||||
|
||||
- name: Prepare for merge
|
||||
conditions:
|
||||
- and:
|
||||
- "-draft"
|
||||
- "#approved-reviews-by=1"
|
||||
- "#review-requested=0"
|
||||
actions:
|
||||
comment:
|
||||
message: |
|
||||
This PR is ready to be merged, and will be in 1 day if nothing happens before.
|
||||
If you want other people to review your PR, request their reviews.
|
||||
If you don't want this PR to be merged now, mark it as a Draft.
|
||||
|
||||
- name: Merge on approval
|
||||
conditions:
|
||||
- and:
|
||||
- or:
|
||||
- "#approved-reviews-by>=2"
|
||||
- and:
|
||||
- "#approved-reviews-by=1"
|
||||
- "updated-at>=1 day ago"
|
||||
- "-draft"
|
||||
- "#review-requested=0"
|
||||
actions:
|
||||
merge:
|
||||
method: rebase
|
||||
5
.github/pull_request_template.md
vendored
Normal file
5
.github/pull_request_template.md
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<!--
|
||||
Before proceeding, make sure you have read https://github.com/nvim-treesitter/nvim-treesitter/blob/main/CONTRIBUTING.md!
|
||||
If you are adding a new parser, use this link instead:
|
||||
<https://github.com/nvim-treesitter/nvim-treesitter/compare/main...my-branch?quick_pull=1&template=new_language.md>
|
||||
-->
|
||||
62
.github/workflows/downstream.yml
vendored
Normal file
62
.github/workflows/downstream.yml
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
name: Tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- "main"
|
||||
paths:
|
||||
- "lua/nvim-treesitter/parsers.lua"
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
test-downstream:
|
||||
name: Check downstream queries
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
NVIM: "nvim"
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: tree-sitter/setup-action/cli@v2
|
||||
|
||||
- name: Install and prepare Neovim
|
||||
env:
|
||||
NVIM_TAG: "nightly"
|
||||
run: |
|
||||
bash ./scripts/ci-install.sh
|
||||
|
||||
- name: Compile parsers
|
||||
run: $NVIM -l ./scripts/install-parsers.lua --max-jobs=10
|
||||
|
||||
- name: Set up ts_query_ls
|
||||
run: curl -fL https://github.com/ribru17/ts_query_ls/releases/latest/download/ts_query_ls-x86_64-unknown-linux-gnu.tar.gz | tar -xz
|
||||
|
||||
- name: Clone textobjects
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
repository: nvim-treesitter/nvim-treesitter-textobjects
|
||||
ref: main
|
||||
path: .tests/nvim-treesitter-textobjects
|
||||
sparse-checkout: queries
|
||||
|
||||
- name: Check textobjects
|
||||
working-directory: .tests/nvim-treesitter-textobjects/
|
||||
run: ../../ts_query_ls check queries/
|
||||
|
||||
- name: Clone context
|
||||
if: always()
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
repository: nvim-treesitter/nvim-treesitter-context
|
||||
ref: master
|
||||
path: .tests/nvim-treesitter-context
|
||||
sparse-checkout: queries
|
||||
|
||||
- name: Check context
|
||||
if: always()
|
||||
working-directory: .tests/nvim-treesitter-context/
|
||||
run: ../../ts_query_ls check queries/
|
||||
|
||||
59
.github/workflows/lint.yml
vendored
59
.github/workflows/lint.yml
vendored
|
|
@ -1,33 +1,50 @@
|
|||
name: Linting and style checking
|
||||
name: Lint
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "main"
|
||||
pull_request:
|
||||
branches:
|
||||
- "main"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
luacheck:
|
||||
name: Luacheck
|
||||
runs-on: ubuntu-latest
|
||||
lua:
|
||||
name: Lint Lua files
|
||||
runs-on: ubuntu-slim
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Prepare
|
||||
- name: Format
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install luarocks -y
|
||||
sudo luarocks install luacheck
|
||||
make formatlua
|
||||
git diff --exit-code
|
||||
|
||||
- name: Run Luacheck
|
||||
run: luacheck .
|
||||
- name: Lint
|
||||
run: make checklua
|
||||
|
||||
stylua:
|
||||
name: StyLua
|
||||
runs-on: ubuntu-latest
|
||||
queries:
|
||||
name: Lint query files
|
||||
runs-on: ubuntu-slim
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Lint with stylua
|
||||
uses: JohnnyMorganz/stylua-action@v3
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
version: latest
|
||||
args: --check .
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Format
|
||||
run: |
|
||||
make formatquery
|
||||
git diff --exit-code
|
||||
|
||||
- name: Lint
|
||||
run: make lintquery
|
||||
|
||||
readme:
|
||||
name: Lint docs
|
||||
runs-on: ubuntu-slim
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Check SUPPORTED_LANGUAGES
|
||||
run: |
|
||||
make docs
|
||||
git diff --exit-code
|
||||
|
|
|
|||
24
.github/workflows/release.yml
vendored
24
.github/workflows/release.yml
vendored
|
|
@ -1,24 +0,0 @@
|
|||
name: "release"
|
||||
on:
|
||||
push:
|
||||
tags: # Will upload to luarocks.org
|
||||
- "*"
|
||||
pull_request: # Will test a local install without uploading to luarocks.org
|
||||
paths:
|
||||
- 'contrib/*.rockspec'
|
||||
- .github/workflows/release.yml
|
||||
|
||||
jobs:
|
||||
luarocks-upload:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: nvim-neorocks/luarocks-tag-release@v5
|
||||
env:
|
||||
LUAROCKS_API_KEY: ${{ secrets.LUAROCKS_API_KEY }}
|
||||
with:
|
||||
name: nvim-treesitter
|
||||
detailed_description: |
|
||||
The goal of nvim-treesitter is both to provide a simple and easy way to use the interface for tree-sitter in Neovim
|
||||
and to provide some basic functionality such as highlighting based on it.
|
||||
template: contrib/nvim-treesitter-luarocks.template
|
||||
58
.github/workflows/test-core.yml
vendored
Normal file
58
.github/workflows/test-core.yml
vendored
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
type:
|
||||
type: string
|
||||
workflow_dispatch:
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
check_compilation:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
nvim_tag: [stable, nightly]
|
||||
name: ${{matrix.nvim_tag}} / ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
NVIM: ${{ matrix.os == 'windows-latest' && 'nvim-win64\\bin\\nvim.exe' || 'nvim' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: tree-sitter/setup-action/cli@v2
|
||||
|
||||
- name: Install and prepare Neovim
|
||||
env:
|
||||
NVIM_TAG: ${{ matrix.nvim_tag }}
|
||||
run: |
|
||||
bash ./scripts/ci-install.sh
|
||||
|
||||
- if: inputs.type == 'build'
|
||||
name: Compile parsers
|
||||
run: $NVIM -l ./scripts/install-parsers.lua --max-jobs=10
|
||||
|
||||
- if: inputs.type == 'generate'
|
||||
name: Generate and compile parsers
|
||||
run: $NVIM -l ./scripts/install-parsers.lua --generate --max-jobs=2
|
||||
|
||||
- name: Check parsers
|
||||
run: $NVIM -l ./scripts/check-parsers.lua
|
||||
|
||||
- name: Check queries (nvim)
|
||||
if: ${{ matrix.os == 'windows-latest' }}
|
||||
run: $NVIM -l ./scripts/check-queries.lua
|
||||
|
||||
- name: Check queries (tsqueryls)
|
||||
if: ${{ matrix.os != 'windows-latest' }}
|
||||
run: make checkquery
|
||||
|
||||
- name: Run highlight tests
|
||||
if: ${{ matrix.os != 'windows-latest' }}
|
||||
run: make tests TESTS=query NVIM_BIN=$NVIM
|
||||
|
||||
- name: Run indents tests
|
||||
if: ${{ matrix.os != 'windows-latest' }}
|
||||
run: make tests TESTS=indent NVIM_BIN=$NVIM
|
||||
20
.github/workflows/test-generate.yml
vendored
Normal file
20
.github/workflows/test-generate.yml
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
name: Tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [unlabeled, labeled, opened, synchronize, reopened]
|
||||
branches:
|
||||
- "main"
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-generate-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
check_compilation:
|
||||
name: Generate
|
||||
if: contains(github.event.pull_request.labels.*.name, 'ci:generate') || github.event_name == 'workflow_dispatch'
|
||||
uses: ./.github/workflows/test-core.yml
|
||||
with:
|
||||
type: "generate"
|
||||
86
.github/workflows/test-queries.yml
vendored
86
.github/workflows/test-queries.yml
vendored
|
|
@ -1,87 +1,21 @@
|
|||
name: Test queries
|
||||
name: Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "main"
|
||||
pull_request:
|
||||
branches:
|
||||
- "master"
|
||||
- "main"
|
||||
workflow_dispatch:
|
||||
|
||||
# Cancel any in-progress CI runs for a PR if it is updated
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}
|
||||
cancel-in-progress: true
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
group: ${{ github.workflow }}-build-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
check_compilation:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-2022, macos-latest]
|
||||
cc: [gcc, clang]
|
||||
nvim_tag: [stable]
|
||||
exclude:
|
||||
- os: ubuntu-latest
|
||||
cc: clang
|
||||
nvim_tag: stable
|
||||
|
||||
- os: macos-latest
|
||||
cc: gcc
|
||||
nvim_tag: stable
|
||||
|
||||
- os: windows-2022
|
||||
cc: clang
|
||||
nvim_tag: stable
|
||||
|
||||
include:
|
||||
- os: windows-2022
|
||||
cc: cl
|
||||
nvim_tag: stable
|
||||
|
||||
- os: ubuntu-latest
|
||||
cc: gcc
|
||||
nvim_tag: nightly
|
||||
|
||||
name: Parser compilation
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
CC: ${{ matrix.cc }}
|
||||
NVIM: ${{ matrix.os == 'windows-2022' && 'nvim-win64\\bin\\nvim.exe' || 'nvim' }}
|
||||
ALLOWED_INSTALLATION_FAILURES: ${{ matrix.os == 'windows-2022' && 'rnoweb' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ilammy/msvc-dev-cmd@v1
|
||||
- uses: actions/setup-node@v4
|
||||
|
||||
- name: Install tree-sitter CLI
|
||||
run: npm i -g tree-sitter-cli
|
||||
|
||||
- name: Install and prepare Neovim
|
||||
env:
|
||||
NVIM_TAG: ${{ matrix.nvim_tag }}
|
||||
run: |
|
||||
bash ./scripts/ci-install-${{ matrix.os }}.sh
|
||||
|
||||
- name: Setup Parsers Cache
|
||||
id: parsers-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./parser/
|
||||
~/AppData/Local/nvim/pack/nvim-treesitter/start/nvim-treesitter/parser/
|
||||
key: ${{ matrix.os }}-${{ matrix.cc }}-${{ matrix.nvim_tag }}-parsers-v1-${{ hashFiles('./lockfile.json', './lua/nvim-treesitter/parsers.lua', './lua/nvim-treesitter/install.lua', './lua/nvim-treesitter/shell_command_selectors.lua') }}
|
||||
|
||||
- name: Compile parsers
|
||||
run: $NVIM --headless -c "lua require'nvim-treesitter.install'.prefer_git=false" -c "TSInstallSync all" -c "q"
|
||||
|
||||
- name: Post compile Windows
|
||||
if: matrix.os == 'windows-2022'
|
||||
run: cp -r ~/AppData/Local/nvim/pack/nvim-treesitter/start/nvim-treesitter/parser/* parser
|
||||
|
||||
- name: Check query files
|
||||
run: $NVIM -l scripts/check-queries.lua
|
||||
name: Build
|
||||
uses: ./.github/workflows/test-core.yml
|
||||
with:
|
||||
type: "build"
|
||||
|
|
|
|||
65
.github/workflows/tests.yml
vendored
65
.github/workflows/tests.yml
vendored
|
|
@ -1,65 +0,0 @@
|
|||
name: Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
pull_request:
|
||||
branches:
|
||||
- "master"
|
||||
|
||||
# Cancel any in-progress CI runs for a PR if it is updated
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
check_compilation:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-latest]
|
||||
cc: [gcc]
|
||||
|
||||
name: Run tests
|
||||
runs-on: ${{ matrix.os }}
|
||||
env:
|
||||
CC: ${{ matrix.cc }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
|
||||
- name: Install tree-sitter CLI
|
||||
run: npm i -g tree-sitter-cli
|
||||
|
||||
- name: Test Dependencies
|
||||
run: |
|
||||
mkdir -p ~/.local/share/nvim/site/pack/plenary.nvim/start
|
||||
cd ~/.local/share/nvim/site/pack/plenary.nvim/start
|
||||
git clone https://github.com/nvim-lua/plenary.nvim
|
||||
curl -L https://github.com/theHamsta/highlight-assertions/releases/download/v0.1.6/highlight-assertions_v0.1.6_x86_64-unknown-linux-gnu.tar.gz | tar -xz
|
||||
cp highlight-assertions /usr/local/bin
|
||||
|
||||
- name: Install and prepare Neovim
|
||||
env:
|
||||
NVIM_TAG: stable
|
||||
TREE_SITTER_CLI_TAG: v0.20.8
|
||||
run: |
|
||||
bash ./scripts/ci-install-${{ matrix.os }}.sh
|
||||
|
||||
- name: Setup Parsers Cache
|
||||
id: parsers-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./parser/
|
||||
~/AppData/Local/nvim/pack/nvim-treesitter/start/nvim-treesitter/parser/
|
||||
key: ${{ matrix.os }}-${{ matrix.cc }}-parsers-v1-${{ hashFiles('./lockfile.json', './lua/nvim-treesitter/parsers.lua', './lua/nvim-treesitter/install.lua', './lua/nvim-treesitter/shell_selectors.lua') }}
|
||||
|
||||
- name: Compile parsers Unix like
|
||||
if: ${{ matrix.os != 'windows-latest' && steps.parsers-cache.outputs.cache-hit != 'true' }}
|
||||
run: |
|
||||
nvim --headless -c "TSInstallSync all" -c "q"
|
||||
|
||||
- name: Tests
|
||||
run: PATH=/usr/local/bin:$PATH ./scripts/run_tests.sh
|
||||
52
.github/workflows/update-lockfile.yml
vendored
52
.github/workflows/update-lockfile.yml
vendored
|
|
@ -1,52 +0,0 @@
|
|||
name: Update lockfile
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "30 6 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
update-lockfile:
|
||||
name: Update lockfile
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: master
|
||||
|
||||
- name: Prepare
|
||||
env:
|
||||
NVIM_TAG: stable
|
||||
run: |
|
||||
wget https://github.com/josephburnett/jd/releases/download/v1.7.1/jd-amd64-linux
|
||||
mv jd-amd64-linux /tmp/jd
|
||||
chmod +x /tmp/jd
|
||||
bash scripts/ci-install-ubuntu-latest.sh
|
||||
|
||||
- name: Update parsers
|
||||
env:
|
||||
SKIP_LOCKFILE_UPDATE_FOR_LANGS: ""
|
||||
run: |
|
||||
cp lockfile.json /tmp/old_lockfile.json
|
||||
nvim -l scripts/write-lockfile.lua
|
||||
# Pretty print
|
||||
cp lockfile.json /tmp/lockfile.json
|
||||
cat /tmp/lockfile.json | jq --sort-keys > lockfile.json
|
||||
|
||||
- name: Commit changes
|
||||
run: |
|
||||
git config user.name 'GitHub'
|
||||
git config user.email 'noreply@github.com'
|
||||
git add lockfile.json
|
||||
UPDATED_PARSERS=$(/tmp/jd -f merge /tmp/old_lockfile.json lockfile.json | jq -r 'keys | join(", ")')
|
||||
echo "UPDATED_PARSERS=$UPDATED_PARSERS" >> $GITHUB_ENV
|
||||
git commit -m "Update parsers: $UPDATED_PARSERS" || echo 'No commit necessary!'
|
||||
git clean -xf
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
with:
|
||||
title: "Update lockfile.json: ${{ env.UPDATED_PARSERS }}"
|
||||
branch: update-lockfile-pr
|
||||
base: ${{ github.head_ref }}
|
||||
draft: true
|
||||
60
.github/workflows/update-parsers.yml
vendored
Normal file
60
.github/workflows/update-parsers.yml
vendored
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
name: Update parsers
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "30 6 * * 6"
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
BIN_DIR: ${{ github.workspace }}/bin
|
||||
|
||||
jobs:
|
||||
update-parsers:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
tier: [1, 2]
|
||||
name: Update parsers tier ${{ matrix.tier }}
|
||||
runs-on: ubuntu-slim
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: main
|
||||
|
||||
- uses: actions/create-github-app-token@v3
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ vars.TOKEN_ID }}
|
||||
private-key: ${{ secrets.TOKEN_PRIVATE_KEY }}
|
||||
|
||||
- name: Add $BIN_DIR to PATH
|
||||
run: echo "$BIN_DIR" >> $GITHUB_PATH
|
||||
|
||||
- name: Prepare
|
||||
env:
|
||||
NVIM_TAG: nightly
|
||||
run: |
|
||||
bash scripts/ci-install.sh
|
||||
wget --directory-prefix="$BIN_DIR" https://github.com/JohnnyMorganz/StyLua/releases/latest/download/stylua-linux-x86_64.zip
|
||||
(cd "$BIN_DIR"; unzip stylua*.zip)
|
||||
|
||||
- name: Update parsers
|
||||
run: ./scripts/update-parsers.lua --tier=${{ matrix.tier }}
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v8
|
||||
with:
|
||||
add-paths: lua/nvim-treesitter/parsers.lua
|
||||
token: ${{ steps.app-token.outputs.token }}
|
||||
sign-commits: true
|
||||
commit-message: "bot(parsers): update ${{ env.UPDATED_PARSERS }}"
|
||||
title: "Update parsers (tier ${{ matrix.tier }}): ${{ env.UPDATED_PARSERS }}"
|
||||
body: "[beep boop](https://github.com/peter-evans/create-pull-request)"
|
||||
branch: update-parsers-tier-${{ matrix.tier }}
|
||||
base: ${{ github.head_ref }}
|
||||
|
||||
- name: Enable Pull Request Automerge
|
||||
if: ${{ matrix.tier == 2 }}
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||
run: gh pr merge --rebase --auto update-parsers-tier-2
|
||||
38
.github/workflows/update-readme.yml
vendored
38
.github/workflows/update-readme.yml
vendored
|
|
@ -1,38 +0,0 @@
|
|||
name: Update README
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
update-readme:
|
||||
name: Update README
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Prepare
|
||||
env:
|
||||
NVIM_TAG: stable
|
||||
run: |
|
||||
bash ./scripts/ci-install-ubuntu-latest.sh
|
||||
|
||||
- name: Check README
|
||||
run: |
|
||||
git config user.email 'actions@github'
|
||||
git config user.name 'Github Actions'
|
||||
nvim -l scripts/update-readme.lua || echo 'Needs update'
|
||||
git add README.md
|
||||
git commit -m 'Update README' || echo 'No commit necessary!'
|
||||
git clean -xf
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
with:
|
||||
commit-message: Update README
|
||||
title: Update README
|
||||
branch: update-readme-pr
|
||||
base: ${{ github.head_ref }}
|
||||
draft: true
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -1,7 +1,8 @@
|
|||
.test-deps
|
||||
doc/tags
|
||||
.luacheckcache
|
||||
/tags
|
||||
nvim.appimage
|
||||
nvim-linux64*
|
||||
nvim-linux-x86_64*
|
||||
nvim-macos*
|
||||
nvim-win64*
|
||||
|
|
|
|||
21
.luacheckrc
21
.luacheckrc
|
|
@ -1,21 +0,0 @@
|
|||
-- Rerun tests only if their modification time changed.
|
||||
cache = true
|
||||
codes = true
|
||||
|
||||
exclude_files = {
|
||||
"tests/indent/lua/"
|
||||
}
|
||||
|
||||
-- Glorious list of warnings: https://luacheck.readthedocs.io/en/stable/warnings.html
|
||||
ignore = {
|
||||
"212", -- Unused argument, In the case of callback function, _arg_name is easier to understand than _, so this option is set to off.
|
||||
"411", -- Redefining a local variable.
|
||||
"412", -- Redefining an argument.
|
||||
"422", -- Shadowing an argument
|
||||
"122" -- Indirectly setting a readonly global
|
||||
}
|
||||
|
||||
-- Global objects defined by the C code
|
||||
read_globals = {
|
||||
"vim",
|
||||
}
|
||||
11
.luarc.json
11
.luarc.json
|
|
@ -1,15 +1,18 @@
|
|||
{
|
||||
"$schema": "https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json",
|
||||
"runtime": {
|
||||
"version": "LuaJIT"
|
||||
"version": "LuaJIT"
|
||||
},
|
||||
"workspace": {
|
||||
"library": [
|
||||
"lua",
|
||||
"$VIMRUNTIME",
|
||||
"${3rd}/luv/library"
|
||||
"${3rd}/busted/library"
|
||||
],
|
||||
"checkThirdParty": false
|
||||
"ignoreDir": [
|
||||
".test-deps",
|
||||
"tests"
|
||||
],
|
||||
"checkThirdParty": "Disable"
|
||||
},
|
||||
"diagnostics": {
|
||||
"groupFileStatus": {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
column_width = 120
|
||||
column_width = 100
|
||||
line_endings = "Unix"
|
||||
indent_type = "Spaces"
|
||||
indent_width = 2
|
||||
quote_style = "AutoPreferDouble"
|
||||
call_parentheses = "None"
|
||||
quote_style = "AutoPreferSingle"
|
||||
call_parentheses = "Always"
|
||||
|
|
|
|||
405
.tsqueryrc.json
Normal file
405
.tsqueryrc.json
Normal file
|
|
@ -0,0 +1,405 @@
|
|||
{
|
||||
"$schema": "https://raw.githubusercontent.com/ribru17/ts_query_ls/refs/heads/master/schemas/config.json",
|
||||
"parser_install_directories": ["${HOME}/.local/share/nvim/site/parser"],
|
||||
"supported_abi_versions": {
|
||||
"start": 13,
|
||||
"end": 15
|
||||
},
|
||||
"parser_aliases": {
|
||||
"html_tags": "html",
|
||||
"ecma": "javascript",
|
||||
"jsx": "javascript"
|
||||
},
|
||||
"valid_captures": {
|
||||
"highlights": {
|
||||
"variable": "various variable names",
|
||||
"variable.builtin": "built-in variable names (e.g. `this`)",
|
||||
"variable.parameter": "parameters of a function",
|
||||
"variable.parameter.builtin": "special parameters (e.g. `_`, `it`)",
|
||||
"variable.member": "object and struct fields",
|
||||
|
||||
"constant": "constant identifiers",
|
||||
"constant.builtin": "built-in constant values",
|
||||
"constant.macro": "constants defined by the preprocessor",
|
||||
|
||||
"module": "modules or namespaces",
|
||||
"module.builtin": "built-in modules or namespaces",
|
||||
"label": "GOTO and other labels (e.g. `label:` in C), including heredoc labels",
|
||||
|
||||
"string": "string literals",
|
||||
"string.documentation": "string documenting code (e.g. Python docstrings)",
|
||||
"string.regexp": "regular expressions",
|
||||
"string.escape": "escape sequences",
|
||||
"string.special": "other special strings (e.g. dates)",
|
||||
"string.special.symbol": "symbols or atoms",
|
||||
"string.special.url": "URIs (e.g. hyperlinks)",
|
||||
"string.special.path": "filenames",
|
||||
|
||||
"character": "character literals",
|
||||
"character.special": "special characters (e.g. wildcards)",
|
||||
|
||||
"boolean": "boolean literals",
|
||||
"number": "numeric literals",
|
||||
"number.float": "floating-point number literals",
|
||||
|
||||
"type": "type or class definitions and annotations",
|
||||
"type.builtin": "built-in types",
|
||||
"type.definition": "identifiers in type definitions (e.g. `typedef <type> <identifier>` in C)",
|
||||
|
||||
"attribute": "attribute annotations (e.g. Python decorators, Rust lifetimes)",
|
||||
"attribute.builtin": "builtin annotations (e.g. `@property` in Python)",
|
||||
"property": "the key in key/value pairs",
|
||||
|
||||
"function": "function definitions",
|
||||
"function.builtin": "built-in functions",
|
||||
"function.call": "function calls",
|
||||
"function.macro": "preprocessor macros",
|
||||
|
||||
"function.method": "method definitions",
|
||||
"function.method.call": "method calls",
|
||||
|
||||
"constructor": "constructor calls and definitions",
|
||||
"operator": "symbolic operators (e.g. `+` / `*`)",
|
||||
|
||||
"keyword": "keywords not fitting into specific categories",
|
||||
"keyword.coroutine": "keywords related to coroutines (e.g. `go` in Go, `async/await` in Python)",
|
||||
"keyword.function": "keywords that define a function (e.g. `func` in Go, `def` in Python)",
|
||||
"keyword.operator": "operators that are English words (e.g. `and` / `or`)",
|
||||
"keyword.import": "keywords for including or exporting modules (e.g. `import` / `from` in Python)",
|
||||
"keyword.type": "keywords describing namespaces and composite types (e.g. `struct`, `enum`)",
|
||||
"keyword.modifier": "keywords modifying other constructs (e.g. `const`, `static`, `public`)",
|
||||
"keyword.repeat": "keywords related to loops (e.g. `for` / `while`)",
|
||||
"keyword.return": "keywords like `return` and `yield`",
|
||||
"keyword.debug": "keywords related to debugging",
|
||||
"keyword.exception": "keywords related to exceptions (e.g. `throw` / `catch`)",
|
||||
"keyword.conditional": "keywords related to conditionals (e.g. `if` / `else`)",
|
||||
"keyword.conditional.ternary": "ternary operator (e.g. `?` / `:`)",
|
||||
"keyword.directive": "various preprocessor directives & shebangs",
|
||||
"keyword.directive.define": "preprocessor definition directives",
|
||||
|
||||
"punctuation.delimiter": "delimiters (e.g. `;` / `.` / `,`)",
|
||||
"punctuation.bracket": "brackets (e.g. `()` / `{}` / `[]`)",
|
||||
"punctuation.special": "special symbols (e.g. `{}` in string interpolation)",
|
||||
|
||||
"comment": "line and block comments",
|
||||
"comment.documentation": "comments documenting code",
|
||||
"comment.error": "error-type comments (e.g. `ERROR`, `FIXME`, `DEPRECATED`)",
|
||||
"comment.warning": "warning-type comments (e.g. `WARNING`, `FIX`, `HACK`)",
|
||||
"comment.todo": "todo-type comments (e.g. `TODO`, `WIP`)",
|
||||
"comment.note": "note-type comments (e.g. `NOTE`, `INFO`, `XXX`)",
|
||||
|
||||
"markup.strong": "bold text",
|
||||
"markup.italic": "italic text",
|
||||
"markup.strikethrough": "struck-through text",
|
||||
"markup.underline": "underlined text (only for literal underline markup!)",
|
||||
"markup.heading": "headings, titles (including markers)",
|
||||
"markup.heading.1": "top-level heading",
|
||||
"markup.heading.2": "section heading",
|
||||
"markup.heading.3": "subsection heading",
|
||||
"markup.heading.4": "and so on",
|
||||
"markup.heading.5": "and so forth",
|
||||
"markup.heading.6": "six levels ought to be enough for anybody",
|
||||
"markup.quote": "block quotes",
|
||||
"markup.math": "math environments (e.g. `$ ... $` in LaTeX)",
|
||||
"markup.link": "text references, footnotes, citations, etc.",
|
||||
"markup.link.label": "link, reference descriptions",
|
||||
"markup.link.url": "URL-style links",
|
||||
"markup.raw": "literal or verbatim text (e.g. inline code)",
|
||||
"markup.raw.block": "literal or verbatim text as a stand-alone block ; (use priority 90 for blocks with injections)",
|
||||
"markup.list": "list markers",
|
||||
"markup.list.checked": "checked todo-style list markers",
|
||||
"markup.list.unchecked": "unchecked todo-style list markers",
|
||||
|
||||
"diff.plus": "added text (for diff files)",
|
||||
"diff.minus": "deleted text (for diff files)",
|
||||
"diff.delta": "changed text (for diff files)",
|
||||
|
||||
"tag": "XML-style tag names (and similar)",
|
||||
"tag.builtin": "builtin tag names (e.g. HTML5 tags)",
|
||||
"tag.attribute": "XML-style tag attributes",
|
||||
"tag.delimiter": "XML-style tag delimiters",
|
||||
|
||||
"conceal": "captures that are only meant to be concealed",
|
||||
"spell": "for defining regions to be spellchecked",
|
||||
"nospell": "for defining regions that should NOT be spellchecked",
|
||||
"none": "completely disable the highlight"
|
||||
},
|
||||
"injections": {
|
||||
"injection.content": "indicates that the captured node should have its contents re-parsed using another language",
|
||||
"injection.language": "indicates that the captured node’s text may contain the name of a language that should be used to re-parse the `@injection.content`",
|
||||
"injection.filename": "indicates that the captured node’s text may contain a filename; the corresponding filetype is then looked-up up via `vim.filetype.match()` and treated as the name of a language that should be used to re-parse the `@injection.content`"
|
||||
},
|
||||
"folds": {
|
||||
"fold": "fold this node"
|
||||
},
|
||||
"indents": {
|
||||
"indent.begin": "Specifies that the next line should be indented. Multiple indents on the same line get collapsed. Indent can also have `indent.immediate` set using a `#set!` directive, which permits the next line to indent even when the block intended to be indented has no content yet, improving interactive typing.",
|
||||
"indent.end": "Used to specify that the indented region ends and any text subsequent to the capture should be dedented.",
|
||||
"indent.align": "Specifies aligned indent blocks (like python aligned/hanging indent). Specify the delimiters with `indent.open_delimiter` and `indent.close_delimiter` metadata. For some languages, the last line of an `indent.align` block must not be the same indent as the natural next line, which can be controlled by setting `indent.avoid_last_matching_next`.",
|
||||
"indent.dedent": "Specifies dedenting starting on the next line.",
|
||||
"indent.branch": "Used to specify that a dedented region starts at the line including the captured nodes.",
|
||||
"indent.ignore": "Specifies that indentation should be ignored for this node.",
|
||||
"indent.auto": "Behaves like 'autoindent' buffer option.",
|
||||
"indent.zero": "Sets indentation for this node to zero (no indentation)."
|
||||
},
|
||||
"locals": {
|
||||
"local.definition": "various definitions",
|
||||
"local.definition.constant": "constants",
|
||||
"local.definition.function": "functions",
|
||||
"local.definition.method": "methods",
|
||||
"local.definition.var": "variables",
|
||||
"local.definition.parameter": "parameters",
|
||||
"local.definition.macro": "preprocessor macros",
|
||||
"local.definition.type": "types or classes",
|
||||
"local.definition.field": "fields or properties",
|
||||
"local.definition.enum": "enumerations",
|
||||
"local.definition.namespace": "modules or namespaces",
|
||||
"local.definition.import": "imported names",
|
||||
"local.definition.associated": "the associated type of a variable",
|
||||
"local.scope": "scope block",
|
||||
"local.reference": "identifier reference"
|
||||
}
|
||||
},
|
||||
"valid_predicates": {
|
||||
"eq": {
|
||||
"any": true,
|
||||
"parameters": [
|
||||
{
|
||||
"type": "capture",
|
||||
"arity": "required"
|
||||
},
|
||||
{
|
||||
"type": "any",
|
||||
"arity": "required"
|
||||
}
|
||||
],
|
||||
"description": "checks for equality between two nodes, or a node and a string"
|
||||
},
|
||||
"any-of": {
|
||||
"parameters": [
|
||||
{
|
||||
"type": "capture",
|
||||
"arity": "required"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"arity": "required"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"arity": "required"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"arity": "variadic"
|
||||
}
|
||||
],
|
||||
"description": "match any of the given strings against the text corresponding to a node"
|
||||
},
|
||||
"contains": {
|
||||
"any": true,
|
||||
"parameters": [
|
||||
{
|
||||
"type": "capture",
|
||||
"arity": "required"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"arity": "required"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"arity": "variadic"
|
||||
}
|
||||
],
|
||||
"description": "match a string against parts of the text corresponding to a node"
|
||||
},
|
||||
"match": {
|
||||
"any": true,
|
||||
"parameters": [
|
||||
{
|
||||
"type": "capture",
|
||||
"arity": "required"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"arity": "required"
|
||||
}
|
||||
],
|
||||
"description": "Match a regexp against the text corresponding to a node"
|
||||
},
|
||||
"lua-match": {
|
||||
"any": true,
|
||||
"parameters": [
|
||||
{
|
||||
"type": "capture",
|
||||
"arity": "required"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"arity": "required"
|
||||
}
|
||||
],
|
||||
"description": "match a Lua pattern against the text corresponding to a node"
|
||||
},
|
||||
"has-ancestor": {
|
||||
"parameters": [
|
||||
{
|
||||
"type": "capture",
|
||||
"arity": "required"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"arity": "required",
|
||||
"constraint": "named_node"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"arity": "variadic",
|
||||
"constraint": "named_node"
|
||||
}
|
||||
],
|
||||
"description": "match any of the given node types against all ancestors of a node"
|
||||
},
|
||||
"has-parent": {
|
||||
"parameters": [
|
||||
{
|
||||
"type": "capture",
|
||||
"arity": "required"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"arity": "required",
|
||||
"constraint": "named_node"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"arity": "variadic",
|
||||
"constraint": "named_node"
|
||||
}
|
||||
],
|
||||
"description": "match any of the given node types against the direct ancestor of a node"
|
||||
},
|
||||
"kind-eq": {
|
||||
"parameters": [
|
||||
{
|
||||
"type": "capture",
|
||||
"arity": "required"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"arity": "required",
|
||||
"constraint": "named_node"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"arity": "variadic",
|
||||
"constraint": "named_node"
|
||||
}
|
||||
],
|
||||
"description": "checks whether a capture corresponds to a given set of nodes"
|
||||
}
|
||||
},
|
||||
"valid_directives": {
|
||||
"set": {
|
||||
"parameters": [
|
||||
{
|
||||
"type": "any",
|
||||
"arity": "required"
|
||||
},
|
||||
{
|
||||
"type": "any",
|
||||
"arity": "optional"
|
||||
},
|
||||
{
|
||||
"type": "any",
|
||||
"arity": "optional"
|
||||
}
|
||||
],
|
||||
"description": "sets key/value metadata for a specific match or capture"
|
||||
},
|
||||
"offset": {
|
||||
"parameters": [
|
||||
{
|
||||
"type": "capture",
|
||||
"arity": "required"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"arity": "required",
|
||||
"constraint": "integer"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"arity": "required",
|
||||
"constraint": "integer"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"arity": "required",
|
||||
"constraint": "integer"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"arity": "required",
|
||||
"constraint": "integer"
|
||||
}
|
||||
],
|
||||
"description": "Takes the range of the captured node and applies an offset. This will set a new range in the form of a list like { {start_row}, {start_col}, {end_row}, {end_col} } for the captured node with `capture_id` as `metadata[capture_id].range`."
|
||||
},
|
||||
"gsub": {
|
||||
"parameters": [
|
||||
{
|
||||
"type": "capture",
|
||||
"arity": "required"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"arity": "required"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"arity": "required"
|
||||
}
|
||||
],
|
||||
"description": "Transforms the content of the node using a Lua pattern. This will set a new `metadata[capture_id].text`."
|
||||
},
|
||||
"trim": {
|
||||
"parameters": [
|
||||
{
|
||||
"type": "capture",
|
||||
"arity": "required"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"arity": "optional",
|
||||
"constraint": {
|
||||
"enum": ["0", "1"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"arity": "optional",
|
||||
"constraint": {
|
||||
"enum": ["0", "1"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"arity": "optional",
|
||||
"constraint": {
|
||||
"enum": ["0", "1"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"arity": "optional",
|
||||
"constraint": {
|
||||
"enum": ["0", "1"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"description": "Trims whitespace from the node. Sets a new `metadata[capture_id].range`. Takes a capture ID and, optionally, four integers to customize trimming behavior (`1` meaning trim, `0` meaning don't trim). When only given a capture ID, trims blank lines (lines that contain only whitespace, or are empty) from the end of the node (for backwards compatibility). Can trim all whitespace from both sides of the node if parameters are given."
|
||||
}
|
||||
}
|
||||
}
|
||||
696
CONTRIBUTING.md
696
CONTRIBUTING.md
|
|
@ -1,77 +1,103 @@
|
|||
# Contributing to `nvim-treesitter`
|
||||
|
||||
First of all, thank you very much for contributing to `nvim-treesitter`.
|
||||
The main parts of `nvim-treesitter` are
|
||||
* a curated list of [parsers](#Parsers);
|
||||
* a collection of [queries](#Queries).
|
||||
|
||||
If you haven't already, you should really come and reach out to us on our
|
||||
[Matrix channel], so we can help you with any question you might have!
|
||||
Before describing these in detail, some general advice:
|
||||
* Some basic knowledge of how tree-sitter works is assumed; we recommend reading
|
||||
- the [upstream documentation](https://tree-sitter.github.io/tree-sitter/);
|
||||
- [Neovim's documentation](https://neovim.io/doc/user/treesitter.html#treesitter).
|
||||
* There are dedicated Matrix channels for questions and general help:
|
||||
- [#nvim-treesitter](https://matrix.to/#/#nvim-treesitter:matrix.org) for questions specific to Neovim's implementation and the queries here;
|
||||
- [#tree-sitter](https://matrix.to/#/#tree-sitter-chat:matrix.org) for general questions regarding treesitter queries and the `tree-sitter` CLI.
|
||||
|
||||
As you know, `nvim-treesitter` is roughly split in two parts:
|
||||
## Parsers
|
||||
|
||||
- Parser configurations : for various things like `locals`, `highlights`
|
||||
- What we like to call _modules_ : tiny lua modules that provide a given feature, based on parser configurations
|
||||
>[!IMPORTANT]
|
||||
> To qualify for inclusion, a parser must meet the following criteria:
|
||||
> * correspond to a filetype detected by Neovim (nightly)
|
||||
> * feature complete, tested by users, and actively maintained (according to maintainer discretion)
|
||||
> * hosted or mirrored on Github (other codeforges are not reliable enough for CI)
|
||||
> * covered by CI using [upstream workflows](https://github.com/tree-sitter/workflows)
|
||||
> * provide reference queries covered by a [`ts_query_ls` workflow](https://github.com/tree-sitter-grammars/template/blob/9c46d09d688d27c7aef31c2b32f50260de4e7906/.github/workflows/ci.yml#L69-L86)
|
||||
> * if the repo contains a `src/parser.c`, it must support the latest ABI
|
||||
> * if the repo does _not_ contain a `src/parser.c`, it must contain an up-to-date `src/grammar.json`
|
||||
> * if the repo contains an external scanner, it must be written in C99
|
||||
>
|
||||
> Tier 1 parsers (preferred) in addition need to
|
||||
> * make regular releases following semver (_patch_ for fixes not affecting queries; _minor_ for changes introducing new nodes or patterns; _major_ for changes removing nodes or previously valid patterns)
|
||||
> * provide WASM release artifacts
|
||||
|
||||
Depending on which part of the plugin you want to contribute to, please read the appropriate section.
|
||||
To add a new parser, edit the following files:
|
||||
|
||||
## Style Checks and Tests
|
||||
1. In `lua/parsers.lua`, add an entry to the returned table of the following form:
|
||||
|
||||
We haven't implemented any functional tests yet. Feel free to contribute.
|
||||
However, we check code style with `luacheck` and `stylua`!
|
||||
Please install luacheck and activate our `pre-push` hook to automatically check style before
|
||||
every push:
|
||||
|
||||
```bash
|
||||
luarocks install luacheck
|
||||
cargo install stylua
|
||||
ln -s ../../scripts/pre-push .git/hooks/pre-push
|
||||
```lua
|
||||
zimbu = {
|
||||
install_info = {
|
||||
url = 'https://github.com/zimbulang/tree-sitter-zimbu', -- git repo; use `path` for local path
|
||||
revision = 'v2.1', -- tag or commit hash
|
||||
-- optional entries:
|
||||
branch = 'develop', -- only needed if different from default branch
|
||||
location = 'parser', -- only needed if the parser is in subdirectory of a "monorepo"
|
||||
generate = true, -- only needed if repo does not contain pre-generated src/parser.c
|
||||
},
|
||||
maintainers = { '@me' }, -- the _query_ maintainers
|
||||
tier = 1, -- stable: track versioned releases instead of latest commit
|
||||
-- optional entries:
|
||||
requires = { 'vim' }, -- if the queries inherit from another language
|
||||
readme_note = "an example language",
|
||||
}
|
||||
```
|
||||
|
||||
## Adding new modules
|
||||
>[!IMPORTANT]
|
||||
> The "maintainers" here refers to the person maintaining the **queries** in `nvim-treesitter`, not the parser maintainers (who likely don't use Neovim). The maintainers' duty is to review issues and PRs related to the query and to keep them updated with respect to parser changes.
|
||||
|
||||
If you want to see a new functionality added to `nvim-treesitter` feel free to first open an issue
|
||||
to that we can track our solution!
|
||||
Thus far, there is basically two types of modules:
|
||||
2. If the parser name is not the same as the Vim filetype, add an entry to the `filetypes` table in `plugin/filetypes.lua`:
|
||||
|
||||
- Little modules (like `incremental selection`) that are built in `nvim-treesitter`, we call them
|
||||
`builtin modules`.
|
||||
- Bigger modules (like `completion-treesitter`, or `nvim-tree-docs`), or modules that integrate
|
||||
with other plugins, that we call `remote modules`.
|
||||
```lua
|
||||
zimbu = { 'zu' },
|
||||
```
|
||||
|
||||
In any case, you can build your own module! To help you started in the process, we have a template
|
||||
repository designed to build new modules [here](https://github.com/nvim-treesitter/module-template).
|
||||
Feel free to use it, and contact us over on our
|
||||
on the "Neovim tree-sitter" [Matrix channel].
|
||||
3. Update the list of [supported languages] by running `make docs` (or `./scripts/update-readme.lua` if on Windows).
|
||||
|
||||
## Parser configurations
|
||||
4. Test if both `:TSInstall zimbu` and `:TSInstallFromGrammar zimbu` work without errors (`:checkhealth treesitter` or `./scripts/check-parsers.lua zimbu`).
|
||||
|
||||
Contributing to parser configurations is basically modifying one of the `queries/*/*.scm`.
|
||||
Each of these `scheme` files contains a _tree-sitter query_ for a given purpose.
|
||||
Before going any further, we highly suggest that you [read more about tree-sitter queries](https://tree-sitter.github.io/tree-sitter/using-parsers#pattern-matching-with-queries).
|
||||
>[!IMPORTANT]
|
||||
> You also need to add queries in order for the parser to actually be useful!
|
||||
|
||||
Each query has an appropriate name, which is then used by modules to extract data from the syntax tree.
|
||||
For now these are the types of queries used by `nvim-treesitter`:
|
||||
When you're done, open a Pull Request using the [provided template](.github/PULL_REQUEST_TEMPLATE/new_language.md), e.g. using `gh pr create -B main -T new_language`.
|
||||
|
||||
- `highlights.scm`: used for syntax highlighting, using the `highlight` module.
|
||||
- `locals.scm`: used to extract keyword definitions, scopes, references, etc, using the `locals` module.
|
||||
- `textobjects.scm`: used to define text objects.
|
||||
- `folds.scm`: used to define folds.
|
||||
- `injections.scm`: used to define injections.
|
||||
## Queries
|
||||
|
||||
For these types there is a _norm_ you will have to follow so that features work fine.
|
||||
Here are some global advices:
|
||||
To add (or edit existing) queries, create a corresponding `runtime/queries/zimbu/*.scm` file:
|
||||
|
||||
- If your language is listed [here](https://github.com/nvim-treesitter/nvim-treesitter#supported-languages),
|
||||
you can install the [playground plugin](https://github.com/nvim-treesitter/playground).
|
||||
- If your language is listed [here](https://github.com/nvim-treesitter/nvim-treesitter#supported-languages),
|
||||
you can debug and experiment with your queries there.
|
||||
- If not, you should consider installing the [tree-sitter cli](https://github.com/tree-sitter/tree-sitter/tree/master/cli),
|
||||
you should then be able to open a local playground using `tree-sitter build-wasm && tree-sitter web-ui` within the
|
||||
parsers repo.
|
||||
- Examples of queries can be found in [queries/](queries/)
|
||||
- Matches in the bottom will override queries that are above of them.
|
||||
- `highlights.scm` used for syntax highlighting,
|
||||
- `injections.scm` used to specify nodes whose content should be parsed as a different language;
|
||||
- `folds.scm`; used to define folds;
|
||||
- `locals.scm`: used to extract keyword definitions, scopes, references, etc. (not used in this plugin).
|
||||
- `indents.scm`; used to control indentation.
|
||||
|
||||
See [tree-sitter queries] for a basic description of the query language. The following tools can be helpful when writing or editing queries:
|
||||
* [ts_query_ls] is a language server for treesitter queries, which can validate, autocomplete, and format. This tool can also be used as an offline linter and formatter (accessible through `make lintquery`, `make checkquery`, `make formatquery` targets).
|
||||
* Neovim's `:InspectTree` will show the parsed tree for a buffer and highlight the text corresponding to any given node (and vice versa).
|
||||
* `:EditQuery` opens a "playground" where you can write query patterns and see which parts of the buffer are captured by each capture.
|
||||
|
||||
>[!IMPORTANT]
|
||||
> The valid captures that can be used in queries is different for each editor, so you cannot just copy them, e.g., from Helix or the parser repositories. For Neovim, all valid captures are listed below. You can verify that your changes adhere to this by running `make lintquery`.
|
||||
|
||||
>[!IMPORTANT]
|
||||
> Since grammars can change constantly, it is important to make sure that the patterns in a query are actually valid for the parser specified in nvim-treesitter's manifest. This can be verified using `make checkquery` (which requires the parser to be installed in the default directory(!) through `nvim-treesitter`). Opening the query in Neovim with the parser installed will also show all invalid patterns, either via [ts_query_ls] or Neovim's builtin query-linter.
|
||||
|
||||
>[!TIP]
|
||||
> Before opening a PR, run `make query` to format, lint, and check all queries.
|
||||
|
||||
#### Inheriting languages
|
||||
|
||||
If your language is an extension of a language (TypeScript is an extension of JavaScript for
|
||||
example), you can include the queries from your base language by adding the following _as the first
|
||||
line of your file_.
|
||||
line of your file_:
|
||||
|
||||
```query
|
||||
; inherits: lang1,(optionallang)
|
||||
|
|
@ -80,205 +106,405 @@ line of your file_.
|
|||
If you want to inherit a language, but don't want the languages inheriting from yours to inherit it,
|
||||
you can mark the language as optional (by putting it between parenthesis).
|
||||
|
||||
#### Formatting
|
||||
|
||||
All queries are expected to follow a standard format, with every node on a single line and indented by two spaces for each level of nesting. You can automatically format the bundled queries by running `make formatquery`.
|
||||
|
||||
Should you need to preserve a specific format for a node, you can exempt it (and all contained nodes) by placing before it
|
||||
```query
|
||||
; format-ignore
|
||||
```
|
||||
|
||||
### Highlights
|
||||
|
||||
As languages differ quite a lot, here is a set of captures available to you when building a `highlights.scm` query. Note that your colorscheme needs to define (or link) these captures as highlight groups.
|
||||
Syntax highlighting is specified in a `highlights.scm` query, which assigns treesitter nodes to captures that can be assigned a highlight group. This feature is implemented in Neovim and documented at [`:h treesitter-highlight`](https://neovim.io/doc/user/treesitter.html#treesitter-highlight).
|
||||
Note that your color scheme needs to define (or link) these captures as highlight groups. You can use Neovim's built-in `:Inspect` function to see exactly which highlight groups are applied at a given position.
|
||||
|
||||
#### Misc
|
||||
The valid captures are listed below.
|
||||
|
||||
```scheme
|
||||
@comment ; line and block comments
|
||||
@comment.documentation ; comments documenting code
|
||||
@error ; syntax/parser errors
|
||||
@none ; completely disable the highlight
|
||||
@preproc ; various preprocessor directives & shebangs
|
||||
@define ; preprocessor definition directives
|
||||
@operator ; symbolic operators (e.g. `+` / `*`)
|
||||
#### Identifiers
|
||||
|
||||
```query
|
||||
@variable ; various variable names
|
||||
@variable.builtin ; built-in variable names (e.g. `this`)
|
||||
@variable.parameter ; parameters of a function
|
||||
@variable.parameter.builtin ; special parameters (e.g. `_`, `it`)
|
||||
@variable.member ; object and struct fields
|
||||
|
||||
@constant ; constant identifiers
|
||||
@constant.builtin ; built-in constant values
|
||||
@constant.macro ; constants defined by the preprocessor
|
||||
|
||||
@module ; modules or namespaces
|
||||
@module.builtin ; built-in modules or namespaces
|
||||
@label ; GOTO and other labels (e.g. `label:` in C), including heredoc labels
|
||||
```
|
||||
|
||||
#### Literals
|
||||
|
||||
```query
|
||||
@string ; string literals
|
||||
@string.documentation ; string documenting code (e.g. Python docstrings)
|
||||
@string.regexp ; regular expressions
|
||||
@string.escape ; escape sequences
|
||||
@string.special ; other special strings (e.g. dates)
|
||||
@string.special.symbol ; symbols or atoms
|
||||
@string.special.url ; URIs (e.g. hyperlinks)
|
||||
@string.special.path ; filenames
|
||||
|
||||
@character ; character literals
|
||||
@character.special ; special characters (e.g. wildcards)
|
||||
|
||||
@boolean ; boolean literals
|
||||
@number ; numeric literals
|
||||
@number.float ; floating-point number literals
|
||||
```
|
||||
|
||||
#### Types
|
||||
|
||||
```query
|
||||
@type ; type or class definitions and annotations
|
||||
@type.builtin ; built-in types
|
||||
@type.definition ; identifiers in type definitions (e.g. `typedef <type> <identifier>` in C)
|
||||
|
||||
@attribute ; attribute annotations (e.g. Python decorators, Rust lifetimes)
|
||||
@attribute.builtin ; builtin annotations (e.g. `@property` in Python)
|
||||
@property ; the key in key/value pairs
|
||||
```
|
||||
|
||||
#### Functions
|
||||
|
||||
```query
|
||||
@function ; function definitions
|
||||
@function.builtin ; built-in functions
|
||||
@function.call ; function calls
|
||||
@function.macro ; preprocessor macros
|
||||
|
||||
@function.method ; method definitions
|
||||
@function.method.call ; method calls
|
||||
|
||||
@constructor ; constructor calls and definitions
|
||||
@operator ; symbolic operators (e.g. `+` / `*`)
|
||||
```
|
||||
|
||||
#### Keywords
|
||||
|
||||
```query
|
||||
@keyword ; keywords not fitting into specific categories
|
||||
@keyword.coroutine ; keywords related to coroutines (e.g. `go` in Go, `async/await` in Python)
|
||||
@keyword.function ; keywords that define a function (e.g. `func` in Go, `def` in Python)
|
||||
@keyword.operator ; operators that are English words (e.g. `and` / `or`)
|
||||
@keyword.import ; keywords for including or exporting modules (e.g. `import` / `from` in Python)
|
||||
@keyword.type ; keywords describing namespaces and composite types (e.g. `struct`, `enum`)
|
||||
@keyword.modifier ; keywords modifying other constructs (e.g. `const`, `static`, `public`)
|
||||
@keyword.repeat ; keywords related to loops (e.g. `for` / `while`)
|
||||
@keyword.return ; keywords like `return` and `yield`
|
||||
@keyword.debug ; keywords related to debugging
|
||||
@keyword.exception ; keywords related to exceptions (e.g. `throw` / `catch`)
|
||||
|
||||
@keyword.conditional ; keywords related to conditionals (e.g. `if` / `else`)
|
||||
@keyword.conditional.ternary ; ternary operator (e.g. `?` / `:`)
|
||||
|
||||
@keyword.directive ; various preprocessor directives & shebangs
|
||||
@keyword.directive.define ; preprocessor definition directives
|
||||
```
|
||||
|
||||
#### Punctuation
|
||||
|
||||
```scheme
|
||||
```query
|
||||
@punctuation.delimiter ; delimiters (e.g. `;` / `.` / `,`)
|
||||
@punctuation.bracket ; brackets (e.g. `()` / `{}` / `[]`)
|
||||
@punctuation.special ; special symbols (e.g. `{}` in string interpolation)
|
||||
```
|
||||
|
||||
#### Literals
|
||||
#### Comments
|
||||
|
||||
```scheme
|
||||
@string ; string literals
|
||||
@string.documentation ; string documenting code (e.g. Python docstrings)
|
||||
@string.regex ; regular expressions
|
||||
@string.escape ; escape sequences
|
||||
@string.special ; other special strings (e.g. dates)
|
||||
```query
|
||||
@comment ; line and block comments
|
||||
@comment.documentation ; comments documenting code
|
||||
|
||||
@character ; character literals
|
||||
@character.special ; special characters (e.g. wildcards)
|
||||
|
||||
@boolean ; boolean literals
|
||||
@number ; numeric literals
|
||||
@float ; floating-point number literals
|
||||
@comment.error ; error-type comments (e.g. `ERROR`, `FIXME`, `DEPRECATED`)
|
||||
@comment.warning ; warning-type comments (e.g. `WARNING`, `FIX`, `HACK`)
|
||||
@comment.todo ; todo-type comments (e.g. `TODO`, `WIP`)
|
||||
@comment.note ; note-type comments (e.g. `NOTE`, `INFO`, `XXX`)
|
||||
```
|
||||
|
||||
#### Functions
|
||||
|
||||
```scheme
|
||||
@function ; function definitions
|
||||
@function.builtin ; built-in functions
|
||||
@function.call ; function calls
|
||||
@function.macro ; preprocessor macros
|
||||
|
||||
@method ; method definitions
|
||||
@method.call ; method calls
|
||||
|
||||
@constructor ; constructor calls and definitions
|
||||
@parameter ; parameters of a function
|
||||
```
|
||||
|
||||
#### Keywords
|
||||
|
||||
```scheme
|
||||
@keyword ; various keywords
|
||||
@keyword.coroutine ; keywords related to coroutines (e.g. `go` in Go, `async/await` in Python)
|
||||
@keyword.function ; keywords that define a function (e.g. `func` in Go, `def` in Python)
|
||||
@keyword.operator ; operators that are English words (e.g. `and` / `or`)
|
||||
@keyword.return ; keywords like `return` and `yield`
|
||||
|
||||
@conditional ; keywords related to conditionals (e.g. `if` / `else`)
|
||||
@conditional.ternary ; ternary operator (e.g. `?` / `:`)
|
||||
|
||||
@repeat ; keywords related to loops (e.g. `for` / `while`)
|
||||
@debug ; keywords related to debugging
|
||||
@label ; GOTO and other labels (e.g. `label:` in C)
|
||||
@include ; keywords for including modules (e.g. `import` / `from` in Python)
|
||||
@exception ; keywords related to exceptions (e.g. `throw` / `catch`)
|
||||
```
|
||||
|
||||
#### Types
|
||||
|
||||
```scheme
|
||||
@type ; type or class definitions and annotations
|
||||
@type.builtin ; built-in types
|
||||
@type.definition ; identifiers in type definitions (e.g. `typedef <type> <identifier>` in C)
|
||||
@type.qualifier ; type qualifiers (e.g. `const`)
|
||||
|
||||
@storageclass ; modifiers that affect storage in memory or life-time
|
||||
@attribute ; attribute annotations (e.g. Python decorators)
|
||||
@field ; object and struct fields
|
||||
@property ; similar to `@field`
|
||||
```
|
||||
|
||||
#### Identifiers
|
||||
|
||||
```scheme
|
||||
@variable ; various variable names
|
||||
@variable.builtin ; built-in variable names (e.g. `this`)
|
||||
|
||||
@constant ; constant identifiers
|
||||
@constant.builtin ; built-in constant values
|
||||
@constant.macro ; constants defined by the preprocessor
|
||||
|
||||
@namespace ; modules or namespaces
|
||||
@symbol ; symbols or atoms
|
||||
```
|
||||
|
||||
#### Text
|
||||
#### Markup
|
||||
|
||||
Mainly for markup languages.
|
||||
|
||||
```scheme
|
||||
@text ; non-structured text
|
||||
@text.strong ; bold text
|
||||
@text.emphasis ; text with emphasis
|
||||
@text.underline ; underlined text
|
||||
@text.strike ; strikethrough text
|
||||
@text.title ; text that is part of a title
|
||||
@text.quote ; text quotations
|
||||
@text.uri ; URIs (e.g. hyperlinks)
|
||||
@text.math ; math environments (e.g. `$ ... $` in LaTeX)
|
||||
@text.environment ; text environments of markup languages
|
||||
@text.environment.name ; text indicating the type of an environment
|
||||
@text.reference ; text references, footnotes, citations, etc.
|
||||
```query
|
||||
@markup.strong ; bold text
|
||||
@markup.italic ; italic text
|
||||
@markup.strikethrough ; struck-through text
|
||||
@markup.underline ; underlined text (only for literal underline markup!)
|
||||
|
||||
@text.literal ; literal or verbatim text (e.g., inline code)
|
||||
@text.literal.block ; literal or verbatim text as a stand-alone block
|
||||
@markup.heading ; headings, titles (including markers)
|
||||
@markup.heading.1 ; top-level heading
|
||||
@markup.heading.2 ; section heading
|
||||
@markup.heading.3 ; subsection heading
|
||||
@markup.heading.4 ; and so on
|
||||
@markup.heading.5 ; and so forth
|
||||
@markup.heading.6 ; six levels ought to be enough for anybody
|
||||
|
||||
@markup.quote ; block quotes
|
||||
@markup.math ; math environments (e.g. `$ ... $` in LaTeX)
|
||||
|
||||
@markup.link ; text references, footnotes, citations, etc.
|
||||
@markup.link.label ; link, reference descriptions
|
||||
@markup.link.url ; URL-style links
|
||||
|
||||
@markup.raw ; literal or verbatim text (e.g. inline code)
|
||||
@markup.raw.block ; literal or verbatim text as a stand-alone block
|
||||
; (use priority 90 for blocks with injections)
|
||||
|
||||
@text.todo ; todo notes
|
||||
@text.note ; info notes
|
||||
@text.warning ; warning notes
|
||||
@text.danger ; danger/error notes
|
||||
|
||||
@text.diff.add ; added text (for diff files)
|
||||
@text.diff.delete ; deleted text (for diff files)
|
||||
@markup.list ; list markers
|
||||
@markup.list.checked ; checked todo-style list markers
|
||||
@markup.list.unchecked ; unchecked todo-style list markers
|
||||
```
|
||||
|
||||
#### Tags
|
||||
|
||||
Used for XML-like tags.
|
||||
|
||||
```scheme
|
||||
@tag ; XML tag names
|
||||
@tag.attribute ; XML tag attributes
|
||||
@tag.delimiter ; XML tag delimiters
|
||||
```query
|
||||
@diff.plus ; added text (for diff files)
|
||||
@diff.minus ; deleted text (for diff files)
|
||||
@diff.delta ; changed text (for diff files)
|
||||
```
|
||||
|
||||
#### Conceal
|
||||
|
||||
```scheme
|
||||
@conceal ; for captures that are only used for concealing
|
||||
```query
|
||||
@tag ; XML-style tag names (and similar)
|
||||
@tag.builtin ; builtin tag names (e.g. HTML5 tags)
|
||||
@tag.attribute ; XML-style tag attributes
|
||||
@tag.delimiter ; XML-style tag delimiters
|
||||
```
|
||||
|
||||
`@conceal` must be followed by `(#set! conceal "")`.
|
||||
#### Non-highlighting captures
|
||||
|
||||
#### Spell
|
||||
```query
|
||||
@conceal ; captures that are only meant to be concealed
|
||||
```
|
||||
|
||||
```scheme
|
||||
>[!TIP]
|
||||
> * See [`:h tree-sitter-highlight-conceal`](https://neovim.io/doc/user/treesitter.html#treesitter-highlight-conceal).
|
||||
> * The capture should be meaningful to allow proper highlighting when `set conceallevel=0`.
|
||||
> * A conceal can be restricted to part of the capture via the [`#offset!` directive](https://neovim.io/doc/user/treesitter.html#treesitter-directive-offset%21).
|
||||
|
||||
```query
|
||||
@spell ; for defining regions to be spellchecked
|
||||
@nospell ; for defining regions that should NOT be spellchecked
|
||||
```
|
||||
|
||||
The main types of nodes which are spell checked are:
|
||||
- Comments
|
||||
- Strings; where it makes sense. Strings that have interpolation or are typically used for non text purposes are not spell checked (e.g. bash).
|
||||
>[!TIP]
|
||||
> The main types of nodes that should be spell checked are
|
||||
> - comments
|
||||
> - strings; where it makes sense. Strings that have interpolation or are typically used for non text purposes are not spell checked (e.g. bash).
|
||||
|
||||
#### Predicates
|
||||
|
||||
Captures can be restricted according to node contents using [predicates](https://neovim.io/doc/user/treesitter.html#treesitter-predicates).
|
||||
|
||||
>[!IMPORTANT]
|
||||
> For performance reasons, prefer earlier predicates in this list:
|
||||
>
|
||||
> 1. `#eq?` (literal match)
|
||||
> 2. `#any-of?` (one of several literal matches)
|
||||
> 3. `#lua-match?` (match against a [Lua pattern](https://neovim.io/doc/user/luaref.html#lua-pattern))
|
||||
> 4. `#match?`/`#vim-match?` (match against a [Vim regular expression](https://neovim.io/doc/user/pattern.html#regexp)
|
||||
|
||||
Besides those provided by Neovim, nvim-treesitter also implements
|
||||
|
||||
```query
|
||||
#kind-eq? ; checks whether a capture corresponds to a given set of nodes
|
||||
#any-kind-eq? ; checks whether any of a list of captures corresponds to a given set of nodes
|
||||
```
|
||||
|
||||
#### Directives
|
||||
|
||||
Nodes contain metadata that can be modified via [directives](https://neovim.io/doc/user/treesitter.html#treesitter-directives).
|
||||
|
||||
#### Priority
|
||||
|
||||
Captures can be assigned a priority to control precedence of highlights via the
|
||||
`#set! "priority" <number>` directive (see `:h treesitter-highlight-priority`).
|
||||
The default priority for treesitter highlights is `100`; queries should only
|
||||
set priorities between `90` and `120`, to avoid conflict with other sources of
|
||||
highlighting (such as diagnostics or LSP semantic tokens).
|
||||
`#set! priority <number>` directive (see [`:h treesitter-highlight-priority`](https://neovim.io/doc/user/treesitter.html#treesitter-highlight-priority)). This is useful for controlling conflicts with injected languages or when inheriting queries from other languages.
|
||||
|
||||
>[!NOTE]
|
||||
> The default priority for treesitter highlights is `100`; queries should only
|
||||
set priorities between `90` and `120`, to avoid conflict with other sources of highlighting (such as diagnostics or LSP semantic tokens).
|
||||
|
||||
>[!TIP]
|
||||
> Precedence is also influenced by pattern order in a query file. If possible, try to achieve the correct result by reordering patterns before resorting to explicit priorities.
|
||||
|
||||
### Injections
|
||||
|
||||
Language injections are controlled by `injections.scm` queries, which specify nodes that should be parsed as a different language. This feature is implemented in Neovim and documented at
|
||||
[`:h treesitter-language-injections](https://neovim.io/doc/user/treesitter.html#treesitter-language-injections).
|
||||
|
||||
The valid captures are:
|
||||
|
||||
```query
|
||||
@injection.language ; dynamic detection of the injection language (i.e. the text of the captured node describes the language)
|
||||
@injection.content ; region for the dynamically detected language
|
||||
@injection.filename ; indicates that the captured node’s text may contain a filename; the corresponding filetype is then looked-up up via vim.filetype.match() and treated as the name of a language that should be used to re-parse the `@injection.content`
|
||||
```
|
||||
|
||||
>[!TIP]
|
||||
> When writing injection queries, try to ensure that each captured node is only matched by a single pattern.
|
||||
|
||||
### Folds
|
||||
|
||||
You can define folds for a given language by adding a `folds.scm` query. This is implemented in Neovim. The only valid capture is `@fold`:
|
||||
|
||||
```query
|
||||
(function_definition) @fold ; fold this node
|
||||
```
|
||||
|
||||
Folds should be given to nodes with defined start and end delimiters/patterns, or to consecutive nodes which are part of the same conceptual "grouping", such as consecutive line comments or import statements. The following items are valid fold candidates:
|
||||
|
||||
- Function/method definitions
|
||||
- Class/interface/trait definitions
|
||||
- Switch/match statements, and individual match arms
|
||||
- Execution blocks (such as those found in conditional statements or loops)
|
||||
- Parameter/argument lists
|
||||
- Array/object/string expressions
|
||||
- Consecutive import statements, consecutive line comments
|
||||
|
||||
The following items would *not* be valid fold candidates:
|
||||
|
||||
- Multiline assignment statements
|
||||
- Multiline property access expressions
|
||||
|
||||
As a rule of thumb, these highlight captures usually reside in or around objects which should be folded:
|
||||
|
||||
- `@function`, `@function.method`
|
||||
- `@keyword.import`, `@keyword.conditional`, `@keyword.repeat`
|
||||
- `@comment`, `@comment.documentation`
|
||||
- `@string`, `@string.documentation`
|
||||
- `@markup.heading.x`, `@markup.list`
|
||||
|
||||
### Indents
|
||||
|
||||
>[!WARNING]
|
||||
> Treesitter-based indentation is still experimental and likely to have breaking changes in the future.
|
||||
|
||||
Indentation for a language is controlled by `indents.scm` queries. The following captures can be used to set the indentation for nodes, either relative or absolute
|
||||
|
||||
* `@indent.begin` specifies that the next line should be indented. Multiple
|
||||
indents on the same line get collapsed, e.g.,
|
||||
```query
|
||||
(
|
||||
(if_statement)
|
||||
(ERROR "else") @indent.begin
|
||||
)
|
||||
```
|
||||
You can also `#set! indent.immediate` to permit the next line to indent even when the block intended to be indented has no content yet. (This can improve interactive typing.)
|
||||
For example for Python,
|
||||
```query
|
||||
((if_statement) @indent.begin
|
||||
(#set! indent.immediate 1))
|
||||
```
|
||||
will allow
|
||||
```python
|
||||
if True:<CR>
|
||||
# Auto indent to here
|
||||
```
|
||||
|
||||
* `@indent.end` is used to specify that the indented region ends and any text subsequent to the capture should be dedented.
|
||||
|
||||
* `@indent.branch` is used to specify that a dedented region starts at the line _including_ the captured nodes.
|
||||
|
||||
* `@indent.dedent` specifies dedenting starting on the _next_ line.
|
||||
|
||||
* `@indent.auto` behaves like Vim's [`autoindent`](https://neovim.io/doc/user/options.html#'autoindent') buffer option (copy whatever the indentation of previous line is when opening a new line after it).
|
||||
|
||||
* `@indent.ignore` specifies that no indent should be added to this node.
|
||||
|
||||
* `@indent.zero` sets the indentation of this node to 0 (i.e., removes _all_ indentation).
|
||||
|
||||
* `@indent.align` can be used to specify blocks that should have the same indentation.
|
||||
This allows
|
||||
```
|
||||
foo(a,
|
||||
b,
|
||||
c)
|
||||
```
|
||||
as well as
|
||||
```
|
||||
foo(
|
||||
a,
|
||||
b,
|
||||
c)
|
||||
```
|
||||
and
|
||||
```
|
||||
foo(
|
||||
a,
|
||||
b,
|
||||
c
|
||||
)
|
||||
```
|
||||
To specify the delimiters to align at, `#set! indent.open_delimiter` and
|
||||
`indent.close_delimiter`, e.g.,
|
||||
```query
|
||||
((argument_list) @indent.align
|
||||
(#set! indent.open_delimiter "(")
|
||||
(#set! indent.close_delimiter ")"))
|
||||
```
|
||||
For some languages, the last line of an `indent.align` block must not be
|
||||
the same indent as the natural next line.
|
||||
For example in Python,
|
||||
|
||||
```python
|
||||
if (a > b and
|
||||
c < d):
|
||||
pass
|
||||
```
|
||||
is not correct, whereas
|
||||
```python
|
||||
if (a > b and
|
||||
c < d):
|
||||
pass
|
||||
```
|
||||
would be correctly indented. This behavior may be selected by setting
|
||||
`indent.avoid_last_matching_next`. For example,
|
||||
```query
|
||||
(if_statement
|
||||
condition: (parenthesized_expression) @indent.align
|
||||
(#set! indent.open_delimiter "(")
|
||||
(#set! indent.close_delimiter ")")
|
||||
(#set! indent.avoid_last_matching_next 1)
|
||||
)
|
||||
```
|
||||
specifies that the last line of an `@indent.align` capture
|
||||
should be additionally indented to avoid clashing with the indent of the first
|
||||
line of the block inside an `if`.
|
||||
|
||||
### Locals
|
||||
|
||||
Note: pay specific attention to the captures here as they are a bit different to
|
||||
those listed in the upstream [Local Variables
|
||||
docs](https://tree-sitter.github.io/tree-sitter/syntax-highlighting#local-variables).
|
||||
Some of these docs didn't exist when `nvim-treesitter` was created and the
|
||||
upstream captures are more limiting than what we have here.
|
||||
Locals are used to keep track of definitions and references in local or global
|
||||
scopes, see [upstream
|
||||
documentation](https://tree-sitter.github.io/tree-sitter/syntax-highlighting#local-variables).
|
||||
Note that nvim-treesitter uses more specific subcaptures for definitions and
|
||||
**does not use locals** (for highlighting or any other purpose). These queries
|
||||
are only provided for limited backwards compatibility.
|
||||
|
||||
```scheme
|
||||
@definition ; various definitions
|
||||
@definition.constant ; constants
|
||||
@definition.function ; functions
|
||||
@definition.method ; methods
|
||||
@definition.var ; variables
|
||||
@definition.parameter ; parameters
|
||||
@definition.macro ; preprocessor macros
|
||||
@definition.type ; types or classes
|
||||
@definition.field ; fields or properties
|
||||
@definition.enum ; enumerations
|
||||
@definition.namespace ; modules or namespaces
|
||||
@definition.import ; imported names
|
||||
@definition.associated ; the associated type of a variable
|
||||
```query
|
||||
@local.definition ; various definitions
|
||||
@local.definition.constant ; constants
|
||||
@local.definition.function ; functions
|
||||
@local.definition.method ; methods
|
||||
@local.definition.var ; variables
|
||||
@local.definition.parameter ; parameters
|
||||
@local.definition.macro ; preprocessor macros
|
||||
@local.definition.type ; types or classes
|
||||
@local.definition.field ; fields or properties
|
||||
@local.definition.enum ; enumerations
|
||||
@local.definition.namespace ; modules or namespaces
|
||||
@local.definition.import ; imported names
|
||||
@local.definition.associated ; the associated type of a variable
|
||||
|
||||
@scope ; scope block
|
||||
@reference ; identifier reference
|
||||
@local.scope ; scope block
|
||||
@local.reference ; identifier reference
|
||||
```
|
||||
|
||||
#### Definition Scope
|
||||
#### Definition scope
|
||||
|
||||
You can set the scope of a definition by setting the `scope` property on the definition.
|
||||
|
||||
|
|
@ -294,8 +520,8 @@ doSomething(); // Should point to the declaration as the definition
|
|||
|
||||
```query
|
||||
(function_declaration
|
||||
((identifier) @definition.var)
|
||||
(#set! "definition.var.scope" "parent"))
|
||||
((identifier) @local.definition.var)
|
||||
(#set! definition.var.scope "parent"))
|
||||
```
|
||||
|
||||
Possible scope values are:
|
||||
|
|
@ -304,57 +530,7 @@ Possible scope values are:
|
|||
- `global`: The definition is valid in the root scope
|
||||
- `local`: The definition is valid in the containing scope. This is the default behavior
|
||||
|
||||
### Folds
|
||||
|
||||
You can define folds for a given language by adding a `folds.scm` query :
|
||||
|
||||
```scheme
|
||||
@fold ; fold this node
|
||||
```
|
||||
|
||||
If the `folds.scm` query is not present, this will fall back to the `@scope` captures in the `locals`
|
||||
query.
|
||||
|
||||
### Injections
|
||||
|
||||
Some captures are related to language injection (like markdown code blocks). They are used in `injections.scm`.
|
||||
|
||||
If you want to dynamically detect the language (e.g. for Markdown blocks) use the `@injection.language` to capture
|
||||
the node describing the language and `@injection.content` to describe the injection region.
|
||||
|
||||
```scheme
|
||||
@injection.language ; dynamic detection of the injection language (i.e. the text of the captured node describes the language)
|
||||
@injection.content ; region for the dynamically detected language
|
||||
```
|
||||
|
||||
For example, to inject javascript into HTML's `<script>` tag
|
||||
|
||||
```html
|
||||
<script>someJsCode();</script>
|
||||
```
|
||||
|
||||
```query
|
||||
(script_element
|
||||
(raw_text) @injection.content
|
||||
(#set! injection.language "javascript")) ; set the parser language for @injection.content region to javascript
|
||||
```
|
||||
|
||||
For regions that don't have a corresponding `@injection.language`, you need to manually set the language
|
||||
through `(#set injection.language "lang_name")`
|
||||
|
||||
To combine all matches of a pattern as one single block of content, add `(#set! injection.combined)` to such pattern
|
||||
|
||||
### Indents
|
||||
|
||||
```scheme
|
||||
@indent.begin ; indent children when matching this node
|
||||
@indent.end ; marks the end of indented block
|
||||
@indent.align ; behaves like python aligned/hanging indent
|
||||
@indent.dedent ; dedent children when matching this node
|
||||
@indent.branch ; dedent itself when matching this node
|
||||
@indent.ignore ; do not indent in this node
|
||||
@indent.auto ; behaves like 'autoindent' buffer option
|
||||
@indent.zero ; sets this node at position 0 (no indent)
|
||||
```
|
||||
|
||||
[Matrix channel]: https://matrix.to/#/#nvim-treesitter:matrix.org
|
||||
[supported languages]: https://github.com/nvim-treesitter/nvim-treesitter/SUPPORTED_LANGUAGES.md
|
||||
[tree-sitter queries]: https://tree-sitter.github.io/tree-sitter/using-parsers/queries/index.html
|
||||
[ts_query_ls]: https://github.com/ribru17/ts_query_ls
|
||||
|
|
|
|||
144
Makefile
144
Makefile
|
|
@ -1,7 +1,139 @@
|
|||
# https://github.com/luarocks/luarocks/wiki/Creating-a-Makefile-that-plays-nice-with-LuaRocks
|
||||
build:
|
||||
echo "Do nothing"
|
||||
NVIM_VERSION ?= nightly
|
||||
|
||||
install:
|
||||
mkdir -p $(INST_LUADIR)
|
||||
cp -r lua/* $(INST_LUADIR)
|
||||
DEPDIR ?= .test-deps
|
||||
CURL ?= curl -sL --create-dirs
|
||||
|
||||
ifeq ($(shell uname -s),Darwin)
|
||||
NVIM_ARCH ?= macos-arm64
|
||||
LUALS_ARCH ?= darwin-arm64
|
||||
STYLUA_ARCH ?= macos-aarch64
|
||||
RUST_ARCH ?= aarch64-apple-darwin
|
||||
else
|
||||
NVIM_ARCH ?= linux-x86_64
|
||||
LUALS_ARCH ?= linux-x64
|
||||
STYLUA_ARCH ?= linux-x86_64
|
||||
RUST_ARCH ?= x86_64-unknown-linux-gnu
|
||||
endif
|
||||
|
||||
.DEFAULT_GOAL := all
|
||||
|
||||
# download test dependencies
|
||||
|
||||
NVIM := $(DEPDIR)/nvim-$(NVIM_ARCH)
|
||||
NVIM_TARBALL := $(NVIM).tar.gz
|
||||
NVIM_URL := https://github.com/neovim/neovim/releases/download/$(NVIM_VERSION)/$(notdir $(NVIM_TARBALL))
|
||||
NVIM_BIN := $(NVIM)/nvim-$(NVIM_ARCH)/bin/nvim
|
||||
NVIM_RUNTIME=$(NVIM)/nvim-$(NVIM_ARCH)/share/nvim/runtime
|
||||
|
||||
.PHONY: nvim
|
||||
nvim: $(NVIM)
|
||||
|
||||
$(NVIM):
|
||||
$(CURL) $(NVIM_URL) -o $(NVIM_TARBALL)
|
||||
mkdir $@
|
||||
tar -xf $(NVIM_TARBALL) -C $@
|
||||
rm -rf $(NVIM_TARBALL)
|
||||
|
||||
EMMYLUALS := $(DEPDIR)/emmylua_check-$(LUALS_ARCH)
|
||||
EMMYLUALS_TARBALL := $(EMMYLUALS).tar.gz
|
||||
EMMYLUALS_URL := https://github.com/emmyluals/emmylua-analyzer-rust/releases/latest/download/$(notdir $(EMMYLUALS_TARBALL))
|
||||
|
||||
.PHONY: emmyluals
|
||||
emmyluals: $(EMMYLUALS)
|
||||
|
||||
$(EMMYLUALS):
|
||||
$(CURL) $(EMMYLUALS_URL) -o $(EMMYLUALS_TARBALL)
|
||||
mkdir $@
|
||||
tar -xf $(EMMYLUALS_TARBALL) -C $@
|
||||
rm -rf $(EMMYLUALS_TARBALL)
|
||||
|
||||
STYLUA := $(DEPDIR)/stylua-$(STYLUA_ARCH)
|
||||
STYLUA_TARBALL := $(STYLUA).zip
|
||||
STYLUA_URL := https://github.com/JohnnyMorganz/StyLua/releases/latest/download/$(notdir $(STYLUA_TARBALL))
|
||||
|
||||
.PHONY: stylua
|
||||
stylua: $(STYLUA)
|
||||
|
||||
$(STYLUA):
|
||||
$(CURL) $(STYLUA_URL) -o $(STYLUA_TARBALL)
|
||||
unzip $(STYLUA_TARBALL) -d $(STYLUA)
|
||||
rm -rf $(STYLUA_TARBALL)
|
||||
|
||||
TSQUERYLS := $(DEPDIR)/ts_query_ls-$(RUST_ARCH)
|
||||
TSQUERYLS_TARBALL := $(TSQUERYLS).tar.gz
|
||||
TSQUERYLS_URL := https://github.com/ribru17/ts_query_ls/releases/latest/download/$(notdir $(TSQUERYLS_TARBALL))
|
||||
|
||||
.PHONY: tsqueryls
|
||||
tsqueryls: $(TSQUERYLS)
|
||||
|
||||
$(TSQUERYLS):
|
||||
$(CURL) $(TSQUERYLS_URL) -o $(TSQUERYLS_TARBALL)
|
||||
mkdir $@
|
||||
tar -xf $(TSQUERYLS_TARBALL) -C $@
|
||||
rm -rf $(TSQUERYLS_TARBALL)
|
||||
|
||||
HLASSERT := $(DEPDIR)/highlight-assertions-$(RUST_ARCH)
|
||||
HLASSERT_TARBALL := $(HLASSERT).tar.gz
|
||||
HLASSERT_URL := https://github.com/nvim-treesitter/highlight-assertions/releases/latest/download/$(notdir $(HLASSERT_TARBALL))
|
||||
|
||||
.PHONY: hlassert
|
||||
hlassert: $(HLASSERT)
|
||||
|
||||
$(HLASSERT):
|
||||
$(CURL) $(HLASSERT_URL) -o $(HLASSERT_TARBALL)
|
||||
mkdir $@
|
||||
tar -xf $(HLASSERT_TARBALL) -C $@
|
||||
rm -rf $(HLASSERT_TARBALL)
|
||||
|
||||
PLENTEST := $(DEPDIR)/plentest.nvim
|
||||
|
||||
.PHONY: plentest
|
||||
plentest: $(PLENTEST)
|
||||
|
||||
$(PLENTEST):
|
||||
git clone --filter=blob:none https://github.com/nvim-treesitter/plentest.nvim $(PLENTEST)
|
||||
|
||||
# actual test targets
|
||||
|
||||
.PHONY: lua
|
||||
lua: formatlua checklua
|
||||
|
||||
.PHONY: formatlua
|
||||
formatlua: $(STYLUA)
|
||||
$(STYLUA)/stylua .
|
||||
|
||||
.PHONY: checklua
|
||||
checklua: $(EMMYLUALS) $(NVIM)
|
||||
VIMRUNTIME=$(NVIM_RUNTIME) $(EMMYLUALS)/emmylua_check --warnings-as-errors .
|
||||
|
||||
.PHONY: query
|
||||
query: formatquery lintquery checkquery
|
||||
|
||||
.PHONY: lintquery
|
||||
lintquery: $(TSQUERYLS)
|
||||
$(TSQUERYLS)/ts_query_ls lint runtime/queries
|
||||
|
||||
.PHONY: formatquery
|
||||
formatquery: $(TSQUERYLS)
|
||||
$(TSQUERYLS)/ts_query_ls format runtime/queries
|
||||
|
||||
.PHONY: checkquery
|
||||
checkquery: $(TSQUERYLS)
|
||||
$(TSQUERYLS)/ts_query_ls check runtime/queries
|
||||
|
||||
.PHONY: docs
|
||||
docs: $(NVIM)
|
||||
$(NVIM_BIN) -l scripts/update-readme.lua
|
||||
|
||||
.PHONY: tests
|
||||
tests: $(NVIM) $(HLASSERT) $(PLENTEST)
|
||||
HLASSERT=$(HLASSERT)/highlight-assertions PLENTEST=$(PLENTEST) \
|
||||
$(NVIM_BIN) --headless --clean -u scripts/minimal_init.lua \
|
||||
-c "lua require('plentest').test_directory('tests/$(TESTS)', { minimal_init = './scripts/minimal_init.lua' })"
|
||||
|
||||
.PHONY: all
|
||||
all: lua query docs tests
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf $(DEPDIR)
|
||||
|
|
|
|||
833
README.md
833
README.md
|
|
@ -1,778 +1,187 @@
|
|||
<div align="center">
|
||||
<h1>nvim-treesitter</h1>
|
||||
<p>
|
||||
<a href="https://matrix.to/#/#nvim-treesitter:matrix.org">
|
||||
<img alt="Matrix Chat" src="https://img.shields.io/matrix/nvim-treesitter:matrix.org" />
|
||||
</a>
|
||||
<a href="https://github.com/nvim-treesitter/nvim-treesitter/actions?query=workflow%3A%22Linting+and+style+checking%22+branch%3Amaster">
|
||||
<img alt="Linting and Style" src="https://github.com/nvim-treesitter/nvim-treesitter/workflows/Linting%20and%20style%20checking/badge.svg" />
|
||||
</a>
|
||||
<a href="https://github.com/nvim-treesitter/nvim-treesitter/actions?query=workflow%3A%22Check+loading+of+syntax+files%22+branch%3Amaster">
|
||||
<img alt="Syntax files" src="https://github.com/nvim-treesitter/nvim-treesitter/workflows/Check%20loading%20of%20syntax%20files/badge.svg" />
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
<h1 align="center">
|
||||
<img src="https://github.com/nvim-treesitter/nvim-treesitter/assets/2361214/0513b223-c902-4f12-92ee-8ac4d8d6f41f" alt="nvim-treesitter">
|
||||
</h1>
|
||||
|
||||
<div align="center">
|
||||
<p>
|
||||
<img src="assets/logo.png" align="center" alt="Logo" />
|
||||
</p>
|
||||
<p>
|
||||
<a href="https://github.com/tree-sitter/tree-sitter">Treesitter</a>
|
||||
configurations and abstraction layer for
|
||||
<a href="https://github.com/neovim/neovim/">Neovim</a>.
|
||||
</p>
|
||||
<p>
|
||||
<i>
|
||||
Logo by <a href="https://github.com/steelsojka">@steelsojka</a>
|
||||
</i>
|
||||
</p>
|
||||
</div>
|
||||
The `nvim-treesitter` plugin provides
|
||||
1. functions for installing, updating, and removing [**tree-sitter parsers**](SUPPORTED_LANGUAGES.md);
|
||||
2. a collection of **queries** for enabling tree-sitter features built into Neovim for these languages;
|
||||
3. a staging ground for [treesitter-based features](#Supported-features) considered for upstreaming to Neovim.
|
||||
|
||||
The goal of `nvim-treesitter` is both to provide a simple and easy way to use the interface for [tree-sitter](https://github.com/tree-sitter/tree-sitter) in Neovim and to provide some basic functionality such as highlighting based on it:
|
||||
For details on these and how to help improving them, see [CONTRIBUTING.md](./CONTRIBUTING.md).
|
||||
|
||||

|
||||
|
||||
Traditional highlighting (left) vs Treesitter-based highlighting (right).
|
||||
More examples can be found in [our gallery](https://github.com/nvim-treesitter/nvim-treesitter/wiki/Gallery).
|
||||
|
||||
**Warning: Treesitter and nvim-treesitter highlighting are an experimental feature of Neovim.
|
||||
Please consider the experience with this plug-in as experimental until Tree-Sitter support in Neovim is stable!
|
||||
We recommend using the nightly builds of Neovim if possible.
|
||||
You can find the current roadmap [here](https://github.com/nvim-treesitter/nvim-treesitter/projects/1).
|
||||
The roadmap and all features of this plugin are open to change, and any suggestion will be highly appreciated!**
|
||||
|
||||
Nvim-treesitter is based on three interlocking features: [**language parsers**](#language-parsers), [**queries**](#adding-queries), and [**modules**](#available-modules), where _modules_ provide features – e.g., highlighting – based on _queries_ for syntax objects extracted from a given buffer by _language parsers_.
|
||||
Users will generally only need to interact with parsers and modules as explained in the next section.
|
||||
For more detailed information on setting these up, see ["Advanced setup"](#advanced-setup).
|
||||
|
||||
---
|
||||
|
||||
### Table of contents
|
||||
|
||||
- [Quickstart](#quickstart)
|
||||
- [Supported languages](#supported-languages)
|
||||
- [Available modules](#available-modules)
|
||||
- [Advanced setup](#advanced-setup)
|
||||
- [Extra features](#extra-features)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
|
||||
---
|
||||
>[!CAUTION]
|
||||
> This is a full, incompatible, rewrite: Treat this as a different plugin you need to set up from scratch following the instructions below. If you can't or don't want to update, specify the [`master` branch](https://github.com/nvim-treesitter/nvim-treesitter/blob/master/README.md) (which is locked but will remain available for backward compatibility with Nvim 0.11).
|
||||
|
||||
# Quickstart
|
||||
|
||||
## Requirements
|
||||
|
||||
- **Neovim 0.9.2** or later ([nightly](https://github.com/neovim/neovim#install-from-source) recommended)
|
||||
- `tar` and `curl` in your path (or alternatively `git`)
|
||||
- A C compiler in your path and libstdc++ installed ([Windows users please read this!](https://github.com/nvim-treesitter/nvim-treesitter/wiki/Windows-support)).
|
||||
- Neovim 0.12.0 or later (nightly)
|
||||
- `tar` and `curl` in your path
|
||||
- [`tree-sitter-cli`](https://github.com/tree-sitter/tree-sitter/blob/master/crates/cli/README.md) (0.26.1 or later, installed via your package manager, **not npm**)
|
||||
- a C compiler in your path (see <https://docs.rs/cc/latest/cc/#compile-time-requirements>)
|
||||
|
||||
>[!IMPORTANT]
|
||||
> The current **support policy** for Neovim is
|
||||
> * the _latest_ [stable release](https://github.com/neovim/neovim/releases/tag/stable),
|
||||
> * the _latest_ [nightly prerelease](https://github.com/neovim/neovim/releases/tag/nightly).
|
||||
> Other versions may work but are neither tested nor considered for fixes.
|
||||
|
||||
## Installation
|
||||
|
||||
You can install `nvim-treesitter` with your favorite package manager (or using the native `package` feature of vim, see `:h packages`).
|
||||
|
||||
**NOTE: This plugin is only guaranteed to work with specific versions of language parsers** (as specified in the `lockfile.json`). **When upgrading the plugin, you must make sure that all installed parsers are updated to the latest version** via `:TSUpdate`.
|
||||
It is strongly recommended to automate this; e.g., if you are using [vim-plug](https://github.com/junegunn/vim-plug), put this in your `init.vim` file:
|
||||
|
||||
```vim
|
||||
Plug 'nvim-treesitter/nvim-treesitter', {'do': ':TSUpdate'}
|
||||
```
|
||||
|
||||
For other plugin managers such as `packer.nvim`, see this [Installation page from the wiki](https://github.com/nvim-treesitter/nvim-treesitter/wiki/Installation) (Note that this page is community maintained).
|
||||
|
||||
## Language parsers
|
||||
|
||||
Treesitter uses a different _parser_ for every language, which needs to be generated via `tree-sitter-cli` from a `grammar.js` file, then compiled to a `.so` library that needs to be placed in neovim's `runtimepath` (typically under `parser/{language}.so`).
|
||||
To simplify this, `nvim-treesitter` provides commands to automate this process.
|
||||
If the language is already [supported by `nvim-treesitter`](#supported-languages), you can install it with
|
||||
|
||||
```vim
|
||||
:TSInstall <language_to_install>
|
||||
```
|
||||
|
||||
This command supports tab expansion.
|
||||
You can also get a list of all available languages and their installation status with `:TSInstallInfo`.
|
||||
Parsers not on this list can be added manually by following the steps described under ["Adding parsers"](#adding-parsers) below.
|
||||
|
||||
To make sure a parser is at the latest compatible version (as specified in `nvim-treesitter`'s `lockfile.json`), use `:TSUpdate {language}`. To update all parsers unconditionally, use `:TSUpdate all` or just `:TSUpdate`.
|
||||
|
||||
## Modules
|
||||
|
||||
Each module provides a distinct tree-sitter-based feature such as [highlighting](#highlight), [indentation](#indentation), or [folding](#folding); see [`:h nvim-treesitter-modules`](doc/nvim-treesitter.txt) or ["Available modules"](#available-modules) below for a list of modules and their options.
|
||||
|
||||
Following examples assume that you are configuring neovim with lua. If you are using vimscript, see `:h lua-heredoc`.
|
||||
All modules are disabled by default and need to be activated explicitly in your `init.lua`, e.g., via
|
||||
This plugin is only guaranteed to work with specific versions of language parsers** (as specified in the `parser.lua` table). **When upgrading the plugin, you must make sure that all installed parsers are updated to the latest version** via `:TSUpdate`.
|
||||
It is strongly recommended to automate this; e.g., using the following spec with [lazy.nvim](https://github.com/folke/lazy.nvim):
|
||||
|
||||
```lua
|
||||
require'nvim-treesitter.configs'.setup {
|
||||
-- A list of parser names, or "all" (the five listed parsers should always be installed)
|
||||
ensure_installed = { "c", "lua", "vim", "vimdoc", "query" },
|
||||
|
||||
-- Install parsers synchronously (only applied to `ensure_installed`)
|
||||
sync_install = false,
|
||||
|
||||
-- Automatically install missing parsers when entering buffer
|
||||
-- Recommendation: set to false if you don't have `tree-sitter` CLI installed locally
|
||||
auto_install = true,
|
||||
|
||||
-- List of parsers to ignore installing (or "all")
|
||||
ignore_install = { "javascript" },
|
||||
|
||||
---- If you need to change the installation directory of the parsers (see -> Advanced Setup)
|
||||
-- parser_install_dir = "/some/path/to/store/parsers", -- Remember to run vim.opt.runtimepath:append("/some/path/to/store/parsers")!
|
||||
|
||||
highlight = {
|
||||
enable = true,
|
||||
|
||||
-- NOTE: these are the names of the parsers and not the filetype. (for example if you want to
|
||||
-- disable highlighting for the `tex` filetype, you need to include `latex` in this list as this is
|
||||
-- the name of the parser)
|
||||
-- list of language that will be disabled
|
||||
disable = { "c", "rust" },
|
||||
-- Or use a function for more flexibility, e.g. to disable slow treesitter highlight for large files
|
||||
disable = function(lang, buf)
|
||||
local max_filesize = 100 * 1024 -- 100 KB
|
||||
local ok, stats = pcall(vim.loop.fs_stat, vim.api.nvim_buf_get_name(buf))
|
||||
if ok and stats and stats.size > max_filesize then
|
||||
return true
|
||||
end
|
||||
end,
|
||||
|
||||
-- Setting this to true will run `:h syntax` and tree-sitter at the same time.
|
||||
-- Set this to `true` if you depend on 'syntax' being enabled (like for indentation).
|
||||
-- Using this option may slow down your editor, and you may see some duplicate highlights.
|
||||
-- Instead of true it can also be a list of languages
|
||||
additional_vim_regex_highlighting = false,
|
||||
},
|
||||
{
|
||||
'nvim-treesitter/nvim-treesitter',
|
||||
lazy = false,
|
||||
build = ':TSUpdate'
|
||||
}
|
||||
```
|
||||
|
||||
Each module can also be enabled or disabled interactively through the following commands:
|
||||
>[!IMPORTANT]
|
||||
> This plugin does not support lazy-loading.
|
||||
|
||||
```vim
|
||||
:TSBufEnable {module} " enable module on current buffer
|
||||
:TSBufDisable {module} " disable module on current buffer
|
||||
:TSEnable {module} [{ft}] " enable module on every buffer. If filetype is specified, enable only for this filetype.
|
||||
:TSDisable {module} [{ft}] " disable module on every buffer. If filetype is specified, disable only for this filetype.
|
||||
:TSModuleInfo [{module}] " list information about modules state for each filetype
|
||||
## Setup
|
||||
|
||||
`nvim-treesitter` can be configured by calling `setup`. **You do not need to call `setup` for `nvim-treesitter` to work using default values.**
|
||||
|
||||
```lua
|
||||
require('nvim-treesitter').setup {
|
||||
-- Directory to install parsers and queries to (prepended to `runtimepath` to have priority)
|
||||
install_dir = vim.fn.stdpath('data') .. '/site'
|
||||
}
|
||||
```
|
||||
|
||||
Parsers and queries can then be installed with
|
||||
|
||||
```lua
|
||||
require('nvim-treesitter').install { 'rust', 'javascript', 'zig' }
|
||||
```
|
||||
|
||||
(This is a no-op if the parsers are already installed.) Note that this function runs asynchronously; for synchronous installation in a script context ("bootstrapping"), you need to `wait()` for it to finish:
|
||||
|
||||
```lua
|
||||
require('nvim-treesitter').install({ 'rust', 'javascript', 'zig' }):wait(300000) -- wait max. 5 minutes
|
||||
```
|
||||
|
||||
Check [`:h nvim-treesitter-commands`](doc/nvim-treesitter.txt) for a list of all available commands.
|
||||
It may be necessary to reload the buffer (e.g., via `:e`) after enabling a module interactively.
|
||||
|
||||
# Supported languages
|
||||
|
||||
For `nvim-treesitter` to support a specific feature for a specific language requires both a parser for that language and an appropriate language-specific query file for that feature.
|
||||
|
||||
The following is a list of languages for which a parser can be installed through `:TSInstall`; a checked box means that `nvim-treesitter` also contains queries at least for the `highlight` module.
|
||||
A list of the currently supported languages can be found [on this page](SUPPORTED_LANGUAGES.md). If you wish to add a new language or improve the queries for an existing one, please see our [contributing guide](CONTRIBUTING.md).
|
||||
|
||||
Experimental parsers are parsers that have a maintainer but are not stable enough for
|
||||
daily use yet.
|
||||
# Supported features
|
||||
|
||||
We are looking for maintainers to add more parsers and to write query files for their languages. Check our [tracking issue](https://github.com/nvim-treesitter/nvim-treesitter/issues/2282) for open language requests.
|
||||
`nvim-treesitter` provides queries for the following features. **These are not automatically enabled.**
|
||||
|
||||
<!--This section of the README is automatically updated by a CI job-->
|
||||
<!--parserinfo-->
|
||||
- [x] [ada](https://github.com/briot/tree-sitter-ada) (maintained by @briot)
|
||||
- [x] [agda](https://github.com/tree-sitter/tree-sitter-agda) (maintained by @Decodetalkers)
|
||||
- [ ] [angular](https://github.com/steelsojka/tree-sitter-angular) (experimental)
|
||||
- [x] [apex](https://github.com/aheber/tree-sitter-sfapex) (maintained by @aheber)
|
||||
- [x] [arduino](https://github.com/ObserverOfTime/tree-sitter-arduino) (maintained by @ObserverOfTime)
|
||||
- [x] [astro](https://github.com/virchau13/tree-sitter-astro) (maintained by @virchau13)
|
||||
- [x] [authzed](https://github.com/mleonidas/tree-sitter-authzed) (maintained by @mattpolzin)
|
||||
- [ ] [awk](https://github.com/Beaglefoot/tree-sitter-awk)
|
||||
- [x] [bash](https://github.com/tree-sitter/tree-sitter-bash) (maintained by @TravonteD)
|
||||
- [x] [bass](https://github.com/amaanq/tree-sitter-bass) (maintained by @amaanq)
|
||||
- [x] [beancount](https://github.com/polarmutex/tree-sitter-beancount) (maintained by @polarmutex)
|
||||
- [x] [bibtex](https://github.com/latex-lsp/tree-sitter-bibtex) (maintained by @theHamsta, @clason)
|
||||
- [x] [bicep](https://github.com/amaanq/tree-sitter-bicep) (maintained by @amaanq)
|
||||
- [x] [bitbake](https://github.com/amaanq/tree-sitter-bitbake) (maintained by @amaanq)
|
||||
- [x] [blueprint](https://gitlab.com/gabmus/tree-sitter-blueprint.git) (experimental, maintained by @gabmus)
|
||||
- [x] [c](https://github.com/tree-sitter/tree-sitter-c) (maintained by @amaanq)
|
||||
- [x] [c_sharp](https://github.com/tree-sitter/tree-sitter-c-sharp) (maintained by @Luxed)
|
||||
- [x] [cairo](https://github.com/amaanq/tree-sitter-cairo) (maintained by @amaanq)
|
||||
- [x] [capnp](https://github.com/amaanq/tree-sitter-capnp) (maintained by @amaanq)
|
||||
- [x] [chatito](https://github.com/ObserverOfTime/tree-sitter-chatito) (maintained by @ObserverOfTime)
|
||||
- [x] [clojure](https://github.com/sogaiu/tree-sitter-clojure) (maintained by @NoahTheDuke)
|
||||
- [x] [cmake](https://github.com/uyha/tree-sitter-cmake) (maintained by @uyha)
|
||||
- [x] [comment](https://github.com/stsewd/tree-sitter-comment) (maintained by @stsewd)
|
||||
- [x] [commonlisp](https://github.com/theHamsta/tree-sitter-commonlisp) (maintained by @theHamsta)
|
||||
- [x] [cooklang](https://github.com/addcninblue/tree-sitter-cooklang) (maintained by @addcninblue)
|
||||
- [x] [corn](https://github.com/jakestanger/tree-sitter-corn) (maintained by @jakestanger)
|
||||
- [x] [cpon](https://github.com/amaanq/tree-sitter-cpon) (maintained by @amaanq)
|
||||
- [x] [cpp](https://github.com/tree-sitter/tree-sitter-cpp) (maintained by @theHamsta)
|
||||
- [x] [css](https://github.com/tree-sitter/tree-sitter-css) (maintained by @TravonteD)
|
||||
- [x] [csv](https://github.com/amaanq/tree-sitter-csv) (maintained by @amaanq)
|
||||
- [x] [cuda](https://github.com/theHamsta/tree-sitter-cuda) (maintained by @theHamsta)
|
||||
- [x] [cue](https://github.com/eonpatapon/tree-sitter-cue) (maintained by @amaanq)
|
||||
- [x] [d](https://github.com/CyberShadow/tree-sitter-d) (experimental, maintained by @nawordar)
|
||||
- [x] [dart](https://github.com/UserNobody14/tree-sitter-dart) (maintained by @akinsho)
|
||||
- [x] [devicetree](https://github.com/joelspadin/tree-sitter-devicetree) (maintained by @jedrzejboczar)
|
||||
- [x] [dhall](https://github.com/jbellerb/tree-sitter-dhall) (maintained by @amaanq)
|
||||
- [x] [diff](https://github.com/the-mikedavis/tree-sitter-diff) (maintained by @gbprod)
|
||||
- [x] [dockerfile](https://github.com/camdencheek/tree-sitter-dockerfile) (maintained by @camdencheek)
|
||||
- [x] [dot](https://github.com/rydesun/tree-sitter-dot) (maintained by @rydesun)
|
||||
- [x] [doxygen](https://github.com/amaanq/tree-sitter-doxygen) (maintained by @amaanq)
|
||||
- [x] [dtd](https://github.com/ObserverOfTime/tree-sitter-xml) (maintained by @ObserverOfTime)
|
||||
- [x] [ebnf](https://github.com/RubixDev/ebnf) (experimental, maintained by @RubixDev)
|
||||
- [x] [eds](https://github.com/uyha/tree-sitter-eds) (maintained by @uyha)
|
||||
- [x] [eex](https://github.com/connorlay/tree-sitter-eex) (maintained by @connorlay)
|
||||
- [x] [elixir](https://github.com/elixir-lang/tree-sitter-elixir) (maintained by @connorlay)
|
||||
- [x] [elm](https://github.com/elm-tooling/tree-sitter-elm) (maintained by @zweimach)
|
||||
- [x] [elsa](https://github.com/glapa-grossklag/tree-sitter-elsa) (maintained by @glapa-grossklag, @amaanq)
|
||||
- [x] [elvish](https://github.com/elves/tree-sitter-elvish) (maintained by @elves)
|
||||
- [ ] [embedded_template](https://github.com/tree-sitter/tree-sitter-embedded-template)
|
||||
- [x] [erlang](https://github.com/WhatsApp/tree-sitter-erlang) (maintained by @filmor)
|
||||
- [x] [facility](https://github.com/FacilityApi/tree-sitter-facility) (maintained by @bryankenote)
|
||||
- [x] [fennel](https://github.com/travonted/tree-sitter-fennel) (maintained by @TravonteD)
|
||||
- [x] [firrtl](https://github.com/amaanq/tree-sitter-firrtl) (maintained by @amaanq)
|
||||
- [x] [fish](https://github.com/ram02z/tree-sitter-fish) (maintained by @ram02z)
|
||||
- [x] [foam](https://github.com/FoamScience/tree-sitter-foam) (experimental, maintained by @FoamScience)
|
||||
- [x] [forth](https://github.com/AlexanderBrevig/tree-sitter-forth) (maintained by @amaanq)
|
||||
- [x] [fortran](https://github.com/stadelmanma/tree-sitter-fortran) (maintained by @amaanq)
|
||||
- [x] [fsh](https://github.com/mgramigna/tree-sitter-fsh) (maintained by @mgramigna)
|
||||
- [x] [func](https://github.com/amaanq/tree-sitter-func) (maintained by @amaanq)
|
||||
- [x] [fusion](https://gitlab.com/jirgn/tree-sitter-fusion.git) (maintained by @jirgn)
|
||||
- [x] [Godot (gdscript)](https://github.com/PrestonKnopp/tree-sitter-gdscript) (maintained by @PrestonKnopp)
|
||||
- [x] [git_config](https://github.com/the-mikedavis/tree-sitter-git-config) (maintained by @amaanq)
|
||||
- [x] [git_rebase](https://github.com/the-mikedavis/tree-sitter-git-rebase) (maintained by @gbprod)
|
||||
- [x] [gitattributes](https://github.com/ObserverOfTime/tree-sitter-gitattributes) (maintained by @ObserverOfTime)
|
||||
- [x] [gitcommit](https://github.com/gbprod/tree-sitter-gitcommit) (maintained by @gbprod)
|
||||
- [x] [gitignore](https://github.com/shunsambongi/tree-sitter-gitignore) (maintained by @theHamsta)
|
||||
- [x] [gleam](https://github.com/gleam-lang/tree-sitter-gleam) (maintained by @amaanq)
|
||||
- [x] [Glimmer and Ember](https://github.com/alexlafroscia/tree-sitter-glimmer) (maintained by @NullVoxPopuli)
|
||||
- [x] [glsl](https://github.com/theHamsta/tree-sitter-glsl) (maintained by @theHamsta)
|
||||
- [x] [GN (Generate Ninja)](https://github.com/amaanq/tree-sitter-gn) (maintained by @amaanq)
|
||||
- [x] [go](https://github.com/tree-sitter/tree-sitter-go) (maintained by @theHamsta, @WinWisely268)
|
||||
- [x] [Godot Resources (gdresource)](https://github.com/PrestonKnopp/tree-sitter-godot-resource) (maintained by @pierpo)
|
||||
- [x] [gomod](https://github.com/camdencheek/tree-sitter-go-mod) (maintained by @camdencheek)
|
||||
- [x] [gosum](https://github.com/amaanq/tree-sitter-go-sum) (maintained by @amaanq)
|
||||
- [x] [gowork](https://github.com/omertuc/tree-sitter-go-work) (maintained by @omertuc)
|
||||
- [x] [gpg](https://github.com/ObserverOfTime/tree-sitter-gpg-config) (maintained by @ObserverOfTime)
|
||||
- [x] [graphql](https://github.com/bkegley/tree-sitter-graphql) (maintained by @bkegley)
|
||||
- [x] [groovy](https://github.com/Decodetalkers/tree-sitter-groovy) (maintained by @Decodetalkers)
|
||||
- [x] [gstlaunch](https://github.com/theHamsta/tree-sitter-gstlaunch) (maintained by @theHamsta)
|
||||
- [ ] [hack](https://github.com/slackhq/tree-sitter-hack)
|
||||
- [x] [hare](https://github.com/amaanq/tree-sitter-hare) (maintained by @amaanq)
|
||||
- [x] [haskell](https://github.com/tree-sitter/tree-sitter-haskell) (maintained by @mrcjkb)
|
||||
- [x] [haskell_persistent](https://github.com/MercuryTechnologies/tree-sitter-haskell-persistent) (maintained by @lykahb)
|
||||
- [x] [hcl](https://github.com/MichaHoffmann/tree-sitter-hcl) (maintained by @MichaHoffmann)
|
||||
- [x] [heex](https://github.com/connorlay/tree-sitter-heex) (maintained by @connorlay)
|
||||
- [x] [hjson](https://github.com/winston0410/tree-sitter-hjson) (maintained by @winston0410)
|
||||
- [x] [hlsl](https://github.com/theHamsta/tree-sitter-hlsl) (maintained by @theHamsta)
|
||||
- [x] [hocon](https://github.com/antosha417/tree-sitter-hocon) (maintained by @antosha417)
|
||||
- [x] [hoon](https://github.com/urbit-pilled/tree-sitter-hoon) (experimental, maintained by @urbit-pilled)
|
||||
- [x] [html](https://github.com/tree-sitter/tree-sitter-html) (maintained by @TravonteD)
|
||||
- [x] [htmldjango](https://github.com/interdependence/tree-sitter-htmldjango) (experimental, maintained by @ObserverOfTime)
|
||||
- [x] [http](https://github.com/rest-nvim/tree-sitter-http) (maintained by @amaanq)
|
||||
- [x] [hurl](https://github.com/pfeiferj/tree-sitter-hurl) (maintained by @pfeiferj)
|
||||
- [x] [ini](https://github.com/justinmk/tree-sitter-ini) (experimental, maintained by @theHamsta)
|
||||
- [x] [ispc](https://github.com/fab4100/tree-sitter-ispc) (maintained by @fab4100)
|
||||
- [x] [janet_simple](https://github.com/sogaiu/tree-sitter-janet-simple) (maintained by @sogaiu)
|
||||
- [x] [java](https://github.com/tree-sitter/tree-sitter-java) (maintained by @p00f)
|
||||
- [x] [javascript](https://github.com/tree-sitter/tree-sitter-javascript) (maintained by @steelsojka)
|
||||
- [x] [jq](https://github.com/flurie/tree-sitter-jq) (maintained by @ObserverOfTime)
|
||||
- [x] [jsdoc](https://github.com/tree-sitter/tree-sitter-jsdoc) (maintained by @steelsojka)
|
||||
- [x] [json](https://github.com/tree-sitter/tree-sitter-json) (maintained by @steelsojka)
|
||||
- [x] [json5](https://github.com/Joakker/tree-sitter-json5) (maintained by @Joakker)
|
||||
- [x] [JSON with comments](https://gitlab.com/WhyNotHugo/tree-sitter-jsonc.git) (maintained by @WhyNotHugo)
|
||||
- [x] [jsonnet](https://github.com/sourcegraph/tree-sitter-jsonnet) (maintained by @nawordar)
|
||||
- [x] [julia](https://github.com/tree-sitter/tree-sitter-julia) (maintained by @theHamsta)
|
||||
- [x] [kconfig](https://github.com/amaanq/tree-sitter-kconfig) (maintained by @amaanq)
|
||||
- [x] [kdl](https://github.com/amaanq/tree-sitter-kdl) (maintained by @amaanq)
|
||||
- [x] [kotlin](https://github.com/fwcd/tree-sitter-kotlin) (maintained by @SalBakraa)
|
||||
- [x] [kusto](https://github.com/Willem-J-an/tree-sitter-kusto) (maintained by @Willem-J-an)
|
||||
- [x] [lalrpop](https://github.com/traxys/tree-sitter-lalrpop) (maintained by @traxys)
|
||||
- [x] [latex](https://github.com/latex-lsp/tree-sitter-latex) (maintained by @theHamsta, @clason)
|
||||
- [x] [ledger](https://github.com/cbarrete/tree-sitter-ledger) (maintained by @cbarrete)
|
||||
- [x] [leo](https://github.com/r001/tree-sitter-leo) (maintained by @r001)
|
||||
- [x] [linkerscript](https://github.com/amaanq/tree-sitter-linkerscript) (maintained by @amaanq)
|
||||
- [x] [liquidsoap](https://github.com/savonet/tree-sitter-liquidsoap) (maintained by @toots)
|
||||
- [x] [llvm](https://github.com/benwilliamgraham/tree-sitter-llvm) (maintained by @benwilliamgraham)
|
||||
- [x] [lua](https://github.com/MunifTanjim/tree-sitter-lua) (maintained by @muniftanjim)
|
||||
- [x] [luadoc](https://github.com/amaanq/tree-sitter-luadoc) (maintained by @amaanq)
|
||||
- [x] [lua patterns](https://github.com/amaanq/tree-sitter-luap) (maintained by @amaanq)
|
||||
- [x] [luau](https://github.com/amaanq/tree-sitter-luau) (maintained by @amaanq)
|
||||
- [x] [m68k](https://github.com/grahambates/tree-sitter-m68k) (maintained by @grahambates)
|
||||
- [x] [make](https://github.com/alemuller/tree-sitter-make) (maintained by @lewis6991)
|
||||
- [x] [markdown (basic highlighting)](https://github.com/MDeiml/tree-sitter-markdown) (experimental, maintained by @MDeiml)
|
||||
- [x] [markdown_inline (needed for full highlighting)](https://github.com/MDeiml/tree-sitter-markdown) (experimental, maintained by @MDeiml)
|
||||
- [x] [matlab](https://github.com/acristoffers/tree-sitter-matlab) (maintained by @acristoffers)
|
||||
- [x] [menhir](https://github.com/Kerl13/tree-sitter-menhir) (maintained by @Kerl13)
|
||||
- [ ] [mermaid](https://github.com/monaqa/tree-sitter-mermaid) (experimental)
|
||||
- [x] [meson](https://github.com/Decodetalkers/tree-sitter-meson) (maintained by @Decodetalkers)
|
||||
- [x] [mlir](https://github.com/artagnon/tree-sitter-mlir) (experimental, maintained by @artagnon)
|
||||
- [x] [nasm](https://github.com/naclsn/tree-sitter-nasm) (maintained by @ObserverOfTime)
|
||||
- [ ] [nickel](https://github.com/nickel-lang/tree-sitter-nickel)
|
||||
- [x] [nim](https://github.com/alaviss/tree-sitter-nim) (maintained by @aMOPel)
|
||||
- [x] [nim_format_string](https://github.com/aMOPel/tree-sitter-nim-format-string) (maintained by @aMOPel)
|
||||
- [x] [ninja](https://github.com/alemuller/tree-sitter-ninja) (maintained by @alemuller)
|
||||
- [x] [nix](https://github.com/cstrahan/tree-sitter-nix) (maintained by @leo60228)
|
||||
- [x] [norg](https://github.com/nvim-neorg/tree-sitter-norg) (maintained by @JoeyGrajciar, @vhyrro)
|
||||
- [x] [nqc](https://github.com/amaanq/tree-sitter-nqc) (maintained by @amaanq)
|
||||
- [x] [objc](https://github.com/amaanq/tree-sitter-objc) (maintained by @amaanq)
|
||||
- [x] [objdump](https://github.com/ColinKennedy/tree-sitter-objdump) (maintained by @ColinKennedy)
|
||||
- [x] [ocaml](https://github.com/tree-sitter/tree-sitter-ocaml) (maintained by @undu)
|
||||
- [x] [ocaml_interface](https://github.com/tree-sitter/tree-sitter-ocaml) (maintained by @undu)
|
||||
- [x] [ocamllex](https://github.com/atom-ocaml/tree-sitter-ocamllex) (maintained by @undu)
|
||||
- [x] [odin](https://github.com/amaanq/tree-sitter-odin) (maintained by @amaanq)
|
||||
- [ ] [org](https://github.com/milisims/tree-sitter-org)
|
||||
- [x] [pascal](https://github.com/Isopod/tree-sitter-pascal.git) (maintained by @Isopod)
|
||||
- [x] [passwd](https://github.com/ath3/tree-sitter-passwd) (maintained by @amaanq)
|
||||
- [x] [pem](https://github.com/ObserverOfTime/tree-sitter-pem) (maintained by @ObserverOfTime)
|
||||
- [x] [perl](https://github.com/tree-sitter-perl/tree-sitter-perl) (maintained by @RabbiVeesh, @LeoNerd)
|
||||
- [x] [php](https://github.com/tree-sitter/tree-sitter-php) (maintained by @tk-shirasaka)
|
||||
- [x] [phpdoc](https://github.com/claytonrcarter/tree-sitter-phpdoc) (experimental, maintained by @mikehaertl)
|
||||
- [x] [pioasm](https://github.com/leo60228/tree-sitter-pioasm) (maintained by @leo60228)
|
||||
- [x] [po](https://github.com/erasin/tree-sitter-po) (maintained by @amaanq)
|
||||
- [x] [pod](https://github.com/tree-sitter-perl/tree-sitter-pod) (maintained by @RabbiVeesh, @LeoNerd)
|
||||
- [x] [Path of Exile item filter](https://github.com/ObserverOfTime/tree-sitter-poe-filter) (experimental, maintained by @ObserverOfTime)
|
||||
- [x] [pony](https://github.com/amaanq/tree-sitter-pony) (maintained by @amaanq, @mfelsche)
|
||||
- [x] [prisma](https://github.com/victorhqc/tree-sitter-prisma) (maintained by @elianiva)
|
||||
- [x] [promql](https://github.com/MichaHoffmann/tree-sitter-promql) (maintained by @MichaHoffmann)
|
||||
- [x] [properties](https://github.com/ObserverOfTime/tree-sitter-properties) (maintained by @ObserverOfTime)
|
||||
- [x] [proto](https://github.com/treywood/tree-sitter-proto) (maintained by @treywood)
|
||||
- [x] [prql](https://github.com/PRQL/tree-sitter-prql) (maintained by @matthias-Q)
|
||||
- [x] [psv](https://github.com/amaanq/tree-sitter-csv) (maintained by @amaanq)
|
||||
- [x] [pug](https://github.com/zealot128/tree-sitter-pug) (experimental, maintained by @zealot128)
|
||||
- [x] [puppet](https://github.com/amaanq/tree-sitter-puppet) (maintained by @amaanq)
|
||||
- [x] [purescript](https://github.com/postsolar/tree-sitter-purescript) (maintained by @postsolar)
|
||||
- [x] [PyPA manifest](https://github.com/ObserverOfTime/tree-sitter-pymanifest) (maintained by @ObserverOfTime)
|
||||
- [x] [python](https://github.com/tree-sitter/tree-sitter-python) (maintained by @stsewd, @theHamsta)
|
||||
- [x] [ql](https://github.com/tree-sitter/tree-sitter-ql) (maintained by @pwntester)
|
||||
- [x] [qmldir](https://github.com/Decodetalkers/tree-sitter-qmldir) (maintained by @amaanq)
|
||||
- [x] [qmljs](https://github.com/yuja/tree-sitter-qmljs) (maintained by @Decodetalkers)
|
||||
- [x] [Tree-Sitter query language](https://github.com/nvim-treesitter/tree-sitter-query) (maintained by @steelsojka)
|
||||
- [x] [r](https://github.com/r-lib/tree-sitter-r) (maintained by @echasnovski)
|
||||
- [ ] [racket](https://github.com/6cdh/tree-sitter-racket)
|
||||
- [x] [rasi](https://github.com/Fymyte/tree-sitter-rasi) (maintained by @Fymyte)
|
||||
- [x] [rbs](https://github.com/joker1007/tree-sitter-rbs) (maintained by @joker1007)
|
||||
- [x] [re2c](https://github.com/amaanq/tree-sitter-re2c) (maintained by @amaanq)
|
||||
- [x] [regex](https://github.com/tree-sitter/tree-sitter-regex) (maintained by @theHamsta)
|
||||
- [x] [rego](https://github.com/FallenAngel97/tree-sitter-rego) (maintained by @FallenAngel97)
|
||||
- [x] [pip requirements](https://github.com/ObserverOfTime/tree-sitter-requirements) (maintained by @ObserverOfTime)
|
||||
- [x] [rnoweb](https://github.com/bamonroe/tree-sitter-rnoweb) (maintained by @bamonroe)
|
||||
- [x] [robot](https://github.com/Hubro/tree-sitter-robot) (maintained by @Hubro)
|
||||
- [x] [ron](https://github.com/amaanq/tree-sitter-ron) (maintained by @amaanq)
|
||||
- [x] [rst](https://github.com/stsewd/tree-sitter-rst) (maintained by @stsewd)
|
||||
- [x] [ruby](https://github.com/tree-sitter/tree-sitter-ruby) (maintained by @TravonteD)
|
||||
- [x] [rust](https://github.com/tree-sitter/tree-sitter-rust) (maintained by @amaanq)
|
||||
- [x] [scala](https://github.com/tree-sitter/tree-sitter-scala) (maintained by @stevanmilic)
|
||||
- [x] [scfg](https://git.sr.ht/~rockorager/tree-sitter-scfg) (maintained by @WhyNotHugo)
|
||||
- [ ] [scheme](https://github.com/6cdh/tree-sitter-scheme)
|
||||
- [x] [scss](https://github.com/serenadeai/tree-sitter-scss) (maintained by @elianiva)
|
||||
- [x] [slang](https://github.com/theHamsta/tree-sitter-slang) (experimental, maintained by @theHamsta)
|
||||
- [x] [slint](https://github.com/jrmoulton/tree-sitter-slint) (experimental, maintained by @jrmoulton)
|
||||
- [x] [smali](https://git.sr.ht/~yotam/tree-sitter-smali) (maintained by @amaanq)
|
||||
- [x] [smithy](https://github.com/indoorvivants/tree-sitter-smithy) (maintained by @amaanq, @keynmol)
|
||||
- [ ] [snakemake](https://github.com/osthomas/tree-sitter-snakemake) (experimental)
|
||||
- [x] [solidity](https://github.com/JoranHonig/tree-sitter-solidity) (maintained by @amaanq)
|
||||
- [x] [soql](https://github.com/aheber/tree-sitter-sfapex) (maintained by @aheber)
|
||||
- [x] [sosl](https://github.com/aheber/tree-sitter-sfapex) (maintained by @aheber)
|
||||
- [x] [sparql](https://github.com/BonaBeavis/tree-sitter-sparql) (maintained by @BonaBeavis)
|
||||
- [x] [sql](https://github.com/derekstride/tree-sitter-sql) (maintained by @derekstride)
|
||||
- [x] [squirrel](https://github.com/amaanq/tree-sitter-squirrel) (maintained by @amaanq)
|
||||
- [x] [ssh_config](https://github.com/ObserverOfTime/tree-sitter-ssh-config) (maintained by @ObserverOfTime)
|
||||
- [x] [starlark](https://github.com/amaanq/tree-sitter-starlark) (maintained by @amaanq)
|
||||
- [x] [strace](https://github.com/sigmaSd/tree-sitter-strace) (maintained by @amaanq)
|
||||
- [x] [styled](https://github.com/mskelton/tree-sitter-styled) (maintained by @mskelton)
|
||||
- [x] [supercollider](https://github.com/madskjeldgaard/tree-sitter-supercollider) (maintained by @madskjeldgaard)
|
||||
- [x] [surface](https://github.com/connorlay/tree-sitter-surface) (maintained by @connorlay)
|
||||
- [x] [svelte](https://github.com/Himujjal/tree-sitter-svelte) (maintained by @elianiva)
|
||||
- [x] [swift](https://github.com/alex-pinkus/tree-sitter-swift) (maintained by @alex-pinkus)
|
||||
- [x] [sxhkdrc](https://github.com/RaafatTurki/tree-sitter-sxhkdrc) (maintained by @RaafatTurki)
|
||||
- [x] [systemtap](https://github.com/ok-ryoko/tree-sitter-systemtap) (maintained by @ok-ryoko)
|
||||
- [x] [t32](https://gitlab.com/xasc/tree-sitter-t32.git) (maintained by @xasc)
|
||||
- [x] [tablegen](https://github.com/amaanq/tree-sitter-tablegen) (maintained by @amaanq)
|
||||
- [x] [teal](https://github.com/euclidianAce/tree-sitter-teal) (maintained by @euclidianAce)
|
||||
- [x] [templ](https://github.com/vrischmann/tree-sitter-templ) (maintained by @vrischmann)
|
||||
- [x] [terraform](https://github.com/MichaHoffmann/tree-sitter-hcl) (maintained by @MichaHoffmann)
|
||||
- [x] [textproto](https://github.com/PorterAtGoogle/tree-sitter-textproto) (maintained by @Porter)
|
||||
- [x] [thrift](https://github.com/duskmoon314/tree-sitter-thrift) (maintained by @amaanq, @duskmoon314)
|
||||
- [x] [tiger](https://github.com/ambroisie/tree-sitter-tiger) (maintained by @ambroisie)
|
||||
- [x] [tlaplus](https://github.com/tlaplus-community/tree-sitter-tlaplus) (maintained by @ahelwer, @susliko)
|
||||
- [x] [todotxt](https://github.com/arnarg/tree-sitter-todotxt.git) (experimental, maintained by @arnarg)
|
||||
- [x] [toml](https://github.com/ikatyang/tree-sitter-toml) (maintained by @tk-shirasaka)
|
||||
- [x] [tsv](https://github.com/amaanq/tree-sitter-csv) (maintained by @amaanq)
|
||||
- [x] [tsx](https://github.com/tree-sitter/tree-sitter-typescript) (maintained by @steelsojka)
|
||||
- [x] [turtle](https://github.com/BonaBeavis/tree-sitter-turtle) (maintained by @BonaBeavis)
|
||||
- [x] [twig](https://github.com/gbprod/tree-sitter-twig) (maintained by @gbprod)
|
||||
- [x] [typescript](https://github.com/tree-sitter/tree-sitter-typescript) (maintained by @steelsojka)
|
||||
- [x] [typoscript](https://github.com/Teddytrombone/tree-sitter-typoscript) (maintained by @Teddytrombone)
|
||||
- [x] [udev](https://github.com/ObserverOfTime/tree-sitter-udev) (maintained by @ObserverOfTime)
|
||||
- [x] [ungrammar](https://github.com/Philipp-M/tree-sitter-ungrammar) (maintained by @Philipp-M, @amaanq)
|
||||
- [x] [unison](https://github.com/kylegoetz/tree-sitter-unison) (maintained by @tapegram)
|
||||
- [x] [usd](https://github.com/ColinKennedy/tree-sitter-usd) (maintained by @ColinKennedy)
|
||||
- [x] [uxn tal](https://github.com/amaanq/tree-sitter-uxntal) (maintained by @amaanq)
|
||||
- [x] [v](https://github.com/v-analyzer/v-analyzer) (maintained by @kkharji, @amaanq)
|
||||
- [x] [vala](https://github.com/vala-lang/tree-sitter-vala) (maintained by @Prince781)
|
||||
- [x] [verilog](https://github.com/tree-sitter/tree-sitter-verilog) (maintained by @zegervdv)
|
||||
- [x] [vhs](https://github.com/charmbracelet/tree-sitter-vhs) (maintained by @caarlos0)
|
||||
- [x] [vim](https://github.com/neovim/tree-sitter-vim) (maintained by @clason)
|
||||
- [x] [vimdoc](https://github.com/neovim/tree-sitter-vimdoc) (maintained by @clason)
|
||||
- [x] [vue](https://github.com/ikatyang/tree-sitter-vue) (maintained by @WhyNotHugo)
|
||||
- [x] [wgsl](https://github.com/szebniok/tree-sitter-wgsl) (maintained by @szebniok)
|
||||
- [x] [wgsl_bevy](https://github.com/theHamsta/tree-sitter-wgsl-bevy) (maintained by @theHamsta)
|
||||
- [x] [wing](https://github.com/winglang/wing) (experimental, maintained by @gshpychka, @MarkMcCulloh)
|
||||
- [x] [xcompose](https://github.com/ObserverOfTime/tree-sitter-xcompose) (maintained by @ObserverOfTime)
|
||||
- [x] [xml](https://github.com/ObserverOfTime/tree-sitter-xml) (maintained by @ObserverOfTime)
|
||||
- [x] [yaml](https://github.com/ikatyang/tree-sitter-yaml) (maintained by @stsewd)
|
||||
- [x] [yang](https://github.com/Hubro/tree-sitter-yang) (maintained by @Hubro)
|
||||
- [x] [yuck](https://github.com/Philipp-M/tree-sitter-yuck) (maintained by @Philipp-M, @amaanq)
|
||||
- [x] [zig](https://github.com/maxxnino/tree-sitter-zig) (maintained by @maxxnino)
|
||||
<!--parserinfo-->
|
||||
## Highlighting
|
||||
|
||||
For related information on the supported languages, including related plugins, see [this wiki page](https://github.com/nvim-treesitter/nvim-treesitter/wiki/Supported-Languages-Information).
|
||||
|
||||
# Available modules
|
||||
|
||||
Modules provide the top-level features of `nvim-treesitter`.
|
||||
The following is a list of modules included in `nvim-treesitter` and their configuration via `init.lua` (where multiple modules can be combined in a single call to `setup`).
|
||||
Note that not all modules work for all languages (depending on the queries available for them).
|
||||
Additional modules can be provided as [external plugins](https://github.com/nvim-treesitter/nvim-treesitter/wiki/Extra-modules-and-plugins).
|
||||
|
||||
#### Highlight
|
||||
|
||||
Consistent syntax highlighting.
|
||||
Treesitter highlighting is provided by Neovim, see `:h treesitter-highlight`. To enable it for a filetype, put `vim.treesitter.start()` in a `ftplugin/<filetype>.lua` in your config directory, or place the following in your `init.lua`:
|
||||
|
||||
```lua
|
||||
require'nvim-treesitter.configs'.setup {
|
||||
highlight = {
|
||||
enable = true,
|
||||
-- Setting this to true will run `:h syntax` and tree-sitter at the same time.
|
||||
-- Set this to `true` if you depend on 'syntax' being enabled (like for indentation).
|
||||
-- Using this option may slow down your editor, and you may see some duplicate highlights.
|
||||
-- Instead of true it can also be a list of languages
|
||||
additional_vim_regex_highlighting = false,
|
||||
},
|
||||
}
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = { '<filetype>' },
|
||||
callback = function() vim.treesitter.start() end,
|
||||
})
|
||||
```
|
||||
|
||||
To customize the syntax highlighting of a capture, simply define or link a highlight group of the same name:
|
||||
## Folds
|
||||
|
||||
Treesitter-based folding is provided by Neovim. To enable it, put the following in your `ftplugin` or `FileType` autocommand:
|
||||
|
||||
```lua
|
||||
-- Highlight the @foo.bar capture group with the "Identifier" highlight group
|
||||
vim.api.nvim_set_hl(0, "@foo.bar", { link = "Identifier" })
|
||||
vim.wo[0][0].foldexpr = 'v:lua.vim.treesitter.foldexpr()'
|
||||
vim.wo[0][0].foldmethod = 'expr'
|
||||
```
|
||||
|
||||
For a language-specific highlight, append the name of the language:
|
||||
## Indentation
|
||||
|
||||
Treesitter-based indentation is provided by this plugin but considered **experimental**. To enable it, put the following in your `ftplugin` or `FileType` autocommand:
|
||||
|
||||
```lua
|
||||
-- Highlight @foo.bar as "Identifier" only in Lua files
|
||||
vim.api.nvim_set_hl(0, "@foo.bar.lua", { link = "Identifier" })
|
||||
vim.bo.indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()"
|
||||
```
|
||||
|
||||
See `:h treesitter-highlight-groups` for details.
|
||||
(Note the specific quotes used.)
|
||||
|
||||
#### Incremental selection
|
||||
## Injections
|
||||
|
||||
Incremental selection based on the named nodes from the grammar.
|
||||
Injections are used for multi-language documents, see `:h treesitter-language-injections`. No setup is needed.
|
||||
|
||||
```lua
|
||||
require'nvim-treesitter.configs'.setup {
|
||||
incremental_selection = {
|
||||
enable = true,
|
||||
keymaps = {
|
||||
init_selection = "gnn", -- set to `false` to disable one of the mappings
|
||||
node_incremental = "grn",
|
||||
scope_incremental = "grc",
|
||||
node_decremental = "grm",
|
||||
},
|
||||
},
|
||||
}
|
||||
```
|
||||
## Locals
|
||||
|
||||
#### Indentation
|
||||
|
||||
Indentation based on treesitter for the `=` operator.
|
||||
**NOTE: This is an experimental feature**.
|
||||
|
||||
```lua
|
||||
require'nvim-treesitter.configs'.setup {
|
||||
indent = {
|
||||
enable = true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Folding
|
||||
|
||||
Tree-sitter based folding. _(Technically not a module because it's per windows and not per buffer.)_
|
||||
|
||||
```vim
|
||||
set foldmethod=expr
|
||||
set foldexpr=nvim_treesitter#foldexpr()
|
||||
set nofoldenable " Disable folding at startup.
|
||||
```
|
||||
|
||||
This will respect your `foldminlines` and `foldnestmax` settings.
|
||||
These queries can be used to look up definitions and references to identifiers in a given scope. They are not used in this plugin and are provided for (limited) backward compatibility.
|
||||
|
||||
# Advanced setup
|
||||
|
||||
## Changing the parser install directory
|
||||
|
||||
If you want to install the parsers to a custom directory you can specify this
|
||||
directory with `parser_install_dir` option in that is passed to `setup`.
|
||||
`nvim-treesitter` will then install the parser files into this directory.
|
||||
|
||||
This directory must be writeable and must be explicitly added to the
|
||||
`runtimepath`. For example:
|
||||
|
||||
```lua
|
||||
vim.opt.runtimepath:append("/some/path/to/store/parsers")
|
||||
|
||||
require'nvim-treesitter.configs'.setup {
|
||||
parser_install_dir = "/some/path/to/store/parsers",
|
||||
|
||||
...
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
If this option is not included in the setup options, or is explicitly set to
|
||||
`nil` then the default install directories will be used. If this value is set
|
||||
the default directories will be ignored.
|
||||
|
||||
Bear in mind that any parser installed into a parser folder on the runtime path
|
||||
will still be considered installed. (For example if
|
||||
"~/.local/share/nvim/site/parser/c.so" exists then the "c" parser will be
|
||||
considered installed, even though it is not in `parser_install_dir`)
|
||||
|
||||
The default paths are:
|
||||
|
||||
1. first the package folder. Where `nvim-treesitter` is installed.
|
||||
2. second the site directory. This is the "site" subdirectory of `stdpath("data")`.
|
||||
|
||||
## Adding parsers
|
||||
## Adding custom languages
|
||||
|
||||
If you have a parser that is not on the list of supported languages (either as a repository on Github or in a local directory), you can add it manually for use by `nvim-treesitter` as follows:
|
||||
|
||||
1. Clone the repository or [create a new project](https://tree-sitter.github.io/tree-sitter/creating-parsers#project-setup) in, say, `~/projects/tree-sitter-zimbu`. Make sure that the `tree-sitter-cli` executable is installed and in your path; see <https://tree-sitter.github.io/tree-sitter/creating-parsers#installation> for installation instructions.
|
||||
2. Run `tree-sitter generate` in this directory (followed by `tree-sitter test` for good measure).
|
||||
3. Add the following snippet to your `init.lua`:
|
||||
1. Add the following snippet in a `User TSUpdate` autocommand:
|
||||
|
||||
```lua
|
||||
local parser_config = require "nvim-treesitter.parsers".get_parser_configs()
|
||||
parser_config.zimbu = {
|
||||
install_info = {
|
||||
url = "~/projects/tree-sitter-zimbu", -- local path or git repo
|
||||
files = {"src/parser.c"}, -- note that some parsers also require src/scanner.c or src/scanner.cc
|
||||
-- optional entries:
|
||||
branch = "main", -- default branch in case of git repo if different from master
|
||||
generate_requires_npm = false, -- if stand-alone parser without npm dependencies
|
||||
requires_generate_from_grammar = false, -- if folder contains pre-generated src/parser.c
|
||||
},
|
||||
filetype = "zu", -- if filetype does not match the parser name
|
||||
}
|
||||
vim.api.nvim_create_autocmd('User', { pattern = 'TSUpdate',
|
||||
callback = function()
|
||||
require('nvim-treesitter.parsers').zimbu = {
|
||||
install_info = {
|
||||
url = 'https://github.com/zimbulang/tree-sitter-zimbu',
|
||||
revision = <sha>, -- commit hash for revision to check out; HEAD if missing
|
||||
-- optional entries:
|
||||
branch = 'develop', -- only needed if different from default branch
|
||||
location = 'parser', -- only needed if the parser is in subdirectory of a "monorepo"
|
||||
generate = true, -- only needed if repo does not contain pre-generated `src/parser.c`
|
||||
generate_from_json = false, -- only needed if repo does not contain `src/grammar.json` either
|
||||
queries = 'queries/neovim', -- also install queries from given directory
|
||||
},
|
||||
}
|
||||
end})
|
||||
```
|
||||
|
||||
If you wish to set a specific parser for a filetype, you should use `vim.treesitter.language.register()`:
|
||||
Alternatively, if you have a local checkout, you can instead use
|
||||
|
||||
```lua
|
||||
vim.treesitter.language.register('python', 'someft') -- the someft filetype will use the python parser and queries.
|
||||
install_info = {
|
||||
path = '~/parsers/tree-sitter-zimbu',
|
||||
-- optional entries
|
||||
location = 'parser',
|
||||
generate = true,
|
||||
generate_from_json = false,
|
||||
queries = 'queries/neovim', -- symlink queries from given directory
|
||||
},
|
||||
```
|
||||
This will always use the state of the directory as-is (i.e., `branch` and `revision` will be ignored).
|
||||
|
||||
2. If the parser name differs from the filetype(s) used by Neovim, you need to register the parser via
|
||||
|
||||
```lua
|
||||
vim.treesitter.language.register('zimbu', { 'zu' })
|
||||
```
|
||||
|
||||
Note this requires Nvim v0.9.
|
||||
|
||||
4. Start `nvim` and `:TSInstall zimbu`.
|
||||
|
||||
You can also skip step 2 and use `:TSInstallFromGrammar zimbu` to install directly from a `grammar.js` in the top-level directory specified by `url`.
|
||||
Once the parser is installed, you can update it (from the latest revision of the `main` branch if `url` is a Github repository) with `:TSUpdate zimbu`.
|
||||
|
||||
Note that neither `:TSInstall` nor `:TSInstallFromGrammar` copy query files from the grammar repository.
|
||||
If you want your installed grammar to be useful, you must manually [add query files](#adding-queries) to your local nvim-treesitter installation.
|
||||
Note also that module functionality is only triggered if your language's filetype is correctly identified.
|
||||
If Neovim does not detect your language's filetype by default, you can use [Neovim's `vim.filetype.add()`](<https://neovim.io/doc/user/lua.html#vim.filetype.add()>) to add a custom detection rule.
|
||||
|
||||
If you use a git repository for your parser and want to use a specific version, you can set the `revision` key
|
||||
in the `install_info` table for you parser config.
|
||||
3. Start `nvim` and `:TSInstall zimbu`.
|
||||
|
||||
>[!IMPORTANT]
|
||||
> If the parser requires an external scanner, this must be written in C.
|
||||
|
||||
### Modifying parsers
|
||||
|
||||
You can use the same approach for overriding parser information. E.g., if you always want to generate the `lua` parser from grammar, add
|
||||
|
||||
```lua
|
||||
vim.api.nvim_create_autocmd('User', { pattern = 'TSUpdate',
|
||||
callback = function()
|
||||
require('nvim-treesitter.parsers').lua.install_info.generate = true
|
||||
end})
|
||||
```
|
||||
|
||||
## Adding queries
|
||||
|
||||
Queries are what `nvim-treesitter` uses to extract information from the syntax tree;
|
||||
they are located in the `queries/{language}/*` runtime directories (see `:h rtp`),
|
||||
like the `queries` folder of this plugin, e.g. `queries/{language}/{locals,highlights,textobjects}.scm`.
|
||||
Other modules may require additional queries such as `folding.scm`. You can find a
|
||||
list of all supported capture names in [CONTRIBUTING.md](https://github.com/nvim-treesitter/nvim-treesitter/blob/master/CONTRIBUTING.md#parser-configurations).
|
||||
|
||||
All queries found in the runtime directories will be combined.
|
||||
By convention, if you want to write a query, use the `queries/` directory,
|
||||
but if you want to extend a query use the `after/queries/` directory.
|
||||
|
||||
If you want to completely override a query, you can use `:h set_query()`.
|
||||
For example, to override the `injections` queries from `c` with your own:
|
||||
|
||||
```lua
|
||||
require("vim.treesitter.query").set_query("c", "injections", "(comment) @comment")
|
||||
```
|
||||
|
||||
Note: when using `set_query`, all queries in the runtime directories will be ignored.
|
||||
|
||||
## Adding modules
|
||||
|
||||
If you wish you write your own module, you need to support
|
||||
|
||||
- tree-sitter language detection support;
|
||||
- attaching and detaching to buffers;
|
||||
- all nvim-treesitter commands.
|
||||
|
||||
At the top level, you can use the `define_modules` function to define one or more modules or module groups:
|
||||
|
||||
```lua
|
||||
require'nvim-treesitter'.define_modules {
|
||||
my_cool_plugin = {
|
||||
attach = function(bufnr, lang)
|
||||
-- Do cool stuff here
|
||||
end,
|
||||
detach = function(bufnr)
|
||||
-- Undo cool stuff here
|
||||
end,
|
||||
is_supported = function(lang)
|
||||
-- Check if the language is supported
|
||||
end
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
with the following properties:
|
||||
|
||||
- `module_path` specifies a require path (string) that exports a module with an `attach` and `detach` function. This is not required if the functions are on this definition.
|
||||
- `enable` determines if the module is enabled by default. This is usually overridden by the user.
|
||||
- `disable` takes a list of languages that this module is disabled for. This is usually overridden by the user.
|
||||
- `is_supported` takes a function that takes a language and determines if this module supports that language.
|
||||
- `attach` takes a function that attaches to a buffer. This is required if `module_path` is not provided.
|
||||
- `detach` takes a function that detaches from a buffer. This is required if `module_path` is not provided.
|
||||
|
||||
# Extra features
|
||||
|
||||
### Statusline indicator
|
||||
|
||||
```vim
|
||||
echo nvim_treesitter#statusline(90) " 90 can be any length
|
||||
module->expression_statement->call->identifier
|
||||
```
|
||||
|
||||
### Utilities
|
||||
|
||||
You can get some utility functions with
|
||||
|
||||
```lua
|
||||
local ts_utils = require 'nvim-treesitter.ts_utils'
|
||||
```
|
||||
|
||||
Check [`:h nvim-treesitter-utils`](doc/nvim-treesitter.txt) for more information.
|
||||
|
||||
# Troubleshooting
|
||||
|
||||
Before doing anything, make sure you have the latest version of this plugin and run `:checkhealth nvim-treesitter`.
|
||||
It can also help to update the parsers via `:TSUpdate`.
|
||||
|
||||
#### Feature `X` does not work for `{language}`...
|
||||
|
||||
First, check the `health#nvim_treesitter#check` and the `health#treesitter#check` sections of `:checkhealth` for any warning.
|
||||
If there is one, it's highly likely that this is the cause of the problem.
|
||||
|
||||
Next check the `## Parser/Features` subsection of the `health#nvim_treesitter#check` section of `:checkhealth` to ensure the desired module is enabled for your language.
|
||||
If not, you might be missing query files; see [Adding queries](#adding-queries).
|
||||
|
||||
Finally, ensure Neovim is correctly identifying your language's filetype using the `:echo &filetype` command while one of your language's files is open in Neovim.
|
||||
If not, add a short Vimscript file to nvim-treesitter's `ftdetect` runtime directory following [Neovim's documentation](https://neovim.io/doc/user/filetype.html#new-filetype) on filetype detection.
|
||||
You can also quickly & temporarily set the filetype for a single buffer with the `:set filetype=langname` command to test whether it fixes the problem.
|
||||
|
||||
If everything is okay, then it might be an actual error.
|
||||
In that case, feel free to [open an issue here](https://github.com/nvim-treesitter/nvim-treesitter/issues/new/choose).
|
||||
|
||||
#### I get `module 'vim.treesitter.query' not found`
|
||||
|
||||
Make sure you have the latest version of Neovim.
|
||||
|
||||
#### I get `Error detected while processing .../plugin/nvim-treesitter.vim` every time I open Neovim
|
||||
|
||||
This is probably due to a change in a parser's grammar or its queries.
|
||||
Try updating the parser that you suspect has changed (`:TSUpdate {language}`) or all of them (`:TSUpdate`).
|
||||
If the error persists after updating all parsers,
|
||||
please [open an issue](https://github.com/nvim-treesitter/nvim-treesitter/issues/new/choose).
|
||||
|
||||
#### I get `query error: invalid node type at position`
|
||||
|
||||
This could be due a query file outside this plugin using outdated nodes,
|
||||
or due to an outdated parser.
|
||||
|
||||
- Make sure you have the parsers up to date with `:TSUpdate`
|
||||
- Make sure you don't have more than one `parser` runtime directory.
|
||||
You can execute this command `:echo nvim_get_runtime_file('parser', v:true)` to find all runtime directories.
|
||||
If you get more than one path, remove the ones that are outside this plugin (`nvim-treesitter` directory),
|
||||
so the correct version of the parser is used.
|
||||
|
||||
#### I experience weird highlighting issues similar to [#78](https://github.com/nvim-treesitter/nvim-treesitter/issues/78)
|
||||
|
||||
This is a well known issue, which arises when the tree and the buffer have gotten out of sync.
|
||||
As this is an upstream issue, we don't have any definite fix.
|
||||
To get around this, you can force reparsing the buffer with
|
||||
|
||||
```vim
|
||||
:write | edit | TSBufEnable highlight
|
||||
```
|
||||
|
||||
This will save, restore and enable highlighting for the current buffer.
|
||||
|
||||
#### I experience bugs when using `nvim-treesitter`'s `foldexpr` similar to [#194](https://github.com/nvim-treesitter/nvim-treesitter/issues/194)
|
||||
|
||||
This might happen, and is known to happen, with `vim-clap`.
|
||||
To avoid these kind of errors, please use `setlocal` instead of `set` for the respective filetypes.
|
||||
|
||||
#### I run into errors like `module 'nvim-treesitter.configs' not found` at startup
|
||||
|
||||
This is because of `rtp` management in `nvim`, adding `packadd
|
||||
nvim-treesitter` should fix the issue.
|
||||
|
||||
#### I want to use Git instead of curl for downloading the parsers
|
||||
|
||||
In your Lua config:
|
||||
|
||||
```lua
|
||||
require("nvim-treesitter.install").prefer_git = true
|
||||
```
|
||||
|
||||
#### I want to use a HTTP proxy for downloading the parsers
|
||||
|
||||
You can either configure curl to use additional CLI arguments in your Lua config:
|
||||
|
||||
```lua
|
||||
require("nvim-treesitter.install").command_extra_args = {
|
||||
curl = { "--proxy", "<proxy url>" },
|
||||
}
|
||||
```
|
||||
|
||||
or you can configure git via `.gitconfig` and use git instead of curl
|
||||
|
||||
```lua
|
||||
require("nvim-treesitter.install").prefer_git = true
|
||||
```
|
||||
|
||||
#### I want to use a mirror instead of "https://github.com/"
|
||||
|
||||
In your Lua config:
|
||||
|
||||
```lua
|
||||
for _, config in pairs(require("nvim-treesitter.parsers").get_parser_configs()) do
|
||||
config.install_info.url = config.install_info.url:gsub("https://github.com/", "something else")
|
||||
end
|
||||
|
||||
require'nvim-treesitter.configs'.setup {
|
||||
--
|
||||
--
|
||||
}
|
||||
```
|
||||
|
||||
#### Using an existing parser for another filetype
|
||||
|
||||
For example, to use the `bash` tree-sitter to highlight file with
|
||||
`filetype=apkbuild`, use:
|
||||
|
||||
```lua
|
||||
vim.treesitter.language.register("bash", "apkbuild")
|
||||
```
|
||||
|
||||
The `bash` tree-sitter must be installed following the usual procedure [as
|
||||
described above](#language-parsers).
|
||||
Queries can be placed anywhere in your `runtimepath` under `queries/<language>`, with earlier directories taking precedence unless the queries are marked with `; extends`; see [`:h treesitter-query-modelines`](https://neovim.io/doc/user/treesitter.html#treesitter-query-modeline).
|
||||
|
|
|
|||
365
SUPPORTED_LANGUAGES.md
generated
Normal file
365
SUPPORTED_LANGUAGES.md
generated
Normal file
|
|
@ -0,0 +1,365 @@
|
|||
# Supported languages
|
||||
|
||||
The following is a list of languages for which a parser can be installed through `:TSInstall`.
|
||||
|
||||
Legend:
|
||||
- **Tier:** _stable_ (updates follow semver releases), _unstable_ (updates follow HEAD), _unmaintained_ (no automatic updates), or _unsupported_ (known to be broken, cannot be installed)
|
||||
- **Queries** available for **H**ighlights, **F**olds, **I**ndents, In**J**ections, **L**ocals
|
||||
- **Maintainer** of queries in nvim-treesitter (may be different from parser maintainer!)
|
||||
|
||||
<!--This section of the README is automatically updated by a CI job-->
|
||||
<!--parserinfo-->
|
||||
Language | Tier | Queries | Maintainer
|
||||
-------- |:----:|:-------:| ----------
|
||||
[ada](https://github.com/briot/tree-sitter-ada) | unstable | `HF JL` | @briot
|
||||
[agda](https://github.com/tree-sitter/tree-sitter-agda) | unstable | `HF J ` | @Decodetalkers
|
||||
[angular](https://github.com/dlvandenberg/tree-sitter-angular) | unstable | `HFIJL` | @dlvandenberg
|
||||
[apex](https://github.com/aheber/tree-sitter-sfapex) | unstable | `HF JL` | @aheber, @xixiafinland
|
||||
[arduino](https://github.com/tree-sitter-grammars/tree-sitter-arduino) | unstable | `HFIJL` | @ObserverOfTime
|
||||
[asm](https://github.com/RubixDev/tree-sitter-asm) | unstable | `H J ` | @RubixDev
|
||||
[astro](https://github.com/virchau13/tree-sitter-astro) | unstable | `HFIJL` | @virchau13
|
||||
[authzed](https://github.com/mleonidas/tree-sitter-authzed) | unstable | `H J ` | @mattpolzin
|
||||
[awk](https://github.com/Beaglefoot/tree-sitter-awk) | unstable | `H J ` |
|
||||
[bash](https://github.com/tree-sitter/tree-sitter-bash) | unstable | `HFIJL` | @TravonteD
|
||||
[bass](https://github.com/vito/tree-sitter-bass) | unstable | `HFIJL` | @amaanq
|
||||
[beancount](https://github.com/polarmutex/tree-sitter-beancount) | unstable | `HF J ` | @polarmutex
|
||||
[bibtex](https://github.com/latex-lsp/tree-sitter-bibtex) | unstable | `HFIJ ` | @theHamsta, @clason
|
||||
[bicep](https://github.com/tree-sitter-grammars/tree-sitter-bicep) | unstable | `HFIJL` | @amaanq
|
||||
[bitbake](https://github.com/tree-sitter-grammars/tree-sitter-bitbake) | unstable | `HFIJL` | @amaanq
|
||||
[blade](https://github.com/EmranMR/tree-sitter-blade) | unstable | `HFIJ ` | @calebdw
|
||||
[bp](https://github.com/ambroisie/tree-sitter-bp)[^bp] | unstable | `HFIJL` | @ambroisie
|
||||
[bpftrace](https://github.com/sgruszka/tree-sitter-bpftrace) | unstable | `H J ` | @sgruszka
|
||||
[brightscript](https://github.com/ajdelcimmuto/tree-sitter-brightscript) | unstable | `HFIJ ` | @ajdelcimmuto
|
||||
[c](https://github.com/tree-sitter/tree-sitter-c) | unstable | `HFIJL` | @amaanq
|
||||
[c3](https://github.com/c3lang/tree-sitter-c3) | unstable | `HFIJ ` | @cbuttner
|
||||
[c_sharp](https://github.com/tree-sitter/tree-sitter-c-sharp) | unstable | `HF JL` | @amaanq
|
||||
[caddy](https://github.com/opa-oz/tree-sitter-caddy) | unmaintained | `HFIJ ` |
|
||||
[cairo](https://github.com/tree-sitter-grammars/tree-sitter-cairo) | unstable | `HFIJL` | @amaanq
|
||||
[capnp](https://github.com/tree-sitter-grammars/tree-sitter-capnp) | unstable | `HFIJL` | @amaanq
|
||||
[chatito](https://github.com/tree-sitter-grammars/tree-sitter-chatito) | unstable | `HFIJL` | @ObserverOfTime
|
||||
[circom](https://github.com/Decurity/tree-sitter-circom) | unstable | `HF JL` | @alexandr-martirosyan
|
||||
[clojure](https://github.com/sogaiu/tree-sitter-clojure) | unstable | `HF JL` | @NoahTheDuke
|
||||
[cmake](https://github.com/uyha/tree-sitter-cmake) | unstable | `HFIJ ` | @uyha
|
||||
[comment](https://github.com/stsewd/tree-sitter-comment) | unstable | `H ` | @stsewd
|
||||
[commonlisp](https://github.com/tree-sitter-grammars/tree-sitter-commonlisp) | unstable | `HF JL` | @theHamsta
|
||||
[cooklang](https://github.com/addcninblue/tree-sitter-cooklang) | unstable | `H J ` | @addcninblue
|
||||
[corn](https://github.com/jakestanger/tree-sitter-corn) | unstable | `HFIJL` | @jakestanger
|
||||
[cpon](https://github.com/tree-sitter-grammars/tree-sitter-cpon) | unstable | `HFIJL` | @amaanq
|
||||
[cpp](https://github.com/tree-sitter/tree-sitter-cpp) | unstable | `HFIJL` | @theHamsta
|
||||
[css](https://github.com/tree-sitter/tree-sitter-css) | unstable | `HFIJ ` | @TravonteD
|
||||
[csv](https://github.com/tree-sitter-grammars/tree-sitter-csv) | unstable | `H ` | @amaanq
|
||||
[cuda](https://github.com/tree-sitter-grammars/tree-sitter-cuda) | unstable | `HFIJL` | @theHamsta
|
||||
[cue](https://github.com/eonpatapon/tree-sitter-cue) | unstable | `HFIJL` | @amaanq
|
||||
[cylc](https://github.com/elliotfontaine/tree-sitter-cylc) | unstable | `HFIJ ` | @elliotfontaine
|
||||
[d](https://github.com/gdamore/tree-sitter-d) | unstable | `HFIJL` | @amaanq
|
||||
[dart](https://github.com/UserNobody14/tree-sitter-dart) | unstable | `HFIJL` | @akinsho
|
||||
[desktop](https://github.com/ValdezFOmar/tree-sitter-desktop) | stable | `HF J ` | @ValdezFOmar
|
||||
[devicetree](https://github.com/joelspadin/tree-sitter-devicetree) | unstable | `HFIJL` | @jedrzejboczar
|
||||
[dhall](https://github.com/jbellerb/tree-sitter-dhall) | unstable | `HF J ` | @amaanq
|
||||
[diff](https://github.com/tree-sitter-grammars/tree-sitter-diff) | unstable | `HF J ` | @gbprod
|
||||
[disassembly](https://github.com/ColinKennedy/tree-sitter-disassembly) | unstable | `H J ` | @ColinKennedy
|
||||
[djot](https://github.com/treeman/tree-sitter-djot) | unstable | `HFIJL` | @NoahTheDuke
|
||||
[dockerfile](https://github.com/camdencheek/tree-sitter-dockerfile) | unstable | `H J ` | @camdencheek
|
||||
[dot](https://github.com/rydesun/tree-sitter-dot) | unstable | `HFIJ ` | @rydesun
|
||||
[doxygen](https://github.com/tree-sitter-grammars/tree-sitter-doxygen) | unstable | `H IJ ` | @amaanq
|
||||
[dtd](https://github.com/tree-sitter-grammars/tree-sitter-xml) | unstable | `HF JL` | @ObserverOfTime
|
||||
[earthfile](https://github.com/glehmann/tree-sitter-earthfile) | unstable | `H J ` | @glehmann
|
||||
[ebnf](https://github.com/RubixDev/ebnf) | unstable | `H J ` | @RubixDev
|
||||
ecma (queries only)[^ecma] | unstable | `HFIJL` | @steelsojka
|
||||
[editorconfig](https://github.com/ValdezFOmar/tree-sitter-editorconfig) | stable | `HF J ` | @ValdezFOmar
|
||||
[eds](https://github.com/uyha/tree-sitter-eds) | unstable | `HF ` | @uyha
|
||||
[eex](https://github.com/connorlay/tree-sitter-eex) | unstable | `H J ` | @connorlay
|
||||
[elixir](https://github.com/elixir-lang/tree-sitter-elixir) | unstable | `HFIJL` | @connorlay
|
||||
[elm](https://github.com/elm-tooling/tree-sitter-elm) | unstable | `HF J ` | @zweimach
|
||||
[elsa](https://github.com/glapa-grossklag/tree-sitter-elsa) | unstable | `HFIJL` | @glapa-grossklag, @amaanq
|
||||
[elvish](https://github.com/elves/tree-sitter-elvish) | unstable | `H J ` | @elves
|
||||
[embedded_template](https://github.com/tree-sitter/tree-sitter-embedded-template) | unstable | `H J ` |
|
||||
[enforce](https://github.com/simonvic/tree-sitter-enforce) | unstable | `HFIJL` | @simonvic
|
||||
[erlang](https://github.com/WhatsApp/tree-sitter-erlang) | unstable | `HF J ` | @filmor
|
||||
[facility](https://github.com/FacilityApi/tree-sitter-facility) | unstable | `HFIJ ` | @bryankenote
|
||||
[faust](https://github.com/khiner/tree-sitter-faust) | unstable | `H J ` | @khiner
|
||||
[fennel](https://github.com/alexmozaidze/tree-sitter-fennel) | unstable | `HF JL` | @alexmozaidze
|
||||
[fidl](https://github.com/google/tree-sitter-fidl) | unstable | `HF J ` | @chaopeng
|
||||
[firrtl](https://github.com/tree-sitter-grammars/tree-sitter-firrtl) | unstable | `HFIJL` | @amaanq
|
||||
[fish](https://github.com/ram02z/tree-sitter-fish) | unstable | `HFIJL` | @ram02z
|
||||
[foam](https://github.com/FoamScience/tree-sitter-foam) | unstable | `HFIJL` | @FoamScience
|
||||
[forth](https://github.com/AlexanderBrevig/tree-sitter-forth) | unstable | `HFIJL` | @amaanq
|
||||
[fortran](https://github.com/stadelmanma/tree-sitter-fortran) | unstable | `HFIJ ` | @amaanq
|
||||
[fsh](https://github.com/mgramigna/tree-sitter-fsh) | unstable | `H J ` | @mgramigna
|
||||
[fsharp](https://github.com/ionide/tree-sitter-fsharp) | unstable | `H J ` | @nsidorenco
|
||||
[func](https://github.com/tree-sitter-grammars/tree-sitter-func) | unstable | `H J ` | @amaanq
|
||||
[gap](https://github.com/gap-system/tree-sitter-gap)[^gap] | unstable | `HF JL` | @reiniscirpons
|
||||
[gaptst](https://github.com/gap-system/tree-sitter-gaptst)[^gaptst] | unstable | `HF J ` | @reiniscirpons
|
||||
[gdscript](https://github.com/PrestonKnopp/tree-sitter-gdscript)[^gdscript] | unmaintained | `HFIJL` |
|
||||
[gdshader](https://github.com/airblast-dev/tree-sitter-gdshader) | unstable | `H J ` | @airblast-dev
|
||||
[git_config](https://github.com/the-mikedavis/tree-sitter-git-config) | unstable | `HF J ` | @amaanq
|
||||
[git_rebase](https://github.com/the-mikedavis/tree-sitter-git-rebase) | unstable | `H J ` | @gbprod
|
||||
[gitattributes](https://github.com/tree-sitter-grammars/tree-sitter-gitattributes) | unstable | `H JL` | @ObserverOfTime
|
||||
[gitcommit](https://github.com/gbprod/tree-sitter-gitcommit) | unstable | `H J ` | @gbprod
|
||||
[gitignore](https://github.com/shunsambongi/tree-sitter-gitignore) | unstable | `H J ` | @theHamsta
|
||||
[gleam](https://github.com/gleam-lang/tree-sitter-gleam) | unstable | `HFIJL` | @amaanq
|
||||
[glimmer](https://github.com/ember-tooling/tree-sitter-glimmer)[^glimmer] | unstable | `HFIJL` | @NullVoxPopuli
|
||||
[glimmer_javascript](https://github.com/NullVoxPopuli/tree-sitter-glimmer-javascript) | unstable | `HFIJL` | @NullVoxPopuli
|
||||
[glimmer_typescript](https://github.com/NullVoxPopuli/tree-sitter-glimmer-typescript) | unstable | `HFIJ ` | @NullVoxPopuli
|
||||
[glsl](https://github.com/tree-sitter-grammars/tree-sitter-glsl) | unstable | `HFIJL` | @theHamsta
|
||||
[gn](https://github.com/tree-sitter-grammars/tree-sitter-gn) | unstable | `HFIJL` | @amaanq
|
||||
[gnuplot](https://github.com/dpezto/tree-sitter-gnuplot) | unstable | `H J ` | @dpezto
|
||||
[go](https://github.com/tree-sitter/tree-sitter-go) | unstable | `HFIJL` | @theHamsta, @WinWisely268
|
||||
[goctl](https://github.com/chaozwn/tree-sitter-goctl) | unstable | `HFIJ ` | @chaozwn
|
||||
[godot_resource](https://github.com/PrestonKnopp/tree-sitter-godot-resource)[^godot_resource] | unstable | `HF JL` | @pierpo
|
||||
[gomod](https://github.com/camdencheek/tree-sitter-go-mod) | unstable | `H J ` | @camdencheek
|
||||
[gosum](https://github.com/tree-sitter-grammars/tree-sitter-go-sum) | unstable | `H ` | @amaanq
|
||||
[gotmpl](https://github.com/ngalaiko/tree-sitter-go-template) | unstable | `HF JL` | @qvalentin
|
||||
[gowork](https://github.com/omertuc/tree-sitter-go-work) | unstable | `H J ` | @omertuc
|
||||
[gpg](https://github.com/tree-sitter-grammars/tree-sitter-gpg-config) | unstable | `H J ` | @ObserverOfTime
|
||||
[graphql](https://github.com/bkegley/tree-sitter-graphql) | unstable | `H IJ ` | @bkegley
|
||||
[gren](https://github.com/MaeBrooks/tree-sitter-gren) | unstable | `H J ` | @MaeBrooks
|
||||
[groovy](https://github.com/murtaza64/tree-sitter-groovy) | unstable | `HFIJL` | @murtaza64
|
||||
[groq](https://github.com/ajrussellaudio/tree-sitter-groq) | unstable | `HFIJ ` | @ajrussellaudio
|
||||
[gstlaunch](https://github.com/tree-sitter-grammars/tree-sitter-gstlaunch) | unstable | `H ` | @theHamsta
|
||||
[hack](https://github.com/slackhq/tree-sitter-hack) | unstable | `H J ` |
|
||||
[hare](https://github.com/tree-sitter-grammars/tree-sitter-hare) | unstable | `HFIJL` | @amaanq
|
||||
[haskell](https://github.com/tree-sitter-grammars/tree-sitter-haskell) | unstable | `HF JL` | @mrcjkb
|
||||
[haskell_persistent](https://github.com/MercuryTechnologies/tree-sitter-haskell-persistent) | unstable | `HF ` | @lykahb
|
||||
[hcl](https://github.com/tree-sitter-grammars/tree-sitter-hcl) | unstable | `HFIJ ` | @MichaHoffmann
|
||||
[heex](https://github.com/connorlay/tree-sitter-heex) | unstable | `HFIJL` | @connorlay
|
||||
[helm](https://github.com/ngalaiko/tree-sitter-go-template) | unstable | `HF JL` | @qvalentin
|
||||
[hjson](https://github.com/winston0410/tree-sitter-hjson) | unstable | `HFIJL` | @winston0410
|
||||
[hlsl](https://github.com/tree-sitter-grammars/tree-sitter-hlsl) | unstable | `HFIJL` | @theHamsta
|
||||
[hlsplaylist](https://github.com/Freed-Wu/tree-sitter-hlsplaylist) | unstable | `H J ` | @Freed-Wu
|
||||
[hocon](https://github.com/antosha417/tree-sitter-hocon) | unstable | `HF J ` | @antosha417
|
||||
[hoon](https://github.com/urbit-pilled/tree-sitter-hoon) | unstable | `HF JL` | @urbit-pilled
|
||||
[html](https://github.com/tree-sitter/tree-sitter-html) | unstable | `HFIJL` | @TravonteD
|
||||
html_tags (queries only)[^html_tags] | unstable | `H IJ ` | @TravonteD
|
||||
[htmldjango](https://github.com/interdependence/tree-sitter-htmldjango) | unstable | `HFIJ ` | @ObserverOfTime
|
||||
[http](https://github.com/rest-nvim/tree-sitter-http) | unstable | `HF J ` | @amaanq, @NTBBloodbath
|
||||
[hurl](https://github.com/pfeiferj/tree-sitter-hurl) | unstable | `HFIJ ` | @pfeiferj
|
||||
[hyprlang](https://github.com/tree-sitter-grammars/tree-sitter-hyprlang) | unstable | `HFIJ ` | @luckasRanarison
|
||||
[idl](https://github.com/cathaysia/tree-sitter-idl) | unstable | `H IJ ` | @cathaysia
|
||||
[idris](https://github.com/kayhide/tree-sitter-idris) | unstable | `HF JL` |
|
||||
[ini](https://github.com/justinmk/tree-sitter-ini) | unstable | `HF J ` | @theHamsta
|
||||
[inko](https://github.com/inko-lang/tree-sitter-inko) | stable | `HFIJL` | @yorickpeterse
|
||||
[ispc](https://github.com/tree-sitter-grammars/tree-sitter-ispc) | unstable | `HFIJL` | @fab4100
|
||||
[janet_simple](https://github.com/sogaiu/tree-sitter-janet-simple) | unstable | `HF JL` | @sogaiu
|
||||
[java](https://github.com/tree-sitter/tree-sitter-java) | unstable | `HFIJL` | @p00f
|
||||
[javadoc](https://github.com/rmuir/tree-sitter-javadoc) | unstable | `H IJ ` | @rmuir
|
||||
[javascript](https://github.com/tree-sitter/tree-sitter-javascript) | unstable | `HFIJL` | @steelsojka
|
||||
[jinja](https://github.com/cathaysia/tree-sitter-jinja)[^jinja] | unstable | `H J ` | @cathaysia
|
||||
[jinja_inline](https://github.com/cathaysia/tree-sitter-jinja)[^jinja_inline] | unstable | `H J ` | @cathaysia
|
||||
[jjdescription](https://github.com/ribru17/tree-sitter-jjdescription) | stable | `H J ` | @ribru17
|
||||
[jq](https://github.com/flurie/tree-sitter-jq) | unstable | `H JL` | @ObserverOfTime
|
||||
[jsdoc](https://github.com/tree-sitter/tree-sitter-jsdoc) | unstable | `H ` | @steelsojka
|
||||
[json](https://github.com/tree-sitter/tree-sitter-json) | unstable | `HFIJL` | @steelsojka
|
||||
[json5](https://github.com/Joakker/tree-sitter-json5) | unstable | `H J ` | @Joakker
|
||||
[jsonnet](https://github.com/sourcegraph/tree-sitter-jsonnet) | unstable | `HF JL` | @nawordar
|
||||
jsx (queries only)[^jsx] | unstable | `HFIJ ` | @steelsojka
|
||||
[julia](https://github.com/tree-sitter-grammars/tree-sitter-julia) | unstable | `HFIJL` | @clason
|
||||
[just](https://github.com/IndianBoy42/tree-sitter-just) | unstable | `HFIJL` | @Hubro
|
||||
[kcl](https://github.com/kcl-lang/tree-sitter-kcl) | unstable | `HF J ` | @bertbaron
|
||||
[kconfig](https://github.com/tree-sitter-grammars/tree-sitter-kconfig) | unstable | `HFIJL` | @amaanq
|
||||
[kdl](https://github.com/tree-sitter-grammars/tree-sitter-kdl) | unstable | `HFIJL` | @amaanq
|
||||
[kitty](https://github.com/OXY2DEV/tree-sitter-kitty) | unstable | `H J ` | @OXY2DEV
|
||||
[kos](https://github.com/kos-lang/tree-sitter-kos) | unstable | `HF JL` | @cdragan
|
||||
[kotlin](https://github.com/fwcd/tree-sitter-kotlin) | unstable | `HF JL` |
|
||||
[koto](https://github.com/koto-lang/tree-sitter-koto) | unstable | `HF JL` | @irh
|
||||
[kusto](https://github.com/Willem-J-an/tree-sitter-kusto) | unstable | `H J ` | @Willem-J-an
|
||||
[lalrpop](https://github.com/traxys/tree-sitter-lalrpop) | unstable | `HF JL` | @traxys
|
||||
[latex](https://github.com/latex-lsp/tree-sitter-latex) | unstable | `HF J ` | @theHamsta, @clason
|
||||
[ledger](https://github.com/cbarrete/tree-sitter-ledger) | unstable | `HFIJ ` | @cbarrete
|
||||
[leo](https://github.com/r001/tree-sitter-leo) | unstable | `H IJ ` | @r001
|
||||
[linkerscript](https://github.com/tree-sitter-grammars/tree-sitter-linkerscript) | unstable | `HFIJL` | @amaanq
|
||||
[liquid](https://github.com/hankthetank27/tree-sitter-liquid) | unstable | `H J ` | @hankthetank27
|
||||
[liquidsoap](https://github.com/savonet/tree-sitter-liquidsoap) | unstable | `HFIJL` | @toots
|
||||
[llvm](https://github.com/benwilliamgraham/tree-sitter-llvm) | unstable | `H J ` | @benwilliamgraham
|
||||
[lua](https://github.com/tree-sitter-grammars/tree-sitter-lua) | unstable | `HFIJL` | @muniftanjim
|
||||
[luadoc](https://github.com/tree-sitter-grammars/tree-sitter-luadoc) | unstable | `H ` | @amaanq
|
||||
[luap](https://github.com/tree-sitter-grammars/tree-sitter-luap)[^luap] | unstable | `H ` | @amaanq
|
||||
[luau](https://github.com/tree-sitter-grammars/tree-sitter-luau) | unstable | `HFIJL` | @amaanq
|
||||
[m68k](https://github.com/grahambates/tree-sitter-m68k) | unstable | `HF JL` | @grahambates
|
||||
[make](https://github.com/tree-sitter-grammars/tree-sitter-make) | unstable | `HF J ` | @lewis6991
|
||||
[markdown](https://github.com/tree-sitter-grammars/tree-sitter-markdown)[^markdown] | unstable | `HFIJ ` | @MDeiml
|
||||
[markdown_inline](https://github.com/tree-sitter-grammars/tree-sitter-markdown)[^markdown_inline] | unstable | `H J ` | @MDeiml
|
||||
[matlab](https://github.com/acristoffers/tree-sitter-matlab) | unstable | `HFIJL` | @acristoffers
|
||||
[menhir](https://github.com/Kerl13/tree-sitter-menhir) | unstable | `H J ` | @Kerl13
|
||||
[mermaid](https://github.com/monaqa/tree-sitter-mermaid) | unstable | `HFIJ ` |
|
||||
[meson](https://github.com/tree-sitter-grammars/tree-sitter-meson) | unstable | `HFIJ ` | @Decodetalkers
|
||||
[mlir](https://github.com/artagnon/tree-sitter-mlir) | unstable | `H JL` | @artagnon
|
||||
[muttrc](https://github.com/neomutt/tree-sitter-muttrc) | unstable | `H J ` | @Freed-Wu
|
||||
[nasm](https://github.com/naclsn/tree-sitter-nasm) | unstable | `H J ` | @ObserverOfTime
|
||||
[nginx](https://github.com/opa-oz/tree-sitter-nginx) | unstable | `HF J ` | @opa-oz
|
||||
[nickel](https://github.com/nickel-lang/tree-sitter-nickel) | unstable | `H IJ ` |
|
||||
[nim](https://github.com/alaviss/tree-sitter-nim) | unstable | `HF JL` | @aMOPel
|
||||
[nim_format_string](https://github.com/aMOPel/tree-sitter-nim-format-string) | unstable | `H J ` | @aMOPel
|
||||
[ninja](https://github.com/alemuller/tree-sitter-ninja) | unstable | `HFIJ ` | @alemuller
|
||||
[nix](https://github.com/nix-community/tree-sitter-nix) | unstable | `HFIJL` | @leo60228, @mrcjkb, @zimbatm
|
||||
[nqc](https://github.com/tree-sitter-grammars/tree-sitter-nqc) | unstable | `HFIJL` | @amaanq
|
||||
[nu](https://github.com/nushell/tree-sitter-nu) | unstable | `HFIJ ` | @abhisheksingh0x558
|
||||
[objc](https://github.com/tree-sitter-grammars/tree-sitter-objc) | unstable | `HFIJL` | @amaanq
|
||||
[objdump](https://github.com/ColinKennedy/tree-sitter-objdump) | unstable | `H J ` | @ColinKennedy
|
||||
[ocaml](https://github.com/tree-sitter/tree-sitter-ocaml) | unstable | `HFIJL` | @undu
|
||||
[ocaml_interface](https://github.com/tree-sitter/tree-sitter-ocaml) | unstable | `HFIJL` | @undu
|
||||
[ocamllex](https://github.com/atom-ocaml/tree-sitter-ocamllex) | unstable | `H J ` | @undu
|
||||
[odin](https://github.com/tree-sitter-grammars/tree-sitter-odin) | unstable | `HFIJL` | @amaanq
|
||||
[pascal](https://github.com/Isopod/tree-sitter-pascal) | unstable | `HFIJL` | @Isopod
|
||||
[passwd](https://github.com/ath3/tree-sitter-passwd) | unstable | `H ` | @amaanq
|
||||
[pem](https://github.com/tree-sitter-grammars/tree-sitter-pem) | unstable | `HF J ` | @ObserverOfTime
|
||||
[perl](https://github.com/tree-sitter-perl/tree-sitter-perl) | unstable | `HF J ` | @RabbiVeesh, @LeoNerd
|
||||
[php](https://github.com/tree-sitter/tree-sitter-php)[^php] | unstable | `HFIJL` | @tk-shirasaka, @calebdw
|
||||
[php_only](https://github.com/tree-sitter/tree-sitter-php)[^php_only] | unstable | `HFIJL` | @tk-shirasaka, @calebdw
|
||||
[phpdoc](https://github.com/claytonrcarter/tree-sitter-phpdoc) | unstable | `H ` | @mikehaertl
|
||||
[pioasm](https://github.com/leo60228/tree-sitter-pioasm) | unstable | `H J ` | @leo60228
|
||||
[pkl](https://github.com/apple/tree-sitter-pkl) | unstable | `HF J ` | @ribru17
|
||||
[po](https://github.com/tree-sitter-grammars/tree-sitter-po) | unstable | `HF J ` | @amaanq
|
||||
[pod](https://github.com/tree-sitter-perl/tree-sitter-pod) | unstable | `H ` | @RabbiVeesh, @LeoNerd
|
||||
[poe_filter](https://github.com/tree-sitter-grammars/tree-sitter-poe-filter)[^poe_filter] | unstable | `HFIJ ` | @ObserverOfTime
|
||||
[pony](https://github.com/tree-sitter-grammars/tree-sitter-pony) | unstable | `HFIJL` | @amaanq, @mfelsche
|
||||
[powershell](https://github.com/airbus-cert/tree-sitter-powershell) | unstable | `HFIJL` | @L2jLiga
|
||||
[printf](https://github.com/tree-sitter-grammars/tree-sitter-printf) | unstable | `H ` | @ObserverOfTime
|
||||
[prisma](https://github.com/victorhqc/tree-sitter-prisma) | unstable | `HF J ` | @elianiva
|
||||
[problog](https://github.com/foxyseta/tree-sitter-prolog) | unstable | `HFIJ ` | @foxyseta
|
||||
[prolog](https://github.com/foxyseta/tree-sitter-prolog) | unstable | `HFIJ ` | @foxyseta
|
||||
[promql](https://github.com/MichaHoffmann/tree-sitter-promql) | unstable | `H J ` | @MichaHoffmann
|
||||
[properties](https://github.com/tree-sitter-grammars/tree-sitter-properties)[^properties] | unstable | `H JL` | @ObserverOfTime
|
||||
[proto](https://github.com/coder3101/tree-sitter-proto) | unstable | `HFIJ ` | @stefanvanburen
|
||||
[prql](https://github.com/PRQL/tree-sitter-prql) | unstable | `H J ` | @matthias-Q
|
||||
[psv](https://github.com/tree-sitter-grammars/tree-sitter-csv) | unstable | `H ` | @amaanq
|
||||
[pug](https://github.com/zealot128/tree-sitter-pug) | unstable | `H J ` | @zealot128
|
||||
[puppet](https://github.com/tree-sitter-grammars/tree-sitter-puppet) | unstable | `HFIJL` | @amaanq
|
||||
[purescript](https://github.com/postsolar/tree-sitter-purescript) | unstable | `H JL` | @postsolar
|
||||
[pymanifest](https://github.com/tree-sitter-grammars/tree-sitter-pymanifest) | unstable | `H J ` | @ObserverOfTime
|
||||
[python](https://github.com/tree-sitter/tree-sitter-python) | stable | `HFIJL` | @stsewd, @theHamsta
|
||||
[ql](https://github.com/tree-sitter/tree-sitter-ql) | unstable | `HFIJL` | @pwntester
|
||||
[qmldir](https://github.com/tree-sitter-grammars/tree-sitter-qmldir) | unstable | `H J ` | @amaanq
|
||||
[qmljs](https://github.com/yuja/tree-sitter-qmljs) | unstable | `HF J ` | @Decodetalkers
|
||||
[query](https://github.com/tree-sitter-grammars/tree-sitter-query)[^query] | unstable | `HFIJL` | @steelsojka
|
||||
[r](https://github.com/r-lib/tree-sitter-r) | unstable | `H IJL` | @ribru17
|
||||
[racket](https://github.com/6cdh/tree-sitter-racket) | unstable | `HF J ` |
|
||||
[ralph](https://github.com/alephium/tree-sitter-ralph) | unstable | `H J ` | @tdroxler
|
||||
[rasi](https://github.com/Fymyte/tree-sitter-rasi) | unstable | `HFIJL` | @Fymyte
|
||||
[razor](https://github.com/tris203/tree-sitter-razor) | unstable | `HF J ` | @tris203
|
||||
[rbs](https://github.com/joker1007/tree-sitter-rbs) | unstable | `HFIJ ` | @joker1007
|
||||
[re2c](https://github.com/tree-sitter-grammars/tree-sitter-re2c) | unstable | `HFIJL` | @amaanq
|
||||
[readline](https://github.com/tree-sitter-grammars/tree-sitter-readline) | unstable | `HFIJ ` | @ribru17
|
||||
[regex](https://github.com/tree-sitter/tree-sitter-regex) | unstable | `H ` | @theHamsta
|
||||
[rego](https://github.com/FallenAngel97/tree-sitter-rego) | unstable | `H J ` | @FallenAngel97
|
||||
[requirements](https://github.com/tree-sitter-grammars/tree-sitter-requirements) | unstable | `H J ` | @ObserverOfTime
|
||||
[rescript](https://github.com/rescript-lang/tree-sitter-rescript) | unstable | `HFIJL` | @ribru17
|
||||
[rifleconf](https://github.com/purarue/tree-sitter-rifleconf) | unstable | `H J ` | @purarue
|
||||
[rnoweb](https://github.com/bamonroe/tree-sitter-rnoweb) | unstable | `HF J ` | @bamonroe
|
||||
[robot](https://github.com/Hubro/tree-sitter-robot) | unmaintained | `HFIJ ` |
|
||||
[robots_txt](https://github.com/opa-oz/tree-sitter-robots-txt) | unstable | `H J ` | @opa-oz
|
||||
[roc](https://github.com/faldor20/tree-sitter-roc) | unmaintained | `H IJL` |
|
||||
[ron](https://github.com/tree-sitter-grammars/tree-sitter-ron) | unstable | `HFIJL` | @amaanq
|
||||
[rst](https://github.com/stsewd/tree-sitter-rst) | unstable | `H JL` | @stsewd
|
||||
[ruby](https://github.com/tree-sitter/tree-sitter-ruby) | unstable | `HFIJL` | @TravonteD
|
||||
[runescript](https://github.com/2004Scape/tree-sitter-runescript) | unstable | `H J ` | @2004Scape
|
||||
[rust](https://github.com/tree-sitter/tree-sitter-rust) | unstable | `HFIJL` | @amaanq
|
||||
[scala](https://github.com/tree-sitter/tree-sitter-scala) | unstable | `HF JL` | @stevanmilic
|
||||
[scfg](https://github.com/rockorager/tree-sitter-scfg) | unstable | `H J ` | @WhyNotHugo
|
||||
[scheme](https://github.com/6cdh/tree-sitter-scheme) | unstable | `HF J ` |
|
||||
[scss](https://github.com/serenadeai/tree-sitter-scss) | unstable | `HFIJ ` | @elianiva
|
||||
[sflog](https://github.com/aheber/tree-sitter-sfapex)[^sflog] | unstable | `H ` | @aheber, @xixiaofinland
|
||||
[slang](https://github.com/tree-sitter-grammars/tree-sitter-slang)[^slang] | unstable | `HFIJL` | @theHamsta
|
||||
[slim](https://github.com/theoo/tree-sitter-slim) | unstable | `HFIJL` | @theoo
|
||||
[slint](https://github.com/slint-ui/tree-sitter-slint) | unstable | `HFIJL` | @hunger
|
||||
[smali](https://github.com/tree-sitter-grammars/tree-sitter-smali) | unstable | `HFIJL` | @amaanq
|
||||
[smithy](https://github.com/indoorvivants/tree-sitter-smithy) | unstable | `H J ` | @amaanq, @keynmol
|
||||
[snakemake](https://github.com/osthomas/tree-sitter-snakemake) | unstable | `HFIJL` | @osthomas
|
||||
[snl](https://github.com/minijackson/tree-sitter-snl)[^snl] | unstable | `HFIJL` | @minijackson
|
||||
[solidity](https://github.com/JoranHonig/tree-sitter-solidity) | unstable | `HF J ` | @amaanq
|
||||
[soql](https://github.com/aheber/tree-sitter-sfapex) | unstable | `H ` | @aheber, @xixiafinland
|
||||
[sosl](https://github.com/aheber/tree-sitter-sfapex) | unstable | `H ` | @aheber, @xixiafinland
|
||||
[sourcepawn](https://github.com/nilshelmig/tree-sitter-sourcepawn) | unstable | `H JL` | @Sarrus1
|
||||
[sparql](https://github.com/GordianDziwis/tree-sitter-sparql) | unstable | `HFIJL` | @GordianDziwis
|
||||
[sproto](https://github.com/hanxi/tree-sitter-sproto) | unstable | `HFIJ ` | @hanxi
|
||||
[sql](https://github.com/derekstride/tree-sitter-sql) | unstable | `HFIJ ` | @derekstride
|
||||
[squirrel](https://github.com/tree-sitter-grammars/tree-sitter-squirrel) | unstable | `HFIJL` | @amaanq
|
||||
[ssh_config](https://github.com/tree-sitter-grammars/tree-sitter-ssh-config) | unstable | `HFIJL` | @ObserverOfTime
|
||||
[starlark](https://github.com/tree-sitter-grammars/tree-sitter-starlark) | unstable | `HFIJL` | @amaanq
|
||||
[strace](https://github.com/sigmaSd/tree-sitter-strace) | unstable | `H J ` | @amaanq
|
||||
[styled](https://github.com/mskelton/tree-sitter-styled) | unstable | `HFIJ ` | @mskelton
|
||||
[supercollider](https://github.com/madskjeldgaard/tree-sitter-supercollider) | unstable | `HFIJL` | @madskjeldgaard, @elgiano
|
||||
[superhtml](https://github.com/kristoff-it/superhtml) | unstable | `H J ` | @rockorager
|
||||
[surface](https://github.com/connorlay/tree-sitter-surface) | unstable | `HFIJ ` | @connorlay
|
||||
[svelte](https://github.com/tree-sitter-grammars/tree-sitter-svelte) | unstable | `HFIJL` | @amaanq
|
||||
[sway](https://github.com/FuelLabs/tree-sitter-sway.git) | unstable | `HFIJL` | @ribru17
|
||||
[swift](https://github.com/alex-pinkus/tree-sitter-swift) | unstable | `HFIJL` | @alex-pinkus
|
||||
[sxhkdrc](https://github.com/RaafatTurki/tree-sitter-sxhkdrc) | unstable | `HF J ` | @RaafatTurki
|
||||
[systemtap](https://github.com/ok-ryoko/tree-sitter-systemtap) | unstable | `HF JL` | @ok-ryoko
|
||||
[systemverilog](https://github.com/gmlarumbe/tree-sitter-systemverilog) | unstable | `HF J ` | @zhangwwpeng
|
||||
[t32](https://github.com/xasc/tree-sitter-t32) | unstable | `HFIJL` | @xasc
|
||||
[tablegen](https://github.com/tree-sitter-grammars/tree-sitter-tablegen) | unstable | `HFIJL` | @amaanq
|
||||
[tact](https://github.com/tact-lang/tree-sitter-tact) | unstable | `HFIJL` | @novusnota
|
||||
[tcl](https://github.com/tree-sitter-grammars/tree-sitter-tcl) | unstable | `HFIJ ` | @lewis6991
|
||||
[teal](https://github.com/euclidianAce/tree-sitter-teal) | unstable | `HFIJL` | @euclidianAce
|
||||
[templ](https://github.com/vrischmann/tree-sitter-templ) | unstable | `HF J ` | @vrischmann
|
||||
[tera](https://github.com/uncenter/tree-sitter-tera) | unstable | `H J ` | @uncenter
|
||||
[terraform](https://github.com/MichaHoffmann/tree-sitter-hcl) | unstable | `HFIJ ` | @MichaHoffmann
|
||||
[textproto](https://github.com/PorterAtGoogle/tree-sitter-textproto) | unstable | `HFIJ ` | @Porter
|
||||
[thrift](https://github.com/tree-sitter-grammars/tree-sitter-thrift) | unstable | `HFIJL` | @amaanq, @duskmoon314
|
||||
[tiger](https://github.com/ambroisie/tree-sitter-tiger) | unstable | `HFIJL` | @ambroisie
|
||||
[tlaplus](https://github.com/tlaplus-community/tree-sitter-tlaplus) | unstable | `HF JL` | @ahelwer, @susliko
|
||||
[tmux](https://github.com/Freed-Wu/tree-sitter-tmux) | unstable | `H J ` | @Freed-Wu, @stevenxxiu
|
||||
[todotxt](https://github.com/arnarg/tree-sitter-todotxt) | unstable | `H ` | @arnarg
|
||||
[toml](https://github.com/tree-sitter-grammars/tree-sitter-toml) | unstable | `HFIJL` | @tk-shirasaka
|
||||
[tsv](https://github.com/tree-sitter-grammars/tree-sitter-csv) | unstable | `H ` | @amaanq
|
||||
[tsx](https://github.com/tree-sitter/tree-sitter-typescript) | unstable | `HFIJL` | @steelsojka
|
||||
[turtle](https://github.com/GordianDziwis/tree-sitter-turtle) | unstable | `HFIJL` | @GordianDziwis
|
||||
[twig](https://github.com/gbprod/tree-sitter-twig) | unstable | `H J ` | @gbprod
|
||||
[typescript](https://github.com/tree-sitter/tree-sitter-typescript) | unstable | `HFIJL` | @steelsojka
|
||||
[typespec](https://github.com/happenslol/tree-sitter-typespec) | unstable | `H IJ ` | @happenslol
|
||||
[typoscript](https://github.com/Teddytrombone/tree-sitter-typoscript) | unstable | `HFIJ ` | @Teddytrombone
|
||||
[typst](https://github.com/uben0/tree-sitter-typst) | unstable | `HFIJ ` | @uben0, @RaafatTurki
|
||||
[udev](https://github.com/tree-sitter-grammars/tree-sitter-udev) | unstable | `H JL` | @ObserverOfTime
|
||||
[ungrammar](https://github.com/tree-sitter-grammars/tree-sitter-ungrammar) | unstable | `HFIJL` | @Philipp-M, @amaanq
|
||||
[unison](https://github.com/kylegoetz/tree-sitter-unison) | unstable | `HF J ` | @tapegram
|
||||
[usd](https://github.com/ColinKennedy/tree-sitter-usd) | unstable | `HFIJL` | @ColinKennedy
|
||||
[uxntal](https://github.com/tree-sitter-grammars/tree-sitter-uxntal) | unstable | `HFIJL` | @amaanq
|
||||
[v](https://github.com/vlang/v-analyzer) | unstable | `HFIJL` | @kkharji, @amaanq
|
||||
[vala](https://github.com/vala-lang/tree-sitter-vala) | unstable | `HF J ` | @Prince781
|
||||
[vento](https://github.com/ventojs/tree-sitter-vento) | unmaintained | `H J ` |
|
||||
[vhdl](https://github.com/jpt13653903/tree-sitter-vhdl) | unstable | `HF J ` | @jpt13653903
|
||||
[vhs](https://github.com/charmbracelet/tree-sitter-vhs) | unstable | `H J ` | @caarlos0
|
||||
[vim](https://github.com/tree-sitter-grammars/tree-sitter-vim) | unstable | `HF JL` | @clason
|
||||
[vimdoc](https://github.com/neovim/tree-sitter-vimdoc) | unstable | `H J ` | @clason
|
||||
[vrl](https://github.com/belltoy/tree-sitter-vrl) | unstable | `HFIJL` | @belltoy
|
||||
[vue](https://github.com/tree-sitter-grammars/tree-sitter-vue) | unstable | `HFIJ ` | @WhyNotHugo, @lucario387
|
||||
[wgsl](https://github.com/szebniok/tree-sitter-wgsl) | unstable | `HFIJ ` | @szebniok
|
||||
[wgsl_bevy](https://github.com/tree-sitter-grammars/tree-sitter-wgsl-bevy) | unstable | `HFI ` | @theHamsta
|
||||
[wing](https://github.com/winglang/tree-sitter-wing) | unstable | `HF JL` | @gshpychka, @MarkMcCulloh
|
||||
[wit](https://github.com/bytecodealliance/tree-sitter-wit) | stable | `HF J ` | @mkatychev
|
||||
[wxml](https://github.com/BlockLune/tree-sitter-wxml) | unstable | `HFIJ ` | @BlockLune
|
||||
[xcompose](https://github.com/tree-sitter-grammars/tree-sitter-xcompose) | unstable | `H JL` | @ObserverOfTime
|
||||
[xml](https://github.com/tree-sitter-grammars/tree-sitter-xml) | unstable | `HFIJL` | @ObserverOfTime
|
||||
[xresources](https://github.com/ValdezFOmar/tree-sitter-xresources) | stable | `HF JL` | @ValdezFOmar
|
||||
[yaml](https://github.com/tree-sitter-grammars/tree-sitter-yaml) | unstable | `HFIJL` | @amaanq
|
||||
[yang](https://github.com/Hubro/tree-sitter-yang) | unstable | `HFIJ ` | @Hubro
|
||||
[yuck](https://github.com/tree-sitter-grammars/tree-sitter-yuck) | unstable | `HFIJL` | @Philipp-M, @amaanq
|
||||
[zathurarc](https://github.com/Freed-Wu/tree-sitter-zathurarc) | unstable | `H J ` | @Freed-Wu
|
||||
[zig](https://github.com/tree-sitter-grammars/tree-sitter-zig) | unstable | `HFIJL` | @amaanq
|
||||
[ziggy](https://github.com/kristoff-it/ziggy) | unmaintained | `H I ` |
|
||||
[ziggy_schema](https://github.com/kristoff-it/ziggy) | unmaintained | `H I ` |
|
||||
[zsh](https://github.com/georgeharker/tree-sitter-zsh) | unstable | `HF JL` | @georgeharker
|
||||
[^bp]: Android Blueprint
|
||||
[^ecma]: queries required by javascript, typescript, tsx, qmljs
|
||||
[^gap]: GAP system
|
||||
[^gaptst]: GAP system test files
|
||||
[^gdscript]: Godot
|
||||
[^glimmer]: Glimmer and Ember
|
||||
[^godot_resource]: Godot Resources
|
||||
[^html_tags]: queries required by html, astro, vue, svelte
|
||||
[^jinja]: basic highlighting
|
||||
[^jinja_inline]: needed for full highlighting
|
||||
[^jsx]: queries required by javascript, tsx
|
||||
[^luap]: Lua patterns
|
||||
[^markdown]: basic highlighting
|
||||
[^markdown_inline]: needed for full highlighting
|
||||
[^php]: PHP with embedded HTML
|
||||
[^php_only]: PHP without embedded HTML
|
||||
[^poe_filter]: Path of Exile item filter
|
||||
[^properties]: Java properties files
|
||||
[^query]: Tree-sitter query language
|
||||
[^sflog]: Salesforce debug log
|
||||
[^slang]: Shader Slang
|
||||
[^snl]: EPICS Sequencer's SNL files
|
||||
<!--parserinfo-->
|
||||
BIN
assets/logo.png
BIN
assets/logo.png
Binary file not shown.
|
Before Width: | Height: | Size: 26 KiB |
|
|
@ -1,27 +0,0 @@
|
|||
function! nvim_treesitter#statusline(...) abort
|
||||
return luaeval("require'nvim-treesitter.statusline'.statusline(_A)", get(a:, 1, {}))
|
||||
endfunction
|
||||
|
||||
function! nvim_treesitter#foldexpr() abort
|
||||
return luaeval(printf('require"nvim-treesitter.fold".get_fold_indic(%d)', v:lnum))
|
||||
endfunction
|
||||
|
||||
function! nvim_treesitter#installable_parsers(arglead, cmdline, cursorpos) abort
|
||||
return join(luaeval("require'nvim-treesitter.parsers'.available_parsers()") + ['all'], "\n")
|
||||
endfunction
|
||||
|
||||
function! nvim_treesitter#installed_parsers(arglead, cmdline, cursorpos) abort
|
||||
return join(luaeval("require'nvim-treesitter.info'.installed_parsers()") + ['all'], "\n")
|
||||
endfunction
|
||||
|
||||
function! nvim_treesitter#available_modules(arglead, cmdline, cursorpos) abort
|
||||
return join(luaeval("require'nvim-treesitter.configs'.available_modules()"), "\n")
|
||||
endfunction
|
||||
|
||||
function! nvim_treesitter#available_query_groups(arglead, cmdline, cursorpos) abort
|
||||
return join(luaeval("require'nvim-treesitter.query'.available_query_groups()"), "\n")
|
||||
endfunction
|
||||
|
||||
function! nvim_treesitter#indent() abort
|
||||
return luaeval(printf('require"nvim-treesitter.indent".get_indent(%d)', v:lnum))
|
||||
endfunction
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
local git_ref = '$git_ref'
|
||||
local modrev = '$modrev'
|
||||
local specrev = '-1'
|
||||
|
||||
local repo_url = '$repo_url'
|
||||
|
||||
rockspec_format = '3.0'
|
||||
package = '$package'
|
||||
version = modrev .. specrev
|
||||
|
||||
description = {
|
||||
summary = 'Nvim Treesitter configurations and abstraction layer',
|
||||
detailed = $detailed_description,
|
||||
labels = { 'neovim' },
|
||||
homepage = 'https://github.com/nvim-treesitter/nvim-treesitter',
|
||||
license = 'Apache-2.0',
|
||||
}
|
||||
|
||||
dependencies = {
|
||||
'lua >= 5.1',
|
||||
}
|
||||
|
||||
-- source = file:///.
|
||||
|
||||
source = {
|
||||
url = repo_url .. '/archive/' .. git_ref .. '.zip',
|
||||
dir = '$repo_name-' .. '$archive_dir_suffix',
|
||||
}
|
||||
|
||||
build = {
|
||||
type = 'make',
|
||||
build_pass = false,
|
||||
install_variables = {
|
||||
INST_PREFIX='$(PREFIX)',
|
||||
INST_BINDIR='$(BINDIR)',
|
||||
INST_LIBDIR='$(LIBDIR)',
|
||||
INST_LUADIR='$(LUADIR)',
|
||||
INST_CONFDIR='$(CONFDIR)',
|
||||
},
|
||||
copy_directories = $copy_directories,
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
local MODREV, SPECREV = 'scm', '-1'
|
||||
rockspec_format = '3.0'
|
||||
package = 'nvim-treesitter'
|
||||
version = MODREV .. SPECREV
|
||||
|
||||
description = {
|
||||
summary = 'Nvim Treesitter configurations and abstraction layer',
|
||||
labels = { 'neovim' },
|
||||
homepage = 'https://github.com/nvim-treesitter/nvim-treesitter',
|
||||
license = 'Apache-2.0',
|
||||
}
|
||||
|
||||
dependencies = {
|
||||
'lua >= 5.1',
|
||||
}
|
||||
|
||||
source = {
|
||||
url = 'git://github.com/nvim-treesitter/nvim-treesitter',
|
||||
}
|
||||
|
||||
build = {
|
||||
type = 'make',
|
||||
install_variables = {
|
||||
INST_PREFIX='$(PREFIX)',
|
||||
INST_BINDIR='$(BINDIR)',
|
||||
INST_LIBDIR='$(LIBDIR)',
|
||||
INST_LUADIR='$(LUADIR)',
|
||||
INST_CONFDIR='$(CONFDIR)',
|
||||
},
|
||||
copy_directories = {
|
||||
'autoload',
|
||||
'doc',
|
||||
'plugin',
|
||||
'queries'
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,4 @@
|
|||
*nvim-treesitter* Treesitter configurations and abstraction layer for Neovim.
|
||||
|
||||
Minimum version of neovim: nightly
|
||||
*nvim-treesitter.txt* Treesitter parser and query installer for Neovim
|
||||
|
||||
Authors:
|
||||
Kiyan Yazdani <yazdani.kiyan@protonmail.com>
|
||||
|
|
@ -13,578 +11,179 @@ Authors:
|
|||
Type |gO| to see the table of contents.
|
||||
|
||||
==============================================================================
|
||||
INTRODUCTION *nvim-treesitter-intro*
|
||||
INTRODUCTION *nvim-treesitter-intro*
|
||||
|
||||
nvim-treesitter wraps the Neovim treesitter API to provide functionalities
|
||||
such as highlighting and incremental selection, and a command to easily
|
||||
install parsers.
|
||||
Nvim-treesitter provides functionalities for managing treesitter parsers and
|
||||
compatible queries for core features (highlighting, injections, folds,
|
||||
indents).
|
||||
|
||||
==============================================================================
|
||||
QUICK START *nvim-treesitter-quickstart*
|
||||
QUICK START *nvim-treesitter-quickstart*
|
||||
|
||||
Install the parser for your language
|
||||
|
||||
>
|
||||
:TSInstall {language}
|
||||
<
|
||||
|
||||
To get a list of supported languages
|
||||
|
||||
>
|
||||
:TSInstallInfo
|
||||
<
|
||||
|
||||
By default, everything is disabled.
|
||||
To enable supported features, put this in your `init.lua` file:
|
||||
|
||||
>
|
||||
require'nvim-treesitter.configs'.setup {
|
||||
-- A directory to install the parsers into.
|
||||
-- If this is excluded or nil parsers are installed
|
||||
-- to either the package dir, or the "site" dir.
|
||||
-- If a custom path is used (not nil) it must be added to the runtimepath.
|
||||
parser_install_dir = "/some/path/to/store/parsers",
|
||||
|
||||
-- A list of parser names, or "all"
|
||||
ensure_installed = { "c", "lua", "rust" },
|
||||
|
||||
-- Install parsers synchronously (only applied to `ensure_installed`)
|
||||
sync_install = false,
|
||||
|
||||
-- Automatically install missing parsers when entering buffer
|
||||
auto_install = false,
|
||||
|
||||
-- List of parsers to ignore installing (for "all")
|
||||
ignore_install = { "javascript" },
|
||||
|
||||
highlight = {
|
||||
-- `false` will disable the whole extension
|
||||
enable = true,
|
||||
|
||||
-- list of language that will be disabled
|
||||
disable = { "c", "rust" },
|
||||
|
||||
-- Setting this to true will run `:h syntax` and tree-sitter at the same time.
|
||||
-- Set this to `true` if you depend on 'syntax' being enabled (like for indentation).
|
||||
-- Using this option may slow down your editor, and you may see some duplicate highlights.
|
||||
-- Instead of true it can also be a list of languages
|
||||
additional_vim_regex_highlighting = false,
|
||||
},
|
||||
To configure `nvim-treesitter`, put this in your `init.lua` file:
|
||||
>lua
|
||||
require'nvim-treesitter'.setup {
|
||||
-- A directory to install the parsers and queries to.
|
||||
-- Defaults to the `stdpath('data')/site` dir.
|
||||
install_dir = "/some/path/to/store/parsers",
|
||||
}
|
||||
vim.opt.runtimepath:append("/some/path/to/store/parsers")
|
||||
<
|
||||
|
||||
See |nvim-treesitter-modules| for a list of all available modules and its options.
|
||||
NOTE: You do not need to call `setup` to use this plugin with the default
|
||||
settings!
|
||||
|
||||
Parsers and queries can then be installed with >lua
|
||||
require'nvim-treesitter'.install { 'rust', 'javascript', 'zig' }
|
||||
<
|
||||
To check installed parsers and queries, use `:checkhealth nvim-treesitter`.
|
||||
|
||||
Treesitter features for installed languages need to be enabled manually in a
|
||||
|FileType| autocommand or |ftplugin|, e.g. >lua
|
||||
vim.api.nvim_create_autocmd('FileType', {
|
||||
pattern = { 'rust', 'javascript', 'zig' },
|
||||
callback = function()
|
||||
-- syntax highlighting, provided by Neovim
|
||||
vim.treesitter.start()
|
||||
-- folds, provided by Neovim
|
||||
vim.wo.foldexpr = 'v:lua.vim.treesitter.foldexpr()'
|
||||
vim.wo.foldmethod = 'expr'
|
||||
-- indentation, provided by nvim-treesitter
|
||||
vim.bo.indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()"
|
||||
end,
|
||||
})
|
||||
<
|
||||
==============================================================================
|
||||
COMMANDS *nvim-treesitter-commands*
|
||||
|
||||
:TSInstall {language} *:TSInstall*
|
||||
|
||||
Install one or more treesitter parsers. {language} can be one or multiple
|
||||
parsers or tiers (`stable`, `unstable`, or `all` (not recommended)). This is a
|
||||
no-op if the parser(s) are already installed. Installation is performed
|
||||
asynchronously. Use *:TSInstall!* to force installation even if a parser is
|
||||
already installed.
|
||||
|
||||
:TSInstallFromGrammar {language} *:TSInstallFromGrammar*
|
||||
|
||||
Like |:TSInstall| but also regenerates the `parser.c` from the original
|
||||
grammar. Useful for languages where the provided `parser.c` is outdated (e.g.,
|
||||
uses a no longer supported ABI).
|
||||
|
||||
:TSUpdate [{language}] *:TSUpdate*
|
||||
|
||||
Update parsers to the `revision` specified in the manifest if this is newer
|
||||
than the installed version. If {language} is specified, update the
|
||||
corresponding parser or tier; otherwise update all installed parsers. This is
|
||||
a no-op if all (specified) parsers are up to date.
|
||||
|
||||
Note: It is recommended to add this command as a build step in your plugin
|
||||
manager.
|
||||
|
||||
:TSUninstall {language} *:TSUninstall*
|
||||
|
||||
Deletes the parser for one or more {language}, or all parsers with `all`.
|
||||
|
||||
:TSLog *:TSLog*
|
||||
|
||||
Shows all messages from previous install, update, or uninstall operations.
|
||||
|
||||
==============================================================================
|
||||
MODULES *nvim-treesitter-modules*
|
||||
API *nvim-treesitter-api*
|
||||
|
||||
|nvim-treesitter| provides several functionalities via modules (and submodules),
|
||||
each module makes use of the query files defined for each language,
|
||||
setup({opts}) *nvim-treesitter.setup()*
|
||||
|
||||
All modules are disabled by default, and some provide default keymaps.
|
||||
Each module corresponds to an entry in the dictionary passed to the
|
||||
`nvim-treesitter.configs.setup` function, this should be in your `init.lua` file.
|
||||
Configure installation options. Needs to be specified before any
|
||||
installation operation.
|
||||
|
||||
>
|
||||
require'nvim-treesitter.configs'.setup {
|
||||
-- Modules and its options go here
|
||||
highlight = { enable = true },
|
||||
incremental_selection = { enable = true },
|
||||
textobjects = { enable = true },
|
||||
}
|
||||
Note: You only need to call `setup` if you want to set non-default
|
||||
options!
|
||||
|
||||
Parameters: ~
|
||||
• {opts} `(table?)` Optional parameters:
|
||||
• {install_dir} (`string?`, default `stdpath('data')/site/`)
|
||||
directory to install parsers and queries to. Note: will be
|
||||
prepended to |runtimepath|.
|
||||
|
||||
install({languages} [, {opts}]) *nvim-treesitter.install()*
|
||||
|
||||
Download, compile, and install the specified treesitter parsers and copy
|
||||
the corresponding queries to a directory on |runtimepath|, enabling their
|
||||
use in Neovim.
|
||||
|
||||
Note: This operation is performed asynchronously by default. For
|
||||
synchronous operation (e.g., in a bootstrapping script), you need to
|
||||
`wait()` for it: >lua
|
||||
require('nvim-treesitter').install({ 'rust', 'javascript', 'zig' })
|
||||
:wait(300000) -- max. 5 minutes
|
||||
<
|
||||
Parameters: ~
|
||||
• {languages} `(string[]|string)` (List of) languages or tiers (`stable`,
|
||||
`unstable`) to install.
|
||||
• {opts} `(table?)` Optional parameters:
|
||||
• {force} (`boolean?`, default `false`) force installation
|
||||
of already installed parsers
|
||||
• {generate} (`boolean?`, default `false`) generate
|
||||
`parser.c` from `grammar.json` or `grammar.js` before
|
||||
compiling.
|
||||
• {max_jobs} (`integer?`) limit parallel tasks (useful in
|
||||
combination with {generate} on memory-limited systems).
|
||||
• {summary} (`boolean?`, default `false`) print summary of
|
||||
successful and total operations for multiple languages.
|
||||
|
||||
All modules share some common options, like `enable` and `disable`.
|
||||
When `enable` is `true` this will enable the module for all supported languages,
|
||||
if you want to disable the module for some languages you can pass a list to the `disable` option.
|
||||
uninstall({languages} [, {opts}]) *nvim-treesitter.uninstall()*
|
||||
|
||||
>
|
||||
require'nvim-treesitter.configs'.setup {
|
||||
highlight = {
|
||||
enable = true,
|
||||
disable = { "cpp", "lua" },
|
||||
},
|
||||
}
|
||||
Remove the parser and queries for the specified language(s).
|
||||
|
||||
Parameters: ~
|
||||
• {languages} `(string[]|string)` (List of) languages or tiers (`stable`,
|
||||
`unstable`) to update.
|
||||
• {opts} `(table?)` Optional parameters:
|
||||
• {summary} (`boolean?`, default `false`) print summary of
|
||||
successful and total operations for multiple languages.
|
||||
|
||||
update([{languages}, {opts}]) *nvim-treesitter.update()*
|
||||
|
||||
Update the parsers and queries if older than the revision specified in the
|
||||
manifest.
|
||||
|
||||
Note: This operation is performed asynchronously by default. For
|
||||
synchronous operation (e.g., in a bootstrapping script), you need to
|
||||
`wait()` for it: >lua
|
||||
require('nvim-treesitter').update():wait(300000) -- max. 5 minutes
|
||||
<
|
||||
Parameters: ~
|
||||
• {languages} `(string[]|string)?` (List of) languages or tiers to update
|
||||
(default: all installed).
|
||||
• {opts} `(table?)` Optional parameters:
|
||||
• {max_jobs} (`integer?`) limit parallel tasks (useful in
|
||||
combination with {generate} on memory-limited systems).
|
||||
• {summary} (`boolean?`, default `false`) print summary of
|
||||
successful and total operations for multiple languages.
|
||||
|
||||
For more fine-grained control, `disable` can also take a function and
|
||||
whenever it returns `true`, the module is disabled for that buffer.
|
||||
The function is called once when a module starts in a buffer and receives the
|
||||
language and buffer number as arguments:
|
||||
indentexpr() *nvim-treesitter.indentexpr()*
|
||||
|
||||
>
|
||||
require'nvim-treesitter.configs'.setup {
|
||||
highlight = {
|
||||
enable = true,
|
||||
disable = function(lang, bufnr) -- Disable in large C++ buffers
|
||||
return lang == "cpp" and vim.api.nvim_buf_line_count(bufnr) > 50000
|
||||
end,
|
||||
},
|
||||
}
|
||||
Used to enable treesitter indentation for a language via >lua
|
||||
vim.bo.indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()"
|
||||
<
|
||||
get_available([{tier}]) *nvim-treesitter.get_available()*
|
||||
|
||||
Options that define or accept a keymap use the same format you use to define
|
||||
keymaps in Neovim, so you can write keymaps as `gd`, `<space>a`, `<leader>a`
|
||||
`<C-a>` (control + a), `<A-n>` (alt + n), `<CR>` (enter), etc.
|
||||
Return list of languages available for installation.
|
||||
|
||||
External plugins can provide their own modules with their own options,
|
||||
those can also be configured using the `nvim-treesitter.configs.setup`
|
||||
function.
|
||||
Parameters: ~
|
||||
• {tier} `(integer?)` Only return languages of specified {tier} (`1`:
|
||||
stable, `2`: unstable, `3`: unmaintained, `4`: unsupported)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
HIGHLIGHT *nvim-treesitter-highlight-mod*
|
||||
get_installed([{type}]) *nvim-treesitter.get_installed()*
|
||||
|
||||
Consistent syntax highlighting.
|
||||
Return list of languages installed via `nvim-treesitter`.
|
||||
|
||||
Query files: `highlights.scm`.
|
||||
Supported options:
|
||||
|
||||
- enable: `true` or `false`.
|
||||
- disable: list of languages.
|
||||
- additional_vim_regex_highlighting: `true` or `false`, or a list of languages.
|
||||
Set this to `true` if you depend on 'syntax' being enabled
|
||||
(like for indentation). Using this option may slow down your editor,
|
||||
and you may see some duplicate highlights.
|
||||
Defaults to `false`.
|
||||
|
||||
>
|
||||
require'nvim-treesitter.configs'.setup {
|
||||
highlight = {
|
||||
enable = true,
|
||||
custom_captures = {
|
||||
-- Highlight the @foo.bar capture group with the "Identifier" highlight group.
|
||||
["foo.bar"] = "Identifier",
|
||||
},
|
||||
-- Setting this to true or a list of languages will run `:h syntax` and tree-sitter at the same time.
|
||||
additional_vim_regex_highlighting = false,
|
||||
},
|
||||
}
|
||||
Note: This only searches `nvim-treesitter`'s (configured or default)
|
||||
installation directory; parsers and queries from other sources can be
|
||||
placed anywhere on 'runtimepath' and are not included. To list all, e.g.,
|
||||
parsers that are installed from any source, use >lua
|
||||
vim.api.nvim_get_runtime_file('parser/*', true)
|
||||
<
|
||||
|
||||
You can also set custom highlight captures
|
||||
>
|
||||
lua <<EOF
|
||||
require"nvim-treesitter.highlight".set_custom_captures {
|
||||
-- Highlight the @foo.bar capture group with the "Identifier" highlight group.
|
||||
["foo.bar"] = "Identifier",
|
||||
}
|
||||
EOF
|
||||
<
|
||||
Note: The api is not stable yet.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
INCREMENTAL SELECTION *nvim-treesitter-incremental-selection-mod*
|
||||
|
||||
Incremental selection based on the named nodes from the grammar.
|
||||
|
||||
Query files: `locals.scm`.
|
||||
Supported options:
|
||||
- enable: `true` or `false`.
|
||||
- disable: list of languages.
|
||||
- keymaps:
|
||||
- init_selection: in normal mode, start incremental selection.
|
||||
Defaults to `gnn`.
|
||||
- node_incremental: in visual mode, increment to the upper named parent.
|
||||
Defaults to `grn`.
|
||||
- scope_incremental: in visual mode, increment to the upper scope
|
||||
(as defined in `locals.scm`). Defaults to `grc`.
|
||||
- node_decremental: in visual mode, decrement to the previous named node.
|
||||
Defaults to `grm`.
|
||||
|
||||
>
|
||||
require'nvim-treesitter.configs'.setup {
|
||||
incremental_selection = {
|
||||
enable = true,
|
||||
keymaps = {
|
||||
init_selection = "gnn",
|
||||
node_incremental = "grn",
|
||||
scope_incremental = "grc",
|
||||
node_decremental = "grm",
|
||||
},
|
||||
},
|
||||
}
|
||||
<
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
INDENTATION *nvim-treesitter-indentation-mod*
|
||||
|
||||
Indentation based on treesitter for the |=| operator.
|
||||
NOTE: this is an experimental feature.
|
||||
|
||||
Query files: `indents.scm`.
|
||||
Supported options:
|
||||
- enable: `true` or `false`.
|
||||
- disable: list of languages.
|
||||
>
|
||||
require'nvim-treesitter.configs'.setup {
|
||||
indent = {
|
||||
enable = true
|
||||
},
|
||||
}
|
||||
|
||||
`@indent` *nvim-treesitter-indentation-queries*
|
||||
Queries can use the following captures: `@indent.begin` and `@indent.dedent`,
|
||||
`@indent.branch`, `@indent.end` or `@indent.align`. An `@indent.ignore` capture tells
|
||||
treesitter to ignore indentation and a `@indent.zero` capture sets
|
||||
the indentation to 0.
|
||||
|
||||
`@indent.begin` *nvim-treesitter-indentation-indent.begin*
|
||||
The `@indent.begin` specifies that the next line should be indented. Multiple
|
||||
indents on the same line get collapsed. Eg.
|
||||
|
||||
>
|
||||
(
|
||||
(if_statement)
|
||||
(ERROR "else") @indent.begin
|
||||
)
|
||||
<
|
||||
Indent can also have `indent.immediate` set using a `#set!` directive, which
|
||||
permits the next line to indent even when the block intended to be indented
|
||||
has no content yet, improving interactive typing.
|
||||
|
||||
eg for python:
|
||||
>
|
||||
((if_statement) @indent.begin
|
||||
(#set! indent.immediate 1))
|
||||
<
|
||||
|
||||
Will allow:
|
||||
>
|
||||
if True:<CR>
|
||||
# Auto indent to here
|
||||
|
||||
`@indent.end` *nvim-treesitter-indentation-indent.end*
|
||||
An `@indent.end` capture is used to specify that the indented region ends and
|
||||
any text subsequent to the capture should be dedented.
|
||||
|
||||
`@indent.branch` *nvim-treesitter-indentation-indent.branch*
|
||||
An `@indent.branch` capture is used to specify that a dedented region starts
|
||||
at the line including the captured nodes.
|
||||
|
||||
`@indent.dedent` *nvim-treesitter-indentation-indent.dedent*
|
||||
A `@indent.dedent` capture specifies dedenting starting on the next line.
|
||||
>
|
||||
`@indent.align` *nvim-treesitter-indentation-aligned_indent.align*
|
||||
Aligned indent blocks may be specified with the `@indent.align` capture.
|
||||
This permits
|
||||
|
||||
>
|
||||
foo(a,
|
||||
b,
|
||||
c)
|
||||
<
|
||||
As well as
|
||||
>
|
||||
foo(
|
||||
a,
|
||||
b,
|
||||
c)
|
||||
<
|
||||
and finally
|
||||
>
|
||||
foo(
|
||||
a,
|
||||
b,
|
||||
c
|
||||
)
|
||||
<
|
||||
To specify the delimiters to use `indent.open_delimiter` and
|
||||
`indent.close_delimiter` should be used. Eg.
|
||||
>
|
||||
((argument_list) @indent.align
|
||||
(#set! indent.open_delimiter "(")
|
||||
(#set! indent.close_delimiter ")"))
|
||||
<
|
||||
|
||||
For some languages the last line of an `indent.align` block must not be
|
||||
the same indent as the natural next line.
|
||||
|
||||
For example in python:
|
||||
|
||||
>
|
||||
if (a > b and
|
||||
c < d):
|
||||
pass
|
||||
|
||||
Is not correct, whereas
|
||||
>
|
||||
if (a > b and
|
||||
c < d):
|
||||
pass
|
||||
|
||||
Would be correctly indented. This behavior may be chosen using
|
||||
`indent.avoid_last_matching_next`. Eg.
|
||||
|
||||
>
|
||||
(if_statement
|
||||
condition: (parenthesized_expression) @indent.align
|
||||
(#set! indent.open_delimiter "(")
|
||||
(#set! indent.close_delimiter ")")
|
||||
(#set! indent.avoid_last_matching_next 1)
|
||||
)
|
||||
<
|
||||
Could be used to specify that the last line of an `@indent.align` capture
|
||||
should be additionally indented to avoid clashing with the indent of the first
|
||||
line of the block inside an if.
|
||||
|
||||
==============================================================================
|
||||
COMMANDS *nvim-treesitter-commands*
|
||||
|
||||
*:TSInstall*
|
||||
:TSInstall {language} ...~
|
||||
|
||||
Install one or more treesitter parsers.
|
||||
You can use |:TSInstall| `all` to install all parsers. Use |:TSInstall!| to
|
||||
force the reinstallation of already installed parsers.
|
||||
*:TSInstallSync*
|
||||
:TSInstallSync {language} ...~
|
||||
|
||||
Perform the |:TSInstall| operation synchronously.
|
||||
|
||||
*:TSInstallInfo*
|
||||
:TSInstallInfo~
|
||||
|
||||
List information about currently installed parsers
|
||||
|
||||
*:TSUpdate*
|
||||
:TSUpdate {language} ...~
|
||||
|
||||
Update the installed parser for one more {language} or all installed parsers
|
||||
if {language} is omitted. The specified parser is installed if it is not already
|
||||
installed.
|
||||
|
||||
*:TSUpdateSync*
|
||||
:TSUpdateSync {language} ...~
|
||||
|
||||
Perform the |:TSUpdate| operation synchronously.
|
||||
|
||||
*:TSUninstall*
|
||||
:TSUninstall {language} ...~
|
||||
|
||||
Deletes the parser for one or more {language}. You can use 'all' for language
|
||||
to uninstall all parsers.
|
||||
|
||||
*:TSBufEnable*
|
||||
:TSBufEnable {module}~
|
||||
|
||||
Enable {module} on the current buffer.
|
||||
A list of modules can be found at |:TSModuleInfo|
|
||||
|
||||
*:TSBufDisable*
|
||||
:TSBufDisable {module}~
|
||||
|
||||
Disable {module} on the current buffer.
|
||||
A list of modules can be found at |:TSModuleInfo|
|
||||
|
||||
*:TSBufToggle*
|
||||
:TSBufToggle {module}~
|
||||
|
||||
Toggle (enable if disabled, disable if enabled) {module} on the current
|
||||
buffer.
|
||||
A list of modules can be found at |:TSModuleInfo|
|
||||
|
||||
*:TSEnable*
|
||||
:TSEnable {module} [{language}]~
|
||||
|
||||
Enable {module} for the session.
|
||||
If {language} is specified, enable module for the session only for this
|
||||
particular language.
|
||||
A list of modules can be found at |:TSModuleInfo|
|
||||
A list of languages can be found at |:TSInstallInfo|
|
||||
|
||||
*:TSDisable*
|
||||
:TSDisable {module} [{language}]~
|
||||
|
||||
Disable {module} for the session.
|
||||
If {language} is specified, disable module for the session only for this
|
||||
particular language.
|
||||
A list of modules can be found at |:TSModuleInfo|
|
||||
A list of languages can be found at |:TSInstallInfo|
|
||||
|
||||
*:TSToggle*
|
||||
:TSToggle {module} [{language}]~
|
||||
|
||||
Toggle (enable if disabled, disable if enabled) {module} for the session.
|
||||
If {language} is specified, toggle module for the session only for this
|
||||
particular language.
|
||||
A list of modules can be found at |:TSModuleInfo|
|
||||
A list of languages can be found at |:TSInstallInfo|
|
||||
|
||||
*:TSModuleInfo*
|
||||
:TSModuleInfo [{module}]~
|
||||
|
||||
List the state for the given module or all modules for the current session in
|
||||
a new buffer.
|
||||
|
||||
These highlight groups are used by default:
|
||||
>
|
||||
highlight default TSModuleInfoGood guifg=LightGreen gui=bold
|
||||
highlight default TSModuleInfoBad guifg=Crimson
|
||||
highlight default link TSModuleInfoHeader Type
|
||||
highlight default link TSModuleInfoNamespace Statement
|
||||
highlight default link TSModuleInfoParser Identifier
|
||||
<
|
||||
|
||||
*:TSEditQuery*
|
||||
:TSEditQuery {query-group} [{lang}]~
|
||||
|
||||
Edit the query file for a {query-group} (e.g. highlights, locals) for given
|
||||
{lang}. If there are multiple files, the user is prompted to select one of them.
|
||||
If no such file exists, a buffer for a new file in the user's config directory
|
||||
is created. If {lang} is not specified, the language of the current buffer
|
||||
is used.
|
||||
|
||||
*:TSEditQueryUserAfter*
|
||||
:TSEditQueryUserAfter {query-group} [{lang}]~
|
||||
|
||||
Same as |:TSEditQuery| but edits a file in the `after` directory of the
|
||||
user's config directory. Useful to add custom extensions for the queries
|
||||
provided by a plugin.
|
||||
|
||||
==============================================================================
|
||||
UTILS *nvim-treesitter-utils*
|
||||
|
||||
Nvim treesitter has some wrapper functions that you can retrieve with:
|
||||
>
|
||||
local ts_utils = require 'nvim-treesitter.ts_utils'
|
||||
<
|
||||
Methods
|
||||
*ts_utils.get_node_at_cursor*
|
||||
get_node_at_cursor(winnr)~
|
||||
|
||||
`winnr` will be 0 if nil.
|
||||
Returns the node under the cursor.
|
||||
|
||||
*ts_utils.is_parent*
|
||||
is_parent(dest, source)~
|
||||
|
||||
Determines whether `dest` is a parent of `source`.
|
||||
Returns a boolean.
|
||||
|
||||
*ts_utils.get_named_children*
|
||||
get_named_children(node)~
|
||||
|
||||
Returns a table of named children of `node`.
|
||||
|
||||
*ts_utils.get_next_node*
|
||||
get_next_node(node, allow_switch_parent, allow_next_parent)~
|
||||
|
||||
Returns the next node within the same parent.
|
||||
If no node is found, returns `nil`.
|
||||
If `allow_switch_parent` is true, it will allow switching parent
|
||||
when the node is the last node.
|
||||
If `allow_next_parent` is true, it will allow next parent if
|
||||
the node is the last node and the next parent doesn't have children.
|
||||
|
||||
*ts_utils.get_previous_node*
|
||||
get_previous_node(node, allow_switch_parents, allow_prev_parent)~
|
||||
|
||||
Returns the previous node within the same parent.
|
||||
`allow_switch_parent` and `allow_prev_parent` follow the same rule
|
||||
as |ts_utils.get_next_node| but if the node is the first node.
|
||||
|
||||
*ts_utils.goto_node*
|
||||
goto_node(node, goto_end, avoid_set_jump)~
|
||||
|
||||
Sets cursor to the position of `node` in the current windows.
|
||||
If `goto_end` is truthy, the cursor is set to the end the node range.
|
||||
Setting `avoid_set_jump` to `true`, avoids setting the current cursor position
|
||||
to the jump list.
|
||||
|
||||
*ts_utils.swap_nodes*
|
||||
swap_nodes(node_or_range1, node_or_range2, bufnr, cursor_to_second)~
|
||||
|
||||
Swaps the nodes or ranges.
|
||||
set `cursor_to_second` to true to move the cursor to the second node
|
||||
|
||||
*ts_utils.memoize_by_buf_tick*
|
||||
memoize_by_buf_tick(fn, options)~
|
||||
|
||||
Caches the return value for a function and returns the cache value if the tick
|
||||
of the buffer has not changed from the previous.
|
||||
|
||||
`fn`: a function that takes any arguments
|
||||
and returns a value to store.
|
||||
`options?`: <table>
|
||||
- `bufnr`: a function/value that extracts the bufnr from the given arguments.
|
||||
- `key`: a function/value that extracts the cache key from the given arguments.
|
||||
`returns`: a function to call with bufnr as argument to
|
||||
retrieve the value from the cache
|
||||
|
||||
*ts_utils.node_to_lsp_range*
|
||||
node_to_lsp_range(node)~
|
||||
|
||||
Get an lsp formatted range from a node range
|
||||
|
||||
*ts_utils.node_length*
|
||||
node_length(node)~
|
||||
|
||||
Get the byte length of node range
|
||||
|
||||
*ts_utils.update_selection*
|
||||
update_selection(buf, node)~
|
||||
|
||||
Set the selection to the node range
|
||||
|
||||
*ts_utils.highlight_range*
|
||||
highlight_range(range, buf, hl_namespace, hl_group)~
|
||||
|
||||
Set a highlight that spans the given range
|
||||
|
||||
*ts_utils.highlight_node*
|
||||
highlight_node(node, buf, hl_namespace, hl_group)~
|
||||
|
||||
Set a highlight that spans the given node's range
|
||||
|
||||
==============================================================================
|
||||
FUNCTIONS *nvim-treesitter-functions*
|
||||
|
||||
*nvim_treesitter#statusline()*
|
||||
nvim_treesitter#statusline(opts)~
|
||||
|
||||
Returns a string describing the current position in the file. This
|
||||
could be used as a statusline indicator.
|
||||
Default options (lua syntax):
|
||||
>
|
||||
{
|
||||
indicator_size = 100,
|
||||
type_patterns = {'class', 'function', 'method'},
|
||||
transform_fn = function(line, _node) return line:gsub('%s*[%[%(%{]*%s*$', '') end,
|
||||
separator = ' -> ',
|
||||
allow_duplicates = false
|
||||
}
|
||||
<
|
||||
- `indicator_size` - How long should the string be. If longer, it is cut from
|
||||
the beginning.
|
||||
- `type_patterns` - Which node type patterns to match.
|
||||
- `transform_fn` - Function used to transform the single item in line. By
|
||||
default it removes opening brackets and spaces from end. Takes two arguments:
|
||||
the text of the line in question, and the corresponding treesitter node.
|
||||
- `separator` - Separator between nodes.
|
||||
- `allow_duplicates` - Whether or not to remove duplicate components.
|
||||
|
||||
*nvim_treesitter#foldexpr()*
|
||||
nvim_treesitter#foldexpr()~
|
||||
|
||||
Functions to be used to determine the fold level at a given line number.
|
||||
To use it: >
|
||||
set foldmethod=expr
|
||||
set foldexpr=nvim_treesitter#foldexpr()
|
||||
<
|
||||
|
||||
This will respect your 'foldminlines' and 'foldnestmax' settings.
|
||||
|
||||
Note: This is highly experimental, and folding can break on some types of
|
||||
edits. If you encounter such breakage, hitting `zx` should fix folding.
|
||||
In any case, feel free to open an issue with the reproducing steps.
|
||||
|
||||
==============================================================================
|
||||
PERFORMANCE *nvim-treesitter-performance*
|
||||
|
||||
`nvim-treesitter` checks the 'runtimepath' on startup in order to discover
|
||||
available parsers and queries and index them. As a consequence, a very long
|
||||
'runtimepath' might result in delayed startup times.
|
||||
|
||||
Parameters: ~
|
||||
• {type} `('queries'|parsers'?)` If specified, only show languages with
|
||||
installed queries or parsers, respectively.
|
||||
|
||||
vim:tw=78:ts=8:expandtab:noet:ft=help:norl:
|
||||
|
|
|
|||
743
lockfile.json
743
lockfile.json
|
|
@ -1,743 +0,0 @@
|
|||
{
|
||||
"ada": {
|
||||
"revision": "ba0894efa03beb70780156b91e28c716b7a4764d"
|
||||
},
|
||||
"agda": {
|
||||
"revision": "c21c3a0f996363ed17b8ac99d827fe5a4821f217"
|
||||
},
|
||||
"angular": {
|
||||
"revision": "624ff108fe949727217cddb302f20e4f16997b1c"
|
||||
},
|
||||
"apex": {
|
||||
"revision": "ca70b2347a79615cd749517f6c6c2352e50a7ce9"
|
||||
},
|
||||
"arduino": {
|
||||
"revision": "ff1045f5da90344d547022c50f1756be4adaf721"
|
||||
},
|
||||
"astro": {
|
||||
"revision": "a092afa5c330495fdfbc652766c29c66ec6880f4"
|
||||
},
|
||||
"authzed": {
|
||||
"revision": "1dec7e1af96c56924e3322cd85fdce15d0a31d00"
|
||||
},
|
||||
"awk": {
|
||||
"revision": "dcf4ac4eaff601d87cc15604765a7ae329c1b2ee"
|
||||
},
|
||||
"bash": {
|
||||
"revision": "7331995b19b8f8aba2d5e26deb51d2195c18bc94"
|
||||
},
|
||||
"bass": {
|
||||
"revision": "27f110dfe79620993f5493ffa0d0f2fe12d250ed"
|
||||
},
|
||||
"beancount": {
|
||||
"revision": "cd08aefa20dc0f3d5984b08b5d468f75bf4fd096"
|
||||
},
|
||||
"bibtex": {
|
||||
"revision": "ccfd77db0ed799b6c22c214fe9d2937f47bc8b34"
|
||||
},
|
||||
"bicep": {
|
||||
"revision": "3604d8c961ab129d2bfc6dfca56419c236ccdb83"
|
||||
},
|
||||
"bitbake": {
|
||||
"revision": "10bacac929ff36a1e8f4056503fe4f8717b21b94"
|
||||
},
|
||||
"blueprint": {
|
||||
"revision": "863cea9f83ad5637300478e0559262f1e791684b"
|
||||
},
|
||||
"c": {
|
||||
"revision": "212a80f86452bb1316324fa0db730cf52f29e05a"
|
||||
},
|
||||
"c_sharp": {
|
||||
"revision": "dd5e59721a5f8dae34604060833902b882023aaf"
|
||||
},
|
||||
"cairo": {
|
||||
"revision": "6216c6ee5e9fc0649c4bd7b1aedd884a55bdd9ef"
|
||||
},
|
||||
"capnp": {
|
||||
"revision": "dc28c9f4212809eab74d10996086297853eb34e5"
|
||||
},
|
||||
"chatito": {
|
||||
"revision": "871622a3a483f0baf94923d8495c8e0bb2c09009"
|
||||
},
|
||||
"clojure": {
|
||||
"revision": "6e41628e9d18b19caea1cb1d72aae4ccff5bdfe9"
|
||||
},
|
||||
"cmake": {
|
||||
"revision": "73ab4b8e9522f014a67f87f585e820d36fa47408"
|
||||
},
|
||||
"comment": {
|
||||
"revision": "aefcc2813392eb6ffe509aa0fc8b4e9b57413ee1"
|
||||
},
|
||||
"commonlisp": {
|
||||
"revision": "cf10fc38bc24faf0549d59217ff37c789973dfdc"
|
||||
},
|
||||
"cooklang": {
|
||||
"revision": "5e113412aadb78955c27010daa4dbe1d202013cf"
|
||||
},
|
||||
"corn": {
|
||||
"revision": "604d73c38d4c28ca68e9e441ffd405d68cb63051"
|
||||
},
|
||||
"cpon": {
|
||||
"revision": "f4b3cbc8b0bd4e13035d39940fef09f1392e8739"
|
||||
},
|
||||
"cpp": {
|
||||
"revision": "a71474021410973b29bfe99440d57bcd750246b1"
|
||||
},
|
||||
"css": {
|
||||
"revision": "98c7b3dceb24f1ee17f1322f3947e55638251c37"
|
||||
},
|
||||
"csv": {
|
||||
"revision": "6c1957405bd6f7751b050f61367f1094fab91444"
|
||||
},
|
||||
"cuda": {
|
||||
"revision": "2c6e806949197e7898910c78f514a3b7ff679068"
|
||||
},
|
||||
"cue": {
|
||||
"revision": "2df92e6755337e9234ad18ffef37f35d95e2ba9d"
|
||||
},
|
||||
"d": {
|
||||
"revision": "c2fbf21bd3aa45495fe13247e040ad5815250032"
|
||||
},
|
||||
"dart": {
|
||||
"revision": "f71e310a93010863f4b17a2a501ea8e2032c345b"
|
||||
},
|
||||
"devicetree": {
|
||||
"revision": "53b4137bd37e726116ea918139767f982a1584d8"
|
||||
},
|
||||
"dhall": {
|
||||
"revision": "affb6ee38d629c9296749767ab832d69bb0d9ea8"
|
||||
},
|
||||
"diff": {
|
||||
"revision": "c165725c28e69b36c5799ff0e458713a844f1aaf"
|
||||
},
|
||||
"dockerfile": {
|
||||
"revision": "33e22c33bcdbfc33d42806ee84cfd0b1248cc392"
|
||||
},
|
||||
"dot": {
|
||||
"revision": "9ab85550c896d8b294d9b9ca1e30698736f08cea"
|
||||
},
|
||||
"doxygen": {
|
||||
"revision": "a750758da90955c86fcc22fcbb6fa44a7d009865"
|
||||
},
|
||||
"dtd": {
|
||||
"revision": "dd7ef38c74d8430da729b4da815e4c40776e03bb"
|
||||
},
|
||||
"ebnf": {
|
||||
"revision": "8e635b0b723c620774dfb8abf382a7f531894b40"
|
||||
},
|
||||
"eds": {
|
||||
"revision": "fde62029d4c715562230070b9af51a9500c2ce10"
|
||||
},
|
||||
"eex": {
|
||||
"revision": "f742f2fe327463335e8671a87c0b9b396905d1d1"
|
||||
},
|
||||
"elixir": {
|
||||
"revision": "11426c5fd20eef360d5ecaf10729191f6bc5d715"
|
||||
},
|
||||
"elm": {
|
||||
"revision": "c26afd7f2316f689410a1622f1780eff054994b1"
|
||||
},
|
||||
"elsa": {
|
||||
"revision": "0a66b2b3f3c1915e67ad2ef9f7dbd2a84820d9d7"
|
||||
},
|
||||
"elvish": {
|
||||
"revision": "5e7210d945425b77f82cbaebc5af4dd3e1ad40f5"
|
||||
},
|
||||
"embedded_template": {
|
||||
"revision": "203f7bd3c1bbfbd98fc19add4b8fcb213c059205"
|
||||
},
|
||||
"erlang": {
|
||||
"revision": "54b6f814f43c4eac81eeedefaa7cc8762fec6683"
|
||||
},
|
||||
"facility": {
|
||||
"revision": "a52579670e2b14ec03d410c3c980fafaf6d659c4"
|
||||
},
|
||||
"fennel": {
|
||||
"revision": "517195970428aacca60891b050aa53eabf4ba78d"
|
||||
},
|
||||
"firrtl": {
|
||||
"revision": "2b5adae629c8cba528c7b1e4aa67a8ae28934ea5"
|
||||
},
|
||||
"fish": {
|
||||
"revision": "f9176908c9eb2e11eb684d79e1d00f3b29bd65c9"
|
||||
},
|
||||
"foam": {
|
||||
"revision": "04664b40c0dadb7ef37028acf3422c63271d377b"
|
||||
},
|
||||
"forth": {
|
||||
"revision": "90189238385cf636b9ee99ce548b9e5b5e569d48"
|
||||
},
|
||||
"fortran": {
|
||||
"revision": "f73d473e3530862dee7cbb38520f28824e7804f6"
|
||||
},
|
||||
"fsh": {
|
||||
"revision": "fa3347712f7a59ed02ccf508284554689c6cde28"
|
||||
},
|
||||
"func": {
|
||||
"revision": "0834e35ecf8b23fbf9ad15b088af6a897e19d4a8"
|
||||
},
|
||||
"fusion": {
|
||||
"revision": "19db2f47ba4c3a0f6238d4ae0e2abfca16e61dd6"
|
||||
},
|
||||
"gdscript": {
|
||||
"revision": "03f20b94707a21bed90bb95101684bc4036139ce"
|
||||
},
|
||||
"git_config": {
|
||||
"revision": "9c2a1b7894e6d9eedfe99805b829b4ecd871375e"
|
||||
},
|
||||
"git_rebase": {
|
||||
"revision": "d8a4207ebbc47bd78bacdf48f883db58283f9fd8"
|
||||
},
|
||||
"gitattributes": {
|
||||
"revision": "19d554d39e4a8491f7a77abcdb75bfbc1c19d0b5"
|
||||
},
|
||||
"gitcommit": {
|
||||
"revision": "e8d9eda4e5ea0b08aa39d48dab0f6553058fbe0f"
|
||||
},
|
||||
"gitignore": {
|
||||
"revision": "f4685bf11ac466dd278449bcfe5fd014e94aa504"
|
||||
},
|
||||
"gleam": {
|
||||
"revision": "62c5388a7badb4e29315690358267a76a734bf83"
|
||||
},
|
||||
"glimmer": {
|
||||
"revision": "f9746dc1d0707717fbba84cb5c22a71586af23e1"
|
||||
},
|
||||
"glsl": {
|
||||
"revision": "5bb58a6a5b0941d4e1256c6335e50d9780e74dde"
|
||||
},
|
||||
"gn": {
|
||||
"revision": "bc06955bc1e3c9ff8e9b2b2a55b38b94da923c05"
|
||||
},
|
||||
"go": {
|
||||
"revision": "ff86c7f1734873c8c4874ca4dd95603695686d7a"
|
||||
},
|
||||
"godot_resource": {
|
||||
"revision": "b6ef0768711086a86b3297056f9ffb5cc1d77b4a"
|
||||
},
|
||||
"gomod": {
|
||||
"revision": "bbe2fe3be4b87e06a613e685250f473d2267f430"
|
||||
},
|
||||
"gosum": {
|
||||
"revision": "e2ac513b2240c7ff1069ae33b2df29ce90777c11"
|
||||
},
|
||||
"gowork": {
|
||||
"revision": "949a8a470559543857a62102c84700d291fc984c"
|
||||
},
|
||||
"gpg": {
|
||||
"revision": "18b2690a15f061a6ff48730589f7a4039af2d002"
|
||||
},
|
||||
"graphql": {
|
||||
"revision": "5e66e961eee421786bdda8495ed1db045e06b5fe"
|
||||
},
|
||||
"groovy": {
|
||||
"revision": "7e023227f46fee428b16a0288eeb0f65ee2523ec"
|
||||
},
|
||||
"gstlaunch": {
|
||||
"revision": "2c0d9c94d35e37aa63fa5002163c8480985b3e5b"
|
||||
},
|
||||
"hack": {
|
||||
"revision": "fca1e294f6dce8ec5659233a6a21f5bd0ed5b4f2"
|
||||
},
|
||||
"hare": {
|
||||
"revision": "3d4af179414525a35dd069ba0208c9b71093d8b3"
|
||||
},
|
||||
"haskell": {
|
||||
"revision": "dd924b8df1eb76261f009e149fc6f3291c5081c2"
|
||||
},
|
||||
"haskell_persistent": {
|
||||
"revision": "577259b4068b2c281c9ebf94c109bd50a74d5857"
|
||||
},
|
||||
"hcl": {
|
||||
"revision": "e135399cb31b95fac0760b094556d1d5ce84acf0"
|
||||
},
|
||||
"heex": {
|
||||
"revision": "4a36c9a388505180da6ee0eda1d8afb8c83481c8"
|
||||
},
|
||||
"hjson": {
|
||||
"revision": "02fa3b79b3ff9a296066da6277adfc3f26cbc9e0"
|
||||
},
|
||||
"hlsl": {
|
||||
"revision": "8b10faba024b536dc85f76e0c678f573b1776034"
|
||||
},
|
||||
"hocon": {
|
||||
"revision": "c390f10519ae69fdb03b3e5764f5592fb6924bcc"
|
||||
},
|
||||
"hoon": {
|
||||
"revision": "0135187126370cbf112d759a50eab4a5c913a827"
|
||||
},
|
||||
"html": {
|
||||
"revision": "d742025fa2d8e6100f134a6ea990443aa1f074b3"
|
||||
},
|
||||
"htmldjango": {
|
||||
"revision": "8873e3df89f9ea1d33f6235e516b600009288557"
|
||||
},
|
||||
"http": {
|
||||
"revision": "6824a247d1326079aab4fa9f9164e9319678081d"
|
||||
},
|
||||
"hurl": {
|
||||
"revision": "cd1a0ada92cc73dd0f4d7eedc162be4ded758591"
|
||||
},
|
||||
"ini": {
|
||||
"revision": "bcb84a2d4bcd6f55b911c42deade75c8f90cb0c5"
|
||||
},
|
||||
"ispc": {
|
||||
"revision": "9b2f9aec2106b94b4e099fe75e73ebd8ae707c04"
|
||||
},
|
||||
"janet_simple": {
|
||||
"revision": "51271e260346878e1a1aa6c506ce6a797b7c25e2"
|
||||
},
|
||||
"java": {
|
||||
"revision": "2b57cd9541f9fd3a89207d054ce8fbe72657c444"
|
||||
},
|
||||
"javascript": {
|
||||
"revision": "f1e5a09b8d02f8209a68249c93f0ad647b228e6e"
|
||||
},
|
||||
"jq": {
|
||||
"revision": "13990f530e8e6709b7978503da9bc8701d366791"
|
||||
},
|
||||
"jsdoc": {
|
||||
"revision": "d01984de49927c979b46ea5c01b78c8ddd79baf9"
|
||||
},
|
||||
"json": {
|
||||
"revision": "3fef30de8aee74600f25ec2e319b62a1a870d51e"
|
||||
},
|
||||
"json5": {
|
||||
"revision": "c23f7a9b1ee7d45f516496b1e0e4be067264fa0d"
|
||||
},
|
||||
"jsonc": {
|
||||
"revision": "02b01653c8a1c198ae7287d566efa86a135b30d5"
|
||||
},
|
||||
"jsonnet": {
|
||||
"revision": "d34615fa12cc1d1cfc1f1f1a80acc9db80ee4596"
|
||||
},
|
||||
"julia": {
|
||||
"revision": "0c088d1ad270f02c4e84189247ac7001e86fe342"
|
||||
},
|
||||
"kconfig": {
|
||||
"revision": "aaba009ba9d7881f0f81742da588ae70b572316d"
|
||||
},
|
||||
"kdl": {
|
||||
"revision": "e180e05132c4cb229a8ba679b298790ef1eca77c"
|
||||
},
|
||||
"kotlin": {
|
||||
"revision": "0ef87892401bb01c84b40916e1f150197bc134b1"
|
||||
},
|
||||
"kusto": {
|
||||
"revision": "8353a1296607d6ba33db7c7e312226e5fc83e8ce"
|
||||
},
|
||||
"lalrpop": {
|
||||
"revision": "06ae1b6c26e23c77c7fb86d51dddad62b42e66b0"
|
||||
},
|
||||
"latex": {
|
||||
"revision": "2ae2021d7b224fb6aa57b760e0d146059f943bb8"
|
||||
},
|
||||
"ledger": {
|
||||
"revision": "8a841fb20ce683bfbb3469e6ba67f2851cfdf94a"
|
||||
},
|
||||
"leo": {
|
||||
"revision": "304611b5eaf53aca07459a0a03803b83b6dfd3b3"
|
||||
},
|
||||
"linkerscript": {
|
||||
"revision": "f99011a3554213b654985a4b0a65b3b032ec4621"
|
||||
},
|
||||
"liquidsoap": {
|
||||
"revision": "691484ae766c4eee2ac59ec09e621b27b9ed9add"
|
||||
},
|
||||
"llvm": {
|
||||
"revision": "1b96e58faf558ce057d4dc664b904528aee743cb"
|
||||
},
|
||||
"lua": {
|
||||
"revision": "9668709211b2e683f27f414454a8b51bf0a6bda1"
|
||||
},
|
||||
"luadoc": {
|
||||
"revision": "990926b13488a4bc0fc0804fc0f8400b5b0a1fb4"
|
||||
},
|
||||
"luap": {
|
||||
"revision": "31461ae9bd0866cb5117cfe5de71189854fd0f3e"
|
||||
},
|
||||
"luau": {
|
||||
"revision": "6953cd4fa5967c9aa3c769b4e4c7e69c904b9fa9"
|
||||
},
|
||||
"m68k": {
|
||||
"revision": "d097b123f19c6eaba2bf181c05420d88b9fc489d"
|
||||
},
|
||||
"make": {
|
||||
"revision": "a4b9187417d6be349ee5fd4b6e77b4172c6827dd"
|
||||
},
|
||||
"markdown": {
|
||||
"revision": "28aa3baef73bd458d053b613b8bd10fd102b4405"
|
||||
},
|
||||
"markdown_inline": {
|
||||
"revision": "28aa3baef73bd458d053b613b8bd10fd102b4405"
|
||||
},
|
||||
"matlab": {
|
||||
"revision": "6071891a8c39600203eba20513666cf93b4d650a"
|
||||
},
|
||||
"menhir": {
|
||||
"revision": "be8866a6bcc2b563ab0de895af69daeffa88fe70"
|
||||
},
|
||||
"mermaid": {
|
||||
"revision": "e26a5f8898a8174f02b4cc9a9050eb3ccfb799f3"
|
||||
},
|
||||
"meson": {
|
||||
"revision": "3d6dfbdb2432603bc84ca7dc009bb39ed9a8a7b1"
|
||||
},
|
||||
"mlir": {
|
||||
"revision": "650a8fb72013ba8d169bdb458e480d640fc545c9"
|
||||
},
|
||||
"nasm": {
|
||||
"revision": "3bc691d2cfba44bea339a775ad496c8bc552c60d"
|
||||
},
|
||||
"nickel": {
|
||||
"revision": "091b5dcc7d138901bcc162da9409c0bb626c0d27"
|
||||
},
|
||||
"nim": {
|
||||
"revision": "70ceee835e033acbc7092cd7f4f6a251789af121"
|
||||
},
|
||||
"nim_format_string": {
|
||||
"revision": "d45f75022d147cda056e98bfba68222c9c8eca3a"
|
||||
},
|
||||
"ninja": {
|
||||
"revision": "0a95cfdc0745b6ae82f60d3a339b37f19b7b9267"
|
||||
},
|
||||
"nix": {
|
||||
"revision": "763168fa916a333a459434f1424b5d30645f015d"
|
||||
},
|
||||
"norg": {
|
||||
"revision": "014073fe8016d1ac440c51d22c77e3765d8f6855"
|
||||
},
|
||||
"nqc": {
|
||||
"revision": "14e6da1627aaef21d2b2aa0c37d04269766dcc1d"
|
||||
},
|
||||
"objc": {
|
||||
"revision": "62e61b6f5c0289c376d61a8c91faf6435cde9012"
|
||||
},
|
||||
"objdump": {
|
||||
"revision": "28d3b2e25a0b1881d1b47ed1924ca276c7003d45"
|
||||
},
|
||||
"ocaml": {
|
||||
"revision": "4abfdc1c7af2c6c77a370aee974627be1c285b3b"
|
||||
},
|
||||
"ocaml_interface": {
|
||||
"revision": "4abfdc1c7af2c6c77a370aee974627be1c285b3b"
|
||||
},
|
||||
"ocamllex": {
|
||||
"revision": "4b9898ccbf198602bb0dec9cd67cc1d2c0a4fad2"
|
||||
},
|
||||
"odin": {
|
||||
"revision": "751f7796fa76075cff52edd1afff569a8a09c2a7"
|
||||
},
|
||||
"org": {
|
||||
"revision": "64cfbc213f5a83da17632c95382a5a0a2f3357c1"
|
||||
},
|
||||
"pascal": {
|
||||
"revision": "9e995404ddff8319631d72d4b46552e737206912"
|
||||
},
|
||||
"passwd": {
|
||||
"revision": "20239395eacdc2e0923a7e5683ad3605aee7b716"
|
||||
},
|
||||
"pem": {
|
||||
"revision": "e01767921df18142055d97407595329d7629e643"
|
||||
},
|
||||
"perl": {
|
||||
"revision": "9c0cea7720f65a5e832c4d924356d7793f519e36"
|
||||
},
|
||||
"php": {
|
||||
"revision": "b569a5f2c0d592e67430520d1a0e1f765d83ceb0"
|
||||
},
|
||||
"phpdoc": {
|
||||
"revision": "915a527d5aafa81b31acf67fab31b0ac6b6319c0"
|
||||
},
|
||||
"pioasm": {
|
||||
"revision": "924aadaf5dea2a6074d72027b064f939acf32e20"
|
||||
},
|
||||
"po": {
|
||||
"revision": "d6aed225290bc71a15ab6f06305cb11419360c56"
|
||||
},
|
||||
"pod": {
|
||||
"revision": "39da859947b94abdee43e431368e1ae975c0a424"
|
||||
},
|
||||
"poe_filter": {
|
||||
"revision": "fa83292e04d27976ab5c354e0c980f2c67628a02"
|
||||
},
|
||||
"pony": {
|
||||
"revision": "16f930b250433cfcd4fb4144df92bb98ad344c20"
|
||||
},
|
||||
"prisma": {
|
||||
"revision": "eca2596a355b1a9952b4f80f8f9caed300a272b5"
|
||||
},
|
||||
"promql": {
|
||||
"revision": "77625d78eebc3ffc44d114a07b2f348dff3061b0"
|
||||
},
|
||||
"properties": {
|
||||
"revision": "97253273bdf8b63546c8006e71ba155ecc27069e"
|
||||
},
|
||||
"proto": {
|
||||
"revision": "e9f6b43f6844bd2189b50a422d4e2094313f6aa3"
|
||||
},
|
||||
"prql": {
|
||||
"revision": "09e158cd3650581c0af4c49c2e5b10c4834c8646"
|
||||
},
|
||||
"psv": {
|
||||
"revision": "6c1957405bd6f7751b050f61367f1094fab91444"
|
||||
},
|
||||
"pug": {
|
||||
"revision": "a7ff31a38908df9b9f34828d21d6ca5e12413e18"
|
||||
},
|
||||
"puppet": {
|
||||
"revision": "9ce9a5f7d64528572aaa8d59459ba869e634086b"
|
||||
},
|
||||
"purescript": {
|
||||
"revision": "85a90951c10f118f819c1137f669800246890db7"
|
||||
},
|
||||
"pymanifest": {
|
||||
"revision": "a77547018ada84ca4bc115c7650b19441120f065"
|
||||
},
|
||||
"python": {
|
||||
"revision": "4bfdd9033a2225cc95032ce77066b7aeca9e2efc"
|
||||
},
|
||||
"ql": {
|
||||
"revision": "bd087020f0d8c183080ca615d38de0ec827aeeaf"
|
||||
},
|
||||
"qmldir": {
|
||||
"revision": "6b2b5e41734bd6f07ea4c36ac20fb6f14061c841"
|
||||
},
|
||||
"qmljs": {
|
||||
"revision": "259133077f2fd854bcaa6f0149d3fc281fc8070b"
|
||||
},
|
||||
"query": {
|
||||
"revision": "3a9808b22742d5bd906ef5d1a562f2f1ae57406d"
|
||||
},
|
||||
"r": {
|
||||
"revision": "c55f8b4dfaa32c80ddef6c0ac0e79b05cb0cbf57"
|
||||
},
|
||||
"racket": {
|
||||
"revision": "e4ba1a9674a3b4dd7905d04f194ae6f8331be342"
|
||||
},
|
||||
"rasi": {
|
||||
"revision": "371dac6bcce0df5566c1cfebde69d90ecbeefd2d"
|
||||
},
|
||||
"rbs": {
|
||||
"revision": "b28e1819d434e95916d11fe48ee6e8959b69197b"
|
||||
},
|
||||
"re2c": {
|
||||
"revision": "47aa19cf5f7aba2ed30e2b377f7172df76e819a6"
|
||||
},
|
||||
"regex": {
|
||||
"revision": "2354482d7e2e8f8ff33c1ef6c8aa5690410fbc96"
|
||||
},
|
||||
"rego": {
|
||||
"revision": "9ac75e71b2d791e0aadeef68098319d86a2a14cf"
|
||||
},
|
||||
"requirements": {
|
||||
"revision": "389dd46a39075ce36af6ee3af50393d9aa506d14"
|
||||
},
|
||||
"rnoweb": {
|
||||
"revision": "502c1126dc6777f09af5bef16e72a42f75bd081e"
|
||||
},
|
||||
"robot": {
|
||||
"revision": "322e4cc65754d2b3fdef4f2f8a71e0762e3d13af"
|
||||
},
|
||||
"ron": {
|
||||
"revision": "ce6086b2c9e8e71065b8129d6c2289c5f66d1879"
|
||||
},
|
||||
"rst": {
|
||||
"revision": "3ba9eb9b5a47aadb1f2356a3cab0dd3d2bd00b4b"
|
||||
},
|
||||
"ruby": {
|
||||
"revision": "4d9ad3f010fdc47a8433adcf9ae30c8eb8475ae7"
|
||||
},
|
||||
"rust": {
|
||||
"revision": "79456e6080f50fc1ca7c21845794308fa5d35a51"
|
||||
},
|
||||
"scala": {
|
||||
"revision": "0c63ada18d34ac83eec6c7a2fba9a47e65cda48a"
|
||||
},
|
||||
"scfg": {
|
||||
"revision": "6deae0cbb458c849a4d1e2985093e9c9c32d7fd0"
|
||||
},
|
||||
"scheme": {
|
||||
"revision": "85b6188fb77c03dfb01d13e58e2844450506860c"
|
||||
},
|
||||
"scss": {
|
||||
"revision": "c478c6868648eff49eb04a4df90d703dc45b312a"
|
||||
},
|
||||
"slang": {
|
||||
"revision": "ac07aa2c875ef6ada2ec468d8a4d0c7c5efd96d7"
|
||||
},
|
||||
"slint": {
|
||||
"revision": "00c8a2d3645766f68c0d0460086c0a994e5b0d85"
|
||||
},
|
||||
"smali": {
|
||||
"revision": "72e334b2630f5852825ba5ff9dfd872447175eb5"
|
||||
},
|
||||
"smithy": {
|
||||
"revision": "8327eb84d55639ffbe08c9dc82da7fff72a1ad07"
|
||||
},
|
||||
"snakemake": {
|
||||
"revision": "65a6c3b4671877821082164da0a310851b211953"
|
||||
},
|
||||
"solidity": {
|
||||
"revision": "168020304759ad5d8b4a88a541a699134e3730c5"
|
||||
},
|
||||
"soql": {
|
||||
"revision": "ca70b2347a79615cd749517f6c6c2352e50a7ce9"
|
||||
},
|
||||
"sosl": {
|
||||
"revision": "ca70b2347a79615cd749517f6c6c2352e50a7ce9"
|
||||
},
|
||||
"sparql": {
|
||||
"revision": "05f949d3c1c15e3261473a244d3ce87777374dec"
|
||||
},
|
||||
"sql": {
|
||||
"revision": "fd70fb358d164cd93fbe2674a9cca276dc5203f7"
|
||||
},
|
||||
"squirrel": {
|
||||
"revision": "e8b5835296f931bcaa1477d3c5a68a0c5c2ba034"
|
||||
},
|
||||
"ssh_config": {
|
||||
"revision": "096981397385f49833dfd66037fa98081bbd9ef9"
|
||||
},
|
||||
"starlark": {
|
||||
"revision": "c45ce2b39062bbd12ea1c210bd200db250efb24a"
|
||||
},
|
||||
"strace": {
|
||||
"revision": "d819cdd5dbe455bd3c859193633c8d91c0df7c36"
|
||||
},
|
||||
"styled": {
|
||||
"revision": "5e52758b32e02adca16bb93f95b3f9c050c72b56"
|
||||
},
|
||||
"supercollider": {
|
||||
"revision": "3b35bd0fded4423c8fb30e9585c7bacbcd0e8095"
|
||||
},
|
||||
"surface": {
|
||||
"revision": "f4586b35ac8548667a9aaa4eae44456c1f43d032"
|
||||
},
|
||||
"svelte": {
|
||||
"revision": "697bb515471871e85ff799ea57a76298a71a9cca"
|
||||
},
|
||||
"swift": {
|
||||
"revision": "f1a48a33a7ceaf8817f7a340ea4ef1b549ffa176"
|
||||
},
|
||||
"sxhkdrc": {
|
||||
"revision": "440d5f913d9465c9c776a1bd92334d32febcf065"
|
||||
},
|
||||
"systemtap": {
|
||||
"revision": "1af543a96d060b1f808982037bfc54cc02218edd"
|
||||
},
|
||||
"t32": {
|
||||
"revision": "b904af353fb2f1df6ac45d8d3e3a5ee85a6cc306"
|
||||
},
|
||||
"tablegen": {
|
||||
"revision": "300f6a490e71f895e644ed2deec6920860a2e107"
|
||||
},
|
||||
"teal": {
|
||||
"revision": "33482c92a0dfa694491d34e167a1d2f52b0dccb1"
|
||||
},
|
||||
"templ": {
|
||||
"revision": "c3baaab33f1f1032eedd3613cd932284975bd21f"
|
||||
},
|
||||
"terraform": {
|
||||
"revision": "e135399cb31b95fac0760b094556d1d5ce84acf0"
|
||||
},
|
||||
"textproto": {
|
||||
"revision": "8dacf02aa402892c91079f8577998ed5148c0496"
|
||||
},
|
||||
"thrift": {
|
||||
"revision": "d4deb1bd9e848f2dbe81103a151d99e8546de480"
|
||||
},
|
||||
"tiger": {
|
||||
"revision": "a7f11d946b44244f71df41d2a78af0665d618dae"
|
||||
},
|
||||
"tlaplus": {
|
||||
"revision": "aaf5bb5c1df0a6e583bb51efa519a9ac788b2ad8"
|
||||
},
|
||||
"todotxt": {
|
||||
"revision": "3937c5cd105ec4127448651a21aef45f52d19609"
|
||||
},
|
||||
"toml": {
|
||||
"revision": "8bd2056818b21860e3d756b5a58c4f6e05fb744e"
|
||||
},
|
||||
"tsv": {
|
||||
"revision": "6c1957405bd6f7751b050f61367f1094fab91444"
|
||||
},
|
||||
"tsx": {
|
||||
"revision": "d847898fec3fe596798c9fda55cb8c05a799001a"
|
||||
},
|
||||
"turtle": {
|
||||
"revision": "085437f5cb117703b7f520dd92161140a684f092"
|
||||
},
|
||||
"twig": {
|
||||
"revision": "eaf80e6af969e25993576477a9dbdba3e48c1305"
|
||||
},
|
||||
"typescript": {
|
||||
"revision": "d847898fec3fe596798c9fda55cb8c05a799001a"
|
||||
},
|
||||
"typoscript": {
|
||||
"revision": "43b221c0b76e77244efdaa9963e402a17c930fbc"
|
||||
},
|
||||
"udev": {
|
||||
"revision": "baeac48a999abb9384cdcce320f0182937aec8ba"
|
||||
},
|
||||
"ungrammar": {
|
||||
"revision": "debd26fed283d80456ebafa33a06957b0c52e451"
|
||||
},
|
||||
"unison": {
|
||||
"revision": "a69d087590f2ca057d1ef1a393de7e22869bb557"
|
||||
},
|
||||
"usd": {
|
||||
"revision": "ab8c30bde2df0e58c4b3f01f220fb0125ecb57a7"
|
||||
},
|
||||
"uxntal": {
|
||||
"revision": "4c5ecd6326ebd61f6f9a22a370cbd100e0d601da"
|
||||
},
|
||||
"v": {
|
||||
"revision": "9ac84e62396bb13c8f1d11f967f0c0f2dec1a448"
|
||||
},
|
||||
"vala": {
|
||||
"revision": "8f690bfa639f2b83d1fb938ed3dd98a7ba453e8b"
|
||||
},
|
||||
"verilog": {
|
||||
"revision": "902031343056bc0b11f3e47b33f036a9cf59f58d"
|
||||
},
|
||||
"vhs": {
|
||||
"revision": "9534865e614c95eb9418e5e73f061c32fa4d9540"
|
||||
},
|
||||
"vim": {
|
||||
"revision": "32c76f150347c1cd044e90b8e2bc73c00677fa55"
|
||||
},
|
||||
"vimdoc": {
|
||||
"revision": "ed8695ad8de39c3f073da130156f00b1148e2891"
|
||||
},
|
||||
"vue": {
|
||||
"revision": "91fe2754796cd8fba5f229505a23fa08f3546c06"
|
||||
},
|
||||
"wgsl": {
|
||||
"revision": "40259f3c77ea856841a4e0c4c807705f3e4a2b65"
|
||||
},
|
||||
"wgsl_bevy": {
|
||||
"revision": "a041228ae64632f59b9bd37346a0dbcb7817f36b"
|
||||
},
|
||||
"wing": {
|
||||
"revision": "ee58533169c654b8d7fd47fde01241e528674d8a"
|
||||
},
|
||||
"xcompose": {
|
||||
"revision": "01344fed31a3cd37a63f03357ec80cbc592a93b5"
|
||||
},
|
||||
"xml": {
|
||||
"revision": "dd7ef38c74d8430da729b4da815e4c40776e03bb"
|
||||
},
|
||||
"yaml": {
|
||||
"revision": "0e36bed171768908f331ff7dff9d956bae016efb"
|
||||
},
|
||||
"yang": {
|
||||
"revision": "2c0e6be8dd4dcb961c345fa35c309ad4f5bd3502"
|
||||
},
|
||||
"yuck": {
|
||||
"revision": "c348825d3f86dec71dee0e1223c6bd73114e3579"
|
||||
},
|
||||
"zig": {
|
||||
"revision": "0d08703e4c3f426ec61695d7617415fff97029bd"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
local install = require "nvim-treesitter.install"
|
||||
local utils = require "nvim-treesitter.utils"
|
||||
local info = require "nvim-treesitter.info"
|
||||
local configs = require "nvim-treesitter.configs"
|
||||
local statusline = require "nvim-treesitter.statusline"
|
||||
|
||||
-- Registers all query predicates
|
||||
require "nvim-treesitter.query_predicates"
|
||||
|
||||
local M = {}
|
||||
|
||||
function M.setup()
|
||||
utils.setup_commands("install", install.commands)
|
||||
utils.setup_commands("info", info.commands)
|
||||
utils.setup_commands("configs", configs.commands)
|
||||
configs.init()
|
||||
end
|
||||
|
||||
M.define_modules = configs.define_modules
|
||||
M.statusline = statusline.statusline
|
||||
|
||||
return M
|
||||
47
lua/nvim-treesitter/_meta/parsers.lua
Normal file
47
lua/nvim-treesitter/_meta/parsers.lua
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
---@meta
|
||||
error('Cannot require a meta file')
|
||||
|
||||
---@class InstallInfo
|
||||
---
|
||||
---URL of parser repo (Github)
|
||||
---@field url string
|
||||
---
|
||||
---Commit hash of parser to download (compatible with queries)
|
||||
---@field revision string
|
||||
---
|
||||
---Branch of parser repo to download (if not default branch)
|
||||
---@field branch? string
|
||||
---
|
||||
---Location of `grammar.js` in repo (if not at root, e.g., in a monorepo)
|
||||
---@field location? string
|
||||
---
|
||||
---Repo does not contain a `parser.c`; must be generated from grammar first
|
||||
---@field generate? boolean
|
||||
---
|
||||
---Generate parser from `grammar.json` instead of `grammar.js` (default true)
|
||||
---@field generate_from_json? boolean
|
||||
---
|
||||
---Parser repo is a local directory; overrides `url`, `revision`, and `branch`
|
||||
---@field path? string
|
||||
---
|
||||
---Directory with queries to be installed
|
||||
---@field queries? string
|
||||
|
||||
---@class ParserInfo
|
||||
---
|
||||
---Information necessary to build and install the parser (empty for query-only language)
|
||||
---@field install_info? InstallInfo
|
||||
---
|
||||
---List of Github users maintaining the queries for Neovim
|
||||
---@field maintainers? string[]
|
||||
---
|
||||
---List of other languages to install (e.g., if queries inherit from them)
|
||||
---@field requires? string[]
|
||||
---
|
||||
---Language support tier, maps to "stable", "unstable", "unmaintained", "unsupported"
|
||||
---@field tier integer
|
||||
---
|
||||
---Explanatory footnote text to add in SUPPORTED_LANGUAGES.md
|
||||
---@field readme_note? string
|
||||
|
||||
---@alias nvim-ts.parsers table<string,ParserInfo>
|
||||
736
lua/nvim-treesitter/async.lua
vendored
Normal file
736
lua/nvim-treesitter/async.lua
vendored
Normal file
|
|
@ -0,0 +1,736 @@
|
|||
---@meta nvim-treesitter.async vendored file, don't diagnose
|
||||
local pcall = copcall or pcall
|
||||
|
||||
--- @param ... any
|
||||
--- @return {[integer]: any, n: integer}
|
||||
local function pack_len(...)
|
||||
return { n = select('#', ...), ... }
|
||||
end
|
||||
|
||||
--- like unpack() but use the length set by F.pack_len if present
|
||||
--- @param t? { [integer]: any, n?: integer }
|
||||
--- @param first? integer
|
||||
--- @return ...any
|
||||
local function unpack_len(t, first)
|
||||
if t then
|
||||
return unpack(t, first or 1, t.n or table.maxn(t))
|
||||
end
|
||||
end
|
||||
|
||||
--- @class async
|
||||
local M = {}
|
||||
|
||||
--- Weak table to keep track of running tasks
|
||||
--- @type table<thread,async.Task?>
|
||||
local threads = setmetatable({}, { __mode = 'k' })
|
||||
|
||||
--- @return async.Task?
|
||||
local function running()
|
||||
local task = threads[coroutine.running()]
|
||||
if task and not (task:_completed() or task._closing) then
|
||||
return task
|
||||
end
|
||||
end
|
||||
|
||||
--- Base class for async tasks. Async functions should return a subclass of
|
||||
--- this. This is designed specifically to be a base class of uv_handle_t
|
||||
--- @class async.Handle
|
||||
--- @field close fun(self: async.Handle, callback?: fun())
|
||||
--- @field is_closing? fun(self: async.Handle): boolean
|
||||
|
||||
--- @alias async.CallbackFn fun(...: any): async.Handle?
|
||||
|
||||
--- @class async.Task : async.Handle
|
||||
--- @field package _callbacks table<integer,fun(err?: any, ...: any)>
|
||||
--- @field package _callback_pos integer
|
||||
--- @field private _thread thread
|
||||
---
|
||||
--- Tasks can call other async functions (task of callback functions)
|
||||
--- when we are waiting on a child, we store the handle to it here so we can
|
||||
--- cancel it.
|
||||
--- @field private _current_child? async.Handle
|
||||
---
|
||||
--- Error result of the task is an error occurs.
|
||||
--- Must use `await` to get the result.
|
||||
--- @field private _err? any
|
||||
---
|
||||
--- Result of the task.
|
||||
--- Must use `await` to get the result.
|
||||
--- @field private _result? any[]
|
||||
local Task = {}
|
||||
Task.__index = Task
|
||||
|
||||
--- @private
|
||||
--- @param func function
|
||||
--- @return async.Task
|
||||
function Task._new(func)
|
||||
local thread = coroutine.create(func)
|
||||
|
||||
local self = setmetatable({
|
||||
_closing = false,
|
||||
_thread = thread,
|
||||
_callbacks = {},
|
||||
_callback_pos = 1,
|
||||
}, Task)
|
||||
|
||||
threads[thread] = self
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- @param callback fun(err?: any, ...: any)
|
||||
function Task:await(callback)
|
||||
if self._closing then
|
||||
callback('closing')
|
||||
elseif self:_completed() then -- TODO(lewis6991): test
|
||||
-- Already finished or closed
|
||||
callback(self._err, unpack_len(self._result))
|
||||
else
|
||||
self._callbacks[self._callback_pos] = callback
|
||||
self._callback_pos = self._callback_pos + 1
|
||||
end
|
||||
end
|
||||
|
||||
--- @package
|
||||
function Task:_completed()
|
||||
return (self._err or self._result) ~= nil
|
||||
end
|
||||
|
||||
-- Use max 32-bit signed int value to avoid overflow on 32-bit systems.
|
||||
-- Do not use `math.huge` as it is not interpreted as a positive integer on all
|
||||
-- platforms.
|
||||
local MAX_TIMEOUT = 2 ^ 31 - 1
|
||||
|
||||
--- Synchronously wait (protected) for a task to finish (blocking)
|
||||
---
|
||||
--- If an error is returned, `Task:traceback()` can be used to get the
|
||||
--- stack trace of the error.
|
||||
---
|
||||
--- Example:
|
||||
--- ```lua
|
||||
---
|
||||
--- local ok, err_or_result = task:pwait(10)
|
||||
---
|
||||
--- if not ok then
|
||||
--- error(task:traceback(err_or_result))
|
||||
--- end
|
||||
---
|
||||
--- local _, result = assert(task:pwait(10))
|
||||
--- ```
|
||||
---
|
||||
--- Can be called if a task is closing.
|
||||
--- @param timeout? integer
|
||||
--- @return boolean status
|
||||
--- @return any ... result or error
|
||||
function Task:pwait(timeout)
|
||||
local done = vim.wait(timeout or MAX_TIMEOUT, function()
|
||||
-- Note we use self:_completed() instead of self:await() to avoid creating a
|
||||
-- callback. This avoids having to cleanup/unregister any callback in the
|
||||
-- case of a timeout.
|
||||
return self:_completed()
|
||||
end)
|
||||
|
||||
if not done then
|
||||
return false, 'timeout'
|
||||
elseif self._err then
|
||||
return false, self._err
|
||||
else
|
||||
return true, unpack_len(self._result)
|
||||
end
|
||||
end
|
||||
|
||||
--- Synchronously wait for a task to finish (blocking)
|
||||
---
|
||||
--- Example:
|
||||
--- ```lua
|
||||
--- local result = task:wait(10) -- wait for 10ms or else error
|
||||
---
|
||||
--- local result = task:wait() -- wait indefinitely
|
||||
--- ```
|
||||
--- @param timeout? integer Timeout in milliseconds
|
||||
--- @return any ... result
|
||||
function Task:wait(timeout)
|
||||
local res = pack_len(self:pwait(timeout))
|
||||
local stat = res[1]
|
||||
|
||||
if not stat then
|
||||
error(self:traceback(res[2]))
|
||||
end
|
||||
|
||||
return unpack_len(res, 2)
|
||||
end
|
||||
|
||||
--- @private
|
||||
--- @param msg? string
|
||||
--- @param _lvl? integer
|
||||
--- @return string
|
||||
function Task:_traceback(msg, _lvl)
|
||||
_lvl = _lvl or 0
|
||||
|
||||
local thread = ('[%s] '):format(self._thread)
|
||||
|
||||
local child = self._current_child
|
||||
if getmetatable(child) == Task then
|
||||
--- @cast child async.Task
|
||||
msg = child:_traceback(msg, _lvl + 1)
|
||||
end
|
||||
|
||||
local tblvl = getmetatable(child) == Task and 2 or nil
|
||||
msg = (msg or '') .. debug.traceback(self._thread, '', tblvl):gsub('\n\t', '\n\t' .. thread)
|
||||
|
||||
if _lvl == 0 then
|
||||
--- @type string
|
||||
msg = msg
|
||||
:gsub('\nstack traceback:\n', '\nSTACK TRACEBACK:\n', 1)
|
||||
:gsub('\nstack traceback:\n', '\n')
|
||||
:gsub('\nSTACK TRACEBACK:\n', '\nstack traceback:\n', 1)
|
||||
end
|
||||
|
||||
return msg
|
||||
end
|
||||
|
||||
--- Get the traceback of a task when it is not active.
|
||||
--- Will also get the traceback of nested tasks.
|
||||
---
|
||||
--- @param msg? string
|
||||
--- @return string
|
||||
function Task:traceback(msg)
|
||||
return self:_traceback(msg)
|
||||
end
|
||||
|
||||
--- If a task completes with an error, raise the error
|
||||
function Task:raise_on_error()
|
||||
self:await(function(err)
|
||||
if err then
|
||||
error(self:_traceback(err), 0)
|
||||
end
|
||||
end)
|
||||
return self
|
||||
end
|
||||
|
||||
--- @private
|
||||
--- @param err? any
|
||||
--- @param result? {[integer]: any, n: integer}
|
||||
function Task:_finish(err, result)
|
||||
self._current_child = nil
|
||||
self._err = err
|
||||
self._result = result
|
||||
threads[self._thread] = nil
|
||||
|
||||
local errs = {} --- @type string[]
|
||||
for _, cb in pairs(self._callbacks) do
|
||||
--- @type boolean, string
|
||||
local ok, cb_err = pcall(cb, err, unpack_len(result))
|
||||
if not ok then
|
||||
errs[#errs + 1] = cb_err
|
||||
end
|
||||
end
|
||||
|
||||
if #errs > 0 then
|
||||
error(table.concat(errs, '\n'), 0)
|
||||
end
|
||||
end
|
||||
|
||||
--- @return boolean
|
||||
function Task:is_closing()
|
||||
return self._closing
|
||||
end
|
||||
|
||||
--- Close the task and all its children.
|
||||
--- If callback is provided it will run asynchronously,
|
||||
--- else it will run synchronously.
|
||||
---
|
||||
--- @param callback? fun()
|
||||
function Task:close(callback)
|
||||
if self:_completed() then
|
||||
if callback then
|
||||
callback()
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
if self._closing then
|
||||
return
|
||||
end
|
||||
|
||||
self._closing = true
|
||||
|
||||
if callback then -- async
|
||||
if self._current_child then
|
||||
self._current_child:close(function()
|
||||
self:_finish('closed')
|
||||
callback()
|
||||
end)
|
||||
else
|
||||
self:_finish('closed')
|
||||
callback()
|
||||
end
|
||||
else -- sync
|
||||
if self._current_child then
|
||||
self._current_child:close(function()
|
||||
self:_finish('closed')
|
||||
end)
|
||||
else
|
||||
self:_finish('closed')
|
||||
end
|
||||
vim.wait(0, function()
|
||||
return self:_completed()
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
--- @param obj any
|
||||
--- @return boolean
|
||||
local function is_async_handle(obj)
|
||||
local ty = type(obj)
|
||||
return (ty == 'table' or ty == 'userdata') and vim.is_callable(obj.close)
|
||||
end
|
||||
|
||||
--- @param ... any
|
||||
function Task:_resume(...)
|
||||
--- @type [boolean, string|async.CallbackFn]
|
||||
local ret = pack_len(coroutine.resume(self._thread, ...))
|
||||
local stat = ret[1]
|
||||
|
||||
if not stat then
|
||||
-- Coroutine had error
|
||||
self:_finish(ret[2])
|
||||
elseif coroutine.status(self._thread) == 'dead' then
|
||||
-- Coroutine finished
|
||||
local result = pack_len(unpack_len(ret, 2))
|
||||
self:_finish(nil, result)
|
||||
else
|
||||
local fn = ret[2]
|
||||
--- @cast fn -string
|
||||
|
||||
-- TODO(lewis6991): refine error handler to be more specific
|
||||
local ok, r
|
||||
ok, r = pcall(fn, function(...)
|
||||
if is_async_handle(r) then
|
||||
--- @cast r async.Handle
|
||||
-- We must close children before we resume to ensure
|
||||
-- all resources are collected.
|
||||
local args = pack_len(...)
|
||||
r:close(function()
|
||||
self:_resume(unpack_len(args))
|
||||
end)
|
||||
else
|
||||
self:_resume(...)
|
||||
end
|
||||
end)
|
||||
|
||||
if not ok then
|
||||
self:_finish(r)
|
||||
elseif is_async_handle(r) then
|
||||
self._current_child = r
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- @return 'running'|'suspended'|'normal'|'dead'?
|
||||
function Task:status()
|
||||
return coroutine.status(self._thread)
|
||||
end
|
||||
|
||||
--- Run a function in an async context, asynchronously.
|
||||
---
|
||||
--- Examples:
|
||||
--- ```lua
|
||||
--- -- The two below blocks are equivalent:
|
||||
---
|
||||
--- -- Run a uv function and wait for it
|
||||
--- local stat = async.arun(function()
|
||||
--- return async.await(2, vim.uv.fs_stat, 'foo.txt')
|
||||
--- end):wait()
|
||||
---
|
||||
--- -- Since uv functions have sync versions. You can just do:
|
||||
--- local stat = vim.fs_stat('foo.txt')
|
||||
--- ```
|
||||
--- @generic T, R
|
||||
--- @param func async fun(...: T...): R...
|
||||
--- @param ... T...
|
||||
--- @return async.Task
|
||||
function M.arun(func, ...)
|
||||
local task = Task._new(func)
|
||||
task:_resume(...)
|
||||
return task
|
||||
end
|
||||
|
||||
--- @alias async.TaskFun<T, R> fun(...: T...): async.Task
|
||||
|
||||
--- @generic T, R
|
||||
--- @class async._TaskFun<T, R>
|
||||
--- @field package _fun async fun(...: T...): R...
|
||||
--- @operator call(...: T...): async.Task
|
||||
local TaskFun = {}
|
||||
TaskFun.__index = TaskFun
|
||||
|
||||
--- @generic T, R
|
||||
--- @param self async._TaskFun<T, R>
|
||||
--- @param ... T...
|
||||
--- @return async.Task
|
||||
function TaskFun:__call(...)
|
||||
return M.arun(self._fun, ...)
|
||||
end
|
||||
|
||||
--- Create an async function
|
||||
--- @generic T, R
|
||||
--- @param fun async fun(...: T...): R...
|
||||
--- @return async.TaskFun<T, R>
|
||||
function M.async(fun)
|
||||
return setmetatable({ _fun = fun }, TaskFun)
|
||||
end
|
||||
|
||||
--- Returns the status of a task’s thread.
|
||||
---
|
||||
--- @param task? async.Task
|
||||
--- @return 'running'|'suspended'|'normal'|'dead'?
|
||||
function M.status(task)
|
||||
task = task or running()
|
||||
if task then
|
||||
assert(getmetatable(task) == Task, 'Expected Task')
|
||||
return task:status()
|
||||
end
|
||||
end
|
||||
|
||||
--- @async
|
||||
--- @generic R1, R2, R3, R4
|
||||
--- @param fun fun(callback: fun(r1: R1, r2: R2, r3: R3, r4: R4)): any?
|
||||
--- @return R1, R2, R3, R4
|
||||
local function yield(fun)
|
||||
assert(type(fun) == 'function', 'Expected function')
|
||||
return coroutine.yield(fun)
|
||||
end
|
||||
|
||||
--- @async
|
||||
--- @param task async.Task
|
||||
--- @return any ...
|
||||
local function await_task(task)
|
||||
--- @param callback fun(err?: string, ...: any)
|
||||
--- @return function
|
||||
local res = pack_len(yield(function(callback)
|
||||
task:await(callback)
|
||||
return task
|
||||
end))
|
||||
|
||||
local err = res[1]
|
||||
|
||||
if err then
|
||||
-- TODO(lewis6991): what is the correct level to pass?
|
||||
error(err, 0)
|
||||
end
|
||||
|
||||
return unpack_len(res, 2)
|
||||
end
|
||||
|
||||
--- Asynchronous blocking wait
|
||||
--- @param argc integer
|
||||
--- @param fun async.CallbackFn
|
||||
--- @param ... any func arguments
|
||||
--- @return any ...
|
||||
local function await_cbfun(argc, fun, ...)
|
||||
local args = pack_len(...)
|
||||
|
||||
--- @param callback fun(...:any)
|
||||
--- @return any?
|
||||
return yield(function(callback)
|
||||
args[argc] = callback
|
||||
args.n = math.max(args.n, argc)
|
||||
return fun(unpack_len(args))
|
||||
end)
|
||||
end
|
||||
|
||||
--- @generic T, R
|
||||
--- @param taskfun async.TaskFun<T, R>
|
||||
--- @param ... T...
|
||||
--- @return R...
|
||||
local function await_taskfun(taskfun, ...)
|
||||
return taskfun._fun(...)
|
||||
end
|
||||
|
||||
--- Asynchronous blocking wait
|
||||
---
|
||||
--- Example:
|
||||
--- ```lua
|
||||
--- local task = async.arun(function()
|
||||
--- return 1, 'a'
|
||||
--- end)
|
||||
---
|
||||
--- local task_fun = async.async(function(arg)
|
||||
--- return 2, 'b', arg
|
||||
--- end)
|
||||
---
|
||||
--- async.arun(function()
|
||||
--- do -- await a callback function
|
||||
--- async.await(1, vim.schedule)
|
||||
--- end
|
||||
---
|
||||
--- do -- await a task (new async context)
|
||||
--- local n, s = async.await(task)
|
||||
--- assert(n == 1 and s == 'a')
|
||||
--- end
|
||||
---
|
||||
--- do -- await a started task function (new async context)
|
||||
--- local n, s, arg = async.await(task_fun('A'))
|
||||
--- assert(n == 2)
|
||||
--- assert(s == 'b')
|
||||
--- assert(args == 'A')
|
||||
--- end
|
||||
---
|
||||
--- do -- await a task function (re-using the current async context)
|
||||
--- local n, s, arg = async.await(task_fun, 'B')
|
||||
--- assert(n == 2)
|
||||
--- assert(s == 'b')
|
||||
--- assert(args == 'B')
|
||||
--- end
|
||||
--- end)
|
||||
--- ```
|
||||
--- @async
|
||||
--- @overload fun(argc: integer, func: async.CallbackFn, ...:any): any ...
|
||||
--- @overload fun(task: async.Task): any ...
|
||||
--- @overload fun(taskfun: async.TaskFun): any ...
|
||||
function M.await(...)
|
||||
assert(running(), 'Not in async context')
|
||||
|
||||
local arg1 = select(1, ...)
|
||||
|
||||
if type(arg1) == 'number' then
|
||||
return await_cbfun(...)
|
||||
elseif getmetatable(arg1) == Task then
|
||||
return await_task(...)
|
||||
elseif getmetatable(arg1) == TaskFun then
|
||||
return await_taskfun(...)
|
||||
end
|
||||
|
||||
error('Invalid arguments, expected Task or (argc, func) got: ' .. type(arg1), 2)
|
||||
end
|
||||
|
||||
--- Creates an async function with a callback style function.
|
||||
---
|
||||
--- Example:
|
||||
---
|
||||
--- ```lua
|
||||
--- --- Note the callback argument is not present in the return function
|
||||
--- --- @type fun(timeout: integer)
|
||||
--- local sleep = async.awrap(2, function(timeout, callback)
|
||||
--- local timer = vim.uv.new_timer()
|
||||
--- timer:start(timeout * 1000, 0, callback)
|
||||
--- -- uv_timer_t provides a close method so timer will be
|
||||
--- -- cleaned up when this function finishes
|
||||
--- return timer
|
||||
--- end)
|
||||
---
|
||||
--- async.arun(function()
|
||||
--- print('hello')
|
||||
--- sleep(2)
|
||||
--- print('world')
|
||||
--- end)
|
||||
--- ```
|
||||
---
|
||||
--- local atimer = async.awrap(
|
||||
--- @param argc integer
|
||||
--- @param func async.CallbackFn
|
||||
--- @return async function
|
||||
function M.awrap(argc, func)
|
||||
assert(type(argc) == 'number')
|
||||
assert(type(func) == 'function')
|
||||
--- @async
|
||||
return function(...)
|
||||
return M.await(argc, func, ...)
|
||||
end
|
||||
end
|
||||
|
||||
if vim.schedule then
|
||||
--- An async function that when called will yield to the Neovim scheduler to be
|
||||
--- able to call the API.
|
||||
M.schedule = M.awrap(1, vim.schedule)
|
||||
end
|
||||
|
||||
--- Create a function that runs a function when it is garbage collected.
|
||||
--- @generic F
|
||||
--- @param f F
|
||||
--- @param gc fun()
|
||||
--- @return F
|
||||
local function gc_fun(f, gc)
|
||||
local proxy = newproxy(true)
|
||||
local proxy_mt = getmetatable(proxy)
|
||||
proxy_mt.__gc = gc
|
||||
proxy_mt.__call = function(_, ...)
|
||||
return f(...)
|
||||
end
|
||||
|
||||
return proxy
|
||||
end
|
||||
|
||||
--- @param task_cbs table<async.Task,function>
|
||||
local function gc_cbs(task_cbs)
|
||||
for task, tcb in pairs(task_cbs) do
|
||||
for j, cb in pairs(task._callbacks) do
|
||||
if cb == tcb then
|
||||
task._callbacks[j] = nil
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- @async
|
||||
--- Example:
|
||||
--- ```lua
|
||||
--- local task1 = async.arun(function()
|
||||
--- return 1, 'a'
|
||||
--- end)
|
||||
---
|
||||
--- local task2 = async.arun(function()
|
||||
--- return 1, 'a'
|
||||
--- end)
|
||||
---
|
||||
--- local task3 = async.arun(function()
|
||||
--- error('task3 error')
|
||||
--- end)
|
||||
---
|
||||
--- async.arun(function()
|
||||
--- for i, err, r1, r2 in async.iter({task1, task2, task3})
|
||||
--- print(i, err, r1, r2)
|
||||
--- end
|
||||
--- end)
|
||||
--- ```
|
||||
---
|
||||
--- Prints:
|
||||
--- ```
|
||||
--- 1 nil 1 'a'
|
||||
--- 2 nil 2 'b'
|
||||
--- 3 'task3 error' nil nil
|
||||
--- ```
|
||||
---
|
||||
--- @param tasks async.Task[]
|
||||
--- @return fun(): (integer?, any?, ...)
|
||||
function M.iter(tasks)
|
||||
assert(running(), 'Not in async context')
|
||||
|
||||
local results = {} --- @type [integer, any, ...][]
|
||||
|
||||
-- Iter blocks in an async context so only one waiter is needed
|
||||
local waiter = nil
|
||||
local task_cbs = {} --- @type table<async.Task,function>
|
||||
local remaining = #tasks
|
||||
|
||||
--- If can_gc_cbs is true, then the iterator function has been garbage
|
||||
--- collected and means any awaiters can also be garbage collected. The
|
||||
--- only time we can't do this is if with the special case when iter() is
|
||||
--- called anonymously (`local i = async.iter(tasks)()`), so we should not
|
||||
--- garbage collect the callbacks until at least one awaiter is called.
|
||||
local can_gc_cbs = false
|
||||
|
||||
for i, task in ipairs(tasks) do
|
||||
local function cb(err, ...)
|
||||
if can_gc_cbs == true then
|
||||
gc_cbs(task_cbs)
|
||||
end
|
||||
|
||||
local callback = waiter
|
||||
|
||||
-- Clear waiter before calling it
|
||||
waiter = nil
|
||||
|
||||
remaining = remaining - 1
|
||||
if callback then
|
||||
-- Iterator is waiting, yield to it
|
||||
callback(i, err, ...)
|
||||
else
|
||||
-- Task finished before Iterator was called. Store results.
|
||||
table.insert(results, pack_len(i, err, ...))
|
||||
end
|
||||
end
|
||||
|
||||
task_cbs[task] = cb
|
||||
task:await(cb)
|
||||
end
|
||||
|
||||
return gc_fun(
|
||||
M.awrap(1, function(callback)
|
||||
if next(results) then
|
||||
local res = table.remove(results, 1)
|
||||
callback(unpack_len(res))
|
||||
elseif remaining == 0 then
|
||||
callback() -- finish
|
||||
else
|
||||
assert(not waiter, 'internal error: waiter already set')
|
||||
waiter = callback
|
||||
end
|
||||
end),
|
||||
function()
|
||||
-- Don't gc callbacks just yet. Wait until at least one of them is called.
|
||||
can_gc_cbs = true
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
do -- join()
|
||||
--- @param results table<integer,table>
|
||||
--- @param i integer
|
||||
--- @param ... any
|
||||
--- @return boolean
|
||||
local function collect(results, i, ...)
|
||||
if i then
|
||||
results[i] = pack_len(...)
|
||||
end
|
||||
return i ~= nil
|
||||
end
|
||||
|
||||
--- @param iter fun(): ...
|
||||
--- @return table<integer,table>
|
||||
local function drain_iter(iter)
|
||||
local results = {} --- @type table<integer,table>
|
||||
while collect(results, iter()) do
|
||||
end
|
||||
return results
|
||||
end
|
||||
|
||||
--- @async
|
||||
--- Wait for all tasks to finish and return their results.
|
||||
---
|
||||
--- Example:
|
||||
--- ```lua
|
||||
--- local task1 = async.arun(function()
|
||||
--- return 1, 'a'
|
||||
--- end)
|
||||
---
|
||||
--- local task2 = async.arun(function()
|
||||
--- return 1, 'a'
|
||||
--- end)
|
||||
---
|
||||
--- local task3 = async.arun(function()
|
||||
--- error('task3 error')
|
||||
--- end)
|
||||
---
|
||||
--- async.arun(function()
|
||||
--- local results = async.join({task1, task2, task3})
|
||||
--- print(vim.inspect(results))
|
||||
--- end)
|
||||
--- ```
|
||||
---
|
||||
--- Prints:
|
||||
--- ```
|
||||
--- {
|
||||
--- [1] = { nil, 1, 'a' },
|
||||
--- [2] = { nil, 2, 'b' },
|
||||
--- [3] = { 'task2 error' },
|
||||
--- }
|
||||
--- ```
|
||||
--- @param tasks async.Task[]
|
||||
--- @return table<integer,[any?,...?]>
|
||||
function M.join(tasks)
|
||||
assert(running(), 'Not in async context')
|
||||
return drain_iter(M.iter(tasks))
|
||||
end
|
||||
|
||||
--- @async
|
||||
--- @param tasks async.Task[]
|
||||
--- @return integer?, any?, ...?
|
||||
function M.joinany(tasks)
|
||||
return M.iter(tasks)()
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
local api = vim.api
|
||||
|
||||
local M = {}
|
||||
|
||||
-- Creates a cache table for buffers keyed by a type name.
|
||||
-- Cache entries attach to the buffer and cleanup entries
|
||||
-- as buffers are detached.
|
||||
function M.create_buffer_cache()
|
||||
local cache = {}
|
||||
|
||||
---@type table<integer, table<string, any>>
|
||||
local items = setmetatable({}, {
|
||||
__index = function(tbl, key)
|
||||
rawset(tbl, key, {})
|
||||
return rawget(tbl, key)
|
||||
end,
|
||||
})
|
||||
|
||||
---@type table<integer, boolean>
|
||||
local loaded_buffers = {}
|
||||
|
||||
---@param type_name string
|
||||
---@param bufnr integer
|
||||
---@param value any
|
||||
function cache.set(type_name, bufnr, value)
|
||||
if not loaded_buffers[bufnr] then
|
||||
loaded_buffers[bufnr] = true
|
||||
-- Clean up the cache if the buffer is detached
|
||||
-- to avoid memory leaks
|
||||
api.nvim_buf_attach(bufnr, false, {
|
||||
on_detach = function()
|
||||
cache.clear_buffer(bufnr)
|
||||
loaded_buffers[bufnr] = nil
|
||||
return true
|
||||
end,
|
||||
on_reload = function() end, -- this is needed to prevent on_detach being called on buffer reload
|
||||
})
|
||||
end
|
||||
|
||||
items[bufnr][type_name] = value
|
||||
end
|
||||
|
||||
---@param type_name string
|
||||
---@param bufnr integer
|
||||
---@return any
|
||||
function cache.get(type_name, bufnr)
|
||||
return items[bufnr][type_name]
|
||||
end
|
||||
|
||||
---@param type_name string
|
||||
---@param bufnr integer
|
||||
---@return boolean
|
||||
function cache.has(type_name, bufnr)
|
||||
return cache.get(type_name, bufnr) ~= nil
|
||||
end
|
||||
|
||||
---@param type_name string
|
||||
---@param bufnr integer
|
||||
function cache.remove(type_name, bufnr)
|
||||
items[bufnr][type_name] = nil
|
||||
end
|
||||
|
||||
---@param bufnr integer
|
||||
function cache.clear_buffer(bufnr)
|
||||
items[bufnr] = nil
|
||||
end
|
||||
|
||||
return cache
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
-- Shim module to address deprecations across nvim versions
|
||||
local ts = vim.treesitter
|
||||
local tsq = ts.query
|
||||
|
||||
local M = {}
|
||||
|
||||
function M.get_query_files(lang, query_group, is_included)
|
||||
return (tsq.get_files or tsq.get_query_files)(lang, query_group, is_included)
|
||||
end
|
||||
|
||||
function M.get_query(lang, query_name)
|
||||
return (tsq.get or tsq.get_query)(lang, query_name)
|
||||
end
|
||||
|
||||
function M.parse_query(lang, query)
|
||||
return (tsq.parse or tsq.parse_query)(lang, query)
|
||||
end
|
||||
|
||||
function M.get_range(node, source, metadata)
|
||||
return (ts.get_range or tsq.get_range)(node, source, metadata)
|
||||
end
|
||||
|
||||
function M.get_node_text(node, bufnr)
|
||||
return (ts.get_node_text or tsq.get_node_text)(node, bufnr)
|
||||
end
|
||||
|
||||
return M
|
||||
174
lua/nvim-treesitter/config.lua
Normal file
174
lua/nvim-treesitter/config.lua
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
local M = {}
|
||||
|
||||
M.tiers = { 'stable', 'unstable', 'unmaintained', 'unsupported' }
|
||||
|
||||
---@class TSConfig
|
||||
---@field install_dir string
|
||||
|
||||
---@type TSConfig
|
||||
local config = {
|
||||
install_dir = vim.fs.joinpath(vim.fn.stdpath('data') --[[@as string]], 'site'),
|
||||
}
|
||||
|
||||
---Setup call for users to override configuration configurations.
|
||||
---@param user_data TSConfig? user configuration table
|
||||
function M.setup(user_data)
|
||||
if user_data then
|
||||
if user_data.install_dir then
|
||||
user_data.install_dir = vim.fs.normalize(user_data.install_dir)
|
||||
vim.o.rtp = user_data.install_dir .. ',' .. vim.o.rtp
|
||||
end
|
||||
config = vim.tbl_deep_extend('force', config, user_data)
|
||||
end
|
||||
end
|
||||
|
||||
-- Returns the install path for parsers, parser info, and queries.
|
||||
-- If the specified directory does not exist, it is created.
|
||||
---@param dir_name string
|
||||
---@return string
|
||||
function M.get_install_dir(dir_name)
|
||||
local dir = vim.fs.joinpath(config.install_dir, dir_name)
|
||||
|
||||
if not vim.uv.fs_stat(dir) then
|
||||
local ok, err = pcall(vim.fn.mkdir, dir, 'p', '0755')
|
||||
if not ok then
|
||||
local log = require('nvim-treesitter.log')
|
||||
log.error(err --[[@as string]])
|
||||
end
|
||||
end
|
||||
return dir
|
||||
end
|
||||
|
||||
---@param type 'queries'|'parsers'?
|
||||
---@return string[]
|
||||
function M.get_installed(type)
|
||||
local installed = {} --- @type table<string, boolean>
|
||||
if not (type and type == 'parsers') then
|
||||
for f in vim.fs.dir(M.get_install_dir('queries')) do
|
||||
installed[f] = true
|
||||
end
|
||||
end
|
||||
if not (type and type == 'queries') then
|
||||
for f in vim.fs.dir(M.get_install_dir('parser')) do
|
||||
installed[vim.fn.fnamemodify(f, ':r')] = true
|
||||
end
|
||||
end
|
||||
return vim.tbl_keys(installed)
|
||||
end
|
||||
|
||||
-- Get a list of all available parsers
|
||||
---@param tier integer? only get parsers of specified tier
|
||||
---@return string[]
|
||||
function M.get_available(tier)
|
||||
vim.api.nvim_exec_autocmds('User', { pattern = 'TSUpdate' })
|
||||
local parsers = require('nvim-treesitter.parsers')
|
||||
--- @type string[]
|
||||
local languages = vim.tbl_keys(parsers)
|
||||
table.sort(languages)
|
||||
if tier then
|
||||
languages = vim.tbl_filter(
|
||||
--- @param p string
|
||||
function(p)
|
||||
return parsers[p] ~= nil and parsers[p].tier == tier
|
||||
end,
|
||||
languages
|
||||
)
|
||||
end
|
||||
return languages
|
||||
end
|
||||
|
||||
local function expand_tiers(list)
|
||||
for i, tier in ipairs(M.tiers) do
|
||||
if vim.list_contains(list, tier) then
|
||||
list = vim.tbl_filter(
|
||||
--- @param l string
|
||||
function(l)
|
||||
return l ~= tier
|
||||
end,
|
||||
list
|
||||
)
|
||||
vim.list_extend(list, M.get_available(i))
|
||||
end
|
||||
end
|
||||
|
||||
return list
|
||||
end
|
||||
|
||||
---Normalize languages
|
||||
---@param languages? string[]|string
|
||||
---@param skip? { missing: boolean?, unsupported: boolean?, installed: boolean?, dependencies: boolean? }
|
||||
---@return string[]
|
||||
function M.norm_languages(languages, skip)
|
||||
if not languages then
|
||||
return {}
|
||||
elseif type(languages) == 'string' then
|
||||
languages = { languages }
|
||||
end
|
||||
|
||||
if vim.list_contains(languages, 'all') then
|
||||
if skip and skip.missing then
|
||||
return M.get_installed()
|
||||
end
|
||||
languages = M.get_available()
|
||||
end
|
||||
|
||||
languages = expand_tiers(languages)
|
||||
|
||||
if skip and skip.installed then
|
||||
local installed = M.get_installed()
|
||||
languages = vim.tbl_filter(
|
||||
--- @param v string
|
||||
function(v)
|
||||
return not vim.list_contains(installed, v)
|
||||
end,
|
||||
languages
|
||||
)
|
||||
end
|
||||
|
||||
if skip and skip.missing then
|
||||
local installed = M.get_installed()
|
||||
languages = vim.tbl_filter(
|
||||
--- @param v string
|
||||
function(v)
|
||||
return vim.list_contains(installed, v)
|
||||
end,
|
||||
languages
|
||||
)
|
||||
end
|
||||
|
||||
local parsers = require('nvim-treesitter.parsers')
|
||||
languages = vim.tbl_filter(
|
||||
--- @param v string
|
||||
function(v)
|
||||
if parsers[v] ~= nil then
|
||||
return true
|
||||
else
|
||||
require('nvim-treesitter.log').warn('skipping unsupported language: ' .. v)
|
||||
return false
|
||||
end
|
||||
end,
|
||||
languages
|
||||
)
|
||||
|
||||
if skip and skip.unsupported then
|
||||
languages = vim.tbl_filter(
|
||||
--- @param v string
|
||||
function(v)
|
||||
return not (parsers[v] and parsers[v].tier and parsers[v].tier == 4)
|
||||
end,
|
||||
languages
|
||||
)
|
||||
end
|
||||
|
||||
if not (skip and skip.dependencies) then
|
||||
for _, lang in pairs(languages) do
|
||||
if parsers[lang] and parsers[lang].requires then
|
||||
vim.list_extend(languages, parsers[lang].requires)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return vim.list.unique(languages)
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
@ -1,616 +0,0 @@
|
|||
local api = vim.api
|
||||
|
||||
local queries = require "nvim-treesitter.query"
|
||||
local ts = require "nvim-treesitter.compat"
|
||||
local parsers = require "nvim-treesitter.parsers"
|
||||
local utils = require "nvim-treesitter.utils"
|
||||
local caching = require "nvim-treesitter.caching"
|
||||
|
||||
local M = {}
|
||||
|
||||
---@class TSConfig
|
||||
---@field modules {[string]:TSModule}
|
||||
---@field sync_install boolean
|
||||
---@field ensure_installed string[]|string
|
||||
---@field ignore_install string[]
|
||||
---@field auto_install boolean
|
||||
---@field parser_install_dir string|nil
|
||||
|
||||
---@type TSConfig
|
||||
local config = {
|
||||
modules = {},
|
||||
sync_install = false,
|
||||
ensure_installed = {},
|
||||
auto_install = false,
|
||||
ignore_install = {},
|
||||
parser_install_dir = nil,
|
||||
}
|
||||
|
||||
-- List of modules that need to be setup on initialization.
|
||||
---@type TSModule[][]
|
||||
local queued_modules_defs = {}
|
||||
-- Whether we've initialized the plugin yet.
|
||||
local is_initialized = false
|
||||
|
||||
---@class TSModule
|
||||
---@field module_path string
|
||||
---@field enable boolean|string[]|function(string): boolean
|
||||
---@field disable boolean|string[]|function(string): boolean
|
||||
---@field keymaps table<string, string>
|
||||
---@field is_supported function(string): boolean
|
||||
---@field attach function(string)
|
||||
---@field detach function(string)
|
||||
---@field enabled_buffers table<integer, boolean>
|
||||
---@field additional_vim_regex_highlighting boolean|string[]
|
||||
|
||||
---@type {[string]: TSModule}
|
||||
local builtin_modules = {
|
||||
highlight = {
|
||||
module_path = "nvim-treesitter.highlight",
|
||||
-- @deprecated: use `highlight.set_custom_captures` instead
|
||||
custom_captures = {},
|
||||
enable = false,
|
||||
is_supported = function(lang)
|
||||
return queries.has_highlights(lang)
|
||||
end,
|
||||
additional_vim_regex_highlighting = false,
|
||||
},
|
||||
incremental_selection = {
|
||||
module_path = "nvim-treesitter.incremental_selection",
|
||||
enable = false,
|
||||
keymaps = {
|
||||
init_selection = "gnn", -- set to `false` to disable one of the mappings
|
||||
node_incremental = "grn",
|
||||
scope_incremental = "grc",
|
||||
node_decremental = "grm",
|
||||
},
|
||||
is_supported = function()
|
||||
return true
|
||||
end,
|
||||
},
|
||||
indent = {
|
||||
module_path = "nvim-treesitter.indent",
|
||||
enable = false,
|
||||
is_supported = queries.has_indents,
|
||||
},
|
||||
}
|
||||
|
||||
local attached_buffers_by_module = caching.create_buffer_cache()
|
||||
|
||||
---Resolves a module by requiring the `module_path` or using the module definition.
|
||||
---@param mod_name string
|
||||
---@return TSModule|nil
|
||||
local function resolve_module(mod_name)
|
||||
local config_mod = M.get_module(mod_name)
|
||||
|
||||
if not config_mod then
|
||||
return
|
||||
end
|
||||
|
||||
if type(config_mod.attach) == "function" and type(config_mod.detach) == "function" then
|
||||
return config_mod
|
||||
elseif type(config_mod.module_path) == "string" then
|
||||
return require(config_mod.module_path)
|
||||
end
|
||||
end
|
||||
|
||||
---Enables and attaches the module to a buffer for lang.
|
||||
---@param mod string path to module
|
||||
---@param bufnr integer|nil buffer number, defaults to current buffer
|
||||
---@param lang string|nil language, defaults to current language
|
||||
local function enable_module(mod, bufnr, lang)
|
||||
local module = M.get_module(mod)
|
||||
if not module then
|
||||
return
|
||||
end
|
||||
|
||||
bufnr = bufnr or api.nvim_get_current_buf()
|
||||
lang = lang or parsers.get_buf_lang(bufnr)
|
||||
|
||||
if not module.enable then
|
||||
if module.enabled_buffers then
|
||||
module.enabled_buffers[bufnr] = true
|
||||
else
|
||||
module.enabled_buffers = { [bufnr] = true }
|
||||
end
|
||||
end
|
||||
|
||||
M.attach_module(mod, bufnr, lang)
|
||||
end
|
||||
|
||||
---Enables autocomands for the module.
|
||||
---After the module is loaded `loaded` will be set to true for the module.
|
||||
---@param mod string path to module
|
||||
local function enable_mod_conf_autocmd(mod)
|
||||
local config_mod = M.get_module(mod)
|
||||
if not config_mod or config_mod.loaded then
|
||||
return
|
||||
end
|
||||
|
||||
api.nvim_create_autocmd("FileType", {
|
||||
group = api.nvim_create_augroup("NvimTreesitter-" .. mod, {}),
|
||||
callback = function(args)
|
||||
require("nvim-treesitter.configs").reattach_module(mod, args.buf)
|
||||
end,
|
||||
desc = "Reattach module",
|
||||
})
|
||||
|
||||
config_mod.loaded = true
|
||||
end
|
||||
|
||||
---Enables the module globally and for all current buffers.
|
||||
---After enabled, `enable` will be set to true for the module.
|
||||
---@param mod string path to module
|
||||
local function enable_all(mod)
|
||||
local config_mod = M.get_module(mod)
|
||||
if not config_mod then
|
||||
return
|
||||
end
|
||||
|
||||
enable_mod_conf_autocmd(mod)
|
||||
config_mod.enable = true
|
||||
config_mod.enabled_buffers = nil
|
||||
|
||||
for _, bufnr in pairs(api.nvim_list_bufs()) do
|
||||
enable_module(mod, bufnr)
|
||||
end
|
||||
end
|
||||
|
||||
---Disables and detaches the module for a buffer.
|
||||
---@param mod string path to module
|
||||
---@param bufnr integer buffer number, defaults to current buffer
|
||||
local function disable_module(mod, bufnr)
|
||||
local module = M.get_module(mod)
|
||||
if not module then
|
||||
return
|
||||
end
|
||||
|
||||
bufnr = bufnr or api.nvim_get_current_buf()
|
||||
if module.enabled_buffers then
|
||||
module.enabled_buffers[bufnr] = false
|
||||
end
|
||||
M.detach_module(mod, bufnr)
|
||||
end
|
||||
|
||||
---Disables autocomands for the module.
|
||||
---After the module is unloaded `loaded` will be set to false for the module.
|
||||
---@param mod string path to module
|
||||
local function disable_mod_conf_autocmd(mod)
|
||||
local config_mod = M.get_module(mod)
|
||||
if not config_mod or not config_mod.loaded then
|
||||
return
|
||||
end
|
||||
api.nvim_clear_autocmds { event = "FileType", group = "NvimTreesitter-" .. mod }
|
||||
config_mod.loaded = false
|
||||
end
|
||||
|
||||
---Disables the module globally and for all current buffers.
|
||||
---After disabled, `enable` will be set to false for the module.
|
||||
---@param mod string path to module
|
||||
local function disable_all(mod)
|
||||
local config_mod = M.get_module(mod)
|
||||
if not config_mod then
|
||||
return
|
||||
end
|
||||
|
||||
config_mod.enabled_buffers = nil
|
||||
disable_mod_conf_autocmd(mod)
|
||||
config_mod.enable = false
|
||||
|
||||
for _, bufnr in pairs(api.nvim_list_bufs()) do
|
||||
disable_module(mod, bufnr)
|
||||
end
|
||||
end
|
||||
|
||||
---Toggles a module for a buffer
|
||||
---@param mod string path to module
|
||||
---@param bufnr integer buffer number, defaults to current buffer
|
||||
---@param lang string language, defaults to current language
|
||||
local function toggle_module(mod, bufnr, lang)
|
||||
bufnr = bufnr or api.nvim_get_current_buf()
|
||||
lang = lang or parsers.get_buf_lang(bufnr)
|
||||
|
||||
if attached_buffers_by_module.has(mod, bufnr) then
|
||||
disable_module(mod, bufnr)
|
||||
else
|
||||
enable_module(mod, bufnr, lang)
|
||||
end
|
||||
end
|
||||
|
||||
-- Toggles the module globally and for all current buffers.
|
||||
-- @param mod path to module
|
||||
local function toggle_all(mod)
|
||||
local config_mod = M.get_module(mod)
|
||||
if not config_mod then
|
||||
return
|
||||
end
|
||||
|
||||
if config_mod.enable then
|
||||
disable_all(mod)
|
||||
else
|
||||
enable_all(mod)
|
||||
end
|
||||
end
|
||||
|
||||
---Recurses through all modules including submodules
|
||||
---@param accumulator function called for each module
|
||||
---@param root {[string]: TSModule}|nil root configuration table to start at
|
||||
---@param path string|nil prefix path
|
||||
local function recurse_modules(accumulator, root, path)
|
||||
root = root or config.modules
|
||||
|
||||
for name, module in pairs(root) do
|
||||
local new_path = path and (path .. "." .. name) or name
|
||||
|
||||
if M.is_module(module) then
|
||||
accumulator(name, module, new_path, root)
|
||||
elseif type(module) == "table" then
|
||||
recurse_modules(accumulator, module, new_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Shows current configuration of all nvim-treesitter modules
|
||||
---@param process_function function used as the `process` parameter
|
||||
--- for vim.inspect (https://github.com/kikito/inspect.lua#optionsprocess)
|
||||
local function config_info(process_function)
|
||||
process_function = process_function
|
||||
or function(item, path)
|
||||
if path[#path] == vim.inspect.METATABLE then
|
||||
return
|
||||
end
|
||||
if path[#path] == "is_supported" then
|
||||
return
|
||||
end
|
||||
return item
|
||||
end
|
||||
print(vim.inspect(config, { process = process_function }))
|
||||
end
|
||||
|
||||
---@param query_group string
|
||||
---@param lang string
|
||||
function M.edit_query_file(query_group, lang)
|
||||
lang = lang or parsers.get_buf_lang()
|
||||
local files = ts.get_query_files(lang, query_group, true)
|
||||
if #files == 0 then
|
||||
utils.notify "No query file found! Creating a new one!"
|
||||
M.edit_query_file_user_after(query_group, lang)
|
||||
elseif #files == 1 then
|
||||
vim.cmd(":edit " .. files[1])
|
||||
else
|
||||
vim.ui.select(files, { prompt = "Select a file:" }, function(file)
|
||||
if file then
|
||||
vim.cmd(":edit " .. file)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
---@param query_group string
|
||||
---@param lang string
|
||||
function M.edit_query_file_user_after(query_group, lang)
|
||||
lang = lang or parsers.get_buf_lang()
|
||||
local folder = utils.join_path(vim.fn.stdpath "config", "after", "queries", lang)
|
||||
local file = utils.join_path(folder, query_group .. ".scm")
|
||||
if vim.fn.isdirectory(folder) ~= 1 then
|
||||
vim.ui.select({ "Yes", "No" }, { prompt = '"' .. folder .. '" does not exist. Create it?' }, function(choice)
|
||||
if choice == "Yes" then
|
||||
vim.fn.mkdir(folder, "p", "0755")
|
||||
vim.cmd(":edit " .. file)
|
||||
end
|
||||
end)
|
||||
else
|
||||
vim.cmd(":edit " .. file)
|
||||
end
|
||||
end
|
||||
|
||||
M.commands = {
|
||||
TSBufEnable = {
|
||||
run = enable_module,
|
||||
args = {
|
||||
"-nargs=1",
|
||||
"-complete=custom,nvim_treesitter#available_modules",
|
||||
},
|
||||
},
|
||||
TSBufDisable = {
|
||||
run = disable_module,
|
||||
args = {
|
||||
"-nargs=1",
|
||||
"-complete=custom,nvim_treesitter#available_modules",
|
||||
},
|
||||
},
|
||||
TSBufToggle = {
|
||||
run = toggle_module,
|
||||
args = {
|
||||
"-nargs=1",
|
||||
"-complete=custom,nvim_treesitter#available_modules",
|
||||
},
|
||||
},
|
||||
TSEnable = {
|
||||
run = enable_all,
|
||||
args = {
|
||||
"-nargs=+",
|
||||
"-complete=custom,nvim_treesitter#available_modules",
|
||||
},
|
||||
},
|
||||
TSDisable = {
|
||||
run = disable_all,
|
||||
args = {
|
||||
"-nargs=+",
|
||||
"-complete=custom,nvim_treesitter#available_modules",
|
||||
},
|
||||
},
|
||||
TSToggle = {
|
||||
run = toggle_all,
|
||||
args = {
|
||||
"-nargs=+",
|
||||
"-complete=custom,nvim_treesitter#available_modules",
|
||||
},
|
||||
},
|
||||
TSConfigInfo = {
|
||||
run = config_info,
|
||||
args = {
|
||||
"-nargs=0",
|
||||
},
|
||||
},
|
||||
TSEditQuery = {
|
||||
run = M.edit_query_file,
|
||||
args = {
|
||||
"-nargs=+",
|
||||
"-complete=custom,nvim_treesitter#available_query_groups",
|
||||
},
|
||||
},
|
||||
TSEditQueryUserAfter = {
|
||||
run = M.edit_query_file_user_after,
|
||||
args = {
|
||||
"-nargs=+",
|
||||
"-complete=custom,nvim_treesitter#available_query_groups",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
---@param mod string module
|
||||
---@param lang string the language of the buffer
|
||||
---@param bufnr integer the buffer
|
||||
function M.is_enabled(mod, lang, bufnr)
|
||||
if not parsers.has_parser(lang) then
|
||||
return false
|
||||
end
|
||||
|
||||
local module_config = M.get_module(mod)
|
||||
if not module_config then
|
||||
return false
|
||||
end
|
||||
|
||||
local buffer_enabled = module_config.enabled_buffers and module_config.enabled_buffers[bufnr]
|
||||
local config_enabled = module_config.enable or buffer_enabled
|
||||
if not config_enabled or not module_config.is_supported(lang) then
|
||||
return false
|
||||
end
|
||||
|
||||
local disable = module_config.disable
|
||||
if type(disable) == "function" then
|
||||
if disable(lang, bufnr) then
|
||||
return false
|
||||
end
|
||||
elseif type(disable) == "table" then
|
||||
-- Otherwise it's a list of languages
|
||||
for _, parser in pairs(disable) do
|
||||
if lang == parser then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
---Setup call for users to override module configurations.
|
||||
---@param user_data TSConfig module overrides
|
||||
function M.setup(user_data)
|
||||
config.modules = vim.tbl_deep_extend("force", config.modules, user_data)
|
||||
config.ignore_install = user_data.ignore_install or {}
|
||||
config.parser_install_dir = user_data.parser_install_dir or nil
|
||||
if config.parser_install_dir then
|
||||
config.parser_install_dir = vim.fn.expand(config.parser_install_dir, ":p")
|
||||
end
|
||||
|
||||
config.auto_install = user_data.auto_install or false
|
||||
if config.auto_install then
|
||||
require("nvim-treesitter.install").setup_auto_install()
|
||||
end
|
||||
|
||||
local ensure_installed = user_data.ensure_installed or {}
|
||||
if #ensure_installed > 0 then
|
||||
if user_data.sync_install then
|
||||
require("nvim-treesitter.install").ensure_installed_sync(ensure_installed)
|
||||
else
|
||||
require("nvim-treesitter.install").ensure_installed(ensure_installed)
|
||||
end
|
||||
end
|
||||
|
||||
config.modules.ensure_installed = nil
|
||||
config.ensure_installed = ensure_installed
|
||||
|
||||
recurse_modules(function(_, _, new_path)
|
||||
local data = utils.get_at_path(config.modules, new_path)
|
||||
if data.enable then
|
||||
enable_all(new_path)
|
||||
end
|
||||
end, config.modules)
|
||||
end
|
||||
|
||||
-- Defines a table of modules that can be attached/detached to buffers
|
||||
-- based on language support. A module consist of the following properties:
|
||||
---* @enable Whether the modules is enabled. Can be true or false.
|
||||
---* @disable A list of languages to disable the module for. Only relevant if enable is true.
|
||||
---* @keymaps A list of user mappings for a given module if relevant.
|
||||
---* @is_supported A function which, given a ft, will return true if the ft works on the module.
|
||||
---* @module_path A string path to a module file using `require`. The exported module must contain
|
||||
--- an `attach` and `detach` function. This path is not required if `attach` and `detach`
|
||||
--- functions are provided directly on the module definition.
|
||||
---* @attach An attach function that is called for each buffer that the module is enabled for. This is required
|
||||
--- if a `module_path` is not specified.
|
||||
---* @detach A detach function that is called for each buffer that the module is enabled for. This is required
|
||||
--- if a `module_path` is not specified.
|
||||
--
|
||||
-- Modules are not setup until `init` is invoked by the plugin. This allows modules to be defined in any order
|
||||
-- and can be loaded lazily.
|
||||
--
|
||||
---* @example
|
||||
---require"nvim-treesitter".define_modules {
|
||||
--- my_cool_module = {
|
||||
--- attach = function()
|
||||
--- do_some_cool_setup()
|
||||
--- end,
|
||||
--- detach = function()
|
||||
--- do_some_cool_teardown()
|
||||
--- end
|
||||
--- }
|
||||
---}
|
||||
---@param mod_defs TSModule[]
|
||||
function M.define_modules(mod_defs)
|
||||
if not is_initialized then
|
||||
table.insert(queued_modules_defs, mod_defs)
|
||||
return
|
||||
end
|
||||
|
||||
recurse_modules(function(key, mod, _, group)
|
||||
group[key] = vim.tbl_extend("keep", mod, {
|
||||
enable = false,
|
||||
disable = {},
|
||||
is_supported = function()
|
||||
return true
|
||||
end,
|
||||
})
|
||||
end, mod_defs)
|
||||
|
||||
config.modules = vim.tbl_deep_extend("keep", config.modules, mod_defs)
|
||||
|
||||
for _, mod in ipairs(M.available_modules(mod_defs)) do
|
||||
local module_config = M.get_module(mod)
|
||||
if module_config and module_config.enable then
|
||||
enable_mod_conf_autocmd(mod)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---Attaches a module to a buffer
|
||||
---@param mod_name string the module name
|
||||
---@param bufnr integer the buffer
|
||||
---@param lang string the language of the buffer
|
||||
function M.attach_module(mod_name, bufnr, lang)
|
||||
bufnr = bufnr or api.nvim_get_current_buf()
|
||||
lang = lang or parsers.get_buf_lang(bufnr)
|
||||
local resolved_mod = resolve_module(mod_name)
|
||||
|
||||
if resolved_mod and not attached_buffers_by_module.has(mod_name, bufnr) and M.is_enabled(mod_name, lang, bufnr) then
|
||||
attached_buffers_by_module.set(mod_name, bufnr, true)
|
||||
resolved_mod.attach(bufnr, lang)
|
||||
end
|
||||
end
|
||||
|
||||
-- Detaches a module to a buffer
|
||||
---@param mod_name string the module name
|
||||
---@param bufnr integer the buffer
|
||||
function M.detach_module(mod_name, bufnr)
|
||||
local resolved_mod = resolve_module(mod_name)
|
||||
bufnr = bufnr or api.nvim_get_current_buf()
|
||||
|
||||
if resolved_mod and attached_buffers_by_module.has(mod_name, bufnr) then
|
||||
attached_buffers_by_module.remove(mod_name, bufnr)
|
||||
resolved_mod.detach(bufnr)
|
||||
end
|
||||
end
|
||||
|
||||
-- Same as attach_module, but if the module is already attached, detach it first.
|
||||
---@param mod_name string the module name
|
||||
---@param bufnr integer the buffer
|
||||
---@param lang string the language of the buffer
|
||||
function M.reattach_module(mod_name, bufnr, lang)
|
||||
M.detach_module(mod_name, bufnr)
|
||||
M.attach_module(mod_name, bufnr, lang)
|
||||
end
|
||||
|
||||
-- Gets available modules
|
||||
---@param root {[string]:TSModule}|nil table to find modules
|
||||
---@return string[] modules list of module paths
|
||||
function M.available_modules(root)
|
||||
local modules = {}
|
||||
|
||||
recurse_modules(function(_, _, path)
|
||||
table.insert(modules, path)
|
||||
end, root)
|
||||
|
||||
return modules
|
||||
end
|
||||
|
||||
---Gets a module config by path
|
||||
---@param mod_path string path to the module
|
||||
---@return TSModule|nil: the module or nil
|
||||
function M.get_module(mod_path)
|
||||
local mod = utils.get_at_path(config.modules, mod_path)
|
||||
|
||||
return M.is_module(mod) and mod or nil
|
||||
end
|
||||
|
||||
-- Determines whether the provided table is a module.
|
||||
-- A module should contain an attach and detach function.
|
||||
---@param mod table|nil the module table
|
||||
---@return boolean
|
||||
function M.is_module(mod)
|
||||
return type(mod) == "table"
|
||||
and ((type(mod.attach) == "function" and type(mod.detach) == "function") or type(mod.module_path) == "string")
|
||||
end
|
||||
|
||||
-- Initializes built-in modules and any queued modules
|
||||
-- registered by plugins or the user.
|
||||
function M.init()
|
||||
is_initialized = true
|
||||
M.define_modules(builtin_modules)
|
||||
|
||||
for _, mod_def in ipairs(queued_modules_defs) do
|
||||
M.define_modules(mod_def)
|
||||
end
|
||||
end
|
||||
|
||||
-- If parser_install_dir is not nil is used or created.
|
||||
-- If parser_install_dir is nil try the package dir of the nvim-treesitter
|
||||
-- plugin first, followed by the "site" dir from "runtimepath". "site" dir will
|
||||
-- be created if it doesn't exist. Using only the package dir won't work when
|
||||
-- the plugin is installed with Nix, since the "/nix/store" is read-only.
|
||||
---@param folder_name string|nil
|
||||
---@return string|nil, string|nil
|
||||
function M.get_parser_install_dir(folder_name)
|
||||
folder_name = folder_name or "parser"
|
||||
|
||||
local install_dir = config.parser_install_dir or utils.get_package_path()
|
||||
local parser_dir = utils.join_path(install_dir, folder_name)
|
||||
|
||||
return utils.create_or_reuse_writable_dir(
|
||||
parser_dir,
|
||||
utils.join_space("Could not create parser dir '", parser_dir, "': "),
|
||||
utils.join_space(
|
||||
"Parser dir '",
|
||||
parser_dir,
|
||||
"' should be read/write (see README on how to configure an alternative install location)"
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
function M.get_parser_info_dir()
|
||||
return M.get_parser_install_dir "parser-info"
|
||||
end
|
||||
|
||||
function M.get_ignored_parser_installs()
|
||||
return config.ignore_install or {}
|
||||
end
|
||||
|
||||
function M.get_ensure_installed_parsers()
|
||||
if type(config.ensure_installed) == "string" then
|
||||
return { config.ensure_installed }
|
||||
end
|
||||
return config.ensure_installed or {}
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
local api = vim.api
|
||||
local tsutils = require "nvim-treesitter.ts_utils"
|
||||
local query = require "nvim-treesitter.query"
|
||||
local parsers = require "nvim-treesitter.parsers"
|
||||
|
||||
local M = {}
|
||||
|
||||
-- This is cached on buf tick to avoid computing that multiple times
|
||||
-- Especially not for every line in the file when `zx` is hit
|
||||
local folds_levels = tsutils.memoize_by_buf_tick(function(bufnr)
|
||||
local max_fold_level = api.nvim_win_get_option(0, "foldnestmax")
|
||||
local trim_level = function(level)
|
||||
if level > max_fold_level then
|
||||
return max_fold_level
|
||||
end
|
||||
return level
|
||||
end
|
||||
|
||||
local parser = parsers.get_parser(bufnr)
|
||||
|
||||
if not parser then
|
||||
return {}
|
||||
end
|
||||
|
||||
local matches = query.get_capture_matches_recursively(bufnr, function(lang)
|
||||
if query.has_folds(lang) then
|
||||
return "@fold", "folds"
|
||||
elseif query.has_locals(lang) then
|
||||
return "@scope", "locals"
|
||||
end
|
||||
end)
|
||||
|
||||
-- start..stop is an inclusive range
|
||||
|
||||
---@type table<number, number>
|
||||
local start_counts = {}
|
||||
---@type table<number, number>
|
||||
local stop_counts = {}
|
||||
|
||||
local prev_start = -1
|
||||
local prev_stop = -1
|
||||
|
||||
local min_fold_lines = api.nvim_win_get_option(0, "foldminlines")
|
||||
|
||||
for _, match in ipairs(matches) do
|
||||
local start, stop, stop_col ---@type integer, integer, integer
|
||||
if match.metadata and match.metadata.range then
|
||||
start, _, stop, stop_col = unpack(match.metadata.range) ---@type integer, integer, integer, integer
|
||||
else
|
||||
start, _, stop, stop_col = match.node:range() ---@type integer, integer, integer, integer
|
||||
end
|
||||
|
||||
if stop_col == 0 then
|
||||
stop = stop - 1
|
||||
end
|
||||
|
||||
local fold_length = stop - start + 1
|
||||
local should_fold = fold_length > min_fold_lines
|
||||
|
||||
-- Fold only multiline nodes that are not exactly the same as previously met folds
|
||||
-- Checking against just the previously found fold is sufficient if nodes
|
||||
-- are returned in preorder or postorder when traversing tree
|
||||
if should_fold and not (start == prev_start and stop == prev_stop) then
|
||||
start_counts[start] = (start_counts[start] or 0) + 1
|
||||
stop_counts[stop] = (stop_counts[stop] or 0) + 1
|
||||
prev_start = start
|
||||
prev_stop = stop
|
||||
end
|
||||
end
|
||||
|
||||
---@type string[]
|
||||
local levels = {}
|
||||
local current_level = 0
|
||||
|
||||
-- We now have the list of fold opening and closing, fill the gaps and mark where fold start
|
||||
for lnum = 0, api.nvim_buf_line_count(bufnr) do
|
||||
local prefix = ""
|
||||
|
||||
local last_trimmed_level = trim_level(current_level)
|
||||
current_level = current_level + (start_counts[lnum] or 0)
|
||||
local trimmed_level = trim_level(current_level)
|
||||
current_level = current_level - (stop_counts[lnum] or 0)
|
||||
local next_trimmed_level = trim_level(current_level)
|
||||
|
||||
-- Determine if it's the start/end of a fold
|
||||
-- NB: vim's fold-expr interface does not have a mechanism to indicate that
|
||||
-- two (or more) folds start at this line, so it cannot distinguish between
|
||||
-- ( \n ( \n )) \n (( \n ) \n )
|
||||
-- versus
|
||||
-- ( \n ( \n ) \n ( \n ) \n )
|
||||
-- If it did have such a mechanism, (trimmed_level - last_trimmed_level)
|
||||
-- would be the correct number of starts to pass on.
|
||||
if trimmed_level - last_trimmed_level > 0 then
|
||||
prefix = ">"
|
||||
elseif trimmed_level - next_trimmed_level > 0 then
|
||||
-- Ending marks tend to confuse vim more than it helps, particularly when
|
||||
-- the fold level changes by at least 2; we can uncomment this if
|
||||
-- vim's behavior gets fixed.
|
||||
-- prefix = "<"
|
||||
prefix = ""
|
||||
end
|
||||
|
||||
levels[lnum + 1] = prefix .. tostring(trimmed_level)
|
||||
end
|
||||
|
||||
return levels
|
||||
end)
|
||||
|
||||
---@param lnum integer
|
||||
---@return string
|
||||
function M.get_fold_indic(lnum)
|
||||
if not parsers.has_parser() or not lnum then
|
||||
return "0"
|
||||
end
|
||||
|
||||
local buf = api.nvim_get_current_buf()
|
||||
|
||||
local levels = folds_levels(buf) or {}
|
||||
|
||||
return levels[lnum] or "0"
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
@ -1,176 +1,174 @@
|
|||
local api = vim.api
|
||||
local fn = vim.fn
|
||||
|
||||
local queries = require "nvim-treesitter.query"
|
||||
local info = require "nvim-treesitter.info"
|
||||
local shell = require "nvim-treesitter.shell_command_selectors"
|
||||
local install = require "nvim-treesitter.install"
|
||||
local utils = require "nvim-treesitter.utils"
|
||||
local ts = require "nvim-treesitter.compat"
|
||||
|
||||
local health = vim.health or require "health"
|
||||
|
||||
-- "report_" prefix has been deprecated, use the recommended replacements if they exist.
|
||||
local _start = health.start or health.report_start
|
||||
local _ok = health.ok or health.report_ok
|
||||
local _warn = health.warn or health.report_warn
|
||||
local _error = health.error or health.report_error
|
||||
local parsers = require('nvim-treesitter.parsers')
|
||||
local config = require('nvim-treesitter.config')
|
||||
local util = require('nvim-treesitter.util')
|
||||
local tsq = vim.treesitter.query
|
||||
local health = vim.health
|
||||
|
||||
local M = {}
|
||||
|
||||
local NVIM_TREESITTER_MINIMUM_ABI = 13
|
||||
local TREE_SITTER_MIN_VER = { 0, 26, 1 }
|
||||
|
||||
---@param name string
|
||||
---@return table?
|
||||
local function check_exe(name)
|
||||
if vim.fn.executable(name) == 1 then
|
||||
local path = vim.fn.exepath(name)
|
||||
local out = vim.trim(vim.fn.system({ name, '--version' }))
|
||||
local version = vim.version.parse(out)
|
||||
return { path = path, version = version, out = out }
|
||||
end
|
||||
end
|
||||
|
||||
local function install_health()
|
||||
_start "Installation"
|
||||
health.start('Requirements')
|
||||
|
||||
if fn.has "nvim-0.9.2" ~= 1 then
|
||||
_error "Nvim-treesitter requires Nvim 0.9.2 or newer"
|
||||
end
|
||||
do -- nvim check
|
||||
if vim.fn.has('nvim-0.12') ~= 1 then
|
||||
health.error('Nvim-treesitter requires Neovim 0.12.0 or later.')
|
||||
end
|
||||
|
||||
if fn.executable "tree-sitter" == 0 then
|
||||
_warn(
|
||||
"`tree-sitter` executable not found (parser generator, only needed for :TSInstallFromGrammar,"
|
||||
.. " not required for :TSInstall)"
|
||||
)
|
||||
else
|
||||
_ok(
|
||||
"`tree-sitter` found "
|
||||
.. (utils.ts_cli_version() or "(unknown version)")
|
||||
.. " (parser generator, only needed for :TSInstallFromGrammar)"
|
||||
)
|
||||
end
|
||||
|
||||
if fn.executable "node" == 0 then
|
||||
_warn("`node` executable not found (only needed for :TSInstallFromGrammar," .. " not required for :TSInstall)")
|
||||
else
|
||||
local handle = io.popen "node --version"
|
||||
local result = handle:read "*a"
|
||||
handle:close()
|
||||
local version = vim.split(result, "\n")[1]
|
||||
_ok("`node` found " .. version .. " (only needed for :TSInstallFromGrammar)")
|
||||
end
|
||||
|
||||
if fn.executable "git" == 0 then
|
||||
_error("`git` executable not found.", {
|
||||
"Install it with your package manager.",
|
||||
"Check that your `$PATH` is set correctly.",
|
||||
})
|
||||
else
|
||||
_ok "`git` executable found."
|
||||
end
|
||||
|
||||
local cc = shell.select_executable(install.compilers)
|
||||
if not cc then
|
||||
_error("`cc` executable not found.", {
|
||||
"Check that any of "
|
||||
.. vim.inspect(install.compilers)
|
||||
.. " is in your $PATH"
|
||||
.. ' or set the environment variable CC or `require"nvim-treesitter.install".compilers` explicitly!',
|
||||
})
|
||||
else
|
||||
local version = vim.fn.systemlist(cc .. (cc == "cl" and "" or " --version"))[1]
|
||||
_ok(
|
||||
"`"
|
||||
.. cc
|
||||
.. "` executable found. Selected from "
|
||||
.. vim.inspect(install.compilers)
|
||||
.. (version and ("\nVersion: " .. version) or "")
|
||||
)
|
||||
end
|
||||
if vim.treesitter.language_version then
|
||||
if vim.treesitter.language_version >= NVIM_TREESITTER_MINIMUM_ABI then
|
||||
_ok(
|
||||
"Neovim was compiled with tree-sitter runtime ABI version "
|
||||
health.ok(
|
||||
'Neovim was compiled with tree-sitter runtime ABI version '
|
||||
.. vim.treesitter.language_version
|
||||
.. " (required >="
|
||||
.. ' (required >='
|
||||
.. NVIM_TREESITTER_MINIMUM_ABI
|
||||
.. "). Parsers must be compatible with runtime ABI."
|
||||
.. ').'
|
||||
)
|
||||
else
|
||||
_error(
|
||||
"Neovim was compiled with tree-sitter runtime ABI version "
|
||||
health.error(
|
||||
'Neovim was compiled with tree-sitter runtime ABI version '
|
||||
.. vim.treesitter.language_version
|
||||
.. ".\n"
|
||||
.. "nvim-treesitter expects at least ABI version "
|
||||
.. '.\n'
|
||||
.. 'nvim-treesitter expects at least ABI version '
|
||||
.. NVIM_TREESITTER_MINIMUM_ABI
|
||||
.. "\n"
|
||||
.. "Please make sure that Neovim is linked against are recent tree-sitter runtime when building"
|
||||
.. " or raise an issue at your Neovim packager. Parsers must be compatible with runtime ABI."
|
||||
.. '\n'
|
||||
.. 'Please make sure that Neovim is linked against a recent tree-sitter library when building'
|
||||
.. ' or raise an issue at your Neovim packager. Parsers must be compatible with runtime ABI.'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
_start("OS Info:\n" .. vim.inspect(vim.loop.os_uname()))
|
||||
do -- treesitter check
|
||||
local ts = check_exe('tree-sitter')
|
||||
if ts then
|
||||
if vim.version.ge(ts.version, TREE_SITTER_MIN_VER) then
|
||||
health.ok(string.format('tree-sitter-cli %s (%s)', ts.version, ts.path))
|
||||
else
|
||||
health.error(
|
||||
string.format('tree-sitter-cli v%d.%d.%d is required', unpack(TREE_SITTER_MIN_VER))
|
||||
)
|
||||
end
|
||||
else
|
||||
health.error('tree-sitter-cli not found')
|
||||
end
|
||||
end
|
||||
|
||||
do -- curl+tar check
|
||||
local tar = check_exe('tar')
|
||||
if tar then
|
||||
health.ok(string.format('tar %s (%s)', tar.version, tar.path))
|
||||
else
|
||||
health.error('tar not found')
|
||||
end
|
||||
|
||||
local curl = check_exe('curl')
|
||||
if curl then
|
||||
health.ok(string.format('curl %s (%s)\n%s', curl.version, curl.path, curl.out))
|
||||
else
|
||||
health.error('curl not found')
|
||||
end
|
||||
end
|
||||
|
||||
health.start('OS Info')
|
||||
local osinfo = vim.uv.os_uname() ---@type table<string,string>
|
||||
for k, v in pairs(osinfo) do
|
||||
health.info(k .. ': ' .. v)
|
||||
end
|
||||
|
||||
local installdir = config.get_install_dir('')
|
||||
health.start('Install directory for parsers and queries')
|
||||
health.info(installdir)
|
||||
if vim.uv.fs_access(installdir, 'w') then
|
||||
health.ok('is writable.')
|
||||
else
|
||||
health.error('is not writable.')
|
||||
end
|
||||
if
|
||||
vim.list_contains(vim.tbl_map(vim.fs.normalize, vim.api.nvim_list_runtime_paths()), installdir)
|
||||
then
|
||||
health.ok('is in runtimepath.')
|
||||
else
|
||||
health.error('is not in runtimepath.')
|
||||
end
|
||||
end
|
||||
|
||||
local function query_status(lang, query_group)
|
||||
local ok, err = pcall(queries.get_query, lang, query_group)
|
||||
local ok, err = pcall(tsq.get, lang, query_group)
|
||||
if not ok then
|
||||
return "x", err
|
||||
return 'x', err
|
||||
elseif not err then
|
||||
return "."
|
||||
return '.'
|
||||
else
|
||||
return "✓"
|
||||
return '✓'
|
||||
end
|
||||
end
|
||||
|
||||
function M.check()
|
||||
--- @type {[1]: string, [2]: string, [3]: string}[]
|
||||
local error_collection = {}
|
||||
-- Installation dependency checks
|
||||
install_health()
|
||||
queries.invalidate_query_cache()
|
||||
-- Parser installation checks
|
||||
local parser_installation = { "Parser/Features" .. string.rep(" ", 9) .. "H L F I J" }
|
||||
for _, parser_name in pairs(info.installed_parsers()) do
|
||||
local installed = #api.nvim_get_runtime_file("parser/" .. parser_name .. ".so", false)
|
||||
|
||||
-- Only append information about installed parsers
|
||||
if installed >= 1 then
|
||||
local multiple_parsers = installed > 1 and "+" or ""
|
||||
local out = " - " .. parser_name .. multiple_parsers .. string.rep(" ", 20 - (#parser_name + #multiple_parsers))
|
||||
for _, query_group in pairs(queries.built_in_query_groups) do
|
||||
local status, err = query_status(parser_name, query_group)
|
||||
out = out .. status .. " "
|
||||
-- Parser installation checks
|
||||
health.start('Installed languages' .. string.rep(' ', 5) .. 'H L F I J')
|
||||
local languages = config.get_installed()
|
||||
table.sort(languages)
|
||||
for _, lang in ipairs(languages) do
|
||||
local parser = parsers[lang]
|
||||
local out = lang .. string.rep(' ', 22 - #lang)
|
||||
if parser and parser.install_info then
|
||||
for _, query_group in pairs(M.bundled_queries) do
|
||||
local status, err = query_status(lang, query_group)
|
||||
out = out .. status .. ' '
|
||||
if err then
|
||||
table.insert(error_collection, { parser_name, query_group, err })
|
||||
table.insert(error_collection, { lang, query_group, err })
|
||||
end
|
||||
end
|
||||
table.insert(parser_installation, vim.fn.trim(out, " ", 2))
|
||||
end
|
||||
if parser and parser.requires then
|
||||
for _, p in pairs(parser.requires) do
|
||||
if not vim.list_contains(languages, p) then
|
||||
table.insert(error_collection, { lang, 'queries', 'dependency ' .. p .. ' missing' })
|
||||
end
|
||||
end
|
||||
end
|
||||
health.info(vim.fn.trim(out, ' ', 2))
|
||||
end
|
||||
local legend = [[
|
||||
health.start(' Legend: [H]ighlights, [L]ocals, [F]olds, [I]ndents, In[J]ections')
|
||||
|
||||
Legend: H[ighlight], L[ocals], F[olds], I[ndents], In[j]ections
|
||||
+) multiple parsers found, only one will be used
|
||||
x) errors found in the query, try to run :TSUpdate {lang}]]
|
||||
table.insert(parser_installation, legend)
|
||||
-- Finally call the report function
|
||||
_start(table.concat(parser_installation, "\n"))
|
||||
if #error_collection > 0 then
|
||||
_start "The following errors have been detected:"
|
||||
health.start('The following errors have been detected in query files:')
|
||||
for _, p in ipairs(error_collection) do
|
||||
local lang, type, err = unpack(p)
|
||||
local lang, type = p[1], p[2]
|
||||
local lines = {}
|
||||
table.insert(lines, lang .. "(" .. type .. "): " .. err)
|
||||
local files = ts.get_query_files(lang, type)
|
||||
table.insert(lines, lang .. '(' .. type .. '): ')
|
||||
local files = tsq.get_files(lang, type)
|
||||
if #files > 0 then
|
||||
table.insert(lines, lang .. "(" .. type .. ") is concatenated from the following files:")
|
||||
for _, file in ipairs(files) do
|
||||
local fd = io.open(file, "r")
|
||||
if fd then
|
||||
local ok, file_err = pcall(ts.parse_query, lang, fd:read "*a")
|
||||
if ok then
|
||||
table.insert(lines, '| [OK]:"' .. file .. '"')
|
||||
else
|
||||
table.insert(lines, '| [ERROR]:"' .. file .. '", failed to load: ' .. file_err)
|
||||
end
|
||||
fd:close()
|
||||
local query = util.read_file(file)
|
||||
local _, file_err = pcall(tsq.parse, lang, query)
|
||||
if file_err then
|
||||
table.insert(lines, file)
|
||||
end
|
||||
end
|
||||
end
|
||||
_error(table.concat(lines, "\n"))
|
||||
health.error(table.concat(lines, ''))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
M.bundled_queries = { 'highlights', 'locals', 'folds', 'indents', 'injections' }
|
||||
|
||||
return M
|
||||
|
|
|
|||
|
|
@ -1,49 +0,0 @@
|
|||
local configs = require "nvim-treesitter.configs"
|
||||
|
||||
local M = {}
|
||||
|
||||
---@param config TSModule
|
||||
---@param lang string
|
||||
---@return boolean
|
||||
local function should_enable_vim_regex(config, lang)
|
||||
local additional_hl = config.additional_vim_regex_highlighting
|
||||
local is_table = type(additional_hl) == "table"
|
||||
|
||||
---@diagnostic disable-next-line: param-type-mismatch
|
||||
return additional_hl and (not is_table or vim.tbl_contains(additional_hl, lang))
|
||||
end
|
||||
|
||||
---@param bufnr integer
|
||||
---@param lang string
|
||||
function M.attach(bufnr, lang)
|
||||
local config = configs.get_module "highlight"
|
||||
vim.treesitter.start(bufnr, lang)
|
||||
if config and should_enable_vim_regex(config, lang) then
|
||||
vim.bo[bufnr].syntax = "ON"
|
||||
end
|
||||
end
|
||||
|
||||
---@param bufnr integer
|
||||
function M.detach(bufnr)
|
||||
vim.treesitter.stop(bufnr)
|
||||
end
|
||||
|
||||
---@deprecated
|
||||
function M.start(...)
|
||||
vim.notify(
|
||||
"`nvim-treesitter.highlight.start` is deprecated: use `nvim-treesitter.highlight.attach` or `vim.treesitter.start`",
|
||||
vim.log.levels.WARN
|
||||
)
|
||||
M.attach(...)
|
||||
end
|
||||
|
||||
---@deprecated
|
||||
function M.stop(...)
|
||||
vim.notify(
|
||||
"`nvim-treesitter.highlight.stop` is deprecated: use `nvim-treesitter.highlight.detach` or `vim.treesitter.stop`",
|
||||
vim.log.levels.WARN
|
||||
)
|
||||
M.detach(...)
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
@ -1,176 +0,0 @@
|
|||
local api = vim.api
|
||||
|
||||
local configs = require "nvim-treesitter.configs"
|
||||
local ts_utils = require "nvim-treesitter.ts_utils"
|
||||
local locals = require "nvim-treesitter.locals"
|
||||
local parsers = require "nvim-treesitter.parsers"
|
||||
local queries = require "nvim-treesitter.query"
|
||||
|
||||
local M = {}
|
||||
|
||||
---@type table<integer, table<TSNode|nil>>
|
||||
local selections = {}
|
||||
|
||||
function M.init_selection()
|
||||
local buf = api.nvim_get_current_buf()
|
||||
local node = ts_utils.get_node_at_cursor()
|
||||
selections[buf] = { [1] = node }
|
||||
ts_utils.update_selection(buf, node)
|
||||
end
|
||||
|
||||
-- Get the range of the current visual selection.
|
||||
--
|
||||
-- The range starts with 1 and the ending is inclusive.
|
||||
---@return integer, integer, integer, integer
|
||||
local function visual_selection_range()
|
||||
local _, csrow, cscol, _ = unpack(vim.fn.getpos "'<") ---@type integer, integer, integer, integer
|
||||
local _, cerow, cecol, _ = unpack(vim.fn.getpos "'>") ---@type integer, integer, integer, integer
|
||||
|
||||
local start_row, start_col, end_row, end_col ---@type integer, integer, integer, integer
|
||||
|
||||
if csrow < cerow or (csrow == cerow and cscol <= cecol) then
|
||||
start_row = csrow
|
||||
start_col = cscol
|
||||
end_row = cerow
|
||||
end_col = cecol
|
||||
else
|
||||
start_row = cerow
|
||||
start_col = cecol
|
||||
end_row = csrow
|
||||
end_col = cscol
|
||||
end
|
||||
|
||||
return start_row, start_col, end_row, end_col
|
||||
end
|
||||
|
||||
---@param node TSNode
|
||||
---@return boolean
|
||||
local function range_matches(node)
|
||||
local csrow, cscol, cerow, cecol = visual_selection_range()
|
||||
local srow, scol, erow, ecol = ts_utils.get_vim_range { node:range() }
|
||||
return srow == csrow and scol == cscol and erow == cerow and ecol == cecol
|
||||
end
|
||||
|
||||
---@param get_parent fun(node: TSNode): TSNode|nil
|
||||
---@return fun():nil
|
||||
local function select_incremental(get_parent)
|
||||
return function()
|
||||
local buf = api.nvim_get_current_buf()
|
||||
local nodes = selections[buf]
|
||||
|
||||
local csrow, cscol, cerow, cecol = visual_selection_range()
|
||||
-- Initialize incremental selection with current selection
|
||||
if not nodes or #nodes == 0 or not range_matches(nodes[#nodes]) then
|
||||
local root = parsers.get_parser():parse()[1]:root()
|
||||
local node = root:named_descendant_for_range(csrow - 1, cscol - 1, cerow - 1, cecol)
|
||||
ts_utils.update_selection(buf, node)
|
||||
if nodes and #nodes > 0 then
|
||||
table.insert(selections[buf], node)
|
||||
else
|
||||
selections[buf] = { [1] = node }
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- Find a node that changes the current selection.
|
||||
local node = nodes[#nodes] ---@type TSNode
|
||||
while true do
|
||||
local parent = get_parent(node)
|
||||
if not parent or parent == node then
|
||||
-- Keep searching in the main tree
|
||||
-- TODO: we should search on the parent tree of the current node.
|
||||
local root = parsers.get_parser():parse()[1]:root()
|
||||
parent = root:named_descendant_for_range(csrow - 1, cscol - 1, cerow - 1, cecol)
|
||||
if not parent or root == node or parent == node then
|
||||
ts_utils.update_selection(buf, node)
|
||||
return
|
||||
end
|
||||
end
|
||||
node = parent
|
||||
local srow, scol, erow, ecol = ts_utils.get_vim_range { node:range() }
|
||||
local same_range = (srow == csrow and scol == cscol and erow == cerow and ecol == cecol)
|
||||
if not same_range then
|
||||
table.insert(selections[buf], node)
|
||||
if node ~= nodes[#nodes] then
|
||||
table.insert(nodes, node)
|
||||
end
|
||||
ts_utils.update_selection(buf, node)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
M.node_incremental = select_incremental(function(node)
|
||||
return node:parent() or node
|
||||
end)
|
||||
|
||||
M.scope_incremental = select_incremental(function(node)
|
||||
local lang = parsers.get_buf_lang()
|
||||
if queries.has_locals(lang) then
|
||||
return locals.containing_scope(node:parent() or node)
|
||||
else
|
||||
return node
|
||||
end
|
||||
end)
|
||||
|
||||
function M.node_decremental()
|
||||
local buf = api.nvim_get_current_buf()
|
||||
local nodes = selections[buf]
|
||||
if not nodes or #nodes < 2 then
|
||||
return
|
||||
end
|
||||
|
||||
table.remove(selections[buf])
|
||||
local node = nodes[#nodes] ---@type TSNode
|
||||
ts_utils.update_selection(buf, node)
|
||||
end
|
||||
|
||||
local FUNCTION_DESCRIPTIONS = {
|
||||
init_selection = "Start selecting nodes with nvim-treesitter",
|
||||
node_incremental = "Increment selection to named node",
|
||||
scope_incremental = "Increment selection to surrounding scope",
|
||||
node_decremental = "Shrink selection to previous named node",
|
||||
}
|
||||
|
||||
---@param bufnr integer
|
||||
function M.attach(bufnr)
|
||||
local config = configs.get_module "incremental_selection"
|
||||
for funcname, mapping in pairs(config.keymaps) do
|
||||
if mapping then
|
||||
---@type string, string|function
|
||||
local mode, rhs
|
||||
if funcname == "init_selection" then
|
||||
mode = "n"
|
||||
---@type function
|
||||
rhs = M[funcname]
|
||||
else
|
||||
mode = "x"
|
||||
-- We need to move to command mode to access marks '< (visual area start) and '> (visual area end) which are not
|
||||
-- properly accessible in visual mode.
|
||||
rhs = string.format(":lua require'nvim-treesitter.incremental_selection'.%s()<CR>", funcname)
|
||||
end
|
||||
vim.keymap.set(
|
||||
mode,
|
||||
mapping,
|
||||
rhs,
|
||||
{ buffer = bufnr, silent = true, noremap = true, desc = FUNCTION_DESCRIPTIONS[funcname] }
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M.detach(bufnr)
|
||||
local config = configs.get_module "incremental_selection"
|
||||
for f, mapping in pairs(config.keymaps) do
|
||||
if mapping then
|
||||
if f == "init_selection" then
|
||||
vim.keymap.del("n", mapping, { buffer = bufnr })
|
||||
else
|
||||
vim.keymap.del("x", mapping, { buffer = bufnr })
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
@ -1,53 +1,49 @@
|
|||
local ts = vim.treesitter
|
||||
local parsers = require "nvim-treesitter.parsers"
|
||||
|
||||
local M = {}
|
||||
|
||||
M.avoid_force_reparsing = {
|
||||
yaml = true,
|
||||
}
|
||||
|
||||
M.comment_parsers = {
|
||||
comment = true,
|
||||
luadoc = true,
|
||||
javadoc = true,
|
||||
jsdoc = true,
|
||||
phpdoc = true,
|
||||
}
|
||||
|
||||
local function getline(lnum)
|
||||
return vim.api.nvim_buf_get_lines(0, lnum - 1, lnum, false)[1] or ""
|
||||
return vim.api.nvim_buf_get_lines(0, lnum - 1, lnum, false)[1] or ''
|
||||
end
|
||||
|
||||
---@param lnum integer
|
||||
---@return integer
|
||||
local function get_indentcols_at_line(lnum)
|
||||
local _, indentcols = getline(lnum):find('^%s*')
|
||||
return indentcols or 0
|
||||
end
|
||||
|
||||
---@param root TSNode
|
||||
---@param lnum integer
|
||||
---@param col? integer
|
||||
---@return TSNode
|
||||
---@return TSNode?
|
||||
local function get_first_node_at_line(root, lnum, col)
|
||||
col = col or vim.fn.indent(lnum)
|
||||
col = col or get_indentcols_at_line(lnum)
|
||||
return root:descendant_for_range(lnum - 1, col, lnum - 1, col + 1)
|
||||
end
|
||||
|
||||
---@param root TSNode
|
||||
---@param lnum integer
|
||||
---@param col? integer
|
||||
---@return TSNode
|
||||
---@return TSNode?
|
||||
local function get_last_node_at_line(root, lnum, col)
|
||||
col = col or (#getline(lnum) - 1)
|
||||
return root:descendant_for_range(lnum - 1, col, lnum - 1, col + 1)
|
||||
end
|
||||
|
||||
---@param node TSNode
|
||||
---@return number
|
||||
local function node_length(node)
|
||||
local _, _, start_byte = node:start()
|
||||
local _, _, end_byte = node:end_()
|
||||
return end_byte - start_byte
|
||||
end
|
||||
|
||||
---@param bufnr integer
|
||||
---@param node TSNode
|
||||
---@param delimiter string
|
||||
---@return TSNode|nil child
|
||||
---@return boolean|nil is_end
|
||||
---@return TSNode? child
|
||||
---@return boolean? is_end
|
||||
local function find_delimiter(bufnr, node, delimiter)
|
||||
for child, _ in node:iter_children() do
|
||||
if child:type() == delimiter then
|
||||
|
|
@ -55,8 +51,9 @@ local function find_delimiter(bufnr, node, delimiter)
|
|||
local line = vim.api.nvim_buf_get_lines(bufnr, linenr, linenr + 1, false)[1]
|
||||
local end_char = { child:end_() }
|
||||
local trimmed_after_delim
|
||||
local escaped_delimiter = delimiter:gsub("[%-%.%+%[%]%(%)%$%^%%%?%*]", "%%%1")
|
||||
trimmed_after_delim, _ = line:sub(end_char[2] + 1):gsub("[%s" .. escaped_delimiter .. "]*", "")
|
||||
local escaped_delimiter = delimiter:gsub('[%-%.%+%[%]%(%)%$%^%%%?%*]', '%%%1')
|
||||
trimmed_after_delim =
|
||||
assert(line):sub(end_char[2] + 1):gsub('[%s' .. escaped_delimiter .. ']*', '')
|
||||
return child, #trimmed_after_delim == 0
|
||||
end
|
||||
end
|
||||
|
|
@ -68,7 +65,7 @@ end
|
|||
---@param hash_fn fun(...): any
|
||||
---@return F
|
||||
local function memoize(fn, hash_fn)
|
||||
local cache = setmetatable({}, { __mode = "kv" }) ---@type table<any,any>
|
||||
local cache = setmetatable({}, { __mode = 'kv' }) ---@type table<any,any>
|
||||
|
||||
return function(...)
|
||||
local key = hash_fn(...)
|
||||
|
|
@ -83,59 +80,53 @@ local function memoize(fn, hash_fn)
|
|||
end
|
||||
|
||||
local get_indents = memoize(function(bufnr, root, lang)
|
||||
---@type table<string,table<string,table>>
|
||||
local map = {
|
||||
["indent.auto"] = {},
|
||||
["indent.begin"] = {},
|
||||
["indent.end"] = {},
|
||||
["indent.dedent"] = {},
|
||||
["indent.branch"] = {},
|
||||
["indent.ignore"] = {},
|
||||
["indent.align"] = {},
|
||||
["indent.zero"] = {},
|
||||
['indent.auto'] = {},
|
||||
['indent.begin'] = {},
|
||||
['indent.end'] = {},
|
||||
['indent.dedent'] = {},
|
||||
['indent.branch'] = {},
|
||||
['indent.ignore'] = {},
|
||||
['indent.align'] = {},
|
||||
['indent.zero'] = {},
|
||||
}
|
||||
|
||||
--TODO(clason): remove when dropping Nvim 0.8 compat
|
||||
local query = (ts.query.get or ts.get_query)(lang, "indents")
|
||||
local query = ts.query.get(lang, 'indents')
|
||||
if not query then
|
||||
return map
|
||||
end
|
||||
for id, node, metadata in query:iter_captures(root, bufnr) do
|
||||
if query.captures[id]:sub(1, 1) ~= "_" then
|
||||
if assert(query.captures[id]):sub(1, 1) ~= '_' then
|
||||
map[query.captures[id]][node:id()] = metadata or {}
|
||||
end
|
||||
end
|
||||
|
||||
return map
|
||||
end, function(bufnr, root, lang)
|
||||
return tostring(bufnr) .. root:id() .. "_" .. lang
|
||||
return tostring(bufnr) .. root:id() .. '_' .. lang
|
||||
end)
|
||||
|
||||
---@param lnum number (1-indexed)
|
||||
---@param lnum integer (1-indexed)
|
||||
---@return integer
|
||||
function M.get_indent(lnum)
|
||||
local bufnr = vim.api.nvim_get_current_buf()
|
||||
local parser = parsers.get_parser(bufnr)
|
||||
local parser = ts.get_parser(bufnr)
|
||||
if not parser or not lnum then
|
||||
return -1
|
||||
end
|
||||
|
||||
--TODO(clason): replace when dropping Nvim 0.8 compat
|
||||
local root_lang = parsers.get_buf_lang(bufnr)
|
||||
|
||||
-- some languages like Python will actually have worse results when re-parsing at opened new line
|
||||
if not M.avoid_force_reparsing[root_lang] then
|
||||
-- Reparse in case we got triggered by ":h indentkeys"
|
||||
parser:parse { vim.fn.line "w0" - 1, vim.fn.line "w$" }
|
||||
end
|
||||
parser:parse({ vim.fn.line('w0') - 1, vim.fn.line('w$') })
|
||||
|
||||
-- Get language tree with smallest range around node that's not a comment parser
|
||||
local root, lang_tree ---@type TSNode, LanguageTree
|
||||
local root, lang_tree ---@type TSNode, vim.treesitter.LanguageTree
|
||||
parser:for_each_tree(function(tstree, tree)
|
||||
if not tstree or M.comment_parsers[tree:lang()] then
|
||||
return
|
||||
end
|
||||
local local_root = tstree:root()
|
||||
if ts.is_in_node_range(local_root, lnum - 1, 0) then
|
||||
if not root or node_length(root) >= node_length(local_root) then
|
||||
if not root or root:byte_length() >= local_root:byte_length() then
|
||||
root = local_root
|
||||
lang_tree = tree
|
||||
end
|
||||
|
|
@ -148,28 +139,27 @@ function M.get_indent(lnum)
|
|||
end
|
||||
|
||||
local q = get_indents(vim.api.nvim_get_current_buf(), root, lang_tree:lang())
|
||||
local is_empty_line = string.match(getline(lnum), "^%s*$") ~= nil
|
||||
local node ---@type TSNode
|
||||
if is_empty_line then
|
||||
local node ---@type TSNode?
|
||||
if getline(lnum):find('^%s*$') then
|
||||
local prevlnum = vim.fn.prevnonblank(lnum)
|
||||
local indent = vim.fn.indent(prevlnum)
|
||||
local indentcols = get_indentcols_at_line(prevlnum)
|
||||
local prevline = vim.trim(getline(prevlnum))
|
||||
-- The final position can be trailing spaces, which should not affect indentation
|
||||
node = get_last_node_at_line(root, prevlnum, indent + #prevline - 1)
|
||||
if node:type():match "comment" then
|
||||
node = get_last_node_at_line(root, prevlnum, indentcols + #prevline - 1)
|
||||
if node and node:type():match('comment') then
|
||||
-- The final node we capture of the previous line can be a comment node, which should also be ignored
|
||||
-- Unless the last line is an entire line of comment, ignore the comment range and find the last node again
|
||||
local first_node = get_first_node_at_line(root, prevlnum, indent)
|
||||
local first_node = get_first_node_at_line(root, prevlnum, indentcols)
|
||||
local _, scol, _, _ = node:range()
|
||||
if first_node:id() ~= node:id() then
|
||||
if first_node and first_node:id() ~= node:id() then
|
||||
-- In case the last captured node is a trailing comment node, re-trim the string
|
||||
prevline = vim.trim(prevline:sub(1, scol - indent))
|
||||
prevline = vim.trim(prevline:sub(1, scol - indentcols))
|
||||
-- Add back indent as indent of prevline was trimmed away
|
||||
local col = indent + #prevline - 1
|
||||
local col = indentcols + #prevline - 1
|
||||
node = get_last_node_at_line(root, prevlnum, col)
|
||||
end
|
||||
end
|
||||
if q["indent.end"][node:id()] then
|
||||
if node and q['indent.end'][node:id()] then
|
||||
node = get_first_node_at_line(root, lnum)
|
||||
end
|
||||
else
|
||||
|
|
@ -185,18 +175,18 @@ function M.get_indent(lnum)
|
|||
end
|
||||
|
||||
-- tracks to ensure multiple indent levels are not applied for same line
|
||||
local is_processed_by_row = {}
|
||||
local is_processed_by_row = {} --- @type table<integer,boolean>
|
||||
|
||||
if q["indent.zero"][node:id()] then
|
||||
if node and q['indent.zero'][node:id()] then
|
||||
return 0
|
||||
end
|
||||
|
||||
while node do
|
||||
-- do 'autoindent' if not marked as @indent
|
||||
if
|
||||
not q["indent.begin"][node:id()]
|
||||
and not q["indent.align"][node:id()]
|
||||
and q["indent.auto"][node:id()]
|
||||
not q['indent.begin'][node:id()]
|
||||
and not q['indent.align'][node:id()]
|
||||
and q['indent.auto'][node:id()]
|
||||
and node:start() < lnum - 1
|
||||
and lnum - 1 <= node:end_()
|
||||
then
|
||||
|
|
@ -207,8 +197,8 @@ function M.get_indent(lnum)
|
|||
-- If a node spans from L1,C1 to L2,C2, we know that lines where L1 < line <= L2 would
|
||||
-- have their indentations contained by the node.
|
||||
if
|
||||
not q["indent.begin"][node:id()]
|
||||
and q["indent.ignore"][node:id()]
|
||||
not q['indent.begin'][node:id()]
|
||||
and q['indent.ignore'][node:id()]
|
||||
and node:start() < lnum - 1
|
||||
and lnum - 1 <= node:end_()
|
||||
then
|
||||
|
|
@ -221,7 +211,10 @@ function M.get_indent(lnum)
|
|||
|
||||
if
|
||||
not is_processed_by_row[srow]
|
||||
and ((q["indent.branch"][node:id()] and srow == lnum - 1) or (q["indent.dedent"][node:id()] and srow ~= lnum - 1))
|
||||
and (
|
||||
(q['indent.branch'][node:id()] and srow == lnum - 1)
|
||||
or (q['indent.dedent'][node:id()] and srow ~= lnum - 1)
|
||||
)
|
||||
then
|
||||
indent = indent - indent_size
|
||||
is_processed = true
|
||||
|
|
@ -232,56 +225,63 @@ function M.get_indent(lnum)
|
|||
local is_in_err = false
|
||||
if should_process then
|
||||
local parent = node:parent()
|
||||
is_in_err = parent and parent:has_error()
|
||||
is_in_err = parent and parent:has_error() or false
|
||||
end
|
||||
if
|
||||
should_process
|
||||
and (
|
||||
q["indent.begin"][node:id()]
|
||||
and (srow ~= erow or is_in_err or q["indent.begin"][node:id()]["indent.immediate"])
|
||||
and (srow ~= lnum - 1 or q["indent.begin"][node:id()]["indent.start_at_same_line"])
|
||||
q['indent.begin'][node:id()]
|
||||
and (srow ~= erow or is_in_err or q['indent.begin'][node:id()]['indent.immediate'])
|
||||
and (srow ~= lnum - 1 or q['indent.begin'][node:id()]['indent.start_at_same_line'])
|
||||
)
|
||||
then
|
||||
indent = indent + indent_size
|
||||
is_processed = true
|
||||
end
|
||||
|
||||
if is_in_err and not q["indent.align"][node:id()] then
|
||||
if is_in_err and not q['indent.align'][node:id()] then
|
||||
-- only when the node is in error, promote the
|
||||
-- first child's aligned indent to the error node
|
||||
-- to work around ((ERROR "X" . (_)) @aligned_indent (#set! "delimeter" "AB"))
|
||||
-- to work around ((ERROR "X" . (_)) @aligned_indent (#set! "delimiter" "AB"))
|
||||
-- matching for all X, instead set do
|
||||
-- (ERROR "X" @aligned_indent (#set! "delimeter" "AB") . (_))
|
||||
-- (ERROR "X" @aligned_indent (#set! "delimiter" "AB") . (_))
|
||||
-- and we will fish it out here.
|
||||
for c in node:iter_children() do
|
||||
if q["indent.align"][c:id()] then
|
||||
q["indent.align"][node:id()] = q["indent.align"][c:id()]
|
||||
if q['indent.align'][c:id()] then
|
||||
q['indent.align'][node:id()] = q['indent.align'][c:id()]
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
-- do not indent for nodes that starts-and-ends on same line and starts on target line (lnum)
|
||||
if should_process and q["indent.align"][node:id()] and (srow ~= erow or is_in_err) and (srow ~= lnum - 1) then
|
||||
local metadata = q["indent.align"][node:id()]
|
||||
local o_delim_node, o_is_last_in_line ---@type TSNode|nil, boolean|nil
|
||||
local c_delim_node, c_is_last_in_line ---@type TSNode|nil, boolean|nil, boolean|nil
|
||||
if
|
||||
should_process
|
||||
and q['indent.align'][node:id()]
|
||||
and (srow ~= erow or is_in_err)
|
||||
and (srow ~= lnum - 1)
|
||||
then
|
||||
local metadata = q['indent.align'][node:id()]
|
||||
local o_delim_node, o_is_last_in_line ---@type TSNode?, boolean?
|
||||
local c_delim_node, c_is_last_in_line ---@type TSNode?, boolean?, boolean?
|
||||
local indent_is_absolute = false
|
||||
if metadata["indent.open_delimiter"] then
|
||||
o_delim_node, o_is_last_in_line = find_delimiter(bufnr, node, metadata["indent.open_delimiter"])
|
||||
if metadata['indent.open_delimiter'] then
|
||||
o_delim_node, o_is_last_in_line =
|
||||
find_delimiter(bufnr, node, metadata['indent.open_delimiter'])
|
||||
else
|
||||
o_delim_node = node
|
||||
end
|
||||
if metadata["indent.close_delimiter"] then
|
||||
c_delim_node, c_is_last_in_line = find_delimiter(bufnr, node, metadata["indent.close_delimiter"])
|
||||
if metadata['indent.close_delimiter'] then
|
||||
c_delim_node, c_is_last_in_line =
|
||||
find_delimiter(bufnr, node, metadata['indent.close_delimiter'])
|
||||
else
|
||||
c_delim_node = node
|
||||
end
|
||||
|
||||
if o_delim_node then
|
||||
local o_srow, o_scol = o_delim_node:start()
|
||||
local c_srow = nil
|
||||
local c_srow = nil --- @type integer?
|
||||
if c_delim_node then
|
||||
c_srow, _ = c_delim_node:start()
|
||||
c_srow = c_delim_node:start()
|
||||
end
|
||||
if o_is_last_in_line then
|
||||
-- hanging indent (previous line ended with starting delimiter)
|
||||
|
|
@ -303,7 +303,7 @@ function M.get_indent(lnum)
|
|||
-- Then its indent level shouldn't be affected by `@aligned_indent` node
|
||||
indent = math.max(indent - indent_size, 0)
|
||||
else
|
||||
indent = o_scol + (metadata["indent.increment"] or 1)
|
||||
indent = o_scol + (metadata['indent.increment'] or 1)
|
||||
indent_is_absolute = true
|
||||
end
|
||||
end
|
||||
|
|
@ -314,7 +314,7 @@ function M.get_indent(lnum)
|
|||
-- then this last line may need additional indent to avoid clashes
|
||||
-- with the next. `indent.avoid_last_matching_next` controls this behavior,
|
||||
-- for example this is needed for function parameters.
|
||||
avoid_last_matching_next = metadata["indent.avoid_last_matching_next"] or false
|
||||
avoid_last_matching_next = metadata['indent.avoid_last_matching_next'] or false
|
||||
end
|
||||
if avoid_last_matching_next then
|
||||
-- last line must be indented more in cases where
|
||||
|
|
@ -343,17 +343,4 @@ function M.get_indent(lnum)
|
|||
return indent
|
||||
end
|
||||
|
||||
---@type table<integer, string>
|
||||
local indent_funcs = {}
|
||||
|
||||
---@param bufnr integer
|
||||
function M.attach(bufnr)
|
||||
indent_funcs[bufnr] = vim.bo.indentexpr
|
||||
vim.bo.indentexpr = "nvim_treesitter#indent()"
|
||||
end
|
||||
|
||||
function M.detach(bufnr)
|
||||
vim.bo.indentexpr = indent_funcs[bufnr]
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
|
|||
|
|
@ -1,190 +0,0 @@
|
|||
local api = vim.api
|
||||
local configs = require "nvim-treesitter.configs"
|
||||
local parsers = require "nvim-treesitter.parsers"
|
||||
|
||||
local M = {}
|
||||
|
||||
local function install_info()
|
||||
local max_len = 0
|
||||
for _, ft in pairs(parsers.available_parsers()) do
|
||||
if #ft > max_len then
|
||||
max_len = #ft
|
||||
end
|
||||
end
|
||||
|
||||
local parser_list = parsers.available_parsers()
|
||||
table.sort(parser_list)
|
||||
for _, lang in pairs(parser_list) do
|
||||
local is_installed = #api.nvim_get_runtime_file("parser/" .. lang .. ".so", false) > 0
|
||||
api.nvim_out_write(lang .. string.rep(" ", max_len - #lang + 1))
|
||||
if is_installed then
|
||||
api.nvim_out_write "[✓] installed\n"
|
||||
elseif pcall(vim.treesitter.inspect_lang, lang) then
|
||||
api.nvim_out_write "[✗] not installed (but still loaded. Restart Neovim!)\n"
|
||||
else
|
||||
api.nvim_out_write "[✗] not installed\n"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Sort a list of modules into namespaces.
|
||||
-- {'mod1', 'mod2.sub1', 'mod2.sub2', 'mod3'}
|
||||
-- ->
|
||||
-- { default = {'mod1', 'mod3'}, mod2 = {'sub1', 'sub2'}}
|
||||
---@param modulelist string[]
|
||||
---@return table
|
||||
local function namespace_modules(modulelist)
|
||||
local modules = {}
|
||||
for _, module in ipairs(modulelist) do
|
||||
if module:find "%." then
|
||||
local namespace, submodule = module:match "^(.*)%.(.*)$"
|
||||
if not modules[namespace] then
|
||||
modules[namespace] = {}
|
||||
end
|
||||
table.insert(modules[namespace], submodule)
|
||||
else
|
||||
if not modules.default then
|
||||
modules.default = {}
|
||||
end
|
||||
table.insert(modules.default, module)
|
||||
end
|
||||
end
|
||||
return modules
|
||||
end
|
||||
|
||||
---@param list string[]
|
||||
---@return integer length
|
||||
local function longest_string_length(list)
|
||||
local length = 0
|
||||
for _, value in ipairs(list) do
|
||||
if #value > length then
|
||||
length = #value
|
||||
end
|
||||
end
|
||||
return length
|
||||
end
|
||||
|
||||
---@param curbuf integer
|
||||
---@param origbuf integer
|
||||
---@param parserlist string[]
|
||||
---@param namespace string
|
||||
---@param modulelist string[]
|
||||
local function append_module_table(curbuf, origbuf, parserlist, namespace, modulelist)
|
||||
local maxlen_parser = longest_string_length(parserlist)
|
||||
table.sort(modulelist)
|
||||
|
||||
-- header
|
||||
local header = ">> " .. namespace .. string.rep(" ", maxlen_parser - #namespace - 1)
|
||||
for _, module in pairs(modulelist) do
|
||||
header = header .. module .. " "
|
||||
end
|
||||
api.nvim_buf_set_lines(curbuf, -1, -1, true, { header })
|
||||
|
||||
-- actual table
|
||||
for _, parser in ipairs(parserlist) do
|
||||
local padding = string.rep(" ", maxlen_parser - #parser + 2)
|
||||
local line = parser .. padding
|
||||
local namespace_prefix = (namespace == "default") and "" or namespace .. "."
|
||||
for _, module in pairs(modulelist) do
|
||||
local modlen = #module
|
||||
module = namespace_prefix .. module
|
||||
if configs.is_enabled(module, parser, origbuf) then
|
||||
line = line .. "✓"
|
||||
else
|
||||
line = line .. "✗"
|
||||
end
|
||||
line = line .. string.rep(" ", modlen + 1)
|
||||
end
|
||||
api.nvim_buf_set_lines(curbuf, -1, -1, true, { line })
|
||||
end
|
||||
|
||||
api.nvim_buf_set_lines(curbuf, -1, -1, true, { "" })
|
||||
end
|
||||
|
||||
local function print_info_modules(parserlist, module)
|
||||
local origbuf = api.nvim_get_current_buf()
|
||||
api.nvim_command "enew"
|
||||
local curbuf = api.nvim_get_current_buf()
|
||||
|
||||
local modules
|
||||
if module then
|
||||
modules = namespace_modules { module }
|
||||
else
|
||||
modules = namespace_modules(configs.available_modules())
|
||||
end
|
||||
|
||||
---@type string[]
|
||||
local namespaces = {}
|
||||
for k, _ in pairs(modules) do
|
||||
table.insert(namespaces, k)
|
||||
end
|
||||
table.sort(namespaces)
|
||||
|
||||
table.sort(parserlist)
|
||||
for _, namespace in ipairs(namespaces) do
|
||||
append_module_table(curbuf, origbuf, parserlist, namespace, modules[namespace])
|
||||
end
|
||||
|
||||
api.nvim_buf_set_option(curbuf, "modified", false)
|
||||
api.nvim_buf_set_option(curbuf, "buftype", "nofile")
|
||||
vim.cmd [[
|
||||
syntax match TSModuleInfoGood /✓/
|
||||
syntax match TSModuleInfoBad /✗/
|
||||
syntax match TSModuleInfoHeader /^>>.*$/ contains=TSModuleInfoNamespace
|
||||
syntax match TSModuleInfoNamespace /^>> \w*/ contained
|
||||
syntax match TSModuleInfoParser /^[^> ]*\ze /
|
||||
]]
|
||||
|
||||
local highlights = {
|
||||
TSModuleInfoGood = { fg = "LightGreen", bold = true, default = true },
|
||||
TSModuleInfoBad = { fg = "Crimson", default = true },
|
||||
TSModuleInfoHeader = { link = "Type", default = true },
|
||||
TSModuleInfoNamespace = { link = "Statement", default = true },
|
||||
TSModuleInfoParser = { link = "Identifier", default = true },
|
||||
}
|
||||
for k, v in pairs(highlights) do
|
||||
api.nvim_set_hl(0, k, v)
|
||||
end
|
||||
end
|
||||
|
||||
local function module_info(module)
|
||||
if module and not configs.get_module(module) then
|
||||
return
|
||||
end
|
||||
|
||||
local parserlist = parsers.available_parsers()
|
||||
if module then
|
||||
print_info_modules(parserlist, module)
|
||||
else
|
||||
print_info_modules(parserlist)
|
||||
end
|
||||
end
|
||||
|
||||
---@return string[]
|
||||
function M.installed_parsers()
|
||||
local installed = {}
|
||||
for _, p in pairs(parsers.available_parsers()) do
|
||||
if parsers.has_parser(p) then
|
||||
table.insert(installed, p)
|
||||
end
|
||||
end
|
||||
return installed
|
||||
end
|
||||
|
||||
M.commands = {
|
||||
TSInstallInfo = {
|
||||
run = install_info,
|
||||
args = {
|
||||
"-nargs=0",
|
||||
},
|
||||
},
|
||||
TSModuleInfo = {
|
||||
run = module_info,
|
||||
args = {
|
||||
"-nargs=?",
|
||||
"-complete=custom,nvim_treesitter#available_modules",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
return M
|
||||
31
lua/nvim-treesitter/init.lua
Normal file
31
lua/nvim-treesitter/init.lua
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
local M = {}
|
||||
|
||||
function M.setup(...)
|
||||
require('nvim-treesitter.config').setup(...)
|
||||
end
|
||||
|
||||
function M.get_available(...)
|
||||
return require('nvim-treesitter.config').get_available(...)
|
||||
end
|
||||
|
||||
function M.get_installed(...)
|
||||
return require('nvim-treesitter.config').get_installed(...)
|
||||
end
|
||||
|
||||
function M.install(...)
|
||||
return require('nvim-treesitter.install').install(...)
|
||||
end
|
||||
|
||||
function M.uninstall(...)
|
||||
return require('nvim-treesitter.install').uninstall(...)
|
||||
end
|
||||
|
||||
function M.update(...)
|
||||
return require('nvim-treesitter.install').update(...)
|
||||
end
|
||||
|
||||
function M.indentexpr()
|
||||
return require('nvim-treesitter.indent').get_indent(vim.v.lnum)
|
||||
end
|
||||
|
||||
return M
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,364 +0,0 @@
|
|||
-- Functions to handle locals
|
||||
-- Locals are a generalization of definition and scopes
|
||||
-- its the way nvim-treesitter uses to "understand" the code
|
||||
|
||||
local queries = require "nvim-treesitter.query"
|
||||
local ts_utils = require "nvim-treesitter.ts_utils"
|
||||
local ts = vim.treesitter
|
||||
local api = vim.api
|
||||
|
||||
local M = {}
|
||||
|
||||
function M.collect_locals(bufnr)
|
||||
return queries.collect_group_results(bufnr, "locals")
|
||||
end
|
||||
|
||||
-- Iterates matches from a locals query file.
|
||||
-- @param bufnr the buffer
|
||||
-- @param root the root node
|
||||
function M.iter_locals(bufnr, root)
|
||||
return queries.iter_group_results(bufnr, "locals", root)
|
||||
end
|
||||
|
||||
---@param bufnr integer
|
||||
---@return any
|
||||
function M.get_locals(bufnr)
|
||||
return queries.get_matches(bufnr, "locals")
|
||||
end
|
||||
|
||||
-- Creates unique id for a node based on text and range
|
||||
---@param scope TSNode: the scope node of the definition
|
||||
---@param node_text string: the node text to use
|
||||
---@return string: a string id
|
||||
function M.get_definition_id(scope, node_text)
|
||||
-- Add a valid starting character in case node text doesn't start with a valid one.
|
||||
return table.concat({ "k", node_text or "", scope:range() }, "_")
|
||||
end
|
||||
|
||||
function M.get_definitions(bufnr)
|
||||
local locals = M.get_locals(bufnr)
|
||||
|
||||
local defs = {}
|
||||
|
||||
for _, loc in ipairs(locals) do
|
||||
if loc.definition then
|
||||
table.insert(defs, loc.definition)
|
||||
end
|
||||
end
|
||||
|
||||
return defs
|
||||
end
|
||||
|
||||
function M.get_scopes(bufnr)
|
||||
local locals = M.get_locals(bufnr)
|
||||
|
||||
local scopes = {}
|
||||
|
||||
for _, loc in ipairs(locals) do
|
||||
if loc.scope and loc.scope.node then
|
||||
table.insert(scopes, loc.scope.node)
|
||||
end
|
||||
end
|
||||
|
||||
return scopes
|
||||
end
|
||||
|
||||
function M.get_references(bufnr)
|
||||
local locals = M.get_locals(bufnr)
|
||||
|
||||
local refs = {}
|
||||
|
||||
for _, loc in ipairs(locals) do
|
||||
if loc.reference and loc.reference.node then
|
||||
table.insert(refs, loc.reference.node)
|
||||
end
|
||||
end
|
||||
|
||||
return refs
|
||||
end
|
||||
|
||||
-- Gets a table with all the scopes containing a node
|
||||
-- The order is from most specific to least (bottom up)
|
||||
---@param node TSNode
|
||||
---@param bufnr integer
|
||||
---@return TSNode[]
|
||||
function M.get_scope_tree(node, bufnr)
|
||||
local scopes = {} ---@type TSNode[]
|
||||
|
||||
for scope in M.iter_scope_tree(node, bufnr) do
|
||||
table.insert(scopes, scope)
|
||||
end
|
||||
|
||||
return scopes
|
||||
end
|
||||
|
||||
-- Iterates over a nodes scopes moving from the bottom up
|
||||
---@param node TSNode
|
||||
---@param bufnr integer
|
||||
---@return fun(): TSNode|nil
|
||||
function M.iter_scope_tree(node, bufnr)
|
||||
local last_node = node
|
||||
return function()
|
||||
if not last_node then
|
||||
return
|
||||
end
|
||||
|
||||
local scope = M.containing_scope(last_node, bufnr, false) or ts_utils.get_root_for_node(node)
|
||||
|
||||
last_node = scope:parent()
|
||||
|
||||
return scope
|
||||
end
|
||||
end
|
||||
|
||||
-- Gets a table of all nodes and their 'kinds' from a locals list
|
||||
---@param local_def any: the local list result
|
||||
---@return table: a list of node entries
|
||||
function M.get_local_nodes(local_def)
|
||||
local result = {}
|
||||
|
||||
M.recurse_local_nodes(local_def, function(def, _node, kind)
|
||||
table.insert(result, vim.tbl_extend("keep", { kind = kind }, def))
|
||||
end)
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
-- Recurse locals results until a node is found.
|
||||
-- The accumulator function is given
|
||||
-- * The table of the node
|
||||
-- * The node
|
||||
-- * The full definition match `@definition.var.something` -> 'var.something'
|
||||
-- * The last definition match `@definition.var.something` -> 'something'
|
||||
---@param local_def any The locals result
|
||||
---@param accumulator function The accumulator function
|
||||
---@param full_match? string The full match path to append to
|
||||
---@param last_match? string The last match
|
||||
function M.recurse_local_nodes(local_def, accumulator, full_match, last_match)
|
||||
if type(local_def) ~= "table" then
|
||||
return
|
||||
end
|
||||
|
||||
if local_def.node then
|
||||
accumulator(local_def, local_def.node, full_match, last_match)
|
||||
else
|
||||
for match_key, def in pairs(local_def) do
|
||||
M.recurse_local_nodes(def, accumulator, full_match and (full_match .. "." .. match_key) or match_key, match_key)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Get a single dimension table to look definition nodes.
|
||||
-- Keys are generated by using the range of the containing scope and the text of the definition node.
|
||||
-- This makes looking up a definition for a given scope a simple key lookup.
|
||||
--
|
||||
-- This is memoized by buffer tick. If the function is called in succession
|
||||
-- without the buffer tick changing, then the previous result will be used
|
||||
-- since the syntax tree hasn't changed.
|
||||
--
|
||||
-- Usage lookups require finding the definition of the node, so `find_definition`
|
||||
-- is called very frequently, which is why this lookup must be fast as possible.
|
||||
--
|
||||
---@param bufnr integer: the buffer
|
||||
---@return table result: a table for looking up definitions
|
||||
M.get_definitions_lookup_table = ts_utils.memoize_by_buf_tick(function(bufnr)
|
||||
local definitions = M.get_definitions(bufnr)
|
||||
local result = {}
|
||||
|
||||
for _, definition in ipairs(definitions) do
|
||||
for _, node_entry in ipairs(M.get_local_nodes(definition)) do
|
||||
local scopes = M.get_definition_scopes(node_entry.node, bufnr, node_entry.scope)
|
||||
-- Always use the highest valid scope
|
||||
local scope = scopes[#scopes]
|
||||
local node_text = ts.get_node_text(node_entry.node, bufnr)
|
||||
local id = M.get_definition_id(scope, node_text)
|
||||
|
||||
result[id] = node_entry
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end)
|
||||
|
||||
-- Gets all the scopes of a definition based on the scope type
|
||||
-- Scope types can be
|
||||
--
|
||||
-- "parent": Uses the parent of the containing scope, basically, skipping a scope
|
||||
-- "global": Uses the top most scope
|
||||
-- "local": Uses the containing scope of the definition. This is the default
|
||||
--
|
||||
---@param node TSNode: the definition node
|
||||
---@param bufnr integer: the buffer
|
||||
---@param scope_type string: the scope type
|
||||
function M.get_definition_scopes(node, bufnr, scope_type)
|
||||
local scopes = {}
|
||||
local scope_count = 1 ---@type integer|nil
|
||||
|
||||
-- Definition is valid for the containing scope
|
||||
-- and the containing scope of that scope
|
||||
if scope_type == "parent" then
|
||||
scope_count = 2
|
||||
-- Definition is valid in all parent scopes
|
||||
elseif scope_type == "global" then
|
||||
scope_count = nil
|
||||
end
|
||||
|
||||
local i = 0
|
||||
for scope in M.iter_scope_tree(node, bufnr) do
|
||||
table.insert(scopes, scope)
|
||||
i = i + 1
|
||||
|
||||
if scope_count and i >= scope_count then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
return scopes
|
||||
end
|
||||
|
||||
---@param node TSNode
|
||||
---@param bufnr integer
|
||||
---@return TSNode node
|
||||
---@return TSNode scope
|
||||
---@return string|nil kind
|
||||
function M.find_definition(node, bufnr)
|
||||
local def_lookup = M.get_definitions_lookup_table(bufnr)
|
||||
local node_text = ts.get_node_text(node, bufnr)
|
||||
|
||||
for scope in M.iter_scope_tree(node, bufnr) do
|
||||
local id = M.get_definition_id(scope, node_text)
|
||||
|
||||
if def_lookup[id] then
|
||||
local entry = def_lookup[id]
|
||||
|
||||
return entry.node, scope, entry.kind
|
||||
end
|
||||
end
|
||||
|
||||
return node, ts_utils.get_root_for_node(node), nil
|
||||
end
|
||||
|
||||
-- Finds usages of a node in a given scope.
|
||||
---@param node TSNode the node to find usages for
|
||||
---@param scope_node TSNode the node to look within
|
||||
---@return TSNode[]: a list of nodes
|
||||
function M.find_usages(node, scope_node, bufnr)
|
||||
bufnr = bufnr or api.nvim_get_current_buf()
|
||||
local node_text = ts.get_node_text(node, bufnr)
|
||||
|
||||
if not node_text or #node_text < 1 then
|
||||
return {}
|
||||
end
|
||||
|
||||
local scope_node = scope_node or ts_utils.get_root_for_node(node)
|
||||
local usages = {}
|
||||
|
||||
for match in M.iter_locals(bufnr, scope_node) do
|
||||
if match.reference and match.reference.node and ts.get_node_text(match.reference.node, bufnr) == node_text then
|
||||
local def_node, _, kind = M.find_definition(match.reference.node, bufnr)
|
||||
|
||||
if kind == nil or def_node == node then
|
||||
table.insert(usages, match.reference.node)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return usages
|
||||
end
|
||||
|
||||
---@param node TSNode
|
||||
---@param bufnr? integer
|
||||
---@param allow_scope? boolean
|
||||
---@return TSNode|nil
|
||||
function M.containing_scope(node, bufnr, allow_scope)
|
||||
local bufnr = bufnr or api.nvim_get_current_buf()
|
||||
local allow_scope = allow_scope == nil or allow_scope == true
|
||||
|
||||
local scopes = M.get_scopes(bufnr)
|
||||
if not node or not scopes then
|
||||
return
|
||||
end
|
||||
|
||||
local iter_node = node
|
||||
|
||||
while iter_node ~= nil and not vim.tbl_contains(scopes, iter_node) do
|
||||
iter_node = iter_node:parent()
|
||||
end
|
||||
|
||||
return iter_node or (allow_scope and node or nil)
|
||||
end
|
||||
|
||||
function M.nested_scope(node, cursor_pos)
|
||||
local bufnr = api.nvim_get_current_buf()
|
||||
|
||||
local scopes = M.get_scopes(bufnr)
|
||||
if not node or not scopes then
|
||||
return
|
||||
end
|
||||
|
||||
local row = cursor_pos.row ---@type integer
|
||||
local col = cursor_pos.col ---@type integer
|
||||
local scope = M.containing_scope(node)
|
||||
|
||||
for _, child in ipairs(ts_utils.get_named_children(scope)) do
|
||||
local row_, col_ = child:start()
|
||||
if vim.tbl_contains(scopes, child) and ((row_ + 1 == row and col_ > col) or row_ + 1 > row) then
|
||||
return child
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function M.next_scope(node)
|
||||
local bufnr = api.nvim_get_current_buf()
|
||||
|
||||
local scopes = M.get_scopes(bufnr)
|
||||
if not node or not scopes then
|
||||
return
|
||||
end
|
||||
|
||||
local scope = M.containing_scope(node)
|
||||
|
||||
local parent = scope:parent()
|
||||
if not parent then
|
||||
return
|
||||
end
|
||||
|
||||
local is_prev = true
|
||||
for _, child in ipairs(ts_utils.get_named_children(parent)) do
|
||||
if child == scope then
|
||||
is_prev = false
|
||||
elseif not is_prev and vim.tbl_contains(scopes, child) then
|
||||
return child
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@param node TSNode
|
||||
---@return TSNode|nil
|
||||
function M.previous_scope(node)
|
||||
local bufnr = api.nvim_get_current_buf()
|
||||
|
||||
local scopes = M.get_scopes(bufnr)
|
||||
if not node or not scopes then
|
||||
return
|
||||
end
|
||||
|
||||
local scope = M.containing_scope(node)
|
||||
|
||||
local parent = scope:parent()
|
||||
if not parent then
|
||||
return
|
||||
end
|
||||
|
||||
local is_prev = true
|
||||
local children = ts_utils.get_named_children(parent)
|
||||
for i = #children, 1, -1 do
|
||||
if children[i] == scope then
|
||||
is_prev = false
|
||||
elseif not is_prev and vim.tbl_contains(scopes, children[i]) then
|
||||
return children[i]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
100
lua/nvim-treesitter/log.lua
Normal file
100
lua/nvim-treesitter/log.lua
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
local echo = vim.api.nvim_echo
|
||||
|
||||
-- TODO(lewis6991): write these out to a file
|
||||
local messages = {} --- @type {[1]: string, [2]: string?, [3]: string}[]
|
||||
|
||||
local sev_to_hl = {
|
||||
trace = 'DiagnosticHint',
|
||||
debug = 'Normal',
|
||||
info = 'MoreMsg',
|
||||
warn = 'WarningMsg',
|
||||
error = 'ErrorMsg',
|
||||
}
|
||||
|
||||
---@param ctx string?
|
||||
---@return string
|
||||
local function mkpfx(ctx)
|
||||
return ctx and string.format('[nvim-treesitter/%s]', ctx) or '[nvim-treesitter]'
|
||||
end
|
||||
|
||||
---@class TSLogModule
|
||||
---@field trace fun(fmt: string, ...: any)
|
||||
---@field debug fun(fmt: string, ...: any)
|
||||
---@field info fun(fmt: string, ...: any)
|
||||
---@field warn fun(fmt: string, ...: any)
|
||||
---@field error fun(fmt: string, ...: any)
|
||||
local M = {}
|
||||
|
||||
---@class Logger
|
||||
---@field ctx? string
|
||||
local Logger = {}
|
||||
|
||||
M.Logger = Logger
|
||||
|
||||
---@param ctx? string
|
||||
---@return Logger
|
||||
function M.new(ctx)
|
||||
return setmetatable({ ctx = ctx }, { __index = Logger })
|
||||
end
|
||||
|
||||
---@param m string
|
||||
---@param ... any
|
||||
function Logger:trace(m, ...)
|
||||
messages[#messages + 1] = { 'trace', self.ctx, m:format(...) }
|
||||
end
|
||||
|
||||
---@param m string
|
||||
---@param ... any
|
||||
function Logger:debug(m, ...)
|
||||
messages[#messages + 1] = { 'debug', self.ctx, m:format(...) }
|
||||
end
|
||||
|
||||
---@param m string
|
||||
---@param ... any
|
||||
function Logger:info(m, ...)
|
||||
local m1 = m:format(...)
|
||||
messages[#messages + 1] = { 'info', self.ctx, m1 }
|
||||
echo({ { mkpfx(self.ctx) .. ': ' .. m1, sev_to_hl.info } }, true, {})
|
||||
end
|
||||
|
||||
---@param m string
|
||||
---@param ... any
|
||||
function Logger:warn(m, ...)
|
||||
local m1 = m:format(...)
|
||||
messages[#messages + 1] = { 'warn', self.ctx, m1 }
|
||||
echo({ { mkpfx(self.ctx) .. ' warning: ' .. m1, sev_to_hl.warn } }, true, {})
|
||||
end
|
||||
|
||||
---@param m string
|
||||
---@param ... any
|
||||
---@return string
|
||||
function Logger:error(m, ...)
|
||||
local m1 = m:format(...)
|
||||
messages[#messages + 1] = { 'error', self.ctx, m1 }
|
||||
echo({ { mkpfx(self.ctx) .. ' error: ' .. m1, sev_to_hl.error } }, true, {})
|
||||
return m1
|
||||
end
|
||||
|
||||
local noctx_logger = M.new()
|
||||
|
||||
setmetatable(M, {
|
||||
__index = function(t, k)
|
||||
--- @diagnostic disable-next-line:no-unknown
|
||||
t[k] = function(...)
|
||||
return noctx_logger[k](noctx_logger, ...)
|
||||
end
|
||||
return t[k]
|
||||
end,
|
||||
})
|
||||
|
||||
function M.show()
|
||||
for _, l in ipairs(messages) do
|
||||
local sev, ctx, msg = l[1], l[2], l[3]
|
||||
local hl = sev_to_hl[sev]
|
||||
local text = ctx and string.format('%s(%s): %s', sev, ctx, msg)
|
||||
or string.format('%s: %s', sev, msg)
|
||||
echo({ { text, hl } }, false, {})
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,453 +0,0 @@
|
|||
local api = vim.api
|
||||
local ts = require "nvim-treesitter.compat"
|
||||
local tsrange = require "nvim-treesitter.tsrange"
|
||||
local utils = require "nvim-treesitter.utils"
|
||||
local parsers = require "nvim-treesitter.parsers"
|
||||
local caching = require "nvim-treesitter.caching"
|
||||
|
||||
local M = {}
|
||||
|
||||
local EMPTY_ITER = function() end
|
||||
|
||||
M.built_in_query_groups = { "highlights", "locals", "folds", "indents", "injections" }
|
||||
|
||||
-- Creates a function that checks whether a given query exists
|
||||
-- for a specific language.
|
||||
---@param query string
|
||||
---@return fun(string): boolean
|
||||
local function get_query_guard(query)
|
||||
return function(lang)
|
||||
return M.has_query_files(lang, query)
|
||||
end
|
||||
end
|
||||
|
||||
for _, query in ipairs(M.built_in_query_groups) do
|
||||
M["has_" .. query] = get_query_guard(query)
|
||||
end
|
||||
|
||||
---@return string[]
|
||||
function M.available_query_groups()
|
||||
local query_files = api.nvim_get_runtime_file("queries/*/*.scm", true)
|
||||
local groups = {}
|
||||
for _, f in ipairs(query_files) do
|
||||
groups[vim.fn.fnamemodify(f, ":t:r")] = true
|
||||
end
|
||||
local list = {}
|
||||
for k, _ in pairs(groups) do
|
||||
table.insert(list, k)
|
||||
end
|
||||
return list
|
||||
end
|
||||
|
||||
do
|
||||
local query_cache = caching.create_buffer_cache()
|
||||
|
||||
local function update_cached_matches(bufnr, changed_tick, query_group)
|
||||
query_cache.set(query_group, bufnr, {
|
||||
tick = changed_tick,
|
||||
cache = M.collect_group_results(bufnr, query_group) or {},
|
||||
})
|
||||
end
|
||||
|
||||
---@param bufnr integer
|
||||
---@param query_group string
|
||||
---@return any
|
||||
function M.get_matches(bufnr, query_group)
|
||||
bufnr = bufnr or api.nvim_get_current_buf()
|
||||
local cached_local = query_cache.get(query_group, bufnr)
|
||||
if not cached_local or api.nvim_buf_get_changedtick(bufnr) > cached_local.tick then
|
||||
update_cached_matches(bufnr, api.nvim_buf_get_changedtick(bufnr), query_group)
|
||||
end
|
||||
|
||||
return query_cache.get(query_group, bufnr).cache
|
||||
end
|
||||
end
|
||||
|
||||
---@param lang string
|
||||
---@param query_name string
|
||||
---@return string[]
|
||||
local function runtime_queries(lang, query_name)
|
||||
return api.nvim_get_runtime_file(string.format("queries/%s/%s.scm", lang, query_name), true) or {}
|
||||
end
|
||||
|
||||
---@type table<string, table<string, boolean>>
|
||||
local query_files_cache = {}
|
||||
|
||||
---@param lang string
|
||||
---@param query_name string
|
||||
---@return boolean
|
||||
function M.has_query_files(lang, query_name)
|
||||
if not query_files_cache[lang] then
|
||||
query_files_cache[lang] = {}
|
||||
end
|
||||
if query_files_cache[lang][query_name] == nil then
|
||||
local files = runtime_queries(lang, query_name)
|
||||
query_files_cache[lang][query_name] = files and #files > 0
|
||||
end
|
||||
return query_files_cache[lang][query_name]
|
||||
end
|
||||
|
||||
do
|
||||
local mt = {}
|
||||
mt.__index = function(tbl, key)
|
||||
if rawget(tbl, key) == nil then
|
||||
rawset(tbl, key, {})
|
||||
end
|
||||
return rawget(tbl, key)
|
||||
end
|
||||
|
||||
-- cache will auto set the table for each lang if it is nil
|
||||
---@type table<string, table<string, Query>>
|
||||
local cache = setmetatable({}, mt)
|
||||
|
||||
-- Same as `vim.treesitter.query` except will return cached values
|
||||
---@param lang string
|
||||
---@param query_name string
|
||||
function M.get_query(lang, query_name)
|
||||
if cache[lang][query_name] == nil then
|
||||
cache[lang][query_name] = ts.get_query(lang, query_name)
|
||||
end
|
||||
|
||||
return cache[lang][query_name]
|
||||
end
|
||||
|
||||
-- Invalidates the query file cache.
|
||||
--
|
||||
-- If lang and query_name is both present, will reload for only the lang and query_name.
|
||||
-- If only lang is present, will reload all query_names for that lang
|
||||
-- If none are present, will reload everything
|
||||
---@param lang? string
|
||||
---@param query_name? string
|
||||
function M.invalidate_query_cache(lang, query_name)
|
||||
if lang and query_name then
|
||||
cache[lang][query_name] = nil
|
||||
if query_files_cache[lang] then
|
||||
query_files_cache[lang][query_name] = nil
|
||||
end
|
||||
elseif lang and not query_name then
|
||||
query_files_cache[lang] = nil
|
||||
for query_name0, _ in pairs(cache[lang]) do
|
||||
M.invalidate_query_cache(lang, query_name0)
|
||||
end
|
||||
elseif not lang and not query_name then
|
||||
query_files_cache = {}
|
||||
for lang0, _ in pairs(cache) do
|
||||
for query_name0, _ in pairs(cache[lang0]) do
|
||||
M.invalidate_query_cache(lang0, query_name0)
|
||||
end
|
||||
end
|
||||
else
|
||||
error "Cannot have query_name by itself!"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- This function is meant for an autocommand and not to be used. Only use if file is a query file.
|
||||
---@param fname string
|
||||
function M.invalidate_query_file(fname)
|
||||
local fnamemodify = vim.fn.fnamemodify
|
||||
M.invalidate_query_cache(fnamemodify(fname, ":p:h:t"), fnamemodify(fname, ":t:r"))
|
||||
end
|
||||
|
||||
---@class QueryInfo
|
||||
---@field root TSNode
|
||||
---@field source integer
|
||||
---@field start integer
|
||||
---@field stop integer
|
||||
|
||||
---@param bufnr integer
|
||||
---@param query_name string
|
||||
---@param root TSNode
|
||||
---@param root_lang string|nil
|
||||
---@return Query|nil, QueryInfo|nil
|
||||
local function prepare_query(bufnr, query_name, root, root_lang)
|
||||
local buf_lang = parsers.get_buf_lang(bufnr)
|
||||
|
||||
if not buf_lang then
|
||||
return
|
||||
end
|
||||
|
||||
local parser = parsers.get_parser(bufnr, buf_lang)
|
||||
if not parser then
|
||||
return
|
||||
end
|
||||
|
||||
if not root then
|
||||
local first_tree = parser:trees()[1]
|
||||
|
||||
if first_tree then
|
||||
root = first_tree:root()
|
||||
end
|
||||
end
|
||||
|
||||
if not root then
|
||||
return
|
||||
end
|
||||
|
||||
local range = { root:range() }
|
||||
|
||||
if not root_lang then
|
||||
local lang_tree = parser:language_for_range(range)
|
||||
|
||||
if lang_tree then
|
||||
root_lang = lang_tree:lang()
|
||||
end
|
||||
end
|
||||
|
||||
if not root_lang then
|
||||
return
|
||||
end
|
||||
|
||||
local query = M.get_query(root_lang, query_name)
|
||||
if not query then
|
||||
return
|
||||
end
|
||||
|
||||
return query,
|
||||
{
|
||||
root = root,
|
||||
source = bufnr,
|
||||
start = range[1],
|
||||
-- The end row is exclusive so we need to add 1 to it.
|
||||
stop = range[3] + 1,
|
||||
}
|
||||
end
|
||||
|
||||
-- Given a path (i.e. a List(String)) this functions inserts value at path
|
||||
---@param object any
|
||||
---@param path string[]
|
||||
---@param value any
|
||||
function M.insert_to_path(object, path, value)
|
||||
local curr_obj = object
|
||||
|
||||
for index = 1, (#path - 1) do
|
||||
if curr_obj[path[index]] == nil then
|
||||
curr_obj[path[index]] = {}
|
||||
end
|
||||
|
||||
curr_obj = curr_obj[path[index]]
|
||||
end
|
||||
|
||||
curr_obj[path[#path]] = value
|
||||
end
|
||||
|
||||
---@param query Query
|
||||
---@param bufnr integer
|
||||
---@param start_row integer
|
||||
---@param end_row integer
|
||||
function M.iter_prepared_matches(query, qnode, bufnr, start_row, end_row)
|
||||
-- A function that splits a string on '.'
|
||||
---@param to_split string
|
||||
---@return string[]
|
||||
local function split(to_split)
|
||||
local t = {}
|
||||
for str in string.gmatch(to_split, "([^.]+)") do
|
||||
table.insert(t, str)
|
||||
end
|
||||
|
||||
return t
|
||||
end
|
||||
|
||||
local matches = query:iter_matches(qnode, bufnr, start_row, end_row)
|
||||
|
||||
local function iterator()
|
||||
local pattern, match, metadata = matches()
|
||||
if pattern ~= nil then
|
||||
local prepared_match = {}
|
||||
|
||||
-- Extract capture names from each match
|
||||
for id, node in pairs(match) do
|
||||
local name = query.captures[id] -- name of the capture in the query
|
||||
if name ~= nil then
|
||||
local path = split(name .. ".node")
|
||||
M.insert_to_path(prepared_match, path, node)
|
||||
local metadata_path = split(name .. ".metadata")
|
||||
M.insert_to_path(prepared_match, metadata_path, metadata[id])
|
||||
end
|
||||
end
|
||||
|
||||
-- Add some predicates for testing
|
||||
---@type string[][] ( TODO: make pred type so this can be pred[])
|
||||
local preds = query.info.patterns[pattern]
|
||||
if preds then
|
||||
for _, pred in pairs(preds) do
|
||||
-- functions
|
||||
if pred[1] == "set!" and type(pred[2]) == "string" then
|
||||
M.insert_to_path(prepared_match, split(pred[2]), pred[3])
|
||||
end
|
||||
if pred[1] == "make-range!" and type(pred[2]) == "string" and #pred == 4 then
|
||||
M.insert_to_path(
|
||||
prepared_match,
|
||||
split(pred[2] .. ".node"),
|
||||
tsrange.TSRange.from_nodes(bufnr, match[pred[3]], match[pred[4]])
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return prepared_match
|
||||
end
|
||||
end
|
||||
return iterator
|
||||
end
|
||||
|
||||
-- Return all nodes corresponding to a specific capture path (like @definition.var, @reference.type)
|
||||
-- Works like M.get_references or M.get_scopes except you can choose the capture
|
||||
-- Can also be a nested capture like @definition.function to get all nodes defining a function.
|
||||
--
|
||||
---@param bufnr integer the buffer
|
||||
---@param captures string|string[]
|
||||
---@param query_group string the name of query group (highlights or injections for example)
|
||||
---@param root TSNode|nil node from where to start the search
|
||||
---@param lang string|nil the language from where to get the captures.
|
||||
--- Root nodes can have several languages.
|
||||
---@return table|nil
|
||||
function M.get_capture_matches(bufnr, captures, query_group, root, lang)
|
||||
if type(captures) == "string" then
|
||||
captures = { captures }
|
||||
end
|
||||
local strip_captures = {} ---@type string[]
|
||||
for i, capture in ipairs(captures) do
|
||||
if capture:sub(1, 1) ~= "@" then
|
||||
error 'Captures must start with "@"'
|
||||
return
|
||||
end
|
||||
-- Remove leading "@".
|
||||
strip_captures[i] = capture:sub(2)
|
||||
end
|
||||
|
||||
local matches = {}
|
||||
for match in M.iter_group_results(bufnr, query_group, root, lang) do
|
||||
for _, capture in ipairs(strip_captures) do
|
||||
local insert = utils.get_at_path(match, capture)
|
||||
if insert then
|
||||
table.insert(matches, insert)
|
||||
end
|
||||
end
|
||||
end
|
||||
return matches
|
||||
end
|
||||
|
||||
function M.iter_captures(bufnr, query_name, root, lang)
|
||||
local query, params = prepare_query(bufnr, query_name, root, lang)
|
||||
if not query then
|
||||
return EMPTY_ITER
|
||||
end
|
||||
assert(params)
|
||||
|
||||
local iter = query:iter_captures(params.root, params.source, params.start, params.stop)
|
||||
|
||||
local function wrapped_iter()
|
||||
local id, node, metadata = iter()
|
||||
if not id then
|
||||
return
|
||||
end
|
||||
|
||||
local name = query.captures[id]
|
||||
if string.sub(name, 1, 1) == "_" then
|
||||
return wrapped_iter()
|
||||
end
|
||||
|
||||
return name, node, metadata
|
||||
end
|
||||
|
||||
return wrapped_iter
|
||||
end
|
||||
|
||||
---@param bufnr integer
|
||||
---@param capture_string string
|
||||
---@param query_group string
|
||||
---@param filter_predicate fun(match: table): boolean
|
||||
---@param scoring_function fun(match: table): number
|
||||
---@param root TSNode
|
||||
---@return table|unknown
|
||||
function M.find_best_match(bufnr, capture_string, query_group, filter_predicate, scoring_function, root)
|
||||
if string.sub(capture_string, 1, 1) == "@" then
|
||||
--remove leading "@"
|
||||
capture_string = string.sub(capture_string, 2)
|
||||
end
|
||||
|
||||
local best ---@type table|nil
|
||||
local best_score ---@type number
|
||||
|
||||
for maybe_match in M.iter_group_results(bufnr, query_group, root) do
|
||||
local match = utils.get_at_path(maybe_match, capture_string)
|
||||
|
||||
if match and filter_predicate(match) then
|
||||
local current_score = scoring_function(match)
|
||||
if not best then
|
||||
best = match
|
||||
best_score = current_score
|
||||
end
|
||||
if current_score > best_score then
|
||||
best = match
|
||||
best_score = current_score
|
||||
end
|
||||
end
|
||||
end
|
||||
return best
|
||||
end
|
||||
|
||||
---Iterates matches from a query file.
|
||||
---@param bufnr integer the buffer
|
||||
---@param query_group string the query file to use
|
||||
---@param root TSNode the root node
|
||||
---@param root_lang? string the root node lang, if known
|
||||
function M.iter_group_results(bufnr, query_group, root, root_lang)
|
||||
local query, params = prepare_query(bufnr, query_group, root, root_lang)
|
||||
if not query then
|
||||
return EMPTY_ITER
|
||||
end
|
||||
assert(params)
|
||||
|
||||
return M.iter_prepared_matches(query, params.root, params.source, params.start, params.stop)
|
||||
end
|
||||
|
||||
function M.collect_group_results(bufnr, query_group, root, lang)
|
||||
local matches = {}
|
||||
|
||||
for prepared_match in M.iter_group_results(bufnr, query_group, root, lang) do
|
||||
table.insert(matches, prepared_match)
|
||||
end
|
||||
|
||||
return matches
|
||||
end
|
||||
|
||||
---@alias CaptureResFn function(string, LanguageTree, LanguageTree): string, string
|
||||
|
||||
-- Same as get_capture_matches except this will recursively get matches for every language in the tree.
|
||||
---@param bufnr integer The buffer
|
||||
---@param capture_or_fn string|CaptureResFn The capture to get. If a function is provided then that
|
||||
--- function will be used to resolve both the capture and query argument.
|
||||
--- The function can return `nil` to ignore that tree.
|
||||
---@param query_type string? The query to get the capture from. This is ignored if a function is provided
|
||||
--- for the capture argument.
|
||||
---@return table[]
|
||||
function M.get_capture_matches_recursively(bufnr, capture_or_fn, query_type)
|
||||
---@type CaptureResFn
|
||||
local type_fn
|
||||
if type(capture_or_fn) == "function" then
|
||||
type_fn = capture_or_fn
|
||||
else
|
||||
type_fn = function(_, _, _)
|
||||
return capture_or_fn, query_type
|
||||
end
|
||||
end
|
||||
local parser = parsers.get_parser(bufnr)
|
||||
local matches = {}
|
||||
|
||||
if parser then
|
||||
parser:for_each_tree(function(tree, lang_tree)
|
||||
local lang = lang_tree:lang()
|
||||
local capture, type_ = type_fn(lang, tree, lang_tree)
|
||||
|
||||
if capture then
|
||||
vim.list_extend(matches, M.get_capture_matches(bufnr, capture, type_, tree:root(), lang) or {})
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
return matches
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
@ -1,238 +0,0 @@
|
|||
local query = require "vim.treesitter.query"
|
||||
|
||||
local html_script_type_languages = {
|
||||
["importmap"] = "json",
|
||||
["module"] = "javascript",
|
||||
["application/ecmascript"] = "javascript",
|
||||
["text/ecmascript"] = "javascript",
|
||||
}
|
||||
|
||||
local non_filetype_match_injection_language_aliases = {
|
||||
ex = "elixir",
|
||||
pl = "perl",
|
||||
sh = "bash",
|
||||
uxn = "uxntal",
|
||||
ts = "typescript",
|
||||
}
|
||||
|
||||
local function get_parser_from_markdown_info_string(injection_alias)
|
||||
local match = vim.filetype.match { filename = "a." .. injection_alias }
|
||||
return match or non_filetype_match_injection_language_aliases[injection_alias] or injection_alias
|
||||
end
|
||||
|
||||
local function error(str)
|
||||
vim.api.nvim_err_writeln(str)
|
||||
end
|
||||
|
||||
local function valid_args(name, pred, count, strict_count)
|
||||
local arg_count = #pred - 1
|
||||
|
||||
if strict_count then
|
||||
if arg_count ~= count then
|
||||
error(string.format("%s must have exactly %d arguments", name, count))
|
||||
return false
|
||||
end
|
||||
elseif arg_count < count then
|
||||
error(string.format("%s must have at least %d arguments", name, count))
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
---@param match (TSNode|nil)[]
|
||||
---@param _pattern string
|
||||
---@param _bufnr integer
|
||||
---@param pred string[]
|
||||
---@return boolean|nil
|
||||
query.add_predicate("nth?", function(match, _pattern, _bufnr, pred)
|
||||
if not valid_args("nth?", pred, 2, true) then
|
||||
return
|
||||
end
|
||||
|
||||
local node = match[pred[2]] ---@type TSNode
|
||||
local n = tonumber(pred[3])
|
||||
if node and node:parent() and node:parent():named_child_count() > n then
|
||||
return node:parent():named_child(n) == node
|
||||
end
|
||||
|
||||
return false
|
||||
end, true)
|
||||
|
||||
---@param match (TSNode|nil)[]
|
||||
---@param _pattern string
|
||||
---@param _bufnr integer
|
||||
---@param pred string[]
|
||||
---@return boolean|nil
|
||||
local function has_ancestor(match, _pattern, _bufnr, pred)
|
||||
if not valid_args(pred[1], pred, 2) then
|
||||
return
|
||||
end
|
||||
|
||||
local node = match[pred[2]]
|
||||
local ancestor_types = { unpack(pred, 3) }
|
||||
if not node then
|
||||
return true
|
||||
end
|
||||
|
||||
local just_direct_parent = pred[1]:find("has-parent", 1, true)
|
||||
|
||||
node = node:parent()
|
||||
while node do
|
||||
if vim.tbl_contains(ancestor_types, node:type()) then
|
||||
return true
|
||||
end
|
||||
if just_direct_parent then
|
||||
node = nil
|
||||
else
|
||||
node = node:parent()
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
query.add_predicate("has-ancestor?", has_ancestor, true)
|
||||
|
||||
query.add_predicate("has-parent?", has_ancestor, true)
|
||||
|
||||
---@param match (TSNode|nil)[]
|
||||
---@param _pattern string
|
||||
---@param bufnr integer
|
||||
---@param pred string[]
|
||||
---@return boolean|nil
|
||||
query.add_predicate("is?", function(match, _pattern, bufnr, pred)
|
||||
if not valid_args("is?", pred, 2) then
|
||||
return
|
||||
end
|
||||
|
||||
-- Avoid circular dependencies
|
||||
local locals = require "nvim-treesitter.locals"
|
||||
local node = match[pred[2]]
|
||||
local types = { unpack(pred, 3) }
|
||||
|
||||
if not node then
|
||||
return true
|
||||
end
|
||||
|
||||
local _, _, kind = locals.find_definition(node, bufnr)
|
||||
|
||||
return vim.tbl_contains(types, kind)
|
||||
end, true)
|
||||
|
||||
---@param match (TSNode|nil)[]
|
||||
---@param _pattern string
|
||||
---@param _bufnr integer
|
||||
---@param pred string[]
|
||||
---@return boolean|nil
|
||||
query.add_predicate("has-type?", function(match, _pattern, _bufnr, pred)
|
||||
if not valid_args(pred[1], pred, 2) then
|
||||
return
|
||||
end
|
||||
|
||||
local node = match[pred[2]]
|
||||
local types = { unpack(pred, 3) }
|
||||
|
||||
if not node then
|
||||
return true
|
||||
end
|
||||
|
||||
return vim.tbl_contains(types, node:type())
|
||||
end, true)
|
||||
|
||||
---@param match (TSNode|nil)[]
|
||||
---@param _ string
|
||||
---@param bufnr integer
|
||||
---@param pred string[]
|
||||
---@return boolean|nil
|
||||
query.add_directive("set-lang-from-mimetype!", function(match, _, bufnr, pred, metadata)
|
||||
local capture_id = pred[2]
|
||||
local node = match[capture_id]
|
||||
if not node then
|
||||
return
|
||||
end
|
||||
local type_attr_value = vim.treesitter.get_node_text(node, bufnr)
|
||||
local configured = html_script_type_languages[type_attr_value]
|
||||
if configured then
|
||||
metadata["injection.language"] = configured
|
||||
else
|
||||
local parts = vim.split(type_attr_value, "/", {})
|
||||
metadata["injection.language"] = parts[#parts]
|
||||
end
|
||||
end, true)
|
||||
|
||||
---@param match (TSNode|nil)[]
|
||||
---@param _ string
|
||||
---@param bufnr integer
|
||||
---@param pred string[]
|
||||
---@return boolean|nil
|
||||
query.add_directive("set-lang-from-info-string!", function(match, _, bufnr, pred, metadata)
|
||||
local capture_id = pred[2]
|
||||
local node = match[capture_id]
|
||||
if not node then
|
||||
return
|
||||
end
|
||||
local injection_alias = vim.treesitter.get_node_text(node, bufnr)
|
||||
metadata["injection.language"] = get_parser_from_markdown_info_string(injection_alias)
|
||||
end, true)
|
||||
|
||||
-- Just avoid some annoying warnings for this directive
|
||||
query.add_directive("make-range!", function() end, true)
|
||||
|
||||
--- transform node text to lower case (e.g., to make @injection.language case insensitive)
|
||||
---
|
||||
---@param match (TSNode|nil)[]
|
||||
---@param _ string
|
||||
---@param bufnr integer
|
||||
---@param pred string[]
|
||||
---@return boolean|nil
|
||||
query.add_directive("downcase!", function(match, _, bufnr, pred, metadata)
|
||||
local id = pred[2]
|
||||
local node = match[id]
|
||||
if not node then
|
||||
return
|
||||
end
|
||||
|
||||
local text = vim.treesitter.get_node_text(node, bufnr, { metadata = metadata[id] }) or ""
|
||||
if not metadata[id] then
|
||||
metadata[id] = {}
|
||||
end
|
||||
metadata[id].text = string.lower(text)
|
||||
end, true)
|
||||
|
||||
-- Trim blank lines from end of the region
|
||||
-- Arguments are the captures to trim.
|
||||
---@param match (TSNode|nil)[]
|
||||
---@param _ string
|
||||
---@param bufnr integer
|
||||
---@param pred string[]
|
||||
---@param metadata table
|
||||
query.add_directive("trim!", function(match, _, bufnr, pred, metadata)
|
||||
for _, id in ipairs { select(2, unpack(pred)) } do
|
||||
local node = match[id]
|
||||
local start_row, start_col, end_row, end_col = node:range()
|
||||
|
||||
-- Don't trim if region ends in middle of a line
|
||||
if end_col ~= 0 then
|
||||
return
|
||||
end
|
||||
|
||||
while true do
|
||||
-- As we only care when end_col == 0, always inspect one line above end_row.
|
||||
local end_line = vim.api.nvim_buf_get_lines(bufnr, end_row - 1, end_row, true)[1]
|
||||
|
||||
if end_line ~= "" then
|
||||
break
|
||||
end
|
||||
|
||||
end_row = end_row - 1
|
||||
end
|
||||
|
||||
-- If this produces an invalid range, we just skip it.
|
||||
if start_row < end_row or (start_row == end_row and start_col <= end_col) then
|
||||
if not metadata[id] then
|
||||
metadata[id] = {}
|
||||
end
|
||||
metadata[id].range = { start_row, start_col, end_row, end_col }
|
||||
end
|
||||
end
|
||||
end, true)
|
||||
|
|
@ -1,335 +0,0 @@
|
|||
local fn = vim.fn
|
||||
local utils = require "nvim-treesitter.utils"
|
||||
|
||||
-- Convert path for cmd.exe on Windows.
|
||||
-- This is needed when vim.opt.shellslash is in use.
|
||||
---@param p string
|
||||
---@return string
|
||||
local function cmdpath(p)
|
||||
if vim.opt.shellslash:get() then
|
||||
local r = p:gsub("/", "\\")
|
||||
return r
|
||||
else
|
||||
return p
|
||||
end
|
||||
end
|
||||
|
||||
local M = {}
|
||||
|
||||
-- Returns the mkdir command based on the OS
|
||||
---@param directory string
|
||||
---@param cwd string
|
||||
---@param info_msg string
|
||||
---@return table
|
||||
function M.select_mkdir_cmd(directory, cwd, info_msg)
|
||||
if fn.has "win32" == 1 then
|
||||
return {
|
||||
cmd = "cmd",
|
||||
opts = {
|
||||
args = { "/C", "mkdir", cmdpath(directory) },
|
||||
cwd = cwd,
|
||||
},
|
||||
info = info_msg,
|
||||
err = "Could not create " .. directory,
|
||||
}
|
||||
else
|
||||
return {
|
||||
cmd = "mkdir",
|
||||
opts = {
|
||||
args = { directory },
|
||||
cwd = cwd,
|
||||
},
|
||||
info = info_msg,
|
||||
err = "Could not create " .. directory,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
-- Returns the remove command based on the OS
|
||||
---@param file string
|
||||
---@param info_msg string
|
||||
---@return table
|
||||
function M.select_rm_file_cmd(file, info_msg)
|
||||
if fn.has "win32" == 1 then
|
||||
return {
|
||||
cmd = "cmd",
|
||||
opts = {
|
||||
args = { "/C", "if", "exist", cmdpath(file), "del", cmdpath(file) },
|
||||
},
|
||||
info = info_msg,
|
||||
err = "Could not delete " .. file,
|
||||
}
|
||||
else
|
||||
return {
|
||||
cmd = "rm",
|
||||
opts = {
|
||||
args = { file },
|
||||
},
|
||||
info = info_msg,
|
||||
err = "Could not delete " .. file,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
---@param executables string[]
|
||||
---@return string|nil
|
||||
function M.select_executable(executables)
|
||||
return vim.tbl_filter(function(c) ---@param c string
|
||||
return c ~= vim.NIL and fn.executable(c) == 1
|
||||
end, executables)[1]
|
||||
end
|
||||
|
||||
-- Returns the compiler arguments based on the compiler and OS
|
||||
---@param repo InstallInfo
|
||||
---@param compiler string
|
||||
---@return string[]
|
||||
function M.select_compiler_args(repo, compiler)
|
||||
if string.match(compiler, "cl$") or string.match(compiler, "cl.exe$") then
|
||||
return {
|
||||
"/Fe:",
|
||||
"parser.so",
|
||||
"/Isrc",
|
||||
repo.files,
|
||||
"-Os",
|
||||
"/LD",
|
||||
}
|
||||
elseif string.match(compiler, "zig$") or string.match(compiler, "zig.exe$") then
|
||||
return {
|
||||
"c++",
|
||||
"-o",
|
||||
"parser.so",
|
||||
repo.files,
|
||||
"-lc",
|
||||
"-Isrc",
|
||||
"-shared",
|
||||
"-Os",
|
||||
}
|
||||
else
|
||||
local args = {
|
||||
"-o",
|
||||
"parser.so",
|
||||
"-I./src",
|
||||
repo.files,
|
||||
"-Os",
|
||||
}
|
||||
if fn.has "mac" == 1 then
|
||||
table.insert(args, "-bundle")
|
||||
else
|
||||
table.insert(args, "-shared")
|
||||
end
|
||||
if
|
||||
#vim.tbl_filter(function(file) ---@param file string
|
||||
local ext = vim.fn.fnamemodify(file, ":e")
|
||||
return ext == "cc" or ext == "cpp" or ext == "cxx"
|
||||
end, repo.files) > 0
|
||||
then
|
||||
table.insert(args, "-lstdc++")
|
||||
end
|
||||
if fn.has "win32" == 0 then
|
||||
table.insert(args, "-fPIC")
|
||||
end
|
||||
return args
|
||||
end
|
||||
end
|
||||
|
||||
-- Returns the compile command based on the OS and user options
|
||||
---@param repo InstallInfo
|
||||
---@param cc string
|
||||
---@param compile_location string
|
||||
---@return Command
|
||||
function M.select_compile_command(repo, cc, compile_location)
|
||||
local make = M.select_executable { "gmake", "make" }
|
||||
if
|
||||
string.match(cc, "cl$")
|
||||
or string.match(cc, "cl.exe$")
|
||||
or not repo.use_makefile
|
||||
or fn.has "win32" == 1
|
||||
or not make
|
||||
then
|
||||
return {
|
||||
cmd = cc,
|
||||
info = "Compiling...",
|
||||
err = "Error during compilation",
|
||||
opts = {
|
||||
args = vim.tbl_flatten(M.select_compiler_args(repo, cc)),
|
||||
cwd = compile_location,
|
||||
},
|
||||
}
|
||||
else
|
||||
return {
|
||||
cmd = make,
|
||||
info = "Compiling...",
|
||||
err = "Error during compilation",
|
||||
opts = {
|
||||
args = {
|
||||
"--makefile=" .. utils.join_path(utils.get_package_path(), "scripts", "compile_parsers.makefile"),
|
||||
"CC=" .. cc,
|
||||
"CXX_STANDARD=" .. (repo.cxx_standard or "c++14"),
|
||||
},
|
||||
cwd = compile_location,
|
||||
},
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
-- Returns the remove command based on the OS
|
||||
---@param cache_folder string
|
||||
---@param project_name string
|
||||
---@return Command
|
||||
function M.select_install_rm_cmd(cache_folder, project_name)
|
||||
if fn.has "win32" == 1 then
|
||||
local dir = cache_folder .. "\\" .. project_name
|
||||
return {
|
||||
cmd = "cmd",
|
||||
opts = {
|
||||
args = { "/C", "if", "exist", cmdpath(dir), "rmdir", "/s", "/q", cmdpath(dir) },
|
||||
},
|
||||
}
|
||||
else
|
||||
return {
|
||||
cmd = "rm",
|
||||
opts = {
|
||||
args = { "-rf", cache_folder .. "/" .. project_name },
|
||||
},
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
-- Returns the move command based on the OS
|
||||
---@param from string
|
||||
---@param to string
|
||||
---@param cwd string
|
||||
---@return Command
|
||||
function M.select_mv_cmd(from, to, cwd)
|
||||
if fn.has "win32" == 1 then
|
||||
return {
|
||||
cmd = "cmd",
|
||||
opts = {
|
||||
args = { "/C", "move", "/Y", cmdpath(from), cmdpath(to) },
|
||||
cwd = cwd,
|
||||
},
|
||||
}
|
||||
else
|
||||
return {
|
||||
cmd = "mv",
|
||||
opts = {
|
||||
args = { "-f", from, to },
|
||||
cwd = cwd,
|
||||
},
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
---@param repo InstallInfo
|
||||
---@param project_name string
|
||||
---@param cache_folder string
|
||||
---@param revision string|nil
|
||||
---@param prefer_git boolean
|
||||
---@return table
|
||||
function M.select_download_commands(repo, project_name, cache_folder, revision, prefer_git)
|
||||
local can_use_tar = vim.fn.executable "tar" == 1 and vim.fn.executable "curl" == 1
|
||||
local is_github = repo.url:find("github.com", 1, true)
|
||||
local is_gitlab = repo.url:find("gitlab.com", 1, true)
|
||||
|
||||
revision = revision or repo.branch or "master"
|
||||
|
||||
if can_use_tar and (is_github or is_gitlab) and not prefer_git then
|
||||
local path_sep = utils.get_path_sep()
|
||||
local url = repo.url:gsub(".git$", "")
|
||||
|
||||
local folder_rev = revision
|
||||
if is_github and revision:match "^v%d" then
|
||||
folder_rev = revision:sub(2)
|
||||
end
|
||||
|
||||
return {
|
||||
M.select_install_rm_cmd(cache_folder, project_name .. "-tmp"),
|
||||
{
|
||||
cmd = "curl",
|
||||
info = "Downloading " .. project_name .. "...",
|
||||
err = "Error during download, please verify your internet connection",
|
||||
opts = {
|
||||
args = {
|
||||
"--silent",
|
||||
"-L", -- follow redirects
|
||||
is_github and url .. "/archive/" .. revision .. ".tar.gz"
|
||||
or url .. "/-/archive/" .. revision .. "/" .. project_name .. "-" .. revision .. ".tar.gz",
|
||||
"--output",
|
||||
project_name .. ".tar.gz",
|
||||
},
|
||||
cwd = cache_folder,
|
||||
},
|
||||
},
|
||||
M.select_mkdir_cmd(project_name .. "-tmp", cache_folder, "Creating temporary directory"),
|
||||
{
|
||||
cmd = "tar",
|
||||
info = "Extracting " .. project_name .. "...",
|
||||
err = "Error during tarball extraction.",
|
||||
opts = {
|
||||
args = {
|
||||
"-xvzf",
|
||||
project_name .. ".tar.gz",
|
||||
"-C",
|
||||
project_name .. "-tmp",
|
||||
},
|
||||
cwd = cache_folder,
|
||||
},
|
||||
},
|
||||
M.select_rm_file_cmd(cache_folder .. path_sep .. project_name .. ".tar.gz"),
|
||||
M.select_mv_cmd(
|
||||
utils.join_path(project_name .. "-tmp", url:match "[^/]-$" .. "-" .. folder_rev),
|
||||
project_name,
|
||||
cache_folder
|
||||
),
|
||||
M.select_install_rm_cmd(cache_folder, project_name .. "-tmp"),
|
||||
}
|
||||
else
|
||||
local git_folder = utils.join_path(cache_folder, project_name)
|
||||
local clone_error = "Error during download, please verify your internet connection"
|
||||
|
||||
return {
|
||||
{
|
||||
cmd = "git",
|
||||
info = "Downloading " .. project_name .. "...",
|
||||
err = clone_error,
|
||||
opts = {
|
||||
args = {
|
||||
"clone",
|
||||
repo.url,
|
||||
project_name,
|
||||
},
|
||||
cwd = cache_folder,
|
||||
},
|
||||
},
|
||||
{
|
||||
cmd = "git",
|
||||
info = "Checking out locked revision",
|
||||
err = "Error while checking out revision",
|
||||
opts = {
|
||||
args = {
|
||||
"checkout",
|
||||
revision,
|
||||
},
|
||||
cwd = git_folder,
|
||||
},
|
||||
},
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
---@param dir string
|
||||
---@param command string
|
||||
---@return string command
|
||||
function M.make_directory_change_for_command(dir, command)
|
||||
if fn.has "win32" == 1 then
|
||||
if string.find(vim.o.shell, "cmd") ~= nil then
|
||||
return string.format("pushd %s & %s & popd", cmdpath(dir), command)
|
||||
else
|
||||
return string.format("pushd %s ; %s ; popd", cmdpath(dir), command)
|
||||
end
|
||||
else
|
||||
return string.format("cd %s;\n %s", dir, command)
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
local parsers = require "nvim-treesitter.parsers"
|
||||
local ts_utils = require "nvim-treesitter.ts_utils"
|
||||
|
||||
local M = {}
|
||||
|
||||
-- Trim spaces and opening brackets from end
|
||||
local transform_line = function(line)
|
||||
return line:gsub("%s*[%[%(%{]*%s*$", "")
|
||||
end
|
||||
|
||||
function M.statusline(opts)
|
||||
if not parsers.has_parser() then
|
||||
return
|
||||
end
|
||||
local options = opts or {}
|
||||
if type(opts) == "number" then
|
||||
options = { indicator_size = opts }
|
||||
end
|
||||
local bufnr = options.bufnr or 0
|
||||
local indicator_size = options.indicator_size or 100
|
||||
local type_patterns = options.type_patterns or { "class", "function", "method" }
|
||||
local transform_fn = options.transform_fn or transform_line
|
||||
local separator = options.separator or " -> "
|
||||
local allow_duplicates = options.allow_duplicates or false
|
||||
|
||||
local current_node = ts_utils.get_node_at_cursor()
|
||||
if not current_node then
|
||||
return ""
|
||||
end
|
||||
|
||||
local lines = {}
|
||||
local expr = current_node
|
||||
|
||||
while expr do
|
||||
local line = ts_utils._get_line_for_node(expr, type_patterns, transform_fn, bufnr)
|
||||
if line ~= "" then
|
||||
if allow_duplicates or not vim.tbl_contains(lines, line) then
|
||||
table.insert(lines, 1, line)
|
||||
end
|
||||
end
|
||||
expr = expr:parent()
|
||||
end
|
||||
|
||||
local text = table.concat(lines, separator)
|
||||
local text_len = #text
|
||||
if text_len > indicator_size then
|
||||
return "..." .. text:sub(text_len - indicator_size, text_len)
|
||||
end
|
||||
|
||||
return text
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
@ -1,467 +0,0 @@
|
|||
local api = vim.api
|
||||
|
||||
local parsers = require "nvim-treesitter.parsers"
|
||||
local utils = require "nvim-treesitter.utils"
|
||||
local ts = vim.treesitter
|
||||
|
||||
local M = {}
|
||||
|
||||
local function get_node_text(node, bufnr)
|
||||
bufnr = bufnr or api.nvim_get_current_buf()
|
||||
if not node then
|
||||
return {}
|
||||
end
|
||||
|
||||
-- We have to remember that end_col is end-exclusive
|
||||
local start_row, start_col, end_row, end_col = ts.get_node_range(node)
|
||||
|
||||
if start_row ~= end_row then
|
||||
local lines = api.nvim_buf_get_lines(bufnr, start_row, end_row + 1, false)
|
||||
if next(lines) == nil then
|
||||
return {}
|
||||
end
|
||||
lines[1] = string.sub(lines[1], start_col + 1)
|
||||
-- end_row might be just after the last line. In this case the last line is not truncated.
|
||||
if #lines == end_row - start_row + 1 then
|
||||
lines[#lines] = string.sub(lines[#lines], 1, end_col)
|
||||
end
|
||||
return lines
|
||||
else
|
||||
local line = api.nvim_buf_get_lines(bufnr, start_row, start_row + 1, false)[1]
|
||||
-- If line is nil then the line is empty
|
||||
return line and { string.sub(line, start_col + 1, end_col) } or {}
|
||||
end
|
||||
end
|
||||
|
||||
---@private
|
||||
---@param node TSNode
|
||||
---@param type_patterns string[]
|
||||
---@param transform_fn fun(line: string): string
|
||||
---@param bufnr integer
|
||||
---@return string
|
||||
function M._get_line_for_node(node, type_patterns, transform_fn, bufnr)
|
||||
local node_type = node:type()
|
||||
local is_valid = false
|
||||
for _, rgx in ipairs(type_patterns) do
|
||||
if node_type:find(rgx) then
|
||||
is_valid = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if not is_valid then
|
||||
return ""
|
||||
end
|
||||
local line = transform_fn(vim.trim(get_node_text(node, bufnr)[1] or ""), node)
|
||||
-- Escape % to avoid statusline to evaluate content as expression
|
||||
return line:gsub("%%", "%%%%")
|
||||
end
|
||||
|
||||
-- Gets the actual text content of a node
|
||||
-- @deprecated Use vim.treesitter.query.get_node_text
|
||||
-- @param node the node to get the text from
|
||||
-- @param bufnr the buffer containing the node
|
||||
-- @return list of lines of text of the node
|
||||
function M.get_node_text(node, bufnr)
|
||||
vim.notify_once(
|
||||
"nvim-treesitter.ts_utils.get_node_text is deprecated: use vim.treesitter.query.get_node_text",
|
||||
vim.log.levels.WARN
|
||||
)
|
||||
return get_node_text(node, bufnr)
|
||||
end
|
||||
|
||||
-- Determines whether a node is the parent of another
|
||||
-- @param dest the possible parent
|
||||
-- @param source the possible child node
|
||||
function M.is_parent(dest, source)
|
||||
if not (dest and source) then
|
||||
return false
|
||||
end
|
||||
|
||||
local current = source
|
||||
while current ~= nil do
|
||||
if current == dest then
|
||||
return true
|
||||
end
|
||||
|
||||
current = current:parent()
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
-- Get next node with same parent
|
||||
---@param node TSNode
|
||||
---@param allow_switch_parents? boolean allow switching parents if last node
|
||||
---@param allow_next_parent? boolean allow next parent if last node and next parent without children
|
||||
function M.get_next_node(node, allow_switch_parents, allow_next_parent)
|
||||
local destination_node ---@type TSNode
|
||||
local parent = node:parent()
|
||||
|
||||
if not parent then
|
||||
return
|
||||
end
|
||||
local found_pos = 0
|
||||
for i = 0, parent:named_child_count() - 1, 1 do
|
||||
if parent:named_child(i) == node then
|
||||
found_pos = i
|
||||
break
|
||||
end
|
||||
end
|
||||
if parent:named_child_count() > found_pos + 1 then
|
||||
destination_node = parent:named_child(found_pos + 1)
|
||||
elseif allow_switch_parents then
|
||||
local next_node = M.get_next_node(node:parent())
|
||||
if next_node and next_node:named_child_count() > 0 then
|
||||
destination_node = next_node:named_child(0)
|
||||
elseif next_node and allow_next_parent then
|
||||
destination_node = next_node
|
||||
end
|
||||
end
|
||||
|
||||
return destination_node
|
||||
end
|
||||
|
||||
-- Get previous node with same parent
|
||||
---@param node TSNode
|
||||
---@param allow_switch_parents? boolean allow switching parents if first node
|
||||
---@param allow_previous_parent? boolean allow previous parent if first node and previous parent without children
|
||||
function M.get_previous_node(node, allow_switch_parents, allow_previous_parent)
|
||||
local destination_node ---@type TSNode
|
||||
local parent = node:parent()
|
||||
if not parent then
|
||||
return
|
||||
end
|
||||
|
||||
local found_pos = 0
|
||||
for i = 0, parent:named_child_count() - 1, 1 do
|
||||
if parent:named_child(i) == node then
|
||||
found_pos = i
|
||||
break
|
||||
end
|
||||
end
|
||||
if 0 < found_pos then
|
||||
destination_node = parent:named_child(found_pos - 1)
|
||||
elseif allow_switch_parents then
|
||||
local previous_node = M.get_previous_node(node:parent())
|
||||
if previous_node and previous_node:named_child_count() > 0 then
|
||||
destination_node = previous_node:named_child(previous_node:named_child_count() - 1)
|
||||
elseif previous_node and allow_previous_parent then
|
||||
destination_node = previous_node
|
||||
end
|
||||
end
|
||||
return destination_node
|
||||
end
|
||||
|
||||
function M.get_named_children(node)
|
||||
local nodes = {} ---@type TSNode[]
|
||||
for i = 0, node:named_child_count() - 1, 1 do
|
||||
nodes[i + 1] = node:named_child(i)
|
||||
end
|
||||
return nodes
|
||||
end
|
||||
|
||||
function M.get_node_at_cursor(winnr, ignore_injected_langs)
|
||||
winnr = winnr or 0
|
||||
local cursor = api.nvim_win_get_cursor(winnr)
|
||||
local cursor_range = { cursor[1] - 1, cursor[2] }
|
||||
|
||||
local buf = vim.api.nvim_win_get_buf(winnr)
|
||||
local root_lang_tree = parsers.get_parser(buf)
|
||||
if not root_lang_tree then
|
||||
return
|
||||
end
|
||||
|
||||
local root ---@type TSNode|nil
|
||||
if ignore_injected_langs then
|
||||
for _, tree in pairs(root_lang_tree:trees()) do
|
||||
local tree_root = tree:root()
|
||||
if tree_root and ts.is_in_node_range(tree_root, cursor_range[1], cursor_range[2]) then
|
||||
root = tree_root
|
||||
break
|
||||
end
|
||||
end
|
||||
else
|
||||
root = M.get_root_for_position(cursor_range[1], cursor_range[2], root_lang_tree)
|
||||
end
|
||||
|
||||
if not root then
|
||||
return
|
||||
end
|
||||
|
||||
return root:named_descendant_for_range(cursor_range[1], cursor_range[2], cursor_range[1], cursor_range[2])
|
||||
end
|
||||
|
||||
function M.get_root_for_position(line, col, root_lang_tree)
|
||||
if not root_lang_tree then
|
||||
if not parsers.has_parser() then
|
||||
return
|
||||
end
|
||||
|
||||
root_lang_tree = parsers.get_parser()
|
||||
end
|
||||
|
||||
local lang_tree = root_lang_tree:language_for_range { line, col, line, col }
|
||||
|
||||
for _, tree in pairs(lang_tree:trees()) do
|
||||
local root = tree:root()
|
||||
|
||||
if root and ts.is_in_node_range(root, line, col) then
|
||||
return root, tree, lang_tree
|
||||
end
|
||||
end
|
||||
|
||||
-- This isn't a likely scenario, since the position must belong to a tree somewhere.
|
||||
return nil, nil, lang_tree
|
||||
end
|
||||
|
||||
---comment
|
||||
---@param node TSNode
|
||||
---@return TSNode result
|
||||
function M.get_root_for_node(node)
|
||||
local parent = node
|
||||
local result = node
|
||||
|
||||
while parent ~= nil do
|
||||
result = parent
|
||||
parent = result:parent()
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
function M.highlight_node(node, buf, hl_namespace, hl_group)
|
||||
if not node then
|
||||
return
|
||||
end
|
||||
M.highlight_range({ node:range() }, buf, hl_namespace, hl_group)
|
||||
end
|
||||
|
||||
-- Get a compatible vim range (1 index based) from a TS node range.
|
||||
--
|
||||
-- TS nodes start with 0 and the end col is ending exclusive.
|
||||
-- They also treat a EOF/EOL char as a char ending in the first
|
||||
-- col of the next row.
|
||||
---comment
|
||||
---@param range integer[]
|
||||
---@param buf integer|nil
|
||||
---@return integer, integer, integer, integer
|
||||
function M.get_vim_range(range, buf)
|
||||
---@type integer, integer, integer, integer
|
||||
local srow, scol, erow, ecol = unpack(range)
|
||||
srow = srow + 1
|
||||
scol = scol + 1
|
||||
erow = erow + 1
|
||||
|
||||
if ecol == 0 then
|
||||
-- Use the value of the last col of the previous row instead.
|
||||
erow = erow - 1
|
||||
if not buf or buf == 0 then
|
||||
ecol = vim.fn.col { erow, "$" } - 1
|
||||
else
|
||||
ecol = #api.nvim_buf_get_lines(buf, erow - 1, erow, false)[1]
|
||||
end
|
||||
ecol = math.max(ecol, 1)
|
||||
end
|
||||
return srow, scol, erow, ecol
|
||||
end
|
||||
|
||||
function M.highlight_range(range, buf, hl_namespace, hl_group)
|
||||
---@type integer, integer, integer, integer
|
||||
local start_row, start_col, end_row, end_col = unpack(range)
|
||||
---@diagnostic disable-next-line: missing-parameter
|
||||
vim.highlight.range(buf, hl_namespace, hl_group, { start_row, start_col }, { end_row, end_col })
|
||||
end
|
||||
|
||||
-- Set visual selection to node
|
||||
-- @param selection_mode One of "charwise" (default) or "v", "linewise" or "V",
|
||||
-- "blockwise" or "<C-v>" (as a string with 5 characters or a single character)
|
||||
function M.update_selection(buf, node, selection_mode)
|
||||
local start_row, start_col, end_row, end_col = M.get_vim_range({ ts.get_node_range(node) }, buf)
|
||||
|
||||
local v_table = { charwise = "v", linewise = "V", blockwise = "<C-v>" }
|
||||
selection_mode = selection_mode or "charwise"
|
||||
|
||||
-- Normalise selection_mode
|
||||
if vim.tbl_contains(vim.tbl_keys(v_table), selection_mode) then
|
||||
selection_mode = v_table[selection_mode]
|
||||
end
|
||||
|
||||
-- enter visual mode if normal or operator-pending (no) mode
|
||||
-- Why? According to https://learnvimscriptthehardway.stevelosh.com/chapters/15.html
|
||||
-- If your operator-pending mapping ends with some text visually selected, Vim will operate on that text.
|
||||
-- Otherwise, Vim will operate on the text between the original cursor position and the new position.
|
||||
local mode = api.nvim_get_mode()
|
||||
if mode.mode ~= selection_mode then
|
||||
-- Call to `nvim_replace_termcodes()` is needed for sending appropriate command to enter blockwise mode
|
||||
selection_mode = vim.api.nvim_replace_termcodes(selection_mode, true, true, true)
|
||||
api.nvim_cmd({ cmd = "normal", bang = true, args = { selection_mode } }, {})
|
||||
end
|
||||
|
||||
api.nvim_win_set_cursor(0, { start_row, start_col - 1 })
|
||||
vim.cmd "normal! o"
|
||||
api.nvim_win_set_cursor(0, { end_row, end_col - 1 })
|
||||
end
|
||||
|
||||
-- Byte length of node range
|
||||
---@param node TSNode
|
||||
---@return number
|
||||
function M.node_length(node)
|
||||
local _, _, start_byte = node:start()
|
||||
local _, _, end_byte = node:end_()
|
||||
return end_byte - start_byte
|
||||
end
|
||||
|
||||
---@deprecated Use `vim.treesitter.is_in_node_range()` instead
|
||||
function M.is_in_node_range(node, line, col)
|
||||
vim.notify_once(
|
||||
"nvim-treesitter.ts_utils.is_in_node_range is deprecated: use vim.treesitter.is_in_node_range",
|
||||
vim.log.levels.WARN
|
||||
)
|
||||
return ts.is_in_node_range(node, line, col)
|
||||
end
|
||||
|
||||
---@deprecated Use `vim.treesitter.get_node_range()` instead
|
||||
function M.get_node_range(node_or_range)
|
||||
vim.notify_once(
|
||||
"nvim-treesitter.ts_utils.get_node_range is deprecated: use vim.treesitter.get_node_range",
|
||||
vim.log.levels.WARN
|
||||
)
|
||||
return ts.get_node_range(node_or_range)
|
||||
end
|
||||
|
||||
---@param node TSNode
|
||||
---@return table
|
||||
function M.node_to_lsp_range(node)
|
||||
local start_line, start_col, end_line, end_col = ts.get_node_range(node)
|
||||
local rtn = {}
|
||||
rtn.start = { line = start_line, character = start_col }
|
||||
rtn["end"] = { line = end_line, character = end_col }
|
||||
return rtn
|
||||
end
|
||||
|
||||
-- Memoizes a function based on the buffer tick of the provided bufnr.
|
||||
-- The cache entry is cleared when the buffer is detached to avoid memory leaks.
|
||||
-- The options argument is a table with two optional values:
|
||||
-- - bufnr: extracts a bufnr from the given arguments.
|
||||
-- - key: extracts the cache key from the given arguments.
|
||||
---@param fn function the fn to memoize, taking the buffer as first argument
|
||||
---@param options? {bufnr: integer?, key: string|fun(...): string?} the memoization options
|
||||
---@return function: a memoized function
|
||||
function M.memoize_by_buf_tick(fn, options)
|
||||
options = options or {}
|
||||
|
||||
---@type table<string, {result: any, last_tick: integer}>
|
||||
local cache = setmetatable({}, { __mode = "kv" })
|
||||
local bufnr_fn = utils.to_func(options.bufnr or utils.identity)
|
||||
local key_fn = utils.to_func(options.key or utils.identity)
|
||||
|
||||
return function(...)
|
||||
local bufnr = bufnr_fn(...)
|
||||
local key = key_fn(...)
|
||||
local tick = api.nvim_buf_get_changedtick(bufnr)
|
||||
|
||||
if cache[key] then
|
||||
if cache[key].last_tick == tick then
|
||||
return cache[key].result
|
||||
end
|
||||
else
|
||||
local function detach_handler()
|
||||
cache[key] = nil
|
||||
end
|
||||
|
||||
-- Clean up logic only!
|
||||
api.nvim_buf_attach(bufnr, false, {
|
||||
on_detach = detach_handler,
|
||||
on_reload = detach_handler,
|
||||
})
|
||||
end
|
||||
|
||||
cache[key] = {
|
||||
result = fn(...),
|
||||
last_tick = tick,
|
||||
}
|
||||
|
||||
return cache[key].result
|
||||
end
|
||||
end
|
||||
|
||||
function M.swap_nodes(node_or_range1, node_or_range2, bufnr, cursor_to_second)
|
||||
if not node_or_range1 or not node_or_range2 then
|
||||
return
|
||||
end
|
||||
local range1 = M.node_to_lsp_range(node_or_range1)
|
||||
local range2 = M.node_to_lsp_range(node_or_range2)
|
||||
|
||||
local text1 = get_node_text(node_or_range1, bufnr)
|
||||
local text2 = get_node_text(node_or_range2, bufnr)
|
||||
|
||||
local edit1 = { range = range1, newText = table.concat(text2, "\n") }
|
||||
local edit2 = { range = range2, newText = table.concat(text1, "\n") }
|
||||
vim.lsp.util.apply_text_edits({ edit1, edit2 }, bufnr, "utf-8")
|
||||
|
||||
if cursor_to_second then
|
||||
utils.set_jump()
|
||||
|
||||
local char_delta = 0
|
||||
local line_delta = 0
|
||||
if
|
||||
range1["end"].line < range2.start.line
|
||||
or (range1["end"].line == range2.start.line and range1["end"].character <= range2.start.character)
|
||||
then
|
||||
line_delta = #text2 - #text1
|
||||
end
|
||||
|
||||
if range1["end"].line == range2.start.line and range1["end"].character <= range2.start.character then
|
||||
if line_delta ~= 0 then
|
||||
--- why?
|
||||
--correction_after_line_change = -range2.start.character
|
||||
--text_now_before_range2 = #(text2[#text2])
|
||||
--space_between_ranges = range2.start.character - range1["end"].character
|
||||
--char_delta = correction_after_line_change + text_now_before_range2 + space_between_ranges
|
||||
--- Equivalent to:
|
||||
char_delta = #text2[#text2] - range1["end"].character
|
||||
|
||||
-- add range1.start.character if last line of range1 (now text2) does not start at 0
|
||||
if range1.start.line == range2.start.line + line_delta then
|
||||
char_delta = char_delta + range1.start.character
|
||||
end
|
||||
else
|
||||
char_delta = #text2[#text2] - #text1[#text1]
|
||||
end
|
||||
end
|
||||
|
||||
api.nvim_win_set_cursor(
|
||||
api.nvim_get_current_win(),
|
||||
{ range2.start.line + 1 + line_delta, range2.start.character + char_delta }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
function M.goto_node(node, goto_end, avoid_set_jump)
|
||||
if not node then
|
||||
return
|
||||
end
|
||||
if not avoid_set_jump then
|
||||
utils.set_jump()
|
||||
end
|
||||
local range = { M.get_vim_range { node:range() } }
|
||||
---@type table<number>
|
||||
local position
|
||||
if not goto_end then
|
||||
position = { range[1], range[2] }
|
||||
else
|
||||
position = { range[3], range[4] }
|
||||
end
|
||||
|
||||
-- Enter visual mode if we are in operator pending mode
|
||||
-- If we don't do this, it will miss the last character.
|
||||
local mode = vim.api.nvim_get_mode()
|
||||
if mode.mode == "no" then
|
||||
vim.cmd "normal! v"
|
||||
end
|
||||
|
||||
-- Position is 1, 0 indexed.
|
||||
api.nvim_win_set_cursor(0, { position[1], position[2] - 1 })
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
@ -1,154 +0,0 @@
|
|||
local M = {}
|
||||
local TSRange = {}
|
||||
TSRange.__index = TSRange
|
||||
|
||||
local api = vim.api
|
||||
local ts_utils = require "nvim-treesitter.ts_utils"
|
||||
local parsers = require "nvim-treesitter.parsers"
|
||||
|
||||
local function get_byte_offset(buf, row, col)
|
||||
return api.nvim_buf_get_offset(buf, row) + vim.fn.byteidx(api.nvim_buf_get_lines(buf, row, row + 1, false)[1], col)
|
||||
end
|
||||
|
||||
function TSRange.new(buf, start_row, start_col, end_row, end_col)
|
||||
return setmetatable({
|
||||
start_pos = { start_row, start_col, get_byte_offset(buf, start_row, start_col) },
|
||||
end_pos = { end_row, end_col, get_byte_offset(buf, end_row, end_col) },
|
||||
buf = buf,
|
||||
[1] = start_row,
|
||||
[2] = start_col,
|
||||
[3] = end_row,
|
||||
[4] = end_col,
|
||||
}, TSRange)
|
||||
end
|
||||
|
||||
function TSRange.from_nodes(buf, start_node, end_node)
|
||||
TSRange.__index = TSRange
|
||||
local start_pos = start_node and { start_node:start() } or { end_node:start() }
|
||||
local end_pos = end_node and { end_node:end_() } or { start_node:end_() }
|
||||
return setmetatable({
|
||||
start_pos = { start_pos[1], start_pos[2], start_pos[3] },
|
||||
end_pos = { end_pos[1], end_pos[2], end_pos[3] },
|
||||
buf = buf,
|
||||
[1] = start_pos[1],
|
||||
[2] = start_pos[2],
|
||||
[3] = end_pos[1],
|
||||
[4] = end_pos[2],
|
||||
}, TSRange)
|
||||
end
|
||||
|
||||
function TSRange.from_table(buf, range)
|
||||
return setmetatable({
|
||||
start_pos = { range[1], range[2], get_byte_offset(buf, range[1], range[2]) },
|
||||
end_pos = { range[3], range[4], get_byte_offset(buf, range[3], range[4]) },
|
||||
buf = buf,
|
||||
[1] = range[1],
|
||||
[2] = range[2],
|
||||
[3] = range[3],
|
||||
[4] = range[4],
|
||||
}, TSRange)
|
||||
end
|
||||
|
||||
function TSRange:parent()
|
||||
local root_lang_tree = parsers.get_parser(self.buf)
|
||||
local root = ts_utils.get_root_for_position(self[1], self[2], root_lang_tree)
|
||||
|
||||
return root
|
||||
and root:named_descendant_for_range(self.start_pos[1], self.start_pos[2], self.end_pos[1], self.end_pos[2])
|
||||
or nil
|
||||
end
|
||||
|
||||
function TSRange:field() end
|
||||
|
||||
function TSRange:child_count()
|
||||
return #self:collect_children()
|
||||
end
|
||||
|
||||
function TSRange:named_child_count()
|
||||
return #self:collect_children(function(c)
|
||||
return c:named()
|
||||
end)
|
||||
end
|
||||
|
||||
function TSRange:iter_children()
|
||||
local raw_iterator = self:parent().iter_children()
|
||||
return function()
|
||||
while true do
|
||||
local node = raw_iterator()
|
||||
if not node then
|
||||
return
|
||||
end
|
||||
local _, _, start_byte = node:start()
|
||||
local _, _, end_byte = node:end_()
|
||||
if start_byte >= self.start_pos[3] and end_byte <= self.end_pos[3] then
|
||||
return node
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function TSRange:collect_children(filter_fun)
|
||||
local children = {}
|
||||
for _, c in self:iter_children() do
|
||||
if not filter_fun or filter_fun(c) then
|
||||
table.insert(children, c)
|
||||
end
|
||||
end
|
||||
return children
|
||||
end
|
||||
|
||||
function TSRange:child(index)
|
||||
return self:collect_children()[index + 1]
|
||||
end
|
||||
|
||||
function TSRange:named_child(index)
|
||||
return self:collect_children(function(c)
|
||||
return c.named()
|
||||
end)[index + 1]
|
||||
end
|
||||
|
||||
function TSRange:start()
|
||||
return unpack(self.start_pos)
|
||||
end
|
||||
|
||||
function TSRange:end_()
|
||||
return unpack(self.end_pos)
|
||||
end
|
||||
|
||||
function TSRange:range()
|
||||
return self.start_pos[1], self.start_pos[2], self.end_pos[1], self.end_pos[2]
|
||||
end
|
||||
|
||||
function TSRange:type()
|
||||
return "nvim-treesitter-range"
|
||||
end
|
||||
|
||||
function TSRange:symbol()
|
||||
return -1
|
||||
end
|
||||
|
||||
function TSRange:named()
|
||||
return false
|
||||
end
|
||||
|
||||
function TSRange:missing()
|
||||
return false
|
||||
end
|
||||
|
||||
function TSRange:has_error()
|
||||
return #self:collect_children(function(c)
|
||||
return c:has_error()
|
||||
end) > 0 and true or false
|
||||
end
|
||||
|
||||
function TSRange:sexpr()
|
||||
return table.concat(
|
||||
vim.tbl_map(function(c)
|
||||
return c:sexpr()
|
||||
end, self:collect_children()),
|
||||
" "
|
||||
)
|
||||
end
|
||||
|
||||
M.TSRange = TSRange
|
||||
return M
|
||||
20
lua/nvim-treesitter/util.lua
Normal file
20
lua/nvim-treesitter/util.lua
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
local M = {}
|
||||
|
||||
--- @param filename string
|
||||
--- @return string
|
||||
function M.read_file(filename)
|
||||
local file = assert(io.open(filename, 'r'))
|
||||
local r = file:read('*a')
|
||||
file:close()
|
||||
return r
|
||||
end
|
||||
|
||||
--- @param filename string
|
||||
--- @param content string
|
||||
function M.write_file(filename, content)
|
||||
local file = assert(io.open(filename, 'w'))
|
||||
file:write(content)
|
||||
file:close()
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
@ -1,237 +0,0 @@
|
|||
local api = vim.api
|
||||
local fn = vim.fn
|
||||
local luv = vim.loop
|
||||
|
||||
local M = {}
|
||||
|
||||
-- Wrapper around vim.notify with common options set.
|
||||
---@param msg string
|
||||
---@param log_level number|nil
|
||||
---@param opts table|nil
|
||||
function M.notify(msg, log_level, opts)
|
||||
local default_opts = { title = "nvim-treesitter" }
|
||||
vim.notify(msg, log_level, vim.tbl_extend("force", default_opts, opts or {}))
|
||||
end
|
||||
|
||||
-- Returns the system-specific path separator.
|
||||
---@return string
|
||||
function M.get_path_sep()
|
||||
return (fn.has "win32" == 1 and not vim.opt.shellslash:get()) and "\\" or "/"
|
||||
end
|
||||
|
||||
-- Returns a function that joins the given arguments with separator. Arguments
|
||||
-- can't be nil. Example:
|
||||
--
|
||||
--[[
|
||||
print(M.generate_join(" ")("foo", "bar"))
|
||||
--]]
|
||||
--prints "foo bar"
|
||||
---@param separator string
|
||||
---@return fun(...: string): string
|
||||
function M.generate_join(separator)
|
||||
return function(...)
|
||||
return table.concat({ ... }, separator)
|
||||
end
|
||||
end
|
||||
|
||||
M.join_path = M.generate_join(M.get_path_sep())
|
||||
|
||||
M.join_space = M.generate_join " "
|
||||
|
||||
---@class Command
|
||||
---@field run function
|
||||
---@field f_args string
|
||||
---@field args string
|
||||
|
||||
-- Define user defined vim command which calls nvim-treesitter module function
|
||||
-- - If module name is 'mod', it should be defined in hierarchy 'nvim-treesitter.mod'
|
||||
-- - A table with name 'commands' should be defined in 'mod' which needs to be passed as
|
||||
-- the commands param of this function
|
||||
--
|
||||
---@param mod string Name of the module that resides in the hierarchy - nvim-treesitter.module
|
||||
---@param commands table<string, Command> Command list for the module
|
||||
--- - {command_name} Name of the vim user defined command, Keys:
|
||||
--- - {run}: (function) callback function that needs to be executed
|
||||
--- - {f_args}: (string, default <f-args>)
|
||||
--- - type of arguments that needs to be passed to the vim command
|
||||
--- - {args}: (string, optional)
|
||||
--- - vim command attributes
|
||||
---
|
||||
---* @example
|
||||
--- If module is nvim-treesitter.custom_mod
|
||||
--- <pre>
|
||||
--- M.commands = {
|
||||
--- custom_command = {
|
||||
--- run = M.module_function,
|
||||
--- f_args = "<f-args>",
|
||||
--- args = {
|
||||
--- "-range"
|
||||
--- }
|
||||
--- }
|
||||
--- }
|
||||
---
|
||||
--- utils.setup_commands("custom_mod", require("nvim-treesitter.custom_mod").commands)
|
||||
--- </pre>
|
||||
---
|
||||
--- Will generate command :
|
||||
--- <pre>
|
||||
--- command! -range custom_command \
|
||||
--- lua require'nvim-treesitter.custom_mod'.commands.custom_command['run<bang>'](<f-args>)
|
||||
--- </pre>
|
||||
function M.setup_commands(mod, commands)
|
||||
for command_name, def in pairs(commands) do
|
||||
local f_args = def.f_args or "<f-args>"
|
||||
local call_fn =
|
||||
string.format("lua require'nvim-treesitter.%s'.commands.%s['run<bang>'](%s)", mod, command_name, f_args)
|
||||
local parts = vim.tbl_flatten {
|
||||
"command!",
|
||||
"-bar",
|
||||
def.args,
|
||||
command_name,
|
||||
call_fn,
|
||||
}
|
||||
api.nvim_command(table.concat(parts, " "))
|
||||
end
|
||||
end
|
||||
|
||||
---@param dir string
|
||||
---@param create_err string
|
||||
---@param writeable_err string
|
||||
---@return string|nil, string|nil
|
||||
function M.create_or_reuse_writable_dir(dir, create_err, writeable_err)
|
||||
create_err = create_err or M.join_space("Could not create dir '", dir, "': ")
|
||||
writeable_err = writeable_err or M.join_space("Invalid rights, '", dir, "' should be read/write")
|
||||
-- Try creating and using parser_dir if it doesn't exist
|
||||
if not luv.fs_stat(dir) then
|
||||
local ok, error = pcall(vim.fn.mkdir, dir, "p", "0755")
|
||||
if not ok then
|
||||
return nil, M.join_space(create_err, error)
|
||||
end
|
||||
|
||||
return dir
|
||||
end
|
||||
|
||||
-- parser_dir exists, use it if it's read/write
|
||||
if luv.fs_access(dir, "RW") then
|
||||
return dir
|
||||
end
|
||||
|
||||
-- parser_dir exists but isn't read/write, give up
|
||||
return nil, M.join_space(writeable_err, dir, "'")
|
||||
end
|
||||
|
||||
function M.get_package_path()
|
||||
-- Path to this source file, removing the leading '@'
|
||||
local source = string.sub(debug.getinfo(1, "S").source, 2)
|
||||
|
||||
-- Path to the package root
|
||||
return fn.fnamemodify(source, ":p:h:h:h")
|
||||
end
|
||||
|
||||
function M.get_cache_dir()
|
||||
local cache_dir = fn.stdpath "data"
|
||||
|
||||
if luv.fs_access(cache_dir, "RW") then
|
||||
return cache_dir
|
||||
elseif luv.fs_access("/tmp", "RW") then
|
||||
return "/tmp"
|
||||
end
|
||||
|
||||
return nil, M.join_space("Invalid cache rights,", fn.stdpath "data", "or /tmp should be read/write")
|
||||
end
|
||||
|
||||
-- Returns $XDG_DATA_HOME/nvim/site, but could use any directory that is in
|
||||
-- runtimepath
|
||||
function M.get_site_dir()
|
||||
return M.join_path(fn.stdpath "data", "site")
|
||||
end
|
||||
|
||||
-- Gets a property at path
|
||||
---@param tbl table the table to access
|
||||
---@param path string the '.' separated path
|
||||
---@return table|nil result the value at path or nil
|
||||
function M.get_at_path(tbl, path)
|
||||
if path == "" then
|
||||
return tbl
|
||||
end
|
||||
|
||||
local segments = vim.split(path, ".", true)
|
||||
---@type table[]|table
|
||||
local result = tbl
|
||||
|
||||
for _, segment in ipairs(segments) do
|
||||
if type(result) == "table" then
|
||||
---@type table
|
||||
-- TODO: figure out the actual type of tbl
|
||||
result = result[segment]
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
function M.set_jump()
|
||||
vim.cmd "normal! m'"
|
||||
end
|
||||
|
||||
-- Filters a list based on the given predicate
|
||||
---@param tbl any[] The list to filter
|
||||
---@param predicate fun(v:any, i:number):boolean The predicate to filter with
|
||||
function M.filter(tbl, predicate)
|
||||
local result = {}
|
||||
|
||||
for i, v in ipairs(tbl) do
|
||||
if predicate(v, i) then
|
||||
table.insert(result, v)
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
-- Returns a list of all values from the first list
|
||||
-- that are not present in the second list.
|
||||
---@param tbl1 any[] The first table
|
||||
---@param tbl2 any[] The second table
|
||||
---@return table
|
||||
function M.difference(tbl1, tbl2)
|
||||
return M.filter(tbl1, function(v)
|
||||
return not vim.tbl_contains(tbl2, v)
|
||||
end)
|
||||
end
|
||||
|
||||
function M.identity(a)
|
||||
return a
|
||||
end
|
||||
|
||||
-- Returns a function returning the given value
|
||||
---@param a any
|
||||
---@return fun():any
|
||||
function M.constant(a)
|
||||
return function()
|
||||
return a
|
||||
end
|
||||
end
|
||||
|
||||
-- Returns a function that returns the given value if it is a function,
|
||||
-- otherwise returns a function that returns the given value.
|
||||
---@param a any
|
||||
---@return fun(...):any
|
||||
function M.to_func(a)
|
||||
return type(a) == "function" and a or M.constant(a)
|
||||
end
|
||||
|
||||
---@return string|nil
|
||||
function M.ts_cli_version()
|
||||
if fn.executable "tree-sitter" == 1 then
|
||||
local handle = io.popen "tree-sitter -V"
|
||||
if not handle then
|
||||
return
|
||||
end
|
||||
local result = handle:read "*a"
|
||||
handle:close()
|
||||
return vim.split(result, "\n")[1]:match "[^tree%psitter ].*"
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
2
parser-info/.gitignore
vendored
2
parser-info/.gitignore
vendored
|
|
@ -1,2 +0,0 @@
|
|||
*
|
||||
!.gitignore
|
||||
2
parser/.gitignore
vendored
2
parser/.gitignore
vendored
|
|
@ -1,2 +0,0 @@
|
|||
*
|
||||
!.gitignore
|
||||
69
plugin/filetypes.lua
Normal file
69
plugin/filetypes.lua
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
local filetypes = {
|
||||
angular = { 'htmlangular' },
|
||||
bash = { 'sh' },
|
||||
bibtex = { 'bib' },
|
||||
c_sharp = { 'cs', 'csharp' },
|
||||
commonlisp = { 'lisp' },
|
||||
cooklang = { 'cook' },
|
||||
devicetree = { 'dts' },
|
||||
diff = { 'gitdiff' },
|
||||
eex = { 'eelixir' },
|
||||
elixir = { 'ex' },
|
||||
embedded_template = { 'eruby' },
|
||||
erlang = { 'erl' },
|
||||
facility = { 'fsd' },
|
||||
faust = { 'dsp' },
|
||||
gdshader = { 'gdshaderinc' },
|
||||
git_config = { 'gitconfig' },
|
||||
git_rebase = { 'gitrebase' },
|
||||
glimmer = { 'handlebars', 'html.handlebars' },
|
||||
godot_resource = { 'gdresource' },
|
||||
haskell = { 'hs' },
|
||||
haskell_persistent = { 'haskellpersistent' },
|
||||
idris = { 'idris2' },
|
||||
ini = { 'confini', 'dosini' },
|
||||
janet_simple = { 'janet' },
|
||||
javascript = { 'javascriptreact', 'ecma', 'ecmascript', 'jsx', 'js' },
|
||||
json = { 'jsonc' },
|
||||
glimmer_javascript = { 'javascript.glimmer' },
|
||||
latex = { 'tex' },
|
||||
linkerscript = { 'ld' },
|
||||
m68k = { 'asm68k' },
|
||||
make = { 'automake' },
|
||||
markdown = { 'pandoc' },
|
||||
muttrc = { 'neomuttrc' },
|
||||
ocaml_interface = { 'ocamlinterface' },
|
||||
perl = { 'pl' },
|
||||
poe_filter = { 'poefilter' },
|
||||
powershell = { 'ps1' },
|
||||
properties = { 'jproperties' },
|
||||
python = { 'py', 'gyp' },
|
||||
qmljs = { 'qml' },
|
||||
runescript = { 'clientscript' },
|
||||
scala = { 'sbt' },
|
||||
slang = { 'shaderslang' },
|
||||
sqp = { 'mysqp' },
|
||||
ssh_config = { 'sshconfig' },
|
||||
starlark = { 'bzl' },
|
||||
surface = { 'sface' },
|
||||
systemverilog = { 'verilog' },
|
||||
t32 = { 'trace32' },
|
||||
tcl = { 'expect' },
|
||||
terraform = { 'terraform-vars' },
|
||||
textproto = { 'pbtxt' },
|
||||
tlaplus = { 'tla' },
|
||||
tsx = { 'typescriptreact', 'typescript.tsx' },
|
||||
typescript = { 'ts' },
|
||||
glimmer_typescript = { 'typescript.glimmer' },
|
||||
typst = { 'typ' },
|
||||
udev = { 'udevrules' },
|
||||
uxntal = { 'tal', 'uxn' },
|
||||
v = { 'vlang' },
|
||||
vhs = { 'tape' },
|
||||
xml = { 'xsd', 'xslt', 'svg' },
|
||||
xresources = { 'xdefaults' },
|
||||
}
|
||||
|
||||
for lang, ft in pairs(filetypes) do
|
||||
vim.treesitter.language.register(lang, ft)
|
||||
end
|
||||
|
|
@ -1,34 +1,75 @@
|
|||
-- Last Change: 2022 Apr 16
|
||||
|
||||
if vim.g.loaded_nvim_treesitter then
|
||||
return
|
||||
end
|
||||
vim.g.loaded_nvim_treesitter = true
|
||||
|
||||
-- setup modules
|
||||
require("nvim-treesitter").setup()
|
||||
|
||||
local api = vim.api
|
||||
|
||||
-- define autocommands
|
||||
local augroup = api.nvim_create_augroup("NvimTreesitter", {})
|
||||
local function complete_available_parsers(arglead)
|
||||
return vim.tbl_filter(
|
||||
--- @param v string
|
||||
function(v)
|
||||
return v:find(arglead) ~= nil
|
||||
end,
|
||||
require('nvim-treesitter.config').get_available()
|
||||
)
|
||||
end
|
||||
|
||||
api.nvim_create_autocmd("Filetype", {
|
||||
pattern = "query",
|
||||
group = augroup,
|
||||
callback = function()
|
||||
api.nvim_clear_autocmds {
|
||||
group = augroup,
|
||||
event = "BufWritePost",
|
||||
}
|
||||
api.nvim_create_autocmd("BufWritePost", {
|
||||
group = augroup,
|
||||
buffer = 0,
|
||||
callback = function(opts)
|
||||
require("nvim-treesitter.query").invalidate_query_file(opts.file)
|
||||
end,
|
||||
desc = "Invalidate query file",
|
||||
})
|
||||
end,
|
||||
desc = "Reload query",
|
||||
local function complete_installed_parsers(arglead)
|
||||
return vim.tbl_filter(
|
||||
--- @param v string
|
||||
function(v)
|
||||
return v:find(arglead) ~= nil
|
||||
end,
|
||||
require('nvim-treesitter.config').get_installed()
|
||||
)
|
||||
end
|
||||
|
||||
-- create user commands
|
||||
api.nvim_create_user_command('TSInstall', function(args)
|
||||
require('nvim-treesitter.install').install(args.fargs, { force = args.bang, summary = true })
|
||||
end, {
|
||||
nargs = '+',
|
||||
bang = true,
|
||||
bar = true,
|
||||
complete = complete_available_parsers,
|
||||
desc = 'Install treesitter parsers',
|
||||
})
|
||||
|
||||
api.nvim_create_user_command('TSInstallFromGrammar', function(args)
|
||||
require('nvim-treesitter.install').install(args.fargs, {
|
||||
generate = true,
|
||||
summary = true,
|
||||
force = args.bang,
|
||||
})
|
||||
end, {
|
||||
nargs = '+',
|
||||
bang = true,
|
||||
bar = true,
|
||||
complete = complete_available_parsers,
|
||||
desc = 'Install treesitter parsers from grammar',
|
||||
})
|
||||
|
||||
api.nvim_create_user_command('TSUpdate', function(args)
|
||||
require('nvim-treesitter.install').update(args.fargs, { summary = true })
|
||||
end, {
|
||||
nargs = '*',
|
||||
bar = true,
|
||||
complete = complete_installed_parsers,
|
||||
desc = 'Update installed treesitter parsers',
|
||||
})
|
||||
|
||||
api.nvim_create_user_command('TSUninstall', function(args)
|
||||
require('nvim-treesitter.install').uninstall(args.fargs, { summary = true })
|
||||
end, {
|
||||
nargs = '+',
|
||||
bar = true,
|
||||
complete = complete_installed_parsers,
|
||||
desc = 'Uninstall treesitter parsers',
|
||||
})
|
||||
|
||||
api.nvim_create_user_command('TSLog', function()
|
||||
require('nvim-treesitter.log').show()
|
||||
end, {
|
||||
desc = 'View log messages',
|
||||
})
|
||||
|
|
|
|||
41
plugin/query_predicates.lua
Normal file
41
plugin/query_predicates.lua
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
local query = vim.treesitter.query
|
||||
|
||||
local predicates = {
|
||||
---@param match table<integer,TSNode[]>
|
||||
---@param pred any[]
|
||||
---@param any boolean
|
||||
---@return boolean
|
||||
['kind-eq'] = function(match, pred, any)
|
||||
local nodes = match[pred[2]]
|
||||
if not nodes or #nodes == 0 then
|
||||
return true
|
||||
end
|
||||
|
||||
local types = { unpack(pred, 3) }
|
||||
for _, node in ipairs(nodes) do
|
||||
local res = vim.list_contains(types, node:type())
|
||||
if any and res then
|
||||
return true
|
||||
elseif not any and not res then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return not any
|
||||
end,
|
||||
}
|
||||
|
||||
-- register custom predicates (overwrite existing; needed for CI)
|
||||
|
||||
---@param match table<integer,TSNode[]>
|
||||
---@param pred any[]
|
||||
---@return boolean
|
||||
query.add_predicate('kind-eq?', function(match, _, _, pred)
|
||||
return predicates['kind-eq'](match, pred, false)
|
||||
end, { force = true })
|
||||
|
||||
---@param match table<integer,TSNode[]>
|
||||
---@param pred any[]
|
||||
---@return boolean
|
||||
query.add_predicate('any-kind-eq?', function(match, _, _, pred)
|
||||
return predicates['kind-eq'](match, pred, true)
|
||||
end, { force = true })
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
;; Support for folding in Ada
|
||||
;; za toggles folding a package, subprogram, if statement or loop
|
||||
|
||||
[
|
||||
(package_declaration)
|
||||
(generic_package_declaration)
|
||||
(package_body)
|
||||
(subprogram_body)
|
||||
(block_statement)
|
||||
(if_statement)
|
||||
(loop_statement)
|
||||
(gnatprep_declarative_if_statement)
|
||||
(gnatprep_if_statement)
|
||||
] @fold
|
||||
|
|
@ -1,190 +0,0 @@
|
|||
;; highlight queries.
|
||||
;; See the syntax at https://tree-sitter.github.io/tree-sitter/using-parsers#pattern-matching-with-queries
|
||||
;; See also https://github.com/nvim-treesitter/nvim-treesitter/blob/master/CONTRIBUTING.md#parser-configurations
|
||||
;; for a list of recommended @ tags, though not all of them have matching
|
||||
;; highlights in neovim.
|
||||
|
||||
[
|
||||
"abort"
|
||||
"abs"
|
||||
"abstract"
|
||||
"accept"
|
||||
"access"
|
||||
"all"
|
||||
"array"
|
||||
"at"
|
||||
"begin"
|
||||
"declare"
|
||||
"delay"
|
||||
"delta"
|
||||
"digits"
|
||||
"do"
|
||||
"end"
|
||||
"entry"
|
||||
"exit"
|
||||
"generic"
|
||||
"interface"
|
||||
"is"
|
||||
"limited"
|
||||
"null"
|
||||
"of"
|
||||
"others"
|
||||
"out"
|
||||
"pragma"
|
||||
"private"
|
||||
"range"
|
||||
"synchronized"
|
||||
"tagged"
|
||||
"task"
|
||||
"terminate"
|
||||
"until"
|
||||
"when"
|
||||
] @keyword
|
||||
[
|
||||
"aliased"
|
||||
"constant"
|
||||
"renames"
|
||||
] @storageclass
|
||||
[
|
||||
"mod"
|
||||
"new"
|
||||
"protected"
|
||||
"record"
|
||||
"subtype"
|
||||
"type"
|
||||
] @keyword.type
|
||||
[
|
||||
"with"
|
||||
"use"
|
||||
] @include
|
||||
[
|
||||
"body"
|
||||
"function"
|
||||
"overriding"
|
||||
"procedure"
|
||||
"package"
|
||||
"separate"
|
||||
] @keyword.function
|
||||
[
|
||||
"and"
|
||||
"in"
|
||||
"not"
|
||||
"or"
|
||||
"xor"
|
||||
] @keyword.operator
|
||||
[
|
||||
"while"
|
||||
"loop"
|
||||
"for"
|
||||
"parallel"
|
||||
"reverse"
|
||||
"some"
|
||||
] @repeat
|
||||
[
|
||||
"return"
|
||||
] @keyword.return
|
||||
[
|
||||
"case"
|
||||
"if"
|
||||
"else"
|
||||
"then"
|
||||
"elsif"
|
||||
"select"
|
||||
] @conditional
|
||||
[
|
||||
"exception"
|
||||
"raise"
|
||||
] @exception
|
||||
(comment) @comment @spell
|
||||
(string_literal) @string
|
||||
(character_literal) @string
|
||||
(numeric_literal) @number
|
||||
|
||||
;; Highlight the name of subprograms
|
||||
(procedure_specification name: (_) @function)
|
||||
(function_specification name: (_) @function)
|
||||
(package_declaration name: (_) @function)
|
||||
(package_body name: (_) @function)
|
||||
(generic_instantiation name: (_) @function)
|
||||
(entry_declaration . (identifier) @function)
|
||||
|
||||
;; Some keywords should take different categories depending on the context
|
||||
(use_clause "use" @include "type" @include)
|
||||
(with_clause "private" @include)
|
||||
(with_clause "limited" @include)
|
||||
(use_clause (_) @namespace)
|
||||
(with_clause (_) @namespace)
|
||||
|
||||
(loop_statement "end" @keyword.repeat)
|
||||
(if_statement "end" @conditional)
|
||||
(loop_parameter_specification "in" @keyword.repeat)
|
||||
(loop_parameter_specification "in" @keyword.repeat)
|
||||
(iterator_specification ["in" "of"] @keyword.repeat)
|
||||
(range_attribute_designator "range" @keyword.repeat)
|
||||
|
||||
(raise_statement "with" @exception)
|
||||
|
||||
(gnatprep_declarative_if_statement) @preproc
|
||||
(gnatprep_if_statement) @preproc
|
||||
(gnatprep_identifier) @preproc
|
||||
|
||||
(subprogram_declaration "is" @keyword.function "abstract" @keyword.function)
|
||||
(aspect_specification "with" @keyword.function)
|
||||
|
||||
(full_type_declaration "is" @keyword.type)
|
||||
(subtype_declaration "is" @keyword.type)
|
||||
(record_definition "end" @keyword.type)
|
||||
(full_type_declaration (_ "access" @keyword.type))
|
||||
(array_type_definition "array" @keyword.type "of" @keyword.type)
|
||||
(access_to_object_definition "access" @keyword.type)
|
||||
(access_to_object_definition "access" @keyword.type
|
||||
[
|
||||
(general_access_modifier "constant" @keyword.type)
|
||||
(general_access_modifier "all" @keyword.type)
|
||||
]
|
||||
)
|
||||
(range_constraint "range" @keyword.type)
|
||||
(signed_integer_type_definition "range" @keyword.type)
|
||||
(index_subtype_definition "range" @keyword.type)
|
||||
(record_type_definition "abstract" @keyword.type)
|
||||
(record_type_definition "tagged" @keyword.type)
|
||||
(record_type_definition "limited" @keyword.type)
|
||||
(record_type_definition (record_definition "null" @keyword.type))
|
||||
(private_type_declaration "is" @keyword.type "private" @keyword.type)
|
||||
(private_type_declaration "tagged" @keyword.type)
|
||||
(private_type_declaration "limited" @keyword.type)
|
||||
(task_type_declaration "task" @keyword.type "is" @keyword.type)
|
||||
|
||||
;; Gray the body of expression functions
|
||||
(expression_function_declaration
|
||||
(function_specification)
|
||||
"is"
|
||||
(_) @attribute
|
||||
)
|
||||
(subprogram_declaration (aspect_specification) @attribute)
|
||||
|
||||
;; Highlight full subprogram specifications
|
||||
;(subprogram_body
|
||||
; [
|
||||
; (procedure_specification)
|
||||
; (function_specification)
|
||||
; ] @function.spec
|
||||
;)
|
||||
|
||||
((comment) @comment.documentation
|
||||
. [
|
||||
(entry_declaration)
|
||||
(subprogram_declaration)
|
||||
(parameter_specification)
|
||||
])
|
||||
|
||||
(compilation_unit
|
||||
. (comment) @comment.documentation)
|
||||
|
||||
(component_list
|
||||
(component_declaration)
|
||||
. (comment) @comment.documentation)
|
||||
|
||||
(enumeration_type_definition
|
||||
(identifier)
|
||||
. (comment) @comment.documentation)
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
;; Better highlighting by referencing to the definition, for variable
|
||||
;; references. However, this is not yet supported by neovim
|
||||
;; See https://tree-sitter.github.io/tree-sitter/syntax-highlighting#local-variables
|
||||
|
||||
(compilation) @scope
|
||||
(package_declaration) @scope
|
||||
(package_body) @scope
|
||||
(subprogram_declaration) @scope
|
||||
(subprogram_body) @scope
|
||||
(block_statement) @scope
|
||||
|
||||
(with_clause (identifier) @definition.import)
|
||||
(procedure_specification name: (_) @definition.function)
|
||||
(function_specification name: (_) @definition.function)
|
||||
(package_declaration name: (_) @definition.var)
|
||||
(package_body name: (_) @definition.var)
|
||||
(generic_instantiation . name: (_) @definition.var)
|
||||
(component_declaration . (identifier) @definition.var)
|
||||
(exception_declaration . (identifier) @definition.var)
|
||||
(formal_object_declaration . (identifier) @definition.var)
|
||||
(object_declaration . (identifier) @definition.var)
|
||||
(parameter_specification . (identifier) @definition.var)
|
||||
(full_type_declaration . (identifier) @definition.type)
|
||||
(private_type_declaration . (identifier) @definition.type)
|
||||
(private_extension_declaration . (identifier) @definition.type)
|
||||
(incomplete_type_declaration . (identifier) @definition.type)
|
||||
(protected_type_declaration . (identifier) @definition.type)
|
||||
(formal_complete_type_declaration . (identifier) @definition.type)
|
||||
(formal_incomplete_type_declaration . (identifier) @definition.type)
|
||||
(task_type_declaration . (identifier) @definition.type)
|
||||
(subtype_declaration . (identifier) @definition.type)
|
||||
|
||||
(identifier) @reference
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
[
|
||||
(record)
|
||||
(module)
|
||||
] @fold
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
(identifier) @variable
|
||||
(pipe_sequence "|" @operator)
|
||||
(string) @string
|
||||
(number) @number
|
||||
(pipe_call
|
||||
name: (identifier) @function)
|
||||
(pipe_call
|
||||
arguments: (pipe_arguments
|
||||
(identifier) @parameter))
|
||||
|
||||
(structural_assignment
|
||||
operator: (identifier) @keyword)
|
||||
|
||||
(member_expression
|
||||
property: (identifier) @property)
|
||||
|
||||
(call_expression
|
||||
function: (identifier) @function)
|
||||
|
||||
(call_expression
|
||||
function: ((identifier) @function.builtin
|
||||
(#eq? @function.builtin "$any")))
|
||||
|
||||
[
|
||||
"let"
|
||||
"as"
|
||||
] @keyword
|
||||
|
||||
[
|
||||
"("
|
||||
")"
|
||||
"["
|
||||
"]"
|
||||
"{"
|
||||
"}"
|
||||
] @punctuation.bracket
|
||||
|
||||
[
|
||||
";"
|
||||
"."
|
||||
","
|
||||
"?."
|
||||
] @punctuation.delimiter
|
||||
|
||||
((identifier) @boolean
|
||||
(#any-of? @boolean "true" "false"))
|
||||
((identifier) @variable.builtin
|
||||
(#any-of? @variable.builtin "this" "\$event" "null"))
|
||||
|
||||
[
|
||||
"-"
|
||||
"&&"
|
||||
"+"
|
||||
"<"
|
||||
"<="
|
||||
"="
|
||||
"=="
|
||||
"==="
|
||||
"!="
|
||||
"!=="
|
||||
">"
|
||||
">="
|
||||
"*"
|
||||
"/"
|
||||
"||"
|
||||
"%"
|
||||
] @operator
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
[
|
||||
(class_body)
|
||||
(constructor_declaration)
|
||||
(argument_list)
|
||||
(annotation_argument_list)
|
||||
] @fold
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
; declarations
|
||||
|
||||
(class_declaration) @scope
|
||||
(method_declaration) @scope
|
||||
(constructor_declaration) @scope
|
||||
(enum_declaration) @scope
|
||||
(enhanced_for_statement) @scope
|
||||
|
||||
; if/else
|
||||
|
||||
(if_statement) @scope
|
||||
(if_statement
|
||||
consequence: (_) @scope) ; if body in case there are no braces
|
||||
(if_statement
|
||||
alternative: (_) @scope) ; else body in case there are no braces
|
||||
|
||||
; try/catch
|
||||
|
||||
(try_statement) @scope ; covers try+catch, individual try and catch are covered by (block)
|
||||
(catch_clause) @scope ; needed because `Exception` variable
|
||||
|
||||
; loops
|
||||
|
||||
(for_statement) @scope
|
||||
(for_statement ; "for" body in case there are no braces
|
||||
body: (_) @scope)
|
||||
(do_statement
|
||||
body: (_) @scope)
|
||||
(while_statement
|
||||
body: (_) @scope)
|
||||
|
||||
; Functions
|
||||
|
||||
(constructor_declaration) @scope
|
||||
(method_declaration) @scope
|
||||
|
||||
;; definitions
|
||||
|
||||
(enum_declaration
|
||||
name: (identifier) @definition.enum)
|
||||
|
||||
(method_declaration
|
||||
name: (identifier) @definition.method)
|
||||
|
||||
(local_variable_declaration
|
||||
declarator: (variable_declarator
|
||||
name: (identifier) @definition.var))
|
||||
|
||||
(enhanced_for_statement
|
||||
name: (identifier) @definition.var)
|
||||
|
||||
(formal_parameter
|
||||
name: (identifier) @definition.parameter)
|
||||
|
||||
(catch_formal_parameter
|
||||
name: (identifier) @definition.parameter)
|
||||
|
||||
(field_declaration
|
||||
declarator: (variable_declarator
|
||||
name: (identifier) @definition.field))
|
||||
|
||||
;; REFERENCES
|
||||
|
||||
(identifier) @reference
|
||||
|
||||
(type_identifier) @reference
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
; inherits: cpp
|
||||
|
||||
((identifier) @function.builtin
|
||||
(#any-of? @function.builtin
|
||||
; Digital I/O
|
||||
"digitalRead"
|
||||
"digitalWrite"
|
||||
"pinMode"
|
||||
; Analog I/O
|
||||
"analogRead"
|
||||
"analogReference"
|
||||
"analogWrite"
|
||||
; Zero, Due & MKR Family
|
||||
"analogReadResolution"
|
||||
"analogWriteResolution"
|
||||
; Advanced I/O
|
||||
"noTone"
|
||||
"pulseIn"
|
||||
"pulseInLong"
|
||||
"shiftIn"
|
||||
"shiftOut"
|
||||
"tone"
|
||||
; Time
|
||||
"delay"
|
||||
"delayMicroseconds"
|
||||
"micros"
|
||||
"millis"
|
||||
; Math
|
||||
"abs"
|
||||
"constrain"
|
||||
"map"
|
||||
"max"
|
||||
"min"
|
||||
"pow"
|
||||
"sq"
|
||||
"sqrt"
|
||||
; Trigonometry
|
||||
"cos"
|
||||
"sin"
|
||||
"tan"
|
||||
; Characters
|
||||
"isAlpha"
|
||||
"isAlphaNumeric"
|
||||
"isAscii"
|
||||
"isControl"
|
||||
"isDigit"
|
||||
"isGraph"
|
||||
"isHexadecimalDigit"
|
||||
"isLowerCase"
|
||||
"isPrintable"
|
||||
"isPunct"
|
||||
"isSpace"
|
||||
"isUpperCase"
|
||||
"isWhitespace"
|
||||
; Random Numbers
|
||||
"random"
|
||||
"randomSeed"
|
||||
; Bits and Bytes
|
||||
"bit"
|
||||
"bitClear"
|
||||
"bitRead"
|
||||
"bitSet"
|
||||
"bitWrite"
|
||||
"highByte"
|
||||
"lowByte"
|
||||
; External Interrupts
|
||||
"attachInterrupt"
|
||||
"detachInterrupt"
|
||||
; Interrupts
|
||||
"interrupts"
|
||||
"noInterrupts"
|
||||
))
|
||||
|
||||
((identifier) @type.builtin
|
||||
(#any-of? @type.builtin
|
||||
"Serial"
|
||||
"SPI"
|
||||
"Stream"
|
||||
"Wire"
|
||||
"Keyboard"
|
||||
"Mouse"
|
||||
"String"
|
||||
))
|
||||
|
||||
((identifier) @constant.builtin
|
||||
(#any-of? @constant.builtin
|
||||
"HIGH"
|
||||
"LOW"
|
||||
"INPUT"
|
||||
"OUTPUT"
|
||||
"INPUT_PULLUP"
|
||||
"LED_BUILTIN"
|
||||
))
|
||||
|
||||
(function_definition
|
||||
(function_declarator
|
||||
declarator: (identifier) @function.builtin)
|
||||
(#any-of? @function.builtin "loop" "setup"))
|
||||
|
||||
(call_expression
|
||||
function: (primitive_type) @function.builtin)
|
||||
|
||||
(call_expression
|
||||
function: (identifier) @constructor
|
||||
(#any-of? @constructor "SPISettings" "String"))
|
||||
|
||||
(declaration
|
||||
(type_identifier) @type.builtin
|
||||
(function_declarator
|
||||
declarator: (identifier) @constructor)
|
||||
(#eq? @type.builtin "SPISettings"))
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
((preproc_arg) @injection.content
|
||||
(#set! injection.language "arduino"))
|
||||
|
||||
((comment) @injection.content
|
||||
(#set! injection.language "comment"))
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
; inherits: html
|
||||
|
||||
[ "---" ] @punctuation.delimiter
|
||||
|
||||
[ "{" "}" ] @punctuation.special
|
||||
|
||||
; custom components get `@type` highlighting
|
||||
((start_tag (tag_name) @type)
|
||||
(#lua-match? @type "^[A-Z]"))
|
||||
((end_tag (tag_name) @type)
|
||||
(#lua-match? @type "^[A-Z]"))
|
||||
((erroneous_end_tag (erroneous_end_tag_name) @type)
|
||||
(#lua-match? @type "^[A-Z]"))
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
; inherits: html_tags
|
||||
|
||||
(frontmatter
|
||||
(raw_text) @injection.content
|
||||
(#set! injection.language "typescript"))
|
||||
|
||||
(interpolation
|
||||
(raw_text) @injection.content
|
||||
(#set! injection.language "tsx"))
|
||||
|
||||
(script_element
|
||||
(raw_text) @injection.content
|
||||
(#set! injection.language "typescript"))
|
||||
|
||||
(style_element
|
||||
(start_tag
|
||||
(attribute
|
||||
(attribute_name) @_lang_attr
|
||||
(quoted_attribute_value (attribute_value) @_lang_value)))
|
||||
(raw_text) @injection.content
|
||||
(#eq? @_lang_attr "lang")
|
||||
(#eq? @_lang_value "scss")
|
||||
(#set! injection.language "scss"))
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
((comment) @injection.content
|
||||
(#set! injection.language "comment"))
|
||||
|
|
@ -1,195 +0,0 @@
|
|||
; adapted from https://github.com/Beaglefoot/tree-sitter-awk
|
||||
|
||||
[
|
||||
(identifier)
|
||||
(field_ref)
|
||||
] @variable
|
||||
(field_ref (_) @variable)
|
||||
|
||||
; https://www.gnu.org/software/gawk/manual/html_node/Auto_002dset.html
|
||||
((identifier) @constant.builtin
|
||||
(#any-of? @constant.builtin
|
||||
"ARGC"
|
||||
"ARGV"
|
||||
"ARGIND"
|
||||
"ENVIRON"
|
||||
"ERRNO"
|
||||
"FILENAME"
|
||||
"FNR"
|
||||
"NF"
|
||||
"FUNCTAB"
|
||||
"NR"
|
||||
"PROCINFO"
|
||||
"RLENGTH"
|
||||
"RSTART"
|
||||
"RT"
|
||||
"SYMTAB"))
|
||||
|
||||
; https://www.gnu.org/software/gawk/manual/html_node/User_002dmodified.html
|
||||
((identifier) @variable.builtin
|
||||
(#any-of? @variable.builtin
|
||||
"BINMODE"
|
||||
"CONVFMT"
|
||||
"FIELDWIDTHS"
|
||||
"FPAT"
|
||||
"FS"
|
||||
"IGNORECASE"
|
||||
"LINT"
|
||||
"OFMT"
|
||||
"OFS"
|
||||
"ORS"
|
||||
"PREC"
|
||||
"ROUNDMODE"
|
||||
"RS"
|
||||
"SUBSEP"
|
||||
"TEXTDOMAIN"))
|
||||
|
||||
(number) @number
|
||||
|
||||
(string) @string
|
||||
(regex) @string.regex
|
||||
(escape_sequence) @string.escape
|
||||
|
||||
(comment) @comment @spell
|
||||
|
||||
((program . (comment) @preproc)
|
||||
(#lua-match? @preproc "^#!/"))
|
||||
|
||||
(ns_qualified_name (namespace) @namespace)
|
||||
(ns_qualified_name "::" @punctuation.delimiter)
|
||||
|
||||
(func_def name: (_ (identifier) @function) @function)
|
||||
(func_call name: (_ (identifier) @function) @function)
|
||||
|
||||
(func_def (param_list (identifier) @parameter))
|
||||
|
||||
[
|
||||
"print"
|
||||
"printf"
|
||||
"getline"
|
||||
] @function.builtin
|
||||
|
||||
[
|
||||
(delete_statement)
|
||||
(break_statement)
|
||||
(continue_statement)
|
||||
(next_statement)
|
||||
(nextfile_statement)
|
||||
] @keyword
|
||||
|
||||
[
|
||||
"func"
|
||||
"function"
|
||||
] @keyword.function
|
||||
|
||||
[
|
||||
"return"
|
||||
"exit"
|
||||
] @keyword.return
|
||||
|
||||
[
|
||||
"do"
|
||||
"while"
|
||||
"for"
|
||||
"in"
|
||||
] @repeat
|
||||
|
||||
[
|
||||
"if"
|
||||
"else"
|
||||
"switch"
|
||||
"case"
|
||||
"default"
|
||||
] @conditional
|
||||
|
||||
[
|
||||
"@include"
|
||||
"@load"
|
||||
] @include
|
||||
|
||||
"@namespace" @preproc
|
||||
|
||||
[
|
||||
"BEGIN"
|
||||
"END"
|
||||
"BEGINFILE"
|
||||
"ENDFILE"
|
||||
] @label
|
||||
|
||||
(binary_exp [
|
||||
"^"
|
||||
"**"
|
||||
"*"
|
||||
"/"
|
||||
"%"
|
||||
"+"
|
||||
"-"
|
||||
"<"
|
||||
">"
|
||||
"<="
|
||||
">="
|
||||
"=="
|
||||
"!="
|
||||
"~"
|
||||
"!~"
|
||||
"in"
|
||||
"&&"
|
||||
"||"
|
||||
] @operator)
|
||||
|
||||
(unary_exp [
|
||||
"!"
|
||||
"+"
|
||||
"-"
|
||||
] @operator)
|
||||
|
||||
(assignment_exp [
|
||||
"="
|
||||
"+="
|
||||
"-="
|
||||
"*="
|
||||
"/="
|
||||
"%="
|
||||
"^="
|
||||
] @operator)
|
||||
|
||||
(ternary_exp [
|
||||
"?"
|
||||
":"
|
||||
] @conditional.ternary)
|
||||
|
||||
(update_exp [
|
||||
"++"
|
||||
"--"
|
||||
] @operator)
|
||||
|
||||
(redirected_io_statement [
|
||||
">"
|
||||
">>"
|
||||
] @operator)
|
||||
|
||||
(piped_io_statement [
|
||||
"|"
|
||||
"|&"
|
||||
] @operator)
|
||||
|
||||
(piped_io_exp [
|
||||
"|"
|
||||
"|&"
|
||||
] @operator)
|
||||
|
||||
(field_ref "$" @punctuation.delimiter)
|
||||
|
||||
(regex "/" @punctuation.delimiter)
|
||||
(regex_constant "@" @punctuation.delimiter)
|
||||
|
||||
[ ";" "," ] @punctuation.delimiter
|
||||
|
||||
[
|
||||
"("
|
||||
")"
|
||||
"["
|
||||
"]"
|
||||
"{"
|
||||
"}"
|
||||
] @punctuation.bracket
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
((comment) @injection.content
|
||||
(#set! injection.language "comment"))
|
||||
|
||||
((regex) @injection.content
|
||||
(#set! injection.language "regex"))
|
||||
|
|
@ -1,186 +0,0 @@
|
|||
[
|
||||
"(" ")"
|
||||
"{" "}"
|
||||
"[" "]"
|
||||
"[[" "]]"
|
||||
"((" "))"
|
||||
] @punctuation.bracket
|
||||
|
||||
[
|
||||
";"
|
||||
";;"
|
||||
";&"
|
||||
";;&"
|
||||
"&"
|
||||
] @punctuation.delimiter
|
||||
|
||||
[
|
||||
">"
|
||||
">>"
|
||||
"<"
|
||||
"<<"
|
||||
"&&"
|
||||
"|"
|
||||
"|&"
|
||||
"||"
|
||||
"="
|
||||
"+="
|
||||
"=~"
|
||||
"=="
|
||||
"!="
|
||||
|
||||
"&>"
|
||||
"&>>"
|
||||
"<&"
|
||||
">&"
|
||||
">|"
|
||||
"<&-"
|
||||
">&-"
|
||||
|
||||
"<<-"
|
||||
"<<<"
|
||||
|
||||
".."
|
||||
] @operator
|
||||
|
||||
; Do *not* spell check strings since they typically have some sort of
|
||||
; interpolation in them, or, are typically used for things like filenames, URLs,
|
||||
; flags and file content.
|
||||
[
|
||||
(string)
|
||||
(raw_string)
|
||||
(ansi_c_string)
|
||||
(heredoc_body)
|
||||
] @string
|
||||
|
||||
[
|
||||
(heredoc_start)
|
||||
(heredoc_end)
|
||||
] @label
|
||||
|
||||
(variable_assignment (word) @string)
|
||||
(command argument: "$" @string) ; bare dollar
|
||||
|
||||
[
|
||||
"if"
|
||||
"then"
|
||||
"else"
|
||||
"elif"
|
||||
"fi"
|
||||
"case"
|
||||
"in"
|
||||
"esac"
|
||||
] @conditional
|
||||
|
||||
[
|
||||
"for"
|
||||
"do"
|
||||
"done"
|
||||
"select"
|
||||
"until"
|
||||
"while"
|
||||
] @repeat
|
||||
|
||||
[
|
||||
"declare"
|
||||
"typeset"
|
||||
"export"
|
||||
"readonly"
|
||||
"local"
|
||||
"unset"
|
||||
"unsetenv"
|
||||
] @keyword
|
||||
|
||||
"function" @keyword.function
|
||||
|
||||
(special_variable_name) @constant
|
||||
|
||||
; trap -l
|
||||
((word) @constant.builtin
|
||||
(#match? @constant.builtin "^SIG(HUP|INT|QUIT|ILL|TRAP|ABRT|BUS|FPE|KILL|USR[12]|SEGV|PIPE|ALRM|TERM|STKFLT|CHLD|CONT|STOP|TSTP|TT(IN|OU)|URG|XCPU|XFSZ|VTALRM|PROF|WINCH|IO|PWR|SYS|RTMIN([+]([1-9]|1[0-5]))?|RTMAX(-([1-9]|1[0-4]))?)$"))
|
||||
|
||||
((word) @boolean
|
||||
(#any-of? @boolean "true" "false"))
|
||||
|
||||
(comment) @comment @spell
|
||||
|
||||
(test_operator) @operator
|
||||
|
||||
(command_substitution "$(" @punctuation.bracket)
|
||||
(process_substitution "<(" @punctuation.bracket)
|
||||
|
||||
(arithmetic_expansion
|
||||
[ "$((" "((" ] @punctuation.special
|
||||
"))" @punctuation.special)
|
||||
|
||||
(arithmetic_expansion "," @punctuation.delimiter)
|
||||
|
||||
(ternary_expression [ "?" ":" ] @conditional.ternary)
|
||||
|
||||
(binary_expression operator: _ @operator)
|
||||
(unary_expression operator: _ @operator)
|
||||
(postfix_expression operator: _ @operator)
|
||||
|
||||
(function_definition
|
||||
name: (word) @function)
|
||||
|
||||
(command_name (word) @function.call)
|
||||
|
||||
((command_name (word) @function.builtin)
|
||||
(#any-of? @function.builtin
|
||||
"alias" "bg" "bind" "break" "builtin" "caller" "cd"
|
||||
"command" "compgen" "complete" "compopt" "continue"
|
||||
"coproc" "dirs" "disown" "echo" "enable" "eval"
|
||||
"exec" "exit" "fc" "fg" "getopts" "hash" "help"
|
||||
"history" "jobs" "kill" "let" "logout" "mapfile"
|
||||
"popd" "printf" "pushd" "pwd" "read" "readarray"
|
||||
"return" "set" "shift" "shopt" "source" "suspend"
|
||||
"test" "time" "times" "trap" "type" "typeset"
|
||||
"ulimit" "umask" "unalias" "wait"))
|
||||
|
||||
(command
|
||||
argument: [
|
||||
(word) @parameter
|
||||
(concatenation (word) @parameter)
|
||||
])
|
||||
|
||||
(number) @number
|
||||
((word) @number
|
||||
(#lua-match? @number "^[0-9]+$"))
|
||||
|
||||
(file_redirect
|
||||
destination: (word) @parameter)
|
||||
|
||||
(file_descriptor) @operator
|
||||
|
||||
(simple_expansion
|
||||
"$" @punctuation.special) @none
|
||||
(expansion
|
||||
"${" @punctuation.special
|
||||
"}" @punctuation.special) @none
|
||||
|
||||
(expansion operator: _ @punctuation.special)
|
||||
(expansion "@" . operator: _ @character.special)
|
||||
|
||||
((expansion
|
||||
(subscript
|
||||
index: (word) @character.special))
|
||||
(#any-of? @character.special "@" "*"))
|
||||
|
||||
"``" @punctuation.special
|
||||
|
||||
(variable_name) @variable
|
||||
|
||||
((variable_name) @constant
|
||||
(#lua-match? @constant "^[A-Z][A-Z_0-9]*$"))
|
||||
|
||||
(case_item
|
||||
value: (word) @parameter)
|
||||
|
||||
[
|
||||
(regex)
|
||||
(extglob_pattern)
|
||||
] @string.regex
|
||||
|
||||
((program . (comment) @preproc)
|
||||
(#lua-match? @preproc "^#!/"))
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
((comment) @injection.content
|
||||
(#set! injection.language "comment"))
|
||||
|
||||
((regex) @injection.content
|
||||
(#set! injection.language "regex"))
|
||||
|
||||
((heredoc_redirect
|
||||
(heredoc_body) @injection.content
|
||||
(heredoc_end) @injection.language)
|
||||
(#downcase! @injection.language))
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
; Scopes
|
||||
(function_definition) @scope
|
||||
|
||||
; Definitions
|
||||
(variable_assignment
|
||||
name: (variable_name) @definition.var)
|
||||
|
||||
(function_definition
|
||||
name: (word) @definition.function)
|
||||
|
||||
; References
|
||||
(variable_name) @reference
|
||||
(word) @reference
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
;; Variables
|
||||
|
||||
(list (symbol) @variable)
|
||||
|
||||
(cons (symbol) @variable)
|
||||
|
||||
(scope (symbol) @variable)
|
||||
|
||||
(symbind (symbol) @variable)
|
||||
|
||||
;; Constants
|
||||
|
||||
((symbol) @constant
|
||||
(#lua-match? @constant "^_*[A-Z][A-Z0-9_]*$"))
|
||||
|
||||
;; Functions
|
||||
|
||||
(list
|
||||
. (symbol) @function)
|
||||
|
||||
;; Namespaces
|
||||
|
||||
(symbind
|
||||
(symbol) @namespace
|
||||
. (keyword))
|
||||
|
||||
;; Includes
|
||||
|
||||
((symbol) @include
|
||||
(#any-of? @include "use" "import" "load"))
|
||||
|
||||
;; Keywords
|
||||
|
||||
((symbol) @keyword
|
||||
(#any-of? @keyword "do" "doc"))
|
||||
|
||||
;; Special Functions
|
||||
|
||||
; Keywords construct a symbol
|
||||
|
||||
(keyword) @constructor
|
||||
|
||||
((list
|
||||
. (symbol) @keyword.function
|
||||
. (symbol) @function
|
||||
(symbol)? @parameter)
|
||||
(#any-of? @keyword.function "def" "defop" "defn" "fn"))
|
||||
|
||||
((cons
|
||||
. (symbol) @keyword.function
|
||||
. (symbol) @function
|
||||
(symbol)? @parameter)
|
||||
(#any-of? @keyword.function "def" "defop" "defn" "fn"))
|
||||
|
||||
((symbol) @function.builtin
|
||||
(#any-of? @function.builtin "dump" "mkfs" "json" "log" "error" "now" "cons" "wrap" "unwrap" "eval" "make-scope" "bind" "meta" "with-meta" "null?" "ignore?" "boolean?" "number?" "string?" "symbol?" "scope?" "sink?" "source?" "list?" "pair?" "applicative?" "operative?" "combiner?" "path?" "empty?" "thunk?" "+" "*" "quot" "-" "max" "min" "=" ">" ">=" "<" "<=" "list->source" "across" "emit" "next" "reduce-kv" "assoc" "symbol->string" "string->symbol" "str" "substring" "trim" "scope->list" "string->fs-path" "string->cmd-path" "string->dir" "subpath" "path-name" "path-stem" "with-image" "with-dir" "with-args" "with-cmd" "with-stdin" "with-env" "with-insecure" "with-label" "with-port" "with-tls" "with-mount" "thunk-cmd" "thunk-args" "resolve" "start" "addr" "wait" "read" "cache-dir" "binds?" "recall-memo" "store-memo" "mask" "list" "list*" "first" "rest" "length" "second" "third" "map" "map-pairs" "foldr" "foldl" "append" "filter" "conj" "list->scope" "merge" "apply" "id" "always" "vals" "keys" "memo" "succeeds?" "run" "last" "take" "take-all" "insecure!" "from" "cd" "wrap-cmd" "mkfile" "path-base" "not"))
|
||||
|
||||
((symbol) @function.macro
|
||||
(#any-of? @function.macro "op" "current-scope" "quote" "let" "provide" "module" "or" "and" "curryfn" "for" "$" "linux"))
|
||||
|
||||
;; Conditionals
|
||||
|
||||
((symbol) @conditional
|
||||
(#any-of? @conditional "if" "case" "cond" "when"))
|
||||
|
||||
;; Repeats
|
||||
|
||||
((symbol) @repeat
|
||||
(#any-of? @repeat "each"))
|
||||
|
||||
;; Operators
|
||||
|
||||
((symbol) @operator (#any-of? @operator "&" "*" "+" "-" "<" "<=" "=" ">" ">="))
|
||||
|
||||
;; Punctuation
|
||||
|
||||
[ "(" ")" ] @punctuation.bracket
|
||||
|
||||
[ "{" "}" ] @punctuation.bracket
|
||||
|
||||
[ "[" "]" ] @punctuation.bracket
|
||||
|
||||
((symbol) @punctuation.delimiter
|
||||
(#eq? @punctuation.delimiter "->"))
|
||||
|
||||
;; Literals
|
||||
|
||||
(string) @string
|
||||
|
||||
(escape_sequence) @string.escape
|
||||
|
||||
(path) @text.uri @string.special
|
||||
|
||||
(number) @number
|
||||
|
||||
(boolean) @boolean
|
||||
|
||||
[
|
||||
(ignore)
|
||||
(null)
|
||||
] @constant.builtin
|
||||
|
||||
[
|
||||
"^"
|
||||
] @character.special
|
||||
|
||||
;; Comments
|
||||
|
||||
(comment) @comment @spell
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
((comment) @injection.content
|
||||
(#set! injection.language "comment"))
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
; Scopes
|
||||
|
||||
[
|
||||
(list)
|
||||
(scope)
|
||||
(cons)
|
||||
] @scope
|
||||
|
||||
; References
|
||||
|
||||
(symbol) @reference
|
||||
|
||||
; Definitions
|
||||
|
||||
((list
|
||||
. (symbol) @_fnkw
|
||||
. (symbol) @definition.function
|
||||
(symbol)? @definition.parameter)
|
||||
(#any-of? @_fnkw "def" "defop" "defn" "fn"))
|
||||
|
||||
((cons
|
||||
. (symbol) @_fnkw
|
||||
. (symbol) @definition.function
|
||||
(symbol)? @definition.parameter)
|
||||
(#any-of? @_fnkw "def" "defop" "defn" "fn"))
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
[
|
||||
(transaction)
|
||||
(section)
|
||||
] @fold
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
[
|
||||
(entry)
|
||||
] @fold
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
([
|
||||
(comment)
|
||||
(diagnostic_comment)
|
||||
] @injection.content
|
||||
(#set! injection.language "comment"))
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
; Scopes
|
||||
|
||||
[
|
||||
(infrastructure)
|
||||
(call_expression)
|
||||
|
||||
(lambda_expression)
|
||||
(subscript_expression)
|
||||
|
||||
(if_statement)
|
||||
(for_statement)
|
||||
|
||||
(array)
|
||||
(object)
|
||||
(interpolation)
|
||||
] @scope
|
||||
|
||||
; References
|
||||
|
||||
(property_identifier) @reference
|
||||
|
||||
(call_expression
|
||||
(identifier) @reference)
|
||||
|
||||
(object_property
|
||||
(_)
|
||||
":"
|
||||
(identifier) @reference)
|
||||
|
||||
(resource_expression
|
||||
(identifier) @reference)
|
||||
|
||||
; Definitions
|
||||
|
||||
(type) @definition.associated
|
||||
|
||||
(object_property
|
||||
(identifier) @definition.field
|
||||
(_))
|
||||
|
||||
(object_property
|
||||
(compatible_identifier) @definition.field
|
||||
(_))
|
||||
|
||||
(import_name) @definition.import
|
||||
|
||||
(module_declaration
|
||||
(identifier) @definition.namespace)
|
||||
|
||||
(parameter_declaration
|
||||
(identifier) @definition.parameter
|
||||
(_))
|
||||
|
||||
(type_declaration
|
||||
(identifier) @definition.type
|
||||
(_))
|
||||
|
||||
(variable_declaration
|
||||
(identifier) @definition.var
|
||||
(_))
|
||||
|
||||
(metadata_declaration
|
||||
(identifier) @definition.var
|
||||
(_))
|
||||
|
||||
(output_declaration
|
||||
(identifier) @definition.var
|
||||
(_))
|
||||
|
||||
(for_statement
|
||||
"for"
|
||||
(for_loop_parameters
|
||||
(loop_variable) @definition.var
|
||||
(loop_enumerator) @definition.var))
|
||||
|
|
@ -1,358 +0,0 @@
|
|||
; Includes
|
||||
|
||||
[
|
||||
"inherit"
|
||||
"include"
|
||||
"require"
|
||||
"export"
|
||||
"import"
|
||||
] @include
|
||||
|
||||
; Keywords
|
||||
|
||||
[
|
||||
"unset"
|
||||
"EXPORT_FUNCTIONS"
|
||||
"python"
|
||||
|
||||
"assert"
|
||||
"exec"
|
||||
"global"
|
||||
"nonlocal"
|
||||
"pass"
|
||||
"print"
|
||||
"with"
|
||||
"as"
|
||||
] @keyword
|
||||
|
||||
[
|
||||
"async"
|
||||
"await"
|
||||
] @keyword.coroutine
|
||||
|
||||
[
|
||||
"return"
|
||||
"yield"
|
||||
] @keyword.return
|
||||
(yield "from" @keyword.return)
|
||||
|
||||
(future_import_statement
|
||||
"from" @include
|
||||
"__future__" @constant.builtin)
|
||||
(import_from_statement "from" @include)
|
||||
"import" @include
|
||||
|
||||
(aliased_import "as" @include)
|
||||
|
||||
["if" "elif" "else"] @conditional
|
||||
|
||||
["for" "while" "break" "continue"] @repeat
|
||||
|
||||
[
|
||||
"try"
|
||||
"except"
|
||||
"except*"
|
||||
"raise"
|
||||
"finally"
|
||||
] @exception
|
||||
|
||||
(raise_statement "from" @exception)
|
||||
|
||||
(try_statement
|
||||
(else_clause
|
||||
"else" @exception))
|
||||
|
||||
[
|
||||
"addtask"
|
||||
"deltask"
|
||||
"addhandler"
|
||||
"def"
|
||||
"lambda"
|
||||
] @keyword.function
|
||||
|
||||
[
|
||||
"before"
|
||||
"after"
|
||||
] @storageclass
|
||||
|
||||
[
|
||||
"append"
|
||||
"prepend"
|
||||
"remove"
|
||||
] @type.qualifier
|
||||
|
||||
; Variables
|
||||
|
||||
[
|
||||
(identifier)
|
||||
(python_identifier)
|
||||
] @variable
|
||||
|
||||
[
|
||||
"noexec"
|
||||
"INHERIT"
|
||||
"OVERRIDES"
|
||||
"$BB_ENV_PASSTHROUGH"
|
||||
"$BB_ENV_PASSTHROUGH_ADDITIONS"
|
||||
] @variable.builtin
|
||||
|
||||
; Reset highlighting in f-string interpolations
|
||||
(interpolation) @none
|
||||
|
||||
;; Identifier naming conventions
|
||||
((python_identifier) @type
|
||||
(#lua-match? @type "^[A-Z].*[a-z]"))
|
||||
([(identifier) (python_identifier)] @constant
|
||||
(#lua-match? @constant "^[A-Z][A-Z_0-9]*$"))
|
||||
|
||||
((python_identifier) @constant.builtin
|
||||
(#lua-match? @constant.builtin "^__[a-zA-Z0-9_]*__$"))
|
||||
|
||||
((python_identifier) @constant.builtin
|
||||
(#any-of? @constant.builtin
|
||||
;; https://docs.python.org/3/library/constants.html
|
||||
"NotImplemented"
|
||||
"Ellipsis"
|
||||
"quit"
|
||||
"exit"
|
||||
"copyright"
|
||||
"credits"
|
||||
"license"))
|
||||
|
||||
((assignment
|
||||
left: (python_identifier) @type.definition
|
||||
(type (python_identifier) @_annotation))
|
||||
(#eq? @_annotation "TypeAlias"))
|
||||
|
||||
((assignment
|
||||
left: (python_identifier) @type.definition
|
||||
right: (call
|
||||
function: (python_identifier) @_func))
|
||||
(#any-of? @_func "TypeVar" "NewType"))
|
||||
|
||||
; Fields
|
||||
|
||||
(flag) @field
|
||||
|
||||
((attribute
|
||||
attribute: (python_identifier) @field)
|
||||
(#lua-match? @field "^[%l_].*$"))
|
||||
|
||||
; Functions
|
||||
|
||||
(call
|
||||
function: (python_identifier) @function.call)
|
||||
|
||||
(call
|
||||
function: (attribute
|
||||
attribute: (python_identifier) @method.call))
|
||||
|
||||
((call
|
||||
function: (python_identifier) @constructor)
|
||||
(#lua-match? @constructor "^%u"))
|
||||
|
||||
((call
|
||||
function: (attribute
|
||||
attribute: (python_identifier) @constructor))
|
||||
(#lua-match? @constructor "^%u"))
|
||||
|
||||
((call
|
||||
function: (python_identifier) @function.builtin)
|
||||
(#any-of? @function.builtin
|
||||
"abs" "all" "any" "ascii" "bin" "bool" "breakpoint" "bytearray" "bytes" "callable" "chr" "classmethod"
|
||||
"compile" "complex" "delattr" "dict" "dir" "divmod" "enumerate" "eval" "exec" "filter" "float" "format"
|
||||
"frozenset" "getattr" "globals" "hasattr" "hash" "help" "hex" "id" "input" "int" "isinstance" "issubclass"
|
||||
"iter" "len" "list" "locals" "map" "max" "memoryview" "min" "next" "object" "oct" "open" "ord" "pow"
|
||||
"print" "property" "range" "repr" "reversed" "round" "set" "setattr" "slice" "sorted" "staticmethod" "str"
|
||||
"sum" "super" "tuple" "type" "vars" "zip" "__import__"))
|
||||
|
||||
(python_function_definition
|
||||
name: (python_identifier) @function)
|
||||
|
||||
(type (python_identifier) @type)
|
||||
(type
|
||||
(subscript
|
||||
(python_identifier) @type)) ; type subscript: Tuple[int]
|
||||
|
||||
((call
|
||||
function: (python_identifier) @_isinstance
|
||||
arguments: (argument_list
|
||||
(_)
|
||||
(python_identifier) @type))
|
||||
(#eq? @_isinstance "isinstance"))
|
||||
|
||||
(anonymous_python_function (identifier) @function)
|
||||
|
||||
(function_definition (identifier) @function)
|
||||
|
||||
(addtask_statement (identifier) @function)
|
||||
|
||||
(deltask_statement (identifier) @function)
|
||||
|
||||
(export_functions_statement (identifier) @function)
|
||||
|
||||
(addhandler_statement (identifier) @function)
|
||||
|
||||
(python_function_definition
|
||||
body:
|
||||
(block
|
||||
. (expression_statement (python_string) @string.documentation @spell)))
|
||||
|
||||
; Namespace
|
||||
|
||||
(inherit_path) @namespace
|
||||
|
||||
;; Normal parameters
|
||||
(parameters
|
||||
(python_identifier) @parameter)
|
||||
;; Lambda parameters
|
||||
(lambda_parameters
|
||||
(python_identifier) @parameter)
|
||||
(lambda_parameters
|
||||
(tuple_pattern
|
||||
(python_identifier) @parameter))
|
||||
; Default parameters
|
||||
(keyword_argument
|
||||
name: (python_identifier) @parameter)
|
||||
; Naming parameters on call-site
|
||||
(default_parameter
|
||||
name: (python_identifier) @parameter)
|
||||
(typed_parameter
|
||||
(python_identifier) @parameter)
|
||||
(typed_default_parameter
|
||||
(python_identifier) @parameter)
|
||||
; Variadic parameters *args, **kwargs
|
||||
(parameters
|
||||
(list_splat_pattern ; *args
|
||||
(python_identifier) @parameter))
|
||||
(parameters
|
||||
(dictionary_splat_pattern ; **kwargs
|
||||
(python_identifier) @parameter))
|
||||
|
||||
;; Literals
|
||||
|
||||
(none) @constant.builtin
|
||||
[(true) (false)] @boolean
|
||||
((python_identifier) @variable.builtin
|
||||
(#eq? @variable.builtin "self"))
|
||||
((python_identifier) @variable.builtin
|
||||
(#eq? @variable.builtin "cls"))
|
||||
|
||||
(integer) @number
|
||||
(float) @float
|
||||
|
||||
; Operators
|
||||
|
||||
[
|
||||
"?="
|
||||
"??="
|
||||
":="
|
||||
"=+"
|
||||
".="
|
||||
"=."
|
||||
"-"
|
||||
"-="
|
||||
":="
|
||||
"!="
|
||||
"*"
|
||||
"**"
|
||||
"**="
|
||||
"*="
|
||||
"/"
|
||||
"//"
|
||||
"//="
|
||||
"/="
|
||||
"&"
|
||||
"&="
|
||||
"%"
|
||||
"%="
|
||||
"^"
|
||||
"^="
|
||||
"+"
|
||||
"+="
|
||||
"<"
|
||||
"<<"
|
||||
"<<="
|
||||
"<="
|
||||
"<>"
|
||||
"="
|
||||
"=="
|
||||
">"
|
||||
">="
|
||||
">>"
|
||||
">>="
|
||||
"@"
|
||||
"@="
|
||||
"|"
|
||||
"|="
|
||||
"~"
|
||||
"->"
|
||||
] @operator
|
||||
|
||||
[
|
||||
"and"
|
||||
"in"
|
||||
"is"
|
||||
"not"
|
||||
"or"
|
||||
"is not"
|
||||
"not in"
|
||||
|
||||
"del"
|
||||
] @keyword.operator
|
||||
|
||||
; Literals
|
||||
|
||||
[
|
||||
(string)
|
||||
(python_string)
|
||||
"\""
|
||||
] @string
|
||||
|
||||
(include_path) @string.special
|
||||
|
||||
[
|
||||
(escape_sequence)
|
||||
(escape_interpolation)
|
||||
] @string.escape
|
||||
|
||||
; Punctuation
|
||||
|
||||
[ "(" ")" "{" "}" "[" "]" ] @punctuation.bracket
|
||||
|
||||
[
|
||||
":"
|
||||
"->"
|
||||
";"
|
||||
"."
|
||||
","
|
||||
(ellipsis)
|
||||
] @punctuation.delimiter
|
||||
|
||||
(variable_expansion [ "${" "}" ] @punctuation.special)
|
||||
(inline_python [ "${@" "}" ] @punctuation.special)
|
||||
(interpolation
|
||||
"{" @punctuation.special
|
||||
"}" @punctuation.special)
|
||||
|
||||
(type_conversion) @function.macro
|
||||
|
||||
([(identifier) (python_identifier)] @type.builtin
|
||||
(#any-of? @type.builtin
|
||||
;; https://docs.python.org/3/library/exceptions.html
|
||||
"BaseException" "Exception" "ArithmeticError" "BufferError" "LookupError" "AssertionError" "AttributeError"
|
||||
"EOFError" "FloatingPointError" "GeneratorExit" "ImportError" "ModuleNotFoundError" "IndexError" "KeyError"
|
||||
"KeyboardInterrupt" "MemoryError" "NameError" "NotImplementedError" "OSError" "OverflowError" "RecursionError"
|
||||
"ReferenceError" "RuntimeError" "StopIteration" "StopAsyncIteration" "SyntaxError" "IndentationError" "TabError"
|
||||
"SystemError" "SystemExit" "TypeError" "UnboundLocalError" "UnicodeError" "UnicodeEncodeError" "UnicodeDecodeError"
|
||||
"UnicodeTranslateError" "ValueError" "ZeroDivisionError" "EnvironmentError" "IOError" "WindowsError"
|
||||
"BlockingIOError" "ChildProcessError" "ConnectionError" "BrokenPipeError" "ConnectionAbortedError"
|
||||
"ConnectionRefusedError" "ConnectionResetError" "FileExistsError" "FileNotFoundError" "InterruptedError"
|
||||
"IsADirectoryError" "NotADirectoryError" "PermissionError" "ProcessLookupError" "TimeoutError" "Warning"
|
||||
"UserWarning" "DeprecationWarning" "PendingDeprecationWarning" "SyntaxWarning" "RuntimeWarning"
|
||||
"FutureWarning" "ImportWarning" "UnicodeWarning" "BytesWarning" "ResourceWarning"
|
||||
;; https://docs.python.org/3/library/stdtypes.html
|
||||
"bool" "int" "float" "complex" "list" "tuple" "range" "str"
|
||||
"bytes" "bytearray" "memoryview" "set" "frozenset" "dict" "type" "object"))
|
||||
|
||||
(comment) @comment @spell
|
||||
|
|
@ -1,127 +0,0 @@
|
|||
[
|
||||
(import_from_statement)
|
||||
|
||||
(parenthesized_expression)
|
||||
(generator_expression)
|
||||
(list_comprehension)
|
||||
(set_comprehension)
|
||||
(dictionary_comprehension)
|
||||
|
||||
(tuple_pattern)
|
||||
(list_pattern)
|
||||
(binary_operator)
|
||||
|
||||
(lambda)
|
||||
|
||||
(concatenated_string)
|
||||
] @indent.begin
|
||||
|
||||
((list) @indent.align
|
||||
(#set! indent.open_delimiter "[")
|
||||
(#set! indent.close_delimiter "]")
|
||||
)
|
||||
((dictionary) @indent.align
|
||||
(#set! indent.open_delimiter "{")
|
||||
(#set! indent.close_delimiter "}")
|
||||
)
|
||||
((set) @indent.align
|
||||
(#set! indent.open_delimiter "{")
|
||||
(#set! indent.close_delimiter "}")
|
||||
)
|
||||
|
||||
((for_statement) @indent.begin
|
||||
(#set! indent.immediate 1))
|
||||
((if_statement) @indent.begin
|
||||
(#set! indent.immediate 1))
|
||||
((while_statement) @indent.begin
|
||||
(#set! indent.immediate 1))
|
||||
((try_statement) @indent.begin
|
||||
(#set! indent.immediate 1))
|
||||
(ERROR "try" ":" @indent.begin (#set! indent.immediate 1))
|
||||
((python_function_definition) @indent.begin
|
||||
(#set! indent.immediate 1))
|
||||
(function_definition) @indent.begin
|
||||
(anonymous_python_function) @indent.begin
|
||||
((with_statement) @indent.begin
|
||||
(#set! indent.immediate 1))
|
||||
|
||||
(if_statement
|
||||
condition: (parenthesized_expression) @indent.align
|
||||
(#set! indent.open_delimiter "(")
|
||||
(#set! indent.close_delimiter ")")
|
||||
(#set! indent.avoid_last_matching_next 1))
|
||||
(while_statement
|
||||
condition: (parenthesized_expression) @indent.align
|
||||
(#set! indent.open_delimiter "(")
|
||||
(#set! indent.close_delimiter ")")
|
||||
(#set! indent.avoid_last_matching_next 1))
|
||||
|
||||
(ERROR "(" @indent.align (#set! indent.open_delimiter "(") (#set! indent.close_delimiter ")") . (_))
|
||||
((argument_list) @indent.align
|
||||
(#set! indent.open_delimiter "(")
|
||||
(#set! indent.close_delimiter ")"))
|
||||
((parameters) @indent.align
|
||||
(#set! indent.open_delimiter "(")
|
||||
(#set! indent.close_delimiter ")")
|
||||
(#set! indent.avoid_last_matching_next 1))
|
||||
((tuple) @indent.align
|
||||
(#set! indent.open_delimiter "(")
|
||||
(#set! indent.close_delimiter ")"))
|
||||
|
||||
(ERROR "[" @indent.align (#set! indent.open_delimiter "[") (#set! indent.close_delimiter "]") . (_))
|
||||
|
||||
(ERROR "{" @indent.align (#set! indent.open_delimiter "{") (#set! indent.close_delimiter "}") . (_))
|
||||
|
||||
[
|
||||
(break_statement)
|
||||
(continue_statement)
|
||||
] @indent.dedent
|
||||
|
||||
(ERROR
|
||||
(_) @indent.branch ":" .
|
||||
(#lua-match? @indent.branch "^else"))
|
||||
|
||||
(ERROR
|
||||
(_) @indent.branch @indent.dedent ":" .
|
||||
(#lua-match? @indent.branch "^elif"))
|
||||
|
||||
(parenthesized_expression ")" @indent.end)
|
||||
(generator_expression ")" @indent.end)
|
||||
(list_comprehension "]" @indent.end)
|
||||
(set_comprehension "}" @indent.end)
|
||||
(dictionary_comprehension "}" @indent.end)
|
||||
|
||||
(tuple_pattern ")" @indent.end)
|
||||
(list_pattern "]" @indent.end)
|
||||
|
||||
(function_definition "}" @indent.end)
|
||||
(anonymous_python_function "}" @indent.end)
|
||||
|
||||
(return_statement
|
||||
[
|
||||
(_) @indent.end
|
||||
(_
|
||||
[
|
||||
(_)
|
||||
")"
|
||||
"}"
|
||||
"]"
|
||||
] @indent.end .)
|
||||
(attribute
|
||||
attribute: (_) @indent.end)
|
||||
(call
|
||||
arguments: (_ ")" @indent.end))
|
||||
"return" @indent.end
|
||||
] .)
|
||||
|
||||
[
|
||||
")"
|
||||
"]"
|
||||
"}"
|
||||
(elif_clause)
|
||||
(else_clause)
|
||||
(except_clause)
|
||||
(finally_clause)
|
||||
] @indent.branch
|
||||
|
||||
(string) @indent.auto
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
; References
|
||||
[
|
||||
(python_identifier)
|
||||
(identifier)
|
||||
] @reference
|
||||
|
||||
; Imports
|
||||
(aliased_import
|
||||
alias: (python_identifier) @definition.import)
|
||||
(import_statement
|
||||
name: (dotted_name ((python_identifier) @definition.import)))
|
||||
(import_from_statement
|
||||
name: (dotted_name ((python_identifier) @definition.import)))
|
||||
|
||||
; Function with parameters, defines parameters
|
||||
(parameters
|
||||
(python_identifier) @definition.parameter)
|
||||
|
||||
(default_parameter
|
||||
(python_identifier) @definition.parameter)
|
||||
|
||||
(typed_parameter
|
||||
(python_identifier) @definition.parameter)
|
||||
|
||||
(typed_default_parameter
|
||||
(python_identifier) @definition.parameter)
|
||||
|
||||
; *args parameter
|
||||
(parameters
|
||||
(list_splat_pattern
|
||||
(python_identifier) @definition.parameter))
|
||||
|
||||
; **kwargs parameter
|
||||
(parameters
|
||||
(dictionary_splat_pattern
|
||||
(python_identifier) @definition.parameter))
|
||||
|
||||
; Function defines function and scope
|
||||
((python_function_definition
|
||||
name: (python_identifier) @definition.function) @scope
|
||||
(#set! definition.function.scope "parent"))
|
||||
|
||||
(function_definition (identifier) @definition.function)
|
||||
|
||||
(anonymous_python_function (identifier) @definition.function)
|
||||
|
||||
;;; Loops
|
||||
; not a scope!
|
||||
(for_statement
|
||||
left: (pattern_list
|
||||
(python_identifier) @definition.var))
|
||||
(for_statement
|
||||
left: (tuple_pattern
|
||||
(python_identifier) @definition.var))
|
||||
(for_statement
|
||||
left: (python_identifier) @definition.var)
|
||||
|
||||
; not a scope!
|
||||
;(while_statement) @scope
|
||||
|
||||
; for in list comprehension
|
||||
(for_in_clause
|
||||
left: (python_identifier) @definition.var)
|
||||
(for_in_clause
|
||||
left: (tuple_pattern
|
||||
(python_identifier) @definition.var))
|
||||
(for_in_clause
|
||||
left: (pattern_list
|
||||
(python_identifier) @definition.var))
|
||||
|
||||
(dictionary_comprehension) @scope
|
||||
(list_comprehension) @scope
|
||||
(set_comprehension) @scope
|
||||
|
||||
;;; Assignments
|
||||
|
||||
(assignment
|
||||
left: (python_identifier) @definition.var)
|
||||
|
||||
(assignment
|
||||
left: (pattern_list
|
||||
(python_identifier) @definition.var))
|
||||
(assignment
|
||||
left: (tuple_pattern
|
||||
(python_identifier) @definition.var))
|
||||
|
||||
(assignment
|
||||
left: (attribute
|
||||
(python_identifier)
|
||||
(python_identifier) @definition.field))
|
||||
|
||||
(variable_assignment (identifier) operator: [ "=" "?=" "??=" ":=" ] @definition.var)
|
||||
|
||||
; Walrus operator x := 1
|
||||
(named_expression
|
||||
(python_identifier) @definition.var)
|
||||
|
||||
(as_pattern
|
||||
alias: (as_pattern_target) @definition.var)
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
(object_id) @variable
|
||||
|
||||
(string) @string
|
||||
(escape_sequence) @string.escape
|
||||
|
||||
(comment) @comment @spell
|
||||
|
||||
(constant) @constant.builtin
|
||||
|
||||
(boolean) @boolean
|
||||
|
||||
(using) @include
|
||||
|
||||
(template) @keyword
|
||||
|
||||
(decorator) @attribute
|
||||
|
||||
(property_definition (property_name) @property)
|
||||
|
||||
(object) @type
|
||||
|
||||
(signal_binding (signal_name) @function.builtin)
|
||||
(signal_binding (function (identifier)) @function)
|
||||
(signal_binding "swapped" @keyword)
|
||||
|
||||
(styles_list "styles" @function.macro)
|
||||
(layout_definition "layout" @function.macro)
|
||||
|
||||
(gettext_string "_" @function.builtin)
|
||||
|
||||
(menu_definition "menu" @keyword)
|
||||
(menu_section "section" @keyword)
|
||||
(menu_item "item" @function.macro)
|
||||
|
||||
(template_definition (template_name_qualifier) @type.qualifier)
|
||||
|
||||
(import_statement (gobject_library) @namespace)
|
||||
|
||||
(import_statement (version_number) @float)
|
||||
|
||||
(float) @float
|
||||
(number) @number
|
||||
|
||||
[
|
||||
";"
|
||||
"."
|
||||
","
|
||||
] @punctuation.delimiter
|
||||
|
||||
[
|
||||
"("
|
||||
")"
|
||||
"["
|
||||
"]"
|
||||
"{"
|
||||
"}"
|
||||
] @punctuation.bracket
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
[
|
||||
(for_statement)
|
||||
(if_statement)
|
||||
(while_statement)
|
||||
(do_statement)
|
||||
(switch_statement)
|
||||
(case_statement)
|
||||
(function_definition)
|
||||
(struct_specifier)
|
||||
(enum_specifier)
|
||||
(comment)
|
||||
(preproc_if)
|
||||
(preproc_elif)
|
||||
(preproc_else)
|
||||
(preproc_ifdef)
|
||||
(preproc_function_def)
|
||||
(initializer_list)
|
||||
(gnu_asm_expression)
|
||||
] @fold
|
||||
|
||||
(compound_statement
|
||||
(compound_statement) @fold)
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
[
|
||||
(compound_statement)
|
||||
(field_declaration_list)
|
||||
(case_statement)
|
||||
(enumerator_list)
|
||||
(compound_literal_expression)
|
||||
(initializer_list)
|
||||
(init_declarator)
|
||||
] @indent.begin
|
||||
|
||||
; With current indent logic, if we capture expression_statement with @indent.begin
|
||||
; It will be affected by _parent_ node with error subnodes deep down the tree
|
||||
; So narrow indent capture to check for error inside expression statement only,
|
||||
(expression_statement
|
||||
(_) @indent.begin
|
||||
";" @indent.end)
|
||||
|
||||
(ERROR
|
||||
"for" "(" @indent.begin ";" ";" ")" @indent.end)
|
||||
|
||||
((for_statement
|
||||
body: (_) @_body) @indent.begin
|
||||
(#not-has-type? @_body compound_statement))
|
||||
|
||||
(while_statement
|
||||
condition: (_) @indent.begin)
|
||||
|
||||
((while_statement
|
||||
body: (_) @_body) @indent.begin
|
||||
(#not-has-type? @_body compound_statement))
|
||||
|
||||
(
|
||||
(if_statement)
|
||||
.
|
||||
(ERROR "else" @indent.begin))
|
||||
|
||||
(if_statement
|
||||
condition: (_) @indent.begin)
|
||||
|
||||
;; Supports if without braces (but not both if-else without braces)
|
||||
((if_statement
|
||||
consequence:
|
||||
(_ ";" @indent.end) @_consequence
|
||||
(#not-has-type? @_consequence compound_statement)
|
||||
alternative:
|
||||
(else_clause
|
||||
"else" @indent.branch
|
||||
[
|
||||
(if_statement (compound_statement) @indent.dedent)? @indent.dedent
|
||||
(compound_statement)? @indent.dedent
|
||||
(_)? @indent.dedent
|
||||
]
|
||||
)?
|
||||
) @indent.begin)
|
||||
|
||||
(else_clause (_ . "{" @indent.branch))
|
||||
|
||||
|
||||
(compound_statement "}" @indent.end)
|
||||
|
||||
[
|
||||
")"
|
||||
"}"
|
||||
(statement_identifier)
|
||||
] @indent.branch
|
||||
|
||||
[
|
||||
"#define"
|
||||
"#ifdef"
|
||||
"#ifndef"
|
||||
"#elif"
|
||||
"#if"
|
||||
"#else"
|
||||
"#endif"
|
||||
] @indent.zero
|
||||
|
||||
[
|
||||
(preproc_arg)
|
||||
(string_literal)
|
||||
] @indent.ignore
|
||||
|
||||
((ERROR (parameter_declaration)) @indent.align
|
||||
(#set! indent.open_delimiter "(")
|
||||
(#set! indent.close_delimiter ")"))
|
||||
([(argument_list) (parameter_list)] @indent.align
|
||||
(#set! indent.open_delimiter "(")
|
||||
(#set! indent.close_delimiter ")"))
|
||||
|
||||
(comment) @indent.auto
|
||||
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
((preproc_arg) @injection.content
|
||||
(#set! injection.language "c"))
|
||||
|
||||
((comment) @injection.content
|
||||
(#set! injection.language "comment"))
|
||||
|
||||
((comment) @injection.content
|
||||
(#match? @injection.content "/\\*!([a-zA-Z]+:)?re2c")
|
||||
(#set! injection.language "re2c"))
|
||||
|
||||
((comment) @injection.content
|
||||
(#lua-match? @injection.content "/[*][!<*][^a-zA-Z]")
|
||||
(#set! injection.language "doxygen"))
|
||||
|
||||
; TODO: add when asm is added
|
||||
; (gnu_asm_expression assembly_code: (string_literal) @injection.content
|
||||
; (#set! injection.language "asm"))
|
||||
; (gnu_asm_expression assembly_code: (concatenated_string (string_literal) @injection.content)
|
||||
; (#set! injection.language "asm"))
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
;; Functions definitions
|
||||
(function_declarator
|
||||
declarator: (identifier) @definition.function)
|
||||
(preproc_function_def
|
||||
name: (identifier) @definition.macro) @scope
|
||||
|
||||
(preproc_def
|
||||
name: (identifier) @definition.macro)
|
||||
(pointer_declarator
|
||||
declarator: (identifier) @definition.var)
|
||||
(parameter_declaration
|
||||
declarator: (identifier) @definition.parameter)
|
||||
(init_declarator
|
||||
declarator: (identifier) @definition.var)
|
||||
(array_declarator
|
||||
declarator: (identifier) @definition.var)
|
||||
(declaration
|
||||
declarator: (identifier) @definition.var)
|
||||
(enum_specifier
|
||||
name: (_) @definition.type
|
||||
(enumerator_list
|
||||
(enumerator name: (identifier) @definition.var)))
|
||||
|
||||
;; Type / Struct / Enum
|
||||
(field_declaration
|
||||
declarator: (field_identifier) @definition.field)
|
||||
(type_definition
|
||||
declarator: (type_identifier) @definition.type)
|
||||
(struct_specifier
|
||||
name: (type_identifier) @definition.type)
|
||||
|
||||
;; goto
|
||||
(labeled_statement (statement_identifier) @definition)
|
||||
|
||||
;; References
|
||||
(identifier) @reference
|
||||
((field_identifier) @reference
|
||||
(#set! reference.kind "field"))
|
||||
((type_identifier) @reference
|
||||
(#set! reference.kind "type"))
|
||||
|
||||
(goto_statement (statement_identifier) @reference)
|
||||
|
||||
;; Scope
|
||||
[
|
||||
(for_statement)
|
||||
(if_statement)
|
||||
(while_statement)
|
||||
(translation_unit)
|
||||
(function_definition)
|
||||
(compound_statement) ; a block in curly braces
|
||||
(struct_specifier)
|
||||
] @scope
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
body: [
|
||||
(declaration_list)
|
||||
(switch_body)
|
||||
(enum_member_declaration_list)
|
||||
] @fold
|
||||
|
||||
accessors: [
|
||||
(accessor_list)
|
||||
] @fold
|
||||
|
||||
initializer: [
|
||||
(initializer_expression)
|
||||
] @fold
|
||||
|
||||
(block) @fold
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue