emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

feature/native-comp 5f13016 14/14: Merge remote-tracking branch 'savanna


From: Andrea Corallo
Subject: feature/native-comp 5f13016 14/14: Merge remote-tracking branch 'savannah/master' into wip2
Date: Thu, 9 Jul 2020 11:57:54 -0400 (EDT)

branch: feature/native-comp
commit 5f13016cedd245a7388ffafddffa20268afaf023
Merge: 02bf2e0 19cf8e5
Author: Andrea Corallo <akrl@sdf.org>
Commit: Andrea Corallo <akrl@sdf.org>

    Merge remote-tracking branch 'savannah/master' into wip2
---
 doc/emacs/programs.texi                 |  10 +-
 doc/lispref/modes.texi                  |   7 +-
 etc/NEWS                                |  27 +-
 lisp/cedet/semantic/grammar.el          |  45 ++-
 lisp/descr-text.el                      |  13 +-
 lisp/emacs-lisp/eldoc.el                | 508 ++++++++++++++++++++++++--------
 lisp/hexl.el                            |   2 +-
 lisp/progmodes/cc-engine.el             |   2 +-
 lisp/progmodes/cfengine.el              |  17 +-
 lisp/progmodes/elisp-mode.el            |  61 ++--
 lisp/progmodes/flymake.el               |  14 +-
 lisp/progmodes/octave.el                |   6 +-
 lisp/progmodes/python.el                |  20 +-
 src/fns.c                               |  14 +
 test/lisp/descr-text-tests.el           |   6 +-
 test/lisp/progmodes/elisp-mode-tests.el |   6 +-
 16 files changed, 551 insertions(+), 207 deletions(-)

diff --git a/doc/emacs/programs.texi b/doc/emacs/programs.texi
index 865a3a6..2757c84 100644
--- a/doc/emacs/programs.texi
+++ b/doc/emacs/programs.texi
@@ -1273,17 +1273,19 @@ 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-strategy
 @vindex eldoc-documentation-functions
   These variables can be used to configure ElDoc mode:
 
 @table @code
-@item eldoc-documentation-function
+@item eldoc-documentation-strategy
 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.
+@code{eldoc-documentation-strategy} returns the first documentation
+string produced by the @code{eldoc-documentation-functions} hook, but
+it may be customized to compose those functions' results in other
+ways.
 
 @item eldoc-documentation-functions
 This abnormal hook holds documentation functions.  It acts as a
diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi
index eaee56f..17e9607 100644
--- a/doc/lispref/modes.texi
+++ b/doc/lispref/modes.texi
@@ -469,9 +469,10 @@ variable @code{imenu-generic-expression}, for the two 
variables
 @code{imenu-create-index-function} (@pxref{Imenu}).
 
 @item
-The mode can specify a local value for
-@code{eldoc-documentation-function} to tell ElDoc mode how to handle
-this mode.
+The mode can tell Eldoc mode how to retrieve different types of
+documentation for whatever is at point, by adding one or more
+buffer-local entries to the special hook
+@code{eldoc-documentation-functions}.
 
 @item
 The mode can specify how to complete various keywords by adding one or
diff --git a/etc/NEWS b/etc/NEWS
index fc5c215..07403f2 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -247,14 +247,25 @@ supplied error message.
 +++
 ** 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 user option.
-Modes should use the new hook instead of this user option to register
-their backends.
+*** New hook 'eldoc-documentation-functions'.
+This hook is intended to be used for registering doc string functions.
+These functions don't need to produce the doc string right away, they
+may arrange for it to be produced asynchronously.  The results of all
+doc string functions are accessible to the user through the existing
+variable 'eldoc-documentation-strategy'.
+
+*** New user option 'eldoc-documentation-strategy'.
+The built-in choices available for this user option let users compose
+the results of 'eldoc-documentation-functions' in various ways, even
+if some of those functions are sychronous and some asynchchronous.
+The user option replaces 'eldoc-documentation-function', which is now
+obsolete.
+
+*** 'eldoc-echo-area-use-multiline-p' is now handled by ElDoc.
+The user option 'eldoc-echo-area-use-multiline-p' is now handled
+by the Eldoc library itself.  Functions in
+'eldoc-documentation-functions' don't need to worry about consulting
+it when producing a doc string.
 
 ** Eshell
 
diff --git a/lisp/cedet/semantic/grammar.el b/lisp/cedet/semantic/grammar.el
index 2c3b24b..1ed1833 100644
--- a/lisp/cedet/semantic/grammar.el
+++ b/lisp/cedet/semantic/grammar.el
@@ -1663,6 +1663,42 @@ Select the buffer containing the tag's definition, and 
move point there."
 
 (defvar semantic-grammar-eldoc-last-data (cons nil nil))
 
