unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Miles Bader <miles@lsi.nec.co.jp>
Cc: abraham@dina.kvl.dk, emacs-devel@gnu.org
Subject: Re: reducing defface redundancy
Date: 03 Jul 2002 15:38:43 +0900	[thread overview]
Message-ID: <buo3cv1b9jg.fsf@mcspd15.ucom.lsi.nec.co.jp> (raw)
In-Reply-To: <200204241754.g3OHsIm03235@aztec.santafe.edu>

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

  parent reply	other threads:[~2002-07-03  6:38 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=buo3cv1b9jg.fsf@mcspd15.ucom.lsi.nec.co.jp \
    --to=miles@lsi.nec.co.jp \
    --cc=abraham@dina.kvl.dk \
    --cc=emacs-devel@gnu.org \
    --cc=miles@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).