Search This Blog

Wednesday, April 6, 2011

Favourite keys for EMACS and SLIME

I made this post about two years ago. It's been really useful to me, and over the years I've added more commands. These are all the things that make emacs a joy and a horror for clojure editing for me.

Emacs is weird. I often hate it for how much it distracts me from what I'm actually trying to do. And yet when I try to use any other editor, I find myself missing emacs features so much that I end up going back to it. And the more you learn about it, the more addicted you get.

I think that there are fundamental usability mistakes in emacs, mostly to do with its habit of rearranging your windows. It was a great relief when I found out that you can store the window arrangement in a register, and then create a key that says 'put it all back! (you bastard)'. I dream of an editor as powerful as emacs but with a sanely designed UI that obeys modern conventions.

In a very real sense, an editor that is to emacs as clojure is to common lisp. What would be wonderful is if it lived in clojure's standard library like idle does for python.

On the other hand, having got the hang of emacs for clojure editing, it very rarely distracts me these days, and in that mode it's a pure joy. I wouldn't use any other tool. It mainly drives me up the wall now when I'm trying to use it to program in some other language.

(Latest: It was an even greater relief when I found winner-mode, which gives you a key for 'put them back the way they were just now, you stupid bastard'. In fact it gives you an undo history.  I've been using that for a while now, and it's great. 

I do wonder if the very fact that you can eventually hack the damned thing around so much that it stops being annoying is what has prevented people from starting the programmable editor project again from scratch but starting with something a bit more modern. ) 

the Editor for Middle Aged Computer Scientists

Is a very good way of editing Clojure, once you have slime and swank installed.

However, the key combinations don't stay in the brain very well if you don't use it all the time, so I thought I'd write down my favourite keys for Clojure editing whilst I'm using it every day, to serve as a cheat sheet for others, and for me in a few months time.

General Editing Keys

C-h m
describe the mode you're in

Incomprehensible undo

C-w    cut
M-w   copy
C-y     paste
M-y    paste the next most recent thing instead

C-x 0      kill this window
C-x 1      make this window the only window

C-x 2
C-x 3  split the window (vertically and horizontally)

C-x o         go to other window

M-g M-g    go to a particular line by number

C-x h         mark whole buffer

M-q           reformat paragraph. good for long comments

M-<           beginning
M->           and end of file

C-x C-+      adjust the font size (nice repeating behaviour, try C-x C-+ C-+)
C-x C- -

There's a nice list of useful keys at

And this is a nice guide

Keyboard Macros

C-x (          start recording
C-x )          stop

C-x e                      execute (then e to reexecute immediately)
C-u 10 C-x e          execute 10 times

C-x C-k C-p   move backwards
C-x C-k C-n   and forwards in the macro ring

Also see:


C-s forward and reverse incremental search

Afterwards RET drops you in the buffer, then C-x C-x should get you back because mark was set at the start of the search!

Slimey stuff

M-x slime                         start slime and a clojure instance
M-x slime-connect           start slime, connect to a running swank server

<F12> r   find the slime REP
<F12> j    find the clojure buffers
(well, that's what it means once you've made this hack in your .emacs file)

;;bind the slime selector to f12 and add a method for finding clojure buffers
(define-key global-map (kbd "<f12>") 'slime-selector)
(def-slime-selector-method ?j
  "most recently visited clojure-mode buffer."
  (slime-recently-visited-buffer 'clojure-mode))

Completion of Symbols

C-c TAB slime-complete-symbol

Switching Namespace
C-c M-p

At the REPL

M-p M-n   previous and next in history

C-x C-o     flush the last output
C-x M-o    flush the whole REPL buffer

Lisp editing and evaluating keys 

Note that in Gnome, Ctrl-Alt-D is 'show desktop', Ctrl-Alt-L is 'lock', and so on.
I turn all those off so that I can edit LISP code easily.
Use System/Preferences/Keyboard Shortcuts)

C-M-x     evaluate this top-level expression

C-x C-e  evaluate the expression behind the cursor

C-u C-x C-e evaluate the expression and paste the result into the buffer!

C-c C-k save compile and load this buffer

go to the definition of the expression under the cursor
come back from it

C-c C-d C-d
describe symbol under cursor

kill by s-expression

mark this top-level s-expression

mark next s-expression

(these last three repeat nicely. C-M-h C-M-h marks the next two top-level expressions)

reindent the s-expression

transpose s-expressions (weirdly useful)
repeated presses move an s-expression along inside a larger one.

beginning and end of top level s-expressions (defn ....)

backwards and forwards by list, previous and next s-expression
(the difference is subtle and not terribly important)

up and down list nest levels

Desktops and Windows

a desktop is a list of buffers, places in buffers, etc.

M-: (desktop-read "~/data/dir") will read a desktop file from an arbitrary place
M-x desktop-save will put one down

window arrangements (the layout of the screen) can be saved in registers

C-x  rfa    store window layout ( in register a , you can use other registers too)
C-x  rja    restore it

Other commands

M-x htmlize-file is great for saving files with their syntax highlighting in html.

M-x kill-rectangle, yank-rectangle and string-rectangle

Not an emacs command, but I have Alt-F11 bound to full-screen windows in GNOME.

A useful keyboard macro

In clojure-mode, trying to make a keyboard macro to paste results into the buffer
always seems to go horribly wrong. But this particular sequence works to write the result of an expression into the buffer above the expression itself. Place the cursor at the start of the expression.

If you do it by hand, the result ends up under the expression. If you record it and play it back, the result is over. No idea why, but this is a lot less haywire than every other time I've tried to do this.

M-C-f ;; forward-sexp
C-u C-x C-e ;; slime-eval-last-expression
M-C-b ;; backward-sexp
RET         ;; reindent-then-newline-and-indent
<up> ;; previous-line


C-x r m  make bookmark
C-x r b   jump to bookmark