Repeating Navigation in Emacs
A few weeks ago I was getting somewhat annoyed while navigating with
a wild set of combinations of C-n
, C-n
, M-f
, M-f
and whatnot through an
org-document that I had been working on, and wondered why there isn't
a simpler way to do that. Something that could for example make the C
or M
stick of sorts.
This being Emacs, I was thinking there had to be a solution. I did some search but couldn't really find something that did just what I had been looking for (then again, I didn't know what to look for).
I ended up trying EVIL-Mode and God-Mode and even though the latter did work well for me (the former confused me too much) neither did what I really wanted to. Somehow switching to another mode only to navigate a little more efficient seemed overkill.
That being said, I did use God-Mode for a while, until I learned about the Repeat-Mode introduced in Emacs via Karthinks and with this found the solution!
I ended up with this code which does exactly what I wanted to: I
invoke the motion I want to use, say M-b
to move back a word and then
happily continue moving backwards pressing only b
.
Even though there is likely a much more elegant solution to write this code, it works and best of all, I did it myself (more or less that is :-) ).
Here's the snippet I came up with:
(repeat-mode t) (defvar svbck-nav-repeat-map (let ((map (make-sparse-keymap))) (define-key map (kbd "f") #'forward-char) (define-key map (kbd "b") #'backward-char) (define-key map (kbd "n") #'next-line) (define-key map (kbd "p") #'previous-line) (define-key map (kbd "a") #'backward-sentence) (define-key map (kbd "e") #'forward-sentence) map)) (dolist (cmd '(forward-char backward-char next-line previous-line backward-sentence forward-sentence)) (put cmd 'repeat-map 'svbck-nav-repeat-map)) (defvar svbck-word-repeat-map (let ((map (make-sparse-keymap))) (define-key map (kbd "f") #'forward-word) (define-key map (kbd "b") #'backward-word) map)) (dolist (cmd '(forward-word backward-word)) (put cmd 'repeat-map 'svbck-word-repeat-map)) (defvar svbck-org-sentence-repeat-map (let ((map (make-sparse-keymap))) (define-key map (kbd "a") #'org-backward-sentence) (define-key map (kbd "e") #'org-forward-sentence) map)) (dolist (cmd '(org-backward-sentence org-forward-sentence)) (put cmd 'repeat-map 'svbck-org-sentence-repeat-map))
I tried to combine this into one repeat-map
but that didn't work out
that well since some of the keys are the same, hence I did one for
each, then again it works this way.
Upadate 2022-12-10 11:15: In the meanwhile I figured out how to make the code a little bit more compact, but I'm sure it could be improved more.