El contexto
Estoy usando el after-make-frame-functions
gancho para cargar correctamente los temas en una configuración de cliente / servidor de emacs . Específicamente, este es el fragmento de código que uso para hacer eso (basado en esta respuesta 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)))
El problema
Cuando emacsclient -c/t
se inicia una nueva sesión, el gancho se ejecuta no solo en el nuevo cuadro, sino en todos los cuadros anteriores existentes (otras sesiones de emacsclient ) y produce un efecto visual muy molesto (los temas se cargan nuevamente en todos esos cuadros) . Peor aún, en la terminal los clientes que ya abrieron el color del tema se desordenaron por completo. Obviamente, eso solo ocurre en los clientes de emacs conectados al mismo servidor de emacs. La razón de este comportamiento es clara, el enlace se ejecuta en el servidor y todos sus clientes se ven afectados.
La pregunta
¿Hay alguna forma de ejecutar esta función solo una vez u obtener el mismo resultado sin usar el gancho?
Una solución parcial
Ahora tengo este código, gracias a la respuesta de @ Drew. Pero aún tiene un problema, una vez que inicia una sesión de cliente en el terminal, la GUI no carga los temas correctamente y viceversa. Después de muchas pruebas, me di cuenta de que el comportamiento depende de qué cliente electrónico comienza primero, y después de descartar varias cosas, creo que tal vez esté relacionado con la paleta de colores que se carga. Si vuelve a cargar manualmente el tema, todo funciona bien y esa es la razón por la cual este comportamiento no aparece cuando el gancho llama a la función cada vez como en mi configuración inicial.
(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 solución definitiva
Finalmente, tengo un código totalmente funcional que resuelve el comportamiento visto en la solución parcial, para lograr esto ejecuto la función una vez por modo (terminal o gui) cuando se inicia emacsclient pertinente por primera vez, luego elimino la función del gancho porque es No se necesita más. ¡Ahora soy feliz! :) Gracias de nuevo @Drew!
El código:
(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)))