From a70e028fb6bf9bcd9af885a6f0d4564e9343efe4 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 15 Nov 2024 12:01:12 +0530 Subject: [PATCH] Use ffdoc in template_lang.rst Also dont include :ffdoc: in .po file --- manual/custom.py | 12 +- manual/template_lang.rst | 358 +++++++++++---------------------------- 2 files changed, 107 insertions(+), 263 deletions(-) diff --git a/manual/custom.py b/manual/custom.py index 9bd2740039..379f485ffb 100644 --- a/manual/custom.py +++ b/manual/custom.py @@ -50,11 +50,19 @@ def ffdoc(m): def source_read_handler(app, docname, source): src = source[0] - if app.builder.name != 'gettext': + if app.builder.name == 'gettext': + if docname == 'template_lang': + src = re.sub(r':ffdoc:`(.+?)`', ' ', src) # ffdoc should not be translated + else: if app.config.language != 'en': src = re.sub(r'(\s+generated/)en/', r'\1' + app.config.language + '/', src) if docname == 'template_lang': - src = re.sub(r':ffdoc:`(.+?)`', ffdoc, src) + try: + src = re.sub(r':ffdoc:`(.+?)`', ffdoc, src) + except Exception: + import traceback + traceback.print_exc() + raise # Sphinx does not call source_read_handle for the .. include directive for m in reversed(tuple(include_pat.finditer(src))): included_doc_name = m.group(1).lstrip('/') diff --git a/manual/template_lang.rst b/manual/template_lang.rst index 9f883f2ee5..29a034ffc9 100644 --- a/manual/template_lang.rst +++ b/manual/template_lang.rst @@ -174,51 +174,30 @@ The functions intended for use in Single Function Mode are: * :ffdoc:`capitalize` -* ``contains(pattern, text if match, text if not match)`` -- checks if the value is matched by the regular expression ``pattern``. Returns ``text if match`` if the pattern matches the value, otherwise returns ``text if no match``. -* ``count(separator)`` -- interprets the value as a list of items separated by ``separator`` and returns the number of items in the list. Most lists use a comma as the separator, but ``authors`` uses an ampersand (&). Examples: ``{tags:count(,)}``, ``{authors:count(&)}``. Aliases: ``count()``, ``list_count()`` -* ``format_number(template)`` -- interprets the value as a number and formats that number using a Python formatting template such as ``{0:5.2f}`` or ``{0:,d}`` or ``${0:5,.2f}``. The formatting template must begin with ``{0:`` and end with ``}`` as in the above examples. Exception: you can leave off the leading "{0:" and trailing "}" if the format template contains only a format. See the template language and the `Python documentation `_ for more examples. Returns the empty string if formatting fails. -* ``human_readable()`` -- expects the value to be a number and returns a string representing that number in KB, MB, GB, etc. -* ``ifempty(text if empty)`` -- if the value is not empty then return the value of the field, otherwise return `text if empty`. -* ``in_list(separator, [ pattern, found_val, ]* not_found_val)`` -- interpret the value as a list of items separated by ``separator``, checking the ``pattern`` against each item in the list. If the ``pattern`` matches an item then return ``found_val``, otherwise return ``not_found_val``. The pair ``pattern`` and ``found_value`` can be repeated as many times as desired, permitting returning different values depending on the item's value. The patterns are checked in order, and the first match is returned. -* ``language_strings(localize)`` -- return the `language names `_ for the `language codes `_ passed in as the value. Example: ``{languages:language_strings()}``. If ``localize`` is zero, return the strings in English. If ``localize`` is not zero, return the strings in the language of the current locale. ``Lang_codes`` is a comma-separated list. -* ``list_item(index, separator)`` -- interpret the value as a list of items separated by ``separator``, returning the 'index'th item. The first item is number zero. The last item has the index ``-1`` as in ``list_item(-1,separator)``. If the item is not in the list, then the empty string is returned. -* ``lookup([ pattern, key, ]* else_key)`` -- The patterns will be checked against the value in order. If a pattern matches then the value of the field named by ``key`` is returned. If no pattern matches then the value of the field named by ``else_key`` is returned. See``switch`` (below). -* ``lowercase()`` -- returns the value of the field in lower case. -* ``rating_to_stars(use_half_stars)`` -- Returns the rating as string of star (``★``) characters. The value must be a number between 0 and 5. Set use_half_stars to 1 if you want half star characters for fractional numbers available with custom ratings columns. -* ``re(pattern, replacement)`` -- return the value after applying the regular expression. All instances of ``pattern`` in the value are replaced with ``replacement``. The template language uses case insensitive `Python regular expressions `_. -* ``select(key)`` -- interpret the value as a comma-separated list of items with each item having the form ``id:value`` (the calibre ``identifier`` format). The function finds the first pair with the id equal to key and returns the corresponding value. If no id matches then the function returns the empty string. -* ``shorten(left chars, middle text, right chars)`` -- Return a shortened version of the value, consisting of ``left chars`` characters from the beginning of the value, followed by ``middle text``, followed by ``right chars`` characters from the end of the value. ``Left chars`` and ``right chars`` must be non-negative integers. Example: assume you want to display the title with a length of at most 15 characters in length. One template that does this is ``{title:shorten(9,-,5)}``. For a book with the title `Ancient English Laws in the Times of Ivanhoe` the result will be `Ancient E-anhoe`: the first 9 characters of the title, a ``-``, then the last 5 characters. If the value's length is less than ``left chars`` + ``right chars`` + the length of ``middle text`` then the value will be returned unchanged. For example, the title `The Dome` would not be changed. -* ``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: - - * 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" - -* ``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": - - * ``{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. -* ``switch([pattern, value,]+ else_value)`` -- for each ``pattern, value`` pair, checks if the value matches the regular expression ``pattern`` and if so returns the associated ``value``. If no ``pattern`` matches, then ``else_value`` is returned. You can have as many ``pattern, value`` pairs as you wish. The first match is returned. -* ``test(text if not empty, text if empty)`` -- return ``text if not empty`` if the value is not empty, otherwise return ``text if empty``. -* ``titlecase()`` -- returns the value of the field in title case. -* ``transliterate()`` -- Return a string in a latin alphabet formed by approximating the sound of the words in the source field. For example, if the source field is ``Фёдор Миха́йлович Достоевский`` this function returns ``Fiodor Mikhailovich Dostoievskii``. -* ``uppercase()`` -- returns the value of the field in upper case. +* :ffdoc:`contains` +* :ffdoc:`list_count` +* :ffdoc:`format_number` +* :ffdoc:`human_readable` +* :ffdoc:`ifempty` +* :ffdoc:`list_contains` +* :ffdoc:`language_strings` +* :ffdoc:`list_item` +* :ffdoc:`lookup` +* :ffdoc:`lowercase` +* :ffdoc:`rating_to_stars` +* :ffdoc:`re` +* :ffdoc:`select` +* :ffdoc:`shorten` +* :ffdoc:`str_in_list` +* :ffdoc:`subitems` +* :ffdoc:`sublist` +* :ffdoc:`swap_around_articles` +* :ffdoc:`swap_around_comma` +* :ffdoc:`switch` +* :ffdoc:`test` +* :ffdoc:`titlecase` +* :ffdoc:`transliterate` +* :ffdoc:`uppercase` **Using functions and formatting in the same template** @@ -436,17 +415,12 @@ The following functions are available in addition to those described in :ref:`Si In `GPM` the functions described in `Single Function Mode` all require an additional first parameter specifying the value to operate upon. All parameters are expression_lists (see the grammar above). -* ``add(x [, y]*)`` -- returns the sum of its arguments. Throws an exception if an argument is not a number. In most cases you can use the ``+`` operator instead of this function. -* ``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:: - - 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. -* ``book_count(query, use_vl)`` -- returns the count of books found by searching for ``query``. If ``use_vl`` is ``0`` (zero) then virtual libraries are ignored. This function and its companion ``book_values()`` are particularly useful in template searches, supporting searches that combine information from many books such as looking for series with only one book. It cannot be used in composite columns unless the tweak ``allow_template_database_functions_in_composites`` is set to True. It can be used only in the GUI. +* :ffdoc:`add` +* :ffdoc:`and` +* :ffdoc:`assign` +* :ffdoc:`approximate_formats` +* :ffdoc:`author_sorts` +* :ffdoc:`book_count` For example this template search uses this function and its companion to find all series with only one book: @@ -472,216 +446,78 @@ In `GPM` the functions described in `Single Function Mode` all require an additi template:"program: series_only_one_book()#@#:n:1" Using a stored template instead of putting the template into the search eliminates problems caused by the requirement to escape quotes in search expressions. -* ``book_values(column, query, sep, use_vl)`` -- returns a list of the unique values contained in the column ``column`` (a lookup name), separated by ``sep``, in the books found by searching for ``query``. If ``use_vl`` is ``0`` (zero) then virtual libraries are ignored. This function and its companion ``book_count()`` are particularly useful in template searches, supporting searches that combine information from many books such as looking for series with only one book. It cannot be used in composite columns unless the tweak ``allow_template_database_functions_in_composites`` is set to True. It can be used only in the GUI. -* ``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("#bool", 1, 0, 1)`` returns ``'Yes'`` if the yes/no field ``#bool`` is either True or undefined (neither True nor False). - - 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. -* ``character(character_name)`` -- returns the character named by character_name. For example, ``character('newline')`` returns a newline character (``'\n'``). The supported character names are ``newline``, ``return``, ``tab``, and ``backslash``. -* ``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. -* ``connected_device_uuid(storage_location_key)`` -- if a device is connected then return the device uuid (unique id), otherwise return the empty string. Each storage location on a device has a different uuid. The ``storage_location_key`` location names are ``'main'``, ``'carda'`` and ``'cardb'``. This function works only in the GUI. -* ``current_library_name()`` -- return the last name on the path to the current calibre library. -* ``current_library_path()`` -- return the full path to the current calibre library. -* ``current_virtual_library_name()`` -- return the name of the current virtual library if there is one, otherwise the empty string. Library name case is preserved. Example: ``program: current_virtual_library_name()``. This function works only in the GUI. -* ``date_arithmetic(date, calc_spec, fmt)`` -- Calculate a new date from ``date`` using ``calc_spec``. Return the new date formatted according to optional ``fmt``: if not supplied then the result will be in ISO format. The calc_spec is a string formed by concatenating pairs of ``vW`` (``valueWhat``) where ``v`` is a possibly-negative number and W is one of the following letters: - - * ``s``: add ``v`` seconds to ``date`` - * ``m``: add ``v`` minutes to ``date`` - * ``h``: add ``v`` hours to ``date`` - * ``d``: add ``v`` days to ``date`` - * ``w``: add ``v`` weeks to ``date`` - * ``y``: add ``v`` years to ``date``, where a year is 365 days. - - Example: ``'1s3d-1m'`` will add 1 second, add 3 days, and subtract 1 minute from ``date``. -* ``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 :ref:`Template Program 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 `. -* ``extra_file_size(file_name)`` -- returns the size in bytes of the extra file ``file_name`` in the book's ``data/`` folder if it exists, otherwise ``-1``. See also the functions ``has_extra_files()``, ``extra_file_names()`` and ``extra_file_modtime()``. This function can be used only in the GUI. -* ``extra_file_modtime(file_name, format_string)`` -- returns the modification time of the extra file ``file_name`` in the book's ``data/`` folder if it exists, otherwise ``-1``. The modtime is formatted according to ``format_string`` (see ``format_date()`` for details). If ``format_string`` is the empty string, returns the modtime as the floating point number of seconds since the epoch. See also the functions ``has_extra_files()``, ``extra_file_names()`` and ``extra_file_size()``. The epoch is OS dependent. This function can be used only in the GUI. -* ``extra_file_names(sep [, pattern])`` -- returns a ``sep``-separated list of extra files in the book's ``data/`` folder. If the optional parameter ``pattern``, a regular expression, is supplied then the list is filtered to files that match ``pattern``. The pattern match is case insensitive. See also the functions ``has_extra_files()``, ``extra_file_modtime()`` and ``extra_file_size()``. This function can be used only in the GUI. -* ``field(lookup_name)`` -- returns the value of the metadata field with lookup name ``lookup_name``. -* ``field_exists(lookup_name)`` -- checks if a field (column) with the lookup name ``lookup_name`` exists, returning ``'1'`` if so and the empty string if not. +* :ffdoc:`book_values` +* :ffdoc:`booksize` +* :ffdoc:`check_yes_no` +* :ffdoc:`ceiling` +* :ffdoc:`character` +* :ffdoc:`cmp` +* :ffdoc:`connected_device_name` +* :ffdoc:`connected_device_uuid` +* :ffdoc:`current_library_name` +* :ffdoc:`current_library_path` +* :ffdoc:`current_virtual_library_name` +* :ffdoc:`date_arithmetic` +* :ffdoc:`days_between` +* :ffdoc:`divide` +* :ffdoc:`eval` +* :ffdoc:`extra_file_size` +* :ffdoc:`extra_file_modtime` +* :ffdoc:`extra_file_names` +* :ffdoc:`field` +* :ffdoc:`field_exists` * :ffdoc:`finish_formatting` -* ``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:: - - 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"``. - -* ``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. It is best if the date is in ISO format as using other date formats often causes errors because the actual date value cannot be unambiguously determined. Note that the ``format_date_field()`` function is both faster and more reliable. - - 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. - * ``to_number :`` convert the date & time into a floating point number (a `timestamp`) - * ``from_number :`` convert a floating point number (a `timestamp`) into an ``iso`` formatted date. If you want a different date format then add the desired formatting string after ``from_number`` and a colon (``:``). Example: ``from_number:MMM dd 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 to contain ``MMMM``. Using ``format_date_field()`` avoids this problem. - -* ``format_date_field(field_name, format_string)`` -- format the value in the field ``field_name``, which must be the lookup name of date field, either standard or custom. See ``format_date()`` for the formatting codes. This function is much faster than format_date and should be used when you are formatting the value in a field (column). It is also more reliable because it works directly on the underlying date. It can't be used for computed dates or dates in string variables. Examples:: - - format_date_field('pubdate', 'yyyy.MM.dd') - format_date_field('#date_read', 'MMM dd, 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. -* ``fractional_part(x)`` -- returns the value after the decimal point. For example, ``fractional_part(3.14)`` returns ``0.14``. Throws an exception if ``x`` is not a number. +* :ffdoc:`first_matching_cmp` +* :ffdoc:`first_non_empty` +* :ffdoc:`floor` +* :ffdoc:`format_date` +* :ffdoc:`formats_modtimes` +* :ffdoc:`formats_paths` +* :ffdoc:`formats_sizes` +* :ffdoc:`fractional_part` * :ffdoc:`get_link` -* ``get_note(field_name, field_value, plain_text)`` -- fetch the note for field 'field_name' with value 'field_value'. If `plain_text` is empty, return the note's HTML including images. If `plain_text` is `1` (or `'1'`), return the note's plain text. If the note doesn't exist, return the empty string in both cases. Example: - - * Return the HTML of the note attached to the tag `Fiction`:: - - program: - get_note('tags', 'Fiction', '') - - * Return the plain text of the note attached to the author `Isaac Asimov`:: - - program: - get_note('authors', 'Isaac Asimov', 1) - - -* ``has_cover()`` -- return ``'Yes'`` if the book has a cover, otherwise the empty string. -* ``has_note(field_name, field_value)``. This function has two variants: - - * if ``field_value`` is not ``''`` (the empty string) return ``'1'`` if the value ``field_value`` in the field ``field_name`` has a note, otherwise ``''``. Example::: - - has_note('tags', 'Fiction') - - returns ``'1'`` if the tag ``fiction`` has an attached note, otherwise ``''``. - - * If ``field_value`` is ``''`` then return a list of values in ``field_name`` that have a note. If no item in the field has a note, return ``''``. This variant is useful for showing column icons if any value in the field has a note, rather than a specific value. - - Example:: - - has_note('authors', '') - - returns a list of authors that have notes, or ``''`` if no author has a note. - - You can test if all the values in ``field_name`` have a note by comparing the list length of this function's return value against the list length of the values in ``field_name``. Example:: - - list_count(has_note('authors', ''), '&') ==# list_count_field('authors') - - -* ``has_extra_files([pattern])`` -- returns the count of extra files, otherwise '' (the empty string). If the optional parameter ``pattern`` (a regular expression) is supplied then the list is filtered to files that match ``pattern`` before the files are counted. The pattern match is case insensitive. See also the functions ``extra_file_names()``, ``extra_file_size()`` and ``extra_file_modtime()``. This function can be used only in the GUI. -* ``identifier_in_list(val, id_name [, found_val, not_found_val])`` -- treat ``val`` as a list of identifiers separated by commas. An identifier has the format ``id_name:value``. The ``id_name`` parameter is the id_name text to search for, either ``id_name`` or ``id_name:regexp``. The first case matches if there is any identifier matching that id_name. The second case matches if id_name matches an identifier and the regexp matches the identifier's value. If ``found_val`` and ``not_found_val`` are provided then if there is a match then return ``found_val``, otherwise return ``not_found_val``. If ``found_val`` and ``not_found_val`` are not provided then if there is a match then return the ``identifier:value`` pair, otherwise the empty string (``''``). -* ``is_dark_mode()`` -- returns ``'1'`` if calibre is running in dark mode, ``''`` (the empty string) otherwise. This function can be used in advanced color and icon rules to choose different colors/icons according to the mode. Example:: - - if is_dark_mode() then 'dark.png' else 'light.png' fi - -* ``is_marked()`` -- check whether the book is `marked` in calibre. If it is then return the value of the mark, either ``'true'`` (lower case) or a comma-separated list of named marks. Returns ``''`` (the empty string) if the book is not marked. This function works only in the GUI. -* ``language_codes(lang_strings)`` -- return the `language codes `_ for the language names passed in `lang_strings`. The strings must be in the language of the current locale. ``Lang_strings`` is a comma-separated list. -* ``list_contains(value, separator, [ pattern, found_val, ]* not_found_val)`` -- (Alias of ``in_list``) Interpreting the value as a list of items separated by ``separator``, evaluate the ``pattern`` against each value in the list. If the ``pattern`` matches any value then return ``found_val``, otherwise return ``not_found_val``. The ``pattern`` and ``found_value`` can be repeated as many times as desired, permitting returning different values depending on the search. The patterns are checked in order. The first match is returned. Aliases: ``in_list()``, ``list_contains()`` -* ``list_count(value, separator)`` -- interprets ``value`` as a list of items separated by ``separator``, returning the count of items in the list. Aliases: ``count()``, ``list_count()`` -* ``list_count_field(lookup_name)``-- returns the count of items in the field with the lookup name `lookup_name`. The field must be multi-valued such as ``authors`` or ``tags``, otherwise the function raises an error. This function is much faster than ``list_count()`` because it operates directly on calibre data without converting it to a string first. Example: ``list_count_field('tags')`` -* ``list_count_matching(list, pattern, separator)`` -- interprets ``list`` as a list of items separated by ``separator``, returning the number of items in the list that match the regular expression ``pattern``. Aliases: ``list_count_matching()``, ``count_matching()`` -* ``list_difference(list1, list2, separator)`` -- return a list made by removing from ``list1`` any item found in ``list2`` using a case-insensitive comparison. The items in ``list1`` and ``list2`` are separated by separator, as are the items in the returned list. -* ``list_equals(list1, sep1, list2, sep2, yes_val, no_val)`` -- return ``yes_val`` if ``list1`` and `list2` contain the same items, otherwise return ``no_val``. The items are determined by splitting each list using the appropriate separator character (``sep1`` or ``sep2``). The order of items in the lists is not relevant. The comparison is case-insensitive. -* ``list_intersection(list1, list2, separator)`` -- return a list made by removing from ``list1`` any item not found in ``list2``, using a case-insensitive comparison. The items in ``list1`` and ``list2`` are separated by separator, as are the items in the returned list. -* ``list_join(with_separator, list1, separator1 [, list2, separator2]*)`` -- return a list made by joining the items in the source lists (``list1`` etc) using ``with_separator`` between the items in the result list. Items in each source ``list[123...]`` are separated by the associated ``separator[123...]``. A list can contain zero values. It can be a field like ``publisher`` that is single-valued, effectively a one-item list. Duplicates are removed using a case-insensitive comparison. Items are returned in the order they appear in the source lists. If items on lists differ only in letter case then the last is used. All separators can be more than one character. - - Example:: - - program: - list_join('#@#', $authors, '&', $tags, ',') - - You can use ``list_join`` on the results of previous calls to ``list_join`` as follows:: - - program: - a = list_join('#@#', $authors, '&', $tags, ','); - b = list_join('#@#', a, '#@#', $#genre, ',', $#people, '&', 'some value', ',') - - You can use expressions to generate a list. For example, assume you want items for ``authors`` and ``#genre``, but with the genre changed to the word "Genre: " followed by the first letter of the genre, i.e. the genre "Fiction" becomes "Genre: F". The following will do that:: - - program: - list_join('#@#', $authors, '&', list_re($#genre, ',', '^(.).*$', 'Genre: \1'), ',') - -* ``list_re(src_list, separator, include_re, opt_replace)`` -- Construct a list by first separating ``src_list`` into items using the ``separator`` character. For each item in the list, check if it matches ``include_re``. If it does then add it to the list to be returned. If ``opt_replace`` is not the empty string then apply the replacement before adding the item to the returned list. -* ``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_2 = '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. -* ``not(value)`` -- returns the string "1" if the value is empty, otherwise returns the empty string. This function can usually be replaced with the unary not (``!``) operator. -* ``ondevice()`` -- return the string ``'Yes'`` if ``ondevice`` is set, otherwise return the empty string. -* ``or(value [, value]*)`` -- returns the string ``'1'`` if any value is not empty, otherwise returns the empty string. You can have as many values as you want. This function can usually be replaced by the ``||`` operator. A reason it cannot be replaced is if short-circuiting will change the results because of side effects. -* ``print(a [, b]*)`` -- prints the arguments to standard output. Unless you start calibre from the command line (``calibre-debug -g``), the output will go into a black hole. The ``print`` function always returns its first argument. +* :ffdoc:`get_note` +* :ffdoc:`has_extra_files` +* :ffdoc:`identifier_in_list` +* :ffdoc:`is_dark_mode` +* :ffdoc:`is_marked` +* :ffdoc:`language_codes` +* :ffdoc:`list_contains` +* :ffdoc:`list_count` +* :ffdoc:`list_count_field` +* :ffdoc:`list_count_matching` +* :ffdoc:`list_difference` +* :ffdoc:`list_equals` +* :ffdoc:`list_intersection` +* :ffdoc:`list_join` +* :ffdoc:`list_union` +* :ffdoc:`mod` +* :ffdoc:`multiply` +* :ffdoc:`not` +* :ffdoc:`ondevice` +* :ffdoc:`or` +* :ffdoc:`print` .. _range_function: -* ``range(start, stop, step, limit)`` -- returns a list of numbers generated by looping over the range specified by the parameters start, stop, and step, with a maximum length of limit. The first value produced is 'start'. Subsequent values ``next_v = current_v + step``. The loop continues while ``next_v < stop`` assuming ``step`` is positive, otherwise while ``next_v > stop``. An empty list is produced if ``start`` fails the test: ``start >= stop`` if ``step`` is positive. The ``limit`` sets the maximum length of the list and has a default of 1000. The parameters ``start``, ``step``, and ``limit`` are optional. Calling ``range()`` with one argument specifies ``stop``. Two arguments specify ``start`` and ``stop``. Three arguments specify ``start``, ``stop``, and ``step``. Four arguments specify ``start``, ``stop``, ``step`` and ``limit``. Examples:: - - range(5) -> '0, 1, 2, 3, 4' - range(0, 5) -> '0, 1, 2, 3, 4' - range(-1, 5) -> '-1, 0, 1, 2, 3, 4' - range(1, 5) -> '1, 2, 3, 4' - range(1, 5, 2) -> '1, 3' - range(1, 5, 2, 5) -> '1, 3' - range(1, 5, 2, 1) -> error(limit exceeded) - -* ``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 value returned by the corresponding template. In :ref:`Template Program 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:: - - program: re_group(field('series'), "(\S* )(.*)", "{$:uppercase()}", "{$}")'} - -* ``round(x)`` -- returns the nearest integer to ``x``. Throws an exception if ``x`` is not a number. -* ``series_sort()`` -- returns the series sort value. -* ``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.) -* ``strcmpcase(x, y, lt, eq, gt)`` -- does a case-sensitive lexical comparison of ``x`` and ``y``. Returns ``lt`` if ``x < y``, ``eq`` if ``x == y``, otherwise ``gt``. - - Note: This is NOT the default behavior used by calibre, for example, in the lexical comparison operators (``==``, ``>``, ``<``, etc.). This function could cause unexpected results, preferably use ``strcmp()`` whenever possible. - -* ``strlen(value)`` -- Returns the length of the string ``value``. -* ``substr(str, start, end)`` -- returns the ``start``'th through the ``end``'th characters of ``str``. The first character in ``str`` is the zero'th character. If ``end`` is negative, then it indicates that many characters counting from the right. If ``end`` is zero, then it indicates the last character. For example, ``substr('12345', 1, 0)`` returns ``'2345'``, and ``substr('12345', 1, -1)`` returns ``'234'``. -* ``subtract(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. -* ``switch_if([test_expression, value_expression,]+ else_expression)`` -- for each ``test_expression, value_expression`` pair, checks if ``test_expression`` is True (non-empty) and if so returns the result of ``value_expression``. If no ``test_expression`` is True then the result of ``else_expression` is returned. You can have as many ``test_expression, value_expression`` pairs as you want. -* ``today()`` -- return a date+time string for today (now). This value is designed for use in `format_date` or `days_between`, but can be manipulated like any other string. The date is in `ISO `_ date/time format. -* ``template(x)`` -- evaluates ``x`` as a template. The evaluation is done in its own context, meaning that variables are not shared between the caller and the template evaluation. -* ``to_hex(val)`` -- returns the string ``val`` encoded in hex. This is useful when constructing calibre URLs. -* ``urls_from_identifiers(identifiers, sort_results)`` -- given a comma-separated list of ``identifiers``, where an `identifier` is a colon-separated pair of values (``id_name:id_value``), returns a comma-separated list of HTML URLs generated from the identifiers. The list not sorted if sort_results is ``0`` (character or number), otherwise it is sorted alphabetically by the identifier name. The URLs are generated in the same way as the built-in identifiers column when shown in :guilabel:`Book details`. +* :ffdoc:`range` +* :ffdoc:`raw_field` +* :ffdoc:`raw_list` +* :ffdoc:`re_group` +* :ffdoc:`round` +* :ffdoc:`series_sort` +* :ffdoc:`strcat` +* :ffdoc:`strcat_max` +* :ffdoc:`strcmp` +* :ffdoc:`strcmpcase` +* :ffdoc:`strlen` +* :ffdoc:`substr` +* :ffdoc:`subtract` +* :ffdoc:`switch_if` +* :ffdoc:`today` +* :ffdoc:`template` +* :ffdoc:`to_hex` +* :ffdoc:`urls_from_identifiers` .. _template_mode: