From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: JD Smith Newsgroups: gmane.emacs.devel Subject: Re: region-based face-remapping Date: Sat, 6 Jan 2024 08:53:22 -0500 Message-ID: <8B06B532-A445-43AE-883D-C9E5CF5DB870@gmail.com> References: <83y1d7zy8s.fsf@gnu.org> <3592E8C5-35FF-44FF-88ED-B458303BF15A@gmail.com> <83edeyzjgp.fsf@gnu.org> <83cyuhy483.fsf@gnu.org> <837ckow5st.fsf@gnu.org> Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3774.300.61.1.2\)) Content-Type: multipart/alternative; boundary="Apple-Mail=_E31BA286-B985-4B1A-80AF-6CB0B097D36C" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="1436"; mail-complaints-to="usenet@ciao.gmane.io" Cc: emacs-devel@gnu.org To: Eli Zaretskii Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Sat Jan 06 14:54:44 2024 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1rM78O-0000Cv-CK for ged-emacs-devel@m.gmane-mx.org; Sat, 06 Jan 2024 14:54:44 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rM77W-0007zi-MO; Sat, 06 Jan 2024 08:53:50 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rM77T-0007zR-4K for emacs-devel@gnu.org; Sat, 06 Jan 2024 08:53:47 -0500 Original-Received: from mail-qv1-xf2f.google.com ([2607:f8b0:4864:20::f2f]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rM77Q-000607-Kd; Sat, 06 Jan 2024 08:53:46 -0500 Original-Received: by mail-qv1-xf2f.google.com with SMTP id 6a1803df08f44-67f91d48863so4677256d6.0; Sat, 06 Jan 2024 05:53:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1704549214; x=1705154014; darn=gnu.org; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:from:to:cc:subject:date:message-id:reply-to; bh=tB/8MkfMpjcA7TZ1j7Go7AJ/rM7gckm4Us6NH+ckc8k=; b=iVm3DU5cvMsmYO0cIW/C9u+UXqPfb7viJoXb4vu3tk/HGsPMutZbYAekzNzJ/cFals 2jUwao5bK3XzRpgrJZlaiuMZ1+rbYb17qr3zPj/eyoDyBJ2PeNoE7xSEoSmmb/srWnPW QBWs21lZxf5sLtGmEREZElnf1hiedrMeN2JrC6s4WIiYc62L9ROe/CzPQJ3Kj7JF23o1 sl2CS56XeXy7ymWM6CaP1khfIc1CMQm/qktcjhyFdagcU4WSAYCI2zRFjjIDyYHGFzhO qtWCnm0sEi6SUAh3ablecBj2iiIwHTLO4Q+vAP+Akqhe+HDxx7XReu/ldAWk8cMjWTfo ie/Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1704549214; x=1705154014; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=tB/8MkfMpjcA7TZ1j7Go7AJ/rM7gckm4Us6NH+ckc8k=; b=ZHY3QUlimlm+G0S4+OKI5bEILXO9mX6eQ5bQcIJcVX8EeDWgu21rRSeAKaV90NRRJG AV2cU9xHEApezyWwIPPxMrrjlFdD0oYxDwGGR1rwn7Mas64B7tOJrWxPn8c1l+HfH7OK sWDFHkQBqfEG10l3yT6LOo0kPE0l2zENM6KmZhscEjKHhZv/EmocSaNgajgrN/QJyiEA /jpdK2oNyc4q9U48L+7FN+YprCxtLtBeRiurvu7ue3d5hdRMgaEgo2MtXSy+tZ/17mVl iAg6WJ6hytscEQWLphr4G25gWvq05s8Y39lUx7MJL+49H9s6lkBdzRz/X3UWAE895kqG y1WQ== X-Gm-Message-State: AOJu0YwCGBpM6bByT8bN3J7jzROa8C908K+Gr05y4pp7o69ewKt4+1T2 HmrVrjJMVxE/WR8ct3uSarndhDAdCw1z1Q== X-Google-Smtp-Source: AGHT+IF/OcCMe2dxfFDyvve94EDOYC0g9vmkHVU+iMzTyJEU8Nv8a4KE0nj7GCPR2QmIzNrgB3TYZA== X-Received: by 2002:ad4:5f48:0:b0:67f:27be:51ec with SMTP id p8-20020ad45f48000000b0067f27be51ecmr1127347qvg.100.1704549213363; Sat, 06 Jan 2024 05:53:33 -0800 (PST) Original-Received: from smtpclient.apple (cm-24-53-187-34.buckeyecom.net. [24.53.187.34]) by smtp.gmail.com with ESMTPSA id ke20-20020a056214301400b0067eab05723dsm1395507qvb.135.2024.01.06.05.53.32 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sat, 06 Jan 2024 05:53:32 -0800 (PST) In-Reply-To: <837ckow5st.fsf@gnu.org> X-Mailer: Apple Mail (2.3774.300.61.1.2) Received-SPF: pass client-ip=2607:f8b0:4864:20::f2f; envelope-from=jdtsmith@gmail.com; helo=mail-qv1-xf2f.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:314624 Archived-At: --Apple-Mail=_E31BA286-B985-4B1A-80AF-6CB0B097D36C Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 > On Jan 5, 2024, at 3:19=E2=80=AFAM, Eli Zaretskii = wrote: >=20 >> From: JD Smith >> Date: Thu, 4 Jan 2024 19:51:46 -0500 >> Cc: emacs-devel@gnu.org >>=20 >> On Jan 4, 2024, at 1:58=E2=80=AFAM, Eli Zaretskii = wrote: >>=20 >> 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. >>=20 >> This makes sense, thanks. In the =E2=80=98face-remap property = scenario, the number of such =E2=80=98face >> property-change positions doesn=E2=80=99t actually change. >=20 > 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=E2=80=99t 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=3Dhundreds of =E2=80=98face changes, this puts an approximate = upper limit on the number of sensible =E2=80=98face + =E2=80=98face-remap = changes: 2N. Much more likely would be just a handful of =E2=80=98face-re= map changes. So I doubt the overhead of =E2=80=9Cadditional merging=E2=80= =9D would be significant. Of course you have to find these special = points, but already you must find =E2=80=98face and =E2=80=98font-lock-fac= e (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). >=20 > 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=E2=80=99s good, since it sounds like even if a =E2=80=98face-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). >>=20 >> Right now it=E2=80=99s just a couple of faces (remove one face-remap, = add another). If I had access to a >> =E2=80=98face-remap property, I could imagine maybe 10 faces at most = being affected as point changes.=20 >> Each face would change by one or two attributes like foreground, = stipple, etc. =20 >=20 > 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=E2=80=99s of order 5 more than the normal contingent of a = dozen or so font-lock-faces. So not a huge number. >> I=E2=80=99m sure there could be lots of uses of this type of = functionality, but =E2=80=9Cenhance the focus on one region >> of importance=E2=80=9D seems like a very common one. For example, = you might imagine dim/gray version of >> all the font-lock faces outside the =E2=80=9Ctreesitter region of = interest=E2=80=9D and bright ones inside. Whenever that >> TS-prescribed region changes, an overlay with a =E2=80=98face-remap = property gets moved. =20 >=20 > 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 =E2=80=98display properties), but that=E2=80=99s = 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. =20 I=E2=80=99m afraid I don=E2=80=99t understand your =E2=80=9Cspecial = variable to consider for text around point=E2=80=9D 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=E2=80=99s 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 =E2=80=9Cplane=E2=80=9D 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=E2=80=99d be very = glad to hear them. In the world of CSS, you=E2=80=99d 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=E2=80=9D, which is only activated when the =E2=80=9Calternate=E2=80= =9D class is applied:
This is some italic text and some bold text. This is = unrelated text.
In CSS =09 .alternate b {...} .alternate i {=E2=80=A6} (In JS later:) myDiv.classList.add('alternate'); --Apple-Mail=_E31BA286-B985-4B1A-80AF-6CB0B097D36C Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8

