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? 😀