Documenting — Logtalk 3.100.1

# Documenting

Assuming that the source_data flag is turned on, the compiler saves all relevant documenting information collected when compiling a source file. The provided lgtdoc tool can access this information by using the reflection support and generate a documentation file for each compiled entity (object, protocol, or category) in XML format. Contents of the XML file include the entity name, type, and compilation mode (static or dynamic), the entity relations with other entities, and a description of any declared predicates (name, compilation mode, scope, …). The XML documentation files can be enriched with arbitrary user-defined information, either about an entity or about its predicates, by using documentation directives. The `lgtdoc` tool includes POSIX and Windows scripts for converting the XML documentation files to several final formats (such as HTML and PDF).

Logtalk supports two documentation directives for providing arbitrary user-defined information about an entity or a predicate. These two directives complement other directives that also provide important documentation information, such as the mode/2 and meta_predicate/1 directives.

## Entity documenting directives

Arbitrary user-defined entity information can be represented using the info/1 directive:

    :- info([
        Key1 is Value1,
        Key2 is Value2,
        ...
    ]).

In this pattern, keys should be atoms and values should be bound terms. The following keys are predefined and may be processed specially by Logtalk tools:

`comment`

  Comment describing the entity purpose (an atom). End the comment with a period (full stop). As a style guideline, don’t use overly long comments. If you need to provide additional details, use the `fails_if` and `remarks` keys.

`author`

  Entity author(s) (an atom or a compound term `{entity}` where `entity` is the name of an XML entity in a user-defined `custom.ent` file).

`version`

  Version number (a `Major:Minor:Patch` compound term) Following the Semantic Versioning guidelines is strongly advised.

`date`

  Date of last modification in ISO 8601 standard format (`Year-Month-Day` where `Year`, `Month`, and `Day` are integers).

`parameters`

  Parameter names and descriptions for parametric entities (a list of `Name-Description` pairs where both names and descriptions are atoms). End the `Description` with a period (full stop).

`parnames`

  Parameter names for parametric entities (a list of atoms; a simpler version of the previous key, used when parameter descriptions are deemed unnecessary).

`copyright`

  Copyright notice for the entity source code (an atom or a compound term `{entity}` where `entity` is the name of an XML entity defined in a user-defined `custom.ent` file).

`license`

  License terms for the entity source code; usually, just the license name (an atom or a compound term `{entity}` where `entity` is the name of an XML entity in a user-defined `custom.ent` file). License names should, whenever possible, be a license identifier as specified in the SPDX standard.

`remarks`

  List of general remarks about the entity using `Topic-Text` pairs where both the topic and the text must be atoms. End the `Text` with a period (full stop).

`see_also`

  List of related entities (using the entity identifiers, which can be atoms or compound terms).

For example:

    :- info([
        version is 2:1:0,
        author is 'Paulo Moura',
        date is 2000-11-20,
        comment is 'Building representation.',
        diagram is 'UML Class Diagram #312'
    ]).

Use only the keywords that make sense for your application, and remember that you are free to invent your own keywords. All key-value pairs can be retrieved programmatically using the reflection API and are visible to the lgtdoc tool (which includes them in the generated documentation).

## Predicate documenting directives

Arbitrary user-defined predicate information can be represented using the info/2 directive:

    :- info(Name/Arity, [
        Key1 is Value1,
        Key2 is Value2,
        ...
    ]).

The first argument can also a grammar rule non-terminal indicator, `Name//Arity`. Keys should be atoms. Values should be bound terms. The following keys are predefined and may be processed specially by Logtalk tools:

`comment`

  Comment describing the predicate (or non-terminal) purpose (an atom). End the comment with a period (full stop). As a style guideline, don’t use overly long comments. If you need to provide additional details, use the `remarks` key.

`fails_if`

  Comment describing failing conditions for the predicate. As a style guideline, don’t use overly long comments. If you need to provide additional details, use the `remarks` key.

`arguments`

  Names and descriptions of predicate arguments for pretty print output (a list of `Name-Description` pairs where both names and descriptions are atoms). End the `Description` with a period (full stop).

`argnames`

  Names of predicate arguments for pretty print output (a list of atoms; a simpler version of the previous key, used when argument descriptions are deemed unnecessary).

`allocation`

  Objects where we should define the predicate. Some possible values are `container`, `descendants`, `instances`, `classes`, `subclasses`, and `any`.

