summaryrefslogtreecommitdiffstats
path: root/2023/info/lspocaml-after.md
blob: 9cc87d9d36c7c3d605c5ce10eaee7a6e0a64e303 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
<!-- Automatically generated by emacsconf-publish-after-page -->


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

[[!template new="1" text="""Hi, I'm Austin Theriault,""" start="00:00:00.000" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and this is writing a language server in OCaml""" start="00:00:01.840" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""for Emacs, fun, and profit.""" start="00:00:04.160" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Real quick, who am I?""" start="00:00:07.640" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Well, I'm a software engineer at Semgrep.""" start="00:00:08.920" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""I work on our editor integrations,""" start="00:00:10.920" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and I love working on programming languages, editors,""" start="00:00:13.240" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and cryptography.""" start="00:00:15.360" video="mainVideo-lspocaml" id="subtitle"]]
[[!template new="1" text="""What is Semgrep?""" start="00:00:16.540" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""We're a small cybersecurity startup""" start="00:00:17.800" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""whose core product is a SaaS tool,""" start="00:00:20.040" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""which is static application security testing.""" start="00:00:21.920" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""You can think of it as like a security linter.""" start="00:00:24.760" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Normal linters will say, hey,""" start="00:00:27.800" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""you wrote ugly code, fix it.""" start="00:00:30.120" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""We'll say, hey, you wrote a SQL injection, fix that.""" start="00:00:31.920" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""We support 30+ languages,""" start="00:00:35.080" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and we have lots of customers all using different IDEs.""" start="00:00:36.960" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Why does that matter?""" start="00:00:39.320" video="mainVideo-lspocaml" id="subtitle"]]
[[!template new="1" text="""Well, our goal is to show security bugs""" start="00:00:40.720" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""as early as possible in the development cycle.""" start="00:00:42.780" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""In the industry, we call this shifting left.""" start="00:00:45.240" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""And so how far left can we shift? The editor.""" start="00:00:48.480" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""So that's why it matters""" start="00:00:52.960" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""that our customers have different editors.""" start="00:00:53.620" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Our goal is to have Semgrep and the editor""" start="00:00:56.080" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""show up like other language tooling.""" start="00:00:58.920" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""And what I mean by that is I wrote some bad OCaml up here,""" start="00:01:01.320" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and the editor gave me that red squiggly and said,""" start="00:01:05.200" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""fix your OCaml, and we want Semgrep to do something similar.""" start="00:01:07.600" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""And so our goal then is to provide a similar experience""" start="00:01:12.200" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""to normal language checking.""" start="00:01:15.520" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""And then since we're a small startup,""" start="00:01:16.920" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and there's a ton of different IDEs that our customers use,""" start="00:01:19.000" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""ideally, we don't want to have to rewrite a plugin""" start="00:01:22.080" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""for every single type of editor out there.""" start="00:01:24.920" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Our other goal is abstract away""" start="00:01:27.560" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""editing and language features for editors to one code base.""" start="00:01:29.160" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Ideally, we write it once""" start="00:01:32.120" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and then plug it into all of them.""" start="00:01:33.880" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""So how can we do that, though?""" start="00:01:35.800" video="mainVideo-lspocaml" id="subtitle"]]
[[!template new="1" text="""Well, in the process of working on this stuff,""" start="00:01:37.880" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""I found out about""" start="00:01:40.680" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""the Language Server Protocol.""" start="00:01:43.000" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""And what's great about the Language Server Protocol is""" start="00:01:44.880" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""it's a specification that defines all the ways""" start="00:01:47.280" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""that these language tools might interact""" start="00:01:50.320" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""with a development tool. And by development tool,""" start="00:01:52.680" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""I mean like VS Code, Sublime, Emacs, any of those.""" start="00:01:56.880" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""And by language tool, I mean something like PyRight, MyPy.""" start="00:02:01.600" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""So what's cool about LSP is that""" start="00:02:07.280" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""you can separate out those tools into language servers""" start="00:02:09.320" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and the development tools into language clients.""" start="00:02:13.000" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""And because they share this common specification,""" start="00:02:15.520" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""they can now interact without knowing each other.""" start="00:02:18.080" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""So it's this great abstraction that means""" start="00:02:20.360" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""all you have to do is go write one language server""" start="00:02:22.800" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and you can hook it up to a bunch of language clients""" start="00:02:25.440" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and it'll just work.""" start="00:02:27.440" video="mainVideo-lspocaml" id="subtitle"]]
[[!template new="1" text="""So let's do a quick case study on language servers in LSP,""" start="00:02:29.040" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""just so you get an idea of why this is super cool.""" start="00:02:34.040" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""So there's this language server called Rust Analyzer.""" start="00:02:37.240" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""It's a language server for the Rust language.""" start="00:02:40.440" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""If you've ever developed in Rust,""" start="00:02:42.880" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""you'll know that takes a really long time to compile,""" start="00:02:44.120" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""but the compiler gives you fantastic feedback.""" start="00:02:46.960" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Rust has a lot of advanced language features,""" start="00:02:50.360" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""so that feedback is super important for developing.""" start="00:02:52.360" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""And so Rust Analyzer will give you that feedback instantly.""" start="00:02:55.440" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Here's a ton of things that it gives you.""" start="00:02:58.920" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Code completion, fixes, compiler errors, warnings,""" start="00:03:01.120" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""type signatures. Rust has a pretty strong type system.""" start="00:03:05.080" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""It also has this thing called lifetimes.""" start="00:03:08.680" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""A bunch of advanced language features in Rust Analyzer""" start="00:03:12.200" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""helps you manage all that""" start="00:03:15.080" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and gives you all that info""" start="00:03:16.200" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""without having to wait for it to compile.""" start="00:03:17.440" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Developing with the Rust Analyzer""" start="00:03:19.220" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""is just orders of magnitude easier""" start="00:03:21.520" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""than just trying to write Rust straight.""" start="00:03:24.320" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Rust Analyzer, fantastic. They went and they developed it,""" start="00:03:26.520" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and now you can go use that in Emacs, NeoVim,""" start="00:03:30.920" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""VS Code, wherever.""" start="00:03:33.640" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""So you can develop Rust in a way that's relatively efficient""" start="00:03:35.240" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""without having to give up your favorite editor.""" start="00:03:39.080" video="mainVideo-lspocaml" id="subtitle"]]
[[!template new="1" text="""So here's a quick little demo""" start="00:03:42.760" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""of all the cool things it can do.""" start="00:03:44.400" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""So you can see I typed an error.""" start="00:03:46.320" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""It tells me that I wrote an error.""" start="00:03:48.120" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""I used the incorrect lifetime,""" start="00:03:50.720" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""which is some advanced language feature,""" start="00:03:52.520" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and it'll let me know that.""" start="00:03:54.160" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""I expanded a Rust macro just there,""" start="00:03:55.160" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""which is similar to Lisp macros,""" start="00:03:57.520" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and then I ran a single unit test,""" start="00:03:59.240" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and that's really cool because I ran a single unit test""" start="00:04:01.360" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""from my editor.""" start="00:04:04.640" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""I didn't have to go and type any commands or anything.""" start="00:04:05.440" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""It just worked.""" start="00:04:07.840" video="mainVideo-lspocaml" id="subtitle"]]
[[!template new="1" text="""So why is this just useful in general for a user?""" start="00:04:09.960" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Well, you get the same experience across editors.""" start="00:04:13.400" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Like I was saying, you don't have to give up""" start="00:04:15.800" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""one editor for another""" start="00:04:17.120" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""so you get some sort of cool language feature.""" start="00:04:18.360" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""You can easily set up and use language servers""" start="00:04:21.720" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""made for other editors""" start="00:04:23.560" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""if developers don't support your editor of choice.""" start="00:04:24.600" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Performance is not dependent on the editor.""" start="00:04:27.860" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""That's fantastic because to do all that Rust stuff,""" start="00:04:31.240" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""it takes a lot of CPU power,""" start="00:04:35.440" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and so that's going to be slow""" start="00:04:37.440" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""if your editor language is not great, not fast.""" start="00:04:40.500" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""And then bug fixes, updates, all that,""" start="00:04:43.680" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""it all comes out at the same time.""" start="00:04:47.800" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""And then from the developer perspective, well,""" start="00:04:50.120" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""adding new editors is quick and easy.""" start="00:04:53.400" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""For reference, when I wrote the Semgrep language server,""" start="00:04:55.360" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""it took me maybe two or three weeks,""" start="00:04:58.700" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""but then actually going and setting it up for VS Code,""" start="00:05:00.520" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""that took an hour. For Emacs, 30 minutes.""" start="00:05:04.000" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""IntelliJ, maybe another hour.""" start="00:05:06.440" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""So it took me a day to add support""" start="00:05:08.360" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""for three different editors,""" start="00:05:10.400" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""which was I think something like 75% of the market share""" start="00:05:11.880" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""or something crazy like that.""" start="00:05:14.800" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""So very quick. You only need one mental model.""" start="00:05:16.320" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""You don't have to figure out""" start="00:05:20.180" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""all these different extension mental models,""" start="00:05:21.080" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""how those editors work, anything like that.""" start="00:05:23.960" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""And another thing that's cool is""" start="00:05:26.520" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""you only have to write tests for the language server,""" start="00:05:28.640" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""not necessarily for the editor.""" start="00:05:30.400" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""It's great to have just one set of tests""" start="00:05:31.960" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""that you have to pass.""" start="00:05:33.840" video="mainVideo-lspocaml" id="subtitle"]]
[[!template new="1" text="""So why does a language server protocol matter with Emacs?""" start="00:05:36.220" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Well, like I was saying before,""" start="00:05:40.160" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Emacs gets the benefit from work put into other editors.""" start="00:05:42.380" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""So we get all this language support,""" start="00:05:45.480" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and no one actually has to go and write the list for it""" start="00:05:47.760" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""or write those tools specific to Emacs.""" start="00:05:51.120" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""You get the language tooling,""" start="00:05:53.200" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""the CPU-intensive part of the editors.""" start="00:05:54.920" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""It can be written in something else.""" start="00:05:56.760" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Lisp is fast. It's not that fast.""" start="00:05:58.560" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Having that speed is fantastic. It's all asynchronous.""" start="00:06:01.320" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""It won't slow down Emacs.""" start="00:06:04.720" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""And then there's this package called `lsp-mode`,""" start="00:06:06.440" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""which is an LSP client commonly included""" start="00:06:08.920" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""in popular Emacs distributions.""" start="00:06:11.360" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""So a lot of people already have that.""" start="00:06:13.320" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""If you're using Emacs 29 or greater, you have `eglot-mode`,""" start="00:06:15.160" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""which is a lighter weight version of `lsp-mode`.""" start="00:06:18.680" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""It's just another LSP client.""" start="00:06:21.680" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""When I wrote the Semgrep language server,""" start="00:06:24.240" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Emacs 29 hadn't come out yet.""" start="00:06:26.360" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""I'm not going to talk too much about `eglot-mode`""" start="00:06:28.320" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""because I did everything in `lsp-mode`,""" start="00:06:31.480" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""but I would imagine a lot of this stuff is very similar.""" start="00:06:33.300" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Here's a list of some supported languages.""" start="00:06:37.780" video="mainVideo-lspocaml" id="subtitle"]]
[[!template new="1" text="""Now let's get into the technical part.""" start="00:06:40.700" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""How does LSP actually work?""" start="00:06:42.640" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""So let's go over how it communicates first.""" start="00:06:45.040" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""It uses JSONRPC,""" start="00:06:47.160" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""which is just kind of like HTTP,""" start="00:06:49.760" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""but instead of sending plain text, you're sending JSON.""" start="00:06:51.960" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""So it's just sending JSON back and forth.""" start="00:06:54.620" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""It's great because it's a way""" start="00:06:56.440" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""for two programs to communicate""" start="00:06:58.540" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""without sharing a common programming language.""" start="00:06:59.960" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Transport platform agnostic,""" start="00:07:02.840" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""so it could be stdin, stdout,""" start="00:07:04.960" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""sockets, whatever. It's just JSON.""" start="00:07:07.080" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""You can send it over whatever.""" start="00:07:09.400" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""There's two different types of messages,""" start="00:07:11.140" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""a request, which requires a response from the other party,""" start="00:07:12.720" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and a notification, which does not expect a response.""" start="00:07:15.840" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""So just a quick little example,""" start="00:07:19.260" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""a user might open a document,""" start="00:07:21.760" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and then it'll send like a text document did open""" start="00:07:23.760" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and what document it was to the language server,""" start="00:07:28.080" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and then they'll change it.""" start="00:07:30.200" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Maybe they edit some code and introduce a syntax error.""" start="00:07:31.080" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""The changes will be sent to the language server,""" start="00:07:35.080" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and then the language server will publish diagnostics,""" start="00:07:37.160" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""which is those red squigglies""" start="00:07:39.220" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""I was talking about earlier,""" start="00:07:41.200" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and say, hey, syntax error or whatever here,""" start="00:07:42.560" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""or maybe the user says,""" start="00:07:45.460" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""I want to go to the definition of this function,""" start="00:07:46.920" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and then the language server will spit back,""" start="00:07:49.160" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""hey, this is where that function lives.""" start="00:07:51.240" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""All very useful,""" start="00:07:53.800" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and the communication is relatively simple,""" start="00:07:55.400" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""which is great.""" start="00:07:57.720" video="mainVideo-lspocaml" id="subtitle"]]
[[!template new="1" text="""This is what it looks like, what a request looks like.""" start="00:07:58.760" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Notifications look somewhat similar.""" start="00:08:01.240" video="mainVideo-lspocaml" id="subtitle"]]
[[!template new="1" text="""So now we know how LSP communication works,""" start="00:08:03.380" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""but how does the actual protocol work?""" start="00:08:05.880" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Well, almost all of the protocol is opt-in,""" start="00:08:09.860" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""meaning you don't have to support the entire specification,""" start="00:08:12.400" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""you can just pick and choose.""" start="00:08:15.840" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Servers and clients will then communicate""" start="00:08:17.400" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""what part of the protocol they both support,""" start="00:08:19.840" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""so they'll both say, hey,""" start="00:08:21.680" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""we support being notified when a user opens a document,""" start="00:08:22.680" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""or if they're looking for documentation.""" start="00:08:26.360" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""And so then once they agree upon what they'll both support,""" start="00:08:28.880" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""then they'll send that stuff,""" start="00:08:33.800" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""those notifications and requests back and forth.""" start="00:08:35.200" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Things like opening and closing files, diagnostics,""" start="00:08:38.580" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""code completion, hovering over stuff, type signatures,""" start="00:08:41.320" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""all of that. And what's cool is""" start="00:08:46.040" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""even though the specification is huge""" start="00:08:48.560" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and probably has everything you need,""" start="00:08:50.240" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""you can go ahead and add custom capabilities""" start="00:08:52.040" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""if you really want to.""" start="00:08:54.480" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""So you can just define a custom method,""" start="00:08:55.520" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and then now that works for you,""" start="00:08:57.980" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and now you can have that in all your editors.""" start="00:09:01.360" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""For example, Rust Analyzer""" start="00:09:03.520" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""has structural search and replace,""" start="00:09:04.560" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""which is like find and replace,""" start="00:09:06.200" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""but with respect to the structure of the code.""" start="00:09:08.160" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""And if you choose to go down this route""" start="00:09:11.600" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""with the custom capabilities,""" start="00:09:13.640" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""you do have to remember you're going to have to""" start="00:09:15.160" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""implement it in every client.""" start="00:09:16.660" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""And that's a little bit more work,""" start="00:09:18.700" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""but it's better than where we were without LSP.""" start="00:09:20.400" video="mainVideo-lspocaml" id="subtitle"]]
[[!template new="1" text="""So some quick tips on writing a language server.""" start="00:09:23.380" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""I'm not going to get too into this""" start="00:09:25.440" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""because it's very application-specific.""" start="00:09:27.480" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""I wrote Semgrep's in OCaml""" start="00:09:30.800" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""since our code base was almost all OCaml already,""" start="00:09:32.760" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and I wanted to leverage that.""" start="00:09:35.120" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Would not recommend""" start="00:09:36.600" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""unless you also have a code base all in OCaml.""" start="00:09:38.040" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Structure is similar to a Rust server,""" start="00:09:41.560" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""so a bunch of independent endpoints.""" start="00:09:43.640" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""I would do everything functionally if I were you.""" start="00:09:45.740" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""This is EmacsConf.""" start="00:09:48.640" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""We're all hopefully used to writing functional Lisp.""" start="00:09:49.920" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""I would recommend TypeScript or Rust, though,""" start="00:09:53.400" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""depending on your level of performance""" start="00:09:56.240" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""that you really need or whatever language""" start="00:09:58.320" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""you're trying to support ideally.""" start="00:10:00.840" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Most languages have""" start="00:10:02.255" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""some sort of language server protocol already.""" start="00:10:03.400" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""But if they don't, then it might be easier""" start="00:10:06.500" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""to do it in that language.""" start="00:10:09.200" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""TypeScript has a lot of support, a lot of documentation,""" start="00:10:10.160" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""a lot of examples out there""" start="00:10:12.800" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""because it was what Microsoft originally intended""" start="00:10:14.160" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""the language server protocol to be for, for VS Code,""" start="00:10:17.680" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""which is written in TypeScript.""" start="00:10:20.920" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Rust is fast, it's going to take more effort,""" start="00:10:22.080" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""but it's very fast, and Rust Analyzer has a great library""" start="00:10:24.440" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""that they use and that they support.""" start="00:10:28.520" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""So support there, examples there are great.""" start="00:10:30.280" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""The hard part is not really the language server protocol,""" start="00:10:32.800" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""but the actual logic. So, like, if you're doing, like,""" start="00:10:35.840" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""language tooling, you're going to have to do""" start="00:10:39.000" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""analysis on the code, so you need to do parsing,""" start="00:10:40.200" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""possibly compiling, all these different advanced features,""" start="00:10:42.680" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""all these advanced different things.""" start="00:10:47.000" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""For example, Rust Analyzer will do incremental compilation,""" start="00:10:48.960" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""which is really, really cool,""" start="00:10:52.520" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""but that's, like, a whole separate talk.""" start="00:10:54.320" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""If you're adapting an existing language tool,""" start="00:10:58.120" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""this stuff is really easy.""" start="00:11:00.320" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""You're basically just wiring stuff up.""" start="00:11:01.680" video="mainVideo-lspocaml" id="subtitle"]]
[[!template new="1" text="""But, yeah. So, now we know all about""" start="00:11:03.480" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""LSP and language servers.""" start="00:11:08.360" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Say you want to actually""" start="00:11:10.800" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""add support for a language server in Emacs.""" start="00:11:11.880" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""How do you do that? Well, let's look at LSP mode,""" start="00:11:14.080" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""because, like I said, this is what I'm most familiar with.""" start="00:11:19.160" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""I'm sure `eglot-mode` is pretty similar.""" start="00:11:21.520" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""So, `lsp-mode`'s repository is on GitHub,""" start="00:11:24.260" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""like everything, and it has a ton of different clients""" start="00:11:27.480" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""for a ton of different languages and frameworks and tools,""" start="00:11:31.500" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""like Semgrep, and these are available""" start="00:11:34.440" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""to anyone who installs LSP mode.""" start="00:11:37.040" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Alternatively, you can make a separate package""" start="00:11:39.740" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and just use LSP mode as a library,""" start="00:11:42.240" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""but I'm not going to focus on this,""" start="00:11:43.680" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""because there's already a ton of resources out there""" start="00:11:45.480" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""on packaging and Emacs.""" start="00:11:47.880" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""So, our steps, very quickly, are going to look like""" start="00:11:50.800" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""adding an Emacs Lisp file that contains some logic,""" start="00:11:54.560" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""add an entry somewhere, so we added a new client""" start="00:11:58.300" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""to the list of clients, and then do some documentation,""" start="00:12:01.320" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""because documentation's great.""" start="00:12:03.720" video="mainVideo-lspocaml" id="subtitle"]]
[[!template new="1" text="""First, creating a client.""" start="00:12:06.000" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""In the `clients/` folder in `lsp-mode/`,""" start="00:12:07.640" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""literally just add, like, `lsp-` whatever it is,""" start="00:12:09.640" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""`require` the library, and register a client.""" start="00:12:12.920" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Registering a client just means, like,""" start="00:12:15.760" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""saying what kind of connection it is.""" start="00:12:18.040" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""It's most likely going to be standard I/O,""" start="00:12:19.560" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""because that's pretty easy to implement,""" start="00:12:21.480" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and then you just pass it the executable""" start="00:12:24.360" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""that you actually want to run.""" start="00:12:26.840" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Say what the activation function is,""" start="00:12:29.560" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""so this is when the client should start,""" start="00:12:31.720" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""so you can specify the language""" start="00:12:33.320" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""or the major mode or whatever,""" start="00:12:36.240" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and now your client will start whenever that's triggered,""" start="00:12:38.760" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and then finally provide just a server ID,""" start="00:12:43.100" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""so that way it's easy to keep track of,""" start="00:12:45.640" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and then run this LSP consistency check function.""" start="00:12:48.580" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""This just makes sure everything up there is good.""" start="00:12:52.760" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""You can do more advanced stuff with making an LSP client""" start="00:12:56.580" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""that I'm not going to get into,""" start="00:12:59.520" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""but just know that these aren't your only options,""" start="00:13:01.200" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and then finally provide your client.""" start="00:13:03.800" video="mainVideo-lspocaml" id="subtitle"]]
[[!template new="1" text="""Next, you just have to add your client""" start="00:13:07.300" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""to the list of clients that `lsp-mode` supports,""" start="00:13:09.800" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and now you've added support for a whole new language,""" start="00:13:12.160" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""whole new framework, whole new tool to Emacs,""" start="00:13:15.640" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and it's taking you, what, like, what is that,""" start="00:13:17.720" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""20 lines of Lisp? No, not even, like, 15.""" start="00:13:20.220" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""15 lines of Lisp, whole new language for Emacs.""" start="00:13:23.640" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""It's really exciting. Now that you have your client,""" start="00:13:26.640" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""let's do some documentation. Go fill out this, like, name,""" start="00:13:31.600" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""where the repository, the source code is,""" start="00:13:35.120" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""because free software is great,""" start="00:13:37.920" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and you should open source your stuff.""" start="00:13:39.600" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Specify the installation command.""" start="00:13:42.180" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""What's cool about this is""" start="00:13:44.200" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""this can be run automatically from Emacs,""" start="00:13:45.400" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""so if it's, like, `pip install pyright`, right,""" start="00:13:48.060" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""you can put that there, and Emacs will ask you,""" start="00:13:50.320" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""do you want to install the language server,""" start="00:13:53.400" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and you can hit yes""" start="00:13:55.280" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and users will just have it installed for them,""" start="00:13:56.200" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and then you can say whether or not it's a debugger.""" start="00:13:59.540" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""This is completely separate,""" start="00:14:01.880" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""so there's this thing called DAP,""" start="00:14:03.160" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""which is the debugger adapter protocol,""" start="00:14:05.120" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and it's similar to LSP but for debuggers,""" start="00:14:07.320" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""which is very cool,""" start="00:14:09.680" video="mainVideo-lspocaml" id="subtitle"]]
[[!template new="1" text="""and then finally link to your documentation.""" start="00:14:11.680" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Please, please document your stuff.""" start="00:14:14.600" video="mainVideo-lspocaml" id="subtitle"]]
[[!template new="1" text="""If you want to add, like, a custom Emacs function""" start="00:14:17.880" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""or custom capabilities, it's super easy.""" start="00:14:20.480" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""It's literally just, like, calling a normal Emacs function.""" start="00:14:22.680" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""For example, Semgrep normally only scans files""" start="00:14:27.640" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""when you open them, but we added a Emacs function""" start="00:14:30.560" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""that will scan your entire project, right,""" start="00:14:34.200" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and so that was just a client notification.""" start="00:14:36.720" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""It was just `lsp-notify` and then a custom method,""" start="00:14:40.960" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and it's great because now you can just scan your project""" start="00:14:44.120" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""from a simple Emacs function.""" start="00:14:46.720" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Requests, very similar to notifications.""" start="00:14:48.720" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""You send it and then pass it a lambda""" start="00:14:52.120" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and do something with the result,""" start="00:14:56.080" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and so that's adding custom capabilities.""" start="00:14:58.460" video="mainVideo-lspocaml" id="subtitle"]]
[[!template new="1" text="""That's pretty much it. Thank you for listening.""" start="00:15:01.360" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Some resources here.""" start="00:15:04.320" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""These links are clickable if you get the PDF,""" start="00:15:05.640" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""if you get the slides. Semgrep: we're hiring!""" start="00:15:08.240" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""If you want to work on, like,""" start="00:15:10.920" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""programming language theory stuff,""" start="00:15:12.120" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""compilers, parsers, editors,""" start="00:15:13.720" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""email me or go look at our jobs.""" start="00:15:18.120" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""The LSP specification, this is, like, the holy Bible.""" start="00:15:22.120" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""It has all the specs, all the types, everything.""" start="00:15:25.120" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""`lsp-mode` and the docs.""" start="00:15:28.340" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""`lsp-mode`, right, that's where you want to add your client.""" start="00:15:30.420" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""The docs are great, super useful.""" start="00:15:33.280" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""Rust Analyzer is just a great reference""" start="00:15:36.100" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""for language servers in general""" start="00:15:38.080" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""if you want to write one or if you just want to, like,""" start="00:15:39.920" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""see how they work. It's all just really well done.""" start="00:15:42.120" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""It's great code, very readable.""" start="00:15:45.400" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""And then down here is just a long video tutorial,""" start="00:15:47.040" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""a longer video tutorial, not by me,""" start="00:15:50.480" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""by someone else, on how to add a language client to Emacs,""" start="00:15:54.700" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""but hopefully this is sufficient for y'all,""" start="00:15:58.440" video="mainVideo-lspocaml" id="subtitle"]]
[[!template text="""and now it's time for some Q&A.""" start="00:16:01.480" video="mainVideo-lspocaml" id="subtitle"]]



Captioner: sachac

Questions or comments? Please e-mail [austin@cutedogs.org](mailto:austin@cutedogs.org?subject=Comment%20for%20EmacsConf%202022%20lspocaml%3A%20Writing%20a%20language%20server%20in%20OCaml%20for%20Emacs%2C%20fun%2C%20and%20profit)


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