Split Frame into 3 equal buffers

Hi hi. :waving_hand:

I know that this can be done with built in stuff that balances windows, but I wanted a function that just does this automatically. It comes in useful for all sorts of things. Just keybind it and blam! :collision: You got 3 equal vertical buffers across your frame. I find it useful. Maybe you will too! :upside_down_face:

;; Divide frame into 3 equal windows
(defun split-frame-into-three-vertical ()
  "Split the current frame into three equal vertical windows."
  (interactive)
  (delete-other-windows)
  (let ((w1 (selected-window)))
    (let ((w2 (split-window-right)))
      (select-window w2)
      (let ((w3 (split-window-right)))
        ;; Optional: balance the window sizes
        (balance-windows)
        ;; You can also set different buffers here if desired
        (select-window w1)))))

I just used my C-q universal binding to bind it to C-q b 3.

Enjoy!

2 Likes

Hm, that might come in helpful. But you can simplify the code into

(defun split-frame-into-three-vertical ()
  "Split the current frame into three equal vertical windows."
  (interactive)
  (delete-other-windows)
  (split-window-right)
  (split-window-right)
  (balance-windows))

split-window-right will not change the selected window, so after the first split, we’re still on w1 in your terminology, and the code above has the following effect:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”¬β”€β”€β”¬β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”¬β”€β”€β”€β”¬β”€β”€β”€β”
β”‚           β”‚    β”‚     ┇     β”‚    β”‚  ┇  ┇     β”‚    β”‚   ┇   ┇   β”‚
β”‚   X       β”‚ -> β”‚  X  ┇     β”‚ -> β”‚X ┇  ┇     β”‚ -> β”‚ X ┇   ┇   β”‚
β”‚   1       β”‚    β”‚  1  ┇  2  β”‚    β”‚1 ┇3 ┇ 2   β”‚    β”‚ 1 ┇ 3 ┇ 2 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”΄β”€β”€β”΄β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”΄β”€β”€β”€β”΄β”€β”€β”€β”˜

(x marks the selected window, the numbers mark the order of window creation)

If you care about the windows being created in the same way like yours, e.g.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”¬β”€β”€β”¬β”€β”€β”    β”Œβ”€β”€β”€β”¬β”€β”€β”€β”¬β”€β”€β”€β”
β”‚           β”‚    β”‚     ┇     β”‚    β”‚     ┇  ┇  β”‚    β”‚   ┇   ┇   β”‚
β”‚   X       β”‚ -> β”‚  X  ┇     β”‚ -> β”‚  X  ┇  ┇  β”‚ -> β”‚ X ┇   ┇   β”‚
β”‚   1       β”‚    β”‚  1  ┇  2  β”‚    β”‚  1  ┇2 ┇3 β”‚    β”‚ 1 ┇ 2 ┇ 3 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”΄β”€β”€β”΄β”€β”€β”˜    β””β”€β”€β”€β”΄β”€β”€β”€β”΄β”€β”€β”€β”˜

then you can use with-selected-window:

(defun split-frame-into-three-vertical ()
  "Split the current frame into three equal vertical windows."
  (interactive)
  (delete-other-windows)
  (with-selected-window (split-window-right)
    (split-window-right))
  (balance-windows))
1 Like

You can also set window-combination-resize to t for window splits.
I think it would be enough for many users.

That only has the same effect if you start with a clean slate. If at any point you manually any window, then window-combination-resize will not balance all windows, but keep the proportions.

(I myself would just use C-x + to balance windows manually, tbh)

1 Like

Similar idea, but will split a window into an arbitrary number of columns and rows:

(defun bigeatie-split-window-evenly (splits)
  "Splits a window evenly into a grid.

Takes a numeric prefix argument between 11 and 99, inclusive.  The first number is interpreted as the number of columns to split the window into and the second number the number of rows.

SPLITS: A two digit number, the tens-place representing columns and the ones-place reprsenting rows."
  (interactive "p")
  (if (and (> splits 10)
	   (< splits 100))
      (let* ((root-width (window-width))
             (root-height (window-height))
	     (columns (max 1 (/ splits 10)))
	     (rows (max 1 (% splits 10)))
	     (split-width (- (/ root-width columns) 0))
	     (split-height (/ root-height rows))
	     (win-list nil))
	(push (selected-window) win-list)
	(dotimes (i (- columns 1))
	  (message (format "%s" i))
	  (push (split-window (selected-window)
			      (- (window-width) split-width)
			      t)
		win-list))
	(dolist (win win-list)
	  (dotimes (i (- rows 1))
	    (split-window win (- (window-height win) split-height)))))))

That’s (if (< 10 splits 100) ...). Also, (if cond body) without else form is (when cond body). Not a big difference, but when compared to if communicates that there is no else part.

Always good to learn the idioms, thanks!