ユーザーとLispプログラムの双方が、カスタムフォーマット制御文字列を用いて特定のテキストの生成方法を制御できるようにすることが有用な場合があります。例えば、フォーマット文字列によって、ある人物の名、姓、およびメールアドレスの表示方法を制御できます。前節で説明した関数
format を使用すると、フォーマット文字列は "%s %s <%s>"
のようになります。しかし、どの指定文字がどの情報に対応しているのかが不明確になることがあるため、この手法はすぐに実用的ではなくなります。
このような場合により便利なフォーマット文字列としては、"%f %l <%e>"のようなものが挙げられます。ここでは、各指定文字がより多くの意味情報を持ち、他の指定文字との相対的な配置を容易に変更できるため、ユーザーによるカスタマイズがより容易になります。
本節で説明する関数 format-spec
は、任意の指定文字を用いる書式制御文字列を対象とする点を除けば、format
と同様の機能を果たします。
この関数は、(letter . replacement) 形式のアリスト(アソシエーションリストを参照)である spec-alist で指定された変換に従い、フォーマット文字列 template から生成された文字列を返します。結果の文字列をフォーマットする際、template 内の各指定 %letter は replacement
に置き換えられます。
template 内の文字は、書式指定を除き、テキストプロパティ(もしあれば)も含めてそのまま出力にコピーされます。書式指定のテキストプロパティは、対応する置換文字列にコピーされます。
alistを用いて変換を指定すると、いくつかの有用な性質が得られます:
REPLACEMENT は、引数を取らず、置換に使用する文字列を返す関数としても指定できます。これは、TEMPLATE 内で対応する LETTER が使用された場合にのみ呼び出されます。例えば、必要がない限り入力を促す処理を避ける場合などに有用です。
オプション引数 ignore-missing は、template に含まれるが spec-alist
には存在しない指定文字の処理方法を指定します。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>"
フォーマット仕様では、置換の諸側面を変更するために、‘%’の直後に以下のフラグ文字を任意の数だけ含めることができます。
このフラグを指定すると、widthで指定されたパディングが、スペースではなく‘0’文字で構成されるようになります。
このフラグを指定すると、widthで指定されたパディングが左ではなく右に挿入されます。
このフラグを指定すると、置換文字列の左側が、指定された幅および精度で切り詰められます。
このフラグを指定すると、置換後の文字列の右側が、指定された幅と精度で切り詰められます。
このフラグは、置換後のテキストを大文字に変換します(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") ; Percentage
(cons ?L "Battery") ; Status
(cons ?t "2:23") ; Remaining time
(cons ?c "24330") ; Capacity
(cons ?r "10.6"))) ; Rate of discharge
(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
は、さまざまな情報を選択的にフォーマットするためによく用いられます。これは、ユーザーがカスタマイズ可能なフォーマット文字列を提供するプログラムにおいて有用です。ユーザーは、プログラムが提供する情報のうち、一部のみを標準的な構文を用いて任意の順序でフォーマットすることを選択できるためです。