holymotion
holymotion copied to clipboard
evil-easymotion, purified of evil
holymotion: evil-easymotion, purged of evil...

In order to remove the dependency on evil, this code was forked from https://github.com/PythonNut/evil-easymotion, which was itself a clone of the popular easymotion package for vim, which describes itself in these terms:
Easymotion provides a much simpler way to use some motions in vim. It takes the
out of w or f{char} by highlighting all possible choices and allowing you to press one key to jump directly to the target.
Below is a gif showing holymotion versions of forward/backward-word and next/previous-line.

Installation
I just use use-package like so:
(use-package holymotion
:straight (holymotion :type git
:host github
:repo "Overdr0ne/holymotion"
:branch "main")
:config
;; define some custom motions, I'm using smartparens here
(holymotion-make-motion
holymotion-forward-sexp #'sp-forward-sexp)
(holymotion-make-motion
holymotion-backward-sexp #'sp-backward-sexp))
Basic Usage
holymotion comes with a handful of predefined holymotions for basic Emacs movement commands for your convenience. They are all prefixed with holymotion-, so take a look around, describe-command, and map them as you please.
However, the intention of this package is to provide a toolkit for making your own motion commands, rather than an exhaustive library of transformations from regular movements to holymotion movements.
Which brings me to the next section...
Building Your Own Motions
Collectors
Where present, collectors are used as the motion specification for generating jump points. It may be an (optionally sharp) quoted function name, a lambda, or a list of any of the above. If multiple functions are provided, the collected points are merged and presented at once.
Macros
holymotion provides this user-facing macros:
-
(holymotion-make-motion name collectors &key ...)Produce a function, named
name, fromcollectors.
Keyword arguments
In addition, various keyword arguments may be used to modify the behavior of the holymotion.
-
:pre-hook exprCode to run before the holymotion executes.
exprmay either be an (optionally sharp) quoted function name, a lambda, or a bare sexp, which is implictly wrapped in a lambda. -
:post-hook exprLike
:pre-hook expr, but code is run after the motion finishes. -
:bind formsA list of forms to bind around the entire holymotion.
formsmay be any bindings accepted bycl-letf*. -
:scope objectAn object to limit the scope of an holymotion.
objectmay be any thing understood bything-at-point. In practice,objectwill often be'line. -
:all-windows exprIf
expris non-nil, the motion will be executed in all visible windows simultaneously. -
:initial-motion callableWhen specified,
(goto-char (funcall callable))is run before the motion is executed. For example, use this to jump to the BOL of each line as in easymotion with:initial-position #'point-at-bol. Unlike in:pre-hook,callableis run once per window when:all-windowsis specified. -
:collect-postprocess callableWhen specified,
callableis called on the collected list of points (which is of the form((point window)...)). Otherwise, the default function, which sorts the points in order of increasing distance from(point), is used. -
:include-invisible exprWhen
expris non-nil, the motion will not skip over invisible overlays. This may be required for motions that generate dramatically different sets of points if they are started at different locations. This defaults tonil.
Tips on Binding Keys
One way to bind your holymotions is to use prefix keys. An empty holymotion-map has been provided for this purpose. So you could bind holymotion-map to some prefix key, like M-h, then bind all of your holymotions to their normal analogs: C-n to holymotion-next-line, C-p to holymotion-previous-line, etc.
Another way is to map your keys within the holymotion-mode-map. Then, you can activate/deactivate that map by enabling/disabling the holymotion-minor-mode, and any keybindings within that keymap will override your current keybindings when enabled. describe-command on holymotion-mode for more details. This ability to replace your keybindings would then give you the shortest keybindings possible, or even replacing normally self-inserting keys; nice for when you are just navigating around.
Personally, I have created an equivalent holymotion for most of my standard motions. Then, I just add a modifier when I want the holymotion version. For example, if you use C-n for next-line, you could bind C-M-n for your holymotion-next-line. Another scheme I’ve used, if you have the Alt(A-) modifier available to you, you could just use that as your modifier instead, since no keys are bound to Alt by default in Emacs.
Finally, if you just want to replace a normal motion command like beginning-of-line with your holymotion equivalent, you can always use the https://www.gnu.org/software/emacs/manual/html_node/elisp/Remapping-Commands.html feature of define-key.
Credits
I'm deeply indebted to:
- PythonNut for authoring
evil-easymotion, the package this was forked from. - abo-abo for authoring
avy, on which this package depends. - Lokaltog for authoring
vim-easymotionand creating the paradigm which this package emulates.