unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* reducing defface redundancy
@ 2002-04-20  3:12 Miles Bader
  2002-04-20  7:14 ` Eli Zaretskii
                   ` (2 more replies)
  0 siblings, 3 replies; 33+ messages in thread
From: Miles Bader @ 2002-04-20  3:12 UTC (permalink / raw)


In order to be optimal on disparate display types, many defface clauses
end up having a bunch of clauses with almost the same contents, but
varying one or two attributes.  With the ability to query individual
features, this might become even worse.  So this is a suggestion on a
way to reduce the redundancy of defface specs.

The basic idea is to allow using a lisp vector ([...]) as a kind of `or'
expression in the attribute part of a defface clause.  Each element of
vector is an attribute list, and the first one that is entirely
`supportable' (that is, `display-capable-p' returns true for all of its
attributes) is used.  [note that this is one reason why I suggested
using face attribute names/values as the argument to
`display-capable-p']

This way, in many cases common attributes could be factored out, and
the variant parts would become just a vector of possibilities with
emacs choosing the first one that works.  I think this style is very
natural, and might even result in better faces because

Currently the grammar of defface specs is something like this:

  SPECS     ::= (CLAUSE ...)
  CLAUSE    ::= (TESTS ATTRIBUTE...)
              | (TESTS (ATTRIBUTE ...))         ; old style attribute list
  ATTRIBUTE ::= ATTR-NAME ATTR-VALUE  
  TESTS     ::= t | (TEST ...)
  TEST      ::= (TEST-NAME TEST-ARG...)

Here's one possibility for a more flexible specification that uses the
`or' vector idea above, and I think should be backward compatible:

  SPECS     ::= (CLAUSE ...)
  CLAUSE    ::= ATTRIBUTE
              | (TESTS CLAUSE...)               ; traditional top-level style
              | [SPECS ...]                     ; `or' vector style
              | (TESTS (ATTRIBUTE ...))         ; old style attribute list
  ATTRIBUTE ::= ATTR-NAME ATTR-VALUE  
  TESTS     ::= t | (TEST ...)
  TEST      ::= (TEST-NAME TEST-ARG...)

In addition to adding the `or' vectors, this makes defface specs
recursive in a way that allows omitting the traditional clause list when
it's not necessary (e.g., when currently you just have `t' as the list
of tests).

Thus _very_ simple defface specs are possible:

  (defface annoying
    '(:foreground "red" :background "yellow"))

which seems very natural.

The `italic' example from my earlier message can become:

  (defface italic
    [(:slant italic) (:underline t)])

And if someone wants a face that's both `emphasized' and yellow, he can do:

  (defface emph-yellow
    '(:foreground "yellow"
      [(:bold t) (:slant italic) (:underline t)]))

which will make either a bold, italic, or underlined yellow face,
depending on what the display is capable of.

Since the new specification is recursive, it's possible to put normal
defface clauses at sub-levels, if that's desirable for factoring out
common attributes; for instance, this is often :

(defface subtle-yet-underlined-mode-line
  '(:inherit mode-line
    :underline t
    (((background light) :background "grey90")
     ((background dark)  :background "grey10"))))

So what'ya think?  It shouldn't be hard to implement, given the
existance of `display-capable-p', it's backward-compatible, and whizzy
as all hell (well, I think so anyway)...

Thanks,

-Miles

-- 
"Most attacks seem to take place at night, during a rainstorm, uphill,
 where four map sheets join."   -- Anon. British Officer in WW I

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

* Re: reducing defface redundancy
  2002-04-20  3:12 reducing defface redundancy Miles Bader
@ 2002-04-20  7:14 ` Eli Zaretskii
  2002-04-20 15:59 ` Per Abrahamsen
  2002-04-21 20:02 ` Richard Stallman
  2 siblings, 0 replies; 33+ messages in thread
From: Eli Zaretskii @ 2002-04-20  7:14 UTC (permalink / raw)
  Cc: emacs-devel

> From: Miles Bader <miles@gnu.org>
> Date: 20 Apr 2002 12:12:57 +0900
> 
> (defface subtle-yet-underlined-mode-line
>   '(:inherit mode-line
>     :underline t
>     (((background light) :background "grey90")
>      ((background dark)  :background "grey10"))))
> 
> So what'ya think?  It shouldn't be hard to implement, given the
> existance of `display-capable-p', it's backward-compatible, and whizzy
> as all hell (well, I think so anyway)...

I'm not sure this will make defface's we have less redundant and
repetitive, but I think the feature as such can be useful.

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

* Re: reducing defface redundancy
  2002-04-20  3:12 reducing defface redundancy Miles Bader
  2002-04-20  7:14 ` Eli Zaretskii
@ 2002-04-20 15:59 ` Per Abrahamsen
  2002-04-20 17:35   ` Eli Zaretskii
                     ` (2 more replies)
  2002-04-21 20:02 ` Richard Stallman
  2 siblings, 3 replies; 33+ messages in thread
From: Per Abrahamsen @ 2002-04-20 15:59 UTC (permalink / raw)
  Cc: emacs-devel

Miles Bader <miles@gnu.org> writes:

> So this is a suggestion on a way to reduce the redundancy of defface
> specs.

Please, always remember that the usability of the defface UI is far
more important than the usability of the defface Lisp interface.
defface is really a sibling to defcustom.

So when making changes to the defface, please consisder first:

1. How will these changes affect the UI?

2. Will the changes make the already far too complex UI more or less
   complex? 

3. If it make the UI more complex, is the added power really worth the
   complexity?

It is really easy to invent all kinds of smart stuff to the defface
spec at the Lisp level.  Comming up with good UI is way harder.

Actually, I think it would be far more useful to work on the UI,
determine what it needs to become simpler or more useful, and then,
afterwards, start to think about how to translate these changes to the
Lisp interface.

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

