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
|
\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename ../../eglot.info
@settitle Eglot: The Emacs Client for the Language Server Protocol
@include docstyle.texi
@syncodeindex vr cp
@syncodeindex fn cp
@c %**end of header
@copying
This manual is for Eglot, the Emacs LSP client.
Copyright @copyright{} 2022--2026 Free Software Foundation, Inc.
@quotation
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with no
Invariant Sections, with the Front-Cover Texts being ``A GNU Manual'',
and with the Back-Cover Texts as in (a) below. A copy of the license is
included in the section entitled ``GNU Free Documentation License''.
(a) The FSF's Back-Cover Text is: ``You have the freedom to copy and
modify this GNU manual.''
@end quotation
@end copying
@dircategory Emacs misc features
@direntry
* Eglot: (eglot). Language Server Protocol client for Emacs.
@end direntry
@titlepage
@sp 4
@c The title is printed in a large font.
@center @titlefont{User's Guide}
@sp 1
@center @titlefont{to}
@sp 1
@center @titlefont{Eglot: The Emacs LSP Client}
@ignore
@sp 2
@center release 1.8
@c -release-
@end ignore
@sp 3
@center Jo@~ao T@'avora & Eli Zaretskii
@c -date-
@page
@vskip 0pt plus 1filll
@insertcopying
@end titlepage
@contents
@ifnottex
@node Top
@top Eglot
@cindex LSP
@cindex language server protocol
Eglot is the Emacs client for the @dfn{Language Server Protocol}
(@acronym{LSP}). The name ``Eglot'' is an acronym that stands for
@ifhtml
``@emph{E}macs Poly@emph{glot}''.
@end ifhtml
@ifnothtml
``Emacs polyGLOT''.
@end ifnothtml
@footnote{ A @dfn{polyglot} is a person who is able to use several
languages. } Eglot provides infrastructure and a set of commands for
enriching the source code editing capabilities of Emacs via LSP@. LSP
is a standardized communications protocol between source code editors
(such as Emacs) and language servers---programs external to Emacs which
analyze the source code on behalf of Emacs. The protocol allows Emacs
to receive various source code services from the server, such as
description and location of function calls, types of variables, class
definitions, syntactic errors, etc. This way, Emacs doesn't need to
implement the language-specific parsing and analysis capabilities in its
own code, but is still capable of providing sophisticated editing
features that rely on such capabilities, such as automatic code
completion, go-to definition of function/class, documentation of symbol
at-point, refactoring, on-the-fly diagnostics, and more.
Eglot itself is completely language-agnostic, but it can support any
programming language for which there is a language server and an Emacs
major mode.
This manual documents how to configure, use, and customize Eglot. To
read this manual from within Emacs, type @kbd{M-x eglot-manual
@key{RET}}.
@insertcopying
@menu
* Quick Start:: For the impatient.
* Eglot and LSP Servers:: How to work with language servers.
* Using Eglot:: Important Eglot commands and variables.
* Customizing Eglot:: Eglot customization and advanced features.
* Advanced server configuration:: Fine-tune a specific language server
* Multi-server support:: Use more than one server in a buffer
* Extending Eglot:: Writing Eglot extensions in Elisp
* Troubleshooting Eglot:: Troubleshooting and reporting bugs.
* GNU Free Documentation License:: The license for this manual.
* Index::
@end menu
@end ifnottex
@node Quick Start
@chapter Quick Start
@cindex quick start
This chapter provides concise instructions for setting up and using
Eglot with your programming project in common usage scenarios. For more
detailed instructions regarding Eglot setup, @pxref{Eglot and LSP
Servers}. @xref{Using Eglot}, for detailed description of using Eglot,
and see @ref{Customizing Eglot}, for adapting Eglot to less common use
patterns.
Here's how to start using Eglot with your programming project:
@enumerate
@item
Select and install a language server.
Eglot comes pre-configured for many popular language servers, see the
value of @code{eglot-server-programs}. If the server(s) mentioned there
satisfy your needs for the programming language(s) with which you want
to use Eglot, you just need to make sure those servers are installed on
your system and Eglot can find them.
Alternatively, install one or more servers of your choice and tell Eglot
where to find them. To do that, you may add to the value of
@code{eglot-server-programs}, as described in @ref{Setting Up LSP
Servers} or have Eglot prompt you about it (@pxref{Eglot Commands}).
@item
Turn on Eglot for your project.
To start using Eglot for a project, type @kbd{M-x eglot @key{RET}} in a
buffer visiting any file that belongs to the project. This starts the
language server configured for the programming language of that buffer,
and causes Eglot to start @dfn{managing} file-visiting buffers related
to that programming language. This includes files that are already
visited at the time the @code{eglot} command is invoked, as well as any
files visited after this invocation.
The notion of a ``project'' used by Eglot is the same Emacs uses
(@pxref{Projects,,, emacs, GNU Emacs Manual}): in the simplest case, the
``project'' is the single file you are editing, but it can also be all
the files in a single directory or a directory tree under some version
control system, such as Git.
There are alternate ways of starting Eglot; see @ref{Starting Eglot}
for details.
@item
Use Eglot.
Most Eglot facilities are integrated into Emacs features, such as ElDoc,
Flymake, Xref, and Imenu. However, Eglot also provides commands of its
own, mainly to perform tasks by the language server, such as @kbd{M-x
eglot-rename} (to rename an identifier across the entire project),
@kbd{M-x eglot-format} (to reformat and reindent code), and some others.
@xref{Eglot Commands}, for the detailed list of Eglot commands.
@item
That's it!
@end enumerate
@node Eglot and LSP Servers
@chapter Eglot and LSP Servers
This chapter describes how to set up Eglot for your needs, and how to
start it.
@menu
* Setting Up LSP Servers:: How to configure LSP servers for your needs.
* Starting Eglot:: Ways of starting Eglot for your project.
* Shutting Down LSP Servers::
@end menu
@node Setting Up LSP Servers
@section Setting Up LSP Servers
@cindex setting up LSP server for Eglot
@cindex LSP server for Eglot, setting up
@cindex language server for Eglot
For Eglot to be useful, it must first be combined with a suitable
language server. Usually, that means running the server program locally
as a child process of Emacs (@pxref{Processes,,, elisp, GNU Emacs Lisp
Reference Manual}) and communicating with it via the standard input and
output streams.
The language server program must be installed separately, and is not
further discussed in this manual; refer to the documentation of the
particular server(s) you want to install.
To use a language server, Eglot must know how to start it and which
programming languages each server supports. This information is
commonly provided by the variable @code{eglot-server-programs}.
@defvar eglot-server-programs
This variable associates major modes with names and command-line
arguments of the language server programs corresponding to the
programming language of each major mode. It provides all the
information that Eglot needs to know about the programming language of
the source you are editing.
The value of the variable is an alist, whose elements are of the form
@w{@code{(@var{major-mode} . @var{server})}}.
The @var{major-mode} of the alist elements can be either a symbol of an
Emacs major mode or a list of the form @w{@code{(@var{mode} :language-id
@var{id})}}, with @var{mode} being a major-mode symbol and @var{id} a
string that identifies the language to the server (if Eglot cannot by
itself convert the major-mode to the language identifier string required
by the server). In addition, @var{major-mode} can be a list of several
major modes specified in one of the above forms -- this means a running
instance of the associated server is responsible for files of multiple
major modes or languages in the project.
The @var{server} part of the alist elements can be one of the following:
@table @code
@item (@var{program} @var{args}@dots{})
This says to invoke @var{program} with zero or more arguments
@var{args}; the program is expected to communicate with Emacs via the
standard input and standard output streams.
@item (@var{program} @var{args}@dots{} :initializationOptions @var{options}@dots{})
@var{program} is invoked with @var{args} but @var{options} specifies how
to construct the @samp{:initializationOptions} JSON object to pass the
server on during the LSP handshake (@pxref{Advanced server
configuration}).
@item (@var{host} @var{port} @var{args}@dots{})
Here @var{host} is a string and @var{port} is a positive integer
specifying a TCP connection to a remote server. The @var{args} are
passed to @code{open-network-stream}, e.g.@: if the connection needs to
use encryption or other non-default parameters (@pxref{Network,,, elisp,
GNU Emacs Lisp Reference Manual}).
@item (@var{program} @var{args}@dots{} :autoport @var{moreargs}@dots{})
@var{program} is started with a command line constructed from @var{args}
followed by an available server port and the rest of arguments in
@var{moreargs}; Eglot then establishes a TCP connection with the server
via that port on the local host.
@item @var{function}
This should be a function of a single argument: non-@code{nil} if the
connection was requested interactively (e.g., by the @code{eglot}
command), otherwise @code{nil}. The function should return a value of
any of the forms described above. This allows interaction with the user
for determining the program to start and its command-line arguments.
@end table
@end defvar
Eglot comes with a fairly complete set of associations of major-modes to
popular language servers predefined. If you need to add server
associations to the default list, use @code{add-to-list}. For example,
if there is a hypothetical language server program @command{fools} for
the language @code{Foo} which is supported by an Emacs major-mode
@code{foo-mode}, you can add it to the alist like this:
@lisp
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
'(foo-mode . ("fools" "--stdio"))))
@end lisp
This will invoke the program @command{fools} with the command-line
argument @option{--stdio} in support of editing source files for which
Emacs turns on @code{foo-mode}, and will communicate with the program
via the standard streams. As usual with invoking programs, the
executable file @file{fools} should be in one of the directories
mentioned by the @code{exec-path} variable (@pxref{Subprocess
Creation,,, elisp, GNU Emacs Lisp Reference Manual}), for Eglot to be
able to find it.
Sometimes, multiple servers are acceptable alternatives for handling a
given major-mode. In those cases, you may combine the helper function
@code{eglot-alternatives} with the functional form of
@code{eglot-server-programs}.
@lisp
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
`(foo-mode . ,(eglot-alternatives
'(("fools" "--stdio")
("phewls" "--fast"))))))
@end lisp
If you have @command{fools} and @command{phewls} installed, the function
produced by @code{eglot-alternatives} will prompt for the server to use
in @code{foo-mode} buffers. Else it will use whichever is available.
@node Starting Eglot
@section Starting Eglot
@cindex starting Eglot
@cindex activating Eglot for a project
@findex eglot
The most common way to start Eglot is to simply visit a source file of a
given language and use the command @kbd{M-x eglot}. This starts the
language server suitable for the visited file's major-mode, and attempts
to connect to it. If the connection to the language server is
successful, you will see the @code{[eglot:@var{project}]} indicator on
the mode line which reflects the server that was started. If the server
program couldn't be started or connection to it failed, you will see an
error message; in that case, try to troubleshoot the problem as
described in @ref{Troubleshooting Eglot}. Once a language server was
successfully started and Eglot connected to it, you can immediately
start using the Emacs features supported by Eglot, as described in
@ref{Eglot Features}.
A single Eglot session for a certain major-mode usually serves all the
buffers under that mode which visit files from the same project, so you
don't need to invoke @kbd{M-x eglot} again when you visit another file
from the same project which is edited using the same major-mode. This
is because Eglot uses the Emacs project infrastructure, as described in
@ref{Eglot and Buffers}, and this knows about files that belong to the
same project. Thus, after starting an Eglot session for some buffer,
that session is automatically reused when visiting files in the same
project with the same major-mode.
@findex eglot-ensure
Alternatively, you could configure Eglot to start automatically for one
or more major-modes from the respective mode hooks. Here's an example
for a hypothetical @code{foo-mode}:
@lisp
(add-hook 'foo-mode-hook 'eglot-ensure)
@end lisp
@noindent
The function @code{eglot-ensure} will start an Eglot session for each
buffer in which @code{foo-mode} is turned on, if there isn't already an
Eglot session that handles the buffer. Note that this variant of
starting an Eglot session is non-interactive, so it should be used only
when you are confident that Eglot can be started reliably for any file
which may be visited with the major-mode in question.
Note that it's often difficult to establish this confidence fully, so it
may be wise to use the interactive command @code{eglot} instead. You
only need to invoke it once per project, as all other files visited
within the same project will automatically be managed with no further
user intervention needed.
When Eglot connects to a language server for the first time in an Emacs
session, it runs the hook @code{eglot-connect-hook} (@pxref{Other
Variables}).
@node Shutting Down LSP Servers
@section Shutting Down LSP Servers
@cindex shutting down LSP server
When Eglot is turned on, it arranges for turning itself off
automatically if the language server process terminates. Turning off
Eglot means that it shuts down the server connection, ceases its
management of all the buffers that use the server connection which was
terminated, deactivates its minor mode, and restores the original values
of the Emacs variables that Eglot changed when it was turned on.
@xref{Eglot and Buffers}, for more details of what Eglot management of a
buffer entails.
@findex eglot-shutdown
You can also shut down a language server manually, by using the command
@kbd{M-x eglot-shutdown}. This prompts for the server (unless there's
only one connection and it's used in the current buffer), and then shuts
it down. By default, it also kills the server's events buffer
(@pxref{Troubleshooting Eglot}), but a prefix argument prevents that.
Alternatively, you can customize the variable @code{eglot-autoshutdown}
to a non-@code{nil} value, in which case Eglot will automatically shut
down the language server process when the last buffer served by that
language server is killed. The default of this variable is @code{nil},
so that visiting another file would automatically activate Eglot even
when the project which started Eglot with the server no longer has any
buffer associated with it. This default allows you to start a server
only once in each Emacs session.
@node Using Eglot
@chapter Using Eglot
This chapter describes in detail the features that Eglot provides and
how it does that. It also provides reference sections for Eglot
commands and variables.
@menu
* Eglot Features::
* Eglot and Buffers::
* Eglot Commands::
@end menu
@node Eglot Features
@section Eglot Features
@cindex features in buffers supported by Eglot
While Eglot is enabled in a buffer, it is said to be @dfn{managing} it,
using LSP and the specific capabilities of the language server to
activate and enhance modern IDE features in Emacs. Some of these
features are provided via other Emacs packages, and some via Eglot
directly (@pxref{Eglot Commands}).
Here's an overview of the main features that Eglot provides:
@itemize @bullet
@item
At-point documentation: when point is near a symbol or an identifier,
information about the identifier's significance in the program (its
function or method signature, its type, its custom documentation string,
etc.) is made available via the ElDoc package (@pxref{Programming
Language Doc,,, emacs, GNU Emacs Manual}).
@item
On-the-fly diagnostic annotations, via the Flymake package
(@pxref{Top,,, Flymake, GNU Flymake manual}). Eglot's Flymake backend
replaces other Flymake backends while it is managing a buffer, and
enhances diagnostics with interactive server-suggested fixes (so-called
@dfn{code actions}, @pxref{Eglot Commands}).
@item
Finding definitions and uses of identifiers, via Xref (@pxref{Xref,,,
emacs, GNU Emacs Manual}). Eglot provides a backend for the Xref
capabilities which uses the language server's understanding of the
program source. In particular, it eliminates the need to generate tags
tables (@pxref{Tags tables,,, emacs, GNU Emacs Manual}) for languages
which are only supported by the @code{etags} backend.
@item
Buffer navigation by name of function, class, method, etc., via Imenu
(@pxref{Imenu,,, emacs, GNU Emacs Manual}). Eglot provides its own
variant of @code{imenu-create-index-function}, which generates the index
for the buffer based on the language server's program source analysis.
@item
Enhanced completion of symbol at point by the @code{completion-at-point}
command (@pxref{Symbol Completion,,, emacs, GNU Emacs Manual}). This
uses the language server's parser data for the completion candidates.
@item
Server-suggested code refactorings. The ElDoc package is also leveraged
to retrieve so-called @dfn{code actions} nearby point. When such
suggestions are available they are annotated with a special indication
and can be easily invoked by the user with the @code{eglot-code-action}
command (@pxref{Eglot Commands}).
@item
On-the-fly succinct informative annotations, so-called @dfn{inlay
hints}. Eglot adds special intangible text nearby certain identifiers,
be it the type of a variable, or the name of a formal parameter in a
function call. @xref{Eglot Commands}, and the
@code{eglot-inlay-hints-mode} minor mode.
@item
Enhanced source code fontification via LSP @dfn{semantic tokens}. Eglot
can leverage the language server's understanding of the role and meaning
of identifiers in the code to provide more accurate syntax highlighting.
@xref{Eglot Commands}, and the @code{eglot-semantic-tokens-mode} minor
mode.
@item
Display of function call and type hierarchies via the
@code{eglot-show-call-hierarchy} and @code{eglot-show-type-hierarchy}
commands (@pxref{Eglot Commands}).
@item
Code reformatting via the @code{eglot-format} and related commands
(@pxref{Eglot Commands}). Automatic reformatting of source code is also
supported and is activated automatically as you type.
@item
If a completion package such as the Company package (a popular
third-party completion package providing @code{company-mode}), is
installed, Eglot enhances it by providing completion candidates based on
the language server's analysis of the source code. (Company can be
installed from GNU ELPA.)
@item
If YASnippet, a popular third-party package for automatic insertion of
code templates (snippets), is installed, and the language server
supports snippet completion candidates, Eglot arranges for the
completion package to instantiate these snippets using YASnippet.
(YASnippet can be installed from GNU ELPA.)
@item
If the popular third-party package @code{markdown-mode} is installed,
and the server provides at-point documentation formatted as Markdown in
addition to plain text, Eglot arranges for the ElDoc package to enrich
this text with fontifications and other nice formatting before
displaying it to the user. This makes the documentation shown by ElDoc
look nicer on display.
@item
In addition to enabling and enhancing other features and packages, Eglot
also provides a number of user commands based on the capabilities of
language servers. Examples include renaming symbols with
@kbd{eglot-rename} and asking to automatically correct problems with
@kbd{eglot-code-actions}. @xref{Eglot Commands}.
@end itemize
Not all servers support the full set of LSP capabilities, but most of
them support enough to enable the basic set of features mentioned above.
Conversely, some servers offer capabilities for which no equivalent
Emacs package exists yet, and so Eglot cannot (yet) expose these
capabilities to Emacs users. However, @xref{Extending Eglot}.
Finally, it's worth noting that, by default, Eglot generally turns on
all features that it @emph{can} turn on. It's possible to opt out of
features via the @code{eglot-ignored-server-capabilities} user option
(@pxref{Customizing Eglot}) and the @code{eglot-managed-mode-hook} hook
that runs after Eglot starts managing a buffer (@pxref{Eglot and
Buffers}).
@node Eglot and Buffers
@section Buffers, Projects, and Eglot
@cindex buffers managed by Eglot
@cindex projects and Eglot
@cindex workspace
One of the main strong points of using a language server is that a
language server has a broad view of the program: it considers more than
just the single source file you are editing. Ideally, the language
server should know about all the source files of your program which are
written in the language supported by the server. In LSP parlance, the
set of the source files of a program is known as a @dfn{workspace}. The
Emacs equivalent of a workspace is a @dfn{project} (@pxref{Projects,,,
emacs, GNU Emacs Manual}). Eglot fully supports Emacs projects, and
considers the file in whose buffer Eglot is turned on as belonging to a
project. In the simplest case, that file is the entire project, i.e.@:
your project consists of a single file. But there are other more
complex projects:
@itemize @bullet
@item
A single-directory project: several source files in a single common
directory.
@item
A VC project: source files in a directory hierarchy under some VCS,
e.g.@: a VCS repository (@pxref{Version Control,,, emacs, GNU Emacs
Manual}).
@item
An EDE project: source files in a directory hierarchy managed via the
Emacs Development Environment (@pxref{EDE,,, emacs, GNU Emacs
Manual}).
@end itemize
Eglot uses Emacs's project management infrastructure to figure out which
files and buffers belong to what project, so any kind of project
supported by that infrastructure is automatically supported by Eglot.
When Eglot starts a server program, it does so in the project's root
directory, which is usually the top-level directory of the project's
directory hierarchy. This ensures the language server has the same
comprehensive view of the project's files as you do.
For example, if you visit the file @file{~/projects/fooey/lib/x.foo} and
@file{x.foo} belongs to a project rooted at @file{~/projects/fooey}
(perhaps because a @file{.git} directory exists there), then @kbd{M-x
eglot} causes the server program to start with that root as the current
working directory. The server then will analyze not only the file
@file{lib/x.foo} you visited, but likely also all the other @file{*.foo}
files under the @file{~/projects/fooey} directory.
In some cases, additional information specific to a given project will
need to be provided to the language server when starting it. The
variable @code{eglot-workspace-configuration} (@pxref{Customizing
Eglot}) exists for that purpose. It specifies the parameters and their
values to communicate to each language server which needs that.
When Eglot is active for a project, the project's buffers are treated
specially in several ways:
@itemize @bullet
@cindex mode-line indication of language server
@cindex mouse clicks on mode-line, and Eglot
@vindex eglot-menu
@item
All of the project's file-visiting buffers under the same major-mode are
served by a single language server connection. (If the project uses
several programming languages, there will usually be a separate server
connection for each group of files written in the same language and
using the same Emacs major-mode.) Eglot adds the
@samp{[eglot:@var{project}]} indication to the mode line of each such
buffer, where @var{server} is the name of the server and @var{project}
identifies the project by its root directory. Clicking the mouse on the
Eglot mode-line indication activates a menu with server-specific items.
The layout of the Eglot mode-line can be changed by customizing
@code{eglot-mode-line-format} (@pxref{Customization Variables}).
@item
For each buffer in which Eglot is active, it notifies the language
server that Eglot is @dfn{managing} the file visited by that buffer.
This tells the language server that the file's contents on disk may no
longer be up-to-date due to unsaved edits. Eglot reports to the server
any changes in the text of each managed buffer, to make the server aware
of unsaved changes. This includes your editing of the buffer and also
changes done automatically by other Emacs features and commands.
Killing a buffer relinquishes its management by Eglot and notifies the
server that the file on disk is up-to-date.
@item
When you visit a file under the same project, whether an existing or a
new file, its buffer is automatically added to the set of buffers
managed by Eglot, and the server which supports the buffer's major-mode
is notified about that. Thus, visiting a non-existent file
@file{/home/joe/projects/fooey/lib/y.foo} in the above example will
notify the server of the @file{*.foo} files' language that a new file
was added to the project, even before the file appears on disk. The
special Eglot minor mode is also turned on automatically in the buffer
visiting the file.
@item
Eglot turns on a special minor mode in each buffer it manages. This
minor mode ensures the server is notified about files Eglot manages.
Unlike other minor-modes, this special minor mode is @emph{not}
activated manually by the user, but automatically, as the result of
starting an Eglot session for the buffer. When Eglot stops managing the
buffer, the minor mode is turned off, and all the settings that Eglot
changed are restored to their original values.
@vindex eglot-managed-mode-hook
@vindex eglot-managed-p
@item
The minor mode's main job is to ``hook up'' Eglot to other Emacs
functionality, i.e. arrange for these features to receive information
from the language server, by changing special variables controlling
these features. @xref{Eglot Features}.
@item
To customize this, Eglot's special minor mode provides a hook variable
@code{eglot-managed-mode-hook} specifically to alter Eglot's interaction
with these variables in each buffer. This hook is run both when the
minor mode is turned on and when it's turned off; use the function
@code{eglot-managed-p} to tell if current buffer is still being managed
or not.
@end itemize
For example, to turn off @dfn{inlay hints} and @dfn{semantic tokens} by
default but still retain the ability to turn them on again
interactively use this:
@lisp
(add-hook 'eglot-managed-mode-hook
(lambda ()
(eglot-inlay-hints-mode -1)
(eglot-semantic-tokens-mode -1)))
@end lisp
@node Eglot Commands
@section Eglot Commands
@cindex commands, Eglot
This section provides a reference for the most commonly used Eglot
commands:
@ftable @code
@item M-x eglot
This command adds the current buffer and the file it visits to the group
of buffers and files managed by Eglot on behalf of a suitable language
server. If a language server for the buffer's @code{major-mode}
(@pxref{Major Modes,,, emacs, GNU Emacs Manual}) is not yet running, it
will be started; otherwise the buffer and its file will be added to
those managed by an existing server session.
The command attempts to figure out the buffer's major mode and the
suitable language server; in case it fails, it might prompt for the
major mode to use and for the server program to start. If invoked with
@kbd{C-u}, it always prompts for the server program, and if invoked with
@kbd{C-u C-u}, it also prompts for the major mode.
If the language server is successfully started and contacted, this
command arranges for any other buffers belonging to the same project and
using the same major mode to use the same language server session. That
includes any buffers created by visiting files after this command
succeeds to connect to a language server.
All the Emacs features that are capable of using Eglot services
(@pxref{Eglot Features}) are automatically configured by this command to
start using the language server via Eglot. To customize which Emacs
features will be configured to use Eglot, use the
@code{eglot-stay-out-of} option (@pxref{Customizing Eglot}).
@item M-x eglot-reconnect
This command shuts down the current connection to the language server
and immediately restarts it using the same options used originally.
This can sometimes be useful to unclog a partially malfunctioning server
connection.
@item M-x eglot-shutdown
This command shuts down a language server. It prompts for a language
server to shut down (unless there's only one server session, and it
manages the current buffer). Then the command shuts down the server and
stops managing the buffers the server was used for. Emacs features
(@pxref{Eglot Features}) that Eglot configured to work with the language
server are restored back to their original configuration.
Normally, this command kills the buffers used for communicating with the
language server, but if invoked with a prefix argument @kbd{C-u}, the
command doesn't kill those buffers, allowing them to be used for
diagnostics and problem reporting (@pxref{Troubleshooting Eglot}).
@item M-x eglot-shutdown-all
This command shuts down all the language servers active in the current
Emacs session. As with @code{eglot-shutdown}, invoking this command
with a prefix argument avoids killing the buffers used for
communications with the language servers.
@item M-x eglot-rename
This command renames the program symbol (a.k.a.@: @dfn{identifier}) at
point to another name. It prompts for the new name of the symbol, and
then modifies all the files in the project which are managed by the
language server of the current buffer to implement the renaming.
@item M-x eglot-format
This command reformats the active region according to the
language server rules. If no region is active, it reformats the entire
current buffer.
@item M-x eglot-format-buffer
This command reformats the current buffer, in the same manner as
@code{eglot-format} does.
@cindex code actions
@item M-x eglot-code-actions
@itemx M-x eglot-code-action-organize-imports
@itemx M-x eglot-code-action-quickfix
@itemx M-x eglot-code-action-extract
@itemx M-x eglot-code-action-inline
@itemx M-x eglot-code-action-rewrite
These commands allow you to invoke the so-called @dfn{code actions}:
requests for the language server to provide editing commands for
correcting, refactoring or beautifying your code. These commands may
affect more than one visited file belonging to the project.
The command @code{eglot-code-actions} asks the server if there are any
code actions for any point in the buffer or contained in the active
region. If there are, you have the choice to execute one of them via
the minibuffer.
A common use of code actions is fixing the Flymake error diagnostics
issued by Eglot (@pxref{Top,,, Flymake, GNU Flymake manual}). Clicking
on a diagnostic with @kbd{mouse-2} invokes
@code{eglot-code-actions-at-mouse} which pops up a menu of available
code actions. The variable @code{eglot-diagnostics-map} can be used to
control the mouse binding.
Other commands execute a specific code action. For example,
@code{eglot-code-action-organize-imports} rearranges the program's
@dfn{imports}---declarations of modules whose capabilities the program
uses.
@cindex inlay hints
@item M-x eglot-inlay-hints-mode
This command toggles LSP @dfn{inlay hints} on and off for the current
buffer. Inlay hints are small text annotations to specific parts of the
whole buffer, not unlike diagnostics, but designed to help readability
instead of indicating problems. For example, a C++ language server can
serve hints about positional parameter names in function calls and a
variable's automatically deduced type. Inlay hints help the user not
have to remember these things by heart.
@cindex momentary inlay hints
@item eglot-momentary-inlay-hints
When bound to a single key in @code{eglot-mode-map}
(@pxref{Customization Variables}), this will arrange for inlay hints to
be displayed as long as the key is held down, and then hidden shortly
after it is released. The best way to set it up is something like this:
@lisp
(define-key eglot-mode-map [f7] 'eglot-momentary-inlay-hints)
@end lisp
@noindent
Note that Emacs doesn't support binding to \"key up\" events, so this
command offers an approximation by estimating your system keyboard delay
and repeat rate.
@cindex semantic tokens
@item M-x eglot-semantic-tokens-mode
This command toggles LSP @dfn{semantic tokens} fontification on and off
for the current buffer. Semantic tokens provide enhanced syntax
highlighting based on the language server's semantic analysis of the
code, going beyond traditional regular-expression-based fontification.
For example, the server can distinguish between different kinds of
variables (parameters, local variables, fields) or indicate whether a
function is being declared or called.
@vindex eglot-semantic-token-types
@vindex eglot-semantic-token-modifiers
The @code{eglot-semantic-faces} customization group contains the user
options @code{eglot-semantic-token-types} and
@code{eglot-semantic-token-modifiers}, which control which semantic
token types and modifiers reported by the language server Eglot should
consider when fontifying. For performance reasons, the server
connection has to be restarted before changes take effect.
@cindex semantic token faces
The @code{eglot-semantic-faces} customization group also contains the
face definitions for controlling the appearance of each token.
@cindex type hierarchy
@item M-x eglot-show-type-hierarchy
Pop up a special buffer showing a interactive tree which represents a
hierarchy of subtypes and supertypes for the symbol at point.
@cindex call hierarchy
@item M-x eglot-call-type-hierarchy
Pop up a special buffer showing a interactive tree which represents a
hierarchy of callers and callee for the symbol at point.
@end ftable
The following Eglot commands are used less commonly, mostly for
diagnostic and troubleshooting purposes:
@ftable @code
@item M-x eglot-events-buffer
This command pops up the events buffer used for communication with the
language server of the current buffer.
@item M-x eglot-stderr-buffer
This command pops up the buffer with the debug info printed by the
language server to its standard error stream.
@item M-x eglot-forget-pending-continuations
Forget pending requests for the server of the current buffer.
@c FIXME: Better description of the need.
@item M-x eglot-signal-didChangeConfiguration
This command updates the language server configuration according to the
current value of the variable @code{eglot-workspace-configuration}
(@pxref{Customizing Eglot}).
@item M-x eglot-clear-status
Clear the last JSONRPC error for the server of the current buffer.
Eglot keeps track of erroneous situations encountered by the server in
its mode-line indication so that the user may inspect the communication
leading up to it (@pxref{Troubleshooting Eglot}). If the situation is
deemed uninteresting or temporary, this command can be used to
``forget'' the error. Note that the command @code{M-x eglot-reconnect}
can sometimes be used to unclog a temporarily malfunctioning server.
@end ftable
As described in @ref{Eglot Features} most features associated with Eglot
are actually provided by other Emacs packages and features, and Eglot
only enhances them by allowing them to use the information coming from
the language servers. For completeness, here's the list of commands of
those other packages that are very commonly used in Eglot-managed
buffers:
@c Not @ftable, because the index entries should mention Eglot
@table @code
@cindex ElDoc, and Eglot
@cindex documentation using Eglot
@item M-x eldoc
Ask the ElDoc system for help at point.
@cindex Flymake, and Eglot
@cindex on-the-fly diagnostics using Eglot
@item M-x flymake-show-buffer-diagnostics
Ask Flymake system to display diagnostics for the current buffer.
@item M-x flymake-show-project-diagnostics
Ask Flymake to list diagnostics for all the files in the current
project.
@cindex xref, and Eglot
@cindex finding definitions of identifiers using Eglot
@item M-x xref-find-definitions
Ask Xref to go the definition of the identifier at point.
@cindex imenu navigation using Eglot
@item M-x imenu
Let the user navigate the program source code using buffer index,
categorizing program elements by syntactic class (class, method,
variable, etc.) and offering completion.
@cindex symbol completion using Eglot
@item M-x completion-at-point
Request completion of the symbol at point.
@end table
@node Customizing Eglot
@chapter Customizing Eglot
@cindex customizing Eglot
To have Eglot behave like you want it, sometimes it suffices to
customize Emacs packages and features that Eglot uses but to do so for
all of Emacs (regardless of Eglot) . For example, to configure the
amount of space taken up by documentation in the echo area, customize
the ElDoc variable @code{eldoc-echo-area-use-multiline-p}. To configure
Flymake faces used for errors and warnings, customize the
@code{flymake-error} and @code{flymake-warning} faces.
Compared to the breadth of its functionality, Eglot itself has a
relatively small number of customization variables. There is
additionally a set of variables that are usually set from Elisp snippets
(@pxref{Init File,,, emacs, The GNU Emacs Manual}).
Other times, it's necessary to have finer control of Eglot's interaction
with these features. @xref{More Customization}.
@menu
* Customization Variables::
* Other Variables::
* More Customization::
@end menu
@node Customization Variables
@section Customization Variables
@cindex variables, Eglot
This section provides a reference for the Eglot user options.
@vtable @code
@item eglot-autoreconnect
This option controls the ability to reconnect automatically to the
language server when Eglot detects that the server process terminated
unexpectedly. The default value @code{3} means to attempt reconnection
only if the previous successful connection lasted for more than that
number of seconds; a different positive value changes the minimal length
of the connection to trigger reconnection. A value of @code{t} means
always reconnect automatically, and @code{nil} means never reconnect (in
which case you will need to reconnect manually using @kbd{M-x eglot}).
@item eglot-connect-timeout
This specifies the number of seconds before connection attempt to a
language server times out. The value of @code{nil} means never time
out. The default is 30 seconds.
@item eglot-sync-connect
This setting is mainly important for connections which are slow to
establish. Whereas the variable @code{eglot-connect-timeout} controls
how long to wait for, this variable controls whether to block Emacs's
user interface while waiting. The default value is @code{3}; a positive
value means block for that many seconds, then wait for the connection in
the background. The value of @code{t} means block during the whole
waiting period. The value of @code{nil} or @code{0} means don't block
at all during the waiting period.
@item eglot-events-buffer-config
This configures the size and format of the Eglot events buffer.
@xref{Eglot Commands, eglot-events-buffer}, for how to access that
buffer. If the value is changed, the connection should be restarted
using @kbd{M-x eglot-reconnect} for the new value to take effect.
@c FIXME: Shouldn't the defcustom do this by itself using the :set
@c attribute? Maybe not because reconnecting is a complex task.
@xref{Troubleshooting Eglot}, for when this could be useful.
@item eglot-autoshutdown
If this is non-@code{nil}, Eglot shuts down a language server when the
last buffer managed by it is killed. @xref{Shutting Down LSP Servers}.
The default is @code{nil}; if you want to shut down a server, use
@kbd{M-x eglot-shutdown} (@pxref{Eglot Commands}).
@item eglot-confirm-server-edits
Various Eglot commands and code actions result in the language server
sending editing commands to Emacs. If this option's value is
non-@code{nil}, Eglot will ask for confirmation before performing edits
proposed by the language server. This option's value can be crafted to
require this confirmation for specific commands or only when the edit
affects files not yet visited by the user. Consult this option's
docstring for more information.
@item eglot-ignored-server-capabilities
This variable's value is a list of language server capabilities that
Eglot should not use. The default is @code{nil}: Eglot uses all of the
capabilities supported by each server.
@item eglot-extend-to-xref
If this is non-@code{nil}, and @kbd{M-.} (@code{xref-find-definitions})
lands you in a file outside of your project, such as a system-installed
library or header file, transiently consider that file as managed by the
same language server. That file is still outside your project
(i.e. @code{project-find-file} won't find it), but Eglot and the server
will consider it to be part of the workspace. The default is
@code{nil}.
@item eglot-mode-map
This variable is the keymap for binding Eglot-related command. It is in
effect only as long as the buffer is managed by Eglot. By default, it
is empty, with the single exception: @kbd{C-h .} is remapped to invoke
@code{eldoc-doc-buffer}. You can bind additional commands in this map.
For example:
@lisp
(define-key eglot-mode-map (kbd "C-c r") 'eglot-rename)
(define-key eglot-mode-map (kbd "C-c o") 'eglot-code-action-organize-imports)
(define-key eglot-mode-map (kbd "C-c h") 'eldoc)
(define-key eglot-mode-map (kbd "<f6>") 'xref-find-definitions)
(define-key eglot-mode-map (kbd "<f7>") 'eglot-momentary-inlay-hints)
@end lisp
@cindex progress
@item eglot-report-progress
Set this variable to non-nil if you'd like progress notifications coming
from the language server to be handled by Emacs's progress reporting
facilities. If the value is the symbol @code{messages} the message
buffer is used, else the progress is reported in the mode line.
@cindex request cancellation
@item eglot-advertise-cancellation
Setting this variable to true causes Eglot to send special cancellation
notification for certain stale client request. This may help some LSP
servers avoid doing costly but ultimately useless work on behalf of the
client, improving overall performance.
@item eglot-code-action-indications
This variable controls the indication of code actions available at
point. Value is a list of symbols, more than one can be specified:
@itemize @minus
@item
@code{eldoc-hint}: ElDoc is used to hint about at-point actions.
@item
@code{margin}: A special indicator appears in the margin of the line
that point is currently on.
@item
@code{nearby}: An interactive special indicator appears near point.
@item
@code{mode-line}: An interactive special indicator appears in the mode
line.
@end itemize
@code{margin} and @code{nearby} are incompatible. If the list is empty,
ElDoc will not hint about at-point actions.
@item eglot-code-action-indicator
This variable is a string determining what the special indicator looks
like.
@item eglot-mode-line-format
This variables controls the shape and look of Eglot's mode line. Its
value is a mode line ``construct'', generally a list of symbols and
strings. The following symbols are meaningful and useful for Eglot's
mode line:
@itemize @minus
@item
@code{eglot-mode-line-menu}: access Eglot's main menu. See also
@code{eglot-menu-string};
@item
@code{eglot-mode-line-session}: indicate current project and access
current session's menu;
@item
@code{eglot-mode-line-error}: an indication of recent LSP errors;
@item
@code{eglot-mode-line-pending-requests}: number of pending LSP requests;
@item
@code{eglot-mode-line-progress}: progress reporter widgets;
@item
@code{eglot-mode-line-action-suggestion}: LSP code actions at point.
@end itemize
@end vtable
@node Other Variables
@section Other Variables
This section provides a reference for Eglot variables that are meant to
be changed from Elisp snippets.
@c @table, not @vtable, because some of the variables are indexed
@c elsewhere
@table @code
@item eglot-server-programs
This variable determines which language server to start for each
supported major mode, and how to invoke that server's program.
@xref{Setting Up LSP Servers}, for the details.
@vindex eglot-strict-mode
@item eglot-strict-mode
This is @code{nil} by default, meaning that Eglot is generally lenient
about non-conforming servers. If you need to debug a server, set this
to @w{@code{(disallow-non-standard-keys enforce-required-keys)}}.
@vindex eglot-server-initialized-hook
@item eglot-server-initialized-hook
A hook run after the server object is successfully initialized (which
includes launching the process) but before any LSP communication is
attempted. Each function receives a @code{eglot-lsp-server} instance as
argument.
@vindex eglot-connect-hook
@item eglot-connect-hook
A hook run after the LSP connection to the server is successfully
established. Each function receives a @code{eglot-lsp-server} instance
as argument. @xref{Starting Eglot}.
@item eglot-managed-mode-hook
A hook run after Eglot started or stopped managing a buffer.
@xref{Eglot and Buffers}, for details of its usage.
@vindex eglot-stay-out-of
@item eglot-stay-out-of
This variable's value lists Emacs features that Eglot shouldn't
automatically try to manage on the user's behalf. It is useful, for
example, when you need to use non-LSP Flymake or Company back-ends. To
have Eglot stay away from some Emacs feature, add that feature's symbol
or a regexp that will match a symbol's name to the list: for example,
the symbol @code{xref} to leave Xref alone, or the string @samp{company}
to stay away from your Company customizations. Here's an example:
@lisp
(add-to-list 'eglot-stay-out-of 'flymake)
@end lisp
Note that you can still configure the excluded Emacs features manually
to use Eglot in your @code{eglot-managed-mode-hook} or via some other
mechanism.
@end table
@node More Customization
@section More Customization
As explained earlier (@pxref{Eglot and Buffers}), Eglot hooks onto
existing Emacs packages and features by setting special variables in its
special minor mode. To gain finer control of Eglot's operation, the
@code{eglot-managed-mode-hook} should be used to tweak, subdue or
completely override Eglot's setting of these variables.
@itemize @bullet
@item
Eglot hooks onto ElDoc's @code{eldoc-documentation-functions} variable,
adding a number of functions to it:
@itemize @minus
@item @code{eglot-hover-eldoc-function}, to display general information
about an identifier.
@item @code{eglot-signature-eldoc-function}, to display function
signature information.
@item @code{eglot-highlight-eldoc-function}, to highlight nearby
manifestations of an identifier.
@item @code{eglot-code-action-suggestion}, to retrieve relevant code
actions at point.
@end itemize
A simple tweak to remove at-point identifier information for
hypothetical language @code{Foo} may look like:
@lisp
(add-hook 'foo-mode-hook
(lambda ()
(add-hook 'eglot-managed-mode-hook
(lambda ()
(remove-hook 'eldoc-documentation-functions
'eglot-hover-eldoc-function
nil t))
nil t)))
@end lisp
For more sophisticated changes, we can take advantage of ElDoc's
well-defined protocols. @xref{Programming Language Doc,,, emacs, GNU
Emacs Manual}. For instance, the functions in
@code{eldoc-display-functions} control displays of the at-point
documentation produced by @code{eldoc-documentation-functions}. As an
example, to ensure that hover documentation specifically is never output
into the Echo area (in all programming modes):
@lisp
(require 'cl-lib)
(defun my/special-eglot-hover-function (cb &rest _ignored)
"Same as `eglot-hover-eldoc-function`, but skip the echo area."
(eglot-hover-eldoc-function (lambda (info &rest _ignore)
(funcall cb info :echo 'skip))))
;; substitute 'eldoc-hover-eldoc-function with our "fixed" variant.
(add-hook
'eglot-managed-mode-hook
(lambda ()
(setq-local eldoc-documentation-functions
(cl-substitute #'my/special-eglot-hover-function
'eglot-hover-eldoc-function
eldoc-documentation-functions))))
@end lisp
@item
Eglot hooks onto Flymake's @code{flymake-diagnostic-functions} variable,
completely replacing its value with Eglot's own
@code{eglot-flymake-backend} function. Additional backends may be added
to work alongside Eglot's.
@lisp
(add-hook 'foo-mode-hook
(lambda ()
(add-hook 'eglot-managed-mode-hook
(lambda ()
(add-hook 'flymake-diagnostic-functions
#'my/special-foo-mode-backend
nil t))
nil t)))
@end lisp
@item
Eglot hooks onto Xref's @code{xref-backend-functions} variable, adding
its own @code{eglot-xref-backend} function to it.
@item
Eglot hooks onto Imenu's @code{imenu-create-index-function}.
@item
Eglot hooks onto Emacs's @code{completion-at-point-functions}.
@item
Eglot hooks onto Company's @code{company-backends} variable, ensuring
only the @code{company-capf} backend lives there. This ensures the same
set of completions as regular @code{completion-at-point}.
@item
Eglot hooks onto YASnippet by automatically activating
@code{yas-minor-mode} when needed to expand server-provided snippets.
@end itemize
@node Advanced server configuration
@chapter Advanced server configuration
Though many language servers work well out-of-the-box, most allow
fine-grained control of their operation via specific configuration
options that are transmitted over the LSP protocol and vary from server
to server. A small number of servers require such special configuration
to work acceptably, or even to work at all.
After having setup a server executable program in
@code{eglot-server-programs} (@pxref{Setting Up LSP Servers}) and
ensuring Eglot can invoke it, you may want to take advantage of some of
these options. You should first distinguish two main kinds of server
configuration:
@itemize @bullet
@item
Project-specific, applying to a specific project;
@item
User-specific, applying to all projects the server is used for.
@end itemize
When you have decided which kind you need, the following sections
teach how Eglot's user variables can be used to achieve it:
@menu
* Project-specific configuration::
* User-specific configuration::
* JSONRPC objects in Elisp::
@end menu
It's important to note that not all servers allow both kinds of
configuration, nor is it guaranteed that user options can be copied over
to project options, and vice-versa. When in doubt, consult your
language server's documentation.
It's also worth noting that some language servers can read these
settings from configuration files in the user's @code{HOME} directory or
in a project's directory. For example, the @command{pylsp} Python
server reads the file @file{~/.config/pycodestyle} for user
configuration. The @command{clangd} C/C++ server reads both
@file{~/.config/clangd/config.yaml} for user configuration and
@file{.clangd} for project configuration. It may be advantageous to use
these mechanisms instead of Eglot's, as this will probably work with
other LSP clients and may be easier to debug than options riding on the
LSP wire.
@node Project-specific configuration
@section Project-specific configuration
@vindex eglot-workspace-configuration
@cindex workspace configuration
To set project-specific settings, which the LSP specification calls
@dfn{workspace configuration}, the variable
@code{eglot-workspace-configuration} may be used.
This variable is a directory-local variable (@pxref{Directory Variables,
, Per-directory Local Variables, emacs, The GNU Emacs Manual}). It's
important to recognize that this variable really only makes sense when
set directory-locally. It usually does not make sense to set it
file-locally or in a major-mode hook.
The most common way to set @code{eglot-workspace-configuration } is
using a @file{.dir-locals.el} file in the root of your project. If you
can't do that, you may also set it from Elisp code via the
@code{dir-locals-set-class-variables} function. (@pxref{Directory Local
Variables,,, elisp, GNU Emacs Lisp Reference Manual}).
However you choose to set it, the variable's value is a plist
(@pxref{Property Lists,,, elisp, GNU Emacs Lisp Reference Manual}) with
the following format:
@lisp
(@var{:server1} @var{plist1} @var{:server2} @var{plist2} @dots{})
@end lisp
@noindent
Here, @var{:server1} and @var{:server2} are keywords whose names
identify the LSP language servers to target. Consult server
documentation to find out what name to use. @var{plist1} and
@var{plist2} are plists of options, possibly nesting other plists.
@findex eglot-show-workspace-configuration
When experimenting with workspace settings, you can use the command
@kbd{M-x eglot-show-workspace-configuration} to inspect and debug the
value of this variable in its final JSON form, ready to be sent to the
server (@pxref{JSONRPC objects in Elisp}). This helper command works
even before actually connecting to the server.
These variable's value doesn't take effect immediately. That happens
upon establishing the connection, in response to an explicit query from
the server, or when issuing the command @kbd{M-x
eglot-signal-didChangeConfiguration} which notifies the server during an
ongoing Eglot session.
@subsection Examples
For some users, setting @code{eglot-workspace-configuration} is a
somewhat daunting task. One of the reasons is having to manage the
general Elisp syntax of per-mode directory-local variables, which uses
alists (@pxref{Association Lists,,, elisp, GNU Emacs Lisp Reference
Manual}), and the specific syntax of Eglot's variable, which uses
plists. Some examples are useful.
Let's say you want to configure two language servers to be used in a
project written in a combination of the Python and Go languages. You
want to use the @command{pylsp} and @command{gopls} languages servers.
In the documentation of the servers in question (or in some other
editor's configuration file, or in some blog article), you find the
following configuration options in informal dotted-notation syntax:
@example
pylsp.plugins.jedi_completion.include_params: true
pylsp.plugins.jedi_completion.fuzzy: true
pylsp.pylint.enabled: false
gopls.usePlaceholders: true
@end example
To apply this to Eglot, and assuming you chose the
@file{.dir-locals.el} file method, the contents of that file could be:
@lisp
((nil
. ((eglot-workspace-configuration
. (:pylsp (:plugins (:jedi_completion (:include_params t
:fuzzy t)
:pylint (:enabled :json-false)))
:gopls (:usePlaceholders t)))))
(python-base-mode . ((indent-tabs-mode . nil)))
(go-mode . ((indent-tabs-mode . t))))
@end lisp
@noindent
Note how alists are used for associating Emacs mode names with other
alists, associating variable names with variable values. Then, pay
special attention to how the value of
@code{eglot-workspace-configuration} is a plist and @emph{not} an alist.
The above form sets the value of @code{eglot-workspace-configuration} in
all the buffers inside the project; each language server will then use
only the section of the parameters intended for it, and ignore the rest.
In our example, @command{pylsp} and @command{gopls} are solely
interested in the @code{:pylsp} and @code{:gopls} parameter section
names, respectively. However, section names don't have to match the
server name and some servers may be even interested in multiple
sections: the @command{typescript-language-server} server is known to be
interested in the @code{:javascript} and @code{:typescript} section
names.
To avoid sending whole configuration sections to servers who are
decidedly not interested in them, the following form may also be used:
@lisp
((python-base-mode
. ((eglot-workspace-configuration
. (:pylsp (:plugins (:jedi_completion (:include_params t
:fuzzy t)
:pylint (:enabled :json-false)))))
(indent-tabs-mode . nil)))
(go-mode
. ((eglot-workspace-configuration
. (:gopls (:usePlaceholders t)))
(indent-tabs-mode . t))))
@end lisp
@noindent
This sets up the value of @code{eglot-workspace-configuration}
separately depending on the major mode of each of that project's
buffers. @code{python-base-mode} buffers will have the variable set to
@code{(:pylsp (:plugins ...))}. @code{go-mode} buffers will have the
variable set to @code{(:gopls (:usePlaceholders t))}.
Some servers will issue workspace configuration for specific source
files inside your project. For example, if you know @code{gopls} is
asking about specific files in the @code{src/imported} subdirectory and
you want to set a different option for @code{gopls.usePlaceholders} ,
you may use something like:
@lisp
((python-base-mode
. ((eglot-workspace-configuration
. (:pylsp (:plugins (:jedi_completion (:include_params t
:fuzzy t)
:pylint (:enabled :json-false)))))
(indent-tabs-mode nil)))
(go-mode
. ((eglot-workspace-configuration
. (:gopls (:usePlaceholders t)))
(indent-tabs-mode t)))
("src/imported"
. ((eglot-workspace-configuration
. (:gopls (:usePlaceholders nil))))))
@end lisp
Finally, if one needs to determine the workspace configuration based on
some dynamic context, @code{eglot-workspace-configuration} can be set to
a function instead of a plist. The function is called with the
@code{eglot-lsp-server} instance of the connected server (if any) and
with @code{default-directory} set to the root of the project. The
function should return a plist suitable for use as the variable's value.
@node User-specific configuration
@section User-specific configuration
@cindex initializationOptions
@cindex command-line arguments
This kind of configuration applies to all projects the server is used
for. Here, there are a number of ways to do this inside Eglot.
A common way is to pass command-line options to the server invocation
via @code{eglot-server-programs}. Let's say we want to configure where
the @command{clangd} server reads its @code{compile_commands.json} from.
This can be done like so:
@lisp
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
`(c++-mode . ("clangd" "--compile-commands-dir=/tmp"))))
@end lisp
@noindent
Another way is to have Eglot pass a JSON object to the server during the
LSP handshake. This is done using the @code{:initializationOptions}
syntax of @code{eglot-server-programs}:
@lisp
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
`(c++-mode . ("clangd" :initializationOptions
(:compilationDatabasePath "/tmp")))))
@end lisp
@noindent
The argument @code{(:compilationDatabasePath "/tmp")} is Emacs's
representation in plist format of a simple JSON object
@code{@{"compilationDatabasePath": "/tmp"@}}. To learn how to represent
more deeply nested options in this format, @pxref{JSONRPC objects in
Elisp}.
In this case, the two examples achieve exactly the same, but notice how
the option's name has changed between them.
@vindex eglot-workspace-configuration
Finally there is another way to do user-specific configuration of
language servers, which may be used if the methods above are not
supported. It consists of @emph{globally} setting
@code{eglot-workspace-configuration}, a variable originally intended for
project-specific configuration. This has the same effect as giving all
your projects a certain default configuration, as described in
@ref{Project-specific configuration}. Here is an example:
@lisp
(setq-default eglot-workspace-configuration
'(:pylsp (:plugins (:jedi_completion (:include_params t
:fuzzy t)
:pylint (:enabled :json-false)))
:gopls (:usePlaceholders t)))
@end lisp
Note that the global value of @code{eglot-workspace-configuration} is
always overridden if a directory-local value is detected.
@node JSONRPC objects in Elisp
@section JSONRPC objects in Elisp
Emacs's preferred way of representing JSON is via Lisp lists. In Eglot,
the syntax of this list is the simplest possible (the one with fewer
parenthesis), a plist (@pxref{Property Lists,,, elisp, GNU Emacs Lisp
Reference Manual}).
The plist may be arbitrarily complex, and generally containing other
keyword-value property sub-plists corresponding to JSON sub-objects.
For representing the JSON leaf values @code{true}, @code{false},
@code{null} and @code{@{@}}, you can use the Lisp values @code{t},
@code{:json-false}, @code{nil}, and @code{eglot-@{@}}, respectively.
JSON arrays are represented as Elisp vectors surrounded by square
brackets (@pxref{Vectors,,,elisp,GNU Emacs Lisp Reference Manual}).
For example, the plist
@lisp
(:pylsp (:plugins (:jedi_completion (:include_params t
:fuzzy t
:cache_for ["pandas" "numpy"])
:pylint (:enabled :json-false)))
:gopls (:usePlaceholders t))
@end lisp
@noindent
is serialized by Eglot to the following JSON text:
@example
@{
"pylsp": @{
"plugins": @{
"jedi_completion": @{
"include_params": true,
"fuzzy": true,
"cache_for": [ "pandas", "numpy" ]
@},
"pylint": @{
"enabled": false
@}
@}
@},
"gopls": @{
"usePlaceholders": true
@}
@}
@end example
@node Multi-server support
@chapter Multi-server support
@cindex multiple servers per buffer
@cindex LSP server multiplexer
@cindex per-buffer multiple servers
One of the most frequently requested features for Eglot in close to a
decade of existence is the ability to use more than one LSP server in a
single buffer. This is distinct from using multiple servers in a
project, where each server manages a disjoint set of files written in
different languages.
The latter case---multiple servers for different files---is
intrinsically supported by Eglot. For example, in a web project with
JavaScript, CSS, and Python files, Eglot can seamlessly manage separate
language servers for each file type within the same project
(@pxref{Starting Eglot}). Each buffer communicates with its appropriate
server, and this works out-of-the-box.
However, there are several scenarios where multiple servers per buffer
are useful:
@itemize @bullet
@item
Combining a spell-checking language server like @command{codebook-lsp}
with language-specific servers for C++, Go, or Python files. The
spell-checker provides diagnostics for comments and strings, while the
language server handles syntax and semantics.
@item
One might want multiple servers to cover different aspects of the same
language. For Python, you might combine @command{ty} for type checking
with @command{ruff} for linting and formatting. For JavaScript, you
might use @command{typescript-language-server} for language features
together with @command{eslint} for linting.
@item
When working on multi-language files like Vue @file{.vue} files, which
contain JavaScript, CSS, and HTML embedded in a single file, multiple
servers can manage the different areas of the buffer.
@end itemize
These use cases are not directly supported by Eglot's architecture,
however, you can use a language-agnostic @dfn{LSP server multiplexer}
that sits between Eglot and the actual language servers. Eglot still
communicates with a single LSP server process in each buffer, but that
process mediates communication to multiple language-specific servers,
meaning that for practical purposes, it's @emph{as if} Eglot was
connected to them directly.
This approach is more powerful and user-friendly than current
workarounds that combine one LSP server in a buffer with additional
non-LSP mechanisms such as extra Flymake backends (@pxref{Top,,,
Flymake, GNU Flymake manual}) for the same buffer.
@menu
* Using Rassumfrassum:: Setup the @code{rass} LSP multiplexer
* Design rationale:: Benefits and drawbacks of LSP multiplexers
@end menu
@node Using Rassumfrassum
@section Using Rassumfrassum
@uref{https://github.com/joaotavora/rassumfrassum, Rassumfrassum} is an
LSP server multiplexer program that fits the bill. Like most language
servers, it must be installed separately since it is not bundled with
Emacs (at time of writing). The installation is similar to installing
any other language server, and usually amounts to making sure the
program executable is somewhere in @code{PATH} or @code{exec-path}.
The Rassumfrassum program, invoked via the @command{rass} command, works
by spawning multiple LSP server subprocesses and aggregating their
capabilities, requests, and responses into a single unified LSP
interface. From Eglot's perspective, it appears to be communicating with
a single server.
To use Rassumfrassum with Eglot, you can start it interactively with a
prefix argument to @code{eglot} and specify the @command{rass} command
followed by the actual servers you want to use, separated by @code{--}:
@example
C-u M-x eglot RET rass -- clangd -- codebook-lsp serve RET
@end example
@noindent
This starts @command{clangd} for C++ language support and
@command{codebook-lsp} for spell-checking in the same buffer.
For Python, you might use:
@example
C-u M-x eglot RET rass -- ty server -- ruff server RET
@end example
@noindent
or simply @kbd{C-u M-x eglot RET rass python}, using the ``preset''
feature. This combines @command{ty} for type checking with
@command{ruff} for linting and formatting.
These configurations can be integrated into the
@code{eglot-server-programs} variable (@pxref{Setting Up LSP Servers})
for automatic use:
@lisp
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
'(c-ts-base-mode . ("rass" "--" "clangd" "--"
"codebook-lsp" "serve")))
(add-to-list 'eglot-server-programs
'(python-mode . ("rass" "--" "ty" "server" "--"
"ruff" "server"))))
@end lisp
@node Design rationale
@section Design rationale
Using an LSP server multiplexer like @command{rass} relieves Eglot from
knowing about the specific characteristics of individual servers and the
complexity of managing multiple simultaneous server connections per
buffer. This helps preserve the essential features that distinguish
Eglot's code base from other LSP offers for Emacs: simple, performant
and mindful of the core tenet of LSP, which is for a client to be
language-agnostic.
This approach has an additional benefit: because the multiplexer
mediates all communication between Eglot and the servers, it can take
advantage of different optimization opportunities. For instance, at the
system level it may be multi-threaded to process different JSONRPC
streams in with true parallelism, something which is currently
impossible to do in plain Elisp. At the LSP-level it can merge server
responses intelligently, truncate unnecessarily large objects, and cache
significant amounts of information in efficient ways. In many cases,
this can reduce the amount of JSONRPC traffic exchanged with Emacs to
levels well below what would occur if a client connected to multiple
servers separately. Some of these optimizations may apply even when a
program like @command{rass} is mediating communication to a single
server.
The multiplexer approach is not without drawbacks. Since LSP is a
relatively large protocol with a decade of existence and many backward
compatibility concerns, combining the responses of servers using completely
different mechanisms of the protocol to respond to the same request
sometimes leads to complexity in covering the corner cases. However,
offloading this complexity to a completely separate layer has proven
very effective in practice.
@node Extending Eglot
@chapter Extending Eglot
Sometimes it may be useful to extend existing Eglot functionality using
Elisp its public methods. A good example of when this need may arise is
adding support for a custom LSP protocol extension only implemented by a
specific server.
The best source of documentation for this is probably Eglot source code
itself, particularly the section marked ``API''.
Most of the functionality is implemented with Common-Lisp style generic
functions (@pxref{Generics,,,eieio,EIEIO}) that can be easily extended
or overridden. The Eglot code itself is an example on how to do this.
The following is a relatively simple example that adds support for the
@code{inactiveRegions} experimental feature introduced in version 17 of
the @command{clangd} C/C++ language server++.
Summarily, the feature works by first having the server detect the
Eglot's advertisement of the @code{inactiveRegions} client capability
during startup, whereupon the language server will report a list of
regions of inactive code for each buffer. This is usually code
surrounded by C/C++ @code{#ifdef} macros that the preprocessor removes
based on compile-time information.
The language server reports the regions by periodically sending a
@code{textDocument/inactiveRegions} notification for each managed buffer
(@pxref{Eglot and Buffers}). Normally, unknown server notifications are
ignored by Eglot, but we're going change that.
Both the announcement of the client capability and the handling of the
new notification is done by adding methods to generic functions.
@itemize @bullet
@item
The first method extends @code{eglot-client-capabilities} using a simple
heuristic to detect if current server is @command{clangd} and enables
the @code{inactiveRegion} capability.
@lisp
(cl-defmethod eglot-client-capabilities :around (server)
(let ((base (cl-call-next-method)))
(when (cl-find "clangd" (process-command
(jsonrpc--process server))
:test #'string-match)
(setf (cl-getf (cl-getf base :textDocument)
:inactiveRegionsCapabilities)
'(:inactiveRegions t)))
base))
@end lisp
Notice we use an internal function of the @code{jsonrpc.el} library, and
a regexp search to detect @command{clangd}. An alternative would be to
define a new EIEIO subclass of @code{eglot-lsp-server}, maybe called
@code{eglot-clangd}, so that the method would be simplified:
@lisp
(cl-defmethod eglot-client-capabilities :around ((_s eglot-clangd))
(let ((base (cl-call-next-method)))
(setf (cl-getf (cl-getf base :textDocument)
:inactiveRegionsCapabilities)
'(:inactiveRegions t))))
@end lisp
However, this would require that users tweak @code{eglot-server-program}
to tell Eglot instantiate such sub-classes instead of the generic
@code{eglot-lsp-server} (@pxref{Setting Up LSP Servers}). For the
purposes of this particular demonstration, we're going to use the more
hacky regexp route which doesn't require that.
Note, however, that detecting server versions before announcing new
capabilities is generally not needed, as both server and client are
required by LSP to ignore unknown capabilities advertised by their
counterparts.
@item
The second method implements @code{eglot-handle-notification} to process
the server notification for the LSP method
@code{textDocument/inactiveRegions}. For each region received it
creates an overlay applying the @code{shadow} face to the region.
Overlays are recreated every time a new notification of this kind is
received.
To learn about how @command{clangd}'s special JSONRPC notification
message is structured in detail you could consult that server's
documentation. Another possibility is to evaluate the first
capability-announcing method, reconnect to the server and peek in the
events buffer (@pxref{Eglot Commands, eglot-events-buffer}). You could
find something like:
@lisp
[server-notification] Mon Sep 4 01:10:04 2023:
(:jsonrpc "2.0" :method "textDocument/inactiveRegions" :params
(:textDocument
(:uri "file:///path/to/file.cpp")
:regions
[(:start (:character 0 :line 18)
:end (:character 58 :line 19))
(:start (:character 0 :line 36)
:end (:character 1 :line 38))]))
@end lisp
This reveals that the @code{textDocument/inactiveRegions} notification
contains a @code{:textDocument} property to designate the managed buffer
and an array of LSP regions under the @code{:regions} property. Notice
how the message (originally in JSON format), is represented as Elisp
plists (@pxref{JSONRPC objects in Elisp}).
The Eglot generic function machinery will automatically destructure the
incoming message, so these two properties can simply be added to the new
method's lambda list as @code{&key} arguments. Also, the
@code{eglot-uri-to-path} and @code{eglot-range-region} may be used to
easily parse the LSP @code{:uri} and @code{:start ... :end ...} objects
to obtain Emacs objects for file names and positions.
The remainder of the implementation consists of standard Elisp
techniques to loop over arrays, manage buffers and overlays.
@lisp
(cl-defmethod eglot-handle-notification
(_server (_method (eql textDocument/inactiveRegions))
&key regions textDocument &allow-other-keys)
(if-let* ((path (expand-file-name (eglot-uri-to-path
(cl-getf textDocument :uri))))
(buffer (find-buffer-visiting path)))
(with-current-buffer buffer
(remove-overlays nil nil 'inactive-code t)
(cl-loop
for r across regions
for (beg . end) = (eglot-range-region r)
for ov = (make-overlay beg end)
do
(overlay-put ov 'face 'shadow)
(overlay-put ov 'inactive-code t)))))
@end lisp
@end itemize
After evaluating these two additions and reconnecting to the
@command{clangd} language server (version 17), the result will be that
all the inactive code in the buffer will be nicely grayed out using the
LSP server knowledge about current compile time preprocessor defines.
@node Troubleshooting Eglot
@chapter Troubleshooting Eglot
@cindex troubleshooting Eglot
This chapter documents commands and variables that can be used to
troubleshoot Eglot problems. It also provides guidelines for
reporting Eglot bugs in a way that facilitates their resolution.
When you encounter problems with Eglot, try first using the commands
@kbd{M-x eglot-events-buffer} and @kbd{M-x eglot-stderr-buffer}. They
pop up special buffers that can be used to inspect the communications
between the Eglot and language server. In many cases, this will
indicate the problems or at least provide a hint.
@menu
* Performance::
* Getting the latest version::
* Reporting bugs::
@end menu
@node Performance
@section Performance
@cindex performance problems, with Eglot
A common and easy-to-fix cause of performance problems in Eglot
(especially in older versions) is its events buffer, since it represents
additional work that Eglot must do (@pxref{Eglot Commands,
eglot-events-buffer}). If you find Eglot is operating correctly but
slowly, try to customize the variable @code{eglot-events-buffer-config}
(@pxref{Customization Variables}) and set its @code{:size} property to
0. This will disable recording any events and may speed things up.
In other situations, the cause of poor performance lies in the language
server itself. Some servers use aggressive caching and other techniques
to improve their performance. Often, this can be tweaked by changing
the server configuration (@pxref{Advanced server configuration}).
Another aspect that may cause performance degradation is the amount of
JSONRPC information exchanged with Emacs. Using an LSP program like
@ref{Using Rassumfrassum,Rassumfrassum} may alleviate such problems.
@node Getting the latest version
@section Getting the latest version
@cindex upgrading Eglot
To install the latest Eglot in an Emacs version that does not bundle
Eglot, use @kbd{M-x package-install}.
Often, a newer Eglot version exists that has fixed a longstanding bug,
has more LSP features, or just better supports a particular language
server. Recent Eglot versions can self-update via the command @kbd{M-x
eglot-upgrade-eglot}. This will replace any currently installed version
with the newest one available from the ELPA archives configured in
@code{package-archives}.
You can also update Eglot through other methods, such as
@code{use-package} (@pxref{Installing packages,,, use-package,
use-package User Manual}), @code{package-install}, @code{list-packages}
or the newer @code{package-upgrade} (@pxref{Packages,,, emacs, GNU Emacs
Manual}). However, do read the docstrings of the command you intend to
use before you use it, as some of them may not work in exactly the same
way across Emacs versions, meaning your configuration may be not
portable.
@node Reporting bugs
@section Reporting bugs
@cindex bug reports
If you think you have found a bug, we want to hear about it. Before
reporting a bug, keep in mind that interaction with language servers
represents a large quantity of unknown variables. Therefore, it is
generally both @emph{difficult} and @emph{absolutely essential} that the
maintainers reproduce bugs exactly as they happened to you, the user.
To report an Eglot bug, send e-mail to @email{bug-gnu-emacs@@gnu.org}.
To understand how to write this email, get acquainted with Emacs's bug
reporting guidelines (@pxref{Bugs,,, emacs, GNU Emacs Manual}). Then,
follow this Eglot-specific checklist:
@enumerate
@item
Include the transcript of JSONRPC events obtained from the buffer popped
up by @kbd{M-x eglot-events-buffer}. You may narrow down the transcript
if you are sure of where the problematic exchange is, but it's safer to
include the whole transcript, either attached or inline.
@item
If Emacs signaled an error (an error message was seen or heard), make
sure to repeat the process after turning on @code{debug-on-error} via
@kbd{M-x toggle-debug-on-error}. This normally produces a backtrace of
the error that should also be attached to the bug report.
@item
Include a description of how the maintainer should obtain, install, and
configure the language server you used. Maintainers usually have access
to GNU/Linux systems, though not necessarily the distribution that you
may be using. If possible, try to replicate the problem with the
C/C@t{++} or Python servers, as these are very easy to install.
@item
If using an LSP multiplexer server like @ref{Using Rassumfrassum,
Rassumfrassum}, first verify if the program replicates by using one of
the multiplexed servers directly. If it doesn't the problem lies in the
LSP multiplexer program and should be reported there.
@item
Include a description of a @emph{minimal} project directory where Eglot
should be started for the problem to happen. Describe each file's name
and its contents, or---sometimes better--- zip that project directory
completely and attach it. Alternatively, you can supply the address of
a public Git repository.
@item
Include versions of the software used. The Emacs version can be
obtained with @kbd{M-x emacs-version}.
We welcome bug reports about all Eglot versions, but it is helpful to
first check if the problem isn't already fixed in the latest version
(@pxref{Getting the latest version}).
It's also essential to include the version of ELPA packages that are
explicitly or implicitly loaded. The optional but popular Company or
Markdown packages are distributed as GNU ELPA packages, not to mention
Eglot itself in some situations. Prefer reproducing the problem with
built-in Treesit major modes like @code{go-ts-mode} or
@code{rust-ts-mode} since the non-ts modes for such languages are
usually provided by ELPA packages, and it's often easy to miss them.
If you can't reproduce your bug without ELPA packages, you may find the
ones you're using in @code{~/.emacs.d/elpa} (or what is in
@code{package-user-dir}). Including a listing of files in that
directory is a way to tell the maintainers about ELPA package versions.
@item
Include a recipe to replicate the problem with @emph{a clean Emacs run}.
The invocation @code{emacs -Q -f package-initialize} starts Emacs with
no configuration and initializes the ELPA packages. A very minimal
@file{.emacs} initialization file (10 lines or less) is also acceptable
and good means to describe changes to variables.
There is usually no need to include @code{require} statements in the
recipe, as Eglot's functionality uses autoloads.
Likewise, there is rarely the need to use things like @code{use-package}
or @code{eglot-ensure}. This just makes the recipe harder to follow.
Prefer setting variables with @code{setq} and adding to hooks with
@code{add-hook}. Prefer starting Eglot with @code{M-x eglot}.
@item
Make sure to double check all the above elements and re-run the recipe
to see that the problem is reproducible. Following the recipe should
produce event transcript and error backtraces that are very similar to
the ones you included. If the problem only happens sometimes, mention
this in your report.
@end enumerate
Please keep in mind that some problems reported against Eglot may
actually be bugs in the language server or the Emacs feature/package
that used Eglot to communicate with the language server. Eglot is, in
many cases, just a frontend to that functionality.
@node GNU Free Documentation License
@appendix GNU Free Documentation License
@include doclicense.texi
@node Index
@unnumbered Index
@printindex cp
@bye
|