El lenguaje de plantillas de calibre¶
El lenguaje de plantillas de calibre es un lenguaje específico de calibre que se utiliza en todo calibre para tareas como especificar rutas de archivo, dar formato a valores y calcular el valor de las columnas especificadas por el usuario. Ejemplos:
Especifar la estructura de carpetas y los nombres de archivo al guardar archivos de la biblioteca de calibre en el disco o en el lector de libros electrónicos.
Definir reglas para añadir iconos y colores a la lista de libros de calibre.
Definir columnas virtuales que contienen datos de otras columnas.
Búsqueda avanzada en la bibliotecas.
Búsqueda y sustitución avanzada de metadatos.
El lenguaje está construido en torno al concepto de una «plantilla», que especifica qué metadatos del libro se usan, las operaciones que se realizan sobre los metadatos y qué formato se aplica.
Plantillas básicas¶
Una plantilla básica consiste en una o varias expresiones de plantilla
. Una expresión de plantilla
consiste en texto y nombres entre llaves ({}
) que se sustituyen por los metadatos correspondientes del libro que está siendo procesado. Por ejemplo, la plantilla predeterminada de calibre para guardar libros en un dispositivo tiene 4 expresiones de plantilla
:
{author_sort}/{title}/{title} - {authors}
Para el libro «The Foundation» de «Isaac Asimov» da lugar a:
Asimov, Isaac/The Foundation/The Foundation - Isaac Asimov
Las barras no son expresiones de plantilla
porque no están entre {}
. Este tipo de texto se mantiene donde aparece. Por ejemplo, si la plantilla es:
{author_sort} Some Important Text {title}/{title} - {authors}
entonces para «The Foundation» la plantilla produce:
Asimov, Isaac Some Important Text The Foundation/The Foundation - Isaac Asimov
Una expresión de plantilla
tiene acceso a todos los metadatos disponibles en calibre, incluidas las columnas personalizadas que haya creado, usando su el nombre de búsqueda
de una columna. Para obtener el nombre de búsqueda o consulta de una columna (también llamada campo), pase el cursor sobre el encabezado de la columna en la lista de libros de calibre. Los nombres de búsqueda para las columnas personalizadas siempre empiezan por #
. Para columnas personalizadas de tipo serie, siempre hay un campo adicional llamado #nombre de búsqueda_index
que es el índice de serie para el libro en la serie. Por ejemplo, si tiene una columna personalizada de serie llamada #miserie
, también habrá una columna llamada #miserie_index
. La columna de índice para la serie normal se llama series_index
.
Además de los campos basados en columnas normales, también puede usar:
{formats}
- Una lista de los formatos disponibles en la biblioteca de calibre para un libro
{identifiers:select(isbn)}
- El ISBN del libro
Si un campo de metadatos para un libro determinado no está definido, entonces el campo en la plantilla se sustituye por un texto vacío (''
). Por ejemplo, considere la siguiente plantilla:
{author_sort}/{series}/{title} {series_index}
Si el libro de Asimov «Second Foundation» está en la serie «Foundation», la plantilla produce:
Asimov, Isaac/Foundation/Second Foundation 3
Si no se ha introducido la serie para el libro, la plantilla produce:
Asimov, Isaac/Second Foundation
El procesador de plantillas elimina automáticamente barras múltiples y espacios iniciales o finales.
Formato avanzado¶
Además de sustituir metadatos, las plantillas pueden incluir texto adicional de manera condicional y controlar el formato de los datos sustituidos.
Incluir texto de mane condicional
A veces 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 separados por un guión. calibre tiene en cuenta este caso usando una sintaxis de expresión de plantilla
especial.
Por ejemplo, y usando el caso anterior de la serie «Foundation», suponga que quiere que la plantilla produzca Foundation - 3 - Second Foundation. Esta plantilla cumple el cometido:
{series} - {series_index} - {title}
Sin embargo, si un libro no tiene serie, la plantilla producirá - - el título, que probablemente no sea lo que deseaba. Normalmente preferiría que el resultado fuese el título sin los guiones. Puede conseguir esto usando la siguiente sintaxis de plantilla:
{campo:|prefijo|sufijo}
Esta expresión de plantilla
dice que si campo
tiene el valor XXXX, el resultado será prefijoXXXXXsufijo. Si campo
está vacío (no tiene ningún valor) el resultado será un texto vacío (nada), porque el prefijo y el sufijo se ignoran. Tanto el prefijo como el sufijo pueden contener espacios.
No use subplantillas ({…}) o funciones (ver más adelante) en el prefijo o el sufijo.
Usando esta sintaxis, podemos resolver el problema anterior de los libros sin serie 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. Continuando con el ejemplo de la serie «Foundation», la plantilla producirá Foundation - 1 - Second Foundation.
Notas:
Debe incluir los dos puntos tras el
nombre de búsqueda
si usa un prefijo o sufijo.Debe incluir ambos caracteres
|
o ninguno. No está permitido usar sólo uno como en{campo:| - }
.Es posible asignar un texto vació para el prefijo o sufijo, como en
{series:|| - }
. La plantilla{title:||}
es lo mismo que{title}
.
Formato
Supongamos que queremos asegurarnos de que series_index
aparezca con dígitos, con ceros a la izquierda. Se consigue de esta manera:
{series_index:0>3s}
- Tres dígitos con ceros a la izquierda
Para obtener ceros a la derecha use:
{series_index:0<3s}
- Tres dígitos con ceros a la derecha
Si usa índices de serie con decimales (por ejemplo 1.1), puede querer asegurarse de que los decimales queden alineados. Por ejemplo, puede que los índices 1 y 2.5 aparezcan como 01.00 y 02.50 para que se ordenen correctamente en un dispositivo que utilice un orden lexicográfico. Para ello, use:
{series_index:0>5.2f}
- Cinco caracteres que incluyen dos dígitos con cero a la izquierda, un punto decimal y dos dígitos tras el punto decimal.
Si quiere sólo las dos primeras letras de los datos, use:
{author_sort:.2}
- Sólo las primeras dos letras del orden de autor
Gran parte del formato del 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).
Usar plantillas para definir columnas personalizadas¶
Las plantillas pueden usarse para mostrar información que no está en los metadatos de calibre o para mostrar los metadatos de una manera diferente al formato normal de calibre. Por ejemplo, puede querer mostrar el ISBN
, un campo que calibre no muestra. Puede conseguirlo creando una columna personalizadad de tipo columna generada a partir de otras columnas (en lo sucesivo llamadas columnas compuestas), e introduciendo una plantilla para generar el texto mostrado. La columna mostrará el resultado de evaluar la plantilla. Por ejemplo, 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.
Nota: No puede modificar los datos mostrados en una columna compuesta, debe modificar las columnas de origen. Si modifica una columna compuesta, por ejemplo pulsando dos veces sobre ella, calibre abrirá la plantilla para modificarla, no los datos resultantes.
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.
Los paneles de conexiones son muy flexibles y pueden escribirse en modo de función única, en modo programación de plantillas, en modo de programación general o en modo de plantilla de Python.
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
yANDROID
un panel de conexiones con una coincidencia exacta de formato y el dispositivo especial
any device
, por ejemploEPUB
yany device
un panel de conexiones con el formato especial
any format
y una coincidencia exacta de dispositivo, por ejemplo:any format
yANDROID
un panel de conexiones con
any format
yany 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.
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 usando las funciones de plantilla. Por ejemplo, para mostrar el título en mayúsculas use la función uppercase
, como en {title:uppercase()}
. Para mostrarlo con las iniciales en mayúscula use {title:titlecase()}
.
Las funciones van en la parte del formato de la plantilla, después de :
y antes del primer |
o del }
de cierre si no se usa ningún prefijo o sufijo. Si tiene tanto un formato como una referencia de función, la función va después de otro :
. Las funciones devuelven el valor de la columna especificada en la plantilla, modificado de manera adecuada.
La sintaxis para usar funciones es una de:
{lookup_name:function(arguments)}
{lookup_name:format:function(arguments)}
{lookup_name:function(arguments)|prefix|suffix}
{lookup_name:format:function(arguments)|prefix|suffix}
Los nombres de función deben is siempre seguidos de paréntesis de apertura y cierre. Algunas funciones requieren valores adicionales (argumentos), y éstos van dentro de los paréntesis. Los argumentos se separan por comas. Una coma literal (como texto, no como separador de argumentos) debe ir precedida de una barra invertida (\
). El último (o único) argumento no puede contener un paréntesis de cierre textual.
Las funciones se evalúan antes de las especificaciones de formato y del prefijo y sufijo. Véase más abajo un ejemplo de cómo usar un formato y una función.
Importante: Si tiene experiencia en programación, tenga en cuenta que la sintaxis del modo de función única no es la que podría esperarse. Los textos van sin comillas y los espacios son importantes. Todos los argumentos se interpretan como constantes; no hay expresiones.
No use subplantillas ({…}) como argumentos de función. En su lugar, use el modo de programación de plantilla o el modo de programación general.
Algunas funciones requieren expresiones regulares. En el lenguaje de plantillas, las expresiones regulares no distinguen entre mayúsculas y minúsculas.
En la documentación de funciones que se presenta a continuación, la notación [algo]*
significa que algo
puede repetirse cero o más veces. La notación [algo]+
significa que algo
se repite una o más veces (debe existir al menos una vez).
Las funciones pensadas para usarse en modo de función única son:
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 valor coincide con la expresión regularpatrón
. Devuelvetexto_si_coincide
si el patrón coincide con el valor, en caso contrario devuelvetexto_si_no_coincide
.count(separador)
– interpreta el valor como una lista de elementos separados porseparador
y devuelve el número de elementos de la lista. La mayoría de las listas usan una coma como separador, peroauthors
usa un «ampersand» (&). Ejemplos:{tags:count(,)}
,{authors,count(&)}
. Sinónimos:count()
,list_count()
format_number(plantilla)
– interpreta el valor como un número y le da formato usando una plantilla de formato de Python como{0:5.2f}
o{0:,d}
o${0:5,.2f}
. La plantilla de formato debe empezar por{0:
y terminar por}
, como en los ejemplos anteriores. Excepción: puede omitir el{0:
inicial y el}
final si la plantilla de formato contiene sólo un formato. Véase la documentación del lenguaje de plantillas y de Python para más ejemplos. Devuelve un texto vacío si el formato falla.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_vacío)
– si el valor no está vacío, devuelve el valor del campo, en caso contrario devuelvetexto_si_vacío
.in_list(separador, [ patrón, encontrado, ]* no_encontrado)
– interpreta el valor como una lista de elementos separados porseparador
y compruebapatrón
para cada elemento de la lista. Sipatrón
coincide con algún elemento, devuelveencontrado
, en caso contrario devuelveno_encontrado
. La pareja de argumentospatrón
yencontrado
puede repetirse tantas veces como se desee, lo que permite devolver diferentes valores según el valor del elemento. Los patrones se evalúan en orden y se devuelve la primera coincidencia.language_strings(localizar)
– devuelve los nombres de los idiomas identificados por los códigos de idioma pasados como valor. Ejemplo{languages:language_strings()}
. Silocalizar
es cero, devuelve los nombres en inglés. Silocalizar
no es cero, devuelve los nombres en el idioma actual. Los códigos de idioma son una lista separada por comas.list_item(índice, separador)
– interpreta el valor como una lista de elementos separados porseparador
y devuelve el elemento númeroíndice
. El primer elemento es el número cero. El último elemento tiene índice-1
y puede obtenerse conlist_item(-1,separador)
. Si el elemento no está en la lista devuelve un texto vacío.lookup([ patrón, clave, ]* clave_alternativa)
– Los patrones se comparan con el valor en orden. Si un patrón coincide, se devuelve el valor del campo indicado porclave
. Si no coincide ningún patrón, se devuelve el valor del campo indicado porclave_alternativa
. Véaseswitch
(más abajo).lowercase()
– devuelve el valor del campo en minúsculas.rating_to_stars(usar_media_estrella)
– Devuelve la calificación como caracteres de estrella (★
). El valor debe ser un número entre 0 y 5. Pongausar_media_estrella
a 1 si quiere caracteres de media estrella para números fraccionarios, disponibles con columnas personalizadas de calificación.re(patrón, sustitución)
– devuelve el valor después de aplicar la expresión regular. Todas las veces que aparezcapatrón
en el valor se sustituirá porsustitución
. El lenguaje de plantillas usa ``expresiones regulares de Python <https://docs.python.org/3/library/re.html>`_, sin distinguir mayúsculas y minúsculas.select(clave)
– interpreta el valor como una lista de elementos separados por comas, con cada elemento de la formaid:valor
(el formato de la columnaidentifier
de calibre). La función encuentra la primera pareja conid
igual aclave
y devuelve elvalor
correspondiente. Si no se encuentra elid
la función devuelve un texto vacío.shorten(car_izq, texto_medio, car_der)
– devuelve una versión abreviada del valor, consistente en un númerocar_izq
de caracteres del principio del valor, seguidos detexto_medio
, seguido de un númerocar_der
de caracteres del final del valor.car_izq
ycar_der
deben ser números enteros no negativos. Ejemplo, supongamos que quiere mostrar el título con una longitud máxima de 15 caracteres. Una plantilla que hace esto es{title:shorten(9,-,5)}
. Para un libro con el título Novísima recopilación de las leyes de España el resultado será Novísima -spaña: los primeros 9 caracteres del título, un-
y los últimos 5 caracteres. Si la longitud del valor es menor quecar_izq
+car_der
+ la longitud detexto_medio
, se usará el valor intacto. Por ejemplo, el título La colmena no se cambiará.str_in_list(separador, [ texto, encontrado, ]+ no_encontrado)
– interpreta el valor como una lista de elementos separados porseparador
, y comparatexto
con cada valor de la lista. El argumentotexto
no es una expresión regular. Sitexto
es igual a alguno de los valores (sin distinción de mayúsculas y minúsculas), devuelve el correspondienteencontrado
. Sitexto
contieneseparador
, se interpreta también como una lista y se compara cada subvalor. La pareja de argumentostexto
yencontrado
puede repetirse tantas veces como se desee, lo que permite devolver diferentes valores según el valor detexto
. Los textos se comparan en orden. Se devuelve la primera coincidencia.subitems(índice_inicio, índice_fin)
– Esta función separa listas de elementos jerárquicos de tipo etiqueta, tales como los géneros. Interpreta val como una lista de elementos separados por comas, donde cada elemento es a su vez una lista de elementos separados por puntos. Devuelve una nueva lista formada tomando de cada elemento los componentes entre las posicionesíndice_inicio
eíndice_fin
y combinando los resultados. Se eliminan los duplicados. El primer subelemento de cada lista separada por puntos ocupa la posición cero. Si un índice es negativo, se cuenta desde el final de la lista. Como caso especial, siíndice_fin
es cero, se considera que es el final de la lista.Ejemplos:
Suponiendo que la columna
#genero
contiene A.B.C:{#genero:subitems(0,1)}
devuelve A{genero:subitems(0,2)}
devuelve A.B{#genero:subitems(1,0)}
devuelve B.C
Suponiendo que la columna
#genero
contiene A.B.C, D.E:{#genero:subitems(0,1)}
devuelve A, D{#genero:subitems(0,2)}
devuelve A.B, D.E
sublist(índice_inicio, índice_fin, separador)
– interpreta el valor como una lista de elementos separados porseparador
y devuelve una nueva lista con los elementos comprendidos entre la posicióníndice_inicio
eíndice_fin
. El primer elemento ocupa la posición cero. Si un índice es negativo, se cuenta desde el final de la lista. Como caso especial, siíndice_fin
es cero, se considera que es el final de la lista.Ejemplos suponiendo que la columna
tags
(separada por comas) contiene A, B, C:{tags:sublist(0,1,\,)}
devuelve A{tags:sublist(-1,0,\,)}
devuelve C{tags:sublist(0,-1,\,)}
devuelve A, B
swap_around_articles(separador)
– devuelve el valor con los artículos puestos al final. El valor puede ser una lista, en cuyo caso se procesará cada elemento de la lista. Si el valor es una lista, debe proporcionar elseparador
de los elementos de la lista. Si no se proporciona ningúnseparador
, la lista se trata como un único valor, no una lista. Los artículos son los que calibre usa para generar el orden de título.swap_around_comma()
– dado un valor de la formaB, A
, devuelveA B
. Esto es útil para convertir nombres en formato APELLIDO, NOMBRE a NOMBRE APELLIDO. Si no hay ninguna coma en el valor, la función devuelve el valor sin cambios.switch([patrón, valor,]+ otro_valor)
– para cada parejapatrón
,valor
, comprueba si el valor contiene coincidencias para la expresión regularpatrón
y, en tal caso, devuelve elvalor
asociado. Si no coincide ningún patrón, devuelveotro_valor
. Pueden emplearse tantas parejaspatrón
,valor
como se desee. Se devuelve la primera coincidencia.test(texto_si_no_vacío, texto_si_vacío)
– devuelvetexto_si_no_vacío
si el valor no está vacío, devuelvetexto_si_vacío
en caso contrario.titlecase()
– devuelve el valor del campo con las iniciales en mayúscula.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 devuelveFiodor Mikhailovich Dostoievskii
.uppercase()
– devuelve el valor del campo en mayúsculas.
Usar funciones y formato en la misma plantilla
Supongamos que tiene una columna personalizada con números enteros #myint
, que quiere mostrar con ceros a la izquierda, como en 003
. Una posibilidad es usa como formato 0>3s
. Sin embargo, de manera predeterminada, si un número (entero o decimal) es igual a cero, el valor se muestra como un texto vacío, así que el valor cero producirá un texto vacío, no 000
. Si quiere ver los valores como 000
, debe usar tanto el texto de formato como la función ifempty
para cambiar el valor vacío a cero de nuevo, la plantilla 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 la plantilla:
{#myint:0>3s:ifempty(0)|[|]}
Modo de programación general¶
El Modo de programación general (MPG) sustituye las expresiones de plantilla por un programa escrito en el lenguaje de plantillas. La sintaxis del lenguaje está definida por la siguiente gramática:
program ::= 'program:' expression_list
expression_list ::= top_expression [ ';' top_expression ]*
top_expression ::= or_expression
or_expression ::= and_expression [ '||' and_expression ]*
and_expression ::= not_expression [ '&&' not_expression ]*
not_expression ::= [ '!' not_expression ]* | concatenate_expr
concatenate_expr::= compare_expr [ '&' compare_expr ]*
compare_expr ::= add_sub_expr [ compare_op add_sub_expr ]
compare_op ::= '==' | '!=' | '>=' | '>' | '<=' | '<' | 'in' | 'inlist' |
'==#' | '!=#' | '>=#' | '>#' | '<=#' | '<#'
add_sub_expr ::= times_div_expr [ add_sub_op times_div_expr ]*
add_sub_op ::= '+' | '-'
times_div_expr ::= unary_op_expr [ times_div_op unary_op_expr ]*
times_div_op ::= '*' | '/'
unary_op_expr ::= [ add_sub_op unary_op_expr ]* | expression
expression ::= identifier | constant | function | assignment | field_reference |
if_expr | for_expr | break_expr | continue_expr |
'(' expression_list ')' | function_def
field_reference ::= '$' [ '$' ] [ '#' ] identifier
identifier ::= id_start [ id_rest ]*
id_start ::= letter | underscore
id_rest ::= id_start | digit
constant ::= " string " | ' string ' | number
function ::= identifier '(' expression_list [ ',' expression_list ]* ')'
function_def ::= 'def' identifier '(' top_expression [ ',' top_expression ]* ')' ':'
expression_list 'fed'
assignment ::= identifier '=' top_expression
if_expr ::= 'if' condition 'then' expression_list
[ elif_expr ] [ 'else' expression_list ] 'fi'
condition ::= top_expression
elif_expr ::= 'elif' condition 'then' expression_list elif_expr | ''
for_expr ::= for_list | for_range
for_list ::= 'for' identifier 'in' list_expr
[ 'separator' separator_expr ] ':' expression_list 'rof'
for_range ::= 'for' identifier 'in' range_expr ':' expression_list 'rof'
range_expr ::= 'range' '(' [ start_expr ',' ] stop_expr
[ ',' step_expr [ ',' limit_expr ] ] ')'
list_expr ::= top_expression
break_expr ::= 'break'
continue_expr ::= 'continue'
separator_expr ::= top_expression
start_expr ::= top_expression
stop_expr ::= top_expression
step_expr ::= top_expression
limit_expr ::= top_expression
Notas:
una
top_expression
siempre tiene un valor. El valor de unaexpression_list
es el valor de la últimatop_expression
de la lista. Por ejemplo, el valor de laexpression_list
1;2;'blabla';3
es3
.En un contexto lógico, cualquier valor que no sea vacío es
True
(verdadero)En un contexto lógico, el valor vacío es
False
(falso)Textos y números pueden usarse indistintamente. Por ejemplo,
10
y'10'
son lo mismo.Los comentarios son líneas que empiezan por un carácter
#
. No se permiten comentarios que empiecen a mitad de línea.
Prioridad de operadores
La prioridad de los operadores (orden de evaluación) de mayor (se evalúa primero) a menor (se evalúa el último) es:
Llamadas a función, constantes, expresiones entre paréntesis, expresiones de declaración, expresiones de asignación, referencias de campo.
Más (
+
) y menos (-
) unarios. Estos operadores se evalúan de derecha a izquierda.Estas y todas las otras operaciones aritméticas devuelven enteros si la expresión resulta en una parte decimal igual a cero. Por ejemplo, si la expresión devuelve
3.0
se cambia a3
.Multiplicación (
*
) y división (/
). Estas operaciones son asociativas y se evalúan de izquierda a derecha. Use paréntesis si quiere cambiar el orden de evaluación.Suma (
+
) y resta (-
). Estas operaciones son asociativas y se evalúan de izquierda a derecha.Comparaciones numéricas y de textos. Estas operaciones devuelven
'1'
si la comparación tiene éxito, en caso contrario un texto vacío (''
). Las comparaciones no son asociativas:a < b < c
es un error de sintaxis.Concatenación de textos (
&
). El operador&
devuelve un texto formado por concatenación de las expresiones a su izquierda y derecha. Ejemplo:'aaa' & 'bbb'
devuelve'aaabbb'
. El operador es asociativo y se evalúa de izquierda a derecha.Negación lógica unaria (
!
). Esta operación devuelve'1'
si la expresión esFalse
(da como resultado un texto vacío), en caso contrario''
.Y lógico (
&&
). Esta operación devuelve'1'
si ambas expresiones a derecha e izquierda sonTrue
, o un texto vacío (''
) si alguna esFalse
. Es asociativa, se evalúa de izquierda a derecha y con cortocircuito https://chortle.ccsu.edu/java5/Notes/chap40/ch40_2.html.O lógico (
||
). Esta operación devuelve'1'
si alguna de las expresiones a derecha e izquierda esTrue
, o un''
si ambas sonFalse
. Es asociativa, se evalúa de izquierda a derecha y con cortocircuito https://chortle.ccsu.edu/java5/Notes/chap40/ch40_8.html.
Referencias de campo
Una field_reference
da como resultado el valor del campo de metadatos indicado por el nombre de búsqueda que sigue al $
o $$
. Usar $
es equivalente a usar la función field
. Usar $
es equivalente a usar la función raw_field
. Ejemplos:
* $authors ==> field('authors')
* $#genre ==> field('#genre')
* $$pubdate ==> raw_field('pubdate')
* $$#my_int ==> raw_field('#my_int')
Expresiones condicionales
Las expresiones condicionales (if_expression
) evalúan primero la condition
. Si la condition
es True
(un valor no vacío) entonces se evalúa expression_list
en la sentencia then
. Si es False
, entonces se evalúa expression_list
en la sentencia elif
o else
, si existen. Las partes elif
y else
son opcionales. Las palabras if
, then
, elif
, else
y fi
están reservadas, no pueden usarse como nombres de identificador. Se pueden añadir espacios y saltos de línea donde sea conveniente. La condition
es una top_expression
, no usa expression_list
, no se permite punto y coma. Los elementos de tipo expression_list
son secuencias de top_expression
separadas por punto y coma. Una expresión condicional devuelve el resultado de la última top_expression
en la expression_list
evaluada, o un texto vacío si no se evaluó ninguna expression_list
.
Ejemplos:
* 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)
Ejemplo de if
anidado:
program:
if field('series') then
if check_yes_no(field('#mybool'), '', '', '1') then
'yes'
else
'no'
fi
else
'no series'
fi
Como se ha mencionado, un if
produce un valor. Esto significa que todas las siguientes expresiones son equivalentes:
* 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
Como último ejemplo, este programa devuelve el valor de la columna series
si el libro tiene una serie, en caso contrario el valor de la columna title
:
program: field(if field('series') then 'series' else 'title' fi)
Expresiones de bucle
Una expresión de bucle (for_expression
) itera sobre una lista de valores, procesando uno cada vez. La list_expression
debe resultar en el nombre de búsqueda
de un campo de metadatos, como tags
o #genero
, o una lista de valores. La función range() (ver más adelante) genera una lista de números. Si el resultado es un nombre de búsqueda
válido, se obtiene el valor del campo y se usa el separador especificado para ese tipo de campo. Si el resultado no es un nombre de búsqueda
válido, se supone que es una lista de valores. La lista se supone separada por comas, a no ser que use la palabra clave opcional separator
, en ese caso los valores de la lista deben estar separados por el resultado de evaluar separator_expr
. No se puede usar un separador si la lista es generada por range()
. Cada valor de la lista se asigna a la variable especificada y luego se evalúa expression_list
. Puede usar break
para salir del bucle y continue
para comenzar con la siguiente iteración.
Ejemplo: Esta plantilla elimina el primer nombre jerárquico para cada valor de Género (#genre`
), construyendo una lista con los nuevos nombres.
program:
new_tags = '';
for i in '#genre':
j = re(i, '^.*?\.(.*)$', '\1');
new_tags = list_union(new_tags, j, ',')
rof;
new_tags
Si el Género original es Historia.Militar, Ciencia ficción.Historia alternativa, Léeme, la plantilla devolverá Militar, Historia alternativa, Léeme. Puede usar esta plantilla en Modificar metadatos en masa > Buscar y sustituir con Buscar establecido en plantilla
para eliminar el primer nivel de la jerarquía y asignar el valor resultante a Género.
Nota: la última línea en la plantilla, new_tags
, no es estrictamente necesaria en este caso, porque for
devuelve el valor de la última top_expression
en expression_list
. El valor de una asignación (assignment
) es el valor de su expresión, así que el valor del for
es lo que se asignó a new_tags
.
Definición de funciones
Si tiene una parte del código en una plantilla que se repite, puede poner ese código en una función local. La palabra clave def
comienza la definición. Le sigue el nombre de la función, la lista de argumentos y el código en la función. La definición de función termina con la palabra clave fed
.
Los argumentos son posicionales. Cuando se invoca una función, los argumentos proporcionados se hacen corresponder de izquierda a derecha con los parámetros definidos, con el valor del argumento asignado al parámetro. Es un error proporcionar más argumentos que parámetros definidos. Los parámetros pueden tener valores predeterminados, como a = 25
. Si no se proporciona un argumento para un parámetro, se usará el valor predeterminado, en caso contrario el parámetro será un texto vacío.
La instrucción return
se puede usar en una función local.
Una función debe definirse antes de poder usarse.
Ejemplo: Esta plantilla calcula una duración aproximada en años, meses y días a partir de un número de días. La función to_plural()
da formato a los valores calculados. Tenga en cuenta que el ejemplo también usa el operador &
:
program:
days = 2112;
years = floor(days/360);
months = floor(mod(days, 360)/30);
days = days - ((years*360) + (months * 30));
def to_plural(v, str):
if v == 0 then return '' fi;
return v & ' ' & (if v == 1 then str else str & 's' fi) & ' '
fed;
to_plural(years, 'year') & to_plural(months, 'month') & to_plural(days,'day')
Operadores de relación
Los operadores de relación devuelven '1'
si la comparación es cierta, en caso contrario devuelven un texto vacío (''
).
Hay dos formas de operadores de relación: comparaciones de texto y comparaciones numéricas.
Las comparaciones de texto usan el orden lexicográfico y no distinguen mayúsculas y minúsculas. Las comparaciones de texto permitidas son ==
, !=
, <
, <=
, >
, >=
, in
e inlist
. El operador in
es True
si el valor de la expresión de la izquierda, interpretado como una expresión regular, coincide con el valor de la expresión de la derecha. El operador inlist
es True
si el valor de la expresión de la izquierda, interpretado como una expresión regular coincide con alguno de los elementos de la lista de la derecha, en la que los elementos están separados por comas. Las comparaciones no distinguen mayúsculas y minúsculas.
Los operadores de comparación numérica son ==#
, !=#
, <#
, <=#
, >#
y >=#
. Las expresiones de la izquierda y la derecha deben resultar en valores numéricos con dos excepciones: Tanto el valor textual None
(campo no definido) como el texto vacío equivalen al valor cero.
Ejemplos:
program: field('series') == 'lala'
devuelve'1'
si la serie del libro es lala, en caso contrario devuelve''
.
program: 'l.a' in field('series')
devuelve'1'
si la serie del libro coincide con la expresión regularl..a
(por ejemplo, lala, El asesino de reyes, etc.), en caso contrario devuelve''
.
program: 'ciencia' inlist field('#genero')
devuelve'1'
si alguno de los géneros del libro coincide con la expresión regularciencia
(por ejemplo Ciencia, Historia de la ciencia, Ciencia ficción, etc.), en caso contrario devuelve''
.
program: '^ciencia$' inlist field('#genero')
devuelve'1'
si alguno de los géneros del libro coincide con la expresión regular^ciencia$
(por ejemplo Ciencia). Los géneros Historia de la ciencia y Ciencia ficción no coinciden. Si no hay ninguna coincidencia, devuelve''
.
program: if field('series') != 'lala' then 'nana' else 'blabla' fi
devuelve'nana'
si la serie del libro no es lala, en caso contrario devuelve'blabla'
.
program: if field('series') == 'lala' || field('series') == '1632' then 'sí' else 'no' fi
devuelve'sí'
si la serie es lala o 1632, en caso contrario devuelve'no'
.
program: if '^(lala|1632)$' in field('series') then 'sí' else 'no' fi
devuelve'sí'
si la serie es lala o 1632, en caso contrario devuelve'no'
.
program: if 11 > 2 then 'sí' else 'no' fi
devuelve'no'
porque el operador>
realiza una comparación lexicográfica.
program: if 11 ># 2 then 'sí' else 'no' fi
devuelve'sí'
porque el operador>#
realiza una comparación numérica.
Otras funciones disponibles
Las siguientes funciones están disponibles, además de las descritas en el modo de función única.
En el MPG todas las funciones descritas en el modo de función única requieren un primer argumento adicional que especifique el valor sobre el que operan. Todos los argumentos son de tipo expression_list
(ver la gramática más arriba).
add(x [, y]*)
– devuelve la suma de sus argumentos. Da un error si algún argumento no es un número. En la mayoría de los casos puede usarse el operador+
en lugar de esta función.and(valor [, valor]*)
– devuelve'1'
si todos los valores son no vacíos, en caso contrario devuelve un texto vacío. Pueden usarse tantos valores como se desee. En la mayoría de los caso se puede usar el operador&&
en lugar de esta función. Un motivo para no sustituirand
por&&
es cuando la evaluación en cortocircuito puede cambiar el resultado debido a los efectos secundarios. Por ejemplo,and(a='',b=5)
realizará las dos asignaciones, mientra que el operador&&
no realizará la segunda.assign(id, val)
– asignaval
aid
y devuelveval
.id
debe ser un identificador, no una expresión. En la mayoría de los casos puede usarse el operador=
en lugar de esta función.approximate_formats()
– devuelve una lista separada por comas de formatos asociados con el libro. No hay garantía de que esta lista sea correcta, aunque probablemente lo sea. Esta función, y otras que no tienen argumentos, puede usarse en el modo de programación de plantillas (ver más adelante) usando la plantilla{:'approximate_formats()'}
. Tenga en cuenta que los nombres de formato resultantes están siempre en mayúsculas, como en «EPUB». La funciónapproximate_formats()
es bastante más rápida que las funcionesformats_...
que se discuten más adelante.author_links(val_separator, pair_separator)
– devuelve un texto que contiene una lista de autores y los enlaces de dichos autores de la forma:author1 val_separator author1_link pair_separator author2 val_separator author2_link etc.
Cada autor está separado de su correspondiente enlace por el texto
val_separator
, sin espacios adicionales. Los paresauthor:linkvalue
están separados por el textopair_separator
, 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 información autores (diferente del valor de orden de autor del libro). La lista devuelta es de la formaorden_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 deseparador
, inclúyalos en el valor deseparador
.book_count(consulta, usar_bv)
– devuelve el número de libros encontrados al buscarconsulta
. Siusar_bv
es0
(cero), no se tienen en cuenta las bibliotecas virtuales. Esta función y su complementobook_values()
son especialmente útiles en búsquedas de plantilla, permitiendo búsquedas que combinan la información de varios libros, como buscar series con un solo libro. No puede usarse en columnas compuestas, a no ser que que el ajusteallow_template_database_functions_in_composites
sea True. Sólo puede usarse en la interfaz gráfica.Por ejemplo, esta búsqueda de plantilla usa esta función y su complemento para encontrar todas las series con un solo libro:
Definir una plantilla guardada (usando Preferencias > Avanzado > Funciones de plantilla) llamada
series_only_one_book
(el nombre es arbitrario). La plantilla es:program: vals = globals(vals=''); if !vals then all_series = book_values('series', 'series:true', ',', 0); for series in all_series: if book_count('series:="' & series & '"', 0) == 1 then vals = list_join(',', vals, ',', series, ',') fi rof; set_globals(vals) fi; str_in_list(vals, ',', $series, 1, '')
La primera vez que se ejecuta esta plantilla (el primer libro que se comprueba) se almacenan los resultados de la búsqueda en la base de datos en una variable de plantilla
global
llamadavals
. Estos resultados se usan para comprobar los siguientes libros sin volver a realizar la búsqueda.Usar la plantilla guardada en una búsqueda de plantilla:
template:"program: series_only_one_book()#@#:n:1"
Al usar una plantilla guardada en lugar de poner la plantilla en la búsqueda. se evitan problemas causados por la necesidad de escapar las comillas en las expresiones de búsqueda.
book_values(columna, consulta, sep, usar_bv)
– devuelve una lista de valores únicos contenidos en la columnacolumna
(un nombre de consulta), separados porsep
, de los libros encontrados al buscarconsulta
. Siusar_bv
es0
(cero), no se tienen en cuenta las bibliotecas virtuales. Esta función y su complementobook_count()
son especialmente útiles en búsquedas de plantilla, permitiendo búsquedas que combinan la información de varios libros, como buscar series con un solo libro. No puede usarse en columnas compuestas, a no ser que que el ajusteallow_template_database_functions_in_composites
sea True. Sólo puede usarse en la interfaz gráfica.booksize()
– devuelve el valor del campo «tamaño» de calibre. Devuelve''
si no hay formatos.check_yes_no(nombre_de_campo, no_definido, es_false, es_true)
– comprueba si el valor del campo de tipo sí o no identificado por el nombre de búsquedanombre_de campo
es uno de los valores especificado en los parámetros. Devuelve “”yes”` si coincide, y un texto vació en caso contrario. Establezca el parámetrono_definido
,es_false
oes_true
a 1 (el número) para comprobar dicha condición, en caso contrario establézcalos a 0. Ejemplo:check_yes_no("#bool", 1, 0, 1)
devuelve'Yes'
si el campo de sí o no#bool
esTrue
o no definido (niTrue
niFalse
).Más de uno de entre
no_definido
,es_false
yes_true
pueden ser 1.ceiling(x)
– devuelve el menor entero que es mayor o igual ax
. Da un error six
no es un número.character(nombre_carácter)
– devuelve el carácter con nombrenombre_carácter
. Por ejemplo,character('newline')
devuelve un carácter de salto de línea ('\n'
”). Los nombres de carácter admitidos sonnewline
(salto de línea),return
(retorno de carro),tab
(tabulación) ybackslash
(barra invertida).cmp(x, y, mn, ig, my)
– comparax
ey
después de convertirlas en números. Devuelvemn
six <# y
,ig
six ==# y
ymy
en caso contrario. Esta función puede sustituirse normalmente por uno de los operadores de comparación numérica (==#
,<#
,>#
, etc.).connected_device_name(ubicación_de_almacenamiento)
– si hay un dispositivo conectado, devuelve el nombre del dispositivo, en caso contrario devuelve un texto vacío. Cada ubicación de almacenamiento de un dispositivo tiene un nombre diferente. Los nombres deubicación_de_almacenamiento
son'main'
,'carda'
y'cardb'
. Esta función sólo está disponible en la interfaz gráfica.connected_device_uuid(ubicación_de_almacenamiento)
– si un dispositivo está conectado, entonces devuelve el uuid (identificador único) del dispositivo, de lo contrario devuelve un texto vacío. Cada ubicación de almacenamiento de un dispositivo tiene un uuid diferente. Los nombres deubicación_de_almacenamiento
son'main'
,'carda'
y'cardb'
. Esta función sólo está disponible en la interfaz gráfica.current_library_name()
– devuelve la última parte de la ruta a la biblioteca de calibre actual.current_library_path()
– devuelve la ruta completa a la biblioteca de calibre actual.current_virtual_library_name()
– devuelve el nombre de la biblioteca virtual actual si hay alguna, en caso contrario devuelve un texto vacío. Se conservan mayúsculas y minúsculas. Ejemplo:program: current_virtual_library_name()
. Esta función sólo funciona en la interfaz gráfica.date_arithmetic(fecha, cálculo, fmt)
– Calcula una nueva fecha a partir defecha
usandocálculo
. Devuelve la nueva fecha con el formato opcionalfmt
: si so se proporciona, el resultado estará en formato ISO. El argumentocálculo
es un texto formado por paresvQ
(valorQué
) dondev
es un número que puede ser negativo yQ
es una de las letras siguientes:s
: añadev
segundos afecha
m
: añadev
minutos afecha
h
: añadev
horas afecha
d
: añadev
días afecha
w
: añadev
semanas afecha
y
: añadev
años afecha
, donde un año son 365 días.
Ejemplo:
'1s3d-1m'
añade 1 segundo, añade 3 días y resta 1 minuto afecha
.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)
– devuelvex / y
. Da un error six
oy
no son números. Esta función puede sustituirse a menudo por el operador/
.eval(texto)
– evalúa texto como un programa, pasando las variables locales. Esto permite usar el procesador de plantillas para elaborar resultados complejos a partir de variables locales. En el modo de programación de plantillas, dado que los caracteres{
y}
se interpretan antes de evaluar la plantilla, 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 pueden usarse en el argumento de esta función en el modo de programación de plantillas.extra_file_size(nombre_archivo)
– devuelve el tamaño en bytes del archivo adicionalnombre_archivo
en la carpetadata/
del libro si existe, o-1
en caso contrario. Ver también las funcioneshas_extra_files()
,extra_file_names()
yextra_file_modtime()
. Esta función sólo puede usarse en la interfaz gráfica.extra_file_modtime(nombre_archivo, texto_formato)
– devuelve la fecha (y hora) de modificación del archivo adicionalnombre_archivo
en la carpetadata/
del libro si existe, o-1
en caso contrario. El formato de la fecha se especifica entexto_formato
(verformat_date()
para más detalles). Sitexto_formato
es un texto vacío, devuelve la fecha de modificación como un número real de segundos desde el inicio de la época. Ver también las funcioneshas_extra_files()
,extra_file_names()
yextra_file_size()
. El inicio de la época depende del sistema operativo. Esta función sólo puede usarse en la interfaz gráfica.extra_file_names(sep [, patrón])
devuelve una lista separada porsep
de archivos adicionales en la carpetadata/
del libro. Si el argumento opcionalpatrón
(una expresión regular) está presente, la lista contiene sólo archivos que coinciden conpatrón
. La coincidencia no distingue mayúsculas y minúsculas. Ver también las funcioneshas_extra_files()
,extra_file_modtime()
yextra_file_size()
. Esta función sólo puede usarse en la interfaz gráfica.field(nombre_de_búsqueda)
– devuelve el campo de metadatos identificado pornombre_de_búsqueda
.field_exists(nombre_campo)
– comprueba si existe un campo (columna) con el nombre de búsquedanombre_campo
, devuelve'1'
si es así y un texto vacío si no.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 a plantillas MPG. 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') )
first_matching_cmp(val, [ cmp, resultado, ]* otro_resultado)
– comparaval < cmp
consecutivamente y devuelve elresultado
correspondiente a la primera comparación que sea cierta. Devuelveotro_resultado
si ninguna comparación es cierta. Ejemplo:i = 10; first_matching_cmp(i,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 primervalor
que no esté vacío. Si todos los valores están vacíos, se devuelve también un texto vacío. Puede incluir tantos valores como quiera.floor(x)
– devuelve el mayor entero que es menor o igual ax
. Da un error six
no es un número.format_date(val, formato_fecha)
– da formato a un valor, que debe ser un texto de fecha, según formato_fecha y devuelve un texto. Los códigos de formato son:d
: el día del mes como un número sin cero a la izquierda (de 1 a 31)dd
: el día del mes como un número con cero a la izquierda (de 01 a 31)ddd
: el nombre del día de la semana traducido y abreviado (por ejemplo, de «lun» a «dom»)dddd
: el nombre del día de la semana completo traducido (por ejemplo, de «lunes» a «domingo»)M
: el mes como un número, sin cero a la izquierda (de 1 a 12)MM
: el mes como un número con cero a la izquierda (de 01 a 12)MMM
: el nombre del mes traducido y abreviado (por ejemplo, de «ene» a «dic»)MMMM
: el nombre del mes completo traducido (por ejemplo, de «enero» a «diciembre»)yy
: el año como un número de dos dígitos (de 00 a 99)yyyy
: el año como un número de cuatro dígitos.h
: la hora sin cero a la izquierda (de 0 a 11 o de 0 a 23, según am/pm)hh
: la hora con un cero a la izquierda (de 00 a 11 o de 00 a 23, según am7pm)m
: el minuto sin cero a la izquierda (de 0 a 59)mm
: el minuto con cero a la izquierda (de 00 a 59)s
: el segundo sin cero a la izquierda (de 0 a 59)s
: el segundo con cero a la izquierda (de 00 a 59)ap
: se usa un reloj de 12 horas en lugar de 24, conap
sustuido por el text traducido para «am» o «pm».AP
: se usa un reloj de 12 horas en lugar de 24, conAP
sustuido por el text traducido para «AM» o «PM».iso
: la fecha con hora y zona horaria. Debe ser el único formato presenteto_number
: convierte la fecha y hora en un número décimal (un «código de tiempo»)from_number
: convierte un número decimal (un «código de tiempo») en una fecha con formatoiso
. Si desea un formato diferente, añada el texto de formato desado depués defrom_number
y dos puntos (:
). Ejemplo:from_number:dd MMM yyyy
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 de fecha para incluir
MMMM
. En este caso, en lugar de usar la funciónfield()
como en:format_date(field('pubdate'), 'yyyy')
use la función
raw_field()
, como en:format_date(raw_field('pubdate'), 'yyyy')
format_date_field(nombre_campo, texto_formato)
– da formato al valor en el camponombre_campo
, que debe ser el nombre de búsqueda de un campo de fecha, ya sea estándar o personalizado. Verformat_date()
para los códigos de formato. Esta función es mucho más rápida que format_date y debe usarse cuando se esté dando formato al valor en un campo (columna). No puede usarse con fechas calculadas o variables de texto. Ejemplos:format_date_field('pubdate', 'yyyy.MM.dd') format_date_field('#date_read', 'MMM dd, yyyy')
formats_modtimes(formato_fecha)
– devuelve una lista separada por comas de elementos separados por dos puntos (FMT:FECHA
) que contienan las fechas de modificación para los formatos de un libro. El argumentoformato_fecha
especifica cómo se da formato a la fecha. Véase la funciónformat_date
para más detalles. Puede usar la funciónselect
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 (FMT:RUTA
) que contienen la ruta completa a los formatos de un libro. Puede usar la funciónselect
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 separada por comas de elementos separados por dos puntos (FMT:TAMAÑO
) que contienen los tamaños en bytes de los formatos de un libro. Puede usar la funciónselect
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».fractional_part(x)
– devuelve el valor tras el punto decimal. Por ejemplo,fractional_part(3.14)
devuelve0.14
. Da un error six
no es un número.get_link(nombre_campo, valor_campo)
– obtiene el enlace para el camponombre_campo
con el valorvalor_campo
. Si no hay ningún enlace asociado, devuelve un texto vacío. Ejemplos:
Lo siguiente devuelve el enlace asociado con la etiqueta
Fiction
:get_link('tags', 'Fiction')Esta plantilla hace una lista de los enlaces para todas las etiquetas asociadas con un libro, de la forma
valor:enlace, ...
:program: ans = ''; for t in $tags: l = get_link('tags', t); if l then ans = list_join(', ', ans, ',', t & ':' & get_link('tags', t), ',') fi rof; ans
get_note(field_name, field_value, plain_text)
– fetch the note for field “field_name” with value “field_value”. If plain_text is empty, return the note’s HTML including images. If plain_text is 1 (or “1”), return the note’s plain text. If the note doesn’t exist, return the empty string in both cases. Example:
Return the HTML of the note attached to the tag Fiction:
program: get_note('tags', 'Fiction', '')Return the plain text of the note attached to the author Isaac Asimov:
program: get_note('authors', 'Isaac Asimov', 1)
has_cover()
– devuelve'Yes'
si el libro tiene portada, en caso contrario devuelve un texto vacío.has_extra_files([patrón])
devuelve el número de archivos adicionales o''
(un texto vacío). Si el argumento opcionalpatrón
(una expresión regular) está presente, sólo se cuentan archivos que coinciden conpatrón
. La coincidencia no distingue mayúsculas y minúsculas. Ver también las funcionesextra_file_names()
,extra_file_modtime()
yextra_file_size()
. Esta función sólo puede usarse en la interfaz gráfica.identifier_in_list(val, nombre_id [, val_encontrado, val_no_encontrado])
– trataval
como una lista de identificadores separados por comas. Un identificador tiene el formatonombre_id:valor
. El parámetronombre_id
es el texto de nombre de identificador a buscar, ya seanombre_id
onombre_id:expreg
. El primer caso coincide si hay algún identificador con ese nombre. El segundo caso coincide si algún identificador tiene ese nombre y la expresión regular coincide con el valor del identificador. Si se proporcionanval_encontrado
yval_no_encontrado
, si hay una coincidencia, se devuelveval_encontrado
; de lo contrario, se devuelveval_no_encontrado
. Sival_encontrado
yval_no_encontrado
están ausentes, si hay alguna coincidencia, se devuelve el paridentificador:valor
; de lo contrario, el texto vacío (''
).is_marked()
– comprueba si el libro está «marcado» en calibre, Si lo está, devuelve el valor de la marca, bien'true'
(en minúsculas) o bien una lista separada por comas de los nombres de marca. Devuelve''
(un texto vacío) si el libro no está marcado. Esta función sólo está disponible en la interfaz gráfica.language_codes(nombres)
– devuelve los códigos de idioma correspondientes anombres
. Los nombres deben estar en el idioma actual. El argumentonombres
es una lista separada por comas.list_contains(valor, separador, [ patrón, encontrado, ]* no_encontrado)
– (Sinónimo dein_list
) Interpreta el campo como una lista de elementos separados porseparador
y evalúapatrón
con cada valor de la lista. Sipatrón
coincide con alguno de los elementos de la lista, devuelveencontrado
, en caso contrario devuelveno_encontrado
. Los argumentospatrón
yencontrado
pueden repetirse tantas veces como se desee, lo que permite devolver diferentes valores según la búsqueda. Los patrones se evalúan en orden. Se devuelve la primera coincidencia. Sinónimos:in_list()
,list_contains()
list_count(valor, separador)
– interpretavalor
como una lista de elementos separados por ``separador`` y devuelve el número de elementos de la lista. Sinónimos:count()
,list_count()
list_count_matching(lista, patrón, separador)
– interpretalista
como una lista de elementos separados por `separador` y devuelve el número de elementos de la lista que coinciden con la expresión regularpatrón
. Sinónimos:list-count_matching()
,count_matching()
list_difference(lista1, lista2, separador)
– devuelve una lista construida eliminando delista1
cualquier elemento que aparezca enlista2
, sin distinguir mayúsculas y minúsculas. Los elementos delista1
ylista2
están separados porseparador
, así como los de la lista resultante.list_equals(lista1, sep1, lista2, sep2, val_sí, val_no)
– devuelveval_sí
silista1
ylista2
contienen los mismos elementos, en caso contrario devuelveval_no
. Los elementos se determinan dividiendo cada lista por el correspondiente carácter separador (sep1
osep2
). 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 delista1
cualquier elemento que no aparezca enlista2
, sin distinguir mayúsculas y minúsculas. Los elementos delista1
ylista2
están separados porseparador
, así como los de la lista resultante.list_join(con_separador, lista1, separador1 [, lista2, separador2]*)
– devuelve una lista formada por unión de los elementos en las listas de origen (lista1
, etc.) usandocon_separador
entre los elementos de la lista resultante. Los elementos de cada lista de origenlista[123...]
están separador por el correspondienteseparador[123...]
. Una lista puede contener cero elementos. Puede ser un campo comopublisher
que contiene un solo valor, una lista de un elemento en la práctica. Los duplicados se eliminan sin distinción de mayúsculas y minúsculas. Los elementos se devuelven en el orden en que aparecen en las listas de origen. Si los elementos difieren sólo en mayúsculas y minúsculas, se usa la última aparición. Todos los separadores pueden ser de más de un carácter.Ejemplo:
program: list_join('#@#', $authors, '&', $tags, ',')
Puede usar
list_join
sobre los resultados de ejecuciones previas delist_join
de la siguiente manera:program: a = list_join('#@#', $authors, '&', $tags, ','); b = list_join('#@#', a, '#@#', $#genre, ',', $#people, '&', 'some value', ',')
Puede usar expresiones para generar una lista. Por ejemplo, supongamos que quiere los elementos de
authors
y#genre
, pero con estos últimos reemplazados por la palabra ``Genre: `` seguida de la primera letra del elemento, es decir con «Ficción» convertido en «Genre: F». Esto se consigue con lo siguiente:program: list_join('#@#', $authors, '&', list_re($#genre, ',', '^(.).*$', 'Genre: \1'), ',')
list_re(lista_orig, separador, incluir, sust_opc)
– construye una lista separando primerolista_orig
en elementos usando el carácterseparador
. Para cada elemento en la lista, comprueba si coincide con la expresión regularincluir
. Si coincide, se añade a la lista final. Sisust_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]*)
– comolist_re
, pero las sustituciones no son opcionales. Usare_group(elemento, búsqueda, plantilla_grupo ...)
para hacer sustituciones..list_remove_duplicates(lista, separador)
– devuelve una lista construida por eliminación de los duplicados enlista
. No distingue mayúsculas y minúsculas, se mantiene la última versión. Los elementos delista
están separados porseparador
, así como los de la lista resultante.list_sort(lista, dirección, separador)
– devuelvelista
ordenada lexicográficamente sin distinción de mayúsculas y minúsculas. Sidirección
es cero, la lista se ordena de manera ascendente, en caso contrario, de manera descendente. Los elementos delista
están separados porseparador
, así como los de la lista resultante.list_split(lista, sep, prefijo_id)
– divide lalista
en valores separados porsep
y asigna los valores a variables locales con nombreprefijo_id_N
, dondeN
es la posición del valor en la lista. El primer elemento tiene posición 0 (cero). La función devuelve el último elemento de la lista.Ejemplo:
list_split('one:two:foo', ':', 'var')
es equivalente a:
var_0 = 'one'; var_1 = 'two'; var_2 = 'foo
list_union(lista1, lista2, separador)
– devuelve una lista construida por combinación de los elementos enlista1
ylista2
, eliminando los duplicados delista2
(no distingue mayúsculas y minúsculas, se mantiene la versión delista1
). Los elementos delista1
ylista2
están separados porseparador
, así como los de la lista resultante. Sinónimos:merge_list()
,list_union()
mod(x, y)
– devuelvefloor
del resto dex / y
. Da un error six
oy
no son números.multiply(x [, y]*)
– devuelve el producto de sus argumentos. Da un error si algún argumento no es un número. Esta función puede sustituirse a menudo por el operador*
.not(valor)
– devuelve el texto'1'
si el valor está vacío, en caso contrario, devuelve un texto vacío. Esta función puede sustituirse a menudo por el operador de negación unario (!
).ondevice()
– devuelve el texto'Yes'
siondevice
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. Pueden incluirse tantos valores como se desee. Esta función puede sustituirse a menudo por el operador||
. Un motivo para no sustituirla es si la evaluación en cortocircuito puede cambiar los resultados debido a efectos secundarios.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
). La funciónprint
siempre devuelve su primer argumento.
range(inicio, fin, paso, límite)
– devuelve una lista de números generados por iteración en el intervalo especificado por los argumentosinicio
,fin
ypaso
, con una longitud máxima delímite
. El primer elemento generado esinicio
. Los valores siguientes sonvalor_sig = valor_act + paso
. El proceso continúa mientrasvalor_sig < fin
, suponiendo quepaso
sea positivo, en caso contrario mientrasvalor_sig > fin
. Siinicio
no cumple la condición, es decir siinicio >= fin
(en caso de quepaso
sea positivo), se devuelve una lista vacía. Ellímite
establece la longitud máxima de la lista y tiene un valor predeterminado de 1000. Los argumentosinicio
,paso
ylímite
son opcionales. Si se ejecutarange()
con un argumento, se interpreta comofin
. Dos argumentos especificaninicio
yfin
. Tres argumentos especificaninicio
,fin
ypaso
. Cuatro argumentos especificaninicio
,fin
,paso
ylímite
. Ejemplos:range(5) -> '0, 1, 2, 3, 4' range(0, 5) -> '0, 1, 2, 3, 4' range(-1, 5) -> '-1, 0, 1, 2, 3, 4' range(1, 5) -> '1, 2, 3, 4' range(1, 5, 2) -> '1, 3' range(1, 5, 2, 5) -> '1, 3' range(1, 5, 2, 1) -> error(limit exceeded)
raw_field(nombre_de_búsqueda [, predeterminado_opcional])
– devuelve el campo de metadatos nombrado pornombre_de_búsqueda
sin aplicar ningún formato. Evalúa y devuelve el segundo argumento opcionalpredeterminado_opcional
si el campo no está definido (None
).raw_list(nombre_de_búsqueda, separador)
– devuelve la lista de metadatos nombrada pornombre_de_búsqueda
sin aplicar ningún formato ni ordenación, con los elementos separados porseparador
.re_group(valor, patrón [, plantilla_para_grupo]*)
– devuelve un texto formado por aplicación de la expresión regularpatrón
avalor
, sustituyendo cada coincidencia con el texto devuelto por la correspondiente plantilla. En el modo de programación de plantillas, como en las funcionestemplate
yeval
, debe usarse[[
en lugar de{
y]]
en lugar de}
.El siguiente ejemplo busca una serie con más de una palabra y pone la primera en mayúsculas:
program: re_group(field('series'), "(\S* )(.*)", "{$:uppercase()}", "{$}")'}
round(x)
– devuelve el entero más cercano ax
. Da un error six
no es un número.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 inicialmentetexto1
. Se van añadiendo textos formados por parejasprefijo
,texto
al final del valor mientras la longitud del resultado sea menor quemáx
. Los prefijos pueden estar vacíos. El resultado es siempre al menostexto1
, aunque su longitud sea mayor quemáx
. Pueden especificarse tantas parejasprefijo
,texto
como se desee.strcmp(x, y, mn, ig, my)
– hace una comparación lexicográfica sin distinción de mayúsculas y minúsculas entrex
ey
como textos. Devuelvemn
six < y
,ig
six == y
,my
en otros casos. Esta función puede sustituirse a menudo por los operadores de comparación lexicográfica (==
,>
,<
, etc.)strcmpcase(x, y, mn, ig, my)
– hace una comparación con distinción de mayúsculas y minúsculas entrex
ey
. Devuelvemn
six < y
. Devuelveig
six = y
, omy
en caso contrario.Atención: Éste NO es el comportamiento predeterminado usado por calibre, por ejemplo, en los operadores de comparación léxica (
==
,>
,<
, etc.). Esta función podría dar resultados inesperados, use preferentementestrcmp()
siempre que sea posible.strlen(valor)
– Devuelve la longitud del textovalor
.substr(texto, inicio, fin)
– devuelve los caracteres entre la posicióninicio
yfin
detexto
. El primer carácter detexto
está en la posición cero. Sifin
es negativo, entonces indica la posición contando desde la derecha. Sifin
es cero, indica el último carácter. Por ejemplo,substr('12345', 1, 0)
devuelve2345
, ysubstr('12345', 1, -1)
devuelve234
.subtract(x, y)
– devuelvex - y
. Da un error six
oy
no son números. Esta función puede sustituirse a menudo por el operador-
.switch_if([expresión_de prueba, expresión_de_valor,]+ otra_expresión)
– para cada parexpresión_de_prueba, expresión_de_valor
, comprueba siexpresión_de_prueba
es True (no vacía) y, de ser así, devuelve el resultado deexpresión_de_valor
. Si ningunaexpresión_de_prueba
es True, se devuelve el resultado deotra_expresión
. Puede haber tantos paresexpresión_de_prueba, expresión_de_valor
como se desee.today()
– devuelve un texto para la fecha y hora hoy (ahora). Este valor está preparado para usarse conformat_date
odays_between
, pero puede manipularse como cualquier otro texto. La fecha está en formato ISO.template(x)
– evalúax
como una plantilla. La evaluación se hace en su propio contexto, lo que significa que las variables no comparten entre quien llama a la función y la evaluación de la plantilla.to_hex(val)
– devuelve el textoval
codificado en hexadecimal. Esto es útil al construir URL de calibre.urls_from_identifiers(identificadores, ordenar_resultado)
– dada una lista deidentificadores
separados por comas, donde cada identificador es un par de valores separados por dos puntos (nombre_id:valor_id
), devuelve una lista de URL HTML separados por comas, generados a partir de los identificadores. La lista no está ordenada siordenar_resultado
es0
(carácter o número), en caso contrario se ordena alfabéticamente según el nombre del identificador. Los URL se generan de la misma manera que la columna predefinida de identificadores cuando se muestra en Detalles del libro.
Programas más complejos en expresiones de plantilla: modo de programación de plantillas¶
El modo de programación de plantillas (MPP) es una mezcla entre el modo de programación general y el modo de función única. El MPP se diferencia del modo de función única en que permite escribir expresiones de plantilla que hacen referencia a otros campos de metadatos, usar funciones anidadas, modificar variables y hacer operaciones aritméticas. Se diferencia del modo de programación general en que la plantilla está entre caracteres {
y }
y no empieza por la palabra program
. La parte del programa de la plantilla es una expression_list
del modo de programación general.
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 de función única, porque no se puede hacer referencia a otro campo en la expresión de la plantilla. En el MPP sí se puede. La siguiente expresión lo demuestra:
{#series:'ifempty($, field('#genre'))'}
El ejemplo muestra varias cosas:
El MPP se usa si la expresión empieza por
:'
y termina en'}
. Cualquier otra cosa se supone que corresponde al modo de función única.la variable
$
representa el campo nombrado en la plantilla sobre la 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.
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"
.
Todas las funciones descritas en el modo de función única y en el modo de programación general pueden usarse en el MPP.
En el MPP, usar los caracteres {
y }
en textos literales puede conducir a errores o resultados inesperados porque confunden al procesador de plantillas. Éste intenta interpretarlos como límites de expresiones de plantilla y no como caracteres. En algunos casos, pero no todos, puede sustituir un {
por [[
y un }
por ]]
. En general, si un program contiene caracteres {
y }
, debería usar el modo de programación general.
Como en el modo de programación general, para las funciones descritas en el modo de función única debe proporcionar el valor sobre el que opera la función como primer argumento, además de los argumentos descritos. En el MPP puede usar $
para acceder al valor especificado por el nombre de búsqueda
de la expresión de plantilla.
Modo de plantilla de Python¶
El modo de plantilla de Python (MPPy) le permite escribir plantillas usando el lenguaje Python nativo y la interfaz de programación de calibre. La interfaz de programación de base de datos será la más útil, pero en este manual no se discutirán más detalles. Las plantillas MPPy son más rápidas y pueden realizar operaciones más complicadas, pero debe saber escribir código Python usando la interfaz de programación de calibre.
Una plantilla MPPy empieza por:
python:
def evaluate(book, context):
# book is a calibre metadata object
# context is an instance of calibre.utils.formatter.PythonTemplateContext,
# which currently contains the following attributes:
# db: a calibre legacy database object.
# globals: the template global variable dictionary.
# arguments: is a list of arguments if the template is called by a GPM template, otherwise None.
# funcs: used to call Built-in/User functions and Stored GPM/Python templates.
# Example: context.funcs.list_re_group()
# your Python code goes here
return 'a string'
Puede añadir el texto anterior a la plantilla usando el menú contextual, al que normalmente se accede pulsando el botón derecho. Los comentarios no son importantes y pueden eliminarse. Debe usar la sangría de Python.
El objeto de contexto admite str(context)
, que devuelve un texto con el contenido del contexto y context.attributes
, que devuelve una lista con los nombres de los atributos del contexto.
El atributo context.funcs
le permite invocar funciones incorporadas y de usuario, así como plantillas guardadas MPG o Python, de manera que puede ejecutarlas directamente en el código. Las funciones se identifican por sus nombres. Si el nombre entra en conflicto con una palabra clave de Python, añada un guión bajo al final. Ejemplos:
context.funcs.list_re_group()
context.funcs.assert_()
He aquí un ejemplo de una plantilla MPPy que genera una lista de todos los autores de una serie. La lista se guarda en una Columna generada a partir de otras columnas, funciona como etiquetas. Se muestra en los detalles del libro y tiene la opción en líneas separadas activada (en Preferencias > Apariencia > Detalles del libro). Esta opción requiere que la lista esté separada por comas. Para satisfacer este requisito la plantilla convierte las comas en los nombres de autor a punto y coma y luego construye una lista de autores separados por comas. Los autores se ordenan, razón por la cual la plantilla usa author_sort.
python:
def evaluate(book, context):
if book.series is None:
return ''
db = context.db.new_api
ans = set()
# Get the list of books in the series
ids = db.search(f'series:"={book.series}"', '')
if ids:
# Get all the author_sort values for the books in the series
author_sorts = (v for v in db.all_field_for('author_sort', ids).values())
# Add the names to the result set, removing duplicates
for aus in author_sorts:
ans.update(v.strip() for v in aus.split('&'))
# Make a sorted comma-separated string from the result set
return ', '.join(v.replace(',', ';') for v in sorted(ans))
La salida en los detalles del libro tiene este aspecto:
Plantillas guardadas¶
El modo de programación general y el modo de plantilla de Python permiten guardar plantillas e invocarlas desde otra plantilla, casi como invocar funciones guardadas. Puede guardar plantillas en Preferencias > Avanzado > Funciones de plantilla. Hay más información en el diálogo correspondiente. Puede invocar una plantilla de la misma manera que una función, pasando argumentos por posición si lo desea. Un argumento puede ser una expresión. Ejemplos para invocar una plantilla, suponiendo que la plantilla guardada se llame foo
:
lala()
– invoca la plantilla sin pasar argumentos.lala(a, b)
– invoca la plantilla pasando los valores de las variablesa
yb
.lala(if field('series') then field('series_index') else 0 fi)
– si el libro tieneseries
, pasa el valor deseries_index
, en caso contrario pasa el valor0
.
En el MPG, puede obtener el valor de los argumentos pasados en la invocación de la plantilla guardada usando la función arguments
. Esta función declara e inicializa las variables locales, parámetros en la práctica. Las variables son posicionales: obtienen el valor del argumento usado en la misma posición en la invocación. Si el argumento correspondiente no aparece en la invocación, arguments
asigna a esa variable el valor predeterminado suministrado. Si no hay valor predeterminado, será un texto vacío. Por ejemplo, la siguiente función arguments
declara dos variables: key
y ``alternate`:
arguments(key, alternate='series')
Ejemplos, suponiendo de nuevo que la plantilla guardada se llame lala
:
lala('#miserie')
– a la variablekey
se le asigna el valor'#miserie'
y a la variablealternate
se le asigna el valor predeterminado'serie'
.lala('series', '#genero')
a la variablekey
se le asigna el valor'series'
y a la variablealternate
se le asigna el valor'#genero'
.lala()
– a la variablekey
se le asigna un texto vacío y a la variablealternate
se le asigna el valor predeterminado'series'
.
En el MPPy los argumentos se pasan en el parámetro arguments
, que es una lista de textos. No existe la posibilidad de especificar valores predeterminados. Debe comprobar la longitud de la lista arguments
para asegurarse de que el número de argumentos es el esperado.
Una buena manera de probar las plantillas guardadas es usar el diálogo Prueba de plantillas. Para facilitar su acceso, asígnele un atajo de teclado en Preferencias > Avanzado > Atajos > Prueba de plantillas. Si le asigna un atajo de teclado podrá alternar rápidamente entre la prueba de plantillas y la modificación del código de programa de la plantilla.
Pasar información adicional a las plantillas¶
Un desarrollador puede decidir pasar información adicional al procesador de plantillas, como metadatos del libro específicos para una aplicación o información sobre lo que se quiere que haga el procesador. Una plantilla puede acceder a esta información y usarla durante la evaluación.
Desarrollador: cómo pasar información adicional
La información adicional es un diccionario Python que contiene pares nombre_de_variable: valor de variable
donde los valores deberían ser textos. La plantilla puede acceder al diccionario, creando variables locales con nombre nombre_de_variable
y valor valor de variable
. El usuario no puede cambiar el nombre, así que lo mejor es usar nombres que no entren en conflicto con otras variables locales, por ejemplo añadiendo un guión bajo al principio del nombre.
El diccionario se pasa al procesador de plantillas (el formatter
) usando el argumento global_vars=diccionario
. La forma completa del método es:
def safe_format(self, fmt, kwargs, error_value, book,
column_name=None, template_cache=None,
strip_results=True, template_functions=None,
global_vars={})
Creador de plantillas: cómo acceder a la información adicional
Puede acceder a la información adicional (el diccionario globals
) en una plantilla usando la función de plantilla:
globals(id[=expression] [, id[=expression]]*)
donde id
es cualquier nombre de variable permitido. Esta función comprueba si la información adicional prevista por el desarrollador contiene el nombre. Si es así, la función asigna el valor a una variable local con ese nombre. Si el nombre no está presente en la información adicional y se suministra una expresión
, se evalua dicha expresión
y el resultado se asigna a la variable local. Si no existe ni un valor ni una expresión, la función asigna el texto vacío (''
) a la variable local.
Una plantilla puede establecer un valor en el diccionario globals
usando la función de plantilla:
set_globals(id[=expression] [, id[=expression]]*)
Esta función asigna la pareja id:valor
del diccionario globals
, donde valor
es el valor de la variable local de la plantilla id
. Si la variable no existe, valor
se toma como el resultado de evaluar expresión
.
Notas sobre las diferencias entre modos¶
Los tres modos de programación, el modo de función única (MFU), el modo de programación de plantillas (MPP) y el modo de programación general (MPG) funcionan de distinta manera. MFU pretende ser «sencillo» y oculta muchos elementos del lenguaje de programación.
Diferencias:
En el MFU el valor de la columna se pasa siempre como un primer argumento «invisible» a la función que se incluye en la plantilla.
El MFU no hace distinciones entre variables y textos; todos los valores son textos.
La siguiente plantilla MFU devuelve el nombre de la serie o el texto
'no series'
:{series:ifempty(no series)}
La plantilla equivalente en MPP es:
{series:'ifempty($, 'no series')'}
La plantilla equivalente en MPG es:
program: ifempty(field('series'), 'no series')
El primer argumento de
ifempty
es el valor del camposeries
. El segundo argumento es el textono series
. En MFU el primer argumento, el valor, se pasa automáticamente (es el argumento invisible).Varias funciones de plantilla, como
booksize()
ycurrent_library_name()
, no admiten argumentos. Debido al «argumento invisible», no puede usar estas funciones en MFU.Las funciones anidadas, en las que una función invoca a otra función para evaluar un argumento, no pueden usarse en MFU. Por ejemplo, esta plantilla, que pretende devolver los 5 primeros caracteres del valor de la serie convertidos en mayúsculas, no funcionará en MFU:
{series:uppercase(substr(0,5))}
MPP y MPG permiten usar funciones anidadas. La plantilla anterior en MPP sería:
{series:'uppercase(substr($, 0,5))'}
En MPG sería:
program: uppercase(substr(field('series'), 0,5))
Como se mencionó ateriormente en la sección modo de programación de plantillas, en el MPP, usar los caracteres
{
y}
en textos literales puede conducir a errores o resultados inesperados porque confunden al procesador de plantillas. Éste intenta interpretarlos como límites de plantilla y no como caracteres. En algunos casos, pero no todos, puede sustituir un{
por[[
y un}
por]]
. En general, si un program contiene caracteres{
y}
, debería usar el modo de programación general.
Funciones de plantilla Python definidas por el usuario¶
Puede añadir funciones propias al procesador de plantillas. Dichas funciones 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:
Creamos un campo compuesto (démosle el nombre de consulta #aa) que contiene
{series}/{series_index} - {title}
. Si la serie no está vacía, esta plantilla produce serie/número_de_serie - título.Creamos un campo compuesto (démosle el nombre de consulta #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.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.
Consejos¶
Use la prueba de plantillas para probar plantillas. Añada esta función al menú contextual para libros en lea biblioteca o asígnele un atajo de teclado.
Las plantillas pueden usar otras plantillas haciendo referencia a columnas compuestas construidas con la plantilla deseada. También puede usar plantillas guardadas.
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
.
Referencia de funciones¶
- Reference for all built-in template language functions
- Arithmetic
- Boolean
- Date functions
- Formatting values
- Get values from metadata
- annotation_count()
- approximate_formats()
- author_links(sep_val, sep_par)
- author_sorts(separador)
- booksize()
- connected_device_name(ubicación_de_almacenamiento)
- connected_device_uuid(ubicación_de_almacenamiento)
- current_library_name()
- current_library_path()
- current_virtual_library_name()
- field(nombre_de_búsqueda)
- formats_modtimes(formato_fecha)
- formats_paths()
- formats_sizes()
- has_cover()
- is_marked()
- language_codes(nombres)
- language_strings(códigos, localizar)
- ondevice()
- raw_field(nombre_de_búsqueda [, predeterminado_opcional])
- raw_list(nombre_de_búsqueda, separador)
- series_sort()
- user_categories()
- virtual_libraries()
- If-then-else
- Iterating over values
- List lookup
- List manipulation
- count(val, separador)
- list_count_matching(lista, patrón, separador)
- list_difference(lista1, lista2, separador)
- list_equals(lista1, sep1, lista2, sep2, val_sí, val_no)
- list_intersection(lista1, lista2, separador)
- list_join(con_separador, lista1, separador1 [, lista2, separador2]*)
- list_re(lista_orig, separador, incluir, sust_opc)
- list_re_group(list_orig, separador, incluir, búsqueda [, plantilla_grupo]+)
- list_remove_duplicates(lista, separador)
- list_sort(lista, dirección, separador)
- list_split(lista, sep, prefijo_id)
- list_union(lista1, lista2, separador)
- range(inicio, fin, paso, límite)
- subitems(val, índice_inicio, índice_fin)
- sublist(val, índice_inicio, índice_fin, separador)
- Other
- Recursion
- Relational
- String case changes
- String manipulation
- character(nombre_carácter)
- re(val, patrón, sustitución)
- re_group(val, patrón [, plantilla_para_grupo]*)
- shorten(val, car_izq, texto_medio, car_der)
- strcat(a [, b]*)
- strcat_max(máx, texto1 [, prefijo2, texto2]*)
- strlen(a)
- substr(texto, inicio, fin)
- swap_around_articles(valor, separador)
- swap_around_comma(val)
- to_hex(val)
- transliterate(a)
- Template database functions
- other
- API of the Metadata objects