Last active
August 29, 2015 14:06
-
-
Save kamichidu/c5d059a16387ff2fe6ad to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let s:V= vital#of('vital') | |
let s:L= s:V.import('Data.List') | |
unlet s:V | |
function! s:is_most_left(winnr) | |
let save_winnr= winnr() | |
try | |
execute a:winnr 'wincmd w' | |
wincmd h | |
return winnr() == a:winnr | |
finally | |
execute save_winnr 'wincmd w' | |
endtry | |
endfunction | |
function! s:is_most_top(winnr) | |
let save_winnr= winnr() | |
try | |
execute a:winnr 'wincmd w' | |
wincmd k | |
return winnr() == a:winnr | |
finally | |
execute save_winnr 'wincmd w' | |
endtry | |
endfunction | |
function! s:is_most_right(winnr) | |
let save_winnr= winnr() | |
try | |
execute a:winnr 'wincmd w' | |
wincmd l | |
return winnr() == a:winnr | |
finally | |
execute save_winnr 'wincmd w' | |
endtry | |
endfunction | |
function! s:is_most_bottom(winnr) | |
let save_winnr= winnr() | |
try | |
execute a:winnr 'wincmd w' | |
wincmd j | |
return winnr() == a:winnr | |
finally | |
execute save_winnr 'wincmd w' | |
endtry | |
endfunction | |
function! s:compute_left(winnr) | |
let save_winnr= winnr() | |
try | |
execute a:winnr 'wincmd w' | |
let left= 0 | |
while !s:is_most_left(winnr()) | |
wincmd h | |
let left+= winwidth('.') | |
" border | |
let left+= 1 | |
endwhile | |
return left | |
finally | |
execute save_winnr 'wincmd w' | |
endtry | |
endfunction | |
function! s:compute_top(winnr) | |
let save_winnr= winnr() | |
try | |
execute a:winnr 'wincmd w' | |
let top= 0 | |
while !s:is_most_top(winnr()) | |
wincmd k | |
let top+= winheight('.') | |
" statusline | |
let top+= 1 | |
endwhile | |
return top | |
finally | |
execute save_winnr 'wincmd w' | |
endtry | |
endfunction | |
function! s:winpos() | |
let save_winnr= winnr() | |
try | |
let positions= [] | |
for winnr in range(1, winnr('$')) | |
let positions+= [{ | |
\ 'winnr': winnr, | |
\ 'left': s:compute_left(winnr), | |
\ 'top': s:compute_top(winnr), | |
\ 'width': winwidth(winnr), | |
\ 'height': winheight(winnr), | |
\}] | |
endfor | |
return positions | |
finally | |
execute save_winnr 'wincmd w' | |
endtry | |
endfunction | |
function! s:snapshot() | |
let g:winlay_snapshot= s:winpos() | |
endfunction | |
function! s:winmark() | |
if !exists('s:seq') | |
let s:seq= 0 | |
endif | |
let s:seq+= 1 | |
let w:hogehoge_mark= s:seq | |
return s:seq | |
endfunction | |
function! s:wingomark(mark) | |
for winnr in range(1, winnr('$')) | |
if getwinvar(winnr, 'hogehoge_mark', -1) == a:mark | |
execute winnr 'wincmd w' | |
return | |
endif | |
endfor | |
endfunction | |
function! s:restore_layout(data) | |
" search horizontal border | |
" find windows have same top | |
let tops= s:L.uniq(map(copy(a:data), 'v:val.top')) | |
let candidates= [] | |
for top in tops | |
let positions= filter(copy(a:data), 'v:val.top == top') | |
if !empty(positions) | |
let candidates+= [{'top': top, 'positions': positions}] | |
endif | |
endfor | |
let widths= map(copy(candidates), "{'top': v:val.top, 'width': s:L.foldl('v:memo + v:val.width', 0, v:val.positions) + (len(v:val.positions) - 1)}") | |
let widths= filter(copy(widths), "v:val.width == max(map(copy(widths), 'v:val.width'))") | |
" search vertical border | |
" find windows have same left | |
let lefts= s:L.uniq(map(copy(a:data), 'v:val.left')) | |
let candidates= [] | |
for left in lefts | |
let positions= filter(copy(a:data), 'v:val.left == left') | |
if !empty(positions) | |
let candidates+= [{'left': left, 'positions': positions}] | |
endif | |
endfor | |
unlet left | |
let heights= map(copy(candidates), "{'left': v:val.left, 'height': s:L.foldl('v:memo + v:val.height', 0, v:val.positions) + (len(v:val.positions) - 1)}") | |
let heights= filter(copy(heights), "v:val.height == max(map(copy(heights), 'v:val.height'))") | |
if len(widths) > 1 | |
let widths= s:L.sort(widths, 'a:a.top - a:b.top') | |
for i in range(len(widths)) | |
let above= widths[i] | |
let below= get(widths, i + 1, {'top': &lines}) | |
let inside= filter(copy(a:data), "v:val.top >= above.top && v:val.top < below.top") | |
let save_winnr= s:winmark() | |
if i < len(widths) - 1 | |
aboveleft split | |
endif | |
if len(inside) > 1 | |
call s:restore_layout(inside) | |
endif | |
call s:wingomark(save_winnr) | |
endfor | |
elseif len(heights) > 1 | |
let heights= s:L.sort(heights, 'a:a.left - a:b.left') | |
for i in range(len(heights)) | |
let left= heights[i] | |
let right= get(heights, i + 1, {'left': &columns}) | |
let inside= filter(copy(a:data), "v:val.left >= left.left && v:val.left < right.left") | |
let save_winnr= s:winmark() | |
if i < len(heights) - 1 | |
aboveleft vsplit | |
endif | |
if len(inside) > 1 | |
call s:restore_layout(inside) | |
endif | |
call s:wingomark(save_winnr) | |
endfor | |
endif | |
endfunction | |
function! s:restore_size(data) | |
if winnr('$') != len(a:data) | |
throw 'Mismatch number of windows' | |
endif | |
let data= s:L.sort(a:data, 'a:a.winnr - a:b.winnr') | |
let save_winnr= winnr() | |
try | |
for state in data | |
execute state.winnr 'wincmd w' | |
execute 'vertical resize' state.width | |
execute 'resize' state.height | |
endfor | |
finally | |
execute save_winnr 'wincmd w' | |
endtry | |
endfunction | |
function! s:restore() | |
try | |
call s:restore_layout(g:winlay_snapshot) | |
call s:restore_size(g:winlay_snapshot) | |
catch | |
echomsg v:throwpoint | |
echomsg v:exception | |
endtry | |
endfunction | |
let g:winlay_stack= [] | |
command! WinLaySnapshot call s:snapshot() | |
command! WinLayRestore call s:restore() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment