elisp: Minor Mode Conventions

 
 22.3.1 Conventions for Writing Minor Modes
 ------------------------------------------
 
 There are conventions for writing minor modes just as there are for
 major modes.  These conventions are described below.  The easiest way to
 follow them is to use the macro ‘define-minor-mode’.  SeeDefining
 Minor Modes.
 
    • Define a variable whose name ends in ‘-mode’.  We call this the
      “mode variable”.  The minor mode command should set this variable.
      The value will be ‘nil’ if the mode is disabled, and non-‘nil’ if
      the mode is enabled.  The variable should be buffer-local if the
      minor mode is buffer-local.
 
      This variable is used in conjunction with the ‘minor-mode-alist’ to
      display the minor mode name in the mode line.  It also determines
      whether the minor mode keymap is active, via ‘minor-mode-map-alist’
      (SeeControlling Active Maps).  Individual commands or hooks
      can also check its value.
 
    • Define a command, called the “mode command”, whose name is the same
      as the mode variable.  Its job is to set the value of the mode
      variable, plus anything else that needs to be done to actually
      enable or disable the mode’s features.
 
      The mode command should accept one optional argument.  If called
      interactively with no prefix argument, it should toggle the mode
      (i.e., enable if it is disabled, and disable if it is enabled).  If
      called interactively with a prefix argument, it should enable the
      mode if the argument is positive and disable it otherwise.
 
      If the mode command is called from Lisp (i.e., non-interactively),
      it should enable the mode if the argument is omitted or ‘nil’; it
      should toggle the mode if the argument is the symbol ‘toggle’;
      otherwise it should treat the argument in the same way as for an
      interactive call with a numeric prefix argument, as described
      above.
 
      The following example shows how to implement this behavior (it is
      similar to the code generated by the ‘define-minor-mode’ macro):
 
           (interactive (list (or current-prefix-arg 'toggle)))
           (let ((enable (if (eq arg 'toggle)
                             (not foo-mode) ; this mode’s mode variable
                           (> (prefix-numeric-value arg) 0))))
             (if enable
                 DO-ENABLE
               DO-DISABLE))
 
      The reason for this somewhat complex behavior is that it lets users
      easily toggle the minor mode interactively, and also lets the minor
      mode be easily enabled in a mode hook, like this:
 
           (add-hook 'text-mode-hook 'foo-mode)
 
      This behaves correctly whether or not ‘foo-mode’ was already
      enabled, since the ‘foo-mode’ mode command unconditionally enables
      the minor mode when it is called from Lisp with no argument.
      Disabling a minor mode in a mode hook is a little uglier:
 
           (add-hook 'text-mode-hook (lambda () (foo-mode -1)))
 
      However, this is not very commonly done.
 
    • Add an element to ‘minor-mode-alist’ for each minor mode (See
      Definition of minor-mode-alist), if you want to indicate the
      minor mode in the mode line.  This element should be a list of the
      following form:
 
           (MODE-VARIABLE STRING)
 
      Here MODE-VARIABLE is the variable that controls enabling of the
      minor mode, and STRING is a short string, starting with a space, to
      represent the mode in the mode line.  These strings must be short
      so that there is room for several of them at once.
 
      When you add an element to ‘minor-mode-alist’, use ‘assq’ to check
      for an existing element, to avoid duplication.  For example:
 
           (unless (assq 'leif-mode minor-mode-alist)
             (push '(leif-mode " Leif") minor-mode-alist))
 
      or like this, using ‘add-to-list’ (SeeList Variables):
 
           (add-to-list 'minor-mode-alist '(leif-mode " Leif"))
 
    In addition, several major mode conventions apply to minor modes as
 well: those regarding the names of global symbols, the use of a hook at
 the end of the initialization function, and the use of keymaps and other
 tables.
 
    The minor mode should, if possible, support enabling and disabling
 via Custom (SeeCustomization).  To do this, the mode variable
 should be defined with ‘defcustom’, usually with ‘:type 'boolean’.  If
 just setting the variable is not sufficient to enable the mode, you
 should also specify a ‘:set’ method which enables the mode by invoking
 the mode command.  Note in the variable’s documentation string that
 setting the variable other than via Custom may not take effect.  Also,
 mark the definition with an autoload cookie (Seeautoload cookie),
 and specify a ‘:require’ so that customizing the variable will load the
 library that defines the mode.  For example:
 
      ;;;###autoload
      (defcustom msb-mode nil
        "Toggle msb-mode.
      Setting this variable directly does not take effect;
      use either \\[customize] or the function `msb-mode'."
        :set 'custom-set-minor-mode
        :initialize 'custom-initialize-default
        :version "20.4"
        :type    'boolean
        :group   'msb
        :require 'msb)