Kontekst
Korzystam z after-make-frame-functions
haka, aby poprawnie załadować motywy w konfiguracji klient / serwer emacs . W szczególności jest to fragment kodu, którego używam do tego (na podstawie tej odpowiedzi 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)))
Problem
Po uruchomieniu nowej emacsclient -c/t
sesji zaczep jest wykonywany nie tylko w nowej ramce, ale we wszystkich poprzednich istniejących ramkach (inne sesje emacsclient ) i daje bardzo irytujący efekt wizualny (motywy są ładowane ponownie we wszystkich tych ramkach) . Co gorsza, w terminalu klienci, którzy już otworzyli, kolor motywu jest całkowicie pomieszany. Oczywiście dzieje się tak tylko na klientach emacs podłączonych do tego samego serwera emacs. Przyczyna tego zachowania jest jasna, hak jest uruchamiany na serwerze i dotyczy to wszystkich jego klientów.
Pytanie
Czy jest jakiś sposób na wykonanie tej funkcji tylko raz lub uzyskanie tego samego wyniku bez użycia haka?
Częściowe rozwiązanie
Mam teraz ten kod, dzięki odpowiedzi @ Drew. Ale nadal ma problem, gdy rozpoczniesz sesję klienta w terminalu, GUI nie ładuje poprawnie motywów i odwrotnie. Po wielu testach zdałem sobie sprawę, że zachowanie zależy od tego, który emacsclient zaczyna się jako pierwszy, a po odrzuceniu różnych rzeczy myślę, że może być związany z załadowaną paletą kolorów. Jeśli przeładujesz ręcznie kompozycję, wszystko działa dobrze i dlatego to zachowanie nie pojawia się, gdy funkcja jest wywoływana przez hak za każdym razem, jak w mojej początkowej konfiguracji.
(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)))
Ostateczne rozwiązanie
Wreszcie mam całkowicie działający kod, który rozwiązuje zachowanie widoczne w rozwiązaniu częściowym. Aby to osiągnąć, uruchamiam funkcję jeden raz w trybie (terminal lub GUI), kiedy po raz pierwszy uruchamiany jest odpowiedni emacsclient, a następnie usuwam funkcję z zaczepu, ponieważ jest nie jest już potrzebny. Teraz jestem szczęśliwy! :) Jeszcze raz dziękuję @Drew!
Kod:
(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)))