+(defun semantic--docstring-format-sym-doc (prefix doc &optional face)
+  "Combine PREFIX and DOC, and shorten the result to fit in the echo area.
+
+When PREFIX is a symbol, propertize its symbol name with FACE
+before combining it with DOC.  If FACE is not provided, just
+apply the nil face.
+
+See also: `eldoc-echo-area-use-multiline-p'."
+  ;; Hoisted from old `eldoc-docstring-format-sym-doc'.
+  ;; 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
+  ;; description.
+  (when (symbolp prefix)
+    (setq prefix (concat (propertize (symbol-name prefix) 'face face) ": ")))
+  (let* ((ea-multi eldoc-echo-area-use-multiline-p)
+         ;; Subtract 1 from window width since emacs will not write
+         ;; any chars to the last column, or in later versions, will
+         ;; cause a wraparound and resize of the echo area.
+         (ea-width (1- (window-width (minibuffer-window))))
+         (strip (- (+ (length prefix)
+                      (length doc))
+                   ea-width)))
+    (cond ((or (<= strip 0)
+               (eq ea-multi t)
+               (and ea-multi (> (length doc) ea-width)))
+           (concat prefix doc))
+          ((> (length doc) ea-width)
+           (substring (format "%s" doc) 0 ea-width))
+          ((>= strip (string-match-p ":? *\\'" prefix))
+           doc)
+          (t
+           ;; Show the end of the partial symbol name, rather
+           ;; than the beginning, since the former is more likely
+           ;; to be unique given package namespace conventions.
+           (concat (substring prefix strip) doc)))))
+
 (defun semantic-grammar-eldoc-get-macro-docstring (macro expander)
   "Return a one-line docstring for the given grammar MACRO.
 EXPANDER is the name of the function that expands MACRO."
@@ -1681,19 +1717,18 @@ EXPANDER is the name of the function that expands 
MACRO."
         (setq doc (eldoc-function-argstring expander))))
       (when doc
         (setq doc
-             (eldoc-docstring-format-sym-doc
+             (semantic--docstring-format-sym-doc
               macro (format "==> %s %s" expander doc) 'default))
         (setq semantic-grammar-eldoc-last-data (cons expander doc)))
       doc))
    ((fboundp 'elisp-get-fnsym-args-string) ;; Emacs≥25
-    (elisp-get-fnsym-args-string
-     expander nil
-     (concat (propertize (symbol-name macro)
+    (concat (propertize (symbol-name macro)
                          'face 'font-lock-keyword-face)
              " ==> "
              (propertize (symbol-name macro)
                          'face 'font-lock-function-name-face)
-             ": ")))))
+             ": "
+             (elisp-get-fnsym-args-string expander nil )))))
 
 (define-mode-local-override semantic-idle-summary-current-symbol-info
   semantic-grammar-mode ()
diff --git a/lisp/descr-text.el b/lisp/descr-text.el
index 1dbbd42..776ce76 100644
--- a/lisp/descr-text.el
+++ b/lisp/descr-text.el
@@ -919,7 +919,7 @@ condition, the function may return string longer than 
WIDTH, see
            (t name)))))))
 
 ;;;###autoload
