unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Eliminating a couple of independent face definitions
@ 2011-02-02  4:05 Chong Yidong
  2011-02-02  4:11 ` Lennart Borgman
                   ` (2 more replies)
  0 siblings, 3 replies; 43+ messages in thread
From: Chong Yidong @ 2011-02-02  4:05 UTC (permalink / raw)
  To: emacs-devel

It would be nice if almost all faces in packaged included with Emacs
inherit from the basic or font-lock faces.  Most faces already do this.
This way, users don't have to specify as much when they write a Custom
theme or their own personal face customizations.

I'd like to inherit-ize most of the remaining faces that don't already
do this.  For instance, compilation-warning is currently "Orange", and
compilation-info is "Green3"; I want to make them inherit from
font-lock-doc-face and font-lock comment-face respectively.  (The rest
of the compilation-mode already inherit from font-lock faces.)

There are a few more similar changes here and there.  Any objection?



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

* Re: Eliminating a couple of independent face definitions
  2011-02-02  4:05 Eliminating a couple of independent face definitions Chong Yidong
@ 2011-02-02  4:11 ` Lennart Borgman
  2011-02-02  5:02   ` Tim Cross
  2011-02-02 17:16   ` Chong Yidong
  2011-02-02  9:58 ` Štěpán Němec
  2011-02-02 10:05 ` Julien Danjou
  2 siblings, 2 replies; 43+ messages in thread
From: Lennart Borgman @ 2011-02-02  4:11 UTC (permalink / raw)
  To: Chong Yidong; +Cc: emacs-devel

On Wed, Feb 2, 2011 at 5:05 AM, Chong Yidong <cyd@stupidchicken.com> wrote:
> It would be nice if almost all faces in packaged included with Emacs
> inherit from the basic or font-lock faces.  Most faces already do this.
> This way, users don't have to specify as much when they write a Custom
> theme or their own personal face customizations.
>
> I'd like to inherit-ize most of the remaining faces that don't already
> do this.  For instance, compilation-warning is currently "Orange", and
> compilation-info is "Green3"; I want to make them inherit from
> font-lock-doc-face and font-lock comment-face respectively.  (The rest
> of the compilation-mode already inherit from font-lock faces.)
>
> There are a few more similar changes here and there.  Any objection?

Yes.

It is really good to try to merge some faces, but the specific merges
you mentioned seems a bit unfortunate. The colors were obviously
chosen to fit into those used in society for "ok" and "warning". Why
not create new faces for such things? (I do not think the font-lock
faces have the same meaning tighed to them, but maybe I am wrong
there.)



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

* Re: Eliminating a couple of independent face definitions
  2011-02-02  4:11 ` Lennart Borgman
@ 2011-02-02  5:02   ` Tim Cross
  2011-02-02 15:15     ` Drew Adams
  2011-02-02 17:17     ` Chong Yidong
  2011-02-02 17:16   ` Chong Yidong
  1 sibling, 2 replies; 43+ messages in thread
From: Tim Cross @ 2011-02-02  5:02 UTC (permalink / raw)
  To: Lennart Borgman; +Cc: Chong Yidong, emacs-devel

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

On Wed, Feb 2, 2011 at 3:11 PM, Lennart Borgman
<lennart.borgman@gmail.com>wrote:

> On Wed, Feb 2, 2011 at 5:05 AM, Chong Yidong <cyd@stupidchicken.com>
> wrote:
> > It would be nice if almost all faces in packaged included with Emacs
> > inherit from the basic or font-lock faces.  Most faces already do this.
> > This way, users don't have to specify as much when they write a Custom
> > theme or their own personal face customizations.
> >
> > I'd like to inherit-ize most of the remaining faces that don't already
> > do this.  For instance, compilation-warning is currently "Orange", and
> > compilation-info is "Green3"; I want to make them inherit from
> > font-lock-doc-face and font-lock comment-face respectively.  (The rest
> > of the compilation-mode already inherit from font-lock faces.)
> >
> > There are a few more similar changes here and there.  Any objection?
>
> Yes.
>
> It is really good to try to merge some faces, but the specific merges
> you mentioned seems a bit unfortunate. The colors were obviously
> chosen to fit into those used in society for "ok" and "warning". Why
> not create new faces for such things? (I do not think the font-lock
> faces have the same meaning tighed to them, but maybe I am wrong
> there.)
>
> I think the concept of using inherited faces so that all packages inherit
from a few well designed faces i.e. have appropriate definitions for
light/dark backgrounds, work on the console, in a terminal, under X, on
windows etc, is a good one. Having a few base faces to maintain in this way
would seem like a positive move and I agree it would make defining custom
themes easier. In fact, Ive recently been doing exactly this for VM
primarily because I thought it was better to use 'core' faces in that
package as they were more likely to be defined based on sound reasoning,
testing and feedback and would more likely be acceptable to a larger number
of users.

