aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard M. Stallman1998-06-29 17:23:25 +0000
committerRichard M. Stallman1998-06-29 17:23:25 +0000
commit2cd6a032aa501a3964be9d222e65bb44ba9960f7 (patch)
treea7e91d28c1752d37bf6989548226c9834a2f86e5
parent8a2df9371a8d2c15009b943d5ec020ebbfea0ec2 (diff)
downloademacs-2cd6a032aa501a3964be9d222e65bb44ba9960f7.tar.gz
emacs-2cd6a032aa501a3964be9d222e65bb44ba9960f7.zip
Require `loadhist'. Variable
(find-function-function) variable removed. (find-function-regexp): New variable, taken from former constant in `find-function-noselect'. Can now find function definitions with parameters on a new line. (find-variable-regexp): New variable. (find-function-recenter-line): New variable. (find-function-after-hook): New variable. (find-function-search-for-symbol): subroutine, from of `find-function-noselect' (find-function-search-for-symbol): `regexp-quote' the symbol name: needed to find-function `mapcar*' for example. (find-function-noselect): Improved docstring. Don't include `library' in let. Use `symbol-file' instead of `describe-symbol-find-file' (find-function-read): Renamed from `find-function-read-function'. With optional arg now read a variable. (find-function-read): Separate `completing-read' calls for variables and functions. (find-function-do-it): If buffer found was already current push mark. Added parameter to indicate if a variable is being searched for. (find-function-do-it): Mention new `find-function-recenter-line' and `find-function-after-hook' in docstring. Use them. (find-function): Remove optional arg. Use `find-function-do-it' and `find-function-read'. (find-function-other-window): ditto. (find-function-other-frame): ditto. (find-function): Mention `find-function-recenter-line' and `find-function-after-hook' in docstring. (find-function-other-window): Remove most of docstring and add reference to `find-function' instead. (find-function-other-frame): Ditto. (find-variable-noselect): New function for finding the point of definition of variables, modeled on `find-function-noselect'. (find-variable-noselect): Use `symbol-file' instead of `describe-symbol-find-file'. (find-variable): New function. (find-variable-other-window): Ditto. (find-variable-other-frame): Ditto. (find-variable): Mention `find-function-recenter-line' and `find-function-after-hook' in docstring. (find-variable-other-window): Remove most of docstring and add reference to `find-variable' instead. (find-variable-other-frame): Ditto. (find-function-on-key): Simplified. Removed stuff now taken care of by interactive "k". (find-function-at-point): New function. (find-variable-at-point): Ditto.
-rw-r--r--lisp/emacs-lisp/find-func.el379
1 files changed, 231 insertions, 148 deletions
diff --git a/lisp/emacs-lisp/find-func.el b/lisp/emacs-lisp/find-func.el
index 9c9830b4f5a..c4f57bbdc19 100644
--- a/lisp/emacs-lisp/find-func.el
+++ b/lisp/emacs-lisp/find-func.el
@@ -1,10 +1,10 @@
1;;; find-func.el --- find the definition of the elisp function near point 1;;; find-func.el --- find the definition of the Emacs Lisp function near point
2 2
3;; Copyright (C) 1997 Free Software Foundation, Inc. 3;; Copyright (C) 1997 Free Software Foundation, Inc.
4 4
5;; Author: Jens Petersen <petersen@kurims.kyoto-u.ac.jp> 5;; Author: Jens Petersen <petersen@kurims.kyoto-u.ac.jp>
6;; Maintainer: petersen@kurims.kyoto-u.ac.jp 6;; Maintainer: petersen@kurims.kyoto-u.ac.jp
7;; Keywords: emacs-lisp, help, functions 7;; Keywords: emacs-lisp, functions, variables
8;; Created: 97/07/25 8;; Created: 97/07/25
9 9
10;; This file is part of GNU Emacs. 10;; This file is part of GNU Emacs.
@@ -28,46 +28,52 @@
28;; 28;;
29;; The funniest thing about this is that I can't imagine why a package 29;; The funniest thing about this is that I can't imagine why a package
30;; so obviously useful as this hasn't been written before!! 30;; so obviously useful as this hasn't been written before!!
31;; This probably belongs in "help.el" or somewhere like that.
32;; 31;;
33;; Put this file in your `load-path', byte-compile it and add the 32;; Put this file in your `load-path', byte-compile it and add the
34;; following code in your init file: 33;; following code in your init file:
35;; 34;;
36;; ;;; find-func 35;; ;;; find-func
37;; (load "find-function") 36;; (load "find-func")
38;; (global-set-key [(control ?c) ?f] 'find-function)
39;; (global-set-key [(control ?c) ?4 ?f] 'find-function-other-window)
40;; (global-set-key [(control ?c) ?5 ?f] 'find-function-other-frame)
41;; (global-set-key [(control ?c) ?k] 'find-function-on-key)
42;; 37;;
43;; and away you go! It does pretty much what you would expect, 38;; and away you go! The default given keybindings as the ones
44;; putting the cursor at the definition of the function at point. 39;; protected by autoload cookies at the bottom of this file. It does
40;; pretty much what you would expect, putting the cursor at the
41;; definition of the function or variable at point.
45;; 42;;
46;; The code is adapted from `describe-function', `describe-key' 43;; The code started out from `describe-function', `describe-key'
47;; ("help.el") and `fff-find-loaded-emacs-lisp-function' (Noah Friedman's 44;; ("help.el") and `fff-find-loaded-emacs-lisp-function' (Noah Friedman's
48;; "fff.el"). 45;; "fff.el").
49 46
50;;; To do:
51;;
52;; o custom?
53;;
54;; o improve handling of advice'd functions? (at the moment it goes to
55;; the advice, not the actual definition)
56
57;;;; Code: 47;;;; Code:
58 48
49(require 'loadhist)
50
59;;; User variables: 51;;; User variables:
52
60(defgroup find-function nil 53(defgroup find-function nil
61 "Find the definition of the elisp function near point." 54 "Finds the definition of the Emacs Lisp symbol near point."
62 :prefix "find-function" 55;; :prefix "find-function"
63 :group 'lisp) 56 :group 'lisp)
64 57
65(defcustom find-function-function 'function-at-point 58(defcustom find-function-regexp
66 "*The function used by `find-function' to select the function near 59 "^\\s-*(def[^cgv\W]\\w+\\*?\\s-+%s\\(\\s-\\|$\\)"
67point. 60"The regexp used by `find-function' to search for a function
61definition. Note it must contain a `%s' at the place where `format'
62should insert the function name. The default value avoids `defconst',
63`defgroup', `defvar'.
68 64
69For example `function-at-point' or `function-called-at-point'." 65Please send improvements and fixes to the maintainer."
70 :type 'function 66 :type 'regexp
67 :group 'find-function)
68
69(defcustom find-variable-regexp
70 "^\\s-*(def[^uma\W]\\w+\\*?\\s-+%s\\(\\s-\\|$\\)"
71 "The regexp used by `find-variable' to search for a variable definition.
72It should match right up to the variable name. The default value
73avoids `defun', `defmacro', `defalias', `defadvice'.
74
75Please send improvements and fixes to the maintainer."
76 :type 'regexp
71 :group 'find-function) 77 :group 'find-function)
72 78
73(defcustom find-function-source-path nil 79(defcustom find-function-source-path nil
@@ -82,71 +88,92 @@ default."
82;;; Functions: 88;;; Functions:
83 89
84;;;###autoload 90;;;###autoload
85(defun find-function-noselect (function &optional path) 91(defcustom find-function-recenter-line 1
86 "Returns list (BUFFER POINT) pointing to the definition of FUNCTION. 92 "The window line-number from which to start displaying a symbol definition.
93A value of nil implies center the beginning of the definition.
94See the function `center-to-window-line' for more information, and
95`find-function' and `find-variable'."
96 :group 'find-function)
97
98(defcustom find-function-after-hook nil
99 "Hook run after finding symbol definition.
100
101See the functions `find-function' and `find-variable'."
102 :group 'find-function)
103
104;;; Functions:
105
106(defun find-function-search-for-symbol (symbol variable-p library)
107 "Search for SYMBOL in LIBRARY.
108If VARIABLE-P is nil, `find-function-regexp' is used, otherwise
109`find-variable-regexp' is used."
110 (if (null library)
111 (error "Don't know where `%s' is defined" symbol))
112 (if (string-match "\\.el\\(c\\)\\'" library)
113 (setq library (substring library 0 (match-beginning 1))))
114 (let* ((path find-function-source-path)
115 (filename (if (file-exists-p library)
116 library
117 ;; use `file-name-sans-extension' here? (if it gets fixed)
118 (if (string-match "\\(\\.el\\)\\'" library)
119 (setq library (substring library 0
120 (match-beginning 1))))
121 (or (locate-library (concat library ".el") t path)
122 (locate-library library t path)))))
123 (if (not filename)
124 (error "The library \"%s\" is not in the path." library))
125 (with-current-buffer (find-file-noselect filename)
126 (save-match-data
127 (let ((regexp (format (if variable-p
128 find-variable-regexp
129 find-function-regexp)
130 (regexp-quote (symbol-name symbol))))
131 (syn-table (syntax-table)))
132 (unwind-protect
133 (progn
134 (set-syntax-table emacs-lisp-mode-syntax-table)
135 (goto-char (point-min))
136 (if (re-search-forward regexp nil t)
137 (progn
138 (beginning-of-line)
139 (cons (current-buffer) (point)))
140 (error "Cannot find definition of `%s' in library \"%s\""
141 symbol library)))
142 (set-syntax-table syn-table)))))))
143
144(defun find-function-noselect (function)
145 "Returns a pair (BUFFER . POINT) pointing to the definition of FUNCTION.
87 146
88Finds the Emacs Lisp library containing the definition of FUNCTION 147Finds the Emacs Lisp library containing the definition of FUNCTION
89in a buffer and places point before the definition. The buffer is 148in a buffer and the point of the definition. The buffer is
90not selected. 149not selected.
91 150
92If the optional argument PATH is given, the library where FUNCTION is 151If the file where FUNCTION is defined is not known, then it is
93defined is searched in PATH instead of `load-path' (see 152searched for in `find-function-source-path' if non `nil', otherwise
94`find-function-source-path')." 153in `load-path'."
95 (and (subrp (symbol-function function))
96 (error "%s is a primitive function" function))
97 (if (not function) 154 (if (not function)
98 (error "You didn't specify a function")) 155 (error "You didn't specify a function"))
156 (and (subrp (symbol-function function))
157 (error "%s is a primitive function" function))
99 (let ((def (symbol-function function)) 158 (let ((def (symbol-function function))
100 library aliases) 159 aliases)
101 (while (symbolp def) 160 (while (symbolp def)
102 (or (eq def function) 161 (or (eq def function)
103 (if aliases 162 (if aliases
104 (setq aliases (concat aliases 163 (setq aliases (concat aliases
105 (format ", which is an alias for %s" 164 (format ", which is an alias for `%s'"
106 (symbol-name def)))) 165 (symbol-name def))))
107 (setq aliases (format "an alias for %s" (symbol-name 166 (setq aliases (format "`%s' an alias for `%s'"
108 def))))) 167 function (symbol-name def)))))
109 (setq function (symbol-function function) 168 (setq function (symbol-function function)
110 def (symbol-function function))) 169 def (symbol-function function)))
111 (if aliases 170 (if aliases
112 (message aliases)) 171 (message aliases))
113 (setq library 172 (let ((library
114 (cond ((eq (car-safe def) 'autoload) 173 (cond ((eq (car-safe def) 'autoload)
115 (nth 1 def)) 174 (nth 1 def))
116 ((describe-function-find-file function)))) 175 ((symbol-file function)))))
117 (if (null library) 176 (find-function-search-for-symbol function nil library))))
118 (error "`%s' is not in `load-history'" function))
119 (if (string-match "\\(\\.elc?\\'\\)" library)
120 (setq library (substring library 0 (match-beginning 1))))
121 (let* ((path (or path find-function-source-path))
122 (compression (or (rassq 'jka-compr-handler file-name-handler-alist)
123 (member 'crypt-find-file-hook find-file-hooks)))
124 (filename (or (locate-library (concat library ".el")
125 t path)
126 (locate-library library t path)
127 (if compression
128 (or (locate-library (concat library ".el.gz")
129 t path)
130 (locate-library (concat library ".gz")
131 t path))))))
132 (if (not filename)
133 (error "The library \"%s\" is not in the path." library))
134 (save-excursion
135 (set-buffer (find-file-noselect filename))
136 (save-match-data
137 (let (;; avoid defconst, defgroup, defvar (any others?)
138 (regexp (format "^\\s-*(def[^cgv\W]\\w+\\s-+%s\\s-"
139 (regexp-quote (symbol-name function))))
140 (syntable (syntax-table)))
141 (set-syntax-table emacs-lisp-mode-syntax-table)
142 (goto-char (point-min))
143 (if (prog1
144 (re-search-forward regexp nil t)
145 (set-syntax-table syntable))
146 (progn
147 (beginning-of-line)
148 (list (current-buffer) (point)))
149 (error "Cannot find definition of %s" function))))))))
150 177
151(defun function-at-point () 178(defun function-at-point ()
152 (or (condition-case () 179 (or (condition-case ()
@@ -174,108 +201,164 @@ defined is searched in PATH instead of `load-path' (see
174 (and (symbolp obj) (fboundp obj) obj)))) 201 (and (symbolp obj) (fboundp obj) obj))))
175 (error nil)))) 202 (error nil))))
176 203
177(defun find-function-read-function () 204(defun find-function-read (&optional variable-p)
178 "Read and return a function, defaulting to the one near point. 205 "Read and return an interned symbol, defaulting to the one near point.
179 206
180The function named by `find-function-function' is used to select the 207If the optional VARIABLE-P is nil, then a function is gotten
181default function." 208defaulting to the value of the function `function-at-point', otherwise
182 (let ((fn (funcall find-function-function)) 209a variable is asked for, with the default coming from
210`variable-at-point'."
211 (let ((symb (funcall (if variable-p
212 'variable-at-point
213 'function-at-point)))
183 (enable-recursive-minibuffers t) 214 (enable-recursive-minibuffers t)
184 val) 215 val)
185 (setq val (completing-read 216 (if (equal symb 0)
186 (if fn 217 (setq symb nil))
187 (format "Find function (default %s): " fn) 218 (setq val (if variable-p
188 "Find function: ") 219 (completing-read
189 obarray 'fboundp t)) 220 (concat "Find variable"
221 (if symb
222 (format " (default %s)" symb))
223 ": ")
224 obarray 'boundp t nil)
225 (completing-read
226 (concat "Find function"
227 (if symb
228 (format " (default %s)" symb))
229 ": ")
230 obarray 'fboundp t nil)))
190 (list (if (equal val "") 231 (list (if (equal val "")
191 fn (intern val))))) 232 symb
233 (intern val)))))
192 234
193(defun find-function-do-it (function path switch-fn) 235(defun find-function-do-it (symbol variable-p switch-fn)
194 "Find Emacs Lisp FUNCTION in PATH and display it with SWITCH-FN. 236 "Find Emacs Lisp SYMBOL in a buffer and display it with SWITCH-FN.
195Point is saved if FUNCTION is in the current buffer." 237If VARIABLE-P is nil, a function definition is searched for, otherwise
238a variable definition is searched for. The start of a definition is
239centered according to the variable `find-function-recenter-line'.
240See also `find-function-after-hook'.
241
242Point is saved in the buffer if it is one of the current buffers."
196 (let ((orig-point (point)) 243 (let ((orig-point (point))
197 (buffer-point (find-function-noselect function path))) 244 (orig-buffers (buffer-list))
198 (if buffer-point 245 (buffer-point (funcall (if variable-p
199 (progn 246 'find-variable-noselect
200 (if (eq (current-buffer) (car buffer-point)) 247 'find-function-noselect)
201 (push-mark orig-point)) 248 symbol)))
202 (funcall switch-fn (car buffer-point)) 249 (when buffer-point
203 (goto-char (elt buffer-point 1)) 250 (funcall switch-fn (car buffer-point))
204 (recenter 0))))) 251 (when (memq (car buffer-point) orig-buffers)
252 (push-mark orig-point))
253 (goto-char (cdr buffer-point))
254 (recenter find-function-recenter-line)
255 (run-hooks find-function-after-hook))))
205 256
206;;;###autoload 257;;;###autoload
207(defun find-function (function &optional path) 258(defun find-function (function)
208 "Find the definition of the function near point in the current window. 259 "Find the definition of the function near point in the current window.
209 260
210Finds the Emacs Lisp library containing the definition of the function 261Finds the Emacs Lisp library containing the definition of the function
211near point (selected by `find-function-function') and places point 262near point (selected by `function-at-point') in a buffer and
212before the definition. Point is saved if FUNCTION is in the current 263places point before the definition. Point is saved in the buffer if
213buffer. 264it is one of the current buffers.
214 265
215If the optional argument PATH is given, the library where FUNCTION is 266The library where FUNCTION is defined is searched for in
216defined is searched in PATH instead of `load-path'" 267`find-function-source-path', if non `nil', otherwise in `load-path'.
217 (interactive (find-function-read-function)) 268See also `find-function-recenter-line' and `find-function-after-hook'."
218 (find-function-do-it function path 'switch-to-buffer)) 269 (interactive (find-function-read))
270 (find-function-do-it function nil 'switch-to-buffer))
219 271
220;;;###autoload 272;;;###autoload
221(defun find-function-other-window (function &optional path) 273(defun find-function-other-window (function)
222 "Find the definition of the function near point in the other window. 274 "Find the definition of the function near point in the other window.
223 275
224Finds the Emacs Lisp package containing the definition of the function 276See `find-function' for more details."
225near point (selected by `find-function-function') and places point 277 (interactive (find-function-read))
226before the definition. Point is saved if FUNCTION is in the current 278 (find-function-do-it function nil 'switch-to-buffer-other-window))
227buffer.
228
229If the optional argument PATH is given, the package where FUNCTION is
230defined is searched in PATH instead of `load-path'"
231 (interactive (find-function-read-function))
232 (find-function-do-it function path 'switch-to-buffer-other-window))
233 279
234;;;###autoload 280;;;###autoload
235(defun find-function-other-frame (function &optional path) 281(defun find-function-other-frame (function)
236 "Find the definition of the function near point in the another frame. 282 "Find the definition of the function near point in the another frame.
237 283
238Finds the Emacs Lisp package containing the definition of the function 284See `find-function' for more details."
239near point (selected by `find-function-function') and places point 285 (interactive (find-function-read))
240before the definition. Point is saved if FUNCTION is in the current 286 (find-function-do-it function nil 'switch-to-buffer-other-frame))
241buffer. 287
288(defun find-variable-noselect (variable)
289 "Returns a pair `(buffer . point)' pointing to the definition of SYMBOL.
290
291Finds the Emacs Lisp library containing the definition of SYMBOL
292in a buffer and the point of the definition. The buffer is
293not selected.
294
295The library where VARIABLE is defined is searched for in
296`find-function-source-path', if non `nil', otherwise in `load-path'."
297 (if (not variable)
298 (error "You didn't specify a variable"))
299 (let ((library (symbol-file variable)))
300 (find-function-search-for-symbol variable 'variable library)))
301
302;;;###autoload
303(defun find-variable (variable)
304 "Find the definition of the variable near point in the current window.
305
306Finds the Emacs Lisp library containing the definition of the variable
307near point (selected by `variable-at-point') in a buffer and
308places point before the definition. Point is saved in the buffer if
309it is one of the current buffers.
310
311The library where VARIABLE is defined is searched for in
312`find-function-source-path', if non `nil', otherwise in `load-path'.
313See also `find-function-recenter-line' and `find-function-after-hook'."
314 (interactive (find-function-read 'variable))
315 (find-function-do-it variable t 'switch-to-buffer))
242 316
243If the optional argument PATH is given, the package where FUNCTION is 317;;;###autoload
244defined is searched in PATH instead of `load-path'" 318(defun find-variable-other-window (variable)
245 (interactive (find-function-read-function)) 319 "Find the definition of the variable near point in the other window.
246 (find-function-do-it function path 'switch-to-buffer-other-frame)) 320
321See `find-variable' for more details."
322 (interactive (find-function-read 'variable))
323 (find-function-do-it variable t 'switch-to-buffer-other-window))
324
325;;;###autoload
326(defun find-variable-other-frame (variable)
327 "Find the definition of the variable near point in the another frame.
328
329See `find-variable' for more details."
330 (interactive (find-function-read 'variable))
331 (find-function-do-it variable t 'switch-to-buffer-other-frame))
247 332
248;;;###autoload 333;;;###autoload
249(defun find-function-on-key (key) 334(defun find-function-on-key (key)
250 "Find the function that KEY invokes. KEY is a string. 335 "Find the function that KEY invokes. KEY is a string.
251Point is saved if FUNCTION is in the current buffer." 336Point is saved if FUNCTION is in the current buffer."
252 (interactive "kFind function on key: ") 337 (interactive "kFind function on key: ")
253 (save-excursion 338 (let ((defn (key-binding key))
254 (let ((modifiers (event-modifiers (aref key 0))) 339 (key-desc (key-description key)))
255 window position) 340 (if (or (null defn) (integerp defn))
256 ;; For a mouse button event, go to the button it applies to 341 (message "%s is unbound" key-desc)
257 ;; to get the right key bindings. And go to the right place 342 (if (consp defn)
258 ;; in case the keymap depends on where you clicked. 343 (message "%s runs %s" key-desc (prin1-to-string defn))
259 (if (or (memq 'click modifiers) (memq 'down modifiers) 344 (find-function-other-window defn)))))
260 (memq 'drag modifiers)) 345
261 (setq window (posn-window (event-start (aref key 0))) 346;;;###autoload
262 position (posn-point (event-start (aref key 0))))) 347(defun find-function-at-point ()
263 (if (windowp window) 348 "Find directly the function at point in the other window."
264 (progn 349 (interactive)
265 (set-buffer (window-buffer window)) 350 (let ((symb (function-at-point)))
266 (goto-char position))) 351 (when symb
267 ;; Ok, now look up the key and name the command. 352 (find-function-other-window symb))))
268 (let ((defn (key-binding key))) 353
269 (if (or (null defn) (integerp defn)) 354;;;###autoload
270 (message "%s is undefined" (key-description key)) 355(defun find-variable-at-point ()
271 (if (consp defn) 356 "Find directly the function at point in the other window."
272 (message (if (windowp window) 357 (interactive)
273 "%s at that spot runs %s" 358 (let ((symb (variable-at-point)))
274 "%s runs %s") 359 (when (and symb (not (equal symb 0)))
275 (key-description key) (prin1-to-string defn)) 360 (find-variable-other-window symb))))
276 (find-function-other-window defn)))))))
277 361
278(provide 'find-func) 362(provide 'find-func)
279 363
280;;; find-func.el ends here 364;;; find-func.el ends here
281