swap-window-buffers

Emacsをウィンドウを2分割で使うことがおおいのですが、それぞれに表示しているバッファを入れ替えたいことがまれにあり、そのためのコマンドを作りました。ウィンドウツリーの選択されているノード(ウィンドウ)と同一階層にあり、ライブ(window-live-p)で隣り合うものを入れ替える対象とします。以下に例として4パターンの分割したウィンドウツリーの図をあげています。

Red-frame: selected-window, Pink-shading: swapping-targets
(defun swap-window-buffers ()
  (interactive)
  (let (siblings
        (child (window-child (window-parent)))
        (src-win (selected-window))
        (src-buf (window-buffer))
        dest-win
        dest-buf)
    (message
     (catch 'except
       (if (or (eq (frame-root-window) src-win)
               (not (window-parent)))
           (throw 'except "Cannot swap!"))
       (while child
         (when (window-live-p child)
           (setq siblings (cons child siblings)))
         (setq child (window-next-sibling child)))
       (if (and (> (length siblings) 1)
                (eq (car siblings) src-win))
           (setq dest-win (car (last siblings)))
         (setq dest-win
               (catch 'dest
                 (mapl #'(lambda (tail)
                           (if (eq (car tail) src-win)
                               (throw 'dest (cadr tail))))
                       (reverse siblings))
                 nil)))
       (if (not dest-win)
           (throw 'except "Cannot swap!"))
       (setq dest-buf (window-buffer dest-win))
       (condition-case nil
           (mapc #'(lambda (pair)
                     (set-window-buffer (car pair) (cdr pair) t))
                 (list (cons dest-win src-buf)
                       (cons src-win dest-buf)))
         (error (throw 'except "Swap failed!")))
       (select-window dest-win t)
       (format "Swap window-buffers: %s <=> %s"
               (buffer-name src-buf) (buffer-name dest-buf))))))

gist