Writing Better Elisp Docstrings
18 Apr 2024 Charles Choi
Emacs has a lot of tools to help you write better documentation strings (docstrings). And if a tool you want doesn’t exist, Emacs can let you make your own. As of late I’ve been writing a lot of Elisp docstrings, so this post covers what's still fresh in my mind. While Elisp-centric, much of this post can apply to other languages as well (I see you Python and Swift).
Previewing Docstrings
A common task in writing an Elisp docstring is to preview it in Emacs Help. When you are still composing the docstring, this process is cumbersome as the point (cursor) is still in the docstring section. To preview the docstring in Emacs Help, one must:
- Run
eval-defun
(C-M-x
) to evaluate the function the point is in. - Move the point to the name of the function.
- Run
M-x describe-function
which will default populate with the function name because of where the point is currently. - Move the point back to previous position (optional).
Repeating all these steps gets old fast. A more ideal workflow is to have an Elisp function that automates the above steps. This function can then be assigned a keybinding for convenient access.
The function cc/describe-function-point-is-in
below does just that. For separation of concerns, evaluating the function (eval-defun
) is kept separate from the steps that show the docstring (steps 2-4).
1 2 3 4 5 6 7 8 9 10 |
|
Amendment 2024-04-19: On Reddit, PropagandaOfTheDude remarked that which-function
can get the name of the enclosing function, simplifying my prior implementation. I've amended cc/describe-function-point-is-in
to use it.
Amendment 2024-04-21: On Reddit, deaddyfreddy shares that when-let
offers an even cleaner implementation of cc/describe-function-point-is-in
which has been amended to reflect this.
I leave it to the reader to assign their preferred keybinding to cc/describe-function-point-is-in
. For yours truly, I’ve bound it to <f6>
in emacs-lisp-mode-map
.
1 |
|
Filling Paragraphs and Sentence Spacing
Writing descriptive docstrings typically entails writing paragraphs. The function fill-paragraph
will ensure that the paragraph you write is formatted with respect to the column length (fill-column
). For single-spaced sentences, fill-paragraph
works swimmingly. More problematic is when the desire is to enforce double-spaced sentences. If the variable sentence-end-double-space
is non-nil, fill-paragraph
will not adjust single-spaced sentences to double-spaced ones. To enforce double-spaced sentences, a different command is needed: repunctuate-sentences
. This command honors sentence-end-double-space
, so if you want single-spaced sentences, it will do the right thing.
In a docstring the workflow for refilling a paragraph while ensuring double-spaced sentences is:
- Mark paragraph as region.
- Run
M-x repunctuate-sentences
. - Run
M-x fill-paragraph
.
Note that the design of repunctuate-sentences
presumes that the buffer is all prose text if no mark is active. As docstrings are in code, this necessitates the step (1) to mark a region/paragraph. It’s left as an exercise to a more sophisticated Elisp developer to write a function that combines the above steps that is robust enough to know when it is in a docstring.
Documentation Tips
In the GNU Elisp Reference there is a section on documentation tips. I highly recommend a deep reading of it. Among the guidance it provides is linking to different document types such as commands/functions, variables, Info docs, man pages, and URLs.
Writing Tools
Emacs is rich with tools for writing. Among them to consider:
- CheckDoc for style checking your Elisp docstring. Amendment 2024-04-21 - One can use flycheck mode which will automatically turn on
checkdoc
, among other things (per input from deaddyfreddy). - Dynamic Abbreviation / Hippie Expand to auto-complete text that is used more than once.
- Templates to deal with boilerplate docstrings (YASnippet is my personal favorite).
- Automatic spell checking (
flyspell-prog-mode
). - Dictionary lookup.
Closing Thoughts
Count me as one who finds great value to a well-written docstring. It is an opportunity to communicate intent from the writer/developer to the reader/user, and frequently for the developer it goes hand-in-hand with writing better code. Emacs provides a robust set of tools to help you write good docstrings with the added capability to make your own if what you need is lacking.