* Re: reducing defface redundancy
  2002-04-20 15:59 ` Per Abrahamsen
@ 2002-04-20 17:35   ` Eli Zaretskii
  2002-04-21  9:12     ` Per Abrahamsen
  2002-04-20 17:41   ` Alex Schroeder
  2002-04-21  2:00   ` Miles Bader
  2 siblings, 1 reply; 33+ messages in thread
From: Eli Zaretskii @ 2002-04-20 17:35 UTC (permalink / raw)
  Cc: miles, emacs-devel

> From: Per Abrahamsen <abraham@dina.kvl.dk>
> Date: Sat, 20 Apr 2002 17:59:41 +0200
> 
> It is really easy to invent all kinds of smart stuff to the defface
> spec at the Lisp level.  Comming up with good UI is way harder.

Sorry, I don't understand: what UI?  defface is not a user-level
feature, it's a programmer feature.  Did you mean API, perhaps?

If you do mean the API, I believe Miles was trying to make it better,
more convenient.  The need to repeat the same face attributes over
and over is a PITA, IMHO.

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

* Re: reducing defface redundancy
  2002-04-20 15:59 ` Per Abrahamsen
  2002-04-20 17:35   ` Eli Zaretskii
@ 2002-04-20 17:41   ` Alex Schroeder
  2002-04-21  2:00   ` Miles Bader
  2 siblings, 0 replies; 33+ messages in thread
From: Alex Schroeder @ 2002-04-20 17:41 UTC (permalink / raw)


Per Abrahamsen <abraham@dina.kvl.dk> writes:

> Actually, I think it would be far more useful to work on the UI,
> determine what it needs to become simpler or more useful, and then,
> afterwards, start to think about how to translate these changes to the
> Lisp interface.

I agree with Per.  Just remember what happened to custom-theme and
friends...  There just was no UI to actually handy all that ilisp
cleverness.  And compare the success of color-theme.el to that.  It is
much simpler (the elisp is a no-brainer), but the UI works.  And is
the important thing.

Alex.
-- 
http://www.electronicintifada.net/diaries/index.html
http://www.us-israel.org/jsource/US-Israel/hr2506c.html

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

* Re: reducing defface redundancy
  2002-04-20 15:59 ` Per Abrahamsen
  2002-04-20 17:35   ` Eli Zaretskii
  2002-04-20 17:41   ` Alex Schroeder
@ 2002-04-21  2:00   ` Miles Bader
  2002-04-21  9:17     ` Per Abrahamsen
  2002-04-22  7:47     ` Richard Stallman
  2 siblings, 2 replies; 33+ messages in thread
From: Miles Bader @ 2002-04-21  2:00 UTC (permalink / raw)
  Cc: emacs-devel

Per Abrahamsen <abraham@dina.kvl.dk> writes:
> Please, always remember that the usability of the defface UI is far
> more important than the usability of the defface Lisp interface.
> defface is really a sibling to defcustom.

They have different constraints though:

Since the defface spec is used by default, by _all_ users of emacs, it
has to be very flexible, and deal with all sorts of possible environments.
The changes I described would be very useful for allowing it to do that
job better.

The face-customization UI on the other hand, is only used by a single
user to define his personal faces; since a given user generally uses
only a small number of different environments, he usually doesn't need
all that flexibility, and is happy with a simpler representation.

> So when making changes to the defface, please consisder first:
> 
> 1. How will these changes affect the UI?

It need not affect it at all.

Remember, by default (unless you select `Show All Display Specs'), the
face customization widget basically tosses out all the clauses of the
current defface spec except the active one.  So, 99% of the time, the
user only deals with the _current_ definition of a face, and is happy.

So, the question is, what should be done for the advanced user, that
really does want to define a complex face using the UI, that works
under different display types?

If my proposal for defface is adopted, I forsee the UI interface
basically `flattening' the defface spec before passing it to the widget.
In other words, it would percolate up all conditional and `or' clauses
to the top-level so the result looks like a traditional defface spec
(in the case of an `or' vector this would result in the vector being
translated into conditional clauses, using the `capable' test I
suggested).

Indeed, this flattening could happen when the defface macro is
expanded, if the flattened form is easier for the infrastructure to
deal with (certainly it would make implementation easier, since
wouldn't have to change any existing functions except defface!).

Here are some examples of flattening:

  1) My previous example `subtle-yet-underlined-mode-line':

      (:inherit mode-line
       :underline t
       ((((background light)) :background "grey90")
        (((background dark))  :background "grey10"))))

     Flattens into:

      ((((background light))
        :inherit mode-line
        :underline t
        :background "grey90")
       (((background dark))  
        :inherit mode-line
        :underline t
        :background "grey10"))

  2) My previous example `emph-yellow':

      (:foreground "yellow"
        [(:weight bold) (:slant italic) (:underline t)]))

     Flattens into:

      ((((capable :weight bold))
        :foreground "yellow"
        :weight bold)
       (((capable :slant italic))
        :foreground "yellow"
        :slant italic)
       (t
        :foreground "yellow"
        :underline t))

So as you can see, my proposal really is just a way to make defface
easier and more convenient.  It won't make the UI any less useful, or
indeed even change it.

And remember, it doesn't just make defface specs less redundant, it also
makes it possible to write _simpler_ defface specs, which more closely
follow the thinking of the face designer.

-Miles
-- 
Next to fried food, the South has suffered most from oratory.
  			-- Walter Hines Page

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

* Re: reducing defface redundancy
  2002-04-20 17:35   ` Eli Zaretskii
@ 2002-04-21  9:12     ` Per Abrahamsen
  0 siblings, 0 replies; 33+ messages in thread
From: Per Abrahamsen @ 2002-04-21  9:12 UTC (permalink / raw)


"Eli Zaretskii" <eliz@is.elta.co.il> writes:

