Le langage de modèle calibre

Le langage de modèle de calibre est un langage spécifique à calibre utilisé dans l’ensemble de calibre pour des tâches telles que la spécification des chemins de fichiers, le formatage des valeurs et le calcul de la valeur des colonnes spécifiées par l’utilisateur. Exemples :

  • Spécifier la structure du dossier et les noms de fichiers lors de l’enregistrement des fichiers de la bibliothèque calibre sur le disque ou le lecteur de livres numériques.

  • Définir des règles pour l’ajout d’icônes et de couleurs à la liste de livres de calibre.

  • Définir les colonnes virtuelles qui contiennent des données provenant d’autres colonnes.

  • Recherche avancée dans la bibliothèque.

  • Recherche et remplacement avancé des métadonnées.

Le langage est construit autour de la notion de modèle, qui spécifie les métadonnées du livre à utiliser, les calculs sur ces métadonnées, et la façon dont elles doivent être formatées.

Modèles de base

Un modèle de base est constitué d’une ou plusieurs expression modèle. Une expression modèle consiste en du texte et des noms entre crochets ({}) qui sont remplacés par les métadonnées correspondantes du livre en cours de traitement. Par exemple, le modèle par défaut de calibre utilisé pour enregistrer des livres sur un périphérique comporte 4 expressions modèle:

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

Pour le livre « The Foundation » par « Isaac Asimov » cela donnera:

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

Les barres obliques ne sont pas des expressions modèle car elles se trouvent entre les {}. Un tel texte est laissé là où il apparaît. Par exemple, si le modèle est:

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

dès lors, pour « The Foundation », le modèle produit:

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

Une expression modèle peut accéder à toutes les métadonnées disponibles dans calibre, y compris les colonnes personnalisées (colonnes que vous créez vous-même), en utilisant le nom de recherche d’une colonne. Pour trouver le nom de recherche d’une colonne (parfois appelée champs), passez votre souris sur l’en-tête de la colonne dans la liste des livres de calibre. Les noms de recherche pour les colonnes personnalisées commencent toujours par #. Pour les colonnes de type série, il y a un champ supplémentaire appelé #lookup name_index qui est l’index de la série pour ce livre dans la série. Par exemple, si vous avez une colonne de série personnalisée nommée #messéries, il y aura également une colonne nommée #messéries_index. L’index de la colonne de série standard est nommé series_index.

En plus des champs standard basés sur des colonnes, vous pouvez également utiliser :

  • {formats} - Une liste des formats disponibles dans la bibliothèque calibre pour un livre

  • {identifiers:select(isbn)} - L’ISBN du livre

Si les métadonnées du champ pour un livre donné ne sont pas définies, le champ dans le modèle est remplacé par la chaîne vide (''). Par exemple, considérons le modèle suivant

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

Si le livre d’Asimov « Seconde Fondation » fait partie de la série « Fondation », alors le modèle produit

Asimov, Isaac/Foundation/Second Foundation 3

Si aucune série n’a été saisie pour le livre, le modèle produit

Asimov, Isaac/Second Foundation

Le processeur de modèles supprime automatiquement les barres obliques multiples et les espaces avant ou arrière.

Mise en forme avancée

Outre la substitution de métadonnées, les modèles peuvent inclure du texte supplémentaire de manière conditionnelle et contrôler le formatage des données substituées.

Comprenant conditionnellement le texte

Parfois, vous voulez que du texte n’apparaisse dans la sortie que si un champ n’est pas vide. Un cas courant est celui de series et series_index où vous voulez soit rien, soit les deux valeurs séparées par un trait d’union. calibre gère ce cas en utilisant une syntaxe spéciale de expression modèle.

Par exemple, et en utilisant l’exemple de Fondation ci-dessus, supposons que vous voulez que le modèle produise Fondation - 3 - Deuxième Fondation. Ce modèle produit ce résultat :

{series} - {series_index} - {title}

Cependant, si un livre n’a pas de série, le modèle produira - - le titre, ce qui n’est probablement pas ce que vous voulez. En général, les gens veulent que le résultat soit le titre sans les traits d’union superflus. Vous pouvez y parvenir en utilisant la syntaxe de modèle suivante :

{field:|prefix_text|suffix_text}

Cette expression modèle indique que si champ a la valeur XXXX, le résultat sera prefix_textXXXXXsuffix_text. Si field est vide (n’a pas de valeur) alors le résultat sera la chaîne vide (rien) car le préfixe et le suffixe sont ignorés. Le préfixe et le suffixe peuvent contenir des blancs.

Ne pas utiliser de sous-modèles (`{ … }`) ou de fonctions (voir ci-dessous) dans le préfixe ou le suffixe.

En utilisant cette syntaxe, nous pouvons résoudre le problème de non-série ci-dessus avec le modèle

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

Les traits d’union ne seront inclus que si le livre possède un index de série, ce qui n’est le cas que si le livre possède une série. Si l’on reprend l’exemple de Fondation, le modèle produira Fondation - 1 - Deuxième Fondation.

Notes :

  • Vous devez inclure les deux points après le nom de la recherche si vous utilisez un préfixe ou un suffixe.

  • Vous devez utiliser soit aucun des caractères |, soit les deux. L’utilisation d’un seul caractère, comme dans {field:| - }, n’est pas autorisée.

  • Il est possible de ne fournir aucun texte pour le préfixe ou le suffixe, comme dans {série:|| - }. Le modèle {title:||} est le même que {title}.

Formatage

Supposons que vous vouliez que series_index soit formaté en trois chiffres avec des zéros en tête. Ceci fait l’affaire :

{series_index:0>3s} - Trois chiffres avec des zéros en tête

Pour des zéros qui suivent, utilisez:

{series_index:0>3s} - Trois chiffres avec des zéros qui suivent

Si vous utilisez des indices de série avec des valeurs fractionnées, par exemple 1.1, vous pouvez souhaiter que les points décimaux soient alignés. Par exemple, vous pouvez vouloir que les indices 1 et 2.5 apparaissent sous la forme 01.00 et 02.50 afin qu’ils soient triés correctement sur un périphérique qui effectue un tri lexical. Pour ce faire, utilisez :

{series_index:0>5.2f} - Cinq caractères composés de deux chiffres avec des zéros en tête, un point décimal, puis deux chiffres après le point décimal.

Si vous ne voulez que les deux premières lettres de la donnée, utilisez :

{author_sort :.2} - Seulement les deux premières lettres du nom de tri de l’auteur

Une grande partie du formatage du langage de modèle de calibre provient de Python. Pour plus de détails sur la syntaxe de ces opérations de formatage avancées, voir la documentation Python <https://docs.python.org/3/library/string.html#formatstrings>

Utilisation de modèles pour définir des colonnes personnalisées

Les modèles peuvent être utilisés pour afficher des informations qui ne sont pas dans les métadonnées de calibre, ou pour afficher les métadonnées différemment du format normal de calibre. Par exemple, vous pourriez vouloir afficher le ISBN, un champ que calibre n’affiche pas. Pour cela, vous pouvez créer une colonne personnalisée de type Colonne construite à partir d’autres colonnes (appelée ci-après colonnes composites) et fournir un modèle pour générer le texte affiché. La colonne affichera le résultat de l’évaluation du modèle. Par exemple, pour afficher l’ISBN, créez la colonne et entrez « identifiers:select(isbn)} » dans la champ du modèle. Pour afficher une colonne contenant les valeurs de deux colonnes personnalisées de séries, séparées par une virgule, utilisez {#series1:||,}{#series2}.

Les colonnes composites peuvent utiliser n’importe quelle option modèle, y compris le formatage.

Remarque : Vous ne pouvez pas modifier les données affichées dans une colonne composite. Vous devez plutôt modifier les colonnes sources. Si vous modifiez une colonne composite, par exemple en double-cliquant dessus, calibre ouvrira le modèle à modifier, et non les données sous-jacentes.

Utilisation des fonctions dans les modèles - Mode de fonctionnement unique

Supposons que vous vouliez afficher la valeur d’un champ en casse majuscules alors que ce champ est normalement en casse titre. Vous pouvez le faire en utilisant les fonctions de modèle. Par exemple, pour afficher le titre en casse majuscules, utilisez la fonction uppercase, comme dans {title:uppercase()}. Pour l’afficher en casse titre, utilisez la fonction {title:titlecase()}.

Les fonctions sont placées dans la partie format du modèle, après le : et avant le premier | ou le } de fermeture si aucun préfixe/suffixe n’est utilisé. Si vous avez à la fois une référence de format et de fonction, la fonction vient après un deuxième :. Les fonctions renvoient la valeur de la colonne spécifiée dans le modèle, convenablement modifiée.

