Мова шаблонів 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}

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

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

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

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

Зауваження щодо виклику функцій у режимі єдиної функції:

  • При використанні функцій у режимі єдиної функції перший параметр, значення, буде автоматично замінено на вміст поля, яке вказано у шаблоні. Наприклад, при обробці шаблона {title:capitalize()} вміст поля title буде передано як параметр значення функції capitalize.

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

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

Документацію до функцій наведено у розділі Посилання на функцію шаблона. У документації описано потрібні для роботи функцій аргументи та завдання, які виконують функції. Наприклад, ось документація до функції ifempty.

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

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

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

показує мітки книги, якщо такі є. Якщо міток немає, показує No tags on this book.

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

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

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

  • cmp(значенян, y, lt, eq, gt) — порівнює значення і y після перетворення обох величин у числа.

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

  • date_arithmetic(дата, специфікація_обчислень, формат) — обчислення нової дати на основі дати «дата» з використанням «специфікації_обчислень»..

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

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

  • format_number(значення, шаблон) — вважати значення числом і форматувати число на основі шаблону форматування python, наприклад {0:5.2f}, {0:,d} або ${0:5,.2f}.

  • fractional_part(значення) — повертає дробову частину десяткового числа.

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

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

  • language_strings(коди_мов, локалізація) — повертає назви мов для кодів мов (назви і коди), які передано як значення..

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

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

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

  • list_item(значення, номер, роздільник) — обробляє значення як список пунктів, відокремлених роздільником «роздільник», повертає пункт з номером «номер».

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

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

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

  • mod(значення, y) — повертає floor від лишку від ділення значення / y.

  • rating_to_stars(використання_пів_зірок) — повертає оцінку як рядок з символів зірок ().

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

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

  • round(значення) — повертає найближче до значення ціле число.

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

  • shorten(значення символи ліворуч, текст посередині, символи праворуч) — повертає скорочену версію значення, яка складається із вказаної кількості символи ліворуч символів на початку значення, далі з тексту посередині, і далі кількості символи праворуч символів наприкінці значення.

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

  • subitems(значення, початковий_номер, кінцевий_номер) — цією функцією користуються для розбиття списків пунктів, зокрема списків жанрів.

  • sublist(значення, початковий_номер, кінцевий_номер, роздільник) — обробляє значення як список пунктів, відокремлених роздільником «роздільник», повертає новий список, створений з пунктів з номера «початковий_номер» до номера «кінцевий_номер».

  • substr(рядок, початок, кінець) — повертає символи від символу з номером початок до символу з номером кінець у рядку рядок.

  • swap_around_articles(роздільник) — повертає значення із артиклями, які пересунуто в кінець.

  • swap_around_comma(значення) — за заданим значенням у форматі B, A повертає значення A B.

  • switch([взірецьN, значенняN,]+ інше_значення) для кожної пари ``взірецьN, значенняN перевіряє, чи відповідає поле формальному виразу взірецьN.

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

  • titlecase(значення) — повернути значення у регістрі заголовка.

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

  • ff_““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' | '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' є тим самим значенням.

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

Пріоритетність операторів

Пріоритетність операторів (порядок обчислення), від найвищої (обчислюються першими) до найнижчої (обчислюються останніми):

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

  • Унарні плюс (+) і мінус (-). Обчислення для цих операторів виконується справа ліворуч.

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

  • Множення (*) і ділення (/). Ці дії є асоціативними і обчислюються зліва праворуч. Скористайтеся дужками, якщо ви хочете змінити порядок обчислення.

  • Додавання (+) і віднімання (-). Ці дії є асоціативними, обчислення виконується зліва праворуч.

  • Порівняння чисел і рядків. Ці оператори повертають '1', якщо порівняння справджується, інакше повертають порожній рядок (''). Порівняння не є асоціативними: a < b < c — синтаксична помилка.

  • Поєднання рядків (&). Оператор & повертає рядок, який сформовано об’єднанням виразів ліворуч і праворуч від нього. Приклад: 'aaa' & 'bbb' повертає 'aaabbb'. Оператор є асоціативним і обчислюється зліва праворуч.

  • Унарне логічне заперечення (!). Цей оператор повертає '1', якщо вираз не є істинним (є порожнім рядком), інакше повертає ''.

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

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

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

Інструкцію field_reference буде замінено значенням поля метаданих, яке має назву пошуку, яку вказано після $ або $$. Використання $ є еквівалентне до використання функції ref:ff_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 та inlist_field. Для оператора in результат обчислення лівого операнда вважається формальним виразом взірця. Результатом обчислення in є True, якщо взірець у лівого операнда відповідає значенню правого операнда. Відповідність встановлюється без врахування регістру символів.

Оператор inlist повертає true, якщо формальний вираз ліворуч від нього відповідає одному із записів у списку праворуч від нього, де записи у списку відокремлено комами. Оператор field_inlist повертає 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 повертає '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)$' 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', оскільки оператор ># виконує числове порівняння.

Функції у режимі загального програмування

Див. розділ Посилання на функцію шаблона, у якому наведено список функцій, які вбудовано до мови шаблонів.

Нотатки:

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

  • Усі параметри є expression_lists (див. граматику вище).

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

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

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

{series_index:0>7.1f:'ifempty($, -5)'}

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

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

    Якщо у шаблоні міститься префікс і суфікс, вираз завершується на '|, де | — роздільник для префікса. Приклад:

    {series_index:0>7.1f:'ifempty($, -5)'|prefix | suffix}
    
  • Функціям мають передаватися усі їхні аргументи. Наприклад, стандартним вбудованим функціями слід передавати початковий параметр значення.

  • Змінну $ використовують як аргумент значення, вона замінює значення поля, яке іменовано у шаблоні, у цьому випадку``series_index``.

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

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

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

Режим шаблонів 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 до обробника шаблонів. Такими функціями можна скористатися в усіх трьох режимах програмування шаблонів. Додати функції можна за допомогою сторінки Налаштування  →  Додатково  →  Шаблонні функції. У діалоговому вікні, яке буде відкрито програмою, можна знайти відповідні настанови. Зауважте, що для досягнення тієї самої мети ви можете скористатися Шаблонами 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, навіть якщо вміст відповідного поля є порожнім.

Посилання на функцію шаблона