1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-06 06:20:55 -08:00

Show ancestor buffer in 3way merges

Add an option ediff-show-ancestor', to control if the ancestor buffer
must be shown in 3way merges (Bug#25493); set it non-nil by default.
Add a toggle to change this option interactively; the original
value of the option is restored on exit.

Update the window setup so that the ancestor buffer is
shown in 3way merges when ediff-show-ancestor is non-nil.

Any operation on ediff windows must take in account the
ancestor window as well, when this is shown.

* lisp/vc/ediff-init.el (ediff-show-ancestor): New option.
(ediff--show-ancestor-orig): New defvar.
* lisp/vc/ediff-wind.el (ediff-window-Ancestor): New defvar.
(ediff-setup-windows-plain-merge, ediff-setup-windows-multiframe-merge):
Display ancestor buffer if ediff-show-ancestor is non-nil.
(ediff-keep-window-config): Expect ancestor window in
ediff-window-config-saved.
(ediff-window-alist): Add entry for the ancestor window.
* lisp/vc/ediff-util.el (ediff-setup-control-buffer):
ediff-window-config-saved contains ancestor window.
(ediff-show-ancestor): Delete this command.
(ediff-setup-keymap): Bind ediff-toggle-show-ancestor to '/' for merge jobs.
(ediff-update-diffs): Compute new diffs using ancestor buffer in 3way merges;
don't cheat it to think that is performing a comparison, that trick is not
necessary anymore: simply call 'ediff-setup-diff-regions-function'
with file-A, file-B and the file ancestor.
(ediff-recenter): Update doc string.  Consider the ancestor buffer.
(ediff--check-ancestor-exists): New defun.
(ediff-toggle-show-ancestor): New command; toggle ediff-show-ancestor.
(ediff--restore-options-on-exit): Restore ediff-show-ancestor on exit.
(ediff-scroll-vertically, ediff-scroll-horizontally)
(ediff-operate-on-windows): Consider the ancestor as well.
* lisp/vc/ediff-help.el (ediff-long-help-message-merge):
List ediff-toggle-show-ancestor.
* doc/misc/ediff.texi (Introduction, Quick Help Commands): Update manual.
; * etc/NEWS: Announce these changes.
This commit is contained in:
Tino Calancha 2017-03-14 16:12:29 +09:00
parent e39d593475
commit 0f3d1b7823
6 changed files with 197 additions and 69 deletions

View file

@ -99,7 +99,8 @@ through them. You can also copy difference regions from one buffer to
another (and recover old differences if you change your mind). another (and recover old differences if you change your mind).
Another powerful feature is the ability to merge a pair of files into a Another powerful feature is the ability to merge a pair of files into a
third buffer. Merging with an ancestor file is also supported. third buffer. Merging with an ancestor file, (a.k.a. 3way merges)
is also supported.
Furthermore, Ediff is equipped with directory-level capabilities that Furthermore, Ediff is equipped with directory-level capabilities that
allow the user to conveniently launch browsing or merging sessions on allow the user to conveniently launch browsing or merging sessions on
groups of files in two (or three) different directories. groups of files in two (or three) different directories.
@ -828,7 +829,10 @@ region in buffer A, etc.
@item / @item /
@kindex / @kindex /
Displays the ancestor file during merges. @vindex ediff-show-ancestor
Toggle to display the ancestor file in 3way merges.
You can enable permanently this setting customizing the variable
@code{ediff-show-ancestor}.
@item & @item &
@kindex & @kindex &
In some situations, such as when one of the files agrees with the ancestor file In some situations, such as when one of the files agrees with the ancestor file

View file

@ -366,6 +366,11 @@ words where first character is upper rather than title case, e.g.,
* Changes in Specialized Modes and Packages in Emacs 26.1 * Changes in Specialized Modes and Packages in Emacs 26.1
+++
*** The ancestor buffer is shown by default in 3way merges.
A new option ediff-show-ancestor and a new toggle
ediff-toggle-show-ancestor.
** TeX: Add luatex and xetex as alternatives to pdftex ** TeX: Add luatex and xetex as alternatives to pdftex
** Electric-Buffer-menu ** Electric-Buffer-menu

View file

@ -112,7 +112,7 @@ n,SPC -next diff | h -highlighting | r -restore buf C's old diff
C-l -recenter | #f/#h -focus/hide regions | + -combine diff regions C-l -recenter | #f/#h -focus/hide regions | + -combine diff regions
v/V -scroll up/dn | X -read-only in buf X | wx -save buf X v/V -scroll up/dn | X -read-only in buf X | wx -save buf X
</> -scroll lt/rt | m -wide display | wd -save diff output </> -scroll lt/rt | m -wide display | wd -save diff output
~ -swap variants | s -shrink window C | / -show ancestor buff ~ -swap variants | s -shrink window C | / -show/hide ancestor buff
| $$ -show clashes only | & -merge w/new default | $$ -show clashes only | & -merge w/new default
| $* -skip changed regions | | $* -skip changed regions |
" "

View file

@ -1363,6 +1363,16 @@ This property can be toggled interactively."
;; if nil, this silences some messages ;; if nil, this silences some messages
(defvar ediff-verbose-p t) (defvar ediff-verbose-p t)
(defcustom ediff-show-ancestor t
"If non-nil, show ancestor buffer in 3way merges and refine it."
:type 'boolean
:group 'ediff-merge
:version "26.1")
;; Store orig value of `ediff-show-ancestor' when changed in
;; `ediff-toggle-show-ancestor' and restore it on exit.
(ediff-defvar-local ediff--show-ancestor-orig nil "")
(defcustom ediff-autostore-merges 'group-jobs-only (defcustom ediff-autostore-merges 'group-jobs-only
"Save the results of merge jobs automatically. "Save the results of merge jobs automatically.
With value nil, don't save automatically. With value t, always With value nil, don't save automatically. With value t, always

View file

@ -178,7 +178,7 @@ to invocation.")
(define-key ediff-mode-map "r" nil) (define-key ediff-mode-map "r" nil)
(cond (ediff-merge-job (cond (ediff-merge-job
;; Will barf if no ancestor ;; Will barf if no ancestor
(define-key ediff-mode-map "/" 'ediff-show-ancestor) (define-key ediff-mode-map "/" 'ediff-toggle-show-ancestor)
;; In merging, we allow only A->C and B->C copying. ;; In merging, we allow only A->C and B->C copying.
(define-key ediff-mode-map "a" 'ediff-copy-A-to-C) (define-key ediff-mode-map "a" 'ediff-copy-A-to-C)
(define-key ediff-mode-map "b" 'ediff-copy-B-to-C) (define-key ediff-mode-map "b" 'ediff-copy-B-to-C)
@ -553,11 +553,12 @@ to invocation.")
(ediff-refresh-mode-lines) (ediff-refresh-mode-lines)
(setq ediff-control-window (selected-window)) (setq ediff-control-window (selected-window))
(setq ediff-window-config-saved (setq ediff-window-config-saved
(format "%S%S%S%S%S%S%S" (format "%S%S%S%S%S%S%S%S"
ediff-control-window ediff-control-window
ediff-window-A ediff-window-A
ediff-window-B ediff-window-B
ediff-window-C ediff-window-C
ediff-window-Ancestor
ediff-split-window-function ediff-split-window-function
(ediff-multiframe-setup-p) (ediff-multiframe-setup-p)
ediff-wide-display-p)) ediff-wide-display-p))
@ -600,12 +601,6 @@ to these buffers are not saved at this point---the user can do this later,
if necessary." if necessary."
(interactive) (interactive)
(ediff-barf-if-not-control-buffer) (ediff-barf-if-not-control-buffer)
(if (and (ediff-buffer-live-p ediff-ancestor-buffer)
(not
(y-or-n-p
"Ancestor buffer will not be used. Recompute diffs anyway? ")))
(error "Recomputation of differences canceled"))
(let ((point-A (ediff-with-current-buffer ediff-buffer-A (point))) (let ((point-A (ediff-with-current-buffer ediff-buffer-A (point)))
;;(point-B (ediff-with-current-buffer ediff-buffer-B (point))) ;;(point-B (ediff-with-current-buffer ediff-buffer-B (point)))
(tmp-buffer (get-buffer-create ediff-tmp-buffer)) (tmp-buffer (get-buffer-create ediff-tmp-buffer))
@ -614,14 +609,17 @@ if necessary."
;; (null ediff-buffer-C) is no problem, as we later check if ;; (null ediff-buffer-C) is no problem, as we later check if
;; ediff-buffer-C is alive ;; ediff-buffer-C is alive
(buf-C-file-name (buffer-file-name ediff-buffer-C)) (buf-C-file-name (buffer-file-name ediff-buffer-C))
(buf-ancestor-file-name (buffer-file-name ediff-ancestor-buffer))
(overl-A (ediff-get-value-according-to-buffer-type (overl-A (ediff-get-value-according-to-buffer-type
'A ediff-narrow-bounds)) 'A ediff-narrow-bounds))
(overl-B (ediff-get-value-according-to-buffer-type (overl-B (ediff-get-value-according-to-buffer-type
'B ediff-narrow-bounds)) 'B ediff-narrow-bounds))
(overl-C (ediff-get-value-according-to-buffer-type (overl-C (ediff-get-value-according-to-buffer-type
'C ediff-narrow-bounds)) 'C ediff-narrow-bounds))
beg-A end-A beg-B end-B beg-C end-C (overl-Ancestor (ediff-get-value-according-to-buffer-type
file-A file-B file-C) 'Ancestor ediff-narrow-bounds))
beg-A end-A beg-B end-B beg-C end-C beg-Ancestor end-Ancestor
file-A file-B file-C file-Ancestor)
(if (stringp buf-A-file-name) (if (stringp buf-A-file-name)
(setq buf-A-file-name (file-name-nondirectory buf-A-file-name))) (setq buf-A-file-name (file-name-nondirectory buf-A-file-name)))
@ -629,15 +627,19 @@ if necessary."
(setq buf-B-file-name (file-name-nondirectory buf-B-file-name))) (setq buf-B-file-name (file-name-nondirectory buf-B-file-name)))
(if (stringp buf-C-file-name) (if (stringp buf-C-file-name)
(setq buf-C-file-name (file-name-nondirectory buf-C-file-name))) (setq buf-C-file-name (file-name-nondirectory buf-C-file-name)))
(if (stringp buf-ancestor-file-name)
(setq buf-ancestor-file-name (file-name-nondirectory buf-ancestor-file-name)))
(ediff-unselect-and-select-difference -1) (ediff-unselect-and-select-difference -1)
(setq beg-A (ediff-overlay-start overl-A) (setq beg-A (ediff-overlay-start overl-A)
beg-B (ediff-overlay-start overl-B) beg-B (ediff-overlay-start overl-B)
beg-C (ediff-overlay-start overl-C) beg-C (ediff-overlay-start overl-C)
beg-Ancestor (ediff-overlay-start overl-Ancestor)
end-A (ediff-overlay-end overl-A) end-A (ediff-overlay-end overl-A)
end-B (ediff-overlay-end overl-B) end-B (ediff-overlay-end overl-B)
end-C (ediff-overlay-end overl-C)) end-C (ediff-overlay-end overl-C)
end-Ancestor (ediff-overlay-end overl-Ancestor))
(if ediff-word-mode (if ediff-word-mode
(progn (progn
@ -645,51 +647,37 @@ if necessary."
(setq file-A (ediff-make-temp-file tmp-buffer "regA")) (setq file-A (ediff-make-temp-file tmp-buffer "regA"))
(ediff-wordify beg-B end-B ediff-buffer-B tmp-buffer) (ediff-wordify beg-B end-B ediff-buffer-B tmp-buffer)
(setq file-B (ediff-make-temp-file tmp-buffer "regB")) (setq file-B (ediff-make-temp-file tmp-buffer "regB"))
(if ediff-3way-job (when ediff-3way-job
(progn
(ediff-wordify beg-C end-C ediff-buffer-C tmp-buffer) (ediff-wordify beg-C end-C ediff-buffer-C tmp-buffer)
(setq file-C (ediff-make-temp-file tmp-buffer "regC")))) (setq file-C (ediff-make-temp-file tmp-buffer "regC")))
(when ediff-merge-with-ancestor-job
(ediff-wordify beg-Ancestor end-Ancestor ediff-ancestor-buffer tmp-buffer)
(setq file-Ancestor (ediff-make-temp-file tmp-buffer "regAncestor")))
) )
;; not word-mode ;; not word-mode
(setq file-A (ediff-make-temp-file ediff-buffer-A buf-A-file-name)) (setq file-A (ediff-make-temp-file ediff-buffer-A buf-A-file-name))
(setq file-B (ediff-make-temp-file ediff-buffer-B buf-B-file-name)) (setq file-B (ediff-make-temp-file ediff-buffer-B buf-B-file-name))
(if ediff-3way-job (if ediff-3way-job
(setq file-C (ediff-make-temp-file ediff-buffer-C buf-C-file-name))) (setq file-C (ediff-make-temp-file ediff-buffer-C buf-C-file-name)))
(when ediff-merge-with-ancestor-job
(setq file-Ancestor
(ediff-make-temp-file
ediff-ancestor-buffer
buf-ancestor-file-name)))
) )
(ediff-clear-diff-vector 'ediff-difference-vector-A 'fine-diffs-also) (ediff-clear-diff-vector 'ediff-difference-vector-A 'fine-diffs-also)
(ediff-clear-diff-vector 'ediff-difference-vector-B 'fine-diffs-also) (ediff-clear-diff-vector 'ediff-difference-vector-B 'fine-diffs-also)
(ediff-clear-diff-vector 'ediff-difference-vector-C 'fine-diffs-also) (ediff-clear-diff-vector 'ediff-difference-vector-C 'fine-diffs-also)
(ediff-clear-diff-vector (ediff-clear-diff-vector
'ediff-difference-vector-Ancestor 'fine-diffs-also) 'ediff-difference-vector-Ancestor 'fine-diffs-also)
;; let them garbage collect. we can't use the ancestor after recomputing
;; the diffs.
(setq ediff-difference-vector-Ancestor nil
ediff-ancestor-buffer nil
ediff-state-of-merge nil)
(setq ediff-killed-diffs-alist nil) ; invalidate saved killed diff regions (setq ediff-killed-diffs-alist nil) ; invalidate saved killed diff regions
(funcall ediff-setup-diff-regions-function file-A file-B
;; In case of merge job, fool it into thinking that it is just doing (if ediff-merge-with-ancestor-job file-Ancestor file-C))
;; comparison
(let ((ediff-setup-diff-regions-function ediff-setup-diff-regions-function)
(ediff-3way-comparison-job ediff-3way-comparison-job)
(ediff-merge-job ediff-merge-job)
(ediff-merge-with-ancestor-job ediff-merge-with-ancestor-job)
(ediff-job-name ediff-job-name))
(if ediff-merge-job
(setq ediff-setup-diff-regions-function 'ediff-setup-diff-regions3
ediff-3way-comparison-job t
ediff-merge-job nil
ediff-merge-with-ancestor-job nil
ediff-job-name 'ediff-files3))
(funcall ediff-setup-diff-regions-function file-A file-B file-C))
(setq ediff-number-of-differences (length ediff-difference-vector-A)) (setq ediff-number-of-differences (length ediff-difference-vector-A))
(delete-file file-A) (delete-file file-A)
(delete-file file-B) (delete-file file-B)
(if file-C (and file-C (delete-file file-C))
(delete-file file-C)) (and file-Ancestor (delete-file file-Ancestor))
(if ediff-3way-job (if ediff-3way-job
(ediff-set-state-of-all-diffs-in-all-buffers ediff-control-buffer)) (ediff-set-state-of-all-diffs-in-all-buffers ediff-control-buffer))
@ -737,14 +725,16 @@ if necessary."
;; optional NO-REHIGHLIGHT says to not rehighlight buffers ;; optional NO-REHIGHLIGHT says to not rehighlight buffers
(defun ediff-recenter (&optional no-rehighlight) (defun ediff-recenter (&optional no-rehighlight)
"Bring the highlighted region of all buffers being compared into view. "Bring the highlighted region of all buffers being compared into view.
Reestablish the default three-window display." Reestablish the default window display."
(interactive) (interactive)
(ediff-barf-if-not-control-buffer) (ediff-barf-if-not-control-buffer)
(let (buffer-read-only) (let (buffer-read-only)
(if (and (ediff-buffer-live-p ediff-buffer-A) (if (and (ediff-buffer-live-p ediff-buffer-A)
(ediff-buffer-live-p ediff-buffer-B) (ediff-buffer-live-p ediff-buffer-B)
(or (not ediff-3way-job) (or (not ediff-3way-job)
(ediff-buffer-live-p ediff-buffer-C))) (ediff-buffer-live-p ediff-buffer-C))
(or (not ediff-merge-with-ancestor-job)
(ediff-buffer-live-p ediff-ancestor-buffer)))
(ediff-setup-windows (ediff-setup-windows
ediff-buffer-A ediff-buffer-B ediff-buffer-C ediff-control-buffer) ediff-buffer-A ediff-buffer-B ediff-buffer-C ediff-control-buffer)
(or (eq this-command 'ediff-quit) (or (eq this-command 'ediff-quit)
@ -963,18 +953,43 @@ On a dumb terminal, switches between ASCII highlighting and no highlighting."
(setq ediff-auto-refine 'nix)) (setq ediff-auto-refine 'nix))
)) ))
(defun ediff-show-ancestor () (defun ediff--check-ancestor-exists ()
"Show the ancestor buffer in a suitable window."
(interactive)
(ediff-recenter)
(or (ediff-buffer-live-p ediff-ancestor-buffer) (or (ediff-buffer-live-p ediff-ancestor-buffer)
(if ediff-merge-with-ancestor-job (if ediff-merge-with-ancestor-job
(error "Lost connection to ancestor buffer...sorry") (error "Lost connection to ancestor buffer. This shouldn't happen. \
(error "Not merging with ancestor"))) Please report this bug to bug-gnu-emacs@gnu.org")
(let (wind) (error "Not merging with ancestor"))))
(cond ((setq wind (ediff-get-visible-buffer-window ediff-ancestor-buffer))
(raise-frame (window-frame wind))) ;; Restore `ediff-show-ancestor' on exit.
(t (set-window-buffer ediff-window-C ediff-ancestor-buffer))))) (defun ediff--restore-options-on-exit ()
(message "Restoring ediff-show-ancestor to %S..." ediff--show-ancestor-orig)
(setq ediff-show-ancestor ediff--show-ancestor-orig
ediff--show-ancestor-orig nil)
(remove-hook 'ediff-quit-hook #'ediff--restore-options-on-exit))
(defun ediff-toggle-show-ancestor ()
"Toggle to show/hide the ancestor buffer."
(interactive)
(ediff--check-ancestor-exists)
;; Save original value if not yet, and add hook to restore it on exit.
(unless ediff--show-ancestor-orig
(setq ediff--show-ancestor-orig ediff-show-ancestor)
(add-hook 'ediff-quit-hook #'ediff--restore-options-on-exit))
(setq ediff-show-ancestor (not ediff-show-ancestor))
;; If equal than orig, then nothing to restore on exit.
(when (eq ediff-show-ancestor ediff--show-ancestor-orig)
(setq ediff--show-ancestor-orig nil)
(remove-hook 'ediff-quit-hook #'ediff--restore-options-on-exit))
(if (not ediff-show-ancestor)
(progn
(delete-window ediff-window-Ancestor)
(ediff-recenter)
(message "Ancestor buffer is hidden"))
(let ((wind
(ediff-get-visible-buffer-window ediff-ancestor-buffer)))
(when wind (raise-frame (window-frame wind))))
(ediff-recenter)
(message "Showing ancestor buffer")))
(defun ediff-make-or-kill-fine-diffs (arg) (defun ediff-make-or-kill-fine-diffs (arg)
"Compute fine diffs. With negative prefix arg, kill fine diffs. "Compute fine diffs. With negative prefix arg, kill fine diffs.
@ -1468,7 +1483,10 @@ Used in ediff-windows/regions only."
(ediff-recenter 'no-rehighlight)) (ediff-recenter 'no-rehighlight))
(if (not (and (ediff-buffer-live-p ediff-buffer-A) (if (not (and (ediff-buffer-live-p ediff-buffer-A)
(ediff-buffer-live-p ediff-buffer-B) (ediff-buffer-live-p ediff-buffer-B)
(or (not ediff-3way-job) ediff-buffer-C) (or (not ediff-3way-job) (ediff-buffer-live-p ediff-buffer-C))
(or (not ediff-merge-with-ancestor-job)
(not ediff-show-ancestor)
(ediff-buffer-live-p ediff-ancestor-buffer))
)) ))
(error ediff-KILLED-VITAL-BUFFER)) (error ediff-KILLED-VITAL-BUFFER))
@ -1476,11 +1494,15 @@ Used in ediff-windows/regions only."
(wind-A ediff-window-A) (wind-A ediff-window-A)
(wind-B ediff-window-B) (wind-B ediff-window-B)
(wind-C ediff-window-C) (wind-C ediff-window-C)
(wind-Anc ediff-window-Ancestor)
(coefA (ediff-get-region-size-coefficient 'A operation)) (coefA (ediff-get-region-size-coefficient 'A operation))
(coefB (ediff-get-region-size-coefficient 'B operation)) (coefB (ediff-get-region-size-coefficient 'B operation))
(three-way ediff-3way-job) (three-way ediff-3way-job)
(with-Ancestor (and ediff-merge-with-ancestor-job ediff-show-ancestor))
(coefC (if three-way (coefC (if three-way
(ediff-get-region-size-coefficient 'C operation)))) (ediff-get-region-size-coefficient 'C operation)))
(coefAnc (if with-Ancestor
(ediff-get-region-size-coefficient 'Ancestor operation))))
(select-window wind-A) (select-window wind-A)
(condition-case nil (condition-case nil
@ -1496,6 +1518,11 @@ Used in ediff-windows/regions only."
(condition-case nil (condition-case nil
(funcall operation (round (* coefC arg))) (funcall operation (round (* coefC arg)))
(error)))) (error))))
(when with-Ancestor
(select-window wind-Anc)
(condition-case nil
(funcall operation (round (* coefAnc arg)))
(error)))
(select-window wind))) (select-window wind)))
(defun ediff-scroll-vertically (&optional arg) (defun ediff-scroll-vertically (&optional arg)
@ -1512,6 +1539,9 @@ the one half of the height of window-A."
(ediff-buffer-live-p ediff-buffer-B) (ediff-buffer-live-p ediff-buffer-B)
(or (not ediff-3way-job) (or (not ediff-3way-job)
(ediff-buffer-live-p ediff-buffer-C)) (ediff-buffer-live-p ediff-buffer-C))
(or (not ediff-merge-with-ancestor-job)
(not ediff-show-ancestor)
(ediff-buffer-live-p ediff-ancestor-buffer))
)) ))
(error ediff-KILLED-VITAL-BUFFER)) (error ediff-KILLED-VITAL-BUFFER))
@ -1531,6 +1561,10 @@ the one half of the height of window-A."
(window-height ediff-window-B) (window-height ediff-window-B)
(if ediff-3way-job (if ediff-3way-job
(window-height ediff-window-C) (window-height ediff-window-C)
500) ; some large number
(if (and ediff-merge-with-ancestor-job
ediff-show-ancestor)
(window-height ediff-window-Ancestor)
500)) ; some large number 500)) ; some large number
2) 2)
1 next-screen-context-lines)) 1 next-screen-context-lines))
@ -1556,6 +1590,9 @@ the width of the A/B/C windows."
(ediff-buffer-live-p ediff-buffer-B) (ediff-buffer-live-p ediff-buffer-B)
(or (not ediff-3way-job) (or (not ediff-3way-job)
(ediff-buffer-live-p ediff-buffer-C)) (ediff-buffer-live-p ediff-buffer-C))
(or (not ediff-merge-with-ancestor-job)
(not ediff-show-ancestor)
(ediff-buffer-live-p ediff-ancestor-buffer))
)) ))
(error ediff-KILLED-VITAL-BUFFER)) (error ediff-KILLED-VITAL-BUFFER))
@ -1587,7 +1624,10 @@ the width of the A/B/C windows."
(if ediff-3way-comparison-job (if ediff-3way-comparison-job
(window-width ediff-window-C) (window-width ediff-window-C)
500) ; some large number 500) ; some large number
) (if (and ediff-merge-with-ancestor-job
ediff-show-ancestor)
(window-height ediff-window-Ancestor)
500)) ; some large number
2) 2)
3))) 3)))
;; window found ;; window found
@ -1689,6 +1729,11 @@ the width of the A/B/C windows."
(funcall func 'B n ctl-buf) (funcall func 'B n ctl-buf)
(if (ediff-buffer-live-p ediff-buffer-C) (if (ediff-buffer-live-p ediff-buffer-C)
(funcall func 'C n ctl-buf) (funcall func 'C n ctl-buf)
0)
(if (and ediff-merge-with-ancestor-job
ediff-show-ancestor
(ediff-buffer-live-p ediff-ancestor-buffer))
(funcall func 'Ancestor n ctl-buf)
0)))) 0))))
;; this covers the horizontal coefficient as well: ;; this covers the horizontal coefficient as well:
;; if max-lines = 0 then coef = 1 ;; if max-lines = 0 then coef = 1

View file

@ -115,6 +115,8 @@ provided functions are written."
(ediff-defvar-local ediff-window-B nil "") (ediff-defvar-local ediff-window-B nil "")
;; Official window for buffer C ;; Official window for buffer C
(ediff-defvar-local ediff-window-C nil "") (ediff-defvar-local ediff-window-C nil "")
;; Official window for buffer Ancestor
(ediff-defvar-local ediff-window-Ancestor nil "")
;; Ediff's window configuration. ;; Ediff's window configuration.
;; Used to minimize the need to rearrange windows. ;; Used to minimize the need to rearrange windows.
(ediff-defvar-local ediff-window-config-saved "" "") (ediff-defvar-local ediff-window-config-saved "" "")
@ -126,7 +128,8 @@ provided functions are written."
(B . ediff-window-B) (B . ediff-window-B)
(?B . ediff-window-B) (?B . ediff-window-B)
(C . ediff-window-C) (C . ediff-window-C)
(?C . ediff-window-C))) (?C . ediff-window-C)
(Ancestor . ediff-window-Ancestor)))
(defcustom ediff-split-window-function 'split-window-vertically (defcustom ediff-split-window-function 'split-window-vertically
@ -363,9 +366,13 @@ into icons, regardless of the window manager."
;; skip dedicated and unsplittable frames ;; skip dedicated and unsplittable frames
(ediff-destroy-control-frame control-buffer) (ediff-destroy-control-frame control-buffer)
(let ((window-min-height 1) (let ((window-min-height 1)
(with-Ancestor-p (ediff-with-current-buffer control-buffer
ediff-merge-with-ancestor-job))
split-window-function split-window-function
merge-window-share merge-window-lines merge-window-share merge-window-lines
wind-A wind-B wind-C) (buf-Ancestor (ediff-with-current-buffer control-buffer
ediff-ancestor-buffer))
wind-A wind-B wind-C wind-Ancestor)
(ediff-with-current-buffer control-buffer (ediff-with-current-buffer control-buffer
(setq merge-window-share ediff-merge-window-share (setq merge-window-share ediff-merge-window-share
;; this lets us have local versions of ediff-split-window-function ;; this lets us have local versions of ediff-split-window-function
@ -394,6 +401,14 @@ into icons, regardless of the window manager."
(setq wind-C (selected-window)) (setq wind-C (selected-window))
(switch-to-buffer buf-C) (switch-to-buffer buf-C)
(when (and ediff-show-ancestor with-Ancestor-p)
(select-window wind-C)
(funcall split-window-function)
(when (eq (selected-window) wind-C)
(other-window 1))
(switch-to-buffer buf-Ancestor)
(setq wind-Ancestor (selected-window)))
(select-window wind-A) (select-window wind-A)
(funcall split-window-function) (funcall split-window-function)
@ -405,7 +420,8 @@ into icons, regardless of the window manager."
(ediff-with-current-buffer control-buffer (ediff-with-current-buffer control-buffer
(setq ediff-window-A wind-A (setq ediff-window-A wind-A
ediff-window-B wind-B ediff-window-B wind-B
ediff-window-C wind-C)) ediff-window-C wind-C
ediff-window-Ancestor wind-Ancestor))
(ediff-select-lowest-window) (ediff-select-lowest-window)
(ediff-setup-control-buffer control-buffer) (ediff-setup-control-buffer control-buffer)
@ -516,9 +532,13 @@ into icons, regardless of the window manager."
(wind-A (ediff-get-visible-buffer-window buf-A)) (wind-A (ediff-get-visible-buffer-window buf-A))
(wind-B (ediff-get-visible-buffer-window buf-B)) (wind-B (ediff-get-visible-buffer-window buf-B))
(wind-C (ediff-get-visible-buffer-window buf-C)) (wind-C (ediff-get-visible-buffer-window buf-C))
(buf-Ancestor (ediff-with-current-buffer control-buf
ediff-ancestor-buffer))
(wind-Ancestor (ediff-get-visible-buffer-window buf-Ancestor))
(frame-A (if wind-A (window-frame wind-A))) (frame-A (if wind-A (window-frame wind-A)))
(frame-B (if wind-B (window-frame wind-B))) (frame-B (if wind-B (window-frame wind-B)))
(frame-C (if wind-C (window-frame wind-C))) (frame-C (if wind-C (window-frame wind-C)))
(frame-Ancestor (if wind-Ancestor (window-frame wind-Ancestor)))
;; on wide display, do things in one frame ;; on wide display, do things in one frame
(force-one-frame (force-one-frame
(ediff-with-current-buffer control-buf ediff-wide-display-p)) (ediff-with-current-buffer control-buf ediff-wide-display-p))
@ -549,7 +569,10 @@ into icons, regardless of the window manager."
(merge-window-share (ediff-with-current-buffer control-buf (merge-window-share (ediff-with-current-buffer control-buf
ediff-merge-window-share)) ediff-merge-window-share))
merge-window-lines merge-window-lines
designated-minibuffer-frame designated-minibuffer-frame ; ediff-merge-with-ancestor-job
(with-Ancestor-p (ediff-with-current-buffer control-buf
ediff-merge-with-ancestor-job))
(done-Ancestor (not with-Ancestor-p))
done-A done-B done-C) done-A done-B done-C)
;; buf-A on its own ;; buf-A on its own
@ -585,6 +608,19 @@ into icons, regardless of the window manager."
(setq wind-C (selected-window)) (setq wind-C (selected-window))
(setq done-C t))) (setq done-C t)))
;; buf-Ancestor on its own
(if (and ediff-show-ancestor
with-Ancestor-p
(window-live-p wind-Ancestor)
(ediff-window-ok-for-display wind-Ancestor)
(null use-same-frame)) ; buf Ancestor on its own
(progn
;; buffer buf-Ancestor is seen in live wind-Ancestor
(select-window wind-Ancestor)
(delete-other-windows)
(setq wind-Ancestor (selected-window))
(setq done-Ancestor t)))
(if (and use-same-frame-for-AB ; implies wind A and B are suitable (if (and use-same-frame-for-AB ; implies wind A and B are suitable
(window-live-p wind-A)) (window-live-p wind-A))
(progn (progn
@ -606,6 +642,7 @@ into icons, regardless of the window manager."
(let ((window-min-height 1)) (let ((window-min-height 1))
(if (and (eq frame-A frame-B) (if (and (eq frame-A frame-B)
(eq frame-B frame-C) (eq frame-B frame-C)
(eq frame-C frame-Ancestor)
(frame-live-p frame-A)) (frame-live-p frame-A))
(select-frame frame-A) (select-frame frame-A)
;; avoid dedicated and non-splittable windows ;; avoid dedicated and non-splittable windows
@ -623,6 +660,14 @@ into icons, regardless of the window manager."
(setq wind-C (selected-window)) (setq wind-C (selected-window))
(switch-to-buffer buf-C) (switch-to-buffer buf-C)
(when (and ediff-show-ancestor with-Ancestor-p)
(select-window wind-C)
(funcall split-window-function)
(if (eq (selected-window) wind-C)
(other-window 1))
(switch-to-buffer buf-Ancestor)
(setq wind-Ancestor (selected-window)))
(select-window wind-A) (select-window wind-A)
(funcall split-window-function) (funcall split-window-function)
@ -633,8 +678,8 @@ into icons, regardless of the window manager."
(setq done-A t (setq done-A t
done-B t done-B t
done-C t) done-C t
)) done-Ancestor t)))
(or done-A ; Buf A to be set in its own frame, (or done-A ; Buf A to be set in its own frame,
;;; or it was set before because use-same-frame = 1 ;;; or it was set before because use-same-frame = 1
@ -668,10 +713,22 @@ into icons, regardless of the window manager."
(setq wind-C (selected-window)) (setq wind-C (selected-window))
)) ))
(or done-Ancestor ; Buf Ancestor to be set in its own frame,
(not ediff-show-ancestor)
;;; or it was set before because use-same-frame = 1
(progn
;; Buf-Ancestor was not set up yet as it wasn't visible
;; and use-same-frame = nil
(select-window orig-wind)
(delete-other-windows)
(switch-to-buffer buf-Ancestor)
(setq wind-Ancestor (selected-window))))
(ediff-with-current-buffer control-buf (ediff-with-current-buffer control-buf
(setq ediff-window-A wind-A (setq ediff-window-A wind-A
ediff-window-B wind-B ediff-window-B wind-B
ediff-window-C wind-C) ediff-window-C wind-C
ediff-window-Ancestor wind-Ancestor)
(setq frame-A (window-frame ediff-window-A) (setq frame-A (window-frame ediff-window-A)
designated-minibuffer-frame designated-minibuffer-frame
(window-frame (minibuffer-window frame-A)))) (window-frame (minibuffer-window frame-A))))
@ -679,7 +736,6 @@ into icons, regardless of the window manager."
(ediff-setup-control-frame control-buf designated-minibuffer-frame) (ediff-setup-control-frame control-buf designated-minibuffer-frame)
)) ))
;; Window setup for all comparison jobs, including 3way comparisons ;; Window setup for all comparison jobs, including 3way comparisons
(defun ediff-setup-windows-multiframe-compare (buf-A buf-B buf-C control-buf) (defun ediff-setup-windows-multiframe-compare (buf-A buf-B buf-C control-buf)
;;; Algorithm: ;;; Algorithm:
@ -1295,7 +1351,9 @@ It assumes that it is called from within the control buffer."
(let ((ctl-wind ediff-control-window) (let ((ctl-wind ediff-control-window)
(A-wind ediff-window-A) (A-wind ediff-window-A)
(B-wind ediff-window-B) (B-wind ediff-window-B)
(C-wind ediff-window-C)) (C-wind ediff-window-C)
(ancestor-job ediff-merge-with-ancestor-job)
(Ancestor-wind ediff-window-Ancestor))
(and (and
(ediff-window-visible-p A-wind) (ediff-window-visible-p A-wind)
@ -1303,13 +1361,19 @@ It assumes that it is called from within the control buffer."
;; if buffer C is defined then take it into account ;; if buffer C is defined then take it into account
(or (not ediff-3way-job) (or (not ediff-3way-job)
(ediff-window-visible-p C-wind)) (ediff-window-visible-p C-wind))
(or (not ancestor-job)
(not ediff-show-ancestor)
(ediff-window-visible-p Ancestor-wind))
(eq (window-buffer A-wind) ediff-buffer-A) (eq (window-buffer A-wind) ediff-buffer-A)
(eq (window-buffer B-wind) ediff-buffer-B) (eq (window-buffer B-wind) ediff-buffer-B)
(or (not ediff-3way-job) (or (not ediff-3way-job)
(eq (window-buffer C-wind) ediff-buffer-C)) (eq (window-buffer C-wind) ediff-buffer-C))
(or (not ancestor-job)
(not ediff-show-ancestor)
(eq (window-buffer Ancestor-wind) ediff-ancestor-buffer))
(string= ediff-window-config-saved (string= ediff-window-config-saved
(format "%S%S%S%S%S%S%S" (format "%S%S%S%S%S%S%S%S"
ctl-wind A-wind B-wind C-wind ctl-wind A-wind B-wind C-wind Ancestor-wind
ediff-split-window-function ediff-split-window-function
(ediff-multiframe-setup-p) (ediff-multiframe-setup-p)
ediff-wide-display-p))))))) ediff-wide-display-p)))))))