unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#25493: 26.0.50; ediff merge should (optionally) show ancestor in fourth window
@ 2017-01-20 11:17 Philipp Stephani
  2017-02-19 10:47 ` Tino Calancha
  0 siblings, 1 reply; 10+ messages in thread
From: Philipp Stephani @ 2017-01-20 11:17 UTC (permalink / raw)
  To: 25493


It would be very useful if ediff merge could optionally display the
ancestor in a fourth window, like vimdiff or meld.  See
https://lists.gnu.org/archive/html/emacs-devel/2017-01/msg00204.html.


In GNU Emacs 26.0.50.40 (x86_64-unknown-linux-gnu, GTK+ Version 3.10.8)
 of 2017-01-19 built on localhost
Repository revision: 8c0fcaf66733f0538a3f024f383cb34a3c93d73c
Windowing system distributor 'The X.Org Foundation', version 11.0.11501000
System Description:	Ubuntu 14.04 LTS

Recent messages:
For information about GNU Emacs and the GNU system, type C-h C-a.
Source file ‘/usr/local/google/home/phst/ThirdParty/Emacs/lisp/emacs-lisp/derived.el’ newer than byte-compiled file

Configured using:
 'configure --with-modules --enable-checking
 --enable-check-lisp-object-type 'CFLAGS=-ggdb3 -O0''

Configured features:
XPM JPEG TIFF GIF PNG SOUND GSETTINGS NOTIFY GNUTLS FREETYPE XFT ZLIB
TOOLKIT_SCROLL_BARS GTK3 X11 MODULES

Important settings:
  value of $LANG: en_US.UTF-8
  locale-coding-system: utf-8-unix

Major mode: Lisp Interaction

Minor modes in effect:
  tooltip-mode: t
  global-eldoc-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  tool-bar-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  line-number-mode: t
  transient-mark-mode: t

Load-path shadows:
None found.

Features:
(shadow sort mail-extr emacsbug message subr-x puny seq byte-opt gv
bytecomp byte-compile cl-extra help-mode cconv cl-loaddefs pcase cl-lib
dired dired-loaddefs format-spec rfc822 mml easymenu mml-sec
password-cache epa derived epg epg-config gnus-util rmail rmail-loaddefs
mm-decode mm-bodies mm-encode mail-parse rfc2231 mailabbrev gmm-utils
mailheader sendmail rfc2047 rfc2045 ietf-drums mm-util mail-prsvr
mail-utils time-date mule-util tooltip eldoc electric uniquify
ediff-hook vc-hooks lisp-float-type mwheel term/x-win x-win
term/common-win x-dnd tool-bar dnd fontset image regexp-opt fringe
tabulated-list replace newcomment text-mode elisp-mode lisp-mode
prog-mode register page menu-bar rfn-eshadow isearch timer select
scroll-bar mouse jit-lock font-lock syntax facemenu font-core
term/tty-colors frame cl-generic cham georgian utf-8-lang misc-lang
vietnamese tibetan thai tai-viet lao korean japanese eucjp-ms cp51932
hebrew greek romanian slovak czech european ethiopic indian cyrillic
chinese composite charscript case-table epa-hook jka-cmpr-hook help
simple abbrev obarray minibuffer cl-preloaded nadvice loaddefs button
faces cus-face macroexp files text-properties overlay sha1 md5 base64
format env code-pages mule custom widget hashtable-print-readable
backquote inotify dynamic-setting system-font-setting
font-render-setting move-toolbar gtk x-toolkit x multi-tty
make-network-process emacs)

Memory information:
((conses 16 97616 6566)
 (symbols 48 20221 1)
 (miscs 40 331 156)
 (strings 32 17989 4269)
 (string-bytes 1 592161)
 (vectors 16 14072)
 (vector-slots 8 471896 4520)
 (floats 8 181 46)
 (intervals 56 206 0)
 (buffers 976 12)
 (heap 1024 31236 1025))

-- 
Google Germany GmbH
Erika-Mann-Straße 33
80636 München

Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg
Geschäftsführer: Matthew Scott Sucherman, Paul Terence Manicle

Diese E-Mail ist vertraulich.  Wenn Sie nicht der richtige Adressat sind,
leiten Sie diese bitte nicht weiter, informieren Sie den Absender und löschen
Sie die E-Mail und alle Anhänge.  Vielen Dank.

This e-mail is confidential.  If you are not the right addressee please do not
forward it, please inform the sender, and please erase this e-mail including
any attachments.  Thanks.





^ permalink raw reply	[flat|nested] 10+ messages in thread

* bug#25493: 26.0.50; ediff merge should (optionally) show ancestor in fourth window
  2017-01-20 11:17 bug#25493: 26.0.50; ediff merge should (optionally) show ancestor in fourth window Philipp Stephani
@ 2017-02-19 10:47 ` Tino Calancha
  2017-02-26 11:35   ` Charles A. Roelli
  2017-03-04 23:06   ` npostavs
  0 siblings, 2 replies; 10+ messages in thread
From: Tino Calancha @ 2017-02-19 10:47 UTC (permalink / raw)
  To: Philipp Stephani; +Cc: 25493, tino.calancha

Philipp Stephani <p.stephani2@gmail.com> writes:

> It would be very useful if ediff merge could optionally display the
> ancestor in a fourth window, like vimdiff or meld.  See
> https://lists.gnu.org/archive/html/emacs-devel/2017-01/msg00204.html.

Following patch, by default, display the ancestor buffer and auto refine
it in 3way merges.
This feature can be disabled by customizing a new option.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; PATCH BEGINS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

From d1d0ef67e9d0a03ee5f60d56d13658f1a3d3a80a Mon Sep 17 00:00:00 2001
From: Tino Calancha <tino.calancha@gmail.com>
Date: Sun, 19 Feb 2017 19:15:04 +0900
Subject: [PATCH 1/3] Show ancestor buffer in 3way merges

