Sphinx documentation style#
Note
Pigweed’s documentation style guide came after much of the documentation was written, so Pigweed doesn’t entirely conform to our own style guide. When updating docs, please update them to match the style guide.
Note
We are moving to the Google Developer Documentation Style Guide (GDDSG) for the English language conventions (rather than technical style for RST usage, etc). Currently, most of our documentation does not adhere.
Pigweed documentation is written using the reStructuredText markup language and processed by Sphinx. We use the Furo theme along with the sphinx-design extension.
Syntax Reference Links#
ReST is flexible, supporting formatting the same logical document in a few ways (for example headings, blank lines). Pigweed has the following restrictions to make our documentation consistent.
Headings#
Use headings according to the following hierarchy, with the shown characters for the ReST heading syntax.
==================================
Document Title: Two Bars of Equals
==================================
Document titles use equals ("====="), above and below. Capitalize the words
in the title, except for 'a', 'of', and 'the'.
---------------------------
Major Sections Within a Doc
---------------------------
Major sections use hyphens ("----"), above and below. Capitalize the words in
the title, except for 'a', 'of', and 'the'.
Heading 1 - For Sections Within a Doc
=====================================
These should be title cased. Use a single equals bar ("====").
Heading 2 - for subsections
---------------------------
Subsections use hyphens ("----"). In many cases, these headings may be
sentence-like. In those cases, only the first letter should be capitalized.
For example, FAQ subsections would have a title with "Why does the X do the
Y?"; note the sentence capitalization (but not title capitalization).
Heading 3 - for subsubsections
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Use the caret symbol ("^^^^") for subsubsections.
Note: Generally don't go beyond heading 3.
Heading 4 - for subsubsubsections
.................................
Don't use this heading level, but if you must, use period characters
("....") for the heading.
Do not put blank lines after headings.#
Yes: No blank after heading
Here is a heading
-----------------
Note that there is no blank line after the heading separator!
No: Unnecessary blank line
Here is a heading
-----------------
There is a totally unnecessary blank line above this one. Don't do this.
Do not put multiple blank lines before a heading.#
Yes: Just one blank after section content before the next heading
There is some text here in the section before the next. It's just here to
illustrate the spacing standard. Note that there is just one blank line
after this paragraph.
Just one blank!
---------------
There is just one blank line before the heading.
No: Extra blank lines
There is some text here in the section before the next. It's just here to
illustrate the spacing standard. Note that there are too many blank lines
after this paragraph; there should be just one.
Too many blanks
---------------
There are too many blanks before the heading for this section.
Directives#
Indent directives 3 spaces; and put a blank line between the directive and the content. This aligns the directive content with the directive name.
Yes: Three space indent for directives; and nested
Here is a paragraph that has some content. After this content is a
directive.
.. my_directive::
Note that this line's start aligns with the "m" above. The 3-space
alignment accounts for the ".. " prefix for directives, to vertically
align the directive name with the content.
This indentation must continue for nested directives.
.. nested_directive::
Here is some nested directive content.
No: One space, two spaces, four spaces, or other indents for directives
Here is a paragraph with some content.
.. my_directive::
The indentation here is incorrect! It's one space short; doesn't align
with the directive name above.
.. nested_directive::
This isn't indented correctly either; it's too much (4 spaces).
No: Missing blank between directive and content.
Here is a paragraph with some content.
.. my_directive::
Note the lack of blank line above here.
Tables#
Consider using .. list-table::
syntax, which is more maintainable and
easier to edit for complex tables (details).
Code Snippets#
Use code blocks from actual source code files wherever possible. This helps keep documentation fresh and removes duplicate code examples. There are a few ways to do this with Sphinx.
The literalinclude directive creates a code blocks from source files. Entire
files can be included or a just a subsection. The best way to do this is with
the :start-after:
and :end-before:
options.
Example:
Documentation Source (.rst
file)
.. literalinclude:: run_doxygen.py
:start-after: [doxygen-environment-variables]
:end-before: [doxygen-environment-variables]
Source File
# DOCSTAG: [doxygen-environment-variables]
env = os.environ.copy()
env['PW_DOXYGEN_OUTPUT_DIRECTORY'] = str(output_dir.resolve())
env['PW_DOXYGEN_INPUT'] = ' '.join(pw_module_list)
env['PW_DOXYGEN_PROJECT_NAME'] = 'Pigweed'
# DOCSTAG: [doxygen-environment-variables]
Rendered Output
env = os.environ.copy()
env['PW_DOXYGEN_OUTPUT_DIRECTORY'] = str(output_dir.resolve())
env['PW_DOXYGEN_INPUT'] = ' '.join(pw_module_list)
env['PW_DOXYGEN_PROJECT_NAME'] = 'Pigweed'
Generating API documentation from source#
Whenever possible, document APIs in the source code and use Sphinx to generate documentation for them. This keeps the documentation in sync with the code and reduces duplication.
Python#
Include Python API documentation from docstrings with autodoc directives. Example:
.. automodule:: pw_cli.log
:members:
.. automodule:: pw_console.embed
:members: PwConsoleEmbed
:undoc-members:
:show-inheritance:
.. autoclass:: pw_console.log_store.LogStore
:members: __init__
:undoc-members:
:show-inheritance:
Include argparse command line help with the argparse directive. Example:
.. argparse::
:module: pw_watch.watch
:func: get_parser
:prog: pw watch
:nodefaultconst:
:nodescription:
:noepilog:
Customize the depth of a page’s table of contents#
Put :tocdepth: X
on the first line of the page, where X
equals how many
levels of section heading you want to show in the page’s table of contents. See
//docs/changelog.rst
for an example.
Changelog#
This section explains how we update the changelog.
On the Friday before Pigweed Live, use changelog to generate a first draft of the changelog.
Copy-paste the reStructuredText output from the changelog tool to the top of
//docs/changelog.rst
.Delete these lines from the previous update in
changelog.rst
(which is no longer the latest update):.. _docs-changelog-latest:
.. changelog_highlights_start
.. changelog_highlights_end
Polish up the auto-generated first draft into something more readable:
Don’t change the section headings. The text in each section heading should map to one of the categories that we allow in our commit messages, such as
bazel
,docs
,pw_base64
, and so on.Add a 1-paragraph summary to each section.
Focus on features, important bug fixes, and breaking changes. Delete internal commits that Pigweed customers won’t care about.
Push your change up to Gerrit and kick off a dry run. After a few minutes the docs will get staged.
Copy the rendered content from the staging site into the Pigweed Live Google Doc.
Make sure to land the changelog updates the same week as Pigweed Live.
There is no need to update //docs/index.rst
. The What's new in Pigweed
content on the homepage is pulled from the changelog (that’s what the
docs-changelog-latest
, changelog_highlights_start
, and
changelog_highlights_end
labels are for).
Why “changelog” and not “release notes”?#
Because Pigweed doesn’t have releases.
Why organize by module / category?#
Why is the changelog organized by category / module? Why not the usual 3 top-level sections: features, fixes, breaking changes?
Because some Pigweed customers only use a few modules. Organizing by module helps them filter out all the changes that aren’t relevant to them faster.
If we keep the changelog section heading text fairly structured, we may be able to present the changelog in other interesting ways. For example, it should be possible to collect every
pw_base64
section in the changelog and then provide a changelog for onlypw_base64
over in thepw_base64
docs.The changelog tool is easily able to organize by module / category due to how we annotate our commits. We will not be able to publish changelog updates every 2 weeks if there is too much manual work involved.
Copy-to-clipboard feature on code blocks#
The copy-to-clipboard feature on code blocks is powered by sphinx-copybutton.
sphinx-copybutton
recognizes $
as an input prompt and automatically
removes it.
There is a workflow for manually removing the copy-to-clipboard button for a particular code block but it has not been implemented yet. See Remove copybuttons using a CSS selector.