>> From: Per Abrahamsen <abraham@dina.kvl.dk>
>> Date: Sat, 20 Apr 2002 17:59:41 +0200
>> 
>> It is really easy to invent all kinds of smart stuff to the defface
>> spec at the Lisp level.  Comming up with good UI is way harder.
>
> Sorry, I don't understand: what UI?  defface is not a user-level
> feature, it's a programmer feature.

The primary purpose of defface is to give customize-face something to
work on.  Just like the primary purpose of defcustom is to give
information to customize-variable.  Otherwise, we could just as well
use the pre-customize facilities for creating faces and variables.

>  Did you mean API, perhaps?

Certainly NOT!  There are a zillion convenient things one can do on
the API level, that will translate badly or not at all to the UI.

Design the UI *first*, then translate it to the API.  The UI is the
hard part.

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

* Re: reducing defface redundancy
  2002-04-21  2:00   ` Miles Bader
@ 2002-04-21  9:17     ` Per Abrahamsen
  2002-04-21  9:34       ` Miles Bader
  2002-04-22  7:47       ` Richard Stallman
  2002-04-22  7:47     ` Richard Stallman
  1 sibling, 2 replies; 33+ messages in thread
From: Per Abrahamsen @ 2002-04-21  9:17 UTC (permalink / raw)


Please do not install any changes to the API until you have the UI
working, and have confirmed that UI has not become any worse from the
change.  

defface was invented because there was no way a useful UI could be
build from the old, infinitely flexible, way to create faces.

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

* Re: reducing defface redundancy
  2002-04-21  9:17     ` Per Abrahamsen
@ 2002-04-21  9:34       ` Miles Bader
  2002-04-22  7:47       ` Richard Stallman
  1 sibling, 0 replies; 33+ messages in thread
From: Miles Bader @ 2002-04-21  9:34 UTC (permalink / raw)
  Cc: emacs-devel

Per Abrahamsen <abraham@dina.kvl.dk> writes:
> Please do not install any changes to the API until you have the UI
> working, and have confirmed that UI has not become any worse from the
> change.  

Don't worry, I won't.

-Miles
-- 
Quidquid latine dictum sit, altum viditur.

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

* Re: reducing defface redundancy
  2002-04-20  3:12 reducing defface redundancy Miles Bader
  2002-04-20  7:14 ` Eli Zaretskii
  2002-04-20 15:59 ` Per Abrahamsen
@ 2002-04-21 20:02 ` Richard Stallman
  2002-04-22  0:28   ` Miles Bader
  2 siblings, 1 reply; 33+ messages in thread
From: Richard Stallman @ 2002-04-21 20:02 UTC (permalink / raw)
  Cc: emacs-devel

    The basic idea is to allow using a lisp vector ([...]) as a kind of `or'
    expression in the attribute part of a defface clause.

Your proposal makes a number of other changes;
is this the best way to do all of them?

I don't see how an "or" construct would be a kind of clause:

      CLAUSE    ::= ATTRIBUTE
		  | (TESTS CLAUSE...)               ; traditional top-level style
		  | [SPECS ...]                     ; `or' vector style

Shouldn't it be a kind of TEST instead?

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

* Re: reducing defface redundancy
  2002-04-21 20:02 ` Richard Stallman
@ 2002-04-22  0:28   ` Miles Bader
  2002-04-22 22:37     ` Richard Stallman
  0 siblings, 1 reply; 33+ messages in thread
From: Miles Bader @ 2002-04-22  0:28 UTC (permalink / raw)
  Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:

>     The basic idea is to allow using a lisp vector ([...]) as a kind of `or'
>     expression in the attribute part of a defface clause.
> 
> Your proposal makes a number of other changes;
> is this the best way to do all of them?
> 
> I don't see how an "or" construct would be a kind of clause:
> 
>       CLAUSE    ::= ATTRIBUTE
> 		  | (TESTS CLAUSE...)             ; traditional top-level style
> 		  | [SPECS ...]                   ; `or' vector style
> 
> Shouldn't it be a kind of TEST instead?

Well, it's not really an `or' in the exact same sense as a typical or
function used in lisp, say.

It's more like the alternatives used for a prolog rule or something, it
tries each element in order until it finds out that is `supportable'.

So a user can just write:

    [ALTERNATIVE1 ALTERNATIVE2 ... DEFAULT]

and the lisp code will effectively say `does the display support all
the attributes ALTERNATIVE1?  If so, lets use that.  If not, does the
display support all the attributes in ALTERNATIVE2?  ...' etc.

I think this often _exactly_ what people are actually _thinking_ when
they design a defface spec (they want a certain effect for the face, and
can think of several physical appearances that might convey it).

[Note that the I've suggested adding the `capability testing' as a
traditional TEST as well, in case someone wants to use that instead.]

I do think, BTW, that the ability to write non-conditional defface
specs with this grammar is a benefit, since I always get annoyed that
I've got to stick in the ((t ...)) crap even when I know I don't need
any tests...  :-)

-Miles
-- 
Would you like fries with that?

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

* Re: reducing defface redundancy
  2002-04-21  9:17     ` Per Abrahamsen
  2002-04-21  9:34       ` Miles Bader
@ 2002-04-22  7:47       ` Richard Stallman
  1 sibling, 0 replies; 33+ messages in thread
From: Richard Stallman @ 2002-04-22  7:47 UTC (permalink / raw)
  Cc: emacs-devel

    Please do not install any changes to the API until you have the UI
    working, and have confirmed that UI has not become any worse from the
    change.  

I agree.

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

* Re: reducing defface redundancy
  2002-04-21  2:00   ` Miles Bader
  2002-04-21  9:17     ` Per Abrahamsen
@ 2002-04-22  7:47     ` Richard Stallman
  2002-04-22  8:15       ` Miles Bader
  1 sibling, 1 reply; 33+ messages in thread
From: Richard Stallman @ 2002-04-22  7:47 UTC (permalink / raw)
  Cc: abraham, emacs-devel

    Remember, by default (unless you select `Show All Display Specs'), the
    face customization widget basically tosses out all the clauses of the
    current defface spec except the active one.  So, 99% of the time, the
    user only deals with the _current_ definition of a face, and is happy.

Simple face customization is clean now because it affects just one
alternative, and it is easy and well-defined to select just the
alternative that applies.

With your propose defface change, the attributes actually specified
would not come from a single alternative in a simple way.  So the
customization of the active parts of the defface spec would raise
difficult issues.  If the user adds a new attribute, where in the
structure does it go?

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

* Re: reducing defface redundancy
  2002-04-22  7:47     ` Richard Stallman
@ 2002-04-22  8:15       ` Miles Bader
  2002-04-23  0:24         ` Richard Stallman
  0 siblings, 1 reply; 33+ messages in thread
From: Miles Bader @ 2002-04-22  8:15 UTC (permalink / raw)
  Cc: abraham, emacs-devel

Richard Stallman <rms@gnu.org> writes:
> Simple face customization is clean now because it affects just one
> alternative, and it is easy and well-defined to select just the
> alternative that applies.
> 
> With your propose defface change, the attributes actually specified
> would not come from a single alternative in a simple way.  So the
> customization of the active parts of the defface spec would raise
> difficult issues.  If the user adds a new attribute, where in the
> structure does it go?

I replied to Per's question about this in some detail, but here's the
short version: You can think of the grammar I outlined as merely being a
convenient shorthand for the defface user; it's not hard to convert it
into exactly the same `simple but redundant' 2-level format that the UI
uses now.

In fact, this transformation can be done in defface (or rather, in the
code the defface macro expands into), before any other part of emacs
sees it; this would keep implementation simple.

Of course, in order to support the display `capability querying'
feature, a new type of test has to be added to the set that the UI and
other parts of the face code recognize, but that's an orthogonal issue
to the change in the defface grammar (and it's not hard to do either).

-Miles
-- 
.Numeric stability is probably not all that important when you're guessing.

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

* Re: reducing defface redundancy
  2002-04-22  0:28   ` Miles Bader
@ 2002-04-22 22:37     ` Richard Stallman
  0 siblings, 0 replies; 33+ messages in thread
From: Richard Stallman @ 2002-04-22 22:37 UTC (permalink / raw)
  Cc: emacs-devel

    So a user can just write:

	[ALTERNATIVE1 ALTERNATIVE2 ... DEFAULT]

    and the lisp code will effectively say `does the display support all
    the attributes ALTERNATIVE1?  If so, lets use that.  If not, does the
    display support all the attributes in ALTERNATIVE2?  ...' etc.

I see.  This is certainly a convenient thing to do in Lisp terms.
And this, by itself, would not pose a problem for Custom.

What does pose a problem for Custom is the nesting of constructs
that you also propose to add.

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

* Re: reducing defface redundancy
  2002-04-22  8:15       ` Miles Bader
@ 2002-04-23  0:24         ` Richard Stallman
  2002-04-23  1:36           ` Miles Bader
  0 siblings, 1 reply; 33+ messages in thread
From: Richard Stallman @ 2002-04-23  0:24 UTC (permalink / raw)
  Cc: abraham, emacs-devel

    I replied to Per's question about this in some detail, but here's the
    short version: You can think of the grammar I outlined as merely being a
    convenient shorthand for the defface user; it's not hard to convert it
    into exactly the same `simple but redundant' 2-level format that the UI
    uses now.

I am not convinced that is a good solution to the issue of what
Custom should do.  Suppose I give a face one unconditional attribute,
and suppose the user customizes that attribute with Custom.
Should his customization always be recorded only for the one kind
of screen he is actually using?

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

* Re: reducing defface redundancy
  2002-04-23  0:24         ` Richard Stallman
@ 2002-04-23  1:36           ` Miles Bader
  2002-04-24 17:54             ` Richard Stallman
  0 siblings, 1 reply; 33+ messages in thread
From: Miles Bader @ 2002-04-23  1:36 UTC (permalink / raw)
  Cc: abraham, emacs-devel

Richard Stallman <rms@gnu.org> writes:
>     You can think of the grammar I outlined as merely being a
>     convenient shorthand for the defface user; it's not hard to convert it
>     into exactly the same `simple but redundant' 2-level format that the UI
>     uses now.
> 
> I am not convinced that is a good solution to the issue of what
> Custom should do.  Suppose I give a face one unconditional attribute,
> and suppose the user customizes that attribute with Custom.
> Should his customization always be recorded only for the one kind
> of screen he is actually using?

Well, there are two interfaces used by the (current) custom face UI:

  * The current-display-type-only interface, which is the default.  This
    displays the face used by the current display, and if the user
    changes something in the face and saves it, the current face
    attributes become unconditional for all display types (trashing any
    display-type-conditionalization that was defined by the defface
    specification for that face).

  * The many-display-types interface, which the user has to explicitly
    enable.  This displays all the various conditional faces that
    defface defined, and allows the user to change any of them.  This
    doesn't trash any information.

My suggestion of flattening the grammar, and using the current UI,
wouldn't change any of this.

If the user choose the 2nd (many-display-types) UI, and there's a
`common' attribute in the defface spec, he will see that common
attribute replicated in each face displayed by the face UI.  Having to
tweak it for each displayed face might be a little annoying, but it
seems to make sense from a UI point of view (a more complex UI that
actually mirrored the defface grammar could solve this, perhaps, but the
additional complexity could make the situation much more confusing).

However, for the 1st UI (current-display-type-only), it might be a
useful try and detect changes to `common' attributes and preserve a
modified version of the original defface spec, instead of just trashing
it as the UI does now.

Anyway, my point is that the new grammar won't make anything worse, and
may provide some additional leeway for improvement.  However, I don't
think clever handling of common attributes in the UI is necessarily a
requirement for an initial implementation (given that there doesn't seem
to be any complaint about the current UI trashing things).

-Miles
-- 
o The existentialist, not having a pillow, goes everywhere with the book by
  Sullivan, _I am going to spit on your graves_.

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

