Documenting Code¶
The purpose of this description is to provide quick summary on documentation style used in espressif/esp-idf repository and how to add new documentation.
Introduction¶
When documenting code for this repository, please follow Doxygen style. You are doing it by inserting special commands, for instance @param
, into standard comments blocks, for example:
/**
* @param ratio this is oxygen to air ratio
*/
Doxygen is phrasing the code, extracting the commands together with subsequent text, and building documentation out of it.
Typical comment block, that contains documentation of a function, looks like below.
Doxygen supports couple of formatting styles. It also gives you great flexibility on level of details to include in documentation. To get familiar with available features, please check data rich and very well organized Doxygen Manual.
Why we need it?¶
The ultimate goal is to ensure that all the code is consistently documented, so we can use tools like Sphinx and Breathe to aid preparation and automatic updates of API documentation when the code changes.
With these tools the above piece of code renders like below:
Go for it!¶
When writing code for this repository, please follow guidelines below.
Document all building blocks of code: functions, structs, typedefs, enums, macros, etc. Provide enough information on purpose, functionality and limitations of documented items, as you would like to see them documented when reading the code by others.
Documentation of function should describe what this function does. If it accepts input parameters and returns some value, all of them should be explained.
Do not add a data type before parameter or any other characters besides spaces. All spaces and line breaks are compressed into a single space. If you like to break a line, then break it twice.
If function has void input or does not return any value, then skip
@param
or@return
When documenting a
define
as well as members of astruct
orenum
, place specific comment like below after each member.To provide well formatted lists, break the line after command (like
@return
in example below).* * @return * - ESP_OK if erase operation was successful * - ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL * - ESP_ERR_NVS_READ_ONLY if handle was opened as read only * - ESP_ERR_NVS_NOT_FOUND if the requested key doesn't exist * - other error codes from the underlying storage driver *
Overview of functionality of documented header file, or group of files that make a library, should be placed in the same directory in a separate
README.rst
file. If directory contains header files for different APIs, then the file name should beapiname-readme.rst
.
Go one extra mile¶
There is couple of tips, how you can make your documentation even better and more useful to the reader.
Add code snippets to illustrate implementation. To do so, enclose snippet using
@code{c}
and@endcode
commands.* * @code{c} * // Example of using nvs_get_i32: * int32_t max_buffer_size = 4096; // default value * esp_err_t err = nvs_get_i32(my_handle, "max_buffer_size", &max_buffer_size); * assert(err == ESP_OK || err == ESP_ERR_NVS_NOT_FOUND); * // if ESP_ERR_NVS_NOT_FOUND was returned, max_buffer_size will still * // have its default value. * @endcode *
The code snippet should be enclosed in a comment block of the function that it illustrates.
To highlight some important information use command
@attention
or@note
.* * @attention * 1. This API only impact WIFI_MODE_STA or WIFI_MODE_APSTA mode * 2. If the ESP32 is connected to an AP, call esp_wifi_disconnect to disconnect. *
Above example also shows how to use a numbered list.
To provide common description to a group of similar functions, enclose them using
/**@{*/
and/**@}*/
markup commands:/**@{*/ /** * @brief common description of similar functions * */ void first_similar_function (void); void second_similar_function (void); /**@}*/
For practical example see nvs_flash/include/nvs.h.
You may want to go even further and skip some code like e.g. repetitive defines or enumerations. In such case enclose the code within
/** @cond */
and/** @endcond */
commands. Example of such implementation is provided in driver/include/driver/gpio.h.Use markdown to make your documentation even more readable. You will add headers, links, tables and more.
* * [ESP32 Technical Reference Manual](https://espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf) *
Note
Code snippets, notes, links, etc. will not make it to the documentation, if not enclosed in a comment block associated with one of documented objects.
- Prepare one or more complete code examples together with description. Place description in a separate file
README.md
in specific folder of examples directory.
Linking Examples¶
When linking to examples on GitHub do not use absolute / hardcoded URLs. Instead, use docutils custom roles that will generate links for you. These auto-generated links point to the tree or blob for the git commit ID (or tag) of the repository. This is needed to ensure that links do not get broken when files in master branch are moved around or deleted.
The following roles are provided:
:idf:`path`
- points to directory inside ESP-IDF:idf_file:`path`
- points to file inside ESP-IDF:idf_raw:`path`
- points to raw view of the file inside ESP-IDF:component:`path`
- points to directory inside ESP-IDF components dir:component_file:`path`
- points to file inside ESP-IDF components dir:component_raw:`path`
- points to raw view of the file inside ESP-IDF components dir:example:`path`
- points to directory inside ESP-IDF examples dir:example_file:`path`
- points to file inside ESP-IDF examples dir:example_raw:`path`
- points to raw view of the file inside ESP-IDF examples dir
Example implementation:
* :example:`get-started/hello_world`
* :example:`Hello World! <get-started/hello_world>`
How it renders:
A check is added to the CI build script, which searches RST files for presence of hard-coded links (identified by tree/master, blob/master, or raw/master part of the URL). This check can be run manually: cd docs
and then make gh-linkcheck
.
Linking Language Versions¶
Switching between documentation in different languages may be done using :link_to_translation:
custom role. The role placed on a page of documentation provides a link to the same page in a language specified as a parameter. Examples below show how to enter links to Chinese and English versions of documentation:
:link_to_translation:`zh_CN:中文版`
:link_to_translation:`en:English`
The language is specified using standard abbreviations like en
or zh_CN
. The text after last semicolon is not standardized and may be entered depending on the context where the link is placed, e.g.:
:link_to_translation:`en:see description in English`
Add Illustrations¶
Consider adding diagrams and pictures to illustrate described concepts.
Sometimes it is better to add an illustration than writing a lengthy paragraph to describe a complex idea, a data structure or an algorithm. This repository is using blockdiag suite of tools to generate diagram images from simple text files.
The following types of diagrams are supported:
With this suite of tools it is possible to generate beautiful diagram images from simple text format (similar to graphviz’s DOT format). The diagram elements are laid out automatically. The diagram code is then converted into “.png” graphics and integrated “behind the scenes” into Sphinx documents.
For the diagram preparation you can use an on-line interactive shell that instantly shows the rendered image.
Below are couple of diagram examples:
- Simple block diagram /
blockdiag
- Wi-Fi Buffer Configuration - Slightly more complicated block diagram - Wi-Fi programming model
- Sequence diagram /
seqdiag
- Scan for a Specific AP in All Channels - Packet diagram /
packetdiag
- NVS Page Structure
Try them out by modifying the source code and see the diagram instantly rendering below.
Note
There may be slight differences in rendering of font used by the interactive shell compared to the font used in the esp-idf documentation.
Add Notes¶
Working on a document, you might need to:
- Place some suggestions on what should be added or modified in future.
- Leave a reminder for yourself or somebody else to follow up.
In this case, add a todo note to your reST file using the directive .. todo::
. For example:
.. todo::
Add a package diagram.
If you add .. todolist::
to a reST file, the directive will be replaced by a list of all todo notes from the whole documentation.
By default, the directives .. todo::
and .. todolist::
are ignored by documentation builders. If you want the notes and the list of notes to be visible in your locally built documentation, do the following:
- Open your local
conf_common.py
file. - Find the parameter
todo_include_todos
. - Change its value from
False
toTrue
.
Before pushing your changes to origin, please set the value of todo_include_todos
back to False
.
For more details about the extension, see sphinx.ext.todo documenation.
Put it all together¶
Once documentation is ready, follow instruction in API Documentation Template and create a single file, that will merge all individual pieces of prepared documentation. Finally add a link to this file to respective .. toctree::
in index.rst
file located in /docs
folder or subfolders.
OK, but I am new to Sphinx!¶
No worries. All the software you need is well documented. It is also open source and free. Start by checking Sphinx documentation. If you are not clear how to write using rst markup language, see reStructuredText Primer. You can also use markdown (.md) files, and find out about more about the specific markdown syntax that we use on`Recommonmark parser’s documentation page <https://recommonmark.readthedocs.io/en/latest/>`_.
Check the source files of this documentation to understand what is behind of what you see now on the screen. Sources are maintained on GitHub in espressif/esp-idf repository in docs folder. You can go directly to the source file of this page by scrolling up and clicking the link in the top right corner. When on GitHub, see what’s really inside, open source files by clicking
Raw
button.You will likely want to see how documentation builds and looks like before posting it on the GitHub. There are two options to do so:
- Install Sphinx, Breathe, Blockdiag and Doxygen to build it locally, see chapter below.
- Set up an account on Read the Docs and build documentation in the cloud. Read the Docs provides document building and hosting for free and their service works really quick and great.
To preview documentation before building, use Sublime Text editor together with OmniMarkupPreviewer plugin.
Setup for building documentation locally¶
You can setup environment to build documentation locally on your PC by installing:
- Doxygen - https://www.stack.nl/~dimitri/doxygen/
- Sphinx - https://github.com/sphinx-doc/sphinx/#readme-for-sphinx
- Breathe - https://github.com/michaeljones/breathe#breathe
- Document theme “sphinx_rtd_theme” - https://github.com/rtfd/sphinx_rtd_theme
- Custom 404 page “sphinx-notfound-page” - https://github.com/rtfd/sphinx-notfound-page
- Blockdiag - http://blockdiag.com/en/index.html
- Recommonmark - https://github.com/rtfd/recommonmark
The package “sphinx_rtd_theme” is added to have the same “look and feel” of ESP32 Programming Guide documentation like on the “Read the Docs” hosting site.
Do not worry about being confronted with several packages to install. Besides Doxygen, all remaining packages are written in Python. Therefore installation of all of them is combined into one simple step.
Installation of Doxygen is OS dependent:
Linux
sudo apt-get install doxygen
Windows - install in MSYS2 console
pacman -S doxygen
MacOS
brew install doxygen
Note
If you are installing on Windows system (Linux and MacOS users should skip this note), before going further, execute two extra steps below. These steps are required to install dependencies of “blockdiag” discussed under Add Illustrations.
Update all the system packages:
$ pacman -Syu
This process will likely require restarting of the MSYS2 MINGW32 console and repeating above commands, until update is complete.
Install pillow, that is one of dependences of the blockdiag:
$ pacman -S mingw32/mingw-w64-i686-python2-pillow
Check the log on the screen that
mingw-w64-i686-python2-pillow-4.3.0-1
is installed. Previous versions of pillow will not work.
A downside of Windows installation is that fonts of the blockdiag pictures <add-illustrations> do not render correctly, you will see some random characters instead. Until this issue is fixed, you can use the interactive shell to see how the complete picture looks like.
All remaining applications are Python packages and you can install them in one step as follows:
cd ~/esp/esp-idf/docs
pip install --user -r requirements.txt
Note
Installation steps assume that ESP-IDF is placed in ~/esp/esp-idf
directory, that is default location of ESP-IDF used in documentation.
Change to directory with files for specific language:
cd en
Now you should be ready to build documentation by invoking:
make html
This may take couple of minutes. After completion, documentation will be placed in ~/esp/esp-idf/docs/en/_build/html
folder. To see it, open index.html
in a web browser.
Wrap up¶
We love good code that is doing cool things. We love it even better, if it is well documented, so we can quickly make it run and also do the cool things.
Go ahead, contribute your code and documentation!