Mallspråket för calibre¶
calibre-mallspråket är ett calibre-specifikt språk som används i hela calibre för uppgifter som att specificera filsökvägar, formatera värden och beräkna värdet för användarspecificerade kolumner. Exempel:
Ange mappstruktur och filnamn när du sparar filer från calibre-biblioteket till disken eller e-bokläsenhet.
Definiera regler för att lägga till ikoner och färger till calibre-boklistan.
Definiera ”virtuella kolumner” som innehåller data från andra kolumner.
Avancerad bibliotekssökning.
Avancerad metadata sök och ersätt.
Språket är uppbyggt kring föreställningen om en ”mall”, som specificerar vilka bokmetadata som ska användas, beräkningar på metadata och hur de ska formateras.
Grundläggande mallar¶
A basic template consists one or more template expressions
. A template expression
consists of text and names in curly brackets ({}
) that is replaced by the corresponding metadata from the book being processed. For example, the default template in calibre used for saving books to device has 4 template expressions
:
{author_sort}/{title}/{title} - {authors}
For the book ”The Foundation” by ”Isaac Asimov” the will become:
Asimov, Isaac/The Foundation/The Foundation - Isaac Asimov
The slashes are not template expressions
because they are in between in {}
. Such text is left where it appears. For example, if the template is:
{author_sort} Some Important Text {title}/{title} - {authors}
then for ”The Foundation” the template produces:
Asimov, Isaac Some Important Text The Foundation/The Foundation - Isaac Asimov
A template expression
can access all the metadata available in calibre, including custom columns (columns you create yourself), by using a column’s lookup name
. To find the lookup name for a column (sometimes called fields), hover your mouse over the column header in calibre’s book list. Lookup names for custom columns always begin with #
. For series type columns there is an additional field named #lookup name_index
that is the series index for that book in the series. For example, if you have a custom series column named #myseries
, there will also be a column named #myseries_index
. The standard series column’s index is named series_index
.
Utöver de vanliga kolumnbaserade fälten kan du också använda:
{formats}
- En lista över format tillgängliga i calibre-biblioteket för en bok
{identifiers:select(isbn)}
- Bokens ISBN
Om metadata för fältet för en given bok inte är definierad ersätts fältet i mallen med den tomma strängen (''
). Tänk till exempel på följande mall:
{author_sort}/{series}/{title} {series_index}
Om Asimovs bok ”Second Foundation” finns i serien ”Foundation” så producerar mallen:
Asimov, Isaac/Foundation/Second Foundation 3
Om en serie inte har angetts för boken producerar mallen:
Asimov, Isaac/Second Foundation
Mallprocessorn tar automatiskt bort flera snedstreck och inledande eller efterföljande mellanslag.
Avancerad formatering¶
Förutom ersättning av metadata kan mallar villkorligt innehålla ytterligare text och styra hur ersatt data formateras.
Villkorligt inkludera text
Sometimes you want text to appear in the output only if a field is not empty. A common case is series
and series_index
where you want either nothing or the two values separated by a hyphen. calibre handles this case using a special template expression
syntax.
For example and using the above Foundation example, assume you want the template to produce Foundation - 3 - Second Foundation. This template produces that output:
{series} - {series_index} - {title}
However, if a book has no series the template will produce - - the title, which is probably not what you want. Generally, people want the result be the title without the extraneous hyphens. You can accomplish this using the following template syntax:
{field:|prefix_text|suffix_text}
This template expression
says that if field
has the value XXXX then the result will be prefix_textXXXXXsuffix_text. If field
is empty (has no value) then the result will be the empty string (nothing) because the prefix and suffix are ignored. The prefix and suffix can contain blanks.
Do not use subtemplates (`{ … }`) or functions (see below) in the prefix or the suffix.
Med hjälp av denna syntax kan vi lösa ovanstående icke-serier problem med mallen:
{series}{series_index:| - | - }{title}
Bindestreck inkluderas endast om boken har ett serieindex, vilket den bara har om den har en serie. Om du fortsätter med Foundation-exemplet igen kommer mallen att producera Foundation - 1 - Second Foundation.
Notes:
You must include the colon after the
lookup name
if you are using a prefix or a suffix.You must either use either no or both
|
characters. Using one, as in{field:| - }
, is not allowed.It is OK to provide no text for either the prefix or the suffix, such as in
{series:|| - }
. The template{title:||}
is the same as{title}
.
Formatering
Anta att du vill att serieindex
ska formateras som tre siffror med inledande nollor. Detta gör tricket:
{series_index:0>3s}
- Tre siffror med inledande nollor
För efterföljande nollor, använd:
{series_index:0<3s}
- Tre siffror med efterföljande nollor
Om du använder serieindex med bråkvärden, t.ex. 1,1, kanske du vill att decimaltecken ska hamna i linje. Till exempel kanske du vill att indexen 1 och 2,5 ska visas som 01,00 och 02,50 så att de kommer att sortera korrekt på en enhet som gör lexikal sortering. För att göra detta, använd:
{series_index:0>5.2f}
- Fem tecken som består av två siffror med inledande nollor, en decimalkomma, sedan 2 siffror efter decimalkomma.
Om du bara vill ha de två första bokstäverna i data, använd:
{author_sort:.2}
- Endast de två första bokstäverna i författaren sorterar namn
Mycket av formateringen av calibre mallspråk kommer från Python. För mer information om syntaxen för dessa avancerade formateringsoperationer, se Python-dokumentationen.
Använda mallar för att definiera anpassade kolumner¶
Templates can be used to display information that isn’t in calibre metadata, or to display metadata differently from calibre’s normal format. For example, you might want to show the ISBN
, a field that calibre does not display. You can accomplish this creating a custom column with the type Column built from other columns (hereafter called composite columns) and providing a template to generate the displayed text. The column will display the result of evaluating the template. For example, to display the ISBN, create the column and enter {identifiers:select(isbn)}
in the template box. To display a column containing the values of two series custom columns, separated by a comma, use {#series1:||,}{#series2}
.
Sammansatta kolumner kan använda godtyckligt mallalternativ, även formatering.
Note: You cannot edit the data displayed in a composite column. Instead you edit the source columns. If you edit a composite column, for example by double-clicking it, calibre will open the template for editing, not the underlying data.
Mallar och pluggbrädor¶
Pluggbrädor används för att ändra metadata som skrivs in böcker under ”skicka till enhet” och ”spara till disk” operationer. En pluggbräda tillåter dig att ange en mall för att tillhandahålla data som ska skrivas i bokens metadata. Du kan använda pluggbrädor för att ändra följande fält: författare, author_sort, språk, förläggare, taggar, titel, title_sort. Den här funktion hjälper personer som vill använda olika metadata i böcker på enheter för att lösa sortering- eller visningsproblem.
When you create a plugboard, you specify the format and device for which the plugboard is to be used. A special device is provided, save_to_disk
, that is used when saving formats (as opposed to sending them to a device). Once you have chosen the format and device, you choose the metadata fields to change, providing templates to supply the new values. These templates are connected to their destination fields, hence the name plugboards. You can of course use composite columns in these templates.
Plugboards are quite flexible and can be written in Single Function Mode, Template Program Mode, General Program Mode, or Python Template mode.
När en pluggbräda kan gälla (innehållsserver, spara till disk, eller skicka till enhet), söker calibre de definierade pluggbrädor att välja den rätta för givet format och enhet. Till exempel för att hitta rätt pluggbräda för en EPUB-bok som skickas till en Android-enhet, söker calibre dessa pluggbrädor enligt följande sökordning:
en pluggbräda med en exakt matchning på format och enhet, till exempel
EPUB
ochANDROID
en pluggbräda med en exakt matchning på format och den speciella
any device
val, till exempel `` EPUB`` ochany device
en pluggbräda med en exakt matchning på format och den speciella
any device
val, ochANDROID
en pluggbräda med
något format
ochnågon enhet
Tagg och författar fält har särskild behandling, eftersom båda dessa fält kan ha mer än en post. En bok kan ha många taggar och många författare. När du anger att ett av dessa två fält ska ändras, är mallens resultat som undersöks för att se om mer än en post finns. För taggar, skärs resultatet bort varhelst calibre finner ett kommatecken. Till exempel om mallen producerar värdet Spänning, Skräck
, då blir resultatet två taggar, Spänning
och Skräck
. Det finns inget sätt att sätta ett kommatecken i mitten av en tagg.
Samma sak händer för författare, men med en annan karaktär för snittet, en & (et-tecken) istället för ett kommatecken. Till exempel om mallen producerar värdet Blogs, Joe&Posts, Susan
, då kommer boken att sluta med två författare, Blogs, Joe
och Posts, Susan
. Om mallen producerar värdet Blogs, Joe;Posts, Susan
, då kommer boken att ha en författare med ett ganska konstigt namn.
Pluggbrädor påverkar metadata som skrivs in i boken när den sparas till disk eller skrivs till enheten. Pluggbrädor påverkar inte metadata som används av spara till disk
och skicka till enhet
för att skapa filnamnen. Istället konstrueras filnamn med hjälp av mallar som anges i lämpliga inställningsfönster.
Using functions in templates - Single Function Mode¶
Suppose you want to display the value of a field in upper case when that field is normally in title case. You can do this using template functions. For example, to display the title in upper case use the uppercase
function, as in {title:uppercase()}
. To display it in title case, use {title:titlecase()}
.
Functions go into the format part of the template, after the :
and before the first |
or the closing }
if no prefix/suffix is used. If you have both a format and a function reference, the function comes after a second :
. Functions return the value of the column specified in the template, suitably modified.
Syntaxen för att använda funktioner är en av:
{lookup_name:function(arguments)}
{lookup_name:format:function(arguments)}
{lookup_name:function(arguments)|prefix|suffix}
{lookup_name:format:function(arguments)|prefix|suffix}
Function names must always be followed by opening and closing parentheses. Some functions require extra values (arguments), and these go inside the parentheses. Arguments are separated by commas. Literal commas (commas as text, not argument separators) must be preceded by a backslash (\
) . The last (or only) argument cannot contain a textual closing parenthesis.
Functions are evaluated before format specifications and the prefix/suffix. See further down for an example of using both a format and a function.
Viktigt: Om du har erfarenhet av programmering, notera att syntaxen i ”enkelt funktionsläge” inte är vad du förväntar dig. Strängar är inte citerade och mellanslag är betydande. Alla argument anses vara konstanter; det finns inga uttryck.
Do not use subtemplates (`{ … }`) as function arguments. Instead, use Template Program Mode and General Program Mode.
Notes on calling functions in Single Function Mode:
When functions are used in Single Function Mode, the first parameter,
value
, is automatically replaced by the content of the field specified in the template. For example, when the template{title:capitalize()}
is processed, the content of thetitle
field is passed as the parametervalue
to the capitalize function.In the function documentation, the notation
[something]*
means thatsomething
can be repeated zero or more times. The notation[something]+
means that thesomething
is repeated one or more times (must exist at least one time).Some functions use regular expressions. In the template language regular expression matching is case-insensitive.
Functions are documented in Mallfunktionsreferens. The documentation tells you what arguments the functions require and what the functions do. For example, here is the documentation of the ifempty function.
ifempty(value, text_if_empty)
– if thevalue
is not empty then return thatvalue
, otherwise returntext_if_empty
.
You see that the function requires two arguments, value
and text_if_empty
. However, because we are using Single Function Mode, we omit the value
argument, passing only text_if_empty
. For example, this template:
{tags:ifempty(No tags on this book)}
shows the tags for a book, if any. If it has no tags then it show No tags on this book.
The following functions are usable in Single Function Mode because their first parameter is value
.
capitalize
(value)
– returns thevalue
with the first letter in upper case and the rest lower case.ceiling
(value)
– returns the smallest integer greater than or equal tovalue
.cmp
(value, y, lt, eq, gt)
– comparesvalue
andy
after converting both to numbers.contains
(value, pattern, text_if_match, text_if_not_match)
– checks if the value is matched by the regular expressionpattern
date_arithmetic
(value, calc_spec, fmt)
– Calculate a new date fromvalue
usingcalc_spec
.floor
(value)
– returns the largest integer less than or equal tovalue
.format_date
(value, format_string)
– format thevalue
, which must be a date string, using theformat_string
, returning a string.format_number
(value, template)
– interprets thevalue
as a number and formats that number using a Python formatting template such as{0:5.2f}
or{0:,d}
or${0:5,.2f}
.fractional_part
(value)
– returns the part of the value after the decimal point.human_readable
(value)
– expects thevalue
to be a number and returns a string representing that number in KB, MB, GB, etc.ifempty
(value, text_if_empty)
– if thevalue
is not empty then return thatvalue
, otherwise returntext_if_empty
.language_strings
(value, localize)
– return the language names for the language codes (see here for names and codes) passed invalue
.list_contains
(value, separator, [ pattern, found_val, ]* not_found_val)
– interpret thevalue
as a list of items separated byseparator
, checking thepattern
against each item in the list.list_count
(value, separator)
– interprets the value as a list of items separated byseparator
and returns the number of items in the list.list_count_matching
(value, pattern, separator)
– interpretsvalue
as a list of items separated byseparator
, returning the number of items in the list that match the regular expressionpattern
.list_item
(value, index, separator)
– interpret thevalue
as a list of items separated byseparator
, returning the ’index’th item.list_sort
(value, direction, separator)
– returnvalue
sorted using a case-insensitive lexical sort.lookup
(value, [ pattern, key, ]* else_key)
– The patterns will be checked against thevalue
in orderlowercase
(value)
– returns thevalue
in lower case.mod
(value, y)
– returns thefloor
of the remainder ofvalue / y
.rating_to_stars
(value, use_half_stars)
– Returns thevalue
as string of star (★
) characters.re
(value, pattern, replacement)
– return thevalue
after applying the regular expression.re_group
(value, pattern [, template_for_group]*)
– return a string made by applying the regular expressionpattern
tovalue
and replacing each matched instanceround
(value)
– returns the nearest integer tovalue
.select
(value, key)
– interpret thevalue
as a comma-separated list of items with each item having the formid:id_value
(the calibreidentifier
format).shorten
(value, left_chars, middle_text, right_chars)
– Return a shortened version of thevalue
str_in_list
(value, separator, [ string, found_val, ]+ not_found_val)
– interpret thevalue
as a list of items separated byseparator
then comparestring
against each value in the list.subitems
(value, start_index, end_index)
– This function breaks apart lists of tag-like hierarchical items such as genres.sublist
(value, start_index, end_index, separator)
– interpret thevalue
as a list of items separated byseparator
, returning a new list made from the items fromstart_index
toend_index
.substr
(value, start, end)
– returns thestart
’th through theend
’th characters ofvalue
swap_around_articles
(value, separator)
– returns thevalue
with articles moved to the end.swap_around_comma
(value)
– given avalue
of the formB, A
, returnA B
.switch
(value, [patternN, valueN,]+ else_value)
– for eachpatternN, valueN
pair, checks if thevalue
matches the regular expressionpatternN
test
(value, text_if_not_empty, text_if_empty)
– returntext_if_not_empty
if the value is not empty, otherwise returntext_if_empty
.titlecase
(value)
– returns thevalue
in title case.transliterate
(value)
– Return a string in a latin alphabet formed by approximating the sound of the words invalue
.uppercase
(value)
– returns thevalue
in upper case.
Using functions and formatting in the same template
Suppose you have an integer custom column #myint
that you want displayed with leading zeros, as in 003
. One way to do this is to use a format of 0>3s
. However, by default if a number (integer or float) equals zero then the value is displayed as the empty string so zero values will produce the empty string, not 000
. If you want to see 000
values then you use both the format string and the ifempty
function to change the empty value back to a zero. The template would be:
{#myint:0>3s:ifempty(0)}
Note that you can use the prefix and suffix as well. If you want the number to appear as [003]
or [000]
, then use the template:
{#myint:0>3s:ifempty(0)|[|]}
General Program Mode¶
General Program Mode (GPM) replaces template expressions with a program written in the template language. The syntax of the language is defined by the following grammar:
program ::= 'program:' expression_list
expression_list ::= top_expression [ ';' top_expression ]*
top_expression ::= or_expression
or_expression ::= and_expression [ '||' and_expression ]*
and_expression ::= not_expression [ '&&' not_expression ]*
not_expression ::= [ '!' not_expression ]* | concatenate_expr
concatenate_expr::= compare_expr [ '&' compare_expr ]*
compare_expr ::= add_sub_expr [ compare_op add_sub_expr ]
compare_op ::= '==' | '!=' | '>=' | '>' | '<=' | '<' |
'in' | 'inlist' | 'inlist_field' |
'==#' | '!=#' | '>=#' | '>#' | '<=#' | '<#'
add_sub_expr ::= times_div_expr [ add_sub_op times_div_expr ]*
add_sub_op ::= '+' | '-'
times_div_expr ::= unary_op_expr [ times_div_op unary_op_expr ]*
times_div_op ::= '*' | '/'
unary_op_expr ::= [ add_sub_op unary_op_expr ]* | expression
expression ::= identifier | constant | function | assignment | field_reference |
if_expr | for_expr | break_expr | continue_expr |
'(' expression_list ')' | function_def
field_reference ::= '$' [ '$' ] [ '#' ] identifier
identifier ::= id_start [ id_rest ]*
id_start ::= letter | underscore
id_rest ::= id_start | digit
constant ::= " string " | ' string ' | number
function ::= identifier '(' expression_list [ ',' expression_list ]* ')'
function_def ::= 'def' identifier '(' top_expression [ ',' top_expression ]* ')' ':'
expression_list 'fed'
assignment ::= identifier '=' top_expression
if_expr ::= 'if' condition 'then' expression_list
[ elif_expr ] [ 'else' expression_list ] 'fi'
condition ::= top_expression
elif_expr ::= 'elif' condition 'then' expression_list elif_expr | ''
for_expr ::= for_list | for_range
for_list ::= 'for' identifier 'in' list_expr
[ 'separator' separator_expr ] ':' expression_list 'rof'
for_range ::= 'for' identifier 'in' range_expr ':' expression_list 'rof'
range_expr ::= 'range' '(' [ start_expr ',' ] stop_expr
[ ',' step_expr [ ',' limit_expr ] ] ')'
list_expr ::= top_expression
break_expr ::= 'break'
continue_expr ::= 'continue'
separator_expr ::= top_expression
start_expr ::= top_expression
stop_expr ::= top_expression
step_expr ::= top_expression
limit_expr ::= top_expression
Notes:
a
top_expression
always has a value. The value of anexpression_list
is the value of the lasttop_expression
in the list. For example, the value of the expression list1;2;'foobar';3
is3
.In a logical context, any non-empty value is
True
In a logical context, the empty value is
False
Strings and numbers can be used interchangeably. For example,
10
and'10'
are the same thing.Comments are lines starting with a ’#’ character. Comments beginning later in a line are not supported.
Operator precedence
The operator precedence (order of evaluation) from highest (evaluated first) to lowest (evaluated last) is:
Funktionsanrop, konstanter, parentesuttryck, satsuttryck, tilldelningsuttryck, fältreferenser.
Unary plus (
+
) and minus (-
). These operators evaluate right to left.These and all the other arithmetic operators return integers if the expression results in a fractional part equal to zero. For example, if an expression returns
3.0
it is changed to3
.Multiply (
*
) and divide (/
). These operators are associative and evaluate left to right. Use parentheses if you want to change the order of evaluation.Add (
+
) and subtract (-
). These operators are associative and evaluate left to right.Numeric and string comparisons. These operators return
'1'
if the comparison succeeds, otherwise the empty string (''
). Comparisons are not associative:a < b < c
is a syntax error.String concatenation (
&
). The&
operator returns a string formed by concatenating the left-hand and right-hand expressions. Example:'aaa' & 'bbb'
returns'aaabbb'
. The operator is associative and evaluates left to right.Unary logical not (
!
). This operator returns'1'
if the expression is False (evaluates to the empty string), otherwise''
.Logical and (
&&
). This operator returns ’1’ if both the left-hand and right-hand expressions are True, or the empty string''
if either is False. It is associative, evaluates left to right, and does short-circuiting.Logical or (
||
). This operator returns'1'
if either the left-hand or right-hand expression is True, or''
if both are False. It is associative, evaluates left to right, and does short-circuiting. It is an inclusive or, returning'1'
if both the left- and right-hand expressions are True.
Field references
A field_reference
evaluates to the value of the metadata field named by lookup name that follows the $
or $$
. Using $
is equivalent to using the field function. Using $$
is equivalent to using the raw_field function. Examples:
* $authors ==> field('authors')
* $#genre ==> field('#genre')
* $$pubdate ==> raw_field('pubdate')
* $$#my_int ==> raw_field('#my_int')
If expressions
If
expressions first evaluate the condition
. If the condition
is True (a non-empty value) then the expression_list
in the then
clause is evaluated. If it is False then if present the expression_list
in the elif
or else
clause is evaluated. The elif
and else
parts are optional. The words if
, then
, elif
, else
, and fi
are reserved; you cannot use them as identifier names. You can put newlines and white space wherever they make sense. The condition
is a top_expression
not an expression_list
; semicolons are not allowed. The expression_lists
are semicolon-separated sequences of top_expressions
. An if
expression returns the result of the last top_expression
in the evaluated expression_list
, or the empty string if no expression list was evaluated.
Examples:
* 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)
Nested if
example:
program:
if field('series') then
if check_yes_no(field('#mybool'), '', '', '1') then
'yes'
else
'no'
fi
else
'no series'
fi
As said above, an if
produces a value. This means that all the following are equivalent:
* 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
For example, this program returns the value of the series
column if the book has a series, otherwise the value of the title
column:
program: field(if field('series') then 'series' else 'title' fi)
For expressions
The for
expression iterates over a list of values, processing them one at a time. The list_expression
must evaluate either to a metadata field lookup name
e.g., tags
or #genre
, or to a list of values. The range generates a list of numbers. If the result is a valid lookup name
then the field’s value is fetched and the separator specified for that field type is used. If the result isn’t a valid lookup name then it is assumed to be a list of values. The list is assumed to be separated by commas unless the optional keyword separator
is supplied, in which case the list values must be separated by the result of evaluating the separator_expr
. A separator cannot be used if the list is generated by range()
. Each value in the list is assigned to the specified variable then the expression_list
is evaluated. You can use break
to jump out of the loop, and continue
to jump to the beginning of the loop for the next iteration.
Example: This template removes the first hierarchical name for each value in Genre (#genre
), constructing a list with the new names:
program:
new_tags = '';
for i in '#genre':
j = re(i, '^.*?\.(.*)$', '\1');
new_tags = list_union(new_tags, j, ',')
rof;
new_tags
If the original Genre is History.Military, Science Fiction.Alternate History, ReadMe then the template returns Military, Alternate History, ReadMe. You could use this template in calibre’s
Edit metadata in bulk → Search & replace with Search for set to template
to strip off the first level of the hierarchy and assign the resulting value to Genre.
Observera: den sista raden i mallen, new_tags
, är inte absolut nödvändig i det här fallet eftersom for
returnerar värdet för det senaste topputtrycket i uttryckslistan. Värdet på en uppgift är värdet på dess uttryck, så värdet för satsen for
är det som tilldelades new_tags
.
Function definition
If you have repeated code in a template then you can put that code into a local function. The def
keyword starts the definition. It is followed by the function name, the argument list, then the code in the function. The function definition ends with the fed
keyword.
Arguments are positional. When a function is called the supplied arguments are matched left to right against the defined parameters, with the value of the argument assigned to the parameter. It is an error to provide more arguments than defined parameters. Parameters can have default values, such as a = 25
. If an argument is not supplied for that parameter then the default value is used, otherwise the parameter is set to the empty string.
The return
statement can be used in a local function.
A function must be defined before it can be used.
Example: This template computes an approximate duration in years, months, and days from a number of days. The function to_plural()
formats the computed values. Note that the example also uses the &
operator:
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')
Relational operators
Relational operators return '1'
if the comparison is true, otherwise the empty string (''
).
There are two forms of relational operators: string comparisons and numeric comparisons.
String comparisons do case-insensitive string comparison using lexical order. The supported string comparison operators are ==
, !=
, <
, <=
, >
, >=
, in
, inlist
, and inlist_field
.
For the in
operator, the result of the left hand expression is interpreted as a regular expression pattern. The in
operator is True if the value of left-hand regular expression matches the value of the right hand expression.
The inlist
operator is true if the left hand regular expression matches any one of the items in the right hand list where the items in the list are separated by commas. The inlist_field
operator is true if the left hand regular expression matches any of the items in the field (column) named by the right hand expression, using the separator defined for the field. NB: the inlist_field
operator requires the right hand expression to evaluate to a field name, while the inlist
operator requires the right hand expression to evaluate to a string containing a comma-separated list. Because of this difference, inlist_field
is substantially faster than inlist
because no string conversions or list constructions are done. The regular expressions are case-insensitive.
The numeric comparison operators are ==#
, !=#
, <#
, <=#
, >#
, >=#
. The left and right expressions must evaluate to numeric values with two exceptions: both the string value ”None” (undefined field) and the empty string evaluate to the value zero.
Exempel:
program: field('series') == 'foo'
returns'1'
if the book’s series is foo, otherwise''
.
program: 'f.o' in field('series')
returns'1'
if the book’s series matches the regular expressionf.o
(e.g., foo, Off Onyx, etc.), otherwise''
.
program: 'science' inlist $#genre
returns'1'
if any of the values retrieved from the book’s genres match the regular expressionscience
, e.g., Science, History of Science, Science Fiction etc., otherwise''
.
program: '^science$' inlist $#genre
returns'1'
if any of the book’s genres exactly match the regular expression^science$
, e.g., Science, otherwise''
. The genres History of Science and Science Fiction don’t match.
program: 'asimov' inlist $authors
returns'1'
if any author matches the regular expressionasimov
, e.g., Asimov, Isaac or Isaac Asimov, otherwise''
.
program: 'asimov' inlist_field 'authors'
returns'1'
if any author matches the regular expressionasimov
, e.g., Asimov, Isaac or Isaac Asimov, otherwise''
.
program: 'asimov$' inlist_field 'authors'
returns'1'
if any author matches the regular expressionasimov$
, e.g., Isaac Asimov, otherwise''
. It doesn’t match Asimov, Isaac because of the$
anchor in the regular expression.
program: if field('series') != 'foo' then 'bar' else 'mumble' fi
returns'bar'
if the book’s series is not foo. Otherwise it returns'mumble'
.
program: if field('series') == 'foo' || field('series') == '1632' then 'yes' else 'no' fi
returns'yes'
if series is either foo or 1632, otherwise'no'
.
program: if '^(foo|1632)$' in field('series') then 'yes' else 'no' fi
returns'yes'
if series is either foo or 1632, otherwise'no'
.
program: if 11 > 2 then 'yes' else 'no' fi
returns'no'
because the>
operator does a lexical comparison.
program: if 11 ># 2 then 'yes' else 'no' fi
returns'yes'
because the>#
operator does a numeric comparison.
Functions in General Program Mode
See Mallfunktionsreferens for the list of functions built into the template language.
Notes:
As opposed to Single Function Mode, in General Program Mode you must specify the first parameter
value
.All parameters are expression_lists (see the grammar above).
More complex programs in template expressions - Template Program Mode¶
Template Program Mode (TPM) is a blend of General Program Mode and
Single Function Mode. TPM differs from Single Function Mode in that it permits writing template expressions that refer to other metadata fields, use nested functions, modify variables, and do arithmetic. It differs from General Program Mode in that the template is contained between {
and }
characters and doesn’t begin with the word program:
. The program portion of the template is a General Program Mode expression list.
Example: assume you want a template to show the series for a book if it has one, otherwise show the value of a custom field #genre. You cannot do this in the Single Function Mode because you cannot make reference to another metadata field within a template expression. In TPM you can, as the following expression demonstrates:
{series_index:0>7.1f:'ifempty($, -5)'}
Exemplet visar flera saker:
TPM is used if the expression begins with
:'
and ends with'}
. Anything else is assumed to be in Single Function Mode.If the template contains a prefix and suffix, the expression ends with
'|
where the|
is the delimiter for the prefix. Example:{series_index:0>7.1f:'ifempty($, -5)'|prefix | suffix}
Functions must be given all their arguments. For example, the standard built-in functions must be given the initial parameter
value
.The variable
$
is usable as thevalue
argument and stands for the value of the field named in the template,series_index
in this case.blanksteg ignoreras och kan användas var som helst i uttrycket.
konstanta strängar omges av matchande citattecken, antingen
'
eller"
.
In TPM, using {
and }
characters in string literals can lead to errors or unexpected results because they confuse the template processor. It tries to treat them as template expression boundaries, not characters. In some but not all cases you can replace a {
with [[
and a }
with ]]. Generally, if your program contains {
and }
characters then you should use General Program Mode.
Python Template Mode¶
Python Template Mode (PTM) lets you write templates using native Python and the calibre API. The database API will be of most use; further discussion is beyond the scope of this manual. PTM templates are faster and can do more complicated operations but you must know how to write code in Python using the calibre API.
A PTM template begins with:
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'
You can add the above text to your template using the context menu, usually accessed with a right click. The comments are not significant and can be removed. You must use python indenting.
The context object supports str(context)
that returns a string of the context’s contents, and context.attributes
that returns a list of the attribute names in the context.
The context.funcs
attribute allows calling Built-in and User template functions, and Stored GPM/Python templates, so that you can execute them directly in your code. The functions are retrieved using their names. If the name conflicts with a Python keyword, add an underscore to the end of the name. Examples:
context.funcs.list_re_group()
context.funcs.assert_()
Here is an example of a PTM template that produces a list of all the authors for a series. The list is stored in a Column built from other columns, behaves like tags. It shows in Book details and has the on separate lines checked (in Preferences → Look & feel → Book details). That option requires the list to be comma-separated. To satisfy that requirement the template converts commas in author names to semicolons then builds a comma-separated list of authors. The authors are then sorted, which is why the template uses 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))
The output in Book details looks like this:
Lagrade mallar¶
Both General Program Mode and Python Template Mode support saving templates and calling those templates from another template, much like calling stored functions. You save templates using Preferences → Advanced → Template functions. More information is provided in that dialog. You call a template the same way you call a function, passing positional arguments if desired. An argument can be any expression. Examples of calling a template, assuming the stored template is named foo
:
foo()
– call the template passing no arguments.foo(a, b)
call the template passing the values of the two variablesa
andb
.foo(if field('series') then field('series_index') else 0 fi)
– if the book has aseries
then pass theseries_index
, otherwise pass the value0
.
In GPM you retrieve the arguments passed in the call to the stored template using the arguments
function. It both declares and initializes local variables, effectively parameters. The variables are positional; they get the value of the parameter given in the call in the same position. If the corresponding parameter is not provided in the call then arguments
assigns that variable the provided default value. If there is no default value then the variable is set to the empty string. For example, the following arguments
function declares 2 variables, key
, alternate
:
arguments(key, alternate='series')
Examples, again assuming the stored template is named foo
:
foo('#myseries')
– argumentkey
is assigned the value'myseries'
and the argumentalternate
is assigned the default value'series'
.foo('series', '#genre')
the variablekey
is assigned the value'series'
and the variablealternate
is assigned the value'#genre'
.foo()
– the variablekey
is assigned the empty string and the variablealternate
is assigned the value'series'
.
In PTM the arguments are passed in the arguments
parameter, which is a list of strings. There isn’t any way to specify default values. You must check the length of the arguments
list to be sure that the number of arguments is what you expect.
An easy way to test stored templates is using the Template tester
dialog. For ease of access give it a keyboard shortcut in Preferences → Advanced → Keyboard shortcuts → Template tester. Giving the Stored templates
dialog a shortcut will help switching more rapidly between the tester and editing the stored template’s source code.
Providing additional information to templates¶
A developer can choose to pass additional information to the template processor, such as application-specific book metadata or information about what the processor is being asked to do. A template can access this information and use it during the evaluation.
Developer: how to pass additional information
The additional information is a Python dictionary containing pairs variable_name: variable_value
where the values must be strings. The template can access the dictionary, creating template local variables named variable_name
containing the value variable_value
. The user cannot change the name so it is best to use names that won’t collide with other template local variables, for example by prefixing the name with an underscore.
This dictionary is passed to the template processor (the formatter
) using the named parameter global_vars=your_dict
. The full method signature is:
def safe_format(self, fmt, kwargs, error_value, book,
column_name=None, template_cache=None,
strip_results=True, template_functions=None,
global_vars={})
Template writer: how to access the additional information
You access the additional information (the globals
dictionary) in a template using the template function:
globals(id[=expression] [, id[=expression]]*)
where id
is any legal variable name. This function checks whether the additional information provided by the developer contains the name. If it does then the function assigns the provided value to a template local variable with that name. If the name is not in the additional information and if an expression
is provided, the expression
is evaluated and the result is assigned to the local variable. If neither a value nor an expression is provided, the function assigns the empty string (''
) to the local variable.
A template can set a value in the globals
dictionary using the template function:
set_globals(id[=expression] [, id[=expression]]*)
This function sets the globals
dictionary key:value pair id:value
where value
is the value of the template local variable id
. If that local variable doesn’t exist then value
is set to the result of evaluating expression
.
Notes on the difference between modes¶
The three program modes, Single Function Mode (SFM), Template Program Mode (TPM), and General Program Mode (GPM), work differently. SFM is intended to be ’simple’ so it hides a lot of programming language bits.
Differences:
In SFM the value of the column is always passed as an ’invisible’ first argument to a function included in the template.
SFM doesn’t support the difference between variables and strings; all values are strings.
The following SFM template returns either the series name or the string ”no series”:
{series:ifempty(no series)}
The equivalent template in TPM is
{series:'ifempty($, 'no series')'}
The equivalent template in GPM is:
program: ifempty(field('series'), 'no series')
The first argument to
ifempty
is the value of the fieldseries
. The second argument is the stringno series
. In SFM the first argument, the value of the field, is automatically passed (the invisible argument).Several template functions, for example
booksize()
andcurrent_library_name()
, take no arguments. Because of the ’invisible argument’ you cannot use these functions in SFM.Nested functions, where a function calls another function to compute an argument, cannot be used in SFM. For example this template, intended to return the first 5 characters of the series value uppercased, won’t work in SFM:
{series:uppercase(substr(0,5))}
TPM and GPM support nested functions. The above template in TPM would be:
{series:'uppercase(substr($, 0,5))'}
I GPM skulle det vara:
program: uppercase(substr(field('series'), 0,5))
As noted in the above Template Program Mode section, using
{
and}
characters in TPM string literals can lead to errors or unexpected results because they confuse the template processor. It tries to treat them as template boundaries, not characters. In some but not all cases you can replace a{
with[[
and a}
with ]]. Generally, if your program contains{
and}
characters then you should use General Program Mode.
Användardefinierade Python-mallfunktioner¶
You can add your own Python functions to the template processor. Such functions can be used in any of the three template programming modes. The functions are added by going to Preferences → Advanced → Template functions. Instructions are shown in that dialog. Note that you can use Python Templates for a similar purpose. As calling user-defined functions is faster than calling a Python template, user-defined functions might be more efficient depending on the complexity of what the function or template does.
Särskilda anvisningar för att spara/skicka mallar¶
Särskild bearbetning tillämpas när en mall används i en spara på disk eller skicka till enhet mall. Värdena på fälten städas, ersätter tecken som är speciella till filsystem med understreck, inklusive snedstreck. Det innebär att textfältet inte kan användas för att skapa mappar. Snedstreck ändras dock inte i prefix eller suffixsträngar, så snedstreck i dessa strängar kommer att orsaka att mappar skapas. På grund av detta kan du skapa variabeldjup mappstruktur.
Antag till exempel att vi vill ha mappstrukturen series/series_index - title, med förbehållet att om serien inte finns, så bör titeln vara i översta mappen. Mallen för att göra detta är:
{series:||/}{series_index:|| - }{title}
Snedstrecket och bindestrecket visas bara om serien inte är tom.
The lookup function lets us do even fancier processing. For example, assume that if a book has a series, then we want the folder structure series/series index - title.fmt. If the book does not have a series then we want the folder structure genre/author_sort/title.fmt. If the book has no genre then we want to use ’Unknown’. We want two completely different paths, depending on the value of series.
För att åstadkomma det här, vi:
Create a composite field (give it lookup name #aa) containing
{series}/{series_index} - {title}
. If the series is not empty, then this template will produce series/series_index - title.Create a composite field (give it lookup name #bb) containing
{#genre:ifempty(Unknown)}/{author_sort}/{title}
. This template produces genre/author_sort/title, where an empty genre is replaced with Unknown.Set the save template to
{series:lookup(.,#aa,#bb)}
. This template chooses composite field#aa
if series is not empty and composite field#bb
if series is empty. We therefore have two completely different save paths, depending on whether or not series is empty.
Tips¶
Use the Template Tester to test templates. Add the tester to the context menu for books in the library and/or give it a keyboard shortcut.
Templates can use other templates by referencing composite columns built with the desired template. Alternatively, you can use Stored Templates.
I en pluggbräda kan du ställa in ett fält till tomt (eller vad som motsvarar tomt) genom att använda den särskilda mallen
{}
. Den här mallen kommer alltid att utvärderas till en tom sträng.Den teknik som beskrivs ovan för att visa siffror även om de har ett nollvärde fungerar med standardfältet series_index.
Mallfunktionsreferens¶
- Reference for all built-in template language functions
- Aritmetik
- Booleskt
- Databasfunktioner
- Datumfunktioner
- Formaterar värden
- Hämta värden från metadata
- annotation_count
- approximate_formats
- author_links
- author_sorts
- booksize
- connected_device_name
- connected_device_uuid
- current_library_name
- current_library_path
- current_virtual_library_name
- field
- formats_modtimes
- formats_paths
- formats_sizes
- has_cover
- is_marked
- language_codes
- language_strings
- ondevice
- raw_field
- raw_list
- series_sort
- user_categories
- virtual_libraries
- Iterera över värden
- Lista uppslag
- Listmanipulation
- Rekursion
- Relationellt
- Skiftlägesändringar
- Strängmanipulation
- Övriga
- API of the Metadata objects