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: Fri, 29 Mar 2024 23:17:09 -0400 Message-ID: References: <86frw8ewk9.fsf@gnu.org> Reply-To: Stefan Monnier Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="24157"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Cc: casouri@gmail.com, 70077@debbugs.gnu.org, yantar92@posteo.net, qhong@alum.mit.edu, frederic.bour@lakaban.net, joaotavora@gmail.com, mail@nicolasgoaziou.fr, acm@muc.de, stephen_leake@stephe-leake.org, alan.zimm@gmail.com, phillip.lord@russet.org.uk To: Eli Zaretskii Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Sat Mar 30 04:18:34 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 1rqPEn-00062B-ND for geb-bug-gnu-emacs@m.gmane-mx.org; Sat, 30 Mar 2024 04:18:34 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rqPEJ-0000dQ-TA; Fri, 29 Mar 2024 23:18:03 -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 1rqPEI-0000dI-Tn for bug-gnu-emacs@gnu.org; Fri, 29 Mar 2024 23:18:02 -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 1rqPEI-00060A-L0 for bug-gnu-emacs@gnu.org; Fri, 29 Mar 2024 23:18:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1rqPEJ-00055w-R5 for bug-gnu-emacs@gnu.org; Fri, 29 Mar 2024 23:18:03 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Stefan Monnier Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 30 Mar 2024 03:18:03 +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.171176864319426 (code B ref 70077); Sat, 30 Mar 2024 03:18:03 +0000 Original-Received: (at 70077) by debbugs.gnu.org; 30 Mar 2024 03:17:23 +0000 Original-Received: from localhost ([127.0.0.1]:43692 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rqPDe-00053G-Nm for submit@debbugs.gnu.org; Fri, 29 Mar 2024 23:17:23 -0400 Original-Received: from mailscanner.iro.umontreal.ca ([132.204.25.50]:49544) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1rqPDd-000534-8V for 70077@debbugs.gnu.org; Fri, 29 Mar 2024 23:17:21 -0400 Original-Received: from pmg2.iro.umontreal.ca (localhost.localdomain [127.0.0.1]) by pmg2.iro.umontreal.ca (Proxmox) with ESMTP id 9AE71803C1; Fri, 29 Mar 2024 23:17:13 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=iro.umontreal.ca; s=mail; t=1711768632; bh=l5FVBO2ixyFlfCyU6ciEHZJs/xQHsI14as4BFV3BnC4=; h=From:To:Cc:Subject:In-Reply-To:References:Date:From; b=HoDRsMA7Q8W8334kRhUq9qeeCAB7Pl2V+daqGvnllsYMBuq08kiw6c2ydYBIHrEtI InXI2LNsnjC4slEGAV5Hyc4Hci1PKyI+E3Hji/5EiX5FKpO0Aejpaqu/HqdCqPcaPo PjezL+IaioA+BrJLZOeIJj0023d+G99ZDV9ekCf2cxN1utEGF6oAT9xZB3cDzXqNYG XSBfBuKkqnNWRtoW7nNyviicX3vOGpq2lIEixDh1e5b6Puj/81R/0CYsJecyRK4kLY qHcByzzhbB8atuCvueZ3o03NaMe4JR2D/6fbffU7EDhyFL8AlaTscV79bAyPqWi4ON klWzmum4u17Lw== Original-Received: from mail01.iro.umontreal.ca (unknown [172.31.2.1]) by pmg2.iro.umontreal.ca (Proxmox) with ESMTP id 3C04B8092A; Fri, 29 Mar 2024 23:17:12 -0400 (EDT) Original-Received: from pastel (104-222-113-60.cpe.teksavvy.com [104.222.113.60]) by mail01.iro.umontreal.ca (Postfix) with ESMTPSA id A3251120857; Fri, 29 Mar 2024 23:17:11 -0400 (EDT) In-Reply-To: <86frw8ewk9.fsf@gnu.org> (Eli Zaretskii's message of "Fri, 29 Mar 2024 21:12:54 +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:282321 Archived-At: --=-=-= Content-Type: text/plain > I cannot imagine how applications would use these APIs. I'm probably > missing something, org the above documentation does. Can you show > some real-life examples? Here's my first attempt at a real-life use. Note: this example doesn't make use of the full API (it doesn't need the `before` argument). Stefan --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=diff-track-changes.patch diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el index d9146ea8cc5..f8c31fb6748 100644 --- a/lisp/vc/diff-mode.el +++ b/lisp/vc/diff-mode.el @@ -53,9 +53,10 @@ ;; - Handle `diff -b' output in context->unified. ;;; Code: +(require 'easy-mmode) +(require 'track-changes) (eval-when-compile (require 'cl-lib)) (eval-when-compile (require 'subr-x)) -(require 'easy-mmode) (autoload 'vc-find-revision "vc") (autoload 'vc-find-revision-no-save "vc") @@ -1441,31 +1441,16 @@ (if (buffer-modified-p) (diff-fixup-modifs (point-min) (point-max))) nil) -;; It turns out that making changes in the buffer from within an -;; *-change-function is asking for trouble, whereas making them -;; from a post-command-hook doesn't pose much problems -(defvar diff-unhandled-changes nil) -(defun diff-after-change-function (beg end _len) - "Remember to fixup the hunk header. -See `after-change-functions' for the meaning of BEG, END and LEN." - ;; Ignoring changes when inhibit-read-only is set is strictly speaking - ;; incorrect, but it turns out that inhibit-read-only is normally not set - ;; inside editing commands, while it tends to be set when the buffer gets - ;; updated by an async process or by a conversion function, both of which - ;; would rather not be uselessly slowed down by this hook. - (when (and (not undo-in-progress) (not inhibit-read-only)) - (if diff-unhandled-changes - (setq diff-unhandled-changes - (cons (min beg (car diff-unhandled-changes)) - (max end (cdr diff-unhandled-changes)))) - (setq diff-unhandled-changes (cons beg end))))) +(defvar-local diff--track-changes nil) -(defun diff-post-command-hook () - "Fixup hunk headers if necessary." - (when (consp diff-unhandled-changes) - (ignore-errors +(defun diff--track-changes-signal (tracker) + (cl-assert (eq tracker diff--track-changes)) + (track-changes-fetch tracker #'diff--track-changes-function)) + +(defun diff--track-changes-function (beg end _before) + (with-demoted-errors "%S" (save-excursion - (goto-char (car diff-unhandled-changes)) + (goto-char beg) ;; Maybe we've cut the end of the hunk before point. (if (and (bolp) (not (bobp))) (backward-char 1)) ;; We used to fixup modifs on all the changes, but it turns out that @@ -1480,17 +1465,16 @@ (re-search-forward diff-context-mid-hunk-header-re nil t))))) (when (and ;; Don't try to fixup changes in the hunk header. - (>= (car diff-unhandled-changes) start) + (>= beg start) ;; Don't try to fixup changes in the mid-hunk header either. (or (not mid) - (< (cdr diff-unhandled-changes) (match-beginning 0)) - (> (car diff-unhandled-changes) (match-end 0))) + (< end (match-beginning 0)) + (> beg (match-end 0))) (save-excursion (diff-end-of-hunk nil 'donttrustheader) ;; Don't try to fixup changes past the end of the hunk. - (>= (point) (cdr diff-unhandled-changes)))) - (diff-fixup-modifs (point) (cdr diff-unhandled-changes))))) - (setq diff-unhandled-changes nil)))) + (>= (point) end))) + (diff-fixup-modifs (point) end)))))) (defun diff-next-error (arg reset) ;; Select a window that displays the current buffer so that point @@ -1572,9 +1557,8 @@ diff-mode ;; setup change hooks (if (not diff-update-on-the-fly) (add-hook 'write-contents-functions #'diff-write-contents-hooks nil t) - (make-local-variable 'diff-unhandled-changes) - (add-hook 'after-change-functions #'diff-after-change-function nil t) - (add-hook 'post-command-hook #'diff-post-command-hook nil t)) + (setq diff--track-changes + (track-changes-register #'diff--track-changes-signal))) ;; add-log support (setq-local add-log-current-defun-function #'diff-current-defun) @@ -1593,12 +1577,13 @@ diff-minor-mode \\{diff-minor-mode-map}" :group 'diff-mode :lighter " Diff" ;; FIXME: setup font-lock - ;; setup change hooks + (when diff--track-changes (track-changes-unregister diff--track-changes)) + (remove-hook 'write-contents-functions #'diff-write-contents-hooks t) (if (not diff-update-on-the-fly) (add-hook 'write-contents-functions #'diff-write-contents-hooks nil t) - (make-local-variable 'diff-unhandled-changes) - (add-hook 'after-change-functions #'diff-after-change-function nil t) - (add-hook 'post-command-hook #'diff-post-command-hook nil t))) + (unless diff--track-changes + (setq diff--track-changes + (track-changes-register #'diff--track-changes-signal))))) ;;; Handy hook functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; --=-=-=--