From: Xah Lee
Subject: Tips For Editing Lisp Code With Emacs
Date: 
Message-ID: <4d8ff4b8-5abe-45cc-b42f-a21936775d82@b1g2000pra.googlegroups.com>
Tips For Editing Lisp Code With Emacs

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 is based on emacs version
22, release in 2007.)

(for HTML version with colors and links, see:
http://xahlee.org/emacs/emacs_editing_lisp.html
)

==========================================
SYNTAX HIGHLIGHTING SETUP

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 CUA Mode

Turn on the CUA mode, under the menu “Options‣C-x/C-c/C-v Cut and
Paste (CUA)”.
emacs basic options

The CUA mode will make emacs behave more like modern applications:

    * It will activate the shortcuts: “Ctrl+x” for cut, “Ctrl+c” for
copy, “Ctrl+v” for paste.
    * It will highlight when a region of a text is selected.
    * When text is selected, typing will over-ride it. Pressing delete
key will delete the region.
    * Text selection can be done by pressing any of the arrow key with
Shift key down.

----------------
Show Paren Mode

The “show-paren-mode” has 2 options about highlighting parens:

    * (1) Color the matching paren when the the cursor is on a paren.
    * (2) Color the entire enclosed expression when the the cursor is
on a paren.

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:

(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”.

==========================================
EVALUATING LISP EXPRESSIONS

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”.

==========================================
FUNCTION DOCUMENTATION LOOKUP

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”.

Note: all these commands are under the GUI Help menu.

----------------
Searching Elisp Manual

Usually a function's inline documentation is sufficient info for
knowing how to use 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 “Help” menu.

Alternatively, you can use google to seach a site of the elisp manual
in html. See GNU Emacs Lisp Reference Manual.

==========================================
NAVIGATING NESTED SYNTAX

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 are sometimes called “sexp”, short for “S-Expression”.)

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 children
(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 important that you
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
  )
)

----------------
Moving To Previous/Next Sibling That Has Children

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”.

----------------
Selecting A Sexp Unit

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. Use one of the tree-walking commands first.

These commands's default shortcuts are difficult to press. You can
rebind them like this:

(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)
(global-set-key (kbd "M-S-<left>") 'backward-list)
(global-set-key (kbd "M-S-<right>") 'forward-list)

The above binding will make “Meta+«arrow»” for walking the sexp tree.
The last two are “Meta+Shift”.

==========================================
TYPING CONVENIENCES

----------------
Typing Parenthesis By Pairs

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 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)

----------------
Arrows Keys Under Homerow

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:

;; make cursor movement keys under right hand's home-row.
(global-set-key [(meta j)] 'backward-char) ; was indent-new-comment-
line
(global-set-key [(meta l)] 'forward-char)  ; was downcase-word
(global-set-key [(meta i)] 'previous-line) ; was tab-to-tab-stop
(global-set-key [(meta k)] 'next-line) ; was kill-sentence

For a more radical ergonomic shortcut set, see: A Ergonomic Keyboard
Shortcut Layout.

  Xah
  ···@xahlee.org
∑ http://xahlee.org/