Customizing Your Documentation With RST Markup
00:00 In the previous lesson, I got you started with Sphinx and showed you how to build your first document. In this lesson, I’ll be diving into RST, the default markup language used by Sphinx. RST is short for reStructuredText.
00:15 I’m sure there’s a good story behind the capitalization in the name, but I’m way too lazy to go looking for it.
00:22 RST is a text-based format where a few key symbols provide style and structure information to the document. If you’ve used Markdown or asciidoc before, this is a similar technology.
00:35 If you’re like me, and you’re routinely using all three, well no, I don’t remember just how many backticks I’m supposed to use in this situation. That’ll make a little more sense in a second.
00:47 Although most people use Markdown for their GitHub project home pages, GitHub does also understand RST. I’ll show you how to take advantage of this a little later.
For the most part, when you’re writing in RST, you’re just writing text. A block of text is considered a paragraph, like you would in any
01:06 You can apply some styling within a paragraph using some special characters. First up is italics, which is done by surrounding something in paired stars.
01:16 Next is bold, which is done by surrounding something in paired double stars. Code is shown with double backticks. This is the one I usually confuse, as it’s single backticks in Markdown and asciidoc, so when you’re switching back and forth, it’s hard to remember.
01:32 I should probably be more generic about this than code. The result is almost always rendered as a monospace font, and depending on your theme, you may also get a different color. Note that this is just for inline.
01:45 There’s a separate way of showing blocks of code, which I’ll show you in a few minutes.
01:50 You can add a line separator between paragraphs by using any punctuation more than four times in a row. I’ve only ever seen people use dashes for this, so I don’t swear how well it’ll work if you use something besides a dash.
It is nice that you can use more than four though in case you want it to stand out in your text files some more. In HTML, this gets rendered as an
<hr> (horizontal rule) tag.
02:16 Headings are kind of weird in RST. The first heading marker you use is what determines it as the title style. That’s kind of nice and flexible and everything, but it makes things a little error-prone.
02:29 The style I’m using on the left is pretty common, and if you stick with it, you’ll be good. Remember though, if you end up using these in a different order, it won’t map to what I have on the left.
02:40 Most of my documents are only three levels, so I usually use either the star or the hash for my titles and then am pretty consistent about equals and dashes for the next two levels.
02:52 Stars are used for bullet lists. Note that RST gets really finicky about the spacing here. If your bullet item ends up needing multiple lines in your text file, you need to indent to indicate it is all part of the same bullet.
03:06 When you build a doc with Sphinx, you’ll get a warning if you forget this. If you do forget it, your output may not look the way you expect, depending on the output format.
03:16 Numbered lists can either be explicit using numbers or automatic using the number sign. Note that a single blank line doesn’t create a new list, so the mess I have on the left creates a single numbered list from one to four on the right.
03:34 There are two kinds of links, external ones and internal ones. External ones typically end up being output as URLs, which may or may not be clickable depending on your output format.
A link is written using single backticks and an underscore suffix. If you want a name to be displayed instead of the link itself, you put the name inside the backticks and surround the link in angle brackets (
03:59 Note it still has the underscore suffix. For internal links, you can create a reference using double dots, an underscore prefix, and a single colon. Careful with this one.
Double colons are meaningful, and you don’t want to confuse the two ideas. Also note that it needs to have a blank line following it. If you have a reference defined, you can link to it using
:ref: then backticks followed by the reference name without the leading underscore.
04:30 This is different from the external link, which uses an underscore suffix on the whole thing. These are all very similar, and I mess this up all the time.
:ref: is optional If the link you’re referencing is in the same document. I’ve had some trouble making that work in certain situations before, so I’ve just developed the habit of always using the
And just like the external link, the internal link can use the angle bracket (
<>) mechanism to show a display name instead of the link itself.
05:06 A directive is a block of instructions. These get used everywhere for all sorts of structure and styling. A directive is comprised of the directive name and then possibly some arguments, some options, and some content: code blocks, notes, warnings, and more are all done with directives.
This example is a
code-block directive. I mentioned earlier that you use double backticks for inline code. If you’re writing more code than that, you would use a
code-block directive like this.
All of the directives start with double leading dots (
..) and then are marked with a double colon (
::). In between is the name of the directive you’re using.
This one I’m using is
code-block. After the double colons, you might have an argument. The argument is optional for the
code-block directive, and it indicates what kind of code is in the block.
06:03 Sphinx uses the Python Pygments library to syntax-highlight code blocks. If you give an argument here, Sphinx will attempt to match it to the appropriate code highlighter.
Underneath the directive statement, you may find zero or more options. Options are between matched colons. The
linenos option to
code-block says that when output, this block should include line numbers.
06:27 After the directive statement and any options, you leave a blank line and then all content that is indented is considered part of the directive’s block. It’s kind of Pythonesque here.
What, did you want curly braces or something? Finally, if you just use the double dots (
..) on its own without the corresponding colons, RST treats the line as a comment.
You saw one of these at the top of the
index.rst file in the previous lesson.
The first directive I’m going to introduce you to is the one to embed pictures in your document. The
image directive takes a single argument, the name of the file to be inserted.
07:08 The path is either relative to the document file the directive is in, or it can be fully qualified. Images can be a little tricky. What formats they support and how sizes are treated are dependent on what the output supports. For HTML, you can use the same kind of image formats you’d use on the Web.
07:28 Some output formats, like LaTeX, support embedding PDFs. PDFs can be tricky when it comes to sizes, so the options specifying width and height here may or may not be effective depending on the output format.
figure directive is essentially an image directive that supports captions. The content portion of the directive is where you specify the contents of the caption.
This is probably the directive I use the most, the
code-block. I showed you it earlier to explain what a directive was, so not much new to see here. The argument that specifies the language is optional, as is the
linenos option. If it can, Sphinx will apply Pygments syntax highlighting for your block.
Don’t forget the blank line between the directive and your code. Oh, and because indentation indicates belonging to the block, that
for statement isn’t actually indented from Python’s perspective.
08:28 Things can get a little messy when you embed a language that has importance to whitespace inside of a document where whitespace is important.
There are a couple of callout boxes that you can take advantage of, the
note and the
warning. Both use the argument to the directive for the content of the box.
08:50 You can use paragraph styling, like bold and italics, inside the callouts. One thing to watch out for is the space between the double colons and the texts.
08:59 This needs to be there or it won’t work properly.
Sphinx supports the ability to embed other files into your file using the
include directive. The options here allow you to include only a portion of the file if you wish.
09:15 I mentioned earlier GitHub supports RST format for your README, and the README from a project is often the same as you’d have in your index page, so I often use this directive to suck the README into the index page.
I’ll demo all this later. There is also a variant on
literalinclude, which includes the file verbatim. No further RST processing is done on the contents of this one.
This also supports the
end-before options that
include does as well. Okay, let’s go use some of this stuff in our documentation.
This is my
index.rst file. I’ve made a couple of small changes from the skeleton file. First, I added a comment at the top telling you what file this is. Second, I added some version information.
The paired pipe symbols (
|) here are a variable replacement mechanism. Any value in your
conf.py can be accessed this way, so the
0.0.1 release number I chose during
quickstart will show up on this line. Before showing you the next change, let me first talk a bit about the table of contents.
toctree directive generates a table of contents. The
maxdepth option specifies how deep to go in the tree. With a value of
2, you will get two levels of headers in the tree.
10:38 This is the default and actually makes pretty good sense. Typically, any files you have in your documentation are going to have a title and then some section headers.
You probably don’t want your sub- and sub-subsection headers in your table of contents. The
caption option indicates what text will show in the table of contents’ caption line. Mine is the default,
The next change I made to
index.rst is adding a value to the
toctree directive. This value corresponds to the name of a file without the extension.
movie here means it expects there to be a file called
movie.rst in the same directory. Assuming it finds such a thing, it will process it and include its headers in the table of contents.
movie.rst, let’s go look at that file.
11:31 Here I’ve written some RST content talking about Firefly the TV show. If you look closely, you’ll see some bold, some monospace, an external link to the IMDB page, and a bullet list.
11:42 I’ve actually been a bad boy here and used what I normally use for section and subsection header markup, those underlines of equals and hyphens. As these are the only two headers in file, they’ll be treated as header level one and two, title and subtitle.
Remember when I said you should be consistent? Yeah, well, I didn’t say I was going to be. And down at the bottom of the file here, I’ve also got a
note box. Let’s go take a look at the result.
Off-screen, I ran
make html again to rebuild my document, and this is the result. There’s the version number and the two levels of table of contents, coming from my two levels of headers in the
12:30 In addition to the ToC macro happening on the right, you also have a list of first-level headers in the left-hand nav.
If I click one of these, as you might expect, clicking the link takes me to the page generated by
movie.rst, and here is all the wonderful text from my TV show babblings.
12:54 Okay, you’ve seen the basics of RRST and building Sphinx docs. Next up, I’ll show you how to take advantage of your pydoc comments. You do write comments in your code, right? I think I said that already.
That’s a good question @maceww6438. Underlines are one of the possible heading markers.
I had to go digging through the spec to be sure, as it isn’t in most of the cheat sheets out there, but the “transition” (RST’s official name for a horizontal rule) requires a blank line before and after it.
In fact it actually refers to it as a section title without title text.
Full spec details here:
Become a Member to join the conversation.
maceww6438 on March 14, 2023
In the section on headings, why didn’t
result in an horizontal rule?