unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Defaulting faces to inherit deemed harmful [was: Stealing a default face from a non-ELPA package]
@ 2022-03-05 16:46 Drew Adams
  2022-03-05 18:38 ` Tim Cross
  0 siblings, 1 reply; 6+ messages in thread
From: Drew Adams @ 2022-03-05 16:46 UTC (permalink / raw)
  To: Tim Cross; +Cc: emacs-devel

> Personally, I wish more packages would define their
> faces in terms of inheritance from standard/built-in
> faces. This would mean a user could tweak the built-in
> faces to suit their preferences and the additional
> packages would inherit those tweaks without needing
> to be done individually.

Personally, I wish fewer packages, and default
Emacs itself, would define _fewer_ faces as
inheriting from other, standard/built-in faces -
in particular from font-lock faces.
___

tl;dr:
I expect that my opinion on this is a tiny minority
one.  I express it anyway, hoping it might open one
or two eyes or kindle a second thought here & there.
___

_Users_ can always do what you say: customize faces
to inherit from some face they want as parent.  And
they can do that at multiple levels: inheritance
hierarchy as deep or broad as you like - turtles
all the way...).
___

Font-lock faces, in particular, are defined to be
appropriate, by default, for particular _purposes_
(contexts) - e.g. comments.  Inheriting from them
willy nilly for faces that have nothing to do with
those purposes (e.g. non-code modes don't have
comments) creates unnecessary coupling.

The only face that has no specific purpose/context
is face `default'.  And that's as it should be.
In effect, all faces inherit from `default' (in
addition to having their own particularities).
___

Inheritance can be invisible at first sight, when
trying to figure out why a face looks as it does.

Inheriting by default is a bludgeon.  That blunt
club is often touted as the _reason_ for built-in
face inheritance by default:

> without needing to be done individually

A false problem, IMO.

1. Customizing a face _should_ in general be an
   individual choice, taking _context_/purpose
   into consideration.  (It's a similar decision
   to that of defining its default appearance.)

2. Nothing prevents customizing a face to inherit
   from another, including from standard/built-in
   faces.  It's _not at all difficult_ to do.
___

Inheriting by default has almost the same negative
effect as defining a face to have, by default, the
same appearance as face `default' (a practice that
`emacs -Q' used to embrace, and perhaps still does
here and there): You can't tell at a glance that
there's a separate/different face there.

Far better to use a different default appearance,
even if perhaps "ugly", so that users immediately
see that there's a separate face there that they
can customize to their liking.

The best way to introduce users to the fact that
they can easily customize faces is to let faces
stand out individually, by default.
___

I don't mean that each face needs a different
default definition.

I mean only that, other things being equal,
identical appearance works against recognizing
the presence of a different face.

What appearance to give a given face by default
is always a judgment call.  I mean only to add
this consideration to such a judgment, as one
more consideration, perhaps too often overlooked
in a zeal to concentrate face default appearance
with predefined inheritance.
___

One place _to_ perhaps use face inheritance by
default is in a theme.

And a library can similarly have some of its
faces inherit from some of _its_ other faces -
the `vc-*' faces inherit from `vc-state-base',
for example (with the tradeoff mentioned above:
lack of immediate recognition).  

A priori, most other uses of predefined
inheritance are  likely unwise/unhelpful, IMO. 

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

* Re: Defaulting faces to inherit deemed harmful  [was: Stealing a default face from a non-ELPA package]
  2022-03-05 16:46 Defaulting faces to inherit deemed harmful [was: Stealing a default face from a non-ELPA package] Drew Adams
