A Novice Friendly Emacs

Making Emacs Code Customizable in Ten Steps

As a Real Programmer, you probably love how customizable Emacs is. You don't have to learn some new weird configuration file format, all the customizations are done in lisp, making it both powerful and simple to use. Lisp is an old and widely used language, so you probably already knew it or at least had it on the list of languages you wanted to learn.

However, for ordinary lusers, concepts like setq, "an alist where the car of each element is a symbol", or `error in init file' are not considered proper elements of an easy to use customization interface. This is where the custom package enters the picture. By supporting the custom package you allow the user to customize your code without the need for any knowledge about lisp or lisp types, and with automatic checks to ensure that the customizations are syntactically correct. Perhaps you will even find that some Real Programmers will prefer this interface for simple customizations.

Here is how to make your code customizable in ten easy steps. You don't have to complete all the steps at once, each step will make your package a little easier to customize.

  1. Insert (require 'custom) in the beginning of your code Remark: this will not be necessary when custom becomes bundled with Emacs.
  2. Replace defvar with defcustom for all user options, see section Declarations.
  3. Add a fourth argument to your defcustom declarations to specify the type, see section Declarations.
  4. Add your refinements to other user options with custom-option-add, see section Declarations.
  5. Organize the user options in one or more groups with custom-group-declare, see section Groups.
  6. Add your user options and groups to other groups with custom-group-add, see section Groups.
  7. Add local keybindings for customizing your package with customize, see section Buffers and Menus.
  8. Add local menus for customizing your package with customize-menu-create, see section Buffers and Menus.
  9. Add new user option types with widget-define, see section Defining New Widgets.
  10. To make it extra easy, there is no tenth step!

The Custom Library

The custom library is implemented in two files:

`custom.el'
which contains the functions needed for all custom declarations, and
`custom-edit.el'
which contains the functions for creating and editing customization buffers.

All functions will be automatically loaded when needed.

Remark: this is not true for the unbundled version, your must insert an explicit `(require 'custom)' statement before declaring any variables for customization. The `custom-edit.el' file will still be loaded on demand.

Custom Example

Here should be an example of a major mode that makes full use of the custom package.

Declarations

Declaring user options make them much easier to edit in the customize buffer.

Variables

The custom package allows the user to edit the value of any variable in a customize buffer, but works best if the variable has the following two properties defined:

default-value
This property contains the variables default value, unevaluated. It is used by the custom-reset-to-default command available in the customize buffer, and also to avoid saving variables unnecessarily.
custom-type
This property controls how the variable will be presented in the customize buffer, and what values will be considered valid. The syntax of custom types is described in section Custom Types.

The easiest way to set these properties is by declaring the variable with defcustom instead of defvar.

Special Form: defcustom symbol init doc &optional type
If symbol is not bound, set it to the evaluated value of init. Set the default-value property of symbol to init. Set the variable documentation for symbol to doc. Set the custom-type property of symbol to type.

The following two pieces of lisp code are equivalent:

Adding Options

Sometimes the user has to choose one or more options from a fixed set. This can be implemented with variables declared with the Choice or Multi custom types (see section Custom Types). If you want to add an option such a set, you can do it with custom-option-add.

Function: custom-option-add symbol type &optional old before ]
Add option to existing variable.@br

symbol should have a Choice or Multi custom-type property, where type will be added a new option. By default, the new option will be added first in the list of option. If old is non-nil, the new option will be added after the option with an old tag. If before is non-nil, the new option will be added before the old option instead.

A typical use of custom-option-add is when your package define a function intended to be added to hook variable defined in another package.

Faces

How text with a given face should be displayed is a matter of personal taste, and therefore an important item for customization. The users preference is also likely to depend on the current visual. For example, he might want text with the warning face to blink on a vt100 frame, but be displayed in large dark bold red letters on a color frame with a light background.

In order to enable user customizations of a face used by your code, you have to make two declarations:

Your code should only refer to the variable, never to the face directly. By convention, the face and the variable should have the same name.

A customize buffer for the variable will allow the user to:

Special Form: custom-face-declare name &rest clauses...
Create and initialize the face named name if it doesn't exists.@br

clauses is a list with elements of the form (expr [attribute value]...). Each expr will be evaluated in turn, until one of them evaluates to non-nil. The face will then be initialized with the specified attributes. Known properties include:

:bold
:italic
:underline
:blink
:font
:stipple
:foreground
:background

Not all face properties are defined for all emacs versions nor for all visuals. Unknown properties will be silently ignored. When a new frame is created, the expr's will be reevaluated, and if a different expr is selected, the face will be created with a specific value for that frame.

In order to implement this, custom-face-declare will create an entry in the global variable custom-face-declared-list of the form (name expr clauses), where expr is from the clause that was used for creating the global face.

Custom Types

This section should explain the syntax for a custom type, with some helpful examples. This this is essentially a duplication of the information in the chapter about Sexp Widgets (see section The Sexp Widgets), I will delay writting this section until the implementation is stable.

Groups

You can group related variables with custom-group-declare, which allows you to create a menu or customize buffer containing all the variables. A group can also contain other groups, allowing the creation of both nested menus, and ridiculously huge customize buffers.

Special Form: custom-group-declare name elements [ keyword value ]...
Declare name (a symbol) as a group.@br The initial group members will be elements, which should evaluate into a list of variable or group names. The following keywords are recognized:

:tag
A string identifying the group. By default it will be the printed representation of name.
:doc
A string documenting the group. By default this will be the function documentation for name if any, or the empty string otherwise.
:format
String controlling how the group is formated in the buffer. The following `%' escapes are available:
`%v'
The group members will be inserted here.
`%d'
Insert the string specified by :doc here.
`%t'
Insert the string specified by :tag here.
The default format is `"%t: %d\n%v"'.

You can add members to existing groups with custom-group-add.

Special Form: custom-group-add group name &optional before
In the group group add new element name.@br name must be a variable or group. If the optional argument before is non-nil, it must be a member of group and name will be inserted before before. If before is not present or nil, name will be inserted at the end of the list.

Groups are actually implemented by setting the custom-type property of the symbols to a special group widget. The two following list expressions are equivalent:

Buffers and Menus

You can create a customize buffer from any symbol with a non-nil custom-type property. This includes all variables declared with defcustom and all groups declared with custom-group-declare. You can also create customize buffers from variables without the custom-type property; they will be assumed to be able to hold any lisp Object. You can create a customize menus from any symbol with a Group custom-type, in practice meaning all groups declared with custom-group-declare.

Command: customize &optional symbol
Create a customization buffer for symbol, by default emacs.

User Option: custom-group-max-nesting
The number of nested groups allowed when creating a customize buffer. Groups nested at this level we be represented as buttons. Activating one of these buttons will create a new customize buffer that group.

Function: customize-group-menu symbol
Return an menu description from symbol. Symbol must be a declared with custom-group-declare. The menu description is in the format expected by easy-menu-define.

What is this weird stuff in my `.emacs'?

Saving from a customization buffer will add two top level expressions to your `.emacs' file.

Wishlist

Modifications as a Customization

For some variables it is more common for the user to modify them than to set them. This practise has several advantages:

The primary examples are hooks that are set with add-hook and remove-hook, large association lists like auto-mode-alist, keymaps, and menus. The custom package should support these.

The Emacs Widget Library

Most graphical user interface toolkits, such as Motif and XView, provide a number of standard user interface controls (sometimes known as `widgets' or `gadgets'). Emacs doesn't really support anything like this, except for an incredible powerful text "widget". On the other hand, Emacs does provide the necessary primitives to implement many other widgets within a text buffer. The widget package simplifies this task.

The basic widgets are:

const
An uneditable widget. Useful for implementing buttons, and as an option in a choice widget.
string
An editable text field.
choice
Allows the user to choose one of multiple options. Each option is itself an widget.
list
This widget can contain a fixed or variable number of other widgets.

This might not seem like much compared with other widget sets, but the Emacs widgets can be combined within each other, making it possible to build quite complex user interfaces.

Now of what possible use can support for widgets be in a text editor? I'm glad you asked. The answer is that widgets are useful for implementing forms. A form in emacs is a buffer where the user is supposed to fill out a number of fields, each of which has a specific meaning. The user is not supposed to change or delete any of the text between the fields. Examples of forms in Emacs are the `forms' package (of course), the customize buffers, the mail and news compose modes, and the HTML form support in the `w3' browser.

The advantages for a programmer of using the widget package to implement forms are:

  1. More complex field than just editable text are supported.
  2. You can give the user immediate feedback if he enters invalid data in a text field, and prevent entering invalid data using the choice and list widgets.
  3. You can have fixed sized fields, thus allowing multiple field to be lined up in columns.
  4. It is simple to query or set the value of a field.
  5. Each field can be highlighted according to its status, in a way this is consistent with other packages.
  6. Editing happens in buffer, not in the mini-buffer.

In order to minimize the code that is loaded by users who does not create any widgets, the code has been split in two files:

`widget.el'
This will declare the user variables, define the function widget-define, and autoload the function widget-create.
`widget-edit.el'
Everything else is here, there is no reason to load it explicitly, as it will be autoloaded when needed.

User Interface

A form consist of read only text for documentation and some fields, where each the fields contain two parts, as tag and a value. The tags are used to identify the fields, so the documentation can refer to the foo field, meaning the field tagged with `Foo'. Here is an example form:

Here is some documentation.

Name: My Name     Choose: This option
Age:  14

See also other work for more information.

Numbers: count to three below
[INS] [DEL] One
[INS] [DEL] Eh, two?
[INS] [DEL] Five!
[INS] 

There are 4 fields in the example, tagged `Name', `Choose', `Age', and `Numbers' respectively. There are basically two thing the user can do within a form, namely editing the editable text fields and activating the buttons.

Editable Text Fields

In the example, the values for the `Name' and `Age' fields are most likely displayed in editable text fields, and so are values for each of the members of the `Numbers' list. All the normal Emacs editing operations are available for editing these fields. The only restriction is that each change you make must be contained within a single editable text field. For example, capitalizing all text from the middle of one field to the middle of another field is prohibited. All changes to the text outside the editing fields is also prohibited.

There is one extra command available for editing editable text fields, namely widget-kill-line, normally bound to C-k.

Command: widget-kill-line &optional count
Identical to kill-line, except that it will not attempt to kill past the end of the field.

Editing text fields are created by the string widget.

The editing text fields are highlighted with the following faces, making them easy to find:

User Option: widget-active-face
Face used for the editing field containing point.

User Option: widget-uninitialized-face
Face used for editing fields that have not yet been initialized.

User Option: widget-invalid-face
Face used for editing fields that contain a invalid value.@br For example if the field is supposed to contain a number, but the user has inserted some letters.

User Option: widget-modified-face
Face used for editing fields that have been modified.@br It is up to the package creating the widget to define when a field is modified or not.

User Option: widget-default-face
Face used for other editing fields.

The first face in the list above that applies to a field is used.

Buttons

Some portions of the buffer have an associated action, which can be activated by a standard key or mouse command. These portions are called buttons. The default commands for activating a button are:

RET
Command: widget-key-action &optional POS
Activate the button at pos, defaulting to point. If point is located in an editable text field, activate the global binding.
mouse-2
Command: widget-mouse-action
Activate the button at the location of the mouse pointer. If the mouse pointer is located in an editable text field, activate the global binding.

There is three different kind of buttons, all of which are present in the example:

The Option Field Tags.
When you activate one of these buttons, you will be asked to choose between a number of different options. This is how you edit an option field. Option fields are created by the choice widget. In the example, `Choose' is an option field tag.
The `[INS]' and `[DEL]' buttons.
Activating these will insert or delete elements from a list field, which is how you edit a list field. List fields are created by the choice widget.
Embedded Buttons.
The `other work' is an example of an embedded button. Embedded buttons are not associated with a fields, but can serve any purpose, such as implementing hypertext references. They are usually created by the const widget.

To make them easier to locate, buttons are emphasized in the buffer.

User Option: widget-button-emphasis
A string controlling how buttons are emphasized.

The string is inserted into the buffer, with `%v' replaced by the button name.

The default value is `"%v"' if the current frame support faces, and `"*%v*"' otherwise.

User Option: widget-button-face
Face used for buttons.

User Option: widget-mouse-face
Face used for buttons when the mouse pointer is above it.

Navigation

You can use all the normal Emacs commands to move around in a form buffer, plus you will have these additional commands:

TAB
Command: widget-forward &optional count
Move point count buttons or editing fields forward.
M-TAB
Command: widget-backward &optional count
Move point count buttons or editing fields backward.

Meta Commands

It is suggested that packages provides the following keybindings, unless they have a good reason not to:

C-c C-a
Apply form, i.e. let all changes to the editing fields take effect.
C-c C-s
Apply form, and make the changes permanent. If it doesn't make sense to distinguish between permanent and transient changes in the form, C-c C-s and C-c C-a should be bound to the same function.
C-c C-c
Apply form, make the changes permanent, and bury the buffer.
C-c C-u
Reset the form to the last applied value.
C-c C-r
Reset the form to the last saved value.
C-c C-z
Reset the form to the default value.

Programming Example

Here should be the lisp code for implementing the example form (see section User Interface), but that will have to wait until I have some code to test it with. Here is instead the beginning of a fascist mail compose mode:

(require 'widget)

(defun fascist-mail ()
  "An unfriendly mail compose mode."
  (interactive)
  (if (get-buffer "*Fascist Mail*")
      (switch-to-buffer "*Fascist Mail*")
    (switch-to-buffer "*Fascist Mail*")
    (let ((aliases (nconc (mapcar (lambda (e) (list (car e)))
                                 mail-aliases)
                          '(("Other" string)))))
      (widget-create `(list (string :format "            Subject: %v")
                              &rest
                              (choice :format "To: %v" ,@aliases))))
    (widget-setup)))

Setting Up the Buffer

Widgets are created with widget-create, which returns a widget object. This object can be queried and manipulated by other widget functions, until it is deleted with widget-delete. After the widgets have been created, widget-setup must be called to enable them.

Function: widget-create type [ keyword argument ]...
Create and return a widget of type type. The syntax for the type argument is described in section Types.

The behavior of widget-create can be modified by the following keyword arguments:

:position
Create the widget at position (a marker or integer) in the buffer.@br By default widgets are created at point.
:modified
A flag indicating whether the widget has been modified.@br By default this is nil.

Other keyword arguments can be used to overwrite the keyword arguments that are part of type.

Function: widget-delete widget
Delete widget and remove it from the buffer.

Function: widget-setup [ keyword argument ]...
Setup a buffer to support widgets.

The widget package depends on before-change-functions, after-change-functions, and post-command-hook to be set in order to work. This function will setup these three variables properly, and should be called once for each buffer that contains widgets. If you need to change the buffer outside the widgets, you should prevent these hooks from being run by wrapping the code in an widget-ignore form.

The behavior of widget-setup can be modified by the following keyword arguments:

:buffer
Setup buffer instead of the current buffer.
:keymap
Use keymap when inside the editing fields, instead of the buffer's local keymap.

If the local keymap contains changes that makes it unsuited for editing, you can use widget-keymap together with the :keymap argument to widget-setup. Since widget-keymap has the global map as its parent, the local bindings will be ignored.

Const: widget-keymap
A keymap with the global keymap as its parent.@br TAB and C-TAB are bound to widget-forward and widget-backward, respectively. RET and mouse-2 are bound to widget-key-action and widget-mouse-action.

Warning: The keymap specified with the :keymap argument to widget-setup is only active when point is inside an editing field. This is fine for keyboard events, but can be very surprising for mouse events. If you redefine any mouse events, it is best to make sure they have the same definition in the local keymap as in the editing field keymap. If you want different actions depending on whether you press the mouse button in or outside an editing field, make the mouse function explicitly check the local-map text property.

Special Form: widget-ignore body...
Execute body without trying to keep the widgets updated. This is necessary if you want to make changes outside the widgets after calling widget-setup.

Types

The syntax of a type specification is given below:

TYPE ::= (const  [KEYWORD ARGUMENT]... VALUE)
     |   (string [KEYWORD ARGUMENT]...)
     |   string
     |   (choice [KEYWORD ARGUMENT]... [TYPE]...)
     |   (list   [KEYWORD ARGUMENT]... 
                 [[@] TYPE]... [&optional [[@] TYPE]...] [&rest [[@] TYPE]])

The following keywords are defined:

:compact
[ choice ] If this is nil (default) use a menu for the choice, otherwise use radio buttons.
:value
[ all ] The initial value for widgets of this type. The syntax for values is specified in section Values.@br By default new widgets will be created uninitialized.
:size
[ string ] The width of the editable field.@br By default this is 20.
:button
[ all ] The function to call when the button part of the widget is activated. The function is called with the widget as an argument, and its return value is ignored.@br The default button function will ask the user to make a selection in a choice widget, and to do nothing in the other widgets.
:doc
[ all ] The string inserted by the `%d' escape in the format string. The default value is the empty string.
:tag
[ all ] The string inserted by the `%t' escape in the format string. The default value is the printed representation of the value for consts, and name of the widget type for other widget types.
:format
[ all ] format is the string will be inserted in the buffer when you create a widget. The following `%' escapes are available:
`%['
`%]'
The text inside these is a button.
`%v'
For choices and lists, this will be replaces with the nested widget(s). For strings, it will be replaced by the editable text field. It has no meaning for consts.
`%d'
Insert the string specified by :doc here.
`%t'
Insert the string specified by :tag here.
The default format is `%t: %d%v'.
:valid-p
[ all ] valid-p should be a function that takes two elements, a type and a value, and return non-nil if value is a valid value for type.@br Here is the default requirements for standard widget types:
const
value must be equal to the widgets own value.
field
value must be a string.
choice
value must be valid for at least one of the option types.
list
value must be a list, and each member of the list must be valid according to the corresponding component type.
:modified-p
[ all ] modified-p should be a function that takes a widget argument, and return non-nil if it had been modified.@br By default, the widget is modified if the user has edited the widget or a component of the widget, or if programmer has explicitly set the modified flag.
:convert-value-to-internal
[ all ] When you set the value of the widget with the :value keyword to widget-create or with widget-value-set it is first converted using this function.@br The default conversion function pass its argument unchanged.
:convert-value-to-external
[ all ] When you ask for the widgets value with widget-value, t is first converted using this function.@br The default conversion function just pass its argument unchanged.

Apart from the keywords, the widgets have very different syntax for the remaining arguments.

const
value is the initial (and permanent) value of the const widget.
string
This widget doesn't have any arguments apart from the keywords.
choice
Each type clause in the choice type represent a separate option. The value of the :tag field of the type is when the user is asked to select one of the option. The type part used to for creating the widget corresponding to the chosen option.
list
In the list type, the type elements up until the first &optional or &rest keyword represent widgets which will always be present. The type elements between the &optional and &rest represents optional widgets. There can be no holes in the list, so if an optional widget is missing, all widgets after it must be missing to. The type element after the &rest keyword represents a variable number widgets of the same type. All optional widgets must be present before any widgets of this type can be present. Inserting `@' tokens before a type means that, when extraction the value of the list, the value of the component widget must be a list which will be spliced into the result. See section Values.

Values

A syntax for a widgets internal value depends on its type, as follows:

const
This can be anything.
string
The value is the string being displayed in the editing field.
choice
The value is the external value of the chosen component widget.
list
The value is a list whose elements are the external values of the widgets contained in the list. Widgets whose type was prepended with a `@' token in the lists type specification will have their external value spliced into the list. Read the documentation string for backquote to understand what this means.

You can examine or set this value by using the widget object that was returned by widget-create. Uninitialized widgets does not have a value.

Function: widget-value widget
Return the current value contained in widget. It is an error to call this function on an uninitialized widget.

Function: widget-value-set widget value
Set the value contained in widget to value. It is an error to call this function with an invalid value.

Function: widget-value-clear widget
Return widget to its uninitialized state. This does nothing for const objects.

Function: widget-initialized widget
Non-nil iff the widget has been initialized.

Function: widget-modified widget
Non-nil iff the widget has been modified.

Function: widget-modified-set widget
Set the modified flag for widget.

Function: widget-modified-clear widget
Clear the modified flag for widget.

Function: widget-valid-p widget value
Non-nil if widget can have value as a valid value.

Function: widget-validate widget &optional verbose
Non-nil if widget has a valid value. If the optional argument verbose is non-nil, signal an error if the widget has an invalid value, and move point near the invalid data.

Properties

It is possible to find both the part of the buffer that is associated with a particular widget, and the widget that is associated with a particular point in the buffer. The first can be done with widget-area, while the later is accomplished by examining the widget text property. This property will be set to the associated widget object within the widgets, and be nil outside the widgets.

Function: widget-area widget
Return of two elements the position of the start of the widget and the position of the end of the widget.

If your application needs to associate some information with the widget objects, for example a reference to the item being edited, it can be done with widget-property-put and widget-property-get.

Function: widget-property-put widget property value
In widget set property to value. property should be a symbol, while value can be anything.

Function: widget-property-get widget property
In widget return the value for property. property should be a symbol, the value is what was last set by widget-property-put for property.

Function: widget-property-check widget property
Non-nil if widget has a value (even nil) for property property.

Function: widget-property-clear widget property
In widget, remove the property property.

Defining New Widgets

You can define specialized widgets with widget-define. It allows you to create a shorthand for more complex widgets, including specifying component widgets and default new default values for the keyword arguments.

Function: widget-define name class convert &rest args
Define a new widget type named name from class.

name and class should both be symbols, class should be one of the basic widget types (const, string, list, and choice).

After the new widget has been defined, the following two calls will create identical widgets:

Using widget-define does just set the widget-type property of name to a list with the three elements, class, convert, and args, which is what widget-create uses.

If you just want to specify defaults for keywords with no complex conversions, you can use identity as your conversion function.

Wishlist.

It should be possible to add or remove items from a list with C-k and C-o.

The Sexp Widgets

A library of widgets for editing lisp expressions sexps is available by loading the `widget-sexp' package. All the sexp widgets have the following common syntax:

(name [ keyword value ]... arg...)

The `arg...' is where the syntax of the sexp widgets varies.

List
Vector
The args specifies the type of list or vector members, respectively. You can enter a &optional keyword in the element list to specify that the following elements are optional, and a &rest keyword before the last element to specify that it can be repeated an arbitrary number of times. You can insert a `@' token before any type whose value will be a list, to indicate that the value should be splices directly into the list rather than be a single element of the list. The precise syntax is the the same as for the list widget, see section Types.
Cons
There are exactly two args, which specifies the syntax for the car and cdr of a cons cell respectively.
Choice
Multi
These two special widgets allows the user to choose between multiple options. The Choice widget only allows a single option to be chosen, while the Multi widget allows the user to make multiple choices. The args is in both cases a list of types. For the Choice widget, the value is the value of the widget representing the chosen option, while the value of the Multi widget is a list values of the widgets representing the chosen options.
String
Sexp
File
Number
Integer
Symbol
Boolean
None of these take any args, only keyword arguments.
Const
This takes one argument, the value of the widget.
Face
There is only a single arg, which should be the name of the default face to customize. The arg can be missing, in which the user must explicitly enter a face name.

All the standard keyword arguments described in section Types are available. For the sexp widgets, the following are likely to be useful:

:doc
Documentation explaining the purpose of this widget.
:tag
Short string identifying the widget.
:compact
[ Choice ] Use radio buttons if nil or a menu otherwise.
:size
[ String, Sexp, File, Number, Integer, Symbol ] The size of the editing field, in characters.

Some of the sexp widgets accept additional keywords:

:true
[ Boolean, Multi ] String inserted for selected items (default `"[X]"').
:false
[ Boolean, Multi ] String inserted for unselected items (default `"[ ]"').
:face
[ Face ] The name of the default face to customize.