comparison lisp/ediff.el @ 11041:17b319a26eea

Installed new version from author.
author Karl Heuer <kwzh@gnu.org>
date Thu, 16 Mar 1995 22:31:54 +0000
parents 716969785d08
children e168f57ece92
comparison
equal deleted inserted replaced
11040:2ea19d4d0b4b 11041:17b319a26eea
1 ;;; ediff.el --- a visual interface to diff & patch 1 ;;; ediff.el --- a comprehensive visual interface to diff & patch
2 ;;; Copyright (C) 1994 Free Software Foundation, Inc. 2 ;;; Copyright (C) 1994 Free Software Foundation, Inc.
3 3
4 ;; Author: Michael Kifer <kifer@cs.sunysb.edu> 4 ;; Author: Michael Kifer <kifer@cs.sunysb.edu>
5 ;; Created: February 2, 1994 5 ;; Created: February 2, 1994
6 ;; Version: 1.65e
7 ;; Keywords: comparing, merging, patching, version control. 6 ;; Keywords: comparing, merging, patching, version control.
8 7
9 (defvar ediff-version "1.65e" "The current version of Ediff") 8 (defconst ediff-version "2.19" "The current version of Ediff")
10 (defvar ediff-date "September 1, 1994" "Date of last update") 9 (defconst ediff-date "March 14, 1995" "Date of last update")
10
11 ;; LCD Archive Entry:
12 ;; ediff|Michael Kifer|kifer@cs.sunysb.edu|
13 ;; A comprehensive visual interface to diff and patch|
14 ;; 14-March-95|2.19|~/packages/ediff.shar.Z|
15
11 16
12 ;; This file is part of GNU Emacs. 17 ;; This file is part of GNU Emacs.
13 18
14 ;; GNU Emacs is free software; you can redistribute it and/or modify 19 ;; GNU Emacs is free software; you can redistribute it and/or modify
15 ;; it under the terms of the GNU General Public License as published by 20 ;; it under the terms of the GNU General Public License as published by
23 28
24 ;; You should have received a copy of the GNU General Public License 29 ;; You should have received a copy of the GNU General Public License
25 ;; along with GNU Emacs; see the file COPYING. If not, write to 30 ;; along with GNU Emacs; see the file COPYING. If not, write to
26 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 31 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
27 32
28
29 ;;; Commentary: 33 ;;; Commentary:
30 ;; ---------- 34 ;; ----------
31 35
32 ;; Never read those diff outputs again! 36 ;; Never read that diff output again!
33 ;; Apply patch selectively, like a pro! 37 ;; Apply patch selectively, like a pro!
38 ;; Merge with ease!
34 39
35 ;; This package provides a convenient way of simultaneous browsing through 40 ;; This package provides a convenient way of simultaneous browsing through
36 ;; the differences between a pair of files or buffers. The two files being 41 ;; the differences between a pair (or a tripple) of files or buffers. The
37 ;; compared (file-A and file-B) are shown in separate windows (side by 42 ;; files being compared, file-A, file-B, and file-C (if applicable) are
38 ;; side, one above the another, or in separate frames), and the differences 43 ;; shown in separate windows (side by side, one above the another, or in
39 ;; are highlighted as you step through them. You can also copy difference 44 ;; separate frames), and the differences are highlighted as you step
40 ;; regions from one buffer to another (and recover old differences if you 45 ;; through them. You can also copy difference regions from one buffer to
41 ;; change your mind). 46 ;; another (and recover old differences if you change your mind).
42 47
43 ;; In addition, Ediff can apply a patch to a file and then let you step 48 ;; In addition, Ediff can apply a patch to a file and then let you step
44 ;; though both files, the patched and the original one, simultaneously, 49 ;; though both files, the patched and the original one, simultaneously,
45 ;; difference-by-difference. You can even apply a patch right out of a 50 ;; difference-by-difference. You can even apply a patch right out of a
46 ;; mail buffer, i.e., patches received by mail don't even have to be saved. 51 ;; mail buffer, i.e., patches received by mail don't even have to be saved.
47 ;; Since Ediff lets you copy differences between buffers, you can, in 52 ;; Since Ediff lets you copy differences between buffers, you can, in
48 ;; effect, apply patches selectively (i.e., you can copy a difference 53 ;; effect, apply patches selectively (i.e., you can copy a difference
49 ;; region from file.orig to file, thereby undoing any particular patch that 54 ;; region from file_orig to file, thereby undoing any particular patch that
50 ;; you don't like). 55 ;; you don't like).
51 56
52 ;; This package builds upon the ideas borrowed from emerge.el. It is still 57 ;; This package builds upon the ideas borrowed from emerge.el and
53 ;; using half a dozen of functions defined there. Several other Ediff's 58 ;; several Ediff's functions are adaptations from emerge.el.
54 ;; functions are adaptations from emerge.el. Ediff requires, at least, 59 ;; Much of the functionality of Ediff is also influenced by emerge.el.
55 ;; Version 5 of emerge.el. This version comes with standard distributions 60
56 ;; of Emacs and Lemacs. Make sure you don't have some stray old copy of 61 ;; The present version of Ediff supersedes Emerge. It provides a superior
57 ;; Emerge on your load path. 62 ;; user interface and has many features not found in Emerge. In particular,
58 63 ;; it can do patching and 2-way and 3-way file comparison in addition to
59 ;; Ediff is complimentary to Emerge. While Emerge is primarily intended 64 ;; merging.
60 ;; for merging of files, Ediff is by far superior for browsing through 65
61 ;; files compared via diff and for patching files with patch. 66 ;; Ediff is aware of version control, which lets the user compare
62 ;; Furthermore, Ediff is more convenient even for merging, when one of the 67 ;; files with their older versions. Ediff can also work with remote and
63 ;; files is a designated output. This situation arises while patching 68 ;; compressed files. Details are given below.
64 ;; files or when comparing an old version of a file with a newer version 69
65 ;; (in such cases, it is often desirable to selectively revert some 70
66 ;; portions of the new file to its old state). 71 ;;; Remarks:
67 72 ;; -------
68 ;; Ediff also supports version control via vc.el (in the standard 73
69 ;; distribution of Emacs 19) and rcs.el. The latter is a package written by 74 ;; 1. Ediff is heavily dependent on the new features of Emacs 19.
70 ;; Sebastian Kremer <sk@thp.Uni-Koeln.DE>, which is available in 75 ;; It won't run under Emacs 18 at all.
71 ;; 76 ;; 2. If running XEmacs, Ediff requires at least version 19.9.
72 ;; ftp.cs.buffalo.edu:pub/Emacs/rcs.tar.Z 77 ;; 3. The function ediff-revision requires the version of vc.el that comes
73 ;; ftp.uni-koeln.de:/pub/gnu/emacs/rcs.tar.Z 78 ;; with Emacs 19.22 and XEmacs 19.10 and later, or rcs.el version 1.67
74 ;; 79 ;; or later. See "Version control support", below.
75 ;; To specify which version control package you are using, set the variable 80
76 ;; ediff-version-control-package, e.g., 81
77 ;; (setq ediff-version-control-package 'rcs) 82 ;;; Installation and use:
78 ;; The default, is 'vc'. 83 ;; ---------------------
79 84
80 85 ;; The user can invoke Ediff interactively using the following functions:
81 ;; Window configuration: 86 ;;
82 ;; ---------------------- 87 ;; ediff-files - compare two files
83 88 ;; ediff - alias for ediff-files
84 ;; By default, Ediff sets things up in one frame, splitting it between a 89 ;; ediff-buffers - compare two buffers
85 ;; small control window and the two windows for file-A and file-B. The 90 ;;
86 ;; split between these latter windows can be horizontal or vertical, which 91 ;; ediff-files3 - compare three files
87 ;; can be changed interactively by hitting 's' while the cursor is in the 92 ;; ediff3 - alias for ediff-files3
88 ;; control window. 93 ;; ediff-buffers3 - compare three buffers
89 ;; 94 ;;
90 ;; In a multi-frame situation, Ediff would work as follows. When it starts, 95 ;; ediff-windows - compare windows
91 ;; it will place the control window in the frame that was selected at the 96 ;; ediff-small-regions - compare small regions
92 ;; time of the invocation. If file-A or file-B is seen in one of the 97 ;; ediff-large-regions - compare large regions
93 ;; frames, Ediff will leave it there. If a file (A/B) is not visible in any 98 ;;
94 ;; frame, Ediff will arrange that it will share a frame with the control 99 ;; ediff-revision - compare buffer & version
95 ;; window. (If none of the files is visible, then both will share the 100 ;;
96 ;; control window frame.) The same algorithm works when you hit 'c' 101 ;; ediff-patch-file - patch file then compare
97 ;; (ediff-recenter), 'p' (ediff-previous-difference), 'n', etc. 102 ;; epatch - alias for ediff-patch-file
103 ;; ediff-patch-buffer - patch buffer then compare
104 ;; epatch-buffer - alias for ediff-patch-buffer
105 ;;
106 ;; ediff-merge-files - merge two files
107 ;; ediff-merge - alias for ediff-merge-files
108 ;; ediff-merge-files-with-ancestor - same but with ancestor
109 ;; ediff-merge-with-ancestor - alias for the above
110 ;; ediff-merge-buffers - merge two buffers
111 ;; ediff-merge-buffers-with-ancestor - same but with ancestor
112 ;; ediff-merge-revisions - same but with ancestor
113 ;; ediff-merge-revisions-with-ancestor - same but with ancestor
114 ;;
115 ;;
116 ;;
117 ;; To use Ediff, put this in your .emacs file:
118 ;;
119 ;; (autoload 'ediff-buffers "ediff" "Visual interface to diff" t)
120 ;; (autoload 'ediff "ediff" "Visual interface to diff" t)
121 ;; (autoload 'ediff-files "ediff" "Visual interface to diff" t)
122 ;; (autoload 'ediff-buffers3 "ediff" "Visual interface to diff" t)
123 ;; (autoload 'ediff3 "ediff3" "Visual interface to diff" t)
124 ;; (autoload 'ediff-files3 "ediff" "Visual interface to diff" t)
125 ;; (autoload 'ediff-merge "ediff" "Visual interface to diff" t)
126 ;; (autoload 'ediff-merge-files "ediff" "Visual interface to diff" t)
127 ;; (autoload 'ediff-merge-files-with-ancestor "ediff"
128 ;; "Visual interface to diff" t)
129 ;; (autoload 'ediff-merge-with-ancestor "ediff" "Visual interface to diff" t)
130 ;; (autoload 'ediff-merge-buffers "ediff" "Visual interface to diff" t)
131 ;; (autoload 'ediff-merge-buffers-with-ancestor "ediff"
132 ;; "Visual interface to diff" t)
133 ;; (autoload 'ediff-merge-revisions "ediff" "Visual interface to diff" t)
134 ;; (autoload 'ediff-merge-revisions-with-ancestor "ediff"
135 ;; "Visual interface to diff" t)
136 ;; (autoload 'ediff-windows "ediff" "Visual interface to diff" t)
137 ;; (autoload 'ediff-small-regions "ediff" "Visual interface to diff" t)
138 ;; (autoload 'ediff-large-regions "ediff" "Visual interface to diff" t)
139 ;; (autoload 'epatch "ediff" "Visual interface to patch" t)
140 ;; (autoload 'ediff-patch-file "ediff" "Visual interface to patch" t)
141 ;; (autoload 'ediff-patch-buffer "ediff" "Visual interface to patch" t)
142 ;; (autoload 'epatch-buffer "ediff" "Visual interface to patch" t)
143 ;; (autoload 'ediff-revision "ediff"
144 ;; "Interface to diff & version control" t)
145 ;;
146 ;;
147 ;; If you want Ediff to be loaded from the very beginning, you should have
148 ;;
149 ;; (require 'ediff)
150 ;;
151 ;; in your .emacs file. This way it is also easier to figure out changes
152 ;; to the default Ediff setting, if such changes become necessary --- see
153 ;; Customization.
154 ;;
155 ;; All the above functions use the diff program to find different
156 ;; regions. They process diff output and display it to the user in a
157 ;; convenient form.
158 ;;
159 ;; The functions ediff-files, ediff-buffers, ediff-files3, ediff-buffers3
160 ;; first display the coarse, line-based difference regions, as commonly
161 ;; found by the diff program.
162 ;; Since diff may report fairly large chunks of text as being
163 ;; different even though the difference may be contained in a few words or
164 ;; even in the white space or line breaks, Ediff will further refine the
165 ;; regions to indicate which exact words differ. If the only difference is
166 ;; in the white space and line breaks, Ediff will say so.
167 ;;
168 ;; The functions ediff-windows, ediff-small-regions and ediff-large-regions
169 ;; do comparison on parts of buffers (which must already exist).
170 ;; Since ediff-windows and ediff-small-regions are intended for relatively
171 ;; small segments of the buffers, comparison is done on the
172 ;; word-basis rather than line basis. No refinement is necessary in this
173 ;; case. This technique is effective only for relatively small
174 ;; regions (perhaps, up to 100 lines), as these functions have a relatively
175 ;; slow startup.
176 ;; To compare large regions, use ediff-large-regions. In this mode, Ediff
177 ;; displays differences as it would if invoked via ediff-files or
178 ;; ediff-buffers.
179 ;;
180 ;; The functions ediff-patch-file and ediff-patch-buffer apply a patch
181 ;; to a file or a buffer and then run Ediff on these buffers, displaying
182 ;; the difference regions.
183 ;;
184 ;; Finally, for files under version control, ediff-revisions will compare a
185 ;; file to one of its versions.
186
187 ;;; Compilation
188 ;; -----------
189 ;;
190 ;; When you byte-compile Ediff, you will get some warnings about functions
191 ;; being undefined. These can be safely ignored.
192 ;;
193
194 ;;; Customization:
195 ;; --------------
196
197 ;; Hooks:
198 ;; -----
199 ;; If you don't like the default setting, you can change it through the
200 ;; various variables and hooks. In particular, the following hooks are
201 ;; available:
202
203 ;; ediff-load-hooks
204 ;; ediff-keymap-setup-hooks
205 ;; ediff-before-setup-windows-hooks
206 ;; ediff-after-setup-windows-hooks
207 ;; ediff-before-setup-control-frame-hooks
208 ;; ediff-after-setup-control-frame-hooks
209 ;; ediff-startup-hooks
210 ;; ediff-select-hooks
211 ;; ediff-unselect-hooks
212 ;; ediff-suspend-hooks
213 ;; ediff-quit-hooks
214 ;; ediff-prepare-buffer-hooks
215 ;; ediff-display-help-hooks
216
217 ;; The hooks in ediff-load-hooks can be used to change defaults after Ediff
218 ;; is loaded. The hooks in ediff-keymap-setup-hooks can be used to alter
219 ;; bindings in Ediff's keymap. These hooks are called right after the
220 ;; default bindings are set.
221 ;;
222 ;; The hooks in ediff-before/after-setup-windows-hooks,
223 ;; ediff-suspend-hooks, and ediff-quit-hooks can be used to save and then
224 ;; restore whatever window configuration you want.
225
226 ;; Note that, by default, ediff-quit-hooks is set to a function,
227 ;; ediff-cleanup-mess, which cleans after Ediff, as appropriate in most
228 ;; cases. It is rather unlikely that the user will want to change
229 ;; it. However, the user may want add other hooks to ediff-quit-hooks,
230 ;; either before or after ediff-cleanup-mess (see the documentation for
231 ;; add-hook on how to do this). One should be aware that hooks executing
232 ;; before ediff-cleanup-mess start in ediff-control-buffer; they should
233 ;; also leave ediff-control-buffer as the current buffer. Hooks that are
234 ;; executed after ediff-cleanup-mess will have either buffer A or buffer B
235 ;; as the current buffer.
236
237 ;; If you are using packages such as mode-line.el to alter
238 ;; the buffer identification field in the mode line, you may have to
239 ;; restore this field after exiting Ediff by calling an appropriate
240 ;; function from a hook in ediff-quit-hooks (in case of mode-line.el, the
241 ;; function to call would be mode-line-abbreviate-buffer-identification).
242 ;; This should be done from a hook that runs before ediff-default-quit-hook,
243 ;; since such hooks run from within ediff-control-buffer, where buffers
244 ;; A, B, and C can be accessed via the variables ediff-buffer-A,
245 ;; ediff-buffer-B, ediff-buffer-C.
246
247 ;; The hooks ediff-before/after-setup-control-frame-hooks can be used to
248 ;; change how and where Ediff Control Panel is displayed, when it is
249 ;; displayed in a separate frame.
250
251 ;; However, be aware that many variables that drive Ediff are local to
252 ;; Ediff Control Panel, which requires special care in writing these hooks.
253 ;; Take a look at ediff-default-suspend-hook and ediff-default-quit-hook to
254 ;; see what's involved.
255
256 ;; The hooks in ediff-prepare-buffer-hooks are executed for each Ediff
257 ;; buffer (A, B, C) right after these buffers are arranged. Ediff runs the
258 ;; hooks in ediff-display-help-hooks each time after setting up the help
259 ;; message. Finally, ediff-mode-hooks are run just after ediff-mode is set
260 ;; up in the control buffer. This is done before any windows or frames are
261 ;; created. One can use it to set local variables that determine the
262 ;; look of the display.
263
264 ;; Quick help:
265 ;; ----------
266 ;;
267 ;; Ediff provides quick help using its control panel window. Since this
268 ;; window takes a fair share of the screen real estate, you can toggle it
269 ;; off by hitting `?'. The control window will then shrink to just one
270 ;; line and a mode line, displaying a short help message. The variable
271 ;;
272 ;; ediff-prefer-long-help-message
273 ;;
274 ;; Tells Ediff whether the user wants the short message initially or the
275 ;; long one. By default, it is set to nil, meaning that the short message
276 ;; will be shown on startup. Set this to t, if you want the long message
277 ;; initially.
278 ;; If you want to change the appearance of the help message on a
279 ;; per-buffer basis, you must use ediff-startup-hooks to change the value
280 ;; of ediff-help-message, which is a variable local to ediff-control-buffer.
281
282 ;; Window and frame configuration:
283 ;; -------------------------------
284
285 ;; In a non-windowing display, Ediff sets things up in one frame, splitting
286 ;; it between a small control window and the windows for file-A, file-B,
287 ;; and file-C. The split between these latter windows can be horizontal or
288 ;; vertical, which can be changed interactively by hitting `|' while the
289 ;; cursor is in the control window.
290 ;;
291 ;; On a window display, Ediff sets up a dedicated frame for Ediff Control
292 ;; Panel and then it would choose windows as follows: If one of the buffers
293 ;; is invisible, it will be displayed in the currently selected frame. If
294 ;; a buffer is visible, it will be displayed in the frame it is visible.
295 ;; If, according to the above criteria, the two buffers fall into the same
296 ;; frame, then be it---the frame will be shared by the two. The same
297 ;; algorithm works when you hit `C-l' (ediff-recenter), `p'
298 ;; (ediff-previous-difference), `n', etc.
98 ;; 299 ;;
99 ;; Thus, you can compare files in one frame or in different frames. 300 ;; Thus, you can compare files in one frame or in different frames.
100 ;; The former is done by default, while the latter can be achieved by 301 ;; The former is done by default, while the latter can be achieved by
101 ;; arranging files A and B to be seen in different frames. Ediff 302 ;; arranging files A, B (and C, if applicable) to be seen in different
102 ;; respects these arrangements, automatically adapting itself to 303 ;; frames. Ediff respects these arrangements, automatically adapting
103 ;; the multi-frame mode. 304 ;; itself to the multi-frame mode.
104 305
105 306 ;; Ediff uses the variables
106 ;; To those who like to go where noone has gone before: 307 ;;
107 308 ;; ediff-control-frame-parameters
108 ;; Ediff lets the user run multiple sessions at once, i.e., you can invoke 309 ;; ediff-control-frame-position-function
109 ;; Ediff on different functions several times in a row, without exiting 310 ;;
110 ;; the previous Ediff sessions. Different sessions may even operate on the 311 ;; to set up its control panels. The user can change or augment
111 ;; same pair of files. So, in principle, it is possible to do, say, 312 ;; ediff-control-frame-parameters including the font, color, etc. The X
112 ;; pairwise comparison of three (or more) different files. Each session 313 ;; resource name of Ediff Control Panel frames is `Ediff'. Under X-windows,
113 ;; would have its own Ediff Control Panel and all the regarding a 314 ;; you can use this name to set up preferences in your ~/.Xdefaults
114 ;; particular session is local to the associated control panel buffer. 315 ;; (~/.xrdb, or whatever is in use). Usually this is preferable to changing
115 ;; You can switch between sessions by suspending one session and then 316 ;; ediff-control-frame-parameters directly. For instance, you can specify
116 ;; switching to another control panel. (Different control panel buffers 317 ;; in ~/.Xdefaults where the control frame is to be sitting on the screen
117 ;; are distinguished by a numerical suffix, e.g., Ediff Control Panel<3>.) 318 ;; using the resource
118 ;; Thus, if you would like to compare three files pairwise, you can do 319 ;;
119 ;; this by preparing three different frames, each with its own control 320 ;; Ediff*geometry
120 ;; window. (This would require a very wide screen, and I never claimed 321 ;;
121 ;; that such 3-way comparison is very easy to do.) 322 ;; In general, any X resource pertaining the control frame can be reached
323 ;; via the prefix `Ediff*'.
324 ;;
325 ;; The prefered way of specifying the position of the control frame is by
326 ;; setting the variable ediff-control-frame-position-function to be a
327 ;; function to be called in order to determine the desired location for the
328 ;; control frame. The default value of this variable is
329 ;; `ediff-make-frame-position'. This function places the control frame in
330 ;; the vicinity of the North-East corner of the frame displaying buffer A.
331 ;; A pair of variables,
332 ;;
333 ;; ediff-narrow-control-frame-leftward-shift
334 ;; ediff-wide-control-frame-rightward-shift
335 ;; ediff-control-frame-upward-shift
336 ;;
337 ;; can be used to adjust the location produced by ediff-make-frame-position.
338 ;; The first variable specifies the number of characters for shifting
339 ;; the control frame from the rightmost edge of frame A when the control
340 ;; frame is displayed as a small window.
341 ;; The second variable specifies the rightward shift of the control frame
342 ;; from the left edge of frame A when the control frame shows the full
343 ;; menu of options.
344 ;; The third variable specifies the number of pixels for the upward shift
345 ;; of the control frame.
346 ;;
347 ;; If you truly and absolutely dislike the way Ediff sets up windows and if
348 ;; you can't customize this via frame parameters, the last resort is to
349 ;; rewrite the function `ediff-setup-windows'. However, we believe that
350 ;; detaching Ediff Control Panel from the rest and making it into a
351 ;; separate frame offers an important opportunity by allowing you to
352 ;; iconify that frame. Under Emacs, the icon will usually accept all of the
353 ;; Ediff commands, but will free up valuable real estate on your screen
354 ;; (this may depend on the window manager, though). Iconifying won't do any
355 ;; good under XEmacs since XEmacs icons do not seem to be sensitive to
356 ;; keyboard input. The saving grace is that, even if not iconified, the
357 ;; control frame is very small, smaller than some icons, so it doesn't take
358 ;; much space in any case.
359 ;;
360 ;; The variable
361 ;;
362 ;; ediff-prefer-iconified-control-frame
363 ;;
364 ;; if t, will cause the control frame to become iconified automatically when
365 ;; the help message is toggled off. This saves valuable real estate on the
366 ;; screen. Toggling help back will deiconify the control frame.
367 ;;
368 ;; To start ediff with an iconified Control Panel, you should set the above
369 ;; to t and ediff-prefer-long-help-message to nil.
370
371 ;; The variable
372 ;;
373 ;; ediff-window-setup-function
374 ;;
375 ;; Controls the way windows are setup. The above multiframe setup is
376 ;; achieved via ediff-setup-windows-multiframe function, which is a default
377 ;; on windowing displays (except for XEmacs 19.10 and earlier, which has a
378 ;; bug that breaks the multiframe display). The plain setup, one where all
379 ;; windows are always in one frame, is done via ediff-setup-windows-plain,
380 ;; which is the default on a non-windowing display (or in an xterm window).
381 ;; In fact, under Emacs, you can switch freely between these two setups by
382 ;; executing the command `ediff-toggle-multiframe'. However, don't try to
383 ;; do it under XEmacs, as it gets thoroughly confused if you switch from
384 ;; multiframe setup to plain setup within the same Ediff session.
385
386 ;; If you don't like either of these setups, write your own function. See
387 ;; the documentation for ediff-window-setup-function for the basic
388 ;; guidelines. However, writing window setups is not easy, so, before
389 ;; embarking on this job, you may want to take a close look at
390 ;; ediff-setup-windows-plain and ediff-setup-windows-multiframe.
391
392 ;; The user can run multiple Ediff sessions at once, by invoking it several
393 ;; times without exiting the previous Ediff sessions. Different sessions
394 ;; may even operate on the same pair of files. So, in principle, it is
395 ;; possible to do, say, pairwise comparison of three (or more) different
396 ;; files. Each session would have its own Ediff Control Panel and all the
397 ;; regarding a particular session is local to the associated control panel
398 ;; buffer. You can switch between sessions by suspending one session and
399 ;; then switching to another control panel. (Different control panel
400 ;; buffers are distinguished by a numerical suffix, e.g., Ediff Control
401 ;; Panel<3>.) Thus, if you would like to compare three files pairwise,
402 ;; you can do this by preparing three different frames, each with its data
403 ;; buffer to be compared. (No, I am not saying that such a 3way
404 ;; comparison is very easy to do.)
122 ;; 405 ;;
123 ;; If you need to conduct multiple Ediff sessions on the same file, one 406 ;; If you need to conduct multiple Ediff sessions on the same file, one
124 ;; thing should be kept in mind: each time you invoke Ediff on a buffer that 407 ;; thing should be kept in mind: each time you invoke Ediff on a buffer that
125 ;; already participates in another Ediff session, that buffer should not 408 ;; already participates in another Ediff session, that buffer should not
126 ;; have any ASCII Ediff flags in it. (Highlighting with faces is OK.) If 409 ;; have any ASCII Ediff flags in it. (Highlighting with faces is OK.) If
127 ;; flags are not removed, difference overlays won't be set correctly 410 ;; flags are not removed, difference overlays won't be set correctly
128 ;; for the second invocation of Ediff. The simplest way to remove ASCII 411 ;; for the second invocation of Ediff. The simplest way to remove ASCII
129 ;; flags from an Ediff buffer is to hit `h' and thus switch to highlighting 412 ;; flags from an Ediff buffer is to hit `h' and thus switch to highlighting
130 ;; with faces (unhighlighting on a dumb terminal). 413 ;; with faces (unhighlighting on a dumb terminal).
131 414
132 ;;; Remote and Compressed Files 415 ;; Remote and Compressed Files
133 ;; --------------------------- 416 ;; ---------------------------
134 417
135 ;; Ediff will work with remote, compressed, and encrypted files. Ediff 418 ;; Ediff will work with remote, compressed, and encrypted files. Ediff
136 ;; supports ange-ftp.el, jka-compr.el, uncompress.el and crypt++.el, but 419 ;; supports ange-ftp.el, jka-compr.el, uncompress.el and crypt++.el, but
137 ;; it may work with other similar packages as well. This 420 ;; it may work with other similar packages as well. This
138 ;; means that you can compare files residing on another machine, or you 421 ;; means that you can compare files residing on another machine, or you
139 ;; can apply a patch to a file on another machine (even the patch itself 422 ;; can apply a patch to a file on another machine (even the patch itself
140 ;; can be a remote file!). 423 ;; can be a remote file!).
141 ;; 424 ;;
142 ;; When patching compressed or remote files, Ediff doesn't rename the 425 ;; When patching compressed or remote files, Ediff doesn't rename the
143 ;; source file into source-file-name.orig (unlike what `patch' would 426 ;; source file into source-file-name_orig (unlike what `patch' would
144 ;; usually do). Instead, the source file retains its name and the result 427 ;; usually do). Instead, the source file retains its name and the result
145 ;; of applying the patch is placed in a temporary file that has the suffix 428 ;; of applying the patch is placed in a temporary file that has the suffix
146 ;; `.patched'. Generally, this applies to files that are handled using 429 ;; `_patched'. Generally, this applies to files that are handled using
147 ;; black magic, such as special file handlers (ange-ftp and some 430 ;; black magic, such as special file handlers (ange-ftp and some
148 ;; compression and encryption packages all use this method). 431 ;; compression and encryption packages all use this method).
149 ;; 432 ;;
150 ;; Regular files are treated by `patch' in the usual manner, i.e., the 433 ;; Regular files are treated by `patch' in the usual manner, i.e., the
151 ;; original is renamed into source-name.orig and the result of the patch 434 ;; original is renamed into source-name_orig and the result of the patch
152 ;; is placed into the file source-name. 435 ;; is placed into the file source-name. (Ediff uses `_orig' instead of
153 436 ;; the usual `.orig' for compatibility with systems like VMS.)
154 437
155 ;;; Remarks:
156 ;; -------
157
158 ;; 1. Ediff is heavily dependent on the new features of Emacs 19.
159 ;; It won't run under Emacs 18 at all.
160 ;; 2. If running Lucid Emacs, Ediff requires at least version 19.9.
161 ;; 3. The function ediff-revision requires the version of vc.el that comes
162 ;; with Emacs 19.22 and later, or rcs.el version 1.67 or later.
163
164
165 ;;; Installation and use:
166 ;; --------------------
167
168 ;; You can invoke Ediff interactively using the following functions:
169 ;;
170 ;; ediff-buffers - compare buffers
171 ;; ediff - alias for ediff-files)
172 ;; ediff-files - compare files
173 ;; ediff-patch-file - patch file then compare
174 ;; epatch - alias for ediff-patch-file
175 ;; ediff-patch-buffer - patch buffer then compare
176 ;; epatch-buffer - alias for ediff-patch-buffer
177 ;; ediff-revision - compare buffer & version
178 ;;
179 ;;
180 ;; To use Ediff, put this in your .emacs file:
181 ;;
182 ;; (autoload 'ediff-buffers "ediff" "Visual interface to diff" t)
183 ;; (autoload 'ediff "ediff" "Visual interface to diff" t)
184 ;; (autoload 'ediff-files "ediff" "Visual interface to diff" t)
185 ;; (autoload 'epatch "ediff" "Visual interface to patch" t)
186 ;; (autoload 'ediff-patch-file "ediff" "Visual interface to patch" t)
187 ;; (autoload 'ediff-patch-buffer "ediff" "Visual interface to patch" t)
188 ;; (autoload 'epatch-buffer "ediff" "Visual interface to patch" t)
189 ;; (autoload 'ediff-revision "ediff"
190 ;; "Interface to diff & version control" t)
191 ;;
192 ;;
193 ;; If you want Ediff to be loaded from the very beginning, you should have
194 ;;
195 ;; (require 'ediff)
196 ;;
197 ;; in your .emacs file. This way it is also easier to figure out changes
198 ;; to the default Ediff setting, if such changes become necessary --- see
199 ;; Customization.
200 ;;
201
202 ;;; Compilation
203 ;; -----------
204 ;;
205 ;; When you byte-compile Ediff, you will get some warnings about functions
206 ;; being undefined. These can be safely ignored.
207 ;;
208 ;; Important:
209 ;; =========
210 ;;
211 ;; If you are using advice.el (directly or indirectly, via one of the
212 ;; other packages), Ediff may not compile properly. In this case, you
213 ;; should do:
214 ;;
215 ;; M-x ad-deactivate-all RET
216 ;;
217 ;; M-x byte-compile-file RET ediff.el RET
218 ;;
219 ;; M-x ad-activate-all RET
220 ;;
221 ;; This precaution will not be needed starting with GNU Emacs 19.23 and
222 ;; Lucid Emacs 19.10, due to fixing a bug in advice.el.
223
224 ;;; Customization:
225 ;; -------------
226
227 ;; Hooks:
228 ;; -----
229 ;; If you don't like the default setting, you can change it through the
230 ;; various variables and hooks. In particular, the following hooks are
231 ;; available:
232
233 ;; ediff-load-hooks
234 ;; ediff-before-setup-windows-hooks
235 ;; ediff-startup-hooks
236 ;; ediff-select-hooks
237 ;; ediff-unselect-hooks
238 ;; ediff-suspend-hooks
239 ;; ediff-quit-hooks
240 ;; ediff-prepare-buffer-hooks
241
242 ;; The hooks in ediff-load-hooks can be used to change defaults after Ediff
243 ;; is loaded.
244 ;; The hooks in ediff-before-setup-windows-hooks, ediff-suspend-hooks, and
245 ;; ediff-quit-hooks can be used to save and then restore whatever window
246 ;; configuration you want. However, make sure you understand what you are
247 ;; doing. Many variables that drive Ediff are local to the different
248 ;; Ediff Control Panel buffers. Take a look at ediff-default-suspend-hook and
249 ;; ediff-default-quit-hook to see what's involved.
250 ;; The hooks in ediff-prepare-buffer-hooks are executed for each Ediff buffer
251 ;; (A and B) right after these buffers are arranged.
252 ;;
253 ;; 438 ;;
254 ;; Selective browsing: Control over stepping through difference regions 439 ;; Selective browsing: Control over stepping through difference regions
255 ;; ----------------------------------------------- 440 ;; --------------------------------------------------------------------
256 ;; 441 ;;
257 ;; Sometimes it is convenient to be able to step through only some 442 ;; Sometimes it is convenient to be able to step through only some
258 ;; difference regions, those that satisfy certain conditions and to ignore 443 ;; difference regions, those that satisfy certain conditions and to ignore
259 ;; all others. The commands `#f' and `#h' let the user specify regular 444 ;; all others. The commands `#f' and `#h' let the user specify regular
260 ;; expressions to control the way Ediff skips to the next or previous 445 ;; expressions to control the way Ediff skips to the next or previous
261 ;; difference. Typing `#f' lets one specify a pair of regular expressions, 446 ;; difference. Typing `#f' lets one specify of regular expressions,
262 ;; regexp-A and regexp-B. 447 ;; regexp-A, regexp-B, and regexp-C.
263 ;; Ediff will then start stepping only through those difference regions where 448 ;; Ediff will then start stepping only through those difference regions where
264 ;; the region in buffer A matches regexp-A and the region in buffer B 449 ;; the region in buffer A matches regexp-A and/or the region in buffer B
265 ;; matches regexp-B. 450 ;; matches regexp-B, etc. Whether `and' or `or' should be used depends on
451 ;; how the user responds to a prompt.
266 ;; Similarly, using `#h', one specifies expressions that match difference 452 ;; Similarly, using `#h', one specifies expressions that match difference
267 ;; regions to be ignored while stepping through the differences. That is, if 453 ;; regions to be ignored while stepping through the differences. That is, if
268 ;; the buf A part matches regexp-A and the buf B part matches regexp B then 454 ;; the buffer A part matches regexp-A, the buffer B part matches regexp B
269 ;; the region will be ignored by ediff-next-difference and 455 ;; and (if applicable) buffer-C part matches regexp-C, then the region will
270 ;; ediff-previous-difference commands. 456 ;; be ignored by ediff-next-difference and ediff-previous-difference commands.
271 ;; 457 ;;
272 ;; Hitting `#f' and `#h' toggles this feature on/off. 458 ;; Hitting `#f' and `#h' toggles this feature on/off.
273 ;; 459 ;;
274 ;; Note that selective browsing affects only ediff-next-difference and 460 ;; Note that selective browsing affects only ediff-next-difference and
275 ;; ediff-previous-difference, i.e., the commands invoked by typing n/SPC 461 ;; ediff-previous-difference, i.e., the commands invoked by typing n/SPC
276 ;; and p/DEL. You can still jump directly (using `j' or `ga/gb') to any 462 ;; and p/DEL. You can still jump directly (using `j' or `ga/gb/gc') to any
277 ;; numbered difference. Also, it should be understood, that #f and #h do 463 ;; numbered difference. Also, it should be understood, that #f and #h do
278 ;; not change the position of the point in the buffers. The effect of these 464 ;; not change the position of the point in the buffers. The effect of these
279 ;; commands is seen only when the user types `n' or `p', i.e., when 465 ;; commands is seen only when the user types `n' or `p', i.e., when
280 ;; Ediff is told to jump to the next or previous difference. 466 ;; Ediff is told to jump to the next or previous difference.
281 ;; 467 ;;
320 ;; Highlighting difference regions 506 ;; Highlighting difference regions
321 ;; ------------------------------- 507 ;; -------------------------------
322 ;; The second group of Ediff variables that could be changed, if you so 508 ;; The second group of Ediff variables that could be changed, if you so
323 ;; wish, is: 509 ;; wish, is:
324 ;; 510 ;;
325 ;; ediff-before-flag-eol 511 ;; ediff-before-flag-bol
326 ;; ediff-after-flag-eol 512 ;; ediff-after-flag-eol
327 ;; ediff-before-flag-mol 513 ;; ediff-before-flag-mol
328 ;; ediff-after-flag-mol 514 ;; ediff-after-flag-mol
329 ;; 515 ;;
330 ;; ediff-current-diff-face-A 516 ;; ediff-current-diff-face-A
331 ;; ediff-current-diff-face-B 517 ;; ediff-current-diff-face-B
518 ;; ediff-current-diff-face-C
332 ;; ediff-fine-diff-face-A 519 ;; ediff-fine-diff-face-A
333 ;; ediff-fine-diff-face-B 520 ;; ediff-fine-diff-face-B
521 ;; ediff-fine-diff-face-C
334 ;; ediff-even-diff-face-A 522 ;; ediff-even-diff-face-A
335 ;; ediff-even-diff-face-B 523 ;; ediff-even-diff-face-B
524 ;; ediff-even-diff-face-C
336 ;; ediff-odd-diff-face-A 525 ;; ediff-odd-diff-face-A
337 ;; ediff-odd-diff-face-B 526 ;; ediff-odd-diff-face-B
527 ;; ediff-odd-diff-face-C
338 ; 528 ;
339 ;; The first four are ASCII strings that mark the beginning and the end of 529 ;; The first four are ASCII strings that mark the beginning and the end of
340 ;; the differences found in file-A and file-B. Ediff uses different flags 530 ;; the differences found in files A, B, and C. Ediff uses different flags
341 ;; to highlight regions that begin/end at the beginning of a line or in a 531 ;; to highlight regions that begin/end at the beginning of a line or in a
342 ;; middle of a line. 532 ;; middle of a line.
343 533
344 ;; The rest are the faces used to highlight text on X displays. On X 534 ;; The rest are the faces used to highlight text on X displays. On X
345 ;; displays, Ediff uses ediff-current-diff-face-A and 535 ;; displays, Ediff uses ediff-current-diff-face-A/B/C to highlight the
346 ;; ediff-current-diff-face-B to highlight the current difference regions. 536 ;; current difference region.
347 ;; The faces ediff-fine-diff-face-A and ediff-fine-diff-face-B 537 ;;
538 ;; The faces ediff-fine-diff-face-A/B/C
348 ;; are used to show the fine differences between the current differences 539 ;; are used to show the fine differences between the current differences
349 ;; regions in buffer A and B. 540 ;; regions in buffers A, B, and C, respectively.
350 ;; Other (non-current) difference regions are displayed in alternating 541 ;;
351 ;; faces: ediff-even/odd-diff-face-A/B. The odd and the even 542 ;; Non-current difference regions are displayed in alternating
543 ;; faces: ediff-even/odd-diff-face-A/B/C. The odd and the even
352 ;; faces are actually identical on monochrome displays, because it is 544 ;; faces are actually identical on monochrome displays, because it is
353 ;; rather poor in what you can do on such a display. So, I chose to use 545 ;; rather poor in what you can do on such a display. So, I chose to use
354 ;; italics to highlight other differences. Any ideas would be welcome. 546 ;; italics to highlight other differences. Any ideas would be welcome.
355 ;; There are two ways to change the default setting for highlighting faces: 547 ;; There are two ways to change the default setting for highlighting faces:
356 ;; either change the variables, as in 548 ;; either change the variables, as in
372 ;; 564 ;;
373 ;; You may also want to take a look at how the above faces are defined in 565 ;; You may also want to take a look at how the above faces are defined in
374 ;; Ediff. 566 ;; Ediff.
375 ;; 567 ;;
376 ;; Note: it is not recommended to use `internal-get-face' (or `get-face' in 568 ;; Note: it is not recommended to use `internal-get-face' (or `get-face' in
377 ;; Lucid) when defining faces for Ediff, since this may cause 569 ;; XEmacs) when defining faces for Ediff, since this may cause
378 ;; problems when there are several frames with different font sizes. 570 ;; problems when there are several frames with different font sizes.
379 ;; Instead, use copy-face or set/make-face-* as shown above. 571 ;; Instead, use copy-face or set/make-face-* as shown above.
380 ;; 572 ;;
381 ;; The last group of variables in this group, 573 ;; The last variable in this group,
382 ;; 574 ;;
383 ;; ediff-want-faces
384 ;; ediff-highlight-all-diffs 575 ;; ediff-highlight-all-diffs
385 ;; ediff-want-default-menus 576 ;;
386 ;; 577 ;; indicates whether---on a window system---the user wants differences to be
387 ;; indicate whether---on a window system---you want differences to be
388 ;; marked using ASCII strings (like on a dumb terminal) or using colors and 578 ;; marked using ASCII strings (like on a dumb terminal) or using colors and
389 ;; highlighting. If ediff-want-faces is t, then highlighting with faces is 579 ;; highlighting. Normally, Ediff highlights all differences, but the selected
390 ;; used. Normally, Ediff highlights all differences, but the selected 580 ;; difference is highlighted more visibly. One can cycle through various
391 ;; difference is highlighted more visibly. You can cycle through various
392 ;; modes of highlighting by hitting `h'. By default, Ediff starts in the 581 ;; modes of highlighting by hitting `h'. By default, Ediff starts in the
393 ;; mode where all difference regions are highlighted. If you prefer to 582 ;; mode where all difference regions are highlighted. If you prefer to
394 ;; start in the mode where unselected differences are not highlighted, you 583 ;; start in the mode where unselected differences are not highlighted, you
395 ;; should set ediff-highlight-all-diffs to nil. 584 ;; should set ediff-highlight-all-diffs to nil.
396 ;; You will still be able to turn on highlighting of all differences by 585 ;; You will still be able to turn on highlighting of all differences by
397 ;; hitting `h'. 586 ;; hitting `h'.
398 ;; The variable `ediff-want-default-menus', if true, will cause Ediff to 587 ;;
399 ;; set up a pair of menues in the menu bar, so you can invoke it from there. 588 ;; If you want to change the above variables, they must be set
400 ;; If you don't like the look of the default menus, set this variable to 589 ;; BEFORE Ediff is loaded.
401 ;; nil and design your own menus.
402 ;;
403 ;; If you plan on changing these variables, they must be set
404 ;; BEFORE ediff.el is loaded.
405 ;; 590 ;;
406 ;; Note: Ediff lets you switch between the two types of highlighting. That 591 ;; Note: Ediff lets you switch between the two types of highlighting. That
407 ;; is you can switch, interactively, from highlighting using faces to 592 ;; is you can switch, interactively, from highlighting using faces to
408 ;; highlighting using ASCII flags, and back. Of course, toggling has 593 ;; highlighting using ASCII flags, and back. Of course, toggling has
409 ;; effect only on a window system. On a dumb terminal or in an xterm 594 ;; effect only on a window system. On a dumb terminal or in an xterm
410 ;; window, the only available option is highlighting with ASCII flags. 595 ;; window, the only available option is highlighting with ASCII flags.
411 ;; 596 ;;
412 ;; Refining difference regions 597 ;; Selective display
413 ;; --------------------------- 598 ;; -----------------
599 ;; If buffers being compared are narrowed at the time of invocation of Ediff,
600 ;; ediff-buffers will preserve the narrowing range. However, if ediff-files
601 ;; is invoked on the files visited by these buffers, narrowing will be
602 ;; turned off, since we assume that the user wants to compare the entire files.
603 ;;
604 ;; Invocation of ediff-small/large-regions and ediff-windows will cause
605 ;; Ediff to set new narrowing ranges. However, the old ranges are preserved
606 ;; and will be returned to after quitting or by hitting `%'.
607 ;;
608 ;; Two variables control the behavior of ediff-windows,
609 ;; ediff-small-regions, and ediff-large-regions with respect to narrowing:
610 ;;
611 ;; ediff-start-narrowed
612 ;; ediff-quit-widened
613 ;;
614 ;; If ediff-start-narrowed is t, then Ediff will narrow display to the
615 ;; appropriate range if it is invoked as ediff-windows or
616 ;; ediff-small/large-regions.
617 ;; If it is nil, then narrowing will not take place. However, the user can
618 ;; still toggle narrowing on and off by typing `%'.
619 ;; Similarly, ediff-quit-widened controls whether Ediff should restore
620 ;; the visibility range that existed before the current invocation.
621 ;;
622 ;;
623 ;; Refinement of difference regions
624 ;; --------------------------------
414 ;; Ediff has variables that control the way fine differences are 625 ;; Ediff has variables that control the way fine differences are
415 ;; highlighted. This feature lets the user highlight the exact words that 626 ;; highlighted. This feature lets the user highlight the exact words that
416 ;; make the difference regions in buffer A and B different. This process 627 ;; make the difference regions in comparison buffers different. This process
417 ;; ignores spaces, tabs, and newlines. 628 ;; ignores spaces, tabs, and newlines.
418 ;; 629 ;;
419 ;; ediff-auto-refine 630 ;; ediff-auto-refine
420 ;; ediff-auto-refine-limit 631 ;; ediff-auto-refine-limit
421 ;; 632 ;;
422 ;; By default, `ediff-auto-refine' is `'on', which means that fine differences 633 ;; By default, `ediff-auto-refine' is `on', which means that fine differences
423 ;; within regions will be highlighted automatically. On a slow system, this 634 ;; within regions will be highlighted automatically. On a slow system, this
424 ;; feature may be undesirable. In any case, the user can always toggle 635 ;; feature may be undesirable. In any case, the user can always toggle
425 ;; auto-refining on/off/nix by hitting `@'. When auto-refining is off, fine 636 ;; auto-refining on/off/nix by hitting `@'. When auto-refining is off, fine
426 ;; differences will be shown only for regions for which these differences 637 ;; differences will be shown only for regions for which these differences
427 ;; have been computed and saved before. If auto-refining is nixed, fine 638 ;; have been computed and saved before. If auto-refining is nixed, fine
429 ;; display fine differences for the current difference region regardless of 640 ;; display fine differences for the current difference region regardless of
430 ;; whether auto-refining is on, off, or nixed. 641 ;; whether auto-refining is on, off, or nixed.
431 ;; If auto-refining is on, the variable `ediff-auto-refine-limit' limits 642 ;; If auto-refining is on, the variable `ediff-auto-refine-limit' limits
432 ;; the size of the regions to be auto-refined. This variable guards against 643 ;; the size of the regions to be auto-refined. This variable guards against
433 ;; possible slow-down that may be caused by an extraordinary large 644 ;; possible slow-down that may be caused by an extraordinary large
434 ;; difference region. However, the user can always force refining by 645 ;; difference region.
435 ;; hitting `*'. 646 ;;
436 ;; 647 ;; However, the user can always force region refining by typing `*'.
437 ;; ediff-fine-diff-program 648 ;;
438 ;; ediff-fine-diff-options 649 ;; Sometimes, when a difference region has too many differences between the
650 ;; variants, highlighting of fine differences stands in the way, especially
651 ;; on color displays. If that is the case, the user can invoke `*' with a
652 ;; negative prefix argument, which would unhighlight fine diffs for the
653 ;; current region.
654 ;;
655 ;; To unhighlight fine differences in all diff regions, use the command
656 ;; `@'. Repeated typing of this key cycles through three different states:
657 ;; auto-refining, no-auto-refining, and unhighlighting of all fine
658 ;; differences.
659 ;;
660 ;; The variable
661 ;;
439 ;; ediff-forward-word-function 662 ;; ediff-forward-word-function
440 ;; 663 ;;
441 ;; These variables let the user control how fine differences are computed. 664 ;; allows the user to control how fine differences are computed.
442 ;; `ediff-fine-diff-program' is diff, by default. However, you can use 665 ;; The value must be a lisp function that determines how the
443 ;; any function as long as it produces output consistent with diff. 666 ;; current difference region should be split into words.
444 ;; `ediff-forward-word-function' is a lisp function that determines how the 667 ;;
445 ;; current difference region is split into words. (Fine diferences are 668 ;; Fine diferences are computed by first splitting the current difference
446 ;; computed by first splitting the current difference region into words and 669 ;; region into words and then passing this along to
447 ;; then passing this along to `ediff-fine-diff-program'. For the default 670 ;; `ediff-diff-program'. For the default ediff-forward-word-function,
448 ;; wordify function, `ediff-forward-word', a word is a string consisting of 671 ;; `ediff-forward-word', a word is a string consisting of letters, `-', or
449 ;; letters, `-', or `_', or a string consisting of symbols that are neither 672 ;; `_', a string of punctuation symbols, a string of digits, or a string
450 ;; space, nor a letter.) 673 ;; consisting of symbols that are neither space, nor a letter.
451 ;; 674 ;;
452 ;; Patch and diff programs 675 ;; Patch and diff programs
453 ;; ----------------------- 676 ;; -----------------------
454 ;; The next group of variables determines the programs to be used for 677 ;; The next group of variables determines the programs to be used for
455 ;; applying patches and for computing the main difference regions (not the 678 ;; applying patches and for computing the main difference regions (not the
457 ;; 680 ;;
458 ;; ediff-patch-program 681 ;; ediff-patch-program
459 ;; ediff-patch-options 682 ;; ediff-patch-options
460 ;; ediff-diff-program 683 ;; ediff-diff-program
461 ;; ediff-diff-options 684 ;; ediff-diff-options
685 ;; ediff-diff3-program
686 ;; ediff-diff3-options
687 ;;
688 ;; Warning about VMS: The output from VMS DIFF is not yet supported.
689 ;; Instead, make sure some implementation of Unix diff on VMS is used.
462 ;; 690 ;;
463 ;; These specify the functions that produce differences and do patching. 691 ;; These specify the functions that produce differences and do patching.
464 ;; The *-options variables specify which options to pass to these programs. 692 ;; The *-options variables specify which options to pass to these programs.
465 ;; It is unlikely that you would want to change these. One possible 693 ;; It is unlikely that you would want to change these.
466 ;; exception is when you may want to generate differences with context 694 ;; However, sometimes you may want to tell diff to ignore spaces and
467 ;; lines in order to send a patch file through email. Then, you might want 695 ;; such. Use the option '-w' for that.
468 ;; to set ediff-diff-options to '-c'. Sometimes, you may also want to tell 696 ;; Diff has several other useful options (type 'man diff' to find out).
469 ;; diff to ignore spaces and such. Use the option '-w' for that. Diff 697 ;;
470 ;; has several other useful options (type 'man diff' to find out). 698 ;; However, Ediff doesn't let you use the option '-c', as it doesn't
471 ;; 699 ;; recognize this format yet. However, if you need to save the output from
472 ;; The output from diff is found in *ediff-diff* buffer, which you can save. 700 ;; diff in a special form, Ediff lets you specify ``custom'' diff format
473 ;; However, using Ediff for producing a diff output makes sense only if you 701 ;; using the following two variables:
474 ;; also intend to use Ediff to browse through the diff'ed files before 702 ;;
475 ;; sending the patch. This is because diff.el, which also comes with 703 ;; ediff-custom-diff-program
476 ;; Emacs, is much faster in yielding the output of diff (Ediff is a big 704 ;; ediff-custom-diff-options
477 ;; gun, if used for this simple purpose). 705 ;;
706 ;; The output generated by ediff-custom-diff-program (which doesn't even
707 ;; have to be a Unix-style diff!) is not used by Ediff, except that you can
708 ;; save if using ediff-save-buffer function (normally bound to `wd' key
709 ;; sequence).
710 ;; However, Ediff is not the preferred way of producing diff output in
711 ;; Emacs, unless you also intend to use Ediff to browse through the diff'ed
712 ;; files. This is because diff.el (M-x diff), which also comes with Emacs,
713 ;; is much faster in yielding the output of diff, while Ediff consumes many
714 ;; resources.
715
716 ;; Support for diff3 and merging
717 ;; -----------------------------
718
719 ;; Ediff supports 3way comparison via the functions `ediff-files3' and
720 ;; `ediff-buffers3'. The interface is the same as for 2-way comparison.
721 ;; In 3-way comparison and merging, Ediff indicates if any two difference
722 ;; regions are identical. For instance, if the current region in buffer A
723 ;; is the same as the region in buffer C, then the mode line of buffer A will
724 ;; display [=diff(C)] and the mode line of buffer C will display [=diff(A)].
725 ;;
726 ;; Merging is done according to the following algorithm.
727 ;;
728 ;; If a diff region in one of the buffers, say B, differs from the ancestor
729 ;; while the region in the other buffer, A, doesn't, then the merge buffer,
730 ;; C, gets the B's region. Similarly when buffer A's region differs from
731 ;; the ancestor and B's doesn't.
732 ;;
733 ;; If both regions, A and B, differ from the ancestor, then Ediff chooses
734 ;; according to the value of
735 ;;
736 ;; ediff-default-variant
737 ;;
738 ;; If the value is `default-A' then A's region is chosen. If it is
739 ;; `default-B' then B's region is chosen. If the value of the above
740 ;; variable is `combined' then the region in buffer C will look like this:
741 ;;
742 ;; #ifdef NEW /* variant A */
743 ;; diff region from buffer A
744 ;; #else /* variant B */
745 ;; diff region from buffer B
746 ;; #endif /* NEW */
747 ;;
748 ;; The actual strings that separate the regions copied from bufer A and B
749 ;; are controled by the variable
750 ;;
751 ;; ediff-combination-pattern
752 ;;
753 ;; which must be a list of three strings.
754 ;;
755 ;; In addition to the state of the difference, during merging Ediff
756 ;; displays the state of the merge for each region. If a difference came
757 ;; from buffer A by default (because both regions A and B were different
758 ;; from the ancestor and ediff-default-variant was set to `default-A')
759 ;; then [=diff(A) default-A] is displayed in the mode line. If the
760 ;; difference in buffer C came, say, from buffer B because the diff region
761 ;; in that buffer differs from the ancestor, but the region in buffer A
762 ;; doesn't (if merging with an ancestor) then [=diff(B) prefer-B] is
763 ;; displayed. The indicators default-A/B and prefer-A/B are inspired by
764 ;; emerge.el and have the same meaning.
765 ;;
766 ;; Another indicator of the state of merge is `combined'. It appears
767 ;; with any difference region in buffer C that was obtained by combining
768 ;; the difference regions in buffers A and B as explained above.
769 ;;
770 ;; Note that the state-of-difference indicators `=diff(A)' and `=diff(B)'
771 ;; above are not redundant, even in the present of a state-of-merge
772 ;; indicator, as the two serve different purposes. For instance, if the
773 ;; mode line displays [=diff(B) prefer(B)] and you copy a diff region from
774 ;; buffer A to buffer C then `=diff(B)' will change to `diff-A' and the
775 ;; mode line will display [=diff(A) prefer-B].
776 ;; This indicates that the difference region in buffer C is identical to
777 ;; that in buffer A, but originally buffer C's region came from buffer B.
778 ;; This is useful to know because the original diff region in buffer C can
779 ;; be recovered by typing `r'.
780 ;;
781 ;; Ediff never changes the state-of-merge indicator, except as a result of
782 ;; the `!' command (see below), in which case the indicator is lost.
783 ;; On the other hand, the state-of-difference indicator is changed
784 ;; automatically by the copying/recovery commands, `a', `b', `r', `+'.
785 ;;
786 ;; If Ediff is asked to recompute differences via the command `!', the
787 ;; information about origins of the regions in the merge buffer (default-A,
788 ;; prefer-B, or combined) will be lost. This is because recomputing
789 ;; differences in this case means running diff3 on buffers A, B, and the
790 ;; merge buffer, not on the ancestor buffer. (It makes no sense to
791 ;; recompute differences with the ancestor, since Ediff assumes that the user
792 ;; doesn't edit buffers A and B, but he may have edited buffer C, and these
793 ;; changes are to be preserved.) Since some difference regions
794 ;; may disappear as a result of editing in buffer C and others may arise,
795 ;; there is generally no simple way to tell where the various regions
796 ;; in the merge buffer came from.
797 ;;
798 ;; In 3-way comparison, Ediff tries to disregard regions consisting of
799 ;; white space only as much as possible. For instance, if, say, the current
800 ;; region in buffer A consists of the white space only (or if it is empty),
801 ;; Ediff will not take it into account for the purpose of computing fine
802 ;; differences. The result is that Ediff can provide more visual
803 ;; information regarding the actual fine differences in the non-white
804 ;; regions B and C. Moreover, if the regions in buffers B and C differ in
805 ;; the white space only, then a message to this effect will be displayed.
806 ;;
807 ;; In merging, the variable
808 ;;
809 ;; ediff-merge-window-share
810 ;;
811 ;; controls the split between window C (the window for the merge-buffer)
812 ;; and the windows for buffers A and B. The default is 0.5. To make the
813 ;; merge-buffer window smaller, reduce this amount. It is not recommended
814 ;; to increase the size of the merge-window to more than half the frame
815 ;; (i.e., to increase the default value of ediff-merge-window-share),
816 ;; since it is then hard to see the contents of buffers A and B.
817 ;;
818 ;; The user can temporarily shrink the merge window to just one line by
819 ;; typing `s'. This change is temporary, until Ediff finds a reason to
820 ;; redraw the screen. Typing `s' again will restore the original window size.
821 ;;
822 ;; With a positive prefix argument, this command will make the merge window
823 ;; slightly taller. This change will hold throughout the current Ediff
824 ;; session. With `-' or a negative prefix argument, the command `s' makes
825 ;; the merge window slightly shorter. This change also holds through the
826 ;; entire current Ediff session.
827 ;;
828 ;; Ediff lets the user automatically skip regions where one of the buffer's
829 ;; regions is prefered because it disagrees with the ancestor, while the
830 ;; other buffer agrees with the ancestor. In this case, Ediff displays only
831 ;; the difference regions where the changes made to the original clash with
832 ;; each other. The variable that controls this behavior is
833 ;;
834 ;; ediff-show-clashes-only
835 ;;
836 ;; The value of this variable can be toggled interactively, by typing `$'.
837 ;; Note that this variable controls only how Ediff chooses the
838 ;; next/previous difference to show. The user can still jump directly to
839 ;; any difference using the command `j' (with prefix argument specifying
840 ;; the difference number).
841
842 ;; Version control support
843 ;; -----------------------
844 ;; Ediff supports version control via vc.el (in the standard
845 ;; distribution of Emacs 19) and rcs.el. The latter is a package written by
846 ;; Sebastian Kremer <sk@thp.Uni-Koeln.DE>, which is available in
847 ;;
848 ;; ftp.cs.buffalo.edu:pub/Emacs/rcs.tar.Z
849 ;; ftp.uni-koeln.de:/pub/gnu/emacs/rcs.tar.Z
850 ;;
851 ;; To specify which version control package you are using, set the variable
852 ;; ediff-version-control-package, e.g.,
853 ;; (setq ediff-version-control-package 'rcs)
854 ;; The default, is `vc'.
855 ;; Note: both packages provide access to RCS, but only vc.el comes standard
856 ;; with Emacs and XEmacs.
857 ;; For files under revision control, one key (usually `=') is bound to the
858 ;; function ediff-revision, which runs Ediff on the current buffer and one
859 ;; of its versions. Use the variable
860 ;;
861 ;; ediff-revision-key
862 ;;
863 ;; if you want to change this binding, e.g., (setq ediff-revision-key "\C-cD")
864
478 ;; 865 ;;
479 ;; Mode line 866 ;; Mode line
480 ;; --------- 867 ;; ---------
481 ;; 868 ;;
482 ;; When Ediff is running, the mode line of Ediff Control Panel buffer 869 ;; When Ediff is running, the mode line of Ediff Control Panel buffer
491 ;; If you don't like the way Ediff identifies its buffers, there is always 878 ;; If you don't like the way Ediff identifies its buffers, there is always
492 ;; ediff-prepare-buffer-hooks, which can be used to modify the mode line. 879 ;; ediff-prepare-buffer-hooks, which can be used to modify the mode line.
493 ;; 880 ;;
494 ;; Miscellaneous 881 ;; Miscellaneous
495 ;; ------------- 882 ;; -------------
496 ;; The last set of variables that can be modified is 883 ;; The last batch of variables that can be modified is
497 ;; 884 ;;
498 ;; ediff-split-window-function 885 ;; ediff-split-window-function
886 ;; ediff-merge-split-window-function
887 ;; ediff-make-wide-display-function
499 ;; ediff-use-last-dir 888 ;; ediff-use-last-dir
500 ;; ediff-no-help-in-control-buffer 889 ;; ediff-no-emacs-help-in-control-buffer
501 ;; ediff-toggle-read-only-function 890 ;; ediff-toggle-read-only-function
502 ;; 891
503 ;; ediff-split-window-function controls the way you want the window be 892 ;; ediff-split-window-function controls the way you want the window be
504 ;; split between file-A and file-B. It defaults to vertical split, but you 893 ;; split between file-A and file-B (and file-C, if applicable). It
505 ;; can set it to 'split-window-horizontally, if you want. Ediff lets you 894 ;; defaults to vertical split, but you can set it to
506 ;; toggle the way windows are split, so you can try different settings 895 ;; split-window-horizontally, if you want.
507 ;; interactively. Note: if file-A and file-B are in different frames, 896 ;; The variable ediff-merge-split-window-function controls how windows are
508 ;; windows are not split, regardless of the value 897 ;; split between buffers A and B in merging jobs.
898
899 ;; Ediff lets you toggle the way
900 ;; windows are split, so you can try different settings interactively.
901 ;; Note: if file-A and file-B (and file-C, if applicable) are in different
902 ;; frames, windows are not split, regardless of the value
509 ;; ediff-split-window-function. Instead, other windows on these frames are 903 ;; ediff-split-window-function. Instead, other windows on these frames are
510 ;; deleted and Ediff starts displaying file-A and file-B using these two 904 ;; deleted and Ediff starts displaying file-A/B/C using these
511 ;; frames, one file per frame. You can then switch to one-frame mode 905 ;; frames, one file per frame. You can then switch to one-frame mode
512 ;; simply by hiding the file-A/B buffer that is displayed on a frame other 906 ;; simply by hiding one of the buffers A/B/C.
513 ;; than the control-window frame. 907 ;;
514 ;; 908 ;; Note that if Ediff detects that the two buffers it compares are residing in
515 ;; Note that if Ediff sees that the two buffers it compares are residing in
516 ;; separate frames, it assumes that the user wants them to be so displayed 909 ;; separate frames, it assumes that the user wants them to be so displayed
517 ;; and stops splitting windows. Instead, it will arrange each buffer to 910 ;; and stops splitting windows. Instead, it will arrange each buffer to
518 ;; occupy its own frame (possibly shared with Ediff's help window). 911 ;; occupy its own frame (possibly shared with Ediff's help window).
912 ;;
913 ;; The user can swap the windows in which buffers are displayed by typing `~'.
914 ;; Furthermore, the user can toggle wide/regular display by typing
915 ;; `m'. This is particularly useful when files are compared side-by-side.
916 ;; By default, the display is widened without changing its height. However,
917 ;; the user can set the variable
918 ;;
919 ;; ediff-make-wide-display-function
920 ;;
921 ;; to contain the name of a function to be called to widen the frame in
922 ;; which to display the buffers. See the documentation string for
923 ;; `ediff-make-wide-display-function' for details. It is also recommended
924 ;; to look into how the default function, `ediff-make-wide-display' is
925 ;; written.
926 ;;
519 ;; 927 ;;
520 ;; The variable ediff-use-last-dir controls the way Ediff presents the 928 ;; The variable ediff-use-last-dir controls the way Ediff presents the
521 ;; default directory when it prompts the user for files to compare. If nil, 929 ;; default directory when it prompts the user for files to compare. If nil,
522 ;; Ediff will use the default directory of the current buffer when it 930 ;; Ediff will use the default directory of the current buffer when it
523 ;; prompts the user for file names. Otherwise, it will use the 931 ;; prompts the user for file names. Otherwise, it will use the
524 ;; directories it had previously used for file-A and file-B. 932 ;; directories it had previously used for file-A/B/C.
525 ;; 933 ;;
526 ;; The variable ediff-no-help-in-control-buffer, if set to t, makes C-h 934 ;; The variable ediff-no-emacs-help-in-control-buffer, if set to t, makes C-h
527 ;; behave like the DEL key, i.e., it will move you back to the previous 935 ;; behave like the DEL key, i.e., it will move you back to the previous
528 ;; difference rather than invoking help. This is useful when, in an xterm 936 ;; difference rather than invoking help. This is useful when, in an xterm
529 ;; window or on a dumb terminal, the Backspace key is bound to C-h and is 937 ;; window or on a dumb terminal, the Backspace key is bound to C-h and is
530 ;; positioned more conveniently than the DEL key. 938 ;; positioned more conveniently than the DEL key.
531 ;; 939 ;;
541 ;; All Ediff commands are displayed in a help window, unless you hit '?' to 949 ;; All Ediff commands are displayed in a help window, unless you hit '?' to
542 ;; shrink it to just one line. You can redisplay the help window by hitting 950 ;; shrink it to just one line. You can redisplay the help window by hitting
543 ;; '?' again. 951 ;; '?' again.
544 ;; 952 ;;
545 ;; Many Ediff commands take numeric prefix arguments. For instance, if you 953 ;; Many Ediff commands take numeric prefix arguments. For instance, if you
546 ;; hit a number, N, and then 'j' (ediff-jump-to-difference), Ediff will 954 ;; hit a number, N, and then `j' (ediff-jump-to-difference), Ediff will
547 ;; take you to Nth difference. Hitting a number, N, and then 'ab' 955 ;; take you to Nth difference. Hitting a number, N, and then `ab'
548 ;; (ediff-diff-to-diff) will copy Nth difference from buffer A to buffer B. 956 ;; (ediff-diff-to-diff) will copy Nth difference from buffer A to buffer B.
549 ;; Hitting 'ba' does copying in the other direction. 957 ;; Hitting `ba' does copying in the other direction. Likewise, `ca' would
550 ;; Likewise, a number, N, followed by 'ra' will restore the Nth difference 958 ;; copy from buffer C to buffer A (if buffer C exists, of course).
959 ;; Likewise, a number, N, followed by `ra' will restore the Nth difference
551 ;; region in buffer A (if it was previously saved as a result of copying 960 ;; region in buffer A (if it was previously saved as a result of copying
552 ;; from B to A). 961 ;; from buffer B to A).
553 ;; 962 ;;
554 ;; Without the prefix argument, all commands operate on the current 963 ;; Without the prefix argument, all commands operate on the current
555 ;; difference region. 964 ;; difference region.
556 ;; 965 ;;
557 ;; The total number of differences and the current difference number are 966 ;; The total number of differences and the current difference number are
558 ;; always displayed in the mode line of the control window. 967 ;; always displayed in the mode line of the control window.
559 ;; 968 ;;
560 ;; If, after making changes to buffers A and B, you decide to save them, it 969 ;; If, after making changes to buffers A, B, or C, you decide to save them,
561 ;; is recommended to use `ediff-save-buffer', which is bound to `wa' and 970 ;; it is recommended to use `ediff-save-buffer', which is bound to `wa', `wb',
562 ;; `wb' (`wa will save buffer A and `wb' saves buffer B). 971 ;; and `wc' (`wa will save buffer A, `wb' saves buffer B, etc.).
563 ;; 972 ;;
564 ;; Typing `wf' will also save the diff output in a file. 973 ;; Typing `wd' saves the diff output in a file.
565 974
566 ;;; Display Modes 975 ;; The command `s' is used only for merging. It allows the user to shrink
567 ;; ------------- 976 ;; window C to its minimal size, thereby exposing as much of buffers A and
568 977 ;; B as possible.
569 ;; Ediff can display files in one frame, stacked side-by-side or one on top 978 ;; This command is intended only for temporary viewing. Therefore, Ediff
570 ;; of another; or it can display the files in different frames. When you 979 ;; will restore the original window size for buffer C whenever window
571 ;; start Ediff, it assumes a 1-frame mode. You can toggle the side-by-side 980 ;; configuration is changed by the user (on toggling help, split,
572 ;; and one-on-top-of-another displays by simply hitting 's'. 981 ;; etc.). However, recentering and jumping to a difference doesn't affect
573 ;; 982 ;; window C. Typing `s' again restores the original size of the merge
574 ;; Ediff switches to the multi-frame mode when: 983 ;; window.
575 ;; 984 ;;
576 ;; 1. file-A and file-B are in different frames (you have to put them into 985 ;; With a positive prefix argument, the command `s' makes the merge
577 ;; different frames manually); or 986 ;; window, window C, slightly taller. With `-' or a negative prefix
578 ;; 2. Ediff Control Panel is visible in one frame and one other file (A 987 ;; argument, `s' makes window C slightly shorter.
579 ;; or B) is visible in another frame. If, say, fileA is visible in a 988 ;;
580 ;; different frame than Ediff Control Panel, fileB doesn't have to be 989 ;; While browsing through differences in the merge mode, one may discover
581 ;; visible. If it is, Ediff will continue displaying fileB in the frame 990 ;; that the default variant was chosen inappropriately, which means that
582 ;; where it was visible before. If it isn't then Ediff will arrange for 991 ;; the user will have to do a lot of copying manually. To facilitate this,
583 ;; fileB to share a frame with Ediff Control Panel. 992 ;; there is a command, bound to `&', which will cause Ediff to start
584 ;; 993 ;; merging anew beginning with the current difference and using the
585 ;; If all three buffers are in separate frames, Ediff will switch to a 994 ;; alternative default variant (the user is asked to type in the new
586 ;; 3-frame mode. If Ediff buffers are currently visible only in two 995 ;; default for merging, which can be either `default-A', `default-B', or
587 ;; frames, Ediff will work in a 2-frame mode. In this mode, one of the 996 ;; `combined'.
588 ;; frames will be shared by Ediff Control Panel and file-A or file-B 997 ;;
589 ;; (whichever is appropriate). 998 ;; Such repeated merging affects only difference regions that have
999 ;; default-A/B status, and only if they were not changed with respect to
1000 ;; their originals.
1001 ;;
1002 ;; Another command that is used for merging only is `+'. Its effect is to
1003 ;; combine the current difference regions of buffers A and B and put the
1004 ;; combination into the merge buffer. See `ediff-combine-diffs' and
1005 ;; `ediff-combination-pattern' for details.
1006 ;;
1007 ;; There is also one command the is not bound to any key:
1008 ;;
1009 ;; ediff-revert-buffers-then-recompute-diffs
1010 ;;
1011 ;; It is useful when, after making changes, you decided to make a fresh
1012 ;; start, or if at some point you changed the files being compared but want
1013 ;; to discard any changes to comparison buffers that were done since then.
1014 ;; This command will ask for confirmation before reverting files. With a
1015 ;; prefix argument, it will revert files without asking.
1016
1017 ;;; Heavy-duty customization:
1018 ;; -------------------------
1019
1020 ;; Some users need to customize Ediff in rather sophisticated ways, which
1021 ;; requires different defaults for different kinds of files (e.g., SGML, etc.).
1022 ;; Ediff supports this kind of customization is several ways.
1023 ;; First, most customization variables are buffer-local. Those that aren't
1024 ;; are usually accessible from within Ediff Control Panel, so one can make
1025 ;; thel local to the panel by calling make-local-variable from within
1026 ;; ediff-startup-hooks.
1027 ;; Second, there is now a new optional (6-th) argument to ediff-setup,
1028 ;; which has the form ( (var-name-1 . val-1) (var-name-2 . val-2) ...).
1029 ;; The function ediff-setup will set the variables on the list to the
1030 ;; respective values in the ediff control buffer. This is an easy way to
1031 ;; throw in custom variables (which usually should be buffer-local) that
1032 ;; can then be tested in various hooks.
1033 ;; Make sure the variable ediff-job-name and ediff-word-mode are set
1034 ;; properly in this case, as some things in Ediff depend on this.
1035 ;; Finally, if custom-tailored help messages are desired, Ediff has
1036 ;; ediff-brief-help-message-custom and ediff-long-help-message-custom,
1037 ;; which are local variables that can be either set to
1038 ;; a function that returns a string.
590 1039
591 1040
592 ;;; Bugs: 1041 ;;; Bugs:
593 ;; ---- 1042 ;; -----
594 1043
595 ;; 1. The undo command doesn't restore deleted regions well. That is, if 1044 ;; 1. The undo command doesn't restore deleted regions well. That is, if
596 ;; you delete all characters in a difference region and then invoke 1045 ;; you delete all characters in a difference region and then invoke
597 ;; `undo', the reinserted text will most likely be reinserted outside of 1046 ;; `undo', the reinstated text will most likely be inserted outside of
598 ;; what Ediff thinks is the current difference region. (This problem 1047 ;; what Ediff thinks is the current difference region. (This problem
599 ;; doesn't seem to exist with Lucid Emacs.) 1048 ;; doesn't seem to exist with XEmacs.)
600 ;; 1049 ;;
601 ;; If at any point you feel that difference regions are no longer correct, 1050 ;; If at any point you feel that difference regions are no longer correct,
602 ;; you can hit '!' to recompute the differences. 1051 ;; you can hit '!' to recompute the differences.
603 1052
604 ;; 2. Emacs 19.xx, where xx < 23, has several bugs related to overlays and 1053 ;; 2. Emacs 19.xx, where xx < 23, has several bugs related to overlays and
616 ;; provide commands for unhighlighting buffers. You can either place these 1065 ;; provide commands for unhighlighting buffers. You can either place these
617 ;; commands in `ediff-prepare-buffer-hooks' (which will unhighlight every 1066 ;; commands in `ediff-prepare-buffer-hooks' (which will unhighlight every
618 ;; buffer used by Ediff) or you can execute them interactively, at any time 1067 ;; buffer used by Ediff) or you can execute them interactively, at any time
619 ;; and on any buffer. 1068 ;; and on any buffer.
620 1069
621 ;; 4. In Lucid Emacs (statically linked with Motif libraries), emerge.el 1070 ;; 4. In XEmacs (statically linked with Motif libraries), emerge.el
622 ;; and hence ediff.el won't start, unless you set (setq scrollbar-width 0). 1071 ;; and hence Ediff won't start, unless you set (setq scrollbar-width 0).
623 ;; This is a Motif-related bug, I was told. 1072 ;; This is a Motif-related bug, I was told.
1073
1074 ;; 5. XEmacs 19.11 (and, probably, earlier versions) has trouble
1075 ;; positioning the point withing Ediff buffers on Ediff's startup.
1076 ;; This doesn't get in the way, though, since when the user start looking
1077 ;; at the diff regions, they are positioned correctly. It seems that
1078 ;; XEmacs doesn't have enough time to redisplay windows---it does this
1079 ;; correctly when it is told to redisplay (sit-for 0).
1080
1081 ;; 6. It seems that XEmacs icons are insensitive to keyboard events. This
1082 ;; deprives XEmacs users from being able to iconify Ediff's control panel,
1083 ;; thereby saving space onthe screen. Also, it seems that XEmacs doesn't
1084 ;; let one create minibuffer-less frames, which leaves Ediff control Panel
1085 ;; with a useless minibuffer. The "unsplittable" property is also ignored
1086 ;; in XEmacs, some further minor annoyances are possible.
1087
1088 ;; 7. XEmacs (19.11 and below) doesn't let one create minibufferless
1089 ;; frames. This causes the problem that messages are displayed in a small
1090 ;; control frame window, when help is toggled off. Ediff overcomes this by
1091 ;; setting synchronize-minibuffers to t, which causes all messages to be
1092 ;; displayed in all minibuffers. If you detest this, set
1093 ;; synchronize-minibuffers to nil after quitting Ediff.
624 1094
625 1095
626 ;;; Change Log: 1096 ;;; Change Log:
627 ;; ---------- 1097 ;; ----------
628 1098
629 ;; Thu Feb 3, 1994 1099 ;; Thu Feb 3, 1994
630 1100
631 ;; Added ediff-read-file-name, which is a stub that takes care of Lemacs
632 ;; versions of Emerge. (Thanks to Alastair Burt <burt@dfki.uni-kl.de>.)
633 ;;
634 ;; Fixed a bug in ediff-setup-windows that caused control window to 1101 ;; Fixed a bug in ediff-setup-windows that caused control window to
635 ;; appear in a wrong place when split-window-keep-point is nil 1102 ;; appear in a wrong place when split-window-keep-point is nil
636 ;; (Thanks to Kevin Broadey <KevinB@bartley.demon.co.uk>.) 1103 ;; (Thanks to Kevin Broadey <KevinB@bartley.demon.co.uk>.)
637 ;; 1104 ;;
638 ;; Added mechanism for using faces instead of before/after flags. This 1105 ;; Added mechanism for using faces instead of before/after flags. This
664 1131
665 ;; Added horizontal scrolling. Added ediff-position-region to ensure 1132 ;; Added horizontal scrolling. Added ediff-position-region to ensure
666 ;; that difference regions in buffer-A and buffer-B are aligned with 1133 ;; that difference regions in buffer-A and buffer-B are aligned with
667 ;; each other. Disabled ediff-toggle-split when buffers are displayed 1134 ;; each other. Disabled ediff-toggle-split when buffers are displayed
668 ;; in different frames. 1135 ;; in different frames.
669 1136 ;;
670 ;; Mon Feb 7, 1994
671
672 ;; Added toggle-window help (Suggested by Boris Goldowsky 1137 ;; Added toggle-window help (Suggested by Boris Goldowsky
673 ;; <boris@cs.rochester.edu>.) 1138 ;; <boris@cs.rochester.edu>.)
674 ;; Added functions to copy differences from one buffer to another and to 1139 ;; Added functions to copy differences from one buffer to another and to
675 ;; recover old differences. 1140 ;; recover old differences.
676 ;; Added prefix arguments to ediff-next-difference and 1141 ;; Added prefix arguments to ediff-next-difference and
684 ;; for suggestion.) Instead, Ediff now has a pair of functions for 1149 ;; for suggestion.) Instead, Ediff now has a pair of functions for
685 ;; safe saving of buffers. 1150 ;; safe saving of buffers.
686 ;; Changed ediff-read-file-name to be more intuitive on ediff-files. 1151 ;; Changed ediff-read-file-name to be more intuitive on ediff-files.
687 ;; Added ediff-prepare-buffer-hooks. (Thanks to Kevin Esler 1152 ;; Added ediff-prepare-buffer-hooks. (Thanks to Kevin Esler
688 ;; <esler@ch.hp.com> for the idea.) 1153 ;; <esler@ch.hp.com> for the idea.)
689 1154 ;;
690 ;; Wed Feb 9, 1994
691
692 ;; Cleanups in ediff-patch-file. Protected ediff-copy-diff against 1155 ;; Cleanups in ediff-patch-file. Protected ediff-copy-diff against
693 ;; a bug that Emacs has in kill-region. 1156 ;; a bug that Emacs has in kill-region.
694 1157 ;;
695 ;; Thu Feb 10, 1994
696
697 ;; Added support for Lemacs. (Thanks to Alastair Burt 1158 ;; Added support for Lemacs. (Thanks to Alastair Burt
698 ;; <burt@dfki.uni-kl.de> for coercing Ediff into working under Lemacs.) 1159 ;; <burt@dfki.uni-kl.de> for coercing Ediff into working under Lemacs.)
699 ;; Added ediff-kill-buffer-carefully and other suggestions by Boris 1160 ;; Added ediff-kill-buffer-carefully and other suggestions by Boris
700 ;; Goldowsky <boris@cs.rochester.edu>. 1161 ;; Goldowsky <boris@cs.rochester.edu>.
701 ;; Refined the protection against interference with highlighting caused 1162 ;; Refined the protection against interference with highlighting caused
721 1182
722 ;; Deleted spurious (auto-save-mode 1) in ediff-control-buffer, which 1183 ;; Deleted spurious (auto-save-mode 1) in ediff-control-buffer, which
723 ;; was causing this buffer to be auto-saved for no good reason. 1184 ;; was causing this buffer to be auto-saved for no good reason.
724 ;; Added read-only protection to ediff-before/after-flags in Lemacs. 1185 ;; Added read-only protection to ediff-before/after-flags in Lemacs.
725 ;; (Thanks to Alastair Burt <burt@dfki.uni-kl.de> for help in testing.) 1186 ;; (Thanks to Alastair Burt <burt@dfki.uni-kl.de> for help in testing.)
726 1187 ;;
727 ;; Wed Feb 16, 1994 1188 ;; Further fixes in the XEmacs part. Changed highlighted region in
728
729 ;; Further fixes in the Lemacs part. Changed highlighted region in
730 ;; ediff-highlight-diff so that an extra character will be highlighted 1189 ;; ediff-highlight-diff so that an extra character will be highlighted
731 ;; only if a difference is empty (thereby allowing the user to see where an 1190 ;; only if a difference is empty (thereby allowing the user to see where an
732 ;; insertion or a deletion has taken place). 1191 ;; insertion or a deletion has taken place).
733 ;; 1192 ;;
734 ;; Simplified interaction with other highlighting packages by giving 1193 ;; Simplified interaction with other highlighting packages by giving
747 ;; Fri Feb 22, 1994 1206 ;; Fri Feb 22, 1994
748 1207
749 ;; Added ediff-before-change-guard to remove ASCII highlighting when 1208 ;; Added ediff-before-change-guard to remove ASCII highlighting when
750 ;; the user attempts to change buffer-A/B. This is needed because 1209 ;; the user attempts to change buffer-A/B. This is needed because
751 ;; otherwise the undo info may become screwed up in those buffers. 1210 ;; otherwise the undo info may become screwed up in those buffers.
752 ;; Hitting 'h' (ediff-toggle-hilit) on a dumb terminal will toggle 1211 ;; Hitting `h' (ediff-toggle-hilit) on a dumb terminal will toggle
753 ;; between ASCII highlighting and no highlighting. 1212 ;; between ASCII highlighting and no highlighting.
754 1213
755 ;; Fri Feb 24, 1994 1214 ;; Fri Feb 24, 1994
756 1215
757 ;; Fixed problems with multiple Ediff sessions running simultaneously. 1216 ;; Fixed problems with multiple Ediff sessions running simultaneously.
782 ;; should eliminate problems with $prompt that some people had. 1241 ;; should eliminate problems with $prompt that some people had.
783 1242
784 ;; Thu March 24, 1994 1243 ;; Thu March 24, 1994
785 1244
786 ;; Achieved quadratic speedup in the size of the file by replacing the 1245 ;; Achieved quadratic speedup in the size of the file by replacing the
787 ;; slow goto-line by forward-line. Ediff is now *much* faster than 1246 ;; slow goto-line by forward-line.
788 ;; Emerge on large files. Converted demarkation of difference regions 1247 ;; Converted demarkation of difference regions
789 ;; from markers to overlays. This will later allow us to highlight all 1248 ;; from markers to overlays. This will later allow us to highlight all
790 ;; diffs, not just the current one. 1249 ;; diffs, not just the current one.
791 1250
792 ;; Wed March 30, 1994 1251 ;; Wed March 30, 1994
793 1252
794 ;; Under X, Ediff now highlights all differences in dim colors and the 1253 ;; Under X, Ediff now highlights all differences in dim colors and the
795 ;; current difference in bright colors. Improved Lucid Emacs support. 1254 ;; current difference in bright colors. Improved XEmacs support.
796
797 ;; Thu March 31, 1994
798
799 ;; Changed toggle hilit to cycle through 3 states: highlighting all 1255 ;; Changed toggle hilit to cycle through 3 states: highlighting all
800 ;; diffs, highlighting only the current diff, and highlighting using 1256 ;; diffs, highlighting only the current diff, and highlighting using
801 ;; ASCII flags. 1257 ;; ASCII flags.
802 ;; Added support for difference regions that are not full lines. 1258 ;; Added support for difference regions that are not full lines.
803 1259
804 ;; Fri April 1, 1994 1260 ;; Fri April 1, 1994
805 1261
806 ;; Fixed bugs related to writing buffers A and B. 1262 ;; Fixed bugs related to writing buffers A and B.
807 ;; Added commands 'ga', 'gb' to jump directly to the closest diff in 1263 ;; Added commands `ga', `gb' to jump directly to the closest diff in
808 ;; buffer A and B, respectively. 1264 ;; buffer A and B, respectively.
809 1265
810 ;; Fri April 11, 1994 1266 ;; Fri April 11, 1994
811 1267
812 ;; Added `ediff-recompute-diffs', a function that lets the user recompute 1268 ;; Added `ediff-update-diffs', a function that lets the user recompute
813 ;; difference regions after extensive editing done to buffers A and B 1269 ;; difference regions after extensive editing done to buffers A and B
814 ;; (bound to `!'). 1270 ;; (bound to `!').
815 1271
816 ;; Wed April 13, 1994 1272 ;; Wed April 13, 1994
817 1273
831 1287
832 ;; Fri April 15, 1994 1288 ;; Fri April 15, 1994
833 1289
834 ;; Changed `ediff-setup-windows' to minimize the need to delete and 1290 ;; Changed `ediff-setup-windows' to minimize the need to delete and
835 ;; create windows. Now jumps faster from diff to diff. 1291 ;; create windows. Now jumps faster from diff to diff.
836
837 ;; Sat April 16, 1994
838
839 ;; Added Ediff to the File menu on the menu bar (FSF's version). 1292 ;; Added Ediff to the File menu on the menu bar (FSF's version).
840 1293
841 ;; Mon April 18, 1994 1294 ;; Mon April 18, 1994
842 1295
843 ;; Fixed to work with OS/2's PM-Emacs. 1296 ;; Fixed to work with OS/2's PM-Emacs.
846 1299
847 ;; Lemacs' menus added (thanks to Alastair Burt for the help). 1300 ;; Lemacs' menus added (thanks to Alastair Burt for the help).
848 1301
849 ;; Wed April 28, 1994 1302 ;; Wed April 28, 1994
850 1303
851 ;; Fixed ediff-leave-window-config (thanks to Norbert Kiesel 1304 ;; Fixed ediff-keep-window-config (thanks to Norbert Kiesel
852 ;; <norbert@i3.informatik.rwth-aachen.de>), ediff-shell and 1305 ;; <norbert@i3.informatik.rwth-aachen.de>), ediff-shell and
853 ;; ediff-protect-metachars (thanks to Richard Stanton 1306 ;; ediff-protect-metachars (thanks to Richard Stanton
854 ;; <stanton@haas.berkeley.edu>). Made access to difference 1307 ;; <stanton@haas.berkeley.edu>). Made access to difference
855 ;; overlays structure-independent, making it less bug-prone. 1308 ;; overlays structure-independent, making it less bug-prone.
856 ;; Patched ediff-read-file-name to work more intuitively with directory 1309 ;; Patched ediff-read-file-name to work more intuitively with directory
887 ;; Added ediff-eval-in-buffer, which is a modified emerge-eval-in-buffer. 1340 ;; Added ediff-eval-in-buffer, which is a modified emerge-eval-in-buffer.
888 ;; The function ediff-status-info, bound to `i', now replaces and extends 1341 ;; The function ediff-status-info, bound to `i', now replaces and extends
889 ;; ediff-file-names and ediff-line-numbers, which were bound to `f' 1342 ;; ediff-file-names and ediff-line-numbers, which were bound to `f'
890 ;; and `i', respectively. 1343 ;; and `i', respectively.
891 1344
892 ;; Wed Jun 8, 1994
893
894 ;; Made `ediff-frame-has-menubar' into a function; copied
895 ;; `emerge-defvar-local' and turned it into `ediff-defvar-local'
896 ;; This is supposed to make the same ediff.elc file work for both Emacs
897 ;; and Lucid Emacs, at least, if compiled under Lucid Emacs. (Thanks
898 ;; to Eric Eide <eeide@asylum.cs.utah.edu>.)
899 1345
900 ;; Wed Jun 10, 1994 1346 ;; Wed Jun 10, 1994
901 1347
902 ;; Improved `ediff-read-file-name' and `ediff-buffers' so they are now 1348 ;; Improved `ediff-read-file-name' and `ediff-buffers' so they are now
903 ;; providing more intuitive defaults. Modified `ediff-read-file-name' 1349 ;; providing more intuitive defaults. Modified `ediff-read-file-name'
935 ;; `ediff-ignore-similar-regions' and can be toggled on/off by typing 1381 ;; `ediff-ignore-similar-regions' and can be toggled on/off by typing
936 ;; `##'. 1382 ;; `##'.
937 1383
938 ;; Mon August 8, 1994 1384 ;; Mon August 8, 1994
939 1385
940 ;; If ediff-save-buffer is invoked with `wf', it'll save the diff 1386 ;; If ediff-save-buffer is invoked with `wd', it'll save the diff
941 ;; output in a file. 1387 ;; output in a file.
942 1388
943 ;; Wed August 24, 1994 1389 ;; Wed August 24, 1994
944 1390
945 ;; Fixed ediff-toggle-read-only and ediff-patch-file so that they will 1391 ;; Fixed ediff-toggle-read-only and ediff-patch-file so that they will
954 ;; Introduced ediff-revision as a uniform way of calling vc.el and 1400 ;; Introduced ediff-revision as a uniform way of calling vc.el and
955 ;; rcs.el. This is controled by ediff-version-control-package 1401 ;; rcs.el. This is controled by ediff-version-control-package
956 ;; variable. Functions vc-ediff, rcs-ediff are replaced by their 1402 ;; variable. Functions vc-ediff, rcs-ediff are replaced by their
957 ;; internal versions. 1403 ;; internal versions.
958 ;; Added ediff-find-file-name-handler function to smooth out the 1404 ;; Added ediff-find-file-name-handler function to smooth out the
959 ;; transition from Emacs 19.22/Lucid 19.9 to 19.23/19/10 1405 ;; transition from Emacs 19.22/XEmacs 19.9 to 19.23/19/10
960 1406
961 ;; Thus September 1, 1994 1407 ;; Thu September 1, 1994
962 1408
963 ;; Made ediff-overlay-put and ediff-move-overlay into bona fide 1409 ;; Made ediff-overlay-put and ediff-move-overlay into bona fide
964 ;; functions (rather than fset symbols). These now check if overlay's 1410 ;; functions (rather than fset symbols). These now check if overlay's
965 ;; buffer is alive. If not, overlay is deleted. This overcomes some of 1411 ;; buffer is alive. If not, overlay is deleted. This overcomes some of
966 ;; the problems with Lemacs. 1412 ;; the problems with Lemacs.
967 1413
1414 ;; Thu September 8, 1994
1415
1416 ;; Added ediff-revision-key, ediff-load-version-control and streamlined
1417 ;; vc/rcs-ediff[-internal]. Eliminated dependency on emerge.el.
1418
1419 ;; Fri September 23, 1994
1420
1421 ;; Added ediff-windows and ediff-regions.
1422 ;; Changed ediff-setup-windows and related procedures to create
1423 ;; a separate dedicated control frame for each invocation of Ediff.
1424
1425 ;; Tue September 27, 1994
1426
1427 ;; Added redraw-display everywhere before creating or deleting
1428 ;; frames. It appears that this cures Emacs' bug where it trashes some
1429 ;; fonts which leads to crashes. Also, some code cleanups and bug fixes.
1430
1431 ;; Fri September 30, 1994
1432
1433 ;; Fixed ediff-update-diffs so it'll work correctly with
1434 ;; ediff-windows and ediff-regions. Added narrowing and widening to the
1435 ;; suite of commands available for ediff-windows and ediff-regions.
1436
1437 ;; Fri October 7, 1994
1438
1439 ;; Changed ediff-setup-windows to funcall the actual window setting
1440 ;; function, which is either ediff-setup-windows-multiframe or
1441 ;; ediff-setup-windows-plain. Changed all temp file names to use `_'
1442 ;; instead of `.'. Presumably, this makes VMS happier.
1443 ;; Ported to VMS (thanks to Richard Levitte <levitte@e.kth.se>).
1444 ;; Added ediff-prefer-long-help-message and changed defaults.
1445 ;; Fighting with XEmacs bugs. Made it possible to switch between plain
1446 ;; and multiframe display easier, but XEmacs is still getting confused
1447 ;; at times. Added ediff-check-version and ediff-set-help-message.
1448 ;; Made more sensible temp file names, which is important when
1449 ;; generating context diffs. Added ediff-make-frame-position and
1450 ;; ediff-control-frame-position-function.
1451
1452 ;; Wed October 12, 1994
1453
1454 ;; ediff-window-visible-p now makes a call to ediff-frame-visible-p
1455 ;; only when window-system is non-nil. Rearranged the block of fset's
1456 ;; so that the wrong things won't be defined when window-system is nil.
1457 ;; Added ediff-revert-buffers-then-recompute-diffs function.
1458 ;; Removed flag-argument from a background call to shell-command.
1459 ;; Added ediff-shell-command to enable custom diff execute in the
1460 ;; background and insert output in ediff-custom-diff-buffer.
1461 ;; Added ediff-shell-command-filter, because XEmacs doesn't have it.
1462 ;; Made ediff-revision set up ediff-job-name to `ediff-revision'.
1463 ;; This enables users do ediff-revision-specific actions on exiting
1464 ;; Ediff using ediff-quit-hooks.
1465 ;; Reshaffled some fset's so that functions for checking color and
1466 ;; faces won't be touched on a non-windowing display.
1467
1468 ;; Thu October 20, 1994
1469
1470 ;; Modified ediff-make-fine-diffs so that no fine diffs are computed if
1471 ;; one of the diff regions is empty. Saves time and also works around
1472 ;; the buggy diff program in AIX.
1473 ;; ediff no longer loads the version control package
1474 ;; automatically---only when ediff-revision is called.
1475 ;; Enabled focusing/hiding diff regions that match both or just one of the
1476 ;; regexps.
1477 ;; Changed ediff-regions to ediff-small-regions. Added ediff-large-regions.
1478 ;; Modified ediff-next/previous-difference to work right when both
1479 ;; skipping regexp matches and skipping similar regions is enabled.
1480 ;; Fixed bugs in positioning the control frame.
1481
1482 ;; Fri October 28, 1994
1483
1484 ;; Fixed bugs in ediff-next/previous-difference, ediff-set-visible-region
1485 ;; Changed/added ediff-word-[1-4].
1486
1487 ;; Tue November 1, 1994
1488
1489 ;; Made ediff-revision delete the temporary version files it creates.
1490
1491 ;; Tue November 29, 1994
1492
1493 ;; Added ediff-swap-buffers. Split ediff-difference-vector into
1494 ;; ediff-difference-vector-A and ediff-difference-vector-B, which
1495 ;; allowed to factor out a lot of stuff.
1496 ;; Made the code buffer-C ready.
1497
1498 ;; Thu December 1, 1994
1499
1500 ;; Lotsa bug fixes. Further rationalized the code.
1501 ;; Added ediff-display-help-hooks, ediff-mode-hooks.
1502 ;; Replaced almost identical ediff-scroll-up/down with
1503 ;; ediff-scroll-vertically.
1504 ;; Replaced almost identical ediff-scroll-left/right with
1505 ;; ediff-scroll-horizontally.
1506 ;; Made the code buffer-C ready.
1507
1508 ;; Thu December 8, 1994
1509
1510 ;; Added ediff-toggle-wide-display. In plain display, help message is
1511 ;; now centered correctly.
1512
1513 ;; Fri December 9, 1994
1514
1515 ;; Added ediff-toggle-multiframe (it doesn't work with XEmacs for some
1516 ;; reason). Fixed ediff-pop-diff and ediff-copy-diff, so that they will
1517 ;; invoke auto-refining, if necessary.
1518
1519 ;; Mon December 12, 1994
1520
1521 ;; Modified ediff-toggle-wide-display so it would funcall
1522 ;; ediff-make-wide-display-function.
1523
1524 ;; Tue December 13, 1994
1525
1526 ;; Ediff now chooses its surrogate minibuffer from frame A.
1527
1528 ;; Mon December 20, 1994
1529
1530 ;; Added ediff-keymap-setup-hooks.
1531
1532 ;; Fri December 23, 1994
1533
1534 ;; Changed the representation in ediff-killed-diffs-alist so that
1535 ;; ediff-save-diff-region and ediff-pop-diff won't be confused when the
1536 ;; user swaps buffers.
1537
1538 ;; Mon December 26, 1994
1539
1540 ;; Placated OS/2 by making Ediff to synchronize the call to startup
1541 ;; hooks with the acynchronous process that computes custom diffs.
1542 ;; This has no effect on Unix installations (and VMS?), but
1543 ;; may increase Ediff's startup time under OS/2 by 1 or 2 seconds.
1544
1545 ;; Thu December 29, 1994
1546
1547 ;; ediff-recenter now deactivates the mark, so that transient mark mode
1548 ;; highlighting won't interfere with Ediff's highlighting.
1549 ;; Also, ediff-recenter tries to not deiconify control frame, if it is
1550 ;; not needed.
1551
1552 ;; Fri December 30, 1994
1553
1554 ;; Small bugs. Worked around the OS/2 bug where
1555 ;; modify-frame-parameters has no effect on iconified frames. Ediff
1556 ;; now remembers the iconification status of the control frame and uses
1557 ;; it as a preferred way of displaying it when help is toggled
1558 ;; off. (This can be observed only in Emacs (not XEmacs) and only if
1559 ;; the window manager lets icons accept keyboard input.)
1560
1561 ;; Tue January 3, 1995
1562
1563 ;; Some futher work on incorporating buffer C in ediff-extract-diffs,
1564 ;; ediff-focus/hide-on-regexp-matches, and
1565 ;; ediff-setup-windows-plain/multiframe. The preceding two functions
1566 ;; now dispatch the appropriate setup function depending on whether the
1567 ;; current job is comparison or merge.
1568
1569 ;; Wed January 4, 1995
1570
1571 ;; Made it work under Emacs built without the X support.
1572
1573 ;; Fri January 6, 1995
1574
1575 ;; Slightly changed the prompting behavior of ediff-files. Bug fix in
1576 ;; mode-line-buffer-identification.
1577
1578 ;; Wed January 18, 1995
1579
1580 ;; Added 3way comparison and support for diff3. Ported to NeXTStep
1581 ;;
1582 ;; Fri January 20, 1995
1583
1584 ;; Added ediff-merge-files, ediff-merge-buffers,
1585 ;; ediff-merge-files-with-ancestor, ediff-merge-buffers-with-ancestor,
1586 ;; ediff-merge-revisions, ediff-merge-revisions-with-ancestor.
1587
1588 ;; Tue January 24, 1995
1589
1590 ;; Bug fixes. Split into several files.
1591
1592 ;; Thu January 26, 1995
1593
1594 ;; `*' is now bound to ediff-make-or-kill-fine-diffs. This lets the
1595 ;; user to kill fine diffs for the current region (by providing a
1596 ;; negative prefix arg), if there are so many of them as to hamper
1597 ;; the viewing.
1598
1599 ;; Mon January 30, 1995
1600
1601 ;; Changed ediff-selective-display to ediff-set-visible-region,
1602 ;; ediff-toggle-selective-display to ediff-toggle-narrow-region.
1603 ;; Ediff now turns selective display off before starting. Restores
1604 ;; selective display on exit.
1605 ;; In 2-way comparison, `a' now copies to buf `b' and `b' to buf `a'.
1606 ;; Previously, the bindings were `ab' and `ba'.
1607
1608 ;; Wed February 1, 1995
1609
1610 ;; Added ediff-undo-selective-display (thanks to Stig <stig@inse.com>).
1611 ;; Rearranged autoloads. Renamed ediff-entry.el into ediff.el and
1612 ;; ediff.el into ediff-util.el.
1613
1614 ;; Fri February 3
1615
1616 ;; Added ediff-toggle-show-clashes-only, which is bound to `$'.
1617
1618 ;; Fri February 19
1619
1620 ;; Some minor patches from Stig. Also, made ediff-xemacs-p and
1621 ;; ediff-*-job into variables for better performance.
1622 ;; In ediff-setup, diff regions are now computed after buffers A/B/C
1623 ;; are set up. Previously, it didn't work right with selective display.
1624 ;; Also, added ediff-profile to time Ediff commands and
1625 ;; ediff-debug-info for civilized display of the difference vectors
1626 ;; (and possibly more in the future).
1627
1628 ;; Tue March 14
1629
1630 ;; Fixed ediff-diff-at-point.
1631
1632
1633 ;;; TO DO:
1634 ;; ------
1635 ;;
1636 ;; 1. Add support for multiple sessions. (At present, one can run
1637 ;; multiple Ediff sessions, but they won't be related.) The idea is to
1638 ;; have vars local to each control buffer, which will tell which buffer is
1639 ;; the next and which is the previous one. The user could then go forward
1640 ;; and backward by typing C-SPC and C-DEL (or C-n and C-p).
1641 ;; This will probably entail some minor modifications to ediff-setup.
1642 ;; The primary use of this feature would be comparing directories of
1643 ;; similarly named files and multi-file patch. For the latter, Ediff will
1644 ;; have to parse patches to extract the names of files.
1645
968 1646
969 ;;; Acknowledgements: 1647 ;;; Acknowledgements:
970 1648
971 ;; Special thanks to Alastair Burt <burt@dfki.uni-kl.de>, Kevin Esler 1649 ;; Special thanks to Alastair Burt <burt@dfki.uni-kl.de>, Kevin Broadey
972 ;; <esler@ch.hp.com>, Kevin Broadey <KevinB@bartley.demon.co.uk>, 1650 ;; <KevinB@bartley.demon.co.uk>, Harald Boegeholz
973 ;; Harald Boegeholz <hwb@machnix.mathematik.uni-stuttgart.de>, 1651 ;; <hwb@machnix.mathematik.uni-stuttgart.de>, Jin S. Choi" <jin@atype.com>,
974 ;; Robert Estes <estes@ece.ucdavis.edu>, Eric Eide <eeide@asylum.cs.utah.edu>, 1652 ;; Eric Eide <eeide@asylum.cs.utah.edu>, Kevin Esler <esler@ch.hp.com>, Robert
975 ;; Eric Freudenthal <freudent@jan.ultra.nyu.edu>, Job Ganzevoort 1653 ;; Estes <estes@ece.ucdavis.edu>, Eric Freudenthal
976 ;; <Job.Ganzevoort@cwi.nl>, Boris Goldowsky <boris@cs.rochester.edu>, 1654 ;; <freudent@jan.ultra.nyu.edu>,
977 ;; Allan Gottlieb <gottlieb@allan.ultra.nyu.edu>, Xiaoli Huang 1655 ;; Job Ganzevoort <Job.Ganzevoort@cwi.nl>, Boris Goldowsky
978 ;; <hxl@epic.com>, irvine@lks.csi.com, jaffe@chipmunk.cita.utoronto.ca, 1656 ;; <boris@cs.rochester.edu>, Allan Gottlieb <gottlieb@allan.ultra.nyu.edu>,
979 ;; David Karr, <dkarr@nmo.gtegsc.com>, Norbert Kiesel 1657 ;; Xiaoli Huang <hxl@epic.com>, Larry Gouge <larry@itginc.com>,
980 ;; <norbert@i3.informatik.rwth-aachen.de>, Heinz Knutzen 1658 ;; irvine@lks.csi.com, jaffe@chipmunk.cita.utoronto.ca, David Karr
981 ;; <hk@informatik.uni-kiel.d400.de>, Martin Maechler 1659 ;; <dkarr@nmo.gtegsc.com>, Norbert Kiesel
982 ;; <maechler@stat.math.ethz.ch>, Richard Mlynarik <mly@adoc.xerox.com>, 1660 ;; <norbert@i3.informatik.rwth-aachen.de>, Fritz Knabe <Fritz.Knabe@ecrc.de>,
983 ;; Eyvind Ness <Eyvind.Ness@hrp.no>, Ray Nickson <nickson@cs.uq.oz.au>, 1661 ;; Heinz Knutzen <hk@informatik.uni-kiel.d400.de>, Ken Laprade
984 ;; Sandy Rutherford <sandy@ibm550.sissa.it>, Andy Scott 1662 ;; <laprade@dw3f.ess.harris.com>, Richard Levitte
985 ;; <ascott@pcocd2.intel.com>, Richard Stallman <rms@gnu.ai.mit.edu>, 1663 ;; <levitte@e.kth.se>, Martin Maechler <maechler@stat.math.ethz.ch>,
986 ;; Richard Stanton, <stanton@haas.berkeley.edu>, Peter Stout 1664 ;; Richard Mlynarik <mly@adoc.xerox.com>, Chris Murphy
987 ;; <Peter_Stout@cs.cmu.edu> for contributing ideas, patches, and bug reports. 1665 ;; <murphycm@sun.aston.ac.uk>, Eyvind Ness <Eyvind.Ness@hrp.no>, Ray Nickson
988 ;; 1666 ;; <nickson@cs.uq.oz.au>, Paul Raines <raines@slac.stanford.edu>, Tibor
989 ;; Thanks also to many others who felt obliged to drop a thanks note. 1667 ;; Polgar <tlp00@spg.amdahl.com>, C.S. Roberson <roberson@aur.alcatel.com>,
990 1668 ;; Kevin Rodgers <kevin.rodgers@ihs.com>, Sandy Rutherford
1669 ;; <sandy@ibm550.sissa.it>, Heribert Schuetz <schuetz@ecrc.de>, Andy Scott
1670 ;; <ascott@pcocd2.intel.com>, Axel Seibert
1671 ;; <axel@tumbolia.ppp.informatik.uni-muenchen.de>, Richard Stallman
1672 ;; <rms@gnu.ai.mit.edu>, Richard Stanton <stanton@haas.berkeley.edu>,
1673 ;; Ake Stenhoff <etxaksf@aom.ericsson.se>,
1674 ;; Stig <stig@hackvan.com>, Peter Stout <Peter_Stout@cs.cmu.edu>,
1675 ;; Raymond Toy <toy@rtp.ericsson.se>,
1676 ;; and Ilya Zakharevich <ilya@math.ohio-state.edu>
1677 ;; for contributing ideas, patches, and bug reports.
1678 ;;
1679 ;; Thanks also to many others who felt obliged to drop a thank you note.
991 1680
992 1681
993 ;;; Code: 1682 ;;; Code:
994 1683
995 (require 'emerge) ;; Ediff uses some functions defined in emerge.el 1684 (require 'ediff-init)
996 1685
997 1686 (defvar ediff-version-control-package 'vc
998 ;;; Macros 1687 "Version control package used.
999 (defmacro ediff-if-lucid () 1688 Currently, Ediff supports vc.el and rcs.el. Set this to `rcs' if you have
1000 (` (string-match "Lucid" emacs-version))) 1689 rcs.el and want to use it instead of the standard vc.el.
1001 1690
1002 (defmacro ediff-odd-p (arg) 1691 Note: both packages provide access to RCS, but only vc.el comes with Emacs
1003 (` (eq (logand (, arg) 1) 1))) 1692 distribution.")
1004 1693
1005 (defmacro ediff-buffer-live-p (buf) 1694 (defvar ediff-revision-key "="
1006 (` (and (, buf) (get-buffer (, buf)) (buffer-name (get-buffer (, buf)))))) 1695 "Key to which `ediff-revision' is to be bound.")
1007
1008 (defmacro ediff-get-buffer (arg)
1009 (` (cond ((eq (, arg) 'A) ediff-A-buffer)
1010 ((eq (, arg) 'B) ediff-B-buffer)
1011 )
1012 ))
1013
1014 (defmacro ediff-char-to-buftype (arg)
1015 (` (cond ((eq (, arg) ?a) 'A)
1016 ((eq (, arg) ?b) 'B)
1017 )
1018 ))
1019
1020 (defmacro ediff-get-difference (n)
1021 (` (aref ediff-difference-vector (, n))))
1022
1023 ;; tell if it has been previously found that the region doesn't
1024 ;; contain diffs other than the white space and newlines
1025 ;; The argument, N, is the diff region number used by Ediff to index the
1026 ;; diff vector. It is 1 less than the number seen by the user.
1027 (defmacro ediff-no-fine-diffs (n)
1028 (` (aref (ediff-get-difference n) 3)))
1029
1030 (defmacro ediff-get-diff-overlay-from-vector (vec buf-type)
1031 (` (aref (, vec)
1032 (cond ((eq (, buf-type) 'A) 0)
1033 ((eq (, buf-type) 'B) 1)
1034 )
1035 )))
1036
1037 (defmacro ediff-get-diff-overlay (n buf-type)
1038 (` (ediff-get-diff-overlay-from-vector
1039 (ediff-get-difference (, n))
1040 (, buf-type))))
1041
1042 (defmacro ediff-get-fine-diff-vector-from-vec (current-diff-vec)
1043 (` (aref (, current-diff-vec) 2)))
1044
1045 (defmacro ediff-set-fine-diff-vector (n fine-vec)
1046 (` (aset (ediff-get-difference (, n)) 2 (, fine-vec))))
1047
1048 ;; if flag is t, puts a mark on diff region saying that
1049 ;; the differences are in white space only. If flag is nil,
1050 ;; the region is marked as essential (i.e., differences are
1051 ;; not just in the white space and newlines.)
1052 (defmacro ediff-mark-diff-as-space-only (n flag)
1053 (` (aset (ediff-get-difference (, n)) 3 (, flag))))
1054
1055 (defmacro ediff-get-fine-diff-vector (n)
1056 (` (ediff-get-fine-diff-vector-from-vec (ediff-get-difference (, n)))))
1057
1058
1059 (defmacro ediff-defvar-local (var value doc)
1060 "Defines SYMBOL as an advertised local variable.
1061 Performs a defvar, then executes `make-variable-buffer-local' on
1062 the variable. Also sets the `preserved' (Emacs) or `permanent-local' (Lucid)
1063 property, so that `kill-all-local-variables' (called by major-mode setting
1064 commands) won't destroy Ediff control variables.
1065
1066 This is a merge of `emerge-defvar-local' for Emacs and Lucid Emacs. It is
1067 needed to make the same ediff.elc work under both Emacsen."
1068 (` (progn
1069 (defvar (, var) (, value) (, doc))
1070 (make-variable-buffer-local '(, var))
1071 (put '(, var)
1072 (if (ediff-if-lucid) 'permanent-local 'preserved)
1073 t))))
1074
1075 (defmacro ediff-eval-in-buffer (buffer &rest forms)
1076 "Macro to switch to BUFFER, evaluate FORMS, returns to original buffer.
1077 Differs from `save-excursion' in that it doesn't save the point and mark.
1078 This is essentially `emerge-eval-in-buffer' with the test for live buffers."
1079 (` (let ((StartBuffer (current-buffer)))
1080 (if (ediff-buffer-live-p (, buffer))
1081 (unwind-protect
1082 (progn
1083 (set-buffer (, buffer))
1084 (,@ forms))
1085 (set-buffer StartBuffer))
1086 (beep 1)
1087 (message "You seem to have killed an essential Ediff buffer---quit!"))
1088 )))
1089
1090
1091 ;;; Functions
1092
1093 (defun ediff-mode ()
1094 "Ediff mode is used by the Ediff file-difference package.
1095 It is entered only through one of the following commands:
1096 `ediff'
1097 `ediff-files'
1098 `ediff-buffers'
1099 `epatch'
1100 `ediff-patch-file'
1101 `ediff-patch-buffer'
1102 `epatch-buffer'
1103 `ediff-revision'
1104
1105 Commands:
1106 \\{ediff-mode-map}"
1107 (interactive)
1108 (kill-all-local-variables)
1109 (setq major-mode 'ediff-mode)
1110 (setq mode-name "Ediff"))
1111
1112 (defun ediff-version ()
1113 "Return string describing the version of Ediff.
1114 When called interactively, displays the version."
1115 (interactive)
1116 (if (interactive-p)
1117 (message (ediff-version))
1118 (format "Ediff %s of %s" ediff-version ediff-date)))
1119
1120
1121 ;; Hook variables
1122
1123 (defvar ediff-before-setup-windows-hooks nil
1124 "*Hooks to run before Ediff sets its own window config.
1125 This can be used to save the previous window config, which can be restored
1126 on ediff-quit or ediff-suspend.")
1127 (defvar ediff-startup-hooks nil
1128 "*Hooks to run in the control buffer after Ediff has been set up.")
1129 (defvar ediff-select-hooks nil
1130 "*Hooks to run after a difference has been selected.")
1131 (defvar ediff-unselect-hooks nil
1132 "*Hooks to run after a difference has been unselected.")
1133 (defvar ediff-prepare-buffer-hooks nil
1134 "*Hooks called after buffers A and B are set up.")
1135 (defvar ediff-load-hooks nil
1136 "*Hook run after Ediff is loaded. Can be used to change defaults.")
1137
1138 (defvar ediff-suspend-hooks (list 'ediff-default-suspend-hook)
1139 "*Hooks to run in the Ediff control buffer when Ediff is suspended.")
1140 (defvar ediff-quit-hooks (list 'ediff-default-quit-hook)
1141 "*Hooks to run in the Ediff control buffer after finishing Ediff.")
1142
1143 (make-variable-buffer-local 'local-write-file-hooks)
1144 (make-variable-buffer-local 'before-change-function)
1145
1146 ;; Help messages
1147
1148 (defconst ediff-help-message-long
1149 " Moving around | Toggling features | Miscellaneous
1150 =======================|===========================|===========================
1151 p,DEL -previous diff | s -vert/horiz split | ab/ba -copy diff A->B/B->A
1152 n,SPC -next diff | h -hiliting | ra/rb -restore diff in A/B
1153 j -jump to diff | @ -auto-refining | * -refine diff
1154 ga/gb -to point in A/B |---------------------------| ! -recompute diffs
1155 c -recenter | ## -skip whitespace |---------------------------
1156 v/V -scroll up/down | #f/#h -focus/hide regions | wa/wb -save buf A/B
1157 </> -scroll lft/rght | A/B -read-only buf A/B | wf -save diff output
1158 =======================|===========================|===========================
1159 | bug -submit bug report |
1160 i -status info | ? -toggle help window | z/q -suspend/quit Ediff"
1161 )
1162
1163 (defconst ediff-help-message-short
1164 " ? - toggle help window")
1165
1166 (defvar ediff-help-message ediff-help-message-long
1167 "*The actual help message.")
1168
1169 ;; diff stuff.
1170 (defvar ediff-diff-program "diff"
1171 "*Name of the program that compares two files.")
1172 (defvar ediff-diff-options ""
1173 "*Options to pass to `ediff-diff-program'.
1174 If diff\(1\) is used as `ediff-diff-program', then the most useful options are
1175 `-w', to ignore space, and `-i', to ignore case of letters.")
1176
1177 ;; Fine differences
1178 (defvar ediff-forward-word-function 'ediff-forward-word
1179 "*Function to call to move to the next word.
1180 Used for splitting difference regions into individual words.")
1181
1182 (defvar ediff-fine-diff-program "diff"
1183 "*Name of the program that compares the current diff regions for fine differences.
1184
1185 This program should produce output in the format of diff. One could
1186 possibly use `spiff' here if appropriate options are set.")
1187
1188 (defvar ediff-fine-diff-options ""
1189 "*Options to pass to `ediff-fine-diff-program'.
1190 If diff\(1\) is used as `ediff-diff-program', then the most useful options are
1191 `-w', to ignore space, and `-i', to ignore case of letters.")
1192
1193 (defvar ediff-whitespace " \n\t\C-j"
1194 "*White space. Used to split strings into words.")
1195
1196 (defvar ediff-word-1 "a-zA-Z---_`'.?!:"
1197 "*Characters matching this regexp constitute words of type 1.
1198
1199 Ediff is using a very simple schema for splitting text into words, which is
1200 used to determine fine differences between regions. There are two types of
1201 words. One consists entirely out of characters in `ediff-word-1' and
1202 another out of characters matching `ediff-word-1'.")
1203
1204 (defvar ediff-word-2 "^a-zA-Z---_`'.?!: \t\n\C-j"
1205 "*Characters matching this regexp constitute words of type 2.
1206 See `ediff-word-1' for more details.")
1207
1208 ;; Selective browsing
1209
1210 (ediff-defvar-local ediff-skip-diff-region-function 'ediff-show-all-diffs
1211 "Function that determines the next/previous diff region to show.
1212 Should return t for regions to be ignored and nil otherwise.
1213 This function gets a region number as an argument. The region number
1214 is the one used internally by Ediff. It is 1 less than the number seen
1215 by the user.")
1216
1217 (ediff-defvar-local ediff-regexp-focus-A ""
1218 "Regexp that determines buf A regions to focus on when skipping to diff.")
1219 (ediff-defvar-local ediff-regexp-focus-B ""
1220 "Regexp that determines buf B regions to focus on when skipping to diff.")
1221
1222 (ediff-defvar-local ediff-regexp-hide-A ""
1223 "Regexp that determines buf A regions to ignore when skipping to diff.")
1224 (ediff-defvar-local ediff-regexp-hide-B ""
1225 "Regexp that determines buf B regions to ignore when skipping to diff.")
1226
1227
1228 ;; Support for patches
1229
1230 (defvar ediff-patch-program "patch"
1231 "*Name of the program that applies patches.")
1232 (defvar ediff-patch-options ""
1233 "*Options to pass to ediff-patch-program.")
1234
1235 (defvar ediff-shell (cond ((eq system-type 'emx) "cmd") ;; OS/2
1236 (t "sh")) ;; unix
1237 "*The shell used to run diff and patch. If user's .profile or
1238 .cshrc files are set up correctly, any shell will do. However, some people
1239 set $prompt or other things incorrectly, which leads to undesirable output
1240 messages. These may cause Ediff to fail. In such a case, set ediff-shell
1241 to a shell that you are not using or, better, fix your shell's startup file.")
1242
1243 (defvar ediff-diff-ok-lines-regexp
1244 "^\\([0-9,]+[acd][0-9,]+$\\|[<>] \\|---\\|Warning:\\)"
1245 "Regexp that matches normal output lines from `ediff-diff-program'.
1246 This is mostly lifted from Emerge, except that Ediff also considers the
1247 'Missing newline' message to be 'normal output.'
1248 Lines that do not match are assumed to be error messages.")
1249
1250 (defvar ediff-fine-diff-ok-lines-regexp
1251 "^\\([0-9,]+[acd][0-9,]+$\\|[<>] \\|---\\|Warning:\\)"
1252 "Regexp that matches normal output lines from `ediff-fine-diff-program'.
1253 This is mostly lifted from Emerge, except that Ediff also considers the
1254 'Missing newline' message to be 'normal output.'
1255 Lines that do not match are assumed to be error messages.")
1256
1257 (defvar ediff-match-diff-line (let ((x "\\([0-9]+\\)\\(\\|,\\([0-9]+\\)\\)"))
1258 (concat "^" x "\\([acd]\\)" x "$"))
1259 "Pattern to match lines produced by diff that describe differences.")
1260
1261 (defvar ediff-patch-buf nil
1262 "The buffer of the patch file.")
1263 (defvar ediff-patch-diagnostics nil
1264 "The buffer where patch would display its diagnostics.")
1265
1266
1267
1268 ;; Copying difference regions between buffers.
1269 (ediff-defvar-local ediff-killed-diffs-alist nil
1270 "A list of killed diffs.
1271 A diff is saved here if it is replaced by a diff
1272 from another buffer. This alist has the form:
1273 \((num (A . diff) (B . diff)) ...),
1274 where A or B parts may be missing.")
1275
1276
1277 ;; Highlighting
1278 (defvar ediff-before-flag-bol
1279 ;"vvvvvvvvvvvvvvvv---- ediff ----vvvvvvvvvvvvvvv\n"
1280 ">>--->>>\n"
1281 "*Flag placed above the highlighted block of differences.
1282 Must end with newline. Must be set before Ediff is loaded.")
1283 (defvar ediff-after-flag-bol
1284 ;"^^^^^^^^^^^^^^^^---- ediff ----^^^^^^^^^^^^^^^\n"
1285 "<<<---<<\n"
1286 "*Flag placed below the highlighted block of differences.
1287 Must end with newline. Must be set before Ediff is loaded.")
1288
1289 (defvar ediff-before-flag-mol ">>--->>>"
1290 "*Like ediff-before-flag, used when a difference starts in mid-line.")
1291 (defvar ediff-after-flag-mol "<<<---<<"
1292 "*Like ediff-after-flag, used when a difference starts in mid-line.")
1293
1294 (ediff-defvar-local ediff-before-flag-A nil
1295 "This is the actual ASCII before-flag in effect in buffer A.
1296 It is either `ediff-before-flag-mol' or `ediff-before-flag-bol' depending
1297 on whether the selected difference region starts in the middle of a line
1298 or at the beginning of a line.")
1299 (ediff-defvar-local ediff-after-flag-A nil
1300 "This is the actual ASCII after-flag in effect in buffer A.
1301 It is either `ediff-before-flag-mol' or `ediff-before-flag-bol' depending
1302 on whether the selected difference region starts in the middle of a line
1303 or at the beginning of a line.")
1304 (ediff-defvar-local ediff-before-flag-B nil
1305 "This is the actual ASCII before-flag in effect in buffer B.
1306 It is either `ediff-before-flag-mol' or `ediff-before-flag-bol' depending
1307 on whether the selected difference region starts in the middle of a line
1308 or at the beginning of a line.")
1309 (ediff-defvar-local ediff-after-flag-B nil
1310 "This is the actual ASCII after-flag in effect in buffer B.
1311 It is either `ediff-before-flag-mol' or `ediff-before-flag-bol' depending
1312 on whether the selected difference region starts in the middle of a line
1313 or at the beginning of a line.")
1314
1315
1316 (ediff-defvar-local ediff-want-faces t
1317 "If t, differences are highlighted using faces on a window system.
1318 If nil, they are highlighted using ASCII flags, ediff-before-flag
1319 and ediff-after-flag. On a non-window system, differences are always
1320 highlighted using ASCII flags.
1321
1322 This variable can be set either in .emacs or toggled interactively, using
1323 ediff-toggle-hilit.")
1324
1325 (ediff-defvar-local ediff-want-default-menus t
1326 "If t, Ediff will set up menus in the menu bar.
1327 This variable must be set before Ediff is loaded. If you don't like the
1328 look of the default menus, set this variable to nil and make your own
1329 menus.")
1330
1331 (ediff-defvar-local ediff-auto-refine (if window-system 'on 'nix)
1332 "If `'on', Ediff auto-highlights fine diffs for the current diff region.
1333 If `off', auto-highlighting is not used. If `'nix', no fine diffs are shown
1334 at all, unless the user force-refines the region by hitting `*'.
1335
1336 This variable can be set either in .emacs or toggled interactively, using
1337 ediff-toggle-hilit.")
1338
1339 (ediff-defvar-local ediff-ignore-similar-regions nil
1340 "*If t, skip over difference regions that differ only in the white space and line breaks.")
1341
1342 (ediff-defvar-local ediff-auto-refine-limit 700
1343 "Auto-refine only those regions that are smaller than this number of bytes.")
1344
1345 (ediff-defvar-local ediff-highlight-all-diffs t
1346 "If nil, only the selected differences are highlighted.
1347 This variable can be set either in .emacs or toggled interactively, using
1348 ediff-toggle-hilit.")
1349
1350 (ediff-defvar-local ediff-highlighting-style nil
1351 "A var local to each control panel buffer.
1352 Indicates highlighting style in effect for this buffer: `face', `ascii',
1353 nil -- temporarily unhighlighted, `off' -- turned off \(on a dumb
1354 terminal only\).")
1355
1356
1357
1358 ;; Variables that control each Ediff session. They are local to the
1359 ;; control buffer.
1360
1361 ;; Mode variables
1362 (ediff-defvar-local ediff-A-buffer nil
1363 "The buffer in which the A variant is stored.")
1364 (ediff-defvar-local ediff-B-buffer nil
1365 "The buffer in which the B variant is stored.")
1366 (ediff-defvar-local ediff-control-buffer nil
1367 "The control buffer of ediff. ")
1368
1369 ;(ediff-defvar-local ediff-control-buffer-suffix nil
1370 ; "The suffix of the control buffer name. ")
1371
1372 (ediff-defvar-local ediff-control-window nil
1373 "The control window.")
1374 (ediff-defvar-local ediff-window-config-saved ""
1375 "Ediff's window configuration.
1376 Used to minimize the need to rearrange windows.")
1377
1378
1379 (ediff-defvar-local ediff-A-buffer-values nil
1380 "Keeps working values of ediff-saved-variables for ediff-A-buffer.")
1381 (ediff-defvar-local ediff-B-buffer-values nil
1382 "Keeps working values of ediff-saved-variables for ediff-B-buffer.")
1383
1384 (ediff-defvar-local ediff-A-buffer-values-setup nil
1385 "Remembers ediff-saved-variables for ediff-A-buffer as they were at setup.")
1386 (ediff-defvar-local ediff-B-buffer-values-setup nil
1387 "Remembers ediff-saved-variables for ediff-B-buffer as they were at setup.")
1388
1389 (ediff-defvar-local ediff-difference-vector nil
1390 "Vector of differences between the variants.
1391 Each difference is represented by a vector of two overlays. The first
1392 overlays the difference section in the A buffer and the second overlays the
1393 diff in the B buffer. If a difference section is empty, the corresponding
1394 overlay's endpoints coincide. ")
1395
1396 (ediff-defvar-local ediff-current-difference -1
1397 "The difference that is currently selected.")
1398 (ediff-defvar-local ediff-number-of-differences nil
1399 "Number of differences found.")
1400
1401 (ediff-defvar-local ediff-diff-buffer nil
1402 "Buffer containing the output of diff, which is used by Ediff to step
1403 through files.")
1404 (ediff-defvar-local ediff-fine-diff-buffer nil
1405 "Buffer used for diff-style fine differences between regions.")
1406 (ediff-defvar-local ediff-tmp-buffer nil
1407 "Temporary buffer used for computing fine differences.")
1408 (ediff-defvar-local ediff-error-buffer nil
1409 "Buffer containing the output of diff when diff returns errors.")
1410
1411 (ediff-defvar-local ediff-this-buffer-control-sessions nil
1412 "List of ediff control panels associated with each buffer A/B.")
1413
1414 (defvar ediff-disturbed-overlays nil
1415 "List of difference overlays disturbed by working with the current diff.")
1416
1417 (defvar ediff-shaded-overlay-priority 100
1418 "Priority of non-selected overlays.")
1419
1420
1421 (if (ediff-if-lucid)
1422 (progn
1423 (fset 'ediff-overlayp (symbol-function 'extentp))
1424 (fset 'ediff-make-overlay (symbol-function 'make-extent))
1425 (fset 'ediff-delete-overlay (symbol-function 'delete-extent))
1426 ;;(fset 'ediff-overlay-put (symbol-function 'set-extent-property))
1427 ;;(fset 'ediff-move-overlay (symbol-function 'set-extent-endpoints))
1428 (fset 'ediff-overlay-buffer (symbol-function 'extent-buffer))
1429 (fset 'ediff-overlay-start (symbol-function 'extent-start-position))
1430 (fset 'ediff-overlay-end (symbol-function 'extent-end-position))
1431 (fset 'ediff-overlay-get (symbol-function 'extent-property)))
1432 (fset 'ediff-overlayp (symbol-function 'overlayp))
1433 (fset 'ediff-make-overlay (symbol-function 'make-overlay))
1434 (fset 'ediff-delete-overlay (symbol-function 'delete-overlay))
1435 ;;(fset 'ediff-overlay-put (symbol-function 'overlay-put))
1436 ;;(fset 'ediff-move-overlay (symbol-function 'move-overlay))
1437 (fset 'ediff-overlay-buffer (symbol-function 'overlay-buffer))
1438 (fset 'ediff-overlay-start (symbol-function 'overlay-start))
1439 (fset 'ediff-overlay-end (symbol-function 'overlay-end))
1440 (fset 'ediff-overlay-get (symbol-function 'overlay-get)))
1441
1442 (if window-system
1443 (if (ediff-if-lucid)
1444 (progn
1445 (fset 'ediff-select-frame (symbol-function 'select-screen))
1446 (fset 'ediff-window-frame (symbol-function 'window-screen))
1447 (fset 'ediff-display-color-p (symbol-function 'x-color-display-p))
1448 (fset 'ediff-valid-color-p (symbol-function 'x-valid-color-name-p))
1449 (fset 'ediff-get-face (symbol-function 'get-face)))
1450 (fset 'ediff-window-frame (symbol-function 'window-frame))
1451 (fset 'ediff-select-frame (symbol-function 'select-frame))
1452 (fset 'ediff-display-color-p (symbol-function 'x-display-color-p))
1453
1454 ;; This is a temporary fix for OS/2 users
1455 ;; pm-win.el in PM-Emacs should be fixed.
1456 (if (eq window-system 'pm)
1457 (fset 'ediff-valid-color-p
1458 (function (lambda (color) (assoc color pm-color-alist))))
1459 (fset 'ediff-valid-color-p (symbol-function 'x-color-defined-p))
1460 )
1461
1462 (fset 'ediff-get-face (symbol-function 'internal-get-face)))
1463 ;; not a window system
1464 (fset 'ediff-window-frame (function (lambda (wind) (if wind 1 nil)) ))
1465 (fset 'ediff-select-frame (symbol-function 'identity))
1466 (fset 'ediff-make-current-diff-overlay (function (lambda (type) nil)))
1467 (fset 'ediff-unhighlight-diffs-totally (function (lambda () nil))))
1468
1469
1470 (if (not window-system)
1471 ()
1472 (defun ediff-set-face (ground face color)
1473 "Sets face foreground/background."
1474 (if (ediff-valid-color-p color)
1475 (if (eq ground 'foreground)
1476 (set-face-foreground face color)
1477 (set-face-background face color))
1478 (cond ((memq face
1479 '(ediff-current-diff-face-A ediff-current-diff-face-B))
1480 (copy-face 'highlight face))
1481 ((memq face
1482 '(ediff-fine-diff-face-A ediff-fine-diff-face-B))
1483 (copy-face 'secondary-selection face)
1484 (set-face-underline-p face t))
1485 ((memq face
1486 '(ediff-odd-diff-face-A ediff-odd-diff-face-B
1487 ediff-even-diff-face-A ediff-even-diff-face-B))
1488 (copy-face 'secondary-selection face)))))
1489
1490 (defvar ediff-current-diff-face-A
1491 (progn
1492 (make-face 'ediff-current-diff-face-A)
1493 (or (face-differs-from-default-p 'ediff-current-diff-face-A)
1494 (cond ((ediff-display-color-p)
1495 (ediff-set-face
1496 'foreground 'ediff-current-diff-face-A "firebrick")
1497 (ediff-set-face
1498 'background 'ediff-current-diff-face-A "pale green"))
1499 (t
1500 (if (ediff-if-lucid)
1501 (copy-face 'modeline 'ediff-current-diff-face-A)
1502 (copy-face 'highlight 'ediff-current-diff-face-A))
1503 )))
1504 'ediff-current-diff-face-A)
1505 ;;(ediff-get-face 'ediff-current-diff-face-A))
1506 "Face for highlighting the selected difference in buffer A.")
1507
1508 (defvar ediff-current-diff-face-B
1509 (progn
1510 (make-face 'ediff-current-diff-face-B)
1511 (or (face-differs-from-default-p 'ediff-current-diff-face-B)
1512 (cond ((ediff-display-color-p)
1513 (ediff-set-face
1514 'foreground 'ediff-current-diff-face-B "DarkOrchid")
1515 (ediff-set-face
1516 'background 'ediff-current-diff-face-B "Yellow"))
1517 (t
1518 (if (ediff-if-lucid)
1519 (copy-face 'modeline 'ediff-current-diff-face-B)
1520 (copy-face 'highlight 'ediff-current-diff-face-B))
1521 )))
1522 'ediff-current-diff-face-B)
1523 ;;(ediff-get-face 'ediff-current-diff-face-B))
1524 "Face for highlighting the selected difference in buffer B.")
1525
1526 (defvar ediff-fine-diff-face-A
1527 (progn
1528 (make-face 'ediff-fine-diff-face-A)
1529 (or (face-differs-from-default-p 'ediff-fine-diff-face-A)
1530 (cond ((ediff-display-color-p)
1531 (ediff-set-face 'foreground 'ediff-fine-diff-face-A
1532 "Navy")
1533 (ediff-set-face 'background 'ediff-fine-diff-face-A
1534 "sky blue"))
1535 (t (set-face-underline-p 'ediff-fine-diff-face-A t))))
1536 'ediff-fine-diff-face-A)
1537 ;;(ediff-get-face 'ediff-fine-diff-face-A))
1538 "Face for highlighting the refinement of the selected diff in buffer A.")
1539
1540 (defvar ediff-fine-diff-face-B
1541 (progn
1542 (make-face 'ediff-fine-diff-face-B)
1543 (or (face-differs-from-default-p 'ediff-fine-diff-face-B)
1544 (cond ((ediff-display-color-p)
1545 (ediff-set-face 'foreground 'ediff-fine-diff-face-B "Black")
1546 (ediff-set-face 'background 'ediff-fine-diff-face-B "cyan"))
1547 (t (set-face-underline-p 'ediff-fine-diff-face-B t))))
1548 'ediff-fine-diff-face-B)
1549 ;;(ediff-get-face 'ediff-fine-diff-face-B))
1550 "Face for highlighting the refinement of the selected diff in buffer B.")
1551
1552
1553 (defvar ediff-even-diff-face-A
1554 (progn
1555 (make-face 'ediff-even-diff-face-A)
1556 (or (face-differs-from-default-p 'ediff-even-diff-face-A)
1557 (cond ((ediff-display-color-p)
1558 (ediff-set-face
1559 'foreground 'ediff-even-diff-face-A "black")
1560 (ediff-set-face
1561 'background 'ediff-even-diff-face-A "light grey"))
1562 (t
1563 (copy-face 'italic 'ediff-even-diff-face-A))))
1564 'ediff-even-diff-face-A)
1565 ;;(ediff-get-face 'ediff-even-diff-face-A))
1566 "Face used to highlight even-numbered differences in buffer A.")
1567
1568 (defvar ediff-even-diff-face-B
1569 (progn
1570 (make-face 'ediff-even-diff-face-B)
1571 (or (face-differs-from-default-p 'ediff-even-diff-face-B)
1572 (cond ((ediff-display-color-p)
1573 (ediff-set-face
1574 'foreground 'ediff-even-diff-face-B "White")
1575 (ediff-set-face
1576 'background 'ediff-even-diff-face-B "Gray"))
1577 (t
1578 (copy-face 'italic 'ediff-even-diff-face-B))))
1579 'ediff-even-diff-face-B)
1580 ;;(ediff-get-face 'ediff-even-diff-face-B))
1581 "Face used to highlight even-numbered differences in buffer B.")
1582
1583 (defvar ediff-odd-diff-face-A
1584 (progn
1585 (make-face 'ediff-odd-diff-face-A)
1586 (or (face-differs-from-default-p 'ediff-odd-diff-face-A)
1587 (cond ((ediff-display-color-p)
1588 (ediff-set-face
1589 'foreground 'ediff-odd-diff-face-A "White")
1590 (ediff-set-face
1591 'background 'ediff-odd-diff-face-A "Gray"))
1592 (t
1593 (copy-face 'italic 'ediff-odd-diff-face-A))))
1594 'ediff-odd-diff-face-A)
1595 ;;(ediff-get-face 'ediff-odd-diff-face-A))
1596 "Face used to highlight odd-numbered differences in buffer A.")
1597
1598 (defvar ediff-odd-diff-face-B
1599 (progn
1600 (make-face 'ediff-odd-diff-face-B)
1601 (or (face-differs-from-default-p 'ediff-odd-diff-face-B)
1602 (cond ((ediff-display-color-p)
1603 (ediff-set-face
1604 'foreground 'ediff-odd-diff-face-B "Black")
1605 (ediff-set-face
1606 'background 'ediff-odd-diff-face-B "light grey"))
1607 (t
1608 (copy-face 'italic 'ediff-odd-diff-face-B))))
1609 'ediff-odd-diff-face-B)
1610 ;;(ediff-get-face 'ediff-odd-diff-face-B))
1611 "Face used to highlight odd-numbered differences in buffer B.")
1612
1613 ;; Create *-var faces. These are the actual faces used to highlight
1614 ;; odd-numbered difference regions.
1615 ;; They are used as follows: when highlighting is turned on,
1616 ;; ediff-odd/even-diff-face-A/B are copied
1617 ;; into ediff-odd/even-diff-face-A/B-var, and all odd/even overlays become
1618 ;; highlighted. When highlighting is turned off, then the face 'default is
1619 ;; copied into ediff-odd/even-diff-face-A/B-var, thereby unhighlighting all
1620 ;; difference regions.
1621 (make-face 'ediff-even-diff-face-A-var)
1622 (make-face 'ediff-even-diff-face-B-var)
1623 (make-face 'ediff-odd-diff-face-A-var)
1624 (make-face 'ediff-odd-diff-face-B-var)
1625
1626 ;; initialize *-var faces
1627 (defun ediff-init-var-faces ()
1628 (copy-face (if (and ediff-want-faces ediff-highlight-all-diffs)
1629 ediff-even-diff-face-A 'default)
1630 'ediff-even-diff-face-A-var)
1631 (copy-face (if (and ediff-want-faces ediff-highlight-all-diffs)
1632 ediff-even-diff-face-B 'default)
1633 'ediff-even-diff-face-B-var)
1634 (copy-face (if (and ediff-want-faces ediff-highlight-all-diffs)
1635 ediff-odd-diff-face-A 'default)
1636 'ediff-odd-diff-face-A-var)
1637 (copy-face (if (and ediff-want-faces ediff-highlight-all-diffs)
1638 ediff-odd-diff-face-B 'default)
1639 'ediff-odd-diff-face-B-var))
1640
1641
1642 ;;; Overlays
1643
1644 (ediff-defvar-local ediff-current-diff-overlay-A nil
1645 "Overlay specifying the current difference region in buffer A.")
1646 (ediff-defvar-local ediff-current-diff-overlay-B nil
1647 "Overlay specifying the current difference region in buffer B.")
1648
1649 (defun ediff-make-current-diff-overlay (type)
1650 (let ((overlay (if (eq type 'A)
1651 'ediff-current-diff-overlay-A
1652 'ediff-current-diff-overlay-B))
1653 (buffer (ediff-get-buffer type))
1654 (face (if (eq type 'A)
1655 (face-name ediff-current-diff-face-A)
1656 (face-name ediff-current-diff-face-B))))
1657 (set overlay (ediff-make-overlay (point-max) (point-max) buffer))
1658 (ediff-overlay-put (eval overlay) 'face face)
1659 (ediff-overlay-put (eval overlay) 'ediff ediff-control-buffer)
1660 ))
1661
1662 ;; Compute priority of ediff overlay.
1663 (defun ediff-highest-priority (start end buffer)
1664 (let ((pos (max 1 (1- start)))
1665 ovr-list)
1666 (if (ediff-if-lucid)
1667 (1+ ediff-shaded-overlay-priority)
1668 (ediff-eval-in-buffer
1669 buffer
1670 (while (< pos (min (point-max) (1+ end)))
1671 (setq ovr-list (append (overlays-at pos) ovr-list))
1672 (setq pos (next-overlay-change pos)))
1673 (1+ (eval
1674 (cons '+
1675 (mapcar (function
1676 (lambda (ovr)
1677 (if ovr
1678 (or (ediff-overlay-get ovr 'priority) 0)
1679 0)))
1680 ovr-list)
1681 )))
1682 ))))
1683
1684 ) ; end of window-system-only code.
1685
1686
1687 ;; Ediff toggle read-only stuff
1688 (defvar ediff-toggle-read-only-function nil
1689 "*Specifies the function to be used to toggle read-only.
1690 If nil, Ediff tries to deduce the function from the binding of C-x C-q.
1691 Normally, this is the `toggle-read-only' function, but, if version
1692 control is used, it could be `vc-toggle-read-only' or `rcs-toggle-read-only'.")
1693
1694 (ediff-defvar-local ediff-local-checkout-flag nil
1695 "If t, indicates that buffer has been already checked out.")
1696
1697
1698
1699 ;;; Misc
1700
1701 (defvar ediff-split-window-function 'split-window-vertically
1702 "*The function to split the main window between buffer-A and buffer-B.
1703 You can set it to be split horizontally instead of the
1704 default vertical split by setting this variable to
1705 'split-window-horizontally. You can also have your own function for fancy
1706 splits. This variable has no effect when buffer-A and buffer-B are shown in
1707 different frames. In this case, Ediff will use those frames to display
1708 these buffers.")
1709
1710
1711 (defconst ediff-saved-variables
1712 '(;;buffer-read-only
1713 buffer-auto-save-file-name)
1714 "Buffer-local variables saved and restored during an Ediff session.")
1715
1716 ;;(defconst ediff-working-values '(nil nil)
1717 (defconst ediff-working-values '(nil)
1718 "Values to be assigned to `ediff-saved-variables' during diff.")
1719 1696
1720 (defvar ediff-use-last-dir nil 1697 (defvar ediff-use-last-dir nil
1721 "*If t, Ediff uses previous directory as default when reading file name.") 1698 "*If t, Ediff uses previous directory as default when reading file name.")
1722
1723 (defvar ediff-no-help-in-control-buffer nil
1724 "*Non-nil means C-h should not invoke Emacs help in control buffer.
1725 Instead, C-h jumps to previous difference.")
1726
1727 (defvar ediff-version-control-package 'vc
1728 "Version control package used.
1729 Currently, Ediff supports vc.el and rcs.el.")
1730
1731 (defvar ediff-temp-file-prefix
1732 (let ((env (or (getenv "TMPDIR")
1733 (getenv "TMP")
1734 (getenv "TEMP")))
1735 d)
1736 (setq d (if (and env (> (length env) 0))
1737 env
1738 "/tmp"))
1739 (if (= (aref d (1- (length d))) ?/)
1740 (setq d (substring d 0 -1)))
1741 (concat d "/ediff"))
1742 "*Prefix to put on Ediff temporary file names.
1743 Do not start with `~/' or `~user-name/'.")
1744
1745 (defvar ediff-temp-file-mode 384 ; u=rw only
1746 "*Mode for Ediff temporary files.")
1747
1748 (ediff-defvar-local ediff-temp-file-A nil
1749 "Temporary file used for refining difference regions in buffer B.")
1750 (ediff-defvar-local ediff-temp-file-B nil
1751 "Temporary file used for refining difference regions in buffer B.")
1752 1699
1753 (defvar ediff-last-dir-A nil 1700 (defvar ediff-last-dir-A nil
1754 "Last directory used by an Ediff command for file-A.") 1701 "Last directory used by an Ediff command for file-A.")
1755 (defvar ediff-last-dir-B nil 1702 (defvar ediff-last-dir-B nil
1756 "Last directory used by an Ediff command for file-B.") 1703 "Last directory used by an Ediff command for file-B.")
1704 (defvar ediff-last-dir-C nil
1705 "Last directory used by an Ediff command for file-C.")
1706 (defvar ediff-last-dir-ancestor nil
1707 "Last directory used by an Ediff command for the ancestor file.")
1757 (defvar ediff-last-dir-patch nil 1708 (defvar ediff-last-dir-patch nil
1758 "Last directory used by an Ediff command for file to patch.") 1709 "Last directory used by an Ediff command for file to patch.")
1759 1710
1760 ;; Build keymaps 1711 ;;; Patching
1761
1762 (defvar ediff-mode-map nil
1763 "Local keymap used in Ediff mode.")
1764
1765 (defun ediff-frame-has-menubar ()
1766 (if (ediff-if-lucid)
1767 current-menubar
1768 (< 0 (cdr (assq 'menu-bar-lines (frame-parameters (selected-frame)))))
1769 ))
1770
1771 ;;; This is split in three parts to avoid
1772 ;;; making a line in loaddefs.el that is too long for patch.
1773 ;;; Note that autoload.el currently looks for cookies
1774 ;;; only at top level in the file.
1775 ;;; So I moved these to top level. But the conditionals on
1776 ;;; purify-flag make these no-ops when you load ediff.
1777 ;;; They only do something in loaddefs.el.
1778 ;;;###autoload
1779 (if purify-flag
1780 (progn
1781 (defvar menu-bar-epatch-menu (make-sparse-keymap "Epatch"))
1782 (fset 'menu-bar-epatch-menu (symbol-value 'menu-bar-epatch-menu))
1783 (defvar menu-bar-ediff-menu (make-sparse-keymap "Ediff"))
1784 (fset 'menu-bar-ediff-menu (symbol-value 'menu-bar-ediff-menu))))
1785
1786
1787 ;;;###autoload
1788 (if purify-flag
1789 (progn
1790 (define-key menu-bar-ediff-menu [ediff-revision]
1791 '("File with a version ..." . ediff-revision))
1792 (define-key menu-bar-ediff-menu [ediff-buffers]
1793 '("Buffers ..." . ediff-buffers))
1794 (define-key menu-bar-ediff-menu [ediff-files]
1795 '("Files ..." . ediff-files))))
1796
1797 ;;;###autoload
1798 (if purify-flag
1799 (progn
1800 (define-key menu-bar-epatch-menu [ediff-patch-buffer]
1801 '("To a Buffer ..." . ediff-patch-buffer))
1802 (define-key menu-bar-epatch-menu [ediff-patch-file]
1803 '("To a File ..." . ediff-patch-file))))
1804
1805
1806 (if (and window-system ediff-want-default-menus (ediff-frame-has-menubar))
1807 (cond ((ediff-if-lucid)
1808 (defvar ediff-menu
1809 '(""
1810 ["Files ..." ediff-files t]
1811 ["Buffers ..." ediff-buffers t]
1812 ["File with a version ..." ediff-revision t]))
1813 (defvar epatch-menu
1814 '(""
1815 ["To a file ..." ediff-patch-file t]
1816 ["To a buffer ..." ediff-patch-buffer t]))
1817 (add-menu '("File") "Compare"
1818 ediff-menu
1819 "New Screen")
1820 (add-menu '("File") "Apply Patch"
1821 epatch-menu
1822 "New Screen")
1823 ;; Display a solid horizontal line
1824 (add-menu-item '("File") "---" nil nil "New Screen"))
1825 (t ;; FSF Emacs
1826 (define-key menu-bar-file-menu [epatch]
1827 '("Apply Patch" . menu-bar-epatch-menu))
1828 (define-key menu-bar-file-menu [ediff]
1829 '("Compare" . menu-bar-ediff-menu)))))
1830
1831
1832
1833 (defun ediff-setup-keymap ()
1834 "Set up the keymap used in the control buffer of Ediff."
1835 (setq ediff-mode-map (make-sparse-keymap))
1836 (suppress-keymap ediff-mode-map)
1837
1838 (define-key ediff-mode-map "p" 'ediff-previous-difference)
1839 (define-key ediff-mode-map "\C-?" 'ediff-previous-difference)
1840 (define-key ediff-mode-map "\C-h" (if ediff-no-help-in-control-buffer
1841 'ediff-previous-difference nil))
1842 (define-key ediff-mode-map "n" 'ediff-next-difference)
1843 (define-key ediff-mode-map " " 'ediff-next-difference)
1844 (define-key ediff-mode-map "j" 'ediff-jump-to-difference)
1845 (define-key ediff-mode-map "g" nil)
1846 (define-key ediff-mode-map "ga" 'ediff-jump-to-difference-at-point)
1847 (define-key ediff-mode-map "gb" 'ediff-jump-to-difference-at-point)
1848 (define-key ediff-mode-map "q" 'ediff-quit)
1849 (define-key ediff-mode-map "z" 'ediff-suspend)
1850 (define-key ediff-mode-map "c" 'ediff-recenter)
1851 (define-key ediff-mode-map "s" 'ediff-toggle-split)
1852 (define-key ediff-mode-map "h" 'ediff-toggle-hilit)
1853 (define-key ediff-mode-map "@" 'ediff-toggle-autorefine)
1854 (define-key ediff-mode-map "v" 'ediff-scroll-up)
1855 (define-key ediff-mode-map "\C-v" 'ediff-scroll-up)
1856 (define-key ediff-mode-map "^" 'ediff-scroll-down)
1857 (define-key ediff-mode-map "\M-v" 'ediff-scroll-down)
1858 (define-key ediff-mode-map "V" 'ediff-scroll-down)
1859 (define-key ediff-mode-map "<" 'ediff-scroll-left)
1860 (define-key ediff-mode-map ">" 'ediff-scroll-right)
1861 (define-key ediff-mode-map "i" 'ediff-status-info)
1862 (define-key ediff-mode-map "?" 'ediff-toggle-help)
1863 (define-key ediff-mode-map "!" 'ediff-recompute-diffs)
1864 (define-key ediff-mode-map "*" 'ediff-make-fine-diffs)
1865 (define-key ediff-mode-map "a" nil)
1866 (define-key ediff-mode-map "ab" 'ediff-diff-to-diff)
1867 (define-key ediff-mode-map "b" nil)
1868 (define-key ediff-mode-map "ba" 'ediff-diff-to-diff)
1869 (define-key ediff-mode-map "bug" 'ediff-submit-report)
1870 (define-key ediff-mode-map "r" nil)
1871 (define-key ediff-mode-map "ra" 'ediff-restore-diff)
1872 (define-key ediff-mode-map "rb" 'ediff-restore-diff)
1873 (define-key ediff-mode-map "#" nil)
1874 (define-key ediff-mode-map "#h" 'ediff-toggle-regexp-match)
1875 (define-key ediff-mode-map "#f" 'ediff-toggle-regexp-match)
1876 (define-key ediff-mode-map "##" 'ediff-toggle-skip-similar)
1877 (define-key ediff-mode-map "o" nil)
1878 (define-key ediff-mode-map "A" 'ediff-toggle-read-only)
1879 (define-key ediff-mode-map "B" 'ediff-toggle-read-only)
1880 (define-key ediff-mode-map "w" nil)
1881 (define-key ediff-mode-map "wa" 'ediff-save-buffer)
1882 (define-key ediff-mode-map "wb" 'ediff-save-buffer)
1883 (define-key ediff-mode-map "wf" 'ediff-save-buffer)
1884 (define-key ediff-mode-map "k" nil)
1885 (define-key ediff-mode-map "kkk" 'ediff-reload-keymap) ;; for debugging
1886 ;; Allow ediff-mode-map to be referenced indirectly
1887 (fset 'ediff-mode-map ediff-mode-map))
1888
1889
1890 ;;; Setup functions
1891
1892 (defun ediff-find-file (file-var buffer &optional last-dir hooks-var)
1893 "Visit FILE and arrange its buffer to Ediff's liking.
1894 FILE is actually a variables symbol that must contain a true file name.
1895 BUFFER is a variable symbol, which will get the buffer object into which
1896 FILE is read. LAST-DIR is the directory variable symbol where FILE's
1897 directory name should be returned. HOOKS is a variable symbol that will be
1898 assigned the hook to be executed after `ediff-strartup' is finished.
1899 `ediff-find-file' arranges that the temp files it might create will be
1900 deleted.
1901 Arguments: (file buffer &optional last-dir hooks)"
1902 (let* ((file (eval file-var))
1903 (file-magic (ediff-find-file-name-handler file)))
1904 (if (not (file-readable-p file))
1905 (error "File `%s' does not exist or is not readable" file))
1906
1907 ;; Record the directory of the file
1908 (if last-dir
1909 (set last-dir (expand-file-name (file-name-directory file))))
1910
1911 ;; Setup the buffer
1912 (set buffer (find-file-noselect file))
1913
1914 (ediff-eval-in-buffer
1915 (eval buffer)
1916 (widen) ;; Make sure the entire file is seen
1917 (cond (file-magic ;; file has handler, such as jka-compr-handler or
1918 ;; ange-ftp-hook-function--arrange for temp file
1919 (ediff-verify-file-buffer 'magic)
1920 (setq file (ediff-make-temp-file))
1921 (set hooks-var (cons (` (lambda () (delete-file (, file))))
1922 (eval hooks-var))))
1923 ;; file processed via auto-mode-alist, a la uncompress.el
1924 ((not (equal (file-truename file)
1925 (file-truename (buffer-file-name))))
1926 (setq file (ediff-make-temp-file))
1927 (set hooks-var (cons (` (lambda () (delete-file (, file))))
1928 (eval hooks-var))))
1929 (t ;; plain file---just check that the file matches the buffer
1930 (ediff-verify-file-buffer))))
1931 (set file-var file)))
1932
1933 (defun ediff-files-internal (file-A file-B &optional startup-hooks)
1934 (let (buffer-A buffer-B)
1935 (message "Reading file %s ... " file-A)(sit-for 0)
1936 (ediff-find-file 'file-A 'buffer-A 'ediff-last-dir-A 'startup-hooks)
1937 (message "Reading file %s ... " file-B)(sit-for 0)
1938 (ediff-find-file 'file-B 'buffer-B 'ediff-last-dir-B 'startup-hooks)
1939 (ediff-setup buffer-A file-A buffer-B file-B startup-hooks)))
1940
1941 (defun ediff-get-patch-buffer (dir)
1942 "Obtain patch buffer. If patch is already in a buffer---use it.
1943 Else, read patch file into a new buffer."
1944 (if (y-or-n-p "Is the patch file already in a buffer? ")
1945 (setq ediff-patch-buf
1946 (get-buffer (read-buffer "Patch buffer name: " nil t))) ;must match
1947 (setq ediff-patch-buf
1948 (find-file-noselect (read-file-name "Patch file name: " dir))))
1949
1950 ;; secure the patch buffer against accidental changes
1951 (ediff-eval-in-buffer
1952 ediff-patch-buf
1953 (setq buffer-read-only t))
1954
1955 (setq ediff-patch-diagnostics
1956 (get-buffer-create "*ediff patch diagnostics*"))
1957 (ediff-eval-in-buffer
1958 ediff-patch-diagnostics
1959 (insert-buffer ediff-patch-buf))
1960 )
1961
1962 ;; Start up Ediff on two files
1963 (defun ediff-setup (buffer-A file-A buffer-B file-B startup-hooks)
1964 (setq file-A (expand-file-name file-A))
1965 (setq file-B (expand-file-name file-B))
1966 (let* ((control-buffer-name
1967 (emerge-unique-buffer-name "Ediff Control Panel" ""))
1968 (control-buffer (ediff-eval-in-buffer
1969 buffer-A
1970 (get-buffer-create control-buffer-name))))
1971 (ediff-eval-in-buffer
1972 control-buffer
1973 (ediff-mode) ;; in control buffer only
1974 (setq buffer-read-only nil) ;; in control buffer only
1975 (setq ediff-A-buffer buffer-A)
1976 (setq ediff-B-buffer buffer-B)
1977 (setq ediff-control-buffer control-buffer)
1978 ; (setq ediff-control-buffer-suffix
1979 ; (if (string-match "<[0-9]*>" control-buffer-name)
1980 ; (substring control-buffer-name
1981 ; (match-beginning 0) (match-end 0))
1982 ; "<1>"))
1983 (setq ediff-error-buffer (get-buffer-create (emerge-unique-buffer-name
1984 "*ediff-errors" "*")))
1985 (ediff-remember-buffer-characteristics t) ;; remember at setup
1986
1987 (ediff-set-keys)
1988 (setq ediff-difference-vector (ediff-setup-diff-regions file-A file-B))
1989 (setq ediff-number-of-differences (length ediff-difference-vector))
1990 (setq ediff-current-difference -1)
1991 (ediff-make-current-diff-overlay 'A)
1992 (ediff-make-current-diff-overlay 'B)
1993 (if window-system
1994 (ediff-init-var-faces))
1995 (run-hooks 'ediff-before-setup-windows-hooks)
1996 (ediff-setup-windows buffer-A buffer-B control-buffer t)
1997
1998 ;; all these must be inside ediff-eval-in-buffer control-buffer,
1999 ;; since these vars are local to control-buffer
2000 ;; These won't run if there are errors in diff
2001 (ediff-eval-in-buffer
2002 ediff-A-buffer
2003 (add-hook 'local-write-file-hooks 'ediff-block-write-file)
2004 (setq before-change-function 'ediff-before-change-guard)
2005 ;; add control-buffer to the list of sessions
2006 (or (memq control-buffer ediff-this-buffer-control-sessions)
2007 (setq ediff-this-buffer-control-sessions
2008 (cons control-buffer ediff-this-buffer-control-sessions)))
2009 (setq mode-line-buffer-identification
2010 (cons "A: "
2011 (if (string-match "\\(^ \\|^[^ \t]*: \\)"
2012 (car mode-line-buffer-identification))
2013 (cons (substring (car mode-line-buffer-identification)
2014 (match-end 0))
2015 (cdr mode-line-buffer-identification))
2016 mode-line-buffer-identification)))
2017 (run-hooks 'ediff-prepare-buffer-hooks))
2018 (ediff-eval-in-buffer
2019 ediff-B-buffer
2020 (add-hook 'local-write-file-hooks 'ediff-block-write-file)
2021 (setq before-change-function 'ediff-before-change-guard)
2022 ;; add control-buffer to the list of sessions
2023 (or (memq control-buffer ediff-this-buffer-control-sessions)
2024 (setq ediff-this-buffer-control-sessions
2025 (cons control-buffer ediff-this-buffer-control-sessions)))
2026 (setq mode-line-buffer-identification
2027 (cons "B: "
2028 (if (string-match "\\(^ \\|^[^ \t]*: \\)"
2029 (car mode-line-buffer-identification))
2030 (cons (substring (car mode-line-buffer-identification)
2031 (match-end 0))
2032 (cdr mode-line-buffer-identification))
2033 mode-line-buffer-identification)))
2034 (run-hooks 'ediff-prepare-buffer-hooks))
2035
2036 (ediff-eval-in-buffer control-buffer
2037 (run-hooks 'startup-hooks 'ediff-startup-hooks)
2038 (setq buffer-read-only t)))))
2039
2040 ;; Generate the difference vector and overlays for the two files
2041 ;; With optional arg `refine', create refining difference regions
2042 (defun ediff-setup-diff-regions (file-A file-B
2043 &optional use-old refine-region
2044 diff-program diff-options
2045 diff-ok-lines-regexp)
2046
2047 (setq diff-program (or diff-program ediff-diff-program)
2048 diff-options (or diff-options ediff-diff-options)
2049 diff-ok-lines-regexp
2050 (or diff-ok-lines-regexp ediff-diff-ok-lines-regexp))
2051
2052 (or use-old (setq ediff-diff-buffer
2053 (get-buffer-create
2054 (emerge-unique-buffer-name "*ediff-diff" "*"))
2055 ediff-fine-diff-buffer
2056 (get-buffer-create
2057 (emerge-unique-buffer-name "*ediff-fine-diff" "*"))
2058 ))
2059 (ediff-eval-in-buffer
2060 (if refine-region ediff-fine-diff-buffer ediff-diff-buffer)
2061 (erase-buffer)
2062 ;; shell-command tends to display old shell command buffers even when it
2063 ;; puts output in another buffer---probably an Emacs bug.
2064 (ediff-kill-buffer-carefully "*Shell Command Output*")
2065 (let ((shell-file-name ediff-shell))
2066 (if refine-region
2067 (message "Refining difference region %d ..." (1+ refine-region))
2068 (message "Computing differences ...")(sit-for 0))
2069 (shell-command
2070 (format "%s %s %s %s"
2071 diff-program diff-options
2072 (ediff-protect-metachars file-A)
2073 (ediff-protect-metachars file-B))
2074 t)
2075 ))
2076
2077
2078 (if refine-region
2079 (progn
2080 (ediff-prepare-error-list diff-ok-lines-regexp ediff-fine-diff-buffer)
2081 (message "Refining difference region %d ... Done." (1+ refine-region))
2082 (ediff-convert-diffs-to-overlays-refine
2083 ediff-A-buffer ediff-B-buffer
2084 (ediff-extract-diffs ediff-fine-diff-buffer)
2085 refine-region))
2086 (ediff-prepare-error-list diff-ok-lines-regexp ediff-diff-buffer)
2087 (message "Computing differences ... Done.")(sit-for 0)
2088 (ediff-convert-diffs-to-overlays
2089 ediff-A-buffer ediff-B-buffer
2090 (ediff-extract-diffs ediff-diff-buffer
2091 ediff-A-buffer ediff-B-buffer))))
2092
2093
2094 (defun ediff-prepare-error-list (ok-regexp diff-buff)
2095 (ediff-eval-in-buffer
2096 ediff-error-buffer
2097 (erase-buffer)
2098 (insert-buffer diff-buff)
2099 (delete-matching-lines ok-regexp)))
2100
2101 ;;; Function to start Ediff by patching a file
2102 1712
2103 ;;;###autoload 1713 ;;;###autoload
2104 (defun ediff-patch-file (source-filename &optional startup-hooks) 1714 (defun ediff-patch-file (source-filename &optional startup-hooks)
2105 "Run Ediff by patching FILE-TP-PATCH." 1715 "Run Ediff by patching FILE-TP-PATCH."
2106 (interactive 1716 (interactive
2108 (if ediff-use-last-dir 1718 (if ediff-use-last-dir
2109 ediff-last-dir-patch 1719 ediff-last-dir-patch
2110 default-directory) 1720 default-directory)
2111 nil))) 1721 nil)))
2112 1722
1723 (setq source-filename (expand-file-name source-filename))
2113 (ediff-get-patch-buffer (file-name-directory source-filename)) 1724 (ediff-get-patch-buffer (file-name-directory source-filename))
1725
2114 (let* ((backup-extension 1726 (let* ((backup-extension
2115 ;; if the user specified a -b option, extract the backup 1727 ;; if the user specified a -b option, extract the backup
2116 ;; extension from there; else use `.orig' 1728 ;; extension from there; else use `_orig'
2117 (substring ediff-patch-options 1729 (substring ediff-patch-options
2118 (if (string-match "-b[ \t]+" ediff-patch-options) 1730 (if (string-match "-b[ \t]+" ediff-patch-options)
2119 (match-end 0) 0) 1731 (match-end 0) 0)
2120 (if (string-match "-b[ \t]+[^ \t]+" ediff-patch-options) 1732 (if (string-match "-b[ \t]+[^ \t]+" ediff-patch-options)
2121 (match-end 0) 0))) 1733 (match-end 0) 0)))
2122 (backup-extension (if (string= backup-extension "")
2123 "orig" backup-extension))
2124 (shell-file-name ediff-shell) 1734 (shell-file-name ediff-shell)
2125 ;; ediff-find-file may use a temp file to do the patch 1735 ;; ediff-find-file may use a temp file to do the patch
2126 ;; so, we save source-filename and true-source-filename as a var 1736 ;; so, we save source-filename and true-source-filename as a var
2127 ;; that initially is source-filename but may be changed to a temp 1737 ;; that initially is source-filename but may be changed to a temp
2128 ;; file for the purpose of patching. 1738 ;; file for the purpose of patching.
2129 (true-source-filename source-filename) 1739 (true-source-filename source-filename)
2130 (target-filename source-filename) 1740 (target-filename source-filename)
2131 target-buf buf-to-patch file-name-magic-p) 1741 target-buf buf-to-patch file-name-magic-p)
1742
1743 ;; if the user didn't specify a backup extension, use _orig
1744 (if (string= backup-extension "")
1745 (setq backup-extension "_orig"))
2132 1746
2133 ;; Make a temp file, if source-filename has a magic file handler (or if 1747 ;; Make a temp file, if source-filename has a magic file handler (or if
2134 ;; it is handled via auto-mode-alist and similar magic). 1748 ;; it is handled via auto-mode-alist and similar magic).
2135 ;; Check if there is a buffer visiting source-filename and if they are in 1749 ;; Check if there is a buffer visiting source-filename and if they are in
2136 ;; synch; arrange for the deletion of temp file. 1750 ;; synch; arrange for the deletion of temp file.
2137 (ediff-find-file 'true-source-filename 'buf-to-patch 1751 (ediff-find-file 'true-source-filename 'buf-to-patch
2138 'ediff-last-dir-patch 'startup-hooks) 1752 'ediff-last-dir-patch 'startup-hooks)
2139 1753
2140 ;; Check if source file name has triggered black magic, such as file name 1754 ;; Check if source file name has triggered black magic, such as file name
2141 ;; handlers or auto mode alist, and make a note of it. 1755 ;; handlers or auto mode alist, and make a note of it.
1756 ;; true-source-filename should be either the original name or a
1757 ;; temporary file where we put the after-product of the file handler.
2142 (setq file-name-magic-p (not (equal (file-truename true-source-filename) 1758 (setq file-name-magic-p (not (equal (file-truename true-source-filename)
2143 (file-truename source-filename)))) 1759 (file-truename source-filename))))
2144 1760
2145 ;; Checkout orig file, if necessary so that the patched file could be 1761 ;; Checkout orig file, if necessary so that the patched file could be
2146 ;; checked back in. 1762 ;; checked back in.
2147 (ediff-toggle-read-only buf-to-patch) 1763 (ediff-toggle-read-only buf-to-patch)
2148 1764
2149 (ediff-eval-in-buffer 1765 (ediff-eval-in-buffer ediff-patch-diagnostics
2150 ediff-patch-diagnostics 1766 (message "Applying patch ... ")(sit-for 0)
2151 (message "Applying patch ... ")(sit-for 0) 1767 ;; always pass patch the -f option, so it won't ask any questions
2152 ;; always pass patch the -f option, so it won't ask any questions 1768 (shell-command-on-region
2153 (shell-command-on-region 1769 (point-min) (point-max)
2154 (point-min) (point-max) 1770 (format "%s -f %s -b %s %s"
2155 (format "%s -f %s %s" 1771 ediff-patch-program ediff-patch-options
2156 ediff-patch-program ediff-patch-options 1772 backup-extension
2157 (expand-file-name true-source-filename)) 1773 (expand-file-name true-source-filename))
2158 t)) 1774 t))
2159 (message "Applying patch ... Done.")(sit-for 0) 1775 (message "Applying patch ... done")(sit-for 0)
2160 (switch-to-buffer ediff-patch-diagnostics) 1776 (switch-to-buffer ediff-patch-diagnostics)
2161 (sit-for 0) ;; synchronize 1777 (sit-for 0) ; synchronize
2162 1778
2163 (or (file-exists-p (concat true-source-filename "." backup-extension)) 1779 (or (file-exists-p (concat true-source-filename backup-extension))
2164 (error "Patch failed or didn't modify the original file.")) 1780 (error "Patch failed or didn't modify the original file"))
2165 1781
2166 ;; If black magic is involved, apply patch to a temp copy of the 1782 ;; If black magic is involved, apply patch to a temp copy of the
2167 ;; file. Otherwise, apply patch to the orig copy. 1783 ;; file. Otherwise, apply patch to the orig copy. If patch is applied
2168 ;; If patch is applied to temp copy, we name the result 1784 ;; to temp copy, we name the result old-name_patched for local files
2169 ;; ***.patched. The orig file name isn't changed, and the temp copy of 1785 ;; and temp-copy_patched for remote files. The orig file name isn't
2170 ;; the original is later deleted. 1786 ;; changed, and the temp copy of the original is later deleted.
2171 ;; Without magic, the original file is renamed (usually into 1787 ;; Without magic, the original file is renamed (usually into
2172 ;; old-name.orig) and the result of patching will have the 1788 ;; old-name_orig) and the result of patching will have the same name as
2173 ;; same name as the original. 1789 ;; the original.
2174 (if (not file-name-magic-p) 1790 (if (not file-name-magic-p)
2175 (ediff-eval-in-buffer 1791 (ediff-eval-in-buffer buf-to-patch
2176 buf-to-patch 1792 (set-visited-file-name (concat source-filename backup-extension))
2177 (set-visited-file-name (concat source-filename "." backup-extension)) 1793 (set-buffer-modified-p nil))
2178 (set-buffer-modified-p nil)) 1794
2179 (setq target-filename (concat true-source-filename ".patched")) 1795 ;; Black magic in effect.
1796 ;; If orig file was remote, put the patched file in the temp directory.
1797 ;; If orig file is local, put the patched file in the directory of
1798 ;; the orig file.
1799 (setq target-filename
1800 (concat
1801 (if (ediff-file-remote-p (file-truename source-filename))
1802 true-source-filename
1803 source-filename)
1804 "_patched"))
1805
2180 (rename-file true-source-filename target-filename t) 1806 (rename-file true-source-filename target-filename t)
2181 1807
2182 ;; arrange that the temp copy of orig will be deleted 1808 ;; arrange that the temp copy of orig will be deleted
2183 (rename-file (concat true-source-filename "." backup-extension) 1809 (rename-file (concat true-source-filename backup-extension)
2184 true-source-filename t)) 1810 true-source-filename t))
2185 1811
2186 ;; make orig buffer read-only 1812 ;; make orig buffer read-only
2187 (setq startup-hooks 1813 (setq startup-hooks
2188 (cons 'ediff-toggle-read-only-patch-orig startup-hooks)) 1814 (cons 'ediff-toggle-read-only-patch-orig startup-hooks))
2189 1815
2190 ;; set up a buf for the patched file 1816 ;; set up a buf for the patched file
2191 (ediff-eval-in-buffer 1817 (ediff-eval-in-buffer
2192 (setq target-buf (find-file-noselect target-filename)) 1818 (setq target-buf (find-file-noselect target-filename))
2193 ;; files to be patched are always checked out first 1819 ;; files to be patched are always checked out first
2194 (setq ediff-local-checkout-flag t)) 1820 (setq ediff-file-checked-out-flag t))
2195 1821
2196 (ediff-buffers buf-to-patch target-buf startup-hooks) 1822 (ediff-buffers buf-to-patch target-buf startup-hooks 'epatch)
2197 1823
2198 (bury-buffer ediff-patch-diagnostics) 1824 (bury-buffer ediff-patch-diagnostics)
2199 (message "Patch diagnostics available in buffer %s." 1825 (message "Patch diagnostics available in buffer %s"
2200 (buffer-name ediff-patch-diagnostics)))) 1826 (buffer-name ediff-patch-diagnostics))))
2201 1827
1828 (defun ediff-toggle-read-only-patch-orig ()
1829 "Used as a startup hook to set `_orig' patch file read-only."
1830 (ediff-toggle-read-only ediff-buffer-A))
1831
1832 ;;;###autoload
2202 (defalias 'epatch 'ediff-patch-file) 1833 (defalias 'epatch 'ediff-patch-file)
1834 ;;;###autoload
2203 (defalias 'epatch-buffer 'ediff-patch-buffer) 1835 (defalias 'epatch-buffer 'ediff-patch-buffer)
2204 1836
2205 ;;; Function to start Ediff on files 1837 ;;; Compare files/buffers
2206 1838
2207 ;;;###autoload 1839 ;;;###autoload
2208 (defun ediff-files (file-A file-B &optional startup-hooks) 1840 (defun ediff-files (file-A file-B &optional startup-hooks)
2209 "Run Ediff on a pair files, FILE-A and FILE-B." 1841 "Run Ediff on a pair of files, FILE-A and FILE-B."
2210 (interactive 1842 (interactive
2211 (let (f) 1843 (let ((dir-A (if ediff-use-last-dir
2212 (list (setq f (ediff-read-file-name "File A to compare" 1844 ediff-last-dir-A
2213 (if ediff-use-last-dir 1845 default-directory))
2214 ediff-last-dir-A 1846 dir-B f)
2215 default-directory) 1847 (list (setq f (ediff-read-file-name "File A to compare" dir-A nil))
2216 nil))
2217 (ediff-read-file-name "File B to compare" 1848 (ediff-read-file-name "File B to compare"
2218 (if ediff-use-last-dir 1849 (setq dir-B
2219 ediff-last-dir-B nil) 1850 (if ediff-use-last-dir
2220 f) 1851 ediff-last-dir-B
1852 (file-name-directory f)))
1853 (progn
1854 (setq file-name-history
1855 (cons (abbreviate-file-name
1856 (expand-file-name
1857 (file-name-nondirectory f)
1858 dir-B))
1859 file-name-history))
1860 f))
2221 ))) 1861 )))
2222 (ediff-files-internal file-A 1862 (ediff-files-internal file-A
2223 (if (file-directory-p file-B) 1863 (if (file-directory-p file-B)
2224 (expand-file-name 1864 (expand-file-name
2225 (file-name-nondirectory file-A) file-B) 1865 (file-name-nondirectory file-A) file-B)
2226 file-B) 1866 file-B)
2227 startup-hooks)) 1867 nil ; file-C
2228 1868 startup-hooks
2229 1869 'ediff-files))
1870
1871 ;;;###autoload
1872 (defun ediff-files3 (file-A file-B file-C &optional startup-hooks)
1873 "Run Ediff on three files, FILE-A, FILE-B, and FILE-C."
1874 (interactive
1875 (let ((dir-A (if ediff-use-last-dir
1876 ediff-last-dir-A
1877 default-directory))
1878 dir-B dir-C f ff)
1879 (list (setq f (ediff-read-file-name "File A to compare" dir-A nil))
1880 (setq ff (ediff-read-file-name "File B to compare"
1881 (setq dir-B
1882 (if ediff-use-last-dir
1883 ediff-last-dir-B
1884 (file-name-directory f)))
1885 (progn
1886 (setq file-name-history
1887 (cons
1888 (abbreviate-file-name
1889 (expand-file-name
1890 (file-name-nondirectory f)
1891 dir-B))
1892 file-name-history))
1893 f)))
1894 (ediff-read-file-name "File C to compare"
1895 (setq dir-C (if ediff-use-last-dir
1896 ediff-last-dir-C
1897 (file-name-directory ff)))
1898 (progn
1899 (setq file-name-history
1900 (cons (abbreviate-file-name
1901 (expand-file-name
1902 (file-name-nondirectory ff)
1903 dir-C))
1904 file-name-history))
1905 ff))
1906 )))
1907 (ediff-files-internal file-A
1908 (if (file-directory-p file-B)
1909 (expand-file-name
1910 (file-name-nondirectory file-A) file-B)
1911 file-B)
1912 (if (file-directory-p file-C)
1913 (expand-file-name
1914 (file-name-nondirectory file-A) file-C)
1915 file-C)
1916 startup-hooks
1917 'ediff-files3))
1918
1919 ;;;###autoload
1920 (defalias 'ediff3 'ediff-files3)
1921
1922
1923 (defun ediff-find-file (file-var buffer-name &optional last-dir hooks-var)
1924 "Visit FILE and arrange its buffer to Ediff's liking.
1925 FILE is actually a variable symbol that must contain a true file name.
1926 BUFFER-NAME is a variable symbol, which will get the buffer object into which
1927 FILE is read. LAST-DIR is the directory variable symbol where FILE's
1928 directory name should be returned. HOOKS is a variable symbol that will be
1929 assigned the hook to be executed after `ediff-startup' is finished.
1930 `ediff-find-file' arranges that the temp files it might create will be
1931 deleted."
1932 (let* ((file (symbol-value file-var))
1933 (file-magic (ediff-find-file-name-handler file))
1934 (temp-file-name-prefix (file-name-nondirectory file)))
1935 (if (not (file-readable-p file))
1936 (error "File `%s' does not exist or is not readable" file))
1937
1938 ;; some of the command, below, require full file name
1939 (setq file (expand-file-name file))
1940
1941 ;; Record the directory of the file
1942 (if last-dir
1943 (set last-dir (expand-file-name (file-name-directory file))))
1944
1945 ;; Setup the buffer
1946 (set buffer-name (find-file-noselect file))
1947
1948 (ediff-eval-in-buffer (symbol-value buffer-name)
1949 (widen) ; Make sure the entire file is seen
1950 (cond (file-magic ;; file has handler, such as jka-compr-handler or
1951 ;; ange-ftp-hook-function--arrange for temp file
1952 (ediff-verify-file-buffer 'magic)
1953 (setq file (ediff-make-temp-file temp-file-name-prefix))
1954 (set hooks-var (cons (` (lambda () (delete-file (, file))))
1955 (symbol-value hooks-var))))
1956 ;; file processed via auto-mode-alist, a la uncompress.el
1957 ((not (equal (file-truename file)
1958 (file-truename (buffer-file-name))))
1959 (setq file (ediff-make-temp-file temp-file-name-prefix))
1960 (set hooks-var (cons (` (lambda () (delete-file (, file))))
1961 (symbol-value hooks-var))))
1962 (t ;; plain file---just check that the file matches the buffer
1963 (ediff-verify-file-buffer))))
1964 (set file-var file)))
1965
1966 (defun ediff-files-internal (file-A file-B file-C startup-hooks job-name)
1967 (let (buf-A buf-B buf-C)
1968 (message "Reading file %s ... " file-A)(sit-for 0)
1969 (ediff-find-file 'file-A 'buf-A 'ediff-last-dir-A 'startup-hooks)
1970 (message "Reading file %s ... " file-B)(sit-for 0)
1971 (ediff-find-file 'file-B 'buf-B 'ediff-last-dir-B 'startup-hooks)
1972 (if (and (stringp file-C) (not ediff-merge-job))
1973 (progn
1974 (message "Reading file %s ... " file-C)(sit-for 0)
1975 (ediff-find-file
1976 'file-C 'buf-C
1977 (if (eq job-name 'ediff-merge-files-with-ancestor)
1978 'ediff-last-dir-ancestor 'ediff-last-dir-C)
1979 'startup-hooks)))
1980 (ediff-setup buf-A file-A
1981 buf-B file-B
1982 buf-C file-C
1983 startup-hooks
1984 (list (cons 'ediff-job-name job-name)))))
1985
1986
1987 ;;;###autoload
2230 (defalias 'ediff 'ediff-files) 1988 (defalias 'ediff 'ediff-files)
2231 1989
2232 1990
2233 ;;; Function to start Ediff on buffers 1991 ;;;###autoload
2234 1992 (defun ediff-buffers (buffer-A buffer-B &optional startup-hooks job-name)
2235 ;;;###autoload
2236 (defun ediff-buffers (buffer-A buffer-B &optional startup-hooks)
2237 "Run Ediff on a pair of buffers, BUFFER-A and BUFFER-B." 1993 "Run Ediff on a pair of buffers, BUFFER-A and BUFFER-B."
2238 (interactive 1994 (interactive
2239 (list (read-buffer "Buffer A to compare: " (current-buffer) t) 1995 (let (bf)
2240 (read-buffer "Buffer B to compare: " 1996 (list (setq bf (read-buffer "Buffer A to compare: "
2241 (progn 1997 (ediff-other-buffer "") t))
2242 ;; realign buffers so that two visible bufs will be 1998 (read-buffer "Buffer B to compare: "
2243 ;; at the top 1999 (progn
2244 (save-window-excursion (other-window 1)) 2000 ;; realign buffers so that two visible bufs will be
2245 (other-buffer (current-buffer) t)) 2001 ;; at the top
2246 t))) 2002 (save-window-excursion (other-window 1))
2003 (ediff-other-buffer bf))
2004 t))))
2005
2006 (or job-name (setq job-name 'ediff-buffers))
2007 (ediff-buffers-internal buffer-A buffer-B nil startup-hooks job-name))
2008
2009 ;;;###autoload
2010 (defun ediff-buffers3 (buffer-A buffer-B buffer-C
2011 &optional startup-hooks job-name)
2012 "Run Ediff on three buffers, BUFFER-A, BUFFER-B, and BUFFER-C."
2013 (interactive
2014 (let (bf bff)
2015 (list (setq bf (read-buffer "Buffer A to compare: "
2016 (ediff-other-buffer "") t))
2017 (setq bff (read-buffer "Buffer B to compare: "
2018 (progn
2019 ;; realign buffers so that two visible
2020 ;; bufs will be at the top
2021 (save-window-excursion (other-window 1))
2022 (ediff-other-buffer bf))
2023 t))
2024 (read-buffer "Buffer C to compare: "
2025 (progn
2026 ;; realign buffers so that three visible
2027 ;; bufs will be at the top
2028 (save-window-excursion (other-window 1))
2029 (ediff-other-buffer (list bf bff)))
2030 t)
2031 )))
2032
2033 (or job-name (setq job-name 'ediff-buffers3))
2034 (ediff-buffers-internal buffer-A buffer-B buffer-C startup-hooks job-name))
2035
2036
2037
2038 (defun ediff-buffers-internal (buf-A buf-B buf-C startup-hooks job-name)
2039 (let* ((buf-A-file-name (buffer-file-name (get-buffer buf-A)))
2040 (buf-B-file-name (buffer-file-name (get-buffer buf-B)))
2041 (buf-C-is-alive (ediff-buffer-live-p buf-C))
2042 (buf-C-file-name (if buf-C-is-alive
2043 (buffer-file-name (get-buffer buf-B))))
2044 file-A file-B file-C)
2045 (if (not (ediff-buffer-live-p buf-A))
2046 (error "Buffer %S doesn't exist" buf-A))
2047 (if (not (ediff-buffer-live-p buf-B))
2048 (error "Buffer %S doesn't exist" buf-B))
2049 (let ((ediff-job-name job-name))
2050 (if (and ediff-3way-comparison-job
2051 (not buf-C-is-alive))
2052 (error "Buffer %S doesn't exist" buf-C)))
2053 (if (stringp buf-A-file-name)
2054 (setq buf-A-file-name (file-name-nondirectory buf-A-file-name)))
2055 (if (stringp buf-B-file-name)
2056 (setq buf-B-file-name (file-name-nondirectory buf-B-file-name)))
2057 (if (stringp buf-C-file-name)
2058 (setq buf-C-file-name (file-name-nondirectory buf-C-file-name)))
2059
2060 ;; these three need to be evaluated in their buffers, since
2061 ;; ediff-make-temp-file checks the current buffer when assigning file
2062 ;; names
2063 (ediff-eval-in-buffer buf-A
2064 (setq file-A (ediff-make-temp-file buf-A-file-name)))
2065 (ediff-eval-in-buffer buf-B
2066 (setq file-B (ediff-make-temp-file buf-B-file-name)))
2067 (if buf-C-is-alive
2068 (ediff-eval-in-buffer buf-C
2069 (setq file-C (ediff-make-temp-file buf-C-file-name))))
2070
2071 (ediff-setup (get-buffer buf-A) file-A
2072 (get-buffer buf-B) file-B
2073 (if buf-C-is-alive (get-buffer buf-C))
2074 file-C
2075 (cons (` (lambda ()
2076 (delete-file (, file-A))
2077 (delete-file (, file-B))
2078 (if (stringp (, file-C)) (delete-file (, file-C)))
2079 ))
2080 startup-hooks)
2081 (list (cons 'ediff-job-name job-name))
2082 )))
2083
2084
2085
2086 ;;; Compare regions and windows
2087
2088 ;;;###autoload
2089 (defun ediff-windows (dumb-mode &optional wind-A wind-B startup-hooks)
2090 "Compare WIND-A and WIND-B, which are selected by clicking.
2091 With prefix argument, DUMB-MODE, or on a non-windowing display, works as
2092 follows:
2093 If WIND-A is nil, use selected window.
2094 If WIND-B is nil, use window next to WIND-A."
2095
2096 (interactive "P")
2097
2098 (if (or dumb-mode (not window-system))
2099 (setq wind-A (ediff-get-next-window wind-A nil)
2100 wind-B (ediff-get-next-window wind-B wind-A))
2101 (setq wind-A (ediff-get-window-by-clicking wind-A nil 1)
2102 wind-B (ediff-get-window-by-clicking wind-B wind-A 2)))
2103
2104 (let ((buffer-A (window-buffer wind-A))
2105 (buffer-B (window-buffer wind-B))
2106 beg-A end-A beg-B end-B)
2107
2108 (save-excursion
2109 (save-window-excursion
2110 (sit-for 0) ; synch before using window-start/end -- a precaution
2111 (select-window wind-A)
2112 (setq beg-A (window-start)
2113 end-A (window-end))
2114 (select-window wind-B)
2115 (setq beg-B (window-start)
2116 end-B (window-end))))
2117 (ediff-regions-internal
2118 buffer-A beg-A end-A buffer-B beg-B end-B
2119 startup-hooks 'ediff-windows 'word-mode)))
2120
2121 ;;;###autoload
2122 (defun ediff-small-regions (buffer-A buffer-B &optional startup-hooks)
2123 "Run Ediff on a pair of regions in two different buffers.
2124 Regions \(i.e., point and mark\) are assumed to be set in advance.
2125 This function is effective only for relatively small regions, up to 200
2126 lines. For large regions, use `ediff-large-regions'."
2127 (interactive
2128 (let (bf)
2129 (list (setq bf (read-buffer "Region's A buffer: "
2130 (ediff-other-buffer "") t))
2131 (read-buffer "Region's B buffer: "
2132 (progn
2133 ;; realign buffers so that two visible bufs will be
2134 ;; at the top
2135 (save-window-excursion (other-window 1))
2136 (ediff-other-buffer bf))
2137 t))))
2247 (if (not (ediff-buffer-live-p buffer-A)) 2138 (if (not (ediff-buffer-live-p buffer-A))
2248 (error "Buffer %S doesn't exist." buffer-A)) 2139 (error "Buffer %S doesn't exist" buffer-A))
2249 (if (not (ediff-buffer-live-p buffer-B)) 2140 (if (not (ediff-buffer-live-p buffer-B))
2250 (error "Buffer %S doesn't exist." buffer-B)) 2141 (error "Buffer %S doesn't exist" buffer-B))
2142
2143
2144 (let (reg-A-beg reg-A-end reg-B-beg reg-B-end)
2145 (save-excursion
2146 (set-buffer buffer-A)
2147 (setq reg-A-beg (region-beginning)
2148 reg-A-end (region-end))
2149 (set-buffer buffer-B)
2150 (setq reg-B-beg (region-beginning)
2151 reg-B-end (region-end)))
2152
2153 (ediff-regions-internal
2154 (get-buffer buffer-A) reg-A-beg reg-A-end
2155 (get-buffer buffer-B) reg-B-beg reg-B-end
2156 startup-hooks 'ediff-small-regions 'word-mode)))
2157
2158 ;;;###autoload
2159 (defun ediff-large-regions (buffer-A buffer-B &optional startup-hooks)
2160 "Run Ediff on a pair of regions in two different buffers.
2161 Regions \(i.e., point and mark\) are assumed to be set in advance.
2162 Each region is enlarged to contain full lines.
2163 This function is effective for large regions, over 100-200
2164 lines. For small regions, use `ediff-small-regions'."
2165 (interactive
2166 (let (bf)
2167 (list (setq bf (read-buffer "Region A's buffer: "
2168 (ediff-other-buffer "") t))
2169 (read-buffer "Region B's buffer: "
2170 (progn
2171 ;; realign buffers so that two visible bufs will be
2172 ;; at the top
2173 (save-window-excursion (other-window 1))
2174 (ediff-other-buffer bf))
2175 t))))
2176 (if (not (ediff-buffer-live-p buffer-A))
2177 (error "Buffer %S doesn't exist" buffer-A))
2178 (if (not (ediff-buffer-live-p buffer-B))
2179 (error "Buffer %S doesn't exist" buffer-B))
2180
2181 (let (reg-A-beg reg-A-end reg-B-beg reg-B-end)
2182 (save-excursion
2183 (set-buffer buffer-A)
2184 (setq reg-A-beg (region-beginning)
2185 reg-A-end (region-end))
2186 ;; enlarge the region to hold full lines
2187 (goto-char reg-A-beg)
2188 (beginning-of-line)
2189 (setq reg-A-beg (point))
2190 (goto-char reg-A-end)
2191 (end-of-line)
2192 (or (eobp) (forward-char)) ; include the newline char
2193 (setq reg-A-end (point))
2251 2194
2252 (let (file-A file-B) 2195 (set-buffer buffer-B)
2253 (ediff-eval-in-buffer 2196 (setq reg-B-beg (region-beginning)
2254 buffer-A 2197 reg-B-end (region-end))
2255 (setq file-A (ediff-make-temp-file))) 2198 ;; enlarge the region to hold full lines
2256 (ediff-eval-in-buffer 2199 (goto-char reg-A-beg)
2257 buffer-B 2200 (goto-char reg-B-beg)
2258 (setq file-B (ediff-make-temp-file))) 2201 (beginning-of-line)
2259 (ediff-setup (get-buffer buffer-A) file-A 2202 (setq reg-B-beg (point))
2260 (get-buffer buffer-B) file-B 2203 (goto-char reg-B-end)
2204 (end-of-line)
2205 (or (eobp) (forward-char)) ; include the newline char
2206 (setq reg-B-end (point))
2207 ) ; save excursion
2208
2209 (ediff-regions-internal
2210 (get-buffer buffer-A) reg-A-beg reg-A-end
2211 (get-buffer buffer-B) reg-B-beg reg-B-end
2212 startup-hooks 'ediff-large-regions nil))) ; no word mode
2213
2214 ;; compare region beg-A to end-A of buffer-A
2215 ;; to regions beg-B -- end-B in buffer-B.
2216 (defun ediff-regions-internal (buffer-A beg-A end-A buffer-B beg-B end-B
2217 startup-hooks job-name word-mode)
2218 (let ((tmp-buffer (get-buffer-create ediff-tmp-buffer))
2219 overl-A overl-B
2220 file-A file-B)
2221
2222 ;; in case beg/end-A/B aren't markers--make them into markers
2223 (ediff-eval-in-buffer buffer-A
2224 (setq beg-A (move-marker (make-marker) beg-A)
2225 end-A (move-marker (make-marker) end-A)))
2226 (ediff-eval-in-buffer buffer-B
2227 (setq beg-B (move-marker (make-marker) beg-B)
2228 end-B (move-marker (make-marker) end-B)))
2229
2230 (if (and (eq buffer-A buffer-B)
2231 (or (and (< beg-A end-B) (<= beg-B beg-A)) ; b-B b-A e-B
2232 (and (< beg-B end-A) (<= end-A end-B)))) ; b-B e-A e-B
2233 (progn
2234 (with-output-to-temp-buffer ediff-msg-buffer
2235 (princ "
2236 You have requested to compare overlapping regions of the same buffer.
2237
2238 In this case, Ediff's highlighting may be confusing---in the same window,
2239 you may see highlighted regions that belong to different regions.
2240
2241 Continue anyway? (y/n) "))
2242
2243 (if (y-or-n-p "Continue anyway? ")
2244 ()
2245 (error "%S aborted" job-name))))
2246
2247 ;; make file-A
2248 (if word-mode
2249 (ediff-wordify beg-A end-A buffer-A tmp-buffer)
2250 (ediff-copy-to-buffer beg-A end-A buffer-A tmp-buffer))
2251 (ediff-eval-in-buffer tmp-buffer
2252 (setq file-A (ediff-make-temp-file "regA")))
2253
2254 ;; make file-B
2255 (if word-mode
2256 (ediff-wordify beg-B end-B buffer-B tmp-buffer)
2257 (ediff-copy-to-buffer beg-B end-B buffer-B tmp-buffer))
2258 (ediff-eval-in-buffer tmp-buffer
2259 (setq file-B (ediff-make-temp-file "regB")))
2260
2261 (setq overl-A (ediff-make-bullet-proof-overlay beg-A end-A buffer-A))
2262 (setq overl-B (ediff-make-bullet-proof-overlay beg-B end-B buffer-B))
2263 (ediff-setup buffer-A file-A
2264 buffer-B file-B
2265 nil nil ; buffer & file C
2261 (cons (` (lambda () 2266 (cons (` (lambda ()
2262 (delete-file (, file-A)) 2267 (delete-file (, file-A))
2263 (delete-file (, file-B)))) 2268 (delete-file (, file-B))))
2264 startup-hooks) 2269 startup-hooks)
2265 ))) 2270 (list (cons 'ediff-word-mode word-mode)
2266 2271 (cons 'ediff-narrow-bounds (list overl-A overl-B))
2272 (cons 'ediff-job-name job-name))
2273 )
2274 ))
2275
2276
2277 ;;; Merge files and buffers
2278
2279 ;;;###autoload
2280 (defalias 'ediff-merge 'ediff-merge-files)
2281
2282 (defsubst ediff-merge-on-startup ()
2283 (ediff-do-merge 0)
2284 (ediff-eval-in-buffer ediff-buffer-C
2285 (set-buffer-modified-p nil)))
2286
2287 ;;;###autoload
2288 (defun ediff-merge-files (file-A file-B &optional startup-hooks)
2289 "Merge two files without ancestor."
2290 (interactive
2291 (let ((dir-A (if ediff-use-last-dir
2292 ediff-last-dir-A
2293 default-directory))
2294 dir-B f)
2295 (list (setq f (ediff-read-file-name "File A to merge" dir-A nil))
2296 (ediff-read-file-name "File B to merge"
2297 (setq dir-B
2298 (if ediff-use-last-dir
2299 ediff-last-dir-B
2300 (file-name-directory f)))
2301 (progn
2302 (setq file-name-history
2303 (cons (abbreviate-file-name
2304 (expand-file-name
2305 (file-name-nondirectory f)
2306 dir-B))
2307 file-name-history))
2308 f))
2309 )))
2310 (setq startup-hooks (cons 'ediff-merge-on-startup startup-hooks))
2311 (ediff-files-internal file-A
2312 (if (file-directory-p file-B)
2313 (expand-file-name
2314 (file-name-nondirectory file-A) file-B)
2315 file-B)
2316 nil ; file-C
2317 startup-hooks
2318 'ediff-merge-files))
2319
2320 ;;;###autoload
2321 (defun ediff-merge-files-with-ancestor (file-A file-B file-ancestor
2322 &optional startup-hooks)
2323 "Merge two files with ancestor."
2324 (interactive
2325 (let ((dir-A (if ediff-use-last-dir
2326 ediff-last-dir-A
2327 default-directory))
2328 dir-B dir-ancestor f ff)
2329 (list (setq f (ediff-read-file-name "File A to merge" dir-A nil))
2330 (setq ff (ediff-read-file-name "File B to merge"
2331 (setq dir-B
2332 (if ediff-use-last-dir
2333 ediff-last-dir-B
2334 (file-name-directory f)))
2335 (progn
2336 (setq file-name-history
2337 (cons
2338 (abbreviate-file-name
2339 (expand-file-name
2340 (file-name-nondirectory f)
2341 dir-B))
2342 file-name-history))
2343 f)))
2344 (ediff-read-file-name "Ancestor file"
2345 (setq dir-ancestor
2346 (if ediff-use-last-dir
2347 ediff-last-dir-ancestor
2348 (file-name-directory ff)))
2349 (progn
2350 (setq file-name-history
2351 (cons (abbreviate-file-name
2352 (expand-file-name
2353 (file-name-nondirectory ff)
2354 dir-ancestor))
2355 file-name-history))
2356 ff))
2357 )))
2358 (setq startup-hooks (cons 'ediff-merge-on-startup startup-hooks))
2359 (ediff-files-internal file-A
2360 (if (file-directory-p file-B)
2361 (expand-file-name
2362 (file-name-nondirectory file-A) file-B)
2363 file-B)
2364 file-ancestor
2365 startup-hooks
2366 'ediff-merge-files-with-ancestor))
2367
2368 ;;;###autoload
2369 (defalias 'ediff-merge-with-ancestor 'ediff-merge-files-with-ancestor)
2370
2371 ;;;###autoload
2372 (defun ediff-merge-buffers (buffer-A buffer-B &optional startup-hooks job-name)
2373 "Merge buffers without ancestor."
2374 (interactive
2375 (let (bf)
2376 (list (setq bf (read-buffer "Buffer A to merge: "
2377 (ediff-other-buffer "") t))
2378 (read-buffer "Buffer B to merge: "
2379 (progn
2380 ;; realign buffers so that two visible bufs will be
2381 ;; at the top
2382 (save-window-excursion (other-window 1))
2383 (ediff-other-buffer bf))
2384 t))))
2385
2386 (setq startup-hooks (cons 'ediff-merge-on-startup startup-hooks))
2387 (or job-name (setq job-name 'ediff-merge-buffers))
2388 (ediff-buffers-internal
2389 buffer-A buffer-B nil startup-hooks job-name))
2390
2391 ;;;###autoload
2392 (defun ediff-merge-buffers-with-ancestor (buffer-A
2393 buffer-B buffer-ancestor
2394 &optional startup-hooks job-name)
2395 "Merge buffers with ancestor."
2396 (interactive
2397 (let (bf bff)
2398 (list (setq bf (read-buffer "Buffer A to merge: "
2399 (ediff-other-buffer "") t))
2400 (setq bff (read-buffer "Buffer B to merge: "
2401 (progn
2402 ;; realign buffers so that two visible
2403 ;; bufs will be at the top
2404 (save-window-excursion (other-window 1))
2405 (ediff-other-buffer bf))
2406 t))
2407 (read-buffer "Ancestor buffer: "
2408 (progn
2409 ;; realign buffers so that three visible
2410 ;; bufs will be at the top
2411 (save-window-excursion (other-window 1))
2412 (ediff-other-buffer (list bf bff)))
2413 t)
2414 )))
2415
2416 (setq startup-hooks (cons 'ediff-merge-on-startup startup-hooks))
2417 (or job-name (setq job-name 'ediff-merge-buffers-with-ancestor))
2418 (ediff-buffers-internal
2419 buffer-A buffer-B buffer-ancestor startup-hooks job-name))
2420
2421
2422 ;;;###autoload
2423 (defun ediff-merge-revisions (rev1 rev2 &optional startup-hooks)
2424 "Run Ediff by merging two revisions of a file.
2425 The file is the one visited by the current buffer."
2426 (interactive
2427 "sVersion 1 to merge (default is the latest version): \nsVersion 2 to merge (default is the latest version): ")
2428 (ediff-load-version-control)
2429 (let (buf1 buf2)
2430 (if (eq ediff-version-control-package 'vc)
2431 (progn
2432 (save-excursion
2433 (vc-version-other-window rev1)
2434 (setq buf1 (current-buffer)))
2435 (save-excursion
2436 (vc-version-other-window rev2)
2437 (setq buf2 (current-buffer)))
2438 (setq startup-hooks
2439 (list (` (lambda ()
2440 (delete-file (, (buffer-file-name buf1)))
2441 (delete-file (, (buffer-file-name buf2))))))))
2442 (setq buf1 (rcs-ediff-view-revision rev1)
2443 buf2 (rcs-ediff-view-revision rev2)))
2444 (ediff-merge-buffers buf1 buf2 startup-hooks 'ediff-merge-revisions)))
2445
2446
2447 ;;;###autoload
2448 (defun ediff-merge-revisions-with-ancestor (rev1
2449 rev2 ancestor-rev
2450 &optional startup-hooks)
2451 "Run Ediff by merging with ancestor of two revisions of a file.
2452 The file is the one visited by the current buffer."
2453 (interactive
2454 "sVersion 1 to merge (default: the latest version): \nsVersion 2 to merge (default: the latest version): \nsAncestor version (default: the latest version): ")
2455 (ediff-load-version-control)
2456 (let (buf1 buf2 ancestor-buf)
2457 (if (eq ediff-version-control-package 'vc)
2458 (progn
2459 (save-excursion
2460 (vc-version-other-window rev1)
2461 (setq buf1 (current-buffer)))
2462 (save-excursion
2463 (vc-version-other-window rev2)
2464 (setq buf2 (current-buffer)))
2465 (save-excursion
2466 (vc-version-other-window ancestor-rev)
2467 (setq ancestor-buf (current-buffer)))
2468 (setq startup-hooks
2469 (list (` (lambda ()
2470 (delete-file (, (buffer-file-name buf1)))
2471 (delete-file (, (buffer-file-name buf2)))
2472 (delete-file (, (buffer-file-name ancestor-buf)))
2473 )))))
2474 (setq buf1 (rcs-ediff-view-revision rev1)
2475 buf2 (rcs-ediff-view-revision rev2)
2476 ancestor-buf (rcs-ediff-view-revision ancestor-rev)))
2477 (ediff-merge-buffers-with-ancestor
2478 buf1 buf2 ancestor-buf
2479 startup-hooks 'ediff-merge-revisions-with-ancestor)))
2480
2481
2482 ;;; Apply patch
2483
2484
2267 ;;;###autoload 2485 ;;;###autoload
2268 (defun ediff-patch-buffer (buffer-name &optional startup-hooks) 2486 (defun ediff-patch-buffer (buffer-name &optional startup-hooks)
2269 "Run Ediff by patching BUFFER-NAME." 2487 "Run Ediff by patching BUFFER-NAME."
2270 (interactive "bBuffer to patch: ") 2488 (interactive "bBuffer to patch: ")
2271 2489
2274 (if (not file-name) 2492 (if (not file-name)
2275 (error "Buffer %s doesn't exist or doesn't visit any file. Why patch?" 2493 (error "Buffer %s doesn't exist or doesn't visit any file. Why patch?"
2276 file-name)) 2494 file-name))
2277 2495
2278 (ediff-patch-file file-name startup-hooks))) 2496 (ediff-patch-file file-name startup-hooks)))
2497
2498
2499 (defun ediff-get-patch-buffer (dir)
2500 "Obtain patch buffer. If patch is already in a buffer---use it.
2501 Else, read patch file into a new buffer."
2502 (if (y-or-n-p "Is the patch file already in a buffer? ")
2503 (setq ediff-patch-buf
2504 (get-buffer (read-buffer "Patch buffer name: " nil t))) ;must match
2505 (setq ediff-patch-buf
2506 (find-file-noselect (read-file-name "Patch file name: " dir))))
2507
2508 ;; secure the patch buffer against accidental changes
2509 (ediff-eval-in-buffer ediff-patch-buf
2510 (setq buffer-read-only t))
2511
2512 (setq ediff-patch-diagnostics
2513 (get-buffer-create "*ediff patch diagnostics*"))
2514 (ediff-eval-in-buffer
2515 ediff-patch-diagnostics
2516 (insert-buffer ediff-patch-buf))
2517 )
2518
2519
2279 2520
2280 2521
2522
2281 ;;; Versions Control functions 2523 ;;; Versions Control functions
2282 2524
2283 ;;;###autoload 2525 ;;;###autoload
2284 (defun ediff-revision (revision) 2526 (defun ediff-revision (revision)
2285 "Call `vc.el' or `rcs.el' depending on `ediff-version-control-package'. 2527 "Call `vc.el' or `rcs.el' depending on `ediff-version-control-package'.
2286 This function is introduced to provide a uniform interface to version 2528 This function is introduced to provide a uniform interface to version
2287 control packages from Ediff." 2529 control packages from Ediff."
2288 (interactive "sVersion to Ediff with (default is the latest version): ") 2530 (interactive "sVersion to Ediff with (default: the latest version): ")
2531 (ediff-load-version-control)
2289 (funcall 2532 (funcall
2290 (intern (format "%S-ediff-internal" ediff-version-control-package)) 2533 (intern (format "%S-ediff-internal" ediff-version-control-package))
2291 revision)) 2534 revision))
2535
2536 ;; Backward compatibility
2537 ;;;###autoload
2538 (defun vc-ediff ()
2539 (interactive)
2540 (beep 1)
2541 (with-output-to-temp-buffer ediff-msg-buffer
2542 (princ "
2543 You have invoked an obsolete function `vc-ediff' or `rcs-ediff'.
2544 Please use `M-x ediff-revision' instead.
2545
2546 Also, please check the variables `ediff-version-control-package'
2547 and `ediff-revision-key' for customization.")))
2548
2549 (defalias 'rcs-ediff 'vc-ediff)
2550
2551 ;; Test if version control package is loaded and load if not
2552 ;; Is SILENT is non-nil, don't report error if package is not found.
2553 (defun ediff-load-version-control (&optional silent)
2554 (or (featurep ediff-version-control-package)
2555 (if (locate-library (symbol-name ediff-version-control-package))
2556 (progn
2557 (message "") ; kill the message from `locate-library'
2558 (require ediff-version-control-package)
2559 (define-key
2560 (cond ((eq ediff-version-control-package 'vc) vc-prefix-map)
2561 ((eq ediff-version-control-package 'rcs) global-map)
2562 (t global-map))
2563 ediff-revision-key 'ediff-revision))
2564 (or silent
2565 (error "Version control package %S.el not found. Use vc.el instead"
2566 ediff-version-control-package)))))
2567
2292 2568
2569 ;; Note: this function will work only with Emacs 19.22 or later.
2293 (defun vc-ediff-internal (rev) 2570 (defun vc-ediff-internal (rev)
2294 ;; Note: this function will work only with Emacs 19.22 and higher.
2295 "Run Ediff on version REV of the current buffer in another window. 2571 "Run Ediff on version REV of the current buffer in another window.
2296 If the current buffer is named `F', the version is named `F.~REV~'. 2572 If the current buffer is named `F', the version is named `F.~REV~'.
2297 If `F.~REV~' already exists, it is used instead of being re-created." 2573 If `F.~REV~' already exists, it is used instead of being re-created."
2298 (or (featurep 'vc)
2299 (if (locate-library "vc") ;; if vc.el is available
2300 (require 'vc-hooks)
2301 (error "The vc.el package is apparently not installed")))
2302 (define-key vc-prefix-map "=" 'ediff-revision)
2303 (let ((newvers (current-buffer))) 2574 (let ((newvers (current-buffer)))
2304 (vc-version-other-window rev) 2575 (vc-version-other-window rev)
2305 ;; current-buffer is supposed to contain the old version 2576 ;; current-buffer is now supposed to contain the old version
2306 ;; in another window 2577 ;; in another window
2307 (ediff-buffers newvers (current-buffer)) 2578 ;; We delete the temp file that was created by vc.el for the old
2579 ;; version
2580 (ediff-buffers (current-buffer) newvers
2581 (list (` (lambda () (delete-file (, (buffer-file-name))))))
2582 'ediff-revision)
2308 )) 2583 ))
2309 2584
2310 (defun rcs-ediff-view-revision (&optional rev) 2585 (defun rcs-ediff-view-revision (&optional rev)
2311 "View previous RCS revision of current file. 2586 "View previous RCS revision of current file.
2312 With prefix argument, prompts for a revision name." 2587 With prefix argument, prompts for a revision name."
2314 (read-string "Revision: ")))) 2589 (read-string "Revision: "))))
2315 (let* ((filename (buffer-file-name (current-buffer))) 2590 (let* ((filename (buffer-file-name (current-buffer)))
2316 (switches (append '("-p") 2591 (switches (append '("-p")
2317 (if rev (list (concat "-r" rev)) nil))) 2592 (if rev (list (concat "-r" rev)) nil)))
2318 (buff (concat (file-name-nondirectory filename) ".~" rev "~"))) 2593 (buff (concat (file-name-nondirectory filename) ".~" rev "~")))
2319 (message "Working...") 2594 (message "Working ...")
2320 (setq filename (expand-file-name filename)) 2595 (setq filename (expand-file-name filename))
2321 (with-output-to-temp-buffer buff 2596 (with-output-to-temp-buffer buff
2322 (let ((output-buffer (ediff-rcs-get-output-buffer filename buff))) 2597 (let ((output-buffer (ediff-rcs-get-output-buffer filename buff)))
2323 (delete-windows-on output-buffer) 2598 (delete-windows-on output-buffer)
2324 (save-excursion 2599 (save-excursion
2333 (defun ediff-rcs-get-output-buffer (file name) 2608 (defun ediff-rcs-get-output-buffer (file name)
2334 ;; Get a buffer for RCS output for FILE, make it writable and clean it up. 2609 ;; Get a buffer for RCS output for FILE, make it writable and clean it up.
2335 ;; Optional NAME is name to use instead of `*RCS-output*'. 2610 ;; Optional NAME is name to use instead of `*RCS-output*'.
2336 ;; This is a modified version from rcs.el v1.1. I use it here to make 2611 ;; This is a modified version from rcs.el v1.1. I use it here to make
2337 ;; Ediff immune to changes in rcs.el 2612 ;; Ediff immune to changes in rcs.el
2338 (let* ((default-major-mode 'fundamental-mode);; no frills! 2613 (let* ((default-major-mode 'fundamental-mode) ; no frills!
2339 (buf (get-buffer-create name))) 2614 (buf (get-buffer-create name)))
2340 (save-excursion 2615 (save-excursion
2341 (set-buffer buf) 2616 (set-buffer buf)
2342 (setq buffer-read-only nil 2617 (setq buffer-read-only nil
2343 default-directory (file-name-directory (expand-file-name file))) 2618 default-directory (file-name-directory (expand-file-name file)))
2344 (erase-buffer)) 2619 (erase-buffer))
2345 buf)) 2620 buf))
2346 2621
2347 (defun rcs-ediff-internal (rev) 2622 (defun rcs-ediff-internal (rev)
2348 "Run Ediff on the current buffer, comparing it with previous RCS revision." 2623 "Run Ediff on the current buffer, comparing it with previous RCS revision."
2349 (or (featurep 'rcs)
2350 (if (locate-library "rcs")
2351 (require 'rcs)
2352 (error "The rcs.el package is apparently not installed")))
2353 (global-set-key "\C-cD" 'ediff-revision)
2354 (let ((newvers (current-buffer)) 2624 (let ((newvers (current-buffer))
2355 (oldvers (rcs-ediff-view-revision rev))) 2625 (oldvers (rcs-ediff-view-revision rev)))
2356 (ediff-buffers newvers oldvers) 2626
2627 ;; rcs.el doesn't create temp version files, so we don't have to delete
2628 ;; anything in startup hooks to ediff-buffers
2629 (ediff-buffers oldvers newvers nil 'ediff-revision)
2357 )) 2630 ))
2358 2631
2359 2632 ;;; Menu bar
2360 2633
2361 2634 ;;; This is split in several parts to avoid
2362 ;; Select the lowest window on the frame. 2635 ;;; making a line in loaddefs.el that is too long for patch.
2363 (defun ediff-select-lowest-window () 2636 ;;; Note that autoload.el currently looks for cookies
2364 (let* ((lowest-window (selected-window)) 2637 ;;; only at top level in the file.
2365 (bottom-edge (car (cdr (cdr (cdr (window-edges)))))) 2638 ;;; So I moved these to top level. But the conditionals on
2366 (last-window (previous-window)) 2639 ;;; purify-flag make these no-ops when you load ediff.
2367 (window-search t)) 2640 ;;; They only do something in loaddefs.el.
2368 (while window-search 2641
2369 (let* ((this-window (next-window)) 2642 ;;;###autoload
2370 (next-bottom-edge (car (cdr (cdr (cdr 2643 (if purify-flag
2371 (window-edges this-window))))))) 2644 ;; explicit string-match, as ediff-xemacs-p is not defined at build time
2372 (if (< bottom-edge next-bottom-edge) 2645 (if (string-match "\\(Lucid\\|Xemacs\\)" emacs-version)
2373 (progn 2646 ()
2374 (setq bottom-edge next-bottom-edge) 2647 (defvar menu-bar-epatch-menu (make-sparse-keymap "Epatch"))
2375 (setq lowest-window this-window))) 2648 (fset 'menu-bar-epatch-menu (symbol-value 'menu-bar-epatch-menu))
2376 2649 (defvar menu-bar-ediff-merge-menu (make-sparse-keymap "Ediff merge"))
2377 (select-window this-window) 2650 (fset 'menu-bar-ediff-merge-menu
2378 (if (eq last-window this-window) 2651 (symbol-value 'menu-bar-ediff-merge-menu))
2379 (progn 2652 (defvar menu-bar-ediff-menu (make-sparse-keymap "Ediff"))
2380 (select-window lowest-window) 2653 (fset 'menu-bar-ediff-menu (symbol-value 'menu-bar-ediff-menu))
2381 (setq window-search nil))))))) 2654 (define-key menu-bar-file-menu [epatch]
2382 2655 '("Apply Patch" . menu-bar-epatch-menu))
2383 ;;; Common setup routines 2656 (define-key menu-bar-file-menu [ediff-merge]
2384 2657 '("Merge" . menu-bar-ediff-merge-menu))
2385 ;; Set up the window configuration. If POS is given, set the points to 2658 (define-key menu-bar-file-menu [ediff]
2386 ;; the beginnings of the buffers. 2659 '("Compare" . menu-bar-ediff-menu))
2387 (defun ediff-setup-windows (buffer-A buffer-B control-buffer &optional pos) 2660 ))
2388 ;; Make sure we are not in the minibuffer window when we try to delete 2661
2389 ;; all other windows. 2662
2390 (if (eq (selected-window) (minibuffer-window)) 2663 ;;;###autoload
2391 (other-window 1)) 2664 (if purify-flag
2392 (or (ediff-leave-window-config control-buffer) 2665 ;; explicit string-match, as ediff-xemacs-p is not defined at build time
2393 (progn 2666 (if (string-match "\\(Lucid\\|Xemacs\\)" emacs-version)
2394 (delete-other-windows) 2667 ()
2395 (switch-to-buffer control-buffer) 2668 (define-key menu-bar-ediff-menu [ediff-revision]
2396 (ediff-refresh-mode-line) 2669 '("File with Revision ..." . ediff-revision))
2397 2670 (define-key menu-bar-ediff-menu [ediff-large-regions]
2398 (ediff-arrange-buffer buffer-A buffer-B (current-buffer) pos) 2671 '("Large Regions ..." . ediff-large-regions))
2399 (ediff-arrange-buffer buffer-B buffer-A (current-buffer) pos) 2672 (define-key menu-bar-ediff-menu [ediff-small-regions]
2400 ;; ediff-arrange-buffer always leaves in ctl buffer 2673 '("Small Regions ..." . ediff-small-regions))
2401 ;; setup ctl wind if it is not set. 2674 (define-key menu-bar-ediff-menu [ediff-windows]
2402 (ediff-setup-control-window) 2675 '("Windows ..." . ediff-windows))
2403 2676 ))
2404 ;; If diff reports errors, show them then quit. 2677
2405 (if (/= 0 (ediff-eval-in-buffer ediff-error-buffer (buffer-size))) 2678 ;;;###autoload
2406 (let ((diff-output-buf ediff-diff-buffer)) 2679 (if purify-flag
2407 (switch-to-buffer ediff-error-buffer) 2680 ;; explicit string-match, as ediff-xemacs-p is not defined at build time
2408 (ediff-kill-buffer-carefully control-buffer) 2681 (if (string-match "\\(Lucid\\|Xemacs\\)" emacs-version)
2409 (error "Errors found in diff output. Diff output buffer is %s" 2682 ()
2410 diff-output-buf)))))) 2683 (define-key menu-bar-ediff-menu [ediff-buffers3]
2411 2684 '("Three Buffers ..." . ediff-buffers3))
2412 2685 (define-key menu-bar-ediff-menu [ediff-files3]
2413 ;; Arranges goal-buf on the screen. 2686 '("Three Files ..." . ediff-files3))
2414 (defun ediff-arrange-buffer (goal-buf other-buf ctl-buf &optional pos) 2687 (define-key menu-bar-ediff-menu [ediff-buffers]
2415 (let* ((ctl-wind (ediff-get-visible-buffer-window ctl-buf)) 2688 '("Two Buffers ..." . ediff-buffers))
2416 (goal-wind (ediff-get-visible-buffer-window goal-buf)) 2689 (define-key menu-bar-ediff-menu [ediff-files]
2417 (other-wind (ediff-get-visible-buffer-window other-buf)) 2690 '("Two Files ..." . ediff-files))
2418 (ctl-frame (ediff-window-frame ctl-wind)) 2691 ))
2419 (goal-frame (if goal-wind (ediff-window-frame goal-wind))) 2692
2420 (other-frame (if other-wind (ediff-window-frame other-wind))) 2693 ;;;###autoload
2421 (ctl-frame-shared (or (eq ctl-frame goal-frame) 2694 (if purify-flag
2422 (eq ctl-frame other-frame)))) 2695 ;; explicit string-match, as ediff-xemacs-p is not defined at build time
2423 2696 (if (string-match "\\(Lucid\\|Xemacs\\)" emacs-version)
2424 (cond ((and goal-frame 2697 ()
2425 (not (eq goal-wind other-wind))) 2698 (define-key
2426 ;; goal buffer is visible and we are not comparing file 2699 menu-bar-ediff-merge-menu [ediff-merge-revisions-with-ancestor]
2427 ;; against itself (by mistake). 2700 '("Revisions with Ancestor ..." . ediff-merge-revisions-with-ancestor))
2428 ;; Note: goal-frame != ctl-frame, as we deleted other 2701 (define-key menu-bar-ediff-merge-menu [ediff-merge-revisions]
2429 ;; windows on ctl-frame. 2702 '("Revisions ..." . ediff-merge-revisions))
2430 (ediff-select-frame goal-frame) 2703 (define-key menu-bar-ediff-merge-menu [ediff-merge-buffers-with-ancestor]
2431 (select-window goal-wind) 2704 '("Buffers with Ancestor ..." . ediff-merge-buffers-with-ancestor))
2432 (delete-other-windows)) 2705 (define-key menu-bar-ediff-merge-menu [ediff-merge-buffers]
2433 2706 '("Buffers ..." . ediff-merge-buffers))
2434 ;; goal-buf invisible, ctl-frame has only ctl-buf 2707 (define-key menu-bar-ediff-merge-menu [ediff-merge-files-with-ancestor]
2435 ;; then put goal-buf on ctl-frame 2708 '("Files with Ancestor ..." . ediff-merge-files-with-ancestor))
2436 ((null ctl-frame-shared) 2709 (define-key menu-bar-ediff-merge-menu [ediff-merge-files]
2437 (ediff-select-frame ctl-frame) 2710 '("Files ..." . ediff-merge-files))
2438 (split-window-vertically) 2711 ))
2439 (ediff-select-lowest-window)
2440 (setq ctl-wind (selected-window))
2441 (switch-to-buffer ctl-buf)
2442 (ediff-setup-control-window)
2443 (other-window 1)
2444 (switch-to-buffer goal-buf)) ; goal-buf set
2445 ;; goal-buf invisible, ctl-frame has ctl-buf and other-buf
2446 ;; So, put everything in one frame
2447 (other-frame ;; share with the other buf
2448 (ediff-select-frame ctl-frame)
2449 (select-window other-wind)
2450 (funcall ediff-split-window-function)
2451 (other-window 1)
2452 (switch-to-buffer goal-buf))
2453 (t ;; debug
2454 (error "Funny window combination (Ediff bug?)")))
2455
2456 (if pos
2457 (goto-char (point-min)))
2458
2459 (ediff-select-frame ctl-frame)
2460 (select-window ctl-wind)
2461 (switch-to-buffer ctl-buf)))
2462 2712
2463 ;; This function assumes that we are in the window where control buffer is 2713 ;;;###autoload
2464 ;; to reside. 2714 (if purify-flag
2465 (defun ediff-setup-control-window () 2715 ;; explicit string-match, as ediff-xemacs-p is not defined at build time
2466 "Set up window for control buffer." 2716 (if (string-match "\\(Lucid\\|Xemacs\\)" emacs-version)
2467 (let ((window-min-height 2))
2468 (erase-buffer)
2469 (insert ediff-help-message)
2470 (shrink-window-if-larger-than-buffer)
2471 (setq ediff-control-window (selected-window))
2472 (setq ediff-window-config-saved
2473 (format "%S%S%S%S"
2474 ediff-control-window
2475 (ediff-get-visible-buffer-window ediff-A-buffer)
2476 (ediff-get-visible-buffer-window ediff-B-buffer)
2477 ediff-split-window-function))
2478 (goto-char (point-min))
2479 (skip-chars-forward ediff-whitespace)))
2480
2481 (defun ediff-leave-window-config (control-buf)
2482 (and (eq control-buf (current-buffer))
2483 (/= (buffer-size) 0)
2484 (ediff-eval-in-buffer
2485 control-buf
2486 (string= ediff-window-config-saved
2487 (format "%S%S%S%S"
2488 (ediff-get-visible-buffer-window ediff-control-buffer)
2489 (ediff-get-visible-buffer-window ediff-A-buffer)
2490 (ediff-get-visible-buffer-window ediff-B-buffer)
2491 ediff-split-window-function)))))
2492
2493
2494 ;; Set up the keymap in the control buffer
2495 (defun ediff-set-keys ()
2496 "Set up Ediff keymap, if necessary."
2497 (if (null ediff-mode-map)
2498 (ediff-setup-keymap))
2499 (use-local-map ediff-mode-map))
2500
2501 ;; Reload Ediff keymap. For debugging only.
2502 (defun ediff-reload-keymap ()
2503 (interactive)
2504 (setq ediff-mode-map nil)
2505 (ediff-set-keys))
2506
2507 (defun ediff-before-change-guard (start end)
2508 "If buffer is highlighted with ASCII flags, remove highlighting.
2509 Arguments, START and END are not used, but are provided
2510 because this is required by `before-change-function'."
2511 (let (rehighlight-key)
2512 (save-window-excursion
2513 (mapcar
2514 (function
2515 (lambda (buf)
2516 (ediff-eval-in-buffer
2517 buf
2518 (if (eq ediff-highlighting-style 'ascii)
2519 (progn
2520 (ediff-unselect-and-select-difference
2521 ediff-current-difference
2522 'unselect-only 'no-recenter)
2523 (setq rehighlight-key
2524 (substitute-command-keys "\\[ediff-recenter]"))
2525 )))))
2526 ediff-this-buffer-control-sessions)
2527 (if rehighlight-key
2528 (error
2529 "ASCII flags removed. You can edit now. Hit %S to rehighlight."
2530 rehighlight-key))
2531 )))
2532
2533 (defun ediff-recompute-diffs ()
2534 "Recompute difference regions in buffers A and B."
2535 (interactive)
2536 (let ((point-A (ediff-eval-in-buffer ediff-A-buffer (point)))
2537 (point-B (ediff-eval-in-buffer ediff-B-buffer (point)))
2538 file-A file-B)
2539 (ediff-unselect-and-select-difference -1)
2540 (ediff-eval-in-buffer
2541 ediff-A-buffer
2542 (setq file-A (ediff-make-temp-file)))
2543 (ediff-eval-in-buffer
2544 ediff-B-buffer
2545 (setq file-B (ediff-make-temp-file)))
2546 (ediff-clear-diff-vector ediff-difference-vector 'fine-diffs-also)
2547 (setq ediff-killed-diffs-alist nil) ; saved kills will no longer be valid
2548 ; after recompute
2549 (setq ediff-difference-vector
2550 (ediff-setup-diff-regions file-A file-B 'use-old))
2551 (setq ediff-number-of-differences (length ediff-difference-vector))
2552 (delete-file file-A)
2553 (delete-file file-B)
2554 (ediff-eval-in-buffer ediff-A-buffer (goto-char point-A))
2555 (ediff-jump-to-difference (ediff-diff-at-point 'A))
2556 (beep 1)
2557 (if (y-or-n-p
2558 "Ediff is at last posn in buff A. Stay (or goto last posn in B)? ")
2559 () 2717 ()
2560 (ediff-eval-in-buffer ediff-B-buffer (goto-char point-B)) 2718 (define-key menu-bar-epatch-menu [ediff-patch-buffer]
2561 (ediff-jump-to-difference (ediff-diff-at-point 'B))) 2719 '("To a Buffer ..." . ediff-patch-buffer))
2562 (message "") 2720 (define-key menu-bar-epatch-menu [ediff-patch-file]
2563 )) 2721 '("To a File ..." . ediff-patch-file))
2564 2722 ))
2565 (defun ediff-remember-buffer-characteristics (&optional arg)
2566 "Record certain properties of the buffers being compared.
2567 Must be called in the control buffer. Saves `read-only', `modified',
2568 and `auto-save' properties in buffer local variables. Turns off
2569 `auto-save-mode'. These properties are restored via a call to
2570 `ediff-restore-buffer-characteristics'."
2571
2572 ;; remember and alter buffer characteristics
2573 (set (if arg 'ediff-A-buffer-values-setup 'ediff-A-buffer-values)
2574 (ediff-eval-in-buffer
2575 ediff-A-buffer
2576 (prog1
2577 (emerge-save-variables ediff-saved-variables)
2578 (emerge-restore-variables ediff-saved-variables
2579 ediff-working-values))))
2580 (set (if arg 'ediff-B-buffer-values-setup 'ediff-B-buffer-values)
2581 (ediff-eval-in-buffer
2582 ediff-B-buffer
2583 (prog1
2584 (emerge-save-variables ediff-saved-variables)
2585 (emerge-restore-variables ediff-saved-variables
2586 ediff-working-values)))))
2587
2588 (defun ediff-restore-buffer-characteristics (&optional arg)
2589 "Restores properties saved by `ediff-remember-buffer-characteristics'."
2590 (let ((A-values (if arg ediff-A-buffer-values-setup ediff-A-buffer-values))
2591 (B-values (if arg ediff-B-buffer-values-setup ediff-B-buffer-values)))
2592 2723
2593 (ediff-eval-in-buffer ediff-A-buffer 2724
2594 (emerge-restore-variables ediff-saved-variables 2725 ;;;###autoload
2595 A-values)) 2726 (if purify-flag
2596 (ediff-eval-in-buffer ediff-B-buffer 2727 ;; explicit string-match, as ediff-xemacs-p is not defined at build time
2597 (emerge-restore-variables ediff-saved-variables 2728 (if (string-match "\\(Lucid\\|Xemacs\\)" emacs-version)
2598 B-values))))
2599
2600
2601 ;; If optional A-buffer and B-buffer are given, then construct a vector of
2602 ;; diff using point values. Otherwise, use line offsets.
2603 (defun ediff-extract-diffs (diff-buffer &optional A-buffer B-buffer)
2604 (let (diff-list
2605 (a-prev 1) ;; this is needed to set the first diff line correctly
2606 (b-prev 1))
2607
2608 (if (and A-buffer B-buffer)
2609 (progn ;; reset point in buffers A and B
2610 (ediff-eval-in-buffer
2611 A-buffer
2612 (goto-char (point-min)))
2613 (ediff-eval-in-buffer
2614 B-buffer
2615 (goto-char (point-min)))))
2616
2617 (ediff-eval-in-buffer
2618 diff-buffer
2619 (goto-char (point-min))
2620 (while (re-search-forward ediff-match-diff-line nil t)
2621 (let* ((a-begin (string-to-int (buffer-substring (match-beginning 1)
2622 (match-end 1))))
2623 (a-end (let ((b (match-beginning 3))
2624 (e (match-end 3)))
2625 (if b
2626 (string-to-int (buffer-substring b e))
2627 a-begin)))
2628 (diff-type (buffer-substring (match-beginning 4) (match-end 4)))
2629 (b-begin (string-to-int (buffer-substring (match-beginning 5)
2630 (match-end 5))))
2631 (b-end (let ((b (match-beginning 7))
2632 (e (match-end 7)))
2633 (if b
2634 (string-to-int (buffer-substring b e))
2635 b-begin)))
2636 a-begin-pt a-end-pt b-begin-pt b-end-pt)
2637 ;; fix the beginning and end numbers, because diff is somewhat
2638 ;; strange about how it numbers lines
2639 (if (string-equal diff-type "a")
2640 (setq b-end (1+ b-end)
2641 a-begin (1+ a-begin)
2642 a-end a-begin)
2643 (if (string-equal diff-type "d")
2644 (setq a-end (1+ a-end)
2645 b-begin (1+ b-begin)
2646 b-end b-begin)
2647 ;; (string-equal diff-type "c")
2648 (setq a-end (1+ a-end)
2649 b-end (1+ b-end))))
2650 (if (and A-buffer B-buffer)
2651 (progn ;; computing main diff vector
2652 ;; convert to relative line numbers
2653 (ediff-eval-in-buffer
2654 A-buffer
2655 (forward-line (- a-begin a-prev))
2656 (setq a-begin-pt (point))
2657 (forward-line (- a-end a-begin))
2658 (setq a-end-pt (point)
2659 a-prev a-end))
2660 (ediff-eval-in-buffer
2661 B-buffer
2662 (forward-line (- b-begin b-prev))
2663 (setq b-begin-pt (point))
2664 (forward-line (- b-end b-begin))
2665 (setq b-end-pt (point)
2666 b-prev b-end))
2667 (setq diff-list
2668 (nconc diff-list (list (vector a-begin-pt a-end-pt
2669 b-begin-pt b-end-pt)))))
2670 ;; computing refinement vector
2671 (setq diff-list
2672 (nconc diff-list (list (vector (- a-begin a-prev)
2673 (- a-end a-begin)
2674 (- b-begin b-prev)
2675 (- b-end b-begin))))
2676 a-prev a-end
2677 b-prev b-end))
2678
2679 ))) ;; end ediff-eval-in-buffer
2680 diff-list
2681 ))
2682
2683 (defun ediff-convert-diffs-to-overlays (A-buffer B-buffer diff-list)
2684 (let* ((current-diff -1)
2685 (total-diffs (length diff-list))
2686 ; (control-buffer-suffix ediff-control-buffer-suffix)
2687 diff-overlay-list list-element
2688 a-begin a-end b-begin b-end
2689 a-overlay b-overlay)
2690
2691 (while diff-list
2692 (setq current-diff (1+ current-diff)
2693 list-element (car diff-list)
2694 a-begin (aref list-element 0)
2695 a-end (aref list-element 1)
2696 b-begin (aref list-element 2)
2697 b-end (aref list-element 3))
2698
2699 ;; Put overlays at appropriate places in buffers
2700 (setq a-overlay (ediff-make-overlay a-begin a-end A-buffer))
2701 ;; Priorities of overlays should be equal in all ediff control
2702 ;; panels buffers. Otherwise it won't work due to Emacs
2703 ;; bug---insert-in-front-hooks will be called
2704 ;; only on behalf of the buffer with higher priority.
2705 (ediff-overlay-put a-overlay 'priority ediff-shaded-overlay-priority)
2706 (ediff-overlay-put a-overlay 'ediff-diff-num current-diff)
2707 (ediff-overlay-put a-overlay
2708 'insert-in-front-hooks '(ediff-insert-in-front))
2709 ; (ediff-overlay-put a-overlay
2710 ; 'ediff-control-buffer control-buffer-suffix)
2711 (ediff-overlay-put a-overlay
2712 'face (if (ediff-odd-p current-diff) ;; odd diff
2713 'ediff-odd-diff-face-A-var
2714 'ediff-even-diff-face-A-var))
2715
2716 (setq b-overlay (ediff-make-overlay b-begin b-end B-buffer))
2717 (ediff-overlay-put b-overlay 'priority ediff-shaded-overlay-priority)
2718 (ediff-overlay-put b-overlay 'ediff-diff-num current-diff)
2719 (ediff-overlay-put b-overlay
2720 'insert-in-front-hooks '(ediff-insert-in-front))
2721 ; (ediff-overlay-put b-overlay
2722 ; 'ediff-control-buffer control-buffer-suffix)
2723 (ediff-overlay-put b-overlay
2724 'face (if (ediff-odd-p current-diff) ;; odd diff
2725 'ediff-odd-diff-face-B-var
2726 'ediff-even-diff-face-B-var))
2727
2728 (if (ediff-if-lucid) ;; chars inserted at end will be inside extent
2729 (progn
2730 (ediff-overlay-put a-overlay
2731 'ediff-marker
2732 (move-marker (make-marker) a-begin A-buffer))
2733 (ediff-overlay-put b-overlay
2734 'ediff-marker
2735 (move-marker (make-marker) b-begin B-buffer))
2736 (ediff-overlay-put a-overlay 'end-open nil)
2737 (ediff-overlay-put b-overlay 'end-open nil)))
2738
2739 ;; record all overlays for this difference
2740 (setq diff-overlay-list
2741 (nconc diff-overlay-list
2742 (list (vector a-overlay b-overlay nil nil)))
2743 diff-list
2744 (cdr diff-list))
2745 (message "Processing diff region %d of %d"
2746 current-diff total-diffs)
2747 ) ;; while
2748 ;; this is just to avoid confusing the user with diff num < total-diffs
2749 (message "Processing diff region %d of %d"
2750 (1+ current-diff) total-diffs)
2751 ;; convert the list of difference information into a vector for
2752 ;; fast access
2753 (apply 'vector diff-overlay-list)))
2754
2755
2756
2757 ;;; Commands
2758
2759 (defun ediff-recenter (&optional no-rehighlight)
2760 "Bring the highlighted region of all buffers A and B into view.
2761 Reestablish the default three-window display."
2762 (interactive)
2763 (setq ediff-disturbed-overlays nil) ;; clear after use
2764 (let (buffer-read-only)
2765 (if (and (ediff-buffer-live-p ediff-A-buffer)
2766 (ediff-buffer-live-p ediff-B-buffer))
2767 (ediff-setup-windows
2768 ediff-A-buffer ediff-B-buffer ediff-control-buffer)))
2769 ;; Redisplay whatever buffers are showing, if there is a selected difference
2770 (if (and (ediff-buffer-live-p ediff-A-buffer)
2771 (ediff-buffer-live-p ediff-B-buffer)
2772 (>= ediff-current-difference 0)
2773 (< ediff-current-difference ediff-number-of-differences))
2774 (let* ( ;; context must be saved before switching to windows A/B
2775 (buffer-A ediff-A-buffer)
2776 (buffer-B ediff-B-buffer)
2777 (wind (selected-window))
2778 (control-buf ediff-control-buffer)
2779 (before-flag-shift-A (if (eq ediff-highlighting-style 'ascii)
2780 (1- (length ediff-before-flag-A))
2781 0))
2782 (after-flag-shift-A (if (eq ediff-highlighting-style 'ascii)
2783 (1- (length ediff-after-flag-A))
2784 0))
2785 (before-flag-shift-B (if (eq ediff-highlighting-style 'ascii)
2786 (1- (length ediff-before-flag-B))
2787 0))
2788 (after-flag-shift-B (if (eq ediff-highlighting-style 'ascii)
2789 (1- (length ediff-after-flag-B))
2790 0))
2791 (window-A (ediff-get-visible-buffer-window buffer-A))
2792 (window-B (ediff-get-visible-buffer-window buffer-B)))
2793
2794 (or no-rehighlight
2795 (ediff-operate-on-flags 'insert))
2796
2797 (if window-A (progn
2798 (select-window window-A)
2799 (ediff-position-region
2800 (- (ediff-get-diff-posn 'A 'beg nil control-buf)
2801 before-flag-shift-A)
2802 (+ (ediff-get-diff-posn 'A 'end nil control-buf)
2803 after-flag-shift-A)
2804 (ediff-get-diff-posn 'A 'beg nil control-buf))))
2805 (if window-B (progn
2806 (select-window window-B)
2807 (ediff-position-region
2808 (- (ediff-get-diff-posn 'B 'beg nil control-buf)
2809 before-flag-shift-B)
2810 (+ (ediff-get-diff-posn 'B 'end nil control-buf)
2811 after-flag-shift-B)
2812 (ediff-get-diff-posn 'B 'beg nil control-buf))))
2813 (select-window wind))))
2814
2815 (defun ediff-toggle-split ()
2816 "Toggle vertical/horizontal window split.
2817 Does nothing if file-A and file-B are in different frames."
2818 (interactive)
2819 (let* ((wind-A (ediff-get-visible-buffer-window ediff-A-buffer))
2820 (wind-B (ediff-get-visible-buffer-window ediff-B-buffer))
2821 (frame-A (if wind-A (ediff-window-frame wind-A)))
2822 (frame-B (if wind-B (ediff-window-frame wind-B))))
2823 (if (eq frame-A frame-B)
2824 (setq ediff-split-window-function
2825 (if (eq ediff-split-window-function 'split-window-vertically)
2826 'split-window-horizontally
2827 'split-window-vertically))
2828 (message "No splitting: Buffers A and B are in different frames."))
2829 (ediff-recenter 'no-rehighlight)))
2830
2831 (defun ediff-toggle-hilit ()
2832 "Switch between highlighting using ASCII flags and highlighting using faces.
2833 On a dumb terminal, switches between ASCII highlighting and no highlighting."
2834 (interactive)
2835 (if (not window-system)
2836 (if (eq ediff-highlighting-style 'ascii)
2837 (progn
2838 (message "ASCII highlighting flags removed.")
2839 (ediff-unselect-and-select-difference ediff-current-difference
2840 'unselect-only)
2841 (setq ediff-highlighting-style 'off))
2842 (ediff-unselect-and-select-difference ediff-current-difference
2843 'select-only))
2844 (ediff-unselect-and-select-difference ediff-current-difference
2845 'unselect-only)
2846 ;; cycle through highlighting
2847 (cond ((and ediff-want-faces ediff-highlight-all-diffs)
2848 (message "Unhighlighting unselected difference regions.")
2849 (setq ediff-highlight-all-diffs nil))
2850 (ediff-want-faces
2851 (message "Highlighting with ASCII flags.")
2852 (setq ediff-want-faces nil))
2853 (t
2854 (message "Re-highlighting all difference regions.")
2855 (setq ediff-want-faces t
2856 ediff-highlight-all-diffs t)))
2857
2858 (if (and ediff-want-faces ediff-highlight-all-diffs)
2859 (if (not (face-differs-from-default-p 'ediff-odd-diff-face-A-var))
2860 (progn
2861 (copy-face ediff-odd-diff-face-A 'ediff-odd-diff-face-A-var)
2862 (copy-face ediff-odd-diff-face-B 'ediff-odd-diff-face-B-var)
2863 (copy-face ediff-even-diff-face-A 'ediff-even-diff-face-A-var)
2864 (copy-face ediff-even-diff-face-B 'ediff-even-diff-face-B-var)))
2865 (copy-face 'default 'ediff-odd-diff-face-A-var)
2866 (copy-face 'default 'ediff-odd-diff-face-B-var)
2867 (copy-face 'default 'ediff-even-diff-face-A-var)
2868 (copy-face 'default 'ediff-even-diff-face-B-var))
2869
2870 (ediff-unselect-and-select-difference
2871 ediff-current-difference 'select-only))
2872 (ediff-operate-on-flags 'insert)
2873 )
2874
2875 (defun ediff-toggle-autorefine ()
2876 "Toggle auto-refine mode."
2877 (interactive)
2878 (cond ((eq ediff-auto-refine 'nix)
2879 (setq ediff-auto-refine 'on)
2880 (ediff-make-fine-diffs ediff-current-difference 'noforce)
2881 (message "Auto-refining is ON."))
2882 ((eq ediff-auto-refine 'on)
2883 (message "Auto-refining is OFF.")
2884 (setq ediff-auto-refine 'off))
2885 (t
2886 (ediff-set-fine-diff-properties ediff-current-difference 'default)
2887 (message "Refinements are HIDDEN.")
2888 (setq ediff-auto-refine 'nix))
2889 ))
2890
2891 (defun ediff-toggle-help ()
2892 "Toggle short/long help message."
2893 (interactive)
2894 (let (buffer-read-only)
2895 (erase-buffer)
2896 (if (string= ediff-help-message ediff-help-message-long)
2897 (setq ediff-help-message ediff-help-message-short)
2898 (setq ediff-help-message ediff-help-message-long)))
2899 (setq ediff-window-config-saved "") ;; force redisplay
2900 (ediff-recenter 'no-rehighlight))
2901
2902
2903 (defun ediff-toggle-read-only-patch-orig ()
2904 "Used as a startup hook to set `.orig' patch file read-only."
2905 (ediff-toggle-read-only ediff-A-buffer))
2906
2907 (defun ediff-toggle-read-only (&optional buff)
2908 "Toggles read-only in buffers A and B.
2909 If buffer is under version control and locked, check it out first."
2910 (interactive)
2911 ;; Optional argument, BUF, is passed only in a startup hook.
2912 (or buff (ediff-recenter))
2913
2914 (ediff-eval-in-buffer
2915 (or buff (if (eq last-command-char ?A) ediff-A-buffer ediff-B-buffer))
2916 (let* ((file (buffer-file-name (current-buffer)))
2917 (file-writable (and file (file-writable-p file)))
2918 (toggle-ro-cmd (cond (ediff-toggle-read-only-function)
2919 (ediff-local-checkout-flag
2920 (if (and file (not file-writable))
2921 (progn
2922 (beep 1)
2923 (message "Warning: file %s is read-only."
2924 (abbreviate-file-name file))))
2925 'toggle-read-only)
2926 (file-writable 'toggle-read-only)
2927 (t (key-binding "\C-x\C-q")))))
2928 (if (and toggle-ro-cmd
2929 (string-match "toggle-read-only" (symbol-name toggle-ro-cmd)))
2930 (save-window-excursion
2931 (setq ediff-local-checkout-flag t)
2932 (or buff
2933 (select-window
2934 (ediff-get-visible-buffer-window (current-buffer))))
2935 (command-execute toggle-ro-cmd))
2936 (error "Don't know how to toggle read-only in buffer %S"
2937 (current-buffer))))))
2938
2939
2940
2941 ;;; Window scrolling operations
2942
2943 ;; Perform some operation on the two file windows (if they are showing).
2944 ;; Catches all errors on the operation in the A and B windows.
2945 ;; Usually, errors come from scrolling off the
2946 ;; beginning or end of the buffer, and this gives nice nice error messages.
2947 (defun ediff-operate-on-windows (operation arg)
2948 (let* ((buffer-A ediff-A-buffer)
2949 (buffer-B ediff-B-buffer)
2950 (wind (selected-window))
2951 (window-A (ediff-get-visible-buffer-window buffer-A))
2952 (window-B (ediff-get-visible-buffer-window buffer-B)))
2953 (if window-A (progn
2954 (select-window window-A)
2955 (condition-case nil
2956 (funcall operation arg)
2957 (error))))
2958 (if window-B (progn
2959 (select-window window-B)
2960 (condition-case nil
2961 (funcall operation arg)
2962 (error))))
2963 (select-window wind)
2964 ))
2965
2966 (defun ediff-scroll-up (&optional arg)
2967 "Scroll up buffers A and B, if they are in windows.
2968 With optional argument ARG, scroll ARG lines; otherwise scroll by nearly
2969 the height of window-A."
2970 (interactive "P")
2971 (ediff-operate-on-windows
2972 'scroll-up
2973 ;; calculate argument to scroll-up
2974 ;; if there is an explicit argument
2975 (if (and arg (not (equal arg '-)))
2976 ;; use it
2977 (prefix-numeric-value arg)
2978 ;; if not, see if we can determine a default amount (the window height)
2979 (let* ((window-A (ediff-get-visible-buffer-window ediff-A-buffer))
2980 (window-B (ediff-get-visible-buffer-window ediff-B-buffer))
2981 default-amount)
2982 (if (or (null window-A) (null window-B))
2983 (setq default-amount 0)
2984 (setq default-amount
2985 (- (min (window-height window-A) (window-height window-B))
2986 1 next-screen-context-lines)))
2987 ;; the window was found
2988 (if arg
2989 ;; C-u as argument means half of default amount
2990 (/ default-amount 2)
2991 ;; no argument means default amount
2992 default-amount)))))
2993
2994 (defun ediff-scroll-down (&optional arg)
2995 "Scroll down buffers A and B, if they are in windows.
2996 With optional argument ARG, scroll ARG lines; otherwise scroll by nearly
2997 the height of window-A."
2998 (interactive "P")
2999 (ediff-operate-on-windows
3000 'scroll-down
3001 ;; calculate argument to scroll-down
3002 ;; if there is an explicit argument
3003 (if (and arg (not (equal arg '-)))
3004 ;; use it
3005 (prefix-numeric-value arg)
3006 ;; if not, see if we can determine a default amount (the window height)
3007 (let* ((window-A (ediff-get-visible-buffer-window ediff-A-buffer))
3008 (window-B (ediff-get-visible-buffer-window ediff-B-buffer))
3009 default-amount)
3010 (if (or (null window-A) (null window-B))
3011 (setq default-amount 0)
3012 (setq default-amount
3013 (- (min (window-height window-A) (window-height window-B))
3014 1 next-screen-context-lines)))
3015 ;; the window was found
3016 (if arg
3017 ;; C-u as argument means half of default amount
3018 (/ default-amount 2)
3019 ;; no argument means default amount
3020 default-amount)))))
3021
3022 (defun ediff-scroll-left (&optional arg)
3023 "Scroll left buffer-A and buffer-B, if they are in windows.
3024 If an argument is given, that is how many columns are scrolled, else nearly
3025 the width of the A and B windows."
3026 (interactive "P")
3027 (ediff-operate-on-windows
3028 'scroll-left
3029 ;; calculate argument to scroll-left
3030 ;; if there is an explicit argument
3031 (if (and arg (not (equal arg '-)))
3032 ;; use it
3033 (prefix-numeric-value arg)
3034 ;; if not, see if we can determine a default amount
3035 ;; (half the window width)
3036 (if (null ediff-control-window)
3037 ;; no control window, use nil
3038 nil
3039 (let ((default-amount
3040 (- (/ (window-width ediff-control-window) 2) 3)))
3041 ;; the window was found
3042 (if arg
3043 ;; C-u as argument means half of default amount
3044 (/ default-amount 2)
3045 ;; no argument means default amount
3046 default-amount))))))
3047
3048 (defun ediff-scroll-right (&optional arg)
3049 "Scroll right buffer-A and buffer-B, if they are in windows.
3050 If an argument is given, that is how many columns are scrolled, else nearly
3051 the width of the A and B windows."
3052 (interactive "P")
3053 (ediff-operate-on-windows
3054 'scroll-right
3055 ;; calculate argument to scroll-right
3056 ;; if there is an explicit argument
3057 (if (and arg (not (equal arg '-)))
3058 ;; use it
3059 (prefix-numeric-value arg)
3060 ;; if not, see if we can determine a default amount
3061 ;; (half the window width)
3062 (if (null ediff-control-window)
3063 ;; no control window, use nil
3064 nil
3065 (let ((default-amount
3066 (- (/ (window-width ediff-control-window) 2) 3)))
3067 ;; the window was found
3068 (if arg
3069 ;; C-u as argument means half of default amount
3070 (/ default-amount 2)
3071 ;; no argument means default amount
3072 default-amount))))))
3073
3074 (defun ediff-position-region (beg end pos)
3075 "This is a variation on `emerge-position-region'.
3076 The difference is that it always tries to align difference regions in
3077 buffer-A and buffer-B, so that it will be easier to compare them."
3078 (set-window-start (selected-window) beg)
3079 (if (pos-visible-in-window-p end)
3080 ;; Determine the number of lines that the region occupies
3081 (let ((lines 0))
3082 (while (> end (progn
3083 (move-to-window-line lines)
3084 (point)))
3085 (setq lines (1+ lines)))
3086 ;; And position the beginning on the right line
3087 (goto-char beg)
3088 (recenter (/ (1+ (max (- (1- (window-height (selected-window)))
3089 lines)
3090 1)
3091 )
3092 2))))
3093 (goto-char pos)
3094 )
3095
3096
3097 (defun ediff-next-difference (&optional arg)
3098 "Advance to the next difference.
3099 With a prefix argument, go back that many differences."
3100 (interactive "P")
3101 (if (< ediff-current-difference ediff-number-of-differences)
3102 (let ((n (min ediff-number-of-differences
3103 (+ ediff-current-difference (if arg arg 1))))
3104 buffer-read-only)
3105
3106 (while (and (< n ediff-number-of-differences)
3107 (funcall ediff-skip-diff-region-function n))
3108 (setq n (1+ n)))
3109
3110 (ediff-unselect-and-select-difference n)
3111 ;; possibly skip inessential difference regions
3112 (while (and ediff-ignore-similar-regions
3113 (< n ediff-number-of-differences)
3114 (ediff-no-fine-diffs n))
3115 (setq n (1+ n))
3116 (ediff-unselect-and-select-difference n))
3117 ) ;; let
3118 (error "At end of the difference list.")))
3119
3120 (defun ediff-previous-difference (&optional arg)
3121 "Go to the previous difference.
3122 With a prefix argument, go back that many differences."
3123 (interactive "P")
3124 (if (> ediff-current-difference -1)
3125 (let ((n (max -1 (- ediff-current-difference (if arg arg 1))))
3126 buffer-read-only)
3127
3128 (while (and (funcall ediff-skip-diff-region-function n)
3129 (> n -1))
3130 (setq n (1- n)))
3131 (ediff-unselect-and-select-difference n)
3132 ;; possibly skip inessential difference regions
3133 (while (and ediff-ignore-similar-regions
3134 (> n -1)
3135 (ediff-no-fine-diffs n))
3136 (setq n (1- n))
3137 (ediff-unselect-and-select-difference n))
3138 ) ;; let
3139 (error "At beginning of the difference list.")))
3140
3141 (defun ediff-jump-to-difference (difference-number)
3142 "Go to the difference specified as a prefix argument."
3143 (interactive "p")
3144 (let (buffer-read-only)
3145 (setq difference-number (1- difference-number))
3146 (if (and (>= difference-number -1)
3147 (< difference-number (1+ ediff-number-of-differences)))
3148 (ediff-unselect-and-select-difference difference-number)
3149 (error "Bad difference number"))))
3150
3151 (defun ediff-jump-to-difference-at-point ()
3152 "Go to the difference closest to the point in buffer A or B.
3153 If this command is invoked via `\\[ediff-jump-to-difference-at-point]'
3154 then the point in buffer B is used.
3155 Otherwise, buffer A's point is used."
3156 (interactive)
3157 (let ((buf-type (ediff-char-to-buftype last-command-char))
3158 buffer-read-only)
3159 (ediff-jump-to-difference (ediff-diff-at-point buf-type))))
3160
3161
3162 ;; find region "most related to the current point position
3163
3164 (defun ediff-diff-at-point (buf-type)
3165 (let ((buffer (ediff-get-buffer buf-type))
3166 (ctl-buffer ediff-control-buffer)
3167 (max-dif-num (1- ediff-number-of-differences))
3168 (diff-no -1)
3169 (prev-beg 0)
3170 (prev-end 0)
3171 (beg 0)
3172 (end 0))
3173
3174 (ediff-eval-in-buffer
3175 buffer
3176 (while (and (or (< (point) prev-beg) (> (point) beg))
3177 (< diff-no max-dif-num))
3178 (setq diff-no (1+ diff-no))
3179 (setq prev-beg beg
3180 prev-end end)
3181 (setq beg (ediff-get-diff-posn buf-type 'beg diff-no ctl-buffer)
3182 end (ediff-get-diff-posn buf-type 'end diff-no ctl-buffer))
3183 )
3184
3185 (if (< (abs (- (point) prev-end))
3186 (abs (- (point) beg)))
3187 diff-no
3188 (1+ diff-no)) ;; jump-to-diff works with diff nums higher by 1
3189 )))
3190
3191 ;;; Copying diffs.
3192
3193 (defun ediff-diff-to-diff (arg)
3194 "Copy buffer-A'th diff to buffer B.
3195 If numerical prefix argument, copy this diff specified in the arg.
3196 Otherwise, copy the difference given by `ediff-current-difference'."
3197 (interactive "P")
3198 (if arg
3199 (ediff-jump-to-difference arg))
3200 (let* ((key1 (aref (this-command-keys) 0))
3201 (key2 (aref (this-command-keys) 1))
3202 (char1 (if (ediff-if-lucid) (event-key key1) key1))
3203 (char2 (if (ediff-if-lucid) (event-key key2) key2)))
3204 (ediff-copy-diff ediff-current-difference
3205 (ediff-char-to-buftype char1)
3206 (ediff-char-to-buftype char2))
3207 (ediff-recenter 'no-rehighlight)))
3208
3209
3210 (defun ediff-copy-diff (n from-buf-type to-buf-type)
3211 "Copy diff N from FROM-BUF-TYPE \(given as 'A or 'B\) to TO-BUF-TYPE."
3212 (let* ((to-buf (ediff-get-buffer to-buf-type))
3213 (from-buf (ediff-get-buffer from-buf-type))
3214 (ctrl-buf ediff-control-buffer)
3215 reg-to-copy reg-to-delete
3216 reg-to-delete-beg reg-to-delete-end)
3217
3218 (ediff-operate-on-flags 'remove)
3219 (setq reg-to-delete-beg
3220 (ediff-get-diff-posn to-buf-type 'beg n ctrl-buf))
3221 (setq reg-to-delete-end
3222 (ediff-get-diff-posn to-buf-type 'end n ctrl-buf))
3223 (setq reg-to-copy (ediff-eval-in-buffer
3224 from-buf
3225 (buffer-substring (ediff-get-diff-posn
3226 from-buf-type 'beg n ctrl-buf)
3227 (ediff-get-diff-posn
3228 from-buf-type 'end n ctrl-buf))))
3229 (setq reg-to-delete (ediff-eval-in-buffer
3230 to-buf
3231 (buffer-substring reg-to-delete-beg
3232 reg-to-delete-end)))
3233 (setq ediff-disturbed-overlays nil) ;; clear before use
3234
3235 (if (string= reg-to-delete reg-to-copy)
3236 (progn 2729 (progn
3237 (ding) 2730 (defvar ediff-menu
3238 (message 2731 '(""
3239 "Diff regions %d are identical in buffers %S and %S. Nothing copied." 2732 ["Two Files ..." ediff-files t]
3240 (1+ n) from-buf-type to-buf-type)) 2733 ["Two Buffers ..." ediff-buffers t]
3241 2734 ["Three Files ..." ediff-files3 t]
3242 ;; seems ok to copy 2735 ["Three Buffers ..." ediff-buffers3 t]
3243 (if (ediff-test-save-region n to-buf-type) 2736 ["Windows ..." ediff-windows t]
3244 (condition-case conds 2737 ["Small Regions ..." ediff-small-regions t]
3245 (progn 2738 ["Large Regions ..." ediff-large-regions t]
3246 (ediff-eval-in-buffer 2739 ["File with Revision ..." ediff-revision t]))
3247 to-buf 2740 (defvar ediff-merge-menu
3248 ;; to prevent flags from interfering if buffer is writable 2741 '(""
3249 (let ((inhibit-read-only (null buffer-read-only)) 2742 ["Files ..." ediff-merge-files t]
3250 before-change-function) 2743 ["Files with Ancestor ..." ediff-merge-files-with-ancestor t]
3251 (goto-char reg-to-delete-end) 2744 ["Buffers ..." ediff-merge-buffers t]
3252 (insert-before-markers reg-to-copy) 2745 ["Buffers with Ancestor ..."
3253 (if (ediff-if-lucid) 2746 ediff-merge-buffers-with-ancestor t]
3254 (progn 2747 ["Revisions ..." ediff-merge-revisions t]
3255 (ediff-collect-extents-lucid reg-to-delete-beg) 2748 ["Revisions with Ancestor ..."
3256 (if (> reg-to-delete-end reg-to-delete-beg) 2749 ediff-merge-revisions-with-ancestor t]))
3257 (progn 2750 (defvar epatch-menu
3258 (kill-region reg-to-delete-beg 2751 '(""
3259 reg-to-delete-end) 2752 ["To a file ..." ediff-patch-file t]
3260 (if (string= reg-to-copy "") 2753 ["To a buffer ..." ediff-patch-buffer t]))
3261 (ediff-adjust-disturbed-extents-lucid 2754 (add-menu '("File") "Compare"
3262 reg-to-delete-beg))))) 2755 ediff-menu
3263 (if (> reg-to-delete-end reg-to-delete-beg) 2756 "New Frame")
3264 (kill-region reg-to-delete-beg reg-to-delete-end) 2757 (add-menu '("File") "Merge"
3265 (ediff-move-disturbed-overlays reg-to-delete-beg))) 2758 ediff-merge-menu
3266 )) 2759 "New Frame")
3267 (ediff-save-diff-region n to-buf-type reg-to-delete)) 2760 (add-menu '("File") "Apply Patch"
3268 (error (message "%s %s" 2761 epatch-menu
3269 (car conds) 2762 "New Frame")
3270 (mapconcat 'prin1-to-string (cdr conds) " ")) 2763 ;; Display a solid horizontal line
3271 (beep 1)))) 2764 (add-menu-item '("File") "---" nil nil "New Screen")
3272 ) 2765 )))
3273 (ediff-operate-on-flags 'insert) 2766
3274 ))
3275
3276 (defun ediff-save-diff-region (n buf-type reg)
3277 "Save Nth diff of buffer BUF-TYPE \(`A' or `B'\).
3278 That is to say, the Nth diff on the `ediff-killed-diffs-alist'. REG
3279 is the region to save. It is redundant here, but is passed anyway, for
3280 convenience."
3281
3282 (let* ((n-th-diff-saved (assoc n ediff-killed-diffs-alist))
3283 (this-buf-n-th-diff-saved (assoc buf-type (cdr n-th-diff-saved))))
3284
3285 (if this-buf-n-th-diff-saved
3286 ;; either nothing saved for n-th diff and buffer or we OK'ed
3287 ;; overriding
3288 (setcdr this-buf-n-th-diff-saved reg)
3289 (if n-th-diff-saved ;; n-th diff saved, but for another buffer
3290 (nconc n-th-diff-saved (list (cons buf-type reg)))
3291 (setq ediff-killed-diffs-alist ;; create record for n-th diff
3292 (cons (list n (cons buf-type reg))
3293 ediff-killed-diffs-alist))))
3294 (message "Saved diff region #%d for buffer %S. To recover hit 'r%s'."
3295 (1+ n) buf-type
3296 (downcase (symbol-name buf-type)))))
3297
3298 (defun ediff-test-save-region (n buf-type)
3299 "Test if saving Nth difference region of buffer BUF-TYPE is possible."
3300 (let* ((n-th-diff-saved (assoc n ediff-killed-diffs-alist))
3301 (this-buf-n-th-diff-saved (assoc buf-type (cdr n-th-diff-saved))))
3302
3303 (if this-buf-n-th-diff-saved
3304 (if (yes-or-no-p
3305 (format
3306 "You've previously copied diff region %d to buffer %S. Confirm."
3307 (1+ n) buf-type))
3308 t
3309 (error "Quit."))
3310 t)))
3311
3312 (defun ediff-pop-diff (n buf-type)
3313 "Pop last killed Nth diff region from buffer BUF-TYPE."
3314 (let* ((n-th-record (assoc n ediff-killed-diffs-alist))
3315 (saved-rec (assoc buf-type (cdr n-th-record)))
3316 (buf (ediff-get-buffer buf-type))
3317 saved-diff reg-beg reg-end recovered)
3318
3319 (if (cdr saved-rec)
3320 (setq saved-diff (cdr saved-rec))
3321 (if (> ediff-number-of-differences 0)
3322 (error "Nothing saved for diff %d in buffer %S." (1+ n) buf-type)
3323 (error "No differences found.")))
3324
3325 (ediff-operate-on-flags 'remove)
3326
3327 (setq reg-beg (ediff-get-diff-posn buf-type 'beg n ediff-control-buffer))
3328 (setq reg-end (ediff-get-diff-posn buf-type 'end n ediff-control-buffer))
3329 (setq ediff-disturbed-overlays nil) ;; clear before use
3330
3331 (condition-case conds
3332 (ediff-eval-in-buffer
3333 buf
3334 (let ((inhibit-read-only (null buffer-read-only))
3335 (before-change-function nil))
3336 (goto-char reg-end)
3337 (insert-before-markers saved-diff)
3338
3339 (if (ediff-if-lucid)
3340 (progn
3341 (ediff-collect-extents-lucid reg-beg)
3342 (if (> reg-end reg-beg)
3343 (progn
3344 (kill-region reg-beg reg-end)
3345 (if (string= saved-diff "")
3346 (ediff-adjust-disturbed-extents-lucid reg-beg)))))
3347 (if (> reg-end reg-beg)
3348 (kill-region reg-beg reg-end)
3349 (ediff-move-disturbed-overlays reg-beg)))
3350
3351 (setq recovered t)
3352 ))
3353 (error (message "%s %s"
3354 (car conds)
3355 (mapconcat 'prin1-to-string (cdr conds) " "))
3356 (beep 1)))
3357
3358 (ediff-operate-on-flags 'insert)
3359 (if recovered
3360 (progn
3361 (setq n-th-record (delq saved-rec n-th-record))
3362 (message "Restored diff region %d in buffer %S." (1+ n) buf-type)))
3363 ))
3364
3365 (defun ediff-restore-diff (arg)
3366 "Restore ARGth diff from `ediff-killed-diffs-alist'.
3367 ARG is a prefix argument. If ARG is nil, restore current-difference."
3368 (interactive "P")
3369 (if arg
3370 (ediff-jump-to-difference arg))
3371 (ediff-pop-diff ediff-current-difference
3372 (ediff-char-to-buftype last-command-char))
3373 (ediff-recenter 'no-rehighlight))
3374
3375 (defun ediff-toggle-regexp-match ()
3376 "Toggle focus on difference regions that match a regexp or hide those diffs."
3377 (interactive)
3378 (let (regexp-A regexp-B)
3379 (cond
3380 ((or (and (eq ediff-skip-diff-region-function 'ediff-focus-on-regexp-matches)
3381 (eq last-command-char ?f))
3382 (and (eq ediff-skip-diff-region-function 'ediff-hide-regexp-matches)
3383 (eq last-command-char ?h)))
3384 (message "Selective browsing by regexp turned off.")
3385 (setq ediff-skip-diff-region-function 'ediff-show-all-diffs))
3386 ((eq last-command-char ?h)
3387 (setq ediff-skip-diff-region-function 'ediff-hide-regexp-matches
3388 regexp-A
3389 (read-string
3390 (format
3391 "Ignore A-regions matching this regexp (default \"%s\"): "
3392 (regexp-quote ediff-regexp-hide-A)))
3393 regexp-B
3394 (read-string
3395 (format
3396 "Ignore B-regions matching this regexp (default \"%s\"): "
3397 (regexp-quote ediff-regexp-hide-B))))
3398 (message "Hide difference regions matching regexp.")
3399 (or (string= regexp-A "") (setq ediff-regexp-hide-A regexp-A))
3400 (or (string= regexp-B "") (setq ediff-regexp-hide-B regexp-B)))
3401 ((eq last-command-char ?f)
3402 (setq ediff-skip-diff-region-function 'ediff-focus-on-regexp-matches
3403 regexp-A
3404 (read-string
3405 (format
3406 "Focus on A-regions matching this regexp (default \"%s\"): "
3407 (regexp-quote ediff-regexp-focus-A)))
3408 regexp-B
3409 (read-string
3410 (format
3411 "Focus on B-regions matching this regexp (default \"%s\"): "
3412 (regexp-quote ediff-regexp-focus-B))))
3413 (message "Focus on difference regions matching regexp.")
3414 (or (string= regexp-A "") (setq ediff-regexp-focus-A regexp-A))
3415 (or (string= regexp-B "") (setq ediff-regexp-focus-B regexp-B))))))
3416
3417 (defun ediff-toggle-skip-similar ()
3418 (interactive)
3419 (setq ediff-ignore-similar-regions (not ediff-ignore-similar-regions))
3420 (if ediff-ignore-similar-regions
3421 (message "Skipping over regions that differ only in white space & line breaks.")
3422 (message "Skipping over white-space differences turned off.")))
3423
3424 (defun ediff-show-all-diffs (n)
3425 "Don't skip difference regions."
3426 nil)
3427
3428 (defun ediff-focus-on-regexp-matches (n)
3429 "Focus on diffs that match regexp `ediff-regexp-focus-A/B'.
3430 Regions to be ignored according to this function are those where
3431 buf A region doesn't match `ediff-regexp-focus-A' and buf B region
3432 doesn't match `ediff-regexp-focus-B'.
3433 This function returns nil if the region number N (specified as
3434 an argument) is not to be ignored and t if region N is to be ignored.
3435
3436 N is a region number used by Ediff internally. It is 1 less
3437 the number seen by the user."
3438 (if (and (>= n 0) (< n ediff-number-of-differences))
3439 (let* ((ctl-buf ediff-control-buffer)
3440 (regex-A ediff-regexp-focus-A)
3441 (regex-B ediff-regexp-focus-B)
3442 (reg-A-match (ediff-eval-in-buffer
3443 ediff-A-buffer
3444 (goto-char (ediff-get-diff-posn 'A 'beg n ctl-buf))
3445 (re-search-forward
3446 regex-A
3447 (ediff-get-diff-posn 'A 'end n ctl-buf)
3448 t)))
3449 (reg-B-match (ediff-eval-in-buffer
3450 ediff-B-buffer
3451 (goto-char (ediff-get-diff-posn 'B 'beg n ctl-buf))
3452 (re-search-forward
3453 regex-B
3454 (ediff-get-diff-posn 'B 'end n ctl-buf)
3455 t))))
3456 (not (and reg-A-match reg-B-match)))))
3457
3458 (defun ediff-hide-regexp-matches (n)
3459 "Hide diffs that match regexp `ediff-regexp-hide-A/B'.
3460 Regions to be ignored are those where buf A region matches
3461 `ediff-regexp-hide-A' and buf B region matches `ediff-regexp-hide-B'.
3462 This function returns nil if the region number N (specified as
3463 an argument) is not to be ignored and t if region N is to be ignored.
3464
3465 N is a region number used by Ediff internally. It is 1 less
3466 the number seen by the user."
3467 (if (and (>= n 0) (< n ediff-number-of-differences))
3468 (let* ((ctl-buf ediff-control-buffer)
3469 (regex-A ediff-regexp-hide-A)
3470 (regex-B ediff-regexp-hide-B)
3471 (reg-A-match (ediff-eval-in-buffer
3472 ediff-A-buffer
3473 (goto-char (ediff-get-diff-posn 'A 'beg n ctl-buf))
3474 (re-search-forward
3475 regex-A
3476 (ediff-get-diff-posn 'A 'end n ctl-buf)
3477 t)))
3478 (reg-B-match (ediff-eval-in-buffer
3479 ediff-B-buffer
3480 (goto-char (ediff-get-diff-posn 'B 'beg n ctl-buf))
3481 (re-search-forward
3482 regex-B
3483 (ediff-get-diff-posn 'B 'end n ctl-buf)
3484 t))))
3485 (and reg-A-match reg-B-match))))
3486
3487
3488 ;;; Quitting, suspending, etc.
3489 (defun ediff-quit ()
3490 "Finish an Ediff session and exit Ediff.
3491 Unselects the selected difference, if any, restores the read-only and modified
3492 flags of the compared file buffers, kills Ediff buffers for this session
3493 \(but not file-A and file-B\)."
3494 (interactive)
3495 (if (prog1
3496 (y-or-n-p "Do you really want to exit Ediff? ")
3497 (message ""))
3498 (ediff-really-quit)))
3499
3500
3501 ;; Perform the quit operations.
3502 (defun ediff-really-quit ()
3503 (setq ediff-help-message ediff-help-message-long)
3504 (ediff-restore-buffer-characteristics t) ;; restore as they were at setup
3505 (ediff-unhighlight-diffs-totally)
3506 (ediff-clear-diff-vector ediff-difference-vector 'fine-diffs-also)
3507 (if ediff-temp-file-A (delete-file ediff-temp-file-A))
3508 (if ediff-temp-file-B (delete-file ediff-temp-file-B))
3509
3510 ;; restore buffer mode line id's in buffer-A/B
3511 (let ((control-buffer ediff-control-buffer))
3512 (condition-case nil
3513 (ediff-eval-in-buffer
3514 ediff-A-buffer
3515 (setq before-change-function nil)
3516 (setq ediff-this-buffer-control-sessions
3517 (delq control-buffer ediff-this-buffer-control-sessions))
3518 (if (null ediff-this-buffer-control-sessions)
3519 (setq local-write-file-hooks
3520 (delq 'ediff-block-write-file local-write-file-hooks)))
3521 (kill-local-variable 'ediff-local-checkout-flag)
3522 (kill-local-variable 'mode-line-buffer-identification))
3523 (error))
3524
3525 (condition-case nil
3526 (ediff-eval-in-buffer
3527 ediff-B-buffer
3528 (setq ediff-this-buffer-control-sessions
3529 (delq control-buffer ediff-this-buffer-control-sessions))
3530 (if (null ediff-this-buffer-control-sessions)
3531 (setq local-write-file-hooks
3532 (delq 'ediff-block-write-file local-write-file-hooks)))
3533 (setq before-change-function nil)
3534 (kill-local-variable 'ediff-local-checkout-flag)
3535 (kill-local-variable 'mode-line-buffer-identification))
3536 (error)))
3537
3538 (run-hooks 'ediff-quit-hooks))
3539
3540 (defun ediff-kill-buffer-carefully (buf)
3541 "Kill buffer BUF if it exists."
3542 (if (ediff-buffer-live-p buf)
3543 (kill-buffer (get-buffer buf))))
3544
3545 ;; The default way of quitting Ediff.
3546 ;; Kills control buffers and leaves the
3547 ;; frame split between the two diff'ed files.
3548 (defun ediff-default-quit-hook ()
3549 (let ((buff-A ediff-A-buffer)
3550 (buff-B ediff-B-buffer))
3551 (ediff-kill-buffer-carefully ediff-diff-buffer)
3552 (ediff-kill-buffer-carefully ediff-fine-diff-buffer)
3553 (ediff-kill-buffer-carefully ediff-tmp-buffer)
3554 (ediff-kill-buffer-carefully ediff-error-buffer)
3555 (ediff-kill-buffer-carefully ediff-control-buffer)
3556 (ediff-kill-buffer-carefully ediff-patch-diagnostics)
3557 (delete-other-windows)
3558
3559 ;; display only if not visible
3560 (condition-case nil
3561 (or (ediff-get-visible-buffer-window buff-B)
3562 (switch-to-buffer buff-B))
3563 (error))
3564 (condition-case nil
3565 (or (ediff-get-visible-buffer-window buff-A)
3566 (progn
3567 (if (ediff-get-visible-buffer-window buff-B)
3568 (split-window-vertically))
3569 (switch-to-buffer buff-A)))
3570 (error))
3571 (message "")
3572 ))
3573
3574 ;; The default way of suspending Ediff.
3575 ;; Buries Ediff buffers, kills all windows.
3576 (defun ediff-default-suspend-hook ()
3577 (let ((buf-A ediff-A-buffer)
3578 (buf-B ediff-B-buffer)
3579 (buf-patch ediff-patch-buf)
3580 (buf-patch-diag ediff-patch-diagnostics)
3581 (buf-err ediff-error-buffer)
3582 (buf-diff ediff-diff-buffer)
3583 (buf-fine-diff ediff-fine-diff-buffer))
3584 (bury-buffer) ;; ediff-control-buffer
3585 (delete-other-windows)
3586 (bury-buffer buf-err)
3587 (bury-buffer buf-diff)
3588 (bury-buffer buf-fine-diff)
3589 (bury-buffer buf-patch)
3590 (bury-buffer buf-patch-diag)
3591 (bury-buffer buf-A)
3592 (bury-buffer buf-B)))
3593
3594
3595 (defun ediff-suspend ()
3596 "Suspend Ediff.
3597 To resume, switch to the appropriate `Ediff Control Panel'
3598 buffer and then type \\[ediff-recenter]. Ediff will automatically set
3599 up an appropriate window config."
3600 (interactive)
3601 (let ((key (substitute-command-keys "\\[ediff-recenter]")))
3602 (run-hooks 'ediff-suspend-hooks)
3603 (message
3604 "To resume Ediff, switch to Ediff Control Panel and hit '%S'" key)))
3605
3606
3607 (defun ediff-status-info ()
3608 "Show the names of the buffers or files being operated on by Ediff.
3609 Hit \\[ediff-recenter] to reset the windows afterward."
3610 (interactive)
3611 (with-output-to-temp-buffer " *ediff-info*"
3612 (princ (ediff-version))
3613 (princ "\n\n")
3614 (ediff-eval-in-buffer ediff-A-buffer
3615 (if buffer-file-name
3616 (princ
3617 (format "File A is: %s\n" buffer-file-name))
3618 (princ
3619 (format "Buffer A is: %s\n" (buffer-name)))))
3620 (ediff-eval-in-buffer ediff-B-buffer
3621 (if buffer-file-name
3622 (princ
3623 (format "File B is: %s\n" buffer-file-name))
3624 (princ
3625 (format "Buffer B is: %s\n" (buffer-name)))))
3626
3627 (let* ((A-line (ediff-eval-in-buffer ediff-A-buffer
3628 (count-lines (point-min) (point))))
3629 (B-line (ediff-eval-in-buffer ediff-B-buffer
3630 (count-lines (point-min) (point)))))
3631 (princ (format "\nPoint position in buffer A = %d\n" A-line))
3632 (princ (format "Point position in buffer B = %d\n" B-line)))
3633
3634 (princ (format "\nCurrent difference number = %S\n"
3635 (cond ((< ediff-current-difference 0) 'start)
3636 ((>= ediff-current-difference
3637 ediff-number-of-differences) 'end)
3638 (t (1+ ediff-current-difference)))))
3639
3640 (cond (ediff-ignore-similar-regions
3641 (princ "\nSkipping over regions that differ only in white space & line breaks."))
3642 (t
3643 (princ "\nNo skipping over regions that differ in white space & line breaks.")))
3644
3645 (cond ((eq ediff-skip-diff-region-function 'ediff-show-all-diffs)
3646 (princ "\nSelective browsing by regexp is off.\n"))
3647 ((eq ediff-skip-diff-region-function 'ediff-hide-regexp-matches)
3648 (princ
3649 "\nIgnoring regions that match")
3650 (princ
3651 (format "\n\t regexp `%s' in buffer A and\n\t regexp `%s' in buffer B\n"
3652 ediff-regexp-hide-A ediff-regexp-hide-B)))
3653 ((eq ediff-skip-diff-region-function 'ediff-focus-on-regexp-matches)
3654 (princ
3655 "\nFocusing on regions that match")
3656 (princ
3657 (format "\n\t regexp `%s' in buffer A and\n\t regexp `%s' in buffer B\n"
3658 ediff-regexp-focus-A ediff-regexp-focus-B)))
3659 (t (princ "\nSelective browsing via a user-defined method.\n")))
3660
3661 (princ "\nBugs: M-x ediff-submit-report")
3662 ))
3663
3664
3665
3666 ;;; Support routines
3667
3668 ;; Select a difference by placing the ASCII flags around the appropriate
3669 ;; group of lines in the A, B buffers
3670 (defun ediff-select-difference (n)
3671 (if (and (ediff-buffer-live-p ediff-A-buffer)
3672 (ediff-buffer-live-p ediff-B-buffer)
3673 (>= n 0) (< n ediff-number-of-differences))
3674 (progn
3675 (ediff-remember-buffer-characteristics)
3676 (if (and window-system ediff-want-faces)
3677 (progn
3678 (ediff-highlight-diff n)
3679 (setq ediff-highlighting-style 'face))
3680 (setq ediff-highlighting-style 'ascii)
3681 (ediff-place-flags-in-buffer 'A ediff-A-buffer
3682 ediff-control-buffer n)
3683 (ediff-place-flags-in-buffer 'B ediff-B-buffer
3684 ediff-control-buffer n))
3685
3686 (cond ((eq ediff-auto-refine 'on)
3687 (if (and
3688 (> ediff-auto-refine-limit
3689 (- (ediff-get-diff-posn 'A 'end n)
3690 (ediff-get-diff-posn 'A 'beg n)))
3691 (> ediff-auto-refine-limit
3692 (- (ediff-get-diff-posn 'B 'end n)
3693 (ediff-get-diff-posn 'B 'beg n))))
3694 (ediff-make-fine-diffs n 'noforce)
3695 (ediff-make-fine-diffs n 'skip)))
3696
3697 ((eq ediff-auto-refine 'off) ; highlight iff fine diffs
3698 (ediff-make-fine-diffs n 'skip))) ; already exist
3699
3700 (ediff-restore-buffer-characteristics)
3701 (run-hooks 'ediff-select-hooks))))
3702
3703
3704 ;; Unselect a difference by removing the ASCII flags in the buffers.
3705 (defun ediff-unselect-difference (n)
3706 (if (and (>= n 0) (< n ediff-number-of-differences))
3707 (progn
3708 (ediff-remember-buffer-characteristics)
3709
3710 (cond ((and window-system ediff-want-faces)
3711 (ediff-unhighlight-diff))
3712 ((eq ediff-highlighting-style 'ascii)
3713 (ediff-remove-flags-from-buffer
3714 ediff-A-buffer
3715 (ediff-get-diff-posn 'A 'beg n)
3716 (ediff-get-diff-posn 'A 'end n)
3717 ediff-before-flag-A ediff-after-flag-A)
3718 (ediff-remove-flags-from-buffer
3719 ediff-B-buffer
3720 (ediff-get-diff-posn 'B 'beg n)
3721 (ediff-get-diff-posn 'B 'end n)
3722 ediff-before-flag-B ediff-after-flag-B)))
3723
3724 (ediff-restore-buffer-characteristics)
3725 (setq ediff-highlighting-style nil)
3726
3727 ;; unhighlight fine diffs
3728 (ediff-set-fine-diff-properties ediff-current-difference 'default)
3729
3730 (run-hooks 'ediff-unselect-hooks))))
3731
3732
3733 ;; Unselects prev diff and selects a new one, if FLAG has value other than
3734 ;; 'select-only or 'unselect-only. If FLAG is 'select-only, the
3735 ;; next difference is selected, but the current selection is not
3736 ;; unselected. If FLAG is 'unselect-only then the current selection is
3737 ;; unselected, but the next one is not selected. If NO-RECENTER is non-nil,
3738 ;; don't recenter buffers after selecting/unselecting.
3739 ;;
3740 ;; Don't use `ediff-select-difference' and `ediff-unselect-difference'
3741 ;; directly, since this will screw up the undo info in the presence of
3742 ;; ASCII flags.
3743 ;; Instead, use `ediff-unselect-and-select-difference' with appropriate
3744 ;; flags.
3745
3746 (defun ediff-unselect-and-select-difference (n &optional flag no-recenter)
3747 (let (;; save buf modified info
3748 (control-buf ediff-control-buffer)
3749 (buf-A-modified (buffer-modified-p ediff-A-buffer))
3750 (buf-B-modified (buffer-modified-p ediff-B-buffer))
3751 ;; temporarily disable undo so highlighting won't confuse the user
3752 buf-A-undo buf-B-undo)
3753
3754 (let ((ediff-current-difference n))
3755 (or no-recenter
3756 (ediff-recenter 'no-rehighlight)))
3757
3758 (if (and (ediff-buffer-live-p ediff-A-buffer)
3759 (ediff-buffer-live-p ediff-B-buffer))
3760 (progn
3761 (ediff-eval-in-buffer
3762 ediff-A-buffer
3763 (setq buf-A-undo buffer-undo-list))
3764 (ediff-eval-in-buffer
3765 ediff-B-buffer
3766 (setq buf-B-undo buffer-undo-list))
3767
3768 (buffer-disable-undo ediff-A-buffer)
3769 (buffer-disable-undo ediff-B-buffer)))
3770
3771 (unwind-protect ;; we don't want to lose undo info due to error
3772 (progn
3773 (or (eq flag 'select-only)
3774 (ediff-unselect-difference ediff-current-difference))
3775
3776 ;; Auto-save buffers while Ediff flags are temporarily removed.
3777 (ediff-eval-in-buffer
3778 ediff-A-buffer
3779 (if buf-A-modified
3780 (do-auto-save)))
3781 (ediff-eval-in-buffer
3782 ediff-B-buffer
3783 (if buf-B-modified
3784 (do-auto-save)))
3785
3786 (or (eq flag 'unselect-only)
3787 (ediff-select-difference n))
3788 (setq ediff-current-difference n)
3789 ) ;; end protected section
3790
3791 (ediff-eval-in-buffer
3792 control-buf
3793 (ediff-refresh-mode-line)
3794 ;; restore undo and buffer-modified info
3795 (ediff-eval-in-buffer
3796 ediff-A-buffer
3797 (set-buffer-modified-p buf-A-modified)
3798 (setq buffer-undo-list buf-A-undo)))
3799
3800 (ediff-eval-in-buffer
3801 control-buf
3802 (ediff-eval-in-buffer
3803 ediff-B-buffer
3804 (set-buffer-modified-p buf-B-modified)
3805 (setq buffer-undo-list buf-B-undo)))
3806 )))
3807
3808 ;; Revise the mode line to display which difference we have selected
3809
3810 (defun ediff-refresh-mode-line ()
3811 (setq mode-line-buffer-identification
3812 (cond ((< ediff-current-difference 0)
3813 (list (format "%%b: At start of %d diffs"
3814 ediff-number-of-differences)))
3815 ((>= ediff-current-difference ediff-number-of-differences)
3816 (list (format "%%b: At end of %d diffs"
3817 ediff-number-of-differences)))
3818 (t
3819 (list (format "%%b: diff %d of %d"
3820 (1+ ediff-current-difference)
3821 ediff-number-of-differences)))))
3822 ;; Force mode-line redisplay
3823 (force-mode-line-update))
3824
3825
3826
3827 ;; Verify that we have a difference selected.
3828 (defun ediff-validate-difference ()
3829 (if (not (and (>= ediff-current-difference 0)
3830 (< ediff-current-difference ediff-number-of-differences)))
3831 (error "No difference selected")))
3832
3833 (defun ediff-read-file-name (prompt default-dir default-file)
3834 ; This is a modified version of a similar function in `emerge.el'.
3835 ; PROMPT should not have trailing ': ', so that it can be modified
3836 ; according to context.
3837 ; If default-file is set, it should be used as the default value.
3838 ; If default-dir is non-nil, use it as the default directory.
3839 ; Otherwise, use the value of Emacs' variable `default-directory.'
3840
3841 ;; hack default-dir if it is not set
3842 (setq default-dir
3843 (file-name-as-directory
3844 (abbreviate-file-name
3845 (expand-file-name (or default-dir
3846 (and default-file
3847 (file-name-directory default-file))
3848 default-directory)))))
3849
3850 ;; strip the directory from default-file
3851 (if default-file
3852 (setq default-file (file-name-nondirectory default-file)))
3853
3854 (let (f)
3855 (setq f (expand-file-name
3856 (read-file-name
3857 (format "%s%s: "
3858 prompt
3859 (if default-file
3860 (concat " (default " default-file ")")
3861 ""))
3862 default-dir
3863 default-file
3864 'confirm
3865 default-file
3866 )
3867 default-dir
3868 ))
3869 ;; If user enters a directory name, expand the default file in that
3870 ;; directory. This allows the user to enter a directory name for the
3871 ;; B-file and diff against the default-file in that directory instead
3872 ;; of a DIRED listing!
3873 (if (and (file-directory-p f) default-file)
3874 (setq f (expand-file-name
3875 (file-name-nondirectory default-file) f)))
3876 f))
3877
3878 ;; If `prefix' is given, then it is used as a prefix for the temp file
3879 ;; name. Otherwise, `.buffer-name' is used. If `file' is given, use this
3880 ;; file and don't create a new one.
3881 (defun ediff-make-temp-file (&optional prefix given-file)
3882 (let ((f (or given-file
3883 (make-temp-name (concat
3884 ediff-temp-file-prefix
3885 (or prefix
3886 (format
3887 ".%s"
3888 "buf")))))))
3889 ;; create the file
3890 (write-region (point-min) (point-max) f nil 'no-message)
3891 (set-file-modes f ediff-temp-file-mode)
3892 f))
3893
3894 ;; Quote metacharacters (using \) when executing diff in Unix, but not in
3895 ;; EMX OS/2
3896 (defun ediff-protect-metachars (str)
3897 (or (eq system-type 'emx)
3898 (let ((limit 0))
3899 (while (string-match emerge-metachars str limit)
3900 (setq str (concat (substring str 0 (match-beginning 0))
3901 "\\"
3902 (substring str (match-beginning 0))))
3903 (setq limit (1+ (match-end 0))))))
3904 str)
3905
3906 ;; Make sure the current buffer (for a file) has the same contents as the
3907 ;; file on disk, and attempt to remedy the situation if not.
3908 ;; Signal an error if we can't make them the same, or the user doesn't want
3909 ;; to do what is necessary to make them the same.
3910 ;; If file has file handlers (indicated by the optional arg), then we
3911 ;; offer to instead of saving. This is one difference with Emerge.
3912 ;; Another is that we always offer to revert obsolete files, whether they
3913 ;; are modified or not.
3914 (defun ediff-verify-file-buffer (&optional file-magic)
3915 ;; First check if the file has been modified since the buffer visited it.
3916 (if (verify-visited-file-modtime (current-buffer))
3917 (if (buffer-modified-p)
3918 ;; If buffer is not obsolete and is modified, offer to save
3919 (if (yes-or-no-p
3920 (format "Buffer out of sync with visited file. %s file %s? "
3921 (if file-magic "Revert" "Save")
3922 buffer-file-name))
3923 (if (not file-magic)
3924 (save-buffer)
3925 ;; for some reason, file-name-handlers append instead of
3926 ;; replacing, so we have to erase first.
3927 (erase-buffer)
3928 (revert-buffer t t))
3929 (error "Buffer out of sync for file %s" buffer-file-name))
3930 ;; If buffer is not obsolete and is not modified, do nothing
3931 nil)
3932 ;; If buffer is obsolete, offer to revert
3933 (if (yes-or-no-p
3934 (format "Buffer out of sync with visited file. Revert file %s? "
3935 buffer-file-name))
3936 (progn
3937 (if file-magic
3938 (erase-buffer))
3939 (revert-buffer t t))
3940 (error "Buffer out of sync for file %s" buffer-file-name))))
3941
3942
3943 (defun ediff-block-write-file ()
3944 "Prevent writing files A and B directly."
3945 (if (ediff-check-for-ascii-flags)
3946 (error "Type 'wa' and 'wb' in Ediff Control Panel to save buffs A/B.")))
3947
3948 (defun ediff-check-for-ascii-flags ()
3949 (eval
3950 (cons 'or
3951 (mapcar (function (lambda (buf)
3952 (if (ediff-buffer-live-p buf)
3953 (ediff-eval-in-buffer
3954 buf
3955 (eq ediff-highlighting-style 'ascii)))))
3956 ediff-this-buffer-control-sessions))))
3957
3958 (defun ediff-insert-in-front (overl beg end)
3959 "Capture overlays that had insertions in the front.
3960 Called when overlay OVERL gets insertion in front."
3961 (if (ediff-overlay-get overl 'ediff-diff-num)
3962 (setq ediff-disturbed-overlays
3963 (cons overl ediff-disturbed-overlays)))
3964 )
3965
3966 (defun ediff-collect-extents-lucid (pos)
3967 "Collects all extents at POS having property `ediff-diff-num'.
3968 Lucid Emacs causes headache by detaching empty extents, so I have to save
3969 them before they disappear."
3970 (let (lis elt)
3971 (while (setq elt (extent-at pos nil 'ediff-diff-num elt))
3972 (setq lis (cons elt lis)))
3973 (setq ediff-disturbed-overlays lis)))
3974
3975 (defun ediff-move-disturbed-overlays (posn)
3976 (mapcar (function (lambda (overl)
3977 (ediff-move-overlay overl
3978 posn
3979 (ediff-overlay-end overl))
3980 ))
3981 ediff-disturbed-overlays)
3982 (setq ediff-disturbed-overlays nil))
3983
3984 (defun ediff-adjust-disturbed-extents-lucid (posn &optional posn-type)
3985 ;; POSN-TYPE tells if POSN should become a new start of the extents
3986 ;; (if 'new-start) or a new end (if 'new-end). If POSN-TYPE is nil, then
3987 ;; POSN is both the new start and the new end.
3988 (mapcar (function (lambda (overl)
3989 (cond ((and (null posn-type)
3990 (equal (ediff-overlay-start overl)
3991 (ediff-overlay-end overl)))
3992 (ediff-move-overlay overl posn posn))
3993
3994 (posn-type
3995 (ediff-move-overlay
3996 overl
3997 (if (eq posn-type 'new-start)
3998 posn
3999 (ediff-overlay-start overl))
4000 (if (eq posn-type 'new-end)
4001 posn
4002 (ediff-overlay-end overl)))))))
4003 ediff-disturbed-overlays)
4004 (setq ediff-disturbed-overlays nil))
4005
4006 (defun ediff-save-buffer ()
4007 "Safe way of saving buffers A, B, and the diff output.
4008 `wa' saves buffer A, `wb' saves buffer B, and `wf' saves the diff output."
4009 (interactive)
4010 (let ((hooks local-write-file-hooks))
4011 (ediff-unselect-and-select-difference ediff-current-difference
4012 'unselect-only)
4013 (unwind-protect
4014 (ediff-eval-in-buffer
4015 (cond ((eq last-command-char ?a)
4016 ediff-A-buffer)
4017 ((eq last-command-char ?b)
4018 ediff-B-buffer)
4019 ((eq last-command-char ?f)
4020 (message "Saving diff output ...")(sit-for 1)
4021 ediff-diff-buffer))
4022 ;; temporarily remove writing block
4023 (setq hooks (delq 'ediff-block-write-file hooks))
4024 (let ((local-write-file-hooks hooks))
4025 (save-buffer)))
4026 (ediff-unselect-and-select-difference ediff-current-difference
4027 'select-only)
4028 )))
4029
4030
4031
4032 ;; Essentially `emerge-remove-flags-in-buffer', modified to allow deletion
4033 ;; of read-only flags.
4034 (defun ediff-remove-flags-from-buffer (buffer before-posn after-posn
4035 before-flag after-flag)
4036 (ediff-eval-in-buffer
4037 buffer
4038 (let ((before-flag-length (length before-flag))
4039 (after-flag-length (length after-flag))
4040 (inhibit-read-only t)
4041 buffer-read-only
4042 before-change-function)
4043 (goto-char after-posn)
4044 (setq after-posn (point-marker)) ;; after-posn is now a marker
4045 ;; remove the flags, if they're there
4046 (goto-char (- before-posn before-flag-length))
4047 (if (ediff-if-lucid)
4048 (ediff-collect-extents-lucid (+ (point) before-flag-length)))
4049 (if (looking-at (regexp-quote before-flag))
4050 (delete-region (point) (+ (point) before-flag-length))
4051 ;; the flag isn't there
4052 (ding)
4053 (message "Trouble removing ASCII flag"))
4054 (if (ediff-if-lucid)
4055 (ediff-adjust-disturbed-extents-lucid (point)))
4056
4057 (if (ediff-if-lucid)
4058 (ediff-collect-extents-lucid (point)))
4059 (goto-char after-posn)
4060 (if (looking-at (regexp-quote after-flag))
4061 (delete-region (point) (+ (point) after-flag-length))
4062 ;; the flag isn't there
4063 (ding)
4064 (message "Trouble removing ASCII flag"))
4065 (if (ediff-if-lucid)
4066 (ediff-adjust-disturbed-extents-lucid (point)))
4067 (setq after-posn nil) ;; after has become a marker--garbage-collect
4068 )))
4069
4070
4071 ;; This is a modified `emerge-place-flags-in-buffer'.
4072 (defun ediff-place-flags-in-buffer (buf-type buffer ctl-buffer difference)
4073 (ediff-eval-in-buffer
4074 buffer
4075 (ediff-place-flags-in-buffer1 buf-type ctl-buffer difference)))
4076
4077 ;; Modified `emerge-place-flags-in-buffer1'.
4078 (defun ediff-place-flags-in-buffer1 (buf-type ctl-buffer difference)
4079 (let ((before-flag-name (if (eq buf-type 'A)
4080 'ediff-before-flag-A
4081 'ediff-before-flag-B))
4082 (after-flag-name (if (eq buf-type 'A)
4083 'ediff-after-flag-A
4084 'ediff-after-flag-B))
4085 (inhibit-read-only t)
4086 buffer-read-only before-change-function beg-of-line flag)
4087
4088 ;; insert the flag before the difference
4089 (let ((before (ediff-get-diff-posn buf-type 'beg difference ctl-buffer)))
4090 (goto-char before)
4091 (setq beg-of-line (bolp))
4092
4093 (setq flag (ediff-eval-in-buffer
4094 ctl-buffer
4095 (if beg-of-line
4096 (set before-flag-name ediff-before-flag-bol)
4097 (set before-flag-name ediff-before-flag-mol))))
4098
4099 ;; insert the flag itself
4100 (if (ediff-if-lucid)
4101 (ediff-collect-extents-lucid (point)))
4102 (insert-before-markers flag)
4103 (if (ediff-if-lucid)
4104 ;; Lucid's extent end-points behave strangely; they won't
4105 ;; respect insert-before-markers
4106 (ediff-adjust-disturbed-extents-lucid (point) 'new-start))
4107 )
4108 ;; insert the flag after the difference
4109 (let* ((after (ediff-get-diff-posn buf-type 'end difference ctl-buffer)))
4110 (goto-char after)
4111 (setq beg-of-line (bolp))
4112
4113 (setq flag (ediff-eval-in-buffer
4114 ctl-buffer
4115 (if beg-of-line
4116 (set after-flag-name ediff-after-flag-bol)
4117 (set after-flag-name ediff-after-flag-mol))))
4118
4119 ;; insert the flag itself
4120 (if (ediff-if-lucid)
4121 (ediff-collect-extents-lucid (point)))
4122 (insert flag)
4123 (if (ediff-if-lucid)
4124 (ediff-adjust-disturbed-extents-lucid after 'new-end))
4125 )))
4126
4127
4128 (defun ediff-get-diff-posn (buf-type pos &optional n control-buf)
4129 "Returns positions of difference sectors in the BUF-TYPE buffer.
4130 BUF-TYPE should be a symbol--either `A' or `B'.
4131 POS is either `beg' or `end'--it specifies whether you want the position at the
4132 beginning of a difference or at the end.
4133
4134 The optional argument N says which difference \(default:
4135 `ediff-current-difference'\). The optional argument CONTROL-BUF says
4136 which control buffer is in effect in case it is not the current
4137 buffer."
4138 (let (diff-overlay)
4139 (or control-buf
4140 (setq control-buf (current-buffer)))
4141
4142 (ediff-eval-in-buffer
4143 control-buf
4144 (or n (setq n ediff-current-difference))
4145 (if (or (< n 0) (>= n ediff-number-of-differences))
4146 (if (> ediff-number-of-differences 0)
4147 (error "There is no diff %d. Valid diffs are 1 to %d."
4148 (1+ n) ediff-number-of-differences)
4149 (error "No differences found.")))
4150 (setq diff-overlay (ediff-get-diff-overlay n buf-type)))
4151
4152 (if (ediff-overlay-get diff-overlay 'detached)
4153 (ediff-move-overlay diff-overlay
4154 (ediff-overlay-get diff-overlay 'ediff-marker)
4155 (ediff-overlay-get diff-overlay 'ediff-marker)))
4156 (if (eq pos 'beg)
4157 (ediff-overlay-start diff-overlay)
4158 (ediff-overlay-end diff-overlay))
4159 ))
4160
4161
4162
4163 ;; These would highlight differences under X
4164 (defun ediff-highlight-diff (n)
4165 "Put face on diff N. Invoked for X displays only."
4166 (let* ((last-A (ediff-eval-in-buffer ediff-A-buffer (point-max)))
4167 (last-B (ediff-eval-in-buffer ediff-B-buffer (point-max)))
4168 (begin-A (ediff-get-diff-posn 'A 'beg n))
4169 (end-A (ediff-get-diff-posn 'A 'end n))
4170 (xtraA (if (equal begin-A end-A) 1 0))
4171 (end-A-hilit (min last-A (+ end-A xtraA)))
4172
4173 (begin-B (ediff-get-diff-posn 'B 'beg n))
4174 (end-B (ediff-get-diff-posn 'B 'end n))
4175 (xtraB (if (equal begin-B end-B) 1 0))
4176 (end-B-hilit (min last-B (+ end-B xtraB))))
4177
4178 (if (ediff-if-lucid)
4179 (progn
4180 (ediff-move-overlay
4181 ediff-current-diff-overlay-A begin-A end-A-hilit)
4182 (ediff-move-overlay
4183 ediff-current-diff-overlay-B begin-B end-B-hilit))
4184 ;; Emacs 19.22 has a bug, which requires that ediff-move-overlay will
4185 ;; have the buffer as a parameter. Believed fixed in 19.23.
4186 (ediff-move-overlay ediff-current-diff-overlay-A
4187 begin-A end-A-hilit ediff-A-buffer)
4188 (ediff-move-overlay ediff-current-diff-overlay-B
4189 begin-B end-B-hilit ediff-B-buffer))
4190 ;; giving priority of 0 and then changing it may look funny, but
4191 ;; this is intended to overcome an Emacs bug.
4192 (ediff-overlay-put ediff-current-diff-overlay-A 'priority 0)
4193 (ediff-overlay-put ediff-current-diff-overlay-B 'priority 0)
4194 (ediff-overlay-put ediff-current-diff-overlay-A 'priority
4195 (ediff-highest-priority begin-A end-A-hilit ediff-A-buffer))
4196 (ediff-overlay-put ediff-current-diff-overlay-B 'priority
4197 (ediff-highest-priority begin-B end-B-hilit ediff-B-buffer))
4198
4199 (or (face-differs-from-default-p 'ediff-odd-diff-face-A-var)
4200 (not ediff-highlight-all-diffs)
4201 (progn
4202 (copy-face ediff-odd-diff-face-A 'ediff-odd-diff-face-A-var)
4203 (copy-face ediff-odd-diff-face-B 'ediff-odd-diff-face-B-var)
4204 (copy-face ediff-even-diff-face-A 'ediff-even-diff-face-A-var)
4205 (copy-face ediff-even-diff-face-B 'ediff-even-diff-face-B-var)))
4206
4207 ;; unhighlight the background overlay for the diff n so they won't
4208 ;; interfere with the current diff overlay
4209 (ediff-overlay-put (ediff-get-diff-overlay n 'A) 'face nil)
4210 (ediff-overlay-put (ediff-get-diff-overlay n 'B) 'face nil)
4211
4212 ;; (sit-for 0) ;; needed synch for some reason in v19.22
4213 ))
4214
4215
4216 (defun ediff-unhighlight-diff ()
4217 "Remove overlays from buffers A and B."
4218
4219 (ediff-move-overlay ediff-current-diff-overlay-A 1 1)
4220 (ediff-move-overlay ediff-current-diff-overlay-B 1 1)
4221
4222 ;; rehighlight the overlay in the background of the
4223 ;; current difference region
4224 (let ((overlay-A (ediff-get-diff-overlay ediff-current-difference 'A))
4225 (overlay-B (ediff-get-diff-overlay ediff-current-difference 'B)))
4226 (ediff-overlay-put overlay-A
4227 'face (if (ediff-odd-p ediff-current-difference)
4228 'ediff-odd-diff-face-A-var
4229 'ediff-even-diff-face-A-var))
4230 (ediff-overlay-put overlay-B
4231 'face (if (ediff-odd-p ediff-current-difference)
4232 'ediff-odd-diff-face-B-var
4233 'ediff-even-diff-face-B-var))
4234 ))
4235
4236
4237 ;; delete highlighting overlays, restore faces to their original form
4238 (defun ediff-unhighlight-diffs-totally ()
4239 (let (buffer-read-only)
4240 (ediff-unselect-and-select-difference -1)
4241
4242 (if (and window-system ediff-want-faces)
4243 (let ((inhibit-quit t))
4244 (if (face-differs-from-default-p 'ediff-odd-diff-face-A-var)
4245 (progn
4246 (copy-face 'default 'ediff-odd-diff-face-A-var)
4247 (copy-face 'default 'ediff-odd-diff-face-B-var)
4248 (copy-face 'default 'ediff-even-diff-face-A-var)
4249 (copy-face 'default 'ediff-even-diff-face-B-var)))
4250 (if (ediff-overlayp ediff-current-diff-overlay-A)
4251 (ediff-delete-overlay ediff-current-diff-overlay-A))
4252 (setq ediff-current-diff-overlay-A nil)
4253 (if (ediff-overlayp ediff-current-diff-overlay-B)
4254 (ediff-delete-overlay ediff-current-diff-overlay-B))
4255 (setq ediff-current-diff-overlay-B nil)))
4256 ))
4257
4258 (defun ediff-clear-diff-vector (vec &optional fin-diffs-also)
4259 ;; null out the difference overlays so they won't slow down future
4260 ;; editing operations
4261 (mapcar (function
4262 (lambda (elt)
4263 (ediff-delete-overlay (ediff-get-diff-overlay-from-vector elt 'A))
4264 (ediff-delete-overlay (ediff-get-diff-overlay-from-vector elt 'B))
4265 (if fin-diffs-also
4266 (ediff-clear-diff-vector
4267 (ediff-get-fine-diff-vector-from-vec elt)))
4268 ))
4269 vec)
4270 ;; allow them to be garbage collected
4271 (setq vec nil))
4272
4273 (defun ediff-operate-on-flags (action)
4274 "Re/unhighlights buffers A and B with all flags from all Ediff sessions.
4275 This is usually needed only when a
4276 buffer is involved in multiple Ediff sessions."
4277 (let* ((A-sessions (ediff-eval-in-buffer
4278 ediff-A-buffer
4279 ediff-this-buffer-control-sessions))
4280 (B-sessions (ediff-eval-in-buffer
4281 ediff-B-buffer
4282 ediff-this-buffer-control-sessions))
4283 (sessions (ediff-union A-sessions B-sessions))
4284 (flag (if (eq action 'remove) 'unselect-only 'select-only)))
4285
4286 (mapcar (function (lambda (buf)
4287 (ediff-eval-in-buffer
4288 buf
4289 (or (if (eq action 'insert)
4290 (memq ediff-highlighting-style '(ascii off))
4291 (not (eq ediff-highlighting-style 'ascii)))
4292 (ediff-unselect-and-select-difference
4293 ediff-current-difference
4294 flag 'no-recenter))
4295 )))
4296 sessions)))
4297
4298
4299
4300 ;;; Refinement of current diff
4301 ;; Split region along word boundaries. Each word will be on its own line.
4302 ;; Output to buffer out-buffer.
4303 (defun ediff-forward-word ()
4304 "Move point one word forward. Used for splitting diff regions into words.
4305 This is the default for `ediff-forward-word-function'."
4306 (or (> (skip-chars-forward ediff-word-1) 0)
4307 (> (skip-chars-forward ediff-word-2) 0)))
4308
4309 (defun ediff-wordify (beg end in-buffer out-buffer)
4310 (let (sv-point string)
4311 (save-excursion
4312 (set-buffer in-buffer)
4313 (setq string (buffer-substring beg end))
4314
4315 (set-buffer out-buffer)
4316 (erase-buffer)
4317 (insert string)
4318 (goto-char (point-min))
4319 (skip-chars-forward ediff-whitespace)
4320 (delete-region (point-min) (point))
4321
4322 (while (not (eobp))
4323 (funcall ediff-forward-word-function)
4324 (setq sv-point (point))
4325 (skip-chars-forward ediff-whitespace)
4326 (delete-region sv-point (point))
4327 (insert "\n")))))
4328
4329 ;; `n' is the diff region to work on.
4330 ;; if `flag' is 'noforce then make fine-diffs only if this region's fine
4331 ;; diffs have not been computed before.
4332 ;; if `flag' is 'skip then don't compute fine diffs for this region.
4333 (defun ediff-make-fine-diffs (&optional n flag)
4334 (interactive)
4335 (or n (setq n ediff-current-difference))
4336
4337 (if (< ediff-number-of-differences 1)
4338 (error "No differences found."))
4339
4340 (or (< n 0)
4341 (>= n ediff-number-of-differences)
4342 ;; n is within the range
4343 (let ((file-A ediff-temp-file-A)
4344 (file-B ediff-temp-file-B))
4345
4346 (cond ((and (eq flag 'noforce) (ediff-get-fine-diff-vector n))
4347 nil)
4348 ((eq flag 'skip)
4349 (or (ediff-get-fine-diff-vector n)
4350 (eq ediff-auto-refine 'off)
4351 (message "Region %d is larger than auto-refine limit. Hit %S to force-refine."
4352 (1+ n)
4353 (substitute-command-keys
4354 "\\[ediff-make-fine-diffs]")
4355 )))
4356 (t
4357 ;; delete old fine diffs
4358 (ediff-clear-diff-vector (ediff-get-fine-diff-vector n))
4359 ;; recompute fine diffs
4360 (setq ediff-tmp-buffer (get-buffer-create "*ediff-tmp*"))
4361
4362 (ediff-wordify
4363 (ediff-get-diff-posn 'A 'beg n)
4364 (ediff-get-diff-posn 'A 'end n)
4365 ediff-A-buffer
4366 ediff-tmp-buffer)
4367 (ediff-eval-in-buffer
4368 ediff-tmp-buffer
4369 (setq file-A (ediff-make-temp-file ".fine-diffs-A" file-A)))
4370
4371 (ediff-wordify
4372 (ediff-get-diff-posn 'B 'beg n)
4373 (ediff-get-diff-posn 'B 'end n)
4374 ediff-B-buffer
4375 ediff-tmp-buffer)
4376 (ediff-eval-in-buffer
4377 ediff-tmp-buffer
4378 (setq file-B (ediff-make-temp-file ".fine-diffs-B" file-B)))
4379
4380 ;; save temp file names.
4381 (setq ediff-temp-file-A file-A
4382 ediff-temp-file-B file-B)
4383
4384 ;; set the new vector of fine diffs, if none exists
4385 (ediff-set-fine-diff-vector
4386 n
4387 (ediff-setup-diff-regions file-A file-B 'use-old-diff-buf n
4388 ediff-fine-diff-program
4389 ediff-fine-diff-options
4390 ediff-fine-diff-ok-lines-regexp))
4391 (if (eq (length (ediff-get-fine-diff-vector n)) 0)
4392 (progn
4393 (message "No diffs found in region %d, except for white space and line breaks."
4394 (1+ n))
4395 (ediff-mark-diff-as-space-only n t))
4396 (ediff-mark-diff-as-space-only n nil)))
4397 ) ;; end cond
4398 (ediff-set-fine-diff-properties n)
4399 )))
4400
4401
4402 (defun ediff-set-fine-diff-properties (n &optional default)
4403 (or (not window-system)
4404 (< n 0)
4405 (>= n ediff-number-of-differences)
4406 ;; in a window system, set faces and priorities of fine overlays
4407 (let ((fine-diff-vector (ediff-get-fine-diff-vector n))
4408 (face-A (if default 'default (face-name ediff-fine-diff-face-A)))
4409 (face-B (if default 'default (face-name ediff-fine-diff-face-B)))
4410 (priority-A (if default
4411 0
4412 (1+ (ediff-overlay-get ediff-current-diff-overlay-A
4413 'priority))))
4414 (priority-B (if default
4415 0
4416 (1+ (ediff-overlay-get ediff-current-diff-overlay-B
4417 'priority)))))
4418 (mapcar
4419 (function (lambda (vec)
4420 (ediff-overlay-put
4421 (ediff-get-diff-overlay-from-vector vec 'A)
4422 'face face-A)
4423 (ediff-overlay-put
4424 (ediff-get-diff-overlay-from-vector vec 'A)
4425 'priority priority-A)
4426
4427 (ediff-overlay-put
4428 (ediff-get-diff-overlay-from-vector vec 'B)
4429 'face face-B)
4430 (ediff-overlay-put
4431 (ediff-get-diff-overlay-from-vector vec 'B)
4432 'priority priority-B)
4433 ))
4434 fine-diff-vector)
4435 )))
4436
4437 (defun ediff-convert-diffs-to-overlays-refine (A-buffer B-buffer
4438 diff-list refine-region)
4439 (let* ((current-diff -1)
4440 (reg-A-start (ediff-get-diff-posn 'A 'beg refine-region))
4441 (reg-B-start (ediff-get-diff-posn 'B 'beg refine-region))
4442 diff-overlay-list list-element
4443 a-begin a-end b-begin b-end
4444 a-overlay b-overlay)
4445
4446 (ediff-eval-in-buffer A-buffer (goto-char reg-A-start))
4447 (ediff-eval-in-buffer B-buffer (goto-char reg-B-start))
4448
4449 (while diff-list
4450 (setq current-diff (1+ current-diff)
4451 list-element (car diff-list)
4452 a-begin (aref list-element 0)
4453 a-end (aref list-element 1)
4454 b-begin (aref list-element 2)
4455 b-end (aref list-element 3))
4456
4457 ;; put overlays at appropriate places in buffers
4458 (setq a-overlay (ediff-make-overlay
4459 (ediff-goto-word (1+ a-begin) A-buffer)
4460 (ediff-goto-word a-end A-buffer 'end)
4461 A-buffer))
4462
4463 (setq b-overlay (ediff-make-overlay
4464 (ediff-goto-word (1+ b-begin) B-buffer)
4465 (ediff-goto-word b-end B-buffer 'end)
4466 B-buffer))
4467
4468 ;; record all overlays for this difference
4469 (setq diff-overlay-list (nconc diff-overlay-list
4470 (list (vector a-overlay b-overlay)))
4471 diff-list (cdr diff-list))
4472 ) ;; while
4473 ;; convert the list of difference information into a vector for
4474 ;; fast access
4475 (apply 'vector diff-overlay-list)))
4476
4477 ;; goto word #n starting at current position in buffer `buf'
4478 ;; For ediff, a word is either a string of a-z,A-Z, incl `-' and `_';
4479 ;; or a string of other non-blanks. A blank is a \n\t\C-j
4480 ;; If `flag' is non-nil, goto the end of the n-th word.
4481 (defun ediff-goto-word (n buf &optional flag)
4482 (ediff-eval-in-buffer
4483 buf
4484 (skip-chars-forward ediff-whitespace)
4485 (while (> n 1)
4486 (funcall ediff-forward-word-function)
4487 (skip-chars-forward ediff-whitespace)
4488 (setq n (1- n)))
4489 ;(if flag
4490 (if (and flag (> n 0))
4491 (funcall ediff-forward-word-function))
4492 (point)))
4493
4494 (defun ediff-get-visible-buffer-window (wind)
4495 (if (ediff-if-lucid)
4496 (get-buffer-window wind t)
4497 (get-buffer-window wind 'visible)))
4498
4499
4500
4501
4502
4503 ;;; Misc
4504
4505 ;; These two functions are here to neutralize Lemacs' unwillingless to
4506 ;; handle overlays whose buffers have been deleted.
4507 (defun ediff-move-overlay (overlay beg end &optional buffer)
4508 "Calls `move-overlay' in Emacs and `set-extent-endpoints' in Lemacs.
4509 Checks if overlay's buffer exists before actually doing the move."
4510 (let ((buf (ediff-overlay-buffer overlay)))
4511 (if (ediff-buffer-live-p buf)
4512 (if (ediff-if-lucid)
4513 (set-extent-endpoints overlay beg end)
4514 (move-overlay overlay beg end buffer))
4515 (ediff-delete-overlay overlay))))
4516
4517 (defun ediff-overlay-put (overlay prop value)
4518 "Calls `overlay-put' or `set-extent-property' depending on Emacs version.
4519 Checks if overlay's buffer exists."
4520 (if (ediff-buffer-live-p (ediff-overlay-buffer overlay))
4521 (if (ediff-if-lucid)
4522 (set-extent-property overlay prop value)
4523 (overlay-put overlay prop value))
4524 (ediff-delete-overlay overlay)))
4525
4526
4527 ;; In Emacs 19.23 and Lucid 19.10, the number of variables to
4528 ;; file-name-handler has changed.
4529 (defun ediff-find-file-name-handler (file)
4530 (let (newvers)
4531 (setq newvers
4532 (cond ((and (boundp 'emacs-major-version)
4533 (> emacs-major-version 19))
4534 t)
4535 ((boundp 'emacs-minor-version)
4536 (if (ediff-if-lucid)
4537 (> emacs-minor-version 9)
4538 (> emacs-minor-version 22)))
4539 (t nil)))
4540 (if newvers
4541 (find-file-name-handler file 'find-file-noselect)
4542 (find-file-name-handler file))))
4543
4544
4545
4546
4547 (defun ediff-submit-report ()
4548 "Submit bug report on Ediff."
4549 (interactive)
4550 (let ((reporter-prompt-for-summary-p t)
4551 varlist salutation)
4552 (setq varlist '(ediff-diff-program ediff-diff-options
4553 ediff-fine-diff-program ediff-fine-diff-options
4554 ediff-patch-program ediff-patch-options
4555 ediff-shell
4556 ediff-want-faces ediff-want-default-menus
4557 ediff-auto-refine ediff-highlighting-style
4558 ediff-A-buffer ediff-B-buffer ediff-control-buffer
4559 ediff-forward-word-function))
4560 (setq salutation "
4561 Congratulations! You are about to report a bug in Ediff!
4562
4563 Please make a concise, accurate summary of what happened
4564 and mail it to the address above.
4565
4566 Some ``bugs'' may actually not be bugs at all. For instance, if you are
4567 reporting that certain difference regions are not matched as you think they
4568 should, this is most likely due to the way Unix diff program decides what
4569 constitutes a difference region. Ediff is an Emacs interface to diff, and
4570 it has nothing to do with those decisions---it only takes the output from
4571 diff and presents it in a way that is better suited for human browsing and
4572 manipulation.
4573
4574 Another popular topic for reports are ``error messages'' arising from
4575 byte-compilation. Because Ediff interfaces to several other packages and
4576 runs under Emacs and Lucid Emacs, byte-compilation may produce output like
4577 this:
4578 While compiling toplevel forms in file ediff.el:
4579 ** reference to free variable pm-color-alist
4580 ........................
4581 While compiling the end of the data:
4582 ** The following functions are not known to be defined:
4583 ediff-valid-color-p, ediff-display-color-p, ediff-set-face,
4584 ........................
4585
4586 These are NOT errors, but inevitable warnings that should be ignored.
4587
4588 So, please don't report those and similar things. However, if all you wanted
4589 is to tell us how much you liked Ediff, go ahead and send this message anyway.
4590
4591 ------------------------------------------------------------------")
4592
4593 (require 'reporter)
4594
4595 (reporter-submit-bug-report "kifer@cs.sunysb.edu"
4596 (ediff-version)
4597 varlist
4598 nil nil
4599 salutation)
4600 ))
4601
4602
4603 (defun ediff-union (list1 list2)
4604 "Combine LIST1 and LIST2 using a set-union operation.
4605 The result list contains all items that appear in either LIST1 or LIST2.
4606 This is a non-destructive function; it makes a copy of the data if necessary
4607 to avoid corrupting the original LIST1 and LIST2.
4608 This is a slightly simplified version from `cl-seq.el'. Added here to
4609 avoid loading cl-*."
4610 (cond ((null list1) list2) ((null list2) list1)
4611 ((equal list1 list2) list1)
4612 (t
4613 (or (>= (length list1) (length list2))
4614 (setq list1 (prog1 list2 (setq list2 list1))))
4615 (while list2
4616 (or (memq (car list2) list1)
4617 (setq list1 (cons (car list2) list1)))
4618 (setq list2 (cdr list2)))
4619 list1)))
4620
4621 ;(defun ediff-debug ()
4622 ; (interactive)
4623 ; (with-output-to-temp-buffer "*ediff-debug*"
4624 ; (princ
4625 ; (format "Ctl buffer: %S\n\nediff-difference-vector:\n"
4626 ; ediff-control-buffer))
4627 ; (mapcar (function
4628 ; (lambda (overl-vec)
4629 ; (princ (format "Diff %d: %S %S %S\n\t %S %S %S\n"
4630 ; (1+ (ediff-overlay-get (aref overl-vec 0)
4631 ; 'ediff-diff-num))
4632 ; (ediff-overlay-get (aref overl-vec 0)
4633 ; 'ediff-control-buffer)
4634 ; (ediff-overlay-get (aref overl-vec 0)
4635 ; 'insert-in-front-hooks)
4636 ; (aref overl-vec 0)
4637 ; (ediff-overlay-get (aref overl-vec 1)
4638 ; 'ediff-control-buffer)
4639 ; (ediff-overlay-get (aref overl-vec 0)
4640 ; 'insert-in-front-hooks)
4641 ; (aref overl-vec 1)
4642 ; ))))
4643 ; ediff-difference-vector)
4644 ; (princ "\nediff-disturbed-overlays:\n")
4645 ; (mapcar (function
4646 ; (lambda (overl)
4647 ; (princ (format "%S %S\n"
4648 ; (ediff-overlay-get overl 'ediff-control-buffer)
4649 ; overl
4650 ; ))))
4651 ; ediff-disturbed-overlays)))
4652
4653
4654 (run-hooks 'ediff-load-hooks)
4655
4656 2767
4657 (provide 'ediff) 2768 (provide 'ediff)
2769 (require 'ediff-util)
4658 2770
4659 ;;; ediff.el ends here 2771 ;;; ediff.el ends here