emacs-devel
[Top][All Lists]
Advanced

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

Re: region-based face-remapping


From: Eli Zaretskii
Subject: Re: region-based face-remapping
Date: Fri, 05 Jan 2024 10:19:46 +0200

> From: JD Smith <jdtsmith@gmail.com>
> Date: Thu, 4 Jan 2024 19:51:46 -0500
> Cc: emacs-devel@gnu.org
> 
>  On Jan 4, 2024, at 1:58 AM, Eli Zaretskii <eliz@gnu.org> wrote:
> 
>  It is called where the 'face' property changes.  The display engine
>  finds the next position where that happens, and arranges for calling
>  face_at_buffer_position when it gets to process that position.  The
>  results of face merging at that position are kept in a cache, to avoid
>  performing it more often than needed.
> 
> This makes sense, thanks.  In the ‘face-remap property scenario, the number 
> of such ‘face
> property-change positions doesn’t actually change.

I don't think this is true. If the 'face-remap' property changes at
some buffer position, the realized faces need to change there,
although the 'face' property didn't change. So with the 'face-remap'
property, we'd need to arrange for face-merging also where the
'face-remap' property changes, not only where the 'face' property
changes.

> But at each such position, the face-merging
> code would have to check for an operative ‘face-remap property at
> point

(Please don't use "point" in this discussion to mean buffer position,
since the display engine doesn't move point while examining buffer
text and its properties.)

> and use it together with
> `face-remapping-alist' to compute the final face merge. I would expect that 
> performance would
> depend on whether the face-merge cache could be (largely) preserved, even as 
> 'face-remap
> properties are added/removed/moved around (typically in repetitive fashion).

The result of merging faces when 'face-remap' is in effect will be
different faces, even though the named faces didn't change.  Those
different faces will be realized and cached, and will have their own
internal face IDs, but will not be exposed to Lisp as symbols, via
APIs such as face-at-point.

>  I do this very thing already in indent-bars[1], globally in the buffer, 
> using face-remapping-alist. 
>  The performance of that remapping is incredibly good in my experience.  So 
> fast in fact that I’ve
>  had to introduce a timer to artificially slow it down since it leads to 
> rapid face flashing during
>  smooth scrolling.
> 
>  How many faces do you have defined on that frame?  I'm guessing not
>  many, or maybe they are all almost identical (differ in only one or
>  two simple attributes).
> 
> Right now it’s just a couple of faces (remove one face-remap, add another).  
> If I had access to a
> ‘face-remap property, I could imagine maybe 10 faces at most being affected 
> as point changes. 
> Each face would change by one or two attributes like foreground, stipple, 
> etc.  

What matters is the total number of named faces defined for the frame,
not the number of faces affected by face-remap.

> I’m sure there could be lots of uses of this type of functionality, but 
> “enhance the focus on one region
> of importance” seems like a very common one.  For example, you might imagine 
> dim/gray version of
> all the font-lock faces outside the “treesitter region of interest” and 
> bright ones inside.  Whenever that
> TS-prescribed region changes, an overlay with a ‘face-remap property gets 
> moved.  

The question I suggest to ponder is whether simpler, less general ways
to implement these features are "good enough".  For example, changing
the appearance of a region of text can be handled by moving an overlay
there with a suitable face definition and high priority; changing the
appearance of text around point can be handled by a special variable
which the display engine will consider when working on text around
point; etc.  IOW, it is not always beneficial to generalize a feature
to the most general abstraction level, certainly not when talking
about Emacs, where a gazillion features related to the proposed new
one are already available and expected to work after the proposed
change.  Adding significant enhancements to Emacs that change previous
design assumptions can easily become a proverbial death by thousand
cuts.



reply via email to

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