Spec-Zone.ru › Elisp

Определение второстепенных режимов

Макрос define-minor-mode предоставляет удобный способ реализации режима в одном автономном определении.

Макрос: define-minor-mode mode doc keyword-args… body…

Этот макрос определяет новый второстепенный режим с именем mode (символ). Он определяет команду с именем mode для переключения второстепенного режима, используя doc в качестве строки документации.

Команда переключения принимает один необязательный аргумент (префиксный). При интерактивном вызове без аргумента она включает или выключает режим. Положительный префиксный аргумент включает режим, любой другой префиксный аргумент выключает его. Из Lisp аргумент toggle переключает режим, тогда как пропущенный аргумент или аргумент nil включает его. Благодаря этому второстепенный режим легко включить, например, в хуке основного режима. Если doc равен nil, макрос предоставляет строку документации по умолчанию, объясняющую описанное выше.

По умолчанию он также определяет переменную с именем mode, которой при включении или выключении режима присваивается значение t или nil соответственно.

keyword-args состоит из ключевых слов и соответствующих им значений. Некоторые ключевые слова имеют специальное значение:

:global global

Если значение не равно nil, оно указывает, что второстепенный режим должен быть глобальным, а не локальным для буфера. По умолчанию используется значение nil.

Одно из следствий глобального второстепенного режима состоит в том, что переменная mode становится переменной настройки. Переключение режима через интерфейс Customize включает и выключает его, а его значение можно сохранить для будущих сеансов Emacs (см. Сохранение настроек в Руководстве GNU Emacs). Чтобы сохранённая переменная работала, необходимо обеспечить доступность функции второстепенного режима при каждом запуске Emacs; обычно для этого форму define-minor-mode помечают как автозагружаемую.

:init-value init-value

Это значение, которому присваивается переменная mode при инициализации. За исключением необычных обстоятельств (см. ниже), это значение должно быть nil. Обратите внимание: define-minor-mode не запускает автоматически тело второстепенного режима, чтобы гарантировать, что режим действительно включён в соответствии с этим значением. Поэтому, если режим глобальный (см. выше), а начальное значение не равно nil, рассмотрите возможность принудительно запускать функцию режима при его загрузке в Emacs, например, так:

 :initialize #'custom-initialize-after-file-load

В противном случае второстепенный режим может сообщать, что он включён, хотя его настройка не была выполнена должным образом.

:lighter lighter

Строка lighter задаёт текст, отображаемый в строке режима, когда режим включён; если она равна nil, режим в строке режима не отображается.

:keymap keymap

Необязательный аргумент keymap задаёт карту клавиш второстепенного режима. Если он не равен nil, это должно быть имя переменной (значение которой является картой клавиш), карта клавиш или ассоциативный список следующей формы:

(key-sequence . definition)

где каждый аргумент key-sequence и definition должен подходить для передачи функции define-key (см. Изменение привязок клавиш). Если keymap — карта клавиш или ассоциативный список, это также определяет переменную mode-map.

:variable place

Эта настройка заменяет переменную mode по умолчанию, используемую для хранения состояния режима. Если указать её, переменная mode не определяется, а любой аргумент init-value не используется. place может быть другой именованной переменной (которую необходимо определить самостоятельно) или любым объектом, который можно использовать с функцией setf (см. Обобщённые переменные). place также может быть cons-ячейкой (get . set), где get — выражение, возвращающее текущее состояние, а set — функция с одним аргументом (состоянием), которая должна присваиваться place.

:after-hook after-hook

Эта настройка определяет единственную форму Lisp, которая вычисляется после выполнения хуков режима. Её не следует заключать в кавычки.

:interactive value

По умолчанию второстепенные режимы являются интерактивными командами. Если value равно nil, это отключается. Если value — список символов, он задаёт основные режимы, в которых полезен этот второстепенный режим.

Все остальные аргументы-ключевые слова напрямую передаются в defcustom, созданный для переменной mode. Описание этих ключевых слов и их значений см. в разделе Определение переменных настройки.

Команда с именем mode сначала выполняет стандартные действия, например присваивает значение переменной с именем mode, а затем выполняет формы body, если они есть. После этого она запускает переменную-хук режима mode-hook и завершает работу вычислением формы, заданной в :after-hook. (Обратите внимание, что всё это, включая запуск хука, выполняется как при включении, так и при выключении режима.)

Начальное значение должно быть nil, кроме случаев, когда (1) режим предварительно загружен в Emacs или (2) включение режима при загрузке не создаёт неудобств, даже если пользователь этого не запрашивал. Например, если режим не оказывает эффекта, пока не включено что-то ещё, и к тому времени он всегда будет загружен, включение режима по умолчанию безвредно. Однако такие обстоятельства встречаются редко. Обычно начальное значение должно быть nil.

Пример использования define-minor-mode:

