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