I want to bind a key which when pressed shows the documentation for an emacs lisp function, but as non-disruptive as possible. I want the contents of describe-function
but jumping directly to the docs for the symbol I'm at if there is an exact match and shown in a temporary popup, perhaps at the bottom of the screen, that goes away if any key is pressed.
2 Answers
I use eldoc, this screenshot shows the first line of concat
's docstring:
(define-advice elisp-get-fnsym-args-string (:around (orig-fun sym &rest r) docstring)
"If SYM is a function, append its docstring."
(concat
(apply orig-fun sym r)
(let* ((doc (and (fboundp sym) (documentation sym 'raw)))
(oneline (and doc (substring doc 0 (string-match "\n" doc)))))
(and oneline
(stringp oneline)
(not (string= "" oneline))
(concat " | " (propertize oneline 'face 'italic))))))
shown in a temporary popup
You can use tooltip (via the builtin tooltip-show
or the third party package pos-tip), or overlay (homemade or popup-tip
from the popup package, or child frame. I believe there also is a package for your purpose (it shows something like Microsoft Clippy alongside?), I can't remember.
-
That's a really neat addition to eldoc!
popup-tip
works well in terminal emacs, split on whether I like it or the echo area better.– RovanionMar 4, 2020 at 14:24
The user thblt@irc.freenode.net#emacs provided the following implementation of a function that shows the documentation in the echo area at the bottom of emacs:
(defun showdoc (f)
(interactive (list (thing-at-point 'symbol t)))
(message "%s: %s" f (documentation (intern f))))
I noticed that if the docstring was long, as for example with interactive, only the bottom part would be show; but it is often the top that is the most interesting. So I expanded on the function so that it would show the function signature at the top, and only show as many lines that fit in the echo area.
(defun elisp-showdoc (f)
(interactive (list (thing-at-point 'symbol t)))
(message
"%s"
(let* ((doc-list (split-string (documentation (intern f)) "\n"))
(number-lines (min (- (floor (* max-mini-window-height (frame-height))) 2)
(- (length doc-list) 2)))
(subset (concatenate 'list
(last doc-list)
'("")
(subseq doc-list 0 number-lines)))
(pruned-subset (if (string-equal (car (last subset)) "")
(butlast subset)
subset)))
(mapconcat #'identity pruned-subset "\n"))))