aboutsummaryrefslogtreecommitdiff
path: root/print.html
blob: 7747ff668a85d0b67b658594fbff073ce5d326d9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
<!DOCTYPE HTML>
<html lang="en" class="colibri" dir="ltr">
    <head>
        <!-- Book generated using mdBook -->
        <meta charset="UTF-8">
        <title></title>
        <meta name="robots" content="noindex">


        <!-- Custom HTML head -->
        
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="theme-color" content="#ffffff">

        <link rel="icon" href="favicon.svg">
        <link rel="shortcut icon" href="favicon.png">
        <link rel="stylesheet" href="css/variables.css">
        <link rel="stylesheet" href="css/general.css">
        <link rel="stylesheet" href="css/chrome.css">
        <link rel="stylesheet" href="css/print.css" media="print">

        <!-- Fonts -->
        <link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
        <link rel="stylesheet" href="fonts/fonts.css">

        <!-- Highlight.js Stylesheets -->
        <link rel="stylesheet" href="highlight.css">
        <link rel="stylesheet" href="tomorrow-night.css">
        <link rel="stylesheet" href="ayu-highlight.css">

        <!-- Custom theme stylesheets -->
        <link rel="stylesheet" href="custom.css">

    </head>
    <body class="sidebar-visible no-js">
    <div id="body-container">
        <!-- Provide site root to javascript -->
        <script>
            var path_to_root = "";
            var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "colibri" : "colibri";
        </script>

        <!-- Work around some values being stored in localStorage wrapped in quotes -->
        <script>
            try {
                var theme = localStorage.getItem('mdbook-theme');
                var sidebar = localStorage.getItem('mdbook-sidebar');

                if (theme.startsWith('"') && theme.endsWith('"')) {
                    localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
                }

                if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
                    localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
                }
            } catch (e) { }
        </script>

        <!-- Set the theme before any content is loaded, prevents flash -->
        <script>
            var theme;
            try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
            if (theme === null || theme === undefined) { theme = default_theme; }
            var html = document.querySelector('html');
            html.classList.remove('colibri')
            html.classList.add(theme);
            var body = document.querySelector('body');
            body.classList.remove('no-js')
            body.classList.add('js');
        </script>

        <input type="checkbox" id="sidebar-toggle-anchor" class="hidden">

        <!-- Hide / unhide sidebar before it is displayed -->
        <script>
            var body = document.querySelector('body');
            var sidebar = null;
            var sidebar_toggle = document.getElementById("sidebar-toggle-anchor");
            if (document.body.clientWidth >= 1080) {
                try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                sidebar = sidebar || 'visible';
            } else {
                sidebar = 'hidden';
            }
            sidebar_toggle.checked = sidebar === 'visible';
            body.classList.remove('sidebar-visible');
            body.classList.add("sidebar-" + sidebar);
        </script>

        <nav id="sidebar" class="sidebar" aria-label="Table of contents">
            <div class="sidebar-scrollbox">
                <ol class="chapter"><li class="chapter-item expanded affix "><a href="title-page.html">Helix</a></li><li class="chapter-item expanded "><a href="install.html"><strong aria-hidden="true">1.</strong> Installation</a></li><li class="chapter-item expanded "><a href="usage.html"><strong aria-hidden="true">2.</strong> Usage</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="keymap.html"><strong aria-hidden="true">2.1.</strong> Keymap</a></li><li class="chapter-item expanded "><a href="commands.html"><strong aria-hidden="true">2.2.</strong> Commands</a></li><li class="chapter-item expanded "><a href="lang-support.html"><strong aria-hidden="true">2.3.</strong> Language support</a></li></ol></li><li class="chapter-item expanded "><a href="from-vim.html"><strong aria-hidden="true">3.</strong> Migrating from Vim</a></li><li class="chapter-item expanded "><a href="configuration.html"><strong aria-hidden="true">4.</strong> Configuration</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="themes.html"><strong aria-hidden="true">4.1.</strong> Themes</a></li><li class="chapter-item expanded "><a href="remapping.html"><strong aria-hidden="true">4.2.</strong> Key remapping</a></li><li class="chapter-item expanded "><a href="languages.html"><strong aria-hidden="true">4.3.</strong> Languages</a></li></ol></li><li class="chapter-item expanded "><a href="guides/index.html"><strong aria-hidden="true">5.</strong> Guides</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="guides/adding_languages.html"><strong aria-hidden="true">5.1.</strong> Adding languages</a></li><li class="chapter-item expanded "><a href="guides/textobject.html"><strong aria-hidden="true">5.2.</strong> Adding textobject queries</a></li><li class="chapter-item expanded "><a href="guides/indent.html"><strong aria-hidden="true">5.3.</strong> Adding indent queries</a></li><li class="chapter-item expanded "><a href="guides/injection.html"><strong aria-hidden="true">5.4.</strong> Adding injection queries</a></li><li class="chapter-item expanded "><a href="guides/rainbow_bracket_queries.html"><strong aria-hidden="true">5.5.</strong> Adding rainbow bracket queries</a></li></ol></li></ol>
            </div>
            <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
        </nav>

        <!-- Track and set sidebar scroll position -->
        <script>
            var sidebarScrollbox = document.querySelector('#sidebar .sidebar-scrollbox');
            sidebarScrollbox.addEventListener('click', function(e) {
                if (e.target.tagName === 'A') {
                    sessionStorage.setItem('sidebar-scroll', sidebarScrollbox.scrollTop);
                }
            }, { passive: true });
            var sidebarScrollTop = sessionStorage.getItem('sidebar-scroll');
            sessionStorage.removeItem('sidebar-scroll');
            if (sidebarScrollTop) {
                // preserve sidebar scroll position when navigating via links within sidebar
                sidebarScrollbox.scrollTop = sidebarScrollTop;
            } else {
                // scroll sidebar to current active section when navigating via "next/previous chapter" buttons
                var activeSection = document.querySelector('#sidebar .active');
                if (activeSection) {
                    activeSection.scrollIntoView({ block: 'center' });
                }
            }
        </script>

        <div id="page-wrapper" class="page-wrapper">

            <div class="page">
                                <div id="menu-bar-hover-placeholder"></div>
                <div id="menu-bar" class="menu-bar sticky">
                    <div class="left-buttons">
                        <label id="sidebar-toggle" class="icon-button" for="sidebar-toggle-anchor" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                            <i class="fa fa-bars"></i>
                        </label>
                        <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
                            <i class="fa fa-paint-brush"></i>
                        </button>
                        <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
                            <li role="none"><button role="menuitem" class="theme" id="light">Light</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="colibri">Colibri</button></li>
                        </ul>
                        <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
                            <i class="fa fa-search"></i>
                        </button>
                    </div>

                    <h1 class="menu-title"></h1>

                    <div class="right-buttons">
                        <a href="print.html" title="Print this book" aria-label="Print this book">
                            <i id="print-button" class="fa fa-print"></i>
                        </a>
                        <a href="https://github.com/helix-editor/helix" title="Git repository" aria-label="Git repository">
                            <i id="git-repository-button" class="fa fa-github"></i>
                        </a>

                    </div>
                </div>

                <div id="search-wrapper" class="hidden">
                    <form id="searchbar-outer" class="searchbar-outer">
                        <input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
                    </form>
                    <div id="searchresults-outer" class="searchresults-outer hidden">
                        <div id="searchresults-header" class="searchresults-header"></div>
                        <ul id="searchresults">
                        </ul>
                    </div>
                </div>

                <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
                <script>
                    document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                    document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                    Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
                        link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                    });
                </script>

                <div id="content" class="content">
                    <main>
                        <h1 id="helix"><a class="header" href="#helix">Helix</a></h1>
