[it would be nice if someone would point out the "proper" place for this info. i was thinking somewhere on the emacswiki, but i couldn't figure out where.]
[i suck at speling]
emacs is a very large program, i've been using it as a mail reader, shell, note pad and ide for the past 6 years and i'm still learning new things. for those of you who've never really sat down and looked at emacs' lisp editing functions, here's a guide to what i do.
0a - do not program with western european keyboards layouts, accented chars are used very rarely in code, while puncuation chars are far more common.
0b - learn to touch type.
0c - don't spend 1500 EUR (or more) for a computer and then skimp on the keyboard.
1 - in just about every programming language i've ever used (C, Java, perl, bash and lisp), and in normal prose, paranthesis occur for more often that the square bracket chars. so the first thing to do is to make typing the parenthesis easy:
(keyboard-translate ?( ?[) (keyboard-translate ?[ ?() (keyboard-translate ?) ?]) (keyboard-translate ?] ?))
This assumes that the [ and ] are easy to reach unshifted chars.
2 - learn to use structured editing. what the hell is structured editing? it's just a way of working which attempts, as much as is usefull, to keep the source code consistently valid. this means, among other things, that you inserting an open parenthesis should insert the closing one as well (idem for ").
here's my setup:
(defun se:move-past-close-and-just-one-space () "Move past next `)' and ensure just one space after it. If called repeatedly removes any leading white space and moves up the enclosing list.
Copyright (c) 2002--2003 Hannu Koivisto azure@iki.fi. All rights reserved. License: GPL." (interactive) (when (eq 'se:move-past-close-and-just-one-space last-command) (delete-horizontal-space t)) (up-list) (just-one-space) (setq this-command 'se:move-past-close-and-just-one-space))
(define-key slime-mode-map [(?()] 'insert-parentheses) (define-key slime-mode-map [(?))] 'se:move-past-close-and-just-one-space) (define-key slime-mode-map [(return)] 'newline-and-indent)
2b - so how do you insert a simple, stand alone, ( or ) char? i happen to have the = char directly below ) and the \ char just to the left of that, so here's what i use:
(define-key slime-mode-map [(control ?=)] (lambda () (interactive) (insert "("))) (define-key slime-mode-map [(control ?\)] (lambda () (interactive) (insert ")")))
chose something that makes sense to use and which requires at most one key press (though it will probably be modified). even with structured editing you'll still need to insert lone parenthesis every now and then.
2c - if you don't want to be so radical and change the meaning of ( and ) know that, in the default lisp mode, insert-parentheses is bound to M-( and M-) is bound to move-past-close-and-reindent.
3 - when editing lisp code you generally don't work on a line or character basis, but you work by moving around lists. usefull emacs functions:
transpose-sexps - this simply swaps the sexp before point with the sexp after point.
backward-sexp - mave to before the preceding sexp
forward-sexp - move after the following sexp
kill-sexp - kill the following sexp
backward-up-list - move point to the start of the enclosing list.
up-list - move forward out of the current enclosing list
down-list - move the just after the open paren of the next list
all of these functions take prefix args which specify how many sexps to move around. backward-up-list can take a negative arg which maves out of the enclosing parens but forwards, basically simulating up-list.
when editing lisp code you will use these the forward/backward/transpose-sexp functions far more often the the char versions, i'd suggest swapping them so that C-M-t (transpose-sexp) is C-t and C-t (transpose-char) is C-M-t:
(define-key slime-mode-map (kbd "C-t") 'transpose-sexps) (define-key slime-mode-map (kbd "C-M-t") 'transpose-chars) (define-key slime-mode-map (kbd "C-b") 'backward-sexp) (define-key slime-mode-map (kbd "C-M-b") 'backward-char) (define-key slime-mode-map (kbd "C-f") 'forward-sexp) (define-key slime-mode-map (kbd "C-M-f") 'forward-char)
on a dvorak keyboard the htn keys are located directly under the right hand, so i've gone ahead and put the forward functions on n, on the transpose ones on t and the backward ones on h.
4 - i often want to "wrap" a sexp with more code, when for example, i want to add a let binding to a part of code. fortunetly the insert-parentheses function when given a prefix argument will insert the open paren at point and the clasing paren after the following n sexps. so if we have the point before "(foo) (bar)" then simply typing M-2 ( will give us "((foo) (bar))" with the point directly after the first (newly inserted) paren.
5 - i often also decide to unwrap same part of code (if for example i've decided to remove a let and it's bindings around a particular form.
(defun mb:unwrap-next-sexp () "Convert (x ...) to ..." (interactive) (forward-sexp) (backward-delete-char 1) (backward-up-list) (delete-char 1) (kill-sexp) (lisp-indent-line))
6 - I am lucky enough to spend much of my time programming lisp, so i find these changes worth the effort it took to figure them out and get used to them. YMMV.