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.
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-\?")))
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.
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)))
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)
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)