From fd69179929b3a9210ce9f4a49dfcacfe1b6d552e Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Sun, 22 Jul 2007 21:26:34 +0000 Subject: (diff-beginning-of-file-and-junk): New function. (diff-file-kill): Use it. (diff-beginning-of-hunk): Add arg `try-harder' using it. (diff-restrict-view, diff-find-source-location, diff-refine-hunk): Use it so they find the hunk even when we're in the file header. --- lisp/diff-mode.el | 52 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 12 deletions(-) (limited to 'lisp/diff-mode.el') diff --git a/lisp/diff-mode.el b/lisp/diff-mode.el index 64199147c21..358df76ba2f 100644 --- a/lisp/diff-mode.el +++ b/lisp/diff-mode.el @@ -390,13 +390,20 @@ when editing big diffs)." ;; The return value is used by easy-mmode-define-navigation. (goto-char (or end (point-max))))) -(defun diff-beginning-of-hunk () +(defun diff-beginning-of-hunk (&optional try-harder) + "Move back to beginning of hunk. +If TRY-HARDER is non-nil, try to cater to the case where we're not in a hunk +but in the file header instead, in which case move forward to the first hunk." (beginning-of-line) (unless (looking-at diff-hunk-header-re) (forward-line 1) (condition-case () (re-search-backward diff-hunk-header-re) - (error (error "Can't find the beginning of the hunk"))))) + (error + (if (not try-harder) + (error "Can't find the beginning of the hunk") + (diff-beginning-of-file-and-junk) + (diff-hunk-next)))))) (defun diff-beginning-of-file () (beginning-of-line) @@ -425,7 +432,7 @@ when editing big diffs)." If the prefix ARG is given, restrict the view to the current file instead." (interactive "P") (save-excursion - (if arg (diff-beginning-of-file) (diff-beginning-of-hunk)) + (if arg (diff-beginning-of-file) (diff-beginning-of-hunk 'try-harder)) (narrow-to-region (point) (progn (if arg (diff-end-of-file) (diff-end-of-hunk)) (point))) @@ -453,18 +460,37 @@ If the prefix ARG is given, restrict the view to the current file instead." (diff-end-of-hunk) (kill-region start (point))))) +(defun diff-beginning-of-file-and-junk () + "Go to the beginning of file-related diff-info. +This is like `diff-beginning-of-file' except it tries to skip back over leading +data such as \"Index: ...\" and such." + (let ((start (point)) + (file (condition-case err (progn (diff-beginning-of-file) (point)) + (error err))) + ;; prevhunk is one of the limits. + (prevhunk (save-excursion (ignore-errors (diff-hunk-prev) (point)))) + err) + (when (consp file) + ;; Presumably, we started before the file header, in the leading junk. + (setq err file) + (diff-file-next) + (setq file (point))) + (let ((index (save-excursion + (re-search-backward "^Index: " prevhunk t)))) + (when index (setq file index)) + (if (<= file start) + (goto-char file) + ;; File starts *after* the starting point: we really weren't in + ;; a file diff but elsewhere. + (goto-char start) + (signal (car err) (cdr err)))))) + (defun diff-file-kill () "Kill current file's hunks." (interactive) - (diff-beginning-of-file) + (diff-beginning-of-file-and-junk) (let* ((start (point)) - (prevhunk (save-excursion - (ignore-errors - (diff-hunk-prev) (point)))) - (index (save-excursion - (re-search-backward "^Index: " prevhunk t))) (inhibit-read-only t)) - (when index (setq start index)) (diff-end-of-file) (if (looking-at "^\n") (forward-char 1)) ;`tla' generates such diffs. (kill-region start (point)))) @@ -1289,7 +1315,8 @@ SRC and DST are the two variants of text as returned by `diff-hunk-text'. SWITCHED is non-nil if the patch is already applied." (save-excursion (let* ((other (diff-xor other-file diff-jump-to-old-file)) - (char-offset (- (point) (progn (diff-beginning-of-hunk) (point)))) + (char-offset (- (point) (progn (diff-beginning-of-hunk 'try-harder) + (point)))) ;; Check that the hunk is well-formed. Otherwise diff-mode and ;; the user may disagree on what constitutes the hunk ;; (e.g. because an empty line truncates the hunk mid-course), @@ -1464,7 +1491,8 @@ For use in `add-log-current-defun-function'." (defun diff-refine-hunk () "Refine the current hunk by ignoring space differences." (interactive) - (let* ((char-offset (- (point) (progn (diff-beginning-of-hunk) (point)))) + (let* ((char-offset (- (point) (progn (diff-beginning-of-hunk 'try-harder) + (point)))) (opts (case (char-after) (?@ "-bu") (?* "-bc") (t "-b"))) (line-nb (and (or (looking-at "[^0-9]+\\([0-9]+\\)") (error "Can't find line number")) -- cgit v1.2.3 From e4456fdfc897d527b46cc5e10d357f99402da53b Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Sun, 22 Jul 2007 21:28:14 +0000 Subject: (diff-find-file-name): Add arg `batch'. --- lisp/ChangeLog | 2 ++ lisp/diff-mode.el | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'lisp/diff-mode.el') diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 62efce60a3e..668cda526f9 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,5 +1,7 @@ 2007-07-22 Stefan Monnier + * diff-mode.el (diff-find-file-name): Add arg `batch'. + * diff-mode.el (diff-beginning-of-file-and-junk): New function. (diff-file-kill): Use it. (diff-beginning-of-hunk): Add arg `try-harder' using it. diff --git a/lisp/diff-mode.el b/lisp/diff-mode.el index 358df76ba2f..ecd32f4c331 100644 --- a/lisp/diff-mode.el +++ b/lisp/diff-mode.el @@ -611,9 +611,11 @@ If the OLD prefix arg is passed, tell the file NAME of the old file." (list (if old (match-string 2) (match-string 4)) (if old (match-string 4) (match-string 2))))))))) -(defun diff-find-file-name (&optional old prefix) +(defun diff-find-file-name (&optional old batch prefix) "Return the file corresponding to the current patch. Non-nil OLD means that we want the old file. +Non-nil BATCH means to prefer returning an incorrect answer than to prompt +the user. PREFIX is only used internally: don't use it." (save-excursion (unless (looking-at diff-file-header-re) @@ -648,7 +650,10 @@ PREFIX is only used internally: don't use it." (boundp 'cvs-pcl-cvs-dirchange-re) (save-excursion (re-search-backward cvs-pcl-cvs-dirchange-re nil t)) - (diff-find-file-name old (match-string 1))) + (diff-find-file-name old batch (match-string 1))) + ;; Invent something, if necessary. + (when batch + (or (car fs) default-directory)) ;; if all else fails, ask the user (let ((file (read-file-name (format "Use file %s: " (or (first fs) "")) nil (first fs) t (first fs)))) -- cgit v1.2.3 From 3dc04e8360589cfdf59f6919ee38c0ec1b50c5fe Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Sun, 22 Jul 2007 21:38:28 +0000 Subject: (diff-unified->context): Use the new `apply' undo entry kind if applicable, so as to save undo-log space. --- lisp/ChangeLog | 3 +++ lisp/diff-mode.el | 25 +++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) (limited to 'lisp/diff-mode.el') diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 668cda526f9..dc71e83d69d 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,5 +1,8 @@ 2007-07-22 Stefan Monnier + * diff-mode.el (diff-unified->context): Use the new `apply' undo entry + if applicable, so as to save undo-log space. + * diff-mode.el (diff-find-file-name): Add arg `batch'. * diff-mode.el (diff-beginning-of-file-and-junk): New function. diff --git a/lisp/diff-mode.el b/lisp/diff-mode.el index ecd32f4c331..3c0208d5b27 100644 --- a/lisp/diff-mode.el +++ b/lisp/diff-mode.el @@ -701,7 +701,12 @@ else cover the whole bufer." (let ((line1 (match-string 4)) (lines1 (match-string 5)) (line2 (match-string 6)) - (lines2 (match-string 7))) + (lines2 (match-string 7)) + ;; Variables to use the special undo function. + (old-undo buffer-undo-list) + (old-end (marker-position end)) + (start (match-beginning 0)) + (reversible t)) (replace-match (concat "***************\n*** " line1 "," (number-to-string (+ (string-to-number line1) @@ -743,6 +748,14 @@ else cover the whole bufer." (if (not (save-excursion (re-search-forward "^+" nil t))) (delete-region (point) (point-max)) (let ((modif nil) (delete nil)) + (if (save-excursion (re-search-forward "^\\+.*\n-" nil t)) + ;; Normally, lines in a substitution come with + ;; first the removals and then the additions, and + ;; the context->unified function follows this + ;; convention, of course. Yet, other alternatives + ;; are valid as well, but they preclude the use of + ;; context->unified as an undo command. + (setq reversible nil)) (while (not (eobp)) (case (char-after) (?\s (insert " ") (setq modif nil) (backward-char 1)) @@ -761,7 +774,15 @@ else cover the whole bufer." (forward-line 1) (when delete (delete-region last-pt (point)) - (setq delete nil))))))))))))))) + (setq delete nil))))))) + (unless (or (not reversible) (eq buffer-undo-list t)) + ;; Drop the many undo entries and replace them with + ;; a single entry that uses diff-context->unified to do + ;; the work. + (setq buffer-undo-list + (cons (list 'apply (- old-end end) start (point-max) + 'diff-context->unified start (point-max)) + old-undo))))))))))) (defun diff-context->unified (start end &optional to-context) "Convert context diffs to unified diffs. -- cgit v1.2.3 From 8f2d38de67278017981023e70e331f0d42aa7927 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Sun, 22 Jul 2007 21:59:55 +0000 Subject: *** empty log message *** --- lisp/ChangeLog | 4 ++++ lisp/diff-mode.el | 13 ++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'lisp/diff-mode.el') diff --git a/lisp/ChangeLog b/lisp/ChangeLog index dc71e83d69d..043592ab416 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,7 @@ +2007-07-22 Dan Nicolaescu + + * diff-mode.el (diff-mode-menu): New entries. + 2007-07-22 Stefan Monnier * diff-mode.el (diff-unified->context): Use the new `apply' undo entry diff --git a/lisp/diff-mode.el b/lisp/diff-mode.el index 3c0208d5b27..cfebb365770 100644 --- a/lisp/diff-mode.el +++ b/lisp/diff-mode.el @@ -164,12 +164,23 @@ when editing big diffs)." '("Diff" ["Jump to Source" diff-goto-source t] ["Apply hunk" diff-apply-hunk t] + ["Test applying hunk" diff-test-hunk t] ["Apply diff with Ediff" diff-ediff-patch t] - ["-----" nil nil] + "-----" ["Reverse direction" diff-reverse-direction t] ["Context -> Unified" diff-context->unified t] ["Unified -> Context" diff-unified->context t] ;;["Fixup Headers" diff-fixup-modifs (not buffer-read-only)] + "-----" + ["Split hunk" diff-split-hunk t] + ["Refine hunk" diff-refine-hunk t] + ["Kill current hunk" diff-hunk-kill t] + ["Kill current file's hunks" diff-file-kill t] + "-----" + ["Previous Hunk" diff-hunk-prev t] + ["Next Hunk" diff-hunk-next t] + ["Previous File" diff-file-prev t] + ["Next File" diff-file-next t] )) (defcustom diff-minor-mode-prefix "\C-c=" -- cgit v1.2.3 From f151b310f65fd73924a32b566a17b3f44279c72a Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Sun, 22 Jul 2007 22:02:49 +0000 Subject: (diff-refine-ignore-spaces-hunk): Rename from diff-refine-hunk. Adjust users. (diff-unified-hunk-p, diff-splittable-p): New functions. (diff-mode-menu): Use it to disable Split when it doesn't work. --- lisp/ChangeLog | 7 +++++++ lisp/diff-mode.el | 21 +++++++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) (limited to 'lisp/diff-mode.el') diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 043592ab416..ad16626bd71 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,10 @@ +2007-07-22 Stefan Monnier + + * diff-mode.el (diff-refine-ignore-spaces-hunk): Rename from + diff-refine-hunk. Adjust users. + (diff-unified-hunk-p, diff-splittable-p): New functions. + (diff-mode-menu): Use it to disable Split when it doesn't work. + 2007-07-22 Dan Nicolaescu * diff-mode.el (diff-mode-menu): New entries. diff --git a/lisp/diff-mode.el b/lisp/diff-mode.el index cfebb365770..a1bd0afa126 100644 --- a/lisp/diff-mode.el +++ b/lisp/diff-mode.el @@ -155,7 +155,7 @@ when editing big diffs)." ("\C-c\C-u" . diff-context->unified) ;; `d' because it duplicates the context :-( --Stef ("\C-c\C-d" . diff-unified->context) - ("\C-c\C-w" . diff-refine-hunk) + ("\C-c\C-w" . diff-refine-ignore-spaces-hunk) ("\C-c\C-f" . next-error-follow-minor-mode)) "Keymap for `diff-mode'. See also `diff-mode-shared-map'.") @@ -172,8 +172,8 @@ when editing big diffs)." ["Unified -> Context" diff-unified->context t] ;;["Fixup Headers" diff-fixup-modifs (not buffer-read-only)] "-----" - ["Split hunk" diff-split-hunk t] - ["Refine hunk" diff-refine-hunk t] + ["Split hunk" diff-split-hunk (diff-splittable-p)] + ["Refine hunk" diff-refine-ignore-spaces-hunk t] ["Kill current hunk" diff-hunk-kill t] ["Kill current file's hunks" diff-file-kill t] "-----" @@ -416,6 +416,12 @@ but in the file header instead, in which case move forward to the first hunk." (diff-beginning-of-file-and-junk) (diff-hunk-next)))))) +(defun diff-unified-hunk-p () + (save-excursion + (ignore-errors + (diff-beginning-of-hunk) + (looking-at "^@@")))) + (defun diff-beginning-of-file () (beginning-of-line) (unless (looking-at diff-file-header-re) @@ -528,6 +534,13 @@ data such as \"Index: ...\" and such." (while (re-search-forward re end t) (incf n)) n))) +(defun diff-splittable-p () + (save-excursion + (beginning-of-line) + (and (looking-at "^[-+ ]") + (progn (forward-line -1) (looking-at "^[-+ ]")) + (diff-unified-hunk-p)))) + (defun diff-split-hunk () "Split the current (unified diff) hunk at point into two hunks." (interactive) @@ -1525,7 +1538,7 @@ For use in `add-log-current-defun-function'." (goto-char (+ (car pos) (cdr src))) (add-log-current-defun)))))) -(defun diff-refine-hunk () +(defun diff-refine-ignore-spaces-hunk () "Refine the current hunk by ignoring space differences." (interactive) (let* ((char-offset (- (point) (progn (diff-beginning-of-hunk 'try-harder) -- cgit v1.2.3