minad / vertico

:dizzy: vertico.el - VERTical Interactive COmpletion
GNU General Public License v3.0
1.44k stars 58 forks source link

Bring up input history in minibuffer #249

Closed shouya closed 2 years ago

shouya commented 2 years ago

I'd like to have a command that is used in a way similar to previous-history-element (M-p/M-n in minibuffer) but instead of revealing a previously selected element, I want it to reveal my previous input.

This feature would be useful because I sometimes want to explore a set of elements filtered down using the same input. e.g. I would run describe-variable, type in something like vertico-[a-z], and then go through the interesting ones. However, I looked up the documentations and issues of this repo and can't find what I need. (https://github.com/minad/vertico/issues/184 is similar but not quite what I'm asking)

The closet thing I got is vertico-repeat.el, which is intended to used from outside the minibuffer with a keystroke or command that bring up the previous vertico session (along with the input). However, when I try to bind the vertico-repeat command under minibuffer-local-map it doesn't work the way I expected. Also I don't know if it's possible to make me go back and forth among my previous inputs.

Actually, I'd happily replace {previous,next}-history-element with commands to scroll through my inputs instead. Because from an input I will be able to find the selected element, but not vice versa.

minad commented 2 years ago

Okay I see. You want to see the input history instead of the selected element history. Unfortunately the input information is lost, since Emacs doesn't keep it around. Vertico-repeat is your best bet. You could try to patch this to filter only for the current command. I would accept a patch which adjusts vertico-repeat accordingly, such that it behaves better when invoked from the minibuffer. I don't have plans to add this myself, but help is welcome.

minad commented 2 years ago

I played around with vertico-repeat and it turns out that we can easily add this feature there. See https://github.com/minad/vertico/commit/7d52afe74429e0ca18c3cde41b88aac3d687e949. If you invoke vertico-repeat-last from an existing minibuffer it will restore the last input corresponding to the current command. If you invoke vertico-repeat-select you can select from all previous inputs for the current command using completion. There is also the vertico-repeat command which either calls vertico-repeat-last or vertico-repeat-select.

shouya commented 2 years ago

Sounds wonderful! I tried experimenting with it but ended up with this error when trying to invoke vertico-repeat.

[minibuffer-completion-table minibuffer-completion-predicate minibuffer-completion-confirm minibuffer--require-match minibuffer-local-must-match-map minibuffer-local-completion-map t (nil lambda) make-composed-keymap read-from-minibuffer ...] 18 2465692]: Command attempted to use minibuffer while in minibuffer

Is there anything wrong with my config?

(use-package vertico-repeat
  :ensure nil
  :bind
  (:map minibuffer-local-map
        ("M-r" . vertico-repeat))

  :config
  (add-hook 'minibuffer-setup-hook #'vertico-repeat-save)

  ;; preserve history across restarts
  (add-to-list 'savehist-additional-variables 'vertico-repeat-history)
  )
minad commented 2 years ago

This error happens if you use enable-recursive-minibuffers=nil. My recommendation is to enable recursive minibuffers globally since they are genuinely useful. But vertico-repeat will also work with recursive minibuffers disabled, see https://github.com/minad/vertico/commit/ab8e87143ba7045308415bf8e3f555cb675bdda7.

shouya commented 2 years ago

Thanks a lot! It worked perfectly now with (setq enable-recursive-minibuffers t).