diff options
| author | Dave Love | 1997-10-25 13:18:56 +0000 |
|---|---|---|
| committer | Dave Love | 1997-10-25 13:18:56 +0000 |
| commit | fffee8be90e8cce92316e4f026285b23d9b92ffe (patch) | |
| tree | df2bbb46cdf8a68a04a742ddab504313c700a773 | |
| parent | 8f08dc930c2380fff5c21bd4d6b8540b9145f7f8 (diff) | |
| download | emacs-fffee8be90e8cce92316e4f026285b23d9b92ffe.tar.gz emacs-fffee8be90e8cce92316e4f026285b23d9b92ffe.zip | |
Initial revision
| -rw-r--r-- | lisp/emacs-lisp/find-func.el | 249 |
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 | ||
| 63 | point. | ||
| 64 | |||
| 65 | For 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 | |||
| 70 | If this variable is `nil' then find-function searches `load-path' by | ||
| 71 | default.") | ||
| 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 | |||
| 79 | Finds the Emacs Lisp library containing the definition of FUNCTION | ||
| 80 | in a buffer and places point before the definition. The buffer is | ||
| 81 | not selected. | ||
| 82 | |||
| 83 | If the optional argument PATH is given, the library where FUNCTION is | ||
| 84 | defined 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 | |||
| 170 | The function named by `find-function-function' is used to select the | ||
| 171 | default 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. | ||
| 185 | Point 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 | |||
| 199 | Finds the Emacs Lisp library containing the definition of the function | ||
| 200 | near point (selected by `find-function-function') and places point | ||
| 201 | before the definition. Point is saved if FUNCTION is in the current | ||
| 202 | buffer. | ||
| 203 | |||
| 204 | If the optional argument PATH is given, the library where FUNCTION is | ||
| 205 | defined 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 | |||
| 212 | Finds the Emacs Lisp package containing the definition of the function | ||
| 213 | near point (selected by `find-function-function') and places point | ||
| 214 | before the definition. Point is saved if FUNCTION is in the current | ||
| 215 | buffer. | ||
| 216 | |||
| 217 | If the optional argument PATH is given, the package where FUNCTION is | ||
| 218 | defined 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 | |||
| 225 | Finds the Emacs Lisp package containing the definition of the function | ||
| 226 | near point (selected by `find-function-function') and places point | ||
| 227 | before the definition. Point is saved if FUNCTION is in the current | ||
| 228 | buffer. | ||
| 229 | |||
| 230 | If the optional argument PATH is given, the package where FUNCTION is | ||
| 231 | defined 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. | ||
| 237 | Point 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 | |||