Subject: bug#38771: Allow face-attribute to be 'reset, (in addition the usual 'unspecified and valid-values)

From: Dave Goel <[email-masked]>
Date: Sat, 28 Dec 2019 05:34:50 -0500

(Thanks for an excellent discussion with Eli (-devel) and Davis, which
ended in Eli suggesting a bug-report.)

You have constructed an awesome new face, f1, for your mode which inherits
from 20 other ancestors, and sets attributes just right.

You now want to make up a new face f2, which would inherit-from f1, except
you would like to clear the value of :height, so that emacs would render it
the same as the user's default at run-time. That  seems like a plausible,
practical, use-case to me.  (And, I was trying to do just that in some code
recently.)

Imagine a face f3 that's just like f1, except that the final (chased) value
of :height is 'unspecified. Can we make f2 behave like f3?

How do you clear :height in f2?

Setting nil doesn't do it. For :height, nil is an invalid value.
Practically, if you set it nil, it behaves like 'unspecified for this
attribute. Nil is often a valid value for attributes like :slant. Nil is
not same as 'unspecified. And, even if it was, see below.

Setting 'unspecified doesn't do it. Emacs will now look up the value from
f2's parent, f1.

You could set f2's height to be the same as default's height at
define-time, but that is not the same as leaving it 'unspecified. Indeed,
the user could have changed the defaults by run-time, and f2 fails to
adhere to that. In summary, f2 != f3.

Finally, you could chase every attribute from f1, and then define f2 based
on that, and leave :height  'unspecified. In other words, set f2=f3 (after
a lot of work). But, even that is unsatsfactory and loses the purpose of
inheritance in multiple ways. (a) That's a lot of work. The whole point of
inheritance was to save all that work. (b) More importantly, we  now we
lose the run-time values of f1. If f1 has been customized, the
customization no longer carries over to f2. The purpose of inheriting f2
from f1 was to carry over most attributes automatically and continuously
even after the user costumizes f1.

It seems that there's no way to clear an attribute, and it would be nice to
allow that.

Could we allow a 'reset? Where the effect of 'reset is to stop all chasing,
and immediately render the final value as 'unspecified (so that emacs looks
up the final value from 'default during rendering)

----
If we are feeling generous, we could also allow an additional 'clear,
slightly different from 'reset, as follows:

If point has five faces (+default) active (f1 f2 f3 f4 f5, default), then
'reset found at, say, f2 behaves as above, sending us straight to 'default.

But, 'clear in f2 merely stops chasing f2's own ancestors. We next go to f3
in this case.