From a5be840c7b72592b8e6ba894b1be8e643ce3df0f Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sun, 26 Feb 2023 14:42:14 +0800 Subject: [PATCH 01/35] Fix the MS-DOS build * msdos/sedlibmk.inp: Update getopt.h conditions. --- msdos/sedlibmk.inp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/msdos/sedlibmk.inp b/msdos/sedlibmk.inp index 634bf999e50..c3f410bd74d 100644 --- a/msdos/sedlibmk.inp +++ b/msdos/sedlibmk.inp @@ -428,6 +428,8 @@ s/= @GL_GENERATE_STDINT_H_CONDITION@/= 1/ s/= @GL_GENERATE_LIMITS_H_CONDITION@/= 1/ s/= @GL_GENERATE_ERRNO_H_CONDITION@/= / s/= @GL_GENERATE_LIMITS_H_CONDITION@/= / +s/= @GL_GENERATE_GETOPT_CDEFS_H_CONDITION@/= 1/ +s/= @GL_GENERATE_GETOPT_H_CONDITION@/= 1/ s/= @GL_GENERATE_GMP_H_CONDITION@/= 1/ s/= @GL_GENERATE_GMP_GMP_H_CONDITION@/= / s/= @GL_GENERATE_MINI_GMP_H_CONDITION@/= 1/ From 8797e514ab68c12ed05d3af88e6baba64bf08f4d Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sat, 25 Feb 2023 15:38:38 -0800 Subject: [PATCH 02/35] Disable xattr test on MS-Windows. * nt/mingw-cfg.site (enable_xattr): Set to "no". (Bug#61782) --- nt/mingw-cfg.site | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nt/mingw-cfg.site b/nt/mingw-cfg.site index 7ca19cbad06..425eaace30d 100644 --- a/nt/mingw-cfg.site +++ b/nt/mingw-cfg.site @@ -170,3 +170,6 @@ gl_cv_func_free_preserves_errno=yes # Don't build the Gnulib nanosleep module: it requires W2K or later, # and MinGW does have nanosleep. gl_cv_func_nanosleep=yes +# Suppress configure-time diagnostic from unnecessary libxattr check, +# as xattr will not be supported here. +enable_xattr=no From 0db88d625a7ca1468af51ef0a04c22577500e059 Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Sun, 26 Feb 2023 01:12:18 -0800 Subject: [PATCH 03/35] ; * src/treesit.c (treesit_predicate_match): Fix typo. --- src/treesit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/treesit.c b/src/treesit.c index ef0f2407840..5a4fe3e8803 100644 --- a/src/treesit.c +++ b/src/treesit.c @@ -2484,7 +2484,7 @@ treesit_predicate_match (Lisp_Object args, struct capture_range captures) { if (XFIXNUM (Flength (args)) != 2) xsignal2 (Qtreesit_query_error, - build_string ("Predicate `equal' requires two " + build_string ("Predicate `match' requires two " "arguments but only given"), Flength (args)); From 5256392a7ec0639ba4ba684d608bb3aaf976c985 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 26 Feb 2023 11:34:14 +0200 Subject: [PATCH 04/35] Fix 'vertical-motion' when display strings are around * src/indent.c (Fvertical_motion): Correct bidi-related condition for character position, when we didn't move vertically. (Bug#61636) --- src/indent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/indent.c b/src/indent.c index 6de18d749ca..08d2bf5ea28 100644 --- a/src/indent.c +++ b/src/indent.c @@ -2401,7 +2401,7 @@ whether or not it is currently displayed in some window. */) last line that it occupies. */ if (it_start < ZV) { - if ((it.bidi_it.scan_dir > 0) + if ((it.bidi_it.scan_dir >= 0 || it.vpos == vpos_init) ? IT_CHARPOS (it) < it_start : IT_CHARPOS (it) > it_start) { From 5b174b96834af7153f2aec1ac10d91caa0d03e52 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 26 Feb 2023 11:46:20 +0200 Subject: [PATCH 05/35] Fix mule-tests in UTF-8 locales * test/lisp/international/mule-tests.el (sgml-html-meta-no-post-less-than-10lines): Fix test condition. --- test/lisp/international/mule-tests.el | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/lisp/international/mule-tests.el b/test/lisp/international/mule-tests.el index 6b76e35ae22..3e0c5bf9f4b 100644 --- a/test/lisp/international/mule-tests.el +++ b/test/lisp/international/mule-tests.el @@ -119,9 +119,10 @@ provide HTML fragments. Some tests override those variables." (ert-deftest sgml-html-meta-no-post-less-than-10lines () "No '', detect charset in the first 10 lines." (let ((sgml-html-meta-post "")) - (should (eq 'utf-8 (sgml-html-meta-run - (concat "\n\n\n\n\n\n\n\n\n" - "")))))) + (should (eq 'utf-8 (coding-system-base + (sgml-html-meta-run + (concat "\n\n\n\n\n\n\n\n\n" + ""))))))) (ert-deftest sgml-html-meta-no-post-10lines () "No '', do not detect charset after the first 10 lines." From b0e87e930e86d2e48659aed9cf85099c1fd2795c Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 26 Feb 2023 10:27:18 +0000 Subject: [PATCH 06/35] Eglot: use faster strategy for moving to LSP positions (bug#61726) Turns out we don't need encode-coding-region after all. * lisp/progmodes/eglot.el (eglot-move-to-lsp-abiding-column): Rewrite. Co-authored-by: Augusto Stoffel --- lisp/progmodes/eglot.el | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 2b9d44f84e6..b52b4975a89 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -1491,19 +1491,16 @@ be set to `eglot-move-to-lsp-abiding-column' (the default), and (line-end-position)))) (defun eglot-move-to-lsp-abiding-column (column) - "Move to COLUMN abiding by the LSP spec." - (save-restriction - (cl-loop - with lbp = (line-beginning-position) - initially - (narrow-to-region lbp (line-end-position)) - (move-to-column column) - for diff = (- column - (eglot-lsp-abiding-column lbp)) - until (zerop diff) - do (condition-case eob-err - (forward-char (/ (if (> diff 0) (1+ diff) (1- diff)) 2)) - (end-of-buffer (cl-return eob-err)))))) + "Move to COLUMN as computed by LSP's UTF-16 criterion." + (let* ((bol (line-beginning-position)) + (goal-char (+ bol column)) + (eol (line-end-position))) + (goto-char bol) + (while (and (< (point) goal-char) + (< (point) eol)) + (if (<= #x010000 (char-after) #x10ffff) + (setq goal-char (1- goal-char))) + (forward-char 1)))) (defun eglot--lsp-position-to-point (pos-plist &optional marker) "Convert LSP position POS-PLIST to Emacs point. From 3e3e6d71be76b80beca946f9dd433d12aa450695 Mon Sep 17 00:00:00 2001 From: Augusto Stoffel Date: Sun, 26 Feb 2023 11:47:32 +0000 Subject: [PATCH 07/35] Eglot: support positionEncoding LSP capability (bug#61726) * lisp/progmodes/eglot.el(eglot-client-capabilities): Announce the new capability. (eglot-bytewise-column, eglot-move-to-bytewise-column): New functions. (eglot--managed-mode): Set 'eglot-current-column-function' and 'eglot-move-to-bytewise-column' appropriately. --- lisp/progmodes/eglot.el | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index b52b4975a89..9e5dd268a94 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -816,6 +816,9 @@ treated as in `eglot--dbind'." `(:valueSet [,@(mapcar #'car eglot--tag-faces)]))) + :general + (list + :positionEncodings ["utf-32" "utf-8" "utf-16"]) :experimental eglot--{}))) (cl-defgeneric eglot-workspace-folders (server) @@ -1441,6 +1444,11 @@ CONNECT-ARGS are passed as additional arguments to (defun eglot-current-column () (- (point) (line-beginning-position))) +(defun eglot-bytewise-column () + "Calculate current column using the LSP `utf-8' criterion." + (length (encode-coding-region (line-beginning-position) (point) + 'utf-8-unix t))) + (defvar eglot-current-column-function #'eglot-lsp-abiding-column "Function to calculate the current column. @@ -1502,6 +1510,18 @@ be set to `eglot-move-to-lsp-abiding-column' (the default), and (setq goal-char (1- goal-char))) (forward-char 1)))) +(defun eglot-move-to-bytewise-column (column) + "Move to COLUMN as computed using the LSP `utf-8' criterion." + (let* ((bol (line-beginning-position)) + (goal-byte (+ (position-bytes bol) column)) + (eol (line-end-position))) + (goto-char bol) + (while (and (< (position-bytes (point)) goal-byte) + (< (point) eol)) + (if (>= (char-after) #x3fff80) ; raw bytes take 2 bytes in the buffer + (setq goal-byte (1+ goal-byte))) + (forward-char 1)))) + (defun eglot--lsp-position-to-point (pos-plist &optional marker) "Convert LSP position POS-PLIST to Emacs point. If optional MARKER, return a marker instead" @@ -1755,6 +1775,14 @@ Use `eglot-managed-p' to determine if current buffer is managed.") :init-value nil :lighter nil :keymap eglot-mode-map (cond (eglot--managed-mode + (pcase (plist-get (eglot--capabilities (eglot-current-server)) + :positionEncoding) + ("utf-32" + (eglot--setq-saving eglot-current-column-function #'eglot-current-column) + (eglot--setq-saving eglot-move-to-column-function #'eglot-move-to-column)) + ("utf-8" + (eglot--setq-saving eglot-current-column-function #'eglot-bytewise-column) + (eglot--setq-saving eglot-move-to-column-function #'eglot-move-to-bytewise-column))) (add-hook 'after-change-functions 'eglot--after-change nil t) (add-hook 'before-change-functions 'eglot--before-change nil t) (add-hook 'kill-buffer-hook #'eglot--managed-mode-off nil t) From ca79b138d424766e3bfe8e4ca5d2b315b9ea4408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Sun, 26 Feb 2023 12:50:42 +0000 Subject: [PATCH 08/35] Eglot: rename and redocument encoding-related functions (bug#61726) * lisp/progmodes/eglot.el (eglot-current-column): Obsolete. (eglot-lsp-abiding-column): Obsolete. (eglot-current-column-function): Obsolete. (eglot-current-linepos-function): Rename from eglot-current-column-function. (eglot-utf-8-linepos): Rename from eglot-bytewise-column. (eglot-utf-16-linepos): Rename from eglot-lsp-abiding-column. (eglot-utf-32-linepos): Rename from eglot-current-column. (eglot-move-to-current-column): Obsolete. (eglot-move-to-lsp-abiding-column): Obsolete. (eglot-move-to-column-function): Obsolete. (eglot-move-to-linepos-function): Rename from eglot-move-to-column-function. (eglot-move-to-utf-8-linepos): Rename from eglot-move-to-bytewise-column. (eglot-move-to-utf-16-linepos): Rename from eglot-move-to-lsp-abiding-column. (eglot-move-to-utf-32-linepos): Rename from eglot-move-to-current-column. (eglot--managed-mode): Adjust. (eglot-client-capabilities): Trim whitespace. * test/lisp/progmodes/eglot-tests.el (eglot-test-lsp-abiding-column) (eglot-test-lsp-abiding-column-1): Use new function/variable names. --- lisp/progmodes/eglot.el | 136 ++++++++++++++++------------- test/lisp/progmodes/eglot-tests.el | 10 +-- 2 files changed, 81 insertions(+), 65 deletions(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 9e5dd268a94..e63dd563c44 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -816,9 +816,7 @@ treated as in `eglot--dbind'." `(:valueSet [,@(mapcar #'car eglot--tag-faces)]))) - :general - (list - :positionEncodings ["utf-32" "utf-8" "utf-16"]) + :general (list :positionEncodings ["utf-32" "utf-8" "utf-16"]) :experimental eglot--{}))) (cl-defgeneric eglot-workspace-folders (server) @@ -1442,25 +1440,31 @@ CONNECT-ARGS are passed as additional arguments to (let ((warning-minimum-level :error)) (display-warning 'eglot (apply #'format format args) :warning))) -(defun eglot-current-column () (- (point) (line-beginning-position))) + +;;; Encoding fever +;;; +(define-obsolete-function-alias + 'eglot-lsp-abiding-column 'eglot-utf-16-linepos "29.1") +(define-obsolete-function-alias + 'eglot-current-column 'eglot-utf-32-linepos "29.1") +(define-obsolete-variable-alias + 'eglot-current-column-function 'eglot-current-linepos-function "29.1") -(defun eglot-bytewise-column () - "Calculate current column using the LSP `utf-8' criterion." +(defvar eglot-current-linepos-function #'eglot-utf-16-linepos + "Function calculating number of code units to line beginning. + +This is the inverse operation of +`eglot-move-to-linepos-function' (which see). It is a function of +no arguments returning the number of code units corresponding to +the current position of point relative to line beginning.") + +(defun eglot-utf-8-linepos () + "Calculate number of code units to line beginning using UTF-8." (length (encode-coding-region (line-beginning-position) (point) 'utf-8-unix t))) -(defvar eglot-current-column-function #'eglot-lsp-abiding-column - "Function to calculate the current column. - -This is the inverse operation of -`eglot-move-to-column-function' (which see). It is a function of -no arguments returning a column number. For buffers managed by -fully LSP-compliant servers, this should be set to -`eglot-lsp-abiding-column' (the default), and -`eglot-current-column' for all others.") - -(defun eglot-lsp-abiding-column (&optional lbp) - "Calculate current COLUMN as defined by the LSP spec. +(defun eglot-utf-16-linepos (&optional lbp) + "Calculate number of code units to line beginning using UTF-16. LBP defaults to `line-beginning-position'." (/ (- (length (encode-coding-region (or lbp (line-beginning-position)) ;; Fix github#860 @@ -1468,60 +1472,71 @@ LBP defaults to `line-beginning-position'." 2) 2)) +(defun eglot-utf-32-linepos () + "Calculate number of code units to line beginning using UTF-32." + (- (point) (line-beginning-position))) + (defun eglot--pos-to-lsp-position (&optional pos) "Convert point POS to LSP position." (eglot--widening ;; LSP line is zero-origin; emacs is one-origin. (list :line (1- (line-number-at-pos pos t)) :character (progn (when pos (goto-char pos)) - (funcall eglot-current-column-function))))) + (funcall eglot-current-linepos-function))))) -(defvar eglot-move-to-column-function #'eglot-move-to-lsp-abiding-column +(define-obsolete-function-alias + 'eglot-move-to-current-column 'eglot-move-to-utf-32-linepos "29.1") +(define-obsolete-function-alias + 'eglot-move-to-lsp-abiding-column 'eglot-move-to-utf-16-linepos "29.1") +(define-obsolete-variable-alias +'eglot-move-to-column-function 'eglot-move-to-linepos-function "29.1") + +(defvar eglot-move-to-linepos-function #'eglot-move-to-utf-16-linepos "Function to move to a column reported by the LSP server. -According to the standard, LSP column/character offsets are based -on a count of UTF-16 code units, not actual visual columns. So -when LSP says position 3 of a line containing just \"aXbc\", -where X is a multi-byte character, it actually means `b', not -`c'. However, many servers don't follow the spec this closely. +Per the LSP spec, character offsets in LSP Position objects count +UTF-16 code units, not actual code points. So when LSP says +position 3 of a line containing just \"aXbc\", where X is a funny +looking character in the UTF-16 \"supplementary plane\", it +actually means `b', not `c'. The default value +`eglot-move-to-utf-16-linepos' accounts for this. -For buffers managed by fully LSP-compliant servers, this should -be set to `eglot-move-to-lsp-abiding-column' (the default), and -`eglot-move-to-column' for all others.") +This variable also be set to `eglot-move-to-utf-8-linepos' or +`eglot-move-to-utf-32-linepos' for servers not closely following +the spec. Also, since LSP 3.17 server and client may agree on an +encoding and Eglot will set this variable automatically.") -(defun eglot-move-to-column (column) - "Move to COLUMN without closely following the LSP spec." - ;; We cannot use `move-to-column' here, because it moves to *visual* - ;; columns, which can be different from LSP columns in case of - ;; `whitespace-mode', `prettify-symbols-mode', etc. (github#296, - ;; github#297) - (goto-char (min (+ (line-beginning-position) column) - (line-end-position)))) - -(defun eglot-move-to-lsp-abiding-column (column) - "Move to COLUMN as computed by LSP's UTF-16 criterion." +(defun eglot-move-to-utf-8-linepos (n) + "Move to line's Nth code unit as computed by LSP's UTF-8 criterion." (let* ((bol (line-beginning-position)) - (goal-char (+ bol column)) + (goal-byte (+ (position-bytes bol) n)) (eol (line-end-position))) (goto-char bol) - (while (and (< (point) goal-char) - (< (point) eol)) - (if (<= #x010000 (char-after) #x10ffff) - (setq goal-char (1- goal-char))) + (while (and (< (position-bytes (point)) goal-byte) (< (point) eol)) + ;; raw bytes take 2 bytes in the buffer + (when (>= (char-after) #x3fff80) (setq goal-byte (1+ goal-byte))) (forward-char 1)))) -(defun eglot-move-to-bytewise-column (column) - "Move to COLUMN as computed using the LSP `utf-8' criterion." +(defun eglot-move-to-utf-16-linepos (n) + "Move to line's Nth code unit as computed by LSP's UTF-16 criterion." (let* ((bol (line-beginning-position)) - (goal-byte (+ (position-bytes bol) column)) - (eol (line-end-position))) + (goal-char (+ bol n)) + (eol (line-end-position))) (goto-char bol) - (while (and (< (position-bytes (point)) goal-byte) - (< (point) eol)) - (if (>= (char-after) #x3fff80) ; raw bytes take 2 bytes in the buffer - (setq goal-byte (1+ goal-byte))) + (while (and (< (point) goal-char) (< (point) eol)) + ;; code points in the "supplementary place" use two code units + (when (<= #x010000 (char-after) #x10ffff) (setq goal-char (1- goal-char))) (forward-char 1)))) +(defun eglot-move-to-utf-32-linepos (n) + "Move to line's Nth code unit as computed by LSP's UTF-32 criterion." + ;; We cannot use `move-to-column' here, because it moves to *visual* + ;; columns, which can be different from LSP characters in case of + ;; `whitespace-mode', `prettify-symbols-mode', etc. (github#296, + ;; github#297) + (goto-char (min (+ (line-beginning-position) n) + (line-end-position)))) + (defun eglot--lsp-position-to-point (pos-plist &optional marker) "Convert LSP position POS-PLIST to Emacs point. If optional MARKER, return a marker instead" @@ -1532,16 +1547,17 @@ If optional MARKER, return a marker instead" (forward-line (min most-positive-fixnum (plist-get pos-plist :line))) (unless (eobp) ;; if line was excessive leave point at eob - (let ((tab-width 1) - (col (plist-get pos-plist :character))) + (let ((col (plist-get pos-plist :character))) (unless (wholenump col) (eglot--warn "Caution: LSP server sent invalid character position %s. Using 0 instead." col) (setq col 0)) - (funcall eglot-move-to-column-function col))) + (funcall eglot-move-to-linepos-function col))) (if marker (copy-marker (point-marker)) (point))))) + +;;; More helpers (defconst eglot--uri-path-allowed-chars (let ((vec (copy-sequence url-path-allowed-chars))) (aset vec ?: nil) ;; see github#639 @@ -1778,11 +1794,11 @@ Use `eglot-managed-p' to determine if current buffer is managed.") (pcase (plist-get (eglot--capabilities (eglot-current-server)) :positionEncoding) ("utf-32" - (eglot--setq-saving eglot-current-column-function #'eglot-current-column) - (eglot--setq-saving eglot-move-to-column-function #'eglot-move-to-column)) + (eglot--setq-saving eglot-current-linepos-function #'eglot-utf-32-linepos) + (eglot--setq-saving eglot-move-to-linepos-function #'eglot-move-to-utf-32-linepos)) ("utf-8" - (eglot--setq-saving eglot-current-column-function #'eglot-bytewise-column) - (eglot--setq-saving eglot-move-to-column-function #'eglot-move-to-bytewise-column))) + (eglot--setq-saving eglot-current-linepos-function #'eglot-utf-8-linepos) + (eglot--setq-saving eglot-move-to-linepos-function #'eglot-move-to-utf-8-linepos))) (add-hook 'after-change-functions 'eglot--after-change nil t) (add-hook 'before-change-functions 'eglot--before-change nil t) (add-hook 'kill-buffer-hook #'eglot--managed-mode-off nil t) @@ -2616,7 +2632,7 @@ Try to visit the target file for a richer summary line." (add-face-text-property hi-beg hi-end 'xref-match t substring) (list substring (line-number-at-pos (point) t) - (eglot-current-column) (- end beg)))))) + (eglot-utf-32-linepos) (- end beg)))))) (`(,summary ,line ,column ,length) (cond (visiting (with-current-buffer visiting (funcall collect))) diff --git a/test/lisp/progmodes/eglot-tests.el b/test/lisp/progmodes/eglot-tests.el index 4b6528351b2..5d5de59a19a 100644 --- a/test/lisp/progmodes/eglot-tests.el +++ b/test/lisp/progmodes/eglot-tests.el @@ -856,8 +856,8 @@ pylsp prefers autopep over yafp, despite its README stating the contrary." '((c-mode . ("clangd"))))) (with-current-buffer (eglot--find-file-noselect "project/foo.c") - (setq-local eglot-move-to-column-function #'eglot-move-to-lsp-abiding-column) - (setq-local eglot-current-column-function #'eglot-lsp-abiding-column) + (setq-local eglot-move-to-linepos-function #'eglot-move-to-utf-16-linepos) + (setq-local eglot-current-linepos-function #'eglot-utf-16-linepos) (eglot--sniffing (:client-notifications c-notifs) (eglot--tests-connect) (end-of-line) @@ -866,12 +866,12 @@ pylsp prefers autopep over yafp, despite its README stating the contrary." (eglot--wait-for (c-notifs 2) (&key params &allow-other-keys) (should (equal 71 (cadddr (cadadr (aref (cadddr params) 0)))))) (beginning-of-line) - (should (eq eglot-move-to-column-function #'eglot-move-to-lsp-abiding-column)) - (funcall eglot-move-to-column-function 71) + (should (eq eglot-move-to-linepos-function #'eglot-move-to-utf-16-linepos)) + (funcall eglot-move-to-linepos-function 71) (should (looking-at "p"))))))) (ert-deftest eglot-test-lsp-abiding-column () - "Test basic `eglot-lsp-abiding-column' and `eglot-move-to-lsp-abiding-column'." + "Test basic LSP character counting logic." (skip-unless (executable-find "clangd")) (eglot-tests--lsp-abiding-column-1)) From a3d15c1f74988b488fc4f924b303f8de620645a9 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 26 Feb 2023 15:24:11 +0200 Subject: [PATCH 09/35] ; Fix last change * lisp/progmodes/eglot.el (eglot-current-linepos-function) (eglot-utf-8-linepos, eglot-utf-16-linepos) (eglot-utf-32-linepos, eglot-move-to-linepos-function) (eglot-move-to-utf-8-linepos, eglot-move-to-utf-32-linepos): Doc fixes. (Bug#61726) --- lisp/progmodes/eglot.el | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index e63dd563c44..ccd9cf3ee44 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -1451,7 +1451,7 @@ CONNECT-ARGS are passed as additional arguments to 'eglot-current-column-function 'eglot-current-linepos-function "29.1") (defvar eglot-current-linepos-function #'eglot-utf-16-linepos - "Function calculating number of code units to line beginning. + "Function calculating number of UTF-16 code units from line beginning. This is the inverse operation of `eglot-move-to-linepos-function' (which see). It is a function of @@ -1459,12 +1459,12 @@ no arguments returning the number of code units corresponding to the current position of point relative to line beginning.") (defun eglot-utf-8-linepos () - "Calculate number of code units to line beginning using UTF-8." + "Calculate number of UTF-8 bytes from line beginning." (length (encode-coding-region (line-beginning-position) (point) 'utf-8-unix t))) (defun eglot-utf-16-linepos (&optional lbp) - "Calculate number of code units to line beginning using UTF-16. + "Calculate number of UTF-16 code units from position given by LBP. LBP defaults to `line-beginning-position'." (/ (- (length (encode-coding-region (or lbp (line-beginning-position)) ;; Fix github#860 @@ -1473,7 +1473,7 @@ LBP defaults to `line-beginning-position'." 2)) (defun eglot-utf-32-linepos () - "Calculate number of code units to line beginning using UTF-32." + "Calculate number of Unicode codepoints from line beginning." (- (point) (line-beginning-position))) (defun eglot--pos-to-lsp-position (&optional pos) @@ -1492,7 +1492,7 @@ LBP defaults to `line-beginning-position'." 'eglot-move-to-column-function 'eglot-move-to-linepos-function "29.1") (defvar eglot-move-to-linepos-function #'eglot-move-to-utf-16-linepos - "Function to move to a column reported by the LSP server. + "Function to move to a position within a line reported by the LSP server. Per the LSP spec, character offsets in LSP Position objects count UTF-16 code units, not actual code points. So when LSP says @@ -1501,13 +1501,13 @@ looking character in the UTF-16 \"supplementary plane\", it actually means `b', not `c'. The default value `eglot-move-to-utf-16-linepos' accounts for this. -This variable also be set to `eglot-move-to-utf-8-linepos' or +This variable can also be set to `eglot-move-to-utf-8-linepos' or `eglot-move-to-utf-32-linepos' for servers not closely following the spec. Also, since LSP 3.17 server and client may agree on an encoding and Eglot will set this variable automatically.") (defun eglot-move-to-utf-8-linepos (n) - "Move to line's Nth code unit as computed by LSP's UTF-8 criterion." + "Move to line's Nth byte as computed by LSP's UTF-8 criterion." (let* ((bol (line-beginning-position)) (goal-byte (+ (position-bytes bol) n)) (eol (line-end-position))) @@ -1529,7 +1529,7 @@ encoding and Eglot will set this variable automatically.") (forward-char 1)))) (defun eglot-move-to-utf-32-linepos (n) - "Move to line's Nth code unit as computed by LSP's UTF-32 criterion." + "Move to line's Nth codepoint as computed by LSP's UTF-32 criterion." ;; We cannot use `move-to-column' here, because it moves to *visual* ;; columns, which can be different from LSP characters in case of ;; `whitespace-mode', `prettify-symbols-mode', etc. (github#296, From 75c65fcc98ef5bda8fe91aeb8ba25c03e3182b8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Sun, 26 Feb 2023 14:05:07 +0000 Subject: [PATCH 10/35] ; Fix last change bug#61726 * lisp/progmodes/eglot.el (eglot-current-linepos-function): Fix docstring. --- lisp/progmodes/eglot.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index ccd9cf3ee44..3d511126d93 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -1451,7 +1451,7 @@ CONNECT-ARGS are passed as additional arguments to 'eglot-current-column-function 'eglot-current-linepos-function "29.1") (defvar eglot-current-linepos-function #'eglot-utf-16-linepos - "Function calculating number of UTF-16 code units from line beginning. + "Function calculating number of code units from line beginning. This is the inverse operation of `eglot-move-to-linepos-function' (which see). It is a function of From 6c4abbab7999f55792a323e4bb1eb55ef5a7b990 Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Sun, 26 Feb 2023 15:40:30 +0100 Subject: [PATCH 11/35] Tramp: Do not unlock when connection is broken * lisp/net/tramp.el (tramp-handle-unlock-file): Do not unlock when connection is broken. (Bug#61663) * test/lisp/net/tramp-tests.el (tramp-test39-make-lock-file-name): Extend test. --- lisp/net/tramp.el | 8 +++++++- test/lisp/net/tramp-tests.el | 24 +++++++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index baa9f966dd8..2110d815c95 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -4778,7 +4778,13 @@ Do not set it manually, it is used buffer-local in `tramp-get-lock-pid'.") (defun tramp-handle-unlock-file (file) "Like `unlock-file' for Tramp files." - (when-let ((lockname (tramp-compat-make-lock-file-name file))) + ;; When there is no connection, we don't do it. Otherwise, + ;; functions like `kill-buffer' would try to reestablish the + ;; connection. See Bug#61663. + (when-let ((v (tramp-dissect-file-name file)) + (p (tramp-get-process v)) + ((process-live-p p)) + (lockname (tramp-compat-make-lock-file-name file))) (condition-case err (delete-file lockname) ;; `userlock--handle-unlock-error' exists since Emacs 28.1. diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index f19847b0103..69004bdbdf3 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -6535,11 +6535,33 @@ INPUT, if non-nil, is a string sent to the process." (save-buffer) (should-not (buffer-modified-p))) (should-not (with-no-warnings (file-locked-p tmp-name1))) + + ;; `kill-buffer' removes the lock. (with-no-warnings (lock-file tmp-name1)) (should (eq (with-no-warnings (file-locked-p tmp-name1)) t)) + (with-temp-buffer + (set-visited-file-name tmp-name1) + (insert "foo") + (should (buffer-modified-p)) + (cl-letf (((symbol-function #'read-from-minibuffer) + (lambda (&rest _args) "yes"))) + (kill-buffer))) + (should-not (with-no-warnings (file-locked-p tmp-name1))) + ;; `kill-buffer' should not remove the lock when the + ;; connection is broken. See Bug#61663. + (with-no-warnings (lock-file tmp-name1)) + (should (eq (with-no-warnings (file-locked-p tmp-name1)) t)) + (with-temp-buffer + (set-visited-file-name tmp-name1) + (insert "foo") + (should (buffer-modified-p)) + (tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password) + (cl-letf (((symbol-function #'read-from-minibuffer) + (lambda (&rest _args) "yes"))) + (kill-buffer))) ;; A new connection changes process id, and also the - ;; lockname contents. + ;; lockname contents. But the lock file still exists. (tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password) (should (stringp (with-no-warnings (file-locked-p tmp-name1)))) From 7c552be89da02270993f0866035abedb8c44f890 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 26 Feb 2023 16:48:07 +0200 Subject: [PATCH 12/35] ; Another doc fix in eglot.el * lisp/progmodes/eglot.el (eglot-current-linepos-function): Another doc fix. --- lisp/progmodes/eglot.el | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 3d511126d93..dd84f545ed4 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -1451,12 +1451,13 @@ CONNECT-ARGS are passed as additional arguments to 'eglot-current-column-function 'eglot-current-linepos-function "29.1") (defvar eglot-current-linepos-function #'eglot-utf-16-linepos - "Function calculating number of code units from line beginning. + "Function calculating position relative to line beginning. -This is the inverse operation of -`eglot-move-to-linepos-function' (which see). It is a function of -no arguments returning the number of code units corresponding to -the current position of point relative to line beginning.") +This is the inverse of `eglot-move-to-linepos-function' (which see). +It is a function of no arguments returning the number of code units +or bytes or codepoints corresponding to the current position of point, +relative to line beginning, as expected by the function that is the +value of `eglot-move-to-linepos-function'.") (defun eglot-utf-8-linepos () "Calculate number of UTF-8 bytes from line beginning." From dde9d149af3281f7ed3d3b9d8a4fd7caa238d0f9 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 26 Feb 2023 19:51:59 +0200 Subject: [PATCH 13/35] ; Improve documentation of loading *.eln files * doc/lispref/loading.texi (How Programs Do Loading): * doc/emacs/building.texi (Lisp Libraries): Some additional details about what happens with natively-compiled files. --- doc/emacs/building.texi | 37 +++++++++++++++++++++++++------------ doc/lispref/loading.texi | 25 ++++++++++++++----------- 2 files changed, 39 insertions(+), 23 deletions(-) diff --git a/doc/emacs/building.texi b/doc/emacs/building.texi index 3f6a418de1a..f82b605598e 100644 --- a/doc/emacs/building.texi +++ b/doc/emacs/building.texi @@ -1556,18 +1556,26 @@ command prompts for a @dfn{library name} rather than a file name; it searches through each directory in the Emacs Lisp load path, trying to find a file matching that library name. If the library name is @samp{@var{foo}}, it tries looking for files named -@file{@var{foo}.elc}, @file{@var{foo}.el}, and @file{@var{foo}}. The -default behavior is to load the first file found. This command -prefers @file{.elc} files over @file{.el} files because compiled files -load and run faster. If it finds that @file{@var{lib}.el} is newer -than @file{@var{lib}.elc}, it issues a warning, in case someone made -changes to the @file{.el} file and forgot to recompile it, but loads -the @file{.elc} file anyway. (Due to this behavior, you can save -unfinished edits to Emacs Lisp source files, and not recompile until -your changes are ready for use.) If you set the option -@code{load-prefer-newer} to a non-@code{nil} value, however, then -rather than the procedure described above, Emacs loads whichever -version of the file is newest. +@file{@var{foo}.elc}, @file{@var{foo}.el}, and @file{@var{foo}}. (If +Emacs was built with native compilation enabled, @code{load-library} +looks for a @samp{.eln} file that corresponds to @file{@var{foo}.el} +and loads it instead of @file{@var{foo}.elc}.) The default behavior +is to load the first file found. This command prefers @file{.eln} +files over @file{.elc} files, and prefers @file{.elc} files over +@file{.el} files, because compiled files load and run faster. If it +finds that @file{@var{lib}.el} is newer than @file{@var{lib}.elc}, it +issues a warning, in case someone made changes to the @file{.el} file +and forgot to recompile it, but loads the @file{.elc} file anyway. +(Due to this behavior, you can save unfinished edits to Emacs Lisp +source files, and not recompile until your changes are ready for use.) +If you set the option @code{load-prefer-newer} to a non-@code{nil} +value, however, then rather than the procedure described above, Emacs +loads whichever version of the file is newest. If Emacs was built +with native compilation, and it cannot find the @samp{.eln} file +corresponding to @file{@var{lib}.el}, it will load a +@file{@var{lib}.elc} and start native compilation of +@file{@var{lib}.el} in the background, then load the @samp{.eln} file +when it finishes compilation. Emacs Lisp programs usually load Emacs Lisp files using the @code{load} function. This is similar to @code{load-library}, but is @@ -1604,6 +1612,11 @@ It is customary to put locally installed libraries in the @code{load-path}, or in some subdirectory of @file{site-lisp}. This way, you don't need to modify the default value of @code{load-path}. +@vindex native-comp-eln-load-path + Similarly to @code{load-path}, the list of directories where Emacs +looks for @file{*.eln} files with natively-compiled Lisp code is +specified by the variable @code{native-comp-eln-load-path}. + @cindex autoload Some commands are @dfn{autoloaded}; when you run them, Emacs automatically loads the associated library first. For instance, the diff --git a/doc/lispref/loading.texi b/doc/lispref/loading.texi index dbbdc767738..5c84ba4b1eb 100644 --- a/doc/lispref/loading.texi +++ b/doc/lispref/loading.texi @@ -75,17 +75,20 @@ file exists, and Emacs was compiled with native-compilation support (@pxref{Native Compilation}), @code{load} attempts to find a corresponding @samp{.eln} file, and if found, loads it instead of @file{@var{filename}.elc}. Otherwise, it loads -@file{@var{filename}.elc}. If there is no file by that name, then -@code{load} looks for a file named @file{@var{filename}.el}. If that -file exists, it is loaded. If Emacs was compiled with support for -dynamic modules (@pxref{Dynamic Modules}), @code{load} next looks for -a file named @file{@var{filename}.@var{ext}}, where @var{ext} is a -system-dependent file-name extension of shared libraries. Finally, if -neither of those names is found, @code{load} looks for a file named -@var{filename} with nothing appended, and loads it if it exists. (The -@code{load} function is not clever about looking at @var{filename}. -In the perverse case of a file named @file{foo.el.el}, evaluation of -@code{(load "foo.el")} will indeed find it.) +@file{@var{filename}.elc} (and starts a background native compilation +to produce the missing @samp{.eln} file, followed by loading that +file). If there is no @file{@var{filename}.elc}, then @code{load} +looks for a file named @file{@var{filename}.el}. If that file exists, +it is loaded. If Emacs was compiled with support for dynamic modules +(@pxref{Dynamic Modules}), @code{load} next looks for a file named +@file{@var{filename}.@var{ext}}, where @var{ext} is a system-dependent +file-name extension of shared libraries (@samp{.so} on GNU and Unix +systems). Finally, if neither of those names is found, @code{load} +looks for a file named @var{filename} with nothing appended, and loads +it if it exists. (The @code{load} function is not clever about +looking at @var{filename}. In the perverse case of a file named +@file{foo.el.el}, evaluation of @code{(load "foo.el")} will indeed +find it.) If Auto Compression mode is enabled, as it is by default, then if @code{load} can not find a file, it searches for a compressed version From 0fde314f6f6e6664cddab1b2f0fe20629cd39d14 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 26 Feb 2023 20:03:20 +0200 Subject: [PATCH 14/35] * lib-src/etags.c (process_file_name): Free malloc'ed vars (bug#61819). --- lib-src/etags.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib-src/etags.c b/lib-src/etags.c index 9fb9e312a66..0b048748602 100644 --- a/lib-src/etags.c +++ b/lib-src/etags.c @@ -1732,6 +1732,8 @@ process_file_name (char *file, language *lang) char *cmd = xmalloc (buf_len); snprintf (cmd, buf_len, "%s %s > %s", compr->command, new_real_name, new_tmp_name); + free (new_real_name); + free (new_tmp_name); #endif inf = (system (cmd) == -1 ? NULL From 267fc6d00c4db6f20da3c2d63e48a71ab70505d3 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Mon, 27 Feb 2023 02:05:56 +0200 Subject: [PATCH 15/35] ruby-smie-rules: Fix misindentation of a method call after assignment * lisp/progmodes/ruby-mode.el (ruby-smie-rules): Fix indentation of a method call after assignment with ruby-after-operator-indent=nil (bug#61822). * test/lisp/progmodes/ruby-mode-resources/ruby-after-operator-indent.rb: Add corresponding example. --- lisp/progmodes/ruby-mode.el | 4 +++- .../ruby-mode-resources/ruby-after-operator-indent.rb | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index dba9ff0a846..559b62fef54 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el @@ -909,7 +909,9 @@ This only affects the output of the command `ruby-toggle-block'." "<<=" ">>=" "&&=" "||=" "and" "or")) (cond ((not ruby-after-operator-indent) - (ruby-smie--indent-to-stmt ruby-indent-level)) + (ruby-smie--indent-to-stmt (if (smie-indent--hanging-p) + ruby-indent-level + 0))) ((and (smie-rule-parent-p ";" nil) (smie-indent--hanging-p)) ruby-indent-level))) diff --git a/test/lisp/progmodes/ruby-mode-resources/ruby-after-operator-indent.rb b/test/lisp/progmodes/ruby-mode-resources/ruby-after-operator-indent.rb index 25cd8736f97..e339d229d3e 100644 --- a/test/lisp/progmodes/ruby-mode-resources/ruby-after-operator-indent.rb +++ b/test/lisp/progmodes/ruby-mode-resources/ruby-after-operator-indent.rb @@ -10,6 +10,10 @@ foo = obj.bar { |m| tee(m) } + obj.qux { |m| hum(m) } +some_variable = abc + some_method( + some_argument +) + foo. bar .baz From 0f15286c5396e3415e0f40c21b6f6d7554f46a5e Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Sun, 26 Feb 2023 18:05:13 -0800 Subject: [PATCH 16/35] New tree-sitter indent anchor standalone-parent used by c-ts-mode When writing c-ts-mode Theo used parent-bol which works well except one case: 1 for (int i=0; 2 i < 5; 3 i++) { 4 func(i); 5 } In this case, when indenting "func(i)", parent-bol returns the start of "i++" on line 3, instead of the "correct" anchor, the start of "for" on line 1. parent-bol would have worked if the "for (...) {" part is in one line. To support this case I tried numerous things and added a bunch of stuff, culminating in c-ts-common-statement-offset. It's complicated, requires extra setup, and slow. Not anymore! I think the new anchor standalone-parent really captures the logic behind how people expect indentation to work. It's simple and fast, and requires no setup. * doc/lispref/modes.texi (Parser-based Indentation): Update manual. * lisp/progmodes/c-ts-mode.el: (c-ts-mode--standalone-grandparent): New anchor. (c-ts-mode--indent-styles): Replace c-ts-common-statement-offset with standalone-parent. (c-ts-base-mode): Add comment. * lisp/treesit.el: (treesit-simple-indent-presets): New anchor standalone-parent. --- doc/lispref/modes.texi | 10 +++++++++- lisp/progmodes/c-ts-mode.el | 32 ++++++++++++++++++++------------ lisp/treesit.el | 15 +++++++++++++++ 3 files changed, 44 insertions(+), 13 deletions(-) diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi index 4c40f414ca0..11892aaa40e 100644 --- a/doc/lispref/modes.texi +++ b/doc/lispref/modes.texi @@ -5093,7 +5093,15 @@ This anchor is a function that is called with 3 arguments: @var{node}, @item parent-bol This anchor is a function that is called with 3 arguments: @var{node}, @var{parent}, and @var{bol}, and returns the first non-space character -on the line of @var{parent}. +on the line which @var{parent}'s start is on. + +@item parent-bol +This anchor is a function that is called with 3 arguments: @var{node}, +@var{parent}, and @var{bol}. It finds the first ancestor node +(parent, grandparent, etc) of @var{node} that starts on its own line, +and return the start of that node. ``Starting on its own line'' means +there is only whitespace character before the node on the line which +the node's start is on. @item prev-sibling This anchor is a function that is called with 3 arguments: @var{node}, diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 041461f220a..2c79cf46308 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -279,6 +279,12 @@ doesn't have a child." ;; prev-sibling doesn't have a child. (treesit-node-start prev-sibling))) +(defun c-ts-mode--standalone-grandparent (_node parent bol &rest args) + "Like the standalone-parent anchor but pass it the grandparent. +PARENT, BOL, ARGS are the same as other anchor functions." + (apply (alist-get 'standalone-parent treesit-simple-indent-presets) + parent (treesit-node-parent parent) bol args)) + (defun c-ts-mode--indent-styles (mode) "Indent rules supported by `c-ts-mode'. MODE is either `c' or `cpp'." @@ -300,9 +306,9 @@ MODE is either `c' or `cpp'." ((parent-is "comment") prev-adaptive-prefix 0) ;; Labels. - ((node-is "labeled_statement") parent-bol 0) + ((node-is "labeled_statement") standalone-parent 0) ((parent-is "labeled_statement") - point-min c-ts-common-statement-offset) + c-ts-mode--standalone-grandparent c-ts-mode-indent-offset) ((node-is "preproc") point-min 0) ((node-is "#endif") point-min 0) @@ -330,7 +336,7 @@ MODE is either `c' or `cpp'." ;; Closing bracket. This should be before initializer_list ;; (and probably others) rule because that rule (and other ;; similar rules) will match the closing bracket. (Bug#61398) - ((node-is "}") point-min c-ts-common-statement-offset) + ((node-is "}") standalone-parent 0) ,@(when (eq mode 'cpp) '(((node-is "access_specifier") parent-bol 0) ;; Indent the body of namespace definitions. @@ -341,25 +347,25 @@ MODE is either `c' or `cpp'." ((match nil "initializer_list" nil 1 1) parent-bol c-ts-mode-indent-offset) ((match nil "initializer_list" nil 2) c-ts-mode--anchor-prev-sibling 0) ;; Statement in enum. - ((match nil "enumerator_list" nil 1 1) point-min c-ts-common-statement-offset) + ((match nil "enumerator_list" nil 1 1) standalone-parent c-ts-mode-indent-offset) ((match nil "enumerator_list" nil 2) c-ts-mode--anchor-prev-sibling 0) ;; Statement in struct and union. - ((match nil "field_declaration_list" nil 1 1) point-min c-ts-common-statement-offset) + ((match nil "field_declaration_list" nil 1 1) standalone-parent c-ts-mode-indent-offset) ((match nil "field_declaration_list" nil 2) c-ts-mode--anchor-prev-sibling 0) ;; Statement in {} blocks. - ((match nil "compound_statement" nil 1 1) point-min c-ts-common-statement-offset) + ((match nil "compound_statement" nil 1 1) standalone-parent c-ts-mode-indent-offset) ((match nil "compound_statement" nil 2) c-ts-mode--anchor-prev-sibling 0) ;; Opening bracket. - ((node-is "compound_statement") point-min c-ts-common-statement-offset) + ((node-is "compound_statement") standalone-parent c-ts-mode-indent-offset) ;; Bug#61291. - ((match "expression_statement" nil "body") point-min c-ts-common-statement-offset) + ((match "expression_statement" nil "body") standalone-parent c-ts-mode-indent-offset) ;; These rules are for cases where the body is bracketless. ;; Tested by the "Bracketless Simple Statement" test. - ((parent-is "if_statement") point-min c-ts-common-statement-offset) - ((parent-is "for_statement") point-min c-ts-common-statement-offset) - ((parent-is "while_statement") point-min c-ts-common-statement-offset) - ((parent-is "do_statement") point-min c-ts-common-statement-offset) + ((parent-is "if_statement") standalone-parent c-ts-mode-indent-offset) + ((parent-is "for_statement") standalone-parent c-ts-mode-indent-offset) + ((parent-is "while_statement") standalone-parent c-ts-mode-indent-offset) + ((parent-is "do_statement") standalone-parent c-ts-mode-indent-offset) ,@(when (eq mode 'cpp) `(((node-is "field_initializer_list") parent-bol ,(* c-ts-mode-indent-offset 2))))))) @@ -836,6 +842,8 @@ the semicolon. This function skips the semicolon." (when (eq c-ts-mode-indent-style 'linux) (setq-local indent-tabs-mode t)) (setq-local c-ts-common-indent-offset 'c-ts-mode-indent-offset) + ;; This setup is not needed anymore, but we might find uses for it + ;; later, so I'm keeping it. (setq-local c-ts-common-indent-type-regexp-alist `((block . ,(rx (or "compound_statement" "field_declaration_list" diff --git a/lisp/treesit.el b/lisp/treesit.el index 1decfc3d7cf..6b4db2a990c 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -1227,6 +1227,16 @@ See `treesit-simple-indent-presets'.") (goto-char (treesit-node-start parent)) (back-to-indentation) (point)))) + (cons 'standalone-parent + (lambda (_n parent &rest _) + (save-excursion + (catch 'term + (while parent + (goto-char (treesit-node-start parent)) + (when (looking-back (rx bol (* whitespace)) + (line-beginning-position)) + (throw 'term (point))) + (setq parent (treesit-node-parent parent))))))) (cons 'prev-sibling (lambda (node &rest _) (treesit-node-start (treesit-node-prev-sibling node)))) @@ -1323,6 +1333,11 @@ parent-bol Returns the beginning of non-space characters on the line where PARENT is on. +standalone-parent + + Finds the first ancestor node (parent, grandparent, etc) that + starts on its own line, and return the start of that node. + prev-sibling Returns the start of NODE's previous sibling. From edf5b97686908114f254b5077c71e8202149545f Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Sun, 26 Feb 2023 18:24:49 -0800 Subject: [PATCH 17/35] Simplify c-ts-mode--top-level-label-matcher * lisp/progmodes/c-ts-mode.el: (c-ts-mode--top-level-label-matcher): Make more assumptions and remove the loop, so it's faster in large files. --- lisp/progmodes/c-ts-mode.el | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 2c79cf46308..befc0cf5643 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -394,16 +394,13 @@ MODE is either `c' or `cpp'." ((parent-is "do_statement") parent-bol 0) ,@common)))) -(defun c-ts-mode--top-level-label-matcher (node &rest _) +(defun c-ts-mode--top-level-label-matcher (node parent &rest _) "A matcher that matches a top-level label. -NODE should be a labeled_statement." - (let ((func (treesit-parent-until - node (lambda (n) - (equal (treesit-node-type n) - "compound_statement"))))) - (and (equal (treesit-node-type node) - "labeled_statement") - (not (treesit-node-top-level func "compound_statement"))))) +NODE should be a labeled_statement. PARENT is its parent." + (and (equal (treesit-node-type node) + "labeled_statement") + (equal "function_definition" + (treesit-node-type (treesit-node-parent parent))))) ;;; Font-lock From aee10ca1cbee1d653f89f028c34066bf3ebb32ab Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Mon, 27 Feb 2023 00:14:32 -0800 Subject: [PATCH 18/35] Adjust tree-sitter defun navigation (bug#61617) Before this change, when you use a tree-sitter navigation function to move to the next beginning of a thing, it jumps over the immediate next thing and lands you at the beginning of the next-next thing. Eg, when point is at the "|", and we evaluate (treesit--navigate-thing pos 1 'beg), we go from | (thing) (thing) to (thing) |(thing) But some might expect point to go to |(thing) (thing) instead, which makes sense. Also, that's how Emacs expect defun navigation functions to work. The discrepancy in expectation causes bug#61617. In this change I made tree-sitter navigation functions to work as what Emacs expects. And what I described for moving to the next beginning of thing is similarly applicable to moving to the end of previous end of thing. * lisp/treesit.el (treesit-beginning-of-defun) (treesit-end-of-defun): Handle the case where defun-skipper moves point back to where we started, by adding a retry. (treesit--navigate-thing): Add a single condition checking for progress to the condition form responsible for checking whether to skip the next defun. Namely (eq pos (funcall advance next)))). * test/src/treesit-tests.el: (treesit--ert-defun-navigation-nested-master) (treesit--ert-defun-navigation-top-level-master): Change tests to reflect the new expectation. --- lisp/treesit.el | 73 ++++++++++++++++++++++++++++----------- test/src/treesit-tests.el | 32 ++++++++--------- 2 files changed, 68 insertions(+), 37 deletions(-) diff --git a/lisp/treesit.el b/lisp/treesit.el index 6b4db2a990c..052f641abfd 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -1828,10 +1828,23 @@ This is a tree-sitter equivalent of `beginning-of-defun'. Behavior of this function depends on `treesit-defun-type-regexp' and `treesit-defun-skipper'." (interactive "^p") - (when (treesit-beginning-of-thing treesit-defun-type-regexp arg) - (when treesit-defun-skipper - (funcall treesit-defun-skipper)) - t)) + (let ((orig-point (point)) + (success nil)) + (catch 'done + (dotimes (_ 2) + + (when (treesit-beginning-of-thing treesit-defun-type-regexp arg) + (when treesit-defun-skipper + (funcall treesit-defun-skipper) + (setq success t))) + + ;; If we end up at the same point, it means we went to the + ;; next beg-of-defun, but defun skipper moved point back to + ;; where we started, in this case we just move one step + ;; further. + (if (or (eq arg 0) (not (eq orig-point (point)))) + (throw 'done success) + (setq arg (if (> arg 0) (1+ arg) (1- arg)))))))) (defun treesit-end-of-defun (&optional arg _) "Move forward to next end of defun. @@ -1843,9 +1856,21 @@ This is a tree-sitter equivalent of `end-of-defun'. Behavior of this function depends on `treesit-defun-type-regexp' and `treesit-defun-skipper'." (interactive "^p\nd") - (when (treesit-end-of-thing treesit-defun-type-regexp arg) - (when treesit-defun-skipper - (funcall treesit-defun-skipper)))) + (let ((orig-point (point))) + (catch 'done + (dotimes (_ 2) ; Not making progress is better than infloop. + + (when (treesit-end-of-thing treesit-defun-type-regexp arg) + (when treesit-defun-skipper + (funcall treesit-defun-skipper))) + + ;; If we end up at the same point, it means we went to the + ;; prev end-of-defun, but defun skipper moved point back to + ;; where we started, in this case we just move one step + ;; further. + (if (or (eq arg 0) (not (eq orig-point (point)))) + (throw 'done nil) + (setq arg (if (> arg 0) (1+ arg) (1- arg)))))))) (defun treesit-default-defun-skipper () "Skips spaces after navigating a defun. @@ -1967,9 +1992,9 @@ REGEXP and PRED are the same as in `treesit-thing-at-point'." ;; ;; prev-end (tricky): ;; 1. prev-sibling exists -;; -> If you think about it, we are already at prev-sibling's end! -;; So we need to go one step further, either to -;; prev-prev-sibling's end, or parent's prev-sibling's end, etc. +;; -> If we are already at prev-sibling's end, we need to go one +;; step further, either to prev-prev-sibling's end, or parent's +;; prev-sibling's end, etc. ;; 2. prev-sibling is nil but parent exists ;; -> Obviously we don't want to go to parent's end, instead, we ;; want to go to parent's prev-sibling's end. Again, we recurse @@ -2019,18 +2044,24 @@ function is called recursively." ;; ...forward. (if (and (eq side 'beg) ;; Should we skip the defun (recurse)? - (cond (next (not recursing)) ; [1] (see below) - (parent t) ; [2] - (t nil))) - ;; Special case: go to next beg-of-defun. Set POS - ;; to the end of next-sib/parent defun, and run one - ;; more step. If there is a next-sib defun, we only - ;; need to recurse once, so we don't need to recurse - ;; if we are already recursing [1]. If there is no + (cond (next (and (not recursing) ; [1] (see below) + (eq pos (funcall advance next)))) + (parent t))) ; [2] + ;; Special case: go to next beg-of-defun, but point + ;; is already on beg-of-defun. Set POS to the end + ;; of next-sib/parent defun, and run one more step. + ;; If there is a next-sib defun, we only need to + ;; recurse once, so we don't need to recurse if we + ;; are already recursing [1]. If there is no ;; next-sib but a parent, keep stepping out ;; (recursing) until we got out of the parents until ;; (1) there is a next sibling defun, or (2) no more ;; parents [2]. + ;; + ;; If point on beg-of-defun but we are already + ;; recurring, that doesn't count as special case, + ;; because we have already made progress (by moving + ;; the end of next before recurring.) (setq pos (or (treesit--navigate-thing (treesit-node-end (or next parent)) 1 'beg regexp pred t) @@ -2039,9 +2070,9 @@ function is called recursively." (setq pos (funcall advance (or next parent)))) ;; ...backward. (if (and (eq side 'end) - (cond (prev (not recursing)) - (parent t) - (t nil))) + (cond (prev (and (not recursing) + (eq pos (funcall advance prev)))) + (parent t))) ;; Special case: go to prev end-of-defun. (setq pos (or (treesit--navigate-thing (treesit-node-start (or prev parent)) diff --git a/test/src/treesit-tests.el b/test/src/treesit-tests.el index 5aa12e8aa0e..468cd221ef9 100644 --- a/test/src/treesit-tests.el +++ b/test/src/treesit-tests.el @@ -977,22 +977,22 @@ and \"]\"." (defvar treesit--ert-defun-navigation-nested-master ;; START PREV-BEG NEXT-END PREV-END NEXT-BEG - '((0 103 105 102 106) ; Between Beg of parent & 1st sibling. + '((0 103 105 102 104) ; Between Beg of parent & 1st sibling. (1 103 105 102 106) ; Beg of 1st sibling. (2 104 105 102 106) ; Inside 1st sibling. - (3 104 107 102 109) ; End of 1st sibling. - (4 104 107 102 109) ; Between 1st sibling & 2nd sibling. - (5 104 107 102 109) ; Beg of 2nd sibling. + (3 104 107 102 106) ; End of 1st sibling. + (4 104 107 105 106) ; Between 1st sibling & 2nd sibling. + (5 104 107 105 109) ; Beg of 2nd sibling. (6 106 107 105 109) ; Inside 2nd sibling. (7 106 108 105 109) ; End of 2nd sibling. - (8 106 108 105 109) ; Between 2nd sibling & end of parent. - (9 103 110 102 nil) ; End of parent. + (8 106 108 107 109) ; Between 2nd sibling & end of parent. + (9 103 110 102 109) ; End of parent. - (100 nil 102 nil 103) ; Before 1st parent. + (100 nil 102 nil 101) ; Before 1st parent. (101 nil 102 nil 103) ; Beg of 1st parent. - (102 101 108 nil 109) ; Between 1st & 2nd parent. - (103 101 108 nil 109) ; Beg of 2nd parent. - (110 109 nil 108 nil) ; After 3rd parent. + (102 101 108 102 103) ; Between 1st & 2nd parent. + (103 101 108 102 109) ; Beg of 2nd parent. + (110 109 nil 110 nil) ; After 3rd parent. ) "Master of nested navigation test. @@ -1000,7 +1000,7 @@ This basically says, e.g., \"start with point on marker 0, go to the prev-beg, now point should be at marker 103\", etc.") (defvar treesit--ert-defun-navigation-top-level-master - ;; START PREV-BEG NEXT-END NEXT-BEG PREV-END + ;; START PREV-BEG NEXT-END PREV-END NEXT-BEG '((0 103 108 102 109) ; Between Beg of parent & 1st sibling. (1 103 108 102 109) ; Beg of 1st sibling. (2 103 108 102 109) ; Inside 1st sibling. @@ -1010,14 +1010,14 @@ the prev-beg, now point should be at marker 103\", etc.") (6 103 108 102 109) ; Inside 2nd sibling. (7 103 108 102 109) ; End of 2nd sibling. (8 103 108 102 109) ; Between 2nd sibling & end of parent. - (9 103 110 102 nil) ; End of parent. + (9 103 110 102 109) ; End of parent. ;; Top-level defuns should be identical to the nested test. - (100 nil 102 nil 103) ; Before 1st parent. + (100 nil 102 nil 101) ; Before 1st parent. (101 nil 102 nil 103) ; Beg of 1st parent. - (102 101 108 nil 109) ; Between 1st & 2nd parent. - (103 101 108 nil 109) ; Beg of 2nd parent. - (110 109 nil 108 nil) ; After 3rd parent. + (102 101 108 102 103) ; Between 1st & 2nd parent. + (103 101 108 102 109) ; Beg of 2nd parent. + (110 109 nil 110 nil) ; After 3rd parent. ) "Master of top-level navigation test.") From 434ab2e08895bdf952de78aea285da33be63c954 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= Date: Sun, 26 Feb 2023 14:34:58 +0100 Subject: [PATCH 19/35] Improve delete-consecutive-dups doc precision and add test * lisp/subr.el (delete-consecutive-dups): Document which element of each run is retained (the earliest in the list). This matters because it makes it safe to ignore the return value. * test/lisp/subr-tests.el (subr--delete-dups) (subr--delete-consecutive-dups): Add tests. --- lisp/subr.el | 4 +++- test/lisp/subr-tests.el | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/lisp/subr.el b/lisp/subr.el index 916b6de494b..ef2f63f7c37 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -768,7 +768,9 @@ one is kept. See `seq-uniq' for non-destructive operation." (defun delete-consecutive-dups (list &optional circular) "Destructively remove `equal' consecutive duplicates from LIST. First and last elements are considered consecutive if CIRCULAR is -non-nil." +non-nil. +Of several consecutive `equal' occurrences, the one earliest in +the list is kept." (let ((tail list) last) (while (cdr tail) (if (equal (car tail) (cadr tail)) diff --git a/test/lisp/subr-tests.el b/test/lisp/subr-tests.el index d5efabc1370..050ee22ac18 100644 --- a/test/lisp/subr-tests.el +++ b/test/lisp/subr-tests.el @@ -1171,5 +1171,39 @@ final or penultimate step during initialization.")) (should-not (list-of-strings-p '("a" nil "b"))) (should-not (list-of-strings-p '("a" "b" . "c")))) +(ert-deftest subr--delete-dups () + (should (equal (delete-dups nil) nil)) + (let* ((a (list "a" "b" "c")) + (a-dedup (delete-dups a))) + (should (equal a-dedup '("a" "b" "c"))) + (should (eq a a-dedup))) + (let* ((a (list "a" "a" "b" "b" "a" "c" "b" "c" "a")) + (a-b (cddr a)) ; link of first "b" + (a-dedup (delete-dups a))) + (should (equal a-dedup '("a" "b" "c"))) + (should (eq a a-dedup)) + (should (eq (cdr a-dedup) a-b)))) + +(ert-deftest subr--delete-consecutive-dups () + (should (equal (delete-consecutive-dups nil) nil)) + (let* ((a (list "a" "b" "c")) + (a-dedup (delete-consecutive-dups a))) + (should (equal a-dedup '("a" "b" "c"))) + (should (eq a a-dedup))) + (let* ((a (list "a" "a" "b" "a" "a" "b" "b" "b" "c" "c" "a" "a")) + (a-b (nthcdr 3 a)) ; link of third "a" + (a-dedup (delete-consecutive-dups a))) + (should (equal a-dedup '("a" "b" "a" "b" "c" "a"))) + (should (eq a a-dedup)) + (should (equal (nthcdr 2 a-dedup) a-b))) + (let* ((a (list "a" "b" "a")) + (a-dedup (delete-consecutive-dups a t))) + (should (equal a-dedup '("a" "b"))) + (should (eq a a-dedup))) + (let* ((a (list "a" "a" "b" "a" "a" "b" "b" "b" "c" "c" "a" "a")) + (a-dedup (delete-consecutive-dups a t))) + (should (equal a-dedup '("a" "b" "a" "b" "c"))) + (should (eq a a-dedup)))) + (provide 'subr-tests) ;;; subr-tests.el ends here From 10d2b76edadb6575545433ea6183c4d8e8588191 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= Date: Mon, 27 Feb 2023 10:40:11 +0100 Subject: [PATCH 20/35] * lisp/calc/calc.el (calcDigit-backspace): Hush warning. --- lisp/calc/calc.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lisp/calc/calc.el b/lisp/calc/calc.el index 1da4f9ad738..a1545edba19 100644 --- a/lisp/calc/calc.el +++ b/lisp/calc/calc.el @@ -2482,7 +2482,8 @@ the United States." (interactive) (cond ((eq last-command 'calcDigit-start) (erase-buffer)) - (t (backward-delete-char 1))) + (t (with-suppressed-warnings ((interactive-only backward-delete-char)) + (backward-delete-char 1)))) (if (= (calc-minibuffer-size) 0) (progn (setq last-command-event 13) From 9d0f856a167040e66ad4bef5699e24552a6bc3c4 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Mon, 27 Feb 2023 13:31:47 +0200 Subject: [PATCH 21/35] Fix description of 'desktop-save-mode' * doc/emacs/misc.texi (Saving Emacs Sessions): Adjust to changes in 'desktop-path'. Reported by Petteri Hintsanen . --- doc/emacs/misc.texi | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi index acabce57223..171544fc983 100644 --- a/doc/emacs/misc.texi +++ b/doc/emacs/misc.texi @@ -2748,10 +2748,12 @@ desktop reloading, since it bypasses the init file, where @findex desktop-revert You can have separate saved desktop configurations in different directories; starting Emacs from a directory where you have a saved -desktop configuration will restore that configuration. You can save -the current desktop and reload the one saved in another directory by -typing @kbd{M-x desktop-change-dir}. Typing @kbd{M-x desktop-revert} -reverts to the previously reloaded desktop. +desktop configuration will restore that configuration, provided that +you customize @code{desktop-path} to prepend @file{.} (the current +directory) to the other directories there. You can save the current +desktop and reload the one saved in another directory by typing +@kbd{M-x desktop-change-dir}. Typing @kbd{M-x desktop-revert} reverts +to the previously reloaded desktop. @vindex desktop-load-locked-desktop The file in which Emacs saves the desktop is locked while the From 647e40f4a0cf2c653d6ff6fc32116cbd2104d6ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Mon, 27 Feb 2023 11:04:44 +0000 Subject: [PATCH 22/35] ; And yet another fix to eglot-current-linepos-function's docstring bug#61726 * lisp/progmodes/eglot.el (eglot-current-linepos-function): Another fix. --- lisp/progmodes/eglot.el | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index dd84f545ed4..32f78f89c0a 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -1453,11 +1453,15 @@ CONNECT-ARGS are passed as additional arguments to (defvar eglot-current-linepos-function #'eglot-utf-16-linepos "Function calculating position relative to line beginning. -This is the inverse of `eglot-move-to-linepos-function' (which see). -It is a function of no arguments returning the number of code units -or bytes or codepoints corresponding to the current position of point, -relative to line beginning, as expected by the function that is the -value of `eglot-move-to-linepos-function'.") +It is a function of no arguments considering the text from line +beginning up to current point. The return value is the number of +UTF code units needed to encode that text from the LSP server's +perspective. This may be a number of octets, 16-bit words or +Unicode code points, depending on whether the LSP server's +`positionEncoding' capability is UTF-8, UTF-16 or UTF-32, +respectively. Position of point should remain unaltered if that +return value is fed through the corresponding inverse function +`eglot-move-to-linepos-function' (which see).") (defun eglot-utf-8-linepos () "Calculate number of UTF-8 bytes from line beginning." From 3d0a6c9baa613d69d75c3b2644e033a21da5f096 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Mon, 27 Feb 2023 11:29:32 +0000 Subject: [PATCH 23/35] Eglot: protect against unintended field text motion (bug#61726) Suggested-by: Augusto Stoffel * lisp/progmodes/eglot.el (eglot--bol): New helper. (eglot-utf-8-linepos, eglot-utf-16-linepos) (eglot-utf-32-linepos, eglot-move-to-utf-8-linepos) (eglot-move-to-utf-16-linepos, eglot-move-to-utf-32-linepos) (eglot-handle-notification, eglot--xref-make-match) (eglot-completion-at-point): Use it. --- lisp/progmodes/eglot.el | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 32f78f89c0a..719b3abe4cb 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -1440,6 +1440,12 @@ CONNECT-ARGS are passed as additional arguments to (let ((warning-minimum-level :error)) (display-warning 'eglot (apply #'format format args) :warning))) +(defalias 'eglot--bol + (if (fboundp 'pos-bol) #'pos-bol + (lambda (&optional n) (let ((inhibit-field-text-motion t)) + (line-beginning-position n)))) + "Return position of first character in current line.") + ;;; Encoding fever ;;; @@ -1465,13 +1471,12 @@ return value is fed through the corresponding inverse function (defun eglot-utf-8-linepos () "Calculate number of UTF-8 bytes from line beginning." - (length (encode-coding-region (line-beginning-position) (point) - 'utf-8-unix t))) + (length (encode-coding-region (eglot--bol) (point) 'utf-8-unix t))) (defun eglot-utf-16-linepos (&optional lbp) "Calculate number of UTF-16 code units from position given by LBP. -LBP defaults to `line-beginning-position'." - (/ (- (length (encode-coding-region (or lbp (line-beginning-position)) +LBP defaults to `eglot--bol'." + (/ (- (length (encode-coding-region (or lbp (eglot--bol)) ;; Fix github#860 (min (point) (point-max)) 'utf-16 t)) 2) @@ -1479,7 +1484,7 @@ LBP defaults to `line-beginning-position'." (defun eglot-utf-32-linepos () "Calculate number of Unicode codepoints from line beginning." - (- (point) (line-beginning-position))) + (- (point) (eglot--bol))) (defun eglot--pos-to-lsp-position (&optional pos) "Convert point POS to LSP position." @@ -1513,7 +1518,7 @@ encoding and Eglot will set this variable automatically.") (defun eglot-move-to-utf-8-linepos (n) "Move to line's Nth byte as computed by LSP's UTF-8 criterion." - (let* ((bol (line-beginning-position)) + (let* ((bol (eglot--bol)) (goal-byte (+ (position-bytes bol) n)) (eol (line-end-position))) (goto-char bol) @@ -1524,7 +1529,7 @@ encoding and Eglot will set this variable automatically.") (defun eglot-move-to-utf-16-linepos (n) "Move to line's Nth code unit as computed by LSP's UTF-16 criterion." - (let* ((bol (line-beginning-position)) + (let* ((bol (eglot--bol)) (goal-char (+ bol n)) (eol (line-end-position))) (goto-char bol) @@ -1539,8 +1544,7 @@ encoding and Eglot will set this variable automatically.") ;; columns, which can be different from LSP characters in case of ;; `whitespace-mode', `prettify-symbols-mode', etc. (github#296, ;; github#297) - (goto-char (min (+ (line-beginning-position) n) - (line-end-position)))) + (goto-char (min (+ (eglot--bol) n) (line-end-position)))) (defun eglot--lsp-position-to-point (pos-plist &optional marker) "Convert LSP position POS-PLIST to Emacs point. @@ -2190,7 +2194,7 @@ COMMAND is a symbol naming the command." (eglot--widening (goto-char (point-min)) (setq beg - (line-beginning-position + (eglot--bol (1+ (plist-get (plist-get range :start) :line)))) (setq end (line-end-position @@ -2630,7 +2634,7 @@ Try to visit the target file for a richer summary line." (collect (lambda () (eglot--widening (pcase-let* ((`(,beg . ,end) (eglot--range-region range)) - (bol (progn (goto-char beg) (line-beginning-position))) + (bol (progn (goto-char beg) (eglot--bol))) (substring (buffer-substring bol (line-end-position))) (hi-beg (- beg bol)) (hi-end (- (min (line-end-position) end) bol))) @@ -2981,7 +2985,7 @@ for which LSP on-type-formatting should be requested." (looking-back (regexp-opt (cl-coerce (cl-getf completion-capability :triggerCharacters) 'list)) - (line-beginning-position)))) + (eglot--bol)))) :exit-function (lambda (proxy status) (when (memq status '(finished exact)) From 6c7078c66f429d8fa43aa7416ee7bb07b0e81386 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Mon, 27 Feb 2023 14:11:13 +0200 Subject: [PATCH 24/35] ; * lisp/progmodes/c-ts-mode.el (treesit-node-prev-sibling): Declare. --- lisp/progmodes/c-ts-mode.el | 1 + 1 file changed, 1 insertion(+) diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index befc0cf5643..2cb6c2709cc 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -77,6 +77,7 @@ (declare-function treesit-node-child "treesit.c") (declare-function treesit-node-child-by-field-name "treesit.c") (declare-function treesit-node-type "treesit.c") +(declare-function treesit-node-prev-sibling "treesit.c") ;;; Custom variables From 44949c292f9133025b1a895bee622d74078255dd Mon Sep 17 00:00:00 2001 From: Arash Esbati Date: Mon, 27 Feb 2023 10:10:13 +0100 Subject: [PATCH 25/35] ; Add `nnimap-user' to Gnus manual * doc/misc/gnus.texi (Customizing the IMAP Connection): Document backend variable `nnimap-user' which was introduced with commit 5e68f8614f in 2011. Add index entries for all backend variables. (bug#61837) --- doc/misc/gnus.texi | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi index d513726979b..cf6820948ad 100644 --- a/doc/misc/gnus.texi +++ b/doc/misc/gnus.texi @@ -14510,13 +14510,23 @@ Here's an example method that's more complex: @table @code @item nnimap-address +@vindex nnimap-address The address of the server, like @samp{imap.gmail.com}. +@item nnimap-user +@vindex nnimap-user +Username to use for authentication to the @acronym{IMAP} server. This +corresponds to the value of the @samp{login} token in your +@file{~/.authinfo} file. Set this variable if you want to access +multiple accounts from the same @acronym{IMAP} server. + @item nnimap-server-port +@vindex nnimap-server-port If the server uses a non-standard port, that can be specified here. A typical port would be @code{"imap"} or @code{"imaps"}. @item nnimap-stream +@vindex nnimap-stream How @code{nnimap} should connect to the server. Possible values are: @table @code @@ -14547,6 +14557,7 @@ Non-encrypted and unsafe straight socket connection. @end table @item nnimap-authenticator +@vindex nnimap-authenticator Some @acronym{IMAP} servers allow anonymous logins. In that case, this should be set to @code{anonymous}. If this variable isn't set, the normal login methods will be used. If you wish to specify a @@ -14556,6 +14567,7 @@ specific login method to be used, you can set this variable to either requires using the @file{oauth2.el} library.) @item nnimap-expunge +@vindex nnimap-expunge When to expunge deleted messages. If @code{never}, deleted articles are marked with the IMAP @code{\\Delete} flag but not automatically expunged. If @code{immediately}, deleted articles are immediately expunged @@ -14571,27 +14583,32 @@ expunge ALL articles that are currently flagged as deleted (i.e., potentially not only the article that was just deleted). @item nnimap-streaming +@vindex nnimap-streaming Virtually all @acronym{IMAP} server support fast streaming of data. If you have problems connecting to the server, try setting this to @code{nil}. @item nnimap-fetch-partial-articles +@vindex nnimap-fetch-partial-articles If non-@code{nil}, fetch partial articles from the server. If set to a string, then it's interpreted as a regexp, and parts that have matching types will be fetched. For instance, @samp{"text/"} will fetch all textual parts, while leaving the rest on the server. @item nnimap-record-commands +@vindex nnimap-record-commands If non-@code{nil}, record all @acronym{IMAP} commands in the @samp{"*imap log*"} buffer. @item nnimap-use-namespaces +@vindex nnimap-use-namespaces If non-@code{nil}, omit the IMAP namespace prefix in nnimap group names. If your IMAP mailboxes are called something like @samp{INBOX} and @samp{INBOX.Lists.emacs}, but you'd like the nnimap group names to be @samp{INBOX} and @samp{Lists.emacs}, you should enable this option. @item nnimap-keepalive-intervals +@vindex nnimap-keepalive-intervals By default, nnimap will send occasional @samp{NOOP} (keepalive) commands to the server, to keep the connection alive. This option governs how often that happens. It is a cons of two integers, From 11c1aa1eb12cb8601355512387c80bf71a2deeb5 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Mon, 27 Feb 2023 14:32:57 +0200 Subject: [PATCH 26/35] ; * doc/misc/gnus.texi: Fix last change. --- doc/misc/gnus.texi | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi index cf6820948ad..f0d3c75d055 100644 --- a/doc/misc/gnus.texi +++ b/doc/misc/gnus.texi @@ -14509,24 +14509,24 @@ Here's an example method that's more complex: @end example @table @code -@item nnimap-address @vindex nnimap-address +@item nnimap-address The address of the server, like @samp{imap.gmail.com}. -@item nnimap-user @vindex nnimap-user +@item nnimap-user Username to use for authentication to the @acronym{IMAP} server. This corresponds to the value of the @samp{login} token in your @file{~/.authinfo} file. Set this variable if you want to access multiple accounts from the same @acronym{IMAP} server. -@item nnimap-server-port @vindex nnimap-server-port +@item nnimap-server-port If the server uses a non-standard port, that can be specified here. A typical port would be @code{"imap"} or @code{"imaps"}. -@item nnimap-stream @vindex nnimap-stream +@item nnimap-stream How @code{nnimap} should connect to the server. Possible values are: @table @code @@ -14556,8 +14556,8 @@ Non-encrypted and unsafe straight socket connection. @end table -@item nnimap-authenticator @vindex nnimap-authenticator +@item nnimap-authenticator Some @acronym{IMAP} servers allow anonymous logins. In that case, this should be set to @code{anonymous}. If this variable isn't set, the normal login methods will be used. If you wish to specify a @@ -14566,8 +14566,8 @@ specific login method to be used, you can set this variable to either @code{plain}, @code{cram-md5} or @code{xoauth2}. (The latter method requires using the @file{oauth2.el} library.) -@item nnimap-expunge @vindex nnimap-expunge +@item nnimap-expunge When to expunge deleted messages. If @code{never}, deleted articles are marked with the IMAP @code{\\Delete} flag but not automatically expunged. If @code{immediately}, deleted articles are immediately expunged @@ -14582,33 +14582,33 @@ EXPUNGE nil is equivalent to @code{never}, while t will immediately expunge ALL articles that are currently flagged as deleted (i.e., potentially not only the article that was just deleted). -@item nnimap-streaming @vindex nnimap-streaming +@item nnimap-streaming Virtually all @acronym{IMAP} server support fast streaming of data. If you have problems connecting to the server, try setting this to @code{nil}. -@item nnimap-fetch-partial-articles @vindex nnimap-fetch-partial-articles +@item nnimap-fetch-partial-articles If non-@code{nil}, fetch partial articles from the server. If set to a string, then it's interpreted as a regexp, and parts that have matching types will be fetched. For instance, @samp{"text/"} will fetch all textual parts, while leaving the rest on the server. -@item nnimap-record-commands @vindex nnimap-record-commands +@item nnimap-record-commands If non-@code{nil}, record all @acronym{IMAP} commands in the @samp{"*imap log*"} buffer. -@item nnimap-use-namespaces @vindex nnimap-use-namespaces +@item nnimap-use-namespaces If non-@code{nil}, omit the IMAP namespace prefix in nnimap group names. If your IMAP mailboxes are called something like @samp{INBOX} and @samp{INBOX.Lists.emacs}, but you'd like the nnimap group names to be @samp{INBOX} and @samp{Lists.emacs}, you should enable this option. -@item nnimap-keepalive-intervals @vindex nnimap-keepalive-intervals +@item nnimap-keepalive-intervals By default, nnimap will send occasional @samp{NOOP} (keepalive) commands to the server, to keep the connection alive. This option governs how often that happens. It is a cons of two integers, From 443c249d85003639512d8d3b6ace184a9ff53bc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= Date: Mon, 27 Feb 2023 13:57:48 +0100 Subject: [PATCH 27/35] Warn about `condition-case` without handlers Omitting handlers from a `condition-case` form makes it useless since no errors are caught. * lisp/emacs-lisp/macroexp.el (macroexp--expand-all): New warning. * test/lisp/emacs-lisp/bytecomp-tests.el (bytecomp-test--with-suppressed-warnings): Add test case. * etc/NEWS: Announce. --- etc/NEWS | 15 +++++++++++++++ lisp/emacs-lisp/macroexp.el | 21 +++++++++++++-------- test/lisp/emacs-lisp/bytecomp-tests.el | 6 ++++++ 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/etc/NEWS b/etc/NEWS index 4b0e4e6bd46..9241598f185 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -321,6 +321,21 @@ compared reliably at all. This warning can be suppressed using 'with-suppressed-warnings' with the warning name 'suspicious'. +--- +*** Warn about 'condition-case' without handlers. +The compiler now warns when the 'condition-case' form is used without +any actual handlers, as in + + (condition-case nil (read buffer)) + +because it has no effect other than the execution of the body form. +In particular, no errors are caught or suppressed. If the intention +was to catch all errors, add an explicit handler for 'error', or use +'ignore-error' or 'ignore-errors'. + +This warning can be suppressed using 'with-suppressed-warnings' with +the warning name 'suspicious'. + +++ ** New function 'file-user-uid'. This function is like 'user-uid', but is aware of file name handlers, diff --git a/lisp/emacs-lisp/macroexp.el b/lisp/emacs-lisp/macroexp.el index c57a27069d6..8cb67c3b8b5 100644 --- a/lisp/emacs-lisp/macroexp.el +++ b/lisp/emacs-lisp/macroexp.el @@ -339,14 +339,19 @@ Assumes the caller has bound `macroexpand-all-environment'." (`(cond . ,clauses) (macroexp--cons fn (macroexp--all-clauses clauses) form)) (`(condition-case . ,(or `(,err ,body . ,handlers) pcase--dontcare)) - (macroexp--cons - fn - (macroexp--cons err - (macroexp--cons (macroexp--expand-all body) - (macroexp--all-clauses handlers 1) - (cddr form)) - (cdr form)) - form)) + (let ((exp-body (macroexp--expand-all body))) + (if handlers + (macroexp--cons fn + (macroexp--cons + err (macroexp--cons + exp-body + (macroexp--all-clauses handlers 1) + (cddr form)) + (cdr form)) + form) + (macroexp-warn-and-return + (format-message "`condition-case' without handlers") + exp-body (list 'suspicious 'condition-case) t form)))) (`(,(or 'defvar 'defconst) ,(and name (pred symbolp)) . ,_) (push name macroexp--dynvars) (macroexp--all-forms form 2)) diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el b/test/lisp/emacs-lisp/bytecomp-tests.el index 185abaf5c22..b6dcfeedb0c 100644 --- a/test/lisp/emacs-lisp/bytecomp-tests.el +++ b/test/lisp/emacs-lisp/bytecomp-tests.el @@ -1446,6 +1446,12 @@ literals (Bug#20852)." '((suspicious set-buffer)) "Warning: Use .with-current-buffer. rather than") + (test-suppression + '(defun zot (x) + (condition-case nil (list x))) + '((suspicious condition-case)) + "Warning: `condition-case' without handlers") + (test-suppression '(defun zot () (let ((_ 1)) From 1767d18c91a3c823d6ab6d69b2666fc5bc2f7d22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= Date: Sun, 26 Feb 2023 16:56:24 +0100 Subject: [PATCH 28/35] Adjust some `pure` and `side-effect-free` function declarations * lisp/emacs-lisp/byte-opt.el (side-effect-free-fns): Add `format-message` and `substring-no-properties`. * lisp/subr.el (number-sequence, copy-tree, looking-at-p) (string-match-p, string-trim-right, string-lines): Declare side-effect-free. (syntax-class, version-list-<, version-list-=, version-list-<=) (version-list-not-zero): Declare pure and side-effect-free. (ensure-list): Declare side-effect-free and error-free. (string-equal-ignore-case): Remove `pure` declaration. We may want it to be pure but right now it's not. --- lisp/emacs-lisp/byte-opt.el | 6 +++--- lisp/subr.el | 14 +++++++++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index d60e3a9dae7..12aa8fb3982 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el @@ -1664,8 +1664,8 @@ See Info node `(elisp) Integer Basics'." file-directory-p file-exists-p file-locked-p file-name-absolute-p file-name-concat file-newer-than-file-p file-readable-p file-symlink-p file-writable-p - float float-time floor format format-time-string frame-first-window - frame-root-window frame-selected-window + float float-time floor format format-message format-time-string + frame-first-window frame-root-window frame-selected-window frame-visible-p fround ftruncate get gethash get-buffer get-buffer-window get-file-buffer hash-table-count @@ -1685,7 +1685,7 @@ See Info node `(elisp) Integer Basics'." regexp-quote region-beginning region-end reverse round sin sqrt string string-equal string-lessp string-search string-to-char - string-to-number string-to-syntax substring + string-to-number string-to-syntax substring substring-no-properties sxhash-equal sxhash-eq sxhash-eql symbol-function symbol-name symbol-plist symbol-value string-make-unibyte diff --git a/lisp/subr.el b/lisp/subr.el index ef2f63f7c37..2a8c51eb7c4 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -806,6 +806,7 @@ TO as (+ FROM (* N INC)) or use a variable whose value was computed with this exact expression. Alternatively, you can, of course, also replace TO with a slightly larger value \(or a slightly more negative value if INC is negative)." + (declare (side-effect-free t)) (if (or (not to) (= from to)) (list from) (or inc (setq inc 1)) @@ -827,6 +828,7 @@ of course, also replace TO with a slightly larger value If TREE is a cons cell, this recursively copies both its car and its cdr. Contrast to `copy-sequence', which copies only along the cdrs. With second argument VECP, this copies vectors as well as conses." + (declare (side-effect-free t)) (if (consp tree) (let (result) (while (consp tree) @@ -5241,11 +5243,13 @@ wherever possible, since it is slow." (defsubst looking-at-p (regexp) "\ Same as `looking-at' except this function does not change the match data." + (declare (side-effect-free t)) (looking-at regexp t)) (defsubst string-match-p (regexp string &optional start) "\ Same as `string-match' except this function does not change the match data." + (declare (side-effect-free t)) (string-match regexp string start t)) (defun subregexp-context-p (regexp pos &optional start) @@ -5516,7 +5520,7 @@ Upper-case and lower-case letters are treated as equal. Unibyte strings are converted to multibyte for comparison. See also `string-equal'." - (declare (pure t) (side-effect-free t)) + (declare (side-effect-free t)) (eq t (compare-strings string1 0 nil string2 0 nil t))) (defun string-prefix-p (prefix string &optional ignore-case) @@ -5843,6 +5847,7 @@ integer that encodes the corresponding syntax class. See Info node `(elisp)Syntax Table Internals' for a list of codes. If SYNTAX is nil, return nil." + (declare (pure t) (side-effect-free t)) (and syntax (logand (car syntax) 65535))) ;; Utility motion commands @@ -6693,6 +6698,7 @@ Note that a version specified by the list (1) is equal to (1 0), \(1 0 0), (1 0 0 0), etc. That is, the trailing zeros are insignificant. Also, a version given by the list (1) is higher than (1 -1), which in turn is higher than (1 -2), which is higher than (1 -3)." + (declare (pure t) (side-effect-free t)) (while (and l1 l2 (= (car l1) (car l2))) (setq l1 (cdr l1) l2 (cdr l2))) @@ -6714,6 +6720,7 @@ Note that a version specified by the list (1) is equal to (1 0), \(1 0 0), (1 0 0 0), etc. That is, the trailing zeros are insignificant. Also, a version given by the list (1) is higher than (1 -1), which in turn is higher than (1 -2), which is higher than (1 -3)." + (declare (pure t) (side-effect-free t)) (while (and l1 l2 (= (car l1) (car l2))) (setq l1 (cdr l1) l2 (cdr l2))) @@ -6735,6 +6742,7 @@ Note that integer list (1) is equal to (1 0), (1 0 0), (1 0 0 0), etc. That is, the trailing zeroes are insignificant. Also, integer list (1) is greater than (1 -1) which is greater than (1 -2) which is greater than (1 -3)." + (declare (pure t) (side-effect-free t)) (while (and l1 l2 (= (car l1) (car l2))) (setq l1 (cdr l1) l2 (cdr l2))) @@ -6752,6 +6760,7 @@ which is greater than (1 -3)." "Return the first non-zero element of LST, which is a list of integers. If all LST elements are zeros or LST is nil, return zero." + (declare (pure t) (side-effect-free t)) (while (and lst (zerop (car lst))) (setq lst (cdr lst))) (if lst @@ -6918,6 +6927,7 @@ REGEXP defaults to \"[ \\t\\n\\r]+\"." "Trim STRING of trailing string matching REGEXP. REGEXP defaults to \"[ \\t\\n\\r]+\"." + (declare (side-effect-free t)) (let ((i (string-match-p (concat "\\(?:" (or regexp "[ \t\n\r]+") "\\)\\'") string))) (if i (substring string 0 i) string))) @@ -6989,6 +6999,7 @@ sentence (see Info node `(elisp) Documentation Tips')." "Return OBJECT as a list. If OBJECT is already a list, return OBJECT itself. If it's not a list, return a one-element list containing OBJECT." + (declare (side-effect-free error-free)) (if (listp object) object (list object))) @@ -7064,6 +7075,7 @@ is inserted before adjusting the number of empty lines." If OMIT-NULLS, empty lines will be removed from the results. If KEEP-NEWLINES, don't strip trailing newlines from the result lines." + (declare (side-effect-free t)) (if (equal string "") (if omit-nulls nil From 4a5eda7ed2ae7567d0d54871cc51e0c2c27d73a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Mon, 27 Feb 2023 14:23:35 +0000 Subject: [PATCH 29/35] Eglot: don't paint hints outside requested region (bug#61812) * lisp/progmodes/eglot.el (eglot--lambda): Add cl-block. (eglot--update-hints-1): Return early if hint is outside the requested inlay hint range. --- lisp/progmodes/eglot.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 719b3abe4cb..ef758371c16 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -641,7 +641,7 @@ Honor `eglot-strict-mode'." Honor `eglot-strict-mode'." (declare (indent 1) (debug (sexp &rest form))) (let ((e (cl-gensym "jsonrpc-lambda-elem"))) - `(lambda (,e) (eglot--dbind ,cl-lambda-list ,e ,@body)))) + `(lambda (,e) (cl-block nil (eglot--dbind ,cl-lambda-list ,e ,@body))))) (cl-defmacro eglot--dcase (obj &rest clauses) "Like `pcase', but for the LSP object OBJ. @@ -3595,6 +3595,7 @@ If NOERROR, return predicate, else erroring function." (paint-hint (eglot--lambda ((InlayHint) position kind label paddingLeft paddingRight) (goto-char (eglot--lsp-position-to-point position)) + (when (or (> (point) to) (< (point) from)) (cl-return)) (let ((ov (make-overlay (point) (point))) (left-pad (and paddingLeft (not (memq (char-before) '(32 9))))) (right-pad (and paddingRight (not (memq (char-after) '(32 9))))) From f601e9666d8b861712c09025711dc3a4261cb0ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Mon, 27 Feb 2023 14:54:53 +0000 Subject: [PATCH 30/35] Eglot: support multiple labels in same inlay hint Mainly the rust-analyzer LSP server uses this. There are still more things we could support, like tooltips and stuff. * lisp/progmodes/eglot.el (lsp-interface-alist): Add InlayHintLabelPart. (eglot--update-hints-1): Support multiple labels for same hint. --- lisp/progmodes/eglot.el | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index ef758371c16..ffc9511469f 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -486,7 +486,8 @@ This can be useful when using docker to run a language server.") (WorkspaceEdit () (:changes :documentChanges)) (WorkspaceSymbol (:name :kind) (:containerName :location :data)) (InlayHint (:position :label) (:kind :textEdits :tooltip :paddingLeft - :paddingRight :data))) + :paddingRight :data)) + (InlayHintLabelPart (:value) (:tooltip :location :command))) "Alist (INTERFACE-NAME . INTERFACE) of known external LSP interfaces. INTERFACE-NAME is a symbol designated by the spec as @@ -3596,20 +3597,29 @@ If NOERROR, return predicate, else erroring function." (eglot--lambda ((InlayHint) position kind label paddingLeft paddingRight) (goto-char (eglot--lsp-position-to-point position)) (when (or (> (point) to) (< (point) from)) (cl-return)) - (let ((ov (make-overlay (point) (point))) - (left-pad (and paddingLeft (not (memq (char-before) '(32 9))))) - (right-pad (and paddingRight (not (memq (char-after) '(32 9))))) - (text (if (stringp label) - label (plist-get (elt label 0) :value)))) - (overlay-put ov 'before-string - (propertize - (concat (and left-pad " ") text (and right-pad " ")) - 'face (pcase kind - (1 'eglot-type-hint-face) - (2 'eglot-parameter-hint-face) - (_ 'eglot-inlay-hint-face)))) - (overlay-put ov 'eglot--inlay-hint t) - (overlay-put ov 'eglot--overlay t))))) + (let ((left-pad (and paddingLeft + (not (memq (char-before) '(32 9))) " ")) + (right-pad (and paddingRight + (not (memq (char-after) '(32 9))) " "))) + (cl-flet + ((do-it (text lpad rpad) + (let ((ov (make-overlay (point) (point)))) + (overlay-put ov 'before-string + (propertize + (concat lpad text rpad) + 'face (pcase kind + (1 'eglot-type-hint-face) + (2 'eglot-parameter-hint-face) + (_ 'eglot-inlay-hint-face)))) + (overlay-put ov 'eglot--inlay-hint t) + (overlay-put ov 'eglot--overlay t)))) + (if (stringp label) (do-it label left-pad right-pad) + (cl-loop + for i from 0 for ldetail across label + do (eglot--dbind ((InlayHintLabelPart) value) ldetail + (do-it value + (and (zerop i) left-pad) + (and (= i (1- (length label))) right-pad)))))))))) (jsonrpc-async-request (eglot--current-server-or-lose) :textDocument/inlayHint From a7a984c0ebebb891e2052d8416544f0bd7002007 Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Mon, 27 Feb 2023 20:32:53 +0200 Subject: [PATCH 31/35] * lisp/icomplete.el: Fix in-buffer completion. (icomplete-force-complete-and-exit, icomplete-force-complete): Use 'icomplete--field-beg/end' when not in the minibuffer to not erase the current buffer. Also disable 'completion-in-region-mode' instead of calling 'exit-minibuffer' (bug#45764, bug#51575, bug#61479). --- lisp/icomplete.el | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/lisp/icomplete.el b/lisp/icomplete.el index f7a91599f3b..fd47d82920f 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -215,15 +215,29 @@ the default otherwise." ;; calculated, This causes the first cached completion to ;; be taken (i.e. the one that the user sees highlighted) completion-all-sorted-completions) - (minibuffer-force-complete-and-exit) + (if (window-minibuffer-p) + (minibuffer-force-complete-and-exit) + (minibuffer-force-complete (icomplete--field-beg) + (icomplete--field-end) + 'dont-cycle) + (completion-in-region-mode -1)) ;; Otherwise take the faster route... - (minibuffer-complete-and-exit))) + (if (window-minibuffer-p) + (minibuffer-complete-and-exit) + (completion-complete-and-exit + (icomplete--field-beg) + (icomplete--field-end) + (lambda () (completion-in-region-mode -1)))))) (defun icomplete-force-complete () "Complete the icomplete minibuffer." (interactive) ;; We're not at all interested in cycling here (bug#34077). - (minibuffer-force-complete nil nil 'dont-cycle)) + (if (window-minibuffer-p) + (minibuffer-force-complete nil nil 'dont-cycle) + (minibuffer-force-complete (icomplete--field-beg) + (icomplete--field-end) + 'dont-cycle))) ;; Apropos `icomplete-scroll', we implement "scrolling icomplete" ;; within classic icomplete, which is "rotating", by contrast. From b5c13032538377b0037c745715613693a1580f81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Mon, 27 Feb 2023 20:40:48 +0200 Subject: [PATCH 32/35] * lisp/icomplete.el (fido-mode): Enable in-buffer completion (bug#45763). --- lisp/icomplete.el | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lisp/icomplete.el b/lisp/icomplete.el index fd47d82920f..47fdf3e7913 100644 --- a/lisp/icomplete.el +++ b/lisp/icomplete.el @@ -443,9 +443,12 @@ more like `ido-mode' than regular `icomplete-mode'." :global t (remove-hook 'minibuffer-setup-hook #'icomplete-minibuffer-setup) (remove-hook 'minibuffer-setup-hook #'icomplete--fido-mode-setup) + (remove-hook 'completion-in-region-mode-hook #'icomplete--in-region-setup) (when fido-mode (icomplete-mode -1) (setq icomplete-mode t) + (when icomplete-in-buffer + (add-hook 'completion-in-region-mode-hook #'icomplete--in-region-setup)) (add-hook 'minibuffer-setup-hook #'icomplete-minibuffer-setup) (add-hook 'minibuffer-setup-hook #'icomplete--fido-mode-setup))) From b699c380286151c97ffae65010d733a092d2db14 Mon Sep 17 00:00:00 2001 From: Augusto Stoffel Date: Thu, 8 Dec 2022 21:05:10 +0100 Subject: [PATCH 33/35] Introduce 'compilation-annotation' text property It is meant to mark parts of compilation buffers which do not correspond to process output (bug#59888). * lisp/progmodes/compile.el (compilation-insert-annotation): New function. (compilation-start, compilation-handle-exit): Use it. (compilation--ensure-parse) Rely on 'compilation-annotation' property instead of 'compilation-header-end'. --- lisp/progmodes/compile.el | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el index ccf64fb670b..6d151db8a83 100644 --- a/lisp/progmodes/compile.el +++ b/lisp/progmodes/compile.el @@ -1706,7 +1706,7 @@ to `compilation-error-regexp-alist' if RULES is nil." (set-marker (make-marker) (save-excursion (goto-char (point-min)) - (text-property-search-forward 'compilation-header-end) + (text-property-search-forward 'compilation-annotation) ;; If we have no end marker, this will be ;; `point-min' still. (point))))) @@ -1854,6 +1854,14 @@ If nil, don't hide anything." ;; buffers when it changes from nil to non-nil or vice-versa. (unless compilation-in-progress (force-mode-line-update t))) +(defun compilation-insert-annotation (&rest args) + "Insert ARGS at point, adding the `compilation-annotation' text property. +This property is used to distinguish output of the compilation +process from additional information inserted by Emacs." + (let ((start (point))) + (apply #'insert args) + (put-text-property start (point) 'compilation-annotation t))) + ;;;###autoload (defun compilation-start (command &optional mode name-function highlight-regexp continue) @@ -1975,17 +1983,16 @@ Returns the compilation buffer created." (setq-local compilation-auto-jump-to-next t)) (when (zerop (buffer-size)) ;; Output a mode setter, for saving and later reloading this buffer. - (insert "-*- mode: " name-of-mode - "; default-directory: " - (prin1-to-string (abbreviate-file-name default-directory)) - " -*-\n")) - (insert (format "%s started at %s\n\n" - mode-name - (substring (current-time-string) 0 19)) - command "\n") - ;; Mark the end of the header so that we don't interpret - ;; anything in it as an error. - (put-text-property (1- (point)) (point) 'compilation-header-end t) + (compilation-insert-annotation + "-*- mode: " name-of-mode + "; default-directory: " + (prin1-to-string (abbreviate-file-name default-directory)) + " -*-\n")) + (compilation-insert-annotation + (format "%s started at %s\n\n" + mode-name + (substring (current-time-string) 0 19)) + command "\n") (setq thisdir default-directory)) (set-buffer-modified-p nil)) ;; Pop up the compilation buffer. @@ -2467,13 +2474,13 @@ commands of Compilation major mode are available. See (cur-buffer (current-buffer))) ;; Record where we put the message, so we can ignore it later on. (goto-char omax) - (insert ?\n mode-name " " (car status)) + (compilation-insert-annotation ?\n mode-name " " (car status)) (if (and (numberp compilation-window-height) (zerop compilation-window-height)) (message "%s" (cdr status))) (if (bolp) (forward-char -1)) - (insert " at " (substring (current-time-string) 0 19)) + (compilation-insert-annotation " at " (substring (current-time-string) 0 19)) (goto-char (point-max)) ;; Prevent that message from being recognized as a compilation error. (add-text-properties omax (point) From 93f557af0ef85ce301bb0780e26351eb8809e91c Mon Sep 17 00:00:00 2001 From: Augusto Stoffel Date: Wed, 7 Dec 2022 18:44:07 +0100 Subject: [PATCH 34/35] New user option 'grep-use-headings' * lisp/progmodes/grep.el (grep-heading-regexp): New user option. (grep-heading): New face (bug#59888). (grep--heading-format, grep--heading-state, grep--heading-filter): Filter function for grep processes and supporting variables. (grep-use-headings): New user option. (grep-mode): Use the above, if applicable. --- etc/NEWS | 9 +++++ lisp/progmodes/grep.el | 66 +++++++++++++++++++++++++++++++ test/lisp/progmodes/grep-tests.el | 14 +++++++ 3 files changed, 89 insertions(+) diff --git a/etc/NEWS b/etc/NEWS index 9241598f185..31fb22fc1e2 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -95,6 +95,15 @@ If you want to get back the old behavior, set the user option to the value (setopt gdb-locals-table-row-config `((type . 0) (name . 0) (value . ,gdb-locals-value-limit))) +** Compile + +*** New user option 'grep-use-headings'. +When non-nil, the output of Grep is split into sections, one for each +file, instead of having file names prefixed to each line. It is +equivalent to the --heading option of some tools such as 'git grep' +and 'rg'. The headings are displayed using the new 'grep-heading' +face. + ** VC --- diff --git a/lisp/progmodes/grep.el b/lisp/progmodes/grep.el index 0da16b44dda..82e9c5d8edf 100644 --- a/lisp/progmodes/grep.el +++ b/lisp/progmodes/grep.el @@ -457,6 +457,33 @@ buffer `default-directory'." :type '(repeat (choice (const :tag "Default" nil) (string :tag "Directory")))) +(defcustom grep-use-headings nil + "If non-nil, subdivide grep output into sections, one per file." + :type 'boolean + :version "30.1") + +(defface grep-heading `((t :inherit ,grep-hit-face)) + "Face of headings when `grep-use-headings' is non-nil." + :version "30.1") + +(defvar grep-heading-regexp + (rx bol + (or + (group-n 2 + (group-n 1 (+ (not (any 0 ?\n)))) + 0) + (group-n 2 + (group-n 1 (+? nonl)) + (any ?: ?- ?=))) + (+ digit) + (any ?: ?- ?=)) + "Regexp used to create headings from grep output lines. +It should be anchored at beginning of line. The first capture +group, if present, should match the heading associated to the +line. The buffer range of the second capture, if present, is +made invisible (presumably because displaying it would be +redundant).") + (defvar grep-find-abbreviate-properties (let ((ellipsis (if (char-displayable-p ?…) "[…]" "[...]")) (map (make-sparse-keymap))) @@ -612,6 +639,40 @@ This function is called from `compilation-filter-hook'." (while (re-search-forward "\033\\[[0-9;]*[mK]" end 1) (replace-match "" t t)))))) +(defvar grep--heading-format + (eval-when-compile + (let ((title (propertize "%s" + 'font-lock-face 'grep-heading + 'outline-level 1))) + (propertize (concat title "\n") 'compilation-annotation t))) + "Format string of grep headings. +This is passed to `format' with one argument, the text of the +first capture group of `grep-heading-regexp'.") + +(defvar-local grep--heading-state nil + "Variable to keep track of the `grep--heading-filter' state.") + +(defun grep--heading-filter () + "Filter function to add headings to output of a grep process." + (unless grep--heading-state + (setq grep--heading-state (cons (point-min-marker) nil))) + (save-excursion + (let ((limit (car grep--heading-state))) + ;; Move point to the old limit and update limit marker. + (move-marker limit (prog1 (pos-bol) (goto-char limit))) + (while (re-search-forward grep-heading-regexp limit t) + (unless (get-text-property (point) 'compilation-annotation) + (let ((heading (match-string-no-properties 1)) + (start (match-beginning 2)) + (end (match-end 2))) + (when start + (put-text-property start end 'invisible t)) + (when (and heading (not (equal heading (cdr grep--heading-state)))) + (save-excursion + (goto-char (pos-bol)) + (insert-before-markers (format grep--heading-format heading))) + (setf (cdr grep--heading-state) heading)))))))) + (defun grep-probe (command args &optional func result) (let (process-file-side-effects) (equal (condition-case nil @@ -906,6 +967,11 @@ The value depends on `grep-command', `grep-template', (add-function :filter-return (local 'kill-transform-function) (lambda (string) (string-replace "\0" ":" string))) + (when grep-use-headings + (add-hook 'compilation-filter-hook #'grep--heading-filter 80 t) + (setq-local outline-search-function #'outline-search-level + outline-level (lambda () (get-text-property + (point) 'outline-level)))) (add-hook 'compilation-filter-hook #'grep-filter nil t)) (defun grep--save-buffers () diff --git a/test/lisp/progmodes/grep-tests.el b/test/lisp/progmodes/grep-tests.el index 39307999d6d..9b7f83086bf 100644 --- a/test/lisp/progmodes/grep-tests.el +++ b/test/lisp/progmodes/grep-tests.el @@ -66,4 +66,18 @@ (cl-letf (((symbol-function 'w32-shell-dos-semantics) #'ignore)) (grep-tests--check-rgrep-abbreviation)))) +(ert-deftest grep-tests--grep-heading-regexp-without-null () + (dolist (sep '(?: ?- ?=)) + (let ((string (format "filename%c123%ctext" sep sep))) + (should (string-match grep-heading-regexp string)) + (should (equal (match-string 1 string) "filename")) + (should (equal (match-string 2 string) (format "filename%c" sep)))))) + +(ert-deftest grep-tests--grep-heading-regexp-with-null () + (dolist (sep '(?: ?- ?=)) + (let ((string (format "funny:0:filename%c123%ctext" 0 sep))) + (should (string-match grep-heading-regexp string)) + (should (equal (match-string 1 string) "funny:0:filename")) + (should (equal (match-string 2 string) "funny:0:filename\0"))))) + ;;; grep-tests.el ends here From 613de662811fccbdcc3521aef394134e8c255127 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Tue, 28 Feb 2023 04:07:55 +0200 Subject: [PATCH 35/35] Rename the newly added -ref- faces to -use- * lisp/font-lock.el (font-lock-variable-use-face) (font-lock-property-use-face): Rename from font-lock-variable-ref-face and font-lock-property-ref-face. Update all references (bug#61655). --- doc/lispref/modes.texi | 8 +++--- etc/NEWS | 4 +-- lisp/cus-theme.el | 4 +-- lisp/font-lock.el | 4 +-- lisp/progmodes/c-ts-mode.el | 6 ++-- lisp/progmodes/cmake-ts-mode.el | 2 +- lisp/progmodes/csharp-mode.el | 20 ++++++------- lisp/progmodes/go-ts-mode.el | 6 ++-- lisp/progmodes/java-ts-mode.el | 6 ++-- lisp/progmodes/js.el | 12 ++++---- lisp/progmodes/json-ts-mode.el | 2 +- lisp/progmodes/python.el | 6 ++-- lisp/progmodes/ruby-ts-mode.el | 4 +-- lisp/progmodes/rust-ts-mode.el | 42 ++++++++++++++-------------- lisp/progmodes/typescript-ts-mode.el | 6 ++-- lisp/textmodes/css-mode.el | 4 +-- lisp/textmodes/toml-ts-mode.el | 4 +-- lisp/textmodes/yaml-ts-mode.el | 12 ++++---- 18 files changed, 76 insertions(+), 76 deletions(-) diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi index 11892aaa40e..fedb2804f26 100644 --- a/doc/lispref/modes.texi +++ b/doc/lispref/modes.texi @@ -3688,8 +3688,8 @@ default, from @code{font-lock-function-name-face}. @vindex font-lock-variable-name-face for the name of a variable being defined or declared. -@item font-lock-variable-ref-face -@vindex font-lock-variable-ref-face +@item font-lock-variable-use-face +@vindex font-lock-variable-use-face for the name of a variable being referenced. This face inherits, by default, from @code{font-lock-variable-name-face}. @@ -3772,8 +3772,8 @@ for properties of an object, such as the declaration of fields in a struct. This face inherits, by default, from @code{font-lock-variable-name-face}. -@item font-lock-property-ref-face -@vindex font-lock-property-ref-face +@item font-lock-property-use-face +@vindex font-lock-property-use-face for properties of an object, such as use of fields in a struct. This face inherits, by default, from @code{font-lock-property-name-face}. diff --git a/etc/NEWS b/etc/NEWS index 5a244285efa..b5e67d47037 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -832,8 +832,8 @@ These faces are primarily meant for use with tree-sitter. They are: 'font-lock-escape-face', 'font-lock-function-call-face', 'font-lock-misc-punctuation-face', 'font-lock-number-face', 'font-lock-operator-face', 'font-lock-property-name-face', -'font-lock-property-ref-face', 'font-lock-punctuation-face', -'font-lock-regexp-face', and 'font-lock-variable-ref-face'. +'font-lock-property-use-face', 'font-lock-punctuation-face', +'font-lock-regexp-face', and 'font-lock-variable-use-face'. +++ ** New face 'variable-pitch-text'. diff --git a/lisp/cus-theme.el b/lisp/cus-theme.el index 46e41dd046c..5d3f2585976 100644 --- a/lisp/cus-theme.el +++ b/lisp/cus-theme.el @@ -73,11 +73,11 @@ Do not call this mode function yourself. It is meant for internal use." font-lock-keyword-face font-lock-negation-char-face font-lock-number-face font-lock-misc-punctuation-face font-lock-operator-face font-lock-preprocessor-face - font-lock-property-name-face font-lock-property-ref-face + font-lock-property-name-face font-lock-property-use-face font-lock-punctuation-face font-lock-regexp-grouping-backslash font-lock-regexp-grouping-construct font-lock-string-face font-lock-type-face font-lock-variable-name-face - font-lock-variable-ref-face + font-lock-variable-use-face font-lock-warning-face button link link-visited fringe header-line tooltip mode-line mode-line-buffer-id mode-line-emphasis mode-line-highlight mode-line-inactive diff --git a/lisp/font-lock.el b/lisp/font-lock.el index b82b7648797..f8815c1698a 100644 --- a/lisp/font-lock.el +++ b/lisp/font-lock.el @@ -2046,7 +2046,7 @@ as the constructs of Haddock, Javadoc and similar systems." "Font Lock mode face used to highlight variable names." :group 'font-lock-faces) -(defface font-lock-variable-ref-face +(defface font-lock-variable-use-face '((t :inherit font-lock-variable-name-face)) "Font Lock mode face used to highlight variable references." :group 'font-lock-faces @@ -2134,7 +2134,7 @@ For example, the declaration of fields in a struct." :group 'font-lock-faces :version "29.1") -(defface font-lock-property-ref-face +(defface font-lock-property-use-face '((t :inherit font-lock-property-name-face)) "Font Lock mode face used to highlight property references. For example, property lookup of fields in a struct." diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 2cb6c2709cc..4b66824c44f 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -547,7 +547,7 @@ MODE is either `c' or `cpp'." '((assignment_expression left: (identifier) @font-lock-variable-name-face) (assignment_expression - left: (field_expression field: (_) @font-lock-property-ref-face)) + left: (field_expression field: (_) @font-lock-property-use-face)) (assignment_expression left: (pointer_expression (identifier) @font-lock-variable-name-face)) @@ -583,7 +583,7 @@ MODE is either `c' or `cpp'." :language mode :feature 'property - '((field_identifier) @font-lock-property-ref-face) + '((field_identifier) @font-lock-property-use-face) :language mode :feature 'bracket @@ -660,7 +660,7 @@ OVERRIDE, START, END, and ARGS, see `treesit-font-lock-rules'." "call_expression")) (treesit-fontify-with-override (treesit-node-start node) (treesit-node-end node) - 'font-lock-variable-ref-face override start end))) + 'font-lock-variable-use-face override start end))) (defun c-ts-mode--fontify-defun (node override start end &rest _) "Correctly fontify the DEFUN macro. diff --git a/lisp/progmodes/cmake-ts-mode.el b/lisp/progmodes/cmake-ts-mode.el index a3f9279ec1c..d83a956af21 100644 --- a/lisp/progmodes/cmake-ts-mode.el +++ b/lisp/progmodes/cmake-ts-mode.el @@ -154,7 +154,7 @@ :language 'cmake :feature 'variable :override t - '((variable) @font-lock-variable-ref-face) + '((variable) @font-lock-variable-use-face) :language 'cmake :feature 'error diff --git a/lisp/progmodes/csharp-mode.el b/lisp/progmodes/csharp-mode.el index 31c87171281..47cd13e7fdb 100644 --- a/lisp/progmodes/csharp-mode.el +++ b/lisp/progmodes/csharp-mode.el @@ -708,9 +708,9 @@ compilation and evaluation time conflicts." (treesit-font-lock-rules :language 'c-sharp :feature 'expression - '((conditional_expression (identifier) @font-lock-variable-ref-face) - (postfix_unary_expression (identifier)* @font-lock-variable-ref-face) - (initializer_expression (assignment_expression left: (identifier) @font-lock-variable-ref-face))) + '((conditional_expression (identifier) @font-lock-variable-use-face) + (postfix_unary_expression (identifier)* @font-lock-variable-use-face) + (initializer_expression (assignment_expression left: (identifier) @font-lock-variable-use-face))) :language 'c-sharp :feature 'bracket @@ -739,8 +739,8 @@ compilation and evaluation time conflicts." :language 'c-sharp :override t :feature 'property - `((attribute (identifier) @font-lock-property-ref-face (attribute_argument_list)) - (attribute (identifier) @font-lock-property-ref-face)) + `((attribute (identifier) @font-lock-property-use-face (attribute_argument_list)) + (attribute (identifier) @font-lock-property-use-face)) :language 'c-sharp :override t @@ -878,23 +878,23 @@ compilation and evaluation time conflicts." :override t '((if_directive "if" @font-lock-preprocessor-face - (identifier) @font-lock-variable-ref-face) + (identifier) @font-lock-variable-use-face) (elif_directive "elif" @font-lock-preprocessor-face - (identifier) @font-lock-variable-ref-face) + (identifier) @font-lock-variable-use-face) (else_directive) @font-lock-preprocessor-face (endif_directive) @font-lock-preprocessor-face (define_directive "define" @font-lock-preprocessor-face - (identifier) @font-lock-variable-ref-face) + (identifier) @font-lock-variable-use-face) (nullable_directive) @font-lock-preprocessor-face (pragma_directive) @font-lock-preprocessor-face (region_directive) @font-lock-preprocessor-face (endregion_directive) @font-lock-preprocessor-face (region_directive - (preproc_message) @font-lock-variable-ref-face) + (preproc_message) @font-lock-variable-use-face) (endregion_directive - (preproc_message) @font-lock-variable-ref-face)))) + (preproc_message) @font-lock-variable-use-face)))) ;;;###autoload (add-to-list 'auto-mode-alist '("\\.cs\\'" . csharp-mode)) diff --git a/lisp/progmodes/go-ts-mode.el b/lisp/progmodes/go-ts-mode.el index d4bafdb577b..e8f93d14744 100644 --- a/lisp/progmodes/go-ts-mode.el +++ b/lisp/progmodes/go-ts-mode.el @@ -177,12 +177,12 @@ :language 'go :feature 'property - '((selector_expression field: (field_identifier) @font-lock-property-ref-face) - (keyed_element (_ (identifier) @font-lock-property-ref-face))) + '((selector_expression field: (field_identifier) @font-lock-property-use-face) + (keyed_element (_ (identifier) @font-lock-property-use-face))) :language 'go :feature 'variable - '((identifier) @font-lock-variable-ref-face) + '((identifier) @font-lock-variable-use-face) :language 'go :feature 'escape-sequence diff --git a/lisp/progmodes/java-ts-mode.el b/lisp/progmodes/java-ts-mode.el index a1f3ad692c2..827d38e30c2 100644 --- a/lisp/progmodes/java-ts-mode.el +++ b/lisp/progmodes/java-ts-mode.el @@ -244,7 +244,7 @@ name: (identifier) @font-lock-variable-name-face) (element_value_pair - key: (identifier) @font-lock-property-ref-face) + key: (identifier) @font-lock-property-use-face) (formal_parameter name: (identifier) @font-lock-variable-name-face) @@ -255,14 +255,14 @@ :override t :feature 'expression '((method_invocation - object: (identifier) @font-lock-variable-ref-face) + object: (identifier) @font-lock-variable-use-face) (method_invocation name: (identifier) @font-lock-function-call-face) (argument_list (identifier) @font-lock-variable-name-face) - (expression_statement (identifier) @font-lock-variable-ref-face)) + (expression_statement (identifier) @font-lock-variable-use-face)) :language 'java :feature 'bracket diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el index e53a80bd499..52ed19cc682 100644 --- a/lisp/progmodes/js.el +++ b/lisp/progmodes/js.el @@ -3563,13 +3563,13 @@ This function is intended for use in `after-change-functions'." :language 'javascript :feature 'property - '(((property_identifier) @font-lock-property-ref-face + '(((property_identifier) @font-lock-property-use-face (:pred js--treesit-property-not-function-p - @font-lock-property-ref-face)) + @font-lock-property-use-face)) - (pair value: (identifier) @font-lock-variable-ref-face) + (pair value: (identifier) @font-lock-variable-use-face) - ((shorthand_property_identifier) @font-lock-property-ref-face)) + ((shorthand_property_identifier) @font-lock-property-use-face)) :language 'javascript :feature 'assignment @@ -3681,8 +3681,8 @@ For OVERRIDE, START, END, see `treesit-font-lock-rules'." (treesit-fontify-with-override (treesit-node-start node) (treesit-node-end node) (pcase (treesit-node-type node) - ("identifier" 'font-lock-variable-ref-face) - ("property_identifier" 'font-lock-property-ref-face)) + ("identifier" 'font-lock-variable-use-face) + ("property_identifier" 'font-lock-property-use-face)) override start end))) (defun js--treesit-defun-name (node) diff --git a/lisp/progmodes/json-ts-mode.el b/lisp/progmodes/json-ts-mode.el index 72f90d5c997..6272c0073e1 100644 --- a/lisp/progmodes/json-ts-mode.el +++ b/lisp/progmodes/json-ts-mode.el @@ -101,7 +101,7 @@ :language 'json :feature 'pair :override t ; Needed for overriding string face on keys. - '((pair key: (_) @font-lock-property-ref-face)) + '((pair key: (_) @font-lock-property-use-face)) :language 'json :feature 'error :override t diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 5aab31c3ea8..1f970633bfc 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -1147,7 +1147,7 @@ fontified." @font-lock-variable-name-face) (assignment left: (attribute attribute: (identifier) - @font-lock-property-ref-face)) + @font-lock-property-use-face)) (pattern_list (identifier) @font-lock-variable-name-face) (tuple_pattern (identifier) @@ -1184,12 +1184,12 @@ fontified." :feature 'property :language 'python '((attribute - attribute: (identifier) @font-lock-property-ref-face) + attribute: (identifier) @font-lock-property-use-face) (class_definition body: (block (expression_statement (assignment left: - (identifier) @font-lock-property-ref-face))))) + (identifier) @font-lock-property-use-face))))) :feature 'operator :language 'python diff --git a/lisp/progmodes/ruby-ts-mode.el b/lisp/progmodes/ruby-ts-mode.el index fedba200f83..fa1d8626f14 100644 --- a/lisp/progmodes/ruby-ts-mode.el +++ b/lisp/progmodes/ruby-ts-mode.el @@ -292,11 +292,11 @@ values of OVERRIDE" :language language :feature 'global - '((global_variable) @font-lock-variable-ref-face) + '((global_variable) @font-lock-variable-use-face) :language language :feature 'instance - '((instance_variable) @font-lock-variable-ref-face) + '((instance_variable) @font-lock-variable-use-face) :language language :feature 'method-definition diff --git a/lisp/progmodes/rust-ts-mode.el b/lisp/progmodes/rust-ts-mode.el index a46d442a0e5..2d5c3211c1a 100644 --- a/lisp/progmodes/rust-ts-mode.el +++ b/lisp/progmodes/rust-ts-mode.el @@ -239,8 +239,8 @@ :language 'rust :feature 'property - '((field_identifier) @font-lock-property-ref-face - (shorthand_field_initializer (identifier) @font-lock-property-ref-face)) + '((field_identifier) @font-lock-property-use-face + (shorthand_field_initializer (identifier) @font-lock-property-use-face)) ;; Must be under type, otherwise some imports can be highlighted as constants. :language 'rust @@ -251,25 +251,25 @@ :language 'rust :feature 'variable - '((arguments (identifier) @font-lock-variable-ref-face) - (array_expression (identifier) @font-lock-variable-ref-face) - (assignment_expression right: (identifier) @font-lock-variable-ref-face) - (binary_expression left: (identifier) @font-lock-variable-ref-face) - (binary_expression right: (identifier) @font-lock-variable-ref-face) - (block (identifier) @font-lock-variable-ref-face) - (compound_assignment_expr right: (identifier) @font-lock-variable-ref-face) - (field_expression value: (identifier) @font-lock-variable-ref-face) - (field_initializer value: (identifier) @font-lock-variable-ref-face) - (if_expression condition: (identifier) @font-lock-variable-ref-face) - (let_condition value: (identifier) @font-lock-variable-ref-face) - (let_declaration value: (identifier) @font-lock-variable-ref-face) - (match_arm value: (identifier) @font-lock-variable-ref-face) - (match_expression value: (identifier) @font-lock-variable-ref-face) - (reference_expression value: (identifier) @font-lock-variable-ref-face) - (return_expression (identifier) @font-lock-variable-ref-face) - (tuple_expression (identifier) @font-lock-variable-ref-face) - (unary_expression (identifier) @font-lock-variable-ref-face) - (while_expression condition: (identifier) @font-lock-variable-ref-face)) + '((arguments (identifier) @font-lock-variable-use-face) + (array_expression (identifier) @font-lock-variable-use-face) + (assignment_expression right: (identifier) @font-lock-variable-use-face) + (binary_expression left: (identifier) @font-lock-variable-use-face) + (binary_expression right: (identifier) @font-lock-variable-use-face) + (block (identifier) @font-lock-variable-use-face) + (compound_assignment_expr right: (identifier) @font-lock-variable-use-face) + (field_expression value: (identifier) @font-lock-variable-use-face) + (field_initializer value: (identifier) @font-lock-variable-use-face) + (if_expression condition: (identifier) @font-lock-variable-use-face) + (let_condition value: (identifier) @font-lock-variable-use-face) + (let_declaration value: (identifier) @font-lock-variable-use-face) + (match_arm value: (identifier) @font-lock-variable-use-face) + (match_expression value: (identifier) @font-lock-variable-use-face) + (reference_expression value: (identifier) @font-lock-variable-use-face) + (return_expression (identifier) @font-lock-variable-use-face) + (tuple_expression (identifier) @font-lock-variable-use-face) + (unary_expression (identifier) @font-lock-variable-use-face) + (while_expression condition: (identifier) @font-lock-variable-use-face)) :language 'rust :feature 'escape-sequence diff --git a/lisp/progmodes/typescript-ts-mode.el b/lisp/progmodes/typescript-ts-mode.el index 5b49b8f50a8..65fba72373c 100644 --- a/lisp/progmodes/typescript-ts-mode.el +++ b/lisp/progmodes/typescript-ts-mode.el @@ -249,9 +249,9 @@ Argument LANGUAGE is either `typescript' or `tsx'." (public_field_definition name: (property_identifier) @font-lock-property-name-face) - (pair key: (property_identifier) @font-lock-property-ref-face) + (pair key: (property_identifier) @font-lock-property-use-face) - ((shorthand_property_identifier) @font-lock-property-ref-face)) + ((shorthand_property_identifier) @font-lock-property-use-face)) :language language :feature 'expression @@ -272,7 +272,7 @@ Argument LANGUAGE is either `typescript' or `tsx'." :language language :feature 'pattern `((pair_pattern - key: (property_identifier) @font-lock-property-ref-face + key: (property_identifier) @font-lock-property-use-face value: [(identifier) @font-lock-variable-name-face (assignment_pattern left: (identifier) @font-lock-variable-name-face)]) diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el index 39e38179359..f51edfb4c80 100644 --- a/lisp/textmodes/css-mode.el +++ b/lisp/textmodes/css-mode.el @@ -1399,8 +1399,8 @@ for determining whether point is within a selector." :feature 'query :language 'css - '((keyword_query) @font-lock-property-ref-face - (feature_name) @font-lock-property-ref-face) + '((keyword_query) @font-lock-property-use-face + (feature_name) @font-lock-property-use-face) :feature 'bracket :language 'css diff --git a/lisp/textmodes/toml-ts-mode.el b/lisp/textmodes/toml-ts-mode.el index 2ff9d07d13b..2c491034372 100644 --- a/lisp/textmodes/toml-ts-mode.el +++ b/lisp/textmodes/toml-ts-mode.el @@ -92,8 +92,8 @@ :language 'toml :feature 'pair :override t ; Needed for overriding string face on keys. - '((bare_key) @font-lock-property-ref-face - (quoted_key) @font-lock-property-ref-face + '((bare_key) @font-lock-property-use-face + (quoted_key) @font-lock-property-use-face (table ("[" @font-lock-bracket-face (_) @font-lock-type-face "]" @font-lock-bracket-face)) diff --git a/lisp/textmodes/yaml-ts-mode.el b/lisp/textmodes/yaml-ts-mode.el index dc0fa00df27..dfa8d22fb34 100644 --- a/lisp/textmodes/yaml-ts-mode.el +++ b/lisp/textmodes/yaml-ts-mode.el @@ -94,22 +94,22 @@ :feature 'property :override t '((block_mapping_pair - key: (flow_node (plain_scalar (string_scalar) @font-lock-property-ref-face))) + key: (flow_node (plain_scalar (string_scalar) @font-lock-property-use-face))) (block_mapping_pair key: (flow_node - [(double_quote_scalar) (single_quote_scalar)] @font-lock-property-ref-face)) + [(double_quote_scalar) (single_quote_scalar)] @font-lock-property-use-face)) (flow_mapping - (_ key: (flow_node (plain_scalar (string_scalar) @font-lock-property-ref-face)))) + (_ key: (flow_node (plain_scalar (string_scalar) @font-lock-property-use-face)))) (flow_mapping (_ key: (flow_node - [(double_quote_scalar) (single_quote_scalar)] @font-lock-property-ref-face))) + [(double_quote_scalar) (single_quote_scalar)] @font-lock-property-use-face))) (flow_sequence - (_ key: (flow_node (plain_scalar (string_scalar) @font-lock-property-ref-face)))) + (_ key: (flow_node (plain_scalar (string_scalar) @font-lock-property-use-face)))) (flow_sequence (_ key: (flow_node - [(double_quote_scalar) (single_quote_scalar)] @font-lock-property-ref-face)))) + [(double_quote_scalar) (single_quote_scalar)] @font-lock-property-use-face)))) :language 'yaml :feature 'error