aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard M. Stallman1993-05-13 19:25:37 +0000
committerRichard M. Stallman1993-05-13 19:25:37 +0000
commit737e38923add1348889ee8fd554b079665b0b16a (patch)
tree809fee93991bade225482fb05b5e4d3f1f18ce83
parent151e4b9ca8a693ed79d29f66be463392d4077d57 (diff)
downloademacs-737e38923add1348889ee8fd554b079665b0b16a.tar.gz
emacs-737e38923add1348889ee8fd554b079665b0b16a.zip
(emerge-count-matches-string): Renamed from count-matches-string.
(emerge-command-prefix): Now C-c C-c. emerge-shadow-key-definition): Deleted. Callers use substitute-key-definition. (emerge-recursively-substitute-key-definition): Deleted. Callers use substitute-key-definition. (emerge-unselect-hook): Renamed from emerge-unselect-hooks. (emerge-files-internal): Use file-local-copy to handle remote files. (emerge-files-with-ancestor-internal): Likewise. (emerge-remote-file-p): Deleted. (emerge-abort): New command. (describe-mode): Deleted. (emerge-hash-string-into-string): Renamed from hash-string-into-string. (emerge-unslashify-name): Renamed from unslashify-name. (emerge-write-and-delete): Don't write-file if file-out is nil.
-rw-r--r--lisp/emerge.el720
1 files changed, 364 insertions, 356 deletions
diff --git a/lisp/emerge.el b/lisp/emerge.el
index a9e76098f55..f17c744d266 100644
--- a/lisp/emerge.el
+++ b/lisp/emerge.el
@@ -1,7 +1,10 @@
1;;; Emacs subsystem to merge two files, version 5 beta 1;;; emerge.el --- merge diffs under Emacs control
2;;; Written by Dale R. Worley <drw@math.mit.edu>.
3 2
4;; WARRANTY DISCLAIMER 3;;; The author has placed this file in the public domain.
4
5;; Author: Dale R. Worley <drw@math.mit.edu>
6;; Version: 5fsf
7;; Keywords: unix, tools
5 8
6;; This software was created by Dale R. Worley and is 9;; This software was created by Dale R. Worley and is
7;; distributed free of charge. It is placed in the public domain and 10;; distributed free of charge. It is placed in the public domain and
@@ -16,19 +19,13 @@
16;; LOST DATA OR LOST PROFITS, OR FOR ANY SPECIAL, INCIDENTAL OR CONSEQUENTIAL 19;; LOST DATA OR LOST PROFITS, OR FOR ANY SPECIAL, INCIDENTAL OR CONSEQUENTIAL
17;; DAMAGES. 20;; DAMAGES.
18 21
19;; Declare that we've got the subsystem loaded 22;;; Code:
20(provide 'emerge)
21
22;; LCD Archive Entry:
23;; emerge|Dale R. Worley|drw@math.mit.edu
24;; |File merge
25;; |92-11-20|version 5 beta|~/packages/emerge.el.Z
26 23
27;;; Macros 24;;; Macros
28 25
29(defmacro emerge-eval-in-buffer (buffer &rest forms) 26(defmacro emerge-eval-in-buffer (buffer &rest forms)
30 "Macro to switch to BUFFER, evaluate FORMS, returns to original buffer. 27 "Macro to switch to BUFFER, evaluate FORMS, returns to original buffer.
31Differs from save-excursion in that it doesn't save the point and mark." 28Differs from `save-excursion' in that it doesn't save the point and mark."
32 (` (let ((StartBuffer (current-buffer))) 29 (` (let ((StartBuffer (current-buffer)))
33 (unwind-protect 30 (unwind-protect
34 (progn 31 (progn
@@ -37,10 +34,11 @@ Differs from save-excursion in that it doesn't save the point and mark."
37 (set-buffer StartBuffer))))) 34 (set-buffer StartBuffer)))))
38 35
39(defmacro emerge-defvar-local (var value doc) 36(defmacro emerge-defvar-local (var value doc)
40 "Defines SYMBOL as an advertised variable. Performs a defvar, then 37 "Defines SYMBOL as an advertised variable.
41executes make-variable-buffer-local on the variable. Also sets the 38Performs a defvar, then executes `make-variable-buffer-local' on
42'preserved' property, so that kill-all-local-variables (called by major-mode 39the variable. Also sets the `preserved' property, so that
43setting commands) won't destroy Emerge control variables." 40`kill-all-local-variables' (called by major-mode setting commands)
41won't destroy Emerge control variables."
44 (` (progn 42 (` (progn
45 (defvar (, var) (, value) (, doc)) 43 (defvar (, var) (, value) (, doc))
46 (make-variable-buffer-local '(, var)) 44 (make-variable-buffer-local '(, var))
@@ -58,28 +56,28 @@ setting commands) won't destroy Emerge control variables."
58 56
59;; We need to define this function so describe-mode can describe Emerge mode. 57;; We need to define this function so describe-mode can describe Emerge mode.
60(defun emerge-mode () 58(defun emerge-mode ()
61 "Emerge mode is used by the Emerge file-merging package. It is entered only 59 "Emerge mode is used by the Emerge file-merging package.
62through one of the functions: 60It is entered only through one of the functions:
63 emerge-files 61 `emerge-files'
64 emerge-files-with-ancestor 62 `emerge-files-with-ancestor'
65 emerge-buffers 63 `emerge-buffers'
66 emerge-buffers-with-ancestor 64 `emerge-buffers-with-ancestor'
67 emerge-files-command 65 `emerge-files-command'
68 emerge-files-with-ancestor-command 66 `emerge-files-with-ancestor-command'
69 emerge-files-remote 67 `emerge-files-remote'
70 emerge-files-with-ancestor-remote 68 `emerge-files-with-ancestor-remote'
71 69
72Commands: 70Commands:
73\\{emerge-basic-keymap} 71\\{emerge-basic-keymap}
74Commands must be prefixed by \\<emerge-fast-keymap>\\[emerge-basic-keymap] in 'edit' mode, but can be invoked directly 72Commands must be prefixed by \\<emerge-fast-keymap>\\[emerge-basic-keymap] in `edit' mode,
75in 'fast' mode.") 73but can be invoked directly in `fast' mode.")
76 74
77(defvar emerge-version "5" 75(defvar emerge-version "5fsf"
78 "The version of Emerge.") 76 "The version of Emerge.")
79 77
80(defun emerge-version () 78(defun emerge-version ()
81 "Return string describing the version of Emerge. When called interactively, 79 "Return string describing the version of Emerge.
82displays the version." 80When called interactively, displays the version."
83 (interactive) 81 (interactive)
84 (if (interactive-p) 82 (if (interactive-p)
85 (message "Emerge version %s" (emerge-version)) 83 (message "Emerge version %s" (emerge-version))
@@ -94,29 +92,29 @@ displays the version."
94;; are given is fixed. 92;; are given is fixed.
95;; The file names are always expanded (see expand-file-name) before being 93;; The file names are always expanded (see expand-file-name) before being
96;; passed to diff, thus they need not be invoked under a shell that 94;; passed to diff, thus they need not be invoked under a shell that
97;; understands '~'. 95;; understands `~'.
98;; The code which processes the diff/diff3 output depends on all the 96;; The code which processes the diff/diff3 output depends on all the
99;; finicky details of their output, including the somewhat strange 97;; finicky details of their output, including the somewhat strange
100;; way they number lines of a file. 98;; way they number lines of a file.
101(defvar emerge-diff-program "diff" 99(defvar emerge-diff-program "diff"
102 "*Name of the program which compares two files.") 100 "*Name of the program which compares two files.")
103(defvar emerge-diff3-program "diff3" 101(defvar emerge-diff3-program "diff3"
104 "*Name of the program which compares an ancestor file (first argument) 102 "*Name of the program which compares three files.
105and two variant files (second and third arguments).") 103Its arguments are the ancestor file and the two variant files.")
106(defvar emerge-diff-options "" 104(defvar emerge-diff-options ""
107 "*Options to be passed to emerge-diff/diff3-program.") 105 "*Options to pass to `emerge-diff-program' and `emerge-diff3-program'.")
108(defvar emerge-match-diff-line (let ((x "\\([0-9]+\\)\\(\\|,\\([0-9]+\\)\\)")) 106(defvar emerge-match-diff-line (let ((x "\\([0-9]+\\)\\(\\|,\\([0-9]+\\)\\)"))
109 (concat "^" x "\\([acd]\\)" x "$")) 107 (concat "^" x "\\([acd]\\)" x "$"))
110 "*Pattern to match lines produced by diff that describe differences (as 108 "*Pattern to match lines produced by diff that describe differences.
111opposed to lines from the source files).") 109This is as opposed to lines from the source files.")
112(defvar emerge-diff-ok-lines 110(defvar emerge-diff-ok-lines
113 "^\\([0-9,]+[acd][0-9,]+$\\|[<>] \\|---\\)" 111 "^\\([0-9,]+[acd][0-9,]+$\\|[<>] \\|---\\)"
114 "*Regexp that matches normal output lines from emerge-diff-program . 112 "*Regexp that matches normal output lines from `emerge-diff-program'.
115Lines that do not match are assumed to be error output.") 113Lines that do not match are assumed to be error messages.")
116(defvar emerge-diff3-ok-lines 114(defvar emerge-diff3-ok-lines
117 "^\\([1-3]:\\|====\\| \\)" 115 "^\\([1-3]:\\|====\\| \\)"
118 "*Regexp that matches normal output lines from emerge-diff3-program . 116 "*Regexp that matches normal output lines from `emerge-diff3-program'.
119Lines that do not match are assumed to be error output.") 117Lines that do not match are assumed to be error messages.")
120 118
121(defvar emerge-rcs-ci-program "ci" 119(defvar emerge-rcs-ci-program "ci"
122 "*Name of the program that checks in RCS revisions.") 120 "*Name of the program that checks in RCS revisions.")
@@ -124,69 +122,68 @@ Lines that do not match are assumed to be error output.")
124 "*Name of the program that checks out RCS revisions.") 122 "*Name of the program that checks out RCS revisions.")
125 123
126(defvar emerge-process-local-variables nil 124(defvar emerge-process-local-variables nil
127 "*Non-nil if Emerge should process the local-variables list in newly created 125 "*Non-nil if Emerge should process local-variables lists in merge buffers.
128merge buffers. (The local-variables list can be processed manually by 126\(You can explicitly request processing the local-variables
129executing \"(hack-local-variables)\".)") 127by executing `(hack-local-variables)'.)")
130(defvar emerge-execute-line-deletions nil 128(defvar emerge-execute-line-deletions nil
131 "*If non-nil: When emerge-execute-line discovers a situation which 129 "*If non-nil: `emerge-execute-line' makes no output if an input was deleted.
132appears to show that a file has been deleted from one version of the 130It concludes that an input version has been deleted when an ancestor entry
133files being merged (when an ancestor entry is present, only one 131is present, only one A or B entry is present, and an output entry is present.
134A or B entry is present, and an output entry is present), no output
135file will be created.
136If nil: In such circumstances, the A or B file that is present will be 132If nil: In such circumstances, the A or B file that is present will be
137copied to the designated output file.") 133copied to the designated output file.")
138 134
139;; Hook variables 135;; Hook variables
140 136
141(defvar emerge-startup-hooks nil 137(defvar emerge-startup-hook nil
142 "*Hooks to run in the merge buffer after the merge has been set up.") 138 "*Hook to run in the merge buffer after the merge has been set up.")
143(defvar emerge-select-hooks nil 139(defvar emerge-select-hook nil
144 "*Hooks to run after a difference has been selected. 140 "*Hook to run after a difference has been selected.
145`n' is the (internal) number of the difference.") 141The variable `n' holds the (internal) number of the difference.")
146(defvar emerge-unselect-hooks nil 142(defvar emerge-unselect-hook nil
147 "*Hooks to run after a difference has been unselected. 143 "*Hook to run after a difference has been unselected.
148`n' is the (internal) number of the difference.") 144The variable `n' holds the (internal) number of the difference.")
149 145
150;; Variables to control the default directories of the arguments to 146;; Variables to control the default directories of the arguments to
151;; Emerge commands. 147;; Emerge commands.
152 148
153(defvar emerge-default-last-directories nil 149(defvar emerge-default-last-directories nil
154 "*If nil, filenames for emerge-files-* commands complete in 150 "*If nil, default dir for filenames in emerge is `default-directory'.
155 default-directory (like an ordinary command).
156If non-nil, filenames complete in the directory of the last argument of the 151If non-nil, filenames complete in the directory of the last argument of the
157same type to an emerge-files-* command.") 152same type to an `emerge-files...' command.")
158 153
159(defvar emerge-last-dir-A nil 154(defvar emerge-last-dir-A nil
160 "Last directory for the first file of an emerge-files command.") 155 "Last directory for the first file of an `emerge-files...' command.")
161(defvar emerge-last-dir-B nil 156(defvar emerge-last-dir-B nil
162 "Last directory for the second file of an emerge-files command.") 157 "Last directory for the second file of an `emerge-files...' command.")
163(defvar emerge-last-dir-ancestor nil 158(defvar emerge-last-dir-ancestor nil
164 "Last directory for the ancestor file of an emerge-files command.") 159 "Last directory for the ancestor file of an `emerge-files...' command.")
165(defvar emerge-last-dir-output nil 160(defvar emerge-last-dir-output nil
166 "Last directory for the output file of an emerge-files command.") 161 "Last directory for the output file of an `emerge-files...' command.")
167(defvar emerge-last-revision-A nil 162(defvar emerge-last-revision-A nil
168 "Last RCS revision use for the first file of an emerge-revisions command.") 163 "Last RCS revision used for first file of an `emerge-revisions...' command.")
169(defvar emerge-last-revision-B nil 164(defvar emerge-last-revision-B nil
170 "Last RCS revision use for the second file of an emerge-revisions command.") 165 "Last RCS revision used for second file of an `emerge-revisions...' command.")
171(defvar emerge-last-revision-ancestor nil 166(defvar emerge-last-revision-ancestor nil
172 "Last RCS revision use for the ancestor file of an emerge-revisions command.") 167 "Last RCS revision used for ancestor file of an `emerge-revisions...' command.")
173 168
174;; The flags used to mark differences in the buffers. 169;; The flags used to mark differences in the buffers.
175 170
176;; These function definitions need to be up here, because they are used 171;; These function definitions need to be up here, because they are used
177;; during loading. 172;; during loading.
178(defun emerge-new-flags () 173(defun emerge-new-flags ()
179 "Function to be called after emerge-{before,after}-flag are changed to 174 "Function to be called after `emerge-{before,after}-flag'.
180compute values that depend on the flags." 175This is called after these functions are changed to compute values that
176depend on the flags."
181 (setq emerge-before-flag-length (length emerge-before-flag)) 177 (setq emerge-before-flag-length (length emerge-before-flag))
182 (setq emerge-before-flag-lines 178 (setq emerge-before-flag-lines
183 (count-matches-string emerge-before-flag "\n")) 179 (emerge-count-matches-string emerge-before-flag "\n"))
184 (setq emerge-before-flag-match (regexp-quote emerge-before-flag)) 180 (setq emerge-before-flag-match (regexp-quote emerge-before-flag))
185 (setq emerge-after-flag-length (length emerge-after-flag)) 181 (setq emerge-after-flag-length (length emerge-after-flag))
186 (setq emerge-after-flag-lines 182 (setq emerge-after-flag-lines
187 (count-matches-string emerge-after-flag "\n")) 183 (emerge-count-matches-string emerge-after-flag "\n"))
188 (setq emerge-after-flag-match (regexp-quote emerge-after-flag))) 184 (setq emerge-after-flag-match (regexp-quote emerge-after-flag)))
189(defun count-matches-string (string regexp) 185
186(defun emerge-count-matches-string (string regexp)
190 "Return the number of matches in STRING for REGEXP." 187 "Return the number of matches in STRING for REGEXP."
191 (let ((i 0) 188 (let ((i 0)
192 (count 0)) 189 (count 0))
@@ -221,18 +218,18 @@ displaying a difference.")
221 (setq d (substring d 0 -1))) 218 (setq d (substring d 0 -1)))
222 (concat d "/emerge")) 219 (concat d "/emerge"))
223 "*Prefix to put on Emerge temporary file names. 220 "*Prefix to put on Emerge temporary file names.
224Do not start with '~/' or '~user-name/'.") 221Do not start with `~/' or `~user-name/'.")
225 222
226(defvar emerge-temp-file-mode 384 ; u=rw only 223(defvar emerge-temp-file-mode 384 ; u=rw only
227 "*Mode for Emerge temporary files.") 224 "*Mode for Emerge temporary files.")
228 225
229(defvar emerge-combine-versions-template 226(defvar emerge-combine-versions-template
230 "#ifdef NEW\n%b#else /* NEW */\n%a#endif /* NEW */\n" 227 "#ifdef NEW\n%b#else /* NEW */\n%a#endif /* NEW */\n"
231 "*Template for emerge-combine-versions to combine the two versions. 228 "*Template for `emerge-combine-versions' to combine the two versions.
232The template is inserted as a string, with the following interpolations: 229The template is inserted as a string, with the following interpolations:
233 %a the A version of the difference 230 %a the A version of the difference
234 %b the B version of the difference 231 %b the B version of the difference
235 %% the character '%' 232 %% the character `%'
236Don't forget to end the template with a newline. 233Don't forget to end the template with a newline.
237Note that this variable can be made local to a particular merge buffer by 234Note that this variable can be made local to a particular merge buffer by
238giving a prefix argument to emerge-set-combine-versions-template .") 235giving a prefix argument to emerge-set-combine-versions-template .")
@@ -241,15 +238,15 @@ giving a prefix argument to emerge-set-combine-versions-template .")
241 238
242(defvar emerge-basic-keymap nil 239(defvar emerge-basic-keymap nil
243 "Keymap of Emerge commands. 240 "Keymap of Emerge commands.
244Directly available in 'fast' mode; 241Directly available in `fast' mode;
245must be prefixed by \\<emerge-fast-keymap>\\[emerge-basic-keymap] in 'edit' mode.") 242must be prefixed by \\<emerge-fast-keymap>\\[emerge-basic-keymap] in `edit' mode.")
246 243
247(defvar emerge-fast-keymap nil 244(defvar emerge-fast-keymap nil
248 "Local keymap used in Emerge 'fast' mode. 245 "Local keymap used in Emerge `fast' mode.
249Makes Emerge commands directly available.") 246Makes Emerge commands directly available.")
250 247
251(defvar emerge-command-prefix "\C-c" 248(defvar emerge-command-prefix "\C-c\C-c"
252 "*Command prefix for Emerge commands in 'edit' mode. 249 "*Command prefix for Emerge commands in `edit' mode.
253Must be set before Emerge is loaded.") 250Must be set before Emerge is loaded.")
254 251
255;; This function sets up the fixed keymaps. It is executed when the first 252;; This function sets up the fixed keymaps. It is executed when the first
@@ -309,10 +306,10 @@ Must be set before Emerge is loaded.")
309 ;; Allow emerge-fast-keymap to be referenced indirectly 306 ;; Allow emerge-fast-keymap to be referenced indirectly
310 (fset 'emerge-fast-keymap emerge-fast-keymap) 307 (fset 'emerge-fast-keymap emerge-fast-keymap)
311 ;; Suppress write-file and save-buffer 308 ;; Suppress write-file and save-buffer
312 (emerge-shadow-key-definition 'write-file 'emerge-query-write-file 309 (substitute-key-definition 'write-file 'emerge-query-write-file
313 (current-global-map) emerge-fast-keymap) 310 emerge-fast-keymap (current-global-map))
314 (emerge-shadow-key-definition 'save-buffer 'emerge-query-save-buffer 311 (substitute-key-definition 'save-buffer 'emerge-query-save-buffer
315 (current-global-map) emerge-fast-keymap)) 312 emerge-fast-keymap (current-global-map)))
316 313
317;; Variables which control each merge. They are local to the merge buffer. 314;; Variables which control each merge. They are local to the merge buffer.
318 315
@@ -389,23 +386,22 @@ the next difference.")
389(emerge-defvar-local emerge-skip-prefers nil 386(emerge-defvar-local emerge-skip-prefers nil
390 "*If non-nil, differences for which there is a preference are automatically 387 "*If non-nil, differences for which there is a preference are automatically
391skipped.") 388skipped.")
392(emerge-defvar-local emerge-quit-hooks nil 389(emerge-defvar-local emerge-quit-hook nil
393 "Hooks to run in the merge buffer after the merge has been finished. 390 "Hooks to run in the merge buffer after the merge has been finished.
394emerge-prefix-argument will be bound to the prefix argument of the emerge-quit 391`emerge-prefix-argument' will hold the prefix argument of the `emerge-quit'
395command. 392command.
396This is not a user option, since Emerge uses it for its own processing.") 393This is *not* a user option, since Emerge uses it for its own processing.")
397(emerge-defvar-local emerge-output-description nil 394(emerge-defvar-local emerge-output-description nil
398 "Describes output destination of the merge, for the use of 395 "Describes output destination of emerge, for `emerge-file-names'.")
399emerge-file-names.")
400 396
401;;; Setup functions for two-file mode. 397;;; Setup functions for two-file mode.
402 398
403(defun emerge-files-internal (file-A file-B &optional startup-hooks quit-hooks 399(defun emerge-files-internal (file-A file-B &optional startup-hooks quit-hooks
404 output-file) 400 output-file)
405 (if (not (file-readable-p file-A)) 401 (if (not (file-readable-p file-A))
406 (error "File '%s' does not exist or is not readable" file-A)) 402 (error "File `%s' does not exist or is not readable" file-A))
407 (if (not (file-readable-p file-B)) 403 (if (not (file-readable-p file-B))
408 (error "File '%s' does not exist or is not readable" file-B)) 404 (error "File `%s' does not exist or is not readable" file-B))
409 (let ((buffer-A (find-file-noselect file-A)) 405 (let ((buffer-A (find-file-noselect file-A))
410 (buffer-B (find-file-noselect file-B))) 406 (buffer-B (find-file-noselect file-B)))
411 ;; Record the directories of the files 407 ;; Record the directories of the files
@@ -417,29 +413,25 @@ emerge-file-names.")
417 (emerge-eval-in-buffer 413 (emerge-eval-in-buffer
418 buffer-A 414 buffer-A
419 (widen) 415 (widen)
420 (if (emerge-remote-file-p) 416 (let ((temp (file-local-copy file-A)))
421 (progn 417 (if temp
422 ;; Store in a local file 418 (setq file-A temp
423 (setq file-A (emerge-make-temp-file "A")) 419 startup-hooks
424 (write-region (point-min) (point-max) file-A nil 'no-message)
425 (setq startup-hooks
426 (cons (` (lambda () (delete-file (, file-A)))) 420 (cons (` (lambda () (delete-file (, file-A))))
427 startup-hooks))) 421 startup-hooks))
428 ;; Verify that the file matches the buffer 422 ;; Verify that the file matches the buffer
429 (emerge-verify-file-buffer))) 423 (emerge-verify-file-buffer))))
430 (emerge-eval-in-buffer 424 (emerge-eval-in-buffer
431 buffer-B 425 buffer-B
432 (widen) 426 (widen)
433 (if (emerge-remote-file-p) 427 (let ((temp (file-local-copy file-B)))
434 (progn 428 (if temp
435 ;; Store in a local file 429 (setq file-B temp
436 (setq file-B (emerge-make-temp-file "B")) 430 startup-hooks
437 (write-region (point-min) (point-max) file-B nil 'no-message)
438 (setq startup-hooks
439 (cons (` (lambda () (delete-file (, file-B)))) 431 (cons (` (lambda () (delete-file (, file-B))))
440 startup-hooks))) 432 startup-hooks))
441 ;; Verify that the file matches the buffer 433 ;; Verify that the file matches the buffer
442 (emerge-verify-file-buffer))) 434 (emerge-verify-file-buffer))))
443 (emerge-setup buffer-A file-A buffer-B file-B startup-hooks quit-hooks 435 (emerge-setup buffer-A file-A buffer-B file-B startup-hooks quit-hooks
444 output-file))) 436 output-file)))
445 437
@@ -474,12 +466,12 @@ emerge-file-names.")
474 (setq emerge-difference-list (emerge-make-diff-list file-A file-B)) 466 (setq emerge-difference-list (emerge-make-diff-list file-A file-B))
475 (setq emerge-number-of-differences (length emerge-difference-list)) 467 (setq emerge-number-of-differences (length emerge-difference-list))
476 (setq emerge-current-difference -1) 468 (setq emerge-current-difference -1)
477 (setq emerge-quit-hooks quit-hooks) 469 (setq emerge-quit-hook quit-hooks)
478 (emerge-remember-buffer-characteristics) 470 (emerge-remember-buffer-characteristics)
479 (emerge-handle-local-variables)) 471 (emerge-handle-local-variables))
480 (emerge-setup-windows buffer-A buffer-B merge-buffer t) 472 (emerge-setup-windows buffer-A buffer-B merge-buffer t)
481 (emerge-eval-in-buffer merge-buffer 473 (emerge-eval-in-buffer merge-buffer
482 (run-hooks 'startup-hooks 'emerge-startup-hooks) 474 (run-hooks 'startup-hooks 'emerge-startup-hook)
483 (setq buffer-read-only t)))) 475 (setq buffer-read-only t))))
484 476
485;; Generate the Emerge difference list between two files 477;; Generate the Emerge difference list between two files
@@ -554,14 +546,14 @@ emerge-file-names.")
554;;; Top-level and setup functions for three-file mode. 546;;; Top-level and setup functions for three-file mode.
555 547
556(defun emerge-files-with-ancestor-internal (file-A file-B file-ancestor 548(defun emerge-files-with-ancestor-internal (file-A file-B file-ancestor
557 &optional startup-hooks quit-hooks 549 &optional startup-hooks quit-hooks
558 output-file) 550 output-file)
559 (if (not (file-readable-p file-A)) 551 (if (not (file-readable-p file-A))
560 (error "File '%s' does not exist or is not readable" file-A)) 552 (error "File `%s' does not exist or is not readable" file-A))
561 (if (not (file-readable-p file-B)) 553 (if (not (file-readable-p file-B))
562 (error "File '%s' does not exist or is not readable" file-B)) 554 (error "File `%s' does not exist or is not readable" file-B))
563 (if (not (file-readable-p file-ancestor)) 555 (if (not (file-readable-p file-ancestor))
564 (error "File '%s' does not exist or is not readable" file-ancestor)) 556 (error "File `%s' does not exist or is not readable" file-ancestor))
565 (let ((buffer-A (find-file-noselect file-A)) 557 (let ((buffer-A (find-file-noselect file-A))
566 (buffer-B (find-file-noselect file-B)) 558 (buffer-B (find-file-noselect file-B))
567 (buffer-ancestor (find-file-noselect file-ancestor))) 559 (buffer-ancestor (find-file-noselect file-ancestor)))
@@ -575,42 +567,36 @@ emerge-file-names.")
575 (emerge-eval-in-buffer 567 (emerge-eval-in-buffer
576 buffer-A 568 buffer-A
577 (widen) 569 (widen)
578 (if (emerge-remote-file-p) 570 (let ((temp (file-local-copy file-A)))
579 (progn 571 (if temp
580 ;; Store in a local file 572 (setq file-A temp
581 (setq file-A (emerge-make-temp-file "A")) 573 startup-hooks
582 (write-region (point-min) (point-max) file-A nil 'no-message)
583 (setq startup-hooks
584 (cons (` (lambda () (delete-file (, file-A)))) 574 (cons (` (lambda () (delete-file (, file-A))))
585 startup-hooks))) 575 startup-hooks))
586 ;; Verify that the file matches the buffer 576 ;; Verify that the file matches the buffer
587 (emerge-verify-file-buffer))) 577 (emerge-verify-file-buffer))))
588 (emerge-eval-in-buffer 578 (emerge-eval-in-buffer
589 buffer-B 579 buffer-B
590 (widen) 580 (widen)
591 (if (emerge-remote-file-p) 581 (let ((temp (file-local-copy file-B)))
592 (progn 582 (if temp
593 ;; Store in a local file 583 (setq file-B temp
594 (setq file-B (emerge-make-temp-file "B")) 584 startup-hooks
595 (write-region (point-min) (point-max) file-B nil 'no-message)
596 (setq startup-hooks
597 (cons (` (lambda () (delete-file (, file-B)))) 585 (cons (` (lambda () (delete-file (, file-B))))
598 startup-hooks))) 586 startup-hooks))
599 ;; Verify that the file matches the buffer 587 ;; Verify that the file matches the buffer
600 (emerge-verify-file-buffer))) 588 (emerge-verify-file-buffer))))
601 (emerge-eval-in-buffer 589 (emerge-eval-in-buffer
602 buffer-ancestor 590 buffer-ancestor
603 (widen) 591 (widen)
604 (if (emerge-remote-file-p) 592 (let ((temp (file-local-copy file-ancestor)))
605 (progn 593 (if temp
606 ;; Store in a local file 594 (setq file-ancestor temp
607 (Setq file-ancestor (emerge-make-temp-file "anc")) 595 startup-hooks
608 (write-region (point-min) (point-max) file-ancestor nil 'no-message)
609 (setq startup-hooks
610 (cons (` (lambda () (delete-file (, file-ancestor)))) 596 (cons (` (lambda () (delete-file (, file-ancestor))))
611 startup-hooks))) 597 startup-hooks))
612 ;; Verify that the file matches the buffer 598 ;; Verify that the file matches the buffer
613 (emerge-verify-file-buffer))) 599 (emerge-verify-file-buffer))))
614 (emerge-setup-with-ancestor buffer-A file-A buffer-B file-B 600 (emerge-setup-with-ancestor buffer-A file-A buffer-B file-B
615 buffer-ancestor file-ancestor 601 buffer-ancestor file-ancestor
616 startup-hooks quit-hooks output-file))) 602 startup-hooks quit-hooks output-file)))
@@ -650,13 +636,13 @@ emerge-file-names.")
650 (emerge-make-diff3-list file-A file-B file-ancestor)) 636 (emerge-make-diff3-list file-A file-B file-ancestor))
651 (setq emerge-number-of-differences (length emerge-difference-list)) 637 (setq emerge-number-of-differences (length emerge-difference-list))
652 (setq emerge-current-difference -1) 638 (setq emerge-current-difference -1)
653 (setq emerge-quit-hooks quit-hooks) 639 (setq emerge-quit-hook quit-hooks)
654 (emerge-remember-buffer-characteristics) 640 (emerge-remember-buffer-characteristics)
655 (emerge-select-prefer-Bs) 641 (emerge-select-prefer-Bs)
656 (emerge-handle-local-variables)) 642 (emerge-handle-local-variables))
657 (emerge-setup-windows buffer-A buffer-B merge-buffer t) 643 (emerge-setup-windows buffer-A buffer-B merge-buffer t)
658 (emerge-eval-in-buffer merge-buffer 644 (emerge-eval-in-buffer merge-buffer
659 (run-hooks 'startup-hooks 'emerge-startup-hooks) 645 (run-hooks 'startup-hooks 'emerge-startup-hook)
660 (setq buffer-read-only t)))) 646 (setq buffer-read-only t))))
661 647
662;; Generate the Emerge difference list between two files with an ancestor 648;; Generate the Emerge difference list between two files with an ancestor
@@ -689,8 +675,11 @@ emerge-file-names.")
689 (if (not (string-equal agreement "1")) 675 (if (not (string-equal agreement "1"))
690 (setq list 676 (setq list
691 (cons 677 (cons
692 (let ((group-2 (emerge-get-diff3-group "2")) 678 (let (group-2 group-3 pos)
693 (group-3 (emerge-get-diff3-group "3"))) 679 (setq pos (point))
680 (setq group-2 (emerge-get-diff3-group "2"))
681 (goto-char pos)
682 (setq group-3 (emerge-get-diff3-group "3"))
694 (vector (car group-2) (car (cdr group-2)) 683 (vector (car group-2) (car (cdr group-2))
695 (car group-3) (car (cdr group-3)) 684 (car group-3) (car (cdr group-3))
696 (cond ((string-equal agreement "2") 'prefer-A) 685 (cond ((string-equal agreement "2") 'prefer-A)
@@ -728,6 +717,7 @@ emerge-file-names.")
728 717
729;;; Functions to start Emerge on files 718;;; Functions to start Emerge on files
730 719
720;;;###autoload
731(defun emerge-files (arg file-A file-B file-out &optional startup-hooks 721(defun emerge-files (arg file-A file-B file-out &optional startup-hooks
732 quit-hooks) 722 quit-hooks)
733 "Run Emerge on two files." 723 "Run Emerge on two files."
@@ -742,12 +732,13 @@ emerge-file-names.")
742 f f))))) 732 f f)))))
743 (emerge-files-internal 733 (emerge-files-internal
744 file-A file-B startup-hooks 734 file-A file-B startup-hooks
745 (if arg 735 (if file-out
746 (cons (` (lambda () (emerge-files-exit (, file-out)))) 736 (cons (` (lambda () (emerge-files-exit (, file-out))))
747 quit-hooks) 737 quit-hooks)
748 quit-hooks) 738 quit-hooks)
749 file-out)) 739 file-out))
750 740
741;;;###autoload
751(defun emerge-files-with-ancestor (arg file-A file-B file-ancestor file-out 742(defun emerge-files-with-ancestor (arg file-A file-B file-ancestor file-out
752 &optional startup-hooks quit-hooks) 743 &optional startup-hooks quit-hooks)
753 "Run Emerge on two files, giving another file as the ancestor." 744 "Run Emerge on two files, giving another file as the ancestor."
@@ -764,7 +755,7 @@ emerge-file-names.")
764 f f))))) 755 f f)))))
765 (emerge-files-with-ancestor-internal 756 (emerge-files-with-ancestor-internal
766 file-A file-B file-ancestor startup-hooks 757 file-A file-B file-ancestor startup-hooks
767 (if arg 758 (if file-out
768 (cons (` (lambda () (emerge-files-exit (, file-out)))) 759 (cons (` (lambda () (emerge-files-exit (, file-out))))
769 quit-hooks) 760 quit-hooks)
770 quit-hooks) 761 quit-hooks)
@@ -778,6 +769,7 @@ emerge-file-names.")
778 769
779;;; Functions to start Emerge on buffers 770;;; Functions to start Emerge on buffers
780 771
772;;;###autoload
781(defun emerge-buffers (buffer-A buffer-B &optional startup-hooks quit-hooks) 773(defun emerge-buffers (buffer-A buffer-B &optional startup-hooks quit-hooks)
782 "Run Emerge on two buffers." 774 "Run Emerge on two buffers."
783 (interactive "bBuffer A to merge: \nbBuffer B to merge: ") 775 (interactive "bBuffer A to merge: \nbBuffer B to merge: ")
@@ -798,6 +790,7 @@ emerge-file-names.")
798 quit-hooks 790 quit-hooks
799 nil))) 791 nil)))
800 792
793;;;###autoload
801(defun emerge-buffers-with-ancestor (buffer-A buffer-B buffer-ancestor 794(defun emerge-buffers-with-ancestor (buffer-A buffer-B buffer-ancestor
802 &optional startup-hooks 795 &optional startup-hooks
803 quit-hooks) 796 quit-hooks)
@@ -832,6 +825,7 @@ emerge-file-names.")
832 825
833;;; Functions to start Emerge from the command line 826;;; Functions to start Emerge from the command line
834 827
828;;;###autoload
835(defun emerge-files-command () 829(defun emerge-files-command ()
836 (let ((file-a (nth 0 command-line-args-left)) 830 (let ((file-a (nth 0 command-line-args-left))
837 (file-b (nth 1 command-line-args-left)) 831 (file-b (nth 1 command-line-args-left))
@@ -841,6 +835,7 @@ emerge-file-names.")
841 file-a file-b nil 835 file-a file-b nil
842 (list (` (lambda () (emerge-command-exit (, file-out)))))))) 836 (list (` (lambda () (emerge-command-exit (, file-out))))))))
843 837
838;;;###autoload
844(defun emerge-files-with-ancestor-command () 839(defun emerge-files-with-ancestor-command ()
845 (let (file-a file-b file-anc file-out) 840 (let (file-a file-b file-anc file-out)
846 ;; check for a -a flag, for filemerge compatibility 841 ;; check for a -a flag, for filemerge compatibility
@@ -868,6 +863,7 @@ emerge-file-names.")
868 863
869;;; Functions to start Emerge via remote request 864;;; Functions to start Emerge via remote request
870 865
866;;;###autoload
871(defun emerge-files-remote (file-a file-b file-out) 867(defun emerge-files-remote (file-a file-b file-out)
872 (setq emerge-file-out file-out) 868 (setq emerge-file-out file-out)
873 (emerge-files-internal 869 (emerge-files-internal
@@ -876,6 +872,7 @@ emerge-file-names.")
876 file-out) 872 file-out)
877 (throw 'client-wait nil)) 873 (throw 'client-wait nil))
878 874
875;;;###autoload
879(defun emerge-files-with-ancestor-remote (file-a file-b file-anc file-out) 876(defun emerge-files-with-ancestor-remote (file-a file-b file-anc file-out)
880 (setq emerge-file-out file-out) 877 (setq emerge-file-out file-out)
881 (emerge-files-with-ancestor-internal 878 (emerge-files-with-ancestor-internal
@@ -914,8 +911,7 @@ emerge-file-names.")
914 revision-B ancestor 911 revision-B ancestor
915 &optional 912 &optional
916 startup-hooks quit-hooks) 913 startup-hooks quit-hooks)
917 "Emerge two RCS revisions of a file, giving another revision as 914 "Emerge two RCS revisions of a file, with another revision as ancestor."
918the ancestor."
919 (interactive 915 (interactive
920 (list current-prefix-arg 916 (list current-prefix-arg
921 (read-file-name "File to merge: " nil nil 'confirm) 917 (read-file-name "File to merge: " nil nil 'confirm)
@@ -1021,17 +1017,17 @@ the ancestor."
1021;;; Function to start Emerge based on a line in a file 1017;;; Function to start Emerge based on a line in a file
1022 1018
1023(defun emerge-execute-line () 1019(defun emerge-execute-line ()
1024 "Process the current line, looking for entries of the form: 1020 "Run Emerge using files named in current text line.
1021Looks in that line for whitespace-separated entries of these forms:
1025 a=file1 1022 a=file1
1026 b=file2 1023 b=file2
1027 ancestor=file3 1024 ancestor=file3
1028 output=file4 1025 output=file4
1029seperated by whitespace. Based on entries found, call emerge correctly 1026to specify the files to use in Emerge.
1030on the files files listed.
1031 1027
1032In addition, if only one of \"a=file\" or \"b=file\" is present, and \"output=file\" 1028In addition, if only one of `a=file' or `b=file' is present, and `output=file'
1033is present: 1029is present:
1034If emerge-execute-line-deletions is non-nil and \"ancestor=file\" is present, 1030If `emerge-execute-line-deletions' is non-nil and `ancestor=file' is present,
1035it is assumed that the file in question has been deleted, and it is 1031it is assumed that the file in question has been deleted, and it is
1036not copied to the output file. 1032not copied to the output file.
1037Otherwise, the A or B file present is copied to the output file." 1033Otherwise, the A or B file present is copied to the output file."
@@ -1061,19 +1057,19 @@ Otherwise, the A or B file present is copied to the output file."
1061 (cond 1057 (cond
1062 ((string-equal tag "a") 1058 ((string-equal tag "a")
1063 (if file-A 1059 (if file-A
1064 (error "This line has two 'A' entries")) 1060 (error "This line has two `A' entries"))
1065 (setq file-A file)) 1061 (setq file-A file))
1066 ((string-equal tag "b") 1062 ((string-equal tag "b")
1067 (if file-B 1063 (if file-B
1068 (error "This line has two 'B' entries")) 1064 (error "This line has two `B' entries"))
1069 (setq file-B file)) 1065 (setq file-B file))
1070 ((or (string-equal tag "anc") (string-equal tag "ancestor")) 1066 ((or (string-equal tag "anc") (string-equal tag "ancestor"))
1071 (if file-ancestor 1067 (if file-ancestor
1072 (error "This line has two 'ancestor' entries")) 1068 (error "This line has two `ancestor' entries"))
1073 (setq file-ancestor file)) 1069 (setq file-ancestor file))
1074 ((or (string-equal tag "out") (string-equal tag "output")) 1070 ((or (string-equal tag "out") (string-equal tag "output"))
1075 (if file-out 1071 (if file-out
1076 (error "This line has two 'output' entries")) 1072 (error "This line has two `output' entries"))
1077 (setq file-out file)) 1073 (setq file-out file))
1078 (t 1074 (t
1079 (error "Unrecognized entry")))) 1075 (error "Unrecognized entry"))))
@@ -1081,9 +1077,9 @@ Otherwise, the A or B file present is copied to the output file."
1081 (error "Unparseable entry"))) 1077 (error "Unparseable entry")))
1082 ;; Make sure that file-A and file-B are present 1078 ;; Make sure that file-A and file-B are present
1083 (if (not (or (and file-A file-B) file-out)) 1079 (if (not (or (and file-A file-B) file-out))
1084 (error "Must have both 'A' and 'B' entries")) 1080 (error "Must have both `A' and `B' entries"))
1085 (if (not (or file-A file-B)) 1081 (if (not (or file-A file-B))
1086 (error "Must have 'A' or 'B' entry")) 1082 (error "Must have `A' or `B' entry"))
1087 ;; Go to the beginning of the next line, so next execution will use 1083 ;; Go to the beginning of the next line, so next execution will use
1088 ;; next line in buffer. 1084 ;; next line in buffer.
1089 (beginning-of-line 2) 1085 (beginning-of-line 2)
@@ -1124,7 +1120,7 @@ Otherwise, the A or B file present is copied to the output file."
1124;;; Sample function for creating information for emerge-execute-line 1120;;; Sample function for creating information for emerge-execute-line
1125 1121
1126(defvar emerge-merge-directories-filename-regexp "[^.]" 1122(defvar emerge-merge-directories-filename-regexp "[^.]"
1127 "Regexp describing files to be processed by emerge-merge-directories.") 1123 "Regexp describing files to be processed by `emerge-merge-directories'.")
1128 1124
1129(defun emerge-merge-directories (a-dir b-dir ancestor-dir output-dir) 1125(defun emerge-merge-directories (a-dir b-dir ancestor-dir output-dir)
1130 (interactive 1126 (interactive
@@ -1247,25 +1243,26 @@ Otherwise, the A or B file present is copied to the output file."
1247 (emerge-force-define-key emerge-edit-keymap emerge-command-prefix 1243 (emerge-force-define-key emerge-edit-keymap emerge-command-prefix
1248 'emerge-basic-keymap) 1244 'emerge-basic-keymap)
1249 ;; Suppress write-file and save-buffer 1245 ;; Suppress write-file and save-buffer
1250 (emerge-recursively-substitute-key-definition 'write-file 1246 (substitute-key-definition 'write-file
1251 'emerge-query-write-file 1247 'emerge-query-write-file
1252 emerge-edit-keymap) 1248 emerge-edit-keymap)
1253 (emerge-recursively-substitute-key-definition 'save-buffer 1249 (substitute-key-definition 'save-buffer
1254 'emerge-query-save-buffer 1250 'emerge-query-save-buffer
1255 emerge-edit-keymap) 1251 emerge-edit-keymap)
1256 (emerge-shadow-key-definition 'write-file 'emerge-query-write-file 1252 (substitute-key-definition 'write-file 'emerge-query-write-file
1257 (current-global-map) emerge-edit-keymap) 1253 emerge-edit-keymap (current-global-map))
1258 (emerge-shadow-key-definition 'save-buffer 'emerge-query-save-buffer 1254 (substitute-key-definition 'save-buffer 'emerge-query-save-buffer
1259 (current-global-map) emerge-edit-keymap) 1255 emerge-edit-keymap (current-global-map))
1260 (use-local-map emerge-fast-keymap) 1256 (use-local-map emerge-fast-keymap)
1261 (setq emerge-edit-mode nil) 1257 (setq emerge-edit-mode nil)
1262 (setq emerge-fast-mode t)) 1258 (setq emerge-fast-mode t))
1263 1259
1264(defun emerge-remember-buffer-characteristics () 1260(defun emerge-remember-buffer-characteristics ()
1265 "Must be called in the merge buffer. Remembers certain properties of the 1261 "Record certain properties of the buffers being merged.
1266buffers being merged (read-only, modified, auto-save), and saves them in 1262Must be called in the merge buffer. Remembers read-only, modified,
1267buffer local variables. Sets the buffers read-only and turns off auto-save. 1263auto-save, and saves them in buffer local variables. Sets the buffers
1268These characteristics are restored by emerge-restore-buffer-characteristics." 1264read-only and turns off `auto-save-mode'.
1265These characteristics are restored by `emerge-restore-buffer-characteristics'."
1269 ;; force auto-save, because we will turn off auto-saving in buffers for the 1266 ;; force auto-save, because we will turn off auto-saving in buffers for the
1270 ;; duration 1267 ;; duration
1271 (do-auto-save) 1268 (do-auto-save)
@@ -1286,8 +1283,7 @@ These characteristics are restored by emerge-restore-buffer-characteristics."
1286 emerge-merging-values))))) 1283 emerge-merging-values)))))
1287 1284
1288(defun emerge-restore-buffer-characteristics () 1285(defun emerge-restore-buffer-characteristics ()
1289 "Restores the characteristics remembered by 1286 "Restores characteristics saved by `emerge-remember-buffer-characteristics'."
1290emerge-remember-buffer-characteristics."
1291 (let ((A-values emerge-A-buffer-values) 1287 (let ((A-values emerge-A-buffer-values)
1292 (B-values emerge-B-buffer-values)) 1288 (B-values emerge-B-buffer-values))
1293 (emerge-eval-in-buffer emerge-A-buffer 1289 (emerge-eval-in-buffer emerge-A-buffer
@@ -1397,14 +1393,15 @@ emerge-remember-buffer-characteristics."
1397 (not (buffer-modified-p emerge-ancestor-buffer))) 1393 (not (buffer-modified-p emerge-ancestor-buffer)))
1398 (kill-buffer emerge-ancestor-buffer)) 1394 (kill-buffer emerge-ancestor-buffer))
1399 ;; Write merge buffer to file 1395 ;; Write merge buffer to file
1400 (write-file file-out)) 1396 (and file-out
1397 (write-file file-out)))
1401 1398
1402;;; Commands 1399;;; Commands
1403 1400
1404(defun emerge-recenter (&optional arg) 1401(defun emerge-recenter (&optional arg)
1405 "Bring the highlighted region of all three merge buffers into view, 1402 "Bring the highlighted region of all three merge buffers into view.
1406if they are in windows. If an ARGUMENT is given, the default three-window 1403This brings the buffers into view if they are in windows.
1407display is reestablished." 1404With an argument, reestablish the default three-window display."
1408 (interactive "P") 1405 (interactive "P")
1409 ;; If there is an argument, rebuild the window structure 1406 ;; If there is an argument, rebuild the window structure
1410 (if arg 1407 (if arg
@@ -1480,9 +1477,9 @@ display is reestablished."
1480 1477
1481(defun emerge-scroll-up (&optional arg) 1478(defun emerge-scroll-up (&optional arg)
1482 "Scroll up all three merge buffers, if they are in windows. 1479 "Scroll up all three merge buffers, if they are in windows.
1483If an ARGUMENT is given, that is how many lines are scrolled, else nearly 1480With argument N, scroll N lines; otherwise scroll by nearly
1484the size of the merge window. `C-u -' alone as argument scrolls half the 1481the height of the merge window.
1485size of the merge window." 1482`C-u -' alone as argument scrolls half the height of the merge window."
1486 (interactive "P") 1483 (interactive "P")
1487 (emerge-operate-on-windows 1484 (emerge-operate-on-windows
1488 'scroll-up 1485 'scroll-up
@@ -1507,9 +1504,9 @@ size of the merge window."
1507 1504
1508(defun emerge-scroll-down (&optional arg) 1505(defun emerge-scroll-down (&optional arg)
1509 "Scroll down all three merge buffers, if they are in windows. 1506 "Scroll down all three merge buffers, if they are in windows.
1510If an ARGUMENT is given, that is how many lines are scrolled, else nearly 1507With argument N, scroll N lines; otherwise scroll by nearly
1511the size of the merge window. `C-u -' alone as argument scrolls half the 1508the height of the merge window.
1512size of the merge window." 1509`C-u -' alone as argument scrolls half the height of the merge window."
1513 (interactive "P") 1510 (interactive "P")
1514 (emerge-operate-on-windows 1511 (emerge-operate-on-windows
1515 'scroll-down 1512 'scroll-down
@@ -1534,7 +1531,7 @@ size of the merge window."
1534 1531
1535(defun emerge-scroll-left (&optional arg) 1532(defun emerge-scroll-left (&optional arg)
1536 "Scroll left all three merge buffers, if they are in windows. 1533 "Scroll left all three merge buffers, if they are in windows.
1537If an ARGUMENT is given, that is how many columns are scrolled, else nearly 1534If an argument is given, that is how many columns are scrolled, else nearly
1538the width of the A and B windows. `C-u -' alone as argument scrolls half the 1535the width of the A and B windows. `C-u -' alone as argument scrolls half the
1539width of the A and B windows." 1536width of the A and B windows."
1540 (interactive "P") 1537 (interactive "P")
@@ -1562,7 +1559,7 @@ width of the A and B windows."
1562 1559
1563(defun emerge-scroll-right (&optional arg) 1560(defun emerge-scroll-right (&optional arg)
1564 "Scroll right all three merge buffers, if they are in windows. 1561 "Scroll right all three merge buffers, if they are in windows.
1565If an ARGUMENT is given, that is how many columns are scrolled, else nearly 1562If an argument is given, that is how many columns are scrolled, else nearly
1566the width of the A and B windows. `C-u -' alone as argument scrolls half the 1563the width of the A and B windows. `C-u -' alone as argument scrolls half the
1567width of the A and B windows." 1564width of the A and B windows."
1568 (interactive "P") 1565 (interactive "P")
@@ -1589,8 +1586,9 @@ width of the A and B windows."
1589 default-amount))))))) 1586 default-amount)))))))
1590 1587
1591(defun emerge-scroll-reset () 1588(defun emerge-scroll-reset ()
1592 "Reset horizontal scrolling of all three merge buffers to the left margin, 1589 "Reset horizontal scrolling in Emerge.
1593if they are in windows." 1590This resets the horizontal scrolling of all three merge buffers
1591to the left margin, if they are in windows."
1594 (interactive) 1592 (interactive)
1595 (emerge-operate-on-windows 1593 (emerge-operate-on-windows
1596 (function (lambda (x) (set-window-hscroll (selected-window) 0))) 1594 (function (lambda (x) (set-window-hscroll (selected-window) 0)))
@@ -1671,9 +1669,15 @@ if they are in windows."
1671 (emerge-unselect-and-select-difference difference-number) 1669 (emerge-unselect-and-select-difference difference-number)
1672 (error "Bad difference number")))) 1670 (error "Bad difference number"))))
1673 1671
1672(defun emerge-abort ()
1673 "Abort the Emerge session."
1674 (interactive)
1675 (emerge-quit t))
1676
1674(defun emerge-quit (arg) 1677(defun emerge-quit (arg)
1675 "Finish an Emerge session. Prefix ARGUMENT means to abort rather than 1678 "Finish the Emerge session and exit Emerge.
1676successfully finish. The difference depends on how the merge was started, 1679Prefix argument means to abort rather than successfully finish.
1680The difference depends on how the merge was started,
1677but usually means to not write over one of the original files, or to signal 1681but usually means to not write over one of the original files, or to signal
1678to some process which invoked Emerge a failure code. 1682to some process which invoked Emerge a failure code.
1679 1683
@@ -1718,13 +1722,14 @@ buffer after this will cause serious problems."
1718 ;; restore mode line 1722 ;; restore mode line
1719 (kill-local-variable 'mode-line-buffer-identification) 1723 (kill-local-variable 'mode-line-buffer-identification)
1720 (let ((emerge-prefix-argument arg)) 1724 (let ((emerge-prefix-argument arg))
1721 (run-hooks 'emerge-quit-hooks))) 1725 (run-hooks 'emerge-quit-hook)))
1722 1726
1723(defun emerge-select-A (&optional force) 1727(defun emerge-select-A (&optional force)
1724 "Select the A variant of this difference. Refuses to function if this 1728 "Select the A variant of this difference.
1725difference has been edited, i.e., if it is neither the A nor the B variant. 1729Refuses to function if this difference has been edited, i.e., if it
1726An ARGUMENT forces the variant to be selected even if the difference has 1730is neither the A nor the B variant.
1727been edited." 1731A prefix argument forces the variant to be selected
1732even if the difference has been edited."
1728 (interactive "P") 1733 (interactive "P")
1729 (let ((operate 1734 (let ((operate
1730 (function (lambda () 1735 (function (lambda ()
@@ -1749,10 +1754,11 @@ been edited."
1749 (emerge-refresh-mode-line))) 1754 (emerge-refresh-mode-line)))
1750 1755
1751(defun emerge-select-B (&optional force) 1756(defun emerge-select-B (&optional force)
1752 "Select the B variant of this difference. Refuses to function if this 1757 "Select the B variant of this difference.
1753difference has been edited, i.e., if it is neither the A nor the B variant. 1758Refuses to function if this difference has been edited, i.e., if it
1754An ARGUMENT forces the variant to be selected even if the difference has 1759is neither the A nor the B variant.
1755been edited." 1760A prefix argument forces the variant to be selected
1761even if the difference has been edited."
1756 (interactive "P") 1762 (interactive "P")
1757 (let ((operate 1763 (let ((operate
1758 (function (lambda () 1764 (function (lambda ()
@@ -1777,7 +1783,8 @@ been edited."
1777 (emerge-refresh-mode-line))) 1783 (emerge-refresh-mode-line)))
1778 1784
1779(defun emerge-default-A () 1785(defun emerge-default-A ()
1780 "Selects the A variant for all differences from here down in the buffer 1786 "Make the A variant the default from here down.
1787This selects the A variant for all differences from here down in the buffer
1781which are still defaulted, i.e., which the user has not selected and for 1788which are still defaulted, i.e., which the user has not selected and for
1782which there is no preference." 1789which there is no preference."
1783 (interactive) 1790 (interactive)
@@ -1798,7 +1805,8 @@ which there is no preference."
1798 (message "Default A set")) 1805 (message "Default A set"))
1799 1806
1800(defun emerge-default-B () 1807(defun emerge-default-B ()
1801 "Selects the B variant for all differences from here down in the buffer 1808 "Make the B variant the default from here down.
1809This selects the B variant for all differences from here down in the buffer
1802which are still defaulted, i.e., which the user has not selected and for 1810which are still defaulted, i.e., which the user has not selected and for
1803which there is no preference." 1811which there is no preference."
1804 (interactive) 1812 (interactive)
@@ -1819,8 +1827,9 @@ which there is no preference."
1819 (message "Default B set")) 1827 (message "Default B set"))
1820 1828
1821(defun emerge-fast-mode () 1829(defun emerge-fast-mode ()
1822 "Set fast mode, in which ordinary Emacs commands are disabled, and Emerge 1830 "Set fast mode, for Emerge.
1823commands are need not be prefixed with \\<emerge-fast-keymap>\\[emerge-basic-keymap]." 1831In this mode ordinary Emacs commands are disabled, and Emerge commands
1832need not be prefixed with \\<emerge-fast-keymap>\\[emerge-basic-keymap]."
1824 (interactive) 1833 (interactive)
1825 (setq buffer-read-only t) 1834 (setq buffer-read-only t)
1826 (use-local-map emerge-fast-keymap) 1835 (use-local-map emerge-fast-keymap)
@@ -1832,8 +1841,9 @@ commands are need not be prefixed with \\<emerge-fast-keymap>\\[emerge-basic-key
1832 (set-buffer-modified-p (buffer-modified-p))) 1841 (set-buffer-modified-p (buffer-modified-p)))
1833 1842
1834(defun emerge-edit-mode () 1843(defun emerge-edit-mode ()
1835 "Set edit mode, in which ordinary Emacs commands are available, and Emerge 1844 "Set edit mode, for Emerge.
1836commands must be prefixed with \\<emerge-fast-keymap>\\[emerge-basic-keymap]." 1845In this mode ordinary Emacs commands are available, and Emerge commands
1846must be prefixed with \\<emerge-fast-keymap>\\[emerge-basic-keymap]."
1837 (interactive) 1847 (interactive)
1838 (setq buffer-read-only nil) 1848 (setq buffer-read-only nil)
1839 (use-local-map emerge-edit-keymap) 1849 (use-local-map emerge-edit-keymap)
@@ -1845,11 +1855,11 @@ commands must be prefixed with \\<emerge-fast-keymap>\\[emerge-basic-keymap]."
1845 (set-buffer-modified-p (buffer-modified-p))) 1855 (set-buffer-modified-p (buffer-modified-p)))
1846 1856
1847(defun emerge-auto-advance (arg) 1857(defun emerge-auto-advance (arg)
1848 "Toggle auto-advance mode, which causes emerge-select-A and 1858 "Toggle Auto-Advance mode, for Emerge.
1849 emerge-select-B to automatically advance to the next difference. (See 1859This mode causes `emerge-select-A' and `emerge-select-B' to automatically
1850emerge-auto-advance.) 1860advance to the next difference.
1851If a positive ARGUMENT is given, it turns on auto-advance mode. 1861With a positive argument, turn on Auto-Advance mode.
1852If a negative ARGUMENT is given, it turns off auto-advance mode." 1862With a negative argument, turn off Auto-Advance mode."
1853 (interactive "P") 1863 (interactive "P")
1854 (setq emerge-auto-advance (if (null arg) 1864 (setq emerge-auto-advance (if (null arg)
1855 (not emerge-auto-advance) 1865 (not emerge-auto-advance)
@@ -1861,11 +1871,11 @@ If a negative ARGUMENT is given, it turns off auto-advance mode."
1861 (set-buffer-modified-p (buffer-modified-p))) 1871 (set-buffer-modified-p (buffer-modified-p)))
1862 1872
1863(defun emerge-skip-prefers (arg) 1873(defun emerge-skip-prefers (arg)
1864 "Toggle skip-prefers mode, which causes emerge-next-difference and 1874 "Toggle Skip-Prefers mode, for Emerge.
1865 emerge-previous-difference to automatically skip over differences for which 1875This mode causes `emerge-next-difference' and `emerge-previous-difference'
1866there is a preference. (See emerge-skip-prefers.) 1876to automatically skip over differences for which there is a preference.
1867If a positive ARGUMENT is given, it turns on skip-prefers mode. 1877With a positive argument, turn on Skip-Prefers mode.
1868If a negative ARGUMENT is given, it turns off skip-prefers mode." 1878With a negative argument, turn off Skip-Prefers mode."
1869 (interactive "P") 1879 (interactive "P")
1870 (setq emerge-skip-prefers (if (null arg) 1880 (setq emerge-skip-prefers (if (null arg)
1871 (not emerge-skip-prefers) 1881 (not emerge-skip-prefers)
@@ -1958,10 +1968,10 @@ With prefix argument, puts mark before, point after."
1958 1968
1959(defun emerge-file-names () 1969(defun emerge-file-names ()
1960 "Show the names of the buffers or files being operated on by Emerge. 1970 "Show the names of the buffers or files being operated on by Emerge.
1961Use ^U L to reset the windows afterward." 1971Use C-u l to reset the windows afterward."
1962 (interactive) 1972 (interactive)
1963 (delete-other-windows) 1973 (delete-other-windows)
1964 (let ((temp-buffer-show-hook 1974 (let ((temp-buffer-show-function
1965 (function (lambda (buf) 1975 (function (lambda (buf)
1966 (split-window-vertically) 1976 (split-window-vertically)
1967 (switch-to-buffer buf) 1977 (switch-to-buffer buf)
@@ -1998,8 +2008,8 @@ Use ^U L to reset the windows afterward."
1998 (princ emerge-output-description)))) 2008 (princ emerge-output-description))))
1999 2009
2000(defun emerge-join-differences (arg) 2010(defun emerge-join-differences (arg)
2001 "Join the selected difference with the following one. With a prefix 2011 "Join the selected difference with the following one.
2002argument, join with the preceeding one." 2012With a prefix argument, join with the preceeding one."
2003 (interactive "P") 2013 (interactive "P")
2004 (let ((n emerge-current-difference)) 2014 (let ((n emerge-current-difference))
2005 ;; adjust n to be first difference to join 2015 ;; adjust n to be first difference to join
@@ -2113,9 +2123,10 @@ argument, join with the preceeding one."
2113 (emerge-recenter)))) 2123 (emerge-recenter))))
2114 2124
2115(defun emerge-trim-difference () 2125(defun emerge-trim-difference ()
2116 "Trim lines off the top and bottom of a difference that are the same in 2126 "Trim lines off top and bottom of difference that are the same.
2117both the A and B versions. (This can happen when the A and B versions 2127If lines are the same in both the A and the B versions, strip them off.
2118have common lines that the ancestor version does not share.)" 2128\(This can happen when the A and B versions have common lines that the
2129ancestor version does not share.)"
2119 (interactive) 2130 (interactive)
2120 ;; make sure we are in a real difference 2131 ;; make sure we are in a real difference
2121 (emerge-validate-difference) 2132 (emerge-validate-difference)
@@ -2211,8 +2222,8 @@ the nearest previous difference."
2211 (emerge-find-difference1 arg (point) 4 5)) 2222 (emerge-find-difference1 arg (point) 4 5))
2212 2223
2213(defun emerge-find-difference-A (arg) 2224(defun emerge-find-difference-A (arg)
2214 "Find the difference containing the current position of the point in the 2225 "Find the difference containing the position of the point in the A buffer.
2215A buffer. (Nonetheless, this command must be executed in the merge buffer.) 2226This command must be executed in the merge buffer.
2216If there is no containing difference and the prefix argument is positive, 2227If there is no containing difference and the prefix argument is positive,
2217it finds the nearest following difference. A negative prefix argument finds 2228it finds the nearest following difference. A negative prefix argument finds
2218the nearest previous difference." 2229the nearest previous difference."
@@ -2224,8 +2235,8 @@ the nearest previous difference."
2224 0 1)) 2235 0 1))
2225 2236
2226(defun emerge-find-difference-B (arg) 2237(defun emerge-find-difference-B (arg)
2227 "Find the difference containing the current position of the point in the 2238 "Find the difference containing the position of the point in the B buffer.
2228B buffer. (Nonetheless, this command must be executed in the merge buffer.) 2239This command must be executed in the merge buffer.
2229If there is no containing difference and the prefix argument is positive, 2240If there is no containing difference and the prefix argument is positive,
2230it finds the nearest following difference. A negative prefix argument finds 2241it finds the nearest following difference. A negative prefix argument finds
2231the nearest previous difference." 2242the nearest previous difference."
@@ -2274,7 +2285,8 @@ the nearest previous difference."
2274 (error "No difference contains or preceeds point"))))))) 2285 (error "No difference contains or preceeds point")))))))
2275 2286
2276(defun emerge-line-numbers () 2287(defun emerge-line-numbers ()
2277 "Display the current line numbers of the points in the A, B, and 2288 "Display the current line numbers.
2289This function displays the line numbers of the points in the A, B, and
2278merge buffers." 2290merge buffers."
2279 (interactive) 2291 (interactive)
2280 (let* ((valid-diff 2292 (let* ((valid-diff
@@ -2304,9 +2316,9 @@ merge buffers."
2304 temp)) 2316 temp))
2305 2317
2306(defun emerge-set-combine-versions-template (start end &optional localize) 2318(defun emerge-set-combine-versions-template (start end &optional localize)
2307 "Copy region into emerge-combine-versions-template which controls how 2319 "Copy region into `emerge-combine-versions-template'.
2308emerge-combine-versions will combine the two versions. 2320This controls how `emerge-combine-versions' will combine the two versions.
2309With prefix argument, emerge-combine-versions is made local to this 2321With prefix argument, `emerge-combine-versions' is made local to this
2310merge buffer. Localization is permanent for any particular merge buffer." 2322merge buffer. Localization is permanent for any particular merge buffer."
2311 (interactive "r\nP") 2323 (interactive "r\nP")
2312 (if localize 2324 (if localize
@@ -2318,22 +2330,21 @@ merge buffer. Localization is permanent for any particular merge buffer."
2318 "emerge-set-combine-versions-template set."))) 2330 "emerge-set-combine-versions-template set.")))
2319 2331
2320(defun emerge-combine-versions (&optional force) 2332(defun emerge-combine-versions (&optional force)
2321 "Combine the two versions using the template in 2333 "Combine versions using the template in `emerge-combine-versions-template'.
2322emerge-combine-versions-template.
2323Refuses to function if this difference has been edited, i.e., if it is 2334Refuses to function if this difference has been edited, i.e., if it is
2324neither the A nor the B variant. 2335neither the A nor the B variant.
2325An ARGUMENT forces the variant to be selected even if the difference has 2336An argument forces the variant to be selected even if the difference has
2326been edited." 2337been edited."
2327 (interactive "P") 2338 (interactive "P")
2328 (emerge-combine-versions-internal emerge-combine-versions-template force)) 2339 (emerge-combine-versions-internal emerge-combine-versions-template force))
2329 2340
2330(defun emerge-combine-versions-register (char &optional force) 2341(defun emerge-combine-versions-register (char &optional force)
2331 "Combine the two versions using the template in register REG. 2342 "Combine the two versions using the template in register REG.
2332See documentation of the variable emerge-combine-versions-template 2343See documentation of the variable `emerge-combine-versions-template'
2333for how the template is interpreted. 2344for how the template is interpreted.
2334Refuses to function if this difference has been edited, i.e., if it is 2345Refuses to function if this difference has been edited, i.e., if it is
2335neither the A nor the B variant. 2346neither the A nor the B variant.
2336An ARGUMENT forces the variant to be selected even if the difference has 2347An argument forces the variant to be selected even if the difference has
2337been edited." 2348been edited."
2338 (interactive "cRegister containing template: \nP") 2349 (interactive "cRegister containing template: \nP")
2339 (let ((template (get-register char))) 2350 (let ((template (get-register char)))
@@ -2371,9 +2382,9 @@ been edited."
2371 ((= c ?b) 2382 ((= c ?b)
2372 (insert-buffer-substring emerge-B-buffer B-begin B-end)) 2383 (insert-buffer-substring emerge-B-buffer B-begin B-end))
2373 ((= c ?%) 2384 ((= c ?%)
2374 (insert ?%) 2385 (insert ?%))
2375 (t 2386 (t
2376 (insert c))))) 2387 (insert c))))
2377 (insert c))) 2388 (insert c)))
2378 (setq i (1+ i)))) 2389 (setq i (1+ i))))
2379 (goto-char merge-begin) 2390 (goto-char merge-begin)
@@ -2381,8 +2392,9 @@ been edited."
2381 (emerge-refresh-mode-line))) 2392 (emerge-refresh-mode-line)))
2382 2393
2383(defun emerge-set-merge-mode (mode) 2394(defun emerge-set-merge-mode (mode)
2384 "Set the major mode in a merge buffer. Overrides any change that the mode 2395 "Set the major mode in a merge buffer.
2385might make to the mode line or local keymap. Leaves merge in fast mode." 2396Overrides any change that the mode might make to the mode line or local
2397keymap. Leaves merge in fast mode."
2386 (interactive 2398 (interactive
2387 (list (intern (completing-read "New major mode for merge buffer: " 2399 (list (intern (completing-read "New major mode for merge buffer: "
2388 obarray 'commandp t nil)))) 2400 obarray 'commandp t nil))))
@@ -2407,7 +2419,7 @@ might make to the mode line or local keymap. Leaves merge in fast mode."
2407 (emerge-place-flags-in-buffer emerge-A-buffer n 0 1) 2419 (emerge-place-flags-in-buffer emerge-A-buffer n 0 1)
2408 (emerge-place-flags-in-buffer emerge-B-buffer n 2 3) 2420 (emerge-place-flags-in-buffer emerge-B-buffer n 2 3)
2409 (emerge-place-flags-in-buffer nil n 4 5)) 2421 (emerge-place-flags-in-buffer nil n 4 5))
2410 (run-hooks 'emerge-select-hooks)) 2422 (run-hooks 'emerge-select-hook))
2411 2423
2412(defun emerge-place-flags-in-buffer (buffer difference before-index 2424(defun emerge-place-flags-in-buffer (buffer difference before-index
2413 after-index) 2425 after-index)
@@ -2478,7 +2490,7 @@ might make to the mode line or local keymap. Leaves merge in fast mode."
2478 (aref diff-vector 2) (aref diff-vector 3)) 2490 (aref diff-vector 2) (aref diff-vector 3))
2479 (emerge-remove-flags-in-buffer emerge-merge-buffer 2491 (emerge-remove-flags-in-buffer emerge-merge-buffer
2480 (aref diff-vector 4) (aref diff-vector 5))) 2492 (aref diff-vector 4) (aref diff-vector 5)))
2481 (run-hooks 'emerge-unselect-hooks)) 2493 (run-hooks 'emerge-unselect-hook))
2482 2494
2483(defun emerge-remove-flags-in-buffer (buffer before after) 2495(defun emerge-remove-flags-in-buffer (buffer before after)
2484 (emerge-eval-in-buffer 2496 (emerge-eval-in-buffer
@@ -2490,13 +2502,13 @@ might make to the mode line or local keymap. Leaves merge in fast mode."
2490 (delete-char emerge-before-flag-length) 2502 (delete-char emerge-before-flag-length)
2491 ;; the flag isn't there 2503 ;; the flag isn't there
2492 (ding) 2504 (ding)
2493 (message "Trouble removing flag.")) 2505 (message "Trouble removing flag"))
2494 (goto-char (1- after)) 2506 (goto-char (1- after))
2495 (if (looking-at emerge-after-flag-match) 2507 (if (looking-at emerge-after-flag-match)
2496 (delete-char emerge-after-flag-length) 2508 (delete-char emerge-after-flag-length)
2497 ;; the flag isn't there 2509 ;; the flag isn't there
2498 (ding) 2510 (ding)
2499 (message "Trouble removing flag."))))) 2511 (message "Trouble removing flag")))))
2500 2512
2501;; Select a difference, removing any flags that exist now. 2513;; Select a difference, removing any flags that exist now.
2502(defun emerge-unselect-and-select-difference (n &optional suppress-display) 2514(defun emerge-unselect-and-select-difference (n &optional suppress-display)
@@ -2554,7 +2566,7 @@ might make to the mode line or local keymap. Leaves merge in fast mode."
2554 2566
2555(defun emerge-read-file-name (prompt alternative-default-dir default-file 2567(defun emerge-read-file-name (prompt alternative-default-dir default-file
2556 A-file) 2568 A-file)
2557 ;; 'prompt' should not have trailing ": ", so that it can be modified 2569 ;; `prompt' should not have trailing ": ", so that it can be modified
2558 ;; according to context. 2570 ;; according to context.
2559 ;; If alternative-default-dir is non-nil, it should be used as the default 2571 ;; If alternative-default-dir is non-nil, it should be used as the default
2560 ;; directory instead if default-directory, if emerge-default-last-directories 2572 ;; directory instead if default-directory, if emerge-default-last-directories
@@ -2699,22 +2711,22 @@ might make to the mode line or local keymap. Leaves merge in fast mode."
2699;;; Functions that query the user before he can write out the current buffer. 2711;;; Functions that query the user before he can write out the current buffer.
2700 2712
2701(defun emerge-query-write-file () 2713(defun emerge-query-write-file ()
2702 "Query the user if he really wants to write out the incomplete merge. 2714 "Ask the user whether to write out an incomplete merge.
2703If he says yes, call write-file to do so. See emerge-query-and-call 2715If answer is yes, call `write-file' to do so. See `emerge-query-and-call'
2704for details of the querying process." 2716for details of the querying process."
2705 (interactive) 2717 (interactive)
2706 (emerge-query-and-call 'write-file)) 2718 (emerge-query-and-call 'write-file))
2707 2719
2708(defun emerge-query-save-buffer () 2720(defun emerge-query-save-buffer ()
2709 "Query the user if he really wants to write out the incomplete merge. 2721 "Ask the user whether to save an incomplete merge.
2710If he says yes, call save-buffer to do so. See emerge-query-and-call 2722If answer is yes, call `save-buffer' to do so. See `emerge-query-and-call'
2711for details of the querying process." 2723for details of the querying process."
2712 (interactive) 2724 (interactive)
2713 (emerge-query-and-call 'save-buffer)) 2725 (emerge-query-and-call 'save-buffer))
2714 2726
2715(defun emerge-query-and-call (command) 2727(defun emerge-query-and-call (command)
2716 "Query the user if he really wants to write out the incomplete merge. 2728 "Ask the user whether to save or write out the incomplete merge.
2717If he says yes, call COMMAND interactively. During the call, the flags 2729If answer is yes, call COMMAND interactively. During the call, the flags
2718around the current difference are removed." 2730around the current difference are removed."
2719 (if (yes-or-no-p "Do you really write to write out this unfinished merge? ") 2731 (if (yes-or-no-p "Do you really write to write out this unfinished merge? ")
2720 ;; He really wants to do it -- unselect the difference for the duration 2732 ;; He really wants to do it -- unselect the difference for the duration
@@ -2756,16 +2768,6 @@ around the current difference are removed."
2756 (if (yes-or-no-p (format "Revert file %s? " buffer-file-name)) 2768 (if (yes-or-no-p (format "Revert file %s? " buffer-file-name))
2757 (revert-buffer t t) 2769 (revert-buffer t t)
2758 (error "Buffer out of sync for file %s" buffer-file-name))))) 2770 (error "Buffer out of sync for file %s" buffer-file-name)))))
2759
2760;; Returns true if the file visited in the current buffer is not accessible
2761;; through its filename, or for some other reason should be stored in a
2762;; temporary file for input to diff.
2763;; As written, checks whether this is an ange-ftp file. It may be modified
2764;; for customization.
2765(defun emerge-remote-file-p ()
2766 (and (boundp 'ange-ftp-path-format)
2767 ange-ftp-path-format
2768 (string-match (car ange-ftp-path-format) buffer-file-name)))
2769 2771
2770;; Utilities that might have value outside of Emerge. 2772;; Utilities that might have value outside of Emerge.
2771 2773
@@ -2777,8 +2779,8 @@ around the current difference are removed."
2777 2779
2778;; Define a key, even if a prefix of it is defined 2780;; Define a key, even if a prefix of it is defined
2779(defun emerge-force-define-key (keymap key definition) 2781(defun emerge-force-define-key (keymap key definition)
2780 "Like define-key, but is not stopped if a prefix of KEY is a defined 2782 "Like `define-key', but forcibly creates prefix characters as needed.
2781command." 2783If some prefix of KEY has a non-prefix definition, it is redefined."
2782 ;; Find out if a prefix of key is defined 2784 ;; Find out if a prefix of key is defined
2783 (let ((v (lookup-key keymap key))) 2785 (let ((v (lookup-key keymap key)))
2784 ;; If so, undefine it 2786 ;; If so, undefine it
@@ -2787,73 +2789,75 @@ command."
2787 ;; Now define the key 2789 ;; Now define the key
2788 (define-key keymap key definition)) 2790 (define-key keymap key definition))
2789 2791
2790;;; Improvements to describe-mode, so that it describes minor modes as well 2792;;;;; Improvements to describe-mode, so that it describes minor modes as well
2791;;; as the major mode 2793;;;;; as the major mode
2792(defun describe-mode (&optional minor) 2794;;(defun describe-mode (&optional minor)
2793 "Display documentation of current major mode. 2795;; "Display documentation of current major mode.
2794If optional MINOR is non-nil (or prefix argument is given if interactive), 2796;;If optional arg MINOR is non-nil (or prefix argument is given if interactive),
2795display documentation of acive minor modes as well. 2797;;display documentation of active minor modes as well.
2796For this to work correctly for a minor mode, the mode's indicator variable 2798;;For this to work correctly for a minor mode, the mode's indicator variable
2797(listed in minor-mode-alist) must also be a function whose documentation 2799;;\(listed in `minor-mode-alist') must also be a function whose documentation
2798describes the minor mode." 2800;;describes the minor mode."
2799 (interactive) 2801;; (interactive)
2800 (with-output-to-temp-buffer "*Help*" 2802;; (with-output-to-temp-buffer "*Help*"
2801 (princ mode-name) 2803;; (princ mode-name)
2802 (princ " Mode:\n") 2804;; (princ " Mode:\n")
2803 (princ (documentation major-mode)) 2805;; (princ (documentation major-mode))
2804 (let ((minor-modes minor-mode-alist) 2806;; (let ((minor-modes minor-mode-alist)
2805 (locals (buffer-local-variables))) 2807;; (locals (buffer-local-variables)))
2806 (while minor-modes 2808;; (while minor-modes
2807 (let* ((minor-mode (car (car minor-modes))) 2809;; (let* ((minor-mode (car (car minor-modes)))
2808 (indicator (car (cdr (car minor-modes)))) 2810;; (indicator (car (cdr (car minor-modes))))
2809 (local-binding (assq minor-mode locals))) 2811;; (local-binding (assq minor-mode locals)))
2810 ;; Document a minor mode if it is listed in minor-mode-alist, 2812;; ;; Document a minor mode if it is listed in minor-mode-alist,
2811 ;; bound locally in this buffer, non-nil, and has a function 2813;; ;; bound locally in this buffer, non-nil, and has a function
2812 ;; definition. 2814;; ;; definition.
2813 (if (and local-binding 2815;; (if (and local-binding
2814 (cdr local-binding) 2816;; (cdr local-binding)
2815 (fboundp minor-mode)) 2817;; (fboundp minor-mode))
2816 (progn 2818;; (progn
2817 (princ (format "\n\n\n%s minor mode (indicator%s):\n" 2819;; (princ (format "\n\n\n%s minor mode (indicator%s):\n"
2818 minor-mode indicator)) 2820;; minor-mode indicator))
2819 (princ (documentation minor-mode))))) 2821;; (princ (documentation minor-mode)))))
2820 (setq minor-modes (cdr minor-modes)))) 2822;; (setq minor-modes (cdr minor-modes))))
2821 (print-help-return-message))) 2823;; (print-help-return-message)))
2822 2824
2823;; Adjust things so that keyboard macro definitions are documented correctly. 2825;; This goes with the redefinition of describe-mode.
2824(fset 'defining-kbd-macro (symbol-function 'start-kbd-macro)) 2826;;;; Adjust things so that keyboard macro definitions are documented correctly.
2825 2827;;(fset 'defining-kbd-macro (symbol-function 'start-kbd-macro))
2826;; Function to shadow a definition in a keymap with definitions in another. 2828
2827(defun emerge-shadow-key-definition (olddef newdef keymap shadowmap) 2829;; substitute-key-definition should work now.
2828 "Shadow OLDDEF with NEWDEF for any keys in KEYMAP with entries in SHADOWMAP. 2830;;;; Function to shadow a definition in a keymap with definitions in another.
2829In other words, SHADOWMAP will now shadow all definitions of OLDDEF in KEYMAP 2831;;(defun emerge-shadow-key-definition (olddef newdef keymap shadowmap)
2830with NEWDEF. Does not affect keys that are already defined in SHADOWMAP, 2832;; "Shadow OLDDEF with NEWDEF for any keys in KEYMAP with entries in SHADOWMAP.
2831including those whose definition is OLDDEF." 2833;;In other words, SHADOWMAP will now shadow all definitions of OLDDEF in KEYMAP
2832 ;; loop through all keymaps accessible from keymap 2834;;with NEWDEF. Does not affect keys that are already defined in SHADOWMAP,
2833 (let ((maps (accessible-keymaps keymap))) 2835;;including those whose definition is OLDDEF."
2834 (while maps 2836;; ;; loop through all keymaps accessible from keymap
2835 (let ((prefix (car (car maps))) 2837;; (let ((maps (accessible-keymaps keymap)))
2836 (map (cdr (car maps)))) 2838;; (while maps
2837 ;; examine a keymap 2839;; (let ((prefix (car (car maps)))
2838 (if (arrayp map) 2840;; (map (cdr (car maps))))
2839 ;; array keymap 2841;; ;; examine a keymap
2840 (let ((len (length map)) 2842;; (if (arrayp map)
2841 (i 0)) 2843;; ;; array keymap
2842 (while (< i len) 2844;; (let ((len (length map))
2843 (if (eq (aref map i) olddef) 2845;; (i 0))
2844 ;; set the shadowing definition 2846;; (while (< i len)
2845 (let ((key (concat prefix (char-to-string i)))) 2847;; (if (eq (aref map i) olddef)
2846 (emerge-define-key-if-possible shadowmap key newdef))) 2848;; ;; set the shadowing definition
2847 (setq i (1+ i)))) 2849;; (let ((key (concat prefix (char-to-string i))))
2848 ;; sparse keymap 2850;; (emerge-define-key-if-possible shadowmap key newdef)))
2849 (while map 2851;; (setq i (1+ i))))
2850 (if (eq (cdr-safe (car-safe map)) olddef) 2852;; ;; sparse keymap
2851 ;; set the shadowing definition 2853;; (while map
2852 (let ((key 2854;; (if (eq (cdr-safe (car-safe map)) olddef)
2853 (concat prefix (char-to-string (car (car map)))))) 2855;; ;; set the shadowing definition
2854 (emerge-define-key-if-possible shadowmap key newdef))) 2856;; (let ((key
2855 (setq map (cdr map))))) 2857;; (concat prefix (char-to-string (car (car map))))))
2856 (setq maps (cdr maps))))) 2858;; (emerge-define-key-if-possible shadowmap key newdef)))
2859;; (setq map (cdr map)))))
2860;; (setq maps (cdr maps)))))
2857 2861
2858;; Define a key if it (or a prefix) is not already defined in the map. 2862;; Define a key if it (or a prefix) is not already defined in the map.
2859(defun emerge-define-key-if-possible (keymap key definition) 2863(defun emerge-define-key-if-possible (keymap key definition)
@@ -2868,16 +2872,17 @@ including those whose definition is OLDDEF."
2868 (if (not present) 2872 (if (not present)
2869 (define-key keymap key definition))))) 2873 (define-key keymap key definition)))))
2870 2874
2871(defun emerge-recursively-substitute-key-definition (olddef newdef keymap) 2875;; Ordinary substitute-key-definition should do this now.
2872 "Like substitute-key-definition, but examines and substitutes in all 2876;;(defun emerge-recursively-substitute-key-definition (olddef newdef keymap)
2873keymaps accessible from KEYMAP. Make sure that subordinate keymaps aren't 2877;; "Like `substitute-key-definition', but act recursively on subkeymaps.
2874shared with other keymaps! (copy-keymap will suffice.)" 2878;;Make sure that subordinate keymaps aren't shared with other keymaps!
2875 ;; Loop through all keymaps accessible from keymap 2879;;\(`copy-keymap' will suffice.)"
2876 (let ((maps (accessible-keymaps keymap))) 2880;; ;; Loop through all keymaps accessible from keymap
2877 (while maps 2881;; (let ((maps (accessible-keymaps keymap)))
2878 ;; Substitute in this keymap 2882;; (while maps
2879 (substitute-key-definition olddef newdef (cdr (car maps))) 2883;; ;; Substitute in this keymap
2880 (setq maps (cdr maps))))) 2884;; (substitute-key-definition olddef newdef (cdr (car maps)))
2885;; (setq maps (cdr maps)))))
2881 2886
2882;; Show the name of the file in the buffer. 2887;; Show the name of the file in the buffer.
2883(defun emerge-show-file-name () 2888(defun emerge-show-file-name ()
@@ -2898,9 +2903,9 @@ SPC, it is ignored; if it is anything else, it is processed as a command."
2898 (while (and (not (pos-visible-in-window-p)) 2903 (while (and (not (pos-visible-in-window-p))
2899 (> (1- (screen-height)) (window-height))) 2904 (> (1- (screen-height)) (window-height)))
2900 (enlarge-window 1)) 2905 (enlarge-window 1))
2901 (let ((c (read-char))) 2906 (let ((c (read-event)))
2902 (if (/= c 32) 2907 (if (not (eq c 32))
2903 (setq unread-command-char c)))))))) 2908 (setq unread-command-events (list c)))))))))
2904 2909
2905;; Improved auto-save file names. 2910;; Improved auto-save file names.
2906;; This function fixes many problems with the standard auto-save file names: 2911;; This function fixes many problems with the standard auto-save file names:
@@ -2916,10 +2921,10 @@ SPC, it is ignored; if it is anything else, it is processed as a command."
2916;; (symbol-function 'emerge-make-auto-save-file-name)) 2921;; (symbol-function 'emerge-make-auto-save-file-name))
2917(defun emerge-make-auto-save-file-name () 2922(defun emerge-make-auto-save-file-name ()
2918 "Return file name to use for auto-saves of current buffer. 2923 "Return file name to use for auto-saves of current buffer.
2919Does not consider auto-save-visited-file-name; that is checked 2924Does not consider `auto-save-visited-file-name';
2920before calling this function. 2925that is checked before calling this function.
2921You can redefine this for customization. 2926You can redefine this for customization.
2922See also auto-save-file-name-p." 2927See also `auto-save-file-name-p'."
2923 (if buffer-file-name 2928 (if buffer-file-name
2924 ;; if buffer has a file, try the format <file directory>/#<file name># 2929 ;; if buffer has a file, try the format <file directory>/#<file name>#
2925 (let ((f (concat (file-name-directory buffer-file-name) 2930 (let ((f (concat (file-name-directory buffer-file-name)
@@ -2935,21 +2940,21 @@ See also auto-save-file-name-p."
2935 "/#&" 2940 "/#&"
2936 (file-name-nondirectory buffer-file-name) 2941 (file-name-nondirectory buffer-file-name)
2937 "&" 2942 "&"
2938 (hash-string-into-string 2943 (emerge-hash-string-into-string
2939 (file-name-directory buffer-file-name)) 2944 (file-name-directory buffer-file-name))
2940 "#"))) 2945 "#")))
2941 ;; if buffer has no file, use the format ~/#%<buffer name>%<process id># 2946 ;; if buffer has no file, use the format ~/#%<buffer name>%<process id>#
2942 (expand-file-name (concat (getenv "HOME") 2947 (expand-file-name (concat (getenv "HOME")
2943 "/#%" 2948 "/#%"
2944 ;; quote / into \! and \ into \\ 2949 ;; quote / into \! and \ into \\
2945 (unslashify-name (buffer-name)) 2950 (emerge-unslashify-name (buffer-name))
2946 "%" 2951 "%"
2947 (make-temp-name "") 2952 (make-temp-name "")
2948 "#")))) 2953 "#"))))
2949 2954
2950;; Hash a string into five characters more-or-less suitable for use in a file 2955;; Hash a string into five characters more-or-less suitable for use in a file
2951;; name. (Allowed characters are ! through ~, except /.) 2956;; name. (Allowed characters are ! through ~, except /.)
2952(defun hash-string-into-string (s) 2957(defun emerge-hash-string-into-string (s)
2953 (let ((bins (vector 0 0 0 0 0)) 2958 (let ((bins (vector 0 0 0 0 0))
2954 (i 0)) 2959 (i 0))
2955 (while (< i (length s)) 2960 (while (< i (length s))
@@ -2966,7 +2971,7 @@ See also auto-save-file-name-p."
2966 2971
2967;; Quote any /s in a string by replacing them with \!. 2972;; Quote any /s in a string by replacing them with \!.
2968;; Also, replace any \s by \\, to make it one-to-one. 2973;; Also, replace any \s by \\, to make it one-to-one.
2969(defun unslashify-name (s) 2974(defun emerge-unslashify-name (s)
2970 (let ((limit 0)) 2975 (let ((limit 0))
2971 (while (string-match "[/\\]" s limit) 2976 (while (string-match "[/\\]" s limit)
2972 (setq s (concat (substring s 0 (match-beginning 0)) 2977 (setq s (concat (substring s 0 (match-beginning 0))
@@ -2982,8 +2987,8 @@ See also auto-save-file-name-p."
2982;; Metacharacters that have to be protected from the shell when executing 2987;; Metacharacters that have to be protected from the shell when executing
2983;; a diff/diff3 command. 2988;; a diff/diff3 command.
2984(defvar emerge-metachars "[ \t\n!\"#$&'()*;<=>?[\\^`{|~]" 2989(defvar emerge-metachars "[ \t\n!\"#$&'()*;<=>?[\\^`{|~]"
2985 "Characters that must be quoted with \\ when used in a shell command 2990 "Characters that must be quoted with \\ when used in a shell command line.
2986line, specified as a [...] regexp.") 2991More precisely, a [...] regexp to match any one such character.")
2987 2992
2988;; Quote metacharacters (using \) when executing a diff/diff3 command. 2993;; Quote metacharacters (using \) when executing a diff/diff3 command.
2989(defun emerge-protect-metachars (s) 2994(defun emerge-protect-metachars (s)
@@ -2995,3 +3000,6 @@ line, specified as a [...] regexp.")
2995 (setq limit (1+ (match-end 0))))) 3000 (setq limit (1+ (match-end 0)))))
2996 s) 3001 s)
2997 3002
3003(provide 'emerge)
3004
3005;;; emerge.el ends here