aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Love1997-10-25 13:18:56 +0000
committerDave Love1997-10-25 13:18:56 +0000
commitfffee8be90e8cce92316e4f026285b23d9b92ffe (patch)
treedf2bbb46cdf8a68a04a742ddab504313c700a773
parent8f08dc930c2380fff5c21bd4d6b8540b9145f7f8 (diff)
downloademacs-fffee8be90e8cce92316e4f026285b23d9b92ffe.tar.gz
emacs-fffee8be90e8cce92316e4f026285b23d9b92ffe.zip
Initial revision
-rw-r--r--lisp/emacs-lisp/find-func.el249
1 files changed, 249 insertions, 0 deletions
diff --git a/lisp/emacs-lisp/find-func.el b/lisp/emacs-lisp/find-func.el
new file mode 100644
index 00000000000..3eefb55b4cd
--- /dev/null
+++ b/lisp/emacs-lisp/find-func.el
@@ -0,0 +1,249 @@
1;;; find-func.el --- find the definition of the elisp function near point
2
3;; Copyright (C) 1997 Free Software Foundation, Inc.
4
5;; Author: Jens Petersen <petersen@kurims.kyoto-u.ac.jp>
6;; Maintainer: petersen@kurims.kyoto-u.ac.jp
7;; Keywords: emacs-lisp, help, functions
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!!
31;; This probably belongs in "help.el" or somewhere like that.
32;;
33;; Put this file in your `load-path', byte-compile it and add the
34;; following code in your init file:
35;;
36;; ;;; find-func
37;; (load "find-function")
38;; (global-set-key [(control ?c) ?f] 'find-function)
39;; (global-set-key [(control ?c) ?4 ?f] 'find-function-other-window)
40;; (global-set-key [(control ?c) ?5 ?f] 'find-function-other-frame)
41;; (global-set-key [(control ?c) ?k] 'find-function-on-key)
42;;
43;; and away you go! It does pretty much what you would expect,
44;; putting the cursor at the definition of the function at point.
45;;
46;; The code is adapted from `describe-function', `describe-key'
47;; ("help.el") and `fff-find-loaded-emacs-lisp-function' (Noah Friedman's
48;; "fff.el").
49
50;;; To do:
51;;
52;; o custom?
53;;
54;; o improve handling of advice'd functions? (at the moment it goes to
55;; the advice, not the actual definition)
56
57;;;; Code:
58
59;;; User variables:
60
61(defvar find-function-function 'function-at-point
62 "*The function used by `find-function' to select the function near
63point.
64
65For example `function-at-point' or `function-called-at-point'.")
66
67(defvar find-function-source-path nil
68 "The default list of directories where find-function searches.
69
70If this variable is `nil' then find-function searches `load-path' by
71default.")
72
73
74;;; Functions:
75
76(defun find-function-noselect (function &optional path)
77 "Returns list `(buffer point)' pointing to the definition of FUNCTION.
78
79Finds the Emacs Lisp library containing the definition of FUNCTION
80in a buffer and places point before the definition. The buffer is
81not selected.
82
83If the optional argument PATH is given, the library where FUNCTION is
84defined is searched in PATH instead of `load-path' (see
85`find-function-source-path')."
86 (and (subrp (symbol-function function))
87 (error "%s is a primitive function" function))
88 (if (not function)
89 (error "You didn't specify a function"))
90 (let ((def (symbol-function function))
91 library aliases)
92 (while (symbolp def)
93 (or (eq def function)
94 (if aliases
95 (setq aliases (concat aliases
96 (format ", which is an alias for %s"
97 (symbol-name def))))
98 (setq aliases (format "an alias for %s" (symbol-name
99 def)))))
100 (setq function (symbol-function function)
101 def (symbol-function function)))
102 (if aliases
103 (message aliases))
104 (setq library
105 (cond ((eq (car-safe def) 'autoload)
106 (nth 1 def))
107 ((describe-function-find-file function))))
108 (if (null library)
109 (error (format "`%s' is not in `load-history'" function)))
110 (if (string-match "\\(\\.elc?\\'\\)" library)
111 (setq library (substring library 0 (match-beginning 1))))
112 (let* ((path (or path find-function-source-path))
113 (compression (or (rassq 'jka-compr-handler file-name-handler-alist)
114 (member 'crypt-find-file-hook find-file-hooks)))
115 (filename (or (locate-library (concat library ".el")
116 t path)
117 (locate-library library t path)
118 (if compression
119 (or (locate-library (concat library ".el.gz")
120 t path)
121 (locate-library (concat library ".gz")
122 t path))))))
123 (if (not filename)
124 (error "The library \"%s\" is not in the path." library))
125 (save-excursion
126 (set-buffer (find-file-noselect filename))
127 (save-match-data
128 (let (;; avoid defconst, defgroup, defvar (any others?)
129 (regexp (format "^\\s-*(def[^cgv\W]\\w+\\s-+%s\\s-" function))
130 (syntable (syntax-table)))
131 (set-syntax-table emacs-lisp-mode-syntax-table)
132 (goto-char (point-min))
133 (if (prog1
134 (re-search-forward regexp nil t)
135 (set-syntax-table syntable))
136 (progn
137 (beginning-of-line)
138 (list (current-buffer) (point)))
139 (error "Cannot find definition of %s" function))))))))
140
141(defun function-at-point ()
142 (or (condition-case ()
143 (let ((stab (syntax-table)))
144 (unwind-protect
145 (save-excursion
146 (set-syntax-table emacs-lisp-mode-syntax-table)
147 (or (not (zerop (skip-syntax-backward "_w")))
148 (eq (char-syntax (char-after (point))) ?w)
149 (eq (char-syntax (char-after (point))) ?_)
150 (forward-sexp -1))
151 (skip-chars-forward "`'")
152 (let ((obj (read (current-buffer))))
153 (and (symbolp obj) (fboundp obj) obj)))
154 (set-syntax-table stab)))
155 (error nil))
156 (condition-case ()
157 (save-excursion
158 (save-restriction
159 (narrow-to-region (max (point-min) (- (point) 1000)) (point-max))
160 (backward-up-list 1)
161 (forward-char 1)
162 (let (obj)
163 (setq obj (read (current-buffer)))
164 (and (symbolp obj) (fboundp obj) obj))))
165 (error nil))))
166
167(defun find-function-read-function ()
168 "Read and return a function, defaulting to the one near point.
169
170The function named by `find-function-function' is used to select the
171default function."
172 (let ((fn (funcall find-function-function))
173 (enable-recursive-minibuffers t)
174 val)
175 (setq val (completing-read
176 (if fn
177 (format "Find function (default %s): " fn)
178 "Find function: ")
179 obarray 'fboundp t))
180 (list (if (equal val "")
181 fn (intern val)))))
182
183(defun find-function-do-it (function path switch-fn)
184 "find elisp FUNCTION in PATH and display it with SWITCH-FN.
185Point is saved if FUNCTION is in the current buffer."
186 (let ((orig-point (point))
187 (buffer-point (find-function-noselect function path)))
188 (if buffer-point
189 (progn
190 (if (eq (current-buffer) (car buffer-point))
191 (push-mark orig-point))
192 (funcall switch-fn (car buffer-point))
193 (goto-char (elt buffer-point 1))
194 (recenter 0)))))
195
196(defun find-function (function &optional path)
197 "Find the definition of the function near point in the current window.
198
199Finds the Emacs Lisp library containing the definition of the function
200near point (selected by `find-function-function') and places point
201before the definition. Point is saved if FUNCTION is in the current
202buffer.
203
204If the optional argument PATH is given, the library where FUNCTION is
205defined is searched in PATH instead of `load-path'"
206 (interactive (find-function-read-function))
207 (find-function-do-it function path 'switch-to-buffer))
208
209(defun find-function-other-window (function &optional path)
210 "Find the definition of the function near point in the other window.
211
212Finds the Emacs Lisp package containing the definition of the function
213near point (selected by `find-function-function') and places point
214before the definition. Point is saved if FUNCTION is in the current
215buffer.
216
217If the optional argument PATH is given, the package where FUNCTION is
218defined is searched in PATH instead of `load-path'"
219 (interactive (find-function-read-function))
220 (find-function-do-it function path 'switch-to-buffer-other-window))
221
222(defun find-function-other-frame (function &optional path)
223 "Find the definition of the function near point in the another frame.
224
225Finds the Emacs Lisp package containing the definition of the function
226near point (selected by `find-function-function') and places point
227before the definition. Point is saved if FUNCTION is in the current
228buffer.
229
230If the optional argument PATH is given, the package where FUNCTION is
231defined is searched in PATH instead of `load-path'"
232 (interactive (find-function-read-function))
233 (find-function-do-it function path 'switch-to-buffer-other-frame))
234
235(defun find-function-on-key (key)
236 "Find the function that KEY invokes. KEY is a string.
237Point is saved if FUNCTION is in the current buffer."
238 (interactive "kFind function on key: ")
239 (let ((defn (key-binding key)))
240 (if (or (null defn) (integerp defn))
241 (message "%s is undefined" (key-description key))
242 (if (and (consp defn) (not (eq 'lambda (car-safe defn))))
243 (message "runs %s" (prin1-to-string defn))
244 (find-function-other-window defn)))))
245
246(provide 'find-func)
247
248;;; find-func.el ends here
249