Der Kontext
Ich verwende den after-make-frame-functions
Haken, um die Themen in einer Emacs-Client / Server-Konfiguration richtig zu laden . Im Einzelnen ist dies das Code-Snippet, mit dem ich das mache (basierend auf dieser SO-Antwort ):
(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)))
Das Problem
Wenn eine neue emacsclient -c/t
Sitzung gestartet wird, wird der Hook nicht nur in dem neuen Frame ausgeführt, sondern in allen vorherigen vorhandenen Frames (andere Emacsclient- Sitzungen), und es entsteht ein sehr ärgerlicher visueller Effekt (die Themes werden in all diesen Frames erneut geladen) . Schlimmer noch, in den bereits geöffneten Terminal-Clients wird das Thema Farbe komplett durcheinander gebracht. Dies geschieht natürlich nur auf den Emacs-Clients, die mit demselben Emacs-Server verbunden sind. Der Grund für dieses Verhalten ist klar, der Hook wird auf dem Server ausgeführt und alle seine Clients sind betroffen.
Die Frage
Gibt es eine Möglichkeit, diese Funktion nur einmal auszuführen oder dasselbe Ergebnis zu erhalten, ohne den Hook zu verwenden?
Eine Teillösung
Ich habe jetzt diesen Code, dank der Antwort von @ Drew. Wenn Sie jedoch eine Client-Sitzung im Terminal starten, wird die GUI die Designs nicht richtig laden und umgekehrt. Nach vielen Tests stellte ich fest, dass das Verhalten davon abhängt, welcher Emacsclient zuerst startet, und nach dem Verwerfen verschiedener Dinge denke ich, dass dies möglicherweise mit der geladenen Farbpalette zusammenhängt. Wenn Sie das Design manuell neu laden, funktioniert alles einwandfrei. Aus diesem Grund tritt dieses Verhalten nicht immer auf, wenn die Funktion wie in meiner ursprünglichen Konfiguration vom Hook aufgerufen wird.
(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)))
Das finale Resultat
Schließlich habe ich voll funktionsfähigen Code, der das in der Teillösung beobachtete Verhalten behebt. Um dies zu erreichen, führe ich die Funktion einmal nach Modus (Terminal oder GUI) aus, wenn der betreffende Emacsclient zum ersten Mal gestartet wird, und entferne dann die Funktion aus dem Hook, weil nicht mehr benötigt. Jetzt bin ich glücklich! :) Nochmals vielen Dank @Drew!
Der Code:
(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)))