`redefinition`

  Describes if a predicate is expected to be redefined and, if so, in what way. Some possible values are `never`, `free`, `specialize`, `call_super_first`, `call_super_last`.

`exceptions`

  List of possible exceptions thrown by the predicate using `Description-Exception` pairs. The description must be an atom. The exception term must be a ground term.

`examples`

  List of typical predicate call examples using the format `Description-Goal-Bindings`. The description must be an atom with the goal term sharing variables with the bindings. The variable bindings term uses the format `{Variable = Term, ...}`. When there are no variable bindings, the success or failure of the predicate call should be represented by the terms `{true}` or `{false}`, respectively (you can also use in alternative the terms `{yes}` or `{no}`).

`remarks`

  List of general remarks about the predicate using `Topic-Text` pairs where both the topic and the text must be atoms. End the `Text` with a period (full stop).

`since`

  Version that added the predicate (`Major:Minor:Patch`).

`see_also`

  List of related predicates and non-terminals (using the predicate and non-terminal indicators).

For example:

    :- info(color/1, [
        comment is 'Table of defined colors.',
        argnames is ['Color'],
        constraint is 'Up to four visible colors allowed.',
        examples is [
           'Check that the color blue is defined' - color(blue) - {true}
        ]
    ]).

As with the `info/1` directive, use only the keywords that make sense for your application and remember that you are free to invent your own keywords. All key-value pairs can also be retrieved programmatically using the reflection API and are visible to the lgtdoc tool (which includes them in the generated documentation).

## Describing predicates

The value of the `comment` key, possibly extended with the `remarks` key, should describe a predicate purpose and, when applicable, the circumstances under which a call may fail. Descriptions should be consistent across library and application APIs. Some guidelines:

1. When starting the description with a verb, use the third-person singular simple present form. For example, write `'Runs ...'`, `'Calls ...'`, `'Compares ...'`, `'Parses ...'`, `'Generates ...'`, `'Converts ...'`, `'Creates ...'`, `'Maps ...'`, `'Merges ...'`, `'Finds ...'`, etc.

2. Predicates that are pure logical relations often have descriptions starting with `'True iff ...'` or `'True if ...'`.

3. Predicates with multiple solutions often have descriptions starting with `'Enumerates, by backtracking, all ...'` or `'Enumerates, by backtracking, the ...'`.

4. Predicate call failure conditions often have descriptions with one or more sentences starting with `'Fails when ...'` or `'Fails if ...'`.

If you’re not sure how best to describe a predicate, look for examples in the Logtalk libraries and developer tools APIs documentation.

## Documenting predicate exceptions

As described above, the `info/2` predicate directive supports an `exceptions` key that allows us to list all exceptions that may occur when calling a predicate. For example:

    :- info(check_option/1, [
        comment is 'Succeeds if the option is valid. Throws an error otherwise.',
        argnames is ['Option'],
        exceptions is [
            '``Option`` is a variable' - instantiation_error,
            '``Option`` is neither a variable nor a compound term' - type_error(compound, 'Option'),
            '``Option`` is a compound term but not a valid option' - domain_error(option, 'Option')
        ]
    ]).

When possible, only standard exceptions should be used. See e.g. the error handling methods section for a full list. The argument names should be the same as those provided in the `arguments` or `argnames` keys. Exceptions are usually listed starting with instantiation and uninstantiation errors, followed by type errors, and then domain errors. These may then be followed by permission, existence, evaluation, representation, or resource errors.

For each exception, use of controlled language as found, e.g., in the ISO Prolog Core standard and this Handbook is advised. Some examples:

Instantiation error when one or more arguments cannot be a variable

  `Argument` is a variable

  `Argument1` and `Argument2` are variables

Instantiation error when a closed list with bound elements is required

  `Argument` is a partial list or a list with an element `Element` which is a variable

Uninstantiation error when an argument is not a variable

  `Argument` is not a variable

Type error when an argument is not a variable but also not of the expected type

  `Argument` is neither a variable nor a TYPE

  `Argument` is neither a partial list nor a list

Type error when an element of a list is not a variable but is not of the expected type

  An element `Element` of the `Argument` list is neither a variable nor a TYPE

Domain error when an argument is of the correct type but not in the expected domain

  `Argument` is a TYPE but not a valid DOMAIN

  `Argument` is an integer that is less than zero

Domain error when an element of a list is of the correct type but not in the expected domain

  An element `Element` of the `Argument` list is a TYPE but not a valid DOMAIN

