前のセクションでは、defcustomにたいして型の詳細な仕様を作成する方法を説明しました。そのような型仕様に名前を与えたい場合があるかもしれません。理解しやすいケースとしては、多くのユーザーオプションに同じ型を使用する場合などです。各オプションにたいして仕様を繰り返すよりその型に名前を与えて、defcustomそれぞれにその名前を使用することができます。他にもユーザーオプションの値が再帰的なデータ構造のケースがあります。あるデータ型がそれ自身を参照できるようにするためには、それが名前をもつ必要があります。
カスタマイゼーション型はウィジェットとして実装されているめ、新しいカスタマイゼーション型を定義するには、新たにウィジェット型を定義します。ここではウィジェットインターフェイスの詳細は説明しません。Introduction in The Emacs Widget Libraryを参照してください。かわりにシンプルな例を用いて、カスタマイゼーション型を新たに定義するために必要な最小限の機能について説明します。
(define-widget 'binary-tree-of-string 'lazy
"A binary tree made of cons-cells and strings."
:offset 4
:tag "Node"
:type '(choice (string :tag "Leaf" :value "")
(cons :tag "Interior"
:value ("" . "")
binary-tree-of-string
binary-tree-of-string)))
(defcustom foo-bar ""
"Sample variable holding a binary tree of strings."
:type 'binary-tree-of-string)
新しいウィジェットを定義するための関数はdefine-widgetと呼ばれます。1つ目の引数は新たなウィジェット型にしたいシンボルです。2つ目の引数は既存のウィジェットを表すシンボルで、新しいウィジェットではこの既存のウィジェットと異なる部分を定義することになります。新たなカスタマイゼーション型を定義する目的にたいしてはlazyウィジェットが最適です。なぜならこれはdefcustomにたいするキーワード引数と同じ構文と名前でキーワード引数:typeを受け取るからです。3つ目の引数は新しいウィジェットにたいするドキュメント文字列です。この文字列はM-x
widget-browse RET binary-tree-of-string RETコマンドで参照することができます。
After these mandatory arguments follow the keyword arguments. The most
important is :type, which describes the data type we want to match
with this widget. Here a binary-tree-of-string is described as being
either a string, or a cons-cell whose car and cdr are themselves both
binary-tree-of-string. Note the reference to the widget type we are
currently in the process of defining. The :tag is another important
keyword argument because we are using the lazy widget for our new
widget. By default, the lazy widget doesn’t have a tag, and in its
absence the customization buffer will show the entire widget’s value (that
is, the value of the user option being customized). Since that’s almost
never a good idea, we provide a string to name the
binary-tree-or-string widget. The :offset argument is there
to ensure that child nodes are indented four spaces relative to the parent
node, making the tree structure apparent in the customization buffer.
defcustomは通常のカスタマイゼーション型に使用される方法で新しいウィジェットを表示します。
lazyという名前の由来は、他のウィジェットではそれらがバッファーでインスタンス化されるとき、他の合成されたウィジェットが下位のウィジェットを内部形式に変換するからです。この変換は再帰的なので、下位のウィジェットはそれら自身の下位ウィジェットへと変換されます。データ構造自体が再帰的なら、その変換は無限再帰(infinite
recursion)となります。lazyウィジェットは、:type引数を必要なときだけ変換することによってこの再帰を防ぎます。