Мова шаблонів calibre

Мова шаблонів calibre є специфічною для calibre мовою програмування, яка використовується у різних компонентах calibre. Її використовують для визначення шляхів до файлів, значення форматування та обчислення значень визначених користувачем стовпчиків. Приклади:

  • Визначення структури каталогів та назви файла при зберіганні файлів з бібліотеки calibre на диск або на пристрій для читання книг.

  • Визначення правил додавання піктограм і кольорів до списку книг calibre.

  • Визначення «віртуальних» стовпчиків, які містять дані з інших стовпчиків.

  • Розширені можливості пошуку у бібліотеці.

  • Розширені можливості з пошуку і заміни у метаданих.

Мову побудовано навколо поняття «шаблон». Шаблон задає, які метадані книги слід використати, обчислення над цими метаданими, і як їх слід форматувати.

Базові шаблони

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

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

Для книги «The Foundation» автора «Isaac Asimov» ми отримаємо:

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

Символи похилих рисок не є шаблонними виразами, оскільки їх обмежено {}. Такі фрагменти тексту після обробки лишаються на місці. Наприклад, якщо шаблоном є такий:

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

для «The Foundation» шаблон дасть:

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

Шаблон може отримувати доступ до усіх метаданих, які доступні у calibre, зокрема нетипових стовпчиків (стовпчиків, які створено користувачем), за їхньою назвою для пошуку. Щоб визначити назву для пошуку для стовпчика (який іноді називають «полем»), наведіть вказівник миші на заголовок стовпчика у списку книг calibre. У назвах для пошуку нетипових стовпчиків першим символом завжди є #. Для стовпчиків типу циклів передбачено додаткове поле із назвою '#назва_для_пошуку'_index, яке містить індекс у циклі. Отже, якщо у вас є нетипове поле циклу із назвою #myseries, буде також і поле із назвою #myseries_index. Індекс стандартного стовпчика циклу має назву series_index.

Окрім полів, заснованих на вмісті стовпчиків, ви також можете використовувати:

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

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

Якщо метаданих поля певної книги не визначено, поле у шаблоні буде замінено на порожній рядок (''). Приклад:

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

Якщо книга Азімова «Second Foundation» є частиною циклу «Foundation», шаблон дасть:

Asimov, Isaac/Foundation/Second Foundation 3

Якщо для книги не введено циклу, шаблон дасть:

Asimov, Isaac/Second Foundation

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

Додаткові можливості з форматування

За допомогою шаблонів, окрім вставляння метаданих, можна виконувати набагато ширший спектр дій. Шаблони можуть включати додатковий текст, якщо виконуються певні умови, і керувати тим, як буде форматовано підставлені дані.

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

Іноді може виникнути потреба у виведенні тексту, лише якщо певне поле є непорожнім Типовим прикладом є series і series_index. У цьому прикладі нам потрібен буде або порожній рядок або два значення, які відокремлено дефісом. У calibre для обробки подібних випадків передбачено спеціальний синтаксис запису шаблона.

Наприклад, використовуючи наведений вище приклад із «Foundation», припустімо, вам потрібно, щоб застосування шаблона давало таке: Foundation - 3 - Second Foundation. Цей шаблон дає такий результат:

{series} - {series_index} - {title}

Втім, якщо книга не належить до циклу, шаблон виведе - - заголовок Ймовірно, це зовсім не те, що потрібно. Здебільшого, бажаним результатом буде просто заголовок, без зайвих дефісів. Для отримання такого результату слід скористатися такою синтаксичною конструкцією шаблонів:

{field:|текст_префікса|текст_суфікса}

Цей шаблонний вираз визначає, що якщо field має значення XXXX, результатом буде prefix_textXXXXXsuffix_text. Якщо field є порожнім (не має значення), результатом буде порожній рядок (нічого), оскільки префікс і суфікс буде проігноровано. Префікс і суфікс можуть містити пробіли.

Не використовуйте підлеглі шаблони (`{ … }`) або функції (див. нижче) у префіксі або суфіксі.

За допомогою цієї синтаксичної конструкції ми можемо розв’язати поставлену вище задачу з шаблоном:

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

Дефіси буде включено, лише якщо для книги визначено індекс у циклі, а таке трапляється, лише якщо метадані містять запис циклу. Продовжуючи приклад із «Foundation», шаблон дасть Foundation - 1 - Second Foundation.

Нотатки:

  • Вам слід включити двокрапку після назви для пошуку, якщо ви хочете скористатися префіксом або суфіксом.

  • Вам слід або не використовувати символи |, або використовувати обидва символи; користуватися одним з них, як у {field:| - }, не можна.

  • Можна не вказувати текст для префікса або суфікса, якось так: {series:|| - }. Шаблон {title:||} є еквівалентним до шаблона {title}.

Форматування

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

{series_index:0>3s} — три цифри із початковими нулями

Для кінцевих нулів скористайтеся такою конструкцією:

{series_index:0<3s} — три цифрви із завершальними нулями

Якщо ви використовуєте індекси у циклі із проміжними значеннями (наприклад, 11), вам може знадобитися вирівнювання десяткової крапки. Наприклад, бажаним буде запис індексів 1 і 2.5 як 01.00 і 02.50 для належного упорядковування на пристроях із лексичним упорядкуванням. Щоб досягти потрібного результату, скористайтеся таким шаблоном:

{series_index:0>5.2f} — п’ять символів складаються із двох цифр і початковими нулями, десяткової крапки і 2 цифр після десяткової крапки.

Якщо вам потрібні лише перші дві літери даних, скористайтеся такою конструкцією:

{author_sort:.2} — лише перші дві літери імені у впорядкованому списку авторів

Більша частина форматування мови шаблонів calibre є похідною від Python. Щоб дізнатися більше про синтаксичні конструкції таких дій з форматування, ознайомтеся із документацією з Python.

Використання шаблонів для визначення нетипових стовпчиків

Шаблони використовують для показу даних, яких немає у метаданих calibre або показу даних у форматуванні, яке відрізняється від стандартного форматування calibre. Наприклад, у вас може виникнути потреба бачити ISBN, поле, вміст якого calibre не показує. Для показу таких даних ви можете скористатися нетиповими стовпчиками. Створіть стовпчик із типом «Стовпчик, створений на основі інших стовпчиків» (надалі ми такі стовпчики називатимемо складеними) і введіть до нього шаблон. Результат: calibre показуватиме у стовпчику результат обчислення шаблона. Для показу ISBN створіть стовпчик і введіть {identifiers:select(isbn)} у поле шаблона. Щоб створити стовпчик, який міститиме значення двох нетипових стовпчиків циклів, скористайтеся шаблоном {#series1:||,}{#series2}.

Складені стовпчики можуть використовувати будь-які варіанти шаблонів, включно з форматуванням.

Зауваження: редагувати дані, які показано у складеному стовпчику не можна. Редагувати слід дані у стовпчиках-джерелах. Якщо ви спробуєте виконати редагування складеного стовпчика, наприклад, подвійним клацанням на даних у ньому, calibre відкриє для редагування шаблон, а не дані, які він виводить.

Шаблони і набори метаданих

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

Під час створення набору метаданих ви визначаєте формат і пристрій, для яких використовуватиметься набір. Передбачено особливий пристрій, save_to_disk, який використовується для збереження книг у певних форматах (на відміну від надсилання книг на пристрій). Після вибору формату і пристрою вам слід вибрати поля метаданих для внесення змін і надати шаблони для визначення нових значень цих полів. Ці шаблони буде з’єднано з відповідними полями призначення. Ви, звичайно ж, можете використовувати у шаблонах наборів метаданих складені стовпчики.

Набори метаданих є доволі гнучкими — їх можна писати у режимі однієї функції, режимі програмування шаблонів, загальному режимі програмування та режимі шаблонів Python.

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

  • набір метаданих із точною відповідністю за форматом і пристроєм, наприклад EPUB і ANDROID

  • набір метаданих із точним відповідником за форматом і спеціальним варіантом any device, наприклад EPUB і any device

  • набір метаданих із спеціальним варіантом any format і точною відповідністю за пристроєм, наприклад any format і ANDROID

  • набір метаданих any format і any device

Поля міток (tags) і авторів (authors) обробляються у особливий спосіб, оскільки у обох цих полях може міститися декілька записів. У книги може бути багато міток і багато авторів. Якщо ви визначаєте одне з цих двох полів як таке, вміст якого слід змінити, результати використання шаблона буде перевірено на наявність декількох записів. Для міток результат буде розділено на записи за знайденими calibre комами. Наприклад, якщо шаблон створює значення Трилер, Жахи, результатом буде дві мітки, Трилер і Жахи. Способів додавання коми у окрему мітку не передбачено.

Те саме стосується авторів, але для поділу на записи використовується інший символ, & (амперсанд), а не кома. Наприклад, якщо шаблоном створюється значення 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}

