diff --git a/etc/EGLOT-NEWS b/etc/EGLOT-NEWS index dc77e4fe624..dd04e677285 100644 --- a/etc/EGLOT-NEWS +++ b/etc/EGLOT-NEWS @@ -12,11 +12,16 @@ This file is about changes in Eglot, the Emacs client for LSP (Language Server Protocol) distributed with GNU Emacs since Emacs version 29.1 and with GNU ELPA since 2018. -Note: references to Eglot issues are presented as "github#nnnn". -This refers to https://github.com/joaotavora/eglot/issues/. -That is, to look up issue github#1234, go to +Note: references to some Eglot issues are presented as "github#nnnn". +This refers to https://github.com/joaotavora/eglot/issues/. That is, +to look up issue github#1234, go to https://github.com/joaotavora/eglot/issues/1234. + +* Changes in Eglot 1.13 (15/03/2023) + +** ELPA installations on Emacs 26.3 are supported again. + * Changes in Eglot 1.12 (13/03/2023) @@ -328,7 +333,7 @@ This disconnects the server after last managed buffer is killed. (github#217, github#270) -** Completion support support has been fixed. +** Completion support has been fixed. Among other things, consider LSP's "filterText" cookies, which enable a kind of poor-man's flex-matching for some backends. diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index a0bb5e75393..0258ed52bee 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -3083,8 +3083,7 @@ The most useful commands here are: `[("Package" ,package-name-column-width package-menu--name-predicate) ("Version" ,package-version-column-width package-menu--version-predicate) ("Status" ,package-status-column-width package-menu--status-predicate) - ,@(if (cdr package-archives) - `(("Archive" ,package-archive-column-width package-menu--archive-predicate))) + ("Archive" ,package-archive-column-width package-menu--archive-predicate) ("Description" 0 package-menu--description-predicate)]) (setq tabulated-list-padding 2) (setq tabulated-list-sort-key (cons "Status" nil)) @@ -3512,9 +3511,8 @@ Return (PKG-DESC [NAME VERSION STATUS DOC])." (package-desc-version pkg))) 'font-lock-face face) ,(propertize status 'font-lock-face face) - ,@(if (cdr package-archives) - (list (propertize (or (package-desc-archive pkg) "") - 'font-lock-face face))) + ,(propertize (or (package-desc-archive pkg) "") + 'font-lock-face face) ,(propertize (package-desc-summary pkg) 'font-lock-face 'package-description)]))) diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 5227897fbec..882b79b3ee7 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -1651,7 +1651,7 @@ ID-FORMAT valid values are `string' and `integer'." (if (tramp-file-property-p v localname "file-attributes") (or (tramp-check-cached-permissions v ?x) (tramp-check-cached-permissions v ?s)) - (tramp-run-test "-x" filename))))) + (tramp-run-test v "-x" localname))))) (defun tramp-sh-handle-file-readable-p (filename) "Like `file-readable-p' for Tramp files." @@ -1661,7 +1661,7 @@ ID-FORMAT valid values are `string' and `integer'." ;; satisfied without remote operation. (if (tramp-file-property-p v localname "file-attributes") (tramp-handle-file-readable-p filename) - (tramp-run-test "-r" filename))))) + (tramp-run-test v "-r" localname))))) ;; Functions implemented using the basic functions above. @@ -1682,7 +1682,7 @@ ID-FORMAT valid values are `string' and `integer'." (tramp-get-file-property v (tramp-file-local-name truename) "file-attributes")) t) - (tramp-run-test "-d" filename)))))) + (tramp-run-test v "-d" localname)))))) (defun tramp-sh-handle-file-writable-p (filename) "Like `file-writable-p' for Tramp files." @@ -1693,7 +1693,7 @@ ID-FORMAT valid values are `string' and `integer'." ;; Examine `file-attributes' cache to see if request can ;; be satisfied without remote operation. (tramp-check-cached-permissions v ?w) - (tramp-run-test "-w" filename)) + (tramp-run-test v "-w" localname)) ;; If file doesn't exist, check if directory is writable. (and (file-directory-p (file-name-directory filename)) @@ -4020,17 +4020,14 @@ Only send the definition if it has not already been done." (tramp-set-connection-property (tramp-get-connection-process vec) "scripts" (cons name scripts)))))) -(defun tramp-run-test (switch filename) - "Run `test' on the remote system, given a SWITCH and a FILENAME. +(defun tramp-run-test (vec switch localname) + "Run `test' on the remote system VEC, given a SWITCH and a LOCALNAME. Returns the exit code of the `test' program." - (with-parsed-tramp-file-name filename nil - (tramp-send-command-and-check - v - (format - "%s %s %s" - (tramp-get-test-command v) - switch - (tramp-shell-quote-argument localname))))) + (tramp-send-command-and-check + vec + (format + "%s %s %s" + (tramp-get-test-command vec) switch (tramp-shell-quote-argument localname)))) (defun tramp-find-executable (vec progname dirlist &optional ignore-tilde ignore-path) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 037cc87148f..6c1b9eafe43 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -2,7 +2,7 @@ ;; Copyright (C) 2018-2023 Free Software Foundation, Inc. -;; Version: 1.12 +;; Version: 1.13 ;; Author: João Távora ;; Maintainer: João Távora ;; URL: https://github.com/joaotavora/eglot @@ -2147,6 +2147,10 @@ COMMAND is a symbol naming the command." (_server (_method (eql telemetry/event)) &rest _any) "Handle notification telemetry/event.") ;; noop, use events buffer +(defalias 'eglot--reporter-update + (if (> emacs-major-version 26) #'progress-reporter-update + (lambda (a b &optional _c) (progress-reporter-update a b)))) + (cl-defmethod eglot-handle-notification (server (_method (eql $/progress)) &key token value) "Handle $/progress notification identified by TOKEN from SERVER." @@ -2162,10 +2166,10 @@ COMMAND is a symbol naming the command." (make-progress-reporter prefix 0 100 percentage 1 0) (make-progress-reporter prefix nil nil nil 1 0)) (eglot--progress-reporters server)))) - (progress-reporter-update pr percentage (fmt title message)))) + (eglot--reporter-update pr percentage (fmt title message)))) ("report" (when-let ((pr (gethash token (eglot--progress-reporters server)))) - (progress-reporter-update pr percentage (fmt title message)))) + (eglot--reporter-update pr percentage (fmt title message)))) ("end" (remhash token (eglot--progress-reporters server)))))))) (cl-defmethod eglot-handle-notification @@ -2183,7 +2187,7 @@ COMMAND is a symbol naming the command." (buffer (find-buffer-visiting path))) (with-current-buffer buffer (cl-loop - initially (assoc-delete-all path flymake-list-only-diagnostics #'string=) + initially (assoc-delete-all path flymake-list-only-diagnostics) for diag-spec across diagnostics collect (eglot--dbind ((Diagnostic) range code message severity source tags) diag-spec @@ -2237,7 +2241,7 @@ COMMAND is a symbol naming the command." into diags finally (setq flymake-list-only-diagnostics - (assoc-delete-all path flymake-list-only-diagnostics #'string=)) + (assoc-delete-all path flymake-list-only-diagnostics)) (push (cons path diags) flymake-list-only-diagnostics))))) (cl-defun eglot--register-unregister (server things how) diff --git a/lisp/progmodes/elixir-ts-mode.el b/lisp/progmodes/elixir-ts-mode.el index 8adf647b081..136275b0f5f 100644 --- a/lisp/progmodes/elixir-ts-mode.el +++ b/lisp/progmodes/elixir-ts-mode.el @@ -87,7 +87,7 @@ (defconst elixir-ts--sexp-regexp (rx bol (or "call" "stab_clause" "binary_operator" "list" "tuple" "map" "pair" - "sigil" "string" "atom" "pair" "alias" "arguments" "atom" "identifier" + "sigil" "string" "atom" "alias" "arguments" "identifier" "boolean" "quoted_content") eol)) diff --git a/test/lisp/progmodes/eglot-tests.el b/test/lisp/progmodes/eglot-tests.el index b95e527c510..7ac26732737 100644 --- a/test/lisp/progmodes/eglot-tests.el +++ b/test/lisp/progmodes/eglot-tests.el @@ -31,23 +31,20 @@ ;; Some of these tests rely on the GNU ELPA package company.el and ;; yasnippet.el being available. -;; Some of the tests require access to a remote host files. Since -;; this could be problematic, a mock-up connection method "mock" is -;; used. Emulating a remote connection, it simply calls "sh -i". -;; Tramp's file name handlers still run, so this test is sufficient -;; except for connection establishing. - -;; If you want to test a real Tramp connection, set -;; $REMOTE_TEMPORARY_FILE_DIRECTORY to a suitable value in order to -;; overwrite the default value. If you want to skip tests accessing a -;; remote host, set this environment variable to "/dev/null" or -;; whatever is appropriate on your system. +;; Some of the tests require access to a remote host files, which is +;; mocked in the simplest case. If you want to test a real Tramp +;; connection, override $REMOTE_TEMPORARY_FILE_DIRECTORY to a suitable +;; value (FIXME: like what?) in order to overwrite the default value. +;; +;; IMPORTANT: Since Eglot is a :core ELPA package, these tests are + ;;supposed to run on Emacsen down to 26.3. Do not use bleeding-edge + ;;functionality not compatible with that Emacs version. ;;; Code: (require 'eglot) (require 'cl-lib) (require 'ert) -(require 'tramp) ; must be prior ert-x +(require 'tramp) (require 'ert-x) ; ert-simulate-command (require 'edebug) (require 'python) ; some tests use pylsp @@ -463,7 +460,7 @@ then restored." (eglot--make-file-or-dir '(".git")) (eglot--make-file-or-dir `("compile_commands.json" . - ,(json-serialize + ,(jsonrpc--json-encode `[(:directory ,default-directory :command "/usr/bin/c++ -Wall -c main.cpp" :file ,(expand-file-name "main.cpp"))]))) (let ((eglot-server-programs '((c++-mode . ("clangd"))))) @@ -744,7 +741,7 @@ pylsp prefers autopep over yafp, despite its README stating the contrary." (should (zerop (shell-command "cargo init"))) (eglot--sniffing (:server-notifications s-notifs) (should (eglot--tests-connect)) - (eglot--wait-for (s-notifs 10) (&key method &allow-other-keys) + (eglot--wait-for (s-notifs 20) (&key method &allow-other-keys) (string= method "textDocument/publishDiagnostics"))) (goto-char (point-max)) (eglot--simulate-key-event ?.) @@ -810,7 +807,7 @@ pylsp prefers autopep over yafp, despite its README stating the contrary." (should (= 4 (length (flymake--project-diagnostics)))))))))) (ert-deftest eglot-test-project-wide-diagnostics-rust-analyzer () - "Test diagnostics through multiple files in a TypeScript LSP." + "Test diagnostics through multiple files in rust-analyzer." (skip-unless (executable-find "rust-analyzer")) (skip-unless (executable-find "cargo")) (skip-unless (executable-find "git")) @@ -829,7 +826,7 @@ pylsp prefers autopep over yafp, despite its README stating the contrary." (eglot--sniffing (:server-notifications s-notifs) (eglot--tests-connect) (flymake-start) - (eglot--wait-for (s-notifs 15) + (eglot--wait-for (s-notifs 20) (&key _id method params &allow-other-keys) (and (string= method "textDocument/publishDiagnostics") (string-suffix-p "main.rs" (plist-get params :uri)))) @@ -1272,18 +1269,28 @@ macro will assume it exists." (defvar tramp-histfile-override) (defun eglot--call-with-tramp-test (fn) + (unless (>= emacs-major-version 27) + (ert-skip "Eglot Tramp support only on Emacs >= 27")) ;; Set up a Tramp method that’s just a shell so the remote host is ;; really just the local host. - (let* ((tramp-remote-path (cons 'tramp-own-remote-path tramp-remote-path)) + (let* ((tramp-remote-path (cons 'tramp-own-remote-path + tramp-remote-path)) (tramp-histfile-override t) (tramp-verbose 1) (temporary-file-directory (or (bound-and-true-p ert-remote-temporary-file-directory) - temporary-file-directory)) + (prog1 (format "/mock::%s" temporary-file-directory) + (add-to-list + 'tramp-methods + '("mock" + (tramp-login-program "sh") (tramp-login-args (("-i"))) + (tramp-direct-async ("-c")) (tramp-remote-shell "/bin/sh") + (tramp-remote-shell-args ("-c")) (tramp-connection-timeout 10))) + (add-to-list 'tramp-default-host-alist + `("\\`mock\\'" nil ,(system-name))) + (when (and noninteractive (not (file-directory-p "~/"))) + (setenv "HOME" temporary-file-directory))))) (default-directory temporary-file-directory)) - ;; We must check the remote LSP server. So far, just "clangd" is used. - (unless (executable-find "clangd" 'remote) - (ert-skip "Remote clangd not found")) (funcall fn))) (ert-deftest eglot-test-tramp-test ()