" == New version: tries to automatically keep up without whatever layout changes " you make, by storing an unfocused and focused size for each window. == " " Explanation: Whenever you leave a window, it remembers what size it was, and " whenever you enter a window, it remembers what size it was before entering. " Thus it records "focused" and "unfocused" sizes for each window, and it will " try to grow/shrink windows on entering/leaving, to match the recorded value. " " Warning: This system is not perfect, specifically when opening a new window " (changing the layout) it has no strategy and will often squash the new " window when it is unfocused (because other windows remember their old sizes, " so don't leave any space for the new window). " " Solution: The best approach appears to be, as soon as your layout breaks in " some way, fix it immediately with 20+ or whatever, to minimize the " damage (before the new broken values get recorded). This is a small work " overhead for the user, which he must exchange for the beneficial features of " this script! " Options: " " New feature: Set a default height for newly split windows, as percentage of " the size of the original window. Without it Vim usually splits 50-50. " "let g:wrs_default_height_pct = 90 " " We "detect" when a split is about to occur by mapping s and :h " below. You may want to add more mappings for other splitting actions. "let g:wrsDebug = 1 function! s:InitEvents() augroup WindowsRememberSizes autocmd! autocmd WinLeave * call Leaving() autocmd WinEnter * call Entering() augroup END endfunction function! s:Debug(msg) if exists('g:wrsDebug') && g:wrsDebug > 0 echo a:msg endif endfunction function! s:Leaving() " Avoid trashing remembered sizes when toggle_maximize.vim script is in use if (exists("g:isToggledVertically") && g:isToggledVertically) || (exists("g:isToggledHorizontally") && g:isToggledHorizontally) return endif let w:heightWhenFocused = winheight(0) let w:widthWhenFocused = winwidth(0) call s:Debug( "[exit] ".bufname('%')." saved foc ".w:widthWhenFocused.",".w:heightWhenFocused ) if exists('w:heightWhenUnfocused') && w:heightWhenUnfocused < winheight(0) call s:Debug( "[exit] ".bufname('%')." setting ".w:widthWhenUnfocused."x".w:heightWhenUnfocused ) exec "resize ".w:heightWhenUnfocused endif if exists('w:widthWhenUnfocused') && w:widthWhenUnfocused < winwidth(0) exec "vert resize ".w:widthWhenUnfocused endif if s:weAreAboutToSplit if exists("g:wrs_default_height_pct") let w:heightWhenFocused = w:heightWhenFocused * 2 * g:wrs_default_height_pct / 100 endif endif let s:heightOfLastWindowWeLeft = winheight(0) endfunction function! s:Entering() " Avoid trashing remembered sizes when toggle_maximize.vim script is in use if (exists("g:isToggledVertically") && g:isToggledVertically) || (exists("g:isToggledHorizontally") && g:isToggledHorizontally) return endif let w:heightWhenUnfocused = winheight(0) let w:widthWhenUnfocused = winwidth(0) call s:Debug( "[enter] ".bufname('%')." saved unf ".w:widthWhenUnfocused.",".w:heightWhenUnfocused ) if s:weAreAboutToSplit " We don't do this on things like MBE "if exists("g:wrs_default_height_pct") && (&buftype!="nofile" || &bufhidden=="") if exists("g:wrs_default_height_pct") && &buftype!="nofile" let w:heightWhenFocused = s:heightOfLastWindowWeLeft * 2 * g:wrs_default_height_pct / 100 let w:widthWhenFocused = winwidth(0) " Silly workaround to prevent the Debug call from breaking :P endif let s:weAreAboutToSplit = 0 endif if exists('w:heightWhenFocused') && w:heightWhenFocused > winheight(0) call s:Debug( "[enter] ".bufname('%')." restoring ".w:widthWhenFocused."x".w:heightWhenFocused ) exec "resize ".w:heightWhenFocused endif if exists('w:widthWhenFocused') && w:widthWhenFocused > winwidth(0) exec "vert resize ".w:widthWhenFocused endif endfunction call s:InitEvents() " Detect when we are about to split window vertically let s:weAreAboutToSplit = 0 function s:WeAreAboutToSplit() let s:weAreAboutToSplit = 1 endfunction nnoremap s :call WeAreAboutToSplit()s "nnoremap s :call WeAreAboutToSplit():split nnoremap :h :call WeAreAboutToSplit():h nnoremap :help :call WeAreAboutToSplit():help " Exposed to user function! ForgetWindowSizes() let l:winnr = winnr() "" PROBLEM: windo will cause Leave and Enter events to fire! Solved - we temporarily clear the events. "" Oh Perhaps noautocmd is the better solution to that. augroup WindowsRememberSizes autocmd! augroup END noautocmd windo silent! exec "unlet! w:widthWhenFocused" noautocmd windo silent! exec "unlet! w:widthWhenUnfocused" noautocmd windo silent! exec "unlet! w:heightWhenFocused" noautocmd windo silent! exec "unlet! w:heightWhenUnfocused" exec l:winnr." wincmd w" call s:InitEvents() endfunction " Some keybinds, entirely optional " NOTE: copied from older version below nmap Om - nmap Ok + nmap Oo < nmap Oj > nnoremap - nnoremap + nnoremap < nnoremap > " BUGS: " When we add a new window to the list, e.g. TagList, when switching to it, the old unfocused size of the previous window from the *old* layout is applied. " I think we need to forget some things when layout changes? Forget all unfocused sizes? " Or perhaps when a new window enters the layout, we should quickly grab its dimensions and set those as its focused and unfocused size? " OK I like this version a lot now. With the exception of the major bugs, which is when new windows are made, sometimes a window will end up 0 height or 0 width. " When we are thinking of restoring or saving values, we could check the number of windows (or even their names) to see if any change has occured. " New windows should be encouraged to take 50% of the space I guess, as per Vim's default. " Perhaps what we should do is have window remember their relative size rather than their actual size. Would this be a percentage, or a ratio? " Then what do we do when a new window is created? Shrink them all by 10%? Shrink them intelligently? " TODO: We need :ForgetWidths and :ForgetHeights and :ForgetSizes to disable " autocmds, so we really can visit every window and forget their w:settings. " It would be pretty handy sometimes, when the display looks right on this " window, but old settings are causing trouble on others. " " TODO: Do something useful on VimResized event, for example scale all " remembered sizes proportional to size change, and scale all open windows " too! Actually NO to the last bit, and no to scaling TList/MBE/FileExplorer! " Vim often does what I want to achieve when I enlarge the window, it makes " the current window grow whilst others stay the same. Actually TList always " stays the same width whether it is current window or not. The only issue is " height - if the current window is below another then it grows, but if it is " above another then it doesn't!