Язык шаблонов calibre

Язык шаблонов calibre — это специфичный для calibre язык, используемый в calibre для таких задач, как указание путей к файлам, форматирование значений и вычисление значений для столбцов, указанных пользователем. Примеры:

  • Укажите структуру папок и имена файлов при сохранении файлов из библиотеки calibre на диск или в читалку электронных книг

  • Определите правила добавления значков и цветов в список книг calibre.

  • Определите виртуальные столбцы, содержащие данные из других столбцов.

  • Расширенный поиск в библиотеке.

  • Расширенный поиск и замена метаданных.

Язык построен на понятии «шаблон», который определяет, какие метаданные книги использовать, вычисления над этими метаданными и способ их форматирования.

Базовые шаблоны

Базовый шаблон состоит из одного или нескольких шаблонных выражений. Шаблонное выражение состоит из текста и имен в фигурных скобках ({}), которые заменяются соответствующими метаданными из обрабатываемой книги. Например, шаблон по умолчанию в calibre, используемый для сохранения книг на устройство, имеет 4 шаблонных выражения:

{author_sort}/{title}/{title} - {authors}

Для книги Айзека Азимова «Основание» «The Foundation» by «Isaac Asimov» им станет:

Asimov, Isaac/The Foundation/The Foundation - Isaac Asimov

Косые черты не являются шаблонными выражениями, потому что они находятся между ними в {}. Такой текст остается там, где он появляется. Например, если шаблон:

{author_sort} Some Important Text {title}/{title} - {authors}

затем для книги «Основание» шаблон создает:

Asimov, Isaac Some Important Text The Foundation/The Foundation - Isaac Asimov

Шаблонное выражение может получить доступ ко всем метаданным, доступным в calibre, включая настраиваемые столбцы (столбцы, которые вы создаете самостоятельно), используя имя поиска столбца. Чтобы найти поисковое имя для столбца (иногда называемых полями), наведите указатель мыши на заголовок столбца в списке книг calibre. Имена подстановки для настраиваемых столбцов всегда начинаются с символа #. Для столбцов типа серии есть дополнительное поле с именем #lookup name_index, которое является индексом серии для этой книги в серии. Например, если у вас есть столбец настраиваемой серии с именем #myseries, также будет столбец с именем #myseries_index. Индекс столбца стандартной серии называется series_index.

В дополнение к стандартным полям на основе столбцов вы также можете использовать:

  • {formats}- Список форматов, доступных в библиотеке calibre для книги

  • {identifiers:select(isbn)} - ISBN книги

Если метаданные для поля для данной книги не определены, тогда поле в шаблоне заменяется пустой строкой (''). Например, рассмотрим следующий шаблон:

{author_sort}/{series}/{title} {series_index}

Если книга Азимова «Второе основание» входит в серию «Основание», то шаблон дает:

Asimov, Isaac/Foundation/Second Foundation 3

Если для книги не введена серия, то шаблон выдает:

Asimov, Isaac/Second Foundation

Обработчик шаблонов автоматически удаляет несколько косых черт и начальные или конечные пробелы.

Расширенное форматирование

Помимо подстановки метаданных, шаблоны могут условно включать дополнительный текст и управлять форматированием заменяемых данных.

Условно включая текст

Иногда вы хотите, чтобы текст отображался в выводе, только если поле не пустое. Обычный случай - это series и series_index, когда вы не хотите ничего или два значения, разделенные дефисом. calibre обрабатывает этот случай, используя специальный синтаксис шаблонного выражения.

Например, используя приведенный выше пример Foundation, предположим, что вы хотите, чтобы шаблон создавал Foundation - 3 - Second Foundation. Этот шаблон производит такой вывод:

{series} - {series_index} - {title}

Однако, если в книге нет серии, шаблон создаст - - title, что, вероятно, не то, что вам нужно. Обычно люди хотят, чтобы в результате получился заголовок без лишних дефисов. Вы можете сделать это, используя следующий синтаксис шаблона:

{field:|prefix_text|suffix_text}

Это шаблонное выражение говорит, что если field имеет значение XXXX, то результатом будет prefix_textXXXXXsuffix_text. Если поле пусто (не имеет значения), результатом будет пустая строка (ничего), потому что префикс и суффикс игнорируются. Префикс и суффикс могут содержать пробелы.

Не используйте подшаблоны (`{ … }`) или функции (см. Ниже) в префиксе или суффиксе.

Используя этот синтаксис, мы можем решить указанную выше проблему без серии с шаблоном:

{series}{series_index:| - | - }{title}

Дефисы будут добавлены только в том случае, если у книги есть индекс серии, который есть только в том случае, если в ней есть серия. Продолжая пример с Foundation снова, шаблон создаст Foundation - 1 - Second Foundation.

Примечания:

  • Вы должны включить двоеточие после имени поиска, если используете префикс или суффикс.

  • Вы должны использовать либо никакой, либо оба символа |. Использовать один, как в {field:| -}, не допускается.

  • Допускается отсутствие текста для префикса или суффикса, например, в {series:|| -}. Шаблон {title:||} такой же, как {title}.

Форматирование

Предположим, вы хотите, чтобы series_index был отформатирован как три цифры с ведущими нулями. Это помогает:

{series_index: 0>3s} - три цифры с ведущими нулями

Для завершающих нулей используйте:

{series_index: 0<3s}- три цифры с завершающими нулями

Если вы используете индексы серий с дробными значениями, например 1.1, и нужно чтобы десятичные точки совпадали. Например, чтобы индексы 1 и 2.5 отображались как 01.00 и 02.50 и правильно сортировались на устройстве, которое выполняет лексическую сортировку. Для этого используйте:

{series_index: 05.2f} - пять символов, состоящих из двух цифр с ведущими нулями, десятичной точкой и двумя цифрами после десятичной точки.

Если вам нужны только первые две буквы данных, используйте:

{author_sort:.2} - Только первые две буквы сортировочного имени автора

Большая часть форматирования языка шаблонов calibre из Python. Дополнительные сведения о синтаксисе расширенных операций форматирования см. в Python documentation.

Использование шаблонов для определения пользовательских столбцов

Шаблоны могут использоваться для отображения информации, которая не входит в метаданные calibre, или для отображения метаданных, отличных от обычного формата calibre. Например, чтобы отобразить ISBN, поле, которое штатно не отображается в calibre. Создайте настраиваемый столбец с типом Столбец, построенный из других столбцов (в дальнейшем называемый составные столбцы) и предоставьте шаблон для генерации отображаемого текста. В столбце отобразится результат оценки шаблона. Чтобы отобразить ISBN, создайте составной столбец и введите {identifiers:select (isbn)} в поле шаблона. Чтобы отобразить столбец, содержащий значения двух пользовательских столбцов серий, разделённых запятой, используйте {#series1:||,}{#series2}.

В составных столбцах можно использовать любой параметр шаблона, включая форматирование.

Примечание. Вы не можете редактировать данные, отображаемые в составном столбце. Вместо этого вы редактируете исходные столбцы. Если вы редактируете составной столбец, например, дважды щелкнув по нему, calibre откроет для редактирования шаблон, а не базовые данные.

Шаблоны и коммутации

Коммутационные панели используются для изменения метаданных, записанных в книги, во время операций отправки на устройство и сохранения на диск. Коммутационная панель позволяет указать шаблон предоставления данных для записи в метаданные книги. Вы можете использовать коммутационные панели для изменения следующих полей: authors, author_sort, language, publisher, tags, title, title_sort. Эта функция помогает в использовании разных метаданных в книгах на устройствах, решении проблем сортировки или отображения.

При создании коммутационной панели вы указываете формат и устройство, для которых она будет использоваться. Предоставляется специальное устройство save_to_disk, которое используется при сохранении форматов (в отличие от их отправки на устройство). После того, как вы выбрали формат и устройство, вы выбираете поля метаданных, которые нужно изменить, предоставляя шаблоны для предоставления новых значений. Эти шаблоны присоединены к своим полям назначения, отсюда и название plugboards. Конечно, в этих шаблонах можно использовать составные столбцы.

Плагборды довольно гибкие и могут быть написаны в режиме Single Function Mode, Template Program Mode, General Program Mode, или Python Template mode.

Когда может применяться коммутационная панель (контент-сервер, сохранение на диск или отправка на устройство), calibre выполняет поиск определенных подключаемых модулей, чтобы выбрать правильный вариант для данного формата и устройства. Например, чтобы найти подходящую коммутационную панель для книги EPUB, отправляемой на устройство ANDROID, calibre выполняет поиск в коммутационных панелях, используя следующий порядок поиска:

  • коммутационная панель с точным соответствием по формату и устройству, например, EPUB и ANDROID

  • коммутационная панель с точным соответствием по формату и специальным выбором any device, например, EPUB и any device

  • коммутационная панель со специальным выбором any format и точным соответствием на устройстве, например, any format и ANDROID

  • коммутационная панель с any format и any device

Поля тегов и авторов обрабатываются по-особому, потому что оба эти поля могут содержать более одного элемента. У книги может быть много тегов и много авторов. Когда вы указываете, что одно из этих двух полей должно быть изменено, результат шаблона проверяется, чтобы увидеть, есть ли там более одного элемента. Для тегов результат будет разделен на части, если calibre найдет запятую. Например, если в шаблоне выдается значение Thriller, Horror, результатом будут два тега: Thriller и Horror. Невозможно поставить запятую в середине тега.

То же самое происходит с авторами, но с использованием другого символа для сокращения, & (амперсанд) вместо запятой. Например, если в шаблоне указано значение Blogs, Joe&Posts, Susan, тогда в книге будет два автора: Blogs, Joe и Posts, Susan. Если шаблон выдает значение Blogs, Joe;Posts, Susan, то у книги будет один автор с довольно странным именем.

Плагины влияют на метаданные, записанные в книгу, когда они сохраняются на диск или записываются на устройство. Плагины не влияют на метаданные, используемые командами «сохранить на диск» и «отправить на устройство» для создания имен файлов. Вместо этого имена файлов создаются с использованием шаблонов, введенных в соответствующем окне настроек.

Использование функций в шаблонах - режим одной функции

Предположим, вы хотите отобразить значение поля в верхнем регистре, когда это поле обычно находится в регистре заголовков. Вы можете сделать это с помощью шаблонных функций. Например, чтобы отобразить заголовок в верхнем регистре, используйте функцию uppercase, как в {title:uppercase()}. Чтобы отобразить его в регистре заголовка, используйте {title:titlecase()}.

Функции входят в форматную часть шаблона после : и перед первым | или закрывающим }, если не используется префикс/суффикс. Если у вас есть и формат, и ссылка на функцию, функция появляется после второго :. Функции возвращают соответствующее измененное значение столбца, указанного в шаблоне.

