14

I'm trying to write a function that will retrieve the docstrings from any sexps in a file that match (def.*).

I'd want to both be able to retrieve any functions/macros, as well as any variables that are defined. For variables I would want the docstring, while for any functions I would also want the argument lists.

Drew
  • 75,699
  • 9
  • 109
  • 225
Jonathan Leech-Pepin
  • 4,307
  • 1
  • 19
  • 32
  • 1
    To clarify: do you have an Elisp source file (my interpretation), or do you have a bunch of variables and functions in the current Emacs environment (Constantine's interpretation)? And if the first interpretation, do you really want all `(def…)` sexps, not just top-level specs? Or the intermediate interpretation of the functions and variables that would be defined if the file is loaded? Or a more relaxed definition that includes such top-level forms as `(when nil (defun …))`)? – Gilles 'SO- stop being evil' Nov 17 '14 at 06:22
  • I had initially wanted the first, however based on Constantine's interpretation I was able to get a functional implementation that got me what I needed. Goal is to convert elisp source into documentation (written in Org) based on Docstrings. – Jonathan Leech-Pepin Nov 17 '14 at 14:51
  • With the second interpretation, the built-in `describe-function` and friends do quite a good part of what you want (docstring and arguments list). – T. Verron Nov 17 '14 at 15:05

1 Answers1

14

If the goal is to get information about functions and variables already in the environment:

  • For docstrings of functions and macros, see the documentation function.

  • For variable docstrings, use documentation-property; for example:

    (documentation-property
     'user-init-file 'variable-documentation)
    
  • For function arity and the argument list, see this Emacs.SE question, the answer, and comments to the question.

(I found this by pressing C-h k C-h f and skimming the source code of describe-function (same for variable docstrings, but studying describe-variable).)

To analyze an Emacs Lisp source code file, assuming that the goal is to get information about top-level def.* forms, one can do something similar to the following.

(defun get-defun-info (buffer)
  "Get information about all `defun' top-level sexps in a buffer
BUFFER. Returns a list with elements of the form (symbol args docstring)."
  (with-current-buffer buffer
    (save-excursion
      (save-restriction
        (widen)
        (goto-char (point-min))
        (let (result)
          ;; keep going while reading succeeds
          (while (condition-case nil
                     (progn
                       (read (current-buffer))
                       (forward-sexp -1)
                       t)
                   (error nil))
            (let ((form (read (current-buffer))))
              (cond
               ((not (listp form))      ; if it's not a list, skip it
                nil)
               ((eq (nth 0 form) 'defun) ; if it's a defun, collect info
                (let ((sym (nth 1 form))
                      (args (nth 2 form))
                      (doc (when (stringp (nth 3 form)) (nth 3 form))))
                  (push (list sym args doc) result))))))
          result)))))

This can be easily extended to defvar, defconst, etc.

To handle defun appearing inside top-level forms one would have to descend into these forms, possibly using recursion.

Constantine
  • 9,072
  • 1
  • 34
  • 49
  • 2
    +1 for telling readers how to find this info themselves. That's the more important lesson of the two that you taught. – Drew Nov 17 '14 at 02:23
  • @Drew It appears we are in a strange situation: the goal of this site is to make itself obsolete… This would make an interesting discussion in chat :) – Sean Allred Nov 17 '14 at 04:57
  • 4
    @SeanAllred Teaching people to learn doesn't stop the questions, it only makes them better. – Malabarba Nov 17 '14 at 09:20
  • 3
    +1 to Malabarba. The purpose of this site should (IMHO) be to **answer what Emacs itself cannot** answer or does not answer *well* or *easily*. Analogy: For site [English Language & Usage](http://english.stackexchange.com/) a reason for closing questions is that "*Questions that can be answered using* ***commonly available references*** are off-topic*". (StackOverflow is similar.) We need not be as extreme, saying that questions that Emacs itself can answer are *off-topic*, but the same idea should apply: get users to *try to find the answer first*. In our case, that means by **asking Emacs**. – Drew Nov 17 '14 at 17:49
  • @Drew Fair points :) – Sean Allred Nov 17 '14 at 18:17