Mercurial > hg > xemacs-beta
diff lisp/prim/find-func.el @ 203:850242ba4a81 r20-3b28
Import from CVS: tag r20-3b28
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:02:21 +0200 |
parents | |
children | e45d5e7c476e |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lisp/prim/find-func.el Mon Aug 13 10:02:21 2007 +0200 @@ -0,0 +1,254 @@ +;;; find-func.el --- find the definition of the Emacs Lisp function near point + +;; Copyright (C) 1997 Free Software Foundation, Inc. + +;; Author: Jens Petersen <petersen@kurims.kyoto-u.ac.jp> +;; Maintainer: petersen@kurims.kyoto-u.ac.jp +;; Keywords: emacs-lisp, functions +;; Created: 97/07/25 +;; URL: <http://www.kurims.kyoto-u.ac.jp/~petersen/emacs-lisp/> + +;; $Id: find-func.el,v 1.1 1997/10/10 01:39:52 steve Exp $ + +;; This file is part of XEmacs. + +;; XEmacs is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; XEmacs is distributed in the hope that it will be useful, but +;; WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with XEmacs; see the file COPYING. If not, write to the +;; Free Software Foundation, 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. + +;;; Commentary: +;; +;; The funniest thing about this is that I can't imagine why a package +;; so obviously useful as this hasn't been written before!! +;; +;; Put this file in your `load-path', byte-compile it and add the +;; following code in your init file: +;; +;; ;;; find-func +;; (load "find-func") +;; (global-set-key [(control ?c) ?f] 'find-function) +;; (global-set-key [(control ?c) ?4 ?f] 'find-function-other-window) +;; (global-set-key [(control ?c) ?5 ?f] 'find-function-other-frame) +;; (global-set-key [(control ?c) ?k] 'find-function-on-key) +;; +;; and away you go! It does pretty much what you would expect, +;; putting the cursor at the definition of the function at point. +;; +;; In XEmacs the source file of dumped functions is recorded (and can +;; be accessed with the function `compiled-function-annotation', which +;; doesn't exist in Emacs), so in XEmacs non-primitive dumped +;; functions can also be found. Unfortunately this is not possible in +;; Emacs. It would be nice if the location of primitive functions in +;; the C code was also recorded! + +;; The code is adapted from `describe-function', `describe-key' +;; ("help.el") and `fff-find-loaded-emacs-lisp-function' (Noah Friedman's +;; "fff.el"). + +;;; To do: +;; +;; o improve handling of advice'd functions? (at the moment it goes to +;; the advice, not the actual definition) +;; +;; o `find-function-other-frame' is not quite right when the function +;; is in the current buffer. +;; +;;;; Code: + +(defgroup find-function nil + "Find the definition of the Emacs Lisp function near point." + :group 'lisp) + +;;; User variables: + +(defcustom find-function-source-path nil + "The default list of directories where find-function searches. + +If this variable is `nil' then find-function searches `load-path' by +default." + :type '(choice (const :tag "Use `load-path'" nil) + (repeat :tag "Directories" + :menu-tag "List" + :value ("") + directory)) + :group 'find-function) + + +;;; Functions: + +(defun find-function-noselect (function) + "Returns a pair `(buffer . point)' pointing to the definition of FUNCTION. + +Finds the Emacs Lisp library containing the definition of FUNCTION +in a buffer and the point of the definition. The buffer is +not selected. + +The library where FUNCTION is defined is searched for in +`find-function-source-path', if non `nil', otherwise in `load-path'." + (and (subrp (symbol-function function)) + (error "%s is a primitive function" function)) + (if (not function) + (error "You didn't specify a function")) + (let ((def (symbol-function function)) + library aliases) + (while (symbolp def) + (or (eq def function) + (if aliases + (setq aliases (concat aliases + (format ", which is an alias for %s" + (symbol-name def)))) + (setq aliases (format "an alias for %s" (symbol-name def))))) + (setq function (symbol-function function) + def (symbol-function function))) + (if aliases + (message aliases)) + (setq library + (cond ((eq (car-safe def) 'autoload) + (nth 1 def)) + ((describe-function-find-file function)) + ((compiled-function-p def) + (substring (compiled-function-annotation def) 0 -4)))) + (if (null library) + (error (format "Don't know where `%s' is defined" function))) + (if (string-match "\\.el\\(c\\)\\'" library) + (setq library (substring library 0 (match-beginning 1)))) + (let* ((path find-function-source-path) + (filename (if (file-exists-p library) + library + (if (string-match "\\(\\.el\\)\\'" library) + (setq library (substring library 0 + (match-beginning + 1)))) + (or (locate-library (concat library ".el") t path) + (locate-library library t path))))) + (if (not filename) + (error "The library \"%s\" is not in the path." library)) + (with-current-buffer (find-file-noselect filename) + (save-match-data + (let (;; avoid defconst, defgroup, defvar (any others?) + (regexp + (format "^\\s-*(def[^cgv\W]\\w+\\*?\\s-+%s\\s-" function)) + (syntable (syntax-table))) + (set-syntax-table emacs-lisp-mode-syntax-table) + (goto-char (point-min)) + (if (prog1 + (re-search-forward regexp nil t) + (set-syntax-table syntable)) + (progn + (beginning-of-line) + (cons (current-buffer) (point))) + (error "Cannot find definition of `%s'" function)))))))) + +(defun find-function-read-function () + "Read and return a function, defaulting to the one near point. + +The function named by `find-function-function' is used to select the +default function." + (let ((fn (funcall find-function-function)) + (enable-recursive-minibuffers t) + val) + (setq val (completing-read + (if fn + (format "Find function (default %s): " fn) + "Find function: ") + obarray 'fboundp t nil 'function-history)) + (list (if (equal val "") + fn (intern val))))) + +(defun find-function-do-it (function switch-fn) + "Find Emacs Lisp FUNCTION in a buffer and display it with SWITCH-FN. +Point is saved in the buffer if it is one of the current buffers." + (let ((orig-point (point)) + (orig-buffers (buffer-list)) + (buffer-point (find-function-noselect function))) + (when buffer-point + (funcall switch-fn (car buffer-point)) + (when (memq (car buffer-point) orig-buffers) + (push-mark orig-point)) + (goto-char (cdr buffer-point)) + (recenter 0)))) + +;;;###autoload +(defun find-function (function) + "Find the definition of the function near point in the current window. + +Finds the Emacs Lisp library containing the definition of the function +near point (selected by `find-function-function') in a buffer and +places point before the definition. Point is saved in the buffer if +it is one of the current buffers. + +The library where FUNCTION is defined is searched for in +`find-function-source-path', if non `nil', otherwise in `load-path'." + (interactive (find-function-read-function)) + (find-function-do-it function 'switch-to-buffer)) + +;;;###autoload +(defun find-function-other-window (function) + "Find the definition of the function near point in the other window. + +Finds the Emacs Lisp library containing the definition of the function +near point (selected by `find-function-function') in a buffer and +places point before the definition. Point is saved in the buffer if +it is one of the current buffers. + +The library where FUNCTION is defined is searched for in +`find-function-source-path', if non `nil', otherwise in `load-path'." + (interactive (find-function-read-function)) + (find-function-do-it function 'switch-to-buffer-other-window)) + +;;;###autoload +(defun find-function-other-frame (function) + "Find the definition of the function near point in the another frame. + +Finds the Emacs Lisp library containing the definition of the function +near point (selected by `find-function-function') in a buffer and +places point before the definition. Point is saved in the buffer if +it is one of the current buffers. + +The library where FUNCTION is defined is searched for in +`find-function-source-path', if non `nil', otherwise in `load-path'." + (interactive (find-function-read-function)) + (find-function-do-it function 'switch-to-buffer-other-frame)) + +;;;###autoload +(defun find-function-on-key (key) + "Find the function that KEY invokes. KEY is a string. +Point is saved if FUNCTION is in the current buffer." + (interactive "kFind function on key: ") + (let ((defn (key-or-menu-binding key))) + (if (or (null defn) (integerp defn)) + (message "%s is undefined" (key-description key)) + (if (and (consp defn) (not (eq 'lambda (car-safe defn)))) + (message "runs %s" (prin1-to-string defn)) + (find-function-other-window defn))))) + +;;;###autoload +(defun find-function-at-point () + "Find directly the function at point in the other window." + (interactive) + (let ((symb (function-at-point))) + (when symb + (find-function-other-window symb)))) + +;; (define-key ctl-x-map "F" 'find-function) ; conflicts with `facemenu-keymap' + +;;;###autoload +(define-key ctl-x-4-map "F" 'find-function-other-window) +;;;###autoload +(define-key ctl-x-5-map "F" 'find-function-other-frame) +;;;###autoload +(define-key ctl-x-map "K" 'find-function-on-key) + +(provide 'find-func) +;;; find-func.el ends here