Синтаксис использования функций - один из:

{lookup_name:function(arguments)}
{lookup_name:format:function(arguments)}
{lookup_name:function(arguments)|prefix|suffix}
{lookup_name:format:function(arguments)|prefix|suffix}

За именами функций всегда должны стоять открывающие и закрывающие круглые скобки. Некоторым функциям требуются дополнительные значения (аргументы), и они заключаются в круглые скобки. Аргументы разделяются запятыми. Буквальным запятым (запятым как тексту, а не разделителям аргументов) должна предшествовать обратная косая черта (\\). Последний (или единственный) аргумент не может содержать закрывающую текстовую скобку.

Функции оцениваются до спецификации формата и префикса/суффикса. См. Ниже пример использования формата и функции.

Важно: если у вас есть опыт программирования, обратите внимание, что синтаксис в Single Function Mode не соответствует вашим ожиданиям. Строки не заключаются в кавычки, а пробелы имеют значение. Все аргументы считаются константами; нет выражений.

Не используйте подшаблоны (`{ … }`) в качестве аргументов функции. Вместо этого используйте Template Program Mode и General Program Mode.

Для некоторых функций требуются регулярные выражения. В языке шаблонов сопоставление регулярных выражений производится без учета регистра.

В документации по функциям ниже обозначение [something]* означает, что something может повторяться ноль или более раз. Обозначение [что-то]+ означает, что что-то повторяется один или несколько раз (должно существовать хотя бы один раз).

Функции, предназначенные для использования в режиме одной функции:

  • capitalize() – возвращает значение, в котором первая буква в верхнем регистре, а остальные в нижнем регистре.

  • содержит (шаблон, текст в случае совпадения, текст в случае несовпадения) - проверяет, соответствует ли значение регулярному выражению паттерн. Возвращает текст при совпадении, если паттерн соответствует значению, в противном случае возвращает текст при отсутствии совпадения.

  • count(separator) - интерпретирует значение как список элементов, разделенных разделителем, и возвращает количество элементов в списке. В большинстве списков в качестве разделителя используется запятая, но в словах «авторы» используется амперсанд (&). Примеры: {tags:count(,)}, {authors:count(&)}. Псевдонимы: count(), list_count()

  • format_number (template) - интерпретирует значение как число и форматирует это число, используя шаблон форматирования Python, такой как {0:5.2f} или {0:,d}` или ``${0:5,.2f}. Шаблон форматирования должен начинаться с {0: и заканчиваться }, как в приведенных выше примерах. Исключение: вы можете опустить начальные {0: и завершающие }, если шаблон формата содержит только формат. См. Дополнительные примеры в языке шаблонов и в `документации Python `_. Возвращает пустую строку, если форматирование не удалось.

  • human_readable() - ожидает, что значение будет числом, и возвращает строку, представляющую это число в КБ, МБ, ГБ и т. д.

  • ifempty(text if empty) - если значение не пустое, то вернуть значение поля, иначе вернуть текст if empty.

  • in_list(separator, [ pattern, found_val, ]* not_found_val) - интерпретирует значение как список элементов, разделенных разделителем, проверяя pattern по каждому элементу в списке. Если шаблон соответствует элементу, вернуть found_val, иначе вернуть not_found_val. Пара pattern и found_value может повторяться сколько угодно раз, что позволяет возвращать разные значения в зависимости от значения элемента. Шаблоны проверяются по порядку, и возвращается первое совпадение.

  • language_strings(localize) – возвращает language names для language codes , переданных в качестве значения. Пример: {languages:language_strings()}. Если localize равно нулю, вернуть строки на английском языке. Если localize не равно нулю, вернуть строки на языке текущей локали. Lang_codes - это список, разделённый запятыми.

  • list_item(индекс, разделитель) – обрабатывает значение как список элементов, разделённых разделителем, возвращая элемент с соответствующим индексом. Первый элемент имеет нулевой индекс. К последнему элементу можно обратиться по индексу -1, напр. list_item(-1,разделитель). Если элемент отсутствует, возвращается пустая строка.

  • lookup([ pattern, key, ]* else_key) – Шаблоны будут проверяться по значению по порядку. Если шаблон совпадает, возвращается значение поля, названного key. Если ни один шаблон не совпадает, возвращается значение поля с именем else_key. Смотрите switch (ниже).

  • lowercase() – возвращает значение поля в нижнем регистре.

  • rating_to_stars(use_half_stars) – Возвращает рейтинг в виде строки, состоящей из звездочек (“). Значение должно быть числом от 0 до 5. Задайте для use_half_stars значение 1, если вы хотите, чтобы символы половинной звезды для дробных чисел были доступны в настраиваемых столбцах рейтингов.

  • re(pattern, replacement) – вернуть значение после применения регулярного выражения. Все вхождения pattern в значении заменяются на replacement. В языке шаблонов используются `Python regular expressions `_.

  • select(ключ) – обрабатывает значение как разделённый запятыми список элементов вида идентификатор:значение (формат идентификаторов calibre). Функция находит первую пару с совпадающим с ключом идентификатором, и возвращает соответствующее значение. При отсутствии совпадений возвращается пустая строка.

  • shorten(left chars, middle text, right chars) – Возвращает сокращенную версию значения, состоящую из символов left chars с начала значения, за которыми следует middle text, за которыми следуют символы right chars с конца значения. left chars и right chars должны быть неотрицательными целыми числами. Пример: предположим, что вы хотите отобразить заголовок длиной не более 15 символов. Один из шаблонов, который делает это, - {title:short(9,-,5)}. Для книги с названием «Ancient English Laws in the Times of Ivanhoe» результатом будет Ancient E-nhoe: первые 9 символов названия, -, затем последние 5 символов. Если длина значения меньше, чем левые символы + правые символы + длина среднего текста, то значение будет возвращено без изменений. Например, название The Dome не изменится.

  • str_in_list(separator, [ string, found_val, ]+ not_found_val) – интерпретирует значение как список элементов, разделенных separator, затем сравнивает string с каждым значением в списке. Строка не является регулярным выражением. Если строка равна любому элементу (без учета регистра), вернуть соответствующее значение found_val. Если строка содержит разделители, она также рассматривается как список, и каждое подзначение проверяется. Пары string и found_value могут повторяться сколько угодно раз, что позволяет возвращать разные значения в зависимости от значения строки. Если ни одна из строк не совпадает, возвращается not_found_value. Строки проверяются по порядку. Возвращается первое совпадение.

  • subitems(нач_индекс, кон_индекс) – Функция разбивает на части списки иерерхических тегов, например жанров. Значение обрабатывается как разделённый запятыми список тегов, каждый элемент в котором – разделенный точками список. Она возвращает новый список, извлекая из каждого элемента компоненты от нач_индекса до кон_индекса, объединяя полученные результаты без повторов. Первый компонент в разделённом точками списке имеет нулевой индекс. Если индекс отрицательный, то он отсчитыватеся от конца списка. Нулевое значение кон_индекса означает длину списка.

    Примеры:

    • Если столбец #genre содержит A.B.C:

      • {#genre:subitems(0,1)} вернет «A»

      • {#genre:subitems(0,2)} вернет «A.B»

      • {#genre:subitems(1,0)} вернет «B.C»

    • Если столбец #genre содержит «A.B.C, D.E»:

      • {#genre:subitems(0,1)} вернет «A, D»

      • {#genre:subitems(0,2)} вернет «A.B, D.E»

  • sublist(start_index, end_index, separator) – интерпретировать значение как список элементов, разделенных separator, возвращая новый список, составленный из элементов от start_index до end_index. Первый элемент - номер ноль. Если индекс отрицательный, он отсчитывается с конца списка. В качестве особого случая предполагается, что end_index, равный нулю, является длиной списка.

    Примеры, предполагающие, что столбец тегов (который разделён запятыми) содержит „“A, B, C““:

    • {tags:sublist(0,1,\,)} вернет «A»

    • {tags:sublist(-1,0,\,)} вернет «C»

    • {tags:sublist(0,-1,\,)} вернет «A, B»

  • swap_around_articles(separator) – возвращает значение со статьями, перемещёнными в конец. Значение может быть списком, и в этом случае обрабатывается каждый элемент в списке. Если значение является списком, вы должны указать separator. Если separator не указан, значение рассматривается как одно значение, а не как список. Статьи articles - это те, которые используются calibre для создания title_sort.

  • swap_around_comma() – если значение имеет вид Б, А, возвращает А Б. Это наиболее полезно для преобразования имён вида «Ф, И О» к виду «И О Ф». Если значение не содержит запятой, то оно возвращается без изменений.

  • switch([pattern, value,]+ else_value) – для каждой пары pattern, value, проверяет, соответствует ли значение регулярному выражению pattern`, и если да, возвращает связанное `` value``. Если нет совпадений с шаблоном, возвращается else_value. У вас может быть столько пар pattern, value, сколько хотите. Возвращается первое совпадение.

  • test(если_не_пусто, если_пусто) – возвращает если_не_пусто если значение не пусто, в противном случае возвращает если_пусто.

  • titlecase() – возвращает значение поля в заглавном регистре.

  • transliterate() – Возвращает строку в латинском алфавите, образованную приближением звучания слов в исходном поле. Например, если исходное поле - Фёдор Миха́йлович Достоевский, эта функция возвращает Fiodor Mikhailovich Dostoievskii.

  • uppercase() – возвращает значение поля в верхнем регистре.

