aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Colascione2025-03-21 19:46:08 -0400
committerDaniel Colascione2025-03-21 20:56:12 -0400
commite5ee1d2a74c6a0989c863c3c6c06eba31efaecb3 (patch)
treecebe7391a81e10fa0776484dfb8c7553b52abf13
parentb21636580bed822bd9fb8bb84014311fa9b4c071 (diff)
downloademacs-e5ee1d2a74c6a0989c863c3c6c06eba31efaecb3.tar.gz
emacs-e5ee1d2a74c6a0989c863c3c6c06eba31efaecb3.zip
Adapt ediff to nonstandard layouts
Make ediff cope with having some of its windows (especially the control window) not shown by a custom ediff-window-setup-function. Modernize relevant adjacent code. After this change, one can write a custom ediff-window-setup-function that doesn't show the control window. * doc/misc/ediff.texi (Notes on Heavy-duty Customization): Refine language to explain that the window setup function doesn't have to show all windows. * lisp/vc/ediff-util.el (ediff-select-control-window-on-setup): New variable. (ediff-setup, ediff-recenter, ediff-recenter-one-window) (ediff-recenter-ancestor, ediff-toggle-read-only) (ediff-operate-on-windows, ediff-jump-to-difference-at-point) (ediff-default-suspend-function) (ediff-clone-buffer-for-region-comparison) (ediff-clone-buffer-for-window-comparison): Modernize control flow; select only windows that exist. * lisp/vc/ediff-wind.el (ediff-with-live-window): New convenience macro. (ediff-window-setup-function): Explain relaxed contract.
-rw-r--r--doc/misc/ediff.texi6
-rw-r--r--etc/NEWS8
-rw-r--r--lisp/vc/ediff-util.el229
-rw-r--r--lisp/vc/ediff-wind.el24
4 files changed, 125 insertions, 142 deletions
diff --git a/doc/misc/ediff.texi b/doc/misc/ediff.texi
index 26a0ee433d0..73f751f3a4b 100644
--- a/doc/misc/ediff.texi
+++ b/doc/misc/ediff.texi
@@ -2399,10 +2399,12 @@ The window displaying buffer A@. If buffer A is not visible, this variable
2399is @code{nil} or it may be a dead window. 2399is @code{nil} or it may be a dead window.
2400 2400
2401@item ediff-window-B 2401@item ediff-window-B
2402The window displaying buffer B. 2402The window displaying buffer B. If buffer B is not visible, this variable
2403is @code{nil} or it may be a dead window.
2403 2404
2404@item ediff-window-C 2405@item ediff-window-C
2405The window displaying buffer C, if any. 2406The window displaying buffer C, if any. If buffer C is not visible,
2407this variable is @code{nil} or it may be a dead window.
2406 2408
2407@item ediff-control-frame 2409@item ediff-control-frame
2408A dedicated frame displaying the control buffer, if it exists. It is 2410A dedicated frame displaying the control buffer, if it exists. It is
diff --git a/etc/NEWS b/etc/NEWS
index 010b7cbee85..ed31222b1ae 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1202,6 +1202,14 @@ changes when supplied with a universal prefix argument via 'C-u':
1202- 'C-u c a' copies all changes from buffer C to buffer A. 1202- 'C-u c a' copies all changes from buffer C to buffer A.
1203- 'C-u c b' copies all changes from buffer C to buffer B. 1203- 'C-u c b' copies all changes from buffer C to buffer B.
1204 1204
1205+++
1206*** Ediff now supports more flexible custom window layouts
1207Custom implementations of 'ediff-window-setup-function' no
1208longer need to display *all* ediff windows. Any of the A, B, C,
1209and control windows can be left undisplayed and the corresponding
1210variable set to nil. This change enables custom layouts without
1211a control panel window.
1212
1205** Dired 1213** Dired
1206 1214
1207+++ 1215+++
diff --git a/lisp/vc/ediff-util.el b/lisp/vc/ediff-util.el
index e07f2c0b2f6..6446e0a945b 100644
--- a/lisp/vc/ediff-util.el
+++ b/lisp/vc/ediff-util.el
@@ -36,6 +36,15 @@
36(require 'ediff-diff) 36(require 'ediff-diff)
37(require 'ediff-merg) 37(require 'ediff-merg)
38 38
39(eval-when-compile
40 (require 'cl-lib))
41
42(ediff-defvar-local ediff-select-control-window-on-setup t
43 "Select the control window after window setup.
44`t' for compatibility. Custom `ediff-window-setup-function'
45implementations may want to set it to `nil' to fully control
46window setup.")
47
39 48
40;;; Functions 49;;; Functions
41 50
@@ -472,20 +481,20 @@ to invocation.")
472 (ediff-get-value-according-to-buffer-type 481 (ediff-get-value-according-to-buffer-type
473 'C ediff-narrow-bounds)))) 482 'C ediff-narrow-bounds))))
474 ;; position point in buf A 483 ;; position point in buf A
475 (save-excursion 484 (when (window-live-p ediff-window-A)
476 (select-window ediff-window-A) 485 (with-selected-window ediff-window-A
477 (goto-char shift-A)) 486 (goto-char shift-A)))
478 ;; position point in buf B 487 ;; position point in buf B
479 (save-excursion 488 (when (window-live-p ediff-window-B)
480 (select-window ediff-window-B) 489 (with-selected-window ediff-window-B
481 (goto-char shift-B)) 490 (goto-char shift-B)))
482 (if ediff-3way-job 491 (if (and ediff-3way-job (window-live-p ediff-window-C))
483 (save-excursion 492 (with-selected-window ediff-window-C
484 (select-window ediff-window-C) 493 (goto-char shift-C))))
485 (goto-char shift-C))) 494
486 ) 495 (when (and ediff-select-control-window-on-setup
487 496 (window-live-p ediff-control-window))
488 (select-window ediff-control-window) 497 (select-window ediff-control-window))
489 (ediff-visible-region) 498 (ediff-visible-region)
490 499
491 (mapc #'funcall startup-hooks) 500 (mapc #'funcall startup-hooks)
@@ -776,16 +785,19 @@ buffers."
776 (or (not ediff-3way-job) 785 (or (not ediff-3way-job)
777 (ediff-buffer-live-p ediff-buffer-C))) 786 (ediff-buffer-live-p ediff-buffer-C)))
778 (progn 787 (progn
779 (or no-rehighlight 788 (or no-rehighlight
780 (ediff-select-difference ediff-current-difference)) 789 (ediff-select-difference ediff-current-difference))
781 790
782 (ediff-recenter-one-window 'A) 791 (save-current-buffer
783 (ediff-recenter-one-window 'B) 792 (ediff-recenter-one-window 'A))
784 (if ediff-3way-job 793 (save-current-buffer
785 (ediff-recenter-one-window 'C)) 794 (ediff-recenter-one-window 'B))
795 (if ediff-3way-job
796 (save-current-buffer
797 (ediff-recenter-one-window 'C)))
786 798
787 (ediff-with-current-buffer control-buf 799 (ediff-with-current-buffer control-buf
788 (ediff-recenter-ancestor) ; check if ancestor is alive 800 (ediff-recenter-ancestor) ; check if ancestor is alive
789 801
790 (if (and (ediff-multiframe-setup-p) 802 (if (and (ediff-multiframe-setup-p)
791 (not ediff-use-long-help-message) 803 (not ediff-use-long-help-message)
@@ -801,13 +813,11 @@ buffers."
801 (ediff-with-current-buffer control-buf (ediff-refresh-mode-lines)) 813 (ediff-with-current-buffer control-buf (ediff-refresh-mode-lines))
802 )) 814 ))
803 815
804;; this function returns to the window it was called from 816;; this function does not change current window
805;; (which was the control window)
806(defun ediff-recenter-one-window (buf-type) 817(defun ediff-recenter-one-window (buf-type)
807 (if (ediff-valid-difference-p) 818 (if (ediff-valid-difference-p)
808 ;; context must be saved before switching to windows A/B/C 819 ;; context must be saved before switching to windows A/B/C
809 (let* ((ctl-wind (selected-window)) 820 (let* ((shift (ediff-overlay-start
810 (shift (ediff-overlay-start
811 (ediff-get-value-according-to-buffer-type 821 (ediff-get-value-according-to-buffer-type
812 buf-type ediff-narrow-bounds))) 822 buf-type ediff-narrow-bounds)))
813 (job-name ediff-job-name) 823 (job-name ediff-job-name)
@@ -817,20 +827,16 @@ buffers."
817 (window (if (window-live-p (symbol-value window-name)) 827 (window (if (window-live-p (symbol-value window-name))
818 (symbol-value window-name)))) 828 (symbol-value window-name))))
819 829
820 (if (and window ediff-windows-job) 830 (when (and window ediff-windows-job)
821 (set-window-start window shift)) 831 (set-window-start window shift))
822 (if window 832 (when window
823 (progn 833 (with-selected-window window
824 (select-window window) 834 (deactivate-mark)
825 (deactivate-mark) 835 (ediff-position-region
826 (ediff-position-region
827 (ediff-get-diff-posn buf-type 'beg nil control-buf) 836 (ediff-get-diff-posn buf-type 'beg nil control-buf)
828 (ediff-get-diff-posn buf-type 'end nil control-buf) 837 (ediff-get-diff-posn buf-type 'end nil control-buf)
829 (ediff-get-diff-posn buf-type 'beg nil control-buf) 838 (ediff-get-diff-posn buf-type 'beg nil control-buf)
830 job-name 839 job-name))))))
831 )))
832 (select-window ctl-wind)
833 )))
834 840
835(defun ediff-recenter-ancestor () 841(defun ediff-recenter-ancestor ()
836 ;; do half-hearted job by recentering the ancestor buffer, if it is alive and 842 ;; do half-hearted job by recentering the ancestor buffer, if it is alive and
@@ -838,21 +844,17 @@ buffers."
838 (if (and (ediff-buffer-live-p ediff-ancestor-buffer) 844 (if (and (ediff-buffer-live-p ediff-ancestor-buffer)
839 (ediff-valid-difference-p)) 845 (ediff-valid-difference-p))
840 (let ((window (ediff-get-visible-buffer-window ediff-ancestor-buffer)) 846 (let ((window (ediff-get-visible-buffer-window ediff-ancestor-buffer))
841 (ctl-wind (selected-window))
842 (job-name ediff-job-name) 847 (job-name ediff-job-name)
843 (ctl-buf ediff-control-buffer)) 848 (ctl-buf ediff-control-buffer))
844 (ediff-with-current-buffer ediff-ancestor-buffer 849 (ediff-with-current-buffer ediff-ancestor-buffer
845 (goto-char (ediff-get-diff-posn 'Ancestor 'beg nil ctl-buf)) 850 (goto-char (ediff-get-diff-posn 'Ancestor 'beg nil ctl-buf))
846 (if window 851 (when (window-live-p window)
847 (progn 852 (with-selected-window window
848 (select-window window) 853 (ediff-position-region
849 (ediff-position-region
850 (ediff-get-diff-posn 'Ancestor 'beg nil ctl-buf) 854 (ediff-get-diff-posn 'Ancestor 'beg nil ctl-buf)
851 (ediff-get-diff-posn 'Ancestor 'end nil ctl-buf) 855 (ediff-get-diff-posn 'Ancestor 'end nil ctl-buf)
852 (ediff-get-diff-posn 'Ancestor 'beg nil ctl-buf) 856 (ediff-get-diff-posn 'Ancestor 'beg nil ctl-buf)
853 job-name)))) 857 job-name)))))))
854 (select-window ctl-wind)
855 )))
856 858
857 859
858;; This will have to be refined for 3way jobs 860;; This will have to be refined for 3way jobs
@@ -1064,10 +1066,9 @@ of the current buffer."
1064 (sit-for 3)))) ; let the user see the warning 1066 (sit-for 3)))) ; let the user see the warning
1065 (if (and toggle-ro-cmd 1067 (if (and toggle-ro-cmd
1066 (string-match "read-only-mode" (symbol-name toggle-ro-cmd))) 1068 (string-match "read-only-mode" (symbol-name toggle-ro-cmd)))
1067 (save-excursion 1069 (save-window-excursion
1068 (save-window-excursion 1070 (ediff-with-live-window (ediff-get-visible-buffer-window buf)
1069 (select-window (ediff-get-visible-buffer-window buf)) 1071 (command-execute toggle-ro-cmd)))
1070 (command-execute toggle-ro-cmd)))
1071 (user-error "Don't know how to toggle read-only in buffer %S" buf)) 1072 (user-error "Don't know how to toggle read-only in buffer %S" buf))
1072 1073
1073 ;; Check if we made the current buffer updatable, but its file is RO. 1074 ;; Check if we made the current buffer updatable, but its file is RO.
@@ -1413,8 +1414,8 @@ Used in ediff-windows/regions only."
1413(defun ediff-operate-on-windows (operation arg) 1414(defun ediff-operate-on-windows (operation arg)
1414 1415
1415 ;; make sure windows aren't dead 1416 ;; make sure windows aren't dead
1416 (if (not (and (window-live-p ediff-window-A) (window-live-p ediff-window-B))) 1417 (unless (and (window-live-p ediff-window-A) (window-live-p ediff-window-B))
1417 (ediff-recenter 'no-rehighlight)) 1418 (ediff-recenter 'no-rehighlight))
1418 (if (not (and (ediff-buffer-live-p ediff-buffer-A) 1419 (if (not (and (ediff-buffer-live-p ediff-buffer-A)
1419 (ediff-buffer-live-p ediff-buffer-B) 1420 (ediff-buffer-live-p ediff-buffer-B)
1420 (or (not ediff-3way-job) (ediff-buffer-live-p ediff-buffer-C)) 1421 (or (not ediff-3way-job) (ediff-buffer-live-p ediff-buffer-C))
@@ -1424,8 +1425,7 @@ Used in ediff-windows/regions only."
1424 )) 1425 ))
1425 (error ediff-KILLED-VITAL-BUFFER)) 1426 (error ediff-KILLED-VITAL-BUFFER))
1426 1427
1427 (let* ((wind (selected-window)) 1428 (let* ((wind-A ediff-window-A)
1428 (wind-A ediff-window-A)
1429 (wind-B ediff-window-B) 1429 (wind-B ediff-window-B)
1430 (wind-C ediff-window-C) 1430 (wind-C ediff-window-C)
1431 (wind-Anc ediff-window-Ancestor) 1431 (wind-Anc ediff-window-Ancestor)
@@ -1438,26 +1438,16 @@ Used in ediff-windows/regions only."
1438 (coefAnc (if with-Ancestor 1438 (coefAnc (if with-Ancestor
1439 (ediff-get-region-size-coefficient 'Ancestor operation)))) 1439 (ediff-get-region-size-coefficient 'Ancestor operation))))
1440 1440
1441 (select-window wind-A) 1441 (ediff-with-live-window wind-A
1442 (condition-case nil 1442 (ignore-errors (funcall operation (round (* coefA arg)))))
1443 (funcall operation (round (* coefA arg))) 1443 (ediff-with-live-window wind-B
1444 (error)) 1444 (ignore-errors (funcall operation (round (* coefB arg)))))
1445 (select-window wind-B) 1445 (when three-way
1446 (condition-case nil 1446 (ediff-with-live-window wind-C
1447 (funcall operation (round (* coefB arg))) 1447 (ignore-errors (funcall operation (round (* coefC arg))))))
1448 (error))
1449 (if three-way
1450 (progn
1451 (select-window wind-C)
1452 (condition-case nil
1453 (funcall operation (round (* coefC arg)))
1454 (error))))
1455 (when with-Ancestor 1448 (when with-Ancestor
1456 (select-window wind-Anc) 1449 (ediff-with-live-window wind-Anc
1457 (condition-case nil 1450 (ignore-errors (funcall operation (round (* coefAnc arg))))))))
1458 (funcall operation (round (* coefAnc arg)))
1459 (error)))
1460 (select-window wind)))
1461 1451
1462(defun ediff-scroll-vertically (&optional arg) 1452(defun ediff-scroll-vertically (&optional arg)
1463 "Vertically scroll buffers A, B (and C if appropriate). 1453 "Vertically scroll buffers A, B (and C if appropriate).
@@ -1817,44 +1807,29 @@ current point position in the specified buffer."
1817 (beg (if past-last-diff 1807 (beg (if past-last-diff
1818 (ediff-with-current-buffer buffer (point-max)) 1808 (ediff-with-current-buffer buffer (point-max))
1819 (ediff-get-diff-posn buf-type 'beg (1- diff-no)))) 1809 (ediff-get-diff-posn buf-type 'beg (1- diff-no))))
1820 ctl-wind wind-A wind-B wind-C 1810 wind-A wind-B wind-C
1821 shift) 1811 shift)
1822 (if past-last-diff 1812 (if past-last-diff
1823 (ediff-jump-to-difference -1) 1813 (ediff-jump-to-difference -1)
1824 (ediff-jump-to-difference diff-no)) 1814 (ediff-jump-to-difference diff-no))
1825 (setq ctl-wind (selected-window) 1815 (setq wind-A ediff-window-A
1826 wind-A ediff-window-A
1827 wind-B ediff-window-B 1816 wind-B ediff-window-B
1828 wind-C ediff-window-C) 1817 wind-C ediff-window-C)
1829 (if arg 1818 (if arg
1830 (progn 1819 (save-selected-window
1831 (ediff-with-current-buffer buffer 1820 (setq shift (- beg pt))
1832 (setq shift (- beg pt))) 1821 (ediff-with-live-window wind-A
1833 (select-window wind-A) 1822 (when past-last-diff (goto-char (point-max)))
1834 (if past-last-diff (goto-char (point-max))) 1823 (ignore-errors (backward-char shift))
1835 (condition-case nil 1824 (recenter))
1836 (backward-char shift) ; noerror, if beginning of buffer 1825 (ediff-with-live-window wind-B
1837 (error)) 1826 (when past-last-diff (goto-char (point-max)))
1838 (recenter) 1827 (ignore-errors (backward-char shift))
1839 (select-window wind-B) 1828 (recenter))
1840 (if past-last-diff (goto-char (point-max))) 1829 (ediff-with-live-window wind-C
1841 (condition-case nil 1830 (when past-last-diff (goto-char (point-max)))
1842 (backward-char shift) ; noerror, if beginning of buffer 1831 (ignore-errors (backward-char shift))
1843 (error)) 1832 (recenter))))))
1844 (recenter)
1845 (if (window-live-p wind-C)
1846 (progn
1847 (select-window wind-C)
1848 (if past-last-diff (goto-char (point-max)))
1849 (condition-case nil
1850 (backward-char shift) ; noerror, if beginning of buffer
1851 (error))
1852 (recenter)
1853 ))
1854 (select-window ctl-wind)
1855 ))
1856 ))
1857
1858 1833
1859;; find region most related to the current point position (or POS, if given) 1834;; find region most related to the current point position (or POS, if given)
1860;; returns diff number as seen by the user (i.e., 1+ the internal 1835;; returns diff number as seen by the user (i.e., 1+ the internal
@@ -2725,10 +2700,7 @@ only if this merge job is part of a group, i.e., was invoked from within
2725 (let* ((buf-A ediff-buffer-A) 2700 (let* ((buf-A ediff-buffer-A)
2726 (buf-B ediff-buffer-B) 2701 (buf-B ediff-buffer-B)
2727 (buf-C ediff-buffer-C) 2702 (buf-C ediff-buffer-C)
2728 (buf-A-wind (ediff-get-visible-buffer-window buf-A)) 2703 (buf-patch (if (boundp 'ediff-patchbufer) ediff-patchbufer nil))
2729 (buf-B-wind (ediff-get-visible-buffer-window buf-B))
2730 (buf-C-wind (ediff-get-visible-buffer-window buf-C))
2731 (buf-patch (if (boundp 'ediff-patchbufer) ediff-patchbufer nil))
2732 (buf-patch-diag (if (boundp 'ediff-patch-diagnostics) 2704 (buf-patch-diag (if (boundp 'ediff-patch-diagnostics)
2733 ediff-patch-diagnostics nil)) 2705 ediff-patch-diagnostics nil))
2734 (buf-err ediff-error-buffer) 2706 (buf-err ediff-error-buffer)
@@ -2746,35 +2718,18 @@ only if this merge job is part of a group, i.e., was invoked from within
2746 (if buf-fine-diff (bury-buffer buf-fine-diff)) 2718 (if buf-fine-diff (bury-buffer buf-fine-diff))
2747 (if buf-patch (bury-buffer buf-patch)) 2719 (if buf-patch (bury-buffer buf-patch))
2748 (if buf-patch-diag (bury-buffer buf-patch-diag)) 2720 (if buf-patch-diag (bury-buffer buf-patch-diag))
2749 (if (window-live-p buf-A-wind) 2721 (cl-loop
2750 (progn 2722 with buffers = (list buf-A buf-B buf-C)
2751 (select-window buf-A-wind) 2723 with windows = (mapcar #'ediff-get-visible-buffer-window buffers)
2752 (delete-other-windows) 2724 for buffer in buffers
2753 (bury-buffer)) 2725 for window in windows
2754 (if (ediff-buffer-live-p buf-A) 2726 do (cond ((window-live-p window)
2755 (progn 2727 (select-window window)
2756 (set-buffer buf-A) 2728 (delete-other-windows)
2757 (bury-buffer)))) 2729 (bury-buffer))
2758 (if (window-live-p buf-B-wind) 2730 (buffer
2759 (progn 2731 (set-buffer buffer)
2760 (select-window buf-B-wind) 2732 (bury-buffer))))))
2761 (delete-other-windows)
2762 (bury-buffer))
2763 (if (ediff-buffer-live-p buf-B)
2764 (progn
2765 (set-buffer buf-B)
2766 (bury-buffer))))
2767 (if (window-live-p buf-C-wind)
2768 (progn
2769 (select-window buf-C-wind)
2770 (delete-other-windows)
2771 (bury-buffer))
2772 (if (ediff-buffer-live-p buf-C)
2773 (progn
2774 (set-buffer buf-C)
2775 (bury-buffer))))
2776 ))
2777
2778 2733
2779(defun ediff-suspend () 2734(defun ediff-suspend ()
2780 "Suspend Ediff. 2735 "Suspend Ediff.
@@ -3274,8 +3229,9 @@ Without an argument, it saves customized diff argument, if available
3274 (setq ediff-temp-indirect-buffer t)) 3229 (setq ediff-temp-indirect-buffer t))
3275 (pop-to-buffer cloned-buff) 3230 (pop-to-buffer cloned-buff)
3276 (setq wind (ediff-get-visible-buffer-window cloned-buff)) 3231 (setq wind (ediff-get-visible-buffer-window cloned-buff))
3277 (select-window wind) 3232 (when (window-live-p wind)
3278 (delete-other-windows) 3233 (select-window wind)
3234 (delete-other-windows))
3279 (or (mark) (push-mark)) 3235 (or (mark) (push-mark))
3280 (setq mark-active 'ediff-util) 3236 (setq mark-active 'ediff-util)
3281 (setq-local transient-mark-mode t) 3237 (setq-local transient-mark-mode t)
@@ -3310,7 +3266,8 @@ Without an argument, it saves customized diff argument, if available
3310 (let ((cloned-buff (ediff-make-cloned-buffer buff region-name))) 3266 (let ((cloned-buff (ediff-make-cloned-buffer buff region-name)))
3311 (ediff-with-current-buffer cloned-buff 3267 (ediff-with-current-buffer cloned-buff
3312 (setq ediff-temp-indirect-buffer t)) 3268 (setq ediff-temp-indirect-buffer t))
3313 (set-window-buffer wind cloned-buff) 3269 (when (window-live-p wind)
3270 (set-window-buffer wind cloned-buff))
3314 cloned-buff)) 3271 cloned-buff))
3315 3272
3316(defun ediff-buffer-type (buffer) 3273(defun ediff-buffer-type (buffer)
diff --git a/lisp/vc/ediff-wind.el b/lisp/vc/ediff-wind.el
index 4ac21cb4136..aefa17de2c6 100644
--- a/lisp/vc/ediff-wind.el
+++ b/lisp/vc/ediff-wind.el
@@ -53,16 +53,21 @@ frame.
53 53
54If you don't like any of the two provided functions, write your own one. 54If you don't like any of the two provided functions, write your own one.
55The basic guidelines: 55The basic guidelines:
56 1. It should leave the control buffer current and the control window 56 1. It should leave the control buffer current and, if showing,
57 selected. 57 the control window selected if showing these windows.
58 2. It should set `ediff-window-A', `ediff-window-B', `ediff-window-C', 58 2. It should set `ediff-window-A', `ediff-window-B', `ediff-window-C',
59 and `ediff-control-window' to contain window objects that display 59 and `ediff-control-window' to contain window objects that display
60 the corresponding buffers. 60 the corresponding buffers or `nil' if the corresponding window
61 is not shown.
61 3. It should accept the following arguments: 62 3. It should accept the following arguments:
62 buffer-A, buffer-B, buffer-C, control-buffer 63 buffer-A, buffer-B, buffer-C, control-buffer
63 Buffer C may not be used in jobs that compare only two buffers. 64 Buffer C may not be used in jobs that compare only two buffers.
64If you plan to do something fancy, take a close look at how the two 65If you plan to do something fancy, take a close look at how the two
65provided functions are written." 66provided functions are written.
67
68Set `ediff-select-control-window-on-setup' to nil to prevent the window
69`ediff-control-window' being selected by ediff after this
70function returns. "
66 :type '(choice (const :tag "Choose Automatically" ediff-setup-windows-default) 71 :type '(choice (const :tag "Choose Automatically" ediff-setup-windows-default)
67 (const :tag "Multi Frame" ediff-setup-windows-multiframe) 72 (const :tag "Multi Frame" ediff-setup-windows-multiframe)
68 (const :tag "Single Frame" ediff-setup-windows-plain) 73 (const :tag "Single Frame" ediff-setup-windows-plain)
@@ -247,6 +252,17 @@ keyboard input to go into icons."
247 252
248;;; Functions 253;;; Functions
249 254
255(defmacro ediff-with-live-window (window &rest body)
256 "Like `with-selected-window' but only if WINDOW is live.
257If WINDOW is not live (or not a window) do nothing and don't evaluate
258BODY, instead returning nil."
259 (declare (indent 1) (debug (form body)))
260 (let ((w (gensym "window")))
261 `(let ((,w ,window))
262 (when (window-live-p ,w)
263 (with-selected-window ,w
264 ,@body)))))
265
250(defun ediff-get-window-by-clicking (_wind _prev-wind wind-number) 266(defun ediff-get-window-by-clicking (_wind _prev-wind wind-number)
251 (let (event) 267 (let (event)
252 (message 268 (message