My only concern is how you define what to inherit from. For example, in your
suggestion of compiler warnings inheriting form  font-lock-comment-face I
immediately wondered why you would not inherit from font-lock-warning face?
It isn't clear to me what rationale would guide the decision as to what base
face to  inherit from. Without this, the choices could become rather
arbitrary and could make face customization or theme definition
even more difficult, resulting in apparently arbitrary use of font lock
properties (which may be OK, I don't know).

It would probably be sufficient to have a clear guideline or set of
recommendations which could be applied by developers when deciding on what
face to inherit from. However, this probably needs to be done prior to
changing definitions to use inherit. I would not expect to get it right or
even get consensus on the first go, but it could be refined and improved.
Developers may also be more likely to use :inherit if they feel there is
some guidance on what to inherit from.

Tim

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

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

* Re: Eliminating a couple of independent face definitions
  2011-02-02  4:05 Eliminating a couple of independent face definitions Chong Yidong
  2011-02-02  4:11 ` Lennart Borgman
@ 2011-02-02  9:58 ` Štěpán Němec
  2011-02-02 17:05   ` Chong Yidong
  2011-02-02 10:05 ` Julien Danjou
  2 siblings, 1 reply; 43+ messages in thread
From: Štěpán Němec @ 2011-02-02  9:58 UTC (permalink / raw)
  To: Chong Yidong; +Cc: emacs-devel

Chong Yidong <cyd@stupidchicken.com> writes:

> It would be nice if almost all faces in packaged included with Emacs
> inherit from the basic or font-lock faces.  Most faces already do this.
> This way, users don't have to specify as much when they write a Custom
> theme or their own personal face customizations.
>
> I'd like to inherit-ize most of the remaining faces that don't already
> do this.  For instance, compilation-warning is currently "Orange", and
> compilation-info is "Green3"; I want to make them inherit from
> font-lock-doc-face and font-lock comment-face respectively.  (The rest
> of the compilation-mode already inherit from font-lock faces.)
>
> There are a few more similar changes here and there.  Any objection?

Making two faces that were originally orange and green both orange(ish)
doesn't sound like a terribly good idea.

Similarly to my reaction to your similar proposal on the Gnus list -- I
don't think you can use the current very limited set of default font
lock faces for all the various faces out there (or "in there" in Emacs
core). Maybe you could introduce some more default faces to begin with,
from which the others could then more sensibly inherit?

  Štěpán



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

* Re: Eliminating a couple of independent face definitions
  2011-02-02  4:05 Eliminating a couple of independent face definitions Chong Yidong
  2011-02-02  4:11 ` Lennart Borgman
  2011-02-02  9:58 ` Štěpán Němec
@ 2011-02-02 10:05 ` Julien Danjou
  2 siblings, 0 replies; 43+ messages in thread
From: Julien Danjou @ 2011-02-02 10:05 UTC (permalink / raw)
  To: Chong Yidong; +Cc: emacs-devel

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

On Wed, Feb 02 2011, Chong Yidong wrote:

> There are a few more similar changes here and there.  Any objection?

I totally agree. I spend most of my theme in my Emacs theme file using
:inherit to redefine fonts rather than (re)specifying various (new) colors.

-- 
Julien Danjou
❱ http://julien.danjou.info

[-- Attachment #2: Type: application/pgp-signature, Size: 835 bytes --]

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

* RE: Eliminating a couple of independent face definitions
  2011-02-02  5:02   ` Tim Cross
@ 2011-02-02 15:15     ` Drew Adams
  2011-02-02 17:17     ` Chong Yidong
  1 sibling, 0 replies; 43+ messages in thread
From: Drew Adams @ 2011-02-02 15:15 UTC (permalink / raw)
  To: 'Tim Cross', 'Lennart Borgman'
  Cc: 'Chong Yidong', emacs-devel

I cannot really voice an objection.  I'd just point out that inheriting means
coupling (dependence).  The upside is of course the same as the downside: change
an ancestor and you change the descendents.  That might be what you want
sometimes, and it might not be what you want sometimes.  (Of course, inheritance
can be overridden/broken.)

FWIW, in my own use of faces I tend not to inherit too much.  Faces have
particular uses (contexts), and it is not that common that the use/purpose is
similar enough that inheritance is called for (in my usage, at least).

And I disagree with the general tendency here to avoid defining new faces (aka
the tendency to reuse faces defined for a different purpose).  Having two
different faces, even with the same attribute values, designed for two different
uses/purposes, makes sense in general.  It is not a great idea, in general, to
reuse a face just because you want the same color etc.

Similarly, I've disagreed with the practice of hard-coding `highlight' as the
`mouse-face' property (throughout the code).  In general, we should use either a
face variable or a new face for each such use, so that users can change the
behavior/appearance in different contexts (without redefining the hard-coded
code).




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

* Re: Eliminating a couple of independent face definitions
  2011-02-02  9:58 ` Štěpán Němec
@ 2011-02-02 17:05   ` Chong Yidong
  0 siblings, 0 replies; 43+ messages in thread
From: Chong Yidong @ 2011-02-02 17:05 UTC (permalink / raw)
  To: Štěpán Němec; +Cc: emacs-devel

Štěpán Němec <stepnem@gmail.com> writes:

> Making two faces that were originally orange and green both orange(ish)
> doesn't sound like a terribly good idea.

Fair enough.  So, let's make it font-lock-variable-name-face and
font-lock-type-face, which are orange and green by default.

> Similarly to my reaction to your similar proposal on the Gnus list -- I
> don't think you can use the current very limited set of default font
> lock faces for all the various faces out there (or "in there" in Emacs
> core). Maybe you could introduce some more default faces to begin with,
> from which the others could then more sensibly inherit?

The counterargument is that the majority of faces out there already do
inherit from font-lock and other basic faces.



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

* Re: Eliminating a couple of independent face definitions
  2011-02-02  4:11 ` Lennart Borgman
  2011-02-02  5:02   ` Tim Cross
@ 2011-02-02 17:16   ` Chong Yidong
  1 sibling, 0 replies; 43+ messages in thread
From: Chong Yidong @ 2011-02-02 17:16 UTC (permalink / raw)
  To: Lennart Borgman; +Cc: emacs-devel

Lennart Borgman <lennart.borgman@gmail.com> writes:

> It is really good to try to merge some faces, but the specific merges
> you mentioned seems a bit unfortunate.

Yes, the initial suggestion was not that good.  I think I was able to
sort things out satisfactorily.



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

* Re: Eliminating a couple of independent face definitions
  2011-02-02  5:02   ` Tim Cross
  2011-02-02 15:15     ` Drew Adams
@ 2011-02-02 17:17     ` Chong Yidong
  2011-02-02 20:33       ` Philipp Haselwarter
                         ` (2 more replies)
  1 sibling, 3 replies; 43+ messages in thread
From: Chong Yidong @ 2011-02-02 17:17 UTC (permalink / raw)
  To: Tim Cross; +Cc: Lennart Borgman, emacs-devel

Tim Cross <theophilusx@gmail.com> writes:

> My only concern is how you define what to inherit from. For example,
> in your suggestion of compiler warnings inheriting form
>  font-lock-comment-face I immediately wondered why you would not
> inherit from font-lock-warning face?

font-lock-warning-face is already used for compilation errors, which are
more serious than warnings.



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

* Re: Eliminating a couple of independent face definitions
  2011-02-02 17:17     ` Chong Yidong
@ 2011-02-02 20:33       ` Philipp Haselwarter
  2011-02-02 23:01         ` Lennart Borgman
  2011-02-03 19:10         ` Drew Adams
  2011-02-02 21:24       ` Eliminating a couple of independent face definitions Tim Cross
  2011-02-03 16:14       ` Dan Nicolaescu
  2 siblings, 2 replies; 43+ messages in thread
From: Philipp Haselwarter @ 2011-02-02 20:33 UTC (permalink / raw)
  To: emacs-devel

"CY" == Chong Yidong <cyd@stupidchicken.com> writes:

CY> Tim Cross <theophilusx@gmail.com> writes:

>> My only concern is how you define what to inherit from. For example,
>> in your suggestion of compiler warnings inheriting form
>>  font-lock-comment-face I immediately wondered why you would not
>> inherit from font-lock-warning face?

CY> font-lock-warning-face is already used for compilation errors, which
CY> are more serious than warnings.

Why not have a font-lock-warning face and a font-lock-error face?

I think some more reasonably named generic fonts to pick from would make
theming a lot easier.
As Drew said, faces need to make sense in their context.
I just spent some time picking sensible faces from the font-lock-*
palette for dired+, which by default defines its own static faces.
Most themes don't address these, resulting in readability issues.

I ended up with a nice looking setup, but the face names make no sense
*at all* in their context.
Some generic faces, that could guarantee some extend of contrast between
them would make consistency much easier.

-- 
Philipp Haselwarter




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

* Re: Eliminating a couple of independent face definitions
  2011-02-02 17:17     ` Chong Yidong
  2011-02-02 20:33       ` Philipp Haselwarter
@ 2011-02-02 21:24       ` Tim Cross
  2011-02-03 16:14       ` Dan Nicolaescu
  2 siblings, 0 replies; 43+ messages in thread
From: Tim Cross @ 2011-02-02 21:24 UTC (permalink / raw)
  To: Chong Yidong; +Cc: Lennart Borgman, emacs-devel

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

On Thu, Feb 3, 2011 at 4:17 AM, Chong Yidong <cyd@stupidchicken.com> wrote:

> Tim Cross <theophilusx@gmail.com> writes:
>
> > My only concern is how you define what to inherit from. For example,
> > in your suggestion of compiler warnings inheriting form
> >  font-lock-comment-face I immediately wondered why you would not
> > inherit from font-lock-warning face?
>
> font-lock-warning-face is already used for compilation errors, which are
> more serious than warnings.
>

OK, that makes it clearer. Maybe a different face than font-lock-comment as
comments are often coloured so as to be a little less noticeable, while
warnings are probably something you want to notice (but not as much as
errors!).

WRT Drew's comments. Some good points. However, to make my position clear, I
would not suggest that packages don't define their own faces, only that they
use inherit to define the default value the face has. Individual users then
have the option to change that individual face if desired.

As someone who has a vision impaired and has somewhat special requirements
for font properties and someone who has maintained packages that use a
number of faces, I know how hard it can be to select appropriate defaults. I
frequently find packages which have poor defaults or defaults which only
work for systems with a light/white background. Although faces have the
facility to be defined with multiple options depending on the display type
or background, it seems not many packages take advantage of this. My main
reason for supporting the notion of using inherit is that it could mean we
may have a set of well defined core faces that developers could use to
provide good defaults, but at the same time, leave the individual user with
the ability to modify if necessary. I prefer inherit over just using a
variable holding a face name as the user can modify things without having to
know what other faces to choose from (and knowing the face they choose is
always defined and not just defined at the time they use something like
list-display-faces to find an alternative).

Stephan has also raised important points. The existing set of 'standard'
faces is not extensive enough to meet all needs. Gnus is probably a good
example. You could not currently use inherit for all the gnus faces without
'doubling up' and losing some distinction between different faces. However,
I don't think the suggestion was to make *all* package faces use inherit -
but of course, if its not all, which ones will it be and how is that
determined?

I still think  making more use of inherit is a good idea. Stephan may be
right in that we could need a larger set of 'core' font-lock-* faces to make
this work and I still think we would need some guidelines/principals to help
developers know which would be the most appropriate face to inherit from.
Doing this would make it easier to maintain a set of well defined core faces
that would work well under all environments and give users a better initial
default experience while allowing maximum flexibility in individual
configuraiton with minimal knowledge.

Tim

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

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

* Re: Eliminating a couple of independent face definitions
  2011-02-02 20:33       ` Philipp Haselwarter
@ 2011-02-02 23:01         ` Lennart Borgman
  2011-02-03 19:10         ` Drew Adams
  1 sibling, 0 replies; 43+ messages in thread
From: Lennart Borgman @ 2011-02-02 23:01 UTC (permalink / raw)
  To: Philipp Haselwarter; +Cc: emacs-devel

On Wed, Feb 2, 2011 at 9:33 PM, Philipp Haselwarter
<philipp.haselwarter@gmx.de> wrote:
>
> Why not have a font-lock-warning face and a font-lock-error face?

+1

And I would also like to see some set of "state" faces, like "wait",
"ready", etc.



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

* Re: Eliminating a couple of independent face definitions
  2011-02-02 17:17     ` Chong Yidong
  2011-02-02 20:33       ` Philipp Haselwarter
  2011-02-02 21:24       ` Eliminating a couple of independent face definitions Tim Cross
@ 2011-02-03 16:14       ` Dan Nicolaescu
  2 siblings, 0 replies; 43+ messages in thread
From: Dan Nicolaescu @ 2011-02-03 16:14 UTC (permalink / raw)
  To: Chong Yidong; +Cc: Tim Cross, Lennart Borgman, emacs-devel

Chong Yidong <cyd@stupidchicken.com> writes:

> Tim Cross <theophilusx@gmail.com> writes:
>
>> My only concern is how you define what to inherit from. For example,
>> in your suggestion of compiler warnings inheriting form
>>  font-lock-comment-face I immediately wondered why you would not
>> inherit from font-lock-warning face?
>
> font-lock-warning-face is already used for compilation errors, which are
> more serious than warnings.

That is an annoyance.  It seems that adding a font-lock-error-face and
make all the current users of font-lock-warning-face use that one is the
right thing to do.

How about changing M-x list-faces-display to mark the faces that just
inherit from other faces with a special tag?
That way when people look to customize their theme it's easy to spot the
base faces.




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

* RE: Eliminating a couple of independent face definitions
  2011-02-02 20:33       ` Philipp Haselwarter
  2011-02-02 23:01         ` Lennart Borgman
@ 2011-02-03 19:10         ` Drew Adams
  2011-02-04  0:12           ` Tim Cross
                             ` (2 more replies)
  1 sibling, 3 replies; 43+ messages in thread
From: Drew Adams @ 2011-02-03 19:10 UTC (permalink / raw)
  To: 'Philipp Haselwarter', emacs-devel

> As Drew said, faces need to make sense in their context.
>
> I just spent some time picking sensible faces from the font-lock-*
> palette for dired+, which by default defines its own static faces.

That's my fault.  I defined the default Dired+ face colors only for light
backgrounds.  I DTRT for Icicles long ago, but I never got around to doing the
same for Dired+.

I've done that now, thanks to your reminder.  (However, I intentionally do not
use face inheritance - see below.)

FWIW, for this I simply use the complements of the light-background default
colors as the dark-background colors.  That is not necessarily ideal, but it at
least is reasonable and consistent.  It is also very quick to do, given some
code (e.g. hexrgb.el or palette.el) that quickly gives you color complements.

Such defaulting could presumably even be built-in (optionally).  For example, we
could allow a dark-background setting to be just a symbol `complement' or
`:complement', which would mean to pick up the `t' setting or the
light-background setting (if present) and use its complement.  Likewise for
light-background setting - whatever is defined would be used for the other
setting, as a complement.  That way a coder could provide a minimal face
definition and still get something reasonable for other background modes.

This could obviously be made more sophisticated, but any such feature could be
an improvement, helping with the problem of coders being lazy and just defining
defaults for one background mode (e.g. light in my case; that is, I designed for
light but defined it as `t', meaning all).

----

Wrt face inheritance -

Faces are customizable - they are just like user options.  In particular, faces
are _not colors_ and faces are _not constants_.  Color names and RGB hex codes
are essentially constants (even if they can appear slightly different on
different systems etc.).

IMO, it makes sense for a face B to inherit from another face A _only_ when what
is wanted is that customization of A automatically is reflected in B.  When
doing this, we should _always_ expect and assume that A will be customized by
users.  This is true no matter how "basic" A is.

This is why (IMO) it does _not_ make sense in general for faces to inherit from
font-lock faces.  A user will want to customize a font-lock face in order to
affect the appearance of _font-locking_, typically in code.  It does not
generally make sense for a non-font-lock face to automatically become affected
by such customization.  Example: basing a Dired face on a font-lock face would
be perverted (IMO).

My guess is that people who are thinking that inheritance from a few (or even
many) "basic" faces (font-lock or others) is a good idea are not taking
customization of such basic faces by users into account.  IOW, they are not
considering them as _faces_, but rather as constants (e.g. as colors or color
combos).

There would be nothing wrong with defining some _constants_ from which faces
could inherit - not defface but something else that indicates the intention of
not being customized.  Nothing wrong with coming up with such "basic faces" that
would never be customized.

But what would that mean?  In this case what is important is not the _usage_ of
the face (it cannot be; that cannot be known), but just its attributes: colors
etc.  IOW, instead of a basic face `highlight' intended for highlighting we
would have basic faces whose names reflect only their appearance:
`red-foreground-bold-boxed' etc.

But though there would be nothing wrong with defining such constant faces, it
would be truly silly.  There is no sense defining such attribute combinations -
no sense defining (uncustomizable) faces for this.  We already have such
constants: the colors themselves (names and #RGB hex codes).  And numbers for
weights etc.  Defining combinations as constants makes little sense.

It is proper to base defface definitions on such constants, but not (in general)
on other faces.  The only time the latter is appropriate (IMO) is when we really
want customizing face A to affect face B which inherits from A.  You do not, I
think, want a Dired face to change just because a user tweaks a font-lock face
to make code comments stand out differently.

The real problem that I'm guessing motivates the (misguided) attempts to base
faces upon each other is that too often the default values of faces are not
defined well enough (see the Dired+ mea culpa above).  Too often too little
effort is devoted to defining the default attributes.

The other problem that has been mentioned is being able to apply different
themes and have the result be more or less reasonable across sets of faces.  I
think that this is not a fundamental problem but is only derivative from not
having good defaults.  Just having reasonable default values that cover both
light and dark backgrounds will go a long way toward eliminating this problem, I
expect.

In addition, tools that let users easily change whole sets of faces together,
incrementally, can help.  Do Re Mi offers some help in this way, and other such
tools can be envisaged.

Example: command `doremi-all-faces-fg+' lets you incrementally modify all face
foregrounds at once (hue, saturation, brightness, red, green, and/or blue).
Obviously such a command is limited, but in combination with others it can be a
real help for customizing - and even for defining themes.

I'd be interested in hearing more arguments in favor of faces inheriting from
faces (e.g. "basic" faces).  So far it all seems misguided to me, but perhaps
I'm missing a thing or two.  Please be clear about (a) the _problems_ you are
trying to solve this way, and (b) _how_ you think face inheritance can solve
them.




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

* Re: Eliminating a couple of independent face definitions
  2011-02-03 19:10         ` Drew Adams
@ 2011-02-04  0:12           ` Tim Cross
  2011-02-05 22:11             ` Drew Adams
  2011-02-04  0:18           ` Stephen J. Turnbull
  2011-02-04 10:26           ` Julien Danjou
  2 siblings, 1 reply; 43+ messages in thread
From: Tim Cross @ 2011-02-04  0:12 UTC (permalink / raw)
  To: Drew Adams; +Cc: emacs-devel, Philipp Haselwarter

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

On Fri, Feb 4, 2011 at 6:10 AM, Drew Adams <drew.adams@oracle.com> wrote:

> > As Drew said, faces need to make sense in their context.
> >
> > I just spent some time picking sensible faces from the font-lock-*
> > palette for dired+, which by default defines its own static faces.
>
> That's my fault.  I defined the default Dired+ face colors only for light
> backgrounds.  I DTRT for Icicles long ago, but I never got around to doing
> the
> same for Dired+.
>
> I've done that now, thanks to your reminder.  (However, I intentionally do
> not
> use face inheritance - see below.)
>
> FWIW, for this I simply use the complements of the light-background default
> colors as the dark-background colors.  That is not necessarily ideal, but
> it at
> least is reasonable and consistent.  It is also very quick to do, given
> some
> code (e.g. hexrgb.el or palette.el) that quickly gives you color
> complements.
>
> Such defaulting could presumably even be built-in (optionally).  For
> example, we
> could allow a dark-background setting to be just a symbol `complement' or
> `:complement', which would mean to pick up the `t' setting or the
> light-background setting (if present) and use its complement.  Likewise for
> light-background setting - whatever is defined would be used for the other
> setting, as a complement.  That way a coder could provide a minimal face
> definition and still get something reasonable for other background modes.
>
> This could obviously be made more sophisticated, but any such feature could
> be
> an improvement, helping with the problem of coders being lazy and just
> defining
> defaults for one background mode (e.g. light in my case; that is, I
> designed for
> light but defined it as `t', meaning all).
>
> ----
>
> Wrt face inheritance -
>
> Faces are customizable - they are just like user options.  In particular,
> faces
> are _not colors_ and faces are _not constants_.  Color names and RGB hex
> codes
> are essentially constants (even if they can appear slightly different on
> different systems etc.).
>
> IMO, it makes sense for a face B to inherit from another face A _only_ when
> what
> is wanted is that customization of A automatically is reflected in B.  When
> doing this, we should _always_ expect and assume that A will be customized
> by
> users.  This is true no matter how "basic" A is.
>
> This is why (IMO) it does _not_ make sense in general for faces to inherit
> from
> font-lock faces.  A user will want to customize a font-lock face in order
> to
> affect the appearance of _font-locking_, typically in code.  It does not
> generally make sense for a non-font-lock face to automatically become
> affected
> by such customization.  Example: basing a Dired face on a font-lock face
> would
> be perverted (IMO).
>
> My guess is that people who are thinking that inheritance from a few (or
> even
> many) "basic" faces (font-lock or others) is a good idea are not taking
> customization of such basic faces by users into account.  IOW, they are not
> considering them as _faces_, but rather as constants (e.g. as colors or
> color
> combos).
>
> There would be nothing wrong with defining some _constants_ from which
> faces
> could inherit - not defface but something else that indicates the intention
> of
> not being customized.  Nothing wrong with coming up with such "basic faces"
> that
> would never be customized.
>
> But what would that mean?  In this case what is important is not the
> _usage_ of
> the face (it cannot be; that cannot be known), but just its attributes:
> colors
> etc.  IOW, instead of a basic face `highlight' intended for highlighting we
> would have basic faces whose names reflect only their appearance:
> `red-foreground-bold-boxed' etc.
>
> But though there would be nothing wrong with defining such constant faces,
> it
> would be truly silly.  There is no sense defining such attribute
> combinations -
> no sense defining (uncustomizable) faces for this.  We already have such
> constants: the colors themselves (names and #RGB hex codes).  And numbers
> for
> weights etc.  Defining combinations as constants makes little sense.
>
> It is proper to base defface definitions on such constants, but not (in
> general)
> on other faces.  The only time the latter is appropriate (IMO) is when we
> really
> want customizing face A to affect face B which inherits from A.  You do
> not, I
> think, want a Dired face to change just because a user tweaks a font-lock
> face
> to make code comments stand out differently.
>
> The real problem that I'm guessing motivates the (misguided) attempts to
> base
> faces upon each other is that too often the default values of faces are not
> defined well enough (see the Dired+ mea culpa above).  Too often too little
> effort is devoted to defining the default attributes.
>
> The other problem that has been mentioned is being able to apply different
> themes and have the result be more or less reasonable across sets of faces.
>  I
> think that this is not a fundamental problem but is only derivative from
> not
> having good defaults.  Just having reasonable default values that cover
> both
> light and dark backgrounds will go a long way toward eliminating this
> problem, I
> expect.
>
> In addition, tools that let users easily change whole sets of faces
> together,
> incrementally, can help.  Do Re Mi offers some help in this way, and other
> such
> tools can be envisaged.
>
> Example: command `doremi-all-faces-fg+' lets you incrementally modify all
> face
> foregrounds at once (hue, saturation, brightness, red, green, and/or blue).
> Obviously such a command is limited, but in combination with others it can
> be a
> real help for customizing - and even for defining themes.
>
> I'd be interested in hearing more arguments in favor of faces inheriting
> from
> faces (e.g. "basic" faces).  So far it all seems misguided to me, but
> perhaps
> I'm missing a thing or two.  Please be clear about (a) the _problems_ you
> are
> trying to solve this way, and (b) _how_ you think face inheritance can
> solve
> them.
>
> OK, I'll have a go....

While I appreciate your point of concern regarding the fact inheritance
would 'link' faces with little or no apparent connection to each other ,
possibly resulting in 'odd' results when a user customizes a face, I
disagree with most of your assumptions and resulting conclusions regarding
motivation.  I am also not convinced that this is a true problem or one of
any significant issue. Likewise, while I can understand the argument that
the relationship between faces should be based on some obvious/clear
relationship, I'm not sure this is a real issue in practice or if it is, it
is more a curiosity rather than a problem i.e. wow, that seems like a
strange face to inherit from, but not something anyone would spend hours
trying to understand.

One thing I would recommend doing, if possible, would be to spend some time
running emacs with a dark background and on a tty. This would likely reveal
how bad some default face definitions are and let you see how tedious it is
having to customize lots of individual face definitions just to get ones
that work.

As I see it, we want to achieve four main goals. We want to make it easier
for developers to set appropriate defaults, we want to get the best default
possible for end users, regardless of platform or light/dark background
preferences, we want to make it as easy as possible for end users to
customize their environment and we want to, if possible, avoid a
proliferation of different face definitions, especially when the definitions
don't really differ in anything other than name as this makes customizing
and theme definition more complex than it needs to be. For all environments,
there are a fairly limited set of possible usable face definitions and it
would be good if we could have something which allows maximum flexibility,
but minimum maintenance and easy customization.

It was good you pointed out that faces are not just about colour. Sometimes,
I think peopoe forget this and only focus on the colour aspect. However,
this is understandable as colour is what distinguishes most faces from each
other.

We need to acknowledge how difficult it is to define good default faces.
Many definitions fail to do this. While your suggestion of using colour
compliments can help, I'm not convinced it is always that easy. One problem
is that different environments have different sets of colours to work with.
For example, if you work under the linux console, you don't have compliments
for most of the colours available under other environments, such as X or (I
presume) Windows/Mac. The problem is further complicated because most
developers won't have access to many of these environments, so can't easil
test and design appropriate faces even if motivated to do so.

I would not argue that inheritance is an ideal solution to this problem,
However, I do think it can be part of the solution. Perhaps something along
the lines of

 * Establish guidelines on how to use inheritance i.e. how to select which
face to inherit from
 * Define a good (not too large) set of base faces. Existing font-lock faces
may be sufficient, maybe not. Would need review.
 * Require all face definitions in core emacs packages to either fully
define a face (i.e. definition for dark/light, tty, X mac ms etc) OR inherit
from a base face (assuming all base faces are fully defined)
 * Add a section to the manual encouraging developers to either provide a
fully defined face or inherit from a base face, but don't just define a
single (usually) light background face

The key here is that all faces in core emacs packages would end up with a
fully defined face, either explicitly or via inherit.

One of the reasons I like the use of inherit for face definitions is mainly
from an end user perspective. I would rather have faces that are fully
defined via inherit, even if that inheritance seems odd, than have a
partially defined face which only works if you have a light background or
are running under a full gui environment. If, when I change the base face
definition, it results in unacceptable changes to some face which inherits
from it, I can customize it. My experience has been that this does sometimes
happen, but not that often and it is more preferable to fix up the few faces
than to spend much more time configuring lots of individual faces. In fact,
as the number of individual face definitions has increased, I actaully think
we have gone the wrong direction. We have too many faces which are mostly
the same. It seems now that every new package is adding its own face
definitions and many of them are poorly defined. It now takes much longer
for me to establish a consistent set of faces.

If we required face definitions to either be fully defined or inherited from
a base set that are fully defined, we would likely give a much better
default experience to end users. Using inheritance also means that when we
find a face definition which is poor for a particular environment, we can
refine that base definition rather than having to find all similarly poor
definitions and updating them individually.

Using inheritance means that it is easier to make broad changes to face
definitions, reducing the time spent in customize and lets you then tweak
those specific faces which don't quite work. So, using your example, if
someone changed the base face that dired+ uses, either they will find the
result in dired+ acceptable or they can then tweak that face further. The
alternative is that it would be necessary to customize both faces, even when
you are going to set them to the same value. The reality is that there are a
limited set of good faces and you will usually end up with the same face
definition being used in multiple roles. Frequently, those roles have
nothing to do with each other. This doesn't matter as the contexts are
completely different. From an end user perspective, it is irrelevant that
compiler messages inherit from font-lock-string - all the end user sees is
that compiler messages use a default face that is green, which may be
exactly the same as strings in their code, but so what.

Of course, much of this may become less of an issue now that emacs has
support for themes. though there isn't yet any environment specific themes
i.e tty, terminal etc.

Tim

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

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

* RE: Eliminating a couple of independent face definitions
  2011-02-03 19:10         ` Drew Adams
  2011-02-04  0:12           ` Tim Cross
@ 2011-02-04  0:18           ` Stephen J. Turnbull
  2011-02-04  3:55             ` John Yates
                               ` (2 more replies)
  2011-02-04 10:26           ` Julien Danjou
  2 siblings, 3 replies; 43+ messages in thread
From: Stephen J. Turnbull @ 2011-02-04  0:18 UTC (permalink / raw)
  To: Drew Adams; +Cc: emacs-devel, 'Philipp Haselwarter'

Drew Adams writes:
 > Example: command `doremi-all-faces-fg+' lets you incrementally
 > modify all face foregrounds at once (hue, saturation, brightness,
 > red, green, and/or blue).  Obviously such a command is limited, but
 > in combination with others it can be a real help for customizing -

Sure, it's a help with customization, but it does not address the
basic problem.

 > I'd be interested in hearing more arguments in favor of faces inheriting from
 > faces (e.g. "basic" faces).

The basic problem is that faces are not colors.  Faces are not fonts.
(Where have I heard this before? ;-)  A face is a semantic component,
intended to express meaning.  Common meanings should have a common
expression.  Thus, for text modes there should be an "emphasis" face,
and of course a "bogus whitespace" face for us pedants.  In
programming modes, "identifier" and "keyword" are common semantics.
In compile modes, "info", "file", "position" (usually line number),
"function", "error", and "warning" are common semantics.  In shell
modes, several levels of "prompt".  Electric modes may want a "paren
flash" face.  Search modes a "hit" face and a "secondary hit" face.

For many simple modes, such basic faces will be enough, and used as
is.  However, modes of medium complexity may want to inherit in order
to allow customization of that mode without affecting others,
especially modes with lots of faces where customization of one face
may collide with the basic definition of another, and the user prefers
to change the second face in the mode where it collides but not
elsewhere.  This has happened to me occasionally, though by now most
of my customizations are inches thick in moss.

It might also be useful to have semantically derived faces, so that
"strong emphasis" (introduced to support markup modes like HTML) would
derive from "emphasis" (but this is speculative).  On the same theme,
"keyword" might derive from "identifier".



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

* Re: Eliminating a couple of independent face definitions
  2011-02-04  0:18           ` Stephen J. Turnbull
@ 2011-02-04  3:55             ` John Yates
  2011-02-04  4:56               ` Stephen J. Turnbull
  2011-02-04  4:57             ` Jambunathan K
  2011-02-05 22:09             ` Drew Adams
  2 siblings, 1 reply; 43+ messages in thread
From: John Yates @ 2011-02-04  3:55 UTC (permalink / raw)
  To: Stephen J. Turnbull; +Cc: Philipp Haselwarter, Drew Adams, emacs-devel

On Thu, Feb 3, 2011 at 7:18 PM, Stephen J. Turnbull <stephen@xemacs.org> wrote:

> The basic problem is that faces are not colors.  Faces are not fonts.
> (Where have I heard this before? ;-)  A face is a semantic component,
> intended to express meaning.  Common meanings should have a common
> expression.

Your argument assumes that users internalize strong associations from
the visuals of a face to very specific semantics.   Further you assume
that users expect faces to be reused consistently across modes based
on conformance to clear semantic models.  A corollary is that
introduction of a new semantic notion not only requires introduction a
new face but also requires that it be visually distinct.

Put another way you expect users to be conscious of distinct faces and
their detailed semantics.  My personal experience contracts that
picture.  I really have only two criteria on which I asses a set of
faces (either out of the box or as I tweak):

1) does the choice of visual (d)emphasis make sense?  are fundamental
structural elements easy to identify and follow? are points that
require my attention appropriately easy to recognize?  are less
important elements easy to skim/skip?

2) is the overall effect pleasing or jarring?  is there unity and
consistency in the use of colors and weights?  (often when first
experimenting with a new mode I feel that once again I am waging my
eternal battle against emacs "fruit salad")

So my mental association is not with any specific semantics of a
particular face but only with the extent to which, within a given
theme, it conveys visual emphasis or lack thereof.  An important
consequence is that I feel no great need to convey every new semantic
via a new, visually distinct face.

/john



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

* Re: Eliminating a couple of independent face definitions
  2011-02-04  3:55             ` John Yates
@ 2011-02-04  4:56               ` Stephen J. Turnbull
  0 siblings, 0 replies; 43+ messages in thread
From: Stephen J. Turnbull @ 2011-02-04  4:56 UTC (permalink / raw)
  To: John Yates; +Cc: emacs-devel, Drew Adams, Philipp Haselwarter

John Yates writes:
 > On Thu, Feb 3, 2011 at 7:18 PM, Stephen J. Turnbull <stephen@xemacs.org> wrote:
 > 
 > > The basic problem is that faces are not colors.  Faces are not fonts.
 > > (Where have I heard this before? ;-)  A face is a semantic component,
 > > intended to express meaning.  Common meanings should have a common
 > > expression.
 > 
 > Your argument assumes that users internalize strong associations from
 > the visuals of a face to very specific semantics.

No, it doesn't.  It simply assumes enough association will carry
over.  Use of bold and italic for emphasis in text modes is very
common.  Use of red for errors is very common.  I'm not saying that
*all* faces should be derived from some base set, but Drew (and now
you) seem to be saying that derivation from a base set is useless.
The law of the excluded middle does not apply to all vs. none, you
know.

 > Further you assume that users expect faces to be reused
 > consistently across modes based on conformance to clear semantic
 > models.

Nope, you're projecting.  Of course (Emacs) users *don't* expect that,
because Emacs currently *doesn't* do it.

 > A corollary is that introduction of a new semantic notion not only
 > requires introduction a new face but also requires that it be
 > visually distinct.

I'm not sure that follows from your assumptions, but in any case I
neither accept them nor believe them necessary, so that is not a
consequence of advocating a base set of faces.

 > 
 > Put another way you expect users to be conscious of distinct faces and
 > their detailed semantics.

 > My personal experience contracts that picture.

Well, of course it does!  Emacs is very useful to you, and currently
fails to provide consistent faces, so you conclude that consistent
faces are unnecessary.  No big surprise there!

 > 2) is the overall effect pleasing or jarring?  is there unity and
 > consistency in the use of colors and weights?  (often when first
 > experimenting with a new mode I feel that once again I am waging my
 > eternal battle against emacs "fruit salad")

