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.


I use eldoc, this screenshot shows the first line of concat's docstring:

shoing concat's docstring in eldoc

(define-advice elisp-get-fnsym-args-string (:around (orig-fun sym &rest r) docstring)
  "If SYM is a function, append its docstring."
   (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. – Rovanion Mar 4 '20 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)))
   (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)
     (mapconcat #'identity pruned-subset "\n"))))

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.