isnan: Fix porting problem to Solaris 10 with bundled gcc.
[bpt/emacs.git] / lisp / emacs-lisp / find-func.el
CommitLineData
2cd6a032 1;;; find-func.el --- find the definition of the Emacs Lisp function near point
fffee8be 2
73b0cd50 3;; Copyright (C) 1997, 1999, 2001-2011 Free Software Foundation, Inc.
fffee8be
DL
4
5;; Author: Jens Petersen <petersen@kurims.kyoto-u.ac.jp>
6;; Maintainer: petersen@kurims.kyoto-u.ac.jp
2cd6a032 7;; Keywords: emacs-lisp, functions, variables
fffee8be
DL
8;; Created: 97/07/25
9
10;; This file is part of GNU Emacs.
11
d6cba7ae 12;; GNU Emacs is free software: you can redistribute it and/or modify
fffee8be 13;; it under the terms of the GNU General Public License as published by
d6cba7ae
GM
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
fffee8be
DL
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
d6cba7ae 23;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
fffee8be
DL
24
25;;; Commentary:
26;;
27;; The funniest thing about this is that I can't imagine why a package
28;; so obviously useful as this hasn't been written before!!
fffee8be 29;; ;;; find-func
86f28125
RS
30;; (find-function-setup-keys)
31;;
32;; or just:
33;;
2cd6a032 34;; (load "find-func")
fffee8be 35;;
86f28125 36;; if you don't like the given keybindings and away you go! It does
2cd6a032
RS
37;; pretty much what you would expect, putting the cursor at the
38;; definition of the function or variable at point.
fffee8be 39;;
2cd6a032 40;; The code started out from `describe-function', `describe-key'
fffee8be
DL
41;; ("help.el") and `fff-find-loaded-emacs-lisp-function' (Noah Friedman's
42;; "fff.el").
43
e8af40ee 44;;; Code:
fffee8be
DL
45
46;;; User variables:
2cd6a032 47
0b5bb3ec 48(defgroup find-function nil
2cd6a032
RS
49 "Finds the definition of the Emacs Lisp symbol near point."
50;; :prefix "find-function"
0b5bb3ec 51 :group 'lisp)
fffee8be 52
54cabb1b
SM
53(defconst find-function-space-re "\\(?:\\s-\\|\n\\|;.*\n\\)+")
54
2cd6a032 55(defcustom find-function-regexp
d3d4fb62
RS
56 ;; Match things like (defun foo ...), (defmacro foo ...),
57 ;; (define-skeleton foo ...), (define-generic-mode 'foo ...),
d8f479c6 58 ;; (define-derived-mode foo ...), (define-minor-mode foo)
54cabb1b
SM
59 (concat
60 "^\\s-*(\\(def\\(ine-skeleton\\|ine-generic-mode\\|ine-derived-mode\\|\
aa4a1bf8 61ine\\(?:-global\\)?-minor-mode\\|ine-compilation-mode\\|un-cvs-mode\\|\
8f1a5a9b 62foo\\|[^icfgv]\\(\\w\\|\\s_\\)+\\*?\\)\\|easy-mmode-define-[a-z-]+\\|easy-menu-define\\|\
aa4a1bf8 63menu-bar-make-toggle\\)"
fe3947c3 64 find-function-space-re
54cabb1b 65 "\\('\\|\(quote \\)?%s\\(\\s-\\|$\\|\(\\|\)\\)")
d3d4fb62
RS
66 "The regexp used by `find-function' to search for a function definition.
67Note it must contain a `%s' at the place where `format'
2cd6a032 68should insert the function name. The default value avoids `defconst',
b0339ffd 69`defgroup', `defvar', `defface'.
fffee8be 70
2cd6a032
RS
71Please send improvements and fixes to the maintainer."
72 :type 'regexp
86f28125 73 :group 'find-function
d8f479c6 74 :version "21.1")
2cd6a032
RS
75
76(defcustom find-variable-regexp
aa4a1bf8
JL
77 (concat
78 "^\\s-*(\\(def[^fumag]\\(\\w\\|\\s_\\)+\\*?\\|\
79easy-mmode-def\\(map\\|syntax\\)\\|easy-menu-define\\)"
80 find-function-space-re
81 "%s\\(\\s-\\|$\\)")
2cd6a032 82 "The regexp used by `find-variable' to search for a variable definition.
0acffda1
RS
83Note it must contain a `%s' at the place where `format'
84should insert the variable name. The default value
1b60b25a 85avoids `defun', `defmacro', `defalias', `defadvice', `defgroup', `defface'.
2cd6a032
RS
86
87Please send improvements and fixes to the maintainer."
88 :type 'regexp
86f28125 89 :group 'find-function
a469e8ba 90 :version "21.1")
fffee8be 91
0acffda1
RS
92(defcustom find-face-regexp
93 (concat"^\\s-*(defface" find-function-space-re "%s\\(\\s-\\|$\\)")
94 "The regexp used by `find-face' to search for a face definition.
95Note it must contain a `%s' at the place where `format'
96should insert the face name.
97
98Please send improvements and fixes to the maintainer."
99 :type 'regexp
100 :group 'find-function
bf247b6e 101 :version "22.1")
0acffda1
RS
102
103(defvar find-function-regexp-alist
104 '((nil . find-function-regexp)
105 (defvar . find-variable-regexp)
106 (defface . find-face-regexp))
107 "Alist mapping definition types into regexp variables.
108Each regexp variable's value should actually be a format string
109to be used to substitute the desired symbol name into the regexp.")
110(put 'find-function-regexp-alist 'risky-local-variable t)
111
0b5bb3ec 112(defcustom find-function-source-path nil
d3d4fb62 113 "The default list of directories where `find-function' searches.
fffee8be 114
d3d4fb62 115If this variable is nil then `find-function' searches `load-path' by
0b5bb3ec
SE
116default."
117 :type '(repeat directory)
118 :group 'find-function)
fffee8be 119
2cd6a032
RS
120(defcustom find-function-recenter-line 1
121 "The window line-number from which to start displaying a symbol definition.
122A value of nil implies center the beginning of the definition.
cb0fd101
JPW
123See `find-function' and `find-variable'."
124 :type '(choice (const :tag "Center" nil)
125 integer)
86f28125 126 :group 'find-function
a6223467 127 :version "20.3")
2cd6a032
RS
128
129(defcustom find-function-after-hook nil
130 "Hook run after finding symbol definition.
131
132See the functions `find-function' and `find-variable'."
d83b2f14 133 :type 'hook
86f28125 134 :group 'find-function
a6223467 135 :version "20.3")
2cd6a032
RS
136
137;;; Functions:
138
f77a6050
SM
139(defun find-library-suffixes ()
140 (let ((suffixes nil))
f352b9d7 141 (dolist (suffix (get-load-suffixes) (nreverse suffixes))
f77a6050
SM
142 (unless (string-match "elc" suffix) (push suffix suffixes)))))
143
6a2fb145
SM
144(defun find-library--load-name (library)
145 (let ((name library))
146 (dolist (dir load-path)
147 (let ((rel (file-relative-name library dir)))
148 (if (and (not (string-match "\\`\\.\\./" rel))
149 (< (length rel) (length name)))
150 (setq name rel))))
151 (unless (equal name library) name)))
152
f77a6050 153(defun find-library-name (library)
352f6bff
CY
154 "Return the absolute file name of the Emacs Lisp source of LIBRARY.
155LIBRARY should be a string (the name of the library)."
fef1f0f2
RF
156 ;; If the library is byte-compiled, try to find a source library by
157 ;; the same name.
158 (if (string-match "\\.el\\(c\\(\\..*\\)?\\)\\'" library)
1a40d81d 159 (setq library (replace-match "" t t library)))
6a2fb145 160 (or
8aa8da05
DG
161 (locate-file library
162 (or find-function-source-path load-path)
163 (find-library-suffixes))
164 (locate-file library
165 (or find-function-source-path load-path)
166 load-file-rep-suffixes)
6a2fb145
SM
167 (when (file-name-absolute-p library)
168 (let ((rel (find-library--load-name library)))
169 (when rel
170 (or
171 (locate-file rel
172 (or find-function-source-path load-path)
173 (find-library-suffixes))
174 (locate-file rel
175 (or find-function-source-path load-path)
176 load-file-rep-suffixes)))))
8aa8da05 177 (error "Can't find library %s" library)))
f77a6050 178
4479a2f8
SM
179(defvar find-function-C-source-directory
180 (let ((dir (expand-file-name "src" source-directory)))
181 (when (and (file-directory-p dir) (file-readable-p dir))
182 dir))
183 "Directory where the C source files of Emacs can be found.
184If nil, do not try to find the source code of functions and variables
185defined in C.")
186
f5e7fddd
GM
187(declare-function ad-get-advice-info "advice" (function))
188
189(defun find-function-advised-original (func)
190 "Return the original function symbol of an advised function FUNC.
191If FUNC is not the symbol of an advised function, just returns FUNC."
192 (or (and (symbolp func)
193 (featurep 'advice)
194 (let ((ofunc (cdr (assq 'origname (ad-get-advice-info func)))))
195 (and (fboundp ofunc) ofunc)))
196 func))
197
0acffda1 198(defun find-function-C-source (fun-or-var file type)
3bdedbcb 199 "Find the source location where FUN-OR-VAR is defined in FILE.
0acffda1 200TYPE should be nil to find a function, or `defvar' to find a variable."
4479a2f8
SM
201 (unless find-function-C-source-directory
202 (setq find-function-C-source-directory
203 (read-directory-name "Emacs C source dir: " nil nil t)))
204 (setq file (expand-file-name file find-function-C-source-directory))
205 (unless (file-readable-p file)
206 (error "The C source file %s is not available"
207 (file-name-nondirectory file)))
0acffda1 208 (unless type
f5e7fddd
GM
209 ;; Either or both an alias and its target might be advised.
210 (setq fun-or-var (find-function-advised-original
211 (indirect-function
212 (find-function-advised-original fun-or-var)))))
4479a2f8
SM
213 (with-current-buffer (find-file-noselect file)
214 (goto-char (point-min))
215 (unless (re-search-forward
0acffda1 216 (if type
4479a2f8
SM
217 (concat "DEFVAR[A-Z_]*[ \t\n]*([ \t\n]*\""
218 (regexp-quote (symbol-name fun-or-var))
219 "\"")
220 (concat "DEFUN[ \t\n]*([ \t\n]*\""
221 (regexp-quote (subr-name fun-or-var))
222 "\""))
223 nil t)
224 (error "Can't find source for %s" fun-or-var))
225 (cons (current-buffer) (match-beginning 0))))
226
f77a6050
SM
227;;;###autoload
228(defun find-library (library)
352f6bff
CY
229 "Find the Emacs Lisp source of LIBRARY.
230LIBRARY should be a string (the name of the library)."
f77a6050 231 (interactive
e8dab975
SM
232 (let* ((dirs (or find-function-source-path load-path))
233 (suffixes (find-library-suffixes))
7c23d9e8
SM
234 (table (apply-partially 'locate-file-completion-table
235 dirs suffixes))
c896ea95 236 (def (if (eq (function-called-at-point) 'require)
d454552c
MR
237 ;; `function-called-at-point' may return 'require
238 ;; with `point' anywhere on this line. So wrap the
239 ;; `save-excursion' below in a `condition-case' to
240 ;; avoid reporting a scan-error here.
241 (condition-case nil
242 (save-excursion
243 (backward-up-list)
244 (forward-char)
245 (forward-sexp 2)
246 (thing-at-point 'symbol))
247 (error nil))
c896ea95 248 (thing-at-point 'symbol))))
7c23d9e8
SM
249 (when (and def (not (test-completion def table)))
250 (setq def nil))
c896ea95
VJL
251 (list
252 (completing-read (if def (format "Library name (default %s): " def)
253 "Library name: ")
7c23d9e8 254 table nil nil nil nil def))))
f77a6050
SM
255 (let ((buf (find-file-noselect (find-library-name library))))
256 (condition-case nil (switch-to-buffer buf) (error (pop-to-buffer buf)))))
257
a4f43048 258;;;###autoload
0acffda1
RS
259(defun find-function-search-for-symbol (symbol type library)
260 "Search for SYMBOL's definition of type TYPE in LIBRARY.
39ff5f64
RS
261Visit the library in a buffer, and return a cons cell (BUFFER . POSITION),
262or just (BUFFER . nil) if the definition can't be found in the file.
263
0acffda1
RS
264If TYPE is nil, look for a function definition.
265Otherwise, TYPE specifies the kind of definition,
266and it is interpreted via `find-function-regexp-alist'.
267The search is done in the source for library LIBRARY."
2cd6a032
RS
268 (if (null library)
269 (error "Don't know where `%s' is defined" symbol))
2bef95e5
RS
270 ;; Some functions are defined as part of the construct
271 ;; that defines something else.
4479a2f8 272 (while (and (symbolp symbol) (get symbol 'definition-name))
2bef95e5 273 (setq symbol (get symbol 'definition-name)))
14f798ff 274 (if (string-match "\\`src/\\(.*\\.\\(c\\|m\\)\\)\\'" library)
0acffda1 275 (find-function-C-source symbol (match-string 1 library) type)
5c8a04f1
MR
276 (when (string-match "\\.el\\(c\\)\\'" library)
277 (setq library (substring library 0 (match-beginning 1))))
278 ;; Strip extension from .emacs.el to make sure symbol is searched in
279 ;; .emacs too.
280 (when (string-match "\\.emacs\\(.el\\)" library)
281 (setq library (substring library 0 (match-beginning 1))))
0acffda1
RS
282 (let* ((filename (find-library-name library))
283 (regexp-symbol (cdr (assq type find-function-regexp-alist))))
78b6524e 284 (with-current-buffer (find-file-noselect filename)
0acffda1 285 (let ((regexp (format (symbol-value regexp-symbol)
35b6eb23
NR
286 ;; Entry for ` (backquote) macro in loaddefs.el,
287 ;; (defalias (quote \`)..., has a \ but
288 ;; (symbol-name symbol) doesn't. Add an
289 ;; optional \ to catch this.
73584626
NR
290 (concat "\\\\?"
291 (regexp-quote (symbol-name symbol)))))
77186c62 292 (case-fold-search))
fe75e6d0
MR
293 (with-syntax-table emacs-lisp-mode-syntax-table
294 (goto-char (point-min))
295 (if (or (re-search-forward regexp nil t)
a04e10bc
SM
296 ;; `regexp' matches definitions using known forms like
297 ;; `defun', or `defvar'. But some functions/variables
298 ;; are defined using special macros (or functions), so
299 ;; if `regexp' can't find the definition, we look for
300 ;; something of the form "(SOMETHING <symbol> ...)".
301 ;; This fails to distinguish function definitions from
302 ;; variable declarations (or even uses thereof), but is
303 ;; a good pragmatic fallback.
fe75e6d0 304 (re-search-forward
2b690e5b 305 (concat "^([^ ]+" find-function-space-re "['(]?"
fe75e6d0 306 (regexp-quote (symbol-name symbol))
b0339ffd 307 "\\_>")
fe75e6d0
MR
308 nil t))
309 (progn
310 (beginning-of-line)
311 (cons (current-buffer) (point)))
39ff5f64 312 (cons (current-buffer) nil))))))))
2cd6a032 313
8a8a9abe 314;;;###autoload
23a8a5ab 315(defun find-function-noselect (function &optional lisp-only)
d3d4fb62 316 "Return a pair (BUFFER . POINT) pointing to the definition of FUNCTION.
fffee8be 317
3bdedbcb 318Finds the source file containing the definition of FUNCTION
2cd6a032 319in a buffer and the point of the definition. The buffer is
39ff5f64
RS
320not selected. If the function definition can't be found in
321the buffer, returns (BUFFER).
fffee8be 322
23a8a5ab
CY
323If FUNCTION is a built-in function, this function normally
324attempts to find it in the Emacs C sources; however, if LISP-ONLY
325is non-nil, signal an error instead.
326
2cd6a032 327If the file where FUNCTION is defined is not known, then it is
373ed135 328searched for in `find-function-source-path' if non-nil, otherwise
2cd6a032 329in `load-path'."
fffee8be 330 (if (not function)
f5e7fddd
GM
331 (error "You didn't specify a function"))
332 (let ((def (symbol-function (find-function-advised-original function)))
2cd6a032 333 aliases)
f5e7fddd
GM
334 ;; FIXME for completeness, it might be nice to print something like:
335 ;; foo (which is advised), which is an alias for bar (which is advised).
fffee8be
DL
336 (while (symbolp def)
337 (or (eq def function)
338 (if aliases
339 (setq aliases (concat aliases
2cd6a032 340 (format ", which is an alias for `%s'"
fffee8be 341 (symbol-name def))))
f5e7fddd 342 (setq aliases (format "`%s' is an alias for `%s'"
2cd6a032 343 function (symbol-name def)))))
f5e7fddd
GM
344 (setq function (symbol-function (find-function-advised-original function))
345 def (symbol-function (find-function-advised-original function))))
fffee8be 346 (if aliases
55aed120 347 (message "%s" aliases))
2cd6a032
RS
348 (let ((library
349 (cond ((eq (car-safe def) 'autoload)
350 (nth 1 def))
6dfa731f 351 ((subrp def)
23a8a5ab
CY
352 (if lisp-only
353 (error "%s is a built-in function" function))
6dfa731f 354 (help-C-file-name def 'subr))
9f14330b 355 ((symbol-file function 'defun)))))
2cd6a032 356 (find-function-search-for-symbol function nil library))))
fffee8be 357
0acffda1 358(defun find-function-read (&optional type)
2cd6a032 359 "Read and return an interned symbol, defaulting to the one near point.
fffee8be 360
0acffda1
RS
361If TYPE is nil, insist on a symbol with a function definition.
362Otherwise TYPE should be `defvar' or `defface'.
363If TYPE is nil, defaults using `function-called-at-point',
364otherwise uses `variable-at-point'."
365 (let ((symb (if (null type)
366 (function-called-at-point)
367 (if (eq type 'defvar)
368 (variable-at-point)
369 (variable-at-point t))))
370 (predicate (cdr (assq type '((nil . fboundp) (defvar . boundp)
371 (defface . facep)))))
372 (prompt (cdr (assq type '((nil . "function") (defvar . "variable")
373 (defface . "face")))))
fffee8be
DL
374 (enable-recursive-minibuffers t)
375 val)
2cd6a032
RS
376 (if (equal symb 0)
377 (setq symb nil))
0acffda1
RS
378 (setq val (completing-read
379 (concat "Find "
380 prompt
381 (if symb
382 (format " (default %s)" symb))
383 ": ")
384 obarray predicate t nil))
fffee8be 385 (list (if (equal val "")
2cd6a032
RS
386 symb
387 (intern val)))))
fffee8be 388
0acffda1 389(defun find-function-do-it (symbol type switch-fn)
d3d4fb62 390 "Find Emacs Lisp SYMBOL in a buffer and display it.
0acffda1
RS
391TYPE is nil to search for a function definition,
392or else `defvar' or `defface'.
393
394The variable `find-function-recenter-line' controls how
395to recenter the display. SWITCH-FN is the function to call
396to display and select the buffer.
397See also `find-function-after-hook'.
2cd6a032 398
0acffda1 399Set mark before moving, if the buffer already existed."
86f28125
RS
400 (let* ((orig-point (point))
401 (orig-buf (window-buffer))
2cd6a032 402 (orig-buffers (buffer-list))
86f28125 403 (buffer-point (save-excursion
0acffda1 404 (find-definition-noselect symbol type)))
86f28125
RS
405 (new-buf (car buffer-point))
406 (new-point (cdr buffer-point)))
2cd6a032 407 (when buffer-point
86f28125 408 (when (memq new-buf orig-buffers)
2cd6a032 409 (push-mark orig-point))
86f28125 410 (funcall switch-fn new-buf)
39ff5f64 411 (when new-point (goto-char new-point))
2cd6a032 412 (recenter find-function-recenter-line)
8d8ca3cf 413 (run-hooks 'find-function-after-hook))))
fffee8be 414
b07745ec 415;;;###autoload
2cd6a032 416(defun find-function (function)
c7efc289 417 "Find the definition of the FUNCTION near point.
fffee8be 418
3bdedbcb 419Finds the source file containing the definition of the function
436c08c2 420near point (selected by `function-called-at-point') in a buffer and
0acffda1
RS
421places point before the definition.
422Set mark before moving, if the buffer already existed.
fffee8be 423
2cd6a032 424The library where FUNCTION is defined is searched for in
373ed135 425`find-function-source-path', if non-nil, otherwise in `load-path'.
2cd6a032
RS
426See also `find-function-recenter-line' and `find-function-after-hook'."
427 (interactive (find-function-read))
428 (find-function-do-it function nil 'switch-to-buffer))
fffee8be 429
b07745ec 430;;;###autoload
2cd6a032 431(defun find-function-other-window (function)
c7efc289 432 "Find, in another window, the definition of FUNCTION near point.
fffee8be 433
2cd6a032
RS
434See `find-function' for more details."
435 (interactive (find-function-read))
436 (find-function-do-it function nil 'switch-to-buffer-other-window))
fffee8be 437
b07745ec 438;;;###autoload
2cd6a032 439(defun find-function-other-frame (function)
3bdedbcb 440 "Find, in another frame, the definition of FUNCTION near point.
fffee8be 441
2cd6a032
RS
442See `find-function' for more details."
443 (interactive (find-function-read))
444 (find-function-do-it function nil 'switch-to-buffer-other-frame))
445
e1acbda2 446;;;###autoload
1c787e34 447(defun find-variable-noselect (variable &optional file)
3bdedbcb 448 "Return a pair `(BUFFER . POINT)' pointing to the definition of VARIABLE.
2cd6a032 449
3bdedbcb
EZ
450Finds the library containing the definition of VARIABLE in a buffer and
451the point of the definition. The buffer is not selected.
39ff5f64 452If the variable's definition can't be found in the buffer, return (BUFFER).
2cd6a032 453
1c787e34 454The library where VARIABLE is defined is searched for in FILE or
373ed135 455`find-function-source-path', if non-nil, otherwise in `load-path'."
2cd6a032 456 (if (not variable)
3bdedbcb
EZ
457 (error "You didn't specify a variable")
458 (let ((library (or file
459 (symbol-file variable 'defvar)
460 (help-C-file-name variable 'var))))
461 (find-function-search-for-symbol variable 'defvar library))))
2cd6a032
RS
462
463;;;###autoload
464(defun find-variable (variable)
ebfb5ed9 465 "Find the definition of the VARIABLE at or before point.
2cd6a032 466
3bdedbcb 467Finds the library containing the definition of the variable
2cd6a032 468near point (selected by `variable-at-point') in a buffer and
0acffda1
RS
469places point before the definition.
470
471Set mark before moving, if the buffer already existed.
2cd6a032
RS
472
473The library where VARIABLE is defined is searched for in
373ed135 474`find-function-source-path', if non-nil, otherwise in `load-path'.
2cd6a032 475See also `find-function-recenter-line' and `find-function-after-hook'."
436c08c2
RS
476 (interactive (find-function-read 'defvar))
477 (find-function-do-it variable 'defvar 'switch-to-buffer))
fffee8be 478
2cd6a032
RS
479;;;###autoload
480(defun find-variable-other-window (variable)
c7efc289 481 "Find, in another window, the definition of VARIABLE near point.
2cd6a032
RS
482
483See `find-variable' for more details."
436c08c2
RS
484 (interactive (find-function-read 'defvar))
485 (find-function-do-it variable 'defvar 'switch-to-buffer-other-window))
2cd6a032
RS
486
487;;;###autoload
488(defun find-variable-other-frame (variable)
3bdedbcb 489 "Find, in another frame, the definition of VARIABLE near point.
2cd6a032
RS
490
491See `find-variable' for more details."
436c08c2
RS
492 (interactive (find-function-read 'defvar))
493 (find-function-do-it variable 'defvar 'switch-to-buffer-other-frame))
fffee8be 494
0acffda1
RS
495;;;###autoload
496(defun find-definition-noselect (symbol type &optional file)
497 "Return a pair `(BUFFER . POINT)' pointing to the definition of SYMBOL.
39ff5f64 498If the definition can't be found in the buffer, return (BUFFER).
3bdedbcb 499TYPE says what type of definition: nil for a function, `defvar' for a
c67a6c48 500variable, `defface' for a face. This function does not switch to the
3bdedbcb 501buffer nor display it.
0acffda1
RS
502
503The library where SYMBOL is defined is searched for in FILE or
373ed135 504`find-function-source-path', if non-nil, otherwise in `load-path'."
3bdedbcb
EZ
505 (cond
506 ((not symbol)
507 (error "You didn't specify a symbol"))
508 ((null type)
509 (find-function-noselect symbol))
510 ((eq type 'defvar)
511 (find-variable-noselect symbol file))
512 (t
0acffda1 513 (let ((library (or file (symbol-file symbol type))))
3bdedbcb 514 (find-function-search-for-symbol symbol type library)))))
0acffda1 515
c7ce7fc4
RS
516;; For symmetry, this should be called find-face; but some programs
517;; assume that, if that name is defined, it means something else.
0acffda1 518;;;###autoload
c7ce7fc4 519(defun find-face-definition (face)
0acffda1
RS
520 "Find the definition of FACE. FACE defaults to the name near point.
521
522Finds the Emacs Lisp library containing the definition of the face
523near point (selected by `variable-at-point') in a buffer and
524places point before the definition.
525
526Set mark before moving, if the buffer already existed.
527
528The library where FACE is defined is searched for in
373ed135 529`find-function-source-path', if non-nil, otherwise in `load-path'.
0acffda1
RS
530See also `find-function-recenter-line' and `find-function-after-hook'."
531 (interactive (find-function-read 'defface))
532 (find-function-do-it face 'defface 'switch-to-buffer))
533
b07745ec 534;;;###autoload
fffee8be
DL
535(defun find-function-on-key (key)
536 "Find the function that KEY invokes. KEY is a string.
0acffda1 537Set mark before moving, if the buffer already existed."
fffee8be 538 (interactive "kFind function on key: ")
cb4f3fc8
RS
539 (let (defn)
540 (save-excursion
541 (let* ((event (and (eventp key) (aref key 0))) ; Null event OK below.
542 (start (event-start event))
543 (modifiers (event-modifiers event))
544 (window (and (or (memq 'click modifiers) (memq 'down modifiers)
545 (memq 'drag modifiers))
546 (posn-window start))))
547 ;; For a mouse button event, go to the button it applies to
548 ;; to get the right key bindings. And go to the right place
549 ;; in case the keymap depends on where you clicked.
550 (when (windowp window)
551 (set-buffer (window-buffer window))
552 (goto-char (posn-point start)))
553 (setq defn (key-binding key))))
554 (let ((key-desc (key-description key)))
555 (if (or (null defn) (integerp defn))
556 (message "%s is unbound" key-desc)
557 (if (consp defn)
558 (message "%s runs %s" key-desc (prin1-to-string defn))
559 (find-function-other-window defn))))))
2cd6a032
RS
560
561;;;###autoload
562(defun find-function-at-point ()
563 "Find directly the function at point in the other window."
564 (interactive)
436c08c2 565 (let ((symb (function-called-at-point)))
2cd6a032
RS
566 (when symb
567 (find-function-other-window symb))))
568
569;;;###autoload
570(defun find-variable-at-point ()
3bdedbcb 571 "Find directly the variable at point in the other window."
2cd6a032
RS
572 (interactive)
573 (let ((symb (variable-at-point)))
574 (when (and symb (not (equal symb 0)))
575 (find-variable-other-window symb))))
fffee8be 576
86f28125
RS
577;;;###autoload
578(defun find-function-setup-keys ()
579 "Define some key bindings for the find-function family of functions."
580 (define-key ctl-x-map "F" 'find-function)
581 (define-key ctl-x-4-map "F" 'find-function-other-window)
582 (define-key ctl-x-5-map "F" 'find-function-other-frame)
583 (define-key ctl-x-map "K" 'find-function-on-key)
584 (define-key ctl-x-map "V" 'find-variable)
585 (define-key ctl-x-4-map "V" 'find-variable-other-window)
586 (define-key ctl-x-5-map "V" 'find-variable-other-frame))
587
fffee8be
DL
588(provide 'find-func)
589
590;;; find-func.el ends here