aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/vc/diff-mode.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/vc/diff-mode.el')
-rw-r--r--lisp/vc/diff-mode.el85
1 files changed, 36 insertions, 49 deletions
diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
index 66043059d14..0a618dc8f39 100644
--- a/lisp/vc/diff-mode.el
+++ b/lisp/vc/diff-mode.el
@@ -53,9 +53,10 @@
53;; - Handle `diff -b' output in context->unified. 53;; - Handle `diff -b' output in context->unified.
54 54
55;;; Code: 55;;; Code:
56(require 'easy-mmode)
57(require 'track-changes)
56(eval-when-compile (require 'cl-lib)) 58(eval-when-compile (require 'cl-lib))
57(eval-when-compile (require 'subr-x)) 59(eval-when-compile (require 'subr-x))
58(require 'easy-mmode)
59 60
60(autoload 'vc-find-revision "vc") 61(autoload 'vc-find-revision "vc")
61(autoload 'vc-find-revision-no-save "vc") 62(autoload 'vc-find-revision-no-save "vc")
@@ -1431,38 +1432,23 @@ else cover the whole buffer."
1431 (if (buffer-modified-p) (diff-fixup-modifs (point-min) (point-max))) 1432 (if (buffer-modified-p) (diff-fixup-modifs (point-min) (point-max)))
1432 nil) 1433 nil)
1433 1434
1434;; It turns out that making changes in the buffer from within an 1435(defvar-local diff--track-changes nil)
1435;; *-change-function is asking for trouble, whereas making them 1436
1436;; from a post-command-hook doesn't pose much problems 1437(defun diff--track-changes-signal (tracker)
1437(defvar diff-unhandled-changes nil) 1438 (cl-assert (eq tracker diff--track-changes))
1438(defun diff-after-change-function (beg end _len) 1439 (track-changes-fetch tracker #'diff--track-changes-function))
1439 "Remember to fixup the hunk header. 1440
1440See `after-change-functions' for the meaning of BEG, END and LEN." 1441(defun diff--track-changes-function (beg end _before)
1441 ;; Ignoring changes when inhibit-read-only is set is strictly speaking 1442 (with-demoted-errors "%S"
1442 ;; incorrect, but it turns out that inhibit-read-only is normally not set 1443 (save-excursion
1443 ;; inside editing commands, while it tends to be set when the buffer gets 1444 (goto-char beg)
1444 ;; updated by an async process or by a conversion function, both of which 1445 ;; Maybe we've cut the end of the hunk before point.
1445 ;; would rather not be uselessly slowed down by this hook. 1446 (if (and (bolp) (not (bobp))) (backward-char 1))
1446 (when (and (not undo-in-progress) (not inhibit-read-only)) 1447 ;; We used to fixup modifs on all the changes, but it turns out that
1447 (if diff-unhandled-changes 1448 ;; it's safer not to do it on big changes, e.g. when yanking a big
1448 (setq diff-unhandled-changes 1449 ;; diff, or when the user edits the header, since we might then
1449 (cons (min beg (car diff-unhandled-changes)) 1450 ;; screw up perfectly correct values. --Stef
1450 (max end (cdr diff-unhandled-changes)))) 1451 (when (ignore-errors (diff-beginning-of-hunk t))
1451 (setq diff-unhandled-changes (cons beg end)))))
1452
1453(defun diff-post-command-hook ()
1454 "Fixup hunk headers if necessary."
1455 (when (consp diff-unhandled-changes)
1456 (ignore-errors
1457 (save-excursion
1458 (goto-char (car diff-unhandled-changes))
1459 ;; Maybe we've cut the end of the hunk before point.
1460 (if (and (bolp) (not (bobp))) (backward-char 1))
1461 ;; We used to fixup modifs on all the changes, but it turns out that
1462 ;; it's safer not to do it on big changes, e.g. when yanking a big
1463 ;; diff, or when the user edits the header, since we might then
1464 ;; screw up perfectly correct values. --Stef
1465 (diff-beginning-of-hunk t)
1466 (let* ((style (if (looking-at "\\*\\*\\*") 'context)) 1452 (let* ((style (if (looking-at "\\*\\*\\*") 'context))
1467 (start (line-beginning-position (if (eq style 'context) 3 2))) 1453 (start (line-beginning-position (if (eq style 'context) 3 2)))
1468 (mid (if (eq style 'context) 1454 (mid (if (eq style 'context)
@@ -1470,17 +1456,16 @@ See `after-change-functions' for the meaning of BEG, END and LEN."
1470 (re-search-forward diff-context-mid-hunk-header-re 1456 (re-search-forward diff-context-mid-hunk-header-re
1471 nil t))))) 1457 nil t)))))
1472 (when (and ;; Don't try to fixup changes in the hunk header. 1458 (when (and ;; Don't try to fixup changes in the hunk header.
1473 (>= (car diff-unhandled-changes) start) 1459 (>= beg start)
1474 ;; Don't try to fixup changes in the mid-hunk header either. 1460 ;; Don't try to fixup changes in the mid-hunk header either.
1475 (or (not mid) 1461 (or (not mid)
1476 (< (cdr diff-unhandled-changes) (match-beginning 0)) 1462 (< end (match-beginning 0))
1477 (> (car diff-unhandled-changes) (match-end 0))) 1463 (> beg (match-end 0)))
1478 (save-excursion 1464 (save-excursion
1479 (diff-end-of-hunk nil 'donttrustheader) 1465 (diff-end-of-hunk nil 'donttrustheader)
1480 ;; Don't try to fixup changes past the end of the hunk. 1466 ;; Don't try to fixup changes past the end of the hunk.
1481 (>= (point) (cdr diff-unhandled-changes)))) 1467 (>= (point) end)))
1482 (diff-fixup-modifs (point) (cdr diff-unhandled-changes))))) 1468 (diff-fixup-modifs (point) end)))))))
1483 (setq diff-unhandled-changes nil))))
1484 1469
1485(defun diff-next-error (arg reset) 1470(defun diff-next-error (arg reset)
1486 ;; Select a window that displays the current buffer so that point 1471 ;; Select a window that displays the current buffer so that point
@@ -1560,9 +1545,8 @@ a diff with \\[diff-reverse-direction].
1560 ;; setup change hooks 1545 ;; setup change hooks
1561 (if (not diff-update-on-the-fly) 1546 (if (not diff-update-on-the-fly)
1562 (add-hook 'write-contents-functions #'diff-write-contents-hooks nil t) 1547 (add-hook 'write-contents-functions #'diff-write-contents-hooks nil t)
1563 (make-local-variable 'diff-unhandled-changes) 1548 (setq diff--track-changes
1564 (add-hook 'after-change-functions #'diff-after-change-function nil t) 1549 (track-changes-register #'diff--track-changes-signal :nobefore t)))
1565 (add-hook 'post-command-hook #'diff-post-command-hook nil t))
1566 1550
1567 ;; add-log support 1551 ;; add-log support
1568 (setq-local add-log-current-defun-function #'diff-current-defun) 1552 (setq-local add-log-current-defun-function #'diff-current-defun)
@@ -1581,12 +1565,15 @@ a diff with \\[diff-reverse-direction].
1581\\{diff-minor-mode-map}" 1565\\{diff-minor-mode-map}"
1582 :group 'diff-mode :lighter " Diff" 1566 :group 'diff-mode :lighter " Diff"
1583 ;; FIXME: setup font-lock 1567 ;; FIXME: setup font-lock
1584 ;; setup change hooks 1568 (when diff--track-changes (track-changes-unregister diff--track-changes))
1585 (if (not diff-update-on-the-fly) 1569 (remove-hook 'write-contents-functions #'diff-write-contents-hooks t)
1586 (add-hook 'write-contents-functions #'diff-write-contents-hooks nil t) 1570 (when diff-minor-mode
1587 (make-local-variable 'diff-unhandled-changes) 1571 (if (not diff-update-on-the-fly)
1588 (add-hook 'after-change-functions #'diff-after-change-function nil t) 1572 (add-hook 'write-contents-functions #'diff-write-contents-hooks nil t)
1589 (add-hook 'post-command-hook #'diff-post-command-hook nil t))) 1573 (unless diff--track-changes
1574 (setq diff--track-changes
1575 (track-changes-register #'diff--track-changes-signal
1576 :nobefore t))))))
1590 1577
1591;;; Handy hook functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1578;;; Handy hook functions ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1592 1579