Skip to content

Instantly share code, notes, and snippets.

@Nondv
Last active May 9, 2024 19:20
Show Gist options
  • Save Nondv/ee88a926427d1d3e5f54b1f6963ef3ef to your computer and use it in GitHub Desktop.
Save Nondv/ee88a926427d1d3e5f54b1f6963ef3ef to your computer and use it in GitHub Desktop.
My custom navigation minor mode for emacs (to move around the code file without holding control down)
;; I often find myself simply jumping around the code to read it.
;; However, it's a bit daunting to keep the Ctrl pressed.
;; I don't like vim but I'd like some simple one button navigation
;;
;; For a while, I used god-mode for that but its purpose is quite different
;; which sometimes caused some weird behaviour when I had it enabled.
;; Plus, some shortcuts simply aren't improved by this (e.g. C-M-f).
;; So I decided to write my own minor mode specifically for navigation *I*
;; need.
;;
;; I don't imagine this is 100% ergonomic and complete but I think people may
;; find it useful if they want to write their own simple mode.
(defvar my/navigation-mode nil)
(add-to-list 'minor-mode-alist '(my/navigation-mode " my/Nav"))
(deftheme my/navigation-mode/theme "Indicates that my/navigation-mode is on")
(custom-theme-set-faces 'my/navigation-mode/theme
'(cursor ((t (:background "#ff0000")))))
(defvar my/navigation-mode/keymap
`(keymap
(t . ,#'my/navigation-mode/fallback-key-handler)))
(keymap-set my/navigation-mode/keymap "e" #'move-end-of-line)
(keymap-set my/navigation-mode/keymap "M-e" #'sp-end-of-sexp)
(keymap-set my/navigation-mode/keymap "a" #'move-beginning-of-line)
(keymap-set my/navigation-mode/keymap "M-a" #'sp-beginning-of-sexp)
;; Originally, I wanted to use WASD for navigation but I noticed that
;; it's hard to break my muscle memory so I went back to FBPNAE
(keymap-set my/navigation-mode/keymap "b" #'backward-char)
(keymap-set my/navigation-mode/keymap "C-b" #'backward-word)
(keymap-set my/navigation-mode/keymap "M-b" #'backward-sexp)
(keymap-set my/navigation-mode/keymap "f" #'forward-char)
(keymap-set my/navigation-mode/keymap "C-f" #'forward-word)
(keymap-set my/navigation-mode/keymap "M-f" #'forward-sexp)
(keymap-set my/navigation-mode/keymap "p" #'previous-line)
(keymap-set my/navigation-mode/keymap "M-p" #'scroll-down-command)
(keymap-set my/navigation-mode/keymap "n" #'next-line)
(keymap-set my/navigation-mode/keymap "M-n" #'scroll-up-command)
(keymap-set my/navigation-mode/keymap "v" #'scroll-up-command)
(keymap-set my/navigation-mode/keymap "M-v" #'scroll-down-command)
(keymap-set my/navigation-mode/keymap "SPC" #'my/navigation-mode)
(keymap-set my/navigation-mode/keymap "<escape>" #'my/navigation-mode)
(defun my/navigation-mode/fallback-key-handler ()
(interactive)
(beep)
(message "[my/navigation-mode] key not recognised. To disable the mode, press SPC"))
(defun my/navigation-mode (&optional arg)
(interactive '(toggle))
(setf my/navigation-mode (if (eql arg 'toggle)
(not my/navigation-mode)
(> arg 0)))
;; The keymap is being added and removed every time the mode is toggled on/off
;; This is to make sure it stays at the head of the alist and takes precedence over
;; other modes (e.g. magit took precedence over god mode in my config)
(if my/navigation-mode
(progn
(add-to-list 'minor-mode-map-alist (cons 'my/navigation-mode my/navigation-mode/keymap))
(enable-theme 'my/navigation-mode/theme)
(message "my/navigation-mode on"))
(progn
(setq minor-mode-map-alist
(seq-filter (lambda (x) (not (eql (car x) 'my/navigation-mode)))
minor-mode-map-alist))
(disable-theme 'my/navigation-mode/theme)
(message "my/navigation-mode off"))))
(global-set-key (kbd "<escape>") #'my/navigation-mode)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment