]> code.delx.au - gnu-emacs/blobdiff - lisp/smerge-mode.el
(ps-zebra-stripe-follow): Don't quote nil and t in docstrings.
[gnu-emacs] / lisp / smerge-mode.el
index 5b182b28e8a0a44bde395e15a03b16d3fd761267..108eff0775996f386e8b9b6073010c846bf94d4a 100644 (file)
@@ -1,10 +1,10 @@
 ;;; smerge-mode.el --- Minor mode to resolve diff3 conflicts
 
-;; Copyright (C) 1999, 2000  Free Software Foundation, Inc.
+;; Copyright (C) 1999, 2000, 2001  Free Software Foundation, Inc.
 
 ;; Author: Stefan Monnier <monnier@cs.yale.edu>
 ;; Keywords: merge diff3 cvs conflict
-;; Revision: $Id: smerge-mode.el,v 1.7 2000/10/06 16:07:31 monnier Exp $
+;; Revision: $Id: smerge-mode.el,v 1.20 2002/10/10 17:30:20 monnier Exp $
 
 ;; This file is part of GNU Emacs.
 
@@ -38,7 +38,7 @@
 ;;      (goto-char (point-min))
 ;;      (when (re-search-forward "^<<<<<<< " nil t)
 ;;        (smerge-mode 1))))
-;;   (add-hook 'find-file-hooks 'sm-try-smerge t)
+;;   (add-hook 'find-file-hook 'sm-try-smerge t)
 
 ;;; Todo:
 
@@ -54,7 +54,7 @@
   :group 'tools
   :prefix "smerge-")
 
