]> code.delx.au - gnu-emacs/blobdiff - lisp/emacs-lisp/find-func.el
Don't require loadhist.
[gnu-emacs] / lisp / emacs-lisp / find-func.el
index 2f394c2c470579d3517ad4c51409c96aa8ee90b9..20b91b10547a0694093390e5cece95e467efc237 100644 (file)
@@ -1,7 +1,7 @@
 ;;; find-func.el --- find the definition of the Emacs Lisp function near point
 
 ;; Copyright (C) 1997, 1999, 2001, 2002, 2003, 2004,
 ;;; find-func.el --- find the definition of the Emacs Lisp function near point
 
 ;; Copyright (C) 1997, 1999, 2001, 2002, 2003, 2004,
-;;   2005 Free Software Foundation, Inc.
+;;   2005, 2006, 2007 Free Software Foundation, Inc.
 
 ;; Author: Jens Petersen <petersen@kurims.kyoto-u.ac.jp>
 ;; Maintainer: petersen@kurims.kyoto-u.ac.jp
 
 ;; Author: Jens Petersen <petersen@kurims.kyoto-u.ac.jp>
 ;; Maintainer: petersen@kurims.kyoto-u.ac.jp
@@ -12,7 +12,7 @@
 
 ;; GNU Emacs is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
 
 ;; GNU Emacs 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)
+;; the Free Software Foundation; either version 3, or (at your option)
 ;; any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
@@ -46,8 +46,6 @@
 
 ;;; Code:
 
 
 ;;; Code:
 
