10

From time to time, by mistake, I split my screen vertically C-x 3 (binded to split-window-right), whereas I originally wanted a horizontal splitting C-x 2 (binded to split-window-below).

Question: is there a function to switch between vertical <-> horizontal splitting?

note: for the moment, I hide the buffer C-x 0 and re-split with the right C-x 2 (instead of C-x 3) and reselect the buffer... which is clearly not optimal.

Picaud Vincent
  • 1,158
  • 8
  • 20
  • Duplicate of https://emacs.stackexchange.com/questions/5371/how-to-change-emacs-windows-from-vertical-split-to-horizontal-split – Calaf Feb 08 '21 at 23:26

4 Answers4

8

I use the following for this:

(defun toggle-window-split ()
  (interactive)
  (if (= (count-windows) 2)
      (let* ((this-win-buffer (window-buffer))
             (next-win-buffer (window-buffer (next-window)))
             (this-win-edges (window-edges (selected-window)))
             (next-win-edges (window-edges (next-window)))
             (this-win-2nd (not (and (<= (car this-win-edges)
                                         (car next-win-edges))
                                     (<= (cadr this-win-edges)
                                         (cadr next-win-edges)))))
             (splitter
              (if (= (car this-win-edges)
                     (car (window-edges (next-window))))
                  'split-window-horizontally
                'split-window-vertically)))
        (delete-other-windows)
        (let ((first-win (selected-window)))
          (funcall splitter)
          (if this-win-2nd (other-window 1))
          (set-window-buffer (selected-window) this-win-buffer)
          (set-window-buffer (next-window) next-win-buffer)
          (select-window first-win)
          (if this-win-2nd (other-window 1))))))

I picked that up from Magnars Sveen of Emacs Rocks fame.

Tyler
  • 21,719
  • 1
  • 52
  • 92
  • Thanks! Just tested it, it works. I will wait a little to see if other solutions working with more than 2 windows are suggested. – Picaud Vincent Dec 18 '18 at 14:43
  • 3
    sure thing. I never thought about this until Magnars mentioned it somewhere, and now it's indispensible. For tweaking more complex layouts I find `ace-swap-windows` from the [ace-window](https://github.com/abo-abo/ace-window) package is also quite handy. – Tyler Dec 18 '18 at 14:49
7

You can roll your own as @Tyler suggested, but there are some packages that support this. Check out the transpose-frame package on MELPA: https://melpa.org/#/transpose-frame

This handles the simple 2-window case, but can also handle more complex arrangements where you flip or rotate the windows around.

glucas
  • 20,175
  • 1
  • 51
  • 83
4

I've not tried the transpose-frame package so I don't know how it compares, but I use the package https://melpa.org/#/rotate . Combined that with https://melpa.org/#/smartrep using the config:

  (use-package smartrep
    :config
    (setq smartrep-mode-line-active-bg nil))

  (use-package rotate
    :config
    (smartrep-define-key global-map "C-|"
    '(("w" . rotate-window)
      ("l" . rotate-layout))))

And then C-| w w w w... etc. rotates through assigning buffers to windows, and C-| l l l l... etc. rotates through layouts (such as your use case of flipping between a vertical and horizontal split).

Marty Neal
  • 199
  • 7
2

I use C-x 0 (or C-x 1) and then C-x 4 b. The buffer I just closed is offered as the default, so it is still quick to do.

Dan
  • 21
  • 1
  • 2
    That doesn't "switch between horizontal and vertical splitting"; it just gives you the default split. – phils Dec 19 '18 at 04:04
  • @phil I think @Dan was referring to the "note" section of question where I say I was reselecting the buffer. The trick is to use `C-x 4 b`, but yes, that does not solve the problem. – Picaud Vincent Dec 19 '18 at 09:15