I have a project using Doxygen, Breathe, and Sphinx for documentation. The hardcoded example snippets of code in the documentation have become a pain to maintain, as the project is constantly evolving. I want to make the example snippets be covered by our automated tests.
I experimented with \example
, \include
, \snippet
, and \dontinclude
, but each of them seem to have problems:
\example
and \include
only allow you to paste the entire contents of a file into a code block. Since I don't want to have #include example_foo.cpp
show up at the top of every example in the documentation, these directives aren't of any help.\snippet
s don't seem to be mergeable into a single code block.\dontinclude
uses \skip
and \until
, but their search pattern is displayed in the code block.I am not interested in any of the directives that require you to hardcode the line numbers, since that's very brittle.
Of these, \snippet
seems the most promising and useful:
But I'd like to merge the snippets, since these separate code blocks look ugly.
I've created a minimal reproducible example repository here:
.
├── Dockerfile
├── docs
│ ├── conf.py
│ ├── doxygen
│ │ └── Doxyfile
│ └── index.rst
├── example
│ └── nums.cpp
├── nums
│ └── nums_struct.hpp
└── README.md
example/nums.cpp
:
//! [one]
int one() {
return 1;
}
//! [one]
int hidden() {
return 42;
}
//! [two]
int two() {
return 2;
}
//! [two]
int main() {
return one() + two();
}
nums/nums_struct.hpp
:
/// \snippet nums.cpp one
/// \snippet nums.cpp two
struct nums_struct
{};
I'm on Arch Linux, but the command sudo docker build . -t hello && sudo docker run -v .:/example hello
should work on other Linux distros out of the box, with Docker as the only dependency. It outputs docs/_build/html/index.html
, which you can view using your browser.
There was a similar question in 2017 titled Is there a way to merge snippets or make a disjoint snippet in Doxygen?, but it didn't get any answers.
Thanks to @albert for nudging me in the right direction.
His answer does not handle functions containing braces, like if-statement curly braces that indicate the start and stop of the scope.
I figured out that by placing the end marker (//! [stop_one]
here) at the end of a line of code, we can prevent a second newline from appearing in the docs.
So using this nums/nums_struct.hpp
:
/// \dontinclude nums.cpp
/// \skipline start_one
/// \until stop_one
/// \skipline start_two
/// \until stop_two
struct nums_struct
{};
and this example/nums.cpp
:
//! [start_one]
int one() {
if (1) {
return 1;
}
return 1;
} //! [stop_one]
int hidden() {
return 42;
}
//! [start_two]
int two() {
return 2;
} //! [stop_two]
int main() {
return one() + two();
}
we can get the output I was originally looking for: