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