За назвами функцій завжди мають іти початкова і завершальна круглі дужки. Деяким функціям обов’язково слід передавати додаткові значення (аргументи), і ці аргументи слід вказувати у дужках. Аргументи відокремлюють комами. Самі коми (коми як текст, а не роздільник аргументів) слід екранувати символом зворотної похилої риски (\) . Останній (або єдиний) аргумент не може містити текстової завершальної дужки.

Функції обчислюють до специфікацій форматів та префіксів/суфіксів. Нижче наведено приклад одночасного використання форматування та функції.

Важливе зауваження: якщо ви маєте досвід програмування, будь ласка, зауважте, що синтаксис у цьому режимі (режимі єдиної функції) не зовсім такий, як ви очікуєте Для рядків не потрібні лапки. Пробіли мають значення. Усі аргументи мають бути сталим; проміжних обчислень не передбачено.

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

У деяких функціях використовуються формальні вирази. У мові шаблонів при встановленні відповідності формальних виразів регістр символів не береться до уваги.

У наведеній нижче документації щодо функцій позначення [щось]* означає, що щось може бути повторено нуль або більшу кількість разів. Позначення [щось]+ означає, що щось повторюється один або декілька разів (але має бути принаймні один такий запис).

Функціями, які призначено для використання у режимі єдиної функції, є такі:

  • capitalize() – повертає значення поля так, що кожне слово у результаті починатиметься з великої літери, а решта літер слів будуть малими.

  • contains(значення, взірець, текст для відповідності, текст для невідповідності) — перевіряє, чи міститься у значенні відповідник формального виразу взірець. Повертає текст для відповідності, якщо буде знайдено відповідник, інакше повертає текст для невідповідності.

  • count(роздільник) — за заданим значенням списком пунктів, відокремлених роздільником роздільник, повертає кількість пунктів у списку. У більшості списків як роздільник використовується кома, для авторів може використовуватися амперсанд. Приклади: {tags:count(,)}, {authors:count(&)}. Варіанти: count(), list_count()

  • format_number(шаблон) — вважати значення числом і форматувати число на основі шаблону форматування python, наприклад {0:5.2f}, {0:,d} або ${0:5,.2f}. Шаблон форматування має починатися з {0: і завершуватися }, як у наведених вище прикладах. Виключення: ви можете обійтися без початкового «{0:» і завершального «}», якщо у шаблоні форматування міститься лише один формат. З докладнішими прикладами можна ознайомитися за допомогою документації до мови шаблонів та документації з Python. Повертає порожній рядок, якщо виконати форматування не вдасться.

  • human_readable() — очікує, що значення є числом, і повертає рядкове представлення числа у кілобайтах, мегабайтах, гігабайтах тощо.

  • ifempty(текст для порожнього) — якщо значення не є порожнім, повертає значення поля, інакше повертає текст для порожнього.

  • in_list(роздільник, [ взірець, значення_якщо_знайдено, ]* значення_якщо_не_знайдено) — обробляє значення як список пунктів, відокремлених роздільником, порівнює взірець з кожним зі значень у списку Якщо рядок збігається зі значенням, повертає значення_якщо_знайдено, інакше повертає значення_якщо_не_знайдено. Значення взірець і значення_якщо_знайдено можна повторювати довільну кількість разів, залежно від значення запису. Перевірка взірців виконується послідовно. Функція повертає перший знайдений відповідник.

  • language_strings(локалізація) — повертає назви мов для кодів мовs, які передано як значення. Приклад: {languages:language_strings()}. Якщо локалізація дорівнює нулеві, повертає рядки англійською. Якщо локалізація не дорівнює нулеві, повертає рядки мовою поточної локалі. Значення коди_мов є списком значень, які відокремлено комами.

  • list_item(номер, роздільник) обробляє значення як список пунктів, відокремлених роздільником «роздільник», повертає пункт з номером «номер». Перший пункт має номер нуль. Останній з пунктів має індекс ``-1, як у «list_item(-1, роздільник)». Якщо пункту немає у списку, буде повернуто порожній рядок.

  • lookup([ взірець, ключ, ]* інший_ключ) — буде виконано встановлення відповідності значення взірцям за порядком. Якщо взірець є відповідним, буде повернуто значення поля, яке вказано назвою key. Якщо взірець не є відповідним, буде повернуто значення поля інший_ключ. Див.``switch`` (нижче).

  • lowercase() — повертає значення поля малими літерами.

  • rating_to_stars(використання_пів_зірок) — повертає оцінку як рядок з символів зірок (). Значення має бути числом від 0 до 5. Встановіть значення використання_пів_зірок рівним 1, якщо ви хочете, щоб у стовпчиках нетипових оцінок, було показано символи пів зірок для нецілих оцінок.

  • re(взірець, замінник) — повертає значення після застосування формального виразу. Усі екземпляри взірця у значенні буде замінено на замінник. У мові шаблонів використано формальні вирази Python без врахування регістру символів.

  • select(ключ) — обробляє значення як список записів, які відокремлено комами. Кожен запис має форму ідентифікатор:значення (форма identifier calibre). Функція знаходить першу пару із ідентифікатором, який рівний ключеві, і повертає відповідне значення. Якщо відповідних ідентифікаторів не буде виявлено, функція поверне порожній рядок.

  • shorten(символи ліворуч, текст посередині, символи праворуч) — повертає скорочену версію значення, яка складається із вказаної кількості символи ліворуч символів на початку значення, далі з тексту посередині, і далі кількості символи праворуч символів наприкінці значення. Символи ліворуч і символи праворуч мають бути невід’ємними цілими значеннями. Приклад: припустімо, ви хочете показати заголовок довжиною не більше 15 символів у довжину. Одним шаблоном, який виконує це завдання є {title:shorten(9,-,5)}. Для книги із заголовком Ancient English Laws in the Times of Ivanhoe результатом буде Ancient E-anhoe: перші 9 символів заголовка, -, далі останні 5 символів. Якщо довжина значення є меншою за символи ліворуч + символи праворуч + довжина текст посередині, значення буде повернуто без змін. Наприклад, заголовок The Dome не буде змінено.

  • str_in_list(роздільник, [ рядок, значення_якщо_знайдено, ]* значення_якщо_не_знайдено) — обробити значення як список записів, які відокремлено символом роздільник, потім порівняти рядок із кожним значенням у списку. Значення рядок не є формальним виразом. Якщо рядок дорівнює будь-якому запису (без врахування регістру символів), повертає відповідне значення_якщо_знайдено. Якщо рядок містить роздільник, його також буде оброблено як список із перевіркою для кожного із вбудованих значень. Можна вказати довільнй кількість пар рядок і значення_якщо_знайдено, що дає змогу повертати різні значення, залежно від значення рядка. Якщо не буде встановлено відповідності жодному з рядків, буде повернуто значення_якщо_не_знайдено. Перевірка рядків виконується у вказаному порядку. Повернуто буде перший з відповідників.

  • 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(початковий_номер, кінцевий_номер, роздільник) — обробляє значення як список пунктів, відокремлених роздільником роздільник, повертає новий список, створений з пунктів з номера початковий_номер до номера кінцевий_номер. Перший пункт має нульовий номер. Якщо вказано від’ємний номер, його буде відраховано від кінця списку. Якщо буде вказано кінцевий_номер рівний нулеві, номер вважатиметься кінцевим у списку.

    Приклад, у яких припускаємо, що у стовпчику міток (значення відокремлено комами) міститься запис «A, B ,C»:

    • {tags:sublist(0,1,\,)} повертає «A»

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

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

  • swap_around_articles(роздільник) — повертає значення із артиклями, які пересунуто в кінець. Значенням може бути список, елементи якого буде оброблено окремо. Якщо значенням є список, вам слід вказати роздільник значень у списку. Якщо значення роздільник вказано не буде, значення вважатиметься одним рядком, а не списком. Артиклями вважаються рядки, які використовуються calibre для створення title_sort.

  • swap_around_comma(значення) — за заданими значеннями у форматі B, A повертає значення A B. Найкорисніше для перетворення імен у форматі «Прізвище, Ім’я» на імена у форматі «Ім’я Прізвище». Якщо коми у значенні не буде виявлено, функція поверне значення без змін.

  • switch([взірець, значення,]+ інше_значення) для кожної пари ``взірець, значення перевіряє, чи відповідає поле формальному виразу взірець. Якщо це так, повертає «значення». Якщо відповідності з взірцем не буде знайдено, буде повернено «інше_значення». Можна визначати довільну кількість пар взірець, значення. Буде повернуто перший з відповідників.

  • test(текст для непорожнього, текст для порожнього) — повертає «текст для непорожнього», якщо значення не є порожнім. Якщо це не так, повертає текст для порожнього.

  • titlecase() — повертає значення поля так, щоб великі літери у результаті використовувалися відповідно до правил щодо заголовків в англійській мові.

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

  • uppercase() — повертає значення поля великими літерами.

