emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 8205108 1/2: * lisp/repeat.el: Add option to indicate repeat-mode


From: Juri Linkov
Subject: master 8205108 1/2: * lisp/repeat.el: Add option to indicate repeat-mode in mode-line (bug#47566)
Date: Wed, 14 Apr 2021 14:12:13 -0400 (EDT)

branch: master
commit 8205108217e2ba77b9d0d6176587033d38bbb20b
Author: Juri Linkov <juri@linkov.net>
Commit: Juri Linkov <juri@linkov.net>

    * lisp/repeat.el: Add option to indicate repeat-mode in mode-line 
(bug#47566)
    
    * lisp/repeat.el (repeat-echo-function): Rename from repeat-mode-echo.
    Add choice repeat-echo-mode-line.
    (repeat-in-progress): New variable.
    (repeat-post-hook): Call repeat-echo-function with nil arg
    at the end of repeating sequence.
    (repeat-echo-message-string): New function with body from repeat-post-hook.
    (repeat-echo-message): Rename from repeat-mode-message.
    (repeat-echo-mode-line-string): New variable.
    (repeat-echo-mode-line): New function.
---
 lisp/repeat.el | 127 +++++++++++++++++++++++++++++++++++----------------------
 1 file changed, 78 insertions(+), 49 deletions(-)

diff --git a/lisp/repeat.el b/lisp/repeat.el
index f1b20d3..2875616 100644
--- a/lisp/repeat.el
+++ b/lisp/repeat.el
@@ -348,17 +348,22 @@ For example, you can set it to <return> like 
`isearch-exit'."
   :group 'convenience
   :version "28.1")
 
-(defcustom repeat-mode-echo #'repeat-mode-message
+(defcustom repeat-echo-function #'repeat-echo-message
   "Function to display a hint about available keys.
 Function is called after every repeatable command with one argument:
-a string with a list of keys."
+a repeating map, or nil after deactivating the repeat mode."
   :type '(choice (const :tag "Show hints in the echo area"
-                        repeat-mode-message)
-                 (const :tag "Don't show hints" ignore)
+                        repeat-echo-message)
+                 (const :tag "Show indicator in the mode line"
+                        repeat-echo-mode-line)
+                 (const :tag "No visual feedback" ignore)
                  (function :tag "Function"))
   :group 'convenience
   :version "28.1")
 
+(defvar repeat-in-progress nil
+  "Non-nil when the repeating map is active.")
+
 ;;;###autoload
 (defvar repeat-map nil
   "The value of the repeating map for the next command.
@@ -386,51 +391,75 @@ When Repeat mode is enabled, and the command symbol has 
the property named
 
 (defun repeat-post-hook ()
   "Function run after commands to set transient keymap for repeatable keys."
-  (when repeat-mode
-    (let ((rep-map (or repeat-map
-                       (and (symbolp real-this-command)
-                            (get real-this-command 'repeat-map)))))
-      (when rep-map
-        (when (boundp rep-map)
-          (setq rep-map (symbol-value rep-map)))
-        (let ((map (copy-keymap rep-map))
-              keys)
-
-          ;; Exit when the last char is not among repeatable keys,
-          ;; so e.g. `C-x u u' repeats undo, whereas `C-/ u' doesn't.
-          (when (and (zerop (minibuffer-depth)) ; avoid remapping in prompts
-                     (or (lookup-key map (this-command-keys-vector))
-                         prefix-arg))
-
-            ;; Messaging
-            (unless prefix-arg
-              (map-keymap (lambda (key _) (push key keys)) map)
-              (let ((mess (format-message
-                           "Repeat with %s%s"
-                           (mapconcat (lambda (key)
-                                        (key-description (vector key)))
-                                      keys ", ")
-                           (if repeat-exit-key
-                               (format ", or exit with %s"
-                                       (key-description repeat-exit-key))
-                             ""))))
-                (funcall repeat-mode-echo mess)))
-
-            ;; Adding an exit key
-            (when repeat-exit-key
-              (define-key map repeat-exit-key 'ignore))
-
-            (when (and repeat-keep-prefix (not prefix-arg))
-              (setq prefix-arg current-prefix-arg))
-
-            (set-transient-map map))))))
-  (setq repeat-map nil))
-
-(defun repeat-mode-message (mess)
-  "Function that displays available repeating keys in the echo area."
-  (if (current-message)
-      (message "%s [%s]" (current-message) mess)
-    (message mess)))
+  (let ((was-in-progress repeat-in-progress))
+    (setq repeat-in-progress nil)
+    (when repeat-mode
+      (let ((rep-map (or repeat-map
+                         (and (symbolp real-this-command)
+                              (get real-this-command 'repeat-map)))))
+        (when rep-map
+          (when (boundp rep-map)
+            (setq rep-map (symbol-value rep-map)))
+          (let ((map (copy-keymap rep-map)))
+
+            ;; Exit when the last char is not among repeatable keys,
+            ;; so e.g. `C-x u u' repeats undo, whereas `C-/ u' doesn't.
+            (when (and (zerop (minibuffer-depth)) ; avoid remapping in prompts
+                       (or (lookup-key map (this-command-keys-vector))
+                           prefix-arg))
+
+              ;; Messaging
+              (unless prefix-arg
+                (funcall repeat-echo-function map))
+
+              ;; Adding an exit key
+              (when repeat-exit-key
+                (define-key map repeat-exit-key 'ignore))
+
+              (when (and repeat-keep-prefix (not prefix-arg))
+                (setq prefix-arg current-prefix-arg))
+
+              (setq repeat-in-progress t)
+              (set-transient-map map))))))
+
+    (setq repeat-map nil)
+    (when (and was-in-progress (not repeat-in-progress))
+      (funcall repeat-echo-function nil))))
+
+(defun repeat-echo-message-string (map)
+  "Return a string with a list of repeating keys."
+  (let (keys)
+    (map-keymap (lambda (key _) (push key keys)) map)
+    (format-message "Repeat with %s%s"
+                    (mapconcat (lambda (key)
+                                 (key-description (vector key)))
+                               keys ", ")
+                    (if repeat-exit-key
+                        (format ", or exit with %s"
+                                (key-description repeat-exit-key))
+                      ""))))
+
+(defun repeat-echo-message (map)
+  "Display available repeating keys in the echo area."
+  (when map
+    (let ((mess (repeat-echo-message-string map)))
+      (if (current-message)
+          (message "%s [%s]" (current-message) mess)
+        (message mess)))))
+
+(defvar repeat-echo-mode-line-string
+  (propertize "[Repeating...] " 'face 'mode-line-emphasis)
+  "String displayed in the mode line in repeating mode.")
+;;;###autoload
+(put 'mode-line-defining-kbd-macro 'risky-local-variable t)
+
+(defun repeat-echo-mode-line (map)
+  "Display the repeat indicator in the mode line."
+  (if map
+      (unless (assq 'repeat-in-progress mode-line-modes)
+        (add-to-list 'mode-line-modes (list 'repeat-in-progress
+                                            repeat-echo-mode-line-string)))
+    (force-mode-line-update t)))
 
 (provide 'repeat)
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]