Package: emacs;
Reported by: Mark Oteiza <mvoteiza <at> udel.edu>
Date: Mon, 28 Aug 2017 02:12:01 UTC
Severity: wishlist
Tags: patch
Found in version 26.0.50
Done: Lars Ingebrigtsen <larsi <at> gnus.org>
Bug is archived. No further changes may be made.
Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
From: Mark Oteiza <mvoteiza <at> udel.edu> To: bug-gnu-emacs <at> gnu.org Subject: 26.0.50; [PATCH] expose eldoc functions in a hook Date: Sun, 27 Aug 2017 22:10:57 -0400
Hi, This makes it possible to use the results from multiple eldoc functions at once, through the addition of an abnormal hook. I'm not aware of a good way to access the default value (or other local values) of eldoc-documentation-function when shadowed by a :before-until advice returning non-nil. Perhaps eldoc-documentation-function should remain a defvar, not sure. diff --git a/doc/emacs/programs.texi b/doc/emacs/programs.texi index 27ac0eb640..ea7f2f3d26 100644 --- a/doc/emacs/programs.texi +++ b/doc/emacs/programs.texi @@ -1279,9 +1279,27 @@ Lisp Doc for a function, it shows the argument list, and for a variable it shows the first line of the variable's documentation string. To toggle Eldoc mode, type @kbd{M-x eldoc-mode}. There's also a Global -Eldoc mode, which is turned on by default, and affects buffers, such -as @samp{*scratch*}, whose major mode is Emacs Lisp or Lisp -Interaction (@w{@kbd{M-x global-eldoc-mode}} to turn it off globally). +Eldoc mode, which is turned on by default, and affects buffers whose +major mode sets the variables described below. Use @w{@kbd{M-x +global-eldoc-mode}} to turn it off globally. + +@vindex eldoc-documentation-function +@vindex eldoc-documentation-functions + These variables can be used to configure ElDoc mode: + +@table @code +@item eldoc-documentation-function +This variable holds the function which is used to retrieve +documentation for the item at point from the functions in the hook +@code{eldoc-documentation-functions}. By default, +@code{eldoc-documentation-function} returns the first documentation +string produced by the @code{eldoc-documentation-functions} hook. + +@item eldoc-documentation-functions +This abnormal hook holds documentation functions. It acts as a +collection of backends for ElDoc. This is what modes should use to +register their documentation functions with ElDoc. +@end table @node Hideshow @section Hideshow minor mode diff --git a/etc/NEWS b/etc/NEWS index 3f38153048..b2dc06b137 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -791,6 +791,15 @@ breakpoint (e.g. with "f" and "o") by customizing the new option This allows to enlarge the maximum recursion depth when instrumenting code. +** ElDoc + +*** New hook 'eldoc-documentation-functions' to be used for registering +doc string functions. This makes the results of all doc string +functions accessible to the user through the existing single function hook +'eldoc-documentation-function'. + +*** 'eldoc-documentation-function' is now a custom variable. + ** Eshell *** 'eshell-input-filter's value is now a named function diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el index bca40ab87d..7d0ff0f359 100644 --- a/lisp/emacs-lisp/eldoc.el +++ b/lisp/emacs-lisp/eldoc.el @@ -41,9 +41,9 @@ ;; (add-hook 'ielm-mode-hook 'eldoc-mode) ;; (add-hook 'eval-expression-minibuffer-setup-hook 'eldoc-mode) -;; Major modes for other languages may use ElDoc by defining an -;; appropriate function as the buffer-local value of -;; `eldoc-documentation-function'. +;; Major modes for other languages may use ElDoc by adding an +;; appropriate function to the buffer-local value of +;; `eldoc-documentation-functions'. ;;; Code: @@ -222,7 +222,11 @@ turn-on-eldoc-mode (defun eldoc--supported-p () "Non-nil if an ElDoc function is set for this buffer." - (not (memq eldoc-documentation-function '(nil ignore)))) + (let ((hook 'eldoc-documentation-functions)) + (and eldoc-documentation-function + (or (and (local-variable-p hook) + (buffer-local-value hook (current-buffer))) + (default-value hook))))) (defun eldoc-schedule-timer () @@ -341,7 +345,47 @@ eldoc-display-message-no-interference-p ;;;###autoload -(defvar eldoc-documentation-function #'ignore +(defvar eldoc-documentation-functions nil + "Hook for functions to call to return doc string. +Each function should accept no arguments and return a one-line +string for displaying doc about a function etc. appropriate to +the context around point. It should return nil if there's no doc +appropriate for the context. Typically doc is returned if point +is on a function-like name or in its arg list. + +Major modes should modify this hook locally, for example: + (add-hook \\='eldoc-documentation-functions #\\='foo-mode-eldoc nil t) +so that the global value (i.e. the default value of the hook) is +taken into account if the major mode specific function does not +return any documentation.") + +(defun eldoc-documentation-default () + "Show doc string for item at point. +Default value for `eldoc-documentation-function'." + (let ((res (run-hook-with-args-until-success 'eldoc-documentation-functions))) + (when res + (if eldoc-echo-area-use-multiline-p res + (truncate-string-to-width + res (1- (window-width (minibuffer-window)))))))) + +(defun eldoc-documentation-compose () + "Show multiple doc string results at once. +Meant as a value for `eldoc-documentation-function'." + (let (res) + (run-hook-wrapped + 'eldoc-documentation-functions + (lambda (f) + (let ((str (funcall f))) + (when str (push str res)) + nil))) + (when res + (setq res (mapconcat #'identity (nreverse res) ", ")) + (if eldoc-echo-area-use-multiline-p res + (truncate-string-to-width + res (1- (window-width (minibuffer-window)))))))) + +;;;###autoload +(defcustom eldoc-documentation-function #'eldoc-documentation-default "Function to call to return doc string. The function of no args should return a one-line string for displaying doc about a function etc. appropriate to the context around point. @@ -352,14 +396,12 @@ eldoc-documentation-function The result is used as is, so the function must explicitly handle the variables `eldoc-argument-case' and `eldoc-echo-area-use-multiline-p', and the face `eldoc-highlight-function-argument', if they are to have any -effect. - -Major modes should modify this variable using `add-function', for example: - (add-function :before-until (local \\='eldoc-documentation-function) - #\\='foo-mode-eldoc-function) -so that the global documentation function (i.e. the default value of the -variable) is taken into account if the major mode specific function does not -return any documentation.") +effect." + :link '(info-link "(emacs) Lisp Doc") + :type '(radio (function-item eldoc-documentation-default) + (function-item eldoc-documentation-compose) + (function :tag "Other function")) + :group 'eldoc) (defun eldoc-print-current-symbol-info () "Print the text produced by `eldoc-documentation-function'." @@ -371,7 +413,8 @@ eldoc-print-current-symbol-info (when eldoc-last-message (eldoc-message nil) nil)) - (eldoc-message (funcall eldoc-documentation-function))))) + (let ((fun eldoc-documentation-function)) + (when fun (eldoc-message (funcall fun))))))) ;; If the entire line cannot fit in the echo area, the symbol name may be ;; truncated or eliminated entirely from the output to make room for the diff --git a/lisp/hexl.el b/lisp/hexl.el index 0a598b22f6..e1c5386c1a 100644 --- a/lisp/hexl.el +++ b/lisp/hexl.el @@ -395,8 +395,8 @@ hexl-mode (add-hook 'change-major-mode-hook 'hexl-maybe-dehexlify-buffer nil t) ;; Set a callback function for eldoc. - (add-function :before-until (local 'eldoc-documentation-function) - #'hexl-print-current-point-info) + (add-hook 'eldoc-documentation-functions + #'hexl-print-current-point-info nil t) (eldoc-add-command-completions "hexl-") (eldoc-remove-command "hexl-save-buffer" "hexl-current-address") @@ -506,6 +506,8 @@ hexl-mode-exit (remove-hook 'change-major-mode-hook 'hexl-maybe-dehexlify-buffer t) (remove-hook 'post-command-hook 'hexl-follow-ascii-find t) + (remove-hook 'eldoc-documentation-functions + #'hexl-print-current-point-info t) (setq hexl-ascii-overlay nil) (let ((mms ())) diff --git a/lisp/ielm.el b/lisp/ielm.el index 42b065fe62..3e8b8198f5 100644 --- a/lisp/ielm.el +++ b/lisp/ielm.el @@ -541,8 +541,8 @@ inferior-emacs-lisp-mode (set (make-local-variable 'completion-at-point-functions) '(comint-replace-by-expanded-history ielm-complete-filename elisp-completion-at-point)) - (add-function :before-until (local 'eldoc-documentation-function) - #'elisp-eldoc-documentation-function) + (add-hook 'eldoc-documentation-functions + #'elisp-eldoc-documentation-function nil t) (set (make-local-variable 'ielm-prompt-internal) ielm-prompt) (set (make-local-variable 'comint-prompt-read-only) ielm-prompt-read-only) (setq comint-get-old-input 'ielm-get-old-input) diff --git a/lisp/progmodes/cfengine.el b/lisp/progmodes/cfengine.el index 5bc7b66063..c775a18220 100644 --- a/lisp/progmodes/cfengine.el +++ b/lisp/progmodes/cfengine.el @@ -1390,12 +1390,15 @@ cfengine3-mode (when buffer-file-name (shell-quote-argument buffer-file-name))))) - ;; For emacs < 25.1 where `eldoc-documentation-function' defaults to - ;; nil. - (or eldoc-documentation-function - (setq-local eldoc-documentation-function #'ignore)) - (add-function :before-until (local 'eldoc-documentation-function) - #'cfengine3-documentation-function) + (if (> emacs-major-version 25) + (add-hook 'eldoc-documentation-functions + #'cfengine3-documentation-function nil t) + ;; For emacs < 25.1 where `eldoc-documentation-function' defaults + ;; to nil. + (or eldoc-documentation-function + (setq-local eldoc-documentation-function #'ignore)) + (add-function :before-until (local 'eldoc-documentation-function) + #'cfengine3-documentation-function)) (add-hook 'completion-at-point-functions #'cfengine3-completion-function nil t) diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index b3f452ca5b..07210381f3 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -235,8 +235,8 @@ emacs-lisp-mode (append '((?\` . ?\') (?‘ . ?’)) electric-pair-text-pairs)) (setq-local electric-quote-string t) (setq imenu-case-fold-search nil) - (add-function :before-until (local 'eldoc-documentation-function) - #'elisp-eldoc-documentation-function) + (add-hook 'eldoc-documentation-functions + #'elisp-eldoc-documentation-function nil t) (add-hook 'xref-backend-functions #'elisp--xref-backend nil t) (setq-local project-vc-external-roots-function #'elisp-load-path-roots) (add-hook 'completion-at-point-functions diff --git a/lisp/progmodes/octave.el b/lisp/progmodes/octave.el index ac9ba630c4..5843361dbd 100644 --- a/lisp/progmodes/octave.el +++ b/lisp/progmodes/octave.el @@ -596,8 +596,7 @@ octave-mode (add-hook 'before-save-hook 'octave-sync-function-file-names nil t) (setq-local beginning-of-defun-function 'octave-beginning-of-defun) (and octave-font-lock-texinfo-comment (octave-font-lock-texinfo-comment)) - (add-function :before-until (local 'eldoc-documentation-function) - 'octave-eldoc-function) + (add-hook 'eldoc-documentation-functions 'octave-eldoc-function nil t) (easy-menu-add octave-mode-menu)) diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 6f169123b9..8b4cfaa77a 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -5198,8 +5198,10 @@ python-mode ;; Emacs<25 (set (make-local-variable 'eldoc-documentation-function) #'python-eldoc-function) - (add-function :before-until (local 'eldoc-documentation-function) - #'python-eldoc-function)) + (if (< emacs-major-version 26) + (add-function :before-until (local 'eldoc-documentation-function) + #'python-eldoc-function) + (add-hook 'eldoc-documentation-functions #'python-eldoc-function nil t))) (add-to-list 'hs-special-modes-alist diff --git a/lisp/simple.el b/lisp/simple.el index 58f8372192..f56a505523 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -1490,8 +1490,8 @@ read--expression (minibuffer-with-setup-hook (lambda () ;; FIXME: call emacs-lisp-mode? - (add-function :before-until (local 'eldoc-documentation-function) - #'elisp-eldoc-documentation-function) + (add-hook 'eldoc-documentation-functions + #'elisp-eldoc-documentation-function nil t) (eldoc-mode 1) (add-hook 'completion-at-point-functions #'elisp-completion-at-point nil t)
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.