Соглашения для основных режимов
Код каждого основного режима должен соответствовать различным соглашениям о программировании, в том числе соглашениям об инициализации локальной карты клавиш и таблицы синтаксиса, именах функций и переменных, а также хуках.
Если использовать макрос define-derived-mode, он автоматически обеспечит соблюдение многих из этих соглашений. См. Определение производных режимов. Обратите также внимание, что режим Fundamental является исключением из многих этих соглашений, поскольку он представляет собой состояние Emacs по умолчанию.
Следующий список соглашений является неполным. Каждый основной режим должен стремиться в целом соответствовать другим основным режимам Emacs, поскольку это делает Emacs более целостным. Невозможно перечислить здесь все возможные случаи, в которых может возникнуть этот вопрос; если разработчики Emacs укажут на область, в которой ваш основной режим отступает от обычных соглашений, приведите его в соответствие.
- Определите команду основного режима, имя которой заканчивается на «-mode». При вызове без аргументов эта команда должна переключать текущий буфер в новый режим, настраивая карту клавиш, таблицу синтаксиса и локальные для буфера переменные в существующем буфере. Она не должна изменять содержимое буфера.
- Напишите для этой команды строку документации, описывающую специальные команды, доступные в этом режиме. См. Получение справки об основном режиме.
Строка документации может содержать специальные подстановки документации «\[command]», «\{keymap}» и «\<keymap>», позволяющие автоматически адаптировать отображение справки к пользовательским привязкам клавиш. См. Подстановка привязок клавиш в документации.
- Команда основного режима должна начинаться с вызова
kill-all-local-variables. Эта функция запускает обычный хукchange-major-mode-hook, а затем удаляет локальные для буфера переменные ранее действовавшего основного режима. См. Создание и удаление привязок, локальных для буфера. - Команда основного режима должна присваивать переменной
major-modeсимвол команды основного режима. Такdescribe-modeузнаёт, какую документацию следует вывести. - Команда основного режима должна присваивать переменной
mode-name«красивое» имя режима, обычно строку (другие возможные формы см. в разделе Структура данных строки режима). Имя режима отображается в строке режима. - Повторный вызов команды основного режима подряд не должен приводить к ошибке и должен давать тот же результат, что и однократный вызов. Иными словами, команда основного режима должна быть идемпотентной.
- Поскольку все глобальные имена находятся в одном пространстве имён, имена всех глобальных переменных, констант и функций, относящихся к режиму, должны начинаться с имени основного режима (или с его сокращения, если имя длинное). См. Соглашения о программировании на Emacs Lisp.
- В основном режиме для редактирования структурированного текста, например языка программирования, вероятно, полезно форматировать текст с отступами согласно его структуре. Поэтому режим должен присвоить переменной
indent-line-functionподходящую функцию и, вероятно, настроить другие переменные для отступов. См. Автоматическая расстановка отступов в коде. -
У основного режима обычно должна быть собственная карта клавиш, используемая как локальная карта клавиш во всех буферах этого режима. Команда основного режима должна вызывать
use-local-mapдля установки этой локальной карты. Дополнительные сведения см. в разделе Активные карты клавиш.Эта карта клавиш должна постоянно храниться в глобальной переменной с именем
modename-mode-map. Обычно эта переменная задаётся в библиотеке, определяющей режим.Советы по написанию кода для настройки переменной карты клавиш режима см. в разделе Советы по надёжному определению переменных.
- Последовательности клавиш, привязанные в карте клавиш основного режима, обычно должны начинаться с C-c, за которым следует управляющий символ, цифра или {, }, <, >, : или ;. Остальные знаки пунктуации зарезервированы для второстепенных режимов, а обычные буквы — для пользователей.
Основной режим также может переопределять клавиши M-n, M-p и M-s. Привязки для M-n и M-p обычно должны выполнять какое-либо перемещение вперёд и назад, хотя это не обязательно должно быть перемещение курсора.
Основному режиму допустимо переопределить стандартную последовательность клавиш, если он предоставляет команду, выполняющую ту же задачу способом, лучше подходящим для текста, с которым работает этот режим. Например, основной режим для редактирования языка программирования может переопределить C-M-a, чтобы переходить к началу функции способом, лучше подходящим для этого языка. Рекомендуемый способ адаптировать C-M-a к потребностям основного режима — присвоить
beginning-of-defun-function(см. Перемещение по сбалансированным выражениям) функцию, предназначенную для этого режима.Основному режиму также допустимо переопределить стандартную последовательность клавиш, стандартное значение которой редко бывает полезным в этом режиме. Например, режимы минибуфера переопределяют M-r, стандартное значение которой редко приносит пользу в минибуфере. Основные режимы, такие как Dired или Rmail, не допускающие непосредственного ввода текста, могут обоснованно переопределять буквы и другие печатные символы, назначая им специальные команды.
- Основные режимы для редактирования текста не должны назначать клавише RET какое-либо действие, кроме вставки новой строки. Однако специализированные режимы для текста, который пользователи не редактируют напрямую, например режимы Dired и Info, могут переопределять RET, назначая ей совершенно иное действие.
- Основные режимы не должны изменять параметры, которые зависят преимущественно от предпочтений пользователя, например включён ли режим Auto-Fill. Оставьте это на усмотрение каждого пользователя. Однако основной режим должен настроить другие переменные так, чтобы режим Auto-Fill работал полезным образом, если пользователь решит его использовать.
-
У режима может быть собственная таблица синтаксиса или общая с другими родственными режимами. Если у него есть собственная таблица синтаксиса, её следует хранить в переменной с именем
modename-mode-syntax-table. См. Таблицы синтаксиса. (Основные режимы, основанные на библиотеке tree-sitter, используют для этого парсеры, предоставляемые tree-sitter; см. Блокировка шрифтов на основе парсера.) - Если режим работает с языком, в котором предусмотрен синтаксис комментариев, ему следует задать переменные, определяющие синтаксис комментариев. См. раздел Параметры управления комментариями в Руководстве GNU Emacs.
-
У режима может быть собственная таблица сокращений или общая с другими родственными режимами. Если у него есть собственная таблица сокращений, её следует хранить в переменной с именем
modename-mode-abbrev-table. Если команда основного режима сама определяет какие-либо сокращения, ей следует передатьtв качестве аргумента system-flag функцииdefine-abbrev. См. Определение сокращений. - Режим должен указывать, как выполнять подсветку в режиме Font Lock, задав локальное для буфера значение переменной
font-lock-defaults(см. Режим Font Lock). Сведения об основном режиме на основе tree-sitter см. в разделе Блокировка шрифтов на основе парсера. - Каждая грань, определяемая режимом, по возможности должна наследоваться от существующей грани Emacs. См. разделы Основные грани и Грани для Font Lock.
- Рассмотрите возможность добавления в строку меню меню для данного режима. Желательно, чтобы оно включало наиболее важные специфичные для меню настройки и команды, позволяющие пользователям быстро и эффективно находить основные функции.
-
Рассмотрите возможность добавления контекстных меню для режима, которые будут использоваться, если пользователи активируют
context-menu-mode(см. раздел Щелчки мышью по меню в Руководстве Emacs). Для этого определите специфичную для режима функцию, которая создаёт одно или несколько меню в зависимости от места щелчка mouse-3 в буфере, а затем добавьте эту функцию к локальному для буфера значениюcontext-menu-functions. - Режим должен указывать, как Imenu следует находить определения или разделы буфера: задав локальное для буфера значение переменной
imenu-generic-expression, двух переменныхimenu-prev-index-position-functionиimenu-extract-index-name-functionлибо переменнойimenu-create-index-function(см. Imenu). - Режим должен указывать, как второстепенному режиму Outline находить строки заголовков: задав локальные для буфера значения переменных
outline-regexpилиoutline-search-function, а также переменнойoutline-level(см. Второстепенный режим Outline). - Режим может сообщить режиму ElDoc, как получать разные типы документации для объекта в точке, добавив одну или несколько локальных для буфера записей в специальный хук
eldoc-documentation-functions. - Режим может указать, как выполнять автодополнение различных ключевых слов, добавив одну или несколько локальных для буфера записей в специальный хук
completion-at-point-functions. См. Автодополнение в обычных буферах. -
Чтобы создать локальную для буфера привязку для переменной настройки Emacs, используйте в команде основного режима
make-local-variable, а неmake-variable-buffer-local. Последняя функция сделает переменную локальной для каждого буфера, в котором она будет задана впоследствии, что затронет буферы, не использующие этот режим. Нежелательно, чтобы режим имел такие глобальные последствия. См. Переменные, локальные для буфера.За редкими исключениями, единственный разумный способ использовать
make-variable-buffer-localв пакете Lisp — применить его к переменной, используемой только внутри этого пакета. Его применение к переменной, используемой другими пакетами, будет им мешать. -
У каждого основного режима должен быть обычный хук режима с именем
modename-mode-hook. Самое последнее, что должна делать команда основного режима, — вызыватьrun-mode-hooks. Эта функция запускает обычный хукchange-major-mode-after-body-hook, хук режима, функциюhack-local-variables(если буфер связан с файлом), а затем обычный хукafter-change-major-mode-hook. См. Хуки режимов. - Команда основного режима может начинаться с вызова другой команды основного режима (называемой родительским режимом), а затем изменять некоторые её настройки. Такой режим называется производным режимом. Рекомендуется определять его с помощью макроса
define-derived-mode, хотя это необязательно. Такой режим должен вызывать команду родительского режима внутри формыdelay-mode-hooks. (Макросdefine-derived-modeделает это автоматически.) См. разделы Определение производных режимов и Хуки режимов. - Если при переключении пользователем буфера из этого режима в любой другой основной режим нужно выполнить какие-либо специальные действия, этот режим может задать локальное для буфера значение
change-major-mode-hook(см. Создание и удаление привязок, локальных для буфера). -
Если этот режим подходит только для специально подготовленного текста, созданного самим режимом (а не введённого пользователем с клавиатуры или полученного из внешнего файла), символ команды основного режима должен иметь свойство с именем
mode-classсо значениемspecial, задаваемое следующим образом:(put 'funny-mode 'mode-class 'special)
Это сообщает Emacs, что новые буферы, созданные, пока текущий буфер находится в режиме Funny, не следует переводить в режим Funny, даже если значением по умолчанию для
major-modeявляетсяnil. По умолчанию значениеnilдляmajor-modeозначает, что при создании новых буферов используется основной режим текущего буфера (см. Как Emacs выбирает основной режим), но для таких режимовspecialвместо этого используется режим Fundamental. Эту возможность используют такие режимы, как Dired, Rmail и Buffer List.Функция
view-bufferне включает режим View в буферах, чей mode-class является специальным, поскольку такие режимы обычно предоставляют собственные привязки, похожие на привязки режима View.Макрос
define-derived-modeавтоматически помечает производный режим как специальный, если родительский режим является специальным. Режим Special — удобный родительский режим, от которого могут наследоваться такие режимы; см. Основные основные режимы. - Если вы хотите сделать новый режим режимом по умолчанию для файлов с определёнными узнаваемыми именами, добавьте элемент в
auto-mode-alist, чтобы выбирать этот режим для таких имён файлов (см. Как Emacs выбирает основной режим). Если вы определяете команду режима для автозагрузки, добавьте этот элемент в тот же файл, где вызываетсяautoload. Если для команды режима используется cookie автозагрузки, можно также использовать cookie автозагрузки для формы, добавляющей этот элемент (см. cookie автозагрузки). Если команда режима не загружается автоматически, достаточно добавить этот элемент в файл с определением режима. -
Верхнеуровневые формы в файле, определяющем режим, следует писать так, чтобы их можно было вычислять несколько раз без нежелательных последствий. Например, используйте
defvarилиdefcustomдля задания переменных, связанных с режимом, чтобы они не инициализировались повторно, если уже имеют значение (см. Определение глобальных переменных).
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/Major-Mode-Conventions.html