summaryrefslogtreecommitdiffstats
path: root/2022/info/lspbridge-after.md
blob: 848d11a0f3cdda98e39e47e3b7dbd0e410cfbc40 (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
<!-- Automatically generated by emacsconf-publish-after-page -->


<a name="lspbridge-mainVideo-transcript"></a>
# Transcript

[[!template text="""Good morning folks, I'm Matthew.""" start="00:00:00.000" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Welcome to another year of EmacsConf.""" start="00:00:04.640" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""It's looking fantastic this year.""" start="00:00:07.400" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Firstly, I have to apologize for my voice""" start="00:00:10.320" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""and occasional cough today.""" start="00:00:13.560" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""I am currently recovering from a cold,""" start="00:00:15.880" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""hopefully it's not Covid or flu,""" start="00:00:18.040" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""so please bear with me today.""" start="00:00:21.160" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Actually, this talk was supposed to be brought to you""" start="00:00:24.720" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""by Manatee Lazycat, the author of lsp-bridge.""" start="00:00:27.920" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""But verbal English isn't Lazycat's strongest skill,""" start="00:00:31.560" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""and we are good friends as we maintain""" start="00:00:36.080" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""the Emacs Application Framework together,""" start="00:00:38.600" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""so here I am today presenting to you this package.""" start="00:00:41.000" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Welcome to my talk on lsp-bridge:""" start="00:00:46.000" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""a smooth-as-butter asynchronous LSP client.""" start="00:00:48.480" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""What is LSP?""" start="00:00:50.321" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""The first question is, what is LSP?""" start="00:00:57.201" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""For anyone who doesn't know here,""" start="00:01:01.160" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""LSP stands for Language Server Protocol,""" start="00:01:03.200" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""it is a set of protocols defined by Microsoft""" start="00:01:06.800" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""that provides smart features like autocomplete,""" start="00:01:09.720" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""go to definition, documentation, etc.,""" start="00:01:13.400" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""that can be implemented across different editors and IDEs.""" start="00:01:17.600" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""It was initially created""" start="00:01:23.440" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""for their Visual Studio Code product,""" start="00:01:25.560" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""then publically shared with everyone.""" start="00:01:28.400" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""So there are language servers out there""" start="00:01:33.920" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""that implemented this procotol,""" start="00:01:36.000" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""and editors need to implement the same procotols""" start="00:01:38.120" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""to talk to the language servers""" start="00:01:41.240" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""in order to retrieve necessary information.""" start="00:01:43.120" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Emacs has 2 LSP clients already, the lsp-mode and eglot,""" start="00:01:46.800" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""both implemented the protocols and both are very good.""" start="00:01:53.160" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Now comes to the second question, of course,""" start="00:02:00.440" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""given lsp-mode and eglot, why another LSP client?""" start="00:02:03.200" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""I used to use lsp-mode all the time,""" start="00:02:09.520" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""I have to say I really appreciate Ivan Yonchovski""" start="00:02:12.360" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""and the team's efforts. Also, I'd like to congratuate eglot""" start="00:02:16.000" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""for making into Emacs 29! These are fantastic packages,""" start="00:02:20.160" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""they are very mature and robust.""" start="00:02:27.440" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""However, with all due respect, both of the implementation""" start="00:02:31.000" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""are fundamentally limited""" start="00:02:35.120" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""by the single-threaded nature of Emacs,""" start="00:02:36.720" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""it is neither the fault of lsp-mode nor eglot.""" start="00:02:39.640" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Although in recent years there have been""" start="00:02:46.000" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""improvements to Emacs core such as native JSON support,""" start="00:02:47.960" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""there are still scenarios where Emacs clog""" start="00:02:51.800" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""for a brief second when processing large amounts of data,""" start="00:02:55.320" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""as Emacs is processing everything in the single thread.""" start="00:02:59.360" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""This problem is especially apparent in some LSP servers""" start="00:03:03.400" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""that feeds in tens of thousands of JSON data""" start="00:03:08.440" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""with every single key press.""" start="00:03:11.840" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Additionally, the large amount of data""" start="00:03:15.200" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""sent by the LSP server, such as the completion candidates,""" start="00:03:17.560" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""the diagnostics and documentation,""" start="00:03:21.280" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""they are temporarily stored in the Emacs memory,""" start="00:03:23.960" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""which will trigger garbage collection very frequently,""" start="00:03:27.360" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""this also causes stuttering user experience.""" start="00:03:31.160" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Increasing the gc-cons-threshold helps,""" start="00:03:34.160" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""but doesn't eliminate the problem.""" start="00:03:37.280" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""For something like the LSP,""" start="00:03:43.760" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""the language servers need time to compute,""" start="00:03:45.560" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""and Emacs needs capacity to process and filter""" start="00:03:48.320" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""all the data coming from the language servers.""" start="00:03:52.360" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""A large codebase project with a slow language server""" start="00:03:55.800" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""that sends tens of thousands of JSON""" start="00:03:59.400" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""will significantly increase the time needed to process it,""" start="00:04:02.440" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""when we don't have a multi-thread,""" start="00:04:06.520" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""the single thread originally allocated for perhaps,""" start="00:04:08.080" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""handling user input will be used to process all the data,""" start="00:04:12.720" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""and don't even talk about the garbage collection along the way.""" start="00:04:17.280" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""The unfortunate truth is that the size of the codebase""" start="00:04:22.720" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""and the efficiency of the language server""" start="00:04:26.240" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""is completely out of Emacs' control,""" start="00:04:28.920" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""it is also out of both the lsp-mode and eglot's control.""" start="00:04:31.760" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""If there's an LSP client""" start="00:04:38.520" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""that can completely eliminate stuttering""" start="00:04:40.280" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""and provide a seamless feedback,""" start="00:04:42.280" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""that would be great, isn't it?""" start="00:04:45.000" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""However, we're vaguely talking about speed right now,""" start="00:04:50.280" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""what is considered fast?""" start="00:04:53.840" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""What is considered seamless?""" start="00:04:56.400" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""What we really mean when we say""" start="00:04:58.360" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""the current LSP implementation is slow?""" start="00:05:01.480" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Let's first look at the problem fundamentally.""" start="00:05:05.240" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""We interact with Emacs through a keyboard,""" start="00:05:12.560" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""so what we perceive as a fast and smooth feedback""" start="00:05:17.680" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""completely depends on how long it takes""" start="00:05:22.720" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""for a keyboard input to display on the Emacs buffer.""" start="00:05:26.000" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""From a pure graphical perspective,""" start="00:05:29.360" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""we need a minimum of 24 frames per second,""" start="00:05:32.920" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""the standard in the media industry,""" start="00:05:36.520" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""for us humans to perceive something as seamless.""" start="00:05:39.080" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Say we need 25 frames per second, this means,""" start="00:05:42.360" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""if we divide 1000 milliseconds by 25,""" start="00:05:47.000" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""we only have approximately 40 millisecond window""" start="00:05:50.400" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""for the response time to spare.""" start="00:05:54.760" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Even if we relax the constraint a bit more,""" start="00:05:57.920" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""on average a typist takes about 100 to 200 milliseconds""" start="00:06:01.680" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""between typing each character,""" start="00:06:06.680" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""so as long as we see a response within this timeframe,""" start="00:06:09.160" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""it is tolerable. However, using a slow language server""" start="00:06:12.600" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""on a large codebase easily exceeds""" start="00:06:19.560" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""the hundred millisecond mark,""" start="00:06:22.280" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""and sometimes takes more than 200 milliseconds,""" start="00:06:24.680" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""and inevitably will cause an inconsistent delay""" start="00:06:27.480" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""for the end user.""" start="00:06:32.040" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""At this point, someone might want to point out""" start="00:06:33.200" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""that nobody is gonna type at the maximum pace all the time.""" start="00:06:37.960" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""That's right, frankly speaking most of my time""" start="00:06:41.080" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""spent at programming is not writing code,""" start="00:06:45.040" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""but staring at the screen""" start="00:06:47.640" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""thinking about how to write the code.""" start="00:06:49.040" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""However, when we do actually type,""" start="00:06:51.280" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""maybe only a sentence, a variable name, a keyword,""" start="00:06:55.600" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""or just performing keybinding shortcuts,""" start="00:07:00.360" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""that's when we want to see our input feedback immediately.""" start="00:07:03.040" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""We've already spend so much time""" start="00:07:08.480" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""thinking about how to write,""" start="00:07:10.480" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""we don't want to waste any more time waiting for Emacs""" start="00:07:12.160" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""to process and show us what we've written""" start="00:07:16.480" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""half a second ago. Otherwise the frustration will build up.""" start="00:07:19.560" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""In the past two years of EmacsConf, I've talked about""" start="00:07:28.400" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""the Emacs Application Framework, a project that extended""" start="00:07:32.000" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Emacs Lisp to Python, Qt and JavaScript ecosystems.""" start="00:07:35.400" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""The EAF project specializes in improving""" start="00:07:39.840" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""the graphical and multimedia capabilities of Emacs""" start="00:07:43.760" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""through other languages, it was a great success.""" start="00:07:47.440" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""It demonstrated the endless possibilities of Emacs""" start="00:07:51.760" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""by embracing the strengths in other ecosystems.""" start="00:07:55.760" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""If anyone is interested for more information on EAF,""" start="00:08:00.160" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""please see the EAF repo and refer to my talks""" start="00:08:04.240" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""from EmacsConf2020 and 2021.""" start="00:08:08.520" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""""" start="00:08:12.960" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""The EAF project was created by Manatee Lazycat as well,""" start="00:08:12.960" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""so he thought if there is a way to design""" start="00:08:16.240" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""an LSP client similar to EAF""" start="00:08:20.000" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""that takes the advantage of Python's multi-threading,""" start="00:08:22.760" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""it will be able to solve our problem.""" start="00:08:25.760" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Conveniently EAF had already done most of the ground work""" start="00:08:27.840" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""and demonstrated the possibility""" start="00:08:32.400" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""of cooperating Elisp and Python using the Emacs RPC effectively.""" start="00:08:34.360" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""LSP Bridge has several goals in mind.""" start="00:08:42.160" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Firstly, performance is the number one priority.""" start="00:08:45.040" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Secondly, use Python multi-threading to bypass""" start="00:08:50.160" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""the aforementioned bottlenecks of a single-threaded Emacs.""" start="00:08:55.840" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Thirdly, provide a simple solution that requires""" start="00:08:59.240" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""minimal setup for someone who just wants to have""" start="00:09:04.520" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""a fast autocomplete system in Emacs.""" start="00:09:07.520" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""This means, LSP Bridge does not intend""" start="00:09:10.080" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""and will not implement the entire LSP protocol,""" start="00:09:16.000" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""which is a vastly different approach""" start="00:09:21.440" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""than a solution like lsp-mode,""" start="00:09:23.640" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""we do not want to compete this way.""" start="00:09:25.760" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""We also believe some of the LSP Protocol features""" start="00:09:28.480" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""are unnecessary, or we already have better solutions""" start="00:09:33.560" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""in the Emacs ecosystem,""" start="00:09:37.760" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""such as tree-sitter for syntax highlighting.""" start="00:09:38.960" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""So we will not reinvent the wheel.""" start="00:09:42.680" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Ultimately, we want to provide the fastest, butter-smooth""" start="00:09:44.960" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""and performant LSP client out of the box.""" start="00:09:50.280" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Design.""" start="00:09:53.680" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Now let's look at the design architecture diagram.""" start="00:09:54.561" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""As you can see, it is split into""" start="00:10:01.240" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""the top half and bottom half.""" start="00:10:04.640" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""The top is the design for a single file model,""" start="00:10:07.080" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""and the bottom half is for project model.""" start="00:10:10.560" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""We make this distinction because we don't want a new user""" start="00:10:13.360" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""to be troubled on choosing a project root directory""" start="00:10:18.160" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""as the first impression to LSP""" start="00:10:22.600" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""before even start writing code.""" start="00:10:25.200" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""""" start="00:10:27.280" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""From a new user's perspective,""" start="00:10:27.280" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""they've just installed this package,""" start="00:10:30.480" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""and all they are expecting""" start="00:10:32.960" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""is using a smart autocomplete system,""" start="00:10:35.160" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""what does root directory even mean in this context?""" start="00:10:37.680" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""So we make the decision for them""" start="00:10:41.520" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""based on whether this file is part of a git repository.""" start="00:10:44.120" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Often times we write code in its own standalone file,""" start="00:10:48.200" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""this is extremely common for scripting languages""" start="00:10:56.720" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""like bash or python. So in the single file model,""" start="00:10:59.920" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""LSP Bridge will start a dedicated LSP server""" start="00:11:03.320" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""for this particular file based on file type,""" start="00:11:07.160" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""and every file corresponds to a LSP server,""" start="00:11:10.320" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""so each server doesn't interfere with one another.""" start="00:11:13.480" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""The project model will have every file of the same type""" start="00:11:17.840" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""under the same project share one server.""" start="00:11:23.720" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""We believe this is a positive trade-off for user experience.""" start="00:11:25.920" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""""" start="00:11:30.440" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""LSP Bridge internally implemented two main threads,""" start="00:11:30.440" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""one is the Request Thread, the other is Response Thread.""" start="00:11:36.600" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""The Request Thread is used to handle all the requests""" start="00:11:40.400" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""coming from Emacs, it does not answer immediately,""" start="00:11:45.280" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""this is important because Emacs doesn't need to wait""" start="00:11:48.680" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""for any response under any reason,""" start="00:11:52.840" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""even if the server is buggy or died out,""" start="00:11:54.680" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""it shouldn't matter to the performance of Emacs.""" start="00:11:58.160" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""The Response Thread is used to handle""" start="00:12:01.160" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""the response coming from LSP servers.""" start="00:12:04.040" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""After retrieving a response, regardless of the JSON size,""" start="00:12:06.560" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""it sends to its own thread for computation,""" start="00:12:11.240" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""such as candidate filtering and renaming.""" start="00:12:14.440" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Once the computation is finished,""" start="00:12:17.080" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""it will determine if this information is expired,""" start="00:12:20.000" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""if not, then push it to Emacs.""" start="00:12:23.640" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""""" start="00:12:26.400" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""From the Emacs side, when it receives the LSP information,""" start="00:12:26.400" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""it only needs to determine the course of action,""" start="00:12:31.560" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""either popup completion, jump to definition,""" start="00:12:34.640" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""renaming action, or show references and show documentions.""" start="00:12:39.160" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""You see, from a user, all LSP Bridge doing""" start="00:12:44.800" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""is these 5 things, the user doesn't need to care about""" start="00:12:49.120" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""anything else like the complicated""" start="00:12:52.280" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Language Server Protocols.""" start="00:12:54.560" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""""" start="00:12:56.480" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Python side caches heavy data""" start="00:12:56.480" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""such as candidate documentation and diagnostics.""" start="00:13:02.440" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""We process as much server data as possible in Python,""" start="00:13:06.280" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""and only pass to Emacs as little data as possible""" start="00:13:11.080" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""so it doesn't clog the Emacs thread""" start="00:13:15.760" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""and triggers garbage collection.""" start="00:13:18.160" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""""" start="00:13:19.800" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""This design is critical, because all Emacs needs to do""" start="00:13:19.800" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""is sending LSP requests to LSP Bridge,""" start="00:13:24.320" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""it doesn't wait for a response,""" start="00:13:27.040" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""it simply knows what to do *when* there is a response.""" start="00:13:29.440" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""So the user's input immediately displays on the buffer""" start="00:13:33.000" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""well within the 40 millisecond window,""" start="00:13:37.160" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""and in the mean time, the user can continue to type""" start="00:13:39.560" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""if he doesn't need the help from LSP right away,""" start="00:13:45.200" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""it fundamentally resolves the stuttering problem.""" start="00:13:48.200" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Now I want to talk about acm-mode,""" start="00:13:51.280" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""which stands for asynchronous completion menu,""" start="00:13:59.080" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""it is a completion framework""" start="00:14:09.600" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""that currently bundled with LSP Bridge""" start="00:14:12.480" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""designed to accomodate for""" start="00:14:15.040" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""the asynchronous nature of LSP servers.""" start="00:14:17.280" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""It is a replacement for the built-in capf,""" start="00:14:20.400" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""short for completion-at-point-functions,""" start="00:14:26.920" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""used in almost everywhere""" start="00:14:30.360" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""including company-mode and corfu-mode.""" start="00:14:32.520" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Yes, we unfortunately reinvented a very fundamental wheel.""" start="00:14:35.760" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""No, it wasn't an easy decision.""" start="00:14:40.840" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""However we still believe it's worth it.""" start="00:14:44.280" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""LSP Bridge initially used company-mode,""" start="00:14:47.880" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""then moved on to corfu-mode for a while,""" start="00:14:53.360" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""but eventually Lazycat determined""" start="00:14:56.120" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""that it is much more painful to write""" start="00:14:59.000" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""a lot of workaround code to force LSP Bridge""" start="00:15:00.720" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""to handle capf nicely than to just fork Corfu,""" start="00:15:05.680" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""remove all the capf code,""" start="00:15:09.960" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""and write a new completion framework from the remainings.""" start="00:15:12.000" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""""" start="00:15:15.240" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Performance wise, capf requires Emacs to store""" start="00:15:15.240" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""the entire candidate list""" start="00:15:20.720" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""when looking up candidate annotations.""" start="00:15:23.120" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""It needs to search through the entire candidate list first,""" start="00:15:27.160" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""then use the candidate as a key""" start="00:15:30.640" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""to search for the actual information.""" start="00:15:32.600" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""This entire process will be repeated every time""" start="00:15:34.800" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""when drawing the completion menu.""" start="00:15:38.920" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""This is truly intensive computing task for Emacs to handle.""" start="00:15:40.680" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""On top of that, the existing capf frameworks assume""" start="00:15:45.200" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""the candidate list, which is retrieved from the LSP server,""" start="00:15:50.520" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""to be ready and finalized in place""" start="00:15:54.280" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""when the completion popup occurred.""" start="00:15:56.840" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""However given the design of LSP Bridge,""" start="00:15:58.720" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Emacs will not sit there and wait for the server response,""" start="00:16:02.120" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""instead the Response Thread may feed Emacs data""" start="00:16:05.920" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""whenever it's ready. This makes capf almost impossible""" start="00:16:10.440" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""to form a finalized candidate list during popup.""" start="00:16:14.920" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""""" start="00:16:21.920" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""The complete reasons regarding why capf is incompatible""" start="00:16:21.920" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""with the asynchronous nature of LSP servers""" start="00:16:26.080" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""are very complicated and deserves its own talk.""" start="00:16:28.680" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Lazycat wrote an entire blog post detailing his reasonings,""" start="00:16:32.480" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""while Corfu's author Daniel Mendler a.k.a minad""" start="00:16:37.080" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""also done his own investigations and experiments,""" start="00:16:41.000" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""and reached a common conclusion.""" start="00:16:44.240" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""For anyone interested, I've pasted the links""" start="00:16:47.240" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""to the corresponding posts here.""" start="00:16:50.920" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Therefore, keep in mind that LSP Bridge""" start="00:16:52.760" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""can only use acm-mode to work nicely,""" start="00:16:57.400" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""so please disable other completion frameworks""" start="00:16:59.920" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""like company and corfu before trying LSP Bridge.""" start="00:17:03.360" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""By designing ACM with asynchronous server response in mind,""" start="00:17:07.160" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""this unlocks LSP Bridge project's potential""" start="00:17:14.920" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""to provide completions from almost any backends.""" start="00:17:18.760" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""ACM has blended all the backends together,""" start="00:17:22.200" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""and configured a priority to display""" start="00:17:25.680" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""important completion results like LSP before other backends.""" start="00:17:28.800" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""It can autocomplete LSP, TabNine, Elisp symbols, yasnippets,""" start="00:17:32.840" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""even English dictionaries and much more.""" start="00:17:38.560" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""As long as you have the backends installed,""" start="00:17:41.040" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""they all work out-of-the-box!""" start="00:17:43.960" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Although LSP Bridge is a relatively new package""" start="00:17:46.320" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""with just over 7 months old, it is already a success!""" start="00:17:55.240" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""As of December of 2022, we have 67 contributors""" start="00:18:00.040" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""making more than 1000 commits,""" start="00:18:06.600" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""and we reached more than 600 stars on Github!""" start="00:18:08.440" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""LSP Bridge is easily extensible,""" start="00:18:12.680" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""developing a new language backend is very simple too,""" start="00:18:16.360" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""feel free to join us!""" start="00:18:18.880" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""LSP Bridge is another successful example""" start="00:18:20.640" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""of extending Emacs Lisp with Python, and just like EAF,""" start="00:18:25.600" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""it demonstrated the potential Emacs can achieve""" start="00:18:29.920" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""when we jump out of the Lisp-only world""" start="00:18:33.640" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""and embrace other ecosystems.""" start="00:18:37.040" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Recently Lazycat created a package called blink-search""" start="00:18:39.200" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""that leveraged similar ideas""" start="00:18:43.480" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""but an asynchronous search framework,""" start="00:18:45.680" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""as well as a package called deno-bridge""" start="00:18:48.920" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""that extended Emacs Lisp""" start="00:18:51.240" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""with Deno JavaScript TypeScript runtimes.""" start="00:18:53.120" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Please check it out,""" start="00:18:56.440" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""if consider joining the development too!""" start="00:18:57.560" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""This is the entirety of my presentation, thanks for joining!""" start="00:19:05.200" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""Me and Lazycat will be available""" start="00:19:08.600" video="mainVideo-lspbridge" id="subtitle"]]
[[!template text="""to answer questions on IRC and Etherpad.""" start="00:19:11.320" video="mainVideo-lspbridge" id="subtitle"]]

Questions or comments? Please e-mail [emacsconf-org-private@gnu.org](mailto:emacsconf-org-private@gnu.org?subject=Comment%20for%20EmacsConf%202022%20lspbridge%3A%20lsp-bridge%3A%20a%20smooth-as-butter%20asynchronous%20LSP%20client)


<!-- End of emacsconf-publish-after-page -->