___              _ _ ____
   /   |  __________(_|_) __ \____  _  ____  __
  / /| | / ___/ ___/ / / / / / __ \| |/_/ / / /
 / ___ |(__  ) /__/ / / /_/ / /_/ />  </ /_/ /
/_/  |_/____/\___/_/_/_____/\____/_/|_|\__, /
                                      /____/

Using python

The most powerful feature of AsciiDoxy is that it allows you to use python code to generate (parts of) your documentation. The python code can be written directly in the AsciiDoc files. AsciiDoxy runs all python code and replaces it with valid AsciiDoc syntax before handing it over to AsciiDoctor.

This feature enables most of the other functionality offered by AsciiDoxy. To fully use AsciiDoxy it is important to understand how to include python code in you AsciiDoc files.

1. Basic syntax

AsciiDoxy uses Mako templates to combine python and AsciiDoc in a single file. It supports all syntax supported by Mako.

The construct ${} can be used to execute python code and insert the result in its place. Everything between ${ and } is evaluated and executed as python code. The result of the execution is inserted in the AsciiDoc file in the place of the ${} construct.

For example:

The sum of 3 and 4 is ${3 + 4}.

Results in:

The sum of 3 and 4 is 7.

It is also possible to use built-in functions provided by python. For example:

The sum of 3 and 4 is ${sum([3, 4])}.

Also results in:

The sum of 3 and 4 is 7.

For more information, and other options see: Mako template syntax.

2. Importing extra functionality

It is possible to use all functionality provided by the python standard library. Extra python packages from the python package index can be used as well. Like in normal python scripts the functionality does need to be imported before it can be used.

To import functionality, add an import statement within a so-called module-level block:

<%!
    import math
%>

Then use the imported functionality in any ${} construct in the file:

The factorial of 5 is ${math.factorial(5)}.

This results in:

The factorial of 5 is 120.

2.1. Python path handling

For import statements to work, the imported modules need to be on the python path. For libraries included with python or installed with pip this is automatic. To include your own python modules, AsciiDoxy needs to know where to look.

By default, the directory containing the input AsciiDoc file is used to look for additional python modules. If needed, you can specify a different path to be included using the --python-dir command line option.

3. Custom functions

Module-level blocks can also be used to define custom functions to reuse in your AsciiDoc files. Write the functions once in a module-level block, and use it multiple times in a ${} construct:

<%!
    def my_sum(*values):
        return sum(values)
%>

The sum of 3 and 4 is ${my_sum(3, 4)}.

The sum of 1, 2, 3 and 4 is ${my_sum(1, 2, 3, 4)}.

The result is:

The sum of 3 and 4 is 7.

The sum of 1, 2, 3 and 4 is 10.

Module-level blocks are executed once when the AsciiDoc files are loaded, before the content is actually rendered. It is recommended to put all imports and user defined functions in module-level blocks.

The AsciiDoxy built-in functionality is not available in module-level blocks. If you need to access to that functionality, use a block without the !:

<%
    ...
%>

Regular python blocks are only executed when the surrounding text is rendered.

4. Using variables

It is possible to define and use variables, like in normal Python code. Usually you define the variables in Python blocks (<% …​ %>). You can then use them in other Python blocks and in expressions:

<%
    platform = "android"
%>

= Instructions for ${platform}

${include(f"instructions-{platform}.adoc")}

Variables defined in Python blocks are only available within the same AsciiDoc files. They are not carried over to any of the included files.

5. Sharing variables and functions

To share variables, and other objects like functions, with included AsciiDoc files, you can assign them to the built-in environment called env. The environment will get copied to any document included from the current document.

When changing variables, or assigning new variables, in an included document, the variables in its parent will not change. The change is limited to the current document, and any document in includes.

For example, you can set a variable in the entry point document:

android.adoc
<%
    env.platform = "android"
%>

${include("instructions.adoc")}

Now you can use this variable in the included document:

instructions.adoc
= Instructions for ${env.platform}

...

You can even share functions using the environment:

main.adoc
<%!
    def my_sum(*values):
        return sum(values)
%>
<%
    env.my_sum = my_sum
%>

The sum of 3 and 4 is ${my_sum(3, 4)}.

${include("sub.adoc")}
sub.adoc
The sum of 1, 2, 3 and 4 is ${env.my_sum(1, 2, 3, 4)}.

6. Accessing command line arguments

All command line arguments provided to AsciiDoxy can be accessed in the AsciiDoc files through the config object. Arguments directly supported by AsciiDoxy are available by name. The dashes (-) are replaced by underscores (_). Arguments that have default values, will have these defaults applied. The other arguments that are passed through to AsciiDoctor are present unmodified in config.extra.

For example the build directory passed to Asciidoxy:

asciidoxy --build-dir my-build-dir ...

Can be used inside AsciiDoc files:

${config.build_dir}

7. Comments

AsciiDoc supports adding comments to your AsciiDoc files that are not carried over into the published documents. Most commonly // is used for single line comments and //// for multiline comments. AsciiDoxy carries over these comments like any other text in the AsciiDoc file. It is AsciiDoctor (or any other AsciiDoc tool chain) that makes sure the comments do not end up in the published document.

When an AsciiDoc comment contains any special AsciiDoxy or Mako directive, it is not ignored by AsciiDoxy. Any code or directive is still executed. This can lead to unexpected results.

For example the following:

// ${link("MyClass")}

Results in the following generated AsciiDoc:

// <<somefile.adoc#myclass,MyClass">>

AsciiDoctor will still ignore it and it will not be part of the published documents. However, some commands like insert result in larger blocks of generated AsciiDoc. Then only the first line is commented out, but the rest will become part of the published document. Some commands can also cause an error during generation, e.g. when MyClass does not exist or is not included anywhere.

To prevent this, use Mako comments instead: ##. These comments will be ignored completely by AsciiDoxy. They will not end up in the published document either.

## ${link("MyClass")}

For multiline comments use <%doc> and </%doc>:

<%doc>
${link("MyClass")}
</%doc>

It is also possible to include verbatim Mako and AsciiDoxy directives in the generated documentation. They need special handling to be ignored by AsciiDoxy, but still end up in the published document:

${"""
${link("MyClass")}
"""}
AsciiDoxy