* Re: reducing defface redundancy
  2002-04-23  1:36           ` Miles Bader
@ 2002-04-24 17:54             ` Richard Stallman
  2002-04-24 20:06               ` Miles Bader
  2002-07-03  6:38               ` Miles Bader
  0 siblings, 2 replies; 33+ messages in thread
From: Richard Stallman @ 2002-04-24 17:54 UTC (permalink / raw)
  Cc: abraham, emacs-devel

    Well, there are two interfaces used by the (current) custom face UI:

      * The current-display-type-only interface, which is the default.

This is the hard case.  Yes you can flatten the nested spec and have custom
operate on that, but the hard part is how to alter the nested spec
based on the user's customizations.

    However, for the 1st UI (current-display-type-only), it might be a
    useful try and detect changes to `common' attributes and preserve a
    modified version of the original defface spec, instead of just trashing
    it as the UI does now.

Getting this right is the hard part.

    Anyway, my point is that the new grammar won't make anything worse, and
    may provide some additional leeway for improvement.

Yes it makes something worse.  It makes the effect of cutsomizing
the face problematical.  At present that is not so.

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

* Re: reducing defface redundancy
  2002-04-24 17:54             ` Richard Stallman
@ 2002-04-24 20:06               ` Miles Bader
  2002-04-25  9:52                 ` Per Abrahamsen
  2002-07-03  6:38               ` Miles Bader
  1 sibling, 1 reply; 33+ messages in thread
From: Miles Bader @ 2002-04-24 20:06 UTC (permalink / raw)
  Cc: abraham, emacs-devel

Richard Stallman <rms@gnu.org> writes:
>     Anyway, my point is that the new grammar won't make anything worse, and
>     may provide some additional leeway for improvement.
> 
> Yes it makes something worse.  It makes the effect of cutsomizing
> the face problematical.  At present that is not so.

Huh?  Customizing a face now _throws away_ information (that is, every
thing defined by the defface spec except that for the current display),
unless the user selects the more complicated interface.  That seems
pretty problematical to me...

Throwing away this information is bad, I think -- but that's a property
of the (current) UI.

I'm mystified as to how you think that things would be _worse_.

-Miles
-- 
I'm beginning to think that life is just one long Yoko Ono album; no rhyme
or reason, just a lot of incoherent shrieks and then it's over.  --Ian Wolff

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

* Re: reducing defface redundancy
  2002-04-24 20:06               ` Miles Bader
@ 2002-04-25  9:52                 ` Per Abrahamsen
  2002-04-26  3:18                   ` Richard Stallman
  0 siblings, 1 reply; 33+ messages in thread
From: Per Abrahamsen @ 2002-04-25  9:52 UTC (permalink / raw)
  Cc: rms, emacs-devel

Miles Bader <miles@gnu.org> writes:

> Richard Stallman <rms@gnu.org> writes:
>>     Anyway, my point is that the new grammar won't make anything worse, and
>>     may provide some additional leeway for improvement.
>> 
>> Yes it makes something worse.  It makes the effect of cutsomizing
>> the face problematical.  At present that is not so.
>
> Huh?  Customizing a face now _throws away_ information (that is, every
> thing defined by the defface spec except that for the current display),
> unless the user selects the more complicated interface.  That seems
> pretty problematical to me...

It is a bug somewhere deep down in the code.  It is _supposed_ to only
affect the "current" display spec, and leave all others as they were.
I was surpised when I learned of this bug, but couldn't figure out how
to fix it.

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

* Re: reducing defface redundancy
  2002-04-25  9:52                 ` Per Abrahamsen
@ 2002-04-26  3:18                   ` Richard Stallman
  0 siblings, 0 replies; 33+ messages in thread
From: Richard Stallman @ 2002-04-26  3:18 UTC (permalink / raw)
  Cc: miles, emacs-devel

    It is a bug somewhere deep down in the code.  It is _supposed_ to only
    affect the "current" display spec, and leave all others as they were.
    I was surpised when I learned of this bug, but couldn't figure out how
    to fix it.

Did you at least figure out how the bug happens?
With that starting point, maybe someone else can design a good fix.

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

* Re: reducing defface redundancy
  2002-04-24 17:54             ` Richard Stallman
  2002-04-24 20:06               ` Miles Bader
@ 2002-07-03  6:38               ` Miles Bader
  2002-07-03  9:31                 ` Kai Großjohann
                                   ` (2 more replies)
  1 sibling, 3 replies; 33+ messages in thread
From: Miles Bader @ 2002-07-03  6:38 UTC (permalink / raw)
  Cc: abraham, emacs-devel

This email is about my suggestion a while ago for adding a more
convenient grammar for defface; I've appended some of the original
message to the end of this one for reference.

If you recall, the main objection to this was that it might not interact
well with the customize-face UI, in particular with the default mode
where customize-face only presents the current face attributes (as
opposed to the optional `display all face specs' mode, where it presents
the whole conditional face definition, with all the various
possibilities broken out).

After that discussion, my thought was that the proper way to deal with
this is actually simple:  when the user changes some attribute, find
out at what `level' in the defface specification the changed attribute
came from, and apply the user's change there; for any attributes _not_
in the original defface spec, just apply them at the `top' (root)
level.  I think this would be very natural (probably more so than the
current behavior, and certainly no worse).  I also think it would be
simple to implement.

So for instance consider the following example:

   (defface subtle-yet-underlined-mode-line
     '(:inherit mode-line
       :underline t
       (((background light) :background "grey90")
        ((background dark)  :background "grey10"))))

If the user customizes this face, he'll be presented with the _current_
list of face attributes; if he's on a dark-background display, that
will be (:inherit mode-line :underline t :background "grey10").

With the suggested algorithm, if he changes `:inherit mode-line',
`:underline t', or adds a previously unused attribute, that change will
apply to all environments.  However, if he changes `:background ...',
the change will only apply to the relevant branch of the `conditional'
in the defface spec.  So basically the rewritten face spec will look
like the original face-spec except with the user's changes integrated.

