Creating Documents with Leo

This chapter discusses Leo’s rst3 command. The rst3 command creates HTML, PDF, LaTeX and other kinds of documents from Leo outlines containing reStructuredText (rST) or Sphinx markup.

Note: docutils is a document processing system using rST markup. Sphinx extends docutils: Sphinx markup is a superset of rST markup. All of Leo’s documentation is written in Sphinx and processed with the rst3 command to produce HTML files.

Leo and rst3 make writing rST/Sphinx documents a lot easier:

  1. Leo outlines organize writing in all the usual ways. You always see the structure of your writing clearly no matter how large it is. You can reorganize chapters, sections and paragraphs effortlessly. View nodes can show you many different views of your writing simultaneously. These features, all by themselves, would make Leo an excellent choice for editing rST documents.
  2. But the rst3 command does more: it automatically creates rST sections from headlines. Without Leo, changing the level of a section is clumsy and error prone: you must carefully change the section’s underlining character. Leo’s rst3 command eliminates all this bother.
  3. The rst3 command converts an @rst tree to rST and then sends this text to docutils or Sphinx for further processing.

In addition to these basic features, the rst3 command provides many other capabilities for power users. We’ll discuss these features later.

Tutorial

This tutorial tells how to get started with Leo’s rst3 command. The tutorial covers only rst3’s basic features. You can do a lot with these features–Leo’s documentation uses only the features described here!

Step-by-step, here is how to use the rst3 command:

  1. Create an @rst node. This node and its descendants will contain your document. The @rst node itself is a good place to specify general information about your documentation, including its title, one or more external files created by the rst3 command, and global settings for the rst3 command.
  2. Write your documentation in the descendants of the @rst node. Within the @rst tree, headlines represent section headings. Body text contain your writing, including rST or Sphinx markup.
  3. To create your documents, run the rst3 command on an outline containing one or more @rst nodes.

That’s all there is to it! The organization of the @rst tree is the organization of your document. To reorganize your document, you just reorganize the nodes in the @rst tree! When you are done writing, create your output using the rst3 command.

The next sections will discuss these three steps in more detail. As you will see, after you set up the @rst node, you can focus exclusively on writing and organizing. Leo’s rst3 command will take care of the rest.

Step 1: Create the @rst node

The headline of the @rst node has the form:

@rst <filename>

Depending on options to be discussed later, the rst3 command will write one or two files: the output file (<filename>), and the intermediate file (<filename>.txt).

For example, the rst3 command applied to @rst abc.html will write abc.html or abc.html.txt or both.

Important: The intermediate file always contains rST/Sphinx markup regardless of the type of the final output files. When in doubt about the rst3 command, you can examine the intermediate file to see what rst3 has done.

Let’s turn our attention to the the body of the @rst node...

Set global options

The @rst node is a good place for options that apply to the entire @rst tree. Typically, you will just set these options once and then completely forget about them.

You set rst3 options in body parts like this:

@ @rst-options
rst3 options, one per line
@c

This is a Leo doc part: the ‘@’ must appear in the leftmost column. As usual, the doc part ends with the @c directive, or the end of the body text.

Here are the recommended options when using docutils:

@ @rst-options
call_docutils=True
code_mode=False
stylesheet_path=..\doc
write_intermediate_file=True
@c

And here are the recommended options when using Sphinx:

@ @rst-options
call_docutils=False
code_mode=False
stylesheet_path=..\doc
write_intermediate_file=True
@c

Note 1: It is good style to specify all these options explicitly, even if they are the same as the standard default values. This ensures that the rst3 command will produce the same results no matter where the @rst node is located.

Note 2: You may have to change the stylesheet_path option so that the generated output file can find the proper stylesheets.

Set your document’s title

Next, set your document’s title by putting something like this in the body text of the @rst node:

#############
War and Peace
#############

Important: The rst3 command reserves the ‘#’ character for the document titles–don’t use any other underlining character.

Sometimes I put the first words of a document in the @rst node:

Well, Prince, so Genoa and Lucca are now just family estates of the
Buonapartes. But I warn you, if you don't tell me that this means war, if
you still try to defend the infamies and horrors perpetrated by that
Antichrist--I really believe he is Antichrist--I will have nothing more to
do with you and you are no longer my friend, no longer my 'faithful slave,'
as you call yourself! But how do you do? I see I have frightened you--sit
down and tell me all the news.

