3

Where can I find the all Emacs' elisp scripts? I don't mean scripts users developed or installed themselves, but the common elisp script already there.

For example,

if I have a function like describe-char or insert-file, how can I find the file contained these functions?

Pierre B
  • 654
  • 2
  • 6
  • 15
  • 2
    `M-x find-function-other-window` and `M-x find-variable-other-window`. I have it set with `(global-set-key (kbd "C-h F") 'find-function-other-window)` and `(global-set-key (kbd "C-h V") 'find-variable-other-window)` My mode-line is set up to display the path of the file that is displayed in the open buffer. Once the file is open, you can also use `M-x describe-variable RET buffer-file-name` and that will give you the full path. – lawlist Mar 26 '14 at 02:32
  • Of course `C-h F` has a fairly useful default binding, so I would suggest picking an unused binding. `C-h C-f` was my pick for this; still not a reserved binding, but it's not currently used by default. – phils Mar 26 '14 at 03:33
  • 5
    Note that the .el could be uninstalled. For example in debian, you will need to install the emacs23-el or emacs24-el package. If you don't then only the elc (compiled lisp file) will be available. – Rémi Mar 26 '14 at 04:28

5 Answers5

3

Ctrl-h f will tell a function's explanation and where it is contained.

And if you want a function to do this automaticlly, here's a draft:

(defun my-find-lisp-object-file-name (function)
  "Display the lisp file name of FUNCTION (a symbol)."
  (interactive
   (let ((fn (function-called-at-point))
     (enable-recursive-minibuffers t)
     val)
     (setq val (completing-read (if fn
                    (format "Describe function (default %s): " fn)
                  "Describe function: ")
                obarray 'fboundp t nil nil
                (and fn (symbol-name fn))))
     (list (if (equal val "")
           fn (intern val)))))
  (if (null function)
      (message "You didn't specify a function")
    (setq object-file-name (find-lisp-object-file-name function (symbol-function function)))
    (if (eq object-file-name 'C-source)
        (message "%s is in %s" function "C source code")
      (setq buff (find-function-search-for-symbol function nil object-file-name))
      (setq buf-name (buffer-name(car buff)))
      (setq buf-pos (cdr buff))
      (switch-to-buffer (car buff))
      (message "%s is in %s(%s, %d)" function object-file-name buf-name buf-pos))))
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • Yes, it describes what the function does, but not where it is. I want to know where the containing *.el file is. – Pierre B Mar 26 '14 at 02:29
  • 1
    @PierreB I'm not sure what you want to know, but when you get the doc of a function, such as `describe-char`, you can get the `.el` file's link in the `*Help*` buffer, and get the location of the `.el` file. Such as `descr-text.el` in `/usr/local/share/emacs/24.3/lisp/descr-text.el.gz`. Isn't it? – songyuanyao Mar 26 '14 at 02:34
  • 1
    Which is to say that the library name displayed in the `*Help*` buffer is linked to the source file which defines the function being described; so you can just follow the link (as an alternative to calling `find-function`). – phils Mar 26 '14 at 03:36
  • 1
    OK, this worked, but only after installing the emacs23-el package, as Remi pointed at above. – Pierre B Mar 26 '14 at 14:51
2

I guess M-x locate-library RET <libname> RET could be an answer tho it needs the library name rather than the function name. Else, M-x find-function-other-window will not just tell you where the file is, but instead will open the file, after which you can use M-x pwd to know where you are.

One more thing: you can do C-h v load-path RET to see the directories that Emacs uses to find its libraries, so that should give you a good idea of where all the bundled Elisp files reside.

Stefan
  • 27,908
  • 4
  • 53
  • 82
1

INITIAL DRAFT (March 25, 2014):  First rough draft.

EDIT (March 26, 2014):  Added a global-set-key. Added one more car to the final message in order to fully extract the path of the file name from the list of button text properties. Added some colorization to the initial and final messages. Added return cursor to beginning of buffer at the end of the function. Added options for find-variable-other-window and find-function-other-window. Added conditions so that no messages are generated if there is no file name.


Here is a fun little function that I whipped up -- it displays a message with a file path if an *.el file is displayed in the *Help* buffer.


(global-set-key (kbd "C-h z") 'lawlist-describe-find-function-variable)

(defun lawlist-describe-find-function-variable ()
"Describe or find a function / variable.  Displays the path of filename."
(interactive)
  (message (concat
    (propertize "Describe" 'face 'font-lock-keyword-face)
    " ["
    (propertize "f" 'face 'font-lock-warning-face)
    "]unction / ["
    (propertize "v" 'face 'font-lock-warning-face)
    "]ariable | "
    (propertize "Find" 'face 'font-lock-keyword-face)
    " ["
    (propertize "F" 'face 'font-lock-warning-face)
    "]unction / ["
    (propertize "V" 'face 'font-lock-warning-face)
    "]ariable"))
  (let* (
      (select-f-or-v (read-char-exclusive))
      function
      variable)
    (cond
      ((eq select-f-or-v ?f)
        (setq function (read (read-string "Please enter a function name:  ")))
        (describe-function function)
        (select-window (get-buffer-window "*Help*")))
      ((eq select-f-or-v ?v)
        (setq variable (read (read-string "Please enter a variable name:  ")))
        (describe-variable variable)
        (select-window (get-buffer-window "*Help*")))
      ((eq select-f-or-v ?F)
        (setq function (read (read-string "Please enter a function name:  ")))
        (find-function-other-window function)
        (when buffer-file-name
          (message (propertize buffer-file-name 'face 'font-lock-warning-face))))
      ((eq select-f-or-v ?V)
        (setq variable (read (read-string "Please enter a variable name:  ")))
        (find-variable-other-window variable)
        (when buffer-file-name
          (message (propertize buffer-file-name 'face 'font-lock-warning-face))))
      (t
        (message "Thanks and come again!")))
    (when (and
        (equal (buffer-name) "*Help*")
        (save-excursion
          (goto-char (point-max))
          (re-search-backward "\\(`*[.]el'\\)" nil t)))
      (goto-char (point-max))
      (re-search-backward "\\(`*[.]el'\\)" nil t)
      (message 
        (propertize
          (car (cdr (car (nthcdr 1 (text-properties-at (point))))))
            'face 'font-lock-warning-face) )
      (goto-char (point-min))) ))
lawlist
  • 13,099
  • 3
  • 49
  • 158
0

If you use lispy minor mode:

  1. You can open the definition of current function by positioning the point on the open paren of that function and pressing F.
  2. You can open the definition of current variable by marking it and pressing F.
  3. You can find all definitions in current directory with g. You get a helm completion interface for all tags in all Elisp files. Each line will have the tag in the first column and the file in the second. My installation's base Elisp directory has 19838 tags, and the completion is fast enough.

  4. You can find all definitions in current directory and its sub-directories with lispy-goto-recursive. It takes minutes to parse and seconds to bring up the completion interface. But it allows to interactively search through all the files in the Emacs source - that's 89675 tags. A sample search: there are 55 top-level tags that contain insert-file spread around about 20 files. Most of them are functions, but the top-level tag (define-key ctl-x-map "i" 'insert-file) is also matched and can be viewed without opening the file.

abo-abo
  • 20,038
  • 3
  • 50
  • 71
0

You can grab the source of Emacs (if you installed Emacs you probably have .elc files - which are compiled elisp files), and search for the function, if you're on Unix like system you can use ack or find/grep all lisp files are in lisp directory

cd Emacs-24.4/lisp
ack 'defun some-function'
find . -name '*.el' | xargs grep 'defun some-function'
jcubic
  • 61,973
  • 54
  • 229
  • 402