aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTino Calancha2017-03-14 16:12:29 +0900
committerTino Calancha2017-03-14 16:12:29 +0900
commit0f3d1b782353fd1fc0ab5f89d47d9e790f44e6b2 (patch)
tree0f9e4ae51b5bb2aaddc5f38d51c5e25a1bab78d6
parente39d593475300ff388cdb69c8134ad513e9310e7 (diff)
downloademacs-0f3d1b782353fd1fc0ab5f89d47d9e790f44e6b2.tar.gz
emacs-0f3d1b782353fd1fc0ab5f89d47d9e790f44e6b2.zip
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.
-rw-r--r--doc/misc/ediff.texi8
-rw-r--r--etc/NEWS5
-rw-r--r--lisp/vc/ediff-help.el2
-rw-r--r--lisp/vc/ediff-init.el10
-rw-r--r--lisp/vc/ediff-util.el155
-rw-r--r--lisp/vc/ediff-wind.el86
6 files changed, 197 insertions, 69 deletions
diff --git a/doc/misc/ediff.texi b/doc/misc/ediff.texi
index 19b7adbd668..87d3dfd6ed9 100644
--- a/doc/misc/ediff.texi
+++ b/doc/misc/ediff.texi
@@ -99,7 +99,8 @@ through them. You can also copy difference regions from one buffer to
99another (and recover old differences if you change your mind). 99another (and recover old differences if you change your mind).
100 100
101Another powerful feature is the ability to merge a pair of files into a 101Another powerful feature is the ability to merge a pair of files into a
102third buffer. Merging with an ancestor file is also supported. 102third buffer. Merging with an ancestor file, (a.k.a. 3way merges)
103is also supported.
103Furthermore, Ediff is equipped with directory-level capabilities that 104Furthermore, Ediff is equipped with directory-level capabilities that
104allow the user to conveniently launch browsing or merging sessions on 105allow the user to conveniently launch browsing or merging sessions on
105groups of files in two (or three) different directories. 106groups of files in two (or three) different directories.
@@ -828,7 +829,10 @@ region in buffer A, etc.
828 829
829@item / 830@item /
830@kindex / 831@kindex /
831Displays the ancestor file during merges. 832@vindex ediff-show-ancestor
833Toggle to display the ancestor file in 3way merges.
834You can enable permanently this setting customizing the variable
835@code{ediff-show-ancestor}.
832@item & 836@item &
833@kindex & 837@kindex &
834In some situations, such as when one of the files agrees with the ancestor file 838In some situations, such as when one of the files agrees with the ancestor file
diff --git a/etc/NEWS b/etc/NEWS
index a51b650fe94..e1b6249d475 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -366,6 +366,11 @@ words where first character is upper rather than title case, e.g.,
366 366
367* Changes in Specialized Modes and Packages in Emacs 26.1 367* Changes in Specialized Modes and Packages in Emacs 26.1
368 368
369+++
370*** The ancestor buffer is shown by default in 3way merges.
371A new option ediff-show-ancestor and a new toggle
372ediff-toggle-show-ancestor.
373
369** TeX: Add luatex and xetex as alternatives to pdftex 374** TeX: Add luatex and xetex as alternatives to pdftex
370 375
371** Electric-Buffer-menu 376** Electric-Buffer-menu
diff --git a/lisp/vc/ediff-help.el b/lisp/vc/ediff-help.el
index 3292b4d939d..52a48252075 100644
--- a/lisp/vc/ediff-help.el
+++ b/lisp/vc/ediff-help.el
@@ -112,7 +112,7 @@ n,SPC -next diff | h -highlighting | r -restore buf C's old diff
112 C-l -recenter | #f/#h -focus/hide regions | + -combine diff regions 112 C-l -recenter | #f/#h -focus/hide regions | + -combine diff regions
113 v/V -scroll up/dn | X -read-only in buf X | wx -save buf X 113 v/V -scroll up/dn | X -read-only in buf X | wx -save buf X
114 </> -scroll lt/rt | m -wide display | wd -save diff output 114 </> -scroll lt/rt | m -wide display | wd -save diff output
115 ~ -swap variants | s -shrink window C | / -show ancestor buff 115 ~ -swap variants | s -shrink window C | / -show/hide ancestor buff
116 | $$ -show clashes only | & -merge w/new default 116 | $$ -show clashes only | & -merge w/new default
117 | $* -skip changed regions | 117 | $* -skip changed regions |
118" 118"
diff --git a/lisp/vc/ediff-init.el b/lisp/vc/ediff-init.el
index 535fdbfc904..e0542688593 100644
--- a/lisp/vc/ediff-init.el
+++ b/lisp/vc/ediff-init.el
@@ -1363,6 +1363,16 @@ This property can be toggled interactively."
1363;; if nil, this silences some messages 1363;; if nil, this silences some messages
1364(defvar ediff-verbose-p t) 1364(defvar ediff-verbose-p t)
1365 1365
1366(defcustom ediff-show-ancestor t
1367"If non-nil, show ancestor buffer in 3way merges and refine it."
1368 :type 'boolean
1369 :group 'ediff-merge
1370 :version "26.1")
1371
1372;; Store orig value of `ediff-show-ancestor' when changed in
1373;; `ediff-toggle-show-ancestor' and restore it on exit.
1374(ediff-defvar-local ediff--show-ancestor-orig nil "")
1375
1366(defcustom ediff-autostore-merges 'group-jobs-only 1376(defcustom ediff-autostore-merges 'group-jobs-only
1367 "Save the results of merge jobs automatically. 1377 "Save the results of merge jobs automatically.
1368With value nil, don't save automatically. With value t, always 1378With value nil, don't save automatically. With value t, always
diff --git a/lisp/vc/ediff-util.el b/lisp/vc/ediff-util.el
index f81397950dd..549066e1eca 100644
--- a/lisp/vc/ediff-util.el
+++ b/lisp/vc/ediff-util.el
@@ -178,7 +178,7 @@ to invocation.")
178 (define-key ediff-mode-map "r" nil) 178 (define-key ediff-mode-map "r" nil)
179 (cond (ediff-merge-job 179 (cond (ediff-merge-job
180 ;; Will barf if no ancestor 180 ;; Will barf if no ancestor
181 (define-key ediff-mode-map "/" 'ediff-show-ancestor) 181 (define-key ediff-mode-map "/" 'ediff-toggle-show-ancestor)
182 ;; In merging, we allow only A->C and B->C copying. 182 ;; In merging, we allow only A->C and B->C copying.
183 (define-key ediff-mode-map "a" 'ediff-copy-A-to-C) 183 (define-key ediff-mode-map "a" 'ediff-copy-A-to-C)
184 (define-key ediff-mode-map "b" 'ediff-copy-B-to-C) 184 (define-key ediff-mode-map "b" 'ediff-copy-B-to-C)
@@ -553,11 +553,12 @@ to invocation.")
553 (ediff-refresh-mode-lines) 553 (ediff-refresh-mode-lines)
554 (setq ediff-control-window (selected-window)) 554 (setq ediff-control-window (selected-window))
555 (setq ediff-window-config-saved 555 (setq ediff-window-config-saved
556 (format "%S%S%S%S%S%S%S" 556 (format "%S%S%S%S%S%S%S%S"
557 ediff-control-window 557 ediff-control-window
558 ediff-window-A 558 ediff-window-A
559 ediff-window-B 559 ediff-window-B
560 ediff-window-C 560 ediff-window-C
561 ediff-window-Ancestor
561 ediff-split-window-function 562 ediff-split-window-function
562 (ediff-multiframe-setup-p) 563 (ediff-multiframe-setup-p)
563 ediff-wide-display-p)) 564 ediff-wide-display-p))
@@ -600,12 +601,6 @@ to these buffers are not saved at this point---the user can do this later,
600if necessary." 601if necessary."
601 (interactive) 602 (interactive)
602 (ediff-barf-if-not-control-buffer) 603 (ediff-barf-if-not-control-buffer)
603 (if (and (ediff-buffer-live-p ediff-ancestor-buffer)
604 (not
605 (y-or-n-p
606 "Ancestor buffer will not be used. Recompute diffs anyway? ")))
607 (error "Recomputation of differences canceled"))
608
609 (let ((point-A (ediff-with-current-buffer ediff-buffer-A (point))) 604 (let ((point-A (ediff-with-current-buffer ediff-buffer-A (point)))
610 ;;(point-B (ediff-with-current-buffer ediff-buffer-B (point))) 605 ;;(point-B (ediff-with-current-buffer ediff-buffer-B (point)))
611 (tmp-buffer (get-buffer-create ediff-tmp-buffer)) 606 (tmp-buffer (get-buffer-create ediff-tmp-buffer))
@@ -614,14 +609,17 @@ if necessary."
614 ;; (null ediff-buffer-C) is no problem, as we later check if 609 ;; (null ediff-buffer-C) is no problem, as we later check if
615 ;; ediff-buffer-C is alive 610 ;; ediff-buffer-C is alive
616 (buf-C-file-name (buffer-file-name ediff-buffer-C)) 611 (buf-C-file-name (buffer-file-name ediff-buffer-C))
612 (buf-ancestor-file-name (buffer-file-name ediff-ancestor-buffer))
617 (overl-A (ediff-get-value-according-to-buffer-type 613 (overl-A (ediff-get-value-according-to-buffer-type
618 'A ediff-narrow-bounds)) 614 'A ediff-narrow-bounds))
619 (overl-B (ediff-get-value-according-to-buffer-type 615 (overl-B (ediff-get-value-according-to-buffer-type
620 'B ediff-narrow-bounds)) 616 'B ediff-narrow-bounds))
621 (overl-C (ediff-get-value-according-to-buffer-type 617 (overl-C (ediff-get-value-according-to-buffer-type
622 'C ediff-narrow-bounds)) 618 'C ediff-narrow-bounds))
623 beg-A end-A beg-B end-B beg-C end-C 619 (overl-Ancestor (ediff-get-value-according-to-buffer-type
624 file-A file-B file-C) 620 'Ancestor ediff-narrow-bounds))
621 beg-A end-A beg-B end-B beg-C end-C beg-Ancestor end-Ancestor
622 file-A file-B file-C file-Ancestor)
625 623
626 (if (stringp buf-A-file-name) 624 (if (stringp buf-A-file-name)
627 (setq buf-A-file-name (file-name-nondirectory buf-A-file-name))) 625 (setq buf-A-file-name (file-name-nondirectory buf-A-file-name)))
@@ -629,15 +627,19 @@ if necessary."
629 (setq buf-B-file-name (file-name-nondirectory buf-B-file-name))) 627 (setq buf-B-file-name (file-name-nondirectory buf-B-file-name)))
630 (if (stringp buf-C-file-name) 628 (if (stringp buf-C-file-name)
631 (setq buf-C-file-name (file-name-nondirectory buf-C-file-name))) 629 (setq buf-C-file-name (file-name-nondirectory buf-C-file-name)))
630 (if (stringp buf-ancestor-file-name)
631 (setq buf-ancestor-file-name (file-name-nondirectory buf-ancestor-file-name)))
632 632
633 (ediff-unselect-and-select-difference -1) 633 (ediff-unselect-and-select-difference -1)
634 634
635 (setq beg-A (ediff-overlay-start overl-A) 635 (setq beg-A (ediff-overlay-start overl-A)
636 beg-B (ediff-overlay-start overl-B) 636 beg-B (ediff-overlay-start overl-B)
637 beg-C (ediff-overlay-start overl-C) 637 beg-C (ediff-overlay-start overl-C)
638 beg-Ancestor (ediff-overlay-start overl-Ancestor)
638 end-A (ediff-overlay-end overl-A) 639 end-A (ediff-overlay-end overl-A)
639 end-B (ediff-overlay-end overl-B) 640 end-B (ediff-overlay-end overl-B)
640 end-C (ediff-overlay-end overl-C)) 641 end-C (ediff-overlay-end overl-C)
642 end-Ancestor (ediff-overlay-end overl-Ancestor))
641 643
642 (if ediff-word-mode 644 (if ediff-word-mode
643 (progn 645 (progn
@@ -645,51 +647,37 @@ if necessary."
645 (setq file-A (ediff-make-temp-file tmp-buffer "regA")) 647 (setq file-A (ediff-make-temp-file tmp-buffer "regA"))
646 (ediff-wordify beg-B end-B ediff-buffer-B tmp-buffer) 648 (ediff-wordify beg-B end-B ediff-buffer-B tmp-buffer)
647 (setq file-B (ediff-make-temp-file tmp-buffer "regB")) 649 (setq file-B (ediff-make-temp-file tmp-buffer "regB"))
648 (if ediff-3way-job 650 (when ediff-3way-job
649 (progn 651 (ediff-wordify beg-C end-C ediff-buffer-C tmp-buffer)
650 (ediff-wordify beg-C end-C ediff-buffer-C tmp-buffer) 652 (setq file-C (ediff-make-temp-file tmp-buffer "regC")))
651 (setq file-C (ediff-make-temp-file tmp-buffer "regC")))) 653 (when ediff-merge-with-ancestor-job
654 (ediff-wordify beg-Ancestor end-Ancestor ediff-ancestor-buffer tmp-buffer)
655 (setq file-Ancestor (ediff-make-temp-file tmp-buffer "regAncestor")))
652 ) 656 )
653 ;; not word-mode 657 ;; not word-mode
654 (setq file-A (ediff-make-temp-file ediff-buffer-A buf-A-file-name)) 658 (setq file-A (ediff-make-temp-file ediff-buffer-A buf-A-file-name))
655 (setq file-B (ediff-make-temp-file ediff-buffer-B buf-B-file-name)) 659 (setq file-B (ediff-make-temp-file ediff-buffer-B buf-B-file-name))
656 (if ediff-3way-job 660 (if ediff-3way-job
657 (setq file-C (ediff-make-temp-file ediff-buffer-C buf-C-file-name))) 661 (setq file-C (ediff-make-temp-file ediff-buffer-C buf-C-file-name)))
662 (when ediff-merge-with-ancestor-job
663 (setq file-Ancestor
664 (ediff-make-temp-file
665 ediff-ancestor-buffer
666 buf-ancestor-file-name)))
658 ) 667 )
659
660 (ediff-clear-diff-vector 'ediff-difference-vector-A 'fine-diffs-also) 668 (ediff-clear-diff-vector 'ediff-difference-vector-A 'fine-diffs-also)
661 (ediff-clear-diff-vector 'ediff-difference-vector-B 'fine-diffs-also) 669 (ediff-clear-diff-vector 'ediff-difference-vector-B 'fine-diffs-also)
662 (ediff-clear-diff-vector 'ediff-difference-vector-C 'fine-diffs-also) 670 (ediff-clear-diff-vector 'ediff-difference-vector-C 'fine-diffs-also)
663 (ediff-clear-diff-vector 671 (ediff-clear-diff-vector
664 'ediff-difference-vector-Ancestor 'fine-diffs-also) 672 'ediff-difference-vector-Ancestor 'fine-diffs-also)
665 ;; let them garbage collect. we can't use the ancestor after recomputing
666 ;; the diffs.
667 (setq ediff-difference-vector-Ancestor nil
668 ediff-ancestor-buffer nil
669 ediff-state-of-merge nil)
670
671 (setq ediff-killed-diffs-alist nil) ; invalidate saved killed diff regions 673 (setq ediff-killed-diffs-alist nil) ; invalidate saved killed diff regions
672 674 (funcall ediff-setup-diff-regions-function file-A file-B
673 ;; In case of merge job, fool it into thinking that it is just doing 675 (if ediff-merge-with-ancestor-job file-Ancestor file-C))
674 ;; comparison
675 (let ((ediff-setup-diff-regions-function ediff-setup-diff-regions-function)
676 (ediff-3way-comparison-job ediff-3way-comparison-job)
677 (ediff-merge-job ediff-merge-job)
678 (ediff-merge-with-ancestor-job ediff-merge-with-ancestor-job)
679 (ediff-job-name ediff-job-name))
680 (if ediff-merge-job
681 (setq ediff-setup-diff-regions-function 'ediff-setup-diff-regions3
682 ediff-3way-comparison-job t
683 ediff-merge-job nil
684 ediff-merge-with-ancestor-job nil
685 ediff-job-name 'ediff-files3))
686 (funcall ediff-setup-diff-regions-function file-A file-B file-C))
687
688 (setq ediff-number-of-differences (length ediff-difference-vector-A)) 676 (setq ediff-number-of-differences (length ediff-difference-vector-A))
689 (delete-file file-A) 677 (delete-file file-A)
690 (delete-file file-B) 678 (delete-file file-B)
691 (if file-C 679 (and file-C (delete-file file-C))
692 (delete-file file-C)) 680 (and file-Ancestor (delete-file file-Ancestor))
693 681
694 (if ediff-3way-job 682 (if ediff-3way-job
695 (ediff-set-state-of-all-diffs-in-all-buffers ediff-control-buffer)) 683 (ediff-set-state-of-all-diffs-in-all-buffers ediff-control-buffer))
@@ -737,14 +725,16 @@ if necessary."
737;; optional NO-REHIGHLIGHT says to not rehighlight buffers 725;; optional NO-REHIGHLIGHT says to not rehighlight buffers
738(defun ediff-recenter (&optional no-rehighlight) 726(defun ediff-recenter (&optional no-rehighlight)
739 "Bring the highlighted region of all buffers being compared into view. 727 "Bring the highlighted region of all buffers being compared into view.
740Reestablish the default three-window display." 728Reestablish the default window display."
741 (interactive) 729 (interactive)
742 (ediff-barf-if-not-control-buffer) 730 (ediff-barf-if-not-control-buffer)
743 (let (buffer-read-only) 731 (let (buffer-read-only)
744 (if (and (ediff-buffer-live-p ediff-buffer-A) 732 (if (and (ediff-buffer-live-p ediff-buffer-A)
745 (ediff-buffer-live-p ediff-buffer-B) 733 (ediff-buffer-live-p ediff-buffer-B)
746 (or (not ediff-3way-job) 734 (or (not ediff-3way-job)
747 (ediff-buffer-live-p ediff-buffer-C))) 735 (ediff-buffer-live-p ediff-buffer-C))
736 (or (not ediff-merge-with-ancestor-job)
737 (ediff-buffer-live-p ediff-ancestor-buffer)))
748 (ediff-setup-windows 738 (ediff-setup-windows
749 ediff-buffer-A ediff-buffer-B ediff-buffer-C ediff-control-buffer) 739 ediff-buffer-A ediff-buffer-B ediff-buffer-C ediff-control-buffer)
750 (or (eq this-command 'ediff-quit) 740 (or (eq this-command 'ediff-quit)
@@ -963,18 +953,43 @@ On a dumb terminal, switches between ASCII highlighting and no highlighting."
963 (setq ediff-auto-refine 'nix)) 953 (setq ediff-auto-refine 'nix))
964 )) 954 ))
965 955
966(defun ediff-show-ancestor () 956(defun ediff--check-ancestor-exists ()
967 "Show the ancestor buffer in a suitable window."
968 (interactive)
969 (ediff-recenter)
970 (or (ediff-buffer-live-p ediff-ancestor-buffer) 957 (or (ediff-buffer-live-p ediff-ancestor-buffer)
971 (if ediff-merge-with-ancestor-job 958 (if ediff-merge-with-ancestor-job
972 (error "Lost connection to ancestor buffer...sorry") 959 (error "Lost connection to ancestor buffer. This shouldn't happen. \
973 (error "Not merging with ancestor"))) 960Please report this bug to bug-gnu-emacs@gnu.org")
974 (let (wind) 961 (error "Not merging with ancestor"))))
975 (cond ((setq wind (ediff-get-visible-buffer-window ediff-ancestor-buffer)) 962
976 (raise-frame (window-frame wind))) 963;; Restore `ediff-show-ancestor' on exit.
977 (t (set-window-buffer ediff-window-C ediff-ancestor-buffer))))) 964(defun ediff--restore-options-on-exit ()
965 (message "Restoring ediff-show-ancestor to %S..." ediff--show-ancestor-orig)
966 (setq ediff-show-ancestor ediff--show-ancestor-orig
967 ediff--show-ancestor-orig nil)
968 (remove-hook 'ediff-quit-hook #'ediff--restore-options-on-exit))
969
970(defun ediff-toggle-show-ancestor ()
971 "Toggle to show/hide the ancestor buffer."
972 (interactive)
973 (ediff--check-ancestor-exists)
974 ;; Save original value if not yet, and add hook to restore it on exit.
975 (unless ediff--show-ancestor-orig
976 (setq ediff--show-ancestor-orig ediff-show-ancestor)
977 (add-hook 'ediff-quit-hook #'ediff--restore-options-on-exit))
978 (setq ediff-show-ancestor (not ediff-show-ancestor))
979 ;; If equal than orig, then nothing to restore on exit.
980 (when (eq ediff-show-ancestor ediff--show-ancestor-orig)
981 (setq ediff--show-ancestor-orig nil)
982 (remove-hook 'ediff-quit-hook #'ediff--restore-options-on-exit))
983 (if (not ediff-show-ancestor)
984 (progn
985 (delete-window ediff-window-Ancestor)
986 (ediff-recenter)
987 (message "Ancestor buffer is hidden"))
988 (let ((wind
989 (ediff-get-visible-buffer-window ediff-ancestor-buffer)))
990 (when wind (raise-frame (window-frame wind))))
991 (ediff-recenter)
992 (message "Showing ancestor buffer")))
978 993
979(defun ediff-make-or-kill-fine-diffs (arg) 994(defun ediff-make-or-kill-fine-diffs (arg)
980 "Compute fine diffs. With negative prefix arg, kill fine diffs. 995 "Compute fine diffs. With negative prefix arg, kill fine diffs.
@@ -1468,7 +1483,10 @@ Used in ediff-windows/regions only."
1468 (ediff-recenter 'no-rehighlight)) 1483 (ediff-recenter 'no-rehighlight))
1469 (if (not (and (ediff-buffer-live-p ediff-buffer-A) 1484 (if (not (and (ediff-buffer-live-p ediff-buffer-A)
1470 (ediff-buffer-live-p ediff-buffer-B) 1485 (ediff-buffer-live-p ediff-buffer-B)
1471 (or (not ediff-3way-job) ediff-buffer-C) 1486 (or (not ediff-3way-job) (ediff-buffer-live-p ediff-buffer-C))
1487 (or (not ediff-merge-with-ancestor-job)
1488 (not ediff-show-ancestor)
1489 (ediff-buffer-live-p ediff-ancestor-buffer))
1472 )) 1490 ))
1473 (error ediff-KILLED-VITAL-BUFFER)) 1491 (error ediff-KILLED-VITAL-BUFFER))
1474 1492
@@ -1476,11 +1494,15 @@ Used in ediff-windows/regions only."
1476 (wind-A ediff-window-A) 1494 (wind-A ediff-window-A)
1477 (wind-B ediff-window-B) 1495 (wind-B ediff-window-B)
1478 (wind-C ediff-window-C) 1496 (wind-C ediff-window-C)
1497 (wind-Anc ediff-window-Ancestor)
1479 (coefA (ediff-get-region-size-coefficient 'A operation)) 1498 (coefA (ediff-get-region-size-coefficient 'A operation))
1480 (coefB (ediff-get-region-size-coefficient 'B operation)) 1499 (coefB (ediff-get-region-size-coefficient 'B operation))
1481 (three-way ediff-3way-job) 1500 (three-way ediff-3way-job)
1501 (with-Ancestor (and ediff-merge-with-ancestor-job ediff-show-ancestor))
1482 (coefC (if three-way 1502 (coefC (if three-way
1483 (ediff-get-region-size-coefficient 'C operation)))) 1503 (ediff-get-region-size-coefficient 'C operation)))
1504 (coefAnc (if with-Ancestor
1505 (ediff-get-region-size-coefficient 'Ancestor operation))))
1484 1506
1485 (select-window wind-A) 1507 (select-window wind-A)
1486 (condition-case nil 1508 (condition-case nil
@@ -1496,6 +1518,11 @@ Used in ediff-windows/regions only."
1496 (condition-case nil 1518 (condition-case nil
1497 (funcall operation (round (* coefC arg))) 1519 (funcall operation (round (* coefC arg)))
1498 (error)))) 1520 (error))))
1521 (when with-Ancestor
1522 (select-window wind-Anc)
1523 (condition-case nil
1524 (funcall operation (round (* coefAnc arg)))
1525 (error)))
1499 (select-window wind))) 1526 (select-window wind)))
1500 1527
1501(defun ediff-scroll-vertically (&optional arg) 1528(defun ediff-scroll-vertically (&optional arg)
@@ -1512,6 +1539,9 @@ the one half of the height of window-A."
1512 (ediff-buffer-live-p ediff-buffer-B) 1539 (ediff-buffer-live-p ediff-buffer-B)
1513 (or (not ediff-3way-job) 1540 (or (not ediff-3way-job)
1514 (ediff-buffer-live-p ediff-buffer-C)) 1541 (ediff-buffer-live-p ediff-buffer-C))
1542 (or (not ediff-merge-with-ancestor-job)
1543 (not ediff-show-ancestor)
1544 (ediff-buffer-live-p ediff-ancestor-buffer))
1515 )) 1545 ))
1516 (error ediff-KILLED-VITAL-BUFFER)) 1546 (error ediff-KILLED-VITAL-BUFFER))
1517 1547
@@ -1531,6 +1561,10 @@ the one half of the height of window-A."
1531 (window-height ediff-window-B) 1561 (window-height ediff-window-B)
1532 (if ediff-3way-job 1562 (if ediff-3way-job
1533 (window-height ediff-window-C) 1563 (window-height ediff-window-C)
1564 500) ; some large number
1565 (if (and ediff-merge-with-ancestor-job
1566 ediff-show-ancestor)
1567 (window-height ediff-window-Ancestor)
1534 500)) ; some large number 1568 500)) ; some large number
1535 2) 1569 2)
1536 1 next-screen-context-lines)) 1570 1 next-screen-context-lines))
@@ -1556,6 +1590,9 @@ the width of the A/B/C windows."
1556 (ediff-buffer-live-p ediff-buffer-B) 1590 (ediff-buffer-live-p ediff-buffer-B)
1557 (or (not ediff-3way-job) 1591 (or (not ediff-3way-job)
1558 (ediff-buffer-live-p ediff-buffer-C)) 1592 (ediff-buffer-live-p ediff-buffer-C))
1593 (or (not ediff-merge-with-ancestor-job)
1594 (not ediff-show-ancestor)
1595 (ediff-buffer-live-p ediff-ancestor-buffer))
1559 )) 1596 ))
1560 (error ediff-KILLED-VITAL-BUFFER)) 1597 (error ediff-KILLED-VITAL-BUFFER))
1561 1598
@@ -1587,7 +1624,10 @@ the width of the A/B/C windows."
1587 (if ediff-3way-comparison-job 1624 (if ediff-3way-comparison-job
1588 (window-width ediff-window-C) 1625 (window-width ediff-window-C)
1589 500) ; some large number 1626 500) ; some large number
1590 ) 1627 (if (and ediff-merge-with-ancestor-job
1628 ediff-show-ancestor)
1629 (window-height ediff-window-Ancestor)
1630 500)) ; some large number
1591 2) 1631 2)
1592 3))) 1632 3)))
1593 ;; window found 1633 ;; window found
@@ -1689,6 +1729,11 @@ the width of the A/B/C windows."
1689 (funcall func 'B n ctl-buf) 1729 (funcall func 'B n ctl-buf)
1690 (if (ediff-buffer-live-p ediff-buffer-C) 1730 (if (ediff-buffer-live-p ediff-buffer-C)
1691 (funcall func 'C n ctl-buf) 1731 (funcall func 'C n ctl-buf)
1732 0)
1733 (if (and ediff-merge-with-ancestor-job
1734 ediff-show-ancestor
1735 (ediff-buffer-live-p ediff-ancestor-buffer))
1736 (funcall func 'Ancestor n ctl-buf)
1692 0)))) 1737 0))))
1693 ;; this covers the horizontal coefficient as well: 1738 ;; this covers the horizontal coefficient as well:
1694 ;; if max-lines = 0 then coef = 1 1739 ;; if max-lines = 0 then coef = 1
diff --git a/lisp/vc/ediff-wind.el b/lisp/vc/ediff-wind.el
index cd10288643d..8516c11d136 100644
--- a/lisp/vc/ediff-wind.el
+++ b/lisp/vc/ediff-wind.el
@@ -115,6 +115,8 @@ provided functions are written."
115(ediff-defvar-local ediff-window-B nil "") 115(ediff-defvar-local ediff-window-B nil "")
116;; Official window for buffer C 116;; Official window for buffer C
117(ediff-defvar-local ediff-window-C nil "") 117(ediff-defvar-local ediff-window-C nil "")
118;; Official window for buffer Ancestor
119(ediff-defvar-local ediff-window-Ancestor nil "")
118;; Ediff's window configuration. 120;; Ediff's window configuration.
119;; Used to minimize the need to rearrange windows. 121;; Used to minimize the need to rearrange windows.
120(ediff-defvar-local ediff-window-config-saved "" "") 122(ediff-defvar-local ediff-window-config-saved "" "")
@@ -126,7 +128,8 @@ provided functions are written."
126 (B . ediff-window-B) 128 (B . ediff-window-B)
127 (?B . ediff-window-B) 129 (?B . ediff-window-B)
128 (C . ediff-window-C) 130 (C . ediff-window-C)
129 (?C . ediff-window-C))) 131 (?C . ediff-window-C)
132 (Ancestor . ediff-window-Ancestor)))
130 133
131 134
132(defcustom ediff-split-window-function 'split-window-vertically 135(defcustom ediff-split-window-function 'split-window-vertically
@@ -363,9 +366,13 @@ into icons, regardless of the window manager."
363 ;; skip dedicated and unsplittable frames 366 ;; skip dedicated and unsplittable frames
364 (ediff-destroy-control-frame control-buffer) 367 (ediff-destroy-control-frame control-buffer)
365 (let ((window-min-height 1) 368 (let ((window-min-height 1)
369 (with-Ancestor-p (ediff-with-current-buffer control-buffer
370 ediff-merge-with-ancestor-job))
366 split-window-function 371 split-window-function
367 merge-window-share merge-window-lines 372 merge-window-share merge-window-lines
368 wind-A wind-B wind-C) 373 (buf-Ancestor (ediff-with-current-buffer control-buffer
374 ediff-ancestor-buffer))
375 wind-A wind-B wind-C wind-Ancestor)
369 (ediff-with-current-buffer control-buffer 376 (ediff-with-current-buffer control-buffer
370 (setq merge-window-share ediff-merge-window-share 377 (setq merge-window-share ediff-merge-window-share
371 ;; this lets us have local versions of ediff-split-window-function 378 ;; this lets us have local versions of ediff-split-window-function
@@ -394,6 +401,14 @@ into icons, regardless of the window manager."
394 (setq wind-C (selected-window)) 401 (setq wind-C (selected-window))
395 (switch-to-buffer buf-C) 402 (switch-to-buffer buf-C)
396 403
404 (when (and ediff-show-ancestor with-Ancestor-p)
405 (select-window wind-C)
406 (funcall split-window-function)
407 (when (eq (selected-window) wind-C)
408 (other-window 1))
409 (switch-to-buffer buf-Ancestor)
410 (setq wind-Ancestor (selected-window)))
411
397 (select-window wind-A) 412 (select-window wind-A)
398 (funcall split-window-function) 413 (funcall split-window-function)
399 414
@@ -405,7 +420,8 @@ into icons, regardless of the window manager."
405 (ediff-with-current-buffer control-buffer 420 (ediff-with-current-buffer control-buffer
406 (setq ediff-window-A wind-A 421 (setq ediff-window-A wind-A
407 ediff-window-B wind-B 422 ediff-window-B wind-B
408 ediff-window-C wind-C)) 423 ediff-window-C wind-C
424 ediff-window-Ancestor wind-Ancestor))
409 425
410 (ediff-select-lowest-window) 426 (ediff-select-lowest-window)
411 (ediff-setup-control-buffer control-buffer) 427 (ediff-setup-control-buffer control-buffer)
@@ -516,9 +532,13 @@ into icons, regardless of the window manager."
516 (wind-A (ediff-get-visible-buffer-window buf-A)) 532 (wind-A (ediff-get-visible-buffer-window buf-A))
517 (wind-B (ediff-get-visible-buffer-window buf-B)) 533 (wind-B (ediff-get-visible-buffer-window buf-B))
518 (wind-C (ediff-get-visible-buffer-window buf-C)) 534 (wind-C (ediff-get-visible-buffer-window buf-C))
535 (buf-Ancestor (ediff-with-current-buffer control-buf
536 ediff-ancestor-buffer))
537 (wind-Ancestor (ediff-get-visible-buffer-window buf-Ancestor))
519 (frame-A (if wind-A (window-frame wind-A))) 538 (frame-A (if wind-A (window-frame wind-A)))
520 (frame-B (if wind-B (window-frame wind-B))) 539 (frame-B (if wind-B (window-frame wind-B)))
521 (frame-C (if wind-C (window-frame wind-C))) 540 (frame-C (if wind-C (window-frame wind-C)))
541 (frame-Ancestor (if wind-Ancestor (window-frame wind-Ancestor)))
522 ;; on wide display, do things in one frame 542 ;; on wide display, do things in one frame
523 (force-one-frame 543 (force-one-frame
524 (ediff-with-current-buffer control-buf ediff-wide-display-p)) 544 (ediff-with-current-buffer control-buf ediff-wide-display-p))
@@ -549,7 +569,10 @@ into icons, regardless of the window manager."
549 (merge-window-share (ediff-with-current-buffer control-buf 569 (merge-window-share (ediff-with-current-buffer control-buf
550 ediff-merge-window-share)) 570 ediff-merge-window-share))
551 merge-window-lines 571 merge-window-lines
552 designated-minibuffer-frame 572 designated-minibuffer-frame ; ediff-merge-with-ancestor-job
573 (with-Ancestor-p (ediff-with-current-buffer control-buf
574 ediff-merge-with-ancestor-job))
575 (done-Ancestor (not with-Ancestor-p))
553 done-A done-B done-C) 576 done-A done-B done-C)
554 577
555 ;; buf-A on its own 578 ;; buf-A on its own
@@ -585,6 +608,19 @@ into icons, regardless of the window manager."
585 (setq wind-C (selected-window)) 608 (setq wind-C (selected-window))
586 (setq done-C t))) 609 (setq done-C t)))
587 610
611 ;; buf-Ancestor on its own
612 (if (and ediff-show-ancestor
613 with-Ancestor-p
614 (window-live-p wind-Ancestor)
615 (ediff-window-ok-for-display wind-Ancestor)
616 (null use-same-frame)) ; buf Ancestor on its own
617 (progn
618 ;; buffer buf-Ancestor is seen in live wind-Ancestor
619 (select-window wind-Ancestor)
620 (delete-other-windows)
621 (setq wind-Ancestor (selected-window))
622 (setq done-Ancestor t)))
623
588 (if (and use-same-frame-for-AB ; implies wind A and B are suitable 624 (if (and use-same-frame-for-AB ; implies wind A and B are suitable
589 (window-live-p wind-A)) 625 (window-live-p wind-A))
590 (progn 626 (progn
@@ -606,6 +642,7 @@ into icons, regardless of the window manager."
606 (let ((window-min-height 1)) 642 (let ((window-min-height 1))
607 (if (and (eq frame-A frame-B) 643 (if (and (eq frame-A frame-B)
608 (eq frame-B frame-C) 644 (eq frame-B frame-C)
645 (eq frame-C frame-Ancestor)
609 (frame-live-p frame-A)) 646 (frame-live-p frame-A))
610 (select-frame frame-A) 647 (select-frame frame-A)
611 ;; avoid dedicated and non-splittable windows 648 ;; avoid dedicated and non-splittable windows
@@ -623,6 +660,14 @@ into icons, regardless of the window manager."
623 (setq wind-C (selected-window)) 660 (setq wind-C (selected-window))
624 (switch-to-buffer buf-C) 661 (switch-to-buffer buf-C)
625 662
663 (when (and ediff-show-ancestor with-Ancestor-p)
664 (select-window wind-C)
665 (funcall split-window-function)
666 (if (eq (selected-window) wind-C)
667 (other-window 1))
668 (switch-to-buffer buf-Ancestor)
669 (setq wind-Ancestor (selected-window)))
670
626 (select-window wind-A) 671 (select-window wind-A)
627 672
628 (funcall split-window-function) 673 (funcall split-window-function)
@@ -633,8 +678,8 @@ into icons, regardless of the window manager."
633 678
634 (setq done-A t 679 (setq done-A t
635 done-B t 680 done-B t
636 done-C t) 681 done-C t
637 )) 682 done-Ancestor t)))
638 683
639 (or done-A ; Buf A to be set in its own frame, 684 (or done-A ; Buf A to be set in its own frame,
640 ;;; or it was set before because use-same-frame = 1 685 ;;; or it was set before because use-same-frame = 1
@@ -668,10 +713,22 @@ into icons, regardless of the window manager."
668 (setq wind-C (selected-window)) 713 (setq wind-C (selected-window))
669 )) 714 ))
670 715
716 (or done-Ancestor ; Buf Ancestor to be set in its own frame,
717 (not ediff-show-ancestor)
718 ;;; or it was set before because use-same-frame = 1
719 (progn
720 ;; Buf-Ancestor was not set up yet as it wasn't visible
721 ;; and use-same-frame = nil
722 (select-window orig-wind)
723 (delete-other-windows)
724 (switch-to-buffer buf-Ancestor)
725 (setq wind-Ancestor (selected-window))))
726
671 (ediff-with-current-buffer control-buf 727 (ediff-with-current-buffer control-buf
672 (setq ediff-window-A wind-A 728 (setq ediff-window-A wind-A
673 ediff-window-B wind-B 729 ediff-window-B wind-B
674 ediff-window-C wind-C) 730 ediff-window-C wind-C
731 ediff-window-Ancestor wind-Ancestor)
675 (setq frame-A (window-frame ediff-window-A) 732 (setq frame-A (window-frame ediff-window-A)
676 designated-minibuffer-frame 733 designated-minibuffer-frame
677 (window-frame (minibuffer-window frame-A)))) 734 (window-frame (minibuffer-window frame-A))))
@@ -679,7 +736,6 @@ into icons, regardless of the window manager."
679 (ediff-setup-control-frame control-buf designated-minibuffer-frame) 736 (ediff-setup-control-frame control-buf designated-minibuffer-frame)
680 )) 737 ))
681 738
682
683;; Window setup for all comparison jobs, including 3way comparisons 739;; Window setup for all comparison jobs, including 3way comparisons
684(defun ediff-setup-windows-multiframe-compare (buf-A buf-B buf-C control-buf) 740(defun ediff-setup-windows-multiframe-compare (buf-A buf-B buf-C control-buf)
685;;; Algorithm: 741;;; Algorithm:
@@ -1295,7 +1351,9 @@ It assumes that it is called from within the control buffer."
1295 (let ((ctl-wind ediff-control-window) 1351 (let ((ctl-wind ediff-control-window)
1296 (A-wind ediff-window-A) 1352 (A-wind ediff-window-A)
1297 (B-wind ediff-window-B) 1353 (B-wind ediff-window-B)
1298 (C-wind ediff-window-C)) 1354 (C-wind ediff-window-C)
1355 (ancestor-job ediff-merge-with-ancestor-job)
1356 (Ancestor-wind ediff-window-Ancestor))
1299 1357
1300 (and 1358 (and
1301 (ediff-window-visible-p A-wind) 1359 (ediff-window-visible-p A-wind)
@@ -1303,13 +1361,19 @@ It assumes that it is called from within the control buffer."
1303 ;; if buffer C is defined then take it into account 1361 ;; if buffer C is defined then take it into account
1304 (or (not ediff-3way-job) 1362 (or (not ediff-3way-job)
1305 (ediff-window-visible-p C-wind)) 1363 (ediff-window-visible-p C-wind))
1364 (or (not ancestor-job)
1365 (not ediff-show-ancestor)
1366 (ediff-window-visible-p Ancestor-wind))
1306 (eq (window-buffer A-wind) ediff-buffer-A) 1367 (eq (window-buffer A-wind) ediff-buffer-A)
1307 (eq (window-buffer B-wind) ediff-buffer-B) 1368 (eq (window-buffer B-wind) ediff-buffer-B)
1308 (or (not ediff-3way-job) 1369 (or (not ediff-3way-job)
1309 (eq (window-buffer C-wind) ediff-buffer-C)) 1370 (eq (window-buffer C-wind) ediff-buffer-C))
1371 (or (not ancestor-job)
1372 (not ediff-show-ancestor)
1373 (eq (window-buffer Ancestor-wind) ediff-ancestor-buffer))
1310 (string= ediff-window-config-saved 1374 (string= ediff-window-config-saved
1311 (format "%S%S%S%S%S%S%S" 1375 (format "%S%S%S%S%S%S%S%S"
1312 ctl-wind A-wind B-wind C-wind 1376 ctl-wind A-wind B-wind C-wind Ancestor-wind
1313 ediff-split-window-function 1377 ediff-split-window-function
1314 (ediff-multiframe-setup-p) 1378 (ediff-multiframe-setup-p)
1315 ediff-wide-display-p))))))) 1379 ediff-wide-display-p)))))))