diff options
Diffstat (limited to '')
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 |