(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)
(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))
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))
;; (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)))
(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
(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))
;; 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)
(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.
(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))
(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
(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)
(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))
(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))
(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))
(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
(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
(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 "" "")
(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
;; 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
(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)
(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)
(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))
(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
(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
(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
(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)
(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
(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))))
(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:
(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)
;; 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)))))))