HTTPS SSH

NAME

bashdoc - extract and format documentation embedded in bash scripts

SYNOPSIS

bashdoc [-h|-v] format SCRIPT

DESCRIPTION

bashdoc[1] extracts documentation from a bash script and formats it nicely. The documentation in SCRIPT must be written in markdown[2]. It will be formatted for output using pandoc[3].

For bashdoc to be able to format a script's documentation, a simple but rigid convention must be followed. Namely, documentation must be contained in a 'here document' that begins with either:

 : <<'DOC'

or

 : <<DOC

and ends with:

 DOC

In all cases, the text must be exactly as shown and it must start in column 1. If multiple such here documents are encountered in a script, they are concatenated into a single documentation string before processing.

Contents of the documentation string must be created with pandoc's flavor of markdown with the extension for definition lists enabled.

Arguments

Required Arguments

The first argument to bashdoc is the output format, which must be one of the following:

man
Extract the raw documentation from SCRIPT and convert it to a man page, per gettroff, and view the resulting with man(1). Note that most user environments are typically setup so that man(1) displays the documentation with a pager, such as less.

manps
Extract the raw documentation from SCRIPT and process it with pandoc and man(1) to create a postscript version of the man page generated by man. When used in this manner, man(1) adds headers, footers, and page numbers; the result is well suited for printing.

gettroff
Extract the raw documentation from SCRIPT and process it with pandoc, converting it to troff code with man macros. The troff code is then written to stdout. The output is suitable for use with the man(1) command.

pdf
Extract the raw documentation from SCRIPT and process it with pandoc to create a pdf document formatted for printing. The pdf document is written to stdout. This differs from the output of manps in that it is formatted with a common LaTeX document style.

tty
Extract the raw documentation from SCRIPT and process it with pandoc, converting it to troff code with man macros. The troff code is then run through groff. This nicely formatted output is written to stdout. The output should resemble that of the previously described man format, the difference being that a pager is not used. This output is suitable for a, possibly verbose, usage text for a script. The '-h' option to bashdoc uses this for its output.

md
Extract the raw markdown documentation from SCRIPT and write it in its raw unprocessed form to stdout.

mds
Extract the raw documentation from SCRIPT, process it with pandoc, then write a version of the documentation in a 'safe' flavor of markdown to stdout. Why would this be useful? Many online code repositories, e.g. Bitbucket, can automatically format and display files containing markdown. However, the markdown they support is rudimentary at best, meaning that a document containing pandoc markdown may not be rendered properly. This option attempts to transform the docstring into a 'safe' flavor of markdown that it can be successfully rendered. Some useful formatting may be lost in the process, but this is better than viewing impenetrable blocks of gibberish on such sites.

The second argument, SCRIPT is a path to the bash script from which the documentation will be extracted.

Options

-h
Write help information to stdout. This actually invokes bashdoc on itself, requesting tty format output.

-v
Write the version string to stdout. Semantic versioning is used.

Meta-information

The first three lines of the documentation string may contain meta information to be used by pandoc when creating output. Those lines are in the format:

% BASHDOC(1)
% Kenneth East <http://east.fm>
% December 13, 2015

Their purpose is self-evident. It is guaranteed not to render properly with anything other than pandoc. See the pandoc documentation[4] on meta-information for details.

Bash parameter expansion

In here documents that begin with

 : <<'DOC'

any shell variables within the here document are left as-is, i.e., they are not expanded.

To enable parameter substitution for shell variables, begin the docstring with

 : <<DOC

Note the absence of single quotes around DOC. In this case, bash parameter substitution is performed on the body of the here doc.

In the latter case, note that if the docstring contains $(foo) or `foo`, it will be expanded by the shell, which will replace it with the output of the foo command. See the bash(1) man page for more information.

USAGE

Command Line

To see an example of what a documentation string looks like, simply run the command:

$ bashdoc md `type -p bashdoc`

The above command will extract the documentation string from the file which implements the bashdoc command (i.e., the file containing the documentation string which generated this document) and write it to stdout.