Использование функций и форматирования в одном шаблоне

Предположим, у вас есть целочисленный настраиваемый столбец #myint, который вы хотите отображать с ведущими нулями, как в 003. Один из способов сделать это - использовать формат 03. Однако по умолчанию, если число (целое или с плавающей запятой) равно нулю, тогда значение отображается как пустая строка, поэтому нулевые значения будут давать пустую строку, а не 000. Если вы хотите увидеть значения 000, используйте как строку формата, так и функцию ifempty, чтобы изменить пустое значение обратно в ноль. Шаблон будет:

{#myint:0>3s:ifempty(0)}

Обратите внимание, что вы также можете использовать префикс и суффикс. Если вы хотите, чтобы номер отображался как [003] или [000], то используйте шаблон:

{#myint:0>3s:ifempty(0)|[|]}

Общий программный режим

Общий программный режим (GPM) заменяет шаблонные выражения программой, написанной на языке шаблонов. Синтаксис языка определяется следующей грамматикой:

program         ::= 'program:' expression_list
expression_list ::= top_expression [ ';' top_expression ]*
top_expression  ::= or_expression
or_expression   ::= and_expression [ '||' and_expression ]*
and_expression  ::= not_expression [ '&&' not_expression ]*
not_expression  ::= [ '!' not_expression ]* | concatenate_expr
concatenate_expr::= compare_expr [ '&' compare_expr ]*
compare_expr    ::= add_sub_expr [ compare_op add_sub_expr ]
compare_op      ::= '==' | '!=' | '>=' | '>' | '<=' | '<' | 'in' | 'inlist' |
                    '==#' | '!=#' | '>=#' | '>#' | '<=#' | '<#'
add_sub_expr    ::= times_div_expr [ add_sub_op times_div_expr ]*
add_sub_op      ::= '+' | '-'
times_div_expr  ::= unary_op_expr [ times_div_op unary_op_expr ]*
times_div_op    ::= '*' | '/'
unary_op_expr   ::= [ add_sub_op unary_op_expr ]* | expression
expression      ::= identifier | constant | function | assignment | field_reference |
                    if_expr | for_expr | break_expr | continue_expr |
                    '(' expression_list ')' | function_def
field_reference ::= '$' [ '$' ] [ '#' ] identifier
identifier      ::= id_start [ id_rest ]*
id_start        ::= letter | underscore
id_rest         ::= id_start | digit
constant        ::= " string " | ' string ' | number
function        ::= identifier '(' expression_list [ ',' expression_list ]* ')'
function_def    ::= 'def' identifier '(' top_expression [ ',' top_expression ]* ')' ':'
                    expression_list 'fed'
assignment      ::= identifier '=' top_expression
if_expr         ::= 'if' condition 'then' expression_list
                    [ elif_expr ] [ 'else' expression_list ] 'fi'
condition       ::= top_expression
elif_expr       ::= 'elif' condition 'then' expression_list elif_expr | ''
for_expr        ::= for_list | for_range
for_list        ::= 'for' identifier 'in' list_expr
                    [ 'separator' separator_expr ] ':' expression_list 'rof'
for_range       ::= 'for' identifier 'in' range_expr ':' expression_list 'rof'
range_expr      ::= 'range' '(' [ start_expr ',' ] stop_expr
                    [ ',' step_expr [ ',' limit_expr ] ] ')'
list_expr       ::= top_expression
break_expr      ::= 'break'
continue_expr   ::= 'continue'
separator_expr  ::= top_expression
start_expr      ::= top_expression
stop_expr       ::= top_expression
step_expr       ::= top_expression
limit_expr      ::= top_expression

Примечания:

  • top_expression всегда имеет значение. Значение expression_list - это значение последнего top_expression в списке. Например, значение списка выражений 1;2;'foobar';3 равно 3.

  • В логическом контексте любое непустое значение - True

  • В логическом контексте пустым значением является False

  • Строки и числа могут использоваться как взаимозаменяемые. Например, 10 и '10' - это одно и то же.

  • Комментарии - это строки, начинающиеся с символа „#“. Комментарии, начинающиеся позже в строке, не поддерживаются.

Приоритет оператора

Приоритет оператора (порядок оценки) от наивысшего (оценивается первым) до самого низкого (оценивается последним):

  • Вызовы функций, константы, выражения в скобках, выражения операторов, выражения присваивания, ссылки на поля.

  • Унарный плюс (+) и минус (-). Эти операторы вычисляют справа налево.

    Эти и все другие арифметические операторы возвращают целые числа, если результат выражения дает дробную часть, равную нулю. Например, если выражение возвращает 3.0, оно изменяется на 3.

  • Умножение (*) и деление (/). Эти операторы ассоциативны и выполняются слева направо. Используйте круглые скобки, если хотите изменить порядок оценки.

  • Сложение (+) и вычитание (-). Эти операторы ассоциативны и выполняются слева направо.

  • Числовые и строковые сравнения. Эти операторы возвращают 1, если сравнение прошло успешно, в противном случае - пустую строку (''). Сравнения не ассоциативны: a < b < c - синтаксическая ошибка.

  • Конкатенация строк (&). Оператор & возвращает строку сформированную путем объединения левого и правого выражений. Пример: 'aaa' & 'bbb'` возвращает ``'aaabbb'. Оператор является ассоциативным и оценивает слева направо.

  • Унарное логическое НЕ (!). Этот оператор возвращает '1', если выражение ложно (возвращает пустую строку), в противном случае ''.

  • Логическое и (&&). Этот оператор возвращает „1“, если и левое, и правое выражения имеют значение True, или пустую строку '', если любое из них имеет значение False. Он ассоциативен, вычисляется слева направо и выполняет `short-circuiting `_.

  • Логическое ИЛИ (||). Этот оператор возвращает 1, если левое или правое выражение истинно, или '', если оба ложны. Он ассоциативен, вычисляется слева направо и выполняет short-circuiting `_. Это `включающее ИЛИ, возвращающее``“1“``, если и левое, и правое выражения истинны.

Ссылки на поля

Field_reference оценивает значение поля метаданных, названного именем поиска, которое следует за $ или $$. Использование $ эквивалентно использованию функции field(). Использование $$ эквивалентно использованию функции raw_field. Примеры:

* $authors ==> field('authors')
* $#genre ==> field('#genre')
* $$pubdate ==> raw_field('pubdate')
* $$#my_int ==> raw_field('#my_int')

If выражения

Выражения if сначала оценивают условие. Если condition равно True (непустое значение), тогда expression_list в предложении then оценивается. Если оно равно False, то при его наличии вычисляется список выражений в предложении elif или else. Части elif и else не являются обязательными. Слова if, then, elif, else и fi зарезервированы; вы не можете использовать их в качестве имен идентификаторов. Вы можете помещать символы новой строки и пробелы везде, где они имеют смысл. condition - это top_expression, а не expression_list; точки с запятой не допускаются. expression_list - это разделенные точкой с запятой последовательности «top_expressions». Выражение if возвращает результат последнего выражения top_expression в вычисленном списке выражений или пустую строку, если список выражений не оценивался.

Примеры:

* program: if field('series') then 'yes' else 'no' fi
* program:
      if field('series') then
          a = 'yes';
          b = 'no'
      else
          a = 'no';
          b = 'yes'
      fi;
      strcat(a, '-', b)

Пример вложенного if:

program:
  if field('series') then
    if check_yes_no(field('#mybool'), '', '', '1') then
      'yes'
    else
      'no'
    fi
  else
    'no series'
  fi

Как сказано выше, if выдаёт значение. Это означает, что всё следующее эквивалентно:

* program: if field('series') then 'foo' else 'bar' fi
* program: if field('series') then a = 'foo' else a = 'bar' fi; a
* program: a = if field('series') then 'foo' else 'bar' fi; a

В качестве последнего примера эта программа возвращает значение столбца series, если в книге есть серия, в противном случае значение столбца title:

program: field(if field('series') then 'series' else 'title' fi)

For выражения

Выражение for выполняет итерацию по списку значений, обрабатывая их по одному. Выражение list_expression должно соответствовать либо полю метаданных lookup name, например tags или # genre, либо списку значений. Функция range() (см. ниже) генерирует список чисел. Если результатом является допустимое lookup name, тогда выбирается значение поля и используется разделитель, указанный для этого типа поля. Если результат не является допустимым именем поиска, предполагается, что это список значений. Предполагается, что список разделен запятыми, если не указано необязательное ключевое слово separator. В этом случае значения списка должны быть разделены результатом вычисления separator_expr. Каждое значение в списке присваивается указанной переменной, после чего вычисляется expression_list. Вы можете использовать break, чтобы выйти из цикла, и continue, чтобы перейти к началу цикла для следующей итерации.

Пример: этот шаблон удаляет первое иерархическое имя для каждого значения в жанре (#genre), создавая список с новыми именами:

program:
  new_tags = '';
  for i in '#genre':
    j = re(i, '^.*?\.(.*)$', '\1');
    new_tags = list_union(new_tags, j, ',')
  rof;
  new_tags

Если исходный жанр - History.Military, Science Fiction.Alternate History, ReadMe, то шаблон возвращает Military, Alternate History, ReadMe. Вы можете использовать этот шаблон в calibre Массовое редактирование метаданных - Поиск и замена с помощью: guilabel:` Search for`, установленного на template, чтобы удалить первый уровень иерархии и присвоить полученное значение Жанру.

Примечание: последняя строка в шаблоне, new_tags, в этом случае не является строго необходимой, потому что for возвращает значение последнего top_expression в списке выражений. Значение присваивания - это значение его выражения, поэтому значение оператора for - это то, что было присвоено new_tags.

Определение функции

Если у вас есть повторяющийся код в шаблоне, вы можете поместить этот код в локальную функцию. Ключевое слово def запускает определение. За ним следует имя функции, список аргументов, затем код функции. Определение функции заканчивается ключевым словом fed

Аргументы позиционные. При вызове функции предоставленные аргументы сопоставляются слева направо с определенными параметрами, при этом значение аргумента присваивается параметру. Будет ошибкой указывать больше аргументов, чем определено параметров. Параметры могут иметь значения по умолчанию, например a = 25. Если для этого параметра не указан аргумент, используется значение по умолчанию, в противном случае параметру присваивается пустая строка.

Оператор return можно использовать в локальной функции.

Функция должна быть определена до того, как её можно будет использовать.

Пример. Этот шаблон вычисляет приблизительную продолжительность в годах, месяцах и днях из числа дней. Функция to_plural() форматирует вычисляемые значения. Обратите внимание, что в примере также используется оператор &:

program:
      days = 2112;
      years = floor(days/360);
      months = floor(mod(days, 360)/30);
      days = days - ((years*360) + (months * 30));

      def to_plural(v, str):
              if v == 0 then return '' fi;
              return v & ' ' & (if v == 1 then str else str & 's' fi) & ' '
      fed;

      to_plural(years, 'year') & to_plural(months, 'month') & to_plural(days,'day')

Операторы отношения

Операторы отношения возвращают 1, если сравнение истинно, в противном случае - пустую строку („“).

Есть две формы операторов отношения: сравнение строк и сравнение чисел.

При сравнении строк выполняется сравнение строк без учета регистра с использованием лексического порядка. Поддерживаемые операторы сравнения строк: ==, !=, <, <=, >, >=, in и inlist. Для оператора in результат левого выражения интерпретируется как шаблон регулярного выражения. Оператор in имеет значение True, если значение левого регулярного выражения совпадает со значением правого выражения. Оператор inlist верен, если левое регулярное выражение соответствует любому из элементов в правом списке, где элементы в списке разделены запятыми. В совпадениях регистр не учитывается.

Операторы сравнения чисел: ==#, !=#, <#, <=#, >#, >=#. Левое и правое выражения должны оцениваться как числовые значения с двумя исключениями: как строковое значение «None» (неопределенное поле), так и пустая строка оцениваются как нулевое значение.

Примеры:

  • program: field('series') == 'foo' возвращает '1' если серия книги - „foo“, иначе - ''.

  • program: 'f.o' in field('series') вернёт '1' если серия книги соответствует регулярному выражению f.o (например, foo, Off Onyx и т. д.), иначе ''.

  • program: 'science' inlist field('#genre') returns '1' if any of the book’s genres match the regular expression science, e.g., Science, History of Science, Science Fiction etc., otherwise ''.

  • program: '^science$' inlist field('#genre') вернёт '1' если какой-либо из жанров книги точно соответствует регулярному выражению ^science$, например Science. Жанры History of Science и Science Fiction не совпадают. Если совпадений нет, возвращается ''.

  • program: if field('series') != 'foo' then 'bar' else 'mumble' fi returns 'bar' если серия книги не foo. В противном случае возвращается 'mumble'.

  • program: if field('series') == 'foo' || field('series') == '1632' then 'yes' else 'no' fi returns 'yes' if series is either 'foo' or '1632', иначе '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 > оператор выполняет лексическое сравнение.

  • program: if 11 ># 2 then 'yes' else 'no' fi вернёт 'yes' потому что оператор ># выполняет числовое сравнение.

Дополнительные доступные функции

Следующие функции доступны в дополнение к описанным в Single Function Mode.

В GPM все функции, описанные в Single Function Mode, требуют дополнительного первого параметра, определяющего значение для работы. Все параметры - это expression_lists (списки выражений) (см. Грамматику выше).

  • add(x [, y]*) – возвращает сумму своих аргументов. Выдает исключение, если аргумент не является числом. В большинстве случаев вместо этой функции можно использовать оператор +.

  • and(value [, value]*) – возвращает строку «1», если все значения не пустые, в противном случае возвращает пустую строку. Значения - сколько захотите. В большинстве случаев вместо этой функции можно использовать оператор &&. Одна из причин не заменять and на && заключается в том, что короткое замыкание может изменить результаты из-за побочных эффектов. Например, and(a='',b=5) всегда будет выполнять оба присваивания, а оператор && не будет выполнять второе.

  • assign(id, val) – присваивает val идентификатору id`, а затем возвращает ``val. id должен быть идентификатором, а не выражением. В большинстве случаев вместо этой функции можно использовать оператор =.

  • approximate_formats() – возвращает разделённый запятыми список форматов, связанных с книгой. Нет никакой гарантии, что список правильный, хотя, вероятно, это так. Эта и другие функции с нулевыми параметрами могут быть вызваны в режиме Template Program Mode (см. ниже) с использованием шаблона``{:“approximate_formats()“}``. Обратите внимание, что имена результирующих форматов всегда пишутся в верхнем регистре, как в EPUB. Функция approximate_formats() значительно быстрее, чем функции formats_..., обсуждаемые ниже.

  • author_links(val_separator, pair_separator) – возвращает строку, содержащую список авторов и значения ссылок этих авторов в форме:

    author1 val_separator author1_link pair_separator author2 val_separator author2_link etc.
    

    Автор отделяется от значения ссылки строкой val_separator без дополнительных пробелов. Пары author: linkvalue разделяются строковым аргументом pair_separator без дополнительных пробелов. Вы можете выбрать строки-разделители, которые не встречаются в именах авторов или в ссылках. Автор включается, даже если ссылка на автора пуста.

  • author_sorts(val_separator) – возвращает строку, содержащую список значений сортировок автора для авторов книги. Сортировка - метаданные автора (отличающиеся от author_sort в книгах). Возвращаемый список имет формат author_sort1 val_separator author_sort2 и т.д. без добавляемых пробелов. Значения author_sort в этом списке в том же порядке, как и авторы в книге. Если вам нужны пробелы вокруг разделителя val_separator, включите их в строку val_separator.

  • book_count(query, use_vl) – возвращает количество книг, найденных при поиске query. Если use_vl равно 0 (ноль), тогда виртуальные библиотеки игнорируются. Эта функция и её компаньон book_values() особенно полезны при поиске по шаблону, поддерживая поиск, объединяющий информацию из многих книг, например, поиск серий только с одной книгой. Его нельзя использовать в составных столбцах, если для настройки allow_template_database_functions_in_composites установлено значение True. Его можно использовать только в графическом интерфейсе.

    Например, этот поиск по шаблону использует эту функцию и её компаньон для поиска всех серий только с одной книгой:

    1. Обозначьте сохранённый шаблон (используя Настройки → Дополнительно → Функции шаблона) с именем series_only_one_book (имя может быть произвольным). Шаблон такой:

      program:
          vals = globals(vals='');
          if !vals then
              all_series = book_values('series', 'series:true', ',', 0);
              for series in all_series:
                  if book_count('series:="' & series & '"', 0) == 1 then
                      vals = list_join(',', vals, ',', series, ',')
                  fi
              rof;
              set_globals(vals)
          fi;
          str_in_list(vals, ',', $series, 1, '')
      

    При первом запуске шаблона (проверена первая книга) он сохраняет результаты поиска в базе данных в переменной шаблона global с именем vals. Эти результаты используются для проверки последующих книг без повторного поиска.

    1. Использовать сохраненный шаблон в поиске по шаблону:

      template:"program: series_only_one_book()#@#:n:1"
      

    Использование сохранённого шаблона вместо ввода шаблона в поиск устраняет проблемы, вызванные требованием избегать кавычек в выражениях поиска.

  • book_values(column, query, sep, use_vl) – возвращает список уникальных значений, содержащихся в столбце column (имя поиска), разделенных sep, в найденных книгах путем поиска query. Если use_vl равно 0 (ноль), тогда виртуальные библиотеки игнорируются. Эта функция и её компаньон book_count() особенно полезны при поиске по шаблону, поддерживая поиск, объединяющий информацию из многих книг, например, поиск серий только с одной книгой. Его нельзя использовать в составных столбцах, если для настройки allow_template_database_functions_in_composites установлено значение True. Его можно использовать только в графическом интерфейсе.

  • booksize() – возвращает значение поля calibre „size“. Возвращает „“, если форматов нет.

  • check_yes_no(field_name, is_undefined, is_false, is_true) – проверяет, является ли значение поля да / нет, названного именем поиска field_name, одним из значений, заданных параметрами, возвращая 'yes', если найдено совпадение, в противном случае возвращает пустую строку. Установите для параметра is_undefined, is_false или is_true значение 1 (число), чтобы проверить это условие, в противном случае установите значение 0. Пример:

    check_yes_no("#bool", 1, 0, 1) возвращает 'Yes' если поле yes/no #bool имеет значение True или undefined (ни True, ни False).

    Для более чем одного из is_undefined, is_false или is_true может быть установлено значение 1.

  • ceiling(x) – возвращает наименьшее целое число, большее или равное x. Выдает исключение, если x не является числом.

  • character(character_name) - возвращает символ, названный character_name. Например, character('newline) возвращает символ новой строки ('\n'). Поддерживаемые имена символов: newline, return, tab, и backslash.

  • cmp(x, y, lt, eq, gt) – сравнивает x и y после преобразования обоих в числа. Возвращает lt, если x <# y. Возвращает eq, если x ==# y. В противном случае возвращает gt. Во многих случаях операторы числового сравнения (==#, <#, ># и т. п.) могут заменить эту функцию.

  • connected_device_name(storage_location_key) – если устройство подключено, вернуть имя устройства, в противном случае вернуть пустую строку. Каждое место хранения на устройстве может иметь другое имя. Названия storage_location_key - 'main', 'carda' и 'cardb'. Эта функция работает только в графическом интерфейсе.

  • connected_device_uuid(storage_location_key) – если устройство подключено, вернуть uuid устройства (уникальный идентификатор), иначе вернуть пустую строку. У каждого места хранения на устройстве свой uuid. Названия локаций - 'main', 'carda' и 'cardb'. Эта функция работает только в графическом интерфейсе.

  • current_library_name() – возвращает последнее имя в пути к текущей библиотеке calibre.

  • current_library_path() – возвращает полный путь к текущей библиотеке calibre.

  • current_virtual_library_name() – вернуть имя текущей виртуальной библиотеки, если она есть, иначе пустую строку. Регистр имени библиотеки сохраняется. Пример: program: current_virtual_library_name().Эта функция работает только в GUI.

  • date_arithmetic(date, calc_spec, fmt) – вычислить новую дату от date с помощью calc_spec. Вернуть новую дату, отформатированную в соответствии с необязательным fmt: если не указано, то результат будет в формате ISO. calc_spec - это строка, образованная конкатенацией пар vW (valueWhat), где v - возможно отрицательное число, а W - одна из следующих букв:

    • s: добавить v секунд к date

    • m: добавить v минут к date

    • h: добавить v часов к date

    • d: добавить v дней к date

    • w: добавить v недель к date

    • y: добавить v лет к date где в году 365 дней.

    Пример: '1s3d-1m' добавит 1 секунду, прибавит 3 дня и вычтет 1 минуту из date.

  • days_between(date1, date2) – возвращает количество дней между date1 и date2. Число положительно, если date1 больше date2, в противном случае отрицательно. Если date1 или date2 не являются датой, функция возвращает пустую строку.

  • divide(x, y) – возвращает x / y. Выдает исключение, если x или y не являются числами. Эту функцию часто можно заменить оператором /.

  • eval(string) – оценивает строку как программу, передавая локальные переменные. Это позволяет использовать шаблонный процессор для построения сложных результатов из локальных переменных. В Template Program Mode, поскольку символы { и }`интерпретируются до оценки шаблона, вы должны использовать`[[`для символа `{ и ]] для символа``}``. Они конвертируются автоматически. Также обратите внимание, что префиксы и суффиксы (синтаксис |prefix|suffix ) не могут использоваться в аргументе этой функции при использовании Template Program Mode.

  • extra_file_size(file_name) – возвращает размер в байтах дополнительного файла file_name в папке data/ книги, если он существует, иначе -1. См. также функции has_extra_files(), extra_file_names() and extra_file_modtime(). Эту функцию можно использовать только в графическом интерфейсе.

  • extra_file_modtime(file_name, format_spec) – возвращает время модификации дополнительного файла file_name в папке data/ книги, если он существует, иначе -1. Modtime форматируется в соответствии с format_spec (см. format_date()). Если format_spec пусто, возвращает modtime как количество секунд с плавающей запятой с начала эпохи. См. также функции has_extra_files(), extra_file_names() и extra_file_size(). Эпоха зависит от ОС. Эту функцию можно использовать только в графическом интерфейсе.

  • extra_file_names(sep [, pattern]) – возвращает разделенный сепараторами (sep) список дополнительных файлов в папке книги data/. Если указан необязательный параметр pattern, регулярное выражение, то список фильтруется для файлов, соответствующих pattern. Сопоставление с pattern нечувствительно к регистру. См. также функции has_extra_files(), extra_file_modtime() и extra_file_size(). Эту функцию можно использовать только в графическом интерфейсе.

  • field(lookup_name) – возвращает поле метаданных с именем lookup_name.

  • field_exists(field_name) – проверяет, существует ли поле (столбец) с именем field_name, возвращая '1', если это так, и пустую строку, если нет.

  • finish_formatting(val, fmt, prefix, suffix) – применяет формат, префикс и суффикс к значению так же, как в шаблоне вроде {series_index:05.2f| - |- }. Эта функция предназначена для упрощения преобразования сложных шаблонов, выполняемых в режиме одной функции или шаблонной программы, в шаблоны GPM. Например, следующая программа делает то же, что и указанный шаблон:

    program: finish_formatting(field("series_index"), "05.2f", " - ", " - ")
    

    Другой пример: для шаблона {series:re(([^\s])[^\s]+(\s|$),\1)}{series_index:0>2s| - | - }{title} используйте:

    program:
      strcat(
        re(field('series'), '([^\s])[^\s]+(\s|$)', '\1'),
           finish_formatting(field('series_index'), '0>2s', ' - ', ' - '),
           field('title')
      )
    
  • first_matching_cmp(val, [ cmp, result, ]* else_result) – сравнивает val < cmp в последовательности, возвращая связанный результат для первого успешного сравнения. Если сравнение не удалось, возвращает else_result. Пример:

    i = 10;
    first_matching_cmp(i,5,"small",10,"middle",15,"large","giant")
    

    возвращает "large". В том же примере с первым значением 16 возвращается "giant".

  • first_non_empty(value [, value]*) – возвращает первое непустое значение. Если все значения пусты, возвращается пустая строка. Вы можете иметь сколько угодно значений.

  • floor(x) – возвращает наибольшее целое число, меньшее или равное x. Выдает исключение, если x не является числом.

  • format_date(val, format_string) – форматирует значение, которое должно быть строкой даты, используя format_string, возвращая строку. Коды форматирования:

    • d : день как число без нуля в начале (от 1 до 31)

    • dd : день как число с нулем в начале (от 01 до 31)

    • ddd : сокращенное название дня недели (например, с «Пн» по «Вс»).

    • dddd : длинное локализованное название дня (например, с Понедельник по Воскресенье).

    • M : месяц как число без нуля в начале (от 1 до 12).

    • MM : месяц как число с нулем в начале (от 01 до 12)

    • MMM : сокращенное название месяца (например, с «Янв» по «Дек»).

    • MMMM : длинное локализованное название месяца (например, с «Январь» по «Декабрь»).

    • yy : год в виде двузначного числа (от 00 до 99).

    • yyyy : четыре цифры года.

    • h : часы без 0 в начале (от 0 до 11 или от 0 до 23, в зависимости от am/pm)

    • hh : часы с 0 в начале (с 00 до 11 или с 00 до 23, в зависимости от am/pm)

    • m : минуты без 0 в начале (от 0 до 59)

    • mm : минуты с 0 в начале (от 00 до 59)

    • s : секунды без начального 0 (от 0 до 59)

    • ss : секунды с 0 в начале (от 00 до 59)

    • ap : использовать 12-часовые часы вместо 24-часовых, с заменой „ap“ на локализованную строку для am или pm.

    • AP : использовать 12-часовой формат времени вместо 24-часового с заменой „AP“ на локализованную строку для AM или PM.

    • iso : дата с указанием времени и часового пояса. Должен быть единственный формат.

    • to_number : преобразовать дату и время в число с плавающей запятой (timestamp отметка времени)

    • from_number : преобразовать число с плавающей запятой (отметку времени) в дату в формате iso. Если вам нужен другой формат даты, добавьте желаемую строку форматирования после from_number и двоеточия (:). Пример: from_number:MMM dd yyyy

    Вы можете получить неожиданные результаты, если форматируемая дата содержит локализованные названия месяцев, что может произойти, если вы изменили настройки формата даты, чтобы они содержали MMMM. В этом случае вместо использования функции field(), как в:

    format_date(field('pubdate'), 'yyyy')
    

    используйте функцию raw_field(), как в:

    format_date(raw_field('pubdate'), 'yyyy')
    
  • format_date_field(field_name, format_string)` – форматирует значение в поле field_name, которое должно быть искомым именем поля даты, стандартным или настраиваемым. См. format_date() для кодов форматирования. Эта функция намного быстрее, чем format_date, и её следует использовать при форматировании значения в поле (столбце). Её нельзя использовать для вычисленных дат или дат в строковых переменных. Примеры:

    format_date_field('pubdate', 'yyyy.MM.dd')
    format_date_field('#date_read', 'MMM dd, yyyy')
    
  • formats_modtimes(date_format_string) – возвращает разделённый запятыми список разделённых двоеточиями элементов FMT:DATE, представляющих собой время изменения форматов книги. Параметр date_format_string задаёт формат даты. Смотрите функцию format_date() для подробностей. Вы можете использовать функцию select для получения времени модификации для заданного формата. Названия форматов всегда в верхнем регистре, например EPUB.

  • formats_paths() – возвращает разделённый запятыми список элементов, разделённых двоеточиями``FMT:PATH``, представляющих собой полный путь к форматам книги. Вы можете использовать функцию select для получения пути для заданного формата. Названия форматов всегда в верхнем регистре, например EPUB.

  • formats_sizes() – возвращает разделённый запятыми список элементов, разделённых двоеточиями``FMT:SIZE``, представляющих собой размеры в байтах форматов книги. Вы можете использовать функцию select для получения размера для заданного формата. Названия форматов всегда в верхнем регистре, например EPUB.

  • fractional_part(x) – возвращает значение после десятичной точки. Например, fractional_part(3.14) возвращает 0.14`. Выдает исключение, если ``x не является числом.

  • get_link(field_name, field_value) – fetch the link for field field_name with value field_value. If there is no attached link, return the empty string. Examples:

  • The following returns the link attached to the tag Fiction:

    get_link('tags', 'Fiction')
    
  • This template makes a list of the links for all the tags associated with a book in the form value:link, ...:

    program:
     ans = '';
     for t in $tags:
         l = get_link('tags', t);
         if l then
             ans = list_join(', ', ans, ',', t & ':' & get_link('tags', t), ',')
         fi
     rof;
     ans
    
  • has_cover() – возвращает 'Yes', если у книги есть обложка, иначе возвращает пустую строку

  • has_extra_files([pattern]) – возвращает количество дополнительных файлов, иначе „“ (пустая строка). Если указан необязательный параметр pattern (регулярное выражение), то список фильтруется по файлам, которые соответствуют pattern, прежде чем файлы будут подсчитаны. Сопоставление с pattern нечувствительно к регистру. См. также функции extra_file_names(), extra_file_size() и extra_file_modtime(). Эту функцию можно использовать только в графическом интерфейсе.

  • identifier_in_list(val, id_name [, found_val, not_found_val]) – рассматривает val как список идентификаторов, разделённый запятыми. Идентификатор имеет формат id_name:value. id_name параметр - id_name текст для поиска, или id_name или id_name:regexp. Первый случай соответствует, если есть какой-либо идентификатор, соответствующий этому id_name. Второй случай соответствует, если id_name соответствует идентификатору, а регулярное выражение соответствует значению идентификатора. Если указаны found_val и not_found_val, то, если есть совпадение, возвращается found_val, в противном случае возвращается not_found_val. Если found_val и not_found_val не указаны, то, если есть совпадение, возвращается пара identfier:value, иначе пустая строка ('').

  • is_marked() – проверить, помечена ли книга в calibre. Если это так, то вернуть значение метки, либо 'true'``(lower case), либо список именованных меток, разделенных запятыми. Возврат ``'', если книга не отмечена.

  • language_codes(lang_strings) – возвращает коды языка <https://www.loc.gov/standards/iso639-2/php/code_list.php>`_ для строк, взятых из lang_strings. Строки должны быть на языке текущей локализации. Lang_strings - это список, разделённый запятыми.

  • list_contains(value, separator, [ pattern, found_val, ]* not_found_val) – (Псевдоним in_list). Интерпретируя значение как список элементов, разделённых separator, оценивает pattern для каждого значения в списке. Если шаблон соответствует любому значению, вернуть found_val, иначе вернуть not_found_val. Шаблоны и found_value могут повторяться сколько угодно раз, что позволяет возвращать разные значения в зависимости от поиска. Шаблоны проверяются по порядку. Возвращается первое совпадение. Псевдонимы: in_list(), list_contains()

  • list_count(value, separator) – интерпретирует значение как список элементов, разделённых separator, возвращая количество элементов в списке. Псевдонимы: count(), list_count()

  • list_count_matching(list, pattern, separator) – интерпретирует list как список элементов, разделенных separator, возвращая количество элементов в списке, которые соответствуют регулярному выражению pattern. Псевдонимы: list_count_matching(), count_matching()

  • list_difference(list1, list2, separator) – возвращает список, созданный при помощи удаления из списка list1 любого элемента, найденного в списке list2, используя регистронезависимое сравнение. Элементы в списках list1 и list2 разделяются разделителем separator, так же как и элементы в возвращаемом списке.

  • list_equals(list1, sep1, list2, sep2, yes_val, no_val) – возвращает yes_val если list1 и list2 содержат одинаковые элементы, иначе возвращает no_val. Элементы определяются разделением каждого списка с использованием соответствующего символа разделителя (sep1 или sep2). Порядок элементов в списке не важен. Сравнение регистронезависимое.

  • list_intersection(list1, list2, separator) – вернуть список, созданный путём удаления из list1 любого элемента, не найденного в list2, с использованием сравнения без учета регистра. Элементы в list1 и list2 разделены разделителем separator, как и элементы в возвращаемом списке.

  • list_join(with_separator, list1, separator1 [, list2, separator2]*) – возвращает список, созданный путем объединения элементов исходных списков (list1 и т. д.), используя with_separator между элементами в списке результатов. Элементы в каждом источнике список[123...] разделены соответствующим разделителем[123...]. Список может содержать нулевые значения. Это может быть поле типа publisher, которое является однозначным, фактически представляет собой список из одного элемента. Дубликаты удаляются с помощью сравнения без учета регистра. Элементы возвращаются в том порядке, в котором они появляются в исходных списках. Если элементы в списках различаются только регистром букв, то используется последний. Все разделители могут состоять из более чем одного символа.

    Пример:

    program:
      list_join('#@#', $authors, '&', $tags, ',')
    

    Вы можете использовать list_join для результатов предыдущих вызовов list_join следующим образом:

    program:
      a = list_join('#@#', $authors, '&', $tags, ',');
      b = list_join('#@#', a, '#@#', $#genre, ',', $#people, '&', 'some value', ',')
    

    Вы можете использовать выражения для создания списка. Например, предположим, что вам нужны элементы для authors и #genre, но с изменением жанра на слово «Genre: «, за которым следует первая буква жанра, то есть genre «Fiction» становится «Genre: F». Это будет сделано следующим образом:

    program:
      list_join('#@#', $authors, '&', list_re($#genre, ',', '^(.).*$', 'Genre: \1'),  ',')
    
  • list_re(src_list, separator, include_re, opt_replace) – создать список, вначале разделив src_list на элементы с помощью символа разделителя. Для каждого элемента в списке проверить, соответствует ли он include_re. Если это так, добавить его в список для возврата. Если opt_replace не является пустой строкой, применить замену перед добавлением элемента в возвращаемый список.

  • list_re_group(src_list, separator, include_re, search_re [, template_for_group]*) – Как и list_re, за исключением того, что замены не являются обязательными. При замене используется re_group(item, search_re, template ...).

  • list_remove_duplicates(list, separator) – вернуть список, созданный путем удаления повторяющихся элементов в list. Если элементы отличаются только регистром, возвращается последний. Элементы в списке list разделены разделителем separator, как и элементы в возвращаемом списке``list``.

  • list_sort(list, direction, separator) – вернуть список, отсортированный с использованием лексической сортировки без учета регистра. Если direction равно нулю, список сортируется по возрастанию, иначе по убыванию. Элементы списка разделены разделителем separator, как и элементы в возвращаемом списке.

  • list_split(list_val, sep, id_prefix) – разделяет list_val на отдельные значения с помощью sep, затем присваивает значения переменным с именем id_prefix_N, где N — позиция значения в списке. Первый элемент имеет позицию 0 (ноль). Функция возвращает последний элемент в списке.

    Пример:

    list_split('one:two:foo', ':', 'var')
    

    эквивалентно:

    var_0 = 'one';
    var_1 = 'two';
    var_2 = 'foo
    
  • list_union(list1, list2, separator) – возвращает список, составленный путем слияния элементов в list1 и list2, удаляя повторяющиеся элементы с помощью сравнения без учета регистра. Если элементы отличаются регистром, используется значение из списка list1. Элементы в списках list1 и list2 разделены разделителем, как и элементы в возвращаемом списке. Псевдонимы: merge_lists(), list_union()

  • mod(x, y) – возвращает floor остаток от x / y. Выдает исключение, если x или y не является числом.

  • multiply(x [, y]*) – возвращает произведение своих аргументов. Выдает исключение, если какой-либо аргумент не является числом. Эту функцию часто можно заменить оператором *.

  • not(value) – возвращает строку «1», если значение пустое, иначе возвращает пустую строку. Эту функцию обычно можно заменить унарным оператором not (!).

  • ondevice() – возвращает 'Yes', если ondevice установлено, иначе возвращает пустую строку.

  • or(value [, value]*) – возвращает строку «1», если все значения не пустые, в противном случае возвращает пустую строку. Значения - сколько захотите. Во многих случаях оператор || может заменить эту функцию. Причина, по которой нельзя заменить - короткое замыкание изменит результаты из-за побочных эффектов.

  • print(a [, b]*) – выводит аргументы на стандартный вывод. Пока вы не запустите calibre из командной строки (calibre-debug -g), вывод идёт в чёрную дыру (black hole). Функция print всегда возвращает свой первый аргумент.

  • range(start, stop, step, limit) – возвращает список чисел, сгенерированный циклом по диапазону, заданному параметрами start, stop и step, с максимальной длиной limit. Первое полученное значение — „start“. Последующие значения next_v = current_v + step. Цикл продолжается, пока next_v stop предполагает, что step положительный, в противном случае, пока next_v stop. Пустой список создается, если start не проходит тест: start = stop, если step положительный. limit устанавливает максимальную длину списка и имеет значение по умолчанию 1000. Параметры start, step и limit являются необязательными. Вызов range() с одним аргументом указывает stop. Два аргумента определяют start и stop. Три аргумента определяют start, stop, and step. Четыре аргумента определяют start, stop, step и limit. Примеры:

    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]) – возвращает поле метаданных с именем lookup_name без применения форматирования. Он оценивает и возвращает необязательный второй аргумент optional_default, если поле не определено (None).

  • raw_list(lookup_name, separator) – возвращает список метаданных с именем lookup_name без применения какого-либо форматирования или сортировки и с элементами, разделенными разделителем separator.

  • re_group(value, pattern [, template_for_group]*) – вернуть строку, полученную путем применения шаблона регулярного выражения к value и замены каждого сопоставленного экземпляра строкой, вычисленной путем замены каждой сопоставленной группы значением, возвращаемым соответствующим шаблоном. В Template Program Mode, как и в случае с шаблоном template и функциями eval, вы используете [[ для { и ]] для }.

    В следующем примере выполняется поиск серии из более чем одного слова с заглавными буквами в первом слове:

    program: re_group(field('series'), "(\S* )(.*)", "{$:uppercase()}", "{$}")'}
    
  • round(x) – возвращает ближайшее к x целое число. Выдает исключение, если x не является числом.

  • series_sort() – возвращает сортировочное значение серии

  • strcat(a [, b]*) – может принимать любое количество аргументов. Возвращает строку, образованную объединением всех аргументов.

  • strcat_max(max, string1 [, prefix2, string2]*) – Возвращает строку, образованную объединением аргументов. Возвращаемое значение инициализируется string1. Пары prefix, string добавляются в конец значения, если результирующая длина строки меньше, чем max. string1 возвращается, даже если string1 длиннее max. Вы можете передать сколько угодно пар prefix, string.

  • strcmp(x, y, lt, eq, gt) – выполняет сравнение x и y как строк без учета регистра. Возвращает lt, если x < y. Возвращает eq, если x == y, иначе возвращает gt. Во многих случаях эту функцию могут заменить операторы лексического сравнения (==`, >, < и т. п.).

  • strcmpcase(x, y, lt, eq, gt) – выполняет лексическое сравнение x и y с учетом регистра. Возвращает lt если x < y, eq если x == y, иначе gt.

    Примечание. Это НЕ поведение по умолчанию, используемое calibre, например, в операторах лексического сравнения (==, >, < и т. д.). Эта функция может привести к неожиданным результатам, желательно использовать strcmp(), когда это возможно.

  • strlen(value) – Возвращает длину строки value.

  • substr(str, start, end) – возвращает подстроку - символы строки str от start до end. Первый символ строки str имеет номер ноль. end отрицательный - это сколько символов будет отсчитываться с конца строки (справа). Если end равен 0 (ноль), то это - последний символ строки. Например, substr('12345', 1, 0) вернёт '2345', и substr('12345', 1, -1) вернёт '234'.

  • subtract(x, y) – возвращает x - y. Выдает исключение, если x или y не являются числами. Эту функцию часто можно заменить оператором -.

  • switch_if([test_expression, value_expression,]+ else_expression) – для каждой пары test_expression, value_expression проверяет, является ли test_expression True (непустым), и если да, то возвращает результат value_expression. Если ни одно из test_expression не равно True, возвращается результат else_expression. У вас может быть столько пар test_expression, value_expression, сколько вы хотите.

  • today() – возвращает текущий день в виде строки. Это значение предназначено для использования в format_date или days_between, но можно использовать как и любую другую строку. Дата в формате ISO.

  • template(x) – оценивает x как шаблон template. Оценка выполняется в собственном контексте, что означает, что переменные не используются совместно между вызывающей стороной и оценкой шаблона.

  • to_hex(val) – возвращает строку val, закодированную в шестнадцатеричном формате. Это полезно при создании URL-ов calibre.

  • urls_from_identifiers(identifiers, sort_results) – задан список идентификаторов, разделённых запятыми, где идентификатор представляет собой пару значений, разделённых двоеточиями (id_name:id_value), возвращает список URL-адресов HTML, разделённых запятыми, сгенерированных из идентификаторов. Список не отсортирован, если sort_results равен 0 (символ или число), в противном случае он сортируется в алфавитном порядке по имени идентификатора. URL-адреса генерируются так же, как столбец встроенных идентификаторов, когда они отображаются в Подробности книги.

Более сложные программы в шаблонных выражениях - Template Program Mode

Template Program Mode (TPM) - смесь General Program Mode и :ref:` Single Function Mode`. TPM отличается от режима одиночной функции тем, что он позволяет писать шаблонные выражения, которые ссылаются на другие поля метаданных, используют вложенные функции, изменяют переменные и выполняют арифметические операции. Он отличается от General Program Mode тем, что шаблон заключен между символами``{`` и``}``и не начинается со слова program:. Программная часть шаблона - это список выражений General Program Mode.

Пример: предположим, что вы хотите, чтобы шаблон отображал серию книги, если она есть, в противном случае показывала бы значение настраиваемого поля #genre. Вы не можете сделать это в Single Function Mode, потому что вы не можете ссылаться на другое поле метаданных в выражении шаблона. В TPM это можно сделать, как демонстрирует следующее выражение:

{#series:'ifempty($, field('#genre'))'}

Пример показывает несколько вещей:

  • TPM используется, если выражение начинается с :' и заканчивается '}. Предполагается, что все остальное находится в Single Function Mode.

  • переменная $ обозначает поле, указанное в шаблоне: в данном случае используется выражение #series.

  • функциям должны быть даны все их аргументы. Нет значения по умолчанию. Например, стандартные встроенные функции должны иметь дополнительный начальный параметр, указывающий исходное поле.

  • пробелы игнорируются и могут использоваться в любом месте выражения.

  • константные строки заключаются в соответствующие кавычки, либо ', либо ''.

В TPM могут использоваться все функции, перечисленные в разделах Single Function Mode и General Program Mode.

В TPM использование символов { и } в строковых литералах может привести к ошибкам или неожиданным результатам, поскольку они сбивают с толку обработчик шаблонов. Он пытается рассматривать их как границы выражения шаблона, а не как символы. В некоторых, но не во всех случаях, вы можете заменить { на [[ и } на ]]. Как правило, если ваша программа содержит символы { и ​​``}``, вам следует использовать General Program Mode.

Как и в General Program Mode, для функций, описанных в Single Function Mode, вы должны указать значение, которое функция должна использовать в качестве первого параметра в дополнение к документированным параметрам. В TPM вы можете использовать $ для доступа к значению, указанному в lookup name имени поиска для шаблонного выражения.

Режим шаблона Python

Режим шаблонов Python (PTM) позволяет создавать шаблоны с использованием родного Python и calibre API. API базы данных будет наиболее полезным; дальнейшее обсуждение выходит за рамки данного руководства. Шаблоны PTM быстрее и могут выполнять более сложные операции, но вы должны знать, как писать код на python, используя calibre API.

Шаблон PTM начинается с:

python:
def evaluate(book, context):
    # book is a calibre metadata object
    # context is an instance of calibre.utils.formatter.PythonTemplateContext,
    # which currently contains the following attributes:
    # db: a calibre legacy database object.
    # globals: the template global variable dictionary.
    # arguments: is a list of arguments if the template is called by a GPM template, otherwise None.
    # funcs: used to call Built-in/User functions and Stored GPM/Python templates.
    # Example: context.funcs.list_re_group()

    # your Python code goes here
    return 'a string'

Вы можете добавить приведенный выше текст в свой шаблон с помощью контекстного меню, доступ к которому обычно осуществляется с помощью щелчка правой кнопкой мыши. Комментарии несущественны и могут быть удалены. Вы должны использовать отступы Python.

Объект контекста поддерживает str(context), который возвращает строку содержимого контекста, и context.attributes, который возвращает список имён атрибутов в контексте.

Атрибут context.funcs позволяет вызывать встроенные и пользовательские функции шаблонов, а также Сохранённые шаблоны GPM/Python, чтобы вы могли выполнять их непосредственно в своем коде. Функции извлекаются по их именам. Если имя конфликтует с ключевым словом Python, добавьте в конце имени символ подчеркивания. Примеры:

context.funcs.list_re_group()
context.funcs.assert_()

Вот пример шаблона PTM, который создает список всех авторов серии. Список хранится как Столбец, состоящий из других столбцов, ведущих себя как теги. Он отображается в Описание книги и отмечен как Категории в отдельных строкахНастройки → Оформление → Описание книги). Этот параметр требует, чтобы список был разделён запятыми. Чтобы удовлетворить это требование, шаблон преобразует запятые в именах авторов в точки с запятой, а затем создаёт список авторов, разделённых запятыми. Затем авторы сортируются, поэтому в шаблоне используется author_sort.

python:
def evaluate(book, context):
    if book.series is None:
        return ''
    db = context.db.new_api
    ans = set()
    # Get the list of books in the series
    ids = db.search(f'series:"={book.series}"', '')
    if ids:
        # Get all the author_sort values for the books in the series
        author_sorts = (v for v in db.all_field_for('author_sort', ids).values())
        # Add the names to the result set, removing duplicates
        for aus in author_sorts:
            ans.update(v.strip() for v in aus.split('&'))
    # Make a sorted comma-separated string from the result set
    return ', '.join(v.replace(',', ';') for v in sorted(ans))

Вывод в Описание книги выглядит так:

Диалог конвертации электронной книги

Сохранённые шаблоны

И Общий программный режим, и Режим шаблона Python поддерживают сохранение шаблонов и вызов этих шаблонов из другого шаблона, во многом аналогично вызову хранимых функций. Вы сохраняете шаблоны, используя Настройки → Расширенные → Шаблонные функции. В этом диалоговом окне - ​​дополнительная информация. Вы вызываете шаблон так же, как вызываете функцию, передавая позиционные аргументы, если необходимо. Аргументом может быть любое выражение. Примеры вызова шаблона, предполагая, что сохраненный шаблон называется foo:

  • foo() – вызов шаблона без аргументов.

  • foo(a, b) вызывает шаблон, передавая значения переменных a и b.

  • foo(if field('series') then field('series_index') else 0 fi) – если в книге есть series, то передать series_index, в противном случае - значение 0.

В GPM вы извлекаете аргументы, переданные при вызове сохраненного шаблона, с помощью функции arguments. Она и объявляет, и инициализирует локальные переменные, фактически параметры. Переменные являются позиционными; они получают значение параметра, заданного при вызове, в той же позиции. Если соответствующий параметр не указан в вызове, тогда arguments присваивает этой переменной предоставленное значение по умолчанию. Если значение по умолчанию отсутствует, переменной присваивается пустая строка. Например, следующая функция arguments объявляет 2 переменные, key, alternate:

arguments(key, alternate='series')

Примеры, снова предполагаем, что сохраненный шаблон назван foo:

  • foo('#myseries') – аргументу key присваивается значение 'myseries', а аргументу alternate присваивается значение по умолчанию 'series'.

  • foo('series', '#genre') переменной ``key присваивается значение 'series', а переменной alternate присваивается значение '#genre'.

  • foo() - переменной key присваивается пустая строка, а переменной alternate присваивается значение 'series'.

В PTM аргументы передаются в параметре arguments, который представляет собой список строк. Невозможно указать значения по умолчанию. Вы должны проверить длину списка аргументов, чтобы убедиться, что количество аргументов соответствует ожидаемому.

Простой способ проверить сохраненные шаблоны - использовать диалоговое окно Тестер шаблонов. Для облегчения доступа используйте сочетание клавиш в Preferences-Advanced-Keyboard shortcuts-Template tester. Ярлык для диалогового окна Сохраненные шаблоны“ поможет быстрее переключаться между тестером и редактированием исходного кода сохраненного шаблона.

Передача шаблонам дополнительной информации

Разработчик может выбрать передачу дополнительной информации процессору шаблонов, например метаданные книги для конкретного приложения или информацию о том, что процессору предлагается сделать. Шаблон может получить доступ к этой информации и использовать ее во время оценки.

** Разработчик: как передать дополнительную информацию **

Дополнительная информация - это словарь dict Python, содержащий пары variable_name: variable_value, где значения должны быть строками. Шаблон может получить доступ к dict, создавая локальные переменные шаблона с именем variable_name, содержащие значение variable_value. Пользователь не может изменить имя, поэтому лучше использовать имена, которые не будут конфликтовать с другими локальными переменными шаблона, например, добавив к имени префикс подчеркивания _.

Этот dict передается процессору шаблонов (formatter) с использованием именованного параметра global_vars=your_dict. Полная сигнатура метода:

def safe_format(self, fmt, kwargs, error_value, book,
                column_name=None, template_cache=None,
                strip_results=True, template_functions=None,
                global_vars={})

** Автор шаблона: как получить доступ к дополнительной информации **

Вы получаете доступ к дополнительной информации (словарю globals) в шаблоне с помощью шаблонной функции:

globals(id[=expression] [, id[=expression]]*)

где id - любое допустимое имя переменной. Эта функция проверяет, содержит ли дополнительная информация, предоставленная разработчиком, имя. Если это так, функция присваивает предоставленное значение локальной переменной шаблона с этим именем. Если имя отсутствует в дополнительной информации и если предоставлено expression, то expression оценивается, и результат присваивается локальной переменной. Если ни значение, ни выражение не предоставлены, функция присваивает пустую строку ('') локальной переменной.

Шаблон может установить значение в словаре globals с помощью шаблонной функции:

set_globals(id[=expression] [, id[=expression]]*)

Эта функция устанавливает globals dict key:value пару id:value, где value - значение шаблонной локальной переменной id. Если эта локальная переменная не существует, тогда value устанавливается равным результату вычисления выражения expression.

Замечания о разнице между режимами

Три программных режима Single Function Mode (SFM), Template Program Mode (TPM) и General Program Mode (GPM) работают по-разному. SFM задуман как „простой“, поэтому он скрывает много тонкостей в языке программирования.

Различия:

  • В SFM значение столбца всегда передается как „invisible“ «невидимый» первый аргумент функции, включенной в шаблон.

  • SFM не поддерживает разницу между переменными и строками; все значения являются строками.

  • Следующий шаблон SFM возвращает либо название серии, либо строку «no series»:

    {series:ifempty(no series)}
    

    Эквивалентный шаблон в TPM

    {series:'ifempty($, 'no series')'}
    

    Эквивалентный шаблон в GPM

    program: ifempty(field('series'), 'no series')
    

    Первый аргумент ifempty - это значение поля series. Второй аргумент - это строка no series. В SFM автоматически передается первый аргумент, значение поля (невидимый аргумент).

  • Некоторые функции-шаблоны, например, booksize() и current_library_name(), не принимают аргументов. Из-за „невидимого аргумента“ вы не можете использовать эти функции в SFM.

  • Вложенные функции, когда функция вызывает другую функцию для вычисления аргумента, не могут использоваться в SFM. Например, этот шаблон, предназначенный для возврата первых 5 символов значения серии в верхнем регистре, не будет работать в SFM:

    {series:uppercase(substr(0,5))}
    
  • TPM и GPM поддерживают вложенные функции. Вышеупомянутый шаблон в TPM будет:

    {series:'uppercase(substr($, 0,5))'}
    

    В GPM это было бы:

    program: uppercase(substr(field('series'), 0,5))
    
  • Как отмечалось выше в разделе Template Program Mode, использование символов { и``}`` в строковых литералах TPM может привести к ошибкам или неожиданным результатам, поскольку они сбивают с толку обработчик шаблонов. Он пытается рассматривать их как границы шаблона, а не как символы. В некоторых, но не во всех случаях, вы можете заменить { на [[ и } на ]]. Как правило, если ваша программа содержит символы { и ​​``}``, вам следует использовать General Program Mode.

Пользовательские шаблонные функции Python

Вы можете добавить свои собственные функции Python в обработчик шаблонов. Такие функции можно использовать в любом из трех режимов программирования шаблона. Функции добавляются в Preferences - Advanced - Template functions. Инструкции отображаются в этом диалоговом окне.

Особые примечания для шаблонов сохранения/отправки

Специальная обработка применяется, когда шаблон используется в шаблоне save to disk или send to device. Значения полей очищаются, заменяя символы, специальные для файловых систем, подчеркиванием, включая косую черту. Это означает, что текст поля нельзя использовать для создания папок. Однако косые черты не изменяются в строках префиксов или суффиксов, поэтому косые черты в этих строках вызовут создание папок. Благодаря этому вы можете создать структуру папок переменной глубины.

Например, предположим, что нам нужна структура папок series/series_index - title, с оговоркой, что если серия не существует, то заголовок должен находиться в верхней папке. Шаблон для этого:

{series:||/}{series_index:|| - }{title}

Косая черта и дефис появляются только в том случае, если серия не пуста.

Функция поиска позволяет нам выполнять еще более интересную обработку. Например, предположим, что если в книге есть серия, то нам нужна структура папок series/series index - title.fmt. Если в книге нет серии, нам нужна структура папок genre/author_sort/title.fmt. Если у книги нет жанра, мы хотим использовать „Unknown“. Нам нужны два совершенно разных пути, в зависимости от значения серии.

Чтобы этого добиться, мы:

  1. Создать составное поле (дать ему имя для поиска #aa), содержащее {series}/{series_index} - {title}. Если серия не пуста, тогда этот шаблон создаст series/series_index - title.

  2. Создать составное поле (дать ему имя для поиска #bb), содержащее {#genre: ifempty (Unknown)}/{author_sort}/{title}. Этот шаблон создаст genre /author_sort/title, где пустой жанр заменяется на 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.

Советы

  • Используйте тестер шаблонов для тестирования шаблонов. Добавьте тестер в контекстное меню для книг в библиотеке и/или назначьте ему сочетание клавиш.

  • Шаблоны могут использовать другие шаблоны, ссылаясь на составные столбцы, построенные с помощью желаемого шаблона. В качестве альтернативы вы можете использовать сохраненные шаблоны.

  • В коммутации полю можно назначить соответствующее его типу пустое значение при помощи специального шаблона {}. Он всегда соответствует пустой строке.

  • Описанный выше метод отображения чисел, даже если они имеют нулевое значение, работает со стандартным полем series_index.

Справочник по функциям