From: Michael Livshin Date: Sat, 15 Dec 2018 01:17:32 +0000 (+0000) Subject: Manage cross-referenced files outside project in same server X-Git-Tag: emacs-29.0.90~1616^2~524^2~4^2~136 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=7eddb6f950b0a067a55347600d499cae608aa728;p=emacs.git Manage cross-referenced files outside project in same server Close https://github.com/joaotavora/eglot/issues/686, Close https://github.com/joaotavora/eglot/issues/695. Co-authored-by: João Távora * eglot.el (eglot-extend-to-xref): new defcustom, default to nil. (eglot--servers-by-xrefed-file): new hash table, mapping file names to servers. (eglot--managed-mode): use eglot-current-server, instead of eglot--cached-server directly. (eglot--current-server-or-lose): ditto. (eglot--maybe-activate-editing-mode): ditto. (eglot-current-server): move all cached-server update logic here -- if eglot--cached-server is nil, try to find it using current project or (optionally) xref location. (eglot--xref-make-match): record the xref location. * README.md (Customization): Mention new defcustom. * NEWS.md: Mention new feature GitHub-reference: fix https://github.com/joaotavora/eglot/issues/76 --- diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index f17e795bfb5..db468d83c14 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -237,6 +237,10 @@ let the buffer grow forever." :type '(choice (const :tag "Don't show confirmation prompt" nil) (symbol :tag "Show confirmation prompt" 'confirm))) +(defcustom eglot-extend-to-xref nil + "If non-nil, activate Eglot in cross-referenced non-project files." + :type 'boolean) + ;; Customizable via `completion-category-overrides'. (when (assoc 'flex completion-styles-alist) (add-to-list 'completion-category-defaults '(eglot (styles flex basic)))) @@ -832,6 +836,9 @@ be guessed." (put 'eglot-lsp-context 'variable-documentation "Dynamically non-nil when searching for projects in LSP context.") +(defvar eglot--servers-by-xrefed-file + (make-hash-table :test 'equal :weakness 'value)) + (defun eglot--current-project () "Return a project object for Eglot's LSP purposes. This relies on `project-current' and thus on @@ -1495,7 +1502,7 @@ Use `eglot-managed-p' to determine if current buffer is managed.") #'eglot-imenu)) (flymake-mode 1) (eldoc-mode 1) - (cl-pushnew (current-buffer) (eglot--managed-buffers eglot--cached-server))) + (cl-pushnew (current-buffer) (eglot--managed-buffers (eglot-current-server)))) (t (remove-hook 'after-change-functions 'eglot--after-change t) (remove-hook 'before-change-functions 'eglot--before-change t) @@ -1533,11 +1540,19 @@ Use `eglot-managed-p' to determine if current buffer is managed.") (defun eglot-current-server () "Return logical EGLOT server for current buffer, nil if none." - eglot--cached-server) + (setq eglot--cached-server + (or eglot--cached-server + (cl-find major-mode + (gethash (eglot--current-project) eglot--servers-by-project) + :key #'eglot--major-mode) + (and eglot-extend-to-xref + buffer-file-name + (gethash (expand-file-name buffer-file-name) + eglot--servers-by-xrefed-file))))) (defun eglot--current-server-or-lose () "Return current logical EGLOT server connection or error." - (or eglot--cached-server + (or (eglot-current-server) (jsonrpc-error "No current JSON-RPC connection"))) (defvar-local eglot--unreported-diagnostics nil @@ -1555,14 +1570,7 @@ If it is activated, also signal textDocument/didOpen." (unless eglot--managed-mode ;; Called when `revert-buffer-in-progress-p' is t but ;; `revert-buffer-preserve-modes' is nil. - (when (and buffer-file-name - (or - eglot--cached-server - (setq eglot--cached-server - (cl-find major-mode - (gethash (eglot--current-project) - eglot--servers-by-project) - :key #'eglot--major-mode)))) + (when (and buffer-file-name (eglot-current-server)) (setq eglot--unreported-diagnostics `(:just-opened . nil)) (eglot--managed-mode) (eglot--signal-textDocument/didOpen)))) @@ -2101,6 +2109,8 @@ Try to visit the target file for a richer summary line." (start-pos (cl-getf start :character)) (end-pos (cl-getf (cl-getf range :end) :character))) (list name line start-pos (- end-pos start-pos))))))) + (setf (gethash (expand-file-name file) eglot--servers-by-xrefed-file) + (eglot--current-server-or-lose)) (xref-make-match summary (xref-make-file-location file line column) length))) (cl-defmethod xref-backend-identifier-completion-table ((_backend (eql eglot)))