diff options
author | Tino Calancha <tino.calancha@gmail.com> | 2017-02-02 22:27:33 +0900 |
---|---|---|
committer | Tino Calancha <tino.calancha@gmail.com> | 2017-02-02 22:27:33 +0900 |
commit | a362b56b51f49963dbb63cd318967bca9b9fef74 (patch) | |
tree | 3583aa5b18eeed72ad80bbe85726ad8174945c2e | |
parent | 01d87bf846b478dea0bfe824678e76089f5af2c7 (diff) | |
download | emacs-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.el | 159 |
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." |