calibre テンプレート言語

calibre テンプレート言語は、ファイルパスの指定、値の整形、ユーザ指定の列の値の計算などのタスクのために calibre 全体で使用される calibre 固有の言語です。例を挙げると:

  • calibre ライブラリからディスクまたは電子書籍リーダにファイルを保存するときに、フォルダ構造とファイル名を指定します。

  • calibre の本のリストにアイコンと色を追加するためのルールを定義します。

  • 他の列からのデータを含む 仮想列 を定義します。

  • 高度なライブラリ検索。

  • 高度なメタデータの検索と置換。

この言語は、使用する本の書誌、その書誌の計算、およびそのフォーマット方法を指定する テンプレート の概念に基づいて構築されています。

基本テンプレート

基本テンプレートは、ひとつ以上の テンプレート表現 で構成されます。テンプレート表現 は、中括弧 ({}) 内のテキストと名前で構成され、処理中の本の対応する書誌に置き換えられます。たとえば、本をデバイスに保存するために使用される calibre のデフォルトのテンプレートには、次の 4 つのテンプレート式があります。

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

"Isaac Asimov" の本 "The Foundation" の場合、次のようになります:

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

スラッシュは {} の間にあるため、テンプレート表現 ではありません。そのようなテキストは、それが表示される場所に残されます。たとえば、テンプレートが次の場合:

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

"The Foundation" にテンプレートは次を生成します:

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

テンプレート表現 は、列の ルックアップ名 を使用して、カスタム列 (自分で作成した列) を含む、calibre で使用可能なすべての書誌にアクセスできます。 (フィールド と呼ばれることもあります) のルックアップ名を見つけるには、マウスを calibre の本リストの列ヘッダに合わせます。カスタム列のルックアップ名は常に # で始まります。シリーズタイプの列の場合、シリーズ内のその本のシリーズインデックスである #lookup name_index という名前の追加フィールドがあります。たとえば、#myseries という名前のカスタムシリーズ列がある場合、#myseries_index という名前の列もあります。標準のシリーズ列のインデックスの名前は series_index です。

標準の列ベースのフィールドに加えて、次のものも使用できます:

  • {formats} - calibre ライブラリで利用可能な本の形式のリスト

  • {identifiers:select(isbn)} - 本の ISBN

特定の本のフィールドの書誌が定義されていない場合、テンプレートのフィールドは空の文字列 ('') に置き換えられます。たとえば、次のテンプレートについて考えてみましょう:

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

Asimov の本 "Second Foundation" がシリーズ "Foundation" に含まれている場合、テンプレートは次のように生成します:

Asimov, Isaac/Foundation/Second Foundation 3

本のシリーズが入力されていない場合、テンプレートは次のように生成します:

Asimov, Isaac/Second Foundation

テンプレートプロセッサは、複数のスラッシュと先頭または末尾のスペースを自動的に削除します。

高度な整形

書誌の置換に加えて、テンプレートには条件付きで追加のテキストを含め、置換されたデータの整形方法を制御できます。

条件つきでテキストを含める

フィールドが空でない場合にのみ、出力にテキストを表示したいというような場合があります。よくあるケースは seriesseries_index` で、何も必要ないか、ハイフンで区切られた 2 つの値が必要です。 calibre は、特殊な ``テンプレート表現 の構文を使用してこのケースを処理します。

たとえば、上記の Foundation の例を使用して、テンプレートで Foundation - 3 - Second Foundation を生成するとします。このテンプレートはその出力を生成します:

{series} - {series_index} - {title}

ただし本にシリーズがない場合、テンプレートは - - タイトル を生成することになりますが、これはおそらくあなたが望むものではないでしょう。一般的に人々は、意味のないハイフンのないただのタイトルとなることを望むものです。これは、次のテンプレート構文を使用すれば達成できます:

{field:|prefix_text|suffix_text}

この テンプレート表現field の値が XXXX の場合、結果は prefix_textXXXXXsuffix_text になることを示しています。field が空 (値がない) 場合、プレフィックスとサフィックスが無視されるため、結果は空の文字列 (なし) となります。プレフィックスとサフィックスには空白を含めることができます。

プレフィックスとサフィックスには、サブテンプレート (`{ ... }`) や関数 (下を参照) を使用しないでください。

この構文を使用すると、テンプレートで上記のシリーズなしの問題を解決できます。

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

ハイフンは、本にシリーズインデックスがある場合にのみ含まれます。シリーズインデックスはシリーズがある場合にのみ含まれます。 Foundationの例を再び続けると、テンプレートは Foundation - 1 - Second Foundation を生成します。

メモ:

  • プレフィックスやサフィックスを使用している場合は、ルックアップ名 の後にコロンを含める必要があります。

  • | の文字は、使用しないか両方使用するかのどちらかです。{field:| - } のようなひとつだけの使用は許されません。

  • プレフィックスやサフィックスにテキストを指定せず、{series:|| - } にしてもかまいません。テンプレート {title:||}`{title} と同じです。

書式設定

series_index を先行ゼロ付きの 3 桁に整形したいとします。次のようにすればそうできます:

{series_index:0>3s} - 先行ゼロ付きの 3 桁

後置ゼロには、次を使います:

{series_index:0<3s} - 後置ゼロ付きの 3 桁

1.1 などの小数値のシリーズインデックスを使用する場合は、小数点の位置を揃えたい場合があります。たとえば、インデックス 1 と 2.5 を 01.00 と 02.50 として表示して、辞書順に並べ替えを行うデバイスで正しく並べ替えられるようにすることができます。これを行うには、次を使用します:

{series_index:0>5.2f} - 先行ゼロ付きの 2 桁、小数点、および小数点以下 2 桁で構成される 5 文字。

データの最初の 2 文字だけが必要な場合は、次を使用します:

{author_sort:.2} - 著者読みの最初の 2 文字のみ

calibre テンプレート言語のフォーマットの多くは Python のものです。これらの高度なフォーマット操作の構文の詳細については、 Python documentation を参照してください。

テンプレートを使用してカスタム列を定義する

