reddit / emacs

Nested/conditional keybindings to navigate in text

bartqk · 2022-09-14 13:49
We all use "C-f" to move letter forward, and probably "Meta+f" to move word forward. I don't like "M-f" as I don't find it ergonomic enough, so I'm sticking to "C-S-f" (ctrl+shift+f). Which isn't perfect too (doesn't even work in my terminal, only in GUI Emacs), but at least I use two pinkies and then I press "f" to move word forward. But... what I'd really like is to press "Ctrl+f", then release "f" and \*then\* press 'w' to move word forward and be able to press "w" as many times I want until I release "Ctrl". Is it possible in emacs? Does it have a name already?
deaddyfreddy · 2022-09-14 14:18
There's https://github.com/abo-abo/hydra but to be fair, I'd try an alternative approach and jump to the exact place you need https://github.com/abo-abo/avy
bartqk · 2022-09-14 14:25
Thank you, this helps!
eleven_cupfuls · 2022-09-14 17:00
I agree with the suggestion to check out avy. If you're on at least Emacs 28 you can take advantage of the new `repeat-mode`/`repeat-map` functionality, something like this: (defvar bk/text-movement-map (let ((map (make-sparse-keymap))) (define-key map (kbd "C-f") #'forward-char) (put 'forward-char 'repeat-map map) (define-key map (kbd "C-w") #'forward-word) (put 'forward-word 'repeat-map map) ;; Other movement commands as desired map)) (global-set-key (kbd "C-f") bk/text-movement-map) This makes the custom keymap active when you press `C-f`; then each command within the map keeps the map active for repeating any of the same commands. If you want `C-f` to do `forward-char` right away but still allow repeats, don't do the `global-set-key` rebind: just set the `repeat-map` properties. (Side note, keep in mind that `C-w` is the default global binding for `kill-region` -- might be a bit confusing.)
akirakom · 2022-09-14 18:36
https://karthinks.com/software/it-bears-repeating/ is a comprehensive survey on transient maps.
bartqk · 2022-09-14 20:05
Thx. Actually there is an extra requirement: I want the same behavior for `backward-word/char`. And I have `backward-char` bound to `C-d`, which is close to `C-f`. So while still having control pressed, I want to press either `d` of `f` and each `d` or `f` should change behavior of future `w` keypresses. And yeah, I know `C-w` is for kill region, what I can to is I can release all the keys and then immediately just press `C-w` to kill. [Update]: actually I don't have even to use `C-w`, it can be for example `C-s`, because I will not want to save during text manipulation, but `C-w` can be useful indeed.
bartqk · 2022-09-14 20:40
Checking, thx!
bartqk · 2022-09-14 21:03
Other solution I'd be happy with is to replace \`C-S-f\` with \`C-;-f\`. \`;\` char is in the homerow and it's ergonomic to press with the right pinky. \`C-\[-f\` would do as well.
arthurno1 · 2022-09-14 22:33
Maybe [keychords](https://www.emacswiki.org/emacs/KeyChord) are something for you? Already suggested avy is good too.
eleven_cupfuls · 2022-09-14 23:01
Okay, well, you can add whatever other commands you want to the map in the same pattern. But with the toggle idea you're talking about defining your own modal context. So, time to start hacking 😉 You can write custom commands that wrap a little bit of logic around the standard movement commands. Or another option would be to look at [ryo-modal](https://github.com/Kungsgeten/ryo-modal) or [meow](https://github.com/meow-edit/meow).