Now there's a strong argument for derivation.  *If* those faces that
can be derived *were* derived, then you could fix up the base faces
(even resetting some that you think are stupid to `default' so they
don't show up at all or whatever), and use doremi to tone down the
rest, perhaps.

 > theme, it conveys visual emphasis or lack thereof.  An important
 > consequence is that I feel no great need to convey every new semantic
 > via a new, visually distinct face.

Would it really annoy you if Emacs had pleasing faces, but dammit,
they're way too consistent? ;-)



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

* Re: Eliminating a couple of independent face definitions
  2011-02-04  0:18           ` Stephen J. Turnbull
  2011-02-04  3:55             ` John Yates
@ 2011-02-04  4:57             ` Jambunathan K
  2011-02-05 22:09             ` Drew Adams
  2 siblings, 0 replies; 43+ messages in thread
From: Jambunathan K @ 2011-02-04  4:57 UTC (permalink / raw)
  To: emacs-devel

"Stephen J. Turnbull" <stephen@xemacs.org> writes:

> The basic problem is that faces are not colors.  Faces are not fonts.
> (Where have I heard this before? ;-)  A face is a semantic component,
> intended to express meaning.  Common meanings should have a common
> expression.  Thus, for text modes there should be an "emphasis" face,
> and of course a "bogus whitespace" face for us pedants.  In
> programming modes, "identifier" and "keyword" are common semantics.
> In compile modes, "info", "file", "position" (usually line number),
> "function", "error", and "warning" are common semantics.  In shell
> modes, several levels of "prompt".  Electric modes may want a "paren
> flash" face.  Search modes a "hit" face and a "secondary hit" face.

Orgmode has it's own set of semantic elements (may I say, broadly
relating to scheduling and task & information management) - todo states,
timestamps, tags ...

Jambunathan K.



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

* Re: Eliminating a couple of independent face definitions
  2011-02-03 19:10         ` Drew Adams
  2011-02-04  0:12           ` Tim Cross
  2011-02-04  0:18           ` Stephen J. Turnbull
@ 2011-02-04 10:26           ` Julien Danjou
  2011-02-04 17:57             ` color-complement for defface (was: Eliminating a couple of independent face definitions) Ted Zlatanov
  2 siblings, 1 reply; 43+ messages in thread
From: Julien Danjou @ 2011-02-04 10:26 UTC (permalink / raw)
  To: Drew Adams; +Cc: emacs-devel, 'Philipp Haselwarter'

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

On Thu, Feb 03 2011, Drew Adams wrote:

> FWIW, for this I simply use the complements of the light-background default
> colors as the dark-background colors.  That is not necessarily ideal, but it at
> least is reasonable and consistent.  It is also very quick to do, given some
> code (e.g. hexrgb.el or palette.el) that quickly gives you color complements.

color.el included in Emacs 24 as `color-complement' so you can even use
it in your defface directly, I think.

-- 
Julien Danjou
❱ http://julien.danjou.info

[-- Attachment #2: Type: application/pgp-signature, Size: 835 bytes --]

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

* color-complement for defface (was: Eliminating a couple of independent face definitions)
  2011-02-04 10:26           ` Julien Danjou
@ 2011-02-04 17:57             ` Ted Zlatanov
  2011-02-14 18:11               ` color-complement for defface Ted Zlatanov
  0 siblings, 1 reply; 43+ messages in thread
From: Ted Zlatanov @ 2011-02-04 17:57 UTC (permalink / raw)
  To: emacs-devel

On Fri, 04 Feb 2011 11:26:49 +0100 Julien Danjou <julien@danjou.info> wrote: 

JD> On Thu, Feb 03 2011, Drew Adams wrote:
>> FWIW, for this I simply use the complements of the light-background default
>> colors as the dark-background colors.  That is not necessarily ideal, but it at
>> least is reasonable and consistent.  It is also very quick to do, given some
>> code (e.g. hexrgb.el or palette.el) that quickly gives you color complements.

JD> color.el included in Emacs 24 as `color-complement' so you can even use
JD> it in your defface directly, I think.

It would be nice if an example of that usage was part of the manual.
Even better would be if defining a face could automatically use the
complement (e.g. by setting the background to 'complement).

Julien, do you want to propose a patch to the manual?

Does anyone have comments on a defface modification to let
color-complement pick the background automatically if requested?  I
don't know how hard that would be to write, but I want to know if it's
even acceptable.

Thanks
Ted




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

* RE: Eliminating a couple of independent face definitions
  2011-02-04  0:18           ` Stephen J. Turnbull
  2011-02-04  3:55             ` John Yates
  2011-02-04  4:57             ` Jambunathan K
@ 2011-02-05 22:09             ` Drew Adams
  2011-02-06  7:11               ` Stephen J. Turnbull
  2 siblings, 1 reply; 43+ messages in thread
From: Drew Adams @ 2011-02-05 22:09 UTC (permalink / raw)
  To: 'Stephen J. Turnbull'; +Cc: emacs-devel, 'Philipp Haselwarter'

S> I'm not saying that *all* faces should be derived from some
S> base set, but Drew (and now you) seem to be saying that
S> derivation from a base set is useless.  The law of the
S> excluded middle does not apply to all vs. none, you know.
 
You are not saying *all*.  And I am not saying *none* (or all
vs none).  Please drop the bugaboo strawman, Stephen.  As a
matter of fact your argument repeats mine; it does not counter
it.

S> The basic problem is that faces are not colors.  Faces are
S> not fonts. (Where have I heard this before? ;-)  A face is
S> a semantic component, intended to express meaning.
S> Common meanings should have a common expression.

d> Inheritance should be based on similarity (preferably set
d> inclusion) of use (usage, use case, purpose), not just on
d> similarity of face attributes.

You used the word "semantic".  Good.  I might well have
included that word in the parens.  We both draw the same
distinction between a face as only a combination of appearance
attributes (no) and a face as having a purpose/meaning for
particular contexts (yes).

It is essentialy the same distinction that is made between
physical markup and logical markup - between `italic' and
`emphasis', for instance.

We have both said that inheritance should, in general, be used
for logical/usage/semantic entities, and *not* simply for
combinations of attributes (physical/appearance).  In my
words:

d> A new face should not inherit from face `region' just because
d> its default attributes are the same as the default attributes
d> of face `region', for example.

The idea that inheritance should be based on similarity of
usage/purpose/semantics rather than just similarity of value
(e.g. color, size) implies that it is a mistake to have faces
that are unrelated to font-locking be based on font-lock
faces.

A face whose purpose has something to do with comments could
be based on `font-lock-comment-face', but a face such as
`region' or `minibuffer-prompt' should probably not be based
on it - there is too little logical/semantical/usage
connection.

Why does this matter?  Coupling.  Unwanted side effects for a
descendent when you customize its ancestor.

d> IMO, it makes sense for a face B to inherit from another face
d> A _only_ when what is wanted is that customization of A
d> automatically is reflected in B.  When doing this, we should
d> _always_ expect and assume that A will be customized by users.
d> This is true no matter how "basic" A is.
d> 
d> This is why (IMO) it does _not_ make sense in general for
d> [all] faces to inherit from font-lock faces.


S> Thus, for text modes there should be an "emphasis" face, and
S> of course a "bogus whitespace" face for us pedants.  In
S> programming modes, "identifier" and "keyword" are common
S> semantics.  In compile modes, "info", "file", "position"
S> (usually line number), "function", "error", and "warning" are
S> common semantics.  In shell modes, several levels of "prompt".
S> Electric modes may want a "paren flash" face.  Search modes a
S> "hit" face and a "secondary hit" face.

Again you support what I said.  The important thing here is
that you have grouped faces into contexts, groups based on
usage/meaning.  (Whether or not those particular groups are
the best choices is beside the point.)

The point is that inheritance makes sense within such a group
(e.g., levels of prompt), and it makes a lot less sense (if
any) across unrelated groups (e.g. prompt, search hit, and
emphasis).

How did this discussion start?  Yidong seemed to be saying
(possible misinterpretation, admittedly) that it would be good
to get rid of duplicate face definitions, by which he
apparently meant faces that have different names but the same
attribute values.

That is the issue.  I argued that that would be misguided.
Such faces typically are *not* duplicates.  A face expresses
meaning (a usage and context); it is not identical to its
appearance.  You put it this way:

S> A face is a semantic component, intended to express meaning.
S> Common meanings should have a common expression.

I went a bit further and said that, in general, _only_ common
meanings or use patterns should have a common expression.

I have nothing against the examples of inheritance that you
argued for.  They are they same kinds of inheritance that I
argued for.  What I think is misguided is trying to boil
things down across meaning groups (usage contexts) based on
only equality of default attribute values.  That's the issue.

Looking for duplication of face definitions, and thus possible
candidates for inheritance (factoring), should not be based on
looking at their default attribute values.

It should be based on what the faces represent, what they do,
what they mean, how they are intended to be used.  When
duplicates of that kind are found, then yes, we can consider
factoring out the duplication by using inheritance.




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

* RE: Eliminating a couple of independent face definitions
  2011-02-04  0:12           ` Tim Cross
@ 2011-02-05 22:11             ` Drew Adams
  2011-02-07  0:59               ` Drew Adams
  2011-02-07  1:08               ` Tim Cross
  0 siblings, 2 replies; 43+ messages in thread
From: Drew Adams @ 2011-02-05 22:11 UTC (permalink / raw)
  To: 'Tim Cross'; +Cc: emacs-devel, 'Philipp Haselwarter'

T> One thing I would recommend doing, if possible, would be to
T> spend some time running emacs with a dark background and on a
T> tty.  This would likely reveal how bad some default face
T> definitions are and let you see how tedious it is having to
T> customize lots of individual face definitions just to get ones
T> that work.
 
I'm not sure what your disagreements are with what I said.  I
agree that poorly defined default face definitions are a real
problem.  I even suggested that they are likely _the_ real
problem here.
 
Given reasonable face defaults that work out of the box on
both dark and light backgrounds, I think many if not most
(perhaps all?) of the problems you cited go away.  With faces
that just work by default, regardless of the background, there
is no need to "customize lots of individual face definitions
just to get ones that work".
 
T> As I see it, we want to achieve four main goals. We want to
T> make it easier for developers to set appropriate defaults, we
T> want to get the best default possible for end users,
T> regardless of platform or light/dark background preferences,
T> we want to make it as easy as possible for end users to
T> customize their environment
 
Agree.
 
T> and we want to, if possible, avoid a proliferation of
T> different face definitions, especially when the definitions
T> don't really differ in anything other than name as this makes
T> customizing and theme definition more complex than it needs to
T> be.
 
Disagree, if by "don't really differ in anything other than
the name" you are referring only to the `defface' default
attribute values.
 
I am in favor of there being two faces instead of one, if
their use/meaning is different, even if their definitions
modulo the names are identical.  In particular, this
facilitates separate customization.
 
It avoids coupling that is not logical and not necessary.
Inheritance (hence coupling) based on physical attributes
(appearance) can perhaps occasionally be appropriate, but in
general it is a no-no.
 
(Names are generally indicative of meaning, but yes, there
could be two faces with different names yet identical meaning.
In that case, yes, the duplication could be eliminated.)
 
(There is an orthogonal reason to avoid using too many faces
at the same time: performance.  But that is a different story
altogether.)
 
T> It was good you pointed out that faces are not just about
T> colour.  Sometimes, I think peopoe forget this and only focus
T> on the colour aspect.  However, this is understandable as
T> colour is what distinguishes most faces from each other.
T> 
T> We need to acknowledge how difficult it is to define good
T> default faces.  Many definitions fail to do this.  While your
T> suggestion of using colour compliments can help, I'm not
T> convinced it is always that easy.  One problem is that
T> different environments have different sets of colours to work
T> with.  For example, if you work under the linux console, you
T> don't have compliments for most of the colours available under
T> other environments, such as X or (I presume) Windows/Mac.  The
T> problem is further complicated because most developers won't
T> have access to many of these environments, so can't easil test
T> and design appropriate faces even if motivated to do so. 
 
Agree.  I did not mean to raise complementing as any kind of
cure-all - far from it.  I was just mentioning that I provided
a quick-and-dirty set of default settings for dark backgrounds
for a particular library by flipping the light-background
defaults to their complements.  Obviously, any set of defaults
for either light or dark deserves to be well thought out.  And
all of the considerations you mention should be taken into
account.
 
The tty thing is a big limitation, in particular.  Designing a
set of faces for use on tty only is a different task from
designing a set for use with many colors and other attributes.
 
For a library that is intended to work with both tty and
graphic windows, either tradeoffs are called for or
essentially two modes or face schemes are needed: full and
degraded (tty).  We have constructs like `(type tty pc)' that
can help with that.
 
T> I would not argue that inheritance is an ideal solution to
T> this problem,  However, I do think it can be part of the
T> solution.  Perhaps something along the lines of
T> 
T>  * Establish guidelines on how to use inheritance i.e. how to
T>    select which face to inherit from
T>  * Define a good (not too large) set of base faces.  Existing
T>    font-lock faces may be sufficient, maybe not.  Would need
T>    review.
T>  * Require all face definitions in core emacs packages to
T>    either fully define a face (i.e. definition for dark/light,
T>    tty, X mac ms etc) OR inherit from a base face (assuming
T>    all base faces are fully defined)
T>  * Add a section to the manual encouraging developers to
T>    either provide a fully defined face or inherit from a base
T>    face, but don't just define a single (usually) light
T>    background face
T> 
T> The key here is that all faces in core emacs packages would
T> end up with a fully defined face, either explicitly or via
T> inherit.
 
Fully-defined, yes - good.  The part that I think can be
misguided is basing everything on inheritance from faces that
are not necessarily related in terms of use or meaning.

Basing a face on a related face is not bad.  Stretching things
to base all faces on some "basic" faces, no matter how
unrelated in terms of meaning or context, is not a great idea.
 
Faces, including "basic" faces, are customizable.  You don't
want a user who customizes `font-lock-doc-face' to suddenly
find that s?he has also affected a chain of unrelated faces
that inherit from it.  Customizing font-lock faces should not
affect Dired or Info or...
 
T> One of the reasons I like the use of inherit for face
T> definitions is mainly from an end user perspective. I would
T> rather have faces that are fully defined via inherit, even if
T> that inheritance seems odd, than have a partially defined face
T> which only works if you have a light background or are running
T> under a full gui environment.
 
Those are not the only two alternatives - it's not either-or.
 
I am in favor of full face definitions.  And I am not against
inheritance.  The important thing is for a face to inherit
only from a related face (in terms of use/meaning).
 
The key is whether it will generally make sense for the
inheriting face if the inherited face gets customized.  If
not, then inheritance is likely not the best way to go.
 
T> If, when I change the base face definition, it results in
T> unacceptable changes to some face which inherits from it, I
T> can customize it.
 
Sure you can, but now you're back to customizing all over the
place - and now across multiple libraries and multiple use
contexts, to boot.  The cure is at least as bad as the
disease.
 
Nothing wrong with inheritance.  But boiling everything down
to font-lock faces (or similar) is a bad idea.  Better for
face inheritance to reflect face usage/meaning: families
(inheritance hierarchies) of related faces, not just
everything inheriting from primordial faces `adam' and `eve'.
 
T> My experience has been that this does sometimes happen, but
T> not that often and it is more preferable to fix up the few
T> faces than to spend much more time configuring lots of
T> individual faces.
 
I think you are again thinking of the fact that you are
needing to configure lots of faces because they were defined
incompletely or with poor defaults.  Take away that
presupposition and where is the argument?
 
T> In fact, as the number of individual face definitions has
T> increased, I actaully think we have gone the wrong direction.
T> We have too many faces which are mostly the same.
 
They are not the same just because they have the same
_appearance_ (by _default_ no less).  This is a key element in
the confusion, I think.  It sounds like it motivated Yidong's
search for faces to eliminate "duplication" via inheritance.
 
Faces are not the same as their (attribute) values.  Faces
have identity and purpose as well as values.
 
This is essentially no different from having multiple user
options (or other variables) that have the same value: 42,
nil, t,...  You would not argue that we define a set of
"basic" user options and use inheritance to factor out any
"duplicate" options that have the same default value of 42 or
nil, would you?
 
You would not argue that we should have only one primeval user
option with a default value of 42, and inherit from it for
wildly different options with different use cases (meanings),
so that someone who customizes the "basic" option to change
the value 42 to 24 ends up changing lots and lots of
inheriting options.  Would you?  How are faces different in
this regard?
 
T> It seems now that every new package is adding its own face
T> definitions
 
Good.  That should probably happen more than it does. ;-)
 