-(require 'loadhist)
-
 ;;; User variables:
 
 (defgroup find-function nil
 ;;; User variables:
 
 (defgroup find-function nil
@@ -63,8 +61,9 @@
   ;;  (define-derived-mode foo ...), (define-minor-mode foo)
   (concat
    "^\\s-*(\\(def\\(ine-skeleton\\|ine-generic-mode\\|ine-derived-mode\\|\
   ;;  (define-derived-mode foo ...), (define-minor-mode foo)
   (concat
    "^\\s-*(\\(def\\(ine-skeleton\\|ine-generic-mode\\|ine-derived-mode\\|\
-ine-minor-mode\\|ine-compilation-mode\\|un-cvs-mode\\|foo\\|[^cfgv]\\w+\\*?\\)\
-\\|easy-mmode-define-global-mode\\|menu-bar-make-toggle\\)"
+ine\\(?:-global\\)?-minor-mode\\|ine-compilation-mode\\|un-cvs-mode\\|\
+foo\\|[^icfgv]\\(\\w\\|\\s_\\)+\\*?\\)\\|easy-mmode-define-[a-z-]+\\|easy-menu-define\\|\
+menu-bar-make-toggle\\)"
    find-function-space-re
    "\\('\\|\(quote \\)?%s\\(\\s-\\|$\\|\(\\|\)\\)")
   "The regexp used by `find-function' to search for a function definition.
    find-function-space-re
    "\\('\\|\(quote \\)?%s\\(\\s-\\|$\\|\(\\|\)\\)")
   "The regexp used by `find-function' to search for a function definition.
@@ -78,7 +77,11 @@ Please send improvements and fixes to the maintainer."
   :version "21.1")
 
 (defcustom find-variable-regexp
   :version "21.1")
 
 (defcustom find-variable-regexp
-  (concat"^\\s-*(def[^fumag]\\(\\w\\|\\s_\\)+\\*?" find-function-space-re "%s\\(\\s-\\|$\\)")
+  (concat
+   "^\\s-*(\\(def[^fumag]\\(\\w\\|\\s_\\)+\\*?\\|\
+easy-mmode-def\\(map\\|syntax\\)\\|easy-menu-define\\)"
+   find-function-space-re
+   "%s\\(\\s-\\|$\\)")
   "The regexp used by `find-variable' to search for a variable definition.
 Note it must contain a `%s' at the place where `format'
 should insert the variable name.  The default value
   "The regexp used by `find-variable' to search for a variable definition.
 Note it must contain a `%s' at the place where `format'
 should insert the variable name.  The default value
@@ -137,18 +140,18 @@ See the functions `find-function' and `find-variable'."
 
 (defun find-library-suffixes ()
   (let ((suffixes nil))
 
 (defun find-library-suffixes ()
   (let ((suffixes nil))
-    (dolist (suffix load-suffixes (nreverse suffixes))
+    (dolist (suffix (get-load-suffixes) (nreverse suffixes))
       (unless (string-match "elc" suffix) (push suffix suffixes)))))
 
 (defun find-library-name (library)
   "Return the absolute file name of the Lisp source of LIBRARY."
       (unless (string-match "elc" suffix) (push suffix suffixes)))))
 
 (defun find-library-name (library)
   "Return the absolute file name of the Lisp source of LIBRARY."
-  ;; Strip off the extension to take advantage of library suffixes in
-  ;; the call to `locate-file'.
-  (if (string-match "\\.el\\(c\\(\\..*\\)?\\)?\\'" library)
+  ;; If the library is byte-compiled, try to find a source library by
+  ;; the same name.
+  (if (string-match "\\.el\\(c\\(\\..*\\)?\\)\\'" library)
       (setq library (replace-match "" t t library)))
   (or (locate-file library
                   (or find-function-source-path load-path)
       (setq library (replace-match "" t t library)))
   (or (locate-file library
                   (or find-function-source-path load-path)
-                  (append (find-library-suffixes) '("")))
+                  (append (find-library-suffixes) load-file-rep-suffixes))
       (error "Can't find library %s" library)))
 
 (defvar find-function-C-source-directory
       (error "Can't find library %s" library)))
 
 (defvar find-function-C-source-directory
@@ -160,7 +163,7 @@ If nil, do not try to find the source code of functions and variables
 defined in C.")
 
 (defun find-function-C-source (fun-or-var file type)
 defined in C.")
 
 (defun find-function-C-source (fun-or-var file type)
-  "Find the source location where SUBR-OR-VAR is defined in FILE.
+  "Find the source location where FUN-OR-VAR is defined in FILE.
 TYPE should be nil to find a function, or `defvar' to find a variable."
   (unless find-function-C-source-directory
     (setq find-function-C-source-directory
 TYPE should be nil to find a function, or `defvar' to find a variable."
   (unless find-function-C-source-directory
     (setq find-function-C-source-directory
@@ -200,6 +203,9 @@ TYPE should be nil to find a function, or `defvar' to find a variable."
 ;;;###autoload
 (defun find-function-search-for-symbol (symbol type library)
   "Search for SYMBOL's definition of type TYPE in LIBRARY.
 ;;;###autoload
 (defun find-function-search-for-symbol (symbol type library)
   "Search for SYMBOL's definition of type TYPE in LIBRARY.
+Visit the library in a buffer, and return a cons cell (BUFFER . POSITION),
+or just (BUFFER . nil) if the definition can't be found in the file.
+
 If TYPE is nil, look for a function definition.
 Otherwise, TYPE specifies the kind of definition,
 and it is interpreted via `find-function-regexp-alist'.
 If TYPE is nil, look for a function definition.
 Otherwise, TYPE specifies the kind of definition,
 and it is interpreted via `find-function-regexp-alist'.
@@ -218,32 +224,45 @@ The search is done in the source for library LIBRARY."
           (regexp-symbol (cdr (assq type find-function-regexp-alist))))
       (with-current-buffer (find-file-noselect filename)
        (let ((regexp (format (symbol-value regexp-symbol)
           (regexp-symbol (cdr (assq type find-function-regexp-alist))))
       (with-current-buffer (find-file-noselect filename)
        (let ((regexp (format (symbol-value regexp-symbol)
-                             (regexp-quote (symbol-name symbol))))
+                             ;; Entry for ` (backquote) macro in loaddefs.el,
+                             ;; (defalias (quote \`)..., has a \ but
+                             ;; (symbol-name symbol) doesn't.  Add an
+                             ;; optional \ to catch this.
+                             (concat "\\\\?"
+                                     (regexp-quote (symbol-name symbol)))))
              (case-fold-search))
          (with-syntax-table emacs-lisp-mode-syntax-table
            (goto-char (point-min))
            (if (or (re-search-forward regexp nil t)
              (case-fold-search))
          (with-syntax-table emacs-lisp-mode-syntax-table
            (goto-char (point-min))
            (if (or (re-search-forward regexp nil t)
+                    ;; `regexp' matches definitions using known forms like
+                    ;; `defun', or `defvar'.  But some functions/variables
+                    ;; are defined using special macros (or functions), so
+                    ;; if `regexp' can't find the definition, we look for
+                    ;; something of the form "(SOMETHING <symbol> ...)".
+                    ;; This fails to distinguish function definitions from
+                    ;; variable declarations (or even uses thereof), but is
+                    ;; a good pragmatic fallback.
                    (re-search-forward
                    (re-search-forward
-                    (concat "^([^ ]+" find-function-space-re "['(]"
+                    (concat "^([^ ]+" find-function-space-re "['(]?"
                             (regexp-quote (symbol-name symbol))
                             "\\_>")
                     nil t))
                (progn
                  (beginning-of-line)
                  (cons (current-buffer) (point)))
                             (regexp-quote (symbol-name symbol))
                             "\\_>")
                     nil t))
                (progn
                  (beginning-of-line)
                  (cons (current-buffer) (point)))
-             (error "Cannot find definition of `%s' in library `%s'"
-                    symbol library))))))))
+             (cons (current-buffer) nil))))))))
 
 ;;;###autoload
 (defun find-function-noselect (function)
   "Return a pair (BUFFER . POINT) pointing to the definition of FUNCTION.
 
 
 ;;;###autoload
 (defun find-function-noselect (function)
   "Return a pair (BUFFER . POINT) pointing to the definition of FUNCTION.
 
-Finds the Emacs Lisp library containing the definition of FUNCTION
+Finds the source file containing the definition of FUNCTION
 in a buffer and the point of the definition.  The buffer is
 in a buffer and the point of the definition.  The buffer is
-not selected.
+not selected.  If the function definition can't be found in
+the buffer, returns (BUFFER).
 
 If the file where FUNCTION is defined is not known, then it is
 
 If the file where FUNCTION is defined is not known, then it is
-searched for in `find-function-source-path' if non nil, otherwise
+searched for in `find-function-source-path' if non-nil, otherwise
 in `load-path'."
   (if (not function)
       (error "You didn't specify a function"))
 in `load-path'."
   (if (not function)
       (error "You didn't specify a function"))
@@ -322,7 +341,7 @@ Set mark before moving, if the buffer already existed."
       (when (memq new-buf orig-buffers)
        (push-mark orig-point))
       (funcall switch-fn new-buf)
       (when (memq new-buf orig-buffers)
        (push-mark orig-point))
       (funcall switch-fn new-buf)
-      (goto-char new-point)
+      (when new-point (goto-char new-point))
       (recenter find-function-recenter-line)
       (run-hooks 'find-function-after-hook))))
 
       (recenter find-function-recenter-line)
       (run-hooks 'find-function-after-hook))))
 
@@ -330,13 +349,13 @@ Set mark before moving, if the buffer already existed."
 (defun find-function (function)
   "Find the definition of the FUNCTION near point.
 
 (defun find-function (function)
   "Find the definition of the FUNCTION near point.
 
-Finds the Emacs Lisp library containing the definition of the function
+Finds the source file containing the definition of the function
 near point (selected by `function-called-at-point') in a buffer and
 places point before the definition.
 Set mark before moving, if the buffer already existed.
 
 The library where FUNCTION is defined is searched for in
 near point (selected by `function-called-at-point') in a buffer and
 places point before the definition.
 Set mark before moving, if the buffer already existed.
 
 The library where FUNCTION is defined is searched for in
-`find-function-source-path', if non nil, otherwise in `load-path'.
+`find-function-source-path', if non-nil, otherwise in `load-path'.
 See also `find-function-recenter-line' and `find-function-after-hook'."
   (interactive (find-function-read))
   (find-function-do-it function nil 'switch-to-buffer))
 See also `find-function-recenter-line' and `find-function-after-hook'."
   (interactive (find-function-read))
   (find-function-do-it function nil 'switch-to-buffer))
@@ -351,7 +370,7 @@ See `find-function' for more details."
 
 ;;;###autoload
 (defun find-function-other-frame (function)
 
 ;;;###autoload
 (defun find-function-other-frame (function)
-  "Find, in ananother frame, the definition of FUNCTION near point.
+  "Find, in another frame, the definition of FUNCTION near point.
 
 See `find-function' for more details."
   (interactive (find-function-read))
 
 See `find-function' for more details."
   (interactive (find-function-read))
@@ -359,31 +378,33 @@ See `find-function' for more details."
 
 ;;;###autoload
 (defun find-variable-noselect (variable &optional file)
 
 ;;;###autoload
 (defun find-variable-noselect (variable &optional file)
-  "Return a pair `(BUFFER . POINT)' pointing to the definition of SYMBOL.
+  "Return a pair `(BUFFER . POINT)' pointing to the definition of VARIABLE.
 
 
-Finds the Emacs Lisp library containing the definition of SYMBOL
-in a buffer, and the point of the definition.  It does not switch
-to the buffer or display it.
+Finds the library containing the definition of VARIABLE in a buffer and
+the point of the definition.  The buffer is not selected.
+If the variable's definition can't be found in the buffer, return (BUFFER).
 
 The library where VARIABLE is defined is searched for in FILE or
 
 The library where VARIABLE is defined is searched for in FILE or
-`find-function-source-path', if non nil, otherwise in `load-path'."
+`find-function-source-path', if non-nil, otherwise in `load-path'."
   (if (not variable)
   (if (not variable)
-      (error "You didn't specify a variable"))
-  (let ((library (or file (symbol-file variable 'defvar))))
-    (find-function-search-for-symbol variable 'defvar library)))
+      (error "You didn't specify a variable")
+    (let ((library (or file
+                       (symbol-file variable 'defvar)
+                       (help-C-file-name variable 'var))))
+      (find-function-search-for-symbol variable 'defvar library))))
 
 ;;;###autoload
 (defun find-variable (variable)
 
 ;;;###autoload
 (defun find-variable (variable)
-  "Find the definition of the VARIABLE near point.
+  "Find the definition of the VARIABLE at or before point.
 
 
-Finds the Emacs Lisp library containing the definition of the variable
+Finds the library containing the definition of the variable
 near point (selected by `variable-at-point') in a buffer and
 places point before the definition.
 
 Set mark before moving, if the buffer already existed.
 
 The library where VARIABLE is defined is searched for in
 near point (selected by `variable-at-point') in a buffer and
 places point before the definition.
 
 Set mark before moving, if the buffer already existed.
 
 The library where VARIABLE is defined is searched for in
-`find-function-source-path', if non nil, otherwise in `load-path'.
+`find-function-source-path', if non-nil, otherwise in `load-path'.
 See also `find-function-recenter-line' and `find-function-after-hook'."
   (interactive (find-function-read 'defvar))
   (find-function-do-it variable 'defvar 'switch-to-buffer))
 See also `find-function-recenter-line' and `find-function-after-hook'."
   (interactive (find-function-read 'defvar))
   (find-function-do-it variable 'defvar 'switch-to-buffer))
@@ -398,7 +419,7 @@ See `find-variable' for more details."
 
 ;;;###autoload
 (defun find-variable-other-frame (variable)
 
 ;;;###autoload
 (defun find-variable-other-frame (variable)
-  "Find, in annother frame, the definition of VARIABLE near point.
+  "Find, in another frame, the definition of VARIABLE near point.
 
 See `find-variable' for more details."
   (interactive (find-function-read 'defvar))
 
 See `find-variable' for more details."
   (interactive (find-function-read 'defvar))
@@ -407,18 +428,23 @@ See `find-variable' for more details."
 ;;;###autoload
 (defun find-definition-noselect (symbol type &optional file)
   "Return a pair `(BUFFER . POINT)' pointing to the definition of SYMBOL.
 ;;;###autoload
 (defun find-definition-noselect (symbol type &optional file)
   "Return a pair `(BUFFER . POINT)' pointing to the definition of SYMBOL.
-TYPE says what type of definition: nil for a function,
-`defvar' or `defface' for a variable or face.  This functoin
-does not switch to the buffer or display it.
+If the definition can't be found in the buffer, return (BUFFER).
+TYPE says what type of definition: nil for a function, `defvar' for a
+variable, `defface' for a face.  This function does not switch to the
+buffer nor display it.
 
 The library where SYMBOL is defined is searched for in FILE or
 
 The library where SYMBOL is defined is searched for in FILE or
-`find-function-source-path', if non nil, otherwise in `load-path'."
-  (if (not symbol)
-      (error "You didn't specify a symbol"))
-  (if (null type)
-      (find-function-noselect symbol)
+`find-function-source-path', if non-nil, otherwise in `load-path'."
+  (cond
+   ((not symbol)
+    (error "You didn't specify a symbol"))
+   ((null type)
+    (find-function-noselect symbol))
+   ((eq type 'defvar)
+    (find-variable-noselect symbol file))
+   (t
     (let ((library (or file (symbol-file symbol type))))
     (let ((library (or file (symbol-file symbol type))))
-      (find-function-search-for-symbol symbol type library))))
+      (find-function-search-for-symbol symbol type library)))))
 
 ;; For symmetry, this should be called find-face; but some programs
 ;; assume that, if that name is defined, it means something else.
 
 ;; For symmetry, this should be called find-face; but some programs
 ;; assume that, if that name is defined, it means something else.
@@ -433,7 +459,7 @@ places point before the definition.
 Set mark before moving, if the buffer already existed.
 
 The library where FACE is defined is searched for in
 Set mark before moving, if the buffer already existed.
 
 The library where FACE is defined is searched for in
-`find-function-source-path', if non nil, otherwise in `load-path'.
+`find-function-source-path', if non-nil, otherwise in `load-path'.
 See also `find-function-recenter-line' and `find-function-after-hook'."
   (interactive (find-function-read 'defface))
   (find-function-do-it face 'defface 'switch-to-buffer))
 See also `find-function-recenter-line' and `find-function-after-hook'."
   (interactive (find-function-read 'defface))
   (find-function-do-it face 'defface 'switch-to-buffer))
@@ -475,7 +501,7 @@ Set mark before moving, if the buffer already existed."
 
 ;;;###autoload
 (defun find-variable-at-point ()
 
 ;;;###autoload
 (defun find-variable-at-point ()
-  "Find directly the function at point in the other window."
+  "Find directly the variable at point in the other window."
   (interactive)
   (let ((symb (variable-at-point)))
     (when (and symb (not (equal symb 0)))
   (interactive)
   (let ((symb (variable-at-point)))
     (when (and symb (not (equal symb 0)))