emacs-which-key icon indicating copy to clipboard operation
emacs-which-key copied to clipboard

Question: displaying which-key during help lookup

Open ScottFreeCode opened this issue 5 years ago • 6 comments

Is it possible to configure/advise/something Emacs to make which-key display the current key sequence entered while I describe-key (C-h k, bonus points if it still works when I've remapped that to helpful-key)?

ScottFreeCode avatar Jan 16 '20 03:01 ScottFreeCode

(This is inspired by how the counsel package uses the ivy package to search for functions/variables to look up with describe-function/describe-variable, by the way. Naturally in my mind the equivalent of search libraries, for key sequences, is which-key!)

ScottFreeCode avatar Jan 16 '20 04:01 ScottFreeCode

Possibly. After looking quickly help--read-key-sequence seems to be the function that would have to be modified. I don't have time for this right now, but I would look at a pr.

justbur avatar Jan 19 '20 20:01 justbur

Hmm. Looks like both help-read-key-sequence and helpful-key call read-key-sequence, which is defined in C. I wonder whether it will turn out to be possible to hook into keys entered during that, or not. I'll dig a little more to see if I can figure it out.

ScottFreeCode avatar Jan 20 '20 23:01 ScottFreeCode

After digging around and finding it's the (null this-command) check in which-key--update that prevents which-key from showing during these commands, and testing that read-key-sequence can be advised, I can see multiple ways to implement this:

  • add a custom variable containing a list of commands not to skip which-key display for; if this-command is not null but is in that list, allow display
  • same but instead of a custom list find all commands that call anything that calls read-key-sequence (not sure this is feasible)
  • advise read-key-sequence to set a which-key flag that can be checked to allow display even if this-command is not null
  • advise read-key-sequence to add and remove advice on which-key--update that uses let to temporarily make this-command be nil (may be inefficient, and I don't know if it affects last-command)

Any solution is going to need to:

  • ~hide the popup (I think the pre command hook that would normally hide it is not run since the command that calls read-key-sequence already started)~ actually fixing the weird following message fixes this, see below
  • if any cleanup needed, then also clean up and rethrow if any errors are thrown (which can happen depending on what function is calling read-key-sequence and whether the user types an invalid binding, either with nothing bound or with a symbol bound that isn't a command)
  • work for describe-key, describe-key-briefly, and optionally user-added commands such as helpful-key

I haven't signed any of the copyright stuff for GNU Elpa, so I don't know that a PR from me wouldn't hold things up.

Also, I am not sure my solution is complete/correct: after getting documentation or an error, if I had started with a prefix, it echoes "- which-key: There are no keys to show" (I believe this means which-key--create-buffer-and-show was called with no prefix description available); I am starting to run out of steam for experimenting at the moment, though.

ScottFreeCode avatar Jan 21 '20 03:01 ScottFreeCode

I tried all three solutions (list of commands, advice sets fleg, advice sets advice that nullifies this-command), and all three have the create buffer and show with no prefix issue.

It's coming after the help command finishes, which comes after the cleanup (in the case of advice).

It's in the trasient map handling branch of which-key--update. That's odd. But adding, say, a check that last-command was not in the same list, fixes it. A bit of a brute force solution though.

If that's fixed, then I don't have to call which-key--hide-popup after all. Interesting.

Well, that means a complete solution is possible using a list of reading commands, e.g. '(describe-key describe-key-briefly helpful-key) Even if it would be better if whatever causes a spurious transient map display attempt was avoided in the first place (obviously it hasn't got a real transient map or it would display it instead of leaving the previous popup end printing that there are no keys in an empty prefix). Hmm…

ScottFreeCode avatar Jan 21 '20 05:01 ScottFreeCode

Figured it out. which-key--update sets which-key--automatic-display: https://github.com/justbur/emacs-which-key/blob/db3d003e903deb07394b4e572206f809578278c6/which-key.el#L2680

which-key--show-page always calls set transient map: https://github.com/justbur/emacs-which-key/blob/db3d003e903deb07394b4e572206f809578278c6/which-key.el#L2202-L2205

But which-key--get-popup-map returns nil if which-key--automatic-display is set: https://github.com/justbur/emacs-which-key/blob/db3d003e903deb07394b4e572206f809578278c6/which-key.el#L2095-L2103

This can be fixed by moving the unless which-key--automatic-display out of which-key--get-popup-map and putting it around that if at the end of which-key--show-page instead, so the transient map is not set at all instead of being set to nil.

Then any of the solutions suggested should work without having to hide the popup afterward and without causing any weird messages.

ScottFreeCode avatar Jan 21 '20 06:01 ScottFreeCode