Previous: Type Keywords, Up: Customization Types [Contents][Index]

#### 14.4.5 Defining New Types

In the previous sections we have described how to construct elaborate type specifications for `defcustom`. In some cases you may want to give such a type specification a name. The obvious case is when you are using the same type for many user options: rather than repeat the specification for each option, you can give the type specification a name, and use that name each `defcustom`. The other case is when a user option’s value is a recursive data structure. To make it possible for a datatype to refer to itself, it needs to have a name.

Since custom types are implemented as widgets, the way to define a new customize type is to define a new widget. We are not going to describe the widget interface here in details, see Introduction in The Emacs Widget Library, for that. Instead we are going to demonstrate the minimal functionality needed for defining new customize types by a simple example.

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

The function to define a new widget is called `define-widget`. The first argument is the symbol we want to make a new widget type. The second argument is a symbol representing an existing widget, the new widget is going to be defined in terms of difference from the existing widget. For the purpose of defining new customization types, the `lazy` widget is perfect, because it accepts a `:type` keyword argument with the same syntax as the keyword argument to `defcustom` with the same name. The third argument is a documentation string for the new widget. You will be able to see that string with the `M-x widget-browse RET binary-tree-of-string RET` command.

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` attribute is a string to name the widget in the user interface, and 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.

The `defcustom` shows how the new widget can be used as an ordinary customization type.

The reason for the name `lazy` is that the other composite widgets convert their inferior widgets to internal form when the widget is instantiated in a buffer. This conversion is recursive, so the inferior widgets will convert their inferior widgets. If the data structure is itself recursive, this conversion is an infinite recursion. The `lazy` widget prevents the recursion: it convert its `:type` argument only when needed.

Previous: Type Keywords, Up: Customization Types [Contents][Index]