(scan_sexps_forward): Fix previous change.
[bpt/emacs.git] / lisp / ediff.el
CommitLineData
0f0b0a86 1;;; ediff.el --- a comprehensive visual interface to diff & patch
732be465 2;;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
813f532d
RS
3
4;; Author: Michael Kifer <kifer@cs.sunysb.edu>
5;; Created: February 2, 1994
fcbadd58 6;; Keywords: comparing, merging, patching, version control.
813f532d 7
f1a5512a
KH
8(defconst ediff-version "2.26" "The current version of Ediff")
9(defconst ediff-date "June 3, 1995" "Date of last update")
eaccd4d8 10
813f532d
RS
11;; This file is part of GNU Emacs.
12
13;; GNU Emacs is free software; you can redistribute it and/or modify
14;; it under the terms of the GNU General Public License as published by
15;; the Free Software Foundation; either version 2, or (at your option)
16;; any later version.
17
18;; GNU Emacs is distributed in the hope that it will be useful,
19;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21;; GNU General Public License for more details.
22
23;; You should have received a copy of the GNU General Public License
24;; along with GNU Emacs; see the file COPYING. If not, write to
25;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
26
813f532d
RS
27;;; Commentary:
28;; ----------
29
0f0b0a86 30;; Never read that diff output again!
08020d91 31;; Apply patch selectively, like a pro!
0f0b0a86 32;; Merge with ease!
813f532d 33
fcbadd58 34;; This package provides a convenient way of simultaneous browsing through
f1a5512a 35;; the differences between a pair (or a triple) of files or buffers. The
0f0b0a86
KH
36;; files being compared, file-A, file-B, and file-C (if applicable) are
37;; shown in separate windows (side by side, one above the another, or in
38;; separate frames), and the differences are highlighted as you step
39;; through them. You can also copy difference regions from one buffer to
40;; another (and recover old differences if you change your mind).
813f532d
RS
41
42;; In addition, Ediff can apply a patch to a file and then let you step
fcbadd58 43;; though both files, the patched and the original one, simultaneously,
813f532d
RS
44;; difference-by-difference. You can even apply a patch right out of a
45;; mail buffer, i.e., patches received by mail don't even have to be saved.
46;; Since Ediff lets you copy differences between buffers, you can, in
47;; effect, apply patches selectively (i.e., you can copy a difference
0f0b0a86 48;; region from file_orig to file, thereby undoing any particular patch that
813f532d
RS
49;; you don't like).
50
f1a5512a
KH
51;; Ediff is aware of version control, which lets the user compare
52;; files with their older versions. Ediff can also work with remote and
53;; compressed files. Details are given below.
54
0f0b0a86
KH
55;; This package builds upon the ideas borrowed from emerge.el and
56;; several Ediff's functions are adaptations from emerge.el.
57;; Much of the functionality of Ediff is also influenced by emerge.el.
813f532d 58
0f0b0a86
KH
59;; The present version of Ediff supersedes Emerge. It provides a superior
60;; user interface and has many features not found in Emerge. In particular,
61;; it can do patching and 2-way and 3-way file comparison in addition to
62;; merging.
fcbadd58 63
813f532d 64
813f532d
RS
65
66;;; Compilation
67;; -----------
68;;
69;; When you byte-compile Ediff, you will get some warnings about functions
70;; being undefined. These can be safely ignored.
b3a26225 71;;
813f532d 72;;; Bugs:
0f0b0a86 73;; -----
813f532d
RS
74
75;; 1. The undo command doesn't restore deleted regions well. That is, if
76;; you delete all characters in a difference region and then invoke
0f0b0a86 77;; `undo', the reinstated text will most likely be inserted outside of
b3a26225 78;; what Ediff thinks is the current difference region. (This problem
0f0b0a86 79;; doesn't seem to exist with XEmacs.)
b3a26225
RS
80;;
81;; If at any point you feel that difference regions are no longer correct,
82;; you can hit '!' to recompute the differences.
83
f1a5512a 84;; 2. On a monochrome display, the repertoire of faces with which to
b3a26225
RS
85;; highlight fine differences is limited. By default, Ediff is using
86;; underlining. However, if the region is already underlied by some other
87;; overlays, there is no simple way to temporarily remove that residual
88;; underlining. This problem occurs when a buffer is highlighted with
89;; hilit19.el or font-lock.el packages. If this residual highlighting gets
90;; in the way, you can do the following. Both font-lock.el and hilit19.el
91;; provide commands for unhighlighting buffers. You can either place these
92;; commands in `ediff-prepare-buffer-hooks' (which will unhighlight every
93;; buffer used by Ediff) or you can execute them interactively, at any time
94;; and on any buffer.
f1a5512a 95;;
813f532d
RS
96
97;;; Change Log:
98;; ----------
99
100;; Thu Feb 3, 1994
101
813f532d
RS
102;; Fixed a bug in ediff-setup-windows that caused control window to
103;; appear in a wrong place when split-window-keep-point is nil
104;; (Thanks to Kevin Broadey <KevinB@bartley.demon.co.uk>.)
105;;
106;; Added mechanism for using faces instead of before/after flags. This
107;; looks much better on an X display, especially on a color one.
108;; (Thanks to Boris Goldowsky <boris@cs.rochester.edu> for the code
109;; that led to ediff-highlight-diff.
110;; Also, thanks to Kevin Esler <esler@ch.hp.com> for suggestions
111;; regarding highlighting differences on X displays.)
112;;
113;; Added functions to apply patches.
114;; (Thanks to Kevin Broadey <KevinB@bartley.demon.co.uk> for this
115;; suggestion.)
116
117;; Fri Feb 4, 1994
118
119;; Added mechanism for toggling vertical/horizontal window split.
120;; (Inspired by a suggestion from Allan Gottlieb
121;; <gottlieb@allan.ultra.nyu.edu> -- thanks.)
122;;
123;; Added mechanism for toggling between highlighting using faces and
124;; highlighting using ASCII flags.
125;;
126;; Fixed a problem with undo. Now, Ediff has smartened up and doesn't
127;; keep undo info on ASCII flags inserted in buffer-A and buffer-B.
128;; So, if you edit the files while browsing through them, undo behaves
129;; as you would expect, i.e., faces/flags don't get in the way.
130
131;; Sun Feb 6, 1994
132
133;; Added horizontal scrolling. Added ediff-position-region to ensure
134;; that difference regions in buffer-A and buffer-B are aligned with
135;; each other. Disabled ediff-toggle-split when buffers are displayed
136;; in different frames.
0f0b0a86 137;;
813f532d
RS
138;; Added toggle-window help (Suggested by Boris Goldowsky
139;; <boris@cs.rochester.edu>.)
140;; Added functions to copy differences from one buffer to another and to
141;; recover old differences.
142;; Added prefix arguments to ediff-next-difference and
143;; ediff-previous-difference.
144
145;; Tue Feb 8, 1994
146
147;; Replaced text properties with overlays. Fixed ediff-setup-windows.
148;; Added ediff-save-buffer to local-write-file-hooks to prevent user
149;; from saving corrupted states. (Thanks to <boris@cs.rochester.edu>
150;; for suggestion.) Instead, Ediff now has a pair of functions for
151;; safe saving of buffers.
152;; Changed ediff-read-file-name to be more intuitive on ediff-files.
153;; Added ediff-prepare-buffer-hooks. (Thanks to Kevin Esler
154;; <esler@ch.hp.com> for the idea.)
0f0b0a86 155;;
813f532d
RS
156;; Cleanups in ediff-patch-file. Protected ediff-copy-diff against
157;; a bug that Emacs has in kill-region.
0f0b0a86 158;;
813f532d
RS
159;; Added support for Lemacs. (Thanks to Alastair Burt
160;; <burt@dfki.uni-kl.de> for coercing Ediff into working under Lemacs.)
161;; Added ediff-kill-buffer-carefully and other suggestions by Boris
162;; Goldowsky <boris@cs.rochester.edu>.
163;; Refined the protection against interference with highlighting caused
164;; by Hilit19. Added the variable ediff-third-party-highlighting.
165;; Added mechanisn for unhighlighting regions highlighted with Hilit19
166;; before hightlighting them with Ediff's overlays. (And for
167;; rehighlighting them with Hilit19, when the current difference moves on.)
168
169;; Sun Feb 13, 1994
170
171;; Added ediff-place-flags-in-buffer and ediff-remote-exit, which are
172;; modifications of Emerge's similar functions. The difference is that
173;; in Ediff they make ediff-before-flag and ediff-after-flag into
174;; read-only regions, so the user can't change them by mistake.
175;;
176;; Adopted a suggestion by Boris Goldowsky <boris@cs.rochester.edu>
177;; that led to a more elegant treatment of faces.
178;;
179;; Added protection against interference with Font-Lock highlighting
180;; similar to that of Hilit19's protection.
181
182;; Tue Feb 15, 1994
183
184;; Deleted spurious (auto-save-mode 1) in ediff-control-buffer, which
185;; was causing this buffer to be auto-saved for no good reason.
186;; Added read-only protection to ediff-before/after-flags in Lemacs.
187;; (Thanks to Alastair Burt <burt@dfki.uni-kl.de> for help in testing.)
0f0b0a86
KH
188;;
189;; Further fixes in the XEmacs part. Changed highlighted region in
813f532d
RS
190;; ediff-highlight-diff so that an extra character will be highlighted
191;; only if a difference is empty (thereby allowing the user to see where an
192;; insertion or a deletion has taken place).
193;;
194;; Simplified interaction with other highlighting packages by giving
195;; Ediff overlays the highest priority. (Taking a cue from
196;; ediff-highlight-diff-lemacs written by Alastair Burt
197;; <burt@dfki.uni-kl.de>.) Zapped ediff-third-party-highlighting
198;; variable and hooks that were previously used to
199;; unhighlight/rehighlight buffers when hilit19/font-lock are on.
200
201;; Fri Feb 18, 1994
202
203;; Added a bit more sophistication to ediff-read-file-name. Now,
204;; ediff-files remembers both, the file-A and the file-B directories.
205;; They are offered as defaults when ediff-use-last-dir is set to t.
206
207;; Fri Feb 22, 1994
208
209;; Added ediff-before-change-guard to remove ASCII highlighting when
210;; the user attempts to change buffer-A/B. This is needed because
211;; otherwise the undo info may become screwed up in those buffers.
0f0b0a86 212;; Hitting `h' (ediff-toggle-hilit) on a dumb terminal will toggle
813f532d
RS
213;; between ASCII highlighting and no highlighting.
214
215;; Fri Feb 24, 1994
216
217;; Fixed problems with multiple Ediff sessions running simultaneously.
218
219;; Tue Mar 1, 1994
220
221;; Added vc-ediff, the Ediff interface to vc.el. (Thanks to Eric
222;; Freudenthal <freudent@jan.ultra.nyu.edu> for contributing this
223;; function.)
224
225;; Sun Mar 6, 1994
226
227;; Added rcs-ediff, an Ediff interface to RCS via rcs.el. (Thanks to
228;; Alastair Burt <burt@dfki.uni-kl.de>.)
229;; Some minor improvements.
230
231;; Tue March 15, 1994
232
233;; Fixed a buglet in defining ediff-current-diff-face-A/B.
234;; (Thanks to Job Ganzevoort <Job.Ganzevoort@cwi.nl>.)
235
236;; Tue March 22, 1994
237
238;; Fixed a bug with ediffing narrowed buffers, reported by Kevin
239;; Broadey <KevinB@bartley.demon.co.uk>.
240;; Made Ediff to work with files that have incomplete last line.
08020d91 241;; Made Ediff execute diff and patch using Bourne Shell, which
813f532d
RS
242;; should eliminate problems with $prompt that some people had.
243
244;; Thu March 24, 1994
245
246;; Achieved quadratic speedup in the size of the file by replacing the
0f0b0a86
KH
247;; slow goto-line by forward-line.
248;; Converted demarkation of difference regions
813f532d
RS
249;; from markers to overlays. This will later allow us to highlight all
250;; diffs, not just the current one.
251
252;; Wed March 30, 1994
253
254;; Under X, Ediff now highlights all differences in dim colors and the
0f0b0a86 255;; current difference in bright colors. Improved XEmacs support.
813f532d
RS
256;; Changed toggle hilit to cycle through 3 states: highlighting all
257;; diffs, highlighting only the current diff, and highlighting using
258;; ASCII flags.
259;; Added support for difference regions that are not full lines.
260
261;; Fri April 1, 1994
262
263;; Fixed bugs related to writing buffers A and B.
0f0b0a86 264;; Added commands `ga', `gb' to jump directly to the closest diff in
813f532d
RS
265;; buffer A and B, respectively.
266
b3a26225
RS
267;; Fri April 11, 1994
268
0f0b0a86 269;; Added `ediff-update-diffs', a function that lets the user recompute
b3a26225
RS
270;; difference regions after extensive editing done to buffers A and B
271;; (bound to `!').
272
273;; Wed April 13, 1994
274
275;; Added the new feature: refining the current difference region.
276;; This would highlight the precise differences between the regions in
277;; buffer A and B. (A way to implement this was suggested by Boris
278;; Goldowsky <boris@cs.rochester.edu>.)
279;;
280;; Fixed Ediff to be immune to several different versions of rcs.el
281;; that are currently in distribution.
282
283;; Thu April 14, 1994
284
285;; Ediff now respects X resources for the faces it uses. It no longer
286;; barks when the colormap has no colors it is using; or when face
287;; fonts can't be italicized, etc.
288
289;; Fri April 15, 1994
290
291;; Changed `ediff-setup-windows' to minimize the need to delete and
292;; create windows. Now jumps faster from diff to diff.
f9ae5324 293;; Added Ediff to the File menu on the menu bar (FSF's version).
b3a26225
RS
294
295;; Mon April 18, 1994
296
297;; Fixed to work with OS/2's PM-Emacs.
298
299;; Thu April 21, 1994
300
301;; Lemacs' menus added (thanks to Alastair Burt for the help).
302
303;; Wed April 28, 1994
304
0f0b0a86 305;; Fixed ediff-keep-window-config (thanks to Norbert Kiesel
b3a26225
RS
306;; <norbert@i3.informatik.rwth-aachen.de>), ediff-shell and
307;; ediff-protect-metachars (thanks to Richard Stanton
308;; <stanton@haas.berkeley.edu>). Made access to difference
309;; overlays structure-independent, making it less bug-prone.
310;; Patched ediff-read-file-name to work more intuitively with directory
311;; names (thanks to Kevin Broadey <KevinB@bartley.demon.co.uk>).
312
313;; Mon May 2, 1994
314
315;; Added `ediff-frame-has-menubar' to guard against the possibility that
316;; the current frame has no menu bar.
317
318;; Fri May 6, 1994
319
320;; Fixed buglet in vc-ediff (thanks to Ray Nickson <nickson@cs.uq.oz.au>).
321
fcbadd58
RS
322;; Wed May 18, 1994
323
324;; Modified ediff-read-file-name to not put long file names in the
325;; default prompt area, as suggested by KevinB@bartley.demon.co.uk.
326;; Applied patch supplied by burt@dfki.uni-kl.de, fixing a problem with
327;; ediff-diff-to-diff in Lemacs.
328
329;; Tue May 31, 1994
330
331;; Added ediff-forward-word-function (as suggested by Job Ganzevoort
f1a5512a 332;; <Job.Ganzevoort@cwi.nl>).
fcbadd58
RS
333
334;; Thu Jun 2, 1994
335
336;; Added `ediff-toggle-regexp-match', which allows the user to step
337;; through only those difference regions that match some regexp; or,
338;; vice versa, to skip over regions that match a regexp. (This feature
339;; was suggested by Andy Scott <ascott@pcocd2.intel.com>.)
340;; Added ediff-eval-in-buffer, which is a modified emerge-eval-in-buffer.
341;; The function ediff-status-info, bound to `i', now replaces and extends
342;; ediff-file-names and ediff-line-numbers, which were bound to `f'
343;; and `i', respectively.
344
fcbadd58
RS
345
346;; Wed Jun 10, 1994
347
348;; Improved `ediff-read-file-name' and `ediff-buffers' so they are now
349;; providing more intuitive defaults. Modified `ediff-read-file-name'
350;; so it won't cause problems under OS/2.
351
352;; Fri Jun 24, 1994
353
354;; Modified ediff-find-file, ediff-files-internal, and made
355;; emerge-verify-file-buffer into ediff-verify-file-buffer so that
356;; Ediff will work correctly with remote and compressed
357;; files. (Suggested by Sandy Rutherford <sandy@ibm550.sissa.it>.)
358
359;; Fri Jun 28, 1994
360
361;; Fixed ediff-patch-files to work with remote and compressed files.
362
f9ae5324
RS
363;; Wed July 20, 1994
364
365;; Changed menu bar items per RMS's suggestion. Changed odd/even faces
366;; in Lemacs to italic. Changed ediff-*-face-* variables so that they
367;; will contain names of faces instead of the face internal
368;; representation. (Copy-face works better with face names than with
369;; face internal representation. With face internal representation, if
370;; a face vector mentions a font explicitly, copy-face may attempt to
371;; copy this font, which would cause an error if the font has a wrong
372;; size for one of the existing frames.) Improved the way
373;; mode-line-buffer-identification is set in ediff-setup so that Ediff
374;; will accommodate the way buffers are identified in mode-line.el and
375;; uniquify.el.
376
0691ced3
RS
377;; Fri August 5, 1994
378
379;; Ediff can now automatically skip over regions that differ only in
380;; the white space and line breaks. This is controled with the variable
381;; `ediff-ignore-similar-regions' and can be toggled on/off by typing
382;; `##'.
383
384;; Mon August 8, 1994
385
0f0b0a86 386;; If ediff-save-buffer is invoked with `wd', it'll save the diff
0691ced3
RS
387;; output in a file.
388
eaccd4d8
RS
389;; Wed August 24, 1994
390
391;; Fixed ediff-toggle-read-only and ediff-patch-file so that they will
392;; check out version-controled files before modifying them. This will
393;; permit checking the modified versions back in. In earlier
394;; versions, such modifications could be lost, unless the user takes
395;; special care of preserving them.
396
397;; Tue August 30, 1994
398
399;; Added ediff-submit-report.
400;; Introduced ediff-revision as a uniform way of calling vc.el and
401;; rcs.el. This is controled by ediff-version-control-package
402;; variable. Functions vc-ediff, rcs-ediff are replaced by their
403;; internal versions.
eaccd4d8 404
0f0b0a86 405;; Thu September 1, 1994
eaccd4d8
RS
406
407;; Made ediff-overlay-put and ediff-move-overlay into bona fide
408;; functions (rather than fset symbols). These now check if overlay's
409;; buffer is alive. If not, overlay is deleted. This overcomes some of
410;; the problems with Lemacs.
411
0f0b0a86 412;; Thu September 8, 1994
b3a26225 413
0f0b0a86
KH
414;; Added ediff-revision-key, ediff-load-version-control and streamlined
415;; vc/rcs-ediff[-internal]. Eliminated dependency on emerge.el.
b3a26225 416
0f0b0a86 417;; Fri September 23, 1994
b3a26225 418
0f0b0a86
KH
419;; Added ediff-windows and ediff-regions.
420;; Changed ediff-setup-windows and related procedures to create
421;; a separate dedicated control frame for each invocation of Ediff.
b3a26225 422
0f0b0a86 423;; Tue September 27, 1994
813f532d 424
0f0b0a86
KH
425;; Added redraw-display everywhere before creating or deleting
426;; frames. It appears that this cures Emacs' bug where it trashes some
427;; fonts which leads to crashes. Also, some code cleanups and bug fixes.
813f532d 428
0f0b0a86 429;; Fri September 30, 1994
813f532d 430
0f0b0a86
KH
431;; Fixed ediff-update-diffs so it'll work correctly with
432;; ediff-windows and ediff-regions. Added narrowing and widening to the
433;; suite of commands available for ediff-windows and ediff-regions.
813f532d 434
0f0b0a86 435;; Fri October 7, 1994
b3a26225 436
0f0b0a86
KH
437;; Changed ediff-setup-windows to funcall the actual window setting
438;; function, which is either ediff-setup-windows-multiframe or
439;; ediff-setup-windows-plain. Changed all temp file names to use `_'
440;; instead of `.'. Presumably, this makes VMS happier.
441;; Ported to VMS (thanks to Richard Levitte <levitte@e.kth.se>).
442;; Added ediff-prefer-long-help-message and changed defaults.
443;; Fighting with XEmacs bugs. Made it possible to switch between plain
444;; and multiframe display easier, but XEmacs is still getting confused
445;; at times. Added ediff-check-version and ediff-set-help-message.
446;; Made more sensible temp file names, which is important when
447;; generating context diffs. Added ediff-make-frame-position and
448;; ediff-control-frame-position-function.
b3a26225 449
0f0b0a86 450;; Wed October 12, 1994
813f532d 451
f1a5512a 452;; ediff-window-visible-p now makes a call to frame-visible-p
0f0b0a86
KH
453;; only when window-system is non-nil. Rearranged the block of fset's
454;; so that the wrong things won't be defined when window-system is nil.
455;; Added ediff-revert-buffers-then-recompute-diffs function.
456;; Removed flag-argument from a background call to shell-command.
457;; Added ediff-shell-command to enable custom diff execute in the
458;; background and insert output in ediff-custom-diff-buffer.
459;; Added ediff-shell-command-filter, because XEmacs doesn't have it.
460;; Made ediff-revision set up ediff-job-name to `ediff-revision'.
461;; This enables users do ediff-revision-specific actions on exiting
462;; Ediff using ediff-quit-hooks.
463;; Reshaffled some fset's so that functions for checking color and
464;; faces won't be touched on a non-windowing display.
b3a26225 465
0f0b0a86 466;; Thu October 20, 1994
813f532d 467
0f0b0a86
KH
468;; Modified ediff-make-fine-diffs so that no fine diffs are computed if
469;; one of the diff regions is empty. Saves time and also works around
470;; the buggy diff program in AIX.
471;; ediff no longer loads the version control package
472;; automatically---only when ediff-revision is called.
473;; Enabled focusing/hiding diff regions that match both or just one of the
474;; regexps.
475;; Changed ediff-regions to ediff-small-regions. Added ediff-large-regions.
476;; Modified ediff-next/previous-difference to work right when both
477;; skipping regexp matches and skipping similar regions is enabled.
478;; Fixed bugs in positioning the control frame.
813f532d 479
0f0b0a86 480;; Fri October 28, 1994
b3a26225 481
0f0b0a86
KH
482;; Fixed bugs in ediff-next/previous-difference, ediff-set-visible-region
483;; Changed/added ediff-word-[1-4].
b3a26225 484
0f0b0a86 485;; Tue November 1, 1994
b3a26225 486
0f0b0a86 487;; Made ediff-revision delete the temporary version files it creates.
813f532d 488
0f0b0a86 489;; Tue November 29, 1994
813f532d 490
0f0b0a86
KH
491;; Added ediff-swap-buffers. Split ediff-difference-vector into
492;; ediff-difference-vector-A and ediff-difference-vector-B, which
493;; allowed to factor out a lot of stuff.
494;; Made the code buffer-C ready.
813f532d 495
0f0b0a86 496;; Thu December 1, 1994
813f532d 497
0f0b0a86
KH
498;; Lotsa bug fixes. Further rationalized the code.
499;; Added ediff-display-help-hooks, ediff-mode-hooks.
500;; Replaced almost identical ediff-scroll-up/down with
501;; ediff-scroll-vertically.
502;; Replaced almost identical ediff-scroll-left/right with
503;; ediff-scroll-horizontally.
504;; Made the code buffer-C ready.
813f532d 505
0f0b0a86 506;; Thu December 8, 1994
813f532d 507
0f0b0a86
KH
508;; Added ediff-toggle-wide-display. In plain display, help message is
509;; now centered correctly.
813f532d 510
0f0b0a86 511;; Fri December 9, 1994
813f532d 512
f1a5512a
KH
513;; Added ediff-toggle-multiframe.
514;; Fixed ediff-pop-diff and ediff-copy-diff, so that they will
0f0b0a86 515;; invoke auto-refining, if necessary.
813f532d 516
0f0b0a86 517;; Mon December 12, 1994
813f532d 518
0f0b0a86
KH
519;; Modified ediff-toggle-wide-display so it would funcall
520;; ediff-make-wide-display-function.
813f532d 521
0f0b0a86 522;; Tue December 13, 1994
813f532d 523
0f0b0a86 524;; Ediff now chooses its surrogate minibuffer from frame A.
813f532d 525
0f0b0a86 526;; Mon December 20, 1994
eaccd4d8 527
0f0b0a86 528;; Added ediff-keymap-setup-hooks.
813f532d 529
0f0b0a86 530;; Fri December 23, 1994
eaccd4d8 531
0f0b0a86
KH
532;; Changed the representation in ediff-killed-diffs-alist so that
533;; ediff-save-diff-region and ediff-pop-diff won't be confused when the
534;; user swaps buffers.
535
536;; Mon December 26, 1994
537
538;; Placated OS/2 by making Ediff to synchronize the call to startup
539;; hooks with the acynchronous process that computes custom diffs.
540;; This has no effect on Unix installations (and VMS?), but
541;; may increase Ediff's startup time under OS/2 by 1 or 2 seconds.
542
543;; Thu December 29, 1994
544
545;; ediff-recenter now deactivates the mark, so that transient mark mode
546;; highlighting won't interfere with Ediff's highlighting.
547;; Also, ediff-recenter tries to not deiconify control frame, if it is
548;; not needed.
549
550;; Fri December 30, 1994
551
552;; Small bugs. Worked around the OS/2 bug where
553;; modify-frame-parameters has no effect on iconified frames. Ediff
554;; now remembers the iconification status of the control frame and uses
555;; it as a preferred way of displaying it when help is toggled
556;; off. (This can be observed only in Emacs (not XEmacs) and only if
557;; the window manager lets icons accept keyboard input.)
558
559;; Tue January 3, 1995
560
561;; Some futher work on incorporating buffer C in ediff-extract-diffs,
562;; ediff-focus/hide-on-regexp-matches, and
563;; ediff-setup-windows-plain/multiframe. The preceding two functions
564;; now dispatch the appropriate setup function depending on whether the
565;; current job is comparison or merge.
566
567;; Wed January 4, 1995
568
569;; Made it work under Emacs built without the X support.
570
571;; Fri January 6, 1995
572
573;; Slightly changed the prompting behavior of ediff-files. Bug fix in
574;; mode-line-buffer-identification.
575
576;; Wed January 18, 1995
577
578;; Added 3way comparison and support for diff3. Ported to NeXTStep
579;;
580;; Fri January 20, 1995
581
582;; Added ediff-merge-files, ediff-merge-buffers,
583;; ediff-merge-files-with-ancestor, ediff-merge-buffers-with-ancestor,
584;; ediff-merge-revisions, ediff-merge-revisions-with-ancestor.
585
586;; Tue January 24, 1995
587
588;; Bug fixes. Split into several files.
589
590;; Thu January 26, 1995
591
592;; `*' is now bound to ediff-make-or-kill-fine-diffs. This lets the
593;; user to kill fine diffs for the current region (by providing a
594;; negative prefix arg), if there are so many of them as to hamper
595;; the viewing.
596
597;; Mon January 30, 1995
598
599;; Changed ediff-selective-display to ediff-set-visible-region,
600;; ediff-toggle-selective-display to ediff-toggle-narrow-region.
601;; Ediff now turns selective display off before starting. Restores
602;; selective display on exit.
603;; In 2-way comparison, `a' now copies to buf `b' and `b' to buf `a'.
604;; Previously, the bindings were `ab' and `ba'.
605
606;; Wed February 1, 1995
607
2b911848 608;; Added ediff-undo-selective-display (thanks to Stig <stig@hackvan.com>).
0f0b0a86
KH
609;; Rearranged autoloads. Renamed ediff-entry.el into ediff.el and
610;; ediff.el into ediff-util.el.
611
612;; Fri February 3
613
614;; Added ediff-toggle-show-clashes-only, which is bound to `$'.
615
616;; Fri February 19
617
618;; Some minor patches from Stig. Also, made ediff-xemacs-p and
619;; ediff-*-job into variables for better performance.
620;; In ediff-setup, diff regions are now computed after buffers A/B/C
621;; are set up. Previously, it didn't work right with selective display.
622;; Also, added ediff-profile to time Ediff commands and
623;; ediff-debug-info for civilized display of the difference vectors
624;; (and possibly more in the future).
625
f1a5512a
KH
626;; Tue March 18
627
628;; Fixed ediff-diff-at-point and ediff-toggle-multiframe.
629;; Added ediff-destroy-control-frame, ediff-window-display-p. The latter
630;; replaces window-system in many cases. Needed because in XEmacs 19.12
631;; window-system returns 'tty on a tty display.
632;; Converted xemacs *screen* nomenclature to *frame*.
633;; Made ediff-patch-buffer cope with buffers that don't visit any file.
634;; Fixed ediff-toggle-read-only so it knows the difference between
635;; version-controlled files and others. It also knows whether we are using
636;; patch or not.
637;; Renamed ediff-windows to ediff-windows-wordwise, added
638;; ediff-windows-linewise. Changed ediff-small/large-regions to
639;; ediff-regions-wordwise/linewise
640
641;; Tue May 2
642
643;; Added ediff-documentation. Fixes for XEmacs 19.12.
644;; Merge buffer now assumes the major mode of ediff-default-variant.
645
646;; Mon May 31, 1995
0f0b0a86 647
f1a5512a
KH
648;; Ediff-revision now takes a prefix argument. Can compare two versions of
649;; the same file. Cleaned up ediff-make-control-frame.
650;; Fixed a bug in ediff-get-visible-buffer-window.
651;; Added ediff-cleanup-hooks, ediff-janitor.
652;; ediff-cleanup-hooks is called before ediff-quit-hooks.
0f0b0a86
KH
653
654
655;;; TO DO:
656;; ------
657;;
658;; 1. Add support for multiple sessions. (At present, one can run
659;; multiple Ediff sessions, but they won't be related.) The idea is to
660;; have vars local to each control buffer, which will tell which buffer is
661;; the next and which is the previous one. The user could then go forward
662;; and backward by typing C-SPC and C-DEL (or C-n and C-p).
663;; This will probably entail some minor modifications to ediff-setup.
664;; The primary use of this feature would be comparing directories of
665;; similarly named files and multi-file patch. For the latter, Ediff will
666;; have to parse patches to extract the names of files.
667
668
669;;; Acknowledgements:
670
671;; Special thanks to Alastair Burt <burt@dfki.uni-kl.de>, Kevin Broadey
672;; <KevinB@bartley.demon.co.uk>, Harald Boegeholz
673;; <hwb@machnix.mathematik.uni-stuttgart.de>, Jin S. Choi" <jin@atype.com>,
674;; Eric Eide <eeide@asylum.cs.utah.edu>, Kevin Esler <esler@ch.hp.com>, Robert
675;; Estes <estes@ece.ucdavis.edu>, Eric Freudenthal
676;; <freudent@jan.ultra.nyu.edu>,
677;; Job Ganzevoort <Job.Ganzevoort@cwi.nl>, Boris Goldowsky
678;; <boris@cs.rochester.edu>, Allan Gottlieb <gottlieb@allan.ultra.nyu.edu>,
679;; Xiaoli Huang <hxl@epic.com>, Larry Gouge <larry@itginc.com>,
f1a5512a
KH
680;; Karl Heuer <kwzh@gnu.ai.mit.edu>, <irvine@lks.csi.com>,
681;; <jaffe@chipmunk.cita.utoronto.ca>, David Karr
0f0b0a86
KH
682;; <dkarr@nmo.gtegsc.com>, Norbert Kiesel
683;; <norbert@i3.informatik.rwth-aachen.de>, Fritz Knabe <Fritz.Knabe@ecrc.de>,
684;; Heinz Knutzen <hk@informatik.uni-kiel.d400.de>, Ken Laprade
685;; <laprade@dw3f.ess.harris.com>, Richard Levitte
686;; <levitte@e.kth.se>, Martin Maechler <maechler@stat.math.ethz.ch>,
687;; Richard Mlynarik <mly@adoc.xerox.com>, Chris Murphy
688;; <murphycm@sun.aston.ac.uk>, Eyvind Ness <Eyvind.Ness@hrp.no>, Ray Nickson
689;; <nickson@cs.uq.oz.au>, Paul Raines <raines@slac.stanford.edu>, Tibor
690;; Polgar <tlp00@spg.amdahl.com>, C.S. Roberson <roberson@aur.alcatel.com>,
691;; Kevin Rodgers <kevin.rodgers@ihs.com>, Sandy Rutherford
692;; <sandy@ibm550.sissa.it>, Heribert Schuetz <schuetz@ecrc.de>, Andy Scott
693;; <ascott@pcocd2.intel.com>, Axel Seibert
694;; <axel@tumbolia.ppp.informatik.uni-muenchen.de>, Richard Stallman
695;; <rms@gnu.ai.mit.edu>, Richard Stanton <stanton@haas.berkeley.edu>,
696;; Ake Stenhoff <etxaksf@aom.ericsson.se>,
697;; Stig <stig@hackvan.com>, Peter Stout <Peter_Stout@cs.cmu.edu>,
698;; Raymond Toy <toy@rtp.ericsson.se>,
699;; and Ilya Zakharevich <ilya@math.ohio-state.edu>
700;; for contributing ideas, patches, and bug reports.
701;;
702;; Thanks also to many others who felt obliged to drop a thank you note.
703
704
705;;; Code:
706
707(require 'ediff-init)
eaccd4d8
RS
708
709(defvar ediff-version-control-package 'vc
710 "Version control package used.
0f0b0a86
KH
711Currently, Ediff supports vc.el and rcs.el. Set this to `rcs' if you have
712rcs.el and want to use it instead of the standard vc.el.
713
714Note: both packages provide access to RCS, but only vc.el comes with Emacs
715distribution.")
716
d8e54b47 717(defvar ediff-revision-key nil
0f0b0a86 718 "Key to which `ediff-revision' is to be bound.")
813f532d 719
0f0b0a86
KH
720(defvar ediff-use-last-dir nil
721 "*If t, Ediff uses previous directory as default when reading file name.")
b3a26225 722
813f532d
RS
723(defvar ediff-last-dir-A nil
724 "Last directory used by an Ediff command for file-A.")
725(defvar ediff-last-dir-B nil
726 "Last directory used by an Ediff command for file-B.")
0f0b0a86
KH
727(defvar ediff-last-dir-C nil
728 "Last directory used by an Ediff command for file-C.")
729(defvar ediff-last-dir-ancestor nil
730 "Last directory used by an Ediff command for the ancestor file.")
fcbadd58
RS
731(defvar ediff-last-dir-patch nil
732 "Last directory used by an Ediff command for file to patch.")
b3a26225 733
0f0b0a86 734;;; Patching
813f532d
RS
735
736;;;###autoload
f1a5512a 737(defun ediff-patch-file (source-filename &optional startup-hooks job-name)
b3a26225 738 "Run Ediff by patching FILE-TP-PATCH."
f1a5512a 739 ;; This now returns the control buffer
fcbadd58
RS
740 (interactive
741 (list (ediff-read-file-name "File to patch"
742 (if ediff-use-last-dir
743 ediff-last-dir-patch
744 default-directory)
745 nil)))
813f532d 746
0f0b0a86 747 (setq source-filename (expand-file-name source-filename))
f1a5512a
KH
748 (ediff-get-patch-buffer
749 (if (eq job-name 'ediff-patch-buffer)
750 (ediff-eval-in-buffer (get-file-buffer source-filename)
751 default-directory)
752 (file-name-directory source-filename)))
0f0b0a86 753
fcbadd58
RS
754 (let* ((backup-extension
755 ;; if the user specified a -b option, extract the backup
0f0b0a86 756 ;; extension from there; else use `_orig'
fcbadd58
RS
757 (substring ediff-patch-options
758 (if (string-match "-b[ \t]+" ediff-patch-options)
759 (match-end 0) 0)
760 (if (string-match "-b[ \t]+[^ \t]+" ediff-patch-options)
761 (match-end 0) 0)))
fcbadd58
RS
762 (shell-file-name ediff-shell)
763 ;; ediff-find-file may use a temp file to do the patch
764 ;; so, we save source-filename and true-source-filename as a var
765 ;; that initially is source-filename but may be changed to a temp
766 ;; file for the purpose of patching.
767 (true-source-filename source-filename)
768 (target-filename source-filename)
f1a5512a 769 target-buf buf-to-patch file-name-magic-p ctl-buf)
0f0b0a86
KH
770
771 ;; if the user didn't specify a backup extension, use _orig
772 (if (string= backup-extension "")
773 (setq backup-extension "_orig"))
fcbadd58
RS
774
775 ;; Make a temp file, if source-filename has a magic file handler (or if
776 ;; it is handled via auto-mode-alist and similar magic).
777 ;; Check if there is a buffer visiting source-filename and if they are in
778 ;; synch; arrange for the deletion of temp file.
779 (ediff-find-file 'true-source-filename 'buf-to-patch
780 'ediff-last-dir-patch 'startup-hooks)
781
782 ;; Check if source file name has triggered black magic, such as file name
783 ;; handlers or auto mode alist, and make a note of it.
0f0b0a86
KH
784 ;; true-source-filename should be either the original name or a
785 ;; temporary file where we put the after-product of the file handler.
0691ced3
RS
786 (setq file-name-magic-p (not (equal (file-truename true-source-filename)
787 (file-truename source-filename))))
fcbadd58 788
f1a5512a 789 ;; Checkout orig file, if necessary, so that the patched file could be
eaccd4d8 790 ;; checked back in.
f1a5512a
KH
791 (if (ediff-file-checked-in-p (buffer-file-name buf-to-patch))
792 (ediff-toggle-read-only buf-to-patch))
eaccd4d8 793
0f0b0a86
KH
794 (ediff-eval-in-buffer ediff-patch-diagnostics
795 (message "Applying patch ... ")(sit-for 0)
796 ;; always pass patch the -f option, so it won't ask any questions
797 (shell-command-on-region
798 (point-min) (point-max)
799 (format "%s -f %s -b %s %s"
800 ediff-patch-program ediff-patch-options
801 backup-extension
802 (expand-file-name true-source-filename))
803 t))
804 (message "Applying patch ... done")(sit-for 0)
fcbadd58 805 (switch-to-buffer ediff-patch-diagnostics)
0f0b0a86 806 (sit-for 0) ; synchronize
fcbadd58 807
0f0b0a86
KH
808 (or (file-exists-p (concat true-source-filename backup-extension))
809 (error "Patch failed or didn't modify the original file"))
813f532d 810
fcbadd58 811 ;; If black magic is involved, apply patch to a temp copy of the
0f0b0a86
KH
812 ;; file. Otherwise, apply patch to the orig copy. If patch is applied
813 ;; to temp copy, we name the result old-name_patched for local files
814 ;; and temp-copy_patched for remote files. The orig file name isn't
815 ;; changed, and the temp copy of the original is later deleted.
fcbadd58 816 ;; Without magic, the original file is renamed (usually into
0f0b0a86
KH
817 ;; old-name_orig) and the result of patching will have the same name as
818 ;; the original.
fcbadd58 819 (if (not file-name-magic-p)
0f0b0a86
KH
820 (ediff-eval-in-buffer buf-to-patch
821 (set-visited-file-name (concat source-filename backup-extension))
822 (set-buffer-modified-p nil))
823
824 ;; Black magic in effect.
825 ;; If orig file was remote, put the patched file in the temp directory.
826 ;; If orig file is local, put the patched file in the directory of
827 ;; the orig file.
828 (setq target-filename
829 (concat
830 (if (ediff-file-remote-p (file-truename source-filename))
831 true-source-filename
832 source-filename)
833 "_patched"))
834
fcbadd58
RS
835 (rename-file true-source-filename target-filename t)
836
837 ;; arrange that the temp copy of orig will be deleted
0f0b0a86 838 (rename-file (concat true-source-filename backup-extension)
fcbadd58
RS
839 true-source-filename t))
840
841 ;; make orig buffer read-only
eaccd4d8 842 (setq startup-hooks
f1a5512a 843 (cons 'ediff-set-read-only-in-buf-A startup-hooks))
eaccd4d8 844
fcbadd58 845 ;; set up a buf for the patched file
f1a5512a 846 (setq target-buf (find-file-noselect target-filename))
fcbadd58 847
f1a5512a
KH
848 (setq ctl-buf
849 (ediff-buffers-internal
850 buf-to-patch target-buf nil
851 startup-hooks '(or job-name ediff-patch-file)))
813f532d 852
fcbadd58 853 (bury-buffer ediff-patch-diagnostics)
f1a5512a
KH
854 (message "Patch diagnostics are available in buffer %s"
855 (buffer-name ediff-patch-diagnostics))
856 ctl-buf))
0f0b0a86 857
f1a5512a 858(defun ediff-set-read-only-in-buf-A ()
0f0b0a86 859 "Used as a startup hook to set `_orig' patch file read-only."
f1a5512a
KH
860 (ediff-eval-in-buffer ediff-buffer-A
861 (toggle-read-only 1)))
813f532d 862
0f0b0a86 863;;;###autoload
813f532d 864(defalias 'epatch 'ediff-patch-file)
0f0b0a86 865;;;###autoload
b3a26225 866(defalias 'epatch-buffer 'ediff-patch-buffer)
813f532d 867
0f0b0a86 868;;; Compare files/buffers
813f532d
RS
869
870;;;###autoload
871(defun ediff-files (file-A file-B &optional startup-hooks)
0f0b0a86 872 "Run Ediff on a pair of files, FILE-A and FILE-B."
813f532d 873 (interactive
0f0b0a86
KH
874 (let ((dir-A (if ediff-use-last-dir
875 ediff-last-dir-A
876 default-directory))
877 dir-B f)
878 (list (setq f (ediff-read-file-name "File A to compare" dir-A nil))
813f532d 879 (ediff-read-file-name "File B to compare"
0f0b0a86
KH
880 (setq dir-B
881 (if ediff-use-last-dir
882 ediff-last-dir-B
883 (file-name-directory f)))
884 (progn
885 (setq file-name-history
886 (cons (abbreviate-file-name
887 (expand-file-name
888 (file-name-nondirectory f)
889 dir-B))
890 file-name-history))
891 f))
892 )))
893 (ediff-files-internal file-A
894 (if (file-directory-p file-B)
895 (expand-file-name
896 (file-name-nondirectory file-A) file-B)
897 file-B)
898 nil ; file-C
899 startup-hooks
900 'ediff-files))
901
902;;;###autoload
903(defun ediff-files3 (file-A file-B file-C &optional startup-hooks)
904 "Run Ediff on three files, FILE-A, FILE-B, and FILE-C."
905 (interactive
906 (let ((dir-A (if ediff-use-last-dir
907 ediff-last-dir-A
908 default-directory))
909 dir-B dir-C f ff)
910 (list (setq f (ediff-read-file-name "File A to compare" dir-A nil))
911 (setq ff (ediff-read-file-name "File B to compare"
912 (setq dir-B
913 (if ediff-use-last-dir
914 ediff-last-dir-B
915 (file-name-directory f)))
916 (progn
917 (setq file-name-history
918 (cons
919 (abbreviate-file-name
920 (expand-file-name
921 (file-name-nondirectory f)
922 dir-B))
923 file-name-history))
924 f)))
925 (ediff-read-file-name "File C to compare"
926 (setq dir-C (if ediff-use-last-dir
927 ediff-last-dir-C
928 (file-name-directory ff)))
929 (progn
930 (setq file-name-history
931 (cons (abbreviate-file-name
932 (expand-file-name
933 (file-name-nondirectory ff)
934 dir-C))
935 file-name-history))
936 ff))
813f532d 937 )))
b3a26225
RS
938 (ediff-files-internal file-A
939 (if (file-directory-p file-B)
940 (expand-file-name
941 (file-name-nondirectory file-A) file-B)
942 file-B)
0f0b0a86
KH
943 (if (file-directory-p file-C)
944 (expand-file-name
945 (file-name-nondirectory file-A) file-C)
946 file-C)
947 startup-hooks
948 'ediff-files3))
813f532d 949
0f0b0a86
KH
950;;;###autoload
951(defalias 'ediff3 'ediff-files3)
813f532d 952
813f532d 953
0f0b0a86
KH
954(defun ediff-find-file (file-var buffer-name &optional last-dir hooks-var)
955 "Visit FILE and arrange its buffer to Ediff's liking.
956FILE is actually a variable symbol that must contain a true file name.
957BUFFER-NAME is a variable symbol, which will get the buffer object into which
958FILE is read. LAST-DIR is the directory variable symbol where FILE's
959directory name should be returned. HOOKS is a variable symbol that will be
960assigned the hook to be executed after `ediff-startup' is finished.
961`ediff-find-file' arranges that the temp files it might create will be
962deleted."
963 (let* ((file (symbol-value file-var))
f1a5512a 964 (file-magic (find-file-name-handler file 'find-file-noselect))
0f0b0a86
KH
965 (temp-file-name-prefix (file-name-nondirectory file)))
966 (if (not (file-readable-p file))
967 (error "File `%s' does not exist or is not readable" file))
968
969 ;; some of the command, below, require full file name
970 (setq file (expand-file-name file))
971
972 ;; Record the directory of the file
973 (if last-dir
974 (set last-dir (expand-file-name (file-name-directory file))))
975
976 ;; Setup the buffer
977 (set buffer-name (find-file-noselect file))
978
979 (ediff-eval-in-buffer (symbol-value buffer-name)
980 (widen) ; Make sure the entire file is seen
981 (cond (file-magic ;; file has handler, such as jka-compr-handler or
982 ;; ange-ftp-hook-function--arrange for temp file
983 (ediff-verify-file-buffer 'magic)
984 (setq file (ediff-make-temp-file temp-file-name-prefix))
985 (set hooks-var (cons (` (lambda () (delete-file (, file))))
986 (symbol-value hooks-var))))
987 ;; file processed via auto-mode-alist, a la uncompress.el
988 ((not (equal (file-truename file)
989 (file-truename (buffer-file-name))))
990 (setq file (ediff-make-temp-file temp-file-name-prefix))
991 (set hooks-var (cons (` (lambda () (delete-file (, file))))
992 (symbol-value hooks-var))))
993 (t ;; plain file---just check that the file matches the buffer
994 (ediff-verify-file-buffer))))
995 (set file-var file)))
996
997(defun ediff-files-internal (file-A file-B file-C startup-hooks job-name)
998 (let (buf-A buf-B buf-C)
999 (message "Reading file %s ... " file-A)(sit-for 0)
1000 (ediff-find-file 'file-A 'buf-A 'ediff-last-dir-A 'startup-hooks)
1001 (message "Reading file %s ... " file-B)(sit-for 0)
1002 (ediff-find-file 'file-B 'buf-B 'ediff-last-dir-B 'startup-hooks)
1003 (if (and (stringp file-C) (not ediff-merge-job))
1004 (progn
1005 (message "Reading file %s ... " file-C)(sit-for 0)
1006 (ediff-find-file
1007 'file-C 'buf-C
1008 (if (eq job-name 'ediff-merge-files-with-ancestor)
1009 'ediff-last-dir-ancestor 'ediff-last-dir-C)
1010 'startup-hooks)))
1011 (ediff-setup buf-A file-A
1012 buf-B file-B
1013 buf-C file-C
1014 startup-hooks
1015 (list (cons 'ediff-job-name job-name)))))
1016
1017
1018;;;###autoload
1019(defalias 'ediff 'ediff-files)
813f532d 1020
813f532d
RS
1021
1022;;;###autoload
0f0b0a86 1023(defun ediff-buffers (buffer-A buffer-B &optional startup-hooks job-name)
813f532d 1024 "Run Ediff on a pair of buffers, BUFFER-A and BUFFER-B."
fcbadd58 1025 (interactive
0f0b0a86
KH
1026 (let (bf)
1027 (list (setq bf (read-buffer "Buffer A to compare: "
1028 (ediff-other-buffer "") t))
1029 (read-buffer "Buffer B to compare: "
1030 (progn
1031 ;; realign buffers so that two visible bufs will be
1032 ;; at the top
1033 (save-window-excursion (other-window 1))
1034 (ediff-other-buffer bf))
1035 t))))
1036
1037 (or job-name (setq job-name 'ediff-buffers))
1038 (ediff-buffers-internal buffer-A buffer-B nil startup-hooks job-name))
1039
1040;;;###autoload
1041(defun ediff-buffers3 (buffer-A buffer-B buffer-C
1042 &optional startup-hooks job-name)
1043 "Run Ediff on three buffers, BUFFER-A, BUFFER-B, and BUFFER-C."
1044 (interactive
1045 (let (bf bff)
1046 (list (setq bf (read-buffer "Buffer A to compare: "
1047 (ediff-other-buffer "") t))
1048 (setq bff (read-buffer "Buffer B to compare: "
1049 (progn
1050 ;; realign buffers so that two visible
1051 ;; bufs will be at the top
1052 (save-window-excursion (other-window 1))
1053 (ediff-other-buffer bf))
1054 t))
1055 (read-buffer "Buffer C to compare: "
1056 (progn
1057 ;; realign buffers so that three visible
1058 ;; bufs will be at the top
1059 (save-window-excursion (other-window 1))
1060 (ediff-other-buffer (list bf bff)))
1061 t)
1062 )))
1063
1064 (or job-name (setq job-name 'ediff-buffers3))
1065 (ediff-buffers-internal buffer-A buffer-B buffer-C startup-hooks job-name))
1066
1067
1068
1069(defun ediff-buffers-internal (buf-A buf-B buf-C startup-hooks job-name)
1070 (let* ((buf-A-file-name (buffer-file-name (get-buffer buf-A)))
1071 (buf-B-file-name (buffer-file-name (get-buffer buf-B)))
1072 (buf-C-is-alive (ediff-buffer-live-p buf-C))
1073 (buf-C-file-name (if buf-C-is-alive
1074 (buffer-file-name (get-buffer buf-B))))
1075 file-A file-B file-C)
1076 (if (not (ediff-buffer-live-p buf-A))
1077 (error "Buffer %S doesn't exist" buf-A))
1078 (if (not (ediff-buffer-live-p buf-B))
1079 (error "Buffer %S doesn't exist" buf-B))
1080 (let ((ediff-job-name job-name))
1081 (if (and ediff-3way-comparison-job
1082 (not buf-C-is-alive))
1083 (error "Buffer %S doesn't exist" buf-C)))
1084 (if (stringp buf-A-file-name)
1085 (setq buf-A-file-name (file-name-nondirectory buf-A-file-name)))
1086 (if (stringp buf-B-file-name)
1087 (setq buf-B-file-name (file-name-nondirectory buf-B-file-name)))
1088 (if (stringp buf-C-file-name)
1089 (setq buf-C-file-name (file-name-nondirectory buf-C-file-name)))
1090
1091 ;; these three need to be evaluated in their buffers, since
1092 ;; ediff-make-temp-file checks the current buffer when assigning file
1093 ;; names
1094 (ediff-eval-in-buffer buf-A
1095 (setq file-A (ediff-make-temp-file buf-A-file-name)))
1096 (ediff-eval-in-buffer buf-B
1097 (setq file-B (ediff-make-temp-file buf-B-file-name)))
1098 (if buf-C-is-alive
1099 (ediff-eval-in-buffer buf-C
1100 (setq file-C (ediff-make-temp-file buf-C-file-name))))
1101
1102 (ediff-setup (get-buffer buf-A) file-A
1103 (get-buffer buf-B) file-B
1104 (if buf-C-is-alive (get-buffer buf-C))
1105 file-C
1106 (cons (` (lambda ()
1107 (delete-file (, file-A))
1108 (delete-file (, file-B))
1109 (if (stringp (, file-C)) (delete-file (, file-C)))
1110 ))
1111 startup-hooks)
1112 (list (cons 'ediff-job-name job-name))
1113 )))
1114
1115
1116
1117;;; Compare regions and windows
1118
1119;;;###autoload
f1a5512a
KH
1120(defun ediff-windows-wordwise (dumb-mode &optional wind-A wind-B startup-hooks)
1121 "Compare WIND-A and WIND-B, which are selected by clicking, wordwise.
0f0b0a86
KH
1122With prefix argument, DUMB-MODE, or on a non-windowing display, works as
1123follows:
1124If WIND-A is nil, use selected window.
1125If WIND-B is nil, use window next to WIND-A."
0f0b0a86 1126 (interactive "P")
f1a5512a
KH
1127 (ediff-windows dumb-mode wind-A wind-B
1128 startup-hooks 'ediff-windows-wordwise 'word-mode))
1129
1130;;;###autoload
1131(defun ediff-windows-linewise (dumb-mode &optional wind-A wind-B startup-hooks)
1132 "Compare WIND-A and WIND-B, which are selected by clicking, linewise.
1133With prefix argument, DUMB-MODE, or on a non-windowing display, works as
1134follows:
1135If WIND-A is nil, use selected window.
1136If WIND-B is nil, use window next to WIND-A."
1137 (interactive "P")
1138 (ediff-windows dumb-mode wind-A wind-B
1139 startup-hooks 'ediff-windows-linewise nil))
0f0b0a86 1140
f1a5512a
KH
1141;; Compare WIND-A and WIND-B, which are selected by clicking.
1142;; With prefix argument, DUMB-MODE, or on a non-windowing display,
1143;; works as follows:
1144;; If WIND-A is nil, use selected window.
1145;; If WIND-B is nil, use window next to WIND-A.
1146(defun ediff-windows (dumb-mode wind-A wind-B startup-hooks job-name word-mode)
1147 (if (or dumb-mode (not (ediff-window-display-p)))
0f0b0a86
KH
1148 (setq wind-A (ediff-get-next-window wind-A nil)
1149 wind-B (ediff-get-next-window wind-B wind-A))
1150 (setq wind-A (ediff-get-window-by-clicking wind-A nil 1)
1151 wind-B (ediff-get-window-by-clicking wind-B wind-A 2)))
1152
1153 (let ((buffer-A (window-buffer wind-A))
1154 (buffer-B (window-buffer wind-B))
1155 beg-A end-A beg-B end-B)
1156
1157 (save-excursion
1158 (save-window-excursion
1159 (sit-for 0) ; synch before using window-start/end -- a precaution
1160 (select-window wind-A)
1161 (setq beg-A (window-start)
1162 end-A (window-end))
1163 (select-window wind-B)
1164 (setq beg-B (window-start)
1165 end-B (window-end))))
1166 (ediff-regions-internal
1167 buffer-A beg-A end-A buffer-B beg-B end-B
f1a5512a 1168 startup-hooks job-name word-mode)))
0f0b0a86
KH
1169
1170;;;###autoload
f1a5512a 1171(defun ediff-regions-wordwise (buffer-A buffer-B &optional startup-hooks)
0f0b0a86
KH
1172 "Run Ediff on a pair of regions in two different buffers.
1173Regions \(i.e., point and mark\) are assumed to be set in advance.
1174This function is effective only for relatively small regions, up to 200
f1a5512a 1175lines. For large regions, use `ediff-regions-linewise'."
0f0b0a86
KH
1176 (interactive
1177 (let (bf)
1178 (list (setq bf (read-buffer "Region's A buffer: "
1179 (ediff-other-buffer "") t))
1180 (read-buffer "Region's B buffer: "
1181 (progn
1182 ;; realign buffers so that two visible bufs will be
1183 ;; at the top
1184 (save-window-excursion (other-window 1))
1185 (ediff-other-buffer bf))
1186 t))))
1187 (if (not (ediff-buffer-live-p buffer-A))
1188 (error "Buffer %S doesn't exist" buffer-A))
1189 (if (not (ediff-buffer-live-p buffer-B))
1190 (error "Buffer %S doesn't exist" buffer-B))
1191
1192
1193 (let (reg-A-beg reg-A-end reg-B-beg reg-B-end)
1194 (save-excursion
1195 (set-buffer buffer-A)
1196 (setq reg-A-beg (region-beginning)
1197 reg-A-end (region-end))
1198 (set-buffer buffer-B)
1199 (setq reg-B-beg (region-beginning)
1200 reg-B-end (region-end)))
1201
1202 (ediff-regions-internal
1203 (get-buffer buffer-A) reg-A-beg reg-A-end
1204 (get-buffer buffer-B) reg-B-beg reg-B-end
f1a5512a 1205 startup-hooks 'ediff-regions-wordwise 'word-mode)))
0f0b0a86
KH
1206
1207;;;###autoload
f1a5512a 1208(defun ediff-regions-linewise (buffer-A buffer-B &optional startup-hooks)
0f0b0a86
KH
1209 "Run Ediff on a pair of regions in two different buffers.
1210Regions \(i.e., point and mark\) are assumed to be set in advance.
1211Each region is enlarged to contain full lines.
1212This function is effective for large regions, over 100-200
f1a5512a 1213lines. For small regions, use `ediff-regions-wordwise'."
0f0b0a86
KH
1214 (interactive
1215 (let (bf)
1216 (list (setq bf (read-buffer "Region A's buffer: "
1217 (ediff-other-buffer "") t))
1218 (read-buffer "Region B's buffer: "
1219 (progn
1220 ;; realign buffers so that two visible bufs will be
1221 ;; at the top
1222 (save-window-excursion (other-window 1))
1223 (ediff-other-buffer bf))
1224 t))))
fcbadd58 1225 (if (not (ediff-buffer-live-p buffer-A))
0f0b0a86 1226 (error "Buffer %S doesn't exist" buffer-A))
fcbadd58 1227 (if (not (ediff-buffer-live-p buffer-B))
0f0b0a86
KH
1228 (error "Buffer %S doesn't exist" buffer-B))
1229
1230 (let (reg-A-beg reg-A-end reg-B-beg reg-B-end)
1231 (save-excursion
1232 (set-buffer buffer-A)
1233 (setq reg-A-beg (region-beginning)
1234 reg-A-end (region-end))
1235 ;; enlarge the region to hold full lines
1236 (goto-char reg-A-beg)
1237 (beginning-of-line)
1238 (setq reg-A-beg (point))
1239 (goto-char reg-A-end)
1240 (end-of-line)
1241 (or (eobp) (forward-char)) ; include the newline char
1242 (setq reg-A-end (point))
fcbadd58 1243
0f0b0a86
KH
1244 (set-buffer buffer-B)
1245 (setq reg-B-beg (region-beginning)
1246 reg-B-end (region-end))
1247 ;; enlarge the region to hold full lines
1248 (goto-char reg-A-beg)
1249 (goto-char reg-B-beg)
1250 (beginning-of-line)
1251 (setq reg-B-beg (point))
1252 (goto-char reg-B-end)
1253 (end-of-line)
1254 (or (eobp) (forward-char)) ; include the newline char
1255 (setq reg-B-end (point))
1256 ) ; save excursion
1257
1258 (ediff-regions-internal
1259 (get-buffer buffer-A) reg-A-beg reg-A-end
1260 (get-buffer buffer-B) reg-B-beg reg-B-end
f1a5512a 1261 startup-hooks 'ediff-regions-linewise nil))) ; no word mode
0f0b0a86
KH
1262
1263;; compare region beg-A to end-A of buffer-A
1264;; to regions beg-B -- end-B in buffer-B.
1265(defun ediff-regions-internal (buffer-A beg-A end-A buffer-B beg-B end-B
1266 startup-hooks job-name word-mode)
1267 (let ((tmp-buffer (get-buffer-create ediff-tmp-buffer))
1268 overl-A overl-B
1269 file-A file-B)
1270
1271 ;; in case beg/end-A/B aren't markers--make them into markers
1272 (ediff-eval-in-buffer buffer-A
1273 (setq beg-A (move-marker (make-marker) beg-A)
1274 end-A (move-marker (make-marker) end-A)))
1275 (ediff-eval-in-buffer buffer-B
1276 (setq beg-B (move-marker (make-marker) beg-B)
1277 end-B (move-marker (make-marker) end-B)))
1278
1279 (if (and (eq buffer-A buffer-B)
1280 (or (and (< beg-A end-B) (<= beg-B beg-A)) ; b-B b-A e-B
1281 (and (< beg-B end-A) (<= end-A end-B)))) ; b-B e-A e-B
1282 (progn
1283 (with-output-to-temp-buffer ediff-msg-buffer
1284 (princ "
1285You have requested to compare overlapping regions of the same buffer.
1286
1287In this case, Ediff's highlighting may be confusing---in the same window,
1288you may see highlighted regions that belong to different regions.
1289
1290Continue anyway? (y/n) "))
1291
1292 (if (y-or-n-p "Continue anyway? ")
1293 ()
1294 (error "%S aborted" job-name))))
1295
1296 ;; make file-A
1297 (if word-mode
1298 (ediff-wordify beg-A end-A buffer-A tmp-buffer)
1299 (ediff-copy-to-buffer beg-A end-A buffer-A tmp-buffer))
1300 (ediff-eval-in-buffer tmp-buffer
1301 (setq file-A (ediff-make-temp-file "regA")))
1302
1303 ;; make file-B
1304 (if word-mode
1305 (ediff-wordify beg-B end-B buffer-B tmp-buffer)
1306 (ediff-copy-to-buffer beg-B end-B buffer-B tmp-buffer))
1307 (ediff-eval-in-buffer tmp-buffer
1308 (setq file-B (ediff-make-temp-file "regB")))
1309
1310 (setq overl-A (ediff-make-bullet-proof-overlay beg-A end-A buffer-A))
1311 (setq overl-B (ediff-make-bullet-proof-overlay beg-B end-B buffer-B))
1312 (ediff-setup buffer-A file-A
1313 buffer-B file-B
1314 nil nil ; buffer & file C
813f532d 1315 (cons (` (lambda ()
b3a26225
RS
1316 (delete-file (, file-A))
1317 (delete-file (, file-B))))
813f532d 1318 startup-hooks)
0f0b0a86
KH
1319 (list (cons 'ediff-word-mode word-mode)
1320 (cons 'ediff-narrow-bounds (list overl-A overl-B))
1321 (cons 'ediff-job-name job-name))
1322 )
1323 ))
1324
1325
1326;;; Merge files and buffers
1327
1328;;;###autoload
1329(defalias 'ediff-merge 'ediff-merge-files)
1330
1331(defsubst ediff-merge-on-startup ()
1332 (ediff-do-merge 0)
1333 (ediff-eval-in-buffer ediff-buffer-C
1334 (set-buffer-modified-p nil)))
1335
1336;;;###autoload
1337(defun ediff-merge-files (file-A file-B &optional startup-hooks)
1338 "Merge two files without ancestor."
1339 (interactive
1340 (let ((dir-A (if ediff-use-last-dir
1341 ediff-last-dir-A
1342 default-directory))
1343 dir-B f)
1344 (list (setq f (ediff-read-file-name "File A to merge" dir-A nil))
1345 (ediff-read-file-name "File B to merge"
1346 (setq dir-B
1347 (if ediff-use-last-dir
1348 ediff-last-dir-B
1349 (file-name-directory f)))
1350 (progn
1351 (setq file-name-history
1352 (cons (abbreviate-file-name
1353 (expand-file-name
1354 (file-name-nondirectory f)
1355 dir-B))
1356 file-name-history))
1357 f))
1358 )))
1359 (setq startup-hooks (cons 'ediff-merge-on-startup startup-hooks))
1360 (ediff-files-internal file-A
1361 (if (file-directory-p file-B)
1362 (expand-file-name
1363 (file-name-nondirectory file-A) file-B)
1364 file-B)
1365 nil ; file-C
1366 startup-hooks
1367 'ediff-merge-files))
1368
1369;;;###autoload
1370(defun ediff-merge-files-with-ancestor (file-A file-B file-ancestor
1371 &optional startup-hooks)
1372 "Merge two files with ancestor."
1373 (interactive
1374 (let ((dir-A (if ediff-use-last-dir
1375 ediff-last-dir-A
1376 default-directory))
1377 dir-B dir-ancestor f ff)
1378 (list (setq f (ediff-read-file-name "File A to merge" dir-A nil))
1379 (setq ff (ediff-read-file-name "File B to merge"
1380 (setq dir-B
1381 (if ediff-use-last-dir
1382 ediff-last-dir-B
1383 (file-name-directory f)))
1384 (progn
1385 (setq file-name-history
1386 (cons
1387 (abbreviate-file-name
1388 (expand-file-name
1389 (file-name-nondirectory f)
1390 dir-B))
1391 file-name-history))
1392 f)))
1393 (ediff-read-file-name "Ancestor file"
1394 (setq dir-ancestor
1395 (if ediff-use-last-dir
1396 ediff-last-dir-ancestor
1397 (file-name-directory ff)))
1398 (progn
1399 (setq file-name-history
1400 (cons (abbreviate-file-name
1401 (expand-file-name
1402 (file-name-nondirectory ff)
1403 dir-ancestor))
1404 file-name-history))
1405 ff))
1406 )))
1407 (setq startup-hooks (cons 'ediff-merge-on-startup startup-hooks))
1408 (ediff-files-internal file-A
1409 (if (file-directory-p file-B)
1410 (expand-file-name
1411 (file-name-nondirectory file-A) file-B)
1412 file-B)
1413 file-ancestor
1414 startup-hooks
1415 'ediff-merge-files-with-ancestor))
1416
1417;;;###autoload
1418(defalias 'ediff-merge-with-ancestor 'ediff-merge-files-with-ancestor)
1419
1420;;;###autoload
1421(defun ediff-merge-buffers (buffer-A buffer-B &optional startup-hooks job-name)
1422 "Merge buffers without ancestor."
1423 (interactive
1424 (let (bf)
1425 (list (setq bf (read-buffer "Buffer A to merge: "
1426 (ediff-other-buffer "") t))
1427 (read-buffer "Buffer B to merge: "
1428 (progn
1429 ;; realign buffers so that two visible bufs will be
1430 ;; at the top
1431 (save-window-excursion (other-window 1))
1432 (ediff-other-buffer bf))
1433 t))))
1434
1435 (setq startup-hooks (cons 'ediff-merge-on-startup startup-hooks))
1436 (or job-name (setq job-name 'ediff-merge-buffers))
1437 (ediff-buffers-internal
1438 buffer-A buffer-B nil startup-hooks job-name))
1439
1440;;;###autoload
1441(defun ediff-merge-buffers-with-ancestor (buffer-A
1442 buffer-B buffer-ancestor
1443 &optional startup-hooks job-name)
1444 "Merge buffers with ancestor."
1445 (interactive
1446 (let (bf bff)
1447 (list (setq bf (read-buffer "Buffer A to merge: "
1448 (ediff-other-buffer "") t))
1449 (setq bff (read-buffer "Buffer B to merge: "
1450 (progn
1451 ;; realign buffers so that two visible
1452 ;; bufs will be at the top
1453 (save-window-excursion (other-window 1))
1454 (ediff-other-buffer bf))
1455 t))
1456 (read-buffer "Ancestor buffer: "
1457 (progn
1458 ;; realign buffers so that three visible
1459 ;; bufs will be at the top
1460 (save-window-excursion (other-window 1))
1461 (ediff-other-buffer (list bf bff)))
1462 t)
1463 )))
1464
1465 (setq startup-hooks (cons 'ediff-merge-on-startup startup-hooks))
1466 (or job-name (setq job-name 'ediff-merge-buffers-with-ancestor))
1467 (ediff-buffers-internal
1468 buffer-A buffer-B buffer-ancestor startup-hooks job-name))
1469
1470
1471;;;###autoload
1472(defun ediff-merge-revisions (rev1 rev2 &optional startup-hooks)
1473 "Run Ediff by merging two revisions of a file.
1474The file is the one visited by the current buffer."
1475 (interactive
1476 "sVersion 1 to merge (default is the latest version): \nsVersion 2 to merge (default is the latest version): ")
1477 (ediff-load-version-control)
1478 (let (buf1 buf2)
1479 (if (eq ediff-version-control-package 'vc)
1480 (progn
1481 (save-excursion
1482 (vc-version-other-window rev1)
1483 (setq buf1 (current-buffer)))
1484 (save-excursion
1485 (vc-version-other-window rev2)
1486 (setq buf2 (current-buffer)))
1487 (setq startup-hooks
1488 (list (` (lambda ()
1489 (delete-file (, (buffer-file-name buf1)))
1490 (delete-file (, (buffer-file-name buf2))))))))
1491 (setq buf1 (rcs-ediff-view-revision rev1)
1492 buf2 (rcs-ediff-view-revision rev2)))
1493 (ediff-merge-buffers buf1 buf2 startup-hooks 'ediff-merge-revisions)))
1494
1495
1496;;;###autoload
1497(defun ediff-merge-revisions-with-ancestor (rev1
1498 rev2 ancestor-rev
1499 &optional startup-hooks)
1500 "Run Ediff by merging with ancestor of two revisions of a file.
1501The file is the one visited by the current buffer."
1502 (interactive
1503 "sVersion 1 to merge (default: the latest version): \nsVersion 2 to merge (default: the latest version): \nsAncestor version (default: the latest version): ")
1504 (ediff-load-version-control)
1505 (let (buf1 buf2 ancestor-buf)
1506 (if (eq ediff-version-control-package 'vc)
1507 (progn
1508 (save-excursion
1509 (vc-version-other-window rev1)
1510 (setq buf1 (current-buffer)))
1511 (save-excursion
1512 (vc-version-other-window rev2)
1513 (setq buf2 (current-buffer)))
1514 (save-excursion
1515 (vc-version-other-window ancestor-rev)
1516 (setq ancestor-buf (current-buffer)))
1517 (setq startup-hooks
1518 (list (` (lambda ()
1519 (delete-file (, (buffer-file-name buf1)))
1520 (delete-file (, (buffer-file-name buf2)))
1521 (delete-file (, (buffer-file-name ancestor-buf)))
1522 )))))
1523 (setq buf1 (rcs-ediff-view-revision rev1)
1524 buf2 (rcs-ediff-view-revision rev2)
1525 ancestor-buf (rcs-ediff-view-revision ancestor-rev)))
1526 (ediff-merge-buffers-with-ancestor
1527 buf1 buf2 ancestor-buf
1528 startup-hooks 'ediff-merge-revisions-with-ancestor)))
1529
1530
1531;;; Apply patch
1532
1533
c8dfbe33 1534;;;###autoload
813f532d
RS
1535(defun ediff-patch-buffer (buffer-name &optional startup-hooks)
1536 "Run Ediff by patching BUFFER-NAME."
1537 (interactive "bBuffer to patch: ")
1538
f1a5512a
KH
1539 (let* ((buf-to-patch (get-buffer buffer-name))
1540 (file-name-ok (if buf-to-patch (buffer-file-name buf-to-patch)))
1541 (buf-mod-status (buffer-modified-p buf-to-patch))
1542 default-dir file-name ctl-buf)
1543 (if file-name-ok
1544 (setq file-name file-name-ok)
1545 (ediff-eval-in-buffer buffer-name
1546 (setq default-dir default-directory)
1547 (setq file-name (ediff-make-temp-file))
1548 (set-visited-file-name file-name)
1549 (setq buffer-auto-save-file-name nil) ; don't create auto-save file
1550 (rename-buffer buffer-name) ; don't confuse the user with new buf name
1551 (set-buffer-modified-p nil)
1552 (set-visited-file-modtime) ; sync buffer and temp file
1553 (setq default-directory default-dir)
1554 ))
813f532d 1555
f1a5512a
KH
1556 (setq ctl-buf
1557 (ediff-patch-file file-name startup-hooks 'ediff-patch-buffer))
1558
1559 (if file-name-ok
1560 ()
1561 (ediff-eval-in-buffer ctl-buf
1562 (delete-file (buffer-file-name ediff-buffer-A))
1563 (delete-file (buffer-file-name ediff-buffer-B))
1564 (ediff-eval-in-buffer ediff-buffer-A
1565 (if default-dir (setq default-directory default-dir))
1566 (set-visited-file-name nil)
1567 (rename-buffer buffer-name)
1568 (set-buffer-modified-p buf-mod-status))
1569 (ediff-eval-in-buffer ediff-buffer-B
1570 (setq buffer-auto-save-file-name nil) ; don't create auto-save file
1571 (if default-dir (setq default-directory default-dir))
1572 (set-visited-file-name nil)
1573 (rename-buffer (ediff-unique-buffer-name
1574 (concat buffer-name "_patched") ""))
1575 (set-buffer-modified-p t))))
1576 ))
0f0b0a86
KH
1577
1578
1579(defun ediff-get-patch-buffer (dir)
1580 "Obtain patch buffer. If patch is already in a buffer---use it.
1581Else, read patch file into a new buffer."
1582 (if (y-or-n-p "Is the patch file already in a buffer? ")
1583 (setq ediff-patch-buf
1584 (get-buffer (read-buffer "Patch buffer name: " nil t))) ;must match
1585 (setq ediff-patch-buf
1586 (find-file-noselect (read-file-name "Patch file name: " dir))))
1587
0f0b0a86
KH
1588 (setq ediff-patch-diagnostics
1589 (get-buffer-create "*ediff patch diagnostics*"))
f1a5512a
KH
1590 (ediff-eval-in-buffer ediff-patch-diagnostics
1591 (insert-buffer ediff-patch-buf)))
0f0b0a86
KH
1592
1593
813f532d
RS
1594
1595
0f0b0a86 1596\f
813f532d
RS
1597;;; Versions Control functions
1598
1599;;;###autoload
f1a5512a 1600(defun ediff-revision (arg)
eaccd4d8 1601 "Call `vc.el' or `rcs.el' depending on `ediff-version-control-package'.
f1a5512a
KH
1602Without prefix argument, compares the current buffer with an older version.
1603With prefix argument, compares two older versions of the current buffer."
1604 (interactive "P")
1605 (let (rev1 rev2)
1606 (if arg
1607 (setq rev1
1608 (read-string
1609 "This buffer's version-1 to compare (default: the latest version): ")
1610 rev2
1611 (read-string "This buffer's version-2 to compare (default: the latest version): "))
1612 (setq rev1
1613 (read-string "Version to compare the current buffer with (default: the latest version): ")))
1614 (ediff-load-version-control)
1615 (funcall
1616 (intern (format "%S-ediff-internal" ediff-version-control-package))
1617 rev1 rev2)
1618 ))
0f0b0a86
KH
1619
1620;; Backward compatibility
1621;;;###autoload
1622(defun vc-ediff ()
1623 (interactive)
1624 (beep 1)
1625 (with-output-to-temp-buffer ediff-msg-buffer
1626 (princ "
1627You have invoked an obsolete function `vc-ediff' or `rcs-ediff'.
1628Please use `M-x ediff-revision' instead.
1629
1630Also, please check the variables `ediff-version-control-package'
1631and `ediff-revision-key' for customization.")))
1632
1633(defalias 'rcs-ediff 'vc-ediff)
1634
1635;; Test if version control package is loaded and load if not
1636;; Is SILENT is non-nil, don't report error if package is not found.
1637(defun ediff-load-version-control (&optional silent)
1638 (or (featurep ediff-version-control-package)
1639 (if (locate-library (symbol-name ediff-version-control-package))
1640 (progn
1641 (message "") ; kill the message from `locate-library'
1642 (require ediff-version-control-package)
d8e54b47
RS
1643 (if ediff-revision-key
1644 (define-key
1645 (cond ((eq ediff-version-control-package 'vc) vc-prefix-map)
1646 ((eq ediff-version-control-package 'rcs) global-map)
1647 (t global-map))
1648 ediff-revision-key 'ediff-revision)))
0f0b0a86 1649 (or silent
f1a5512a 1650 (error "Version control package %S.el not found. Use vc.el instead"
0f0b0a86
KH
1651 ediff-version-control-package)))))
1652
eaccd4d8 1653
f1a5512a
KH
1654(defun vc-ediff-internal (rev1 &optional rev2)
1655 "Run Ediff on versions of the current buffer.
1656If both REV1 and REV2 are given then these two versions are compared.
1657If only REV1 is given then the current buffer is compared against version REV1.
813f532d 1658If the current buffer is named `F', the version is named `F.~REV~'.
08020d91 1659If `F.~REV~' already exists, it is used instead of being re-created."
f1a5512a
KH
1660 (let ((curbuf (current-buffer))
1661 (curwind (selected-window))
1662 file1 file2
1663 rev1buf rev2buf)
1664 (vc-version-other-window rev1)
1665 (setq rev1buf (current-buffer)
1666 file1 (buffer-file-name))
1667 (select-window curwind)
1668 (if (not (stringp rev2))
1669 (setq rev2buf curbuf)
1670 (vc-version-other-window rev2)
1671 (setq rev2buf (current-buffer)
1672 file2 (buffer-file-name)))
1673 (ediff-buffers
1674 rev1buf rev2buf
1675 (list (` (lambda ()
1676 (delete-file (, file1))
1677 (if (, file2) (delete-file (, file2)))
1678 )))
1679 'ediff-revision)))
813f532d
RS
1680
1681(defun rcs-ediff-view-revision (&optional rev)
b3a26225 1682 "View previous RCS revision of current file.
813f532d
RS
1683With prefix argument, prompts for a revision name."
1684 (interactive (list (if current-prefix-arg
1685 (read-string "Revision: "))))
1686 (let* ((filename (buffer-file-name (current-buffer)))
1687 (switches (append '("-p")
1688 (if rev (list (concat "-r" rev)) nil)))
1689 (buff (concat (file-name-nondirectory filename) ".~" rev "~")))
0f0b0a86 1690 (message "Working ...")
813f532d 1691 (setq filename (expand-file-name filename))
0691ced3 1692 (with-output-to-temp-buffer buff
b3a26225 1693 (let ((output-buffer (ediff-rcs-get-output-buffer filename buff)))
813f532d
RS
1694 (delete-windows-on output-buffer)
1695 (save-excursion
1696 (set-buffer output-buffer)
1697 (apply 'call-process "co" nil t nil
1698 ;; -q: quiet (no diagnostics)
1699 (append switches rcs-default-co-switches
1700 (list "-q" filename)))))
1701 (message "")
1702 buff)))
b3a26225
RS
1703
1704(defun ediff-rcs-get-output-buffer (file name)
1705 ;; Get a buffer for RCS output for FILE, make it writable and clean it up.
1706 ;; Optional NAME is name to use instead of `*RCS-output*'.
fcbadd58 1707 ;; This is a modified version from rcs.el v1.1. I use it here to make
b3a26225 1708 ;; Ediff immune to changes in rcs.el
0f0b0a86 1709 (let* ((default-major-mode 'fundamental-mode) ; no frills!
b3a26225
RS
1710 (buf (get-buffer-create name)))
1711 (save-excursion
1712 (set-buffer buf)
1713 (setq buffer-read-only nil
1714 default-directory (file-name-directory (expand-file-name file)))
1715 (erase-buffer))
1716 buf))
813f532d 1717
f1a5512a 1718(defun rcs-ediff-internal (rev1 &optional rev2)
eaccd4d8 1719 "Run Ediff on the current buffer, comparing it with previous RCS revision."
f1a5512a
KH
1720 (let ((rev2buf (if (stringp rev2)
1721 (rcs-ediff-view-revision rev2)
1722 (current-buffer)))
1723 (rev1buf (rcs-ediff-view-revision rev1)))
fcbadd58 1724
0f0b0a86
KH
1725 ;; rcs.el doesn't create temp version files, so we don't have to delete
1726 ;; anything in startup hooks to ediff-buffers
f1a5512a 1727 (ediff-buffers rev1buf rev2buf nil 'ediff-revision)
813f532d 1728 ))
813f532d 1729
0f0b0a86 1730;;; Menu bar
eaccd4d8 1731
0f0b0a86
KH
1732;;; This is split in several parts to avoid
1733;;; making a line in loaddefs.el that is too long for patch.
1734;;; Note that autoload.el currently looks for cookies
1735;;; only at top level in the file.
1736;;; So I moved these to top level. But the conditionals on
1737;;; purify-flag make these no-ops when you load ediff.
1738;;; They only do something in loaddefs.el.
813f532d 1739
0f0b0a86
KH
1740;;;###autoload
1741(if purify-flag
1742 ;; explicit string-match, as ediff-xemacs-p is not defined at build time
1743 (if (string-match "\\(Lucid\\|Xemacs\\)" emacs-version)
1744 ()
1745 (defvar menu-bar-epatch-menu (make-sparse-keymap "Epatch"))
1746 (fset 'menu-bar-epatch-menu (symbol-value 'menu-bar-epatch-menu))
1747 (defvar menu-bar-ediff-merge-menu (make-sparse-keymap "Ediff merge"))
1748 (fset 'menu-bar-ediff-merge-menu
1749 (symbol-value 'menu-bar-ediff-merge-menu))
1750 (defvar menu-bar-ediff-menu (make-sparse-keymap "Ediff"))
1751 (fset 'menu-bar-ediff-menu (symbol-value 'menu-bar-ediff-menu))
0f0b0a86 1752 ))
813f532d 1753
f1a5512a
KH
1754;;; These must be placed in menu-bar.el in Emacs
1755;;
1756;; (define-key menu-bar-tools-menu [epatch]
1757;; '("Apply Patch" . menu-bar-epatch-menu))
1758;; (define-key menu-bar-tools-menu [ediff-merge]
1759;; '("Merge" . menu-bar-ediff-merge-menu))
1760;; (define-key menu-bar-tools-menu [ediff]
1761;; '("Compare" . menu-bar-ediff-menu))
1762
813f532d 1763
0f0b0a86
KH
1764;;;###autoload
1765(if purify-flag
1766 ;; explicit string-match, as ediff-xemacs-p is not defined at build time
1767 (if (string-match "\\(Lucid\\|Xemacs\\)" emacs-version)
1768 ()
1769 (define-key menu-bar-ediff-menu [ediff-revision]
1770 '("File with Revision ..." . ediff-revision))
2ef2d897 1771 (define-key menu-bar-ediff-menu [separator-ediff-files] '("--"))
0f0b0a86
KH
1772 (define-key menu-bar-ediff-menu [ediff-buffers3]
1773 '("Three Buffers ..." . ediff-buffers3))
1774 (define-key menu-bar-ediff-menu [ediff-files3]
1775 '("Three Files ..." . ediff-files3))
1776 (define-key menu-bar-ediff-menu [ediff-buffers]
1777 '("Two Buffers ..." . ediff-buffers))
1778 (define-key menu-bar-ediff-menu [ediff-files]
1779 '("Two Files ..." . ediff-files))
1780 ))
813f532d 1781
f1a5512a
KH
1782;;;###autoload
1783(if purify-flag
1784 ;; explicit string-match, as ediff-xemacs-p is not defined at build time
1785 (if (string-match "\\(Lucid\\|Xemacs\\)" emacs-version)
1786 ()
2ef2d897 1787 (define-key menu-bar-ediff-menu [separator-ediff-regions] '("--"))
f1a5512a
KH
1788 (define-key menu-bar-ediff-menu [ediff-regions-linewise]
1789 '("Regions Line-by-line ..." . ediff-regions-linewise))
1790 (define-key menu-bar-ediff-menu [ediff-regions-wordwise]
1791 '("Regions Word-by-word ..." . ediff-regions-wordwise))
2ef2d897 1792 (define-key menu-bar-ediff-menu [separator-ediff-windows] '("--"))
f1a5512a
KH
1793 (define-key menu-bar-ediff-menu [ediff-windows-linewise]
1794 '("Windows Line-by-line ..." . ediff-windows-linewise))
1795 (define-key menu-bar-ediff-menu [ediff-windows-wordwise]
1796 '("Windows Word-by-word ..." . ediff-windows-wordwise))
1797 ))
1798
0f0b0a86
KH
1799;;;###autoload
1800(if purify-flag
1801 ;; explicit string-match, as ediff-xemacs-p is not defined at build time
1802 (if (string-match "\\(Lucid\\|Xemacs\\)" emacs-version)
1803 ()
1804 (define-key
1805 menu-bar-ediff-merge-menu [ediff-merge-revisions-with-ancestor]
1806 '("Revisions with Ancestor ..." . ediff-merge-revisions-with-ancestor))
1807 (define-key menu-bar-ediff-merge-menu [ediff-merge-revisions]
1808 '("Revisions ..." . ediff-merge-revisions))
2ef2d897 1809 (define-key menu-bar-ediff-merge-menu [separator-ediff-merge] '("--"))
0f0b0a86
KH
1810 (define-key menu-bar-ediff-merge-menu [ediff-merge-buffers-with-ancestor]
1811 '("Buffers with Ancestor ..." . ediff-merge-buffers-with-ancestor))
1812 (define-key menu-bar-ediff-merge-menu [ediff-merge-buffers]
1813 '("Buffers ..." . ediff-merge-buffers))
1814 (define-key menu-bar-ediff-merge-menu [ediff-merge-files-with-ancestor]
1815 '("Files with Ancestor ..." . ediff-merge-files-with-ancestor))
1816 (define-key menu-bar-ediff-merge-menu [ediff-merge-files]
1817 '("Files ..." . ediff-merge-files))
1818 ))
b3a26225 1819
0f0b0a86
KH
1820;;;###autoload
1821(if purify-flag
1822 ;; explicit string-match, as ediff-xemacs-p is not defined at build time
1823 (if (string-match "\\(Lucid\\|Xemacs\\)" emacs-version)
1824 ()
1825 (define-key menu-bar-epatch-menu [ediff-patch-buffer]
1826 '("To a Buffer ..." . ediff-patch-buffer))
1827 (define-key menu-bar-epatch-menu [ediff-patch-file]
1828 '("To a File ..." . ediff-patch-file))
1829 ))
813f532d 1830
813f532d 1831
0f0b0a86
KH
1832;;;###autoload
1833(if purify-flag
1834 ;; explicit string-match, as ediff-xemacs-p is not defined at build time
1835 (if (string-match "\\(Lucid\\|Xemacs\\)" emacs-version)
813f532d 1836 (progn
0f0b0a86 1837 (defvar ediff-menu
f1a5512a 1838 '("Compare"
0f0b0a86
KH
1839 ["Two Files ..." ediff-files t]
1840 ["Two Buffers ..." ediff-buffers t]
1841 ["Three Files ..." ediff-files3 t]
1842 ["Three Buffers ..." ediff-buffers3 t]
f1a5512a
KH
1843 "---"
1844 ["File with Revision ..." ediff-revision t]
1845 "---"
1846 ["Windows Word-by-word ..." ediff-windows-wordwise t]
1847 ["Windows Line-by-line ..." ediff-windows-linewise t]
1848 "---"
1849 ["Regions Word-by-word ..." ediff-regions-wordwise t]
1850 ["Regions Line-by-line ..." ediff-regions-linewise t]))
0f0b0a86 1851 (defvar ediff-merge-menu
f1a5512a 1852 '("Merge"
0f0b0a86
KH
1853 ["Files ..." ediff-merge-files t]
1854 ["Files with Ancestor ..." ediff-merge-files-with-ancestor t]
1855 ["Buffers ..." ediff-merge-buffers t]
1856 ["Buffers with Ancestor ..."
1857 ediff-merge-buffers-with-ancestor t]
f1a5512a 1858 "---"
0f0b0a86
KH
1859 ["Revisions ..." ediff-merge-revisions t]
1860 ["Revisions with Ancestor ..."
1861 ediff-merge-revisions-with-ancestor t]))
1862 (defvar epatch-menu
f1a5512a 1863 '("Apply Patch"
0f0b0a86
KH
1864 ["To a file ..." ediff-patch-file t]
1865 ["To a buffer ..." ediff-patch-buffer t]))
f1a5512a
KH
1866 (add-submenu '("Tools") ediff-menu "VC")
1867 (add-submenu '("Tools") ediff-merge-menu "VC")
1868 (add-submenu '("Tools") epatch-menu "VC")
0f0b0a86 1869 ;; Display a solid horizontal line
f1a5512a 1870 (add-menu-button '("Tools") ["---" nil nil] "VC")
0f0b0a86 1871 )))
b3a26225 1872
813f532d
RS
1873
1874(provide 'ediff)
0f0b0a86 1875(require 'ediff-util)
813f532d
RS
1876
1877;;; ediff.el ends here