@ 2022-03-05 18:38 ` Tim Cross
  2022-03-05 19:40   ` Eli Zaretskii
  2022-03-05 20:17   ` Drew Adams
  0 siblings, 2 replies; 6+ messages in thread
From: Tim Cross @ 2022-03-05 18:38 UTC (permalink / raw)
  To: Drew Adams; +Cc: emacs-devel


Drew Adams <drew.adams@oracle.com> writes:

>> Personally, I wish more packages would define their
>> faces in terms of inheritance from standard/built-in
>> faces. This would mean a user could tweak the built-in
>> faces to suit their preferences and the additional
>> packages would inherit those tweaks without needing
>> to be done individually.
>
> Personally, I wish fewer packages, and default
> Emacs itself, would define _fewer_ faces as
> inheriting from other, standard/built-in faces -
> in particular from font-lock faces.
> ___
>
> tl;dr:
> I expect that my opinion on this is a tiny minority
> one.  I express it anyway, hoping it might open one
> or two eyes or kindle a second thought here & there.
> ___
>
> _Users_ can always do what you say: customize faces
> to inherit from some face they want as parent.  And
> they can do that at multiple levels: inheritance
> hierarchy as deep or broad as you like - turtles
> all the way...).
> ___
>
> Font-lock faces, in particular, are defined to be
> appropriate, by default, for particular _purposes_
> (contexts) - e.g. comments.  Inheriting from them
> willy nilly for faces that have nothing to do with
> those purposes (e.g. non-code modes don't have
> comments) creates unnecessary coupling.
>
> The only face that has no specific purpose/context
> is face `default'.  And that's as it should be.
> In effect, all faces inherit from `default' (in
> addition to having their own particularities).
> ___
>
> Inheritance can be invisible at first sight, when
> trying to figure out why a face looks as it does.
>
> Inheriting by default is a bludgeon.  That blunt
> club is often touted as the _reason_ for built-in
> face inheritance by default:
>
>> without needing to be done individually
>
> A false problem, IMO.
>
> 1. Customizing a face _should_ in general be an
>    individual choice, taking _context_/purpose
>    into consideration.  (It's a similar decision
>    to that of defining its default appearance.)
>
> 2. Nothing prevents customizing a face to inherit
>    from another, including from standard/built-in
>    faces.  It's _not at all difficult_ to do.
> ___
>
> Inheriting by default has almost the same negative
> effect as defining a face to have, by default, the
> same appearance as face `default' (a practice that
> `emacs -Q' used to embrace, and perhaps still does
> here and there): You can't tell at a glance that
> there's a separate/different face there.
>
> Far better to use a different default appearance,
> even if perhaps "ugly", so that users immediately
> see that there's a separate face there that they
> can customize to their liking.
>
> The best way to introduce users to the fact that
> they can easily customize faces is to let faces
> stand out individually, by default.
> ___
>
> I don't mean that each face needs a different
> default definition.
>
> I mean only that, other things being equal,
> identical appearance works against recognizing
> the presence of a different face.
>
> What appearance to give a given face by default
> is always a judgment call.  I mean only to add
> this consideration to such a judgment, as one
> more consideration, perhaps too often overlooked
> in a zeal to concentrate face default appearance
> with predefined inheritance.
> ___
>
> One place _to_ perhaps use face inheritance by
> default is in a theme.
>
> And a library can similarly have some of its
> faces inherit from some of _its_ other faces -
> the `vc-*' faces inherit from `vc-state-base',
> for example (with the tradeoff mentioned above:
> lack of immediate recognition).  
>
> A priori, most other uses of predefined
> inheritance are  likely unwise/unhelpful, IMO. 

The big use case your argument overlooks is the one I'm forced to deal
with all the time. I have very specific requirements for face colours
because of a vision impairment. Emacs is a constant frustration for me
because of the number of faces which are defined. For example,
list-display-faces shows over 1030 faces on my system!

Without inheritance, this means I have to customise a majority of those
faces. I have also yet to find a theme which handles this well, though
the modus themes are pretty good and life has gotten better since all
the fine work put into those themes.

The issue of inheritance based on faces defined for a different purpose
is not a big issue and could be largely addressed by defining a good set
of 'base' faces with appropriate names. However, I find this a lesser
problem than the number of faces which are poorly defined and only work
well if you are running in a GUI frame or use a light theme or use a
terminal with 256 colour support etc. 

I also think the issue of inheritance causing problems because users
don't realise a face inherits from another face is overstated.
Inheritance is just another attribute in the face definition and is as
clear as any other attribute setting. Furthermore, if inheritance was
used more, users would become more aware of it and would deal with it
appropriately.

