]> code.delx.au - gnu-emacs/blobdiff - lisp/emacs-lisp/eldoc.el
Replace eldoc-documentation-function with a hook
[gnu-emacs] / lisp / emacs-lisp / eldoc.el
index d527d676d5192a8dca5294dce23e301d001ff8bf..5cc16a864748ddaad7eeaf8dbc4d76d9429df395 100644 (file)
@@ -1,6 +1,6 @@
 ;;; eldoc.el --- Show function arglist or variable docstring in echo area  -*- lexical-binding:t; -*-
 
-;; Copyright (C) 1996-2015 Free Software Foundation, Inc.
+;; Copyright (C) 1996-2016 Free Software Foundation, Inc.
 
 ;; Author: Noah Friedman <friedman@splode.com>
 ;; Maintainer: friedman@splode.com
@@ -43,7 +43,7 @@
 
 ;; Major modes for other languages may use ElDoc by defining an
 ;; appropriate function as the buffer-local value of
-;; `eldoc-documentation-function'.
+;; `eldoc-documentation-functions'.
 
 ;;; Code:
 
@@ -80,7 +80,7 @@ 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-functions' handle it explicitly."
   :type '(radio (function-item upcase)
                (function-item downcase)
                 function)
@@ -103,7 +103,7 @@ 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."
+`eldoc-documentation-functions' handle it explicitly."
   :type '(radio (const :tag "Always" t)
                 (const :tag "Never" nil)
                 (const :tag "Yes, but truncate symbol names if it will\
@@ -113,8 +113,8 @@ Note that this variable has no effect, unless
 (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'
-handles it explicitly."
+Note that this face has no effect unless the `eldoc-documentation-functions'
+handle it explicitly."
   :group 'eldoc)
 
 ;;; No user options below here.
@@ -186,7 +186,7 @@ expression point is on."
   :group 'eldoc :lighter eldoc-minor-mode-string
   (setq eldoc-last-message nil)
   (cond
-   ((memq eldoc-documentation-function '(nil ignore))
+   ((not (eldoc-supported-p))
     (message "There is no ElDoc support in this buffer")
     (setq eldoc-mode nil))
    (eldoc-mode
@@ -197,12 +197,23 @@ expression point is on."
    (t
     (kill-local-variable 'eldoc-message-commands)
     (remove-hook 'post-command-hook 'eldoc-schedule-timer t)
-    (remove-hook 'pre-command-hook 'eldoc-pre-command-refresh-echo-area t))))
+    (remove-hook 'pre-command-hook 'eldoc-pre-command-refresh-echo-area t)
+    (when eldoc-timer
+      (cancel-timer eldoc-timer)
+      (setq eldoc-timer nil)))))
 
 ;;;###autoload
 (define-minor-mode global-eldoc-mode
-  "Enable `eldoc-mode' in all buffers where it's applicable."
-  :group 'eldoc :global t
+  "Toggle Global Eldoc mode on or off.
+With a prefix argument ARG, enable Global Eldoc mode if ARG is
+positive, and disable it otherwise.  If called from Lisp, enable
+the mode if ARG is omitted or nil, and toggle it if ARG is ‘toggle’.
+
+If Global Eldoc mode is on, `eldoc-mode' will be enabled in all
+buffers where it's applicable.  These are buffers that have modes
+that have enabled eldoc support.  See `eldoc-documentation-functions'."
+  :group 'eldoc
+  :global t
   :initialize 'custom-initialize-delay
   :init-value t
   (setq eldoc-last-message nil)
@@ -222,12 +233,10 @@ expression point is on."
            (memq eldoc-timer timer-idle-list)) ;FIXME: Why?
       (setq eldoc-timer
             (run-with-idle-timer
-            eldoc-idle-delay t
+            eldoc-idle-delay nil
             (lambda ()
                (when (or eldoc-mode
-                         (and global-eldoc-mode
-                              (not (memq eldoc-documentation-function
-                                         '(nil ignore)))))
+                         (and global-eldoc-mode (eldoc-supported-p)))
                  (eldoc-print-current-symbol-info))))))
 
   ;; If user has changed the idle delay, update the timer.
@@ -261,7 +270,7 @@ Otherwise work like `message'."
                        mode-line-format)))
           (setq eldoc-mode-line-string
                 (when (stringp format-string)
-                  (apply 'format format-string args)))
+                  (apply #'format-message format-string args)))
           (force-mode-line-update)))
     (apply 'message format-string args)))
 
@@ -274,7 +283,7 @@ Otherwise work like `message'."
                ;; eldoc-last-message so eq test above might succeed on
                ;; subsequent calls.
                ((null (cdr args)) (car args))
-               (t (apply 'format args))))
+               (t (apply #'format-message args))))
     ;; In emacs 19.29 and later, and XEmacs 19.13 and later, all messages
     ;; are recorded in a log.  Do not put eldoc messages in that log since
     ;; they are Legion.
@@ -323,10 +332,11 @@ Otherwise work like `message'."
 
 \f
 ;;;###autoload
-(defvar eldoc-documentation-function #'ignore
-  "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.
+(defvar eldoc-documentation-functions #'ignore
+  "Hook to run to return doc string.
+A function in this hook should accept no args and return a
+one-line string for displaying documentation of a function,
+variable, 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.
@@ -336,13 +346,15 @@ 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)
+Major modes should modify this variable using `add-hook', for example:
+  (add-hook \\='eldoc-documentation-functions #\\='foo-eldoc nil t)
 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.")
 
+(define-obsolete-variable-alias 'eldoc-documentation-function
+  'eldoc-documentation-functions "25.2")
+
 (defun eldoc-print-current-symbol-info ()
   ;; This is run from post-command-hook or some idle timer thing,
   ;; so we need to be careful that errors aren't ignored.
@@ -352,9 +364,47 @@ return any documentation.")
              (when eldoc-last-message
                (eldoc-message nil)
                nil))
-        (eldoc-message (funcall eldoc-documentation-function)))))
+        (eldoc-message
+          (run-hook-with-args-until-success 'eldoc-documentation-functions)))))
+
+(defun eldoc-supported-p ()
+  "Return t if `eldoc-documentation-functions' has non-null elements."
+  (if (listp eldoc-documentation-functions)
+      (catch :eldoc-supported
+        (mapc
+         (lambda (fun)
+           (when (not (memq fun '(nil ignore)))
+             (throw :eldoc-supported t)))
+         eldoc-documentation-functions)
+        nil)
+    (not (memq eldoc-documentation-functions '(nil ignore)))))
+
+;; 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)
+  (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)))))
 
-\f
 ;; 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
 ;; their own messages in the echo area; the eldoc functions would instantly
@@ -385,6 +435,7 @@ return any documentation.")
 \f
 ;; Prime the command list.
 (eldoc-add-command-completions
+ "back-to-indentation"
  "backward-" "beginning-of-" "delete-other-windows" "delete-window"
  "down-list" "end-of-" "exchange-point-and-mark" "forward-" "goto-"
  "handle-select-window" "indent-for-tab-command" "left-" "mark-page"