Set an Emacs variable with double completion
06 Jun 2016I'd like to show off a certain Elisp productivity booster that I've had in an unfinished state for a while and finished just today.
A large part of tweaking Elisp is simply setting variables. The new command, counsel-set-variable, allows to set them quite a bit faster.
Completion stage 1:
First of all, you get completion for all variables that you have defined:
Completion stage 2:
Once a symbol is selected, the code checks whether the symbol is a
defcustom
with type 'boolean
or 'radio
. Since then it is
possible to offer all values that the symbol is allowed to become for
completion.
For example, here's a typical 'radio
-type definition:
(defcustom avy-style 'at-full
"The default method of displaying the overlays.
Use `avy-styles-alist' to customize this per-command."
:type '(choice
(const :tag "Pre" pre)
(const :tag "At" at)
(const :tag "At Full" at-full)
(const :tag "Post" post)
(const :tag "De Bruijn" de-bruijn)))
And here's a completion screen offered for this variable:
It is worth noting that the current value of the variable is pre-selected, to give a nice reference point for the new setting.
In case the symbol isn't a boolean or a radio
Then you get a completion session similar to M-x
read-expression
, but with the initial contents already filled
in. For example:
The read-expression
part combines well with this setting in my config:
(defun conditionally-enable-lispy ()
(when (eq this-command 'eval-expression)
(lispy-mode 1)))
(add-hook
'minibuffer-setup-hook
'conditionally-enable-lispy)
Here's a series of commands using
lispy-mode that I would typically
use for the screenshot above, to set ivy-re-builders-alist
to a new
value:
- C-f (
forward-char
) to get into special. - -e (
lispy-ace-subword
) to mark theplus
part of the code. - C-d (
lispy-delete
) to delete the active region.
After the C-f -e C-d chain of bindings, the minibuffer contents become:
(setq ivy-re-builders-alist '((t . ivy--regex-|)))
I press C-M-i (completion-at-point
) to get completion for
all symbols that start with ivy--regex-
. Since I have ivy-mode
on,
C-M-i starts a recursive completion session. I highly
recommend adding these settings to your config:
;; Allow to read from minibuffer while in minibuffer.
(setq enable-recursive-minibuffers t)
;; Show the minibuffer depth (when larger than 1)
(minibuffer-depth-indicate-mode 1)
Finally, I would e.g. select e.g. ivy--regex-fuzzy
and RET
RET to finalize the eval. The first RET exits from
completion-at-point
and the second RET exits from
counsel-set-variable
.
Outro
I think this command, especially the newly added read-expression
part, is quite a bit faster than what I did before. That is switching
to *scratch*
and typing in the setq
manually and evaluating with
C-j. Here's my binding for the new command:
(global-set-key (kbd "<f2> j") 'counsel-set-variable)
It's not very mnemonic, but it's really fast. Just a suggestion, in case you don't know where to bind it. Happy hacking!