1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
|
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.
|