To convert the same documentation string to a man page and then view it with man(8):

$ bashdoc man `type -p bashdoc`

To create a printable pdf version of the documentation for the bash script ~/bin/foo and then view it in OS-X preview:

$ bashdoc pdf ~/bin/foo
$ open foo.pdf

As a Documentation Provider Within Other Scripts

bashdoc can also be used as a documentation provider within other scripts. For example, if the script 'foo' is documented in the manner just described, bashdoc can be called within 'foo' to produce 'foo's documentation. E.g.:

# Code snippet from within the 'foo' script.
# OPT is a command line option to 'foo'

case "$OPT" in
    -h|--help) 
        # formatted documentation for 'foo' on stdout
        bashdoc tty "$0"
        ;;
    --man)
        # display formatted documentation for 'foo' with man(1)
        bashdoc man "$0"
        ;;
    --md)
        # raw documentation string for 'foo' on stdout
        bashdoc md "$0"
        ;;
esac

Opting Out

If you have a script with documentation formatted for use with bashdoc but you do not wish to use bashdoc, you can get the raw documentation on stdout with a one-liner:

    $ S=.../path/to/script/to/get/doc/from/foo.sh
    $ sed '/^:/,/^DOC/!d;s/^:/cat/' "$S" | sh -s

This one line is actually the key to the entire bashdoc scheme. Thanks to mikeserv for the excellent idea.

EXIT STATUS

bashdoc exits with a status of 0 when successful and non-zero otherwise.

INSTALLATION

Put the file bashdoc somewhere in your path and make it executable.

pandoc must be present on your system. groff is required for man, gettroff, and tty. LaTeX is required for pdf.

BUGS

No line in the docstring can begin with DOC in the first column, as this will terminate the here document prematurely. If you wish to embed a DOC in your docstring, one workaround is to precede the embedded DOC with a space in column 1. For an example of this workaround, inspect the docstring used to create this document.

It can be difficult to create markdown that renders satisfactorily in both pdf and in man formats.

More specifically, markdown code intended to render verbatim text / code fragments (e.g., `x = 33`) is rendered correctly by pandoc in pdf, as unadorned plain text in pandoc man pages, and surrounded by a shaded box on Bitbucket. This is most unsatisfying. Trying to get satisfactory rendering in pandoc's pdf, pandoc's man page, and Bitbucket's/Github's markdown from a single document can be extremely frustrating, if not impossible. If something isn't clear in a man rendering, it will likely be clarified with a pdf rendering, which should be more accurate.

Single quotes within the documentation string can confuse syntax highlighing in editors and code formatters.

Argument error handling is de-minimis.

NOTES

N.B. This documentation was created with bashdoc.

The idea for this approach to embedding documentation in a shell script was taken from mikeserv's answer in: http://unix.stackexchange.com/questions/185657.

This has only been tested on OS-X 10.11.2.

It is a simple matter to add additional pandoc markdown features by extending the value of the '-f' option in this script's implementation. It would be nice to allow additional extensions to be enabled from within the script being documented.

Should test for the presence of pandoc, groff, and LaTeX and act accordingly.

Would be nice to allow for two classes of documentation strings: summary and detailed. This would allow a brief usage type output for -h along with a full version which would produce complete documentation.

docopt uses semantic versioning.

This documentation is amusingly lengthy given the brevity of the associated code.

SEE ALSO

pandoc, bash(1), groff(1), man(1)

'socco.sh' is a more advanced documentation tool that prints comments and code side-by-side, literate programming style. See http://rtomayko.github.io/shocco/.

Source code for bashdoc is available at https://bitbucket.org/MaDeuce/bashdoc.

[1] This is bashdoc v2.0.0.

[2] http://daringfireball.net/projects/markdown/syntax
http://pandoc.org/README.html#pandocs-markdown

[3] http://pandoc.org/README.html

[4] http://pandoc.org/README.html#metadata-blocks