<p>Docs for bleeding edge master can be found at
<a href="https://docs.helix-editor.com/master">https://docs.helix-editor.com/master</a>.</p>
<p>See the <a href="./usage.html">usage</a> section for a quick overview of the editor, <a href="./keymap.html">keymap</a>
section for all available keybindings and the <a href="./configuration.html">configuration</a> section
for defining custom keybindings, setting themes, etc.
For everything else (e.g., how to install supported language servers), see the <a href="https://github.com/helix-editor/helix/wiki">Helix Wiki</a>.</p>
<p>Refer the <a href="https://github.com/helix-editor/helix/wiki/FAQ">FAQ</a> for common questions.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="installing-helix"><a class="header" href="#installing-helix">Installing Helix</a></h1>
<!--toc:start-->
<ul>
<li><a href="install.html#pre-built-binaries">Pre-built binaries</a></li>
<li><a href="install.html#linux-macos-windows-and-openbsd-packaging-status">Linux, macOS, Windows and OpenBSD packaging status</a></li>
<li><a href="install.html#linux">Linux</a>
<ul>
<li><a href="install.html#ubuntu">Ubuntu</a></li>
<li><a href="install.html#fedorarhel">Fedora/RHEL</a></li>
<li><a href="install.html#arch-linux-extra">Arch Linux extra</a></li>
<li><a href="install.html#nixos">NixOS</a></li>
<li><a href="install.html#flatpak">Flatpak</a></li>
<li><a href="install.html#snap">Snap</a></li>
<li><a href="install.html#appimage">AppImage</a></li>
</ul>
</li>
<li><a href="install.html#macos">macOS</a>
<ul>
<li><a href="install.html#homebrew-core">Homebrew Core</a></li>
</ul>
</li>
<li><a href="install.html#windows">Windows</a>
<ul>
<li><a href="install.html#winget">Winget</a></li>
<li><a href="install.html#scoop">Scoop</a></li>
<li><a href="install.html#chocolatey">Chocolatey</a></li>
<li><a href="install.html#msys2">MSYS2</a></li>
</ul>
</li>
<li><a href="install.html#building-from-source">Building from source</a>
<ul>
<li><a href="install.html#configuring-helixs-runtime-files">Configuring Helix's runtime files</a>
<ul>
<li><a href="install.html#linux-and-macos">Linux and macOS</a></li>
<li><a href="install.html#windows">Windows</a></li>
<li><a href="install.html#multiple-runtime-directories">Multiple runtime directories</a></li>
</ul>
</li>
<li><a href="install.html#validating-the-installation">Validating the installation</a></li>
<li><a href="install.html#configure-the-desktop-shortcut">Configure the desktop shortcut</a></li>
</ul>
</li>
</ul>
<!--toc:end-->
<p>To install Helix, follow the instructions specific to your operating system.
Note that:</p>
<ul>
<li>
<p>To get the latest nightly version of Helix, you need to
<a href="install.html#building-from-source">build from source</a>.</p>
</li>
<li>
<p>To take full advantage of Helix, install the language servers for your
preferred programming languages. See the
<a href="https://github.com/helix-editor/helix/wiki/How-to-install-the-default-language-servers">wiki</a>
for instructions.</p>
</li>
</ul>
<h2 id="pre-built-binaries"><a class="header" href="#pre-built-binaries">Pre-built binaries</a></h2>
<p>Download pre-built binaries from the
<a href="https://github.com/helix-editor/helix/releases">GitHub Releases page</a>. Add the binary to your system's <code>$PATH</code> to use it from the command
line.</p>
<h2 id="linux-macos-windows-and-openbsd-packaging-status"><a class="header" href="#linux-macos-windows-and-openbsd-packaging-status">Linux, macOS, Windows and OpenBSD packaging status</a></h2>
<p><a href="https://repology.org/project/helix/versions"><img src="https://repology.org/badge/vertical-allrepos/helix.svg" alt="Packaging status" /></a></p>
<h2 id="linux"><a class="header" href="#linux">Linux</a></h2>
<p>The following third party repositories are available:</p>
<h3 id="ubuntu"><a class="header" href="#ubuntu">Ubuntu</a></h3>
<p>Add the <code>PPA</code> for Helix:</p>
<pre><code class="language-sh">sudo add-apt-repository ppa:maveonair/helix-editor
sudo apt update
sudo apt install helix
</code></pre>
<h3 id="fedorarhel"><a class="header" href="#fedorarhel">Fedora/RHEL</a></h3>
<p>Enable the <code>COPR</code> repository for Helix:</p>
<pre><code class="language-sh">sudo dnf copr enable varlad/helix
sudo dnf install helix
</code></pre>
<h3 id="arch-linux-extra"><a class="header" href="#arch-linux-extra">Arch Linux extra</a></h3>
<p>Releases are available in the <code>extra</code> repository:</p>
<pre><code class="language-sh">sudo pacman -S helix
</code></pre>
<p>Additionally, a <a href="https://aur.archlinux.org/packages/helix-git/">helix-git</a> package is available
in the AUR, which builds the master branch.</p>
<h3 id="nixos"><a class="header" href="#nixos">NixOS</a></h3>
<p>Helix is available in <a href="https://github.com/nixos/nixpkgs">nixpkgs</a> through the <code>helix</code> attribute,
the unstable channel usually carries the latest release.</p>
<p>Helix is also available as a <a href="https://nixos.wiki/wiki/Flakes">flake</a> in the project
root. Use <code>nix develop</code> to spin up a reproducible development shell. Outputs are
cached for each push to master using <a href="https://www.cachix.org/">Cachix</a>. The
flake is configured to automatically make use of this cache assuming the user
accepts the new settings on first use.</p>
<p>If you are using a version of Nix without flakes enabled,
<a href="https://docs.cachix.org/installation">install Cachix CLI</a> and use
<code>cachix use helix</code> to configure Nix to use cached outputs when possible.</p>
<h3 id="flatpak"><a class="header" href="#flatpak">Flatpak</a></h3>
<p>Helix is available on <a href="https://flathub.org/en-GB/apps/com.helix_editor.Helix">Flathub</a>:</p>
<pre><code class="language-sh">flatpak install flathub com.helix_editor.Helix
flatpak run com.helix_editor.Helix
</code></pre>
<h3 id="snap"><a class="header" href="#snap">Snap</a></h3>
<p>Helix is available on <a href="https://snapcraft.io/helix">Snapcraft</a> and can be installed with:</p>
<pre><code class="language-sh">snap install --classic helix
</code></pre>
<p>This will install Helix as both <code>/snap/bin/helix</code> and <code>/snap/bin/hx</code>, so make sure <code>/snap/bin</code> is in your <code>PATH</code>.</p>
<h3 id="appimage"><a class="header" href="#appimage">AppImage</a></h3>
<p>Install Helix using the Linux <a href="https://appimage.org/">AppImage</a> format.
Download the official Helix AppImage from the <a href="https://github.com/helix-editor/helix/releases/latest">latest releases</a> page.</p>
<pre><code class="language-sh">chmod +x helix-*.AppImage # change permission for executable mode
./helix-*.AppImage # run helix
</code></pre>
<h2 id="macos"><a class="header" href="#macos">macOS</a></h2>
<h3 id="homebrew-core"><a class="header" href="#homebrew-core">Homebrew Core</a></h3>
<pre><code class="language-sh">brew install helix
</code></pre>
<h2 id="windows"><a class="header" href="#windows">Windows</a></h2>
<p>Install on Windows using <a href="https://learn.microsoft.com/en-us/windows/package-manager/winget/">Winget</a>, <a href="https://scoop.sh/">Scoop</a>, <a href="https://chocolatey.org/">Chocolatey</a>
or <a href="https://msys2.org/">MSYS2</a>.</p>
<h3 id="winget"><a class="header" href="#winget">Winget</a></h3>
<p>Windows Package Manager winget command-line tool is by default available on Windows 11 and modern versions of Windows 10 as a part of the App Installer.
You can get <a href="https://www.microsoft.com/p/app-installer/9nblggh4nns1#activetab=pivot:overviewtab">App Installer from the Microsoft Store</a>. If it's already installed, make sure it is updated with the latest version.</p>
<pre><code class="language-sh">winget install Helix.Helix
</code></pre>
<h3 id="scoop"><a class="header" href="#scoop">Scoop</a></h3>
<pre><code class="language-sh">scoop install helix
</code></pre>
<h3 id="chocolatey"><a class="header" href="#chocolatey">Chocolatey</a></h3>
<pre><code class="language-sh">choco install helix
</code></pre>
<h3 id="msys2"><a class="header" href="#msys2">MSYS2</a></h3>
<p>For 64-bit Windows 8.1 or above:</p>
<pre><code class="language-sh">pacman -S mingw-w64-ucrt-x86_64-helix
</code></pre>
<h2 id="building-from-source"><a class="header" href="#building-from-source">Building from source</a></h2>
<p>Requirements:</p>
<p>Clone the Helix GitHub repository into a directory of your choice. The
examples in this documentation assume installation into either <code>~/src/</code> on
Linux and macOS, or <code>%userprofile%\src\</code> on Windows.</p>
<ul>
<li>The <a href="https://www.rust-lang.org/tools/install">Rust toolchain</a></li>
<li>The <a href="https://git-scm.com/">Git version control system</a></li>
<li>A C++14 compatible compiler to build the tree-sitter grammars, for example GCC or Clang</li>
</ul>
<p>If you are using the <code>musl-libc</code> standard library instead of <code>glibc</code> the following environment variable must be set during the build to ensure tree-sitter grammars can be loaded correctly:</p>
<pre><code class="language-sh">RUSTFLAGS=&quot;-C target-feature=-crt-static&quot;
</code></pre>
<ol>
<li>
<p>Clone the repository:</p>
<pre><code class="language-sh">git clone https://github.com/helix-editor/helix
cd helix
</code></pre>
</li>
<li>
<p>Compile from source:</p>
<pre><code class="language-sh">cargo install --path helix-term --locked
</code></pre>
<p>This command will create the <code>hx</code> executable and construct the tree-sitter
grammars in the local <code>runtime</code> folder.</p>
</li>
</ol>
<blockquote>
<p>💡 Tree-sitter grammars can be fetched and compiled if not pre-packaged. Fetch
grammars with <code>hx --grammar fetch</code> and compile them with
<code>hx --grammar build</code>. This will install them in
the <code>runtime</code> directory within the user's helix config directory (more
<a href="install.html#multiple-runtime-directories">details below</a>).</p>
</blockquote>
<h3 id="configuring-helixs-runtime-files"><a class="header" href="#configuring-helixs-runtime-files">Configuring Helix's runtime files</a></h3>
<h4 id="linux-and-macos"><a class="header" href="#linux-and-macos">Linux and macOS</a></h4>
<p>The <strong>runtime</strong> directory is one below the Helix source, so either set a
<code>HELIX_RUNTIME</code> environment variable to point to that directory and add it to
your <code>~/.bashrc</code> or equivalent:</p>
<pre><code class="language-sh">HELIX_RUNTIME=~/src/helix/runtime
</code></pre>
<p>Or, create a symbolic link:</p>
<pre><code class="language-sh">ln -Ts $PWD/runtime ~/.config/helix/runtime
</code></pre>
<p>If the above command fails to create a symbolic link because the file exists either move <code>~/.config/helix/runtime</code> to a new location or delete it, then run the symlink command above again.</p>
<h4 id="windows-1"><a class="header" href="#windows-1">Windows</a></h4>
<p>Either set the <code>HELIX_RUNTIME</code> environment variable to point to the runtime files using the Windows setting (search for
<code>Edit environment variables for your account</code>) or use the <code>setx</code> command in
Cmd:</p>
<pre><code class="language-sh">setx HELIX_RUNTIME &quot;%userprofile%\source\repos\helix\runtime&quot;
</code></pre>
<blockquote>
<p>💡 <code>%userprofile%</code> resolves to your user directory like
<code>C:\Users\Your-Name\</code> for example.</p>
</blockquote>
<p>Or, create a symlink in <code>%appdata%\helix\</code> that links to the source code directory:</p>
<div class="table-wrapper"><table><thead><tr><th>Method</th><th>Command</th></tr></thead><tbody>
<tr><td>PowerShell</td><td><code>New-Item -ItemType Junction -Target &quot;runtime&quot; -Path &quot;$Env:AppData\helix\runtime&quot;</code></td></tr>
<tr><td>Cmd</td><td><code>cd %appdata%\helix</code> <br/> <code>mklink /D runtime &quot;%userprofile%\src\helix\runtime&quot;</code></td></tr>
</tbody></table>
</div>
<blockquote>
<p>💡 On Windows, creating a symbolic link may require running PowerShell or
Cmd as an administrator.</p>
</blockquote>
<h4 id="multiple-runtime-directories"><a class="header" href="#multiple-runtime-directories">Multiple runtime directories</a></h4>
<p>When Helix finds multiple runtime directories it will search through them for files in the
following order:</p>
<ol>
<li><code>runtime/</code> sibling directory to <code>$CARGO_MANIFEST_DIR</code> directory (this is intended for
developing and testing helix only).</li>
<li><code>runtime/</code> subdirectory of OS-dependent helix user config directory.</li>
<li><code>$HELIX_RUNTIME</code></li>
<li>Distribution-specific fallback directory (set at compile time—not run time—
with the <code>HELIX_DEFAULT_RUNTIME</code> environment variable)</li>
<li><code>runtime/</code> subdirectory of path to Helix executable.</li>
</ol>
<p>This order also sets the priority for selecting which file will be used if multiple runtime
directories have files with the same name.</p>
<h4 id="note-to-packagers"><a class="header" href="#note-to-packagers">Note to packagers</a></h4>
<p>If you are making a package of Helix for end users, to provide a good out of
the box experience, you should set the <code>HELIX_DEFAULT_RUNTIME</code> environment
variable at build time (before invoking <code>cargo build</code>) to a directory which
will store the final runtime files after installation. For example, say you want
to package the runtime into <code>/usr/lib/helix/runtime</code>. The rough steps a build
script could follow are:</p>
<ol>
<li><code>export HELIX_DEFAULT_RUNTIME=/usr/lib/helix/runtime</code></li>
<li><code>cargo build --profile opt --locked --path helix-term</code></li>
<li><code>cp -r runtime $BUILD_DIR/usr/lib/helix/</code></li>
<li><code>cp target/opt/hx $BUILD_DIR/usr/bin/hx</code></li>
</ol>
<p>This way the resulting <code>hx</code> binary will always look for its runtime directory in
<code>/usr/lib/helix/runtime</code> if the user has no custom runtime in <code>~/.config/helix</code>
or <code>HELIX_RUNTIME</code>.</p>
<h3 id="validating-the-installation"><a class="header" href="#validating-the-installation">Validating the installation</a></h3>
<p>To make sure everything is set up as expected you should run the Helix health
check:</p>
<pre><code class="language-sh">hx --health
</code></pre>
<p>For more information on the health check results refer to
<a href="https://github.com/helix-editor/helix/wiki/Healthcheck">Health check</a>.</p>
<h3 id="configure-the-desktop-shortcut"><a class="header" href="#configure-the-desktop-shortcut">Configure the desktop shortcut</a></h3>
<p>If your desktop environment supports the
<a href="https://specifications.freedesktop.org/menu-spec/menu-spec-latest.html">XDG desktop menu</a>
you can configure Helix to show up in the application menu by copying the
provided <code>.desktop</code> and icon files to their correct folders:</p>
<pre><code class="language-sh">cp contrib/Helix.desktop ~/.local/share/applications
cp contrib/helix.png ~/.icons # or ~/.local/share/icons
</code></pre>
<p>To use another terminal than the system default, you can modify the <code>.desktop</code>
file. For example, to use <code>kitty</code>:</p>
<pre><code class="language-sh">sed -i &quot;s|Exec=hx %F|Exec=kitty hx %F|g&quot; ~/.local/share/applications/Helix.desktop
sed -i &quot;s|Terminal=true|Terminal=false|g&quot; ~/.local/share/applications/Helix.desktop
</code></pre>
<div style="break-before: page; page-break-before: always;"></div><h1 id="using-helix"><a class="header" href="#using-helix">Using Helix</a></h1>
<!--toc:start-->
<ul>
<li><a href="usage.html#registers">Registers</a>
<ul>
<li><a href="usage.html#user-defined-registers">User-defined registers</a></li>
<li><a href="usage.html#special-registers">Special registers</a></li>
</ul>
</li>
<li><a href="usage.html#surround">Surround</a></li>
<li><a href="usage.html#selecting-and-manipulating-text-with-textobjects">Selecting and manipulating text with textobjects</a></li>
<li><a href="usage.html#navigating-using-tree-sitter-textobjects">Navigating using tree-sitter textobjects</a></li>
<li><a href="usage.html#moving-the-selection-with-syntax-aware-motions">Moving the selection with syntax-aware motions</a></li>
</ul>
<!--toc:end-->
<p>For a full interactive introduction to Helix, refer to the
<a href="https://github.com/helix-editor/helix/blob/master/runtime/tutor">tutor</a> which
can be accessed via the command <code>hx --tutor</code> or <code>:tutor</code>.</p>
<blockquote>
<p>💡 Currently, not all functionality is fully documented, please refer to the
<a href="./keymap.html">key mappings</a> list.</p>
</blockquote>
<h2 id="registers"><a class="header" href="#registers">Registers</a></h2>
<p>In Helix, registers are storage locations for text and other data, such as the
result of a search. Registers can be used to cut, copy, and paste text, similar
to the clipboard in other text editors. Usage is similar to Vim, with <code>&quot;</code> being
used to select a register.</p>
<h3 id="user-defined-registers"><a class="header" href="#user-defined-registers">User-defined registers</a></h3>
<p>Helix allows you to create your own named registers for storing text, for
example:</p>
<ul>
<li><code>&quot;ay</code> - Yank the current selection to register <code>a</code>.</li>
<li><code>&quot;op</code> - Paste the text in register <code>o</code> after the selection.</li>
</ul>
<p>If a register is selected before invoking a change or delete command, the selection will be stored in the register and the action will be carried out:</p>
<ul>
<li><code>&quot;hc</code> - Store the selection in register <code>h</code> and then change it (delete and enter insert mode).</li>
<li><code>&quot;md</code> - Store the selection in register <code>m</code> and delete it.</li>
</ul>
<h3 id="default-registers"><a class="header" href="#default-registers">Default registers</a></h3>
<p>Commands that use registers, like yank (<code>y</code>), use a default register if none is specified.
These registers are used as defaults:</p>
<div class="table-wrapper"><table><thead><tr><th>Register character</th><th>Contains</th></tr></thead><tbody>
<tr><td><code>/</code></td><td>Last search</td></tr>
<tr><td><code>:</code></td><td>Last executed command</td></tr>
<tr><td><code>&quot;</code></td><td>Last yanked text</td></tr>
<tr><td><code>@</code></td><td>Last recorded macro</td></tr>
</tbody></table>
</div>
<h3 id="special-registers"><a class="header" href="#special-registers">Special registers</a></h3>
<p>Some registers have special behavior when read from and written to.</p>
<div class="table-wrapper"><table><thead><tr><th>Register character</th><th>When read</th><th>When written</th></tr></thead><tbody>
<tr><td><code>_</code></td><td>No values are returned</td><td>All values are discarded</td></tr>
<tr><td><code>#</code></td><td>Selection indices (first selection is <code>1</code>, second is <code>2</code>, etc.)</td><td>This register is not writable</td></tr>
<tr><td><code>.</code></td><td>Contents of the current selections</td><td>This register is not writable</td></tr>
<tr><td><code>%</code></td><td>Name of the current file</td><td>This register is not writable</td></tr>
<tr><td><code>*</code></td><td>Reads from the system clipboard</td><td>Joins and yanks to the system clipboard</td></tr>
<tr><td><code>+</code></td><td>Reads from the primary clipboard</td><td>Joins and yanks to the primary clipboard</td></tr>
</tbody></table>
</div>
<p>When yanking multiple selections to the clipboard registers, the selections
are joined with newlines. Pasting from these registers will paste multiple
selections if the clipboard was last yanked to by the Helix session. Otherwise
the clipboard contents are pasted as one selection.</p>
<h2 id="surround"><a class="header" href="#surround">Surround</a></h2>
<p>Helix includes built-in functionality similar to <a href="https://github.com/tpope/vim-surround">vim-surround</a>.
The keymappings have been inspired from <a href="https://github.com/machakann/vim-sandwich">vim-sandwich</a>:</p>
<p><img src="https://user-images.githubusercontent.com/23398472/122865801-97073180-d344-11eb-8142-8f43809982c6.gif" alt="Surround demo" /></p>
<div class="table-wrapper"><table><thead><tr><th>Key Sequence</th><th>Action</th></tr></thead><tbody>
<tr><td><code>ms&lt;char&gt;</code> (after selecting text)</td><td>Add surround characters to selection</td></tr>
<tr><td><code>mr&lt;char_to_replace&gt;&lt;new_char&gt;</code></td><td>Replace the closest surround characters</td></tr>
<tr><td><code>md&lt;char_to_delete&gt;</code></td><td>Delete the closest surround characters</td></tr>
</tbody></table>
</div>
<p>You can use counts to act on outer pairs.</p>
<p>Surround can also act on multiple selections. For example, to change every occurrence of <code>(use)</code> to <code>[use]</code>:</p>
<ol>
<li><code>%</code> to select the whole file</li>
<li><code>s</code> to split the selections on a search term</li>
<li>Input <code>use</code> and hit Enter</li>
<li><code>mr([</code> to replace the parentheses with square brackets</li>
</ol>
<p>Multiple characters are currently not supported, but planned for future release.</p>
<h2 id="selecting-and-manipulating-text-with-textobjects"><a class="header" href="#selecting-and-manipulating-text-with-textobjects">Selecting and manipulating text with textobjects</a></h2>
<p>In Helix, textobjects are a way to select, manipulate and operate on a piece of
text in a structured way. They allow you to refer to blocks of text based on
their structure or purpose, such as a word, sentence, paragraph, or even a
function or block of code.</p>
<p><img src="https://user-images.githubusercontent.com/23398472/124231131-81a4bb00-db2d-11eb-9d10-8e577ca7b177.gif" alt="Textobject demo" />
<img src="https://user-images.githubusercontent.com/23398472/132537398-2a2e0a54-582b-44ab-a77f-eb818942203d.gif" alt="Textobject tree-sitter demo" /></p>
<ul>
<li><code>ma</code> - Select around the object (<code>va</code> in Vim, <code>&lt;alt-a&gt;</code> in Kakoune)</li>
<li><code>mi</code> - Select inside the object (<code>vi</code> in Vim, <code>&lt;alt-i&gt;</code> in Kakoune)</li>
</ul>
<div class="table-wrapper"><table><thead><tr><th>Key after <code>mi</code> or <code>ma</code></th><th>Textobject selected</th></tr></thead><tbody>
<tr><td><code>w</code></td><td>Word</td></tr>
<tr><td><code>W</code></td><td>WORD</td></tr>
<tr><td><code>p</code></td><td>Paragraph</td></tr>
<tr><td><code>(</code>, <code>[</code>, <code>'</code>, etc.</td><td>Specified surround pairs</td></tr>
<tr><td><code>m</code></td><td>The closest surround pair</td></tr>
<tr><td><code>f</code></td><td>Function</td></tr>
<tr><td><code>t</code></td><td>Type (or Class)</td></tr>
<tr><td><code>a</code></td><td>Argument/parameter</td></tr>
<tr><td><code>c</code></td><td>Comment</td></tr>
<tr><td><code>T</code></td><td>Test</td></tr>
<tr><td><code>g</code></td><td>Change</td></tr>
</tbody></table>
</div>
<blockquote>
<p>💡 <code>f</code>, <code>t</code>, etc. need a tree-sitter grammar active for the current
document and a special tree-sitter query file to work properly. <a href="./lang-support.html">Only
some grammars</a> currently have the query file implemented.
Contributions are welcome!</p>
</blockquote>
<h2 id="navigating-using-tree-sitter-textobjects"><a class="header" href="#navigating-using-tree-sitter-textobjects">Navigating using tree-sitter textobjects</a></h2>
<p>Navigating between functions, classes, parameters, and other elements is
possible using tree-sitter and textobject queries. For
example to move to the next function use <code>]f</code>, to move to previous
type use <code>[t</code>, and so on.</p>
<p><img src="https://user-images.githubusercontent.com/23398472/152332550-7dfff043-36a2-4aec-b8f2-77c13eb56d6f.gif" alt="Tree-sitter-nav-demo" /></p>
<p>For the full reference see the <a href="./keymap.html#unimpaired">unimpaired</a> section of the key bind
documentation.</p>
<blockquote>
<p>💡 This feature relies on tree-sitter textobjects
and requires the corresponding query file to work properly.</p>
</blockquote>
<h2 id="moving-the-selection-with-syntax-aware-motions"><a class="header" href="#moving-the-selection-with-syntax-aware-motions">Moving the selection with syntax-aware motions</a></h2>
<p><code>Alt-p</code>, <code>Alt-o</code>, <code>Alt-i</code>, and <code>Alt-n</code> (or <code>Alt</code> and arrow keys) allow you to move the 
selection according to its location in the syntax tree. For example, many languages have the
following syntax for function calls:</p>
<pre><code class="language-js">func(arg1, arg2, arg3);
</code></pre>
<p>A function call might be parsed by tree-sitter into a tree like the following.</p>
<pre><code class="language-tsq">(call
  function: (identifier) ; func
  arguments:
    (arguments           ; (arg1, arg2, arg3)
      (identifier)       ; arg1
      (identifier)       ; arg2
      (identifier)))     ; arg3
</code></pre>
<p>Use <code>:tree-sitter-subtree</code> to view the syntax tree of the primary selection. In
a more intuitive tree format:</p>
<pre><code>            ┌────┐
            │call│
      ┌─────┴────┴─────┐
      │                │
┌─────▼────┐      ┌────▼────┐
│identifier│      │arguments│
│  &quot;func&quot;  │ ┌────┴───┬─────┴───┐
└──────────┘ │        │         │
             │        │         │
   ┌─────────▼┐  ┌────▼─────┐  ┌▼─────────┐
   │identifier│  │identifier│  │identifier│
   │  &quot;arg1&quot;  │  │  &quot;arg2&quot;  │  │  &quot;arg3&quot;  │
   └──────────┘  └──────────┘  └──────────┘
</code></pre>
<p>If you have a selection that wraps <code>arg1</code> (see the tree above), and you use
<code>Alt-n</code>, it will select the next sibling in the syntax tree: <code>arg2</code>.</p>
<pre><code class="language-js">// before
func([arg1], arg2, arg3)
// after
func(arg1, [arg2], arg3);
</code></pre>
<p>Similarly, <code>Alt-o</code> will expand the selection to the parent node, in this case, the
arguments node.</p>
<pre><code class="language-js">func[(arg1, arg2, arg3)];
</code></pre>
<p>There is also some nuanced behavior that prevents you from getting stuck on a
node with no sibling. When using <code>Alt-p</code> with a selection on <code>arg1</code>, the previous
child node will be selected. In the event that <code>arg1</code> does not have a previous
sibling, the selection will move up the syntax tree and select the previous
element. As a result, using <code>Alt-p</code> with a selection on <code>arg1</code> will move the
selection to the &quot;func&quot; <code>identifier</code>.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="keymap"><a class="header" href="#keymap">Keymap</a></h1>
<ul>
<li><a href="keymap.html#normal-mode">Normal mode</a>
<ul>
<li><a href="keymap.html#movement">Movement</a></li>
<li><a href="keymap.html#changes">Changes</a>
<ul>
<li><a href="keymap.html#shell">Shell</a></li>
</ul>
</li>
<li><a href="keymap.html#selection-manipulation">Selection manipulation</a></li>
<li><a href="keymap.html#search">Search</a></li>
<li><a href="keymap.html#minor-modes">Minor modes</a>
<ul>
<li><a href="keymap.html#view-mode">View mode</a></li>
<li><a href="keymap.html#goto-mode">Goto mode</a></li>
<li><a href="keymap.html#match-mode">Match mode</a></li>
<li><a href="keymap.html#window-mode">Window mode</a></li>
<li><a href="keymap.html#space-mode">Space mode</a>
<ul>
<li><a href="keymap.html#popup">Popup</a></li>
</ul>
</li>
<li><a href="keymap.html#unimpaired">Unimpaired</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="keymap.html#insert-mode">Insert mode</a></li>
<li><a href="keymap.html#select--extend-mode">Select / extend mode</a></li>
<li><a href="keymap.html#picker">Picker</a></li>
<li><a href="keymap.html#prompt">Prompt</a></li>
</ul>
<blockquote>
<p>💡 Mappings marked (<strong>LSP</strong>) require an active language server for the file.</p>
</blockquote>
<blockquote>
<p>💡 Mappings marked (<strong>TS</strong>) require a tree-sitter grammar for the file type.</p>
</blockquote>
<h2 id="normal-mode"><a class="header" href="#normal-mode">Normal mode</a></h2>
<p>Normal mode is the default mode when you launch helix. Return to it from other modes by typing <code>Escape</code>.</p>
<h3 id="movement"><a class="header" href="#movement">Movement</a></h3>
<blockquote>
<p>NOTE: Unlike Vim, <code>f</code>, <code>F</code>, <code>t</code> and <code>T</code> are not confined to the current line.</p>
</blockquote>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>h</code>, <code>Left</code></td><td>Move left</td><td><code>move_char_left</code></td></tr>
<tr><td><code>j</code>, <code>Down</code></td><td>Move down</td><td><code>move_visual_line_down</code></td></tr>
<tr><td><code>k</code>, <code>Up</code></td><td>Move up</td><td><code>move_visual_line_up</code></td></tr>
<tr><td><code>l</code>, <code>Right</code></td><td>Move right</td><td><code>move_char_right</code></td></tr>
<tr><td><code>w</code></td><td>Move next word start</td><td><code>move_next_word_start</code></td></tr>
<tr><td><code>b</code></td><td>Move previous word start</td><td><code>move_prev_word_start</code></td></tr>
<tr><td><code>e</code></td><td>Move next word end</td><td><code>move_next_word_end</code></td></tr>
<tr><td><code>W</code></td><td>Move next WORD start</td><td><code>move_next_long_word_start</code></td></tr>
<tr><td><code>B</code></td><td>Move previous WORD start</td><td><code>move_prev_long_word_start</code></td></tr>
<tr><td><code>E</code></td><td>Move next WORD end</td><td><code>move_next_long_word_end</code></td></tr>
<tr><td><code>t</code></td><td>Find 'till next char</td><td><code>find_till_char</code></td></tr>
<tr><td><code>f</code></td><td>Find next char</td><td><code>find_next_char</code></td></tr>
<tr><td><code>T</code></td><td>Find 'till previous char</td><td><code>till_prev_char</code></td></tr>
<tr><td><code>F</code></td><td>Find previous char</td><td><code>find_prev_char</code></td></tr>
<tr><td><code>G</code></td><td>Go to line number <code>&lt;n&gt;</code></td><td><code>goto_line</code></td></tr>
<tr><td><code>Alt-.</code></td><td>Repeat last motion (<code>f</code>, <code>t</code> or <code>m</code>)</td><td><code>repeat_last_motion</code></td></tr>
<tr><td><code>Home</code></td><td>Move to the start of the line</td><td><code>goto_line_start</code></td></tr>
<tr><td><code>End</code></td><td>Move to the end of the line</td><td><code>goto_line_end</code></td></tr>
<tr><td><code>Ctrl-b</code>, <code>PageUp</code></td><td>Move page up</td><td><code>page_up</code></td></tr>
<tr><td><code>Ctrl-f</code>, <code>PageDown</code></td><td>Move page down</td><td><code>page_down</code></td></tr>
<tr><td><code>Ctrl-u</code></td><td>Move half page up</td><td><code>half_page_up</code></td></tr>
<tr><td><code>Ctrl-d</code></td><td>Move half page down</td><td><code>half_page_down</code></td></tr>
<tr><td><code>Ctrl-i</code></td><td>Jump forward on the jumplist</td><td><code>jump_forward</code></td></tr>
<tr><td><code>Ctrl-o</code></td><td>Jump backward on the jumplist</td><td><code>jump_backward</code></td></tr>
<tr><td><code>Ctrl-s</code></td><td>Save the current selection to the jumplist</td><td><code>save_selection</code></td></tr>
</tbody></table>
</div>
<h3 id="changes"><a class="header" href="#changes">Changes</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>r</code></td><td>Replace with a character</td><td><code>replace</code></td></tr>
<tr><td><code>R</code></td><td>Replace with yanked text</td><td><code>replace_with_yanked</code></td></tr>
<tr><td><code>~</code></td><td>Switch case of the selected text</td><td><code>switch_case</code></td></tr>
<tr><td><code>`</code></td><td>Set the selected text to lower case</td><td><code>switch_to_lowercase</code></td></tr>
<tr><td><code>Alt-`</code></td><td>Set the selected text to upper case</td><td><code>switch_to_uppercase</code></td></tr>
<tr><td><code>i</code></td><td>Insert before selection</td><td><code>insert_mode</code></td></tr>
<tr><td><code>a</code></td><td>Insert after selection (append)</td><td><code>append_mode</code></td></tr>
<tr><td><code>I</code></td><td>Insert at the start of the line</td><td><code>insert_at_line_start</code></td></tr>
<tr><td><code>A</code></td><td>Insert at the end of the line</td><td><code>insert_at_line_end</code></td></tr>
<tr><td><code>\</code></td><td>Insert digraphs</td><td><code>insert_digraph</code></td></tr>
<tr><td><code>o</code></td><td>Open new line below selection</td><td><code>open_below</code></td></tr>
<tr><td><code>O</code></td><td>Open new line above selection</td><td><code>open_above</code></td></tr>
<tr><td><code>.</code></td><td>Repeat last insert</td><td>N/A</td></tr>
<tr><td><code>u</code></td><td>Undo change</td><td><code>undo</code></td></tr>
<tr><td><code>U</code></td><td>Redo change</td><td><code>redo</code></td></tr>
<tr><td><code>Alt-u</code></td><td>Move backward in history</td><td><code>earlier</code></td></tr>
<tr><td><code>Alt-U</code></td><td>Move forward in history</td><td><code>later</code></td></tr>
<tr><td><code>y</code></td><td>Yank selection</td><td><code>yank</code></td></tr>
<tr><td><code>p</code></td><td>Paste after selection</td><td><code>paste_after</code></td></tr>
<tr><td><code>P</code></td><td>Paste before selection</td><td><code>paste_before</code></td></tr>
<tr><td><code>&quot;</code> <code>&lt;reg&gt;</code></td><td>Select a register to yank to or paste from</td><td><code>select_register</code></td></tr>
<tr><td><code>&gt;</code></td><td>Indent selection</td><td><code>indent</code></td></tr>
<tr><td><code>&lt;</code></td><td>Unindent selection</td><td><code>unindent</code></td></tr>
<tr><td><code>=</code></td><td>Format selection (currently nonfunctional/disabled) (<strong>LSP</strong>)</td><td><code>format_selections</code></td></tr>
<tr><td><code>d</code></td><td>Delete selection</td><td><code>delete_selection</code></td></tr>
<tr><td><code>Alt-d</code></td><td>Delete selection, without yanking</td><td><code>delete_selection_noyank</code></td></tr>
<tr><td><code>c</code></td><td>Change selection (delete and enter insert mode)</td><td><code>change_selection</code></td></tr>
<tr><td><code>Alt-c</code></td><td>Change selection (delete and enter insert mode, without yanking)</td><td><code>change_selection_noyank</code></td></tr>
<tr><td><code>Ctrl-a</code></td><td>Increment object (number) under cursor</td><td><code>increment</code></td></tr>
<tr><td><code>Ctrl-x</code></td><td>Decrement object (number) under cursor</td><td><code>decrement</code></td></tr>
<tr><td><code>Q</code></td><td>Start/stop macro recording to the selected register (experimental)</td><td><code>record_macro</code></td></tr>
<tr><td><code>q</code></td><td>Play back a recorded macro from the selected register (experimental)</td><td><code>replay_macro</code></td></tr>
</tbody></table>
</div>
<h4 id="shell"><a class="header" href="#shell">Shell</a></h4>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>|</code></td><td>Pipe each selection through shell command, replacing with output</td><td><code>shell_pipe</code></td></tr>
<tr><td><code>Alt-|</code></td><td>Pipe each selection into shell command, ignoring output</td><td><code>shell_pipe_to</code></td></tr>
<tr><td><code>!</code></td><td>Run shell command, inserting output before each selection</td><td><code>shell_insert_output</code></td></tr>
<tr><td><code>Alt-!</code></td><td>Run shell command, appending output after each selection</td><td><code>shell_append_output</code></td></tr>
<tr><td><code>$</code></td><td>Pipe each selection into shell command, keep selections where command returned 0</td><td><code>shell_keep_pipe</code></td></tr>
</tbody></table>
</div>
<h3 id="selection-manipulation"><a class="header" href="#selection-manipulation">Selection manipulation</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>s</code></td><td>Select all regex matches inside selections</td><td><code>select_regex</code></td></tr>
<tr><td><code>S</code></td><td>Split selection into sub selections on regex matches</td><td><code>split_selection</code></td></tr>
<tr><td><code>Alt-s</code></td><td>Split selection on newlines</td><td><code>split_selection_on_newline</code></td></tr>
<tr><td><code>Alt-minus</code></td><td>Merge selections</td><td><code>merge_selections</code></td></tr>
<tr><td><code>Alt-_</code></td><td>Merge consecutive selections</td><td><code>merge_consecutive_selections</code></td></tr>
<tr><td><code>&amp;</code></td><td>Align selection in columns</td><td><code>align_selections</code></td></tr>
<tr><td><code>_</code></td><td>Trim whitespace from the selection</td><td><code>trim_selections</code></td></tr>
<tr><td><code>;</code></td><td>Collapse selection onto a single cursor</td><td><code>collapse_selection</code></td></tr>
<tr><td><code>Alt-;</code></td><td>Flip selection cursor and anchor</td><td><code>flip_selections</code></td></tr>
<tr><td><code>Alt-:</code></td><td>Ensures the selection is in forward direction</td><td><code>ensure_selections_forward</code></td></tr>
<tr><td><code>,</code></td><td>Keep only the primary selection</td><td><code>keep_primary_selection</code></td></tr>
<tr><td><code>Alt-,</code></td><td>Remove the primary selection</td><td><code>remove_primary_selection</code></td></tr>
<tr><td><code>C</code></td><td>Copy selection onto the next line (Add cursor below)</td><td><code>copy_selection_on_next_line</code></td></tr>
<tr><td><code>Alt-C</code></td><td>Copy selection onto the previous line (Add cursor above)</td><td><code>copy_selection_on_prev_line</code></td></tr>
<tr><td><code>(</code></td><td>Rotate main selection backward</td><td><code>rotate_selections_backward</code></td></tr>
<tr><td><code>)</code></td><td>Rotate main selection forward</td><td><code>rotate_selections_forward</code></td></tr>
<tr><td><code>Alt-(</code></td><td>Rotate selection contents backward</td><td><code>rotate_selection_contents_backward</code></td></tr>
<tr><td><code>Alt-)</code></td><td>Rotate selection contents forward</td><td><code>rotate_selection_contents_forward</code></td></tr>
<tr><td><code>%</code></td><td>Select entire file</td><td><code>select_all</code></td></tr>
<tr><td><code>x</code></td><td>Select current line, if already selected, extend to next line</td><td><code>extend_line_below</code></td></tr>
<tr><td><code>X</code></td><td>Extend selection to line bounds (line-wise selection)</td><td><code>extend_to_line_bounds</code></td></tr>
<tr><td><code>Alt-x</code></td><td>Shrink selection to line bounds (line-wise selection)</td><td><code>shrink_to_line_bounds</code></td></tr>
<tr><td><code>J</code></td><td>Join lines inside selection</td><td><code>join_selections</code></td></tr>
<tr><td><code>Alt-J</code></td><td>Join lines inside selection and select the inserted space</td><td><code>join_selections_space</code></td></tr>
<tr><td><code>K</code></td><td>Keep selections matching the regex</td><td><code>keep_selections</code></td></tr>
<tr><td><code>Alt-K</code></td><td>Remove selections matching the regex</td><td><code>remove_selections</code></td></tr>
<tr><td><code>Ctrl-c</code></td><td>Comment/uncomment the selections</td><td><code>toggle_comments</code></td></tr>
<tr><td><code>Alt-o</code>, <code>Alt-up</code></td><td>Expand selection to parent syntax node (<strong>TS</strong>)</td><td><code>expand_selection</code></td></tr>
<tr><td><code>Alt-i</code>, <code>Alt-down</code></td><td>Shrink syntax tree object selection (<strong>TS</strong>)</td><td><code>shrink_selection</code></td></tr>
<tr><td><code>Alt-p</code>, <code>Alt-left</code></td><td>Select previous sibling node in syntax tree (<strong>TS</strong>)</td><td><code>select_prev_sibling</code></td></tr>
<tr><td><code>Alt-n</code>, <code>Alt-right</code></td><td>Select next sibling node in syntax tree (<strong>TS</strong>)</td><td><code>select_next_sibling</code></td></tr>
</tbody></table>
</div>
<h3 id="search"><a class="header" href="#search">Search</a></h3>
<p>Search commands all operate on the <code>/</code> register by default. To use a different register, use <code>&quot;&lt;char&gt;</code>.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>/</code></td><td>Search for regex pattern</td><td><code>search</code></td></tr>
<tr><td><code>?</code></td><td>Search for previous pattern</td><td><code>rsearch</code></td></tr>
<tr><td><code>n</code></td><td>Select next search match</td><td><code>search_next</code></td></tr>
<tr><td><code>N</code></td><td>Select previous search match</td><td><code>search_prev</code></td></tr>
<tr><td><code>*</code></td><td>Use current selection as the search pattern</td><td><code>search_selection</code></td></tr>
</tbody></table>
</div>
<h3 id="minor-modes"><a class="header" href="#minor-modes">Minor modes</a></h3>
<p>These sub-modes are accessible from normal mode and typically switch back to normal mode after a command.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>v</code></td><td>Enter <a href="keymap.html#select--extend-mode">select (extend) mode</a></td><td><code>select_mode</code></td></tr>
<tr><td><code>g</code></td><td>Enter <a href="keymap.html#goto-mode">goto mode</a></td><td>N/A</td></tr>
<tr><td><code>m</code></td><td>Enter <a href="keymap.html#match-mode">match mode</a></td><td>N/A</td></tr>
<tr><td><code>:</code></td><td>Enter command mode</td><td><code>command_mode</code></td></tr>
<tr><td><code>z</code></td><td>Enter <a href="keymap.html#view-mode">view mode</a></td><td>N/A</td></tr>
<tr><td><code>Z</code></td><td>Enter sticky <a href="keymap.html#view-mode">view mode</a></td><td>N/A</td></tr>
<tr><td><code>Ctrl-w</code></td><td>Enter <a href="keymap.html#window-mode">window mode</a></td><td>N/A</td></tr>
<tr><td><code>Space</code></td><td>Enter <a href="keymap.html#space-mode">space mode</a></td><td>N/A</td></tr>
</tbody></table>
</div>
<p>These modes (except command mode) can be configured by
<a href="https://docs.helix-editor.com/remapping.html#minor-modes">remapping keys</a>.</p>
<h4 id="view-mode"><a class="header" href="#view-mode">View mode</a></h4>
<p>Accessed by typing <code>z</code> in <a href="keymap.html#normal-mode">normal mode</a>.</p>
<p>View mode is intended for scrolling and manipulating the view without changing
the selection. The &quot;sticky&quot; variant of this mode (accessed by typing <code>Z</code> in
normal mode) is persistent and can be exited using the escape key. This is
useful when you're simply looking over text and not actively editing it.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>z</code>, <code>c</code></td><td>Vertically center the line</td><td><code>align_view_center</code></td></tr>
<tr><td><code>t</code></td><td>Align the line to the top of the screen</td><td><code>align_view_top</code></td></tr>
<tr><td><code>b</code></td><td>Align the line to the bottom of the screen</td><td><code>align_view_bottom</code></td></tr>
<tr><td><code>m</code></td><td>Align the line to the middle of the screen (horizontally)</td><td><code>align_view_middle</code></td></tr>
<tr><td><code>j</code>, <code>down</code></td><td>Scroll the view downwards</td><td><code>scroll_down</code></td></tr>
<tr><td><code>k</code>, <code>up</code></td><td>Scroll the view upwards</td><td><code>scroll_up</code></td></tr>
<tr><td><code>Ctrl-f</code>, <code>PageDown</code></td><td>Move page down</td><td><code>page_down</code></td></tr>
<tr><td><code>Ctrl-b</code>, <code>PageUp</code></td><td>Move page up</td><td><code>page_up</code></td></tr>
<tr><td><code>Ctrl-d</code></td><td>Move half page down</td><td><code>half_page_down</code></td></tr>
<tr><td><code>Ctrl-u</code></td><td>Move half page up</td><td><code>half_page_up</code></td></tr>
</tbody></table>
</div>
<h4 id="goto-mode"><a class="header" href="#goto-mode">Goto mode</a></h4>
<p>Accessed by typing <code>g</code> in <a href="keymap.html#normal-mode">normal mode</a>.</p>
<p>Jumps to various locations.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>g</code></td><td>Go to line number <code>&lt;n&gt;</code> else start of file</td><td><code>goto_file_start</code></td></tr>
<tr><td><code>e</code></td><td>Go to the end of the file</td><td><code>goto_last_line</code></td></tr>
<tr><td><code>f</code></td><td>Go to files in the selection</td><td><code>goto_file</code></td></tr>
<tr><td><code>h</code></td><td>Go to the start of the line</td><td><code>goto_line_start</code></td></tr>
<tr><td><code>l</code></td><td>Go to the end of the line</td><td><code>goto_line_end</code></td></tr>
<tr><td><code>s</code></td><td>Go to first non-whitespace character of the line</td><td><code>goto_first_nonwhitespace</code></td></tr>
<tr><td><code>t</code></td><td>Go to the top of the screen</td><td><code>goto_window_top</code></td></tr>
<tr><td><code>c</code></td><td>Go to the middle of the screen</td><td><code>goto_window_center</code></td></tr>
<tr><td><code>b</code></td><td>Go to the bottom of the screen</td><td><code>goto_window_bottom</code></td></tr>
<tr><td><code>d</code></td><td>Go to definition (<strong>LSP</strong>)</td><td><code>goto_definition</code></td></tr>
<tr><td><code>y</code></td><td>Go to type definition (<strong>LSP</strong>)</td><td><code>goto_type_definition</code></td></tr>
<tr><td><code>r</code></td><td>Go to references (<strong>LSP</strong>)</td><td><code>goto_reference</code></td></tr>
<tr><td><code>i</code></td><td>Go to implementation (<strong>LSP</strong>)</td><td><code>goto_implementation</code></td></tr>
<tr><td><code>a</code></td><td>Go to the last accessed/alternate file</td><td><code>goto_last_accessed_file</code></td></tr>
<tr><td><code>m</code></td><td>Go to the last modified/alternate file</td><td><code>goto_last_modified_file</code></td></tr>
<tr><td><code>n</code></td><td>Go to next buffer</td><td><code>goto_next_buffer</code></td></tr>
<tr><td><code>p</code></td><td>Go to previous buffer</td><td><code>goto_previous_buffer</code></td></tr>
<tr><td><code>.</code></td><td>Go to last modification in current file</td><td><code>goto_last_modification</code></td></tr>
<tr><td><code>j</code></td><td>Move down textual (instead of visual) line</td><td><code>move_line_down</code></td></tr>
<tr><td><code>k</code></td><td>Move up textual (instead of visual) line</td><td><code>move_line_up</code></td></tr>
</tbody></table>
</div>
<h4 id="match-mode"><a class="header" href="#match-mode">Match mode</a></h4>
<p>Accessed by typing <code>m</code> in <a href="keymap.html#normal-mode">normal mode</a>.</p>
<p>See the relevant section in <a href="./usage.html">Usage</a> for an explanation about
<a href="./usage.html#surround">surround</a> and <a href="./usage.html#navigating-using-tree-sitter-textobjects">textobject</a> usage.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>m</code></td><td>Goto matching bracket (<strong>TS</strong>)</td><td><code>match_brackets</code></td></tr>
<tr><td><code>s</code> <code>&lt;char&gt;</code></td><td>Surround current selection with <code>&lt;char&gt;</code></td><td><code>surround_add</code></td></tr>
<tr><td><code>r</code> <code>&lt;from&gt;&lt;to&gt;</code></td><td>Replace surround character <code>&lt;from&gt;</code> with <code>&lt;to&gt;</code></td><td><code>surround_replace</code></td></tr>
<tr><td><code>d</code> <code>&lt;char&gt;</code></td><td>Delete surround character <code>&lt;char&gt;</code></td><td><code>surround_delete</code></td></tr>
<tr><td><code>a</code> <code>&lt;object&gt;</code></td><td>Select around textobject</td><td><code>select_textobject_around</code></td></tr>
<tr><td><code>i</code> <code>&lt;object&gt;</code></td><td>Select inside textobject</td><td><code>select_textobject_inner</code></td></tr>
</tbody></table>
</div>
<p>TODO: Mappings for selecting syntax nodes (a superset of <code>[</code>).</p>
<h4 id="window-mode"><a class="header" href="#window-mode">Window mode</a></h4>
<p>Accessed by typing <code>Ctrl-w</code> in <a href="keymap.html#normal-mode">normal mode</a>.</p>
<p>This layer is similar to Vim keybindings as Kakoune does not support windows.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>w</code>, <code>Ctrl-w</code></td><td>Switch to next window</td><td><code>rotate_view</code></td></tr>
<tr><td><code>v</code>, <code>Ctrl-v</code></td><td>Vertical right split</td><td><code>vsplit</code></td></tr>
<tr><td><code>s</code>, <code>Ctrl-s</code></td><td>Horizontal bottom split</td><td><code>hsplit</code></td></tr>
<tr><td><code>f</code></td><td>Go to files in the selection in horizontal splits</td><td><code>goto_file</code></td></tr>
<tr><td><code>F</code></td><td>Go to files in the selection in vertical splits</td><td><code>goto_file</code></td></tr>
<tr><td><code>h</code>, <code>Ctrl-h</code>, <code>Left</code></td><td>Move to left split</td><td><code>jump_view_left</code></td></tr>
<tr><td><code>j</code>, <code>Ctrl-j</code>, <code>Down</code></td><td>Move to split below</td><td><code>jump_view_down</code></td></tr>
<tr><td><code>k</code>, <code>Ctrl-k</code>, <code>Up</code></td><td>Move to split above</td><td><code>jump_view_up</code></td></tr>
<tr><td><code>l</code>, <code>Ctrl-l</code>, <code>Right</code></td><td>Move to right split</td><td><code>jump_view_right</code></td></tr>
<tr><td><code>q</code>, <code>Ctrl-q</code></td><td>Close current window</td><td><code>wclose</code></td></tr>
<tr><td><code>o</code>, <code>Ctrl-o</code></td><td>Only keep the current window, closing all the others</td><td><code>wonly</code></td></tr>
<tr><td><code>H</code></td><td>Swap window to the left</td><td><code>swap_view_left</code></td></tr>
<tr><td><code>J</code></td><td>Swap window downwards</td><td><code>swap_view_down</code></td></tr>
<tr><td><code>K</code></td><td>Swap window upwards</td><td><code>swap_view_up</code></td></tr>
<tr><td><code>L</code></td><td>Swap window to the right</td><td><code>swap_view_right</code></td></tr>
</tbody></table>
</div>
<h4 id="space-mode"><a class="header" href="#space-mode">Space mode</a></h4>
<p>Accessed by typing <code>Space</code> in <a href="keymap.html#normal-mode">normal mode</a>.</p>
<p>This layer is a kludge of mappings, mostly pickers.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>f</code></td><td>Open file picker</td><td><code>file_picker</code></td></tr>
<tr><td><code>F</code></td><td>Open file picker at current working directory</td><td><code>file_picker_in_current_directory</code></td></tr>
<tr><td><code>b</code></td><td>Open buffer picker</td><td><code>buffer_picker</code></td></tr>
<tr><td><code>j</code></td><td>Open jumplist picker</td><td><code>jumplist_picker</code></td></tr>
<tr><td><code>g</code></td><td>Debug (experimental)</td><td>N/A</td></tr>
<tr><td><code>k</code></td><td>Show documentation for item under cursor in a <a href="keymap.html#popup">popup</a> (<strong>LSP</strong>)</td><td><code>hover</code></td></tr>
<tr><td><code>s</code></td><td>Open document symbol picker (<strong>LSP</strong>)</td><td><code>symbol_picker</code></td></tr>
<tr><td><code>S</code></td><td>Open workspace symbol picker (<strong>LSP</strong>)</td><td><code>workspace_symbol_picker</code></td></tr>
<tr><td><code>d</code></td><td>Open document diagnostics picker (<strong>LSP</strong>)</td><td><code>diagnostics_picker</code></td></tr>
<tr><td><code>D</code></td><td>Open workspace diagnostics picker (<strong>LSP</strong>)</td><td><code>workspace_diagnostics_picker</code></td></tr>
<tr><td><code>r</code></td><td>Rename symbol (<strong>LSP</strong>)</td><td><code>rename_symbol</code></td></tr>
<tr><td><code>a</code></td><td>Apply code action (<strong>LSP</strong>)</td><td><code>code_action</code></td></tr>
<tr><td><code>h</code></td><td>Select symbol references (<strong>LSP</strong>)</td><td><code>select_references_to_symbol_under_cursor</code></td></tr>
<tr><td><code>'</code></td><td>Open last fuzzy picker</td><td><code>last_picker</code></td></tr>
<tr><td><code>w</code></td><td>Enter <a href="keymap.html#window-mode">window mode</a></td><td>N/A</td></tr>
<tr><td><code>p</code></td><td>Paste system clipboard after selections</td><td><code>paste_clipboard_after</code></td></tr>
<tr><td><code>P</code></td><td>Paste system clipboard before selections</td><td><code>paste_clipboard_before</code></td></tr>
<tr><td><code>y</code></td><td>Yank selections to clipboard</td><td><code>yank_to_clipboard</code></td></tr>
<tr><td><code>Y</code></td><td>Yank main selection to clipboard</td><td><code>yank_main_selection_to_clipboard</code></td></tr>
<tr><td><code>R</code></td><td>Replace selections by clipboard contents</td><td><code>replace_selections_with_clipboard</code></td></tr>
<tr><td><code>/</code></td><td>Global search in workspace folder</td><td><code>global_search</code></td></tr>
<tr><td><code>?</code></td><td>Open command palette</td><td><code>command_palette</code></td></tr>
<tr><td><code>e</code></td><td>Reveal current file in explorer</td><td><code>reveal_current_file</code></td></tr>
</tbody></table>
</div>
<blockquote>
<p>💡 Global search displays results in a fuzzy picker, use <code>Space + '</code> to bring it back up after opening a file.</p>
</blockquote>
<h5 id="popup"><a class="header" href="#popup">Popup</a></h5>
<p>Displays documentation for item under cursor.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th></tr></thead><tbody>
<tr><td><code>Ctrl-u</code></td><td>Scroll up</td></tr>
<tr><td><code>Ctrl-d</code></td><td>Scroll down</td></tr>
</tbody></table>
</div>
<h4 id="unimpaired"><a class="header" href="#unimpaired">Unimpaired</a></h4>
<p>These mappings are in the style of <a href="https://github.com/tpope/vim-unimpaired">vim-unimpaired</a>.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>]d</code></td><td>Go to next diagnostic (<strong>LSP</strong>)</td><td><code>goto_next_diag</code></td></tr>
<tr><td><code>[d</code></td><td>Go to previous diagnostic (<strong>LSP</strong>)</td><td><code>goto_prev_diag</code></td></tr>
<tr><td><code>]D</code></td><td>Go to last diagnostic in document (<strong>LSP</strong>)</td><td><code>goto_last_diag</code></td></tr>
<tr><td><code>[D</code></td><td>Go to first diagnostic in document (<strong>LSP</strong>)</td><td><code>goto_first_diag</code></td></tr>
<tr><td><code>]f</code></td><td>Go to next function (<strong>TS</strong>)</td><td><code>goto_next_function</code></td></tr>
<tr><td><code>[f</code></td><td>Go to previous function (<strong>TS</strong>)</td><td><code>goto_prev_function</code></td></tr>
<tr><td><code>]t</code></td><td>Go to next type definition (<strong>TS</strong>)</td><td><code>goto_next_class</code></td></tr>
<tr><td><code>[t</code></td><td>Go to previous type definition (<strong>TS</strong>)</td><td><code>goto_prev_class</code></td></tr>
<tr><td><code>]a</code></td><td>Go to next argument/parameter (<strong>TS</strong>)</td><td><code>goto_next_parameter</code></td></tr>
<tr><td><code>[a</code></td><td>Go to previous argument/parameter (<strong>TS</strong>)</td><td><code>goto_prev_parameter</code></td></tr>
<tr><td><code>]c</code></td><td>Go to next comment (<strong>TS</strong>)</td><td><code>goto_next_comment</code></td></tr>
<tr><td><code>[c</code></td><td>Go to previous comment (<strong>TS</strong>)</td><td><code>goto_prev_comment</code></td></tr>
<tr><td><code>]T</code></td><td>Go to next test (<strong>TS</strong>)</td><td><code>goto_next_test</code></td></tr>
<tr><td><code>[T</code></td><td>Go to previous test (<strong>TS</strong>)</td><td><code>goto_prev_test</code></td></tr>
<tr><td><code>]p</code></td><td>Go to next paragraph</td><td><code>goto_next_paragraph</code></td></tr>
<tr><td><code>[p</code></td><td>Go to previous paragraph</td><td><code>goto_prev_paragraph</code></td></tr>
<tr><td><code>]g</code></td><td>Go to next change</td><td><code>goto_next_change</code></td></tr>
<tr><td><code>[g</code></td><td>Go to previous change</td><td><code>goto_prev_change</code></td></tr>
<tr><td><code>]G</code></td><td>Go to last change</td><td><code>goto_last_change</code></td></tr>
<tr><td><code>[G</code></td><td>Go to first change</td><td><code>goto_first_change</code></td></tr>
<tr><td><code>]Space</code></td><td>Add newline below</td><td><code>add_newline_below</code></td></tr>
<tr><td><code>[Space</code></td><td>Add newline above</td><td><code>add_newline_above</code></td></tr>
</tbody></table>
</div>
<h2 id="insert-mode"><a class="header" href="#insert-mode">Insert mode</a></h2>
<p>Accessed by typing <code>i</code> in <a href="keymap.html#normal-mode">normal mode</a>.</p>
<p>Insert mode bindings are minimal by default. Helix is designed to
be a modal editor, and this is reflected in the user experience and internal
mechanics. Changes to the text are only saved for undos when
escaping from insert mode to normal mode.</p>
<blockquote>
<p>💡 New users are strongly encouraged to learn the modal editing paradigm
to get the smoothest experience.</p>
</blockquote>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>Escape</code></td><td>Switch to normal mode</td><td><code>normal_mode</code></td></tr>
<tr><td><code>Ctrl-s</code></td><td>Commit undo checkpoint</td><td><code>commit_undo_checkpoint</code></td></tr>
<tr><td><code>Ctrl-x</code></td><td>Autocomplete</td><td><code>completion</code></td></tr>
<tr><td><code>Ctrl-r</code></td><td>Insert a register content</td><td><code>insert_register</code></td></tr>
<tr><td><code>Ctrl-w</code>, <code>Alt-Backspace</code></td><td>Delete previous word</td><td><code>delete_word_backward</code></td></tr>
<tr><td><code>Alt-d</code>, <code>Alt-Delete</code></td><td>Delete next word</td><td><code>delete_word_forward</code></td></tr>
<tr><td><code>Ctrl-u</code></td><td>Delete to start of line</td><td><code>kill_to_line_start</code></td></tr>
<tr><td><code>Ctrl-k</code></td><td>Delete to end of line</td><td><code>kill_to_line_end</code></td></tr>
<tr><td><code>Ctrl-h</code>, <code>Backspace</code>, <code>Shift-Backspace</code></td><td>Delete previous char</td><td><code>delete_char_backward</code></td></tr>
<tr><td><code>Ctrl-d</code>, <code>Delete</code></td><td>Delete next char</td><td><code>delete_char_forward</code></td></tr>
<tr><td><code>Ctrl-j</code>, <code>Enter</code></td><td>Insert new line</td><td><code>insert_newline</code></td></tr>
</tbody></table>
</div>
<p>These keys are not recommended, but are included for new users less familiar
with modal editors.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Command</th></tr></thead><tbody>
<tr><td><code>Up</code></td><td>Move to previous line</td><td><code>move_line_up</code></td></tr>
<tr><td><code>Down</code></td><td>Move to next line</td><td><code>move_line_down</code></td></tr>
<tr><td><code>Left</code></td><td>Backward a char</td><td><code>move_char_left</code></td></tr>
<tr><td><code>Right</code></td><td>Forward a char</td><td><code>move_char_right</code></td></tr>
<tr><td><code>PageUp</code></td><td>Move one page up</td><td><code>page_up</code></td></tr>
<tr><td><code>PageDown</code></td><td>Move one page down</td><td><code>page_down</code></td></tr>
<tr><td><code>Home</code></td><td>Move to line start</td><td><code>goto_line_start</code></td></tr>
<tr><td><code>End</code></td><td>Move to line end</td><td><code>goto_line_end_newline</code></td></tr>
</tbody></table>
</div>
<p>As you become more comfortable with modal editing, you may want to disable some
insert mode bindings. You can do this by editing your <code>config.toml</code> file.</p>
<pre><code class="language-toml">[keys.insert]
up = &quot;no_op&quot;
down = &quot;no_op&quot;
left = &quot;no_op&quot;
right = &quot;no_op&quot;
pageup = &quot;no_op&quot;
pagedown = &quot;no_op&quot;
home = &quot;no_op&quot;
end = &quot;no_op&quot;
</code></pre>
<h2 id="select--extend-mode"><a class="header" href="#select--extend-mode">Select / extend mode</a></h2>
<p>Accessed by typing <code>v</code> in <a href="keymap.html#normal-mode">normal mode</a>.</p>
<p>Select mode echoes Normal mode, but changes any movements to extend
selections rather than replace them. Goto motions are also changed to
extend, so that <code>vgl</code>, for example, extends the selection to the end of
the line.</p>
<p>Search is also affected. By default, <code>n</code> and <code>N</code> will remove the current
selection and select the next instance of the search term. Toggling this
mode before pressing <code>n</code> or <code>N</code> makes it possible to keep the current
selection. Toggling it on and off during your iterative searching allows
you to selectively add search terms to your selections.</p>
<h2 id="picker"><a class="header" href="#picker">Picker</a></h2>
<p>Keys to use within picker. Remapping currently not supported.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th></tr></thead><tbody>
<tr><td><code>Shift-Tab</code>, <code>Up</code>, <code>Ctrl-p</code></td><td>Previous entry</td></tr>
<tr><td><code>Tab</code>, <code>Down</code>, <code>Ctrl-n</code></td><td>Next entry</td></tr>
<tr><td><code>PageUp</code>, <code>Ctrl-u</code></td><td>Page up</td></tr>
<tr><td><code>PageDown</code>, <code>Ctrl-d</code></td><td>Page down</td></tr>
<tr><td><code>Home</code></td><td>Go to first entry</td></tr>
<tr><td><code>End</code></td><td>Go to last entry</td></tr>
<tr><td><code>Enter</code></td><td>Open selected</td></tr>
<tr><td><code>Alt-Enter</code></td><td>Open selected in the background without closing the picker</td></tr>
<tr><td><code>Ctrl-s</code></td><td>Open horizontally</td></tr>
<tr><td><code>Ctrl-v</code></td><td>Open vertically</td></tr>
<tr><td><code>Ctrl-t</code></td><td>Toggle preview</td></tr>
<tr><td><code>Escape</code>, <code>Ctrl-c</code></td><td>Close picker</td></tr>
</tbody></table>
</div>
<h2 id="prompt"><a class="header" href="#prompt">Prompt</a></h2>
<p>Keys to use within prompt, Remapping currently not supported.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th></tr></thead><tbody>
<tr><td><code>Escape</code>, <code>Ctrl-c</code></td><td>Close prompt</td></tr>
<tr><td><code>Alt-b</code>, <code>Ctrl-Left</code></td><td>Backward a word</td></tr>
<tr><td><code>Ctrl-b</code>, <code>Left</code></td><td>Backward a char</td></tr>
<tr><td><code>Alt-f</code>, <code>Ctrl-Right</code></td><td>Forward a word</td></tr>
<tr><td><code>Ctrl-f</code>, <code>Right</code></td><td>Forward a char</td></tr>
<tr><td><code>Ctrl-e</code>, <code>End</code></td><td>Move prompt end</td></tr>
<tr><td><code>Ctrl-a</code>, <code>Home</code></td><td>Move prompt start</td></tr>
<tr><td><code>Ctrl-w</code>, <code>Alt-Backspace</code>, <code>Ctrl-Backspace</code></td><td>Delete previous word</td></tr>
<tr><td><code>Alt-d</code>, <code>Alt-Delete</code>, <code>Ctrl-Delete</code></td><td>Delete next word</td></tr>
<tr><td><code>Ctrl-u</code></td><td>Delete to start of line</td></tr>
<tr><td><code>Ctrl-k</code></td><td>Delete to end of line</td></tr>
<tr><td><code>Backspace</code>, <code>Ctrl-h</code>, <code>Shift-Backspace</code></td><td>Delete previous char</td></tr>
<tr><td><code>Delete</code>, <code>Ctrl-d</code></td><td>Delete next char</td></tr>
<tr><td><code>Ctrl-s</code></td><td>Insert a word under doc cursor, may be changed to Ctrl-r Ctrl-w later</td></tr>
<tr><td><code>Ctrl-p</code>, <code>Up</code></td><td>Select previous history</td></tr>
<tr><td><code>Ctrl-n</code>, <code>Down</code></td><td>Select next history</td></tr>
<tr><td><code>Ctrl-r</code></td><td>Insert the content of the register selected by following input char</td></tr>
<tr><td><code>Tab</code></td><td>Select next completion item</td></tr>
<tr><td><code>BackTab</code></td><td>Select previous completion item</td></tr>
<tr><td><code>Enter</code></td><td>Open selected</td></tr>
</tbody></table>
</div>
<h2 id="file-explorer"><a class="header" href="#file-explorer">File explorer</a></h2>
<p>Press <code>?</code> to see keymaps. Remapping currently not supported.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="commands"><a class="header" href="#commands">Commands</a></h1>
<p>Command mode can be activated by pressing <code>:</code>. The built-in commands are:</p>
<div class="table-wrapper"><table><thead><tr><th>Name</th><th>Description</th></tr></thead><tbody>
<tr><td><code>:quit</code>, <code>:q</code></td><td>Close the current view.</td></tr>
<tr><td><code>:quit!</code>, <code>:q!</code></td><td>Force close the current view, ignoring unsaved changes.</td></tr>
<tr><td><code>:open</code>, <code>:o</code></td><td>Open a file from disk into the current view.</td></tr>
<tr><td><code>:buffer-close</code>, <code>:bc</code>, <code>:bclose</code></td><td>Close the current buffer.</td></tr>
<tr><td><code>:buffer-close!</code>, <code>:bc!</code>, <code>:bclose!</code></td><td>Close the current buffer forcefully, ignoring unsaved changes.</td></tr>
<tr><td><code>:buffer-close-others</code>, <code>:bco</code>, <code>:bcloseother</code></td><td>Close all buffers but the currently focused one.</td></tr>
<tr><td><code>:buffer-close-others!</code>, <code>:bco!</code>, <code>:bcloseother!</code></td><td>Force close all buffers but the currently focused one.</td></tr>
<tr><td><code>:buffer-close-all</code>, <code>:bca</code>, <code>:bcloseall</code></td><td>Close all buffers without quitting.</td></tr>
<tr><td><code>:buffer-close-all!</code>, <code>:bca!</code>, <code>:bcloseall!</code></td><td>Force close all buffers ignoring unsaved changes without quitting.</td></tr>
<tr><td><code>:buffer-next</code>, <code>:bn</code>, <code>:bnext</code></td><td>Goto next buffer.</td></tr>
<tr><td><code>:buffer-previous</code>, <code>:bp</code>, <code>:bprev</code></td><td>Goto previous buffer.</td></tr>
<tr><td><code>:write</code>, <code>:w</code></td><td>Write changes to disk. Accepts an optional path (:write some/path.txt)</td></tr>
<tr><td><code>:write!</code>, <code>:w!</code></td><td>Force write changes to disk creating necessary subdirectories. Accepts an optional path (:write! some/path.txt)</td></tr>
<tr><td><code>:write-buffer-close</code>, <code>:wbc</code></td><td>Write changes to disk and closes the buffer. Accepts an optional path (:write-buffer-close some/path.txt)</td></tr>
<tr><td><code>:write-buffer-close!</code>, <code>:wbc!</code></td><td>Force write changes to disk creating necessary subdirectories and closes the buffer. Accepts an optional path (:write-buffer-close! some/path.txt)</td></tr>
<tr><td><code>:new</code>, <code>:n</code></td><td>Create a new scratch buffer.</td></tr>
<tr><td><code>:format</code>, <code>:fmt</code></td><td>Format the file using the LSP formatter.</td></tr>
<tr><td><code>:indent-style</code></td><td>Set the indentation style for editing. ('t' for tabs or 1-8 for number of spaces.)</td></tr>
<tr><td><code>:line-ending</code></td><td>Set the document's default line ending. Options: crlf, lf.</td></tr>
<tr><td><code>:earlier</code>, <code>:ear</code></td><td>Jump back to an earlier point in edit history. Accepts a number of steps or a time span.</td></tr>
<tr><td><code>:later</code>, <code>:lat</code></td><td>Jump to a later point in edit history. Accepts a number of steps or a time span.</td></tr>
<tr><td><code>:write-quit</code>, <code>:wq</code>, <code>:x</code></td><td>Write changes to disk and close the current view. Accepts an optional path (:wq some/path.txt)</td></tr>
<tr><td><code>:write-quit!</code>, <code>:wq!</code>, <code>:x!</code></td><td>Write changes to disk and close the current view forcefully. Accepts an optional path (:wq! some/path.txt)</td></tr>
<tr><td><code>:write-all</code>, <code>:wa</code></td><td>Write changes from all buffers to disk.</td></tr>
<tr><td><code>:write-all!</code>, <code>:wa!</code></td><td>Forcefully write changes from all buffers to disk creating necessary subdirectories.</td></tr>
<tr><td><code>:write-quit-all</code>, <code>:wqa</code>, <code>:xa</code></td><td>Write changes from all buffers to disk and close all views.</td></tr>
<tr><td><code>:write-quit-all!</code>, <code>:wqa!</code>, <code>:xa!</code></td><td>Write changes from all buffers to disk and close all views forcefully (ignoring unsaved changes).</td></tr>
<tr><td><code>:quit-all</code>, <code>:qa</code></td><td>Close all views.</td></tr>
<tr><td><code>:quit-all!</code>, <code>:qa!</code></td><td>Force close all views ignoring unsaved changes.</td></tr>
<tr><td><code>:cquit</code>, <code>:cq</code></td><td>Quit with exit code (default 1). Accepts an optional integer exit code (:cq 2).</td></tr>
<tr><td><code>:cquit!</code>, <code>:cq!</code></td><td>Force quit with exit code (default 1) ignoring unsaved changes. Accepts an optional integer exit code (:cq! 2).</td></tr>
<tr><td><code>:theme</code></td><td>Change the editor theme (show current theme if no name specified).</td></tr>
<tr><td><code>:yank-join</code></td><td>Yank joined selections. A separator can be provided as first argument. Default value is newline.</td></tr>
<tr><td><code>:clipboard-yank</code></td><td>Yank main selection into system clipboard.</td></tr>
<tr><td><code>:clipboard-yank-join</code></td><td>Yank joined selections into system clipboard. A separator can be provided as first argument. Default value is newline.</td></tr>
<tr><td><code>:primary-clipboard-yank</code></td><td>Yank main selection into system primary clipboard.</td></tr>
<tr><td><code>:primary-clipboard-yank-join</code></td><td>Yank joined selections into system primary clipboard. A separator can be provided as first argument. Default value is newline.</td></tr>
<tr><td><code>:clipboard-paste-after</code></td><td>Paste system clipboard after selections.</td></tr>
<tr><td><code>:clipboard-paste-before</code></td><td>Paste system clipboard before selections.</td></tr>
<tr><td><code>:clipboard-paste-replace</code></td><td>Replace selections with content of system clipboard.</td></tr>
<tr><td><code>:primary-clipboard-paste-after</code></td><td>Paste primary clipboard after selections.</td></tr>
<tr><td><code>:primary-clipboard-paste-before</code></td><td>Paste primary clipboard before selections.</td></tr>
<tr><td><code>:primary-clipboard-paste-replace</code></td><td>Replace selections with content of system primary clipboard.</td></tr>
<tr><td><code>:show-clipboard-provider</code></td><td>Show clipboard provider name in status bar.</td></tr>
<tr><td><code>:change-current-directory</code>, <code>:cd</code></td><td>Change the current working directory.</td></tr>
<tr><td><code>:show-directory</code>, <code>:pwd</code></td><td>Show the current working directory.</td></tr>
<tr><td><code>:encoding</code></td><td>Set encoding. Based on <code>https://encoding.spec.whatwg.org</code>.</td></tr>
<tr><td><code>:character-info</code>, <code>:char</code></td><td>Get info about the character under the primary cursor.</td></tr>
<tr><td><code>:reload</code>, <code>:rl</code></td><td>Discard changes and reload from the source file.</td></tr>
<tr><td><code>:reload-all</code>, <code>:rla</code></td><td>Discard changes and reload all documents from the source files.</td></tr>
<tr><td><code>:update</code>, <code>:u</code></td><td>Write changes only if the file has been modified.</td></tr>
<tr><td><code>:lsp-workspace-command</code></td><td>Open workspace command picker</td></tr>
<tr><td><code>:lsp-restart</code></td><td>Restarts the language servers used by the current doc</td></tr>
<tr><td><code>:lsp-stop</code></td><td>Stops the language servers that are used by the current doc</td></tr>
<tr><td><code>:tree-sitter-scopes</code></td><td>Display tree sitter scopes, primarily for theming and development.</td></tr>
<tr><td><code>:tree-sitter-highlight-name</code></td><td>Display name of tree-sitter highlight scope under the cursor.</td></tr>
<tr><td><code>:debug-start</code>, <code>:dbg</code></td><td>Start a debug session from a given template with given parameters.</td></tr>
<tr><td><code>:debug-remote</code>, <code>:dbg-tcp</code></td><td>Connect to a debug adapter by TCP address and start a debugging session from a given template with given parameters.</td></tr>
<tr><td><code>:debug-eval</code></td><td>Evaluate expression in current debug context.</td></tr>
<tr><td><code>:vsplit</code>, <code>:vs</code></td><td>Open the file in a vertical split.</td></tr>
<tr><td><code>:vsplit-new</code>, <code>:vnew</code></td><td>Open a scratch buffer in a vertical split.</td></tr>
<tr><td><code>:hsplit</code>, <code>:hs</code>, <code>:sp</code></td><td>Open the file in a horizontal split.</td></tr>
<tr><td><code>:hsplit-new</code>, <code>:hnew</code></td><td>Open a scratch buffer in a horizontal split.</td></tr>
<tr><td><code>:tutor</code></td><td>Open the tutorial.</td></tr>
<tr><td><code>:goto</code>, <code>:g</code></td><td>Goto line number.</td></tr>
<tr><td><code>:set-language</code>, <code>:lang</code></td><td>Set the language of current buffer (show current language if no value specified).</td></tr>
<tr><td><code>:set-option</code>, <code>:set</code></td><td>Set a config option at runtime.<br>For example to disable smart case search, use <code>:set search.smart-case false</code>.</td></tr>
<tr><td><code>:toggle-option</code>, <code>:toggle</code></td><td>Toggle a boolean config option at runtime.<br>For example to toggle smart case search, use <code>:toggle search.smart-case</code>.</td></tr>
<tr><td><code>:get-option</code>, <code>:get</code></td><td>Get the current value of a config option.</td></tr>
<tr><td><code>:sort</code></td><td>Sort ranges in selection.</td></tr>
<tr><td><code>:rsort</code></td><td>Sort ranges in selection in reverse order.</td></tr>
<tr><td><code>:reflow</code></td><td>Hard-wrap the current selection of lines to a given width.</td></tr>
<tr><td><code>:tree-sitter-subtree</code>, <code>:ts-subtree</code></td><td>Display tree sitter subtree under cursor, primarily for debugging queries.</td></tr>
<tr><td><code>:config-reload</code></td><td>Refresh user config.</td></tr>
<tr><td><code>:config-open</code></td><td>Open the user config.toml file.</td></tr>
<tr><td><code>:config-open-workspace</code></td><td>Open the workspace config.toml file.</td></tr>
<tr><td><code>:log-open</code></td><td>Open the helix log file.</td></tr>
<tr><td><code>:insert-output</code></td><td>Run shell command, inserting output before each selection.</td></tr>
<tr><td><code>:append-output</code></td><td>Run shell command, appending output after each selection.</td></tr>
<tr><td><code>:pipe</code></td><td>Pipe each selection to the shell command.</td></tr>
<tr><td><code>:pipe-to</code></td><td>Pipe each selection to the shell command, ignoring output.</td></tr>
<tr><td><code>:run-shell-command</code>, <code>:sh</code></td><td>Run a shell command</td></tr>
<tr><td><code>:reset-diff-change</code>, <code>:diffget</code>, <code>:diffg</code></td><td>Reset the diff change at the cursor position.</td></tr>
<tr><td><code>:clear-register</code></td><td>Clear given register. If no argument is provided, clear all registers.</td></tr>
<tr><td><code>:redraw</code></td><td>Clear and re-render the whole UI</td></tr>
</tbody></table>
</div><div style="break-before: page; page-break-before: always;"></div><h1 id="language-support"><a class="header" href="#language-support">Language Support</a></h1>
<p>The following languages and Language Servers are supported. To use
Language Server features, you must first <a href="https://github.com/helix-editor/helix/wiki/How-to-install-the-default-language-servers">install</a> the
appropriate Language Server.</p>
<p>You can check the language support in your installed helix version with <code>hx --health</code>.</p>
<p>Also see the <a href="./languages.html">Language Configuration</a> docs and the <a href="./guides/adding_languages.html">Adding
Languages</a> guide for more language configuration information.</p>
<div class="table-wrapper"><table><thead><tr><th>Language</th><th>Syntax Highlighting</th><th>Treesitter Textobjects</th><th>Auto Indent</th><th>Rainbow Brackets</th><th>Default LSP</th></tr></thead><tbody>
<tr><td>astro</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>awk</td><td></td><td></td><td></td><td></td><td><code>awk-language-server</code></td></tr>
<tr><td>bash</td><td></td><td></td><td></td><td></td><td><code>bash-language-server</code></td></tr>
<tr><td>bass</td><td></td><td></td><td></td><td></td><td><code>bass</code></td></tr>
<tr><td>beancount</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>bibtex</td><td></td><td></td><td></td><td></td><td><code>texlab</code></td></tr>
<tr><td>bicep</td><td></td><td></td><td></td><td></td><td><code>bicep-langserver</code></td></tr>
<tr><td>blueprint</td><td></td><td></td><td></td><td></td><td><code>blueprint-compiler</code></td></tr>
<tr><td>c</td><td></td><td></td><td></td><td></td><td><code>clangd</code></td></tr>
<tr><td>c-sharp</td><td></td><td></td><td></td><td></td><td><code>OmniSharp</code></td></tr>
<tr><td>cabal</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>cairo</td><td></td><td></td><td></td><td></td><td><code>cairo-language-server</code></td></tr>
<tr><td>capnp</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>clojure</td><td></td><td></td><td></td><td></td><td><code>clojure-lsp</code></td></tr>
<tr><td>cmake</td><td></td><td></td><td></td><td></td><td><code>cmake-language-server</code></td></tr>
<tr><td>comment</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>common-lisp</td><td></td><td></td><td></td><td></td><td><code>cl-lsp</code></td></tr>
<tr><td>cpon</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>cpp</td><td></td><td></td><td></td><td></td><td><code>clangd</code></td></tr>
<tr><td>crystal</td><td></td><td></td><td></td><td></td><td><code>crystalline</code></td></tr>
<tr><td>css</td><td></td><td></td><td></td><td></td><td><code>vscode-css-language-server</code></td></tr>
<tr><td>cue</td><td></td><td></td><td></td><td></td><td><code>cuelsp</code></td></tr>
<tr><td>d</td><td></td><td></td><td></td><td></td><td><code>serve-d</code></td></tr>
<tr><td>dart</td><td></td><td></td><td></td><td></td><td><code>dart</code></td></tr>
<tr><td>devicetree</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>dhall</td><td></td><td></td><td></td><td></td><td><code>dhall-lsp-server</code></td></tr>
<tr><td>diff</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>dockerfile</td><td></td><td></td><td></td><td></td><td><code>docker-langserver</code></td></tr>
<tr><td>dot</td><td></td><td></td><td></td><td></td><td><code>dot-language-server</code></td></tr>
<tr><td>dtd</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>edoc</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>eex</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>ejs</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>elixir</td><td></td><td></td><td></td><td></td><td><code>elixir-ls</code></td></tr>
<tr><td>elm</td><td></td><td></td><td></td><td></td><td><code>elm-language-server</code></td></tr>
<tr><td>elvish</td><td></td><td></td><td></td><td></td><td><code>elvish</code></td></tr>
<tr><td>env</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>erb</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>erlang</td><td></td><td></td><td></td><td></td><td><code>erlang_ls</code></td></tr>
<tr><td>esdl</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>fish</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>forth</td><td></td><td></td><td></td><td></td><td><code>forth-lsp</code></td></tr>
<tr><td>fortran</td><td></td><td></td><td></td><td></td><td><code>fortls</code></td></tr>
<tr><td>fsharp</td><td></td><td></td><td></td><td></td><td><code>fsautocomplete</code></td></tr>
<tr><td>gas</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>gdscript</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>gemini</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>git-attributes</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>git-commit</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>git-config</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>git-ignore</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>git-rebase</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>gleam</td><td></td><td></td><td></td><td></td><td><code>gleam</code></td></tr>
<tr><td>glsl</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>go</td><td></td><td></td><td></td><td></td><td><code>gopls</code></td></tr>
<tr><td>godot-resource</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>gomod</td><td></td><td></td><td></td><td></td><td><code>gopls</code></td></tr>
<tr><td>gotmpl</td><td></td><td></td><td></td><td></td><td><code>gopls</code></td></tr>
<tr><td>gowork</td><td></td><td></td><td></td><td></td><td><code>gopls</code></td></tr>
<tr><td>graphql</td><td></td><td></td><td></td><td></td><td><code>graphql-lsp</code></td></tr>
<tr><td>hare</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>haskell</td><td></td><td></td><td></td><td></td><td><code>haskell-language-server-wrapper</code></td></tr>
<tr><td>haskell-persistent</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>hcl</td><td></td><td></td><td></td><td></td><td><code>terraform-ls</code></td></tr>
<tr><td>heex</td><td></td><td></td><td></td><td></td><td><code>elixir-ls</code></td></tr>
<tr><td>hosts</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>html</td><td></td><td></td><td></td><td></td><td><code>vscode-html-language-server</code></td></tr>
<tr><td>hurl</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>idris</td><td></td><td></td><td></td><td></td><td><code>idris2-lsp</code></td></tr>
<tr><td>iex</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>ini</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>java</td><td></td><td></td><td></td><td></td><td><code>jdtls</code></td></tr>
<tr><td>javascript</td><td></td><td></td><td></td><td></td><td><code>typescript-language-server</code></td></tr>
<tr><td>jinja</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>jsdoc</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>json</td><td></td><td></td><td></td><td></td><td><code>vscode-json-language-server</code></td></tr>
<tr><td>json5</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>jsonnet</td><td></td><td></td><td></td><td></td><td><code>jsonnet-language-server</code></td></tr>
<tr><td>jsx</td><td></td><td></td><td></td><td></td><td><code>typescript-language-server</code></td></tr>
<tr><td>julia</td><td></td><td></td><td></td><td></td><td><code>julia</code></td></tr>
<tr><td>just</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>kdl</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>kotlin</td><td></td><td></td><td></td><td></td><td><code>kotlin-language-server</code></td></tr>
<tr><td>latex</td><td></td><td></td><td></td><td></td><td><code>texlab</code></td></tr>
<tr><td>lean</td><td></td><td></td><td></td><td></td><td><code>lean</code></td></tr>
<tr><td>ledger</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>llvm</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>llvm-mir</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>llvm-mir-yaml</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>lua</td><td></td><td></td><td></td><td></td><td><code>lua-language-server</code></td></tr>
<tr><td>make</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>markdoc</td><td></td><td></td><td></td><td></td><td><code>markdoc-ls</code></td></tr>
<tr><td>markdown</td><td></td><td></td><td></td><td></td><td><code>marksman</code></td></tr>
<tr><td>markdown.inline</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>matlab</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>mermaid</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>meson</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>mint</td><td></td><td></td><td></td><td></td><td><code>mint</code></td></tr>
<tr><td>msbuild</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>nasm</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>nickel</td><td></td><td></td><td></td><td></td><td><code>nls</code></td></tr>
<tr><td>nim</td><td></td><td></td><td></td><td></td><td><code>nimlangserver</code></td></tr>
<tr><td>nix</td><td></td><td></td><td></td><td></td><td><code>nil</code></td></tr>
<tr><td>nu</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>nunjucks</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>ocaml</td><td></td><td></td><td></td><td></td><td><code>ocamllsp</code></td></tr>
<tr><td>ocaml-interface</td><td></td><td></td><td></td><td></td><td><code>ocamllsp</code></td></tr>
<tr><td>odin</td><td></td><td></td><td></td><td></td><td><code>ols</code></td></tr>
<tr><td>opencl</td><td></td><td></td><td></td><td></td><td><code>clangd</code></td></tr>
<tr><td>openscad</td><td></td><td></td><td></td><td></td><td><code>openscad-lsp</code></td></tr>
<tr><td>org</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>pascal</td><td></td><td></td><td></td><td></td><td><code>pasls</code></td></tr>
<tr><td>passwd</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>pem</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>perl</td><td></td><td></td><td></td><td></td><td><code>perlnavigator</code></td></tr>
<tr><td>php</td><td></td><td></td><td></td><td></td><td><code>intelephense</code></td></tr>
<tr><td>po</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>pod</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>ponylang</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>prisma</td><td></td><td></td><td></td><td></td><td><code>prisma-language-server</code></td></tr>
<tr><td>prolog</td><td></td><td></td><td></td><td></td><td><code>swipl</code></td></tr>
<tr><td>protobuf</td><td></td><td></td><td></td><td></td><td><code>bufls</code>, <code>pb</code></td></tr>
<tr><td>prql</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>purescript</td><td></td><td></td><td></td><td></td><td><code>purescript-language-server</code></td></tr>
<tr><td>python</td><td></td><td></td><td></td><td></td><td><code>pylsp</code></td></tr>
<tr><td>qml</td><td></td><td></td><td></td><td></td><td><code>qmlls</code></td></tr>
<tr><td>r</td><td></td><td></td><td></td><td></td><td><code>R</code></td></tr>
<tr><td>racket</td><td></td><td></td><td></td><td></td><td><code>racket</code></td></tr>
<tr><td>regex</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>rego</td><td></td><td></td><td></td><td></td><td><code>regols</code></td></tr>
<tr><td>rescript</td><td></td><td></td><td></td><td></td><td><code>rescript-language-server</code></td></tr>
<tr><td>rmarkdown</td><td></td><td></td><td></td><td></td><td><code>R</code></td></tr>
<tr><td>robot</td><td></td><td></td><td></td><td></td><td><code>robotframework_ls</code></td></tr>
<tr><td>ron</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>rst</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>ruby</td><td></td><td></td><td></td><td></td><td><code>solargraph</code></td></tr>
<tr><td>rust</td><td></td><td></td><td></td><td></td><td><code>rust-analyzer</code></td></tr>
<tr><td>sage</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>scala</td><td></td><td></td><td></td><td></td><td><code>metals</code></td></tr>
<tr><td>scheme</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>scss</td><td></td><td></td><td></td><td></td><td><code>vscode-css-language-server</code></td></tr>
<tr><td>slint</td><td></td><td></td><td></td><td></td><td><code>slint-lsp</code></td></tr>
<tr><td>smithy</td><td></td><td></td><td></td><td></td><td><code>cs</code></td></tr>
<tr><td>sml</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>solidity</td><td></td><td></td><td></td><td></td><td><code>solc</code></td></tr>
<tr><td>sql</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>sshclientconfig</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>starlark</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>strace</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>svelte</td><td></td><td></td><td></td><td></td><td><code>svelteserver</code></td></tr>
<tr><td>sway</td><td></td><td></td><td></td><td></td><td><code>forc</code></td></tr>
<tr><td>swift</td><td></td><td></td><td></td><td></td><td><code>sourcekit-lsp</code></td></tr>
<tr><td>t32</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>tablegen</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>task</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>templ</td><td></td><td></td><td></td><td></td><td><code>templ</code></td></tr>
<tr><td>tfvars</td><td></td><td></td><td></td><td></td><td><code>terraform-ls</code></td></tr>
<tr><td>todotxt</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>toml</td><td></td><td></td><td></td><td></td><td><code>taplo</code></td></tr>
<tr><td>tsq</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>tsx</td><td></td><td></td><td></td><td></td><td><code>typescript-language-server</code></td></tr>
<tr><td>twig</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>typescript</td><td></td><td></td><td></td><td></td><td><code>typescript-language-server</code></td></tr>
<tr><td>ungrammar</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>unison</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>uxntal</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>v</td><td></td><td></td><td></td><td></td><td><code>v-analyzer</code></td></tr>
<tr><td>vala</td><td></td><td></td><td></td><td></td><td><code>vala-language-server</code></td></tr>
<tr><td>verilog</td><td></td><td></td><td></td><td></td><td><code>svlangserver</code></td></tr>
<tr><td>vhdl</td><td></td><td></td><td></td><td></td><td><code>vhdl_ls</code></td></tr>
<tr><td>vhs</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>vue</td><td></td><td></td><td></td><td></td><td><code>vue-language-server</code></td></tr>
<tr><td>wast</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>wat</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>webc</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>wgsl</td><td></td><td></td><td></td><td></td><td><code>wgsl_analyzer</code></td></tr>
<tr><td>wit</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>wren</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>xit</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>xml</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>yaml</td><td></td><td></td><td></td><td></td><td><code>yaml-language-server</code>, <code>ansible-language-server</code></td></tr>
<tr><td>yuck</td><td></td><td></td><td></td><td></td><td></td></tr>
<tr><td>zig</td><td></td><td></td><td></td><td></td><td><code>zls</code></td></tr>
</tbody></table>
</div><div style="break-before: page; page-break-before: always;"></div><h1 id="migrating-from-vim"><a class="header" href="#migrating-from-vim">Migrating from Vim</a></h1>
<p>Helix's editing model is strongly inspired from Vim and Kakoune, and a notable
difference from Vim (and the most striking similarity to Kakoune) is that Helix
follows the <code>selection → action</code> model. This means that whatever you are
going to act on (a word, a paragraph, a line, etc.) is selected first and the
action itself (delete, change, yank, etc.) comes second. A cursor is simply a
single width selection.</p>
<p>See also Kakoune's <a href="https://github.com/mawww/kakoune/wiki/Migrating-from-Vim">Migrating from Vim</a> and Helix's <a href="https://github.com/helix-editor/helix/wiki/Migrating-from-Vim">Migrating from Vim</a>.</p>
<blockquote>
<p>TODO: Mention textobjects, surround, registers</p>
</blockquote>
<div style="break-before: page; page-break-before: always;"></div><h1 id="configuration"><a class="header" href="#configuration">Configuration</a></h1>
<p>To override global configuration parameters, create a <code>config.toml</code> file located in your config directory:</p>
<ul>
<li>Linux and Mac: <code>~/.config/helix/config.toml</code></li>
<li>Windows: <code>%AppData%\helix\config.toml</code></li>
</ul>
<blockquote>
<p>💡 You can easily open the config file by typing <code>:config-open</code> within Helix normal mode.</p>
</blockquote>
<p>Example config:</p>
<pre><code class="language-toml">theme = &quot;onedark&quot;

[editor]
line-number = &quot;relative&quot;
mouse = false

[editor.cursor-shape]
insert = &quot;bar&quot;
normal = &quot;block&quot;
select = &quot;underline&quot;

[editor.file-picker]
hidden = false
</code></pre>
<p>You can use a custom configuration file by specifying it with the <code>-c</code> or
<code>--config</code> command line argument, for example <code>hx -c path/to/custom-config.toml</code>.
Additionally, you can reload the configuration file by sending the USR1
signal to the Helix process on Unix operating systems, such as by using the command <code>pkill -USR1 hx</code>.</p>
<p>Finally, you can have a <code>config.toml</code> local to a project by putting it under a <code>.helix</code> directory in your repository.
Its settings will be merged with the configuration directory <code>config.toml</code> and the built-in configuration.</p>
<h2 id="editor"><a class="header" href="#editor">Editor</a></h2>
<h3 id="editor-section"><a class="header" href="#editor-section"><code>[editor]</code> Section</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Default</th></tr></thead><tbody>
<tr><td><code>scrolloff</code></td><td>Number of lines of padding around the edge of the screen when scrolling</td><td><code>5</code></td></tr>
<tr><td><code>mouse</code></td><td>Enable mouse mode</td><td><code>true</code></td></tr>
<tr><td><code>middle-click-paste</code></td><td>Middle click paste support</td><td><code>true</code></td></tr>
<tr><td><code>scroll-lines</code></td><td>Number of lines to scroll per scroll wheel step</td><td><code>3</code></td></tr>
<tr><td><code>shell</code></td><td>Shell to use when running external commands</td><td>Unix: <code>[&quot;sh&quot;, &quot;-c&quot;]</code><br/>Windows: <code>[&quot;cmd&quot;, &quot;/C&quot;]</code></td></tr>
<tr><td><code>line-number</code></td><td>Line number display: <code>absolute</code> simply shows each line's number, while <code>relative</code> shows the distance from the current line. When unfocused or in insert mode, <code>relative</code> will still show absolute line numbers</td><td><code>absolute</code></td></tr>
<tr><td><code>cursorline</code></td><td>Highlight all lines with a cursor</td><td><code>false</code></td></tr>
<tr><td><code>cursorcolumn</code></td><td>Highlight all columns with a cursor</td><td><code>false</code></td></tr>
<tr><td><code>gutters</code></td><td>Gutters to display: Available are <code>diagnostics</code> and <code>diff</code> and <code>line-numbers</code> and <code>spacer</code>, note that <code>diagnostics</code> also includes other features like breakpoints, 1-width padding will be inserted if gutters is non-empty</td><td><code>[&quot;diagnostics&quot;, &quot;spacer&quot;, &quot;line-numbers&quot;, &quot;spacer&quot;, &quot;diff&quot;]</code></td></tr>
<tr><td><code>auto-completion</code></td><td>Enable automatic pop up of auto-completion</td><td><code>true</code></td></tr>
<tr><td><code>auto-format</code></td><td>Enable automatic formatting on save</td><td><code>true</code></td></tr>
<tr><td><code>auto-save</code></td><td>Enable automatic saving on the focus moving away from Helix. Requires <a href="https://github.com/helix-editor/helix/wiki/Terminal-Support">focus event support</a> from your terminal</td><td><code>false</code></td></tr>
<tr><td><code>idle-timeout</code></td><td>Time in milliseconds since last keypress before idle timers trigger. Used for autocompletion, set to 0 for instant</td><td><code>400</code></td></tr>
<tr><td><code>preview-completion-insert</code></td><td>Whether to apply completion item instantly when selected</td><td><code>true</code></td></tr>
<tr><td><code>completion-trigger-len</code></td><td>The min-length of word under cursor to trigger autocompletion</td><td><code>2</code></td></tr>
<tr><td><code>completion-replace</code></td><td>Set to <code>true</code> to make completions always replace the entire word and not just the part before the cursor</td><td><code>false</code></td></tr>
<tr><td><code>auto-info</code></td><td>Whether to display info boxes</td><td><code>true</code></td></tr>
<tr><td><code>true-color</code></td><td>Set to <code>true</code> to override automatic detection of terminal truecolor support in the event of a false negative</td><td><code>false</code></td></tr>
<tr><td><code>undercurl</code></td><td>Set to <code>true</code> to override automatic detection of terminal undercurl support in the event of a false negative</td><td><code>false</code></td></tr>
<tr><td><code>rulers</code></td><td>List of column positions at which to display the rulers. Can be overridden by language specific <code>rulers</code> in <code>languages.toml</code> file</td><td><code>[]</code></td></tr>
<tr><td><code>bufferline</code></td><td>Renders a line at the top of the editor displaying open buffers. Can be <code>always</code>, <code>never</code> or <code>multiple</code> (only shown if more than one buffer is in use)</td><td><code>never</code></td></tr>
<tr><td><code>initial-mode</code></td><td>The initial mode for newly opened editors.</td><td><code>&quot;normal&quot;</code></td></tr>
<tr><td><code>color-modes</code></td><td>Whether to color the mode indicator with different colors depending on the mode itself</td><td><code>false</code></td></tr>
<tr><td><code>text-width</code></td><td>Maximum line length. Used for the <code>:reflow</code> command and soft-wrapping if <code>soft-wrap.wrap-at-text-width</code> is set</td><td><code>80</code></td></tr>
<tr><td><code>workspace-lsp-roots</code></td><td>Directories relative to the workspace root that are treated as LSP roots. Should only be set in <code>.helix/config.toml</code></td><td><code>[]</code></td></tr>
<tr><td><code>default-line-ending</code></td><td>The line ending to use for new documents. Can be <code>native</code>, <code>lf</code>, <code>crlf</code>, <code>ff</code>, <code>cr</code> or <code>nel</code>. <code>native</code> uses the platform's native line ending (<code>crlf</code> on Windows, otherwise <code>lf</code>).</td><td><code>native</code></td></tr>
<tr><td><code>insert-final-newline</code></td><td>Whether to automatically insert a trailing line-ending on write if missing</td><td><code>true</code></td></tr>
<tr><td><code>rainbow-brackets</code></td><td>Whether to render rainbow colors for matching brackets. Requires tree-sitter <code>rainbows.scm</code> queries for the language.</td><td><code>false</code></td></tr>
</tbody></table>
</div>
<h3 id="editorstatusline-section"><a class="header" href="#editorstatusline-section"><code>[editor.statusline]</code> Section</a></h3>
<p>Allows configuring the statusline at the bottom of the editor.</p>
<p>The configuration distinguishes between three areas of the status line:</p>
<p><code>[ ... ... LEFT ... ... | ... ... ... ... CENTER ... ... ... ... | ... ... RIGHT ... ... ]</code></p>
<p>Statusline elements can be defined as follows:</p>
<pre><code class="language-toml">[editor.statusline]
left = [&quot;mode&quot;, &quot;spinner&quot;]
center = [&quot;file-name&quot;]
right = [&quot;diagnostics&quot;, &quot;selections&quot;, &quot;position&quot;, &quot;file-encoding&quot;, &quot;file-line-ending&quot;, &quot;file-type&quot;]
separator = &quot;&quot;
mode.normal = &quot;NORMAL&quot;
mode.insert = &quot;INSERT&quot;
mode.select = &quot;SELECT&quot;
</code></pre>
<p>The <code>[editor.statusline]</code> key takes the following sub-keys:</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Default</th></tr></thead><tbody>
<tr><td><code>left</code></td><td>A list of elements aligned to the left of the statusline</td><td><code>[&quot;mode&quot;, &quot;spinner&quot;, &quot;file-name&quot;, &quot;read-only-indicator&quot;, &quot;file-modification-indicator&quot;]</code></td></tr>
<tr><td><code>center</code></td><td>A list of elements aligned to the middle of the statusline</td><td><code>[]</code></td></tr>
<tr><td><code>right</code></td><td>A list of elements aligned to the right of the statusline</td><td><code>[&quot;diagnostics&quot;, &quot;selections&quot;, &quot;register&quot;, &quot;position&quot;, &quot;file-encoding&quot;]</code></td></tr>
<tr><td><code>separator</code></td><td>The character used to separate elements in the statusline</td><td><code>&quot;&quot;</code></td></tr>
<tr><td><code>mode.normal</code></td><td>The text shown in the <code>mode</code> element for normal mode</td><td><code>&quot;NOR&quot;</code></td></tr>
<tr><td><code>mode.insert</code></td><td>The text shown in the <code>mode</code> element for insert mode</td><td><code>&quot;INS&quot;</code></td></tr>
<tr><td><code>mode.select</code></td><td>The text shown in the <code>mode</code> element for select mode</td><td><code>&quot;SEL&quot;</code></td></tr>
</tbody></table>
</div>
<p>The following statusline elements can be configured:</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th></tr></thead><tbody>
<tr><td><code>mode</code></td><td>The current editor mode (<code>mode.normal</code>/<code>mode.insert</code>/<code>mode.select</code>)</td></tr>
<tr><td><code>spinner</code></td><td>A progress spinner indicating LSP activity</td></tr>
<tr><td><code>file-name</code></td><td>The path/name of the opened file</td></tr>
<tr><td><code>file-base-name</code></td><td>The basename of the opened file</td></tr>
<tr><td><code>file-modification-indicator</code></td><td>The indicator to show whether the file is modified (a <code>[+]</code> appears when there are unsaved changes)</td></tr>
<tr><td><code>file-encoding</code></td><td>The encoding of the opened file if it differs from UTF-8</td></tr>
<tr><td><code>file-line-ending</code></td><td>The file line endings (CRLF or LF)</td></tr>
<tr><td><code>read-only-indicator</code></td><td>An indicator that shows <code>[readonly]</code> when a file cannot be written</td></tr>
<tr><td><code>total-line-numbers</code></td><td>The total line numbers of the opened file</td></tr>
<tr><td><code>file-type</code></td><td>The type of the opened file</td></tr>
<tr><td><code>diagnostics</code></td><td>The number of warnings and/or errors</td></tr>
<tr><td><code>workspace-diagnostics</code></td><td>The number of warnings and/or errors on workspace</td></tr>
<tr><td><code>selections</code></td><td>The number of active selections</td></tr>
<tr><td><code>primary-selection-length</code></td><td>The number of characters currently in primary selection</td></tr>
<tr><td><code>position</code></td><td>The cursor position</td></tr>
<tr><td><code>position-percentage</code></td><td>The cursor position as a percentage of the total number of lines</td></tr>
<tr><td><code>separator</code></td><td>The string defined in <code>editor.statusline.separator</code> (defaults to <code>&quot;&quot;</code>)</td></tr>
<tr><td><code>spacer</code></td><td>Inserts a space between elements (multiple/contiguous spacers may be specified)</td></tr>
<tr><td><code>version-control</code></td><td>The current branch name or detached commit hash of the opened workspace</td></tr>
<tr><td><code>register</code></td><td>The current selected register</td></tr>
</tbody></table>
</div>
<h3 id="editorlsp-section"><a class="header" href="#editorlsp-section"><code>[editor.lsp]</code> Section</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Default</th></tr></thead><tbody>
<tr><td><code>enable</code></td><td>Enables LSP integration. Setting to false will completely disable language servers regardless of language settings.</td><td><code>true</code></td></tr>
<tr><td><code>display-messages</code></td><td>Display LSP progress messages below statusline<sup class="footnote-reference"><a href="#1">1</a></sup></td><td><code>false</code></td></tr>
<tr><td><code>auto-signature-help</code></td><td>Enable automatic popup of signature help (parameter hints)</td><td><code>true</code></td></tr>
<tr><td><code>display-inlay-hints</code></td><td>Display inlay hints<sup class="footnote-reference"><a href="#2">2</a></sup></td><td><code>false</code></td></tr>
<tr><td><code>display-signature-help-docs</code></td><td>Display docs under signature help popup</td><td><code>true</code></td></tr>
<tr><td><code>snippets</code></td><td>Enables snippet completions. Requires a server restart (<code>:lsp-restart</code>) to take effect after <code>:config-reload</code>/<code>:set</code>.</td><td><code>true</code></td></tr>
<tr><td><code>goto-reference-include-declaration</code></td><td>Include declaration in the goto references popup.</td><td><code>true</code></td></tr>
</tbody></table>
</div>
<div class="footnote-definition" id="1"><sup class="footnote-definition-label">1</sup>
<p>By default, a progress spinner is shown in the statusline beside the file path.</p>
</div>
<div class="footnote-definition" id="2"><sup class="footnote-definition-label">2</sup>
<p>You may also have to activate them in the LSP config for them to appear, not just in Helix. Inlay hints in Helix are still being improved on and may be a little bit laggy/janky under some circumstances. Please report any bugs you see so we can fix them!</p>
</div>
<h3 id="editorcursor-shape-section"><a class="header" href="#editorcursor-shape-section"><code>[editor.cursor-shape]</code> Section</a></h3>
<p>Defines the shape of cursor in each mode.
Valid values for these options are <code>block</code>, <code>bar</code>, <code>underline</code>, or <code>hidden</code>.</p>
<blockquote>
<p>💡 Due to limitations of the terminal environment, only the primary cursor can
change shape.</p>
</blockquote>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Default</th></tr></thead><tbody>
<tr><td><code>normal</code></td><td>Cursor shape in <a href="./keymap.html#normal-mode">normal mode</a></td><td><code>block</code></td></tr>
<tr><td><code>insert</code></td><td>Cursor shape in <a href="./keymap.html#insert-mode">insert mode</a></td><td><code>block</code></td></tr>
<tr><td><code>select</code></td><td>Cursor shape in <a href="./keymap.html#select--extend-mode">select mode</a></td><td><code>block</code></td></tr>
</tbody></table>
</div>
<h3 id="editorfile-picker-section"><a class="header" href="#editorfile-picker-section"><code>[editor.file-picker]</code> Section</a></h3>
<p>Set options for file picker and global search. Ignoring a file means it is
not visible in the Helix file picker and global search.</p>
<p>All git related options are only enabled in a git repository.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Default</th></tr></thead><tbody>
<tr><td><code>hidden</code></td><td>Enables ignoring hidden files</td><td>true</td></tr>
<tr><td><code>follow-symlinks</code></td><td>Follow symlinks instead of ignoring them</td><td>true</td></tr>
<tr><td><code>deduplicate-links</code></td><td>Ignore symlinks that point at files already shown in the picker</td><td>true</td></tr>
<tr><td><code>parents</code></td><td>Enables reading ignore files from parent directories</td><td>true</td></tr>
<tr><td><code>ignore</code></td><td>Enables reading <code>.ignore</code> files</td><td>true</td></tr>
<tr><td><code>git-ignore</code></td><td>Enables reading <code>.gitignore</code> files</td><td>true</td></tr>
<tr><td><code>git-global</code></td><td>Enables reading global <code>.gitignore</code>, whose path is specified in git's config: <code>core.excludefile</code> option</td><td>true</td></tr>
<tr><td><code>git-exclude</code></td><td>Enables reading <code>.git/info/exclude</code> files</td><td>true</td></tr>
<tr><td><code>max-depth</code></td><td>Set with an integer value for maximum depth to recurse</td><td>Defaults to <code>None</code>.</td></tr>
</tbody></table>
</div>
<h3 id="editorauto-pairs-section"><a class="header" href="#editorauto-pairs-section"><code>[editor.auto-pairs]</code> Section</a></h3>
<p>Enables automatic insertion of pairs to parentheses, brackets, etc. Can be a
simple boolean value, or a specific mapping of pairs of single characters.</p>
<p>To disable auto-pairs altogether, set <code>auto-pairs</code> to <code>false</code>:</p>
<pre><code class="language-toml">[editor]
auto-pairs = false # defaults to `true`
</code></pre>
<p>The default pairs are <code>(){}[]''&quot;&quot;``</code>, but these can be customized by
setting <code>auto-pairs</code> to a TOML table:</p>
<pre><code class="language-toml">[editor.auto-pairs]
'(' = ')'
'{' = '}'
'[' = ']'
'&quot;' = '&quot;'
'`' = '`'
'&lt;' = '&gt;'
</code></pre>
<p>Additionally, this setting can be used in a language config. Unless
the editor setting is <code>false</code>, this will override the editor config in
documents with this language.</p>
<p>Example <code>languages.toml</code> that adds &lt;&gt; and removes ''</p>
<pre><code class="language-toml">[[language]]
name = &quot;rust&quot;

[language.auto-pairs]
'(' = ')'
'{' = '}'
'[' = ']'
'&quot;' = '&quot;'
'`' = '`'
'&lt;' = '&gt;'
</code></pre>
<h3 id="editorsearch-section"><a class="header" href="#editorsearch-section"><code>[editor.search]</code> Section</a></h3>
<p>Search specific options.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Default</th></tr></thead><tbody>
<tr><td><code>smart-case</code></td><td>Enable smart case regex searching (case-insensitive unless pattern contains upper case characters)</td><td><code>true</code></td></tr>
<tr><td><code>wrap-around</code></td><td>Whether the search should wrap after depleting the matches</td><td><code>true</code></td></tr>
</tbody></table>
</div>
<h3 id="editorwhitespace-section"><a class="header" href="#editorwhitespace-section"><code>[editor.whitespace]</code> Section</a></h3>
<p>Options for rendering whitespace with visible characters. Use <code>:set whitespace.render all</code> to temporarily enable visible whitespace.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Default</th></tr></thead><tbody>
<tr><td><code>render</code></td><td>Whether to render whitespace. May either be <code>&quot;all&quot;</code> or <code>&quot;none&quot;</code>, or a table with sub-keys <code>space</code>, <code>nbsp</code>, <code>tab</code>, and <code>newline</code></td><td><code>&quot;none&quot;</code></td></tr>
<tr><td><code>characters</code></td><td>Literal characters to use when rendering whitespace. Sub-keys may be any of <code>tab</code>, <code>space</code>, <code>nbsp</code>, <code>newline</code> or <code>tabpad</code></td><td>See example below</td></tr>
</tbody></table>
</div>
<p>Example</p>
<pre><code class="language-toml">[editor.whitespace]
render = &quot;all&quot;
# or control each character
[editor.whitespace.render]
space = &quot;all&quot;
tab = &quot;all&quot;
newline = &quot;none&quot;

[editor.whitespace.characters]
space = &quot;·&quot;
nbsp = &quot;&quot;
tab = &quot;&quot;
newline = &quot;&quot;
tabpad = &quot;·&quot; # Tabs will look like &quot;→···&quot; (depending on tab width)
</code></pre>
<h3 id="editorindent-guides-section"><a class="header" href="#editorindent-guides-section"><code>[editor.indent-guides]</code> Section</a></h3>
<p>Options for rendering vertical indent guides.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Default</th></tr></thead><tbody>
<tr><td><code>render</code></td><td>Whether to render indent guides</td><td><code>false</code></td></tr>
<tr><td><code>character</code></td><td>Literal character to use for rendering the indent guide</td><td><code></code></td></tr>
<tr><td><code>skip-levels</code></td><td>Number of indent levels to skip</td><td><code>0</code></td></tr>
<tr><td><code>rainbow-option</code></td><td>Enum to set rainbow indentations. Options: <code>normal</code>, <code>dim</code> and <code>none</code>.</td><td><code>none</code></td></tr>
</tbody></table>
</div>
<p>Example:</p>
<pre><code class="language-toml">[editor.indent-guides]
render = true
character = &quot;&quot; # Some characters that work well: &quot;&quot;, &quot;&quot;, &quot;&quot;, &quot;&quot;
skip-levels = 1
rainbow-option = &quot;normal&quot;
</code></pre>
<h3 id="editorgutters-section"><a class="header" href="#editorgutters-section"><code>[editor.gutters]</code> Section</a></h3>
<p>For simplicity, <code>editor.gutters</code> accepts an array of gutter types, which will
use default settings for all gutter components.</p>
<pre><code class="language-toml">[editor]
gutters = [&quot;diff&quot;, &quot;diagnostics&quot;, &quot;line-numbers&quot;, &quot;spacer&quot;]
</code></pre>
<p>To customize the behavior of gutters, the <code>[editor.gutters]</code> section must
be used. This section contains top level settings, as well as settings for
specific gutter components as subsections.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Default</th></tr></thead><tbody>
<tr><td><code>layout</code></td><td>A vector of gutters to display</td><td><code>[&quot;diagnostics&quot;, &quot;spacer&quot;, &quot;line-numbers&quot;, &quot;spacer&quot;, &quot;diff&quot;]</code></td></tr>
</tbody></table>
</div>
<p>Example:</p>
<pre><code class="language-toml">[editor.gutters]
layout = [&quot;diff&quot;, &quot;diagnostics&quot;, &quot;line-numbers&quot;, &quot;spacer&quot;]
</code></pre>
<h4 id="editorguttersline-numbers-section"><a class="header" href="#editorguttersline-numbers-section"><code>[editor.gutters.line-numbers]</code> Section</a></h4>
<p>Options for the line number gutter</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Default</th></tr></thead><tbody>
<tr><td><code>min-width</code></td><td>The minimum number of characters to use</td><td><code>3</code></td></tr>
</tbody></table>
</div>
<p>Example:</p>
<pre><code class="language-toml">[editor.gutters.line-numbers]
min-width = 1
</code></pre>
<h4 id="editorguttersdiagnostics-section"><a class="header" href="#editorguttersdiagnostics-section"><code>[editor.gutters.diagnostics]</code> Section</a></h4>
<p>Currently unused</p>
<h4 id="editorguttersdiff-section"><a class="header" href="#editorguttersdiff-section"><code>[editor.gutters.diff]</code> Section</a></h4>
<p>Currently unused</p>
<h4 id="editorguttersspacer-section"><a class="header" href="#editorguttersspacer-section"><code>[editor.gutters.spacer]</code> Section</a></h4>
<p>Currently unused</p>
<h3 id="editorsoft-wrap-section"><a class="header" href="#editorsoft-wrap-section"><code>[editor.soft-wrap]</code> Section</a></h3>
<p>Options for soft wrapping lines that exceed the view width:</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Default</th></tr></thead><tbody>
<tr><td><code>enable</code></td><td>Whether soft wrapping is enabled.</td><td><code>false</code></td></tr>
<tr><td><code>max-wrap</code></td><td>Maximum free space left at the end of the line.</td><td><code>20</code></td></tr>
<tr><td><code>max-indent-retain</code></td><td>Maximum indentation to carry over when soft wrapping a line.</td><td><code>40</code></td></tr>
<tr><td><code>wrap-indicator</code></td><td>Text inserted before soft wrapped lines, highlighted with <code>ui.virtual.wrap</code></td><td><code></code></td></tr>
<tr><td><code>wrap-at-text-width</code></td><td>Soft wrap at <code>text-width</code> instead of using the full viewport size.</td><td><code>false</code></td></tr>
</tbody></table>
</div>
<p>Example:</p>
<pre><code class="language-toml">[editor.soft-wrap]
enable = true
max-wrap = 25 # increase value to reduce forced mid-word wrapping
max-indent-retain = 0
wrap-indicator = &quot;&quot;  # set wrap-indicator to &quot;&quot; to hide it
</code></pre>
<h3 id="editorexplorer-section"><a class="header" href="#editorexplorer-section"><code>[editor.explorer]</code> Section</a></h3>
<p>Sets explorer side width and style.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Default</th></tr></thead><tbody>
<tr><td><code>column-width</code></td><td>explorer side width</td><td>30</td></tr>
<tr><td><code>position</code></td><td>explorer widget position, <code>left</code> or <code>right</code></td><td><code>left</code></td></tr>
</tbody></table>
</div>
<h3 id="editorsmart-tab-section"><a class="header" href="#editorsmart-tab-section"><code>[editor.smart-tab]</code> Section</a></h3>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th><th>Default</th></tr></thead><tbody>
<tr><td><code>enable</code></td><td>If set to true, then when the cursor is in a position with non-whitespace to its left, instead of inserting a tab, it will run <code>move_parent_node_end</code>. If there is only whitespace to the left, then it inserts a tab as normal. With the default bindings, to explicitly insert a tab character, press Shift-tab.</td><td><code>true</code></td></tr>
<tr><td><code>supersede-menu</code></td><td>Normally, when a menu is on screen, such as when auto complete is triggered, the tab key is bound to cycling through the items. This means when menus are on screen, one cannot use the tab key to trigger the <code>smart-tab</code> command. If this option is set to true, the <code>smart-tab</code> command always takes precedence, which means one cannot use the tab key to cycle through menu items. One of the other bindings must be used instead, such as arrow keys or <code>C-n</code>/<code>C-p</code>.</td><td><code>false</code></td></tr>
</tbody></table>
</div>
<h3 id="editordigraphs-section"><a class="header" href="#editordigraphs-section"><code>[editor.digraphs]</code> Section</a></h3>
<p>By default, special characters can be input using the <code>insert_digraphs</code> command, bound to <code>\</code> in normal mode.
Custom digraphs can be added to the <code>editor.digraphs</code> section of the config.</p>
<pre><code class="language-toml">[editor.digraphs]
ka = &quot;&quot;
ku = { symbols = &quot;&quot;, description = &quot;The japanese character Ku&quot; }
shrug = &quot;¯\\_(ツ)_/¯&quot;
</code></pre>
<div style="break-before: page; page-break-before: always;"></div><h1 id="themes"><a class="header" href="#themes">Themes</a></h1>
<p>To use a theme add <code>theme = &quot;&lt;name&gt;&quot;</code> to the top of your <a href="./configuration.html"><code>config.toml</code></a> file, or select it during runtime using <code>:theme &lt;name&gt;</code>.</p>
<h2 id="creating-a-theme"><a class="header" href="#creating-a-theme">Creating a theme</a></h2>
<p>Create a file with the name of your theme as the file name (i.e <code>mytheme.toml</code>) and place it in your <code>themes</code> directory (i.e <code>~/.config/helix/themes</code> or <code>%AppData%\helix\themes</code> on Windows). The directory might have to be created beforehand.</p>
<blockquote>
<p>💡 The names &quot;default&quot; and &quot;base16_default&quot; are reserved for built-in themes
and cannot be overridden by user-defined themes.</p>
</blockquote>
<h3 id="overview"><a class="header" href="#overview">Overview</a></h3>
<p>Each line in the theme file is specified as below:</p>
<pre><code class="language-toml">key = { fg = &quot;#ffffff&quot;, bg = &quot;#000000&quot;, underline = { color = &quot;#ff0000&quot;, style = &quot;curl&quot;}, modifiers = [&quot;bold&quot;, &quot;italic&quot;] }
</code></pre>
<p>Where <code>key</code> represents what you want to style, <code>fg</code> specifies the foreground color, <code>bg</code> the background color, <code>underline</code> the underline <code>style</code>/<code>color</code>, and <code>modifiers</code> is a list of style modifiers. <code>bg</code>, <code>underline</code> and <code>modifiers</code> can be omitted to defer to the defaults.</p>
<p>To specify only the foreground color:</p>
<pre><code class="language-toml">key = &quot;#ffffff&quot;
</code></pre>
<p>If the key contains a dot <code>'.'</code>, it must be quoted to prevent it being parsed as a <a href="https://toml.io/en/v1.0.0#keys">dotted key</a>.</p>
<pre><code class="language-toml">&quot;key.key&quot; = &quot;#ffffff&quot;
</code></pre>
<p>For inspiration, you can find the default <code>theme.toml</code>
<a href="https://github.com/helix-editor/helix/blob/master/theme.toml">here</a> and
user-submitted themes
<a href="https://github.com/helix-editor/helix/blob/master/runtime/themes">here</a>.</p>
<h3 id="using-the-linter"><a class="header" href="#using-the-linter">Using the linter</a></h3>
<p>Use the supplied linting tool to check for errors and missing scopes:</p>
<pre><code class="language-sh">cargo xtask themelint onedark # replace onedark with &lt;name&gt;
</code></pre>
<h2 id="the-details-of-theme-creation"><a class="header" href="#the-details-of-theme-creation">The details of theme creation</a></h2>
<h3 id="color-palettes"><a class="header" href="#color-palettes">Color palettes</a></h3>
<p>It's recommended to define a palette of named colors, and refer to them in the
configuration values in your theme. To do this, add a table called
<code>palette</code> to your theme file:</p>
<pre><code class="language-toml">&quot;ui.background&quot; = &quot;white&quot;
&quot;ui.text&quot; = &quot;black&quot;

[palette]
white = &quot;#ffffff&quot;
black = &quot;#000000&quot;
</code></pre>
<p>Keep in mind that the <code>[palette]</code> table includes all keys after its header,
so it should be defined after the normal theme options.</p>
<p>The default palette uses the terminal's default 16 colors, and the colors names
are listed below. The <code>[palette]</code> section in the config file takes precedence
over it and is merged into the default palette.</p>
<div class="table-wrapper"><table><thead><tr><th>Color Name</th></tr></thead><tbody>
<tr><td><code>default</code></td></tr>
<tr><td><code>black</code></td></tr>
<tr><td><code>red</code></td></tr>
<tr><td><code>green</code></td></tr>
<tr><td><code>yellow</code></td></tr>
<tr><td><code>blue</code></td></tr>
<tr><td><code>magenta</code></td></tr>
<tr><td><code>cyan</code></td></tr>
<tr><td><code>gray</code></td></tr>
<tr><td><code>light-red</code></td></tr>
<tr><td><code>light-green</code></td></tr>
<tr><td><code>light-yellow</code></td></tr>
<tr><td><code>light-blue</code></td></tr>
<tr><td><code>light-magenta</code></td></tr>
<tr><td><code>light-cyan</code></td></tr>
<tr><td><code>light-gray</code></td></tr>
<tr><td><code>white</code></td></tr>
</tbody></table>
</div>
<h3 id="modifiers"><a class="header" href="#modifiers">Modifiers</a></h3>
<p>The following values may be used as modifier, provided they are supported by
your terminal emulator.</p>
<div class="table-wrapper"><table><thead><tr><th>Modifier</th></tr></thead><tbody>
<tr><td><code>bold</code></td></tr>
<tr><td><code>dim</code></td></tr>
<tr><td><code>italic</code></td></tr>
<tr><td><code>underlined</code></td></tr>
<tr><td><code>slow_blink</code></td></tr>
<tr><td><code>rapid_blink</code></td></tr>
<tr><td><code>reversed</code></td></tr>
<tr><td><code>hidden</code></td></tr>
<tr><td><code>crossed_out</code></td></tr>
</tbody></table>
</div>
<blockquote>
<p>💡 The <code>underlined</code> modifier is deprecated and only available for backwards compatibility.
Its behavior is equivalent to setting <code>underline.style=&quot;line&quot;</code>.</p>
</blockquote>
<h3 id="underline-style"><a class="header" href="#underline-style">Underline style</a></h3>
<p>One of the following values may be used as a value for <code>underline.style</code>, providing it is
supported by your terminal emulator.</p>
<div class="table-wrapper"><table><thead><tr><th>Modifier</th></tr></thead><tbody>
<tr><td><code>line</code></td></tr>
<tr><td><code>curl</code></td></tr>
<tr><td><code>dashed</code></td></tr>
<tr><td><code>dotted</code></td></tr>
<tr><td><code>double_line</code></td></tr>
</tbody></table>
</div>
<h3 id="inheritance"><a class="header" href="#inheritance">Inheritance</a></h3>
<p>Extend other themes by setting the <code>inherits</code> property to an existing theme.</p>
<pre><code class="language-toml">inherits = &quot;boo_berry&quot;

# Override the theming for &quot;keyword&quot;s:
&quot;keyword&quot; = { fg = &quot;gold&quot; }

# Override colors in the palette:
[palette]
berry = &quot;#2A2A4D&quot;
</code></pre>
<h3 id="rainbow"><a class="header" href="#rainbow">Rainbow</a></h3>
<p>The <code>rainbow</code> key is used for rainbow highlight for matching brackets.
The key is a list of styles.</p>
<pre><code class="language-toml">rainbow = [&quot;#ff0000&quot;, &quot;#ffa500&quot;, &quot;#fff000&quot;, { fg = &quot;#00ff00&quot;, modifiers = [&quot;bold&quot;] }]
</code></pre>
<p>Colors from the palette and modifiers may be used.</p>
<h3 id="scopes"><a class="header" href="#scopes">Scopes</a></h3>
<p>The following is a list of scopes available to use for styling:</p>
<h4 id="syntax-highlighting"><a class="header" href="#syntax-highlighting">Syntax highlighting</a></h4>
<p>These keys match <a href="https://tree-sitter.github.io/tree-sitter/syntax-highlighting#theme">tree-sitter scopes</a>.</p>
<p>When determining styling for a highlight, the longest matching theme key will be used. For example, if the highlight is <code>function.builtin.static</code>, the key <code>function.builtin</code> will be used instead of <code>function</code>.</p>
<p>We use a similar set of scopes as
<a href="https://www.sublimetext.com/docs/scope_naming.html">Sublime Text</a>. See also
<a href="https://macromates.com/manual/en/language_grammars">TextMate</a> scopes.</p>
<ul>
<li>
<p><code>attribute</code> - Class attributes, HTML tag attributes</p>
</li>
<li>
<p><code>type</code> - Types</p>
<ul>
<li><code>builtin</code> - Primitive types provided by the language (<code>int</code>, <code>usize</code>)</li>
<li><code>enum</code>
<ul>
<li><code>variant</code></li>
</ul>
</li>
</ul>
</li>
<li>
<p><code>constructor</code></p>
</li>
<li>
<p><code>constant</code> (TODO: constant.other.placeholder for <code>%v</code>)</p>
<ul>
<li><code>builtin</code> Special constants provided by the language (<code>true</code>, <code>false</code>, <code>nil</code> etc)
<ul>
<li><code>boolean</code></li>
</ul>
</li>
<li><code>character</code>
<ul>
<li><code>escape</code></li>
</ul>
</li>
<li><code>numeric</code> (numbers)
<ul>
<li><code>integer</code></li>
<li><code>float</code></li>
</ul>
</li>
</ul>
</li>
<li>
<p><code>string</code> (TODO: string.quoted.{single, double}, string.raw/.unquoted)?</p>
<ul>
<li><code>regexp</code> - Regular expressions</li>
<li><code>special</code>
<ul>
<li><code>path</code></li>
<li><code>url</code></li>
<li><code>symbol</code> - Erlang/Elixir atoms, Ruby symbols, Clojure keywords</li>
</ul>
</li>
</ul>
</li>
<li>
<p><code>comment</code> - Code comments</p>
<ul>
<li><code>line</code> - Single line comments (<code>//</code>)</li>
<li><code>block</code> - Block comments (e.g. (<code>/* */</code>)
<ul>
<li><code>documentation</code> - Documentation comments (e.g. <code>///</code> in Rust)</li>
</ul>
</li>
</ul>
</li>
<li>
<p><code>variable</code> - Variables</p>
<ul>
<li><code>builtin</code> - Reserved language variables (<code>self</code>, <code>this</code>, <code>super</code>, etc.)</li>
<li><code>parameter</code> - Function parameters</li>
<li><code>other</code>
<ul>
<li><code>member</code> - Fields of composite data types (e.g. structs, unions)</li>
</ul>
</li>
</ul>
</li>
<li>
<p><code>label</code></p>
</li>
<li>
<p><code>punctuation</code></p>
<ul>
<li><code>delimiter</code> - Commas, colons</li>
<li><code>bracket</code> - Parentheses, angle brackets, etc.</li>
<li><code>special</code> - String interpolation brackets.</li>
</ul>
</li>
<li>
<p><code>keyword</code></p>
<ul>
<li><code>control</code>
<ul>
<li><code>conditional</code> - <code>if</code>, <code>else</code></li>
<li><code>repeat</code> - <code>for</code>, <code>while</code>, <code>loop</code></li>
<li><code>import</code> - <code>import</code>, <code>export</code></li>
<li><code>return</code></li>
<li><code>exception</code></li>
</ul>
</li>
<li><code>operator</code> - <code>or</code>, <code>in</code></li>
<li><code>directive</code> - Preprocessor directives (<code>#if</code> in C)</li>
<li><code>function</code> - <code>fn</code>, <code>func</code></li>
<li><code>storage</code> - Keywords describing how things are stored
<ul>
<li><code>type</code> - The type of something, <code>class</code>, <code>function</code>, <code>var</code>, <code>let</code>, etc.</li>
<li><code>modifier</code> - Storage modifiers like <code>static</code>, <code>mut</code>, <code>const</code>, <code>ref</code>, etc.</li>
</ul>
</li>
</ul>
</li>
<li>
<p><code>operator</code> - <code>||</code>, <code>+=</code>, <code>&gt;</code></p>
</li>
<li>
<p><code>function</code></p>
<ul>
<li><code>builtin</code></li>
<li><code>method</code></li>
<li><code>macro</code></li>
<li><code>special</code> (preprocessor in C)</li>
</ul>
</li>
<li>
<p><code>tag</code> - Tags (e.g. <code>&lt;body&gt;</code> in HTML)</p>
<ul>
<li><code>builtin</code></li>
</ul>
</li>
<li>
<p><code>namespace</code></p>
</li>
<li>
<p><code>special</code></p>
</li>
<li>
<p><code>markup</code></p>
<ul>
<li><code>heading</code>
<ul>
<li><code>marker</code></li>
<li><code>1</code>, <code>2</code>, <code>3</code>, <code>4</code>, <code>5</code>, <code>6</code> - heading text for h1 through h6</li>
</ul>
</li>
<li><code>list</code>
<ul>
<li><code>unnumbered</code></li>
<li><code>numbered</code></li>
<li><code>checked</code></li>
<li><code>unchecked</code></li>
</ul>
</li>
<li><code>bold</code></li>
<li><code>italic</code></li>
<li><code>strikethrough</code></li>
<li><code>link</code>
<ul>
<li><code>url</code> - URLs pointed to by links</li>
<li><code>label</code> - non-URL link references</li>
<li><code>text</code> - URL and image descriptions in links</li>
</ul>
</li>
<li><code>quote</code></li>
<li><code>raw</code>
<ul>
<li><code>inline</code></li>
<li><code>block</code></li>
</ul>
</li>
</ul>
</li>
<li>
<p><code>diff</code> - version control changes</p>
<ul>
<li><code>plus</code> - additions
<ul>
<li><code>gutter</code> - gutter indicator</li>
</ul>
</li>
<li><code>minus</code> - deletions
<ul>
<li><code>gutter</code> - gutter indicator</li>
</ul>
</li>
<li><code>delta</code> - modifications
<ul>
<li><code>moved</code> - renamed or moved files/changes</li>
<li><code>gutter</code> - gutter indicator</li>
</ul>
</li>
</ul>
</li>
</ul>
<h4 id="interface"><a class="header" href="#interface">Interface</a></h4>
<p>These scopes are used for theming the editor interface:</p>
<ul>
<li><code>markup</code>
<ul>
<li><code>normal</code>
<ul>
<li><code>completion</code> - for completion doc popup UI</li>
<li><code>hover</code> - for hover popup UI</li>
</ul>
</li>
<li><code>heading</code>
<ul>
<li><code>completion</code> - for completion doc popup UI</li>
<li><code>hover</code> - for hover popup UI</li>
</ul>
</li>
<li><code>raw</code>
<ul>
<li><code>inline</code>
<ul>
<li><code>completion</code> - for completion doc popup UI</li>
<li><code>hover</code> - for hover popup UI</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Notes</th></tr></thead><tbody>
<tr><td><code>ui.background</code></td><td></td></tr>
<tr><td><code>ui.background.separator</code></td><td>Picker separator below input line</td></tr>
<tr><td><code>ui.cursor</code></td><td></td></tr>
<tr><td><code>ui.cursor.normal</code></td><td></td></tr>
<tr><td><code>ui.cursor.insert</code></td><td></td></tr>
<tr><td><code>ui.cursor.select</code></td><td></td></tr>
<tr><td><code>ui.cursor.match</code></td><td>Matching bracket etc.</td></tr>
<tr><td><code>ui.cursor.primary</code></td><td>Cursor with primary selection</td></tr>
<tr><td><code>ui.cursor.primary.normal</code></td><td></td></tr>
<tr><td><code>ui.cursor.primary.insert</code></td><td></td></tr>
<tr><td><code>ui.cursor.primary.select</code></td><td></td></tr>
<tr><td><code>ui.debug.breakpoint</code></td><td>Breakpoint indicator, found in the gutter</td></tr>
<tr><td><code>ui.debug.active</code></td><td>Indicator for the line at which debugging execution is paused at, found in the gutter</td></tr>
<tr><td><code>ui.gutter</code></td><td>Gutter</td></tr>
<tr><td><code>ui.gutter.selected</code></td><td>Gutter for the line the cursor is on</td></tr>
<tr><td><code>ui.highlight.frameline</code></td><td>Line at which debugging execution is paused at</td></tr>
<tr><td><code>ui.linenr</code></td><td>Line numbers</td></tr>
<tr><td><code>ui.linenr.selected</code></td><td>Line number for the line the cursor is on</td></tr>
<tr><td><code>ui.statusline</code></td><td>Statusline</td></tr>
<tr><td><code>ui.statusline.inactive</code></td><td>Statusline (unfocused document)</td></tr>
<tr><td><code>ui.statusline.normal</code></td><td>Statusline mode during normal mode (<a href="./configuration.html#editor-section">only if <code>editor.color-modes</code> is enabled</a>)</td></tr>
<tr><td><code>ui.statusline.insert</code></td><td>Statusline mode during insert mode (<a href="./configuration.html#editor-section">only if <code>editor.color-modes</code> is enabled</a>)</td></tr>
<tr><td><code>ui.statusline.select</code></td><td>Statusline mode during select mode (<a href="./configuration.html#editor-section">only if <code>editor.color-modes</code> is enabled</a>)</td></tr>
<tr><td><code>ui.statusline.separator</code></td><td>Separator character in statusline</td></tr>
<tr><td><code>ui.popup</code></td><td>Documentation popups (e.g. Space + k)</td></tr>
<tr><td><code>ui.popup.info</code></td><td>Prompt for multiple key options</td></tr>
<tr><td><code>ui.window</code></td><td>Borderlines separating splits</td></tr>
<tr><td><code>ui.help</code></td><td>Description box for commands</td></tr>
<tr><td><code>ui.text</code></td><td>Command prompts, popup text, etc.</td></tr>
<tr><td><code>ui.text.focus</code></td><td>The currently selected line in the picker</td></tr>
<tr><td><code>ui.text.inactive</code></td><td>Same as <code>ui.text</code> but when the text is inactive (e.g. suggestions)</td></tr>
<tr><td><code>ui.text.info</code></td><td>The key: command text in <code>ui.popup.info</code> boxes</td></tr>
<tr><td><code>ui.virtual.ruler</code></td><td>Ruler columns (see the <a href="./configuration.html#editor-section"><code>editor.rulers</code> config</a>)</td></tr>
<tr><td><code>ui.virtual.whitespace</code></td><td>Visible whitespace characters</td></tr>
<tr><td><code>ui.virtual.indent-guide</code></td><td>Vertical indent width guides</td></tr>
<tr><td><code>ui.virtual.inlay-hint</code></td><td>Default style for inlay hints of all kinds</td></tr>
<tr><td><code>ui.virtual.inlay-hint.parameter</code></td><td>Style for inlay hints of kind <code>parameter</code> (LSPs are not required to set a kind)</td></tr>
<tr><td><code>ui.virtual.inlay-hint.type</code></td><td>Style for inlay hints of kind <code>type</code> (LSPs are not required to set a kind)</td></tr>
<tr><td><code>ui.virtual.wrap</code></td><td>Soft-wrap indicator (see the <a href="./configuration.html#editor-section"><code>editor.soft-wrap</code> config</a>)</td></tr>
<tr><td><code>ui.menu</code></td><td>Code and command completion menus</td></tr>
<tr><td><code>ui.menu.selected</code></td><td>Selected autocomplete item</td></tr>
<tr><td><code>ui.menu.scroll</code></td><td><code>fg</code> sets thumb color, <code>bg</code> sets track color of scrollbar</td></tr>
<tr><td><code>ui.selection</code></td><td>For selections in the editing area</td></tr>
<tr><td><code>ui.selection.primary</code></td><td></td></tr>
<tr><td><code>ui.highlight</code></td><td>Highlighted lines in the picker preview</td></tr>
<tr><td><code>ui.cursorline.primary</code></td><td>The line of the primary cursor (<a href="./configuration.html#editor-section">if cursorline is enabled</a>)</td></tr>
<tr><td><code>ui.cursorline.secondary</code></td><td>The lines of any other cursors (<a href="./configuration.html#editor-section">if cursorline is enabled</a>)</td></tr>
<tr><td><code>ui.cursorcolumn.primary</code></td><td>The column of the primary cursor (<a href="./configuration.html#editor-section">if cursorcolumn is enabled</a>)</td></tr>
<tr><td><code>ui.cursorcolumn.secondary</code></td><td>The columns of any other cursors (<a href="./configuration.html#editor-section">if cursorcolumn is enabled</a>)</td></tr>
<tr><td><code>warning</code></td><td>Diagnostics warning (gutter)</td></tr>
<tr><td><code>error</code></td><td>Diagnostics error (gutter)</td></tr>
<tr><td><code>info</code></td><td>Diagnostics info (gutter)</td></tr>
<tr><td><code>hint</code></td><td>Diagnostics hint (gutter)</td></tr>
<tr><td><code>diagnostic</code></td><td>Diagnostics fallback style (editing area)</td></tr>
<tr><td><code>diagnostic.hint</code></td><td>Diagnostics hint (editing area)</td></tr>
<tr><td><code>diagnostic.info</code></td><td>Diagnostics info (editing area)</td></tr>
<tr><td><code>diagnostic.warning</code></td><td>Diagnostics warning (editing area)</td></tr>
<tr><td><code>diagnostic.error</code></td><td>Diagnostics error (editing area)</td></tr>
</tbody></table>
</div><div style="break-before: page; page-break-before: always;"></div><h1 id="key-remapping"><a class="header" href="#key-remapping">Key remapping</a></h1>
<p>Helix currently supports one-way key remapping through a simple TOML configuration
file. (More powerful solutions such as rebinding via commands will be
available in the future).</p>
<p>To remap keys, create a <code>config.toml</code> file in your <code>helix</code> configuration
directory (default <code>~/.config/helix</code> on Linux systems) with a structure like
this:</p>
<pre><code class="language-toml"># At most one section each of 'keys.normal', 'keys.insert' and 'keys.select'
[keys.normal]
C-s = &quot;:w&quot; # Maps Ctrl-s to the typable command :w which is an alias for :write (save file)
C-o = &quot;:open ~/.config/helix/config.toml&quot; # Maps Ctrl-o to opening of the helix config file
a = &quot;move_char_left&quot; # Maps the 'a' key to the move_char_left command
w = &quot;move_line_up&quot; # Maps the 'w' key move_line_up
&quot;C-S-esc&quot; = &quot;extend_line&quot; # Maps Ctrl-Shift-Escape to extend_line
g = { a = &quot;code_action&quot; } # Maps `ga` to show possible code actions
&quot;ret&quot; = [&quot;open_below&quot;, &quot;normal_mode&quot;] # Maps the enter key to open_below then re-enter normal mode

[keys.insert]
&quot;A-x&quot; = &quot;normal_mode&quot;     # Maps Alt-X to enter normal mode
j = { k = &quot;normal_mode&quot; } # Maps `jk` to exit insert mode
</code></pre>
<h2 id="minor-modes-1"><a class="header" href="#minor-modes-1">Minor modes</a></h2>
<p>Minor modes are accessed by pressing a key (usually from normal mode), giving access to dedicated bindings. Bindings
can be modified or added by nesting definitions.</p>
<pre><code class="language-toml">[keys.insert.j]
k = &quot;normal_mode&quot; # Maps `jk` to exit insert mode

[keys.normal.g]
a = &quot;code_action&quot; # Maps `ga` to show possible code actions

# invert `j` and `k` in view mode
[keys.normal.z]
j = &quot;scroll_up&quot;
k = &quot;scroll_down&quot;

# create a new minor mode bound to `+`
[keys.normal.&quot;+&quot;]
m = &quot;:run-shell-command make&quot;
c = &quot;:run-shell-command cargo build&quot;
t = &quot;:run-shell-command cargo test&quot;
</code></pre>
<h2 id="special-keys-and-modifiers"><a class="header" href="#special-keys-and-modifiers">Special keys and modifiers</a></h2>
<p>Ctrl, Shift and Alt modifiers are encoded respectively with the prefixes
<code>C-</code>, <code>S-</code> and <code>A-</code>. Special keys are encoded as follows:</p>
<div class="table-wrapper"><table><thead><tr><th>Key name</th><th>Representation</th></tr></thead><tbody>
<tr><td>Backspace</td><td><code>&quot;backspace&quot;</code></td></tr>
<tr><td>Space</td><td><code>&quot;space&quot;</code></td></tr>
<tr><td>Return/Enter</td><td><code>&quot;ret&quot;</code></td></tr>
<tr><td>-</td><td><code>&quot;minus&quot;</code></td></tr>
<tr><td>Left</td><td><code>&quot;left&quot;</code></td></tr>
<tr><td>Right</td><td><code>&quot;right&quot;</code></td></tr>
<tr><td>Up</td><td><code>&quot;up&quot;</code></td></tr>
<tr><td>Down</td><td><code>&quot;down&quot;</code></td></tr>
<tr><td>Home</td><td><code>&quot;home&quot;</code></td></tr>
<tr><td>End</td><td><code>&quot;end&quot;</code></td></tr>
<tr><td>Page Up</td><td><code>&quot;pageup&quot;</code></td></tr>
<tr><td>Page Down</td><td><code>&quot;pagedown&quot;</code></td></tr>
<tr><td>Tab</td><td><code>&quot;tab&quot;</code></td></tr>
<tr><td>Delete</td><td><code>&quot;del&quot;</code></td></tr>
<tr><td>Insert</td><td><code>&quot;ins&quot;</code></td></tr>
<tr><td>Null</td><td><code>&quot;null&quot;</code></td></tr>
<tr><td>Escape</td><td><code>&quot;esc&quot;</code></td></tr>
</tbody></table>
</div>
<p>Keys can be disabled by binding them to the <code>no_op</code> command.</p>
<p>To remove all default bindings, <code>unbind-default-keys = true</code> can be added to the top level configuration.</p>
<pre><code class="language-toml">unbind-default-keys = true

# Only these normal mode bindings will be used
[keys.normal]
n = &quot;normal_mode&quot;
t = &quot;goto_definition&quot;

# remember to add bindings to return to normal mode
[keys.select]
esc = &quot;normal_mode&quot;

[keys.insert]
esc = &quot;normal_mode&quot;
</code></pre>
<p>A list of commands is available in the <a href="https://docs.helix-editor.com/keymap.html">Keymap</a> documentation
and in the source code at <a href="https://github.com/helix-editor/helix/blob/master/helix-term/src/commands.rs"><code>helix-term/src/commands.rs</code></a> at the invocation of <code>static_commands!</code> macro and the <code>TypableCommandList</code>.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="languages"><a class="header" href="#languages">Languages</a></h1>
<p>Language-specific settings and settings for language servers are configured
in <code>languages.toml</code> files.</p>
<h2 id="languagestoml-files"><a class="header" href="#languagestoml-files"><code>languages.toml</code> files</a></h2>
<p>There are three possible locations for a <code>languages.toml</code> file:</p>
<ol>
<li>
<p>In the Helix source code, which lives in the
<a href="https://github.com/helix-editor/helix/blob/master/languages.toml">Helix repository</a>.
It provides the default configurations for languages and language servers.</p>
</li>
<li>
<p>In your <a href="./configuration.html">configuration directory</a>. This overrides values
from the built-in language configuration. For example, to disable
auto-LSP-formatting in Rust:</p>
<pre><code class="language-toml"># in &lt;config_dir&gt;/helix/languages.toml

[language-server.mylang-lsp]
command = &quot;mylang-lsp&quot;

[[language]]
name = &quot;rust&quot;
auto-format = false
</code></pre>
</li>
<li>
<p>In a <code>.helix</code> folder in your project. Language configuration may also be
overridden local to a project by creating a <code>languages.toml</code> file in a
<code>.helix</code> folder. Its settings will be merged with the language configuration
in the configuration directory and the built-in configuration.</p>
</li>
</ol>
<h2 id="language-configuration"><a class="header" href="#language-configuration">Language configuration</a></h2>
<p>Each language is configured by adding a <code>[[language]]</code> section to a
<code>languages.toml</code> file. For example:</p>
<pre><code class="language-toml">[[language]]
name = &quot;mylang&quot;
scope = &quot;source.mylang&quot;
injection-regex = &quot;mylang&quot;
file-types = [&quot;mylang&quot;, &quot;myl&quot;]
comment-token = &quot;#&quot;
indent = { tab-width = 2, unit = &quot;  &quot; }
formatter = { command = &quot;mylang-formatter&quot; , args = [&quot;--stdin&quot;] }
language-servers = [ &quot;mylang-lsp&quot; ]
</code></pre>
<p>These configuration keys are available:</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th></tr></thead><tbody>
<tr><td><code>name</code></td><td>The name of the language</td></tr>
<tr><td><code>language-id</code></td><td>The language-id for language servers, checkout the table at <a href="https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocumentItem">TextDocumentItem</a> for the right id</td></tr>
<tr><td><code>scope</code></td><td>A string like <code>source.js</code> that identifies the language. Currently, we strive to match the scope names used by popular TextMate grammars and by the Linguist library. Usually <code>source.&lt;name&gt;</code> or <code>text.&lt;name&gt;</code> in case of markup languages</td></tr>
<tr><td><code>injection-regex</code></td><td>regex pattern that will be tested against a language name in order to determine whether this language should be used for a potential <a href="https://tree-sitter.github.io/tree-sitter/syntax-highlighting#language-injection">language injection</a> site.</td></tr>
<tr><td><code>file-types</code></td><td>The filetypes of the language, for example <code>[&quot;yml&quot;, &quot;yaml&quot;]</code>. See the file-type detection section below.</td></tr>
<tr><td><code>shebangs</code></td><td>The interpreters from the shebang line, for example <code>[&quot;sh&quot;, &quot;bash&quot;]</code></td></tr>
<tr><td><code>roots</code></td><td>A set of marker files to look for when trying to find the workspace root. For example <code>Cargo.lock</code>, <code>yarn.lock</code></td></tr>
<tr><td><code>auto-format</code></td><td>Whether to autoformat this language when saving</td></tr>
<tr><td><code>diagnostic-severity</code></td><td>Minimal severity of diagnostic for it to be displayed. (Allowed values: <code>Error</code>, <code>Warning</code>, <code>Info</code>, <code>Hint</code>)</td></tr>
<tr><td><code>comment-token</code></td><td>The token to use as a comment-token</td></tr>
<tr><td><code>indent</code></td><td>The indent to use. Has sub keys <code>unit</code> (the text inserted into the document when indenting; usually set to N spaces or <code>&quot;\t&quot;</code> for tabs) and <code>tab-width</code> (the number of spaces rendered for a tab)</td></tr>
<tr><td><code>language-servers</code></td><td>The Language Servers used for this language. See below for more information in the section <a href="languages.html#configuring-language-servers-for-a-language">Configuring Language Servers for a language</a></td></tr>
<tr><td><code>grammar</code></td><td>The tree-sitter grammar to use (defaults to the value of <code>name</code>)</td></tr>
<tr><td><code>formatter</code></td><td>The formatter for the language, it will take precedence over the lsp when defined. The formatter must be able to take the original file as input from stdin and write the formatted file to stdout</td></tr>
<tr><td><code>text-width</code></td><td>Maximum line length. Used for the <code>:reflow</code> command and soft-wrapping if <code>soft-wrap.wrap-at-text-width</code> is set, defaults to <code>editor.text-width</code></td></tr>
<tr><td><code>workspace-lsp-roots</code></td><td>Directories relative to the workspace root that are treated as LSP roots. Should only be set in <code>.helix/config.toml</code>. Overwrites the setting of the same name in <code>config.toml</code> if set.</td></tr>
<tr><td><code>rulers</code></td><td>Overrides the <code>editor.rulers</code> config key for the language.</td></tr>
<tr><td><code>rainbow-brackets</code></td><td>Overrides the <code>editor.rainbow-brackets</code> config key for the language.</td></tr>
</tbody></table>
</div>
<h3 id="file-type-detection-and-the-file-types-key"><a class="header" href="#file-type-detection-and-the-file-types-key">File-type detection and the <code>file-types</code> key</a></h3>
<p>Helix determines which language configuration to use based on the <code>file-types</code> key
from the above section. <code>file-types</code> is a list of strings or tables, for
example:</p>
<pre><code class="language-toml">file-types = [&quot;Makefile&quot;, &quot;toml&quot;, { suffix = &quot;.git/config&quot; }]
</code></pre>
<p>When determining a language configuration to use, Helix searches the file-types
with the following priorities:</p>
<ol>
<li>Exact match: if the filename of a file is an exact match of a string in a
<code>file-types</code> list, that language wins. In the example above, <code>&quot;Makefile&quot;</code>
will match against <code>Makefile</code> files.</li>
<li>Extension: if there are no exact matches, any <code>file-types</code> string that
matches the file extension of a given file wins. In the example above, the
<code>&quot;toml&quot;</code> matches files like <code>Cargo.toml</code> or <code>languages.toml</code>.</li>
<li>Suffix: if there are still no matches, any values in <code>suffix</code> tables
are checked against the full path of the given file. In the example above,
the <code>{ suffix = &quot;.git/config&quot; }</code> would match against any <code>config</code> files
in <code>.git</code> directories. Note: <code>/</code> is used as the directory separator but is
replaced at runtime with the appropriate path separator for the operating
system, so this rule would match against <code>.git\config</code> files on Windows.</li>
</ol>
<h2 id="language-server-configuration"><a class="header" href="#language-server-configuration">Language Server configuration</a></h2>
<p>Language servers are configured separately in the table <code>language-server</code> in the same file as the languages <code>languages.toml</code></p>
<p>For example:</p>
<pre><code class="language-toml">[language-server.mylang-lsp]
command = &quot;mylang-lsp&quot;
args = [&quot;--stdio&quot;]
config = { provideFormatter = true }
environment = { &quot;ENV1&quot; = &quot;value1&quot;, &quot;ENV2&quot; = &quot;value2&quot; }

[language-server.efm-lsp-prettier]
command = &quot;efm-langserver&quot;

[language-server.efm-lsp-prettier.config]
documentFormatting = true
languages = { typescript = [ { formatCommand =&quot;prettier --stdin-filepath ${INPUT}&quot;, formatStdin = true } ] }
</code></pre>
<p>These are the available options for a language server.</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th></tr></thead><tbody>
<tr><td><code>command</code></td><td>The name or path of the language server binary to execute. Binaries must be in <code>$PATH</code></td></tr>
<tr><td><code>args</code></td><td>A list of arguments to pass to the language server binary</td></tr>
<tr><td><code>config</code></td><td>LSP initialization options</td></tr>
<tr><td><code>timeout</code></td><td>The maximum time a request to the language server may take, in seconds. Defaults to <code>20</code></td></tr>
<tr><td><code>environment</code></td><td>Any environment variables that will be used when starting the language server <code>{ &quot;KEY1&quot; = &quot;Value1&quot;, &quot;KEY2&quot; = &quot;Value2&quot; }</code></td></tr>
</tbody></table>
</div>
<p>A <code>format</code> sub-table within <code>config</code> can be used to pass extra formatting options to
<a href="https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_formatting">Document Formatting Requests</a>.
For example, with typescript:</p>
<pre><code class="language-toml">[language-server.typescript-language-server]
# pass format options according to https://github.com/typescript-language-server/typescript-language-server#workspacedidchangeconfiguration omitting the &quot;[language].format.&quot; prefix.
config = { format = { &quot;semicolons&quot; = &quot;insert&quot;, &quot;insertSpaceBeforeFunctionParenthesis&quot; = true } }
</code></pre>
<h3 id="configuring-language-servers-for-a-language"><a class="header" href="#configuring-language-servers-for-a-language">Configuring Language Servers for a language</a></h3>
<p>The <code>language-servers</code> attribute in a language tells helix which language servers are used for this language.</p>
<p>They have to be defined in the <code>[language-server]</code> table as described in the previous section.</p>
<p>Different languages can use the same language server instance, e.g. <code>typescript-language-server</code> is used for javascript, jsx, tsx and typescript by default.</p>
<p>In case multiple language servers are specified in the <code>language-servers</code> attribute of a <code>language</code>,
it's often useful to only enable/disable certain language-server features for these language servers.</p>
<p>As an example, <code>efm-lsp-prettier</code> of the previous example is used only with a formatting command <code>prettier</code>,
so everything else should be handled by the <code>typescript-language-server</code> (which is configured by default).
The language configuration for typescript could look like this:</p>
<pre><code class="language-toml">[[language]]
name = &quot;typescript&quot;
language-servers = [ { name = &quot;efm-lsp-prettier&quot;, only-features = [ &quot;format&quot; ] }, &quot;typescript-language-server&quot; ]
</code></pre>
<p>or equivalent:</p>
<pre><code class="language-toml">[[language]]
name = &quot;typescript&quot;
language-servers = [ { name = &quot;typescript-language-server&quot;, except-features = [ &quot;format&quot; ] }, &quot;efm-lsp-prettier&quot; ]
</code></pre>
<p>Each requested LSP feature is prioritized in the order of the <code>language-servers</code> array.
For example, the first <code>goto-definition</code> supported language server (in this case <code>typescript-language-server</code>) will be taken for the relevant LSP request (command <code>goto_definition</code>).
The features <code>diagnostics</code>, <code>code-action</code>, <code>completion</code>, <code>document-symbols</code> and <code>workspace-symbols</code> are an exception to that rule, as they are working for all language servers at the same time and are merged together, if enabled for the language.
If no <code>except-features</code> or <code>only-features</code> is given, all features for the language server are enabled.
If a language server itself doesn't support a feature, the next language server array entry will be tried (and so on).</p>
<p>The list of supported features is:</p>
<ul>
<li><code>format</code></li>
<li><code>goto-definition</code></li>
<li><code>goto-declaration</code></li>
<li><code>goto-type-definition</code></li>
<li><code>goto-reference</code></li>
<li><code>goto-implementation</code></li>
<li><code>signature-help</code></li>
<li><code>hover</code></li>
<li><code>document-highlight</code></li>
<li><code>completion</code></li>
<li><code>code-action</code></li>
<li><code>workspace-command</code></li>
<li><code>document-symbols</code></li>
<li><code>workspace-symbols</code></li>
<li><code>diagnostics</code></li>
<li><code>rename-symbol</code></li>
<li><code>inlay-hints</code></li>
</ul>
<h2 id="tree-sitter-grammar-configuration"><a class="header" href="#tree-sitter-grammar-configuration">Tree-sitter grammar configuration</a></h2>
<p>The source for a language's tree-sitter grammar is specified in a <code>[[grammar]]</code>
section in <code>languages.toml</code>. For example:</p>
<pre><code class="language-toml">[[grammar]]
name = &quot;mylang&quot;
source = { git = &quot;https://github.com/example/mylang&quot;, rev = &quot;a250c4582510ff34767ec3b7dcdd3c24e8c8aa68&quot; }
</code></pre>
<p>Grammar configuration takes these keys:</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th></tr></thead><tbody>
<tr><td><code>name</code></td><td>The name of the tree-sitter grammar</td></tr>
<tr><td><code>source</code></td><td>The method of fetching the grammar - a table with a schema defined below</td></tr>
</tbody></table>
</div>
<p>Where <code>source</code> is a table with either these keys when using a grammar from a
git repository:</p>
<div class="table-wrapper"><table><thead><tr><th>Key</th><th>Description</th></tr></thead><tbody>
<tr><td><code>git</code></td><td>A git remote URL from which the grammar should be cloned</td></tr>
<tr><td><code>rev</code></td><td>The revision (commit hash or tag) which should be fetched</td></tr>
<tr><td><code>subpath</code></td><td>A path within the grammar directory which should be built. Some grammar repositories host multiple grammars (for example <code>tree-sitter-typescript</code> and <code>tree-sitter-ocaml</code>) in subdirectories. This key is used to point <code>hx --grammar build</code> to the correct path for compilation. When omitted, the root of repository is used</td></tr>
</tbody></table>
</div>
<h3 id="choosing-grammars"><a class="header" href="#choosing-grammars">Choosing grammars</a></h3>
<p>You may use a top-level <code>use-grammars</code> key to control which grammars are
fetched and built when using <code>hx --grammar fetch</code> and <code>hx --grammar build</code>.</p>
<pre><code class="language-toml"># Note: this key must come **before** the [[language]] and [[grammar]] sections
use-grammars = { only = [ &quot;rust&quot;, &quot;c&quot;, &quot;cpp&quot; ] }
# or
use-grammars = { except = [ &quot;yaml&quot;, &quot;json&quot; ] }
</code></pre>
<p>When omitted, all grammars are fetched and built.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="guides"><a class="header" href="#guides">Guides</a></h1>
<p>This section contains guides for adding new language server configurations,
tree-sitter grammars, textobject and rainbow bracket queries, and other similar items.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="adding-new-languages-to-helix"><a class="header" href="#adding-new-languages-to-helix">Adding new languages to Helix</a></h1>
<p>In order to add a new language to Helix, you will need to follow the steps
below.</p>
<h2 id="language-configuration-1"><a class="header" href="#language-configuration-1">Language configuration</a></h2>
<ol>
<li>Add a new <code>[[language]]</code> entry in the <code>languages.toml</code> file and provide the
necessary configuration for the new language. For more information on
language configuration, refer to the
<a href="guides/../languages.html">language configuration section</a> of the documentation.
A new language server can be added by extending the <code>[language-server]</code> table in the same file.</li>
<li>If you are adding a new language or updating an existing language server
configuration, run the command <code>cargo xtask docgen</code> to update the
<a href="guides/../lang-support.html">Language Support</a> documentation.</li>
</ol>
<blockquote>
<p>💡 If you are adding a new Language Server configuration, make sure to update
the
<a href="https://github.com/helix-editor/helix/wiki/How-to-install-the-default-language-servers">Language Server Wiki</a>
with the installation instructions.</p>
</blockquote>
<h2 id="grammar-configuration"><a class="header" href="#grammar-configuration">Grammar configuration</a></h2>
<ol>
<li>If a tree-sitter grammar is available for the new language, add a new
<code>[[grammar]]</code> entry to the <code>languages.toml</code> file.</li>
<li>If you are testing the grammar locally, you can use the <code>source.path</code> key
with an absolute path to the grammar. However, before submitting a pull
request, make sure to switch to using <code>source.git</code>.</li>
</ol>
<h2 id="queries"><a class="header" href="#queries">Queries</a></h2>
<ol>
<li>In order to provide syntax highlighting and indentation for the new language,
you will need to add queries.</li>
<li>Create a new directory for the language with the path
<code>runtime/queries/&lt;name&gt;/</code>.</li>
<li>Refer to the
<a href="https://tree-sitter.github.io/tree-sitter/syntax-highlighting#queries">tree-sitter website</a>
for more information on writing queries.</li>
<li>A list of highlight captures can be found <a href="https://docs.helix-editor.com/themes.html#scopes">on the themes page</a>.</li>
</ol>
<blockquote>
<p>💡 In Helix, the first matching query takes precedence when evaluating
queries, which is different from other editors such as Neovim where the last
matching query supersedes the ones before it. See
<a href="https://github.com/helix-editor/helix/pull/1170#issuecomment-997294090">this issue</a>
for an example.</p>
</blockquote>
<h2 id="common-issues"><a class="header" href="#common-issues">Common issues</a></h2>
<ul>
<li>If you encounter errors when running Helix after switching branches, you may
need to update the tree-sitter grammars. Run the command <code>hx --grammar fetch</code>
to fetch the grammars and <code>hx --grammar build</code> to build any out-of-date
grammars.</li>
<li>If a parser is causing a segfault, or you want to remove it, make sure to
remove the compiled parser located at <code>runtime/grammars/&lt;name&gt;.so</code>.</li>
<li>If you are attempting to add queries and Helix is unable to locate them, ensure that the environment variable <code>HELIX_RUNTIME</code> is set to the location of the <code>runtime</code> folder you're developing in.</li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="adding-textobject-queries"><a class="header" href="#adding-textobject-queries">Adding textobject queries</a></h1>
<p>Helix supports textobjects that are language specific, such as functions, classes, etc.
These textobjects require an accompanying tree-sitter grammar and a <code>textobjects.scm</code> query file
to work properly. Tree-sitter allows us to query the source code syntax tree
and capture specific parts of it. The queries are written in a lisp dialect.
More information on how to write queries can be found in the <a href="https://tree-sitter.github.io/tree-sitter/using-parsers#query-syntax">official tree-sitter
documentation</a>.</p>
<p>Query files should be placed in <code>runtime/queries/{language}/textobjects.scm</code>
when contributing to Helix. Note that to test the query files locally you should put
them under your local runtime directory (<code>~/.config/helix/runtime</code> on Linux
for example).</p>
<p>The following <a href="https://tree-sitter.github.io/tree-sitter/using-parsers#capturing-nodes">captures</a> are recognized:</p>
<div class="table-wrapper"><table><thead><tr><th>Capture Name</th></tr></thead><tbody>
<tr><td><code>function.inside</code></td></tr>
<tr><td><code>function.around</code></td></tr>
<tr><td><code>class.inside</code></td></tr>
<tr><td><code>class.around</code></td></tr>
<tr><td><code>test.inside</code></td></tr>
<tr><td><code>test.around</code></td></tr>
<tr><td><code>parameter.inside</code></td></tr>
<tr><td><code>comment.inside</code></td></tr>
<tr><td><code>comment.around</code></td></tr>
</tbody></table>
</div>
<p><a href="https://github.com/search?q=repo%3Ahelix-editor%2Fhelix+filename%3Atextobjects.scm&amp;type=Code&amp;ref=advsearch&amp;l=&amp;l=">Example query files</a> can be found in the helix GitHub repository.</p>
<h2 id="queries-for-textobject-based-navigation"><a class="header" href="#queries-for-textobject-based-navigation">Queries for textobject based navigation</a></h2>
<p>Tree-sitter based navigation in Helix is done using captures in the
following order:</p>
<ul>
<li><code>object.movement</code></li>
<li><code>object.around</code></li>
<li><code>object.inside</code></li>
</ul>
<p>For example if a <code>function.around</code> capture has been already defined for a language
in its <code>textobjects.scm</code> file, function navigation should also work automatically.
<code>function.movement</code> should be defined only if the node captured by <code>function.around</code>
doesn't make sense in a navigation context.</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="adding-indent-queries"><a class="header" href="#adding-indent-queries">Adding indent queries</a></h1>
<p>Helix uses tree-sitter to correctly indent new lines. This requires a tree-
sitter grammar and an <code>indent.scm</code> query file placed in <code>runtime/queries/ {language}/indents.scm</code>. The indentation for a line is calculated by traversing
the syntax tree from the lowest node at the beginning of the new line (see
<a href="guides/indent.html#indent-queries">Indent queries</a>). Each of these nodes contributes to the total
indent when it is captured by the query (in what way depends on the name of
the capture.</p>
<p>Note that it matters where these added indents begin. For example,
multiple indent level increases that start on the same line only increase
the total indent level by 1. See <a href="guides/indent.html#capture-types">Capture types</a>.</p>
<h2 id="indent-queries"><a class="header" href="#indent-queries">Indent queries</a></h2>
<p>When Helix is inserting a new line through <code>o</code>, <code>O</code>, or <code>&lt;ret&gt;</code>, to determine
the indent level for the new line, the query in <code>indents.scm</code> is run on the
document. The starting position of the query is the end of the line above where
a new line will be inserted.</p>
<p>For <code>o</code>, the inserted line is the line below the cursor, so that starting
position of the query is the end of the current line.</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>fn need_hero(some_hero: Hero, life: Life) -&gt; {
    matches!(some_hero, Hero { // ←─────────────────╮
        strong: true,//←╮  ↑  ↑                     │
        fast: true,  // │  │  ╰── query start       │
        sure: true,  // │  ╰───── cursor            ├─ traversal 
        soon: true,  // ╰──────── new line inserted │  start node
    }) &amp;&amp;            //                             │
//  ↑                                               │
//  ╰───────────────────────────────────────────────╯
    some_hero &gt; life
}
<span class="boring">}</span></code></pre></pre>
<p>For <code>O</code>, the newly inserted line is the <em>current</em> line, so the starting position
of the query is the end of the line above the cursor.</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>fn need_hero(some_hero: Hero, life: Life) -&gt; { // ←─╮
    matches!(some_hero, Hero { // ←╮          ↑     │
        strong: true,//    ↑   ╭───╯          │     │
        fast: true,  //    │   │ query start ─╯     │
        sure: true,  //    ╰───┼ cursor             ├─ traversal
        soon: true,  //        ╰ new line inserted  │  start node
    }) &amp;&amp;            //                             │
    some_hero &gt; life //                             │
} // ←──────────────────────────────────────────────╯
<span class="boring">}</span></code></pre></pre>
<p>From this starting node, the syntax tree is traversed up until the root node.
Each indent capture is collected along the way, and then combined according to
their <a href="guides/indent.html#capture-types">capture types</a> and <a href="guides/indent.html#scopes">scopes</a> to a final indent
level for the line.</p>
<h3 id="capture-types"><a class="header" href="#capture-types">Capture types</a></h3>
<ul>
<li><code>@indent</code> (default scope <code>tail</code>):
Increase the indent level by 1. Multiple occurrences in the same line <em>do not</em>
stack. If there is at least one <code>@indent</code> and one <code>@outdent</code> capture on the
same line, the indent level isn't changed at all.</li>
<li><code>@outdent</code> (default scope <code>all</code>):
Decrease the indent level by 1. The same rules as for <code>@indent</code> apply.</li>
<li><code>@indent.always</code> (default scope <code>tail</code>):
Increase the indent level by 1. Multiple occurrences on the same line <em>do</em>
stack. The final indent level is <code>@indent.always</code><code>@outdent.always</code>. If
an <code>@indent</code> and an <code>@indent.always</code> are on the same line, the <code>@indent</code> is
ignored.</li>
<li><code>@outdent.always</code> (default scope <code>all</code>):
Decrease the indent level by 1. The same rules as for <code>@indent.always</code> apply.</li>
<li><code>@align</code> (default scope <code>all</code>):
Align everything inside this node to some anchor. The anchor is given
by the start of the node captured by <code>@anchor</code> in the same pattern.
Every pattern with an <code>@align</code> should contain exactly one <code>@anchor</code>.
Indent (and outdent) for nodes below (in terms of their starting line)
the <code>@align</code> node is added to the indentation required for alignment.</li>
<li><code>@extend</code>:
Extend the range of this node to the end of the line and to lines that are
indented more than the line that this node starts on. This is useful for
languages like Python, where for the purpose of indentation some nodes (like
functions or classes) should also contain indented lines that follow them.</li>
<li><code>@extend.prevent-once</code>:
Prevents the first extension of an ancestor of this node. For example, in Python
a return expression always ends the block that it is in. Note that this only
stops the extension of the next <code>@extend</code> capture. If multiple ancestors are
captured, only the extension of the innermost one is prevented. All other
ancestors are unaffected (regardless of whether the innermost ancestor would
actually have been extended).</li>
</ul>
<h4 id="indent--outdent"><a class="header" href="#indent--outdent"><code>@indent</code> / <code>@outdent</code></a></h4>
<p>Consider this example:</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>fn shout(things: Vec&lt;Thing&gt;) {
    //                       ↑
    //                       ├───────────────────────╮ indent level
    //                    @indent                    ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄
    //                                               │
    let it_all = |out| { things.filter(|thing| { //  │      1
    //                 ↑                       ↑     │
    //                 ├───────────────────────┼─────┼┄┄┄┄┄┄┄┄┄┄┄┄┄┄
    //              @indent                 @indent  │
    //                                               │      2
        thing.can_do_with(out) //                    │
    })}; //                                          ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄
  //↑↑↑                                              │      1
} //╰┼┴──────────────────────────────────────────────┴┄┄┄┄┄┄┄┄┄┄┄┄┄┄
// 3x @outdent
<span class="boring">}</span></code></pre></pre>
<pre><code class="language-scm">((block) @indent)
[&quot;}&quot; &quot;)&quot;] @outdent
</code></pre>
<p>Note how on the second line, we have two blocks begin on the same line. In this
case, since both captures occur on the same line, they are combined and only
result in a net increase of 1. Also note that the closing <code>}</code>s are part of the
<code>@indent</code> captures, but the 3 <code>@outdent</code>s also combine into 1 and result in that
line losing one indent level.</p>
<h4 id="extend--extendprevent-once"><a class="header" href="#extend--extendprevent-once"><code>@extend</code> / <code>@extend.prevent-once</code></a></h4>
<p>For an example of where <code>@extend</code> can be useful, consider Python, which is
whitespace-sensitive.</p>
<pre><code class="language-scm">]
  (parenthesized_expression)
  (function_definition)
  (class_definition)
] @indent

</code></pre>
<pre><code class="language-python">class Hero:
    def __init__(self, strong, fast, sure, soon):#  ←─╮
        self.is_strong = strong #                     │
        self.is_fast = fast     # ╭─── query start    │
        self.is_sure = sure     # │ ╭─ cursor         │
        self.is_soon = soon     # │ │                 │
        #     ↑            ↑      │ │                 │
        #     │            ╰──────╯ │                 │
        #     ╰─────────────────────╯                 │
        #                                             ├─ traversal
    def need_hero(self, life):         #              │  start node
        return (                       #              │
            self.is_strong             #              │
            and self.is_fast           #              │
            and self.is_sure           #              │
            and self.is_soon           #              │
            and self &gt; life            #              │
        ) # ←─────────────────────────────────────────╯
</code></pre>
<p>Without braces to catch the scope of the function, the smallest descendant of
the cursor on a line feed ends up being the entire inside of the class. Because
of this, it will miss the entire function node and its indent capture, leading
to an indent level one too small.</p>
<p>To address this case, <code>@extend</code> tells helix to &quot;extend&quot; the captured node's span
to the line feed and every consecutive line that has a greater indent level than
the line of the node.</p>
<pre><code class="language-scm">(parenthesized_expression) @indent

]
  (function_definition)
  (class_definition)
] @indent @extend

</code></pre>
<pre><code class="language-python">class Hero:
    def __init__(self, strong, fast, sure, soon):#  ←─╮
        self.is_strong = strong #                     │
        self.is_fast = fast     # ╭─── query start    ├─ traversal
        self.is_sure = sure     # │ ╭─ cursor         │  start node
        self.is_soon = soon     # │ │ ←───────────────╯
        #     ↑            ↑      │ │                 
        #     │            ╰──────╯ │
        #     ╰─────────────────────╯
    def need_hero(self, life):
        return (
            self.is_strong
            and self.is_fast
            and self.is_sure
            and self.is_soon
            and self &gt; life
        )
</code></pre>
<p>Furthermore, there are some cases where extending to everything with a greater
indent level may not be desirable. Consider the <code>need_hero</code> function above. If
our cursor is on the last line of the returned expression.</p>
<pre><code class="language-python">class Hero:
    def __init__(self, strong, fast, sure, soon):
        self.is_strong = strong
        self.is_fast = fast
        self.is_sure = sure
        self.is_soon = soon

    def need_hero(self, life):
        return (
            self.is_strong
            and self.is_fast
            and self.is_sure
            and self.is_soon
            and self &gt; life
        ) # ←─── cursor
    #←────────── where cursor should go on new line
</code></pre>
<p>In Python, the are a few tokens that will always end a scope, such as a return
statement. Since the scope ends, so should the indent level. But because the
function span is extended to every line with a greater indent level, a new line
would just continue on the same level. And an <code>@outdent</code> would not help us here
either, since it would cause everything in the parentheses to become outdented
as well.</p>
<p>To help, we need to signal an end to the extension. We can do this with
<code>@extend.prevent-once</code>.</p>
<pre><code class="language-scm">(parenthesized_expression) @indent

]
  (function_definition)
  (class_definition)
] @indent @extend

(return_statement) @extend.prevent-once
</code></pre>
<h4 id="indentalways--outdentalways"><a class="header" href="#indentalways--outdentalways"><code>@indent.always</code> / <code>@outdent.always</code></a></h4>
<p>As mentioned before, normally if there is more than one <code>@indent</code> or <code>@outdent</code>
capture on the same line, they are combined.</p>
<p>Sometimes, there are cases when you may want to ensure that every indent capture
is additive, regardless of how many occur on the same line. Consider this
example in YAML.</p>
<pre><code class="language-yaml">  - foo: bar
# ↑ ↑
# │ ╰─────────────── start of map
# ╰───────────────── start of list element
    baz: quux # ←─── cursor
    # ←───────────── where the cursor should go on a new line
    garply: waldo
  - quux:
      bar: baz
    xyzzy: thud
    fred: plugh
</code></pre>
<p>In YAML, you often have lists of maps. In these cases, the syntax is such that
the list element and the map both start on the same line. But we really do want
to start an indentation for each of these so that subsequent keys in the map
hang over the list and align properly. This is where <code>@indent.always</code> helps.</p>
<pre><code class="language-scm">((block_sequence_item) @item @indent.always @extend
  (#not-one-line? @item))

((block_mapping_pair
    key: (_) @key
    value: (_) @val
    (#not-same-line? @key @val)
  ) @indent.always @extend
)
</code></pre>
<h2 id="predicates"><a class="header" href="#predicates">Predicates</a></h2>
<p>In some cases, an S-expression cannot express exactly what pattern should be matched.
For that, tree-sitter allows for predicates to appear anywhere within a pattern,
similar to how <code>#set!</code> declarations work:</p>
<pre><code class="language-scm">(some_kind
  (child_kind) @indent
  (#predicate? arg1 arg2 ...)
)
</code></pre>
<p>The number of arguments depends on the predicate that's used.
Each argument is either a capture (<code>@name</code>) or a string (<code>&quot;some string&quot;</code>).
The following predicates are supported by tree-sitter:</p>
<ul>
<li>
<p><code>#eq?</code>/<code>#not-eq?</code>:
The first argument (a capture) must/must not be equal to the second argument
(a capture or a string).</p>
</li>
<li>
<p><code>#match?</code>/<code>#not-match?</code>:
The first argument (a capture) must/must not match the regex given in the
second argument (a string).</p>
</li>
</ul>
<p>Additionally, we support some custom predicates for indent queries:</p>
<ul>
<li>
<p><code>#not-kind-eq?</code>:
The kind of the first argument (a capture) must not be equal to the second
argument (a string).</p>
</li>
<li>
<p><code>#same-line?</code>/<code>#not-same-line?</code>:
The captures given by the 2 arguments must/must not start on the same line.</p>
</li>
<li>
<p><code>#one-line?</code>/<code>#not-one-line?</code>:
The captures given by the fist argument must/must span a total of one line.</p>
</li>
</ul>
<h3 id="scopes-1"><a class="header" href="#scopes-1">Scopes</a></h3>
<p>Added indents don't always apply to the whole node. For example, in most
cases when a node should be indented, we actually only want everything
except for its first line to be indented. For this, there are several
scopes (more scopes may be added in the future if required):</p>
<ul>
<li><code>tail</code>:
This scope applies to everything except for the first line of the
captured node.</li>
<li><code>all</code>:
This scope applies to the whole captured node. This is only different from
<code>tail</code> when the captured node is the first node on its line.</li>
</ul>
<p>For example, imagine we have the following function</p>
<pre><pre class="playground"><code class="language-rust"><span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>fn aha() { // ←─────────────────────────────────────╮
  let take = &quot;on me&quot;;  // ←──────────────╮  scope:  │
  let take = &quot;me on&quot;;             //     ├─ &quot;tail&quot;  ├─ (block) @indent
  let ill = be_gone_days(1 || 2); //     │          │
} // ←───────────────────────────────────┴──────────┴─ &quot;}&quot; @outdent
                                         //                scope: &quot;all&quot;
<span class="boring">}</span></code></pre></pre>
<p>We can write the following query with the <code>#set!</code> declaration:</p>
<pre><code class="language-scm">((block) @indent
 (#set! &quot;scope&quot; &quot;tail&quot;))
(&quot;}&quot; @outdent
 (#set! &quot;scope&quot; &quot;all&quot;))
</code></pre>
<p>As we can see, the &quot;tail&quot; scope covers the node, except for the first line.
Everything up to and including the closing brace gets an indent level of 1.
Then, on the closing brace, we encounter an outdent with a scope of &quot;all&quot;, which
means the first line is included, and the indent level is cancelled out on this
line. (Note these scopes are the defaults for <code>@indent</code> and <code>@outdent</code>—they are
written explicitly for demonstration.)</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="adding-injection-queries"><a class="header" href="#adding-injection-queries">Adding Injection Queries</a></h1>
<p>Writing language injection queries allows one to highlight a specific node as a different language.
In addition to the <a href="http://tree-sitter.github.io/tree-sitter/syntax-highlighting#language-injection">standard</a> language injection options used by tree-sitter, there
are a few Helix specific extensions that allow for more control.</p>
<p>And example of a simple query that would highlight all strings as bash in Nix:</p>
<pre><code class="language-scm">((string_expression (string_fragment) @injection.content)
  (#set! injection.language &quot;bash&quot;))
</code></pre>
<h2 id="capture-types-1"><a class="header" href="#capture-types-1">Capture Types</a></h2>
<ul>
<li>
<p><code>@injection.language</code> (standard):
The captured node may contain the language name used to highlight the node captured by
<code>@injection.content</code>.</p>
</li>
<li>
<p><code>@injection.content</code> (standard):
Marks the content to be highlighted as the language captured with <code>@injection.language</code> <em>et al</em>.</p>
</li>
<li>
<p><code>@injection.filename</code> (extension):
The captured node may contain a filename with a file-extension known to Helix,
highlighting <code>@injection.content</code> as that language. This uses the language extensions defined in
both the default languages.toml distributed with Helix, as well as user defined languages.</p>
</li>
<li>
<p><code>@injection.shebang</code> (extension):
The captured node may contain a shebang used to choose a language to highlight as. This also uses
the shebangs defined in the default and user <code>languages.toml</code>.</p>
</li>
</ul>
<h2 id="settings"><a class="header" href="#settings">Settings</a></h2>
<ul>
<li>
<p><code>injection.combined</code> (standard):
Indicates that all the matching nodes in the tree should have their content parsed as one
nested document.</p>
</li>
<li>
<p><code>injection.language</code> (standard):
Forces the captured content to be highlighted as the given language</p>
</li>
<li>
<p><code>injection.include-children</code> (standard):
Indicates that the content node’s entire text should be re-parsed, including the text of its child
nodes. By default, child nodes’ text will be excluded from the injected document.</p>
</li>
<li>
<p><code>injection.include-unnamed-children</code> (extension):
Same as <code>injection.include-children</code> but only for unnamed child nodes.</p>
</li>
</ul>
<h2 id="predicates-1"><a class="header" href="#predicates-1">Predicates</a></h2>
<ul>
<li>
<p><code>#eq?</code> (standard):
The first argument (a capture) must be equal to the second argument
(a capture or a string).</p>
</li>
<li>
<p><code>#match?</code> (standard):
The first argument (a capture) must match the regex given in the
second argument (a string).</p>
</li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="adding-rainbow-bracket-queries"><a class="header" href="#adding-rainbow-bracket-queries">Adding Rainbow Bracket Queries</a></h1>
<p>Helix uses <code>rainbows.scm</code> tree-sitter query files to provide rainbow bracket
functionality.</p>
<p>Tree-sitter queries are documented in the tree-sitter online documentation.
If you're writing queries for the first time, be sure to check out the section
on <a href="https://tree-sitter.github.io/tree-sitter/syntax-highlighting#highlights">syntax highlighting queries</a> and on <a href="https://tree-sitter.github.io/tree-sitter/using-parsers#pattern-matching-with-queries">query syntax</a>.</p>
<p>Rainbow queries have two captures: <code>@rainbow.scope</code> and <code>@rainbow.bracket</code>.
<code>@rainbow.scope</code> should capture any node that increases the nesting level
while <code>@rainbow.bracket</code> should capture any bracket nodes. Put another way:
<code>@rainbow.scope</code> switches to the next rainbow color for all nodes in the tree
under it while <code>@rainbow.bracket</code> paints captured nodes with the current
rainbow color.</p>
<p>For an example, let's add rainbow queries for the tree-sitter query (TSQ)
language itself. These queries will go into a
<code>runtime/queries/tsq/rainbows.scm</code> file in the repository root.</p>
<p>First we'll add the <code>@rainbow.bracket</code> captures. TSQ only has parentheses and
square brackets:</p>
<pre><code class="language-tsq">[&quot;(&quot; &quot;)&quot; &quot;[&quot; &quot;]&quot;] @rainbow.bracket
</code></pre>
<p>The ordering of the nodes within the alternation (square brackets) is not
taken into consideration.</p>
<blockquote>
<p>Note: Why are these nodes quoted? Most syntax highlights capture text
surrounded by parentheses. These are <em>named nodes</em> and correspond to the
names of rules in the grammar. Brackets are usually written in tree-sitter
grammars as literal strings, for example:</p>
<pre><code class="language-js">{
  // ...
  arguments: seq(&quot;(&quot;, repeat($.argument), &quot;)&quot;),
  // ...
}
</code></pre>
<p>Nodes written as literal strings in tree-sitter grammars may be captured
in queries with those same literal strings.</p>
</blockquote>
<p>Then we'll add <code>@rainbow.scope</code> captures. The easiest way to do this is to
view the <code>grammar.js</code> file in the tree-sitter grammar's repository. For TSQ,
that file is <a href="https://github.com/the-mikedavis/tree-sitter-tsq/blob/48b5e9f82ae0a4727201626f33a17f69f8e0ff86/grammar.js">here</a>. As we scroll down the <code>grammar.js</code>, we
see that the <code>(alternation)</code>, (L36) <code>(group)</code> (L57), <code>(named_node)</code> (L59),
<code>(predicate)</code> (L87) and  <code>(wildcard_node)</code> (L97) nodes all contain literal
parentheses or square brackets in their definitions. These nodes are all
direct parents of brackets and happen to also be the nodes we want to change
to the next rainbow color, so we capture them as <code>@rainbow.scope</code>.</p>
<pre><code class="language-tsq">[
  (group)
  (named_node)
  (wildcard_node)
  (predicate)
  (alternation)
] @rainbow.scope
</code></pre>
<p>This strategy works as a rule of thumb for most programming and configuration
languages. Markup languages can be trickier and may take additional
experimentation to find the correct nodes to use for scopes and brackets.</p>
<p>The <code>:tree-sitter-subtree</code> command shows the syntax tree under the primary
selection in S-expression format and can be a useful tool for determining how
to write a query.</p>
<h3 id="properties"><a class="header" href="#properties">Properties</a></h3>
<p>The <code>rainbow.include-children</code> property may be applied to <code>@rainbow.scope</code>
captures. By default, all <code>@rainbow.bracket</code> captures must be direct descendant
of a node captured with <code>@rainbow.scope</code> in a syntax tree in order to be
highlighted. The <code>rainbow.include-children</code> property disables that check and
allows <code>@rainbow.bracket</code> captures to be highlighted if they are direct or
indirect descendants of some node captured with <code>@rainbow.scope</code>.</p>
<p>For example, this property is used in the HTML rainbow queries.</p>
<p>For a document like <code>&lt;a&gt;link&lt;/a&gt;</code>, the syntax tree is:</p>
<pre><code class="language-tsq">(element                   ; &lt;a&gt;link&lt;/a&gt;
  (start_tag               ; &lt;a&gt;
    (tag_name))            ; a
  (text)                   ; link
  (end_tag                 ; &lt;/a&gt;
    (tag_name)))           ; a
</code></pre>
<p>If we want to highlight the <code>&lt;</code>, <code>&gt;</code> and <code>&lt;/</code> nodes with rainbow colors, we
capture them as <code>@rainbow.bracket</code>:</p>
<pre><code class="language-tsq">[&quot;&lt;&quot; &quot;&gt;&quot; &quot;&lt;/&quot;] @rainbow.bracket
</code></pre>
<p>And we capture <code>(element)</code> as <code>@rainbow.scope</code> because <code>(element)</code> nodes nest
within each other: they increment the nesting level and switch to the next
color in the rainbow.</p>
<pre><code class="language-tsq">(element) @rainbow.scope
</code></pre>
<p>But this combination of <code>@rainbow.scope</code> and <code>@rainbow.bracket</code> will not
highlight any nodes. <code>&lt;</code>, <code>&gt;</code> and <code>&lt;/</code> are children of the <code>(start_tag)</code> and
<code>(end_tag)</code> nodes. We can't capture <code>(start_tag)</code> and <code>(end_tag)</code> as
<code>@rainbow.scope</code> because they don't nest other elements. We can fix this case
by removing the requirement that <code>&lt;</code>, <code>&gt;</code> and <code>&lt;/</code> are direct descendants of
<code>(element)</code> using the <code>rainbow.include-children</code> property.</p>
<pre><code class="language-tsq">((element) @rainbow.scope
 (#set! rainbow.include-children))
</code></pre>
<p>With this property set, <code>&lt;</code>, <code>&gt;</code>, and <code>&lt;/</code> will highlight with rainbow colors
even though they aren't direct descendents of the <code>(element)</code> node.</p>
<p><code>rainbow.include-children</code> is not necessary for the vast majority of programming
languages. It is only necessary when the node that increments the nesting level
(changes rainbow color) is not the direct parent of the bracket node.</p>

                    </main>

                    <nav class="nav-wrapper" aria-label="Page navigation">
                        <!-- Mobile navigation buttons -->


                        <div style="clear: both"></div>
                    </nav>
                </div>
            </div>

            <nav class="nav-wide-wrapper" aria-label="Page navigation">

            </nav>

        </div>




        <script>
            window.playground_copyable = true;
        </script>


        <script src="elasticlunr.min.js"></script>
        <script src="mark.min.js"></script>
        <script src="searcher.js"></script>

        <script src="clipboard.min.js"></script>
        <script src="highlight.js"></script>
        <script src="book.js"></script>

        <!-- Custom JS scripts -->

        <script>
        window.addEventListener('load', function() {
            window.setTimeout(window.print, 100);
        });
        </script>

    </div>
    </body>
</html>