If reasonable, related faces exist on which to base the new
face definitions, then by all means inheritance might well be
called for.  But a new package should _not_ avoid adding its
own face definitions, whether they are defined using
inheritance or not (i.e., pointer or copy).
 
On the contrary.  What should be avoided is reusing some face
that makes no sense in the current context.  What is the
_practical_ criterion?  Whether or not customizing the face
wrt its original context/purpose will have a negative effect
in the new context.  If not, then go for it (reuse/inherit).
 
T> and many of them are poorly defined.  It now takes much
T> longer for me to establish a consistent set of faces.
 
Bad - agreed.  But not a necessary consequence of having many
faces.  More likely a consequence of poor default definitions
(as you mentioned).
 
T> If we required face definitions to either be fully defined or
T> inherited from a base set that are fully defined, we would
T> likely give a much better default experience to end users.
 
Full face definitions are good, yes.
That is independent of the question of inheritance.
 
Well... indiscrimately imposing inheritance (from fully defined
faces) can ensure full definitions.  But it has a cost: it can
also introduce unnecessary and unwanted dependencies with
negative consequences.
 
T> Using inheritance also means that when we find a face
T> definition which is poor for a particular environment, we can
T> refine that base definition rather than having to find all
T> similarly poor definitions and updating them individually.
 
Yes and no.  "Fixing" it for one environment might do exactly
the wrong thing for another context, e.g. for one of its
descendents.  Inheritance needs to be used carefully, based on
intended use/meaning of the faces involved.
 
T> Using inheritance means that it is easier to make broad
T> changes to face definitions, reducing the time spent in
T> customize and lets you then tweak those specific faces which
T> don't quite work.
T>
T> So, using your example, if someone changed the base face that
T> dired+ uses, either they will find the result in dired+
T> acceptable or they can then tweak that face further.  The
T> alternative is that it would be necessary to customize both
T> faces, even when you are going to set them to the same value.
 
Maybe, maybe not.  Depends what kind of change you want/need.
 
It's true that if you want to change all occurrences of red
foreground to blue then more customization would be involved
without inheritance.  Maybe we could find a way to make such
changes easier - I don't have a problem with that.
 
But we should not be using _inheritance_ for that (in
general).  A Dired face should either not inherit or it should
inherit from a related face, not just some face whose _default
appearance_ looks good for Dired.  It makes no sense to base a
Dired face on a font-lock face, for instance.
 
Just because you might want some Dired face to have a red
foreground by default is no reason to go looking for a face
with a red foreground to inherit from.  Look instead for a
face with a related use/meaning.  If you find none, then do
not use inheritance here.  That's the guideline I'd suggest.
 
I emphasize the use/meaning of a given face: what it is for,
what it represents, what it does.  I think you are emphasizing
its default appearance - attribute values (color etc.).  To
me, a face or a variable `foo' is mainly about its use, not
its value.
 
If the opposite were true, then we would name faces and
variables after their default values, not after their uses.
Yes, I've seen some Lisp code with face names like
`underlined-bold-red-foreground-on-gray-background'.
(Mea culpa: I even wrote such code at one point.)
 
And there's not necessarily anything wrong with that; for some
contexts it might make sense.  But in that case it makes more
sense for the "face" to be a constant, not customizable.  It
would be perverse to customize a face named `red-foreground'
to have a green foreground.
 
(And in general it is more likely for single attributes to be
reuse candidates than it is for combinations of attributes.)
 
T> The reality is that there are a limited set of good faces and
T> you will usually end up with the same face definition being
T> used in multiple roles.  Frequently, those roles have nothing
T> to do with each other.  This doesn't matter as the contexts
T> are completely different.  From an end user perspective, it is
T> irrelevant that compiler messages inherit from
T> font-lock-string - all the end user sees is that compiler
T> messages use a default face that is green, which may be
T> exactly the same as strings in their code, but so what.
 
I strongly disagree here.
 
If the roles/meanings/use are unrelated, then inheritance is
usually inappropriate.  It _does_ matter whether a
compiler-messages face inherits from `font-lock-string-face' -
_if_ someone customizes that parent face.
 
If we defined a compiler-messages face to inherit from
`font-lock-string-face' _only_ because we liked the default
foreground choice of `LightSalmon', that would be misguided,
IMO.
 
If there is no existing face that is related in terms of
use/meaning, then the compiler-messages face should not
inherit; it should just be defined with a default foreground
of `LightSalmon'.  That kind of duplication is not a curse but
a blessing.
 
Then a user can customize either the compiler-messages face or
`font-lock-string-face' without affecting the other.  And that
makes sense because (by hypothesis) the two are unrelated.




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

* RE: Eliminating a couple of independent face definitions
  2011-02-05 22:09             ` Drew Adams
@ 2011-02-06  7:11               ` Stephen J. Turnbull
  0 siblings, 0 replies; 43+ messages in thread
From: Stephen J. Turnbull @ 2011-02-06  7:11 UTC (permalink / raw)
  To: Drew Adams; +Cc: 'Philipp Haselwarter', emacs-devel

I'm glad we agree about avoiding redundant defintion of semantically
similar faces.

Drew Adams writes:

 > How did this discussion start?  Yidong seemed to be saying
 > (possible misinterpretation, admittedly) that it would be good
 > to get rid of duplicate face definitions, by which he
 > apparently meant faces that have different names but the same
 > attribute values.

That seems unlikely to me; Emacs developers are generally good about
focusing on underlying semantics rather than surface similarities.  In
this case, if that were his intention he'd most likely have suggested
a naming convention that expresses face structure.  You might have
been well-advised to ask him if that is what he meant.

 > I have nothing against the examples of inheritance that you
 > argued for.  They are they same kinds of inheritance that I
 > argued for.

You did?  I'm sorry, I missed it.  The question I responded to didn't
make that distinction at all; it simply asked what is the rationale
for inheritance.

And others (cf. John Yates) do not seem to agree that semantic
redundancy is an issue of concern.  In a long thread it's easy to
become confused about who advocated what, and almost all the arguments
(including conflicting ones) become associated with the most verbose
posters.  If I misrepresented your position, I'm sorry.




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

* RE: Eliminating a couple of independent face definitions
  2011-02-05 22:11             ` Drew Adams
@ 2011-02-07  0:59               ` Drew Adams
  2011-02-07  1:30                 ` Tim Cross
  2011-02-08 13:58                 ` Davis Herring
  2011-02-07  1:08               ` Tim Cross
  1 sibling, 2 replies; 43+ messages in thread
From: Drew Adams @ 2011-02-07  0:59 UTC (permalink / raw)
  To: 'Tim Cross'; +Cc: 'Philipp Haselwarter', emacs-devel

Tim pointed out the problem of faces that are not fully defined, in particular,
for light and dark backgrounds (and for tty).  He pointed to the need for the
Emacs source code to define all faces fully so that they work, out-of-the-box,
regardless of default background etc.

And he pointed to the fact that, given such a basis, inheritance can carry the
ball forward so that newly created faces are more likely, themselves, to be
fully defined - without programmers needing to be face experts or jump through
hoops.

I agreed with Tim that it is good to fully define faces.  Not doing so makes
users customize more than they should need to.  But I also explained why
inheritance can be overkill as a solution to this problem.  Inheritance should
be used when the inheriting face is related to the inherited face - similar
use/meaning/purpose.  It should (generally) be avoided when there is no such
relation.

Inheritance does a good job of enforcing full face definition (given solid
starting points).  Can we get the same benefit some other way - a way that is
not error prone by relying on programmers to copy full definitions by hand etc.?

Sure - just use a copy instead of a pointer.  What's bad about inheriting an
unrelated fully-defined face is that customizing that face also changes the
inheriting face.  But that only happens because the new face always points to
its ancestor for its attribute values.

Why not introduce a new `defface' keyword `:copy-default'?  It would define the
new face with the same default attribute values as another face.  A copy of
those values (actually, of the attributes spec) would be made at `defface' time.
The two faces would remain independent instead of being joined at the hip.  Only
the _default_ attribute values would be used; the current values of the
reference face would have no effect at any time.

If face `barred-foo' is unrelated to font-locking and strings, then instead of
this (which is identical to the `defface' for `font-lock-doc-face):