What do you think of this suggestion?

-Miles



Excerpt from original message:

In order to be optimal on disparate display types, many defface clauses
end up having a bunch of clauses with almost the same contents, but
varying one or two attributes.  With the ability to query individual
features, this might become even worse.  So this is a suggestion on a
way to reduce the redundancy of defface specs.

The basic idea is to allow using a lisp vector ([...]) as a kind of `or'
expression in the attribute part of a defface clause.  Each element of
vector is an attribute list, and the first one that is entirely
`supportable' (that is, `display-capable-p' returns true for all of its
attributes) is used.

This way, in many cases common attributes could be factored out, and the
variant parts would become just a vector of possibilities with emacs
choosing the first one that works.  I think this style is very natural,
and might even result in better faces because it would be easier to
write good face specifications (currently, you have to duplicate a lot
of stuff, and it can get tedious to keep everything updated).

Here's one possibility for a more flexible specification that uses the
`or' vector idea above, and I think should be backward compatible:

  SPECS     ::= (CLAUSE ...)
  CLAUSE    ::= ATTRIBUTE
              | (TESTS CLAUSE...)               ; traditional top-level style
              | [SPECS ...]                     ; `or' vector style
              | (TESTS (ATTRIBUTE ...))         ; old style attribute list
  ATTRIBUTE ::= ATTR-NAME ATTR-VALUE  
  TESTS     ::= t | (TEST ...)
  TEST      ::= (TEST-NAME TEST-ARG...)

In addition to adding the `or' vectors, this makes defface specs
recursive in a way that allows omitting the traditional clause list when
it's not necessary (e.g., when currently you just have `t' as the list
of tests).

Thus _very_ simple defface specs are possible:

  (defface annoying
    '(:foreground "red" :background "yellow"))

which seems very natural.

The `italic' example from my earlier message can become:

  (defface italic
    [(:slant italic) (:underline t)])

And if someone wants a face that's both `emphasized' and yellow, he can do:

  (defface emph-yellow
    '(:foreground "yellow"
      [(:bold t) (:slant italic) (:underline t)]))

which will make either a bold, italic, or underlined yellow face,
depending on what the display is capable of.

Since the new specification is recursive, it's possible to put normal
defface clauses at sub-levels, if that's desirable for factoring out
common attributes; for instance, this is often :

(defface subtle-yet-underlined-mode-line
  '(:inherit mode-line
    :underline t
    (((background light) :background "grey90")
     ((background dark)  :background "grey10"))))

-- 
"Most attacks seem to take place at night, during a rainstorm, uphill,
 where four map sheets join."   -- Anon. British Officer in WW I

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

* Re: reducing defface redundancy
  2002-07-03  6:38               ` Miles Bader
@ 2002-07-03  9:31                 ` Kai Großjohann
  2002-07-03 14:50                 ` Kim F. Storm
  2002-07-08 18:20                 ` Richard Stallman
  2 siblings, 0 replies; 33+ messages in thread
From: Kai Großjohann @ 2002-07-03  9:31 UTC (permalink / raw)
  Cc: rms, abraham, emacs-devel

Miles Bader <miles@lsi.nec.co.jp> writes:

> With the suggested algorithm, if he changes `:inherit mode-line',
> `:underline t', or adds a previously unused attribute, that change will
> apply to all environments.  However, if he changes `:background ...',
> the change will only apply to the relevant branch of the `conditional'
> in the defface spec.  So basically the rewritten face spec will look
> like the original face-spec except with the user's changes integrated.

I like this idea.  It is simple and easy to grok for the user.

At a later time, people can think about enhancing Custom such that
more complicated things can be done, eg. using Emacs running on a
light background to change the color for dark backgrounds.

kai
-- 
A large number of young women don't trust men with beards.  (BFBS Radio)

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

* Re: reducing defface redundancy
  2002-07-03  6:38               ` Miles Bader
  2002-07-03  9:31                 ` Kai Großjohann
@ 2002-07-03 14:50                 ` Kim F. Storm
  2002-07-08 18:20                 ` Richard Stallman
  2 siblings, 0 replies; 33+ messages in thread
From: Kim F. Storm @ 2002-07-03 14:50 UTC (permalink / raw)
  Cc: rms, abraham, emacs-devel

Miles Bader <miles@lsi.nec.co.jp> writes:

> After that discussion, my thought was that the proper way to deal with
> this is actually simple:  when the user changes some attribute, find
> out at what `level' in the defface specification the changed attribute
> came from, and apply the user's change there; for any attributes _not_
> in the original defface spec, just apply them at the `top' (root)
> level.  I think this would be very natural (probably more so than the
> current behavior, and certainly no worse).  I also think it would be
> simple to implement.
> 
> What do you think of this suggestion?

Sounds fine.

-- 
Kim F. Storm <storm@cua.dk> http://www.cua.dk

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

* Re: reducing defface redundancy
  2002-07-03  6:38               ` Miles Bader
  2002-07-03  9:31                 ` Kai Großjohann
  2002-07-03 14:50                 ` Kim F. Storm
@ 2002-07-08 18:20                 ` Richard Stallman
  2002-07-09  1:25                   ` Miles Bader
  2 siblings, 1 reply; 33+ messages in thread
From: Richard Stallman @ 2002-07-08 18:20 UTC (permalink / raw)
  Cc: abraham, emacs-devel

    With the suggested algorithm, if he changes `:inherit mode-line',
    `:underline t', or adds a previously unused attribute, that change will
    apply to all environments.  However, if he changes `:background ...',
    the change will only apply to the relevant branch of the `conditional'
    in the defface spec.  So basically the rewritten face spec will look
    like the original face-spec except with the user's changes integrated.

    What do you think of this suggestion?

I think users will find this surprising and inconsistent.  In
addition, we want to have buffer-local face definitions, and that will
make this issue even more complex.

This is an instance of the general conflict between WYSIWYG editing
and conditional formatting commands.  That suggests we should
completely separate the WYSIWYG layer from the conditional command
later.  Here's a proposal.

You can customize a face for the current display, for the current
session, looking at a simple list of attributes, but you cannot save
this.  Or you can customize the conditional commands that define the
face, by looking at the whole structure of them.  That kind of
customization you can save if you wish.

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

* Re: reducing defface redundancy
  2002-07-08 18:20                 ` Richard Stallman