Add an option to control if the ancestor buffer must
be shown in 3way merges (Bug#25493).
Add an option to control whether if show or ignore diffs with
ancestor that are equal in buffers A and B.
* lisp/vc/ediff-init.el (ediff-show-ancestor)
(ediff-hide-equal-diffs-with-ancestor): New options.
(ediff--restore-options-on-exit-alist): New defvar.
(ediff-get-value-according-to-buffer-type):
Add clause for the ancestor.
* lisp/vc/ediff-wind.el (ediff-window-Ancestor): New defvar.
(ediff-setup-windows-plain-merge, ediff-setup-windows-multiframe-merge):
Display ancestor buffer when ediff-show-ancestor is non-nil.
(ediff-keep-window-config): Expect ancestor window in
ediff-window-config-saved.
* lisp/vc/ediff-util.el (ediff-setup-control-buffer):
ediff-window-config-saved contains ancestor window.
(ediff-setup-keymap): New bindings for merge jobs:
bind ediff-toggle-show-ancestor to '\';
bind ediff-toggle-hide-equal-diffs-with-ancestor to '$%'.
(ediff-update-diffs): Compute new diffs using ancestor buffer.
(ediff--check-ancestor-exists): New defsubst extracted from
ediff-show-ancestor.
(ediff-swap-buffers): Take in account the ancestor.
(ediff-toggle-show-ancestor): New command; toggle ediff-show-ancestor.
(ediff-toggle-hide-equal-diffs-with-ancestor): New command; toggle
ediff-hide-equal-diffs-with-ancestor.
(ediff--restore-options-on-exit): Restore on exit option values changed
in previous toggles.
* lisp/vc/ediff-help.el (ediff-long-help-message-merge):
List the new toggles.
---
 lisp/vc/ediff-help.el |   2 +
 lisp/vc/ediff-init.el |  19 ++++++
 lisp/vc/ediff-util.el | 162 ++++++++++++++++++++++++++++++++++++--------------
 lisp/vc/ediff-wind.el |  83 ++++++++++++++++++++++----
 4 files changed, 210 insertions(+), 56 deletions(-)

diff --git a/lisp/vc/ediff-help.el b/lisp/vc/ediff-help.el
index 3292b4d939..89645d2f3b 100644
--- a/lisp/vc/ediff-help.el
+++ b/lisp/vc/ediff-help.el
@@ -115,6 +115,8 @@ ediff-long-help-message-merge
     ~ -swap variants |     s -shrink window C    |  / -show ancestor buff
                      |  $$ -show clashes only    |  & -merge w/new default
                      |  $* -skip changed regions |
+                     |  $% -all ancestor diffs   |
+                     |  \\ -show/hide ancestor    |
 "
   "Help message for merge sessions.
 Normally, not a user option.  See `ediff-help-message' for details.")
diff --git a/lisp/vc/ediff-init.el b/lisp/vc/ediff-init.el
index 0235926fbe..66a2a0f527 100644
--- a/lisp/vc/ediff-init.el
+++ b/lisp/vc/ediff-init.el
@@ -134,6 +134,7 @@ ediff-get-value-according-to-buffer-type
   `(cond ((eq ,buf-type 'A) (nth 0 ,list))
 	 ((eq ,buf-type 'B) (nth 1 ,list))
 	 ((eq ,buf-type 'C) (nth 2 ,list))
+	 ((eq ,buf-type 'Ancestor) (nth 3 ,list))
 	 ))
 
 (defmacro ediff-char-to-buftype (arg)
@@ -1355,6 +1356,24 @@ ediff-make-buffers-readonly-at-startup
 ;; if nil, this silences some messages
 (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")
+
+(defcustom ediff-hide-equal-diffs-with-ancestor t
+  "If non-nil, hide diffs with ancestor that are equal in buffers A and B."
+  :type 'boolean
+  :group 'ediff-merge
+  :version "26.1")
+
+;; Store original values of options changed with
+;; `ediff-toggle-show-ancestor' or
+;; `ediff-toggle-hide-equal-diffs-with-ancestor'.  It's an alist
+;; (VAR . VALUE).
+(ediff-defvar-local ediff--restore-options-on-exit-alist nil "")
+
 (defcustom ediff-autostore-merges  'group-jobs-only
   "Save the results of merge jobs automatically.
 With 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 f81397950d..25dd2988bb 100644
--- a/lisp/vc/ediff-util.el
+++ b/lisp/vc/ediff-util.el
@@ -179,6 +179,7 @@ ediff-setup-keymap
   (cond (ediff-merge-job
 	 ;; 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.
 	 (define-key ediff-mode-map "a" 'ediff-copy-A-to-C)
 	 (define-key ediff-mode-map "b" 'ediff-copy-B-to-C)
@@ -187,6 +188,7 @@ ediff-setup-keymap
 	 (define-key ediff-mode-map "+" 'ediff-combine-diffs)
 	 (define-key ediff-mode-map "$"  nil)
 	 (define-key ediff-mode-map "$$" 'ediff-toggle-show-clashes-only)
+	 (define-key ediff-mode-map "$%" 'ediff-toggle-hide-equal-diffs-with-ancestor)
 	 (define-key ediff-mode-map "$*" 'ediff-toggle-skip-changed-regions)
 	 (define-key ediff-mode-map "&" 'ediff-re-merge))
 	(ediff-3way-comparison-job
@@ -553,11 +555,12 @@ ediff-setup-control-buffer
     (ediff-refresh-mode-lines)
     (setq ediff-control-window (selected-window))
     (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-window-A
 		  ediff-window-B
 		  ediff-window-C
+		  ediff-window-Ancestor
 		  ediff-split-window-function
 		  (ediff-multiframe-setup-p)
 		  ediff-wide-display-p))
@@ -600,12 +603,6 @@ ediff-update-diffs
 if necessary."
   (interactive)
   (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)))
 	;;(point-B (ediff-with-current-buffer ediff-buffer-B (point)))
 	(tmp-buffer (get-buffer-create ediff-tmp-buffer))
@@ -614,14 +611,17 @@ ediff-update-diffs
 	;; (null ediff-buffer-C) is no problem, as we later check if
 	;; ediff-buffer-C is alive
 	(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
 		  'A ediff-narrow-bounds))
 	(overl-B (ediff-get-value-according-to-buffer-type
 		  'B ediff-narrow-bounds))
 	(overl-C (ediff-get-value-according-to-buffer-type
 		  'C ediff-narrow-bounds))
-	beg-A end-A beg-B end-B beg-C end-C
-	file-A file-B file-C)
+        (overl-Ancestor (ediff-get-value-according-to-buffer-type
+                         '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)
 	(setq buf-A-file-name (file-name-nondirectory buf-A-file-name)))
@@ -629,15 +629,19 @@ ediff-update-diffs
 	(setq buf-B-file-name (file-name-nondirectory buf-B-file-name)))
     (if (stringp 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)
 
     (setq beg-A (ediff-overlay-start overl-A)
 	  beg-B (ediff-overlay-start overl-B)
 	  beg-C (ediff-overlay-start overl-C)
+	  beg-Ancestor (ediff-overlay-start overl-Ancestor)
 	  end-A (ediff-overlay-end overl-A)
 	  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
 	(progn
@@ -645,51 +649,37 @@ ediff-update-diffs
 	  (setq file-A (ediff-make-temp-file tmp-buffer "regA"))
 	  (ediff-wordify beg-B end-B ediff-buffer-B tmp-buffer)
 	  (setq file-B (ediff-make-temp-file tmp-buffer "regB"))
-	  (if ediff-3way-job
-	      (progn
-		(ediff-wordify beg-C end-C ediff-buffer-C tmp-buffer)
-		(setq file-C (ediff-make-temp-file tmp-buffer "regC"))))
+	  (when ediff-3way-job
+            (ediff-wordify beg-C end-C ediff-buffer-C tmp-buffer)
+            (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
       (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))
       (if ediff-3way-job
 	  (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-B 'fine-diffs-also)
     (ediff-clear-diff-vector 'ediff-difference-vector-C 'fine-diffs-also)
     (ediff-clear-diff-vector
      '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
-
-    ;; In case of merge job, fool it into thinking that it is just doing
-    ;; 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))
-
+    (funcall ediff-setup-diff-regions-function file-A file-B
+             (if ediff-merge-with-ancestor-job file-Ancestor file-C))
     (setq ediff-number-of-differences (length ediff-difference-vector-A))
     (delete-file file-A)
     (delete-file file-B)
-    (if file-C
-	(delete-file file-C))
+    (and file-C (delete-file file-C))
+    (and file-Ancestor (delete-file file-Ancestor))
 
     (if ediff-3way-job
 	(ediff-set-state-of-all-diffs-in-all-buffers ediff-control-buffer))
@@ -737,14 +727,16 @@ ediff-revert-buffers-then-recompute-diffs
 ;; optional NO-REHIGHLIGHT says to not rehighlight buffers
 (defun ediff-recenter (&optional no-rehighlight)
   "Bring the highlighted region of all buffers being compared into view.
-Reestablish the default three-window display."
+Reestablish the default window display."
   (interactive)
   (ediff-barf-if-not-control-buffer)
   (let (buffer-read-only)
     (if (and (ediff-buffer-live-p ediff-buffer-A)
 	     (ediff-buffer-live-p ediff-buffer-B)
 	     (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-buffer-A ediff-buffer-B ediff-buffer-C ediff-control-buffer)
       (or (eq this-command 'ediff-quit)
@@ -963,19 +955,92 @@ ediff-toggle-autorefine
 	 (setq ediff-auto-refine 'nix))
 	))
 
+(defsubst ediff--check-ancestor-exists ()
+  (or (ediff-buffer-live-p ediff-ancestor-buffer)
+      (if ediff-merge-with-ancestor-job
+	  (error "Lost connection to ancestor buffer.  This shouldn't happen.  \
+Please report this bug to bug-gnu-emacs@gnu.org")
+	(error "Not merging with ancestor"))))
+
 (defun ediff-show-ancestor ()
   "Show the ancestor buffer in a suitable window."
   (interactive)
   (ediff-recenter)
-  (or (ediff-buffer-live-p ediff-ancestor-buffer)
-      (if ediff-merge-with-ancestor-job
-	  (error "Lost connection to ancestor buffer...sorry")
-	(error "Not merging with ancestor")))
+  (ediff--check-ancestor-exists)
   (let (wind)
     (cond ((setq wind (ediff-get-visible-buffer-window ediff-ancestor-buffer))
 	   (raise-frame (window-frame wind)))
 	  (t (set-window-buffer ediff-window-C ediff-ancestor-buffer)))))
 
+;; Restore on exit the original values for options changed with
+;; `ediff-toggle-show-ancestor' or `ediff-toggle-hide-equal-diffs-with-ancestor'.
+(defun ediff--restore-options-on-exit ()
+  (when ediff--restore-options-on-exit-alist
+    (mapc (lambda (x)
+            (let ((var (car x))
+                  (value (cdr x)))
+              (message "Restoring %S to %S..." var value)
+              (set var value)))
+          ediff--restore-options-on-exit-alist)
+    (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)
+  (let ((alist ediff--restore-options-on-exit-alist))
+    ;; Save original value if not yet, and add hook to restore it on exit.
+    (unless (assq 'ediff-show-ancestor alist)
+      (push (cons 'ediff-show-ancestor ediff-show-ancestor)
+            alist)
+      (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
+              (alist-get 'ediff-show-ancestor alist))
+      (assq-delete-all 'ediff-show-ancestor alist)
+      (unless alist
+        (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)
+        (cond ((setq wind (ediff-get-visible-buffer-window ediff-ancestor-buffer))
+               (raise-frame (window-frame wind)))
+              (t (set-window-buffer ediff-window-C ediff-ancestor-buffer))))
+      (ediff-recenter)
+      (message "Showing ancestor buffer"))
+    (setq ediff--restore-options-on-exit-alist alist)))
+
+(defun ediff-toggle-hide-equal-diffs-with-ancestor ()
+  "Toggle `ediff-hide-equal-diffs-with-ancestor'."
+  (interactive)
+  (let ((alist ediff--restore-options-on-exit-alist))
+    ;; Save original value if not yet, and add hook to restore it on exit.
+    (unless (assq 'ediff-hide-equal-diffs-with-ancestor
+                  alist)
+      (push (cons 'ediff-hide-equal-diffs-with-ancestor
+                  ediff-hide-equal-diffs-with-ancestor)
+            alist)
+      (add-hook 'ediff-quit-hook #'ediff--restore-options-on-exit))
+    (setq ediff-hide-equal-diffs-with-ancestor
+          (not ediff-hide-equal-diffs-with-ancestor))
+    ;; If equal than orig, then nothing to restore on exit.
+    (when (eq ediff-hide-equal-diffs-with-ancestor
+              (alist-get 'ediff-hide-equal-diffs-with-ancestor
+                         alist))
+      (assq-delete-all 'ediff-hide-equal-diffs-with-ancestor
+                       alist)
+      (unless alist
+        (remove-hook 'ediff-quit-hook #'ediff--restore-options-on-exit)))
+    (ediff-update-diffs)
+    (if (not ediff-hide-equal-diffs-with-ancestor)
+        (message "Showing all diffs with ancestor")
+      (message "Ignoring diffs with ancestor when they are equal in buffers A and B"))
+    (setq ediff--restore-options-on-exit-alist alist)))
+
 (defun ediff-make-or-kill-fine-diffs (arg)
   "Compute fine diffs.  With negative prefix arg, kill fine diffs.
 In both cases, operates on the current difference region."
@@ -1232,7 +1297,12 @@ ediff-swap-buffers
 		     (list (nth 2 ediff-narrow-bounds)
 			   (nth 0 ediff-narrow-bounds)
 			   (nth 1 ediff-narrow-bounds)))
-		    (ediff-3way-job
+		    (ediff-merge-with-ancestor-job
+		     (list (nth 1 ediff-narrow-bounds)
+			   (nth 0 ediff-narrow-bounds)
+			   (nth 2 ediff-narrow-bounds)
+                           (nth 3 ediff-narrow-bounds)))
+                    (ediff-3way-job
 		     (list (nth 1 ediff-narrow-bounds)
 			   (nth 0 ediff-narrow-bounds)
 			   (nth 2 ediff-narrow-bounds)))
diff --git a/lisp/vc/ediff-wind.el b/lisp/vc/ediff-wind.el
index cd10288643..560dc470a5 100644
--- a/lisp/vc/ediff-wind.el
+++ b/lisp/vc/ediff-wind.el
@@ -115,6 +115,8 @@ ediff-window-setup-function
 (ediff-defvar-local ediff-window-B nil "")
 ;; Official window for buffer C
 (ediff-defvar-local ediff-window-C nil "")
+;; Official window for buffer Ancestor
+(ediff-defvar-local ediff-window-Ancestor nil "")
 ;; Ediff's window configuration.
 ;; Used to minimize the need to rearrange windows.
 (ediff-defvar-local ediff-window-config-saved "" "")
@@ -363,9 +365,13 @@ ediff-setup-windows-plain-merge
   ;; skip dedicated and unsplittable frames
   (ediff-destroy-control-frame control-buffer)
   (let ((window-min-height 1)
+	(with-Ancestor-p (ediff-with-current-buffer control-buffer
+                           ediff-merge-with-ancestor-job))
 	split-window-function
 	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
       (setq merge-window-share ediff-merge-window-share
 	    ;; this lets us have local versions of ediff-split-window-function
@@ -394,6 +400,14 @@ ediff-setup-windows-plain-merge
     (setq wind-C (selected-window))
     (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)
     (funcall split-window-function)
 
@@ -405,7 +419,8 @@ ediff-setup-windows-plain-merge
     (ediff-with-current-buffer control-buffer
       (setq ediff-window-A wind-A
 	    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-setup-control-buffer control-buffer)
@@ -516,9 +531,13 @@ ediff-setup-windows-multiframe-merge
 	 (wind-A (ediff-get-visible-buffer-window buf-A))
 	 (wind-B (ediff-get-visible-buffer-window buf-B))
 	 (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-B (if wind-B (window-frame wind-B)))
 	 (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
 	 (force-one-frame
 	  (ediff-with-current-buffer control-buf ediff-wide-display-p))
@@ -549,7 +568,10 @@ ediff-setup-windows-multiframe-merge
 	 (merge-window-share (ediff-with-current-buffer control-buf
 			       ediff-merge-window-share))
 	 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)
 
     ;; buf-A on its own
@@ -585,6 +607,19 @@ ediff-setup-windows-multiframe-merge
 	  (setq wind-C (selected-window))
 	  (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
 	     (window-live-p wind-A))
 	(progn
@@ -606,6 +641,7 @@ ediff-setup-windows-multiframe-merge
 	(let ((window-min-height 1))
 	  (if (and (eq frame-A frame-B)
 		   (eq frame-B frame-C)
+		   (eq frame-C frame-Ancestor)
 		   (frame-live-p frame-A))
 	      (select-frame frame-A)
 	    ;; avoid dedicated and non-splittable windows
@@ -623,6 +659,14 @@ ediff-setup-windows-multiframe-merge
 	  (setq wind-C (selected-window))
 	  (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)
 
 	  (funcall split-window-function)
@@ -633,8 +677,8 @@ ediff-setup-windows-multiframe-merge
 
 	  (setq done-A 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 it was set before because use-same-frame = 1
@@ -668,10 +712,22 @@ ediff-setup-windows-multiframe-merge
 	  (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
       (setq ediff-window-A wind-A
 	    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)
 	    designated-minibuffer-frame
 	    (window-frame (minibuffer-window frame-A))))
@@ -679,7 +735,6 @@ ediff-setup-windows-multiframe-merge
     (ediff-setup-control-frame control-buf designated-minibuffer-frame)
     ))
 
-
 ;; Window setup for all comparison jobs, including 3way comparisons
 (defun ediff-setup-windows-multiframe-compare (buf-A buf-B buf-C control-buf)
 ;;; Algorithm:
@@ -1295,7 +1350,9 @@ ediff-keep-window-config
 	 (let ((ctl-wind ediff-control-window)
 	       (A-wind ediff-window-A)
 	       (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
 	    (ediff-window-visible-p A-wind)
@@ -1303,13 +1360,19 @@ ediff-keep-window-config
 	    ;; if buffer C is defined then take it into account
 	    (or (not ediff-3way-job)
 		(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 B-wind) ediff-buffer-B)
 	    (or (not ediff-3way-job)
 		(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
-		     (format "%S%S%S%S%S%S%S"
-			     ctl-wind A-wind B-wind C-wind
+		     (format "%S%S%S%S%S%S%S%S"
+			     ctl-wind A-wind B-wind C-wind Ancestor-wind
 			     ediff-split-window-function
 			     (ediff-multiframe-setup-p)
 			     ediff-wide-display-p)))))))
-- 
2.11.0

From 2a1bc9b77c20153e2a1454bc1d20eb734ef41d15 Mon Sep 17 00:00:00 2001
From: Tino Calancha <tino.calancha@gmail.com>
Date: Sun, 19 Feb 2017 19:15:09 +0900
Subject: [PATCH 2/3] Auto refine ancestor buffer in 3way merges

* lisp/vc/ediff-diff.el (ediff-convert-diffs-to-overlays):
Prefer 'when' instead of 'if' here.
(ediff-make-fine-diffs, ediff-set-fine-diff-properties)
(ediff-set-fine-overlays-in-one-buffer)
(ediff-extract-diffs3, ediff-set-diff-overlays-in-one-buffer):
Consider ancestor buffer as well.
(ediff--set-right-faces): New defun.
* lisp/vc/ediff-init.el (ediff-state-of-merge): Update comment with new
state-of-merge 'A=B.
(ediff-fine-diff-face-Ancestor-A, ediff-fine-diff-face-Ancestor-B)
(ediff-fine-diff-face-AB, ediff-temp-file-Ancestor): New defvars.
(ediff-fine-diff-Ancestor-A, ediff-fine-diff-Ancestor-B)
(ediff-fine-diff-AB): New faces.
Add echo help for the new faces.
(ediff-clear-fine-differences): Clear ancestor diffs as well.
* lisp/vc/ediff-util.el (ediff-delete-temp-files): Delete ancestor
temporary file as well.
* doc/misc/ediff.texi (Quick Help Commands)
(Merging and diff3): Update manual.
; * etc/NEWS: Add entry for the new features.
---
 doc/misc/ediff.texi   |  55 +++++++--
 etc/NEWS              |   8 ++
 lisp/vc/ediff-diff.el | 332 ++++++++++++++++++++++++++++++--------------------
 lisp/vc/ediff-init.el |  62 +++++++++-
 lisp/vc/ediff-util.el |  14 +--
 5 files changed, 315 insertions(+), 156 deletions(-)

diff --git a/doc/misc/ediff.texi b/doc/misc/ediff.texi
index 19b7adbd66..2b3144f888 100644
--- a/doc/misc/ediff.texi
+++ b/doc/misc/ediff.texi
@@ -99,7 +99,8 @@ Introduction
 another (and recover old differences if you change your mind).
 
 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
 allow the user to conveniently launch browsing or merging sessions on
 groups of files in two (or three) different directories.
@@ -810,6 +811,15 @@ Quick Help Commands
 of the variants clashes with the ancestor but the other variant agrees with
 it.  Typing @kbd{$$} again undoes this setting.
 
+@item $%
+@kindex $%
+When performing a 3way merge, any differences with the ancestor identical in
+both files, A and B are discarded.  Use this command in the control buffer
+if you want to see those differences as well.  Typing @kbd{$%} again
+undoes this setting.
+To enable this feature permanently, you might wish to customize the variable
+@code{ediff-hide-equal-diffs-with-ancestor}.
+
 @item $*
 @kindex $*
 When merging files with large number of differences, it is sometimes
@@ -828,7 +838,15 @@ Quick Help Commands
 
 @item /
 @kindex /
-Displays the ancestor file during merges.
+Displays the ancestor file during merges in the current difference.
+
+@item \
+@kindex \
+@vindex ediff-show-ancestor
+Displays the ancestor file during merges for all differences.
+You can enable permanently this setting customizing the variable
+@code{ediff-show-ancestor}.
+
 @item &
 @kindex &
 In some situations, such as when one of the files agrees with the ancestor file
@@ -1638,9 +1656,11 @@ Highlighting Difference Regions
 @item ediff-current-diff-face-A
 @itemx ediff-current-diff-face-B
 @itemx ediff-current-diff-face-C
+@itemx ediff-current-diff-face-Ancestor
 @vindex ediff-current-diff-face-A
 @vindex ediff-current-diff-face-B
 @vindex ediff-current-diff-face-C
+@vindex ediff-current-diff-face-Ancestor
 Ediff uses these faces to highlight current differences on devices where
 Emacs can display faces.  These and subsequently described faces can be set
 either in @file{.emacs} or in @file{.Xdefaults}.  The X resource for Ediff
@@ -1648,12 +1668,20 @@ Highlighting Difference Regions
 the information on how to set X resources.
 @item ediff-fine-diff-face-A
 @itemx ediff-fine-diff-face-B
+@itemx ediff-fine-diff-face-AB
 @itemx ediff-fine-diff-face-C
+@itemx ediff-fine-diff-face-Ancestor
+@itemx ediff-fine-diff-face-Ancestor-A
+@itemx ediff-fine-diff-face-Ancestor-B
 @vindex ediff-fine-diff-face-A
 @vindex ediff-fine-diff-face-B
+@vindex ediff-fine-diff-face-AB
 @vindex ediff-fine-diff-face-C
+@vindex ediff-fine-diff-face-Ancestor
+@vindex ediff-fine-diff-face-Ancestor-A
+@vindex ediff-fine-diff-face-Ancestor-B
 Ediff uses these faces to show the fine differences between the current
-differences regions in buffers A, B, and C, respectively.
+differences regions in buffers A, B, and C or Ancestor respectively.
 
 @item ediff-even-diff-face-A
 @itemx ediff-even-diff-face-B
@@ -2048,16 +2076,17 @@ Merging and diff3
 regions in buffers A or B are non-empty, this means that text was
 modified.  Otherwise, the original text was deleted.
 
-Although the ancestor buffer is normally invisible, Ediff maintains
-difference regions there and advances the current difference region
-accordingly.  All highlighting of difference regions is provided in the
-ancestor buffer, except for the fine differences.  Therefore, if desired, the
-user can put the ancestor buffer in a separate frame and watch it
-there.  However, on a TTY, only one frame can be visible at any given time,
-and Ediff doesn't support any single-frame window configuration where all
-buffers, including the ancestor buffer, would be visible.  However, the
-ancestor buffer can be displayed by typing @kbd{/} to the control
-window.  (Type @kbd{C-l} to hide it again.)
+@vindex ediff-hide-equal-diffs-with-ancestor
+The ancestor buffer is normally visible.  All highlighting of difference
+regions is provided on it, including the fine differences.
+By default, differences with the ancestor identical in the other two
+buffers are discarded.
+The option @code{ediff-hide-equal-diffs-with-ancestor} controls
+whether if those differences must be shown or not.  This option can be
+temporary disabled by typing @kbd{$%} to the control buffer.
+For those differences the state-of-difference indicator is @samp{A=B}.
+If desired, the ancestor buffer can be hidden by typing @kbd{\} to
+the control buffer.
 
 Note that the state-of-difference indicators @samp{=diff(A)} and
 @samp{=diff(B)} above are not redundant, even in the presence of a
diff --git a/etc/NEWS b/etc/NEWS
index 143e4655de..39940f0507 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -357,6 +357,14 @@ words where first character is upper rather than title case, e.g.,
 \f
 * Changes in Specialized Modes and Packages in Emacs 26.1
 
+** Ediff
+
++++
+*** The ancestor buffer is shown and refined by default in 3way merges.
+Two new options ediff-show-ancestor and
+ediff-hide-equal-diffs-with-ancestor and two new toggles
+ediff-toggle-show-ancestor, ediff-toggle-hide-equal-diffs-with-ancestor.
+
 ** TeX: Add luatex and xetex as alternatives to pdftex
 
 ** Electric-Buffer-menu
diff --git a/lisp/vc/ediff-diff.el b/lisp/vc/ediff-diff.el
index 37f22340d7..2e3bdc1475 100644
--- a/lisp/vc/ediff-diff.el
+++ b/lisp/vc/ediff-diff.el
@@ -509,8 +509,8 @@ ediff-convert-diffs-to-overlays
   (ediff-set-diff-overlays-in-one-buffer 'B diff-list)
   (if ediff-3way-job
       (ediff-set-diff-overlays-in-one-buffer 'C diff-list))
-  (if ediff-merge-with-ancestor-job
-      (ediff-set-diff-overlays-in-one-buffer 'Ancestor diff-list))
+  (when ediff-merge-with-ancestor-job
+    (ediff-set-diff-overlays-in-one-buffer 'Ancestor diff-list))
   ;; set up vector showing the status of merge regions
   (if ediff-merge-job
       (setq ediff-state-of-merge
@@ -613,6 +613,45 @@ ediff-set-diff-overlays-in-one-buffer
 	 (vconcat diff-overlay-list))
     ))
 
+
+;; Highlight with the same face overlays from different buffers
+;; with identical content.
+(defun ediff--set-right-faces (n)
+  (let ((ov-a (ediff-get-fine-diff-vector n 'A))
+        (ov-b (ediff-get-fine-diff-vector n 'B))
+        (ov-anc (ediff-get-fine-diff-vector n 'Ancestor))
+        (buf-A ediff-buffer-A)
+        (buf-B ediff-buffer-B)
+        (buf-anc ediff-ancestor-buffer))
+    (cl-flet ((set-faces-fn (overlays1 overlays2 buffer1 buffer2 face &optional setall)
+                (cl-mapc
+                 (lambda (ov1 ov2)
+                   (cl-flet ((fn (ov buf)
+                                 (with-current-buffer buf
+                                   (buffer-substring (ediff-overlay-start ov)
+                                                     (ediff-overlay-end ov)))))
+                     (when (string= (fn ov1 buffer1) (fn ov2 buffer2))
+                       (when setall
+                         (ediff-overlay-put ov1 'ediff-old-face face)
+                         (ediff-overlay-put ov1 'face face))
+                       (ediff-overlay-put ov2 'ediff-old-face face)
+                       (ediff-overlay-put ov2 'face face))))
+                 overlays1 overlays2)))
+      ;; Fine diffs common to A and B.
+      (set-faces-fn ov-a ov-b buf-A buf-B ediff-fine-diff-face-AB 'setall)
+      ;; Fine diffs common to A and Ancestor.
+      (set-faces-fn ov-a ov-anc buf-A buf-anc ediff-fine-diff-face-Ancestor-A)
+      ;; Fine diffs common to B and Ancestor.
+      (set-faces-fn ov-b ov-anc buf-B buf-anc ediff-fine-diff-face-Ancestor-B)
+      ;; Set `ediff-fine-diff-Ancestor' for fine diffs just present in Ancestor buffer.
+      (mapc (lambda (ov)
+              (unless (memq (ediff-overlay-get ov 'face)
+                            `(,ediff-fine-diff-face-Ancestor-A
+                              ,ediff-fine-diff-face-Ancestor-B))
+                (ediff-overlay-put ov 'ediff-old-face ediff-fine-diff-face-Ancestor)
+                (ediff-overlay-put ov 'face ediff-fine-diff-face-Ancestor)))
+            ov-anc))))
+
 ;; `n' is the diff region to work on.  Default is ediff-current-difference.
 ;; if `flag' is 'noforce then make fine-diffs only if this region's fine
 ;; diffs have not been computed before.
@@ -634,12 +673,17 @@ ediff-make-fine-diffs
 	    (file-A ediff-temp-file-A)
 	    (file-B ediff-temp-file-B)
 	    (file-C ediff-temp-file-C)
+	    (file-Ancestor ediff-temp-file-Ancestor)
 	    (empty-A (ediff-empty-diff-region-p n 'A))
 	    (empty-B (ediff-empty-diff-region-p n 'B))
 	    (empty-C (ediff-empty-diff-region-p n 'C))
+	    (empty-Ancestor (and ediff-merge-with-ancestor-job
+                                 (ediff-empty-diff-region-p n 'Ancestor)))
 	    (whitespace-A (ediff-whitespace-diff-region-p n 'A))
 	    (whitespace-B (ediff-whitespace-diff-region-p n 'B))
 	    (whitespace-C (ediff-whitespace-diff-region-p n 'C))
+	    (whitespace-Ancestor (and ediff-merge-with-ancestor-job
+                                      (ediff-whitespace-diff-region-p n 'Ancestor)))
 	    cumulative-fine-diff-length)
 
 	(cond ;; If one of the regions is empty (or 2 in 3way comparison)
@@ -727,10 +771,22 @@ ediff-make-fine-diffs
 			   (ediff-make-temp-file
 			    tmp-buffer "fineDiffC" file-C))))
 
-	       ;; save temp file names.
+               (when ediff-merge-with-ancestor-job
+                 (ediff-wordify
+                  (ediff-get-diff-posn 'Ancestor 'beg n)
+                  (ediff-get-diff-posn 'Ancestor 'end n)
+                  ediff-ancestor-buffer
+                  tmp-buffer
+                  ediff-control-buffer)
+                 (setq file-Ancestor
+                       (ediff-make-temp-file
+                        tmp-buffer "fineDiffAncestor" file-Ancestor)))
+
+               ;; save temp file names.
 	       (setq ediff-temp-file-A file-A
 		     ediff-temp-file-B file-B
-		     ediff-temp-file-C file-C)
+		     ediff-temp-file-C file-C
+		     ediff-temp-file-Ancestor file-Ancestor)
 
 	       ;; set the new vector of fine diffs, if none exists
 	       (cond ((and ediff-3way-job whitespace-A)
@@ -738,10 +794,13 @@ ediff-make-fine-diffs
 		     ((and ediff-3way-job whitespace-B)
 		      (ediff-setup-fine-diff-regions file-A nil file-C n))
 		     ((and ediff-3way-job
-			   ;; In merge-jobs, whitespace-C is t, since
-			   ;; ediff-empty-diff-region-p returns t in this case
-			   whitespace-C)
-		      (ediff-setup-fine-diff-regions file-A file-B nil n))
+		           ;; In merge-jobs, whitespace-C is t, since
+		           ;; ediff-empty-diff-region-p returns t in this case
+		           whitespace-C)
+                      (if (or (not ediff-merge-with-ancestor-job)
+                              (not ediff-show-ancestor))
+                          (ediff-setup-fine-diff-regions file-A file-B nil n)
+                        (ediff-setup-fine-diff-regions file-A file-B file-Ancestor n)))
 		     (t
 		      (ediff-setup-fine-diff-regions file-A file-B file-C n)))
 
@@ -779,6 +838,9 @@ ediff-make-fine-diffs
 	       )
 	      ) ; end cond
 	(ediff-set-fine-diff-properties n)
+        (when (and ediff-merge-with-ancestor-job
+                   ediff-show-ancestor)
+          (ediff--set-right-faces n))
 	)))
 
 ;; Interface to ediff-make-fine-diffs. Checks for auto-refine limit, etc.
@@ -812,7 +874,11 @@ ediff-set-fine-diff-properties
 	(ediff-set-fine-diff-properties-in-one-buffer 'A n default)
 	(ediff-set-fine-diff-properties-in-one-buffer 'B n default)
 	(if ediff-3way-job
-	    (ediff-set-fine-diff-properties-in-one-buffer 'C n default)))))
+	    (ediff-set-fine-diff-properties-in-one-buffer 'C n default))
+        (when (and ediff-merge-with-ancestor-job
+                   ediff-show-ancestor)
+          (ediff-set-fine-diff-properties-in-one-buffer 'Ancestor n default))
+)))
 
 (defun ediff-set-fine-diff-properties-in-one-buffer (buf-type
 						     n &optional default)
@@ -900,9 +966,11 @@ ediff-set-fine-overlays-in-one-buffer
 (defun ediff-convert-fine-diffs-to-overlays (diff-list region-num)
   (ediff-set-fine-overlays-in-one-buffer 'A diff-list region-num)
   (ediff-set-fine-overlays-in-one-buffer 'B diff-list region-num)
-  (if ediff-3way-job
-      (ediff-set-fine-overlays-in-one-buffer 'C diff-list region-num)
-    ))
+  (when ediff-3way-job
+    (ediff-set-fine-overlays-in-one-buffer 'C diff-list region-num)
+    (when (and ediff-merge-with-ancestor-job
+               ediff-show-ancestor)
+      (ediff-set-fine-overlays-in-one-buffer 'Ancestor diff-list region-num))))
 
 
 ;; Stolen from emerge.el
@@ -955,9 +1023,7 @@ ediff-extract-diffs3
 	(c-prev 1)
 	(c-prev-pt nil)
 	(anc-prev 1)
-	diff-list shift-A shift-B shift-C
-	)
-
+	diff-list shift-A shift-B shift-C)
     ;; diff list contains word numbers or points, depending on word-mode
     (setq diff-list (cons (if word-mode 'words 'points)
 			  diff-list))
@@ -989,125 +1055,123 @@ ediff-extract-diffs3
       (goto-char (point-min))
       (while (re-search-forward ediff-match-diff3-line nil t)
 	;; leave point after matched line
-       (beginning-of-line 2)
-       (let ((agreement (buffer-substring (match-beginning 1) (match-end 1))))
-	 ;; if the files A and B are the same and not 3way-comparison,
-	 ;; ignore the difference
-	 (if (or three-way-comp (not (string-equal agreement "3")))
-	     (let* ((a-begin (car (ediff-get-diff3-group "1")))
-		    (a-end  (nth 1 (ediff-get-diff3-group "1")))
-		    (b-begin (car (ediff-get-diff3-group "2")))
-		    (b-end (nth 1 (ediff-get-diff3-group "2")))
-		    (c-or-anc-begin (car (ediff-get-diff3-group "3")))
-		    (c-or-anc-end (nth 1 (ediff-get-diff3-group "3")))
-		    (state-of-merge
-		     (cond ((string-equal agreement "1") 'prefer-A)
-			   ((string-equal agreement "2") 'prefer-B)
-			   (t ediff-default-variant)))
-		    (state-of-diff-merge
-		     (if (memq state-of-merge '(default-A prefer-A)) 'B 'A))
-		    (state-of-diff-comparison
-		     (cond ((string-equal agreement "1") 'A)
-			   ((string-equal agreement "2") 'B)
-			   ((string-equal agreement "3") 'C)))
-		    state-of-ancestor
-		    c-begin c-end
-		    a-begin-pt a-end-pt
-		    b-begin-pt b-end-pt
-		    c-begin-pt c-end-pt
-		    anc-begin-pt anc-end-pt)
-
-	       (setq state-of-ancestor
-		     (= c-or-anc-begin c-or-anc-end))
-
-	       (cond (three-way-comp
-		      (setq c-begin c-or-anc-begin
-			    c-end c-or-anc-end))
-		     ((eq ediff-default-variant 'default-B)
-		      (setq c-begin b-begin
-			    c-end b-end))
-		     (t
-		      (setq c-begin a-begin
-			    c-end a-end)))
-
-	       ;; compute main diff vector
-	       (if word-mode
-		   ;; make diff-list contain word numbers
-		   (setq diff-list
-			 (nconc diff-list
-				(list (vector
-				       (- a-begin a-prev) (- a-end a-begin)
-				       (- b-begin b-prev) (- b-end b-begin)
-				       (- c-begin c-prev) (- c-end c-begin)
-				       nil nil ; dummy ancestor
-				       nil     ; state of diff
-				       nil     ; state of merge
-				       nil     ; state of ancestor
-				       )))
-			 a-prev a-end
-			 b-prev b-end
-			 c-prev c-end)
-		 ;; else convert lines to points
-		 (ediff-with-current-buffer A-buffer
-		   (goto-char (or a-prev-pt shift-A (point-min)))
-		   (forward-line (- a-begin a-prev))
-		   (setq a-begin-pt (point))
-		   (forward-line (- a-end a-begin))
-		   (setq a-end-pt (point)
-			 a-prev a-end
-			 a-prev-pt a-end-pt))
-		 (ediff-with-current-buffer B-buffer
-		   (goto-char (or b-prev-pt shift-B (point-min)))
-		   (forward-line (- b-begin b-prev))
-		   (setq b-begin-pt (point))
-		   (forward-line (- b-end b-begin))
-		   (setq b-end-pt (point)
-			 b-prev b-end
-			 b-prev-pt b-end-pt))
-		 (ediff-with-current-buffer C-buffer
-		   (goto-char (or c-prev-pt shift-C (point-min)))
-		   (forward-line (- c-begin c-prev))
-		   (setq c-begin-pt (point))
-		   (forward-line (- c-end c-begin))
-		   (setq c-end-pt (point)
-			 c-prev c-end
-			 c-prev-pt c-end-pt))
-		 (if (ediff-buffer-live-p anc-buffer)
-		     (ediff-with-current-buffer anc-buffer
-		       (forward-line (- c-or-anc-begin anc-prev))
-		       (setq anc-begin-pt (point))
-		       (forward-line (- c-or-anc-end c-or-anc-begin))
-		       (setq anc-end-pt (point)
-			     anc-prev c-or-anc-end)))
-		 (setq diff-list
-		       (nconc
-			diff-list
-			;; if comparing with ancestor, then there also is a
-			;; state-of-difference marker
-			(if three-way-comp
-			    (list (vector
-				   a-begin-pt a-end-pt
-				   b-begin-pt b-end-pt
-				   c-begin-pt c-end-pt
-				   nil nil ; ancestor begin/end
-				   state-of-diff-comparison
-				   nil	; state of merge
-				   nil  ; state of ancestor
-				   ))
-			  (list (vector a-begin-pt a-end-pt
-					b-begin-pt b-end-pt
-					c-begin-pt c-end-pt
-					anc-begin-pt anc-end-pt
-					state-of-diff-merge
-					state-of-merge
-					state-of-ancestor
-					)))
-			)))
-	       ))
-
-	 ))) ; end ediff-with-current-buffer
-    diff-list
-    ))
+        (beginning-of-line 2)
+        (let ((agreement (buffer-substring (match-beginning 1) (match-end 1))))
+          ;; Show diffs even if A and B are the same when
+          ;; ediff-hide-equal-diffs-with-ancestor is nil.
+          (unless (and (string-equal agreement "3")
+                       ediff-hide-equal-diffs-with-ancestor)
+            (let* ((a-begin (car (ediff-get-diff3-group "1")))
+                   (a-end  (nth 1 (ediff-get-diff3-group "1")))
+                   (b-begin (car (ediff-get-diff3-group "2")))
+                   (b-end (nth 1 (ediff-get-diff3-group "2")))
+                   (c-or-anc-begin (car (ediff-get-diff3-group "3")))
+                   (c-or-anc-end (nth 1 (ediff-get-diff3-group "3")))
+                   (state-of-merge
+                    (cond ((string-equal agreement "1") 'prefer-A)
+                          ((string-equal agreement "2") 'prefer-B)
+                          ((string-equal agreement "3") 'A=B)
+                          (t ediff-default-variant)))
+                   (state-of-diff-merge
+                    (if (memq state-of-merge '(default-A prefer-A)) 'B 'A))
+                   (state-of-diff-comparison
+                    (cond ((string-equal agreement "1") 'A)
+                          ((string-equal agreement "2") 'B)
+                          ((string-equal agreement "3") 'C)))
+                   state-of-ancestor
+                   c-begin c-end
+                   a-begin-pt a-end-pt
+                   b-begin-pt b-end-pt
+                   c-begin-pt c-end-pt
+                   anc-begin-pt anc-end-pt)
+
+              (setq state-of-ancestor
+                    (= c-or-anc-begin c-or-anc-end))
+
+              (cond (three-way-comp
+                     (setq c-begin c-or-anc-begin
+                           c-end c-or-anc-end))
+                    ((eq ediff-default-variant 'default-B)
+                     (setq c-begin b-begin
+                           c-end b-end))
+                    (t
+                     (setq c-begin a-begin
+                           c-end a-end)))
+
+              ;; compute main diff vector
+              (if word-mode
+                  ;; make diff-list contain word numbers
+                  (setq diff-list
+                        (nconc diff-list
+                               (list (vector
+                                      (- a-begin a-prev) (- a-end a-begin)
+                                      (- b-begin b-prev) (- b-end b-begin)
+                                      (- c-begin c-prev) (- c-end c-begin)
+                                      nil nil ; dummy ancestor
+                                      nil     ; state of diff
+                                      nil     ; state of merge
+                                      nil     ; state of ancestor
+                                      )))
+                        a-prev a-end
+                        b-prev b-end
+                        c-prev c-end)
+                ;; else convert lines to points
+                (ediff-with-current-buffer A-buffer
+                  (goto-char (or a-prev-pt shift-A (point-min)))
+                  (forward-line (- a-begin a-prev))
+                  (setq a-begin-pt (point))
+                  (forward-line (- a-end a-begin))
+                  (setq a-end-pt (point)
+                        a-prev a-end
+                        a-prev-pt a-end-pt))
+                (ediff-with-current-buffer B-buffer
+                  (goto-char (or b-prev-pt shift-B (point-min)))
+                  (forward-line (- b-begin b-prev))
+                  (setq b-begin-pt (point))
+                  (forward-line (- b-end b-begin))
+                  (setq b-end-pt (point)
+                        b-prev b-end
+                        b-prev-pt b-end-pt))
+                (ediff-with-current-buffer C-buffer
+                  (goto-char (or c-prev-pt shift-C (point-min)))
+                  (forward-line (- c-begin c-prev))
+                  (setq c-begin-pt (point))
+                  (forward-line (- c-end c-begin))
+                  (setq c-end-pt (point)
+                        c-prev c-end
+                        c-prev-pt c-end-pt))
+                (if (ediff-buffer-live-p anc-buffer)
+                    (ediff-with-current-buffer anc-buffer
+                      (forward-line (- c-or-anc-begin anc-prev))
+                      (setq anc-begin-pt (point))
+                      (forward-line (- c-or-anc-end c-or-anc-begin))
+                      (setq anc-end-pt (point)
+                            anc-prev c-or-anc-end)))
+                (setq diff-list
+                      (nconc
+                       diff-list
+                       ;; if comparing with ancestor, then there also is a
+                       ;; state-of-difference marker
+                       (if three-way-comp
+                           (list (vector
+                                  a-begin-pt a-end-pt
+                                  b-begin-pt b-end-pt
+                                  c-begin-pt c-end-pt
+                                  nil nil ; ancestor begin/end
+                                  state-of-diff-comparison
+                                  nil; state of merge
+                                  nil  ; state of ancestor
+                                  ))
+                         (list (vector a-begin-pt a-end-pt
+                                       b-begin-pt b-end-pt
+                                       c-begin-pt c-end-pt
+                                       anc-begin-pt anc-end-pt
+                                       state-of-diff-merge
+                                       state-of-merge
+                                       state-of-ancestor
+                                       ))))))))
+          ))) ; end ediff-with-current-buffer
+    diff-list))
 
 ;; Generate the difference vector and overlays for three files
 ;; File-C is either the third file to compare (in case of 3-way comparison)
diff --git a/lisp/vc/ediff-init.el b/lisp/vc/ediff-init.el
index 66a2a0f527..7e5291db5b 100644
--- a/lisp/vc/ediff-init.el
+++ b/lisp/vc/ediff-init.el
@@ -665,7 +665,7 @@ ediff-protected-variables
 
 ;; [ status status status ...]
 ;; Each status: [state-of-merge state-of-ancestor]
-;; state-of-merge is default-A, default-B, prefer-A, or prefer-B.  It
+;; state-of-merge is default-A, default-B, prefer-A, prefer-B or A=B.  It
 ;; indicates the way a diff region was created in buffer C.
 ;; state-of-ancestor says if the corresponding region in ancestor buffer is
 ;; empty.
@@ -1067,6 +1067,52 @@ ediff-fine-diff-Ancestor
 At present, this face is not used and no fine differences are computed for the
 ancestor buffer."
   :group 'ediff-highlighting)
+
+(defface ediff-fine-diff-Ancestor-A
+  '((t (:inherit ediff-fine-diff-A)))
+  "Face for highlighting refinement parts in Ancestor buffer due to buffer A."
+  :group 'ediff-highlighting
+  :version "26.1")
+
+;; An internal variable.  Ediff takes the face from here.  When unhighlighting,
+;; this variable is set to nil, then again to the appropriate face.
+(defvar ediff-fine-diff-face-Ancestor-A 'ediff-fine-diff-Ancestor-A
+  "Face for highlighting the fine differences in buffer Ancestor comming from buffer A.
+DO NOT CHANGE this variable.  Instead, use the customization
+widget to customize the actual face object `ediff-fine-diff-Ancestor-A'
+this variable represents.")
+(ediff-hide-face ediff-fine-diff-face-Ancestor-A)
+
+(defface ediff-fine-diff-Ancestor-B
+  '((t (:inherit ediff-fine-diff-B)))
+  "Face for highlighting refinement parts in Ancestor buffer due to buffer B."
+  :group 'ediff-highlighting
+  :version "26.1")
+
+;; An internal variable.  Ediff takes the face from here.  When unhighlighting,
+;; this variable is set to nil, then again to the appropriate face.
+(defvar ediff-fine-diff-face-Ancestor-B 'ediff-fine-diff-Ancestor-B
+  "Face for highlighting the fine differences in buffer Ancestor comming from buffer B.
+DO NOT CHANGE this variable.  Instead, use the customization
+widget to customize the actual face object `ediff-fine-diff-Ancestor-B'
+this variable represents.")
+(ediff-hide-face ediff-fine-diff-face-Ancestor-B)
+
+(defface ediff-fine-diff-AB
+  '((t (:inherit match)))
+  "Face for highlighting refinement parts common to buffers A and B."
+  :group 'ediff-highlighting
+  :version "26.1")
+
+;; An internal variable.  Ediff takes the face from here.  When unhighlighting,
+;; this variable is set to nil, then again to the appropriate face.
+(defvar ediff-fine-diff-face-AB 'ediff-fine-diff-AB
+  "Face for highlighting the fine differences common to buffers A and B.
+DO NOT CHANGE this variable.  Instead, use the customization
+widget to customize the actual face object `ediff-fine-diff-AB'
+this variable represents.")
+(ediff-hide-face ediff-fine-diff-face-AB)
+
 ;; An internal variable.  Ediff takes the face from here.  When unhighlighting,
 ;; this variable is set to nil, then again to the appropriate face.
 (defvar ediff-fine-diff-face-Ancestor 'ediff-fine-diff-Ancestor
@@ -1324,6 +1370,12 @@ ediff-fine-diff-face-alist
      "A `refinement' of the current difference region")
 (put ediff-fine-diff-face-Ancestor 'ediff-help-echo
      "A `refinement' of the current difference region")
+(put ediff-fine-diff-face-Ancestor-A 'ediff-help-echo
+     "Parts of `refinement' of the current difference region due to buffer A")
+(put ediff-fine-diff-face-Ancestor-B 'ediff-help-echo
+     "Parts of `refinement' of the current difference region due to buffer B")
+(put ediff-fine-diff-face-AB 'ediff-help-echo
+     "Parts of `refinement' of the current difference common to buffes A and B")
 
 (add-hook 'ediff-quit-hook 'ediff-cleanup-mess)
 (add-hook 'ediff-suspend-hook 'ediff-default-suspend-function)
@@ -1438,6 +1490,8 @@ ediff-H-glyph
 (ediff-defvar-local ediff-temp-file-B nil "")
 ;; Temporary file used for refining difference regions in buffer C.
 (ediff-defvar-local ediff-temp-file-C nil "")
+;; Temporary file used for refining difference regions in buffer Ancestor.
+(ediff-defvar-local ediff-temp-file-Ancestor nil "")
 
 
 (defun ediff-file-remote-p (file-name)
@@ -1520,7 +1574,11 @@ ediff-clear-fine-differences
   (ediff-clear-fine-differences-in-one-buffer n 'A)
   (ediff-clear-fine-differences-in-one-buffer n 'B)
   (if ediff-3way-job
-      (ediff-clear-fine-differences-in-one-buffer n 'C)))
+      (ediff-clear-fine-differences-in-one-buffer n 'C))
+  (when (and ediff-merge-with-ancestor-job
+             ediff-show-ancestor)
+    (ediff-clear-fine-differences-in-one-buffer n 'Ancestor))
+  )
 
 
 (defsubst ediff-mouse-event-p (event)
diff --git a/lisp/vc/ediff-util.el b/lisp/vc/ediff-util.el
index 25dd2988bb..fb3d85b758 100644
--- a/lisp/vc/ediff-util.el
+++ b/lisp/vc/ediff-util.el
@@ -2617,13 +2617,13 @@ ediff-good-frame-under-mouse
 
 
 (defun ediff-delete-temp-files ()
-  (if (and (stringp ediff-temp-file-A) (file-exists-p ediff-temp-file-A))
-      (delete-file ediff-temp-file-A))
-  (if (and (stringp ediff-temp-file-B) (file-exists-p ediff-temp-file-B))
-      (delete-file ediff-temp-file-B))
-  (if (and (stringp ediff-temp-file-C) (file-exists-p ediff-temp-file-C))
-      (delete-file ediff-temp-file-C)))
-
+  (mapc (lambda (x)
+          (when (and (stringp x) (file-exists-p x))
+            (delete-file x)))
+        (list ediff-temp-file-A
+              ediff-temp-file-B
+              ediff-temp-file-C
+              ediff-temp-file-Ancestor)))
 
 ;; Kill control buffer, other auxiliary Ediff buffers.
 ;; Leave one of the frames split between buffers A/B/C
-- 
2.11.0

From 50b874fc64d8303ce7be71026e76fd28e5b1a91e Mon Sep 17 00:00:00 2001
From: Tino Calancha <tino.calancha@gmail.com>
Date: Sun, 19 Feb 2017 19:15:16 +0900
Subject: [PATCH 3/3] diff-mode: Improve default faces for buffer ancestor

* lisp/vc/ediff-init.el (ediff-current-diff-Ancestor)
(ediff-fine-diff-Ancestor): Use defaults consistent with
faces for 'ediff-buffer-A' and 'ediff-buffer-B'.
---
 lisp/vc/ediff-init.el | 36 ++++++++++++++++++++++--------------
 1 file changed, 22 insertions(+), 14 deletions(-)

diff --git a/lisp/vc/ediff-init.el b/lisp/vc/ediff-init.el
index 7e5291db5b..6b5bdca347 100644
--- a/lisp/vc/ediff-init.el
+++ b/lisp/vc/ediff-init.el
@@ -943,13 +943,17 @@ ediff-current-diff-face-C
 
 (defface ediff-current-diff-Ancestor
   (if (featurep 'emacs)
-      '((((class color) (min-colors 88))
-	 (:background "VioletRed"))
-	(((class color) (min-colors 16))
-	 (:foreground "Black" :background "VioletRed"))
-	(((class color))
-	 (:foreground "black" :background "magenta3"))
-	(t (:inverse-video t)))
+      '((((class color) (min-colors 88) (background light))
+         :background "#cfdeee")
+        (((class color) (min-colors 88) (background dark))
+         :background "#004151")
+        (((class color) (min-colors 16) (background light))
+         :background "#cfdeee")
+        (((class color) (min-colors 16) (background dark))
+         :background "#004151")
+        (((class color))
+         (:foreground "black" :background "magenta3"))
+        (t (:inverse-video t)))
     '((((type tty))    (:foreground "black" :background "magenta3"))
       (((class color)) (:foreground "Black" :background "VioletRed"))
       (t (:inverse-video t))))
@@ -1053,13 +1057,17 @@ ediff-fine-diff-face-C
 
 (defface ediff-fine-diff-Ancestor
   (if (featurep 'emacs)
-      '((((class color) (min-colors 88))
-	 (:background "Green"))
-	(((class color) (min-colors 16))
-	 (:foreground "Black" :background "Green"))
-	(((class color))
-	 (:foreground "red3" :background "green"))
-	(t		     (:underline t :stipple "gray3")))
+      '((((class color) (min-colors 88) (background light))
+         :background "#00c5c0")
+        (((class color) (min-colors 88) (background dark))
+         :background "#009591")
+        (((class color) (min-colors 16) (background light))
+         :background "#00c5c0")
+        (((class color) (min-colors 16) (background dark))
+         :background "#009591")
+        (((class color))
+         (:foreground "red3" :background "green"))
+        (t		     (:underline t :stipple "gray3")))
     '((((type tty))    (:foreground "red3" :background "green"))
       (((class color)) (:foreground "Black" :background "Green"))
       (t	     	     (:underline t :stipple "gray3"))))
-- 
2.11.0

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; PATCH ENDS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

In GNU Emacs 26.0.50 (build 2, x86_64-pc-linux-gnu, GTK+ Version 3.22.7)
 of 2017-02-19
Repository revision: 938426d1ca0930b859c3e37b26513f5d74761284





^ permalink raw reply related	[flat|nested] 10+ messages in thread

* bug#25493: 26.0.50; ediff merge should (optionally) show ancestor in fourth window
  2017-02-19 10:47 ` Tino Calancha
@ 2017-02-26 11:35   ` Charles A. Roelli
  2017-02-28  3:55     ` Tino Calancha
  2017-03-04 23:06   ` npostavs
  1 sibling, 1 reply; 10+ messages in thread
From: Charles A. Roelli @ 2017-02-26 11:35 UTC (permalink / raw)
  To: Tino Calancha; +Cc: Philipp Stephani, 25493

Wow, well done.  Has this been committed yet?





^ permalink raw reply	[flat|nested] 10+ messages in thread

* bug#25493: 26.0.50; ediff merge should (optionally) show ancestor in fourth window
  2017-02-26 11:35   ` Charles A. Roelli
@ 2017-02-28  3:55     ` Tino Calancha
  2017-02-28  4:42       ` npostavs
  0 siblings, 1 reply; 10+ messages in thread
From: Tino Calancha @ 2017-02-28  3:55 UTC (permalink / raw)
  To: Charles A. Roelli; +Cc: Philipp Stephani, 25493, Tino Calancha



On Sun, 26 Feb 2017, Charles A. Roelli wrote:

> Wow, well done.  Has this been committed yet?
No yet.  I am waiting for aproval.
People must be busy preparing the Emacs 25.2 release.

If we don't get feedback in a while we can ask for opinion
in its emacs-devel thread: 
https://lists.gnu.org/archive/html/emacs-devel/2017-01/msg00375.html







^ permalink raw reply	[flat|nested] 10+ messages in thread

* bug#25493: 26.0.50; ediff merge should (optionally) show ancestor in fourth window
  2017-02-28  3:55     ` Tino Calancha
@ 2017-02-28  4:42       ` npostavs
  2017-02-28  6:39         ` Tino Calancha
  0 siblings, 1 reply; 10+ messages in thread
From: npostavs @ 2017-02-28  4:42 UTC (permalink / raw)
  To: Tino Calancha; +Cc: Philipp Stephani, Charles A. Roelli, 25493

Tino Calancha <tino.calancha@gmail.com> writes:

> On Sun, 26 Feb 2017, Charles A. Roelli wrote:
>
>> Wow, well done.  Has this been committed yet?
> No yet.  I am waiting for aproval.
> People must be busy preparing the Emacs 25.2 release.

It's a big patch, I haven't had time to digest the whole thing yet, but
I'm wondering about why do we need both "\ show/hide ancestor" and "/
-show ancestor buff"?

         ~ -swap variants |     s -shrink window C    |  / -show ancestor buff
                          |  $$ -show clashes only    |  & -merge w/new default
                          |  $* -skip changed regions |
    +                     |  $% -all ancestor diffs   |
    +                     |  \\ -show/hide ancestor    |





^ permalink raw reply	[flat|nested] 10+ messages in thread

* bug#25493: 26.0.50; ediff merge should (optionally) show ancestor in fourth window
  2017-02-28  4:42       ` npostavs
@ 2017-02-28  6:39         ` Tino Calancha
  0 siblings, 0 replies; 10+ messages in thread
From: Tino Calancha @ 2017-02-28  6:39 UTC (permalink / raw)
  To: npostavs; +Cc: Philipp Stephani, Charles A. Roelli, 25493, Tino Calancha



On Mon, 27 Feb 2017, npostavs@users.sourceforge.net wrote:

> Tino Calancha <tino.calancha@gmail.com> writes:
>
>> On Sun, 26 Feb 2017, Charles A. Roelli wrote:
>>
>>> Wow, well done.  Has this been committed yet?
>> No yet.  I am waiting for aproval.
>> People must be busy preparing the Emacs 25.2 release.
>
> It's a big patch, I haven't had time to digest the whole thing yet,
Thanks for look on it.  Please, take your time.
> I'm wondering about why do we need both "\ show/hide ancestor" and "/
> -show ancestor buff"?
>
>         ~ -swap variants |     s -shrink window C    |  / -show ancestor buff
>                          |  $$ -show clashes only    |  & -merge w/new default
>                          |  $* -skip changed regions |
>    +                     |  $% -all ancestor diffs   |
>    +                     |  \\ -show/hide ancestor    |

Yeah, it's weird.  I though about that.  Probably we just need the toggle 
show/hide; we might use for it the original key binding for show ancestor.

In first iteration i wanted just to provide the new feature and let
people suggest if something must be drop/supersed.





^ permalink raw reply	[flat|nested] 10+ messages in thread

* bug#25493: 26.0.50; ediff merge should (optionally) show ancestor in fourth window
  2017-02-19 10:47 ` Tino Calancha
  2017-02-26 11:35   ` Charles A. Roelli
@ 2017-03-04 23:06   ` npostavs
  2017-03-06 14:06     ` Tino Calancha
  1 sibling, 1 reply; 10+ messages in thread
From: npostavs @ 2017-03-04 23:06 UTC (permalink / raw)
  To: Tino Calancha; +Cc: Philipp Stephani, 25493

Tino Calancha <tino.calancha@gmail.com> writes:

> Philipp Stephani <p.stephani2@gmail.com> writes:
>
>> It would be very useful if ediff merge could optionally display the
>> ancestor in a fourth window, like vimdiff or meld.  See
>> https://lists.gnu.org/archive/html/emacs-devel/2017-01/msg00204.html.
>
> Following patch, by default, display the ancestor buffer and auto refine
> it in 3way merges.
> This feature can be disabled by customizing a new option.

Could you perhaps explain more in the commit messages about how the
patch works, at a high level?  It's long enough that I get lost while
reading it.

As a user, I noticed that `ediff-scroll-vertically' doesn't scroll the
ancestor buffer.

Also, I want diff refining in buffer A and B against the ancestor, not
each other.  This might be more of an addtional feature request that
doesn't necessarily need to addressed in your patch though.

> Subject: [PATCH 1/3] Show ancestor buffer in 3way merges
>
> Add an option to control if the ancestor buffer must
> be shown in 3way merges (Bug#25493).
> Add an option to control whether if show or ignore diffs with
                                   ^^
s/if/to/ I think?

>  
> +(defsubst ediff--check-ancestor-exists ()

I don't think there is reason for this to be a defsubst over a defun.

> +
> +(defun ediff-toggle-show-ancestor ()

> +    (when (eq ediff-show-ancestor
> +              (alist-get 'ediff-show-ancestor alist))
> +      (assq-delete-all 'ediff-show-ancestor alist)

I think this should be (setq alist (assq-delete-all ...))

or equivalently (cl-callf assq-delete-all alist 'ediff-show-ancestor)


> +(defun ediff-toggle-hide-equal-diffs-with-ancestor ()

> +    (when (eq ediff-hide-equal-diffs-with-ancestor
> +              (alist-get 'ediff-hide-equal-diffs-with-ancestor
> +                         alist))
> +      (assq-delete-all 'ediff-hide-equal-diffs-with-ancestor
> +                       alist)

Again here.






^ permalink raw reply	[flat|nested] 10+ messages in thread

* bug#25493: 26.0.50; ediff merge should (optionally) show ancestor in fourth window
  2017-03-04 23:06   ` npostavs
@ 2017-03-06 14:06     ` Tino Calancha
  2017-03-11 13:45       ` npostavs
  0 siblings, 1 reply; 10+ messages in thread
From: Tino Calancha @ 2017-03-06 14:06 UTC (permalink / raw)
  To: npostavs; +Cc: Philipp Stephani, 25493, tino.calancha

npostavs@users.sourceforge.net writes:

Thanks again for looking on this.  I must admit the previous patch
was terrible.
> Could you perhaps explain more in the commit messages about how the
> patch works, at a high level?  It's long enough that I get lost while
> reading it.
OK.  I have simplified the patch a lot.  I have restricted to the problem
in hands: to show the buffer ancestor in 3way merges.  The refinement of
this buffer must keep in the TODO list (see below).
> As a user, I noticed that `ediff-scroll-vertically' doesn't scroll the
> ancestor buffer.
Good catch! Fixed in the new patch.
> Also, I want diff refining in buffer A and B against the ancestor, not
> each other.  This might be more of an addtional feature request that
> doesn't necessarily need to addressed in your patch though.
It sounds like a nice idea.  We should open a new bug report once we
finish this one: there we can implement those refinements with the
ancestor.

--8<-----------------------------cut here---------------start------------->8---
From e86a53982794f421c393cd2d6f935cd4bb666852 Mon Sep 17 00:00:00 2001
From: Tino Calancha <tino.calancha@gmail.com>
Date: Mon, 6 Mar 2017 13:24:07 +0900
Subject: [PATCH 1/2] diff-mode: Improve default faces for buffer ancestor

* lisp/vc/ediff-init.el (ediff-current-diff-Ancestor)
(ediff-fine-diff-Ancestor): Use defaults consistent with
faces for 'ediff-buffer-A' and 'ediff-buffer-B'.
---
 lisp/vc/ediff-init.el | 36 ++++++++++++++++++++++--------------
 1 file changed, 22 insertions(+), 14 deletions(-)

diff --git a/lisp/vc/ediff-init.el b/lisp/vc/ediff-init.el
index 0235926fbe..535fdbfc90 100644
--- a/lisp/vc/ediff-init.el
+++ b/lisp/vc/ediff-init.el
@@ -942,13 +942,17 @@ ediff-current-diff-face-C
 
 (defface ediff-current-diff-Ancestor
   (if (featurep 'emacs)
-      '((((class color) (min-colors 88))
-	 (:background "VioletRed"))
-	(((class color) (min-colors 16))
-	 (:foreground "Black" :background "VioletRed"))
-	(((class color))
-	 (:foreground "black" :background "magenta3"))
-	(t (:inverse-video t)))
+      '((((class color) (min-colors 88) (background light))
+         :background "#cfdeee")
+        (((class color) (min-colors 88) (background dark))
+         :background "#004151")
+        (((class color) (min-colors 16) (background light))
+         :background "#cfdeee")
+        (((class color) (min-colors 16) (background dark))
+         :background "#004151")
+        (((class color))
+         (:foreground "black" :background "magenta3"))
+        (t (:inverse-video t)))
     '((((type tty))    (:foreground "black" :background "magenta3"))
       (((class color)) (:foreground "Black" :background "VioletRed"))
       (t (:inverse-video t))))
@@ -1052,13 +1056,17 @@ ediff-fine-diff-face-C
 
 (defface ediff-fine-diff-Ancestor
   (if (featurep 'emacs)
-      '((((class color) (min-colors 88))
-	 (:background "Green"))
-	(((class color) (min-colors 16))
-	 (:foreground "Black" :background "Green"))
-	(((class color))
-	 (:foreground "red3" :background "green"))
-	(t		     (:underline t :stipple "gray3")))
+      '((((class color) (min-colors 88) (background light))
+         :background "#00c5c0")
+        (((class color) (min-colors 88) (background dark))
+         :background "#009591")
+        (((class color) (min-colors 16) (background light))
+         :background "#00c5c0")
+        (((class color) (min-colors 16) (background dark))
+         :background "#009591")
+        (((class color))
+         (:foreground "red3" :background "green"))
+        (t		     (:underline t :stipple "gray3")))
     '((((type tty))    (:foreground "red3" :background "green"))
       (((class color)) (:foreground "Black" :background "Green"))
       (t	     	     (:underline t :stipple "gray3"))))
-- 
2.11.0

From a67907ba3166b3bcc22504c099b056c072fd1d09 Mon Sep 17 00:00:00 2001
From: Tino Calancha <tino.calancha@gmail.com>
Date: Mon, 6 Mar 2017 22:47:09 +0900
Subject: [PATCH 2/2] 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.
(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.
---
 doc/misc/ediff.texi   |   8 ++-
 etc/NEWS              |   5 ++
 lisp/vc/ediff-help.el |   2 +-
 lisp/vc/ediff-init.el |  10 ++++
 lisp/vc/ediff-util.el | 155 ++++++++++++++++++++++++++++++++------------------
 lisp/vc/ediff-wind.el |  86 ++++++++++++++++++++++++----
 6 files changed, 197 insertions(+), 69 deletions(-)

diff --git a/doc/misc/ediff.texi b/doc/misc/ediff.texi
index 19b7adbd66..87d3dfd6ed 100644
--- a/doc/misc/ediff.texi
+++ b/doc/misc/ediff.texi
@@ -99,7 +99,8 @@ Introduction
 another (and recover old differences if you change your mind).
 
 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
 allow the user to conveniently launch browsing or merging sessions on
 groups of files in two (or three) different directories.
@@ -828,7 +829,10 @@ Quick Help Commands
 
 @item /
 @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 &
 @kindex &
 In some situations, such as when one of the files agrees with the ancestor file
diff --git a/etc/NEWS b/etc/NEWS
index 8f7356f3e0..9dd3fe2053 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -361,6 +361,11 @@ words where first character is upper rather than title case, e.g.,
 \f
 * 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
 
 ** Electric-Buffer-menu
diff --git a/lisp/vc/ediff-help.el b/lisp/vc/ediff-help.el
index 3292b4d939..52a4825207 100644
--- a/lisp/vc/ediff-help.el
+++ b/lisp/vc/ediff-help.el
@@ -112,7 +112,7 @@ ediff-long-help-message-merge
   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
   </> -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
                      |  $* -skip changed regions |
 "
diff --git a/lisp/vc/ediff-init.el b/lisp/vc/ediff-init.el
index 535fdbfc90..e054268859 100644
--- a/lisp/vc/ediff-init.el
+++ b/lisp/vc/ediff-init.el
@@ -1363,6 +1363,16 @@ ediff-make-buffers-readonly-at-startup
 ;; if nil, this silences some messages
 (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
   "Save the results of merge jobs automatically.
 With 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 f81397950d..549066e1ec 100644
--- a/lisp/vc/ediff-util.el
+++ b/lisp/vc/ediff-util.el
@@ -178,7 +178,7 @@ ediff-setup-keymap
   (define-key ediff-mode-map "r"  nil)
   (cond (ediff-merge-job
 	 ;; 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.
 	 (define-key ediff-mode-map "a" 'ediff-copy-A-to-C)
 	 (define-key ediff-mode-map "b" 'ediff-copy-B-to-C)
@@ -553,11 +553,12 @@ ediff-setup-control-buffer
     (ediff-refresh-mode-lines)
     (setq ediff-control-window (selected-window))
     (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-window-A
 		  ediff-window-B
 		  ediff-window-C
+		  ediff-window-Ancestor
 		  ediff-split-window-function
 		  (ediff-multiframe-setup-p)
 		  ediff-wide-display-p))
@@ -600,12 +601,6 @@ ediff-update-diffs
 if necessary."
   (interactive)
   (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)))
 	;;(point-B (ediff-with-current-buffer ediff-buffer-B (point)))
 	(tmp-buffer (get-buffer-create ediff-tmp-buffer))
@@ -614,14 +609,17 @@ ediff-update-diffs
 	;; (null ediff-buffer-C) is no problem, as we later check if
 	;; ediff-buffer-C is alive
 	(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
 		  'A ediff-narrow-bounds))
 	(overl-B (ediff-get-value-according-to-buffer-type
 		  'B ediff-narrow-bounds))
 	(overl-C (ediff-get-value-according-to-buffer-type
 		  'C ediff-narrow-bounds))
-	beg-A end-A beg-B end-B beg-C end-C
-	file-A file-B file-C)
+        (overl-Ancestor (ediff-get-value-according-to-buffer-type
+                         '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)
 	(setq buf-A-file-name (file-name-nondirectory buf-A-file-name)))
@@ -629,15 +627,19 @@ ediff-update-diffs
 	(setq buf-B-file-name (file-name-nondirectory buf-B-file-name)))
     (if (stringp 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)
 
     (setq beg-A (ediff-overlay-start overl-A)
 	  beg-B (ediff-overlay-start overl-B)
 	  beg-C (ediff-overlay-start overl-C)
+	  beg-Ancestor (ediff-overlay-start overl-Ancestor)
 	  end-A (ediff-overlay-end overl-A)
 	  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
 	(progn
@@ -645,51 +647,37 @@ ediff-update-diffs
 	  (setq file-A (ediff-make-temp-file tmp-buffer "regA"))
 	  (ediff-wordify beg-B end-B ediff-buffer-B tmp-buffer)
 	  (setq file-B (ediff-make-temp-file tmp-buffer "regB"))
-	  (if ediff-3way-job
-	      (progn
-		(ediff-wordify beg-C end-C ediff-buffer-C tmp-buffer)
-		(setq file-C (ediff-make-temp-file tmp-buffer "regC"))))
+	  (when ediff-3way-job
+            (ediff-wordify beg-C end-C ediff-buffer-C tmp-buffer)
+            (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
       (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))
       (if ediff-3way-job
 	  (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-B 'fine-diffs-also)
     (ediff-clear-diff-vector 'ediff-difference-vector-C 'fine-diffs-also)
     (ediff-clear-diff-vector
      '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
-
-    ;; In case of merge job, fool it into thinking that it is just doing
-    ;; 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))
-
+    (funcall ediff-setup-diff-regions-function file-A file-B
+             (if ediff-merge-with-ancestor-job file-Ancestor file-C))
     (setq ediff-number-of-differences (length ediff-difference-vector-A))
     (delete-file file-A)
     (delete-file file-B)
-    (if file-C
-	(delete-file file-C))
+    (and file-C (delete-file file-C))
+    (and file-Ancestor (delete-file file-Ancestor))
 
     (if ediff-3way-job
 	(ediff-set-state-of-all-diffs-in-all-buffers ediff-control-buffer))
@@ -737,14 +725,16 @@ ediff-revert-buffers-then-recompute-diffs
 ;; optional NO-REHIGHLIGHT says to not rehighlight buffers
 (defun ediff-recenter (&optional no-rehighlight)
   "Bring the highlighted region of all buffers being compared into view.
-Reestablish the default three-window display."
+Reestablish the default window display."
   (interactive)
   (ediff-barf-if-not-control-buffer)
   (let (buffer-read-only)
     (if (and (ediff-buffer-live-p ediff-buffer-A)
 	     (ediff-buffer-live-p ediff-buffer-B)
 	     (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-buffer-A ediff-buffer-B ediff-buffer-C ediff-control-buffer)
       (or (eq this-command 'ediff-quit)
@@ -963,18 +953,43 @@ ediff-toggle-autorefine
 	 (setq ediff-auto-refine 'nix))
 	))
 
-(defun ediff-show-ancestor ()
-  "Show the ancestor buffer in a suitable window."
-  (interactive)
-  (ediff-recenter)
+(defun ediff--check-ancestor-exists ()
   (or (ediff-buffer-live-p ediff-ancestor-buffer)
       (if ediff-merge-with-ancestor-job
-	  (error "Lost connection to ancestor buffer...sorry")
-	(error "Not merging with ancestor")))
-  (let (wind)
-    (cond ((setq wind (ediff-get-visible-buffer-window ediff-ancestor-buffer))
-	   (raise-frame (window-frame wind)))
-	  (t (set-window-buffer ediff-window-C ediff-ancestor-buffer)))))
+	  (error "Lost connection to ancestor buffer.  This shouldn't happen.  \
+Please report this bug to bug-gnu-emacs@gnu.org")
+	(error "Not merging with ancestor"))))
+
+;; Restore `ediff-show-ancestor' on exit.
+(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)
   "Compute fine diffs.  With negative prefix arg, kill fine diffs.
@@ -1468,7 +1483,10 @@ ediff-operate-on-windows
       (ediff-recenter 'no-rehighlight))
   (if (not (and (ediff-buffer-live-p ediff-buffer-A)
 		(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))
 
@@ -1476,11 +1494,15 @@ ediff-operate-on-windows
 	 (wind-A ediff-window-A)
 	 (wind-B ediff-window-B)
 	 (wind-C ediff-window-C)
+	 (wind-Anc ediff-window-Ancestor)
 	 (coefA (ediff-get-region-size-coefficient 'A operation))
 	 (coefB (ediff-get-region-size-coefficient 'B operation))
 	 (three-way ediff-3way-job)
+         (with-Ancestor (and ediff-merge-with-ancestor-job ediff-show-ancestor))
 	 (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)
     (condition-case nil
@@ -1496,6 +1518,11 @@ ediff-operate-on-windows
 	  (condition-case nil
 	      (funcall operation (round (* coefC arg)))
 	    (error))))
+    (when with-Ancestor
+      (select-window wind-Anc)
+      (condition-case nil
+          (funcall operation (round (* coefAnc arg)))
+        (error)))
     (select-window wind)))
 
 (defun ediff-scroll-vertically (&optional arg)
@@ -1512,6 +1539,9 @@ ediff-scroll-vertically
 		(ediff-buffer-live-p ediff-buffer-B)
 		(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))
 
@@ -1531,6 +1561,10 @@ ediff-scroll-vertically
 			(window-height ediff-window-B)
 			(if ediff-3way-job
 			    (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
 		   2)
 		1 next-screen-context-lines))
@@ -1556,6 +1590,9 @@ ediff-scroll-horizontally
 		(ediff-buffer-live-p ediff-buffer-B)
 		(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))
 
@@ -1587,7 +1624,10 @@ ediff-scroll-horizontally
 			  (if ediff-3way-comparison-job
 			      (window-width 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
 		     2)
 		  3)))
 	 ;; window found
@@ -1689,6 +1729,11 @@ ediff-get-region-size-coefficient
 			       (funcall func 'B n ctl-buf)
 			       (if (ediff-buffer-live-p ediff-buffer-C)
 				   (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))))
 	  ;; this covers the horizontal coefficient as well:
 	  ;; if max-lines = 0 then coef = 1
diff --git a/lisp/vc/ediff-wind.el b/lisp/vc/ediff-wind.el
index cd10288643..8516c11d13 100644
--- a/lisp/vc/ediff-wind.el
+++ b/lisp/vc/ediff-wind.el
@@ -115,6 +115,8 @@ ediff-window-setup-function
 (ediff-defvar-local ediff-window-B nil "")
 ;; Official window for buffer C
 (ediff-defvar-local ediff-window-C nil "")
+;; Official window for buffer Ancestor
+(ediff-defvar-local ediff-window-Ancestor nil "")
 ;; Ediff's window configuration.
 ;; Used to minimize the need to rearrange windows.
 (ediff-defvar-local ediff-window-config-saved "" "")
@@ -126,7 +128,8 @@ ediff-window-alist
     (B . ediff-window-B)
     (?B . ediff-window-B)
     (C . ediff-window-C)
-    (?C . ediff-window-C)))
+    (?C . ediff-window-C)
+    (Ancestor . ediff-window-Ancestor)))
 
 
 (defcustom ediff-split-window-function 'split-window-vertically
@@ -363,9 +366,13 @@ ediff-setup-windows-plain-merge
   ;; skip dedicated and unsplittable frames
   (ediff-destroy-control-frame control-buffer)
   (let ((window-min-height 1)
+	(with-Ancestor-p (ediff-with-current-buffer control-buffer
+                           ediff-merge-with-ancestor-job))
 	split-window-function
 	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
       (setq merge-window-share ediff-merge-window-share
 	    ;; this lets us have local versions of ediff-split-window-function
@@ -394,6 +401,14 @@ ediff-setup-windows-plain-merge
     (setq wind-C (selected-window))
     (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)
     (funcall split-window-function)
 
@@ -405,7 +420,8 @@ ediff-setup-windows-plain-merge
     (ediff-with-current-buffer control-buffer
       (setq ediff-window-A wind-A
 	    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-setup-control-buffer control-buffer)
@@ -516,9 +532,13 @@ ediff-setup-windows-multiframe-merge
 	 (wind-A (ediff-get-visible-buffer-window buf-A))
 	 (wind-B (ediff-get-visible-buffer-window buf-B))
 	 (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-B (if wind-B (window-frame wind-B)))
 	 (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
 	 (force-one-frame
 	  (ediff-with-current-buffer control-buf ediff-wide-display-p))
@@ -549,7 +569,10 @@ ediff-setup-windows-multiframe-merge
 	 (merge-window-share (ediff-with-current-buffer control-buf
 			       ediff-merge-window-share))
 	 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)
 
     ;; buf-A on its own
@@ -585,6 +608,19 @@ ediff-setup-windows-multiframe-merge
 	  (setq wind-C (selected-window))
 	  (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
 	     (window-live-p wind-A))
 	(progn
@@ -606,6 +642,7 @@ ediff-setup-windows-multiframe-merge
 	(let ((window-min-height 1))
 	  (if (and (eq frame-A frame-B)
 		   (eq frame-B frame-C)
+		   (eq frame-C frame-Ancestor)
 		   (frame-live-p frame-A))
 	      (select-frame frame-A)
 	    ;; avoid dedicated and non-splittable windows
@@ -623,6 +660,14 @@ ediff-setup-windows-multiframe-merge
 	  (setq wind-C (selected-window))
 	  (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)
 
 	  (funcall split-window-function)
@@ -633,8 +678,8 @@ ediff-setup-windows-multiframe-merge
 
 	  (setq done-A 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 it was set before because use-same-frame = 1
@@ -668,10 +713,22 @@ ediff-setup-windows-multiframe-merge
 	  (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
       (setq ediff-window-A wind-A
 	    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)
 	    designated-minibuffer-frame
 	    (window-frame (minibuffer-window frame-A))))
@@ -679,7 +736,6 @@ ediff-setup-windows-multiframe-merge
     (ediff-setup-control-frame control-buf designated-minibuffer-frame)
     ))
 
-
 ;; Window setup for all comparison jobs, including 3way comparisons
 (defun ediff-setup-windows-multiframe-compare (buf-A buf-B buf-C control-buf)
 ;;; Algorithm:
@@ -1295,7 +1351,9 @@ ediff-keep-window-config
 	 (let ((ctl-wind ediff-control-window)
 	       (A-wind ediff-window-A)
 	       (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
 	    (ediff-window-visible-p A-wind)
@@ -1303,13 +1361,19 @@ ediff-keep-window-config
 	    ;; if buffer C is defined then take it into account
 	    (or (not ediff-3way-job)
 		(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 B-wind) ediff-buffer-B)
 	    (or (not ediff-3way-job)
 		(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
-		     (format "%S%S%S%S%S%S%S"
-			     ctl-wind A-wind B-wind C-wind
+		     (format "%S%S%S%S%S%S%S%S"
+			     ctl-wind A-wind B-wind C-wind Ancestor-wind
 			     ediff-split-window-function
 			     (ediff-multiframe-setup-p)
 			     ediff-wide-display-p)))))))
-- 
2.11.0

--8<-----------------------------cut here---------------end--------------->8---
In GNU Emacs 26.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.22.8)
 of 2017-03-06
Repository revision: 0fae08d0072f74d97ca70b91a4d46d8d28a03952  





^ permalink raw reply related	[flat|nested] 10+ messages in thread

* bug#25493: 26.0.50; ediff merge should (optionally) show ancestor in fourth window
  2017-03-06 14:06     ` Tino Calancha
@ 2017-03-11 13:45       ` npostavs
  2017-03-14  7:43         ` Tino Calancha
  0 siblings, 1 reply; 10+ messages in thread
From: npostavs @ 2017-03-11 13:45 UTC (permalink / raw)
  To: Tino Calancha; +Cc: Philipp Stephani, 25493

Tino Calancha <tino.calancha@gmail.com> writes:

> OK.  I have simplified the patch a lot.  I have restricted to the problem
> in hands: to show the buffer ancestor in 3way merges.  The refinement of
> this buffer must keep in the TODO list (see below).

Thanks, it's a lot more comprehensible now.

> Subject: [PATCH 2/2] 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.
                                           ^^
Extra space there.

> -
> -    ;; In case of merge job, fool it into thinking that it is just doing
> -    ;; 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))
> -
> +    (funcall ediff-setup-diff-regions-function file-A file-B
> +             (if ediff-merge-with-ancestor-job file-Ancestor file-C))

It works when I tested it, so I guess this is correct, but it's not
really obvious to me why (i.e., why we no longer need to "fool it").
Could you add an explanation to the commit message?

Otherwise looks good to me.





^ permalink raw reply	[flat|nested] 10+ messages in thread

* bug#25493: 26.0.50; ediff merge should (optionally) show ancestor in fourth window
  2017-03-11 13:45       ` npostavs
@ 2017-03-14  7:43         ` Tino Calancha
  0 siblings, 0 replies; 10+ messages in thread
From: Tino Calancha @ 2017-03-14  7:43 UTC (permalink / raw)
  To: 25493-done

npostavs@users.sourceforge.net writes:

>> Subject: [PATCH 2/2] 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.
>                                            ^^
> Extra space there.
Thanks.
>> -
>> -    ;; In case of merge job, fool it into thinking that it is just doing
>> -    ;; 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))
>> -
>> +    (funcall ediff-setup-diff-regions-function file-A file-B
>> +             (if ediff-merge-with-ancestor-job file-Ancestor file-C))
>
> It works when I tested it, so I guess this is correct, but it's not
> really obvious to me why (i.e., why we no longer need to "fool it").
> Could you add an explanation to the commit message?
Now I mention that this trick is not necessary.  Before the patch there
were several parts of the code executed only if
`ediff-3way-comparison-job' was non-nil.  After the patch, those parts
of the code also test if `ediff-merge-with-ancestor-job' is non-nil;
that's why we don't need to fool it anymore.
> Otherwise looks good to me.
Thank you.
Pushed to master as commit 0f3d1b782353fd1fc0ab5f89d47d9e790f44e6b2





^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2017-03-14  7:43 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-01-20 11:17 bug#25493: 26.0.50; ediff merge should (optionally) show ancestor in fourth window Philipp Stephani
2017-02-19 10:47 ` Tino Calancha
2017-02-26 11:35   ` Charles A. Roelli
2017-02-28  3:55     ` Tino Calancha
2017-02-28  4:42       ` npostavs
2017-02-28  6:39         ` Tino Calancha
2017-03-04 23:06   ` npostavs
2017-03-06 14:06     ` Tino Calancha
2017-03-11 13:45       ` npostavs
2017-03-14  7:43         ` Tino Calancha

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).