]> code.delx.au - gnu-emacs/blobdiff - lisp/vc/smerge-mode.el
Merge from emacs-23; up to 2010-06-10T12:56:11Z!michael.albinus@gmx.de.
[gnu-emacs] / lisp / vc / smerge-mode.el
similarity index 91%
rename from lisp/smerge-mode.el
rename to lisp/vc/smerge-mode.el
index 635217fa3af522fc2ff9a84c21f63a415c4fc878..f26ccdbedda3c7dc7e11b5899ecc4b283c0b06b8 100644 (file)
@@ -1,10 +1,9 @@
-;;; smerge-mode.el --- Minor mode to resolve diff3 conflicts
+;;; smerge-mode.el --- Minor mode to resolve diff3 conflicts -*- lexical-binding: t -*-
 
-;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
-;;   2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+;; Copyright (C) 1999-2011 Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
-;; Keywords: tools revision-control merge diff3 cvs conflict
+;; Keywords: vc, tools, revision control, merge, diff3, cvs, conflict
 
 ;; This file is part of GNU Emacs.
 
@@ -46,7 +45,7 @@
 
 (eval-when-compile (require 'cl))
 (require 'diff-mode)                    ;For diff-auto-refine-mode.
-
+(require 'newcomment)
 
 ;;; The real definition comes later.
 (defvar smerge-mode)
@@ -455,10 +454,41 @@ BUF contains a plain diff between match-1 and match-3."
               (insert ">>>>>>> " name3 "\n")
               (setq line endline))))))))
 
+(defconst smerge-resolve--normalize-re "[\n\t][ \t\n]*\\| [ \t\n]+")
+
+(defun smerge-resolve--extract-comment (beg end)
+  "Extract the text within the comments that span BEG..END."
+  (save-excursion
+    (let ((comments ())
+          combeg)
+      (goto-char beg)
+      (while (and (< (point) end)
+                  (setq combeg (comment-search-forward end t)))
+        (let ((beg (point)))
+          (goto-char combeg)
+          (comment-forward 1)
+          (save-excursion
+            (comment-enter-backward)
+            (push " " comments)
+            (push (buffer-substring-no-properties beg (point)) comments))))
+      (push " " comments)
+      (with-temp-buffer
+        (apply #'insert (nreverse comments))
+        (goto-char (point-min))
+        (while (re-search-forward smerge-resolve--normalize-re
+                                  nil t)
+          (replace-match " "))
+        (buffer-string)))))
+
+(defun smerge-resolve--normalize (beg end)
+  (replace-regexp-in-string
+   smerge-resolve--normalize-re " "
+   (concat " " (buffer-substring-no-properties beg end) " ")))
+
 (defun smerge-resolve (&optional safe)
   "Resolve the conflict at point intelligently.
-This relies on mode-specific knowledge and thus only works in
-some major modes.  Uses `smerge-resolve-function' to do the actual work."
+This relies on mode-specific knowledge and thus only works in some
+major modes.  Uses `smerge-resolve-function' to do the actual work."
   (interactive)
   (smerge-match-conflict)
   (smerge-remove-props (match-beginning 0) (match-end 0))
@@ -472,7 +502,8 @@ some major modes.  Uses `smerge-resolve-function' to do the actual work."
        (m2e (match-end 2))
        (m3e (match-end 3))
        (buf (generate-new-buffer " *smerge*"))
-        m b o)
+        m b o
+        choice)
     (unwind-protect
        (progn
           (cond
@@ -557,6 +588,43 @@ some major modes.  Uses `smerge-resolve-function' to do the actual work."
              (narrow-to-region m0b m0e)
               (smerge-remove-props m0b m0e)
              (insert-file-contents m nil nil nil t)))
+           ;; If the conflict is only made of comments, and one of the two
+           ;; changes is only rearranging spaces (e.g. reflowing text) while
+           ;; the other is a real change, drop the space-rearrangement.
+           ((and m2e
+                 (comment-only-p m1b m1e)
+                 (comment-only-p m2b m2e)
+                 (comment-only-p m3b m3e)
+                 (let ((t1 (smerge-resolve--extract-comment m1b m1e))
+                       (t2 (smerge-resolve--extract-comment m2b m2e))
+                       (t3 (smerge-resolve--extract-comment m3b m3e)))
+                   (cond
+                    ((and (equal t1 t2) (not (equal t2 t3)))
+                     (setq choice 3))
+                    ((and (not (equal t1 t2)) (equal t2 t3))
+                     (setq choice 1)))))
+            (set-match-data md)
+           (smerge-keep-n choice))
+           ;; Idem, when the conflict is contained within a single comment.
+           ((save-excursion
+              (and m2e
+                   (nth 4 (syntax-ppss m0b))
+                   ;; If there's a conflict earlier in the file,
+                   ;; syntax-ppss is not reliable.
+                   (not (re-search-backward smerge-begin-re nil t))
+                   (progn (goto-char (nth 8 (syntax-ppss m0b)))
+                          (forward-comment 1)
+                          (> (point) m0e))
+                   (let ((t1 (smerge-resolve--normalize m1b m1e))
+                         (t2 (smerge-resolve--normalize m2b m2e))
+                         (t3 (smerge-resolve--normalize m3b m3e)))
+                     (cond
+                    ((and (equal t1 t2) (not (equal t2 t3)))
+                     (setq choice 3))
+                    ((and (not (equal t1 t2)) (equal t2 t3))
+                     (setq choice 1))))))
+            (set-match-data md)
+           (smerge-keep-n choice))
            (t
             (error "Don't know how to resolve"))))
       (if (buffer-name buf) (kill-buffer buf))
