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