From: JD Smith <jdtsmith@gmail.com>
To: Eli Zaretskii <eliz@gnu.org>
Cc: emacs-devel@gnu.org
Subject: Re: region-based face-remapping
Date: Wed, 3 Jan 2024 18:15:04 -0500 [thread overview]
Message-ID: <ABD260AF-CB90-41A5-A417-322212C32C51@gmail.com> (raw)
In-Reply-To: <83edeyzjgp.fsf@gnu.org>
[-- Attachment #1: Type: text/plain, Size: 6056 bytes --]
> On Jan 3, 2024, at 7:31 AM, Eli Zaretskii <eliz@gnu.org> wrote:
>
>> From: JD Smith <jdtsmith@gmail.com>
>>
>> To make the entire face API position-dependent does seem complex. I presume face calculation
>> first checks if there is a valid 'face-remapping-alist’ and does substitutions.
>
> Not exactly. You need to keep in mind that each buffer or string
> position could have several sources of face information, see
> "Displaying Faces" in the ELisp manual for the gory details.So first
> Emacs needs to collect all those faces from all the relevant sources,
> and then it merges them. Face remapping happens during the merge: each
> face that is referenced by a symbol (a.k.a. "named face") is remapped
> if needed.
I see. But if there were a property at the position where Emacs is collecting and merging all the face information, say
‘(face-remap ((some-face . another-face)))
would the merge process be able to easily use this style of remap-information, in addition to the buffer-local 'face-remapping-alist (with the local property taking precedence over the variable)?
>> If 'face-remap were a
>> valid (overlay/text) property, that would seem to obviate any deeper API changes: just add this
>> property where remapping is desired.
>
> I don't think I follow.
>
> The workhorse we use now for obtaining face information is the
> function face_at_buffer_position, which calls the various face-merging
> routines. Those merging routines and their subroutines consider
> face-remapping-alist as part of face merging process outlined above.
> I don't see how we can avoid passing the buffer position to them if
> face-remapping depends on buffer position. Also, those routines will
> now need to perform property or overlay search for the special
> face-remapping property, using the position they are passed.
>
> Am I missing something?
Perhaps we are talking about different things. I was speaking from the point of the view of the ELISP user of the faces API. From the ELISP face API, I don’t see a need to include any new position information for face definition and face property assignment. I think now that you were speaking about the internal API. Internally during the face merge process, I agree there would need to know the properties at a merging-the-face-info point under consideration, which could influence the merge.
Maybe the issue is that face_at_buffer_position is called only at certain special positions, not on each position in the buffer? If so, I can see how your concern about property/overlay search would apply (though what those positions would be I don’t know, since I can assign a different 'face property to arbitrary ranges as small as one character).
>> This may relate to the text-property “planes” discussion from a
>> couple years back. Based on that discussion, perhaps targeting only ‘face is not enough. Is there
>> another approach to “selectively enabling/substituting properties by region”, beyond just
>> text-property-search-forward within the region (looking within ‘display properties too)?
>
> I don't think I understand which discussion you have in mind and how
> it is relevant to the issue at hand.
I meant this discussion (and the related earlier one mentioned, by Stefan M):
https://lists.nongnu.org/archive/html/emacs-devel/2019-11/msg00599.html
My read of that discussion is it would allow external control of various “planes" of a text property: turn some on, others off, without searching through the entirety of the buffer finding and replacing those properties. Similar to layers in a photo editor. Whether that type of external control could be limited to a region I am unsure (though the MMM discussion makes me think that was envisioned). The “layers” or “planes” concept certainly seems related.
>> To make this concrete, how would people approach the following:
>>
>> 1 On point motion, treesitter’s syntax tree is consulted to find an "enclosing semantic context
>> region".
>> 2 Within that region, pre-existing faces (or perhaps other properties) get updated to a “highlighted”
>> variant.
>> 3 Outdated/prior regions have the highlighted variants removed.
>>
>> Since you don’t know in advance how large such regions might be, it seems problematic to search
>> and replace all the various faces or other properties.
>
> How do you envision to do items 2 and 3 above? IOW, how do you
> "update pre-existing faces"?
In an ideal scenario, by applying a text or overlay property '(face-remap ((some-face . some-highlight-face))) to that region.
> The naïve solution, of somehow changing
> the face attributes on the fly, will be a performance killer, since
> currently any change in any named face invalidates all the faces we
> already know about and requires their "realization" anew -- because we
> don't track the dependencies between faces, and thus don't know which
> other faces need to be updated as result. So this would mean that any
> point movement could potentially cause recalculation of all the faces
> on the selected frame.
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.
> And face realization is a relatively expensive
> process, especially if there are a lot of them (we had reports about
> users who routinely have hundreds or even thousands of faces on a
> frame). Thus my question about items 2 and 3, which seem to do exactly
> what we avoid doing: modify named faces.
Does “substitute a named face for another named or anonymous face” lead to similar concerns? Or can those then all be precomputed without the constant face realization concern?
[1] https://github.com/jdtsmith/indent-bars
[-- Attachment #2.1: Type: text/html, Size: 35856 bytes --]
[-- Attachment #2.2: favicon.ico --]
[-- Type: image/vnd.microsoft.icon, Size: 1406 bytes --]
next prev parent reply other threads:[~2024-01-03 23:15 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-02 0:22 region-based face-remapping JD Smith
2024-01-02 13:00 ` Eli Zaretskii
2024-01-02 15:49 ` JD Smith
2024-01-03 12:31 ` Eli Zaretskii
2024-01-03 12:40 ` Dmitry Gutov
2024-01-03 13:42 ` Eli Zaretskii
2024-01-04 0:07 ` Dmitry Gutov
2024-01-04 7:05 ` Eli Zaretskii
2024-01-05 3:49 ` Dmitry Gutov
2024-01-05 8:50 ` Eli Zaretskii
2024-01-05 14:18 ` Dmitry Gutov
2024-01-05 14:34 ` Eli Zaretskii
2024-01-05 16:25 ` Dmitry Gutov
2024-01-03 23:15 ` JD Smith [this message]
2024-01-04 6:58 ` Eli Zaretskii
2024-01-05 0:51 ` JD Smith
2024-01-05 8:19 ` Eli Zaretskii
2024-01-05 16:35 ` Dmitry Gutov
2024-01-06 14:04 ` JD Smith
2024-01-06 13:53 ` JD Smith
2024-01-06 14:27 ` Eli Zaretskii
2024-01-06 14:56 ` JD Smith
2024-01-08 17:28 ` Eli Zaretskii
2024-01-07 3:41 ` Dmitry Gutov
2024-01-15 19:55 ` Stefan Monnier via Emacs development discussions.
2024-01-15 20:19 ` Eli Zaretskii
2024-01-15 20:25 ` Eli Zaretskii
2024-01-15 20:36 ` Stefan Monnier
-- strict thread matches above, loose matches on Subject: below --
2024-01-08 21:49 JD Smith
2024-01-09 13:03 ` Eli Zaretskii
2024-01-09 14:15 ` Stefan Monnier
2024-01-09 20:20 ` JD Smith
2024-01-15 20:17 ` Stefan Monnier via Emacs development discussions.
2024-01-09 20:20 ` JD Smith
2024-01-10 12:36 ` Eli Zaretskii
2024-01-09 21:31 ` JD Smith
2024-01-10 12:44 ` Eli Zaretskii
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=ABD260AF-CB90-41A5-A417-322212C32C51@gmail.com \
--to=jdtsmith@gmail.com \
--cc=eliz@gnu.org \
--cc=emacs-devel@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).