Quickstart by example

This page gets you started quickly with sphinxcontrib-emacs, by an simple example. It assumes

  • that you are already familiar with Sphinx,
  • and have Sphinx and sphinxcontrib-emacs installed.

Thus, this page will only go through the specific setup and features of sphinxcontrib-emacs. Consult the Sphinx documentation for information about Sphinx.

Warning

If you are not familiar with Sphinx, please go through the Sphinx tutorial first.

The project layout

We want to document a simple hello.el library, which implements the good old Hello world program.

Our project has the following layout:

README.md
hello.el

hello.el is very simple, with just one command, and a user option:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
(defcustom greeting "Hello %s!"
  "The greeting to use in `greet'.

The value of this variable should contain is used as string for
`format', with the only argument being the name of the user to
greet."
  :safe #'stringp
  :package-version '(hello . "0.1"))

(make-variable-buffer-local 'greeting)

(defun greet (name)
  "Greet the user with the given NAME, in classic Hello world style.

When called interactively, prompt for NAME.

Use the message template from `greeting' to assemble the greeting
mesage.

See URL `http://en.wikipedia.org/wiki/Hello_world_program'."
  (interactive "sYour name: ")
  (message greeting name))

(global-set-key (kbd "C-c g") #'greet)

Setup

We create a subdirectory doc/ for our documentation, and go through the sphinx-quickstart tool, which gives us a skeleton for our documentation:

doc/conf.py
doc/index.rst
doc/Makefile
doc/make.bat

doc/conf.py is the build configuration. Here we enable sphinxcontrib-emacs by adding it to the extensions setting:

# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = ['sphinxcontrib.emacs']

Documenting commands

We start with documenting the interactive command, the most important feature of our hello library.

We create a separate document doc/hello.rst for the documentation of the hello library, and add it to the TOC tree in doc/index.rst:

.. toctree::
   :maxdepth: 2

   hello

In doc/hello.rst we can now document the hello command:

===================
 The hello library
===================

Greet users.

.. el:command:: greet
   :binding: C-c g

   Prompt for the name of a user and greet them.

   Use :el:option:`greeting` to change the greeting text.

:el:option:`greeting` inserts a cross-reference to the documentation of the greeting option, which we add further down.

In hello.el, we install global key binding C-c g for our command, so we document this additional binding in the :binding: option. This binding now appears in the documentation of the greet command:

C-c g
M-x greet

Prompt for the name of a user and greet them.

Use greeting to change the greeting text.

Documenting different invocations of commands

In Emacs Lisp, any command is a function as well, which can be called from Emacs Lisp. To account for this, we also want to document the function “aspect” of greet:

.. el:function:: greet name
   :noindex:

   Greet the user with the given ``name``.

   ``name`` is a string identifying the user to greet.
Function greet name

Greet the user with the given name.

name is a string identifying the user to greet.

We use the :noindex: option to suppress the index entry and cross-reference target, since we have already documented the greet symbol as command.

In the documentation index, and in cross-references, greet will always refer to the interactive command, documented above.

Auto-documenting functions

When documenting greet as a function, we wrote an explicit documentation. However, we already have documentation, in the docstring of greet:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
(defun greet (name)
  "Greet the user with the given NAME, in classic Hello world style.

When called interactively, prompt for NAME.

Use the message template from `greeting' to assemble the greeting
mesage.

See URL `http://en.wikipedia.org/wiki/Hello_world_program'."
  (interactive "sYour name: ")
  (message greeting name))

To avoid this duplication, we change our documentation to extract the docstring of the greet function.

First, we need to point sphinxcontrib-emacs to the Emacs Lisp source file, by changing appending the following to doc/conf.py:

emacs_lisp_load_path = [
    os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
]

This tells sphinxcontrib-emacs, that Emacs Lisp source files are to be found in the parent directory of the documentation (remember our project layout). By using os.path.join() and os.pardir, we ensure that our documentation builds regardless of where we checked out our project.

Then we load the hello library to make its docstrings available, by adding the following to the top of doc/hello.rst:

Now we use the docstring of greet as documentation of the greet function:

.. el:require:: hello

.. el:function:: greet
   :noindex:
   :auto:
Function greet name
Greet the user with the given NAME, in classic Hello world style.

When called interactively, prompt for NAME.

Use the message template from `greeting' to assemble the greeting
mesage.

See URL `http://en.wikipedia.org/wiki/Hello_world_program'.

We remove our manually written documentation, and instead add the :auto: option to have docstring of greet inserted as documentation. Note that we also removed the argument name, since :auto: will also extract the function signature.

In docstrings, only the markup of Help Mode is parsed (see Documentation Tips(elisp)). reST is not supported.

Note

The peculiar layout and presentation of extracted docstrings is to maintain compatibility with the limited markup and presentation of docstrings in Emacs’ Help Mode.

Auto-documenting options

Now we can also automatically document the greeting option:

.. el:option:: greeting
   :auto:

Using :auto: for variables will automatically add the variables properties as well. Remember the definition of greeting:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
(defcustom greeting "Hello %s!"
  "The greeting to use in `greet'.

The value of this variable should contain is used as string for
`format', with the only argument being the name of the user to
greet."
  :safe #'stringp
  :package-version '(hello . "0.1"))

(make-variable-buffer-local 'greeting)

The variable is marked as safe for string values, and as buffer-local. These properties are reflected in the documentation. The package version is recorded as well:

User Option greeting

Variable properties

Automatically becomes buffer-local when set. This variable is safe as a file local variable if its value satisfies the predicate stringp.

The greeting to use in `greet'.

The value of this variable should contain is used as string for
`format', with the only argument being the name of the user to
greet.

This user option was introduced, or its default value was changed, in version 0.1 of the hello package.

Further reading