Существуют соглашения для написания режимов, как и для
основных режимов (см. Основные режимы). Эти
соглашения описаны ниже. Самый простой способ следовать им — использовать макрос
define-minor-mode. См. Определение режимов.
nil, если режим отключен, и не-nil,
если режим включен. Переменная должна быть локальной для буфера, если режим является
локальным для буфера.
Эта переменная используется совместно с minor-mode-alist для
отображения имени режима в строке режима. Она также определяет, активен ли
сопоставление клавиш режима, через minor-mode-map-alist (см.
Управление активными сопоставлениями).
Отдельные команды или хуки также могут проверять ее значение.
Команда режима должна принимать один необязательный аргумент. Если она вызывается интерактивно без аргумента префикса, она должна переключать режим (т.е. включать, если он отключен, и отключать, если он включен). Если она вызывается интерактивно с аргументом префикса, она должна включить режим, если аргумент положительный, и отключить его в противном случае.
Если команда режима вызывается из Lisp (т.е. неинтерактивно), она должна
включить режим, если аргумент опущен или равен nil; она должна
переключать режим, если аргумент — символ toggle; в противном
случае она должна обрабатывать аргумент так же, как для интерактивного вызова
с числовым аргументом префикса, как описано выше.
Пример ниже показывает, как реализовать это поведение (это похоже на код,
генерируемый макросом define-minor-mode):
(interactive (list (or current-prefix-arg 'toggle)))
(let ((enable
(if (eq arg 'toggle)
(not foo-mode) ; это переменная режима
(> (prefix-numeric-value arg) 0))))
(if enable
do-enable
do-disable))
Причина этого несколько сложного поведения в том, что это позволяет пользователям легко переключать режим интерактивно, а также позволяет легко включить режим в хуке режима, как это:
(add-hook 'text-mode-hook 'foo-mode)
Это работает правильно независимо от того, был ли foo-mode
уже включен, поскольку команда режима foo-mode безусловно
включает режим, когда она вызывается из Lisp без аргументов. Отключение
режима в хуке режима немного более громоздкое:
(add-hook 'text-mode-hook (lambda () (foo-mode -1)))
Однако это не очень часто делается.
Включение или отключение режима дважды подряд не должно вызывать сбоев и должно делать то же самое, что и включение или отключение один раз. Другими словами, команда режима должна быть идемпотентной.
minor-mode-alist для каждого
режима (см. Определение minor-mode-alist),
если вы хотите указать режим в строке режима. Этот элемент должен быть списком
следующего вида:
(mode-variable string)
Здесь mode-variable — это переменная, управляющая включением режима, а string — это короткая строка, начинающаяся с пробела, для представления режима в строке режима. Эти строки должны быть короткими, чтобы было место для нескольких из них одновременно.
При добавлении элемента в minor-mode-alist используйте
assq, чтобы проверить наличие существующего элемента,
избегая дублирования. Например:
(unless (assq 'leif-mode minor-mode-alist) (push '(leif-mode " Leif") minor-mode-alist))
Или так, используя add-to-list (см. Изменение переменных списка):
(add-to-list 'minor-mode-alist '(leif-mode " Leif"))
Кроме того, к режимам также применяются несколько соглашений основных режимов (см. Соглашения основных режимов): касающиеся имен глобальных символов, использования хука в конце функции инициализации и использования сопоставлений клавиш и других таблиц.
Режим должен, по возможности, поддерживать включение и отключение через
Custom (см. Настройки кастомизации).
Для этого переменная режима должна быть определена с помощью defcustom,
обычно с :type 'boolean. Если простое присвоение
переменной недостаточно для включения режима, вы также должны указать метод
:set, который включает режим, вызывая команду режима. Обратите
внимание в строке документации переменной, что установка переменной не через
Custom может не сработать. Также отметьте определение файлом автозагрузки
(см. autoload cookie) и
укажите :require, чтобы кастомизация переменной загружала
библиотеку, определяющую режим. Например:
;;;###autoload (defcustom msb-mode nil "Переключить msb-mode. Установка этой переменной напрямую не имеет эффекта; используйте либо \\[customize] либо функцию `msb-mode'." :set 'custom-set-minor-mode :initialize 'custom-initialize-default :version "20.4" :type 'boolean :group 'msb :require 'msb)