3
votes

I came across this gist

(defun swap-windows ()
 "If you have 2 windows, it swaps them."
 (interactive)
 (cond ((not (= (count-windows) 2))
        (message "You need exactly 2 windows to do this."))
       (t
        (let* ((w1 (first (window-list)))
               (w2 (second (window-list)))
               (b1 (window-buffer w1))
               (b2 (window-buffer w2))
               (s1 (window-start w1))
               (s2 (window-start w2)))
          (set-window-buffer w1 b2)
          (set-window-buffer w2 b1)
          (set-window-start w1 s2)
          (set-window-start w2 s1)))))

today, which swaps the contents of the buffers in two windows, as long as there are exactly two windows. The problem for me is that I usually have ecb running, which creates 1 or more extra windows. I've never really done anything with elisp except tweak methods I get from other places, and this (hopefully) simple change is a bit above my current comprehension.

I spent some time looking through both the ecb information, and the emacs manual, but can't find a reasonable way to determine if there are exactly two non-ecb windows open.

I also tried using things like 'bury-buffer' on the ecb windows, so I could just assume the they wouldn't be at the front of the list, but that was a flawed approach to begin with.

So my question, is there a way to modify the gist to make it work with ecb? I'm assuming there is something special about ecb windows, but I couldn't find anything I could access.

2

2 Answers

3
votes

I also tried using things like 'bury-buffer' on the ecb windows, so I could just assume the they wouldn't be at the front of the list, but that was a flawed approach to begin with.

Bit of a hack, but you can hide the ECB windows, call swap-windows, and show them again, like so:

(defun my-swap-windows ()
  (interactive)
  (ecb-hide-ecb-windows)
  (swap-windows)
  (ecb-show-ecb-windows))

By the way, I had to add this line to get the gist to work:

(require 'cl)

Edit: I wasn't seeing the window resizing problem you described, but this code should swap non-ECB windows while ignoring ECB windows.

(require 'cl)

(defun non-ecb-window-list ()
  (remove-if
   #'(lambda (window)
       (find (window-buffer window) (ecb-dedicated-special-buffers)))
   (window-list)))

(defun count-non-ecb-windows ()
  (length (non-ecb-window-list)))

(defun swap-windows ()
 "If you have 2 windows, it swaps them."
 (interactive)
 (cond ((not (= (count-non-ecb-windows) 2))
        (message "You need exactly 2 windows to do this."))
       (t
        (let* ((w1 (first (non-ecb-window-list)))
               (w2 (second (non-ecb-window-list)))
               (b1 (window-buffer w1))
               (b2 (window-buffer w2))
               (s1 (window-start w1))
               (s2 (window-start w2)))
          (set-window-buffer w1 b2)
          (set-window-buffer w2 b1)
          (set-window-start w1 s2)
          (set-window-start w2 s1)))))
1
votes

I'll go ahead and post this answer, as I wrote/discovered it with some more trial and error. It isn't what I asked for, which the accepted answer is, but it has its own merits for others reading this thread.

(defun swap-windows ()
 "Swap two windows."
 (interactive)
 (let* ((w1 (selected-window))
    (w2 (next-window))
    (b1 (window-buffer w1))
    (b2 (window-buffer w2))
    (s1 (window-start w1))
    (s2 (window-start w2)))
   (set-window-buffer w1 b2)
   (set-window-buffer w2 b1)
   (set-window-start w1 s2)
   (set-window-start w2 s1)))

Since I basically always know what C-x o will go to, which is what 'next-window' is supposed to return, this function is almost always what I want. However, it leaves off any kind of error checking, and doesn't really answer the question as written, just my poorly expressed intent.