unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* RE: [Feature request] face property `raise'
@ 2003-04-29 18:19 Wedler, Christoph
  2003-05-13  1:47 ` Richard Stallman
  0 siblings, 1 reply; 23+ messages in thread
From: Wedler, Christoph @ 2003-04-29 18:19 UTC (permalink / raw)
  Cc: emacs-devel

rms@gnu.org writes:

 >   A. Don't define different groups of different properties: make all
 >      properties text properties (or group all special = non-user-defined
 >      text properties together)

 >      B. Just provide one abstraction mechanism for all special properties
 >      with the ability to merge the abstract properties (like face
 >      merging).

 > That is an interesting idea.  Could you try writing a precise
 > spec for what it would look like?

 > One complication will be how to extend face customization to handle an
 > unbounded set of properties.  Right now there is a fixed set of face
 > attributes.


OK, below you find some ideas / a draft about this.  It lists potential
problems and possible options how to solve them.  Comments welcome.


 1. the general mechanism: properties, face merging, priorities of
    overlay/text properties, null-value problem

 2. property names for built-in properties (used by the display engine),

 3. backward compatiblity issues (what to do with the current
    properties, especially the properties display/face/category?)

 4. face customization

 5. implementation


1. GENERAL IDEA ----------------------

The general idea is as follows:

 * All properties are "direct" text/overlay properties (as opposed to
   the current display specs, face attributes etc)

 * One special property (`face') specifies a list of faces (i.e.,
   symbols naming the faces).  A face serves as an abstraction
   mechanism, i.e., defines values for some properties.

   As opposed to the current behaviour (new in Emacs-21?), you cannot
   specify individual properties with the text property `face', because
   this is not needed: face attributes are normal "direct" text/overlay
   properties.

   Questions considered below:

    - face/property merging: a property is defined directly and/or in
      more than one face -- which one to choose?

    - how does the face/property merging relate with properties
      specified by overlays?

    - can a face specify the face property? => see 4

 * One special property (`mouse-face) defines additional
   properties to use when the mouse is "near" the characters with the
   `mouse-face property.


A value for the same property can be specified directly and indirectly
via faces.  For each character, the value can be specified by a text
property and by a property of overlays which apply to that character.
The question is: what is the "final" value for that property?

Before we discuss that, let's look at the 3 kind of values for a
property:

 * Absolute values, like :height 120

 * Relative values, like :height 1.2

 * not specified = "null value".  There are three posibilities how this
   can be specified:

     i.   not specified is different to any specified value.  In this
          case, `get-text-property' and friends must allow to
          distinguish this, i.e., this function must have an optional
          DEFAULT argument.

     ii.  nil = not specified.  In this case, we must have specific
          FALSE values for boolean properties like :underline (and even
          some non-booleans like `image'), e.g., :none.

     iii. :null (or some other value) = not specified.  In this case
          `get-text-property' and friends must return that value if a
          properties is not specified

   Option ii is IMHO the best and most Emacs-like (there are only a few
   boolean-like properties), i would also be OK.


The algorithm which determines the "final" property value to apply for a
given character is as follows.

-----------

final_property (charpos, prop) =
  let value1 = if mouse_over (charpos)
                  then mouse_property (charpos, prop)
                  else <unspecified>,
      value2 = specified_prop (charpos, prop),
      value3 = face_property ('default, prop),
      value4 = built_in_prop_value (prop)
  in
     value1 * value2 * value3 * value4

mouse_property (charpos, prop) =
  let mouse_face = specified_prop (charpos, 'mouse-face)
  in
     if mouse_face.specified
        then face_property (mouse_face, prop)
        else <unspecified>

specified_prop (charpos, prop) =
  let values = map (lambda (overlay) =>
                       object_property (overlay, prop),
                    overlays_in_priority_order_at (charpos));
  in
     -- overlay props       -- text props
     reduce ((*), values) * object_property (charpos, prop)

object_property (charpos_or_overlay, prop) =
  let values = map (lambda (face) =>
                       face_property (face, prop),
                    direct_property (charpos_or_overlay, 'face))
  in
     direct_property (charpos_or_overlay, prop) *
        reduce ((*), values)

direct_property : built_in
face_property : built_in

value1 * value2 =                   -- combining values
   if value1.absolutep then
      value1
   elseif value1.unspecifiedp then
      value2
   elseif (value2.unspecifiedp) then
      value1
   elseif (value2.absolutep) then
      combine_to_absolute_value (value1, value2)
   else
      combine_to_relative_value (value1, value2)
   
-----------

Example: let's assume the following line in a buffer

   FFFTTTOOOOOTTTFFF

All characters in the line have the following text properties:

  - mouse-face = highlight which defines background = green
  - face = dark which defines background = grey

The characters TTTOOOOOTTT have the following text properties:

  - background = orange

There is an overlay over the OOOOO with the properties:

  - face = selection which defines background = yellow

Then we'll see the following background colors:

  - if the mouse is over the line, the complete line has a green
    background,
  - otherwise, the OOOOOs have a yellow background, both TTTs have a
    orange background, the rest a grey background

This shows:

  - the most important distinction is mouse vs not mouse,
  - then: overlay (high prio..low prio) vs text property
  - then: direct property vs face properties



2. PROPERTY NAMES -----------

There are properties used by the display engine (built-in properties)
and properties not used by the display engine (user properties).

I see two possibilities for a naming convention for built-in properties
(I do not discuss the individual names of the properties in this mail):

 a. :prop-name, i.e. a symbol starting with a colon,

 b. prop-name, i.e., another symbol

Currently, text/overlay properties use a, face attribute use b, display
properties use a and space properties (grouped in the display spec
`space') use b.

I would suggest to use b:

 - Advantage: more backward compatible (see 3 below),

 - Advantage: a package-specific property might become a built-in
   property in a future release (e.g., fontified)

 - Disadvantage: potential naming conflict of future built-in properties
   with user properties (this is already the case in Emacs)


3. BACKWARD COMPATIBILITY -----------

Of course, if things change in this area, we have the problem of old
ELisp coding.  The individual problems with possible option:

 a. The display property.  The options:

      i. obsolete, ignore it

     ii. obsolete, use it (lower prio than the new direct properties,
         but higher than indirect properties via faces)

 b. direct face attributes in the face property:

      i. setting such a value for the face property is not allowed
         (signals an error)

     ii. obsolete, such list elements in the value of the face property
         are ignored.

    iii. obsolete, use it (with prio as it is now)

 c. category attribute

      i. obsolete, ignore it

     ii. obsolete, use the symbol as an additional face (with lowest
         prio)

 d. changed names of properties: if we use naming convention 1b, we
    would be more backward compatible

 e. ...

The first options are cleaner and will lead to a faster display engine
and probably easier to implement, the latter options are more backward
compatible.


4. FACE CUSTOMIZATION -----------

If faces serve as a general abstraction mechanism, it must be possible
to customize the corresponding face properties:

 - built-in properties can have special support like provided now for
   all face attributes

 - user properties are stored in an alist/plist (symbol |-> sexpr) and
   customized like any variable having such an alist/plist as :type.

We could use the face attribute `face' for the face inherit mechanism.


5. IMPLEMENTATION -----------

Sorry, I cannot say anything here, how much of the current coding can be
reused / has to be rewritten...


- Christoph

^ permalink raw reply	[flat|nested] 23+ messages in thread
* RE: [Feature request] face property `raise'
@ 2003-05-14 17:45 Wedler, Christoph
  2003-05-14 20:57 ` Miles Bader
  2003-05-15 15:42 ` Richard Stallman
  0 siblings, 2 replies; 23+ messages in thread
From: Wedler, Christoph @ 2003-05-14 17:45 UTC (permalink / raw)
  Cc: emacs-devel

Miles Bader wrote:
 > Your code is not a replacement for category -- category does much more.

What does it more?

 > So why do you keep saying it's necessary only for `backward-compatibility'?

Maybe an answer to your previous mail helps.

 > I'm not sure why it was suggested to be marked `obsolete' anyway --
 > `category' is a general abstraction mechanism for text properties
 > (and overlays), not an ad-hoc display-related property.  [...]

Hmm, half my proposal was about using just one abstraction mechanism for
all properties: faces.  (The other half was about not trying to group
properties into direct text/overlay props, display specs, face
attributes, etc...)

 >> Without extra checks for backward-compatibility properties ('category'
 >> etc) and if the above answer is b, there don't need to be a difference
 >> with the efficiency.  Otherwise, there might be...

 > Do you have any evidence or reasoning to support this conclusion?  It
 > sounds like your change would end up checking for many more
 > properties...

Yes.  The "if the above answer is b" means that Emacs merges each
display spec individually, i.e., the same as the corresponding direct
properties would be merged with my approach.  In other words, the number
of direct text/overlay props, display specs, face attributes, etc which
Emacs would have to check now are not less than the number of direct
properties to check with my approach.

In order not to discuss hypothetical things, I checked the merging of
display properties: the answer is a.  Of course, that's faster, but this
kind of merging is a bit limited.  In other words, the more efficient
implementation depends on the current semantics, which is a bit confusing.

(defun dp ()
  (interactive)
  (insert "MMM M1M M2M M3M M4M MMM")
  (let ((ol (make-overlay (- (point) 11) (- (point) 4))))
    (overlay-put ol 'display '(raise 1.5))
    (put-text-property (- (point) 15) (- (point) 8)
		       'display '(height (+ 2)))
    (put-text-property (- (point) 19) (- (point) 16)
		       'display '((raise 1.5) (height (+ 2))))))

With Emacs, only M1M is higher and raised, M3M is only raised.

In my approach, where `height' and `raise' are direct properties, M3M
would also be higher and raised (with my approach, the code would look
different, of course: no property `display' stuff).

- Christoph

^ permalink raw reply	[flat|nested] 23+ messages in thread
* RE: [Feature request] face property `raise'
@ 2003-05-13 17:17 Wedler, Christoph
  2003-05-13 21:23 ` Miles Bader
  2003-05-14 21:04 ` Richard Stallman
  0 siblings, 2 replies; 23+ messages in thread
From: Wedler, Christoph @ 2003-05-13 17:17 UTC (permalink / raw)
  Cc: emacs-devel

Richard Stallman wrote:

 > 	 iii. :null (or some other value) = not specified.  In this case
 > 	      `get-text-property' and friends must return that value if a
 > 	      properties is not specified

 > In the current design, the value :unspecified means aface attribute is
 > unspecified.  I think that is essentially your option 3.

That's true then for face properties.  If this is generally true, this
would mean:

  - overlay A from S to E with high prio, mouse-face: nil
  - overlay B from S to E with low prio, mouse-face: some-face

 => there is no highlighting when the mouse is in the region S to E

Is this the case?  Or is there highlighting (nil would be the null value for
mouse-face).

 >     I see two possibilities for a naming convention for built-in properties
 >     (I do not discuss the individual names of the properties in this mail):

 >     [...] b. prop-name, i.e., another symbol

 > I would suggest to use b:

I agree.

 > I agree; the backward-compatibility issue is decisive.
 > However, we could recognize the existing face attribute
 > keywords as properties too.

 >      a. The display property.  The options:

 > 	  i. obsolete, ignore it

 > I think that is ok.  The display property is not used in very much
 > code.

Stefan is probably right that this is might not be true anymore...

 >      b. direct face attributes in the face property:

 > 	iii. obsolete, use it (with prio as it is now)

 > That would be necessary.

Sure, if backward-compatibility is an important issue...

 >      c. category attribute

 > 	 ii. obsolete, use the symbol as an additional face (with lowest
 > 	     prio)

 > That would be necessary.

Same as above (backward-compatibility).

 > Meanwhile, there is an important implementation efficiency issue here.
 > The display code currently checks for just a few properties, and that
 > makes it efficient.

It depends -- let's look at an example with overlays both defining
the display property:

  - overlay A from S to E with high prio, display: (D1 a1 D2 a2)
  - overlay B from S to E with low prio,  display: (D1 b1 D3 b3)

What's the "combined" display property?

  a. (D1 a1 D2 a2) ?

  b. (D1 a1 D2 a2 D3 b3)

I assume the answer is a.  But, if we see the properties Dx as
independent properties, b would be the correct answer.  (A similar
example could be constructed with face attributes in the property
`face' -- what's the answer there?)

 > Clean though this new design is, we may need to stay with the old
 > design if we cannot make the new one efficient.

Without extra checks for backward-compatibility properties ('category'
etc) and if the above answer is b, there don't need to be a difference
with the efficiency.  Otherwise, there might be...

- Christoph

^ permalink raw reply	[flat|nested] 23+ messages in thread
* RE: [Feature request] face property `raise'
@ 2003-04-11 19:34 Wedler, Christoph
  2003-04-13 11:22 ` Richard Stallman
  0 siblings, 1 reply; 23+ messages in thread
From: Wedler, Christoph @ 2003-04-11 19:34 UTC (permalink / raw)


Kevin Rodgers wrote:
 > Wedler, Christoph wrote:

 >> 2. the ability to define "abstract" properties and assign one ore more
 >> of them to text (parts).  Each abstract property represents a list of
 >> (concrete) properties (with their values).

 > Isn't that what the `category' property provides?

It looks like.  I wouldn't have guessed that Emacs introduces two
abstraction mechanism, which

 - work completely different (categories: simple symbol, face: list of
   face names with some merging algorithm),

 - work for a different set of properties

I think the error started when Emacs tried to define groups of different
properties:

 1. there are properties called text properties like `invisible',

 2. there are properties called face attributes, which you have to
    specify together in the text property `face' (you can specify
    abstractions = the face name, and concrete properties = the face
    attributes here),

 3. there are properties called display specs, which you have to specify
    together in the text property `display',

 4. there are properties called space properties, which you have to
    specify together in the display spec `space', which you have to
    specify together with other display specs in the text property
    `display'.

This doesn't make anything clearer, it just leads to confusion that you
have to set/get/change different properties differently.  Additionally,
there is no clear distrinction which group you should choose for a new
property.

The distinction is probably not along the lines:

 - how => face property
 - where => display property

if <info:(elisp)Display Property> starts with

   The `display' text property (or overlay property) is used to insert
   images into text, and also control other aspects of how text displays.

Therefore, some properties are defined twice:

 - you can specify the text size via 2 (:height) and 3 (height)
 - you can specify the space width via 3 (space-width) and 4 (:width)

and I could somehow understand that you want to avoid a similar
situation for the `raise' property...

A fix would be:

 A. Don't define different groups of different properties: make all
    properties text properties (or group all special = non-user-defined
    text properties together)

 B. Just provide one abstraction mechanism for all special properties
    with the ability to merge the abstract properties (like face
    merging).

I would use faces as the abstraction mechanism because

 - there is a way how user can customize the face properties
 - there is a package (font-lock) which can set the the abstract
   properties automatically


To categories: I'm not sure whether they help me resetting "my"
properties if the is a function like `remove-yank-excluded-properties'
in subr.el...

- Christoph

^ permalink raw reply	[flat|nested] 23+ messages in thread
* RE: [Feature request] face property `raise'
@ 2003-04-10 18:48 Wedler, Christoph
  2003-04-10 23:14 ` Kevin Rodgers
  0 siblings, 1 reply; 23+ messages in thread
From: Wedler, Christoph @ 2003-04-10 18:48 UTC (permalink / raw)
  Cc: kai.grossjohann

rms@gnu.org writes:

 > It sounds like the main reason you would rather use a face
 > is so that you could specify a symbol and define the symbol's
 > meaning elsewhere.  Currently that can be done for the face
 > property but not for the display property.

 > Is that ability to refer to a symbol whose meaning is
 > defined elsewhere the real issue?

Exactly.  (And we have this symbol already: the symbol naming a face.)

What we like to have in Emacs is:

 1. the ability to assign various properties (let's use the simple name
    for the moment) to text (parts)

 2. the ability to define "abstract" properties and assign one ore more
    of them to text (parts).  Each abstract property represents a list of
    (concrete) properties (with their values).

If you read this you might think that the properties which can be
assigned directly via 1 and those which can be assigned indirectly via 2
should be basically the same.

I would agree.  And this is how things work in HTML/CSS.

In fact, there is already a property which can be assigned via 1 and 2
in Emacs:

 1. the font-size can be assigned via the display property `height'

 2. the font-size can be assigned via the font of a face

    (Emacs new font selection mechanism is already an important step in
    the right direction: the font is not a useful property, the
    font-size, font-family, etc are useful properties, a font is just
    used for the physical representation of a couple of properties.)

Some properties might not be useful to assign indirectly => you provide
them as display properties only.

Some or indeed all properties which are currently just face properties
are probably also useful for direct assignment => you could make them
display properties, too (e.g., color, etc).

In conclusion: Emacs already has abstraction mechanism, it is just
called a bit strangely (face) and presented as standing beside the
display properties.

- Christoph

^ permalink raw reply	[flat|nested] 23+ messages in thread
* RE: [Feature request] face property `raise'
@ 2003-04-09 18:06 Wedler, Christoph
  2003-04-09 18:50 ` Kai Großjohann
  2003-04-10  6:23 ` Richard Stallman
  0 siblings, 2 replies; 23+ messages in thread
From: Wedler, Christoph @ 2003-04-09 18:06 UTC (permalink / raw)


Kai Grossjohann wrote:
 > "Wedler, Christoph" <christoph.wedler@sap.com> writes:

 >> >     I would like to see a face property `raise' with the same
 >> >     semantics as the display property `raise'.
 >> 
 >> > I don't think so.  Raising is not a matter of how something is
 >> > displayed, but where it is displayed.
 >> 
 >> Where something is displayed (at least relatively, and that's what
 >> `raise' is about) is a special case of how something is displayed.

 > [...] So I agree with Richard that it is about "where", and much less
 > about "how".  ({Super,sub,...}scripts are usually smaller, so that
 > the size could be added to "how".)

Hm, my point[1] was that the where-vs-how distinction is not only
unclear[2], it's also not the right distinction to decide which property
should be a display property and which a face property (the property
`image' is clearly "how" and should be made a face property if I follow
Richards reasoning).

IMHO, the right distinction is:

 1. If the value of a property is specific for ONE PART of the buffer,
    it is useful to have this property as a DISPLAY property.

 2. If the value of a property is the same for a CLASS of characters in
    the buffer, it is useful to have this property as a FACE property.

Example for 1: absolute positions (one kind of "where") are specific to
one part of the buffer and are therefore useful for a display property
(e.g., :align-to).

Example for 1: most images shouldn't be displayed more than once in a
buffer, i.e., there are specific to one part of the buffer => the image
property is correctly a display property (images don't have to do
anything with "where", don't they?  ...but clearly with "how"!).  (To
support images as icons, one could imagine `image' as a face property,
too.)

Example for 2: property `raise' (I have already provided 2-3 examples:
super-/subscripts and footnote numbers).  If you have an example where
it is useful to assign this property to one specific part of the buffer
(and want a display property for this), that fine for me, but please
make `raise' a face property, since it is mostly used for a CLASS of
characters.

- Christoph

[1] unfortunately, only the intro of my message was cited, not part of
the rest of the 45 lines...

[2] relative-"where" can be seen as a specific "how".  Kai, of course,
if R (relative-"where") is a subset of W ("where") and H ("how"), and x
(property raise) is an element of R, then x might be more about W than
H, but it remains the fact that x is also an element of H.

^ permalink raw reply	[flat|nested] 23+ messages in thread
* RE: [Feature request] face property `raise'
@ 2003-04-08 17:52 Wedler, Christoph
  2003-04-08 18:54 ` Kai Großjohann
  0 siblings, 1 reply; 23+ messages in thread
From: Wedler, Christoph @ 2003-04-08 17:52 UTC (permalink / raw)
  Cc: emacs-devel

 >     I would like to see a face property `raise' with the same semantics as
 >     the display property `raise'.

 > I don't think so.  Raising is not a matter of how something is
 > displayed, but where it is displayed.

Where something is displayed (at least relatively, and that's what
`raise' is about) is a special case of how something is displayed.

The question of face (style-class like in HTML/CSS would be a better
name) vs display property is determined by the following:

  * display property: determines the display style of ONE SPECIFIC
    buffer part,

  * face property: assigns a style class to a buffer part.  By
    customizing the face, you determine the display style of all buffer
    parts having this style class.

In my previous mail, I've given you an example where face properties are
much better (super-/subscripts: after all, you want to raise subscripts
consistently by e.g. 5 pixels), a face for footnote numberings would be
another example.  (I also gave 5 general reasons.)

I've yet to see an example where display properties are useful for
`raise', except for some Emacs painting package.  (But even that example
would not invalidate my examples, i.e., a face property `raise' would
still be useful.)

