Второй вариант - использовать необязательный аргумент LOCAL
для add-hook
, который делает указанную функцию локальной для буфера.При таком подходе вы могли бы написать свой хук следующим образом:
(add-hook 'python-mode-hook 'cr/python-mode-shell-setup)
(defun cr/python-mode-shell-setup ()
(add-hook 'hack-local-variables-hook
(lambda () (message "virtualenv-name is %s" cr/virtualenv-name)
(let ((python-base (cr/virtualenv)))
(cond ((and (fboundp 'ipython-shell-hook) (file-executable-p (concat python-base "/bin/ipython")))
(setq python-python-command (concat python-base "/bin/ipython"))
(setq py-python-command (concat python-base "/bin/ipython"))
(setq py-python-command-args '( "-colors" "NoColor")))
(t
(setq python-python-command (concat python-base "/bin/python"))
(setq py-python-command (concat python-base "/bin/python"))
(setq py-python-command-args nil)))))
nil t)) ; buffer-local hack-local-variables-hook
т.е. python-mode-hook
запускается первым и регистрирует анонимную функцию с помощью hack-local-variables-hook
только для текущего буфера;и эта функция затем вызывается после обработки локальных переменных.
Комментарий Lindydancer предлагает третий подход.Это не так чисто, как два других, но оказалось интересным независимо.Мне не понравилась идея вызова (hack-local-variables)
дважды, но я вижу, что если вы установите буфер local-enable-local-variables
локально, это помешает (hack-local-variables)
делать что-либо, поэтому вы могли бы сделайте это:
(defun cr/python-mode-shell-setup ()
(report-errors "File local-variables error: %s"
(hack-local-variables)))
(set (make-local-variable 'local-enable-local-variables) nil)
(let ((python-base (cr/virtualenv)))
...))
Очевидно, что это немного изменяет нормальную последовательность выполнения, поэтому возможны побочные эффекты.Меня беспокоило, что если тот же основной режим установлен локальной переменной comment в файле, это может привести к бесконечной рекурсии, но на самом деле это не проблема.
Комментарии заголовка локальной переменной (например, -*- mode: foo -*-
) обрабатываются (set-auto-mode)
, так что все в порядке;но комментарий mode: foo
Local Variables:
кажется, что это будет проблемой, так как он обрабатывается (hack-local-variables)
, и поэтому, если режим установлен таким образом, я думал, что это вызовет рекурсию.
На практике ябыл в состоянии вызвать проблему, используя простую функцию в качестве «режима», которая не делала ничего, кроме попыток запустить свои ловушки;однако тестирование в «правильном» режиме не показало проблемы, так что это, вероятно, безопасно в реальности.Я не стал вдаваться в подробности (так как два других решения намного чище, чем этот), но я думаю, что механизм ловушек с отложенным режимом, вероятно, объясняет это?