lispy point history
09 Mar 2015It was kind of disappointing to summarize in
the last post
that there weren't many new features for
lispy 0.24.0. So I thought long and hard and came up with something
quite obvious: since lispy
offers commands to quickly manipulate point and mark, it should offer one
to quickly restore them.
Here's the bulk of the new code:
(defvar lispy-pos-ring (make-ring 200)
"Ring for point and mark position history.")
(ring-insert lispy-pos-ring 1)
(defun lispy--remember ()
"Store the current point and mark in history."
(if (region-active-p)
(let ((bnd (lispy--bounds-dwim)))
(unless (equal bnd (ring-ref lispy-pos-ring 0))
(ring-insert lispy-pos-ring bnd)))
(unless (eq (point) (ring-ref lispy-pos-ring 0))
(ring-insert lispy-pos-ring (point)))))
(defun lispy-back ()
"Move point to a previous position"
(interactive)
(if (zerop (ring-length lispy-pos-ring))
(user-error "At beginning of point history")
(let ((pt (ring-remove lispy-pos-ring 0)))
(if (consp pt)
(lispy--mark pt)
(deactivate-mark)
(goto-char pt)))))
Here, I'm using lispy-pos-ring
made with make-ring
to store the
last 200 point and mark positions. In Elisp, a ring is basically a stack backed by a vector.
When the vector space overflows, the older stuff is overwritten.
In this ring I store each time either the point, or a cons of the point and mark if the region is active. This way possible to restore the region even if it was deactivated several movement commands ago.
I've put lispy--remember
into the most used navigation commands:
- j -
lispy-down
- k -
lispy-up
- h -
lispy-left
- l -
lispy-right
- f -
lispy-flow
- i -
lispy-mark-car
(when the region is active) - a -
lispy-ace-paren
And lispy-back
is now bound to b. The previous binding of
b - lispy-store-region-and-buffer
is now bound to
xB (quite close to B - the binding for
lispy-ediff-regions
).
I really like the new command, it's especially useful to reverse h and l. Previously, they could be reversed with f, but that can get annoying if you have to press it many times. This results in a much more relaxed editing - I know that whatever I press, I can restore the point position quickly if needed.
This feature is added to the already present list of safeguards:
- j and k are guaranteed not to exit the parent list.
- > and < are guaranteed not to exit the parent list.
- C reverses itself.
Here's a recipe to copy the third item of the current list and move
the point back: 4mnb. You can use it to copy a function's
docstring if you're in Elisp. You'll need 3mnb for
Clojure, since it weirdly has the docstring before the arguments. I
think it's pretty cool: by typing 3mnb I'm basically
calling (kill-new (caddr (current-sexp)))
on my own code.