LCOV - code coverage report
Current view: top level - lisp/emacs-lisp - find-func.el (source / functions) Hit Total Coverage
Test: tramp-tests-after.info Lines: 0 257 0.0 %
Date: 2017-08-30 10:12:24 Functions: 0 31 0.0 %

          Line data    Source code
       1             : ;;; find-func.el --- find the definition of the Emacs Lisp function near point  -*- lexical-binding:t -*-
       2             : 
       3             : ;; Copyright (C) 1997, 1999, 2001-2017 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, functions, variables
       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 3 of the License, or
      15             : ;; (at your option) 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.  If not, see <http://www.gnu.org/licenses/>.
      24             : 
      25             : ;;; Commentary:
      26             : ;;
      27             : ;; The funniest thing about this is that I can't imagine why a package
      28             : ;; so obviously useful as this hasn't been written before!!
      29             : ;; ;;; find-func
      30             : ;; (find-function-setup-keys)
      31             : ;;
      32             : ;; or just:
      33             : ;;
      34             : ;; (load "find-func")
      35             : ;;
      36             : ;; if you don't like the given keybindings and away you go!  It does
      37             : ;; pretty much what you would expect, putting the cursor at the
      38             : ;; definition of the function or variable at point.
      39             : ;;
      40             : ;; The code started out from `describe-function', `describe-key'
      41             : ;; ("help.el") and `fff-find-loaded-emacs-lisp-function' (Noah Friedman's
      42             : ;; "fff.el").
      43             : 
      44             : ;;; Code:
      45             : 
      46             : (eval-when-compile (require 'cl-lib))
      47             : 
      48             : ;;; User variables:
      49             : 
      50             : (defgroup find-function nil
      51             :   "Finds the definition of the Emacs Lisp symbol near point."
      52             : ;;   :prefix "find-function"
      53             :   :group 'lisp)
      54             : 
      55             : (defconst find-function-space-re "\\(?:\\s-\\|\n\\|;.*\n\\)+")
      56             : 
      57             : (defcustom find-function-regexp
      58             :   ;; Match things like (defun foo ...), (defmacro foo ...),
      59             :   ;; (define-skeleton foo ...), (define-generic-mode 'foo ...),
      60             :   ;;  (define-derived-mode foo ...), (define-minor-mode foo)
      61             :   (concat
      62             :    "^\\s-*(\\(def\\(ine-skeleton\\|ine-generic-mode\\|ine-derived-mode\\|\
      63             : ine\\(?:-global\\)?-minor-mode\\|ine-compilation-mode\\|un-cvs-mode\\|\
      64             : foo\\|\\(?:[^icfgv]\\|g[^r]\\)\\(\\w\\|\\s_\\)+\\*?\\)\\|easy-mmode-define-[a-z-]+\\|easy-menu-define\\|\
      65             : menu-bar-make-toggle\\)"
      66             :    find-function-space-re
      67             :    "\\('\\|(quote \\)?%s\\(\\s-\\|$\\|[()]\\)")
      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'
      70             : should insert the function name.  The default value avoids `defconst',
      71             : `defgroup', `defvar', `defface'.
      72             : 
      73             : Please send improvements and fixes to the maintainer."
      74             :   :type 'regexp
      75             :   :group 'find-function
      76             :   :version "21.1")
      77             : 
      78             : (defcustom find-variable-regexp
      79             :   (concat
      80             :    "^\\s-*(\\(def[^fumag]\\(\\w\\|\\s_\\)+\\*?\\|\
      81             : easy-mmode-def\\(map\\|syntax\\)\\|easy-menu-define\\)"
      82             :    find-function-space-re
      83             :    "%s\\(\\s-\\|$\\)")
      84             :   "The regexp used by `find-variable' to search for a variable definition.
      85             : Note it must contain a `%s' at the place where `format'
      86             : should insert the variable name.  The default value
      87             : avoids `defun', `defmacro', `defalias', `defadvice', `defgroup', `defface'.
      88             : 
      89             : Please send improvements and fixes to the maintainer."
      90             :   :type 'regexp
      91             :   :group 'find-function
      92             :   :version "21.1")
      93             : 
      94             : (defcustom find-face-regexp
      95             :   (concat"^\\s-*(defface" find-function-space-re "%s\\(\\s-\\|$\\)")
      96             :   "The regexp used by `find-face' to search for a face definition.
      97             : Note it must contain a `%s' at the place where `format'
      98             : should insert the face name.
      99             : 
     100             : Please send improvements and fixes to the maintainer."
     101             :   :type 'regexp
     102             :   :group 'find-function
     103             :   :version "22.1")
     104             : 
     105             : (defcustom find-feature-regexp
     106             :   (concat ";;; Code:")
     107             :   "The regexp used by `xref-find-definitions' when searching for a feature definition.
     108             : Note it may contain up to one `%s' at the place where `format'
     109             : should insert the feature name."
     110             :   ;; We search for ";;; Code" rather than (feature '%s) because the
     111             :   ;; former is near the start of the code, and the latter is very
     112             :   ;; uninteresting. If the regexp is not found, just goes to
     113             :   ;; (point-min), which is acceptable in this case.
     114             :   :type 'regexp
     115             :   :group 'xref
     116             :   :version "25.1")
     117             : 
     118             : (defcustom find-alias-regexp
     119             :   "(defalias +'%s"
     120             :   "The regexp used by `xref-find-definitions' to search for an alias definition.
     121             : Note it must contain a `%s' at the place where `format'
     122             : should insert the feature name."
     123             :   :type 'regexp
     124             :   :group 'xref
     125             :   :version "25.1")
     126             : 
     127             : (defvar find-function-regexp-alist
     128             :   '((nil . find-function-regexp)
     129             :     (defvar . find-variable-regexp)
     130             :     (defface . find-face-regexp)
     131             :     (feature . find-feature-regexp)
     132             :     (defalias . find-alias-regexp))
     133             :   "Alist mapping definition types into regexp variables.
     134             : Each regexp variable's value should actually be a format string
     135             : to be used to substitute the desired symbol name into the regexp.
     136             : Instead of regexp variable, types can be mapped to functions as well,
     137             : in which case the function is called with one argument (the object
     138             : we're looking for) and it should search for it.")
     139             : (put 'find-function-regexp-alist 'risky-local-variable t)
     140             : 
     141             : (defcustom find-function-source-path nil
     142             :   "The default list of directories where `find-function' searches.
     143             : 
     144             : If this variable is nil then `find-function' searches `load-path' by
     145             : default."
     146             :   :type '(repeat directory)
     147             :   :group 'find-function)
     148             : 
     149             : (defcustom find-function-recenter-line 1
     150             :   "The window line-number from which to start displaying a symbol definition.
     151             : A value of nil implies center the beginning of the definition.
     152             : See `find-function' and `find-variable'."
     153             :   :type '(choice (const :tag "Center" nil)
     154             :                  integer)
     155             :   :group 'find-function
     156             :   :version "20.3")
     157             : 
     158             : (defcustom find-function-after-hook nil
     159             :   "Hook run after finding symbol definition.
     160             : 
     161             : See the functions `find-function' and `find-variable'."
     162             :   :type 'hook
     163             :   :group 'find-function
     164             :   :version "20.3")
     165             : 
     166             : ;;; Functions:
     167             : 
     168             : (defun find-library-suffixes ()
     169           0 :   (let ((suffixes nil))
     170           0 :     (dolist (suffix (get-load-suffixes) (nreverse suffixes))
     171           0 :       (unless (string-match "elc" suffix) (push suffix suffixes)))))
     172             : 
     173             : (defun find-library--load-name (library)
     174           0 :   (let ((name library))
     175           0 :     (dolist (dir load-path)
     176           0 :       (let ((rel (file-relative-name library dir)))
     177           0 :         (if (and (not (string-match "\\`\\.\\./" rel))
     178           0 :                  (< (length rel) (length name)))
     179           0 :             (setq name rel))))
     180           0 :     (unless (equal name library) name)))
     181             : 
     182             : (defun find-library-name (library)
     183             :   "Return the absolute file name of the Emacs Lisp source of LIBRARY.
     184             : LIBRARY should be a string (the name of the library)."
     185             :   ;; If the library is byte-compiled, try to find a source library by
     186             :   ;; the same name.
     187           0 :   (when (string-match "\\.el\\(c\\(\\..*\\)?\\)\\'" library)
     188           0 :     (setq library (replace-match "" t t library)))
     189           0 :   (or
     190           0 :    (locate-file library
     191           0 :                 (or find-function-source-path load-path)
     192           0 :                 (find-library-suffixes))
     193           0 :    (locate-file library
     194           0 :                 (or find-function-source-path load-path)
     195           0 :                 load-file-rep-suffixes)
     196           0 :    (when (file-name-absolute-p library)
     197           0 :      (let ((rel (find-library--load-name library)))
     198           0 :        (when rel
     199           0 :          (or
     200           0 :           (locate-file rel
     201           0 :                        (or find-function-source-path load-path)
     202           0 :                        (find-library-suffixes))
     203           0 :           (locate-file rel
     204           0 :                        (or find-function-source-path load-path)
     205           0 :                        load-file-rep-suffixes)))))
     206           0 :    (find-library--from-load-history library)
     207           0 :    (error "Can't find library %s" library)))
     208             : 
     209             : (defun find-library--from-load-history (library)
     210             :   ;; In `load-history', the file may be ".elc", ".el", ".el.gz", and
     211             :   ;; LIBRARY may be "foo.el" or "foo".
     212           0 :   (let ((load-re
     213           0 :          (concat "\\(" (regexp-quote (file-name-sans-extension library)) "\\)"
     214           0 :                  (regexp-opt (get-load-suffixes)) "\\'")))
     215           0 :     (cl-loop
     216           0 :      for (file . _) in load-history thereis
     217           0 :      (and (stringp file) (string-match load-re file)
     218           0 :           (let ((dir (substring file 0 (match-beginning 1)))
     219           0 :                 (basename (match-string 1 file)))
     220           0 :             (locate-file basename (list dir) (find-library-suffixes)))))))
     221             : 
     222             : (defvar find-function-C-source-directory
     223             :   (let ((dir (expand-file-name "src" source-directory)))
     224             :     (if (file-accessible-directory-p dir) dir))
     225             :   "Directory where the C source files of Emacs can be found.
     226             : If nil, do not try to find the source code of functions and variables
     227             : defined in C.")
     228             : 
     229             : (declare-function ad-get-advice-info "advice" (function))
     230             : 
     231             : (defun find-function-advised-original (func)
     232             :   "Return the original function definition of an advised function FUNC.
     233             : If FUNC is not a symbol, return it.  Else, if it's not advised,
     234             : return the symbol's function definition."
     235           0 :   (or (and (symbolp func)
     236           0 :            (featurep 'nadvice)
     237           0 :            (let ((ofunc (advice--symbol-function func)))
     238           0 :              (if (advice--p ofunc)
     239           0 :                  (advice--cd*r ofunc)
     240           0 :                ofunc)))
     241           0 :       func))
     242             : 
     243             : (defun find-function-C-source (fun-or-var file type)
     244             :   "Find the source location where FUN-OR-VAR is defined in FILE.
     245             : TYPE should be nil to find a function, or `defvar' to find a variable."
     246           0 :   (let ((dir (or find-function-C-source-directory
     247           0 :                  (read-directory-name "Emacs C source dir: " nil nil t))))
     248           0 :     (setq file (expand-file-name file dir))
     249           0 :     (if (file-readable-p file)
     250           0 :         (if (null find-function-C-source-directory)
     251           0 :             (setq find-function-C-source-directory dir))
     252           0 :       (error "The C source file %s is not available"
     253           0 :              (file-name-nondirectory file))))
     254           0 :   (unless type
     255             :     ;; Either or both an alias and its target might be advised.
     256           0 :     (setq fun-or-var (find-function-advised-original
     257           0 :                       (indirect-function
     258           0 :                        (find-function-advised-original fun-or-var)))))
     259           0 :   (with-current-buffer (find-file-noselect file)
     260           0 :     (goto-char (point-min))
     261           0 :     (unless (re-search-forward
     262           0 :              (if type
     263           0 :                  (concat "DEFVAR[A-Z_]*[ \t\n]*([ \t\n]*\""
     264           0 :                          (regexp-quote (symbol-name fun-or-var))
     265           0 :                          "\"")
     266           0 :                (concat "DEFUN[ \t\n]*([ \t\n]*\""
     267           0 :                        (regexp-quote (subr-name (advice--cd*r fun-or-var)))
     268           0 :                        "\""))
     269           0 :              nil t)
     270           0 :       (error "Can't find source for %s" fun-or-var))
     271           0 :     (cons (current-buffer) (match-beginning 0))))
     272             : 
     273             : ;;;###autoload
     274             : (defun find-library (library)
     275             :   "Find the Emacs Lisp source of LIBRARY.
     276             : 
     277             : Interactively, prompt for LIBRARY using the one at or near point."
     278           0 :   (interactive (list (read-library-name)))
     279           0 :   (prog1
     280           0 :       (switch-to-buffer (find-file-noselect (find-library-name library)))
     281           0 :     (run-hooks 'find-function-after-hook)))
     282             : 
     283             : (defun read-library-name ()
     284             :   "Read and return a library name, defaulting to the one near point.
     285             : 
     286             : A library name is the filename of an Emacs Lisp library located
     287             : in a directory under `load-path' (or `find-function-source-path',
     288             : if non-nil)."
     289           0 :   (let* ((dirs (or find-function-source-path load-path))
     290           0 :          (suffixes (find-library-suffixes))
     291           0 :          (table (apply-partially 'locate-file-completion-table
     292           0 :                                  dirs suffixes))
     293           0 :          (def (if (eq (function-called-at-point) 'require)
     294             :                   ;; `function-called-at-point' may return 'require
     295             :                   ;; with `point' anywhere on this line.  So wrap the
     296             :                   ;; `save-excursion' below in a `condition-case' to
     297             :                   ;; avoid reporting a scan-error here.
     298           0 :                   (condition-case nil
     299           0 :                       (save-excursion
     300           0 :                         (backward-up-list)
     301           0 :                         (forward-char)
     302           0 :                         (forward-sexp 2)
     303           0 :                         (thing-at-point 'symbol))
     304           0 :                     (error nil))
     305           0 :                 (thing-at-point 'symbol))))
     306           0 :     (when (and def (not (test-completion def table)))
     307           0 :       (setq def nil))
     308           0 :     (completing-read (if def
     309           0 :                          (format "Library name (default %s): " def)
     310           0 :                        "Library name: ")
     311           0 :                      table nil nil nil nil def)))
     312             : 
     313             : ;;;###autoload
     314             : (defun find-library-other-window (library)
     315             :   "Find the Emacs Lisp source of LIBRARY in another window.
     316             : 
     317             : See `find-library' for more details."
     318           0 :   (interactive (list (read-library-name)))
     319           0 :   (prog1
     320           0 :       (switch-to-buffer-other-window (find-file-noselect
     321           0 :                                       (find-library-name library)))
     322           0 :     (run-hooks 'find-function-after-hook)))
     323             : 
     324             : ;;;###autoload
     325             : (defun find-library-other-frame (library)
     326             :   "Find the Emacs Lisp source of LIBRARY in another frame.
     327             : 
     328             : See `find-library' for more details."
     329           0 :   (interactive (list (read-library-name)))
     330           0 :   (prog1
     331           0 :       (switch-to-buffer-other-frame (find-file-noselect
     332           0 :                                      (find-library-name library)))
     333           0 :     (run-hooks 'find-function-after-hook)))
     334             : 
     335             : ;;;###autoload
     336             : (defun find-function-search-for-symbol (symbol type library)
     337             :   "Search for SYMBOL's definition of type TYPE in LIBRARY.
     338             : Visit the library in a buffer, and return a cons cell (BUFFER . POSITION),
     339             : or just (BUFFER . nil) if the definition can't be found in the file.
     340             : 
     341             : If TYPE is nil, look for a function definition.
     342             : Otherwise, TYPE specifies the kind of definition,
     343             : and it is interpreted via `find-function-regexp-alist'.
     344             : The search is done in the source for library LIBRARY."
     345           0 :   (if (null library)
     346           0 :       (error "Don't know where `%s' is defined" symbol))
     347             :   ;; Some functions are defined as part of the construct
     348             :   ;; that defines something else.
     349           0 :   (while (and (symbolp symbol) (get symbol 'definition-name))
     350           0 :     (setq symbol (get symbol 'definition-name)))
     351           0 :   (if (string-match "\\`src/\\(.*\\.\\(c\\|m\\)\\)\\'" library)
     352           0 :       (find-function-C-source symbol (match-string 1 library) type)
     353           0 :     (when (string-match "\\.el\\(c\\)\\'" library)
     354           0 :       (setq library (substring library 0 (match-beginning 1))))
     355             :     ;; Strip extension from .emacs.el to make sure symbol is searched in
     356             :     ;; .emacs too.
     357           0 :     (when (string-match "\\.emacs\\(.el\\)" library)
     358           0 :       (setq library (substring library 0 (match-beginning 1))))
     359           0 :     (let* ((filename (find-library-name library))
     360           0 :            (regexp-symbol (cdr (assq type find-function-regexp-alist))))
     361           0 :       (with-current-buffer (find-file-noselect filename)
     362           0 :         (let ((regexp (if (functionp regexp-symbol) regexp-symbol
     363           0 :                         (format (symbol-value regexp-symbol)
     364             :                                 ;; Entry for ` (backquote) macro in loaddefs.el,
     365             :                                 ;; (defalias (quote \`)..., has a \ but
     366             :                                 ;; (symbol-name symbol) doesn't.  Add an
     367             :                                 ;; optional \ to catch this.
     368           0 :                                 (concat "\\\\?"
     369           0 :                                         (regexp-quote (symbol-name symbol))))))
     370             :               (case-fold-search))
     371           0 :           (with-syntax-table emacs-lisp-mode-syntax-table
     372           0 :             (goto-char (point-min))
     373           0 :             (if (if (functionp regexp)
     374           0 :                     (funcall regexp symbol)
     375           0 :                   (or (re-search-forward regexp nil t)
     376             :                       ;; `regexp' matches definitions using known forms like
     377             :                       ;; `defun', or `defvar'.  But some functions/variables
     378             :                       ;; are defined using special macros (or functions), so
     379             :                       ;; if `regexp' can't find the definition, we look for
     380             :                       ;; something of the form "(SOMETHING <symbol> ...)".
     381             :                       ;; This fails to distinguish function definitions from
     382             :                       ;; variable declarations (or even uses thereof), but is
     383             :                       ;; a good pragmatic fallback.
     384           0 :                       (re-search-forward
     385           0 :                        (concat "^([^ ]+" find-function-space-re "['(]?"
     386           0 :                                (regexp-quote (symbol-name symbol))
     387           0 :                                "\\_>")
     388           0 :                        nil t)))
     389           0 :                 (progn
     390           0 :                   (beginning-of-line)
     391           0 :                   (cons (current-buffer) (point)))
     392           0 :               (cons (current-buffer) nil))))))))
     393             : 
     394             : (defun find-function-library (function &optional lisp-only verbose)
     395             :   "Return the pair (ORIG-FUNCTION . LIBRARY) for FUNCTION.
     396             : 
     397             : ORIG-FUNCTION is the original name, after removing all advice and
     398             : resolving aliases.  LIBRARY is an absolute file name, a relative
     399             : file name inside the C sources directory, or a name of an
     400             : autoloaded feature.
     401             : 
     402             : If ORIG-FUNCTION is a built-in function and LISP-ONLY is non-nil,
     403             : signal an error.
     404             : 
     405             : If VERBOSE is non-nil, and FUNCTION is an alias, display a
     406             : message about the whole chain of aliases."
     407           0 :   (let ((def (when (symbolp function)
     408           0 :                (or (fboundp function)
     409           0 :                    (signal 'void-function (list function)))
     410           0 :                (find-function-advised-original function)))
     411             :         aliases)
     412             :     ;; FIXME for completeness, it might be nice to print something like:
     413             :     ;; foo (which is advised), which is an alias for bar (which is advised).
     414           0 :     (while (and def (symbolp def))
     415           0 :       (or (eq def function)
     416           0 :           (not verbose)
     417           0 :           (setq aliases (if aliases
     418           0 :                             (concat aliases
     419           0 :                                     (format-message
     420             :                                      ", which is an alias for `%s'"
     421           0 :                                      (symbol-name def)))
     422           0 :                           (format-message "`%s' is an alias for `%s'"
     423           0 :                                           function (symbol-name def)))))
     424           0 :       (setq function (find-function-advised-original function)
     425           0 :             def (find-function-advised-original function)))
     426           0 :     (if aliases
     427           0 :         (message "%s" aliases))
     428           0 :     (cons function
     429           0 :           (cond
     430           0 :            ((autoloadp def) (nth 1 def))
     431           0 :            ((subrp def)
     432           0 :             (if lisp-only
     433           0 :                 (error "%s is a built-in function" function))
     434           0 :             (help-C-file-name def 'subr))
     435           0 :            ((symbol-file function 'defun))))))
     436             : 
     437             : ;;;###autoload
     438             : (defun find-function-noselect (function &optional lisp-only)
     439             :   "Return a pair (BUFFER . POINT) pointing to the definition of FUNCTION.
     440             : 
     441             : Finds the source file containing the definition of FUNCTION
     442             : in a buffer and the point of the definition.  The buffer is
     443             : not selected.  If the function definition can't be found in
     444             : the buffer, returns (BUFFER).
     445             : 
     446             : If FUNCTION is a built-in function, this function normally
     447             : attempts to find it in the Emacs C sources; however, if LISP-ONLY
     448             : is non-nil, signal an error instead.
     449             : 
     450             : If the file where FUNCTION is defined is not known, then it is
     451             : searched for in `find-function-source-path' if non-nil, otherwise
     452             : in `load-path'."
     453           0 :   (if (not function)
     454           0 :     (error "You didn't specify a function"))
     455           0 :   (let ((func-lib (find-function-library function lisp-only t)))
     456           0 :     (find-function-search-for-symbol (car func-lib) nil (cdr func-lib))))
     457             : 
     458             : (defun find-function-read (&optional type)
     459             :   "Read and return an interned symbol, defaulting to the one near point.
     460             : 
     461             : If TYPE is nil, insist on a symbol with a function definition.
     462             : Otherwise TYPE should be `defvar' or `defface'.
     463             : If TYPE is nil, defaults using `function-called-at-point',
     464             : otherwise uses `variable-at-point'."
     465           0 :   (let* ((symb1 (cond ((null type) (function-called-at-point))
     466           0 :                       ((eq type 'defvar) (variable-at-point))
     467           0 :                       (t (variable-at-point t))))
     468           0 :          (symb  (unless (eq symb1 0) symb1))
     469           0 :          (predicate (cdr (assq type '((nil . fboundp)
     470             :                                       (defvar . boundp)
     471           0 :                                       (defface . facep)))))
     472           0 :          (prompt-type (cdr (assq type '((nil . "function")
     473             :                                         (defvar . "variable")
     474           0 :                                         (defface . "face")))))
     475           0 :          (prompt (concat "Find " prompt-type
     476           0 :                          (and symb (format " (default %s)" symb))
     477           0 :                          ": "))
     478             :          (enable-recursive-minibuffers t))
     479           0 :     (list (intern (completing-read
     480           0 :                    prompt obarray predicate
     481           0 :                    t nil nil (and symb (symbol-name symb)))))))
     482             : 
     483             : (defun find-function-do-it (symbol type switch-fn)
     484             :   "Find Emacs Lisp SYMBOL in a buffer and display it.
     485             : TYPE is nil to search for a function definition,
     486             : or else `defvar' or `defface'.
     487             : 
     488             : The variable `find-function-recenter-line' controls how
     489             : to recenter the display.  SWITCH-FN is the function to call
     490             : to display and select the buffer.
     491             : See also `find-function-after-hook'.
     492             : 
     493             : Set mark before moving, if the buffer already existed."
     494           0 :   (let* ((orig-point (point))
     495           0 :         (orig-buffers (buffer-list))
     496           0 :         (buffer-point (save-excursion
     497           0 :                         (find-definition-noselect symbol type)))
     498           0 :         (new-buf (car buffer-point))
     499           0 :         (new-point (cdr buffer-point)))
     500           0 :     (when buffer-point
     501           0 :       (when (memq new-buf orig-buffers)
     502           0 :         (push-mark orig-point))
     503           0 :       (funcall switch-fn new-buf)
     504           0 :       (when new-point (goto-char new-point))
     505           0 :       (recenter find-function-recenter-line)
     506           0 :       (run-hooks 'find-function-after-hook))))
     507             : 
     508             : ;;;###autoload
     509             : (defun find-function (function)
     510             :   "Find the definition of the FUNCTION near point.
     511             : 
     512             : Finds the source file containing the definition of the function
     513             : near point (selected by `function-called-at-point') in a buffer and
     514             : places point before the definition.
     515             : Set mark before moving, if the buffer already existed.
     516             : 
     517             : The library where FUNCTION is defined is searched for in
     518             : `find-function-source-path', if non-nil, otherwise in `load-path'.
     519             : See also `find-function-recenter-line' and `find-function-after-hook'."
     520           0 :   (interactive (find-function-read))
     521           0 :   (find-function-do-it function nil 'switch-to-buffer))
     522             : 
     523             : ;;;###autoload
     524             : (defun find-function-other-window (function)
     525             :   "Find, in another window, the definition of FUNCTION near point.
     526             : 
     527             : See `find-function' for more details."
     528           0 :   (interactive (find-function-read))
     529           0 :   (find-function-do-it function nil 'switch-to-buffer-other-window))
     530             : 
     531             : ;;;###autoload
     532             : (defun find-function-other-frame (function)
     533             :   "Find, in another frame, the definition of FUNCTION near point.
     534             : 
     535             : See `find-function' for more details."
     536           0 :   (interactive (find-function-read))
     537           0 :   (find-function-do-it function nil 'switch-to-buffer-other-frame))
     538             : 
     539             : ;;;###autoload
     540             : (defun find-variable-noselect (variable &optional file)
     541             :   "Return a pair `(BUFFER . POINT)' pointing to the definition of VARIABLE.
     542             : 
     543             : Finds the library containing the definition of VARIABLE in a buffer and
     544             : the point of the definition.  The buffer is not selected.
     545             : If the variable's definition can't be found in the buffer, return (BUFFER).
     546             : 
     547             : The library where VARIABLE is defined is searched for in FILE or
     548             : `find-function-source-path', if non-nil, otherwise in `load-path'."
     549           0 :   (if (not variable)
     550           0 :       (error "You didn't specify a variable")
     551           0 :     (let ((library (or file
     552           0 :                        (symbol-file variable 'defvar)
     553           0 :                        (help-C-file-name variable 'var))))
     554           0 :       (find-function-search-for-symbol variable 'defvar library))))
     555             : 
     556             : ;;;###autoload
     557             : (defun find-variable (variable)
     558             :   "Find the definition of the VARIABLE at or before point.
     559             : 
     560             : Finds the library containing the definition of the variable
     561             : near point (selected by `variable-at-point') in a buffer and
     562             : places point before the definition.
     563             : 
     564             : Set mark before moving, if the buffer already existed.
     565             : 
     566             : The library where VARIABLE is defined is searched for in
     567             : `find-function-source-path', if non-nil, otherwise in `load-path'.
     568             : See also `find-function-recenter-line' and `find-function-after-hook'."
     569           0 :   (interactive (find-function-read 'defvar))
     570           0 :   (find-function-do-it variable 'defvar 'switch-to-buffer))
     571             : 
     572             : ;;;###autoload
     573             : (defun find-variable-other-window (variable)
     574             :   "Find, in another window, the definition of VARIABLE near point.
     575             : 
     576             : See `find-variable' for more details."
     577           0 :   (interactive (find-function-read 'defvar))
     578           0 :   (find-function-do-it variable 'defvar 'switch-to-buffer-other-window))
     579             : 
     580             : ;;;###autoload
     581             : (defun find-variable-other-frame (variable)
     582             :   "Find, in another frame, the definition of VARIABLE near point.
     583             : 
     584             : See `find-variable' for more details."
     585           0 :   (interactive (find-function-read 'defvar))
     586           0 :   (find-function-do-it variable 'defvar 'switch-to-buffer-other-frame))
     587             : 
     588             : ;;;###autoload
     589             : (defun find-definition-noselect (symbol type &optional file)
     590             :   "Return a pair `(BUFFER . POINT)' pointing to the definition of SYMBOL.
     591             : If the definition can't be found in the buffer, return (BUFFER).
     592             : TYPE says what type of definition: nil for a function, `defvar' for a
     593             : variable, `defface' for a face.  This function does not switch to the
     594             : buffer nor display it.
     595             : 
     596             : The library where SYMBOL is defined is searched for in FILE or
     597             : `find-function-source-path', if non-nil, otherwise in `load-path'."
     598           0 :   (cond
     599           0 :    ((not symbol)
     600           0 :     (error "You didn't specify a symbol"))
     601           0 :    ((null type)
     602           0 :     (find-function-noselect symbol))
     603           0 :    ((eq type 'defvar)
     604           0 :     (find-variable-noselect symbol file))
     605             :    (t
     606           0 :     (let ((library (or file (symbol-file symbol type))))
     607           0 :       (find-function-search-for-symbol symbol type library)))))
     608             : 
     609             : ;; For symmetry, this should be called find-face; but some programs
     610             : ;; assume that, if that name is defined, it means something else.
     611             : ;;;###autoload
     612             : (defun find-face-definition (face)
     613             :   "Find the definition of FACE.  FACE defaults to the name near point.
     614             : 
     615             : Finds the Emacs Lisp library containing the definition of the face
     616             : near point (selected by `variable-at-point') in a buffer and
     617             : places point before the definition.
     618             : 
     619             : Set mark before moving, if the buffer already existed.
     620             : 
     621             : The library where FACE is defined is searched for in
     622             : `find-function-source-path', if non-nil, otherwise in `load-path'.
     623             : See also `find-function-recenter-line' and `find-function-after-hook'."
     624           0 :   (interactive (find-function-read 'defface))
     625           0 :   (find-function-do-it face 'defface 'switch-to-buffer))
     626             : 
     627             : (defun find-function-on-key-do-it (key find-fn)
     628             :   "Find the function that KEY invokes.  KEY is a string.
     629             : Set mark before moving, if the buffer already existed.
     630             : 
     631             : FIND-FN is the function to call to navigate to the function."
     632           0 :   (let (defn)
     633           0 :     (save-excursion
     634           0 :       (let* ((event (and (eventp key) (aref key 0))) ; Null event OK below.
     635           0 :              (start (event-start event))
     636           0 :              (modifiers (event-modifiers event))
     637           0 :              (window (and (or (memq 'click modifiers) (memq 'down modifiers)
     638           0 :                               (memq 'drag modifiers))
     639           0 :                           (posn-window start))))
     640             :         ;; For a mouse button event, go to the button it applies to
     641             :         ;; to get the right key bindings.  And go to the right place
     642             :         ;; in case the keymap depends on where you clicked.
     643           0 :         (when (windowp window)
     644           0 :           (set-buffer (window-buffer window))
     645           0 :           (goto-char (posn-point start)))
     646           0 :         (setq defn (key-binding key))))
     647           0 :     (let ((key-desc (key-description key)))
     648           0 :       (if (or (null defn) (integerp defn))
     649           0 :           (message "%s is unbound" key-desc)
     650           0 :         (if (consp defn)
     651           0 :             (message "%s runs %s" key-desc (prin1-to-string defn))
     652           0 :           (funcall find-fn defn))))))
     653             : 
     654             : ;;;###autoload
     655             : (defun find-function-on-key (key)
     656             :   "Find the function that KEY invokes.  KEY is a string.
     657             : Set mark before moving, if the buffer already existed."
     658             :   (interactive "kFind function on key: ")
     659           0 :   (find-function-on-key-do-it key #'find-function))
     660             : 
     661             : ;;;###autoload
     662             : (defun find-function-on-key-other-window (key)
     663             :   "Find, in the other window, the function that KEY invokes.
     664             : See `find-function-on-key'."
     665             :   (interactive "kFind function on key: ")
     666           0 :   (find-function-on-key-do-it key #'find-function-other-window))
     667             : 
     668             : ;;;###autoload
     669             : (defun find-function-on-key-other-frame (key)
     670             :   "Find, in the other frame, the function that KEY invokes.
     671             : See `find-function-on-key'."
     672             :   (interactive "kFind function on key: ")
     673           0 :   (find-function-on-key-do-it key #'find-function-other-frame))
     674             : 
     675             : ;;;###autoload
     676             : (defun find-function-at-point ()
     677             :   "Find directly the function at point in the other window."
     678             :   (interactive)
     679           0 :   (let ((symb (function-called-at-point)))
     680           0 :     (when symb
     681           0 :       (find-function-other-window symb))))
     682             : 
     683             : ;;;###autoload
     684             : (defun find-variable-at-point ()
     685             :   "Find directly the variable at point in the other window."
     686             :   (interactive)
     687           0 :   (let ((symb (variable-at-point)))
     688           0 :     (when (and symb (not (equal symb 0)))
     689           0 :       (find-variable-other-window symb))))
     690             : 
     691             : ;;;###autoload
     692             : (defun find-function-setup-keys ()
     693             :   "Define some key bindings for the find-function family of functions."
     694           0 :   (define-key ctl-x-map "F" 'find-function)
     695           0 :   (define-key ctl-x-4-map "F" 'find-function-other-window)
     696           0 :   (define-key ctl-x-5-map "F" 'find-function-other-frame)
     697           0 :   (define-key ctl-x-map "K" 'find-function-on-key)
     698           0 :   (define-key ctl-x-4-map "K" 'find-function-on-key-other-window)
     699           0 :   (define-key ctl-x-5-map "K" 'find-function-on-key-other-frame)
     700           0 :   (define-key ctl-x-map "V" 'find-variable)
     701           0 :   (define-key ctl-x-4-map "V" 'find-variable-other-window)
     702           0 :   (define-key ctl-x-5-map "V" 'find-variable-other-frame))
     703             : 
     704             : (provide 'find-func)
     705             : 
     706             : ;;; find-func.el ends here

Generated by: LCOV version 1.12