Looking how things are done outside the Emacs world would also be
useful: let's assume HTML wouldn't have a SUP element.  Then everyone
would advice you to use

    <SPAN class="SUP">superscript</SPAN>

and define

    SPAN.SUP { vertical-align: super; font-size: smaller; }

instead using

    <SPAN style="vertical-align: super; font-size: smaller;">
       superscript
    </SPAN>

for every superscript.  In Emacs, the recommendation (using the class
attribute) corresponds to setting a face, the non-recommendation (using
the style attribute) corresponds to setting display properties.

 > Some unsophisticated text formatters treated superscript as if it
 > were a font, but more sophisticated ones don't.

I don't know where this is related to the question whether a face
property `raise' would be useful.

- Christoph

^ permalink raw reply	[flat|nested] 23+ messages in thread
* [Feature request] face property `raise'
@ 2003-04-07 17:33 Wedler, Christoph
  2003-04-08  6:45 ` Richard Stallman
  0 siblings, 1 reply; 23+ messages in thread
From: Wedler, Christoph @ 2003-04-07 17:33 UTC (permalink / raw)


I would like to see a face property `raise' with the same semantics as
the display property `raise'.  At least, I would like to see that such a
property is considered a good idea.

A face in Emacs is a named collection of graphical attributes (see
<info:(elisp)Faces>).

There are a couple of advantages of faces versus display properties
(`image' and STRING don't really relate well to the other display
properties), I'll demonstrate them with an example `subscript-face':

 1. With faces, you have a nice mechanism which abstracts the logical
    property "being a subscript" from some physical properties (e.g.,
    "baseline raised by 0.3ex", "font-size 80%", ...)

 2. Users can use the usual way to customize things.

 3. There is a standard mechanism to "merge" faces.  Packagages which
    use text properties have to define their own merging code.

 4. Since faces are named, packages can easily remove the faces from a
    text region.  If a package A uses text properties, it's much more
    difficult just to remove the properties where A is the owner.

 5. There is a package which can set faces according to the syntactical
    structure of the code/text: font-lock.  We could easily define
    font-lock keywords for super- and subscripts.

    (I know that the font-lock.el in the Emacs development version has
    the variable `font-lock-extra-managed-props' which you might think
    might be used to set display properties, but it doesn't help
    too much due to 3 and 4 above.)

- Christoph

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

end of thread, other threads:[~2003-05-15 15:42 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-04-29 18:19 [Feature request] face property `raise' Wedler, Christoph
2003-05-13  1:47 ` Richard Stallman
2003-05-13  2:22   ` Miles Bader
2003-05-14 21:05     ` Richard Stallman
2003-05-13 14:13   ` Stefan Monnier
2003-05-14 21:04     ` Richard Stallman
  -- strict thread matches above, loose matches on Subject: below --
2003-05-14 17:45 Wedler, Christoph
2003-05-14 20:57 ` Miles Bader
2003-05-15 15:42 ` Richard Stallman
2003-05-13 17:17 Wedler, Christoph
2003-05-13 21:23 ` Miles Bader
2003-05-14 21:04 ` Richard Stallman
2003-04-11 19:34 Wedler, Christoph
2003-04-13 11:22 ` Richard Stallman
2003-04-10 18:48 Wedler, Christoph
2003-04-10 23:14 ` Kevin Rodgers
2003-04-09 18:06 Wedler, Christoph
2003-04-09 18:50 ` Kai Großjohann
2003-04-10  6:23 ` Richard Stallman
2003-04-08 17:52 Wedler, Christoph
2003-04-08 18:54 ` Kai Großjohann
2003-04-07 17:33 Wedler, Christoph
2003-04-08  6:45 ` 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).