]> code.delx.au - gnu-emacs/blobdiff - lisp/ediff.el
Fix a typo in a comment. Reported by Michel de Ruiter <Michel@smr.nl>.
[gnu-emacs] / lisp / ediff.el
index ea7d747a70ae2b43ec77aa5b069d146edce5e32b..efab0dec0d1af2c9f2c0589e10a3e5a6e11acbde 100644 (file)
@@ -1,13 +1,13 @@
 ;;; ediff.el --- a comprehensive visual interface to diff & patch
 
-;; Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+;; Copyright (C) 1994, 95, 96, 97, 98, 99, 2000 Free Software Foundation, Inc.
 
 ;; Author: Michael Kifer <kifer@cs.sunysb.edu>
 ;; Created: February 2, 1994
 ;; Keywords: comparing, merging, patching, version control.
 
-(defconst ediff-version "2.67" "The current version of Ediff")
-(defconst ediff-date "August 7, 1997" "Date of last update")  
+(defconst ediff-version "2.74" "The current version of Ediff")
+(defconst ediff-date "October 31, 1999" "Date of last update")  
 
 
 ;; This file is part of GNU Emacs.
@@ -42,7 +42,7 @@
 ;; another (and recover old differences if you change your mind).
 
 ;; Ediff also supports merging operations on files and buffers, including
-;; merging using ancestor versions. Both comparison and merging operations can
+;; merging using ancestor versions.  Both comparison and merging operations can
 ;; be performed on directories, i.e., by pairwise comparison of files in those
 ;; directories.
 
 ;; you don't like).
 
 ;; Ediff is aware of version control, which lets the user compare
-;; files with their older versions. Ediff can also work with remote and
-;; compressed files. Details are given below.
+;; files with their older versions.  Ediff can also work with remote and
+;; compressed files.  Details are given below.
 
 ;; Finally, Ediff supports directory-level comparison, merging and patching.
 ;; See the on-line manual for details.
 
 ;; This package builds upon the ideas borrowed from emerge.el and several
-;; Ediff's functions are adaptations from emerge.el. Much of the functionality
+;; Ediff's functions are adaptations from emerge.el.  Much of the functionality
 ;; Ediff provides is also influenced by emerge.el.
 
-;; The present version of Ediff supersedes Emerge. It provides a superior user
-;; interface and has numerous major features not found in Emerge. In
+;; The present version of Ediff supersedes Emerge.  It provides a superior user
+;; interface and has numerous major features not found in Emerge.  In
 ;; particular, it can do patching, and 2-way and 3-way file comparison,
 ;; merging, and directory operations.
 
@@ -75,7 +75,7 @@
 
 ;;; Bugs:
 
-;;  1. The undo command doesn't restore deleted regions well. That is, if
+;;  1. The undo command doesn't restore deleted regions well.  That is, if
 ;;  you delete all characters in a difference region and then invoke
 ;;  `undo', the reinstated text will most likely be inserted outside of
 ;;  what Ediff thinks is the current difference region. (This problem
 ;;  you can hit '!' to recompute the differences.
 
 ;;  2. On a monochrome display, the repertoire of faces with which to
-;;  highlight fine differences is limited. By default, Ediff is using
-;;  underlining. However, if the region is already underlined by some other
+;;  highlight fine differences is limited.  By default, Ediff is using
+;;  underlining.  However, if the region is already underlined by some other
 ;;  overlays, there is no simple way to temporarily remove that residual
-;;  underlining. This problem occurs when a buffer is highlighted with
-;;  hilit19.el or font-lock.el packages. If this residual highlighting gets
-;;  in the way, you can do the following. Both font-lock.el and hilit19.el
-;;  provide commands for unhighlighting buffers. You can either place these
+;;  underlining.  This problem occurs when a buffer is highlighted with
+;;  hilit19.el or font-lock.el packages.  If this residual highlighting gets
+;;  in the way, you can do the following.  Both font-lock.el and hilit19.el
+;;  provide commands for unhighlighting buffers.  You can either place these
 ;;  commands in `ediff-prepare-buffer-hook' (which will unhighlight every
 ;;  buffer used by Ediff) or you can execute them interactively, at any time
 ;;  and on any buffer.
 
 ;; Ediff was inspired by Dale R. Worley's <drw@math.mit.edu> emerge.el.
 ;; Ediff would not have been possible without the help and encouragement of
