1

when helm is active, I can press C-c ? to open a buffer containing helpful information for the current helm session. Now, coming from vim, I'd like to have some evil-bindings in that window, but I'm not even able to determine the mode that the buffer is in, as everything except from a couple of keystrokes is not bound to anything.

How can I rebind keys in helm's help-buffer?

3

By design, *Helm Help* buffers do not use a keymap. Instead, helm hard-codes all navigation in *Helm Help* buffers in a function called helm-help-event-loop. This can be a bit surprising, as not only does it override any navigation shortcuts you use globally (like your evil bindings), but it also makes it difficult (but not impossible) to customize.

The approach you need to take is to redefine helm-help-event-loop after it is loaded. The following should work:

(eval-after-load "helm-lib"
  '(defun helm-help-event-loop ()
    (let ((prompt (propertize
                   "[SPC,C-v,down,next:NextPage  b,M-v,up,prior:PrevPage C-s/r:Isearch q:Quit]"
                   'face 'helm-helper))
          scroll-error-top-bottom)
      (helm-awhile (read-key prompt)
        (cl-case it
          ((?\C-v ? down next) (helm-help-scroll-up helm-scroll-amount))
          ((?\M-v ?b up prior) (helm-help-scroll-down helm-scroll-amount))
          (?\C-s (isearch-forward))
          (?\C-r (isearch-backward))
          (?\C-a (call-interactively #'move-beginning-of-line))
          (?\C-e (call-interactively #'move-end-of-line))
          (?\C-f (call-interactively #'forward-char))
          (?\C-b (call-interactively #'backward-char))
          (?\C-n (helm-help-next-line))
          (?\C-p (helm-help-previous-line))
          (?\M-a (call-interactively #'backward-sentence))
          (?\M-e (call-interactively #'forward-sentence))
          (?\M-f (call-interactively #'forward-word))
          (?\M-b (call-interactively #'backward-word))
          (?\C-  (helm-help-toggle-mark))
          (?\M-w (copy-region-as-kill
                  (region-beginning) (region-end))
                 (deactivate-mark))
          ;; new bindings added here:
          (?j    (helm-help-next-line))
          (?k    (helm-help-previous-line))
          ;; end of new bindings
          (?q    (cl-return))
          (t     (ignore)))))))

In this example, I've added two new bindings - j to scroll down one line, and k to scroll up one line. You should be able to follow the syntax of the other lines to add additional options. Note that, unlike normal keybindings, you use the actual function calls (i.e., (helm-help-next-line), rather than referring to the function names (i.e., 'helm-help-next-line). This is because in this context, you are not referring to the functions, but the code directly calls them. Also, you can probably use the regular function calls (i.e., (move-end-of-line)), rather than wrapping them in (call-interactively ...). This latter form is apparently only needed if you use a screen-reader.

You can of course use this to remove keybindings as well. However, make sure you leave at least one binding for (cl-return), or you'll be stuck in the help window forever.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.