Commit | Line | Data |
---|---|---|
2cd6a032 | 1 | ;;; find-func.el --- find the definition of the Emacs Lisp function near point |
fffee8be | 2 | |
1b60b25a | 3 | ;; Copyright (C) 1997, 1999, 2001, 2004, 2005 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 | ||
12 | ;; GNU Emacs is free software; you can redistribute it and/or modify | |
13 | ;; it under the terms of the GNU General Public License as published by | |
14 | ;; the Free Software Foundation; either version 2, or (at your option) | |
15 | ;; any later version. | |
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 | |
23 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | |
24 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
25 | ;; Boston, MA 02111-1307, USA. | |
26 | ||
27 | ;;; Commentary: | |
28 | ;; | |
29 | ;; The funniest thing about this is that I can't imagine why a package | |
30 | ;; so obviously useful as this hasn't been written before!! | |
fffee8be | 31 | ;; ;;; find-func |
86f28125 RS |
32 | ;; (find-function-setup-keys) |
33 | ;; | |
34 | ;; or just: | |
35 | ;; | |
2cd6a032 | 36 | ;; (load "find-func") |
fffee8be | 37 | ;; |
86f28125 | 38 | ;; if you don't like the given keybindings and away you go! It does |
2cd6a032 RS |
39 | ;; pretty much what you would expect, putting the cursor at the |
40 | ;; definition of the function or variable at point. | |
fffee8be | 41 | ;; |
2cd6a032 | 42 | ;; The code started out from `describe-function', `describe-key' |
fffee8be DL |
43 | ;; ("help.el") and `fff-find-loaded-emacs-lisp-function' (Noah Friedman's |
44 | ;; "fff.el"). | |
45 | ||
e8af40ee | 46 | ;;; Code: |
fffee8be | 47 | |
2cd6a032 RS |
48 | (require 'loadhist) |
49 | ||
fffee8be | 50 | ;;; User variables: |
2cd6a032 | 51 | |
0b5bb3ec | 52 | (defgroup find-function nil |
2cd6a032 RS |
53 | "Finds the definition of the Emacs Lisp symbol near point." |
54 | ;; :prefix "find-function" | |
0b5bb3ec | 55 | :group 'lisp) |
fffee8be | 56 | |
54cabb1b SM |
57 | (defconst find-function-space-re "\\(?:\\s-\\|\n\\|;.*\n\\)+") |
58 | ||
2cd6a032 | 59 | (defcustom find-function-regexp |
d3d4fb62 RS |
60 | ;; Match things like (defun foo ...), (defmacro foo ...), |
61 | ;; (define-skeleton foo ...), (define-generic-mode 'foo ...), | |
d8f479c6 | 62 | ;; (define-derived-mode foo ...), (define-minor-mode foo) |
54cabb1b SM |
63 | (concat |
64 | "^\\s-*(\\(def\\(ine-skeleton\\|ine-generic-mode\\|ine-derived-mode\\|\ | |
b0339ffd | 65 | ine-minor-mode\\|un-cvs-mode\\|foo\\|[^cfgv]\\w+\\*?\\)\ |
54cabb1b SM |
66 | \\|easy-mmode-define-global-mode\\)" find-function-space-re |
67 | "\\('\\|\(quote \\)?%s\\(\\s-\\|$\\|\(\\|\)\\)") | |
d3d4fb62 RS |
68 | "The regexp used by `find-function' to search for a function definition. |
69 | Note it must contain a `%s' at the place where `format' | |
2cd6a032 | 70 | should insert the function name. The default value avoids `defconst', |
b0339ffd | 71 | `defgroup', `defvar', `defface'. |
fffee8be | 72 | |
2cd6a032 RS |
73 | Please send improvements and fixes to the maintainer." |
74 | :type 'regexp | |
86f28125 | 75 | :group 'find-function |
d8f479c6 | 76 | :version "21.1") |
2cd6a032 RS |
77 | |
78 | (defcustom find-variable-regexp | |
1b60b25a | 79 | (concat"^\\s-*(def[^fumag]\\(\\w\\|\\s_\\)+\\*?" find-function-space-re "%s\\(\\s-\\|$\\)") |
2cd6a032 | 80 | "The regexp used by `find-variable' to search for a variable definition. |
0acffda1 RS |
81 | Note it must contain a `%s' at the place where `format' |
82 | should insert the variable name. The default value | |
1b60b25a | 83 | avoids `defun', `defmacro', `defalias', `defadvice', `defgroup', `defface'. |
2cd6a032 RS |
84 | |
85 | Please send improvements and fixes to the maintainer." | |
86 | :type 'regexp | |
86f28125 | 87 | :group 'find-function |
a469e8ba | 88 | :version "21.1") |
fffee8be | 89 | |
0acffda1 RS |
90 | (defcustom find-face-regexp |
91 | (concat"^\\s-*(defface" find-function-space-re "%s\\(\\s-\\|$\\)") | |
92 | "The regexp used by `find-face' to search for a face definition. | |
93 | Note it must contain a `%s' at the place where `format' | |
94 | should insert the face name. | |
95 | ||
96 | Please send improvements and fixes to the maintainer." | |
97 | :type 'regexp | |
98 | :group 'find-function | |
bf247b6e | 99 | :version "22.1") |
0acffda1 RS |
100 | |
101 | (defvar find-function-regexp-alist | |
102 | '((nil . find-function-regexp) | |
103 | (defvar . find-variable-regexp) | |
104 | (defface . find-face-regexp)) | |
105 | "Alist mapping definition types into regexp variables. | |
106 | Each regexp variable's value should actually be a format string | |
107 | to be used to substitute the desired symbol name into the regexp.") | |
108 | (put 'find-function-regexp-alist 'risky-local-variable t) | |
109 | ||
0b5bb3ec | 110 | (defcustom find-function-source-path nil |
d3d4fb62 | 111 | "The default list of directories where `find-function' searches. |
fffee8be | 112 | |
d3d4fb62 | 113 | If this variable is nil then `find-function' searches `load-path' by |
0b5bb3ec SE |
114 | default." |
115 | :type '(repeat directory) | |
116 | :group 'find-function) | |
fffee8be | 117 | |
2cd6a032 RS |
118 | (defcustom find-function-recenter-line 1 |
119 | "The window line-number from which to start displaying a symbol definition. | |
120 | A value of nil implies center the beginning of the definition. | |
cb0fd101 JPW |
121 | See `find-function' and `find-variable'." |
122 | :type '(choice (const :tag "Center" nil) | |
123 | integer) | |
86f28125 | 124 | :group 'find-function |
a6223467 | 125 | :version "20.3") |
2cd6a032 RS |
126 | |
127 | (defcustom find-function-after-hook nil | |
128 | "Hook run after finding symbol definition. | |
129 | ||
130 | See the functions `find-function' and `find-variable'." | |
86f28125 | 131 | :group 'find-function |
a6223467 | 132 | :version "20.3") |
2cd6a032 RS |
133 | |
134 | ;;; Functions: | |
135 | ||
f77a6050 SM |
136 | (defun find-library-suffixes () |
137 | (let ((suffixes nil)) | |
138 | (dolist (suffix load-suffixes (nreverse suffixes)) | |
139 | (unless (string-match "elc" suffix) (push suffix suffixes))))) | |
140 | ||
141 | (defun find-library-name (library) | |
142 | "Return the full name of the elisp source of LIBRARY." | |
143 | ;; If the library is byte-compiled, try to find a source library by | |
144 | ;; the same name. | |
1a40d81d SM |
145 | (if (string-match "\\.el\\(c\\(\\..*\\)?\\)\\'" library) |
146 | (setq library (replace-match "" t t library))) | |
f77a6050 SM |
147 | (or (locate-file library |
148 | (or find-function-source-path load-path) | |
43ce8949 | 149 | (append (find-library-suffixes) '(""))) |
4dbf594b | 150 | (error "Can't find library %s" library))) |
f77a6050 | 151 | |
4479a2f8 SM |
152 | (defvar find-function-C-source-directory |
153 | (let ((dir (expand-file-name "src" source-directory))) | |
154 | (when (and (file-directory-p dir) (file-readable-p dir)) | |
155 | dir)) | |
156 | "Directory where the C source files of Emacs can be found. | |
157 | If nil, do not try to find the source code of functions and variables | |
158 | defined in C.") | |
159 | ||
0acffda1 | 160 | (defun find-function-C-source (fun-or-var file type) |
4479a2f8 | 161 | "Find the source location where SUBR-OR-VAR is defined in FILE. |
0acffda1 | 162 | TYPE should be nil to find a function, or `defvar' to find a variable." |
4479a2f8 SM |
163 | (unless find-function-C-source-directory |
164 | (setq find-function-C-source-directory | |
165 | (read-directory-name "Emacs C source dir: " nil nil t))) | |
166 | (setq file (expand-file-name file find-function-C-source-directory)) | |
167 | (unless (file-readable-p file) | |
168 | (error "The C source file %s is not available" | |
169 | (file-name-nondirectory file))) | |
0acffda1 | 170 | (unless type |
4479a2f8 SM |
171 | (setq fun-or-var (indirect-function fun-or-var))) |
172 | (with-current-buffer (find-file-noselect file) | |
173 | (goto-char (point-min)) | |
174 | (unless (re-search-forward | |
0acffda1 | 175 | (if type |
4479a2f8 SM |
176 | (concat "DEFVAR[A-Z_]*[ \t\n]*([ \t\n]*\"" |
177 | (regexp-quote (symbol-name fun-or-var)) | |
178 | "\"") | |
179 | (concat "DEFUN[ \t\n]*([ \t\n]*\"" | |
180 | (regexp-quote (subr-name fun-or-var)) | |
181 | "\"")) | |
182 | nil t) | |
183 | (error "Can't find source for %s" fun-or-var)) | |
184 | (cons (current-buffer) (match-beginning 0)))) | |
185 | ||
f77a6050 SM |
186 | ;;;###autoload |
187 | (defun find-library (library) | |
188 | "Find the elisp source of LIBRARY." | |
189 | (interactive | |
190 | (list | |
191 | (completing-read "Library name: " | |
192 | 'locate-file-completion | |
193 | (cons (or find-function-source-path load-path) | |
194 | (find-library-suffixes))))) | |
195 | (let ((buf (find-file-noselect (find-library-name library)))) | |
196 | (condition-case nil (switch-to-buffer buf) (error (pop-to-buffer buf))))) | |
197 | ||
a4f43048 | 198 | ;;;###autoload |
0acffda1 RS |
199 | (defun find-function-search-for-symbol (symbol type library) |
200 | "Search for SYMBOL's definition of type TYPE in LIBRARY. | |
201 | If TYPE is nil, look for a function definition. | |
202 | Otherwise, TYPE specifies the kind of definition, | |
203 | and it is interpreted via `find-function-regexp-alist'. | |
204 | The search is done in the source for library LIBRARY." | |
2cd6a032 RS |
205 | (if (null library) |
206 | (error "Don't know where `%s' is defined" symbol)) | |
2bef95e5 RS |
207 | ;; Some functions are defined as part of the construct |
208 | ;; that defines something else. | |
4479a2f8 | 209 | (while (and (symbolp symbol) (get symbol 'definition-name)) |
2bef95e5 | 210 | (setq symbol (get symbol 'definition-name))) |
4479a2f8 | 211 | (if (string-match "\\`src/\\(.*\\.c\\)\\'" library) |
0acffda1 | 212 | (find-function-C-source symbol (match-string 1 library) type) |
78b6524e DL |
213 | (if (string-match "\\.el\\(c\\)\\'" library) |
214 | (setq library (substring library 0 (match-beginning 1)))) | |
0acffda1 RS |
215 | (let* ((filename (find-library-name library)) |
216 | (regexp-symbol (cdr (assq type find-function-regexp-alist)))) | |
78b6524e | 217 | (with-current-buffer (find-file-noselect filename) |
0acffda1 | 218 | (let ((regexp (format (symbol-value regexp-symbol) |
2cd6a032 | 219 | (regexp-quote (symbol-name symbol)))) |
77186c62 | 220 | (case-fold-search)) |
fe75e6d0 MR |
221 | (with-syntax-table emacs-lisp-mode-syntax-table |
222 | (goto-char (point-min)) | |
223 | (if (or (re-search-forward regexp nil t) | |
224 | (re-search-forward | |
54cabb1b | 225 | (concat "^([^ ]+" find-function-space-re "['(]" |
fe75e6d0 | 226 | (regexp-quote (symbol-name symbol)) |
b0339ffd | 227 | "\\_>") |
fe75e6d0 MR |
228 | nil t)) |
229 | (progn | |
230 | (beginning-of-line) | |
231 | (cons (current-buffer) (point))) | |
232 | (error "Cannot find definition of `%s' in library `%s'" | |
233 | symbol library)))))))) | |
2cd6a032 | 234 | |
8a8a9abe | 235 | ;;;###autoload |
2cd6a032 | 236 | (defun find-function-noselect (function) |
d3d4fb62 | 237 | "Return a pair (BUFFER . POINT) pointing to the definition of FUNCTION. |
fffee8be DL |
238 | |
239 | Finds the Emacs Lisp library containing the definition of FUNCTION | |
2cd6a032 | 240 | in a buffer and the point of the definition. The buffer is |
fffee8be DL |
241 | not selected. |
242 | ||
2cd6a032 | 243 | If the file where FUNCTION is defined is not known, then it is |
d3d4fb62 | 244 | searched for in `find-function-source-path' if non nil, otherwise |
2cd6a032 | 245 | in `load-path'." |
fffee8be DL |
246 | (if (not function) |
247 | (error "You didn't specify a function")) | |
2cd6a032 RS |
248 | (and (subrp (symbol-function function)) |
249 | (error "%s is a primitive function" function)) | |
fffee8be | 250 | (let ((def (symbol-function function)) |
2cd6a032 | 251 | aliases) |
fffee8be DL |
252 | (while (symbolp def) |
253 | (or (eq def function) | |
254 | (if aliases | |
255 | (setq aliases (concat aliases | |
2cd6a032 | 256 | (format ", which is an alias for `%s'" |
fffee8be | 257 | (symbol-name def)))) |
2cd6a032 RS |
258 | (setq aliases (format "`%s' an alias for `%s'" |
259 | function (symbol-name def))))) | |
fffee8be DL |
260 | (setq function (symbol-function function) |
261 | def (symbol-function function))) | |
262 | (if aliases | |
263 | (message aliases)) | |
2cd6a032 RS |
264 | (let ((library |
265 | (cond ((eq (car-safe def) 'autoload) | |
266 | (nth 1 def)) | |
9f14330b | 267 | ((symbol-file function 'defun))))) |
2cd6a032 | 268 | (find-function-search-for-symbol function nil library)))) |
fffee8be | 269 | |
0acffda1 | 270 | (defun find-function-read (&optional type) |
2cd6a032 | 271 | "Read and return an interned symbol, defaulting to the one near point. |
fffee8be | 272 | |
0acffda1 RS |
273 | If TYPE is nil, insist on a symbol with a function definition. |
274 | Otherwise TYPE should be `defvar' or `defface'. | |
275 | If TYPE is nil, defaults using `function-called-at-point', | |
276 | otherwise uses `variable-at-point'." | |
277 | (let ((symb (if (null type) | |
278 | (function-called-at-point) | |
279 | (if (eq type 'defvar) | |
280 | (variable-at-point) | |
281 | (variable-at-point t)))) | |
282 | (predicate (cdr (assq type '((nil . fboundp) (defvar . boundp) | |
283 | (defface . facep))))) | |
284 | (prompt (cdr (assq type '((nil . "function") (defvar . "variable") | |
285 | (defface . "face"))))) | |
fffee8be DL |
286 | (enable-recursive-minibuffers t) |
287 | val) | |
2cd6a032 RS |
288 | (if (equal symb 0) |
289 | (setq symb nil)) | |
0acffda1 RS |
290 | (setq val (completing-read |
291 | (concat "Find " | |
292 | prompt | |
293 | (if symb | |
294 | (format " (default %s)" symb)) | |
295 | ": ") | |
296 | obarray predicate t nil)) | |
fffee8be | 297 | (list (if (equal val "") |
2cd6a032 RS |
298 | symb |
299 | (intern val))))) | |
fffee8be | 300 | |
0acffda1 | 301 | (defun find-function-do-it (symbol type switch-fn) |
d3d4fb62 | 302 | "Find Emacs Lisp SYMBOL in a buffer and display it. |
0acffda1 RS |
303 | TYPE is nil to search for a function definition, |
304 | or else `defvar' or `defface'. | |
305 | ||
306 | The variable `find-function-recenter-line' controls how | |
307 | to recenter the display. SWITCH-FN is the function to call | |
308 | to display and select the buffer. | |
309 | See also `find-function-after-hook'. | |
2cd6a032 | 310 | |
0acffda1 | 311 | Set mark before moving, if the buffer already existed." |
86f28125 RS |
312 | (let* ((orig-point (point)) |
313 | (orig-buf (window-buffer)) | |
2cd6a032 | 314 | (orig-buffers (buffer-list)) |
86f28125 | 315 | (buffer-point (save-excursion |
0acffda1 | 316 | (find-definition-noselect symbol type))) |
86f28125 RS |
317 | (new-buf (car buffer-point)) |
318 | (new-point (cdr buffer-point))) | |
2cd6a032 | 319 | (when buffer-point |
86f28125 | 320 | (when (memq new-buf orig-buffers) |
2cd6a032 | 321 | (push-mark orig-point)) |
86f28125 RS |
322 | (funcall switch-fn new-buf) |
323 | (goto-char new-point) | |
2cd6a032 | 324 | (recenter find-function-recenter-line) |
8d8ca3cf | 325 | (run-hooks 'find-function-after-hook)))) |
fffee8be | 326 | |
b07745ec | 327 | ;;;###autoload |
2cd6a032 | 328 | (defun find-function (function) |
c7efc289 | 329 | "Find the definition of the FUNCTION near point. |
fffee8be DL |
330 | |
331 | Finds the Emacs Lisp library containing the definition of the function | |
436c08c2 | 332 | near point (selected by `function-called-at-point') in a buffer and |
0acffda1 RS |
333 | places point before the definition. |
334 | Set mark before moving, if the buffer already existed. | |
fffee8be | 335 | |
2cd6a032 | 336 | The library where FUNCTION is defined is searched for in |
d3d4fb62 | 337 | `find-function-source-path', if non nil, otherwise in `load-path'. |
2cd6a032 RS |
338 | See also `find-function-recenter-line' and `find-function-after-hook'." |
339 | (interactive (find-function-read)) | |
340 | (find-function-do-it function nil 'switch-to-buffer)) | |
fffee8be | 341 | |
b07745ec | 342 | ;;;###autoload |
2cd6a032 | 343 | (defun find-function-other-window (function) |
c7efc289 | 344 | "Find, in another window, the definition of FUNCTION near point. |
fffee8be | 345 | |
2cd6a032 RS |
346 | See `find-function' for more details." |
347 | (interactive (find-function-read)) | |
348 | (find-function-do-it function nil 'switch-to-buffer-other-window)) | |
fffee8be | 349 | |
b07745ec | 350 | ;;;###autoload |
2cd6a032 | 351 | (defun find-function-other-frame (function) |
c7efc289 | 352 | "Find, in ananother frame, the definition of FUNCTION near point. |
fffee8be | 353 | |
2cd6a032 RS |
354 | See `find-function' for more details." |
355 | (interactive (find-function-read)) | |
356 | (find-function-do-it function nil 'switch-to-buffer-other-frame)) | |
357 | ||
e1acbda2 | 358 | ;;;###autoload |
1c787e34 SM |
359 | (defun find-variable-noselect (variable &optional file) |
360 | "Return a pair `(BUFFER . POINT)' pointing to the definition of SYMBOL. | |
2cd6a032 RS |
361 | |
362 | Finds the Emacs Lisp library containing the definition of SYMBOL | |
0acffda1 RS |
363 | in a buffer, and the point of the definition. It does not switch |
364 | to the buffer or display it. | |
2cd6a032 | 365 | |
1c787e34 | 366 | The library where VARIABLE is defined is searched for in FILE or |
d3d4fb62 | 367 | `find-function-source-path', if non nil, otherwise in `load-path'." |
2cd6a032 RS |
368 | (if (not variable) |
369 | (error "You didn't specify a variable")) | |
9f14330b | 370 | (let ((library (or file (symbol-file variable 'defvar)))) |
0acffda1 | 371 | (find-function-search-for-symbol variable 'defvar library))) |
2cd6a032 RS |
372 | |
373 | ;;;###autoload | |
374 | (defun find-variable (variable) | |
c7efc289 | 375 | "Find the definition of the VARIABLE near point. |
2cd6a032 RS |
376 | |
377 | Finds the Emacs Lisp library containing the definition of the variable | |
378 | near point (selected by `variable-at-point') in a buffer and | |
0acffda1 RS |
379 | places point before the definition. |
380 | ||
381 | Set mark before moving, if the buffer already existed. | |
2cd6a032 RS |
382 | |
383 | The library where VARIABLE is defined is searched for in | |
d3d4fb62 | 384 | `find-function-source-path', if non nil, otherwise in `load-path'. |
2cd6a032 | 385 | See also `find-function-recenter-line' and `find-function-after-hook'." |
436c08c2 RS |
386 | (interactive (find-function-read 'defvar)) |
387 | (find-function-do-it variable 'defvar 'switch-to-buffer)) | |
fffee8be | 388 | |
2cd6a032 RS |
389 | ;;;###autoload |
390 | (defun find-variable-other-window (variable) | |
c7efc289 | 391 | "Find, in another window, the definition of VARIABLE near point. |
2cd6a032 RS |
392 | |
393 | See `find-variable' for more details." | |
436c08c2 RS |
394 | (interactive (find-function-read 'defvar)) |
395 | (find-function-do-it variable 'defvar 'switch-to-buffer-other-window)) | |
2cd6a032 RS |
396 | |
397 | ;;;###autoload | |
398 | (defun find-variable-other-frame (variable) | |
c7efc289 | 399 | "Find, in annother frame, the definition of VARIABLE near point. |
2cd6a032 RS |
400 | |
401 | See `find-variable' for more details." | |
436c08c2 RS |
402 | (interactive (find-function-read 'defvar)) |
403 | (find-function-do-it variable 'defvar 'switch-to-buffer-other-frame)) | |
fffee8be | 404 | |
0acffda1 RS |
405 | ;;;###autoload |
406 | (defun find-definition-noselect (symbol type &optional file) | |
407 | "Return a pair `(BUFFER . POINT)' pointing to the definition of SYMBOL. | |
408 | TYPE says what type of definition: nil for a function, | |
409 | `defvar' or `defface' for a variable or face. This functoin | |
410 | does not switch to the buffer or display it. | |
411 | ||
412 | The library where SYMBOL is defined is searched for in FILE or | |
413 | `find-function-source-path', if non nil, otherwise in `load-path'." | |
414 | (if (not symbol) | |
415 | (error "You didn't specify a symbol")) | |
416 | (if (null type) | |
417 | (find-function-noselect symbol) | |
418 | (let ((library (or file (symbol-file symbol type)))) | |
419 | (find-function-search-for-symbol symbol type library)))) | |
420 | ||
c7ce7fc4 RS |
421 | ;; For symmetry, this should be called find-face; but some programs |
422 | ;; assume that, if that name is defined, it means something else. | |
0acffda1 | 423 | ;;;###autoload |
c7ce7fc4 | 424 | (defun find-face-definition (face) |
0acffda1 RS |
425 | "Find the definition of FACE. FACE defaults to the name near point. |
426 | ||
427 | Finds the Emacs Lisp library containing the definition of the face | |
428 | near point (selected by `variable-at-point') in a buffer and | |
429 | places point before the definition. | |
430 | ||
431 | Set mark before moving, if the buffer already existed. | |
432 | ||
433 | The library where FACE is defined is searched for in | |
434 | `find-function-source-path', if non nil, otherwise in `load-path'. | |
435 | See also `find-function-recenter-line' and `find-function-after-hook'." | |
436 | (interactive (find-function-read 'defface)) | |
437 | (find-function-do-it face 'defface 'switch-to-buffer)) | |
438 | ||
b07745ec | 439 | ;;;###autoload |
fffee8be DL |
440 | (defun find-function-on-key (key) |
441 | "Find the function that KEY invokes. KEY is a string. | |
0acffda1 | 442 | Set mark before moving, if the buffer already existed." |
fffee8be | 443 | (interactive "kFind function on key: ") |
cb4f3fc8 RS |
444 | (let (defn) |
445 | (save-excursion | |
446 | (let* ((event (and (eventp key) (aref key 0))) ; Null event OK below. | |
447 | (start (event-start event)) | |
448 | (modifiers (event-modifiers event)) | |
449 | (window (and (or (memq 'click modifiers) (memq 'down modifiers) | |
450 | (memq 'drag modifiers)) | |
451 | (posn-window start)))) | |
452 | ;; For a mouse button event, go to the button it applies to | |
453 | ;; to get the right key bindings. And go to the right place | |
454 | ;; in case the keymap depends on where you clicked. | |
455 | (when (windowp window) | |
456 | (set-buffer (window-buffer window)) | |
457 | (goto-char (posn-point start))) | |
458 | (setq defn (key-binding key)))) | |
459 | (let ((key-desc (key-description key))) | |
460 | (if (or (null defn) (integerp defn)) | |
461 | (message "%s is unbound" key-desc) | |
462 | (if (consp defn) | |
463 | (message "%s runs %s" key-desc (prin1-to-string defn)) | |
464 | (find-function-other-window defn)))))) | |
2cd6a032 RS |
465 | |
466 | ;;;###autoload | |
467 | (defun find-function-at-point () | |
468 | "Find directly the function at point in the other window." | |
469 | (interactive) | |
436c08c2 | 470 | (let ((symb (function-called-at-point))) |
2cd6a032 RS |
471 | (when symb |
472 | (find-function-other-window symb)))) | |
473 | ||
474 | ;;;###autoload | |
475 | (defun find-variable-at-point () | |
476 | "Find directly the function at point in the other window." | |
477 | (interactive) | |
478 | (let ((symb (variable-at-point))) | |
479 | (when (and symb (not (equal symb 0))) | |
480 | (find-variable-other-window symb)))) | |
fffee8be | 481 | |
86f28125 RS |
482 | ;;;###autoload |
483 | (defun find-function-setup-keys () | |
484 | "Define some key bindings for the find-function family of functions." | |
485 | (define-key ctl-x-map "F" 'find-function) | |
486 | (define-key ctl-x-4-map "F" 'find-function-other-window) | |
487 | (define-key ctl-x-5-map "F" 'find-function-other-frame) | |
488 | (define-key ctl-x-map "K" 'find-function-on-key) | |
489 | (define-key ctl-x-map "V" 'find-variable) | |
490 | (define-key ctl-x-4-map "V" 'find-variable-other-window) | |
491 | (define-key ctl-x-5-map "V" 'find-variable-other-frame)) | |
492 | ||
fffee8be DL |
493 | (provide 'find-func) |
494 | ||
1b60b25a | 495 | ;; arch-tag: 43ecd81c-74dc-4d9a-8f63-a61e55670d64 |
fffee8be | 496 | ;;; find-func.el ends here |