Having over 1000 separate face definitions seems insane at one level,
but I guess it does allow the ability for users to have ultimate
customisation. However, if we are going to have so many faces, there
really needs to be a mechanism which allows customisation which avoids
having to have 1000 set-face-* or a huge set custom face block in your
init file. This doesn't have to be via inheritance, but that seems to be
a workable solution until someone suggests something better.

I'm sure some will suggest the problem is due to too many packages
defining faces when not necessary. That may be true. However, I see lots
of people requesting distinct faces in many of the packages I follow, so
don't see that getting any better - in fact, I expect it will get worse
as more great useful packages are added to the Emacs ecosystem. 





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

* Re: Defaulting faces to inherit deemed harmful  [was: Stealing a default face from a non-ELPA package]
  2022-03-05 18:38 ` Tim Cross
@ 2022-03-05 19:40   ` Eli Zaretskii
  2022-03-05 22:27     ` Tim Cross
  2022-03-05 20:17   ` Drew Adams
  1 sibling, 1 reply; 6+ messages in thread
From: Eli Zaretskii @ 2022-03-05 19:40 UTC (permalink / raw)
  To: Tim Cross; +Cc: drew.adams, emacs-devel

> From: Tim Cross <theophilusx@gmail.com>
> Date: Sun, 06 Mar 2022 05:38:55 +1100
> Cc: emacs-devel <emacs-devel@gnu.org>
> 
> The big use case your argument overlooks is the one I'm forced to deal
> with all the time. I have very specific requirements for face colours
> because of a vision impairment. Emacs is a constant frustration for me
> because of the number of faces which are defined. For example,
> list-display-faces shows over 1030 faces on my system!
> 
> Without inheritance, this means I have to customise a majority of those
> faces.

I don't see how inheritance would have made your problem smaller.  Are
you assuming that the inheriting faces will never override the colors
of their parent face?  If they do define their own colors (and most
faces do), inheritance won't help you to change any significant part
of the faces in fewer steps than you need to do now.

> Having over 1000 separate face definitions seems insane at one level,
> but I guess it does allow the ability for users to have ultimate
> customisation. However, if we are going to have so many faces, there
> really needs to be a mechanism which allows customisation which avoids
> having to have 1000 set-face-* or a huge set custom face block in your
> init file. This doesn't have to be via inheritance, but that seems to be
> a workable solution until someone suggests something better.

I don't think I understand the problem for which you are looking for a
solution.  Would you please state it clearly?  Or at least could you
describe what kind of customizations of each and every face do you
have to do for your specific requirements?  Without a clear idea of
the problem you are facing (pun intended), it is hard to say anything
intelligent regarding possible solutions.



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

* RE: [External] : Re: Defaulting faces to inherit deemed harmful [was: Stealing a default face from a non-ELPA package]
  2022-03-05 18:38 ` Tim Cross
  2022-03-05 19:40   ` Eli Zaretskii
@ 2022-03-05 20:17   ` Drew Adams
  1 sibling, 0 replies; 6+ messages in thread
From: Drew Adams @ 2022-03-05 20:17 UTC (permalink / raw)
  To: Tim Cross; +Cc: emacs-devel

> The big use case your argument overlooks is the one I'm forced to deal
> with all the time. I have very specific requirements for face colours
> because of a vision impairment. Emacs is a constant frustration for me
> because of the number of faces which are defined. For example,
> list-display-faces shows over 1030 faces on my system!

Eli pointed out that faces that inherit can also set other
face attributes, specializing their the appearance and so
forcing you to customize them individually as well.

Beyond that important observation, I think that what
you (Tim) have said - which is useful & valid - is really
an argument for Customize to add the ability to quickly &
easily choose a selection of faces and apply a given
setting to all of them at once.

That's totally separate, conceptually - and potentially in
practice - from inheritance by default (i.e., predefined).

Telling Emacs to inherit each of a set of faces from some
face would then be a simple operation.

Likewise, doing that to define multiple inheritance levels,
using different face groups and different faces to inherit
from (including from faces that inherit from others etc.).

For the Customize UI to define such an operation to apply
a setting to a set of faces is a nice-to-have (but truly
welcome) addition.  But a first start would be to define
a command that does that.

The command could be general - any face attributes, not
just :inherit.  And multiple attributes at the same time.

It would need to let you (1) choose the faces to act on
(to set their attributes), (2) choose the attributes to
set, and (3) choose the new attribute values (e.g., for
attribute :inherit, choose which face to inherit from).

To choose multiple thingies, a command can loop over
minibuffer reads, or use `completing-read-multiple', or
use some completion framework that lets you easily
define a set of things using completion matching etc. 

