summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTino Calancha <tino.calancha@gmail.com>2017-02-02 22:27:33 +0900
committerTino Calancha <tino.calancha@gmail.com>2017-02-02 22:27:33 +0900
commita362b56b51f49963dbb63cd318967bca9b9fef74 (patch)
tree3583aa5b18eeed72ad80bbe85726ad8174945c2e
parent01d87bf846b478dea0bfe824678e76089f5af2c7 (diff)
downloademacs-a362b56b51f49963dbb63cd318967bca9b9fef74.tar.gz
emacs-a362b56b51f49963dbb63cd318967bca9b9fef74.tar.bz2
emacs-a362b56b51f49963dbb63cd318967bca9b9fef74.zip
Check if there are hunks before kill or refine a hunk
* lisp/vc/diff-mode.el (diff--some-hunks-p): New predicate. (diff-hunk-kill, diff-file-kill, diff-refine-hunk): Use it (Bug#25571).
-rw-r--r--lisp/vc/diff-mode.el159
1 files changed, 85 insertions, 74 deletions
diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
index a7ac53953dd..31c33e6a720 100644
--- a/lisp/vc/diff-mode.el
+++ b/lisp/vc/diff-mode.el
@@ -650,28 +650,36 @@ If the prefix ARG is given, restrict the view to the current file instead."
(if arg (diff-bounds-of-file) (diff-bounds-of-hunk)))
(set (make-local-variable 'diff-narrowed-to) (if arg 'file 'hunk)))
+(defun diff--some-hunks-p ()
+ (save-excursion
+ (goto-char (point-min))
+ (re-search-forward diff-hunk-header-re nil t)))
+
(defun diff-hunk-kill ()
"Kill the hunk at point."
(interactive)
- (let* ((hunk-bounds (diff-bounds-of-hunk))
- (file-bounds (ignore-errors (diff-bounds-of-file)))
- ;; If the current hunk is the only one for its file, kill the
- ;; file header too.
- (bounds (if (and file-bounds
- (progn (goto-char (car file-bounds))
- (= (progn (diff-hunk-next) (point))
- (car hunk-bounds)))
- (progn (goto-char (cadr hunk-bounds))
- ;; bzr puts a newline after the last hunk.
- (while (looking-at "^\n")
- (forward-char 1))
- (= (point) (cadr file-bounds))))
- file-bounds
- hunk-bounds))
- (inhibit-read-only t))
- (apply 'kill-region bounds)
- (goto-char (car bounds))
- (ignore-errors (diff-beginning-of-hunk t))))
+ (if (not (diff--some-hunks-p))
+ (error "No hunks")
+ (diff-beginning-of-hunk t)
+ (let* ((hunk-bounds (diff-bounds-of-hunk))
+ (file-bounds (ignore-errors (diff-bounds-of-file)))
+ ;; If the current hunk is the only one for its file, kill the
+ ;; file header too.
+ (bounds (if (and file-bounds
+ (progn (goto-char (car file-bounds))
+ (= (progn (diff-hunk-next) (point))
+ (car hunk-bounds)))
+ (progn (goto-char (cadr hunk-bounds))
+ ;; bzr puts a newline after the last hunk.
+ (while (looking-at "^\n")
+ (forward-char 1))
+ (= (point) (cadr file-bounds))))
+ file-bounds
+ hunk-bounds))
+ (inhibit-read-only t))
+ (apply 'kill-region bounds)
+ (goto-char (car bounds))
+ (ignore-errors (diff-beginning-of-hunk t)))))
(defun diff-beginning-of-file-and-junk ()
"Go to the beginning of file-related diff-info.
@@ -723,10 +731,12 @@ data such as \"Index: ...\" and such."
(defun diff-file-kill ()
"Kill current file's hunks."
(interactive)
- (diff-beginning-of-hunk t)
- (let ((inhibit-read-only t))
- (apply 'kill-region (diff-bounds-of-file)))
- (ignore-errors (diff-beginning-of-hunk t)))
+ (if (not (diff--some-hunks-p))
+ (error "No hunks")
+ (diff-beginning-of-hunk t)
+ (let ((inhibit-read-only t))
+ (apply 'kill-region (diff-bounds-of-file)))
+ (ignore-errors (diff-beginning-of-hunk t))))
(defun diff-kill-junk ()
"Kill spurious empty diffs."
@@ -2009,57 +2019,58 @@ Return new point, if it was moved."
"Highlight changes of hunk at point at a finer granularity."
(interactive)
(require 'smerge-mode)
- (save-excursion
- (diff-beginning-of-hunk t)
- (let* ((start (point))
- (style (diff-hunk-style)) ;Skips the hunk header as well.
- (beg (point))
- (props-c '((diff-mode . fine) (face diff-refine-changed)))
- (props-r '((diff-mode . fine) (face diff-refine-removed)))
- (props-a '((diff-mode . fine) (face diff-refine-added)))
- ;; Be careful to go back to `start' so diff-end-of-hunk gets
- ;; to read the hunk header's line info.
- (end (progn (goto-char start) (diff-end-of-hunk) (point))))
-
- (remove-overlays beg end 'diff-mode 'fine)
-
- (goto-char beg)
- (pcase style
- (`unified
- (while (re-search-forward "^-" end t)
- (let ((beg-del (progn (beginning-of-line) (point)))
- beg-add end-add)
- (when (and (diff--forward-while-leading-char ?- end)
- ;; Allow for "\ No newline at end of file".
- (progn (diff--forward-while-leading-char ?\\ end)
- (setq beg-add (point)))
- (diff--forward-while-leading-char ?+ end)
- (progn (diff--forward-while-leading-char ?\\ end)
- (setq end-add (point))))
- (smerge-refine-subst beg-del beg-add beg-add end-add
- nil 'diff-refine-preproc props-r props-a)))))
- (`context
- (let* ((middle (save-excursion (re-search-forward "^---")))
- (other middle))
- (while (re-search-forward "^\\(?:!.*\n\\)+" middle t)
- (smerge-refine-subst (match-beginning 0) (match-end 0)
- (save-excursion
- (goto-char other)
- (re-search-forward "^\\(?:!.*\n\\)+" end)
- (setq other (match-end 0))
- (match-beginning 0))
- other
- (if diff-use-changed-face props-c)
- 'diff-refine-preproc
- (unless diff-use-changed-face props-r)
- (unless diff-use-changed-face props-a)))))
- (_ ;; Normal diffs.
- (let ((beg1 (1+ (point))))
- (when (re-search-forward "^---.*\n" end t)
- ;; It's a combined add&remove, so there's something to do.
- (smerge-refine-subst beg1 (match-beginning 0)
- (match-end 0) end
- nil 'diff-refine-preproc props-r props-a))))))))
+ (when (diff--some-hunks-p)
+ (save-excursion
+ (diff-beginning-of-hunk t)
+ (let* ((start (point))
+ (style (diff-hunk-style)) ;Skips the hunk header as well.
+ (beg (point))
+ (props-c '((diff-mode . fine) (face diff-refine-changed)))
+ (props-r '((diff-mode . fine) (face diff-refine-removed)))
+ (props-a '((diff-mode . fine) (face diff-refine-added)))
+ ;; Be careful to go back to `start' so diff-end-of-hunk gets
+ ;; to read the hunk header's line info.
+ (end (progn (goto-char start) (diff-end-of-hunk) (point))))
+
+ (remove-overlays beg end 'diff-mode 'fine)
+
+ (goto-char beg)
+ (pcase style
+ (`unified
+ (while (re-search-forward "^-" end t)
+ (let ((beg-del (progn (beginning-of-line) (point)))
+ beg-add end-add)
+ (when (and (diff--forward-while-leading-char ?- end)
+ ;; Allow for "\ No newline at end of file".
+ (progn (diff--forward-while-leading-char ?\\ end)
+ (setq beg-add (point)))
+ (diff--forward-while-leading-char ?+ end)
+ (progn (diff--forward-while-leading-char ?\\ end)
+ (setq end-add (point))))
+ (smerge-refine-subst beg-del beg-add beg-add end-add
+ nil 'diff-refine-preproc props-r props-a)))))
+ (`context
+ (let* ((middle (save-excursion (re-search-forward "^---")))
+ (other middle))
+ (while (re-search-forward "^\\(?:!.*\n\\)+" middle t)
+ (smerge-refine-subst (match-beginning 0) (match-end 0)
+ (save-excursion
+ (goto-char other)
+ (re-search-forward "^\\(?:!.*\n\\)+" end)
+ (setq other (match-end 0))
+ (match-beginning 0))
+ other
+ (if diff-use-changed-face props-c)
+ 'diff-refine-preproc
+ (unless diff-use-changed-face props-r)
+ (unless diff-use-changed-face props-a)))))
+ (_ ;; Normal diffs.
+ (let ((beg1 (1+ (point))))
+ (when (re-search-forward "^---.*\n" end t)
+ ;; It's a combined add&remove, so there's something to do.
+ (smerge-refine-subst beg1 (match-beginning 0)
+ (match-end 0) end
+ nil 'diff-refine-preproc props-r props-a)))))))))
(defun diff-undo (&optional arg)
"Perform `undo', ignoring the buffer's read-only status."