diff options
| author | Noah Friedman | 1997-02-03 06:13:34 +0000 |
|---|---|---|
| committer | Noah Friedman | 1997-02-03 06:13:34 +0000 |
| commit | 332ae8db49745ebff5a895fae82eca1cad3d6b72 (patch) | |
| tree | ab991e3b5405e0251b761257318cdc71cd86aff2 | |
| parent | 509a8fcde89b144b6638693f1bbeb854e7aa492c (diff) | |
| download | emacs-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.el | 481 |
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 @@ | |||
| 57 | For the emacs lisp function at the beginning of the sexp which point is | 60 | For the emacs lisp function at the beginning of the sexp which point is |
| 58 | within, show the defined parameters for the function in the echo area. | 61 | within, show the defined parameters for the function in the echo area. |
| 59 | This information is extracted directly from the function or macro if it is | 62 | This information is extracted directly from the function or macro if it is |
| 60 | in pure lisp. | 63 | in pure lisp. If the emacs function is a subr, the parameters are obtained |
| 61 | 64 | from the documentation string if possible. | |
| 62 | If the emacs function is a subr, the parameters are obtained from the | ||
| 63 | documentation string if possible. | ||
| 64 | 65 | ||
| 65 | If point is over a documented variable, print that variable's docstring | 66 | If point is over a documented variable, print that variable's docstring |
| 66 | instead; see function `eldoc-print-var-docstring'. | 67 | instead. |
| 67 | 68 | ||
| 68 | This variable is buffer-local.") | 69 | This 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. |
| 73 | If user input arrives before this interval of time has elapsed after the | 74 | If user input arrives before this interval of time has elapsed after the |
| 74 | last input, no documentation will be printed. | 75 | last input, no documentation will be printed. |
| 75 | 76 | ||
| 76 | If this variable is set to 0, no idle time is required.") | 77 | If 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. |
| 80 | This has two preferred values: `upcase' or `downcase'. | 90 | This has two preferred values: `upcase' or `downcase'. |
| 81 | Actually, any name of a function which takes a string as an argument and | 91 | Actually, any name of a function which takes a string as an argument and |
| 82 | returns another string is acceptable.") | 92 | returns 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 | ||
| 87 | This is not done for all commands since some print their own | 97 | Eldoc does not try to print function arglists, etc. after just any command, |
| 88 | messages in the echo area, and these functions would instantly overwrite | 98 | because some commands print their own messages in the echo area and these |
| 89 | them. But self-insert-command as well as most motion commands are good | 99 | functions would instantly overwrite them. But self-insert-command as well |
| 90 | candidates. | 100 | as most motion commands are good candidates. |
| 91 | 101 | ||
| 92 | It is probably best to manipulate this data structure with the commands | 102 | This variable contains an obarray of symbols; it is probably best to |
| 93 | `eldoc-add-command' and `eldoc-remove-command'.") | 103 | manipulate 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. |
| 154 | See documentation for the variable of the same name for more details. | ||
| 155 | |||
| 156 | If called interactively with no prefix argument, toggle current condition | ||
| 157 | of the mode. | ||
| 158 | If called with a positive or negative prefix argument, enable or disable | ||
| 159 | the 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. |
| 168 | If called interactively, completion matches any bound function. | 192 | If called interactively, completion on defined commands is available. |
| 169 | 193 | ||
| 170 | When point is in a sexp, the function args are not reprinted in the echo | 194 | When point is in a sexp, the function args are not reprinted in the echo |
| 171 | area after every possible interactive command because some of them print | 195 | area after every possible interactive command because some of them print |
| 172 | their own messages in the echo area; the eldoc functions would instantly | 196 | their own messages in the echo area; the eldoc functions would instantly |
| 173 | overwrite them unless it is more restrained." | 197 | overwrite 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 | |||
| 186 | overwrite them unless it is more restrained." | 210 | overwrite 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. | ||
| 218 | If called with no argument, print the first line of the variable | ||
| 219 | documentation string for the symbol at point in the echo area. | ||
| 220 | If called with a symbol, print the line for that symbol. | ||
| 221 | |||
| 222 | If the entire line cannot fit in the echo area, the variable name may be | ||
| 223 | truncated or eliminated entirely from the output to make room. | ||
| 224 | Any leading `*' in the docstring (which indicates the variable is a user | ||
| 225 | option) 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. | ||
| 256 | For the function at the beginning of the sexp which point is within, show | ||
| 257 | the defined parameters for the function in the echo area. | ||
| 258 | This information is extracted directly from the function or macro if it is | ||
| 259 | in pure lisp. | ||
| 260 | If the emacs function is a subr, the parameters are obtained from the | ||
| 261 | documentation 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. |