.. imprint: a program for creating documents from data and content templates

.. Copyright (C) 2019  Joseph R. Fox-Rabinovitz <jfoxrabinovitz at gmail dot com>

.. This program is free software: you can redistribute it and/or modify
.. it under the terms of the GNU Affero General Public License as
.. published by the Free Software Foundation, either version 3 of the
.. License, or (at your option) any later version.

.. This program is distributed in the hope that it will be useful,
.. but WITHOUT ANY WARRANTY; without even the implied warranty of
.. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
.. GNU Affero General Public License for more details.

.. Author: Joseph Fox-Rabinovitz <jfoxrabinovitz at gmail dot com>
.. Version: 13 Apr 2019: Initial Coding


.. _keywords:

========
Keywords
========

The :ref:`engine <introduction-layers-engine>` is configured through the
:ref:`configuration-ipc` and the :ref:`configuration-iif` it includes. These
files supply a set of keywords associated with values. There are two types of
keywords: :ref:`keywords-system` and :ref:`keywords-user`.


.. _keywords-toc:

.. contents:: Contents
   :depth: 2
   :local:


.. _keywords-system:

---------------
System Keywords
---------------

System keywords configure the behavior of the
:ref:`engine <introduction-layers-engine>` and
:ref:`plugins <introduction-layers-plugins>`. System keywords are
conventionally identified by the lowercase_with_underscore naming scheme.

Most system keywords are optional, with sensible defaults used in case they are
omitted. There are a few mandatory keywords that will result in an error if
they are not supplied:

- :ref:`keywords-system-data_config`
  Required for all documents that use :doc:`plugins <plugin_api>`.
- :ref:`keywords-system-input_xml`
- :ref:`keywords-system-output_docx`

The following is a complete listing of known system keywords. Custom tags and
plugins may define additional keywords (or use existing ones for their own
purposes).


.. _keywords-system-caption_counter_depth:

``caption_counter_depth``
=========================

The number of elements to include in the caption of a generated figure, table
or heading reference before the object number. For example, say we have a
figure that is the second figure under heading 1.2.3. Let's also say that it is
the fifth figure under heading 1.2 and the 10th in the first section. In that
case, the following table shows the resulting reference captions for different
values of this keyword:

+-----------------------+---------------+
| caption_counter_depth | caption       |
+=======================+===============+
|                  None |   1.2.3-2     |
+-----------------------+---------------+
|                     0 |   10          |
+-----------------------+---------------+
|                     1 |   1-10        |
+-----------------------+---------------+
|                     2 |   1.2-5       |
+-----------------------+---------------+
|                    3+ |   1.2.3-2     |
+-----------------------+---------------+

This keyword is optional. It defaults to 1.


.. _keywords-system-data_config:

``data_config``
===============

The name of the :ref:`configuration-idc` that configures the entire
:ref:`introduction-layers-plugins`.

This keyword is mandatory if the :ref:`configuration-xml` specifies content
generated by plugins, and completely ignored otherwise.


.. _keywords-system-date:

``date``
========

This keyword has no special meaning. However, it is implicitly set to the
result of :py:meth:`datetime.datetime.now` when headers and footers are
processed, if not set explicitly to something else. This makes it simpler to
include information about the time of generation into the
:ref:`configuration-docx-headers-footers`. The implicitly-defined value is not
available at any point besides the final keyword replacement step for
:ref:`configuration-docx-headers-footers`.

This keyword is optional.


.. _keywords-system-file_level:

``file_level``
==============

The minimum cutoff level to dump to the file. To dump everything to the file
use ``logging.NOTSET``, ``0``, or ``1``. The value can be a (case insensitive)
string level name, a number or one of the constants in the :py:mod:`logging`
module.

If :ref:`keywords-system-log_file` is missing, this level will be ignored and
nothing will be written to a file.

This keyword is optional. It defaults to ``logging.NOTSET``.

.. seealso:: :ref:`Logging Configuration <logging-configuration>`


.. _keywords-system-includes:

``includes``
============

A sequence of :ref:`include file <configuration-iif>` names. Include files can
only add new keywords to the existing configuration. They do not overwrite any
keywords that are already set. It is therefore important that include files are
loaded in breadth-first order in the order that they appear in the sequence.

This keyword is optional.


.. _keywords-system-input_docx:

``input_docx``
==============

The name of the :ref:`configuration-docx` to use as a style and formatting
template in the :ref:`introduction-layers-template`. All the styles referenced
explicitly by the :ref:`configuration-xml` and implicitly in the
:ref:`future-work-user-defaults` must be present in this file. This file must
also contain all the required formatting for
:ref:`configuration-docx-headers-footers`.

This keyword is optional. The default is the empty document provided by
`python-docx`_.


.. _keywords-system-input_xml:

``input_xml``
=============

The name of the :ref:`configuration-xml` file to use a content and layout
template in the :ref:`introduction-layers-template`. This template must follow
the specification laid out in :doc:`xml_spec`. It may contain additional tags,
loaded through the :ref:`keywords-system-tags` mapping.

This keyword is mandatory.


.. _keywords-system-log_file:

``log_file``
============

The name of the output file to write to. All messages with level greater than
or equal to :ref:`keywords-system-file_level` will be written to the named
file.

If boolean :py:obj:`True`, a file with the same name as
:ref:`keywords-system-output_docx`, but with a ``.log`` extension will be
created.

This keyword is optional. If omitted, a log file will not be written, and
:ref:`keywords-system-file_level` is ignored.

.. seealso:: :ref:`Logging Configuration <logging-configuration>`


.. _keywords-system-log_format:

``log_format``
==============

