1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-06 06:20:55 -08:00

ElDoc: rework rendering of echo area (bug#62029)

Previously, the display function 'eldoc-display-in-echo-area' reused
the same buffer as 'eldoc-display-in-doc-buffer', but that made it
harder to render documentation items differently depending on the
specific constraints of each display functions.

Allow documentation-generating backends to pass an :echo-area property
for tweaking the echo area display of certain documentation items.

* lisp/emacs-lisp/eldoc.el (eldoc-documentation-functions): Update docstring.
(eldoc--doc-buffer-docs): Remove.
(eldoc--format-doc-buffer): Simplify.
(eldoc--echo-area-render): New helper.
(eldoc-display-in-echo-area): Use 'eldoc--echo-area-render'.
This commit is contained in:
João Távora 2023-03-23 09:02:18 +00:00
parent 9b18407c7f
commit e19994fe8c

View file

@ -437,7 +437,7 @@ documentation-producing backend to cooperate with specific
documentation-displaying frontends. For example, KEY can be:
* `:thing', VALUE being a short string or symbol designating what
is being reported on. It can, for example be the name of the
DOCSTRING reports on. It can, for example be the name of the
function whose signature is being documented, or the name of
the variable whose docstring is being documented.
`eldoc-display-in-echo-area', a member of
@ -453,6 +453,11 @@ documentation-displaying frontends. For example, KEY can be:
originated. `eldoc-display-in-buffer' may use this organize the
documentation buffer accordingly.
* `:echo', controlling how `eldoc-display-in-echo-area' should
present this documentation item, to save space. If VALUE is
`skip' don't echo DOCSTRING. If a number, only echo DOCSTRING
up to that character position.
Finally, major modes should modify this hook locally, for
example:
(add-hook \\='eldoc-documentation-functions #\\='foo-mode-eldoc nil t)
@ -476,8 +481,6 @@ directly from the user or from ElDoc's automatic mechanisms'.")
(defvar eldoc--doc-buffer nil "Buffer displaying latest ElDoc-produced docs.")
(defvar eldoc--doc-buffer-docs nil "Documentation items in `eldoc--doc-buffer'.")
(defun eldoc-doc-buffer (&optional interactive)
"Get or display ElDoc documentation buffer.
@ -501,40 +504,56 @@ If INTERACTIVE, display it. Else, return said buffer."
eldoc--doc-buffer
(setq eldoc--doc-buffer
(get-buffer-create " *eldoc*")))
(unless (eq docs eldoc--doc-buffer-docs)
(setq-local eldoc--doc-buffer-docs docs)
(let ((inhibit-read-only t)
(things-reported-on))
(special-mode)
(erase-buffer)
(setq-local nobreak-char-display nil)
(cl-loop for (docs . rest) on docs
for (this-doc . plist) = docs
for thing = (plist-get plist :thing)
when thing do
(cl-pushnew thing things-reported-on)
(setq this-doc
(concat
(propertize (format "%s" thing)
'face (plist-get plist :face))
": "
this-doc))
do (insert this-doc)
when rest do (insert "\n")
finally (goto-char (point-min)))
;; Rename the buffer, taking into account whether it was
;; hidden or not
(rename-buffer (format "%s*eldoc%s*"
(if (string-match "^ " (buffer-name)) " " "")
(if things-reported-on
(format " for %s"
(mapconcat
(lambda (s) (format "%s" s))
things-reported-on
", "))
""))))))
(let ((inhibit-read-only t)
(things-reported-on))
(special-mode)
(erase-buffer)
(setq-local nobreak-char-display nil)
(cl-loop for (docs . rest) on docs
for (this-doc . plist) = docs
for thing = (plist-get plist :thing)
when thing do
(cl-pushnew thing things-reported-on)
(setq this-doc
(concat
(propertize (format "%s" thing)
'face (plist-get plist :face))
": "
this-doc))
do (insert this-doc)
when rest do (insert "\n")
finally (goto-char (point-min)))
;; Rename the buffer, taking into account whether it was
;; hidden or not
(rename-buffer (format "%s*eldoc%s*"
(if (string-match "^ " (buffer-name)) " " "")
(if things-reported-on
(format " for %s"
(mapconcat
(lambda (s) (format "%s" s))
things-reported-on
", "))
"")))))
eldoc--doc-buffer)
(defun eldoc--echo-area-render (docs)
"Similar to `eldoc--format-doc-buffer', but for echo area.
Helper for `eldoc-display-in-echo-area'."
(cl-loop for (item . rest) on docs
for (this-doc . plist) = item
for echo = (plist-get plist :echo)
for thing = (plist-get plist :thing)
unless (eq echo 'skip) do
(when echo (setq this-doc (substring this-doc 0 echo)))
(when thing (setq this-doc
(concat
(propertize (format "%s" thing)
'face (plist-get plist :face))
": "
this-doc)))
(insert this-doc)
(when rest (insert "\n"))))
(defun eldoc--echo-area-substring (available)
"Given AVAILABLE lines, get buffer substring to display in echo area.
Helper for `eldoc-display-in-echo-area'."
@ -620,15 +639,15 @@ Honor `eldoc-echo-area-use-multiline-p' and
single-doc)
((and (numberp available)
(cl-plusp available))
;; Else, given a positive number of logical lines, we
;; format the *eldoc* buffer, using as most of its
;; contents as we know will fit.
(with-current-buffer (eldoc--format-doc-buffer docs)
(save-excursion
(eldoc--echo-area-substring available))))
;; Else, given a positive number of logical lines, grab
;; as many as we can.
(with-temp-buffer
(eldoc--echo-area-render docs)
(eldoc--echo-area-substring available)))
(t ;; this is the "truncate brutally" situation
(let ((string
(with-current-buffer (eldoc--format-doc-buffer docs)
(with-temp-buffer
(eldoc--echo-area-render docs)
(buffer-substring (goto-char (point-min))
(progn (end-of-visible-line)
(point))))))