Bug #1921348: English text in code block. Many other cleanup, spelling, and grammar changes.

This commit is contained in:
Charles Haley 2021-03-25 13:05:02 +00:00
parent 530ca249b5
commit c2a25a8bd1
2 changed files with 277 additions and 262 deletions

View File

@ -11,7 +11,7 @@ The calibre template language is a calibre-specific language used throughout cal
* Advanced library searching.
* Advanced metadata search and replace.
The language is built around the notion of a `template`, which specifies computations on book metadata and how it is to be formatted.
The language is built around the notion of a `template`, which specifies which book metadata to use, computations on that metadata, and how it is to be formatted.
Basic Templates
---------------
@ -24,7 +24,7 @@ For the book "The Foundation" by "Isaac Asimov" the will become::
Asimov, Isaac/The Foundation/The Foundation - Isaac Asimov
The slashes are not ``template expressions`` because they are not enclosed in ``{}``. Such text is left where it appears. For example, if the template is::
The slashes are not ``template expressions`` because they are in between in ``{}``. Such text is left where it appears. For example, if the template is::
{author_sort} Some Important Text {title}/{title} - {authors}
@ -32,12 +32,12 @@ then for "The Foundation" the template produces::
Asimov, Isaac Some Important Text The Foundation/The Foundation - Isaac Asimov
A ``template expression`` can access all the metadata available in calibre, including custom columns (columns you create yourself), by using a columns's ``lookup name``. To find the lookup name for a `column` (sometimes called `fields`), hover your mouse over the column header in calibre's book list. Lookup names for custom columns always begin with ``#``. For series type columns there is an additional field named ``#lookup name_index`` that is the series index for that book in the series. For example, if you have a custom series column named ``#myseries``, there will also be a column named ``#myseries_index``. The standard series column's index is named ``series_index``.
A ``template expression`` can access all the metadata available in calibre, including custom columns (columns you create yourself), by using a column's ``lookup name``. To find the lookup name for a `column` (sometimes called `fields`), hover your mouse over the column header in calibre's book list. Lookup names for custom columns always begin with ``#``. For series type columns there is an additional field named ``#lookup name_index`` that is the series index for that book in the series. For example, if you have a custom series column named ``#myseries``, there will also be a column named ``#myseries_index``. The standard series column's index is named ``series_index``.
In addition to the standard column based fields, you also can use::
In addition to the standard column based fields, you also can use:
{formats} - A list of formats available in the calibre library for a book
{identifiers:select(isbn)} - The ISBN of the book
* ``{formats}`` - A list of formats available in the calibre library for a book
* ``{identifiers:select(isbn)}`` - The ISBN of the book
If the metadata for field for a given a book is not defined then the field in the template is replaced by the empty string (``''``). For example, consider the following template::
@ -70,7 +70,7 @@ This template produces that output::
{series} - {series_index} - {title}
However, if a book has no series the template will produce ``- - title``, which is probably not what is wished. Most people would prefer the result be ``title``, without the extraneous hyphens. You can accomplish this using the following template syntax::
However, if a book has no series the template will produce ``- - title``, which is probably not what you want. Generally, people want the result be the title without the extraneous hyphens. You can accomplish this using the following template syntax::
{field:|prefix_text|suffix_text}
@ -110,15 +110,15 @@ If you want only the first two letters of the data, use:
``{author_sort:.2}`` - Only the first two letters of the author sort name
Much of the calibre template language comes from Python. For more details on the syntax of these advanced formatting operations see the `Python documentation <https://docs.python.org/3/library/string.html#formatstrings>`_.
Much of the calibre template language formatting comes from Python. For more details on the syntax of these advanced formatting operations see the `Python documentation <https://docs.python.org/3/library/string.html#formatstrings>`_.
Using templates to define custom columns
-----------------------------------------
Templates are used to display information that isn't in calibre metadata, or to display metadata differently from calibre's normal format. For example, you might want to show the ``ISBN``, a field that calibre does not display. You can accomplish this creating a custom column with the type `Column built from other columns` (hereafter called composite columns) and providing a template to generate the displayed text. The column will display the result of evaluating the template. For example, to display the ISBN, create the column and enter ``{identifiers:select(isbn)}`` into the template box. To display a column containing the values of two series custom columns, separated by a comma, use ``{#series1:||,}{#series2}``.
Templates can be used to display information that isn't in calibre metadata, or to display metadata differently from calibre's normal format. For example, you might want to show the ``ISBN``, a field that calibre does not display. You can accomplish this creating a custom column with the type `Column built from other columns` (hereafter called `composite columns`) and providing a template to generate the displayed text. The column will display the result of evaluating the template. For example, to display the ISBN, create the column and enter ``{identifiers:select(isbn)}`` in the template box. To display a column containing the values of two series custom columns, separated by a comma, use ``{#series1:||,}{#series2}``.
Composite columns can use any template option including formatting.
Composite columns can use any template option, including formatting.
Note: You cannot edit the data displayed in a composite column. Instead you edit the source columns. If you edit a composite column, for example by double-clicking it, calibre will open the template for editing, not the underlying data.
@ -148,7 +148,7 @@ Functions are evaluated before format specifications and the prefix/suffix. See
Some functions require regular expressions. In the template language regular expression matching is case-insensitive.
In the function documentation below, the notation ``[something]*`` means that `something` can be repeated zero or more times. The notation ``[something]+`` means that the `something` is repeated one or more times (must exist at least one time).
In the function documentation below, the notation ``[something]*`` means that ``something`` can be repeated zero or more times. The notation ``[something]+`` means that the ``something`` is repeated one or more times (must exist at least one time).
The functions intended for use in Single Function Mode are:
@ -171,23 +171,26 @@ The functions intended for use in Single Function Mode are:
* ``str_in_list(separator, [ string, found_val, ]+ not_found_val)`` -- interpret the value as a list of items separated by ``separator`` then compare ``string`` against each value in the list. The ``string`` is not a regular expression. If ``string`` is equal to any item (ignoring case) then return the corresponding ``found_val``. If ``string`` contains ``separators`` then it is also treated as a list and each subvalue is checked. The ``string`` and ``found_value`` pairs can be repeated as many times as desired, permitting returning different values depending on string's value. If none of the strings match then ``not_found_value`` is returned. The strings are checked in order. The first match is returned.
* ``subitems(start_index, end_index)`` -- This function breaks apart lists of tag-like hierarchical items such as genres. It interprets the value as a comma-separated list of tag-like items, where each item is a period-separated list. It returns a new list made by extracting from each item the components from ``start_index`` to ``end_index``, then merging the results back together. Duplicates are removed. The first subitem in a period-separated list has an index of zero. If an index is negative then it counts from the end of the list. As a special case, an end_index of zero is assumed to be the length of the list.
Examples::
Examples:
* Assuming a #genre column containing `A.B.C`:
* ``{#genre:subitems(0,1)}`` returns "A"
* ``{#genre:subitems(0,2)}`` returns "A.B"
* ``{#genre:subitems(1,0)}`` returns "B.C"
* Assuming a #genre column containing "A.B.C"
{#genre:subitems(0,1)} returns "A"
{#genre:subitems(0,2)} returns "A.B"
{#genre:subitems(1,0)} returns "B.C"
* Assuming a #genre column containing "A.B.C, D.E":
{#genre:subitems(0,1)} returns "A, D"
{#genre:subitems(0,2)} returns "A.B, D.E"
* ``{#genre:subitems(0,1)}`` returns "A, D"
* ``{#genre:subitems(0,2)}`` returns "A.B, D.E"
* ``sublist(start_index, end_index, separator)`` -- interpret the value as a list of items separated by ``separator``, returning a new list made from the items from ``start_index`` to ``end_index``. The first item is number zero. If an index is negative, then it counts from the end of the list. As a special case, an end_index of zero is assumed to be the length of the list.
Examples assuming that the tags column (which is comma-separated) contains "A, B ,C"::
Examples assuming that the tags column (which is comma-separated) contains "A, B ,C":
{tags:sublist(0,1,\,)} returns "A"
{tags:sublist(-1,0,\,)} returns "C"
{tags:sublist(0,-1,\,)} returns "A, B"
* ``{tags:sublist(0,1,\,)}`` returns "A"
* ``{tags:sublist(-1,0,\,)}`` returns "C"
* ``{tags:sublist(0,-1,\,)}`` returns "A, B"
* ``swap_around_articles(separator)`` -- returns the value with articles moved to the end. The value can be a list, in which case each item in the list is processed. If the value is a list then you must provide the ``separator``. If no ``separator`` is provided then the value is treated as being a single value, not a list. The `articles` are those used by calibre to generate the ``title_sort``.
* ``swap_around_comma()`` -- given a value of the form ``B, A``, return ``A B``. This is most useful for converting names in LN, FN format to FN LN. If there is no comma in the value then the function returns the value unchanged.
@ -199,7 +202,7 @@ The functions intended for use in Single Function Mode are:
**Using functions and formatting in the same template**
Suppose you have an integer custom column ``#myint`` that you want displayed with leading zeros, as in ``003``. To do this, you would use a format of ``0>3s``. However, by default if a number (integer or float) equals zero then the value is displayed as the empty string so zero values will produce the empty string, not ``000``. If you want to see ``000`` values then you use both the format string and the ``ifempty`` function to change the empty value back to a zero. The template would be::
Suppose you have an integer custom column ``#myint`` that you want displayed with leading zeros, as in ``003``. One way to do this is to use a format of ``0>3s``. However, by default if a number (integer or float) equals zero then the value is displayed as the empty string so zero values will produce the empty string, not ``000``. If you want to see ``000`` values then you use both the format string and the ``ifempty`` function to change the empty value back to a zero. The template would be::
{#myint:0>3s:ifempty(0)}
@ -212,7 +215,7 @@ Note that you can use the prefix and suffix as well. If you want the number to a
General Program Mode
-----------------------------------
`General Program Mode` (`GPM`) replaces the template with a program written in the `template language`. The syntax of the language is defined by the following grammar::
`General Program Mode` (`GPM`) replaces `template expressions` with a program written in the `template language`. The syntax of the language is defined by the following grammar::
program ::= 'program:' expression_list
expression_list ::= top_expression [ ';' top_expression ]*
@ -246,31 +249,32 @@ General Program Mode
list_expression ::= top_expression
separator_expr ::= top_expression
Comments are lines with a '#' character at the beginning of the line. Comments beginning later in the line are not supported.
Notes:
A ``top_expression`` always has a value. The value of an ``expression_list`` is the value
of the last ``top_expression`` in the list. For example the value of the following ``expression_list``::
1; 2; 'foobar'; 3
is 3.
* a ``top_expression`` always has a value. The value of an ``expression_list`` is the value of the last ``top_expression`` in the list. For example, the value of the expression list ``1;2;'foobar';3`` is ``3``.
* In a logical context, any non-empty value is ``True``
* In a logical context, the empty value is ``False``
* Strings and numbers can be used interchangeably. For example, ``10`` and ``'10'`` are the same thing.
* Comments are lines starting with a '#' character. Comments beginning later in a line are not supported.
**Operator Precedence**
The operator precedence (order of evaluation) specified by the above grammar, from highest to lowest is:
The operator precedence (order of evaluation) from highest (evaluated first) to lowest (evaluated last) is:
* Function calls, constants, parenthesized expressions, statement expressions, assignment expressions, field references.
* Unary plus (``+``) and minus (``-``). These operators evaluate right to left. These and all the other arithmetic operators return integers if the expression results in a fractional part equal to zero. Example: if an expression returns ``3.0`` it is changed to ``3``.
* Unary plus (``+``) and minus (``-``). These operators evaluate right to left.
These and all the other arithmetic operators return integers if the expression results in a fractional part equal to zero. For example, if an expression returns ``3.0`` it is changed to ``3``.
* Multiply (``*``) and divide (``/``). These operators are associative and evaluate left to right. Use parentheses if you want to change the order of evaluation.
* Add (``+``) and subtract (``-``). These operators are associative and evaluate left to right.
* Numeric and string comparisons. These operators return ``1`` (the number one) if the comparison is True (a non-empty string), otherwise the empty string (``''``). Comparisons are not associative: ``a < b < c`` is a syntax error.
* Unary logical not (``!``). This operator returns '1' if the expression is False (evaluates to the empty string), otherwise ``''``.
* Numeric and string comparisons. These operators return ``'1'`` if the comparison succeeds, otherwise the empty string (``''``). Comparisons are not associative: ``a < b < c`` is a syntax error.
* Unary logical not (``!``). This operator returns ``'1'`` if the expression is False (evaluates to the empty string), otherwise ``''``.
* Logical and (``&&``). This operator returns '1' if both the left-hand and right-hand expressions are True, or the empty string ``''`` if either is False. It is associative, evaluates left to right, and does `short-circuiting <https://chortle.ccsu.edu/java5/Notes/chap40/ch40_2.html>`_.
* Logical or (``||``). This operator returns ``'1'`` if either the left-hand or right-hand expression is True, or ``''`` if both are False. It is associative, evaluates left to right, and does short-circuiting. The operator is an inclusive or, returning '1' if both the left- and right-hand expressions are True.
* Logical or (``||``). This operator returns ``'1'`` if either the left-hand or right-hand expression is True, or ``''`` if both are False. It is associative, evaluates left to right, and does `short-circuiting <https://chortle.ccsu.edu/java5/Notes/chap40/ch40_2.html>`_. It is an `inclusive or`, returning ``'1'`` if both the left- and right-hand expressions are True.
**Field References**
A ``field_reference`` evaluates to the value of the metadata field named by lookup key that follows the ``$`` or ``$$``. Using ``$`` is equivalent to using the ``field()`` function. Using ``$$`` is equivalent to using the ``raw_field`` function. Examples::
A ``field_reference`` evaluates to the value of the metadata field named by lookup name that follows the ``$`` or ``$$``. Using ``$`` is equivalent to using the ``field()`` function. Using ``$$`` is equivalent to using the ``raw_field`` function. Examples::
* $authors ==> field('authors')
* $#genre ==> field('#genre')
@ -279,7 +283,7 @@ A ``field_reference`` evaluates to the value of the metadata field named by look
**If Expressions**
``If`` expressions first evaluate the ``condition``, which is True if it evaluates to anything other than the empty string. If the ``condition`` is True then the ``expression_list`` in the ``then`` clause is evaluated. If it is False then the ``expression_list`` in the ``elif`` or ``else`` clause is evaluated if present. The ``elif`` and ``else`` parts are optional. The words ``if``, ``then``, ``elif``, ``else``, and ``fi`` are reserved; you cannot use them as identifier names. You can put newlines and white space wherever they make sense. The ``condition`` is a ``top_expression`` not an ``expression_list``; semicolons are not allowed. The ``expression_lists`` are semicolon-separated sequences of template language top_expressions. An ``if`` expression returns the result of the last ``top_expression`` in the evaluated ``expression_list``, or '' if no expression list was evaluated.
``If`` expressions first evaluate the ``condition``. If the ``condition`` is True (a non-empty value) then the ``expression_list`` in the ``then`` clause is evaluated. If it is False then if present the ``expression_list`` in the ``elif`` or ``else`` clause is evaluated. The ``elif`` and ``else`` parts are optional. The words ``if``, ``then``, ``elif``, ``else``, and ``fi`` are reserved; you cannot use them as identifier names. You can put newlines and white space wherever they make sense. The ``condition`` is a ``top_expression`` not an ``expression_list``; semicolons are not allowed. The ``expression_lists`` are semicolon-separated sequences of ``top_expressions``. An ``if`` expression returns the result of the last ``top_expression`` in the evaluated ``expression_list``, or the empty string if no expression list was evaluated.
Examples::
@ -293,7 +297,8 @@ Examples::
b = 'yes'
fi;
strcat(a, '-', b)
* Nested ``if`` example::
Nested ``if`` example::
program:
if field('series') then
@ -312,13 +317,13 @@ As said above, an ``if`` produces a value. This means that all the following are
* program: if field('series') then a = 'foo' else a = 'bar' fi; a
* program: a = if field('series') then 'foo' else 'bar' fi; a
As a last example, this program returns the value of the ``series`` column if the book has a series, otherwise the value of the ``title``::
As a last example, this program returns the value of the ``series`` column if the book has a series, otherwise the value of the ``title`` column::
program: field(if field('series') then 'series' else 'title' fi)
**For Expressions**
The ``for`` expression iterates of a list of values, processing them one at a time. The ``list_expression`` must evaluate to either a metadata field ``lookup name``, for example ``tags`` or ``#genre``, or a list of values. If the result is a valid ``lookup name`` then the field's value is fetched and the separator specified for that field type is used. If the result isn't a valid lookup name then it is assumed to be a list of values. The list is assumed to be separated by commas unless the optional keyword ``separator`` is supplied, in which case the list values must be separated by the result of evaluating the ``separator_expr``. Each value in the list is assigned to the variable ``id`` then the ``expression_list`` is evaluated.
The ``for`` expression iterates over a list of values, processing them one at a time. The ``list_expression`` must evaluate to either a metadata field ``lookup name``, for example ``tags`` or ``#genre``, or a list of values. If the result is a valid ``lookup name`` then the field's value is fetched and the separator specified for that field type is used. If the result isn't a valid lookup name then it is assumed to be a list of values. The list is assumed to be separated by commas unless the optional keyword ``separator`` is supplied, in which case the list values must be separated by the result of evaluating the ``separator_expr``. Each value in the list is assigned to the specified variable then the ``expression_list`` is evaluated.
Example: This template removes the first hierarchical name for each value in Genre (``#genre``), constructing a list with the new names::
@ -337,9 +342,11 @@ Note: the last line in the template, ``new_tags``, isn't strictly necessary in t
**Relational Operators**
Relational operators return ``'1'`` if they evaluate to True, otherwise the empty string ('').
Relational operators return ``'1'`` if the comparison is true, otherwise the empty string ('').
There are two forms of relational operators: string comparisons and numeric comparisons. The string comparisons do case-insensitive string comparison using lexical order. The supported string comparison operators are ``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``, and ``in``.
There are two forms of relational operators: string comparisons and numeric comparisons.
String comparisons do case-insensitive string comparison using lexical order. The supported string comparison operators are ``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``, and ``in``.
For the ``in`` operator, the result of the left hand expression is interpreted as a regular expression pattern. The ``in`` operator is True if the value of left-hand expression interpreted as a regular expression matches the value of the right hand expression. The match is case-insensitive.
The numeric comparison operators are ``==#``, ``!=#``, ``<#``, ``<=#``, ``>#``, ``>=#``. The left and right expressions must evaluate to numeric values with two exceptions: both the string value "None" (undefined field) and the empty string evaluate to the value zero.
@ -348,11 +355,11 @@ Examples:
* ``program: field('series') == 'foo'`` returns ``'1'`` if the book's series is 'foo', otherwise ``''``.
* ``program: 'f.o' in field('series')`` returns ``'1'`` if the book's series matches the regular expression ``f.o`` (e.g., `foo`, `Off Onyx`, etc.), otherwise ``''``.
* ``program: if field('series') != 'foo' then 'bar' else 'mumble' fi`` returns ``bar`` if the book's series is not ``foo``, else ``mumble``.
* ``program: if field('series') == 'foo' || field('series') == '1632' then 'yes' else 'no' fi`` returns ``yes`` if series is either `foo` or `1632`, otherwise ``no``.
* ``program: if '^(foo|1632)$' in field('series') then 'yes' else 'no' fi`` returns 'yes' if series is either `foo` or `1632`, otherwise 'no'.
* ``program: if 11 > 2 then 'yes' else 'no' fi`` returns `no` because it does a lexical comparison.
* ``program: if 11 ># 2 then 'yes' else 'no' fi`` returns `yes` because it does a numeric comparison.
* ``program: if field('series') != 'foo' then 'bar' else 'mumble' fi`` returns ``'bar'`` if the book's series is not ``foo``. Otherwise it returns ``'mumble'``.
* ``program: if field('series') == 'foo' || field('series') == '1632' then 'yes' else 'no' fi`` returns ``'yes'`` if series is either ``'foo'`` or ``'1632'``, otherwise ``'no'``.
* ``program: if '^(foo|1632)$' in field('series') then 'yes' else 'no' fi`` returns ``'yes'`` if series is either ``'foo'`` or ``'1632'``, otherwise ``'no'``.
* ``program: if 11 > 2 then 'yes' else 'no' fi`` returns ``'no'`` because the ``>`` operator does a lexical comparison.
* ``program: if 11 ># 2 then 'yes' else 'no' fi`` returns ``'yes'`` because the ``>#`` operator does a numeric comparison.
**Additional Available Functions**
@ -364,18 +371,18 @@ In `GPM` the functions described in `Single Function Mode` all require an additi
* ``and(value [, value]*)`` -- returns the string "1" if all values are not empty, otherwise returns the empty string. You can have as many values as you want. In most cases you can use the ``&&`` operator instead of this function. One reason not to replace ``and`` with ``&&`` is if short-circuiting can change the results because of side effects. For example, ``and(a='',b=5)`` will always do both assignments, where the ``&&`` operator won't do the second.
* ``assign(id, val)`` -- assigns ``val`` to ``id``, then returns ``val``. ``id`` must be an identifier, not an expression. In most cases you can use the ``=`` operator instead of this function.
* ``approximate_formats()`` -- return a comma-separated list of formats associated with the book. There is no guarantee that the list is correct, although it probably is. This and other zero-parameter functions can be called in Template Program Mode (see below) using the template ``{:'approximate_formats()'}``. Note that resulting format names are always uppercase, as in EPUB. The ``approximate_formats()`` function is significantly faster than the ``formats_...`` functions discussed below.
* ``author_links(val_separator, pair_separator)`` -- returns a string containing a list of authors and those authors' link values in the form:
* ``author_links(val_separator, pair_separator)`` -- returns a string containing a list of authors and those authors' link values in the form::
``author1 val_separator author1_link pair_separator author2 val_separator author2_link`` etc.
author1 val_separator author1_link pair_separator author2 val_separator author2_link etc.
An author is separated from its link value by the ``val_separator`` string with no added spaces. ``author:linkvalue`` pairs are separated by the ``pair_separator`` string argument with no added spaces. It is up to you to choose separator strings that do not occur in author names or links. An author is included even if the author link is empty.
* ``author_sorts(val_separator)`` -- returns a string containing a list of author's sort values for the authors of the book. The sort is the one in the author metadata information (different from the author_sort in books). The returned list has the form ``author sort 1`` ``val_separator`` ``author sort 2`` etc. with no added spaces. The author sort values in this list are in the same order as the authors of the book. If you want spaces around ``val_separator`` then include them in the ``val_separator`` string.
* ``booksize()`` -- returns the value of the calibre 'size' field. Returns '' if there are no formats.
* ``check_yes_no(field_name, is_undefined, is_false, is_true)`` -- checks if the value of the yes/no field named by the lookup name ``field_name`` is one of the values specified by the parameters, returning ``'yes'`` if a match is found otherwise returning the empty string. Set the parameter ``is_undefined``, ``is_false``, or ``is_true`` to 1 (the number) to check that condition, otherwise set it to 0. Example::
* ``check_yes_no(field_name, is_undefined, is_false, is_true)`` -- checks if the value of the yes/no field named by the lookup name ``field_name`` is one of the values specified by the parameters, returning ``'yes'`` if a match is found otherwise returning the empty string. Set the parameter ``is_undefined``, ``is_false``, or ``is_true`` to 1 (the number) to check that condition, otherwise set it to 0. Example:
check_yes_no("#bool", 1, 0, 1)
``check_yes_no("#bool", 1, 0, 1)`` returns ``'yes'`` if the yes/no field ``#bool`` is either True or undefined (neither True nor False).
returns ``'yes'`` if the yes/no field ``"#bool"`` is either undefined (neither True nor False) or True. More than one of ``is_undefined``, ``is_false``, or ``is_true`` can be set to 1.
More than one of ``is_undefined``, ``is_false``, or ``is_true`` can be set to 1.
* ``ceiling(x)`` -- returns the smallest integer greater than or equal to ``x``. Throws an exception if ``x`` is not a number.
* ``cmp(x, y, lt, eq, gt)`` -- compares ``x`` and ``y`` after converting both to numbers. Returns ``lt`` if ``x <# y``, ``eq`` if ``x ==# y``, otherwise ``gt``. This function can usually be replaced with one of the numeric compare operators (``==#``, ``<#``, ``>#``, etc).
* ``connected_device_name(storage_location_key)`` -- if a device is connected then return the device name, otherwise return the empty string. Each storage location on a device has its own device name. The ``storage_location_key`` names are ``'main'``, ``'carda'`` and ``'cardb'``. This function works only in the GUI.
@ -384,7 +391,7 @@ In `GPM` the functions described in `Single Function Mode` all require an additi
* ``current_library_path()`` -- return the full path to the current calibre library.
* ``days_between(date1, date2)`` -- return the number of days between ``date1`` and ``date2``. The number is positive if ``date1`` is greater than ``date2``, otherwise negative. If either ``date1`` or ``date2`` are not dates, the function returns the empty string.
* ``divide(x, y)`` -- returns ``x / y``. Throws an exception if either ``x`` or ``y`` are not numbers. This function can usually be replaced by the ``/`` operator.
* ``eval(string)`` -- evaluates the string as a program, passing the local variables. This permits using the template processor to construct complex results from local variables. In Template Program Mode (see below), because the `{` and `}` characters are interpreted before the template is evaluated you must use `[[` for the `{` character and `]]` for the ``}`` character. They are converted automatically. Note also that prefixes and suffixes (the `|prefix|suffix` syntax) cannot be used in the argument to this function when using Template Program Mode.
* ``eval(string)`` -- evaluates the string as a program, passing the local variables. This permits using the template processor to construct complex results from local variables. In :ref:`Template Program Mode <template_mode>`, because the `{` and `}` characters are interpreted before the template is evaluated you must use `[[` for the `{` character and `]]` for the ``}`` character. They are converted automatically. Note also that prefixes and suffixes (the `|prefix|suffix` syntax) cannot be used in the argument to this function when using :ref:`Template Program Mode <template_mode>`.
* ``field(lookup_name)`` -- returns the value of the metadata field with lookup name ``lookup_name``.
* ``field_exists(field_name)`` -- checks if a field (column) with the lookup name ``field_name`` exists, returning ``'1'`` if so and the empty string if not.
* ``finish_formatting(val, fmt, prefix, suffix)`` -- apply the format, prefix, and suffix to a value in the same way as done in a template like ``{series_index:05.2f| - |- }``. This function is provided to ease conversion of complex single-function- or template-program-mode templates to `GPM` Templates. For example, the following program produces the same output as the above template::
@ -402,35 +409,43 @@ In `GPM` the functions described in `Single Function Mode` all require an additi
* ``first_matching_cmp(val, [ cmp, result, ]* else_result)`` -- compares ``val < cmp`` in sequence, returning the associated result for the first comparison that succeeds. Returns else_result if no comparison succeeds. Example::
first_matching_cmp(10,5,"small",10,"middle",15,"large","giant")
i = 10;
first_matching_cmp(i,5,"small",10,"middle",15,"large","giant")
returns "large". The same example with a first value of 16 returns "giant".
returns ``"large"``. The same example with a first value of 16 returns ``"giant"``.
* ``first_non_empty(value [, value]*)`` -- returns the first ``value`` that is not empty. If all values are empty, then the empty string is returned. You can have as many values as you want.
* ``floor(x)`` -- returns the largest integer less than or equal to ``x``. Throws an exception if ``x`` is not a number.
* ``format_date(val, format_string)`` -- format the value, which must be a date string, using the format_string, returning a string. The formatting codes are::
* ``format_date(val, format_string)`` -- format the value, which must be a date string, using the format_string, returning a string. The formatting codes are:
d : the day as number without a leading zero (1 to 31)
dd : the day as number with a leading zero (01 to 31)
ddd : the abbreviated localized day name (e.g. "Mon" to "Sun").
dddd : the long localized day name (e.g. "Monday" to "Sunday").
M : the month as number without a leading zero (1 to 12).
MM : the month as number with a leading zero (01 to 12)
MMM : the abbreviated localized month name (e.g. "Jan" to "Dec").
MMMM : the long localized month name (e.g. "January" to "December").
yy : the year as two digit number (00 to 99).
yyyy : the year as four digit number.
h : the hours without a leading 0 (0 to 11 or 0 to 23, depending on am/pm)
hh : the hours with a leading 0 (00 to 11 or 00 to 23, depending on am/pm)
m : the minutes without a leading 0 (0 to 59)
mm : the minutes with a leading 0 (00 to 59)
s : the seconds without a leading 0 (0 to 59)
ss : the seconds with a leading 0 (00 to 59)
ap : use a 12-hour clock instead of a 24-hour clock, with 'ap' replaced by the localized string for am or pm.
AP : use a 12-hour clock instead of a 24-hour clock, with 'AP' replaced by the localized string for AM or PM.
iso : the date with time and timezone. Must be the only format present.
* ``d :`` the day as number without a leading zero (1 to 31)
* ``dd :`` the day as number with a leading zero (01 to 31)
* ``ddd :`` the abbreviated localized day name (e.g. "Mon" to "Sun").
* ``dddd :`` the long localized day name (e.g. "Monday" to "Sunday").
* ``M :`` the month as number without a leading zero (1 to 12).
* ``MM :`` the month as number with a leading zero (01 to 12)
* ``MMM :`` the abbreviated localized month name (e.g. "Jan" to "Dec").
* ``MMMM :`` the long localized month name (e.g. "January" to "December").
* ``yy :`` the year as two digit number (00 to 99).
* ``yyyy :`` the year as four digit number.
* ``h :`` the hours without a leading 0 (0 to 11 or 0 to 23, depending on am/pm)
* ``hh :`` the hours with a leading 0 (00 to 11 or 00 to 23, depending on am/pm)
* ``m :`` the minutes without a leading 0 (0 to 59)
* ``mm :`` the minutes with a leading 0 (00 to 59)
* ``s :`` the seconds without a leading 0 (0 to 59)
* ``ss :`` the seconds with a leading 0 (00 to 59)
* ``ap :`` use a 12-hour clock instead of a 24-hour clock, with 'ap' replaced by the localized string for am or pm.
* ``AP :`` use a 12-hour clock instead of a 24-hour clock, with 'AP' replaced by the localized string for AM or PM.
* ``iso :`` the date with time and timezone. Must be the only format present.
You might get unexpected results if the date you are formatting contains localized month names, which can happen if you changed the date format tweaks to contain ``MMMM``. In this case, instead of using the ``field()`` function as in::
format_date(field('pubdate'), 'yyyy')
use the ``raw_field()`` function as in::
format_date(raw_field('pubdate'), 'yyyy')
You might get unexpected results if the date you are formatting contains localized month names, which can happen if you changed the date format tweaks to contain ``MMMM``. In this case, instead of using something like ``format_date(field('pubdate'), 'yyyy')``, write the template using ``raw_field``, as in ``format_date(raw_field('pubdate'), 'yyyy')``.
* ``formats_modtimes(date_format_string)`` -- return a comma-separated list of colon-separated items ``FMT:DATE`` representing modification times for the formats of a book. The ``date_format_string`` parameter specifies how the date is to be formatted. See the ``format_date()`` function for details. You can use the ``select`` function to get the modification time for a specific format. Note that format names are always uppercase, as in EPUB.
* ``formats_paths()`` -- return a comma-separated list of colon-separated items ``FMT:PATH`` giving the full path to the formats of a book. You can use the select function to get the path for a specific format. Note that format names are always uppercase, as in EPUB.
* ``formats_sizes()`` -- return a comma-separated list of colon-separated ``FMT:SIZE`` items giving the sizes in bytes of the formats of a book. You can use the select function to get the size for a specific format. Note that format names are always uppercase, as in EPUB.
@ -448,6 +463,18 @@ In `GPM` the functions described in `Single Function Mode` all require an additi
* ``list_re_group(src_list, separator, include_re, search_re [, template_for_group]*)`` -- Like list_re except replacements are not optional. It uses ``re_group(item, search_re, template ...)`` when doing the replacements.
* ``list_remove_duplicates(list, separator)`` -- return a list made by removing duplicate items in ``list``. If items differ only in case then the last is returned. The items in ``list`` are separated by ``separator``, as are the items in the returned list.
* ``list_sort(list, direction, separator)`` -- return ``list`` sorted using a case-insensitive lexical sort. If ``direction`` is zero, ``list`` is sorted ascending, otherwise descending. The list items are separated by ``separator``, as are the items in the returned list.
* ``list_split(list_val, sep, id_prefix)`` -- splits ``list_val`` into separate values using ``sep``, then assigns the values to local variables named ``id_prefix_N`` where N is the position of the value in the list. The first item has position 0 (zero). The function returns the last element in the list.
Example::
list_split('one:two:foo', ':', 'var')
is equivalent to::
var_0 = 'one';
var_1 = 'two';
var_3 = 'foo
* ``list_union(list1, list2, separator)`` -- return a list made by merging the items in ``list1`` and ``list2``, removing duplicate items using a case-insensitive comparison. If items differ in case, the one in ``list1`` is used. The items in ``list1`` and ``list2`` are separated by ``separator``, as are the items in the returned list. Aliases: ``merge_lists()``, ``list_union()``
* ``mod(x, y)`` -- returns the ``floor`` of the remainder of ``x / y``. Throws an exception if either ``x`` or ``y`` is not a number.
* ``multiply(x [, y]*)`` -- returns the product of its arguments. Throws an exception if any argument is not a number. This function can usually be replaced by the ``*`` operator.
@ -457,7 +484,7 @@ In `GPM` the functions described in `Single Function Mode` all require an additi
* ``print(a [, b]*)`` -- prints the arguments to standard output. Unless you start calibre from the command line (``calibre-debug -g``), the output will go to a black hole. The ``print`` function always returns the empty string.
* ``raw_field(lookup_name [, optional_default])`` -- returns the metadata field named by ``lookup_name`` without applying any formatting. It evaluates and returns the optional second argument ``optional_default`` if the field's value is undefined (``None``).
* ``raw_list(lookup_name, separator)`` -- returns the metadata list named by ``lookup_name`` without applying any formatting or sorting, with the items separated by separator.
* ``re_group(value, pattern [, template_for_group]*)`` -- return a string made by applying the regular expression pattern to ``value`` and replacing each matched instance with the the value returned by the corresponding template. In Template Program Mode, like for the ``template`` and the ``eval`` functions, you use ``[[`` for ``{`` and ``]]`` for ``}``.
* ``re_group(value, pattern [, template_for_group]*)`` -- return a string made by applying the regular expression pattern to ``value`` and replacing each matched instance with the the value returned by the corresponding template. In :ref:`Template Program Mode <template_mode>`, like for the ``template`` and the ``eval`` functions, you use ``[[`` for ``{`` and ``]]`` for ``}``.
The following example looks for a series with more than one word and uppercases the first word::
@ -465,18 +492,6 @@ In `GPM` the functions described in `Single Function Mode` all require an additi
* ``round(x)`` -- returns the nearest integer to ``x``. Throws an exception if ``x`` is not a number.
* ``series_sort()`` -- returns the series sort value.
* ``split(list_val, sep, id_prefix)`` -- splits ``list_val`` into separate values using ``sep``, then assigns the values to local variables named ``id_prefix_N`` where N is the position of the value in the list. The first item has position 0 (zero). The function returns the last element in the list.
Example::
split('one:two:foo', ':', 'var')
is equivalent to::
var_0 = 'one';
var_1 = 'two';
var_3 = 'foo
* ``strcat(a [, b]*)`` -- can take any number of arguments. Returns a string formed by concatenating all the arguments.
* ``strcat_max(max, string1 [, prefix2, string2]*)`` -- Returns a string formed by concatenating the arguments. The returned value is initialized to ``string1``. Strings made from ``prefix, string`` pairs are added to the end of the value as long as the resulting string length is less than ``max``. Prefixes can be empty. Returns ``string1`` even if ``string1`` is longer than ``max``. You can pass as many ``prefix, string`` pairs as you wish.
* ``strcmp(x, y, lt, eq, gt)`` -- does a case-insensitive lexical comparison of ``x`` and ``y``. Returns ``lt`` if ``x < y``, ``eq`` if ``x == y``, otherwise ``gt``. This function can often be replaced by one of the lexical comparison operators (``==``, ``>``, ``<``, etc.)
@ -488,8 +503,8 @@ In `GPM` the functions described in `Single Function Mode` all require an additi
.. _template_mode:
More complex programs in templates - Template Program Mode
-------------------------------------------------------------
More complex programs in template expressions - Template Program Mode
----------------------------------------------------------------------
`Template Program Mode` (`TPM`) is a blend of :ref:`General Program Mode <general_mode>` and
:ref:`Single Function Mode <single_mode>`. `TPM` differs from Single Function Mode in that it permits writing template expressions that refer to other metadata fields, use nested functions, modify variables, and do arithmetic. It differs from `General Program Mode` in that the template is contained between ``{`` and ``}`` characters and doesn't begin with the word ``program:``. The program portion of the template is a General Program Mode expression list.
@ -509,7 +524,7 @@ The example shows several things:
All the functions listed under `Single Function Mode` and `General Program Mode` can be used in `TPM`.
In `TPM`, using ``{`` and ``}`` characters in string literals can lead to errors or unexpected results because they confuse the template processor. It tries to treat them as template boundaries, not characters. In some but not all cases you can replace a ``{`` with ``[[`` and a ``}`` with `]]`. Generally, if your program contains ``{`` and ``}`` characters then you should use `General Program Mode`.
In `TPM`, using ``{`` and ``}`` characters in string literals can lead to errors or unexpected results because they confuse the template processor. It tries to treat them as template expression boundaries, not characters. In some but not all cases you can replace a ``{`` with ``[[`` and a ``}`` with `]]`. Generally, if your program contains ``{`` and ``}`` characters then you should use `General Program Mode`.
As with `General Program Mode`, for functions documented under :ref:`Single Function Mode <single_mode>` you must supply the value the function is to act upon as the first parameter in addition to the documented parameters. In `TPM` you can use ``$`` to access the value specified by the ``lookup name`` for the template expression.
@ -528,7 +543,7 @@ You retrieve the arguments passed in the call to the stored template using the `
Examples, again assuming the stored template is named ``foo``:
* ``foo('#myseries')`` -- argument ``key`` will have the value ``'myseries'`` and the argument ``alternate`` will have the value ``'series'``.
* ``foo('#myseries')`` -- argument ``key`` is assigned the value ``'myseries'`` and the argument ``alternate`` is assigned the default value ``'series'``.
* ``foo('series', '#genre')`` the variable ``key`` is assigned the value ``'series'`` and the variable ``alternate`` is assigned the value ``'#genre'``.
* ``foo()`` -- the variable ``key`` is assigned the empty string and the variable ``alternate`` is assigned the value ``'series'``.
@ -543,7 +558,7 @@ A developer can choose to pass additional information to the template processor,
The additional information is a Python dictionary containing pairs ``variable_name: variable_value`` where the values must be strings. The template can access the dict, creating template local variables named ``variable_name`` containing the value ``variable_value``. The user cannot change the name so it is best to use names that won't collide with other template local variables, for example by prefixing the name with an underscore.
This dict is passed to the template processor (the ``formatter``) using the named parameter ``global_vars=your_dict``. The full method signature is:
This dict is passed to the template processor (the ``formatter``) using the named parameter ``global_vars=your_dict``. The full method signature is::
def safe_format(self, fmt, kwargs, error_value, book,
column_name=None, template_cache=None,
@ -568,9 +583,13 @@ This function sets the ``globals`` dict key:value pair ``id:value`` where ``valu
Notes on the difference between modes
-----------------------------------------
The three program modes, :ref:`Single Function Mode <single_mode>` (SFM), :ref:`Template Program Mode <template_mode>` (`TPM`), and :ref:`General Program Mode <general_mode>` (`GPM`), work differently. SFM is intended to be 'simple' so it hides a lot of programming language bits. For example, the value of the column is always passed as an 'invisible' first argument to a function included in the template. SFM also doesn't support the difference between variables and strings; all values are strings.
The three program modes, :ref:`Single Function Mode <single_mode>` (SFM), :ref:`Template Program Mode <template_mode>` (`TPM`), and :ref:`General Program Mode <general_mode>` (`GPM`), work differently. SFM is intended to be 'simple' so it hides a lot of programming language bits.
Example: the following SFM template returns either the series name or the string "no series"::
Differences:
* In SFM the value of the column is always passed as an 'invisible' first argument to a function included in the template.
* SFM doesn't support the difference between variables and strings; all values are strings.
* The following SFM template returns either the series name or the string "no series"::
{series:ifempty(no series)}
@ -583,14 +602,12 @@ The equivalent template in `GPM` is::
program: ifempty(field('series'), 'no series')
The first argument to ``ifempty`` is the value of the field ``series``. The second argument is the string ``no series``. In SFM the first argument, the value of the field, is automatically passed (the invisible argument).
Several template functions, for example ``booksize()`` and ``current_library_name()``, take no arguments. Because of the 'invisible argument' you cannot use these functions in SFM.
Nested functions, where a function calls another function to compute an argument, cannot be used in SFM. For example this template, intended to return the first 5 characters of the series value uppercased, won't work in SFM::
* Several template functions, for example ``booksize()`` and ``current_library_name()``, take no arguments. Because of the 'invisible argument' you cannot use these functions in SFM.
* Nested functions, where a function calls another function to compute an argument, cannot be used in SFM. For example this template, intended to return the first 5 characters of the series value uppercased, won't work in SFM::
{series:uppercase(substr(0,5))}
`TPM` and `GPM` support nested functions. The above template in `TPM` would be::
* `TPM` and `GPM` support nested functions. The above template in `TPM` would be::
{series:'uppercase(substr($, 0,5))'}
@ -598,7 +615,7 @@ In `GPM` it would be::
program: uppercase(substr(field('series'), 0,5))
As noted in the above :ref:`Template Program Mode <template_mode>` section, using ``{`` and ``}`` characters in `TPM` string literals can lead to errors or unexpected results because they confuse the template processor. It tries to treat them as template boundaries, not characters. In some but not all cases you can replace a ``{`` with ``[[`` and a ``}`` with `]]`. Generally, if your program contains ``{`` and ``}`` characters then you should use `General Program Mode`.
* As noted in the above :ref:`Template Program Mode <template_mode>` section, using ``{`` and ``}`` characters in `TPM` string literals can lead to errors or unexpected results because they confuse the template processor. It tries to treat them as template boundaries, not characters. In some but not all cases you can replace a ``{`` with ``[[`` and a ``}`` with `]]`. Generally, if your program contains ``{`` and ``}`` characters then you should use `General Program Mode`.
User-defined Python template functions
@ -620,10 +637,9 @@ The slash and the hyphen appear only if series is not empty.
The lookup function lets us do even fancier processing. For example, assume that if a book has a series, then we want the folder structure `series/series index - title.fmt`. If the book does not have a series then we want the folder structure `genre/author_sort/title.fmt`. If the book has no genre then we want to use 'Unknown'. We want two completely different paths, depending on the value of series.
To accomplish this, we:
1. Create a composite field (give it lookup name #aa) containing ``{series}/{series_index} - {title}``. If
the series is not empty, then this template will produce `series/series_index - title`.
2. Create a composite field (give it lookup name #bb) containing ``{#genre:ifempty(Unknown)}/{author_sort}/{title}``.
This template produces `genre/author_sort/title`, where an empty genre is replaced with `Unknown`.
1. Create a composite field (give it lookup name #aa) containing ``{series}/{series_index} - {title}``. If the series is not empty, then this template will produce `series/series_index - title`.
2. Create a composite field (give it lookup name #bb) containing ``{#genre:ifempty(Unknown)}/{author_sort}/{title}``. This template produces `genre/author_sort/title`, where an empty genre is replaced with `Unknown`.
3. Set the save template to ``{series:lookup(.,#aa,#bb}``. This template chooses composite field ``#aa`` if series is not empty and composite field ``#bb`` if series is empty. We therefore have two completely different save paths, depending on whether or not `series` is empty.
Templates and plugboards
@ -650,10 +666,9 @@ The same thing happens for authors, but using a different character for the cut,
Plugboards affect the metadata written into the book when it is saved to disk or written to the device. Plugboards do not affect the metadata used by ``save to disk`` and ``send to device`` to create the file names. Instead, file names are constructed using the templates entered on the appropriate preferences window.
Tips:
------------
-----
* Use the Template Tester to test templates. Add the tester to the context menu for books in the
library and/or give it a keyboard shortcut.
* Use the Template Tester to test templates. Add the tester to the context menu for books in the library and/or give it a keyboard shortcut.
* Templates can use other templates by referencing composite columns built with the desired template. Alternatively, you can use Stored Templates.
* In a plugboard, you can set a field to empty (or whatever is equivalent to empty) by using the special template ``{}``. This template will always evaluate to an empty string.
* The technique described above to show numbers even if they have a zero value works with the standard field series_index.

View File

@ -424,7 +424,7 @@ class BuiltinListSplit(BuiltinFormatterFunction):
name = 'list_split'
arg_count = 3
category = 'List manipulation'
__doc__ = doc = _('split(list_val, sep, id_prefix) -- splits the list_val '
__doc__ = doc = _('list_split(list_val, sep, id_prefix) -- splits the list_val '
"into separate values using 'sep', then assigns the values "
"to variables named 'id_prefix_N' where N is the position "
"of the value in the list. The first item has position 0 (zero). "