Використання функцій і форматування у одному шаблоні

Припустімо, у нас є нетиповий стовпчик із назвою #myint, у якому містяться цілі числа. Вам потрібно представити їх у форматі із початковими нулями, ось так: 003. Для цього можна було б скористатися форматуванням 0>3s. Втім, типово, якщо число (ціле або дійсне) дорівнює нулеві, значення буде показано як порожній рядок. Отже, нульові значення початкові значення призводитимуть до порожніх рядків, а не до записів 000. Якщо вам потрібні саме значення 000, вам слід скористатися одразу і рядком форматування, і функцією ifempty для заміни порожнього значення на нульове. Шаблон може бути таким:

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

Зауважте, що ви можете також використовувати префікс і суфікс. Якщо ви хочете, щоб число було показано як [003] або [000], скористайтеся таким шаблоном:

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

Загальний режим програмування

Загальний режим програмування замінює `вирази шаблонів програмою, яку написано мовою шаблонів. Синтаксис мови визначено такою граматикою:

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“, якщо вирази ліворуч і праворуч від нього є істинними, або порожній рядок '', якщо хоча б одне з тверджень ліворуч і праворуч є хибним. Оператор є асоціативним, обчислюється зліва праворуч, і має властивість скороченого обчислення.

  • Логічне «АБО» (||) Цей оператор повертає '1', якщо твердження ліворуч або праворуч від нього є істинним, або '', якщо обидва твердження є хибними. Є асоціативним, обчислюється зліва праворуч і має властивість скороченого обчислення. Оператор є інклюзивним «АБО», тобто повертає '1', якщо вирази праворуч і ліворуч від нього є істинними.

Посилання на поля

Інструкцію field_reference буде замінено значенням поля метаданих, яке має назву пошуку, яку вказано після $ або $$. Використання $ є еквівалентне до використання функції field(). Використання $$ є еквівалентним до використання функції raw_field. Приклади:

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

Вирази if

У виразах if спочатку обчислюється умова. Якщо умова справджується (обчислення дають непорожнє значення), обчислюється expression_list у інструкції then``. Якщо умова не справджується, обчислюється, якщо є, expression_list у інструкції elif або else, якщо існують такі інструкції. Частини elif і else є необов’язковими. Слова if, then, elif, else і fi є зарезервованими, ви не можете використовувати їх як назви ідентифікаторів. Ви можете вставляти розриви рядків та пробіли там, де захочете. Запис condition є top_expression, а не expression_list; не можна використовувати крапку з комою. Набори expression_lists є розділеними крапками з комами послідовності top_expression. Вираз if повертає результат останнього top_expression у обчисленому expression_list або порожній рядок, якщо жодного списку виразів не було обчислено.

Приклади:

* 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 має оброблятися до назви для пошуку поля метаданих, наприклад tags або #genre, або списку значень. Функція range() (див. нижче) створює список чисел. Якщо результат є коректною назвою для пошуку, отримується значення поля. Використовується роздільник, вказаний для відповідного типу поля. Якщо результат не є коректною назвою для пошуку, припускається, що це список значень. Припускається, що значення у списку розділено комами, якщо не вказано необов’язкове ключове слово 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 Пакетне редагування метаданих  →  Пошук із заміною ^ у полі Шукати слід вказати шаблон для вилучення першого рівня ієрархії і визначення значення-результату для поля «Жанр».

Зауваження: останній рядок у шаблоні, 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 є true, якщо формальний вираз ліворуч від нього відповідає будь-якому із записів операнда праворуч від нього; записи слід відокремлювати комами. Відповідність встановлюється без врахування регістру символів.

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

Приклади:

  • program: field('series') == 'foo' повертає '1', якщо циклом книги є „foo“, інакше повертає ''.

  • program: 'f.o' in field('series') повертає '1', якщо цикл книги відповідає формальному виразу f.o (наприклад, foo, Off Onyx тощо), інакше повертає ''.

  • program: 'science' inlist field('#genre') повертає '1', якщо будь-який із записів жанрів книги відповідає формальному виразу science, наприклад, Science, History of Science, Science Fiction тощо). У інших випадках буде повернуто ''.

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

  • program: if field('series') != 'foo' then 'bar' else 'mumble' fi повертає 'bar', якщо циклом книги не є foo, інакше повертає mumble.

  • program: if field('series') == 'foo' || field('series') == '1632' then 'yes' else 'no' fi повертає yes, якщо циклом є 'foo' або '1632', інакше повертає no.

  • program: if '^(foo|'1632)$' in field('series') then 'yes' else 'no' fi повертає 'yes', якщо циклом є 'foo' або '1632', інакше повертає 'no'.

  • program: if 11 > 2 then 'yes' else 'no' fi повертає 'no', оскільки оператор > виконує лексичне порівняння.

  • program: if 11 > 2 then 'yes' else 'no' fi повертає 'yes', оскільки оператор ># виконує числове порівняння.

Додаткові функції

Окрім функцій, які описано у розділі Режим єдиної функції, можна скористатися описаними нижче функціями.

У загальному режимі програмування функції, які описано для режиму єдиної функції, усі потребують додаткового першого параметра, який визначає значення, яке слід обробляти. Усі параметри належать до expression_lists (див. граматику вище).

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

  • and(значення [, значення]*) — повертає рядок «1», якщо усі значення не є порожніми, інакше повертає порожній рядок. Кількість значень може бути довільною. У більшості випадків замість цієї функції можна скористатися оператором &&. Однією з причин не замінювати and на && є випадки, коли оптимізація обчислення може змінити результати через сторонні ефекти. Наприклад, and(a='',b=5) виконує обидва записи значень, а оператор && не виконає другого з них.

  • assign(ідентифікатор, значення) — надає ідентифікатору значення, потім повертає значення. ідентифікатор має бути ідентифікатором, а не виразом. У більшості випадків можна замість цієї функції використовувати оператор =.

  • approximate_formats() — повернути розділений комами список форматів, які пов’язано з книгою. Гарантувати чинність такого списку не можна, хоча, ймовірно, він залишається чинним. Цю функцію та інші функції без параметрів можна викликати у режимі шаблонного програмування (див. нижче) за допомогою шаблона «{:“approximate_formats()“}». Зауважте, що назви форматів завжди слід вказувати великими літерами, ось так: EPUB. Функція approximate_formats() є значно швидшою за функції formats_..., які описано нижче.

  • author_links(роздільник_значень, роздільник_пар) — повертає рядок, що містить список авторів з відповідними пов’язаними значеннями у такому форматі:

    author1 val_separator author1_link pair_separator author2 val_separator author2_link etc.
    

    Запис автора буде відділено від пов’язаного із ним значення рядком роздільник_значень без додаткових пробілів. Пари автор:пов'язане значення буде відокремлено рядком роздільник_пар без додаткових пробілів. Ви можете вибирати рядки роздільників довільним чином, так, щоб вони не збігалися з іменами авторів або посиланнями. Запис автора буде включено, навіть якщо пов’язане з ним значення посилання є порожнім.

  • author_sorts(роздільник_значень) — повертає рядок, що містить список значень упорядкування записів авторів книги. Критерієм упорядковування є один із записів метаданих автора (відмінний від author_sort у книгах). Повернутий список має такий формат: упорядкування автора 1 роздільник_значень упорядкування автора 2 тощо без додавання пробілів. Значення упорядковування авторів у цьому списку перебувають у тому самому порядку, що і автори у книзі. Якщо вам потрібні пробіли навколо роздільника_значень, додайте їх до рядка роздільника.

  • book_count(запит, використати_віртуальні) — повертає кількість книг, які було знайдено за запитом запит. Якщо значенням використати_віртуальні є 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, '')
      

    Під час першого запуску шаблона (перевірка першої книги) він зберігає результати пошуків у базі даних у загальній шаблонній змінній із назвою vals. Ці результати буде використано для подальшого пошуку книг без повторної обробки усієї бази даних.

    1. Використання збереженого шаблона у шаблонному пошуку:

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

    Використання збереженого шаблона замість вписування шаблона у пошук усуває проблеми, які пов’язано із вимогою щодо екранування лапок у виразах для пошуку.

  • book_values(стовпчик, запит, роздільник, використати_віртуальні) — повертає список неповторюваних значень, що містяться у стовпчику стовпчик (назві пошуку), відокремлені роздільником роздільник, у книгах, які було знайдено за запитом запит. Якщо значенням використати_віртуальні є 0 (нуль), віртуальні бібліотеки буде проігноровано. Ця функція і подібна до неї функція book_count() корисні, зокрема, у шаблонних пошуках, де передбачено підтримку пошуків, які поєднують відомості з багатьох книг, наприклад, пошуків циклів, де є лише одна книга. Функцією не можна користуватися у складених стовпчиках, якщо для коригування allow_template_database_functions_in_composites не встановлено значення True. Можна використовувати лише у графічному інтерфейсі.

  • booksize() — повертає значення поля calibre «size». Повертає „“, якщо форматів немає.

  • check_yes_no(назва_поля, is_undefined, is_false, is_true) — перевіряє, чи дорівнює значення поля «так/ні», вказаного назвою для пошуку назва_поля, значенню, вказаному параметрами, повертає 'yes', якщо знайдено відповідник, інакше, повертає порожній рядок. Встановіть для параметрів is_undefined, is_false або is_true значення 1 (число), щоб перевірити відповідну умову, інакше, встановіть 0. Приклад:

    check_yes_no("#bool", 1, 0, 1) повертає 'yes', якщо "#bool" поля так/ні або не визначено (він не є істинним і не є хибним), або дорівнює True.

    Значення 1 можна встановлювати для декількох записів з набору is_undefined, is_false або is_true.

  • ceiling(x) — повертає найменше ціле число, яке є більшим або рівним x. Надсилає виключення, якщо x не є числом.

  • character(назва_символу) — повертає символ із назвою «назва_символу». Наприклад, 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(ключ_розташування_сховища) — якщо пристрій з’єднано, повертає назву пристрою, якщо ні — порожній рядок. Кожне розташування сховища даних на пристрої має власну назву. Значення параметра ключ_розташування_сховища: 'main', 'card' і 'cardb'. Ця функція працює лише у графічному інтерфейсі користувача.

  • connected_device_uuid(ключ_розташування_сховища) — якщо пристрій з’єднано, повертає UUID (унікальний ідентифікатор) пристрою, якщо ні — порожній рядок. Кожне розташування сховища даних на пристрої має власний UUID. Значення параметра ключ_розташування_сховища: 'main', 'carda' і 'cardb'. Ця функція працює лише у графічному інтерфейсі користувача.

  • current_library_name() — повертає останню адресу поточної бібліотеки calibre.

  • current_library_path() — повертає повний шлях до поточної бібліотеки calibre.

  • current_virtual_library_name() — повертає назву поточної віртуальної бібліотеки, якщо така є, і порожній рядок, якщо такої немає. Регістр символів назви бібліотеки буде збережено. Приклад: program: current_virtual_library_name(). Ця функція працює лише у режимі графічного інтерфейсу користувача.

  • date_arithmetic(дата, специфікація_обчислень, формат) — обчислення нової дати на основі дати дата з використанням специфікації_обчислень. Повертає нову дату, форматовану відповідно до додаткового параметра формат. Якщо формат не вказано, результат буде виведено у форматі ISO. Параметр специфікація_обчислень є рядком, який сформовано поєднанням пар зО (значенняОперація), де з є можливо від’ємним числом, а О є однією з таких літер:

    • s — додати з секунд до значення дата

    • m — додати з хвилин до значення дата

    • h — додати з годин до значення дата

    • d — додати з днів до значення дата

    • w — додати з тижнів до значення дата

    • y — додати з років до значення дата, де роком вважаються 365 днів.

    Приклад: 1s3d-1m — додати 1 секунду, додати 3 дні і відняти 1 хвилину від дати дата.

  • days_between(дата1, дата2) — повертає кількість днів між датою дата1 і датою дата2``. Кількість днів є додатною, якщо дата1 перевищує дата2, інакше значення буде від’ємним. Якщо значення дата1 або значення дата2 не вдасться обробити як дату, функція поверне порожній рядок.

  • divide(x, y) — повертає частку x / y. Повідомляє про виключення, якщо x або y не є числом. Зазвичай, цю функцію можна замінити оператором /.

  • ``eval(рядок) — обробляє рядок як програму з передаванням локальних змінних <template_mode>`. Це надає змогу скористатися обробником шаблонів для побудови складних результатів на основі локальних змінних. У режимі програмування шаблонів символи «{» і «}» обробляють до обробки шаблона, тому вам слід використовувати «[[» для позначення символу «{» і «]]» для позначення символу «}». Перетворення буде виконано автоматично. Також слід зауважити, що у аргументі цієї функції не можна використовувати префікси і суфікси (тобто синтаксичні конструкції, подібні до «|префікс|суфікс»), якщо використовується режим програмування шаблонів.

  • extra_file_size(назва_файла) — повертає розмір у байтах додаткового файла «назва_файла» у теці «data/» книги, якщо він існує. Якщо файла не існує, повертає -1. Див. також функції has_extra_files(), extra_file_names() та extra_file_modtime(). Цією функцією можна скористатися лише у графічному інтерфейсі.

  • extra_file_modtime(назва_файла, рядок_формату) — повертає час внесення змін до додаткового файла назва_файла у теці data/ книги, якщо він існує. Якщо файла не існує, повертає -1. Час внесення змін буде форматовано відповідно до рядка формату (див. format_date()). Якщо специфікатор формату є порожнім, повертає час внесення змін як десятковий дріб секунд з початку епохи. Див. також функції has_extra_files(), extra_file_names() та extra_file_size(). Значення епохи є специфічним для операційної системи. Цією функцією можна скористатися лише у графічному інтерфейсі.

  • extra_file_names(роздільник[, взірець]) — список відокремлених роздільником назв файлів у теці data/ книги. Якщо вказано необов’язковий параметр «взірець» (формальний вираз), список буде відфільтровано до файлів, які відповідають взірцю. Відповідність визначатиметься без врахування регістру символів. Див. також функції has_extra_files(), extra_file_modtime() та extra_file_size(). Цією функцією можна скористатися лише у графічному інтерфейсі.

  • field(назва_для_пошуку) — повертає значення поля метаданих із назвою для пошуку назва_для_пошуку.

  • field_exists(назва_поля) — перевіряє, чи існує поле (стовпчик) із назвою для пошуку назва_поля. Повертає '1', якщо поле існує, і порожній рядок, якщо не існує.

  • finish_formatting(значення, формат, префікс, суфікс) — застосувати формат, префікс і суфікс до значення у спосіб, у який це виконується шаблоном, зокрема {series_index:05.2f| - |- }. Цю функцію створено для спрощення перетворення складних шаблонів режиму єдиної функції і програмного режиму до шаблонів загального програмного режиму. Наприклад, наведена нижче програма виводить ті самі дані, що і вказаний вище програма-шаблон:

    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(значення, [ умова, результат, ]* інший_результат) — послідовно виконує порівняння значення < умова, повертаючи пов’язаний результат для першої з виконаних умов у послідовності. Повертає інший_результат, якщо жодну з умов не буде виконано. Приклад:

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

    повертає "large". Той самий приклад із першим значенням 16 повертатиме "giant".

  • first_non_empty(значення [, значення]*) — повертає перше значення, яке не є порожнім. Якщо всі значення є порожніми, повертає порожній рядок. Ви можете вказати довільну кількість значень.

  • floor(x) — повертає найбільше ціле число, яке є меншим або рівним x. Надсилає виключення, якщо x не є числом.

  • format_date(значення, рядок_формату) — форматувати значення, яке має бути рядком дати, на основі значення рядок_формату, повернути рядок. Коди форматування:

    • 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   : перетворити дату і час у число із рухомою крапкою (часову позначку)

    • 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(назва_поля, рядок_форматування) — форматувати значення у полі назва_поля, яке має бути фільтром поля дати, стандартного або нетипового. Див. format_date(), щоб дізнатися більше про коди форматування. Ця функція є набагато швидшою за format_date. Нею слід користуватися, якщо ви форматуєте значення у полі (стовпчику). Нею не можна користуватися для обчислених дат або дат у рядкових змінних. Приклади:

    format_date_field('pubdate', 'yyyy.MM.dd')
    format_date_field('#date_read', 'MMM dd, yyyy')
    
  • formats_modtimes(рядок_формату_дати) — повертає відокремлений комами список відокремлених двокрапками пунктів ФОРМАТ:ДАТА, які відповідають часу внесення змін до файлів форматів книги. Параметр рядок_формату_дати визначає спосіб форматування дати. Докладніше про цей формат можна дізнатися з опису функції format_date(). Для отримання даних щодо часу внесення змін до одного з форматів ви можете скористатися функцією select. Зауважте, що назви форматів буде вказано великими літерами, наприклад EPUB.

  • formats_paths() — повернути розділений комами список розділених двокрапками записів ФОРМАТ:ШЛЯХ, щоб відповідають шляхам до файлів книги у різних форматах. Для отримання шляху до файла певного формату ви можете скористатися функцією select. Зауважте, що назви форматів слід вказувати великими літерами, ось так: EPUB.

  • formats_sizes() — повертає відокремлений комами список відокремлених двокрапками пунктів ФОРМАТ:РОЗМІР, які відповідають об’єму у байтах файлів форматів книги. Для отримання даних щодо об’єму файла у одному з форматів ви можете скористатися функцією select. Зауважте, що назви форматів буде вказано великими літерами, наприклад EPUB.

  • fractional_part(x) — повертає дробову частину десяткового числа. Наприклад, fractional_part(3.14) дорівнює 0.14. Надсилає виключення, якщо x не є числом.

  • get_link(назва_поля, значення_поля) — отримати посилання для поля назва_поля зі значенням значення_поля. Якщо немає пов’язаного посилання, повертає порожній рядок. Приклади:

  • Наведена нижче команда повертає посилання, яке пов’язане із міткою Fiction:

    get_link('tags', 'Fiction')
    
  • Цей шаблон створює список посилань для усіх міток, які пов’язано із книгою, у форматі значення:посилання, ...:

    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
    
  • hascover() — повертає «Yes», якщо у книги є зображення обкладинки, інакше повертає порожній рядок.

  • has_extra_files([взірець]) — повертає кількість додаткових файлів, якщо такі є. Якщо файлів немає, повертає „“ (порожній рядок). Якщо вказано необов’язковий параметр «взірець» (формальний вираз), список, перш ніж буде виконано обчислення кількості, буде відфільтровано до файлів, які відповідають взірцю. Відповідність визначатиметься без врахування регістру символів. Див. також функції extra_file_names(), extra_file_size() та extra_file_modtime(). Цією функцією можна скористатися лише у графічному інтерфейсі.

  • identifier_in_list(значення, назва_ідентифікатора [, значення_якщо_знайдено, значення_якщо_не_знайдено]) — обробити значення як список відокремлених комами ідентифікаторів. Ідентифікатор слід записувати у форматі «назва_ідентифікатора:значення». Параметр назва_ідентифікатора є текстом назви ідентифікатора, який слід знайти, або у форматі «назва_ідентифікатора» або «назва_ідентифікатора:формальний_вираз». Відповідність у першому випадку буде встановлено, якщо буде виявлено будь-який ідентифікатор, що відповідає критерію «назва_ідентифікатора». У другому випадку відповідність буде встановлено, якщо «назва_ідентифікатора» відповідає ідентифікатору, а «формальний_вираз» відповідає значенню ідентифікатора. Якщо задано значення_якщо_знайдено і значення_якщо_не_знайдено, якщо буде встановлено відповідність, програма поверне значення_якщо_знайдено. Якщо нічого не буде знайдено, програма поверне значення_якщо_не_знайдено. Якщо не задано значення_якщо_знайдено і значення_якщо_не_знайдено, якщо буде встановлено відповідність, програма поверне пару ідентифікатор:значення. Якщо значення не задано, буде повернуто порожній рядок ('').

  • is_marked() — перевірити, чи має книга стан marked у calibre. Якщо це так, буде повернуто значення позначки, або 'true' (у нижньому регістрі), або список іменованих позначок, які відокремлено комами. Повертає '' (порожній рядок), якщо книгу не позначено. Ця функція працює лише у графічному інтерфейсі.

  • language_codes(рядки_мов) — повертає коди мов для назв мов, які передано за допомогою аргументу рядки_мов. Рядки має бути вказано мовою поточної локалі. Аргумент рядки_мов є списком значень, які відокремлено комами.

  • list_contains(значення, роздільник, [ взірець, значення_якщо_знайдено, ] значення_якщо_не_знайдено) — (альтернатива in_list) обробляє значення як список пунктів, відокремлених роздільником, порівнює взірець з кожним зі значень у списку. Якщо рядок збігається зі значенням, повертає значення_якщо_знайдено, інакше повертає значення_якщо_не_знайдено. Значення взірець і значення_якщо_знайдено можна повторювати довільну кількість разів, залежно від пошуку. Перевірка взірців виконується послідовно. Функція повертає перший знайдений відповідник. Варіанти: in_list(), list_contains()

  • list_count(значення, роздільник) — за заданим значенням списком пунктів, відокремлених роздільником роздільник, повертає кількість пунктів у списку. Варіанти: count(), list_count()

  • list_count_matching(список, взірець, роздільник) — за заданим значенням списком пунктів, відокремлених роздільником «роздільник», повертає кількість пунктів у списку, які відповідають заданому формальним виразом взірцю. Варіанти: list_count_matching(), count_matching()

  • list_difference(список1, список2, роздільник) — повертає список, створений вилученням зі списку список1 всіх пунктів, які містяться у списку список2, на основі порівняння без врахування регістру. Пункти у списках список1 і список2 відокремлюються роздільником «роздільник», як і пункти у повернутому функцією списку.

  • list_equals(список1, роздільник1, список2, роздільник2, значення_якщо_так, значення_якщо_ні) — повертає значення_якщо_так, якщо список1 і список2 містять однакові записи``. Якщо це не так, повертає значення_якщо_ні. Записи визначаються поділом кожного зі списків на основі вказаного символу роздільника (роздільник1 або роздільник2). Порядок записів у списках не береться до уваги. Порівняння виконуватиметься без врахування регістру символів.

  • list_intersection(список1, список2, роздільник) — повертає список, створений вилученням зі списку список1 всіх пунктів, яких немає у списку список2, на основі порівняння без врахування регістру. Пункти у списках список1 і список2 відокремлюються роздільником «роздільник», як і пункти у повернутому функцією списку.

  • list_join(із_роздільником, список1, роздільник1 [, список2, роздільник2]*) — повертає список, створений об’єднанням записів у початкових списках (список1, список2 тощо) з використанням роздільника із_роздільником між записами у списку-результаті. Записи у кожному із початкових списків список[123...] розділено відповідним роздільником роздільник[123...]. У списку можуть міститися нульові значення. Він може бути полем, подібним до поля видавця, яке має одне значення, фактично, списком з одного запису. Дублікати буде вилучено з використанням порівняння без врахування регістру символів. Записи буде повернуто у порядку, у якому їх вказано у початкових списках. Якщо записи у списках відрізняються лише регістром символів, буде використано останній з них. Усі роздільники можуть складатися з декількох символів.

    Приклад:

    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: », за яким має бути вказано першу літеру жанру, тобто, якщо жанром є «Fiction», матимемо «Genre: F». Результату можна досягти так:

    program:
      list_join('#@#', $authors, '&', list_re($#genre, ',', '^(.).*$', 'Genre: \1'),  ',')
    
  • list_re(початковий_список, роздільник, фв_пошуку, пар_заміни) — будує список таким чином: спочатку поділяє початковий_список на запис на основі вказаного символу роздільник. Для кожного з записів у списку перевіряє відповідність формальному виразу фв_пошуку. Якщо відповідність буде встановлено, запис буде додано до повернутого списку. Якщо параметр пар_заміни не буде порожнім, заміну буде виконано до додавання запису до повернутого списку.

  • list_re_group(список_джерел, роздільник, фв_включення, фв_пошуку [, шаблон_групи]*) — Подібне до list_re, але замінники є обов’язковими. Використовує re_group(пункт_списку, фв_пошуку, шаблон ...) під час виконання замін у остаточному списку.

  • list_remove_duplicatesunion(список, роздільник) — повертає список, створений вилученням дублікатів з початкового списку. Якщо записи пунктів відрізнятимуться лише регістром символів, буде повернуто лише останній з них. Пункти у списку має бути відокремлено роздільником, який також буде використано під час формування списку-результату.

  • list_sort(список, напрямок, роздільник) — повертає список, впорядкований без врахування регістру. Якщо значенням параметра напрямок є нуль, список буде впорядковано за зростанням. Якщо значення буде іншим, список впорядковуватиметься за спаданням. Записи у початковому списку має бути відокремлено роздільником, як і записи у списку-результаті.

  • lis_split(значення_список, роздільник, префікс_ідентифікатора) — ділить значення_список на окремі значення з використанням роздільника роздільник, а потім надає значення локальним змінним із назвами префікс_ідентифікатора_N, де N — позиція значення у списку. Перший запис має позицію 0 (нуль). Функція повертає останній елемент у списку.

    Приклад:

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

    дає такий результат:

    var_0 = 'one';
    var_1 = 'two';
    var_2 = 'foo
    
  • list_union(список1, список2, роздільник) — повертає список, створений за допомогою об’єднання пунктів у списках список1 і список2` з вилученням дублікатів, виявлених шляхом порівняння без врахування регістру символів. Якщо записи пунктів відрізнятимуться лише регістром символів, використовуватиметься пункт зі списку ``список1. Пункти у списках список1 і список2 має бути відокремлено роздільником, який також буде використано під час формування списку-результату. Варіанти: merge_lists()`, list_union()

  • mod(x) — повертає floor від лишку від ділення x / y. Повідомляє про виключення, якщо x або y не є числом.

  • multiply(x [, y]*) — повертає добуток аргументів. Надсилає повідомлення про виключення, якщо аргумент не є числом. Зазвичай, цю функцію можна замінити оператором *.

  • not(значення) — повертає рядок «1», якщо значення не є порожнім. Якщо значення є порожнім, повертає порожній рядок. Зазвичай, цю функцію можна замінити на унарний оператор «НІ» (!).

  • ondevice() — повертає 'Yes', якщо встановлено ondevice, інакше повертає порожній рядок

  • or(значення [, значення]*) — повертає рядок "'1", якщо хоч одне значення не є порожнім. Якщо всі значення є порожніми, повертає порожній рядок. Кількість значень може бути довільною. Зазвичай, цю функцію можна замінити оператором ||. Причиною того, що її не можна замінити, є те, що при оптимізації обчислення може бути змінено результати через сторонні ефекти.

  • print(a [, b]*) — виводить аргументи до стандартного виведення. Якщо ви не запускали calibre з командного рядка (calibre-debug -g), дані нікуди не буде виведено. Функція print завжди повертає свій перший аргумент.

  • range(початок, кінець, крок, обмеження) — повертає список, який створено циклічним проходженням діапазону, який вказано параметрами «початок», «кінець» та «крок» із максимальною довжиною «обмеження». Першим значенням у списку буде «початок». Наступними значеннями будуть наступне_значення = поточне_значення + крок. Проходження циклу триватиме, доки наступне_значення < кінець , якщо крок є додатним, інакше, доки наступне_значення > кінець. Буде виведено порожній список, якщо не буде виконано умову початок >= кінець і крок є додатним. Значення обмеження встановлює максимальну довжину списку. Типовим значенням є 1000. Параметри початок, крок і обмеження є необов’язковими. Виклик range() із одним аргументом задає кінець. Два аргументи задають початок і кінець. Три аргументи задають початок, кінець і крок. Чотири аргументи задають початок, кінець, крок і обмеження. Приклади:

    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(назва_для_пошуку [, необов'язкове_типове_значення]) — повертає вміст іменованого поля метаданих без застосування форматування. Обробляє і повертає додатковий другий аргумент, необов'язкове_типове_значення, якщо значення поля не визначено (None).

  • raw_list(назва_для_пошуку, роздільник) — повертає список метаданих з назвою «назва_для_пошуку» без застосування будь-якого форматування або упорядковування. Записи у списку буде відокремлено значенням «роздільник».

  • re_group(значення, взірець [, шаблон_для_групи]*) — повертає рядок, створений за допомогою застосування формального виразу заданого зразком до значення та заміною кожного з відповідників значенням, повернутим відповідним шаблоном. У режимі шаблонного програмування, як і у функціях template та eval, замість { слід використовувати [[, замість }]].

    У наведеному нижче прикладі виконується пошук записів циклів із декількох слів і перша літера першого слова замінюється на велику:

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

  • series_sort() — повертає значення впорядкування циклу.

  • strcat(a [, b]*) — може приймати довільну кількість аргументів. Повертає рядок, отриманий з’єднанням всіх аргументів..

  • strcat_max(максимум, рядок1 [, префікс2, рядок2]*) — повертає рядок, утворений об’єднанням аргументів функції. Початковим значенням результату буде рядок1. Пари префікс, рядок додаватимуться в кінець результату, якщо довжина рядка-результату не перевищуватиме значення максимум. Префікси можуть бути порожніми. Значення рядок1 буде повернуто, навіть якщо довжина рядка рядок1 перевищує максимум. Функції можна передавати довільну кількість пар префікс, рядок.

  • 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(значення) — повертає довжину рядка значення.

  • substr(рядок, початок, кінець) — повертає символи від символу з номером початок до символу з номером кінець у рядку рядок. Вважається, що у рядок починається з нульового символу. Якщо значення кінець є від’ємним, символи буде відраховано у напрямку до початку рядка. Якщо значенням кінець є нуль, кінцем вважатиметься останній символ. Приклади: substr('12345', 1, 0) повертає '2345', а substr('12345', 1, -1) повертає '234'.

  • subtract(x, y) — повертає різницю x - y. Повідомляє про виключення, якщо x або y не є числом. Зазвичай, цю функцію можна замінити оператором -.

  • switch_if([вираз_перевірки, вираз_значення,]+ альтернативний_вираз) — для кожної пари вираз_перевірки, вираз_значення перевіряє, чи дорівнює вираз_перевірки True (непорожнє значення) і, якщо це так, повертає результат вираз_значення. Якщо, жоден вираз_перевірки не дорівнює True, буде повернуто альтернативний_вираз. Можлива кількість пар вираз_перевірки, вираз_значення є необмеженою.

  • today() — повертає сьогоднішню дату і час (зараз). Це значення створено для використання у format_date або days_between, але з ним можна працювати як зі звичайним рядком. Дату буде повернуто у форматі ISO <https://en.wikipedia.org/wiki/ISO_8601>`_.

  • template(x) — обробляє x як шаблон. Обробка виконується у власному контексті, тобто змінні не є спільними для обробки функції виклику і шаблона.

  • to_hex(значення) — повертає рядок значення, який закодовано шістнадцятковими числами. Корисно при побудові адрес calibre.

  • urls_from_identifiers(ідентифікатори, упорядкувати_результати) — за заданим списком відокремлених комами ідентифікаторів, де ідентифікатором є пара відокремлених двокрапкою значень (назва:значення_ідентифікатора), повертає список відокремлених комами адрес HTML на основі ідентифікаторів. Список лишиться неупорядкованим, якщо упорядкувати_результати має значення 0 (символ або число), інакше, список буде упорядковано за назвами ідентифікаторів. Адреси буде створено у той самий спосіб, що і для вбудованого стовпчика ідентифікаторів, який показано на панелі подробиць щодо книги.

Складніші програми у виразах шаблонів — режим програмування шаблонів.

Режим програмування шаблонів є сумішшю загального режиму програмування і режиму єдиної функції. Режим програмування шаблонів відрізняється від режиму єдиної функції тим, що у ньому можна писати вирази шаблонів, які посилаються на інші поля метаданих, використовувати вкладені функції, змінювати значення змінних і виконувати арифметичні дії. Він відрізняється від загального режиму програмування тим, що шаблон міститься між символами { і } і не починається зі слова program:. Програмна частина шаблона є списком виразів загального режиму програмування.

Почнімо з прикладу. Припустімо, що ви хочете, щоб ваш шаблон показував цикл для книги, яка належить до циклу, і значення нетипового поля #genre, якщо книга не належить до циклів. Зробити це за допомогою режиму єдиної функції неможливо, оскільки ви не можете послатися на інше поле метаданих у виразі шаблона. Але у програмному режимі ви можете це зробити. Спрацює такий вираз:

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

Приклад демонструє декілька речей:

  • Режим програмування шаблонів буде використано, якщо вираз починається з :' і завершується '}. Усі інші варіанти вважатимуться використанням режиму єдиної функції.

  • змінна $ позначає іменоване у шаблоні поле, яке обробляє вираз; у нашому випадку це #series.

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

  • пробіли буде проігноровано; їх можна використовувати будь-де у виразі.

  • сталі рядки слід брати у відповідні лапки ' або ".

У режимі програмування шаблонів можна користуватися усіма функціями зі списків режиму єдиної функції і загальному режимі програмування.

У режимі програмування шаблонів використання символів { і } у рядкових літералах режиму програмування шаблонів може призвести до помилок або неочікуваних результатів, оскільки ці символи заважають нормальній роботі обробника шаблонів. Він намагається обробити їх як межі виразу шаблона, а не символи. У деяких, але не в усіх випадках, ви можете замінити { на [[ і } на ]]. Загалом кажучи, якщо у вашій програмі є символи { і }, вам слід користуватися загальним режимом програмування.

Як і у загальному режимі програмування, для функцій з документації до режиму єдиної функції вам доведеться передати функції значення, з яким вона має працювати, як перший параметр, додаткового до документованих параметрів. У режимі програмування шаблонів ви можете скористатися $ для доступу до значення, яке вказано назвою для пошуку для виразу шаблона.

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

Режим шаблонів Python (PTM) надає вам змогу писати шаблони за допомогою мови Python та програмного інтерфейсу calibre. Найкориснішим програмним інтерфейсом буде програмний інтерфейс роботи з базою даних. Подальше обговорення не належить до предмета цього підручника. Шаблони PTM є швидшими і можуть виконувати складніші дії, але вам потрібні будуть значення щодо написання коду мовою Python за допомогою програмного інтерфейсу calibre.

Шаблон 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.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<python_mode> передбачено можливість збереження шаблонів загального режиму програмування та виклику цих шаблонів з інших шаблонів, подібно до виклику збережених функцій. Зберегти шаблони можна за допомогою пункту :guilabel:`Налаштування->Додатково->Шаблонні функції. у відповідному діалоговому вікні буде наведено довідкову інформації. Викликати шаблон можна у той самий спосіб, що і функцію, передавши йому, якщо потрібно, позиційні аргументи. Аргументом може бути будь-який вираз. Приклади виклику шаблону, де ми припускаємо, що збережений шаблон має назву foo:

  • foo() — виклик шаблону без передавання аргументів.

  • foo(a, b) — виклик шаблону з передаванням значень двох змінних — a і b.

  • foo(if field('series') then field('series_index') else 0 fi) — якщо книга належить до циклу, передати номер книги у циклі, інакше — передати значення 0.

Отримання аргументів відбувається за допомогою виклику збереженого шаблона за допомогою функції 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, який є списком рядків. Не існує способу вказати типові значення. Вам слід перевірити довжину списку arguments, щоб переконатися, що кількість аргументів є тією, на яку ви сподіваєтеся.

Простим способом тестування збережених шаблонів є використання вікна Засіб тестування шаблонів. Для полегшення доступу надайте цьому вікну клавіатурного скорочення за допомогою пункту Налаштування → Додатково → Клавіатурні скорочення → Засіб тестування шаблонів. Надання клавіатурного скорочення вікну Збережені шаблони допоможе вам швидше перемикатися між тестуванням та редагування початкового коду збереженого шаблону.

Надання додаткової інформації шаблонам

Розробник може передати додаткові відомості обробнику шаблонів, зокрема, специфічні для книги метадані або відомості про те, що слід виконати обробнику. Шаблон може отримувати доступ до цих відомостей і використовувати їх під час обробки.

Розробник: як передати додаткові відомості

Додатковими відомостями є словник Python, який містить пари назва_змінної: значення_змінної, де значеннями мають бути рядки. Шаблон може отримувати доступ до словника, створюючи локальні змінні із назвами назва_змінної, які міститимуть значення значення_змінної. Користувач не може змінювати назву, тому краще користуватися назвами, які не збігатимуться із локальними змінними інших шаблонів. Можна, наприклад, додати до усіх назв початковий символ підкреслювання.

Цей словник буде передано обробнику шаблонів (форматувальнику) за допомогою іменованого параметра global_vars=ваш_словник. Ось повний запис методу:

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]]*)

де записом ідентифікатор є будь-яка коректна назва змінної. Ця функція перевіряє, чи у додаткових відомостях, наданих розробником, міститься відповідна назва. Якщо це так, функція призначає надане значення змінної локальній змінній із вказаною назвою. Якщо назву змінної не буде виявлено у додаткових відомостях і якщо вказано вираз, буде виконано обчислення виразу із призначенням результату локальній змінній. Якщо не буде знайдено ні значення, ні виразу, локальній змінній буде призначено порожній рядок ('').

Шаблон може встановлювати значення у словнику globals за допомогою шаблонної функції:

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

Ця функція встановлює значення пари словника globals ключ:значення ідентифікатор:значення, де значенням є значення локальної змінної шаблона ідентифікатор. Якщо такої локальної змінної не існує, значення буде встановлено для результату обчислення виразу.

Зауваження щодо відмінностей між режимами

У роботі трьох режимів програмування, режиму єдиної функції, режиму програмування шаблонів та загального режиму програмування є відмінності. Режим єдиної функції є «простим», тому у ньому багато можливостей програмування «приховано».

Відмінності:

  • У режимі єдиної функції значення стовпчика завжди передається як «невидимий» перший аргумент функції, включено до шаблона.

  • У режимі єдиної функції не передбачено підтримки розрізнення між змінними і рядками; усі значення є рядками.

  • У наведеному нижче шаблоні режиму єдиної функції шаблон повертає або назву циклу, або рядок «no series»:

    {series:ifempty(no series)}
    

    Еквівалентний шаблон у режимі програмування шаблонів:

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

    Еквівалентний шаблон у режимі загального програмування:

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

    Першим аргументом ifempty є значення поля series, а другим аргументом — рядок no series. У режимі єдиної функції перший аргумент, значення поля, передається автоматично (невидимий аргумент).

  • Декілька шаблонних функцій, зокрема booksize() і current_library_name(), не приймають аргументів. Через наявність невидимого аргументу ви не зможете скористатися цими функціями у режимі єдиної функції.

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

    {series:uppercase(substr(0,5))}
    
  • У шаблонному режимі програмування та загальному режимі програмування передбачено підтримку вкладених функцій. Наведений вище шаблон у шаблонному режимі програмування можна записати так:

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

    У загальному режимі програмування це було б:

    program: uppercase(substr(field('series'), 0,5))
    
  • Як було зауважено вище у розділі Режим програмування шаблонів, використання символів { і } у рядкових літералах режиму програмування шаблонів може призвести до помилок або неочікуваних результатів, оскільки ці символи заважають нормальній роботі обробника шаблонів. Він намагається обробити їх як межі шаблона, а не символи. У деяких, але не в усіх випадках, ви можете замінити { на [[ і } на ]]. Загалом кажучи, якщо у вашій програмі є символи { і }, вам слід користуватися загальним режимом програмування.

Визначені користувачем шаблонні функції Python

Ви можете додавати власні функції мовою Python до обробника шаблонів. Такими функціями можна скористатися в усіх трьох режимах програмування шаблонів. Додати функції можна за допомогою сторінки Налаштування  →  Додатково  →  Шаблонні функції. У діалоговому вікні, яке буде відкрито програмою, можна знайти відповідні настанови.

Спеціальні нотатки щодо шаблонів збереження або надсилання

До шаблонів, які використовуються для дій зберегти на диск і надіслати на пристрій, застосовується спеціальна обробка. Значення полів буде очищено із заміною символів, які мають спеціальне значення у файлових системах, зокрема символів похилих рисок, на символи підкреслювання. Це означає, що текст поля не можна використовувати для створення тек. Втім, похилі риски не замінюватимуться у рядках префікса і суфікса, отже похилі риски у цих рядках можна використати для створення тек. Таким чином, ви можете створити структуру тек довільного рівня вкладеності.

Наприклад, припустімо ми хочемо створити структуру тек цикл/номер_у_циклі - назва, із умовою, що якщо циклу не існує, назву слід розташувати у верхній теці. Шаблон для виконання цього завдання:

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

Похила риска і дефіс мають з’являтися, лише якщо цикл не є порожнім.

Функція lookup надає вам змогу виконувати виконувати навіть ще вишуканішу обробку. Наприклад, припустімо, що якщо книга належить до циклу, ми хочемо мати структуру тек цикл/номер у циклі - назва.формат. Якщо книга не належить до циклу, нам потрібна структура тек жанр/упорядковане ім’я автора/назва.формат. Якщо ж книга не належить до певного жанру, слід скористатися текою „Unknown“. Нам потрібно два повністю різних шляхи, залежно від значення параметра циклу.

Для виконання цього завдання ми:

  1. Створимо складене поле (надавши йому назву #aa), що міститиме дані {series}/{series_index} - {title}. Якщо значення циклу (series) є непорожнім, такий шаблон дасть нам цикл/номер_у_циклі - назва.

  2. Створимо складене поле (надавши йому назву #bb) із вмістом {#genre:ifempty(Unknown)}/{author_sort}/{title}. Цей шаблон дає жанр/упорядковані_автори/назва. Якщо немає даних щодо жанру, запис жанру буде замінено на Unknown.

  3. Встановимо шаблон збереження {series:lookup(.,#aa,#bb)}. Цей шаблон вибирає складене поле #aa, якщо значення запису циклу є непорожнім, і складене поле #bb, якщо значення запису циклу є порожнім. Таким чином, ми матимемо повністю різні шляхи для збереження книг, залежно від того, чи є запис series порожнім.

Підказки

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

  • У шаблонах можна використовувати інші шаблони шляхом посилання на складені стовпчики, які побудовано за допомогою бажаних шаблонів. Крім того, ви можете скористатися «Збереженими шаблонами».

  • У наборі метаданих ви можете вказати порожні значення поля (або вказати будь-який еквівалент порожнього поля) за допомогою спеціального шаблона {}. Цей шаблон завжди обробляється як порожній рядок.

  • Описана вище методика для показу чисел працює зі стандартним полем series_index, навіть якщо вміст відповідного поля є порожнім.

Довідник з функцій