@@ -815,12 +883,12 @@ Its behavior has mainly two restrictions:
   This only matters if `smerge-refine-weight-hack' is nil.")
 
 (defvar smerge-refine-ignore-whitespace t
-  "If non-nil,Indicate that smerge-refine should try to ignore change in whitespace.")
+  "If non-nil, indicate that `smerge-refine' should try to ignore change in whitespace.")
 
 (defvar smerge-refine-weight-hack t
   "If non-nil, pass to diff as many lines as there are chars in the region.
 I.e. each atomic element (e.g. word) will be copied as many times (on different
-lines) as it has chars.  This has 2 advantages:
+lines) as it has chars.  This has two advantages:
 - if `diff' tries to minimize the number *lines* (rather than chars)
   added/removed, this adjust the weights so that adding/removing long
   symbols is considered correspondingly more costly.
@@ -919,8 +987,8 @@ chars to try and eliminate some spurious differences."
   "Show fine differences in the two regions BEG1..END1 and BEG2..END2.
 PROPS is an alist of properties to put (via overlays) on the changes.
 If non-nil, PREPROC is called with no argument in a buffer that contains
-a copy of a region, just before preparing it to for `diff'.  It can be used to
-replace chars to try and eliminate some spurious differences."
+a copy of a region, just before preparing it to for `diff'.  It can be
+used to replace chars to try and eliminate some spurious differences."
   (let* ((buf (current-buffer))
          (pos (point))
          (file1 (make-temp-file "diff1"))
@@ -988,9 +1056,9 @@ replace chars to try and eliminate some spurious differences."
 
 (defun smerge-refine (&optional part)
   "Highlight the words of the conflict that are different.
-For 3-way conflicts, highlights only 2 of the 3 parts.
-A numeric argument PART can be used to specify which 2 parts;
-repeating the command will highlight other 2 parts."
+For 3-way conflicts, highlights only two of the three parts.
+A numeric argument PART can be used to specify which two parts;
+repeating the command will highlight other two parts."
   (interactive
    (if (integerp current-prefix-arg) (list current-prefix-arg)
      (smerge-match-conflict)
@@ -1009,6 +1077,10 @@ repeating the command will highlight other 2 parts."
   (setq part (cond ((null (match-end 2)) 2)
                    ((eq (match-end 1) (match-end 3)) 1)
                    ((integerp part) part)
+                   ;; If one of the parts is empty, any refinement using
+                   ;; it will be trivial and uninteresting.
+                   ((eq (match-end 1) (match-beginning 1)) 1)
+                   ((eq (match-end 3) (match-beginning 3)) 3)
                    (t 2)))
   (let ((n1 (if (eq part 1) 2 1))
         (n2 (if (eq part 3) 2 3)))
@@ -1161,7 +1233,7 @@ buffer names."
 
 (defun smerge-makeup-conflict (pt1 pt2 pt3 &optional pt4)
   "Insert diff3 markers to make a new conflict.
-Uses point and mark for 2 of the relevant positions and previous marks
+Uses point and mark for two of the relevant positions and previous marks
 for the other ones.
 By default, makes up a 2-way conflict,
 with a \\[universal-argument] prefix, makes up a 3-way conflict."
@@ -1184,7 +1256,7 @@ with a \\[universal-argument] prefix, makes up a 3-way conflict."
     (insert "<<<<<<< MINE\n"))
   (if smerge-mode nil (smerge-mode 1))
   (smerge-refine))
-      
+
 
 (defconst smerge-parsep-re
   (concat smerge-begin-re "\\|" smerge-end-re "\\|"
@@ -1227,5 +1299,4 @@ If no conflict maker is found, turn off `smerge-mode'."
 
 (provide 'smerge-mode)
 
-;; arch-tag: 605c8d1e-e43d-4943-a6f3-1bcc4333e690
 ;;; smerge-mode.el ends here