New transient mode 'repeat-mode' to allow shorter key sequences (bug#46515)
* doc/emacs/basic.texi (Repeating): Document repeat-mode. * lisp/repeat.el (repeat-exit-key): New defcustom. (repeat-mode): New global minor mode. (repeat-post-hook): New function. * lisp/bindings.el (undo-repeat-map): New variable. (undo): Put 'repeat-map' property with 'undo-repeat-map'. (next-error-repeat-map): New variable. (next-error, previous-error): Put 'repeat-map' property with 'next-error-repeat-map'. * lisp/window.el (other-window-repeat-map): New variable. (other-window): Put 'repeat-map' property with 'other-window-repeat-map'. (resize-window-repeat-map): New variable. (enlarge-window, enlarge-window-horizontally) (shrink-window-horizontally, shrink-window): Put 'repeat-map' property with 'resize-window-repeat-map'.
This commit is contained in:
parent
734396aa04
commit
12409c9064
5 changed files with 132 additions and 0 deletions
|
@ -880,3 +880,14 @@ characters. You can repeat that command (including its argument) three
|
|||
additional times, to delete a total of 80 characters, by typing @kbd{C-x
|
||||
z z z}. The first @kbd{C-x z} repeats the command once, and each
|
||||
subsequent @kbd{z} repeats it once again.
|
||||
|
||||
@findex repeat-mode
|
||||
Also you can activate @code{repeat-mode} that temporarily enables
|
||||
a transient mode with short keys after a limited number of commands.
|
||||
Currently supported shorter key sequences are @kbd{C-x u u} instead of
|
||||
@kbd{C-x u C-x u} to undo many changes, @kbd{C-x o o} instead of
|
||||
@kbd{C-x o C-x o} to switch several windows, @kbd{C-x @{ @{ @} @} ^ ^
|
||||
v v} to resize the selected window interactively, @kbd{M-g n n p p} to
|
||||
navigate @code{next-error} matches. Any other key exits transient mode
|
||||
and then is executed normally. The user option @code{repeat-exit-key}
|
||||
defines an additional key to exit this transient mode.
|
||||
|
|
11
etc/NEWS
11
etc/NEWS
|
@ -2068,6 +2068,17 @@ the behavior introduced in Octave 3.8 of using a backslash as a line
|
|||
continuation marker within double-quoted strings, and an ellipsis
|
||||
everywhere else.
|
||||
|
||||
** Repeat
|
||||
|
||||
+++
|
||||
*** New transient mode 'repeat-mode' to allow shorter key sequences.
|
||||
You can type 'C-x u u' instead of 'C-x u C-x u' to undo many changes,
|
||||
'C-x o o' instead of 'C-x o C-x o' to switch several windows,
|
||||
'C-x { { } } ^ ^ v v' to resize the selected window interactively,
|
||||
'M-g n n p p' to navigate next-error matches. Any other key exits
|
||||
transient mode and then is executed normally. 'repeat-exit-key'
|
||||
defines an additional key to exit mode like 'isearch-exit' (RET).
|
||||
|
||||
|
||||
* New Modes and Packages in Emacs 28.1
|
||||
|
||||
|
|
|
@ -950,6 +950,12 @@ if `inhibit-field-text-motion' is non-nil."
|
|||
;; 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 key sequences `C-x u u'. 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)
|
||||
|
@ -1036,6 +1042,17 @@ if `inhibit-field-text-motion' is non-nil."
|
|||
|
||||
(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)
|
||||
|
|
|
@ -329,6 +329,77 @@ recently executed command not bound to an input event\"."
|
|||
|
||||
;;;;; ************************* EMACS CONTROL ************************* ;;;;;
|
||||
|
||||
|
||||
;; And now for something completely different.
|
||||
|
||||
;;; repeat-mode
|
||||
|
||||
(defcustom repeat-exit-key nil
|
||||
"Key that stops the modal repeating of keys in sequence.
|
||||
For example, you can set it to <return> like `isearch-exit'."
|
||||
:type '(choice (const :tag "No special key to exit repeating sequence" nil)
|
||||
(key-sequence :tag "Key that exits repeating 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)
|
||||
(let* ((keymaps nil)
|
||||
(commands (all-completions
|
||||
"" obarray (lambda (s)
|
||||
(and (commandp s)
|
||||
(get s 'repeat-map)
|
||||
(push (get s 'repeat-map) keymaps))))))
|
||||
(message "Repeat mode is enabled for %d commands and %d keymaps"
|
||||
(length commands)
|
||||
(length (delete-dups keymaps))))))
|
||||
|
||||
(defun repeat-post-hook ()
|
||||
"Function run after commands to set transient keymap for repeatable keys."
|
||||
(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))
|
||||
keys mess)
|
||||
(map-keymap (lambda (key _) (push key keys)) 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 (or (memq last-command-event keys)
|
||||
(memq this-original-command '(universal-argument
|
||||
universal-argument-more
|
||||
digit-argument
|
||||
negative-argument)))
|
||||
;; Messaging
|
||||
(setq 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))
|
||||
"")))
|
||||
(if (current-message)
|
||||
(message "%s [%s]" (current-message) mess)
|
||||
(message mess))
|
||||
|
||||
;; Adding an exit key
|
||||
(when repeat-exit-key
|
||||
(define-key map repeat-exit-key 'ignore))
|
||||
|
||||
(set-transient-map map)))))))
|
||||
|
||||
(provide 'repeat)
|
||||
|
||||
;;; repeat.el ends here
|
||||
|
|
|
@ -10252,6 +10252,28 @@ displaying that processes's buffer."
|
|||
(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
|
||||
|
|
Loading…
Add table
Reference in a new issue