Язык шаблонов 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.

Примечания по вызову функций в режиме одиночной функции:

  • Когда функции используются в режиме одиночной функции, первый параметр, value, автоматически заменяется содержимым поля, указанного в шаблоне. Например, когда обрабатывается шаблон {title:capitalize()}, содержимое поля title передается в качестве параметра value функции capitalize.

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

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

Функции задокументированы в Справочник по шаблонным функциям. В документации указано, какие аргументы требуются функциям и что они делают. Например, вот документация функции ifempty.

  • ifempty(value, text_if_empty) – если value не пустое, то вернуть это value, иначе вернуть text_if_empty.

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

{tags:ifempty(No tags on this book)}

показывает теги для книги, если таковые имеются. Если у неё нет тегов, то отображается В этой книге нет тегов.

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

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

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

  • cmp(value, y, lt, eq, gt) – сравнивает value и y после преобразования обоих в числа.

  • contains(value, pattern, text_if_match, text_if_not_match) – проверяет, соответствует ли значение регулярному выражению pattern. Возвращает text_if_match при совпадении, иначе возвращает text_if_not_match.

  • ff_““date_arithmetic(value, calc_spec, fmt)'' -- вычислить новую дату от ``value с помощью 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.

  • encode_for_url(value, use_plus) – возвращает значение value закодированное для использования в URL, как указанно с use_plus. Значение URL-кодированное. Далее, если use_plus равно 0, то пробелы заменяются знаками '+' (плюс). Если это 1, то пробелы заменяются %20.

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

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

  • format_duration(value, template, [largest_unit]) – format the value, a number of seconds, into a string showing weeks, days, hours, minutes, and seconds. If the value is a float then it is rounded to the nearest integer.

  • format_number(value, template) – интерпретирует value как число и форматирует это число, используя шаблон форматирования Python, такой как {0:5.2f} или {0:,d}` или ``${0:5,.2f}. Шаблон форматирования должен начинаться с {0: и заканчиваться }, как в приведенных выше примерах. Исключение: вы можете опустить начальные {0: и завершающие }, если шаблон формата содержит только формат. См. [URL href=»https://manual.calibre-ebook.com/template_lang.html»] Template Language[/URL] и [URL href=»https://docs.python.org/3/library/string.html#formatstrings»] Python[/URL]. Возвращает пустую строку, если сбой форматирования.

  • fractional_part(value) – возвращает значение после десятичной точки.

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

  • ifempty(value, text_if_empty) – если value не пустое, то вернуть это value, иначе вернуть text_if_empty.

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

  • list_contains(value, separator, [ pattern, found_val, ]* not_found_val) – интерпретирует value как список элементов, разделенных разделителем separator, проверяя pattern для каждого элемента в списке.

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

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

  • list_item(value, index, separator) – обрабатывает значение как список элементов, разделённых separator, возвращая элемент с номером index. Первый элемент имеет номер ноль. Последний элемент с номером индекса -1 как list_item(-1,separator). Если элемент не в списке, то возвращается пустое значение. Разделитель (separator) работает так же, как и в функции count, обычно запятая, но амперсанд для списков, вроде author.

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

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

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

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

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

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

  • re_group(value, pattern [, template_for_group]*) – вернуть строку, полученную путем применения шаблона регулярного выражения pattern к value и замены каждого сопоставленного экземпляра строкой, вычисленной путем замены каждой сопоставленной группы значением, возвращаемым соответствующим шаблоном. В [URL href=»https://manual.calibre-ebook.com/template_lang.html#more-complex-programs-in-template-expressions-template-program-mode»] программном режиме шаблона, как и в случае с template и eval, вы используете [[ для { и ]] для }. В следующем примере выполняется поиск ряда, состоящего более чем из одного слова, и первое слово переводится в верхний регистр [CODE] program: re_group(field(„series“), «(S* )(.*)», «{$:uppercase()}», «{$}»)“} [/CODE]

  • round(value) – возвращает ближайшее к value целое число. Выдаёт исключение, если value не является числом.

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

  • shorten(value, left chars, middle text, right chars) – Возвращает сокращённую версию значения``value``, состоящую из символов 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 символов. Если длина значения меньше, чем left chars + right chars + длина middle text, то значение будет возвращено без изменений. Например, название The Dome не изменится.

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

  • subitems(value, start_index, end_index) – Эта функция разделяет списки на иерархические элементы, подобные тегам, такие как жанры.

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

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

    • {tags:sublist(0,1,\,)} returns «A»

    • {tags:sublist(-1,0,\,)} returns «C»

    • {tags:sublist(0,-1,\,)} returns «A, B»

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

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

  • swap_around_comma(value) – если значение value имеет вид B, A, возвращает A B. Это наиболее полезно для преобразования имён вида LN, FN (Ф, И О) к виду FN LN (И О Ф). Если значение не содержит запятой в value, то оно возвращается без изменений.

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

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

  • titlecase(value) – возвращает value в регистре ЗАГОЛОВКОВ.

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

  • uppercase(value) – возвращает value в верхнем регистре

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

Предположим, у вас есть целочисленный настраиваемый столбец #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' | 'inlist_field' |
                    '==#' | '!=#' | '>=#' | '>#' | '<=#' | '<#'
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' - это одно и то же.

  • Comments are lines starting with a „#“ character, possibly preceded by blanks or tabs.

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

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

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

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

    Эти и все другие арифметические операторы возвращают целые числа, если результат выражения дает дробную часть, равную нулю. Например, если выражение возвращает 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, либо списку значений. Параметр :ref: ff_range генерирует список чисел. Если результатом является допустимое lookup name, то извлекается значение поля и используется разделитель, указанный для этого типа поля. Если результатом не является допустимое имя для поиска, то предполагается, что это список значений. Предполагается, что список разделяется запятыми, если не указано необязательное ключевое слово separator, и в этом случае значения списка должны быть разделены результатом вычисления separator_expr. Разделитель нельзя использовать, если список генерируется с помощью range(). Каждое значение в списке присваивается указанной переменной, после чего вычисляется 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 результат левого выражения интерпретируется как шаблон регулярного выражения. Они являются истинными, если значение регулярного выражения слева совпадает со значением выражения справа. Регулярные выражения не чувствительны к регистру.

Оператор inlist имеет значение true, если левое регулярное выражение соответствует любому из элементов в правом списке, где элементы в списке разделены запятыми. Оператор inlist_field имеет значение true, если левое регулярное выражение соответствует любому из элементов в поле (столбце), названном правым выражением, используя разделитель, определённый для поля. ПРИМЕЧАНИЕ: оператор inlist_field требует, чтобы правое выражение преобразовывалось в имя поля, в то время как оператор inlist требует, чтобы правое выражение преобразовывалось в строку, содержащую список, разделённый запятыми. Из-за этого различия inlist_field выполняется существенно быстрее, чем inlist, поскольку не выполняются преобразования строк или построения списков.

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

Примеры:

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

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

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

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

  • program: 'asimov' inlist $authors вернёт '1' если какой-либо автор соответствует регулярному выражению asimov, например, Asimov, Isaac или Isaac Asimov, иначе ''.

  • program: 'asimov' inlist_field 'authors' вернёт '1' если какой-либо автор соответствует регулярному выражению asimov, например, Asimov, Isaac или Isaac Asimov, иначе ''.

  • program: 'asimov$' inlist_field 'authors' вернёт '1' если какой-либо автор соответствует регулярному выражению asimov$, например, Isaac Asimov, иначе ''. Это не соответствует Asimov, Isaac из-за привязки $ в регулярном выражении.

  • 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, otherwise 'no'.

  • program: if '^(foo|1632)$'  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, в Общем программном режиме вы должны указать первый параметр value.

  • Все параметры являются expression_lists (смотрите грамматику выше).

Более сложные программы в шаблонных выражениях - 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($, $#genre)'}

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

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

    Если шаблон содержит префикс и суффикс, выражение заканчивается на '|, где | является разделителем префикса. Пример:

    {series:'ifempty($, $#genre)'|prefix | suffix}
    
  • функциям должны быть даны все их аргументы. Например, стандартные встроенные функции должны иметь дополнительный начальный параметр value.

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

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

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

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

Режим шаблона 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))

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

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

Шаблоны и URL

Вы можете использовать шаблоны для создания URL-адресов. Здесь описаны два случая:

  • Пользовательский столбец: :guilabel:`Book details guilabel: URL-адреса

  • Схема URL-адресов calibre