A string that determines the contents of each line of the log file. The format
of this string is the same as for the `fmt` attribute of a
:py:class:`logging.Formatter`. It uses ``%`` interpolation syntax, with all the
:py:class:`logging.LogRecord` attributes as valid keyword replacements.

This keyword is optional. If omitted, the log message will be formatted
according to ``'%(asctime)s - %(name)s - %(levelname)s - %(message)s'``.

.. seealso:: :ref:`Logging Configuration <logging-configuration>`


.. _keywords-system-log_images:

``log_images``
==============

Whether or not to log images in separate files, in addition to inserting them
into the document. Evaluated as a boolean, regardless of the actual type of the
value. It is up to individual tag handlers to respect this setting. This
setting is independent of the other logger settings.

This keyword is optional. If omitted, it normally defaults to falsy, but custom
tags may chose to interpret it differently.

.. seealso:: :ref:`Image Logging <logging-images>`


.. _keywords-system-log_stderr:

``log_stderr``
==============

Whether or not to print log output to the standard error stream. Evaluated as a
boolean, regardless of the actual type of the value. If truthy, all messages
with level greater than or equal to :ref:`keywords-system-stderr_level` are
written to standard error.

This keyword is optional. If omitted, it defaults to falsy, and
:ref:`keywords-system-stderr_level` is ignored.

.. seealso:: :ref:`Logging Configuration <logging-configuration>`


.. _keywords-system-log_stdout:

``log_stdout``
==============

Whether or not to print log output to the standard output stream. Evaluated as
a boolean, regardless of the actual type of the value. If truthy, all messages
with level greater than or equal to :ref:`keywords-system-stdout_level` are
written to standard error.

If falsy, :ref:`keywords-system-stdout_level` is ignored.

If :ref:`keywords-system-log_stderr` is set to truthy along with this keyword,
then messages with a logging level greater than or equal to
:ref:`keywords-system-stderr_level` will not be sent to standard output.

This keyword is optional. It defaults to truthy.

.. seealso:: :ref:`Logging Configuration <logging-configuration>`


.. _keywords-system-output_docx:

``output_docx``
===============

The name of the generated document. If a file with the same name already
exists, the program's behavior is determined by the
:ref:`keywords-system-overwrite_output` keyword.

This keyword is mandatory.


.. _keywords-system-overwrite_output:

``overwrite_output``
====================

Determines how to handle the case where the file named by
:ref:`keywords-system-output_docx` already exists. The following options are
recognized:

    ``'raise'``
        Raise an error and abort.
    ``'rename'``
        Keep prompting the user for a new file name until they select one that
        does not already exist. A default suggestion is generated, which can be
        selected automatically.
    ``'silent'``
        Overwrite the existing file without further comment.
    ``'warn'``
        Overwrite the existing file, but with a warning.

Any other value will trigger a :term:`fatal error`.

This keyword is optional. It defaults to ``'raise'``.


.. _keywords-system-stderr_level:

``stderr_level``
================

The minimum threshold for messages that go to the standard error stream. This
acts as an (exclusive) upper threshold for messages sent to the standard output
stream as well. This level does not affect the level being logged to the file.
The value can be a (case insensitive) string level name, a number or one of the
constants in the :py:mod:`logging` module.

If :ref:`keywords-system-log_stderr` is missing or falsy, this level will be
ignored.

This keyword is optional. It defaults to ``logging.ERROR``.

.. seealso:: :ref:`Logging Configuration <logging-configuration>`


.. _keywords-system-stdout_level:

``stdout_level``
================

The minimum threshold for messages that go to the standard output stream. This
level does not affect the level being logged to the file. The value can be a
(case insensitive) string level name, a number or one of the constants in the
:py:mod:`logging` module.

If :ref:`keywords-system-log_stderr` is truthy,
:ref:`keywords-system-stderr_level` provides the exclusive upper threshold for
messages sent to standard output.

If :ref:`keywords-system-log_stdout` is falsy, this level will be ignored.

This keyword is optional. It defaults to ``logging.WARNING``.

.. seealso:: :ref:`Logging Configuration <logging-configuration>`


.. _keywords-system-tags:

``tags``
========

Sets up user-defined tags for the :ref:`configuration-xml`. This is a mapping of
tag names to user-defined :ref:`tag-api-descriptors`. Values may be strings
containing the fully-qualified names of the object to import, or the objects
themselves. Both of the values in the following example are valid::

    import my.custom.module

    tags = {
        'tag1': my.cusom.module.descriptor,
        'tag2': 'my.custom.module.descriptor',
    }

This keyword is optional.


.. _keywords-user:

---------------------
User-Defined Keywords
---------------------

User-defined keywords provide the data used to perform keyword replacements for
the :ref:`xml-spec-tags-kwd` tags in the :ref:`configuration-xml`. They provide
the per-report configuration of the basic content. User-defined keywords are
conventionally identified by a CamelCase naming scheme. While the naming is not
strictly a requirement, any lowercase_and_underscore name is automatically
reserved for use as a :ref:`system keyword <keywords-system>`.


.. _keywords-user-expr:

Computed Keywords
=================

In addition to direct definition in the :ref:`configuration-ipc` /
:ref:`configuration-iif` and insertion via the :ref:`xml-spec-tags-kwd` tag,
keywords can be computed through the :ref:`xml-spec-tags-expr` tag in the
:ref:`configuration-xml`. The namespace in which an :ref:`xml-spec-tags-expr`
tag is evaluated is the existing mapping of keywords defined up to that point.
The result is a new user-defined keyword. System keywords placed in an
:ref:`xml-spec-tags-expr` tag are not guaranteed to work correctly. This form of
computation is provided to de-clutter the :ref:`configuration-ipc`, and avoid
information redundancy in the frequently edited file.


.. include:: /link-defs.rst
