0

Does vim have a way of arranging split windows in a grid pattern? (Preferably, without closing existing splits, and without using a plugin.)

Tmux has some predefined windowpane layouts. For example, ctrl+b alt+1 will divide the window horizonally (i.e., it moves existing splits into a tall, skinny configuration). And ctrl+b alt+2 will divide the window vertically (it moves existing splits into a short, wide configuration).

The one I'm interested in is tmux's ctrl+b alt+5. If you have an even number of splits, it will arrange the splits in a regular grid pattern. (Except for 8 splits, for some reason. But if there are 9 splits, ctrl+b alt+5 produces a 3x3 grid.)

In vim, using various combinations of ctrl+w H, ctrl+w J, ctrl+w K, ctrl+w L, ctrl+w r, and ctrl+w x, I can reproduce the tmux preset layouts, except for tmux ctrl+b alt+5. And I know that I can get the grid layout by closing and re-splitting a window; but I would like to avoid that.

So, to restate my question: Does vim have a way of arranging split windows in a grid pattern? (Preferably, without closing existing splits, and without using a plugin.)

This question from 2015 is basically the same as mine: How can I get my windows back into a grid formation? (I guess I'm wondering if the answer is still "not really").

I am using vim version 8.1, on WSL Ubuntu in Windows Terminal on Windows 10. (I know vim 9 exists, and I will upgrade sooner or later. If the grid layout functionaly exists in version 9, please let me know.)

Thanks for any help.

1
  • 1
    Once you have things arranged the way you like, you can use a session or view to get back to that layout quickly.
    – D. Ben Knoble
    Feb 6 at 14:18

1 Answer 1

1

I have created the vim-orpheus plugin to display in the grid all the unsaved buffer at a glance with the command:

:Qall

I have also added the :Grid command to show all the listed buffer at a glance:

enter image description here

If you are only interested by the code of the Grid command here is the code:

let s:height_factor = 3

function! s:getwindowsize(winnr)
  let ret = winwidth(a:winnr)
  let ret = ret * winheight(a:winnr) * s:height_factor
  return ret
endfunction

function! s:getlargestwindow()
  let ret = 0
  let largestsize = 0
  for winnr in range(1, winnr('$'))
    let currentsize = s:getwindowsize(winnr)
    if currentsize > largestsize
      let ret = winnr
      let largestsize = currentsize
    endif
  endfor
  return ret
endfunction

function! s:addonewindow()
  let winnr = s:getlargestwindow()
  execute winnr . 'wincmd w'
  if winheight(winnr) * s:height_factor > winwidth(winnr)
    wincmd s
  else
    wincmd v
  endif
  " wincmd =
endfunction

function! s:spreadbuffers(buffers)
  if len(a:buffers) == 0
    return
  endif
  if winnr('$') > 1
    execute 'b' . a:buffers[1]
    only
  endif
  for i in range(2, len(a:buffers))
    call s:addonewindow()
  endfor
  let winnr = 0
  for bufnr in a:buffers
    let winnr = winnr + 1
    execute winnr . 'wincmd w'
    execute 'b' . bufnr
  endfor
endfunction

function! s:getlistedbuffers()
  let buffers = range(1, bufnr('$'))
  let buffers = filter(buffers, 'bufexists(v:val)')
  let buffers = filter(buffers, 'getbufinfo(v:val)[0].listed')
  return buffers
endfunction

function! s:spreadlistedbuffers()
  let buffers = s:getlistedbuffers()
  call s:spreadbuffers(buffers)
  1wincmd w
endfunction

" Grid All Listed
command! Grid call s:spreadlistedbuffers()
2
  • Thanks; I will take a look this weekend.
    – m_mlvx
    Feb 8 at 3:53
  • Thanks for the feedback. The code do it for the listed buffers. I could adapt it for the visible buffers if needed. Feb 8 at 5:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.