¿Cómo puedo anular una cara predefinida para fondos claros y oscuros?

9

Me gustaría utilizar set-face-attributepara elegir uno de los dos colores para el primer plano dependiendo de si el fondo del tema actual es claro u oscuro.

El comportamiento esperado es que el primer plano cambia automáticamente si cambio de un tema de fondo claro a un tema de fondo oscuro o viceversa.

Aquí hay un caso de uso:

Personalizo la cara de la stripe-hl-linesiguiente manera:

 (set-face-attribute 'stripe-hl-line nil
                        :overline   "gray"
                        :underline  "gray"
                        :foreground "dodger blue")

Pero me gustaría cambiar el primer plano en función de si el tema es claro u oscuro. De esa manera no tengo que preocuparme por personalizar esa cara en cada tema.

Kaushal Modi
fuente
Eso es algo que normalmente se hace en la definición del tema.
wasamasa
Aunque podría complicarse, parece que podría hacer uso de la colorbiblioteca aquí. Probablemente podría obtener el valor rgb o hexadecimal de la cara de fondo, determinar un valor umbral para "oscuro" y establecer el primer plano en consecuencia.
Dan
@wasamasa Sí. Pero para algunas caras, no me importa que su color sea específico para el tema. He actualizado mi pregunta con una cara de ejemplo que quiero personalizar.
Kaushal Modi
@Dan ¿Cuál sería un gancho apropiado para reevaluar el hexágono de fondo?
Kaushal Modi
esta es la lógica que puede usar `(defface Changing-face '((((fondo oscuro)): primer plano" Blanco ") (t: primer plano" Negro ")): grupo' x-mode-faces)` ... Dado que si desea usar la cara existente, puede agregar las 2 líneas del medio a la forma de defface existente.
Madhavan

Respuestas:

9

Gracias a @MadhavanKumar, me centré en derivar una solución basada en defface.

Me di cuenta de que no puedo anular una existente, deffacepero siempre puedo crear mi propio color de fondo sensible defface. Entonces, la única pregunta era cómo usar mi defface personalizada en lugar de la original.

Usaré el mismo ejemplo de anular la stripe-hl-linecara para analizar la solución. Esta cara se define en el paquete stripe-buffer.

Aquí están los pasos:

Paso 1. Define tu propio defface

(defface my/stripe-hl-line
  '((((background dark))  (:overline "gray" :underline "gray" :foreground "dodger blue"))
    (t                    (:overline "gray" :underline "gray" :foreground "red")))
  "Bold face for highlighting the current line in Hl-Line mode."
  :group 'stripe-buffer)

Esto dará como resultado que el color de primer plano de la my/stripe-hl-linecara sea azul para fondos oscuros y rojo para fondos claros.

Paso 2. Crea una función para reasignar la cara

La face-remap-add-relativefunción se utiliza para reasignar una cara existente a una nueva cara. En este caso, estoy reasignando la stripe-hl-linecara a my/stripe-hl-line.

(defun my/stripe-hl-line-face-remap ()
  (face-remap-add-relative 'stripe-hl-line 'my/stripe-hl-line))

Paso 3. Haz la reasignación en la ubicación adecuada

Desde la stripe-bufferfuente, veo que la hl-linecara se reasigna a la stripe-hl-linecara. Entonces necesitamos hacer nuestra reasignación después de que ocurra esa reasignación (que está en la stripe-listify-bufferdefinición de la función).

Entonces hacemos nuestra reasignación aconsejando stripe-listify-bufferusar el combinador.:after advice

(advice-add 'stripe-listify-buffer :after #'my/stripe-hl-line-face-remap)

¡Hecho!

Dicho esto, hubiera sido increíble usar directamente algo como set-face-attributeponer caras basadas en la oscuridad del fondo.

Kaushal Modi
fuente