- C-k should delete the whole multi-line string.
- y should work for all parens, not just
- p should actually eval in other window for
- Prevent pairs inserting an extra space when at minibuffer start.
- ol works properly for active region.
- xf will pretty-print the macros for Elisp.
- M-m works better when before
- Fix ', ^ after a
- Improve / (splice) for quoted regions.
- Z works with
- The new M is used in xf.
- Allow to flatten Elisp
- c should insert an extra newline for top-level sexps.
Paredit key bindings
You can have only Paredit + special key bindings by using this composition of key themes:
(lispy-set-key-theme '(special paredit))
The default setting is:
(lispy-set-key-theme '(special lispy c-digits))
New algorithm for multi-lining
M is now bound to
lispy-alt-multiline instead of
lispy-multiline. It has a much better and more customizable algorithm.
See these variables for customization:
They are set to reasonable defaults. But you can customize them if you feel that a particular form should be multi-lined in a different way.
lispy-multiline-threshold is a bit of ad-hoc to make things nice. Set this to nil if you want a completely rigorous multi-line. With the default setting of 32, expressions shorter than this won't be multi-lined. This makes 95% of the code look really good.
The algorithm has a safety check implemented for Elisp: if
read on the transformed expression returns something different than
read on the original expression, an error will be signaled and no change will be made. For expressions that can't be
read, like buffers/markers/windows/cyclic lists/overlays, only a warning will be issued (
lispy can read them, unlike
d and > give priority to
For the expression
(a) will be considered the sexp at point, instead of
(b). This is consistent with
show-paren-mode. If a space is present, all ambiguities are resolved anyway.
b works fine even if the buffer changes
I've switched the point and mark history to markers instead of points. When the buffer is changed, the markers are updated, so b will work fine.
Extend Clojure reader
In order for i (prettify code) to work for Clojure, it must be able to read the current expression. I've been extending the Elisp reader to understand Clojure. In the past commits, support was added for:
- empty sets
- auto-symbols, like
Extend Elisp reader
It should be possible to read any
#<...> form, as well as
g and G get a persistent action for
This is a powerful feature that the
helm back end has had for a long time. When you press g, C-n and C-p will change the current selection. But C-M-n and C-M-p will change the current selection and move there, without exiting the completion.
This also means that you can call
ivy-resume to resume either g (
e works with
As you might know, the regular C-x C-e or
eval-buffer will not reset the values of
defcustom and such (you need C-M-x instead). But e does it, now also for
Improve faces for dark backgrounds
I normally use a light background, so I didn't notice before that the faces looked horrible with a dark background.
The ` will quote the region
If you have a region selected, pressing ` will result in:
Customize the file selection back end for V
lispy-visit) allows to open a file in current project. Previously, it used
Now it uses
find-file-in-project by default, with the option to customize to
Fixup calls to
looking-back isn't very efficient, so it's preferable to avoid it or at least add a search bound to improve efficiency. Also the bound became mandatory in 25, while it was optional before.
M-m will work better in strings and comments.
See the relevant test:
(should (string= (lispy-with "\"See `plu|mage'.\"" (kbd "M-m")) "\"See ~`plumage'|.\""))
Thanks to this, to e.g. get the value of a quoted var in a docstring or a comment, or jump to its definition, you can M-m. Then, you can step-in with i to select the symbol without quotes.
Update the tags strategy
A much better algorithm with caching an examining of file modification time is used now. This means that the tags should be up-to-date 99% of the time, even immediately after a save, and no necessary re-parsing will be done. And it all works fine with the
1% of the time,
lispy-tag-arity stops working, I don't know why, since it's hard to reproduce. You can then pass a prefix arg to refresh tags bypassing the cache, e.g 2g or 2G.
Also a bug is fixed in Clojure tag navigation, where the tag start positions were off by one char.
The fetched tags retrieval is fast: less than
0.15s on Emacs'
lisp/ directory to retrieve 21256 tags from 252 files. Which means it's lightning fast on smaller code bases (
lispy has only 651 tags).
xj can also step into macros
lispy-debug-step-in, bound to xj locally and C-x C-j globally can now step into macros, as well as into functions. This command is very useful for Edebug-less debugging. Stepping into macros with
&rest parameters should work fine as well.
p can now lax-eval function and macro arguments
When positioned at function or macro args, p will set them as if the function or macro was called with empty args, or the appropriate amount of nils. If the function is interned and interactive, use its interactive form to set the arguments appropriately.
Again, this is very useful for debugging.
Allow to paste anywhere in the list using a numeric arg
As you might know, P (
lispy-paste) is a powerful command that:
- Replaces selection with current kill when the region is active.
- Yanks the current kill before or after the current list otherwise.
Now, you can:
- Yank the current kill to become the second element of the list with 2P
- Yank the current kill to become the third element of the list with 3P
It's OK to pass a larger arg than the length of the current list. In that case, the paste will be made into the last element of the list.
Update the way / (
When there's no next element within parent, jump to parent from appropriate side. When the region is active, don't deactivate it. When splicing region, remove random quotes at region bounds.
This change makes the splice a lot more manageable. For example, starting with this Clojure code, with
| marking the current point:
(defn read-resource "Read a resource into a string" [path] (read-string |(slurp (clojure.java.io/resource path))))
A double splice // will result in:
(defn read-resource "Read a resource into a string" [path] |(read-string slurp clojure.java.io/resource path))
After xR (reverse list), 2 SPC (same as C-f),
-> (plain insert), [M (back to parent and multi-line), the final result:
(defn read-resource "Read a resource into a string" [path] |(-> path clojure.java.io/resource slurp read-string))
This also shows off xR -
lispy-reverse, which reverses the current list. Finally, reverting from the last code to the initial one can be done simply with xf - it will flatten the
-> macro call.
lispy-elisp-modeslist. It means that you can eval there if you want.
- V (
lispy-visit) should turn on
projectile-global-modeif it's not on.
- M (
lispy-multiline) works better for Clojure: the regexes for vectors, maps and sets have been improved.
- C-k should not delete only the string when located at start of string.
- M will not turn vectors into lists any more.
- the backquote bug for i and M was fixed.
- you can flatten Elisp closures as well, at least the plain ones.
The movement commands, such as:
- the arrows hjkl (
- f (
- q (
- i (
lispy-tab), only when called for an active region
will not store each movement in the point-and-mark history. You can press b to go back in
history. This is especially useful for h, l, and f, since they are
not trivially reversible.
b was previously bound to
lispy-store-region-and-buffer, so you could do Ediff with
b and B. Now it's bound to xB.
Hungry comment delete
lispy-delete) when positioned at the start of a comment, and with only whitespace
before the start of the line, will delete the whole comment.
If you want to un-comment, just use C-u ; from any point in the comment.
Added flatten operation for Clojure
lispy-flatten) now also works for Clojure, before it was only for Elisp.
Example 1 (flatten a macro):
|(->> [1 2 3 4 5] (map sqr) (filter odd?))
When you press xf you get this:
|(filter odd? (map sqr [1 2 3 4 5]))
Example 2 (flatten a standard function):
|(map odd? [1 2 3 4 5])
(let [f odd? coll [1 2 3 4 5]] (lazy-seq (when-let [s (seq coll)] (if (chunked-seq? s) (let [c (chunk-first s) size (int (count c)) b (chunk-buffer size)] (dotimes [i size] (chunk-append b (f (.nth c i)))) (chunk-cons (chunk b) (map f (chunk-rest s)))) (cons (f (first s)) (map f (rest s)))))))
A bit of a gibberish, but at least we can confirm that
map is indeed lazy.
Example 3 (flatten your own function):
(defn sqr [x] (* x x))
This one requires the function to be properly loaded with C-c C-l (
otherwise Clojure will not know the location of the function.
(+ |(sqr 10) 20)
(+ |(let [x 10] (* x x)) 20)
Added lax eval for Clojure
This is similar to the lax eval for Elisp. If you mark an expression with a region:
asdf [1 2 3]
and press e, you will actually eval this:
(do (def asdf [1 2 3]) asdf)
You can do this for let bindings, it's super-useful for debugging. The rule is that if the first
element of the region is a symbol, and there's more stuff in the region besides the symbol, a lax
eval will be performed.
e will auto-start CIDER
If CIDER isn't live, e will start it and properly eval the current statement.
2F will search for variables first
Since Elisp is a LISP-2, there can be a function and a variable with the same name. F
lispy-follow) prefers functions, but now 2F will prefer variables.
2e will eval and insert the commented result
|(filter odd? (map sqr [1 2 3 4 5]))
Pressing 2e gives:
(filter odd? (map sqr [1 2 3 4 5])) ;; => ;; (1 9 25)
This works for all dialects, so you can also have:
(symbol-function 'exit-minibuffer) ;; => ;; (closure (t) ;; nil "Terminate this minibuffer argument." (interactive) ;; (setq deactivate-mark nil) ;; (throw (quote exit) ;; nil))
*MODULES* ;; => ;; ("SWANK-ARGLISTS" "SWANK-FANCY-INSPECTOR" "SWANK-FUZZY" "SWANK-C-P-C" ;; "SWANK-UTIL" "SWANK-PRESENTATIONS" "SWANK-REPL" ;; "SWANK-TRACE-DIALOG" "SB-CLTL2" "SB-POSIX" "SB-INTROSPECT")
To do the last eval you need to be in special. So first mark the symbol
*MODULES* with a region.
A convenient function to mark the current symbol is M-m (
lispy-occur) now has an
ivy back end
lispy-occur launches an interactive search within the current top-level expression, usually a
defun. This is useful to see where a variable is used in a function, or to quickly navigate to a
You can customize
lispy-occur-backend to either
ivy (the default) or
helm (if you have it,
since it's no longer a dependency of
Add ivy back end to
Now it's the default one for navigating to tags. You can select alternatively
ido if you
Remove the dependency on
Instead the dependency on
ace-window will be re-used. This allows for a lot of code
simplifications and better tests.
New custom variables:
lispy-avy-style-char: choose where the overlay appears for Q (
lispy-avy-style-paren: choose where the overlay appears for q (
lispy-avy-style-symbol: choose where the overlay appears for a (
and - (
lispy-ace-subword) and H (
lispy-avy-keys, which is
z by default.
This is a list of compatibility features with other packages, such as
They add overhead, so you might want to turn them off if you don't use the mentioned packages.
F works for Scheme
You can navigate to a symbol definition in Scheme with F. This feature was already
in place for Elisp, Clojure and CL.
- DEL behaves properly after a string and one space.
- C-k works better for expressions preceded with "#".
- 3 should not add a space when there is one already.
- # will not add a space after a comma.
- C-j works better in comments after a quote.
lispy--eval-elisp-formfirst arg is now named
form. It was impossible
to evaluate an unrelated
formvariable with the previous behavior.
- F again works properly when jumping to a jar (e.g. to
defn) from Clojure source.
- C-k won't call
delete-regionin some obscure branches.
- P (
lispy-paste) will add a newline when called from start of line. This way,
nP becomes equivalent to c (
lispy-clone). Of course, it's more flexible: you
can do e.g. nkP.
- xb (
lispy-bind-variable) now works on regions as well. Use it to bind the current
sexp or region as a let-bound variable: it will put you in
iedit. When you're done with
lispy-mark-symbol) to exit
iedit. If you need to move the let binding around, use
a combination of C (
lispy-convolute) and h (
- g will ignore
- M-m works better in unbalanced buffers, which should be an rare thing.
lispy-tag-arity: now g will recognize
- The tag logic was improved to do less parsing.
lispy-outlinewas updated to match the standard
^;;;outline regex. Try pressing I
in e.g. org.el, it's quite beautiful.
lispy-evalfunctions will preserve the match data.
- > will delete the extra whitespace while slurping.
undercover/Coveralls test coverage report.
- H (
lispy-ace-symbol-replace) is now a Hydra: type h to delete more, type
u to undo.
- Q (
lispy-ace-char) now uses
avyto jump. This change allows to cover this
function with a test.
p can now iterate
dolist variables in Elisp.
(defun range (a b) (message "called range") (number-sequence a b)) (dolist |(i (range 1 3)) (message "i=%d" i))
Pressing p with point where
| is, will
This is another step toward
edebug-less debugging, adding to special behavior for
lispy-helm-columnsis now a list
'(60 80). The first number is the width of the tag name
column, the second number is the width of both tag name and tag file.
- j and k should now move to outline when at beginning of comment. The previous
behavior was to look for the first sexp in the direction. You can still do that with f.
- I (
lispy-shiftab) is now a two-way cycle, instead of three-way, like
The contents can be obtained with C-u I or C-u C-TAB.
- M-DEL improved in strings; it doesn't leave the string after kill; whitespace issue is fixed.
(eq (char-before) ?\()being interpreted as nil by
- F is fixed for Clojure after breaking with a CIDER update
- M-RET inserts an outline of at least level 1
- M-m fixed near a string
- p will not modify whitespace
- C-g will not jumble ace commands
- j and k don't switch list side when they can't go any further
- C-d is even less whitespace-hungry
- e will treat
identityfor eval purposes: it's now possible to eval e.g.
(list (list ,foo)|), which will return the result of
- C-3 will try to expand abbrevs
- DEL will treat a comment as a sexp, when at start of comment: extra whitespace will be deleted.
- p is greatly improved for when there are more that 2 windows: you will select the target window
ace-window. Afterwards, if the window configuration doesn't change, the target window will stay the same
and you don't need to select anymore.
- 4 SPC will amend current sexp with a newline
- M-left and M-right move outlines, just like in
- C-a will call
lispy-move-beginning-of-linewhich either moves to beginning of line,
or back to indentation when already there. It will also reveal a hidden outline when appropriate.
Completion methods aplenty for g
A new custom variable
lispy-completion-method can now take 3 values:
helm- completes with
- completes with
ido, strings don't include filename to save space
ido-vertical-modeis on, gives strings same as for
- completes with
default- falls back to other completion methods:
icomplete-mode, when it's on
icy-mode, when it's on
completing-readwhen nothing else is on
Updated outline shortcuts
When at outline:
- l will promote
- h will demote
- M-RET will not leave special when adding an outline
- a forwards to M-RET now
- L will go to the outline's first child sexp
- t is bound to `end-of-line' when at outline. Use
e.g. at to immediately edit the outline name. Or use
alt to promote it once before editing etc.
- DEL can delete the previous outline.
- h doesn't jump between top-level sexp and the outline anymore.
- n will not throw when the kill ring is empty.
- ' will not add a space when preceeded by
- h and l don't deactivate mark on failure (when can't move further)
- i changes
- C-j works for `cider-clojure-interaction-mode', as does E
- ## will first attempt to start a map or set literal in Clojure, then do a gensym literal.
- a will not select select empty parens and symbols can
start with "~,@".
- RET and C-j carry the quotes with them and
re-indent. If you don't want to carry the quotes, you can press a
- M-j will behave better when at eol inside a string
- 2 SPC will now exit special and insert a space in front of the list.
- 3 SPC will now exitspecial and insert a space in back of the list.
- M-d calls
lispy-kill-word. Similar to
takes care of matching the list and string delimiters.
- M-DEL calls
lispy-backward-kill-word. Similar to
takes care of matching the list and string delimiters.
- M-k calls
lispy-kill-sentence. Similar to
kill-sentence, but the sentence now the current list.
lispy-forwardis bound to C-M-n, in addition to ]
lispy-backwardis bound to C-M-p, in addition to [
The obsolete aliases
lispy-out-forward-nostring were removed.
lispy-counterclockwise have been marked as
obsolete and will be removed in
0.23.0. There's no need to replace
them, since they don't do much.
- ( adds a space when wrapping region
- w/s work for files indented with both tabs and spaces (but this doesn't
mean that anyone should do that)
- p doesn't change the whitespace
- fix the issue of dynamic variable
- i will fall back to the default indent-sexp if the thing to indent is too large
- '' will not insert an extra space
- F (follow) and M-. (goto-symbol) now unfold a hidden outline if they end up there.
- mm (mark-list) will not trigger
xh (describe) now describes variables in addition to functions.
y (occur) pre-select was improved.
y (occur) will deactivate mark.
C (convolute) now works from both sides, not just from the front.
t (teleport) will now work only within the current defun. This will make it more consistent, since
it will not depend on the window scroll amount.
e (eval) is greatly improved for Clojure. It will now concatenate both the output
and the eval result, with output colored as string.
i (indent) now works also with Clojure map literals.
B (ediff-bounds) the ediff will try re-use the current window configuration.
C-4 C-h or C-h F1 will describe the bindings
C-d and DEL are now less whitespace-hungry and more intuitive
xj (debug-step-in) now works for adviced functions
A (beginning-of-defun) will restore point and mark when called twice
S (stringify) or C-u " (quote) don't move the point.
S (stringify) will keep the region.
' (tick) will unquote if the current region is a string. So now you can
quote/unquote region with "/'.
m and M-m will mark the full sexp, i.e. together with
i now works for marked quoted symbols, so if you have
|(add-to-list 'auto-mode-alist '(\"\\\\.cache\\\\'\" . emacs-lisp-mode))
you can eval
auto-mode-alist with mijie.
- xb now calls
lispy-bind-variable: the current expression will be moved to
a let binding and you will write down the binding name with
iedit. You can use M-m
ieditand to mark the newly created name. Then, if you want to move the
let, just use
a combination of C and h.
- C-return now calls
lispy-open-line: it's useful to add a new line after the current
expression without moving the point.
lispy-alt-lineis the alternative newline. It might be a bit confusing, so it's not bound.
However, it's very useful: see the tests. You can bind it to one of C-j or C-m
or return, as they all don't have to do the same thing.
- you can now enable
slime-repl-mode, RET will work.
- p (eval-other-window) now works for
cl-labels: it will appropriately bind the function at point.
- 0m (mark-list) now marks the inner part of the list, i.e. without parens.
- # (hash) now works in a similar way to other keys that add one extra space:
`, : etc.
- c (clone) is now improved for region selection. You can now generate a function call
from function definition with 2mcol( or mijcol(.
- ~ (tilde) is a new function that, besides inserting tilde can toggle it at the start
of the region when the region is active.
Extended outline support
The outline style was changed, to allow for nested outlines.
- j: If at outline, move to next outline.
- k: If at outline, move to previous outline.
- h: If at top-level, move to parent outline. Go back when called the second time.
- l: If at outline, move to the first child sexp.
- i: If at outline, fold/unfold it with
- I: fold/unfold all outlines with
- M-return: Add an outline, just like in
- v: works for outlines
- a: If at outline, add a new outline and move there.
- M-j (split) and M-J (join) were improved a lot for strings and lists. See tests.
- + (join) will no longer exit the list, instead keeping the position.
You can easily view tests now
- the testing support was improved, so now the tests look more clear.
- xv (view-test): You can position the point at a
and this function will should you in an overlay:
- initial state of the code, with point and mark
- the key to trigger the transformation
- the expected final state of the code
Here's another preview, with special handling of point, mark, region and
In an effort to simplify the notation,
lispy-out-forward was renamed to
lispy-out-backward was renamed to
The old names are retained as obsolete aliases for the current functions. They will be removed in the next release.
w/s can move quoted sexps, e.g. moving these will work as expected:
(custom-set-variables '(inhibit-startup-screen t)| '(initial-scratch-message "") '(scroll-bar-mode nil) '(show-paren-mode t) '(tool-bar-mode nil) '(menu-bar-mode nil))
DEL will delete the preceding comment in this situation:
(bar) ;; bar |(baz)
- the preselect option of g works better
- g now gives additional info for
- g now highlights Elisp user-visible functions (i.e. commands) with
- M-i (
iedit) now also works from left paren
- M-m can now mark a string when the point is at the last quote of the string.
- y now calls
lispy-occur. Halfway through implementing
it, I realized that it's basically just
helm-swooprestricted to current defun.
Still, it's very convenient to navigate to a function call by name within the current top-level
sexp, or to see variable's usage with current function.
- xu now calls
See screencast for the detailed demo of these two features.
- D is now
lispy-describe). Now the
follow-go back combo is very ergonomic at F/D.
The global bindings for follow-go back are still M-./M-,
- xh is now
w/s now works even if the next symbol isn't a list
(foo |(bar) baz) ->s-> (foo baz |(bar))
C-k now considers braces and brackets in addition to parens
no more compilation errors on Emacs-24.3
i will pretty-print Clojure better
- xr works on region as well
- DEL deletes quotation chars (e.g. quote, quasi-quote) along with the list
- C-y obeys
- " works better with region
- DEL and C-d have been largely overhauled
- DEL calls
recenterif it deleted a lot of text
- m marks/unmarks comment when called from comment start
- p works also for
condbranches: just aim at the
branch and it will call the branch test and, if it's true, the
- the repo has been shrunk with http://rtyley.github.io/bfg-repo-cleaner/, so it takes
less time to clone now.
- M works better for Clojure
- M-q calls
lispy-fill, which will re-print current expression,
- o g calls
- o g p calls
- 0 g calls
- ' and ` insert an extra space when necessary
lispy-quote) doesn't add extra space when at eol
- navigation commands don't try to re-indent read-only buffers
C-kwill not delete in one case instead of killing
lispy-cursor-down) deactivates itself
lispy-eval-other-window) does a
setqwhen asked to eval the
definition part of a
lispy-flatten) gives a warning when trying to extract body
from e.g. Emacs C code
lispy-eval-and-replace) ends in special now
lispy-raise) obeys prefix arg, i.e.
3rdoes what you
C-4(previously synonym for
lispy-x) is now just a
standard Emacs map, so things like
C-4 ?are given for free
mnow takes a prefix arg, e.g.
2mwill mark the second element
of the list.
olwill no longer select region if it wasn't selected before
ican now handle Clojure's lambda syntax
xdwill not move the point in case of failure
owill work with
Enow supports pretty-printing for Clojure (use
-will mark the first part of the symbol if only one symbol is selected