-(defcustom smerge-diff-buffer-name "*smerge-diff*"
+(defcustom smerge-diff-buffer-name "*vc-diff*"
   "Buffer name to use for displaying diffs."
   :group 'smerge
   :type '(choice
@@ -115,6 +115,7 @@ Used in `smerge-diff-base-mine' and related functions."
 (easy-mmode-defmap smerge-basic-map
   `(("n" . smerge-next)
     ("p" . smerge-prev)
+    ("r" . smerge-resolve)
     ("a" . smerge-keep-all)
     ("b" . smerge-keep-base)
     ("o" . smerge-keep-other)
@@ -160,7 +161,7 @@ Used in `smerge-diff-base-mine' and related functions."
 
 (defconst smerge-font-lock-keywords
   '((smerge-find-conflict
-     (1 smerge-mine-face prepend)
+     (1 smerge-mine-face prepend t)
      (2 smerge-base-face prepend t)
      (3 smerge-other-face prepend t)
      ;; FIXME: `keep' doesn't work right with syntactic fontification.
@@ -181,11 +182,8 @@ Can be nil if the style is undecided, or else:
 - `diff3-A'")
 
 ;; Compiler pacifiers
-(defvar font-lock-mode nil)
-(defvar font-lock-keywords nil)
-(eval-when-compile
-  (unless (fboundp 'font-lock-fontify-region)
-    (autoload 'font-lock-fontify-region "font-lock")))
+(defvar font-lock-mode)
+(defvar font-lock-keywords)
 
 ;;;;
 ;;;; Actual code
@@ -205,7 +203,7 @@ Can be nil if the style is undecided, or else:
             (save-excursion (goto-char (point-min))
                             (not (re-search-forward smerge-begin-re nil t))))
     (smerge-mode -1)))
-    
+
 
 (defun smerge-keep-all ()
   "Keep all three versions.
@@ -218,6 +216,54 @@ Convenient for the kind of conflicts that can arise in ChangeLog files."
                 t t)
   (smerge-auto-leave))
 
+(defun smerge-combine-with-next ()
+  "Combine the current conflict with the next one."
+  (interactive)
+  (smerge-match-conflict)
+  (let ((ends nil))
+    (dolist (i '(3 2 1 0))
+      (push (if (match-end i) (copy-marker (match-end i) t)) ends))
+    (setq ends (apply 'vector ends))
+    (goto-char (aref ends 0))
+    (if (not (re-search-forward smerge-begin-re nil t))
+       (error "No next conflict")
+      (smerge-match-conflict)
+      (let ((match-data (mapcar (lambda (m) (if m (copy-marker m)))
+                               (match-data))))
+       ;; First copy the in-between text in each alternative.
+       (dolist (i '(1 2 3))
+         (when (aref ends i)
+           (goto-char (aref ends i))
+           (insert-buffer-substring (current-buffer)
+                                    (aref ends 0) (car match-data))))
+       (delete-region (aref ends 0) (car match-data))
+       ;; Then move the second conflict's alternatives into the first.
+       (dolist (i '(1 2 3))
+         (set-match-data match-data)
+         (when (and (aref ends i) (match-end i))
+           (goto-char (aref ends i))
+           (insert-buffer-substring (current-buffer)
+                                    (match-beginning i) (match-end i))))
+       (delete-region (car match-data) (cadr match-data))
+       ;; Free the markers.
+       (dolist (m match-data) (if m (move-marker m nil)))
+       (mapc (lambda (m) (if m (move-marker m nil))) ends)))))
+
+(defvar smerge-resolve-function
+  (lambda () (error "Don't know how to resolve"))
+  "Mode-specific merge function.
+The function is called with no argument and with the match data set
+according to `smerge-match-conflict'.")
+
+(defun smerge-resolve ()
+  "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."
+  (interactive)
+  (smerge-match-conflict)
+  (funcall smerge-resolve-function)
+  (smerge-auto-leave))
+
 (defun smerge-keep-base ()
   "Revert to the base version."
   (interactive)
@@ -287,11 +333,11 @@ An error is raised if not inside a conflict."
 
               (start (match-beginning 0))
               (mine-start (match-end 0))
-              (filename (match-string 1))
+              (filename (or (match-string 1) ""))
 
               (_ (re-search-forward smerge-end-re))
               (_ (assert (< orig-point (match-end 0))))
-              
+
               (other-end (match-beginning 0))
               (end (match-end 0))
 
@@ -324,7 +370,7 @@ An error is raised if not inside a conflict."
           (setq base-end   mine-end)
           (setq mine-start other-start)
           (setq mine-end   other-end)))
-              
+
          (store-match-data (list start end
                                  mine-start mine-end
                                  base-start base-end
@@ -332,7 +378,7 @@ An error is raised if not inside a conflict."
                                  (when base-start (1- base-start)) base-start
                                  (1- other-start) other-start))
          t)
-      (error "Point not in conflict region"))))
+      (search-failed (error "Point not in conflict region")))))
 
 (defun smerge-find-conflict (&optional limit)
   "Find and match a conflict region.  Intended as a font-lock MATCHER.
@@ -350,48 +396,58 @@ The point is moved to the end of the conflict."
   (smerge-ensure-match n2)
   (let ((name1 (aref smerge-match-names n1))
        (name2 (aref smerge-match-names n2))
+       ;; Read them before the match-data gets clobbered.
+       (beg1 (match-beginning n1))
+       (end1 (match-end n1))
+       (beg2 (match-beginning n2))
+       (end2 (match-end n2))
        (file1 (make-temp-file "smerge1"))
        (file2 (make-temp-file "smerge2"))
        (dir default-directory)
-       (file (file-relative-name buffer-file-name)))
-    (write-region (match-beginning n1) (match-end n1) file1)
-    (write-region (match-beginning n2) (match-end n2) file2)
+       (file (file-relative-name buffer-file-name))
+       (coding-system-for-read buffer-file-coding-system))
+    (write-region beg1 end1 file1 nil 'nomessage)
+    (write-region beg2 end2 file2 nil 'nomessage)
     (unwind-protect
        (with-current-buffer (get-buffer-create smerge-diff-buffer-name)
          (setq default-directory dir)
          (let ((inhibit-read-only t))
            (erase-buffer)
-           (apply 'call-process diff-command nil t nil
-                  (append smerge-diff-switches
-                          (list "-L" (concat name1 "/" file)
-                                "-L" (concat name2 "/" file)
-                                file1 file2))))
+           (let ((status
+                  (apply 'call-process diff-command nil t nil
+                         (append smerge-diff-switches
+                                 (list "-L" (concat name1 "/" file)
+                                       "-L" (concat name2 "/" file)
+                                       file1 file2)))))
+             (if (eq status 0) (insert "No differences found.\n"))))
          (goto-char (point-min))
          (diff-mode)
          (display-buffer (current-buffer) t))
       (delete-file file1)
       (delete-file file2))))
 
