This is the documentation for version 4 of "emerge.el", an Emacs package that allows you to combine two versions of a file by selecting, for each place where they differ, which version of the difference you prefer. It is similar to Sun's "filemerge". Written by Dale R. Worley . Copyright 1989, 1990, 1991 by Dale R. Worley. Do what you will with it. ;; LCD Archive Entry: ;; emerge|Dale R. Worley|drw@math.mit.edu ;; |File merge documentation ;; |91-12-13|version 4|~/packages/emerge.doc.Z - Changes from version 3 to version 4 More configuration variables are marked as user options. Code is included for an improved version of make-auto-save-file-name which eliminates many problems with the default version. See the documentation of emerge-make-auto-save-file-name to see how to activate it. Emerge now works with Gnu diff3, which can produce the groups of lines from the various files in the order 1, 2, 3 or 1, 3, 2. Added x f command to show what files or buffers are being operated on. The merge buffer now starts read-only, which being in fast mode it should be. When merging buffers, Emerge writes their contents into temporary files in the directory $TMPDIR (if it is defined), or /tmp by default. Added x j command to join two differences. Added x s command to split a difference into two differences. Added emerge-version variable and function to report the version of Emerge being run. Added x t command to trim unchanged lines off top and bottom of difference region. Added x d, x a, and x b commands to locate the differences at or near a given location in one of the buffers. Emerge no longer tries to copy the minor modes from the A buffer to the merge buffer, only the major mode. The programs executed to find the differences between versions of the file are no longer controlled by emerge-diff/diff3-command, but rather by: emerge-diff-program Variable: *Name of the program which compares two files. emerge-diff3-program Variable: *Name of the program which compares an ancestor file (first argument) and two variant files (second and third arguments). emerge-diff-options Variable: *Options to be passed to emerge-diff/diff3-program. The names of the files are expanded (see expand-file-name) before being passed to emerge-diff/diff3-program, so diff need not invoked under a shell that understands '~', for instance. If the diff/diff3 program reports errors, the user is notified and the errors are displayed. The command "0j" can be used to suppress the flags from showing in the buffers. A discussion of the effect of the merge flags on indentation of code has been added to the documentation. If kill-fix.el is loaded, Emerge control variables new have their 'preserved' property set, so setting the major mode in the merge buffer doesn't destroy Emerge's state. Added x c, x C, and x x commands to allow the A and B versions to be combined into #ifdef - #endif forms. Replaced calls of "ding" to calls of "error" where appropriate. Added x m command to allow major mode of merge buffer to be changed. Added x 1 command to shrink the merge window to one line. Added emerge-startup-hooks to allow customization. Fixed a bug that is activated when a remote merge request is made when the minibuffer window is selected. - Changes from version 2 to version 3 The directory into which temporary files are written is now controlled by a user option (emerge-temp-file-prefix). The A and B versions of the difference can be loaded into the kill ring with the "c a" and "c b" commands. The A and B versions of the difference can be inserted into the merge buffer with the "i a" and "i b" commands. The difference region of the merge buffer can be surrounded by the point and mark with the "m" command. The three windows can be scrolled together with the "^", "v", "<", ">", and "|" commands. The "s s" and "s a" commands report the state of the option in the echo area. Similarly, the "f" and "e" commands report what they do in the echo area. The "q" command has been revamped, and its behavior is now controlled by the manner in which Emerge is started. In particular, if you wish to write the merge buffer into a file upon exiting, invoke emerge-files[-with-ancestor] with a prefix argument, and it will prompt you for the file name. Then exiting will write the merge buffer to the file, unless "q" is given a prefix argument. The "i a" and "i b" commands now work in fast mode. The modifications that Emerge makes to save-buffer and write-file are described. Emerge now handles merging narrowed buffers correctly. Emerge now isn't fooled when the buffer visiting a file is not the same as the file on disk. - Starting To start Emerge, you must run one of four commands: emerge-files emerge-files-with-ancestor emerge-buffers emerge-buffers-with-ancestor The "files" versions prompt you for two file names (the "A" and "B" files), the "buffers" versions prompt you for two buffer names (the "A" and "B" buffers). Emerge then runs a "diff" of the two entities (emerge-buffers writes the buffers into temporary files for input to diff) and digests the output to form a list of the differences between the two files. Then three buffers are set up: two containing the entities (emerge-files does a find-file (C-x C-f) on the files to get them into buffers), and one, the "merge buffer", which contains the working copy of the merged file that you are constructing. The three buffers are put up in a nice three-window display, showing the A and B buffers in the upper half and the merge buffer in the lower half. The versions of the command that say "with-ancestor" ask for a third name, that of an entity which is a common ancestor from which the versions being merged were derived. These commands use "diff3" to compare all three versions. If one version of a difference agrees with the ancestor, then it is presumed that the other version is the "correct" version, and is said to be "preferred". (Note that if you use emerge-files, Emerge attempts to make sure that file on disk and the file in the buffer are the same. If the file on disk has been changed, Emerge offers to revert the buffer. If the buffer has been modified, Emerge offers to save the buffer. If the user declines the offer, or if the file on disk and the buffer have both been modified, Emerge aborts with an error message. Emerge is careful to widen the buffers containing the files if they have been narrowed. If you use emerge-buffers, the buffers are not widened -- only the visible portion is used.) During the merge, the A and B buffers are read-only, so you don't damage them. (This is because the A and B versions of the differences are extracted from these buffers.) When you quit the merge, the read-only/read-write status and modified flag on the A and B buffers are restored. In addition, auto-saving of the A and B buffers is suppressed during the merge. This is because Emerge modifies the A and B buffers to point out the text of the differences, and it would be useless to save these changes. (Just before suppressing auto-saving, Emerge forces an auto-save.) If you give a prefix argument to emerge-files or emerge-files-with-ancestor, it prompts you for another file name, which is the file into which the merged file is to be written when you exit Emerge. The output file name defaults to the A file name. If you successfully quit Emerge, the merge buffer will be written to the output file, and the buffers for the A, B, and ancestor buffers will be deleted (if they exist and are not modified). If you abort Emerge, the merge buffer will not be written and the buffers will not be deleted. You can have any number of merges going at once -- just don't use any one buffer as input to more than one merge at once, since that will cause the read-only/modified/auto-save status save-and-restore to screw up. Beware that when Emerge starts up, it does a diff or diff3 of the files, which can take many minutes for long files with many differences. Emacs can't do anything else until diff finishes. If diff or diff3 produces error messages, Emerge will beep and display the error messages instead of the merge buffer. There will be a message in the echo area giving the name of the merge buffer. Note that this is really just an informational message -- you still have switch to the merge buffer and abort the merge to restore the conditions before you ran Emerge. (Emerge considers any output line that does not match the regexp emerge-diff/diff3-ok-lines to be an error message.) After the merge has been set up, Emerge runs the hooks in emerge-startup-hooks. - Merging Once you have started the merge, you manipulate the merge buffer with special commands issued in the merge buffer. You may also edit the buffer with ordinary Emacs commands. Emerge keeps track of each difference between the A and B buffers and the corresponding section of the merge buffer. Initially, all differences show the A version, except those for which B is preferred (because A agrees with the ancestor), which show the B version. Emerge always has its attention focused on one particular difference, which is marked off in the three buffers by "vvvvvvvvvvvvvvvvvvvv" above and "^^^^^^^^^^^^^^^^^^^^" below. The number of the difference is shown in the mode line. A merge buffer can be in two modes: "fast" mode and "edit" mode. In fast mode, emerge commands are single characters, and ordinary Emacs commands are disabled. This makes Emerge operations fast, but prevents you from doing more than selecing the A or the B version of differences. In edit mode, all emerge commands must be prefixed with C-c, and all (non-conflicting) Emacs commands are available. This allows editing the merge buffer, but slows down Emerge operations. Edit and fast modes are indicated by "F" and "E" in the minor modes in the mode line. The Emerge commands are: p go to the previous difference n go to the next difference a select the A version of this difference b select the B version of this difference j go to a particular difference (prefix argument specifies which difference) (0j suppresses display of the flags) q quit - finish the merge* f go into fast mode e go into edit mode s a set/clear auto-advance mode* s s set/clear skip-prefers mode* l recenter (C-l) all three windows* - and 0 through 9 prefix numeric arguments d a select the A version as the default from here down in the merge buffer* d b select the B version as the default from here down in the merge buffer* c a copy the A version of the difference into the kill ring c b copy the B version of the difference into the kill ring i a insert the A version of the difference at the point i b insert the B version of the difference at the point m put the point and mark around the difference region ^ scroll-down (like M-v) the three windows* v scroll-up (like C-v) the three windows* < scroll-left (like C-x <) the three windows* > scroll-right (like C-x >) the three windows* | reset horizontal scroll on the three windows* x 1 shrink the merge window to one line (use C-u l to restore it to full size) x a find the difference containing a location in the A buffer* x b find the difference containing a location in the B buffer* x c combine the two versions of this difference* x C combine the two versions of this difference, using a register's value as the template* x d find the difference containing a location in the merge buffer* x f show the files/buffers Emerge is operating on in Help window (use C-u l to restore windows) x j join this difference with the following one (C-u x j joins this difference with the previous one) x l show line numbers of points in A, B, and merge buffers x m change major mode of merge buffer* x s split this difference into two differences (first position the point in all three buffers to the places to split the difference) x t trim identical lines off top and bottom of difference (such lines occur when the A and B versions are identical but differ from the ancestor version) x x set the template for the x c command* * - more details on these commands are given below emerge-version is a variable giving the version number of Emerge. It is also a function which displays emerge-version (when called interactively) or returns it (when called from a program). - Differences and their states A difference can have one of seven states: A: the difference is showing the A version. B: the difference is showing the B version. default-A and default-B: the difference is showing the A or B state, but has never been selected by the user. All differences start in the default-A state (and thus the merge buffer is a copy of the A buffer), except those for which one buffer or another is preferred. When the user selects the difference, it changes to the A or B state. prefer-A and prefer-B: the difference is showing the A or B state. In addition, the other buffer (that is, for prefer-A, the B buffer; for prefer-B, the A buffer) agrees with the ancestor buffer. Thus, presumably, the displayed version is the correct one. The "a" and "b" commands override these states, and turn them into the A and B states. combined: the difference is showing a combination of the A and B states that was constructed by the "x c" or "x C" commands. Since this state is neither the A or B states, the "a" and "b" commands won't alter the difference unless they are given a prefix argument. The state of the currently selected difference is shown in the mode line of the merge window: state display A A B B prefer-A A* prefer-B B* combined comb - Select default commands (d a and d b) The d a and d b commands change all default-A's to default-B's (or vice-versa) from the selected difference on down to the end of the file to default-A or default-B, respectively. (Since a difference that has been selected can not have state default-A or default-B, it will never be affected by d a or d b. This leads to the unexpected result that d a or d b never affects the difference selected at the moment, but prevents differences that you have already looked at from changing unexpectedly.) If you work your way down from the top of the file, using d a and d b at judicious points, you can effectivly make the A version the default for some sections of the merge buffer and the B version the default for others. - Exiting (q) The quit command finishes the merge session by restoring the state of the A and B buffers and removing the markers around the currently selected difference. It also disables the Emerge commands in the merge buffer, since executing them later could damage the contents of the various buffers. The action of "q" depends on how Emerge was started and whether "q" was given a prefix argument. If there was no prefix argument, it is considered a "successful" finish. If there was a prefix argument, it is considered an "unsuccessful" finish. In either case, you are asked to cofirm the exit, and the confirmation message tells which sort of exit you are confirming. If Emerge was started by some other process, success/failure is reported to the caller. If Emerge was started with emerge-files or emerge-files-with-ancestor, if a prefix argument was given to that command, then you specified a file into which the merge is to be written. A successful exit writes the merge into the output file and then kills the A, B, and ancestor buffers (so they aren't lying around to confuse you, since they probably all have similar names). - Auto-advance mode (s a) If auto-advance mode is set, the "a" and "b" commands perform an "n" (select next difference) afterward. When auto-advance mode is set, it is indicated by "A" in the minor modes in the mode line. "s a" with a positive argument sets auto-advance, with a non-positive argument clears it, and with no argument toggles it. - Skip-prefers mode (s s) If skip-prefers mode is set, the "n" and "p" commands skip over differences with states prefer-A and prefer-B. Thus you will only see differences for which one version isn't presumed "correct". When skip-prefers mode is set, it is indicated by "S" in the minor modes in the mode line. "s s" with a positive argument sets auto-advance, with a non-positive argument clears it, and with no argument toggles it. - Recenter (l) The Emerge "l" command causes the selected difference to be brought into view in the three windows, or at least, whichever of the three merge buffers are visible at the moment. If a prefix argument is given, then the original three-window display is set up before the difference texts are shown. - Scrolling the text (^, v, <, >, and |) Emerge has several commands which scroll all three windows by the same amount, thus allowing you to easily compare the versions of the text. The commands are "^" (scroll-up), "v" (scroll-down), "<" (scroll-left), ">" (scroll-right), and "|" (reset horizontal scrolling). (Remember that Emacs names scrolling commands by the motion of the text with respect to the window, so C-v is called "scroll-up".) If these commands (except "|") are given an argument, that is the number of lines or characters by which the windows are scrolled. Otherwise, the amount of motion is computed based on the dimensions of the merge buffer window -- the height of the merge buffer window (minus next-screen-context-lines), or half the width of the merge buffer window. (The A and B version windows are assumed to be as high as the merge window, but half as wide.) If the argument is just `C-u -', then the scrolling is half the default amount. - Finding the difference at or near a location (x d, x a, and x b) The "x d" command selects the difference containing the current point in the merge buffer. If there is no difference containing the point, an error is given. An argument can be given to the command to change this behavior: if the argument is positive (e.g., C-u), the next following difference is selected; if the argument is negative (e.g., C-u -), the previous difference is selected. The "x a" and "x b" commands select the difference containing the current point in the A and B buffers, respectively. Otherwise, they act like the "x d" command. Note that although the point used in the commands is not the merge buffer point, the commands can only be issued in the merge buffer, because it is the only buffer with the Emerge keymap. - Combining the two versions (x c, x C, and x x) Sometimes one wants to combine the two versions of a difference. For instance, when merging two versions of a program, one wants to make something like this: #ifdef NEW ...new version of code... #else /* NEW */ ...old version of code... #endif /* NEW */ The "x c" command will make such a combined version. (Note that any combined version is not the same as either the A or B versions, and so the "a" and "b" commands will refuse to alter it unless they are given a prefix argument.) The combination is made under control of a template, which is a character string with the following interpolations: %a the A version of the difference %b the B version of the difference %% the character '%' Thus, the template used above is #ifdef NEW\n%b#else /* NEW */\n%a#endif /* NEW */\n (using \n here to represent newlines). The template is stored in the variable emerge-combine-versions-template, and its initial value is the one given above. The template can be set (from the current region) by the "x x" command. (Be careful to get the newlines in the template in the right places!) ("x x" was chosen by analogy with "C-x x".) ("x x" is only available in the merge buffer, of course. Elsewhere, M-x emerge-set-combine-versions-template can be used.) If "x x" is given a prefix argument, emerge-combine-versions-template is localized in the merge buffer before its value is set, so the "x x" command's effect (and the effect of any later "x x" command in the merge buffer) is only on the merge buffer. The "x C" command is like "x c", but it prompts for a character which is the register whose value is to be used as the template. This allows one to use multiple templates conveniently. - Changing the major mode of the edit buffer (x m) The "x m" command prompts for the name of a major-mode-setting command and executes it. Ordinarily, major-mode-setting commands change the mode line and local keymap, so the "x m" command then resets the Emerge mode line and the fast or edit mode local keymap, as appropriate. If you have already changed the major mode of the merge buffer and lost the Emerge keymap, you can use M-x emerge-set-merge-mode to execute this command. Beware that "x m" accepts any command name, not just major-mode-setting commands. - Writing the merge buffer manually Emerge places a wrapper (emerge-query-and-call) on the key bindings of save-buffer (usually "C-x C-s") and write-file (usually "C-x C-w"), in order to protect the user from writing out the merge before it is finished. Emerge-query-and-call asks the user if he is sure he wants to write out the incomplete merge. If he answers yes, the buffer is written out. The flags are suppressed while the write is being done. As a result of this, the displayed portions of the buffers are recentered (equivalent to "l"). - Running Emerge standalone If you invoke emacs with the following arguments, you can execute Emerge as a standalone program: emacs -l emerge -f emerge-files-command file-a file-b file-out emacs -l emerge -f emerge-files-with-ancestor-command file-a file-b file-ancestor file-out When the user gives the "q" (quit) command, Emerge will write out the merge buffer in file-out and terminate Emacs. If a prefix argument is given, Emacs will terminate with an unsuccessful return code (1), if not, it will terminate with a successful return code (0). - Invoking Emerge remotely If you use the Emacs client/server code that supports remote execution, then you can invoke Emerge remotely by executing one of the Lisp calls: (emerge-files-remote "file A" "file B" "output file") (emerge-files-with-ancestor-remote "file A" "file B" "ancestor file" "output file") Returning a successful/unsuccessful return code is not yet supported by the Emacs client/server code. Beware that in systems of networked workstations, even though all user directories are shared between all the workstations, the /tmp directory on each workstation is not shared, so writing files into /tmp and then remotely invoking Emerge is not likely to work. - Effect of merge flags on indenting code The presence of the flags confuses the indentation code of C and Emacs-Lisp modes. Starting the flag strings (emerge-{before,after}-flag) with '#' (for C) or ';' (for Lisp) prevents the indentation code from noticing the flags. Remember to change the flag strings before loading Emerge, or to execute emerge-new-flags after changing them. But never change the flag strings while a merge is being performed. - Autoloading The following autoloads will make all top-level Emerge files autoloading. Make sure that "emerge" is in a directory on load-path. (autoload 'emerge-files "emerge" "Run Emerge on two files." t) (autoload 'emerge-files-with-ancestor "emerge" "Run Emerge on two files, giving another file as the ancestor." t) (autoload 'emerge-buffers "emerge" "Run Emerge on two buffers." t) (autoload 'emerge-buffers-with-ancestor "emerge" "Run Emerge on two buffers, giving another buffer as the ancestor." t) (autoload 'emerge-files-command "emerge") (autoload 'emerge-files-with-ancestor-command "emerge") (autoload 'emerge-files-remote "emerge") (autoload 'emerge-files-with-ancestor-remote "emerge")