notes from /dev/null

by Charles Choi 최민수


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:

  1. Run eval-defun (C-M-x) to evaluate the function the point is in.
  2. Move the point to the name of the function.
  3. Run M-x describe-function which will default populate with the function name because of where the point is currently.
  4. 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
(defun cc/describe-function-point-is-in ()
  "Describe enclosing Elisp function at point.
\nInvoke `describe-function' on the enclosing Elisp function the
point is in.

Thanks to mwnaylor, PropagandaOfTheDude, and deaddyfreddy for
helping write this function. "
  (interactive)
  (when-let ((interned (intern-soft (which-function))))
    (describe-function interned)))

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
(define-key emacs-lisp-mode-map (kbd "<f6>") #'cc/describe-function-point-is-in)

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:

  1. Mark paragraph as region.
  2. Run M-x repunctuate-sentences.
  3. 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:

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.

References

emacs

 

AboutMastodonInstagramGitHub

Feeds & TagsGet Captee for macOS

Powered by Pelican