Existence error when an entity of a given kind does not exist

  The KIND `Argument` does not exist

Other classes of errors have a less rigid style. In case of doubt, look for examples in this Handbook, in the APIs documentation, and in standard documents.

## Processing and viewing documenting files

The lgtdoc tool generates an XML documenting file per entity. It can also generate library, directory, entity, and predicate indexes when documenting libraries and directories. For example, assuming the default filename extensions, a `trace` object and a `sort(_)` parametric object will result in `trace_0.xml` and `sort_1.xml` XML files.

Each entity XML file contains references to two other files, an XML specification file and a XSLT stylesheet file. The XML specification file can be either a DTD file (`logtalk_entity.dtd`) or an XML Scheme file (`logtalk_entity.xsd`). The XSLT stylesheet file is responsible for converting the XML files to some desired format such as HTML or PDF. The default names for the XML specification file and the XSL stylesheet file are defined by the lgtdoc tool but can be overridden by passing a list of options to the tool predicates. The `lgtdoc/xml` sub-directory in the Logtalk installation directory contains the XML specification files described above, along with several sample XSL stylesheet files and sample scripts for converting XML documenting files to several formats (e.g., reStructuredText, Markdown, HTML, and PDF). For example, assume that you want to generate the API documentation for the `types` library:

    | ?- {types(loader)}.
    ....

    | ?- {lgtdoc(loader)}.
    ....

    | ?- lgtdoc::library(types).
    ...

The above queries will result in the creation of a `xml_docs` in your current directory by default. Assuming that we want to generate Sphinx-based documentation and that we are using a POSIX operating-system, the next steps would be:

    $ cd xml_docs
    $ lgt2rst -s -m

The `lgt2rst` script will ask a few questions (project name, author, version, …). After its completion, the generated HTML files will be found in the `_build/html` directory by default:

    $ open _build/html/index.html

For Windows operating-systems, PowerShell scripts are available. For example, assuming that we want to generate HTML documentation, we could run in a PowerShell window:

    PS > cd xml_docs
    PS > lgt2html.ps1 -p saxon

After completion, the generated HTML files will be found in the `xml_docs` directory by default.

See the `NOTES` file in the tool directory for details, specially on the XSLT processor dependencies. You may use the supplied sample files as a starting point for generating the documentation of your Logtalk applications.

The Logtalk DTD file, `logtalk_entity.dtd`, contains a reference to a user-customizable file, `custom.ent`, which declares XML entities for source code author names, license terms, and copyright strings. After editing the `custom.ent` file to reflect your personal data, you may use the XML entities on `info/1` documenting directives. For example, assuming that the XML entities are named author, license, and copyright we may write:

    :- info([
        version is 1:1:0,
        author is {author},
        license is {license},
        copyright is {copyright}
    ]).

The entity references are replaced by the value of the corresponding XML entity when the XML documenting files are processed (not when they are generated; this notation is just a shortcut to take advantage of XML entities).

The lgtdoc tool supports a set of options that can be used to control the generation of the XML documentation files. See the tool documentation for details. There is also a doclet tool that allows automating the steps required to generate the documentation for an application.

## Inline formatting in comments text

Inline formatting in comments text can be accomplished by using Markdown or reStructuredText syntax and converting XML documenting files to Markdown or reStructuredText files (and these, if required, to e.g. HTML, ePub, or PDF formats). Note that Markdown and reStructuredText common syntax elements are enough for most API documentation:

    Mark *italic text* with one asterisk.
    Mark **bold text** with two asterisks.
    Mark ``monospaced text`` with two backquotes.

Rendering this block as markup gives:

> Mark italic text with one asterisk. Mark bold text with two asterisks. Mark `monospaced text` with two backquotes.

As single backquotes have different purposes in Markdown (monospaced text) and reStructuredText (domain- or application-dependent meaning), never use them. This also avoids doubts if there’s an inline formatting typo in text meant to be rendered as monospaced text (usually inline code fragments).

## Diagrams

The diagrams tool supports a wide range of diagrams that can also help in documenting an application. The generated diagrams can include URL links to both source code and API documentation. They can also be linked, connecting, for example, high level diagrams to detail diagrams. These features allow diagrams to be an effective solution for navigating and understanding the structure and implementation of an application. This tool uses the same reflection API as the `lgtdoc` tool and thus has access to the same source data. See the tool documentation for details.