From a6ba9972ee0e3305c7b41fd380a88dd18a6626a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Mon, 25 May 2020 17:38:23 +0100 Subject: [PATCH 2/2] Adjust eldoc-documentation-functions protocol for better async Instead of exposing a eldoc-documentation-callback variable to clients, just pass it the callback as the first argument. * lisp/emacs-lisp/eldoc.el (eldoc-documentation-functions): Rewrite docstring. (eldoc-documentation-default, eldoc-documentation-compose): Use internal eldoc--callback. (eldoc-documentation-callback). (eldoc---callback): Rename from eldoc-documentation-callback. (eldoc-print-current-symbol-info): Bind eldoc--callback. * lisp/hexl.el (hexl-print-current-point-info): Adjust to new eldoc-documentation-functions protocol. * lisp/progmodes/cfengine.el (cfengine3-documentation-function): Adjust to new eldoc-documentation-functions protocol. * lisp/progmodes/elisp-mode.el (elisp-eldoc-documentation-function): Adjust to new eldoc-documentation-functions protocol. * lisp/progmodes/octave.el (octave-eldoc-function): Adjust to new eldoc-documentation-functions protocol. * lisp/progmodes/python.el (python-eldoc-function): Adjust to new eldoc-documentation-functions protocol. --- lisp/emacs-lisp/eldoc.el | 45 ++++++++++++++++++------------------ lisp/hexl.el | 2 +- lisp/progmodes/cfengine.el | 2 +- lisp/progmodes/elisp-mode.el | 6 +++-- lisp/progmodes/octave.el | 4 ++-- lisp/progmodes/python.el | 2 +- 6 files changed, 32 insertions(+), 29 deletions(-) diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el index f5dcdb4ea0..a4e1e460ac 100644 --- a/lisp/emacs-lisp/eldoc.el +++ b/lisp/emacs-lisp/eldoc.el @@ -339,22 +339,22 @@ eldoc-display-message-no-interference-p (defvar eldoc-documentation-functions nil "Hook of functions that produce doc strings. -Each hook function should accept no arguments and decide whether -to display a doc short string about the context around point. If -the decision and the doc string can be produced quickly, the hook -function should immediately return the doc string, or nil if -there's no doc appropriate for the context. Otherwise, if its -computation is expensive or can't be performed directly, the hook -function should save the value bound to -`eldoc-documentation-callback', and arrange for that callback -function to be asynchronously called at a later time, passing it -either nil or the desired doc string. The hook function should -then return a non-nil, non-string value. - -A current limitation of the asynchronous case is that it is only -guaranteed to work correctly if the value of -`eldoc-documentation-function' (notice the singular) is -`eldoc-documentation-default'. +Each hook function should accept at least one argument CALLBACK +and decide whether to display a doc short string about the +context around point. If the decision and the doc string can be +produced quickly, the hook function can ignore CALLBACK and +immediately return the doc string, or nil if there's no doc +appropriate for the context. Otherwise, if its computation is +expensive or can't be performed directly, the hook function +should arrange for CALLBACK to be asynchronously called at a +later time, passing it either nil or the desired doc string. The +hook function should then return a non-nil, non-string value. + +Note that this hook is only in effect if the value of +`eldoc-documentation-function' (notice the singular) is bound to +one of its pre-set values. Furthermore, the asynchronous +mechanism described above is only guaranteed to work correctly if +that value is `eldoc-documentation-default'. Typically doc is returned if point is on a function-like name or in its arg list. @@ -374,7 +374,9 @@ eldoc--handle-multiline (defun eldoc-documentation-default () "Show first doc string for item at point. Default value for `eldoc-documentation-function'." - (let ((res (run-hook-with-args-until-success 'eldoc-documentation-functions))) + (let ((res (run-hook-with-args-until-success + 'eldoc-documentation-functions + eldoc--callback))) (cond ((stringp res) (eldoc--handle-multiline res)) (t res)))) @@ -385,7 +387,7 @@ eldoc-documentation-compose (run-hook-wrapped 'eldoc-documentation-functions (lambda (f) - (let ((str (funcall f))) + (let ((str (funcall f eldoc--callback))) (when (stringp str) (push str res)) nil))) (when res @@ -426,9 +428,8 @@ eldoc--supported-p ;; this variable should be unbound, but that confuses ;; `describe-symbol' for some reason. -(defvar eldoc-documentation-callback nil - "Dynamically bound. Accessible to `eldoc-documentation-functions'. -See that function for details.") +(defvar eldoc---callback nil + "Dynamically bound. Passed to `eldoc-documentation-functions'.") (defun eldoc-print-current-symbol-info () "Print the text produced by `eldoc-documentation-function'." @@ -446,7 +447,7 @@ eldoc-print-current-symbol-info (while-no-input (let* ((waiting-for-callback nil) - (eldoc-documentation-callback + (eldoc--callback (lambda (string) (with-current-buffer buffer ;; JT@2020-05-25: Currently, we expect one single diff --git a/lisp/hexl.el b/lisp/hexl.el index cf7118f208..38eca77e26 100644 --- a/lisp/hexl.el +++ b/lisp/hexl.el @@ -515,7 +515,7 @@ hexl-current-address (message "Current address is %d/0x%08x" hexl-address hexl-address)) hexl-address)) -(defun hexl-print-current-point-info () +(defun hexl-print-current-point-info (&rest _ignored) "Return current hexl-address in string. This function is intended to be used as eldoc callback." (let ((addr (hexl-current-address))) diff --git a/lisp/progmodes/cfengine.el b/lisp/progmodes/cfengine.el index f25b3cb9e2..9a6d81ce06 100644 --- a/lisp/progmodes/cfengine.el +++ b/lisp/progmodes/cfengine.el @@ -1294,7 +1294,7 @@ cfengine3-make-syntax-cache 'symbols)) syntax))) -(defun cfengine3-documentation-function () +(defun cfengine3-documentation-function (&rest _ignored) "Document CFengine 3 functions around point. Intended as the value of `eldoc-documentation-function', which see. Use it by enabling `eldoc-mode'." diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index d37eb8c152..d7865a7319 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -1402,8 +1402,10 @@ elisp--eldoc-last-data or argument string for functions. 2 - `function' if function args, `variable' if variable documentation.") -(defun elisp-eldoc-documentation-function () - "`eldoc-documentation-function' (which see) for Emacs Lisp." +(defun elisp-eldoc-documentation-function (_ignored &rest _also-ignored) + "Contextual documentation function for Emacs Lisp. +Intended to be placed in `eldoc-documentation-functions' (which +see)." (let ((current-symbol (elisp--current-symbol)) (current-fnsym (elisp--fnsym-in-current-sexp))) (cond ((null current-fnsym) diff --git a/lisp/progmodes/octave.el b/lisp/progmodes/octave.el index 352c1810d1..2cf305c404 100644 --- a/lisp/progmodes/octave.el +++ b/lisp/progmodes/octave.el @@ -1639,8 +1639,8 @@ octave-eldoc-function-signatures (nreverse result))))) (cdr octave-eldoc-cache)) -(defun octave-eldoc-function () - "A function for `eldoc-documentation-function' (which see)." +(defun octave-eldoc-function (&rest _ignored) + "A function for `eldoc-documentation-functions' (which see)." (when (inferior-octave-process-live-p) (let* ((ppss (syntax-ppss)) (paren-pos (cadr ppss)) diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 1ca9f01963..404a67ba9f 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -4571,7 +4571,7 @@ python-eldoc-function-timeout-permanent :type 'boolean :version "25.1") -(defun python-eldoc-function () +(defun python-eldoc-function (&rest _ignored) "`eldoc-documentation-function' for Python. For this to work as best as possible you should call `python-shell-send-buffer' from time to time so context in -- 2.20.1