Как «группировать» крючки?

14

Существуют определенные вещи, такие как отображение конечных пробелов, отображение границ буфера, разноцветные разделители и многое другое, что я хотел бы включить в большинстве режимов или, скорее, во всех, связанных с программированием и текстом (поскольку отображение конечных пробелов в скажем ediff-mode, столкнулся бы с основным режимом) вместо использования глобального вспомогательного режима с правилами исключений. Так как большинство режимов являются производными от prog-modeили text-mode, добавление рассматриваемой функции к обоим prog-mode-hookи text-mode-hookдействительно работает, однако есть достаточно режимов, не соответствующих этой спецификации, таких как css-modeили LaTeX-mode.

Я хотел бы определить ловушку, которая в настоящее время охватывает все эти режимы, чтобы добавлять функции только к одной ловушке. Давайте назовем это non-special-mode-hook(чтобы отличить это от special-mode-hook). Как я смогу создать такой хук, который будет работать для всех основных режимов, для которых он сделан?

wasamasa
источник

Ответы:

19

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

(defun my-non-special-mode-setup ()
  (setq show-trailing-whitespace t)
  ...)
(dolist (hook '(prog-mode-hook text-mode-hook css-mode-hook ...))
  (add-hook hook 'my-non-special-mode-setup))

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

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

sanityinc
источник
Спасибо, я думаю, что я адаптирую это решение и для других полезных групп (например, для тех, кто не подходит).
Васамаса
1
Это именно то , что я делаю сам: github.com/purcell/emacs.d/blob/...
sanityinc
1
Отлично, не могли бы вы добавить URL к своему ответу? Я полагаю, что выделенный фрагмент не только очень хорошо объясняет фактическое использование, но также демонстрирует дальнейшее использование, такое как использование связанного с Emacs Lisp "хука" в качестве подмножества большего "хука" и того, как можно автоматически создавать имена хуков из существующих основных режимов. с derived-mode-hook-name.
васамаса
Мне нравится это больше, чем мое, только для (dolist ...)vs (add-hook ...)<repeat>. Я бы придерживаться только с месторождением при сохранении режима изменений , специфичных для отдельного (файл-в-режиме use-package, el-get). Оба являются универсальными решениями, но с разных точек зрения.
Джонатан Лич-Пепин
Имейте в виду, что если вы не укажете здесь APPENDаргумент, отличный от nil, add-hookто хуки будут вызываться в обратном порядке по сравнению с порядком списка, который вы предоставляете. Ничего плохого в этом нет; просто знайте об этом, если порядок имеет значение.
Дрю
5

Вы можете добавить функцию after-change-major-mode-hook, которая проверяет, является ли новый режим интересным (возможно, сквозным (not (derived-mode-p 'special-mode))), и если это так, запускается non-special-mode-hook.

legoscia
источник
Это звучит довольно изящно (как только вы разобрались со всеми «нестандартными» режимами, поскольку есть некоторые, которые просто используют fundamental-mode, но делают больше, чем просто отображают текст), но на мой вкус слишком волшебно. Отсюда и голос.
Васамаса
4

Я обнаружил, что часто выполняю шаблон @ sanityinc, заключая в себе мои настройки и второстепенные активации режима в defun и циклически перебирая хуки для его вызова, но мне нужен более чистый подход, поэтому я написал этот макрос:

(defmacro hook-modes (modes &rest body)
  (declare (indent 1))
  `(--each ,modes
     (add-hook (intern (format "%s-hook" it))
               (lambda () ,@body))))

Примечание: я dash.elза чистоту, но он может быть легко адаптирован для использования (dolist).

Затем вы можете определить сгруппированные режимы как список переменных и использовать их следующим образом:

(defvar progish-modes
  '(prog-mode css-mode sgml-mode))

(hook-modes progish-modes
  (highlight-symbol-mode)
  (highlight-symbol-nav-mode))
waymondo
источник
1
Обратите внимание, что здесь вы можете использовать, derived-mode-hook-nameчтобы получить имя переменной хука режима, тем самым избегая internхитрости.
sanityinc
@sanityinc TIL derived-mode-hook-name. хороший совет!
waymondo
1

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

(defun run-my-hooks ()
  "Run all the following functions in the hook"
  (smartparens-mode 1)
  (whitespace-mode 1)
  (my-needed-mode 1)
  ...)

(add-hook 'specific-mode-hook 'run-my-hooks)
(add-hook 'another-mode-hook 'run-my-hooks)

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

Джонатан Лич-Пепин
источник
-2

Может быть, вы можете попробовать это:

(setq lisp-dialects-mode-hook '(lisp-mode-hook
                            lisp-interaction-mode-hook
                            emacs-lisp-mode-hook
                            ;; common-lisp-mode-hook
                            scheme-mode-hook
                            clojure-mode-hook
                            cider-repl-mode-hook
                            ))

(add-hook 'lisp-dialects-mode-hook 'func)
stardiviner
источник