Thanks to @MadhavanKumar, I focused on deriving a solution based on defface
.
I realized that I can't override an existing defface
but I can always create my own background color sensitive defface
. Then the only question was how to use my custom defface instead of the original.
I'll use the same example of overriding the stripe-hl-line
face to walk through the solution. This face is defined in the package stripe-buffer
.
Here are the steps:
Step 1. Define your own 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)
This will result in the foreground color of my/stripe-hl-line
face being dodger blue for dark backgrounds and red for light backgrounds.
Step 2. Create a function to remap the face
The face-remap-add-relative
function is used to remap an existing face to a new face. In this case, I am remapping the stripe-hl-line
face to my/stripe-hl-line
.
(defun my/stripe-hl-line-face-remap ()
(face-remap-add-relative 'stripe-hl-line 'my/stripe-hl-line))
Step 3. Do the remapping at appropriate location
From the stripe-buffer
source, I see that the hl-line
face is remapped to stripe-hl-line
face. So we need to do our remapping after that remapping happens (which is in the stripe-listify-buffer
function definition).
So we do our remapping by advising stripe-listify-buffer
using the :after
advice
combinator.
(advice-add 'stripe-listify-buffer :after #'my/stripe-hl-line-face-remap)
Done!
That said, it would have been awesome to directly use something like set-face-attribute
to set faces based on the background darkness.
color
library here. You could probably get the rgb or hex value of the background face, determine some threshold value for "dark", and set the foreground accordingly.