unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Faces: How to clear an attribute while continuing to inherit other attributes?
@ 2019-10-10  2:42 Dave Goel
  2019-10-10  8:09 ` Eli Zaretskii
  0 siblings, 1 reply; 13+ messages in thread
From: Dave Goel @ 2019-10-10  2:42 UTC (permalink / raw)
  To: emacs-devel, Dave Goel

[-- Attachment #1: Type: text/plain, Size: 1316 bytes --]

How to unset an inherited face attribute while continuing to inherit other
attributes?

Face 'a inherits from 'b, which sets foreground to yellow. How do I keep 'a
inheriting from 'b, but set the foreground to (nothing), so that actually
rendering 'a goes to the default foreground (white) instead of yellow?

Emacs allows us to set a's foreground to nil (instead of 'unspecified), but
it magically becomes 'unspecified when queried. That's not what I was
aiming for. That is because 'unspecified means actually rendering face 'a
would yield yellow, the color inherited from 'b instead of the default
foreground.

Here's a test:

(progn
  (defface a nil "")
  (defface b nil "")
  (set-face-attribute  'b nil :foreground "yellow")
  (set-face-attribute 'a nil :inherit 'b)
  (set-face-attribute 'a nil :foreground nil)
  ;; let's chase how 'a would render:
  (face-attribute 'a :foreground nil t))

=> "yellow"

We expected either "white", the default foreground.


So, unfortunately, setting a's foreground to nil seems to be equivalent to
setting a's foreground to 'unspecified.

Once I set it to nil, I edebugged (face-attribute), and it calls  '
internal-get-lisp-face-attribute which yields 'unspecified instead of the
expected nil.

(Please cc replies if you can. I tested all this with emacs24.)

Thanks
Dave

[-- Attachment #2: Type: text/html, Size: 2404 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Faces: How to clear an attribute while continuing to inherit other attributes?
  2019-10-10  2:42 Faces: How to clear an attribute while continuing to inherit other attributes? Dave Goel
@ 2019-10-10  8:09 ` Eli Zaretskii
  2019-10-10 15:56   ` Dave Goel
  0 siblings, 1 reply; 13+ messages in thread
From: Eli Zaretskii @ 2019-10-10  8:09 UTC (permalink / raw)
  To: Dave Goel; +Cc: deego3, emacs-devel

> From: Dave Goel <deego3@gmail.com>
> Date: Wed, 9 Oct 2019 22:42:50 -0400
> 
> Emacs allows us to set a's foreground to nil (instead of 'unspecified), but it magically becomes 'unspecified
> when queried. That's not what I was aiming for. That is because 'unspecified means actually rendering face 'a
> would yield yellow, the color inherited from 'b instead of the default foreground.
> 
> Here's a test:  
> 
> (progn
>   (defface a nil "")
>   (defface b nil "")
>   (set-face-attribute  'b nil :foreground "yellow")
>   (set-face-attribute 'a nil :inherit 'b)
>   (set-face-attribute 'a nil :foreground nil)
>   ;; let's chase how 'a would render:
>   (face-attribute 'a :foreground nil t))
> 
> => "yellow"
> 
> We expected either "white", the default foreground.

What do you mean by "default foreground" here? is that the foreground
of the default face, or the foreground of whatever other face(s) that
are merged to produce the appearance of a character on display?



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Faces: How to clear an attribute while continuing to inherit other attributes?
  2019-10-10  8:09 ` Eli Zaretskii
@ 2019-10-10 15:56   ` Dave Goel
  2019-10-10 15:59     ` Dave Goel
  2019-10-10 17:37     ` Eli Zaretskii
  0 siblings, 2 replies; 13+ messages in thread
From: Dave Goel @ 2019-10-10 15:56 UTC (permalink / raw)
  To: Eli Zaretskii, Dave Goel; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 443 bytes --]

> What do you mean by "default foreground" here?

I mean: The foreground of the face called 'default. That's what emacs picks
the attribute from if none is matched.
It seems that the intention of allowing face A to specify an attribute as
nil is to /clear/ the inherited attribute (so that emacs can fall back upon
the default for that attribute). Unfortunately, nil seems to become
'unspecified at the moment, which => inherit the attribute.

[-- Attachment #2: Type: text/html, Size: 870 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Faces: How to clear an attribute while continuing to inherit other attributes?
  2019-10-10 15:56   ` Dave Goel
@ 2019-10-10 15:59     ` Dave Goel
  2019-10-10 17:37     ` Eli Zaretskii
  1 sibling, 0 replies; 13+ messages in thread
From: Dave Goel @ 2019-10-10 15:59 UTC (permalink / raw)
  To: Eli Zaretskii, Dave Goel; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 841 bytes --]