Step 2: Write your document

Now comes the “interesting” part–actually writing your novel, short story, documentation or whatever.

As always with Leo, you organize your work with outlines. By default, (that is, with the recommended options discussed in Step 1) the rst3 command will produce the following output:

  1. Each node becomes an rST/Sphinx section.

    The level of each section corresponds to the level of the node in the headline. Children of the @rst node create level 1 sections. Grandchildren of the @rst node create level 2 sections, and so on.

  2. The headline of each node becomes the section heading.

  3. The body text of each node becomes the contents of the node’s section.

    Note: The body text of any node in an @rst tree contains plain text, with optional rST or Sphinx markup. Sphinx markup is a superset of rST markup. For more details on markup, see the Sphinx or reStructuredText documentation.

That’s all there is to it!

Well almost. There is one other feature you should know about. Headlines that start with ‘@rst-‘ control the rst3 command. The three most useful are:

@rst-no-head <ignored-text>

Causes the rst3 command to copy just the body text of the node. In other words, the node’s body text become part of the previous section. Leo’s docs use such nodes for rST links and other “invisible” markup.

@rst-ignore <ignored-text>

The rst3 command ignores any @rst-ignore node. Neither the headline nor the body text becomes part of the output. You can use such nodes for notes that you do not want to become part of the actual document.

@rst-ignore-tree <ignored-text>

The rst3 command ignores the @rst-ignore-tree node and all its descendants.

Step 3: Run the rst3 command

This step is easy. Select an outline containing one or more @rst trees. Now do <Alt-X>rst3<Return>. You can use <Ctrl-P> (repeat-complex-command) instead if the last minibuffer command was the rst3 command.

The rst3 command writes its output to either the output file or the intermediate file, or both:

  • With the recommended settings for docutils, the rst3 command will run docutils automatically, producing the output file as the result.
  • With the recommended settings for Sphinx, the rst3 command will generate the intermediate file. You must then run Sphinx’s make utility to turn the intermediate file into the final output file.

Go forth and experiment

You now know everything needed to get started with the rst3 command. Some possible next steps are:

  1. Look at Leo’s own documentation in LeoDocs.leo. It’s in the node “@rst htmlrstplugin3.html”. Discover how the nodes in this tree correspond to the documentation you see before you.
  2. Create your own @rst nodes. Run the rst3 command on them and see what happens. If you get stuck, you please ask for help at Leo’s Google Group.

Options

This section discusses options–what they are, how to set them and how to set their defaults.

General options

Here is a complete list of options for the rst3 and code-to-rst commands:

call_docutils (default: True):

Call docutils to process the intermediate file.

default_path (default: ‘’)

The path to be prepended to filenames given in root nodes.

default_encoding (default: utf-8)

The default encoding to be used for non-ascii (unicode characters).

encoding (default: the default_encoding setting)

The encoding to be used for non-ascii (unicode) characters. Important: this option has effect only in @rst-options doc parts in root @rst nodes.

generate_rst (default: True)

A master switch. True: generate rST markup for rST sections and rST code-blocks. False: generate plain text and ignore @ @rst-markup doc parts.

generate_rst_header_comment (default: True)

True: Leo writes a comment line of the form:

.. rst3: filename: <filename>

at the start of intermediate files. This option has effect only if the generate_rst and write_intermediate_file options are both True.

publish-argv-for-missing-stylesheets (Default: ‘’)

The arguments to be passed to docutils.core.Publisher().publish() when no stylesheet is in effect. This is a string that represents a comma-separated list of strings: For example, the option:

publish-argv-for-missing-stylesheets=--language=de,--documentclass=report,--use-latex-toc

results in the call:

publish(['--language=de','--documentclass=report','--use-latex-toc'])

show_headlines (default: True)

True: automatically generate rST sections from headlines. False: ignore headlines.

Note: The level of the node in the outline determines the level of the section underlining in the rST markup. Higher-level headlines in the outline correspond to higher-level section headings; lower-level headlines in the outline correspond to lower-level section headings.

show_organizer_nodes (default: True)

True: generate rST sections for nodes that do not contain body text.

Note: This option has no effect unless the rST section would otherwise be written.

show_sections (default: True)

