kill ruby buffer 导致 lsp-ruby 错误

今天又玩了一下 lsp-mode, python 和 ruby 都可以很好的工作了.

只是有一个小不爽, 当 kill ruby buffer 以后, 会导致一下的错误:

Debugger entered--Lisp error: (error "lsp-ruby TCP connection: Cannot communicate with the process (closed)")
  signal(error ("lsp-ruby TCP connection: Cannot communicate with the process (closed)"))
  error("%s: Cannot communicate with the process (%s)" "lsp-ruby TCP connection" closed)
  (progn (error "%s: Cannot communicate with the process (%s)" (process-name proc) (process-status proc)))
  (if (memq (process-status proc) '(stop exit closed failed nil)) (progn (error "%s: Cannot communicate with the process (%s)" (process-name proc) (process-status proc))))
  lsp--send-no-wait("Content-Length: 3939\15\n\15\n{\"jsonrpc\":\"2.0\",\"method\":\"textDocument/didOpen\",\"params\":{\"textDocument\":{\"uri\":\"file:///Users/andy/tower-ng/app/controllers/members_controller.rb\",\"languageId\":\"ruby\",\"version\":0,\"text\":\"# frozen_string_literal: true\\n\\n# Control team member.\\nclass MembersController < ApplicationController\\n  def index\\n    # Create memeber array.\\n    @member_array = []\\n\\n    # Push creator at first.\\n    team = current_team\\n    team_creator = User.find_by_email(team.creator)\\n\\n    @member_array.push(user_hashid: team_creator.hashid,\\n                       name: team_creator.name,\\n                       type: \\\"超级管理员\\\",\\n                       email: team_creator.email,\\n                       color: \\\"member-type-super-admin\\\",\\n                       photo_url: current_user.avatar_url)\\n\\n    # Push team members.\\n    TeamAdmin.select { |t| t.team_id == team.id }.each do |team_admin|\\n      user = User.find_by_id(team_admin.user_id)\\n\\n      member_type = team_admin.is_administrator ? \\\"管理员\\\" : \\\"成员\\\"\\n      member_color = team_admin.is_administrator ? \\\"member-type-admin\\\" : \\\"member-type-member\\\"\\n\\n      if user&.activated?\\n        @member_array.push(user_hashid: user.hashid,\\n                           name: user.name,\\n                           type: member_type,\\n                           email: user.email,\\n                           color: member_color,\\n                           photo_url: user.avatar_url)\\n\\n      elsif !user.nil?\\n        @member_array.push(user_hashid: user.hashid,\\n                           name: user.email.split(\\\"@\\\")[0],\\n                           type: \\\"已邀请\\\",\\n                           email: user.email,\\n                           color: member_color,\\n                           photo_url: user.avatar_url)\\n\\n      end\\n    end\\n  end\\n\\n  def new; end\\n\\n  def show\\n    @project = Project.find_by_hashid(params[:id])\\n    @user = User.find_by_hashid(params[:id])\\n\\n    if @user&.activated?\\n      redirect_to user_path(@user.id)\\n    else\\n      @user_name = @user.email.split(\\\"@\\\")[0]\\n    end\\n  end\\n\\n  def create\\n    params[:members].values.reverse.uniq { |m| m[0] }.reverse_each do |member|\\n      user = User.find_by_email(member[0])\\n\\n      unless user\\n        user = User.new(email: member[0])\\n        user.save\\n\\n        print(\\\"Send activation mail: \\\", edit_account_activation_url(user.activation_token, email: user.email, team_id: current_team.hashid), \\\"\\\\n\\\")\\n      end\\n\\n      team_admin = TeamAdmin.new(team_id: current_team.id, user_id: user.id, is_administrator: member[1] == \\\"admin\\\")\\n      team_admin.save\\n    end\\n\\n    redirect_to team_members_path\\n  end\\n\\n  def edit\\n    if params[:action_type] == \\\"cancel_invite\\\"\\n\\n      user = User.find_by_hashid(params[:id])\\n\\n      if user&.activated?\\n        redirect_to user_path(user.id)\\n      else\\n        team_admin = TeamAdmin.find_by_user_id(user.id)\\n        team_admin&.destroy\\n\\n        user&.destroy\\n\\n        respond_to do |format|\\n          format.json do\\n            render json: { status: \\\"successful\\\",\\n                           redirect: team_members_url(current_team.hashid) }\\n          end\\n        end\\n      end\\n\\n    elsif params[:action_type] == \\\"resend_invite_email\\\"\\n\\n      user = User.find_by_hashid(params[:id])\\n\\n      if user&.activated?\\n        redirect_to user_path(user.id)\\n      else\\n        user_activation_token = User.new_token\\n        user_activation_digest = User.digest(user_activation_token)\\n        user.update_attribute(:activation_digest, user_activation_digest)\\n\\n        print(\\\"Send activation mail: \\\", edit_account_activation_url(user_activation_token, email: user.email, team_id: current_team.hashid), \\\"\\\\n\\\")\\n\\n        respond_to do |format|\\n          format.json do\\n            render json: { status: \\\"successful\\\" }\\n          end\\n        end\\n      end\\n\\n    end\\n  end\\nend\\n\"}}}" #<process lsp-ruby TCP connection>)
  lsp--text-document-did-open()
  (let* ((root (file-truename (funcall (progn (or (and ... t) (signal ... ...)) (aref client 7))))) (workspace (gethash root lsp--workspaces)) new-conn response init-params parser proc cmd-proc) (if workspace (progn (setq lsp--cur-workspace workspace) (lsp-mode 1)) (progn (setq parser (record 'lsp--parser nil nil 'nil nil nil nil 0 nil nil nil nil)) (setq lsp--cur-workspace (make-lsp--workspace :parser parser :file-versions (make-hash-table :test 'equal) :root root :client client)) (progn (or (and (memq (type-of parser) cl-struct-lsp--parser-tags) t) (signal 'wrong-type-argument (list 'lsp--parser parser))) (let* ((v parser)) (aset v 11 lsp--cur-workspace))) (setq new-conn (funcall (progn (or (and ... t) (signal ... ...)) (aref client 5)) (lsp--parser-make-filter parser (progn (or ... ...) (aref client 8))) (lsp--make-sentinel lsp--cur-workspace))) (setq cmd-proc (if (consp new-conn) (car new-conn) new-conn)) (setq proc (if (consp new-conn) (cdr new-conn) new-conn)) (progn (or (and (memq (type-of lsp--cur-workspace) cl-struct-lsp--workspace-tags) t) (signal 'wrong-type-argument (list 'lsp--workspace lsp--cur-workspace))) (let* ((v lsp--cur-workspace)) (aset v 8 proc))) (progn (or (and (memq (type-of lsp--cur-workspace) cl-struct-lsp--workspace-tags) t) (signal 'wrong-type-argument (list 'lsp--workspace lsp--cur-workspace))) (let* ((v lsp--cur-workspace)) (aset v 9 cmd-proc)))) (puthash root lsp--cur-workspace lsp--workspaces) (lsp-mode 1) (run-hooks 'lsp-before-initialize-hook) (setq init-params (list ':processId (emacs-pid) ':rootPath root ':rootUri (concat lsp--uri-file-prefix (url-hexify-string (file-truename root) url-path-allowed-chars)) ':capabilities (lsp--client-capabilities) ':initializationOptions (if (functionp extra-init-params) (funcall extra-init-params lsp--cur-workspace) extra-init-params))) (setq response (lsp--send-request (plist-put (progn (progn (or ... ...) nil) (list :jsonrpc "2.0" :method "initialize" :params init-params)) :id (progn (or (and ... t) (signal ... ...)) (let* (...) (aset v 14 ...)))))) (if response nil (signal 'lsp-empty-response-error (list "initialize"))) (progn (or (and (memq (type-of lsp--cur-workspace) cl-struct-lsp--workspace-tags) t) (signal 'wrong-type-argument (list 'lsp--workspace lsp--cur-workspace))) (let* ((v lsp--cur-workspace)) (aset v 3 (gethash "capabilities" response)))) (lsp--send-no-wait (let* ((json-encoding-pretty-print lsp-print-io) (json-false :json-false) (body (json-encode (progn ... ...)))) (format "Content-Length: %d\15\n\15\n%s" (string-bytes body) body)) (progn (or (and (memq (type-of lsp--cur-workspace) cl-struct-lsp--workspace-tags) t) (signal 'wrong-type-argument (list 'lsp--workspace lsp--cur-workspace))) (aref lsp--cur-workspace 8))) (run-hooks 'lsp-after-initialize-hook)) (lsp--text-document-did-open))
  lsp--start(#s(lsp--client :language-id (closure ((stderr . "*lsp-ruby stderr*<2>") (prefix-function) (enable-function . lsp-ruby-enable) (initialize-fn . lsp-ruby--initialize-client) (extra-init-params) (ignore-messages) (ignore-regexps) (port . 7658) (host . "127.0.0.1") (command-fn) (command "solargraph" "socket") (root-directory-fn closure ((name closure (t) (dir) (directory-files dir nil "\\(Rakefile\\|Gemfile\\)")) lsp--no-response t) nil (let ((dir ...)) (if dir (file-truename dir) (if lsp-message-project-root-warning ... ... default-directory)))) (language-id-fn) (language-id . "ruby") (--cl-rest-- :language-id "ruby" :language-id-fn nil :root-directory-fn (closure ((name closure ... ... ...) lsp--no-response t) nil (let (...) (if dir ... ...))) :command ("solargraph" "socket") :command-fn nil :host "127.0.0.1" :port 7658 :ignore-regexps nil :ignore-messages nil :extra-init-params nil :initialize-fn lsp-ruby--initialize-client :enable-function lsp-ruby-enable :prefix-function nil) (name . lsp-ruby) t) (_) language-id) :send-sync nil :send-async nil :type nil :new-connection (closure ((stderr . "*lsp-ruby stderr*<2>") (port . 7658) (host . "127.0.0.1") (command-fn) (command "solargraph" "socket") (name . "lsp-ruby") t) (filter sentinel) (let* ((command (if command-fn (funcall command-fn) command)) (final-command (if (consp command) command (list command))) proc tcp-proc) (if (executable-find (nth 0 final-command)) nil (error (format "Couldn't find executable %s" (nth 0 final-command)))) (setq proc (make-process :name name :connection-type 'pipe :coding 'no-conversion :command final-command :sentinel sentinel :stderr stderr :noquery t) tcp-proc (open-network-stream (concat name " TCP connection") nil host port :type 'plain)) (set-process-query-on-exit-flag (get-buffer-process (get-buffer stderr)) nil) (set-process-query-on-exit-flag tcp-proc nil) (set-process-filter tcp-proc filter) (cons proc tcp-proc))) :stderr "*lsp-ruby stderr*<2>" :get-root (closure ((name closure (t) (dir) (directory-files dir nil "\\(Rakefile\\|Gemfile\\)")) lsp--no-response t) nil (let ((dir (locate-dominating-file "." name))) (if dir (file-truename dir) (if lsp-message-project-root-warning (message "Couldn't find project root, using the current directory as the root.") (lsp-warn "Couldn't find project root, using the current directory as the root.") default-directory)))) :ignore-regexps nil :ignore-messages nil :notification-handlers #<hash-table equal 0/65 0x40d79a69> :request-handlers #<hash-table equal 0/65 0x40d79b91> :response-handlers #<hash-table eql 0/65 0x5c75e545> :string-renderers (("ruby" . lsp-ruby--render-string)) :last-id 0 :enable-function lsp-ruby-enable :prefix-function nil :uri-handlers #<hash-table equal 0/65 0x5c75e87d> :action-handlers #<hash-table equal 0/65 0x5c010cb9> :default-renderer nil) nil)
  (if (lsp--should-start-p root) (lsp--start client extra-init-params) (message "Not initializing project %s" root))
  (let ((root (funcall (progn (or (and (memq ... cl-struct-lsp--client-tags) t) (signal 'wrong-type-argument (list ... client))) (aref client 7))))) (if (lsp--should-start-p root) (lsp--start client extra-init-params) (message "Not initializing project %s" root)))
  (let* ((stderr (generate-new-buffer-name (concat "*" (symbol-name name) " stderr*"))) (client (make-lsp--client :language-id (or language-id-fn #'(lambda (_) language-id)) :new-connection (lsp--make-tcp-connection (symbol-name name) command command-fn host port stderr) :stderr stderr :get-root root-directory-fn :ignore-regexps ignore-regexps :ignore-messages ignore-messages :enable-function enable-function :prefix-function prefix-function))) (if initialize-fn (progn (funcall initialize-fn client))) (let ((root (funcall (progn (or (and ... t) (signal ... ...)) (aref client 7))))) (if (lsp--should-start-p root) (lsp--start client extra-init-params) (message "Not initializing project %s" root))))
  (progn (let* ((stderr (generate-new-buffer-name (concat "*" (symbol-name name) " stderr*"))) (client (make-lsp--client :language-id (or language-id-fn #'(lambda ... language-id)) :new-connection (lsp--make-tcp-connection (symbol-name name) command command-fn host port stderr) :stderr stderr :get-root root-directory-fn :ignore-regexps ignore-regexps :ignore-messages ignore-messages :enable-function enable-function :prefix-function prefix-function))) (if initialize-fn (progn (funcall initialize-fn client))) (let ((root (funcall (progn (or ... ...) (aref client 7))))) (if (lsp--should-start-p root) (lsp--start client extra-init-params) (message "Not initializing project %s" root)))))
  (if (and (not lsp-mode) (buffer-file-name)) (progn (let* ((stderr (generate-new-buffer-name (concat "*" (symbol-name name) " stderr*"))) (client (make-lsp--client :language-id (or language-id-fn #'...) :new-connection (lsp--make-tcp-connection (symbol-name name) command command-fn host port stderr) :stderr stderr :get-root root-directory-fn :ignore-regexps ignore-regexps :ignore-messages ignore-messages :enable-function enable-function :prefix-function prefix-function))) (if initialize-fn (progn (funcall initialize-fn client))) (let ((root (funcall (progn ... ...)))) (if (lsp--should-start-p root) (lsp--start client extra-init-params) (message "Not initializing project %s" root))))))
  (progn (progn (or (symbolp name) (signal 'wrong-type-argument (list 'symbol name 'name))) nil) (progn (or (or (null language-id) (stringp language-id)) (signal 'wrong-type-argument (list '(or null string) language-id 'language-id))) nil) (progn (or (or (null language-id-fn) (functionp language-id-fn)) (signal 'wrong-type-argument (list '(or null function) language-id-fn 'language-id-fn))) nil) (progn (or (or (null root-directory-fn) (functionp root-directory-fn)) (signal 'wrong-type-argument (list '(or null function) root-directory-fn 'root-directory-fn))) nil) (progn (or (listp command) (signal 'wrong-type-argument (list 'list command 'command))) nil) (progn (or (or (null command-fn) (functionp command-fn)) (signal 'wrong-type-argument (list '(or null function) command-fn 'command-fn))) nil) (progn (or (stringp host) (signal 'wrong-type-argument (list 'string host 'host))) nil) (progn (or (and (integerp port) (>= port '1) (<= port '65535)) (signal 'wrong-type-argument (list '(integer 1 65535) port 'port))) nil) (progn (or (listp ignore-regexps) (signal 'wrong-type-argument (list 'list ignore-regexps 'ignore-regexps))) nil) (progn (or (listp ignore-messages) (signal 'wrong-type-argument (list 'list ignore-messages 'ignore-messages))) nil) (progn (or (or (listp extra-init-params) (functionp extra-init-params)) (signal 'wrong-type-argument (list '(or list function) extra-init-params 'extra-init-params))) nil) (progn (or (or (null initialize-fn) (functionp initialize-fn)) (signal 'wrong-type-argument (list '(or null function) initialize-fn 'initialize-fn))) nil) (progn (or (or (null prefix-function) (functionp prefix-function)) (signal 'wrong-type-argument (list '(or null function) prefix-function 'prefix-function))) nil) (if (and (not lsp-mode) (buffer-file-name)) (progn (let* ((stderr (generate-new-buffer-name (concat "*" ... " stderr*"))) (client (make-lsp--client :language-id (or language-id-fn ...) :new-connection (lsp--make-tcp-connection ... command command-fn host port stderr) :stderr stderr :get-root root-directory-fn :ignore-regexps ignore-regexps :ignore-messages ignore-messages :enable-function enable-function :prefix-function prefix-function))) (if initialize-fn (progn (funcall initialize-fn client))) (let ((root (funcall ...))) (if (lsp--should-start-p root) (lsp--start client extra-init-params) (message "Not initializing project %s" root)))))))
  (progn (let ((--cl-keys-- --cl-rest--)) (while --cl-keys-- (cond ((memq (car --cl-keys--) '(:language-id :language-id-fn :root-directory-fn :command :command-fn :host :port :ignore-regexps :ignore-messages :extra-init-params :initialize-fn :enable-function :prefix-function :allow-other-keys)) (setq --cl-keys-- (cdr (cdr --cl-keys--)))) ((car (cdr (memq ... --cl-rest--))) (setq --cl-keys-- nil)) (t (error "Keyword argument %s not one of (:language-id :language-id-fn :root-directory-fn :command :command-fn :host :port :ignore-regexps :ignore-messages :extra-init-params :initialize-fn :enable-function :prefix-function)" (car --cl-keys--)))))) (progn (progn (or (symbolp name) (signal 'wrong-type-argument (list 'symbol name 'name))) nil) (progn (or (or (null language-id) (stringp language-id)) (signal 'wrong-type-argument (list '(or null string) language-id 'language-id))) nil) (progn (or (or (null language-id-fn) (functionp language-id-fn)) (signal 'wrong-type-argument (list '(or null function) language-id-fn 'language-id-fn))) nil) (progn (or (or (null root-directory-fn) (functionp root-directory-fn)) (signal 'wrong-type-argument (list '(or null function) root-directory-fn 'root-directory-fn))) nil) (progn (or (listp command) (signal 'wrong-type-argument (list 'list command 'command))) nil) (progn (or (or (null command-fn) (functionp command-fn)) (signal 'wrong-type-argument (list '(or null function) command-fn 'command-fn))) nil) (progn (or (stringp host) (signal 'wrong-type-argument (list 'string host 'host))) nil) (progn (or (and (integerp port) (>= port '1) (<= port '65535)) (signal 'wrong-type-argument (list '(integer 1 65535) port 'port))) nil) (progn (or (listp ignore-regexps) (signal 'wrong-type-argument (list 'list ignore-regexps 'ignore-regexps))) nil) (progn (or (listp ignore-messages) (signal 'wrong-type-argument (list 'list ignore-messages 'ignore-messages))) nil) (progn (or (or (listp extra-init-params) (functionp extra-init-params)) (signal 'wrong-type-argument (list '(or list function) extra-init-params 'extra-init-params))) nil) (progn (or (or (null initialize-fn) (functionp initialize-fn)) (signal 'wrong-type-argument (list '(or null function) initialize-fn 'initialize-fn))) nil) (progn (or (or (null prefix-function) (functionp prefix-function)) (signal 'wrong-type-argument (list '(or null function) prefix-function 'prefix-function))) nil) (if (and (not lsp-mode) (buffer-file-name)) (progn (let* ((stderr (generate-new-buffer-name ...)) (client (make-lsp--client :language-id ... :new-connection ... :stderr stderr :get-root root-directory-fn :ignore-regexps ignore-regexps :ignore-messages ignore-messages :enable-function enable-function :prefix-function prefix-function))) (if initialize-fn (progn (funcall initialize-fn client))) (let ((root ...)) (if (lsp--should-start-p root) (lsp--start client extra-init-params) (message "Not initializing project %s" root))))))))
  (let* ((language-id (car (cdr (plist-member --cl-rest-- ':language-id)))) (language-id-fn (car (cdr (plist-member --cl-rest-- ':language-id-fn)))) (root-directory-fn (car (cdr (plist-member --cl-rest-- ':root-directory-fn)))) (command (car (cdr (plist-member --cl-rest-- ':command)))) (command-fn (car (cdr (plist-member --cl-rest-- ':command-fn)))) (host (car (cdr (plist-member --cl-rest-- ':host)))) (port (car (cdr (plist-member --cl-rest-- ':port)))) (ignore-regexps (car (cdr (plist-member --cl-rest-- ':ignore-regexps)))) (ignore-messages (car (cdr (plist-member --cl-rest-- ':ignore-messages)))) (extra-init-params (car (cdr (plist-member --cl-rest-- ':extra-init-params)))) (initialize-fn (car (cdr (plist-member --cl-rest-- ':initialize-fn)))) (enable-function (car (cdr (plist-member --cl-rest-- ':enable-function)))) (prefix-function (car (cdr (plist-member --cl-rest-- ':prefix-function))))) (progn (let ((--cl-keys-- --cl-rest--)) (while --cl-keys-- (cond ((memq (car --cl-keys--) '...) (setq --cl-keys-- (cdr ...))) ((car (cdr ...)) (setq --cl-keys-- nil)) (t (error "Keyword argument %s not one of (:language-id :language-id-fn :root-directory-fn :command :command-fn :host :port :ignore-regexps :ignore-messages :extra-init-params :initialize-fn :enable-function :prefix-function)" (car --cl-keys--)))))) (progn (progn (or (symbolp name) (signal 'wrong-type-argument (list 'symbol name 'name))) nil) (progn (or (or (null language-id) (stringp language-id)) (signal 'wrong-type-argument (list '... language-id 'language-id))) nil) (progn (or (or (null language-id-fn) (functionp language-id-fn)) (signal 'wrong-type-argument (list '... language-id-fn 'language-id-fn))) nil) (progn (or (or (null root-directory-fn) (functionp root-directory-fn)) (signal 'wrong-type-argument (list '... root-directory-fn 'root-directory-fn))) nil) (progn (or (listp command) (signal 'wrong-type-argument (list 'list command 'command))) nil) (progn (or (or (null command-fn) (functionp command-fn)) (signal 'wrong-type-argument (list '... command-fn 'command-fn))) nil) (progn (or (stringp host) (signal 'wrong-type-argument (list 'string host 'host))) nil) (progn (or (and (integerp port) (>= port '1) (<= port '65535)) (signal 'wrong-type-argument (list '... port 'port))) nil) (progn (or (listp ignore-regexps) (signal 'wrong-type-argument (list 'list ignore-regexps 'ignore-regexps))) nil) (progn (or (listp ignore-messages) (signal 'wrong-type-argument (list 'list ignore-messages 'ignore-messages))) nil) (progn (or (or (listp extra-init-params) (functionp extra-init-params)) (signal 'wrong-type-argument (list '... extra-init-params 'extra-init-params))) nil) (progn (or (or (null initialize-fn) (functionp initialize-fn)) (signal 'wrong-type-argument (list '... initialize-fn 'initialize-fn))) nil) (progn (or (or (null prefix-function) (functionp prefix-function)) (signal 'wrong-type-argument (list '... prefix-function 'prefix-function))) nil) (if (and (not lsp-mode) (buffer-file-name)) (progn (let* ((stderr ...) (client ...)) (if initialize-fn (progn ...)) (let (...) (if ... ... ...))))))))
  lsp--enable-tcp-client(lsp-ruby :language-id "ruby" :language-id-fn nil :root-directory-fn (closure ((name closure (t) (dir) (directory-files dir nil "\\(Rakefile\\|Gemfile\\)")) lsp--no-response t) nil (let ((dir (locate-dominating-file "." name))) (if dir (file-truename dir) (if lsp-message-project-root-warning (message "Couldn't find project root, using the current directory as the root.") (lsp-warn "Couldn't find project root, using the current directory as the root.") default-directory)))) :command ("solargraph" "socket") :command-fn nil :host "127.0.0.1" :port 7658 :ignore-regexps nil :ignore-messages nil :extra-init-params nil :initialize-fn lsp-ruby--initialize-client :enable-function lsp-ruby-enable :prefix-function nil)
  lsp-ruby-enable()
  run-hooks(change-major-mode-after-body-hook prog-mode-hook ruby-mode-hook)
  apply(run-hooks (change-major-mode-after-body-hook prog-mode-hook ruby-mode-hook))
  run-mode-hooks(ruby-mode-hook)
  ruby-mode()

LSP 针对 kill buffer 有没有保护措施或者 restart 措施?

看着错误像 kill-buffer 导致 lsp-ruby 的 process 被 killed, 再次打开 ruby buffer 的时候, 触发了lsp–send-no-wait 里面的进程检查错误.

还在研究中, 欢迎玩 lsp-mode 比较溜的同学指导下. :wink:

有一個lsp-restart-workspace,但可能解決不了你的問題。

language server異常退出導致整個workspace大量報錯是一直以來的問題……需要你去修復~

我发现 lsp-restart-workspace 可以临时解决, 但是每次都要执行一次好麻烦.

我估计还是 lsp-ruby 的代码写的有点问题, 我看了一下 eglot 的代码, lsp-ruby 应该用动态端口, 而不是死的端口.

还没有细看

lsp-mode 可以像 eglot 那样支持 autoport 参数吗? 如果支持, 应该可以快速修复好.

不知道&……沒研究過eglot lsp-ruby

eglot 的 ruby 没有问题, 但是总是会在下方弹出 server 的 document.

lsp-mode 可以很好的和 python, javascript 等其他模式工作.

eglot 在动态端口和自动重连做的比 lsp-mode 好太多 (lsp-mode 只要服务器已断开就只会报错), 而且可以很好的和 ruby-mode 一起工作.

但是 eglot 默认的设置非常烦人, 只要 hover string 的时候, eglot 就会在 minibuffer 显示帮助文档, 导致 minibuffer 一直弹来弹去, 眼睛快瞎了. ~~一直在看 eglot 的代码, 找了所有的 message 代码都不对, 终于找到是 :textDocument/hover 在控制, 所以写了一个补丁默认禁用 eglot 在minibuffer 显示帮助函数: https://github.com/joaotavora/eglot/pull/105~~ 经过 eglot 作者提醒, 用了下面的选项禁用之:

(setq eglot-ignored-server-capabilites '(:hoverProvider))

lsp-mode 的参考配置: https://github.com/manateelazycat/lazycat-emacs/blob/master/site-lisp/config/init-lsp.el

html/css 不能工作, 所以注释掉了.

eglot 的代码质量比 lsp-mode 好很多, 等 https://github.com/joaotavora/eglot/issues/106 这个bug修复后, 我就从 lsp-mode 切换到 eglot

1 个赞

发现是 pyls 的bug, 手动在本地打上这个 patch : Properties completion · Issue #373 · palantir/python-language-server · GitHub eglot 就好了.

除了 JavaScript 还是用 lsp-mode 以外, 其他都转移到 eglot 上了, eglot 超级稳定, 不会像 lsp-mode 容易崩溃

2 个赞