bug-gnu-emacs
[Top][All Lists]
Advanced

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

bug#46515: Repeat mode


From: Juri Linkov
Subject: bug#46515: Repeat mode
Date: Sun, 14 Feb 2021 20:27:08 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (x86_64-pc-linux-gnu)

Tags: patch

Like discussed in bug#12572, bug#15234 and recently in
https://lists.gnu.org/archive/html/emacs-devel/2021-02/msg00139.html
here is a patch that provides an opt-in feature for easy-to-repeat
key sequences:

C-x u u u - undo sequences
C-x o o o - switch windows
C-x right left right left - next/previous buffer switching
M-g n n n p p p - next-error navigation
C-x { { { } } } - window resizing
...

diff --git a/lisp/repeat.el b/lisp/repeat.el
index 795577c93f..1b31963d22 100644
--- a/lisp/repeat.el
+++ b/lisp/repeat.el
@@ -329,6 +329,39 @@ repeat-message
 
 ;;;;; ************************* EMACS CONTROL ************************* ;;;;;
 
+
+;;; repeat-mode
+
+(defcustom repeat-exit-key [return] ; like `isearch-exit'
+  "Key that stops the modal repeating of keys in sequence."
+  :type '(choice (const :tag "No special key to exit repeat sequence" nil)
+                (key-sequence :tag "Key that exits repeat sequence"))
+  :group 'convenience
+  :version "28.1")
+
+;;;###autoload
+(define-minor-mode repeat-mode
+  "Toggle Repeat mode.
+When Repeat mode is enabled, and the command symbol has the property named
+`repeat-map', this map is activated temporarily for the next command."
+  :global t :group 'convenience
+  (if (not repeat-mode)
+      (remove-hook 'post-command-hook 'repeat-post-hook)
+    (add-hook 'post-command-hook 'repeat-post-hook)))
+
+(defun repeat-post-hook ()
+  "Function run after commands to set transient keymap."
+  (when repeat-mode
+    (let ((repeat-map (and (symbolp this-command)
+                           (get this-command 'repeat-map))))
+      (when repeat-map
+        (when (boundp repeat-map)
+          (setq repeat-map (symbol-value repeat-map)))
+        (let ((map (copy-keymap repeat-map)))
+          (when repeat-exit-key
+            (define-key map repeat-exit-key 'ignore))
+          (set-transient-map map))))))
+
 (provide 'repeat)
 
 ;;; repeat.el ends here
diff --git a/lisp/bindings.el b/lisp/bindings.el
index 2f4bab11cf..70ddd9d9ba 100644
--- a/lisp/bindings.el
+++ b/lisp/bindings.el
@@ -950,6 +950,12 @@ global-map
 ;; Richard said that we should not use C-x <uppercase letter> and I have
 ;; no idea whereas to bind it.  Any suggestion welcome.  -stef
 ;; (define-key ctl-x-map "U" 'undo-only)
+(defvar undo-repeat-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map "u" 'undo)
+    map)
+  "Keymap to repeat undo `C-x u u' sequences.  Used in `repeat-mode'.")
+(put 'undo 'repeat-map 'undo-repeat-map)
 
 (define-key esc-map "!" 'shell-command)
 (define-key esc-map "|" 'shell-command-on-region)
@@ -964,6 +970,17 @@ ctl-x-map
 (define-key global-map [XF86Back] 'previous-buffer)
 (put 'previous-buffer :advertised-binding [?\C-x left])
 
+(defvar next-buffer-repeat-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map [right] 'next-buffer)
+    (define-key map [C-right] 'next-buffer)
+    (define-key map [left] 'previous-buffer)
+    (define-key map [C-left] 'previous-buffer)
+    map)
+  "Keymap to repeat next-buffer key sequences.  Used in `repeat-mode'.")
+(put 'next-buffer 'repeat-map 'next-buffer-repeat-map)
+(put 'previous-buffer 'repeat-map 'next-buffer-repeat-map)
+
 (let ((map minibuffer-local-map))
   (define-key map "\en"   'next-history-element)
   (define-key map [next]  'next-history-element)
@@ -1036,6 +1053,17 @@ global-map
 
 (define-key ctl-x-map "`" 'next-error)
 
+(defvar next-error-repeat-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map    "n" 'next-error)
+    (define-key map "\M-n" 'next-error)
+    (define-key map    "p" 'previous-error)
+    (define-key map "\M-p" 'previous-error)
+    map)
+  "Keymap to repeat next-error key sequences.  Used in `repeat-mode'.")
+(put 'next-error 'repeat-map 'next-error-repeat-map)
+(put 'previous-error 'repeat-map 'next-error-repeat-map)
+
 (defvar goto-map (make-sparse-keymap)
   "Keymap for navigation commands.")
 (define-key esc-map "g" goto-map)
diff --git a/lisp/window.el b/lisp/window.el
index 2d0a73b426..d1a0f80da9 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -10252,6 +10252,30 @@ ctl-x-4-map
 (define-key ctl-x-4-map "1" 'same-window-prefix)
 (define-key ctl-x-4-map "4" 'other-window-prefix)
 
+(defvar other-window-repeat-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map "o" 'other-window)
+    map)
+  "Keymap to repeat other-window key sequences.  Used in `repeat-mode'.")
+
+(put 'other-window 'repeat-map 'other-window-repeat-map)
+
+(defvar resize-window-repeat-map
+  (let ((map (make-sparse-keymap)))
+    ;; Standard keys:
+    (define-key map "^" 'enlarge-window)
+    (define-key map "}" 'enlarge-window-horizontally)
+    (define-key map "{" 'shrink-window-horizontally)
+    ;; Additional keys:
+    (define-key map "v" 'shrink-window)
+    map)
+  "Keymap to repeat window resizing commands.  Used in `repeat-mode'.")
+
+(put 'enlarge-window 'repeat-map 'resize-window-repeat-map)
+(put 'enlarge-window-horizontally 'repeat-map 'resize-window-repeat-map)
+(put 'shrink-window-horizontally 'repeat-map 'resize-window-repeat-map)
+(put 'shrink-window 'repeat-map 'resize-window-repeat-map)
+
 (provide 'window)
 
 ;;; window.el ends here

reply via email to

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