テンプレートを使用すると、calibre の書誌にない情報を表示したり、calibre の通常の形式とは異なる方法で書誌を表示したりできます。たとえば、calibre が表示しないフィールドである ISBN を表示したいことがあるかもしれません。これは、他の列から構築された列 タイプ (以降、複合列と呼びます) を使用してカスタム列を作成し、表示されるテキストを生成するためのテンプレートを提供することで実現できます。この列には、テンプレートの評価結果が表示されます。たとえば、ISBN を表示するには、列を作成し、テンプレートボックスに {identifiers:select(isbn)} と入力します。 2 つのシリーズカスタム列の値をカンマで区切って含む列を表示するには、{#series1:||,}{#series2} を使用します。

複合列は、書式設定を含む任意のテンプレートオプションを使用できます。

注: 複合列に表示されているデータを編集することはできません。代わりに、ソース列を編集します。複合列を編集する場合、たとえばダブルクリックした場合、calibreは、基になるデータではなく、編集用のテンプレートを開きます。

テンプレートでの関数の使用 - 単関数モード

あるフィールドが通常はタイトルケースで、その値を大文字で表示したいと仮定します。テンプレート関数 を使用すれば、それが可能です。たとえば、タイトルを大文字で表示するには uppercase 関数を使用して、{title:uppercase()}` とします。タイトルケースで表示するには {title:titlecase()} を使用します。

関数は、テンプレートのフォーマット部分に入ります。それは : の後、かつ最初の | またはプレフィックス/サフィックスが使われていれば閉じ括弧 } の前です。フォーマットと関数参照の両方がある場合、関数は 2 個目の : の後に来ます。関数は、テンプレートで指定された列の値を適切に変更して返します。

関数を使用するための構文は、次のいずれかです:

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

関数名の後には、必ず開き括弧と閉じ括弧を付ける必要があります。一部の関数は追加の値 (引数) を必要とし、これらは括弧内に入ります。引数はカンマで区切ります。リテラルコンマ (引数の区切り文字ではなくテキストとしてのカンマ) の前には、バックスラッシュ (\) を付ける必要があります。最後の (または唯一の) 引数には、テキストの閉じ括弧を含めることはできません。

関数は、フォーマット指定とプレフィックス/サフィックスの前に評価されます。フォーマットと関数の両方を使用する例については、さらに下を参照してください。

重要: プログラミングの経験がある場合は、単関数モード の構文が思ったものと違うことに注意してください。文字列は引用符で囲まれておらず、スペースは重要です。すべての引数は定数と見なされます。式はありません。

**サブテンプレート ({ ... }) を関数の引数として使用しないでください。**代わりに テンプレートプログラムモード および 一般プログラムモード を使用してください。

一部の関数には正規表現が必要です。テンプレート言語では、正規表現のマッチでは大文字と小文字が区別されません。

以下の関数説明書では、[something]* という表記は something が 0 回以上繰り返される可能性があることを意味しています。[something]+ という表記は something が 1 回以上繰り返される (1 回は必ず存在する) ことを意味しています。

単関数モードでの利用が想定されている関数は:

  • capitalize() -- 最初の文字が大文字で残りが小文字の値を返します。

  • contains(pattern, text if match, text if not match) -- 値が正規表現 pattern とマッチするかどうかを調べます。pattern が値にマッチすれば text if match を返し、そうでなければ text if no match を返します。

  • count(separator) -- 値を separator で区切られた項目のリストとして解釈し、リスト内の項目数を返します。ほとんどのリストは区切り文字としてカンマを使用しますが、authors はアンパーサンド (&) を使用します。例: {tags:count(,)}, {authors:count(&)}. Aliases: count(), list_count()

  • format_number(template) -- 値を数値として解釈し、その数値を Python 整形テンプレートを使用して {0:5.2f}{0:,d}${0:5,.2f} のように整形します。上の例に示されるように、整形テンプレートは必ず {0: で始め、 } で終わらなくてはなりません。例外: 整形テンプレートに書式がひとつしか含まれていない場合には、先頭の "{0:" と末尾の "}" を省略可能です。その他の例については Python 説明書 を参照してください。整形に失敗した場合には、空の文字列を返します。

  • human_readable() -- 値が数値であると想定し、その数値を KB、MB、GB などで表す文字列を返します。

  • ifempty(text if empty) -- 値が空でない場合はフィールドの値を返し、そうでない場合は text if empty を返します

  • in_list(separator, [ pattern, found_val, ]* not_found_val) -- 値を separator で区切られた項目のリストと解釈し、リスト内の各項目に対して pattern をチェックします。pattern が項目にマッチする場合は found_val を返し、そうでなければ not_found_val を返します。patternfound_value のペアは好きなだけ繰り返すことができるので、項目の値に応じて異なる値を返すことができます。pattern は順番にチェックされ、最初にマッチしたものが返されます。

  • language_strings(localize) -- 渡された値の 言語コード言語名 を返します。例: {languages:language_strings()} もし localize がゼロなら、英語の文字列を返します。localize がゼロでなければ、現在のロケールの言語の文字列を返します。Lang_codes はカンマ区切りのリストです。

  • list_item(index, separator) -- 値を separator で区切られた項目のリストと解釈し、'index' 番目の項目を返します。最初の項目はゼロ番目です。最後の項目は -1 番目で、list_item(-1,separator)` のように指定します。項目がリストの中になければ、空の文字列を返します。

  • lookup([ pattern, key, ]* else_key) -- pattern は値に対して順番にチェックされます。pattern がマッチしたら、key で指定されたフィールドの値を返します。pattern にマッチするものがなければ、 else_key で指定されるフィールドの値を返します。switch (下記) を参照のこと。

  • lowercase() -- フィールドの値を小文字にして返します。

  • rating_to_stars(use_half_stars) -- 星 () の文字列で評価を返します。値は 0 から 5 までの数値でなくてはなりません。カスタム評価列で使用可能な小数値に星半分を使いたい場合は、use_half_stars に 1 を設定します。

  • re(pattern, replacement) -- 正規表現を適用した後に値を返します。値の中にある pattern のインスタンスはすべて replacement に置換されます。テンプレート言語では、大文字と小文字を区別しない Python 正規表現 を使用します。

  • select(key) -- 値を項目のカンマ区切りリストとして解釈します。項目はそれぞれ id:value (calibre の identifier ID形式) の形式です。この関数は、id が key に等しい最初のペアを見つけて、対応する値を返します。一致するIDがなければ、関数は空の文字列を返します。

  • shorten(left chars, middle text, right chars) -- 値の短縮バージョンを返します。短縮バージョンは値の先頭から left chars で指定した文字数分の文字列、その次に middle text、その後ろに値の末尾から right chars で指定した文字数分の文字列で構成されます。Left chars および right chars 負でない整数でなければなりません。例: 最大 15 文字の長さのタイトルを表示するとします。これを行うテンプレートの一例は、 {title:shorten(9,-,5)} です。Ancient English Laws in the Times of Ivanhoe というタイトルの本の場合は Ancient E-anhoe: タイトルの最初の 9 文字, -, そして末尾の 5 文字です。 値の長さが left chars + right chars + middle text の長さよりも短ければ、変更せずに返されます。たとえば The Dome は変更されません。

  • str_in_list(separator, [ string, found_val, ]+ not_found_val) -- 値を separator で区切られた項目のリストとして解釈し、string をリスト内の各値と比較します。string は正規表現ではありません。string が任意の項目と等しい場合 (大文字と小文字を区別しない)、対応する found_val を返します。stringseparators が含まれていればリストとしても扱われ、各サブ値がチェックされます。stringfound_value のペアは好きなだけ繰り返すことができ、文字列の値の応じて異なる値を返すことができます。マッチする文字列がなければ not_found_value が返されます。文字列は順番にチェックされ、最初にマッチしたものが返されます。

  • subitems(start_index, end_index) -- この関数は、ジャンルのようなタグに似た回想項目を分買いします。値はタグに似たカンマ区切りのリスト項目と解釈されます。ここでの項目は、ピリオド区切りのリストです。各項目から start_index から end_index までの要素を抽出して作った新しいリストを返し、その結果を一緒にマージします。重複は削除されます。ピリオド区切りのリストにある最初のサブ項目のインデックスはゼロです。インデックスが負の値であれば、リストの後ろから数えます。特殊なケースとして、ゼロの end_index はリストの長さと解釈されます。

    例:

    • #genre 列に A.B.C が含まれていると仮定すると:

      • {#genre:subitems(0,1)} は "A" を返します

      • {#genre:subitems(0,2)} は "A.B" を返します

      • {#genre:subitems(1,0)} は "B.C" を返します

    • #genre 列に "A.B.C, D.E" が含まれていると仮定すると:

      • {#genre:subitems(0,1)} は "A, D" を返します

      • {#genre:subitems(0,2)} は "A.B, D.E" を返します

  • sublist(start_index, end_index, separator) -- 値を separator で区切られた項目のリストとして解釈し、項目の start_index から end_index で作られた新しいリストを返します。項目の最初の番号はゼロです。インデックスが負の値であれば、リストの後ろから数えます。特殊なケースとして、ゼロの end_index はリストの長さと解釈されます。

    タグ列 (カンマ区切り) に "A, B ,C" が含まれていると仮定した例:

    • {tags:sublist(0,1,\,)} は "A" を返します

    • {tags:sublist(-1,0,\,)} は "C" を返します

    • {tags:sublist(0,-1,\,)} は "A, B" を返します

  • swap_around_articles(separator) -- 記事を最後に移動した値を返します。値はリストにすることもでき、その場合にはリスト内の各項目が処理されます。値がリストのときには、separator を指定する必要があります。separator の指定がなければ値はリストではなく単一の値として扱われます。記事title_sort を生成するために calibre によって使用される記事です。

  • swap_around_comma() -- B, A` の形式の値を指定すると A B を返します。これは「姓, 名」の形式の名前を「名 姓」に変換するのに最適です。値の中にカンマがなければ、関数は値を変更せずに返します。

  • switch([pattern, value,]+ else_value) -- pattern, value のペアごとに値が正規表現 pattern にマッチするか確認し、マッチすれば対応する value を返します。pattern にマッチするものがなければ else_value を返します。pattern, value のペアは好きなだけ繰り返すことができます。最初にマッチしたものが返されます。

  • test(text if not empty, text if empty) -- 値が空でなければ text if not empty を返し、空なら text if empty を返します。

  • titlecase() -- フィールドの値をタイトルケースにして返します。

  • transliterate() --ソースフィールドの単語の音を近似することによって形成されたラテンアルファベットの文字列を返します。たとえば、ソースフィールドが Фёдор Миха́йлович Достоевский の場合、この関数は Fiodor Mikhailovich Dostoievskii を返します。

  • uppercase() -- フィールドの値を大文字にして返します。

同じテンプレートで関数と書式を使用する

整数のカスタム列 #myint003 のように先行ゼロ付きで表示したいと仮定します。これを実現する方法のひとつは 0>3s という書式を使用することです。ただしデフォルトでは数値 (整数または浮動小数点) がゼロに等しい場合には、その値は空の文字列として表示されるため、値ゼロは 000 ではなく空の文字列となります。値を 000 と表示したいのであれば、書式文字列と ifempty 関数を両方使用して空の値をゼロに戻してやります。そのテンプレートは次のようになるでしょう:

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

プレフィックスとサフィックスも使用できます。もし数字を [003][000] のように表示したいのであれば、次のテンプレートを使用します:

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

一般プログラムモード

一般プログラムモード (GPM) は テンプレート表現テンプレート言語 で記述したプログラムに置き換えます。言語の構文は、次の文法で定義されます:

program         ::= 'program:' expression_list
expression_list ::= top_expression [ ';' top_expression ]*
top_expression  ::= or_expression
or_expression   ::= and_expression [ '||' and_expression ]*
and_expression  ::= not_expression [ '&&' not_expression ]*
not_expression  ::= [ '!' not_expression ]* | compare_exp
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

メモ:

  • top_expression には常に値があります。expression_list の値は、リストの最後の top_expression の値です。たとえば、式リストの値 1;2;'foobar';33 です。

  • 論理的なコンテキストでは、空でない値はすべて True

  • 論理的なコンテキストでは、空の値はすべて False

  • 文字列と数字は同じ意味で使用できます。たとえば 10'10' は同じものです。

  • コメントは '#' 文字で始まる行です。行の途中から始まるコメントはサポートされていません。

演算子の優先順位

演算子の優先順位 (評価する順) の最高 (最初に評価) から最低 (最後に評価) までは、次のとおりです:

  • 関数呼び出し、定数、括弧で囲まれた式、比較演算式、代入式、フィールド参照。

  • 単項プラス (+) およびマイナス (-)。これらの演算子は右から左に評価します。

    これらおよび他のすべての算術演算子は、式の小数部がゼロならば整数を返します。たとえば式が 3.0 を返す場合、それは 3 に変更されます。

  • 乗算 (*) と除算 (/)。これらの演算子は結合性があり、左から右に評価します。評価の順序を変更する場合は、括弧を使用してください。

  • 加算 (+) と減算 (-)。これらの演算子は結合性があり、左から右に評価します。

  • 数値と文字列の比較。これらの演算子は、比較が成功した場合は '1' を返し、それ以外の場合は空の文字列 ('')を返します。比較は連想的ではありません。 a < b < c は構文エラーです。

  • 文字列の連結 (&)。& 演算子は、左辺と右辺の式を連結して形成された文字列を返します。例: 'aaa' & 'bbb''aaabbb' を返します。演算子は結合性があり、左から右に評価します。

  • 単項論理否定 (!)。この演算子は、式が False (空の文字列に評価される) なら ``'1'``を返し、そうでなければ ``''``を返します。

  • 論理積 (&&)。この演算子は、左辺と右辺の両方の式が True のときに '1' を返し、どちらかが False なら空の文字列 '' を返します。これは連想的で、左から右に評価し、 短絡評価 を行います。

  • 論理和 (||)。この演算子は、左辺または右辺の式のいずれかが True であれば '1'``を返し、両方とも False なら ``'' を返します。これは連想的で、左から右に評価し、 短絡評価 を行います。 これは 包含的論理和 で、左辺または右辺の式の両方が True のときに '1' を返します。

フィールド参照

field_reference$ または $$ に続くルックアップ名で指定された書誌フィールドの値に評価されます。$ の使用は field() 関数の使用と同等です。$$ の使用は raw_field 関数の使用と同等です。例:

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

if 文

If 文は最初に condition を評価します。condition が True (空でない値) であれば、then 句の中にある expression_list が評価されます。False なら elif または else 句の中に expression_list があればそれが評価されます。elifelse の部分はオプションです。if, then, elif, else, および fi は予約語です。識別子の名前として使用することはできません。 意味のあるところならどこにでも改行と空白を置くことができます。conditiontop_expression であって expression_list ではありません。セミコロンは使用できません。expression_liststop_expressions のセミコロン区切りのシーケンスです。if 文は評価した expression_list の中で最後の top_expression を返し、評価したものがなければ空の文字列を返します。

例:

* program: if field('series') then 'yes' else 'no' fi
* program:
      if field('series') then
          a = 'yes';
          b = 'no'
      else
          a = 'no';
          b = 'yes'
      fi;
      strcat(a, '-', b)

入れ子になった if の例:

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

上で説明したように if は値を生成します。これは、次のすべてが同等であることを意味します:

* program: if field('series') then 'foo' else 'bar' fi
* program: if field('series') then a = 'foo' else a = 'bar' fi; a
* program: a = if field('series') then 'foo' else 'bar' fi; a

最後の例として、このプログラムは、本にシリーズがある場合は シリーズ 列の値を返し、そうでない場合は タイトル 列の値を返します:

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

for 文

for 文は値のリストを反復処理し、一度にひとつずつ処理します。 list_expressiontags#genre などの書誌フィールド ルックアップ名、または値のリストのいずれかに評価される必要があります。range() 関数 (下を参照) は数値のリストを生成します。 結果が有効な ルックアップ名 であればフィールドの値がフェッチされ、そのフィールドタイプに指定されたセパレータが使用されます。結果が有効なルックアップ名でない場合は、値のリストであると見なされます。オプションのキーワード separator が指定されていない限り、リストはコンマで区切られていると見なされます。指定されている場合、リスト値は、 separator_expr``の評価結果で区切る必要があります。``range() で生成されたリストには区切り文字は使用できません。リスト内の各値は指定された変数に割り当てられ、expression_list が評価されます。break を使ってループから抜けることもでき、continue を使うと次の反復のためにループの先頭に移動します。

例: このテンプレートは、ジャンル (#genre) の各値の最初の階層名を削除し、新しい名前でリストを作成します:

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

元のジャンルが History.Military, Science Fiction.Alternate History, ReadMe の場合、テンプレートは Military, Alternate History, ReadMe を返します。このテンプレートを calibre の 書誌を一括編集  →  検索と置換検索template を設定して階層の最初のレベルを取り除き、結果の値をジャンルに割り当てます。

注: この場合、テンプレートの最後の行である new_tags は必ずしも必要ではありません。これは、for が式リストの最後の top_expression の値を返すためです。割り当ての値はその式の値であるため、for 文の値は new_tags に割り当てられたものです。

関数の定義

テンプレートの中に繰り返されるコードがある場合は、そのコードをローカル関数に配置できます。def キーワードで定義を開始します。その後に関数名、引数リスト、関数内のコードが続きます。関数定義は fed キーワードで終了します。

引数はキーワード引数です。関数が呼び出されると、指定された引数が定義されたパラメータに対して左から右に照合され、引数の値がパラメータに割り当てられます。定義されたパラメータよりも多くの引数を指定するとエラーになります。パラメータには、a = 25 などのデフォルト値を設定できます。そのパラメータに引数が指定されていない場合はデフォルト値が使用され、それ以外の場合はパラメータが空の文字列に設定されます。

return 文はローカル関数の中で使用できます。

関数は、使用する前に定義する必要があります。

例: このテンプレートは、日数から年、月、日でおおよその期間を計算します。関数 to_plural()` は、計算された値を整形します。ただしこの例では``&`` 演算子も使用してます::eo

program:
      days = 2112;
      years = floor(days/360);
      months = floor(mod(days, 360)/30);
      days = days - ((years*360) + (months * 30));

      def to_plural(v, str):
              if v == 0 then return '' fi;
              return v & ' ' & (if v == 1 then str else str & 's' fi) & ' '
      fed;

      to_plural(years, 'year') & to_plural(months, 'month') & to_plural(days,'day')

関係演算子

関係演算子は、比較が真なら ``'1'``を返し、そうでなければ空の文字列 ('') を返します。

関係演算子は 2 種類あり、それは文字列比較と数値比較です。

文字列の比較では、大文字と小文字を区別しない文字列比較を辞書順で行います。サポートされている文字列比較演算子は、==, !=, <, <=, >, >=, in, および inlist です。 in 演算子の場合、左側の式の結果は正規表現パターンとして解釈されます。左側の正規表現の値が右側の式の値とマッチする場合、in 演算子は True です。左側の正規表現が、リスト内の項目がカンマで区切られている右側のリスト内の項目のいずれかにマッチする場合、inlist 演算子は True です。マッチには大文字と小文字は区別されません。

数値比較演算子は、==#, !=#, <#, <=#, >#, >=# です。左と右の式は、2 つの例外を除いて数値に評価される必要があります。文字列値 "None" (未定義のフィールド) と空の文字列の両方が値ゼロに評価されます。

例:

  • program: field('series') == 'foo' は本のシリーズが 'foo' であれば '1' を返し、そうでなければ '' を返します。

  • program: 'f.o' in field('series') は、本のシリーズが正規表現 f.o (例: foo, Off Onyx, など) とマッチすれば '1' を返し、そうでなければ '' を返します。

  • program: 'science' inlist field('#genre') は、本のジャンルのいずれかが正規表現 science, (例: Science, History of Science, Science Fiction など) とマッチすれば '1' を返し、そうでなければotherwise '' を返します。

  • program: '^science$' inlist field('#genre') は、本のジャンルのいずれかが正規表現 ^science$ に完全一致すれば (例: Science) '1' を返します。ジャンル History of ScienceScience Fiction はマッチしません。マッチするものがなければ '' を返します。

  • program: if field('series') != 'foo' then 'bar' else 'mumble' fi は、本の series が foo でなければ 'bar' を返します。それ以外のときには 'mumble' を返します。

  • program: if field('series') == 'foo' || field('series') == '1632' then 'yes' else 'no' fi は、本の series が 'foo' または '1632' のとき 'yes' を返し、それ以外のときにいは 'no' を返します。

  • program: if '^(foo|1632)$' in field('series') then 'yes' else 'no' fi は series が 'foo' または '1632' なら 'yes'``を返し、それ以外のときには ``'no' を返します。

  • program: if 11 > 2 then 'yes' else 'no' fi'no' を返します。なぜなら > 演算子が辞書比較を行うからです。

  • program: if 11 ># 2 then 'yes' else 'no' fi'yes' を返します。なぜなら ># 演算子は数値比較を行うからです。

利用可能な追加の関数

単関数モード で説明したものに加えて、次の関数が利用できます。

GPM では、単関数モード で説明されている機能はすべて、操作する値を指定する最初のパラメータを追加で必要とします。すべてのパラメータは expression_lists です (上記の文法を参照)。

  • add(x [, y]*) -- 引数の合計を返します。引数が数値でない場合は、例外をスローします。ほとんどの場合、この関数の代わりに + 演算子を使用できます。

  • and(value [, value]*) -- すべての値が空でない場合は文字列 "1" を返し、そうでない場合は空の文字列を返します。必要な数だけ値を持つことができます。ほとんどの場合、この関数の代わりに && 演算子を使用できます。and&& を置き換えない理由のひとつは、副作用により短絡評価が結果を変えてしまう可能性があるためです。たとえば、and(a='',b=5) は常に両方の割り当てを行いますが、&& 演算子は 2 番目の割り当てを行いません。

  • assign(id, val) -- valid に割り当ててから、val を返します。 id は、式ではなく識別子でなくてはなりません。ほとんどの場合、この関数の代わりに = 演算子を使用できます。

  • approximate_formats() -- 本に関連付けられている形式のカンマ区切りリストを返します。おそらく正しいとはいえ、リストが正しいという保証はありません。この関数およびその他のゼロパラメータ関数は、テンプレート {:'approximate_formats()'} を使用してテンプレートプログラムモード (以下を参照) で呼び出すことができます。結果の形式名は、EPUB の場合と同様に、常に大文字となります。approximate_formats() 関数は、以下で説明する ``formats_... `` 関数よりも大幅に高速です。

  • author_links(val_separator, pair_separator) -- 著者のリストとそれらの著者のリンク値を含む文字列を次の形式で返します:

    author1 val_separator author1_link pair_separator author2 val_separator author2_link etc.
    

    作成者は、スペースを追加せずに val_separator 文字列によってリンク値から分離されます。 author:linkvalue のペアは、スペースを追加せずに、pair_separator 文字列引数で区切られます。著者名やリンクに含まれない区切り文字列を選択してください。著者リンクが空の場合でも、著者が含まれます。

  • author_sorts(val_separator) -- 本の著者の著者読みの値のリストを含む文字列を返します。著者読みは、著者の書誌情報に含まれるものです (本の author_sort とは異なります)。author sort 1 val_separator author sort 2 などの形のリストを返します。スペースは追加されません。このリストの著者読みの値は、本の著者と同じ順序です。 val_separator の前後にスペースが必要な場合は、それらを val_separator 文字列に含めます。

  • book_count(query, use_vl) -- returns the count of books found by searching for query. If use_vl is 0 (zero) then virtual libraries are ignored. This function and its companion book_values() are particularly useful in template searches, supporting searches that combine information from many books such as looking for series with only one book. It cannot be used in composite columns unless the tweak allow_template_database_functions_in_composites is set to True. It can be used only in the GUI.

    For example this template search uses this function and its companion to find all series with only one book:

    1. Define a stored template (using Preferences → Advanced → Template functions) named series_only_one_book (the name is arbitrary). The template is:

      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, '')
      

    The first time the template runs (the first book checked) it stores the results of the database lookups in a global template variable named vals. These results are used to check subsequent books without redoing the lookups.

    1. Use the stored template in a template search:

      template:"program: series_only_one_book()#@#:n:1"
      

    Using a stored template instead of putting the template into the search eliminates problems caused by the requirement to escape quotes in search expressions.

  • book_values(column, query, sep, use_vl) -- returns a list of the unique values contained in the column column (a lookup name), separated by sep, in the books found by searching for query. If use_vl is 0 (zero) then virtual libraries are ignored. This function and its companion book_count() are particularly useful in template searches, supporting searches that combine information from many books such as looking for series with only one book. It cannot be used in composite columns unless the tweak allow_template_database_functions_in_composites is set to True. It can be used only in the GUI.

  • booksize() -- calibre の 'size' フィールドの値を返します。形式がない場合は '' を返します。

  • check_yes_no(field_name, is_undefined, is_false, is_true) -- ルックアップ名 field_name で指定された yes/no フィールドの値がパラメータで指定された値のいずれかであるかどうかをチェックし、一致が見つかった場合は 'yes' を返し、そうでなければ空の文字列を返します。パラメータ``is_undefined``, is_false, または ``is_true``を1(数値)に設定してその条件を確認します。それ以外の場合は0に設定します。例:

    check_yes_no("#bool", 1, 0, 1) は、yes/no フィールド #bool が True または未定義 (True でも False でもない) ときに 'yes' を返します。

    is_undefined, is_false, または is_true のうち複数を 1 に設定できます。

  • ceiling(x) -- x 以上の最小の整数を返します。 x が数値でない場合、例外をスローします。

  • character(character_name) -- character_name で指定された文字を返します。たとえば、character('newline') は改行文字 ('\n')を返します。サポートしている文字名は、newline, return, tab, および backslash です。

  • cmp(x, y, lt, eq, gt) -- xy の両方を数値に変換した後、それらを比較します。x <# y なら ltx ==# y なら eq を返し、それ以外の場合は gt を返します。この関数は通常、数値比較演算子(==#, <#, ># など)のひとつに置き換えることができます。

  • connected_device_name(storage_location_key) -- デバイスが接続されていればデバイス名を返し、そうでない場合は空の文字列を返します。デバイスの各保管場所には、独自のデバイス名があります。storage_location_key の名前は、'main', 'carda' および ``'cardb'``です。この機能は GUI でのみ機能します。

  • connected_device_uuid(storage_location_key) -- デバイスが接続されていればデバイスのuuid (一意のID) を返します。それ以外の場合は、空の文字列を返します。デバイスの保存場所ごとに異なる uuid がついています。storage_location_key の名前は、'main', 'carda' および ``'cardb'``です。この機能は GUI でのみ機能します。

  • current_library_name() -- 現在の calibre ライブラリへのパスの最後の名前を返します。

  • current_library_path() -- 現在の calibre ライブラリへのフルパスを返します。

  • current_virtual_library_name() -- 現在の仮想ライブラリがある場合はその名前を返します。ない場合は空の文字列を返します。ライブラリ名の大文字小文字は保持されます。例: program: current_virtual_library_name()。この機能はGUIでのみ機能します。

  • date_arithmetic(date, calc_spec, fmt) -- calc_spec を使用して date から新しい日付を計算します。オプションの fmt に従って整形された新しい日付を返します。指定されていない場合、結果は ISO 書式になります。 calc_specは、vW (valueWhat) のペアを連結して形成された文字列です。ここで、v は負の可能性のある数値であり、Wは次のいずれかの文字です:

    • s: datev 秒を加算

    • m: datev 分を加算

    • h: datev 時間を加算

    • d: datev 日を加算

    • w: datev 週間を加算

    • y: datev 年を加算、ただし 1 年は 365 日

    例: '1s3d-1m'date に 1 秒を加算、3 日を加算、1 分を減算します。

  • days_between(date1, date2) -- rdate1とdate2の間の日数を返します。 date1date2``より大きい場合、数値は正であり、それ以外の場合は負です。``date1 または ``date2``のいずれかが日付でない場合、関数は空の文字列を返します。

  • divide(x, y) -- x / y を返します。x または y のいずれかが数値でない場合、例外をスローします。この関数は通常、 / 演算子で置き換えることができます。

  • eval(string) -- 文字列をプログラムとして評価し、ローカル変数を渡します。これにより、テンプレートプロセッサを使用して、ローカル変数から複雑な結果を作成できます。テンプレートプログラムモード <template_mode>`では、テンプレートが評価される前に `{ および } の文字が解釈されるため、} の文字には [[} の文字には ]] を使用する必要があります。これは自動的に変換されます。テンプレートプログラムモード を使用している場合、この関数の引数にプレフィックスとサフィックス (|prefix|suffix 構文) を使用できないことにも注意してください。

  • field(lookup_name) -- ルックアップ名 lookup_name の書誌フィールドの値を返します。

  • field_exists(field_name) -- ルックアップ名 field_name のフィールド(列)が存在するかどうかを確認し、存在すれば '1' を返し、存在しない場合は空の文字列を返します。

  • finish_formatting(val, fmt, prefix, suffix) -- {series_index:05.2f| - |- } のようなテンプレートで行われるのと同じ方法で、フォーマット、プレフィックス、およびサフィックスを値に適用します。この関数は、複雑な単関数モードやテンプレートプログラムモードのテンプレートから GPM テンプレートへの変換を容易にするために提供されています。たとえば次のプログラムは、上記のテンプレートと同じ出力を生成します:

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

    別の例: テンプレート {series:re(([^\s])[^\s]+(\s|$),\1)}{series_index:0>2s| - | - }{title} には次を使用します:

    program:
      strcat(
        re(field('series'), '([^\s])[^\s]+(\s|$)', '\1'),
           finish_formatting(field('series_index'), '0>2s', ' - ', ' - '),
           field('title')
      )
    
  • first_matching_cmp(val, [ cmp, result, ]* else_result) -- val < cmp を順番に比較し、成功した最初の比較に関連づけられた結果を返します。比較が成功しなかった場合は else_result を返します。例:

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

    これは "large" を返します。同じ例で最初の値を 16 にすると "giant" を返します。

  • first_non_empty(value [, value]*) -- 空ではない最初の value を返します。すべての値が空の場合、空の文字列が返されます。必要なだけの数の value を渡すことができます。

  • floor(x) -- x 以下の最大の整数を返します。x が数値でない場合、例外をスローします。

  • format_date(val, format_string) -- format_string を使用して、文字列を返す値を整形します。これは日付文字列である必要があります。書式コードは次のとおりです:

    • d    : 先行ゼロのない数値としての日 (1から31)

    • dd   : 先行ゼロ付きの数値としての日 (01 to 31)

    • ddd  : ローカライズされた曜日の省略名 (例: "Mon" から "Sun").

    • dddd : ローカライズされた曜日の正式名 (例: "Monday" から "Sunday").

    • M    : 先行ゼロのない数値としての月 (1 から 12).

    • MM   : 先行ゼロ付きの数値としての月 (01 から 12)

    • MMM  : ローカライズされた月の省略名 (例: "Jan" から "Dec").

    • MMMM : ローカライズされた月の正式名 (例: "January" to "December").

    • yy   : 2 桁の数字としての年 (00 から 99)

    • yyyy : 4 桁の数字としての年

    • h    : 先行ゼロのない時間 (am/pm に応じて 0 から 11 または 0 から 23)

    • hh   : 先行ゼロ付きの時間 (am/pm に応じて 00 から 11 または 00 から 23)

    • m    : 先行ゼロのない分 (0 から 59)

    • mm   : 先行ゼロ付きの分 (00 から 59)

    • s    : 先行ゼロのない秒 (0 から 59)

    • ss   : 先行ゼロ付きの秒 (00 から 59)

    • ap   : 24時間制ではなく12時間制を使用し、 'ap' を午前または午後のローカライズされた文字列に置き換えます。

    • AP   : 24時間制ではなく12時間制を使用し、'AP' を AM または PM のローカライズされた文字列に置き換えます。

    • iso  : 時間とタイムゾーンのある日付。単独で使用すること。

    • to_number   : 日付と時刻を浮動小数点数 (タイムスタンプ) に変換します

    • from_number : 浮動小数点数 (タイムスタンプ) を iso 書式の日付に変換します。別の日付書式が必要な場合は、from_number とコロン (:)の後に目的の書式文字列を追加します。例: from_number:MMM dd yyyy

    整形する日付にローカライズされた月の名前が含まれていると、予期しない結果が生じる可能性があります。これは、日付書式の tweak を MMMM を含むように変更した場合に発生する可能性があります。この場合、代わりに field() 関数を次のように使用します:

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

    次のように raw_field() 関数を使用します:

    format_date(raw_field('pubdate'), 'yyyy')
    
  • formats_modtimes(date_format_string) -- コロンで区切られたアイテムのコンマ区切りのリストを返します。 FMT:DATE は、本の形式の変更時刻を表します。 date_format_string パラメータは、日付の整形方法を指定します。詳しくは format_date() 関数を参照してください。select 関数を使用すると、特定の形式の変更時刻を取得できます。 EPUB のように、形式名は常に大文字となります。

  • formats_paths() -- コロンで区切られたアイテムのコンマ区切りのリストを返します。FMT:PATH は、本の形式へのフルパスを示します。 select 関数を使用すると、特定の形式のパスを取得できます。 EPUB のように、形式名は常に大文字となります。

  • formats_sizes() -- コロンで区切られたFMT:SIZEアイテムのコンマ区切りのリストを返し、本の形式のサイズをバイト単位で示します。 select 関数を使用して、特定の形式のサイズを取得できます。 EPUB のように、形式名は常に大文字となります。

  • fractional_part(x) -- 小数点以下の値を返します。たとえば fractional_part(3.14)0.14 を返します。x が数値でない場合、例外をスローします。

  • has_cover() -- 本に表紙があれば 'Yes' を返し、そうでなければ空の文字列を返します。

  • is_marked() -- 本が calibre でマークされているかどうかを確認します。マークされていればマークの値を返します。マークの値は 'true' (小文字) または名前付きマークのコンマ区切りリストのいずれかです。本がマークされていない場合は、 '' (空の文字列) を返します。この機能は GUI でのみ機能します。

  • language_codes(lang_strings) -- lang_strings`で渡された言語名の `言語コード を返します。文字列は、現在のロケールの言語でなくてはなりません。Lang_strings はコンマ区切りのリストです。

  • list_contains(value, separator, [ pattern, found_val, ]* not_found_val) -- (in_list の別名) 値を separator で区切られた項目のリストとして解釈し、リスト内の各値に対して pattern を評価します。pattern がいずれかの値とマッチすれば found_val を返し、そうでなければ not_found_val を返します。patternfound_value は必要な回数だけ繰り返すことができ、検索によって異なる値を返すことができます。patterm は順番にチェックされます。最初のマッチが返されます。別名: in_list(), list_contains()

  • list_count(value, separator) -- valueseparator で区切られた項目のリストとして解釈し、リスト内の項目の数を返します。別名: count(), list_count()

  • list_count_matching(list, pattern, separator) -- listseparator で区切られた項目のリストとして解釈し、正規表現 pattern にマッチするリスト内の項目の数を返します。別名: list_count_matching(), count_matching()

  • list_difference(list1, list2, separator) -- 大文字と小文字を区別しない比較を使用して、list2 で見つかった項目を list1 から削除して作成されたリストを返します。 list1list2 の項目、および返されたリストの項目は、いずれも separator で区切られます。

  • list_equals(list1, sep1, list2, sep2, yes_val, no_val) -- list1list2 に同じ項目が含まれていれば yes_val を返し、そうでなければ no_val を返します。項目は、適切な区切り文字 (sep1 または sep2) を使用して各リストを分割することによって決定されます。リスト内の項目の順序は関係ありません。比較では大文字と小文字は区別されません。

  • list_intersection(list1, list2, separator) -- 大文字と小文字を区別しない比較を使用して、list2 にない項目を list1 から 削除して作成されたリストを返します。 list1list2 の項目、および返されたリストの項目は、いずれも separator で区切られます。

  • list_join(with_separator, list1, separator1 [, list2, separator2]*) -- ソースリスト (list1 など) の項目と結果リストの項目を with_separator を使用して結合して作成されたリストを返します。各ソース list[123...] の項目は、対応する``separator[123...]`` で区切られています。リストにはゼロ値を含めることができます。これは、値をひとつしか持たない、事実上 1 項目のリストである publisher のようなフィールドにすることができます。重複は、大文字と小文字を区別しない比較を使用して削除します。項目は、ソースリストに表示されている順序で返されます。リストの項目が大文字と小文字の違いしかない場合は、最後のものが使用されます。区切り文字はすべて、複数の文字にすることができます。

    例:

    program:
      list_join('#@#', $authors, '&', $tags, ',')
    

    次のように list_join への以前の呼び出しの結果に list_join を使用できます:

    program:
      a = list_join('#@#', $authors, '&', $tags, ',');
      b = list_join('#@#', a, '#@#', $#genre, ',', $#people, '&', 'some value', ',')
    

    式を使用してリストを生成できます。たとえば authors と `` #genre`` の項目が必要だと仮定して、しかしジャンルが "Genre: " の後にそのジャンルの頭文字をつけた単語に変更されるとします。つまりジャンル "Fiction" は "Genre: F" になります。次のようにするとそれを行います:

    program:
      list_join('#@#', $authors, '&', list_re($#genre, ',', '^(.).*$', 'Genre: \1'),  ',')
    
  • list_re(src_list, separator, include_re, opt_replace) -- 最初に src_listseparator を使用して項目に分割することにより、リストを作成します。リスト内の各項目について、include_re とマッチするかどうかを確認します。マッチすれば、返されるリストに追加します。 opt_replace` が空の文字列でなければ、返されたリストに項目を追加する前に置換を適用します。

  • list_re_group(src_list, separator, include_re, search_re [, template_for_group]*) -- 置換がオプションではないことを除いて、list_reと同様です。置換を行うときに re_group(item, search_re, template ...) を使用します。

  • list_remove_duplicates(list, separator) -- list 内の重複項目を削除して作成されたリストを返します。項目に大文字と小文字しか違いがない場合、最後のものが返されます。list 内の項目、および返されたリスト内の項目は、いずれも separator で区切られます。

  • list_sort(list, direction, separator) -- 大文字と小文字を区別せず辞書順に並べ替えられた list を返します。方向がゼロの場合、リストは昇順に並べ替えられ、そうでない場合は降順並べ替えられますます。list の項目と、返されたリストの項目は、いずれも separator で区切られます。

  • list_split(list_val, sep, id_prefix) -- sep を区切り文字として使用して list_val を個別の値に分割し、id_prefix_N という名前のローカル変数に値を割り当てます。N はリスト内の値の位置です。最初の項目の位置は 0 (ゼロ) です。この関数は、リストの最後の要素を返します。

    例:

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

    これは次と同等です:

    var_0 = 'one';
    var_1 = 'two';
    var_2 = 'foo
    
  • list_union(list1, list2, separator) -- list1list2 の項目をマージし、重複する項目を大文字と小文字を区別しない比較を使用して削除して作成されたリストを返します。大文字と小文字が異なる場合は、list1 のものを使用します。list1list2 の項目と、返されたリストの項目は、いずれも separator で区切られます。別名: merge_lists(), list_union()

  • mod(x, y) -- x / y の余りの floor を返します。xy のいずれかが数値でない場合、例外をスローします。

  • multiply(x [, y]*) -- 引数の積を返します。引数が数値でない場合は、例外をスローします。この関数は通常、* 演算子で置き換えることができます。

  • not(value) -- 値が空であれば文字列 "1" を返し、そうでなければ空の文字列を返します。この関数は通常、単項否定演算子 (!) に置き換えることができます。

  • ondevice() -- ondevice が設定されていれば文字列 'Yes' を返し、そうでなければ空の文字列を返します。

  • or(value [, value]*) -- 値が空でなければ文字列 '1' を返し、そうでなければ空の文字列を返します。必要なだけの数の value を渡せます。この関数は通常、|| 演算子に置き換えることができます。置き換えができないのは、短絡評価すると副作用により結果が変わる場合です。

  • print(a [, b]*) -- 引数を標準出力に出力します。コマンドライン (calibre-debug -g) から calibre を開始しない限り、出力はブラックホールに入ります。 print 関数は、常に最初の引数を返します。

  • range(start, stop, step, limit) -- パラメータ start、stop、および step で指定された範囲をループすることによって生成された数値のリストを、長さの上限値とともに返します。生成される最初の値は 'start' です。それに続く値は next_v = current_v + step です。step が正の数であれば next_v < stop の間、そうでなければ next_v > stop の間ループします。step が正のとき、startstart >= stop のテストに失敗すると、空のリストが生成されます。limit はリストの最大長を設定し、デフォルトは1000です。パラメータ start, step, および limit はオプションです。引数 1 個を指定して range() を呼び出すと、stop を指定します。引数 2 個は、startstop を指定します。引数 3 個は、start, stop, および step``を指定します。引数 4 個は、``start, stop, step および limit を指定します。例:

    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(lookup_name [, optional_default]) -- 書式を適用せずに lookup_name で指定された書誌フィールドを返します。フィールドの値が未定義 (None) の場合、オプションの 2 番目の引数 optional_default を評価して返します。

  • raw_list(lookup_name, separator) -- 書式や並べ替えを適用せずに、lookup_name で指定した書誌リストを返します。項目は``separator`` で区切られます。

  • re_group(value, pattern [, template_for_group]*) -- 正規表現パターンを`` value`` に適用し、マッチした各インスタンスを対応するテンプレートによって返される値に置き換えて作成された文字列を返します。 テンプレートプログラムモード では、template 関数や eval 関数と同様に `` [[`` を `` {`` に、そして ]]` ``} に使用します。

    次の例では、複数の単語を含むシリーズを検索し、最初の単語を大文字にします:

    program: re_group(field('series'), "(\S* )(.*)", "{$:uppercase()}", "{$}")'}
    
  • round(x) -- x に最も近い整数を返します。x が数値でない場合、例外をスローします。

  • series_sort() -- シリーズ読みの値を返します。

  • strcat(a [, b]*) -- 任意の数の引数を渡せます。すべての引数を連結して形成された文字列を返します。

  • strcat_max(max, string1 [, prefix2, string2]*) -- 引数を連結して形成された文字列を返します。戻り値は string1 に初期化されます。結果の文字列の長さが max 未満である限り、prefix, string のペアから作成された文字列が値の最後に追加されます。プレフィックスは空にすることができます。 string1max より長くても、string1 を返します。必要なだけの数の prefix, string のペアを渡すことができます。

  • strcmp(x, y, lt, eq, gt) -- 大文字と小文字を区別しないxとyの字句比較を行います。x < y ならば lt を返し、x == y であれば eq を返し、それ以外の場合に gt を返します。この関数はたいていの場合、辞書比較演算子 (==, >, < など) のひとつに置き換えることができます。

  • strlen(value) -- 文字列 value の長さを返します。

  • substr(str, start, end) -- strstart 番目から end 番目まで文字列を返します。 str の先頭の文字は 0 番目の文字となります。 end が負の場合には、右から数えて end 番目までの文字となります。 end がゼロなら、最後の文字を示します。たとえば substr('12345', 1, 0)'2345' を返し、substr('12345', 1, -1)'234' を返します。

  • subtract(x, y) -- x - y を返します。 xy のいずれかが数値でない場合、例外をスローします。この関数は通常、 - 演算子で置き換えることができます。

  • today() -- 今日 (現在) の日付と時刻の文字列を返します。この値は format_date または days_between で使用するために設計されていますが、他の文字列と同じように取り扱うことができます。日付は ISO による日付/時刻の書式です。

  • template(x) -- x をテンプレートとして評価します。評価は独自のコンテキストで実行されます。つまり、変数は呼び出し元とテンプレート評価の間で共有されません。

  • urls_from_identifiers(identifiers, sort_results) -- カンマで区切られた identifiers のリストを指定すると、その ID から生成されたHTML URLをカンマで区切ったリストで返します。identifier はコロンで区切られた値のペア(id_name:id_value) です。sort_results が 0 (文字または数値) のとき、リストは並べ替えられません。それ以外の場合は、ID 名のアルファベット順に並べ替えられます。 URLは、本の詳細 に表示されるビルトイン ID 列と同じ方法で生成されます。

より複雑なテンプレート表現のプログラム - テンプレートプログラムモード

テンプレートプログラムモード (TPM) は、 一般プログラムモード and 単関数モード を組み合わせたものです。 TPM は、他の書誌フィールドを参照し、ネストされた関数を使用し、変数を変更し、算術演算を実行するテンプレート式を記述できるという点で、単関数モードとは異なります。このテンプレートが {} 文字の間に置かれ、program: という部分で始まらないという点で、一般プログラムモード とは異なります。テンプレートのプログラム部分は、一般プログラムモードの式リストです。

例: テンプレートで、ある本がシリーズものならシリーズを表示し、そうでなければカスタムフィールド #genre の値を表示したいと仮定します。単関数モード ではテンプレートの式の中からは別の書誌フィールドを参照できないため、この処理は実現できません。 TPM でなら可能です。次の式のようにします:

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

例からはいくつかのことがわかります:

  • TPM は、式が :' で始まり、 ' で終わる場合に使用されます。それ以外はすべて、単関数モード と見なされます。

  • 変数 $ は、テンプレートで指定されたフィールドを表します。式は操作対象で、この場合は #series です。

  • 関数にはすべての引数を指定する必要があります。デフォルト値はありません。たとえば標準のビルトイン関数には、ソースフィールドを示す追加の初期パラメータを指定する必要があります。

  • 空白は無視され、式の中のどこでも使用できます。

  • 定数文字列は対になる引用符、' または " のいずれかで囲まれます。

単関数モード および 一般プログラムモード にリストされている関数はすべて TPM で使用できます。

TPM では、文字列リテラルで { および } 文字を使用するとテンプレートプロセッサが混乱するため、エラーや予期しない結果が発生する可能性があります。それらを文字ではなく、テンプレート式の境界として処理しようとするのです。必ずしもすべてのケースでうまく行くわけではありませんが、{[[ に、そして }]] に置き換えることができます。一般に、プログラムに { および } 文字が含まれている場合は、一般プログラムモード を使用すべきです。

一般プログラムモード と同様に、単関数モード で書かれた関数の場合、書かれているパラメータに加えて、関数が最初のパラメータとして機能する値を指定する必要があります。 TPM では、 $ を使用して、テンプレート式の ルックアップ名 で指定された値にアクセスできます。

保存済み一般プログラムモードテンプレート

一般プログラムモード は、保存された関数を呼び出すのと同じように、テンプレートの保存と別のテンプレートからのそれらのテンプレートの呼び出しをサポートします。環境設定 → 高度な設定 → テンプレート関数 を使用してテンプレートを保存します。詳細については、そのダイアログを参照してください。テンプレートは、関数を呼び出すのと同じ方法で呼び出し、必要に応じてキーワード引数を渡します。引数は任意の式にすることができます。保存されたテンプレートの名前が foo であると仮定して、テンプレートを呼び出す例:

  • foo() -- 引数を渡さずにテンプレートを呼び出します。

  • foo(a, b) は、2 つの変数 ab の値を渡すテンプレートを呼び出します。

  • foo(if field('series') then field('series_index') else 0 fi) -- 本に series があれば series_index を渡し、そうでなければ値 0 を渡します。

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

例として、保存されたテンプレートの名前が今回も foo であると仮定します:

  • foo('#myseries') -- 引数 key には値 'myseries' が割り当てられ、引数 alternate にはデフォルト値 'series' が割り当てられます。

  • foo('series', '#genre') 変数 key には値 'series' が割り当てられ、変数 alternate には値 '#genre' が割り当てられます。

  • foo() -- 変数 key には空の文字列が割り当てられ、変数 alternate には値 'series' が割り当てられます。

保存済みテンプレートをテストする簡単な方法は、 テンプレートテスタ ダイアログを使用することです。アクセスしやすくするには、環境設定 → 高度な設定 → キーボードショートカット → テンプレートテスタ でキーボードショートカットを指定します。 保存済みテンプレート ダイアログにショートカットを指定すると、テスタをすばやく切り替えたり、保存されたテンプレートのソースコードを編集したりするのに役立ちます。

テンプレートに追加情報を与える

開発者は、アプリケーション固有の本の書誌やプロセッサに要求されていることに関する情報など、追加情報をテンプレートプロセッサに渡すことを選択できます。テンプレートはこの情報にアクセスして、評価中に使用できます。

開発者: 追加情報の渡し方

追加情報は、値が文字列である変数 variable_name: variable_value のペアを含む Python 辞書です。テンプレートは辞書にアクセスして、値 variable_value を含む variable_name という名前のテンプレートローカル変数を作成できます。ユーザはこの名前を変更できないため、名前の前にアンダースコアを付けるなどして、他のテンプレートローカル変数と衝突しない名前を使用することをお勧めします。

この辞書は、名前付きパラメータ global_vars=your_dict を使用してテンプレートプロセッサ (フォーマッタ`) に渡されます。完全なメソッドシグネチャは次のとおりです:

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

テンプレート作者: 追加情報のアクセス方法

テンプレートの追加情報 (グローバル辞書) にアクセスにはテンプレート関数を使用します:

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

ここで、id は任意の有効な変数名です。この関数は、開発者から提供された追加情報に名前が含まれているかどうかを確認します。その場合、関数は提供された値をその名前のテンプレートローカル変数に割り当てます。名前が追加情報に含まれておらず、式が指定されている場合、式が評価され、結果がローカル変数に割り当てられます。値も式も指定されていない場合、関数は空の文字列 ('') をローカル変数に割り当てます。

テンプレートは、テンプレート関数を使用して グローバル 辞書に値を設定できます。

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

この関数は、グローバル辞書 key:value ペアに id:value を設定します。ここで、value はテンプレートローカル変数 id の値です。そのローカル変数が存在しない場合、valueexpression の評価結果を設定します。

モード間の違いに関する注意事項

3つのプログラムモード、 単関数モード (SFM), テンプレートプログラムモード (TPM), and 一般プログラムモード (GPM)は、それぞれ動作が異なります。 SFMは「シンプル」を目指しているため、多くのプログラミング言語情報を隠します。

相違点:

  • SFM では、列の値は常に「非表示」の最初の引数としてテンプレートに含まれる関数に渡されます。

  • SFMは、変数と文字列の違いをサポートしていません。すべての値は文字列です。

  • 次のSFMテンプレートは、シリーズ名か文字列 "no series" のいずれかを返します:

    {series:ifempty(no series)}
    

    TPM で同等のテンプレートは

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

    GPM で同等のテンプレートは:

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

    ifempty の最初の引数は、フィールド series の値です。 2 番目の引数は文字列 no series です。 SFMでは、最初の引数であるフィールドの値が自動的に渡されます (非表示の引数)。

  • booksize()current_library_name() などのテンプレート関数には引数を受け取らないものがいくつかあります。 「目に見えない引数」を使用するせいで、SFMではこれらの関数は使用できません。

  • 関数が別の関数を呼び出して引数を計算する入れ子関数は、SFMでは使用できません。たとえば、大文字のシリーズ値の最初の 5 文字を​​返すことを目的としたこのテンプレートは、SFMでは機能しません:

    {series:uppercase(substr(0,5))}
    
  • TPM と`GPM` は、入れ子の関数をサポートします。 TPM の上記のテンプレートは次のようになります。

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

    GPM では次のようになります:

    program: uppercase(substr(field('series'), 0,5))
    
  • 上記のテンプレートプログラムモードのセクションで説明したように、TPM文字列リテラルで{および}文字を使用すると、テンプレートプロセッサが混乱するため、エラーや予期しない結果が発生する可能性があります。それらを文字ではなくテンプレート境界として処理しようとします。すべてではありませんが {[[ に、そして }]] に置き換えることができる場合もあります。一般的に、プログラムに {} の文字が含まれている場合には 一般プログラムモード を使用すべきです。

ユーザ定義の Python テンプレート関数

テンプレートプロセッサに独自の Python 関数を追加できます。このような関数は、3つのテンプレートプログラミングモードのいずれでも使用できます。関数は 環境変数  →  高度な設定  →  テンプレート関数 に行って追加します。手順はそのダイアログに表示されます。

テンプレートの保存/送信に関する特記事項

あるテンプレートが ディスクに保存デバイスに送信 テンプレートの中で使用される場合、特別な処理が適用されます。フィールドの値がクリーンアップされ、ファイルシステムに固有の文字がスラッシュを含むアンダースコアに置き換えられます。これは、フィールドテキストはフォルダの作成には使用できないことを意味します。ただし、プレフィックス文字列またはサフィックス文字列ではスラッシュが変更されないため、これらの文字列にスラッシュを含めると、フォルダが作成されます。このため、深さが可変のフォルダ構造を作成できます。

たとえば、フォルダの構造を series/series_index - title としたいが、シリーズが存在しない場合はタイトルを最上位のフォルダに配置したいと仮定します。これを行うためのテンプレートは次のとおりです:

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

スラッシュとハイフンは、シリーズが空でない場合にのみ表示されます。

ルックアップ関数を使用すると、さらに高度な処理を実行できます。たとえば、本にシリーズがあるときにはフォルダ構造を series/series index - title.fmt にしたいと仮定します。そして本にシリーズがない場合は、フォルダ構造を genre/author_sort/title.fmt にしたいものとします。その本にジャンルがない場合は 'Unknown' を使用します。series の値に応じて、2つの完全に異なるパスが必要です。

これを達成するには:

  1. {series}/{series_index} - {title} を含む複合フィールドを作成します (ルックアップ名 #aa を指定します)。シリーズが空でなければ、このテンプレートは series/series_index - title を生成します。

  2. {#genre:ifempty(Unknown)}/{author_sort}/{title} を含む複合フィールドを作成します (ルックアップ名 #bb を指定します)。このテンプレートは genre/author_sort/title を生成し、空のジャンルは Unknown に置き換えられます。

  3. 保存するテンプレートを {series:lookup(.,#aa,#bb} に設定します。このテンプレートは、シリーズが空でない場合は合成フィールド #aa を選択し、シリーズが空の場合は合成フィールド #bb を選択します。したがってシリーズが空かどうかによって、2 つの完全に異なる保存パスを持つことになります。

テンプレートとプラグボード

プラグボードは、デバイスへの送信およびディスクへの保存操作中に本に書き込まれる書誌を変更するために使用されます。プラグボードを使用すると、本の書誌に書き込むデータを提供するテンプレートを指定できます。プラグボードを使用すると authors, author_sort, language, publisher, tags, title, title_sort のフィールドを変更できます。この機能は、デバイス上の本で別の書誌を使用して、並べ替えや表示の問題を解決したい人に役立ちます。

プラグボードを作成するときは、プラグボードを使用する形式とデバイスを指定します。形式を保存するときに使用される特別なデバイス save_to_disk が提供されます (デバイスに送信するのではありません)。形式とデバイスを選択したら、変更する書誌フィールドを選択し、新しい値を提供するためのテンプレートを提供します。これらのテンプレートは宛先フィールドに 接続 されているため、プラグボードという名前が付けられています。これらのテンプレートでは、もちろん複合列を使用できます。

プラグボードが適用される可能性がある場合 (コンテンツサーバ、ディスクに保存、またはデバイスに送信)、calibre は定義されたプラグボードを検索して、指定された形式とデバイスに適したプラグボードを選択します。たとえば、ANDROID デバイスに送信される EPUB ブックに適切なプラグボードを見つけるために、calibre は次の検索順でプラグボードを検索します:

  • 形式とデバイスが完全に一致するプラグボード。例: EPUB かつ ANDROID

  • 形式が完全に一致し、特別な 任意のデバイス を選択できるプラグボード。例: EPUB かつ 任意のデバイス

  • 特別な 任意のフォーマット を選択し、デバイス上で完全に一致するプラグボード。例: 任意のフォーマット かつ ANDROID

  • 任意のフォーマット任意のデバイス を備えたプラグボード

タグフィールドと著者フィールドはどちらも複数のアイテムを保持できるため、特殊な扱いがあります。本にはいくつものタグと何人もの著者を含めることができます。これら 2 つのフィールドのいずれかを変更するように指定すると、テンプレートの結果に複数の項目がないか確認されます。タグの場合、calibre はカンマを見つけるたびに結果を分割します。たとえばテンプレートが値 Thriller, Horror を生成すると、結果は2つのタグ、Thriller``Horror``になります。タグの途中にカンマを入れる方法はありません。

著者にも同じことが起こりますが、分割に別の文字、カンマの代わりに & (アンパサンド) を使用します。たとえばテンプレートが値 Blogs, Joe&Posts, Susan を生成すると、本の著者は``Blogs, Joe`` と Posts, Susan の 2 人になります。テンプレートが Blogs, Joe;Posts, Susan という値を生成すると、その本の著者はかなり変わった名前の 1 人となります。

プラグボードは、本がディスクに保存されるとき、またはデバイスに書き込まれるときに、本に書き込まれる書誌に影響を与えます。プラグボードは、ファイル名を作成するための ディスクに保存デバイスに送信 によって使われる書誌には影響しません。代わりに、ファイル名は、適切な設定ウィンドウに入力されたテンプレートを使用して作成されます。

ヒント

  • テンプレートテスタを使用してテンプレートをテストします。テスタをライブラリ内の本のコンテキストメニューに追加するか、キーボードショートカットを指定します。

  • テンプレートは、他のテンプレートを使用できます。それをするには、使用したいテンプレートの作成した複合列を参照します。または、保存済みテンプレートを使用することもできます。

  • 書誌の置換に加えて、テンプレートには条件付きで追加のテキストを含め、置換されたデータの整形方法を制御できます。

  • ゼロ値であっても数値を表示する上記の手法は、標準フィールド series_index で機能します。

関数リファレンス