Wednesday, October 25, 2006

Scroll bindings (Wednesday Emacs blogging)

Part of the Zen of Emacs is the fact that --- in contrast to merely mortal text editors or word processors --- you need not move your hands from the default typing position for common navigation tasks, like moving to the beginning of a line (C-a) or word (M-b).

Clearly, therefore, it is uncivilized to use arrow keys, or to move your hand to the mouse and hunt for that little arrow on your scroll bar, when you merely want to scroll up or down a couple of lines. Accordingly, the following elisp binds downwards and upwards scrolling to the M-n and M-p keystrokes respectively.

; Handy incremental scrolling keys
(define-key global-map "\M-n" (lambda () (interactive) (scroll-up 1)))
(define-key global-map "\M-p" (lambda () (interactive) (scroll-down 1)))

I chose M-n and M-p to be mnemonic "cognates" with C-n and C-p. Note that scroll-up is so named because it moves the document up, which makes the viewport appear to scroll down, and vice versa for scroll-down.

Nevertheless, it is sometimes convenient to do scrolling with your mouse --- e.g., if your hand's already there because you're switching focus among open windows. Recent Emacsen understand the scroll wheel, but some older versions do not. Fortunately, they can be taught, using the following recipe suitable for either (FSF) .emacs or (XEmacs) .xemacs/init.el:

; Mouse wheel: scroll up/down; control-wheel for pgup/pgdn.
(defun wheel-scroll-up   ()   (lambda () (interactive) (scroll-up 2)))
(defun wheel-scroll-down ()   (lambda () (interactive) (scroll-down 2)))
(defun wheel-scroll-pgup ()   (lambda () (interactive) (scroll-up 20)))
(defun wheel-scroll-pgdown () (lambda () (interactive) (scroll-down 20)))
(cond
 ((string-match "XEmacs" emacs-version)
  (progn
    (define-key global-map 'button5 (wheel-scroll-up))
    (define-key global-map 'button4 (wheel-scroll-down))
    (define-key global-map '(control button5) (wheel-scroll-pgup))
    (define-key global-map '(control button4) (wheel-scroll-pgdown))))
 (t ; FSF Emacs uses weird [bracket] keymap specifiers.
  (progn
    (define-key global-map [mouse-5] (wheel-scroll-up))
    (define-key global-map [mouse-4] (wheel-scroll-down))
    (define-key global-map [C-mouse-5] (wheel-scroll-pgup))
    (define-key global-map [C-mouse-4] (wheel-scroll-pgdown)))))

This recipe also binds C-mouse-4 and C-mouse-5 to page-down and page-up, for handy fast scrolling, which does not come standard even on recent Emacsen. It should be pretty obvious how to customize it to scroll more or fewer lines at a time.

No comments:

Post a Comment