summaryrefslogtreecommitdiffstats
path: root/2023/info/lspocaml-after.md
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--2023/info/lspocaml-after.md793
1 files changed, 793 insertions, 0 deletions
diff --git a/2023/info/lspocaml-after.md b/2023/info/lspocaml-after.md
new file mode 100644
index 00000000..56d6ba54
--- /dev/null
+++ b/2023/info/lspocaml-after.md
@@ -0,0 +1,793 @@
+<!-- Automatically generated by emacsconf-publish-after-page -->
+
+
+<a name="lspocaml-mainVideo-transcript"></a>
+# Transcript
+
+
+[[!template new="1" text="""Introduction""" start="00:00:00.000" video="mainVideo-lspocaml" id="subtitle"]]
+
+[[!template 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="""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="""How do we show security bugs early?""" start="00:00:40.720" video="mainVideo-lspocaml" id="subtitle"]]
+
+[[!template 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="""What is the Language Server Protocol?""" start="00:01:37.880" video="mainVideo-lspocaml" id="subtitle"]]
+
+[[!template 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="""Case study: Rust Analyzer""" start="00:02:29.040" video="mainVideo-lspocaml" id="subtitle"]]
+
+[[!template 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="""Rust Analyzer in action""" start="00:03:42.760" video="mainVideo-lspocaml" id="subtitle"]]
+
+[[!template 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="""Why is this useful?""" start="00:04:09.960" video="mainVideo-lspocaml" id="subtitle"]]
+
+[[!template 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 what about Emacs?""" start="00:05:36.220" video="mainVideo-lspocaml" id="subtitle"]]
+
+[[!template 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="""Technical part - Brief communication overview""" start="00:06:40.700" video="mainVideo-lspocaml" id="subtitle"]]
+
+[[!template 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="""Example request""" start="00:07:58.760" video="mainVideo-lspocaml" id="subtitle"]]
+
+[[!template 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="""LSP capabilities""" start="00:08:03.380" video="mainVideo-lspocaml" id="subtitle"]]
+
+[[!template 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="""Tips on writing a LS""" start="00:09:23.380" video="mainVideo-lspocaml" id="subtitle"]]
+
+[[!template 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="""Supporting a LS through LSP mode in Emacs""" start="00:11:03.480" video="mainVideo-lspocaml" id="subtitle"]]
+
+[[!template 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="""Create a client""" start="00:12:06.000" video="mainVideo-lspocaml" id="subtitle"]]
+
+[[!template 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="""Add to list of client packages""" start="00:13:07.300" video="mainVideo-lspocaml" id="subtitle"]]
+
+[[!template 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="""Add documentation!""" start="00:14:11.680" video="mainVideo-lspocaml" id="subtitle"]]
+
+[[!template 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="""Adding commands and custom capabilities""" start="00:14:17.880" video="mainVideo-lspocaml" id="subtitle"]]
+
+[[!template 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="""Thanks for listening""" start="00:15:01.360" video="mainVideo-lspocaml" id="subtitle"]]
+
+[[!template 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
+
+<a name="lspocaml-qanda-transcript"></a>
+# Q&A transcript (unedited)
+
+[[!template text="""[Speaker 0]: I would invite all on the,""" start="00:00:03.540" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""who are currently watching,""" start="00:00:04.600" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""who have questions, put them into the pad""" start="00:00:06.819" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""that I can ask them. I'm kind of monitoring""" start="00:00:08.940" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""the IRC concurrently. So the first question""" start="00:00:16.320" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""that we have on the pad is concerning why you""" start="00:00:18.640" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""have switched from OCaml.""" start="00:00:19.600" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""Maybe the person has missed it in the talk,""" start="00:00:22.420" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""if you've mentioned it.""" start="00:00:23.480" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""Why have you switched from OCaml to,""" start="00:00:25.080" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""in this case, I guess,""" start="00:00:25.920" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""Rust?""" start="00:00:26.180" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 1]: Yeah, I mentioned like with writing a""" start="00:00:30.960" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""language server that I wrote mine for my""" start="00:00:34.280" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""company in OCaml But I wouldn't recommend it""" start="00:00:36.900" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""just in general unless like you're doing""" start="00:00:38.960" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""something specific with OCaml And the reason""" start="00:00:41.720" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""for that and I recommended Rust or like""" start="00:00:44.180" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""TypeScript is like OCaml is great.""" start="00:00:45.780" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""It's very performant but it's cross""" start="00:00:49.080" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""compilation story is not great.""" start="00:00:50.739" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""It's like really hard to cross compile like""" start="00:00:54.100" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""from 1 platform to another.""" start="00:00:55.840" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""And then like the ecosystem and its standard""" start="00:00:58.120" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""library is also not great.""" start="00:01:00.380" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""And like Rust, its cross compilation is""" start="00:01:03.460" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""great. Its ecosystem is great.""" start="00:01:05.820" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""OCaml is great if you need to use it,""" start="00:01:08.720" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""but it's just it's not ideal.""" start="00:01:10.880" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""And there's just also no good examples of a""" start="00:01:14.220" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""language server in OCaml.""" start="00:01:15.240" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""There's the official like OCaml language""" start="00:01:19.119" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""server, But they use a ton of super advanced""" start="00:01:22.920" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""language features, like module functors and a""" start="00:01:27.380" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""bunch of other random stuff.""" start="00:01:28.440" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""So it's not really readable.""" start="00:01:29.479" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""But Rust, there's Rust analyzer,""" start="00:01:31.860" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""which is readable. In TypeScript,""" start="00:01:33.340" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""there's like a million different ones.""" start="00:01:34.860" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""So it's less of a, not OCaml is like,""" start="00:01:39.340" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""it's not that OCaml isn't great.""" start="00:01:40.920" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""It's more of a, these other languages would""" start="00:01:43.320" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""probably just be easier.""" start="00:01:44.160" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""So.""" start="00:01:45.280" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 0]: I guess since the integration to,""" start="00:01:48.619" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""for example, like NeoVim or some other""" start="00:01:50.820" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""editors are just revenue fine because of the""" start="00:01:53.320" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 1]: Sorry, can you say that again?""" start="00:01:56.920" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 0]: LSP, I guess. The LSP,""" start="00:01:58.580" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""so it's a standard LSP specification that""" start="00:02:01.979" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""you're using. So you can also,""" start="00:02:03.080" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""for instance, use it and other editors,""" start="00:02:04.920" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""like for instance, new them or so.""" start="00:02:06.660" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 1]: Yeah. Yeah. You can use it.""" start="00:02:08.680" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""It's most, most editors nowadays support it.""" start="00:02:11.680" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""Like obviously Emacs, NeoVim,""" start="00:02:13.280" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""Sublime, VS code, Intel,""" start="00:02:16.420" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""all the IntelliJ ones.""" start="00:02:17.700" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""So yeah, that's, that's the fun part.""" start="00:02:21.560" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""You don't have to write 10 different""" start="00:02:23.440" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""languages to get a bunch of editor support.""" start="00:02:26.500" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 0]: Also experience writing it.""" start="00:02:30.200" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""So I didn't have really time to hear into""" start="00:02:33.820" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""your talk. So I'm sorry if I ask you""" start="00:02:36.300" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""questions that you have already said.""" start="00:02:38.100" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""How was the experience of writing an LSP?""" start="00:02:41.400" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""So have you any knowledge beforehand or do""" start="00:02:44.340" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""you just read it all on yourself?""" start="00:02:45.600" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 1]: Yeah, there's not a ton of documentation,""" start="00:02:49.200" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""which is what motivated me to do this talk.""" start="00:02:53.440" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""Basically, I just looked at the""" start="00:02:56.380" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""specification, and I knew Rust Analyzer was""" start="00:02:58.820" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""cool. And so I looked at Rust Analyzer,""" start="00:03:00.240" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""and I looked at PyRite.""" start="00:03:01.600" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""And I just went from there.""" start="00:03:04.200" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""I found out about all this because I already""" start="00:03:07.920" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""using Emacs, I already knew about it.""" start="00:03:10.240" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""I was like, this is going to be easier than""" start="00:03:12.160" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""something else. So yeah,""" start="00:03:15.020" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""there's the experience is fine.""" start="00:03:17.720" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""It's just a lot of wiring stuff up.""" start="00:03:21.060" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""It's not a lot of like hard thinking until""" start="00:03:24.100" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""you get to like performance heavy stuff.""" start="00:03:26.200" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""Like, so for some graph,""" start="00:03:27.740" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""like we're doing a ton of like code parsing""" start="00:03:30.760" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""and like analyzing. And so that's,""" start="00:03:32.980" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""it takes up like a ton of processing power.""" start="00:03:35.760" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""So like for stuff like that,""" start="00:03:37.280" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""like now you have to think about caching and""" start="00:03:39.620" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""like ordering things. So that part's hard,""" start="00:03:43.980" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""but that's more of a, like very much""" start="00:03:47.180" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""application specific thing.""" start="00:03:48.640" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 0]: Right. Anything in the IRC chat.""" start="00:03:58.320" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""I think not. It's nothing I can see.""" start="00:04:01.840" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""No questions, that's kind of odd to be""" start="00:04:13.380" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""honest. I cannot really ask questions""" start="00:04:17.440" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""concerning LSP specific.""" start="00:04:18.680" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 1]: Yeah, no worries.""" start="00:04:22.400" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 0]: Good question, what could be asked?""" start="00:04:31.460" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""Let's call, let's ask something very""" start="00:04:35.740" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""unspecific concerning the Emacs usage.""" start="00:04:38.260" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""And when have you started?""" start="00:04:39.340" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""How did you came through it and stuff like""" start="00:04:41.580" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""this?""" start="00:04:41.780" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 1]: Yeah. I like and when I was in high school,""" start="00:04:46.560" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""me and my friends just were like,""" start="00:04:48.480" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""got obsessed with Linux for whatever reason.""" start="00:04:51.820" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""And then like we traveled down like the,""" start="00:04:53.940" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""like the free software,""" start="00:04:55.560" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""like we just thought that was like very""" start="00:04:57.700" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""entertaining and like interesting to read""" start="00:05:00.040" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""about all the free software stuff.""" start="00:05:01.200" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""They were like, yeah, that's cool.""" start="00:05:03.120" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""And so we all started using Linux.""" start="00:05:04.540" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""And I'm like, well, if I'm using free""" start="00:05:06.960" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""software, I'm going to use Emacs.""" start="00:05:08.300" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""And so I started using Emacs just to try it""" start="00:05:12.280" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""out. And then I kind of got,""" start="00:05:13.940" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""I feel like, Stockholm syndrome into it.""" start="00:05:16.880" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""And now I've realized like,""" start="00:05:18.720" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""I don't know, now that I've done the like""" start="00:05:21.860" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""actual work to get into Emacs,""" start="00:05:23.880" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""it's just, there's so much more I can do with""" start="00:05:26.280" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""it. But yeah, it was somewhat unintentional.""" start="00:05:30.300" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 0]: I probably have the same course I've started""" start="00:05:36.100" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""like 2 years ago using Emacs.""" start="00:05:37.780" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""And also just, oh, there's at first some cool""" start="00:05:42.720" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""people on YouTube, so systems crafters and""" start="00:05:45.020" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""people like this. And also,""" start="00:05:46.300" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""ah, VS Code, I used a lot of VS Code""" start="00:05:49.440" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""beforehand and then VS Codium because open""" start="00:05:53.560" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""source and then oh are there any other""" start="00:05:55.640" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""alternatives and I came to like Neovim and""" start="00:05:58.020" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""Emacs and often switching around but I stick""" start="00:06:01.160" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""to Emacs at some point to be honest.""" start="00:06:03.220" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 1]: Yeah, I think Emacs also just looks really""" start="00:06:07.180" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""cool. I will say that.""" start="00:06:08.500" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""And also just like I like Vim.""" start="00:06:14.240" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""Vim is cool but like being able to like write""" start="00:06:16.960" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""lists and like modify your editor on the fly""" start="00:06:19.240" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""is just like very appealing to me.""" start="00:06:20.920" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""I don't know, Emacs was tough at first""" start="00:06:23.860" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""because like all the like default key""" start="00:06:25.520" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""bindings are just kind of like and then and""" start="00:06:28.380" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""then I read somewhere someone was like yeah""" start="00:06:29.860" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""well Richard Stallman uses evil mode so it's""" start="00:06:33.220" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""okay. I was like alright I can that's like""" start="00:06:36.220" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""blessing enough for me Like I'm just gonna""" start="00:06:38.000" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""switch to evil mode. And I was like,""" start="00:06:39.520" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""this is way, way better as far as key""" start="00:06:42.160" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""bindings go.""" start="00:06:42.920" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 0]: Kind of relates. So I switched for,""" start="00:06:46.720" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""I think, half a year to the default key""" start="00:06:49.900" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""bindings from Vim beforehand.""" start="00:06:51.300" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""I switched back to Evil and now I'm losing""" start="00:06:54.960" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""some kind of hybrid styles.""" start="00:06:56.100" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""It's kind of weird. But we have a question on""" start="00:07:01.000" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""the pad. So what are the corner cases,""" start="00:07:03.260" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""limitations, and other issues you encountered""" start="00:07:05.380" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""in implementing an LSP server with client in""" start="00:07:08.860" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""Emacs that were surprising?""" start="00:07:09.940" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 1]: Yeah, I would say the corner cases and""" start="00:07:13.680" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""limitations are definitely like,""" start="00:07:15.280" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""once again, they're going to be very""" start="00:07:16.960" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""application specific, but it's usually just""" start="00:07:18.960" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""the performance part. So like I was saying""" start="00:07:22.420" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""before, right, in general if you're doing""" start="00:07:24.680" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""language tooling, you're gonna be doing""" start="00:07:26.120" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""either parsing or interpreting or something""" start="00:07:29.760" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""like that, which is very just like""" start="00:07:31.560" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""computationally heavy and so if you're trying""" start="00:07:34.740" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""to like do that stuff while someone is""" start="00:07:36.900" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""editing a file right like every keystrokes""" start="00:07:38.520" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""every like 1 to 2 seconds if they have a fast""" start="00:07:42.660" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""computer that's great but a lot of people""" start="00:07:44.240" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""don't have like that fast of a computer that""" start="00:07:46.400" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""they can go and like do compilation every""" start="00:07:49.480" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""single keystroke. So like,""" start="00:07:51.680" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""I would say, I would say the like limitation""" start="00:07:54.080" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""is just how fast your computer is and how""" start="00:07:56.920" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""good you are at like implementing caching for""" start="00:07:59.140" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""like whatever you're doing.""" start="00:08:01.020" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""That's also just the main issues I've run""" start="00:08:04.080" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""into is just it's a constant uphill battle.""" start="00:08:08.080" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""People will somehow find larger and larger""" start="00:08:12.120" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""files. You'll end up with files that are like""" start="00:08:14.580" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""thousands, like tens of thousands of lines""" start="00:08:17.320" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""long and you think yeah,""" start="00:08:18.700" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""surely no 1 would expect like instantaneous""" start="00:08:21.340" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""response for like like editing a file that""" start="00:08:25.440" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""has like tens of thousands of lines,""" start="00:08:26.820" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""but then they do. As far as corner cases go,""" start="00:08:30.000" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""I would say the corner case is like,""" start="00:08:31.960" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""just in general is actually distributing the""" start="00:08:37.760" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""language server. Cause like writing the""" start="00:08:41.039" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""language server is fine.""" start="00:08:42.340" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""Like wiring everything up is fine.""" start="00:08:44.540" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""But then like, once you actually have to go""" start="00:08:47.180" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""and distribute it, well,""" start="00:08:47.960" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""now you're distributing in a binary.""" start="00:08:49.200" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""Like I was saying before with OCaml,""" start="00:08:51.660" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""doesn't have great cross compilation.""" start="00:08:53.940" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""So for some graph for our language server,""" start="00:08:58.840" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""we target Linux and Mac OS,""" start="00:09:01.560" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""and we have a ton of people who use Windows,""" start="00:09:03.840" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""but compiling OCaml for Windows is basically""" start="00:09:06.960" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""impossible. So our corner case there,""" start="00:09:10.080" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""the way we solved it was now we're""" start="00:09:11.980" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""transpiling OCaml to JavaScript,""" start="00:09:14.160" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""which is a huge can of worms.""" start="00:09:17.080" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""Like it's a lot of fun.""" start="00:09:18.840" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""It's very interesting,""" start="00:09:19.400" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""but like it's not ideal.""" start="00:09:22.860" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""And so that's what I was saying before.""" start="00:09:24.340" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""I recommend like Rust or TypeScript because""" start="00:09:26.360" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""those are way more portable and a lot easier""" start="00:09:29.580" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""to install. And you don't have to worry about""" start="00:09:31.280" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""any of that weird packaging stuff.""" start="00:09:33.600" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""So yeah, I would say that's like the main""" start="00:09:37.600" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""corner case and the main limitation is just""" start="00:09:40.260" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""speed and caching.""" start="00:09:41.720" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 0]: You mentioned this obscure large file so""" start="00:09:47.160" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""someone doesn't want to refactor or""" start="00:09:49.000" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""something. How did you start?""" start="00:09:51.760" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""So did you have any way to still be""" start="00:09:54.480" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""relatively performant when they have big""" start="00:09:56.320" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""files or is it just not supported?""" start="00:09:58.020" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""I don't care.""" start="00:09:58.920" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 1]: Yeah, no, we, so we support larger files now""" start="00:10:03.140" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""And the way we ended up doing that,""" start="00:10:05.460" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""so SemGrep is like you write this generic""" start="00:10:11.480" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""pattern. You kind of write the language,""" start="00:10:14.540" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""but then there's these other symbols and""" start="00:10:17.160" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""stuff that are included in that,""" start="00:10:18.760" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""this like meta language.""" start="00:10:19.760" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""And so what happens is,""" start="00:10:22.420" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""is most languages get,""" start="00:10:23.600" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""they get parsed and then into a syntax tree,""" start="00:10:27.720" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""right? Like whatever the language is syntax""" start="00:10:29.180" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""tree is, and then they get,""" start="00:10:30.620" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""the syntax tree gets converted into this,""" start="00:10:33.800" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""like, we call it like an abstract syntax""" start="00:10:35.860" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""tree, which is like abstract from like any,""" start="00:10:38.080" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""like languages specific syntax tree.""" start="00:10:39.860" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""And so then we can cache that,""" start="00:10:41.940" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""which is really good because like if someone""" start="00:10:44.480" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""types something like we don't have to go""" start="00:10:47.700" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""through and do like the full parsing and like""" start="00:10:50.280" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""converting, we only have to do it""" start="00:10:51.560" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""incrementally. And so that's,""" start="00:10:54.960" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""that's how we dealt with that.""" start="00:10:56.100" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""Or the other option is that we just,""" start="00:10:58.140" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""we just cache whatever the previous results""" start="00:11:00.720" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""are, and then run it asynchronously,""" start="00:11:03.460" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""and they might get it delayed.""" start="00:11:04.960" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""But we've ended up doing more AST caching,""" start="00:11:08.200" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""which is fun and cool.""" start="00:11:09.880" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 0]: Sounds good. So we have here a question from""" start="00:11:15.600" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""Blaine. If Eaglet is a subset of LSP mode,""" start="00:11:18.240" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""can EGLOT conflict with LSP mode if both are""" start="00:11:21.680" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""present in your initial .el""" start="00:11:23.400" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""file?""" start="00:11:24.280" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 1]: Yeah, so I haven't played around with EGLOT""" start="00:11:27.740" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""mode a ton, so I'm not 100% sure.""" start="00:11:30.580" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""I think all of the key bindings and commands,""" start="00:11:33.920" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""if you just install it out of the box,""" start="00:11:36.320" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""I Think they're different.""" start="00:11:39.020" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""So I don't think there's like any like""" start="00:11:41.440" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""overlap as far as that stuff goes but you""" start="00:11:44.760" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""will have the overlap of like you entered,""" start="00:11:47.520" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""like you started a major mode for like some""" start="00:11:49.780" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""language, like they'll both probably start""" start="00:11:51.500" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""the language server and provide diagnostics""" start="00:11:53.040" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""and everything. And so then now you're""" start="00:11:55.320" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""getting like, you're just like doubling the""" start="00:11:58.180" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""work your computer is doing.""" start="00:11:59.340" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""So there's that conflict.""" start="00:12:00.480" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""But if you prefer EGLOT mode or LSP mode for""" start="00:12:04.160" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""like 1 language or framework,""" start="00:12:05.200" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""like 1 major mode and LSP mode for the other,""" start="00:12:09.060" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""I think you should be fine.""" start="00:12:10.600" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 0]: All right. Just to let you know,""" start="00:12:14.680" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""we have like 1 minute on the stream and then""" start="00:12:20.460" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""we'll switch back and to the pre-recorded""" start="00:12:22.540" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""stuff I guess.""" start="00:12:24.000" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 2]: Yeah yeah yeah let's hi sorry for the rude""" start="00:12:27.440" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""interruption but I'm just doing a little bit""" start="00:12:29.440" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""of time keeping so thank you so much Austin""" start="00:12:31.700" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""sadly I wasn't able to follow the Q&A because""" start="00:12:34.340" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""I was in the other track answering questions.""" start="00:12:36.280" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""If, Austin, you want to stay and answer some""" start="00:12:39.960" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""more questions, feel free to do so.""" start="00:12:41.580" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""People tend to start talking as soon as we go""" start="00:12:45.920" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""off air, And I wouldn't be surprised with LSP""" start="00:12:48.400" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""that people would do the same.""" start="00:12:49.540" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""We're gonna move on for this track.""" start="00:12:52.800" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""We're gonna move on in 20 seconds to the next""" start="00:12:54.840" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""1. So Floey, thank you for hosting.""" start="00:12:56.920" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""Austin, thank you for all your answers.""" start="00:12:58.680" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""And We'll see you in a bit.""" start="00:13:01.460" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 1]: Cool. Thanks. See you.""" start="00:13:04.740" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 0]: Thanks for the Q&A.""" start="00:13:06.700" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 2]: All right. All right. You are now off air.""" start="00:13:10.120" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""Thank you so much, Austin.""" start="00:13:11.400" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""I'm going to go back running in the""" start="00:13:13.100" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""background. And thank you,""" start="00:13:13.940" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""Flowey, for everything.""" start="00:13:14.700" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 0]: And thanks. Yeah. Have a nice,""" start="00:13:20.900" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""probably a nice day at your work.""" start="00:13:23.160" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 1]: Yeah, no worries. Yeah.""" start="00:13:24.140" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""Yeah, it's still it's like lunchtime for me.""" start="00:13:26.380" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 0]: So okay, here, it's like,""" start="00:13:28.100" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""09:00. 9pm. Thanks for the talk.""" start="00:13:34.380" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""Sorry for the inconvenience was not having""" start="00:13:36.300" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""any, any questions, really.""" start="00:13:37.540" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 1]: So yeah. Oh yeah, no worries.""" start="00:13:39.000" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""It's like, there's like no documentation on""" start="00:13:41.100" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""any of this stuff. So I didn't really expect""" start="00:13:42.940" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""any.""" start="00:13:43.380" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 0]: Yeah, I was kind of interested when I jumped""" start="00:13:47.220" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""into NeoVim. I write it 1 or 2 things on my""" start="00:13:51.000" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""own, but never really got really deep into""" start="00:13:53.140" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""it. And you're gonna see with like compiler""" start="00:13:54.520" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""design and stuff like this,""" start="00:13:55.920" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""but not really specific.""" start="00:13:57.400" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""So I was""" start="00:13:58.320" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 1]: kind of- Yeah, that's the hard part.""" start="00:14:00.860" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""It's like, it's, LSP is cool,""" start="00:14:02.440" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""but then you have to like deal with all the""" start="00:14:05.020" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""like compiler stuff and programming language""" start="00:14:06.760" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""theory.""" start="00:14:07.200" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 0]: So yeah. So it's, it shouldn't be too""" start="00:14:10.600" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""complicated. I had not really a question,""" start="00:14:13.280" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""so, but it worked out fine.""" start="00:14:14.700" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""Thanks for the Q and A.""" start="00:14:16.500" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""And if I have any questions to Oak Hamill,""" start="00:14:18.560" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""Elderspeak will get an email from you.""" start="00:14:20.640" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 1]: Oh yeah, definitely.""" start="00:14:21.560" video="qanda-lspocaml" id="subtitle"]]
+[[!template text="""[Speaker 0]: Dan?""" start="00:14:23.500" video="qanda-lspocaml" id="subtitle"]]
+
+Questions or comments? Please e-mail [austin@cutedogs.org](mailto:austin@cutedogs.org?subject=Comment%20for%20EmacsConf%202023%20lspocaml%3A%20Writing%20a%20language%20server%20in%20OCaml%20for%20Emacs%2C%20fun%2C%20and%20profit)
+
+
+<!-- End of emacsconf-publish-after-page -->