💾 Archived View for idiomdrottning.org › on-top-of-emacs-god-mode captured on 2023-09-28 at 17:00:05. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-01-29)

-=-=-=-=-=-=-

On top of Emacs’ god-mode

I’ve been using god-mode for a few years. It’s an Emacs mode that’s sort of like if Control was held down all the time. The key sequence C-c C-s C-p becomes just csp and C-x n n becomes x nn. I’ve built some cruft of my own on top of it.

Single character editing

Let’s start with the unusualest stuff first:

(define-key god-local-mode-map (kbd "o") 'insert-one-character)

(defun insert-one-character (times)
  (interactive "p")
  (overwrite-mode 1)
  (dotimes (x times) (quoted-insert 1))
  (overwrite-mode 0))

C-q already existed, so if you want to insert one character you could already use q. The difference between q and o is how they deal with prefix arguments, where q will insert more of the same while o will listen that amount of times. If you want to insert three hyphens, 3q-. If you want to insert the word “and”, 3oand. Or 5o and if you want spaces.

This version deletes as many characters (to the right) as it inserts:

(define-key god-local-mode-map (kbd ">") 'overwrite-insert)

(defun overwrite-insert (times)
  (interactive "p")
  (delete-char times)
  (insert-one-character times))

Often enough I just wanna insert a space. This one does work like q, in that the prefix sets the number of spaces you get.

(define-key god-local-mode-map (kbd "O") 'spacer)

(defun spacer (times)  (interactive "p") (dotimes (x times) (insert " ")))

Then, for my-dumb-del, it’s just a way to make h work as a backspace in god-mode. I use F1 as a help key.

(define-key god-local-mode-map (kbd "h") 'my-dumb-del)

(defun my-dumb-del ()
  (interactive)
  (setq unread-command-events (listify-key-sequence "\C-\?")))

“Incarnation”: temporarily leave god-mode

Incarnate switches out of god-mode except that RET returns to god-mode (and then to insert a newline after, hit RET again. Use C-j to insert newlines without leaving the incarnation.)

Great when I just wanna insert just a handful of words, so I don’t need to toggle out of god-mode completely, but it’s more than I wanna bother to count so the prefix and o solution isn’t the best. I just hit i, type some words, then RET.

On a physical keyboard, just toggling in and out of god-mode is easy enough, but on the tablet’s touch screen, there aren’t that many freely accessible remappable keys, so this is a great way to work.

My god-mode cursor is a red box, my normal cursor is a black box, and my incarnate cursor is a black bar.

(define-key god-local-mode-map (kbd "i") 'incarnate)

(defun unincarnate ()
  (interactive)
  (incarnate-mode -1)
  (setq cursor-type 'box)
  (god-local-mode 1)
  (set-cursor-color "#b0381e"))

(defun incarnate ()
  (interactive)
  (when (bound-and-true-p god-local-mode)
    (god-local-mode 0)
    (unless (display-graphic-p)
      (set-cursor-color "black")
      (setq cursor-type 'bar)
      (incarnate-mode))))

(define-minor-mode incarnate-mode
  "As normal but toggle to God mode on RET"
  :lighter " God-Inc"
  :keymap '(("\r" . unincarnate)))

In addition to i, I also have many of my paredit commands also incarnate, and many that work regardless of whether I’m in god-mode or not, giving me sort of a very DWIMmy experience that works well for me on tablet.

Time based insertion

This is still pretty experimental, but it’s an alternative to incarnation where instead it turns off god-mode and turns it back on when the typing has been idle for a number of seconds (it can handle decinal seconds just fine). In the sample code here, it’s set to two seconds.

(defun type-something-quickly ()
  (interactive)
  (run-with-idle-timer 2 nil #'(lambda () (god-local-mode 1)))
  (god-local-mode -1))

Here’s a way to dispatch between those two methods based on whether you’re on graphic display or not (as a proxy for finding out whether you are on SSH).

(defun type-quickly-or-incarnate ()
  (interactive)
  (if (display-graphic-p)
      (type-something-quickly)
    (incarnate)))

Leaping and searching

Isearch with god-mode can be a bit sticky and I wanted a few extra ways to exit or abort (exit affirms the jump and takes you to what you found, while abort cancels the search).

(require 'god-mode-isearch)
(define-key isearch-mode-map (kbd "<escape>") 'god-mode-isearch-activate)
(define-key isearch-mode-map (kbd "=") 'isearch-exit)
(define-key isearch-mode-map (kbd "<f3>") 'isearch-abort)
(define-key god-mode-isearch-map (kbd "<escape>") 'god-mode-isearch-disable)
(define-key god-mode-isearch-map (kbd "m") 'isearch-exit)
(define-key god-mode-isearch-map (kbd "g") 'isearch-abort)
(define-key god-mode-isearch-map (kbd "h") 'isearch-delete-char)

I also have “leaping” (r and s in god-mode) as something different from full on isearch (C-r and C-s, that is to say, deliberately using control even though it’s god-mode).

This has been so awesome in practice and I use it all the time. Just being able to leap back to a recent character or handful of characters is great while if I’m doing a more tricky, remote, deliberate search I’ll hit control first. I haven’t been getting them confused since “leaping” feels more like a relation to stuff like forward-sentence, backward-sexp etc, a way to navigate locally, it doesn’t “feel like searching”, I dunno.

(global-set-key (kbd "C-r") 'isearch-backward)
(global-set-key (kbd "C-s") 'isearch-forward)
(define-key god-local-mode-map (kbd "r") 'leap-back)
(define-key god-local-mode-map (kbd "s") 'leap-forward)

(defun leap-skele (proc)
  (run-with-idle-timer
   .5 nil
   (lambda () (when (= 0 (length isearch-string)) (message ""))  (isearch-done)))
  (funcall proc))

(defun leap-back () (interactive) (leap-skele 'isearch-backward))
(defun leap-forward () (interactive) (leap-skele 'isearch-forward))

I’m only recently starting to experiment with more stuff that’s totally different with god-mode on or off. Having / for replace-regex has quickly become something I’ve gotten spoiled by.

(define-key god-local-mode-map (kbd "/") 'replace-regexp)

Settings

OK, that was it for the new and interesting things. Time for the settings I use.

Escape doesn’t work very well over SSH so I have a bunch of touch-screen–specific methods, along with F3 as a more reliable alternative.

(global-set-key (kbd "•") 'god-mode)
(global-set-key (kbd "Äź") 'god-mode)
(global-set-key (kbd "Č©") 'god-mode)
(global-set-key (kbd "<f3>") 'god-mode)

Since I use C-z so heavily (I have it set to toggle a shell buffer), I use comma for repeat instead:

(define-key god-local-mode-map (kbd ",") 'repeat)

(defun split-window-func-with-other-buffer (split-function)
  (lexical-let ((s-f split-function))
    (lambda ()
      (interactive)
      (funcall s-f)
      (set-window-buffer (next-window) (other-buffer)))))

(global-set-key (kbd "C-x C-1") 'delete-other-windows)
(global-set-key (kbd "C-x C-'") 'delete-other-windows)
(global-set-key (kbd "C-x '") 'delete-other-windows)
(global-set-key (kbd "C-x C-o") 'other-window)
(global-set-key (kbd "C-x C-2") (split-window-func-with-other-buffer 'split-window-vertically))
(global-set-key (kbd "C-x C-,") (split-window-func-with-other-buffer 'split-window-vertically))
(global-set-key (kbd "C-x ,") (split-window-func-with-other-buffer 'split-window-vertically))
(global-set-key (kbd "C-x C-3") (split-window-func-with-other-buffer 'split-window-horizontally))
(global-set-key (kbd "C-x C-.") (split-window-func-with-other-buffer 'split-window-horizontally))
(global-set-key (kbd "C-x .") (split-window-func-with-other-buffer 'split-window-horizontally))
(global-set-key (kbd "C-x 2") (split-window-func-with-other-buffer 'split-window-vertically))
(global-set-key (kbd "C-x 3") (split-window-func-with-other-buffer 'split-window-horizontally))
(global-set-key (kbd "C-x C-0") 'delete-window)

(add-to-list 'god-exempt-major-modes 'Buffer-Selection-Menu-mode)
(add-to-list 'god-exempt-major-modes 'notmuch-search-mode)
(add-to-list 'god-exempt-major-modes 'notmuch-show-mode)
(add-to-list 'god-exempt-major-modes 'Info-mode)

Love function keys:

(setq god-mode-enable-function-key-translation nil)