From: Tino Calancha <tino.calancha@gmail.com>
To: Philipp Stephani <p.stephani2@gmail.com>
Cc: 25493@debbugs.gnu.org, tino.calancha@gmail.com
Subject: bug#25493: 26.0.50; ediff merge should (optionally) show ancestor in fourth window
Date: Sun, 19 Feb 2017 19:47:32 +0900 [thread overview]
Message-ID: <874lzqe9tn.fsf@calancha-pc> (raw)
In-Reply-To: <wvr44m0u56at.fsf@gmail.com> (Philipp Stephani's message of "Fri, 20 Jan 2017 12:17:46 +0100")
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
next prev parent reply other threads:[~2017-02-19 10:47 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=874lzqe9tn.fsf@calancha-pc \
--to=tino.calancha@gmail.com \
--cc=25493@debbugs.gnu.org \
--cc=p.stephani2@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).