From: JD Smith <jdtsmith@gmail.com>
To: Eli Zaretskii <eliz@gnu.org>
Cc: emacs-devel@gnu.org
Subject: Re: region-based face-remapping
Date: Sat, 6 Jan 2024 08:53:22 -0500 [thread overview]
Message-ID: <8B06B532-A445-43AE-883D-C9E5CF5DB870@gmail.com> (raw)
In-Reply-To: <837ckow5st.fsf@gnu.org>
[-- Attachment #1: Type: text/plain, Size: 6608 bytes --]
> On Jan 5, 2024, at 3:19 AM, Eli Zaretskii <eliz@gnu.org> wrote:
>
>> 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.
I wondered about that. Since I don’t know emacs internals, I am (blissfully?) unaware of how close at hand the information of (get-text-property (point) 'face-remap) is. Since a typical buffer has maybe N=hundreds of ‘face changes, this puts an approximate upper limit on the number of sensible ‘face + ‘face-remap changes: 2N. Much more likely would be just a handful of ‘face-remap changes. So I doubt the overhead of “additional merging” would be significant. Of course you have to find these special points, but already you must find ‘face and ‘font-lock-face (and others?).
>> 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.
That’s good, since it sounds like even if a ‘face-remap property range is moved, but includes the same underlying face data, the cache for those internal merged faces should remain valid.
>> 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 define the faces on the fly based on max indentation depth, but in practice it’s of order 5 more than the normal contingent of a dozen or so font-lock-faces. So not a huge number.
>> 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;
Indeed I have pondered this for several months and found nothing suitable. Do you have any specific approaches to consider, which would allow you to selectively affect the appearance of certain small ranges of text within a (much) larger region of text? The problem is, the region is well known, but changing the appearance everywhere within it is not suitable to the problem at hand. I could obviously scrub through the entire region on the fly replacing face properties as I go (including inside ‘display properties), but that’s painful and probably too slow for interactive use.
> 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.
I’m afraid I don’t understand your “special variable to consider for text around point” idea. Can you give an example of how this could work in practice? How would such a variable be updated and associated with text, if not via text properties?
> 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.
Of course, well understood. It’s eminently sensible to guard against kitchen-sink-itis. Lacking familiarity with the core face code, I wondered if there was a straightforward extension to the global face-remapping-alist which could be brought to bear on the problem. But perhaps there are other more straightforward means.
If you have other simpler ideas in mind that would allow turning on and off a latent “plane” of varying face information within a region of text (information which, I should have mentioned, could easily be computed and pre-applied by font-lock), I’d be very glad to hear them.
In the world of CSS, you’d do this quite simply by (say) updating the class of the div which wraps your text of interest, and having special styling for, e.g., "alternate bold" and "alternate italic”, which is only activated when the “alternate” class is applied:
<div class=“normal”>
This is <i>some italic text</i> and <b>some bold</b> text. This is unrelated text.
</div>
In CSS
.alternate b {...}
.alternate i {…}
(In JS later:)
myDiv.classList.add('alternate');
[-- Attachment #2: Type: text/html, Size: 29538 bytes --]
next prev parent reply other threads:[~2024-01-06 13:53 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
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 [this message]
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=8B06B532-A445-43AE-883D-C9E5CF5DB870@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).