ユーザーやLispプログラムが、カスタムフォーマットの制御文字列を介して特定のテキストが生成される方法を制御できるようにすると便利な場合があります。たとえばフォーマット文字列は人の姓や名、emailアドレスを表示する方法を制御できます。前のセクションで説明した関数format
を使用することにより、フォーマット文字列は"%s %s <%s>"
のようになるかもしれません。しかしこのアプローチはどの仕様文字がどの情報に対応するかが不明瞭なのですぐに非実用的になります。
そのような場合には"%f %l <%e>"
のようなフォーマット文字列のほうが便利かもしれません。このフォーマット文字列では仕様文字それぞれがより意味的な情報をもち、他の仕様文字に関連して簡単に再配置できるので、このようなフォーマット文字列はユーザーにより簡単にカスタマイズできます。
このセクションで説明する関数format-spec
はformat
と同様の機能を処理しますが、任意の仕様文字を使用するフォーマットコントロール文字列を処理する点が異なります。
この関数はspec-alistで指定された変換にしたがってフォーマット文字列templateから生成された文字列をリターンする。spec-alistは(letter . replacement)
という形式のalist(連想リストを参照)。template内の仕様%letter
はそれぞれ結果文字列のフォーマット時に置換される。
(もしあれば)template内のフォーマット仕様以外の文字はテキストプロパティを含めて出力に直接コピーされる。フォーマット仕様のすべてのテキストプロパティは置換先にコピーされる。
変換の指定にalistを使用することによって有用な特性がいくつか生成される:
REPLACEMENTは引数なしで呼び出されて置換に用いる文字列をリターンする関数でもよい。この関数はTEMPLATEで対応するLETTERが使用された際にのみ呼び出される。これはたとえば必要なとき以外は入力を求めるプロンプトの表示を避ける場合に役に立つかもしれない。
オプション引数ignore-missingは、spec-alistで見つからないtemplate内の仕様文字の処理方法を示す。nil
か省略なら、関数はエラーをシグナルする。ignore
ならこれらのフォーマット仕様は(もしあれば)テキストプロパティも含めてそのまま出力する。delete
ならこれらのフォーマット仕様は出力から取り除かれる。これら以外の非nil
値はignore
と同様に処理されるが、出力中に‘%%’があればそのまま残される。
オプション引数splitが非nil
なら、format-spec
は単一文字列のかわりに置換場所を基準に結果を文字列リストに分割してリターンする。たとえば:
(format-spec "foo %b bar" '((?b . "zot")) nil t) ⇒ ("foo " "zot" " bar")
format-spec
が受け取るフォーマット仕様の構文はformat
が受け取るフォーマット仕様と似ていますが同一ではありません。いずれの場合でもフォーマット仕様は‘%’で始まり‘s’のようなアルファベット文字で終わる文字シーケンスです。
仕様文字の固定セットに特定の意味を割り当てるformat
とは異なり、format-spec
は任意の仕様文字を受け取ってそれらをすべて等しく扱います。たとえば:
(setq my-site-info (list (cons ?s system-name) (cons ?t (symbol-name system-type)) (cons ?c system-configuration) (cons ?v emacs-version) (cons ?e invocation-name) (cons ?p (number-to-string (emacs-pid))) (cons ?a user-mail-address) (cons ?n user-full-name))) (format-spec "%e %v (%c)" my-site-info) ⇒ "emacs 27.1 (x86_64-pc-linux-gnu)" (format-spec "%n <%a>" my-site-info) ⇒ "Emacs Developers <emacs-devel@gnu.org>"
フォーマット仕様には置換の様相を変更するために、‘%’の直後に任意個数のフラグ文字を含めることができます。
このフラグは指定された幅のパディングをスペースのかわりに‘0’で構成する。
このフラグは指定された幅のパディングを左側ではなく右側に挿入する。
このフラグはもし幅と精度が指定されたら置換の左側を切り捨てる。
このフラグはもし幅と精度が指定されたら置換の右側を切り捨てる。
このフラグは置換されるテキストを大文字に変換する(Lispでの大文字小文字変換を参照)。
このフラグは置換されるテキストを小文字に変換する(Lispでの大文字小文字変換を参照)。
矛盾したフラグ(たとえば大文字と小文字)を使用した場合の結果は未定義です。
format
の場合と同様に幅(任意のフラグの後の10進数値)、精度(任意のフラグと幅の後の小数点‘.’に続く10進数)をフォーマット仕様に含めることができます。
指定した幅より置換の文字が少なければ左側がパディングされます。
(format-spec "%8a is padded on the left with spaces" '((?a . "alpha"))) ⇒ " alpha is padded on the left with spaces"
指定した精度より置換の文字が多ければ右側が切り詰められます。
(format-spec "%.2a is truncated on the right" '((?a . "alpha"))) ⇒ "al is truncated on the right"
以下は前述の機能をいくつか組み合わせたより複雑な例です:
(setq my-battery-info (list (cons ?p "73") ; パーセント表示 (cons ?L "Battery") ; 状態 (cons ?t "2:23") ; 残り時間 (cons ?c "24330") ; 容量 (cons ?r "10.6"))) ; 放電率 (format-spec "%>^-3L : %3p%% (%05t left)" my-battery-info) ⇒ "BAT : 73% (02:23 left)" (format-spec "%>^-3L : %3p%% (%05t left)" (cons (cons ?L "AC") my-battery-info)) ⇒ "AC : 73% (02:23 left)"
このセクションの例で示したように、format-spec
はさまざまな情報の断片を選択的にフォーマットするために頻繁に使用されます。これはプログラムが可能にする情報のサブセットだけをユーザーが通常の構文で望む順序で選択できるように、ユーザーにカスタマイズ可能なフォーマット文字列を提供するプログラムにとって有用です。