Le contexte
J'utilise le after-make-frame-functions
hook pour charger correctement les thèmes dans une configuration client / serveur emacs . Plus précisément, voici l'extrait de code que j'utilise pour le faire (basé sur cette réponse 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)))
Le problème
Lorsqu'une nouvelle emacsclient -c/t
session est démarrée, le hook est exécuté non seulement dans le nouveau cadre, mais dans tous les cadres existants existants (autres sessions emacsclient ) et cela fait un effet visuel très ennuyeux (les thèmes sont chargés à nouveau dans tous ces cadres) . Pire encore, dans le terminal, les clients déjà ouverts, la couleur du thème est complètement gâchée. Évidemment, cela ne se produit que sur les clients emacs connectés au même serveur emacs. La raison de ce comportement est claire, le hook est exécuté sur le serveur et tous ses clients sont affectés.
La question
Existe-t-il un moyen d'exécuter cette fonction une seule fois ou d'obtenir le même résultat sans utiliser le hook?
Une solution partielle
J'ai maintenant ce code, grâce à la réponse de @ Drew. Mais il y a toujours un problème, une fois que vous démarrez une session client dans le terminal, l'interface graphique ne charge pas les thèmes correctement et vice-versa. Après beaucoup de tests, j'ai réalisé que le comportement dépend de quel emacsclient commence en premier, et après avoir jeté diverses choses, je pense que c'est peut-être lié à la palette de couleurs qui est chargée. Si vous rechargez manuellement le thème, tout fonctionne bien et c'est la raison pour laquelle ce comportement n'apparaît pas lorsque la fonction est appelée par le hook à chaque fois comme dans ma configuration initiale.
(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)))
La solution finale
Enfin, j'ai un code totalement fonctionnel qui résout le comportement vu dans la solution partielle, pour y parvenir, j'exécute la fonction une fois par mode (terminal ou gui) lorsque le client pertinent est démarré pour la première fois, puis supprimez la fonction du crochet car est plus besoin. Maintenant, je suis heureux! :) Merci encore @Drew!
Le 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)))