Wilfred / helpful

A better Emacs *help* buffer
1.11k stars 62 forks source link

Error when looking up help for `help-command` #228

Open casouri opened 4 years ago

casouri commented 4 years ago

Reproduce:

M-x helpful-callable RET help-command RET

Backtrace:

Debugger entered--Lisp error: (wrong-type-argument sequencep t)
  mapconcat(identity (t) " ")
  s-join(" " (t))
  helpful--signature(help-command)
  helpful-update()
  helpful-callable(help-command)
  funcall-interactively(helpful-callable help-command)
  call-interactively(helpful-callable record nil)
  command-execute(helpful-callable record)
  execute-extended-command(nil "helpful-callable" #("hel\nhelpful-callable\nhelpful-variable\nghelp-switch-to-page\nhelp\nghelp-refresh\nghelp-global-minor-mode\nghelp-minor-mode\nghelp-page-minor-mode\nghelp-describe-symbol" 0 1 (ws-butler-chg delete) 1 3 (ws-butler-chg chg) 3 4 (read-only nil ws-butler-chg chg) 4 6 (face ((:foreground "#f0f0f0") ivy-current-match ivy-minibuffer-match-face-1) mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 6 20 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) face ((:foreground "#f0f0f0") ivy-current-match) read-only nil ws-butler-chg chg) 20 21 (read-only nil ws-butler-chg chg) 21 23 (face ivy-minibuffer-match-face-1 mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 23 37 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 37 38 (read-only nil ws-butler-chg chg) 38 39 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 39 41 (face ivy-minibuffer-match-face-1 mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 41 58 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 58 59 (read-only nil ws-butler-chg chg) 59 61 (face ivy-minibuffer-match-face-1 mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 61 63 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 63 64 (read-only nil ws-butler-chg chg) 64 65 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 65 67 (face ivy-minibuffer-match-face-1 mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 67 77 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 77 78 (read-only nil ws-butler-chg chg) 78 79 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 79 81 (face ivy-minibuffer-match-face-1 mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 81 101 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 101 102 (read-only nil ws-butler-chg chg) 102 103 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 103 105 (face ivy-minibuffer-match-face-1 mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 105 118 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 118 119 (read-only nil ws-butler-chg chg) 119 120 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 120 122 (face ivy-minibuffer-match-face-1 mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 122 140 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 140 141 (read-only nil ws-butler-chg chg) 141 142 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 142 144 (face ivy-minibuffer-match-face-1 mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 144 162 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg)))
  funcall-interactively(execute-extended-command nil "helpful-callable" #("hel\nhelpful-callable\nhelpful-variable\nghelp-switch-to-page\nhelp\nghelp-refresh\nghelp-global-minor-mode\nghelp-minor-mode\nghelp-page-minor-mode\nghelp-describe-symbol" 0 1 (ws-butler-chg delete) 1 3 (ws-butler-chg chg) 3 4 (read-only nil ws-butler-chg chg) 4 6 (face ((:foreground "#f0f0f0") ivy-current-match ivy-minibuffer-match-face-1) mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 6 20 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) face ((:foreground "#f0f0f0") ivy-current-match) read-only nil ws-butler-chg chg) 20 21 (read-only nil ws-butler-chg chg) 21 23 (face ivy-minibuffer-match-face-1 mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 23 37 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 37 38 (read-only nil ws-butler-chg chg) 38 39 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 39 41 (face ivy-minibuffer-match-face-1 mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 41 58 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 58 59 (read-only nil ws-butler-chg chg) 59 61 (face ivy-minibuffer-match-face-1 mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 61 63 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 63 64 (read-only nil ws-butler-chg chg) 64 65 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 65 67 (face ivy-minibuffer-match-face-1 mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 67 77 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 77 78 (read-only nil ws-butler-chg chg) 78 79 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 79 81 (face ivy-minibuffer-match-face-1 mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 81 101 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 101 102 (read-only nil ws-butler-chg chg) 102 103 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 103 105 (face ivy-minibuffer-match-face-1 mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 105 118 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 118 119 (read-only nil ws-butler-chg chg) 119 120 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 120 122 (face ivy-minibuffer-match-face-1 mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 122 140 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 140 141 (read-only nil ws-butler-chg chg) 141 142 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 142 144 (face ivy-minibuffer-match-face-1 mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg) 144 162 (mouse-face ivy-minibuffer-match-highlight help-echo (format (if tooltip-mode "mouse-1: %s\nmouse-3: %s" "mouse-1: %s   mouse-3: %s") ivy-mouse-1-tooltip ivy-mouse-3-tooltip) read-only nil ws-butler-chg chg)))
  call-interactively(execute-extended-command nil nil)
  command-execute(execute-extended-command)
nickdrozd commented 4 years ago

This is a funny one. Here is what describe-function gives (after running (require 'help)):

help-command is a sparse keymap.

Prefix command (definition is a keymap associating keystrokes with commands).

According to the manual:

 -- Prefix Command: help-command
     This symbol is not a function; its function definition cell holds
     the keymap known as ‘help-map’.  It is defined in ‘help.el’ as
     follows:

          (define-key global-map (string help-char) 'help-command)
          (fset 'help-command help-map)
casouri commented 4 years ago

Indeed, but if describe-function does return the documentation, why would helpful error?

nickdrozd commented 4 years ago

The screw-up comes in helpful--signature, specifically around the handling of advertised-args. I don't know what the correct fix is. This is a pathological edge case. How does describe-function handle it?

casouri commented 4 years ago

Probably not a hard one. I think the problem is just nobody has the time to look into it...

Wilfred commented 4 years ago

It's not actually a function, it's a (obscure to me) way of handling prefix keys for key maps.

https://emacs.stackexchange.com/questions/28576/when-does-emacs-treat-keymaps-as-functions

https://emacs.stackexchange.com/questions/32754/what-does-fset-symbol-keymap-do

Helpful should support this though.

betaprior commented 4 years ago

This is not an isolated edge case. I just hit this exact same error in doom emacs calling M-x helpful-callable RET yas-expand RET. Looking up help for something as popular as yas-expand shouldn't blow up with an error. This really ought to be fixed.

Janfel commented 4 years ago

In the case of yas-expand, describe-function first produces the original function definition using (nth 3 (help-fns--analyze-function 'yas-expand)) before passing it to help-function-arglist. This will not automatically solve help-command though, as (nth 3 (help-fns--analyze-function 'yas-expand)) returns the keymap object instead of a function symbol.