[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

before- and after-string issues

From: martin rudalics
Subject: before- and after-string issues
Date: Sat, 14 May 2005 09:42:58 +0200
User-agent: Mozilla Thunderbird 1.0 (Windows/20041206)

The issues listed below are not very troubling.  I came accross them
when I tried to install a before-string at bob that does _not_ get
highlighted when `point' equals `point-min'.  That's the only one I
really care about and did not get around.  Anyway, here is the list:

A. Highlighting and face inheritance

Let O denote an overlay ranging from buffer positions S to T and A an
after-string of O produced by something like

  (let ((O (make-overlay S T)))
    (overlay-put O 'after-string A))

Putting `mark' before S and `point' after T highlights the entire
overlay but not its after-string.  Placing `mark' after T and `point'
after the character following T does not highlight a single character of
O but does highlight the after-string.  This is counterintuitive.

Moreover, A inherits face properties from the character displayed after
A and not from the last character of the overlay.  Counterintuitive too.

I could imagine to resolve this problem by installing some kind of
barrier: The idea is to never merge face properties - wherever they come
around the current position as follows:

(1) positive-length after-strings

(2) zero-length before-strings

=== barrier ===

(3) zero-length after-strings

(4) positive-length before-strings

Within groups overlays would be ordered by priority, length ...

Strings in (1) and (2) would inherit all face properties including
highlighting from the first preceding character.  If there is no such
character _no_ property would be inherited.  Strings in (3) and (4)
would inherit face properties from the first following character.  If
there is none no properties would be inherited.  It seems a matter of
taste whether the buffer should be widened before checking for the
existence of these characters.

B. After-string precedes before-string

Let OA and OB denote two different empty overlays residing at the same
buffer position.  If OB has a before-string and OA has an after-string
the after-string is displayed in front of the before-string.  The
barrier sketched above would handle this in a more intuitive way.

C. Redisplay

Let O denote a front-advance, rear-advance overlay with a newline
terminated before-string residing at `point-min' (O's end-position does
not matter here) like:

  (let ((O (make-overlay (point-min) (point-min) nil t t)))
    (overlay-put O 'before-string "<<<\n"))

Suppose `point' equals `point-min', hence the cursor appears after O.
When I now insert a character say "!" it gets displayed in front of O
like this:


The cursor is still after O.  When I now insert a newline I get



that is, the before-string is displayed twice with the cursor after the
second incarnation.  Redisplay removes the double.

(In the Elisp documentation text "If READ-ADVANCE is non-`nil', text
inserted at the beginning of the overlay is included in the overlay."
you should replace "READ" by "REAR" and "beginning" by "end".  However I
would replace "front-advance" by "front-exclude" and "rear-advance" by
"rear-include" anyway.)

A related problem occurs with two before-string enhanced overlays where
OA denotes an empty front- and rear-advance overlay and OB a front- and
rear-stay-behind overlay like

  (let ((OA (make-overlay (point-at-bol) (point-at-bol) nil t t))
        (OB (make-overlay (point-at-bol) (point-at-eol))))

Inserting a character at the beginning of these overlays has OB's
before-string disappear from the screen.  Redisplay brings it back.

D. Empty and non-empty overlays at bob

Consider two overlays O1 and O2:

  (let ((O1 (make-overlay (point-min) (point-min)))
        (O2 (make-overlay (point-min) (1+ (point-min)))))
    (overlay-put O1 'before-string "1")
    (overlay-put O2 'before-string "2"))

Placing `mark' at (1+ (point-min)) and (de-)highlighting the region by
moving `point' between (point-min) and (1+ (point-min)) interchanges "1"
and "2" along with movement of `point'.  Placing `mark' at the position
(+ (point-min) 2) and (de-)highlighting the region by moving `point'
between (+ (point-min) 2) and (1+ (point-min)) shortly interchanges "1"
and "2" before reverting to the previous state.

E. Mouse-face

Consider two overlays with a mouse-face property, S-face, T-face, and
A-face some faces, S > T:

  (let ((OS (make-overlay S T))
        (OT (make-overlay T T))
        (A (propertize "A" 'mouse-face 'A-face)))
    (overlay-put OS 'mouse-face 'S-face)
    (overlay-put OS 'after-string A)
    (overlay-put OT 'mouse-face 'T-face))

Moving the mouse over OS highlights A and OT in S-face too.  Face
inheritance from the preceding character seems to work here.  However,
mouse-faces should _not_ get inherited ever.  Note also that OT is
displayed in front of A.

F. Front-/rear-advance insertions

A before-string of a front-advance overlay may be displayed before a
before-string of a front-stay-behind overlay with the same start
position.  When I insert a character at the start position of these
overlays, the before-strings must be interchanged on the display to
accomodate the change.  This looks funny.

Moreover it seems that I cannot insert a character immediately before an
empty, front-advance overlay.  The character appears always after the

In order to handle insertion types one could group overlays as follows:

(1) positive-length, rear-stay-behind after-strings

(2) zero-length, front-stay-behind before-strings

=== possible insertion position ===

(3) positive-length, rear-advance after-strings

(4) zero-length, front-advance before-strings

=== barrier ===

(5) zero-length, rear-stay-behind after-strings

(6) positive-length, front-stay-behind before-strings

=== possible insertion position ===

(7) zero-length, rear-advance after-strings

(8) positive-length, front-advance before-strings

A final aside: `reftex-sel.el' from 14.01.2005 still insists that
"before-string property is broken in Emacs".

reply via email to

[Prev in Thread] Current Thread [Next in Thread]