lsp-mode新接口lsp.el

自己写个私有层

之前写过个lsp的…… 这一升级就lsp-*-enable都没了, 所以不太愿意写了= =!

解决方案只是一条替换语句, 但是找到失效的原因, 或者说找到这个页面却google了不少时间.

You need to check every commit until you find the change about the function

thx, I have never used it, and I’ll have a try.

btw, why you speak English on emacs-china site?

你应该搞个签名解释,不然每个人都会问一次

现在的 lsp.el 如何判断项目根目录?

以前是这样:

(defconst lsp-javascript-typescript--get-root
  (lsp-make-traverser #'(lambda (dir)
                          (directory-files dir nil "package.json"))))
                                                    ^^^^^^^^^^^^^

https://github.com/emacs-lsp/lsp-mode/blob/master/lsp-clients.el 中没看到有类似的操作。

现在的 lsp.el 如何判断项目根目录?

修改了一樓。

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

btw, why you speak English on emacs- china site?

I think the name only suggests that Chinese is the mainstream language in the forum. Other languages are not precluded.

(c-c++ :variables c-c+±adopt-subprojects t c-c+±default-mode-for-headers 'c+±mode c-c+±backend 'lsp-ccls c-c+±enable-clang-support t)

Some forwarding variables are not very necessary.

https://github.com/emacs-lsp/lsp-mode/issues/542 [Poll] lsp-mode - minimal or batteries included

Please share your opinions

2 个赞

果然是有竞争,才会进步。如果没有eglot,lspmode的作者怕是不会这么快积极更新了。

並不是作者變得積極更新,而是維護者發生了變更。

我希望lsp-mode用plist代替hash table (gethash等)

有個問題,如何disable flymake-cc?

flymake默认是关闭的呀,你看看是谁开启的

这算lsp开启的,我是说flymake不会自己启动,这个意思。

