Jak odzyskać dokumenty z funkcji i zmiennych?

11

Próbuję napisać funkcję, która pobierze ciągi znaków z dowolnej sexps w pasującym pliku (def.*).

Chciałbym móc zarówno pobierać dowolne funkcje / makra, jak i dowolne zdefiniowane zmienne. Dla zmiennych chciałbym docstring, podczas gdy dla dowolnych funkcji chciałbym również listy argumentów.

Jonathan Leech-Pepin
źródło
1
Aby wyjaśnić: czy masz plik źródłowy Elisp (moja interpretacja), czy masz kilka zmiennych i funkcji w obecnym środowisku Emacsa (interpretacja Constantine)? A jeśli pierwsza interpretacja, czy naprawdę chcesz wszystkich (def…)sexps, a nie tylko specyfikacji najwyższego poziomu? Lub pośrednia interpretacja funkcji i zmiennych, które byłyby zdefiniowane, gdyby plik został załadowany? Lub bardziej swobodna definicja obejmująca takie formularze najwyższego poziomu, jak (when nil (defun …)))?
Gilles „SO- przestań być zły”
Początkowo chciałem pierwszy, jednak w oparciu o interpretację Constantine'a udało mi się uzyskać funkcjonalną implementację, która zapewniła mi to, czego potrzebowałem. Celem jest konwersja źródła elisp na dokumentację (napisaną w Org) na podstawie Docstrings.
Jonathan Leech-Pepin
W drugiej interpretacji wbudowane funkcje describe-functioni przyjaciele wykonują całkiem niezłą część tego, co chcesz (lista dokumentów i argumentów).
T. Verron,

Odpowiedzi:

10

Jeśli celem jest uzyskanie informacji o funkcjach i zmiennych już znajdujących się w środowisku :

  • Dokumenty funkcji i makr znajdują się w documentationfunkcji.

  • W przypadku zmiennych dokumentów używaj documentation-property; na przykład:

    (documentation-property
     'user-init-file 'variable-documentation)
    
  • Arity funkcji i listę argumentów można znaleźć w tym pytaniu Emacs.SE , odpowiedzi i komentarzach do pytania.

(Znalazłem to, naciskając C-h k C-h fi przeglądając kod źródłowy describe-function(to samo dla zmiennych dokumentów, ale studiując describe-variable).)

Aby przeanalizować plik kodu źródłowego Emacsa Lispa, zakładając, że celem jest uzyskanie informacji o def.*formularzach najwyższego poziomu , można zrobić coś podobnego do następującego.

(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)))))

To może być łatwo rozszerzony defvar, defconstitp

Aby poradzić sobie z defunpojawianiem się wewnątrz formularzy najwyższego poziomu, należałoby zejść do tych formularzy, prawdopodobnie używając rekurencji.

Konstantyn
źródło
2
+1 za poinformowanie czytelników, jak samodzielnie znaleźć te informacje. To ważniejsza lekcja z dwóch, których nauczyłeś.
Drew
@Drew Wygląda na to, że znajdujemy się w dziwnej sytuacji: celem tej witryny jest uczynienie się przestarzałym… To by była ciekawa dyskusja na czacie :)
Sean Allred,
4
@SeanAllred Uczenie ludzi uczenia się nie zatrzymuje pytań, a jedynie czyni je lepszymi.
Malabarba
3
+1 do Malabarba. Celem tej witryny powinno (IMHO) być odpowiedź na to, czego sama Emacs nie może odpowiedzieć lub nie odpowiada dobrze lub łatwo . Analogia: w przypadku języka angielskiego i korzystania z witryny przyczyną zamykania pytań jest to, że „ pytania, na które można odpowiedzieć przy użyciu powszechnie dostępnych referencji, są nie na temat *”. (StackOverflow jest podobny.) Nie musimy być tak ekstremalni, mówiąc, że pytania, na które sam Emacs może odpowiedzieć, są nie na temat , ale ten sam pomysł powinien mieć zastosowanie: zachęć użytkowników, aby najpierw spróbowali znaleźć odpowiedź . W naszym przypadku oznacza to, pytając Emacsa .
Drew
@Drew Fair points :)
Sean Allred