(or emacs irrelevant)

Zoom in / out with style

I don't usually zoom a lot, typically I do it to size up other people's functions. Then, I zoom-out a couple times in a row until the function fits on the screen. Sometimes, I overshoot the zoom-out, and I have to zoom-in instead. I have text-scale-increase bound to <f2> g and text-scale-decrease bound to <f2> l.

Below, I'll demonstrate how to call those two commands interchangeably with e.g. <f2> g g g l g g l, i.e. omitting the <f2> prefix.

Define repeatable command

(defun def-rep-command (alist)
  "Return a lambda that calls the first function of ALIST.
It sets the transient map to all functions of ALIST."
  (lexical-let ((keymap (make-sparse-keymap))
                (func (cdar alist)))
    (mapc (lambda (x)
            (define-key keymap (car x) (cdr x)))
          alist)
    (lambda (arg)
      (interactive "p")
      (funcall func arg)
      (set-transient-map keymap t))))

This is a pretty simple function that takes an alist of keys and commands, and returns a lambda that calls the first command and sets the transient map to call the first and other commands. The way the transient map works, it takes priority over almost all maps, but disappears as soon as you press something that doesn't belong to it.

The zoom-in / zoom-out use case

(global-set-key (kbd "<f2> g")
                (def-rep-command
                    '(("g" . text-scale-increase)
                      ("l" . text-scale-decrease))))
(global-set-key (kbd "<f2> l")
                (def-rep-command
                    '(("l" . text-scale-decrease)
                      ("g" . text-scale-increase))))

And this is it. A nice thing about this setup is that I don't have to think about the zoom state and quitting it: I'll quit it automatically as soon as I press anything other than l or g. Moreover, the command that exited the zoom state will be executed as usual.