Контекст
Я использую after-make-frame-functions
хук для правильной загрузки тем в конфигурации клиент / сервер emacs . В частности, это фрагмент кода, который я использую для этого (на основе этого SO ответа ):
(if (daemonp)
(add-hook 'after-make-frame-functions
(lambda (frame)
(select-frame frame)
(load-theme 'monokai t)
;; setup the smart-mode-line and its theme
(sml/setup)))
(progn (load-theme 'monokai t)
(sml/setup)))
Проблема
Когда начинается новый emacsclient -c/t
сеанс, ловушка выполняется не только в новом кадре, но и во всех предыдущих существующих кадрах (другие сеансы emacsclient ), и это создает очень раздражающий визуальный эффект (темы снова загружаются во все эти кадры) . Хуже того, в терминале клиенты уже открыли тему, цвет которой полностью испортился. Очевидно, что это происходит только на клиентах emacs, подключенных к тому же серверу emacs. Причина такого поведения ясна: ловушка запускается на сервере и затрагиваются все его клиенты.
Вопрос
Есть ли способ выполнить эту функцию только один раз или получить тот же результат без использования ловушки?
Частичное решение
Теперь у меня есть этот код, благодаря ответу @ Drew. Но все же есть проблема: после запуска клиентского сеанса в терминале графический интерфейс не загружает темы должным образом и наоборот. После многих испытаний я понял, что поведение зависит от того, какой emacsclient запускается первым, и после отбрасывания различных вещей, я думаю, что это может быть связано с загруженной цветовой палитрой. Если вы перезагружаете вручную тему, все работает нормально, и это причина, почему это поведение не появляется, когда функция вызывается ловушкой каждый раз, как в моей начальной конфигурации.
(defun emacsclient-setup-theme-function (frame)
(progn
(select-frame frame)
(load-theme 'monokai t)
;; setup the smart-mode-line and its theme
(sml/setup)
(remove-hook 'after-make-frame-functions 'emacsclient-setup-theme-function)))
(if (daemonp)
(add-hook 'after-make-frame-functions 'emacsclient-setup-theme-function)
(progn (load-theme 'monokai t)
(sml/setup)))
Окончательное решение
Наконец, у меня есть полностью рабочий код, который решает поведение, наблюдаемое в частичном решении, для достижения этого я запускаю функцию один раз в режиме (терминал или графический интерфейс), когда затем запускается соответствующий emacsclient, затем удаляю функцию из ловушки, потому что больше не нужно. Теперь я счастлив! :) Еще раз спасибо @Drew!
Код:
(setq myGraphicModeHash (make-hash-table :test 'equal :size 2))
(puthash "gui" t myGraphicModeHash)
(puthash "term" t myGraphicModeHash)
(defun emacsclient-setup-theme-function (frame)
(let ((gui (gethash "gui" myGraphicModeHash))
(ter (gethash "term" myGraphicModeHash)))
(progn
(select-frame frame)
(when (or gui ter)
(progn
(load-theme 'monokai t)
;; setup the smart-mode-line and its theme
(sml/setup)
(sml/apply-theme 'dark)
(if (display-graphic-p)
(puthash "gui" nil myGraphicModeHash)
(puthash "term" nil myGraphicModeHash))))
(when (not (and gui ter))
(remove-hook 'after-make-frame-functions 'emacsclient-setup-theme-function)))))
(if (daemonp)
(add-hook 'after-make-frame-functions 'emacsclient-setup-theme-function)
(progn (load-theme 'monokai t)
(sml/setup)))