La syntaxe pour utiliser les fonctions est l’une des suivantes

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

Les noms de fonctions doivent toujours être suivis de parenthèses ouvrantes et fermantes. Certaines fonctions nécessitent des valeurs supplémentaires (arguments), qui sont placées à l’intérieur des parenthèses. Les arguments sont séparés par des virgules. Les virgules Littérales (les virgules en tant que texte, et non en tant que séparateurs d’arguments) doivent être précédées d’une barre oblique inversée (\) . Le dernier (ou le seul) argument ne peut pas contenir de parenthèse fermante textuelle.

Les fonctions sont évaluées avant les spécifications de format et le préfixe/suffixe. Voir plus bas pour un exemple d’utilisation à la fois d’un format et d’une fonction.

Important : Si vous avez de l’expérience en programmation, veuillez noter que la syntaxe du Mode Fonction Unique n’est pas celle à laquelle vous vous attendez. Les chaînes de caractères ne sont pas citées et les espaces sont significatifs. Tous les arguments sont considérés comme des constantes ; il n’y a pas d’expressions.

N’utilisez pas les sous-modèles (`{ … }`) comme arguments de fonction. A la place, utilisez plutôt Mode Programme Modèle et Mode Programme Général.

Certaines fonctions nécessitent des expressions régulières. Dans le langage des modèles, la correspondance des expressions régulières est insensible à la casse.

Dans la documentation des fonctions ci-dessous, la notation [quelque chose]* signifie que quelque chose peut être répété zéro fois ou plus. La notation [quelque chose]+ signifie que quelque chose est répété une ou plusieurs fois (doit exister au moins une fois).

