From e444115d026c809395d4d248a99bb467bc87bb1d Mon Sep 17 00:00:00 2001 From: Robert Pluim Date: Thu, 2 Feb 2023 11:37:45 +0100 Subject: [PATCH 01/62] Improve keymap-global-set and keymap-local-set interactive use fix * lisp/keymap.el (keymap-global-set, keymap-local-set): Add optional `interactive' arg and use it to decide when to convert the key specification to a string. Add `advertised-calling-convention' declarations. (Bug#61149) --- lisp/keymap.el | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/lisp/keymap.el b/lisp/keymap.el index 201a49cef8c..4f02639ffe2 100644 --- a/lisp/keymap.el +++ b/lisp/keymap.el @@ -65,7 +65,7 @@ DEFINITION is anything that can be a key's definition: (setq definition (key-parse definition))) (define-key keymap (key-parse key) definition)) -(defun keymap-global-set (key command) +(defun keymap-global-set (key command &optional interactive) "Give KEY a global binding as COMMAND. COMMAND is the command definition to use; usually it is a symbol naming an interactively-callable function. @@ -75,13 +75,14 @@ KEY is a string that satisfies `key-valid-p'. Note that if KEY has a local binding in the current buffer, that local binding will continue to shadow any global binding that you make with this function." - (declare (compiler-macro (lambda (form) (keymap--compile-check key) form))) - (interactive "KSet key globally:\nCSet key %s globally to command: ") - (unless (stringp key) + (declare (compiler-macro (lambda (form) (keymap--compile-check key) form)) + (advertised-calling-convention (key command) "29.1")) + (interactive "KSet key globally: \nCSet key %s globally to command: \np") + (when interactive (setq key (key-description key))) (keymap-set (current-global-map) key command)) -(defun keymap-local-set (key command) +(defun keymap-local-set (key command &optional interactive) "Give KEY a local binding as COMMAND. COMMAND is the command definition to use; usually it is a symbol naming an interactively-callable function. @@ -90,12 +91,13 @@ KEY is a string that satisfies `key-valid-p'. The binding goes in the current buffer's local map, which in most cases is shared with all other buffers in the same major mode." - (declare (compiler-macro (lambda (form) (keymap--compile-check key) form))) - (interactive "KSet key locally:\nCSet key %s locally to command: ") + (declare (compiler-macro (lambda (form) (keymap--compile-check key) form)) + (advertised-calling-convention (key command) "29.1")) + (interactive "KSet key locally: \nCSet key %s locally to command: \np") (let ((map (current-local-map))) (unless map (use-local-map (setq map (make-sparse-keymap)))) - (unless (stringp key) + (when interactive (setq key (key-description key))) (keymap-set map key command))) From c3f58a66514b2c1b0d2441c9cf37d94d64bef224 Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Fri, 3 Feb 2023 06:01:04 -0800 Subject: [PATCH 02/62] Don't casemap erc-sasl-user when set to :nick * lisp/erc/erc-sasl.el (erc-sasl-user): Fix doc string. (erc-sasl--get-user): Don't apply casemapping when the option `erc-sasl-user' is set to `:nick'. While many servers and auth-services providers perform case-folding when comparing SASL usernames, only some recognize RFC1459 mappings, which ERC previously applied blindly. Instead, ERC now behaves like other clients in leaving such preparation in the hands of the server. This bug was introduced with changes new to ERC 5.5 and Emacs 29 (bug#29108). --- lisp/erc/erc-sasl.el | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lisp/erc/erc-sasl.el b/lisp/erc/erc-sasl.el index a0b36d07613..97c7c54a517 100644 --- a/lisp/erc/erc-sasl.el +++ b/lisp/erc/erc-sasl.el @@ -67,12 +67,11 @@ Note that any value other than nil or `external' likely requires (defcustom erc-sasl-user :user "Account username to send when authenticating. -This is also referred to as the authentication identity or +This option specifies the SASL authentication identity, or \"authcid\". A value of `:user' or `:nick' indicates that the -corresponding connection parameter on file should be used. These -are most often derived from arguments provided to the `erc' and -`erc-tls' entry points. In the case of `:nick', a downcased -version is used." +corresponding connection parameter on file should be used. ERC +typically obtains these from arguments given to its entry-point +commands, `erc' and `erc-tls'." :type '(choice string (const :user) (const :nick))) (defcustom erc-sasl-password :password @@ -129,7 +128,7 @@ integration." (defun erc-sasl--get-user () (pcase (alist-get 'user erc-sasl--options) (:user erc-session-username) - (:nick (erc-downcase (erc-current-nick))) + (:nick (erc-current-nick)) (v v))) (defun erc-sasl-auth-source-password-as-host (&rest plist) From 35e238cae8b017486dd2d2a52d0b31af6a167689 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Fri, 3 Feb 2023 16:45:56 +0200 Subject: [PATCH 03/62] Improve documentation of 'header-line-indent-mode' * doc/lispref/modes.texi (Header Lines): Rewrite the documentation of 'header-line-indent-mode' and its two variables. Fix the example. * doc/lispref/display.texi (Pixel Specification): More accurate description of what happens with :align-to in header-lines. Improve indexing. (Bug#61239) * src/buffer.c (syms_of_buffer) : * lisp/display-line-numbers.el (header-line-indent) (header-line-indent-width, header-line-indent-mode): Doc fixes. * etc/NEWS: Enhance the announcement of 'header-line-indent-mode'. --- doc/lispref/display.texi | 46 ++++++++++++++++++++----- doc/lispref/modes.texi | 67 +++++++++++++++++++++++++++++++----- etc/NEWS | 8 +++-- lisp/display-line-numbers.el | 49 +++++++++++++++++--------- src/buffer.c | 4 +-- 5 files changed, 136 insertions(+), 38 deletions(-) diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 5a9a9f95f7b..c5374e1481a 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -5285,9 +5285,10 @@ space taken by the line-number display. The @code{left}, @code{center}, and @code{right} positions can be used with @code{:align-to} to specify a position relative to the left edge, center, or right edge of the text area. When the window -displays line numbers, the @code{left} and the @code{center} positions -are offset to account for the screen space taken by the line-number -display. +displays line numbers, and @code{:align-to} is used in display +properties of buffer text (as opposed to header line, see below), the +@code{left} and the @code{center} positions are offset to account for +the screen space taken by the line-number display. Any of the above window elements (except @code{text}) can also be used with @code{:align-to} to specify that the position is relative to @@ -5301,11 +5302,11 @@ the left-margin, use :align-to (+ left-margin (0.5 . left-margin)) @end example - If no specific base offset is set for alignment, it is always relative -to the left edge of the text area. For example, @samp{:align-to 0} in a -header-line aligns with the first text column in the text area. When -the window displays line numbers, the text is considered to start where -the space used for line-number display ends. + If no specific base offset is set for alignment, it is always +relative to the left edge of the text area. For example, +@samp{:align-to 0} aligns with the first text column in the text area. +When the window displays line numbers, the text is considered to start +where the space used for line-number display ends. A value of the form @code{(@var{num} . @var{expr})} stands for the product of the values of @var{num} and @var{expr}. For example, @@ -5317,6 +5318,35 @@ product of the values of @var{num} and @var{expr}. For example, expressions. The form @code{(- @var{expr} ...)} negates or subtracts the value of the expressions. +@vindex header-line-format@r{, and } :align-to +@cindex aligning header line, when line numbers are displayed +@cindex header line alignment when line numbers are displayed + Text shown in the header line that uses @code{:align-to} display +specifications is not automatically realigned when +@code{display-line-numbers-mode} is turned on and off, or when the +width of line numbers on display changes. To arrange for the +header-line text alignment to be updated, thus keeping the header-line +text aligned with the buffer text, turn on the +@code{header-line-indent-mode} in the buffer and use its two +variables, @code{header-line-indent} and +@code{header-line-indent-width}, in the display specification. +@xref{Header Lines}. Here's a simple example: + +@lisp +(setq header-line-format + (concat (propertize " " + 'display + '(space :align-to + (+ header-line-indent-width 10))) + "Column")) +@end lisp + +@noindent +This will keep the text @samp{Column} on the header line aligned with +column 10 of buffer text, regardless of whether +@code{display-line-numbers-mode} is on or off, and also when +line-number display changes its width. + @node Other Display Specs @subsection Other Display Specifications diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi index fe5eb8a1b8d..750c4b47894 100644 --- a/doc/lispref/modes.texi +++ b/doc/lispref/modes.texi @@ -2578,21 +2578,70 @@ header line, for windows displaying the buffer. The format of the value is the same as for @code{mode-line-format} (@pxref{Mode Line Data}). It is normally @code{nil}, so that ordinary buffers have no header line. +@end defvar -@findex header-line-indent-mode -If @code{display-line-numbers-mode} is used, and you want the header -line to be indented by the same amount as the buffer contents, you can -use the @code{header-line-indent-mode} minor mode. This minor mode -keeps the @code{header-line-indent} variable updated, so that you can -say something like: +If @code{display-line-numbers-mode} is turned on in a buffer +(@pxref{Display Custom, display-line-numbers-mode,, emacs, The GNU +Emacs Manual}), the buffer text is indented on display by the amount +of screen space needed to show the line numbers. By contrast, text of +the header line is not automatically indented, because a header line +never displays a line number, and because the text of the header line +is not necessarily directly related to buffer text below it. If a +Lisp program needs the header-line text to be aligned with buffer text +(for example, if the buffer displays columnar data, like +@code{tabulated-list-mode} does, @pxref{Tabulated List Mode}), it +should turn on the minor mode @code{header-line-indent-mode}. + +@deffn Command header-line-indent-mode +This buffer-local minor mode tracks the changes of the width of the +line-number display on screen (which may vary depending on the range +of line numbers shown in the window), and allows Lisp programs to +arrange that header-line text is always aligned with buffer text when +the line-number width changes. Such Lisp programs should turn on this +mode in the buffer, and use the variables @code{header-line-indent} +and @code{header-line-indent-width} in the @code{header-line-format} +to ensure it is adjusted to the text indentation at all times. +@end deffn + +@defvar header-line-indent +This variable's value is a whitespace string whose width is kept equal +to the current width of line-numbers on display, provided that +@code{header-line-indent-mode} is turned on in the buffer shown in the +window. The number of spaces is calculated under the assumption that +the face of the header-line text uses the same font, including size, +as the frame's default font; if that assumption is false, use +@code{header-line-indent-width}, described below, instead. This +variable is intended to be used in simple situations where the +header-line text needs to be indented as a whole to be realigned with +buffer text, by prepending this variable's value to the actual +header-line text. For example, the following definition of +@code{header-line-format}: @lisp (setq header-line-format - `("" header-line-format ,my-header-line)) + `("" header-line-indent ,my-header-line)) @end lisp -This can be useful if you're displaying columnar data, and the header -line should align with that data in the buffer. +@noindent +where @code{my-header-line} is the format string that produces the +actual text of the header line, will make sure the header-line text +is always indented like the buffer text below it. +@end defvar + +@defvar header-line-indent-width +This variable's value is kept updated to provide the current width, in +units of the frame's canonical character width, used for displaying +the line numbers, provided that @code{header-line-indent-mode} is +turned on in the buffer shown in the window. It can be used for +aligning the header-line text with the buffer text when +@code{header-line-indent} is not flexible enough. For example, if the +header line uses a font whose metrics is different from the default +face's font, your Lisp program can calculate the width of line-number +display in pixels, by multiplying the value of this variable by the +value returned by @code{frame-char-width} (@pxref{Frame Font}), and +then use the result to align header-line text using the +@code{:align-to} display property spec (@pxref{Specified Space}) in +pixels on the relevant parts of @code{header-line-frormat}. @end defvar @defun window-header-line-height &optional window diff --git a/etc/NEWS b/etc/NEWS index e3cbeb84d30..2d15e39036a 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -3946,9 +3946,11 @@ This argument can be used to override values of print-related settings. +++ ** New minor mode 'header-line-indent-mode'. -This is meant to be used in modes that have a header line that should -be kept aligned with the buffer contents when the user switches -'display-line-numbers-mode' on or off. +This is meant to be used by Lisp programs that show a header line +which should be kept aligned with the buffer contents when the user +switches 'display-line-numbers-mode' on or off, and when the width of +line-number display changes. See the "(elisp) Header Lines" node in +the Emacs Lisp Reference manual for more information. +++ ** New global minor mode 'lost-selection-mode'. diff --git a/lisp/display-line-numbers.el b/lisp/display-line-numbers.el index 37cf7ade46e..89e9cec6fcd 100644 --- a/lisp/display-line-numbers.el +++ b/lisp/display-line-numbers.el @@ -112,19 +112,27 @@ the mode is on, set `display-line-numbers' directly." ;;;###autoload (defvar header-line-indent "" - "String to indent at the start if the header line. -This is used in `header-line-indent-mode', and buffers that have -this switched on should have a `header-line-format' that look like: + "String of spaces to indent the beginning of header-line due to line numbers. +This is intended to be used in `header-line-format', and requires +the `header-line-indent-mode' to be turned on, in order for the width +of this string to be kept updated when the line-number width changes +on display. An example of a `header-line-format' that uses this +variable might look like this: (\"\" header-line-indent THE-REST...) +where THE-REST is the format string which produces the actual text +of the header-line. Also see `header-line-indent-width'.") ;;;###autoload (defvar header-line-indent-width 0 - "The width of the current line numbers displayed. -This is updated when `header-line-indent-mode' is switched on. - + "The width of the current line number display in the window. +This is measured in units of the frame's canonical columns. +This is updated when `header-line-indent-mode' is switched on, +and is intended for use in `:align-to' display specifications +that are part of `header-line-format', when portions of header-line +text should be aligned to respective parts of buffer text. Also see `header-line-indent'.") (defun header-line-indent--line-number-width () @@ -155,21 +163,30 @@ Also see `header-line-indent'.") ;;;###autoload (define-minor-mode header-line-indent-mode - "Mode to indent the header line in `display-line-numbers-mode' buffers. -This means that the header line will be kept indented so that it -has blank space that's as wide as the displayed line numbers in -the buffer. + "Minor mode to help with alignment of header line when line numbers are shown. +This minor mode should be turned on in buffers which dispay header-line +that needs to be aligned with buffer text when `display-line-numbers-mode' +is turned on in the buffer. -Buffers that have this switched on should have a -`header-line-format' that look like: +Buffers that have this switched on should have a `header-line-format' +that uses the `header-line-indent' or the `header-line-indent-width' +variables, which this mode will keep up-to-date with the current +display of line numbers. For example, a `header-line-format' that +looks like this: (\"\" header-line-indent THE-REST...) -The `header-line-indent-width' variable is also kept updated, and -has the width of `header-line-format'. This can be used, for -instance, in `:align-to' specs, like: +will make sure the text produced by THE-REST (which should be +a header-line format string) is always indented to be aligned on +display with the first column of buffer text. - (space :align-to (+ header-line-indent-width 10))" +The `header-line-indent-width' variable is also kept updated, +and can be used, for instance, in `:align-to' specs as part +of `header-line-format', like this: + + (space :align-to (+ header-line-indent-width 10)) + +See also `line-number-display-width'." :lighter nil (if header-line-indent-mode (progn diff --git a/src/buffer.c b/src/buffer.c index 88ca69b0dd8..38648519ba0 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -5081,8 +5081,8 @@ the mode line appears at the bottom. */); The header line appears, optionally, at the top of a window; the mode line appears at the bottom. -Also see `header-line-indent-mode' if `display-line-number-mode' is -used. */); +Also see `header-line-indent-mode' if `display-line-numbers-mode' is +turned on and header-line text should be aligned with buffer text. */); DEFVAR_PER_BUFFER ("mode-line-format", &BVAR (current_buffer, mode_line_format), Qnil, From f25c15ceb7d9b26cc8b93648730571187ef36c85 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Fri, 3 Feb 2023 18:02:53 +0100 Subject: [PATCH 04/62] ; Fix typos --- admin/notes/tree-sitter/treesit_record_change | 2 +- lisp/display-line-numbers.el | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/notes/tree-sitter/treesit_record_change b/admin/notes/tree-sitter/treesit_record_change index bb0f9edc353..0dc6491e2d1 100644 --- a/admin/notes/tree-sitter/treesit_record_change +++ b/admin/notes/tree-sitter/treesit_record_change @@ -5,7 +5,7 @@ buffer, lest tree-sitter's parse tree would be corrupted/out of sync. All buffer changes in Emacs are made through functions in insdel.c (and casefiddle.c), I augmented functions in those files with calls to -treesit_record_change. Below is a manifest of all the relavent +treesit_record_change. Below is a manifest of all the relevant functions in insdel.c as of Emacs 29: Function Calls diff --git a/lisp/display-line-numbers.el b/lisp/display-line-numbers.el index 89e9cec6fcd..4f87ffd0e22 100644 --- a/lisp/display-line-numbers.el +++ b/lisp/display-line-numbers.el @@ -164,7 +164,7 @@ Also see `header-line-indent'.") ;;;###autoload (define-minor-mode header-line-indent-mode "Minor mode to help with alignment of header line when line numbers are shown. -This minor mode should be turned on in buffers which dispay header-line +This minor mode should be turned on in buffers which display header-line that needs to be aligned with buffer text when `display-line-numbers-mode' is turned on in the buffer. From d99b5151f8c41d45084d10c49c86d6c228d5f730 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sat, 4 Feb 2023 03:34:22 +0200 Subject: [PATCH 05/62] Add syntax-propertize-function to ruby-ts-mode * lisp/progmodes/ruby-ts-mode.el (ruby-ts--s-p-query): New variable. (ruby-ts--syntax-propertize): New function. (ruby-ts--parser-after-change): New function. (ruby-ts-mode): Use both of them. --- lisp/progmodes/ruby-ts-mode.el | 85 +++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/lisp/progmodes/ruby-ts-mode.el b/lisp/progmodes/ruby-ts-mode.el index 7725d0824e3..02cc1aad5e6 100644 --- a/lisp/progmodes/ruby-ts-mode.el +++ b/lisp/progmodes/ruby-ts-mode.el @@ -95,6 +95,11 @@ (declare-function treesit-node-end "treesit.c") (declare-function treesit-node-start "treesit.c") (declare-function treesit-node-string "treesit.c") +(declare-function treesit-query-compile "treesit.c") +(declare-function treesit-query-capture "treesit.c") +(declare-function treesit-parser-add-notifier "treesit.c") +(declare-function treesit-parser-buffer "treesit.c") +(declare-function treesit-parser-list "treesit.c") (defgroup ruby-ts nil "Major mode for editing Ruby code." @@ -1002,6 +1007,70 @@ leading double colon is not added." (concat result sep method-name) result))) +(defvar ruby-ts--s-p-query + (when (treesit-available-p) + (treesit-query-compile 'ruby + '(((heredoc_body) @heredoc) + ;; $' $" $`. + ((global_variable) @global_var + (:match "\\`\\$[#\"'`:?]" @global_var)) + ;; ?' ?" ?` are character literals. + ((character) @char + (:match "\\`?[#\"'`:?]" @char)) + ;; Symbols like :+, :<=> or :foo=. + ((simple_symbol) @symbol + (:match "[[:punct:]]" @symbol)) + ;; Method calls with name ending with ? or !. + ((call method: (identifier) @ident) + (:match "[?!]\\'" @ident)) + ;; Backtick method redefinition. + ((operator "`" @backtick)) + ;; TODO: Stop at interpolations. + ((regex "/" @regex-slash)) + ;; =begin...=end + ((comment) @comm + (:match "\\`=" @comm)) + ;; Percent literals: %w[], %q{}, ... + ((string) @percent + (:match "\\`%" @percent)))))) + +(defun ruby-ts--syntax-propertize (beg end) + (let ((captures (treesit-query-capture 'ruby ruby-ts--s-p-query beg end))) + (pcase-dolist (`(,name . ,node) captures) + (pcase name + ('regex_slash + (put-text-property (treesit-node-start node) (treesit-node-end node) + 'syntax-table (string-to-syntax "\"/"))) + ('ident + (put-text-property (1- (treesit-node-end node)) (treesit-node-end node) + 'syntax-table (string-to-syntax "_"))) + ('symbol + (put-text-property (1+ (treesit-node-start node)) (treesit-node-end node) + 'syntax-table (string-to-syntax "_"))) + ('heredoc + (put-text-property (treesit-node-start node) (1+ (treesit-node-start node)) + 'syntax-table (string-to-syntax "\"")) + (put-text-property (1- (treesit-node-end node)) (treesit-node-end node) + 'syntax-table (string-to-syntax "\""))) + ('percent + (put-text-property (1+ (treesit-node-start node)) (+ 2 (treesit-node-start node)) + 'syntax-table (string-to-syntax "|")) + (put-text-property (1- (treesit-node-end node)) (treesit-node-end node) + 'syntax-table (string-to-syntax "|"))) + ((or 'global_var 'char) + (put-text-property (treesit-node-start node) (1+ (treesit-node-start node)) + 'syntax-table (string-to-syntax "'")) + (put-text-property (1+ (treesit-node-start node)) (treesit-node-end node) + 'syntax-table (string-to-syntax "_"))) + ('backtick + (put-text-property (treesit-node-start node) (treesit-node-end node) + 'syntax-table (string-to-syntax "_"))) + ('comm + (dolist (pos (list (treesit-node-start node) + (1- (treesit-node-end node)))) + (put-text-property pos (1+ pos) 'syntax-table + (string-to-syntax "!")))))))) + (defvar-keymap ruby-ts-mode-map :doc "Keymap used in Ruby mode" :parent prog-mode-map @@ -1049,7 +1118,21 @@ leading double colon is not added." interpolation literal symbol assignment) ( bracket error function operator punctuation))) - (treesit-major-mode-setup)) + (treesit-major-mode-setup) + + (treesit-parser-add-notifier (car (treesit-parser-list)) + #'ruby-ts--parser-after-change) + + (setq-local syntax-propertize-function #'ruby-ts--syntax-propertize)) + +(defun ruby-ts--parser-after-change (ranges parser) + ;; Make sure we re-syntax-propertize the full node that is being + ;; edited. This is most pertinent to multi-line complex nodes such + ;; as heredocs. + (when ranges + (with-current-buffer (treesit-parser-buffer parser) + (syntax-ppss-flush-cache (cl-loop for r in ranges + minimize (car r)))))) (if (treesit-ready-p 'ruby) ;; Copied from ruby-mode.el. From 4c765d93ab3dd646c1b9722bdd5a91da525d06f2 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sat, 4 Feb 2023 04:16:55 +0200 Subject: [PATCH 06/62] Refine the previous change * lisp/progmodes/ruby-ts-mode.el (ruby-ts--s-p-query): Fix a typo. (ruby-ts--syntax-propertize): Use pcase-exhaustive to avoid typos. Put the last s-t property after heredoc's end (apparently parse-partial-sexp likes that more). Move first s-t property on percent literals to the very beginning (to be refined later). Differentiate the %r{} literals from /.../ ones -- tree-sitter parses them exactly the same. --- lisp/progmodes/ruby-ts-mode.el | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/lisp/progmodes/ruby-ts-mode.el b/lisp/progmodes/ruby-ts-mode.el index 02cc1aad5e6..c0971193244 100644 --- a/lisp/progmodes/ruby-ts-mode.el +++ b/lisp/progmodes/ruby-ts-mode.el @@ -1026,7 +1026,7 @@ leading double colon is not added." ;; Backtick method redefinition. ((operator "`" @backtick)) ;; TODO: Stop at interpolations. - ((regex "/" @regex-slash)) + ((regex "/" @regex_slash)) ;; =begin...=end ((comment) @comm (:match "\\`=" @comm)) @@ -1037,10 +1037,16 @@ leading double colon is not added." (defun ruby-ts--syntax-propertize (beg end) (let ((captures (treesit-query-capture 'ruby ruby-ts--s-p-query beg end))) (pcase-dolist (`(,name . ,node) captures) - (pcase name + (pcase-exhaustive name ('regex_slash - (put-text-property (treesit-node-start node) (treesit-node-end node) - 'syntax-table (string-to-syntax "\"/"))) + ;; N.B.: A regexp literal with modifiers actually includes them in + ;; the trailing "/" node. + (put-text-property (treesit-node-start node) (1+ (treesit-node-start node)) + 'syntax-table + ;; Differentiate the %r{...} literals. + (if (eq ?/ (char-after (treesit-node-start node))) + (string-to-syntax "\"/") + (string-to-syntax "|")))) ('ident (put-text-property (1- (treesit-node-end node)) (treesit-node-end node) 'syntax-table (string-to-syntax "_"))) @@ -1050,10 +1056,11 @@ leading double colon is not added." ('heredoc (put-text-property (treesit-node-start node) (1+ (treesit-node-start node)) 'syntax-table (string-to-syntax "\"")) - (put-text-property (1- (treesit-node-end node)) (treesit-node-end node) + (put-text-property (treesit-node-end node) (1+ (treesit-node-end node)) 'syntax-table (string-to-syntax "\""))) ('percent - (put-text-property (1+ (treesit-node-start node)) (+ 2 (treesit-node-start node)) + ;; TODO: Put the first one on the first paren in both %Q{} and %(). + (put-text-property (treesit-node-start node) (1+ (treesit-node-start node)) 'syntax-table (string-to-syntax "|")) (put-text-property (1- (treesit-node-end node)) (treesit-node-end node) 'syntax-table (string-to-syntax "|"))) From 3a64f81ebc153ad26331d9d43659a56bed3247bd Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 4 Feb 2023 10:15:18 +0200 Subject: [PATCH 07/62] Don't clobber match data in 'y-or-n-p' * lisp/subr.el (y-or-n-p): Avoid clobbering caller's match data. (Bug#61091) --- lisp/subr.el | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lisp/subr.el b/lisp/subr.el index 0f754fcd31f..32c997425cf 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -3573,12 +3573,14 @@ like) while `y-or-n-p' is running)." (if (or (zerop l) (eq ?\s (aref prompt (1- l)))) "" " ") (if dialog "" - (substitute-command-keys - (if help-form - (format "(\\`y', \\`n' or \\`%s') " - (key-description - (vector help-char))) - "(\\`y' or \\`n') "))))))) + ;; Don't clobber caller's match data. + (save-match-data + (substitute-command-keys + (if help-form + (format "(\\`y', \\`n' or \\`%s') " + (key-description + (vector help-char))) + "(\\`y' or \\`n') ")))))))) ;; Preserve the actual command that eventually called ;; `y-or-n-p' (otherwise `repeat' will be repeating ;; `exit-minibuffer'). From 873a0a15085629ac54fdee609c82b66583e3aefc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jostein=20Kj=C3=B8nigsen?= Date: Sat, 28 Jan 2023 15:23:11 +0100 Subject: [PATCH 08/62] Add support for TypeScript compilation to compile.el (bug#61104) * lisp/progmodes/compile.el (compilation-error-regexp-alist-alist): Add regexps. --- lisp/progmodes/compile.el | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el index 5758eadf996..1e57d0b7bb2 100644 --- a/lisp/progmodes/compile.el +++ b/lisp/progmodes/compile.el @@ -649,6 +649,24 @@ File = \\(.+\\), Line = \\([0-9]+\\)\\(?:, Column = \\([0-9]+\\)\\)?" ;; we do not know what lines will follow. (guile-file "^In \\(.+\\..+\\):\n" 1 nil nil 0) (guile-line "^ *\\([0-9]+\\): *\\([0-9]+\\)" nil 1 2) + + ;; Typescript compilation prior to tsc version 2.7, "plain" format: + ;; greeter.ts(30,12): error TS2339: Property 'foo' does not exist. + (typescript-tsc-plain + ,(concat + "^[[:blank:]]*" + "\\([^(\r\n)]+\\)(\\([0-9]+\\),\\([0-9]+\\)):[[:blank:]]+" + "error [[:alnum:]]+: [^\r\n]+$") + 1 2 3 2) + + ;; Typescript compilation after tsc version 2.7, "pretty" format: + ;; src/resources/document.ts:140:22 - error TS2362: something. + (typescript-tsc-pretty + ,(concat + "^[[:blank:]]*" + "\\([^(\r\n)]+\\):\\([0-9]+\\):\\([0-9]+\\) - [[:blank:]]*" + "error [[:alnum:]]+: [^\r\n]+$") + 1 2 3 2) )) "Alist of values for `compilation-error-regexp-alist'.") From 8870b54db995e4e8fc6ecfcdd85c4b0e6545dd29 Mon Sep 17 00:00:00 2001 From: Theodor Thornhill Date: Fri, 3 Feb 2023 09:05:13 +0100 Subject: [PATCH 09/62] Add tests for compilation support for TypeScript (bug#61104) * test/lisp/progmodes/compile-tests.el (compile-tests--test-regexps-data): Add new test-cases. (compile-test-error-regexps): Increase expected errors --- test/lisp/progmodes/compile-tests.el | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/lisp/progmodes/compile-tests.el b/test/lisp/progmodes/compile-tests.el index 53dc7f2a133..078eef36774 100644 --- a/test/lisp/progmodes/compile-tests.el +++ b/test/lisp/progmodes/compile-tests.el @@ -382,6 +382,10 @@ ;; sun-ada (sun-ada "/home3/xdhar/rcds_rc/main.a, line 361, char 6:syntax error: \",\" inserted" 1 6 361 "/home3/xdhar/rcds_rc/main.a") + (typescript-tsc-plain "/home/foo/greeter.ts(30,12): error TS2339: Property 'foo' does not exist." + 1 12 30 "/home/foo/greeter.ts") + (typescript-tsc-pretty "src/resources/document.ts:140:22 - error TS2362: something." + 1 22 140 "src/resources/document.ts") ;; 4bsd (edg-1 "/usr/src/foo/foo.c(8): warning: w may be used before set" 1 nil 8 "/usr/src/foo/foo.c") @@ -495,7 +499,7 @@ The test data is in `compile-tests--test-regexps-data'." (compilation-num-warnings-found 0) (compilation-num-infos-found 0)) (mapc #'compile--test-error-line compile-tests--test-regexps-data) - (should (eq compilation-num-errors-found 98)) + (should (eq compilation-num-errors-found 100)) (should (eq compilation-num-warnings-found 35)) (should (eq compilation-num-infos-found 28))))) From 1a123feb1815d6a2ee4ba6abb747fb62fd8b9e0f Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 4 Feb 2023 13:34:42 +0200 Subject: [PATCH 10/62] Fix bidi reordering of sequence of whitespace characters before a TAB * src/bidi.c (bidi_level_of_next_char): Test the current level only for characters whose original type is BN. (Bug#61269) --- src/bidi.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/bidi.c b/src/bidi.c index e01251263be..93875d243e4 100644 --- a/src/bidi.c +++ b/src/bidi.c @@ -3300,12 +3300,15 @@ bidi_level_of_next_char (struct bidi_it *bidi_it) it belongs to a sequence of WS characters preceding a newline or a TAB or a paragraph separator. */ if ((bidi_it->orig_type == NEUTRAL_WS - || bidi_it->orig_type == WEAK_BN + || (bidi_it->orig_type == WEAK_BN + /* If this BN character is already at base level, we don't + need to consider resetting it, since I1 and I2 below + will not change the level, so avoid the potentially + costly loop below. */ + && level != bidi_it->level_stack[0].level) || bidi_isolate_fmt_char (bidi_it->orig_type)) - && bidi_it->next_for_ws.charpos < bidi_it->charpos - /* If this character is already at base level, we don't need to - reset it, so avoid the potentially costly loop below. */ - && level != bidi_it->level_stack[0].level) + /* This means the informaition about WS resolution is not valid. */ + && bidi_it->next_for_ws.charpos < bidi_it->charpos) { int ch; ptrdiff_t clen = bidi_it->ch_len; @@ -3340,7 +3343,7 @@ bidi_level_of_next_char (struct bidi_it *bidi_it) || bidi_it->orig_type == NEUTRAL_S || bidi_it->ch == '\n' || bidi_it->ch == BIDI_EOB || ((bidi_it->orig_type == NEUTRAL_WS - || bidi_it->orig_type == WEAK_BN + || bidi_it->orig_type == WEAK_BN /* L1/Retaining */ || bidi_isolate_fmt_char (bidi_it->orig_type) || bidi_explicit_dir_char (bidi_it->ch)) && (bidi_it->next_for_ws.type == NEUTRAL_B From 89b550eac2909f1fcd7cc5eb3dfe81e853bf5ed0 Mon Sep 17 00:00:00 2001 From: Davide Masserut Date: Thu, 2 Feb 2023 21:00:02 +0100 Subject: [PATCH 11/62] Fix switch statement indentation for go-ts-mode (bug#61238) * lisp/progmodes/go-ts-mode.el (go-ts-mode--indent-rules): Add indentation for type switch and select case blocks * test/lisp/progmodes/go-ts-mode-resources/indent.erts: New .erts file to test indentation of Go constructs and prevent regression of bug fixes. * test/lisp/progmodes/go-ts-mode-tests.el: New file with go-ts-mode tests. --- lisp/progmodes/go-ts-mode.el | 4 ++ .../go-ts-mode-resources/indent.erts | 47 +++++++++++++++++++ test/lisp/progmodes/go-ts-mode-tests.el | 31 ++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 test/lisp/progmodes/go-ts-mode-resources/indent.erts create mode 100644 test/lisp/progmodes/go-ts-mode-tests.el diff --git a/lisp/progmodes/go-ts-mode.el b/lisp/progmodes/go-ts-mode.el index 5f3e1ea3e68..95dcf653fc6 100644 --- a/lisp/progmodes/go-ts-mode.el +++ b/lisp/progmodes/go-ts-mode.el @@ -72,6 +72,7 @@ ((node-is "labeled_statement") no-indent) ((parent-is "argument_list") parent-bol go-ts-mode-indent-offset) ((parent-is "block") parent-bol go-ts-mode-indent-offset) + ((parent-is "communication_case") parent-bol go-ts-mode-indent-offset) ((parent-is "const_declaration") parent-bol go-ts-mode-indent-offset) ((parent-is "default_case") parent-bol go-ts-mode-indent-offset) ((parent-is "expression_case") parent-bol go-ts-mode-indent-offset) @@ -82,7 +83,10 @@ ((parent-is "labeled_statement") parent-bol go-ts-mode-indent-offset) ((parent-is "literal_value") parent-bol go-ts-mode-indent-offset) ((parent-is "parameter_list") parent-bol go-ts-mode-indent-offset) + ((parent-is "select_statement") parent-bol 0) + ((parent-is "type_case") parent-bol go-ts-mode-indent-offset) ((parent-is "type_spec") parent-bol go-ts-mode-indent-offset) + ((parent-is "type_switch_statement") parent-bol 0) ((parent-is "var_declaration") parent-bol go-ts-mode-indent-offset) (no-node parent-bol 0))) "Tree-sitter indent rules for `go-ts-mode'.") diff --git a/test/lisp/progmodes/go-ts-mode-resources/indent.erts b/test/lisp/progmodes/go-ts-mode-resources/indent.erts new file mode 100644 index 00000000000..a89d69b307c --- /dev/null +++ b/test/lisp/progmodes/go-ts-mode-resources/indent.erts @@ -0,0 +1,47 @@ +Code: + (lambda () + (go-ts-mode) + (indent-region (point-min) (point-max))) + +Point-Char: | + +Name: Basic + +=-= +package main + +func main() { +} +=-=-= + +Name: Switch and Select + +=-= +package main + +func main() { + var x any + switch x { + case 1: + println("one") + default: + println("default case") + } + + switch x.(type) { + case int: + println("integer") + default: + println("don't know the type") + } + + var c chan int + select { + case x := <-c: + println(x) + default: + println("no communication") + } +} + +=-=-= diff --git a/test/lisp/progmodes/go-ts-mode-tests.el b/test/lisp/progmodes/go-ts-mode-tests.el new file mode 100644 index 00000000000..548465208f9 --- /dev/null +++ b/test/lisp/progmodes/go-ts-mode-tests.el @@ -0,0 +1,31 @@ +;;; go-ts-mode-tests.el --- Tests for Tree-sitter-based Go mode -*- lexical-binding: t; -*- + +;; Copyright (C) 2023 Free Software Foundation, Inc. + +;; This file is part of GNU Emacs. + +;; GNU Emacs is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; GNU Emacs is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs. If not, see . + +;;; Code: + +(require 'ert) +(require 'ert-x) +(require 'treesit) + +(ert-deftest go-ts-mode-test-indentation () + (skip-unless (treesit-ready-p 'go)) + (ert-test-erts-file (ert-resource-file "indent.erts"))) + +(provide 'go-ts-mode-tests) +;;; go-ts-mode-tests.el ends here From 69380a88e9292a08822eeef972d8ace639e15519 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sat, 4 Feb 2023 22:46:41 +0200 Subject: [PATCH 12/62] c-ts-mode: Highlight name in parameter declarations * lisp/progmodes/c-ts-mode.el (c-ts-mode--font-lock-settings): Uncomment parameter declaration highlighting (bug#61275). (c-ts-mode--fontify-declarator): Check that identifier was found. Some declarations can miss identifier name. --- lisp/progmodes/c-ts-mode.el | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 390f67a8e8c..2a164af26ea 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -440,11 +440,10 @@ MODE is either `c' or `cpp'." declarator: (_) @c-ts-mode--fontify-declarator) (function_definition - declarator: (_) @c-ts-mode--fontify-declarator)) + declarator: (_) @c-ts-mode--fontify-declarator) - ;; Should we highlight identifiers in the parameter list? - ;; (parameter_declaration - ;; declarator: (_) @c-ts-mode--fontify-declarator)) + (parameter_declaration + declarator: (_) @c-ts-mode--fontify-declarator)) :language mode :feature 'assignment @@ -552,9 +551,10 @@ For NODE, OVERRIDE, START, END, and ARGS, see identifier))) ("function_declarator" 'font-lock-function-name-face) (_ 'font-lock-variable-name-face)))) - (treesit-fontify-with-override - (treesit-node-start identifier) (treesit-node-end identifier) - face override start end))) + (when identifier + (treesit-fontify-with-override + (treesit-node-start identifier) (treesit-node-end identifier) + face override start end)))) (defun c-ts-mode--fontify-variable (node override start end &rest _) "Fontify an identifier node if it is a variable. From 671e5d9fad5852165f4e63992c91cd6f8c715004 Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Thu, 2 Feb 2023 18:54:49 -0800 Subject: [PATCH 13/62] ; * lisp/treesit.el (treesit--font-lock-level-setter): Minor change. --- lisp/treesit.el | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lisp/treesit.el b/lisp/treesit.el index 98f446a1456..6426eb08fe6 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -555,8 +555,12 @@ omitted, default END to BEG." "Generic tree-sitter font-lock error" 'treesit-error) +(defvar treesit-font-lock-settings) (defun treesit--font-lock-level-setter (sym val) - "Custom setter for `treesit-font-lock-level'." + "Custom setter for `treesit-font-lock-level'. +Set the default value of SYM to VAL, recompute fontification +features and refontify for every buffer where tree-sitter-based +fontification is enabled." (set-default sym val) (and (treesit-available-p) (named-let loop ((res nil) @@ -571,7 +575,7 @@ omitted, default END to BEG." res) (let ((buffer (car buffers))) (with-current-buffer buffer - (if (treesit-parser-list) + (if treesit-font-lock-settings (loop (append res (list buffer)) (cdr buffers)) (loop res (cdr buffers))))))))) From b80f36b88c76b8f8ce3f2e6f9bd56aa2ccbe7b39 Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Fri, 3 Feb 2023 18:35:33 -0800 Subject: [PATCH 14/62] Make c-ts-mode-set-style's effect local (bug#61245) Now c-ts-mode-set-style's effect is local, and there is a new function c-ts-mode-set-global-style that changes the global setting. * lisp/progmodes/c-ts-mode.el: (c-ts-mode--indent-style-setter): Use c-ts-mode-set-style. (c-ts-mode-indent-style) (c-ts-mode--prompt-for-style): Minor change in docstring. (c-ts-mode-set-global-style): New function (from c-ts-mode-set-style). (c-ts-mode-set-local-style): Remove function (became c-ts-mode-set-style). (c-ts-mode-set-style): Renamed from c-ts-mode-set-local-style. * test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts: * test/lisp/progmodes/c-ts-mode-resources/indent.erts: Use c-ts-mode-set-style. --- lisp/progmodes/c-ts-mode.el | 29 +++++++++++-------- .../c-ts-mode-resources/indent-bsd.erts | 2 +- .../progmodes/c-ts-mode-resources/indent.erts | 4 +-- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 2a164af26ea..1a8ef79dac8 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -89,18 +89,19 @@ (defun c-ts-mode--indent-style-setter (sym val) "Custom setter for `c-ts-mode-set-style'. + Apart from setting the default value of SYM to VAL, also change -the value of SYM in `c-ts-mode' and `c++-ts-mode' buffers to VAL." +the value of SYM in `c-ts-mode' and `c++-ts-mode' buffers to VAL. + +SYM should be `c-ts-mode-indent-style', and VAL should be a style +symbol." (set-default sym val) (named-let loop ((res nil) (buffers (buffer-list))) (if (null buffers) (mapc (lambda (b) (with-current-buffer b - (setq-local treesit-simple-indent-rules - (treesit--indent-rules-optimize - (c-ts-mode--get-indent-style - (if (derived-mode-p 'c-ts-mode) 'c 'cpp)))))) + (c-ts-mode-set-style val))) res) (let ((buffer (car buffers))) (with-current-buffer buffer @@ -112,8 +113,8 @@ the value of SYM in `c-ts-mode' and `c++-ts-mode' buffers to VAL." "Style used for indentation. The selected style could be one of GNU, K&R, LINUX or BSD. If -one of the supplied styles doesn't suffice a function could be -set instead. This function is expected return a list that +one of the supplied styles doesn't suffice, a function could be +set instead. This function is expected to return a list that follows the form of `treesit-simple-indent-rules'." :version "29.1" :type '(choice (symbol :tag "Gnu" gnu) @@ -134,7 +135,7 @@ MODE is either `c' or `cpp'." `((,mode ,@style)))) (defun c-ts-mode--prompt-for-style () - "Prompt for a indent style and return the symbol for it." + "Prompt for an indent style and return the symbol for it." (let ((mode (if (derived-mode-p 'c-ts-mode) 'c 'c++))) (intern (completing-read @@ -142,16 +143,20 @@ MODE is either `c' or `cpp'." (mapcar #'car (c-ts-mode--indent-styles mode)) nil t nil nil "gnu")))) -(defun c-ts-mode-set-style (style) +(defun c-ts-mode-set-global-style (style) "Set the indent style of C/C++ modes globally to STYLE. This changes the current indent style of every C/C++ buffer and -the default C/C++ indent style in this Emacs session." +the default C/C++ indent style for `c-ts-mode' and `c++-ts-mode' +in this Emacs session." (interactive (list (c-ts-mode--prompt-for-style))) (c-ts-mode--indent-style-setter 'c-ts-mode-indent-style style)) -(defun c-ts-mode-set-local-style (style) - "Set the C/C++ indent style of the current buffer to STYLE." +(defun c-ts-mode-set-style (style) + "Set the C/C++ indent style of the current buffer to STYLE. + +To set the default indent style globally, use +`c-ts-mode-set-global-style'." (interactive (list (c-ts-mode--prompt-for-style))) (if (not (derived-mode-p 'c-ts-mode 'c++-ts-mode)) (user-error "The current buffer is not in `c-ts-mode' nor `c++-ts-mode'") diff --git a/test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts b/test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts index ba4f854baf8..74e34fe821b 100644 --- a/test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts +++ b/test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts @@ -3,7 +3,7 @@ Code: (c-ts-mode) (setq-local indent-tabs-mode nil) (setq-local c-ts-mode-indent-offset 2) - (c-ts-mode-set-local-style 'bsd) + (c-ts-mode-set-style 'bsd) (indent-region (point-min) (point-max))) Point-Char: | diff --git a/test/lisp/progmodes/c-ts-mode-resources/indent.erts b/test/lisp/progmodes/c-ts-mode-resources/indent.erts index 058c6e9099c..7dcc3b0fb3a 100644 --- a/test/lisp/progmodes/c-ts-mode-resources/indent.erts +++ b/test/lisp/progmodes/c-ts-mode-resources/indent.erts @@ -3,7 +3,7 @@ Code: (c-ts-mode) (setq-local indent-tabs-mode nil) (setq-local c-ts-mode-indent-offset 2) - (c-ts-mode-set-local-style 'gnu) + (c-ts-mode-set-style 'gnu) (indent-region (point-min) (point-max))) Point-Char: | @@ -196,7 +196,7 @@ Code: (c-ts-mode) (setq-local indent-tabs-mode nil) (setq-local c-ts-mode-indent-offset 8) - (c-ts-mode-set-local-style 'linux) + (c-ts-mode-set-style 'linux) (indent-region (point-min) (point-max))) Name: Labels (Linux Style) From b40a929a3f238d48213c75f6a7613cdeaec14686 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sun, 5 Feb 2023 02:42:52 +0200 Subject: [PATCH 15/62] ; ruby-ts--syntax-propertize: Amend commentary --- lisp/progmodes/ruby-ts-mode.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lisp/progmodes/ruby-ts-mode.el b/lisp/progmodes/ruby-ts-mode.el index c0971193244..e83bc2f9e11 100644 --- a/lisp/progmodes/ruby-ts-mode.el +++ b/lisp/progmodes/ruby-ts-mode.el @@ -1059,7 +1059,8 @@ leading double colon is not added." (put-text-property (treesit-node-end node) (1+ (treesit-node-end node)) 'syntax-table (string-to-syntax "\""))) ('percent - ;; TODO: Put the first one on the first paren in both %Q{} and %(). + ;; FIXME: Put the first one on the first paren in both %Q{} and %(). + ;; That would stop electric-pair-mode from pairing, though. Hmm. (put-text-property (treesit-node-start node) (1+ (treesit-node-start node)) 'syntax-table (string-to-syntax "|")) (put-text-property (1- (treesit-node-end node)) (treesit-node-end node) From 2c33e2889b4d711689a606d175ff56931c157fb4 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 5 Feb 2023 08:24:32 +0200 Subject: [PATCH 16/62] Fix byte-compilation of *-ts-mode.el files * lisp/treesit.el (treesit-font-lock-settings): Move to before use, to prevent failure in byte-compiling modes which require this file. (Bug#61282) --- lisp/treesit.el | 49 ++++++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/lisp/treesit.el b/lisp/treesit.el index 6426eb08fe6..948016dc723 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -555,7 +555,30 @@ omitted, default END to BEG." "Generic tree-sitter font-lock error" 'treesit-error) -(defvar treesit-font-lock-settings) +(defvar-local treesit-font-lock-settings nil + "A list of SETTINGs for treesit-based fontification. + +The exact format of each SETTING is considered internal. Use +`treesit-font-lock-rules' to set this variable. + +Each SETTING has the form: + + (QUERY ENABLE FEATURE OVERRIDE) + +QUERY must be a compiled query. See Info node `(elisp)Pattern +Matching' for how to write a query and compile it. + +For SETTING to be activated for font-lock, ENABLE must be t. To +disable this SETTING, set ENABLE to nil. + +FEATURE is the \"feature name\" of the query. Users can control +which features are enabled with `treesit-font-lock-level' and +`treesit-font-lock-feature-list'. + +OVERRIDE is the override flag for this query. Its value can be +t, nil, append, prepend, keep. See more in +`treesit-font-lock-rules'.") + (defun treesit--font-lock-level-setter (sym val) "Custom setter for `treesit-font-lock-level'. Set the default value of SYM to VAL, recompute fontification @@ -638,30 +661,6 @@ See the manual for more explanations on some of the features. For changes to this variable to take effect, run `treesit-font-lock-recompute-features'.") -(defvar-local treesit-font-lock-settings nil - "A list of SETTINGs for treesit-based fontification. - -The exact format of each SETTING is considered internal. Use -`treesit-font-lock-rules' to set this variable. - -Each SETTING has the form: - - (QUERY ENABLE FEATURE OVERRIDE) - -QUERY must be a compiled query. See Info node `(elisp)Pattern -Matching' for how to write a query and compile it. - -For SETTING to be activated for font-lock, ENABLE must be t. To -disable this SETTING, set ENABLE to nil. - -FEATURE is the \"feature name\" of the query. Users can control -which features are enabled with `treesit-font-lock-level' and -`treesit-font-lock-feature-list'. - -OVERRIDE is the override flag for this query. Its value can be -t, nil, append, prepend, keep. See more in -`treesit-font-lock-rules'.") - (defun treesit-font-lock-rules (&rest query-specs) "Return a value suitable for `treesit-font-lock-settings'. From 0358267204d1c9ddeff46aac168c6a8c5d173d95 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 5 Feb 2023 10:50:12 +0200 Subject: [PATCH 17/62] Update the Emacs FAQ for Emacs 29 * doc/misc/efaq.texi (New in Emacs 29, History of Emacs): Add new section about Emacs 29. --- doc/misc/efaq.texi | 120 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/doc/misc/efaq.texi b/doc/misc/efaq.texi index 396a4753842..4a8c863230f 100644 --- a/doc/misc/efaq.texi +++ b/doc/misc/efaq.texi @@ -847,6 +847,7 @@ in the Emacs development repository (@pxref{Latest version of Emacs}). @menu * Origin of the term Emacs:: * Latest version of Emacs:: +* New in Emacs 29:: * New in Emacs 28:: * New in Emacs 27:: * New in Emacs 26:: @@ -919,6 +920,125 @@ Emacs, type @kbd{C-h C-n} (@kbd{M-x view-emacs-news}). You can give this command a prefix argument to read about which features were new in older versions. +@node New in Emacs 29 +@section What is different about Emacs 29? +@cindex Differences between Emacs 28 and Emacs 29 +@cindex Emacs 29, new features in + +Here's a list of the most important changes in Emacs 29 as compared to +Emacs 28 (the full list is too long, and can be read in the Emacs +@file{NEWS} file by typing @kbd{C-h n} inside Emacs). + +@itemize +@item +Emacs can now be built with the +@uref{https://tree-sitter.github.io/tree-sitter/, tree-sitter +library}, which provides incremental parsing capabilities for several +programming languages. Emacs comes with several major modes which use +this library for syntax highlighting (a.k.a. ``fontification''), +indentation, Imenu support, etc. These modes have names +@code{@var{lang}-ts-mode}, where @var{lang} is the programming +language. For example, @code{c-ts-mode}, @code{ruby-ts-mode}, etc. +There are several new font-lock faces, such as +@code{font-lock-number-face} and @code{font-lock-operator-face}, +intended to be used with these modes. + +@item +Emacs can now be built in the PGTK (``pure GTK'') configuration, which +supports running Emacs on window systems other than X, such as Wayland +and Broadway. + +@item +Emacs now has built-in support for accessing SQLite databases. This +requires Emacs to be built with the optional @file{sqlite3} library. + +@item +Emacs comes with the popular @code{use-package} package bundled. + +@item +Emacs can now display WebP images, if it was built with the optional +@file{libwebp} library. + +@item +On X window system, Emacs now supports the XInput2 specification for +input events. + +@item +Emacs now comes with a client library for using Language Server +Protocol (@acronym{LSP}) servers. This library, named @file{eglot.el} +(the name stands for ``Emacs polyGlot'') provides LSP support for +various software development and maintenance features, such as +@code{xref}, Imenu, ElDoc, etc. + +@item +Emacs can now cope with files with very long lines much better. It no +longer hangs when displaying such long lines, and allows +reasonably-responsive editing when such lines are present in the +visible portion of a buffer. + +@item +Emacs now supports the latest version 15.0 of the Unicode Standard. + +@item +The new mode @code{pixel-scroll-precision-mode} allows precise and +smooth scrolling of the display at pixel resolution, if your mouse +supports this. + +@item +Emacs now supports 24-bit true colors on more terminals. + +@item +On capable X terminal emulators, Emacs now supports setting the X +primary selection on TTY frames. + +@item +New convenient commands are now available for inserting, searching, +listing, and describing Emoji. These commands are on the @w{@kbd{C-x +8 e}} prefix key. The commands @kbd{C-u C-x =} +(@code{what-cursor-position}) and @kbd{M-x describe-char} now show the +names of Emoji sequences at point. + +@item +The Help commands were enhanced: + +@itemize @minus +@item +@kbd{M-x apropos-variable} shows the values of the matching variables. +@item +@kbd{C-h b} activates @code{outline-minor-mode} in the buffer, which +makes it easier to browse long lists of key bindings. +@item +@kbd{I} in the @file{*Help*} buffer displays the corresponding +documentation in the Emacs Lisp Reference manual. +@item +New command @code{help-quick} displays a buffer with overview of +common Help commands. +@end itemize + +@item +Outline Minor mode uses buttons to hide and show outlines. + +@item +Deleted frames can now be undeleted using @kbd{C-x 5 u}, if the +optional @code{undelete-frame-mode} is enabled. + +@item +You can now delete the entire composed sequence of characters with +@key{Delete} and edits the composed sequence by turning on the +@code{composition-break-at-point} option. + +@item +Support is added for many old scripts and writing systems, such as Tai +Tham, Brahmi, Tirhuta, Modi, Lepcha, and many others. + +@item +New translations of the Emacs tutorial: Ukrainian and Greek. + +@item +New major modes for Typescript, Csharp, CMake, Go, Rust, and Yaml. +@end itemize + + @node New in Emacs 28 @section What is different about Emacs 28? @cindex Differences between Emacs 27 and Emacs 28 From f13479d95566e234a70001f02d4209f145e3729a Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 5 Feb 2023 11:14:25 +0200 Subject: [PATCH 18/62] Fix installation of tree-sitter grammar on MS-Windows * lisp/treesit.el (treesit--install-language-grammar-1): Fix a failure on MS-Windows when the old DLL is still being used. (Bug#61289) --- lisp/treesit.el | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/lisp/treesit.el b/lisp/treesit.el index 948016dc723..7e31da95ef4 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -2884,7 +2884,17 @@ function signals an error." ;; Copy out. (unless (file-exists-p out-dir) (make-directory out-dir t)) - (copy-file lib-name (file-name-as-directory out-dir) t t) + (let* ((library-fname (expand-file-name lib-name out-dir)) + (old-fname (concat library-fname ".old"))) + ;; Rename the existing shared library, if any, then + ;; install the new one, and try deleting the old one. + ;; This is for Windows systems, where we cannot simply + ;; overwrite a DLL that is being used. + (if (file-exists-p library-fname) + (rename-file library-fname old-fname t)) + (copy-file lib-name (file-name-as-directory out-dir) t t) + ;; Ignore errors, in case the old version is still used. + (ignore-errors (delete-file old-fname))) (message "Library installed to %s/%s" out-dir lib-name)) (when (file-exists-p workdir) (delete-directory workdir t))))) From 03d9d18513b6ec50d0022f09d040ce330c918fff Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 5 Feb 2023 13:57:10 +0200 Subject: [PATCH 19/62] Fix display of raised/lowered composed text * src/xdisp.c (fill_gstring_glyph_string): Adjust the base line of the glyph string due to subscript/superscript. (Bug#61290) --- src/xdisp.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/xdisp.c b/src/xdisp.c index d2c91e5847b..a19c9908616 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -29317,6 +29317,7 @@ fill_gstring_glyph_string (struct glyph_string *s, int face_id, int start, int end, int overlaps) { struct glyph *glyph, *last; + int voffset; Lisp_Object lgstring; int i; bool glyph_not_available_p; @@ -29324,6 +29325,7 @@ fill_gstring_glyph_string (struct glyph_string *s, int face_id, s->for_overlaps = overlaps; glyph = s->row->glyphs[s->area] + start; last = s->row->glyphs[s->area] + end; + voffset = glyph->voffset; glyph_not_available_p = glyph->glyph_not_available_p; s->cmp_id = glyph->u.cmp.id; s->cmp_from = glyph->slice.cmp.from; @@ -29374,6 +29376,9 @@ fill_gstring_glyph_string (struct glyph_string *s, int face_id, if (glyph_not_available_p) s->font_not_found_p = true; + /* Adjust base line for subscript/superscript text. */ + s->ybase += voffset; + return glyph - s->row->glyphs[s->area]; } From 96181ed3f09b12c7e91ddabab5b02f0ee868fa50 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 5 Feb 2023 14:09:35 +0200 Subject: [PATCH 20/62] Document 'plistp' * doc/lispref/lists.texi (Property Lists): Document 'plistp'. (Bug#61293) --- doc/lispref/lists.texi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/lispref/lists.texi b/doc/lispref/lists.texi index 44b7058e19d..454fd217ac2 100644 --- a/doc/lispref/lists.texi +++ b/doc/lispref/lists.texi @@ -1914,6 +1914,11 @@ properties. Every symbol possesses a list of properties, used to record miscellaneous information about the symbol; these properties are stored in the form of a property list. @xref{Symbol Properties}. +@defun plistp object +This predicate function returns non-@code{nil} if @var{object} is a +valid property list. +@end defun + @menu * Plists and Alists:: Comparison of the advantages of property lists and association lists. From 1dd751c3ac4e4276b461b83df7d9c4d002cf016e Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 5 Feb 2023 15:15:35 +0200 Subject: [PATCH 21/62] ; Improve documentation of 'proper-list-p' * doc/lispref/lists.texi (Cons Cells): Add cross-reference to 'proper-list-p' documentation. --- doc/lispref/lists.texi | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/lispref/lists.texi b/doc/lispref/lists.texi index 454fd217ac2..f3758f5ce60 100644 --- a/doc/lispref/lists.texi +++ b/doc/lispref/lists.texi @@ -79,7 +79,10 @@ circular or dotted. If a program doesn't look far enough down the list to see the @sc{cdr} of the final cons cell, it won't care. However, some functions that operate on lists demand proper lists and signal errors if given a dotted list. Most functions that try to find -the end of a list enter infinite loops if given a circular list. +the end of a list enter infinite loops if given a circular list. You +can use the function @code{proper-list-p}, described in the next +section (@pxref{List-related Predicates, proper-list-p}), to determine +whether a list is a proper one. @cindex list structure Because most cons cells are used as part of lists, we refer to any From 0c125fcc67a47b933716124223404a45e73357c7 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sun, 5 Feb 2023 15:46:28 +0200 Subject: [PATCH 22/62] Make highlighting more regular across TS modes (bug#61205) * doc/emacs/display.texi (Parser-based Font Lock): Update description of treesit-font-lock-level, moving 'property' to level 4. * lisp/treesit.el (treesit-font-lock-level): Likewise, in docstring. * lisp/progmodes/c-ts-mode.el (c-ts-base-mode): Do that here. * lisp/progmodes/cmake-ts-mode.el (cmake-ts-mode): Add a comment. * lisp/progmodes/go-ts-mode.el (go-ts-mode): Add 'definition' to level 1. Move 'function', 'property' and 'variable' to level 4. (go-ts-mode--font-lock-settings): Move a bunch of existing rules to 'definition'. Add highlighting of function parameters. * lisp/progmodes/rust-ts-mode.el (rust-ts-mode) (rust-ts-mode--font-lock-settings): Same. And also change "scoped identifiers" highlights to only match capitalized names. --- doc/emacs/display.texi | 4 ++-- lisp/progmodes/c-ts-mode.el | 4 ++-- lisp/progmodes/cmake-ts-mode.el | 3 +++ lisp/progmodes/go-ts-mode.el | 26 +++++++++++++++--------- lisp/progmodes/rust-ts-mode.el | 35 ++++++++++++++++++++------------- lisp/treesit.el | 5 +++-- 6 files changed, 48 insertions(+), 29 deletions(-) diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi index 97732b65e32..a86c12a0db7 100644 --- a/doc/emacs/display.texi +++ b/doc/emacs/display.texi @@ -1159,11 +1159,11 @@ function definitions. This level adds fontification of keywords, strings, and data types. @item Level 3 This is the default level; it adds fontification of assignments, -numbers, properties, etc. +numbers, etc. @item Level 4 This level adds everything else that can be fontified: operators, delimiters, brackets, other punctuation, function names in function -calls, variables, etc. +calls, property look ups, variables, etc. @end table @vindex treesit-font-lock-feature-list diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 1a8ef79dac8..5093c3980b6 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -779,8 +779,8 @@ the semicolon. This function skips the semicolon." (setq-local treesit-font-lock-feature-list '(( comment definition) ( keyword preprocessor string type) - ( assignment constant escape-sequence label literal property ) - ( bracket delimiter error function operator variable)))) + ( assignment constant escape-sequence label literal) + ( bracket delimiter error function operator property variable)))) ;;;###autoload (define-derived-mode c-ts-mode c-ts-base-mode "C" diff --git a/lisp/progmodes/cmake-ts-mode.el b/lisp/progmodes/cmake-ts-mode.el index c241a2868e5..04f5d6bdac8 100644 --- a/lisp/progmodes/cmake-ts-mode.el +++ b/lisp/progmodes/cmake-ts-mode.el @@ -220,6 +220,9 @@ the subtrees." (setq-local treesit-font-lock-feature-list '((comment) (keyword string) + ;; 'function' and 'variable' here play slightly + ;; different roles than in other ts modes, so we + ;; kept them at level 3. (builtin constant escape-sequence function number variable) (bracket error misc-punctuation))) diff --git a/lisp/progmodes/go-ts-mode.el b/lisp/progmodes/go-ts-mode.el index 95dcf653fc6..4b14e55281e 100644 --- a/lisp/progmodes/go-ts-mode.el +++ b/lisp/progmodes/go-ts-mode.el @@ -123,17 +123,26 @@ :feature 'delimiter '((["," "." ";" ":"]) @font-lock-delimiter-face) + :language 'go + :feature 'definition + '((function_declaration + name: (identifier) @font-lock-function-name-face) + (method_declaration + name: (field_identifier) @font-lock-function-name-face) + (method_spec + name: (field_identifier) @font-lock-function-name-face) + (field_declaration + name: (field_identifier) @font-lock-property-face) + (parameter_declaration + name: (identifier) @font-lock-variable-name-face)) + :language 'go :feature 'function '((call_expression function: (identifier) @font-lock-function-name-face) (call_expression function: (selector_expression - field: (field_identifier) @font-lock-function-name-face)) - (function_declaration - name: (identifier) @font-lock-function-name-face) - (method_declaration - name: (field_identifier) @font-lock-function-name-face)) + field: (field_identifier) @font-lock-function-name-face))) :language 'go :feature 'keyword @@ -221,11 +230,10 @@ ;; Font-lock. (setq-local treesit-font-lock-settings go-ts-mode--font-lock-settings) (setq-local treesit-font-lock-feature-list - '(( comment) + '(( comment definition) ( keyword string type) - ( constant escape-sequence function label number - property variable) - ( bracket delimiter error operator))) + ( constant escape-sequence label number) + ( bracket delimiter error function operator property variable))) (treesit-major-mode-setup))) diff --git a/lisp/progmodes/rust-ts-mode.el b/lisp/progmodes/rust-ts-mode.el index e317793d211..5722d037bba 100644 --- a/lisp/progmodes/rust-ts-mode.el +++ b/lisp/progmodes/rust-ts-mode.el @@ -155,6 +155,16 @@ :feature 'delimiter '((["," "." ";" ":" "::"]) @font-lock-delimiter-face) + :language 'rust + :feature 'definition + '((function_item name: (identifier) @font-lock-function-name-face) + (macro_definition "macro_rules!" @font-lock-constant-face) + (macro_definition (identifier) @font-lock-preprocessor-face) + (field_declaration name: (field_identifier) @font-lock-property-face) + (parameter pattern: (identifier) @font-lock-variable-name-face) + (parameter + pattern: (reference_pattern (identifier) @font-lock-variable-name-face))) + :language 'rust :feature 'function '((call_expression @@ -164,15 +174,12 @@ field: (field_identifier) @font-lock-function-name-face) (scoped_identifier name: (identifier) @font-lock-function-name-face)]) - (function_item (identifier) @font-lock-function-name-face) (generic_function function: [(identifier) @font-lock-function-name-face (field_expression field: (field_identifier) @font-lock-function-name-face) (scoped_identifier name: (identifier) @font-lock-function-name-face)]) - (macro_definition "macro_rules!" @font-lock-constant-face) - (macro_definition (identifier) @font-lock-preprocessor-face) (macro_invocation macro: (identifier) @font-lock-preprocessor-face)) :language 'rust @@ -208,20 +215,20 @@ (mod_item name: (identifier) @font-lock-constant-face) (primitive_type) @font-lock-type-face (type_identifier) @font-lock-type-face - (scoped_identifier name: (identifier) @font-lock-type-face) - (scoped_identifier path: (identifier) @font-lock-constant-face) - (scoped_identifier - (scoped_identifier - path: (identifier) @font-lock-constant-face)) + ((scoped_identifier name: (identifier) @font-lock-type-face) + (:match "^[A-Z]" @font-lock-type-face)) + ((scoped_identifier path: (identifier) @font-lock-type-face) + (:match "^[A-Z]" @font-lock-type-face)) + ((scoped_identifier + (scoped_identifier + path: (identifier) @font-lock-type-face)) + (:match "^[A-Z]" @font-lock-type-face)) ((scoped_identifier path: [(identifier) @font-lock-type-face (scoped_identifier name: (identifier) @font-lock-type-face)]) (:match "^[A-Z]" @font-lock-type-face)) (scoped_type_identifier path: (identifier) @font-lock-constant-face) - (scoped_use_list - path: [(identifier) @font-lock-constant-face - (scoped_identifier (identifier) @font-lock-constant-face)]) (type_identifier) @font-lock-type-face (use_as_clause alias: (identifier) @font-lock-type-face) (use_list (identifier) @font-lock-type-face)) @@ -317,11 +324,11 @@ delimiters < and >'s." ;; Font-lock. (setq-local treesit-font-lock-settings rust-ts-mode--font-lock-settings) (setq-local treesit-font-lock-feature-list - '(( comment) + '(( comment definition) ( keyword string) ( attribute builtin constant escape-sequence - function number property type variable) - ( bracket delimiter error operator))) + number type) + ( bracket delimiter error function operator property variable))) ;; Imenu. (setq-local treesit-simple-imenu-settings diff --git a/lisp/treesit.el b/lisp/treesit.el index 7e31da95ef4..7bd68c9a6d9 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -612,9 +612,10 @@ fontifications. Level 1 usually contains only comments and definitions. Level 2 usually adds keywords, strings, data types, etc. Level 3 usually represents full-blown fontifications, including -assignments, constants, numbers and literals, properties, etc. +assignments, constants, numbers and literals, etc. Level 4 adds everything else that can be fontified: delimiters, -operators, brackets, punctuation, all functions and variables, etc. +operators, brackets, punctuation, all functions, properties, +variables, etc. In addition to the decoration level, individual features can be turned on/off by calling `treesit-font-lock-recompute-features'. From 58dc03ba7e4c67027f49ed9f741ceb68de262f72 Mon Sep 17 00:00:00 2001 From: Jonas Bernoulli Date: Wed, 1 Feb 2023 20:25:15 +0100 Subject: [PATCH 23/62] No longer use transient in isearch-emoji-by-name * lisp/isearch.el (isearch-emoji-by-name): Use 'emoji--read-emoji' and if that returns derivations, 'completing-read' to select one of them. This fixes bug#60740. * lisp/international/emoji.el (emoji--init): Autoload. (emoji--read-emoji): New function, which doesn't use transient and returns a list of the glyph and all derivations, if any. (emoji--choose-emoji): Use 'emoji--read-emoji'. --- lisp/international/emoji.el | 36 ++++++++++++++++++++---------------- lisp/isearch.el | 20 ++++++++------------ 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/lisp/international/emoji.el b/lisp/international/emoji.el index 2d17cf639b0..f75bd877991 100644 --- a/lisp/international/emoji.el +++ b/lisp/international/emoji.el @@ -245,6 +245,7 @@ the name is not known." (error "Emoji name is unknown") (message "%s" name))))) +;;;###autoload (defun emoji--init (&optional force inhibit-adjust) (when (or (not emoji--labels) force) @@ -638,7 +639,7 @@ We prefer the earliest unique letter." collect (cons (concat (string prefix) "-group") (seq-take bit 77)))))))) -(defun emoji--choose-emoji () +(defun emoji--read-emoji () ;; Use the list of names. (let* ((table (if (not emoji-alternate-names) @@ -678,21 +679,24 @@ We prefer the earliest unique letter." (complete-with-action action table string pred))) nil t))) (when (cl-plusp (length name)) - (let* ((glyph (if emoji-alternate-names - (cadr (split-string name "\t")) - (gethash name emoji--all-bases))) - (derived (gethash glyph emoji--derived))) - (if (not derived) - ;; Simple glyph with no derivations. - (progn - (emoji--add-recent glyph) - (insert glyph)) - ;; Choose a derived version. - (let ((emoji--done-derived (make-hash-table :test #'equal))) - (setf (gethash glyph emoji--done-derived) t) - (funcall - (emoji--define-transient - (cons "Choose Emoji" (cons glyph derived)))))))))) + (let ((glyph (if emoji-alternate-names + (cadr (split-string name "\t")) + (gethash name emoji--all-bases)))) + (cons glyph (gethash glyph emoji--derived)))))) + +(defun emoji--choose-emoji () + (pcase-let ((`(,glyph ,derived)) (emoji--read-emoji)) + (if (not derived) + ;; Simple glyph with no derivations. + (progn + (emoji--add-recent glyph) + (insert glyph)) + ;; Choose a derived version. + (let ((emoji--done-derived (make-hash-table :test #'equal))) + (setf (gethash glyph emoji--done-derived) t) + (funcall + (emoji--define-transient + (cons "Choose Emoji" (cons glyph derived)))))))) (defvar-keymap emoji-zoom-map "+" #'emoji-zoom-increase diff --git a/lisp/isearch.el b/lisp/isearch.el index 22e27764127..bfa71756146 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -2774,25 +2774,21 @@ With argument, add COUNT copies of the character." (mapconcat 'isearch-text-char-description string "")))))))) -(defvar emoji--derived) (defun isearch-emoji-by-name (&optional count) "Read an Emoji name and add it to the search string COUNT times. COUNT (interactively, the prefix argument) defaults to 1. The command accepts Unicode names like \"smiling face\" or \"heart with arrow\", and completion is available." (interactive "p") + (emoji--init) (with-isearch-suspended - (let ((emoji (with-temp-buffer - ;; Derived emoji not supported yet (bug#60740). - ;; So first load `emoji--labels', then `emoji--init' - ;; will not fill `emoji--derived' that is set - ;; to an empty hash table below. - (ignore-errors (require 'emoji-labels)) - (let ((emoji--derived (make-hash-table :test #'equal))) - (emoji-search)) - (if (and (integerp count) (> count 1)) - (apply 'concat (make-list count (buffer-string))) - (buffer-string))))) + (pcase-let* ((`(,glyph . ,derived) (emoji--read-emoji)) + (emoji (if derived + (completing-read "Select derivation: " + (cons glyph derived) nil t) + glyph))) + (when (and (integerp count) (> count 1)) + (setq emoji (apply 'concat (make-list count emoji)))) (when emoji (setq isearch-new-string (concat isearch-string emoji) isearch-new-message (concat isearch-message From 3ffd0eddce651aabefedf10249ebd9d6e7b5b8fa Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sun, 5 Feb 2023 16:43:59 +0200 Subject: [PATCH 24/62] Highlight more complex function parameters * lisp/progmodes/rust-ts-mode.el (rust-ts-mode--fontify-parameter): New function. (rust-ts-mode--font-lock-settings): Use it. --- lisp/progmodes/rust-ts-mode.el | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/lisp/progmodes/rust-ts-mode.el b/lisp/progmodes/rust-ts-mode.el index 5722d037bba..e46fa0342dd 100644 --- a/lisp/progmodes/rust-ts-mode.el +++ b/lisp/progmodes/rust-ts-mode.el @@ -161,9 +161,7 @@ (macro_definition "macro_rules!" @font-lock-constant-face) (macro_definition (identifier) @font-lock-preprocessor-face) (field_declaration name: (field_identifier) @font-lock-property-face) - (parameter pattern: (identifier) @font-lock-variable-name-face) - (parameter - pattern: (reference_pattern (identifier) @font-lock-variable-name-face))) + (parameter) @rust-ts-mode--fontify-parameter) :language 'rust :feature 'function @@ -256,6 +254,18 @@ '((ERROR) @font-lock-warning-face)) "Tree-sitter font-lock settings for `rust-ts-mode'.") +(defalias 'rust-ts-mode--fontify-parameter + (and + (treesit-available-p) + `(lambda (node override start end &rest _) + (let ((captures (treesit-query-capture + (treesit-node-child-by-field-name node "pattern") + ,(treesit-query-compile 'rust '((identifier) @id))))) + (pcase-dolist (`(_name . ,id) captures) + (treesit-fontify-with-override + (treesit-node-start id) (treesit-node-end id) + 'font-lock-variable-name-face override start end)))))) + (defun rust-ts-mode--defun-name (node) "Return the defun name of NODE. Return nil if there is no name or if NODE is not a defun node." From 94f291d1505a6eccc3d7503992265f9e15101c86 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 5 Feb 2023 17:27:43 +0200 Subject: [PATCH 25/62] ; * lisp/paren.el (show-paren-predicate): Doc fix. (Bug#61098) --- lisp/paren.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lisp/paren.el b/lisp/paren.el index b2a79624c0f..d1623a2b248 100644 --- a/lisp/paren.el +++ b/lisp/paren.el @@ -122,7 +122,8 @@ On non-graphical frames, the context is shown in the echo area." "Whether to use `show-paren-mode' in a buffer. The default is to enable the mode in all buffers that don't derive from `special-mode', which means that it's on (by default) -in all editing buffers." +in all editing buffers. +The predicate is passed as argument to `buffer-match-p', which see." :type 'buffer-predicate :safe #'booleanp :version "29.1") From 18c43bb9d6ced167aa315b4485b6283247e8b127 Mon Sep 17 00:00:00 2001 From: Alan Mackenzie Date: Sun, 5 Feb 2023 15:59:44 +0000 Subject: [PATCH 26/62] Ensure upper bound of font-lock region is less than point-max This fixes bug #61298. The new long-lines code may have narrowed a buffer before font-lock-default-fontify-region gets called. * lisp/font-lock.el (font-lock-default-fontify-region): Set `end' to point-max if it is greater that it. --- lisp/font-lock.el | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lisp/font-lock.el b/lisp/font-lock.el index 1fa45379b9f..9e944fe188a 100644 --- a/lisp/font-lock.el +++ b/lisp/font-lock.el @@ -1154,6 +1154,8 @@ Put first the functions more likely to cause a change and cheaper to compute.") "Fontify the text between BEG and END. If LOUDLY is non-nil, print status messages while fontifying. This function is the default `font-lock-fontify-region-function'." + (or (<= end (point-max)) + (setq end (point-max))) (with-silent-modifications ;; Use the fontification syntax table, if any. (with-syntax-table (or font-lock-syntax-table (syntax-table)) From 85705a7059f33e43b2395552beb9a01d32d76a5e Mon Sep 17 00:00:00 2001 From: Jonas Bernoulli Date: Sun, 5 Feb 2023 17:19:15 +0100 Subject: [PATCH 27/62] ; Move misplaces parenthesis in emoji--choose-emoji * lisp/international/emoji.el (emoji--choose-emoji): Move misplaced parenthesis. --- lisp/international/emoji.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/international/emoji.el b/lisp/international/emoji.el index f75bd877991..18fc167974c 100644 --- a/lisp/international/emoji.el +++ b/lisp/international/emoji.el @@ -685,7 +685,7 @@ We prefer the earliest unique letter." (cons glyph (gethash glyph emoji--derived)))))) (defun emoji--choose-emoji () - (pcase-let ((`(,glyph ,derived)) (emoji--read-emoji)) + (pcase-let ((`(,glyph ,derived) (emoji--read-emoji))) (if (not derived) ;; Simple glyph with no derivations. (progn From d12727057d49df72df9da185e62e8a2caece249b Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sun, 5 Feb 2023 18:19:04 +0200 Subject: [PATCH 28/62] rust-ts-mode--indent-rules: Indent to 0 at top level --- lisp/progmodes/rust-ts-mode.el | 1 + 1 file changed, 1 insertion(+) diff --git a/lisp/progmodes/rust-ts-mode.el b/lisp/progmodes/rust-ts-mode.el index e46fa0342dd..f7a8a97cc5a 100644 --- a/lisp/progmodes/rust-ts-mode.el +++ b/lisp/progmodes/rust-ts-mode.el @@ -69,6 +69,7 @@ (defvar rust-ts-mode--indent-rules `((rust + ((parent-is "source_file") point-min 0) ((node-is ")") parent-bol 0) ((node-is "]") parent-bol 0) ((node-is "}") (and parent parent-bol) 0) From e38ff004631805672aa07e3e7a87ae2e8d948a02 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sun, 5 Feb 2023 18:49:24 +0200 Subject: [PATCH 29/62] rust-ts-mode: Highlight variable declarations (rust-ts-mode--font-lock-settings): Change scoped_type_identifier highlight to match similar cases. Highlight variable declarations inside all kinds of destructuring patterns, not just function definitions. * lisp/progmodes/rust-ts-mode.el (rust-ts-mode--fontify-pattern): Rename from 'rust-ts-mode--fontify-parameter'. Check the id node's parent to avoid touching type identifiers. --- lisp/progmodes/rust-ts-mode.el | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/lisp/progmodes/rust-ts-mode.el b/lisp/progmodes/rust-ts-mode.el index f7a8a97cc5a..3beaa741605 100644 --- a/lisp/progmodes/rust-ts-mode.el +++ b/lisp/progmodes/rust-ts-mode.el @@ -162,7 +162,11 @@ (macro_definition "macro_rules!" @font-lock-constant-face) (macro_definition (identifier) @font-lock-preprocessor-face) (field_declaration name: (field_identifier) @font-lock-property-face) - (parameter) @rust-ts-mode--fontify-parameter) + (parameter) @rust-ts-mode--fontify-pattern + (let_declaration) @rust-ts-mode--fontify-pattern + (for_expression) @rust-ts-mode--fontify-pattern + (let_condition) @rust-ts-mode--fontify-pattern + (match_arm) @rust-ts-mode--fontify-pattern) :language 'rust :feature 'function @@ -227,7 +231,7 @@ (scoped_identifier name: (identifier) @font-lock-type-face)]) (:match "^[A-Z]" @font-lock-type-face)) - (scoped_type_identifier path: (identifier) @font-lock-constant-face) + (scoped_type_identifier path: (identifier) @font-lock-type-face) (type_identifier) @font-lock-type-face (use_as_clause alias: (identifier) @font-lock-type-face) (use_list (identifier) @font-lock-type-face)) @@ -255,17 +259,21 @@ '((ERROR) @font-lock-warning-face)) "Tree-sitter font-lock settings for `rust-ts-mode'.") -(defalias 'rust-ts-mode--fontify-parameter +(defalias 'rust-ts-mode--fontify-pattern (and (treesit-available-p) `(lambda (node override start end &rest _) (let ((captures (treesit-query-capture (treesit-node-child-by-field-name node "pattern") - ,(treesit-query-compile 'rust '((identifier) @id))))) + ,(treesit-query-compile 'rust '((identifier) @id + (shorthand_field_identifier) @id))))) (pcase-dolist (`(_name . ,id) captures) - (treesit-fontify-with-override - (treesit-node-start id) (treesit-node-end id) - 'font-lock-variable-name-face override start end)))))) + (unless (string-match-p "\\`scoped_\\(?:type_\\)?identifier\\'" + (treesit-node-type + (treesit-node-parent id))) + (treesit-fontify-with-override + (treesit-node-start id) (treesit-node-end id) + 'font-lock-variable-name-face override start end))))))) (defun rust-ts-mode--defun-name (node) "Return the defun name of NODE. From d7b4a8487f64527d5913f7094b12266d012180c1 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 5 Feb 2023 18:51:11 +0200 Subject: [PATCH 30/62] ; * lisp/isearch.el (emoji--read-emoji): Avoid compilation warning. --- lisp/isearch.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/isearch.el b/lisp/isearch.el index bfa71756146..62ac6f129fc 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -2773,7 +2773,7 @@ With argument, add COUNT copies of the character." isearch-new-message (concat isearch-message (mapconcat 'isearch-text-char-description string "")))))))) - +(autoload 'emoji--read-emoji "emoji") (defun isearch-emoji-by-name (&optional count) "Read an Emoji name and add it to the search string COUNT times. COUNT (interactively, the prefix argument) defaults to 1. From 929daafa1d6ca786507e726e21aa295c3b4afe00 Mon Sep 17 00:00:00 2001 From: Jonas Bernoulli Date: Sun, 5 Feb 2023 17:50:10 +0100 Subject: [PATCH 31/62] ; Fix trivial mistake in emoji--choose-emoji * lisp/international/emoji.el (emoji--choose-emoji): The derived versions are in the cdr not cadr. --- lisp/international/emoji.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/international/emoji.el b/lisp/international/emoji.el index 18fc167974c..bcd4aac4f29 100644 --- a/lisp/international/emoji.el +++ b/lisp/international/emoji.el @@ -685,7 +685,7 @@ We prefer the earliest unique letter." (cons glyph (gethash glyph emoji--derived)))))) (defun emoji--choose-emoji () - (pcase-let ((`(,glyph ,derived) (emoji--read-emoji))) + (pcase-let ((`(,glyph . ,derived) (emoji--read-emoji))) (if (not derived) ;; Simple glyph with no derivations. (progn From bb999df5d6f26bb1214ffad844a8b6fbf18c682e Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 5 Feb 2023 18:52:59 +0200 Subject: [PATCH 32/62] ; Fix whitespace of last change --- lisp/isearch.el | 1 + 1 file changed, 1 insertion(+) diff --git a/lisp/isearch.el b/lisp/isearch.el index 62ac6f129fc..094e02d605e 100644 --- a/lisp/isearch.el +++ b/lisp/isearch.el @@ -2773,6 +2773,7 @@ With argument, add COUNT copies of the character." isearch-new-message (concat isearch-message (mapconcat 'isearch-text-char-description string "")))))))) + (autoload 'emoji--read-emoji "emoji") (defun isearch-emoji-by-name (&optional count) "Read an Emoji name and add it to the search string COUNT times. From 24085ba6105712ec601f94a5941da5c7f034f5fb Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sun, 5 Feb 2023 18:52:57 +0200 Subject: [PATCH 33/62] ; go-ts-mode--indent-rules: Indent to 0 at top level --- lisp/progmodes/go-ts-mode.el | 1 + 1 file changed, 1 insertion(+) diff --git a/lisp/progmodes/go-ts-mode.el b/lisp/progmodes/go-ts-mode.el index 4b14e55281e..e5b7bcca9aa 100644 --- a/lisp/progmodes/go-ts-mode.el +++ b/lisp/progmodes/go-ts-mode.el @@ -66,6 +66,7 @@ (defvar go-ts-mode--indent-rules `((go + ((parent-is "source_file") point-min 0) ((node-is ")") parent-bol 0) ((node-is "]") parent-bol 0) ((node-is "}") parent-bol 0) From 6568a1aaf9a97107947e801d1c3328a3119f0957 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sun, 5 Feb 2023 19:06:47 +0200 Subject: [PATCH 34/62] Fix inability to turn show-paren-local-mode on manually (bug#61098) * lisp/paren.el (show-paren-local-mode): Don't kill the local value when both local and global are t. Because the show-paren-predicate check in show-paren-function also checks whether a local (non-nil) value of this variable exists. --- lisp/paren.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lisp/paren.el b/lisp/paren.el index d1623a2b248..7ee4e9ae682 100644 --- a/lisp/paren.el +++ b/lisp/paren.el @@ -166,8 +166,8 @@ use `show-paren-local-mode'." (cond ((eq show-paren-mode (default-value 'show-paren-mode)) (unless show-paren-mode - (show-paren--delete-overlays)) - (kill-local-variable 'show-paren-mode)) + (show-paren--delete-overlays) + (kill-local-variable 'show-paren-mode))) ((not (default-value 'show-paren-mode)) ;; Locally enabled, but globally disabled. (show-paren-mode 1) ; Setup the timer. From 948e343496bce96fcc5f2ccb702e4be2c549096e Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 5 Feb 2023 19:10:39 +0200 Subject: [PATCH 35/62] ; Fix byte-compilation warning * lisp/progmodes/rust-ts-mode.el (treesit-query-compile): Avoid byte-compilation warning. --- lisp/progmodes/rust-ts-mode.el | 1 + 1 file changed, 1 insertion(+) diff --git a/lisp/progmodes/rust-ts-mode.el b/lisp/progmodes/rust-ts-mode.el index 3beaa741605..571e268c221 100644 --- a/lisp/progmodes/rust-ts-mode.el +++ b/lisp/progmodes/rust-ts-mode.el @@ -38,6 +38,7 @@ (declare-function treesit-node-start "treesit.c") (declare-function treesit-node-type "treesit.c") (declare-function treesit-node-parent "treesit.c") +(declare-function treesit-query-compile "treesit.c") (defcustom rust-ts-mode-indent-offset 4 "Number of spaces for each indentation step in `rust-ts-mode'." From 26e947ccb1453defcfce080cdc5ea7ca2cb8917e Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Sun, 5 Feb 2023 20:23:57 +0200 Subject: [PATCH 36/62] * lisp/vc/vc.el (vc-find-revision-no-save): Fix parens (bug#61256). Move '(setq failed nil)' from UNWINDFORMS of 'unwind-protect' to BODYFORM. --- lisp/vc/vc.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index a181765eac3..4ba62c0b3c7 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -2342,8 +2342,8 @@ Unlike `vc-find-revision-save', doesn't save the buffer to the file." (ignore-errors (delay-mode-hooks (set-auto-mode)))) (normal-mode)) (set-buffer-modified-p nil) - (setq buffer-read-only t)) - (setq failed nil) + (setq buffer-read-only t) + (setq failed nil)) (when (and failed (unless buffer (get-file-buffer filename))) (with-current-buffer (get-file-buffer filename) (set-buffer-modified-p nil)) From 60089dcfe06c64ff75d14f042fda1b052d0bad69 Mon Sep 17 00:00:00 2001 From: Tassilo Horn Date: Sun, 5 Feb 2023 19:54:17 +0100 Subject: [PATCH 37/62] Add to bug-reference-auto-setup-functions after its declaring defvar If it's the init-value of the defvar, add-hook from a third-party package will suppress the default functions if it takes place before bug-reference is loaded. * lisp/progmodes/bug-reference.el (bug-reference-auto-setup-functions): Add to bug-reference-auto-setup-functions after its declaring defvar. --- lisp/progmodes/bug-reference.el | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/lisp/progmodes/bug-reference.el b/lisp/progmodes/bug-reference.el index d7dd3ed1c9a..2c5378fcbb5 100644 --- a/lisp/progmodes/bug-reference.el +++ b/lisp/progmodes/bug-reference.el @@ -599,12 +599,7 @@ and set it if applicable." (erc-format-target) (erc-network-name)))) -(defvar bug-reference-auto-setup-functions - (list #'bug-reference-try-setup-from-vc - #'bug-reference-try-setup-from-gnus - #'bug-reference-try-setup-from-rmail - #'bug-reference-try-setup-from-rcirc - #'bug-reference-try-setup-from-erc) +(defvar bug-reference-auto-setup-functions nil "Functions trying to auto-setup `bug-reference-mode'. These functions are run after `bug-reference-mode' has been activated in a buffer and try to guess suitable values for @@ -618,6 +613,21 @@ guesswork is based on these variables: - `bug-reference-setup-from-irc-alist' for guessing based on IRC channel or network names.") +;; Add the default auto-setup functions. We don't have them as +;; init value of bug-reference-auto-setup-functions because then +;; they wouldn't be added if some package uses +;; +;; (add-hook 'bug-reference-auto-setup-functions +;; #'my-pkg--bug-reference-try-setup-from-my-pkg) +;; +;; before bug-reference.el is loaded. +(dolist (fn (list #'bug-reference-try-setup-from-vc + #'bug-reference-try-setup-from-gnus + #'bug-reference-try-setup-from-rmail + #'bug-reference-try-setup-from-rcirc + #'bug-reference-try-setup-from-erc)) + (add-hook 'bug-reference-auto-setup-functions fn)) + (defun bug-reference--run-auto-setup () (when (or bug-reference-mode bug-reference-prog-mode) From 793c24a6ac72aada1981907185dbfbf6e82a0124 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sun, 5 Feb 2023 21:07:45 +0200 Subject: [PATCH 38/62] Make sure 'M-x show-paren-local-mode' turns on right away * lisp/paren.el (show-paren--enabled-p): Extract from 'show-paren-function'. (show-paren-local-mode): Use it in the :variable getter (bug#61098). --- lisp/paren.el | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/lisp/paren.el b/lisp/paren.el index 7ee4e9ae682..4c91fd29490 100644 --- a/lisp/paren.el +++ b/lisp/paren.el @@ -161,8 +161,9 @@ use `show-paren-local-mode'." ;;;###autoload (define-minor-mode show-paren-local-mode "Toggle `show-paren-mode' only in this buffer." - :variable ( show-paren-mode . - (lambda (val) (setq-local show-paren-mode val))) + :variable ((show-paren--enabled-p) + . + (lambda (val) (setq-local show-paren-mode val))) (cond ((eq show-paren-mode (default-value 'show-paren-mode)) (unless show-paren-mode @@ -428,14 +429,17 @@ It is the default value of `show-paren-data-function'." ;; `show-paren-delay'. (defvar-local show-paren--last-pos nil) +(defun show-paren--enabled-p () + (and show-paren-mode + ;; If we're using `show-paren-local-mode', then + ;; always heed the value. + (or (local-variable-p 'show-paren-mode) + ;; If not, check that the predicate matches. + (buffer-match-p show-paren-predicate (current-buffer))))) + (defun show-paren-function () "Highlight the parentheses until the next input arrives." - (let ((data (and show-paren-mode - ;; If we're using `show-paren-local-mode', then - ;; always heed the value. - (or (local-variable-p 'show-paren-mode) - ;; If not, check that the predicate matches. - (buffer-match-p show-paren-predicate (current-buffer))) + (let ((data (and (show-paren--enabled-p) (funcall show-paren-data-function)))) (if (not data) (progn From 088425538f2122d88a4f4e132dbb2f1139648531 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sun, 5 Feb 2023 21:34:12 +0200 Subject: [PATCH 39/62] rust-ts-mode--font-lock-settings: Improve consistency * lisp/progmodes/rust-ts-mode.el (rust-ts-mode--font-lock-settings): Remove the rule that highlighted scope identifier in a function call as type. The existing rules will handle it when it does look like a type (capitalized). --- lisp/progmodes/rust-ts-mode.el | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lisp/progmodes/rust-ts-mode.el b/lisp/progmodes/rust-ts-mode.el index 571e268c221..18b42b9eced 100644 --- a/lisp/progmodes/rust-ts-mode.el +++ b/lisp/progmodes/rust-ts-mode.el @@ -206,10 +206,7 @@ :language 'rust :feature 'type - `((call_expression - function: (scoped_identifier - path: (identifier) @font-lock-type-face)) - (enum_variant name: (identifier) @font-lock-type-face) + `((enum_variant name: (identifier) @font-lock-type-face) (match_arm pattern: (match_pattern (_ type: (identifier) @font-lock-type-face))) (match_arm From a529b0d6463de109fb467c1a8c29722251d31925 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sun, 5 Feb 2023 23:42:18 +0200 Subject: [PATCH 40/62] rust-ts-mode: Fix highlighting of function name in call_expression * lisp/progmodes/rust-ts-mode.el (rust-ts-mode--font-lock-settings): Remove :override from the 'property' rules and move them above 'variable' (bug#61302). --- lisp/progmodes/rust-ts-mode.el | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lisp/progmodes/rust-ts-mode.el b/lisp/progmodes/rust-ts-mode.el index 18b42b9eced..5c71a8ad461 100644 --- a/lisp/progmodes/rust-ts-mode.el +++ b/lisp/progmodes/rust-ts-mode.el @@ -234,6 +234,11 @@ (use_as_clause alias: (identifier) @font-lock-type-face) (use_list (identifier) @font-lock-type-face)) + :language 'rust + :feature 'property + '((field_identifier) @font-lock-property-face + (shorthand_field_initializer (identifier) @font-lock-property-face)) + :language 'rust :feature 'variable '((identifier) @font-lock-variable-name-face @@ -245,12 +250,6 @@ :override t '((escape_sequence) @font-lock-escape-face) - :language 'rust - :feature 'property - :override t - '((field_identifier) @font-lock-property-face - (shorthand_field_initializer (identifier) @font-lock-property-face)) - :language 'rust :feature 'error :override t From 07ffe902c638d58b677820aa26c16db94510eca3 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Mon, 6 Feb 2023 04:05:19 +0200 Subject: [PATCH 41/62] c-ts-mode: Highlight "property functions" as functions * lisp/progmodes/c-ts-mode.el (c-ts-mode--font-lock-settings): Highlight "property functions" as functions (bug#61302). --- lisp/progmodes/c-ts-mode.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 5093c3980b6..3740130be30 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -470,7 +470,9 @@ MODE is either `c' or `cpp'." :language mode :feature 'function '((call_expression - function: (identifier) @font-lock-function-name-face)) + function: + [(identifier) @font-lock-function-name-face + (field_expression field: (field_identifier) @font-lock-function-name-face)])) :language mode :feature 'variable From 1fab91d852e461ae8091e906b3c6c4f17143068d Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Mon, 6 Feb 2023 04:12:25 +0200 Subject: [PATCH 42/62] go-ts-mode: Fix highlighting of function name in call_expression * lisp/progmodes/go-ts-mode.el (go-ts-mode--font-lock-settings): Remove :override from the 'property' rules and move them above 'variable' (bug#61302). Just like in rust-ts-mode. --- lisp/progmodes/go-ts-mode.el | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lisp/progmodes/go-ts-mode.el b/lisp/progmodes/go-ts-mode.el index e5b7bcca9aa..dbb08c81447 100644 --- a/lisp/progmodes/go-ts-mode.el +++ b/lisp/progmodes/go-ts-mode.el @@ -169,6 +169,11 @@ :feature 'type '([(package_identifier) (type_identifier)] @font-lock-type-face) + :language 'go + :feature 'property + '((field_identifier) @font-lock-property-face + (keyed_element (_ (identifier) @font-lock-property-face))) + :language 'go :feature 'variable '((identifier) @font-lock-variable-name-face) @@ -178,12 +183,6 @@ :override t '((escape_sequence) @font-lock-escape-face) - :language 'go - :feature 'property - :override t - '((field_identifier) @font-lock-property-face - (keyed_element (_ (identifier) @font-lock-property-face))) - :language 'go :feature 'error :override t From 79ab62e0bb5d6185a358a2473c65b6461ea97793 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Mon, 6 Feb 2023 04:42:12 +0200 Subject: [PATCH 43/62] go-ts-mode: Highlight variable declarations * lisp/progmodes/go-ts-mode.el (go-ts-mode--font-lock-settings): Highlight variable declarations in 'definition' feature. --- lisp/progmodes/go-ts-mode.el | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lisp/progmodes/go-ts-mode.el b/lisp/progmodes/go-ts-mode.el index dbb08c81447..7802c1fbfcc 100644 --- a/lisp/progmodes/go-ts-mode.el +++ b/lisp/progmodes/go-ts-mode.el @@ -135,7 +135,13 @@ (field_declaration name: (field_identifier) @font-lock-property-face) (parameter_declaration - name: (identifier) @font-lock-variable-name-face)) + name: (identifier) @font-lock-variable-name-face) + (short_var_declaration + left: (expression_list + (identifier) @font-lock-variable-name-face + ("," (identifier) @font-lock-variable-name-face)*)) + (var_spec name: (identifier) @font-lock-variable-name-face + ("," name: (identifier) @font-lock-variable-name-face)*)) :language 'go :feature 'function From c3262216abbb9ea04e1d3af25df1f9743efd1513 Mon Sep 17 00:00:00 2001 From: Theodor Thornhill Date: Sun, 5 Feb 2023 08:24:14 +0100 Subject: [PATCH 44/62] Add array_initializer to java-ts-mode Indent strings inside arrray_initializer one step: public class Java { void foo() { return new String[]{ "foo", // These "bar" } } } * lisp/progmodes/java-ts-mode.el (java-ts-mode--indent-rules): New matcher. --- lisp/progmodes/java-ts-mode.el | 1 + 1 file changed, 1 insertion(+) diff --git a/lisp/progmodes/java-ts-mode.el b/lisp/progmodes/java-ts-mode.el index fc264f448af..b9f78940957 100644 --- a/lisp/progmodes/java-ts-mode.el +++ b/lisp/progmodes/java-ts-mode.el @@ -78,6 +78,7 @@ ((parent-is "comment") prev-adaptive-prefix 0) ((parent-is "text_block") no-indent) ((parent-is "class_body") parent-bol java-ts-mode-indent-offset) + ((parent-is "array_initializer") parent-bol java-ts-mode-indent-offset) ((parent-is "annotation_type_body") parent-bol java-ts-mode-indent-offset) ((parent-is "interface_body") parent-bol java-ts-mode-indent-offset) ((parent-is "constructor_body") parent-bol java-ts-mode-indent-offset) From 5a6dfab1e4d5d89e5d5ff3bef73279926f067dbc Mon Sep 17 00:00:00 2001 From: Theodor Thornhill Date: Sun, 5 Feb 2023 08:49:08 +0100 Subject: [PATCH 45/62] Use c-ts-common-statement-offset in java-ts-mode (bug#61142) * lisp/progmodes/java-ts-mode.el (java-ts-mode--indent-rules): Add new matchers to enable c-ts-common machinery. (java-ts-mode): Add regexps. * lisp/progmodes/c-ts-common.el (c-ts-common-statement-offset): Fix typo in documentation and use the new if statement helpers. (c-ts-common-if-statement-regexp): New defvar. (c-ts-common-nestable-if-statement-p): New defvar. (c-ts-common--fix-nestable-if-statement): New helper. * test/lisp/progmodes/c-ts-mode-resources/indent.erts: Add test for complicated bracket matching indentation. * lisp/progmodes/c-ts-mode.el (c-ts-mode--indent-styles): Add indent rules for bracketless statements. --- lisp/progmodes/c-ts-common.el | 34 +++++++++++++- lisp/progmodes/c-ts-mode.el | 7 +++ lisp/progmodes/java-ts-mode.el | 36 +++++++++++---- .../progmodes/c-ts-mode-resources/indent.erts | 45 +++++++++++++++++++ 4 files changed, 112 insertions(+), 10 deletions(-) diff --git a/lisp/progmodes/c-ts-common.el b/lisp/progmodes/c-ts-common.el index 8729cae4ba7..6767f10a9e7 100644 --- a/lisp/progmodes/c-ts-common.el +++ b/lisp/progmodes/c-ts-common.el @@ -281,11 +281,22 @@ special handling from our bracket-counting indent algorithm. This can be nil, meaning such special handling is not needed.") +(defvar c-ts-common-if-statement-regexp "if_statement" + "Regexp used to select an if statement in a C like language. + +This can be set to a different regexp if needed.") + +(defvar c-ts-common-nestable-if-statement-p t + "Does the current parser nest if-else statements? + +t if the current tree-sitter grammar nests the else if +statements, nil otherwise.") + (defun c-ts-common-statement-offset (node parent bol &rest _) "This anchor is used for children of a statement inside a block. This function basically counts the number of block nodes (i.e., -brackets) (defined by `c-ts-mode--indent-block-type-regexp') +brackets) (defined by `c-ts-common-indent-block-type-regexp') between NODE and the root node (not counting NODE itself), and multiply that by `c-ts-common-indent-offset'. @@ -312,6 +323,9 @@ characters on the current line." (while (if (eq node t) (setq node parent) node) + ;; Subtract one indent level if the language nests + ;; if-statements and node is if_statement. + (setq level (c-ts-common--fix-nestable-if-statement level node)) (when (string-match-p c-ts-common-indent-block-type-regexp (treesit-node-type node)) (cl-incf level) @@ -354,6 +368,24 @@ the bracket in the body." (1+ level) level))) +(defun c-ts-common--fix-nestable-if-statement (level node) + "Takes LEVEL and NODE and return adjusted LEVEL. +Look at the type of NODE, when it is an if-statement node, as +defined by `c-ts-common-if-statement-regexp' and its parent is +also an if-statement node, subtract one level. Otherwise return +the value unchanged. Whether or not if-statements are nestable +is controlled by `c-ts-common-nestable-if-statement-p'." + ;; This fixes indentation for cases shown in bug#61142. + (or (and node + (equal (treesit-node-type (treesit-node-prev-sibling node)) "else") + (treesit-node-parent node) + c-ts-common-nestable-if-statement-p + (equal (treesit-node-type node) c-ts-common-if-statement-regexp) + (equal (treesit-node-type (treesit-node-parent node)) + c-ts-common-if-statement-regexp) + (cl-decf level)) + level)) + (provide 'c-ts-common) ;;; c-ts-common.el ends here diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 3740130be30..93816081666 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -238,6 +238,13 @@ MODE is either `c' or `cpp'." ((parent-is "labeled_statement") point-min c-ts-common-statement-offset) + ;; Bracketless statement matchers. + ((match nil "while_statement" "condition") parent-bol c-ts-mode-indent-offset) + ((match nil "if_statement" "consequence") parent-bol c-ts-mode-indent-offset) + ((match nil "if_statement" "alternative") parent-bol c-ts-mode-indent-offset) + ((match nil "do_statement" "body") parent-bol c-ts-mode-indent-offset) + ((match nil "for_statement" "body") parent-bol c-ts-mode-indent-offset) + ((match "preproc_ifdef" "compound_statement") point-min 0) ((match "#endif" "preproc_ifdef") point-min 0) ((match "preproc_if" "compound_statement") point-min 0) diff --git a/lisp/progmodes/java-ts-mode.el b/lisp/progmodes/java-ts-mode.el index b9f78940957..1d7bdb07224 100644 --- a/lisp/progmodes/java-ts-mode.el +++ b/lisp/progmodes/java-ts-mode.el @@ -70,22 +70,25 @@ (defvar java-ts-mode--indent-rules `((java ((parent-is "program") point-min 0) - ((node-is "}") (and parent parent-bol) 0) + ((match "}" "element_value_array_initializer") + parent-bol 0) + ((node-is "}") point-min c-ts-common-statement-offset) ((node-is ")") parent-bol 0) + ((node-is "else") parent-bol 0) ((node-is "]") parent-bol 0) ((and (parent-is "comment") c-ts-common-looking-at-star) c-ts-common-comment-start-after-first-star -1) ((parent-is "comment") prev-adaptive-prefix 0) ((parent-is "text_block") no-indent) - ((parent-is "class_body") parent-bol java-ts-mode-indent-offset) + ((parent-is "class_body") point-min c-ts-common-statement-offset) ((parent-is "array_initializer") parent-bol java-ts-mode-indent-offset) - ((parent-is "annotation_type_body") parent-bol java-ts-mode-indent-offset) - ((parent-is "interface_body") parent-bol java-ts-mode-indent-offset) - ((parent-is "constructor_body") parent-bol java-ts-mode-indent-offset) + ((parent-is "annotation_type_body") point-min c-ts-common-statement-offset) + ((parent-is "interface_body") point-min c-ts-common-statement-offset) + ((parent-is "constructor_body") point-min c-ts-common-statement-offset) ((parent-is "enum_body_declarations") parent-bol 0) - ((parent-is "enum_body") parent-bol java-ts-mode-indent-offset) - ((parent-is "switch_block") parent-bol java-ts-mode-indent-offset) - ((parent-is "record_declaration_body") parent-bol java-ts-mode-indent-offset) + ((parent-is "enum_body") point-min c-ts-common-statement-offset) + ((parent-is "switch_block") point-min c-ts-common-statement-offset) + ((parent-is "record_declaration_body") point-min c-ts-common-statement-offset) ((query "(method_declaration (block _ @indent))") parent-bol java-ts-mode-indent-offset) ((query "(method_declaration (block (_) @indent))") parent-bol java-ts-mode-indent-offset) ((parent-is "local_variable_declaration") parent-bol java-ts-mode-indent-offset) @@ -118,7 +121,7 @@ ((parent-is "case_statement") parent-bol java-ts-mode-indent-offset) ((parent-is "labeled_statement") parent-bol java-ts-mode-indent-offset) ((parent-is "do_statement") parent-bol java-ts-mode-indent-offset) - ((parent-is "block") (and parent parent-bol) java-ts-mode-indent-offset))) + ((parent-is "block") point-min c-ts-common-statement-offset))) "Tree-sitter indent rules.") (defvar java-ts-mode--keywords @@ -300,6 +303,21 @@ Return nil if there is no name or if NODE is not a defun node." (c-ts-common-comment-setup) ;; Indent. + (setq-local c-ts-common-indent-block-type-regexp + (regexp-opt '("class_body" + "array_initializer" + "constructor_body" + "annotation_type_body" + "interface_body" + "enum_body" + "switch_block" + "record_declaration_body" + "block"))) + (setq-local c-ts-common-indent-bracketless-type-regexp + (regexp-opt '("if_statement" + "for_statement" + "while_statement"))) + (setq-local c-ts-common-indent-offset 'java-ts-mode-indent-offset) (setq-local treesit-simple-indent-rules java-ts-mode--indent-rules) ;; Electric diff --git a/test/lisp/progmodes/c-ts-mode-resources/indent.erts b/test/lisp/progmodes/c-ts-mode-resources/indent.erts index 7dcc3b0fb3a..6f64e1e7953 100644 --- a/test/lisp/progmodes/c-ts-mode-resources/indent.erts +++ b/test/lisp/progmodes/c-ts-mode-resources/indent.erts @@ -244,3 +244,48 @@ int main() { } } =-=-= + +Name: Complicated mixed bracket matching indentation (bug#61142) + +=-= +void foo( + int foo) { + for (;;) + return 5; + + if (a == 0 + && b == 1 + && foo) + { + return 0; + } + else if (a == 1) + { + return 1; + } + else if (true) + return 5; + else + { + if (a == 0 + && b == 1 + && foo) + for ( + int i = 0; + i < 5; + i++) + if (true) + do + i = 5; + while (true); + else if (false) + { + return 6; + } + else + if (true + && false) + return 6; + } +} +=-=-= From 17ab426670af16f40334501d9018835bbd24a5db Mon Sep 17 00:00:00 2001 From: Aleksandr Vityazev Date: Mon, 6 Feb 2023 13:39:10 +0300 Subject: [PATCH 46/62] * lisp/treesit.el (treesit): Fix shortdoc example form (bug#61318). --- lisp/treesit.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/treesit.el b/lisp/treesit.el index 7bd68c9a6d9..6015e78bbd5 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -2963,7 +2963,7 @@ function signals an error." "Parsers" (treesit-parser-create - :no-eval (treesit-parser-create) + :no-eval (treesit-parser-create 'c) :eg-result-string "#") (treesit-parser-delete :no-value (treesit-parser-delete parser)) From 9dfccb89fc576c89f48a89c95203c3bd68194154 Mon Sep 17 00:00:00 2001 From: Tassilo Horn Date: Mon, 6 Feb 2023 17:09:40 +0100 Subject: [PATCH 47/62] Clarify bug-reference-auto-setup-functions docstring. * lisp/progmodes/bug-reference.el (bug-reference-auto-setup-functions): Add clarification to docstring that this variable is for packages, not for users. --- lisp/progmodes/bug-reference.el | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lisp/progmodes/bug-reference.el b/lisp/progmodes/bug-reference.el index 2c5378fcbb5..9f1439e6a04 100644 --- a/lisp/progmodes/bug-reference.el +++ b/lisp/progmodes/bug-reference.el @@ -611,7 +611,21 @@ guesswork is based on these variables: - `bug-reference-setup-from-mail-alist' for guessing based on mail group names or mail header values. - `bug-reference-setup-from-irc-alist' for guessing based on IRC - channel or network names.") + channel or network names. + +Note: This variable's purpose is to allow packages to provide +bug-reference auto-setup support in buffers managed by this +package. Therefore, such auto-setup function should check if the +current buffer is \"their\" buffer and only act if that's the +case, e.g., in terms of `derived-mode-p'. + +The variable is not intended for users. Those are advised to set +`bug-reference-bug-regexp' and `bug-reference-url-format' using +other means such as file-local variable sections, a +`.dir-locals.el' file, or compute and set their values in +`bug-reference-mode-hook' or `bug-reference-prog-mode-hook'. If +the bug regexp and URL format are already set after those hooks +have been run, the auto-setup is inhibited.") ;; Add the default auto-setup functions. We don't have them as ;; init value of bug-reference-auto-setup-functions because then From 97533e73ad68f8d9050f8ed349cf95f009e20b72 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Mon, 6 Feb 2023 18:34:39 +0200 Subject: [PATCH 48/62] ; * lisp/progmodes/c-ts-common.el (treesit-node-prev-sibling): Declare. --- lisp/progmodes/c-ts-common.el | 1 + 1 file changed, 1 insertion(+) diff --git a/lisp/progmodes/c-ts-common.el b/lisp/progmodes/c-ts-common.el index 6767f10a9e7..0b0a7ff7cd3 100644 --- a/lisp/progmodes/c-ts-common.el +++ b/lisp/progmodes/c-ts-common.el @@ -51,6 +51,7 @@ (declare-function treesit-node-end "treesit.c") (declare-function treesit-node-type "treesit.c") (declare-function treesit-node-parent "treesit.c") +(declare-function treesit-node-prev-sibling "treesit.c") ;;; Comment indentation and filling From 321cbd9a6014bf0b70dc0b01aed27f36aec4051d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= Date: Mon, 6 Feb 2023 11:45:33 +0100 Subject: [PATCH 49/62] Tighten and simplify typescript compilation-mode regexps (bug#61104) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * lisp/progmodes/compile.el (compilation-error-regexp-alist-alist): Tighten regexps and simplify. Translate to rx. * etc/compilation.txt: Add examples. In collaboration with Jostein Kjønigsen. --- etc/compilation.txt | 14 ++++++++++++++ lisp/progmodes/compile.el | 28 ++++++++++++++++++++-------- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/etc/compilation.txt b/etc/compilation.txt index 672cbebafff..5f6ecb09cc2 100644 --- a/etc/compilation.txt +++ b/etc/compilation.txt @@ -639,6 +639,20 @@ symbol: weblint index.html (13:1) Unknown element +* Typescript prior to tsc version 2.7, "plain" format + +symbol: typescript-tsc-plain + +greeter.ts(30,12): error TS2339: Property 'foo' does not exist. + + +* Typescript after tsc version 2.7, "pretty" format + +symbol: typescript-tsc-pretty + +src/resources/document.ts:140:22 - error TS2362: something. + + * Directory tracking Directories are matched via 'compilation-directory-matcher'. Files which are diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el index 1e57d0b7bb2..ccf64fb670b 100644 --- a/lisp/progmodes/compile.el +++ b/lisp/progmodes/compile.el @@ -653,19 +653,31 @@ File = \\(.+\\), Line = \\([0-9]+\\)\\(?:, Column = \\([0-9]+\\)\\)?" ;; Typescript compilation prior to tsc version 2.7, "plain" format: ;; greeter.ts(30,12): error TS2339: Property 'foo' does not exist. (typescript-tsc-plain - ,(concat - "^[[:blank:]]*" - "\\([^(\r\n)]+\\)(\\([0-9]+\\),\\([0-9]+\\)):[[:blank:]]+" - "error [[:alnum:]]+: [^\r\n]+$") + ,(rx bol + (group (not (in " \t\n()")) ; 1: file + (* (not (in "\n()")))) + "(" + (group (+ (in "0-9"))) ; 2: line + "," + (group (+ (in "0-9"))) ; 3: column + "): error " + (+ (in "0-9A-Z")) ; error code + ": ") 1 2 3 2) ;; Typescript compilation after tsc version 2.7, "pretty" format: ;; src/resources/document.ts:140:22 - error TS2362: something. (typescript-tsc-pretty - ,(concat - "^[[:blank:]]*" - "\\([^(\r\n)]+\\):\\([0-9]+\\):\\([0-9]+\\) - [[:blank:]]*" - "error [[:alnum:]]+: [^\r\n]+$") + ,(rx bol + (group (not (in " \t\n()")) ; 1: file + (* (not (in "\n()")))) + ":" + (group (+ (in "0-9"))) ; 2: line + ":" + (group (+ (in "0-9"))) ; 3: column + " - error " + (+ (in "0-9A-Z")) ; error code + ": ") 1 2 3 2) )) "Alist of values for `compilation-error-regexp-alist'.") From 2ac8c4bbd6f47751a68b0230310f6fddd7da8de5 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Tue, 7 Feb 2023 00:28:25 +0200 Subject: [PATCH 50/62] (eglot-completion-at-point): Return correct values in :company-kind * lisp/progmodes/eglot.el (eglot-completion-at-point): Return the correct values in :company-kind for "EnumMember" and "TypeParameter". The convention is to use kebab case rather than plain downcasing. Reported in https://github.com/company-mode/company-mode/issues/1370. --- lisp/progmodes/eglot.el | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 3fc1d68422a..c906890c949 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -2873,7 +2873,10 @@ for which LSP on-type-formatting should be requested." (when-let* ((lsp-item (get-text-property 0 'eglot--lsp-item proxy)) (kind (alist-get (plist-get lsp-item :kind) eglot--kind-names))) - (intern (downcase kind)))) + (pcase kind + ("EnumMember" 'enum-member) + ("TypeParameter" 'type-parameter) + (_ (intern (downcase kind)))))) :company-deprecated (lambda (proxy) (when-let ((lsp-item (get-text-property 0 'eglot--lsp-item proxy))) From d68ff6016d0ca011b5bf0fd05578fe1abb2e53a9 Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Sun, 5 Feb 2023 15:20:52 -0800 Subject: [PATCH 51/62] Fix c-ts-mode indentation (bug#61291) Fix indentation for the semicolon in while (str_a[i++] == str_b[j++]) ; * lisp/progmodes/c-ts-mode.el (c-ts-mode--indent-styles): New rule. * test/lisp/progmodes/c-ts-mode-resources/indent.erts: New test. --- lisp/progmodes/c-ts-mode.el | 2 ++ test/lisp/progmodes/c-ts-mode-resources/indent.erts | 11 +++++++++++ 2 files changed, 13 insertions(+) diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 93816081666..1737b8c5715 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -285,6 +285,8 @@ MODE is either `c' or `cpp'." ((node-is "}") point-min c-ts-common-statement-offset) ;; Opening bracket. ((node-is "compound_statement") point-min c-ts-common-statement-offset) + ;; Bug#61291. + ((match "expression_statement" nil "body") point-min c-ts-common-statement-offset) ,@(when (eq mode 'cpp) `(((node-is "field_initializer_list") parent-bol ,(* c-ts-mode-indent-offset 2))))))) diff --git a/test/lisp/progmodes/c-ts-mode-resources/indent.erts b/test/lisp/progmodes/c-ts-mode-resources/indent.erts index 6f64e1e7953..2750526f893 100644 --- a/test/lisp/progmodes/c-ts-mode-resources/indent.erts +++ b/test/lisp/progmodes/c-ts-mode-resources/indent.erts @@ -144,6 +144,17 @@ int f2(int x, }; =-=-= +Name: Semi-colon in While Loop (bug#61291) + +=-= +while (true) + ; +for (int i = 0; + i < 5; + i++) + ; +=-=-= + Name: Multiline Block Comments 1 (bug#60270) =-= From 7cb92b5398771b088450942d9eaefd53b5f91cf6 Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Sun, 5 Feb 2023 17:05:21 -0800 Subject: [PATCH 52/62] Fix c-ts-mode indentation Turns out I shouldn't have removed the explicit rules. Anyway, now it indents properly. * lisp/progmodes/c-ts-mode.el (c-ts-mode--indent-styles): Add rules. * test/lisp/progmodes/c-ts-mode-resources/indent.erts: Add tests --- lisp/progmodes/c-ts-mode.el | 6 ++++++ .../lisp/progmodes/c-ts-mode-resources/indent.erts | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 1737b8c5715..f2d5a482009 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -287,6 +287,12 @@ MODE is either `c' or `cpp'." ((node-is "compound_statement") point-min c-ts-common-statement-offset) ;; Bug#61291. ((match "expression_statement" nil "body") point-min c-ts-common-statement-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) ,@(when (eq mode 'cpp) `(((node-is "field_initializer_list") parent-bol ,(* c-ts-mode-indent-offset 2))))))) diff --git a/test/lisp/progmodes/c-ts-mode-resources/indent.erts b/test/lisp/progmodes/c-ts-mode-resources/indent.erts index 2750526f893..8c588f56f9a 100644 --- a/test/lisp/progmodes/c-ts-mode-resources/indent.erts +++ b/test/lisp/progmodes/c-ts-mode-resources/indent.erts @@ -155,6 +155,20 @@ for (int i = 0; ; =-=-= +Name: Bracketless Simple Statement + +=-= +for (int i = 0; i < 5; i++) + continue; + +while (true) + return 1; + +do + i++; +while (true) +=-=-= + Name: Multiline Block Comments 1 (bug#60270) =-= From 87d39a30b1264e111cfd2f9cbdc95dcd0870684b Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Sun, 5 Feb 2023 19:32:24 -0800 Subject: [PATCH 53/62] Fix c-ts-mode indentation Sign, ok, there's another edge case: else if statements. Because "else if" is usually implemented as just another if statement nested in the else branch, this creates additional levels that indentation needs to ignore. I converted c-ts-common-indent-block-type-regexp + c-ts-common-indent-bracketless-type-regexp into a new, more flexible variable, c-ts-common-indent-type-regexp-alist, to avoid adding yet more variables in order to recognize else and if statements. * lisp/progmodes/c-ts-common.el: (c-ts-common-indent-type-regexp-alist): New variable. (c-ts-common-indent-block-type-regexp) (c-ts-common-indent-bracketless-type-regexp): Remove variables. (c-ts-common--node-is): New function. (c-ts-common-statement-offset): Use the new variable, and add the "else if" special case. Also merge the code of c-ts-mode--fix-bracketless-indent, because now the code is much more succinct. (c-ts-mode--fix-bracketless-indent): Merge into c-ts-common-statement-offset. * lisp/progmodes/c-ts-mode.el: (c-ts-base-mode): Setup c-ts-common-indent-type-regexp-alist. * test/lisp/progmodes/c-ts-mode-resources/indent.erts: New test. --- lisp/progmodes/c-ts-common.el | 148 ++++++++---------- lisp/progmodes/c-ts-mode.el | 18 ++- .../progmodes/c-ts-mode-resources/indent.erts | 13 ++ 3 files changed, 88 insertions(+), 91 deletions(-) diff --git a/lisp/progmodes/c-ts-common.el b/lisp/progmodes/c-ts-common.el index 0b0a7ff7cd3..8262e6261d4 100644 --- a/lisp/progmodes/c-ts-common.el +++ b/lisp/progmodes/c-ts-common.el @@ -267,33 +267,52 @@ This should be the symbol of the indent offset variable for the particular major mode. This cannot be nil for `c-ts-common' statement indent functions to work.") -(defvar c-ts-common-indent-block-type-regexp nil - "Regexp matching types of block nodes (i.e., {} blocks). +(defvar c-ts-common-indent-type-regexp-alist nil + "An alist of of node type regexps. -This cannot be nil for `c-ts-common' statement indent functions -to work.") +Each key in the alist is one of `if', `else', `do', `while', +`for', `block', `close-bracket'. Each value in the alist +is the regexp matching the type of that kind of node. Most of +these types are self-explanatory, e.g., `if' corresponds to +\"if_statement\" in C. `block' corresponds to the {} block. -(defvar c-ts-common-indent-bracketless-type-regexp nil - "A regexp matching types of bracketless constructs. +Some types, specifically `else', is usually not identified by a +standalone node, but a child under the \"if_statement\", under a +field name like \"alternative\", etc. In that case, use a +cons (TYPE . FIELD-NAME) as the value, where TYPE is the node's +parent's type, and FIELD-NAME is the field name of the node. -These constructs include if, while, do-while, for statements. In -these statements, the body can omit the bracket, which requires -special handling from our bracket-counting indent algorithm. +If the language doesn't have a particular type, it is fine to +omit it.") -This can be nil, meaning such special handling is not needed.") +(defun c-ts-common--node-is (node &rest types) + "Return non-nil if NODE is any one of the TYPES. -(defvar c-ts-common-if-statement-regexp "if_statement" - "Regexp used to select an if statement in a C like language. +TYPES can be any of `if', `else', `while', `do', `for', and +`block'. -This can be set to a different regexp if needed.") +If NODE is nil, return nil." + (declare (indent 2)) + (catch 'ret + (when (null node) + (throw 'ret nil)) + (dolist (type types) + (let ((regexp (alist-get + type c-ts-common-indent-type-regexp-alist)) + (parent (treesit-node-parent node))) + (when (and regexp + (if (consp regexp) + (and parent + (string-match-p (car regexp) + (treesit-node-type parent)) + (string-match-p (cdr regexp) + (treesit-node-field-name + node))) + (string-match-p regexp (treesit-node-type node)))) + (throw 'ret t)))) + nil)) -(defvar c-ts-common-nestable-if-statement-p t - "Does the current parser nest if-else statements? - -t if the current tree-sitter grammar nests the else if -statements, nil otherwise.") - -(defun c-ts-common-statement-offset (node parent bol &rest _) +(defun c-ts-common-statement-offset (node parent &rest _) "This anchor is used for children of a statement inside a block. This function basically counts the number of block nodes (i.e., @@ -311,10 +330,7 @@ characters on the current line." ;; If NODE is a opening/closing bracket on its own line, take off ;; one level because the code below assumes NODE is a statement ;; _inside_ a {} block. - (when (and node - (or (string-match-p c-ts-common-indent-block-type-regexp - (treesit-node-type node)) - (save-excursion (goto-char bol) (looking-at-p "}")))) + (when (c-ts-common--node-is node 'block 'close-bracket) (cl-decf level)) ;; If point is on an empty line, NODE would be nil, but we pretend ;; there is a statement node. @@ -324,69 +340,35 @@ characters on the current line." (while (if (eq node t) (setq node parent) node) - ;; Subtract one indent level if the language nests - ;; if-statements and node is if_statement. - (setq level (c-ts-common--fix-nestable-if-statement level node)) - (when (string-match-p c-ts-common-indent-block-type-regexp - (treesit-node-type node)) - (cl-incf level) - (save-excursion - (goto-char (treesit-node-start node)) - ;; Add an extra level if the opening bracket is on its own - ;; line, except (1) it's at top-level, or (2) it's immediate - ;; parent is another block. - (cond ((bolp) nil) ; Case (1). - ((let ((parent-type (treesit-node-type - (treesit-node-parent node)))) - ;; Case (2). - (and parent-type - (string-match-p - c-ts-common-indent-block-type-regexp - parent-type))) - nil) - ;; Add a level. - ((looking-back (rx bol (* whitespace)) - (line-beginning-position)) - (cl-incf level))))) - (setq level (c-ts-mode--fix-bracketless-indent level node)) + (let ((parent (treesit-node-parent node))) + ;; Increment level for every bracket (with exception). + (when (c-ts-common--node-is node 'block) + (cl-incf level) + (save-excursion + (goto-char (treesit-node-start node)) + ;; Add an extra level if the opening bracket is on its own + ;; line, except (1) it's at top-level, or (2) it's immediate + ;; parent is another block. + (cond ((bolp) nil) ; Case (1). + ((c-ts-common--node-is parent 'block) ; Case (2). + nil) + ;; Add a level. + ((looking-back (rx bol (* whitespace)) + (line-beginning-position)) + (cl-incf level))))) + ;; Fix bracketless statements. + (when (and (c-ts-common--node-is parent + 'if 'do 'while 'for) + (not (c-ts-common--node-is node 'block))) + (cl-incf level)) + ;; Flatten "else if" statements. + (when (and (c-ts-common--node-is node 'else) + (c-ts-common--node-is node 'if)) + (cl-decf level))) ;; Go up the tree. (setq node (treesit-node-parent node))) (* level (symbol-value c-ts-common-indent-offset)))) -(defun c-ts-mode--fix-bracketless-indent (level node) - "Takes LEVEL and NODE and return adjusted LEVEL. -This fixes indentation for cases shown in bug#61026. Basically -in C-like syntax, statements like if, for, while sometimes omit -the bracket in the body." - (let ((block-re c-ts-common-indent-block-type-regexp) - (statement-re - c-ts-common-indent-bracketless-type-regexp) - (node-type (treesit-node-type node)) - (parent-type (treesit-node-type (treesit-node-parent node)))) - (if (and block-re statement-re node-type parent-type - (not (string-match-p block-re node-type)) - (string-match-p statement-re parent-type)) - (1+ level) - level))) - -(defun c-ts-common--fix-nestable-if-statement (level node) - "Takes LEVEL and NODE and return adjusted LEVEL. -Look at the type of NODE, when it is an if-statement node, as -defined by `c-ts-common-if-statement-regexp' and its parent is -also an if-statement node, subtract one level. Otherwise return -the value unchanged. Whether or not if-statements are nestable -is controlled by `c-ts-common-nestable-if-statement-p'." - ;; This fixes indentation for cases shown in bug#61142. - (or (and node - (equal (treesit-node-type (treesit-node-prev-sibling node)) "else") - (treesit-node-parent node) - c-ts-common-nestable-if-statement-p - (equal (treesit-node-type node) c-ts-common-if-statement-regexp) - (equal (treesit-node-type (treesit-node-parent node)) - c-ts-common-if-statement-regexp) - (cl-decf level)) - level)) - (provide 'c-ts-common) ;;; c-ts-common.el ends here diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index f2d5a482009..b898f7d9ee3 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -765,14 +765,16 @@ 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) - (setq-local c-ts-common-indent-block-type-regexp - (rx (or "compound_statement" - "field_declaration_list" - "enumerator_list"))) - (setq-local c-ts-common-indent-bracketless-type-regexp - (rx (or "if_statement" "do_statement" - "for_statement" "while_statement"))) - + (setq-local c-ts-common-indent-type-regexp-alist + `((block . ,(rx (or "compound_statement" + "field_declaration_list" + "enumerator_list"))) + (if . "if_statement") + (else . ("if_statement" . "alternative")) + (do . "do_statement") + (while . "while_statement") + (for . "for_statement") + (close-bracket . "}"))) ;; Comment (c-ts-common-comment-setup) diff --git a/test/lisp/progmodes/c-ts-mode-resources/indent.erts b/test/lisp/progmodes/c-ts-mode-resources/indent.erts index 8c588f56f9a..21b84c2e7e3 100644 --- a/test/lisp/progmodes/c-ts-mode-resources/indent.erts +++ b/test/lisp/progmodes/c-ts-mode-resources/indent.erts @@ -169,6 +169,19 @@ do while (true) =-=-= +Name: Nested If-Else + +=-= +if (true) + return 0; +else if (false) + return 1; +else if (true) + return 2; +else if (false) + return 3; +=-=-= + Name: Multiline Block Comments 1 (bug#60270) =-= From 746748f5c283b98a221571e725833affe304a748 Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Mon, 6 Feb 2023 18:48:04 -0800 Subject: [PATCH 54/62] Make java-ts-mode use the c-ts-common-indent-type-regexp-alist * lisp/progmodes/java-ts-mode.el: (java-ts-mode): Setup c-ts-common-indent-type-regexp-alist. --- lisp/progmodes/java-ts-mode.el | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/lisp/progmodes/java-ts-mode.el b/lisp/progmodes/java-ts-mode.el index 1d7bdb07224..dc651c11a00 100644 --- a/lisp/progmodes/java-ts-mode.el +++ b/lisp/progmodes/java-ts-mode.el @@ -303,20 +303,22 @@ Return nil if there is no name or if NODE is not a defun node." (c-ts-common-comment-setup) ;; Indent. - (setq-local c-ts-common-indent-block-type-regexp - (regexp-opt '("class_body" - "array_initializer" - "constructor_body" - "annotation_type_body" - "interface_body" - "enum_body" - "switch_block" - "record_declaration_body" - "block"))) - (setq-local c-ts-common-indent-bracketless-type-regexp - (regexp-opt '("if_statement" - "for_statement" - "while_statement"))) + (setq-local c-ts-common-indent-type-regexp-alist + `((block . ,(rx (or "class_body" + "array_initializer" + "constructor_body" + "annotation_type_body" + "interface_body" + "enum_body" + "switch_block" + "record_declaration_body" + "block"))) + (close-bracket . "}") + (if . "if_statement") + (else . ("if_statement" . "alternative")) + (for . "for_statement") + (while . "while_statement") + (do . "do_statement"))) (setq-local c-ts-common-indent-offset 'java-ts-mode-indent-offset) (setq-local treesit-simple-indent-rules java-ts-mode--indent-rules) From 22f0159c5aa8aca3d650505b41adfbd03f719b11 Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Tue, 7 Feb 2023 19:28:15 +0100 Subject: [PATCH 55/62] Fix last Tramp commit * lisp/net/tramp.el (tramp-completion-file-name-handler): Run only when `minibuffer-completing-file-name' is non-nil. * test/lisp/net/tramp-tests.el (tramp-test26-file-name-completion): Fix test. --- lisp/net/tramp.el | 2 +- test/lisp/net/tramp-tests.el | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 69812506e48..b75a1816fdb 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -2773,7 +2773,7 @@ Fall back to normal file name handler if no Tramp file name handler exists." "Invoke Tramp file name completion handler for OPERATION and ARGS. Falls back to normal file name handler if no Tramp file name handler exists." (if-let - ((fn (and tramp-mode + ((fn (and tramp-mode minibuffer-completing-file-name (assoc operation tramp-completion-file-name-handler-alist)))) (save-match-data (apply (cdr fn) args)) (tramp-run-real-handler operation args))) diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index d903ba626b9..eea59843d47 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -4524,7 +4524,8 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." (let ((tramp-fuse-remove-hidden-files t) (method (file-remote-p ert-remote-temporary-file-directory 'method)) (host (file-remote-p ert-remote-temporary-file-directory 'host)) - (orig-syntax tramp-syntax)) + (orig-syntax tramp-syntax) + (minibuffer-completing-file-name t)) (when (and (stringp host) (string-match tramp-host-with-port-regexp host)) (setq host (match-string 1 host))) From a98d0daac473737da720c20f49f6f5abf36b074b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= Date: Tue, 7 Feb 2023 13:16:40 +0100 Subject: [PATCH 56/62] Remove unnecessary cons in lexical eval * src/eval.c (list_of_t): New. (Feval): Use list_of_t instead of consing every time. (syms_of_eval): Set list_of_t to (t) and staticpro it. --- src/eval.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/eval.c b/src/eval.c index d42f7ffe894..e377e30c6fb 100644 --- a/src/eval.c +++ b/src/eval.c @@ -2348,6 +2348,8 @@ it defines a macro. */) } +static Lisp_Object list_of_t; /* Never-modified constant containing (t). */ + DEFUN ("eval", Feval, Seval, 1, 2, 0, doc: /* Evaluate FORM and return its value. If LEXICAL is t, evaluate using lexical scoping. @@ -2357,7 +2359,7 @@ alist mapping symbols to their value. */) { specpdl_ref count = SPECPDL_INDEX (); specbind (Qinternal_interpreter_environment, - CONSP (lexical) || NILP (lexical) ? lexical : list1 (Qt)); + CONSP (lexical) || NILP (lexical) ? lexical : list_of_t); return unbind_to (count, eval_sub (form)); } @@ -4392,6 +4394,9 @@ alist of active lexical bindings. */); Qcatch_all_memory_full = Fmake_symbol (build_pure_c_string ("catch-all-memory-full")); + staticpro (&list_of_t); + list_of_t = list1 (Qt); + defsubr (&Sor); defsubr (&Sand); defsubr (&Sif); From c9ba05af8dfabca00023bd2312dec4ec59497801 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Tue, 7 Feb 2023 21:53:05 +0200 Subject: [PATCH 57/62] Fix crashes inside 'xfree' called from treesit.c * src/treesit.c (treesit_load_language): Always xstrdup 'c_name', to avoid crashes inside xfree. (Bug#61351) --- src/treesit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/treesit.c b/src/treesit.c index 8e772523cc7..b15d44fca01 100644 --- a/src/treesit.c +++ b/src/treesit.c @@ -620,7 +620,7 @@ treesit_load_language (Lisp_Object language_symbol, char *c_name = xstrdup (SSDATA (base_name)); treesit_symbol_to_c_name (c_name); if (found_override) - c_name = SSDATA (override_c_name); + c_name = xstrdup (SSDATA (override_c_name)); langfn = dynlib_sym (handle, c_name); xfree (c_name); error = dynlib_error (); From 88d5327fe2ab6ecfde22fee8835c583bfd1f2ce2 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Tue, 7 Feb 2023 18:03:22 -0500 Subject: [PATCH 58/62] (cconv-convert): Fix regression * lisp/emacs-lisp/cconv.el (cconv-convert, cconv-analyze-form): Since we can't always remove the wrapper, make sure the wrapper accepts the expected calling convention (i.e. called with no args). --- lisp/emacs-lisp/cconv.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lisp/emacs-lisp/cconv.el b/lisp/emacs-lisp/cconv.el index e8d639903c1..570c9e66060 100644 --- a/lisp/emacs-lisp/cconv.el +++ b/lisp/emacs-lisp/cconv.el @@ -483,7 +483,7 @@ places where they originally did not directly appear." (bf (if (stringp (car body)) (cdr body) body)) (if (when (eq 'interactive (car-safe (car bf))) (gethash form cconv--interactive-form-funs))) - (wrapped (pcase if (`#'(lambda (_cconv--dummy) .,_) t) (_ nil))) + (wrapped (pcase if (`#'(lambda (&rest _cconv--dummy) .,_) t) (_ nil))) (cif (when if (cconv-convert if env extend))) (_ (pcase cif ('nil nil) @@ -747,7 +747,7 @@ This function does not return anything but instead fills the (let ((if (cadr (car bf)))) (unless (macroexp-const-p if) ;Optimize this common case. (let ((f (if (eq 'function (car-safe if)) if - `#'(lambda (_cconv--dummy) ,if)))) + `#'(lambda (&rest _cconv--dummy) ,if)))) (setf (gethash form cconv--interactive-form-funs) f) (cconv-analyze-form f env)))))) (cconv--analyze-function vrs body-forms env form)) From 2273cdb40e1939f7c29a669f6a64e6a27738c1a5 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Tue, 7 Feb 2023 18:10:33 -0500 Subject: [PATCH 59/62] * lisp/edmacro.el (edit-kbd-macro): Fix thinko (bug#61333) --- lisp/edmacro.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lisp/edmacro.el b/lisp/edmacro.el index c0723dc8dfe..c995e2f89d7 100644 --- a/lisp/edmacro.el +++ b/lisp/edmacro.el @@ -156,9 +156,9 @@ With a prefix argument, format the macro in a more concise way." (setq mac cmd) (setq cmd nil))) (when (kmacro-p mac) - (setq mac (kmacro--keys mac) - mac-counter (kmacro--counter mac) - mac-format (kmacro--format mac))) + (setq mac-counter (kmacro--counter mac) + mac-format (kmacro--format mac) + mac (kmacro--keys mac))) (unless (arrayp mac) (error "Key sequence %s is not a keyboard macro" (key-description keys))) From 643a11c6e5defc0a34da1a53b64aa1e097298923 Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Wed, 8 Feb 2023 09:34:49 +0200 Subject: [PATCH 60/62] * lisp/progmodes/xref.el (xref--insert-xrefs): Remove extra space (bug#61340). --- lisp/progmodes/xref.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index 4db0df6c3b8..63e065e696e 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el @@ -1126,7 +1126,7 @@ GROUP is a string for decoration purposes and XREF is an maximize (xref-location-line (xref-item-location xref))) for line-format = (and max-line - (format "%%%dd: " (1+ (floor (log max-line 10))))) + (format "%%%dd:" (1+ (floor (log max-line 10))))) with item-text-props = (list 'mouse-face 'highlight 'keymap xref--button-map 'help-echo From f3fce3a71c7571be19a451403b46fa667bfa3c16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= Date: Wed, 8 Feb 2023 13:18:32 +0100 Subject: [PATCH 61/62] Simplify and speed up parts of elisp optimiser * lisp/emacs-lisp/byte-opt.el (byte-optimize-constant-args): Simplify. (byte-optimize--constant-symbol-p): Speed up. (byteopt--eval-const): New. (byte-optimize-member, byte-optimize-concat, byte-optimize-append): Use byteopt--eval-const instead of eval which is much slower. --- lisp/emacs-lisp/byte-opt.el | 41 ++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index e0c769c7e60..b7e21db688f 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el @@ -1019,16 +1019,14 @@ for speeding up processing.") (t form)))) (defun byte-optimize-constant-args (form) - (let ((ok t) - (rest (cdr form))) - (while (and rest ok) - (setq ok (macroexp-const-p (car rest)) - rest (cdr rest))) - (if ok - (condition-case () - (list 'quote (eval form)) - (error form)) - form))) + (let ((rest (cdr form))) + (while (and rest (macroexp-const-p (car rest))) + (setq rest (cdr rest))) + (if rest + form + (condition-case () + (list 'quote (eval form t)) + (error form))))) (defun byte-optimize-identity (form) (if (and (cdr form) (null (cdr (cdr form)))) @@ -1036,8 +1034,19 @@ for speeding up processing.") form)) (defun byte-optimize--constant-symbol-p (expr) - "Whether EXPR is a constant symbol." - (and (macroexp-const-p expr) (symbolp (eval expr)))) + "Whether EXPR is a constant symbol, like (quote hello), nil, t, or :keyword." + (if (consp expr) + (and (memq (car expr) '(quote function)) + (symbolp (cadr expr))) + (or (memq expr '(nil t)) + (keywordp expr)))) + +(defsubst byteopt--eval-const (expr) + "Evaluate EXPR which must be a constant (quoted or self-evaluating). +Ie, (macroexp-const-p EXPR) must be true." + (if (consp expr) + (cadr expr) ; assumed to be 'VALUE or #'SYMBOL + expr)) (defun byte-optimize--fixnump (o) "Return whether O is guaranteed to be a fixnum in all Emacsen. @@ -1074,7 +1083,7 @@ See Info node `(elisp) Integer Basics'." (byte-optimize--fixnump (nth 1 form)) (let ((arg2 (nth 2 form))) (and (macroexp-const-p arg2) - (let ((listval (eval arg2))) + (let ((listval (byteopt--eval-const arg2))) (and (listp listval) (not (memq nil (mapcar (lambda (o) @@ -1131,7 +1140,7 @@ See Info node `(elisp) Integer Basics'." val) (while (and args (macroexp-const-p (car args)) (progn - (setq val (eval (car args))) + (setq val (byteopt--eval-const (car args))) (and (or (stringp val) (and (or (listp val) (vectorp val)) (not (memq nil @@ -1528,7 +1537,7 @@ See Info node `(elisp) Integer Basics'." (cond ((macroexp-const-p arg) ;; constant arg - (let ((val (eval arg))) + (let ((val (byteopt--eval-const arg))) (cond ;; Elide empty arguments (nil, empty string, etc). ((zerop (length val)) @@ -1538,7 +1547,7 @@ See Info node `(elisp) Integer Basics'." (loop (cdr args) (cons (list 'quote - (append (eval prev) val nil)) + (append (byteopt--eval-const prev) val nil)) (cdr newargs)))) (t (loop (cdr args) (cons arg newargs)))))) From 680bc20553ebf01375ab7957b6f0be066335fd6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= Date: Wed, 8 Feb 2023 13:45:57 +0100 Subject: [PATCH 62/62] Flatten nested `concat` calls * lisp/emacs-lisp/byte-opt.el (byte-optimize-concat): Flatten nested forms; concat is associative. This reduces the number of calls and may coalesce adjacent constant strings. --- lisp/emacs-lisp/byte-opt.el | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el index b7e21db688f..3eef8f385b5 100644 --- a/lisp/emacs-lisp/byte-opt.el +++ b/lisp/emacs-lisp/byte-opt.el @@ -1132,21 +1132,31 @@ See Info node `(elisp) Integer Basics'." form)) (defun byte-optimize-concat (form) - "Merge adjacent constant arguments to `concat'." + "Merge adjacent constant arguments to `concat' and flatten nested forms." (let ((args (cdr form)) (newargs nil)) (while args - (let ((strings nil) - val) - (while (and args (macroexp-const-p (car args)) - (progn - (setq val (byteopt--eval-const (car args))) - (and (or (stringp val) - (and (or (listp val) (vectorp val)) - (not (memq nil - (mapcar #'characterp val)))))))) - (push val strings) - (setq args (cdr args))) + (let ((strings nil)) + (while + (and args + (let ((arg (car args))) + (pcase arg + ;; Merge consecutive constant arguments. + ((pred macroexp-const-p) + (let ((val (byteopt--eval-const arg))) + (and (or (stringp val) + (and (or (listp val) (vectorp val)) + (not (memq nil + (mapcar #'characterp val))))) + (progn + (push val strings) + (setq args (cdr args)) + t)))) + ;; Flatten nested `concat' form. + (`(concat . ,nested-args) + (setq args (append nested-args (cdr args))) + t))))) + (when strings (let ((s (apply #'concat (nreverse strings)))) (when (not (zerop (length s)))