Emacs key bindings, Paredit and saving macros

The other day I discovered the peepcode screencast Meet Emacs and although video is not really the ideal way for me to learn, and especially not something like Emacs, it managed to finally sell me and make me get my ass off the couch.


Don’t worry though, you get at full transcript which has been one of the most important documents for me in getting to where I am now.

Installing emacs is as easy as apt-get install, make sure you get version 23 (or better). After that I downloaded the starter kit. The starter kit comes with a package manager (M-x package-list-packages) where you can download stuff, for instance the clojure mode and paredit. I had problems with curly bracket after doing that though. In the end I ended up putting both clojure-mode and version 21 of paredit in ~/emacs.d/henrik. That is also the folder where I put the major mode for PicoLisp.

My first priority was get my head around how to work with s-expressions, courtesy of paredit. Below are some key combinations I’ve found useful so far (many of them are general and not associated with paredit).

1.) C-M-k -> [ -> C-y => Kill (cut) the preceding expression, write a [ to get [] and then paste the expression into it.
2.) M-UP => (let |(some expression)) ->(some expression)
3.) C-M-@ => Mark the preceding expression.
4.) C-M-q => Re-indent preceding expression.
5.) C-M-\ => Re-indent selection, great in combination with C-M-@
6.) C-SPC to start marking, C-g to stop.
7.) C-_ to undo.
8.) C-x C-f => Opens up the find file buffer.
9.) C-h k -> key-combo to see what function key-combo is mapped to.
10.) C-x o to switch between frames.
11.) C-x 1 to close all but the current frame.
12.) Start recording macro with f3 and stop with f4. Repeat the just saved macro 9 times with M-9 C-x e.
13.) C-x C-k n => Give a command name to the latest recorded macro.
14.) M-w => Copy selected text. C-w will cut. And paste with C-y.
15.) C-x C-b to see the buffer switcher and C-x k to kill a buffer.
16.) C-x C-s to save current buffer to file.
17.) C-M-d and C-M-u, to move down one sexpr and up one sexpr.
18.) C-M-t will transpose a sexpr.
19.) C-x 0 will close the current window/frame.
20.) C-u C-l center text vertically.
21.) C-a move to beginning of line.
22.) C-k yank current line.
23.) C-x h select the whole buffer.
24.) C-M b and C-M f to move to the beginning and end of the s-expr.
25.) M-x comment-region (I’ve set it to C-c c) comments the selected region and M-x uncomment-region (I’ve set it to C-c C-u c) uncomments the selected region (perfect for languages like PicoLisp, Clojure and Ruby).
26.) C-right arrow and C-left arrow to slurp/barf the next s-expr.
27.) C-q ; to for instance insert a semi-colon without also triggering the automatic generation of a newline.
28.) M-% to search and replace in current file.

The above takes care of most of what I want my Lisp editor to do, some of the combinations are too crazy to complete on my Swedish keyboard though so they needed to be remapped, like this:

(global-set-key (kbd "C-M-m") 'mark-sexp)

I put the above in a file called henrik.el in the emacs.d/henrik folder. The starter kit will load it automatically for us, just like the other files we’ve already put there.

There was however two more things I wanted to have, and that is the ability to wrap stuff in [] and {} too, not just () with M-(. But how to do this without editing paredit.el or spending days learning elisp? As you might have inferred by now; the answer is above.

By doing #1, while recording it as a macro #12 and then naming the macro #13 I could finally do the following:

M-x insert-kbd-macro RET macroname RET

The result was some elisp in my current buffer that I could then put in henrik.el which looks like this at the moment:

(fset 'sqbracket-wrap
   (lambda (&optional arg) "Keyboard macro." (interactive "p") (kmacro-exec-ring-item (quote ("\213[" 0 "%d")) arg)))
   
(fset 'curlybrace-wrap
   (lambda (&optional arg) "Keyboard macro." (interactive "p") (kmacro-exec-ring-item (quote ("\213{" 0 "%d")) arg)))

(global-set-key (kbd "C-s") 'save-buffer)
(global-set-key (kbd "C-z") 'undo)
(global-set-key (kbd "C-M-m") 'mark-sexp)
(global-set-key (kbd "M-[") 'sqbracket-wrap)
(global-set-key (kbd "M-{") 'curlybrace-wrap)
(global-set-key [f1] 'menu-bar-mode)

(defun lisp-enable-paredit-hook () (paredit-mode 1))
(add-hook 'picolisp-mode-hook 'lisp-enable-paredit-hook)

Note the stuff at the end there, these are two lines I ripped from clojure-mode.el to make paredit work with PicoLisp. The paredit minor mode needs to be hooked to the PicoLisp major mode.

Note that M-{ is per default already mapped to jump back one paragraph or something like that but I felt that that is something I won’t have any use for anyway. In any case the key binding could be made to work only in Clojure files, something I might change to in the future when I learn how to do that.

I have the following in my config too:

(global-set-key (kbd "C-c C-s") 'find-grep-dired)

It will allow me a recursive search in all files/folders for a certain expression/word, the result is a buffer with the matching files. In that buffer I can choose to open any given file or replace the word, more info here.

Other useful links:

Marking objects
Expressions and balanced parentheses
Paredit Cheatsheet
Editing lisp code with Emacs
Being productive with Emacs
Keyboard macro tricks
Save keyboard macro
Emacs hooks

Javascript setup:
1.) Install js2-mode.
2.) Install Yasnippet.
3.) Install Autopair.

Javascript keys:
C-j will return and automatically indent.

Related Posts

Tags: , , , , , ,