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