1 |
;;; ediff.el --- a comprehensive visual interface to diff & patch |
;;; ediff.el --- a comprehensive visual interface to diff & patch |
2 |
|
|
3 |
;; Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 01 Free Software Foundation, Inc. |
;; Copyright (C) 1994, 95, 96, 97, 98, 99, 2000, 01, 02 Free Software Foundation, Inc. |
4 |
|
|
5 |
;; Author: Michael Kifer <kifer@cs.sunysb.edu> |
;; Author: Michael Kifer <kifer@cs.stonybrook.edu> |
6 |
;; Created: February 2, 1994 |
;; Created: February 2, 1994 |
7 |
;; Keywords: comparing, merging, patching, tools, unix |
;; Keywords: comparing, merging, patching, tools, unix |
8 |
|
|
9 |
(defconst ediff-version "2.76" "The current version of Ediff") |
(defconst ediff-version "2.76.1" "The current version of Ediff") |
10 |
(defconst ediff-date "July 18, 2001" "Date of last update") |
(defconst ediff-date "January 4, 2002" "Date of last update") |
11 |
|
|
12 |
|
|
13 |
;; This file is part of GNU Emacs. |
;; This file is part of GNU Emacs. |
172 |
(let ((current (dired-get-filename nil 'no-error)) |
(let ((current (dired-get-filename nil 'no-error)) |
173 |
(marked (condition-case nil |
(marked (condition-case nil |
174 |
(dired-get-marked-files 'no-dir) |
(dired-get-marked-files 'no-dir) |
175 |
(error))) |
(error nil))) |
176 |
aux-list choices result) |
aux-list choices result) |
177 |
(or (integerp fileno) (setq fileno 0)) |
(or (integerp fileno) (setq fileno 0)) |
178 |
(if (stringp default) |
(if (stringp default) |
199 |
default-directory)) |
default-directory)) |
200 |
dir-B f) |
dir-B f) |
201 |
(list (setq f (ediff-read-file-name |
(list (setq f (ediff-read-file-name |
202 |
"File A to compare" dir-A |
"File A to compare" |
203 |
(ediff-get-default-file-name))) |
dir-A |
204 |
|
(ediff-get-default-file-name) |
205 |
|
'no-dirs)) |
206 |
(ediff-read-file-name "File B to compare" |
(ediff-read-file-name "File B to compare" |
207 |
(setq dir-B |
(setq dir-B |
208 |
(if ediff-use-last-dir |
(if ediff-use-last-dir |
235 |
default-directory)) |
default-directory)) |
236 |
dir-B dir-C f ff) |
dir-B dir-C f ff) |
237 |
(list (setq f (ediff-read-file-name |
(list (setq f (ediff-read-file-name |
238 |
"File A to compare" dir-A |
"File A to compare" |
239 |
(ediff-get-default-file-name))) |
dir-A |
240 |
|
(ediff-get-default-file-name) |
241 |
|
'no-dirs)) |
242 |
(setq ff (ediff-read-file-name "File B to compare" |
(setq ff (ediff-read-file-name "File B to compare" |
243 |
(setq dir-B |
(setq dir-B |
244 |
(if ediff-use-last-dir |
(if ediff-use-last-dir |
336 |
(defun ediff-files-internal (file-A file-B file-C startup-hooks job-name |
(defun ediff-files-internal (file-A file-B file-C startup-hooks job-name |
337 |
&optional merge-buffer-file) |
&optional merge-buffer-file) |
338 |
(let (buf-A buf-B buf-C) |
(let (buf-A buf-B buf-C) |
339 |
|
(if (string= file-A file-B) |
340 |
|
(error "Files A and B are the same")) |
341 |
|
(if (stringp file-C) |
342 |
|
(or (and (string= file-A file-C) (error "Files A and C are the same")) |
343 |
|
(and (string= file-B file-C) (error "Files B and C are the same")))) |
344 |
(message "Reading file %s ... " file-A) |
(message "Reading file %s ... " file-A) |
345 |
;;(sit-for 0) |
;;(sit-for 0) |
346 |
(ediff-find-file 'file-A 'buf-A 'ediff-last-dir-A 'startup-hooks) |
(ediff-find-file 'file-A 'buf-A 'ediff-last-dir-A 'startup-hooks) |
837 |
(select-window wind-B) |
(select-window wind-B) |
838 |
(setq beg-B (window-start) |
(setq beg-B (window-start) |
839 |
end-B (window-end)))) |
end-B (window-end)))) |
840 |
|
(setq buffer-A |
841 |
|
(ediff-clone-buffer-for-window-comparison |
842 |
|
buffer-A wind-A "-Window1-") |
843 |
|
buffer-B |
844 |
|
(ediff-clone-buffer-for-window-comparison |
845 |
|
buffer-B wind-B "-Window2-")) |
846 |
(ediff-regions-internal |
(ediff-regions-internal |
847 |
buffer-A beg-A end-A buffer-B beg-B end-B |
buffer-A beg-A end-A buffer-B beg-B end-B |
848 |
startup-hooks job-name word-mode nil))) |
startup-hooks job-name word-mode nil))) |
849 |
|
|
850 |
|
;; Suggested by Hannu Koivisto <azure@iki.fi> |
851 |
|
(defun ediff-clone-buffer-for-region-comparison (buff-name region-name) |
852 |
|
(let ((cloned-buff (ediff-make-indirect-buffer |
853 |
|
buff-name |
854 |
|
(concat buff-name region-name |
855 |
|
(symbol-name (gensym))))) |
856 |
|
(wind (ediff-get-visible-buffer-window buff-name))) |
857 |
|
(ediff-with-current-buffer cloned-buff |
858 |
|
(setq ediff-temp-indirect-buffer t)) |
859 |
|
(if (window-live-p wind) |
860 |
|
(set-window-buffer wind cloned-buff)) |
861 |
|
(pop-to-buffer cloned-buff) |
862 |
|
(message |
863 |
|
"Mark a region in buffer %s; then type %s. Use %s to abort." |
864 |
|
(buffer-name cloned-buff) |
865 |
|
(ediff-format-bindings-of 'exit-recursive-edit) |
866 |
|
(ediff-format-bindings-of 'abort-recursive-edit)) |
867 |
|
(recursive-edit) |
868 |
|
cloned-buff)) |
869 |
|
|
870 |
|
(defun ediff-clone-buffer-for-window-comparison (buff wind region-name) |
871 |
|
(let ((cloned-buff (ediff-make-indirect-buffer |
872 |
|
buff |
873 |
|
(concat (buffer-name buff) |
874 |
|
region-name (symbol-name (gensym)))))) |
875 |
|
(ediff-with-current-buffer cloned-buff |
876 |
|
(setq ediff-temp-indirect-buffer t)) |
877 |
|
(set-window-buffer wind cloned-buff) |
878 |
|
cloned-buff)) |
879 |
|
|
880 |
|
(defun ediff-make-indirect-buffer (base-buf indirect-buf-name) |
881 |
|
(ediff-cond-compile-for-xemacs-or-emacs |
882 |
|
(make-indirect-buffer base-buf indirect-buf-name) ; xemacs |
883 |
|
(make-indirect-buffer base-buf indirect-buf-name 'clone) ; emacs |
884 |
|
)) |
885 |
|
|
886 |
;;;###autoload |
;;;###autoload |
887 |
(defun ediff-regions-wordwise (buffer-A buffer-B &optional startup-hooks) |
(defun ediff-regions-wordwise (buffer-A buffer-B &optional startup-hooks) |
888 |
"Run Ediff on a pair of regions in two different buffers. |
"Run Ediff on a pair of regions in specified buffers. |
889 |
Regions \(i.e., point and mark\) are assumed to be set in advance. |
Regions \(i.e., point and mark\) are assumed to be set in advance except |
890 |
|
for the second region in the case both regions are from the same buffer. |
891 |
|
In such a case the user is asked to interactively establish the second |
892 |
|
region. |
893 |
This function is effective only for relatively small regions, up to 200 |
This function is effective only for relatively small regions, up to 200 |
894 |
lines. For large regions, use `ediff-regions-linewise'." |
lines. For large regions, use `ediff-regions-linewise'." |
895 |
(interactive |
(interactive |
909 |
(error "Buffer %S doesn't exist" buffer-B)) |
(error "Buffer %S doesn't exist" buffer-B)) |
910 |
|
|
911 |
|
|
912 |
(let (reg-A-beg reg-A-end reg-B-beg reg-B-end) |
(let ((buffer-A |
913 |
|
(ediff-clone-buffer-for-region-comparison buffer-A "-Region1-")) |
914 |
|
(buffer-B |
915 |
|
(ediff-clone-buffer-for-region-comparison buffer-B "-Region2-")) |
916 |
|
reg-A-beg reg-A-end reg-B-beg reg-B-end) |
917 |
(save-excursion |
(save-excursion |
918 |
(set-buffer buffer-A) |
(set-buffer buffer-A) |
919 |
(setq reg-A-beg (region-beginning) |
(setq reg-A-beg (region-beginning) |
929 |
|
|
930 |
;;;###autoload |
;;;###autoload |
931 |
(defun ediff-regions-linewise (buffer-A buffer-B &optional startup-hooks) |
(defun ediff-regions-linewise (buffer-A buffer-B &optional startup-hooks) |
932 |
"Run Ediff on a pair of regions in two different buffers. |
"Run Ediff on a pair of regions in specified buffers. |
933 |
Regions \(i.e., point and mark\) are assumed to be set in advance. |
Regions \(i.e., point and mark\) are assumed to be set in advance except |
934 |
|
for the second region in the case both regions are from the same buffer. |
935 |
|
In such a case the user is asked to interactively establish the second |
936 |
|
region. |
937 |
Each region is enlarged to contain full lines. |
Each region is enlarged to contain full lines. |
938 |
This function is effective for large regions, over 100-200 |
This function is effective for large regions, over 100-200 |
939 |
lines. For small regions, use `ediff-regions-wordwise'." |
lines. For small regions, use `ediff-regions-wordwise'." |
953 |
(if (not (ediff-buffer-live-p buffer-B)) |
(if (not (ediff-buffer-live-p buffer-B)) |
954 |
(error "Buffer %S doesn't exist" buffer-B)) |
(error "Buffer %S doesn't exist" buffer-B)) |
955 |
|
|
956 |
(let (reg-A-beg reg-A-end reg-B-beg reg-B-end) |
(let ((buffer-A |
957 |
|
(ediff-clone-buffer-for-region-comparison buffer-A "-Region1-")) |
958 |
|
(buffer-B |
959 |
|
(ediff-clone-buffer-for-region-comparison buffer-B "-Region2-")) |
960 |
|
reg-A-beg reg-A-end reg-B-beg reg-B-end) |
961 |
(save-excursion |
(save-excursion |
962 |
(set-buffer buffer-A) |
(set-buffer buffer-A) |
963 |
(setq reg-A-beg (region-beginning) |
(setq reg-A-beg (region-beginning) |
1006 |
(setq beg-B (move-marker (make-marker) beg-B) |
(setq beg-B (move-marker (make-marker) beg-B) |
1007 |
end-B (move-marker (make-marker) end-B))) |
end-B (move-marker (make-marker) end-B))) |
1008 |
|
|
|
(if (and (eq buffer-A buffer-B) |
|
|
(or (and (< beg-A end-B) (<= beg-B beg-A)) ; b-B b-A e-B |
|
|
(and (< beg-B end-A) (<= end-A end-B)))) ; b-B e-A e-B |
|
|
(progn |
|
|
(with-output-to-temp-buffer ediff-msg-buffer |
|
|
(ediff-with-current-buffer standard-output |
|
|
(fundamental-mode)) |
|
|
(princ " |
|
|
You have requested to compare overlapping regions of the same buffer. |
|
|
|
|
|
In this case, Ediff's highlighting may be confusing---in the same window, |
|
|
you may see highlighted regions that belong to different regions. |
|
|
|
|
|
Continue anyway? (y/n) ")) |
|
|
|
|
|
(if (y-or-n-p "Continue anyway? ") |
|
|
() |
|
|
(error "%S aborted" job-name)))) |
|
|
|
|
1009 |
;; make file-A |
;; make file-A |
1010 |
(if word-mode |
(if word-mode |
1011 |
(ediff-wordify beg-A end-A buffer-A tmp-buffer) |
(ediff-wordify beg-A end-A buffer-A tmp-buffer) |
1057 |
default-directory)) |
default-directory)) |
1058 |
dir-B f) |
dir-B f) |
1059 |
(list (setq f (ediff-read-file-name |
(list (setq f (ediff-read-file-name |
1060 |
"File A to merge" dir-A |
"File A to merge" |
1061 |
(ediff-get-default-file-name))) |
dir-A |
1062 |
|
(ediff-get-default-file-name) |
1063 |
|
'no-dirs)) |
1064 |
(ediff-read-file-name "File B to merge" |
(ediff-read-file-name "File B to merge" |
1065 |
(setq dir-B |
(setq dir-B |
1066 |
(if ediff-use-last-dir |
(if ediff-use-last-dir |
1101 |
default-directory)) |
default-directory)) |
1102 |
dir-B dir-ancestor f ff) |
dir-B dir-ancestor f ff) |
1103 |
(list (setq f (ediff-read-file-name |
(list (setq f (ediff-read-file-name |
1104 |
"File A to merge" dir-A |
"File A to merge" |
1105 |
(ediff-get-default-file-name))) |
dir-A |
1106 |
|
(ediff-get-default-file-name) |
1107 |
|
'no-dirs)) |
1108 |
(setq ff (ediff-read-file-name "File B to merge" |
(setq ff (ediff-read-file-name "File B to merge" |
1109 |
(setq dir-B |
(setq dir-B |
1110 |
(if ediff-use-last-dir |
(if ediff-use-last-dir |
1271 |
(intern (format "ediff-%S-merge-internal" ediff-version-control-package)) |
(intern (format "ediff-%S-merge-internal" ediff-version-control-package)) |
1272 |
rev1 rev2 ancestor-rev startup-hooks merge-buffer-file))) |
rev1 rev2 ancestor-rev startup-hooks merge-buffer-file))) |
1273 |
|
|
1274 |
|
;; MK: Check. This function doesn't seem to be used any more by pcvs or pcl-cvs |
1275 |
;;;###autoload |
;;;###autoload |
1276 |
(defun run-ediff-from-cvs-buffer (pos) |
(defun run-ediff-from-cvs-buffer (pos) |
1277 |
"Run Ediff-merge on appropriate revisions of the selected file. |
"Run Ediff-merge on appropriate revisions of the selected file. |
1357 |
(if ediff-use-last-dir |
(if ediff-use-last-dir |
1358 |
ediff-last-dir-A |
ediff-last-dir-A |
1359 |
default-directory) |
default-directory) |
1360 |
(ediff-get-default-file-name)))) |
(ediff-get-default-file-name) |
1361 |
|
'no-dirs))) |
1362 |
(find-file file) |
(find-file file) |
1363 |
(if (and (buffer-modified-p) |
(if (and (buffer-modified-p) |
1364 |
(y-or-n-p (message "Buffer %s is modified. Save buffer? " |
(y-or-n-p (message "Buffer %s is modified. Save buffer? " |