[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#70077: An easier way to track buffer changes
From: |
Stefan Monnier |
Subject: |
bug#70077: An easier way to track buffer changes |
Date: |
Fri, 29 Mar 2024 23:17:09 -0400 |
User-agent: |
Gnus/5.13 (Gnus v5.13) |
> 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
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 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
bug#70077: An easier way to track buffer changes,
Stefan Monnier <=
bug#70077: An easier way to track buffer changes, phillip . lord, 2024/03/29
bug#70077: An easier way to track buffer changes, Ihor Radchenko, 2024/03/30