@ 2002-07-09  1:25                   ` Miles Bader
  2002-07-09 18:51                     ` Richard Stallman
  2002-07-09 18:51                     ` Richard Stallman
  0 siblings, 2 replies; 33+ messages in thread
From: Miles Bader @ 2002-07-09  1:25 UTC (permalink / raw)
  Cc: abraham, emacs-devel

Richard Stallman <rms@gnu.org> writes:
>     So basically the rewritten face spec will look like the original
>     face-spec except with the user's changes integrated.
> 
> I think users will find this surprising and inconsistent.

Can you say why you think this?  I think it gets about as close as we
can to `doing the intuitive thing' when a someone uses the simple face
customization -- it's really impossible to always do things correctly,
since we'd have to read the user's mind.

Remember that the way I suggest integrating the user's changes follows
the structure set up by the face creator, and possible user
customizations are one thing to think about when creating the face.

> In addition, we want to have buffer-local face definitions, and that
> will make this issue even more complex.

It depends on how buffer-local face definitions are implemented.  My
feeling is that there _shouldn't_ be real buffer-specific faces, but
rather a way of remapping faces within a buffer.  For instance foo-mode
could make the `foo-default' be used as the default face within its
buffers; if the user want's to change it, they'd have customize
`foo-default', not `default' (though the customization widget could
notice that there's a buffer-local remapping, and ask the user `do you
want to edit the global `default' face, or the `foo-default' face being
used in this buffer').

> You can customize a face for the current display, for the current
> session, looking at a simple list of attributes, but you cannot save
> this.  Or you can customize the conditional commands that define the
> face, by looking at the whole structure of them.  That kind of
> customization you can save if you wish.

Well that would certainly get rid of the ambiguity, but I suspect that
most users would absolutely hate it (I certainly would) -- it attempts
to solve a fairly rare problem (face customizations that have surprising
results on other display types) by making the _normal case_ more
inconvenient and confusing!

I think this is a case where it's possible to do a good job
automatically most of the time.  Since the problems that might arise are
fairly minor (the face looks a bit funny), I think they're well
justified by the extra convenience and utility for users in the common
case from doing things automatically.

-Miles
-- 
The secret to creativity is knowing how to hide your sources.
  --Albert Einstein

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

* Re: reducing defface redundancy
  2002-07-09  1:25                   ` Miles Bader
@ 2002-07-09 18:51                     ` Richard Stallman
  2002-07-09 18:51                     ` Richard Stallman
  1 sibling, 0 replies; 33+ messages in thread
From: Richard Stallman @ 2002-07-09 18:51 UTC (permalink / raw)
  Cc: abraham, emacs-devel

    Can you say why you think this?  I think it gets about as close as we
    can to `doing the intuitive thing' when a someone uses the simple face
    customization -- it's really impossible to always do things correctly,
    since we'd have to read the user's mind.

The user who operates at that level won't be shown, and may not know,
at which level the various attributes were specified.  If person
changes two attributes, and one change affects all terminals while the
other does not, that will be a surprise.

Here is an idea.  Let's eliminate the concept of nested or "common"
attribute specs, and make the list look like a simple cond.  However,
the face to inherit from should be unconditional.  Thus, when you want
common attributes for face A in various conditions, you put them in
another face B and make A inherit from B.

This way, either all the attributes specified directly in face A are
general or all are specific to a particular kind of terminal.  Thus,
customizing A is a simple matter, and its behavior is clear.

In terms of the actual features of defface, this is almost a return to
the way it was a year ago.  However, using the inheritance we can get
the effect of nesting of specifications.

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

* Re: reducing defface redundancy
  2002-07-09  1:25                   ` Miles Bader
  2002-07-09 18:51                     ` Richard Stallman
@ 2002-07-09 18:51                     ` Richard Stallman
  2002-07-09 20:52                       ` Stefan Monnier
  1 sibling, 1 reply; 33+ messages in thread
From: Richard Stallman @ 2002-07-09 18:51 UTC (permalink / raw)
  Cc: abraham, emacs-devel

    It depends on how buffer-local face definitions are implemented.  My
    feeling is that there _shouldn't_ be real buffer-specific faces, but
    rather a way of remapping faces within a buffer.

Face remapping sounds like a convenient interface for this job.  It
also should be easy to implement.

Meanwhile, what do we really want in regard to frame-specific
attributes?  We want to have faces look different on different kinds
of terminals.  The method we use to specify this is the specs in
defface.  That feature should remain.  But is there any use for
functions to set face attributes per frame?  I see none.  Maybe we
should eliminate that feature.  If we ever want to provide such a
feature in the future, we could provide per-frame face remapping like
the per-buffer face remapping.

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

* Re: reducing defface redundancy
  2002-07-09 18:51                     ` Richard Stallman
@ 2002-07-09 20:52                       ` Stefan Monnier
  2002-07-10 19:20                         ` Richard Stallman
  0 siblings, 1 reply; 33+ messages in thread
From: Stefan Monnier @ 2002-07-09 20:52 UTC (permalink / raw)
  Cc: miles, abraham, emacs-devel

> defface.  That feature should remain.  But is there any use for
> functions to set face attributes per frame?

I actually realized yesterday that I use this feature for my
minibuffer-frame by setting its font and background differently
(which in turns sets the frame-local value of the `default' face).

  (setq minibuffer-frame-alist
	'((minibuffer . only)
	  (top . -1) (left . 0) (user-position . t)
	  (height . 1) (width . 256) (user-size . t)
	  (vertical-scroll-bars . nil)
	  (menu-bar-lines . 0)
	  (tool-bar-lines . 0)
	  (font . "-misc-fixed-bold-r-normal-*-*-100-100-100-*-*-*-*")
	  (background-color . "grey75")
	  (name . "emacs-minibuffer")))

