From b3e7768a0ee0e894d7a4c232842af8be014ff8cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= Date: Mon, 19 Dec 2022 12:05:09 +0100 Subject: [PATCH 01/14] Repair setopt test after error demotion to warning * test/lisp/cus-edit-tests.el (test-setopt): Check for a warrning instead of an error in attempt to call `setopt` with a value that does not match the declared type (bug#60162). --- test/lisp/cus-edit-tests.el | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/test/lisp/cus-edit-tests.el b/test/lisp/cus-edit-tests.el index 0ef5168109b..31ba68b4107 100644 --- a/test/lisp/cus-edit-tests.el +++ b/test/lisp/cus-edit-tests.el @@ -83,7 +83,14 @@ (ert-deftest test-setopt () (should (= (setopt cus-edit-test-foo1 1) 1)) (should (= cus-edit-test-foo1 1)) - (should-error (setopt cus-edit-test-foo1 :foo))) - + (let* ((text-quoting-style 'grave) + (warn-txt + (with-current-buffer (get-buffer-create "*Warnings*") + (let ((inhibit-read-only t)) + (erase-buffer)) + (setopt cus-edit-test-foo1 :foo) + (buffer-substring-no-properties (point-min) (point-max))))) + (should (string-search "Value `:foo' does not match type number" + warn-txt)))) (provide 'cus-edit-tests) ;;; cus-edit-tests.el ends here From a75d1da911c07a201a19d8827cd74f181220c274 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Mon, 19 Dec 2022 15:33:09 +0200 Subject: [PATCH 02/14] Make emacsclient add abbreviated file names to file-name-history * lisp/server.el (server-visit-files): Use 'file-name-history--add' to add the visited files to history. (Bug#60097) --- lisp/server.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/server.el b/lisp/server.el index fd740d126df..d963ee5b1e0 100644 --- a/lisp/server.el +++ b/lisp/server.el @@ -1495,7 +1495,7 @@ so don't mark these buffers specially, just visit them normally." minibuffer-auto-raise)) (filen (car file)) (obuf (get-file-buffer filen))) - (add-to-history 'file-name-history filen) + (file-name-history--add filen) (if (null obuf) (progn (run-hooks 'pre-command-hook) From 64163618d21bfa31e56b47c813ce50681c3d3556 Mon Sep 17 00:00:00 2001 From: Richard Hansen Date: Sun, 18 Dec 2022 23:04:00 -0500 Subject: [PATCH 03/14] whitespace: Fix unintended change in buffer modification status * lisp/whitespace.el (whitespace--empty-at-bob-matcher) whitespace--empty-at-eob-matcher, whitespace--update-bob-eob): Silently add the `font-lock-multiline' text property when highlighting beginning-of-buffer and end-of-buffer empty lines to prevent Emacs from running modification hooks or considering the buffer to be modified (Bug#60066). * test/lisp/whitespace-tests.el (whitespace-tests--empty-bob-eob-modified): Add a regression test. --- lisp/whitespace.el | 28 ++++++++++++++++------------ test/lisp/whitespace-tests.el | 10 ++++++++++ 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/lisp/whitespace.el b/lisp/whitespace.el index 25ea07e9db7..9bc6ad9db46 100644 --- a/lisp/whitespace.el +++ b/lisp/whitespace.el @@ -2268,10 +2268,11 @@ Highlighting those lines can be distracting.)" (save-excursion (goto-char whitespace-point) (line-beginning-position))))) (when (= p 1) - ;; See the comment in `whitespace--update-bob-eob' for why this - ;; text property is added here. - (put-text-property 1 whitespace-bob-marker - 'font-lock-multiline t)) + (with-silent-modifications + ;; See the comment in `whitespace--update-bob-eob' for why + ;; this text property is added here. + (put-text-property 1 whitespace-bob-marker + 'font-lock-multiline t))) (when (< p e) (set-match-data (list p e)) (goto-char e)))) @@ -2292,10 +2293,11 @@ about to start typing, and if they do, that line and previous empty lines will no longer be EoB empty lines. Highlighting those lines can be distracting.)" (when (= limit (1+ (buffer-size))) - ;; See the comment in `whitespace--update-bob-eob' for why this - ;; text property is added here. - (put-text-property whitespace-eob-marker limit - 'font-lock-multiline t)) + (with-silent-modifications + ;; See the comment in `whitespace--update-bob-eob' for why this + ;; text property is added here. + (put-text-property whitespace-eob-marker limit + 'font-lock-multiline t))) (let ((b (max (point) whitespace-eob-marker whitespace-bob-marker ; See comment in the bob func. (save-excursion (goto-char whitespace-point) @@ -2437,8 +2439,9 @@ purposes)." (save-match-data (when (looking-at whitespace-empty-at-bob-regexp) (set-marker whitespace-bob-marker (match-end 1)) - (put-text-property (match-beginning 1) (match-end 1) - 'font-lock-multiline t)))) + (with-silent-modifications + (put-text-property (match-beginning 1) (match-end 1) + 'font-lock-multiline t))))) (when (or (null end) (>= end (save-excursion (goto-char whitespace-eob-marker) @@ -2451,8 +2454,9 @@ purposes)." (when (whitespace--looking-back whitespace-empty-at-eob-regexp) (set-marker whitespace-eob-marker (match-beginning 1)) - (put-text-property (match-beginning 1) (match-end 1) - 'font-lock-multiline t))))))))) + (with-silent-modifications + (put-text-property (match-beginning 1) (match-end 1) + 'font-lock-multiline t)))))))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/test/lisp/whitespace-tests.el b/test/lisp/whitespace-tests.el index fb53543c9e1..3e94d7e921b 100644 --- a/test/lisp/whitespace-tests.el +++ b/test/lisp/whitespace-tests.el @@ -327,6 +327,16 @@ buffer's content." "«:whitespace-empty:\n" "»"))))) +(ert-deftest whitespace-tests--empty-bob-eob-modified () + "Regression test for Bug#60066." + (whitespace-tests--with-test-buffer '() + (insert "\nx\n\n") + (goto-char 2) + (set-buffer-modified-p nil) + (let ((whitespace-style '(face empty))) + (whitespace-mode 1) + (should (not (buffer-modified-p)))))) + (provide 'whitespace-tests) ;;; whitespace-tests.el ends here From 63cdbd986bb8f841717e2d813df6f75b6b02cf8b Mon Sep 17 00:00:00 2001 From: "F. Jason Park" Date: Sun, 11 Dec 2022 19:16:07 -0800 Subject: [PATCH 04/14] ; Really respect browse-url var in erc-compat * lisp/erc/erc-compat.el: Do what was supposed to be done by 75f26646d4a569cfb485de4baddcda66ff44b2c3 "; Be nicer when updating browse-url var in erc-compat". This is the less harmful version of that patch (from bug#59976#8) but without the cl-lib requirement since users may not want to load the main ERC library right away. * lisp/erc/erc.el: Clarify some comments regarding the core API. --- lisp/erc/erc-compat.el | 10 +++++----- lisp/erc/erc.el | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/lisp/erc/erc-compat.el b/lisp/erc/erc-compat.el index 77625398abd..fdcb146d42a 100644 --- a/lisp/erc/erc-compat.el +++ b/lisp/erc/erc-compat.el @@ -391,11 +391,11 @@ If START or END is negative, it counts from the end." (cond ((fboundp 'browse-url-irc)) ; 29 ((boundp 'browse-url-default-handlers) ; 28 - (setf (alist-get "\\`irc6?s?://" browse-url-default-handlers - nil nil (lambda (a _) - (and (stringp a) - (string-match-p a "irc://localhost")))) - #'erc-compat--29-browse-url-irc)) + (add-to-list 'browse-url-default-handlers + '("\\`irc6?s?://" . erc-compat--29-browse-url-irc) + nil (lambda (_ a) + (and (stringp (car-safe a)) + (string-match-p (car a) "irc://localhost"))))) ((boundp 'browse-url-browser-function) ; 27 (require 'browse-url) (let ((existing browse-url-browser-function)) diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index 6cfc39c4bda..6a5e0018964 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -1765,8 +1765,7 @@ all channel buffers on all servers." ;; to, it was never realized. ;; ;; New library code should use the `erc--target' struct instead. -;; Third-party code can continue to use this until a getter for -;; `erc--target' (or whatever replaces it) is exported. +;; Third-party code can continue to use this and `erc-default-target'. (defvar-local erc-default-recipients nil "List of default recipients of the current buffer.") @@ -6012,13 +6011,14 @@ See also `erc-downcase'." ;; While `erc-default-target' happens to return nil in channel buffers ;; you've parted or from which you've been kicked, using it to detect ;; whether a channel is currently joined may become unreliable in the -;; future. For now, new code should consider using +;; future. For now, third-party code can use ;; ;; (erc-get-channel-user (erc-current-nick)) ;; -;; and expect a nicer option eventually. For retrieving a target -;; regardless of subscription or connection status, use replacements -;; based on `erc--target' instead. See also `erc--default-target'. +;; A predicate may be provided eventually. For retrieving a target's +;; name regardless of subscription or connection status, new library +;; code should use `erc--default-target'. Third-party code should +;; continue to use `erc-default-target'. (defun erc-default-target () "Return the current default target (as a character string) or nil if none." From 23f7c9c2a92e4619b7c4d2286d4249f812cd695d Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Mon, 19 Dec 2022 19:01:04 +0200 Subject: [PATCH 05/14] Fix storing email into nnmail by Gnus * lisp/gnus/nnml.el (nnml--encode-headers): Wrap 'rfc2047-encode-string' calls with 'ignore-errors', to avoid disrupting email workflows due to possibly-invalid headers. Reported by Florian Weimer . --- lisp/gnus/nnml.el | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/lisp/gnus/nnml.el b/lisp/gnus/nnml.el index 40e4b9ea828..7aa445e6646 100644 --- a/lisp/gnus/nnml.el +++ b/lisp/gnus/nnml.el @@ -776,17 +776,22 @@ article number. This function is called narrowed to an article." (nnml--encode-headers headers) headers)))) +;; RFC2047-encode Subject and From, but leave invalid headers unencoded. (defun nnml--encode-headers (headers) (let ((subject (mail-header-subject headers)) (rfc2047-encoding-type 'mime)) (unless (string-match "\\`[[:ascii:]]*\\'" subject) - (setf (mail-header-subject headers) - (mail-encode-encoded-word-string subject t)))) + (let ((encoded-subject + (ignore-errors (mail-encode-encoded-word-string subject t)))) + (if encoded-subject + (setf (mail-header-subject headers) encoded-subject))))) (let ((from (mail-header-from headers)) (rfc2047-encoding-type 'address-mime)) (unless (string-match "\\`[[:ascii:]]*\\'" from) - (setf (mail-header-from headers) - (rfc2047-encode-string from t))))) + (let ((encoded-from + (ignore-errors (rfc2047-encode-string from t)))) + (if encoded-from + (setf (mail-header-from headers) encoded-from)))))) (defun nnml-get-nov-buffer (group &optional incrementalp) (let ((buffer (gnus-get-buffer-create From 399433cc2b9500b7ee78503c03cead106b76bbd6 Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Mon, 19 Dec 2022 19:54:08 +0200 Subject: [PATCH 06/14] * lisp/progmodes/project.el: Filter out empty strings from history (bug#58447) (project--read-file-cpd-relative): Do not include empty strings (when prefix has the same length as the string). --- lisp/progmodes/project.el | 1 + 1 file changed, 1 insertion(+) diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index 559da6dd649..605636d93e3 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -1045,6 +1045,7 @@ by the user at will." (mapcan (lambda (s) (and (string-prefix-p abbr-cpd s) + (not (eq (length abbr-cpd) (length s))) (list (substring s (length abbr-cpd))))) (symbol-value hist)))) (project--completing-read-strict prompt From b9e813f79f2d7afb5f14caad17a865e66af17f15 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Mon, 19 Dec 2022 19:37:44 +0200 Subject: [PATCH 07/14] ; ruby-indent-level: Improve the docstring --- lisp/progmodes/ruby-mode.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index fa51597697f..d7efe982870 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el @@ -212,7 +212,7 @@ It should match the part after \"def\" and until \"=\".") :safe 'booleanp) (defcustom ruby-indent-level 2 - "Indentation of Ruby statements." + "Number of spaces for each indentation step in `ruby-mode'." :type 'integer :safe 'integerp) From 2b1fdbffcb595bcd72fa9aa3db674c6985042bcb Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Mon, 19 Dec 2022 21:01:27 +0200 Subject: [PATCH 08/14] ruby-method-params-indent: New user option * lisp/progmodes/ruby-mode.el (ruby-method-params-indent): New option (bug#60110). (ruby-smie-rules): Use it. * etc/NEWS: Mention it. * test/lisp/progmodes/ruby-mode-resources/ruby.rb: Ensure the var's value is default. * test/lisp/progmodes/ruby-mode-resources/ruby-method-params-indent.rb: New file. * test/lisp/progmodes/ruby-mode-tests.el (ruby-deftest-indent): New macro, use it to run the indentation test using the new file. Disable the :expensive-test tag, because neither runs for "longer than some few seconds", both take significantly below 1s. --- etc/NEWS | 3 +++ lisp/progmodes/ruby-mode.el | 26 ++++++++++++++++--- .../ruby-method-params-indent.rb | 18 +++++++++++++ .../progmodes/ruby-mode-resources/ruby.rb | 4 +++ test/lisp/progmodes/ruby-mode-tests.el | 24 ++++++++++------- 5 files changed, 62 insertions(+), 13 deletions(-) create mode 100644 test/lisp/progmodes/ruby-mode-resources/ruby-method-params-indent.rb diff --git a/etc/NEWS b/etc/NEWS index 017fd850b4e..0e844596347 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2761,6 +2761,9 @@ project-dedicated or global) is specified by the new --- *** Support for endless methods. +--- +*** New user option 'ruby-method-params-indent'. + ** Eshell +++ diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index d7efe982870..2b813dfcbcc 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el @@ -268,6 +268,23 @@ Only has effect when `ruby-use-smie' is t." :safe 'booleanp :version "24.4") +(defcustom ruby-method-params-indent t + "Indentation of multiline method parameters. + +When t, the parameters list is indented to the method name. + +When a number, indent the parameters list this many columns +against the beginning of the method (the \"def\" keyword). + +The value nil means the same as 0. + +Only has effect when `ruby-use-smie' is t." + :type '(choice (const :tag "Indent to the method name" t) + (number :tag "Indent specified number of columns against def") + (const :tag "Indent to def" nil)) + :safe (lambda (val) (or (memq val '(t nil)) (numberp val))) + :version 29.1) + (defcustom ruby-deep-arglist t "Deep indent lists in parenthesis when non-nil. Also ignores spaces after parenthesis when `space'. @@ -660,9 +677,12 @@ This only affects the output of the command `ruby-toggle-block'." (unless (or (eolp) (forward-comment 1)) (cons 'column (current-column))))) ('(:before . " @ ") - (save-excursion - (skip-chars-forward " \t") - (cons 'column (current-column)))) + (if (or (eq ruby-method-params-indent t) + (not (smie-rule-parent-p "def" "def="))) + (save-excursion + (skip-chars-forward " \t") + (cons 'column (current-column))) + (smie-rule-parent (or ruby-method-params-indent 0)))) ('(:before . "do") (ruby-smie--indent-to-stmt)) ('(:before . ".") (if (smie-rule-sibling-p) diff --git a/test/lisp/progmodes/ruby-mode-resources/ruby-method-params-indent.rb b/test/lisp/progmodes/ruby-mode-resources/ruby-method-params-indent.rb new file mode 100644 index 00000000000..2b665797397 --- /dev/null +++ b/test/lisp/progmodes/ruby-mode-resources/ruby-method-params-indent.rb @@ -0,0 +1,18 @@ +class C + def self.foo( + baz, + bar + ) = + what + + def foo=( + baz, + bar + ) + hello + end +end + +# Local Variables: +# ruby-method-params-indent: 0 +# End: diff --git a/test/lisp/progmodes/ruby-mode-resources/ruby.rb b/test/lisp/progmodes/ruby-mode-resources/ruby.rb index 2451edaee22..6a69d9db78a 100644 --- a/test/lisp/progmodes/ruby-mode-resources/ruby.rb +++ b/test/lisp/progmodes/ruby-mode-resources/ruby.rb @@ -538,3 +538,7 @@ class Bar baz end end + +# Local Variables: +# ruby-method-params-indent: t +# End: diff --git a/test/lisp/progmodes/ruby-mode-tests.el b/test/lisp/progmodes/ruby-mode-tests.el index 9be01dc78f9..560f780285a 100644 --- a/test/lisp/progmodes/ruby-mode-tests.el +++ b/test/lisp/progmodes/ruby-mode-tests.el @@ -943,16 +943,20 @@ VALUES-PLIST is a list with alternating index and value elements." "Blub#bye" "Blub#hiding"))))) -(ert-deftest ruby--indent/converted-from-manual-test () - :tags '(:expensive-test) - ;; Converted from manual test. - (let ((buf (find-file-noselect (ert-resource-file "ruby.rb")))) - (unwind-protect - (with-current-buffer buf - (let ((orig (buffer-string))) - (indent-region (point-min) (point-max)) - (should (equal (buffer-string) orig)))) - (kill-buffer buf)))) +(defmacro ruby-deftest-indent (file) + `(ert-deftest ,(intern (format "ruby-indent-test/%s" file)) () + ;; :tags '(:expensive-test) + (let ((buf (find-file-noselect (ert-resource-file ,file)))) + (unwind-protect + (with-current-buffer buf + (let ((orig (buffer-string))) + ;; Indent and check that we get the original text. + (indent-region (point-min) (point-max)) + (should (equal (buffer-string) orig)))) + (kill-buffer buf))))) + +(ruby-deftest-indent "ruby.rb") +(ruby-deftest-indent "ruby-method-params-indent.rb") (ert-deftest ruby--test-chained-indentation () (with-temp-buffer From cfbfd393b450d4eb7ac0b7922b44208688553c9e Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Mon, 19 Dec 2022 21:46:40 +0200 Subject: [PATCH 09/14] * lisp/progmodes/project.el (project--read-file-cpd-relative): Optimize. --- lisp/progmodes/project.el | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index 605636d93e3..c2633798473 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -1040,13 +1040,14 @@ by the user at will." (setq substrings (cons "./" substrings)))) (new-collection (project--file-completion-table substrings)) (abbr-cpd (abbreviate-file-name common-parent-directory)) + (abbr-cpd-length (length abbr-cpd)) (relname (cl-letf ((history-add-new-input nil) ((symbol-value hist) (mapcan (lambda (s) (and (string-prefix-p abbr-cpd s) - (not (eq (length abbr-cpd) (length s))) - (list (substring s (length abbr-cpd))))) + (not (eq abbr-cpd-length (length s))) + (list (substring s abbr-cpd-length)))) (symbol-value hist)))) (project--completing-read-strict prompt new-collection From fb7f3999c59ce3a1b08bca8d8b79db885fd3550f Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Tue, 20 Dec 2022 02:58:48 +0200 Subject: [PATCH 10/14] ; Fix ruby-method-params-indent's :version value --- lisp/progmodes/ruby-mode.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index 2b813dfcbcc..1f3e9b6ae7b 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el @@ -283,7 +283,7 @@ Only has effect when `ruby-use-smie' is t." (number :tag "Indent specified number of columns against def") (const :tag "Indent to def" nil)) :safe (lambda (val) (or (memq val '(t nil)) (numberp val))) - :version 29.1) + :version "29.1") (defcustom ruby-deep-arglist t "Deep indent lists in parenthesis when non-nil. From 8550a9937858e4524acd43015b28a42a707d26fc Mon Sep 17 00:00:00 2001 From: Philipp Stephani Date: Tue, 20 Dec 2022 13:29:49 +0100 Subject: [PATCH 11/14] ; * src/emacs-module.h.in (enum emacs_funcall_exit): Fix typo. --- src/emacs-module.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/emacs-module.h.in b/src/emacs-module.h.in index bef89b059fc..22096db7e85 100644 --- a/src/emacs-module.h.in +++ b/src/emacs-module.h.in @@ -116,7 +116,7 @@ enum emacs_funcall_exit /* Function has signaled an error using `signal'. */ emacs_funcall_exit_signal = 1, - /* Function has exit using `throw'. */ + /* Function has exited using `throw'. */ emacs_funcall_exit_throw = 2 }; From d03ea8937803c6714df71dd148c79ca893d159e9 Mon Sep 17 00:00:00 2001 From: Brian Leung Date: Mon, 19 Dec 2022 15:03:06 -0800 Subject: [PATCH 12/14] eglot.el: Add vscode-json-languageserver to eglot-server-programs * lisp/progmodes/eglot.el (eglot-server-programs): Add the alternative name of the vcscode JSON server. (Bug#60198) --- lisp/progmodes/eglot.el | 1 + 1 file changed, 1 insertion(+) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index ce4ca4f3d92..0f1bfd0447d 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -190,6 +190,7 @@ chosen (interactively or automatically)." '("pylsp" "pyls" ("pyright-langserver" "--stdio") "jedi-language-server"))) ((js-json-mode json-mode json-ts-mode) . ,(eglot-alternatives '(("vscode-json-language-server" "--stdio") + ("vscode-json-languageserver" "--stdio") ("json-languageserver" "--stdio")))) ((js-mode js-ts-mode tsx-ts-mode typescript-ts-mode typescript-mode) . ("typescript-language-server" "--stdio")) From 8ef3777d54429744dc941145c25067d6964374aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=ADn?= Date: Tue, 20 Dec 2022 16:32:37 +0100 Subject: [PATCH 13/14] Correct capitalization of Lisp in the manual (bug#60222) * doc/lispref/compile.texi (Native-Compilation Functions): Fix typo. --- doc/lispref/compile.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/lispref/compile.texi b/doc/lispref/compile.texi index 3e397349995..ae4905bb1f9 100644 --- a/doc/lispref/compile.texi +++ b/doc/lispref/compile.texi @@ -930,7 +930,7 @@ used by Emacs to natively-compile any Lisp file or byte-compiled Lisp file that is loaded into Emacs, when no natively-compiled file for it is available. Note that because of this use of a subprocess, native compilation may produce warning and errors which byte-compilation does -not, and lisp code may thus need to be modified to work correctly. See +not, and Lisp code may thus need to be modified to work correctly. See @code{native-comp-async-report-warnings-errors} in @pxref{Native-Compilation Variables} for more details. From d3a76db88b4357fe1c92f240796ea9b522b97a8e Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Tue, 20 Dec 2022 19:22:15 +0200 Subject: [PATCH 14/14] * lisp/repeat.el: Fix repeat-keep-prefix to allow customizing it to non-nil. * lisp/repeat.el (repeat-keep-prefix): Add or remove 'repeat-pre-hook' depending on the customized value. (repeat-mode): Add or remove 'repeat-pre-hook' to/from 'pre-command-hook' when 'repeat-keep-prefix' is non-nil. (repeat-pre-hook): New function. (repeat-get-map, repeat-check-map): New function refactored from 'repeat-post-hook'. (repeat-post-hook): Move some code to smaller functions. (describe-repeat-maps): Set outline-regexp without ^L. * test/lisp/repeat-tests.el (repeat-tests-keep-prefix): Uncomment test case that is fixed now in bug#51281 and bug#55986. --- lisp/repeat.el | 111 ++++++++++++++++++++++++-------------- test/lisp/repeat-tests.el | 30 ++++++----- 2 files changed, 86 insertions(+), 55 deletions(-) diff --git a/lisp/repeat.el b/lisp/repeat.el index 33e8d98ce33..3b3a444ee24 100644 --- a/lisp/repeat.el +++ b/lisp/repeat.el @@ -368,6 +368,13 @@ This property can override the value of this variable." (defcustom repeat-keep-prefix nil "Whether to keep the prefix arg of the previous command when repeating." :type 'boolean + :initialize #'custom-initialize-default + :set (lambda (sym val) + (set-default sym val) + (when repeat-mode + (if repeat-keep-prefix + (add-hook 'pre-command-hook 'repeat-pre-hook) + (remove-hook 'pre-command-hook 'repeat-pre-hook)))) :group 'repeat :version "28.1") @@ -419,7 +426,11 @@ When Repeat mode is enabled, and the command symbol has the property named See `describe-repeat-maps' for a list of all repeatable commands." :global t :group 'repeat (if (not repeat-mode) - (remove-hook 'post-command-hook 'repeat-post-hook) + (progn + (remove-hook 'pre-command-hook 'repeat-pre-hook) + (remove-hook 'post-command-hook 'repeat-post-hook)) + (when repeat-keep-prefix + (add-hook 'pre-command-hook 'repeat-pre-hook)) (add-hook 'post-command-hook 'repeat-post-hook) (let* ((keymaps nil) (commands (all-completions @@ -431,15 +442,21 @@ See `describe-repeat-maps' for a list of all repeatable commands." (length commands) (length (delete-dups keymaps)))))) -(defvar repeat--prev-mb '(0) - "Previous minibuffer state.") - (defun repeat--command-property (property) (or (and (symbolp this-command) (get this-command property)) (and (symbolp real-this-command) (get real-this-command property)))) +(defun repeat-get-map () + "Return a transient map for keys repeatable after the current command." + (when repeat-mode + (let ((rep-map (or repeat-map (repeat--command-property 'repeat-map)))) + (when rep-map + (when (and (symbolp rep-map) (boundp rep-map)) + (setq rep-map (symbol-value rep-map))) + rep-map)))) + (defun repeat-check-key (key map) "Check if the last key is suitable to activate the repeating MAP." (let* ((prop (repeat--command-property 'repeat-check-key)) @@ -449,50 +466,61 @@ See `describe-repeat-maps' for a list of all repeatable commands." ;; Try without modifiers: (lookup-key map (vector (event-basic-type key)))))) +(defvar repeat--prev-mb '(0) + "Previous minibuffer state.") + +(defun repeat-check-map (map) + "Decides whether MAP can be used for the next command." + (and map + ;; Detect changes in the minibuffer state to allow repetitions + ;; in the same minibuffer, but not when the minibuffer is activated + ;; in the middle of repeating sequence (bug#47566). + (or (< (minibuffer-depth) (car repeat--prev-mb)) + (eq current-minibuffer-command (cdr repeat--prev-mb))) + (repeat-check-key last-command-event map) + t)) + +(defun repeat-pre-hook () + "Function run before commands to handle repeatable keys." + (when (and repeat-mode repeat-keep-prefix repeat-in-progress + (not prefix-arg) current-prefix-arg) + (let ((map (repeat-get-map))) + ;; Only when repeat-post-hook will activate the same map + (when (repeat-check-map map) + ;; Optimize to use less logic in the function `repeat-get-map' + ;; for the next call: when called again from `repeat-post-hook' + ;; it will use the variable `repeat-map'. + (setq repeat-map map) + ;; Preserve universal argument + (setq prefix-arg current-prefix-arg))))) + (defun repeat-post-hook () "Function run after commands to set transient keymap for repeatable keys." (let ((was-in-progress repeat-in-progress)) (setq repeat-in-progress nil) - (when repeat-mode - (let ((rep-map (or repeat-map (repeat--command-property 'repeat-map)))) - (when rep-map - (when (and (symbolp rep-map) (boundp rep-map)) - (setq rep-map (symbol-value rep-map))) - (let ((map (copy-keymap rep-map))) + (let ((map (repeat-get-map))) + (when (repeat-check-map map) + ;; Messaging + (funcall repeat-echo-function map) - (when (and - ;; Detect changes in the minibuffer state to allow repetitions - ;; in the same minibuffer, but not when the minibuffer is activated - ;; in the middle of repeating sequence (bug#47566). - (or (< (minibuffer-depth) (car repeat--prev-mb)) - (eq current-minibuffer-command (cdr repeat--prev-mb))) - (or (not repeat-keep-prefix) prefix-arg) - (repeat-check-key last-command-event map)) + ;; Adding an exit key + (when repeat-exit-key + (setq map (copy-keymap map)) + (define-key map (if (key-valid-p repeat-exit-key) + (kbd repeat-exit-key) + repeat-exit-key) + 'ignore)) - ;; Messaging - (unless prefix-arg - (funcall repeat-echo-function map)) + (setq repeat-in-progress t) + (repeat--exit) + (let ((exitfun (set-transient-map map))) + (setq repeat-exit-function exitfun) - ;; Adding an exit key - (when repeat-exit-key - (define-key map (if (key-valid-p repeat-exit-key) - (kbd repeat-exit-key) - repeat-exit-key) - 'ignore)) - - (when (and repeat-keep-prefix (not prefix-arg)) - (setq prefix-arg current-prefix-arg)) - - (setq repeat-in-progress t) - (let ((exitfun (set-transient-map map))) - (repeat--exit) - (setq repeat-exit-function exitfun) - - (let* ((prop (repeat--command-property 'repeat-exit-timeout)) - (timeout (unless (eq prop 'no) (or prop repeat-exit-timeout)))) - (when timeout - (setq repeat-exit-timer - (run-with-idle-timer timeout nil #'repeat-exit)))))))))) + (let* ((prop (repeat--command-property 'repeat-exit-timeout)) + (timeout (unless (eq prop 'no) (or prop repeat-exit-timeout)))) + (when timeout + (setq repeat-exit-timer + (run-with-idle-timer timeout nil #'repeat-exit))))))) (setq repeat-map nil) (setq repeat--prev-mb (cons (minibuffer-depth) current-minibuffer-command)) @@ -582,6 +610,7 @@ Used in `repeat-mode'." (push s (alist-get (get s 'repeat-map) keymaps))))) (with-help-window (help-buffer) (with-current-buffer standard-output + (setq-local outline-regexp "[*]+") (insert "A list of keymaps used by commands with the symbol property `repeat-map'.\n") (dolist (keymap (sort keymaps (lambda (a b) diff --git a/test/lisp/repeat-tests.el b/test/lisp/repeat-tests.el index 1382d003599..06c6f748a2a 100644 --- a/test/lisp/repeat-tests.el +++ b/test/lisp/repeat-tests.el @@ -76,27 +76,27 @@ "C-x w a b a c" '((1 a) (1 b) (1 a)) "c") (repeat-tests--check - "M-C-a b a c" + "C-M-a b a c" '((1 a) (1 b) (1 a)) "c") (repeat-tests--check - "M-C-z b a c" + "C-M-z b a c" '((1 a)) "bac") (unwind-protect (progn (put 'repeat-tests-call-a 'repeat-check-key 'no) (repeat-tests--check - "M-C-z b a c" + "C-M-z b a c" '((1 a) (1 b) (1 a)) "c")) (put 'repeat-tests-call-a 'repeat-check-key nil))) (let ((repeat-check-key nil)) (repeat-tests--check - "M-C-z b a c" + "C-M-z b a c" '((1 a) (1 b) (1 a)) "c") (unwind-protect (progn (put 'repeat-tests-call-a 'repeat-check-key t) (repeat-tests--check - "M-C-z b a c" + "C-M-z b a c" '((1 a)) "bac")) (put 'repeat-tests-call-a 'repeat-check-key nil)))))) @@ -125,15 +125,17 @@ (repeat-tests--check "C-2 C-x w a C-3 c" '((2 a)) "ccc")) - ;; TODO: fix and uncomment - ;; (let ((repeat-keep-prefix t)) - ;; (repeat-tests--check - ;; "C-2 C-x w a b a b c" - ;; '((2 a) (2 b) (2 a) (2 b)) "c") - ;; (repeat-tests--check - ;; "C-2 C-x w a C-1 C-2 b a C-3 C-4 b c" - ;; '((2 a) (12 b) (12 a) (34 b)) "c")) - ))) + ;; Fixed in bug#51281 and bug#55986 + (let ((repeat-keep-prefix t)) + ;; Re-enable to take effect. + (repeat-mode -1) (repeat-mode +1) + (repeat-tests--check + "C-2 C-x w a b a b c" + '((2 a) (2 b) (2 a) (2 b)) "c") + ;; (repeat-tests--check + ;; "C-2 C-x w a C-1 C-2 b a C-3 C-4 b c" + ;; '((2 a) (12 b) (12 a) (34 b)) "c") + )))) ;; TODO: :tags '(:expensive-test) for repeat-exit-timeout