Indeed, that's how it works - correctly - for some attributes, example,
:underlin. Setting it to nil clears anything inherited, making emacs fall
back to the default.
:foreground and :background go halfway towards that behavior, providing the
ability to set to nil, but then treat it as 'unspecified.




On Thu, Oct 10, 2019 at 11:56 AM Dave Goel <deego3@gmail.com> wrote:

>
> > What do you mean by "default foreground" here?
>
> I mean: The foreground of the face called 'default. That's what emacs
> picks the attribute from if none is matched.
> It seems that the intention of allowing face A to specify an attribute as
> nil is to /clear/ the inherited attribute (so that emacs can fall back upon
> the default for that attribute). Unfortunately, nil seems to become
> 'unspecified at the moment, which => inherit the attribute.
>
>
>

[-- Attachment #2: Type: text/html, Size: 1986 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Faces: How to clear an attribute while continuing to inherit other attributes?
  2019-10-10 15:56   ` Dave Goel
  2019-10-10 15:59     ` Dave Goel
@ 2019-10-10 17:37     ` Eli Zaretskii
  2019-10-10 17:50       ` Dave Goel
  1 sibling, 1 reply; 13+ messages in thread
From: Eli Zaretskii @ 2019-10-10 17:37 UTC (permalink / raw)
  To: Dave Goel; +Cc: deego3, emacs-devel

> From: Dave Goel <deego3@gmail.com>
> Date: Thu, 10 Oct 2019 11:56:21 -0400
> Cc: emacs-devel@gnu.org
> 
> > What do you mean by "default foreground" here?
> 
> I mean: The foreground of the face called 'default.

Then you could simply set the foreground of your face to be the same
as of the default face by using set-face-attribute, no?



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Faces: How to clear an attribute while continuing to inherit other attributes?
  2019-10-10 17:37     ` Eli Zaretskii
@ 2019-10-10 17:50       ` Dave Goel
  2019-10-10 18:07         ` Eli Zaretskii
  0 siblings, 1 reply; 13+ messages in thread
From: Dave Goel @ 2019-10-10 17:50 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1140 bytes --]

Of course, but that runs counter to the philosophy of inheritance. If you
changed the default, you have to then go back and change all such faces.

Again, if it was something like :underline or :bold or :height, you
wouldn't see this problem: setting them to nil would remove any
inheritance, and then, whenever you change the 'default face, your face's
final resolved value automatically uses that.

It seems that :fg and :bg also try to implement precisely that (providing a
nil option as well as 'unspecified), but then don't do the final step
correctly.

It seems that the design of faces goes out of its way to carefully
distinguish nil from 'unspecified, precisely to allow you to clear an
attribute..




On Thu, Oct 10, 2019 at 1:37 PM Eli Zaretskii <eliz@gnu.org> wrote:

> > From: Dave Goel <deego3@gmail.com>
> > Date: Thu, 10 Oct 2019 11:56:21 -0400
> > Cc: emacs-devel@gnu.org
> >
> > > What do you mean by "default foreground" here?
> >
> > I mean: The foreground of the face called 'default.
>
> Then you could simply set the foreground of your face to be the same
> as of the default face by using set-face-attribute, no?
>

[-- Attachment #2: Type: text/html, Size: 2428 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Faces: How to clear an attribute while continuing to inherit other attributes?
  2019-10-10 17:50       ` Dave Goel
@ 2019-10-10 18:07         ` Eli Zaretskii
  2019-10-10 18:26           ` Dave Goel
       [not found]           ` <47578dbd-71ea-cb02-c337-96fb18af1915@lanl.gov>
  0 siblings, 2 replies; 13+ messages in thread
From: Eli Zaretskii @ 2019-10-10 18:07 UTC (permalink / raw)
  To: Dave Goel; +Cc: emacs-devel

> From: Dave Goel <deego3@gmail.com>
> Date: Thu, 10 Oct 2019 13:50:33 -0400
> Cc: emacs-devel@gnu.org
> 
> Of course, but that runs counter to the philosophy of inheritance. If you changed the default, you have to then
> go back and change all such faces. 

Not if your code does

  (set-face-foreground FACE (face-foreground 'default))

With this, if the default face changes the color, FACE will follow
suit.

You could also try inheriting from both default and another face,
although I'm not sure this will do what you want (as I don't yet have
a clear idea of what you are trying to do)

> Again, if it was something like :underline or :bold or :height, you wouldn't see this problem: setting them to nil
> would remove any inheritance, and then, whenever you change the 'default face, your face's final resolved
> value automatically uses that.   

That's because for boolean attributes nil is a valid value, whereas
valid values for colors are strings, so nil isn't valid and is taken
as unspecified.

You must understand that face inheritance is a one-way street: Emacs
merges all the faces in the chain starting from default and going down
the inheritance chain, so the last face in the chain that specifies a
color wins.

> It seems that :fg and :bg also try to implement precisely that (providing a nil option as well as 'unspecified),
> but then don't do the final step correctly.

I don't see anything incorrect in what you describe, it is all
expected behavior.

> It seems that the design of faces goes out of its way to carefully distinguish nil from 'unspecified, precisely to
> allow you to clear an attribute..

See above: I think your conclusion is wrong.



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Faces: How to clear an attribute while continuing to inherit other attributes?
  2019-10-10 18:07         ` Eli Zaretskii
@ 2019-10-10 18:26           ` Dave Goel
  2019-10-10 18:39             ` Eli Zaretskii
       [not found]           ` <47578dbd-71ea-cb02-c337-96fb18af1915@lanl.gov>
  1 sibling, 1 reply; 13+ messages in thread
From: Dave Goel @ 2019-10-10 18:26 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 931 bytes --]

> Not if your code does
>   (set-face-foreground FACE (face-foreground 'default))
> With this, if the default face changes the color, FACE will follow
suit.


I don't see that at all here in my emacs24:

 (progn
   (defface a nil "")
   (defface b nil "")
   (set-face-attribute  'b nil :foreground "yellow")
   (set-face-attribute 'a nil :inherit 'b)
   (set-face-foreground 'a (face-foreground 'default))
   ;; let's chase how 'a would render:
   (let
       ((init (face-attribute 'a :foreground nil t))
        final)
        (set-face-foreground 'default "pink")
        (setq final (face-attribute 'a :foreground nil t))
        (message "%S %S" init final)))

"\"white\" \"white\""
Per your assertion, the message should have been: white, pink.

Also, your point seems to be: We shouldn't allow nil (to clear
inheritances) for :fg and :bg (unlike for other faces) because: "*we only
allow strings*". I don't get that logic.

[-- Attachment #2: Type: text/html, Size: 1868 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Faces: How to clear an attribute while continuing to inherit other attributes?
  2019-10-10 18:26           ` Dave Goel
@ 2019-10-10 18:39             ` Eli Zaretskii
  0 siblings, 0 replies; 13+ messages in thread
From: Eli Zaretskii @ 2019-10-10 18:39 UTC (permalink / raw)
  To: Dave Goel; +Cc: emacs-devel

> From: Dave Goel <deego3@gmail.com>
> Date: Thu, 10 Oct 2019 14:26:02 -0400
> Cc: emacs-devel@gnu.org
> 
> > Not if your code does
> >   (set-face-foreground FACE (face-foreground 'default))
> > With this, if the default face changes the color, FACE will follow
> suit.
> 
> I don't see that at all here in my emacs24:

That's because you expect the attribute to magically change after you
set it.  That won't happen; what I meant was to set your face's
foreground _after_ the default changes.

Like I said: I don't have a clear idea of what you are trying to do,
so it's little wonder I'm suggesting things that don't work for you.

> Also, your point seems to be: We shouldn't allow nil (to clear inheritances) for :fg and :bg (unlike for other
> faces) because: "we only allow strings". I don't get that logic. 

There's no way to "clear" inheritance.  What you can do is override
the attributes of the parent face in the inheriting face.  That's
_override_, not _clear_.  IOW, you have to supply a value for the
attribute, and there's no value that "clears" the attribute.

I suggest to take a step back and describe in more detail the problem
you are trying to solve, for which you wanted to "clear" the
foreground color of an inheriting face.  It sounds like you somehow
zeroed in on a particular solution that cannot work.  So please
describe the problem this was supposed to solve, and let us propose a
solution that does work.



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Faces: How to clear an attribute while continuing to inherit other attributes?
       [not found]             ` <83k19cqvdi.fsf@gnu.org>
@ 2019-10-11  0:56               ` Dave Goel
  2019-10-11  1:13                 ` Dave Goel
  2019-10-11  8:36                 ` Eli Zaretskii
  0 siblings, 2 replies; 13+ messages in thread
From: Dave Goel @ 2019-10-11  0:56 UTC (permalink / raw)
  To: Eli Zaretskii, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 731 bytes --]

> That's because you expect the attribute to magically change after you
set it.

Yes, I do :)

That's what face A would do if it did not inherit B (which specified the
attribute). It would magically follow whatever default does. for the
missing attribute.



On Thu, Oct 10, 2019 at 3:00 PM Eli Zaretskii <eliz@gnu.org> wrote:

> That's what 'unspecified' does, and it clearly isn't what Dave
> wanted.  He wanted a value that says "clear that attribute", and
> there's no such value.


But, again, nothing stops us from providing one. For example, specifying
'clear would cause all inheritances to pause, so that the result of chasing
becomes 'unspecified, even if one of the ancestors specified the face.
.
What is DMARC?



>
>

[-- Attachment #2: Type: text/html, Size: 3136 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Faces: How to clear an attribute while continuing to inherit other attributes?
  2019-10-11  0:56               ` Dave Goel
@ 2019-10-11  1:13                 ` Dave Goel
  2019-10-11  8:37                   ` Eli Zaretskii
  2019-10-11  8:36                 ` Eli Zaretskii
  1 sibling, 1 reply; 13+ messages in thread
From: Dave Goel @ 2019-10-11  1:13 UTC (permalink / raw)
  To: Eli Zaretskii, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1278 bytes --]

If this were implemented, I'd also want 'clear to follow normal precedence
rules. For example, if a region has 3 faces, and the first face resolves to
'clear, then the final attribute is 'clear no matter what the other two
faces say, and no matter what any ancestor faces say. And, since the final,
chased attribute resolves to 'clear, emacs would look up the value from
'default, which always provides a value for every attribute.




On Thu, Oct 10, 2019 at 8:56 PM Dave Goel <deego3@gmail.com> wrote:

>
> > That's because you expect the attribute to magically change after you
> set it.
>
> Yes, I do :)
>
> That's what face A would do if it did not inherit B (which specified the
> attribute). It would magically follow whatever default does. for the
> missing attribute.
>
>
>
> On Thu, Oct 10, 2019 at 3:00 PM Eli Zaretskii <eliz@gnu.org> wrote:
>
>> That's what 'unspecified' does, and it clearly isn't what Dave
>> wanted.  He wanted a value that says "clear that attribute", and
>> there's no such value.
>
>
> But, again, nothing stops us from providing one. For example, specifying
> 'clear would cause all inheritances to pause, so that the result of chasing
> becomes 'unspecified, even if one of the ancestors specified the face.
> .
> What is DMARC?
>
>
>
>>
>>

[-- Attachment #2: Type: text/html, Size: 4314 bytes --]

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Faces: How to clear an attribute while continuing to inherit other attributes?
  2019-10-11  0:56               ` Dave Goel
  2019-10-11  1:13                 ` Dave Goel
@ 2019-10-11  8:36                 ` Eli Zaretskii
  1 sibling, 0 replies; 13+ messages in thread
From: Eli Zaretskii @ 2019-10-11  8:36 UTC (permalink / raw)
  To: Dave Goel; +Cc: emacs-devel

> From: Dave Goel <deego3@gmail.com>
> Date: Thu, 10 Oct 2019 20:56:56 -0400
> Cc: Davis Herring <herring@lanl.gov>
> 
>  That's what 'unspecified' does, and it clearly isn't what Dave
>  wanted.  He wanted a value that says "clear that attribute", and
>  there's no such value.
>  
> But, again, nothing stops us from providing one.

Nothing, except someone who'd sit down and write the code that makes
sense in related situations.



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Faces: How to clear an attribute while continuing to inherit other attributes?
  2019-10-11  1:13                 ` Dave Goel
@ 2019-10-11  8:37                   ` Eli Zaretskii
  0 siblings, 0 replies; 13+ messages in thread
From: Eli Zaretskii @ 2019-10-11  8:37 UTC (permalink / raw)
  To: Dave Goel; +Cc: emacs-devel

> From: Dave Goel <deego3@gmail.com>
> Date: Thu, 10 Oct 2019 21:13:51 -0400
> Cc: Davis Herring <herring@lanl.gov>
> 
> If this were implemented, I'd also want 'clear to follow normal precedence rules. For example, if a region has 3
> faces, and the first face resolves to 'clear, then the final attribute is 'clear no matter what the other two faces
> say, and no matter what any ancestor faces say. And, since the final, chased attribute resolves to 'clear,
> emacs would look up the value from 'default, which always provides a value for every attribute. 

This is against how Emacs merges faces.  But feel free to file a
feature request via report-emacs-bug, maybe someone will find a way to
do it.



^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2019-10-11  8:37 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-10-10  2:42 Faces: How to clear an attribute while continuing to inherit other attributes? Dave Goel
2019-10-10  8:09 ` Eli Zaretskii
2019-10-10 15:56   ` Dave Goel
2019-10-10 15:59     ` Dave Goel
2019-10-10 17:37     ` Eli Zaretskii
2019-10-10 17:50       ` Dave Goel
2019-10-10 18:07         ` Eli Zaretskii
2019-10-10 18:26           ` Dave Goel
2019-10-10 18:39             ` Eli Zaretskii
     [not found]           ` <47578dbd-71ea-cb02-c337-96fb18af1915@lanl.gov>
     [not found]             ` <83k19cqvdi.fsf@gnu.org>
2019-10-11  0:56               ` Dave Goel
2019-10-11  1:13                 ` Dave Goel
2019-10-11  8:37                   ` Eli Zaretskii
2019-10-11  8:36                 ` Eli Zaretskii

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).