lsp-mode新接口lsp.el

First cut on lsp-mode restructoring 後繼,https://github.com/emacs-lsp/lsp-mode/pull/469 被合併了。

這是重大的改動

  • 原來的簡單client如lsp-{css,bash,groovy,html,…}被整合進lsp-clients.el。對於這類語言(require 'lsp-clients)M-x lsp。複雜的仍保留各自的包:lsp-ccls lsp-java …
  • 支援每個workspace多個language servers,標識爲lsp--buffer-workspaces
  • 簡單的session管理,見M-x lsp-describe-session(用widget.el畫樹) M-x lsp-restart-workspace
  • 原先,project最後一個buffer close時關閉language server,現在需要用M-x lsp-shutdown-workspace (或者(setq lsp-keep-workspace-alive nil))
  • 預設lsp-auto-configuret,自動配置lsp-ui company-lsp(及yas-minor-mode) flymake/flycheck
  • 爲了簡化mutual dependency處理,之前的各個lsp-*.el被合併成lsp.el,接下來要做的是把各個包遷移到lsp.el的新接口。現在是引入breaking changes的絕佳機會。詳見lsp-mode#479 Port existing packages to lsp.el
  • 原來用lsp--cur-workspace標識當前workspace (哪個language,哪個project);現在用lsp--buffer-workspaces(複數是因爲可以多language servers),當lsp--cur-workspace設置時則處理單一language server
  • 若language server支援workspace folders,client可以使用(lsp-register-client (make-lsp-client ... :multi-root t))。新開的buffer所屬的project也會註冊到現有的language server上,除非lsp的參數ignore-multi-foldert

我做了一些測試,lsp.ellsp-*.el定義了很多同名函數,有些有行爲差異,如果部分插件依賴前者、部分插件依賴後者就會導致一些插件運行錯誤。12月8日舊的接口刪除了,lsp-mode.el重定向到lsp.el

spacemacs +tools/lsp用戶參見https://github.com/syl20bnr/spacemacs/issues/11161#issuecomment-443483225討論

配置

(use-package lsp-mode
  :commands lsp
  :init
  (setq lsp-auto-guess-root t)    ; 我習慣自動選project root
  ;; (setq lsp-prefer-flymake t)  ; 預設t。flymake替代flycheck
  :config
  (require 'lsp-clients)          ; ocaml,css,python,bash,...
  )

lsp-java

(use-package lsp-java
  :hook (java-mode . (lambda () (require 'lsp-java) (lsp))))

ccls

(use-package ccls
  :hook ((c-mode c++-mode objc-mode) . (lambda () (require 'ccls) (lsp))))

另外參見 https://github.com/MaskRay/ccls/wiki/lsp-mode 注意原來的M-x lsp-ccls-enable不存在了

clangd (lsp-clients.el predefined server)

(use-package lsp-mode
  :commands lsp
  :hook ((c-mode c++-mode objc-mode) . lsp))

作爲predefined server, priority爲-1會被priority 0的external package覆蓋

pyls

(add-hook 'python-mode-hook #'lsp)

其他

另外emacs-cquery我也改好了。

project root用lsp--suggest-project-root查詢,(projectile-project-root)(project-current)。如果(setq lsp-auto-guess-root t)可以避免進入新project時的menu

14赞

Thanks

看来是向着eglot的方向发展了

更新到最新的emacs-ccls之后,emacs调不起ccls进程了,报了下面这个错误

问题解决了,开方式变了,没仔细看文档,抱歉。

今天试了一下,确实更像 eglot 了,但还有很多没有 port,bug 也不少,暂时还不稳定。

重新組織了下內容。另外Emacs 26的話可以用flymake了,需要設定(setq lsp-prefer-flymake t)

Update: Emacs 26.1以上優先flymake,除非(setq lsp-prefer-flymake nil)

新版本的bug太多了,简直没法用。

舉例?舉例?

这种更新一般要选择一个吉日啊,比如沐浴更衣后在这个月底的23:59分敲下 update 命令 :joy:

主要是company-lsp的PR还没merge,然而其他的merge的都很快,就不同步了

已经合并了吧, 3号就合并了。

PS: 我觉得主要问题是插件变动比较大,原本的配置基本上已经无法继续使用了,而大家的配置又没有及时更新,所以导致了各种问题

确实,主要是 README 没有同步更新,包括 README-next。其实大部分功能都没有问题,少部分 client 没有 port 完成或者不稳定。Centaur Emacs 已经迁移到最新的lsp上了,配置其实比以前简单很多。

分享一下你的 lsp 配置文件链接吧, 我这几天转了 eglot 也是各种问题.

有时候看到 lsp-mode/eglot 的用户体验做的太差了, 真的想自己写一个 lsp 框架来零配置的解决所有这些配置麻烦, company 折腾的代码.

LSP是好的框架, 大部分LSP Server都实现的不错, 但是 Emacs 的 LSP Client实现的太差了:

  • lsp-mode 配置太麻烦, 而且从架构设计上不够健壮
  • eglot 启动文件太慢了, 而且绑死 flymake

最近太忙了, 忍住了, 如果哪一天实在忍不住了, 我就自己写 lsp 框架.

1赞

还有个fix lsp prefix的还没merge,好像还在WIP。搞笑的是,我一模一样的配置,company-lsp 在linux上面可以用,mac就挂了😂我也懒得改recipe了,反正最近不怎么用mac

1赞

如果有好的想法也可以自己来写哈,不过另起炉灶需要很多精力啊。参与到现有项目中也是一个选择。新的lsp还不错,开发者也很积极。

我的配置在这里:https://github.com/seagle0128/.emacs.d/blob/master/lisp/init-lsp.el。

1赞

好的, 谢谢, 我一会看看你的配置, 感谢分享.

我主要觉得在 LSP 协议和服务端都实现很健全, VSCode/Vi 都用的很爽的时候, Emacs 这边确实各种因为作者的问题, 导致设计架构不好, 配置麻烦, 用户体验太差 (卡和各种报错).

用户需要的就是零配置的LSP Client插件, 一行 require 代码搞定所有事情, 最多提供几个选项可以自定义 mode-hook 和关闭高级功能.

我先忍一段时间吧, 如果这几个月忙完了, lsp-mode 和 eglot 还是让我各种崩溃的话, 我就自己写啦, 对这两个项目的代码质量和用户体验没法吐槽了.

是的,VSCode 用户体验确实很棒,这也是 Emacs 应该借鉴的地方。只是习惯了 Emacs 各种 keybinding,也受不了浏览器系编辑器巨大的内存占用,还是坚守这个老古董了。lsp-modeeglot都在朝好的方向发展,假以时日应该能稳定和成熟起来。如果到时还是各种问题,我也愿意一起搞个新的出来 :smile:

更新了一下,好几个client都有问题,先迁移到eglot, 感觉细节差得还有点多,比如flymake 有些错误提示不会实时消除,不知道大家有没有遇到这样的问题

新的接口lsp 确实有些Client还有问题,我刚才就报了两个 issue。不过最近修复很快。

eglot是后来者,flymake 是同一个作者。不过总感觉质量和功能有些不爽。反正目前我还是用flycheck,尽管flymake内置并重写了。相应的,试用了一段eglot,感觉还是太简陋了,离自己想要的还是差很远,虽然目前还保留一个选项在Centaur Emacs中。eglot 唯一的优点就只剩配置简单了。