Les fonctions destinées à être utilisées en Mode Fonction Unique sont les suivantes :

  • capitalize() – renvoie la valeur avec la première lettre en majuscule et le reste en minuscule.

  • contains(pattern, text if match, text if not match) – vérifie si la valeur est couverte par l’expression régulière pattern. Renvoie text if match si le motif correspond à la valeur, sinon renvoie text if no match.

  • count(separator) – interprète la valeur comme une liste d’éléments séparés par le separator et retourne le nombre d’éléments dans la liste. La plupart des listes utilisent une virgule comme séparateur, mais authors utilise une esperluette (&). Exemples : {tags:count(,)}, {authors:count(&)}. Alias : count(), list_count()

  • format_number(template) – interprète la valeur comme un nombre et formate ce nombre en utilisant un modèle de formatage Python tel que {0:5.2f} ou {0 :,d}` ou ${0:5,.2f}. Le modèle de formatage doit commencer par {0: et se terminer par } comme dans les exemples ci-dessus. Exception : vous pouvez omettre le début « {0 : » et la fin « } » si le modèle de format ne contient qu’un format. Voir le langage des modèles et la documentation Python pour plus d’exemples. Renvoie la chaîne vide si le formatage échoue.

  • human_readable() – s’attend que la valeur soit un nombre et renvoie une chaîne représentant ce nombre en KB, MB, GB, etc.

  • ifempty(text) – si le champ n’est pas vide, renvoie la valeur du champ. Autrement renvoie text if empty.

  • in_list(separator, [ pattern, found_val, ]* not_found_val) – interprète la valeur comme une liste d’éléments séparés par le separator, en vérifiant le pattern pour chaque élément de la liste. Si le pattern correspond à un élément, il renvoie found_val, sinon il renvoie not_found_val. La paire pattern``et ``found_value peut être répétée autant de fois que souhaité, ce qui permet de renvoyer des valeurs différentes selon la valeur de l’élément. Les motifs sont vérifiés dans l’ordre, et la première correspondance est retournée.

  • language_strings(localize) – retourne les noms de langue pour les codes de langue passés en tant que valeur. Exemple : {languages:language_strings()}. Si localize est zéro, retourne les chaînes de caractères en anglais. Si localize est différent de zéro, retourne les chaînes de caractères dans la langue de la locale courante. Lang_codes est une liste séparée par des virgules.

  • list_item(index, separator) – interprète la valeur comme une liste d’éléments séparés par un separator, en retournant index'. Le premier élément est le numéro zéro. Le dernier élément a l’indice -1 comme dans list_item(-1,separator). Si l’élément n’est pas dans la liste, alors la chaîne vide est retournée.

  • lookup([ pattern, key, ]* else_key) – Les motifs seront comparés à la valeur dans l’ordre. Si un motif correspond, la valeur du champ nommé par key est retournée. Si aucun motif ne correspond, la valeur du champ nommé par else_key est retournée. Voir switch (ci-dessous).

  • lowercase() – renvoie la valeur du champ en minuscule.

  • rating_to_stars(use_half_stars) – Renvoie la note sous forme de chaîne de caractères étoilés (). La valeur doit être un nombre entre 0 et 5. Définissez use_half_stars à 1 si vous voulez des caractères de demi-étoile pour les nombres fractionnés disponibles avec les colonnes d’évaluation personnalisées.

  • re(pattern, replacement) – retourne la valeur après application de l’expression régulière. Toutes les instances de pattern dans la valeur sont remplacées par replacement. Le langage des modèles utilise des Expressions régulières Python insensibles à la casse.

  • select(key) – interprète la valeur comme une liste d’éléments séparés par des virgules, chaque élément ayant la forme id:value (le format identifiant de calibre). La fonction trouve la première paire dont l’id est égal à key et renvoie la valeur correspondante. Si aucun id ne correspond, la fonction renvoie la chaîne vide.

  • shorten(left chars, middle text, right chars) – Renvoie une version raccourcie de la valeur, composée de left chars du début de la valeur, suivis de middle text, suivis de right chars de la fin de la valeur. Les « left chars » et les « right chars » doivent être des entiers non négatifs. Exemple : supposons que vous vouliez afficher le titre avec une longueur maximale de 15 caractères. Un modèle qui fait cela est {titre:shorten(9,-,5)}. Pour un livre dont le titre est Ancient English Laws in the Times of Ivanhoe, le résultat sera Ancient E-nhoe : les 9 premiers caractères du titre, un -, puis les 5 derniers caractères. Si la longueur de la valeur est inférieure à left chars + right chars + la longueur du middle text alors la valeur sera retournée inchangée. Par exemple, le titre Le Dôme ne sera pas modifié.

  • str_in_list(separator, [ string, found_val, ]+ not_found_val) – interprète la valeur comme une liste d’éléments séparés par le separator puis compare string à chaque valeur de la liste. string n’est pas une expression régulière. Si string est égal à n’importe quel élément (en ignorant la casse), alors il renvoie la found_val correspondante. Si string contient des separators, elle est également traitée comme une liste et chaque sous-valeur est vérifiée. Les paires string et found_value peuvent être répétées autant de fois que souhaité, ce qui permet de renvoyer des valeurs différentes selon la valeur de la chaîne. Si aucune des chaînes de caractères ne correspond, le système renvoie not_found_value. Les chaînes de caractères sont vérifiées dans l’ordre. La première correspondance est retournée.

  • subitems(start_index, end_index) – Cette fonction sépare les listes d’éléments hiérarchiques de type balise, comme les genres. Elle interprète la valeur comme une liste d’éléments de type balise séparés par des virgules, où chaque élément est une liste séparée par des points. Elle retourne une nouvelle liste faite en extrayant de chaque élément les composants de start_index à end_index, puis en fusionnant les résultats ensemble. Les doublons sont supprimés. Le premier sous-élément d’une liste séparée par un point a un indice de zéro. Si un index est négatif, il est compté à partir de la fin de la liste. Dans un cas particulier, un end_index de zéro est supposé être la longueur de la liste.

    Exemples :

    • Supposons une colonne #genre contenant A.B.C :

      • {#genre:subitems(0,1)} renvoie « A »

      • {#genre:subitems(0,2)} renvoie « A.B »

      • {#genre:subitems(1,0)} renvoie « B.C »

    • Supposons une colonne #genre contenant « A.B.C, D.E » :

      • {#genre:subitems(0,1)} renvoie « A, D »

      • {#genre:subitems(0,2)} renvoie « A.B, D.E »

  • sublist(start_index, end_index, separator) – interprète la valeur comme une liste d’éléments séparés par le separator, renvoyant une nouvelle liste composée des éléments de start_index à end_index. Le premier élément est le numéro zéro. Si un index est négatif, alors il compte à partir de la fin de la liste. Dans un cas spécial, un end_index de zéro est supposé être la longueur de la liste.

    Exemples en supposant que la colonne des étiquettes (qui est séparée par des virgules) contient « A, B ,C » :

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

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

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

  • swap_around_articles(separator) – renvoie la valeur avec les articles déplacés à la fin. La valeur peut être une liste, dans ce cas chaque article de la liste est traité. Si la valeur est une liste, vous devez fournir le séparateur. Si aucun séparateur n’est fourni, alors la valeur est traitée comme étant une valeur unique, et non une liste. Les articles sont ceux utilisés par calibre pour générer le title_sort.

  • swap_around_comma() – étant donné une valeur de la forme B, A, retourne A B. Ceci est très utile pour convertir des noms au format LN, FN en FN LN. S’il n’y a pas de virgule dans la valeur, la fonction retourne la valeur inchangée.

  • switch([pattern, value,]+ else_value) – pour chaque paire pattern, value, vérifie si la valeur correspond à l’expression régulière pattern et si oui, retourne la value associée. Si aucun pattern ne correspond, else_value est retourné. Vous pouvez avoir autant de couples pattern, value que vous le souhaitez. La première correspondance est retournée.

  • test(text if not empty, text if empty) – retourne text if not empty si la valeur n’est pas vide, sinon retourne text if empty.

  • titlecase() – renvoie la valeur du champ en casse titre.

  • transliterate() - Restitue une chaîne en alphabet latin représentant approximativement le son des mots de la chaîne source. Par exemple, si le champ source est Фёдор Миха́йлович Достоевский la fonction renverra Fiodor Mikhailovich Dostoievskii.”

  • uppercase() – renvoie la valeur du champ en majuscule.

Utilisation des fonctions et du formatage dans le même modèle

Supposons que vous ayez une colonne personnalisée de nombres entiers, ##myint, que vous voulez afficher avec des zéros en tête, comme dans 003. Une façon de le faire est d’utiliser le format 0>3s. Cependant, par défaut, si un nombre (entier ou flottant) est égal à zéro, la valeur est affichée sous la forme d’une chaîne vide, de sorte que les valeurs nulles produiront la chaîne vide, et non 000. Si vous voulez voir les valeurs 000, vous devez utiliser à la fois la chaîne de format et la fonction ifempty pour transformer la valeur vide en zéro. Le modèle serait

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

Notez que vous pouvez également utiliser le préfixe et le suffixe. Si vous voulez que le numéro apparaisse sous la forme [003] ou [000], utilisez alors le modèle

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

Mode Programme Général

Le Mode Programme Général (MPG) remplace les expressions modèles par un programme écrit dans le langage modèle. La syntaxe de ce langage est définie par la grammaire suivante

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 ]* | compare_exp
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 ')'
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 ]* ')'
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' identifier 'in' list_expr
                    [ 'separator' separator_expr ] ':' expression_list 'rof'
list_expr       ::= top_expression
break_expr      ::= 'break'
continue_expr   ::= 'continue'
separator_expr  ::= top_expression

Notes :

  • une top_expression a toujours une valeur. La valeur d’une expression_list est la valeur de la dernière top_expression Par exemple, la valeur de la liste d’expressions 1;2;'foobar';3 est 3.

  • Dans un contexte logique, toute valeur non vide est True.

  • Dans un contexte logique, la valeur vide est False.

  • Les chaînes de caractères et les nombres peuvent être utilisés indifféremment. Par exemple, 10 et '10' sont la même chose.

  • Les commentaires sont des lignes commençant par le caractère « # ». Les commentaires commençant plus loin dans une ligne ne sont pas pris en charge.

Préséance de l’opérateur

L’ordre de préséance de l’opérateurs (ordre d’évaluation), du plus élevé (évalué en premier) au plus bas (évalué en dernier), est le suivant :

  • Appels de fonctions, constantes, expressions entre parenthèses, expressions d’instructions, expressions d’affectation, références de champs.

  • Les opérateurs unaires plus (+) et moins (-). Ces opérateurs s’évaluent de droite à gauche.

    Ces opérateurs et tous les autres opérateurs arithmétiques renvoient des entiers si l’expression donne une partie fractionnaire égale à zéro. Par exemple, si une expression renvoie 3.0, elle est transformée en 3.

  • Multiplier (*) et diviser (/). Ces opérateurs sont associatifs et s’évaluent de gauche à droite. Utilisez les parenthèses si vous souhaitez modifier l’ordre d’évaluation.

  • Additionner (+) et soustraire (-). Ces opérateurs sont associatifs et s’évaluent de gauche à droite.

  • Comparaisons de nombres et de chaînes de caractères. Ces opérateurs renvoient '1' si la comparaison réussit, sinon la chaîne vide (''). Les comparaisons ne sont pas associatives : a < b < c est une erreur de syntaxe.

  • Unaire non logique (!). Cet opérateur renvoie '1' si l’expression est fausse (évaluée à la chaîne vide), sinon ''.

  • L’opérateur logique et (&&). Cet opérateur renvoie “1” si les deux expressions de gauche et de droite sont vraies, ou la chaîne vide '' si l’une ou l’autre est fausse. Il est associatif, s’évalue de gauche à droite, et fait du court-circuitage.

  • Logique ou (||). Cet opérateur renvoie '1' si l’expression de gauche ou de droite est vraie, ou '' si les deux sont fausses. Il est associatif, s’évalue de gauche à droite, et fait du court-circuitage. C’est un or inclusif, qui renvoie « 1 » si les deux expressions de gauche et de droite sont vraies.

Références des champs

Un « field_reference » est évalué à la valeur du champ de métadonnées nommé par le nom de la consultation qui suit le « $ » ou le « $$ ». L’utilisation de $ équivaut à l’utilisation de la fonction field(). L’utilisation de $$ équivaut à l’utilisation de la fonction raw_field. Exemples

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

Expressions if

Les expressions If évaluent d’abord la condition. Si la condition est True (une valeur non vide), alors expression_list de la clause then est évaluée. Si elle est False, expression_list de la clause elif ou else est évaluée si elle est présente. Les parties if et else sont facultatives. Les mots if ``, ``then, elif ``, ``else et fi sont réservés ; vous ne pouvez pas les utiliser comme noms d’identifiants. Vous pouvez mettre des retours à la ligne et des espaces partout où cela a un sens. La condition est une top_expression et non une expression_list ; les points-virgules ne sont pas autorisés. Les expression_list sont des séquences de top_expressions séparées par des points-virgules. Une expression if renvoie le résultat de la dernière top_expressions de la top_expression évaluée, ou la chaîne vide si aucune liste d’expression n’a été évaluée.

Exemples:

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

Exemple de if imbriqué:

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

Comme dit plus haut, un if produit une valeur. Cela signifie que tous les cas suivants sont équivalents

* 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

Comme dernier exemple, ce programme retourne la valeur de la colonne series si le livre a une série, sinon la valeur de la colonne title

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

Expressions for

L’expression for itère sur une liste de valeurs, en les traitant une par une. L’expression « list_expression » doit être évaluée soit par un nom de champ de métadonnées, par exemple tags ou #genre, soit par une liste de valeurs. Si le résultat est un lookup name valide, alors la valeur du champ est récupérée et le séparateur spécifié pour ce type de champ est utilisé. Si le résultat n’est pas un nom de référence valide, il est supposé être une liste de valeurs. La liste est supposée être séparée par des virgules, sauf si le mot-clé optionnel separator est fourni, auquel cas les valeurs de la liste doivent être séparées par le résultat de l’évaluation de l’expression separator_expr. Chaque valeur de la liste est assignée à la variable spécifiée puis la expression_list est évaluée. Vous pouvez utiliser break pour sortir de la boucle, et continue pour revenir au début de la boucle pour la prochaine itération.

Exemple : Ce modèle supprime le premier nom hiérarchique pour chaque valeur dans le genre (#genre), en construisant une liste avec les nouveaux noms

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

Si le Genre original est Histoire.Militaire, Science Fiction.Histoire alternative, Lisez-moi, alors le modèle renvoie Militaire, Histoire alternative, Lisez-moi. Vous pouvez utiliser ce modèle dans le calibre Modifier les métadonnées par lot  →  Rechercher & remplacer avec Rechercher après défini à modèe pour supprimer le premier niveau de la hiérarchie et attribuer la valeur résultante à Genre.

Note : la dernière ligne du modèle, new_tags, n’est pas strictement nécessaire dans ce cas car for renvoie la valeur de la dernière top_expression de la liste d’expressions. La valeur d’une affectation est la valeur de son expression, donc la valeur de l’instruction for est ce qui a été affecté à new_tags.

Opérateurs relationnels

Les opérateurs relationnels renvoient '1' si la comparaison est vraie, sinon la chaîne vide (“”).

Il existe deux formes d’opérateurs relationnels : les comparaisons de chaînes de caractères et les comparaisons numériques.

Les comparaisons de chaînes de caractères effectuent une comparaison insensible à la casse en utilisant l’ordre lexical. Les opérateurs de comparaison de chaînes de caractères pris en charge sont ==, !=, <, <=, >, >=, in, et inlist. Pour l’opérateur in, le résultat de l’expression de gauche est interprété comme un motif d’expression régulière. L’opérateur in est True si la valeur de l’expression régulière de gauche correspond à la valeur de l’expression de droite. L’opérateur inlist est vrai si l’expression régulière de gauche correspond à l’un des éléments de la liste de droite, les éléments de la liste étant séparés par des virgules. Les correspondances sont insensibles à la casse.

Les opérateurs de comparaison numérique sont ==#, !=#, <#, <=#, >#, >=#. Les expressions de gauche et de droite doivent être évaluées par des valeurs numériques, à deux exceptions près : la chaîne de caractères « None » (champ indéfini) et la chaîne de caractères vide sont évaluées par la valeur zéro.

Exemples :

  • program:field('series') == 'foo' renvoie '1' si la série du livre est “foo”, sinon ''.

  • Program: 'f.o' in field('series') renvoie “1”` si la série du livre correspond à l’expression régulière f.o (par exemple, foo, Off Onyx, etc.), sinon ''.

  • Program: 'science' inlist field('#genre') renvoie '1' si l’un des genres du livre correspond à l’expression régulière science, par exemple, Science, Histoire de la science, Science Fiction etc., sinon ''.

  • Program: '^science$' inlist field('#genre') renvoie “1”` si l’un des genres du livre correspond exactement à l’expression régulière ^science$, par exemple, Science. Les genres Histoire des sciences et Science Fiction ne correspondent pas. S’il n’y a pas de correspondance, elle renvoie ''.

  • Program: if field('series') != 'foo' then 'bar' else 'mumble' fi renvoie 'bar' si la série du livre n’est pas foo. Sinon, renvoie mumble.

  • Program: if field('series') == 'foo' || field('series') == '1632' then 'yes' else 'no' fi renvoie 'yes' si séries existe soit 'foo' soit '1632', sinon “no”`.

  • program: if '^(foo|1632)$' in field('series') then 'yes' else 'no' fi renvoie 'yes' si la série existe soit 'foo' ou '1632', sinon 'no'.

  • program: if '11' > '2' then 'yes' else 'no' fi renvoie `”no”`` parce que l’opérateur > fait une comparaison lexicale.

  • Program: if 11 ># 2 then 'yes' else 'no' fi renvoie 'yes' parce que l’opérateur ># effectue une comparaison numérique.

Fonctions supplémentaires disponibles

Les fonctions suivantes sont disponibles en plus de celles décrites dans Mode fonction unique.

Dans MPG, les fonctions décrites dans Mode Fonction Simple requièrent toutes un premier paramètre supplémentaire spécifiant la valeur sur laquelle opérer. Tous les paramètres sont des listes d’expressions (voir la grammaire ci-dessus).

  • add(x [, y]*) – renvoie la somme de ses arguments. Lance une exception si un argument n’est pas un nombre. Dans la plupart des cas, vous pouvez utiliser l’opérateur + à la place de cette fonction.

  • and(value [, value]*) – retourne la chaîne « 1 » si toutes les valeurs ne sont pas vides, sinon retourne la chaîne vide. Vous pouvez avoir autant de valeurs que vous le souhaitez. Dans la plupart des cas, vous pouvez utiliser l’opérateur && à la place de cette fonction. Une raison de ne pas remplacer and par && est que le court-circuitage peut modifier les résultats à cause d’effets secondaires. Par exemple, et(a='',b=5) fera toujours les deux affectations, alors que l’opérateur && ne fera pas la seconde.

  • assign(id, val) – affecte val à id, puis retourne val. id doit être un identifiant, pas une expression. Dans la plupart des cas, vous pouvez utiliser l’opérateur = à la place de cette fonction.

  • approximate_formats() – renvoie une liste, séparée par des virgules, des formats associés au livre. Il n’y a aucune garantie que la liste soit correcte, bien qu’elle le soit probablement. Cette fonction et d’autres fonctions à zéro paramètre peuvent être appelées en mode programme modèle (voir ci-dessous) en utilisant le modèle {:'approximate_formats()'}. Notez que les noms de formats résultants sont toujours en majuscules, comme dans EPUB. La fonction approximate_formats() est nettement plus rapide que les fonctions formats_... présentées ci-dessous.

  • author_links(val_separator, pair_separator) – renvoie une chaîne contenant une liste d’auteurs et les valeurs des liens de ces auteurs sous la forme

    author1 val_separator author1_link pair_separator author2 val_separator author2_link etc.
    

    Un auteur est séparé de sa valeur de lien par la chaîne val_separator sans espaces ajoutés. Les paires author:linkvalue sont séparées par la chaîne de caractères pair_separator, sans espaces ajoutés. C’est à vous de choisir des chaînes de séparation qui n’apparaissent pas dans les noms d’auteurs ou les liens. Un auteur est inclus même si le lien de l’auteur est vide.

  • author_sorts(val_separator) – renvoie une chaîne contenant une liste des valeurs de tri de l’auteur pour les auteurs du livre. Le tri est celui des métadonnées auteur (différente de l’author_sort dans les livres). La liste renvoyée a la forme author sort 1 val_separator author sort 2 etc. Les valeurs de tri auteur dans cette liste sont dans le même ordre que les auteurs du livre. Si vous voulez les espaces autour du val_separator incluez les alors dans la chaîne val_separator.

  • booksize() – renvoie la valeur du champ “size” de calibre. Renvoie “” s’il n’y a pas de formats.

  • check_yes_no(field_name, is_undefined, is_false, is_true) – vérifie si la valeur du champ oui/non nommé par le nom de la référence externe field_name est l’une des valeurs spécifiées par les paramètres, renvoyant 'yes' si une correspondance est trouvée sinon renvoyant la chaîne vide. Définissez le paramètre is_undefined, is_false ou is_true à 1 (le nombre) pour vérifier cette condition, sinon définissez-le à 0. Exemple :

    check_yes_no("#bool", 1, 0, 1) renvoie 'yes' si le champ oui/non #bool est soit Vrai, soit indéfini (ni Vrai, ni Faux).

    Plus d’un élément parmi  » is_undefined « ,  » is_false  » ou  » is_true  » peut être mis à 1.

  • ceiling(x) – renvoie le plus petit entier supérieur ou égal à x. Envoie une exception si x n’est pas un nombre.

  • character(character_name) – renvoie le caractère désigné par character_name. Par exemple, character('newline') renvoie un caractère de nouvelle ligne ('\n'). Les noms de caractères pris en charge sont newline, return, tab, et backslash.

  • cmp(x, y, lt, eq, gt) – compare x et y après les avoir convertis en nombres. Renvoie lt si x <# y, eq si x ==# y, sinon gt. Cette fonction peut généralement être remplacée par l’un des opérateurs de comparaison numérique (==#, <#, >#, etc).

  • connected_device_name(storage_location_key) – si un périphérique est connecté alors retourne le nom du périphérique, sinon retourne la chaîne vide. Chaque emplacement de stockage sur un périphérique peut avoir un nom différent. Les noms storage_location_key sont 'main', 'carda' et 'cardb'. Cette fonction ne fonctionne que dans l’interface graphique.

  • connected_device_uuid(storage_location_key) – si un périphérique est connecté alors retourne l’uuid du périphérique (id unique), sinon retourne la chaîne vide. Chaque emplacement de stockage sur un périphérique a un uuid différent. Les noms storage_location_key sont 'main', 'carda' et 'cardb'. Cette fonction ne fonctionne que dans l’interface graphique.

  • current_library_name() – renvoie le dernier nom sur le chemin de la bibliothèque calibre actuelle.

  • current_library_path() – renvoie le chemin complet vers la bibliothèque calibre actuelle.

  • date_arithmetic(date, calc_spec, fmt) – Calcule une nouvelle date à partir de date en utilisant calc_spec. Retourne la nouvelle date formatée selon l’option fmt : si elle n’est pas fournie, le résultat sera au format ISO. calc_spec est une chaîne de caractères formée par la concaténation de paires de vW (valueWhat) où v est un nombre éventuellement négatif et W est l’une des lettres suivantes :

    • s: ajoute v secondes à date

    • m: ajoute v minutes à date

    • h: ajoute v heures à date

    • d: ajoute v jours à date

    • w: ajoute v semaines à date

    • y: ajoute v années à date, où une année compte 365 jours.

    Exemple : '1s3d-1m' ajoutera 1 seconde, ajoutera 3 jours, et soustraira 1 minute de date.

  • days_between(date1, date2) – renvoie le nombre de jours entre date1 et date2. Le nombre est positif si date1 est plus grand que date2, sinon négatif. Si date1 ou date2 ne sont pas des dates, la fonction renvoie une chaîne vide.

  • divide(x, y) – renvoie x / y. Lance une exception si x ou y ne sont pas des nombres. Cette fonction peut généralement être remplacée par l’opérateur /.

  • eval(string) – évalue la chaîne comme un programme, en passant les variables locales. Cela permet d’utiliser le processeur de modèles pour construire des résultats complexes à partir de variables locales. En Mode Modèle de Programme, comme les caractères { et } sont interprétés avant l’évaluation du modèle, vous devez utiliser [[] pour le caractère { et ]] pour le caractère }. Ils sont convertis automatiquement. Notez également que les préfixes et les suffixes (la syntaxe |prefix|suffix) ne peuvent pas être utilisés dans l’argument de cette fonction lors de l’utilisation de Mode Modèle de Programme.

  • field(lookup_name) – renvoie la valeur du champ de métadonnées avec le nom de recherche lookup_name.

  • field_exists(field_name) – vérifie si un champ (colonne) avec le nom de recherche field_name existe, retournant “1”` si c’est le cas et la chaîne vide si non.

  • finish_formatting(val, fmt, prefix, suffix) – applique le format, le préfixe et le suffixe à une valeur de la même manière que dans un modèle comme {series_index:05.2f| - |- }. Cette fonction est fournie pour faciliter la conversion des modèles complexes single-function- ou modèles template-program-mode en modèles MGP. Par exemple, le programme suivant produit la même sortie que le modèle ci-dessus

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

    Un autre exemple: pour le modèle {series:re(([^\s])[^\s]+(\s|$),\1)}{series_index:0>2s| - | - }{title} utilisez:

    program:
      strcat(
        re(field('series'), '([^\s])[^\s]+(\s|$)', '\1'),
           finish_formatting(field('series_index'), '0>2s', ' - ', ' - '),
           field('title')
      )
    
  • first_matching_cmp(val, [ cmp, result, ]* else_result) – compare val < cmp en séquence, en retournant le résultat associé à la première comparaison qui réussit. Retourne else_result si aucune comparaison ne réussit. Exemple

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

    renvoie "grand". Le même exemple avec une première valeur de 16 renvoie "géant".

  • first_non_empty(value [, value]*) – retourne la première valeur non vide. Si toutes les valeurs sont vides, alors la chaîne vide est retournée. Vous pouvez avoir autant de valeurs que vous voulez.

  • floor(x) – renvoie le plus grand entier inférieur ou égal à x. Envoie une exception si x n’est pas un nombre.

  • format_date(val, format_string) – formate la valeur, qui doit être une chaîne date, en utilisant format_string, retournant une chaîne. Les codes de formatage sont:

    • d : le jour sous la forme d’un nombre sans zéro initial (1 à 31)

    • dd : le jour sous la forme d’un nombre avec un zéro initial (1 à 31)

    • ddd : le nom abrégé du jour localisé (par exemple de « Lun » à « Dim »).

    • dddd : le nom long du jour localisé (par exemple de « lundi » à « dimanche »).

    • M : le mois sous la forme d’un nombre sans zéro initial (1 à 12).

    • MM : le mois sous la forme d’un nombre avec un zéro initial (1 à 12).

    • MMM : le nom abrégé du mois localisé (par exemple de « Jan » à « Déc »).

    • MMMM : le nom long du mois localisé (par exemple de « janvier » à « décembre »).

    • yy : l’année sous la forme d’un nombre à deux chiffres (00 à 99).

    • yyyy : l’année sous la forme d’un nombre à quatre chiffres.

    • h : les heures sans le premier 0 (0 à 11 ou 0 à 23, selon am/pm)

    • hh : les heures avec le premier 0 (00 à 11 ou 00 à 23, selon am/pm)

    • m : les minutes sans le premier 0 (0 à 59)

    • mm : les minutes avec le premier 0 (00 à 59)

    • s : les secondes sans le premier 0 (0 à 59)

    • ss : les secondes avec un 0 en tête (00 à 59)

    • ap : utilise une horloge de 12 heures au lieu d’une horloge de 24 heures, avec “ap” remplacé par la chaîne localisée pour am ou pm.

    • AP : utilise une horloge de 12 heures au lieu d’une horloge de 24 heures, avec “AP” remplacé par la chaîne localisée pour AM ou PM.

    • iso : la date avec l’heure et le fuseau horaire. Ce doit être le seul format présent.

    • to_number : convertit la date et l’heure en un nombre à virgule flottante (un timestamp)

    • from_number : convertit un nombre à virgule flottante (un timestamp) en une date formatée iso. Si vous souhaitez un format de date différent, ajoutez la chaîne de formatage souhaitée après from_number et un deux-points (:). Exemple : from_number:MMM dd yyyy.

    Vous pouvez obtenir des résultats inattendus si la date que vous formatez contient des noms de mois localisés, ce qui peut se produire si vous avez modifié les ajustements de format de date pour qu’ils contiennent MMMM. Dans ce cas, au lieu d’utiliser la fonction field() comme dans

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

    utiliser la fonction raw_field() comme dans

    format_date(raw_field('pubdate'), 'yyyy')
    
  • formats_modtimes(date_format_string) – renvoie une liste séparée par des virgules d’éléments séparés par des deux points FMT:DATE représentant les heures de modification des formats d’un livre. Le paramètre date_format_string spécifie comment la date doit être formatée. Voir la fonction format_date() pour plus de détails. Vous pouvez utiliser la fonction select pour obtenir l’heure de modification d’un format spécifique. Notez que les noms de format sont toujours en majuscules, comme dans EPUB.

  • formats_paths() – retourne une liste d’éléments séparés par des virgules et des deux-points FMT:PATH donnant le chemin complet vers les formats d’un livre. Vous pouvez utiliser la fonction select pour obtenir le chemin d’accès à un format spécifique. Notez que les noms de format sont toujours en majuscules, comme dans EPUB.

  • formats_sizes() – renvoie une liste d’éléments FMT:SIZE séparés par des virgules, donnant les tailles en octets des formats d’un livre. Vous pouvez utiliser la fonction select pour obtenir la taille d’un format spécifique. Notez que les noms de format sont toujours en majuscules, comme dans EPUB.

  • fractional_part(x) – renvoie la valeur après la virgule. Par exemple, fractional_part(3.14) renvoie 0.14. Envoie une exception si x n’est pas un nombre.

  • has_cover() – retourne 'Yes' si le livre a une couverture, sinon la chaîne vide.

  • is_marked() – vérifie si le livre est marqué dans calibre. S’il l’est, retourne la valeur de la marque, soit true' (minuscule), soit une liste de marques nommées, séparées par des virgules.. Si le livre n’est pas marqué, retourne " (chaîne vide). Cette fonction ne fonctionne que dans l’interface graphique.

  • language_codes(lang_strings) – retourne les codes de langue pour les noms de langue passés dans lang_strings. Les chaînes de caractères doivent être dans la langue de la locale courante. Lang_strings est une liste séparée par des virgules.

  • list_contains(value, separator, [ pattern, found_val, ]* not_found_val) – (Alias de in_list) Interprétant la valeur comme une liste d’éléments séparés par le separator, évalue le pattern par rapport à chaque valeur de la liste. Si le pattern correspond à une valeur, il renvoie found_val, sinon il renvoie not_found_val. Le pattern et la found_value peuvent être répétés autant de fois que vous le souhaitez, ce qui permet de renvoyer différentes valeurs en fonction de la recherche. Les motifs sont vérifiés dans l’ordre. La première correspondance est retournée. Alias : in_list(), list_contains().

  • list_count(value, separator) – interprète value comme une liste d’éléments séparés par separator, et retourne le nombre d’éléments dans la liste. Alias : count(), list_count()

  • list_count_matching(list, pattern, separator) – interprète list comme une liste d’éléments séparés par separator, en retournant le nombre d’éléments dans la liste qui correspondent à l’expression régulière pattern. Alias : list_count_matching(), count_matching()

  • list_difference(list1, list2, separator) – restitue une liste en supprimant de list1 tout élément trouvé dans list2 ``en utilisant une comparaison insensible à la casse. Les éléments dans ``list1 et list2 sont séparés par le séparateur, comme le sont les éléments dans la liste restituée.

  • list_equals(list1, sep1, list2, sep2, yes_val, no_val) –retourne yes_val si list1 et list2 contiennent les mêmes éléments, sinon renvoie no_val. Les éléments sont déterminés en éclatant chaque liste à l’aide du séparateur approprié (sep1 ou sep2). L’ordre des éléments dans la liste n’est pas pris en compte. La comparaison est insensible à la casse.

  • list_intersection(list1, list2, separator) – retourne une liste faite en retirant de list1 tout élément non trouvé dans list2, en utilisant une comparaison insensible à la casse. Les éléments de list1 et list2 sont séparés par un séparateur, comme le sont les éléments de la liste retournée.

  • list_re(src_list, separator, include_re, opt_replace) – Construit une liste en séparant d’abord src_list en éléments en utilisant le caractère separator. Pour chaque élément de la liste, vérifiez s’il correspond à include_re. Si c’est le cas, ajoutez-le à la liste à retourner. Si opt_replace n’est pas une chaîne vide, il faut appliquer le remplacement avant d’ajouter l’élément à la liste retournée.

  • list_re_group(src_list, separator, include_re, search_re [, template_for_group]*) – Comme list_re sauf que les remplacements ne sont pas optionnels. Elle utilise re_group(item, search_re, template ...) pour effectuer les remplacements.

  • list_remove_duplicates(list, separator) – retourne une liste faite en supprimant les éléments en double dans list. Si les éléments ne diffèrent que par la casse, le dernier est retourné. Les éléments de list sont séparés par separator, comme le sont les éléments de la liste retournée.

  • list_sort(list, direction, separator) – retourne list triée en utilisant un tri lexical insensible à la casse. Si direction est zéro, list est triée de manière ascendante, sinon de manière descendante. Les éléments de la liste sont séparés par le separator, comme le sont les éléments de la liste retournée.

  • list_split(list_val, sep, id_prefix) – divise list_val en valeurs séparées en utilisant sep, puis affecte les valeurs à des variables locales nommées id_prefix_N où N est la position de la valeur dans la liste. Le premier élément a la position 0 (zéro). La fonction renvoie le dernier élément de la liste.

    Exemple:

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

    est équivalent à

    var_0 = 'one';
    var_1 = 'two';
    var_2 = 'foo
    
  • list_union(list1, list2, separator) – retourne une liste faite en fusionnant les éléments de list1 et list2, en supprimant les éléments en double en utilisant une comparaison insensible à la casse. Si les éléments diffèrent selon la casse, c’est celui de la « list1 » qui est utilisé. Les éléments de « list1 » et « list2 » sont séparés par un « separator », tout comme les éléments de la liste retournée. Alias : merge_lists(), list_union()

  • mod(x, y) – renvoie le floor du reste de x / y. Lance une exception si x ou y n’est pas un nombre.

  • multiply(x [, y]*) – renvoie le produit de ses arguments. Lance une exception si l’un des arguments n’est pas un nombre. Cette fonction peut généralement être remplacée par l’opérateur *.

  • not(valeur) – retourne la chaîne « 1 » si la valeur est vide, sinon retourne la chaîne vide. Cette fonction peut généralement être remplacée par l’opérateur unaire not (!).

  • ondevice() – retourne la chaîne Yes' si ondevice est défini, sinon retourne la chaîne vide.

  • or(value [, value]*) – retourne la chaîne '1' si une valeur n’est pas vide, sinon retourne la chaîne vide. Vous pouvez avoir autant de valeurs que vous le souhaitez. Cette fonction peut généralement être remplacée par l’opérateur ||. Une raison pour laquelle elle ne peut pas être remplacée est que le court-circuitage modifiera les résultats à cause d’effets secondaires.

  • print(a [, b]*) – imprime les arguments sur la sortie standard. A moins que vous ne lanciez calibre depuis la ligne de commande (calibre-debug -g), la sortie ira dans un trou noir. La fonction print retourne toujours la chaîne vide.

  • raw_field(lookup_name [, optional_default]) – renvoie le champ de métadonnées nommé par lookup_name sans appliquer de formatage. Il évalue et renvoie le second argument facultatif optional_default si la valeur du champ est indéfinie (None).

  • raw_list(lookup_name, separator) – renvoie la liste de métadonnées nommée par lookup_name sans appliquer de formatage ou de tri, avec les éléments séparés par le séparateur.

  • re_group(value, pattern [, template_for_group]*) – renvoie une chaîne faite en appliquant le motif de l’expression régulière à value et en remplaçant chaque instance trouvée par la valeur renvoyée par le modèle correspondant. En Mode Programme Modèle, comme pour les fonctions template et eval, vous utilisez [[` pour { et ]] pour }.

    L’exemple suivant recherche une série comportant plus d’un mot et met en majuscule le premier mot

    program: re_group(field('series'), "(\S* )(.*)", "{$:uppercase()}", "{$}")'}
    
  • round(x) – renvoie l’entier le plus proche de x. Envoie une exception si x n’est pas un nombre.

  • series_sort() – renvoie la valeur de tri des séries.

  • strcat(a [, b]*) – peut avoir n’importe quel nombre d’arguments. Renvoie une chaîne constituée par la concaténation de tous les arguments.

  • strcat_max(max, string1 [, prefix2, string2]*) – Renvoie une chaîne formée par la concaténation des arguments. La valeur retournée est initialisée à string1. Les chaînes formées à partir des paires prefix, string sont ajoutées à la fin de la valeur tant que la longueur de la chaîne résultante est inférieure à max. Les préfixes peuvent être vides. Retourne string1 même si string1 est plus long que max. Vous pouvez passer autant de paires prefix, string que vous le souhaitez.

  • strcmp(x, y, lt, eq, gt) – effectue une comparaison lexicale insensible à la casse de x et y. Elle retourne lt si x < y, eq si x == y, sinon gt. Cette fonction peut souvent être remplacée par l’un des opérateurs de comparaison lexicale (==, >, <, etc.).

  • strlen( value) – Retourne la longueur de la chaîne value.

  • substr(str, start, end) – renvoie les caractères de début jusqu’à fin de str. Le premier caractère dans str est le caractère zéro. Si end est négatif, cela indique que beaucoup de caractères sont comptés à partir de la droite. Si end est zéro, cela indique le dernier caractère. Par exemple, substr('12345', 1, 0) renvoie '2345', et substr('12345', 1, -1) renvoie '234'.

  • substract(x, y) – renvoie x / y. Lance une exception si x ou y ne sont pas des nombres. Cette fonction peut généralement être remplacée par l’opérateur -.

  • today() – retourne une chaîne date+heure pour aujourd’hui (now). Cette valeur est conçue pour être utilisée dans format_date ou days_between, mais peut être manipulée comme toute autre chaîne. La date est au format `ISO `_ date/heure.

  • template(x) – évalue x comme un modèle. L’évaluation est faite dans son propre contexte, ce qui signifie que les variables ne sont pas partagées entre l’appelant et l’évaluation du modèle.

Programmes plus complexes dans les expressions modèles - Mode Programme de Modèles

Le Mode Programme de Modèle (MPM) est un mélange du Mode de Programme Général et du Mode Fonction Unique. Le MPM diffère du Mode Fonction Unique en ce qu’il permet d’écrire des expressions de modèle qui font référence à d’autres champs de métadonnées, utilisent des fonctions imbriquées, modifient des variables et font de l’arithmétique. Il diffère du Mode Programme Général en ce que le modèle est contenu entre les caractères {` et } et ne commence pas par le mot program:. La partie programme du modèle est une liste d’expressions du Mode Programme Général.

Exemple : supposons que vous vouliez qu’un modèle affiche la série d’un livre s’il en a une, sinon la valeur d’un champ personnalisé #genre. Vous ne pouvez pas faire cela dans le mode Mode Fonction Unique car vous ne pouvez pas faire référence à un autre champ de métadonnées dans une expression de modèle. En MPM, vous le pouvez, comme le montre l’expression suivante

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

L’exemple montre plusieurs choses :

  • MPM est utilisé si l’expression commence par :' et se termine par '. Tout le reste est supposé être en :ref:Mode Fonction Unique.

  • la variable $ représente le champ nommé dans le modèle : l’expression sur laquelle on opère, #series dans ce cas.

  • les fonctions doivent être données avec tous leurs arguments. Il n’y a pas de valeur par défaut. Par exemple, les fonctions intégrées standard doivent recevoir un paramètre initial supplémentaire indiquant le champ source.

  • les espaces sont ignorés et peuvent être utlisés n’importe où dans l’expression.

  • les chaînes constantes sont entre guillemets, soit ' ou ".

Toutes les fonctions listées dans les rubriques Mode Fonction Unique et Mode Programme Général peuvent être utilisées dans le MPM.

En MPM, l’utilisation des caractères {` et } dans les chaînes de caractères peut conduire à des erreurs ou des résultats inattendus parce qu’ils confondent le processeur de modèle. Il essaie de les traiter comme des limites d’expression de modèle et non comme des caractères. Dans certains cas, mais pas dans tous, vous pouvez remplacer un { par [[ et un } par ]]. En général, si votre programme contient des caractères { et }, vous devriez utiliser le Mode Programme Général.

Comme pour le Mode Général de Programme, pour les fonctions documentées sous Mode Fonction Unique, vous devez fournir la valeur sur laquelle la fonction doit agir comme premier paramètre en plus des paramètres documentés. En MPM, vous pouvez utiliser $ pour accéder à la valeur spécifiée par le lookup name de l’expression modèle.

Modèles de mode de programme général stockés

Mode Programme Général permet d’enregistrer des modèles et de les appeler à partir d’un autre modèle, tout comme l’appel de fonctions stockées. Vous enregistrez les modèles en utilisant Préférences → Avancé → Modèles de fonctions. Plus d’informations sont fournies dans cette boite de dialogue. Vous appelez un modèle de la même manière que vous appelez une fonction, en passant des arguments de position si vous le souhaitez. Un argument peut être n’importe quelle expression. Exemples d’appel d’un modèle, en supposant que le modèle stocké est nommé foo :

  • foo() – appelle le modèle en ne passant aucun argument.

  • foo(a, b) appelle le modèle en passant les valeurs des deux variables a et b.

  • foo(if field('series') then field('series_index') else 0 fi) – si le livre a series alors passez le series_index, sinon passez la valeur 0.

Vous récupérez les arguments passés dans l’appel au modèle stocké en utilisant la fonction arguments. Elle déclare et initialise les variables locales, en fait des paramètres. Les variables sont positionnelles ; elles obtiennent la valeur de la valeur donnée dans l’appel dans la même position. Si le paramètre correspondant n’est pas fourni dans l’appel, alors la fonction arguments attribue à cette variable la valeur par défaut fournie. S’il n’y a pas de valeur par défaut, alors la variable est fixée à la chaîne vide. Par exemple, la fonction « arguments » suivante déclare 2 variables, key, alternate:

arguments(key, alternate='series')

Par exemple, en supposant encore une fois que le modèle stocké est nommé foo :

  • foo('#myseries') – l’argument key se voit attribuer la valeur myseries' et l’argument alternate se voit attribuer la valeur par défaut 'series'.

  • foo('series', '#genre') la variable key prend la valeur 'series' et la variable alternate prend la valeur '#genre'.

  • foo() – la variable key se voit attribuer la chaîne vide et la variable alternate se voit attribuer la valeur 'series'.

Une façon simple de tester les modèles stockés est d’utiliser le dialogue « Testeur de modèle ». Pour faciliter l’accès, donnez-lui un raccourci clavier dans Préférences → Avancé → Raccourcis clavier → Tester le modèle`. Donner un raccourci au dialogue Modèles stockés aidera à passer plus rapidement du testeur à l’édition du code source du modèle stocké.

Fournir des informations supplémentaires aux modèles

Un développeur peut choisir de transmettre des informations supplémentaires au processeur du modèle, telles que des métadonnées de livre spécifiques à l’application ou des informations sur ce qui est demandé au processeur. Un modèle peut accéder à ces informations et les utiliser pendant l’évaluation.

Développeur : comment transmettre des informations supplémentaires

L’information supplémentaire est un dictionnaire Python contenant les paires variable_name: variable_value où les valeurs devraient être des chaînes de caractères. Le modèle peut accéder au dict, en créant des variables locales de modèle nommées variable_name contenant la valeur variable_value. L’utilisateur ne peut pas changer le nom, il est donc préférable d’utiliser des noms qui n’entreront pas en collision avec d’autres variables locales du modèle, par exemple en préfixant le nom par un trait de soulignement.

Ce dict est passé au processeur de modèle (le « formatter ») en utilisant le paramètre nommé « global_vars=your_dict ». La signature complète de la méthode est

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

Rédacteur de modèles : comment accéder aux informations complémentaires

Vous accédez aux informations supplémentaires (le dict « globals ») dans un modèle en utilisant la fonction template

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

id est un nom de variable légale quelconque. Cette fonction vérifie si les informations supplémentaires fournies par le développeur contiennent le nom. Si c’est le cas, la fonction attribue la valeur fournie à une variable locale modèle avec ce nom. Si le nom ne figure pas dans les informations supplémentaires et si une « expression » est fournie, cette « expression » est évaluée et le résultat est attribué à la variable locale. Si ni une valeur ni une expression n’est fournie, la fonction attribue la chaîne vide ('') à la variable locale.

Un modèle peut définir une valeur dans le dict « globals » en utilisant la fonction modèle

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

Cette fonction définit la paire key:value globals dict id:valuevalue est la valeur de la variable locale id du modèle. Si cette variable locale n’existe pas, alors value est définie comme le résultat de l’évaluation de expression.

Notes sur la différence entre les modes

Les trois modes de programmation, Mode Fonction Simple (MFS), Mode Modèle de Programmation (MMP), et Mode Général de Programmation (MGP), fonctionnent différemment. Le MFS est destiné à être “simple” et cache donc beaucoup de bits de langage de programmation.

Différences :

  • Dans MFS, la valeur de la colonne est toujours passée comme premier argument “invisible” à une fonction incluse dans le modèle.

  • Le MFS ne supporte pas la différence entre les variables et les chaînes de caractères ; toutes les valeurs sont des chaînes de caractères.

  • Le modèle SFM suivant renvoie soit le nom de la série, soit la chaîne « pas de série »

    {series:ifempty(no series)}
    

    Le modèle équivalent dans MPM est

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

    Le modèle équivalent dans MGP est

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

    Le premier argument de ifempty est la valeur du champ série. Le second argument est la chaîne no series. Dans SFM, le premier argument, la valeur du champ, est automatiquement passé (l’argument invisible).

  • Plusieurs fonctions du modèle, par exemple booksize() et current_library_name(), ne prennent aucun argument. En raison de l“« argument invisible », vous ne pouvez pas utiliser ces fonctions dans SFM.

  • Les fonctions imbriquées, où une fonction appelle une autre fonction pour calculer un argument, ne peuvent pas être utilisées dans SFM. Par exemple, ce modèle, destiné à renvoyer les 5 premiers caractères de la valeur de la série en majuscules, ne fonctionnera pas dans SFM

    {series:uppercase(substr(0,5))}
    
  • MPM et MPG soutiennent des fonctions imbriquées. Le modèle ci-dessus dans MPM serait

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

    Dans MPG, ce serait

    program: uppercase(substr(field('series'), 0,5))
    
  • Comme indiqué dans la section Mode de Programmation des Modèles ci-dessus, l’utilisation des caractères { et } dans les chaînes de caractères MPM peut conduire à des erreurs ou à des résultats inattendus car ils perturbent le processeur de modèles. Il essaie de les traiter comme des limites de modèles et non comme des caractères. Dans certains cas, mais pas dans tous, vous pouvez remplacer un { par [[ et un } par ]]`. En général, si votre programme contient des caractères ``{ et }, vous devriez utiliser le Mode Général de Programmation.

Fonctions des modèles Python définis par l’utilisateur

Vous pouvez ajouter vos propres fonctions Python au processeur de modèles. Ces fonctions peuvent être utilisées dans l’un des trois modes de programmation du modèle. Les fonctions sont ajoutées en allant dans Préférences  →  Avancé  →  Fonctions de modèle. Les instructions sont affichées dans cette boite de dialogue.

Notes spéciales pour la sauvergarde/l’envoi des modèles

Un traitement spécial est appliqué quand un modèle est utilisé dans un modèle Enregistrer sur le disque ou Envoyer au périphérique. Les valeurs des champs sont nettoyées, les caractères qui sont propres aux systèmes de fichiers sont remplacées par des traits de soulignement, y compris les barres obliques. Cela signifie que le texte d’un champ ne peut pas être utilisé pour créer des dossiers. Toutefois, les barres obliques ne sont pas modifiés dans des chaînes préfixe ou suffixe. Vous pouvez donc insérer des barres obliques qui et provoquer ainsi la création de dossiers. Ainsi, vous pouvez créer une structure de dossier avec des profondeurs variables.

Par exemple, supposons que nous voulons que la structure des dossiers soit series/series_index - titre, en prévoyant que si la série n’existe pas, alors le titre devrait être dans le dossier racine (le premier dossier, pas le sous-dossier). Le modèle pour faire cela est :

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

La barre oblique et le trait d’union apparaissent uniquement si la série n’est pas vide.

La fonction de recherche nous permet de faire le traitement encore plus poussé. Par exemple, supposons que si un livre est dans une série, alors nous voulons que la structure soit la suivante : series/series index - title.fmt.. Si le livre n’est pas dans une série, alors nous voulons que la structure des dossiers soit genre/author_sort/title.fmt. Si le livre n’a pas de genre, alors nous voulons utiliser “Inconnu”. Nous voulons deux chemins de répertoire totalement différents en fonction de la valeur de la série.

Pour accomplir cela, nous :

  1. Créer un champ composite (donner-lui le nom de recherche #aa) contenant {series}/{series_index} - {titre}. Si la série n’est pas vide, alors ce modèle produira series/series_index - titre.

  2. Créons une champ composite (appelons-le #bb) contenant {#genre:ifempty(Unknown)}/{author_sort}/{title}. Ce modèle produit genre/author_sort/title, où un genre vide est remplacé par Inconnu.

  3. Paramétrez le modèle de sauvegarde à {series:lookup(.,#aa,#bb)}. Ce modèle choisit le champ composite #aa si série n’est pas vide, et le champ composite #bb si série est vide. Nous avons dès lors deux chemins de sauvegarde complètement différents, dépendant du fait que series soit vide ou pas.

Modèles et tableaux de connexions

Les tableaux de connexions sont utilisés pour modifier les métadonnées écrites dans les livres pendant l’envoi à une liseuse et les opérations de sauvegarde sur le disque. Le tableau de connexion vous permet de spécifier pour un modèle de lecteur précis quelles données à insérer dans les métadonnées du livre. Vous pouvez utiliser les tableaux de connexions pour modifier les champs suivants : authors, author_sort, language, publisher, tags, title, title_sort. Cette fonctionnalité aide ceux qui veulent utiliser les différentes métadonnées des livres pour contrôler le tri ou l’affichage des livres sur leurs périphériques.

Lorsque vous créez un tableau de connexion, vous spécifiez le format et le périphérique pour lequel le tableau de connexion doit être utilisé. Un périphérique spécial est procuré, save_to_disk qui est utilisé lors de la sauvegarde de formats (en opposition à les envoyer vers le périphérique). Une fois que vous avez choisi le format et le périphérique, vous choisissez les champs de métadonnées à modifier, indiquez le modèle à appliquer pour fournir les nouvelles valeurs. Ces modèles sont reliés à leurs champs de destination, d’où le nom de tableau de connexions. Vous pouvez bien sûr utiliser des colonnes composites dans ces modèles.

Quand un tableau de connexion doit s’appliquer (Serveur de contenu, sauvegarde sur disque ou envoyer au périphérique), calibre recherche les tableau de connexions définis et celui qui est correct pour le format donné et le périphérique. Par exemple, pour trouver le tableau de connexion approprié pour un livre EPUB envoyé à un périphérique ANDROID, calibre recherche dans les tableaux de connexion dans l’ordre de recherche suivant :

  • un tableau de connexion avec une correspondance exacte sur le format et le périphérique, par ex., EPUB et ANDROID

  • un tableau de connexion avec une correspondance exacte sur le format et le choix spécial n'importe quel périphérique, par ex., EPUB et n'importe quel périphérique

  • un tableau de connexion avec le choix spécial n'importe quel format et une correspondance exacte sur le périphérique, par ex., n'importe quel format et ANDROID

  • un tableau de conversion avec n'importe quel format et n'importe quel périphérique

Les étiquettes et les champs auteur ont un traitement spécial, parce que ces deux champs peuvent contenir plusieurs données. Un livre peut avoir plusieurs étiquettes et plusieurs auteurs. Lorsque vous spécifiez que l’un de ces deux champs doit être modifié, le résultat du modèle est examiné pour voir s’il y a plus d’un élément dedans. Pour les étiquettes, le résultat est découpé partout où calibre trouve une virgule. Par exemple, si le modèle produit les valeurs Thriller, Horreur, alors ke résultat sera deux étiquettes, Thriller et Horreur. Il n’est pas possible de mettre une virgule au milieu d’une étiquette.

La même chose se produit pour les auteurs, mais en utilisant un caractère différent comme séparateur, le & (esperluette) au lieu d’une virgule. Par exemple, si le modèle produit la valeur Blogs, Joe&Posts, Susan, alors le livre finira avec deux auteurs Blogs, Joe et Posts, Susan. Si le modèle produit la valeur Blogs, Joe;Posts, Susan, alors ce livre aura un auteur avec un nom assez étrange.

Les tableaux de connexions affectent les métadonnées écrites dans le livre quand il est sauvegardé sur le disque ou copié sur le périphérique. Les tableaux de connexions n’affecte pas les métadonnées utilisées par Enregistrer sur le disque et Envoyer au périphérique. A la place, les noms de fichiers sont construits en utilisant les modèles entrés dans la fenêtre de préférence appropriée.

Astuces :

  • Utilisez le Testeur de Modèles pour tester les modèles. Ajoutez le testeur au menu contextuel des livres de la bibliothèque et/ou donnez-lui un raccourci clavier.

  • Les modèles peuvent utiliser d’autres modèles en faisant référence à des colonnes composites construites avec le modèle souhaité. Vous pouvez également utiliser des Modèles Stockés comme alternative.

  • Dans un tableau de connexions, vous pouvez paramétrer un champ à vide (ou quelque soit sont équivalent à vide) en utilisant le modèle spécial {}. Ce modèle sera toujours évalué à une chaîne vide.

  • La technique indiquée ci-dessus pour montrer les nombre même s’ils ont une valeur zéro fonctionne avec le champ standard series_index.

Référence de la fonction