10

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.

  • 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 Nov 17 '14 at 6: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
9

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.

  • 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 2: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 4:57
  • 4
    @SeanAllred Teaching people to learn doesn't stop the questions, it only makes them better. – Malabarba Nov 17 '14 at 9: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 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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.