0

I often use the <C-w>_ and <C-w>| commands in Vim to maximize the current pane to fill the entire window (I have it keymapped to <C-w>0).

And I've recently started using a tiling window manager, which means I sometimes find myself "moving" terminals into smaller or larger sections of the screen.

What happens is, say I have a vim instance in the lower right portion of my screen, with the current pane "maximized" to full view.

If I set that "tile" with the vim instance to be the active tile, it will move it to the main tile which takes up, say, 65% of the left side of the screen. This means the entire vim window itself now takes up a larger width and height and because of that, the active pane is no longer "fullscreen" based on this adjustment. Which means I need to rerun the <C-w>0 command in order for it to "recalculate" the pane dimensions so it fills up the now larger window space.

How could I have this done automatically? Maybe something to the effect of:

Upon window resize, if the active pane had previously been maximized, re-run the maximize command. Similarly, if the <C-w>= had been previously ran, then re-run the resize all panes to be equal command.

Maybe it could tie in somehow to Vim's VimResized autocommand? http://vimdoc.sourceforge.net/htmldoc/autocmd.html#VimResized

Thanks in advance for any help or pointers!


EDIT: I've started reading about VimScript, will look into writing my first Plugin to hopefully address this need :)

2
  • Are you aware of :only? I use it all the time to “maximise” a window, although it has the difference that you can’t as easily recreate the previously split files so may or may not help your workflow. Apr 1, 2021 at 20:08
  • Yes, I'm aware of :only, but like you said, I don't use it often because I usually want to keep the ability to quickly restore the "minimized" panes. Thanks for offering though! :)
    – Spectator6
    Apr 1, 2021 at 21:58

3 Answers 3

1

You could set a global variable (g:zoom_status) to remember whether you are meant to be zoomed in (maximised) or not. Then, every time the terminal is resized restore the windows to that status.

For example, to map [leader]0 (where [leader] defaults to \) to toggle between zoomed in state (window maximised) and zoomed out (all windows equal):

function! ToggleZoom()
    let g:zoom_status = get(g:, 'zoom_status', 0)
    if g:zoom_status == 0
        " Not currently zoomed, so lets zoom in
        wincmd _
        wincmd |
        let g:zoom_status = 1
    else
        " Currently zoomed in, so lets zoom out
        wincmd =
        let g:zoom_status = 0
    endif
endfunction

nnoremap <leader>0 :call ToggleZoom()<CR>

Then, to keep either zoomed in or out every time vim is resized:

function! RetainZoomStatus()
    " Assume that if we haven't called ToggleZoom() before then all windows
    " are probably meant to be equal (set g:zoom_status to 0)
    let g:zoom_status = get(g:, 'zoom_status', 0)
    if g:zoom_status == 0
        wincmd =
    else
        wincmd _
        wincmd |
    endif
endfunction

augroup zoom
    autocmd!
    autocmd VimResized * call RetainZoomStatus()
augroup END

There are probably lots of edge cases depending on your workflow that might make this not do what you want, but with a bit of tweaking it could cover most of the way you work. The key is probably remembering to toggle between "one window maximised" and "all windows equal" with [leader]0, but at worst if you forget you can just hit it again.

NB: I have used [leader]0) rather than CTRL0 because in native vim the latter can't be mapped; perhaps you are using neovim which can do this.

1
  • Hi Andrew! Thanks for the pointers! That's almost exactly how I've set it up so far :) It's nice to see your vimscript as a comparison! As for my reference <C-0>, that was a typo on my part, I meant to say <C-w>0 and <C-w>=
    – Spectator6
    Apr 2, 2021 at 1:50
0

I can't build you a plugin but I can give you some ideas. You want to look into columns you're going to need it see :help columns.

let s:tWidth = &columns "the width size of the window
let s:WL31 = float2nr(eval('0.30*' . s:tWidth))
let s:WL32 = float2nr(eval('0.43*' . s:tWidth))
let s:WL33 = float2nr(eval('0.25*' . s:tWidth))

You're going to be resizing with this:

let customSize = float2nr(eval('0.28*' . s:tWidth))
execute ':'winnr('$') . 'resize|vert '. winnr('$') . 'resize ' . customSize

Move windows like this:

execute leftWin . 'wincmd x' 

How many windows are open ?

let openWindows=gettabinfo(tabpagenr())[0].windows->len()

Then for loop on all the windows you want to resize:

for counter in range(1,openWindows)
"code here to resize the windows you want
endfor

Hope that at least gives you some ideas.

3
  • Thank you @ritchie! I'm excited to dive into this :) Along with your suggestions, I've also found several "golden ratio" related plugins that have helped point me in the right direction too.
    – Spectator6
    Apr 1, 2021 at 23:56
  • @Spectator6 No problem, I recommend you ready Learn Vim The Hardway it's a long read but it will save you a lot of hours.
    – ritchie
    Apr 2, 2021 at 0:34
  • Great reference, thank you!
    – Spectator6
    Apr 2, 2021 at 1:53
0

Another way of achieving your desired workflow might be to use tab pages. Tab pages can be thought of as another viewport on the same set of buffers, with its own window layout.

Therefore, if you have a bunch of splits, you can make the current split the only window visible in a new tab page with:

:tab split

To then go back to your previously-defined layout, you can either close the current tab page with :tabclose or go to the previous tab page with :tabprevious (mapped to gT). As this truly is the only window open in the current tab page, resizing the window won't have any problems, and your other layout remains preserved in your first tab page. You can see the current tab pages you have and what windows they are showing with :tabs.

Using this workflow, the other part of your puzzle is if you have multiple windows open in the current tab page, make them all equal every time vim is resized. This can be achieved with:

augroup zoom
    autocmd!
    autocmd VimResized * wincmd =
augroup zoom

The main scenario this will not deal with is if you have multiple windows open in the current tab page, but they aren't equal (e.g. 75%/25%) and you want to preserve that. You'd then need more complex logic in the autocmd.

Your Answer

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

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