-(defun describe-char-eldoc ()
+(defun describe-char-eldoc (_callback &rest _)
   "Return a description of character at point for use by ElDoc mode.
 
 Return nil if character at point is a printable ASCII
@@ -929,10 +929,17 @@ Otherwise return a description formatted by
 of `eldoc-echo-area-use-multiline-p' variable and width of
 minibuffer window for width limit.
 
-This function is meant to be used as a value of
-`eldoc-documentation-function' variable."
+This function can be used as a value of
+`eldoc-documentation-functions' variable."
   (let ((ch (following-char)))
     (when (and (not (zerop ch)) (or (< ch 32) (> ch 127)))
+      ;; TODO: investigate if the new `eldoc-documentation-functions'
+      ;; API could significantly improve this.  JT@2020-07-07: Indeed,
+      ;; instead of returning a string tailored here for the echo area
+      ;; exclusively, we could call the (now unused) argument
+      ;; _CALLBACK with hints on how to shorten the string if needed,
+      ;; or with multiple usable strings which Eldoc picks according
+      ;; to its space contraints.
       (describe-char-eldoc--format
        ch
        (unless (eq eldoc-echo-area-use-multiline-p t)
diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el
index ef5dbf8..9efd770 100644
--- a/lisp/emacs-lisp/eldoc.el
+++ b/lisp/emacs-lisp/eldoc.el
@@ -5,7 +5,7 @@
 ;; Author: Noah Friedman <friedman@splode.com>
 ;; Keywords: extensions
 ;; Created: 1995-10-06
-;; Version: 1.0.0
+;; Version: 1.1.0
 ;; Package-Requires: ((emacs "26.3"))
 
 ;; This is a GNU ELPA :core package.  Avoid functionality that is not
@@ -47,6 +47,8 @@
 
 ;;; Code:
 
+(eval-when-compile (require 'cl-lib))
+
 (defgroup eldoc nil
   "Show function arglist or variable docstring in echo area."
   :group 'lisp
@@ -77,38 +79,50 @@ Actually, any name of a function which takes a string as an 
argument and
 returns another string is acceptable.
 
 Note that this variable has no effect, unless
-`eldoc-documentation-function' handles it explicitly."
+`eldoc-documentation-strategy' handles it explicitly."
   :type '(radio (function-item upcase)
                (function-item downcase)
                 function))
 (make-obsolete-variable 'eldoc-argument-case nil "25.1")
 
 (defcustom eldoc-echo-area-use-multiline-p 'truncate-sym-name-if-fit
-  "Allow long ElDoc messages to resize echo area display.
-If value is t, never attempt to truncate messages; complete symbol name
-and function arglist or 1-line variable documentation will be displayed
-even if echo area must be resized to fit.
-
-If value is any non-nil value other than t, symbol name may be truncated
-if it will enable the function arglist or documentation string to fit on a
-single line without resizing window.  Otherwise, behavior is just like
-former case.
-
-If value is nil, messages are always truncated to fit in a single line of
-display in the echo area.  Function or variable symbol name may be
-truncated to make more of the arglist or documentation string visible.
-
-Note that this variable has no effect, unless
-`eldoc-documentation-function' handles it explicitly."
-  :type '(radio (const :tag "Always" t)
-                (const :tag "Never" nil)
-                (const :tag "Yes, but truncate symbol names if it will\
- enable argument list to fit on one line" truncate-sym-name-if-fit)))
+  "Allow long ElDoc doc strings to resize echo area display.
+If value is t, never attempt to truncate messages, even if the
+echo area must be resized to fit.
+
+If value is a number (integer or floating point), it has the
+semantics of `max-mini-window-height', constraining the resizing
+for Eldoc purposes only.
+
+Any resizing respects `max-mini-window-height'.
+
+If value is any non-nil symbol other than t, the part of the doc
+string that represents the symbol's name may be truncated if it
+will enable the rest of the doc string to fit on a single line,
+without resizing the echo area.
+
+If value is nil, a doc string is always truncated to fit in a
+single line of display in the echo area."
+  :type '(radio (const   :tag "Always" t)
+                (float   :tag "Fraction of frame height" 0.25)
+                (integer :tag "Number of lines" 5)
+                (const   :tag "Never" nil)
+                (const   :tag "Yes, but ask major-mode to truncate
+ symbol names if it will\ enable argument list to fit on one
+ line" truncate-sym-name-if-fit)))
+
+(defcustom eldoc-prefer-doc-buffer nil
+  "Prefer Eldoc's documentation buffer if it is showing in some frame.
+If this variable's value is t and a piece of documentation needs
+to be truncated to fit in the echo area, do so if Eldoc's
+documentation buffer is not already showing, since the buffer
+always holds the full documentation."
+  :type 'boolean)
 
 (defface eldoc-highlight-function-argument
   '((t (:inherit bold)))
   "Face used for the argument at point in a function's argument list.
-Note that this face has no effect unless the `eldoc-documentation-function'
+Note that this face has no effect unless the `eldoc-documentation-strategy'
 handles it explicitly.")
 
 ;;; No user options below here.
@@ -150,7 +164,7 @@ directly.  Instead, use `eldoc-add-command' and 
`eldoc-remove-command'.")
 This is used to determine if `eldoc-idle-delay' is changed by the user.")
 
 (defvar eldoc-message-function #'eldoc-minibuffer-message
-  "The function used by `eldoc-message' to display messages.
+  "The function used by `eldoc--message' to display messages.
 It should receive the same arguments as `message'.")
 
 (defun eldoc-edit-message-commands ()
@@ -203,7 +217,7 @@ expression point is on." :lighter eldoc-minor-mode-string
   :init-value t
   ;; For `read--expression', the usual global mode mechanism of
   ;; `change-major-mode-hook' runs in the minibuffer before
-  ;; `eldoc-documentation-function' is set, so `turn-on-eldoc-mode'
+  ;; `eldoc-documentation-strategy' is set, so `turn-on-eldoc-mode'
   ;; does nothing.  Configure and enable eldoc from
   ;; `eval-expression-minibuffer-setup-hook' instead.
   (if global-eldoc-mode
@@ -216,13 +230,16 @@ expression point is on." :lighter eldoc-minor-mode-string
   ;; Setup `eldoc', similar to `emacs-lisp-mode'.  FIXME: Call
   ;; `emacs-lisp-mode' itself?
   (add-hook 'eldoc-documentation-functions
-            #'elisp-eldoc-documentation-function nil t)
+            #'elisp-eldoc-var-docstring nil t)
+  (add-hook 'eldoc-documentation-functions
+            #'elisp-eldoc-funcall nil t)
+  (setq eldoc-documentation-strategy 'eldoc-documentation-default)
   (eldoc-mode +1))
 
 ;;;###autoload
 (defun turn-on-eldoc-mode ()
   "Turn on `eldoc-mode' if the buffer has ElDoc support enabled.
-See `eldoc-documentation-function' for more detail."
+See `eldoc-documentation-strategy' for more detail."
   (when (eldoc--supported-p)
     (eldoc-mode 1)))
 
@@ -241,7 +258,9 @@ reflect the change."
                (when (or eldoc-mode
                          (and global-eldoc-mode
                               (eldoc--supported-p)))
-                 (eldoc-print-current-symbol-info))))))
+                 ;; Don't ignore, but also don't full-on signal errors
+                 (with-demoted-errors "eldoc error: %s"
+                   (eldoc-print-current-symbol-info)) )))))
 
   ;; If user has changed the idle delay, update the timer.
   (cond ((not (= eldoc-idle-delay eldoc-current-idle-delay))
@@ -279,7 +298,10 @@ Otherwise work like `message'."
           (force-mode-line-update)))
     (apply #'message format-string args)))
 
-(defun eldoc-message (&optional string)
+(make-obsolete
+ 'eldoc-message "use `eldoc-documentation-functions' instead." "eldoc-1.1.0")
+(defun eldoc-message (&optional string) (eldoc--message string))
+(defun eldoc--message (&optional string)
   "Display STRING as an ElDoc message if it's non-nil.
 
 Also store it in `eldoc-last-message' and return that value."
@@ -313,8 +335,8 @@ Also store it in `eldoc-last-message' and return that 
value."
        (not (minibufferp))      ;We don't use the echo area when in minibuffer.
        (if (and (eldoc-display-message-no-interference-p)
                (eldoc--message-command-p this-command))
-          (eldoc-message eldoc-last-message)
-         ;; No need to call eldoc-message since the echo area will be cleared
+          (eldoc--message eldoc-last-message)
+         ;; No need to call eldoc--message since the echo area will be cleared
          ;; for us, but do note that the last-message will be gone.
          (setq eldoc-last-message nil))))
 
@@ -338,12 +360,39 @@ Also store it in `eldoc-last-message' and return that 
value."
 
 
 (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.
+  "Hook of functions that produce doc strings.
+
+A doc string is typically relevant if point is on a function-like
+name, inside its arg list, or on any object with some associated
+information.
+
+Each hook function is called with at least one argument CALLBACK,
+a function, and decides whether to display a doc short string
+about the context around point.
+
+- If that decision can be taken quickly, the hook function may
+  call CALLBACK immediately following the protocol described
+  berlow.  Alternatively it may ignore CALLBACK entirely and
+  return either the doc string, or nil if there's no doc
+  appropriate for the context.
+
+- If the computation of said doc string (or the decision whether
+  there is one at all) is expensive or can't be performed
+  directly, the hook function should return a non-nil, non-string
+  value and arrange for CALLBACK to be called at a later time,
+  using asynchronous processes or other asynchronous mechanisms.
+
+To call the CALLBACK function, the hook function must pass it an
+obligatory argument DOCSTRING, a string containing the
+documentation, followed by an optional list of keyword-value
+pairs of the form (:KEY VALUE :KEY2 VALUE2...).  KEY can be:
+
+* `:thing', VALUE is a short string or symbol designating what is
+  being reported on.  The documentation display engine can elect
+  to remove this information depending on space contraints;
+
+* `:face', VALUE is a symbol designating a face to use when
+  displaying `:thing''s value.
 
 Major modes should modify this hook locally, for example:
   (add-hook \\='eldoc-documentation-functions #\\='foo-mode-eldoc nil t)
@@ -351,110 +400,331 @@ 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.")
 
+(defvar eldoc--doc-buffer nil "Buffer holding latest eldoc-produced docs.")
+(defun eldoc-doc-buffer (&optional interactive)
+  "Get latest *eldoc* help buffer.  Interactively, display it."
+  (interactive (list t))
+  (prog1
+      (if (and eldoc--doc-buffer (buffer-live-p eldoc--doc-buffer))
+          eldoc--doc-buffer
+          (setq eldoc--doc-buffer (get-buffer-create "*eldoc*")))
+    (when interactive (display-buffer eldoc--doc-buffer))))
+
+(defun eldoc--handle-docs (docs)
+  "Display multiple DOCS in echo area.
+DOCS is a list of (STRING PLIST...).  It is already sorted.
+Honor most of `eldoc-echo-area-use-multiline-p'."
+  ;; If there's nothing to report clear the echo area, but don't erase
+  ;; the last *eldoc* buffer.
+  (if (null docs) (eldoc--message nil)
+    (let*
+        ;; Otherwise, establish some parameters.
+        ((width (1- (window-width (minibuffer-window))))
+         (val (if (and (symbolp eldoc-echo-area-use-multiline-p)
+                       eldoc-echo-area-use-multiline-p)
+                  max-mini-window-height
+                eldoc-echo-area-use-multiline-p))
+         (available (cl-typecase val
+                      (float (truncate (* (frame-height) val)))
+                      (integer val)
+                      (t 1)))
+         (things-reported-on)
+         single-sym-name)
+      ;; Then, compose the contents of the `*eldoc*' buffer.
+      (with-current-buffer (eldoc-doc-buffer)
+        (let ((inhibit-read-only t))
+          (erase-buffer) (setq buffer-read-only t)
+          (local-set-key "q" 'quit-window)
+          (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")))
+        ;; Rename the buffer.
+        (when things-reported-on
+          (rename-buffer (format "*eldoc for %s*"
+                                 (mapconcat (lambda (s) (format "%s" s))
+                                            things-reported-on
+                                            ", ")))))
+      ;; Finally, output to the echo area.  We handle the
+      ;; `truncate-sym-name-if-fit' special case first, by selecting a
+      ;; top-section of the `*eldoc' buffer.  I'm pretty sure nicer
+      ;; strategies can be used here, probably by splitting this
+      ;; function into some `eldoc-display-functions' special hook.
+      (if (and (eq 'truncate-sym-name-if-fit eldoc-echo-area-use-multiline-p)
+               (null (cdr docs))
+               (setq single-sym-name
+                     (format "%s" (plist-get (cdar docs) :thing)))
+               (> (+ (length (caar docs)) (length single-sym-name) 2) width))
+          (eldoc--message (caar docs))
+        (with-current-buffer (eldoc-doc-buffer)
+          (goto-char (point-min))
+          (cond
+           ;; Potentially truncate a long message into less lines,
+           ;; then display it in the echo area;
+           ((> available 1)
+            (cl-loop
+             initially (goto-char (line-end-position (1+ available)))
+             for truncated = nil then t
+             for needed
+             = (let ((truncate-lines message-truncate-lines))
+                 (count-screen-lines (point-min) (point) t 
(minibuffer-window)))
+             while (> needed (if truncated (1- available) available))
+             do (goto-char (line-end-position (if truncated 0 -1)))
+             (while (bolp) (goto-char (line-end-position 0)))
+             finally
+             (unless (and truncated
+                          eldoc-prefer-doc-buffer
+                          (get-buffer-window eldoc--doc-buffer))
+               (eldoc--message
+                (concat (buffer-substring (point-min) (point))
+                        (and truncated
+                             (format
+                              "\n(Documentation truncated. Use `%s' to see 
rest)"
+                              (substitute-command-keys 
"\\[eldoc-doc-buffer]"))))))))
+           ((= available 1)
+            ;; Truncate "brutally." ; FIXME: use `eldoc-prefer-doc-buffer' too?
+            (eldoc--message
+             (truncate-string-to-width
+              (buffer-substring (point-min) (line-end-position 1)) 
width)))))))))
+
 (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)))
-    (when res
-      (if eldoc-echo-area-use-multiline-p res
-        (truncate-string-to-width
-         res (1- (window-width (minibuffer-window))))))))
+Default value for `eldoc-documentation-strategy'."
+  (run-hook-with-args-until-success 'eldoc-documentation-functions
+                                    (eldoc--make-callback :patient)))
+
+(defun eldoc--documentation-compose-1 (eagerlyp)
+  "Helper function for composing multiple doc strings.
+If EAGERLYP is non-nil show documentation as soon as possible,
+else wait for all doc strings."
+  (run-hook-wrapped 'eldoc-documentation-functions
+                    (lambda (f)
+                      (let* ((callback (eldoc--make-callback
+                                        (if eagerlyp :eager :patient)))
+                             (str (funcall f callback)))
+                        (if (or (null str) (stringp str)) (funcall callback 
str))
+                        nil)))
+  t)
 
 (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))))))))
