Álvaro Ramírez
Generating elisp org docs
chatgpt-shell's README includes few org tables documenting the package's customizable variables as well as available commands. Don't worry, this isn't really another ChatGPT post.
Here's an extract of the docs table:
| Custom variable | Description | |---------------------------------------+-------------------------------------------------------------| | chatgpt-shell-display-function | Function to display the shell. | | chatgpt-shell-curl-additional-options | Additional options for `curl' command. | | chatgpt-shell-system-prompt | The system message helps set the behavior of the assistant. |
While the table docs didn't take long to build manually, they quickly became out of sync with their elisp counterparts. Not ideal, as it'll require a little more careful maintenance in the future.
Emacs being the self-documenting editor that it is, I figured I should be able to extract customizable variables, commands, along with their respective docs, and generate these very same org tables.
I had no idea how to go about this, but apropos-variable and apropos-command surely knew where to fetch the details from. A peak into apropos.el
quickly got me on my way. Turns out mapatoms is just what I needed. It iterates over obarray, Emacs's symbol table. We can use it to extract the symbols we're after.
Since we're filtering symbols from chatgpt-shell
, we can start by including only those whose symbol-name
match "^chatgpt-shell". Out of all matching, we should only keep custom variables. We can use custom-variable-p
to check for that. This gives us all relevant variables. We can subsequently get each variable's corresponding docs using (get symbol 'variable-documentation)
and put it into a list.
Now, if we pull our org babel rabbit out of our Emacs magic hat, we can use :results table
to print the list as an org table. The source block powering this magic trick looks as follows:
#+begin_src emacs-lisp :results table :colnames '("Custom variable" "Description") (let ((rows)) (mapatoms (lambda (symbol) (when (and (string-match "^chatgpt-shell" (symbol-name symbol)) (custom-variable-p symbol)) (push `(,symbol ,(car (split-string (or (get (indirect-variable symbol) 'variable-documentation) (get symbol 'variable-documentation) "") "\n"))) rows)))) rows) #+end_src
And just like that… we effortlessly get our elisp docs in an org table, straight from Emacs's symbol table.
It's worth noting that our snippet used indirect-variable
to resolve aliases but also limited descriptions to the first line in each docstring.
To build a similar table for interactive commands, we can use the following block (also including bindings).
#+BEGIN_SRC emacs-lisp :results table :colnames '("Binding" "Command" "Description") (let ((rows)) (mapatoms (lambda (symbol) (when (and (string-match "^chatgpt-shell" (symbol-name symbol)) (commandp symbol)) (push `(,(mapconcat #'help--key-description-fontified (where-is-internal symbol shell-maker-mode-map nil nil (command-remapping symbol)) ", ") ,symbol ,(car (split-string (or (documentation symbol t) "") "\n"))) rows)))) rows) #+END_SRC
You see? This post wasn't really about ChatGPT. Aren't you glad you stuck around? 😀