(struct ftfont_info): New member matrix.
[bpt/emacs.git] / lisp / ediff-merg.el
CommitLineData
475f9031 1;;; ediff-merg.el --- merging utilities
b578f267 2
0d30b337 3;; Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
ae940284 4;; 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
475f9031 5
50a07e18 6;; Author: Michael Kifer <kifer@cs.stonybrook.edu>
475f9031
KH
7
8;; This file is part of GNU Emacs.
9
eb3fa2cf 10;; GNU Emacs is free software: you can redistribute it and/or modify
475f9031 11;; it under the terms of the GNU General Public License as published by
eb3fa2cf
GM
12;; the Free Software Foundation, either version 3 of the License, or
13;; (at your option) any later version.
475f9031
KH
14
15;; GNU Emacs is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
eb3fa2cf 21;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
475f9031 22
3afbc435
PJ
23;;; Commentary:
24
b578f267 25;;; Code:
475f9031 26
ddc90f39 27
ddc90f39
MK
28;; compiler pacifier
29(defvar ediff-window-A)
30(defvar ediff-window-B)
31(defvar ediff-window-C)
32(defvar ediff-merge-window-share)
33(defvar ediff-window-config-saved)
34
35(eval-when-compile
8480ec72 36 (require 'ediff-util))
ddc90f39
MK
37;; end pacifier
38
475f9031
KH
39(require 'ediff-init)
40
1e70790f 41(defcustom ediff-quit-merge-hook 'ediff-maybe-save-and-delete-merge
9201cc28 42 "Hooks to run before quitting a merge job.
1e70790f
MK
43The most common use is to save and delete the merge buffer."
44 :type 'hook
45 :group 'ediff-merge)
46
bbe6126c 47
ddc90f39 48(defcustom ediff-default-variant 'combined
9201cc28 49 "The variant to be used as a default for buffer C in merging.
ddc90f39
MK
50Valid values are the symbols `default-A', `default-B', and `combined'."
51 :type '(radio (const default-A) (const default-B) (const combined))
52 :group 'ediff-merge)
475f9031 53
71296446 54(defcustom ediff-combination-pattern
086171bf 55 '("<<<<<<< variant A" A ">>>>>>> variant B" B "####### Ancestor" Ancestor "======= end")
9201cc28 56 "Pattern to be used for combining difference regions in buffers A and B.
71296446 57The value must be a list of the form
4601d7c4 58\(STRING1 bufspec1 STRING2 bufspec2 STRING3 bufspec3 STRING4)
086171bf
MK
59where bufspec is the symbol A, B, or Ancestor. For instance, if the value is
60'(STRING1 A STRING2 Ancestor STRING3 B STRING4) then the
61combined text will look like this:
475f9031
KH
62
63STRING1
64diff region from variant A
65STRING2
086171bf 66diff region from the ancestor
475f9031 67STRING3
086171bf
MK
68diff region from variant B
69STRING4
ddc90f39 70"
086171bf
MK
71 :type '(choice (list string symbol string symbol string)
72 (list string symbol string symbol string symbol string))
ddc90f39 73 :group 'ediff-merge)
475f9031 74
3af0304a 75(defcustom ediff-show-clashes-only nil
9201cc28 76 "If t, show only those diff regions where both buffers disagree with the ancestor.
475f9031 77This means that regions that have status prefer-A or prefer-B will be
4601d7c4 78skipped over. A value of nil means show all regions."
3af0304a
MK
79 :type 'boolean
80 :group 'ediff-merge
81 )
82(make-variable-buffer-local 'ediff-show-clashes-only)
83
84(defcustom ediff-skip-merge-regions-that-differ-from-default nil
9201cc28 85 "If t, show only the regions that have not been changed by the user.
3af0304a
MK
86A region is considered to have been changed if it is different from the current
87default (`default-A', `default-B', `combined') and it hasn't been marked as
88`prefer-A' or `prefer-B'.
71296446 89A region is considered to have been changed also when it is marked as
3af0304a
MK
90as `prefer-A', but is different from the corresponding difference region in
91Buffer A or if it is marked as `prefer-B' and is different from the region in
92Buffer B."
93 :type 'boolean
94 :group 'ediff-merge
95 )
96(make-variable-buffer-local 'ediff-skip-merge-regions-that-differ-from-default)
475f9031 97
e2de3a29 98;; check if there is no clash between the ancestor and one of the variants.
39bcfe5f 99;; if it is not a merge job then return true
68b962d4 100(defun ediff-merge-region-is-non-clash (n)
39bcfe5f
MK
101 (if (ediff-merge-job)
102 (string-match "prefer" (or (ediff-get-state-of-merge n) ""))
103 t))
e2de3a29 104
8e41a31c
MK
105;; If ediff-show-clashes-only, check if there is no clash between the ancestor
106;; and one of the variants.
68b962d4
MK
107(defun ediff-merge-region-is-non-clash-to-skip (n)
108 (and (ediff-merge-job)
109 ediff-show-clashes-only
e2de3a29 110 (ediff-merge-region-is-non-clash n)))
8e41a31c 111
3af0304a
MK
112;; If ediff-skip-changed-regions, check if the merge region differs from
113;; the current default. If a region is different from the default, it means
114;; that the user has made determination as to how to merge for this particular
71296446 115;; region.
68b962d4
MK
116(defun ediff-skip-merge-region-if-changed-from-default-p (n)
117 (and (ediff-merge-job)
118 ediff-skip-merge-regions-that-differ-from-default
3af0304a
MK
119 (ediff-merge-changed-from-default-p n 'prefers-too)))
120
121
086171bf
MK
122(defun ediff-get-combined-region (n)
123 (let ((pattern-list ediff-combination-pattern)
124 (combo-region "")
125 (err-msg
126 "ediff-combination-pattern: Invalid format. Please consult the documentation")
50a07e18 127 region-delim region-spec)
086171bf
MK
128
129 (if (< (length pattern-list) 5)
130 (error err-msg))
131
132 (while (> (length pattern-list) 2)
133 (setq region-delim (nth 0 pattern-list)
134 region-spec (nth 1 pattern-list))
135 (or (and (stringp region-delim) (memq region-spec '(A B Ancestor)))
136 (error err-msg))
137
50a07e18 138 (condition-case nil
086171bf
MK
139 (setq combo-region
140 (concat combo-region
141 region-delim "\n"
71296446 142 (ediff-get-region-contents
086171bf
MK
143 n region-spec ediff-control-buffer)))
144 (error ""))
145 (setq pattern-list (cdr (cdr pattern-list)))
146 )
147
148 (setq region-delim (nth 0 pattern-list))
149 (or (stringp region-delim)
150 (error err-msg))
151 (setq combo-region (concat combo-region region-delim "\n"))
152 ))
153
154;;(defsubst ediff-make-combined-diff (regA regB)
155;; (concat (nth 0 ediff-combination-pattern) "\n"
156;; regA
157;; (nth 1 ediff-combination-pattern) "\n"
158;; regB
159;; (nth 2 ediff-combination-pattern) "\n"))
009650b3 160
475f9031
KH
161(defsubst ediff-set-state-of-all-diffs-in-all-buffers (ctl-buf)
162 (let ((n 0))
163 (while (< n ediff-number-of-differences)
164 (ediff-set-state-of-diff-in-all-buffers n ctl-buf)
165 (setq n (1+ n)))))
71296446 166
475f9031
KH
167(defun ediff-set-state-of-diff-in-all-buffers (n ctl-buf)
168 (let ((regA (ediff-get-region-contents n 'A ctl-buf))
169 (regB (ediff-get-region-contents n 'B ctl-buf))
170 (regC (ediff-get-region-contents n 'C ctl-buf)))
13340e24
KH
171 (cond ((and (string= regA regB) (string= regA regC))
172 (ediff-set-state-of-diff n 'A "=diff(B)")
173 (ediff-set-state-of-diff n 'B "=diff(C)")
174 (ediff-set-state-of-diff n 'C "=diff(A)"))
175 ((string= regA regB)
475f9031
KH
176 (ediff-set-state-of-diff n 'A "=diff(B)")
177 (ediff-set-state-of-diff n 'B "=diff(A)")
178 (ediff-set-state-of-diff n 'C nil))
179 ((string= regA regC)
180 (ediff-set-state-of-diff n 'A "=diff(C)")
181 (ediff-set-state-of-diff n 'C "=diff(A)")
182 (ediff-set-state-of-diff n 'B nil))
183 ((string= regB regC)
184 (ediff-set-state-of-diff n 'C "=diff(B)")
185 (ediff-set-state-of-diff n 'B "=diff(C)")
186 (ediff-set-state-of-diff n 'A nil))
187 ((string= regC (ediff-get-combined-region n))
188 (ediff-set-state-of-diff n 'A nil)
189 (ediff-set-state-of-diff n 'B nil)
190 (ediff-set-state-of-diff n 'C "=diff(A+B)"))
191 (t (ediff-set-state-of-diff n 'A nil)
192 (ediff-set-state-of-diff n 'B nil)
193 (ediff-set-state-of-diff n 'C nil)))
194 ))
71296446 195
13340e24 196(defun ediff-set-merge-mode ()
13340e24
KH
197 (normal-mode t)
198 (remove-hook 'local-write-file-hooks 'ediff-set-merge-mode))
c439fb30 199
71296446 200
475f9031
KH
201;; Go over all diffs starting with DIFF-NUM and copy regions into buffer C
202;; according to the state of the difference.
203;; Since ediff-copy-diff refuses to copy identical diff regions, there is
204;; no need to optimize ediff-do-merge any further.
205;;
206;; If re-merging, change state of merge in all diffs starting with
207;; DIFF-NUM, except those where the state is prefer-* or where it is
13340e24
KH
208;; `default-*' or `combined' but the buf C region appears to be modified
209;; since last set by default.
475f9031
KH
210(defun ediff-do-merge (diff-num &optional remerging)
211 (if (< diff-num 0) (setq diff-num 0))
212 (let ((n diff-num)
bbe6126c 213 ;;(default-state-of-merge (format "%S" ediff-default-variant))
13340e24 214 do-not-copy state-of-merge)
475f9031 215 (while (< n ediff-number-of-differences)
bbe6126c 216 (setq do-not-copy nil) ; reset after each cycle
475f9031
KH
217 (if (= (mod n 10) 0)
218 (message "%s buffers A & B into C ... region %d of %d"
219 (if remerging "Re-merging" "Merging")
220 n
221 ediff-number-of-differences))
71296446 222
475f9031 223 (setq state-of-merge (ediff-get-state-of-merge n))
475f9031
KH
224
225 (if remerging
50a07e18
MK
226 ;;(let ((reg-A (ediff-get-region-contents n 'A ediff-control-buffer))
227 ;; (reg-B (ediff-get-region-contents n 'B ediff-control-buffer))
228 ;; (reg-C (ediff-get-region-contents n 'C ediff-control-buffer)))
1e2b6acf 229 (progn
71296446 230
bbe6126c 231 ;; if region was edited since it was first set by default
3af0304a
MK
232 (if (or (ediff-merge-changed-from-default-p n)
233 ;; was preferred
13340e24 234 (string-match "prefer" state-of-merge))
3af0304a 235 ;; then ignore
475f9031 236 (setq do-not-copy t))
71296446 237
475f9031 238 ;; change state of merge for this diff, if necessary
13340e24
KH
239 (if (and (string-match "\\(default\\|combined\\)" state-of-merge)
240 (not do-not-copy))
475f9031
KH
241 (ediff-set-state-of-merge
242 n (format "%S" ediff-default-variant)))
243 ))
71296446 244
475f9031 245 ;; state-of-merge may have changed via ediff-set-state-of-merge, so
13340e24 246 ;; check it once again
475f9031 247 (setq state-of-merge (ediff-get-state-of-merge n))
71296446 248
475f9031
KH
249 (or do-not-copy
250 (if (string= state-of-merge "combined")
251 ;; use n+1 because ediff-combine-diffs works via user numbering
252 ;; of diffs, which is 1+ to what ediff uses internally
253 (ediff-combine-diffs (1+ n) 'batch)
71296446 254 (ediff-copy-diff
13340e24 255 n (if (string-match "-A" state-of-merge) 'A 'B) 'C 'batch)))
475f9031
KH
256 (setq n (1+ n)))
257 (message "Merging buffers A & B into C ... Done")
258 ))
71296446 259
475f9031
KH
260
261(defun ediff-re-merge ()
3af0304a 262 "Remerge unmodified diff regions using a new default. Start with the current region."
475f9031
KH
263 (interactive)
264 (let* ((default-variant-alist
265 (list '("default-A") '("default-B") '("combined")))
266 (actual-alist
267 (delete (list (symbol-name ediff-default-variant))
268 default-variant-alist)))
269 (setq ediff-default-variant
270 (intern
71296446 271 (completing-read
3af0304a 272 (format "Current merge default is `%S'. New default: "
475f9031
KH
273 ediff-default-variant)
274 actual-alist nil 'must-match)))
275 (ediff-do-merge ediff-current-difference 'remerge)
276 (ediff-recenter)
277 ))
71296446 278
475f9031
KH
279(defun ediff-shrink-window-C (arg)
280 "Shrink window C to just one line.
281With a prefix argument, returns window C to its normal size.
282Used only for merging jobs."
283 (interactive "P")
284 (if (not ediff-merge-job)
285 (error "ediff-shrink-window-C can be used only for merging jobs"))
286 (cond ((eq arg '-) (setq arg -1))
287 ((not (numberp arg)) (setq arg nil)))
288 (cond ((null arg)
289 (let ((ediff-merge-window-share
290 (if (< (window-height ediff-window-C) 3)
291 ediff-merge-window-share 0)))
292 (setq ediff-window-config-saved "") ; force redisplay
293 (ediff-recenter 'no-rehighlight)))
294 ((and (< arg 0) (> (window-height ediff-window-C) 2))
295 (setq ediff-merge-window-share (* ediff-merge-window-share 0.9))
296 (setq ediff-window-config-saved "") ; force redisplay
297 (ediff-recenter 'no-rehighlight))
298 ((and (> arg 0) (> (window-height ediff-window-A) 2))
299 (setq ediff-merge-window-share (* ediff-merge-window-share 1.1))
300 (setq ediff-window-config-saved "") ; force redisplay
301 (ediff-recenter 'no-rehighlight))))
302
303
3af0304a 304;; N here is the user's region number. It is 1+ what Ediff uses internally.
475f9031
KH
305(defun ediff-combine-diffs (n &optional batch-invocation)
306 "Combine Nth diff regions of buffers A and B and place the combination in C.
3af0304a 307N is a prefix argument. If nil, combine the current difference regions.
4ae69eac
MK
308Combining is done according to the specifications in variable
309`ediff-combination-pattern'."
475f9031 310 (interactive "P")
4ae69eac 311 (setq n (if (numberp n) (1- n) ediff-current-difference))
71296446 312
50a07e18 313 (let (reg-combined)
086171bf
MK
314 ;;(setq regA (ediff-get-region-contents n 'A ediff-control-buffer)
315 ;; regB (ediff-get-region-contents n 'B ediff-control-buffer))
316 ;;(setq reg-combined (ediff-make-combined-diff regA regB))
317 (setq reg-combined (ediff-get-combined-region n))
71296446 318
475f9031 319 (ediff-copy-diff n nil 'C batch-invocation reg-combined))
4ae69eac 320 (or batch-invocation (ediff-jump-to-difference (1+ n))))
71296446 321
475f9031
KH
322
323;; Checks if the region in buff C looks like a combination of the regions
3af0304a 324;; in buffers A and B. Return a list (reg-a-beg reg-a-end reg-b-beg reg-b-end)
086171bf
MK
325;; These refer to where the delimiters for region A, B, Ancestor start and end
326;; in buffer C
475f9031
KH
327(defun ediff-looks-like-combined-merge (region-num)
328 (if ediff-merge-job
329 (let ((combined (string-match (regexp-quote "(A+B)")
330 (or (ediff-get-state-of-diff region-num 'C)
331 "")))
086171bf
MK
332 (mrgreg-beg (ediff-get-diff-posn 'C 'beg region-num))
333 (mrgreg-end (ediff-get-diff-posn 'C 'end region-num))
334 (pattern-list ediff-combination-pattern)
335 delim reg-beg reg-end delim-regs-list)
71296446 336
475f9031 337 (if combined
e756eb9f 338 (ediff-with-current-buffer ediff-buffer-C
086171bf
MK
339 (while pattern-list
340 (goto-char mrgreg-beg)
341 (setq delim (nth 0 pattern-list))
342 (search-forward delim mrgreg-end 'noerror)
343 (setq reg-beg (match-beginning 0))
344 (setq reg-end (match-end 0))
345 (if (and reg-beg reg-end)
346 (setq delim-regs-list
347 ;; in reverse
348 (cons reg-end (cons reg-beg delim-regs-list))))
349 (if (> (length pattern-list) 1)
350 (setq pattern-list (cdr (cdr pattern-list)))
351 (setq pattern-list nil))
352 )))
353
354 (reverse delim-regs-list)
475f9031 355 )))
3b90e5b8 356
937382fa 357(defvar state-of-merge) ; dynamic var
3af0304a
MK
358
359;; Check if the non-preferred merge has been modified since originally set.
360;; This affects only the regions that are marked as default-A/B or combined.
361;; If PREFERS-TOO is non-nil, then look at the regions marked as prefers-A/B as
362;; well.
363(defun ediff-merge-changed-from-default-p (diff-num &optional prefers-too)
364 (let ((reg-A (ediff-get-region-contents diff-num 'A ediff-control-buffer))
365 (reg-B (ediff-get-region-contents diff-num 'B ediff-control-buffer))
366 (reg-C (ediff-get-region-contents diff-num 'C ediff-control-buffer)))
367
368 (setq state-of-merge (ediff-get-state-of-merge diff-num))
71296446 369
3af0304a
MK
370 ;; if region was edited since it was first set by default
371 (or (and (string= state-of-merge "default-A")
372 (not (string= reg-A reg-C)))
373 (and (string= state-of-merge "default-B")
374 (not (string= reg-B reg-C)))
375 (and (string= state-of-merge "combined")
086171bf
MK
376 ;;(not (string= (ediff-make-combined-diff reg-A reg-B) reg-C)))
377 (not (string= (ediff-get-combined-region diff-num) reg-C)))
3af0304a
MK
378 (and prefers-too
379 (string= state-of-merge "prefer-A")
380 (not (string= reg-A reg-C)))
381 (and prefers-too
382 (string= state-of-merge "prefer-B")
383 (not (string= reg-B reg-C)))
384 )))
71296446 385
475f9031 386
b6178721
MK
387(provide 'ediff-merg)
388
389
fa043571
SM
390;; Local Variables:
391;; eval: (put 'ediff-defvar-local 'lisp-indent-hook 'defun)
392;; eval: (put 'ediff-with-current-buffer 'lisp-indent-hook 1)
393;; eval: (put 'ediff-with-current-buffer 'edebug-form-spec '(form body))
394;; End:
92c51e07 395
cbee283d 396;; arch-tag: 9b798cf9-02ba-487f-a62e-b63aa823dbfb
3afbc435 397;;; ediff-merg.el ends here