Subject: bug#51465: closed (Re: [External] : Re: bug#51465: 27.2; `face-all-attributes' doc or behavior (?))

From: [email-masked] (GNU bug Tracking System)
Date: Fri, 29 Oct 2021 07:25:02 +0000

Your bug report

#51465: 27.2; `face-all-attributes' doc or behavior (?)

which was filed against the emacs package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
51465: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=51465
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: [External] : Re: bug#51465: 27.2; `face-all-attributes' doc or behavior (?)
From: Eli Zaretskii <[email-masked]>
To: Drew Adams <[email-masked]>
Cc: [email-masked]
Date: Fri, 29 Oct 2021 10:24:06 +0300
List-Id: <debbugs-submit.debbugs.gnu.org>

> From: Drew Adams <[email-masked]>
> CC: "[email-masked]" <[email-masked]>
> Date: Thu, 28 Oct 2021 23:08:42 +0000
> 
> > > (elisp) `Attribute Functions' says "the default attributes of FACE
> > > for newly created frames".  I would expect to see :background as
> > > "LightGoldenrod", not as `unspecified'.
> > 
> > Why? because that's what you actually see in a new frame?  Those
> > aren't the default attributes, those are the attributes specified by
> > defface.
> 
> The Elisp manual says it returns "the default attributes
> of FACE for newly created frames."
> 
> Whenever I create a new frame (from emacs -Q) that face
> on that frame has a :background of "LightGoldenrod" -
> never `unspecified'.  Is the manual wrong?

No, it isn't wrong: the "default attributes for newly created frames"
are those the face has before applying the definitions in defface.

Note that the description of face-attribute in the same section
already hints on what is going on here:

                      If FRAME is ‘t’, this function returns the value
     of the specified attribute for newly-created frames (this is
     normally ‘unspecified’, unless you have specified some value using
     ‘set-face-attribute’; see below).

If you use set-face-attribute with the FRAME argument t to set some
attribute's value, the next call to face-all-attributes will no longer
show 'unspecified' for that attribute.  And the next frame created
after that will use the attribute value you specified, effectively
overriding the corresponding attribute's value defined by defface.

> Unless otherwise specified (which could be by
> `default-frame-alist' or whatever) a newly created
> frame has, according to the manual, the attributes
> for that face that are given by `face-all-attributes'
> when that function is passed a nil FRAME arg: "the
> default attributes of FACE for newly created frames."
> 
> IOW, it calls this "the default attributes" for
> "newly created frames", not the attributes for some
> existing frame (this is the FRAME=nil case).
> 
> And yet, with emacs -Q, every newly created frame
> has :background set to "LightGoldenrod" (AFAICT).
> At the very least, most, if not all, newly created
> frames have that attribute value.  None have that
> attribute with a value of `unspecified'.

That's because defface's definitions are merged with those defaults,
when the frame is created, which in this case yields the
non-unspecified background color.  So you rarely if ever see those
default attributes, except if you call this function.

> I'd think that "default" would just mean what you
> get for a newly created frame unless there is
> something that overrides that somehow.

That is correct, and that is what happens here; see above.

> I'd think that "default" is what the current customized value of the
> face has - that's what you get by default for a newly created frame
> (or if it's not customized then the value given by the original
> defface).

Right.  But the default values are before merging the defface's
definitions.

> I'm hoping you at least see a possibility for
> confusion in the doc.

Thanks, I've now clarified the documentation on the release branch to
be more specific about the meaning of "default" in this context, and
made sure the same explanation appears in both face-attribute and
face-all-attributes.

> And maybe even a problematic behavior

I see no problems in the behavior, no.  It's just a complex issue, and
it isn't easy to explain it clearly to readers that aren't necessarily
privy to the implementation details.  Hopefully, it's more clear now.

> (what's the point of returning `unspecified' everywhere?).

Only if no default values were defined via set-face-attribute.

And with that, I'm closing this bug report.

Subject: 27.2; `face-all-attributes' doc or behavior (?)
From: Drew Adams <[email-masked]>
To: "[email-masked]" <[email-masked]>
Date: Thu, 28 Oct 2021 19:08:53 +0000
List-Id: <debbugs-submit.debbugs.gnu.org>

emacs -Q

Set eval-expression-print-length to nil for the session.

 (face-all-attributes 'region) ; C-x C-e

Shows all attributes, including :background, with value `unspecified'.

 (face-all-attributes 'region (selected-frame)) ; C-x C-e

Shows attribute :background with value "LightGoldenrod".

The doc string of `face-all-attributes' says that a nil second arg
means use "the default attributes".

What does that mean - what are the default attributes?  I was expecting
that it meant the default settings for the face: default set of
attributes with their default values for that face.

(elisp) `Attribute Functions' says "the default attributes of FACE for
newly created frames".  I would expect to see :background as
"LightGoldenrod", not as `unspecified'.

If arg FRAME is specified (as a frame) then the function returns the
attributes of FACE on FRAME.  Not sure what that means either - faces
have different attributes on different frames?

If I do `M-x customize-face region' from emacs -Q I see :background set
as "LightGoldenrod".  That command customizes the face for all frames,
no?  So doesn't that mean that the face has that background for all
frames (by default)?

Why would one want to get a list of the face's attributes with every
attribute value as `unspecified'?  More importantly, how to get the
actual (default) values "for all frames" - what you see when you use
`customize-face'?

I feel I must be missing something obvious, here.  But the Elisp manual
didn't make things any clearer.

___

You can let me know if the rest of this report should be posted as a
separate bug report.  But perhaps you could just let me know what I'm
missing in this regard too, if that's simple to do.

My question is why do we have the &rest argument ARGUMENTS of
`set-face-attribute' be a plist, but what `face-all-attributes' returns
is an alist?  Just to do something like the following isn't possible:

(apply #'set-face-attribute 'some-face
                            nil
                            (face-all-attributes 'other-face))

To accomplish that you need to convert the alist returned by
`face-all-attributes' to a plist, and pass that to `set-face-attribute'.
Why?  What other uses of these two functions would suggest that they
should use different ways to express the list of face attributes?

In GNU Emacs 27.2 (build 1, x86_64-w64-mingw32)
 of 2021-03-26 built on CIRROCUMULUS
Repository revision: deef5efafb70f4b171265b896505b92b6eef24e6
Repository branch: HEAD
Windowing system distributor 'Microsoft Corp.', version 10.0.19042
System Description: Microsoft Windows 10 Pro (v10.0.2009.19042.1288)