aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTino Calancha2017-01-21 11:54:55 +0900
committerTino Calancha2017-01-21 11:54:55 +0900
commite5e42cefd7f2eb47d2c8660a7a317e8b08d36a82 (patch)
treedd7bfb464bba6f0a0bf3cef6e96d7813b8f776b8
parent1508b538fd8f8c2e00aadcea42ac36013fad02e3 (diff)
downloademacs-e5e42cefd7f2eb47d2c8660a7a317e8b08d36a82.tar.gz
emacs-e5e42cefd7f2eb47d2c8660a7a317e8b08d36a82.zip
diff-hunk-kill independent of point inside headers
Make diff-apply-hunk and diff-hunk-kill independent of the point position in a diff header (Bug#17544). This change allows to apply hunks in order. It also makes possible to press M-k repeatedly to kill hunks in the order they appear in the buffer. See discussion on #Bug25105. * lisp/vc/diff-mode.el (diff-file-junk-re): Move definition before it's used. (diff--at-diff-header-p): New predicate; return non-nil when point is inside a hunk header, a file header, or within a line matching diff-file-junk-re. (diff-beginning-of-hunk): Use it. Check if the point is inside a diff header, in the middle of a hunk, or before the first hunk. (diff-apply-hunk): Call diff-beginning-of-hunk with non-nil arg before apply the hunk. (diff-hunk-kill, diff-file-kill): Call diff-beginning-of-hunk with non-nil arg after kill the hunks. (diff-post-command-hook): Call diff-beginning-of-hunk with non-nil argument.
-rw-r--r--lisp/vc/diff-mode.el67
1 files changed, 49 insertions, 18 deletions
diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
index 4e878c404cd..b7ad8e8ebd8 100644
--- a/lisp/vc/diff-mode.el
+++ b/lisp/vc/diff-mode.el
@@ -498,22 +498,55 @@ See http://lists.gnu.org/archive/html/emacs-devel/2007-11/msg01990.html")
498 ;; The return value is used by easy-mmode-define-navigation. 498 ;; The return value is used by easy-mmode-define-navigation.
499 (goto-char (or end (point-max))))) 499 (goto-char (or end (point-max)))))
500 500
501;; "index ", "old mode", "new mode", "new file mode" and
502;; "deleted file mode" are output by git-diff.
503(defconst diff-file-junk-re
504 "diff \\|index \\|\\(?:deleted file\\|new\\(?: file\\)?\\|old\\) mode\\|=== modified file")
505
506;; If point is in a diff header, then return beginning
507;; of hunk position otherwise return nil.
508(defun diff--at-diff-header-p ()
509 "Return non-nil if point is inside a diff header."
510 (let ((regexp-hunk diff-hunk-header-re)
511 (regexp-file diff-file-header-re)
512 (regexp-junk diff-file-junk-re)
513 (orig (point)))
514 (catch 'headerp
515 (save-excursion
516 (forward-line 0)
517 (when (looking-at regexp-hunk) ; Hunk header.
518 (throw 'headerp (point)))
519 (forward-line -1)
520 (when (re-search-forward regexp-file (point-at-eol 4) t) ; File header.
521 (forward-line 0)
522 (throw 'headerp (point)))
523 (goto-char orig)
524 (forward-line 0)
525 (when (looking-at regexp-junk) ; Git diff junk.
526 (while (and (looking-at regexp-junk)
527 (not (bobp)))
528 (forward-line -1))
529 (re-search-forward regexp-file nil t)
530 (forward-line 0)
531 (throw 'headerp (point)))) nil)))
532
501(defun diff-beginning-of-hunk (&optional try-harder) 533(defun diff-beginning-of-hunk (&optional try-harder)
502 "Move back to the previous hunk beginning, and return its position. 534 "Move back to the previous hunk beginning, and return its position.
503If point is in a file header rather than a hunk, advance to the 535If point is in a file header rather than a hunk, advance to the
504next hunk if TRY-HARDER is non-nil; otherwise signal an error." 536next hunk if TRY-HARDER is non-nil; otherwise signal an error."
505 (beginning-of-line) 537 (beginning-of-line)
506 (if (looking-at diff-hunk-header-re) 538 (if (looking-at diff-hunk-header-re) ; At hunk header.
507 (point) 539 (point)
508 (forward-line 1) 540 (let ((pos (diff--at-diff-header-p))
509 (condition-case () 541 (regexp diff-hunk-header-re))
510 (re-search-backward diff-hunk-header-re) 542 (cond (pos ; At junk diff header.
511 (error 543 (if try-harder
512 (unless try-harder 544 (goto-char pos)
513 (error "Can't find the beginning of the hunk")) 545 (error "Can't find the beginning of the hunk")))
514 (diff-beginning-of-file-and-junk) 546 ((re-search-backward regexp nil t)) ; In the middle of a hunk.
515 (diff-hunk-next) 547 ((re-search-forward regexp nil t) ; At first hunk header.
516 (point))))) 548 (forward-line 0))
549 (t (error "Can't find the beginning of the hunk"))))))
517 550
518(defun diff-unified-hunk-p () 551(defun diff-unified-hunk-p ()
519 (save-excursion 552 (save-excursion
@@ -632,12 +665,8 @@ If the prefix ARG is given, restrict the view to the current file instead."
632 hunk-bounds)) 665 hunk-bounds))
633 (inhibit-read-only t)) 666 (inhibit-read-only t))
634 (apply 'kill-region bounds) 667 (apply 'kill-region bounds)
635 (goto-char (car bounds)))) 668 (goto-char (car bounds))
636 669 (diff-beginning-of-hunk t)))
637;; "index ", "old mode", "new mode", "new file mode" and
638;; "deleted file mode" are output by git-diff.
639(defconst diff-file-junk-re
640 "diff \\|index \\|\\(?:deleted file\\|new\\(?: file\\)?\\|old\\) mode\\|=== modified file")
641 670
642(defun diff-beginning-of-file-and-junk () 671(defun diff-beginning-of-file-and-junk ()
643 "Go to the beginning of file-related diff-info. 672 "Go to the beginning of file-related diff-info.
@@ -690,7 +719,8 @@ data such as \"Index: ...\" and such."
690 "Kill current file's hunks." 719 "Kill current file's hunks."
691 (interactive) 720 (interactive)
692 (let ((inhibit-read-only t)) 721 (let ((inhibit-read-only t))
693 (apply 'kill-region (diff-bounds-of-file)))) 722 (apply 'kill-region (diff-bounds-of-file)))
723 (diff-beginning-of-hunk t))
694 724
695(defun diff-kill-junk () 725(defun diff-kill-junk ()
696 "Kill spurious empty diffs." 726 "Kill spurious empty diffs."
@@ -1274,7 +1304,7 @@ See `after-change-functions' for the meaning of BEG, END and LEN."
1274 ;; it's safer not to do it on big changes, e.g. when yanking a big 1304 ;; it's safer not to do it on big changes, e.g. when yanking a big
1275 ;; diff, or when the user edits the header, since we might then 1305 ;; diff, or when the user edits the header, since we might then
1276 ;; screw up perfectly correct values. --Stef 1306 ;; screw up perfectly correct values. --Stef
1277 (diff-beginning-of-hunk) 1307 (diff-beginning-of-hunk t)
1278 (let* ((style (if (looking-at "\\*\\*\\*") 'context)) 1308 (let* ((style (if (looking-at "\\*\\*\\*") 'context))
1279 (start (line-beginning-position (if (eq style 'context) 3 2))) 1309 (start (line-beginning-position (if (eq style 'context) 3 2)))
1280 (mid (if (eq style 'context) 1310 (mid (if (eq style 'context)
@@ -1738,6 +1768,7 @@ the value of this variable when given an appropriate prefix argument).
1738 1768
1739With a prefix argument, REVERSE the hunk." 1769With a prefix argument, REVERSE the hunk."
1740 (interactive "P") 1770 (interactive "P")
1771 (diff-beginning-of-hunk t)
1741 (pcase-let ((`(,buf ,line-offset ,pos ,old ,new ,switched) 1772 (pcase-let ((`(,buf ,line-offset ,pos ,old ,new ,switched)
1742 ;; Sometimes we'd like to have the following behavior: if 1773 ;; Sometimes we'd like to have the following behavior: if
1743 ;; REVERSE go to the new file, otherwise go to the old. 1774 ;; REVERSE go to the new file, otherwise go to the old.