Emacs: separate minibuffer history for a command
Just updated my init.el
today and I had a hard time finding an easy or definitive
answer to this question on the web, so here's a small writeup.
The gist of it is simple: I have an interactive command (using the magic interactive
form) and when using savehist-mode
, I want it to have a separate history that won't pollute the global minibuffer one and vice versa.
Here's the command concerned:
(defun sed-on-region (start end script) "Run a `sed -E` script on a region" (interactive "*r\ns`sed -E` script: ") (call-process-region start end "sed" t t t "-E" script))
Note the interactive string format specifying that:
* | It should error out when used in a read-only buffer. |
r | The two first parameters are the current region's start and end. |
s… | The third is a string read from the minibuffer using … as prompt. |
At that point, I dived into the usual rabbit hole: furious perusing of emacs' doc, various
StackOverflow posts and even mailing list archives to end up - after a few half-baked abominations -
at the "proper" solution. Which is to use the second interactive
argument descriptor style: a form that is evaluated to get a list of arguments to pass to
the command
.
Then it was just a matter of putting the Lego pieces together:
(defvar sed-on-region-history nil) (with-eval-after-load 'savehist (push 'sed-on-region-history savehist-additional-variables)) (defun sed-on-region (start end script) "Run a `sed -E` script on a region" (interactive (progn (barf-if-buffer-read-only) (list (region-beginning) (region-end) (read-string "`sed -E` script: " nil 'sed-on-region-history)))) (call-process-region start end "sed" t t t "-E" script))
Ta-da! Well, I say "just", but in truth I did struggle a bit with interactive
(mostly because I tried to guess by example when I should have sat down to RTFM) and finding
out which function was being called by the read-only buffer check *
(barf-if-buffer-read-only
, emacs' legendary doc did fail me here).
Here's the rest of my config for the curious.