El lenguaje de plantillas de calibre

El lenguaje de plantillas de calibre se usa en varios lugares. Se usa para controlar la estructura de carpetas y el nombre del archivo cuando se guardan archivos de la biblioteca de calibre en el disco o en un lector. También se usa para definir columnas «virtuales» que contienen datos de otras columnas, etcétera.

El lenguaje de plantillas básico es muy simple pero también tiene características avanzadas muy potentes. La idea básica es que una plantilla consiste en texto y nombres entre llaves que se sustituyen por los metadatos correspondientes del libro que está siendo procesado. Así, por ejemplo, la plantilla predeterminada usada para guardar libros en un dispositivo en calibre es:

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

Para el libro «La Fundación» de «Isaac Asimov» da lugar a:

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

Las barras son texto que se ponen en la plantilla donde van a aparecer. Por ejemplo, si la plantilla es:

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

Para el libro «La Fundación» de «Isaac Asimov» da lugar a:

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

Puede usar los distintos campos de metadatos disponibles en calibre en una plantilla, incluidas las columnas personalizadas que haya creado. Para obtener el nombre de plantilla de una columna, pase el cursor sobre el encabezado de la columna. Los nombre para los campos personalizados (columnas que haya creado usted) siempre empiezan por #. Para campos personalizados de tipo serie, siempre hay un campo adicional llamado #nombredeserie_index que es el índice de serie para dicha serie. Así, si tiene un campo personalizado de serie llamado #miserie, también habrá un campo llamado #miserie_index.

Además de los campos basados en columnas, también puede usar:

{formats} - A list of formats available in the calibre library for a book
{identifiers:select(isbn)} - The ISBN of the book

Si un libro concreto no tiene un determinado metadato, el campo se elimina automáticamente de la plantilla para este libro. Considere, por ejemplo:

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

Si un libro tiene una serie, la plantilla producirá:

Asimov, Isaac/Foundation/Second Foundation 3

y si un libro no pertenece a una serie:

Asimov, Isaac/Second Foundation

(calibre elimina automáticamente barras múltiples y espacios iniciales o finales).

Formato avanzado

Puede hacerse más que simples sustituciones con las plantillas. Se puede incluir texto de manera condicional y controlar el formato de los datos sustituidos.

Primero, incluir texto condicionalmente. Hay casos en los que puede querer que aparezca un texto en la salida sólo si un campo no está vacío. Un caso común es series y series_index, para los que puede querer o nada o ambos valores con un guión entre ellos. calibre tiene en cuenta este caso usando una sintaxis de campo especial.

Por ejemplo, supongamos que desea usar la plantilla:

{series} - {series_index} - {title}

Si el libro no tiene serie, la respuesta será - - title. Mucha gente preferiría que el resultado fuera simplemente title, sin los guiones. Para conseguir esto, use la sintaxis extendida {campo:|prefijo|sufijo}. Cuando usa esta sintaxis, si el campo tiene el valor SERIE el resultado será prefijoSERIEsufijo. Si el campo no tiene ningún valor, el resultado será un texto vacío (nada); el prefijo y el sufijo se descartan. El prefijo y el sufijo pueden contener espacios. No use subplantillas (`{ … }`) ni funciones (ver más adelante) como prefijo o sufijo.

Usando esta sintaxis, podemos resolver el problema anterior de las series con esta plantilla:

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

Los guiones se incluirán solamente si el libro tiene índice de serie, que sólo tendrá si tiene una serie.

Notas: debe incluir el carácter : si quiere usar un prefijo o un sufijo. Debe usar ambos caracteres | o ninguno; usar sólo no, como en {campo:| - }, no está permitido. Es posible especificar un texto vacío en uno u otro lugar, como en {series:|| - }. Usar {title:||} es lo mismo que usar {title}.

Segundo: formato. Supongamos que queremos asegurarnos de que series_index siempre tenga tres dígitos, con ceros a la izquierda. Se conseguiría de esta manera:

{series_index:0>3s} - Three digits with leading zeros

Si en lugar de ceros a la izquierda desea espacios, utilice:

{series_index:>3s} - Three digits with leading spaces

Para obtener ceros a la derecha use:

{series_index:0<3s} - Three digits with trailing zeros

Si usa índices de serie con subvalores (por ejemplo 1,1), puede querer asegurarse de que los decimales quedan alineados. Por ejemplo, puede que los índices 1 y 2,5 aparezcan como 01,00 y 02,50 para que se ordenen correctamente. Para ello, use:

{series_index:0>5.2f} - Five characters, consisting of two digits with leading zeros, a decimal point, then 2 digits after the decimal point

Si quiere sólo las dos primeras letras de los datos, use:

{author_sort:.2} - Only the first two letter of the author sort name

El lenguaje de plantillas de calibre proviene de Python, para obtener más detalles sobre la sintaxis de estas operaciones de formato avanzadas, vea la documentación de Python (en inglés).

Funciones avanzadas

Usar plantillas en columnas personalizadas

