Popup Help In Emacs Lisp

If you use Clojure & Emacs, you probably use ac-nrepl-popup-doc to get the docs for the thing under the point, in a temporary popup window. And if you write any Elisp, you might be hankering for the same thing for Emacs' docs.

Here's some code that displays the same text as describe-function, but in a popup overlay:

(require 'popup)

(defun describe-function-in-popup ()
  (interactive)
  (let* ((thing (symbol-at-point))
         (description (save-window-excursion
                        (describe-function thing)
                        (switch-to-buffer "*Help*")
                        (buffer-string))))
    (popup-tip description
               :point (point)
               :around t
               :height 30
               :scroll-bar t
               :margin t)))

This code is actually fairly simple, so let's break it down:

symbol-at-point picks up the thing under the cursor, which should be the function you're hovering over.

The shenannigens inside save-window-excursion is just opening the regular describe-function window, snarfing its contents, and then closing it immediately. That puts the help text in description.

Then we just call popup-tip to display it. Here's a screenshot:

Popup Emacs Help

You'll probably want to set up your own favourite keybinding, but here's one example, binding it to M-5:

(global-set-key (kbd "M-5") 'describe-function-in-popup)

Update

Thanks to a comment from Steve Purcell, we can refine this to work for variables & faces, not just functions. The big change here is that we replace describe-function with help-xref-interned.

(defun describe-thing-in-popup ()
  (interactive)
  (let* ((thing (symbol-at-point))
         (help-xref-following t)
         (description (with-temp-buffer
                        (help-mode)
                        (help-xref-interned thing)
                        (buffer-string))))
    (popup-tip description
               :point (point)
               :around t
               :height 30
               :scroll-bar t
               :margin t)))

One of the nice things about this change is that help-xref lets us supply our own temporary buffer, instead of re-using *Help*. That means we don't clobber anything that's currently in your help buffer.

To take advantage of that, we just need to set help-xref-following to t, and put the temp buffer in help-mode.