пользовательский столбец URL-адреса для поиска сведений о книге

Когда вы создаете пользовательский столбец, вы можете указать URL-адрес, который будет использоваться в Сведения о книге, используя шаблон. Например, если у вас есть пользовательский столбец для Translators, вы можете определить URL-адрес, который приведет вас на сайт для переводчиков. URL-адреса для поиска сведений о книге могут быть предоставлены для типов столбцов Текст, Перечисляемый“, „Серия“ и „Столбец, построенный из других столбцов.

При нажатии на элемент с шаблоном поиска в Сведения о книге шаблон оценивается. Ему предоставляются обычные метаданные книги. Также предоставляются три дополнительных поля:

  • item_value: значение нажатого элемента.

  • item_value_quoted: значение нажатого элемента, кодированный URL. Специальные символы экранируются, чтобы сделать их действительными в URL-адресах, а пробелы заменяются на знаки '+' (плюс).

  • item_value_no_plus: значение нажатого элемента, кодированный URL. Специальные символы экранируются, чтобы сделать их действительными в URL-адресах, а пробелы заменяются на знаки '+' (плюс).

Существует несколько способов создания URL-адреса. Ниже в качестве примера используется Википедия.

Самый простой - это базовый шаблон:

https://en.wikipedia.org/w/index.php?search={item_value_encoded}

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

  • make_url(path, [query_name, query_value]+) – эта функция - простейший способ создания URL-адреса запроса. Она использует path, веб-сайт и страницу, которые вы хотите запросить и пары query_name, query_value, из которых строится запрос. Как правило, query_value должно быть закодировано в URL. С помощью этой функции оно всегда закодировано, пробелы всегда заменяются знаками „+“.

  • make_url_extended(...) – эта функция аналогична make_url() но дает вам больше контроля над компонентами URL. Компонентами URL являются

    scheme:://authority/path?query string.

    См. Uniform Resource Locator в Wikipedia.

    У функции два варианта:

    make_url_extended(scheme, authority, path, [query_name, query_value]+)
    

    и

    make_url_extended(scheme, authority, path, query_string)
    
  • query_string([query_name, query_value, how_to_encode]+)– возвращает строку запроса URL сконструированную из триад query_name, query_value, how_to_encode. Строка запроса это серия элементов выглядящих как query_name=query_value, где query_value это URL-кодирование. Элементы запроса разделяются символами '&' (ampersand).

  • encode_for_url(value, use_plus) – возвращает значение value закодированное для использования в URL, как указанно с use_plus. Значение URL-кодированное. Далее, если use_plus равно 0, то пробелы заменяются знаками '+' (плюс). Если это 1, то пробелы заменяются %20.