(define-minor-mode hungry-mode
  "Toggle Hungry mode.
Interactively with no argument, this command toggles the mode.
A positive prefix argument enables the mode, any other prefix
argument disables it.  From Lisp, argument omitted or nil enables
the mode, `toggle' toggles the state.

When Hungry mode is enabled, the control delete key
gobbles all preceding whitespace except the last.
See the command \\[hungry-electric-delete]."
 ;; The initial value.
 nil
 ;; The indicator for the mode line.
 " Hungry"
 ;; The minor mode bindings.
 '(([C-backspace] . hungry-electric-delete)))

Этот код определяет второстепенный режим с именем «Hungry mode», команду hungry-mode для его переключения, переменную hungry-mode, указывающую, включён ли режим, и переменную hungry-mode-map, содержащую карту клавиш, активную при включённом режиме. Карта клавиш инициализируется привязкой для C-DEL. Форм body нет — многим второстепенным режимам они не нужны.

То же самое можно записать следующим образом:

(define-minor-mode hungry-mode
  "Toggle Hungry mode.
...rest of documentation as before..."
 ;; The initial value.
 :init-value nil
 ;; The indicator for the mode line.
 :lighter " Hungry"
 ;; The minor mode bindings.
 :keymap
 '(([C-backspace] . hungry-electric-delete)
   ([C-M-backspace]
    . (lambda ()
        (interactive)
        (hungry-electric-delete t)))))
Макрос: define-globalized-minor-mode global-mode mode turn-on keyword-args… body…

Этот макрос определяет глобальный переключатель с именем global-mode, который включает или выключает локальный для буфера второстепенный режим mode во всех буферах (или в некоторых; см. ниже). Он также выполняет формы body. Чтобы включить второстепенный режим в буфере, используется функция turn-on; чтобы выключить его, вызывается mode с аргументом −1. (Функция turn-on является отдельной функцией, чтобы она могла определять, следует ли включать второстепенный режим, когда заранее не ясно, нужно ли включать его всегда.)

Обратите внимание, что это отличается от использования define-minor-mode с ключевым словом :global, отличным от nil: режим, определённый этим макросом, по-прежнему локален для буфера, он просто включается во всех (или некоторых) буферах.

Глобальное включение режима затрагивает только те буферы, которые впоследствии создаются с использованием основного режима, следующего соглашению о запуске run-mode-hooks. Во второстепенных режимах, не следующих этому соглашению, режим включён не будет.

Этот макрос определяет параметр настройки global-mode (см. Параметры настройки), который можно переключать через интерфейс Customize, чтобы включать и выключать второстепенный режим. Как и в случае с define-minor-mode, необходимо обеспечить вычисление формы define-globalized-minor-mode при каждом запуске Emacs, например, указав ключевое слово :require.

Используйте :group group в keyword-args, чтобы задать группу настройки для переменной глобального второстепенного режима.

По умолчанию локальная для буфера переменная второстепенного режима, указывающая, включён он или выключен, совпадает с именем самого режима. Используйте :variable variable, если это не так: некоторые второстепенные режимы хранят сведения о состоянии в другой переменной.

Как правило, определяя глобальный второстепенный режим, следует также определить его неглобальную версию, чтобы пользователи могли включать (или отключать) её в отдельных буферах. Это также позволяет отключить глобально включённый второстепенный режим в конкретном основном режиме с помощью хука этого режима.

Если макросу передано ключевое слово :predicate, он создаст пользовательский параметр с тем же именем, что и глобальная переменная режима, но с -modes вместо -mode в конце, то есть global-modes. Эта переменная будет использоваться в функции-предикате, определяющей, следует ли активировать второстепенный режим для конкретного основного режима. Пользователи могут настроить значение переменной, чтобы управлять основными режимами, в которых будет включаться второстепенный режим. Допустимые значения :predicate (а значит, и созданного пользовательского параметра) включают t (использовать во всех основных режимах), nil (не использовать ни в одном основном режиме) или список имён режимов, перед которым при необходимости может стоять not (как в (not mode-name …)). Эти элементы можно комбинировать, как показано в примерах ниже.

(c-mode (not mail-mode message-mode) text-mode)

Это означает: «использовать в режимах, производных от c-mode, не использовать в режимах, производных от message-mode или mail-mode, но использовать в режимах, производных от text-mode, и не использовать в остальных режимах».

((not c-mode) t)

Это означает: «не использовать в режимах, производных от c-mode, но использовать во всех остальных».

(text-mode)

Это означает: «использовать в режимах, производных от text-mode, но нигде больше». (В конце подразумевается элемент nil.)

Макрос: buffer-local-set-state variable value...

Второстепенные режимы часто задают локальные для буфера переменные, влияющие на некоторые возможности Emacs. При выключении второстепенного режима ожидается, что он восстановит прежние значения этих переменных. Этот вспомогательный макрос упрощает эту задачу: он работает подобно setq-local, но возвращает объект, который можно использовать для восстановления прежних значений и состояний (с помощью соответствующей функции buffer-local-restore-state).

Copyright © 1990-1996, 1998-2026 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Defining-Minor-Modes.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API