I wouldn't care too much about losing this feature (although I like
the grey background for it).


	Stefan

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

* Re: reducing defface redundancy
  2002-07-09 20:52                       ` Stefan Monnier
@ 2002-07-10 19:20                         ` Richard Stallman
  2002-07-11 17:01                           ` Stefan Monnier
  0 siblings, 1 reply; 33+ messages in thread
From: Richard Stallman @ 2002-07-10 19:20 UTC (permalink / raw)
  Cc: miles, abraham, emacs-devel

If we have buffer-specific face attributes, or buffer-specific face
redirections, you could use them to give the minibuffer different
faces.  Do you ever create a minibuffer window that is part of a
larger frame?  If you do, would you be unhappy if the special face
definitions that you use for the minibuffer were effective there too?

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

* Re: reducing defface redundancy
  2002-07-10 19:20                         ` Richard Stallman
@ 2002-07-11 17:01                           ` Stefan Monnier
  2002-07-12  1:28                             ` Miles Bader
  2002-07-12 17:37                             ` Richard Stallman
  0 siblings, 2 replies; 33+ messages in thread
From: Stefan Monnier @ 2002-07-11 17:01 UTC (permalink / raw)
  Cc: monnier+gnu/emacs, miles, abraham, emacs-devel

> If we have buffer-specific face attributes, or buffer-specific face
> redirections, you could use them to give the minibuffer different faces.

How would we do that ?  As part of the creation of the " *minibuffer-N*"
buffers ?  What about the echo area ?

> Do you ever create a minibuffer window that is part of a larger frame?

No.

> If you do, would you be unhappy if the special face
> definitions that you use for the minibuffer were effective there too?

No.


	Stefan

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

* Re: reducing defface redundancy
  2002-07-11 17:01                           ` Stefan Monnier
@ 2002-07-12  1:28                             ` Miles Bader
  2002-07-12 17:37                             ` Richard Stallman
  1 sibling, 0 replies; 33+ messages in thread
From: Miles Bader @ 2002-07-12  1:28 UTC (permalink / raw)
  Cc: Richard Stallman, abraham, emacs-devel

"Stefan Monnier" <monnier+gnu/emacs@rum.cs.yale.edu> writes:
> > If we have buffer-specific face attributes, or buffer-specific face
> > redirections, you could use them to give the minibuffer different faces.
> 
> How would we do that ?  As part of the creation of the " *minibuffer-N*"
> buffers ?  What about the echo area ?

In my scheme, which uses a variable (call it `face-mappings') to do face
remappings in buffers, there could be a special variable
`echo-area-face-mappings' to handle the echo area.

Perhaps minibuffers should inherit the contents of that variable as the
initial value for their `face-mappings' variable, which would make the keep
the appearance of the echo-area/minibuffer consistent, or maybe their
should be an independent `minibuffer-face-mappings' variable.  In any case,
more specific customizations can be done using `minibuffer-setup-hook'.

-Miles
-- 
P.S.  All information contained in the above letter is false,
      for reasons of military security.

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

* Re: reducing defface redundancy
  2002-07-11 17:01                           ` Stefan Monnier
  2002-07-12  1:28                             ` Miles Bader
@ 2002-07-12 17:37                             ` Richard Stallman
  1 sibling, 0 replies; 33+ messages in thread
From: Richard Stallman @ 2002-07-12 17:37 UTC (permalink / raw)
  Cc: monnier+gnu/emacs, miles, abraham, emacs-devel

    How would we do that ?  As part of the creation of the " *minibuffer-N*"
    buffers ?

We could say that each new minibuffer copies the face redirections of
the first minibuffer.

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

end of thread, other threads:[~2002-07-12 17:37 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-04-20  3:12 reducing defface redundancy Miles Bader
2002-04-20  7:14 ` Eli Zaretskii
2002-04-20 15:59 ` Per Abrahamsen
2002-04-20 17:35   ` Eli Zaretskii
2002-04-21  9:12     ` Per Abrahamsen
2002-04-20 17:41   ` Alex Schroeder
2002-04-21  2:00   ` Miles Bader
2002-04-21  9:17     ` Per Abrahamsen
2002-04-21  9:34       ` Miles Bader
2002-04-22  7:47       ` Richard Stallman
2002-04-22  7:47     ` Richard Stallman
2002-04-22  8:15       ` Miles Bader
2002-04-23  0:24         ` Richard Stallman
2002-04-23  1:36           ` Miles Bader
2002-04-24 17:54             ` Richard Stallman
2002-04-24 20:06               ` Miles Bader
2002-04-25  9:52                 ` Per Abrahamsen
2002-04-26  3:18                   ` Richard Stallman
2002-07-03  6:38               ` Miles Bader
2002-07-03  9:31                 ` Kai Großjohann
2002-07-03 14:50                 ` Kim F. Storm
2002-07-08 18:20                 ` Richard Stallman
2002-07-09  1:25                   ` Miles Bader
2002-07-09 18:51                     ` Richard Stallman
2002-07-09 18:51                     ` Richard Stallman
2002-07-09 20:52                       ` Stefan Monnier
2002-07-10 19:20                         ` Richard Stallman
2002-07-11 17:01                           ` Stefan Monnier
2002-07-12  1:28                             ` Miles Bader
2002-07-12 17:37                             ` Richard Stallman
2002-04-21 20:02 ` Richard Stallman
2002-04-22  0:28   ` Miles Bader
2002-04-22 22:37     ` Richard Stallman

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