With various completion/selection frameworks this would
be particularly easy to provide - and to use.  With
vanilla Emacs it might be a bit more cumbersome, but
something reasonable could be done.

> I'm sure some will suggest the problem is due to too 
> many packages defining faces when not necessary.

Not I.  Quite the contrary.  I wish more libraries
would consider defining more faces, for specific
uses/contexts.

E.g., my Info+ defines 26 faces; Bookmark+ defines 29;
Dired+ defines 28; Icicles defines 37.

> I see lots of people requesting distinct faces in many of
> the packages I follow, so don't see that getting any better
> - in fact, I expect it will get worse as more great useful
> packages are added to the Emacs ecosystem.

I'm not surprised.  And I don't see it as bad/worse but
good/normal/useful, in general.

If more faces are defined for more, finer-grained contexts,
a user can always coalesce any groups of them to look the
same (modulo the bother you raised in doing that, which I
addressed above).

But consider the other direction: If some library defines
only very coarse-grained highlighting, i.e., it doesn't
let you distinguish things on a fine scale, then you're
out of luck to move in a finer-grained direction.  Other
than resorting to Elisp and tweaking the library's use of
faces (e.g. its font-locking).

It's easier to lump existing distinctions than to split
them to provide more distinctions.  Much easier.



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

* Re: Defaulting faces to inherit deemed harmful  [was: Stealing a default face from a non-ELPA package]
  2022-03-05 19:40   ` Eli Zaretskii
@ 2022-03-05 22:27     ` Tim Cross
  2022-03-06  2:35       ` [External] : " Drew Adams
  0 siblings, 1 reply; 6+ messages in thread
From: Tim Cross @ 2022-03-05 22:27 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: drew.adams, emacs-devel


Eli Zaretskii <eliz@gnu.org> writes:

>> From: Tim Cross <theophilusx@gmail.com>
>> Date: Sun, 06 Mar 2022 05:38:55 +1100
>> Cc: emacs-devel <emacs-devel@gnu.org>
>> 
>> The big use case your argument overlooks is the one I'm forced to deal
>> with all the time. I have very specific requirements for face colours
>> because of a vision impairment. Emacs is a constant frustration for me
>> because of the number of faces which are defined. For example,
>> list-display-faces shows over 1030 faces on my system!
>> 
>> Without inheritance, this means I have to customise a majority of those
>> faces.
>
> I don't see how inheritance would have made your problem smaller.  Are
> you assuming that the inheriting faces will never override the colors
> of their parent face?  If they do define their own colors (and most
> faces do), inheritance won't help you to change any significant part
> of the faces in fewer steps than you need to do now.
>
>> Having over 1000 separate face definitions seems insane at one level,
>> but I guess it does allow the ability for users to have ultimate
>> customisation. However, if we are going to have so many faces, there
>> really needs to be a mechanism which allows customisation which avoids
>> having to have 1000 set-face-* or a huge set custom face block in your
>> init file. This doesn't have to be via inheritance, but that seems to be
>> a workable solution until someone suggests something better.
>
> I don't think I understand the problem for which you are looking for a
> solution.  Would you please state it clearly?  Or at least could you
> describe what kind of customizations of each and every face do you
> have to do for your specific requirements?  Without a clear idea of
> the problem you are facing (pun intended), it is hard to say anything
> intelligent regarding possible solutions.

Well I don't have a problem per se. I was mainly responding to Drew's
claim that defining faces to use inheritance was harmful.

My basic point is that I would prefer package authors use inheritance to
define the default value for new faces they add over the way too many
packages set the default value for faces they define. The issue is many
packages only do an extremely simplistic default face definition. For
example, just setting the foreground to a colour which looks good for
the theme they are using and not using the facilities available to set
the default based on whether the user is running in a GUI frame, inside
a terminal, on the GNU Linux console or whether they are using a dark or
light theme. I suspect this is because doing a proper default face
setting which works across different environments and light or dark
themes can be complex. If on the other hand, their default just inherits
from one of the built-in faces which typically do take these factors
into account, it would provide increased consistency and work out of the
box for more people.

So basically, my argument is EITHER define the face so that the default
works well regardless of whether the user is running in GUI, terminal,
console or a light/dark theme OR inherit from a built-in face, but don't
just make the default a simple :foreground "xxxx", which will only work
well if the user happens to use a similar environment and light or dark
theme as the author.

And yes, your correct that a face can be defined to inherit from another
face and also set the foreground or background and some do. However,
I've found that many don't and so setting the foreground/background of
the parent can provide good results and reduce the number of faces you
need to tweak individually. 



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

* RE: [External] : Re: Defaulting faces to inherit deemed harmful [was: Stealing a default face from a non-ELPA package]
  2022-03-05 22:27     ` Tim Cross