(defface barred-foo '((t :inherit font-lock-string-face))
  "Face to use for foos that are barred."
  :group 'foobar)

You would use this:

(defface barred-foo '((t :copy-default font-lock-string-face))
  "Face to use for foos that are barred."
  :group 'foobar)

The new face `barred-foo' would have no relation to `font-lock-string-face'.  A
user could customize the latter without that change affecting the former.

The result of the `defface' would be identical to this complex definition (taken
from the definition of `font-lock-string-face'):

(defface barred-foo 
  '((((class grayscale) (background light))
     (:foreground "DimGray" :slant italic))
    (((class grayscale) (background dark))
     (:foreground "LightGray" :slant italic))
    (((class color) (min-colors 88)
     (background light)) (:foreground "VioletRed4"))
    (((class color) (min-colors 88)
     (background dark))  (:foreground "LightSalmon"))
    (((class color) (min-colors 16)
     (background light)) (:foreground "RosyBrown"))
    (((class color) (min-colors 16)
     (background dark))  (:foreground "LightSalmon"))
    (((class color) (min-colors 8))
     (:foreground "green"))
    (t (:slant italic)))
  "Face to use for foos that are barred."
  :group 'foobar)

Simple for even lazy programmers to use.  Not so error-prone for eager
programmers who might otherwise try to make such a copy by hand.  Guaranteed to
be as reasonable for all backgrounds and tty as is the tried-and-true
`font-lock-string-face'.

Anywhere you might use `:inherit' in a face definition you could use
`:copy-default'.  The same `defface' could use both `:inherit' and
`:copy-default', to inherit some attribute values from one face and copy others
(defaults) from another.

We would encourage programmers to use `:inherit' when the new face (its
use/meaning/purpose) is related to the referenced face - that is, when they want
a change in the latter to be reflected in the former.  (`font-lock-doc-face'
inherits from `font-lock-string-face' because they are related.)

We would encourage them to use `:copy-default' when the referenced face is
unrelated and all they want to do is reuse its default-attributes spec.
(`barred-foo' is about foos, not about font-locking or strings.)

I expect that the latter case is more common than the former, but I could be
wrong.

New faces are often created together, as a group in some library, and these are
often related in terms of use/purpose, so inheritance among them can make sense.
But it is less likely that there is an existing face outside of that context
whose use/meaning/purpose is related.  IOW, I see inheritance as most useful
within a library or among related libraries.

It's worth quoting Tim again here.  Having `:copy-default' in addition to
`:inherit' would improve the solution, I think.

T> I would not argue that inheritance is an ideal solution to
T> this problem,  However, I do think it can be part of the
T> solution.  Perhaps something along the lines of
T> 
T>  * Establish guidelines on how to use inheritance i.e. how to
T>    select which face to inherit from
T>  * Define a good (not too large) set of base faces.  Existing
T>    font-lock faces may be sufficient, maybe not.  Would need
T>    review.
T>  * Require all face definitions in core emacs packages to
T>    either fully define a face (i.e. definition for dark/light,
T>    tty, X mac ms etc) OR inherit from a base face (assuming
T>    all base faces are fully defined)
T>  * Add a section to the manual encouraging developers to
T>    either provide a fully defined face or inherit from a base
T>    face, but don't just define a single (usually) light
T>    background face
T> 
T> The key here is that all faces in core emacs packages would
T> end up with a fully defined face, either explicitly or via
T> inherit.




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

* Re: Eliminating a couple of independent face definitions
  2011-02-05 22:11             ` Drew Adams
  2011-02-07  0:59               ` Drew Adams
@ 2011-02-07  1:08               ` Tim Cross
  1 sibling, 0 replies; 43+ messages in thread
From: Tim Cross @ 2011-02-07  1:08 UTC (permalink / raw)
  To: Drew Adams; +Cc: emacs-devel, Philipp Haselwarter

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

On Sun, Feb 6, 2011 at 9:11 AM, Drew Adams <drew.adams@oracle.com> wrote:

> T> One thing I would recommend doing, if possible, would be to
> T> spend some time running emacs with a dark background and on a
> T> tty.  This would likely reveal how bad some default face
> T> definitions are and let you see how tedious it is having to
> T> customize lots of individual face definitions just to get ones
> T> that work.
>
> I'm not sure what your disagreements are with what I said.  I
> agree that poorly defined default face definitions are a real
> problem.  I even suggested that they are likely _the_ real
> problem here.
>
> I think our point of disagreement is small - it is really a matter of
degrees. Your position is one I would characterise as representing a pure or
strict view of inheritance and one I see as having a strong ideological and
theoretical base. Mine is possibly chracterised as being more pragmatic and
less pure or strict, possibly characterised as being more liberal.

There are also a number of assumptions and conclusions you ahve made
regarding some of my points, which are incorrect. I will try to make my
position with these clearer.

Given reasonable face defaults that work out of the box on
> both dark and light backgrounds, I think many if not most
> (perhaps all?) of the problems you cited go away.  With faces
> that just work by default, regardless of the background, there
> is no need to "customize lots of individual face definitions
> just to get ones that work".
>
> Agreed. If all faces were well defined there would be no problem. However,
the reality is that frequently they are not. My suggestions are based on the
belief that this is because defining good default face settings is not easy,
takes more effort than some developers want to expend, is difficult to do
right as developers don't necessarily have access to all the environments
involved and it may be unreasonable to expect all developers have the
necessary knowledge and experience to know/identify a good default face
setting. Therefore, my focus is on what we can do to make it easier for
developers to do the right thing. One solution which I think would work
towards this would be to develop a set of guidelines on how to identify and
select appropriate faces to inherit from and pitfalls to avoid combined with
requiring that faces are either fully defined or inherit from a  core/base
face which is fully defined.

I'm not arguing that faces with similar appearance should be linked via
inheritance and I'm not arguing that existing fully defined faces should be
converted to use inheritance.

The main point of disagreement concerns determining appropriate faces to
inherit from. Your position is that inheritance should only be used to
inherit from a face with the same/similar semantics/meaning as the child
face. My argument is less restrictive. If a core face exists that has the
same semantic meaning as the child face, then of course that is the obvious
choice. However, if there are no core faces with the same semantic meaning I
would rather have the face inherit from a fully defined face with a
different semantic meaning, provided that does not cause confusion within
the mode used by the child face, rather than have a face that is not fully
defined.

I would go further and suggest that while you accept the use of inheritance
provided the inheritance chain follows the same semantic meaning, you would
prefer in general not to use inheritance even if a good candidate with the
same semantic meaning does exist in the core set of fully defined faces.
While I would never argue that developers should be forced to use
inheritance, I would suggest this is the wrong approach. I believe
inheritance should definitely be used when there is clear semantic
equivalents within the core set because this will help ensure consistency in
representation of semantically related items. For example, I currently have
numerous definitions for 'hyperlink' type objects as well as clickable
buttons. I would like objects of these types to have the same appearance in
all modes. However, I like hyperlinks to be a specific colour, with
underlining, bold and italic fonts. To achieve this (possibly unusual)
appearance in a consistent manner, I have to customize multiple faces.
However, if inheritance was used, I would only have to do this once.

If I understand your position regarding inheritance, you disagree with the
concept of a child face inheriting from a semantically unrelated face
because you feel doing so will lead to confusion and unexpected results
because it 'muddies' the semantics of the inheritance and will cause
unexpected/unwanted side effects when a core face definition is changed. I
don't see it as being that straight-forward. I agree that badly chosen
inheritance would cause problems - for example, having something that was
not a clickable link inherit from the link face. On the other hand, core
packages, such as dired, have been using inheritance from sematically
unrelated faces for some time and I'm not aware it has caused problems. The
dired-directory face inherits from font-lock-function-name-face. There is no
'semantic' link between these two faces, yet having this inheritance
apparently works. Yes, if I change the value of
font-lock-function-name-face, it will change the appearance of directory
names in dired. However, in practice, this is rarely a problem. In fact, if
your changing the face to make it fit better with some theme or to work
better in your environment, it is likely that this change would fit with
your overall objectives anyway.

One of the reasons I think this works is because the choice is unrelated and
does not confuse contexts within the mode the face is used in. If dired had
a face to represent function names, then using font-lock-function-name-face
for directory names would be a bad idea. However, dired does not have such a
context and therefore does not cause confusion within that mode.
Furthermore, I don't believe it would cause confusion with modes that use
font-lock-function-name-face for function names. The two modes are distinct
enough that it is clear that a face with X attributes in dired is different
to a face with the same attributes in completely unrelated modes, such as
emacs-lisp-mode.

There are some other benefits to using inheritance in this manner. I think
it is reasonable to suggest that all users have some underlying 'theme' they
want to achieve with face settings. Some themes may seem unusual or even
unpleasant, but there is usually some overriding pattern - faces are not
selected randomly (I guess there may be some extreme cases where people
might do this, but it isn't the 'norm'). Within any theme there is a finite
set of usable faces i.e. faces that can be read, fit with the theme and are
aesthetically acceptable. As we increase the number of individual face
definitions, we also increase the number of faces with different
names/meanings which have the same set of attributes as other unrelated
faces.

If we assume two basic approaches, your pure inheritance model and my less
rigid inheritance approach, we end up with two vary different situations
when it comes to the user customizing faces to obtain their desired theme.
Under your approach, they will need to customize a larger number of faces to
obtain their desired outcome.  However, under my approach, which is more
likely to make greater use of inheritance because it is not restricted to
only using semantically related faces, it is more probable that less faces
will need to be defined.

Of course, we could probably achieve a better 'middle ground' with a larger,
more comprehensive set of core/base faces as this would increase the
likelihood that a child face can find a sematically related core/base face
definition. I have nothing against this and included it as part of my
suggestion on how to improve matters and reduce the number of poorly defined
faces.


> T> As I see it, we want to achieve four main goals. We want to
> T> make it easier for developers to set appropriate defaults, we
> T> want to get the best default possible for end users,
> T> regardless of platform or light/dark background preferences,
> T> we want to make it as easy as possible for end users to
> T> customize their environment
>
> Agree.
>
> T> and we want to, if possible, avoid a proliferation of
> T> different face definitions, especially when the definitions
> T> don't really differ in anything other than name as this makes
> T> customizing and theme definition more complex than it needs to
> T> be.
>
> Disagree, if by "don't really differ in anything other than
> the name" you are referring only to the `defface' default
> attribute values.
>
> I am in favor of there being two faces instead of one, if
> their use/meaning is different, even if their definitions
> modulo the names are identical.  In particular, this
> facilitates separate customization.
>
> I was actually thinking of faces that have the same meaning, different
names and different default definitions. This is a growing problem. We end
up with inconsistency between modes for faces representing the same type of
object. It was not meant to mean faces that happen to have the same
attribute sets. For example, I have a number of modes that have the same
concept of a clickable 'button'. In some modes they look different to how
buttons look in other modes. I want them to all look the same and have to
customize them individually. This is what I meant by the proliferation of
faces.



> It avoids coupling that is not logical and not necessary.
> Inheritance (hence coupling) based on physical attributes
> (appearance) can perhaps occasionally be appropriate, but in
> general it is a no-no.
>
> Yes, where possible, inheritance should be used to link semantically
related faces . However, linking semantically unrelated faces is not as bad
in practice as you suggest and could be used to improve the end user
expereince without causing the confusion you suggest. Yes, there are
dangers, but there are also benefits which I think outweigh the downside of
a strict inheritance approach, especially if there are only a few core/base
fonts to inherit from.

(Names are generally indicative of meaning, but yes, there
> could be two faces with different names yet identical meaning.
> In that case, yes, the duplication could be eliminated.)
>
> (There is an orthogonal reason to avoid using too many faces
> at the same time: performance.  But that is a different story
> altogether.)
>
> T> It was good you pointed out that faces are not just about
> T> colour.  Sometimes, I think peopoe forget this and only focus
> T> on the colour aspect.  However, this is understandable as
> T> colour is what distinguishes most faces from each other.
> T>
> T> We need to acknowledge how difficult it is to define good
> T> default faces.  Many definitions fail to do this.  While your
> T> suggestion of using colour compliments can help, I'm not
> T> convinced it is always that easy.  One problem is that
> T> different environments have different sets of colours to work
> T> with.  For example, if you work under the linux console, you
> T> don't have compliments for most of the colours available under
> T> other environments, such as X or (I presume) Windows/Mac.  The
> T> problem is further complicated because most developers won't
> T> have access to many of these environments, so can't easil test
> T> and design appropriate faces even if motivated to do so.
>
> Agree.  I did not mean to raise complementing as any kind of
> cure-all - far from it.  I was just mentioning that I provided
> a quick-and-dirty set of default settings for dark backgrounds
> for a particular library by flipping the light-background
> defaults to their complements.  Obviously, any set of defaults
> for either light or dark deserves to be well thought out.  And
> all of the considerations you mention should be taken into
> account.
>
> The tty thing is a big limitation, in particular.  Designing a
> set of faces for use on tty only is a different task from
> designing a set for use with many colors and other attributes.
>
> For a library that is intended to work with both tty and
> graphic windows, either tradeoffs are called for or
> essentially two modes or face schemes are needed: full and
> degraded (tty).  We have constructs like `(type tty pc)' that
> can help with that.
>
> The tty face values are a little tricky because you have a much smaller set
of attributes to work with and the attributes you do have have less options.
However, the defface macro has the ability to handle this and while it may
be a pain to do, it is doable and should be part of any fully defined face
definition. I would suggest there are very few packages which are only
designed to run within a GUI environment (e.g. doc-view I guess, can't think
of many others).


> T> I would not argue that inheritance is an ideal solution to
> T> this problem,  However, I do think it can be part of the
> T> solution.  Perhaps something along the lines of
> T>
> T>  * Establish guidelines on how to use inheritance i.e. how to
> T>    select which face to inherit from
> T>  * Define a good (not too large) set of base faces.  Existing
> T>    font-lock faces may be sufficient, maybe not.  Would need
> T>    review.
> T>  * Require all face definitions in core emacs packages to
> T>    either fully define a face (i.e. definition for dark/light,
> T>    tty, X mac ms etc) OR inherit from a base face (assuming
> T>    all base faces are fully defined)
> T>  * Add a section to the manual encouraging developers to
> T>    either provide a fully defined face or inherit from a base
> T>    face, but don't just define a single (usually) light
> T>    background face
> T>
> T> The key here is that all faces in core emacs packages would
> T> end up with a fully defined face, either explicitly or via
> T> inherit.
>
> Fully-defined, yes - good.  The part that I think can be
> misguided is basing everything on inheritance from faces that
> are not necessarily related in terms of use or meaning.
>
> Nobody has suggested basing everything on inheritance and it has not been
suggested that inheritance should be forced on anyone (though, as outlined
above, there could be a strong argument for forcing inheritance for clearly
semantically related faces). The suggestion is that if you don't want to
fully define a face, then use inheritance RATHER than a partially defined
face.


> Basing a face on a related face is not bad.  Stretching things
> to base all faces on some "basic" faces, no matter how
> unrelated in terms of meaning or context, is not a great idea.
>
> Nobody has suggested basing *all* faces on some base set.


> Faces, including "basic" faces, are customizable.  You don't
> want a user who customizes `font-lock-doc-face' to suddenly
> find that s?he has also affected a chain of unrelated faces
> that inherit from it.  Customizing font-lock faces should not
> affect Dired or Info or...
>
> Except they already do! I don't see this as a 'real' problem, but more a
theoretical one. Yes, changing face attributes in font-lock-* faces will
change the look of dired faces, but does that really matter in practice?
Maybe the dired faces should be fully defined and I would not have an issue
with that. However, I'm glad they are using inheritance rather than only
having partial definitions.
.

> T> One of the reasons I like the use of inherit for face
> T> definitions is mainly from an end user perspective. I would
> T> rather have faces that are fully defined via inherit, even if
> T> that inheritance seems odd, than have a partially defined face
> T> which only works if you have a light background or are running
> T> under a full gui environment.
>
> Those are not the only two alternatives - it's not either-or.
>
> I am in favor of full face definitions.  And I am not against
> inheritance.  The important thing is for a face to inherit
> only from a related face (in terms of use/meaning).
>

I would argue it is preferable rather than being required.

>
> The key is whether it will generally make sense for the
> inheriting face if the inherited face gets customized.  If
> not, then inheritance is likely not the best way to go.
>
> I actually agree, except we would differ on what makes sense.


> T> If, when I change the base face definition, it results in
> T> unacceptable changes to some face which inherits from it, I
> T> can customize it.
>
> Sure you can, but now you're back to customizing all over the
> place - and now across multiple libraries and multiple use
> contexts, to boot.  The cure is at least as bad as the
> disease.
>
> No, its not as bad. If more faces inherited from fully defined core faces,
then the faces I need to customize are only those which I find aesthetically
unacceptable and does not include faces that are not fully defined and
therefore are not even readable in my environment. Moreover, many of the
faces I find aesthetically unacceptable are likely to have the same/similar
attributes. I can change the base definition and have my changes propogate
through all faces that currently have the unacceptable default. Without the
use of inheritance, I have multiple faces to change. When they are not fully
defined, many of those changes are needed just to make the face readable
i.e. not just an aesthetic change, but a necessary one.

Nothing wrong with inheritance.  But boiling everything down
> to font-lock faces (or similar) is a bad idea.  Better for
> face inheritance to reflect face usage/meaning: families
> (inheritance hierarchies) of related faces, not just
> everything inheriting from primordial faces `adam' and `eve'.
>
> Why do you keep taking the extreme? Nobody has suggested that all faces
inherit form some low base. This is not what I've suggested - either fully
define or inherit, just don't have partial poorly defined faces that only
work in a limited environment, such as a light background.


> T> My experience has been that this does sometimes happen, but
> T> not that often and it is more preferable to fix up the few
> T> faces than to spend much more time configuring lots of
> T> individual faces.
>
> I think you are again thinking of the fact that you are
> needing to configure lots of faces because they were defined
> incompletely or with poor defaults.  Take away that
> presupposition and where is the argument?
>

To take away that presupposition, you need to come up with something that
enables developers to do the right thing and not only use partial face
definitions as the default. This is the whole point. Yes, theoretically, if
all faces were fully defined, most of the problem would go away (though
there are then other issues concerning consistency). The reality is that too
often, faces are not fully defined. Inheritance would provide a simple way
to have a fully defined face when the developer cannot or does not want to
fully define the face themselves.


> T> In fact, as the number of individual face definitions has
> T> increased, I actaully think we have gone the wrong direction.
> T> We have too many faces which are mostly the same.
>
> They are not the same just because they have the same
> _appearance_ (by _default_ no less).  This is a key element in
> the confusion, I think.  It sounds like it motivated Yidong's
> search for faces to eliminate "duplication" via inheritance.
>
> I acknowledge that. However, we have instances of faces that do represent
the same semantic object, but which have different definitions in different
modes i.e. clickable buttons etc. I have three different faces for
representing dates (admittedly, these are add-on packages and not core
ones), I have different faces for representing links etc. None of these use
inheritance and in some cases, have different default values. In these
instances, inheritance should be used. I then have the ability to set all
like things to the same appearance and if I want, the option to change or
augement them per mode.


> Faces are not the same as their (attribute) values.  Faces
> have identity and purpose as well as values.
>
> Agreed. We may differ on how far that identity reaches. I see
dired-directory as having its own identity and its relevance is restricted
to within dired mode. It inherits from a font-lock face, but I don't see
that as part of its identity as such. You appear to see the face it inherits
from as part of its identity as well. I'm not sure this is always so or
necessary.

This is essentially no different from having multiple user
> options (or other variables) that have the same value: 42,
> nil, t,...  You would not argue that we define a set of
> "basic" user options and use inheritance to factor out any
> "duplicate" options that have the same default value of 42 or
> nil, would you?
>
> You would not argue that we should have only one primeval user
> option with a default value of 42, and inherit from it for
> wildly different options with different use cases (meanings),
> so that someone who customizes the "basic" option to change
> the value 42 to 24 ends up changing lots and lots of
> inheriting options.  Would you?  How are faces different in
> this regard?
>
> Now this is just plain silly and a very poor analogy . Faces have a lot
more in common and a much closer relationship than al the user variables.
Faces work together to present a theme, they are not independent as you
imply. Faces that don't set an attribute inherit the value from the default
face. You configure faces based on an overall theme and how they interact
with each other and faces all have the same format/attributes. To suggest
they are as indpendent from each other as other user variables is nonsense.

Ignoring how poor the analogy is, the fact is that NOBODY has suggested that
all faces need to inherit form a base set. This was never proposed.

T> It seems now that every new package is adding its own face
> T> definitions
>
> Good.  That should probably happen more than it does. ;-)
>
> If reasonable, related faces exist on which to base the new
> face definitions, then by all means inheritance might well be
> called for.  But a new package should _not_ avoid adding its
> own face definitions, whether they are defined using
> inheritance or not (i.e., pointer or copy).
>
> Disagree. A package should only define its own face when either there is no
existing face which adequately represents the meaining of the face OR there
is a strong expectation that the user may want to customize the face
independently. There is a definite danger of having too many faces and
ending up with a consistency problem. Consider the situation where every
programming mode defined its own face to represent comments and did not use
inheritance. What benefit does that give us? Very little. What harm -
potentially a lot as now you have to configure multiple faces to just get
code comments to have a consistent appearance.

A mode should NOT create a new face just for the sake of it and if it does
create a new face, either fully define the face or inherit from a fully
defined face - its that simple.  If you want to restrict inheritance to only
use faces with the same semantic meaning, fine. I think it is over
restrictive, but care less about that than about having a solution that
would ensure faces are fully defined and providing a way to achieve this
that will facilitate developers doing the right thing.

On the contrary.  What should be avoided is reusing some face
> that makes no sense in the current context.  What is the
> _practical_ criterion?  Whether or not customizing the face
> wrt its original context/purpose will have a negative effect
> in the new context.  If not, then go for it (reuse/inherit).
>

Agreed - pretty much my position.

>
> T> and many of them are poorly defined.  It now takes much
> T> longer for me to establish a consistent set of faces.
>
> Bad - agreed.  But not a necessary consequence of having many
> faces.  More likely a consequence of poor default definitions
> (as you mentioned).
>
> Yes, but encouraging the addition of new faces without good justification
is bad - it is the other extreme. Too often, I use applications that don't
have enough faces and I cannot change the appearance of some object that I
would like to somehow stand-out. However, the other extreme is a
proliferation of unnecessary faces that just make customization and theming
more difficult.

T> If we required face definitions to either be fully defined or
> T> inherited from a base set that are fully defined, we would
> T> likely give a much better default experience to end users.
>
> Full face definitions are good, yes.
> That is independent of the question of inheritance.
>
> Well... indiscrimately imposing inheritance (from fully defined
> faces) can ensure full definitions.  But it has a cost: it can
> also introduce unnecessary and unwanted dependencies with
> negative consequences.
>
> Well, either direction has a cost. There is no avoiding that. My view is to
find the point at which we get the best cost/benefit. Inheritance provides a
way to reduce the burden on developers to fullly define faces and has the
potential to reduce the number of faces that are only partially defined and
work only in limited configurations/environments. Whether we have strict or
less rigid restrictions on inheritance will affect how easily inheritance
can be used in this manner. Strict inheritance will give a consistent
semantic meaning in inheritance chains and potentially more predictable
resutls when modifying base faces. Less rigid inheritance would allow
inheritance to be used instead of fully face definitions in more situations.
If badly applied it does have the potential to cause confusion, but this
could be mitigated with good guidelines. New faces should only be introduced
when there is a demonstrated case and not just as an automatic default
action.

T> Using inheritance also means that when we find a face
> T> definition which is poor for a particular environment, we can
> T> refine that base definition rather than having to find all
> T> similarly poor definitions and updating them individually.
>
> Yes and no.  "Fixing" it for one environment might do exactly
> the wrong thing for another context, e.g. for one of its
> descendents.  Inheritance needs to be used carefully, based on
> intended use/meaning of the faces involved.
>
> Maybe, though I don't think it is as bad in practice as you assume.
Existing modes have been using inheritance in a non-semantic fashion since
at least emacs 21 and this doesn't seem to have cause any major issues.

T> Using inheritance means that it is easier to make broad
> T> changes to face definitions, reducing the time spent in
> T> customize and lets you then tweak those specific faces which
> T> don't quite work.
> T>
> T> So, using your example, if someone changed the base face that
> T> dired+ uses, either they will find the result in dired+
> T> acceptable or they can then tweak that face further.  The
> T> alternative is that it would be necessary to customize both
> T> faces, even when you are going to set them to the same value.
>
> Maybe, maybe not.  Depends what kind of change you want/need.
>
> It's true that if you want to change all occurrences of red
> foreground to blue then more customization would be involved
> without inheritance.  Maybe we could find a way to make such
> changes easier - I don't have a problem with that.
>
> Maybe this could be an alternative. Frequently, you do need to change
colours 'across the board' - often because the faces are not fully defined
and you have a different background to the assumed default and need to make
the change to make the face more readable. So, perhaps this would fix the
symptom. However, it does not address the basic problem, which is faces that
are not fully defined.

But we should not be using _inheritance_ for that (in
> general).  A Dired face should either not inherit or it should
> inherit from a related face, not just some face whose _default
> appearance_ looks good for Dired.  It makes no sense to base a
> Dired face on a font-lock face, for instance.
>
> So you would argue that the existing dired face definitions are wrong.
However, they ahve been like that for quite some time and it appears to
work.


> Just because you might want some Dired face to have a red
> foreground by default is no reason to go looking for a face
> with a red foreground to inherit from.  Look instead for a
> face with a related use/meaning.  If you find none, then do
> not use inheritance here.  That's the guideline I'd suggest.
>
> I emphasize the use/meaning of a given face: what it is for,
> what it represents, what it does.  I think you are emphasizing
> its default appearance - attribute values (color etc.).  To
> me, a face or a variable `foo' is mainly about its use, not
> its value.
>
> No, I'm not focused on its appearance. The difference is that while I agree
you should select the face that has a similar semantic meaning if one
exists, I have no issue with using one that does not provided it does not
cause confusion within the mode it is used in. I would cite dired as an
example where this has been done successfully.


> If the opposite were true, then we would name faces and
> variables after their default values, not after their uses.
> Yes, I've seen some Lisp code with face names like
> `underlined-bold-red-foreground-on-gray-background'.
> (Mea culpa: I even wrote such code at one point.)
>
> And there's not necessarily anything wrong with that; for some
> contexts it might make sense.  But in that case it makes more
> sense for the "face" to be a constant, not customizable.  It
> would be perverse to customize a face named `red-foreground'
> to have a green foreground.
>

(And in general it is more likely for single attributes to be
> reuse candidates than it is for combinations of attributes.)
>
> T> The reality is that there are a limited set of good faces and
> T> you will usually end up with the same face definition being
> T> used in multiple roles.  Frequently, those roles have nothing
> T> to do with each other.  This doesn't matter as the contexts
> T> are completely different.  From an end user perspective, it is
> T> irrelevant that compiler messages inherit from
> T> font-lock-string - all the end user sees is that compiler
> T> messages use a default face that is green, which may be
> T> exactly the same as strings in their code, but so what.
>
> I strongly disagree here.
>
> If the roles/meanings/use are unrelated, then inheritance is
> usually inappropriate.  It _does_ matter whether a
> compiler-messages face inherits from `font-lock-string-face' -
> _if_ someone customizes that parent face.
>
> But does it really matter. I change font-lock-comment-face to orange
because that is easier to read or more aesthetic given my default background
colour. As a result, compiler-message face also changes to orange. Isn't it
just as likely that if pink was not acceptable for comments in code that
pink is also unacceptable for messages in compile-mode? Sure, maybe I might
decide I'd still like pink for those messages and I can override the
inheritance, but in practice, I think in most cases, this would be fine and
has been my experience with the mdoes that do use inheritance in such a
manner.

Of course, if there is a base face with a more closely fitting semantic
meaning, it should be used in preference and you would avoid using faces
like link or button that have very precise meanings that could cause
confusion within the mode - especially if that mode supports links or
buttons.

If we defined a compiler-messages face to inherit from
> `font-lock-string-face' _only_ because we liked the default
> foreground choice of `LightSalmon', that would be misguided,
> IMO.
>
> Perhaps, if that was the only motivation. However, if you choose that
font-lock face because you want to use inheritance rather than spend time
fully defining compiler-message face and if the font-lock face is fully
defined, then it may be a valid choice.


> If there is no existing face that is related in terms of
> use/meaning, then the compiler-messages face should not
> inherit; it should just be defined with a default foreground
> of `LightSalmon'.  That kind of duplication is not a curse but
> a blessing.
>

NO, That would be a partial font definition. If I happen to use a background
of LightSalmon, that face is now unreadable. Either fully define the face or
inherit.

>
> Then a user can customize either the compiler-messages face or
> `font-lock-string-face' without affecting the other.  And that
> makes sense because (by hypothesis) the two are unrelated.
>
> Even if compiler-message face uses inheritance form an unrelated face, you
still have the option of customizing it to something different or even
removing the inheritance if so desired.

Tim

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

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

* Re: Eliminating a couple of independent face definitions
  2011-02-07  0:59               ` Drew Adams
@ 2011-02-07  1:30                 ` Tim Cross
  2011-02-07 14:09                   ` Drew Adams
  2011-02-08 13:58                 ` Davis Herring
  1 sibling, 1 reply; 43+ messages in thread
From: Tim Cross @ 2011-02-07  1:30 UTC (permalink / raw)
  To: Drew Adams; +Cc: Philipp Haselwarter, emacs-devel

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

On Mon, Feb 7, 2011 at 11:59 AM, Drew Adams <drew.adams@oracle.com> wrote:

> Tim pointed out the problem of faces that are not fully defined, in
> particular,
> for light and dark backgrounds (and for tty).  He pointed to the need for
> the
> Emacs source code to define all faces fully so that they work,
> out-of-the-box,
> regardless of default background etc.
>
> And he pointed to the fact that, given such a basis, inheritance can carry
> the
> ball forward so that newly created faces are more likely, themselves, to be
> fully defined - without programmers needing to be face experts or jump
> through
> hoops.
>
> I agreed with Tim that it is good to fully define faces.  Not doing so
> makes
> users customize more than they should need to.  But I also explained why
> inheritance can be overkill as a solution to this problem.  Inheritance
> should
> be used when the inheriting face is related to the inherited face - similar
> use/meaning/purpose.  It should (generally) be avoided when there is no
> such
> relation.
>
> Inheritance does a good job of enforcing full face definition (given solid
> starting points).  Can we get the same benefit some other way - a way that
> is
> not error prone by relying on programmers to copy full definitions by hand
> etc.?
>
> Sure - just use a copy instead of a pointer.  What's bad about inheriting
> an
> unrelated fully-defined face is that customizing that face also changes the
> inheriting face.  But that only happens because the new face always points
> to
> its ancestor for its attribute values.
>
> Why not introduce a new `defface' keyword `:copy-default'?  It would define
> the
> new face with the same default attribute values as another face.  A copy of
> those values (actually, of the attributes spec) would be made at `defface'
> time.
> The two faces would remain independent instead of being joined at the hip.
>  Only
> the _default_ attribute values would be used; the current values of the
> reference face would have no effect at any time.
>
> If face `barred-foo' is unrelated to font-locking and strings, then instead
> of
> this (which is identical to the `defface' for `font-lock-doc-face):
>
> (defface barred-foo '((t :inherit font-lock-string-face))
>  "Face to use for foos that are barred."
>  :group 'foobar)
>
> You would use this:
>
> (defface barred-foo '((t :copy-default font-lock-string-face))
>  "Face to use for foos that are barred."
>  :group 'foobar)
>
> The new face `barred-foo' would have no relation to
> `font-lock-string-face'.  A
> user could customize the latter without that change affecting the former.
>
> The result of the `defface' would be identical to this complex definition
> (taken
> from the definition of `font-lock-string-face'):
>
> (defface barred-foo
>  '((((class grayscale) (background light))
>     (:foreground "DimGray" :slant italic))
>    (((class grayscale) (background dark))
>     (:foreground "LightGray" :slant italic))
>    (((class color) (min-colors 88)
>     (background light)) (:foreground "VioletRed4"))
>    (((class color) (min-colors 88)
>     (background dark))  (:foreground "LightSalmon"))
>    (((class color) (min-colors 16)
>     (background light)) (:foreground "RosyBrown"))
>    (((class color) (min-colors 16)
>     (background dark))  (:foreground "LightSalmon"))
>    (((class color) (min-colors 8))
>     (:foreground "green"))
>    (t (:slant italic)))
>  "Face to use for foos that are barred."
>  :group 'foobar)
>
> Simple for even lazy programmers to use.  Not so error-prone for eager
> programmers who might otherwise try to make such a copy by hand.
>  Guaranteed to
> be as reasonable for all backgrounds and tty as is the tried-and-true
> `font-lock-string-face'.
>
> Anywhere you might use `:inherit' in a face definition you could use
> `:copy-default'.  The same `defface' could use both `:inherit' and
> `:copy-default', to inherit some attribute values from one face and copy
> others
> (defaults) from another.
>
> We would encourage programmers to use `:inherit' when the new face (its
> use/meaning/purpose) is related to the referenced face - that is, when they
> want
> a change in the latter to be reflected in the former.
>  (`font-lock-doc-face'
> inherits from `font-lock-string-face' because they are related.)
>
> We would encourage them to use `:copy-default' when the referenced face is
> unrelated and all they want to do is reuse its default-attributes spec.
> (`barred-foo' is about foos, not about font-locking or strings.)
>
> I expect that the latter case is more common than the former, but I could
> be
> wrong.
>
> New faces are often created together, as a group in some library, and these
> are
> often related in terms of use/purpose, so inheritance among them can make
> sense.
> But it is less likely that there is an existing face outside of that
> context
> whose use/meaning/purpose is related.  IOW, I see inheritance as most
> useful
> within a library or among related libraries.
>
> It's worth quoting Tim again here.  Having `:copy-default' in addition to
> `:inherit' would improve the solution, I think.
>
> T> I would not argue that inheritance is an ideal solution to
> T> this problem,  However, I do think it can be part of the
> T> solution.  Perhaps something along the lines of
> T>
> T>  * Establish guidelines on how to use inheritance i.e. how to
> T>    select which face to inherit from
> T>  * Define a good (not too large) set of base faces.  Existing
> T>    font-lock faces may be sufficient, maybe not.  Would need
> T>    review.
> T>  * Require all face definitions in core emacs packages to
> T>    either fully define a face (i.e. definition for dark/light,
> T>    tty, X mac ms etc) OR inherit from a base face (assuming
> T>    all base faces are fully defined)
> T>  * Add a section to the manual encouraging developers to
> T>    either provide a fully defined face or inherit from a base
> T>    face, but don't just define a single (usually) light
> T>    background face
> T>
> T> The key here is that all faces in core emacs packages would
> T> end up with a fully defined face, either explicitly or via
> T> inherit.
>
> Ignoring implementation issues, your suggestion appears to meet the main
objective i.e. making it easier for programmers to do the right thing and
have fully defined faces without having to jump through all the hoops. I
would agree that it is a better solution than using inheritance with
semantically unrelated parents as it does appear to provide a solution that
does not compromise the strict form of preferred inheritance and a way to
improve the quality of default face values.

I would suggest that in addition to such enhancements to defface, we need to
provide guidelines in the manual on how to use inheritance and copy and
would go further and argue that for semantically related faces, inheritance
*should* be used to help enhance consistency and allow users to customize a
semantic 'class' in one go.

Tim

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

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

* RE: Eliminating a couple of independent face definitions
  2011-02-07  1:30                 ` Tim Cross
@ 2011-02-07 14:09                   ` Drew Adams
  2011-02-07 21:14                     ` Tim Cross
  0 siblings, 1 reply; 43+ messages in thread
From: Drew Adams @ 2011-02-07 14:09 UTC (permalink / raw)
  To: 'Tim Cross'; +Cc: 'Philipp Haselwarter', emacs-devel

T> Ignoring implementation issues, your suggestion appears to
T> meet the main objective i.e. making it easier for programmers
T> to do the right thing and have fully defined faces without
T> having to jump through all the hoops. I would agree that it is
T> a better solution than using inheritance with semantically
T> unrelated parents as it does appear to provide a solution that
T> does not compromise the strict form of preferred inheritance
T> and a way to improve the quality of default face values. 
T>
T> I would suggest that in addition to such enhancements to defface,
T> we need to provide guidelines in the manual on how to use
T> inheritance and copy and would go further and argue that for
T> semantically related faces, inheritance *should* be used to help
T> enhance consistency and allow users to customize a semantic
T> 'class' in one go.

Yes to guidelines in the manual and yes to encouraging inheritance among faces
with similar meaning/use.  As I said:

d> We would encourage programmers to use `:inherit' when the
d> new face (its use/meaning/purpose) is related to the
d> referenced face - that is, when they want a change in the
d> latter to be reflected in the former.

d> We would encourage them to use `:copy-default' when the
d> referenced face is unrelated and all they want to do is
d> reuse its default-attributes spec.

We would encourage them to use one or the other, to get full face definitions
able to handle different backgrounds etc.  And we would explain when it can be
good to use one vs the other.

We would also say why full definitions are important, and perhaps use an example
to point out characteristics of a full definition. 





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

* Re: Eliminating a couple of independent face definitions
  2011-02-07 14:09                   ` Drew Adams
@ 2011-02-07 21:14                     ` Tim Cross
  2011-02-07 22:12                       ` Drew Adams
  0 siblings, 1 reply; 43+ messages in thread
From: Tim Cross @ 2011-02-07 21:14 UTC (permalink / raw)
  To: Drew Adams; +Cc: Philipp Haselwarter, emacs-devel

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

On Tue, Feb 8, 2011 at 1:09 AM, Drew Adams <drew.adams@oracle.com> wrote:

> T> Ignoring implementation issues, your suggestion appears to
> T> meet the main objective i.e. making it easier for programmers
> T> to do the right thing and have fully defined faces without
> T> having to jump through all the hoops. I would agree that it is
> T> a better solution than using inheritance with semantically
> T> unrelated parents as it does appear to provide a solution that
> T> does not compromise the strict form of preferred inheritance
> T> and a way to improve the quality of default face values.
> T>
> T> I would suggest that in addition to such enhancements to defface,
> T> we need to provide guidelines in the manual on how to use
> T> inheritance and copy and would go further and argue that for
> T> semantically related faces, inheritance *should* be used to help
> T> enhance consistency and allow users to customize a semantic
> T> 'class' in one go.
>
> Yes to guidelines in the manual and yes to encouraging inheritance among
> faces
> with similar meaning/use.  As I said:
>
> d> We would encourage programmers to use `:inherit' when the
> d> new face (its use/meaning/purpose) is related to the
> d> referenced face - that is, when they want a change in the
> d> latter to be reflected in the former.
>
> d> We would encourage them to use `:copy-default' when the
> d> referenced face is unrelated and all they want to do is
> d> reuse its default-attributes spec.
>
> We would encourage them to use one or the other, to get full face
> definitions
> able to handle different backgrounds etc.  And we would explain when it can
> be
> good to use one vs the other.
>
> We would also say why full definitions are important, and perhaps use an
> example
> to point out characteristics of a full definition.
>
> There is an example in the maual that shows using the different classes to
handle tty, dark/light etc. Of course, this doesn't mean it couldn't be
extended/improved.

I do see some possible implementation issues with the copy concept though.
One problem could be determining when to do the copy. If I have face x and
then define face y using your proposed copy semantics, how would you control
when that copy occurs. For example, if I customize face x, how will face y
know the next time emacs is started to use the old values of face x and not
the new customized values? Somehow the defface would need to know to only
copy the values from face x the first time it is defined/used i.e. from the
first session that the face is used and to then keep those values for future
sessions. Without this, you would simply have a form of delayed inheritance,
which is likely going to be even more confusing that using normal
inheritance as the change would be session dependent and time delayed. This
seems like a non-trivial modification to the defface mechanism as it
introduces a new state/time dimension i.e. copy face x attributes unless
face y attributes have already been copied in a previous session.  Maybe
defface could have some type of 'initform' exstension that is used to
configure the face if it has no custom setting. The result would need to be
written to the custom-faces section so that it is only run once.

Tim

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

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

* RE: Eliminating a couple of independent face definitions
  2011-02-07 21:14                     ` Tim Cross
@ 2011-02-07 22:12                       ` Drew Adams
  2011-02-08  3:51                         ` Tim Cross
  0 siblings, 1 reply; 43+ messages in thread
From: Drew Adams @ 2011-02-07 22:12 UTC (permalink / raw)
  To: 'Tim Cross'; +Cc: 'Philipp Haselwarter', emacs-devel

T> I do see some possible implementation issues with
T> the copy concept though. One problem could be
T> determining when to do the copy. If I have face x
T> and then define face y using your proposed copy
T> semantics, how would you control when that copy occurs.

I have not thought about implementation, nor will I really try to. ;-)  I leave
that to others more knowledgable.

I did say what I thought was called for wrt copy time, however: copy when the
`defface' with the `:copy-default' gets eval'd.  Normally, that's at load time.

And I did mention that only the default-attributes spec would be copied from the
reference face - not the current values of its attributes:

d> Why not introduce a new `defface' keyword `:copy-default'?
d> It would define the new face with the same default
d> attribute values as another face.  A copy of those values
d> (actually, of the attributes spec) would be made at
d> `defface' time.

d> Only the _default_ attribute values would be used; the
d> current values of the reference face would have no effect
d> at any time.

IOW, this is a relation between two face _definitions_ (two `defface's), not
between a `defface' and another face's current attribute values.

Yes, this would likely require saving the referenced face spec in some form in
the byte-compiled reference file, if that is not done already.  And it would
require copying that spec to the receiver at its `defface' eval time.

[Another possibility is to allow copying when the receiver `defface' is
byte-compiled, not just when it is eval'd.  Dunno whether that would be a good
idea or whether it could introduce differences (eval vs compile time).]

No, I haven't tried to think this through, and especially not in terms of
implementation.  Just throwing the idea out there as food for thought by others
more qualified.

T> For example, if I customize face x, how will face y
T> know the next time emacs is started to use the old
T> values of face x and not the new customized values?

See above.  It would always look to face x's _definition_ (`defface'), not to
its current attribute values.  Customization of face x should have no effect.

T> Somehow the defface would need to know to only copy
T> the values from face x the first time it is defined/used
T> i.e. from the first session that the face is used and
T> to then keep those values for future sessions.

Not sure I follow you.  It would _never_ copy the current values.  It would copy
only the attributes spec from the reference face, that is, the part of the
definition that is called for being copied.

But yes, that spec would need to be available, in the source reference file (no
problem) and in the byte-compiled reference file.  A copy chain could presumably
handled: if C copies from B which copies from A, then B's defface would be
eval'd before C's defface.

There might be some problems to work out, but I don't imagine they would be
insurmountable.  (But I know nothing about face implementation or
byte-compilation.)

T> Without this, you would simply have a form of delayed
T> inheritance, which is likely going to be even more
T> confusing that using normal inheritance as the change
T> would be session dependent and time delayed.

I don't follow.  Again, it is only the default-attributes spec that would be
copied, not the current attribute values.  Access to that spec is all that is
needed, I think.  And it should be possible to provide that access through the
byte-compiled reference file (as well as through the source reference file) -
that is, the file whose `defface' is copied from.

But again, I might well be missing a thing or two (or three...).

T> This seems like a non-trivial modification to the
T> defface mechanism as it introduces a new state/time
T> dimension i.e. copy face x attributes unless face y
T> attributes have already been copied in a previous session.

The current attribute values would never be copied.  Only the default-attributes
spec would be copied - that is, the part of the reference face's definition (its
`defface') that we specified to be copied.

T> Maybe defface could have some type of 'initform'
T> exstension that is used to configure the face if it
T> has no custom setting. The result would need to be
T> written to the custom-faces section so that it is
T> only run once. 

I don't follow.  But maybe you just misunderstood and thought I meant that the
current attribute values would be copied?




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

* Re: Eliminating a couple of independent face definitions
  2011-02-07 22:12                       ` Drew Adams
@ 2011-02-08  3:51                         ` Tim Cross
  2011-02-08 15:26                           ` Drew Adams
  0 siblings, 1 reply; 43+ messages in thread
From: Tim Cross @ 2011-02-08  3:51 UTC (permalink / raw)
  To: Drew Adams; +Cc: Philipp Haselwarter, emacs-devel

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

On Tue, Feb 8, 2011 at 9:12 AM, Drew Adams <drew.adams@oracle.com> wrote:

> T> I do see some possible implementation issues with
> T> the copy concept though. One problem could be
> T> determining when to do the copy. If I have face x
> T> and then define face y using your proposed copy
> T> semantics, how would you control when that copy occurs.
>
> I have not thought about implementation, nor will I really try to. ;-)  I
> leave
> that to others more knowledgable.
>
> I did say what I thought was called for wrt copy time, however: copy when
> the
> `defface' with the `:copy-default' gets eval'd.  Normally, that's at load
> time.
>
> And I did mention that only the default-attributes spec would be copied
> from the
> reference face - not the current values of its attributes:
>
> d> Why not introduce a new `defface' keyword `:copy-default'?
> d> It would define the new face with the same default
> d> attribute values as another face.  A copy of those values
> d> (actually, of the attributes spec) would be made at
> d> `defface' time.
>
> d> Only the _default_ attribute values would be used; the
> d> current values of the reference face would have no effect
> d> at any time.
>
> IOW, this is a relation between two face _definitions_ (two `defface's),
> not
> between a `defface' and another face's current attribute values.
>
> Yes, this would likely require saving the referenced face spec in some form
> in
> the byte-compiled reference file, if that is not done already.  And it
> would
> require copying that spec to the receiver at its `defface' eval time.
>
> [Another possibility is to allow copying when the receiver `defface' is
> byte-compiled, not just when it is eval'd.  Dunno whether that would be a
> good
> idea or whether it could introduce differences (eval vs compile time).]
>
> No, I haven't tried to think this through, and especially not in terms of
> implementation.  Just throwing the idea out there as food for thought by
> others
> more qualified.
>
> T> For example, if I customize face x, how will face y
> T> know the next time emacs is started to use the old
> T> values of face x and not the new customized values?
>
> See above.  It would always look to face x's _definition_ (`defface'), not
> to
> its current attribute values.  Customization of face x should have no
> effect.
>
> T> Somehow the defface would need to know to only copy
> T> the values from face x the first time it is defined/used
> T> i.e. from the first session that the face is used and
> T> to then keep those values for future sessions.
>
> Not sure I follow you.  It would _never_ copy the current values.  It would
> copy
> only the attributes spec from the reference face, that is, the part of the
> definition that is called for being copied.
>
> But yes, that spec would need to be available, in the source reference file
> (no
> problem) and in the byte-compiled reference file.  A copy chain could
> presumably
> handled: if C copies from B which copies from A, then B's defface would be
> eval'd before C's defface.
>
> There might be some problems to work out, but I don't imagine they would be
> insurmountable.  (But I know nothing about face implementation or
> byte-compilation.)
>
> T> Without this, you would simply have a form of delayed
> T> inheritance, which is likely going to be even more
> T> confusing that using normal inheritance as the change
> T> would be session dependent and time delayed.
>
> I don't follow.  Again, it is only the default-attributes spec that would
> be
> copied, not the current attribute values.  Access to that spec is all that
> is
> needed, I think.  And it should be possible to provide that access through
> the
> byte-compiled reference file (as well as through the source reference file)
> -
> that is, the file whose `defface' is copied from.
>
> But again, I might well be missing a thing or two (or three...).
>
> T> This seems like a non-trivial modification to the
> T> defface mechanism as it introduces a new state/time
> T> dimension i.e. copy face x attributes unless face y
> T> attributes have already been copied in a previous session.
>
> The current attribute values would never be copied.  Only the
> default-attributes
> spec would be copied - that is, the part of the reference face's definition
> (its
> `defface') that we specified to be copied.
>
> T> Maybe defface could have some type of 'initform'
> T> exstension that is used to configure the face if it
> T> has no custom setting. The result would need to be
> T> written to the custom-faces section so that it is
> T> only run once.
>
> I don't follow.  But maybe you just misunderstood and thought I meant that
> the
> current attribute values would be copied?
>
> Like you say, it probably needs to be looked at by someone with more
knowledge. My thoughts were that since defface is a macro, we can only get
at its specification at load time. However, can we get to that specification
before emacs has loaded the custom faces section or user init files that
would/could modify that specification?

If we can't, then I guess it would be necessary to somehow parse the
original source or byte-codes, which begins to make the whole thing a lot
more complex - I'm not even sure how you would identify the appropriate file
that contains the defface spec.

Complex doesn't mean it cannot be done, but it does mean it will be far less
likely that anyone would want to implement it. If nobody is willing to
implement it, then it all becomes academic and nothing happens. Thats why I
think it is important to also consider implementation implications, even if
we don't plan to actually do the implementation ourselves. At worst, it does
no harm, at best, it might provide the seed for implementation or a better
idea. I also suspect 'ideas' which don't attempt to examine implementation
implications are unlikely to be taken vary seriously or gain any traction.

I think its necessary to have a clear grasp of emacs' initialization
process/order to really know what options there are to implement a 'copy'
facility. I'm beginning to think that a better alternative would be to add a
simple command for developers that would just, given a face name, put its
current definition into the kill ring/register/buffer in a format
appropriate for using in a defface definition. Essentially, this would be a
convenience wrapper around find-face-definition that extracts the definition
from the source file. This seems less complicated and may still provide an
easy way for developers to copy an existing full face definition without
having to manually locate the sources, cut and then paste. Could mean less
reason to not provide a fully defined face definition. The disadvantage is
that once set, it would not reflect any changes in the default definition of
the face it is copied from, which would be the main advantage of your
suggestion. However, I suspect the defface definitoin of most faces rarely
changes, especially for some of the older base faces that have been around
for a while and have probably already been tweaked to be as good as they can
be.

Tim

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

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

* RE: Eliminating a couple of independent face definitions
  2011-02-07  0:59               ` Drew Adams
  2011-02-07  1:30                 ` Tim Cross
@ 2011-02-08 13:58                 ` Davis Herring
  2011-02-08 14:33                   ` Drew Adams
  1 sibling, 1 reply; 43+ messages in thread
From: Davis Herring @ 2011-02-08 13:58 UTC (permalink / raw)
  To: Drew Adams
  Cc: 'Tim Cross', emacs-devel, 'Philipp Haselwarter'

> Sure - just use a copy instead of a pointer.

Having D copy from B is equivalent to having them both inherit from a new
face A with B's previous definition.  With the inheritance, the user does
have the option to change both of them at once if desired.  And we already
have inheritance.

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.



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

* RE: Eliminating a couple of independent face definitions
  2011-02-08 13:58                 ` Davis Herring
@ 2011-02-08 14:33                   ` Drew Adams
  2011-02-08 15:34                     ` Davis Herring
  0 siblings, 1 reply; 43+ messages in thread
From: Drew Adams @ 2011-02-08 14:33 UTC (permalink / raw)
  To: herring; +Cc: 'Tim Cross', emacs-devel, 'Philipp Haselwarter'

> > Sure - just use a copy instead of a pointer.
> 
> Having D copy from B is equivalent to having them both 
> inherit from a new face A with B's previous definition.

It is certainly not equivalent.
Just customize A to see the difference.

> With the inheritance, the user does have the option
> to change both of them at once if desired.

Precisely why they are not equivalent.  Read the thread, if you have not
already, for why inheritance is not the be-all and end-all.
 
> And we already have inheritance.

Hammer...nail.




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

* RE: Eliminating a couple of independent face definitions
  2011-02-08  3:51                         ` Tim Cross
@ 2011-02-08 15:26                           ` Drew Adams
  2011-02-08 19:10                             ` Philipp Haselwarter
  0 siblings, 1 reply; 43+ messages in thread
From: Drew Adams @ 2011-02-08 15:26 UTC (permalink / raw)
  To: 'Tim Cross'; +Cc: 'Philipp Haselwarter', emacs-devel

T> Like you say, it probably needs to be looked at by
T> someone with more knowledge.

Yes.  My recollection of the thread a few years back around Richard's changes to
setting face attributes informs me that those who are familiar with face
implementation (e.g. Yidong) are much better placed to think about how these
things might be done.  I remember it seeming to be fairly complex.  It is also
they who would decide _whether_ such things should be done.

T> My thoughts were that since defface is a macro, we
T> can only get at its specification at load time.

I don't think so, but I could be wrong.  AFAIK, you can do this at any time to
get the default spec:
(get SOME-FACE 'face-defface-spec).

(I thought there was also a way for a user to restore that default in Customize,
but it seems I was mistaken about that.  You can `Show Lisp Expression', but
that just shows the current value, not the default expression from the
`defface'.)

T> However, can we get to that specification before emacs
T> has loaded the custom faces section or user init files
T> that would/could modify that specification?

I don't think we need to - see above.  But again, I'm not going to try to get
involved with implementing this.  If those who are face-implementation
knowledgable are interested they will get involved.  If not, so be it.




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

* RE: Eliminating a couple of independent face definitions
  2011-02-08 14:33                   ` Drew Adams
@ 2011-02-08 15:34                     ` Davis Herring
  2011-02-08 16:16                       ` Drew Adams
  0 siblings, 1 reply; 43+ messages in thread
From: Davis Herring @ 2011-02-08 15:34 UTC (permalink / raw)
  To: Drew Adams
  Cc: 'Tim Cross', emacs-devel, 'Philipp Haselwarter'

>> Having D copy from B is equivalent to having them both
>> inherit from a new face A with B's previous definition.
>
> It is certainly not equivalent.
> Just customize A to see the difference.

But A didn't exist before, so that's a new feature, not a difference per
se.  If we wanted, we could prevent the user from even knowing about A
(have `customize-face' not support it), and they would be equivalent.  So
surely this is better...?

>> With the inheritance, the user does have the option
>> to change both of them at once if desired.
>
> Precisely why they are not equivalent.  Read the thread, if you have not
> already, for why inheritance is not the be-all and end-all.

I'm quite surprised that you didn't leap at this idea.  Since when is
offering the user a choice a bad thing?  If they don't want to customize
A, they won't, and they'll then have exactly the same set of options that
the copying idea would give them.

Now, I must say that I've realized an imperfection in my idea: if Emacs
defines D but not B (and thus no one bothers to make A), an external
package that defines B must either inherit from D or copy-paste its
definition.  But faces in Emacs that seem worthy of inheritance by anyone
may be mechanically transformed into D-A pairs to avoid the problem.

>> And we already have inheritance.
>
> Hammer...nail.

David J. Wheeler might disagree.  (And you were talking about how it might
be non-trivial to implement the copying idea.)

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.



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

* RE: Eliminating a couple of independent face definitions
  2011-02-08 15:34                     ` Davis Herring
@ 2011-02-08 16:16                       ` Drew Adams
  2011-02-08 17:40                         ` Lennart Borgman
  2011-02-08 19:10                         ` Davis Herring
  0 siblings, 2 replies; 43+ messages in thread
From: Drew Adams @ 2011-02-08 16:16 UTC (permalink / raw)
  To: herring; +Cc: 'Tim Cross', emacs-devel, 'Philipp Haselwarter'

> >> Having D copy from B is equivalent to having them both
> >> inherit from a new face A with B's previous definition.
> >
> > It is certainly not equivalent.
> > Just customize A to see the difference.
> 
> But A didn't exist before, so that's a new feature, not a 
> difference per se.  If we wanted, we could prevent the user
> from even knowing about A (have `customize-face' not support
> it), and they would be equivalent.

That comes back to my earlier suggestion of "inheriting" from constant
(uncustomizable) "faces".

> So surely this is better...?

I don't think so.  But it is a possibility.

I think it is better to make clear the difference: inheriting from a
customizable face and either "inheriting" from an uncustomizable "face" or
copying the default spec from an ordinary (customizable) face.

With `:copy-default' vs `:inherit' it is clear what is going on.  With just
`:inherit' it is less obvious what's happening.  I prefer my later suggestion to
my earlier one (which you are repeating).
> >> With the inheritance, the user does have the option
> >> to change both of them at once if desired.
> >
> > Precisely why they are not equivalent.  Read the thread, if 
> > you have not already, for why inheritance is not the be-all
> > and end-all.
> 
> If they don't want to customize A, they won't, and they'll
> then have exactly the same set of options that the copying
> idea would give them.

And if they do customize A then they end up with changes down the line to other
(inheriting) faces.  They cannot customize A without causing those side effects.

That's the point.  Users must take all of that into consideration when deciding
whether they want to customize A.  Which means that they also need to be aware
(become aware) of the inheritance relations - the fact that fiddling with A will
in fact affect faces B, D,...Z.

A user might well want to customize A, but without having repercussions
elsewhere.  S?he cannot do that, and that fact will affect whether s?he
ultimately "wants" to customize A.  After becoming fully aware of the
inheritance relations, that is. ;-)

Inheritance couples faces together.  That's both its strength and its weakness
(of course).  If a user can customize face A, then any face that inherits from
it (directly or indirectly) is affected.  It's as simple as that.

A pointer is not a copy.  Both pointers and copies are useful.  If the aim is to
get a full face definition without the trouble of coding it explicitly, then you
can either point to (inherit) an existing definition or copy one.

Note BTW (e.g. Tim) that inheritance does _not_ in fact point to an existing
face definition.  It points to a _current value_.  And just because face A might
have a nice, full default-attributes definition, covering light and dark
backgrounds, tty's, etc., that does not mean that the _current_ value of A is a
full definition.  Nothing prevents a user from customizing A to change it's
nice, full definition to simply a `Red' foreground in all cases.




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

* Re: Eliminating a couple of independent face definitions
  2011-02-08 16:16                       ` Drew Adams
@ 2011-02-08 17:40                         ` Lennart Borgman
  2011-02-08 19:10                         ` Davis Herring
  1 sibling, 0 replies; 43+ messages in thread
From: Lennart Borgman @ 2011-02-08 17:40 UTC (permalink / raw)
  To: Drew Adams; +Cc: Philipp Haselwarter, Tim Cross, emacs-devel

On Tue, Feb 8, 2011 at 5:16 PM, Drew Adams <drew.adams@oracle.com> wrote:
>
> That comes back to my earlier suggestion of "inheriting" from constant
> (uncustomizable) "faces".

That is totally out of the question for me.

Take for example a vision impaired person who want to customize a face
to make it more readable. Then inheritance is very important. Without
it s/he would have an enormous job to customize all relevant faces.



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

* RE: Eliminating a couple of independent face definitions
  2011-02-08 16:16                       ` Drew Adams
  2011-02-08 17:40                         ` Lennart Borgman
@ 2011-02-08 19:10                         ` Davis Herring
  1 sibling, 0 replies; 43+ messages in thread
From: Davis Herring @ 2011-02-08 19:10 UTC (permalink / raw)
  To: Drew Adams
  Cc: 'Tim Cross', emacs-devel, 'Philipp Haselwarter'

> That comes back to my earlier suggestion of "inheriting" from constant
> (uncustomizable) "faces".

I don't see the point in having anything be uncustomizable, though -- just
give it a name `function-name-base' and perhaps a docstring that says
"customize only if you want a global effect; otherwise customize the
inheritors".  More on this idea below.

> A user might well want to customize A, but without having repercussions
> elsewhere.  S?he cannot do that, and that fact will affect whether s?he
> ultimately "wants" to customize A.  After becoming fully aware of the
> inheritance relations, that is. ;-)

No, they can't want that (barring simple confusion).  The important bit is
that no code uses A directly for anything, ever.  The code uses D (and B)
and thus uses A's attributes, but it never uses A.  If the user wants just
D to be different, they customize it (to override some/all of what it
inherits from A, or to inherit from something else entirely).  If they
choose to customize A it is _because_ they want everything changed along
with it; they are preferring "consistency" to "specificity".

As for becoming aware, that's why the convention of "this face exists
solely for inheritance" must be specified.  But that's not hard for the
user to notice, so I don't consider it a problem.

Davis

-- 
This product is sold by volume, not by mass.  If it appears too dense or
too sparse, it is because mass-energy conversion has occurred during
shipping.



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

* Re: Eliminating a couple of independent face definitions
  2011-02-08 15:26                           ` Drew Adams
@ 2011-02-08 19:10                             ` Philipp Haselwarter
  0 siblings, 0 replies; 43+ messages in thread
From: Philipp Haselwarter @ 2011-02-08 19:10 UTC (permalink / raw)
  To: emacs-devel

please stop cc'ing me..


-- 
Philipp Haselwarter




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

* Re: color-complement for defface
  2011-02-04 17:57             ` color-complement for defface (was: Eliminating a couple of independent face definitions) Ted Zlatanov
@ 2011-02-14 18:11               ` Ted Zlatanov
  2011-02-20 17:44                 ` Julien Danjou
  0 siblings, 1 reply; 43+ messages in thread
From: Ted Zlatanov @ 2011-02-14 18:11 UTC (permalink / raw)
  To: emacs-devel

On Fri, 04 Feb 2011 11:57:30 -0600 Ted Zlatanov <tzz@lifelogs.com> wrote: 

TZ> On Fri, 04 Feb 2011 11:26:49 +0100 Julien Danjou <julien@danjou.info> wrote: 
JD> On Thu, Feb 03 2011, Drew Adams wrote:
>>> FWIW, for this I simply use the complements of the light-background default
>>> colors as the dark-background colors.  That is not necessarily ideal, but it at
>>> least is reasonable and consistent.  It is also very quick to do, given some
>>> code (e.g. hexrgb.el or palette.el) that quickly gives you color complements.

JD> color.el included in Emacs 24 as `color-complement' so you can even use
JD> it in your defface directly, I think.

TZ> It would be nice if an example of that usage was part of the manual.
TZ> Even better would be if defining a face could automatically use the
TZ> complement (e.g. by setting the background to 'complement).

TZ> Julien, do you want to propose a patch to the manual?

I'll take an example, at least, and write the rest.

TZ> Does anyone have comments on a defface modification to let
TZ> color-complement pick the background automatically if requested?  I
TZ> don't know how hard that would be to write, but I want to know if it's
TZ> even acceptable.

Second try.  I still think this is a worthy improvement to Emacs.

Ted




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

* Re: color-complement for defface
  2011-02-14 18:11               ` color-complement for defface Ted Zlatanov
@ 2011-02-20 17:44                 ` Julien Danjou
  2011-03-10 19:09                   ` Ted Zlatanov
  0 siblings, 1 reply; 43+ messages in thread
From: Julien Danjou @ 2011-02-20 17:44 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

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

On Mon, Feb 14 2011, Ted Zlatanov wrote:

> TZ> Julien, do you want to propose a patch to the manual?
>
> I'll take an example, at least, and write the rest.

Sorry Ted. I had your mail tagged important, but well…

Here's a very simple example on how to use it:

#+begin_src: emacs-lisp
(defface myface
  (let ((color "red"))
    `((((class color) (background light))
       (:foreground ,color))
      (((class color) (background dark))
        (:foreground ,(apply 'color-rgb->hex (color-complement color))))
      (t nil)))
  "My face.")
#+end_src

Obviously, a new function/macro could be created to automate this use of
color-complement.

-- 
Julien Danjou
❱ http://julien.danjou.info

[-- Attachment #2: Type: application/pgp-signature, Size: 835 bytes --]

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

* Re: color-complement for defface
  2011-02-20 17:44                 ` Julien Danjou
@ 2011-03-10 19:09                   ` Ted Zlatanov
  2011-03-10 19:11                     ` Ted Zlatanov
  0 siblings, 1 reply; 43+ messages in thread
From: Ted Zlatanov @ 2011-03-10 19:09 UTC (permalink / raw)
  To: emacs-devel

On Sun, 20 Feb 2011 18:44:04 +0100 Julien Danjou <julien@danjou.info> wrote: 

JD> Here's a very simple example on how to use it:
JD> #+begin_src: emacs-lisp
JD> (defface myface
JD>   (let ((color "red"))
JD>     `((((class color) (background light))
JD>        (:foreground ,color))
JD>       (((class color) (background dark))
JD>         (:foreground ,(apply 'color-rgb->hex (color-complement color))))
JD>       (t nil)))
JD>   "My face.")
JD> #+end_src

A patch that shows how to do this in lispref/display.texi is attached.
I put it under the :foreground property documentation for `defface' but
it's right next to the :background property too, so it should be obvious
to a reader how to use it to do the opposite, setting the background to
a complement.

JD> Obviously, a new function/macro could be created to automate this use of
JD> color-complement.

The :foreground and background properties can only be a string
currently, so it may be even simpler to allow them to be the form
(complement "color-string").  That should be a clean extension.  If not,
I guess a function or a macro could do it too.

Ted




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

* Re: color-complement for defface
  2011-03-10 19:09                   ` Ted Zlatanov
@ 2011-03-10 19:11                     ` Ted Zlatanov
  0 siblings, 0 replies; 43+ messages in thread
From: Ted Zlatanov @ 2011-03-10 19:11 UTC (permalink / raw)
  To: emacs-devel

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

(patches?  we don't need no steenkin' patches!)

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: doc-defface-color-complement.patch --]
[-- Type: text/x-diff, Size: 908 bytes --]

=== modified file 'doc/lispref/display.texi'
--- doc/lispref/display.texi	2011-01-31 23:54:50 +0000
+++ doc/lispref/display.texi	2011-03-10 19:03:48 +0000
@@ -2057,6 +2057,21 @@
 black-and-white displays, certain shades of gray are implemented by
 stipple patterns.
 
+You may want to set the foreground automatically in some cases using
+the @code{color-complement} and @code{color-rgb-to-hex} functions from
+the @code{color.el} library.  Here's an example:
+
+@example
+(defface myface
+  (let ((color "red"))
+    `((((class color) (background light))
+       (:foreground ,color))
+      (((class color) (background dark))
+        (:foreground ,(apply 'color-rgb-to-hex (color-complement color))))
+      (t nil)))
+  "My face.")
+@end example
+
 @item :background
 Background color, a string.  The value can be a system-defined color
 name, or a hexadecimal color specification.  @xref{Color Names}.


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

end of thread, other threads:[~2011-03-10 19:11 UTC | newest]

Thread overview: 43+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-02-02  4:05 Eliminating a couple of independent face definitions Chong Yidong
2011-02-02  4:11 ` Lennart Borgman
2011-02-02  5:02   ` Tim Cross
2011-02-02 15:15     ` Drew Adams
2011-02-02 17:17     ` Chong Yidong
2011-02-02 20:33       ` Philipp Haselwarter
2011-02-02 23:01         ` Lennart Borgman
2011-02-03 19:10         ` Drew Adams
2011-02-04  0:12           ` Tim Cross
2011-02-05 22:11             ` Drew Adams
2011-02-07  0:59               ` Drew Adams
2011-02-07  1:30                 ` Tim Cross
2011-02-07 14:09                   ` Drew Adams
2011-02-07 21:14                     ` Tim Cross
2011-02-07 22:12                       ` Drew Adams
2011-02-08  3:51                         ` Tim Cross
2011-02-08 15:26                           ` Drew Adams
2011-02-08 19:10                             ` Philipp Haselwarter
2011-02-08 13:58                 ` Davis Herring
2011-02-08 14:33                   ` Drew Adams
2011-02-08 15:34                     ` Davis Herring
2011-02-08 16:16                       ` Drew Adams
2011-02-08 17:40                         ` Lennart Borgman
2011-02-08 19:10                         ` Davis Herring
2011-02-07  1:08               ` Tim Cross
2011-02-04  0:18           ` Stephen J. Turnbull
2011-02-04  3:55             ` John Yates
2011-02-04  4:56               ` Stephen J. Turnbull
2011-02-04  4:57             ` Jambunathan K
2011-02-05 22:09             ` Drew Adams
2011-02-06  7:11               ` Stephen J. Turnbull
2011-02-04 10:26           ` Julien Danjou
2011-02-04 17:57             ` color-complement for defface (was: Eliminating a couple of independent face definitions) Ted Zlatanov
2011-02-14 18:11               ` color-complement for defface Ted Zlatanov
2011-02-20 17:44                 ` Julien Danjou
2011-03-10 19:09                   ` Ted Zlatanov
2011-03-10 19:11                     ` Ted Zlatanov
2011-02-02 21:24       ` Eliminating a couple of independent face definitions Tim Cross
2011-02-03 16:14       ` Dan Nicolaescu
2011-02-02 17:16   ` Chong Yidong
2011-02-02  9:58 ` Štěpán Němec
2011-02-02 17:05   ` Chong Yidong
2011-02-02 10:05 ` Julien Danjou

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