From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Eli Zaretskii Newsgroups: gmane.emacs.devel Subject: Re: region-based face-remapping Date: Wed, 03 Jan 2024 14:31:50 +0200 Message-ID: <83edeyzjgp.fsf@gnu.org> References: <83y1d7zy8s.fsf@gnu.org> <3592E8C5-35FF-44FF-88ED-B458303BF15A@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="28249"; mail-complaints-to="usenet@ciao.gmane.io" Cc: emacs-devel@gnu.org To: JD Smith Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Wed Jan 03 13:33:01 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 1rL0Qe-00074M-Of for ged-emacs-devel@m.gmane-mx.org; Wed, 03 Jan 2024 13:33:00 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rL0Pq-0008A2-SD; Wed, 03 Jan 2024 07:32:10 -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 1rL0Pp-00089U-CG for emacs-devel@gnu.org; Wed, 03 Jan 2024 07:32:09 -0500 Original-Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1rL0Pp-0003Z6-0D; Wed, 03 Jan 2024 07:32:09 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-version:References:Subject:In-Reply-To:To:From: Date; bh=6+gM1tFWaiZLejYj2jrvIsXvt4N5sUe5C8Z1D2TyMng=; b=DQpXh5iYluuCO8/my2KC HGIzlXtyW/O98xEwxCCf5/JZ43sb0n2PqDt6ityNG44FFSfy+vsQWW6Kb5kt+/d0SryyriAmCl4HH AxiaxLZMiJwOPY6K5gMCKIbUqOuJvn/Av4NJa6lwJCfacrfsIF4jLB3nJYffZnppPpThawrlg8ISG pcmhJQ0cR6wMWVKpV5nvfY6fW8XEqtj9ih4XgRj+RConf8JrU/3RYULL0OSscj45JaMuaHNxdviGx XU9w7gKIt6SJeer8DO3GmUShHaP+Y9MAqyMHFANs92AgKYmDNYK3Ew/tt1ZAuVCQn71WtFzqTOiWI VmIc6mMVxlDDzQ==; In-Reply-To: <3592E8C5-35FF-44FF-88ED-B458303BF15A@gmail.com> (message from JD Smith on Tue, 2 Jan 2024 10:49:49 -0500) 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:314485 Archived-At: > From: JD Smith > Date: Tue, 2 Jan 2024 10:49:49 -0500 > Cc: emacs-devel@gnu.org > > On Jan 2, 2024, at 8:00 AM, Eli Zaretskii wrote: > > From: JD Smith > Date: Mon, 1 Jan 2024 19:22:29 -0500 > > Has there been any discussion of implementing region-based face remapping, perhaps > by adding 'face-remap as a property to overlays? This would be very useful for modes in > which local syntax highlighting depends on point, now broadly possible thanks to treesitter > (think “brighten surrounding semantic unit” or similar). > > If you only want to change the appearance around point, you need a > much smaller revolution than position-dependent faces, which are > something much more general. E.g., position-dependent faces need to > change all the face-related APIs to pass a position and a buffer > arguments, whereas if it's only "around point", you need nothing like > that because the position of point is always known in each buffer. > > 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. > 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? > 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. > 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"? 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. 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.