True: generate rST sections corresponding to headlines. False: don’t generate sections. Instead, generate lines of the form:

**headline**

strip_at_file_prefixes (default: True)

True: remove @auto, @file, @nosent and @thin from the start of headlines.

stylesheet_name (default: ‘default.css’)

The name of the stylesheet passed to docutils.

stylesheet_path (default: ‘’)

The directory containing the stylesheet passed to docutils.

Note: If the stylesheet_embed option is True, specify a path relative to the location of the Leo file. If the stylesheet_embed option is False, specify a path relative to the location of the HTML file.

stylesheet_embed (default: True)

True: The content of the stylesheet file will be embedded in the HTML file. False: The HTML file will link to an external stylesheet file.

underline_characters (default: #=+*^~”’`-:>_)

The underlining characters to be used to specify rST sections. The first character is reserved so you can specify the top-level section explicitly.

verbose (default: True)

True: write informational messages.

write_intermediate_file (default: False)

Important: the rst3 command always creates an intermediate file. This option controls whether that file is an internal Python object or an actual file on the external file system.

True: writes the intermediate file to the external file system. The name of the intermediate file has the name of the output file with .txt appended. This option has effect only if the generate_rst option is True.

False: writes the intermediate file to an internal Python object.

Headline commands

Any headline that starts with @rst- controls the rst3 command.

@rst-ignore <ignored-text>

Ignore the node and its descendants.

@rst-ignore-node <ignored-text>

Ignore the node, but not its descendants.

@rst-ignore-tree <ignored-text>

Same as @rst-ignore. Ignore the node and its descendants.

@rst-no-head <ignored-text>

Ignore the headline but not the body text of this node. This has no effect on descendant nodes.

@rst-no-headlines <ignored-text>

Ignore all headlines. (Set show_headlines=False)

@rst-option <option> = <value>

Set a single option to the given value. The default value is True.

@rst-options <ignored-text>

Set options from body text. The body text should contain nothing but lines of the form:

<option>=<value>

@rst-preformat <ignored-text>

Format the body text of the node as computer source code. In effect, this option adds a line containing ‘::’ at the start of the body text. The option then indents all following lines.

This option has no effect on descendant nodes.

Option doc parts

Option doc parts set rst3 options. Option doc parts start with @ @rst-options followed by lines of the form name=value. (Comment lines starting with ‘..’ are allowed.) For example:

@ @rst-options
.. This comment line is ignored.
show_headlines=False
show_leo_directives=False
verbose=True
@c

This is a real Leo doc part. Like all other doc parts an option doc part starts with the @ directive and continues until the end of body text or until the next @c directive.

Defaults for options

Settings in leoSettings.leo or myLeoSettings.leo specify the defaults to be used for all rst3 options. The form of these settings is:

@bool rst3_<option name> = True/False
@string rst3_<option name> = aString

That is, to create a default value for an rst3 setting, you must prefix the option name with ‘rst3_’. For example:

@bool rst3_write_intermediate_file = True

Http plugin options

The following options are for the use of Bernhard Mulder’s http plugin. The http plugin creates an http server running on a local port, typically 8080. When the http plugin is running you will see a purple message in the log window that looks something like this:

http serving enabled on port 8080, version 0.91

To use the http plugin, start a web browser and enter this url:

http://localhost:8080/

You will see a a top level page containing one link for every open .leo file. Clicking on a link will cause the http server to pass a new page to the browser. You can use the browser’s refresh button to update the top-level view in the browser after you have opened or closed files.

Important: See the docstring for the http plugin for information on configuring the plugin. Some of the following rst3 settings must match values of settings for the http plugin.

Here are the rst3 options that support the http plugin:

http_server_support (default: False)

A master switch: none of the following options have any effect unless this option is True. If True, the rst3 command does the following:

  1. Writes node markers in the rst output for use by the http plugin. Node markers are rst named hyperlink targets. By default they look like:

    .. _http-node-marker-N

    where N is a unique node number.

  2. Adds additional information to all nodes of the tree being formatted using Leo’s unknownAttributes mechanism.

http_attributename (default: ‘rst_http_attribute’)

The name of the attribute name written to the unknownAttributes attribute of each outline node in the rst root tree. The default is ‘rst_http_attribute’; it should match the following setting of the http plugin:

@string rst_http_attributename = 'rst_http_attribute'

clear_http_attributes (default: False)

If True the rst3 command initially clears the fields specified by http_attributename.

node_begin_marker (default: ‘http-node-marker-‘)

The string used for node markers.

Section expansion options

New in Leo 4.9: The following three options allow you to expand noweb section references, much like Leo itself does.

expand_noweb_references

True: Replace references by definitions. Definitions must be descendants of the referencing node.

ignore_noweb_definitions

True: ignore section definition nodes.

expand_noweb_recursively

True: recursively expand definitions by expanding any references found in definitions.

Notes:

  • This is an experimental feature: all aspects might changed. The defaults for all these options ensure that the rst3 command works as it has always.
  • The rst3 command ensures that unbounded expansions can not happen. While expanding any section, the rst3 will not expand again any sections that have already occurred in the expansion.

Other topics

Markup doc parts

Markup doc parts have the following form:

@ @rst-markup
any rST markup
@c

Markup doc parts inserts the markup directly into the output. Markup doc parts are most useful when formatting an outline as code using the code-to-rst command.

Required cascading style sheets

HTML files generated by the rst3 command assume that three .css (cascading style sheet) files exist in the same directory. For the HTML output to look good the following .css files should exist:

  • default.css is the default style sheet that docutils expects to exist.
  • leo_rst.css contains some style improvements based on Gunnar Schwant’s DocFactory.
  • silver_city.css is the style sheet that controls the syntax highlighting generated by SilverCity.

The latter two style sheets are imported at the end of the default.css.

Important: You can use cascading style sheets to do things that otherwise wouldn’t be possible with “plain” rST. For instance, the background color of this page was specified in a body style.

Further study

The file ListManagerDocs.html is an impressive example of the kind of output that can be generated relatively easily using the rst3 command.

The source for ListManagerDocs.html is wxListManager.leo. Important: wxListManager.leo was written for the old rst2 plugin; it could be greatly simplified if adapted for the rst3 command.

This documentation was created using the rst3 command. The source code for this documentation is in LeoDocs.leo. The source code for the rst3 command is in leoRst.py in leoPy.leo.

Acknowledgements

Josef Dalcolmo wrote the initial rst plugin. Timo Honkasalo, Bernhard Mulder, Paul Paterson, Kent Tenney and Steve Zatz made contributions to the rst and rst2 plugins.

Theory of operation

The code for the rst3 command is more complex than usual. Fortunately, the overall organization is straightforward.

defaultOptionsDict
This dictionary represents each rst3 option. To add another option, just add another entry to this dictionary. Keys are the option name, including the rst3_ prefix. Values are the default value of the option. The hard-coded values in the dictionary may be changed as the result of @settings entries.
processTree
processTree is the top-level code that handles one rst root node. It calls preprocessTree to create the vnodeOptionDict ivar. processTree then calls either writeNormalTree or writeSpecialTree depending on whether text will be sent to docutils for further processing. These two methods handle mundane details of opening and closing files. Both writeNormalTree and writeSpecialTree call writeTree to do the actual work.
vnodeOptionDict
The entries in this dictionary represent the options that are set in one particular node. The keys of vnodeOptionDict are vnodes, the values are anonymous dictionaries. These anonymous inner dictionaries contain the options that are explicitly set at each vnode (and thus each position). Preprocessing the tree this way ensures that each node (headline and body text) is parsed exactly once.
writeTree
writeTree first calls scanAllOptions, which has the effect of initializing all options. writeTree then calls writeNode for each node that will be processed by the rst3 command. Options may cause the rst3 command to skip a node or an entire subtree.
writeNode
writeNode first calls scanAllOptions to compute the options that are in effect for that single node. Once options have been computed, processing the node is straightforward. writeNode calls writeBody and writeHeadline to do the real work. These methods generate or skip text based on various options.
scanAllOptions

scanAllOptions recreates the optionsDict ivar to represent all the options in effect for for the particular node being processed by writeNode. Client code gets these options by calling the getOption method.

scanAllOptions first inits all options from settings, then updates those options using the anonymous dictionaries contained in the vnodeOptionsDict. scanAllOptions works like g.scanAllDirectives, but the code is much simpler.

Previous topic

Controlling Syntax Coloring

Next topic

Scripting Leo with Python