Например, предположим, что у вас есть пользовательский столбец Переводчики (#translators), где имена - Last name, First name. Возможно, при создании URL-адреса вам потребуется преобразовать имя в First name Last name. Для этого вы можете использовать функцию :ref: ff_make_url:

program: make_url('https://en.wikipedia.org/w/index.php', 'search', swap_around_comma($item_value))

Если мы предположим, что переводчика зовут Boy-Żeleński, Tadeusz, то приведенный выше шаблон выдает ссылку:

https://en.wikipedia.org/w/index.php?search=Tadeusz+Boy-%C5%BBele%C5%84ski

Обратите внимание, что имя пользователя теперь стоит первым, пробел - это плюс, а неанглоязычные символы в фамилии URL-кодированы.

Функции make_url_extended, query_string и encode_for_url могут быть полезны в зависимости от любой дополнительной сложности обработки.

Схема URL-адресов calibre

Calibre поддерживает несколько различных URL-адресов для навигации по вашим библиотекам calibre. В этом разделе показано, как использовать шаблоны для создания URL-адресов. Смотрите Схема URL-адресов calibre:// для получения подробной информации о доступных URL-адресах.

  • Переключение на определённую библиотеку. Синтаксис этого URL-адреса следующий:

    calibre://switch-library/Library_Name
    

    Library_Name необходимо заменить на название библиотеки calibre, которую вы хотите открыть. Название библиотеки отображается в строке заголовка окна. Это простое имя, а не путь к файлу библиотеки. Вы должны написать его так, как показано в строке заголовка, включая регистр букв. Символ _ (подчеркивание) обозначает текущую библиотеку. Если имя содержит какие-либо пробелы или специальные символы, то оно должно быть закодировано в шестнадцатеричном формате с использованием функции to_hex, как в следующем примере:

    program: strcat('calibre://switch-library/_hex_-', to_hex(current_library_name()))
    

    Шаблон генерирует URL-адрес:

    calibre://switch-library/_hex_-4c6962726172792e746573745f736d616c6c
    

    Вы можете заменить функцию current_library_name() фактическим именем библиотеки, как в:

    program: strcat('calibre://switch-library/_hex_-', to_hex('Library.test_small'))
    
  • Ссылки для показа книг. По этим ссылкам выбирается книга в библиотеке calibre. Синтаксис этого URL-адреса следующий:

    calibre://show-book/Library_Name/book_id
    

    book id - это цифровой идентификатор книги в calibre, доступный в шаблонах как $ id. Как указано выше, название библиотеки может потребоваться в шестнадцатеричном кодировании. Вот пример:

    program: strcat('calibre://show-book/_hex_-', to_hex(current_library_name()), '/', $id)
    

    Он выдает URL-адрес:

    calibre://show-book/_hex_-4c6962726172792e746573745f736d616c6c/1353
    
  • Поиск книг. Эти ссылки выполняют поиск книг в указанной библиотеке calibre. Синтаксис этого URL-адреса следующий:

    calibre://search/Library_Name?q=query
    calibre://search/Library_Name?eq=hex_encoded_query
    

    где query - любое допустимое поисковое выражение calibre. Вы должны закодировать любой запрос, содержащий пробелы или специальные символы, в шестнадцатеричном формате, что обычно означает их все. Например, поисковое выражение calibre для поиска иерархического тега, начинающегося с „AA“, является tags:"=.AA". Этот шаблон создает URL-адрес поиска для этого выражения:

    program: strcat('calibre://search/_hex_-', to_hex(current_library_name()), '?eq=', to_hex('tags:"=.AA"'))
    

    Результирующий URL-адрес выглядит следующим образом:

    calibre://search/_hex_-4c6962726172792e746573745f736d616c6c?eq=746167733a223d2e414122
    

    Вот пример того же URL, созданного с использованием функции :ref:ff_make_url_extended вместо :ref:ff_strcat:

    program: make_url_extended('calibre', '', 'search/_hex_-' & to_hex(current_library_name()),
                               'eq', to_hex('tags:"=.AA"'))
    
  • Открыть окно сведений о книге в какой-либо библиотеке. Синтаксис этого URL-адреса следующий:

    calibre://book-details/Library_Name/book_id
    

    Примером шаблона является:

    program: strcat('calibre://book-details/_hex_-', to_hex(current_library_name()), '/', $id)
    

    который выдает URL-адрес:

    calibre://book-details/_hex_-4c6962726172792e746573745f736d616c6c/1353
    
  • Открыть примечания, связанные с автором/серией/и т.д. Синтаксис URL-адреса следующий:

    calibre://book-details/Library_Name/Field_Name/id_Item_Id
    calibre://book-details/Library_Name/Field_Name/hex_Hex_Encoded_Item_Name
    

    Field_Name - это поисковое имя поля. Если поле представляет собой пользовательский столбец, замените символ # символом подчеркивания (_). Item_Id - это внутренний числовой идентификатор значения в поле. Не существует шаблонной функции, которая возвращала бы Item_Id, поэтому шаблоны обычно используют вторую форму, Hex_Encoded_Item_Name. Вот образец шаблона, который открывает заметку для человека Boy-Żeleński, Tadeusz в поле #authtest:

    program: strcat('calibre://show-note/_hex_-', to_hex(current_library_name()),
                    '/_authtest/hex_', to_hex('Boy-Żeleński, Tadeusz'))
    

    который выдает URL-адрес:

    calibre://show-note/_hex_-4c6962726172792e746573745f736d616c6c/_authtest/hex_426f792dc5bb656c65c584736b692c205461646575737a
    

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

И Общий программный режим, и Режим шаблона 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 в процессор шаблонов. Такие функции можно использовать в любом из трех режимов программирования шаблонов. Функции добавляются по ссылке: guilabel:Настройки - Расширенные - Функции шаблонов. Инструкции показаны в этом диалоговом окне. Обратите внимание, что вы можете использовать Шаблоны Python для аналогичной цели. Поскольку вызов пользовательских функций выполняется быстрее, чем вызов шаблона Python, пользовательские функции могут быть более эффективными в зависимости от сложности того, что выполняет функция или шаблон.

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

В графическом интерфейсе (Столбцы, созданные из других столбцов и:guilabel:Поиск по шаблону):

  • Шаблоны GPM работают по-прежнему.

  • Шаблон Python будет иметь полный доступ к базе данных calibre.

В правилах значков:

  • шаблоны правил значков не содержат данных книги, поэтому функции на основе полей, такие как format_date_field, list_count_field, и check_yes_no не работают.

В контент-сервере:

  • Шаблоны имеют доступ к новому API, но не к старому API (LibraryDatabase).

  • Из-за вышесказанного, работа следующих функций форматирования в шаблонах GPM не гарантируется (составные столбцы, правила значков и т.д.), и их следует избегать, если вы используете контент-сервер:

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

Специальная обработка применяется, когда шаблон используется в шаблоне 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. Установить для шаблона сохранения значение {series:lookup(.,#aa,#bb}. Этот шаблон выбирает составное поле #aa, если серия не пуста, и составное поле #bb, если серия пуста, поэтому у нас есть два совершенно разных пути сохранения, в зависимости от того, пуста ли series.

Советы

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

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

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

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

Справочник по шаблонным функциям