summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmacsConf <emacsconf-org@gnu.org>2023-12-03 14:45:20 -0500
committerEmacsConf <emacsconf-org@gnu.org>2023-12-03 14:45:20 -0500
commitbd781a0ab6e5c888cd7f0dfb005ae123edbe5191 (patch)
tree09136c545272a33b802a47fbe14cec871340a48a
parentc95e53136b6a7f0925d9085cc0fc55774b4f8704 (diff)
downloademacsconf-wiki-bd781a0ab6e5c888cd7f0dfb005ae123edbe5191.tar.xz
emacsconf-wiki-bd781a0ab6e5c888cd7f0dfb005ae123edbe5191.zip
Automated commit
Diffstat (limited to '')
-rw-r--r--2023/captions/emacsconf-2023-lspocaml--writing-a-language-server-in-ocaml-for-emacs-fun-and-profit--austin-theriault--main--chapters.vtt56
-rw-r--r--2023/captions/emacsconf-2023-lspocaml--writing-a-language-server-in-ocaml-for-emacs-fun-and-profit--austin-theriault--main.vtt1180
-rw-r--r--2023/info/lspocaml-after.md389
-rw-r--r--2023/info/lspocaml-before.md22
4 files changed, 1646 insertions, 1 deletions
diff --git a/2023/captions/emacsconf-2023-lspocaml--writing-a-language-server-in-ocaml-for-emacs-fun-and-profit--austin-theriault--main--chapters.vtt b/2023/captions/emacsconf-2023-lspocaml--writing-a-language-server-in-ocaml-for-emacs-fun-and-profit--austin-theriault--main--chapters.vtt
new file mode 100644
index 00000000..93edc9fb
--- /dev/null
+++ b/2023/captions/emacsconf-2023-lspocaml--writing-a-language-server-in-ocaml-for-emacs-fun-and-profit--austin-theriault--main--chapters.vtt
@@ -0,0 +1,56 @@
+WEBVTT
+
+
+00:00:00.000 --> 00:00:16.539
+Introduction
+
+00:00:16.540 --> 00:00:40.719
+What is Semgrep?
+
+00:00:40.720 --> 00:01:37.879
+How do we show security bugs early?
+
+00:01:37.880 --> 00:02:29.039
+What is the Language Server Protocol?
+
+00:02:29.040 --> 00:03:42.759
+Case study: Rust Analyzer
+
+00:03:42.760 --> 00:04:09.959
+Rust Analyzer in action
+
+00:04:09.960 --> 00:05:36.219
+Why is this useful?
+
+00:05:36.220 --> 00:06:40.699
+So what about Emacs?
+
+00:06:40.700 --> 00:07:58.759
+Technical part - Brief communication overview
+
+00:07:58.760 --> 00:08:03.379
+Example request
+
+00:08:03.380 --> 00:09:23.379
+LSP capabilities
+
+00:09:23.380 --> 00:11:03.479
+Tips on writing a LS
+
+00:11:03.480 --> 00:12:05.999
+Supporting a LS through LSP mode in Emacs
+
+00:12:06.000 --> 00:13:07.299
+Create a client
+
+00:13:07.300 --> 00:14:11.679
+Add to list of client packages
+
+00:14:11.680 --> 00:14:17.879
+Add documentation!
+
+00:14:17.880 --> 00:15:01.359
+Adding commands and custom capabilities
+
+00:15:01.360 --> 00:16:03.920
+Thanks for listening
diff --git a/2023/captions/emacsconf-2023-lspocaml--writing-a-language-server-in-ocaml-for-emacs-fun-and-profit--austin-theriault--main.vtt b/2023/captions/emacsconf-2023-lspocaml--writing-a-language-server-in-ocaml-for-emacs-fun-and-profit--austin-theriault--main.vtt
new file mode 100644
index 00000000..cce4f460
--- /dev/null
+++ b/2023/captions/emacsconf-2023-lspocaml--writing-a-language-server-in-ocaml-for-emacs-fun-and-profit--austin-theriault--main.vtt
@@ -0,0 +1,1180 @@
+WEBVTT captioned by sachac, checked by sachac
+
+NOTE Introduction
+
+00:00:00.000 --> 00:00:01.839
+Hi, I'm Austin Theriault,
+
+00:00:01.840 --> 00:00:04.159
+and this is writing a language server in OCaml
+
+00:00:04.160 --> 00:00:07.639
+for Emacs, fun, and profit.
+
+00:00:07.640 --> 00:00:08.919
+Real quick, who am I?
+
+00:00:08.920 --> 00:00:10.919
+Well, I'm a software engineer at Semgrep.
+
+00:00:10.920 --> 00:00:13.239
+I work on our editor integrations,
+
+00:00:13.240 --> 00:00:15.359
+and I love working on programming languages, editors,
+
+00:00:15.360 --> 00:00:16.539
+and cryptography.
+
+NOTE What is Semgrep?
+
+00:00:16.540 --> 00:00:17.799
+What is Semgrep?
+
+00:00:17.800 --> 00:00:20.039
+We're a small cybersecurity startup
+
+00:00:20.040 --> 00:00:21.919
+whose core product is a SaaS tool,
+
+00:00:21.920 --> 00:00:24.759
+which is static application security testing.
+
+00:00:24.760 --> 00:00:27.799
+You can think of it as like a security linter.
+
+00:00:27.800 --> 00:00:30.119
+Normal linters will say, hey,
+
+00:00:30.120 --> 00:00:31.919
+you wrote ugly code, fix it.
+
+00:00:31.920 --> 00:00:35.079
+We'll say, hey, you wrote a SQL injection, fix that.
+
+00:00:35.080 --> 00:00:36.959
+We support 30+ languages,
+
+00:00:36.960 --> 00:00:39.319
+and we have lots of customers all using different IDEs.
+
+00:00:39.320 --> 00:00:40.719
+Why does that matter?
+
+NOTE How do we show security bugs early?
+
+00:00:40.720 --> 00:00:42.779
+Well, our goal is to show security bugs
+
+00:00:42.780 --> 00:00:45.239
+as early as possible in the development cycle.
+
+00:00:45.240 --> 00:00:48.479
+In the industry, we call this shifting left.
+
+00:00:48.480 --> 00:00:52.959
+And so how far left can we shift? The editor.
+
+00:00:52.960 --> 00:00:53.619
+So that's why it matters
+
+00:00:53.620 --> 00:00:56.079
+that our customers have different editors.
+
+00:00:56.080 --> 00:00:58.919
+Our goal is to have Semgrep and the editor
+
+00:00:58.920 --> 00:01:01.319
+show up like other language tooling.
+
+00:01:01.320 --> 00:01:05.199
+And what I mean by that is I wrote some bad OCaml up here,
+
+00:01:05.200 --> 00:01:07.599
+and the editor gave me that red squiggly and said,
+
+00:01:07.600 --> 00:01:12.199
+fix your OCaml, and we want Semgrep to do something similar.
+
+00:01:12.200 --> 00:01:15.519
+And so our goal then is to provide a similar experience
+
+00:01:15.520 --> 00:01:16.919
+to normal language checking.
+
+00:01:16.920 --> 00:01:18.999
+And then since we're a small startup,
+
+00:01:19.000 --> 00:01:22.079
+and there's a ton of different IDEs that our customers use,
+
+00:01:22.080 --> 00:01:24.919
+ideally, we don't want to have to rewrite a plugin
+
+00:01:24.920 --> 00:01:27.559
+for every single type of editor out there.
+
+00:01:27.560 --> 00:01:29.159
+Our other goal is abstract away
+
+00:01:29.160 --> 00:01:32.119
+editing and language features for editors to one code base.
+
+00:01:32.120 --> 00:01:33.879
+Ideally, we write it once
+
+00:01:33.880 --> 00:01:35.799
+and then plug it into all of them.
+
+00:01:35.800 --> 00:01:37.879
+So how can we do that, though?
+
+NOTE What is the Language Server Protocol?
+
+00:01:37.880 --> 00:01:40.679
+Well, in the process of working on this stuff,
+
+00:01:40.680 --> 00:01:42.999
+I found out about
+
+00:01:43.000 --> 00:01:44.879
+the Language Server Protocol.
+
+00:01:44.880 --> 00:01:47.279
+And what's great about the Language Server Protocol is
+
+00:01:47.280 --> 00:01:50.319
+it's a specification that defines all the ways
+
+00:01:50.320 --> 00:01:52.679
+that these language tools might interact
+
+00:01:52.680 --> 00:01:56.879
+with a development tool. And by development tool,
+
+00:01:56.880 --> 00:02:01.599
+I mean like VS Code, Sublime, Emacs, any of those.
+
+00:02:01.600 --> 00:02:07.279
+And by language tool, I mean something like PyRight, MyPy.
+
+00:02:07.280 --> 00:02:09.319
+So what's cool about LSP is that
+
+00:02:09.320 --> 00:02:12.999
+you can separate out those tools into language servers
+
+00:02:13.000 --> 00:02:15.519
+and the development tools into language clients.
+
+00:02:15.520 --> 00:02:18.079
+And because they share this common specification,
+
+00:02:18.080 --> 00:02:20.359
+they can now interact without knowing each other.
+
+00:02:20.360 --> 00:02:22.799
+So it's this great abstraction that means
+
+00:02:22.800 --> 00:02:25.439
+all you have to do is go write one language server
+
+00:02:25.440 --> 00:02:27.439
+and you can hook it up to a bunch of language clients
+
+00:02:27.440 --> 00:02:29.039
+and it'll just work.
+
+NOTE Case study: Rust Analyzer
+
+00:02:29.040 --> 00:02:34.039
+So let's do a quick case study on language servers in LSP,
+
+00:02:34.040 --> 00:02:37.239
+just so you get an idea of why this is super cool.
+
+00:02:37.240 --> 00:02:40.439
+So there's this language server called Rust Analyzer.
+
+00:02:40.440 --> 00:02:42.879
+It's a language server for the Rust language.
+
+00:02:42.880 --> 00:02:44.119
+If you've ever developed in Rust,
+
+00:02:44.120 --> 00:02:46.959
+you'll know that takes a really long time to compile,
+
+00:02:46.960 --> 00:02:50.359
+but the compiler gives you fantastic feedback.
+
+00:02:50.360 --> 00:02:52.359
+Rust has a lot of advanced language features,
+
+00:02:52.360 --> 00:02:55.439
+so that feedback is super important for developing.
+
+00:02:55.440 --> 00:02:58.919
+And so Rust Analyzer will give you that feedback instantly.
+
+00:02:58.920 --> 00:03:01.119
+Here's a ton of things that it gives you.
+
+00:03:01.120 --> 00:03:05.079
+Code completion, fixes, compiler errors, warnings,
+
+00:03:05.080 --> 00:03:08.679
+type signatures. Rust has a pretty strong type system.
+
+00:03:08.680 --> 00:03:12.199
+It also has this thing called lifetimes.
+
+00:03:12.200 --> 00:03:15.079
+A bunch of advanced language features in Rust Analyzer
+
+00:03:15.080 --> 00:03:16.199
+helps you manage all that
+
+00:03:16.200 --> 00:03:17.439
+and gives you all that info
+
+00:03:17.440 --> 00:03:19.219
+without having to wait for it to compile.
+
+00:03:19.220 --> 00:03:21.519
+Developing with the Rust Analyzer
+
+00:03:21.520 --> 00:03:24.319
+is just orders of magnitude easier
+
+00:03:24.320 --> 00:03:26.519
+than just trying to write Rust straight.
+
+00:03:26.520 --> 00:03:30.919
+Rust Analyzer, fantastic. They went and they developed it,
+
+00:03:30.920 --> 00:03:33.639
+and now you can go use that in Emacs, NeoVim,
+
+00:03:33.640 --> 00:03:35.239
+VS Code, wherever.
+
+00:03:35.240 --> 00:03:39.079
+So you can develop Rust in a way that's relatively efficient
+
+00:03:39.080 --> 00:03:42.759
+without having to give up your favorite editor.
+
+NOTE Rust Analyzer in action
+
+00:03:42.760 --> 00:03:44.399
+So here's a quick little demo
+
+00:03:44.400 --> 00:03:46.319
+of all the cool things it can do.
+
+00:03:46.320 --> 00:03:48.119
+So you can see I typed an error.
+
+00:03:48.120 --> 00:03:50.719
+It tells me that I wrote an error.
+
+00:03:50.720 --> 00:03:52.519
+I used the incorrect lifetime,
+
+00:03:52.520 --> 00:03:54.159
+which is some advanced language feature,
+
+00:03:54.160 --> 00:03:55.159
+and it'll let me know that.
+
+00:03:55.160 --> 00:03:57.519
+I expanded a Rust macro just there,
+
+00:03:57.520 --> 00:03:59.239
+which is similar to Lisp macros,
+
+00:03:59.240 --> 00:04:01.359
+and then I ran a single unit test,
+
+00:04:01.360 --> 00:04:04.639
+and that's really cool because I ran a single unit test
+
+00:04:04.640 --> 00:04:05.439
+from my editor.
+
+00:04:05.440 --> 00:04:07.839
+I didn't have to go and type any commands or anything.
+
+00:04:07.840 --> 00:04:09.959
+It just worked.
+
+NOTE Why is this useful?
+
+00:04:09.960 --> 00:04:13.399
+So why is this just useful in general for a user?
+
+00:04:13.400 --> 00:04:15.799
+Well, you get the same experience across editors.
+
+00:04:15.800 --> 00:04:17.119
+Like I was saying, you don't have to give up
+
+00:04:17.120 --> 00:04:18.359
+one editor for another
+
+00:04:18.360 --> 00:04:21.719
+so you get some sort of cool language feature.
+
+00:04:21.720 --> 00:04:23.559
+You can easily set up and use language servers
+
+00:04:23.560 --> 00:04:24.599
+made for other editors
+
+00:04:24.600 --> 00:04:27.859
+if developers don't support your editor of choice.
+
+00:04:27.860 --> 00:04:31.239
+Performance is not dependent on the editor.
+
+00:04:31.240 --> 00:04:35.439
+That's fantastic because to do all that Rust stuff,
+
+00:04:35.440 --> 00:04:37.439
+it takes a lot of CPU power,
+
+00:04:37.440 --> 00:04:40.499
+and so that's going to be slow
+
+00:04:40.500 --> 00:04:43.679
+if your editor language is not great, not fast.
+
+00:04:43.680 --> 00:04:47.799
+And then bug fixes, updates, all that,
+
+00:04:47.800 --> 00:04:50.119
+it all comes out at the same time.
+
+00:04:50.120 --> 00:04:53.399
+And then from the developer perspective, well,
+
+00:04:53.400 --> 00:04:55.359
+adding new editors is quick and easy.
+
+00:04:55.360 --> 00:04:58.699
+For reference, when I wrote the Semgrep language server,
+
+00:04:58.700 --> 00:05:00.519
+it took me maybe two or three weeks,
+
+00:05:00.520 --> 00:05:03.999
+but then actually going and setting it up for VS Code,
+
+00:05:04.000 --> 00:05:06.439
+that took an hour. For Emacs, 30 minutes.
+
+00:05:06.440 --> 00:05:08.359
+IntelliJ, maybe another hour.
+
+00:05:08.360 --> 00:05:10.399
+So it took me a day to add support
+
+00:05:10.400 --> 00:05:11.879
+for three different editors,
+
+00:05:11.880 --> 00:05:14.799
+which was I think something like 75% of the market share
+
+00:05:14.800 --> 00:05:16.319
+or something crazy like that.
+
+00:05:16.320 --> 00:05:20.179
+So very quick. You only need one mental model.
+
+00:05:20.180 --> 00:05:21.079
+You don't have to figure out
+
+00:05:21.080 --> 00:05:23.959
+all these different extension mental models,
+
+00:05:23.960 --> 00:05:26.519
+how those editors work, anything like that.
+
+00:05:26.520 --> 00:05:28.639
+And another thing that's cool is
+
+00:05:28.640 --> 00:05:30.399
+you only have to write tests for the language server,
+
+00:05:30.400 --> 00:05:31.959
+not necessarily for the editor.
+
+00:05:31.960 --> 00:05:33.839
+It's great to have just one set of tests
+
+00:05:33.840 --> 00:05:36.219
+that you have to pass.
+
+NOTE So what about Emacs?
+
+00:05:36.220 --> 00:05:40.159
+So why does a language server protocol matter with Emacs?
+
+00:05:40.160 --> 00:05:42.379
+Well, like I was saying before,
+
+00:05:42.380 --> 00:05:45.479
+Emacs gets the benefit from work put into other editors.
+
+00:05:45.480 --> 00:05:47.759
+So we get all this language support,
+
+00:05:47.760 --> 00:05:51.119
+and no one actually has to go and write the list for it
+
+00:05:51.120 --> 00:05:53.199
+or write those tools specific to Emacs.
+
+00:05:53.200 --> 00:05:54.919
+You get the language tooling,
+
+00:05:54.920 --> 00:05:56.759
+the CPU-intensive part of the editors.
+
+00:05:56.760 --> 00:05:58.559
+It can be written in something else.
+
+00:05:58.560 --> 00:06:01.319
+Lisp is fast. It's not that fast.
+
+00:06:01.320 --> 00:06:04.719
+Having that speed is fantastic. It's all asynchronous.
+
+00:06:04.720 --> 00:06:06.439
+It won't slow down Emacs.
+
+00:06:06.440 --> 00:06:08.919
+And then there's this package called `lsp-mode`,
+
+00:06:08.920 --> 00:06:11.359
+which is an LSP client commonly included
+
+00:06:11.360 --> 00:06:13.319
+in popular Emacs distributions.
+
+00:06:13.320 --> 00:06:15.159
+So a lot of people already have that.
+
+00:06:15.160 --> 00:06:18.679
+If you're using Emacs 29 or greater, you have `eglot-mode`,
+
+00:06:18.680 --> 00:06:21.679
+which is a lighter weight version of `lsp-mode`.
+
+00:06:21.680 --> 00:06:24.239
+It's just another LSP client.
+
+00:06:24.240 --> 00:06:26.359
+When I wrote the Semgrep language server,
+
+00:06:26.360 --> 00:06:28.319
+Emacs 29 hadn't come out yet.
+
+00:06:28.320 --> 00:06:31.479
+I'm not going to talk too much about `eglot-mode`
+
+00:06:31.480 --> 00:06:33.299
+because I did everything in `lsp-mode`,
+
+00:06:33.300 --> 00:06:37.779
+but I would imagine a lot of this stuff is very similar.
+
+00:06:37.780 --> 00:06:40.699
+Here's a list of some supported languages.
+
+NOTE Technical part - Brief communication overview
+
+00:06:40.700 --> 00:06:42.639
+Now let's get into the technical part.
+
+00:06:42.640 --> 00:06:45.039
+How does LSP actually work?
+
+00:06:45.040 --> 00:06:47.159
+So let's go over how it communicates first.
+
+00:06:47.160 --> 00:06:49.759
+It uses JSONRPC,
+
+00:06:49.760 --> 00:06:51.959
+which is just kind of like HTTP,
+
+00:06:51.960 --> 00:06:54.619
+but instead of sending plain text, you're sending JSON.
+
+00:06:54.620 --> 00:06:56.439
+So it's just sending JSON back and forth.
+
+00:06:56.440 --> 00:06:58.539
+It's great because it's a way
+
+00:06:58.540 --> 00:06:59.959
+for two programs to communicate
+
+00:06:59.960 --> 00:07:02.839
+without sharing a common programming language.
+
+00:07:02.840 --> 00:07:04.959
+Transport platform agnostic,
+
+00:07:04.960 --> 00:07:07.079
+so it could be stdin, stdout,
+
+00:07:07.080 --> 00:07:09.399
+sockets, whatever. It's just JSON.
+
+00:07:09.400 --> 00:07:11.139
+You can send it over whatever.
+
+00:07:11.140 --> 00:07:12.719
+There's two different types of messages,
+
+00:07:12.720 --> 00:07:15.839
+a request, which requires a response from the other party,
+
+00:07:15.840 --> 00:07:19.259
+and a notification, which does not expect a response.
+
+00:07:19.260 --> 00:07:21.759
+So just a quick little example,
+
+00:07:21.760 --> 00:07:23.759
+a user might open a document,
+
+00:07:23.760 --> 00:07:28.079
+and then it'll send like a text document did open
+
+00:07:28.080 --> 00:07:30.199
+and what document it was to the language server,
+
+00:07:30.200 --> 00:07:31.079
+and then they'll change it.
+
+00:07:31.080 --> 00:07:35.079
+Maybe they edit some code and introduce a syntax error.
+
+00:07:35.080 --> 00:07:37.159
+The changes will be sent to the language server,
+
+00:07:37.160 --> 00:07:39.219
+and then the language server will publish diagnostics,
+
+00:07:39.220 --> 00:07:41.199
+which is those red squigglies
+
+00:07:41.200 --> 00:07:42.559
+I was talking about earlier,
+
+00:07:42.560 --> 00:07:45.459
+and say, hey, syntax error or whatever here,
+
+00:07:45.460 --> 00:07:46.919
+or maybe the user says,
+
+00:07:46.920 --> 00:07:49.159
+I want to go to the definition of this function,
+
+00:07:49.160 --> 00:07:51.239
+and then the language server will spit back,
+
+00:07:51.240 --> 00:07:53.799
+hey, this is where that function lives.
+
+00:07:53.800 --> 00:07:55.399
+All very useful,
+
+00:07:55.400 --> 00:07:57.719
+and the communication is relatively simple,
+
+00:07:57.720 --> 00:07:58.759
+which is great.
+
+NOTE Example request
+
+00:07:58.760 --> 00:08:01.239
+This is what it looks like, what a request looks like.
+
+00:08:01.240 --> 00:08:03.379
+Notifications look somewhat similar.
+
+NOTE LSP capabilities
+
+00:08:03.380 --> 00:08:05.879
+So now we know how LSP communication works,
+
+00:08:05.880 --> 00:08:09.859
+but how does the actual protocol work?
+
+00:08:09.860 --> 00:08:12.399
+Well, almost all of the protocol is opt-in,
+
+00:08:12.400 --> 00:08:15.839
+meaning you don't have to support the entire specification,
+
+00:08:15.840 --> 00:08:17.399
+you can just pick and choose.
+
+00:08:17.400 --> 00:08:19.839
+Servers and clients will then communicate
+
+00:08:19.840 --> 00:08:21.679
+what part of the protocol they both support,
+
+00:08:21.680 --> 00:08:22.679
+so they'll both say, hey,
+
+00:08:22.680 --> 00:08:26.359
+we support being notified when a user opens a document,
+
+00:08:26.360 --> 00:08:28.879
+or if they're looking for documentation.
+
+00:08:28.880 --> 00:08:33.799
+And so then once they agree upon what they'll both support,
+
+00:08:33.800 --> 00:08:35.199
+then they'll send that stuff,
+
+00:08:35.200 --> 00:08:38.579
+those notifications and requests back and forth.
+
+00:08:38.580 --> 00:08:41.319
+Things like opening and closing files, diagnostics,
+
+00:08:41.320 --> 00:08:46.039
+code completion, hovering over stuff, type signatures,
+
+00:08:46.040 --> 00:08:48.559
+all of that. And what's cool is
+
+00:08:48.560 --> 00:08:50.239
+even though the specification is huge
+
+00:08:50.240 --> 00:08:52.039
+and probably has everything you need,
+
+00:08:52.040 --> 00:08:54.479
+you can go ahead and add custom capabilities
+
+00:08:54.480 --> 00:08:55.519
+if you really want to.
+
+00:08:55.520 --> 00:08:57.979
+So you can just define a custom method,
+
+00:08:57.980 --> 00:09:01.359
+and then now that works for you,
+
+00:09:01.360 --> 00:09:03.519
+and now you can have that in all your editors.
+
+00:09:03.520 --> 00:09:04.559
+For example, Rust Analyzer
+
+00:09:04.560 --> 00:09:06.199
+has structural search and replace,
+
+00:09:06.200 --> 00:09:08.159
+which is like find and replace,
+
+00:09:08.160 --> 00:09:11.599
+but with respect to the structure of the code.
+
+00:09:11.600 --> 00:09:13.639
+And if you choose to go down this route
+
+00:09:13.640 --> 00:09:15.159
+with the custom capabilities,
+
+00:09:15.160 --> 00:09:16.659
+you do have to remember you're going to have to
+
+00:09:16.660 --> 00:09:18.699
+implement it in every client.
+
+00:09:18.700 --> 00:09:20.399
+And that's a little bit more work,
+
+00:09:20.400 --> 00:09:23.379
+but it's better than where we were without LSP.
+
+NOTE Tips on writing a LS
+
+00:09:23.380 --> 00:09:25.439
+So some quick tips on writing a language server.
+
+00:09:25.440 --> 00:09:27.479
+I'm not going to get too into this
+
+00:09:27.480 --> 00:09:30.799
+because it's very application-specific.
+
+00:09:30.800 --> 00:09:32.759
+I wrote Semgrep's in OCaml
+
+00:09:32.760 --> 00:09:35.119
+since our code base was almost all OCaml already,
+
+00:09:35.120 --> 00:09:36.599
+and I wanted to leverage that.
+
+00:09:36.600 --> 00:09:38.039
+Would not recommend
+
+00:09:38.040 --> 00:09:41.559
+unless you also have a code base all in OCaml.
+
+00:09:41.560 --> 00:09:43.639
+Structure is similar to a Rust server,
+
+00:09:43.640 --> 00:09:45.739
+so a bunch of independent endpoints.
+
+00:09:45.740 --> 00:09:48.639
+I would do everything functionally if I were you.
+
+00:09:48.640 --> 00:09:49.919
+This is EmacsConf.
+
+00:09:49.920 --> 00:09:53.399
+We're all hopefully used to writing functional Lisp.
+
+00:09:53.400 --> 00:09:56.239
+I would recommend TypeScript or Rust, though,
+
+00:09:56.240 --> 00:09:58.319
+depending on your level of performance
+
+00:09:58.320 --> 00:10:00.839
+that you really need or whatever language
+
+00:10:00.840 --> 00:10:02.254
+you're trying to support ideally.
+
+00:10:02.255 --> 00:10:03.399
+Most languages have
+
+00:10:03.400 --> 00:10:06.499
+some sort of language server protocol already.
+
+00:10:06.500 --> 00:10:09.199
+But if they don't, then it might be easier
+
+00:10:09.200 --> 00:10:10.159
+to do it in that language.
+
+00:10:10.160 --> 00:10:12.799
+TypeScript has a lot of support, a lot of documentation,
+
+00:10:12.800 --> 00:10:14.159
+a lot of examples out there
+
+00:10:14.160 --> 00:10:17.679
+because it was what Microsoft originally intended
+
+00:10:17.680 --> 00:10:20.919
+the language server protocol to be for, for VS Code,
+
+00:10:20.920 --> 00:10:22.079
+which is written in TypeScript.
+
+00:10:22.080 --> 00:10:24.439
+Rust is fast, it's going to take more effort,
+
+00:10:24.440 --> 00:10:28.519
+but it's very fast, and Rust Analyzer has a great library
+
+00:10:28.520 --> 00:10:30.279
+that they use and that they support.
+
+00:10:30.280 --> 00:10:32.799
+So support there, examples there are great.
+
+00:10:32.800 --> 00:10:35.839
+The hard part is not really the language server protocol,
+
+00:10:35.840 --> 00:10:38.999
+but the actual logic. So, like, if you're doing, like,
+
+00:10:39.000 --> 00:10:40.199
+language tooling, you're going to have to do
+
+00:10:40.200 --> 00:10:42.679
+analysis on the code, so you need to do parsing,
+
+00:10:42.680 --> 00:10:46.999
+possibly compiling, all these different advanced features,
+
+00:10:47.000 --> 00:10:48.959
+all these advanced different things.
+
+00:10:48.960 --> 00:10:52.519
+For example, Rust Analyzer will do incremental compilation,
+
+00:10:52.520 --> 00:10:54.319
+which is really, really cool,
+
+00:10:54.320 --> 00:10:58.119
+but that's, like, a whole separate talk.
+
+00:10:58.120 --> 00:11:00.319
+If you're adapting an existing language tool,
+
+00:11:00.320 --> 00:11:01.679
+this stuff is really easy.
+
+00:11:01.680 --> 00:11:03.479
+You're basically just wiring stuff up.
+
+NOTE Supporting a LS through LSP mode in Emacs
+
+00:11:03.480 --> 00:11:08.359
+But, yeah. So, now we know all about
+
+00:11:08.360 --> 00:11:10.799
+LSP and language servers.
+
+00:11:10.800 --> 00:11:11.879
+Say you want to actually
+
+00:11:11.880 --> 00:11:14.079
+add support for a language server in Emacs.
+
+00:11:14.080 --> 00:11:19.159
+How do you do that? Well, let's look at LSP mode,
+
+00:11:19.160 --> 00:11:21.519
+because, like I said, this is what I'm most familiar with.
+
+00:11:21.520 --> 00:11:24.259
+I'm sure `eglot-mode` is pretty similar.
+
+00:11:24.260 --> 00:11:27.479
+So, `lsp-mode`'s repository is on GitHub,
+
+00:11:27.480 --> 00:11:31.499
+like everything, and it has a ton of different clients
+
+00:11:31.500 --> 00:11:34.439
+for a ton of different languages and frameworks and tools,
+
+00:11:34.440 --> 00:11:37.039
+like Semgrep, and these are available
+
+00:11:37.040 --> 00:11:39.739
+to anyone who installs LSP mode.
+
+00:11:39.740 --> 00:11:42.239
+Alternatively, you can make a separate package
+
+00:11:42.240 --> 00:11:43.679
+and just use LSP mode as a library,
+
+00:11:43.680 --> 00:11:45.479
+but I'm not going to focus on this,
+
+00:11:45.480 --> 00:11:47.879
+because there's already a ton of resources out there
+
+00:11:47.880 --> 00:11:50.799
+on packaging and Emacs.
+
+00:11:50.800 --> 00:11:54.559
+So, our steps, very quickly, are going to look like
+
+00:11:54.560 --> 00:11:58.299
+adding an Emacs Lisp file that contains some logic,
+
+00:11:58.300 --> 00:12:01.319
+add an entry somewhere, so we added a new client
+
+00:12:01.320 --> 00:12:03.719
+to the list of clients, and then do some documentation,
+
+00:12:03.720 --> 00:12:05.999
+because documentation's great.
+
+NOTE Create a client
+
+00:12:06.000 --> 00:12:07.639
+First, creating a client.
+
+00:12:07.640 --> 00:12:09.639
+In the `clients/` folder in `lsp-mode/`,
+
+00:12:09.640 --> 00:12:12.919
+literally just add, like, `lsp-` whatever it is,
+
+00:12:12.920 --> 00:12:15.759
+`require` the library, and register a client.
+
+00:12:15.760 --> 00:12:18.039
+Registering a client just means, like,
+
+00:12:18.040 --> 00:12:19.559
+saying what kind of connection it is.
+
+00:12:19.560 --> 00:12:21.479
+It's most likely going to be standard I/O,
+
+00:12:21.480 --> 00:12:24.359
+because that's pretty easy to implement,
+
+00:12:24.360 --> 00:12:26.839
+and then you just pass it the executable
+
+00:12:26.840 --> 00:12:29.559
+that you actually want to run.
+
+00:12:29.560 --> 00:12:31.719
+Say what the activation function is,
+
+00:12:31.720 --> 00:12:33.319
+so this is when the client should start,
+
+00:12:33.320 --> 00:12:36.239
+so you can specify the language
+
+00:12:36.240 --> 00:12:38.279
+or the major mode or whatever,
+
+00:12:38.760 --> 00:12:43.099
+and now your client will start whenever that's triggered,
+
+00:12:43.100 --> 00:12:45.639
+and then finally provide just a server ID,
+
+00:12:45.640 --> 00:12:48.579
+so that way it's easy to keep track of,
+
+00:12:48.580 --> 00:12:52.759
+and then run this LSP consistency check function.
+
+00:12:52.760 --> 00:12:56.579
+This just makes sure everything up there is good.
+
+00:12:56.580 --> 00:12:59.519
+You can do more advanced stuff with making an LSP client
+
+00:12:59.520 --> 00:13:01.199
+that I'm not going to get into,
+
+00:13:01.200 --> 00:13:03.799
+but just know that these aren't your only options,
+
+00:13:03.800 --> 00:13:07.299
+and then finally provide your client.
+
+NOTE Add to list of client packages
+
+00:13:07.300 --> 00:13:09.799
+Next, you just have to add your client
+
+00:13:09.800 --> 00:13:12.159
+to the list of clients that `lsp-mode` supports,
+
+00:13:12.160 --> 00:13:15.639
+and now you've added support for a whole new language,
+
+00:13:15.640 --> 00:13:17.719
+whole new framework, whole new tool to Emacs,
+
+00:13:17.720 --> 00:13:20.219
+and it's taking you, what, like, what is that,
+
+00:13:20.220 --> 00:13:23.639
+20 lines of Lisp? No, not even, like, 15.
+
+00:13:23.640 --> 00:13:26.639
+15 lines of Lisp, whole new language for Emacs.
+
+00:13:26.640 --> 00:13:31.599
+It's really exciting. Now that you have your client,
+
+00:13:31.600 --> 00:13:35.119
+let's do some documentation. Go fill out this, like, name,
+
+00:13:35.120 --> 00:13:37.919
+where the repository, the source code is,
+
+00:13:37.920 --> 00:13:39.599
+because free software is great,
+
+00:13:39.600 --> 00:13:42.179
+and you should open source your stuff.
+
+00:13:42.180 --> 00:13:44.199
+Specify the installation command.
+
+00:13:44.200 --> 00:13:45.399
+What's cool about this is
+
+00:13:45.400 --> 00:13:48.059
+this can be run automatically from Emacs,
+
+00:13:48.060 --> 00:13:50.319
+so if it's, like, `pip install pyright`, right,
+
+00:13:50.320 --> 00:13:53.399
+you can put that there, and Emacs will ask you,
+
+00:13:53.400 --> 00:13:55.279
+do you want to install the language server,
+
+00:13:55.280 --> 00:13:56.199
+and you can hit yes
+
+00:13:56.200 --> 00:13:59.539
+and users will just have it installed for them,
+
+00:13:59.540 --> 00:14:01.879
+and then you can say whether or not it's a debugger.
+
+00:14:01.880 --> 00:14:03.159
+This is completely separate,
+
+00:14:03.160 --> 00:14:05.119
+so there's this thing called DAP,
+
+00:14:05.120 --> 00:14:07.319
+which is the debugger adapter protocol,
+
+00:14:07.320 --> 00:14:09.679
+and it's similar to LSP but for debuggers,
+
+00:14:09.680 --> 00:14:11.679
+which is very cool,
+
+NOTE Add documentation!
+
+00:14:11.680 --> 00:14:14.599
+and then finally link to your documentation.
+
+00:14:14.600 --> 00:14:17.879
+Please, please document your stuff.
+
+NOTE Adding commands and custom capabilities
+
+00:14:17.880 --> 00:14:20.479
+If you want to add, like, a custom Emacs function
+
+00:14:20.480 --> 00:14:22.679
+or custom capabilities, it's super easy.
+
+00:14:22.680 --> 00:14:27.639
+It's literally just, like, calling a normal Emacs function.
+
+00:14:27.640 --> 00:14:30.559
+For example, Semgrep normally only scans files
+
+00:14:30.560 --> 00:14:34.199
+when you open them, but we added a Emacs function
+
+00:14:34.200 --> 00:14:36.719
+that will scan your entire project, right,
+
+00:14:36.720 --> 00:14:40.959
+and so that was just a client notification.
+
+00:14:40.960 --> 00:14:44.119
+It was just `lsp-notify` and then a custom method,
+
+00:14:44.120 --> 00:14:46.719
+and it's great because now you can just scan your project
+
+00:14:46.720 --> 00:14:48.719
+from a simple Emacs function.
+
+00:14:48.720 --> 00:14:52.119
+Requests, very similar to notifications.
+
+00:14:52.120 --> 00:14:56.079
+You send it and then pass it a lambda
+
+00:14:56.080 --> 00:14:58.459
+and do something with the result,
+
+00:14:58.460 --> 00:15:01.359
+and so that's adding custom capabilities.
+
+NOTE Thanks for listening
+
+00:15:01.360 --> 00:15:04.319
+That's pretty much it. Thank you for listening.
+
+00:15:04.320 --> 00:15:05.639
+Some resources here.
+
+00:15:05.640 --> 00:15:08.239
+These links are clickable if you get the PDF,
+
+00:15:08.240 --> 00:15:10.919
+if you get the slides. Semgrep: we're hiring!
+
+00:15:10.920 --> 00:15:12.119
+If you want to work on, like,
+
+00:15:12.120 --> 00:15:13.719
+programming language theory stuff,
+
+00:15:13.720 --> 00:15:18.119
+compilers, parsers, editors,
+
+00:15:18.120 --> 00:15:22.119
+email me or go look at our jobs.
+
+00:15:22.120 --> 00:15:25.119
+The LSP specification, this is, like, the holy Bible.
+
+00:15:25.120 --> 00:15:28.339
+It has all the specs, all the types, everything.
+
+00:15:28.340 --> 00:15:30.419
+`lsp-mode` and the docs.
+
+00:15:30.420 --> 00:15:33.279
+`lsp-mode`, right, that's where you want to add your client.
+
+00:15:33.280 --> 00:15:36.099
+The docs are great, super useful.
+
+00:15:36.100 --> 00:15:38.079
+Rust Analyzer is just a great reference
+
+00:15:38.080 --> 00:15:39.919
+for language servers in general
+
+00:15:39.920 --> 00:15:42.119
+if you want to write one or if you just want to, like,
+
+00:15:42.120 --> 00:15:45.399
+see how they work. It's all just really well done.
+
+00:15:45.400 --> 00:15:47.039
+It's great code, very readable.
+
+00:15:47.040 --> 00:15:50.479
+And then down here is just a long video tutorial,
+
+00:15:50.480 --> 00:15:54.699
+a longer video tutorial, not by me,
+
+00:15:54.700 --> 00:15:58.439
+by someone else, on how to add a language client to Emacs,
+
+00:15:58.440 --> 00:16:00.679
+but hopefully this is sufficient for y'all,
+
+00:16:01.480 --> 00:16:03.920
+and now it's time for some Q&A.
diff --git a/2023/info/lspocaml-after.md b/2023/info/lspocaml-after.md
index 409fc04c..9cc87d9d 100644
--- a/2023/info/lspocaml-after.md
+++ b/2023/info/lspocaml-after.md
@@ -1,6 +1,395 @@
<!-- 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)
diff --git a/2023/info/lspocaml-before.md b/2023/info/lspocaml-before.md
index 4f3a366a..6d8a625d 100644
--- a/2023/info/lspocaml-before.md
+++ b/2023/info/lspocaml-before.md
@@ -8,12 +8,32 @@ The following image shows where the talk is in the schedule for Sun 2023-12-03.
Format: 17-min talk; Q&A: BigBlueButton conference room <https://media.emacsconf.org/2023/current/bbb-lspocaml.html>
Etherpad: <https://pad.emacsconf.org/2023-lspocaml>
Discuss on IRC: [#emacsconf-dev](https://chat.emacsconf.org/?join=emacsconf,emacsconf-dev)
-Status: Ready to stream
+Status: Now playing on the conference livestream
<div>Times in different timezones:</div><div class="times" start="2023-12-03T19:45:00Z" end="2023-12-03T20:00:00Z"><div class="conf-time">Sunday, Dec 3 2023, ~2:45 PM - 3:00 PM EST (US/Eastern)</div><div class="others"><div>which is the same as:</div>Sunday, Dec 3 2023, ~1:45 PM - 2:00 PM CST (US/Central)<br />Sunday, Dec 3 2023, ~12:45 PM - 1:00 PM MST (US/Mountain)<br />Sunday, Dec 3 2023, ~11:45 AM - 12:00 PM PST (US/Pacific)<br />Sunday, Dec 3 2023, ~7:45 PM - 8:00 PM UTC <br />Sunday, Dec 3 2023, ~8:45 PM - 9:00 PM CET (Europe/Paris)<br />Sunday, Dec 3 2023, ~9:45 PM - 10:00 PM EET (Europe/Athens)<br />Monday, Dec 4 2023, ~1:15 AM - 1:30 AM IST (Asia/Kolkata)<br />Monday, Dec 4 2023, ~3:45 AM - 4:00 AM +08 (Asia/Singapore)<br />Monday, Dec 4 2023, ~4:45 AM - 5:00 AM JST (Asia/Tokyo)</div></div><div><strong><a href="/2023/watch/dev/">Find out how to watch and participate</a></strong></div>
+<div class="vid"><video controls preload="none" id="lspocaml-mainVideo"><source src="https://media.emacsconf.org/2023/emacsconf-2023-lspocaml--writing-a-language-server-in-ocaml-for-emacs-fun-and-profit--austin-theriault--main.webm" />captions="""<track label="English" kind="captions" srclang="en" src="/2023/captions/emacsconf-2023-lspocaml--writing-a-language-server-in-ocaml-for-emacs-fun-and-profit--austin-theriault--main.vtt" default />"""<track kind="chapters" label="Chapters" src="/2023/captions/emacsconf-2023-lspocaml--writing-a-language-server-in-ocaml-for-emacs-fun-and-profit--austin-theriault--main--chapters.vtt" /><p><em>Your browser does not support the video tag. Please download the video instead.</em></p></video>[[!template id="chapters" vidid="lspocaml-mainVideo" data="""
+00:00.000 Introduction
+00:16.540 What is Semgrep?
+00:40.720 How do we show security bugs early?
+01:37.880 What is the Language Server Protocol?
+02:29.040 Case study: Rust Analyzer
+03:42.760 Rust Analyzer in action
+04:09.960 Why is this useful?
+05:36.220 So what about Emacs?
+06:40.700 Technical part - Brief communication overview
+07:58.760 Example request
+08:03.380 LSP capabilities
+09:23.380 Tips on writing a LS
+11:03.480 Supporting a LS through LSP mode in Emacs
+12:06.000 Create a client
+13:07.300 Add to list of client packages
+14:11.680 Add documentation!
+14:17.880 Adding commands and custom capabilities
+15:01.360 Thanks for listening
+"""]]<div></div>Duration: 16:04 minutes<div class="files resources"><ul><li><a href="https://pad.emacsconf.org/2023-lspocaml">Open Etherpad</a></li><li><a href="https://media.emacsconf.org/2023/current/bbb-lspocaml.html">Open public Q&A</a></li><li><a href="https://media.emacsconf.org/2023/emacsconf-2023-lspocaml--writing-a-language-server-in-ocaml-for-emacs-fun-and-profit--austin-theriault--final.webm">Download --final.webm (29MB)</a></li><li><a href="https://media.emacsconf.org/2023/emacsconf-2023-lspocaml--writing-a-language-server-in-ocaml-for-emacs-fun-and-profit--austin-theriault--intro.vtt">Download --intro.vtt</a></li><li><a href="https://media.emacsconf.org/2023/emacsconf-2023-lspocaml--writing-a-language-server-in-ocaml-for-emacs-fun-and-profit--austin-theriault--intro.webm">Download --intro.webm</a></li><li><a href="https://media.emacsconf.org/2023/emacsconf-2023-lspocaml--writing-a-language-server-in-ocaml-for-emacs-fun-and-profit--austin-theriault--main--chapters.vtt">Download --main--chapters.vtt</a></li><li><a href="https://media.emacsconf.org/2023/emacsconf-2023-lspocaml--writing-a-language-server-in-ocaml-for-emacs-fun-and-profit--austin-theriault--main.opus">Download --main.opus (8.7MB)</a></li><li><a href="https://media.emacsconf.org/2023/emacsconf-2023-lspocaml--writing-a-language-server-in-ocaml-for-emacs-fun-and-profit--austin-theriault--main.txt">Download --main.txt</a></li><li><a href="https://media.emacsconf.org/2023/emacsconf-2023-lspocaml--writing-a-language-server-in-ocaml-for-emacs-fun-and-profit--austin-theriault--main.vtt">Download --main.vtt</a></li><li><a href="https://media.emacsconf.org/2023/emacsconf-2023-lspocaml--writing-a-language-server-in-ocaml-for-emacs-fun-and-profit--austin-theriault--main.webm">Download --main.webm (29MB)</a></li><li><a href="https://media.emacsconf.org/2023/emacsconf-2023-lspocaml--writing-a-language-server-in-ocaml-for-emacs-fun-and-profit--austin-theriault--normalized.opus">Download --normalized.opus (14MB)</a></li><li><a href="https://media.emacsconf.org/2023/emacsconf-2023-lspocaml--writing-a-language-server-in-ocaml-for-emacs-fun-and-profit--austin-theriault--original.mp4">Download --original.mp4 (156MB)</a></li><li><a href="https://media.emacsconf.org/2023/emacsconf-2023-lspocaml--writing-a-language-server-in-ocaml-for-emacs-fun-and-profit--austin-theriault--reencoded.webm">Download --reencoded.webm (24MB)</a></li><li><a href="https://media.emacsconf.org/2023/emacsconf-2023-lspocaml--writing-a-language-server-in-ocaml-for-emacs-fun-and-profit--austin-theriault.pdf">Download .pdf (87MB)</a></li><li><a href="https://toobnix.org/w/jgMzmGyx4H1YDwc5n1eRZu">View on Toobnix</a></li></ul></div></div>
# Description
<!-- End of emacsconf-publish-before-page --> \ No newline at end of file