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