From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of text editors" Newsgroups: gmane.emacs.bugs Subject: bug#70077: An easier way to track buffer changes Date: Tue, 09 Apr 2024 19:30:17 -0400 Message-ID: References: <86frvy51af.fsf@gnu.org> <865xwrxk88.fsf@gnu.org> Reply-To: Stefan Monnier Mime-Version: 1.0 Content-Type: text/plain Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="29108"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Cc: acm@muc.de, yantar92@posteo.net, 70077@debbugs.gnu.org To: Eli Zaretskii Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Wed Apr 10 01:31:17 2024 Return-path: Envelope-to: geb-bug-gnu-emacs@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 1ruKvt-0007O3-1c for geb-bug-gnu-emacs@m.gmane-mx.org; Wed, 10 Apr 2024 01:31:17 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ruKvY-0004C3-EP; Tue, 09 Apr 2024 19:30:56 -0400 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 1ruKvW-0004Bs-Gl for bug-gnu-emacs@gnu.org; Tue, 09 Apr 2024 19:30:54 -0400 Original-Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1ruKvW-0000vT-7f for bug-gnu-emacs@gnu.org; Tue, 09 Apr 2024 19:30:54 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1ruKve-0005R1-Ax for bug-gnu-emacs@gnu.org; Tue, 09 Apr 2024 19:31:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Stefan Monnier Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 09 Apr 2024 23:31:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 70077 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 70077-submit@debbugs.gnu.org id=B70077.171270543720838 (code B ref 70077); Tue, 09 Apr 2024 23:31:02 +0000 Original-Received: (at 70077) by debbugs.gnu.org; 9 Apr 2024 23:30:37 +0000 Original-Received: from localhost ([127.0.0.1]:51773 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ruKvF-0005Q1-1O for submit@debbugs.gnu.org; Tue, 09 Apr 2024 19:30:37 -0400 Original-Received: from mailscanner.iro.umontreal.ca ([132.204.25.50]:52844) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ruKvD-0005Po-3y for 70077@debbugs.gnu.org; Tue, 09 Apr 2024 19:30:35 -0400 Original-Received: from pmg1.iro.umontreal.ca (localhost.localdomain [127.0.0.1]) by pmg1.iro.umontreal.ca (Proxmox) with ESMTP id 76A8E1000FC; Tue, 9 Apr 2024 19:30:20 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=iro.umontreal.ca; s=mail; t=1712705419; bh=P4yNbkX18cP7PGG83TX4Ye6wMCBI0zL8QdmXAz37n+I=; h=From:To:Cc:Subject:In-Reply-To:References:Date:From; b=msHxrTWVr1K4WkVJUg1BbLhwV76NizdFNU1GbEUsxNcMGCX0W4zJHi+gum3rqt00x 9EWkeFL0CHPqDgfRy6Do6M4Mh9qESe6H4EZ+PdWMmuYJq9yKyUE1AumuIIMhfbyf09 uhgz8MvqW9u5+9xKG73dX9lV6Rh5azRLw8NrgKAs08fLr0grAgFQxsqsp5fZ/m71So ujOUfvq2u9PVfqnKJZZvn6nxQ6R66qTpcR3VK8gkWeSfBAkEavV2UhD6hV12eU5a3k 6B0+PwJ8E2fPqalMU1WuLHCSHnGfYlup679dTdps22DAHhmWbxbRus+/yUvVEMdR3w L7lKQjCQvgBjA== Original-Received: from mail01.iro.umontreal.ca (unknown [172.31.2.1]) by pmg1.iro.umontreal.ca (Proxmox) with ESMTP id 2736010004A; Tue, 9 Apr 2024 19:30:19 -0400 (EDT) Original-Received: from pastel (unknown [45.72.201.215]) by mail01.iro.umontreal.ca (Postfix) with ESMTPSA id F1A0512030C; Tue, 9 Apr 2024 19:30:18 -0400 (EDT) In-Reply-To: <865xwrxk88.fsf@gnu.org> (Eli Zaretskii's message of "Tue, 09 Apr 2024 06:56:07 +0300") X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:283018 Archived-At: >> +Using @code{before-change-functions} and @code{after-change-functions} >> +can be difficult in practice because of a number of pitfalls, such as >> +the fact that the two calls are not always properly paired, or some >> +calls may be missing, either because of bugs in the C code or because of >> +inappropriate use of @code{inhibit-modification-hooks}. > > I don't think we should talk about bugs in C code in the manual, at > least not so explicitly. I would rephrase > > the fact that the two calls are not always properly paired, or some > calls may be missing, either because some Emacs primitives cannot > properly pair them or because of incorrect use of > @code{inhibit-modification-hooks}. Thanks. >> +@code{track-changes-register}, passing it a @var{signal} function as >> +argument. This will return a tracker @var{id} which is used to identify >> +your tracker to the other functions of the library. The other main >> +function of the library is @code{track-changes-fetch} which lets you >> +fetch the changes you have not yet processed. > > The last sentence is redundant, since you are about to describe > track-changes-fetch shortly. Good point. >> +When the buffer is modified, the library will call the @var{signal} >> +function to inform you of that change and will immediately start >> +accumulating subsequent changes into a single combined change. >> +The @var{signal} function serves only to warn that a modification >> +occurred but does not receive a description of the change. Also the >> +library will not call it again until after you processed >> +the change. > > The last sentence should IMO say "...until after you retrieved the > change by calling @code{track-changes-fetch}." The important part > here is to say what "process" means in practice, instead of leaving it > unsaid. But then we get: ...until after you retrieved the change by calling @code{track-changes-fetch}. To process changes, you need to call @code{track-changes-fetch}, ... which again is kind of redundant/heavy. I went with: To start tracking changes, you have to call @code{track-changes-register}, passing it a @var{signal} function as argument. This returns a tracker @var{id} which is used to identify your change tracker to the other functions of the library. When the buffer is modified, the library calls the @var{signal} function to inform you of that change and immediately starts accumulating subsequent changes into a single combined change. The @var{signal} function serves only to warn that a modification occurred but does not receive a description of the change. Also the library will not call it again until after you retrieved the change. To retrieve changes, you need to call @code{track-changes-fetch}, which provides you with the bounds of the changes accumulated since the last call, as well as the previous content of that region. It also ``re-arms'' the @var{signal} function so that the library will call it again after the next buffer modification. [ Where I also switched to the present tense. Not sure why I used the future tense. ] >> +@defun track-changes-register signal &key nobefore disjoint immediate >> +This function creates a new @emph{tracker}. Trackers are kept abstract, > > I suggest to use "change tracker" instead of just "tracker". On my > daytime job, "tracker" has a very different meaning, so I stumble each > time I see this used like that. > > Also, I suggest to use @dfn for its markup (and add a @cindex for it > for good measure). I turned some uses of "tracker" into "change tracker" and I think it's indeed an improvement. I tried to do it more systematically but with all the "track-changes" and "change trackers" I started to feel like I was writing a tongue twister. >> +By default, the call to the @var{signal} function does not happen >> +immediately, but is instead postponed with a 0 seconds timer. > ^^^^^^^^^^^^^^^ > A cross-reference to where timers are described is in order there. Thanks. >> +usually desired to make sure the @var{signal} function is not called too >> +frequently and runs in a permissive context, freeing the client from >> +performance concerns or worries about which operations might be >> +problematic. If a client wants to have more control, they can provide >> +a non-nil value as the @var{immediate} argument in which case the > ^^^ > @code{nil} Duh. >> +Once @var{func} finishes, @code{track-changes-fetch} re-enables the >> +@var{signal} function so that it will be called the next time a change >> +occurs. This is the reason why it calls @var{func} instead of returning >> +a description: it makes sure that the @var{signal} function will not be >> +called while you're still processing past changes. > > I think there's a subtler issue here that needs to be described > explicitly: if the entire processing of the change is not done inside > FUNC, there's no guarantee that by the time some other function > processes it, the change is still valid and in particular SIGNAL will > not have been called again. This is not a trivial aspect, since a > program can use FUNC to do just some partial processing, like squirrel > the changes to some buffer for later processing. I tried to be more explicit about that as follows: Once @var{func} finishes, @code{track-changes-fetch} re-enables the @var{signal} function so that it will be called the next time a change occurs. This is the reason why it calls @var{func} instead of returning a description: it lets you process the change without worrying about the risk that the @var{signal} function gets triggered in the middle of it, because the @var{signal} is re-enabled only after @var{func} finishes. Note that calling SIGNAL before the change is "processed" is not necessarily a problem. E.g. Eglot does exactly that: its FUNC just turns the NEWBEG/NEWEND/BEFORE into something like OLDBEG/OLDEND/AFTER and pushes it on a list for later processing, it then waits for more changes to come before later sending them to the server. >> * New Modes and Packages in Emacs 30.1 >> +** New package Track-Changes. > This should be marked with "+++". Thanks. >> No, what it's saying is that these slots can contain values of any type >> (since any type is a subtype of t). >> This `Type` information is a way to document what kind of values can be >> found in those slots. Very often we don't bother specifying it, in >> which case `t` is used as a default. > Then maybe show "Any" or even "N/A". t is simply not informative at > all. Actually, it is counter-productive: it makes a simple issue look > complex and strange. OK, I just used the empty string. Stefan