-(eval-when-compile
-  ;; compiler pacifiers
-  (defvar smerge-ediff-windows)
-  (defvar smerge-ediff-buf)
-  (defvar ediff-buffer-A)
-  (defvar ediff-buffer-B)
-  (defvar ediff-buffer-C)
-  (unless (fboundp 'ediff-cleanup-mess)
-    (autoload 'ediff-cleanup-mess "ediff-util")))
-
-(defun smerge-ediff ()
-  "Invoke ediff to resolve the conflicts."
+;; compiler pacifiers
+(defvar smerge-ediff-windows)
+(defvar smerge-ediff-buf)
+(defvar ediff-buffer-A)
+(defvar ediff-buffer-B)
+(defvar ediff-buffer-C)
+
+;;;###autoload
+(defun smerge-ediff (&optional name-mine name-other name-base)
+  "Invoke ediff to resolve the conflicts.
+NAME-MINE, NAME-OTHER, and NAME-BASE, if non-nil, are used for the
+buffer names."
   (interactive)
   (let* ((buf (current-buffer))
         (mode major-mode)
         ;;(ediff-default-variant 'default-B)
         (config (current-window-configuration))
         (filename (file-name-nondirectory buffer-file-name))
-        (mine (generate-new-buffer (concat "*" filename " MINE*")))
-        (other (generate-new-buffer (concat "*" filename " OTHER*")))
+        (mine (generate-new-buffer
+               (or name-mine (concat "*" filename " MINE*"))))
+        (other (generate-new-buffer
+                (or name-other (concat "*" filename " OTHER*"))))
         base)
     (with-current-buffer mine
       (buffer-disable-undo)
@@ -413,9 +469,10 @@ The point is moved to the end of the conflict."
       (buffer-enable-undo)
       (set-buffer-modified-p nil)
       (funcall mode))
-    
+
     (when base
-      (setq base (generate-new-buffer (concat "*" filename " BASE*")))
+      (setq base (generate-new-buffer
+                 (or name-base (concat "*" filename " BASE*"))))
       (with-current-buffer base
        (buffer-disable-undo)
        (insert-buffer-substring buf)
@@ -425,7 +482,7 @@ The point is moved to the end of the conflict."
        (buffer-enable-undo)
        (set-buffer-modified-p nil)
        (funcall mode)))
-    
+
     ;; the rest of the code is inspired from vc.el
     ;; Fire up ediff.
     (set-buffer
@@ -434,7 +491,7 @@ The point is moved to the end of the conflict."
          ;; nil 'ediff-merge-revisions-with-ancestor buffer-file-name)
        (ediff-merge-buffers mine other)))
         ;; nil 'ediff-merge-revisions buffer-file-name)))
-    
+
     ;; Ediff is now set up, and we are in the control buffer.
     ;; Do a few further adjustments and take precautions for exit.
     (set (make-local-variable 'smerge-ediff-windows) config)
@@ -465,48 +522,17 @@ The point is moved to the end of the conflict."
   "Minor mode to simplify editing output from the diff3 program.
 \\{smerge-mode-map}"
   nil " SMerge" nil
-  (when font-lock-mode
+  (when (and (boundp 'font-lock-mode) font-lock-mode)
+    (set (make-local-variable 'font-lock-multiline) t)
     (save-excursion
       (if smerge-mode
          (font-lock-add-keywords nil smerge-font-lock-keywords 'append)
        (font-lock-remove-keywords nil smerge-font-lock-keywords))
       (goto-char (point-min))
       (while (smerge-find-conflict)
-       (font-lock-fontify-region (match-beginning 0) (match-end 0) nil)))))
+       (save-excursion
+         (font-lock-fontify-region (match-beginning 0) (match-end 0) nil))))))
 
 
 (provide 'smerge-mode)
-
-;;; Change Log:
-;; $Log: smerge-mode.el,v $
-;; Revision 1.7  2000/10/06 16:07:31  monnier
-;; (smerge-diff): Setup the buffer's default-directory
-;; and add filename to the names so that diff-mode can jump to source.
-;;
-;; Revision 1.6  2000/10/05 06:05:51  miles
-;; (smerge-mine-face, smerge-other-face, smerge-base-face, smerge-markers-face):
-;;   Add dark-background variants.
-;;
-;; Revision 1.5  2000/08/16 19:51:55  monnier
-;; (smerge-mode-menu): Doc fix.
-;;
-;; Revision 1.4  2000/07/21 13:52:19  fx
-;; (smerge-mode-menu): Fill it out.
-;;
-;; Revision 1.3  2000/05/25 18:08:26  fx
-;; (smerge-diff-switches): Don't use list* in defcustom.
-;;
-;; Revision 1.2  2000/03/22 00:54:55  monnier
-;; (smerge-auto-leave): New function and variable.
-;; (smerge-basic-map): Rename from smerge-basic-keymap.
-;; Change the bindings for smerge-diff-*.
-;; (smerge-*-map): Use easy-mmode-defmap.
-;; (smerge-(next|prev)): Use easy-mmode-define-navigation.
-;; (smerge-keep-*): Use smerge-auto-leave.
-;;
-;; Revision 1.1  1999/12/09 13:00:21  monnier
-;; New file.  Provides a simple minor-mode for files containing
-;; diff3-style conflict markers, such as generated by RCS
-;;
-
 ;;; smerge-mode.el ends here