@ 2022-03-06  2:35       ` Drew Adams
  0 siblings, 0 replies; 6+ messages in thread
From: Drew Adams @ 2022-03-06  2:35 UTC (permalink / raw)
  To: Tim Cross, Eli Zaretskii; +Cc: emacs-devel@gnu.org

> Well I don't have a problem per se. I was mainly responding to Drew's
> claim that defining faces to use inheritance was harmful.

To be fair (in spite of the abbreviated and
tongue-in-cheek Subject line) what I really
suggested was _less predefining_ of faces
with inheritance.

I responded to your post saying you would
prefer that "_more_ packages would define
their faces in terms of inheritance from
standard/built-in faces."  Where you would
like more to do that, I'd like fewer to.

> The issue is many packages only do an extremely simplistic
> default face definition.

If "simplistic" means not imposing inheritance
by default, then good for them.  In general,
it's better not to couple a face's default
definition to another face's definition (for
the reasons I gave).

> For example, just setting the foreground to a colour which looks good for
> the theme they are using and not using the facilities available to set
> the default based on whether the user is running in a GUI frame, inside
> a terminal, on the GNU Linux console or whether they are using a dark
> or light theme.

That's something entirely different from 
whether to inject inheritance into a face's
default definition.

I happen to agree with everything in your last
paragraph.  It's just unrelated to whether it's
good or bad to define face X as inheriting from
face Y by default.

Except that of course any decision to inherit
from another face by default should involve
attention to the things you mention.  The same
attention should be paid when considering all
face attributes.

> I suspect this is because doing a proper default face
> setting which works across different environments and light or dark
> themes can be complex.

Yes, I think so.  The same problem exists for
defining the types of defcustoms.  Many, many
(most?) could stand to be refined a bit, to be
more useful.

> If on the other hand, their default just
> inherits from one of the built-in faces which typically do take 
> these factors into account, it would provide increased consistency

I suppose that's true.  But that's another
lazy way out - like what you decry - even if
it's more likely not to be flaky.

> So basically, my argument is EITHER define the face so that the default
> works well regardless of whether the user is running in GUI, terminal,
> console or a light/dark theme

Just leave it at that.  The message should be
to just take face attributes seriously when
defining defaults.  Including :inherit.

> don't just make the default a simple :foreground "xxxx", which will only work
> well if the user happens to use a similar environment and light or dark
> theme as the author.

It's really not that hard to choose a default
color for dark if you only use light, or vice
versa.

It's best of course to test/try both.  But even
just using a color complement for the opposite
`background-mode' can be pretty good.  (And it's
simple to obtain: `color-complement-hex'.)



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

end of thread, other threads:[~2022-03-06  2:35 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-05 16:46 Defaulting faces to inherit deemed harmful [was: Stealing a default face from a non-ELPA package] Drew Adams
2022-03-05 18:38 ` Tim Cross
2022-03-05 19:40   ` Eli Zaretskii
2022-03-05 22:27     ` Tim Cross
2022-03-06  2:35       ` [External] : " Drew Adams
2022-03-05 20:17   ` Drew Adams

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).