-;; its many users. See Ediff on-line Info for the full list of those who
-;; helped. Improved defaults in Ediff file-name reading commands.
+;; its many users.  See Ediff on-line Info for the full list of those who
+;; helped.  Improved defaults in Ediff file-name reading commands.
 
 ;;; Code:
 
 ;; BUFFER-NAME is a variable symbol, which will get the buffer object into
 ;; which FILE is read.
 ;; LAST-DIR is the directory variable symbol where FILE's
-;; directory name should be returned. HOOKS-VAR is a variable symbol that will
+;; directory name should be returned.  HOOKS-VAR is a variable symbol that will
 ;; be assigned the hook to be executed after `ediff-startup' is finished.
 ;; `ediff-find-file' arranges that the temp files it might create will be
 ;; deleted.
 (defun ediff-find-file (file-var buffer-name &optional last-dir hooks-var)
   (let* ((file (symbol-value file-var))
-        (file-magic (find-file-name-handler file 'find-file-noselect))
+        (file-magic (ediff-filename-magic-p file))
         (temp-file-name-prefix (file-name-nondirectory file)))
     (cond ((not (file-readable-p file))
           (error "File `%s' does not exist or is not readable" file))
             (setq file
                   (ediff-make-temp-file
                    (current-buffer) temp-file-name-prefix))
-            (set hooks-var (cons (` (lambda () (delete-file (, file))))
+            (set hooks-var (cons `(lambda () (delete-file ,file))
                                  (symbol-value hooks-var))))
            ;; file processed via auto-mode-alist, a la uncompress.el
            ((not (equal (file-truename file)
             (setq file
                   (ediff-make-temp-file
                    (current-buffer) temp-file-name-prefix))
-            (set hooks-var (cons (` (lambda () (delete-file (, file))))
+            (set hooks-var (cons `(lambda () (delete-file ,file))
                                  (symbol-value hooks-var))))
            (t ;; plain file---just check that the file matches the buffer
             (ediff-verify-file-buffer))))
     (set file-var file)))
 
-(defun ediff-files-internal (file-A file-B file-C startup-hooks job-name)
+;; MERGE-BUFFER-FILE is the file to be associated with the merge buffer
+(defun ediff-files-internal (file-A file-B file-C startup-hooks job-name
+                                   &optional merge-buffer-file)
   (let (buf-A buf-B buf-C)
     (message "Reading file %s ... " file-A)
     ;;(sit-for 0)
                 buf-B file-B
                 buf-C file-C
                 startup-hooks
-                (list (cons 'ediff-job-name job-name)))))
+                (list (cons 'ediff-job-name job-name))
+                merge-buffer-file)))
   
 
 ;;;###autoload
       
 
                        
-(defun ediff-buffers-internal (buf-A buf-B buf-C startup-hooks job-name)
+;; MERGE-BUFFER-FILE is the file to be associated with the merge buffer
+(defun ediff-buffers-internal (buf-A buf-B buf-C startup-hooks job-name
+                                    &optional merge-buffer-file)
   (let* ((buf-A-file-name (buffer-file-name (get-buffer buf-A)))
         (buf-B-file-name (buffer-file-name (get-buffer buf-B)))
         (buf-C-is-alive (ediff-buffer-live-p buf-C))
                 (get-buffer buf-B) file-B
                 (if buf-C-is-alive (get-buffer buf-C))
                 file-C
-                (cons (` (lambda ()
-                           (delete-file (, file-A))
-                           (delete-file (, file-B))
-                           (if (stringp (, file-C)) (delete-file (, file-C)))
-                           ))
+                (cons `(lambda ()
+                         (delete-file ,file-A)
+                         (delete-file ,file-B)
+                         (if (stringp ,file-C) (delete-file ,file-C)))
                       startup-hooks)
                 (list (cons 'ediff-job-name job-name))
-                )))
+                merge-buffer-file)))
 
 
 ;;; Directory and file group operations
 ;;;###autoload
 (defun ediff-directories (dir1 dir2 regexp)
   "Run Ediff on a pair of directories, DIR1 and DIR2, comparing files that have
-the same name in both. The third argument, REGEXP, is a regular expression that
-can be used to filter out certain file names."
+the same name in both.  The third argument, REGEXP, is a regular expression
+that can be used to filter out certain file names."
   (interactive
    (let ((dir-A (ediff-get-default-directory-name))
         f)
@@ -480,7 +484,7 @@ can be used to filter out certain file names."
 (defun ediff-directory-revisions (dir1 regexp)
   "Run Ediff on a directory, DIR1, comparing its files with their revisions.
 The second argument, REGEXP, is a regular expression that filters the file
-names. Only the files that are under revision control are taken into account."
+names.  Only the files that are under revision control are taken into account."
   (interactive
    (let ((dir-A (ediff-get-default-directory-name)))
      (list (ediff-read-file-name
@@ -499,7 +503,7 @@ names. Only the files that are under revision control are taken into account."
 ;;;###autoload
 (defun ediff-directories3 (dir1 dir2 dir3 regexp)
   "Run Ediff on three directories, DIR1, DIR2, and DIR3, comparing files that
-have the same name in all three. The last argument, REGEXP, is a regular
+have the same name in all three.  The last argument, REGEXP, is a regular
 expression that can be used to filter out certain file names."
   (interactive
    (let ((dir-A (ediff-get-default-directory-name))
@@ -526,10 +530,10 @@ expression that can be used to filter out certain file names."
 (defalias 'edirs3 'ediff-directories3)
 
 ;;;###autoload
-(defun ediff-merge-directories (dir1 dir2 regexp)
+(defun ediff-merge-directories (dir1 dir2 regexp &optional merge-autostore-dir)
   "Run Ediff on a pair of directories, DIR1 and DIR2, merging files that have
-the same name in both. The third argument, REGEXP, is a regular expression that
-can be used to filter out certain file names."
+the same name in both.  The third argument, REGEXP, is a regular expression
+that can be used to filter out certain file names."
   (interactive
    (let ((dir-A (ediff-get-default-directory-name))
         f)
@@ -544,17 +548,20 @@ can be used to filter out certain file names."
           )))
   (ediff-directories-internal
    dir1 dir2 nil regexp 'ediff-merge-files 'ediff-merge-directories
+   nil merge-autostore-dir
    ))
 
 ;;;###autoload
 (defalias 'edirs-merge 'ediff-merge-directories)
 
 ;;;###autoload
-(defun ediff-merge-directories-with-ancestor (dir1 dir2 ancestor-dir regexp)
+(defun ediff-merge-directories-with-ancestor (dir1 dir2 ancestor-dir regexp
+                                                  &optional
+                                                  merge-autostore-dir)
   "Merge files in directories DIR1 and DIR2 using files in ANCESTOR-DIR as ancestors.
-Ediff merges files that have identical names in DIR1, DIR2. If a pair of files
+Ediff merges files that have identical names in DIR1, DIR2.  If a pair of files
 in DIR1 and DIR2 doesn't have an ancestor in ANCESTOR-DIR, Ediff will merge
-without ancestor. The fourth argument, REGEXP, is a regular expression that
+without ancestor.  The fourth argument, REGEXP, is a regular expression that
 can be used to filter out certain file names."
   (interactive
    (let ((dir-A (ediff-get-default-directory-name))
@@ -576,13 +583,15 @@ can be used to filter out certain file names."
   (ediff-directories-internal
    dir1 dir2 ancestor-dir regexp
    'ediff-merge-files-with-ancestor 'ediff-merge-directories-with-ancestor
+   nil merge-autostore-dir
    ))
 
 ;;;###autoload
-(defun ediff-merge-directory-revisions (dir1 regexp)
+(defun ediff-merge-directory-revisions (dir1 regexp
+                                            &optional merge-autostore-dir)
   "Run Ediff on a directory, DIR1, merging its files with their revisions.
 The second argument, REGEXP, is a regular expression that filters the file
-names. Only the files that are under revision control are taken into account."
+names.  Only the files that are under revision control are taken into account."
   (interactive
    (let ((dir-A (ediff-get-default-directory-name)))
      (list (ediff-read-file-name
@@ -592,16 +601,19 @@ names. Only the files that are under revision control are taken into account."
           )))
   (ediff-directory-revisions-internal
    dir1 regexp 'ediff-merge-revisions 'ediff-merge-directory-revisions
+   nil merge-autostore-dir
    ))
 
 ;;;###autoload
 (defalias 'edir-merge-revisions 'ediff-merge-directory-revisions)
 
 ;;;###autoload
-(defun ediff-merge-directory-revisions-with-ancestor (dir1 regexp)
+(defun ediff-merge-directory-revisions-with-ancestor (dir1 regexp
+                                                          &optional
+                                                          merge-autostore-dir)
   "Run Ediff on a directory, DIR1, merging its files with their revisions and ancestors.
 The second argument, REGEXP, is a regular expression that filters the file
-names. Only the files that are under revision control are taken into account."
+names.  Only the files that are under revision control are taken into account."
   (interactive
    (let ((dir-A (ediff-get-default-directory-name)))
      (list (ediff-read-file-name
@@ -612,6 +624,7 @@ names. Only the files that are under revision control are taken into account."
   (ediff-directory-revisions-internal
    dir1 regexp 'ediff-merge-revisions-with-ancestor
    'ediff-merge-directory-revisions-with-ancestor
+   nil merge-autostore-dir
    ))
 
 ;;;###autoload
@@ -627,11 +640,12 @@ names. Only the files that are under revision control are taken into account."
 ;; The third argument, REGEXP, is a regular expression that can be used to
 ;; filter out certain file names.
 ;; JOBNAME is the symbol indicating the meta-job to be performed.
-;; MERGE-DIR is the directory in which to store merged files.
+;; MERGE-AUTOSTORE-DIR is the directory in which to store merged files.
 (defun ediff-directories-internal (dir1 dir2 dir3 regexp action jobname 
-                                       &optional startup-hooks)
+                                       &optional startup-hooks
+                                       merge-autostore-dir)
   ;; ediff-read-file-name is set to attach a previously entered file name if
-  ;; the currently entered file is a directory. This code takes care of that.
+  ;; the currently entered file is a directory.  This code takes care of that.
   (setq dir1 (if (file-directory-p dir1) dir1 (file-name-directory dir1))
        dir2 (if (file-directory-p dir2) dir2 (file-name-directory dir2)))
 
@@ -647,27 +661,35 @@ names. Only the files that are under revision control are taken into account."
              (string= dir2 dir3))
         (error "Directories B and C are the same: %s" dir1)))
 
+  (if merge-autostore-dir
+      (or (stringp merge-autostore-dir)
+         (error "%s: Directory for storing merged files must be a string"
+                jobname)))
   (let (diffs ; var where ediff-intersect-directories returns the diff list
-       merge-autostore-dir
        file-list meta-buf)
-    (if (and ediff-autostore-merges (ediff-merge-metajob jobname))
+    (if (and ediff-autostore-merges
+            (ediff-merge-metajob jobname)
+            (not merge-autostore-dir))
        (setq merge-autostore-dir 
-             (ediff-read-file-name "Directory to save merged files:"
-                                   (if ediff-use-last-dir
+             (read-file-name "Save merged files in directory: "
+                             (if ediff-use-last-dir
                                        ediff-last-merge-autostore-dir
                                      (ediff-strip-last-dir dir1))
-                                   nil)))
+                             nil
+                             'must-match)))
     ;; verify we are not merging into an orig directory
-    (if (stringp merge-autostore-dir)
+    (if merge-autostore-dir
        (cond ((and (stringp dir1) (string= merge-autostore-dir dir1))
-              (or (y-or-n-p "Merge directory same as directory A, sure? ")
+              (or (y-or-n-p
+                   "Directory for saving merged files = Directory A.  Sure? ")
                   (error "Directory merge aborted")))
              ((and (stringp dir2) (string= merge-autostore-dir dir2))
-              (or (y-or-n-p "Merge directory same as directory B, sure? ")
+              (or (y-or-n-p
+                   "Directory for saving merged files = Directory B.  Sure? ")
                   (error "Directory merge aborted")))
              ((and (stringp dir3) (string= merge-autostore-dir dir3))
               (or (y-or-n-p
-                   "Merge directory same as ancestor directory, sure? ")
+                   "Directory for saving merged files = Ancestor Directory.  Sure? ")
                   (error "Directory merge aborted")))))
     
     (setq file-list (ediff-intersect-directories 
@@ -676,11 +698,11 @@ names. Only the files that are under revision control are taken into account."
     (setq startup-hooks
          ;; this sets various vars in the meta buffer inside
          ;; ediff-prepare-meta-buffer
-         (cons (` (lambda ()
-                    ;; tell what to do if the user clicks on a session record
-                    (setq ediff-session-action-function (quote (, action)))
-                    ;; set ediff-dir-difference-list 
-                    (setq ediff-dir-difference-list (quote (, diffs)))))
+         (cons `(lambda ()
+                  ;; tell what to do if the user clicks on a session record
+                  (setq ediff-session-action-function (quote ,action))
+                  ;; set ediff-dir-difference-list 
+                  (setq ediff-dir-difference-list (quote ,diffs)))
                startup-hooks))
     (setq meta-buf (ediff-prepare-meta-buffer 
                    'ediff-filegroup-action
@@ -692,24 +714,34 @@ names. Only the files that are under revision control are taken into account."
     (ediff-show-meta-buffer meta-buf)
     ))
 
+;; MERGE-AUTOSTORE-DIR can be given to tell ediff where to store the merged
+;; files
 (defun ediff-directory-revisions-internal (dir1 regexp action jobname 
-                                               &optional startup-hooks)
+                                               &optional startup-hooks
+                                               merge-autostore-dir)
   (setq dir1 (if (file-directory-p dir1) dir1 (file-name-directory dir1)))
 
-  (let (file-list meta-buf merge-autostore-dir)
-    (if (and ediff-autostore-merges (ediff-merge-metajob jobname))
+  (if merge-autostore-dir
+      (or (stringp merge-autostore-dir)
+         (error "%S: Directory for storing merged files must be a string"
+                jobname)))
+  (let (file-list meta-buf)
+    (if (and ediff-autostore-merges 
+            (ediff-merge-metajob jobname)
+            (not merge-autostore-dir))
        (setq merge-autostore-dir 
-             (ediff-read-file-name "Directory to save merged files:"
-                                   (if ediff-use-last-dir
-                                       ediff-last-merge-autostore-dir
-                                     (ediff-strip-last-dir dir1))
-                                   nil)))
+             (read-file-name "Save merged files in directory: "
+                             (if ediff-use-last-dir
+                                 ediff-last-merge-autostore-dir
+                               (ediff-strip-last-dir dir1))
+                             nil
+                             'must-match)))
     ;; verify merge-autostore-dir != dir1
-    (if (and (stringp merge-autostore-dir)
+    (if (and merge-autostore-dir
             (stringp dir1)
             (string= merge-autostore-dir dir1))
        (or (y-or-n-p
-            "Directory for saving merges is the same as directory A. Sure? ")
+            "Directory for saving merged file = directory A.  Sure? ")
            (error "Merge of directory revisions aborted")))
     
     (setq file-list
@@ -718,10 +750,9 @@ names. Only the files that are under revision control are taken into account."
     (setq startup-hooks
          ;; this sets various vars in the meta buffer inside
          ;; ediff-prepare-meta-buffer
-         (cons (` (lambda ()
-                    ;; tell what to do if the user clicks on a session record
-                    (setq ediff-session-action-function (quote (, action)))
-                    ))
+         (cons `(lambda ()
+                  ;; tell what to do if the user clicks on a session record
+                  (setq ediff-session-action-function (quote ,action)))
                startup-hooks))
     (setq meta-buf (ediff-prepare-meta-buffer 
                    'ediff-filegroup-action
@@ -792,7 +823,7 @@ If WIND-B is nil, use window next to WIND-A."
   "Run Ediff on a pair of regions in two different buffers.
 Regions \(i.e., point and mark\) are assumed to be set in advance.
 This function is effective only for relatively small regions, up to 200
-lines. For large regions, use `ediff-regions-linewise'."
+lines.  For large regions, use `ediff-regions-linewise'."
   (interactive 
    (let (bf)
      (list (setq bf (read-buffer "Region's A buffer: "
@@ -830,7 +861,7 @@ lines. For large regions, use `ediff-regions-linewise'."
 Regions \(i.e., point and mark\) are assumed to be set in advance.
 Each region is enlarged to contain full lines.
 This function is effective for large regions, over 100-200
-lines. For small regions, use `ediff-regions-wordwise'."
+lines.  For small regions, use `ediff-regions-wordwise'."
   (interactive 
    (let (bf)
      (list (setq bf (read-buffer "Region A's buffer: "
@@ -930,16 +961,15 @@ Continue anyway? (y/n) "))
     (ediff-setup buffer-A file-A
                 buffer-B file-B
                 nil nil            ; buffer & file C
-                (cons (` (lambda ()
-                           (delete-file (, file-A))
-                           (delete-file (, file-B))))
+                (cons `(lambda ()
+                           (delete-file ,file-A)
+                           (delete-file ,file-B))
                       startup-hooks)
                 (append
                  (list (cons 'ediff-word-mode  word-mode)
                        (cons 'ediff-narrow-bounds (list overl-A overl-B))
                        (cons 'ediff-job-name job-name))
-                 setup-parameters)
-                )
+                 setup-parameters))
     ))
     
  
@@ -954,7 +984,10 @@ Continue anyway? (y/n) "))
     (set-buffer-modified-p nil)))
 
 ;;;###autoload
-(defun ediff-merge-files (file-A file-B &optional startup-hooks)
+(defun ediff-merge-files (file-A file-B
+                                ;; MERGE-BUFFER-FILE is the file to be
+                                ;; associated with the merge buffer 
+                                &optional startup-hooks merge-buffer-file)
   "Merge two files without ancestor."
   (interactive
    (let ((dir-A (if ediff-use-last-dir
@@ -986,11 +1019,17 @@ Continue anyway? (y/n) "))
                          file-B)
                          nil ; file-C
                          startup-hooks
-                         'ediff-merge-files))
+                         'ediff-merge-files
+                         merge-buffer-file))
                          
 ;;;###autoload
 (defun ediff-merge-files-with-ancestor (file-A file-B file-ancestor
-                                              &optional startup-hooks)
+                                              &optional
+                                              startup-hooks
+                                              ;; MERGE-BUFFER-FILE is the file
+                                              ;; to be associated with the
+                                              ;; merge buffer
+                                              merge-buffer-file)
   "Merge two files with ancestor."
   (interactive
    (let ((dir-A (if ediff-use-last-dir
@@ -1036,13 +1075,18 @@ Continue anyway? (y/n) "))
                          file-B)
                          file-ancestor
                          startup-hooks
-                         'ediff-merge-files-with-ancestor))
+                         'ediff-merge-files-with-ancestor
+                         merge-buffer-file))
                          
 ;;;###autoload
 (defalias 'ediff-merge-with-ancestor 'ediff-merge-files-with-ancestor)
                          
 ;;;###autoload
-(defun ediff-merge-buffers (buffer-A buffer-B &optional startup-hooks job-name)
+(defun ediff-merge-buffers (buffer-A buffer-B
+                                    &optional
+                                    ;; MERGE-BUFFER-FILE is the file to be
+                                    ;; associated with the merge buffer
+                                    startup-hooks job-name merge-buffer-file)
   "Merge buffers without ancestor."
   (interactive 
    (let (bf)
@@ -1059,12 +1103,17 @@ Continue anyway? (y/n) "))
   (setq startup-hooks (cons 'ediff-merge-on-startup startup-hooks))
   (or job-name (setq job-name 'ediff-merge-buffers))
   (ediff-buffers-internal
-   buffer-A buffer-B nil startup-hooks job-name))
+   buffer-A buffer-B nil startup-hooks job-name merge-buffer-file))
    
 ;;;###autoload
-(defun ediff-merge-buffers-with-ancestor (buffer-A 
-                                         buffer-B buffer-ancestor
-                                         &optional startup-hooks job-name)
+(defun ediff-merge-buffers-with-ancestor (buffer-A buffer-B buffer-ancestor
+                                                  &optional
+                                                  startup-hooks
+                                                  job-name
+                                                  ;; MERGE-BUFFER-FILE is the
+                                                  ;; file to be associated
+                                                  ;; with the merge buffer
+                                                  merge-buffer-file)
   "Merge buffers with ancestor."
   (interactive 
    (let (bf bff)
@@ -1089,11 +1138,12 @@ Continue anyway? (y/n) "))
   (setq startup-hooks (cons 'ediff-merge-on-startup startup-hooks))
   (or job-name (setq job-name 'ediff-merge-buffers-with-ancestor))
   (ediff-buffers-internal
-   buffer-A buffer-B buffer-ancestor startup-hooks job-name))
+   buffer-A buffer-B buffer-ancestor startup-hooks job-name merge-buffer-file))
       
 
 ;;;###autoload
-(defun ediff-merge-revisions (&optional file startup-hooks)
+(defun ediff-merge-revisions (&optional file startup-hooks merge-buffer-file)
+  ;; MERGE-BUFFER-FILE is the file to be associated with the merge buffer
   "Run Ediff by merging two revisions of a file.
 The file is the optional FILE argument or the file visited by the current
 buffer."
@@ -1116,11 +1166,16 @@ buffer."
     ;; ancestor-revision=nil
     (funcall
      (intern (format "ediff-%S-merge-internal" ediff-version-control-package))
-     rev1 rev2 nil startup-hooks)))
+     rev1 rev2 nil startup-hooks merge-buffer-file)))
     
 
 ;;;###autoload
-(defun ediff-merge-revisions-with-ancestor (&optional file startup-hooks)
+(defun ediff-merge-revisions-with-ancestor (&optional
+                                           file startup-hooks
+                                           ;; MERGE-BUFFER-FILE is the file to
+                                           ;; be associated with the merge
+                                           ;; buffer
+                                           merge-buffer-file)
   "Run Ediff by merging two revisions of a file with a common ancestor.
 The file is the the optional FILE argument or the file visited by the current
 buffer."
@@ -1142,18 +1197,18 @@ buffer."
          ancestor-rev
          (read-string
           (format
-           "Ancestor version (default: %s): "
+           "Ancestor version (default: %s's base revision): "
            (if (stringp file)
                (file-name-nondirectory file) "current buffer"))))
     (ediff-load-version-control)
     (funcall
      (intern (format "ediff-%S-merge-internal" ediff-version-control-package))
-     rev1 rev2 ancestor-rev startup-hooks)))
+     rev1 rev2 ancestor-rev startup-hooks merge-buffer-file)))
 
 ;;;###autoload
 (defun run-ediff-from-cvs-buffer (pos)
   "Run Ediff-merge on appropriate revisions of the selected file.
-First run after `M-x cvs-update'. Then place the cursor on a line describing a
+First run after `M-x cvs-update'.  Then place the cursor on a line describing a
 file and then run `run-ediff-from-cvs-buffer'."
   (interactive "d")
   (ediff-load-version-control)
@@ -1166,13 +1221,18 @@ file and then run `run-ediff-from-cvs-buffer'."
 ;;; Apply patch
 
 ;;;###autoload
-(defun ediff-patch-file ()
-  "Run Ediff by patching SOURCE-FILENAME."
-  ;; This now returns the control buffer
-  (interactive)
-  (let (source-dir source-file patch-buf)
+(defun ediff-patch-file (&optional arg patch-buf)
+  "Run Ediff by patching SOURCE-FILENAME.
+If optional PATCH-BUF is given, use the patch in that buffer
+and don't ask the user.
+If prefix argument, then: if even argument, assume that the patch is in a
+buffer. If odd -- assume it is in a file."
+  (interactive "P")
+  (let (source-dir source-file)
     (require 'ediff-ptch)
-    (setq patch-buf (ediff-get-patch-buffer))
+    (setq patch-buf
+         (ediff-get-patch-buffer
+          (if arg (prefix-numeric-value arg)) patch-buf))
     (setq source-dir (cond (ediff-use-last-dir ediff-last-dir-patch)
                           ((and (not ediff-patch-default-directory)
                                 (buffer-file-name patch-buf))
@@ -1182,24 +1242,26 @@ file and then run `run-ediff-from-cvs-buffer'."
                           (t default-directory)))
     (setq source-file
          ;; the default is the directory, not the visited file name
-         (ediff-read-file-name "Which file to patch? " source-dir source-dir))
+         (read-file-name 
+          "File to patch (directory, if multifile patch): "
+          source-dir (ediff-get-default-file-name)))
     (ediff-dispatch-file-patching-job patch-buf source-file)))
 
 ;;;###autoload
-(defun ediff-patch-buffer ()
+(defun ediff-patch-buffer (&optional arg patch-buf)
   "Run Ediff by patching BUFFER-NAME."
-  (interactive)
-  (let (patch-buf)
-    (require 'ediff-ptch)
-    (setq patch-buf (ediff-get-patch-buffer))
-    (ediff-patch-buffer-internal
-     patch-buf
-     (read-buffer "Which buffer to patch? "
-                 (cond ((eq patch-buf (current-buffer))
-                        (window-buffer (other-window 1)))
-                       (t (current-buffer)))
-                 'must-match))))
+  (interactive "P")
+  (require 'ediff-ptch)
+  (setq patch-buf
+       (ediff-get-patch-buffer
+        (if arg (prefix-numeric-value arg)) patch-buf))
+  (ediff-patch-buffer-internal
+   patch-buf
+   (read-buffer
+    "Which buffer to patch? "
+    (ediff-prompt-for-patch-buffer))))
   
+
 ;;;###autoload
 (defalias 'epatch 'ediff-patch-file)
 ;;;###autoload
@@ -1214,7 +1276,7 @@ file and then run `run-ediff-from-cvs-buffer'."
 (defun ediff-revision (&optional file startup-hooks)
   "Run Ediff by comparing versions of a file.
 The file is an optional FILE argument or the file visited by the current
-buffer. Use `vc.el' or `rcs.el' depending on `ediff-version-control-package'."
+buffer.  Use `vc.el' or `rcs.el' depending on `ediff-version-control-package'."
   ;; if buffer is non-nil, use that buffer instead of the current buffer
   (interactive "P")
   (if (stringp file) (find-file file))
@@ -1250,7 +1312,7 @@ buffer. Use `vc.el' or `rcs.el' depending on `ediff-version-control-package'."
            (message "") ; kill the message from `locate-library'
            (require ediff-version-control-package))
        (or silent
-           (error "Version control package %S.el not found. Use vc.el instead"
+           (error "Version control package %S.el not found.  Use vc.el instead"
                   ediff-version-control-package)))))
 
 
@@ -1300,4 +1362,6 @@ With optional NODE, goes to that node."
 
 (require 'ediff-util)
 
+(run-hooks 'ediff-load-hook)
+
 ;;; ediff.el ends here