A veces hay casos en los que quiere mostrar metadatos que calibre no muestra normalmente, o mostrarlos de una manera diferente. Por ejemplo, puede querer mostrar el ISBN, un campo que calibre no muestra. Puede usar columnas personalizadas para esto creando una columna de tipo «columna generada a partir de otras columnas» (en lo sucesivo llamadas columnas compuestas), e introduciendo una plantilla. calibre mostrará una columna con el resultado de evaluar la plantilla. Para mostrar el ISBN, cree la columna e introduzca {identifiers:select(isbn)} en el cuadro de plantilla. Para mostrar una columna que contenga los valores de dos campos personalizados de serie separados por una coma, use {#serie1:||,}{#serie2}.

Las columnas compuestas pueden utilizar cualquier opción de plantilla, incluidas las de formato.

No puede cambiar los datos contenidos en una columna compuesta. Si modifica una columna compuesta pulsando dos veces sobre un elemento, se abrirá la plantilla para modificarla, no los datos resultantes. Modificar la plantilla en la interfaz gráfica es una manera rápida de probar y modificar columnas compuestas.

Usar funciones en plantillas: modo de función única

Supongamos que desea mostrar el valor de un campo en mayúsculas, aunque normalmente el valor del campo tiene sólo las iniciales en mayúscula. Puede conseguir esto (y muchas otras cosas) usando las funciones disponibles para plantillas. Por ejemplo, para mostrar el título en mayúsculas use {title:uppercase()}. Para mostrarlo con las iniciales en mayúscula use {title:titlecase()}.

Las referencias a funciones aparecen en la parte del formato, después de : y antes del primer | o del } de cierre. Si tiene tanto un formato como una referencia de función, la función después de otro :. Las funciones siempre deben acabar con (). Algunas funciones toman valores adicionales (argumentos), y éstos van dentro de los ().

Las funciones siempre se aplican antes de las especificaciones de formato. Véase más abajo un ejemplo de cómo usar un formato y una función, donde se demuestra este orden.

La sintaxis para usar funciones es {campo:función(argumentos)} o {campo:función(argumentos)|prefijo|sufijo}. Los argumentos van separados por comas. Las comas dentro de los argumentos deben ir precedidas por una barra invertida ( \\ ). El último (o único) argumento no puede contener un paréntesis de cierre ( ) ). Las funciones devuelven el valor del campo usado en la plantilla, convenientemente modificado.

Importante: Si tiene experiencia en programación, tenga en cuenta que la sintaxis de este modo (de función única) no es la que podría esperarse. Los textos van sin comillas. Los espacios son importantes. Todos los argumentos deben ser constantes; no hay evaluación interna. No use subplantillas (``{…}``) como argumentos de función. En lugar de ello, use el modo de programación de plantilla y el modo de programación general.

Muchas funciones usan expresiones regulares. En todos los casos, la expresión regular no distingue entre mayúsculas y minúsculas.

