[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.
i would also suggest checking out this: (the se:move-past-close-and-just-one-space function was taken from here)
http://dsl-tregw1cbe.dial.inet.fi/~azure/suur-sexp.el
On 2004-07-18, Marco Baringer mb@bese.it wrote:
i would also suggest checking out this: (the se:move-past-close-and-just-one-space function was taken from here)
Yesterday, I took that function and created my own () bindings that seem to DTRT rather often:
http://boinkor.net/lisp/balanced-parens.el
What this code does is:
* bind ( to insert ( in comments and strings; when in code, insert balanced parens * bind ) to insert a closing paren in comments and strings; when in code, move past the closing paren and: * reindent, if we're at the top level or in a place that indents by 2 spaces (incredibly hacky, that) or * insert a space
That heuristic seems to work surprisingly well for me, so far. Perhaps fellow slimers will like it as well.
Happy hacking,
Marco Baringer mb@bese.it writes:
[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
CLiki?
Paolo
Great idea Marco.
Here are my highly opinionated added comments :-)
Marco Baringer mb@bese.it writes:
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 ").
Yes. A good start is to learn M-(, then C-M-{f,b}, then C-M-{u,d}, C-M-t, etc. Takes a while to learn them all but it's not so bad if you start using them one at a time.
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 ")")))
You could also use `C-q (' to insert a "(".
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:
I use the standard bindings for these myself. But yes, it's good to learn all the sexp-based editing commands, and they're pretty easy to pick up one at a time, e.g. starting with C-M-{a,b}, then C-M-{d,u}, then C-M-k, etc.
My own highly opinionated additions:
Standard Emacs commands: Learn to use C-{n,p,f,b,a,e} instead of arrow keys. Use C-m for return, C-h for backspace (Help is moved to Hyper-h), C-i for tab, and so on. They are easier to reach.
Keywiz: Use keywiz.el (http://www.ifa.au.dk/~harder/keywiz.el) to learn new Emacs commands. Keywiz is a game that shows you the name & docstring of a command and challenges you to press the corresponding key sequence. /Highly/ educational.
(Someone should hack keywiz to work on one keymap at a time.)
Keyboard: Use the Alt key for Meta, not Escape. Turn Capslock into Control. Convert some key into a Hyper modifier (right-shift for me). The xkeycaps program takes care of this.
Bindings: Add lots of convenient bindings on Hyper-<char> and C-c <unshifted-char>. Examples: pop global mark ring (aka `(set-mark-command t)'), slime-selector, put other-window on H-o.
Should also bind short Hyper-prefixed window manager keys for maximize-window-{fully,horizontally,vertically}, close window, focus window to <left|right|up|down>. Use a grid of enough virtual desktops that you don't need to have any overlapping windows. This is easy in Sawfish at least.
-Luke