From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Tino Calancha Newsgroups: gmane.emacs.bugs Subject: bug#25493: 26.0.50; ediff merge should (optionally) show ancestor in fourth window Date: Mon, 06 Mar 2017 23:06:44 +0900 Message-ID: <87innmh53f.fsf@calancha-pc> References: <874lzqe9tn.fsf@calancha-pc> <87fuisabg5.fsf@users.sourceforge.net> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: blaine.gmane.org 1488809245 22806 195.159.176.226 (6 Mar 2017 14:07:25 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Mon, 6 Mar 2017 14:07:25 +0000 (UTC) User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.0.50 (gnu/linux) Cc: Philipp Stephani , 25493@debbugs.gnu.org, tino.calancha@gmail.com To: npostavs@users.sourceforge.net Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Mon Mar 06 15:07:19 2017 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cktIC-0005HC-2H for geb-bug-gnu-emacs@m.gmane.org; Mon, 06 Mar 2017 15:07:16 +0100 Original-Received: from localhost ([::1]:44079 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cktII-0001xA-3a for geb-bug-gnu-emacs@m.gmane.org; Mon, 06 Mar 2017 09:07:22 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:36305) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cktI4-0001uQ-BD for bug-gnu-emacs@gnu.org; Mon, 06 Mar 2017 09:07:12 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cktHz-0000sO-65 for bug-gnu-emacs@gnu.org; Mon, 06 Mar 2017 09:07:08 -0500 Original-Received: from debbugs.gnu.org ([208.118.235.43]:43708) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1cktHy-0000s3-Vy for bug-gnu-emacs@gnu.org; Mon, 06 Mar 2017 09:07:03 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1cktHy-0004BE-9u for bug-gnu-emacs@gnu.org; Mon, 06 Mar 2017 09:07:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Tino Calancha Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Mon, 06 Mar 2017 14:07:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 25493 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: Original-Received: via spool by 25493-submit@debbugs.gnu.org id=B25493.148880921716055 (code B ref 25493); Mon, 06 Mar 2017 14:07:02 +0000 Original-Received: (at 25493) by debbugs.gnu.org; 6 Mar 2017 14:06:57 +0000 Original-Received: from localhost ([127.0.0.1]:41907 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cktHs-0004Ar-IH for submit@debbugs.gnu.org; Mon, 06 Mar 2017 09:06:57 -0500 Original-Received: from mail-pf0-f194.google.com ([209.85.192.194]:35286) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1cktHq-0004Ab-Da for 25493@debbugs.gnu.org; Mon, 06 Mar 2017 09:06:55 -0500 Original-Received: by mail-pf0-f194.google.com with SMTP id 67so13334241pfg.2 for <25493@debbugs.gnu.org>; Mon, 06 Mar 2017 06:06:54 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:references:date:in-reply-to:message-id :user-agent:mime-version; bh=OAmhSaex4kxhT9px88+9/qpSsoETMTxlM7P2LRCVB18=; b=BU+oJcrDwroEBsXHa6aevh2AwfgoYcLU2BmWqrDfgMtC27M//jt3yFUZIel1Ef+ZM6 w8J3fCLJa+f4euD7iWGNvt9vFfFnrPhWwTS8uGnaFBOfp/v5D1cVNtCQ5tJp02CAAItk 7bVKm4KMsPnp9+h/vnv0YP3Blhzc6DwBcbzdmVbsu2h0U+3ckJrJXqqfoouR50EhZk+D UU60W6ss9ni0yusg1wlGHhfkMbVh373U5HfnFOobIj9CUhkDucp8EUqK9JvWnSjGVnxt SCw0zsbx1PuPUC464vCQj9GvpDzKYdt3isXerqs6RiVFZfrCU2gfFfUJZjAho9NIdOls lBFg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:references:date:in-reply-to :message-id:user-agent:mime-version; bh=OAmhSaex4kxhT9px88+9/qpSsoETMTxlM7P2LRCVB18=; b=taURkk1355MecG4YPsvp8W4ty3/UTUwlhho7NjEl7lgrLx5uih6PYCLt2JtYoxLCa1 4acAwJENxFST9QwOojaxW3b8lWpURf0jFZOJIiaGT3IPJELxQwe2kK1OjPy0/GTRBvGI sDGE/hLmRu5y8RhyO2QY1jVC4Ny1cXozQinh4iD+mMr7wRdGP9QRYa0A6RLog7bNNdrg 0P4uiX5OI61M+ODhpJhZa2TPtKSptNf2O1KDP1KsXwfrUO9gYqtMo9pe1TXe5uv+jBSy Fo6HRlUPnhCWfVCZo1CbRrqBQBXZ18pfLO+MCTqNuW84I94eqFP2Al8uuiW+eRJ5LxoM /1fg== X-Gm-Message-State: AMke39kObUgrTQ4d4PDtCHQRWANi2w9k1yy86jHpW3ANJoR8FyawSTgJO13IMo0VP6sDAA== X-Received: by 10.99.37.199 with SMTP id l190mr20438127pgl.86.1488809208479; Mon, 06 Mar 2017 06:06:48 -0800 (PST) Original-Received: from calancha-pc (128.126.156.220.dy.bbexcite.jp. [220.156.126.128]) by smtp.gmail.com with ESMTPSA id z27sm39984936pfg.38.2017.03.06.06.06.46 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 06 Mar 2017 06:06:47 -0800 (PST) In-Reply-To: <87fuisabg5.fsf@users.sourceforge.net> (npostavs's message of "Sat, 04 Mar 2017 18:06:50 -0500") X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:130251 Archived-At: 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 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 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., * 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