aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNoah Friedman1997-02-03 06:13:34 +0000
committerNoah Friedman1997-02-03 06:13:34 +0000
commit332ae8db49745ebff5a895fae82eca1cad3d6b72 (patch)
treeab991e3b5405e0251b761257318cdc71cd86aff2
parent509a8fcde89b144b6638693f1bbeb854e7aa492c (diff)
downloademacs-332ae8db49745ebff5a895fae82eca1cad3d6b72.tar.gz
emacs-332ae8db49745ebff5a895fae82eca1cad3d6b72.zip
Update copyright notice to reflect assignment to FSF and incorporation
into Emacs. Attempt to load `timer'. (eldoc-idle-delay): Make defconst. (eldoc-minor-mode-string): Make defconst. (eldoc-argument-case): Make defconst. (eldoc-message-commands): Renamed from eldoc-mode-message-commands. All callers changed. Add `mouse-set-point' as a default candidate. (eldoc-use-idle-timer-p): New constant. (eldoc-timer): New variable. (eldoc-current-idle-delay): New variable. (eldoc-schedule-timer): New function. (eldoc-mode): Use idle timers if supported. (eldoc-add-command): Provide completion on interactive commands only, not all bound functions. (eldoc-print-current-symbol-info): Renamed from eldoc-mode-print-current-symbol-info. All callers changed. Check whether using idle timers or being run from post-command hooks. Use `executing-kbd-macro' instead of `executing-macro'. (eldoc-print-fnsym-args): Don't make interactive. Cache current symbol name in eldoc-last-data; it was forgetting to do this previously. If subr args cannot be determined, show single-line docstring for it instead. (eldoc-docstring-message): New function. (eldoc-print-docstring): New function. (eldoc-print-var-docstring): Use them. (eldoc-function-argstring-from-docstring-method-table): New constant. (eldoc-function-argstring-from-docstring): Use it.
-rw-r--r--lisp/emacs-lisp/eldoc.el481
1 files changed, 278 insertions, 203 deletions
diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el
index ff84819c748..5123fd7b81b 100644
--- a/lisp/emacs-lisp/eldoc.el
+++ b/lisp/emacs-lisp/eldoc.el
@@ -1,45 +1,41 @@
1;;; eldoc.el --- show function arglist or variable docstring in echo area 1;;; eldoc.el --- show function arglist or variable docstring in echo area
2 2
3;; Copyright (C) 1995 Noah S. Friedman 3;; Copyright (C) 1996, 1997 Free Software Foundation, Inc.
4 4
5;; Author: Noah Friedman <friedman@prep.ai.mit.edu> 5;; Author: Noah Friedman <friedman@prep.ai.mit.edu>
6;; Maintainer: friedman@prep.ai.mit.edu 6;; Maintainer: friedman@prep.ai.mit.edu
7;; Keywords: extensions 7;; Keywords: extensions
8;; Status: Works in Emacs 19 and XEmacs.
9;; Created: 1995-10-06 8;; Created: 1995-10-06
10 9
11;; LCD Archive Entry: 10;; $Id: eldoc.el,v 1.7 1996/10/04 04:43:42 friedman Exp $
12;; eldoc|Noah Friedman|friedman@prep.ai.mit.edu|
13;; show function arglist or variable docstring in echo area|
14;; $Date: 1996/07/14 16:46:25 $|$Revision: 1.6 $|~/misc/eldoc.el.gz|
15 11
16;; $Id: eldoc.el,v 1.6 1996/07/14 16:46:25 friedman Exp friedman $ 12;; This file is part of GNU Emacs.
17 13
18;; This program is free software; you can redistribute it and/or modify 14;; GNU Emacs is free software; you can redistribute it and/or modify
19;; it under the terms of the GNU General Public License as published by 15;; it under the terms of the GNU General Public License as published by
20;; the Free Software Foundation; either version 2, or (at your option) 16;; the Free Software Foundation; either version 2, or (at your option)
21;; any later version. 17;; any later version.
22;; 18
23;; This program is distributed in the hope that it will be useful, 19;; GNU Emacs is distributed in the hope that it will be useful,
24;; but WITHOUT ANY WARRANTY; without even the implied warranty of 20;; but WITHOUT ANY WARRANTY; without even the implied warranty of
25;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26;; GNU General Public License for more details. 22;; GNU General Public License for more details.
27;; 23
28;; You should have received a copy of the GNU General Public License 24;; You should have received a copy of the GNU General Public License
29;; along with this program; if not, you can either send email to this 25;; along with GNU Emacs; see the file COPYING. If not, write to the
30;; program's maintainer or write to: The Free Software Foundation, 26;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
31;; Inc.; 59 Temple Place, Suite 330; Boston, MA 02111-1307, USA. 27;; Boston, MA 02111-1307, USA.
32 28
33;;; Commentary: 29;;; Commentary:
34 30
35;; This program was inspired by the behavior of the Lisp Machine "mouse 31;; This program was inspired by the behavior of the "mouse documentation
36;; documentation window"; as you type a function's symbol name as part of a 32;; window" on many Lisp Machine systems; as you type a function's symbol
37;; sexp, it will print the argument list for that function. However, this 33;; name as part of a sexp, it will print the argument list for that
38;; program's behavior is different in a couple of significant ways. For 34;; function. Behavior is not identical; for example, you need not actually
39;; one, you need not actually type the function name; you need only move 35;; type the function name, you need only move point around in a sexp that
40;; point around in a sexp that calls it. However, if point is over a 36;; calls it. Also, if point is over a documented variable, it will print
41;; documented variable, it will print the one-line documentation for that 37;; the one-line documentation for that variable instead, to remind you of
42;; variable instead, to remind you of that variable's purpose. 38;; that variable's meaning.
43 39
44;; One useful way to enable this minor mode is to put the following in your 40;; One useful way to enable this minor mode is to put the following in your
45;; .emacs: 41;; .emacs:
@@ -50,6 +46,13 @@
50 46
51;;; Code: 47;;; Code:
52 48
49;; Use idle timers if available in the version of emacs running.
50;; Please don't change this to use `require'; this package works as-is in
51;; XEmacs (which doesn't have timer.el as of 19.14), and I would like to
52;; maintain compatibility with that since I must use it sometimes. --Noah
53(or (featurep 'timer)
54 (load "timer" t))
55
53;;;###autoload 56;;;###autoload
54(defvar eldoc-mode nil 57(defvar eldoc-mode nil
55 "*If non-nil, show the defined parameters for the elisp function near point. 58 "*If non-nil, show the defined parameters for the elisp function near point.
@@ -57,57 +60,66 @@
57For the emacs lisp function at the beginning of the sexp which point is 60For the emacs lisp function at the beginning of the sexp which point is
58within, show the defined parameters for the function in the echo area. 61within, show the defined parameters for the function in the echo area.
59This information is extracted directly from the function or macro if it is 62This information is extracted directly from the function or macro if it is
60in pure lisp. 63in pure lisp. If the emacs function is a subr, the parameters are obtained
61 64from the documentation string if possible.
62If the emacs function is a subr, the parameters are obtained from the
63documentation string if possible.
64 65
65If point is over a documented variable, print that variable's docstring 66If point is over a documented variable, print that variable's docstring
66instead; see function `eldoc-print-var-docstring'. 67instead.
67 68
68This variable is buffer-local.") 69This variable is buffer-local.")
69(make-variable-buffer-local 'eldoc-mode) 70(make-variable-buffer-local 'eldoc-mode)
70 71
71(defvar eldoc-idle-delay 0.50 72(defconst eldoc-idle-delay 0.50
72 "*Number of seconds of idle time to wait before printing. 73 "*Number of seconds of idle time to wait before printing.
73If user input arrives before this interval of time has elapsed after the 74If user input arrives before this interval of time has elapsed after the
74last input, no documentation will be printed. 75last input, no documentation will be printed.
75 76
76If this variable is set to 0, no idle time is required.") 77If this variable is set to 0, no idle time is required.")
77 78
78(defvar eldoc-argument-case 'upcase 79(defconst eldoc-minor-mode-string " ElDoc"
80 "*String to display in mode line when Eldoc Mode is enabled.")
81
82;; Put this minor mode on the global minor-mode-alist.
83(or (assq 'eldoc-mode (default-value 'minor-mode-alist))
84 (setq-default minor-mode-alist
85 (append (default-value 'minor-mode-alist)
86 '((eldoc-mode eldoc-minor-mode-string)))))
87
88(defconst eldoc-argument-case 'upcase
79 "Case to display argument names of functions, as a symbol. 89 "Case to display argument names of functions, as a symbol.
80This has two preferred values: `upcase' or `downcase'. 90This has two preferred values: `upcase' or `downcase'.
81Actually, any name of a function which takes a string as an argument and 91Actually, any name of a function which takes a string as an argument and
82returns another string is acceptable.") 92returns another string is acceptable.")
83 93
84(defvar eldoc-mode-message-commands nil 94(defvar eldoc-message-commands nil
85 "*Obarray of command names where it is appropriate to print in the echo area. 95 "*Commands after which it is appropriate to print in the echo area.
86 96
87This is not done for all commands since some print their own 97Eldoc does not try to print function arglists, etc. after just any command,
88messages in the echo area, and these functions would instantly overwrite 98because some commands print their own messages in the echo area and these
89them. But self-insert-command as well as most motion commands are good 99functions would instantly overwrite them. But self-insert-command as well
90candidates. 100as most motion commands are good candidates.
91 101
92It is probably best to manipulate this data structure with the commands 102This variable contains an obarray of symbols; it is probably best to
93`eldoc-add-command' and `eldoc-remove-command'.") 103manipulate this data structure with the commands `eldoc-add-command' and
104`eldoc-remove-command'.")
94 105
95(cond ((null eldoc-mode-message-commands) 106(cond ((null eldoc-message-commands)
96 ;; If you increase the number of buckets, keep it a prime number. 107 ;; If you increase the number of buckets, keep it a prime number.
97 (setq eldoc-mode-message-commands (make-vector 31 0)) 108 (setq eldoc-message-commands (make-vector 31 0))
98 (let ((list '("self-insert-command" 109 (let ((list '("self-insert-command"
99 "next-" "previous-" 110 "next-" "previous-"
100 "forward-" "backward-" 111 "forward-" "backward-"
101 "beginning-of-" "end-of-" 112 "beginning-of-" "end-of-"
102 "goto-" 113 "goto-"
103 "recenter" 114 "recenter"
104 "scroll-")) 115 "scroll-"
116 "mouse-set-point"))
105 (syms nil)) 117 (syms nil))
106 (while list 118 (while list
107 (setq syms (all-completions (car list) obarray 'fboundp)) 119 (setq syms (all-completions (car list) obarray 'fboundp))
108 (setq list (cdr list)) 120 (setq list (cdr list))
109 (while syms 121 (while syms
110 (set (intern (car syms) eldoc-mode-message-commands) t) 122 (set (intern (car syms) eldoc-message-commands) t)
111 (setq syms (cdr syms))))))) 123 (setq syms (cdr syms)))))))
112 124
113;; Bookkeeping; the car contains the last symbol read from the buffer. 125;; Bookkeeping; the car contains the last symbol read from the buffer.
@@ -115,14 +127,15 @@ It is probably best to manipulate this data structure with the commands
115;; be printed again if necessary without reconsing. 127;; be printed again if necessary without reconsing.
116(defvar eldoc-last-data '(nil . nil)) 128(defvar eldoc-last-data '(nil . nil))
117 129
118(defvar eldoc-minor-mode-string " ElDoc" 130;; Idle timers are supported in Emacs 19.31 and later.
119 "*String to display in mode line when Eldoc Mode is enabled.") 131(defconst eldoc-use-idle-timer-p (fboundp 'run-with-idle-timer))
120 132
121;; Put this minor mode on the global minor-mode-alist. 133;; eldoc's timer object, if using idle timers
122(or (assq 'eldoc-mode (default-value 'minor-mode-alist)) 134(defvar eldoc-timer nil)
123 (setq-default minor-mode-alist 135
124 (append (default-value 'minor-mode-alist) 136;; idle time delay currently in use by timer.
125 '((eldoc-mode eldoc-minor-mode-string))))) 137;; This is used to determine if eldoc-idle-delay is changed by the user.
138(defvar eldoc-current-idle-delay eldoc-idle-delay)
126 139
127;; In emacs 19.29 and later, and XEmacs 19.13 and later, all messages are 140;; In emacs 19.29 and later, and XEmacs 19.13 and later, all messages are
128;; recorded in a log. Do not put eldoc messages in that log since 141;; recorded in a log. Do not put eldoc messages in that log since
@@ -137,15 +150,26 @@ It is probably best to manipulate this data structure with the commands
137 150
138;;;###autoload 151;;;###autoload
139(defun eldoc-mode (&optional prefix) 152(defun eldoc-mode (&optional prefix)
140 "*If non-nil, then enable eldoc-mode (see variable docstring)." 153 "*Enable or disable eldoc mode.
154See documentation for the variable of the same name for more details.
155
156If called interactively with no prefix argument, toggle current condition
157of the mode.
158If called with a positive or negative prefix argument, enable or disable
159the mode, respectively."
141 (interactive "P") 160 (interactive "P")
142 161
143 ;; Make sure it's on the post-command-idle-hook if defined, otherwise put 162 (cond (eldoc-use-idle-timer-p
144 ;; it on post-command-hook. The former first appeared in Emacs 19.30. 163 (add-hook 'post-command-hook 'eldoc-schedule-timer))
145 (add-hook (if (boundp 'post-command-idle-hook) 164 (t
146 'post-command-idle-hook 165 ;; Use post-command-idle-hook if defined, otherwise use
147 'post-command-hook) 166 ;; post-command-hook. The former is only proper to use in Emacs
148 'eldoc-mode-print-current-symbol-info) 167 ;; 19.30; that is the first version in which it appeared, but it
168 ;; was obsolesced by idle timers in Emacs 19.31.
169 (add-hook (if (boundp 'post-command-idle-hook)
170 'post-command-idle-hook
171 'post-command-hook)
172 'eldoc-print-current-symbol-info)))
149 173
150 (setq eldoc-mode (if prefix 174 (setq eldoc-mode (if prefix
151 (>= (prefix-numeric-value prefix) 0) 175 (>= (prefix-numeric-value prefix) 0)
@@ -165,15 +189,15 @@ It is probably best to manipulate this data structure with the commands
165 189
166(defun eldoc-add-command (cmd) 190(defun eldoc-add-command (cmd)
167 "Add COMMAND to the list of commands which causes function arg display. 191 "Add COMMAND to the list of commands which causes function arg display.
168If called interactively, completion matches any bound function. 192If called interactively, completion on defined commands is available.
169 193
170When point is in a sexp, the function args are not reprinted in the echo 194When point is in a sexp, the function args are not reprinted in the echo
171area after every possible interactive command because some of them print 195area after every possible interactive command because some of them print
172their own messages in the echo area; the eldoc functions would instantly 196their own messages in the echo area; the eldoc functions would instantly
173overwrite them unless it is more restrained." 197overwrite them unless it is more restrained."
174 (interactive "aAdd function to eldoc message commands list: ") 198 (interactive "CAdd function to eldoc message commands list: ")
175 (and (fboundp cmd) 199 (and (fboundp cmd)
176 (set (intern (symbol-name cmd) eldoc-mode-message-commands) t))) 200 (set (intern (symbol-name cmd) eldoc-message-commands) t)))
177 201
178(defun eldoc-remove-command (cmd) 202(defun eldoc-remove-command (cmd)
179 "Remove COMMAND from the list of commands which causes function arg display. 203 "Remove COMMAND from the list of commands which causes function arg display.
@@ -186,24 +210,51 @@ their own messages in the echo area; the eldoc functions would instantly
186overwrite them unless it is more restrained." 210overwrite them unless it is more restrained."
187 (interactive (list (completing-read 211 (interactive (list (completing-read
188 "Remove function from eldoc message commands list: " 212 "Remove function from eldoc message commands list: "
189 eldoc-mode-message-commands 'boundp t))) 213 eldoc-message-commands 'boundp t)))
190 (and (symbolp cmd) 214 (and (symbolp cmd)
191 (setq cmd (symbol-name cmd))) 215 (setq cmd (symbol-name cmd)))
192 (if (fboundp 'unintern) 216 (if (fboundp 'unintern)
193 (unintern cmd eldoc-mode-message-commands) 217 (unintern cmd eldoc-message-commands)
194 (let ((s (intern-soft cmd eldoc-mode-message-commands))) 218 (let ((s (intern-soft cmd eldoc-message-commands)))
195 (and s 219 (and s
196 (makunbound s))))) 220 (makunbound s)))))
197 221
198(defun eldoc-mode-print-current-symbol-info () 222;; Idle timers are part of Emacs 19.31 and later.
223(defun eldoc-schedule-timer ()
224 (or (and eldoc-timer
225 (memq eldoc-timer timer-idle-list))
226 (setq eldoc-timer
227 (run-with-idle-timer eldoc-idle-delay t
228 'eldoc-print-current-symbol-info)))
229
230 ;; If user has changed the idle delay, update the timer.
231 (cond ((not (= eldoc-idle-delay eldoc-current-idle-delay))
232 (setq eldoc-current-idle-delay eldoc-idle-delay)
233 (timer-set-idle-time eldoc-timer eldoc-idle-delay t))))
234
235
236(defun eldoc-print-current-symbol-info ()
199 (and eldoc-mode 237 (and eldoc-mode
200 (not executing-macro) 238 (not executing-kbd-macro)
201 ;; Having this mode operate in the minibuffer makes it impossible to 239
202 ;; see what you're doing. 240 ;; Having this mode operate in an active minibuffer makes it
241 ;; impossible to what you're doing.
203 (not (eq (selected-window) (minibuffer-window))) 242 (not (eq (selected-window) (minibuffer-window)))
204 (sit-for eldoc-idle-delay) 243
205 (symbolp this-command) 244 (cond (eldoc-use-idle-timer-p
206 (intern-soft (symbol-name this-command) eldoc-mode-message-commands) 245 (and (symbolp last-command)
246 (intern-soft (symbol-name last-command)
247 eldoc-message-commands)))
248 (t
249 ;; If we don't have idle timers, this function is
250 ;; running on post-command-hook directly; that means the
251 ;; user's last command is still on `this-command', and we
252 ;; must wait briefly for input to see whether to do display.
253 (and (symbolp this-command)
254 (intern-soft (symbol-name this-command)
255 eldoc-message-commands)
256 (sit-for eldoc-idle-delay))))
257
207 (let ((current-symbol (eldoc-current-symbol)) 258 (let ((current-symbol (eldoc-current-symbol))
208 (current-fnsym (eldoc-fnsym-in-current-sexp))) 259 (current-fnsym (eldoc-fnsym-in-current-sexp)))
209 (cond ((eq current-symbol current-fnsym) 260 (cond ((eq current-symbol current-fnsym)
@@ -212,70 +263,24 @@ overwrite them unless it is more restrained."
212 (or (eldoc-print-var-docstring current-symbol) 263 (or (eldoc-print-var-docstring current-symbol)
213 (eldoc-print-fnsym-args current-fnsym))))))) 264 (eldoc-print-fnsym-args current-fnsym)))))))
214 265
215
216(defun eldoc-print-var-docstring (&optional sym)
217 "Print the brief (one-line) documentation string for the variable at point.
218If called with no argument, print the first line of the variable
219documentation string for the symbol at point in the echo area.
220If called with a symbol, print the line for that symbol.
221
222If the entire line cannot fit in the echo area, the variable name may be
223truncated or eliminated entirely from the output to make room.
224Any leading `*' in the docstring (which indicates the variable is a user
225option) is not printed."
226 (interactive)
227 (let* ((s (or sym (eldoc-current-symbol)))
228 (name (symbol-name s))
229 (doc (and s (documentation-property s 'variable-documentation t))))
230 (and doc
231 (save-match-data
232 (and (string-match "\n" doc)
233 (setq doc (substring doc 0 (match-beginning 0))))
234 (and (string-match "^\\*" doc)
235 (setq doc (substring doc 1)))
236 (let* ((doclen (+ (length name) (length ": ") (length doc)))
237 ;; Subtract 1 from window width since emacs seems not to
238 ;; write any chars to the last column, at least for some
239 ;; terminal types.
240 (strip (- doclen (1- (window-width (minibuffer-window))))))
241 (cond ((> strip 0)
242 (let* ((len (length name)))
243 (cond ((>= strip len)
244 (eldoc-message "%s" doc))
245 (t
246 (setq name (substring name 0 (- len strip)))
247 (eldoc-message "%s: %s" name doc)))))
248 (t
249 (eldoc-message "%s: %s" s doc))))
250 t))))
251
252
253;;;###autoload
254(defun eldoc-print-fnsym-args (&optional symbol) 266(defun eldoc-print-fnsym-args (&optional symbol)
255 "*Show the defined parameters for the function near point.
256For the function at the beginning of the sexp which point is within, show
257the defined parameters for the function in the echo area.
258This information is extracted directly from the function or macro if it is
259in pure lisp.
260If the emacs function is a subr, the parameters are obtained from the
261documentation string if possible."
262 (interactive) 267 (interactive)
263 (let ((sym (or symbol (eldoc-fnsym-in-current-sexp))) 268 (let ((sym (or symbol (eldoc-fnsym-in-current-sexp)))
264 (printit t)
265 (args nil)) 269 (args nil))
266 (cond ((not (and (symbolp sym) 270 (cond ((not (and (symbolp sym)
267 (fboundp sym)))) 271 (fboundp sym))))
268 ((eq sym (car eldoc-last-data)) 272 ((eq sym (car eldoc-last-data))
269 (setq printit nil)
270 (setq args (cdr eldoc-last-data))) 273 (setq args (cdr eldoc-last-data)))
271 ((subrp (eldoc-symbol-function sym)) 274 ((subrp (eldoc-symbol-function sym))
272 (setq args (eldoc-function-argstring-from-docstring sym)) 275 (setq args (or (eldoc-function-argstring-from-docstring sym)
276 (eldoc-docstring-first-line (documentation sym t))))
277 (setcar eldoc-last-data sym)
273 (setcdr eldoc-last-data args)) 278 (setcdr eldoc-last-data args))
274 (t 279 (t
275 (setq args (eldoc-function-argstring sym)) 280 (setq args (eldoc-function-argstring sym))
281 (setcar eldoc-last-data sym)
276 (setcdr eldoc-last-data args))) 282 (setcdr eldoc-last-data args)))
277 (and args 283 (and args
278 printit
279 (eldoc-message "%s: %s" sym args)))) 284 (eldoc-message "%s: %s" sym args))))
280 285
281(defun eldoc-fnsym-in-current-sexp () 286(defun eldoc-fnsym-in-current-sexp ()
@@ -313,75 +318,165 @@ documentation string if possible."
313 (t t)))) 318 (t t))))
314 (eldoc-function-argstring-format arglist))) 319 (eldoc-function-argstring-format arglist)))
315 320
321(defun eldoc-function-argstring-format (arglist)
322 (cond ((not (listp arglist))
323 (setq arglist nil))
324 ((symbolp (car arglist))
325 (setq arglist
326 (mapcar (function (lambda (s)
327 (if (memq s '(&optional &rest))
328 (symbol-name s)
329 (funcall eldoc-argument-case
330 (symbol-name s)))))
331 arglist)))
332 ((stringp (car arglist))
333 (setq arglist
334 (mapcar (function (lambda (s)
335 (if (member s '("&optional" "&rest"))
336 s
337 (funcall eldoc-argument-case s))))
338 arglist))))
339 (concat "(" (mapconcat 'identity arglist " ") ")"))
340
341
342(defun eldoc-print-var-docstring (&optional sym)
343 (or sym (setq sym (eldoc-current-symbol)))
344 (eldoc-print-docstring sym (documentation-property
345 sym 'variable-documentation t)))
346
347;; Print the brief (one-line) documentation string for the symbol.
348(defun eldoc-print-docstring (symbol doc)
349 (and doc
350 (eldoc-message "%s" (eldoc-docstring-message symbol doc))))
351
352;; If the entire line cannot fit in the echo area, the variable name may be
353;; truncated or eliminated entirely from the output to make room.
354;; Any leading `*' in the docstring (which indicates the variable is a user
355;; option) is not printed."
356(defun eldoc-docstring-message (symbol doc)
357 (and doc
358 (let ((name (symbol-name symbol)))
359 (setq doc (eldoc-docstring-first-line doc))
360 (save-match-data
361 (let* ((doclen (+ (length name) (length ": ") (length doc)))
362 ;; Subtract 1 from window width since emacs seems not to
363 ;; write any chars to the last column, at least for some
364 ;; terminal types.
365 (strip (- doclen (1- (window-width (minibuffer-window))))))
366 (cond ((> strip 0)
367 (let* ((len (length name)))
368 (cond ((>= strip len)
369 (format "%s" doc))
370 (t
371 (setq name (substring name 0 (- len strip)))
372 (format "%s: %s" name doc)))))
373 (t
374 (format "%s: %s" symbol doc))))))))
375
376(defun eldoc-docstring-first-line (doc)
377 (save-match-data
378 (and (string-match "\n" doc)
379 (setq doc (substring doc 0 (match-beginning 0))))
380 (and (string-match "^\\*" doc)
381 (setq doc (substring doc 1))))
382 doc)
383
384
385;; Alist of predicate/action pairs.
386;; Each member of the list is a sublist consisting of a predicate function
387;; used to determine if the arglist for a function can be found using a
388;; certain pattern, and a function which returns the actual arglist from
389;; that docstring.
390;;
391;; The order in this table is significant, since later predicates may be
392;; more general than earlier ones.
393;;
394;; Compiler note for Emacs 19.29 and later: these functions will be
395;; compiled to bytecode, but can't be lazy-loaded even if you set
396;; byte-compile-dynamic; to do that would require making them named
397;; top-level defuns, and that's not particularly desirable either.
398(defconst eldoc-function-argstring-from-docstring-method-table
399 (list
400 ;; Try first searching for args starting with symbol name.
401 ;; This is to avoid matching parenthetical remarks in e.g. sit-for.
402 (list (function (lambda (doc fn)
403 (string-match (format "^(%s[^\n)]*)$" fn) doc)))
404 (function (lambda (doc)
405 ;; end does not include trailing ")" sequence.
406 (let ((end (- (match-end 0) 1)))
407 (if (string-match " +" doc (match-beginning 0))
408 (substring doc (match-end 0) end)
409 "")))))
410
411 ;; Try again not requiring this symbol name in the docstring.
412 ;; This will be the case when looking up aliases.
413 (list (function (lambda (doc fn)
414 (string-match "^([^\n)]+)$" doc)))
415 (function (lambda (doc)
416 ;; end does not include trailing ")" sequence.
417 (let ((end (- (match-end 0) 1)))
418 (and (string-match " +" doc (match-beginning 0))
419 (substring doc (match-end 0) end))))))
420
421 ;; Emacs subr docstring style:
422 ;; (fn arg1 arg2 ...): description...
423 (list (function (lambda (doc fn)
424 (string-match "^([^\n)]+):" doc)))
425 (function (lambda (doc)
426 ;; end does not include trailing "):" sequence.
427 (let ((end (- (match-end 0) 2)))
428 (and (string-match " +" doc (match-beginning 0))
429 (substring doc (match-end 0) end))))))
430
431 ;; XEmacs subr docstring style:
432 ;; "arguments: (arg1 arg2 ...)
433 (list (function (lambda (doc fn)
434 (string-match "^arguments: (\\([^\n)]+\\))" doc)))
435 (function (lambda (doc)
436 ;; also skip leading paren, but the first word is
437 ;; actually an argument, not the function name.
438 (substring doc (match-beginning 1) (match-end 1)))))
439
440 ;; This finds the argstring for `condition-case'. Any others?
441 (list (function (lambda (doc fn)
442 (string-match
443 (format "^Usage looks like \\((%s[^\n)]*)\\)\\.$" fn)
444 doc)))
445 (function (lambda (doc)
446 ;; end does not include trailing ")" sequence.
447 (let ((end (- (match-end 1) 1)))
448 (and (string-match " +" doc (match-beginning 1))
449 (substring doc (match-end 0) end))))))
450
451 ;; This finds the argstring for `setq-default'. Any others?
452 (list (function (lambda (doc fn)
453 (string-match (format "^[ \t]+\\((%s[^\n)]*)\\)$" fn)
454 doc)))
455 (function (lambda (doc)
456 ;; end does not include trailing ")" sequence.
457 (let ((end (- (match-end 1) 1)))
458 (and (string-match " +" doc (match-beginning 1))
459 (substring doc (match-end 0) end))))))
460
461 ;; This finds the argstring for `start-process'. Any others?
462 (list (function (lambda (doc fn)
463 (string-match "^Args are +\\([^\n]+\\)$" doc)))
464 (function (lambda (doc)
465 (substring doc (match-beginning 1) (match-end 1)))))
466 ))
467
316(defun eldoc-function-argstring-from-docstring (fn) 468(defun eldoc-function-argstring-from-docstring (fn)
317 (let ((docstring (documentation fn 'raw)) 469 (let ((docstring (documentation fn 'raw))
470 (table eldoc-function-argstring-from-docstring-method-table)
318 (doc nil) 471 (doc nil)
319 (doclist nil) 472 (doclist nil))
320 (end nil))
321 (save-match-data 473 (save-match-data
322 ;; TODO: Move these into a separate table that is iterated over until 474 (while table
323 ;; a match is found. 475 (cond ((funcall (car (car table)) docstring fn)
324 (cond 476 (setq doc (funcall (car (cdr (car table))) docstring))
325 ;; Try first searching for args starting with symbol name. 477 (setq table nil))
326 ;; This is to avoid matching parenthetical remarks in e.g. sit-for. 478 (t
327 ((string-match (format "^(%s[^\n)]*)$" fn) docstring) 479 (setq table (cdr table)))))
328 ;; end does not include trailing ")" sequence.
329 (setq end (- (match-end 0) 1))
330 (if (string-match " +" docstring (match-beginning 0))
331 (setq doc (substring docstring (match-end 0) end))
332 (setq doc "")))
333
334 ;; Try again not requiring this symbol name in the docstring.
335 ;; This will be the case when looking up aliases.
336 ((string-match (format "^([^\n)]+)$" fn) docstring)
337 ;; end does not include trailing ")" sequence.
338 (setq end (- (match-end 0) 1))
339 (if (string-match " +" docstring (match-beginning 0))
340 (setq doc (substring docstring (match-end 0) end))
341 (setq doc "")))
342
343 ;; Emacs subr docstring style:
344 ;; (fn arg1 arg2 ...): description...
345 ((string-match "^([^\n)]+):" docstring)
346 ;; end does not include trailing "):" sequence.
347 (setq end (- (match-end 0) 2))
348 (if (string-match " +" docstring (match-beginning 0))
349 (setq doc (substring docstring (match-end 0) end))
350 (setq doc "")))
351
352 ;; XEmacs subr docstring style:
353 ;; "arguments: (arg1 arg2 ...)
354 ((string-match "^arguments: (\\([^\n)]+\\))" docstring)
355 ;; Also, skip leading paren, but the first word is actually an
356 ;; argument, not the function name.
357 (setq doc (substring docstring
358 (match-beginning 1)
359 (match-end 1))))
360
361 ;; This finds the argstring for `condition-case'.
362 ;; I don't know if there are any others with the same pattern.
363 ((string-match (format "^Usage looks like \\((%s[^\n)]*)\\)\\.$" fn)
364 docstring)
365 ;; end does not include trailing ")" sequence.
366 (setq end (- (match-end 1) 1))
367 (if (string-match " +" docstring (match-beginning 1))
368 (setq doc (substring docstring (match-end 0) end))
369 (setq doc "")))
370
371 ;; This finds the argstring for `setq-default'.
372 ;; I don't know if there are any others with the same pattern.
373 ((string-match (format "^[ \t]+\\((%s[^\n)]*)\\)$" fn) docstring)
374 ;; end does not include trailing ")" sequence.
375 (setq end (- (match-end 1) 1))
376 (if (string-match " +" docstring (match-beginning 1))
377 (setq doc (substring docstring (match-end 0) end))
378 (setq doc "")))
379
380 ;; This finds the argstring for `start-process'.
381 ;; I don't know if there are any others with the same pattern.
382 ((string-match "^Args are +\\([^\n]+\\)$" docstring)
383 (setq doc (substring docstring (match-beginning 1) (match-end 1))))
384 )
385 480
386 (cond ((not (stringp doc)) 481 (cond ((not (stringp doc))
387 nil) 482 nil)
@@ -401,26 +496,6 @@ documentation string if possible."
401 (t 496 (t
402 (concat "(" (funcall eldoc-argument-case doc) ")")))))) 497 (concat "(" (funcall eldoc-argument-case doc) ")"))))))
403 498
404(defun eldoc-function-argstring-format (arglist)
405 (cond ((not (listp arglist))
406 (setq arglist nil))
407 ((symbolp (car arglist))
408 (setq arglist
409 (mapcar (function (lambda (s)
410 (if (memq s '(&optional &rest))
411 (symbol-name s)
412 (funcall eldoc-argument-case
413 (symbol-name s)))))
414 arglist)))
415 ((stringp (car arglist))
416 (setq arglist
417 (mapcar (function (lambda (s)
418 (if (member s '("&optional" "&rest"))
419 s
420 (funcall eldoc-argument-case s))))
421 arglist))))
422 (concat "(" (mapconcat 'identity arglist " ") ")"))
423
424 499
425;; forward-sexp calls scan-sexps, which returns an error if it hits the 500;; forward-sexp calls scan-sexps, which returns an error if it hits the
426;; beginning or end of the sexp. This returns nil instead. 501;; beginning or end of the sexp. This returns nil instead.