7267
|
1 ;;; ediff.el --- a visual interface to diff & patch
|
|
2 ;;; Copyright (C) 1994 Free Software Foundation, Inc.
|
|
3
|
|
4 ;; Author: Michael Kifer <kifer@cs.sunysb.edu>
|
|
5 ;; Created: February 2, 1994
|
7424
|
6 ;; Version: 1.52
|
|
7 ;; Keywords: tools
|
7267
|
8
|
|
9 ;; This file is part of GNU Emacs.
|
|
10
|
|
11 ;; GNU Emacs is free software; you can redistribute it and/or modify
|
|
12 ;; it under the terms of the GNU General Public License as published by
|
|
13 ;; the Free Software Foundation; either version 2, or (at your option)
|
|
14 ;; any later version.
|
|
15
|
|
16 ;; GNU Emacs is distributed in the hope that it will be useful,
|
|
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
19 ;; GNU General Public License for more details.
|
|
20
|
|
21 ;; You should have received a copy of the GNU General Public License
|
|
22 ;; along with GNU Emacs; see the file COPYING. If not, write to
|
|
23 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
24
|
|
25
|
|
26 ;;; Commentary:
|
|
27 ;; ----------
|
|
28
|
7391
|
29 ;; Never read those diff outputs again!
|
|
30 ;; Apply patch selectively, like a pro!
|
7267
|
31
|
|
32 ;; This package provides a convenient way of simultaneous brousing through
|
|
33 ;; the differences between a pair of files or buffers. The two files being
|
|
34 ;; compared (file-A and file-B) are shown in separate windows (side by
|
|
35 ;; side, one above the another, or in separate frames), and the differences
|
|
36 ;; are highlighted as you step through them. You can also copy difference
|
|
37 ;; regions from one buffer to another (and recover old differences if you
|
|
38 ;; change your mind).
|
|
39
|
|
40 ;; In addition, Ediff can apply a patch to a file and then let you step
|
|
41 ;; though both files, the patched and the original one, simultateously,
|
|
42 ;; difference-by-difference. You can even apply a patch right out of a
|
|
43 ;; mail buffer, i.e., patches received by mail don't even have to be saved.
|
|
44 ;; Since Ediff lets you copy differences between buffers, you can, in
|
|
45 ;; effect, apply patches selectively (i.e., you can copy a difference
|
|
46 ;; region from file.orig to file, thereby undoing any particular patch that
|
|
47 ;; you don't like).
|
|
48
|
7424
|
49 ;; This package builds upon the ideas borrowed from emerge.el. It is still
|
|
50 ;; using half a dozen of functions defined there. Several other Ediff's
|
|
51 ;; functions are adaptations from emerge.el. Ediff requires, at least,
|
|
52 ;; Version 5 of emerge.el. This version comes with standard distributions
|
|
53 ;; of Emacs and Lemacs. Make sure you don't have some stray old copy of
|
|
54 ;; Emerge on your load path.
|
|
55
|
|
56 ;; Ediff is complimentary to Emerge. While Emerge is primarily intended
|
|
57 ;; for merging of files, Ediff is by far superior for browsing through
|
|
58 ;; files compared via diff and for patching files with patch.
|
|
59 ;; Furthermore, Ediff is more convenient even for merging, when one of the
|
|
60 ;; files is a designated output. This situation arises while patching
|
|
61 ;; files or when comparing an old version of a file with a newer version
|
|
62 ;; (in such cases, it is often desirable to selectively revert some
|
|
63 ;; portions of the new file to its old state).
|
|
64
|
|
65 ;; Ediff also supports version control via vc.el (in the standard
|
|
66 ;; distribution of Emacs 19) and rcs.el. The latter is a package written by
|
|
67 ;; Sebastian Kremer <sk@thp.Uni-Koeln.DE>, which is available in
|
|
68 ;;
|
|
69 ;; ftp.cs.buffalo.edu:pub/Emacs/rcs.tar.Z
|
|
70 ;; ftp.uni-koeln.de:/pub/gnu/emacs/rcs.tar.Z
|
|
71 ;;
|
|
72
|
7267
|
73
|
|
74 ;; Window configuration:
|
|
75 ;; ----------------------
|
|
76
|
|
77 ;; By default, Ediff sets things up in one frame, splitting it between a
|
|
78 ;; small control window and the two windows for file-A and file-B. The
|
|
79 ;; split between these latter windows can be horizontal or vertical, which
|
|
80 ;; can be changed interactively by hitting 's' while the cursor is in the
|
|
81 ;; control window.
|
|
82 ;;
|
|
83 ;; In a multi-frame situation, Ediff would work as follows. When it starts,
|
|
84 ;; it will place the control window in the frame that was selected at the
|
|
85 ;; time of the invocation. If file-A or file-B is seen in one of the
|
|
86 ;; frames, Ediff will leave it there. If a file (A/B) is not visible in any
|
|
87 ;; frame, Ediff will arrange that it will share a frame with the control
|
|
88 ;; window. (If none of the files is visible, then both will share the
|
|
89 ;; control window frame.) The same algorithm works when you hit 'c'
|
|
90 ;; (ediff-recenter), 'p' (ediff-previous-difference), 'n', etc.
|
|
91 ;;
|
|
92 ;; Thus, you can compare files in one frame or in different frames.
|
|
93 ;; The former is done by default, while the latter can be achieved by
|
|
94 ;; arranging files A and B to be seen in different frames. Ediff
|
|
95 ;; respects these arrangements, automatically adapting itself to
|
|
96 ;; the multi-frame mode.
|
|
97
|
|
98
|
7424
|
99 ;; To those who like to go where noone has gone before:
|
7267
|
100
|
|
101 ;; Ediff lets the user run multiple sessions at once, i.e., you can invoke
|
|
102 ;; Ediff on different functions several times in a row, without exiting
|
|
103 ;; the previous Ediff sessions. Different sessions may even operate on the
|
|
104 ;; same pair of files. So, in principle, it is possible to do, say,
|
|
105 ;; pairwise comparison of three (or more) different files. Each session
|
|
106 ;; would have its own *ediff-control* buffer and all the regarding a
|
|
107 ;; particular session is local to the associated *ediff-control* buffer.
|
|
108 ;; You can switch between sessions by suspending one session and then
|
|
109 ;; switching to another *ediff-control* buffer. (Different such buffers
|
|
110 ;; are distinguished by a numerical suffix, e.g., *ediff-control*<3>.)
|
|
111 ;; This, if you would like to compare three files pairwise, you can do
|
|
112 ;; this by preparing three different frames, each with its own control
|
|
113 ;; window. (This would require a very wide screen, and I never claimed
|
|
114 ;; that such 3-way comparison is very easy to do.)
|
|
115 ;;
|
|
116 ;; If you need to conduct multiple Ediff sessions on the same file, one
|
|
117 ;; thing should be kept in mind: each time you invoke Ediff on a buffer that
|
|
118 ;; already participates in another Ediff session, that buffer should not
|
|
119 ;; have any ASCII Ediff flags in it. (Highlighting with faces is OK.) If
|
|
120 ;; flags are not removed, difference overlays won't be set correctly
|
|
121 ;; for the second invocation of Ediff. The simplest way to remove ASCII
|
7424
|
122 ;; flags from an Ediff buffer is to hit `h' and thus switch to highlighting
|
|
123 ;; with faces (unhighlighting on a dumb terminal).
|
7267
|
124
|
|
125
|
|
126 ;;; Remarks:
|
|
127 ;; -------
|
|
128
|
7424
|
129 ;; 1. Ediff is heavily dependent on the new features of Emacs 19.
|
|
130 ;; It won't run under Emacs 18 at all.
|
7267
|
131 ;; 2. If running Lucid Emacs, Ediff requires at least version 19.9.
|
7424
|
132 ;; 3. The function vc-ediff requires the vc.el version that comes with
|
7267
|
133 ;; Emacs 19.22.
|
|
134
|
|
135
|
|
136 ;;; Installation and use:
|
|
137 ;; --------------------
|
|
138
|
|
139 ;; You can invoke Ediff interactively using the following functions:
|
|
140 ;;
|
|
141 ;; ediff-buffers - compare buffers
|
|
142 ;; ediff (alias for ediff-files)
|
|
143 ;; ediff-files - compare files
|
|
144 ;; ediff-patch-file - patch file then compare
|
7424
|
145 ;; epatch - alias for ediff-patch-file
|
7267
|
146 ;; ediff-patch-buffer - patch buffer then compare
|
7424
|
147 ;; epatch-buffer - alias for ediff-patch-buffer
|
7267
|
148 ;; vc-ediff - compare buffer & version
|
|
149 ;; using vc.el package
|
|
150 ;; (Emacs 19.22 and up).
|
|
151 ;; rcs-ediff - same using rcs.el; rcs.el
|
|
152 ;; is not part of the
|
|
153 ;; standard Emacs distribution.
|
|
154 ;;
|
|
155 ;; There is also the function ediff-files-remote, which can be invoked only
|
|
156 ;; from within another Emacs Lisp function, i.e., non-interactively.
|
|
157 ;;
|
|
158 ;; To use Ediff, put this in your .emacs file:
|
|
159 ;;
|
7391
|
160 ;; (autoload 'ediff-buffers "ediff" "Visual interface to diff" t)
|
|
161 ;; (autoload 'ediff "ediff" "Visual interface to diff" t)
|
|
162 ;; (autoload 'ediff-files "ediff" "Visual interface to diff" t)
|
|
163 ;; (autoload 'epatch "ediff" "Visual interface to patch" t)
|
|
164 ;; (autoload 'ediff-patch-file "ediff" "Visual interface to patch" t)
|
|
165 ;; (autoload 'ediff-patch-buffer "ediff" "Visual interface to patch" t)
|
7424
|
166 ;; (autoload 'epatch-buffer "ediff" "Visual interface to patch" t)
|
7267
|
167 ;; (autoload 'vc-ediff "ediff"
|
|
168 ;; "Interface to diff & version control via vc.el" t)
|
|
169 ;; (autoload 'rcs-ediff "ediff"
|
|
170 ;; "Interface to diff & version control via rcs.el" t)
|
|
171 ;;
|
|
172 ;;
|
|
173 ;; If you want Ediff to be loaded from the very beginning, you should have
|
|
174 ;;
|
|
175 ;; (require 'ediff)
|
|
176 ;;
|
|
177 ;; in your .emacs file. This way it is also easier to figure out changes
|
|
178 ;; to the default Ediff setting, if such changes become necessary --- see
|
|
179 ;; Customization.
|
|
180 ;;
|
|
181
|
|
182 ;;; Compilation
|
|
183 ;; -----------
|
|
184 ;;
|
|
185 ;; When you byte-compile Ediff, you will get some warnings about functions
|
|
186 ;; being undefined. These can be safely ignored.
|
7424
|
187 ;;
|
|
188 ;; Important:
|
|
189 ;; =========
|
|
190 ;;
|
|
191 ;; If you are using advice.el (directly or indirectly, via one of the
|
|
192 ;; other packages), Ediff may not compile properly. In this case, you
|
|
193 ;; should do:
|
|
194 ;;
|
|
195 ;; M-x ad-deactivate-all RET
|
|
196 ;;
|
|
197 ;; M-x byte-compile-file RET ediff.el RET
|
|
198 ;;
|
|
199 ;; M-x ad-activate-all RET
|
|
200 ;;
|
|
201 ;; This precaution will not be needed starting with GNU Emacs 19.23 and
|
|
202 ;; Lucid Emacs 19.10, due to fixing a bug in advice.el.
|
7267
|
203
|
|
204 ;;; Customization:
|
|
205 ;; -------------
|
|
206
|
7424
|
207 ;; Hooks:
|
|
208 ;; -----
|
7267
|
209 ;; If you don't like the default setting, you can change it through the
|
|
210 ;; various variables and hooks. In particular, the following hooks are
|
|
211 ;; available:
|
|
212
|
|
213 ;; ediff-load-hooks
|
|
214 ;; ediff-before-setup-windows-hooks
|
|
215 ;; ediff-startup-hooks
|
|
216 ;; ediff-select-hooks
|
|
217 ;; ediff-unselect-hooks
|
|
218 ;; ediff-suspend-hooks
|
|
219 ;; ediff-quit-hooks
|
|
220 ;; ediff-prepare-buffer-hooks
|
|
221
|
|
222 ;; The hooks in ediff-load-hooks can be used to change defaults after Ediff
|
|
223 ;; is loaded.
|
|
224 ;; The hooks in ediff-before-setup-windows-hooks, ediff-suspend-hooks, and
|
|
225 ;; ediff-quit-hooks can be used to save and then restore whatever window
|
|
226 ;; configuration you want. However, make sure you understand what you are
|
|
227 ;; doing. Many variables that drive Ediff are local to the different
|
|
228 ;; *ediff-control* buffers. Take a look at ediff-default-suspend-hook and
|
|
229 ;; ediff-default-quit-hook to see what's involved.
|
|
230 ;; The hooks in ediff-prepare-buffer-hooks are executed for each Ediff buffer
|
|
231 ;; (A and B) right after these buffers are arranged.
|
|
232 ;;
|
7424
|
233 ;; Highlighting of difference regions
|
|
234 ;; ----------------------------------
|
7267
|
235 ;; The second group of Ediff variables that could be changed, if you so
|
|
236 ;; wish, is:
|
|
237 ;;
|
|
238 ;; ediff-before-flag-eol
|
|
239 ;; ediff-after-flag-eol
|
|
240 ;; ediff-before-flag-mol
|
|
241 ;; ediff-after-flag-mol
|
|
242 ;;
|
|
243 ;; ediff-current-diff-face-A
|
|
244 ;; ediff-current-diff-face-B
|
7424
|
245 ;; ediff-fine-diff-face-A
|
|
246 ;; ediff-fine-diff-face-B
|
7267
|
247 ;; ediff-even-diff-face-A
|
|
248 ;; ediff-even-diff-face-B
|
|
249 ;; ediff-odd-diff-face-A
|
|
250 ;; ediff-odd-diff-face-B
|
|
251 ;
|
|
252 ;; The first four are ASCII strings that mark the beginning and the end of
|
|
253 ;; the differences found in file-A and file-B. Ediff uses different flags
|
|
254 ;; to highlight regions that begin/end at the beginning of a line or in a
|
|
255 ;; middle of a line.
|
|
256
|
|
257 ;; The rest are the faces used to highlight text on X displays. On X
|
|
258 ;; displays, Ediff uses ediff-current-diff-face-A and
|
|
259 ;; ediff-current-diff-face-B to highlight the current difference regions.
|
7424
|
260 ;; The faces ediff-fine-diff-face-A and ediff-fine-diff-face-B
|
|
261 ;; are used to show the fine differences between the current differences
|
|
262 ;; regions in buffer A and B.
|
7267
|
263 ;; Other (non-current) difference regions are displayed in alternating
|
7391
|
264 ;; faces: ediff-even/odd-diff-face-A/B. The odd and the even
|
7267
|
265 ;; faces are actually identical on monochrome displays, because it is
|
7424
|
266 ;; rather poor in what you can do on such a display. So, I chose to use
|
|
267 ;; italics to highlight other differences. Any ideas would be welcome. (In
|
|
268 ;; Lucid Emacs, the faces are different because it supports pixmaps.)
|
7267
|
269 ;; There are two ways to change the default setting for highlighting faces:
|
|
270 ;; either change the variables, as in
|
|
271 ;;
|
|
272 ;; (setq ediff-current-diff-face-A (internal-get-face 'bold-italic))
|
|
273 ;;
|
|
274 ;; (`internal-get-face' should be `get-face' if you are using Lucid Emacs)
|
|
275 ;; or by selectively modifying the defaults:
|
|
276 ;;
|
|
277 ;; (add-hook 'ediff-load-hooks
|
|
278 ;; (function (lambda ()
|
|
279 ;; (set-face-foreground ediff-current-diff-face-B "blue")
|
|
280 ;; (set-face-background ediff-current-diff-face-B "red")
|
|
281 ;; (make-face-italic ediff-current-diff-face-B))))
|
|
282 ;;
|
|
283 ;; You may also want to take a look at how the above faces are defined in
|
|
284 ;; Ediff.
|
|
285 ;;
|
7424
|
286 ;; The last group of variables in this group,
|
7267
|
287 ;;
|
|
288 ;; ediff-want-faces
|
7424
|
289 ;; ediff-highlight-all-diffs
|
|
290 ;; ediff-want-default-menus
|
7267
|
291 ;;
|
|
292 ;; indicate whether---on a window system---you want differences to be
|
|
293 ;; marked using ASCII strings (like on a dumb terminal) or using colors and
|
|
294 ;; highlighting. If ediff-want-faces is t, then highlighting with faces is
|
|
295 ;; used. Normally, Ediff highlights all differences, but the selected
|
7424
|
296 ;; difference is highlighted more visibly. You can cycle through various
|
|
297 ;; modes of highlighting by hitting `h'. By default, Ediff starts in the
|
|
298 ;; mode where all difference regions are highlighted. If you prefer to
|
|
299 ;; start in the mode where unselected differences are not highlighted, you
|
|
300 ;; should set ediff-highlight-all-diffs to nil.
|
|
301 ;; You will still be able to turn on highlighting of all differences by
|
|
302 ;; hitting `h'.
|
|
303 ;; The variable `ediff-want-default-menus', if true, will cause Ediff to
|
|
304 ;; set up a pair of menues in the menu bar, so you can invoke it from there.
|
|
305 ;; If you don't like the look of the default menus, set this variable to
|
|
306 ;; nil and design your own menus.
|
7267
|
307 ;;
|
|
308 ;; If you plan on changing these variables, they must be set
|
|
309 ;; BEFORE ediff.el is loaded.
|
|
310 ;;
|
|
311 ;; Note: Ediff lets you switch between the two types of highlighting. That
|
|
312 ;; is you can switch, interactively, from highlighting using faces to
|
|
313 ;; highlighting using ASCII flags, and back. Of course, toggling has
|
|
314 ;; effect only on a window system. On a dumb terminal or in an xterm
|
|
315 ;; window, the only available option is highlighting with ASCII flags.
|
|
316 ;;
|
7424
|
317 ;; Refining difference regions
|
|
318 ;; ---------------------------
|
|
319 ;; There are also variables that control the way fine differences are
|
|
320 ;; highlighted. This feature lets the user highlight the exact words that
|
|
321 ;; make the difference regions in buffer A and B different. This process
|
|
322 ;; ignores spaces, tabs, and newlines.
|
|
323 ;;
|
|
324 ;; ediff-auto-refine
|
|
325 ;; ediff-auto-refine-limit
|
|
326 ;;
|
|
327 ;; By default, `ediff-auto-refine' is `'on', which means that fine differences
|
|
328 ;; within regions will be highlighted automatically. On a slow system, this
|
|
329 ;; feature may be undesirable. In any case, the user can always toggle
|
|
330 ;; auto-refining on/off/nix by hitting `@'. When auto-refining is off, fine
|
|
331 ;; differences will be shown only for regions for which these differences
|
|
332 ;; have been computed and saved before. If auto-refining is nixed, fine
|
|
333 ;; differences will not be shown at all. Hitting `*' will compute and
|
|
334 ;; display fine differences for the current difference region regardless of
|
|
335 ;; whether auto-refining is on, off, or nixed.
|
|
336 ;; If auto-refining is on, the variable `ediff-auto-refine-limit' limits
|
|
337 ;; the size of the regions to be auto-refined. This variable guards against
|
|
338 ;; possible slow-down that may be caused by an extraordinary large
|
|
339 ;; difference region. However, the user can always force refining by
|
|
340 ;; hitting `*'.
|
|
341 ;;
|
|
342 ;; ediff-fine-diff-program
|
|
343 ;; ediff-fine-diff-options
|
|
344 ;; ediff-wordify-function
|
|
345 ;;
|
|
346 ;; These variables let the user control how fine differences are computed.
|
|
347 ;; `ediff-fine-diff-program' is diff, by default. However, you can use
|
|
348 ;; any function as long as it produces output consistent with diff.
|
|
349 ;; `ediff-wordify-function' is a lisp function that determines how the
|
|
350 ;; current difference region is split into words. (Fine diferences are
|
|
351 ;; computed by first splitting the current difference region into words and
|
|
352 ;; then passing this along to `ediff-fine-diff-program'. For the default
|
|
353 ;; wordify function, `ediff-wordify', a word is a string consisting of
|
|
354 ;; letters, `-', or `_', or a string consisting of symbols that are neither
|
|
355 ;; space, nor a letter.)
|
|
356 ;;
|
|
357 ;; Patch and diff programs
|
|
358 ;; -----------------------
|
|
359 ;; The next group of variables determines the programs to be used for
|
|
360 ;; applying patches and for computing the main difference regions (not the
|
|
361 ;; fine difference regions):
|
7267
|
362 ;;
|
|
363 ;; ediff-patch-program
|
|
364 ;; ediff-patch-options
|
|
365 ;; ediff-diff-program
|
|
366 ;; ediff-diff-options
|
|
367 ;;
|
|
368 ;; These specify the functions that produce differences and do patching.
|
|
369 ;; The *-options variables specify which options to pass to these programs.
|
|
370 ;; It is unlikely that you would want to change these. One possible
|
|
371 ;; exception is when you may want to generate differences with context
|
|
372 ;; lines in order to send a patch file through email. Then, you might want
|
|
373 ;; to set ediff-diff-options to '-c'. Sometimes, you may also want to tell
|
7391
|
374 ;; diff to ignore spaces and such. Use the option '-w' for that. Diff
|
7267
|
375 ;; has several other useful options (type 'man diff' to find out).
|
|
376 ;;
|
7391
|
377 ;; The output from diff is found in *ediff-diff* buffer. However, this
|
7267
|
378 ;; makes sense only if you also intend to use Ediff to browse through the
|
|
379 ;; diff'ed files before sending the patch. This is because diff.el is much
|
7424
|
380 ;; faster in yielding the output of diff (Ediff is a big gun, if used
|
7267
|
381 ;; for this simple purpose).
|
|
382 ;;
|
7424
|
383 ;; Miscellaneous
|
|
384 ;; -------------
|
7267
|
385 ;; The last set of variables that can be modified is
|
|
386 ;;
|
|
387 ;; ediff-split-window-function
|
|
388 ;; ediff-use-last-dir
|
7424
|
389 ;; ediff-no-help-in-control-buffer
|
7267
|
390 ;;
|
|
391 ;; ediff-split-window-function controls the way you want the window be
|
|
392 ;; split between file-A and file-B. It defaults to vertical split, but you
|
|
393 ;; can set it to 'split-window-horizontally, if you want. Ediff lets you
|
|
394 ;; toggle the way windows are split, so you can try different settings
|
|
395 ;; interactively. Note: if file-A and file-B are in different frames,
|
|
396 ;; windows are not split, regardless of the value
|
|
397 ;; ediff-split-window-function. Instead, other windows on these frames are
|
|
398 ;; deleted and Ediff starts displaying file-A and file-B using these two
|
|
399 ;; frames, one file per frame. You can then switch to one-frame mode
|
|
400 ;; simply by hiding the file-A/B buffer that is displayed on a frame other
|
|
401 ;; than the control-window frame.
|
|
402 ;;
|
|
403 ;; Note that if Ediff sees that the two buffers it compares are residing in
|
|
404 ;; separate frames, it assumes that the user wants them to be so displayed
|
|
405 ;; and stops splitting windows. Instead, it will arrange each buffer to
|
|
406 ;; occupy its own frame (possibly shared with Ediff's help window).
|
|
407 ;;
|
|
408 ;; The variable ediff-use-last-dir controls the way Ediff presents the
|
|
409 ;; default directory when it prompts the user for files to compare. If nil,
|
|
410 ;; Ediff will use the default directory of the current buffer when it
|
|
411 ;; prompts the user for file names. Otherwise, it will use the
|
|
412 ;; directories it had previously used for file-A and file-B.
|
|
413 ;;
|
7424
|
414 ;; The ediff-no-help-in-control-buffer, if set to t, makes C-h behave like
|
7267
|
415 ;; the DEL key, i.e., it will move you back to the previous difference
|
|
416 ;; rather than invoking help. This is useful when, in an xterm window or on
|
|
417 ;; a dumb terminal, the Backspace key is bound to C-h and is positioned
|
|
418 ;; more conveniently than the DEL key.
|
|
419
|
|
420
|
|
421 ;;; Commands
|
|
422 ;; --------
|
|
423
|
|
424 ;; All Ediff commands are displayed in a help window, unless you hit '?' to
|
|
425 ;; shrink it to just one line. You can redisplay the help window by hitting
|
|
426 ;; '?' again.
|
|
427 ;;
|
|
428 ;; Many Ediff commands take numeric prefix arguments. For instance, if you
|
7424
|
429 ;; hit a number, N, and then 'j' (ediff-jump-to-difference), Ediff will
|
|
430 ;; take you to Nth difference. Hitting a number, N, and then 'ab'
|
7419
|
431 ;; (ediff-diff-to-diff) will copy Nth difference from buffer A to buffer B.
|
7267
|
432 ;; Hitting 'ba' does copying in the other direction.
|
7424
|
433 ;; Likewise, a number, N, followed by 'ra' will restore the Nth difference
|
7267
|
434 ;; region in buffer A (if it was previously saved as a result of copying
|
|
435 ;; from B to A).
|
|
436 ;;
|
|
437 ;; Without the prefix argument, all commands operate on the current
|
|
438 ;; difference region.
|
|
439 ;;
|
|
440 ;; The total number of differences and the current difference number are
|
|
441 ;; always displayed in the mode line of the control window.
|
|
442
|
|
443 ;;; Display Modes
|
|
444 ;; -------------
|
|
445
|
|
446 ;; Ediff can display files in one frame, stacked side-by-side or one on top
|
|
447 ;; of another; or it can display the files in different frames. When you
|
|
448 ;; start Ediff, it assumes a 1-frame mode. You can toggle the side-by-side
|
|
449 ;; and one-on-top-of-another displays by simply hitting 's'.
|
|
450 ;;
|
|
451 ;; Ediff switches to the multi-frame mode when:
|
|
452 ;;
|
|
453 ;; 1. file-A and file-B are in different frames (you have to put them into
|
|
454 ;; different frames manually); or
|
|
455 ;; 2. *ediff-control* buffer is visible in one frame and one other file (A
|
|
456 ;; or B) is visible in another frame. If, say, fileA is visible in a
|
|
457 ;; different frame than *ediff-control*, fileB doesn't have to be
|
|
458 ;; visible. If it is, Ediff will continue displaying fileB in the frame
|
|
459 ;; where it was visible before. If it isn't then Ediff will arrange for
|
|
460 ;; fileB to share a frame with *ediff-control*.
|
|
461 ;;
|
|
462 ;; If all three buffers are in separate frames, Ediff will switch to a
|
|
463 ;; 3-frame mode. If Ediff buffers are currently visible only in two
|
|
464 ;; frames, Ediff will work in a 2-frame mode. In this mode, one of the
|
|
465 ;; frames will be shared by *ediff-control* and file-A or file-B
|
|
466 ;; (whichever is appropriate).
|
|
467
|
|
468
|
|
469 ;;; Bugs:
|
|
470 ;; ----
|
|
471
|
|
472 ;; 1. The undo command doesn't restore deleted regions well. That is, if
|
|
473 ;; you delete all characters in a difference region and then invoke
|
|
474 ;; `undo', the reinserted text will most likely be reinserted outside of
|
7424
|
475 ;; what Ediff thinks is the current difference region. (This problem
|
|
476 ;; doesn't seem to exist with Lucid Emacs.)
|
|
477 ;;
|
|
478 ;; If at any point you feel that difference regions are no longer correct,
|
|
479 ;; you can hit '!' to recompute the differences.
|
|
480
|
|
481 ;; 2. Emacs 19.xx, where xx < 23, has several bugs related to overlays and
|
|
482 ;; faces. Somethimes, these may cause highlighting of the refinements or
|
|
483 ;; of the unselected differences to disappear. Hitting `!' will bring them
|
|
484 ;; back. In version 19.23, these problems no longer occur.
|
|
485
|
|
486 ;; 3. On a monochrome display, the repertoire of faces with which to
|
|
487 ;; highlight fine differences is limited. By default, Ediff is using
|
|
488 ;; underlining. However, if the region is already underlied by some other
|
|
489 ;; overlays, there is no simple way to temporarily remove that residual
|
|
490 ;; underlining. This problem occurs when a buffer is highlighted with
|
|
491 ;; hilit19.el or font-lock.el packages. If this residual highlighting gets
|
|
492 ;; in the way, you can do the following. Both font-lock.el and hilit19.el
|
|
493 ;; provide commands for unhighlighting buffers. You can either place these
|
|
494 ;; commands in `ediff-prepare-buffer-hooks' (which will unhighlight every
|
|
495 ;; buffer used by Ediff) or you can execute them interactively, at any time
|
|
496 ;; and on any buffer.
|
|
497
|
|
498 ;; 4. In Lucid Emacs (statically linked with Motif libraries), emerge.el
|
|
499 ;; and hence ediff.el won't start, unless you set (setq scrollbar-width 0).
|
|
500 ;; This is a Motif-related bug, I was told.
|
7267
|
501
|
|
502
|
|
503 ;;; Change Log:
|
|
504 ;; ----------
|
|
505
|
|
506 ;; Thu Feb 3, 1994
|
|
507
|
|
508 ;; Added ediff-read-file-name, which is a stub that takes care of Lemacs
|
|
509 ;; versions of Emerge. (Thanks to Alastair Burt <burt@dfki.uni-kl.de>.)
|
|
510 ;;
|
|
511 ;; Fixed a bug in ediff-setup-windows that caused control window to
|
|
512 ;; appear in a wrong place when split-window-keep-point is nil
|
|
513 ;; (Thanks to Kevin Broadey <KevinB@bartley.demon.co.uk>.)
|
|
514 ;;
|
|
515 ;; Added mechanism for using faces instead of before/after flags. This
|
|
516 ;; looks much better on an X display, especially on a color one.
|
|
517 ;; (Thanks to Boris Goldowsky <boris@cs.rochester.edu> for the code
|
|
518 ;; that led to ediff-highlight-diff.
|
|
519 ;; Also, thanks to Kevin Esler <esler@ch.hp.com> for suggestions
|
|
520 ;; regarding highlighting differences on X displays.)
|
|
521 ;;
|
|
522 ;; Added functions to apply patches.
|
|
523 ;; (Thanks to Kevin Broadey <KevinB@bartley.demon.co.uk> for this
|
|
524 ;; suggestion.)
|
|
525
|
|
526 ;; Fri Feb 4, 1994
|
|
527
|
|
528 ;; Added mechanism for toggling vertical/horizontal window split.
|
|
529 ;; (Inspired by a suggestion from Allan Gottlieb
|
|
530 ;; <gottlieb@allan.ultra.nyu.edu> -- thanks.)
|
|
531 ;;
|
|
532 ;; Added mechanism for toggling between highlighting using faces and
|
|
533 ;; highlighting using ASCII flags.
|
|
534 ;;
|
|
535 ;; Fixed a problem with undo. Now, Ediff has smartened up and doesn't
|
|
536 ;; keep undo info on ASCII flags inserted in buffer-A and buffer-B.
|
|
537 ;; So, if you edit the files while browsing through them, undo behaves
|
|
538 ;; as you would expect, i.e., faces/flags don't get in the way.
|
|
539
|
|
540 ;; Sun Feb 6, 1994
|
|
541
|
|
542 ;; Added horizontal scrolling. Added ediff-position-region to ensure
|
|
543 ;; that difference regions in buffer-A and buffer-B are aligned with
|
|
544 ;; each other. Disabled ediff-toggle-split when buffers are displayed
|
|
545 ;; in different frames.
|
|
546
|
|
547 ;; Mon Feb 7, 1994
|
|
548
|
|
549 ;; Added toggle-window help (Suggested by Boris Goldowsky
|
|
550 ;; <boris@cs.rochester.edu>.)
|
|
551 ;; Added functions to copy differences from one buffer to another and to
|
|
552 ;; recover old differences.
|
|
553 ;; Added prefix arguments to ediff-next-difference and
|
|
554 ;; ediff-previous-difference.
|
|
555
|
|
556 ;; Tue Feb 8, 1994
|
|
557
|
|
558 ;; Replaced text properties with overlays. Fixed ediff-setup-windows.
|
|
559 ;; Added ediff-save-buffer to local-write-file-hooks to prevent user
|
|
560 ;; from saving corrupted states. (Thanks to <boris@cs.rochester.edu>
|
|
561 ;; for suggestion.) Instead, Ediff now has a pair of functions for
|
|
562 ;; safe saving of buffers.
|
|
563 ;; Changed ediff-read-file-name to be more intuitive on ediff-files.
|
|
564 ;; Added ediff-prepare-buffer-hooks. (Thanks to Kevin Esler
|
|
565 ;; <esler@ch.hp.com> for the idea.)
|
|
566
|
|
567 ;; Wed Feb 9, 1994
|
|
568
|
|
569 ;; Cleanups in ediff-patch-file. Protected ediff-copy-diff against
|
|
570 ;; a bug that Emacs has in kill-region.
|
|
571
|
|
572 ;; Thu Feb 10, 1994
|
|
573
|
|
574 ;; Added support for Lemacs. (Thanks to Alastair Burt
|
|
575 ;; <burt@dfki.uni-kl.de> for coercing Ediff into working under Lemacs.)
|
|
576 ;; Added ediff-kill-buffer-carefully and other suggestions by Boris
|
|
577 ;; Goldowsky <boris@cs.rochester.edu>.
|
|
578 ;; Refined the protection against interference with highlighting caused
|
|
579 ;; by Hilit19. Added the variable ediff-third-party-highlighting.
|
|
580 ;; Added mechanisn for unhighlighting regions highlighted with Hilit19
|
|
581 ;; before hightlighting them with Ediff's overlays. (And for
|
|
582 ;; rehighlighting them with Hilit19, when the current difference moves on.)
|
|
583
|
|
584 ;; Sun Feb 13, 1994
|
|
585
|
|
586 ;; Added ediff-place-flags-in-buffer and ediff-remote-exit, which are
|
|
587 ;; modifications of Emerge's similar functions. The difference is that
|
|
588 ;; in Ediff they make ediff-before-flag and ediff-after-flag into
|
|
589 ;; read-only regions, so the user can't change them by mistake.
|
|
590 ;;
|
|
591 ;; Adopted a suggestion by Boris Goldowsky <boris@cs.rochester.edu>
|
|
592 ;; that led to a more elegant treatment of faces.
|
|
593 ;;
|
|
594 ;; Added protection against interference with Font-Lock highlighting
|
|
595 ;; similar to that of Hilit19's protection.
|
|
596
|
|
597 ;; Tue Feb 15, 1994
|
|
598
|
|
599 ;; Deleted spurious (auto-save-mode 1) in ediff-control-buffer, which
|
|
600 ;; was causing this buffer to be auto-saved for no good reason.
|
|
601 ;; Added read-only protection to ediff-before/after-flags in Lemacs.
|
|
602 ;; (Thanks to Alastair Burt <burt@dfki.uni-kl.de> for help in testing.)
|
|
603
|
|
604 ;; Wed Feb 16, 1994
|
|
605
|
|
606 ;; Further fixes in the Lemacs part. Changed highlighted region in
|
|
607 ;; ediff-highlight-diff so that an extra character will be highlighted
|
|
608 ;; only if a difference is empty (thereby allowing the user to see where an
|
|
609 ;; insertion or a deletion has taken place).
|
|
610 ;;
|
|
611 ;; Simplified interaction with other highlighting packages by giving
|
|
612 ;; Ediff overlays the highest priority. (Taking a cue from
|
|
613 ;; ediff-highlight-diff-lemacs written by Alastair Burt
|
|
614 ;; <burt@dfki.uni-kl.de>.) Zapped ediff-third-party-highlighting
|
|
615 ;; variable and hooks that were previously used to
|
|
616 ;; unhighlight/rehighlight buffers when hilit19/font-lock are on.
|
|
617
|
|
618 ;; Fri Feb 18, 1994
|
|
619
|
|
620 ;; Added a bit more sophistication to ediff-read-file-name. Now,
|
|
621 ;; ediff-files remembers both, the file-A and the file-B directories.
|
|
622 ;; They are offered as defaults when ediff-use-last-dir is set to t.
|
|
623
|
|
624 ;; Fri Feb 22, 1994
|
|
625
|
|
626 ;; Added ediff-before-change-guard to remove ASCII highlighting when
|
|
627 ;; the user attempts to change buffer-A/B. This is needed because
|
|
628 ;; otherwise the undo info may become screwed up in those buffers.
|
|
629 ;; Hitting 'h' (ediff-toggle-hilit) on a dumb terminal will toggle
|
|
630 ;; between ASCII highlighting and no highlighting.
|
|
631
|
|
632 ;; Fri Feb 24, 1994
|
|
633
|
|
634 ;; Fixed problems with multiple Ediff sessions running simultaneously.
|
|
635
|
|
636 ;; Tue Mar 1, 1994
|
|
637
|
|
638 ;; Added vc-ediff, the Ediff interface to vc.el. (Thanks to Eric
|
|
639 ;; Freudenthal <freudent@jan.ultra.nyu.edu> for contributing this
|
|
640 ;; function.)
|
|
641
|
|
642 ;; Sun Mar 6, 1994
|
|
643
|
|
644 ;; Added rcs-ediff, an Ediff interface to RCS via rcs.el. (Thanks to
|
|
645 ;; Alastair Burt <burt@dfki.uni-kl.de>.)
|
|
646 ;; Some minor improvements.
|
|
647
|
|
648 ;; Tue March 15, 1994
|
|
649
|
|
650 ;; Fixed a buglet in defining ediff-current-diff-face-A/B.
|
|
651 ;; (Thanks to Job Ganzevoort <Job.Ganzevoort@cwi.nl>.)
|
|
652
|
|
653 ;; Tue March 22, 1994
|
|
654
|
|
655 ;; Fixed a bug with ediffing narrowed buffers, reported by Kevin
|
|
656 ;; Broadey <KevinB@bartley.demon.co.uk>.
|
|
657 ;; Made Ediff to work with files that have incomplete last line.
|
7391
|
658 ;; Made Ediff execute diff and patch using Bourne Shell, which
|
7267
|
659 ;; should eliminate problems with $prompt that some people had.
|
|
660
|
|
661 ;; Thu March 24, 1994
|
|
662
|
|
663 ;; Achieved quadratic speedup in the size of the file by replacing the
|
|
664 ;; slow goto-line by forward-line. Ediff is now *much* faster than
|
|
665 ;; Emerge on large files. Converted demarkation of difference regions
|
|
666 ;; from markers to overlays. This will later allow us to highlight all
|
|
667 ;; diffs, not just the current one.
|
|
668
|
|
669 ;; Wed March 30, 1994
|
|
670
|
|
671 ;; Under X, Ediff now highlights all differences in dim colors and the
|
|
672 ;; current difference in bright colors. Improved Lucid Emacs support.
|
|
673
|
|
674 ;; Thu March 31, 1994
|
|
675
|
|
676 ;; Changed toggle hilit to cycle through 3 states: highlighting all
|
|
677 ;; diffs, highlighting only the current diff, and highlighting using
|
|
678 ;; ASCII flags.
|
|
679 ;; Added support for difference regions that are not full lines.
|
|
680
|
|
681 ;; Fri April 1, 1994
|
|
682
|
|
683 ;; Fixed bugs related to writing buffers A and B.
|
|
684 ;; Added commands 'ga', 'gb' to jump directly to the closest diff in
|
|
685 ;; buffer A and B, respectively.
|
|
686
|
7424
|
687 ;; Fri April 11, 1994
|
|
688
|
|
689 ;; Added `ediff-recompute-diffs', a function that lets the user recompute
|
|
690 ;; difference regions after extensive editing done to buffers A and B
|
|
691 ;; (bound to `!').
|
|
692
|
|
693 ;; Wed April 13, 1994
|
|
694
|
|
695 ;; Added the new feature: refining the current difference region.
|
|
696 ;; This would highlight the precise differences between the regions in
|
|
697 ;; buffer A and B. (A way to implement this was suggested by Boris
|
|
698 ;; Goldowsky <boris@cs.rochester.edu>.)
|
|
699 ;;
|
|
700 ;; Fixed Ediff to be immune to several different versions of rcs.el
|
|
701 ;; that are currently in distribution.
|
|
702
|
|
703 ;; Thu April 14, 1994
|
|
704
|
|
705 ;; Ediff now respects X resources for the faces it uses. It no longer
|
|
706 ;; barks when the colormap has no colors it is using; or when face
|
|
707 ;; fonts can't be italicized, etc.
|
|
708
|
|
709 ;; Fri April 15, 1994
|
|
710
|
|
711 ;; Changed `ediff-setup-windows' to minimize the need to delete and
|
|
712 ;; create windows. Now jumps faster from diff to diff.
|
|
713
|
|
714 ;; Sat April 16, 1994
|
|
715
|
|
716 ;; Added Ediff to the File menu on the menu bar (FSF's version).
|
|
717
|
|
718 ;; Mon April 18, 1994
|
|
719
|
|
720 ;; Fixed to work with OS/2's PM-Emacs.
|
|
721
|
|
722 ;; Thu April 21, 1994
|
|
723
|
|
724 ;; Lemacs' menus added (thanks to Alastair Burt for the help).
|
|
725
|
|
726 ;; Wed April 28, 1994
|
|
727
|
|
728 ;; Fixed ediff-leave-window-config (thanks to Norbert Kiesel
|
|
729 ;; <norbert@i3.informatik.rwth-aachen.de>), ediff-shell and
|
|
730 ;; ediff-protect-metachars (thanks to Richard Stanton
|
|
731 ;; <stanton@haas.berkeley.edu>). Made access to difference
|
|
732 ;; overlays structure-independent, making it less bug-prone.
|
|
733 ;; Patched ediff-read-file-name to work more intuitively with directory
|
|
734 ;; names (thanks to Kevin Broadey <KevinB@bartley.demon.co.uk>).
|
|
735
|
|
736 ;; Mon May 2, 1994
|
|
737
|
|
738 ;; Added `ediff-frame-has-menubar' to guard against the possibility that
|
|
739 ;; the current frame has no menu bar.
|
|
740
|
|
741 ;; Fri May 6, 1994
|
|
742
|
|
743 ;; Fixed buglet in vc-ediff (thanks to Ray Nickson <nickson@cs.uq.oz.au>).
|
|
744
|
|
745
|
|
746 ;;; Acknowledgements:
|
|
747
|
|
748 ;; Special thanks to Alastair Burt <burt@dfki.uni-kl.de>, Kevin Esler
|
|
749 ;; <esler@ch.hp.com>, Kevin Broadey <KevinB@bartley.demon.co.uk>,
|
|
750 ;; Eric Freudenthal <freudent@jan.ultra.nyu.edu>, Job Ganzevoort
|
|
751 ;; <Job.Ganzevoort@cwi.nl>, Boris Goldowsky <boris@cs.rochester.edu>,
|
|
752 ;; Allan Gottlieb <gottlieb@allan.ultra.nyu.edu>, Xiaoli Huang
|
|
753 ;; <hxl@epic.com>, irvine@lks.csi.com, jaffe@chipmunk.cita.utoronto.ca,
|
|
754 ;; David Karr, <dkarr@nmo.gtegsc.com>, Norbert Kiesel
|
|
755 ;; <norbert@i3.informatik.rwth-aachen.de>, Heinz Knutzen
|
|
756 ;; <hk@informatik.uni-kiel.d400.de>, Martin Maechler
|
|
757 ;; <maechler@stat.math.ethz.ch>, Richard Mlynarik <mly@adoc.xerox.com>,
|
|
758 ;; Ray Nickson <nickson@cs.uq.oz.au>, Andy Scott <ascott@pcocd2.intel.com>,
|
|
759 ;; Richard Stanton <stanton@haas.berkeley.edu>, for contributing ideas,
|
|
760 ;; patches and bug reports.
|
|
761 ;;
|
|
762 ;; Thanks also to many others who felt obliged to drop a thanks note.
|
|
763
|
|
764
|
7267
|
765
|
|
766 ;;; Code:
|
|
767
|
7424
|
768 (require 'emerge) ;; Ediff uses some functions defined in emerge.el
|
7267
|
769
|
|
770
|
|
771 ;;; Macros
|
|
772 (defmacro ediff-if-lucid ()
|
|
773 (` (string-match "Lucid" emacs-version)))
|
7424
|
774
|
7267
|
775 (defmacro ediff-odd-p (arg)
|
|
776 (` (eq (logand (, arg) 1) 1)))
|
7424
|
777
|
7267
|
778 (defmacro ediff-buffer-live-p (buf)
|
|
779 (` (and (, buf) (get-buffer (, buf)) (buffer-name (get-buffer (, buf))))))
|
|
780
|
7424
|
781 (defmacro ediff-get-buffer (arg)
|
|
782 (` (cond ((eq (, arg) 'A) ediff-A-buffer)
|
|
783 ((eq (, arg) 'B) ediff-B-buffer)
|
|
784 )
|
|
785 ))
|
|
786
|
|
787 (defmacro ediff-char-to-buftype (arg)
|
|
788 (` (cond ((eq (, arg) ?a) 'A)
|
|
789 ((eq (, arg) ?b) 'B)
|
|
790 )
|
|
791 ))
|
|
792
|
|
793 (defmacro ediff-get-difference (n)
|
|
794 (` (aref ediff-difference-vector (, n))))
|
|
795
|
|
796 (defmacro ediff-get-diff-overlay-from-vector (vec buf-type)
|
|
797 (` (aref (, vec)
|
|
798 (cond ((eq (, buf-type) 'A) 0)
|
|
799 ((eq (, buf-type) 'B) 1)
|
|
800 )
|
|
801 )))
|
|
802
|
|
803 (defmacro ediff-get-diff-overlay (n buf-type)
|
|
804 (` (ediff-get-diff-overlay-from-vector
|
|
805 (ediff-get-difference (, n))
|
|
806 (, buf-type))))
|
|
807
|
|
808 (defmacro ediff-get-fine-diff-vector-from-vec (current-diff-vec)
|
|
809 (` (aref (, current-diff-vec) 2)))
|
|
810
|
|
811 (defmacro ediff-set-fine-diff-vector (n fine-vec)
|
|
812 (` (aset (ediff-get-difference (, n)) 2 (, fine-vec))))
|
|
813
|
|
814 (defmacro ediff-get-fine-diff-vector (n)
|
|
815 (` (ediff-get-fine-diff-vector-from-vec (ediff-get-difference (, n)))))
|
|
816
|
|
817 (defmacro ediff-frame-has-menubar ()
|
|
818 (if (ediff-if-lucid)
|
|
819 current-menubar
|
|
820 (< 0 (cdr (assq 'menu-bar-lines (frame-parameters (selected-frame)))))
|
|
821 ))
|
|
822
|
|
823
|
|
824 ;;; Functions
|
7267
|
825
|
|
826 (defun ediff-mode ()
|
|
827 "Ediff mode is used by the Ediff file-difference package.
|
|
828 It is entered only through one of the following commands:
|
7419
|
829 `ediff'
|
|
830 `ediff-files'
|
|
831 `ediff-buffers'
|
|
832 `epatch'
|
|
833 `ediff-patch-file'
|
|
834 `ediff-patch-buffer'
|
7424
|
835 `epatch-buffer'
|
7419
|
836 `vc-ediff'
|
|
837 `rcs-ediff'
|
7267
|
838 or through a non-interactive Emacs Lisp function
|
7419
|
839 `ediff-files-remote'
|
7267
|
840
|
|
841 Commands:
|
|
842 \\{ediff-mode-map}"
|
|
843 (interactive)
|
|
844 (kill-all-local-variables)
|
|
845 (setq major-mode 'ediff-mode)
|
|
846 (setq mode-name "Ediff"))
|
|
847
|
7424
|
848 (defvar ediff-version "1.52"
|
7267
|
849 "The current version of Ediff.")
|
|
850
|
|
851 (defun ediff-version ()
|
|
852 "Return string describing the version of Ediff.
|
|
853 When called interactively, displays the version."
|
|
854 (interactive)
|
|
855 (if (interactive-p)
|
|
856 (message "Ediff version %s" (ediff-version))
|
|
857 ediff-version))
|
|
858
|
|
859
|
|
860 ;; Hook variables
|
|
861
|
|
862 (defvar ediff-before-setup-windows-hooks nil
|
7424
|
863 "*Hooks to run before Ediff sets its own window config.
|
|
864 This can be used to save the previous window config, which can be restored
|
|
865 on ediff-quit or ediff-suspend.")
|
7267
|
866 (defvar ediff-startup-hooks nil
|
|
867 "*Hooks to run in the control buffer after Ediff has been set up.")
|
|
868 (defvar ediff-select-hooks nil
|
|
869 "*Hooks to run after a difference has been selected.")
|
|
870 (defvar ediff-unselect-hooks nil
|
|
871 "*Hooks to run after a difference has been unselected.")
|
|
872 (defvar ediff-prepare-buffer-hooks nil
|
|
873 "*Hooks called after buffers A and B are set up.")
|
|
874 (defvar ediff-load-hooks nil
|
7419
|
875 "*Hook run after Ediff is loaded. Can be used to change defaults.")
|
7267
|
876
|
7424
|
877 (defvar ediff-suspend-hooks (list 'ediff-default-suspend-hook)
|
7419
|
878 "*Hooks to run in the Ediff control buffer when Ediff is suspended.")
|
7424
|
879 (defvar ediff-quit-hooks (list 'ediff-default-quit-hook)
|
7419
|
880 "*Hooks to run in the Ediff control buffer after finishing Ediff.")
|
7267
|
881
|
|
882 (make-variable-buffer-local 'local-write-file-hooks)
|
|
883 (make-variable-buffer-local 'before-change-function)
|
|
884
|
|
885 ;; Help messages
|
|
886
|
|
887 (defconst ediff-help-message-long
|
7424
|
888 "p,DEL - prev diff v/V - scroll up/dn * - refine diff ! - recomp diffs
|
|
889 n,SPC - next diff </> - scroll lt/rt ab - diff A to B l - line numbers
|
|
890 j - jump to diff s - toggle split ba - diff B to A f - file names
|
|
891 ga/gb - goto pt in A/B h - toggle hilit ra - restore A z - suspend Ediff
|
|
892 c - recenter @ - toggle refine rb - restore B q - quit Ediff
|
|
893 wa/wb - save buf A/B A/B - toggle read-only in buffers A/B ? - toggle help")
|
7267
|
894
|
|
895 (defconst ediff-help-message-short
|
7424
|
896 " ? - toggle help window")
|
7267
|
897
|
|
898 (defvar ediff-help-message ediff-help-message-long
|
7419
|
899 "*The actual help message.")
|
7267
|
900
|
7424
|
901 ;; diff stuff.
|
7267
|
902 (defvar ediff-diff-program "diff"
|
7419
|
903 "*Name of the program that compares two files.")
|
7267
|
904 (defvar ediff-diff-options ""
|
7419
|
905 "*Options to pass to `ediff-diff-program'.")
|
7267
|
906
|
7424
|
907 ;; Find diff stuff.
|
|
908 (defvar ediff-wordify-function 'ediff-wordify
|
|
909 "*Function to call to split current diff region into separate words.")
|
|
910
|
|
911 (defvar ediff-fine-diff-program "diff"
|
|
912 "*Name of the program that compares the current diff regions for fine differences.
|
|
913
|
|
914 This program should produce output in the format of diff. One could
|
|
915 possibly use `spiff' here if appropriate options are set.")
|
|
916
|
|
917 (defvar ediff-fine-diff-options ""
|
|
918 "*Options to pass to `ediff-fine-diff-program'.")
|
|
919
|
|
920 (defvar ediff-whitespace " \n\t\j"
|
|
921 "*White space. Used to split strings into words.")
|
|
922
|
|
923 (defvar ediff-word-1 "a-zA-Z---_`'.?!:"
|
|
924 "*Characters constituting type 1 words.
|
|
925
|
|
926 Ediff is using a very simple schema for splitting text into words, which is
|
|
927 used to determine fine differences between regions. There are two types of
|
|
928 words. One consists entirely out of characters in `ediff-word-1' and
|
|
929 another out of characters matching `ediff-word-1'.")
|
|
930
|
|
931 (defvar ediff-word-2 "^a-zA-Z---_`'.?!: \t\n\j"
|
|
932 "*Characters matching this regexp constitute words of type 2.
|
|
933 See `ediff-word-1' for more details.")
|
|
934
|
7267
|
935
|
|
936 ;; Support for patches
|
|
937
|
|
938 (defvar ediff-patch-program "patch"
|
7419
|
939 "*Name of the program that applies patches.")
|
7267
|
940 (defvar ediff-patch-options ""
|
7419
|
941 "*Options to pass to ediff-patch-program.")
|
7267
|
942
|
7424
|
943 (defvar ediff-shell (cond ((eq system-type 'emx) "cmd") ;; OS/2
|
|
944 (t "sh")) ;; unix
|
|
945 "*The shell used to run diff and patch. If user's .profile or
|
|
946 .cshrc files are set up correctly, any shell will do. However, some people
|
|
947 set $prompt or other things incorrectly, which leads to undesirable output
|
|
948 messages. These may cause Ediff to fail. In such a case, set ediff-shell
|
|
949 to a shell that you are not using or, better, fix your shell's startup file.")
|
|
950
|
7267
|
951 (defvar ediff-diff-ok-lines-regexp
|
|
952 "^\\([0-9,]+[acd][0-9,]+$\\|[<>] \\|---\\|Warning:\\)"
|
7419
|
953 "*Regexp that matches normal output lines from `ediff-diff-program'.
|
7267
|
954 This is mostly lifted from Emerge, except that Ediff also considers the
|
|
955 'Missing newline' message to be 'normal output.'
|
|
956 Lines that do not match are assumed to be error messages.")
|
|
957
|
7424
|
958 (defvar ediff-fine-diff-ok-lines-regexp
|
|
959 "^\\([0-9,]+[acd][0-9,]+$\\|[<>] \\|---\\|Warning:\\)"
|
|
960 "*Regexp that matches normal output lines from `ediff-fine-diff-program'.
|
|
961 This is mostly lifted from Emerge, except that Ediff also considers the
|
|
962 'Missing newline' message to be 'normal output.'
|
|
963 Lines that do not match are assumed to be error messages.")
|
|
964
|
7267
|
965 (defvar ediff-match-diff-line (let ((x "\\([0-9]+\\)\\(\\|,\\([0-9]+\\)\\)"))
|
|
966 (concat "^" x "\\([acd]\\)" x "$"))
|
|
967 "*Pattern to match lines produced by diff that describe differences.")
|
|
968
|
|
969 (defvar ediff-patch-buf nil
|
|
970 "The buffer of the patch file.")
|
|
971 (defvar ediff-patch-diagnostics nil
|
7391
|
972 "The buffer where patch would display its diagnostics.")
|
7267
|
973
|
|
974
|
|
975 ;; Copying diffs betw buffers.
|
|
976
|
|
977 (emerge-defvar-local ediff-killed-diffs-alist nil
|
7424
|
978 "A list of killed diffs.
|
7419
|
979 A diff is saved here if it is replaced by a diff
|
7267
|
980 from another buffer. This alist has the form:
|
7424
|
981 ((num (A . diff) (B . diff)) ...),
|
7419
|
982 where A or B parts may be missing.")
|
7267
|
983
|
|
984
|
|
985 ;; Highlighting
|
|
986 (defvar ediff-before-flag-bol
|
|
987 ;"vvvvvvvvvvvvvvvv---- ediff ----vvvvvvvvvvvvvvv\n"
|
|
988 ">>--->>>\n"
|
7424
|
989 "*Flag placed above the highlighted block of differences.
|
|
990 Must end with newline. Must be set before Ediff is loaded.")
|
7267
|
991 (defvar ediff-after-flag-bol
|
|
992 ;"^^^^^^^^^^^^^^^^---- ediff ----^^^^^^^^^^^^^^^\n"
|
|
993 "<<<---<<\n"
|
7419
|
994 "*Flag placed below the highlighted block of differences.
|
7424
|
995 Must end with newline. Must be set before Ediff is loaded.")
|
7267
|
996
|
|
997 (defvar ediff-before-flag-mol ">>--->>>"
|
7419
|
998 "*Like ediff-before-flag, used when a difference starts in mid-line.")
|
7267
|
999 (defvar ediff-after-flag-mol "<<<---<<"
|
7419
|
1000 "*Like ediff-after-flag, used when a difference starts in mid-line.")
|
7267
|
1001
|
|
1002 (emerge-defvar-local ediff-before-flag-A nil
|
|
1003 "This is the actual ASCII before-flag in effect in buffer A.
|
|
1004 It is either `ediff-before-flag-mol' or `ediff-before-flag-bol' depending
|
|
1005 on whether the selected difference region starts in the middle of a line
|
|
1006 or at the beginning of a line.")
|
|
1007 (emerge-defvar-local ediff-after-flag-A nil
|
|
1008 "This is the actual ASCII after-flag in effect in buffer A.
|
|
1009 It is either `ediff-before-flag-mol' or `ediff-before-flag-bol' depending
|
|
1010 on whether the selected difference region starts in the middle of a line
|
|
1011 or at the beginning of a line.")
|
|
1012 (emerge-defvar-local ediff-before-flag-B nil
|
|
1013 "This is the actual ASCII before-flag in effect in buffer B.
|
|
1014 It is either `ediff-before-flag-mol' or `ediff-before-flag-bol' depending
|
|
1015 on whether the selected difference region starts in the middle of a line
|
|
1016 or at the beginning of a line.")
|
|
1017 (emerge-defvar-local ediff-after-flag-B nil
|
|
1018 "This is the actual ASCII after-flag in effect in buffer B.
|
|
1019 It is either `ediff-before-flag-mol' or `ediff-before-flag-bol' depending
|
|
1020 on whether the selected difference region starts in the middle of a line
|
|
1021 or at the beginning of a line.")
|
|
1022
|
|
1023
|
|
1024 (emerge-defvar-local ediff-want-faces t
|
7419
|
1025 "If t, differences are highlighted using faces on a window system.
|
|
1026 If nil, they are highlighted using ASCII flags, ediff-before-flag
|
7267
|
1027 and ediff-after-flag. On a non-window system, differences are always
|
|
1028 highlighted using ASCII flags.
|
|
1029
|
7424
|
1030 This variable can be set either in .emacs or toggled interactively, using
|
|
1031 ediff-toggle-hilit.")
|
|
1032
|
|
1033 (emerge-defvar-local ediff-want-default-menus t
|
|
1034 "If t, Ediff will set up menus in the menu bar.
|
|
1035 This variable must be set before Ediff is loaded. If you don't like the
|
|
1036 look of the default menus, set this variable to nil and make your own
|
|
1037 menus.")
|
|
1038
|
|
1039 (emerge-defvar-local ediff-auto-refine 'on
|
|
1040 "If `'on', Ediff auto-highlights fine diffs for the current diff region.
|
|
1041 If `off', auto-highlighting is not used. If `'nix', no fine diffs are shown
|
|
1042 at all, unless the user force-refines the region by hitting `*'.
|
|
1043
|
|
1044 This variable can be set either in .emacs or toggled interactively, using
|
|
1045 ediff-toggle-hilit.")
|
|
1046
|
|
1047 (emerge-defvar-local ediff-auto-refine-limit 700
|
|
1048 "Auto-refine only those regions that are smaller than this number of bytes.")
|
|
1049
|
|
1050 (emerge-defvar-local ediff-highlight-all-diffs t
|
|
1051 "If nil, only the selected differences are highlighted.
|
|
1052 This variable can be set either in .emacs or toggled interactively, using
|
|
1053 ediff-toggle-hilit.")
|
7267
|
1054
|
|
1055 (emerge-defvar-local ediff-highlighting-style nil
|
7419
|
1056 "A var local to each ediff-control buffer.
|
|
1057 Indicates highlighting style in effect for this buffer: `face', `ascii',
|
|
1058 nil -- temporarily unhighlighted, `off' -- turned off \(on a dumb
|
|
1059 terminal only\).")
|
7267
|
1060
|
|
1061
|
|
1062
|
|
1063 ;; Variables that control each Ediff session. They are local to the
|
|
1064 ;; control buffer.
|
|
1065
|
|
1066 ;; Mode variables
|
|
1067 (emerge-defvar-local ediff-A-buffer nil
|
|
1068 "The buffer in which the A variant is stored.")
|
|
1069 (emerge-defvar-local ediff-B-buffer nil
|
|
1070 "The buffer in which the B variant is stored.")
|
|
1071 (emerge-defvar-local ediff-control-buffer nil
|
|
1072 "The control buffer of ediff. ")
|
|
1073
|
7424
|
1074 ;(emerge-defvar-local ediff-control-buffer-suffix nil
|
|
1075 ; "The suffix of the control buffer name. ")
|
7267
|
1076
|
7424
|
1077 (emerge-defvar-local ediff-control-window nil
|
7267
|
1078 "The control window.")
|
7424
|
1079 (emerge-defvar-local ediff-window-config-saved ""
|
|
1080 "Ediff's window configuration.
|
|
1081 Used to minimize the need to rearrange windows.")
|
7267
|
1082
|
|
1083
|
|
1084 (emerge-defvar-local ediff-A-buffer-values nil
|
|
1085 "Keeps working values of ediff-saved-variables for ediff-A-buffer.")
|
|
1086 (emerge-defvar-local ediff-B-buffer-values nil
|
|
1087 "Keeps working values of ediff-saved-variables for ediff-B-buffer.")
|
|
1088
|
|
1089 (emerge-defvar-local ediff-A-buffer-values-setup nil
|
|
1090 "Remembers ediff-saved-variables for ediff-A-buffer as they were at setup.")
|
|
1091 (emerge-defvar-local ediff-B-buffer-values-setup nil
|
|
1092 "Remembers ediff-saved-variables for ediff-B-buffer as they were at setup.")
|
|
1093
|
|
1094 (emerge-defvar-local ediff-difference-vector nil
|
7424
|
1095 "Vector of differences between the variants.
|
7419
|
1096 Each difference is represented by a vector of two overlays. The first
|
7424
|
1097 overlays the difference section in the A buffer and the second overlays the
|
|
1098 diff in the B buffer. If a difference section is empty, the corresponding
|
|
1099 overlay's endpoints coincide. ")
|
7267
|
1100
|
|
1101 (emerge-defvar-local ediff-current-difference -1
|
|
1102 "The difference that is currently selected.")
|
|
1103 (emerge-defvar-local ediff-number-of-differences nil
|
|
1104 "Number of differences found.")
|
|
1105
|
|
1106 (emerge-defvar-local ediff-diff-buffer nil
|
7424
|
1107 "Buffer containing the output of diff, which is used by Ediff to step
|
|
1108 through files.")
|
|
1109 (emerge-defvar-local ediff-tmp-buffer nil
|
|
1110 "Temporary buffer used for computing fine differences.")
|
|
1111 (emerge-defvar-local ediff-error-buffer nil
|
|
1112 "Buffer containing the output of diff when diff returns errors.")
|
|
1113
|
7267
|
1114 (emerge-defvar-local ediff-this-buffer-control-sessions nil
|
7419
|
1115 "List of ediff-control buffers associated with each buffer A/B.")
|
7267
|
1116
|
|
1117 (defvar ediff-disturbed-overlays nil
|
7419
|
1118 "List of difference overlays disturbed by working with the current diff.")
|
7267
|
1119
|
|
1120 (defvar ediff-shaded-overlay-priority
|
|
1121 (if (ediff-if-lucid)
|
|
1122 (1+ mouse-highlight-priority)
|
|
1123 100) ;; 100 is a kludge. There is a bug in insert-in-front-hooks
|
|
1124 ;; in Emacs < 19.23. When this is fixed, I will get rid of
|
|
1125 ;; this kludge.
|
|
1126 "Priority of non-selected overlays.")
|
|
1127
|
|
1128
|
|
1129 (if (ediff-if-lucid)
|
|
1130 (progn
|
|
1131 (fset 'ediff-overlayp (symbol-function 'extentp))
|
|
1132 (fset 'ediff-make-overlay (symbol-function 'make-extent))
|
|
1133 (fset 'ediff-delete-overlay (symbol-function 'delete-extent))
|
|
1134 (fset 'ediff-overlay-put (symbol-function 'set-extent-property))
|
|
1135 (fset 'ediff-move-overlay (symbol-function 'set-extent-endpoints))
|
|
1136 (fset 'ediff-overlay-start (symbol-function 'extent-start-position))
|
|
1137 (fset 'ediff-overlay-end (symbol-function 'extent-end-position))
|
|
1138 (fset 'ediff-overlay-get (symbol-function 'extent-property)))
|
|
1139 (fset 'ediff-overlayp (symbol-function 'overlayp))
|
|
1140 (fset 'ediff-make-overlay (symbol-function 'make-overlay))
|
|
1141 (fset 'ediff-delete-overlay (symbol-function 'delete-overlay))
|
|
1142 (fset 'ediff-overlay-put (symbol-function 'overlay-put))
|
|
1143 (fset 'ediff-move-overlay (symbol-function 'move-overlay))
|
|
1144 (fset 'ediff-overlay-start (symbol-function 'overlay-start))
|
|
1145 (fset 'ediff-overlay-end (symbol-function 'overlay-end))
|
|
1146 (fset 'ediff-overlay-get (symbol-function 'overlay-get)))
|
|
1147
|
|
1148 (if window-system
|
|
1149 (if (ediff-if-lucid)
|
|
1150 (progn
|
|
1151 (fset 'ediff-select-frame (symbol-function 'select-screen))
|
|
1152 (fset 'ediff-window-frame (symbol-function 'window-screen))
|
|
1153 (fset 'ediff-display-color-p (symbol-function 'x-color-display-p))
|
7424
|
1154 (fset 'ediff-valid-color-p (symbol-function 'x-valid-color-name-p))
|
7267
|
1155 (fset 'ediff-get-face (symbol-function 'get-face)))
|
|
1156 (fset 'ediff-window-frame (symbol-function 'window-frame))
|
|
1157 (fset 'ediff-select-frame (symbol-function 'select-frame))
|
|
1158 (fset 'ediff-display-color-p (symbol-function 'x-display-color-p))
|
7424
|
1159
|
|
1160 ;; This is a temporary fix for OS/2 users
|
|
1161 ;; pm-win.el in PM-Emacs should be fixed.
|
|
1162 (if (eq window-system 'pm)
|
|
1163 (fset 'ediff-valid-color-p
|
|
1164 (function (lambda (color) (assoc color pm-color-alist))))
|
|
1165 (fset 'ediff-valid-color-p (symbol-function 'x-color-defined-p))
|
|
1166 )
|
|
1167
|
7267
|
1168 (fset 'ediff-get-face (symbol-function 'internal-get-face)))
|
|
1169 ;; not a window system
|
|
1170 (fset 'ediff-window-frame (function (lambda (wind) (if wind 1 nil)) ))
|
|
1171 (fset 'ediff-select-frame (symbol-function 'identity))
|
|
1172 (fset 'ediff-make-current-diff-overlay (function (lambda (type) nil)))
|
|
1173 (fset 'ediff-unhighlight-diffs-totally (function (lambda () nil))))
|
|
1174
|
|
1175
|
|
1176 (if (not window-system)
|
|
1177 ()
|
7424
|
1178 (defun ediff-set-face (ground face color)
|
|
1179 "Sets face foreground/background. If color unavailable, guides the user."
|
|
1180 (if (ediff-valid-color-p color)
|
|
1181 (if (eq ground 'foreground)
|
|
1182 (set-face-foreground face color)
|
|
1183 (set-face-background face color))
|
|
1184 (cond ((memq face
|
|
1185 '(ediff-current-diff-face-A ediff-current-diff-face-B))
|
|
1186 (copy-face 'highlight face))
|
|
1187 ((memq face
|
|
1188 '(ediff-fine-diff-face-A ediff-fine-diff-face-B))
|
|
1189 (copy-face 'secondary-selection face)
|
|
1190 (set-face-underline-p face t))
|
|
1191 ((memq face
|
|
1192 '(ediff-odd-diff-face-A ediff-odd-diff-face-B
|
|
1193 ediff-even-diff-face-A ediff-even-diff-face-B))
|
|
1194 (copy-face 'secondary-selection face)))))
|
|
1195
|
7267
|
1196 (defvar ediff-current-diff-face-A
|
|
1197 (progn
|
|
1198 (make-face 'ediff-current-diff-face-A)
|
7424
|
1199 (or (face-differs-from-default-p 'ediff-current-diff-face-A)
|
|
1200 (cond ((ediff-display-color-p)
|
|
1201 (ediff-set-face
|
|
1202 'foreground 'ediff-current-diff-face-A "firebrick")
|
|
1203 (ediff-set-face
|
|
1204 'background 'ediff-current-diff-face-A "pale green"))
|
|
1205 (t
|
|
1206 (if (ediff-if-lucid)
|
|
1207 (copy-face 'modeline 'ediff-current-diff-face-A)
|
|
1208 (copy-face 'highlight 'ediff-current-diff-face-A))
|
|
1209 )))
|
7267
|
1210 (ediff-get-face 'ediff-current-diff-face-A))
|
7424
|
1211 "Face for highlighting the selected difference in buffer A.")
|
7267
|
1212
|
|
1213 (defvar ediff-current-diff-face-B
|
|
1214 (progn
|
|
1215 (make-face 'ediff-current-diff-face-B)
|
7424
|
1216 (or (face-differs-from-default-p 'ediff-current-diff-face-B)
|
|
1217 (cond ((ediff-display-color-p)
|
|
1218 (ediff-set-face
|
|
1219 'foreground 'ediff-current-diff-face-B "DarkOrchid")
|
|
1220 (ediff-set-face
|
|
1221 'background 'ediff-current-diff-face-B "Yellow"))
|
|
1222 (t
|
|
1223 (if (ediff-if-lucid)
|
|
1224 (copy-face 'modeline 'ediff-current-diff-face-B)
|
|
1225 (copy-face 'highlight 'ediff-current-diff-face-B))
|
|
1226 )))
|
7267
|
1227 (ediff-get-face 'ediff-current-diff-face-B))
|
7424
|
1228 "Face for highlighting the selected difference in buffer B.")
|
|
1229
|
|
1230 (defvar ediff-fine-diff-face-A
|
|
1231 (progn
|
|
1232 (make-face 'ediff-fine-diff-face-A)
|
|
1233 (or (face-differs-from-default-p 'ediff-fine-diff-face-A)
|
|
1234 (cond ((ediff-display-color-p)
|
|
1235 (ediff-set-face 'foreground 'ediff-fine-diff-face-A
|
|
1236 "Navy")
|
|
1237 (ediff-set-face 'background 'ediff-fine-diff-face-A
|
|
1238 "sky blue"))
|
|
1239 (t (set-face-underline-p 'ediff-fine-diff-face-A t))))
|
|
1240 (ediff-get-face 'ediff-fine-diff-face-A))
|
|
1241 "Face for highlighting the refinement of the selected diff in buffer A.")
|
|
1242
|
|
1243 (defvar ediff-fine-diff-face-B
|
|
1244 (progn
|
|
1245 (make-face 'ediff-fine-diff-face-B)
|
|
1246 (or (face-differs-from-default-p 'ediff-fine-diff-face-B)
|
|
1247 (cond ((ediff-display-color-p)
|
|
1248 (ediff-set-face 'foreground 'ediff-fine-diff-face-B "Black")
|
|
1249 (ediff-set-face 'background 'ediff-fine-diff-face-B "cyan"))
|
|
1250 (t (set-face-underline-p 'ediff-fine-diff-face-B t))))
|
|
1251 (ediff-get-face 'ediff-fine-diff-face-B))
|
|
1252 "Face for highlighting the refinement of the selected diff in buffer B.")
|
|
1253
|
7267
|
1254
|
|
1255 (defvar ediff-even-diff-face-A
|
|
1256 (progn
|
|
1257 (make-face 'ediff-even-diff-face-A)
|
7424
|
1258 (or (face-differs-from-default-p 'ediff-even-diff-face-A)
|
|
1259 (cond ((ediff-display-color-p)
|
|
1260 (ediff-set-face
|
|
1261 'foreground 'ediff-even-diff-face-A "black")
|
|
1262 (ediff-set-face
|
|
1263 'background 'ediff-even-diff-face-A "light grey"))
|
|
1264 (t
|
|
1265 (if (ediff-if-lucid)
|
|
1266 (progn
|
|
1267 (copy-face 'highlight 'ediff-even-diff-face-A)
|
|
1268 (invert-face 'ediff-even-diff-face-A))
|
|
1269 (copy-face 'italic 'ediff-even-diff-face-A)))))
|
7267
|
1270 (ediff-get-face 'ediff-even-diff-face-A))
|
|
1271 "Face used to highlight even-numbered differences in buffer A.")
|
|
1272
|
|
1273 (defvar ediff-even-diff-face-B
|
|
1274 (progn
|
|
1275 (make-face 'ediff-even-diff-face-B)
|
7424
|
1276 (or (face-differs-from-default-p 'ediff-even-diff-face-B)
|
|
1277 (cond ((ediff-display-color-p)
|
|
1278 (ediff-set-face
|
|
1279 'foreground 'ediff-even-diff-face-B "White")
|
|
1280 (ediff-set-face
|
|
1281 'background 'ediff-even-diff-face-B "Gray"))
|
|
1282 (t
|
|
1283 (if (ediff-if-lucid)
|
|
1284 (copy-face 'highlight 'ediff-even-diff-face-B)
|
|
1285 (copy-face 'italic 'ediff-even-diff-face-B)))))
|
7267
|
1286 (ediff-get-face 'ediff-even-diff-face-B))
|
|
1287 "Face used to highlight even-numbered differences in buffer B.")
|
7424
|
1288
|
7267
|
1289 (defvar ediff-odd-diff-face-A
|
|
1290 (progn
|
|
1291 (make-face 'ediff-odd-diff-face-A)
|
7424
|
1292 (or (face-differs-from-default-p 'ediff-odd-diff-face-A)
|
|
1293 (cond ((ediff-display-color-p)
|
|
1294 (ediff-set-face
|
|
1295 'foreground 'ediff-odd-diff-face-A "White")
|
|
1296 (ediff-set-face
|
|
1297 'background 'ediff-odd-diff-face-A "Gray"))
|
|
1298 (t
|
|
1299 (if (ediff-if-lucid)
|
|
1300 (copy-face 'highlight 'ediff-odd-diff-face-A)
|
|
1301 (copy-face 'italic 'ediff-odd-diff-face-A)))))
|
|
1302 (ediff-get-face 'ediff-odd-diff-face-A))
|
7267
|
1303 "Face used to highlight odd-numbered differences in buffer A.")
|
|
1304
|
|
1305 (defvar ediff-odd-diff-face-B
|
|
1306 (progn
|
|
1307 (make-face 'ediff-odd-diff-face-B)
|
7424
|
1308 (or (face-differs-from-default-p 'ediff-odd-diff-face-B)
|
|
1309 (cond ((ediff-display-color-p)
|
|
1310 (ediff-set-face
|
|
1311 'foreground 'ediff-odd-diff-face-B "Black")
|
|
1312 (ediff-set-face
|
|
1313 'background 'ediff-odd-diff-face-B "light grey"))
|
|
1314 (t
|
|
1315 (if (ediff-if-lucid)
|
|
1316 (progn
|
|
1317 (copy-face 'highlight 'ediff-odd-diff-face-B)
|
|
1318 (invert-face 'ediff-odd-diff-face-B))
|
|
1319 (copy-face 'italic 'ediff-odd-diff-face-B)))))
|
7267
|
1320 (ediff-get-face 'ediff-odd-diff-face-B))
|
|
1321 "Face used to highlight odd-numbered differences in buffer B.")
|
7424
|
1322
|
7267
|
1323 ;; Create *-var faces. These are the actual faces used to highlight
|
|
1324 ;; odd-numbered difference regions.
|
|
1325 ;; They are used as follows: when highlighting is turned on,
|
|
1326 ;; ediff-odd/even-diff-face-A/B are copied
|
|
1327 ;; into ediff-odd/even-diff-face-A/B-var, and all odd/even overlays become
|
|
1328 ;; highlighted. When highlighting is turned off, then the face 'default is
|
|
1329 ;; copied into ediff-odd/even-diff-face-A/B-var, thereby unhighlighting all
|
|
1330 ;; difference regions.
|
|
1331 (make-face 'ediff-even-diff-face-A-var)
|
|
1332 (make-face 'ediff-even-diff-face-B-var)
|
|
1333 (make-face 'ediff-odd-diff-face-A-var)
|
|
1334 (make-face 'ediff-odd-diff-face-B-var)
|
|
1335
|
|
1336 ;; initialize *-var faces
|
|
1337 (defun ediff-init-var-faces ()
|
7424
|
1338 (copy-face (if (and ediff-want-faces ediff-highlight-all-diffs)
|
7267
|
1339 ediff-even-diff-face-A 'default)
|
|
1340 'ediff-even-diff-face-A-var)
|
7424
|
1341 (copy-face (if (and ediff-want-faces ediff-highlight-all-diffs)
|
7267
|
1342 ediff-even-diff-face-B 'default)
|
|
1343 'ediff-even-diff-face-B-var)
|
7424
|
1344 (copy-face (if (and ediff-want-faces ediff-highlight-all-diffs)
|
7267
|
1345 ediff-odd-diff-face-A 'default)
|
|
1346 'ediff-odd-diff-face-A-var)
|
7424
|
1347 (copy-face (if (and ediff-want-faces ediff-highlight-all-diffs)
|
7267
|
1348 ediff-odd-diff-face-B 'default)
|
|
1349 'ediff-odd-diff-face-B-var))
|
|
1350
|
|
1351
|
|
1352 ;;; Overlays
|
|
1353
|
|
1354 (emerge-defvar-local ediff-current-diff-overlay-A nil
|
|
1355 "Overlay in buffer A.")
|
|
1356 (emerge-defvar-local ediff-current-diff-overlay-B nil
|
|
1357 "Overlay in buffer B.")
|
|
1358
|
|
1359 (defun ediff-make-current-diff-overlay (type)
|
|
1360 (let ((overlay (if (eq type 'A)
|
|
1361 'ediff-current-diff-overlay-A
|
|
1362 'ediff-current-diff-overlay-B))
|
7424
|
1363 (buffer (ediff-get-buffer type))
|
7267
|
1364 (face (if (eq type 'A)
|
|
1365 (face-name ediff-current-diff-face-A)
|
|
1366 (face-name ediff-current-diff-face-B))))
|
|
1367 (set overlay (ediff-make-overlay (point-max) (point-max) buffer))
|
|
1368 (ediff-overlay-put (eval overlay) 'face face)
|
|
1369 (ediff-overlay-put (eval overlay) 'ediff ediff-control-buffer)
|
|
1370 ))
|
|
1371
|
|
1372 ;; Computes priority of ediff overlay.
|
|
1373 (defun ediff-highest-priority (start end buffer)
|
|
1374 (let ((pos (max 1 (1- start)))
|
|
1375 ovr-list)
|
|
1376 (if (ediff-if-lucid)
|
|
1377 (+ 2 mouse-highlight-priority)
|
|
1378 (emerge-eval-in-buffer
|
|
1379 buffer
|
|
1380 (while (< pos (min (point-max) (1+ end)))
|
|
1381 (setq ovr-list (append (overlays-at pos) ovr-list))
|
|
1382 (setq pos (next-overlay-change pos)))
|
|
1383 (1+ (eval
|
|
1384 (cons '+
|
|
1385 (mapcar (function
|
|
1386 (lambda (ovr)
|
|
1387 (if ovr
|
|
1388 (or (ediff-overlay-get ovr 'priority) 0)
|
|
1389 0)))
|
|
1390 ovr-list)
|
|
1391 )))
|
|
1392 ))))
|
|
1393
|
|
1394 ) ; end of window-system-only code.
|
|
1395
|
|
1396
|
|
1397
|
|
1398 ;;; Misc
|
|
1399
|
|
1400 (defvar ediff-split-window-function 'split-window-vertically
|
7419
|
1401 "*The function to split the main window between buffer-A and buffer-B.
|
|
1402 You can set it to be split horizontally instead of the
|
7424
|
1403 default vertical split by setting this variable to
|
7267
|
1404 'split-window-horizontally. You can also have your own function for fancy
|
|
1405 splits. This variable has no effect when buffer-A and buffer-B are shown in
|
|
1406 different frames. In this case, Ediff will use those frames to display
|
|
1407 these buffers.")
|
|
1408
|
|
1409 (defconst ediff-saved-variables
|
|
1410 '(buffer-read-only
|
|
1411 buffer-auto-save-file-name)
|
7419
|
1412 "Buffer-local variables saved and restored during an Ediff session.")
|
7267
|
1413
|
|
1414 (defconst ediff-working-values '(nil nil)
|
7419
|
1415 "Values to be assigned to `ediff-saved-variables' during diff.")
|
7267
|
1416
|
|
1417 (defvar ediff-use-last-dir nil
|
7419
|
1418 "*If t, Ediff uses previous directory as default when reading file name.")
|
7267
|
1419
|
|
1420 (defvar ediff-nix-help-in-control-buffer nil
|
7419
|
1421 "*Non-nil mean C-h should not to invoke Emacs help.
|
|
1422 Instead, C-h jumps to previous difference.")
|
7267
|
1423
|
|
1424 (defvar ediff-temp-file-prefix
|
|
1425 (let ((env (getenv "TMPDIR"))
|
|
1426 d)
|
|
1427 (setq d (if (and env (> (length env) 0))
|
|
1428 env
|
|
1429 "/tmp"))
|
|
1430 (if (= (aref d (1- (length d))) ?/)
|
|
1431 (setq d (substring d 0 -1)))
|
|
1432 (concat d "/ediff"))
|
|
1433 "*Prefix to put on Ediff temporary file names.
|
|
1434 Do not start with `~/' or `~user-name/'.")
|
|
1435
|
|
1436 (defvar ediff-temp-file-mode 384 ; u=rw only
|
|
1437 "*Mode for Ediff temporary files.")
|
|
1438
|
7424
|
1439 (emerge-defvar-local ediff-temp-file-A nil
|
|
1440 "Temporary file used for refining difference regions in buffer B.")
|
|
1441 (emerge-defvar-local ediff-temp-file-B nil
|
|
1442 "Temporary file used for refining difference regions in buffer B.")
|
|
1443
|
7267
|
1444 (defvar ediff-last-dir-A nil
|
|
1445 "Last directory used by an Ediff command for file-A.")
|
|
1446 (defvar ediff-last-dir-B nil
|
|
1447 "Last directory used by an Ediff command for file-B.")
|
|
1448
|
|
1449 ;; Build keymaps
|
|
1450
|
|
1451 (defvar ediff-mode-map nil
|
|
1452 "Local keymap used in Ediff mode.")
|
7424
|
1453
|
|
1454 (if (and window-system ediff-want-default-menus (ediff-frame-has-menubar))
|
|
1455 (if (ediff-if-lucid)
|
|
1456 (progn ;; Lucid menu bars
|
|
1457 (defvar ediff-menu
|
|
1458 '(""
|
|
1459 ["Between Files ..." ediff-files t]
|
|
1460 ["Between Buffers ..." ediff-buffers t]
|
|
1461 ["With a Revision via VC ..." vc-ediff t]
|
|
1462 ["With a Revision via RCS ..." rcs-ediff t]))
|
|
1463 (defvar epatch-menu
|
|
1464 '(""
|
|
1465 ["To a File ..." ediff-patch-file t]
|
|
1466 ["To a Buffer ..." ediff-patch-buffer t]))
|
|
1467 (add-menu '("File") "Find Differences"
|
|
1468 ediff-menu
|
|
1469 "Delete Screen")
|
|
1470 (add-menu '("File") "Apply Patch"
|
|
1471 epatch-menu
|
|
1472 "Delete Screen")
|
|
1473 ;; Displays as a solid horizontal line
|
|
1474 (add-menu-item '("File") "---" nil nil "Delete Screen")
|
|
1475 )
|
|
1476 ;; FSF menu bars
|
|
1477 ;;;###autoload
|
|
1478 (defvar menu-bar-epatch-menu (make-sparse-keymap "menu-bar-epatch-map"))
|
|
1479 ;;;###autoload
|
|
1480 (fset 'menu-bar-epatch-menu (symbol-value 'menu-bar-epatch-menu))
|
|
1481 ;;;###autoload
|
|
1482 (defvar menu-bar-ediff-menu (make-sparse-keymap "menu-bar-ediff-map"))
|
|
1483 ;;;###autoload
|
|
1484 (fset 'menu-bar-ediff-menu (symbol-value 'menu-bar-ediff-menu))
|
|
1485
|
|
1486 ;;;###autoload
|
|
1487 (define-key menu-bar-ediff-menu [rcs-ediff]
|
|
1488 '("With a Revision via RCS ..." . rcs-ediff))
|
|
1489 ;;;###autoload
|
|
1490 (define-key menu-bar-ediff-menu [vc-ediff]
|
|
1491 '("With a Revision via VC ..." . vc-ediff))
|
|
1492 ;;;###autoload
|
|
1493 (define-key menu-bar-ediff-menu [ediff-buffers]
|
|
1494 '("Between Buffers ..." . ediff-buffers))
|
|
1495 ;;;###autoload
|
|
1496 (define-key menu-bar-ediff-menu [ediff-files]
|
|
1497 '("Between Files ..." . ediff-files))
|
|
1498
|
|
1499 ;;;###autoload
|
|
1500 (define-key menu-bar-epatch-menu [ediff-patch-buffer]
|
|
1501 '("To a Buffer ..." . ediff-patch-buffer))
|
|
1502 ;;;###autoload
|
|
1503 (define-key menu-bar-epatch-menu [ediff-patch-file]
|
|
1504 '("To a File ..." . ediff-patch-file))
|
|
1505
|
|
1506 (define-key menu-bar-file-menu [epatch]
|
|
1507 '("Apply Patch" . menu-bar-epatch-menu))
|
|
1508 (define-key menu-bar-file-menu [ediff]
|
|
1509 '("Find Differences" . menu-bar-ediff-menu))
|
|
1510 ))
|
7267
|
1511
|
|
1512
|
|
1513 (defun ediff-setup-keymap ()
|
|
1514 "Set up the keymap used in the control buffer of Ediff."
|
|
1515 (setq ediff-mode-map (make-sparse-keymap))
|
|
1516 (suppress-keymap ediff-mode-map)
|
|
1517
|
|
1518 (define-key ediff-mode-map "p" 'ediff-previous-difference)
|
|
1519 (define-key ediff-mode-map "\C-?" 'ediff-previous-difference)
|
7424
|
1520 (define-key ediff-mode-map "\C-h" (if ediff-no-help-in-control-buffer
|
7267
|
1521 'ediff-previous-difference nil))
|
|
1522 (define-key ediff-mode-map "n" 'ediff-next-difference)
|
|
1523 (define-key ediff-mode-map " " 'ediff-next-difference)
|
|
1524 (define-key ediff-mode-map "j" 'ediff-jump-to-difference)
|
|
1525 (define-key ediff-mode-map "g" nil)
|
|
1526 (define-key ediff-mode-map "ga" 'ediff-jump-to-difference-at-point)
|
|
1527 (define-key ediff-mode-map "gb" 'ediff-jump-to-difference-at-point)
|
|
1528 (define-key ediff-mode-map "q" 'ediff-quit)
|
|
1529 (define-key ediff-mode-map "z" 'ediff-suspend)
|
|
1530 (define-key ediff-mode-map "c" 'ediff-recenter)
|
|
1531 (define-key ediff-mode-map "s" 'ediff-toggle-split)
|
|
1532 (define-key ediff-mode-map "h" 'ediff-toggle-hilit)
|
7424
|
1533 (define-key ediff-mode-map "@" 'ediff-toggle-autorefine)
|
7267
|
1534 (define-key ediff-mode-map "v" 'ediff-scroll-up)
|
|
1535 (define-key ediff-mode-map "\C-v" 'ediff-scroll-up)
|
|
1536 (define-key ediff-mode-map "^" 'ediff-scroll-down)
|
|
1537 (define-key ediff-mode-map "\M-v" 'ediff-scroll-down)
|
|
1538 (define-key ediff-mode-map "V" 'ediff-scroll-down)
|
|
1539 (define-key ediff-mode-map "<" 'ediff-scroll-left)
|
|
1540 (define-key ediff-mode-map ">" 'ediff-scroll-right)
|
|
1541 (define-key ediff-mode-map "f" 'ediff-file-names)
|
|
1542 (define-key ediff-mode-map "l" 'ediff-line-numbers)
|
|
1543 (define-key ediff-mode-map "?" 'ediff-toggle-help)
|
7424
|
1544 (define-key ediff-mode-map "!" 'ediff-recompute-diffs)
|
|
1545 (define-key ediff-mode-map "*" 'ediff-make-fine-diffs)
|
7267
|
1546 (define-key ediff-mode-map "a" nil)
|
|
1547 (define-key ediff-mode-map "ab" 'ediff-diff-to-diff)
|
|
1548 (define-key ediff-mode-map "b" nil)
|
|
1549 (define-key ediff-mode-map "ba" 'ediff-diff-to-diff)
|
|
1550 (define-key ediff-mode-map "r" nil)
|
|
1551 (define-key ediff-mode-map "ra" 'ediff-restore-diff)
|
|
1552 (define-key ediff-mode-map "rb" 'ediff-restore-diff)
|
|
1553 (define-key ediff-mode-map "o" nil)
|
|
1554 (define-key ediff-mode-map "A" 'ediff-toggle-read-only)
|
|
1555 (define-key ediff-mode-map "B" 'ediff-toggle-read-only)
|
|
1556 (define-key ediff-mode-map "w" nil)
|
|
1557 (define-key ediff-mode-map "wa" 'ediff-save-buffer)
|
|
1558 (define-key ediff-mode-map "wb" 'ediff-save-buffer)
|
|
1559 (define-key ediff-mode-map "k" nil)
|
|
1560 (define-key ediff-mode-map "kkk" 'ediff-reload-keymap) ;; for debug
|
|
1561 ;; Allow ediff-mode-map to be referenced indirectly
|
|
1562 (fset 'ediff-mode-map ediff-mode-map))
|
|
1563
|
|
1564
|
|
1565 ;;; Setup functions
|
|
1566
|
|
1567 (defun ediff-find-file (file buffer &optional last-dir)
|
|
1568 "Visits FILE for ediff.
|
|
1569 BUFFER is a variable symbol that is supposed to
|
|
1570 get the buffer into which FILE is read. LAST-DIR is the directory variable
|
|
1571 symbol where FILE's dir name should be returned.
|
|
1572 Arguments: (file 'buffer &optional 'last-dir)"
|
|
1573 (if (not (file-readable-p file))
|
|
1574 (error "File `%s' does not exist or is not readable" file))
|
|
1575
|
|
1576 ;; Record the buffer
|
|
1577 (set buffer (find-file-noselect file))
|
|
1578 ;; Record the directory of the file
|
|
1579 (if last-dir
|
|
1580 (set last-dir (expand-file-name (file-name-directory file))))
|
|
1581
|
|
1582 ;; Make sure the entire file is seen, and it reflects what is on disk
|
|
1583 (emerge-eval-in-buffer
|
|
1584 (eval buffer)
|
|
1585 (widen)
|
|
1586 (let ((temp (file-local-copy file))
|
|
1587 startup-hooks)
|
|
1588 (if temp
|
|
1589 (setq file temp
|
|
1590 startup-hooks
|
|
1591 (cons (` (lambda () (delete-file (, file))))
|
|
1592 startup-hooks))
|
|
1593 ;; Verify that the file matches the buffer
|
|
1594 (emerge-verify-file-buffer)))))
|
|
1595
|
|
1596 (defun ediff-files-internal (file-A file-B &optional startup-hooks)
|
|
1597 (let (buffer-A buffer-B)
|
7424
|
1598 (message "Reading file %s ... " file-A)(sit-for .5)
|
7267
|
1599 (ediff-find-file file-A 'buffer-A 'ediff-last-dir-A)
|
7424
|
1600 (message "Reading file %s ... " file-B)(sit-for .5)
|
7267
|
1601 (ediff-find-file file-B 'buffer-B 'ediff-last-dir-B)
|
|
1602 (ediff-setup buffer-A file-A buffer-B file-B startup-hooks)))
|
|
1603
|
|
1604 (defun ediff-get-patch-buffer (dir)
|
|
1605 "Obtain patch buffer. If patch is already in a buffer---use it.
|
|
1606 Else, read patch file into a new buffer."
|
|
1607 (if (y-or-n-p "Is the patch file already in a buffer? ")
|
|
1608 (setq ediff-patch-buf
|
|
1609 (get-buffer (read-buffer "Patch buffer name: " nil t))) ;must match
|
|
1610 (setq ediff-patch-buf
|
|
1611 (find-file-noselect (read-file-name "Patch file name: "
|
|
1612 dir))))
|
|
1613 (emerge-eval-in-buffer
|
|
1614 ediff-patch-buf
|
|
1615 (toggle-read-only 1))
|
|
1616 (setq ediff-patch-diagnostics
|
|
1617 (get-buffer-create "*ediff patch diagnostics*"))
|
|
1618 (emerge-eval-in-buffer
|
|
1619 ediff-patch-diagnostics
|
|
1620 (insert-buffer ediff-patch-buf))
|
|
1621 )
|
|
1622
|
|
1623 ;; Start up Ediff on two files
|
|
1624 (defun ediff-setup (buffer-A file-A buffer-B file-B startup-hooks)
|
|
1625 (setq file-A (expand-file-name file-A))
|
|
1626 (setq file-B (expand-file-name file-B))
|
|
1627 (let* ((control-buffer-name (emerge-unique-buffer-name "*ediff-control" "*"))
|
|
1628 (control-buffer (emerge-eval-in-buffer
|
|
1629 buffer-A
|
|
1630 (get-buffer-create control-buffer-name))))
|
|
1631 (emerge-eval-in-buffer
|
|
1632 control-buffer
|
|
1633 (ediff-mode) ;; in control buffer only
|
|
1634 (setq buffer-read-only nil)
|
|
1635 (setq ediff-A-buffer buffer-A)
|
|
1636 (setq ediff-B-buffer buffer-B)
|
|
1637 (setq ediff-control-buffer control-buffer)
|
7424
|
1638 ; (setq ediff-control-buffer-suffix
|
|
1639 ; (if (string-match "<[0-9]*>" control-buffer-name)
|
|
1640 ; (substring control-buffer-name
|
|
1641 ; (match-beginning 0) (match-end 0))
|
|
1642 ; "<1>"))
|
|
1643 (setq ediff-error-buffer (get-buffer-create (emerge-unique-buffer-name
|
|
1644 "*ediff-errors" "*")))
|
7267
|
1645 (ediff-remember-buffer-characteristics t) ;; remember at setup
|
|
1646
|
|
1647 (ediff-set-keys)
|
7424
|
1648 (setq ediff-difference-vector (ediff-setup-diff-regions file-A file-B))
|
7267
|
1649 (setq ediff-number-of-differences (length ediff-difference-vector))
|
|
1650 (setq ediff-current-difference -1)
|
|
1651 (ediff-make-current-diff-overlay 'A)
|
|
1652 (ediff-make-current-diff-overlay 'B)
|
|
1653 (if window-system
|
|
1654 (ediff-init-var-faces))
|
|
1655 (run-hooks 'ediff-before-setup-windows-hooks)
|
|
1656 (ediff-setup-windows buffer-A buffer-B control-buffer t)
|
|
1657
|
|
1658 ;; all these must be inside emerge-eval-in-buffer control-buffer,
|
|
1659 ;; since these vars are local to control-buffer
|
|
1660 ;; These won't run if there are errors in diff
|
|
1661 (emerge-eval-in-buffer
|
|
1662 ediff-A-buffer
|
|
1663 (run-hooks 'ediff-prepare-buffer-hooks)
|
|
1664 (add-hook 'local-write-file-hooks 'ediff-block-write-file)
|
|
1665 (setq before-change-function 'ediff-before-change-guard)
|
|
1666 ;; add control-buffer to the list of sessions
|
|
1667 (or (memq control-buffer ediff-this-buffer-control-sessions)
|
|
1668 (setq ediff-this-buffer-control-sessions
|
|
1669 (cons control-buffer ediff-this-buffer-control-sessions)))
|
|
1670 (setq mode-line-buffer-identification '("A: %b")))
|
|
1671 (emerge-eval-in-buffer
|
|
1672 ediff-B-buffer
|
|
1673 (run-hooks 'ediff-prepare-buffer-hooks)
|
|
1674 (add-hook 'local-write-file-hooks 'ediff-block-write-file)
|
|
1675 (setq before-change-function 'ediff-before-change-guard)
|
|
1676 ;; add control-buffer to the list of sessions
|
|
1677 (or (memq control-buffer ediff-this-buffer-control-sessions)
|
|
1678 (setq ediff-this-buffer-control-sessions
|
|
1679 (cons control-buffer ediff-this-buffer-control-sessions)))
|
|
1680 (setq mode-line-buffer-identification '("B: %b")))
|
|
1681
|
|
1682 (emerge-eval-in-buffer control-buffer
|
|
1683 (run-hooks 'startup-hooks 'ediff-startup-hooks)
|
|
1684 (setq buffer-read-only t)))))
|
|
1685
|
7424
|
1686 ;; Generate the difference vector and overlays for the two files
|
|
1687 ;; With optional arg `refine', create refining difference regions
|
|
1688 (defun ediff-setup-diff-regions (file-A file-B
|
|
1689 &optional use-old refine-region
|
|
1690 diff-program diff-options
|
|
1691 diff-ok-lines-regexp)
|
|
1692
|
|
1693 (setq diff-program (or diff-program ediff-diff-program)
|
|
1694 diff-options (or diff-options ediff-diff-options)
|
|
1695 diff-ok-lines-regexp
|
|
1696 (or diff-ok-lines-regexp ediff-diff-ok-lines-regexp))
|
|
1697
|
|
1698 (or use-old (setq ediff-diff-buffer
|
|
1699 (get-buffer-create
|
|
1700 (emerge-unique-buffer-name "*ediff-diff" "*"))))
|
7267
|
1701 (emerge-eval-in-buffer
|
|
1702 ediff-diff-buffer
|
|
1703 (erase-buffer)
|
|
1704 ;; shell-command tends to display old shell command buffers even when it
|
|
1705 ;; puts output in another buffer---probably an Emacs bug.
|
|
1706 (ediff-kill-buffer-carefully "*Shell Command Output*")
|
|
1707 (let ((shell-file-name ediff-shell))
|
7424
|
1708 (if refine-region
|
|
1709 (message "Refining difference region %d ..." (1+ refine-region))
|
|
1710 (message "Computing differences ...")(sit-for .5))
|
7267
|
1711 (shell-command
|
|
1712 (format "%s %s %s %s"
|
7424
|
1713 diff-program diff-options
|
|
1714 (ediff-protect-metachars file-A)
|
|
1715 (ediff-protect-metachars file-B))
|
7267
|
1716 t)
|
|
1717 ))
|
7424
|
1718 (ediff-prepare-error-list diff-ok-lines-regexp)
|
|
1719 (if refine-region
|
|
1720 (message "Refining difference region %d ... Done." (1+ refine-region))
|
|
1721 (message "Computing differences ... Done.")(sit-for .5))
|
|
1722 (if refine-region
|
|
1723 (ediff-convert-diffs-to-overlays-refine
|
|
1724 ediff-A-buffer ediff-B-buffer
|
|
1725 (ediff-extract-diffs ediff-diff-buffer)
|
|
1726 refine-region)
|
|
1727 (ediff-convert-diffs-to-overlays
|
|
1728 ediff-A-buffer ediff-B-buffer
|
|
1729 (ediff-extract-diffs ediff-diff-buffer ediff-A-buffer ediff-B-buffer)))
|
|
1730 )
|
|
1731
|
7267
|
1732
|
|
1733 (defun ediff-prepare-error-list (ok-regexp)
|
|
1734 (let ((diff-buff ediff-diff-buffer))
|
|
1735 (emerge-eval-in-buffer
|
7424
|
1736 ediff-error-buffer
|
7267
|
1737 (erase-buffer)
|
|
1738 (insert-buffer diff-buff)
|
|
1739 (delete-matching-lines ok-regexp))))
|
|
1740
|
|
1741 ;;; Function to start Ediff by patching a file
|
|
1742
|
|
1743 ;;;###autoload
|
|
1744 (defun ediff-patch-file (file-to-patch &optional startup-hooks)
|
7424
|
1745 "Run Ediff by patching FILE-TP-PATCH."
|
7267
|
1746 (interactive "fFile to patch: ")
|
|
1747
|
|
1748 (ediff-get-patch-buffer (file-name-directory file-to-patch))
|
|
1749 (let ((buf (get-file-buffer file-to-patch)))
|
|
1750 (if buf
|
|
1751 (progn
|
|
1752 (emerge-eval-in-buffer
|
|
1753 buf
|
|
1754 (if (buffer-modified-p buf)
|
|
1755 (if (y-or-n-p
|
|
1756 (format
|
|
1757 "File '%s' is already in buffer %s. Save before killing? "
|
|
1758 file-to-patch (buffer-name buf)))
|
|
1759 (save-buffer buf)))
|
|
1760 (set-buffer-modified-p nil))
|
|
1761 (ediff-kill-buffer-carefully buf))))
|
|
1762 (emerge-eval-in-buffer
|
|
1763 ediff-patch-diagnostics
|
|
1764 (let ((shell-file-name ediff-shell))
|
7424
|
1765 (message "Applying patch ... ")(sit-for .5)
|
|
1766 ;; always pass patch the -f option, so it won't ask any questions
|
7267
|
1767 (shell-command-on-region
|
|
1768 (point-min) (point-max)
|
|
1769 (format "%s %s %s"
|
7424
|
1770 ediff-patch-program (concat "-f " ediff-patch-options)
|
7267
|
1771 (expand-file-name file-to-patch))
|
|
1772 t)
|
7424
|
1773 (message "Applying patch ... Done.")(sit-for .5)
|
7267
|
1774 ))
|
|
1775 (switch-to-buffer ediff-patch-diagnostics)
|
|
1776 (sit-for 0) ;; synchronize
|
|
1777
|
|
1778 (setq startup-hooks (cons 'ediff-toggle-read-only-A startup-hooks))
|
7424
|
1779 (if (file-exists-p (format "%s.orig" file-to-patch))
|
|
1780 (ediff-files
|
|
1781 (format "%s.orig" file-to-patch) file-to-patch startup-hooks)
|
|
1782 (error "Patch failed or didn't modify the original file."))
|
7267
|
1783
|
|
1784 (bury-buffer ediff-patch-diagnostics)
|
|
1785 (message "Patch diagnostics available in buffer %s."
|
|
1786 (buffer-name ediff-patch-diagnostics)))
|
|
1787
|
|
1788 (defalias 'epatch 'ediff-patch-file)
|
7424
|
1789 (defalias 'epatch-buffer 'ediff-patch-buffer)
|
7267
|
1790
|
|
1791 ;;; Function to start Ediff on files
|
|
1792
|
|
1793 ;;;###autoload
|
|
1794 (defun ediff-files (file-A file-B &optional startup-hooks)
|
|
1795 "Run Ediff on a pair files, FILE-A and FILE-B."
|
|
1796 (interactive
|
|
1797 (let (f)
|
|
1798 (list (setq f (ediff-read-file-name "File A to compare"
|
|
1799 (if ediff-use-last-dir
|
|
1800 ediff-last-dir-A
|
|
1801 default-directory)
|
|
1802 nil nil))
|
|
1803 (ediff-read-file-name "File B to compare"
|
|
1804 (if ediff-use-last-dir
|
|
1805 ediff-last-dir-B nil)
|
|
1806 f f)
|
|
1807 )))
|
7424
|
1808 (ediff-files-internal file-A
|
|
1809 (if (file-directory-p file-B)
|
|
1810 (expand-file-name
|
|
1811 (file-name-nondirectory file-A) file-B)
|
|
1812 file-B)
|
|
1813 startup-hooks))
|
7267
|
1814
|
|
1815
|
|
1816 (defalias 'ediff 'ediff-files)
|
|
1817
|
|
1818
|
|
1819 ;;; Function to start Ediff on buffers
|
|
1820
|
|
1821 ;;;###autoload
|
|
1822 (defun ediff-buffers (buffer-A buffer-B &optional startup-hooks)
|
|
1823 "Run Ediff on a pair of buffers, BUFFER-A and BUFFER-B."
|
|
1824 (interactive "bBuffer A to compare: \nbBuffer B to compare: ")
|
7424
|
1825 (let (file-A file-B)
|
7267
|
1826 (emerge-eval-in-buffer
|
|
1827 buffer-A
|
7424
|
1828 (setq file-A (ediff-make-temp-file)))
|
7267
|
1829 (emerge-eval-in-buffer
|
|
1830 buffer-B
|
7424
|
1831 (setq file-B (ediff-make-temp-file)))
|
|
1832 (ediff-setup (get-buffer buffer-A) file-A
|
|
1833 (get-buffer buffer-B) file-B
|
7267
|
1834 (cons (` (lambda ()
|
7424
|
1835 (delete-file (, file-A))
|
|
1836 (delete-file (, file-B))))
|
7267
|
1837 startup-hooks)
|
|
1838 )))
|
|
1839
|
7424
|
1840 ;;;;###autoload
|
7267
|
1841 (defun ediff-patch-buffer (buffer-name &optional startup-hooks)
|
|
1842 "Run Ediff by patching BUFFER-NAME."
|
|
1843 (interactive "bBuffer to patch: ")
|
|
1844
|
|
1845 (let* ((file-buffer (get-buffer buffer-name))
|
|
1846 (file-name (if file-buffer (buffer-file-name file-buffer))))
|
|
1847 (if (not file-name)
|
|
1848 (error "Buffer %s doesn't exist or doesn't visit any file. Why patch?"
|
|
1849 file-name))
|
|
1850
|
|
1851 (ediff-patch-file file-name startup-hooks)))
|
|
1852
|
|
1853
|
|
1854 ;;; Versions Control functions
|
|
1855
|
|
1856 ;;;###autoload
|
|
1857 (defun vc-ediff (rev)
|
7424
|
1858 ;; Note: this function will work only with Emacs 19.22 and higher.
|
7267
|
1859 "Run ediff on version REV of the current buffer in another window.
|
|
1860 If the current buffer is named `F', the version is named `F.~REV~'.
|
7391
|
1861 If `F.~REV~' already exists, it is used instead of being re-created."
|
7267
|
1862 (interactive "sVersion to ediff with (default is the latest version): ")
|
|
1863 (or (featurep 'vc)
|
|
1864 (if (locate-library "vc") ;; if vc.el is available
|
|
1865 (progn
|
|
1866 (require 'vc-hooks)
|
|
1867 (define-key vc-prefix-map "=" 'vc-ediff))
|
|
1868 (error "The VC package is apparently not installed.")))
|
|
1869 (let ((newvers (current-buffer))
|
|
1870 (oldvers (vc-version-other-window rev)))
|
7424
|
1871 ;; current-buffer is supposed to contain the old version in another
|
|
1872 ;; window
|
|
1873 (ediff-buffers newvers (current-buffer))
|
7267
|
1874 ))
|
|
1875
|
|
1876 (defun rcs-ediff-view-revision (&optional rev)
|
7424
|
1877 "View previous RCS revision of current file.
|
7267
|
1878 With prefix argument, prompts for a revision name."
|
|
1879 (interactive (list (if current-prefix-arg
|
|
1880 (read-string "Revision: "))))
|
|
1881 (let* ((filename (buffer-file-name (current-buffer)))
|
|
1882 (switches (append '("-p")
|
|
1883 (if rev (list (concat "-r" rev)) nil)))
|
|
1884 (buff (concat (file-name-nondirectory filename) ".~" rev "~")))
|
|
1885 (message "Working...")
|
|
1886 (setq filename (expand-file-name filename))
|
|
1887 (with-output-to-temp-buffer
|
|
1888 buff
|
7424
|
1889 (let ((output-buffer (ediff-rcs-get-output-buffer filename buff)))
|
7267
|
1890 (delete-windows-on output-buffer)
|
|
1891 (save-excursion
|
|
1892 (set-buffer output-buffer)
|
|
1893 (apply 'call-process "co" nil t nil
|
|
1894 ;; -q: quiet (no diagnostics)
|
|
1895 (append switches rcs-default-co-switches
|
|
1896 (list "-q" filename)))))
|
|
1897 (message "")
|
|
1898 buff)))
|
7424
|
1899
|
|
1900 (defun ediff-rcs-get-output-buffer (file name)
|
|
1901 ;; Get a buffer for RCS output for FILE, make it writable and clean it up.
|
|
1902 ;; Optional NAME is name to use instead of `*RCS-output*'.
|
|
1903 ;; This is a mofified version from rcs.el v1.1. I use it here to make
|
|
1904 ;; Ediff immune to changes in rcs.el
|
|
1905 (let* ((default-major-mode 'fundamental-mode);; no frills!
|
|
1906 (buf (get-buffer-create name)))
|
|
1907 (save-excursion
|
|
1908 (set-buffer buf)
|
|
1909 (setq buffer-read-only nil
|
|
1910 default-directory (file-name-directory (expand-file-name file)))
|
|
1911 (erase-buffer))
|
|
1912 buf))
|
7267
|
1913
|
|
1914 ;;;###autoload
|
|
1915 (defun rcs-ediff (&optional rev)
|
7424
|
1916 "Run Ediff on the current buffer, comparing it with previous RCS revision.
|
7267
|
1917 With prefix argument, prompts for revision name."
|
|
1918 (interactive (list (if current-prefix-arg
|
|
1919 (read-string "Revision: "))))
|
|
1920 (or (featurep 'rcs)
|
|
1921 (if (locate-library "rcs")
|
|
1922 (progn
|
|
1923 (require 'rcs)
|
|
1924 (global-set-key "\C-cD" 'rcs-ediff))
|
|
1925 (error "The RCS package is apparently not installed.")))
|
|
1926 (let ((newvers (current-buffer))
|
|
1927 (oldvers (rcs-ediff-view-revision rev)))
|
|
1928 (ediff-buffers newvers oldvers)
|
|
1929 ))
|
|
1930
|
|
1931
|
|
1932 ;;; Functions to start Ediff via remote request
|
|
1933
|
|
1934 ;;;###autoload
|
|
1935 (defun ediff-files-remote (file-a file-b)
|
|
1936 "Run Ediff on remote files, FILE-A and FILE-B."
|
|
1937 (ediff-files-internal file-a file-b nil)
|
|
1938 (throw 'client-wait nil))
|
|
1939
|
|
1940
|
|
1941 (defun ediff-remote-exit (exit-func)
|
|
1942 "Exit remote Ediff session."
|
|
1943 (ediff-really-quit)
|
|
1944 (funcall exit-func))
|
|
1945
|
|
1946
|
|
1947
|
|
1948 ;; Select the lowest window on the frame.
|
|
1949 (defun ediff-select-lowest-window ()
|
|
1950 (let* ((lowest-window (selected-window))
|
|
1951 (bottom-edge (car (cdr (cdr (cdr (window-edges))))))
|
|
1952 (last-window (previous-window))
|
|
1953 (window-search t))
|
|
1954 (while window-search
|
|
1955 (let* ((this-window (next-window))
|
|
1956 (next-bottom-edge (car (cdr (cdr (cdr
|
|
1957 (window-edges this-window)))))))
|
|
1958 (if (< bottom-edge next-bottom-edge)
|
|
1959 (progn
|
|
1960 (setq bottom-edge next-bottom-edge)
|
|
1961 (setq lowest-window this-window)))
|
|
1962
|
|
1963 (select-window this-window)
|
|
1964 (if (eq last-window this-window)
|
|
1965 (progn
|
|
1966 (select-window lowest-window)
|
|
1967 (setq window-search nil)))))))
|
|
1968
|
|
1969 ;;; Common setup routines
|
|
1970
|
|
1971 ;; Set up the window configuration. If POS is given, set the points to
|
|
1972 ;; the beginnings of the buffers.
|
|
1973 (defun ediff-setup-windows (buffer-A buffer-B control-buffer &optional pos)
|
|
1974 ;; Make sure we are not in the minibuffer window when we try to delete
|
|
1975 ;; all other windows.
|
|
1976 (if (eq (selected-window) (minibuffer-window))
|
|
1977 (other-window 1))
|
7424
|
1978 (or (ediff-leave-window-config control-buffer)
|
|
1979 (progn
|
|
1980 (delete-other-windows)
|
|
1981 (switch-to-buffer control-buffer)
|
|
1982 (ediff-refresh-mode-line)
|
7267
|
1983
|
7424
|
1984 (ediff-arrange-buffer buffer-A buffer-B (current-buffer) pos)
|
|
1985 (ediff-arrange-buffer buffer-B buffer-A (current-buffer) pos)
|
|
1986 ;; ediff-arrange-buffer always leaves in ctl buffer
|
|
1987 ;; setup ctl wind if it is not set.
|
|
1988 (ediff-setup-control-window)
|
7267
|
1989
|
7424
|
1990 ;; If diff reports errors, show them then quit.
|
|
1991 (if (/= 0 (emerge-eval-in-buffer ediff-error-buffer (buffer-size)))
|
|
1992 (let ((diff-output-buf ediff-diff-buffer))
|
|
1993 (switch-to-buffer ediff-error-buffer)
|
|
1994 (ediff-kill-buffer-carefully control-buffer)
|
|
1995 (error "Errors found in diff output. Diff output buffer is %s"
|
|
1996 diff-output-buf))))))
|
7267
|
1997
|
|
1998
|
|
1999 ;; Arranges goal-buf on the screen.
|
|
2000 (defun ediff-arrange-buffer (goal-buf other-buf ctl-buf &optional pos)
|
|
2001 (let* ((ctl-wind (get-buffer-window ctl-buf t))
|
|
2002 (goal-wind (get-buffer-window goal-buf t))
|
|
2003 (other-wind (get-buffer-window other-buf t))
|
|
2004 (ctl-frame (ediff-window-frame ctl-wind))
|
|
2005 (goal-frame (if goal-wind (ediff-window-frame goal-wind)))
|
|
2006 (other-frame (if other-wind (ediff-window-frame other-wind)))
|
|
2007 (ctl-frame-shared (or (eq ctl-frame goal-frame)
|
|
2008 (eq ctl-frame other-frame))))
|
|
2009
|
|
2010 (cond ((and goal-frame (not (eq goal-wind other-wind)))
|
|
2011 ;; goal buffer is visible and we are not comparing file
|
|
2012 ;; against itself (by mistake).
|
|
2013 ;; Note: goal-frame != ctl-frame, as we deleted other
|
|
2014 ;; windows on ctl-frame.
|
|
2015 (ediff-select-frame goal-frame)
|
|
2016 (select-window goal-wind)
|
|
2017 (delete-other-windows))
|
|
2018
|
|
2019 ;; goal-buf invisible, ctl-frame has only ctl-buf
|
|
2020 ;; then put goal-buf on ctl-frame
|
|
2021 ((null ctl-frame-shared)
|
|
2022 (ediff-select-frame ctl-frame)
|
|
2023 (split-window-vertically)
|
|
2024 (ediff-select-lowest-window)
|
|
2025 (setq ctl-wind (selected-window))
|
|
2026 (switch-to-buffer ctl-buf)
|
|
2027 (ediff-setup-control-window)
|
|
2028 (other-window 1)
|
|
2029 (switch-to-buffer goal-buf)) ; goal-buf set
|
|
2030 ;; goal-buf invisible, ctl-frame has ctl-buf and other-buf
|
|
2031 ;; So, put everything in one frame
|
|
2032 (other-frame ;; share with the other buf
|
|
2033 (ediff-select-frame ctl-frame)
|
|
2034 (select-window other-wind)
|
|
2035 (funcall ediff-split-window-function)
|
|
2036 (other-window 1)
|
|
2037 (switch-to-buffer goal-buf))
|
|
2038 (t ;; debug
|
|
2039 (error "Funny window combination (Ediff bug?)")))
|
|
2040
|
|
2041 (if pos
|
|
2042 (goto-char (point-min)))
|
|
2043
|
|
2044 (ediff-select-frame ctl-frame)
|
|
2045 (select-window ctl-wind)
|
|
2046 (switch-to-buffer ctl-buf)))
|
|
2047
|
|
2048 ;; This function assumes that we are in the window where control buffer is
|
|
2049 ;; to reside.
|
|
2050 (defun ediff-setup-control-window ()
|
|
2051 "Set up window for control buffer."
|
|
2052 (erase-buffer)
|
|
2053 (insert ediff-help-message)
|
|
2054 (shrink-window-if-larger-than-buffer)
|
|
2055 (setq ediff-control-window (selected-window))
|
7424
|
2056 (setq ediff-window-config-saved
|
|
2057 (format "%S%S%S%S"
|
|
2058 ediff-control-window
|
|
2059 (get-buffer-window ediff-A-buffer t)
|
|
2060 (get-buffer-window ediff-B-buffer t)
|
|
2061 ediff-split-window-function))
|
7267
|
2062 (goto-char (point-min))
|
7424
|
2063 (skip-chars-forward ediff-whitespace))
|
|
2064
|
|
2065 (defun ediff-leave-window-config (control-buf)
|
|
2066 (and (eq control-buf (current-buffer))
|
|
2067 (/= (buffer-size) 0)
|
|
2068 (emerge-eval-in-buffer
|
|
2069 control-buf
|
|
2070 (string= ediff-window-config-saved
|
|
2071 (format "%S%S%S%S"
|
|
2072 (get-buffer-window ediff-control-buffer t)
|
|
2073 (get-buffer-window ediff-A-buffer t)
|
|
2074 (get-buffer-window ediff-B-buffer t)
|
|
2075 ediff-split-window-function)))))
|
7267
|
2076
|
|
2077
|
|
2078 ;; Set up the keymap in the control buffer
|
|
2079 (defun ediff-set-keys ()
|
|
2080 "Set up Ediff keymap, if necessary."
|
|
2081 (if (null ediff-mode-map)
|
|
2082 (ediff-setup-keymap))
|
|
2083 (use-local-map ediff-mode-map))
|
|
2084
|
|
2085 ;; Reload Ediff keymap. For debugging only.
|
|
2086 (defun ediff-reload-keymap ()
|
|
2087 (interactive)
|
|
2088 (setq ediff-mode-map nil)
|
|
2089 (ediff-set-keys))
|
|
2090
|
|
2091 (defun ediff-before-change-guard (start end)
|
7419
|
2092 "If buffer is highlighted with ASCII flags, remove highlighting.
|
|
2093 Arguments, START and END are not used, but are provided
|
|
2094 because this is required by `before-change-function'."
|
7424
|
2095 (let (rehighlight-key)
|
7267
|
2096 (save-window-excursion
|
|
2097 (mapcar
|
|
2098 (function
|
|
2099 (lambda (buf)
|
|
2100 (if (ediff-buffer-live-p buf)
|
|
2101 (emerge-eval-in-buffer
|
|
2102 buf
|
|
2103 (if (eq ediff-highlighting-style 'ascii)
|
|
2104 (progn
|
|
2105 (ediff-unselect-and-select-difference
|
|
2106 ediff-current-difference
|
|
2107 'unselect-only 'no-recenter)
|
7424
|
2108 (setq rehighlight-key
|
|
2109 (substitute-command-keys "\\[ediff-recenter]"))
|
7267
|
2110 ))))))
|
|
2111 ediff-this-buffer-control-sessions)
|
7424
|
2112 (if rehighlight-key
|
|
2113 (error
|
|
2114 "ASCII flags removed. You can edit now. Hit %S to rehighlight."
|
|
2115 rehighlight-key))
|
7267
|
2116 )))
|
7424
|
2117
|
|
2118 (defun ediff-recompute-diffs ()
|
|
2119 "Recompute difference regions in buffers A and B."
|
|
2120 (interactive)
|
|
2121 (let ((curr-diff ediff-current-difference)
|
|
2122 (point-A (emerge-eval-in-buffer ediff-A-buffer (point)))
|
|
2123 (point-B (emerge-eval-in-buffer ediff-B-buffer (point)))
|
|
2124 file-A file-B)
|
|
2125 (ediff-unselect-and-select-difference -1)
|
|
2126 (emerge-eval-in-buffer
|
|
2127 ediff-A-buffer
|
|
2128 (setq file-A (ediff-make-temp-file)))
|
|
2129 (emerge-eval-in-buffer
|
|
2130 ediff-B-buffer
|
|
2131 (setq file-B (ediff-make-temp-file)))
|
|
2132 (ediff-clear-diff-vector ediff-difference-vector 'fine-diffs-also)
|
|
2133 (setq ediff-killed-diffs-alist nil) ; saved kills will no longer be valid
|
|
2134 ; after recompute
|
|
2135 (setq ediff-difference-vector
|
|
2136 (ediff-setup-diff-regions file-A file-B 'use-old))
|
|
2137 (setq ediff-number-of-differences (length ediff-difference-vector))
|
|
2138 (delete-file file-A)
|
|
2139 (delete-file file-B)
|
|
2140 (emerge-eval-in-buffer ediff-A-buffer (goto-char point-A))
|
|
2141 (ediff-jump-to-difference (ediff-diff-at-point 'A))
|
|
2142 (beep 1)
|
|
2143 (if (y-or-n-p
|
|
2144 "Ediff is around last posn in buff A. Stay (or goto last posn in B)? ")
|
|
2145 ()
|
|
2146 (emerge-eval-in-buffer ediff-B-buffer (goto-char point-B))
|
|
2147 (ediff-jump-to-difference (ediff-diff-at-point 'B)))
|
|
2148 (message "")
|
|
2149 ))
|
7267
|
2150
|
|
2151 (defun ediff-remember-buffer-characteristics (&optional arg)
|
|
2152 "Record certain properties of the buffers being compared.
|
7419
|
2153 Must be called in the control buffer. Saves `read-only', `modified',
|
|
2154 and `auto-save' properties in buffer local variables. Turns off
|
|
2155 `auto-save-mode'. These properties are restored via a call to
|
|
2156 `ediff-restore-buffer-characteristics'."
|
7267
|
2157
|
|
2158 ;; remember and alter buffer characteristics
|
|
2159 (set (if arg 'ediff-A-buffer-values-setup 'ediff-A-buffer-values)
|
|
2160 (emerge-eval-in-buffer
|
|
2161 ediff-A-buffer
|
|
2162 (prog1
|
|
2163 (emerge-save-variables ediff-saved-variables)
|
|
2164 (emerge-restore-variables ediff-saved-variables
|
|
2165 ediff-working-values))))
|
|
2166 (set (if arg 'ediff-B-buffer-values-setup 'ediff-B-buffer-values)
|
|
2167 (emerge-eval-in-buffer
|
|
2168 ediff-B-buffer
|
|
2169 (prog1
|
|
2170 (emerge-save-variables ediff-saved-variables)
|
|
2171 (emerge-restore-variables ediff-saved-variables
|
|
2172 ediff-working-values)))))
|
|
2173
|
|
2174 (defun ediff-restore-buffer-characteristics (&optional arg)
|
7419
|
2175 "Restores properties saved by `ediff-remember-buffer-characteristics'."
|
7267
|
2176 (let ((A-values (if arg ediff-A-buffer-values-setup ediff-A-buffer-values))
|
|
2177 (B-values (if arg ediff-B-buffer-values-setup ediff-B-buffer-values)))
|
|
2178 (emerge-eval-in-buffer ediff-A-buffer
|
|
2179 (emerge-restore-variables ediff-saved-variables
|
|
2180 A-values))
|
|
2181 (emerge-eval-in-buffer ediff-B-buffer
|
|
2182 (emerge-restore-variables ediff-saved-variables
|
|
2183 B-values))))
|
|
2184
|
|
2185
|
7424
|
2186 ;; if optional A-buffer and B-buffer are given, then construct a vector of
|
|
2187 ;; diff using point values. Otherwise, use line offsets.
|
|
2188 (defun ediff-extract-diffs (diff-buffer &optional A-buffer B-buffer)
|
7267
|
2189 (let (diff-list
|
|
2190 (a-prev 1) ;; this is needed to set the first diff line correctly
|
|
2191 (b-prev 1))
|
7424
|
2192
|
|
2193 (if (and A-buffer B-buffer)
|
|
2194 (progn ;; reset point in buffers A and B
|
|
2195 (emerge-eval-in-buffer
|
|
2196 A-buffer
|
|
2197 (goto-char (point-min)))
|
|
2198 (emerge-eval-in-buffer
|
|
2199 B-buffer
|
|
2200 (goto-char (point-min)))))
|
|
2201
|
7267
|
2202 (emerge-eval-in-buffer
|
|
2203 diff-buffer
|
|
2204 (goto-char (point-min))
|
|
2205 (while (re-search-forward ediff-match-diff-line nil t)
|
|
2206 (let* ((a-begin (string-to-int (buffer-substring (match-beginning 1)
|
|
2207 (match-end 1))))
|
|
2208 (a-end (let ((b (match-beginning 3))
|
|
2209 (e (match-end 3)))
|
|
2210 (if b
|
|
2211 (string-to-int (buffer-substring b e))
|
|
2212 a-begin)))
|
|
2213 (diff-type (buffer-substring (match-beginning 4) (match-end 4)))
|
|
2214 (b-begin (string-to-int (buffer-substring (match-beginning 5)
|
|
2215 (match-end 5))))
|
|
2216 (b-end (let ((b (match-beginning 7))
|
|
2217 (e (match-end 7)))
|
|
2218 (if b
|
|
2219 (string-to-int (buffer-substring b e))
|
|
2220 b-begin)))
|
|
2221 a-begin-pt a-end-pt b-begin-pt b-end-pt)
|
|
2222 ;; fix the beginning and end numbers, because diff is somewhat
|
|
2223 ;; strange about how it numbers lines
|
|
2224 (if (string-equal diff-type "a")
|
|
2225 (setq b-end (1+ b-end)
|
|
2226 a-begin (1+ a-begin)
|
|
2227 a-end a-begin)
|
|
2228 (if (string-equal diff-type "d")
|
|
2229 (setq a-end (1+ a-end)
|
|
2230 b-begin (1+ b-begin)
|
|
2231 b-end b-begin)
|
|
2232 ;; (string-equal diff-type "c")
|
|
2233 (setq a-end (1+ a-end)
|
|
2234 b-end (1+ b-end))))
|
7424
|
2235 (if (and A-buffer B-buffer)
|
|
2236 (progn ;; computing main diff vector
|
|
2237 ;; convert to relative line numbers
|
|
2238 (emerge-eval-in-buffer
|
|
2239 A-buffer
|
|
2240 (forward-line (- a-begin a-prev))
|
|
2241 (setq a-begin-pt (point))
|
|
2242 (forward-line (- a-end a-begin))
|
|
2243 (setq a-end-pt (point)
|
|
2244 a-prev a-end))
|
|
2245 (emerge-eval-in-buffer
|
|
2246 B-buffer
|
|
2247 (forward-line (- b-begin b-prev))
|
|
2248 (setq b-begin-pt (point))
|
|
2249 (forward-line (- b-end b-begin))
|
|
2250 (setq b-end-pt (point)
|
|
2251 b-prev b-end))
|
|
2252 (setq diff-list
|
|
2253 (nconc diff-list (list (vector a-begin-pt a-end-pt
|
|
2254 b-begin-pt b-end-pt)))))
|
|
2255 ;; computing refinement vector
|
|
2256 (setq diff-list
|
|
2257 (nconc diff-list (list (vector (- a-begin a-prev)
|
|
2258 (- a-end a-begin)
|
|
2259 (- b-begin b-prev)
|
|
2260 (- b-end b-begin))))
|
|
2261 a-prev a-end
|
|
2262 b-prev b-end))
|
|
2263
|
|
2264 ))) ;; end emerge-eval-in-buffer
|
7267
|
2265 diff-list
|
|
2266 ))
|
|
2267
|
|
2268 (defun ediff-convert-diffs-to-overlays (A-buffer B-buffer diff-list)
|
|
2269 (let* ((current-diff -1)
|
|
2270 (total-diffs (length diff-list))
|
7424
|
2271 ; (control-buffer-suffix ediff-control-buffer-suffix)
|
7267
|
2272 diff-overlay-list list-element
|
|
2273 a-begin a-end b-begin b-end
|
|
2274 a-overlay b-overlay)
|
|
2275
|
|
2276 (while diff-list
|
|
2277 (setq current-diff (1+ current-diff)
|
|
2278 list-element (car diff-list)
|
|
2279 a-begin (aref list-element 0)
|
|
2280 a-end (aref list-element 1)
|
|
2281 b-begin (aref list-element 2)
|
|
2282 b-end (aref list-element 3))
|
|
2283
|
|
2284 ;; place overlays at the appropriate places in the buffers
|
|
2285 (setq a-overlay (ediff-make-overlay a-begin a-end A-buffer))
|
7424
|
2286 ;; priorities of overlays should be equal in all ediff-control
|
|
2287 ;; buffers. otherwise it won't work due to Emacs
|
|
2288 ;; bug---insert-in-front-hooks will be called
|
7267
|
2289 ;; only on behalf of the buffer with higher priority.
|
|
2290 (ediff-overlay-put a-overlay 'priority ediff-shaded-overlay-priority)
|
|
2291 (ediff-overlay-put a-overlay 'ediff-diff-num current-diff)
|
|
2292 (ediff-overlay-put a-overlay
|
|
2293 'insert-in-front-hooks '(ediff-insert-in-front))
|
7424
|
2294 ; (ediff-overlay-put a-overlay
|
|
2295 ; 'ediff-control-buffer control-buffer-suffix)
|
7267
|
2296 (ediff-overlay-put a-overlay
|
|
2297 'face (if (ediff-odd-p current-diff) ;; odd diff
|
|
2298 'ediff-odd-diff-face-A-var
|
|
2299 'ediff-even-diff-face-A-var))
|
|
2300
|
|
2301 (setq b-overlay (ediff-make-overlay b-begin b-end B-buffer))
|
|
2302 (ediff-overlay-put b-overlay 'priority ediff-shaded-overlay-priority)
|
|
2303 (ediff-overlay-put b-overlay 'ediff-diff-num current-diff)
|
|
2304 (ediff-overlay-put b-overlay
|
|
2305 'insert-in-front-hooks '(ediff-insert-in-front))
|
7424
|
2306 ; (ediff-overlay-put b-overlay
|
|
2307 ; 'ediff-control-buffer control-buffer-suffix)
|
7267
|
2308 (ediff-overlay-put b-overlay
|
|
2309 'face (if (ediff-odd-p current-diff) ;; odd diff
|
|
2310 'ediff-odd-diff-face-B-var
|
|
2311 'ediff-even-diff-face-B-var))
|
|
2312
|
|
2313 (if (ediff-if-lucid) ;; chars inserted at end will be inside extent
|
|
2314 (progn
|
|
2315 (ediff-overlay-put a-overlay
|
|
2316 'ediff-marker
|
|
2317 (move-marker (make-marker) a-begin A-buffer))
|
|
2318 (ediff-overlay-put b-overlay
|
|
2319 'ediff-marker
|
|
2320 (move-marker (make-marker) b-begin B-buffer))
|
|
2321 (ediff-overlay-put a-overlay 'end-open nil)
|
|
2322 (ediff-overlay-put b-overlay 'end-open nil)))
|
|
2323
|
|
2324 ;; record all overlays for this difference
|
|
2325 (setq diff-overlay-list
|
7424
|
2326 (nconc diff-overlay-list (list (vector a-overlay b-overlay nil)))
|
7267
|
2327 diff-list (cdr diff-list))
|
7424
|
2328 (message "Processing diff region %d of %d"
|
7267
|
2329 current-diff total-diffs)
|
|
2330 ) ;; while
|
|
2331 ;; this is just to avoid confusing the user with diff num < total-diffs
|
7424
|
2332 (message "Processing diff region %d of %d"
|
7267
|
2333 (1+ current-diff) total-diffs)
|
|
2334 ;; convert the list of difference information into a vector for
|
|
2335 ;; fast access
|
7424
|
2336 (apply 'vector diff-overlay-list)))
|
7267
|
2337
|
|
2338
|
|
2339
|
|
2340 ;;; Commands
|
|
2341
|
|
2342 (defun ediff-recenter (&optional no-rehighlight)
|
|
2343 "Bring the highlighted region of all buffers A and B into view.
|
|
2344 Reestablish the default three-window display."
|
|
2345 (interactive)
|
|
2346 (setq ediff-disturbed-overlays nil) ;; clear after use
|
|
2347 (let (buffer-read-only)
|
|
2348 (ediff-setup-windows ediff-A-buffer ediff-B-buffer ediff-control-buffer))
|
|
2349 ;; Redisplay whatever buffers are showing, if there is a selected difference
|
|
2350 (if (and (>= ediff-current-difference 0)
|
|
2351 (< ediff-current-difference ediff-number-of-differences))
|
|
2352 (let* ( ;; context must be saved before switching to windows A/B
|
|
2353 (buffer-A ediff-A-buffer)
|
|
2354 (buffer-B ediff-B-buffer)
|
|
2355 (wind (selected-window))
|
|
2356 (control-buf ediff-control-buffer)
|
|
2357 (before-flag-shift-A (if (eq ediff-highlighting-style 'ascii)
|
|
2358 (1- (length ediff-before-flag-A))
|
|
2359 0))
|
|
2360 (after-flag-shift-A (if (eq ediff-highlighting-style 'ascii)
|
|
2361 (1- (length ediff-after-flag-A))
|
|
2362 0))
|
|
2363 (before-flag-shift-B (if (eq ediff-highlighting-style 'ascii)
|
|
2364 (1- (length ediff-before-flag-B))
|
|
2365 0))
|
|
2366 (after-flag-shift-B (if (eq ediff-highlighting-style 'ascii)
|
|
2367 (1- (length ediff-after-flag-B))
|
|
2368 0))
|
|
2369 (window-A (get-buffer-window buffer-A t))
|
|
2370 (window-B (get-buffer-window buffer-B t)))
|
|
2371
|
|
2372 (or no-rehighlight
|
|
2373 (ediff-operate-on-flags 'insert))
|
|
2374
|
|
2375 (if window-A (progn
|
|
2376 (select-window window-A)
|
|
2377 (ediff-position-region
|
|
2378 (- (ediff-get-diff-posn 'A 'beg nil control-buf)
|
|
2379 before-flag-shift-A)
|
|
2380 (+ (ediff-get-diff-posn 'A 'end nil control-buf)
|
|
2381 after-flag-shift-A)
|
|
2382 (ediff-get-diff-posn 'A 'beg nil control-buf))))
|
|
2383 (if window-B (progn
|
|
2384 (select-window window-B)
|
|
2385 (ediff-position-region
|
|
2386 (- (ediff-get-diff-posn 'B 'beg nil control-buf)
|
|
2387 before-flag-shift-B)
|
|
2388 (+ (ediff-get-diff-posn 'B 'end nil control-buf)
|
|
2389 after-flag-shift-B)
|
|
2390 (ediff-get-diff-posn 'B 'beg nil control-buf))))
|
|
2391 (select-window wind))))
|
|
2392
|
|
2393 (defun ediff-toggle-split ()
|
|
2394 "Toggle vertical/horizontal window split.
|
|
2395 Does nothing if file-A and file-B are in different frames."
|
|
2396 (interactive)
|
|
2397 (let* ((wind-A (get-buffer-window ediff-A-buffer t))
|
|
2398 (wind-B (get-buffer-window ediff-B-buffer t))
|
|
2399 (frame-A (if wind-A (ediff-window-frame wind-A)))
|
|
2400 (frame-B (if wind-B (ediff-window-frame wind-B))))
|
|
2401 (if (eq frame-A frame-B)
|
|
2402 (setq ediff-split-window-function
|
|
2403 (if (eq ediff-split-window-function 'split-window-vertically)
|
|
2404 'split-window-horizontally
|
|
2405 'split-window-vertically))
|
7424
|
2406 (message "No splitting: Buffers A and B are in different frames."))
|
7267
|
2407 (ediff-recenter 'no-rehighlight)))
|
|
2408
|
|
2409 (defun ediff-toggle-hilit ()
|
|
2410 "Switch between highlighting using ASCII flags and highlighting using faces.
|
|
2411 On a dumb terminal, switches between ASCII highlighting and no highlighting."
|
|
2412 (interactive)
|
|
2413 (if (not window-system)
|
|
2414 (if (eq ediff-highlighting-style 'ascii)
|
|
2415 (progn
|
|
2416 (message "ASCII highlighting flags removed.")
|
|
2417 (ediff-unselect-and-select-difference ediff-current-difference
|
|
2418 'unselect-only)
|
|
2419 (setq ediff-highlighting-style 'off))
|
|
2420 (ediff-unselect-and-select-difference ediff-current-difference
|
|
2421 'select-only))
|
|
2422 (ediff-unselect-and-select-difference ediff-current-difference
|
|
2423 'unselect-only)
|
|
2424 ;; cycle through highlighting
|
7424
|
2425 (cond ((and ediff-want-faces ediff-highlight-all-diffs)
|
|
2426 (message "Unhighlighting unselected difference regions.")
|
|
2427 (setq ediff-highlight-all-diffs nil))
|
7267
|
2428 (ediff-want-faces
|
7424
|
2429 (message "Highlighting with ASCII flags.")
|
7267
|
2430 (setq ediff-want-faces nil))
|
|
2431 (t
|
7424
|
2432 (message "Re-highlighting all difference regions.")
|
7267
|
2433 (setq ediff-want-faces t
|
7424
|
2434 ediff-highlight-all-diffs t)))
|
7267
|
2435
|
7424
|
2436 (if (and ediff-want-faces ediff-highlight-all-diffs)
|
7267
|
2437 (if (not (face-differs-from-default-p 'ediff-odd-diff-face-A-var))
|
|
2438 (progn
|
|
2439 (copy-face ediff-odd-diff-face-A 'ediff-odd-diff-face-A-var)
|
|
2440 (copy-face ediff-odd-diff-face-B 'ediff-odd-diff-face-B-var)
|
|
2441 (copy-face ediff-even-diff-face-A 'ediff-even-diff-face-A-var)
|
|
2442 (copy-face ediff-even-diff-face-B 'ediff-even-diff-face-B-var)))
|
|
2443 (copy-face 'default 'ediff-odd-diff-face-A-var)
|
|
2444 (copy-face 'default 'ediff-odd-diff-face-B-var)
|
|
2445 (copy-face 'default 'ediff-even-diff-face-A-var)
|
|
2446 (copy-face 'default 'ediff-even-diff-face-B-var))
|
|
2447
|
|
2448 (ediff-unselect-and-select-difference
|
|
2449 ediff-current-difference 'select-only))
|
|
2450 (ediff-operate-on-flags 'insert)
|
|
2451 )
|
|
2452
|
7424
|
2453 (defun ediff-toggle-autorefine ()
|
|
2454 "Toggle auto-refine mode."
|
|
2455 (interactive)
|
|
2456 (if window-system
|
|
2457 (cond ((eq ediff-auto-refine 'nix)
|
|
2458 (setq ediff-auto-refine 'on)
|
|
2459 (ediff-make-fine-diffs ediff-current-difference 'noforce)
|
|
2460 (message "Auto-refining is ON."))
|
|
2461 ((eq ediff-auto-refine 'on)
|
|
2462 (message "Auto-refining is OFF.")
|
|
2463 (setq ediff-auto-refine 'off))
|
|
2464 (t
|
|
2465 (ediff-set-fine-diff-properties ediff-current-difference 'default)
|
|
2466 (message "Refinements are HIDDEN.")
|
|
2467 (setq ediff-auto-refine 'nix))
|
|
2468 )))
|
|
2469
|
7267
|
2470 (defun ediff-toggle-help ()
|
|
2471 "Toggle short/long help message."
|
|
2472 (interactive)
|
|
2473 (let (buffer-read-only)
|
|
2474 (erase-buffer)
|
|
2475 (if (string= ediff-help-message ediff-help-message-long)
|
|
2476 (setq ediff-help-message ediff-help-message-short)
|
|
2477 (setq ediff-help-message ediff-help-message-long)))
|
7424
|
2478 (setq ediff-window-config-saved "") ;; force redisplay
|
7267
|
2479 (ediff-recenter 'no-rehighlight))
|
|
2480
|
|
2481
|
|
2482 (defun ediff-toggle-read-only-A ()
|
|
2483 "Used as a startup hook to set `.orig' patch file read-only."
|
|
2484 (let ((last-command-char ?A))
|
|
2485 (ediff-toggle-read-only)))
|
|
2486
|
|
2487 (defun ediff-toggle-read-only ()
|
|
2488 "Toggles buffer-read-only for buffer buffers A and B."
|
|
2489 (interactive)
|
|
2490 (emerge-eval-in-buffer
|
|
2491 (if (eq last-command-char ?A) ediff-A-buffer ediff-B-buffer)
|
|
2492 (setq buffer-read-only (null buffer-read-only))))
|
|
2493
|
|
2494 ;;; Window scrolling operations
|
|
2495 ;; These operations are designed to scroll all three windows the same amount,
|
|
2496 ;; so as to keep the text in them aligned.
|
|
2497
|
7424
|
2498 ;; Perform some operation on the two file windows (if they are showing).
|
7267
|
2499 ;; Catches all errors on the operation in the A and B windows.
|
|
2500 ;; Usually, errors come from scrolling off the
|
|
2501 ;; beginning or end of the buffer, and this gives nice nice error messages.
|
|
2502 (defun ediff-operate-on-windows (operation arg)
|
|
2503 (let* ((buffer-A ediff-A-buffer)
|
|
2504 (buffer-B ediff-B-buffer)
|
|
2505 (wind (selected-window))
|
|
2506 (window-A (get-buffer-window buffer-A t))
|
|
2507 (window-B (get-buffer-window buffer-B t)))
|
|
2508 (if window-A (progn
|
|
2509 (select-window window-A)
|
|
2510 (condition-case nil
|
|
2511 (funcall operation arg)
|
|
2512 (error))))
|
|
2513 (if window-B (progn
|
|
2514 (select-window window-B)
|
|
2515 (condition-case nil
|
|
2516 (funcall operation arg)
|
|
2517 (error))))
|
|
2518 (select-window wind)
|
|
2519 ))
|
|
2520
|
|
2521 (defun ediff-scroll-up (&optional arg)
|
|
2522 "Scroll up buffers A and B, if they are in windows.
|
|
2523 With optional argument ARG, scroll ARG lines; otherwise scroll by nearly
|
|
2524 the height of window-A."
|
|
2525 (interactive "P")
|
|
2526 (ediff-operate-on-windows
|
|
2527 'scroll-up
|
|
2528 ;; calculate argument to scroll-up
|
|
2529 ;; if there is an explicit argument
|
|
2530 (if (and arg (not (equal arg '-)))
|
|
2531 ;; use it
|
|
2532 (prefix-numeric-value arg)
|
|
2533 ;; if not, see if we can determine a default amount (the window height)
|
|
2534 (let* ((window-A (get-buffer-window ediff-A-buffer t))
|
|
2535 (window-B (get-buffer-window ediff-B-buffer t))
|
|
2536 default-amount)
|
|
2537 (if (or (null window-A) (null window-B))
|
|
2538 (setq default-amount 0)
|
|
2539 (setq default-amount
|
|
2540 (- (min (window-height window-A) (window-height window-B))
|
|
2541 1 next-screen-context-lines)))
|
|
2542 ;; the window was found
|
|
2543 (if arg
|
|
2544 ;; C-u as argument means half of default amount
|
|
2545 (/ default-amount 2)
|
|
2546 ;; no argument means default amount
|
|
2547 default-amount)))))
|
|
2548
|
|
2549 (defun ediff-scroll-down (&optional arg)
|
|
2550 "Scroll down buffers A and B, if they are in windows.
|
|
2551 With optional argument ARG, scroll ARG lines; otherwise scroll by nearly
|
|
2552 the height of window-A."
|
|
2553 (interactive "P")
|
|
2554 (ediff-operate-on-windows
|
|
2555 'scroll-down
|
|
2556 ;; calculate argument to scroll-down
|
|
2557 ;; if there is an explicit argument
|
|
2558 (if (and arg (not (equal arg '-)))
|
|
2559 ;; use it
|
|
2560 (prefix-numeric-value arg)
|
|
2561 ;; if not, see if we can determine a default amount (the window height)
|
|
2562 (let* ((window-A (get-buffer-window ediff-A-buffer t))
|
|
2563 (window-B (get-buffer-window ediff-B-buffer t))
|
|
2564 default-amount)
|
|
2565 (if (or (null window-A) (null window-B))
|
|
2566 (setq default-amount 0)
|
|
2567 (setq default-amount
|
|
2568 (- (min (window-height window-A) (window-height window-B))
|
|
2569 1 next-screen-context-lines)))
|
|
2570 ;; the window was found
|
|
2571 (if arg
|
|
2572 ;; C-u as argument means half of default amount
|
|
2573 (/ default-amount 2)
|
|
2574 ;; no argument means default amount
|
|
2575 default-amount)))))
|
|
2576
|
|
2577 (defun ediff-scroll-left (&optional arg)
|
|
2578 "Scroll left buffer-A and buffer-B, if they are in windows.
|
|
2579 If an argument is given, that is how many columns are scrolled, else nearly
|
|
2580 the width of the A and B windows."
|
|
2581 (interactive "P")
|
|
2582 (ediff-operate-on-windows
|
|
2583 'scroll-left
|
|
2584 ;; calculate argument to scroll-left
|
|
2585 ;; if there is an explicit argument
|
|
2586 (if (and arg (not (equal arg '-)))
|
|
2587 ;; use it
|
|
2588 (prefix-numeric-value arg)
|
|
2589 ;; if not, see if we can determine a default amount
|
|
2590 ;; (half the window width)
|
|
2591 (if (null ediff-control-window)
|
|
2592 ;; no control window, use nil
|
|
2593 nil
|
|
2594 (let ((default-amount
|
|
2595 (- (/ (window-width ediff-control-window) 2) 3)))
|
|
2596 ;; the window was found
|
|
2597 (if arg
|
|
2598 ;; C-u as argument means half of default amount
|
|
2599 (/ default-amount 2)
|
|
2600 ;; no argument means default amount
|
|
2601 default-amount))))))
|
|
2602
|
|
2603 (defun ediff-scroll-right (&optional arg)
|
|
2604 "Scroll right buffer-A and buffer-B, if they are in windows.
|
|
2605 If an argument is given, that is how many columns are scrolled, else nearly
|
|
2606 the width of the A and B windows."
|
|
2607 (interactive "P")
|
|
2608 (ediff-operate-on-windows
|
|
2609 'scroll-right
|
|
2610 ;; calculate argument to scroll-right
|
|
2611 ;; if there is an explicit argument
|
|
2612 (if (and arg (not (equal arg '-)))
|
|
2613 ;; use it
|
|
2614 (prefix-numeric-value arg)
|
|
2615 ;; if not, see if we can determine a default amount
|
|
2616 ;; (half the window width)
|
|
2617 (if (null ediff-control-window)
|
|
2618 ;; no control window, use nil
|
|
2619 nil
|
|
2620 (let ((default-amount
|
|
2621 (- (/ (window-width ediff-control-window) 2) 3)))
|
|
2622 ;; the window was found
|
|
2623 (if arg
|
|
2624 ;; C-u as argument means half of default amount
|
|
2625 (/ default-amount 2)
|
|
2626 ;; no argument means default amount
|
|
2627 default-amount))))))
|
|
2628
|
|
2629 (defun ediff-position-region (beg end pos)
|
7424
|
2630 "This is a variation on `emerge-position-region'.
|
7267
|
2631 The difference is that it always tries to align difference regions in
|
|
2632 buffer-A and buffer-B, so that it will be easier to compare them."
|
|
2633 (set-window-start (selected-window) beg)
|
|
2634 (if (pos-visible-in-window-p end)
|
|
2635 ;; Determine the number of lines that the region occupies
|
|
2636 (let ((lines 0))
|
|
2637 (while (> end (progn
|
|
2638 (move-to-window-line lines)
|
|
2639 (point)))
|
|
2640 (setq lines (1+ lines)))
|
|
2641 ;; And position the beginning on the right line
|
|
2642 (goto-char beg)
|
|
2643 (recenter (/ (1+ (max (- (1- (window-height (selected-window)))
|
|
2644 lines)
|
|
2645 1)
|
|
2646 )
|
|
2647 2))))
|
|
2648 (goto-char pos)
|
|
2649 )
|
|
2650
|
|
2651
|
7424
|
2652 (defun ediff-next-difference (&optional arg)
|
7267
|
2653 "Advance to the next difference.
|
|
2654 With a prefix argument, go back that many differences."
|
|
2655 (interactive "P")
|
|
2656 (if (< ediff-current-difference ediff-number-of-differences)
|
|
2657 (let ((n (min ediff-number-of-differences
|
|
2658 (+ ediff-current-difference (if arg arg 1))))
|
|
2659 (buffer-read-only nil))
|
|
2660 (ediff-unselect-and-select-difference n))
|
|
2661 (error "At end of the difference list.")))
|
|
2662
|
7424
|
2663 (defun ediff-previous-difference (&optional arg)
|
7267
|
2664 "Go to the previous difference.
|
|
2665 With a prefix argument, go back that many differences."
|
|
2666 (interactive "P")
|
|
2667 (if (> ediff-current-difference -1)
|
|
2668 (let ((n (max -1 (- ediff-current-difference (if arg arg 1))))
|
|
2669 (buffer-read-only nil))
|
|
2670 (ediff-unselect-and-select-difference n))
|
|
2671 (error "At beginning of the difference list.")))
|
|
2672
|
|
2673 (defun ediff-jump-to-difference (difference-number)
|
|
2674 "Go to the difference specified as a prefix argument."
|
|
2675 (interactive "p")
|
|
2676 (let ((buffer-read-only nil))
|
|
2677 (setq difference-number (1- difference-number))
|
|
2678 (if (and (>= difference-number -1)
|
|
2679 (< difference-number (1+ ediff-number-of-differences)))
|
|
2680 (ediff-unselect-and-select-difference difference-number)
|
|
2681 (error "Bad difference number"))))
|
|
2682
|
|
2683 (defun ediff-jump-to-difference-at-point ()
|
|
2684 "Go to the difference closest to the point in buffer A or B.
|
|
2685 If this command is invoked via `ja' or `ga' then the point in buffer A is
|
7424
|
2686 used. Otherwise, buffer B is used."
|
7267
|
2687 (interactive)
|
|
2688 (let ((buffer-read-only nil)
|
7424
|
2689 (buf-type (ediff-char-to-buftype last-command-char)))
|
7267
|
2690 (ediff-jump-to-difference (ediff-diff-at-point buf-type))))
|
|
2691
|
|
2692
|
|
2693 ;; find region "most related to the current point position
|
|
2694
|
|
2695 (defun ediff-diff-at-point (buf-type)
|
7424
|
2696 (let ((buffer (ediff-get-buffer buf-type))
|
7267
|
2697 (ctl-buffer ediff-control-buffer)
|
|
2698 (diff-no -1)
|
|
2699 (prev-beg 0)
|
7424
|
2700 (prev-end 0)
|
|
2701 (beg 0)
|
|
2702 (end 0))
|
7267
|
2703
|
|
2704 (emerge-eval-in-buffer
|
|
2705 buffer
|
|
2706 (while (or (< (point) prev-beg) (> (point) beg))
|
|
2707 (setq diff-no (1+ diff-no))
|
7424
|
2708 (setq prev-beg beg
|
|
2709 prev-end end)
|
|
2710 (setq beg (ediff-get-diff-posn buf-type 'beg diff-no ctl-buffer)
|
|
2711 end (ediff-get-diff-posn buf-type 'end diff-no ctl-buffer))
|
|
2712 )
|
7267
|
2713
|
7424
|
2714 (if (< (abs (- (point) prev-end))
|
7267
|
2715 (abs (- (point) beg)))
|
|
2716 diff-no
|
|
2717 (1+ diff-no)) ;; jump-to-diff works with diff nums higher by 1
|
|
2718 )))
|
|
2719
|
|
2720 ;;; Copying diffs.
|
|
2721
|
|
2722 (defun ediff-diff-to-diff (arg)
|
|
2723 "Copy buffer-A'th diff to buffer B.
|
|
2724 If numerical prefix argument, copy this diff specified in the arg.
|
7419
|
2725 Otherwise, copy the difference given by `ediff-current-difference'."
|
7267
|
2726 (interactive "P")
|
|
2727 (if arg
|
|
2728 (ediff-jump-to-difference arg))
|
|
2729 (ediff-copy-diff ediff-current-difference
|
7424
|
2730 (ediff-char-to-buftype (aref (this-command-keys) 0))
|
|
2731 (ediff-char-to-buftype (aref (this-command-keys) 1)))
|
7267
|
2732 (ediff-recenter 'no-rehighlight))
|
|
2733
|
|
2734
|
7424
|
2735 (defun ediff-copy-diff (n from-buf-type to-buf-type)
|
|
2736 "Copy diff N from FROM-BUF-TYPE \(given as 'A or 'B\) to TO-BUF-TYPE."
|
|
2737 (let* ((to-buf (ediff-get-buffer to-buf-type))
|
|
2738 (from-buf (ediff-get-buffer from-buf-type))
|
7267
|
2739 (ctrl-buf ediff-control-buffer)
|
|
2740 reg-to-copy reg-to-delete
|
|
2741 reg-to-delete-beg reg-to-delete-end)
|
|
2742
|
|
2743 (ediff-operate-on-flags 'remove)
|
|
2744 (setq reg-to-delete-beg
|
7424
|
2745 (ediff-get-diff-posn to-buf-type 'beg n ctrl-buf))
|
7267
|
2746 (setq reg-to-delete-end
|
7424
|
2747 (ediff-get-diff-posn to-buf-type 'end n ctrl-buf))
|
7267
|
2748 (setq reg-to-copy (emerge-eval-in-buffer
|
7424
|
2749 from-buf
|
7267
|
2750 (buffer-substring (ediff-get-diff-posn
|
7424
|
2751 from-buf-type 'beg n ctrl-buf)
|
7267
|
2752 (ediff-get-diff-posn
|
7424
|
2753 from-buf-type 'end n ctrl-buf))))
|
7267
|
2754 (setq reg-to-delete (emerge-eval-in-buffer
|
7424
|
2755 to-buf
|
7267
|
2756 (buffer-substring reg-to-delete-beg
|
|
2757 reg-to-delete-end)))
|
|
2758 (setq ediff-disturbed-overlays nil) ;; clear before use
|
|
2759
|
|
2760 (if (string= reg-to-delete reg-to-copy)
|
|
2761 (progn
|
|
2762 (ding)
|
|
2763 (message
|
7424
|
2764 "Diff regions %d are identical in buffers %S and %S. Nothing copied."
|
|
2765 (1+ n) from-buf-type to-buf-type))
|
7267
|
2766
|
|
2767 ;; seems ok to copy
|
7424
|
2768 (if (ediff-test-save-region n to-buf-type)
|
7267
|
2769 (condition-case conds
|
|
2770 (let (inhibit-read-only)
|
|
2771 (emerge-eval-in-buffer
|
7424
|
2772 to-buf
|
7267
|
2773 ;; to prevent flags from interfering if buffer is writable
|
|
2774 (setq inhibit-read-only (null buffer-read-only))
|
|
2775 (let ((before-change-function nil))
|
|
2776 (goto-char reg-to-delete-end)
|
|
2777 (insert-before-markers reg-to-copy)
|
|
2778 (if (ediff-if-lucid)
|
|
2779 (progn
|
|
2780 (ediff-collect-extents-lucid reg-to-delete-beg)
|
|
2781 (if (> reg-to-delete-end reg-to-delete-beg)
|
|
2782 (progn
|
|
2783 (kill-region reg-to-delete-beg
|
|
2784 reg-to-delete-end)
|
|
2785 (if (string= reg-to-copy "")
|
|
2786 (ediff-adjust-disturbed-extents-lucid
|
|
2787 reg-to-delete-beg)))))
|
|
2788 (if (> reg-to-delete-end reg-to-delete-beg)
|
|
2789 (kill-region reg-to-delete-beg reg-to-delete-end)
|
|
2790 (ediff-move-disturbed-overlays reg-to-delete-beg)))
|
|
2791 ))
|
7424
|
2792 (ediff-save-diff-region n to-buf-type reg-to-delete))
|
7267
|
2793 (error (message "%s %s"
|
|
2794 (car conds)
|
|
2795 (mapconcat 'prin1-to-string (cdr conds) " "))
|
|
2796 (beep 1))))
|
|
2797 )
|
|
2798 (ediff-operate-on-flags 'insert)
|
|
2799 ))
|
|
2800
|
|
2801 (defun ediff-save-diff-region (n buf-type reg)
|
7419
|
2802 "Save Nth diff of buffer BUF-TYPE \(`A' or `B'\).
|
|
2803 That is to say, the Nth diff on the `ediff-killed-diffs-alist'. REG
|
7424
|
2804 is the region to save. It is redundant here, but is passed anyway, for
|
7419
|
2805 convenience."
|
7267
|
2806
|
|
2807 (let* ((n-th-diff-saved (assoc n ediff-killed-diffs-alist))
|
|
2808 (this-buf-n-th-diff-saved (assoc buf-type (cdr n-th-diff-saved))))
|
|
2809
|
|
2810 (if this-buf-n-th-diff-saved
|
|
2811 ;; either nothing saved for n-th diff and buffer or we OK'ed
|
|
2812 ;; overriding
|
|
2813 (setcdr this-buf-n-th-diff-saved reg)
|
|
2814 (if n-th-diff-saved ;; n-th diff saved, but for another buffer
|
|
2815 (nconc n-th-diff-saved (list (cons buf-type reg)))
|
|
2816 (setq ediff-killed-diffs-alist ;; create record for n-th diff
|
|
2817 (cons (list n (cons buf-type reg))
|
|
2818 ediff-killed-diffs-alist))))
|
7424
|
2819 (message "Saved diff region #%d for buffer %S. To recover hit 'r%s'."
|
|
2820 (1+ n) buf-type
|
|
2821 (downcase (symbol-name buf-type)))))
|
7267
|
2822
|
|
2823 (defun ediff-test-save-region (n buf-type)
|
7419
|
2824 "Test if saving Nth difference region of buffer BUF-TYPE is possible."
|
7267
|
2825 (let* ((n-th-diff-saved (assoc n ediff-killed-diffs-alist))
|
|
2826 (this-buf-n-th-diff-saved (assoc buf-type (cdr n-th-diff-saved))))
|
|
2827
|
|
2828 (if this-buf-n-th-diff-saved
|
|
2829 (if (yes-or-no-p
|
|
2830 (format
|
7424
|
2831 "You've previously copied diff region %d to buffer %S. Confirm."
|
|
2832 (1+ n) buf-type))
|
7267
|
2833 t
|
|
2834 (error "Quit."))
|
|
2835 t)))
|
|
2836
|
|
2837 (defun ediff-pop-diff (n buf-type)
|
7419
|
2838 "Pop last killed Nth diff region from buffer BUF-TYPE."
|
7267
|
2839 (let* ((n-th-record (assoc n ediff-killed-diffs-alist))
|
|
2840 (saved-rec (assoc buf-type (cdr n-th-record)))
|
7424
|
2841 (buf (ediff-get-buffer buf-type))
|
7267
|
2842 saved-diff reg-beg reg-end recovered)
|
|
2843
|
|
2844 (if (cdr saved-rec)
|
|
2845 (setq saved-diff (cdr saved-rec))
|
7424
|
2846 (if (> ediff-number-of-differences 0)
|
|
2847 (error "Nothing saved for diff %d in buffer %S." (1+ n) buf-type)
|
|
2848 (error "No differences found.")))
|
7267
|
2849
|
|
2850 (ediff-operate-on-flags 'remove)
|
|
2851
|
|
2852 (setq reg-beg (ediff-get-diff-posn buf-type 'beg n ediff-control-buffer))
|
|
2853 (setq reg-end (ediff-get-diff-posn buf-type 'end n ediff-control-buffer))
|
|
2854 (setq ediff-disturbed-overlays nil) ;; clear before use
|
|
2855
|
|
2856 (condition-case conds
|
|
2857 (emerge-eval-in-buffer
|
|
2858 buf
|
|
2859 (let ((inhibit-read-only (null buffer-read-only))
|
|
2860 (before-change-function nil))
|
|
2861 (goto-char reg-end)
|
|
2862 (insert-before-markers saved-diff)
|
|
2863
|
|
2864 (if (ediff-if-lucid)
|
|
2865 (progn
|
|
2866 (ediff-collect-extents-lucid reg-beg)
|
|
2867 (if (> reg-end reg-beg)
|
|
2868 (progn
|
|
2869 (kill-region reg-beg reg-end)
|
|
2870 (if (string= saved-diff "")
|
|
2871 (ediff-adjust-disturbed-extents-lucid reg-beg)))))
|
|
2872 (if (> reg-end reg-beg)
|
|
2873 (kill-region reg-beg reg-end)
|
|
2874 (ediff-move-disturbed-overlays reg-beg)))
|
|
2875
|
|
2876 (setq recovered t)
|
|
2877 ))
|
|
2878 (error (message "%s %s"
|
|
2879 (car conds)
|
|
2880 (mapconcat 'prin1-to-string (cdr conds) " "))
|
|
2881 (beep 1)))
|
|
2882
|
|
2883 (ediff-operate-on-flags 'insert)
|
|
2884 (if recovered
|
|
2885 (progn
|
|
2886 (setq n-th-record (delq saved-rec n-th-record))
|
7424
|
2887 (message "Restored diff region %d in buffer %S." (1+ n) buf-type)))
|
7267
|
2888 ))
|
|
2889
|
|
2890 (defun ediff-restore-diff (arg)
|
7419
|
2891 "Restore ARGth diff from `ediff-killed-diffs-alist'.
|
|
2892 ARG is a prefix argument. If ARG is nil, restore current-difference."
|
7267
|
2893 (interactive "P")
|
|
2894 (if arg
|
|
2895 (ediff-jump-to-difference arg))
|
|
2896 (ediff-pop-diff ediff-current-difference
|
7424
|
2897 (ediff-char-to-buftype last-command-char))
|
7267
|
2898 (ediff-recenter 'no-rehighlight))
|
|
2899
|
|
2900
|
|
2901 ;;; Quitting, suspending, etc.
|
|
2902 (defun ediff-quit ()
|
|
2903 "Finish an Ediff session and exit Ediff.
|
|
2904 Unselects the selected difference, if any, restores the read-only and modified
|
|
2905 flags of the compared file buffers, kills Ediff buffers for this session
|
|
2906 \(but not file-A and file-B\)."
|
|
2907 (interactive)
|
|
2908 (if (prog1
|
|
2909 (y-or-n-p "Do you really want to exit Ediff? ")
|
|
2910 (message ""))
|
|
2911 (ediff-really-quit)))
|
|
2912
|
7424
|
2913
|
7267
|
2914 ;; Perform the quit operations.
|
|
2915 (defun ediff-really-quit ()
|
|
2916 (setq ediff-help-message ediff-help-message-long)
|
|
2917 (ediff-restore-buffer-characteristics t) ;; restore as they were at setup
|
|
2918 (ediff-unhighlight-diffs-totally)
|
7424
|
2919 (ediff-clear-diff-vector ediff-difference-vector 'fine-diffs-also)
|
|
2920 (if ediff-temp-file-A (delete-file ediff-temp-file-A))
|
|
2921 (if ediff-temp-file-B (delete-file ediff-temp-file-B))
|
7267
|
2922
|
|
2923 ;; restore buffer mode line id's in buffer-A/B
|
|
2924 (let ((control-buffer ediff-control-buffer))
|
|
2925 (emerge-eval-in-buffer
|
|
2926 ediff-A-buffer
|
|
2927 (setq before-change-function nil)
|
|
2928 (setq ediff-this-buffer-control-sessions
|
|
2929 (delq control-buffer ediff-this-buffer-control-sessions))
|
|
2930 (if (null ediff-this-buffer-control-sessions)
|
|
2931 (setq local-write-file-hooks
|
|
2932 (delq 'ediff-block-write-file local-write-file-hooks)))
|
|
2933 (kill-local-variable 'mode-line-buffer-identification))
|
|
2934 (emerge-eval-in-buffer
|
|
2935 ediff-B-buffer
|
|
2936 (setq ediff-this-buffer-control-sessions
|
|
2937 (delq control-buffer ediff-this-buffer-control-sessions))
|
|
2938 (if (null ediff-this-buffer-control-sessions)
|
|
2939 (setq local-write-file-hooks
|
|
2940 (delq 'ediff-block-write-file local-write-file-hooks)))
|
|
2941 (setq before-change-function nil)
|
|
2942 (kill-local-variable 'mode-line-buffer-identification)))
|
|
2943
|
|
2944 (run-hooks 'ediff-quit-hooks))
|
|
2945
|
|
2946 (defun ediff-kill-buffer-carefully (buf)
|
|
2947 "Kill buffer BUF if it exists."
|
|
2948 (if (ediff-buffer-live-p buf)
|
|
2949 (kill-buffer (get-buffer buf))))
|
|
2950
|
|
2951 ;; The default way of quitting Ediff.
|
|
2952 ;; Kills control buffers and leaves the
|
|
2953 ;; frame split between the two diff'ed files.
|
|
2954 (defun ediff-default-quit-hook ()
|
|
2955 (let ((buff-A ediff-A-buffer)
|
|
2956 (buff-B ediff-B-buffer))
|
|
2957 (ediff-kill-buffer-carefully ediff-diff-buffer)
|
7424
|
2958 (ediff-kill-buffer-carefully ediff-tmp-buffer)
|
|
2959 (ediff-kill-buffer-carefully ediff-error-buffer)
|
7267
|
2960 (ediff-kill-buffer-carefully ediff-control-buffer)
|
|
2961 (ediff-kill-buffer-carefully ediff-patch-diagnostics)
|
|
2962 (delete-other-windows)
|
|
2963 (switch-to-buffer buff-B)
|
|
2964 (split-window-vertically)
|
|
2965 (switch-to-buffer buff-A)))
|
|
2966
|
|
2967 ;; The default way of suspending Ediff.
|
|
2968 ;; Buries Ediff buffers, kills all windows.
|
|
2969 (defun ediff-default-suspend-hook ()
|
|
2970 (let ((buf-A ediff-A-buffer)
|
|
2971 (buf-B ediff-B-buffer)
|
|
2972 (buf-patch ediff-patch-buf)
|
|
2973 (buf-patch-diag ediff-patch-diagnostics)
|
7424
|
2974 (buf-err ediff-error-buffer)
|
7267
|
2975 (buf-diff ediff-diff-buffer))
|
|
2976 (bury-buffer) ;; ediff-control-buffer
|
|
2977 (delete-other-windows)
|
|
2978 (bury-buffer buf-err)
|
|
2979 (bury-buffer buf-diff)
|
|
2980 (bury-buffer buf-patch)
|
|
2981 (bury-buffer buf-patch-diag)
|
|
2982 (bury-buffer buf-A)
|
|
2983 (bury-buffer buf-B)))
|
|
2984
|
|
2985
|
|
2986 (defun ediff-suspend ()
|
7419
|
2987 "Suspend Ediff.
|
|
2988 To resume, switch to the appropriate `*ediff-control*'
|
|
2989 buffer and then type \\[ediff-recenter]. Ediff will automatically set
|
7267
|
2990 up an appropriate window config."
|
|
2991 (interactive)
|
7424
|
2992 (let ((key (substitute-command-keys "\\[ediff-recenter]")))
|
7267
|
2993 (run-hooks 'ediff-suspend-hooks)
|
|
2994 (message
|
7424
|
2995 "To resume Ediff, switch to *ediff-control* and hit '%S'" key)))
|
7267
|
2996
|
|
2997
|
|
2998 (defun ediff-file-names ()
|
|
2999 "Show the names of the buffers or files being operated on by Ediff.
|
7419
|
3000 Hit \\[ediff-recenter] to reset the windows afterward."
|
7267
|
3001 (interactive)
|
|
3002 (with-output-to-temp-buffer "*Help*"
|
|
3003 (emerge-eval-in-buffer ediff-A-buffer
|
|
3004 (if buffer-file-name
|
7424
|
3005 (princ
|
|
3006 (format "File A is: %s\n" buffer-file-name))
|
|
3007 (princ
|
|
3008 (format "Buffer A is: %s\n" (buffer-name)))))
|
7267
|
3009 (emerge-eval-in-buffer ediff-B-buffer
|
|
3010 (if buffer-file-name
|
7424
|
3011 (princ
|
|
3012 (format "File B is: %s\n" buffer-file-name))
|
|
3013 (princ
|
|
3014 (format "Buffer B is: %s\n" (buffer-name)))))
|
7267
|
3015 ))
|
|
3016
|
|
3017
|
|
3018
|
|
3019 (defun ediff-line-numbers ()
|
|
3020 "Display the current line numbers.
|
|
3021 This function displays the line numbers of the points in the A, B."
|
|
3022 (interactive)
|
|
3023 (let* ((A-line (emerge-eval-in-buffer ediff-A-buffer
|
|
3024 (count-lines (point-min) (point))))
|
|
3025 (B-line (emerge-eval-in-buffer ediff-B-buffer
|
|
3026 (count-lines (point-min) (point)))))
|
|
3027 (message "At lines: A = %d, B = %d" A-line B-line)))
|
|
3028
|
|
3029
|
|
3030 ;;; Support routines
|
|
3031
|
|
3032 ;; Select a difference by placing the ASCII flags around the appropriate
|
|
3033 ;; group of lines in the A, B buffers
|
|
3034 (defun ediff-select-difference (n)
|
|
3035 (if (and (>= n 0) (< n ediff-number-of-differences))
|
|
3036 (progn
|
|
3037 (ediff-remember-buffer-characteristics)
|
|
3038 (if (and window-system ediff-want-faces)
|
|
3039 (progn
|
|
3040 (ediff-highlight-diff n)
|
|
3041 (setq ediff-highlighting-style 'face))
|
|
3042 (setq ediff-highlighting-style 'ascii)
|
|
3043 (ediff-place-flags-in-buffer 'A ediff-A-buffer
|
|
3044 ediff-control-buffer n)
|
|
3045 (ediff-place-flags-in-buffer 'B ediff-B-buffer
|
|
3046 ediff-control-buffer n))
|
|
3047
|
7424
|
3048 (if window-system
|
|
3049 (cond ((eq ediff-auto-refine 'on)
|
|
3050 (if (and
|
|
3051 (> ediff-auto-refine-limit
|
|
3052 (- (ediff-get-diff-posn 'A 'end n)
|
|
3053 (ediff-get-diff-posn 'A 'beg n)))
|
|
3054 (> ediff-auto-refine-limit
|
|
3055 (- (ediff-get-diff-posn 'B 'end n)
|
|
3056 (ediff-get-diff-posn 'B 'beg n))))
|
|
3057 (ediff-make-fine-diffs n 'noforce)
|
|
3058 (ediff-make-fine-diffs n 'skip)))
|
|
3059
|
|
3060 ((eq ediff-auto-refine 'off) ; highlight iff fine diffs
|
|
3061 (ediff-make-fine-diffs n 'skip)))) ; already exist
|
|
3062
|
7267
|
3063 (ediff-restore-buffer-characteristics)
|
|
3064 (run-hooks 'ediff-select-hooks))))
|
|
3065
|
|
3066
|
|
3067 ;; Unselect a difference by removing the ASCII flags in the buffers.
|
|
3068 (defun ediff-unselect-difference (n)
|
|
3069 (if (and (>= n 0) (< n ediff-number-of-differences))
|
|
3070 (progn
|
|
3071 (ediff-remember-buffer-characteristics)
|
|
3072
|
|
3073 (cond ((and window-system ediff-want-faces)
|
|
3074 (ediff-unhighlight-diff))
|
|
3075 ((eq ediff-highlighting-style 'ascii)
|
|
3076 (ediff-remove-flags-from-buffer
|
|
3077 ediff-A-buffer
|
|
3078 (ediff-get-diff-posn 'A 'beg n)
|
|
3079 (ediff-get-diff-posn 'A 'end n)
|
|
3080 ediff-before-flag-A ediff-after-flag-A)
|
|
3081 (ediff-remove-flags-from-buffer
|
|
3082 ediff-B-buffer
|
|
3083 (ediff-get-diff-posn 'B 'beg n)
|
|
3084 (ediff-get-diff-posn 'B 'end n)
|
|
3085 ediff-before-flag-B ediff-after-flag-B)))
|
|
3086
|
|
3087 (ediff-restore-buffer-characteristics)
|
|
3088 (setq ediff-highlighting-style nil)
|
7424
|
3089
|
|
3090 ;; unhighlight fine diffs
|
|
3091 (if window-system
|
|
3092 (ediff-set-fine-diff-properties
|
|
3093 ediff-current-difference 'default))
|
|
3094
|
7267
|
3095 (run-hooks 'ediff-unselect-hooks))))
|
|
3096
|
|
3097
|
|
3098 ;; Unselects prev diff and selects a new one, if FLAG has value other than
|
|
3099 ;; 'select-only or 'unselect-only. If FLAG is 'select-only, the
|
|
3100 ;; next difference is selected, but the current selection is not
|
|
3101 ;; unselected. If FLAG is 'unselect-only then the current selection is
|
|
3102 ;; unselected, but the next one is not selected. If NO-RECENTER is non-nil,
|
|
3103 ;; don't recenter buffers after selecting/unselecting.
|
|
3104 ;;
|
7419
|
3105 ;; Don't use `ediff-select-difference' and `ediff-unselect-difference'
|
7267
|
3106 ;; directly,;; since this will screw up the undo info in the presence of
|
|
3107 ;; ASCII flags.
|
7419
|
3108 ;; Instead, use `ediff-unselect-and-select-difference' with appropriate
|
7267
|
3109 ;; flags.
|
|
3110
|
|
3111 (defun ediff-unselect-and-select-difference (n &optional flag no-recenter)
|
7424
|
3112 (let (;; save buf modified info
|
|
3113 (control-buf ediff-control-buffer)
|
7267
|
3114 (buf-A-modified (buffer-modified-p ediff-A-buffer))
|
|
3115 (buf-B-modified (buffer-modified-p ediff-B-buffer))
|
|
3116 ;; temporarily disable undo so highlighting won't confuse the user
|
|
3117 buf-A-undo buf-B-undo)
|
|
3118
|
7424
|
3119 (let ((ediff-current-difference n))
|
|
3120 (or no-recenter
|
|
3121 (ediff-recenter 'no-rehighlight)))
|
|
3122
|
|
3123 (emerge-eval-in-buffer
|
|
3124 ediff-A-buffer
|
|
3125 (setq buf-A-undo buffer-undo-list))
|
|
3126 (emerge-eval-in-buffer
|
|
3127 ediff-B-buffer
|
|
3128 (setq buf-B-undo buffer-undo-list))
|
|
3129
|
|
3130 (buffer-disable-undo ediff-A-buffer)
|
|
3131 (buffer-disable-undo ediff-B-buffer)
|
|
3132
|
|
3133 (unwind-protect ;; we don't want to lose undo info due to error
|
|
3134 (progn
|
|
3135 (or (eq flag 'select-only)
|
|
3136 (ediff-unselect-difference ediff-current-difference))
|
|
3137
|
|
3138 ;; Auto-save buffers while Ediff flags are temporarily removed.
|
|
3139 (emerge-eval-in-buffer
|
|
3140 ediff-A-buffer
|
|
3141 (if buf-A-modified
|
|
3142 (do-auto-save)))
|
|
3143 (emerge-eval-in-buffer
|
|
3144 ediff-B-buffer
|
|
3145 (if buf-B-modified
|
|
3146 (do-auto-save)))
|
|
3147
|
|
3148 (or (eq flag 'unselect-only)
|
|
3149 (ediff-select-difference n))
|
|
3150 (setq ediff-current-difference n)
|
|
3151 ) ;; end protected section
|
|
3152
|
|
3153 (emerge-eval-in-buffer
|
|
3154 control-buf
|
|
3155 (ediff-refresh-mode-line)
|
|
3156
|
|
3157 ;; restore undo and buffer-modified info
|
7267
|
3158 (emerge-eval-in-buffer
|
|
3159 ediff-A-buffer
|
7424
|
3160 (set-buffer-modified-p buf-A-modified)
|
|
3161 (setq buffer-undo-list buf-A-undo)))
|
|
3162
|
|
3163 (emerge-eval-in-buffer
|
|
3164 control-buf
|
7267
|
3165 (emerge-eval-in-buffer
|
|
3166 ediff-B-buffer
|
7424
|
3167 (set-buffer-modified-p buf-B-modified)
|
|
3168 (setq buffer-undo-list buf-B-undo))
|
|
3169 ))))
|
7267
|
3170
|
|
3171 ;; Revise the mode line to display which difference we have selected
|
|
3172
|
|
3173 (defun ediff-refresh-mode-line ()
|
|
3174 (setq mode-line-buffer-identification
|
7424
|
3175 (cond ((< ediff-current-difference 0)
|
|
3176 (list (format "Ediff: %%b At start: %d diffs"
|
|
3177 ediff-number-of-differences)))
|
|
3178 ((>= ediff-current-difference ediff-number-of-differences)
|
|
3179 (list (format "Ediff: %%b At end: %d diffs"
|
|
3180 ediff-number-of-differences)))
|
|
3181 (t
|
|
3182 (list (format "Ediff: %%b diff %d of %d"
|
|
3183 (1+ ediff-current-difference)
|
|
3184 ediff-number-of-differences)))))
|
7267
|
3185 ;; Force mode-line redisplay
|
|
3186 (set-buffer-modified-p (buffer-modified-p)))
|
|
3187
|
|
3188
|
|
3189
|
|
3190 ;; Verify that we have a difference selected.
|
|
3191 (defun ediff-validate-difference ()
|
|
3192 (if (not (and (>= ediff-current-difference 0)
|
|
3193 (< ediff-current-difference ediff-number-of-differences)))
|
|
3194 (error "No difference selected")))
|
|
3195
|
|
3196 (defun ediff-read-file-name (prompt default-dir default-file A-file)
|
7419
|
3197 ; This is a modified version of a similar function in `emerge.el'.
|
7267
|
3198 ; PROMPT should not have trailing ': ', so that it can be modified
|
|
3199 ; according to context.
|
|
3200 ; If both A-FILE and default-dir are set, the file constructed our of
|
|
3201 ; default-dir and the non-directory part of A-FILE is used as default and as
|
|
3202 ; initial input.
|
|
3203 ; If A-FILE is set (but default-dir is not), it is used as default and
|
|
3204 ; initial input.
|
|
3205 ; If default-file is set, it should be used as the default value.
|
|
3206 ; If default-dir is non-nil, use it as the default directory.
|
|
3207 ; Otherwise, use the value in Emacs's var default-directory.
|
7424
|
3208 (let (f)
|
|
3209 (setq f
|
|
3210 (cond
|
|
3211 ((and A-file default-dir)
|
|
3212 (read-file-name (format "%s (default %s%s): "
|
|
3213 prompt
|
|
3214 (abbreviate-file-name
|
|
3215 (expand-file-name default-dir))
|
|
3216 (file-name-nondirectory A-file))
|
|
3217 (expand-file-name default-dir)
|
|
3218 (concat (expand-file-name default-dir)
|
|
3219 (file-name-nondirectory A-file))
|
|
3220 'confirm (file-name-nondirectory A-file)))
|
|
3221 (A-file
|
|
3222 (read-file-name (format "%s (default %s): "
|
|
3223 prompt (file-name-nondirectory A-file))
|
|
3224 (expand-file-name (file-name-directory A-file))
|
|
3225 A-file
|
|
3226 'confirm (file-name-nondirectory A-file)))
|
|
3227 ;; If there is a default file, but no A-file, use it.
|
|
3228 (default-file
|
|
3229 (read-file-name (format "%s (default %s): " prompt default-file)
|
|
3230 default-dir;; if nil then default-directory.
|
|
3231 nil 'confirm))
|
|
3232 (t
|
|
3233 (read-file-name (concat prompt ": ")
|
|
3234 default-dir;; if nil then default-directory.
|
|
3235 nil 'confirm))))
|
|
3236 ;; If user enters a directory name, expand the default file in that
|
|
3237 ;; directory. This allows the user to enter a directory name for the
|
|
3238 ;; B-file and diff against the A-file in that directory instead of a DIRED
|
|
3239 ;; listing!
|
|
3240 (if (and (file-directory-p f)
|
|
3241 (or A-file default-file))
|
|
3242 (setq f (expand-file-name
|
|
3243 (file-name-nondirectory (or A-file default-file)) f)))
|
|
3244 f))
|
7267
|
3245
|
|
3246
|
7424
|
3247 ;; If `prefix' is given, then it is used as a prefix for the temp file
|
|
3248 ;; name. Otherwise, `.buffer-name' is used. If `file' is given, use this
|
|
3249 ;; file and don't create a new one.
|
|
3250 (defun ediff-make-temp-file (&optional prefix given-file)
|
|
3251 (let ((f (or given-file
|
|
3252 (make-temp-name (concat
|
|
3253 ediff-temp-file-prefix
|
|
3254 (or prefix
|
|
3255 (format
|
|
3256 ".%s"
|
|
3257 (file-name-nondirectory
|
|
3258 (buffer-name)))))))))
|
7267
|
3259 ;; create the file
|
7424
|
3260 (write-region (point-min) (point-max) f nil 'no-message)
|
7267
|
3261 (set-file-modes f ediff-temp-file-mode)
|
|
3262 f))
|
7424
|
3263
|
|
3264 ;; Quote metacharacters (using \) when executing diff in Unix, but not in
|
|
3265 ;; EMX OS/2
|
|
3266 (defun ediff-protect-metachars (str)
|
|
3267 (or (eq system-type 'emx)
|
|
3268 (let ((limit 0))
|
|
3269 (while (string-match emerge-metachars str limit)
|
|
3270 (setq str (concat (substring str 0 (match-beginning 0))
|
|
3271 "\\"
|
|
3272 (substring str (match-beginning 0))))
|
|
3273 (setq limit (1+ (match-end 0))))))
|
|
3274 str)
|
|
3275
|
|
3276
|
7267
|
3277 (defun ediff-block-write-file ()
|
|
3278 "Prevent writing files A and B directly."
|
|
3279 (if (ediff-check-for-ascii-flags)
|
|
3280 (error "Use 'wa' and 'wb' to save buffs A/B (first switch back to *ediff-control*.")))
|
|
3281
|
|
3282 (defun ediff-check-for-ascii-flags ()
|
|
3283 (eval
|
|
3284 (cons 'or
|
|
3285 (mapcar (function (lambda (buf)
|
|
3286 (emerge-eval-in-buffer
|
|
3287 buf
|
|
3288 (eq ediff-highlighting-style 'ascii))))
|
|
3289 ediff-this-buffer-control-sessions))))
|
|
3290
|
|
3291 (defun ediff-insert-in-front (overl beg end)
|
|
3292 "Capture overlays that had insertions in the front.
|
|
3293 Called when overlay OVERL gets insertion in front."
|
|
3294 (if (ediff-overlay-get overl 'ediff-diff-num)
|
|
3295 (setq ediff-disturbed-overlays
|
|
3296 (cons overl ediff-disturbed-overlays)))
|
|
3297 )
|
|
3298
|
|
3299 (defun ediff-collect-extents-lucid (pos)
|
|
3300 "Collects all extents at POS having property `ediff-diff-num'.
|
|
3301 Lucid Emacs causes headache by detaching empty extents, so I have to save
|
|
3302 them before they disappear."
|
|
3303 (let (lis elt)
|
|
3304 (while (setq elt (extent-at pos nil 'ediff-diff-num elt))
|
|
3305 (setq lis (cons elt lis)))
|
|
3306 (setq ediff-disturbed-overlays lis)))
|
|
3307
|
|
3308 (defun ediff-move-disturbed-overlays (posn)
|
|
3309 (mapcar (function (lambda (overl)
|
|
3310 (ediff-move-overlay overl
|
|
3311 posn
|
|
3312 (ediff-overlay-end overl))
|
|
3313 ))
|
|
3314 ediff-disturbed-overlays)
|
|
3315 (setq ediff-disturbed-overlays nil))
|
|
3316
|
|
3317 (defun ediff-adjust-disturbed-extents-lucid (posn &optional posn-type)
|
|
3318 ;; POSN-TYPE tells if POSN should become a new start of the extents
|
|
3319 ;; (if 'new-start) or a new end (if 'new-end). If POSN-TYPE is nil, then
|
|
3320 ;; POSN is both the new start and the new end.
|
|
3321 (mapcar (function (lambda (overl)
|
|
3322 (cond ((and (null posn-type)
|
|
3323 (equal (ediff-overlay-start overl)
|
|
3324 (ediff-overlay-end overl)))
|
|
3325 (ediff-move-overlay overl posn posn))
|
|
3326
|
|
3327 (posn-type
|
|
3328 (ediff-move-overlay
|
|
3329 overl
|
|
3330 (if (eq posn-type 'new-start)
|
|
3331 posn
|
|
3332 (ediff-overlay-start overl))
|
|
3333 (if (eq posn-type 'new-end)
|
|
3334 posn
|
|
3335 (ediff-overlay-end overl)))))))
|
|
3336 ediff-disturbed-overlays)
|
|
3337 (setq ediff-disturbed-overlays nil))
|
|
3338
|
|
3339 (defun ediff-save-buffer ()
|
|
3340 "Safe way of saving buffers A and B."
|
|
3341 (interactive)
|
|
3342 (let ((hooks local-write-file-hooks))
|
|
3343 (ediff-unselect-and-select-difference ediff-current-difference
|
|
3344 'unselect-only)
|
|
3345 (unwind-protect
|
|
3346 (emerge-eval-in-buffer
|
|
3347 (if (eq last-command-char ?a) ediff-A-buffer ediff-B-buffer)
|
|
3348 ;; temporarily remove writing block
|
|
3349 (setq hooks (delq 'ediff-block-write-file hooks))
|
|
3350 (let ((local-write-file-hooks hooks))
|
|
3351 (save-buffer)))
|
|
3352 (ediff-unselect-and-select-difference ediff-current-difference
|
|
3353 'select-only)
|
|
3354 )))
|
|
3355
|
|
3356
|
|
3357
|
7419
|
3358 ;; Essentially `emerge-remove-flags-in-buffer', modified to allow deletion
|
|
3359 ;; of read-only flags.
|
7267
|
3360 (defun ediff-remove-flags-from-buffer (buffer before-posn after-posn
|
|
3361 before-flag after-flag)
|
|
3362 (emerge-eval-in-buffer
|
|
3363 buffer
|
|
3364 (let ((buffer-read-only nil)
|
|
3365 (before-change-function nil)
|
|
3366 (inhibit-read-only t)
|
|
3367 (before-flag-length (length before-flag))
|
|
3368 (after-flag-length (length after-flag))
|
|
3369 )
|
|
3370 (goto-char after-posn)
|
|
3371 (setq after-posn (point-marker)) ;; after-posn is now a marker
|
|
3372 ;; remove the flags, if they're there
|
|
3373 (goto-char (- before-posn before-flag-length))
|
|
3374 (if (ediff-if-lucid)
|
|
3375 (ediff-collect-extents-lucid (+ (point) before-flag-length)))
|
|
3376 (if (looking-at (regexp-quote before-flag))
|
|
3377 (delete-region (point) (+ (point) before-flag-length))
|
|
3378 ;; the flag isn't there
|
|
3379 (ding)
|
|
3380 (message "Trouble removing ASCII flag"))
|
|
3381 (if (ediff-if-lucid)
|
|
3382 (ediff-adjust-disturbed-extents-lucid (point)))
|
|
3383
|
|
3384 (if (ediff-if-lucid)
|
|
3385 (ediff-collect-extents-lucid (point)))
|
|
3386 (goto-char after-posn)
|
|
3387 (if (looking-at (regexp-quote after-flag))
|
|
3388 (delete-region (point) (+ (point) after-flag-length))
|
|
3389 ;; the flag isn't there
|
|
3390 (ding)
|
|
3391 (message "Trouble removing ASCII flag"))
|
|
3392 (if (ediff-if-lucid)
|
|
3393 (ediff-adjust-disturbed-extents-lucid (point)))
|
|
3394 (setq after-posn nil) ;; after has become a marker--garbage-collect
|
|
3395 )))
|
|
3396
|
|
3397
|
7419
|
3398 ;; This is a modified `emerge-place-flags-in-buffer'.
|
7267
|
3399 (defun ediff-place-flags-in-buffer (buf-type buffer ctl-buffer difference)
|
|
3400 (emerge-eval-in-buffer
|
|
3401 buffer
|
|
3402 (ediff-place-flags-in-buffer1 buf-type ctl-buffer difference)))
|
|
3403
|
7419
|
3404 ;; Modified `emerge-place-flags-in-buffer1'.
|
7267
|
3405 (defun ediff-place-flags-in-buffer1 (buf-type ctl-buffer difference)
|
|
3406 (let ((buffer-read-only nil)
|
|
3407 (inhibit-read-only t)
|
|
3408 (before-change-function nil)
|
|
3409 (before-flag-name (if (eq buf-type 'A)
|
|
3410 'ediff-before-flag-A
|
|
3411 'ediff-before-flag-B))
|
|
3412 (after-flag-name (if (eq buf-type 'A)
|
|
3413 'ediff-after-flag-A
|
|
3414 'ediff-after-flag-B))
|
|
3415 beg-of-line flag)
|
|
3416
|
|
3417 ;; insert the flag before the difference
|
|
3418 (let ((before (ediff-get-diff-posn buf-type 'beg difference ctl-buffer)))
|
|
3419 (goto-char before)
|
|
3420 (setq beg-of-line (bolp))
|
|
3421
|
|
3422 (setq flag (emerge-eval-in-buffer
|
|
3423 ctl-buffer
|
|
3424 (if beg-of-line
|
|
3425 (set before-flag-name ediff-before-flag-bol)
|
|
3426 (set before-flag-name ediff-before-flag-mol))))
|
|
3427
|
|
3428 ;; insert the flag itself
|
|
3429 (if (ediff-if-lucid)
|
|
3430 (ediff-collect-extents-lucid (point)))
|
|
3431 (insert-before-markers flag)
|
|
3432 (if (ediff-if-lucid)
|
|
3433 ;; Lucid's extent end-points behave strangely; they won't
|
|
3434 ;; respect insert-before-markers
|
|
3435 (ediff-adjust-disturbed-extents-lucid (point) 'new-start))
|
|
3436 )
|
|
3437 ;; insert the flag after the difference
|
|
3438 (let* ((after (ediff-get-diff-posn buf-type 'end difference ctl-buffer)))
|
|
3439 (goto-char after)
|
|
3440 (setq beg-of-line (bolp))
|
|
3441
|
|
3442 (setq flag (emerge-eval-in-buffer
|
|
3443 ctl-buffer
|
|
3444 (if beg-of-line
|
|
3445 (set after-flag-name ediff-after-flag-bol)
|
|
3446 (set after-flag-name ediff-after-flag-mol))))
|
|
3447
|
|
3448 ;; insert the flag itself
|
|
3449 (if (ediff-if-lucid)
|
|
3450 (ediff-collect-extents-lucid (point)))
|
|
3451 (insert flag)
|
|
3452 (if (ediff-if-lucid)
|
|
3453 (ediff-adjust-disturbed-extents-lucid after 'new-end))
|
|
3454 )))
|
|
3455
|
|
3456
|
|
3457 (defun ediff-get-diff-posn (buf-type pos &optional n control-buf)
|
7419
|
3458 "Returns positions of difference sectors in the BUF-TYPE buffer.
|
|
3459 BUF-TYPE should be a symbol--either `A' or `B'.
|
|
3460 POS is either `beg' or `end'--it specifies whether you want the position at the
|
7424
|
3461 beginning of a difference or at the end.
|
7267
|
3462
|
7419
|
3463 The optional argument N says which difference \(default:
|
|
3464 `ediff-current-difference'\). The optional argument CONTROL-BUF says
|
|
3465 which control buffer is in effect in case it is not the current
|
|
3466 buffer."
|
7267
|
3467 (let (diff-overlay)
|
|
3468 (or control-buf
|
|
3469 (setq control-buf (current-buffer)))
|
|
3470
|
|
3471 (emerge-eval-in-buffer
|
|
3472 control-buf
|
|
3473 (or n (setq n ediff-current-difference))
|
|
3474 (if (or (< n 0) (>= n ediff-number-of-differences))
|
7424
|
3475 (if (> ediff-number-of-differences 0)
|
|
3476 (error "There is no diff %d. Valid diffs are 1 to %d."
|
|
3477 (1+ n) ediff-number-of-differences)
|
|
3478 (error "No differences found.")))
|
|
3479 (setq diff-overlay (ediff-get-diff-overlay n buf-type)))
|
|
3480
|
7267
|
3481 (if (ediff-overlay-get diff-overlay 'detached)
|
|
3482 (ediff-move-overlay diff-overlay
|
|
3483 (ediff-overlay-get diff-overlay 'ediff-marker)
|
|
3484 (ediff-overlay-get diff-overlay 'ediff-marker)))
|
|
3485 (if (eq pos 'beg)
|
|
3486 (ediff-overlay-start diff-overlay)
|
|
3487 (ediff-overlay-end diff-overlay))
|
|
3488 ))
|
|
3489
|
|
3490
|
|
3491
|
|
3492 ;; These would highlight differences under X
|
|
3493 (defun ediff-highlight-diff (n)
|
|
3494 "Put face on diff N. Invoked for X displays only."
|
|
3495 (let* ((last-A (emerge-eval-in-buffer ediff-A-buffer (point-max)))
|
|
3496 (last-B (emerge-eval-in-buffer ediff-B-buffer (point-max)))
|
|
3497 (begin-A (ediff-get-diff-posn 'A 'beg n))
|
|
3498 (end-A (ediff-get-diff-posn 'A 'end n))
|
|
3499 (xtraA (if (equal begin-A end-A) 1 0))
|
|
3500 (end-A-hilit (min last-A (+ end-A xtraA)))
|
|
3501
|
|
3502 (begin-B (ediff-get-diff-posn 'B 'beg n))
|
|
3503 (end-B (ediff-get-diff-posn 'B 'end n))
|
|
3504 (xtraB (if (equal begin-B end-B) 1 0))
|
|
3505 (end-B-hilit (min last-B (+ end-B xtraB))))
|
|
3506
|
|
3507 (if (ediff-if-lucid)
|
|
3508 (progn
|
|
3509 (ediff-move-overlay
|
|
3510 ediff-current-diff-overlay-A begin-A end-A-hilit)
|
|
3511 (ediff-move-overlay
|
|
3512 ediff-current-diff-overlay-B begin-B end-B-hilit))
|
7391
|
3513 ;; Emacs 19.22 has a bug, which requires that ediff-move-overlay will
|
|
3514 ;; have the buffer as a parameter. Believed fixed in 19.23.
|
7267
|
3515 (ediff-move-overlay ediff-current-diff-overlay-A
|
|
3516 begin-A end-A-hilit ediff-A-buffer)
|
|
3517 (ediff-move-overlay ediff-current-diff-overlay-B
|
|
3518 begin-B end-B-hilit ediff-B-buffer))
|
|
3519 ;; giving priority of 0 and then changing it may look funny, but
|
|
3520 ;; this is intended to overcome an Emacs bug.
|
|
3521 (ediff-overlay-put ediff-current-diff-overlay-A 'priority 0)
|
|
3522 (ediff-overlay-put ediff-current-diff-overlay-B 'priority 0)
|
|
3523 (ediff-overlay-put ediff-current-diff-overlay-A 'priority
|
|
3524 (ediff-highest-priority begin-A end-A-hilit ediff-A-buffer))
|
|
3525 (ediff-overlay-put ediff-current-diff-overlay-B 'priority
|
|
3526 (ediff-highest-priority begin-B end-B-hilit ediff-B-buffer))
|
|
3527
|
7424
|
3528 (or (face-differs-from-default-p 'ediff-odd-diff-face-A-var)
|
|
3529 (not ediff-highlight-all-diffs)
|
7267
|
3530 (progn
|
|
3531 (copy-face ediff-odd-diff-face-A 'ediff-odd-diff-face-A-var)
|
|
3532 (copy-face ediff-odd-diff-face-B 'ediff-odd-diff-face-B-var)
|
|
3533 (copy-face ediff-even-diff-face-A 'ediff-even-diff-face-A-var)
|
|
3534 (copy-face ediff-even-diff-face-B 'ediff-even-diff-face-B-var)))
|
|
3535
|
|
3536 ;; unhighlight the background overlay for the diff n so they won't
|
|
3537 ;; interfere with the current diff overlay
|
7424
|
3538 (ediff-overlay-put (ediff-get-diff-overlay n 'A) 'face nil)
|
|
3539 (ediff-overlay-put (ediff-get-diff-overlay n 'B) 'face nil)
|
7267
|
3540
|
|
3541 (sit-for 0) ;; needs to synch for some reason
|
|
3542 ))
|
|
3543
|
|
3544
|
|
3545 (defun ediff-unhighlight-diff ()
|
|
3546 "Remove overlays from buffers A and B."
|
|
3547
|
|
3548 (ediff-move-overlay ediff-current-diff-overlay-A 1 1)
|
|
3549 (ediff-move-overlay ediff-current-diff-overlay-B 1 1)
|
|
3550
|
|
3551 ;; rehighlight the overlay in the background of the
|
|
3552 ;; current difference region
|
7424
|
3553 (ediff-overlay-put (ediff-get-diff-overlay ediff-current-difference 'A)
|
7267
|
3554 'face (if (ediff-odd-p ediff-current-difference)
|
|
3555 'ediff-odd-diff-face-A-var
|
|
3556 'ediff-even-diff-face-A-var))
|
7424
|
3557 (ediff-overlay-put (ediff-get-diff-overlay ediff-current-difference 'B)
|
7267
|
3558 'face (if (ediff-odd-p ediff-current-difference)
|
|
3559 'ediff-odd-diff-face-B-var
|
|
3560 'ediff-even-diff-face-B-var))
|
|
3561 )
|
|
3562
|
|
3563
|
7424
|
3564 ;; delete highlighting overlays, restore faces to their original form
|
7267
|
3565 (defun ediff-unhighlight-diffs-totally ()
|
7424
|
3566 (setq buffer-read-only nil)
|
|
3567 (ediff-unselect-and-select-difference -1)
|
|
3568
|
7267
|
3569 (if (and window-system ediff-want-faces)
|
|
3570 (let ((inhibit-quit t))
|
|
3571 (if (face-differs-from-default-p 'ediff-odd-diff-face-A-var)
|
|
3572 (progn
|
|
3573 (copy-face 'default 'ediff-odd-diff-face-A-var)
|
|
3574 (copy-face 'default 'ediff-odd-diff-face-B-var)
|
|
3575 (copy-face 'default 'ediff-even-diff-face-A-var)
|
|
3576 (copy-face 'default 'ediff-even-diff-face-B-var)))
|
|
3577 (if (ediff-overlayp ediff-current-diff-overlay-A)
|
|
3578 (ediff-delete-overlay ediff-current-diff-overlay-A))
|
|
3579 (setq ediff-current-diff-overlay-A nil)
|
|
3580 (if (ediff-overlayp ediff-current-diff-overlay-B)
|
|
3581 (ediff-delete-overlay ediff-current-diff-overlay-B))
|
7424
|
3582 (setq ediff-current-diff-overlay-B nil)))
|
|
3583 )
|
|
3584
|
|
3585 (defun ediff-clear-diff-vector (vec &optional fin-diffs-also)
|
|
3586 ;; null out the difference overlays so they won't slow down future
|
|
3587 ;; editing operations
|
|
3588 (mapcar (function
|
|
3589 (lambda (elt)
|
|
3590 (ediff-delete-overlay (ediff-get-diff-overlay-from-vector elt 'A))
|
|
3591 (ediff-delete-overlay (ediff-get-diff-overlay-from-vector elt 'B))
|
|
3592 (if fin-diffs-also
|
|
3593 (ediff-clear-diff-vector
|
|
3594 (ediff-get-fine-diff-vector-from-vec elt)))
|
|
3595 ))
|
|
3596 vec)
|
|
3597 ;; allow them to be garbage collected
|
|
3598 (setq vec nil))
|
7267
|
3599
|
|
3600 (defun ediff-operate-on-flags (action)
|
7419
|
3601 "Re/unhighlights buffers A and B with all flags from all Ediff sessions.
|
|
3602 This is usually needed only when a
|
7267
|
3603 buffer is involved in multiple Ediff sessions."
|
|
3604 (let* ((A-sessions (emerge-eval-in-buffer
|
|
3605 ediff-A-buffer
|
|
3606 ediff-this-buffer-control-sessions))
|
|
3607 (B-sessions (emerge-eval-in-buffer
|
|
3608 ediff-B-buffer
|
|
3609 ediff-this-buffer-control-sessions))
|
|
3610 (sessions (ediff-union A-sessions B-sessions))
|
|
3611 (flag (if (eq action 'remove) 'unselect-only 'select-only)))
|
|
3612
|
|
3613 (mapcar (function (lambda (buf)
|
7424
|
3614 (if (ediff-buffer-live-p buf)
|
|
3615 (emerge-eval-in-buffer
|
|
3616 buf
|
|
3617 (or (if (eq action 'insert)
|
7267
|
3618 (memq ediff-highlighting-style '(ascii off))
|
7424
|
3619 (not (eq ediff-highlighting-style 'ascii)))
|
|
3620 (ediff-unselect-and-select-difference
|
|
3621 ediff-current-difference
|
|
3622 flag 'no-recenter))
|
|
3623 ))))
|
7267
|
3624 sessions)))
|
7424
|
3625
|
|
3626
|
|
3627
|
|
3628 ;;; Refinement of current diff
|
|
3629 ;; Split region along word boundaries. Each word will be on its own line.
|
|
3630 ;; Output to buffer out-buffer.
|
|
3631 (defun ediff-wordify (beg end in-buffer out-buffer)
|
|
3632 (let (sv-point string)
|
|
3633 (save-excursion
|
|
3634 (set-buffer in-buffer)
|
|
3635 (setq string (buffer-substring beg end))
|
|
3636
|
|
3637 (set-buffer out-buffer)
|
|
3638 (erase-buffer)
|
|
3639 (insert string)
|
|
3640 (goto-char (point-min))
|
|
3641 (skip-chars-forward ediff-whitespace)
|
|
3642 (delete-region (point-min) (point))
|
7267
|
3643
|
7424
|
3644 (while (or (> (skip-chars-forward ediff-word-1) 0)
|
|
3645 (> (skip-chars-forward ediff-word-2) 0))
|
|
3646
|
|
3647 (setq sv-point (point))
|
|
3648 (skip-chars-forward ediff-whitespace)
|
|
3649 (delete-region sv-point (point))
|
|
3650 (insert "\n")))))
|
|
3651
|
|
3652
|
|
3653 ;; `n' is the diff region to work on.
|
|
3654 ;; if `flag' is 'noforce then make fine-diffs only if this region's fine
|
|
3655 ;; diffs have not been computed before.
|
|
3656 ;; if `flag' is 'skip then don't compute fine diffs for this region.
|
|
3657 (defun ediff-make-fine-diffs (&optional n flag)
|
|
3658 (interactive)
|
|
3659 (if (not window-system)
|
|
3660 (error "Non-window system."))
|
|
3661 (or n (setq n ediff-current-difference))
|
|
3662
|
|
3663 (if (< ediff-number-of-differences 1)
|
|
3664 (error "No differences found."))
|
|
3665
|
|
3666 (let ((file-A ediff-temp-file-A)
|
|
3667 (file-B ediff-temp-file-B))
|
|
3668
|
|
3669 (cond ((and (eq flag 'noforce) (ediff-get-fine-diff-vector n))
|
|
3670 nil)
|
|
3671 ((eq flag 'skip)
|
|
3672 (or (ediff-get-fine-diff-vector n)
|
|
3673 (eq ediff-auto-refine 'off)
|
|
3674 (message "Region %d is larger than auto-refine limit. Hit %S to force-refine."
|
|
3675 (1+ n)
|
|
3676 (substitute-command-keys "\\[ediff-make-fine-diffs]")
|
|
3677 )))
|
|
3678 (t
|
|
3679 ;; delete old fine diffs
|
|
3680 (ediff-clear-diff-vector (ediff-get-fine-diff-vector n))
|
|
3681 ;; recompute fine diffs
|
|
3682 (setq ediff-tmp-buffer (get-buffer-create "*ediff-tmp*"))
|
|
3683
|
|
3684 (funcall ediff-wordify-function
|
|
3685 (ediff-get-diff-posn 'A 'beg n)
|
|
3686 (ediff-get-diff-posn 'A 'end n)
|
|
3687 ediff-A-buffer
|
|
3688 ediff-tmp-buffer)
|
|
3689 (emerge-eval-in-buffer
|
|
3690 ediff-tmp-buffer
|
|
3691 (setq file-A (ediff-make-temp-file ".fine-diffs-A" file-A)))
|
|
3692
|
|
3693 (funcall ediff-wordify-function
|
|
3694 (ediff-get-diff-posn 'B 'beg n)
|
|
3695 (ediff-get-diff-posn 'B 'end n)
|
|
3696 ediff-B-buffer
|
|
3697 ediff-tmp-buffer)
|
|
3698 (emerge-eval-in-buffer
|
|
3699 ediff-tmp-buffer
|
|
3700 (setq file-B (ediff-make-temp-file ".fine-diffs-B" file-B)))
|
|
3701
|
|
3702 ;; save temp file names.
|
|
3703 (setq ediff-temp-file-A file-A
|
|
3704 ediff-temp-file-B file-B)
|
|
3705
|
|
3706 ;; set the new vector of fine diffs, if none exists
|
|
3707 (ediff-set-fine-diff-vector
|
|
3708 n
|
|
3709 (ediff-setup-diff-regions file-A file-B 'use-old-diff-buf n
|
|
3710 ediff-fine-diff-program
|
|
3711 ediff-fine-diff-options
|
|
3712 ediff-fine-diff-ok-lines-regexp))
|
|
3713 (if (eq (length (ediff-get-fine-diff-vector n)) 0)
|
|
3714 (message "No differences found in region %d, except for white space and line breaks."
|
|
3715 (1+ n))))
|
|
3716 ) ;; end cond
|
|
3717 (ediff-set-fine-diff-properties n)
|
|
3718 ))
|
|
3719
|
|
3720
|
|
3721 (defun ediff-set-fine-diff-properties (n &optional default)
|
|
3722 (let ((fine-diff-vector (ediff-get-fine-diff-vector n))
|
|
3723 (face-A (if default 'default (face-name ediff-fine-diff-face-A)))
|
|
3724 (face-B (if default 'default (face-name ediff-fine-diff-face-B)))
|
|
3725 (priority-A (if default
|
|
3726 0
|
|
3727 (1+ (ediff-overlay-get ediff-current-diff-overlay-A
|
|
3728 'priority))))
|
|
3729 (priority-B (if default
|
|
3730 0
|
|
3731 (1+ (ediff-overlay-get ediff-current-diff-overlay-B
|
|
3732 'priority)))))
|
|
3733 (mapcar
|
|
3734 (function (lambda (vec)
|
|
3735 (ediff-overlay-put
|
|
3736 (ediff-get-diff-overlay-from-vector vec 'A)
|
|
3737 'face face-A)
|
|
3738 (ediff-overlay-put
|
|
3739 (ediff-get-diff-overlay-from-vector vec 'A)
|
|
3740 'priority priority-A)
|
|
3741
|
|
3742 (ediff-overlay-put
|
|
3743 (ediff-get-diff-overlay-from-vector vec 'B)
|
|
3744 'face face-B)
|
|
3745 (ediff-overlay-put
|
|
3746 (ediff-get-diff-overlay-from-vector vec 'B)
|
|
3747 'priority priority-B)
|
|
3748 ))
|
|
3749 fine-diff-vector)
|
|
3750 ))
|
|
3751
|
|
3752 (defun ediff-convert-diffs-to-overlays-refine (A-buffer B-buffer
|
|
3753 diff-list refine-region)
|
|
3754 (let* ((current-diff -1)
|
|
3755 (reg-A-start (ediff-get-diff-posn 'A 'beg refine-region))
|
|
3756 (reg-B-start (ediff-get-diff-posn 'B 'beg refine-region))
|
|
3757 diff-overlay-list list-element
|
|
3758 a-begin a-end b-begin b-end
|
|
3759 a-overlay b-overlay)
|
|
3760
|
|
3761 (emerge-eval-in-buffer A-buffer (goto-char reg-A-start))
|
|
3762 (emerge-eval-in-buffer B-buffer (goto-char reg-B-start))
|
|
3763
|
|
3764 (while diff-list
|
|
3765 (setq current-diff (1+ current-diff)
|
|
3766 list-element (car diff-list)
|
|
3767 a-begin (aref list-element 0)
|
|
3768 a-end (aref list-element 1)
|
|
3769 b-begin (aref list-element 2)
|
|
3770 b-end (aref list-element 3))
|
|
3771
|
|
3772 ;; place overlays at the appropriate places in the buffers
|
|
3773 (setq a-overlay (ediff-make-overlay
|
|
3774 (ediff-goto-word (1+ a-begin) A-buffer)
|
|
3775 (ediff-goto-word a-end A-buffer 'end)
|
|
3776 A-buffer))
|
|
3777
|
|
3778 (setq b-overlay (ediff-make-overlay
|
|
3779 (ediff-goto-word (1+ b-begin) B-buffer)
|
|
3780 (ediff-goto-word b-end B-buffer 'end)
|
|
3781 B-buffer))
|
|
3782
|
|
3783 ;; record all overlays for this difference
|
|
3784 (setq diff-overlay-list (nconc diff-overlay-list
|
|
3785 (list (vector a-overlay b-overlay)))
|
|
3786 diff-list (cdr diff-list))
|
|
3787 ) ;; while
|
|
3788 ;; convert the list of difference information into a vector for
|
|
3789 ;; fast access
|
|
3790 (apply 'vector diff-overlay-list)))
|
|
3791
|
|
3792 ;; goto word #n starting at current position in buffer `buf'
|
|
3793 ;; For ediff, a word is either a string of a-z,A-Z, incl `-' and `_';
|
|
3794 ;; or a string of other non-blanks. A blank is a \n\t\j
|
|
3795 ;; If `flag' is non-nil, goto the end of the n-th word.
|
|
3796 (defun ediff-goto-word (n buf &optional flag)
|
|
3797 (emerge-eval-in-buffer
|
|
3798 buf
|
|
3799 (skip-chars-forward ediff-whitespace)
|
|
3800 (while (> n 1)
|
|
3801 (or (> (skip-chars-forward ediff-word-1) 0)
|
|
3802 (> (skip-chars-forward ediff-word-2) 0))
|
|
3803 (skip-chars-forward ediff-whitespace)
|
|
3804 (setq n (1- n)))
|
|
3805 ;(if flag
|
|
3806 (if (and flag (> n 0))
|
|
3807 (or (> (skip-chars-forward ediff-word-1) 0)
|
|
3808 (> (skip-chars-forward ediff-word-2) 0)))
|
|
3809 (point)))
|
|
3810
|
|
3811
|
|
3812
|
|
3813
|
|
3814
|
|
3815 ;;; Misc
|
|
3816
|
7267
|
3817 (defun ediff-union (list1 list2)
|
|
3818 "Combine LIST1 and LIST2 using a set-union operation.
|
|
3819 The result list contains all items that appear in either LIST1 or LIST2.
|
|
3820 This is a non-destructive function; it makes a copy of the data if necessary
|
|
3821 to avoid corrupting the original LIST1 and LIST2.
|
7419
|
3822 This is a slightly simplified version from `cl-seq.el'. Added here to
|
7267
|
3823 avoid loading cl-*."
|
|
3824 (cond ((null list1) list2) ((null list2) list1)
|
|
3825 ((equal list1 list2) list1)
|
|
3826 (t
|
|
3827 (or (>= (length list1) (length list2))
|
|
3828 (setq list1 (prog1 list2 (setq list2 list1))))
|
|
3829 (while list2
|
|
3830 (or (memq (car list2) list1)
|
|
3831 (setq list1 (cons (car list2) list1)))
|
|
3832 (setq list2 (cdr list2)))
|
|
3833 list1)))
|
|
3834
|
7424
|
3835
|
|
3836 ;(defun ediff-debug ()
|
|
3837 ; (interactive)
|
|
3838 ; (with-output-to-temp-buffer "*ediff-debug*"
|
|
3839 ; (princ
|
|
3840 ; (format "Ctl buffer: %S\n\nediff-difference-vector:\n"
|
|
3841 ; ediff-control-buffer))
|
|
3842 ; (mapcar (function
|
|
3843 ; (lambda (overl-vec)
|
|
3844 ; (princ (format "Diff %d: %S %S %S\n\t %S %S %S\n"
|
|
3845 ; (1+ (ediff-overlay-get (aref overl-vec 0)
|
|
3846 ; 'ediff-diff-num))
|
|
3847 ; (ediff-overlay-get (aref overl-vec 0)
|
|
3848 ; 'ediff-control-buffer)
|
|
3849 ; (ediff-overlay-get (aref overl-vec 0)
|
|
3850 ; 'insert-in-front-hooks)
|
|
3851 ; (aref overl-vec 0)
|
|
3852 ; (ediff-overlay-get (aref overl-vec 1)
|
|
3853 ; 'ediff-control-buffer)
|
|
3854 ; (ediff-overlay-get (aref overl-vec 0)
|
|
3855 ; 'insert-in-front-hooks)
|
|
3856 ; (aref overl-vec 1)
|
|
3857 ; ))))
|
|
3858 ; ediff-difference-vector)
|
|
3859 ; (princ "\nediff-disturbed-overlays:\n")
|
|
3860 ; (mapcar (function
|
|
3861 ; (lambda (overl)
|
|
3862 ; (princ (format "%S %S\n"
|
|
3863 ; (ediff-overlay-get overl 'ediff-control-buffer)
|
|
3864 ; overl
|
|
3865 ; ))))
|
|
3866 ; ediff-disturbed-overlays)))
|
7267
|
3867
|
|
3868
|
|
3869 (run-hooks 'ediff-load-hooks)
|
|
3870
|
|
3871
|
|
3872 (provide 'ediff)
|
|
3873
|
|
3874 ;;; ediff.el ends here
|