WEBVTT captioned by matthew
NOTE Opening
00:00:00.000 --> 00:00:04.639
Good morning folks, I'm Matthew.
00:00:04.640 --> 00:00:07.399
Welcome to another year of EmacsConf.
00:00:07.400 --> 00:00:10.319
It's looking fantastic this year.
00:00:10.320 --> 00:00:13.559
Firstly, I have to apologize for my voice
00:00:13.560 --> 00:00:15.879
and occasional cough today.
00:00:15.880 --> 00:00:18.039
I am currently recovering from a cold,
00:00:18.040 --> 00:00:21.159
hopefully it's not Covid or flu,
00:00:21.160 --> 00:00:24.719
so please bear with me today.
00:00:24.720 --> 00:00:27.919
Actually, this talk was supposed to be brought to you
00:00:27.920 --> 00:00:31.559
by Manatee Lazycat, the author of lsp-bridge.
00:00:31.560 --> 00:00:36.079
But verbal English isn't Lazycat's strongest skill,
00:00:36.080 --> 00:00:38.599
and we are good friends as we maintain
00:00:38.600 --> 00:00:40.999
the Emacs Application Framework together,
00:00:41.000 --> 00:00:45.999
so here I am today presenting to you this package.
00:00:46.000 --> 00:00:48.479
Welcome to my talk on lsp-bridge:
00:00:48.480 --> 00:00:50.320
a smooth-as-butter asynchronous LSP client.
NOTE What is LSP?
00:00:50.321 --> 00:00:57.200
What is LSP?
00:00:57.201 --> 00:01:01.159
The first question is, what is LSP?
00:01:01.160 --> 00:01:03.199
For anyone who doesn't know here,
00:01:03.200 --> 00:01:06.799
LSP stands for Language Server Protocol,
00:01:06.800 --> 00:01:09.719
it is a set of protocols defined by Microsoft
00:01:09.720 --> 00:01:13.399
that provides smart features like autocomplete,
00:01:13.400 --> 00:01:17.599
go to definition, documentation, etc.,
00:01:17.600 --> 00:01:23.439
that can be implemented across different editors and IDEs.
00:01:23.440 --> 00:01:25.559
It was initially created
00:01:25.560 --> 00:01:28.399
for their Visual Studio Code product,
00:01:28.400 --> 00:01:33.919
then publically shared with everyone.
00:01:33.920 --> 00:01:35.999
So there are language servers out there
00:01:36.000 --> 00:01:38.119
that implemented this procotol,
00:01:38.120 --> 00:01:41.239
and editors need to implement the same procotols
00:01:41.240 --> 00:01:43.119
to talk to the language servers
00:01:43.120 --> 00:01:46.799
in order to retrieve necessary information.
00:01:46.800 --> 00:01:53.159
Emacs has 2 LSP clients already, the lsp-mode and eglot,
00:01:53.160 --> 00:01:57.319
both implemented the protocols and both are very good.
NOTE Why another LSP client?
00:02:00.440 --> 00:02:03.199
Now comes to the second question, of course,
00:02:03.200 --> 00:02:09.519
given lsp-mode and eglot, why another LSP client?
00:02:09.520 --> 00:02:12.359
I used to use lsp-mode all the time,
00:02:12.360 --> 00:02:15.999
I have to say I really appreciate Ivan Yonchovski
00:02:16.000 --> 00:02:20.159
and the team's efforts. Also, I'd like to congratuate eglot
00:02:20.160 --> 00:02:27.439
for making into Emacs 29! These are fantastic packages,
00:02:27.440 --> 00:02:30.999
they are very mature and robust.
NOTE
00:02:31.000 --> 00:02:31.000
However, with all due respect, both of the implementation
00:02:35.120 --> 00:02:36.719
are fundamentally limited
00:02:36.720 --> 00:02:39.639
by the single-threaded nature of Emacs,
00:02:39.640 --> 00:02:43.639
it is neither the fault of lsp-mode nor eglot.
NOTE
00:02:46.000 --> 00:02:47.959
Although in recent years there have been
00:02:47.960 --> 00:02:51.799
improvements to Emacs core such as native JSON support,
00:02:51.800 --> 00:02:55.319
there are still scenarios where Emacs clog
00:02:55.320 --> 00:02:59.359
for a brief second when processing large amounts of data,
00:02:59.360 --> 00:03:03.399
as Emacs is processing everything in the single thread.
00:03:03.400 --> 00:03:08.439
This problem is especially apparent in some LSP servers
00:03:08.440 --> 00:03:11.839
that feeds in tens of thousands of JSON data
00:03:11.840 --> 00:03:15.199
with every single key press.
NOTE
00:03:15.200 --> 00:03:17.559
Additionally, the large amount of data
00:03:17.560 --> 00:03:21.279
sent by the LSP server, such as the completion candidates,
00:03:21.280 --> 00:03:23.959
the diagnostics and documentation,
00:03:23.960 --> 00:03:27.359
they are temporarily stored in the Emacs memory,
00:03:27.360 --> 00:03:31.159
which will trigger garbage collection very frequently,
00:03:31.160 --> 00:03:34.159
this also causes stuttering user experience.
00:03:34.160 --> 00:03:37.279
Increasing the gc-cons-threshold helps,
00:03:37.280 --> 00:03:43.759
but doesn't eliminate the problem.
NOTE
00:03:43.760 --> 00:03:45.559
For something like the LSP,
00:03:45.560 --> 00:03:48.319
the language servers need time to compute,
00:03:48.320 --> 00:03:52.359
and Emacs needs capacity to process and filter
00:03:52.360 --> 00:03:55.799
all the data coming from the language servers.
00:03:55.800 --> 00:03:59.399
A large codebase project with a slow language server
00:03:59.400 --> 00:04:02.439
that sends tens of thousands of JSON
00:04:02.440 --> 00:04:06.519
will significantly increase the time needed to process it,
00:04:06.520 --> 00:04:08.079
when we don't have a multi-thread,
00:04:08.080 --> 00:04:12.719
the single thread originally allocated for perhaps,
00:04:12.720 --> 00:04:17.279
handling user input will be used to process all the data,
00:04:17.280 --> 00:04:22.719
and don't even talk about the garbage collection along the way.
NOTE
00:04:22.720 --> 00:04:26.239
The unfortunate truth is that the size of the codebase
00:04:26.240 --> 00:04:28.919
and the efficiency of the language server
00:04:28.920 --> 00:04:31.759
is completely out of Emacs' control,
00:04:31.760 --> 00:04:38.519
it is also out of both the lsp-mode and eglot's control.
NOTE
00:04:38.520 --> 00:04:40.279
If there's an LSP client
00:04:40.280 --> 00:04:42.279
that can completely eliminate stuttering
00:04:42.280 --> 00:04:44.999
and provide a seamless feedback,
00:04:45.000 --> 00:04:50.279
that would be great, isn't it?
NOTE What is seamless input feedback?
00:04:50.280 --> 00:04:53.839
However, we're vaguely talking about speed right now,
00:04:53.840 --> 00:04:56.399
what is considered fast?
00:04:56.400 --> 00:04:58.359
What is considered seamless?
00:04:58.360 --> 00:05:01.479
What we really mean when we say
00:05:01.480 --> 00:05:05.239
the current LSP implementation is slow?
00:05:05.240 --> 00:05:12.559
Let's first look at the problem fundamentally.
NOTE
00:05:12.560 --> 00:05:17.679
We interact with Emacs through a keyboard,
00:05:17.680 --> 00:05:22.719
so what we perceive as a fast and smooth feedback
00:05:22.720 --> 00:05:25.999
completely depends on how long it takes
00:05:26.000 --> 00:05:29.359
for a keyboard input to display on the Emacs buffer.
00:05:29.360 --> 00:05:32.919
From a pure graphical perspective,
00:05:32.920 --> 00:05:36.519
we need a minimum of 24 frames per second,
00:05:36.520 --> 00:05:39.079
the standard in the media industry,
00:05:39.080 --> 00:05:42.359
for us humans to perceive something as seamless.
00:05:42.360 --> 00:05:46.999
Say we need 25 frames per second, this means,
00:05:47.000 --> 00:05:50.399
if we divide 1000 milliseconds by 25,
00:05:50.400 --> 00:05:54.759
we only have approximately 40 millisecond window
00:05:54.760 --> 00:05:57.919
for the response time to spare.
00:05:57.920 --> 00:06:01.679
Even if we relax the constraint a bit more,
00:06:01.680 --> 00:06:06.679
on average a typist takes about 100 to 200 milliseconds
00:06:06.680 --> 00:06:09.159
between typing each character,
00:06:09.160 --> 00:06:12.599
so as long as we see a response within this timeframe,
00:06:12.600 --> 00:06:19.559
it is tolerable. However, using a slow language server
00:06:19.560 --> 00:06:22.279
on a large codebase easily exceeds
00:06:22.280 --> 00:06:24.679
the hundred millisecond mark,
00:06:24.680 --> 00:06:27.479
and sometimes takes more than 200 milliseconds,
00:06:27.480 --> 00:06:32.039
and inevitably will cause an inconsistent delay
00:06:32.040 --> 00:06:33.199
for the end user.
NOTE
00:06:33.200 --> 00:06:37.959
At this point, someone might want to point out
00:06:37.960 --> 00:06:41.079
that nobody is gonna type at the maximum pace all the time.
00:06:41.080 --> 00:06:45.039
That's right, frankly speaking most of my time
00:06:45.040 --> 00:06:47.639
spent at programming is not writing code,
00:06:47.640 --> 00:06:49.039
but staring at the screen
00:06:49.040 --> 00:06:51.279
thinking about how to write the code.
00:06:51.280 --> 00:06:55.599
However, when we do actually type,
00:06:55.600 --> 00:07:00.359
maybe only a sentence, a variable name, a keyword,
00:07:00.360 --> 00:07:03.039
or just performing keybinding shortcuts,
00:07:03.040 --> 00:07:08.479
that's when we want to see our input feedback immediately.
00:07:08.480 --> 00:07:10.479
We've already spend so much time
00:07:10.480 --> 00:07:12.159
thinking about how to write,
00:07:12.160 --> 00:07:16.479
we don't want to waste any more time waiting for Emacs
00:07:16.480 --> 00:07:19.559
to process and show us what we've written
00:07:19.560 --> 00:07:27.679
half a second ago. Otherwise the frustration will build up.
NOTE EAF showed a possibility
00:07:28.400 --> 00:07:31.999
In the past two years of EmacsConf, I've talked about
00:07:32.000 --> 00:07:35.399
the Emacs Application Framework, a project that extended
00:07:35.400 --> 00:07:39.839
Emacs Lisp to Python, Qt and JavaScript ecosystems.
00:07:39.840 --> 00:07:43.759
The EAF project specializes in improving
00:07:43.760 --> 00:07:47.439
the graphical and multimedia capabilities of Emacs
00:07:47.440 --> 00:07:51.759
through other languages, it was a great success.
00:07:51.760 --> 00:07:55.759
It demonstrated the endless possibilities of Emacs
00:07:55.760 --> 00:08:00.159
by embracing the strengths in other ecosystems.
00:08:00.160 --> 00:08:04.239
If anyone is interested for more information on EAF,
00:08:04.240 --> 00:08:08.519
please see the EAF repo and refer to my talks
00:08:08.520 --> 00:08:12.959
from EmacsConf2020 and 2021.
00:08:12.960 --> 00:08:12.960
00:08:12.960 --> 00:08:16.239
The EAF project was created by Manatee Lazycat as well,
00:08:16.240 --> 00:08:19.999
so he thought if there is a way to design
00:08:20.000 --> 00:08:22.759
an LSP client similar to EAF
00:08:22.760 --> 00:08:25.759
that takes the advantage of Python's multi-threading,
00:08:25.760 --> 00:08:27.839
it will be able to solve our problem.
00:08:27.840 --> 00:08:32.399
Conveniently EAF had already done most of the ground work
00:08:32.400 --> 00:08:34.359
and demonstrated the possibility
00:08:34.360 --> 00:08:42.159
of cooperating Elisp and Python using the Emacs RPC effectively.
NOTE LSP Bridge Objectives
00:08:42.160 --> 00:08:45.039
LSP Bridge has several goals in mind.
00:08:45.040 --> 00:08:50.159
Firstly, performance is the number one priority.
00:08:50.160 --> 00:08:55.839
Secondly, use Python multi-threading to bypass
00:08:55.840 --> 00:08:59.239
the aforementioned bottlenecks of a single-threaded Emacs.
00:08:59.240 --> 00:09:04.519
Thirdly, provide a simple solution that requires
00:09:04.520 --> 00:09:07.519
minimal setup for someone who just wants to have
00:09:07.520 --> 00:09:10.079
a fast autocomplete system in Emacs.
00:09:10.080 --> 00:09:15.999
This means, LSP Bridge does not intend
00:09:16.000 --> 00:09:21.439
and will not implement the entire LSP protocol,
00:09:21.440 --> 00:09:23.639
which is a vastly different approach
00:09:23.640 --> 00:09:25.759
than a solution like lsp-mode,
00:09:25.760 --> 00:09:28.479
we do not want to compete this way.
00:09:28.480 --> 00:09:33.559
We also believe some of the LSP Protocol features
00:09:33.560 --> 00:09:37.759
are unnecessary, or we already have better solutions
00:09:37.760 --> 00:09:38.959
in the Emacs ecosystem,
00:09:38.960 --> 00:09:42.679
such as tree-sitter for syntax highlighting.
00:09:42.680 --> 00:09:44.959
So we will not reinvent the wheel.
00:09:44.960 --> 00:09:50.279
Ultimately, we want to provide the fastest, butter-smooth
00:09:50.280 --> 00:09:53.679
and performant LSP client out of the box.
NOTE Design.
00:09:53.680 --> 00:09:54.560
Design.
00:09:54.561 --> 00:10:01.239
Now let's look at the design architecture diagram.
00:10:01.240 --> 00:10:04.639
As you can see, it is split into
00:10:04.640 --> 00:10:07.079
the top half and bottom half.
00:10:07.080 --> 00:10:10.559
The top is the design for a single file model,
00:10:10.560 --> 00:10:13.359
and the bottom half is for project model.
00:10:13.360 --> 00:10:18.159
We make this distinction because we don't want a new user
00:10:18.160 --> 00:10:22.599
to be troubled on choosing a project root directory
00:10:22.600 --> 00:10:25.199
as the first impression to LSP
00:10:25.200 --> 00:10:27.279
before even start writing code.
00:10:27.280 --> 00:10:27.280
00:10:27.280 --> 00:10:30.479
From a new user's perspective,
00:10:30.480 --> 00:10:32.959
they've just installed this package,
00:10:32.960 --> 00:10:35.159
and all they are expecting
00:10:35.160 --> 00:10:37.679
is using a smart autocomplete system,
00:10:37.680 --> 00:10:41.519
what does root directory even mean in this context?
00:10:41.520 --> 00:10:44.119
So we make the decision for them
00:10:44.120 --> 00:10:48.199
based on whether this file is part of a git repository.
00:10:48.200 --> 00:10:56.719
Often times we write code in its own standalone file,
00:10:56.720 --> 00:10:59.919
this is extremely common for scripting languages
00:10:59.920 --> 00:11:03.319
like bash or python. So in the single file model,
00:11:03.320 --> 00:11:07.159
LSP Bridge will start a dedicated LSP server
00:11:07.160 --> 00:11:10.319
for this particular file based on file type,
00:11:10.320 --> 00:11:13.479
and every file corresponds to a LSP server,
00:11:13.480 --> 00:11:17.839
so each server doesn't interfere with one another.
00:11:17.840 --> 00:11:23.719
The project model will have every file of the same type
00:11:23.720 --> 00:11:25.919
under the same project share one server.
00:11:25.920 --> 00:11:30.439
We believe this is a positive trade-off for user experience.
00:11:30.440 --> 00:11:30.440
00:11:30.440 --> 00:11:36.599
LSP Bridge internally implemented two main threads,
00:11:36.600 --> 00:11:40.399
one is the Request Thread, the other is Response Thread.
00:11:40.400 --> 00:11:45.279
The Request Thread is used to handle all the requests
00:11:45.280 --> 00:11:48.679
coming from Emacs, it does not answer immediately,
00:11:48.680 --> 00:11:52.839
this is important because Emacs doesn't need to wait
00:11:52.840 --> 00:11:54.679
for any response under any reason,
00:11:54.680 --> 00:11:58.159
even if the server is buggy or died out,
00:11:58.160 --> 00:12:01.159
it shouldn't matter to the performance of Emacs.
00:12:01.160 --> 00:12:04.039
The Response Thread is used to handle
00:12:04.040 --> 00:12:06.559
the response coming from LSP servers.
00:12:06.560 --> 00:12:11.239
After retrieving a response, regardless of the JSON size,
00:12:11.240 --> 00:12:14.439
it sends to its own thread for computation,
00:12:14.440 --> 00:12:17.079
such as candidate filtering and renaming.
00:12:17.080 --> 00:12:19.999
Once the computation is finished,
00:12:20.000 --> 00:12:23.639
it will determine if this information is expired,
00:12:23.640 --> 00:12:26.399
if not, then push it to Emacs.
00:12:26.400 --> 00:12:26.400
00:12:26.400 --> 00:12:31.559
From the Emacs side, when it receives the LSP information,
00:12:31.560 --> 00:12:34.639
it only needs to determine the course of action,
00:12:34.640 --> 00:12:39.159
either popup completion, jump to definition,
00:12:39.160 --> 00:12:44.799
renaming action, or show references and show documentions.
00:12:44.800 --> 00:12:49.119
You see, from a user, all LSP Bridge doing
00:12:49.120 --> 00:12:52.279
is these 5 things, the user doesn't need to care about
00:12:52.280 --> 00:12:54.559
anything else like the complicated
00:12:54.560 --> 00:12:56.479
Language Server Protocols.
00:12:56.480 --> 00:12:56.480
00:12:56.480 --> 00:13:02.439
Python side caches heavy data
00:13:02.440 --> 00:13:06.279
such as candidate documentation and diagnostics.
00:13:06.280 --> 00:13:11.079
We process as much server data as possible in Python,
00:13:11.080 --> 00:13:15.759
and only pass to Emacs as little data as possible
00:13:15.760 --> 00:13:18.159
so it doesn't clog the Emacs thread
00:13:18.160 --> 00:13:19.799
and triggers garbage collection.
00:13:19.800 --> 00:13:19.800
00:13:19.800 --> 00:13:24.319
This design is critical, because all Emacs needs to do
00:13:24.320 --> 00:13:27.039
is sending LSP requests to LSP Bridge,
00:13:27.040 --> 00:13:29.439
it doesn't wait for a response,
00:13:29.440 --> 00:13:32.999
it simply knows what to do *when* there is a response.
00:13:33.000 --> 00:13:37.159
So the user's input immediately displays on the buffer
00:13:37.160 --> 00:13:39.559
well within the 40 millisecond window,
00:13:39.560 --> 00:13:45.199
and in the mean time, the user can continue to type
00:13:45.200 --> 00:13:48.199
if he doesn't need the help from LSP right away,
00:13:48.200 --> 00:13:51.279
it fundamentally resolves the stuttering problem.
NOTE ACM - Asynchronous Completion Menu
00:13:51.280 --> 00:13:59.079
Now I want to talk about acm-mode,
00:13:59.080 --> 00:14:09.599
which stands for asynchronous completion menu,
00:14:09.600 --> 00:14:12.479
it is a completion framework
00:14:12.480 --> 00:14:15.039
that currently bundled with LSP Bridge
00:14:15.040 --> 00:14:17.279
designed to accomodate for
00:14:17.280 --> 00:14:20.399
the asynchronous nature of LSP servers.
00:14:20.400 --> 00:14:26.919
It is a replacement for the built-in capf,
00:14:26.920 --> 00:14:30.359
short for completion-at-point-functions,
00:14:30.360 --> 00:14:32.519
used in almost everywhere
00:14:32.520 --> 00:14:35.759
including company-mode and corfu-mode.
00:14:35.760 --> 00:14:40.839
Yes, we unfortunately reinvented a very fundamental wheel.
00:14:40.840 --> 00:14:44.279
No, it wasn't an easy decision.
00:14:44.280 --> 00:14:47.879
However we still believe it's worth it.
00:14:47.880 --> 00:14:53.359
LSP Bridge initially used company-mode,
00:14:53.360 --> 00:14:56.119
then moved on to corfu-mode for a while,
00:14:56.120 --> 00:14:58.999
but eventually Lazycat determined
00:14:59.000 --> 00:15:00.719
that it is much more painful to write
00:15:00.720 --> 00:15:05.679
a lot of workaround code to force LSP Bridge
00:15:05.680 --> 00:15:09.959
to handle capf nicely than to just fork Corfu,
00:15:09.960 --> 00:15:11.999
remove all the capf code,
00:15:12.000 --> 00:15:15.239
and write a new completion framework from the remainings.
00:15:15.240 --> 00:15:15.240
00:15:15.240 --> 00:15:20.719
Performance wise, capf requires Emacs to store
00:15:20.720 --> 00:15:23.119
the entire candidate list
00:15:23.120 --> 00:15:27.159
when looking up candidate annotations.
00:15:27.160 --> 00:15:30.639
It needs to search through the entire candidate list first,
00:15:30.640 --> 00:15:32.599
then use the candidate as a key
00:15:32.600 --> 00:15:34.799
to search for the actual information.
00:15:34.800 --> 00:15:38.919
This entire process will be repeated every time
00:15:38.920 --> 00:15:40.679
when drawing the completion menu.
00:15:40.680 --> 00:15:45.199
This is truly intensive computing task for Emacs to handle.
00:15:45.200 --> 00:15:50.519
On top of that, the existing capf frameworks assume
00:15:50.520 --> 00:15:54.279
the candidate list, which is retrieved from the LSP server,
00:15:54.280 --> 00:15:56.839
to be ready and finalized in place
00:15:56.840 --> 00:15:58.719
when the completion popup occurred.
00:15:58.720 --> 00:16:02.119
However given the design of LSP Bridge,
00:16:02.120 --> 00:16:05.919
Emacs will not sit there and wait for the server response,
00:16:05.920 --> 00:16:10.439
instead the Response Thread may feed Emacs data
00:16:10.440 --> 00:16:14.919
whenever it's ready. This makes capf almost impossible
00:16:14.920 --> 00:16:21.919
to form a finalized candidate list during popup.
00:16:21.920 --> 00:16:21.920
00:16:21.920 --> 00:16:26.079
The complete reasons regarding why capf is incompatible
00:16:26.080 --> 00:16:28.679
with the asynchronous nature of LSP servers
00:16:28.680 --> 00:16:32.479
are very complicated and deserves its own talk.
00:16:32.480 --> 00:16:37.079
Lazycat wrote an entire blog post detailing his reasonings,
00:16:37.080 --> 00:16:40.999
while Corfu's author Daniel Mendler a.k.a minad
00:16:41.000 --> 00:16:44.239
also done his own investigations and experiments,
00:16:44.240 --> 00:16:47.239
and reached a common conclusion.
00:16:47.240 --> 00:16:50.919
For anyone interested, I've pasted the links
00:16:50.920 --> 00:16:52.759
to the corresponding posts here.
00:16:52.760 --> 00:16:57.399
Therefore, keep in mind that LSP Bridge
00:16:57.400 --> 00:16:59.919
can only use acm-mode to work nicely,
00:16:59.920 --> 00:17:03.359
so please disable other completion frameworks
00:17:03.360 --> 00:17:07.159
like company and corfu before trying LSP Bridge.
NOTE LSP Bridge + ACM -> Multi-Backend Completion Framework
00:17:07.160 --> 00:17:14.919
By designing ACM with asynchronous server response in mind,
00:17:14.920 --> 00:17:18.759
this unlocks LSP Bridge project's potential
00:17:18.760 --> 00:17:22.199
to provide completions from almost any backends.
00:17:22.200 --> 00:17:25.679
ACM has blended all the backends together,
00:17:25.680 --> 00:17:28.799
and configured a priority to display
00:17:28.800 --> 00:17:32.839
important completion results like LSP before other backends.
00:17:32.840 --> 00:17:38.559
It can autocomplete LSP, TabNine, Elisp symbols, yasnippets,
00:17:38.560 --> 00:17:41.039
even English dictionaries and much more.
00:17:41.040 --> 00:17:43.959
As long as you have the backends installed,
00:17:43.960 --> 00:17:46.319
they all work out-of-the-box!
NOTE Today and future. Join us!
00:17:46.320 --> 00:17:55.239
Although LSP Bridge is a relatively new package
00:17:55.240 --> 00:18:00.039
with just over 7 months old, it is already a success!
00:18:00.040 --> 00:18:06.599
As of December of 2022, we have 67 contributors
00:18:06.600 --> 00:18:08.439
making more than 1000 commits,
00:18:08.440 --> 00:18:12.679
and we reached more than 600 stars on Github!
00:18:12.680 --> 00:18:16.359
LSP Bridge is easily extensible,
00:18:16.360 --> 00:18:18.879
developing a new language backend is very simple too,
00:18:18.880 --> 00:18:20.639
feel free to join us!
00:18:20.640 --> 00:18:25.599
LSP Bridge is another successful example
00:18:25.600 --> 00:18:29.919
of extending Emacs Lisp with Python, and just like EAF,
00:18:29.920 --> 00:18:33.639
it demonstrated the potential Emacs can achieve
00:18:33.640 --> 00:18:37.039
when we jump out of the Lisp-only world
00:18:37.040 --> 00:18:39.199
and embrace other ecosystems.
00:18:39.200 --> 00:18:43.479
Recently Lazycat created a package called blink-search
00:18:43.480 --> 00:18:45.679
that leveraged similar ideas
00:18:45.680 --> 00:18:48.919
but an asynchronous search framework,
00:18:48.920 --> 00:18:51.239
as well as a package called deno-bridge
00:18:51.240 --> 00:18:53.119
that extended Emacs Lisp
00:18:53.120 --> 00:18:56.439
with Deno JavaScript TypeScript runtimes.
00:18:56.440 --> 00:18:57.559
Please check it out,
00:18:57.560 --> 00:19:05.199
if consider joining the development too!
NOTE Thanks
00:19:05.200 --> 00:19:08.599
This is the entirety of my presentation, thanks for joining!
00:19:08.600 --> 00:19:11.319
Me and Lazycat will be available
00:19:11.320 --> 00:19:20.240
to answer questions on IRC and Etherpad.