Xah Lee, 2007-12
This page gives you some tips about editing emacs lisp code in emacs. Most tips will also apply to editing other lisp language codes or code with many nested matching pairs. (This page presumes emacs version 22, released in mid 2007.)
Turn on the following modes: Syntax Highlighting, Active Region Highlighting, Paren Match Highlighting.
Turn on Syntax Highlighting will color your code, Active Region Highlighting will color currently selected region, Paren Match Highlighting will color the matching parenthesis your cursor is on.
You can turn these modes on by using the menu “Options”, then “Options‣Save Options”.
Turn on the CUA mode, under the menu “Options‣C-x/C-c/C-v Cut and Paste (CUA)”.
The CUA mode will make emacs behave more like modern applications:
Activating the menu “Options‣Paren Match Highlighting” is equivalent to typing “Alt+x show-paren-mode”.
The “show-paren-mode” has 2 options about highlighting parens:
By default, it does (1), but the (2) seems more useful. To make it highlight entire enclosed text, put this code in your “.emacs” file:
(setq show-paren-style 'expression)
Also, you can change the default background color for highlighting the paren. You can do so by typing “Alt-x customize-face” then “show-paren-match”. Then, move your cursor to the “Attributes” section, “Background” item, in the value section type “azure2” replacing the default “turquoise”. Then, click the button “Save for Future Sessions” at the top. This will save the lisp code in your emacs init file. For example, the following shows in my emacs init file:
(custom-set-faces ;; custom-set-faces was added by Custom. ;; If you edit it by hand, you could mess it up, so be careful. ;; Your init file should contain only one such instance. ;; If there is more than one, they won't work right. '(show-paren-match ((((class color) (background light)) (:background "azure2")))))
To see a list of available colors and their names, type “Alt-x list-colors-display”.
To evaluate a single lisp expression, move your cursor to the right of the last closing parenthesis, and type “Alt+x eval-last-sexp” (Ctrl+x Ctrl+e). Alternatively, there's “eval-region” and “eval-buffer”.
You can also evaluate a file without opening it, by “Alt-x load-file”.
Also, emacs has a interactive emacs lisp shell, “Alt+x ielm”.
To find the inline documentation of a function, type “Ctrl+h f” (describe-function), then type the function name. If the word the cursor is on is a valid elisp function, emacs will use that by default.
Once the function's inline doc string page comes up, you can jump to the function's location in source code by clicking on underlined file name (or move your cursor there and press Enter).
To find the documentation of a variable, type “Ctrl+h v” (describe-variable).
To search command names using a regex, type “Ctrl+h a” (apropos-command). Note that this will only search commands, not functions. (A “command” is a function with the “(interactive ...)” clause.) To search all function's name space, give the command a empty argument, like this: “Ctrl+u Ctrl+h a”.
For example, you want to do something with a file but you are new to elisp and don't know what function are available. You might start looking for it by “Ctrl+h a RET file” which will return all functions with “file” in their name.
To search all symbols space (function, commands, variables), type “Alt+x apropos”.
Note: all these commands are under the menu “Help‣Describe” or “Help‣Search Documentation”.
Usually a function's inline documentation is sufficient for knowing how to use the function, but sometimes you want to read about a function in the elisp manual, which often gives more detail and context.
To search for a function in the elisp manual, use “elisp-index-search”. For emacs manual, use “emacs-index-search”. Both of these commands are under the menu “Help”.
Alternatively, you can use google to seach a site of the elisp manual in html. See the Google search box at the bottom of GNU Emacs Lisp Reference Manual.
Lisp code with its nested parenthesis syntax represents a tree structure. Emacs has several commands that are very helpful in moving around nested syntax, analogous to navigating a tree. Here is a table showing their shortcuts, names, and purpose. (For historical reasons, lisp code units are sometimes called “sexp”, short for “S-EXPression” (the “S” denote “Symbolic”).)
| Shortcut | Command name | Purpose |
|---|---|---|
| Ctrl+Meta+← | backward-sexp | Move to previous sibling (move to the (beginning of) previous sexp unit) |
| Ctrl+Meta+→ | forward-sexp | Move to next sibling (move to the (end of) next sexp unit) |
| Ctrl+Meta+↑ | backward-up-list | Move to parent (move to the (beginning of) outer paren pair) |
| Ctrl+Meta+↓ | down-list | Move to first child (move into the (beginning of) first inner paren pair) |
Here is a lisp code layed out in a way to show its tree structure. You should try the above commands on it. It is very helpful to understand how sexp corresponds to a tree, and how the commands move the cursor exactly.
( defun
fold
"Applies (f x ele) recursively to the list li ..."
(f x li)
( let
(
(li2 li)
(ele)
(x2 x)
)
(while
(setq ele (pop li2))
(setq x2 (funcall f x2 ele))
)
x2
)
)
Place your cursor at the beginning of the left bracket. Now, try to move your cursor, by using only the tree-walking commands, to the “pop”, then move it to “let”, then “funcall”.
The commands “backward-sexp” and “forward-sexp” moves to the previous or next sibling of the sexp the current cursor is on. For example, if you have “(a (b) c d (e f))” and your cursor is on end paren of “(b)”, then, “forward-sexp” will move it to “c”, and do it again will move it to “d”, then end paren of “(e f)”. Occationally, you want to move to the next sibling that has a branch. For example, if you are at the end of “(b)” and you want to move it to next paren pair the “(e f)”, you can then use “backward-list” and “forward-list”.
You can use the command “mark-sexp” (Ctrl+Meta+Space) to select a complete sexp. However, your cursor should be at the beginning of the unit. To select a complete sexp, type “Ctrl+Alt+↑” then “Ctrl+Alt+Space”.
These commands's default shortcuts are difficult to press. You can rebind them like this:
The default shortcut for tree-walking commands involves holding down both Meta and Control, which is inconvenient. You can rebind them with just Meta.
(global-set-key (kbd "M-<up>") 'backward-up-list) (global-set-key (kbd "M-<down>") 'down-list) (global-set-key (kbd "M-<left>") 'backward-sexp) (global-set-key (kbd "M-<right>") 'forward-sexp)
The above binding will make “Meta+‹arrow›” for walking the sexp tree.
On a PC keyboard, the matching pairs “(){}[]” are in locations difficult to type. It is convenient to move them under the home row, and also to type them always in pairs. Here's the code you can use for that:
(global-set-key (kbd "H-j") (lambda () (interactive) (insert "{}") (backward-char 1))) (global-set-key (kbd "H-k") (lambda () (interactive) (insert "()") (backward-char 1))) (global-set-key (kbd "H-l") (lambda () (interactive) (insert "[]") (backward-char 1)))
The “H” in the above code indicates the Hyper modifier key. You can make your Mac's Option key as Hyper or your PC's Windows key. Here's the code:
(setq w32-pass-lwindow-to-system nil
w32-lwindow-modifier 'hyper) ;; Left Windows key
(setq mac-option-modifier 'hyper)
Emacs default cursor movement keys (C-p, C-n, C-b, C-f) are inconvenient to press. (See Why Emacs's Keyboard Shortcuts Are Painful) You can rebind the cursor movement keys under the home row with “Alt” down. Here's the code:
(global-set-key (kbd "M-j") 'backward-char) ; was indent-new-comment-line (global-set-key (kbd "M-l") 'forward-char) ; was downcase-word (global-set-key (kbd "M-i") 'previous-line) ; was tab-to-tab-stop (global-set-key (kbd "M-k") 'next-line) ; was kill-sentence (global-set-key (kbd "M-SPC") 'set-mark-command) ; was just-one-space
For a more radical ergonomic shortcut set, see: A Ergonomic Keyboard Shortcut Layout.
Related essays:
Page created: 2007-12. © 2007 by Xah Lee.