Remove trailing / from $ns_appbindir
[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
acaf905b 3;; Copyright (C) 1997, 1999, 2001-2012 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."
77694924
SM
201 (let ((dir (or find-function-C-source-directory
202 (read-directory-name "Emacs C source dir: " nil nil t))))
203 (setq file (expand-file-name file dir))
204 (if (file-readable-p file)
205 (if (null find-function-C-source-directory)
206 (setq find-function-C-source-directory dir))
207 (error "The C source file %s is not available"
208 (file-name-nondirectory file))))
0acffda1 209 (unless type
f5e7fddd
GM
210 ;; Either or both an alias and its target might be advised.
211 (setq fun-or-var (find-function-advised-original
212 (indirect-function
213 (find-function-advised-original fun-or-var)))))
4479a2f8
SM
214 (with-current-buffer (find-file-noselect file)
215 (goto-char (point-min))
216 (unless (re-search-forward
0acffda1 217 (if type
4479a2f8
SM
218 (concat "DEFVAR[A-Z_]*[ \t\n]*([ \t\n]*\""
219 (regexp-quote (symbol-name fun-or-var))
220 "\"")
221 (concat "DEFUN[ \t\n]*([ \t\n]*\""
222 (regexp-quote (subr-name fun-or-var))
223 "\""))
224 nil t)
225 (error "Can't find source for %s" fun-or-var))
226 (cons (current-buffer) (match-beginning 0))))
227
f77a6050
SM
228;;;###autoload
229(defun find-library (library)
352f6bff
CY
230 "Find the Emacs Lisp source of LIBRARY.
231LIBRARY should be a string (the name of the library)."
f77a6050 232 (interactive
e8dab975
SM
233 (let* ((dirs (or find-function-source-path load-path))
234 (suffixes (find-library-suffixes))
7c23d9e8
SM
235 (table (apply-partially 'locate-file-completion-table
236 dirs suffixes))
c896ea95 237 (def (if (eq (function-called-at-point) 'require)
d454552c
MR
238 ;; `function-called-at-point' may return 'require
239 ;; with `point' anywhere on this line. So wrap the
240 ;; `save-excursion' below in a `condition-case' to
241 ;; avoid reporting a scan-error here.
242 (condition-case nil
243 (save-excursion
244 (backward-up-list)
245 (forward-char)
246 (forward-sexp 2)
247 (thing-at-point 'symbol))
248 (error nil))
c896ea95 249 (thing-at-point 'symbol))))
7c23d9e8
SM
250 (when (and def (not (test-completion def table)))
251 (setq def nil))
c896ea95
VJL
252 (list
253 (completing-read (if def (format "Library name (default %s): " def)
254 "Library name: ")
7c23d9e8 255 table nil nil nil nil def))))
f77a6050
SM
256 (let ((buf (find-file-noselect (find-library-name library))))
257 (condition-case nil (switch-to-buffer buf) (error (pop-to-buffer buf)))))
258
a4f43048 259;;;###autoload
0acffda1
RS
260(defun find-function-search-for-symbol (symbol type library)
261 "Search for SYMBOL's definition of type TYPE in LIBRARY.
39ff5f64
RS
262Visit the library in a buffer, and return a cons cell (BUFFER . POSITION),
263or just (BUFFER . nil) if the definition can't be found in the file.
264
0acffda1
RS
265If TYPE is nil, look for a function definition.
266Otherwise, TYPE specifies the kind of definition,
267and it is interpreted via `find-function-regexp-alist'.
268The search is done in the source for library LIBRARY."
2cd6a032
RS
269 (if (null library)
270 (error "Don't know where `%s' is defined" symbol))
2bef95e5
RS
271 ;; Some functions are defined as part of the construct
272 ;; that defines something else.
4479a2f8 273 (while (and (symbolp symbol) (get symbol 'definition-name))
2bef95e5 274 (setq symbol (get symbol 'definition-name)))
14f798ff 275 (if (string-match "\\`src/\\(.*\\.\\(c\\|m\\)\\)\\'" library)
0acffda1 276 (find-function-C-source symbol (match-string 1 library) type)
5c8a04f1
MR
277 (when (string-match "\\.el\\(c\\)\\'" library)
278 (setq library (substring library 0 (match-beginning 1))))
279 ;; Strip extension from .emacs.el to make sure symbol is searched in
280 ;; .emacs too.
281 (when (string-match "\\.emacs\\(.el\\)" library)
282 (setq library (substring library 0 (match-beginning 1))))
0acffda1
RS
283 (let* ((filename (find-library-name library))
284 (regexp-symbol (cdr (assq type find-function-regexp-alist))))
78b6524e 285 (with-current-buffer (find-file-noselect filename)
0acffda1 286 (let ((regexp (format (symbol-value regexp-symbol)
35b6eb23
NR
287 ;; Entry for ` (backquote) macro in loaddefs.el,
288 ;; (defalias (quote \`)..., has a \ but
289 ;; (symbol-name symbol) doesn't. Add an
290 ;; optional \ to catch this.
73584626
NR
291 (concat "\\\\?"
292 (regexp-quote (symbol-name symbol)))))
77186c62 293 (case-fold-search))
fe75e6d0
MR
294 (with-syntax-table emacs-lisp-mode-syntax-table
295 (goto-char (point-min))
296 (if (or (re-search-forward regexp nil t)
a04e10bc
SM
297 ;; `regexp' matches definitions using known forms like
298 ;; `defun', or `defvar'. But some functions/variables
299 ;; are defined using special macros (or functions), so
300 ;; if `regexp' can't find the definition, we look for
301 ;; something of the form "(SOMETHING <symbol> ...)".
302 ;; This fails to distinguish function definitions from
303 ;; variable declarations (or even uses thereof), but is
304 ;; a good pragmatic fallback.
fe75e6d0 305 (re-search-forward
2b690e5b 306 (concat "^([^ ]+" find-function-space-re "['(]?"
fe75e6d0 307 (regexp-quote (symbol-name symbol))
b0339ffd 308 "\\_>")
fe75e6d0
MR
309 nil t))
310 (progn
311 (beginning-of-line)
312 (cons (current-buffer) (point)))
39ff5f64 313 (cons (current-buffer) nil))))))))
2cd6a032 314
8a8a9abe 315;;;###autoload
23a8a5ab 316(defun find-function-noselect (function &optional lisp-only)
d3d4fb62 317 "Return a pair (BUFFER . POINT) pointing to the definition of FUNCTION.
fffee8be 318
3bdedbcb 319Finds the source file containing the definition of FUNCTION
2cd6a032 320in a buffer and the point of the definition. The buffer is
39ff5f64
RS
321not selected. If the function definition can't be found in
322the buffer, returns (BUFFER).
fffee8be 323
23a8a5ab
CY
324If FUNCTION is a built-in function, this function normally
325attempts to find it in the Emacs C sources; however, if LISP-ONLY
326is non-nil, signal an error instead.
327
2cd6a032 328If the file where FUNCTION is defined is not known, then it is
373ed135 329searched for in `find-function-source-path' if non-nil, otherwise
2cd6a032 330in `load-path'."
fffee8be 331 (if (not function)
f5e7fddd
GM
332 (error "You didn't specify a function"))
333 (let ((def (symbol-function (find-function-advised-original function)))
2cd6a032 334 aliases)
f5e7fddd
GM
335 ;; FIXME for completeness, it might be nice to print something like:
336 ;; foo (which is advised), which is an alias for bar (which is advised).
fffee8be
DL
337 (while (symbolp def)
338 (or (eq def function)
339 (if aliases
340 (setq aliases (concat aliases
2cd6a032 341 (format ", which is an alias for `%s'"
fffee8be 342 (symbol-name def))))
f5e7fddd 343 (setq aliases (format "`%s' is an alias for `%s'"
2cd6a032 344 function (symbol-name def)))))
f5e7fddd
GM
345 (setq function (symbol-function (find-function-advised-original function))
346 def (symbol-function (find-function-advised-original function))))
fffee8be 347 (if aliases
55aed120 348 (message "%s" aliases))
2cd6a032
RS
349 (let ((library
350 (cond ((eq (car-safe def) 'autoload)
351 (nth 1 def))
6dfa731f 352 ((subrp def)
23a8a5ab
CY
353 (if lisp-only
354 (error "%s is a built-in function" function))
6dfa731f 355 (help-C-file-name def 'subr))
9f14330b 356 ((symbol-file function 'defun)))))
2cd6a032 357 (find-function-search-for-symbol function nil library))))
fffee8be 358
0acffda1 359(defun find-function-read (&optional type)
2cd6a032 360 "Read and return an interned symbol, defaulting to the one near point.
fffee8be 361
0acffda1
RS
362If TYPE is nil, insist on a symbol with a function definition.
363Otherwise TYPE should be `defvar' or `defface'.
364If TYPE is nil, defaults using `function-called-at-point',
365otherwise uses `variable-at-point'."
341cabd8 366 (let* ((symb1 (cond ((null type) (function-called-at-point))
367 ((eq type 'defvar) (variable-at-point))
368 (t (variable-at-point t))))
369 (symb (unless (eq symb1 0) symb1))
370 (predicate (cdr (assq type '((nil . fboundp)
371 (defvar . boundp)
372 (defface . facep)))))
373 (prompt-type (cdr (assq type '((nil . "function")
374 (defvar . "variable")
375 (defface . "face")))))
376 (prompt (concat "Find " prompt-type
377 (and symb (format " (default %s)" symb))
378 ": "))
379 (enable-recursive-minibuffers t))
380 (list (intern (completing-read
381 prompt obarray predicate
382 t nil nil (and symb (symbol-name symb)))))))
fffee8be 383
0acffda1 384(defun find-function-do-it (symbol type switch-fn)
d3d4fb62 385 "Find Emacs Lisp SYMBOL in a buffer and display it.
0acffda1
RS
386TYPE is nil to search for a function definition,
387or else `defvar' or `defface'.
388
389The variable `find-function-recenter-line' controls how
390to recenter the display. SWITCH-FN is the function to call
391to display and select the buffer.
392See also `find-function-after-hook'.
2cd6a032 393
0acffda1 394Set mark before moving, if the buffer already existed."
86f28125
RS
395 (let* ((orig-point (point))
396 (orig-buf (window-buffer))
2cd6a032 397 (orig-buffers (buffer-list))
86f28125 398 (buffer-point (save-excursion
0acffda1 399 (find-definition-noselect symbol type)))
86f28125
RS
400 (new-buf (car buffer-point))
401 (new-point (cdr buffer-point)))
2cd6a032 402 (when buffer-point
86f28125 403 (when (memq new-buf orig-buffers)
2cd6a032 404 (push-mark orig-point))
86f28125 405 (funcall switch-fn new-buf)
39ff5f64 406 (when new-point (goto-char new-point))
2cd6a032 407 (recenter find-function-recenter-line)
8d8ca3cf 408 (run-hooks 'find-function-after-hook))))
fffee8be 409
b07745ec 410;;;###autoload
2cd6a032 411(defun find-function (function)
c7efc289 412 "Find the definition of the FUNCTION near point.
fffee8be 413
3bdedbcb 414Finds the source file containing the definition of the function
436c08c2 415near point (selected by `function-called-at-point') in a buffer and
0acffda1
RS
416places point before the definition.
417Set mark before moving, if the buffer already existed.
fffee8be 418
2cd6a032 419The library where FUNCTION is defined is searched for in
373ed135 420`find-function-source-path', if non-nil, otherwise in `load-path'.
2cd6a032
RS
421See also `find-function-recenter-line' and `find-function-after-hook'."
422 (interactive (find-function-read))
423 (find-function-do-it function nil 'switch-to-buffer))
fffee8be 424
b07745ec 425;;;###autoload
2cd6a032 426(defun find-function-other-window (function)
c7efc289 427 "Find, in another window, the definition of FUNCTION near point.
fffee8be 428
2cd6a032
RS
429See `find-function' for more details."
430 (interactive (find-function-read))
431 (find-function-do-it function nil 'switch-to-buffer-other-window))
fffee8be 432
b07745ec 433;;;###autoload
2cd6a032 434(defun find-function-other-frame (function)
3bdedbcb 435 "Find, in another frame, the definition of FUNCTION near point.
fffee8be 436
2cd6a032
RS
437See `find-function' for more details."
438 (interactive (find-function-read))
439 (find-function-do-it function nil 'switch-to-buffer-other-frame))
440
e1acbda2 441;;;###autoload
1c787e34 442(defun find-variable-noselect (variable &optional file)
3bdedbcb 443 "Return a pair `(BUFFER . POINT)' pointing to the definition of VARIABLE.
2cd6a032 444
3bdedbcb
EZ
445Finds the library containing the definition of VARIABLE in a buffer and
446the point of the definition. The buffer is not selected.
39ff5f64 447If the variable's definition can't be found in the buffer, return (BUFFER).
2cd6a032 448
1c787e34 449The library where VARIABLE is defined is searched for in FILE or
373ed135 450`find-function-source-path', if non-nil, otherwise in `load-path'."
2cd6a032 451 (if (not variable)
3bdedbcb
EZ
452 (error "You didn't specify a variable")
453 (let ((library (or file
454 (symbol-file variable 'defvar)
455 (help-C-file-name variable 'var))))
456 (find-function-search-for-symbol variable 'defvar library))))
2cd6a032
RS
457
458;;;###autoload
459(defun find-variable (variable)
ebfb5ed9 460 "Find the definition of the VARIABLE at or before point.
2cd6a032 461
3bdedbcb 462Finds the library containing the definition of the variable
2cd6a032 463near point (selected by `variable-at-point') in a buffer and
0acffda1
RS
464places point before the definition.
465
466Set mark before moving, if the buffer already existed.
2cd6a032
RS
467
468The library where VARIABLE is defined is searched for in
373ed135 469`find-function-source-path', if non-nil, otherwise in `load-path'.
2cd6a032 470See also `find-function-recenter-line' and `find-function-after-hook'."
436c08c2
RS
471 (interactive (find-function-read 'defvar))
472 (find-function-do-it variable 'defvar 'switch-to-buffer))
fffee8be 473
2cd6a032
RS
474;;;###autoload
475(defun find-variable-other-window (variable)
c7efc289 476 "Find, in another window, the definition of VARIABLE near point.
2cd6a032
RS
477
478See `find-variable' for more details."
436c08c2
RS
479 (interactive (find-function-read 'defvar))
480 (find-function-do-it variable 'defvar 'switch-to-buffer-other-window))
2cd6a032
RS
481
482;;;###autoload
483(defun find-variable-other-frame (variable)
3bdedbcb 484 "Find, in another frame, the definition of VARIABLE near point.
2cd6a032
RS
485
486See `find-variable' for more details."
436c08c2
RS
487 (interactive (find-function-read 'defvar))
488 (find-function-do-it variable 'defvar 'switch-to-buffer-other-frame))
fffee8be 489
0acffda1
RS
490;;;###autoload
491(defun find-definition-noselect (symbol type &optional file)
492 "Return a pair `(BUFFER . POINT)' pointing to the definition of SYMBOL.
39ff5f64 493If the definition can't be found in the buffer, return (BUFFER).
3bdedbcb 494TYPE says what type of definition: nil for a function, `defvar' for a
c67a6c48 495variable, `defface' for a face. This function does not switch to the
3bdedbcb 496buffer nor display it.
0acffda1
RS
497
498The library where SYMBOL is defined is searched for in FILE or
373ed135 499`find-function-source-path', if non-nil, otherwise in `load-path'."
3bdedbcb
EZ
500 (cond
501 ((not symbol)
502 (error "You didn't specify a symbol"))
503 ((null type)
504 (find-function-noselect symbol))
505 ((eq type 'defvar)
506 (find-variable-noselect symbol file))
507 (t
0acffda1 508 (let ((library (or file (symbol-file symbol type))))
3bdedbcb 509 (find-function-search-for-symbol symbol type library)))))
0acffda1 510
c7ce7fc4
RS
511;; For symmetry, this should be called find-face; but some programs
512;; assume that, if that name is defined, it means something else.
0acffda1 513;;;###autoload
c7ce7fc4 514(defun find-face-definition (face)
0acffda1
RS
515 "Find the definition of FACE. FACE defaults to the name near point.
516
517Finds the Emacs Lisp library containing the definition of the face
518near point (selected by `variable-at-point') in a buffer and
519places point before the definition.
520
521Set mark before moving, if the buffer already existed.
522
523The library where FACE is defined is searched for in
373ed135 524`find-function-source-path', if non-nil, otherwise in `load-path'.
0acffda1
RS
525See also `find-function-recenter-line' and `find-function-after-hook'."
526 (interactive (find-function-read 'defface))
527 (find-function-do-it face 'defface 'switch-to-buffer))
528
b07745ec 529;;;###autoload
fffee8be
DL
530(defun find-function-on-key (key)
531 "Find the function that KEY invokes. KEY is a string.
0acffda1 532Set mark before moving, if the buffer already existed."
fffee8be 533 (interactive "kFind function on key: ")
cb4f3fc8
RS
534 (let (defn)
535 (save-excursion
536 (let* ((event (and (eventp key) (aref key 0))) ; Null event OK below.
537 (start (event-start event))
538 (modifiers (event-modifiers event))
539 (window (and (or (memq 'click modifiers) (memq 'down modifiers)
540 (memq 'drag modifiers))
541 (posn-window start))))
542 ;; For a mouse button event, go to the button it applies to
543 ;; to get the right key bindings. And go to the right place
544 ;; in case the keymap depends on where you clicked.
545 (when (windowp window)
546 (set-buffer (window-buffer window))
547 (goto-char (posn-point start)))
548 (setq defn (key-binding key))))
549 (let ((key-desc (key-description key)))
550 (if (or (null defn) (integerp defn))
551 (message "%s is unbound" key-desc)
552 (if (consp defn)
553 (message "%s runs %s" key-desc (prin1-to-string defn))
554 (find-function-other-window defn))))))
2cd6a032
RS
555
556;;;###autoload
557(defun find-function-at-point ()
558 "Find directly the function at point in the other window."
559 (interactive)
436c08c2 560 (let ((symb (function-called-at-point)))
2cd6a032
RS
561 (when symb
562 (find-function-other-window symb))))
563
564;;;###autoload
565(defun find-variable-at-point ()
3bdedbcb 566 "Find directly the variable at point in the other window."
2cd6a032
RS
567 (interactive)
568 (let ((symb (variable-at-point)))
569 (when (and symb (not (equal symb 0)))
570 (find-variable-other-window symb))))
fffee8be 571
86f28125
RS
572;;;###autoload
573(defun find-function-setup-keys ()
574 "Define some key bindings for the find-function family of functions."
575 (define-key ctl-x-map "F" 'find-function)
576 (define-key ctl-x-4-map "F" 'find-function-other-window)
577 (define-key ctl-x-5-map "F" 'find-function-other-frame)
578 (define-key ctl-x-map "K" 'find-function-on-key)
579 (define-key ctl-x-map "V" 'find-variable)
580 (define-key ctl-x-4-map "V" 'find-variable-other-window)
581 (define-key ctl-x-5-map "V" 'find-variable-other-frame))
582
fffee8be
DL
583(provide 'find-func)
584
585;;; find-func.el ends here