-
-(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.
-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.
-
-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."
+  "Show multiple doc strings at once after waiting for all.
+Meant as a value for `eldoc-documentation-strategy'."
+  (eldoc--documentation-compose-1 nil))
+
+(defun eldoc-documentation-compose-eagerly ()
+  "Show multiple doc strings at once as soon as possible.
+Meant as a value for `eldoc-documentation-strategy'."
+  (eldoc--documentation-compose-1 t))
+
+(defun eldoc-documentation-enthusiast ()
+  "Show most important doc string produced so far.
+Meant as a value for `eldoc-documentation-strategy'."
+  (run-hook-wrapped 'eldoc-documentation-functions
+                    (lambda (f)
+                      (let* ((callback (eldoc--make-callback :enthusiast))
+                             (str (funcall f callback)))
+                        (if (stringp str) (funcall callback str))
+                        nil))))
+
+(define-obsolete-variable-alias 'eldoc-documentation-function
+  'eldoc-documentation-strategy "eldoc-1.1.0")
+
+(defcustom eldoc-documentation-strategy #'eldoc-documentation-default
+  "How to collect and organize results of `eldoc-documentation-functions'.
+
+This variable controls how `eldoc-documentation-functions', which
+specifies the sources of documentation, is queried and how its
+results are organized before being displayed to the user.  The
+following values are allowed:
+
+- `eldoc-documentation-default': calls functions in the special
+  hook in order until one is found that produces a doc string
+  value.  Display only that value;
+
+- `eldoc-documentation-compose': calls all functions in the
+  special hook and displays all of the resulting doc strings
+  together.  Wait for all strings to be ready, and preserve their
+  relative as specified by the order of functions in the hook;
+
+- `eldoc-documentation-compose-eagerly': calls all functions in
+  the special hook and display as many of the resulting doc
+  strings as possible, as soon as possibl.  Preserving the
+  relative order of doc strings;
+
+- `eldoc-documentation-enthusiast': calls all functions in the
+  special hook and displays only the most important resulting
+  docstring one at any given time.  A function appearing first in
+  the special hook is considered more important.
+
+This variable can also be set to a function of no args that
+returns something other than a string or nil and allows for some
+or all of the special hook `eldoc-documentation-functions' to be
+run.  In that case, the strategy function should follow that
+other variable's protocol closely and endeavor to display the
+resulting doc strings itself.
+
+For backward compatibility to the \"old\" protocol, this variable
+can also be set to a function that returns nil or a doc string,
+depending whether or not there is documentation to display at
+all."
   :link '(info-link "(emacs) Lisp Doc")
   :type '(radio (function-item eldoc-documentation-default)
                 (function-item eldoc-documentation-compose)
+                (function-item eldoc-documentation-compose-eagerly)
+                (function-item eldoc-documentation-enthusiast)
                 (function :tag "Other function"))
   :version "28.1")
 
 (defun eldoc--supported-p ()
   "Non-nil if an ElDoc function is set for this buffer."
-  (and (not (memq eldoc-documentation-function '(nil ignore)))
+  (and (not (memq eldoc-documentation-strategy '(nil ignore)))
        (or eldoc-documentation-functions
            ;; The old API had major modes set `eldoc-documentation-function'
            ;; to provide eldoc support.  It's impossible now to determine
-           ;; reliably whether the `eldoc-documentation-function' provides
+           ;; reliably whether the `eldoc-documentation-strategy' provides
            ;; eldoc support (as in the old API) or whether it just provides
            ;; a way to combine the results of the
            ;; `eldoc-documentation-functions' (as in the new API).
            ;; But at least if it's set buffer-locally it's a good hint that
            ;; there's some eldoc support in the current buffer.
-           (local-variable-p 'eldoc-documentation-function))))
+           (local-variable-p 'eldoc-documentation-strategy))))
+
+(defvar eldoc--enthusiasm-curbing-timer nil
+  "Timer used by the `eldoc-documentation-enthusiast' strategy.
+When a doc string is encountered, it must endure a certain amount
+of time unchallenged until it is displayed to the user.  This
+prevents blinking if a lower priority docstring comes in shortly
+before a higher priority one.")
+
+(defalias 'eldoc #'eldoc-print-current-symbol-info)
+
+;; This variable should be unbound, but that confuses
+;; `describe-symbol' for some reason.
+(defvar eldoc--make-callback nil "Helper for function `eldoc--make-callback'.")
+
+;; JT@2020-07-08: the below docstring for the internal function
+;; `eldoc--invoke-strategy' could be moved to
+;; `eldoc-documentation-strategy' or thereabouts if/when we decide to
+;; extend or publish the `make-callback' protocol.
+(defun eldoc--make-callback (method)
+  "Make callback suitable for `eldoc-documentation-functions'.
+The return value is a function FN whose lambda list is (STRING
+&rest PLIST) and can be called by those functions.  Its
+responsibility is always to register the docstring STRING along
+with options specified in PLIST as the documentation to display
+for each particular situation.
+
+METHOD specifies how the callback behaves relative to other
+competing elements in `eldoc-documentation-functions'.  It can
+have the following values:
+
+- `:enthusiast' says to display STRING as soon as possible if
+  there's no higher priority doc string;
+
+- `:patient' says to display STRING along with all other
+   competing strings but only when all of all
+   `eldoc-documentation-functions' have been collected;
+
+- `:eager' says to display STRING along with all other competing
+  strings so far, as soon as possible."
+  (funcall eldoc--make-callback method))
+
+(defun eldoc--invoke-strategy ()
+  "Invoke `eldoc-documentation-strategy' function.
+
+That function's job is to run the `eldoc-documentation-functions'
+special hook, using the `run-hook' family of functions.  The way
+we invoke it here happens in a way strategy function can itself
+call `eldoc--make-callback' to produce values to give to the
+elements of the special hook `eldoc-documentation-functions'.
+
+For each element of `eldoc-documentation-functions' invoked a
+corresponding call to `eldoc--make-callback' must be made.  See
+docstring of `eldoc--make-callback' for the types of callback
+that can be produced.
+
+If the strategy function does not use `eldoc--make-callback', it
+must find some alternate way to produce callbacks to feed to
+`eldoc-documentation-function', and those callbacks should
+endeavour to display the docstrings given to them."
+  (let* (;; how many docstrings callbaks have been
+         (howmany 0)
+         ;; how many calls to callbacks we're waiting on. Used by
+         ;; `:patient'.
+         (want 0)
+         ;; how many doc strings and corresponding options have been
+         ;; registered it.
+         (docs-registered '()))
+          (cl-labels
+              ((register-doc (pos string plist)
+                (when (and string (> (length string) 0))
+                  (push (cons pos (cons string plist)) docs-registered)))
+               (display-doc ()
+                (eldoc--handle-docs
+                 (mapcar #'cdr
+                         (setq docs-registered
+                               (sort docs-registered
+                                     (lambda (a b) (< (car a) (car b))))))))
+               (make-callback (method)
+                (let ((pos (prog1 howmany (cl-incf howmany))))
+                  (cl-ecase method
+                    (:enthusiast
+                     (lambda (string &rest plist)
+                       (when (and string (cl-loop for (p) in docs-registered
+                                                  never (< p pos)))
+                         (setq docs-registered '())
+                         (register-doc pos string plist)
+                         (when (and (timerp eldoc--enthusiasm-curbing-timer)
+                                    (memq eldoc--enthusiasm-curbing-timer
+                                          timer-list))
+                           (cancel-timer eldoc--enthusiasm-curbing-timer))
+                         (setq eldoc--enthusiasm-curbing-timer
+                               (run-at-time (unless (zerop pos) 0.3)
+                                            nil #'display-doc)))
+                       t))
+                    (:patient
+                     (cl-incf want)
+                     (lambda (string &rest plist)
+                       (register-doc pos string plist)
+                       (when (zerop (cl-decf want)) (display-doc))
+                       t))
+                    (:eager
+                     (lambda (string &rest plist)
+                       (register-doc pos string plist)
+                       (display-doc)
+                       t))))))
+            (let* ((eldoc--make-callback #'make-callback)
+                   (res (funcall eldoc-documentation-strategy)))
+              ;; Observe the old and the new protocol:
+              (cond (;; Old protocol: got string, output immediately;
+                     (stringp res) (register-doc 0 res nil) (display-doc))
+                    (;; Old protocol: got nil, clear the echo area;
+                     (null res) (eldoc--message nil))
+                    (;; New protocol: trust callback will be called;
+                     t))))))
 
 (defun eldoc-print-current-symbol-info ()
-  "Print the text produced by `eldoc-documentation-function'."
-  ;; This is run from post-command-hook or some idle timer thing,
-  ;; so we need to be careful that errors aren't ignored.
-  (with-demoted-errors "eldoc error: %s"
-    (if (not (eldoc-display-message-p))
-        ;; Erase the last message if we won't display a new one.
-        (when eldoc-last-message
-          (eldoc-message nil))
-      (let ((non-essential t))
-        ;; Only keep looking for the info as long as the user hasn't
-        ;; requested our attention.  This also locally disables inhibit-quit.
-        (while-no-input
-          (eldoc-message (funcall eldoc-documentation-function)))))))
-
-;; 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
-;; description.
-(defun eldoc-docstring-format-sym-doc (prefix doc &optional face)
-  "Combine PREFIX and DOC, and shorten the result to fit in the echo area.
-
-When PREFIX is a symbol, propertize its symbol name with FACE
-before combining it with DOC.  If FACE is not provided, just
-apply the nil face.
-
-See also: `eldoc-echo-area-use-multiline-p'."
-  (when (symbolp prefix)
-    (setq prefix (concat (propertize (symbol-name prefix) 'face face) ": ")))
-  (let* ((ea-multi eldoc-echo-area-use-multiline-p)
-         ;; Subtract 1 from window width since emacs will not write
-         ;; any chars to the last column, or in later versions, will
-         ;; cause a wraparound and resize of the echo area.
-         (ea-width (1- (window-width (minibuffer-window))))
-         (strip (- (+ (length prefix) (length doc)) ea-width)))
-    (cond ((or (<= strip 0)
-               (eq ea-multi t)
-               (and ea-multi (> (length doc) ea-width)))
-           (concat prefix doc))
-          ((> (length doc) ea-width)
-           (substring (format "%s" doc) 0 ea-width))
-          ((>= strip (string-match-p ":? *\\'" prefix))
-           doc)
-          (t
-           ;; Show the end of the partial symbol name, rather
-           ;; than the beginning, since the former is more likely
-           ;; to be unique given package namespace conventions.
-           (concat (substring prefix strip) doc)))))
+  "Document thing at point."
+  (interactive)
+  (if (not (eldoc-display-message-p))
+      ;; Erase the last message if we won't display a new one.
+      (when eldoc-last-message
+        (eldoc--message nil))
+    (let ((non-essential t))
+      ;; Only keep looking for the info as long as the user hasn't
+      ;; requested our attention.  This also locally disables
+      ;; inhibit-quit.
+      (while-no-input
+        (eldoc--invoke-strategy)))))
 
 ;; When point is in a sexp, the function args are not reprinted in the echo
 ;; area after every possible interactive command because some of them print
diff --git a/lisp/hexl.el b/lisp/hexl.el
index cf7118f..38eca77 100644
--- a/lisp/hexl.el
+++ b/lisp/hexl.el
@@ -515,7 +515,7 @@ Ask the user for confirmation."
       (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/cc-engine.el b/lisp/progmodes/cc-engine.el
index 784a6c7..c3a98d9 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -1582,7 +1582,7 @@ comment at the start of cc-engine.el for more info."
          (save-excursion (backward-char)
                          (looking-at "\\s("))
          (c-crosses-statement-barrier-p (point) end)))))
-(make-obsolete 'c-at-expression-start-p nil "5.35")
+(make-obsolete 'c-at-expression-start-p nil "CC mode 5.35")
 
 
 ;; A set of functions that covers various idiosyncrasies in
diff --git a/lisp/progmodes/cfengine.el b/lisp/progmodes/cfengine.el
index f25b3cb..a8fe485 100644
--- a/lisp/progmodes/cfengine.el
+++ b/lisp/progmodes/cfengine.el
@@ -1294,10 +1294,10 @@ Calls `cfengine-cf-promises' with \"-s json\"."
                           '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'."
+Intended as the value of `eldoc-documentation-functions', which
+see.  Use it by enabling `eldoc-mode'."
   (let ((fdef (cfengine3--current-function)))
     (when fdef
       (cfengine3-format-function-docstring fdef))))
@@ -1390,15 +1390,8 @@ to the action header."
                  (when buffer-file-name
                    (shell-quote-argument buffer-file-name)))))
 
-  (if (boundp 'eldoc-documentation-functions)
-      (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 'eldoc-documentation-functions
+            #'cfengine3-documentation-function nil t)
 
   (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 8812c49..6df5411 100644
--- a/lisp/progmodes/elisp-mode.el
+++ b/lisp/progmodes/elisp-mode.el
@@ -280,7 +280,9 @@ Blank lines separate paragraphs.  Semicolons start comments.
                           electric-pair-text-pairs))
     (add-hook 'electric-pair-mode-hook #'emacs-lisp-set-electric-text-pairs))
   (add-hook 'eldoc-documentation-functions
-            #'elisp-eldoc-documentation-function nil t)
+            #'elisp-eldoc-var-docstring nil t)
+  (add-hook 'eldoc-documentation-functions
+            #'elisp-eldoc-funcall 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
@@ -1403,20 +1405,27 @@ which see."
       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."
-  (let ((current-symbol (elisp--current-symbol))
-       (current-fnsym  (elisp--fnsym-in-current-sexp)))
-    (cond ((null current-fnsym)
-          nil)
-         ((eq current-symbol (car current-fnsym))
-          (or (apply #'elisp-get-fnsym-args-string current-fnsym)
-              (elisp-get-var-docstring current-symbol)))
-         (t
-          (or (elisp-get-var-docstring current-symbol)
-              (apply #'elisp-get-fnsym-args-string current-fnsym))))))
-
-(defun elisp-get-fnsym-args-string (sym &optional index prefix)
+(defun elisp-eldoc-funcall (callback &rest _ignored)
+  "Document function call at point.
+Intended for `eldoc-documentation-functions' (which see)."
+  (let* ((sym-info (elisp--fnsym-in-current-sexp))
+         (fn-sym (car sym-info)))
+    (when fn-sym
+      (funcall callback (apply #'elisp-get-fnsym-args-string sym-info)
+               :thing fn-sym
+               :face (if (functionp fn-sym)
+                         'font-lock-function-name-face
+                       'font-lock-keyword-face)))))
+
+(defun elisp-eldoc-var-docstring (callback &rest _ignored)
+  "Document variable at point.
+Intended for `eldoc-documentation-functions' (which see)."
+  (let ((sym (elisp--current-symbol)))
+    (when sym (funcall callback (elisp-get-var-docstring sym)
+                       :thing sym
+                       :face 'font-lock-variable-name-face))))
+
+(defun elisp-get-fnsym-args-string (sym &optional index)
   "Return a string containing the parameter list of the function SYM.
 If SYM is a subr and no arglist is obtainable from the docstring
 or elsewhere, return a 1-line docstring."
@@ -1442,20 +1451,13 @@ or elsewhere, return a 1-line docstring."
              ;; Stringify, and store before highlighting, downcasing, etc.
             (elisp--last-data-store sym (elisp-function-argstring args)
                                      'function))))))
-    ;; Highlight, truncate.
+    ;; Highlight
     (if argstring
        (elisp--highlight-function-argument
-         sym argstring index
-         (or prefix
-             (concat (propertize (symbol-name sym) 'face
-                                 (if (functionp sym)
-                                     'font-lock-function-name-face
-                                   'font-lock-keyword-face))
-                     ": "))))))
-
-(defun elisp--highlight-function-argument (sym args index prefix)
-  "Highlight argument INDEX in ARGS list for function SYM.
-In the absence of INDEX, just call `eldoc-docstring-format-sym-doc'."
+         sym argstring index))))
+
+(defun elisp--highlight-function-argument (sym args index)
+  "Highlight argument INDEX in ARGS list for function SYM."
   ;; FIXME: This should probably work on the list representation of `args'
   ;; rather than its string representation.
   ;; FIXME: This function is much too long, we need to split it up!
@@ -1558,7 +1560,6 @@ In the absence of INDEX, just call 
`eldoc-docstring-format-sym-doc'."
       (when start
        (setq doc (copy-sequence args))
        (add-text-properties start end (list 'face argument-face) doc))
-      (setq doc (eldoc-docstring-format-sym-doc prefix doc))
       doc)))
 
 ;; Return a string containing a brief (one-line) documentation string for
@@ -1571,9 +1572,7 @@ In the absence of INDEX, just call 
`eldoc-docstring-format-sym-doc'."
         (t
          (let ((doc (documentation-property sym 'variable-documentation t)))
            (when doc
-             (let ((doc (eldoc-docstring-format-sym-doc
-                         sym (elisp--docstring-first-line doc)
-                         'font-lock-variable-name-face)))
+             (let ((doc (elisp--docstring-first-line doc)))
                (elisp--last-data-store sym doc 'variable)))))))
 
 (defun elisp--last-data-store (symbol doc type)
diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el
index 4ca5c65..37e7324 100644
--- a/lisp/progmodes/flymake.el
+++ b/lisp/progmodes/flymake.el
@@ -4,9 +4,9 @@
 
 ;; Author: Pavel Kobyakov <pk_at_work@yahoo.com>
 ;; Maintainer: João Távora <joaotavora@gmail.com>
-;; Version: 1.0.8
+;; Version: 1.0.9
 ;; Keywords: c languages tools
-;; Package-Requires: ((emacs "26.1"))
+;; Package-Requires: ((emacs "26.1") (eldoc "1.1.0"))
 
 ;; This is a GNU ELPA :core package.  Avoid functionality that is not
 ;; compatible with the version of Emacs recorded above.
@@ -1002,6 +1002,7 @@ special *Flymake log* buffer."  :group 'flymake :lighter
     (add-hook 'after-change-functions 'flymake-after-change-function nil t)
     (add-hook 'after-save-hook 'flymake-after-save-hook nil t)
     (add-hook 'kill-buffer-hook 'flymake-kill-buffer-hook nil t)
+    (add-hook 'eldoc-documentation-functions 'flymake-eldoc-function nil t)
 
     ;; If Flymake happened to be alrady already ON, we must cleanup
     ;; existing diagnostic overlays, lest we forget them by blindly
@@ -1019,6 +1020,7 @@ special *Flymake log* buffer."  :group 'flymake :lighter
     (remove-hook 'after-save-hook 'flymake-after-save-hook t)
     (remove-hook 'kill-buffer-hook 'flymake-kill-buffer-hook t)
     ;;+(remove-hook 'find-file-hook (function flymake-find-file-hook) t)
+    (remove-hook 'eldoc-documentation-functions 'flymake-eldoc-function t)
 
     (mapc #'delete-overlay (flymake--overlays))
 
@@ -1086,6 +1088,14 @@ START and STOP and LEN are as in 
`after-change-functions'."
     (flymake-mode)
     (flymake-log :warning "Turned on in `flymake-find-file-hook'")))
 
+(defun flymake-eldoc-function (report-doc &rest _)
+  "Document diagnostics at point.
+Intended for `eldoc-documentation-functions' (which see)."
+  (let ((diags (flymake-diagnostics (point))))
+    (when diags
+      (funcall report-doc
+               (mapconcat #'flymake-diagnostic-text diags "\n")))))
+
 (defun flymake-goto-next-error (&optional n filter interactive)
   "Go to Nth next Flymake diagnostic that matches FILTER.
 Interactively, always move to the next diagnostic.  With a prefix
diff --git a/lisp/progmodes/octave.el b/lisp/progmodes/octave.el
index 352c181..e07f818 100644
--- a/lisp/progmodes/octave.el
+++ b/lisp/progmodes/octave.el
@@ -755,7 +755,7 @@ Key bindings:
   (setq font-lock-defaults '(inferior-octave-font-lock-keywords nil nil))
 
   (setq-local info-lookup-mode 'octave-mode)
-  (setq-local eldoc-documentation-function 'octave-eldoc-function)
+  (add-hook 'eldoc-documentation-functions 'octave-eldoc-function nil t)
 
   (setq-local comint-input-ring-file-name
               (or (getenv "OCTAVE_HISTFILE") "~/.octave_hist"))
@@ -1639,8 +1639,8 @@ code line."
                   (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 22248f0..165463a 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -4573,7 +4573,7 @@ returns will be used.  If not FORCE-PROCESS is passed what
   :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
@@ -5553,14 +5553,16 @@ REPORT-FN is Flymake's callback function."
                                                  (current-column))))
          (^ '(- (1+ (current-indentation))))))
 
-  (if (null eldoc-documentation-function)
-      ;; Emacs<25
-      (set (make-local-variable 'eldoc-documentation-function)
-           #'python-eldoc-function)
-    (if (boundp 'eldoc-documentation-functions)
-        (add-hook 'eldoc-documentation-functions #'python-eldoc-function nil t)
-      (add-function :before-until (local 'eldoc-documentation-function)
-                    #'python-eldoc-function)))
+  (with-no-warnings
+    ;; supress warnings about eldoc-documentation-function being obsolete
+   (if (null eldoc-documentation-function)
+       ;; Emacs<25
+       (set (make-local-variable 'eldoc-documentation-function)
+            #'python-eldoc-function)
+     (if (boundp 'eldoc-documentation-functions)
+         (add-hook 'eldoc-documentation-functions #'python-eldoc-function nil 
t)
+       (add-function :before-until (local 'eldoc-documentation-function)
+                     #'python-eldoc-function))))
 
   (add-to-list
    'hs-special-modes-alist
diff --git a/src/fns.c b/src/fns.c
index a95a4b6..811d6e8 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -1530,11 +1530,21 @@ same_float (Lisp_Object x, Lisp_Object y)
   return !neql;
 }
 
+/* True if X can be compared using `eq'.
+   This predicate is approximative, for maximum speed.  */
+static bool
+eq_comparable_value (Lisp_Object x)
+{
+  return SYMBOLP (x) || FIXNUMP (x);
+}
+
 DEFUN ("member", Fmember, Smember, 2, 2, 0,
        doc: /* Return non-nil if ELT is an element of LIST.  Comparison done 
with `equal'.
 The value is actually the tail of LIST whose car is ELT.  */)
   (Lisp_Object elt, Lisp_Object list)
 {
+  if (eq_comparable_value (elt))
+    return Fmemq (elt, list);
   Lisp_Object tail = list;
   FOR_EACH_TAIL (tail)
     if (! NILP (Fequal (elt, XCAR (tail))))
@@ -1622,6 +1632,8 @@ The value is actually the first element of ALIST whose 
car equals KEY.
 Equality is defined by TESTFN if non-nil or by `equal' if nil.  */)
      (Lisp_Object key, Lisp_Object alist, Lisp_Object testfn)
 {
+  if (eq_comparable_value (key) && NILP (testfn))
+    return Fassq (key, alist);
   Lisp_Object tail = alist;
   FOR_EACH_TAIL (tail)
     {
@@ -1672,6 +1684,8 @@ DEFUN ("rassoc", Frassoc, Srassoc, 2, 2, 0,
 The value is actually the first element of ALIST whose cdr equals KEY.  */)
   (Lisp_Object key, Lisp_Object alist)
 {
+  if (eq_comparable_value (key))
+    return Frassq (key, alist);
   Lisp_Object tail = alist;
   FOR_EACH_TAIL (tail)
     {
diff --git a/test/lisp/descr-text-tests.el b/test/lisp/descr-text-tests.el
index 74fcdf5..b060dff 100644
--- a/test/lisp/descr-text-tests.el
+++ b/test/lisp/descr-text-tests.el
@@ -75,18 +75,18 @@
     (goto-char (point-min))
     (should (eq ?a (following-char))) ; make sure we are where we think we are
     ;; Function should return nil for an ASCII character.
-    (should (not (describe-char-eldoc)))
+    (should (not (describe-char-eldoc 'ignore)))
 
     (goto-char (1+ (point)))
     (should (eq ?… (following-char)))
     (let ((eldoc-echo-area-use-multiline-p t))
       ;; Function should return description of an Unicode character.
       (should (equal "U+2026: Horizontal ellipsis (Po: Punctuation, Other)"
-                     (describe-char-eldoc))))
+                     (describe-char-eldoc 'ignore))))
 
     (goto-char (point-max))
     ;; At the end of the buffer, function should return nil and not blow up.
-    (should (not (describe-char-eldoc)))))
+    (should (not (describe-char-eldoc 'ignore)))))
 
 
 (provide 'descr-text-test)
diff --git a/test/lisp/progmodes/elisp-mode-tests.el 
b/test/lisp/progmodes/elisp-mode-tests.el
index 2ba0065..2de533e 100644
--- a/test/lisp/progmodes/elisp-mode-tests.el
+++ b/test/lisp/progmodes/elisp-mode-tests.el
@@ -194,7 +194,7 @@
   (dotimes (i 3)
     (should
      (equal (elisp-mode-tests--face-propertized-string
-             (elisp--highlight-function-argument 'foo "(A B C)" (1+ i) "foo: 
"))
+             (elisp--highlight-function-argument 'foo "(A B C)" (1+ i)))
             (propertize (nth i '("A" "B" "C"))
                         'face 'eldoc-highlight-function-argument)))))
 
@@ -206,7 +206,7 @@
     (cl-flet ((bold-arg (i)
                (elisp-mode-tests--face-propertized-string
                 (elisp--highlight-function-argument
-                 'foo "(PROMPT LST &key A B C)" i "foo: "))))
+                 'foo "(PROMPT LST &key A B C)" i))))
       (should-not (bold-arg 0))
       (progn (forward-sexp) (forward-char))
       (should (equal (bold-arg 1) "PROMPT"))
@@ -226,7 +226,7 @@
     (cl-flet ((bold-arg (i)
                (elisp-mode-tests--face-propertized-string
                 (elisp--highlight-function-argument
-                 'foo "(X &key A B C)" i "foo: "))))
+                 'foo "(X &key A B C)" i))))
       (should-not (bold-arg 0))
       ;; The `:b' specifies positional arg `X'.
       (progn (forward-sexp) (forward-char))



reply via email to

[Prev in Thread] Current Thread [Next in Thread]