Line data Source code
1 : ;;; eldoc.el --- Show function arglist or variable docstring in echo area -*- lexical-binding:t; -*-
2 :
3 : ;; Copyright (C) 1996-2017 Free Software Foundation, Inc.
4 :
5 : ;; Author: Noah Friedman <friedman@splode.com>
6 : ;; Maintainer: friedman@splode.com
7 : ;; Keywords: extensions
8 : ;; Created: 1995-10-06
9 :
10 : ;; This file is part of GNU Emacs.
11 :
12 : ;; GNU Emacs is free software: you can redistribute it and/or modify
13 : ;; it under the terms of the GNU General Public License as published by
14 : ;; the Free Software Foundation, either version 3 of the License, or
15 : ;; (at your option) any later version.
16 :
17 : ;; GNU Emacs is distributed in the hope that it will be useful,
18 : ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 : ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 : ;; GNU General Public License for more details.
21 :
22 : ;; You should have received a copy of the GNU General Public License
23 : ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
24 :
25 : ;;; Commentary:
26 :
27 : ;; This program was inspired by the behavior of the "mouse documentation
28 : ;; window" on many Lisp Machine systems; as you type a function's symbol
29 : ;; name as part of a sexp, it will print the argument list for that
30 : ;; function. Behavior is not identical; for example, you need not actually
31 : ;; type the function name, you need only move point around in a sexp that
32 : ;; calls it. Also, if point is over a documented variable, it will print
33 : ;; the one-line documentation for that variable instead, to remind you of
34 : ;; that variable's meaning.
35 :
36 : ;; One useful way to enable this minor mode is to put the following in your
37 : ;; .emacs:
38 : ;;
39 : ;; (add-hook 'emacs-lisp-mode-hook 'eldoc-mode)
40 : ;; (add-hook 'lisp-interaction-mode-hook 'eldoc-mode)
41 : ;; (add-hook 'ielm-mode-hook 'eldoc-mode)
42 : ;; (add-hook 'eval-expression-minibuffer-setup-hook 'eldoc-mode)
43 :
44 : ;; Major modes for other languages may use ElDoc by defining an
45 : ;; appropriate function as the buffer-local value of
46 : ;; `eldoc-documentation-function'.
47 :
48 : ;;; Code:
49 :
50 : (defgroup eldoc nil
51 : "Show function arglist or variable docstring in echo area."
52 : :group 'lisp
53 : :group 'extensions)
54 :
55 : (defcustom eldoc-idle-delay 0.50
56 : "Number of seconds of idle time to wait before printing.
57 : If user input arrives before this interval of time has elapsed after the
58 : last input, no documentation will be printed.
59 :
60 : If this variable is set to 0, no idle time is required."
61 : :type 'number
62 : :group 'eldoc)
63 :
64 : (defcustom eldoc-print-after-edit nil
65 : "If non-nil eldoc info is only shown when editing.
66 : Changing the value requires toggling `eldoc-mode'."
67 : :type 'boolean
68 : :group 'eldoc)
69 :
70 : ;;;###autoload
71 : (defcustom eldoc-minor-mode-string (purecopy " ElDoc")
72 : "String to display in mode line when ElDoc Mode is enabled; nil for none."
73 : :type '(choice string (const :tag "None" nil))
74 : :group 'eldoc)
75 :
76 : (defcustom eldoc-argument-case #'identity
77 : "Case to display argument names of functions, as a symbol.
78 : This has two preferred values: `upcase' or `downcase'.
79 : Actually, any name of a function which takes a string as an argument and
80 : returns another string is acceptable.
81 :
82 : Note that this variable has no effect, unless
83 : `eldoc-documentation-function' handles it explicitly."
84 : :type '(radio (function-item upcase)
85 : (function-item downcase)
86 : function)
87 : :group 'eldoc)
88 : (make-obsolete-variable 'eldoc-argument-case nil "25.1")
89 :
90 : (defcustom eldoc-echo-area-use-multiline-p 'truncate-sym-name-if-fit
91 : "Allow long ElDoc messages to resize echo area display.
92 : If value is t, never attempt to truncate messages; complete symbol name
93 : and function arglist or 1-line variable documentation will be displayed
94 : even if echo area must be resized to fit.
95 :
96 : If value is any non-nil value other than t, symbol name may be truncated
97 : if it will enable the function arglist or documentation string to fit on a
98 : single line without resizing window. Otherwise, behavior is just like
99 : former case.
100 :
101 : If value is nil, messages are always truncated to fit in a single line of
102 : display in the echo area. Function or variable symbol name may be
103 : truncated to make more of the arglist or documentation string visible.
104 :
105 : Note that this variable has no effect, unless
106 : `eldoc-documentation-function' handles it explicitly."
107 : :type '(radio (const :tag "Always" t)
108 : (const :tag "Never" nil)
109 : (const :tag "Yes, but truncate symbol names if it will\
110 : enable argument list to fit on one line" truncate-sym-name-if-fit))
111 : :group 'eldoc)
112 :
113 : (defface eldoc-highlight-function-argument
114 : '((t (:inherit bold)))
115 : "Face used for the argument at point in a function's argument list.
116 : Note that this face has no effect unless the `eldoc-documentation-function'
117 : handles it explicitly."
118 : :group 'eldoc)
119 :
120 : ;;; No user options below here.
121 :
122 : (defvar eldoc-message-commands-table-size 31
123 : "Used by `eldoc-add-command' to initialize `eldoc-message-commands' obarray.
124 : It should probably never be necessary to do so, but if you
125 : choose to increase the number of buckets, you must do so before loading
126 : this file since the obarray is initialized at load time.
127 : Remember to keep it a prime number to improve hash performance.")
128 :
129 : (defvar eldoc-message-commands
130 : ;; Don't define as `defconst' since it would then go to (read-only) purespace.
131 : (make-vector eldoc-message-commands-table-size 0)
132 : "Commands after which it is appropriate to print in the echo area.
133 : ElDoc does not try to print function arglists, etc., after just any command,
134 : because some commands print their own messages in the echo area and these
135 : functions would instantly overwrite them. But `self-insert-command' as well
136 : as most motion commands are good candidates.
137 : This variable contains an obarray of symbols; do not manipulate it
138 : directly. Instead, use `eldoc-add-command' and `eldoc-remove-command'.")
139 :
140 : ;; Not a constant.
141 : (defvar eldoc-last-data (make-vector 3 nil)
142 : ;; Don't define as `defconst' since it would then go to (read-only) purespace.
143 : "Bookkeeping; elements are as follows:
144 : 0 - contains the last symbol read from the buffer.
145 : 1 - contains the string last displayed in the echo area for variables,
146 : or argument string for functions.
147 : 2 - `function' if function args, `variable' if variable documentation.")
148 : (make-obsolete-variable 'eldoc-last-data "use your own instead" "25.1")
149 :
150 : (defvar eldoc-last-message nil)
151 :
152 : (defvar eldoc-timer nil "ElDoc's timer object.")
153 :
154 : (defvar eldoc-current-idle-delay eldoc-idle-delay
155 : "Idle time delay currently in use by timer.
156 : This is used to determine if `eldoc-idle-delay' is changed by the user.")
157 :
158 : (defvar eldoc-message-function #'eldoc-minibuffer-message
159 : "The function used by `eldoc-message' to display messages.
160 : It should receive the same arguments as `message'.")
161 :
162 : (defun eldoc-edit-message-commands ()
163 : "Return an obarray containing common editing commands.
164 :
165 : When `eldoc-print-after-edit' is non-nil, ElDoc messages are only
166 : printed after commands contained in this obarray."
167 0 : (let ((cmds (make-vector 31 0))
168 0 : (re (regexp-opt '("delete" "insert" "edit" "electric" "newline"))))
169 0 : (mapatoms (lambda (s)
170 0 : (and (commandp s)
171 0 : (string-match-p re (symbol-name s))
172 0 : (intern (symbol-name s) cmds)))
173 0 : obarray)
174 0 : cmds))
175 :
176 :
177 : ;;;###autoload
178 : (define-minor-mode eldoc-mode
179 : "Toggle echo area display of Lisp objects at point (ElDoc mode).
180 : With a prefix argument ARG, enable ElDoc mode if ARG is positive,
181 : and disable it otherwise. If called from Lisp, enable ElDoc mode
182 : if ARG is omitted or nil.
183 :
184 : ElDoc mode is a buffer-local minor mode. When enabled, the echo
185 : area displays information about a function or variable in the
186 : text where point is. If point is on a documented variable, it
187 : displays the first line of that variable's doc string. Otherwise
188 : it displays the argument list of the function called in the
189 : expression point is on."
190 : :group 'eldoc :lighter eldoc-minor-mode-string
191 47 : (setq eldoc-last-message nil)
192 47 : (cond
193 47 : ((not (eldoc--supported-p))
194 0 : (when (called-interactively-p 'any)
195 0 : (message "There is no ElDoc support in this buffer"))
196 0 : (setq eldoc-mode nil))
197 47 : (eldoc-mode
198 47 : (when eldoc-print-after-edit
199 47 : (setq-local eldoc-message-commands (eldoc-edit-message-commands)))
200 47 : (add-hook 'post-command-hook 'eldoc-schedule-timer nil t)
201 47 : (add-hook 'pre-command-hook 'eldoc-pre-command-refresh-echo-area nil t))
202 : (t
203 0 : (kill-local-variable 'eldoc-message-commands)
204 0 : (remove-hook 'post-command-hook 'eldoc-schedule-timer t)
205 0 : (remove-hook 'pre-command-hook 'eldoc-pre-command-refresh-echo-area t)
206 0 : (when eldoc-timer
207 0 : (cancel-timer eldoc-timer)
208 47 : (setq eldoc-timer nil)))))
209 :
210 : ;;;###autoload
211 : (define-globalized-minor-mode global-eldoc-mode eldoc-mode turn-on-eldoc-mode
212 : :group 'eldoc
213 : :initialize 'custom-initialize-delay
214 : :init-value t)
215 :
216 : ;;;###autoload
217 : (defun turn-on-eldoc-mode ()
218 : "Turn on `eldoc-mode' if the buffer has ElDoc support enabled.
219 : See `eldoc-documentation-function' for more detail."
220 112 : (when (eldoc--supported-p)
221 112 : (eldoc-mode 1)))
222 :
223 : (defun eldoc--supported-p ()
224 : "Non-nil if an ElDoc function is set for this buffer."
225 159 : (not (memq eldoc-documentation-function '(nil ignore))))
226 :
227 :
228 : (defun eldoc-schedule-timer ()
229 : "Ensure `eldoc-timer' is running.
230 :
231 : If the user has changed `eldoc-idle-delay', update the timer to
232 : reflect the change."
233 0 : (or (and eldoc-timer
234 0 : (memq eldoc-timer timer-idle-list)) ;FIXME: Why?
235 0 : (setq eldoc-timer
236 0 : (run-with-idle-timer
237 0 : eldoc-idle-delay nil
238 : (lambda ()
239 0 : (when (or eldoc-mode
240 0 : (and global-eldoc-mode
241 0 : (eldoc--supported-p)))
242 0 : (eldoc-print-current-symbol-info))))))
243 :
244 : ;; If user has changed the idle delay, update the timer.
245 0 : (cond ((not (= eldoc-idle-delay eldoc-current-idle-delay))
246 0 : (setq eldoc-current-idle-delay eldoc-idle-delay)
247 0 : (timer-set-idle-time eldoc-timer eldoc-idle-delay t))))
248 :
249 : (defvar eldoc-mode-line-string nil)
250 : (put 'eldoc-mode-line-string 'risky-local-variable t)
251 :
252 : (defun eldoc-minibuffer-message (format-string &rest args)
253 : "Display messages in the mode-line when in the minibuffer.
254 : Otherwise work like `message'."
255 0 : (if (minibufferp)
256 0 : (progn
257 0 : (add-hook 'minibuffer-exit-hook
258 0 : (lambda () (setq eldoc-mode-line-string nil
259 : ;; http://debbugs.gnu.org/16920
260 0 : eldoc-last-message nil))
261 0 : nil t)
262 0 : (with-current-buffer
263 0 : (window-buffer
264 0 : (or (window-in-direction 'above (minibuffer-window))
265 0 : (minibuffer-selected-window)
266 0 : (get-largest-window)))
267 0 : (unless (and (listp mode-line-format)
268 0 : (assq 'eldoc-mode-line-string mode-line-format))
269 0 : (setq mode-line-format
270 0 : (list "" '(eldoc-mode-line-string
271 : (" " eldoc-mode-line-string " "))
272 0 : mode-line-format)))
273 0 : (setq eldoc-mode-line-string
274 0 : (when (stringp format-string)
275 0 : (apply #'format-message format-string args)))
276 0 : (force-mode-line-update)))
277 0 : (apply 'message format-string args)))
278 :
279 : (defun eldoc-message (&optional format-string &rest args)
280 : "Display FORMAT-STRING formatted with ARGS as an ElDoc message.
281 :
282 : Store the message (if any) in `eldoc-last-message', and return it."
283 0 : (let ((omessage eldoc-last-message))
284 0 : (setq eldoc-last-message
285 0 : (cond ((eq format-string eldoc-last-message) eldoc-last-message)
286 0 : ((null format-string) nil)
287 : ;; If only one arg, no formatting to do, so put it in
288 : ;; eldoc-last-message so eq test above might succeed on
289 : ;; subsequent calls.
290 0 : ((null args) format-string)
291 0 : (t (apply #'format-message format-string args))))
292 : ;; In emacs 19.29 and later, and XEmacs 19.13 and later, all messages
293 : ;; are recorded in a log. Do not put eldoc messages in that log since
294 : ;; they are Legion.
295 : ;; Emacs way of preventing log messages.
296 0 : (let ((message-log-max nil))
297 0 : (cond (eldoc-last-message
298 0 : (funcall eldoc-message-function "%s" eldoc-last-message))
299 0 : (omessage (funcall eldoc-message-function nil)))))
300 0 : eldoc-last-message)
301 :
302 : (defun eldoc--message-command-p (command)
303 : "Return non-nil if COMMAND is in `eldoc-message-commands'."
304 0 : (and (symbolp command)
305 0 : (intern-soft (symbol-name command) eldoc-message-commands)))
306 :
307 : ;; This function goes on pre-command-hook for XEmacs or when using idle
308 : ;; timers in Emacs. Motion commands clear the echo area for some reason,
309 : ;; which make eldoc messages flicker or disappear just before motion
310 : ;; begins. This function reprints the last eldoc message immediately
311 : ;; before the next command executes, which does away with the flicker.
312 : ;; This doesn't seem to be required for Emacs 19.28 and earlier.
313 : (defun eldoc-pre-command-refresh-echo-area ()
314 : "Reprint `eldoc-last-message' in the echo area."
315 0 : (and eldoc-last-message
316 0 : (not (minibufferp)) ;We don't use the echo area when in minibuffer.
317 0 : (if (and (eldoc-display-message-no-interference-p)
318 0 : (eldoc--message-command-p this-command))
319 0 : (eldoc-message eldoc-last-message)
320 : ;; No need to call eldoc-message since the echo area will be cleared
321 : ;; for us, but do note that the last-message will be gone.
322 0 : (setq eldoc-last-message nil))))
323 :
324 : ;; Decide whether now is a good time to display a message.
325 : (defun eldoc-display-message-p ()
326 : "Return non-nil when it is appropriate to display an ElDoc message."
327 0 : (and (eldoc-display-message-no-interference-p)
328 : ;; If this-command is non-nil while running via an idle
329 : ;; timer, we're still in the middle of executing a command,
330 : ;; e.g. a query-replace where it would be annoying to
331 : ;; overwrite the echo area.
332 0 : (not this-command)
333 0 : (eldoc--message-command-p last-command)))
334 :
335 :
336 : ;; Check various conditions about the current environment that might make
337 : ;; it undesirable to print eldoc messages right this instant.
338 : (defun eldoc-display-message-no-interference-p ()
339 : "Return nil if displaying a message would cause interference."
340 0 : (not (or executing-kbd-macro (bound-and-true-p edebug-active))))
341 :
342 :
343 : ;;;###autoload
344 : (defvar eldoc-documentation-function #'ignore
345 : "Function to call to return doc string.
346 : The function of no args should return a one-line string for displaying
347 : doc about a function etc. appropriate to the context around point.
348 : It should return nil if there's no doc appropriate for the context.
349 : Typically doc is returned if point is on a function-like name or in its
350 : arg list.
351 :
352 : The result is used as is, so the function must explicitly handle
353 : the variables `eldoc-argument-case' and `eldoc-echo-area-use-multiline-p',
354 : and the face `eldoc-highlight-function-argument', if they are to have any
355 : effect.
356 :
357 : Major modes should modify this variable using `add-function', for example:
358 : (add-function :before-until (local \\='eldoc-documentation-function)
359 : #\\='foo-mode-eldoc-function)
360 : so that the global documentation function (i.e. the default value of the
361 : variable) is taken into account if the major mode specific function does not
362 : return any documentation.")
363 :
364 : (defun eldoc-print-current-symbol-info ()
365 : "Print the text produced by `eldoc-documentation-function'."
366 : ;; This is run from post-command-hook or some idle timer thing,
367 : ;; so we need to be careful that errors aren't ignored.
368 0 : (with-demoted-errors "eldoc error: %s"
369 0 : (and (or (eldoc-display-message-p)
370 : ;; Erase the last message if we won't display a new one.
371 0 : (when eldoc-last-message
372 0 : (eldoc-message nil)
373 0 : nil))
374 0 : (eldoc-message (funcall eldoc-documentation-function)))))
375 :
376 : ;; If the entire line cannot fit in the echo area, the symbol name may be
377 : ;; truncated or eliminated entirely from the output to make room for the
378 : ;; description.
379 : (defun eldoc-docstring-format-sym-doc (prefix doc &optional face)
380 : "Combine PREFIX and DOC, and shorten the result to fit in the echo area.
381 :
382 : When PREFIX is a symbol, propertize its symbol name with FACE
383 : before combining it with DOC. If FACE is not provided, just
384 : apply the nil face.
385 :
386 : See also: `eldoc-echo-area-use-multiline-p'."
387 0 : (when (symbolp prefix)
388 0 : (setq prefix (concat (propertize (symbol-name prefix) 'face face) ": ")))
389 0 : (let* ((ea-multi eldoc-echo-area-use-multiline-p)
390 : ;; Subtract 1 from window width since emacs will not write
391 : ;; any chars to the last column, or in later versions, will
392 : ;; cause a wraparound and resize of the echo area.
393 0 : (ea-width (1- (window-width (minibuffer-window))))
394 0 : (strip (- (+ (length prefix) (length doc)) ea-width)))
395 0 : (cond ((or (<= strip 0)
396 0 : (eq ea-multi t)
397 0 : (and ea-multi (> (length doc) ea-width)))
398 0 : (concat prefix doc))
399 0 : ((> (length doc) ea-width)
400 0 : (substring (format "%s" doc) 0 ea-width))
401 0 : ((>= strip (string-match-p ":? *\\'" prefix))
402 0 : doc)
403 : (t
404 : ;; Show the end of the partial symbol name, rather
405 : ;; than the beginning, since the former is more likely
406 : ;; to be unique given package namespace conventions.
407 0 : (concat (substring prefix strip) doc)))))
408 :
409 : ;; When point is in a sexp, the function args are not reprinted in the echo
410 : ;; area after every possible interactive command because some of them print
411 : ;; their own messages in the echo area; the eldoc functions would instantly
412 : ;; overwrite them unless it is more restrained.
413 : ;; These functions do display-command table management.
414 :
415 : (defun eldoc-add-command (&rest cmds)
416 : "Add each of CMDS to the obarray `eldoc-message-commands'."
417 30 : (dolist (name cmds)
418 139 : (and (symbolp name)
419 139 : (setq name (symbol-name name)))
420 139 : (set (intern name eldoc-message-commands) t)))
421 :
422 : (defun eldoc-add-command-completions (&rest names)
423 : "Pass every prefix completion of NAMES to `eldoc-add-command'."
424 1 : (dolist (name names)
425 30 : (apply #'eldoc-add-command (all-completions name obarray 'commandp))))
426 :
427 : (defun eldoc-remove-command (&rest cmds)
428 : "Remove each of CMDS from the obarray `eldoc-message-commands'."
429 0 : (dolist (name cmds)
430 0 : (and (symbolp name)
431 0 : (setq name (symbol-name name)))
432 0 : (unintern name eldoc-message-commands)))
433 :
434 : (defun eldoc-remove-command-completions (&rest names)
435 : "Pass every prefix completion of NAMES to `eldoc-remove-command'."
436 0 : (dolist (name names)
437 0 : (apply #'eldoc-remove-command
438 0 : (all-completions name eldoc-message-commands))))
439 :
440 :
441 : ;; Prime the command list.
442 : (eldoc-add-command-completions
443 : "back-to-indentation"
444 : "backward-" "beginning-of-" "delete-other-windows" "delete-window"
445 : "down-list" "end-of-" "exchange-point-and-mark" "forward-" "goto-"
446 : "handle-select-window" "indent-for-tab-command" "left-" "mark-page"
447 : "mark-paragraph" "mouse-set-point" "move-" "move-beginning-of-"
448 : "move-end-of-" "newline" "next-" "other-window" "pop-global-mark"
449 : "previous-" "recenter" "right-" "scroll-" "self-insert-command"
450 : "split-window-" "up-list")
451 :
452 : (provide 'eldoc)
453 :
454 : ;;; eldoc.el ends here
|