Lispy
Short and sweet LISP editing
Install / Use
/learn @abo-abo/LispyREADME
![License GPL 3][badge-license]
<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc/generate-toc again -->short and sweet LISP editing
Table of Contents
- Introduction
- Getting Started
- Operating on lists
- Operating on regions
- IDE-like features
- Demos
- [Demo 1: Practice generating code](#demo-1-practice-generating-codehttpabo-abogithubiolispydemo-1)
- [Demo 2: The substitution model for procedure application](#demo-2-the-substitution-model-for-procedure-applicationhttpabo-abogithubiolispydemo-2)
- [Demo 3: Down the rabbit hole](#demo-3-down-the-rabbit-holehttpabo-abogithubiolispydemo-3)
- [Demo 4: Project Euler p100 and Clojure](#demo-4-project-euler-p100-and-clojurehttpabo-abogithubiolispydemo-4)
- [Demo 5: ->>ification](#demo-5--ificationhttpabo-abogithubiolispydemo-5)
- [Demo 6: cond->if->cond](#demo-6-cond-if-condhttpabo-abogithubiolispydemo-6)
- Screencasts
Introduction
This package reimagines Paredit - a popular method to navigate and edit LISP code in Emacs.
The killer-feature are the short bindings:
| command | binding | binding | command
|:-----------------------------|:----------------:|:------------:|:------------------
|paredit-forward | <kbd>C-M-f</kbd> | <kbd>j</kbd> | lispy-down
|paredit-backward | <kbd>C-M-b</kbd> | <kbd>k</kbd> | lispy-up
|paredit-backward-up | <kbd>C-M-u</kbd> | <kbd>h</kbd> | lispy-left
|paredit-forward-up | <kbd>C-M-n</kbd> | <kbd>l</kbd> | lispy-right
|paredit-raise-sexp | <kbd>M-r</kbd> | <kbd>r</kbd> | lispy-raise
|paredit-convolute-sexp | <kbd>M-?</kbd> | <kbd>C</kbd> | lispy-convolute
|paredit-forward-slurp-sexp | <kbd>C-)</kbd> | <kbd>></kbd> | lispy-slurp
|paredit-forward-barf-sexp | <kbd>C-}</kbd> | <kbd><</kbd> | lispy-barf
|paredit-backward-slurp-sexp | <kbd>C-(</kbd> | <kbd>></kbd> | lispy-slurp
|paredit-backward-barf-sexp | <kbd>C-{</kbd> | <kbd><</kbd> | lispy-barf
Most of more than 100 interactive commands that lispy provides are
bound to <kbd>a</kbd>-<kbd>z</kbd> and <kbd>A</kbd>-<kbd>Z</kbd> in
lispy-mode. You can see the full command reference with many
examples here.
The price for these short bindings is that they are only active when:
- the point is before an open paren:
(,[or{ - the point is after a close paren:
),]or} - the region is active
The advantage of short bindings is that you are more likely to use them. As you use them more, you learn how to combine them, increasing your editing efficiency.
To further facilitate building complex commands from smaller commands,
lispy-mode binds digit-argument to <kbd>0</kbd>-<kbd>9</kbd>. For
example, you can mark the third element of the list with
<kbd>3m</kbd>. You can then mark third through fifth element (three
total) with <kbd>2></kbd> or <kbd>>></kbd>. You can then move the
selection to the last three elements of the list with <kbd>99j</kbd>.
If you are currently using Paredit, note that lispy-mode and
paredit-mode can actually coexist with very few conflicts, although
there would be some redundancy.
Relation to vi
The key binding method is influenced by vi, although this isn't modal editing per se.
Here's a quote from Wikipedia on how vi works, in case you don't know:
vi is a modal editor: it operates in either insert mode (where typed text becomes part of the document) or normal mode (where keystrokes are interpreted as commands that control the edit session). For example, typing i while in normal mode switches the editor to insert mode, but typing i again at this point places an "i" character in the document. From insert mode, pressing ESC switches the editor back to normal mode.
Here's an illustration of Emacs, vi and lispy bindings for inserting a char and calling a command:
| | insert "j" | forward-list |------------------|:--------------:|:-------------: |Emacs | <kbd>j</kbd> | <kbd>C-M-n</kbd> |vi in insert mode | <kbd>j</kbd> | impossible |vi in normal mode | impossible | <kbd>j</kbd> |lispy | <kbd>j</kbd> | <kbd>j</kbd>
Advantages/disadvantages:
- Emacs can both insert and call commands without switching modes (since it has none), but the command bindings are long
- vi has short command bindings, but you have to switch modes between inserting and calling commands
- lispy has short command bindings and doesn't need to switch modes
Of course it's not magic, lispy needs to have normal/insert mode to perform both functions with <kbd>j</kbd>. The difference from vi is that the mode is explicit instead of implicit - it's determined by the point position or the region state:
- you are in normal mode when the point is before/after paren or the region is active
- otherwise you are in insert mode
So people who generally like Emacs bindings (like me) can have the cake and eat it too (no dedicated insert mode + shorter key bindings). While people who like vi can still get an experience that's reasonably close to vi for LISP editing (since vi's line-based approach isn't very appropriate for LISP anyway).
But if you ask:
What if I want to insert when the point is before/after paren or the region is active?
The answer is that because of the LISP syntax you don't want to write this:
j(progn
(forward-char 1))k
Also, Emacs does nothing special by default when the region is active and you press a normal key, so new commands can be called in that situation.
Features
-
Basic navigation by-list and by-region:
- <kbd>h</kbd> moves left
- <kbd>j</kbd> moves down
- <kbd>k</kbd> moves up
- <kbd>l</kbd> moves right
- <kbd>f</kbd> steps inside the list
- <kbd>b</kbd> moves back in history for all above commands
-
Paredit transformations, callable by plain letters:
- <kbd>></kbd> slurps
- <kbd><</kbd> barfs
- <kbd>r</kbd> raises
- <kbd>C</kbd> convolutes
- <kbd>s</kbd> moves down
- <kbd>w</kbd> moves up
-
IDE-like features for Elisp, Clojure, Scheme, Common Lisp, Hy, Python and Julia:
- <kbd>e</kbd> evals
- <kbd>E</kbd> evals and inserts
- <kbd>g</kbd> jumps to any tag in the current directory with semantic
- <kbd>G</kbd> jumps to any tag in the current file
- <kbd>M-.</kbd> jumps to symbol, <kbd>M-,</kbd> jumps back
- <kbd>F</kbd> jumps to symbol, <kbd>D</kbd> jumps back
- <kbd>C-1</kbd> shows documentation in an overlay
- <kbd>C-2</kbd> shows arguments in an overlay
- <kbd>Z</kbd> breaks
out of
edebug, while storing current function's arguments
Some pictures here.
- Code manipulation:
- <kbd>i</kbd> prettifies code (remove extra space, hanging parens ...)
- <kbd>xi</kbd> transforms
condexpression to equivalentifexpressions - <kbd>xc</kbd> transforms
ifexpressions to an equivalentcondexpression - <kbd>x></kbd> transforms expressions from/to an equivalent
thread-lastexpression - <kbd>xf</kbd> flattens function or macro call (extract body and substitute arguments)
- <kbd>xr</kbd> evals and replaces
- <kbd>xl</kbd> turns current
defuninto alambda - <kbd>xd</kbd> turns current
lambdainto adefun - <kbd>O</kbd> formats the code into one line
- <kbd>M</kbd> formats the code into multiple lines
- Misc. bindings:
- outlines navigation/folding (<kbd>J</kbd>, <kbd>K</kbd>, <kbd>I</kbd>, <kbd>i</kbd>)
- narrow/widen (<kbd>N</kbd>, <kbd>W</kbd>)
