## Upping my Emacs navigation game

| categories: | tags:

I have been trying to up my navigation game in Emacs, by which I mean I want to get my cursor where I want it with a minimal number of keystrokes, and preferrably no mouse actions. There are lots of little and big navigations I do a lot:

1. forward/backward by a character
2. forward/backward by a word/subword
3. forward/backward by a sentence
4. forward/backward by a line
5. to the beginning and end of a line
6. to the beginning and end of a sentence
7. to the beginning and end of a paragraph
8. to the beginning and end of a page
9. to the beginning and end of a buffer
10. scrolling up/down
11. into another window
12. back and forth to buffers

Occasionally, I want to save a location so I can easily get back to it. Not all of these are strictly speaking navigation in the usual sense, but they are things I do often enough. There are Emacs commands for all these, and keyboard shortcuts for many of them, but I don't use them often, and as a result I don't remember them either.

Here I develop a hydra that will provide these features. Hydra is a super amazing, menu prompting system that provides hints to remind you of what can be done, and to access it from a character. It is possible to pass numeric and universal arguments to the commands by typing -, a number, or C-u before pressing the character.

I want some commands to be repeatable, which we get with a "red" hydra, and some commands to exit on running, which we get with a "blue" head. So, here is an over-the-top hydra for navigation.

(defhydra hydra-navigate (:color red
:hint nil)
"
_f_: forward-char       _w_: forward-word       _n_: next-line
_b_: backward-char      _W_: backward-word      _p_: previous-line
^ ^                     _o_: subword-right      _,_: beginning-of-line
^ ^                     _O_: subword-left       _._: end-of-line

_s_: forward sentence   _a_: forward paragraph  _g_: forward page
_S_: backward sentence  _A_: backward paragraph _G_: backward page

_h_: helm mini _B_: buffer list _i_: window
_<left>_: previous buffer   _<right>_: next buffer
_<up>_: scroll-up           _<down>_: scroll-down

_[_: backward-sexp _]_: forward-sexp
_<_ beginning of buffer _>_ end of buffer _m_: set mark _/_: jump to mark
"
("f" forward-char)
("b" backward-char)
("w" forward-word)
("W" backward-word)
("n" next-line)
("p" previous-line)
("o" subword-right)
("O" subword-left)
("s" forward-sentence)
("S" backward-sentence)
("a" forward-paragraph)
("A" backward-paragraph)
("g" forward-page)
("G" backward-page)
("<right>" next-buffer)
("<left>" previous-buffer)
("h" helm-mini :color blue)
("i" ace-window :color blue)
("m" org-mark-ring-push)
("/" org-mark-ring-goto :color blue)
("B" helm-buffers-list)
("<up>" scroll-up)
("<down>" scroll-down)
("<" beginning-of-buffer)
(">" end-of-buffer)
("." end-of-line)
("[" backward-sexp)
("]" forward-sexp)
("," beginning-of-line)
("q" nil "quit" :color blue))

(global-set-key (kbd "s-n") 'hydra-navigate/body)

hydra-navigate/body


I basically like it. The menu is a little on the large side, but it makes for easy modal navigation in a buffer, to other windows, and other buffers. On the whole for moderate cursor movements, this results in basically equal keystrokes. For example, to move 3 characters forward, we have C-f C-f C-f or C-u 3 C-f, or s-n 3 f. The advantage (I think) is a single interface to all these navigation commands with hints on what to do.

There is still another level of navigation, which is related to navigation by searching. That is a whole different level of navigation I will work on another day!