On Jan 5, 2024, at 3:19=E2=80=AFAM, 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=E2=80=AFAM= , 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 =E2=80=98face-remap = property scenario, the number of such =E2=80=98face
property-change = positions doesn=E2=80=99t 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=E2=80=99t 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=3Dhundreds of =E2=80=98face changes, this = puts an approximate upper limit on the number of sensible =E2=80=98face = + =E2=80=98face-remap changes: 2N.  Much more likely would be just = a handful of =E2=80=98face-remap changes.  So I doubt the overhead = of =E2=80=9Cadditional merging=E2=80=9D would be significant.  Of = course you have to find these special points, but already you must find = =E2=80=98face and =E2=80=98font-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=E2=80=99s good, since = it sounds like even if a =E2=80=98face-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=E2=80=99s just a couple of faces (remove one face-remap, add = another).  If I had access to a
=E2=80=98face-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=E2=80=99s of order 5 more than the normal contingent of a dozen or so = font-lock-faces.  So not a huge number.

I=E2=80=99m sure there could be lots of uses of = this type of functionality, but =E2=80=9Cenhance the focus on one = region
of importance=E2=80=9D seems like a very common one.  For = example, you might imagine dim/gray version of
all the font-lock = faces outside the =E2=80=9Ctreesitter region of interest=E2=80=9D and = bright ones inside.  Whenever that
TS-prescribed region changes, = an overlay with a =E2=80=98face-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 = =E2=80=98display properties), but that=E2=80=99s 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=E2=80=99m = afraid I don=E2=80=99t understand your =E2=80=9Cspecial variable to = consider for text around point=E2=80=9D 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=E2=80=99s 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 =E2=80=9Cplane=E2=80=9D 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=E2=80=99d be very glad to = hear them.

In the world of CSS, you=E2=80=99d = 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=E2=80=9D, which is only activated when the = =E2=80=9Calternate=E2=80=9D class is = applied:

<div = class=3D=E2=80=9Cnormal=E2=80=9D>
This is = <i>some italic text</i> and <b>some bold</b> = text.  This is unrelated = text.
</div>

In CSS
.alternate b = {...}
.alternate i = {=E2=80=A6}

(In JS = later:)

 myDiv.classList.add('alternate');


= --Apple-Mail=_E31BA286-B985-4B1A-80AF-6CB0B097D36C--