(define-derived-mode c-mode prog-mode "C"
...
  (add-hook 'flymake-diagnostic-functions 'flymake-cc nil t)
  (c-run-mode-hooks 'c-mode-common-hook))

flymake啓動是想要的,但不想要flymake-cc

暫時在mode-hook裏加

(setq flymake-diagnostic-functions (list 'lsp--flymake-backend))))
1 个赞

举个例子, 一进入 python 就报错:

Debugger entered--Lisp error: (void-variable severity)
  (let ((range (list :start (list :line start-line :column start-character) :end (list :line end-line :column end-character))) (line start-line) (column start-character) (severity severity) (code code) (source source) (message (if source (format "%s: %s" source message) message)) (original diag)) (record 'lsp-diagnostic range line column severity code source message original))
  (let* ((--dash-source-2-- (gethash "range" diag)) (--dash-source-3-- (gethash "start" --dash-source-2--)) (start-line (gethash "line" --dash-source-3--)) (start-character (gethash "character" --dash-source-3--)) (--dash-source-4-- (gethash "end" --dash-source-2--)) (end-line (gethash "line" --dash-source-4--)) (end-character (gethash "character" --dash-source-4--))) (let ((range (list :start (list :line start-line :column start-character) :end (list :line end-line :column end-character))) (line start-line) (column start-character) (severity severity) (code code) (source source) (message (if source (format "%s: %s" source message) message)) (original diag)) (record 'lsp-diagnostic range line column severity code source message original)))
  lsp--make-diag(#<hash-table equal 4/65 0x5bb1e9c9>)
  mapcar(lsp--make-diag (#<hash-table equal 4/65 0x5bb1e9c9> #<hash-table equal 5/65 0x40c6e5c1> #<hash-table equal 5/65 0x40635441> #<hash-table equal 5/65 0x5cca55c1> #<hash-table equal 5/65 0x5adfd301> #<hash-table equal 5/65 0x5adfd69d> #<hash-table equal 5/65 0x5cca9041> #<hash-table equal 5/65 0x5ccb11fd> #<hash-table equal 5/65 0x5ccb125d> #<hash-table equal 5/65 0x5ccbf401> #<hash-table equal 5/65 0x5ccbf441> #<hash-table equal 5/65 0x5ccc157d> #<hash-table equal 5/65 0x5ccc15dd> #<hash-table equal 5/65 0x5ccc3fad> #<hash-table equal 5/65 0x5ccc4a41> #<hash-table equal 5/65 0x5ccc5641> #<hash-table equal 5/65 0x5ccc6241> #<hash-table equal 5/65 0x5ccc7681> #<hash-table equal 5/65 0x5ccc7a1d> #<hash-table equal 5/65 0x5ccc8641> #<hash-table equal 5/65 0x5ccc95fd> #<hash-table equal 5/65 0x5ccc965d> #<hash-table equal 5/65 0x5cccae01> #<hash-table equal 5/65 0x5cccae41> #<hash-table equal 5/65 0x5cccc5fd> #<hash-table equal 5/65 0x5cccc65d> #<hash-table equal 5/65 0x5cccdfad> #<hash-table equal 5/65 0x5cccea41> #<hash-table equal 5/65 0x5cccf641> #<hash-table equal 5/65 0x5ccd0241>))
  (puthash file (mapcar #'lsp--make-diag diagnostics) workspace-diagnostics)
  (progn (puthash file (mapcar #'lsp--make-diag diagnostics) workspace-diagnostics))
  (if (or lsp-report-if-no-buffer buffer) (progn (puthash file (mapcar #'lsp--make-diag diagnostics) workspace-diagnostics)))
  (if diagnostics (if (or lsp-report-if-no-buffer buffer) (progn (puthash file (mapcar #'lsp--make-diag diagnostics) workspace-diagnostics))) (remhash file workspace-diagnostics))
  (let* ((file (lsp--uri-to-path (gethash "uri" params))) (diagnostics (gethash "diagnostics" params)) (buffer (find-buffer-visiting file)) (workspace-diagnostics (lsp--workspace-diagnostics workspace))) (if diagnostics (if (or lsp-report-if-no-buffer buffer) (progn (puthash file (mapcar #'lsp--make-diag diagnostics) workspace-diagnostics))) (remhash file workspace-diagnostics)) (if buffer (progn (save-current-buffer (set-buffer buffer) (run-hooks 'lsp-after-diagnostics-hook)))))
  lsp--on-diagnostics(#s(lsp--workspace :parser #s(lsp--parser :waiting-for-response nil :response-result nil :headers nil :body nil :reading-body nil :body-length nil :body-received nil :leftovers "" :queued-notifications nil :queued-requests nil :workspace #1) :file-versions #<hash-table equal 1/65 0x5cafe545> :server-capabilities #<hash-table equal 15/65 0x5ca9fdd9> :registered-server-capabilities nil :root "~/emacs-application-framework/" :client #s(lsp--client :language-id nil :add-on? nil :DEPRECATED_send-async nil :DEPRECATED_type nil :new-connection (:connect (closure ((command . "pyls") cl-struct-lsp-session-tags cl-struct-lsp--workspace-tags cl-struct-lsp--registered-capability-tags cl-struct-lsp-diagnostic-tags cl-struct-lsp--client-tags cl-struct-lsp--parser-tags t) (filter sentinel name) (let ((final-command ...) (process-name ...)) (if (lsp-server-present\? final-command) nil (error ...)) (let (...) (set-process-query-on-exit-flag proc nil) (cons proc proc)))) :test\? (closure ((command . "pyls") cl-struct-lsp-session-tags cl-struct-lsp--workspace-tags cl-struct-lsp--registered-capability-tags cl-struct-lsp-diagnostic-tags cl-struct-lsp--client-tags cl-struct-lsp--parser-tags t) nil (lsp-server-present\? (lsp-resolve-final-function command)))) :DEPRECATED_stderr nil :DEPRECATED_get-root nil :ignore-regexps nil :ignore-messages nil :notification-handlers #<hash-table equal 0/65 0x40c44435> :request-handlers #<hash-table equal 0/65 0x40c44455> :response-handlers #<hash-table eql 0/65 0x40c4d041> :string-renderers nil :DEPRECATED_last-id 0 :DEPRECATED_enable-function nil :prefix-function nil :uri-handlers #<hash-table equal 0/65 0x40c4d441> :action-handlers #<hash-table equal 0/65 0x40c4e7e1> :DEPRECATED_default-renderer nil :use-native-json nil :major-modes (python-mode) :priority -1 :server-id pyls :multi-root nil :initialization-options nil :library-folders-fn (closure (t) (_workspace) lsp-clients-python-library-directories) :before-file-open-fn nil :initialized-fn nil) :change-timer-disabled nil :proc #<process pyls> :cmd-proc #<process pyls> :buffers (#<buffer eaf.py>) :highlight-overlays #<hash-table eq 0/65 0x5cafe565> :extra-client-capabilities nil :status initialized :metadata #<hash-table equal 0/65 0x5cafe585> :watches #<hash-table equal 0/65 0x4054f08d> :workspace-folders nil :last-id 0 :status-string nil :shutdown-action nil :diagnostics #<hash-table equal 0/65 0x5bb2053d>) #<hash-table equal 2/65 0x5bb1e9a9>)
  funcall(lsp--on-diagnostics #s(lsp--workspace :parser #s(lsp--parser :waiting-for-response nil :response-result nil :headers nil :body nil :reading-body nil :body-length nil :body-received nil :leftovers "" :queued-notifications nil :queued-requests nil :workspace #2) :file-versions #<hash-table equal 1/65 0x5cafe545> :server-capabilities #<hash-table equal 15/65 0x5ca9fdd9> :registered-server-capabilities nil :root "~/emacs-application-framework/" :client #s(lsp--client :language-id nil :add-on? nil :DEPRECATED_send-async nil :DEPRECATED_type nil :new-connection (:connect (closure ((command . "pyls") cl-struct-lsp-session-tags cl-struct-lsp--workspace-tags cl-struct-lsp--registered-capability-tags cl-struct-lsp-diagnostic-tags cl-struct-lsp--client-tags cl-struct-lsp--parser-tags t) (filter sentinel name) (let ((final-command ...) (process-name ...)) (if (lsp-server-present\? final-command) nil (error ...)) (let (...) (set-process-query-on-exit-flag proc nil) (cons proc proc)))) :test\? (closure ((command . "pyls") cl-struct-lsp-session-tags cl-struct-lsp--workspace-tags cl-struct-lsp--registered-capability-tags cl-struct-lsp-diagnostic-tags cl-struct-lsp--client-tags cl-struct-lsp--parser-tags t) nil (lsp-server-present\? (lsp-resolve-final-function command)))) :DEPRECATED_stderr nil :DEPRECATED_get-root nil :ignore-regexps nil :ignore-messages nil :notification-handlers #<hash-table equal 0/65 0x40c44435> :request-handlers #<hash-table equal 0/65 0x40c44455> :response-handlers #<hash-table eql 0/65 0x40c4d041> :string-renderers nil :DEPRECATED_last-id 0 :DEPRECATED_enable-function nil :prefix-function nil :uri-handlers #<hash-table equal 0/65 0x40c4d441> :action-handlers #<hash-table equal 0/65 0x40c4e7e1> :DEPRECATED_default-renderer nil :use-native-json nil :major-modes (python-mode) :priority -1 :server-id pyls :multi-root nil :initialization-options nil :library-folders-fn (closure (t) (_workspace) lsp-clients-python-library-directories) :before-file-open-fn nil :initialized-fn nil) :change-timer-disabled nil :proc #<process pyls> :cmd-proc #<process pyls> :buffers (#<buffer eaf.py>) :highlight-overlays #<hash-table eq 0/65 0x5cafe565> :extra-client-capabilities nil :status initialized :metadata #<hash-table equal 0/65 0x5cafe585> :watches #<hash-table equal 0/65 0x4054f08d> :workspace-folders nil :last-id 0 :status-string nil :shutdown-action nil :diagnostics #<hash-table equal 0/65 0x5bb2053d>) #<hash-table equal 2/65 0x5bb1e9a9>)
  (if handler (funcall handler (progn (or (and (memq (type-of p) cl-struct-lsp--parser-tags) t) (signal 'wrong-type-argument (list 'lsp--parser p))) (aref p 11)) params) (if (string-prefix-p "$" method) nil (lsp-warn "Unknown method: %s" method)))
  (let* ((params (gethash "params" notification)) (client (progn (or (and (memq (type-of ...) cl-struct-lsp--workspace-tags) t) (signal 'wrong-type-argument (list 'lsp--workspace (progn ... ...)))) (aref (progn (or (and ... t) (signal ... ...)) (aref p 11)) 6))) (method (gethash "method" notification)) (handler (gethash method (progn (or (and (memq ... cl-struct-lsp--client-tags) t) (signal 'wrong-type-argument (list ... client))) (aref client 10)) (gethash method lsp--default-notification-handlers)))) (if handler (funcall handler (progn (or (and (memq (type-of p) cl-struct-lsp--parser-tags) t) (signal 'wrong-type-argument (list 'lsp--parser p))) (aref p 11)) params) (if (string-prefix-p "$" method) nil (lsp-warn "Unknown method: %s" method))))
  lsp--on-notification(#s(lsp--parser :waiting-for-response nil :response-result nil :headers nil :body nil :reading-body nil :body-length nil :body-received nil :leftovers "" :queued-notifications nil :queued-requests nil :workspace #s(lsp--workspace :parser #1 :file-versions #<hash-table equal 1/65 0x5cafe545> :server-capabilities #<hash-table equal 15/65 0x5ca9fdd9> :registered-server-capabilities nil :root "~/emacs-application-framework/" :client #s(lsp--client :language-id nil :add-on? nil :DEPRECATED_send-async nil :DEPRECATED_type nil :new-connection (:connect (closure ((command . "pyls") cl-struct-lsp-session-tags cl-struct-lsp--workspace-tags cl-struct-lsp--registered-capability-tags cl-struct-lsp-diagnostic-tags cl-struct-lsp--client-tags cl-struct-lsp--parser-tags t) (filter sentinel name) (let (... ...) (if ... nil ...) (let ... ... ...))) :test\? (closure ((command . "pyls") cl-struct-lsp-session-tags cl-struct-lsp--workspace-tags cl-struct-lsp--registered-capability-tags cl-struct-lsp-diagnostic-tags cl-struct-lsp--client-tags cl-struct-lsp--parser-tags t) nil (lsp-server-present\? (lsp-resolve-final-function command)))) :DEPRECATED_stderr nil :DEPRECATED_get-root nil :ignore-regexps nil :ignore-messages nil :notification-handlers #<hash-table equal 0/65 0x40c44435> :request-handlers #<hash-table equal 0/65 0x40c44455> :response-handlers #<hash-table eql 0/65 0x40c4d041> :string-renderers nil :DEPRECATED_last-id 0 :DEPRECATED_enable-function nil :prefix-function nil :uri-handlers #<hash-table equal 0/65 0x40c4d441> :action-handlers #<hash-table equal 0/65 0x40c4e7e1> :DEPRECATED_default-renderer nil :use-native-json nil :major-modes (python-mode) :priority -1 :server-id pyls :multi-root nil :initialization-options nil :library-folders-fn (closure (t) (_workspace) lsp-clients-python-library-directories) :before-file-open-fn nil :initialized-fn nil) :change-timer-disabled nil :proc #<process pyls> :cmd-proc #<process pyls> :buffers (#<buffer eaf.py>) :highlight-overlays #<hash-table eq 0/65 0x5cafe565> :extra-client-capabilities nil :status initialized :metadata #<hash-table equal 0/65 0x5cafe585> :watches #<hash-table equal 0/65 0x4054f08d> :workspace-folders nil :last-id 0 :status-string nil :shutdown-action nil :diagnostics #<hash-table equal 0/65 0x5bb2053d>)) #<hash-table equal 3/65 0x5bb1e905>)
  (cond ((eq val 'response) (progn (or id (cl--assertion-failed 'id)) nil) (let* ((callback (and t (gethash (if ... ... id) (progn ... ...) nil)))) (if callback (progn (funcall callback (gethash "result" json-data nil)) (remhash id (progn (or ... ...) (aref client 12)))) (progn (progn (or (and ... t) (signal ... ...)) (let* (...) (aset v 2 ...))) (progn (or (and ... t) (signal ... ...)) (let* (...) (aset v 1 nil))))))) ((eq val 'response-error) (let* ((err (gethash "error" json-data nil)) (code (gethash "code" err nil))) (if (and json-data (not (memq code lsp--silent-errors))) (progn (message (lsp--error-string err))))) (progn (progn (or (and (memq (type-of p) cl-struct-lsp--parser-tags) t) (signal 'wrong-type-argument (list 'lsp--parser p))) (let* ((v p)) (aset v 2 nil))) (progn (or (and (memq (type-of p) cl-struct-lsp--parser-tags) t) (signal 'wrong-type-argument (list 'lsp--parser p))) (let* ((v p)) (aset v 1 nil))))) ((eq val 'notification) (lsp--on-notification p json-data)) ((eq val 'request) (lsp--on-request p json-data)) (t nil))
  (let* ((val (lsp--get-message-type json-data))) (cond ((eq val 'response) (progn (or id (cl--assertion-failed 'id)) nil) (let* ((callback (and t (gethash ... ... nil)))) (if callback (progn (funcall callback (gethash "result" json-data nil)) (remhash id (progn ... ...))) (progn (progn (or ... ...) (let* ... ...)) (progn (or ... ...) (let* ... ...)))))) ((eq val 'response-error) (let* ((err (gethash "error" json-data nil)) (code (gethash "code" err nil))) (if (and json-data (not (memq code lsp--silent-errors))) (progn (message (lsp--error-string err))))) (progn (progn (or (and (memq ... cl-struct-lsp--parser-tags) t) (signal 'wrong-type-argument (list ... p))) (let* ((v p)) (aset v 2 nil))) (progn (or (and (memq ... cl-struct-lsp--parser-tags) t) (signal 'wrong-type-argument (list ... p))) (let* ((v p)) (aset v 1 nil))))) ((eq val 'notification) (lsp--on-notification p json-data)) ((eq val 'request) (lsp--on-request p json-data)) (t nil)))
  (let* ((lsp--cur-workspace (progn (or (and (memq (type-of p) cl-struct-lsp--parser-tags) t) (signal 'wrong-type-argument (list 'lsp--parser p))) (aref p 11))) (client (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 6))) (json-data (lsp--read-json msg (progn (or (and (memq ... cl-struct-lsp--client-tags) t) (signal 'wrong-type-argument (list ... client))) (aref client 20)))) (id (gethash "id" json-data nil))) (let* ((val (lsp--get-message-type json-data))) (cond ((eq val 'response) (progn (or id (cl--assertion-failed 'id)) nil) (let* ((callback (and t ...))) (if callback (progn (funcall callback ...) (remhash id ...)) (progn (progn ... ...) (progn ... ...))))) ((eq val 'response-error) (let* ((err (gethash "error" json-data nil)) (code (gethash "code" err nil))) (if (and json-data (not ...)) (progn (message ...)))) (progn (progn (or (and ... t) (signal ... ...)) (let* (...) (aset v 2 nil))) (progn (or (and ... t) (signal ... ...)) (let* (...) (aset v 1 nil))))) ((eq val 'notification) (lsp--on-notification p json-data)) ((eq val 'request) (lsp--on-request p json-data)) (t nil))))
  lsp--parser-on-message(#s(lsp--parser :waiting-for-response nil :response-result nil :headers nil :body nil :reading-body nil :body-length nil :body-received nil :leftovers "" :queued-notifications nil :queued-requests nil :workspace #s(lsp--workspace :parser #1 :file-versions #<hash-table equal 1/65 0x5cafe545> :server-capabilities #<hash-table equal 15/65 0x5ca9fdd9> :registered-server-capabilities nil :root "~/emacs-application-framework/" :client #s(lsp--client :language-id nil :add-on? nil :DEPRECATED_send-async nil :DEPRECATED_type nil :new-connection (:connect (closure ((command . "pyls") cl-struct-lsp-session-tags cl-struct-lsp--workspace-tags cl-struct-lsp--registered-capability-tags cl-struct-lsp-diagnostic-tags cl-struct-lsp--client-tags cl-struct-lsp--parser-tags t) (filter sentinel name) (let (... ...) (if ... nil ...) (let ... ... ...))) :test\? (closure ((command . "pyls") cl-struct-lsp-session-tags cl-struct-lsp--workspace-tags cl-struct-lsp--registered-capability-tags cl-struct-lsp-diagnostic-tags cl-struct-lsp--client-tags cl-struct-lsp--parser-tags t) nil (lsp-server-present\? (lsp-resolve-final-function command)))) :DEPRECATED_stderr nil :DEPRECATED_get-root nil :ignore-regexps nil :ignore-messages nil :notification-handlers #<hash-table equal 0/65 0x40c44435> :request-handlers #<hash-table equal 0/65 0x40c44455> :response-handlers #<hash-table eql 0/65 0x40c4d041> :string-renderers nil :DEPRECATED_last-id 0 :DEPRECATED_enable-function nil :prefix-function nil :uri-handlers #<hash-table equal 0/65 0x40c4d441> :action-handlers #<hash-table equal 0/65 0x40c4e7e1> :DEPRECATED_default-renderer nil :use-native-json nil :major-modes (python-mode) :priority -1 :server-id pyls :multi-root nil :initialization-options nil :library-folders-fn (closure (t) (_workspace) lsp-clients-python-library-directories) :before-file-open-fn nil :initialized-fn nil) :change-timer-disabled nil :proc #<process pyls> :cmd-proc #<process pyls> :buffers (#<buffer eaf.py>) :highlight-overlays #<hash-table eq 0/65 0x5cafe565> :extra-client-capabilities nil :status initialized :metadata #<hash-table equal 0/65 0x5cafe585> :watches #<hash-table equal 0/65 0x4054f08d> :workspace-folders nil :last-id 0 :status-string nil :shutdown-action nil :diagnostics #<hash-table equal 0/65 0x5bb2053d>)) "{\"jsonrpc\": \"2.0\", \"method\": \"textDocument/publishDiagnostics\", \"params\": {\"uri\": \"file:///Users/andy/emacs-application-framework/eaf.py\", \"diagnostics\": [{\"source\": \"pyflakes\", \"range\": {\"start\": {\"line\": 24, \"character\": 0}, \"end\": {\"line\": 24, \"character\": 61}}, \"message\": \"'app.browser.buffer.AppBuffer as NeverUsed' imported but unused\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 22, \"character\": 79}, \"end\": {\"line\": 22, \"character\": 128}}, \"message\": \"E501 line too long (127 > 79 characters)\", \"code\": \"E501\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 23, \"character\": 79}, \"end\": {\"line\": 23, \"character\": 118}}, \"message\": \"E501 line too long (117 > 79 characters)\", \"code\": \"E501\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 24, \"character\": 53}, \"end\": {\"line\": 24, \"character\": 61}}, \"message\": \"E261 at least two spaces before inline comment\", \"code\": \"E261\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 40, \"character\": 0}, \"end\": {\"line\": 40, \"character\": 32}}, \"message\": \"E302 expected 2 blank lines, found 1\", \"code\": \"E302\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 58, \"character\": 79}, \"end\": {\"line\": 58, \"character\": 83}}, \"message\": \"E501 line too long (82 > 79 characters)\", \"code\": \"E501\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 72, \"character\": 79}, \"end\": {\"line\": 72, \"character\": 108}}, \"message\": \"E501 line too long (107 > 79 characters)\", \"code\": \"E501\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 104, \"character\": 79}, \"end\": {\"line\": 104, \"character\": 95}}, \"message\": \"E501 line too long (94 > 79 characters)\", \"code\": \"E501\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 134, \"character\": 79}, \"end\": {\"line\": 134, \"character\": 88}}, \"message\": \"E501 line too long (87 > 79 characters)\", \"code\": \"E501\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 152, \"character\": 79}, \"end\": {\"line\": 152, \"character\": 105}}, \"message\": \"E501 line too long (104 > 79 characters)\", \"code\": \"E501\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 164, \"character\": 79}, \"end\": {\"line\": 164, \"character\": 93}}, \"message\": \"E501 line too long (92 > 79 characters)\", \"code\": \"E501\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 165, \"character\": 79}, \"end\": {\"line\": 165, \"character\": 84}}, \"message\": \"E501 line too long (83 > 79 characters)\", \"code\": \"E501\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 168, \"character\": 79}, \"end\": {\"line\": 168, \"character\": 111}}, \"message\": \"E501 line too long (110 > 79 characters)\", \"code\": \"E501\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 170, \"character\": 79}, \"end\": {\"line\": 170, \"character\": 85}}, \"message\": \"E501 line too long (84 > 79 characters)\", \"code\": \"E501\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 193, \"character\": 79}, \"end\": {\"line\": 193, \"character\": 85}}, \"message\": \"E501 line too long (84 > 79 characters)\", \"code\": \"E501\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 201, \"character\": 79}, \"end\": {\"line\": 201, \"character\": 91}}, \"message\": \"E501 line too long (90 > 79 characters)\", \"code\": \"E501\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 204, \"character\": 79}, \"end\": {\"line\": 204, \"character\": 118}}, \"message\": \"E501 line too long (117 > 79 characters)\", \"code\": \"E501\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 208, \"character\": 79}, \"end\": {\"line\": 208, \"character\": 83}}, \"message\": \"E501 line too long (82 > 79 characters)\", \"code\": \"E501\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 210, \"character\": 79}, \"end\": {\"line\": 210, \"character\": 81}}, \"message\": \"E501 line too long (80 > 79 characters)\", \"code\": \"E501\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 211, \"character\": 79}, \"end\": {\"line\": 211, \"character\": 83}}, \"message\": \"E501 line too long (82 > 79 characters)\", \"code\": \"E501\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 308, \"character\": 79}, \"end\": {\"line\": 308, \"character\": 93}}, \"message\": \"E501 line too long (92 > 79 characters)\", \"code\": \"E501\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 310, \"character\": 79}, \"end\": {\"line\": 310, \"character\": 95}}, \"message\": \"E501 line too long (94 > 79 characters)\", \"code\": \"E501\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 317, \"character\": 79}, \"end\": {\"line\": 317, \"character\": 91}}, \"message\": \"E501 line too long (90 > 79 characters)\", \"code\": \"E501\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 330, \"character\": 79}, \"end\": {\"line\": 330, \"character\": 89}}, \"message\": \"E501 line too long (88 > 79 characters)\", \"code\": \"E501\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 332, \"character\": 79}, \"end\": {\"line\": 332, \"character\": 107}}, \"message\": \"E501 line too long (106 > 79 characters)\", \"code\": \"E501\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 334, \"character\": 79}, \"end\": {\"line\": 334, \"character\": 96}}, \"message\": \"E501 line too long (95 > 79 characters)\", \"code\": \"E501\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 338, \"character\": 79}, \"end\": {\"line\": 338, \"character\": 87}}, \"message\": \"E501 line too long (86 > 79 characters)\", \"code\": \"E501\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 340, \"character\": 0}, \"end\": {\"line\": 340, \"character\": 27}}, \"message\": \"E305 expected 2 blank lines after class or function definition, found 1\", \"code\": \"E305\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 344, \"character\": 38}, \"end\": {\"line\": 344, \"character\": 78}}, \"message\": \"E261 at least two spaces before inline comment\", \"code\": \"E261\", \"severity\": 2}, {\"source\": \"pycodestyle\", \"range\": {\"start\": {\"line\": 347, \"character\": 79}, \"end\": {\"line\": 347, \"character\": 85}}, \"message\": \"E501 line too long (84 > 79 characters)\", \"code\": \"E501\", \"severity\": 2}]}}")
  (let ((m (car --dolist-tail--))) (if lsp-print-io (progn (let ((inhibit-message t)) (lsp-message "<<<< %s\n%s" (lsp--workspace-print (progn (or ... ...) (aref p 11))) (lsp--json-pretty-print m))))) (lsp--parser-on-message p m) (setq --dolist-tail-- (cdr --dolist-tail--)))
  (while --dolist-tail-- (let ((m (car --dolist-tail--))) (if lsp-print-io (progn (let ((inhibit-message t)) (lsp-message "<<<< %s\n%s" (lsp--workspace-print (progn ... ...)) (lsp--json-pretty-print m))))) (lsp--parser-on-message p m) (setq --dolist-tail-- (cdr --dolist-tail--))))
  (let ((--dolist-tail-- messages)) (while --dolist-tail-- (let ((m (car --dolist-tail--))) (if lsp-print-io (progn (let ((inhibit-message t)) (lsp-message "<<<< %s\n%s" (lsp--workspace-print ...) (lsp--json-pretty-print m))))) (lsp--parser-on-message p m) (setq --dolist-tail-- (cdr --dolist-tail--)))))
  (progn (let ((--dolist-tail-- messages)) (while --dolist-tail-- (let ((m (car --dolist-tail--))) (if lsp-print-io (progn (let (...) (lsp-message "<<<< %s\n%s" ... ...)))) (lsp--parser-on-message p m) (setq --dolist-tail-- (cdr --dolist-tail--))))))
  (if messages (progn (let ((--dolist-tail-- messages)) (while --dolist-tail-- (let ((m (car --dolist-tail--))) (if lsp-print-io (progn (let ... ...))) (lsp--parser-on-message p m) (setq --dolist-tail-- (cdr --dolist-tail--)))))))
  (let ((messages (condition-case err (lsp--parser-read p output) (error (let ((chunk ...)) (lsp--parser-reset p) (progn (progn ... ...) (progn ... ...)) (lsp-warn "Failed to parse the following chunk:\n'''\n%s\n'''\nwith message %s" chunk err) nil))))) (if messages (progn (let ((--dolist-tail-- messages)) (while --dolist-tail-- (let ((m ...)) (if lsp-print-io (progn ...)) (lsp--parser-on-message p m) (setq --dolist-tail-- (cdr --dolist-tail--))))))))
  (progn (let ((messages (condition-case err (lsp--parser-read p output) (error (let (...) (lsp--parser-reset p) (progn ... ...) (lsp-warn "Failed to parse the following chunk:\n'''\n%s\n'''\nwith message %s" chunk err) nil))))) (if messages (progn (let ((--dolist-tail-- messages)) (while --dolist-tail-- (let (...) (if lsp-print-io ...) (lsp--parser-on-message p m) (setq --dolist-tail-- ...))))))))
  (if (let* ((--cl-var-- ignore-regexps) (r nil) (--cl-var-- t) --cl-var--) (while (and (consp --cl-var--) (progn (setq r (car --cl-var--)) (if (string-match r output) (setq --cl-var-- nil --cl-var-- nil) t))) (setq --cl-var-- (cdr --cl-var--))) (if --cl-var-- (progn t) --cl-var--)) (progn (let ((messages (condition-case err (lsp--parser-read p output) (error (let ... ... ... ... nil))))) (if messages (progn (let ((--dolist-tail-- messages)) (while --dolist-tail-- (let ... ... ... ...))))))))
  (closure ((ignore-regexps) (p . #s(lsp--parser :waiting-for-response nil :response-result nil :headers nil :body nil :reading-body nil :body-length nil :body-received nil :leftovers "" :queued-notifications nil :queued-requests nil :workspace #s(lsp--workspace :parser #5 :file-versions #<hash-table equal 1/65 0x5cafe545> :server-capabilities #<hash-table equal 15/65 0x5ca9fdd9> :registered-server-capabilities nil :root "~/emacs-application-framework/" :client #s(lsp--client :language-id nil :add-on? nil :DEPRECATED_send-async nil :DEPRECATED_type nil :new-connection (:connect (closure ... ... ...) :test\? (closure ... nil ...)) :DEPRECATED_stderr nil :DEPRECATED_get-root nil :ignore-regexps nil :ignore-messages nil :notification-handlers #<hash-table equal 0/65 0x40c44435> :request-handlers #<hash-table equal 0/65 0x40c44455> :response-handlers #<hash-table eql 0/65 0x40c4d041> :string-renderers nil :DEPRECATED_last-id 0 :DEPRECATED_enable-function nil :prefix-function nil :uri-handlers #<hash-table equal 0/65 0x40c4d441> :action-handlers #<hash-table equal 0/65 0x40c4e7e1> :DEPRECATED_default-renderer nil :use-native-json nil :major-modes (python-mode) :priority -1 :server-id pyls :multi-root nil :initialization-options nil :library-folders-fn (closure (t) (_workspace) lsp-clients-python-library-directories) :before-file-open-fn nil :initialized-fn nil) :change-timer-disabled nil :proc #<process pyls> :cmd-proc #<process pyls> :buffers (#<buffer eaf.py>) :highlight-overlays #<hash-table eq 0/65 0x5cafe565> :extra-client-capabilities nil :status initialized :metadata #<hash-table equal 0/65 0x5cafe585> :watches #<hash-table equal 0/65 0x4054f08d> :workspace-folders nil :last-id 0 :status-string nil :shutdown-action nil :diagnostics #<hash-table equal 0/65 0x5bb2053d>))) cl-struct-lsp-session-tags cl-struct-lsp--workspace-tags cl-struct-lsp--registered-capability-tags cl-struct-lsp-diagnostic-tags cl-struct-lsp--client-tags cl-struct-lsp--parser-tags t) (_proc output) (if (let* ((--cl-var-- ignore-regexps) (r nil) (--cl-var-- t) --cl-var--) (while (and (consp --cl-var--) (progn (setq r (car --cl-var--)) (if (string-match r output) (setq --cl-var-- nil --cl-var-- nil) t))) (setq --cl-var-- (cdr --cl-var--))) (if --cl-var-- (progn t) --cl-var--)) (progn (let 

懶貓大神能自行處理的吧……也可能是Emacs版本問題導致flymake不好。我看了下,這是正常的。

剛剛還發了個PR修復pyls用的MarkupContent渲染:

  (if (and (hash-table-p contents) (gethash "kind" contents))
      ;; MarkupContent, deprecated by LSP but actually very flexible.
      ;; It tends to be long and is not suitable in echo area.
      (if render-all (lsp--render-element contents) "")
    ;; MarkedString -> MarkedString[]
    (when (or (hash-table-p contents) (stringp contents))
      (setq contents (list contents)))
    ;; Consider the signature consisting of the elements who have a renderable
    ;; "language" property. When render-all is nil, ignore other elements.
    (string-join
     (seq-map
      #'lsp--render-element
      (if render-all
          contents
        (--filter (and (hash-table-p it) (lsp-get-renderer (gethash "language" it)))
                  contents)))
     "\n"))

當配置的多個servers支持某一major-mode,前天的改動會彈出prompt。對於我,就是ccls clangd二選一。解決方案是讓lsp-clients.el定義的servers priority -1,外部的priority 0,高的覆蓋低的。(外部packages是手動require的,理應有更高優先級)

lsp-mode的use-package配置方案我貼到 GitHub - emacs-lsp/lsp-mode: Emacs client/library for the Language Server Protocol

另外現在lsp.el變成了forwarder,推薦用(require 'lsp-mode)而不是(require 'lsp)

我即使只 require 了 lsp-mode 和 company-lsp 也没法正常补全.

我现在的问题是, 现阶段 lsp-mode 更新后, 如果一个用户不用 package.el , 完全没法工作.

一定要用 lsp-ui 吗?

我覺得你應該像寫自己的工具那樣,稍微花一點精力看下這個東西是怎麼回事。 對於package.el用戶,特別是use-package用戶,lsp-mode已經非常接近out-of-the-box了。

不用package.el自然會有很多困擾。需要用lsp-mode lsp-ui company-lsp全套的話,下面幾個依賴需要安裝:

dash ht f spinner markdown-mode yasnippet

你可能對這個感興趣 [Poll] lsp-mode - minimal or batteries included · Issue #542 · emacs-lsp/lsp-mode · GitHub 我不反對把某些組件移進lsp-mode,但是我不能commit lsp-mode,只能commit lsp-ui,所以我不說話(我也沒有精力去做一個完全的maintainer,我的elisp技能一直是用多少學多少,elisp大神們不用C++,C++大神們不用elisp,我才不得已學點elisp搬運東西進lsp-mode;另外一邊處理ccls issues已經讓我很困擾了)

另外這個 signatureHelp 的討論大家也可以看看: Added constraints to ParameterInformation.label break possible use cases · Issue #640 · microsoft/language-server-protocol · GitHub oblitum提出的。MS的人過度重視兼容性(以及vscode的現成實現),讓人挺難受的

1 个赞

依赖我都安装了, 我最近没时间研究 LSP 新版代码到底出了什么问题了.

什么时候有空我自己写 LSP Client 吧, 实在忍受不了一个 out-of-the-box 的东西, 进入各种语言的时候各种报错.

我不认为 lsp-mode 现在做到了开箱即用, 可能是lsp-mode的作者对开箱即用的概念和我的认识有偏差.

2 个赞

这个是我的lsp依赖:

         (lsp . (:repo "emacs-lsp/lsp-mode" :dependency (ht f spinner)))
         (company-lsp . (:repo "tigersoldier/company-lsp"))
         (company-box . (:repo "sebastiencs/company-box"))
         (lsp-ui . (:repo "emacs-lsp/lsp-ui"))
         (spinner . (:repo "Malabarba/spinner.el"))
         (dash . (:repo "magnars/dash.el"))
         (f . (:repo "rejeep/f.el" :dependency (dash s)))
         (s . (:repo "magnars/s.el"))
         (ht . (:repo "Wilfred/ht.el" :dependency (dash)))
         (lsp-python . (:repo "emacs-lsp/lsp-python"))

试试eglot?eglot我感觉还算稳定。

今天更新了lsp-mode后发现自定义的lsp-server会报LSP:: xxx.xx not in project.我设置了 (setq lsp-auto-guess-root t lsp-prefer-flymake nil)

go的新lsp-server的配置是这样的: (require 'lsp) (lsp-register-client (make-lsp-client :new-connection (lsp-stdio-connection “golsp”) :major-modes '(go-mode) :server-id 'go-lsp))

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

不知道我是个例还是其他?