16

Like most Emacs users I've customized a mode by changing the variables. What never occurred to me is the whole programming mentality behind having customizable this-and-that. I realized this when I started looking at some of the source code for eshell. I'm not an elisp programmer, but specifically em-ls.el seems to use defcustom, defgroup, etc. This would seem to be a shadow-world of globally-defined variables that the elisp code uses. So one question would be, Is the use of defcustom another way of doing (customizable) global variables?

Can anyone point me to lit on how to properly use (first understand) the whole idea behind defcustom, when to use, why, when not? Maybe a beginner example for a elisp beginner.

  • Could you clarify what you're asking? Do you want to know when to use the customize facilities versus when to customize by hand? Or are you interested in writing a mode? The latter is the situation in which you might actually find yourself using things like defcustom and the like. – Dan Aug 26 '15 at 16:33
20

The customization system is a built-in feature of Emacs designed to solve precisely the problem you describe—programming may not be the ideal way for the average user to configure their editor.

The primary entry point to the customization functionality is M-x customize RET (or Options > Customize Emacs > Top-level Customization Group from the menu). From there you'll see an interactive menu system for adjusting settings. This interface enforces that all settings are of the correct type (number, string, color, etc.), avoiding a major source of error encountered when users configure Emacs programmatically. If the user chooses to persist any changes they make through the UI, the settings are stored to a special section in the user's initialization file (read: .emacs).

defcustom is wrapper around lower-level Emacs Lisp functionality like defvar that both declares the variable and makes it visible within the customization interface. It also allows the developer to provide extra metadata needed to display an appropriate interactive control—i.e. what type of value is stored in this variable? An arbitrary string? A number? A choice from a fixed set of options? etc. defgroup is a grouping construct for these customizable options so that they can be arranged into a nice hierarchy.

This functionality should be used any time a piece of data should be considered a configurable option for the user rather than an internal detail of the library.

Here's a simple example cribbed from a small library of mine:

(defgroup checkbox nil
  "Quick manipulation of textual checkboxes."
  :group 'convenience)

(defcustom checkbox-states '("[ ]" "[x]")
  "Checkbox states to cycle between.
First item will be the state for new checkboxes."
  :group 'checkbox
  :type '(repeat string))

The defgroup creates a new group within the Customization interface under the top-level convenience item. I then needed a variable to store the possible checkbox states. I could have used defvar, but since I want this to be easily customizable, I chose to use defcustom. The :group portion indicates that it belongs to the previously-defined group, and the :type indicates that it is a sequence of strings. There's also a default value and a description. There are also additional facilities (not shown here) for transforming values entered by the user.

If I now run M-x customize RET and navigate to Convenience > Checkbox, I see the following:

customization interface

It's not the most beautiful interface in the world, but notice that it has interactive tools for customizing the value of "Checkbox States" (checkbox-states internally). It shows the current string values along with INS (insert) and DEL (delete) buttons, and allows us to edit the string values in edit boxes. When we're done we can decide whether to apply our changes, revert them, or apply and save them for future sessions.

  • 2
    Good post! The most significant advantages to Customizing (and defcustom) are that it automatically takes care of : (1) type-checking, to help prevent you from assigning an incorrect value to a variable (provided the writer of the defcustom made the effort to provide a reasonable type check), (2) initialization (:initialize) and update ctions (triggered) (:set). – Drew Aug 26 '15 at 18:13
  • Thanks! I've updated the post to reflect your suggestions. – camdez Aug 27 '15 at 2:54
7

Is the use of defcustom another way of doing (customizable) global variables?

Yes. Especially if you want users of your code to be able to change variables easily through the M-x customize interface.

defcustom provides two important benefits to your users: documentation and type safety. Documentation is nice to have right there. Type safety allows one to specify what kinds of valid values your variables can take.

Of course defvar is fine if all you'r doing is customizing for yourself and don't anticipate wider usage. However, some would say sticking with defcustom through and through is a good habit to inculcate.

Can anyone point me to lit on how to properly use...

The manual page for defcustom has further clarifications. Customizations topic in the manual has complete details.

...when to use, why, when not?

I personally find defcustom less cumbersome during development as I don't have to deal with reload problems with defvar and setq.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.