Las funciones disponibles se enumeran a continuación. Tenga en cuenta que la documentación definitiva para las funciones está disponibles en la sección Clasificación de funciones:

  • lowercase() – devuelve el valor del campo en minúsculas.

  • uppercase() – devuelve el valor del campo en mayúsculas.

  • titlecase() – devuelve el valor del campo con las iniciales en mayúscula.

  • capitalize() – devuelve el valor con la primera letra mayúscula y el resto en minúsculas.

  • contains(patrón, texto_si_coincide, texto_si_no_coincide) – comprueba si el campo contiene coincidencias para la expresión regular patrón. Devuelve texto_si_coincide si se encuentran coincidencias, en caso contrario devuelve texto_si_no_coincide.

  • count(separador) – interpreta el valor como una lista de elementos separados por ­separador y devuelve el número de elementos de la lista. La mayoría de las listas usan una coma como separador, pero «authors» usa un ampersand («&»). Ejemplos: {tags:count(,)}, {authors,count(&)}

  • format_number(template) – interprets the field as a number and format that number using a Python formatting template such as «{0:5.2f}» or «{0:,d}» or «${0:5,.2f}». The field_name part of the template must be a 0 (zero) (the «{0:» in the above examples). You can leave off the leading «{0:» and trailing «}» if the template contains only a format. See the template language and Python documentation for more examples. Returns the empty string if formatting fails.

  • human_readable() – espera que el valor sea un número y devuelve un texto que representa ese número en KB, MB, GB, etc.

  • ifempty(texto) – si el campo no está vacío, devuelve el valor del campo. En caso contrario devuelve texto.

  • in_list(separator, pattern, found_val, ..., not_found_val) – interpret the field as a list of items separated by separator, evaluating the pattern against each value in the list. If the pattern matches a value, return found_val, otherwise return not_found_val. The pattern and found_value can be repeated as many times as desired, permitting returning different values depending on the search. The patterns are checked in order. The first match is returned.

  • language_codes(nombres) – devuelve los códigos de idioma correspondientes a «nombres». Los nombres deben estar en el idioma actual. El argumento «nombres» es una lista separada por comas.

  • language_strings(códigos, localizar) – devuelve los nombres de los idiomas identificados por códigos. Si localizar es cero, devuelve los nombres en inglés. Si localizar no es cero, devuelve los nombres en el idioma actual. El argumento códigos es una lista separada por comas.

  • list_item(índice, separador) – interpreta el campo como una lista de elementos separados por «separador» y devuelve el elemento número «índice». El primer elemento es el número cero. El último elemento puede obtenerse con list_item(-1, separador). Si el elemento no está en la lista devuelve un valor vacío. El separador tiene el mismo significado que en la función «count».

  • lookup(patrón, campo, patrón, campo, ..., otro_campo) – como switch, pero los argumentos son nombres de campo (metadatos), no texto. Se usará el valor del campo apropiado. Tenga en cuenta que puesto que las columnas compuestas son campos, puede usar esta función en un campo compuesto para usar el valor de otro campo compuesto. Esto es muy útil para construir rutas de guardado variables (más sobre esto más adelante).

  • re(patrón, sustitución) – devuelve el campo después de aplicar la expresión regular. Todas las veces que aparezca patrón se sustituirá por sustitución. Como en todo calibre, se trata de expresiones regulares compatibles con Python.

  • select(clave) – interpreta el campo como una lista de elementos separados por comas, con los elementos de la forma «id:valor». Encuentra la pareja con «id» igual a «clave» y devuelve el valor correspondiente. Esta función es particularmente útil para extraer un valor tal como el isbn del conjunto de identificadores de un libro.

  • shorten(car_izq, texto_medio, car_der) – devuelve una versión abreviada del campo, consistente en un número car_izq de caracteres del principio del campo, seguidos de texto_medio, seguido de un número car_der de caracteres del final del campo. car_izq y car_der deben ser números enteros. Por ejemplo, supongamos que el título del libro es «Novísima recopilación de las leyes de España» y que quiere que quepa en un espacio de 15 caracteres a lo sumo. Si usa {title:shorten(9,-,5)}, el resultado será «Novísima -spaña». Si la longitud del campo es menor que car_izq + car_der + la longitud de texto_medio, se usará el campo intacto. Por ejemplo, el título «La colmena» no se cambiará.

  • str_in_list(separator, string, found_val, ..., not_found_val) – interpret the field as a list of items separated by separator, comparing the string against each value in the list. If the string matches a value (ignoring case), return found_val, otherwise return not_found_val. If the string contains separators, then it is also treated as a list and each value is checked. The string and found_value can be repeated as many times as desired, permitting returning different values depending on the search. The strings are checked in order. The first match is returned.

  • subitems(start_index, end_index) – This function is used to break apart lists of tag-like hierarchical items such as genres. It interprets the field as a comma-separated list of tag-like items, where each item is a period-separated list. Returns a new list made by first finding all the period-separated tag-like items, then for each such item extracting the components from start_index to end_index, then combining the results back together. The first component in a period-separated list has an index of zero. If an index is negative, then it counts from the end of the list. As a special case, an end_index of zero is assumed to be the length of the list. Examples:

    Assuming a #genre column containing "A.B.C":
        {#genre:subitems(0,1)} returns "A"
        {#genre:subitems(0,2)} returns "A.B"
        {#genre:subitems(1,0)} returns "B.C"
    Assuming a #genre column containing "A.B.C, D.E":
        {#genre:subitems(0,1)} returns "A, D"
        {#genre:subitems(0,2)} returns "A.B, D.E"
    
  • sublist(start_index, end_index, separator) – interpret the field as a list of items separated by separator, returning a new list made from the items from start_index to end_index. The first item is number zero. If an index is negative, then it counts from the end of the list. As a special case, an end_index of zero is assumed to be the length of the list. Examples assuming that the tags column (which is comma-separated) contains «A, B ,C»:

    {tags:sublist(0,1,\,)} returns "A"
    {tags:sublist(-1,0,\,)} returns "C"
    {tags:sublist(0,-1,\,)} returns "A, B"
    
  • swap_around_comma() – given a field with a value of the form B, A, return A B. This is most useful for converting names in LN, FN format to FN LN. If there is no comma, the function returns val unchanged.

  • switch(patrón, valor, patrón, valor, ..., otro_valor) – para cada pareja patrón, valor, comprueba si el campo contiene coincidencias para la expresión regular patrón y, en tal caso, devuelve ese valor. Si no coincide ningún patrón, devuelve otro_valor. Pueden emplearse tantas parejas patrón, valor como se desee.

  • test(texto_si_no_vacío, texto_si_vacío) – devuelve texto_si_no_vacío si el campo no está vacío, devuelve texto_si_vacío en caso contrario.

  • transliterate() – Devuelve un texto en el alfabeto latino formado por aproximación del sonido de las palabras en el campo de origen. Por ejemplo, si el campo de origen es «Фёдор Миха́йлович Достоевский» la función devuelve «Fiodor Mikhailovich Dostoievskii».

Veamos ahora cómo usar funciones y format en el mismo campo. Supongamos que tiene una columna personalizada con números enteros llamada #myint, que quiere mostrar con ceros a la izquierda, como en «003». Para conseguirlo usaría un formato de 0>3s. Sin embargo, de manera predeterminada, si un número (entero o decimal) es igual a cero, el campo produce un valor vacío, así que el valor cero no produce nada, no «000». Si realmente quiere ver los valores como «000», debe usar el texto de formato y la función ifempty para cambiar el valor vacío a cero de nuevo, la referencia al campo sería:

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

Tenga en cuenta que puede usar también prefijo y sufijo. Si desea que el número aparezca como [003] o [000], use el campo:

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

Usar funciones en plantillas: modo de programación de plantilla

El modo de programación de lenguaje de plantillas se diferencia del modo de función única en que le permite escribir expresiones de plantilla que se refieren a otros campos de metadatos, modifican valores y realizan operaciones aritméticas. Es un lenguaje de programación razonablemente completo.

Puede usar las funciones documentadas anteriormente en modo de programación de plantilla. Véase más adelante para más detalles.

Para empezar con un ejemplo, supongamos que quiere una plantilla que muestre la serie de un libro si la tiene, y en caso contrario muestre el valor del campo personalizado «#genre». Esto no se puede hacer en el modo básico, porque no se puede hacer referencia a otro campo en la expresión de la plantilla. En el modo de programación sí se puede. La siguiente expresión funciona:

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

El ejemplo muestra varias cosas:

  • el modo de programa se usa si la expresión empieza por :' y termina por '. Cualquier otra cosa se supone que es una sola función.
  • la variable $ representa el campo sobre el que opera la expresión, #series en este caso.
  • las funciones deben llevar todos sus argumentos. No hay valores predeterminados. Por ejemplo, las funciones estándar predefinidas deben tener un parámetro inicial que indique el campo de origen, lo que es una diferencia importante con respecto al modo de función única.
  • los espacios en blanco se ignoran y se pueden utilizar en cualquier lugar dentro de la expresión.
  • los textos constantes se encierran en comillas del mismo tipo, ya sea ' o ".

El lenguaje es parecido a los lenguajes «funcionales», en tanto que se construye casi únicamente a base de funciones. Una sentencia es una función. Una expresión es una función. Las constantes e identificadores pueden interpretarse como funciones que devuelven el valor indicado por la constante o almacenado en el identificador.

La sintaxis del lenguaje se muestra en la siguiente gramática:

constant   ::= " string " | ' string ' | number
identifier ::= sequence of letters or ``_`` characters
function   ::= identifier ( statement [ , statement ]* )
expression ::= identifier | constant | function | assignment
assignment ::= identifier '=' expression
statement  ::= expression [ ; expression ]*
program    ::= statement

Los comentarios son líneas que empiezan por un carácter «#».

Una expresión siempre tiene un valor, ya sea el valor de la constante, el valor contenido en el identificador o el valor devuelto por una función. El valor de una sentencia es el valor de la última expresión de la secuencia de sentencias. Así, el valor del siguiente programa (sentencia):

1; 2; 'foobar'; 3

es 3.

Otro ejemplo de un programa complejo pero más bien tonto podría ayudar a aclarar las cosas:

{series_index:'
    substr(
        strcat($, '->',
            cmp(divide($, 2), 1,
                assign(c, 1); substr('lt123', c, 0),
                'eq', 'gt')),
        0, 6)
   '| prefix | suffix}

Este programa hace lo siguiente:

  • especifica que el campo que se examina es series_index. Esto establece el valor de la variable $.
  • ejecuta la función substr, que toma 3 argumentos (texto, inicio, fin). Devuelve un texto formado extrayendo los caracteres entre inicio y fin de texto (el primer carácter es el número cero). En este caso, el texto se calcula mediante la función strcat, inicio es 0 y fin es 6. En este caso, devolverá los primeros 6 caracteres del texto devuelto por strcat, que debe evaluarse antes de que substr pueda finalizar.
  • ejecuta la función strcat (concatenación de textos). strcat acepta 1 o más argumentos, y devuelve un texto formado por la concatenación de todos los valores. En este caso hay tres argumentos. El primer argumento es el valor en $, que aquí es el valor de series_index. El segundo parámetro es el texto constante '->'. El tercer parámetro es el valor devuelto por la función cmp, que debe evaluarse completamente antes de que strcat pueda finalizar.
  • La función cmp toma 5 argumentos (x, y, mn, ig, my). Compara x e y y devuelve el tercer argumento, mn si x < y, el cuarto argumento, ig, si x = y, y el quinto argumento, my, si x > y. Como en todas las funciones, todos los parámetros pueden ser sentencias. En este caso el primer parámetro (el valor de x) es el resultado de dividir series_index entre 2. El segundo parámetro, y, es la constante 1. El tercer parámetro, mn es una sentencia (volveremos a él más adelante). El cuarto parámetro, ig, es el texto constante 'eq'. El quinto parámetro es el texto constante 'gt'.
  • El tercer parámetro (el de mn) es una sentencia, o una sequencia de expresiones. Recuerde que una sentencia (una sentencia de expresiones separadas por punto y coma) también es una expresión, que devuelve el valor de la última expresión de la lista. En este caso, el programa primero asigna el valor 1 a la variable local c, después devuelve un subtexto creado extrayendo desde el carácter número c hasta el final. Puesto que c siempre contiene la constante 1, el subtexto devolverá los caracteres desde el segundo hasta el final, o 't123'.
  • Una vez que se ejecuta la sentencia que proporciona un valor para el tercer parámetro, cmp puede devolver un valor. En este punto, strcat puede devolver un valor, y substr puede devolver un valor. Entonces el programa finaliza.

Para distintos valores de series_index, el programa devuelve:

  • series_index == undefined, resultado = prefix ->t123 suffix
  • series_index == 0.5, resultado = prefix 0.50-> suffix
  • series_index == 1, resultado = prefix 1->t12 suffix
  • series_index == 2, resultado = prefix 2->eq suffix
  • series_index == 3, resultado = prefix 3->gt suffix

Todas las funciones mostradas en el modo de función única puede usarse en el modo de programación. Para ello debe proporcionar el valor sobre el que actuará la función como primer parámetro, además de los parámetros documentados anteriormente. Por ejemplo, en el modo de programación los parámetros de la función test son test(x, texto_si_no_vacío, texto_si_vacío). El parámetro x, que es el valor que se comprueba, casi siempre será una variable o una llamada una función, a menudo field().

Las siguientes funciones están disponibles, además de las descritas en el modo de función única. Recuerde del ejemplo anterior que las funciones del modo de función única requieren un primer parámetro adicional que especifique el campo sobre el que se opera. Excepto el parámetro id de assign, todos los parámetros pueden ser sentencias (secuencias de expresiones). Tenga en cuenta que la documentación definitiva de las funciones está disponible en la sección Clasificación de funciones:

  • and(valor, valor, ...) – devuelve el texto «1» si todos los valores son no vacíos, en caso contrario devuelve un texto vacío. Esta función opera bien con test o first_non_empty. Pueden usarse tantos valores como se desee.

  • add(x, y) – devuelve x + y. Da un error si x o y no son números.

  • assign(id, val) – asigna val a id y devuelve val. id debe ser un identificador, no una expresión

  • approximate_formats() – devuelve una lista separada por comas de formatos que en algún momento estuvieron asociados con el libro. No hay garantía de que esta lista sea correcta, aunque probablemente lo sea. Esta función puede ejecutarse en el modo de programación de plantillas usando la plantilla {:'approximate_formats()'}. Tenga en cuenta que los nombres de formato están siempre en mayúsculas, como en «EPUB».

  • author_links(sep_val, sep_par) – devuelve un texto que contiene una lista de autores y enlaces de autores de la forma: autor1 sep_val enlace_autor1 sep_par autor2 sep_val enlace_autor2 etc. Cada autor está separado de su correspondiente enlace por el texto sep_val, sin espacios adicionales. Los pares autor:enlace_autor están separados por el texto sep_par, sin espacios adicionales. Es responsabilidad del usuario proporcionar separadores que no aparezcan en los nombres o enlaces de autor. El nombre de autor se incluye aunque su enlace esté vacío.

  • author_sorts(separador) – devuelve un texto que contiene la lista de valores de orden de autor para los autores del libro. El orden de autor es el que figura en los metadatos de autores (diferente del valor de orden de autor del libro). La lista devuelta es de la forma orden_de_autor_1 separador orden_de_autor_2 etc. Los valores de orden de autor en la lista están en el mismo orden que los autores del libro. Si quiere espacios alrededor de separador, inclúyalos en el valor.

  • booksize() – devuelve el valor del campo «tamaño» de calibre. Devuelve «» si no hay formatos.

  • cmp(x, y, mn, ig, my) – compara x e y después de convertirlas en números. Devuelve mn si x < y. Devuelve ig si x == y. Devuelve my en otros casos.

  • current_library_name() – devuelve la última parte de la ruta a la biblioteca de calibre actual. Esta función puede llamarse en el modo de programación de plantilla usando la plantilla {:'current_library_name()'}.

  • current_library_path() – devuelve la ruta a la biblioteca de calibre actual. Esta función puede usarse en el modo de programación de plantillas utilizando la plantilla {:'current_library_path()'}.

  • days_between(fecha1, fecha2) – devuelve el número de días entre fecha1 y fecha2. El número es positivo si fecha1 es posterior a fecha2, en caso contrario es negativo. Si fecha1 o fecha2 no son fechas, la función devuelve un texto vacío.

  • divide(x, y) – devuelve x / y. Da un error si x o y no son números.

  • eval(texto) – evalúa texto como un programa, pasando las variables locales (las definidas con assign). Esto permite usar el procesador de plantillas para elaborar resultados complejos a partir de variables locales. Dado que los caracteres { y } tienen un uso especial, debe usarse [[ en lugar de { y ]] para }; se convertirán automáticamente. Tenga en cuenta que los prefijos y sufijos (la sintaxis |prefijo|sufijo|) no puede usarse en el argumento de esta función en el modo de programación de plantilla.

  • field(nombre) – devuelve el campo de metadatos identificado por nombre.

  • first_matching_cmp(val, cmp1, resultado1, cmp2, resultado2, ..., otro_resultado) – compara val < cmpN consecutivamente y devuelve resultadoN para la primera comparación que sea cierta. Devuelve otro_resultado si ninguna comparación es cierta. Ejemplo:

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

    devuelve «»large»». El mismo ejemplo con un primer valor de 16 devuelve «»giant»».

  • first_non_empty(valor, valor, ...) – devuelve el primer valor que no esté vacío. Si todos los valores están vacíos, se devuelve también un valor vacío. Puede incluir tantos valores como quiera.

  • format_date(val, formato_fecha) – da formato a un valor, que debe ser un campo de fecha, según formato_fecha y devuelve un texto. Los códigos de formato son:

    d    : the day as number without a leading zero (1 to 31)
    dd   : the day as number with a leading zero (01 to 31)
    ddd  : the abbreviated localized day name (e.g. "Mon" to "Sun").
    dddd : the long localized day name (e.g. "Monday" to "Sunday").
    M    : the month as number without a leading zero (1 to 12).
    MM   : the month as number with a leading zero (01 to 12)
    MMM  : the abbreviated localized month name (e.g. "Jan" to "Dec").
    MMMM : the long localized month name (e.g. "January" to "December").
    yy   : the year as two digit number (00 to 99).
    yyyy : the year as four digit number.
    h    : the hours without a leading 0 (0 to 11 or 0 to 23, depending on am/pm)
    hh   : the hours with a leading 0 (00 to 11 or 00 to 23, depending on am/pm)
    m    : the minutes without a leading 0 (0 to 59)
    mm   : the minutes with a leading 0 (00 to 59)
    s    : the seconds without a leading 0 (0 to 59)
    ss   : the seconds with a leading 0 (00 to 59)
    ap   : use a 12-hour clock instead of a 24-hour clock, with 'ap' replaced by the localized string for am or pm.
    AP   : use a 12-hour clock instead of a 24-hour clock, with 'AP' replaced by the localized string for AM or PM.
    iso  : the date with time and timezone. Must be the only format present.
    

    Puede obtener resultados inesperados si la fecha a la que se da formato contiene nombres de meses traducidos, lo que puede ocurrir si ha modificado los ajustes de formato para incluir MMMM. En este caso, en lugar de usar algo como {pubdate:format_date(yyyy)}, escriba la plantilla usando el modo de programación de plantillas, como en {:'format_date(raw_field('pubdate'),'yyyy')'}.

  • finish_formatting(val, formato, prefijo, sufijo) – aplica el formato, prefijo y sufijo a un valor de la misma manera que se haría en una plantilla como {series_index:05.2f| - |- }. Esta función se proporciona para facilitar la conversión de plantillas complejas en modo de función única o de plantilla al modo de programación general (ver más adelante) y aprovechar la compilación de plantillas. Por ejemplo, el siguiente programa produce la misma salida que la plantilla anterior:

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

    Otro ejemplo: para la plantilla {series:re(([^\s])[^\s]+(\s|$),\1)}{series_index:0>2s| - | - }{title} use:

    program:
        strcat(
            re(field('series'), '([^\s])[^\s]+(\s|$)', '\1'),
            finish_formatting(field('series_index'), '0>2s', ' - ', ' - '),
            field('title')
        )
    
  • formats_modtimes(formato_fecha) – devuelve una lista de elementos (separados por dos puntos) separados por comas que representa las fechas de modificación para los formatos de un libro. El argumento formato_fecha especifica cómo se da formato a la fecha. Véase la función «format_date» para más detalles. Puede usar la función «select» para obtener la fecha de modificación de un formato específico. Tenga en cuenta que los nombres de formato siempre están en mayúsculas, como en «EPUB».

  • formats_paths() – devuelve una lista separada por comas de elementos separados por dos puntos que representan la ruta completa a los formatos de un libro. Puede usar la función «select» para obtener la ruta a un formato específico. Tenga en cuenta que los nombres de formato están siempre en mayúsculas, como en «EPUB».

  • formats_sizes() – devuelve una lista de elementos (separados por dos puntos) separados por comas que representa los tamaños en bytes de los formatos de un libro. Puede usar la función «select» para obtener el tamaño de un formato específico. Tenga en cuenta que los nombres de formato siempre están en mayúsculas, como en «EPUB».

  • has_cover() – devuelve Yes si el libro tiene portada, en caso contrario devuelve un texto vacío.

  • not(valor) – devuelve el texto «1» si el valor está vacío, en caso contrario, devuelve un texto vacío. Esta función opera bien con «test» o «first_non_empty».

  • list_difference(lista1, lista2, separador) – devuelve una lista construida eliminando de lista1 cualquier elemento que aparezca en lista2, sin distinguir mayúsculas y minúsculas. Los elementos de lista1 y lista2 están separados por separador, así como los de la lista resultante.

  • list_equals(lista1, sep1, lista2, sep2, val_sí, val_no) – devuelve val_sí si lista1 y lista2 contienen los mismos elementos, en caso contrario devuelve val_no. Los elementos se determinan dividiendo cada lista por el correspondiente carácter separador (sep1 o sep2). El orden de los elementos no es relevante. La comparación no diferencia mayúsculas y minúsculas.

  • list_intersection(lista1, lista2, separador) – devuelve una lista construida eliminando de lista1 cualquier elemento que no aparezca en lista2, sin distinguir mayúsculas y minúsculas. Los elementos de lista1 y lista2 están separados por separador, así como los de la lista resultante.

  • list_re(lista_orig, separador, incluir, sust_opc) – construye una lista separando primero lista_orig en elementos usando el carácter separador. Para cada elemento en la lista, comprueba si coincide con la expresión regular incluir. Si coincide, se añade a la lista final. Si sust_opc no es un texto vacío, se aplica la sustitución antes de añadir el elemento a la lista final.

  • list_re_group(lista_orig, separador, incluir, búsqueda, plantilla_grupo_1, plantilla_grupo_2, ...) – como list_re, pero las sustituciones no son opcionales. Usa re_group(elemento, búsqueda, plantilla_grupo_1, ...) para hacer sustituciones..

  • list_sort(lista, dirección, separador) – devuelve lista ordenada sin distinción de mayúsculas y minúsculas. Si dirección es cero, la lista se ordena de manera ascendente, en caso contrario, de manera descendente. Los elementos de lista están separados por separador, así como los de la lista resultante.

  • list_union(lista1, lista2, separador) – devuelve una lista construida por combinación de los elementos en lista1 y lista2, eliminando los duplicados de lista2 (no distingue mayúsculas y minúsculas, se mantiene la versión de lista1). Los elementos de lista1 y lista2 están separados por separador, así como los de la lista resultante.

  • multiply(x, y)– devuelve x * y. Da una excepción si x o y no son números.

  • ondevice() – devuelve el texto «Yes» si ondevice está activado, si no, devuelve un texto vacío

  • or(valor, valor, ...) – devuelve el texto «1» si alguno de los valores no está vacío, en caso contrario devuelve un texto vacío. Esta función opera bien con test o first_non_empty. Pueden usarse tantos valores como se desee.

  • print(a, b, ...) – escribe los argumentos en la salida estándar. Sólo será visible si inicia calibre a partir de línea de órdenes (calibre-debug -g).

  • raw_field(name) – devuelve el campo de metadatos llamado nombre sin aplicar ningún formato.

  • raw_list(nombre, separador) – devuelve la lista de metadatos nombrada por nombre sin aplicar ningún formato u ordenación, con los elementos separados por separador.

  • re_group(val, patrón, plantilla_para_grupo_1, para_grupo_2, ...) – devuelve un texto formado por aplicación de la expresión regular patrón al valor val, sustituyendo cada coincidencia por el texto calculado al sustituir cada grupo por el valor devuelto por la correspondiente plantilla. El valor de correspondencia original del grupo está disponible como «$». En el modo de programación de plantillas, como en las funciones template y eval, use [[ en lugar de { y ]] en lugar de }. El siguiente ejemplo en modo de programación de plantillas busca nombres de serie con más de una palabra y pone la primera palabra en mayúsculas:

    {series:'re_group($, "(\S* )(.*)", "[[$:uppercase()]]", "[[$]]")'}
    
  • series_sort() – devuelve el valor de orden de serie.

  • strcat(a, b, ...) – puede tomar cualquier número de argumentos. Devuelve texto formado por la concatenación de todos los argumentos.

  • strcat_max(máx, texto1, prefijo2, texto2, ...) – devuelve un texto formado por concatenación de los argumentos. El valor devuelto es inicialmente texto1. Se van añadiendo parejas prefijo, texto al final del valor mientras la longitud del resultado sea menor que máx. El resultado es siempre al menos texto1, aunque su longitud sea mayor que máx. Pueden especificarse tantas parejas prefijo, texto como se desee.

  • strcmp(x, y, mn, ig, my) – hace una comparación sin distinción de mayúsculas y minúsculas entre x e y como textos. Devuelve mn si x < y. Devuelve ig si x == y. Devuelve my en otros casos.

  • strlen(a) – Devuelve la longitud del texto pasado como argumento.

  • substr(texto, inicio, fin) – devuelve los caracteres entre la posición inicio y fin de texto. El primer carácter de texto está en la posición cero. Si fin es negativo, entonces indica la posición contando desde la derecha. Si fin es cero, indica el último carácter. Por ejemplo, substr('12345', 1, 0) devuelve 2345, y substr('12345', 1, -1) devuelve 234.

  • subtract(x, y) – devuelve x - y. Da un error si x o y no son números.

  • today() – devuelve un texto para la fecha de hoy. Este valor está preparado para usarse con format_date o days_between, pero puede manipularse como cualquier otro texto. La fecha está en formato ISO.

  • template(x) – evalúa x como una plantilla. La evaluación se realiza en un contexto propio, lo que significa que las variables no se comparten entre el proceso que llama a la función y la evaluación de la plantilla. Dado que los caracteres { y } tienen un uso especial, debe usar [[ en lugar de { y ]] para }; se convertirán automáticamente. Por ejemplo, template('[[orden_de_título]]') evaluará la plantilla {orden_de_título} y devolverá su valor. Tenga en cuenta que los prefijos y sufijos (la sintaxis |prefijo|sufijo) no puede usarse en el argumento de esta función en el modo de programación de plantilla.

Clasificación de funciones

Usar el modo de programa general

Para programas de plantilla más complicados, a veces es más sencillo evitar la sintaxis de plantillas (todos los caracteres «{» y «}») y escribir programas con aspecto más convencional. Puede hacer esto en calibre comenzando la plantilla con program:. En este caso no se realizará ningún procesado de plantillas. El valor especial $ no se establece. El programa es enteramente responsable de producir los resultados correctos.

Una ventaja del modo program: es que las llaves ya no son especiales. Por ejemplo, no es necesario usar «[[» y «]]» al usar la función template(). Otra ventaja es que las plantillas en modo de programación se compilan en Python y pueden ejecutarse más rápidamente que las plantillas en los otros dos modos. La mejora de velocidad depende de la complejidad de las plantillas: cuanto más compleja mayor es la mejora. La compilación se activa y desactiva con el ajuste compile_gpm_templates (Compilar plantillas en el modo de programa general a python). El principal motivo para desactivar la compilación es si una plantilla compilada no funciona, si esto ocurre por favor envíe un informe de error.

El siguiente ejemplo es una implementación en modo program: de una fórmula del foro MobileRead: «Poner la serie en el título, usando iniciales o una forma abreviada. Eliminar artículos al inicio del nombre de la serie (cualquiera).» Por ejemplo, para el libro «Las dos torres» en la serie «El señor de los anillos», la fórmula da sdla [02] Las dos torres. Usando plantillas estándar, la fórmula requiere tres columnas personalizadas y un panel de conexiones, como se explica a continuación:

La solución requiere crear tres columnas compuestas. La primera columna se usa para eliminar los artículos iniciales. La segunda se usa para calcular la forma «abreviada». La tercera es para calcular la forma de «iniciales». Una vez tiene estas columnas, el panel de conexiones selecciona entre ellas. Puede ocultar alguna o las tres columnas en la vista de biblioteca:

First column:
Name: #stripped_series.
Template: {series:re(^(A|The|An)\s+,)||}

Second column (the shortened form):
Name: #shortened.
Template: {#stripped_series:shorten(4,-,4)}

Third column (the initials form):
Name: #initials.
Template: {#stripped_series:re(([^\s])[^\s]+(\s|$),\1)}

Plugboard expression:
Template:{#stripped_series:lookup(.\s,#initials,.,#shortened,series)}{series_index:0>2.0f| [|] }{title}
Destination field: title

This set of fields and plugboard produces:
Series: The Lord of the Rings
Series index: 2
Title: The Two Towers
Output: LotR [02] The Two Towers

Series: Dahak
Series index: 1
Title: Mutineers Moon
Output: Dahak [01] Mutineers Moon

Series: Berserkers
Series Index: 4
Title: Berserker Throne
Output: Bers-kers [04] Berserker Throne

Series: Meg Langslow Mysteries
Series Index: 3
Title: Revenge of the Wrought-Iron Flamingos
Output: MLM [03] Revenge of the Wrought-Iron Flamingos

El siguiente programa produce los mismos resultados que la fórmula original, usando solamente una columna personalizada para mantener los resultados de un programa que calcule el valor de título especial:

Custom column:
Name: #special_title
Template: (the following with all leading spaces removed)
    program:
    #       compute the equivalent of the composite fields and store them in local variables
        stripped = re(field('series'), '^(A|The|An)\s+', '');
        shortened = shorten(stripped, 4, '-' ,4);
        initials = re(stripped, '[^\w]*(\w?)[^\s]+(\s|$)', '\1');

    #       Format the series index. Ends up as empty if there is no series index.
    #       Note that leading and trailing spaces will be removed by the formatter,
    #       so we cannot add them here. We will do that in the strcat below.
    #       Also note that because we are in 'program' mode, we can freely use
    #       curly brackets in strings, something we cannot do in template mode.
        s_index = template('{series_index:0>2.0f}');

    #       print(stripped, shortened, initials, s_index);

    #       Now concatenate all the bits together. The switch picks between
    #       initials and shortened, depending on whether there is a space
    #       in stripped. We then add the brackets around s_index if it is
    #       not empty. Finally, add the title. As this is the last function in
    #       the program, its value will be returned.
        strcat(
            switch( stripped,
                    '.\s', initials,
                    '.', shortened,
                    field('series')),
            test(s_index, strcat(' [', s_index, '] '), ''),
            field('title'));

Plugboard expression:
Template:{#special_title}
Destination field: title

Sería posible hacer lo anterior sin columnas personalizadas, poniendo el programa en el cuadro de plantilla del panel de conexiones. Sin embargo, para hacerlo, habría que eliminar todos los comentarios, puesto que el cuadro de texto del panel de conexiones no admite varias líneas. Es discutible si el beneficio de no tener una columna personalizada compensa el gran incremento de dificultad creado por tener el programa en una única y enorme línea.

Funciones de plantilla definidas por el usuario

Puede añadir funciones propias al procesador de plantillas. Dichas funciones están escritas en Python y pueden usarse en cualquiera de los tres modos de programación de plantillas. Las funciones se añaden en Preferencias > Avanzado > Funciones de plantilla. Las instrucciones se muestran en el correspondiente cuadro de diálogo.

Notas especiales para plantillas de guardado o envío

Cuando una plantilla se usa como plantilla de «guardado a disco» o de «envío a dispositivo», ocurre un procesado especial. Los valores de los campos se sanean, eliminando caracteres especiales para los sistemas operativos por guiones bajos, incluyendo barras. Esto significa que el texto de los campos no puede usarse para crear carpetas. Sin embargo, las barras no se modifican en los textos de prefijo o sufijo, por lo que las barras en estos textos harán que se creen carpetas. Gracias a esto, es posible crear estructuras de carpetas de profundidad variable.

Por ejemplo, supongamos que quiere una estructura de carpetas serie/índice de serie - título, con la salvedad de que si la serie no existe el título debe estar en la carpeta superior. La plantilla para conseguir esto es:

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

La barra y el guión sólo aparecen si la serie no está vacía.

La función lookup() nos permite realizar un procesado aún más complejo. Por ejemplo, supongamos que si un libro tiene una serie, entonces queremos una estructura de carpetas serie/índice de serie - título. Si el libro no tiene una serie, entonces queremos la estructura género/orden de autor/título. Si el libro no tiene género, queremos que use «Desconocido». Queremos seguir dos caminos completamente distintos según el valor de la serie.

Para lograr esto:
  1. Creamos un campo compuesto (démosle el nombre de búsqueda #AA) que contiene {series}/{series_index} - {title}. Si la serie no está vacía, esta plantilla produce serie/número_de_serie - título.
  2. Creamos un campo compuesto (démosle el nombre de búsqueda #BB) que contenga {#genre:ifempty(Desconocido)}/{author_sort}/{title}. Esta plantilla produce género/orden de autor/título, donde un género vacío se sustituye por Desconocido.
  3. Establecemos la plantilla de guardado en {series:lookup(.,#AA,#BB)}. Esta plantilla elige el campo compuesto #AA si la serie no está vacía y el campo compuesto #BB si la serie está vacía. Obtenemos por lo tanto dos rutas de guardado completamente diferentes según el campo series esté o no vacío.

Plantillas y controles de metadatos

Los paneles de conexiones se usan para cambiar los metadatos escritos en los libros durante las operaciones de guardado en disco y de envío a dispositivo. Un panel de conexiones le permite especificar una plantilla para suministrar los datos que se escribirán en los metadatos del libro. Puede usar los paneles de conexiones para modificar los siguientes campos: authors, author_sort, language, publisher, tags, title, title_sort. Esa función es útil para los que quieren usar metadatos diferentes en los libros de los dispositivos, para solucionar problemas de ordenación o de visualización.

Cuando cree un panel de conexiones, especifique el formato y dispositivo para los que se usará. Hay un dispositivo especial «save_to_disk», que se usa para guardar formatos (en lugar de enviarlos a un dispositivo). Una vez que ha elegido el formato y dispositivo, elija los campos de metadatos para cambiar, y suministre plantillas para obtener los nuevos valores. Estas plantillas están conectadas con sus campos de destino, de ahí el nombre panel de conexiones. Por supuesto, puede usar columnas compuestas en estas plantillas.

Cuando un panel de conexiones pueda aplicarse (servidor de contenido, guardado en disco o envío a dispositivo), calibre busca los paneles definidos para elegir el correcto según el formato y dispositivo. Por ejemplo, para encontrar el panel de conexiones apropiado para enviar un libro EPUB a un dispositivo ANDROID, calibre busca en los paneles en el siguiente orden:

  • un panel de conexiones con una coincidencia exacta de formato y dispositivo, por ejemplo: EPUB y ANDROID
  • un panel de conexiones con una coincidencia exacta de formato y el dispositivo especial any device, por ejemplo EPUB y any device
  • un panel de conexiones con el formato especial any format y una coincidencia exacta de dispositivo, por ejemplo: any format y ANDROID
  • un panel de conexiones con any format y any device

Los campos etiquetas y autores tienen un trato especial, debido a que ambos pueden tener más de un elemento. Un libro puede poseer varias etiquetas y varios autores. Cuando indique que desea cambiar uno de estos campos, la plantilla se examina para comprobar si hay más de un elemento. Para las etiquetas, el resultado se divide dondequiera que calibre encuentre una coma. Por ejemplo, si la plantilla produce el valor Intriga, Terror, el resultado serán dos etiquetas: Intriga y Terror. No existe manera de poner una coma dentro de una etiqueta.

Lo mismo ocurre con los autores, pero usando un carácter diferente para el corte, un signo «&» en lugar de una coma. Por ejemplo, si la plantilla produce el valor Blogs, Joe&Posts, Susan, el libro acabará con dos autores, Blogs, Joe y Posts, Susan. Si la plantilla produce el valor Blogs, Joe;Posts, Susan, el libro tendrá un autor con un nombre peculiar.

Los paneles de conexiones afectan a los metadatos escritos en el libro cuando se guarda en disco o se escribe en un dispositivo. Los paneles de conexiones no afectan a los metadatos usados por las funciones Guardar en el disco Enviar al dispositivo para crear los nombres de archivo. En lugar de ello, los nombres de archivo se construyen usando las plantillas introducidas en la ventana de preferencias correspondiente.

Consejos útiles

Puede encontrar útiles los siguientes consejos.

  • Cree una columna compuesta personalizada para probar plantillas. Una vez que tenga la columna, puede hacer cambios en la plantilla pulsando dos veces en la columna. Oculte la columna cuando no esté haciendo pruebas.
  • Las plantillas pueden usar otras plantillas haciendo referencia a una columna personalizada compuesta.
  • En un panel de conexiones, puede establecer un campo como vacío (o lo que sea equivalente a vacío) utilizando la plantilla especial {}. Esta plantilla siempre producirá un texto vacío.
  • La técnica descrita anteriormente para mostrar los números incluso si son cero funciona con el campo estándar «series_index».