lsp-bridge -- 速度最快的语法补全插件

是需要的,只修了一半 hh

最新的代码有这个问题

Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/threading.py", line 926, in _bootstrap_inner
    self.run()
  File "/usr/local/lib/python3.7/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/Users/zy/.emacs.d/repo/lsp-bridge/lsp-bridge.py", line 96, in postgui_dispatcher
    getattr(self, func_name)(*func_args)
  File "/Users/zy/.emacs.d/repo/lsp-bridge/lsp-bridge.py", line 167, in _do
    getattr(action, name)(*args[1:])
TypeError: change_file() takes 8 positional arguments but 11 were given

你可能需要 rebuild 一下 package?感觉执行的是旧的 el 和新的 py。

好的!我等会再试下

正常了,thx

同志们,我试了可以和eglot共存,因为有些功能如eldoc和flymake我还离不了。参考配置:

(use-package lsp-bridge
           :load-path "~/.emacs.d/packages/lsp/lsp-bridge-master"
           :commands(lsp-bridge-mode)
           :init
           (defun lsp-ensure()
             (setq-local corfu-auto nil)  ;; let lsp-bridge control when popup completion frame    
             (lsp-bridge-mode 1)
             (define-key lsp-bridge-mode-map [remap xref-find-definitions] 'lsp-bridge-find-define)
             (when (functionp 'eglot-ensure)
               (eglot-ensure)
               )
             )
           :config
           (require 'lsp-bridge-orderless)
           (require 'lsp-bridge-icon)
           )
         (use-package eglot
           :load-path "~/.emacs.d/packages/lsp"
           :init
           (unless (functionp 'lsp-bridge-mode)
             (defun lsp-ensure() (eglot-ensure)))
           (setq eglot-confirm-server-initiated-edits nil) ; 避免code action的提示
           :commands (eglot eglot-ensure eglot-rename)
           :config
           ;; flymake还是要开的,错误不处理的话,补全就不能用了。用跟cmake一样的vs版本可以解决很多错误
           ;; (add-to-list 'eglot-stay-out-of 'flymake)
           (when (functionp 'lsp-bridge-mode)   ;; 用lsp-bridge时,eglot只开启部分功能
             (add-to-list 'eglot-stay-out-of 'xref)
             (add-to-list 'eglot-stay-out-of 'company) ;; 它还会用原生的,所以要remove-hook completion-at-point-functions
             (add-hook 'eglot-managed-mode-hook
                       (lambda ()
                         (remove-hook 'completion-at-point-functions #'eglot-completion-at-point t)
                         (remove-hook 'xref-backend-functions 'eglot-xref-backend t)
                         ))
             )
           (setq eglot-autoshutdown t)      ;; 不关退出emacs会卡死
           (push :documentHighlightProvider ;; 关闭光标下sybmol加粗高亮
                 eglot-ignored-server-capabilities) 
           ;; clang-format不需要了,默认情况下会sort includes line,导致编译不过,但clangd的却不会,但是要自定义格式需要创建.clang-format文件
           (define-key eglot-mode-map [(meta f8)] 'eglot-format)
           )

最后给prog mode添加hook即可:
(add-hook 'rust-mode-hook (lambda ()
			                
			                (lsp-ensure)
			                ))

不过呢,这样配下来,感觉好像是有那么一点卡了,哈哈

只需要在use-package下加个:disabled可以随时禁用eglot单独用lsp-bridge,或者禁用lsp-bridge单独用eglot。

2 个赞

现在handle_completion_response只传了completion_items, kinds, annotations这三个东西回 emacs,后续如果需要更多字段,怎么处理比较好呢? 再加参数看起来不太合适

是否可以直接构造 plist,然后传给 emacs 直接 read?不太清楚这样做开销是否会很大。但是好处是 capf 那部分代码可以直接抄 elgot 的,很多功能就不用重复开发了

一个可用的简单实现,没有考虑细节

def lispify(L):
    "Convert a Python object L to a lisp representation."
    if isinstance(L, str):
        return f"\"{L}\""
    if isinstance(L, float) or isinstance(L, int):
        return str(L)
    elif isinstance(L, list) or isinstance(L, tuple):
        return "(" + " ".join(map(lispify, L)) + ")"
    elif isinstance(L, dict):
        s = [":{0} {1}".format(k, lispify(v)) for k, v in L.items()]
        return "(" + " ".join(s) + ")"

主要是我还加了几个依赖company的包,主要是company-ctags和company-tabnine,没找到corfu下有可以替代的包;corfu可以和company共存吗?

@zerol 大佬改造了一下, 现在可以支持 sexpdata 传递复杂数据。

但是我的意思是,你需要把 server 返回的 document 都传递回 elisp 吗? 像 volar 这样的后端狂魔, 打一个字符回传几万行的 markdown 文档不好吧。

我的建议是有文档可以缓存到 python 端,然后用的时候一个一个的请求。

如果有 lsp , ctags应该不用了。

tabnine 我正经用了3年,但是客观的说,只有在 javascript 那里写重复代码的时候才有用, 比如 this.long_attr = long_attr 这种重复体力活的地方。

其他时候 tabnine 消耗了我太多性能, 却帮助不大。

1 个赞

用 lsp-bridge 直接配 flycheck 吧,我天天用, 性能好得很。

eldoc 功能稍微等一下,这两天支持一下。

在稍微大一点的项目或者后端传递数据比较多的情况, lsp-mode 和 eglot 都会卡手的。

好的,我去试试flycheck

tabnine 直接用 cape 转 company-tabnine 或者用 GitHub - 50ways2sayhard/tabnine-capf: A capf version of company-tabnine: https://github.com/TommyX12/company-tabnine

有一些高级功能,比如 snippet 或 auto-import 还是需要传到 emacs 那边处理的吧,这些数据的量也不会很大

对,凡是数据量大的谨慎传递到 Emacs 端去处理, lsp-bridge 这边是多线程运行的,有足够的时间去处理这些数据。

Emacs 那边只用处理结果就行了, 这样可以保证以后加所有功能, lsp-bridge 都能在性能上比肩 VSCode 体验的。

已经在工作环境正式用了半天了,已经对现在的情况满足了,希望能谨慎加功能,速度还是第一要素

1 个赞

flycheck 和 go 一起性能不咋地,而且对比 eglot + flymake 还有显示慢和位置不对等问题

感谢反馈,放心, 性能和功能的平衡我会把握的,性能是 lsp-bridge 这个项目创建的初衷,这个不会妥协的。

1 个赞

懒猫对代码格式化的支持怎么考虑?会考虑加到 lsp-bridge 里吗?

代码格式化为啥要加到 lsp-bridge ?

Emacs生态已经非常完整了,LSP出来之前代码格式化、实时错误检查都非常成熟了。

我的个人看法:

  1. lsp-bridge 专注于代码补全、定义跳转、引用查看、重命名和API文档查看这些依赖语义分析的功能,这是LSP的长处
  2. 像代码格式化、实时检查等等Emacs生态有的功能都不用做,一来LSP后端也是依赖社区的静态工具,为啥不让Emacs直接和这些工具通讯,而是在LSP塞这么多功能?
6 个赞