YARD Documentation with Emacs
In Emacs, the
fill-paragraph command
lets you reformat a chunk of text to break lines at a certain
width. Bound to M-q by default, it is a handy way to enforce
consistent line widths inside text documents.
Recently, I've been editing a lot of inline documentation in Ruby code using YARD. A typical doc comment looks like this:
# Reverses the contents of a String or IO object. 
# 
# @param [String, #read] contents the contents to reverse 
# @return [String] the contents reversed lexically 
def reverse(contents) 
  # ...
end
As descriptions got longer, I found myself wishing to reformat
paragraphs. While Emacs knows how to fill paragraphs inside Ruby
comments, hitting M-q still turned text into unreadable gibberish:
# Reverses the contents of a String or IO object.  @param [String,
# #read] contents the contents to reverse @return [String] the
# contents reversed lexically
Turns out there is an easy way to tell Emacs how to recognize
paragraphs: paragraph-separate and paragraph-start.  Let's define
a function that sets these variables to YARD specific values. The
concatenate call is only there to improve readability.
(defun yard-paragraph-boundaries ()
  (interactive)
  ; Paragraphs are separated by lines containing only a # character
  (setq paragraph-separate "[ \t]*#[ \t]*$")
  ; Paragraphs start with YARD tags or list items
  (setq paragraph-start
      (concatenate
       'string
       "^[ \t]*"         ; some whitespace
       "#[ \t]*"         ; a # character followed by whitespace
       "\\("
         "@[[:alpha:]]+" ; a YARD tag
       "\\|"             ; or
         "-"             ; a list item
       "\\)"
       "\\([ \t]+.*\\)?" ; an optional text
       "[ \t]*$")))      ; some more whitespace
Finally, we can call the function whenever ruby-mode is entered:
(add-hook 'ruby-mode-hook
      '(lambda ()
        (yard-paragraph-boundaries)))
Now text inside YARD comments can be reformatted with a single key stroke. Emacs even preserves custom indentation levels:
# @param [String] A really long description text which spans
#   multiple lines and has a custom indentation, which is
#   preserved even when the paragraph is reformatted.