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 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