Правильный способ включить второстепенный режим

24

У меня есть режим foo, и я бы включил для него бар-минорный режим . Так какой путь более распространен и предпочтителен?

A

(add-hook 'foo-mode-hook 'bar-minor-mode)

В

(add-hook 'foo-mode-hook (lambda ()
                           "Turn on `bar-minor-mode' mode."
                           (bar-minor-mode 1)))

С

(defun bar-minor-mode-on ()
  "Turn on `bar-minor-mode' mode."
  (interactive)
  (bar-minor-mode 1))

(add-hook 'foo-mode-hook 'bar-minor-mode-on)

D

• вариант C, но функция перенесена в восходящий поток

Е

• вариант C, но функция хранится в рецепте плагина

Netsu
источник
4
Привет @ Нецу, я заметил, что ты добавил цитату, которую я удалил из твоей лямбды. В общем, цитировать лямбды вредно, поэтому Стефан и я просто пытаемся мотивировать хорошие практики. :-)
Малабарба

Ответы:

26

Это зависит от того, какую версию (версии) Emacs вы используете (или нацеливаетесь). Если вы используете исключительно Emacs 24+, вы можете смело использовать вариант A:

* Incompatible Lisp Changes in Emacs 24.1

** Passing a nil argument to a minor mode function call now ENABLES
the minor mode unconditionally.  This is so that you can write e.g.

 (add-hook 'text-mode-hook 'foo-mode)

to enable foo-mode in Text mode buffers, removing the need for
`turn-on-foo-mode' style functions.  This affects all mode commands
defined by `define-minor-mode'.  If called interactively, the mode
command still toggles the minor mode.

Это из файла NEWS, но в соответствии с комментариями рекомендуется использовать кавычки функций для символов функций, например:

 (add-hook 'text-mode-hook #'foo-mode)

Если код может потребоваться запустить под Emacs 23 (или более ранней версии), я бы выбрал вариант C, так как лично мне не нравится видеть анонимные функции в переменных хуков. (Я не уверен, что понимаю, что вы подразумеваете под вариантами D & E, запомните).

Phils
источник
3
Желательно использовать кавычки функций для второстепенного режима, чтобы байтовый компилятор мог предупредить вас, если режим не определен.
lunaryorn
Спасибо. Но все же необходимо ли использовать функцию цитирования? Какие преимущества это дает? Также это необходимо для лямбд?
Нетсу
7

Вот еще один способ сделать это, который имеет некоторые преимущества, предполагая, что вы редактируете свою собственную конфигурацию, а не пакет, который вы распространяете.

(add-hook 'foo-mode-hook
          #'custom-foo-hook)

(defun custom-foo-hook ()
  (bar-minor-mode 1)
  (baz-minor-mode 1)
  ;; ...
  (define-key foo-mode-map "C-c C-b" #'foobar))

Преимущество состоит в том, что все хранится в одном хуке, поэтому чтобы отключить некоторые вещи, вам не нужно ничего делать remove-hook, а вместо этого комментировать некоторые вещи в custom-foo-hookи C-M-x.

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

Або-або
источник
1
Это (по сути) вариант C с другим именем, но я согласен, что стоит подчеркнуть. Это, безусловно, тот подход, который я использую, когда настраиваю поведение основного режима в своем собственном конфиге.
Филс
1
Вариант C предполагает add-hookвключение нескольких операторов для каждого второстепенного режима. Я хотел подчеркнуть, что наличие только одного add-hookутверждения является преимуществом.
abo-abo
Согласовано. В моей голове я в значительной степени перевел вариант C, чтобы «определить пользовательскую функцию, которая включает режим», а не «определить пользовательскую функцию, которая только включает режим», но, оглядываясь назад, последняя, ​​похоже, была намерением. Как вы говорите, это зависит от того, предназначен ли код для личного использования.
Филс
7

Почему вы определяете новую команду, которая делает именно то, что bar-minor-modeделает?

Начиная с 24.1, все они полностью эквивалентны, поэтому просто используйте менее избыточный: вариант A

(add-hook 'foo-mode-hook #'bar-minor-mode)
Malabarba
источник
1
Это безопасное решение? Я имею в виду, если один из родительских режимов foo-mode-hook имеет тот же хук, что bar-minor-mode будет вызывать дважды, поэтому будет отключен. Неожиданное поведение.
Нетсу
2
@ Нецу да, вызов функции второстепенного режима без аргументов ВКЛЮЧАЕТ безусловный режим.
Малабарба
4
@Malabarba Только в Emacs 24. В более ранних версиях я действительно переключал режим.
lunaryorn
1
@lunaryorn Да, поэтому ответ Филса лучше. :-) Я был слишком ленив, чтобы починить мой.
Малабарба