Withdraw mouse-major-mode-map modifications.
[bpt/emacs.git] / lisp / ediff.el
1 ;;; ediff.el --- a comprehensive visual interface to diff & patch
2 ;;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
3
4 ;; Author: Michael Kifer <kifer@cs.sunysb.edu>
5 ;; Created: February 2, 1994
6 ;; Keywords: comparing, merging, patching, version control.
7
8 (defconst ediff-version "2.26" "The current version of Ediff")
9 (defconst ediff-date "June 3, 1995" "Date of last update")
10
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
27 ;;; Commentary:
28 ;; ----------
29
30 ;; Never read that diff output again!
31 ;; Apply patch selectively, like a pro!
32 ;; Merge with ease!
33
34 ;; This package provides a convenient way of simultaneous browsing through
35 ;; the differences between a pair (or a triple) of files or buffers. The
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).
41
42 ;; In addition, Ediff can apply a patch to a file and then let you step
43 ;; though both files, the patched and the original one, simultaneously,
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
48 ;; region from file_orig to file, thereby undoing any particular patch that
49 ;; you don't like).
50
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
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.
58
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.
63
64
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.
71 ;;
72 ;;; Bugs:
73 ;; -----
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
77 ;; `undo', the reinstated text will most likely be inserted outside of
78 ;; what Ediff thinks is the current difference region. (This problem
79 ;; doesn't seem to exist with XEmacs.)
80 ;;
81 ;; If at any point you feel that difference regions are no longer correct,
82 ;; you can hit '!' to recompute the differences.
83
84 ;; 2. On a monochrome display, the repertoire of faces with which to
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.
95 ;;
96
97 ;;; Change Log:
98 ;; ----------
99
100 ;; Thu Feb 3, 1994
101
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.
137 ;;
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.)
155 ;;
156 ;; Cleanups in ediff-patch-file. Protected ediff-copy-diff against
157 ;; a bug that Emacs has in kill-region.
158 ;;
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.)
188 ;;
189 ;; Further fixes in the XEmacs part. Changed highlighted region in
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.
212 ;; Hitting `h' (ediff-toggle-hilit) on a dumb terminal will toggle
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.
241 ;; Made Ediff execute diff and patch using Bourne Shell, which
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
247 ;; slow goto-line by forward-line.
248 ;; Converted demarkation of difference regions
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
255 ;; current difference in bright colors. Improved XEmacs support.
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.
264 ;; Added commands `ga', `gb' to jump directly to the closest diff in
265 ;; buffer A and B, respectively.
266
267 ;; Fri April 11, 1994
268
269 ;; Added `ediff-update-diffs', a function that lets the user recompute
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.
293 ;; Added Ediff to the File menu on the menu bar (FSF's version).
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
305 ;; Fixed ediff-keep-window-config (thanks to Norbert Kiesel
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
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
332 ;; <Job.Ganzevoort@cwi.nl>).
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
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
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
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
386 ;; If ediff-save-buffer is invoked with `wd', it'll save the diff
387 ;; output in a file.
388
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.
404
405 ;; Thu September 1, 1994
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
412 ;; Thu September 8, 1994
413
414 ;; Added ediff-revision-key, ediff-load-version-control and streamlined
415 ;; vc/rcs-ediff[-internal]. Eliminated dependency on emerge.el.
416
417 ;; Fri September 23, 1994
418
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.
422
423 ;; Tue September 27, 1994
424
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.
428
429 ;; Fri September 30, 1994
430
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.
434
435 ;; Fri October 7, 1994
436
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.
449
450 ;; Wed October 12, 1994
451
452 ;; ediff-window-visible-p now makes a call to frame-visible-p
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.
465
466 ;; Thu October 20, 1994
467
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.
479
480 ;; Fri October 28, 1994
481
482 ;; Fixed bugs in ediff-next/previous-difference, ediff-set-visible-region
483 ;; Changed/added ediff-word-[1-4].
484
485 ;; Tue November 1, 1994
486
487 ;; Made ediff-revision delete the temporary version files it creates.
488
489 ;; Tue November 29, 1994
490
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.
495
496 ;; Thu December 1, 1994
497
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.
505
506 ;; Thu December 8, 1994
507
508 ;; Added ediff-toggle-wide-display. In plain display, help message is
509 ;; now centered correctly.
510
511 ;; Fri December 9, 1994
512
513 ;; Added ediff-toggle-multiframe.
514 ;; Fixed ediff-pop-diff and ediff-copy-diff, so that they will
515 ;; invoke auto-refining, if necessary.
516
517 ;; Mon December 12, 1994
518
519 ;; Modified ediff-toggle-wide-display so it would funcall
520 ;; ediff-make-wide-display-function.
521
522 ;; Tue December 13, 1994
523
524 ;; Ediff now chooses its surrogate minibuffer from frame A.
525
526 ;; Mon December 20, 1994
527
528 ;; Added ediff-keymap-setup-hooks.
529
530 ;; Fri December 23, 1994
531
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
608 ;; Added ediff-undo-selective-display (thanks to Stig <stig@inse.com>).
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
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
647
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.
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>,
680 ;; Karl Heuer <kwzh@gnu.ai.mit.edu>, <irvine@lks.csi.com>,
681 ;; <jaffe@chipmunk.cita.utoronto.ca>, David Karr
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)
708
709 (defvar ediff-version-control-package 'vc
710 "Version control package used.
711 Currently, Ediff supports vc.el and rcs.el. Set this to `rcs' if you have
712 rcs.el and want to use it instead of the standard vc.el.
713
714 Note: both packages provide access to RCS, but only vc.el comes with Emacs
715 distribution.")
716
717 (defvar ediff-revision-key nil
718 "Key to which `ediff-revision' is to be bound.")
719
720 (defvar ediff-use-last-dir nil
721 "*If t, Ediff uses previous directory as default when reading file name.")
722
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.")
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.")
731 (defvar ediff-last-dir-patch nil
732 "Last directory used by an Ediff command for file to patch.")
733
734 ;;; Patching
735
736 ;;;###autoload
737 (defun ediff-patch-file (source-filename &optional startup-hooks job-name)
738 "Run Ediff by patching FILE-TP-PATCH."
739 ;; This now returns the control buffer
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)))
746
747 (setq source-filename (expand-file-name source-filename))
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)))
753
754 (let* ((backup-extension
755 ;; if the user specified a -b option, extract the backup
756 ;; extension from there; else use `_orig'
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)))
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)
769 target-buf buf-to-patch file-name-magic-p ctl-buf)
770
771 ;; if the user didn't specify a backup extension, use _orig
772 (if (string= backup-extension "")
773 (setq backup-extension "_orig"))
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.
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.
786 (setq file-name-magic-p (not (equal (file-truename true-source-filename)
787 (file-truename source-filename))))
788
789 ;; Checkout orig file, if necessary, so that the patched file could be
790 ;; checked back in.
791 (if (ediff-file-checked-in-p (buffer-file-name buf-to-patch))
792 (ediff-toggle-read-only buf-to-patch))
793
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)
805 (switch-to-buffer ediff-patch-diagnostics)
806 (sit-for 0) ; synchronize
807
808 (or (file-exists-p (concat true-source-filename backup-extension))
809 (error "Patch failed or didn't modify the original file"))
810
811 ;; If black magic is involved, apply patch to a temp copy of the
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.
816 ;; Without magic, the original file is renamed (usually into
817 ;; old-name_orig) and the result of patching will have the same name as
818 ;; the original.
819 (if (not file-name-magic-p)
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
835 (rename-file true-source-filename target-filename t)
836
837 ;; arrange that the temp copy of orig will be deleted
838 (rename-file (concat true-source-filename backup-extension)
839 true-source-filename t))
840
841 ;; make orig buffer read-only
842 (setq startup-hooks
843 (cons 'ediff-set-read-only-in-buf-A startup-hooks))
844
845 ;; set up a buf for the patched file
846 (setq target-buf (find-file-noselect target-filename))
847
848 (setq ctl-buf
849 (ediff-buffers-internal
850 buf-to-patch target-buf nil
851 startup-hooks '(or job-name ediff-patch-file)))
852
853 (bury-buffer ediff-patch-diagnostics)
854 (message "Patch diagnostics are available in buffer %s"
855 (buffer-name ediff-patch-diagnostics))
856 ctl-buf))
857
858 (defun ediff-set-read-only-in-buf-A ()
859 "Used as a startup hook to set `_orig' patch file read-only."
860 (ediff-eval-in-buffer ediff-buffer-A
861 (toggle-read-only 1)))
862
863 ;;;###autoload
864 (defalias 'epatch 'ediff-patch-file)
865 ;;;###autoload
866 (defalias 'epatch-buffer 'ediff-patch-buffer)
867
868 ;;; Compare files/buffers
869
870 ;;;###autoload
871 (defun ediff-files (file-A file-B &optional startup-hooks)
872 "Run Ediff on a pair of files, FILE-A and FILE-B."
873 (interactive
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))
879 (ediff-read-file-name "File B to compare"
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))
937 )))
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)
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))
949
950 ;;;###autoload
951 (defalias 'ediff3 'ediff-files3)
952
953
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.
956 FILE is actually a variable symbol that must contain a true file name.
957 BUFFER-NAME is a variable symbol, which will get the buffer object into which
958 FILE is read. LAST-DIR is the directory variable symbol where FILE's
959 directory name should be returned. HOOKS is a variable symbol that will be
960 assigned the hook to be executed after `ediff-startup' is finished.
961 `ediff-find-file' arranges that the temp files it might create will be
962 deleted."
963 (let* ((file (symbol-value file-var))
964 (file-magic (find-file-name-handler file 'find-file-noselect))
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)
1020
1021
1022 ;;;###autoload
1023 (defun ediff-buffers (buffer-A buffer-B &optional startup-hooks job-name)
1024 "Run Ediff on a pair of buffers, BUFFER-A and BUFFER-B."
1025 (interactive
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
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.
1122 With prefix argument, DUMB-MODE, or on a non-windowing display, works as
1123 follows:
1124 If WIND-A is nil, use selected window.
1125 If WIND-B is nil, use window next to WIND-A."
1126 (interactive "P")
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.
1133 With prefix argument, DUMB-MODE, or on a non-windowing display, works as
1134 follows:
1135 If WIND-A is nil, use selected window.
1136 If 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))
1140
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)))
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
1168 startup-hooks job-name word-mode)))
1169
1170 ;;;###autoload
1171 (defun ediff-regions-wordwise (buffer-A buffer-B &optional startup-hooks)
1172 "Run Ediff on a pair of regions in two different buffers.
1173 Regions \(i.e., point and mark\) are assumed to be set in advance.
1174 This function is effective only for relatively small regions, up to 200
1175 lines. For large regions, use `ediff-regions-linewise'."
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
1205 startup-hooks 'ediff-regions-wordwise 'word-mode)))
1206
1207 ;;;###autoload
1208 (defun ediff-regions-linewise (buffer-A buffer-B &optional startup-hooks)
1209 "Run Ediff on a pair of regions in two different buffers.
1210 Regions \(i.e., point and mark\) are assumed to be set in advance.
1211 Each region is enlarged to contain full lines.
1212 This function is effective for large regions, over 100-200
1213 lines. For small regions, use `ediff-regions-wordwise'."
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))))
1225 (if (not (ediff-buffer-live-p buffer-A))
1226 (error "Buffer %S doesn't exist" buffer-A))
1227 (if (not (ediff-buffer-live-p buffer-B))
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))
1243
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
1261 startup-hooks 'ediff-regions-linewise nil))) ; no word mode
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 "
1285 You have requested to compare overlapping regions of the same buffer.
1286
1287 In this case, Ediff's highlighting may be confusing---in the same window,
1288 you may see highlighted regions that belong to different regions.
1289
1290 Continue 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
1315 (cons (` (lambda ()
1316 (delete-file (, file-A))
1317 (delete-file (, file-B))))
1318 startup-hooks)
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.
1474 The 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.
1501 The 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
1534 ;;;###autoload
1535 (defun ediff-patch-buffer (buffer-name &optional startup-hooks)
1536 "Run Ediff by patching BUFFER-NAME."
1537 (interactive "bBuffer to patch: ")
1538
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 ))
1555
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 ))
1577
1578
1579 (defun ediff-get-patch-buffer (dir)
1580 "Obtain patch buffer. If patch is already in a buffer---use it.
1581 Else, 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
1588 (setq ediff-patch-diagnostics
1589 (get-buffer-create "*ediff patch diagnostics*"))
1590 (ediff-eval-in-buffer ediff-patch-diagnostics
1591 (insert-buffer ediff-patch-buf)))
1592
1593
1594
1595
1596 \f
1597 ;;; Versions Control functions
1598
1599 ;;;###autoload
1600 (defun ediff-revision (arg)
1601 "Call `vc.el' or `rcs.el' depending on `ediff-version-control-package'.
1602 Without prefix argument, compares the current buffer with an older version.
1603 With 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 ))
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 "
1627 You have invoked an obsolete function `vc-ediff' or `rcs-ediff'.
1628 Please use `M-x ediff-revision' instead.
1629
1630 Also, please check the variables `ediff-version-control-package'
1631 and `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)
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)))
1649 (or silent
1650 (error "Version control package %S.el not found. Use vc.el instead"
1651 ediff-version-control-package)))))
1652
1653
1654 (defun vc-ediff-internal (rev1 &optional rev2)
1655 "Run Ediff on versions of the current buffer.
1656 If both REV1 and REV2 are given then these two versions are compared.
1657 If only REV1 is given then the current buffer is compared against version REV1.
1658 If the current buffer is named `F', the version is named `F.~REV~'.
1659 If `F.~REV~' already exists, it is used instead of being re-created."
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)))
1680
1681 (defun rcs-ediff-view-revision (&optional rev)
1682 "View previous RCS revision of current file.
1683 With 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 "~")))
1690 (message "Working ...")
1691 (setq filename (expand-file-name filename))
1692 (with-output-to-temp-buffer buff
1693 (let ((output-buffer (ediff-rcs-get-output-buffer filename buff)))
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)))
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*'.
1707 ;; This is a modified version from rcs.el v1.1. I use it here to make
1708 ;; Ediff immune to changes in rcs.el
1709 (let* ((default-major-mode 'fundamental-mode) ; no frills!
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))
1717
1718 (defun rcs-ediff-internal (rev1 &optional rev2)
1719 "Run Ediff on the current buffer, comparing it with previous RCS revision."
1720 (let ((rev2buf (if (stringp rev2)
1721 (rcs-ediff-view-revision rev2)
1722 (current-buffer)))
1723 (rev1buf (rcs-ediff-view-revision rev1)))
1724
1725 ;; rcs.el doesn't create temp version files, so we don't have to delete
1726 ;; anything in startup hooks to ediff-buffers
1727 (ediff-buffers rev1buf rev2buf nil 'ediff-revision)
1728 ))
1729
1730 ;;; Menu bar
1731
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.
1739
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))
1752 ))
1753
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
1763
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))
1771 (define-key menu-bar-ediff-menu [separator-ediff-files] '("--"))
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 ))
1781
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 ()
1787 (define-key menu-bar-ediff-menu [separator-ediff-regions] '("--"))
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))
1792 (define-key menu-bar-ediff-menu [separator-ediff-windows] '("--"))
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
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))
1809 (define-key menu-bar-ediff-merge-menu [separator-ediff-merge] '("--"))
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 ))
1819
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 ))
1830
1831
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)
1836 (progn
1837 (defvar ediff-menu
1838 '("Compare"
1839 ["Two Files ..." ediff-files t]
1840 ["Two Buffers ..." ediff-buffers t]
1841 ["Three Files ..." ediff-files3 t]
1842 ["Three Buffers ..." ediff-buffers3 t]
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]))
1851 (defvar ediff-merge-menu
1852 '("Merge"
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]
1858 "---"
1859 ["Revisions ..." ediff-merge-revisions t]
1860 ["Revisions with Ancestor ..."
1861 ediff-merge-revisions-with-ancestor t]))
1862 (defvar epatch-menu
1863 '("Apply Patch"
1864 ["To a file ..." ediff-patch-file t]
1865 ["To a buffer ..." ediff-patch-buffer t]))
1866 (add-submenu '("Tools") ediff-menu "VC")
1867 (add-submenu '("Tools") ediff-merge-menu "VC")
1868 (add-submenu '("Tools") epatch-menu "VC")
1869 ;; Display a solid horizontal line
1870 (add-menu-button '("Tools") ["---" nil nil] "VC")
1871 )))
1872
1873
1874 (provide 'ediff)
1875 (require 'ediff-util)
1876
1877 ;;; ediff.el ends here