2018-04-05 13:06:54 +02:00

433 lines
13 KiB
VimL

" =============== ============================================================
" Name : window.vim
" Synopsis : vim script library: window
" Author : Zhao Cai <caizhaoff@gmail.com>
" HomePage : https://github.com/zhaocai/zl.vim
" Version : 0.1
" Date Created : Sat 03 Sep 2011 03:54:00 PM EDT
" Last Modified : Tue 23 Oct 2012 04:59:06 PM EDT
" Tag : [ vim, syntax ]
" Copyright : © 2012 by Zhao Cai,
" Released under current GPL license.
" =============== ============================================================
" ============================================================================
" Status: ⟨⟨⟨1
" ============================================================================
call GoldenView#zl#rc#set_default({
\ 'g:GoldenView_zl_window__ignore_urule' : {
\ 'filetype' : [
\ '' ,
\ 'qf' , 'vimpager', 'undotree', 'tagbar',
\ 'nerdtree', 'vimshell', 'vimfiler', 'voom' ,
\ 'tabman' , 'unite' , 'quickrun', 'Decho' ,
\ ],
\ 'buftype' : [
\ 'nofile' ,
\ ],
\ 'bufname' : [
\ 'GoToFile' , 'diffpanel_\d\+' ,
\ '__Gundo_Preview__' , '__Gundo__' ,
\ '\[LustyExplorer-Buffers\]' , '\-MiniBufExplorer\-' ,
\ '_VOOM\d\+$' , '__Urannotate_\d\+__' ,
\ '__MRU_Files__' ,
\ ],
\ },
\ })
let s:GoldenView_zl_window__ignore_nrule = GoldenView#zl#rule#norm(
\ g:GoldenView_zl_window__ignore_urule, {
\ 'logic' : 'or',
\ }
\ )
function! GoldenView#zl#window#is_last_visible()
"--------- ------------------------------------------------
" Desc : check if no visible buffer left
"
" Args :
"
" Return :
" - 0 : false
" - 1 : true
" Raise :
"
"--------- ------------------------------------------------
for i in range(tabpagenr('$'))
let tabnr = i + 1
for bufnr in tabpagebuflist(tabnr)
let ft = getbufvar(bufnr, '&ft')
let buftype = getbufvar(bufnr, '&buftype')
if empty(ft) && empty(buftype)
continue
endif
if ! GoldenView#zl#rule#is_true(s:GoldenView_zl_window__ignore_nrule)
return 0
endif
endfor
endfor
return 1
endfunction
" ============================================================================
" Move: ⟨⟨⟨1
" ============================================================================
let s:golden_ratio = 1.618
function! GoldenView#zl#window#next_window_or_tab()
if tabpagenr('$') == 1 && winnr('$') == 1
call GoldenView#zl#window#split_nicely()
elseif winnr() < winnr("$")
wincmd w
else
tabnext
wincmd w
endif
endfunction
function! GoldenView#zl#window#previous_window_or_tab()
if winnr() > 1
wincmd W
else
tabprevious
execute winnr("$") . "wincmd w"
endif
endfunction
" ============================================================================
" Size: ⟨⟨⟨1
" ============================================================================
function! GoldenView#zl#window#golden_ratio_width()
return float2nr(&columns / s:golden_ratio)
endfunction
function! GoldenView#zl#window#golden_ratio_height()
return float2nr(&lines / s:golden_ratio)
endfunction
function! GoldenView#zl#window#textwidth()
return &tw == 0 ? 78 : &tw
endfunction
" ============================================================================
" Split: ⟨⟨⟨1
" ============================================================================
function! GoldenView#zl#window#nicely_split_cmd(...)
let opts = {
\ 'winnr' : 0 ,
\}
if a:0 >= 1 && type(a:1) == type({})
call extend(opts, a:1)
endif
let ww = winwidth(opts['winnr'])
let tw = &textwidth
if tw != 0 && ww > s:golden_ratio * tw
return 'vsplit'
endif
if ww > &columns / s:golden_ratio
return 'vsplit'
endif
return 'split'
endfunction
function! GoldenView#zl#window#split_nicely()
let split_cmd = GoldenView#zl#window#nicely_split_cmd()
try
exec split_cmd
catch /^Vim\%((\a\+)\)\=:E36/
if split_cmd == 'split'
let &winminheight = &winminheight / 2
else
let &winminwidth = &winminwidth / 2
endif
exec split_cmd
endtry
wincmd p
endfunction
function! GoldenView#zl#window#toggle_split()
let prev_name = winnr()
silent! wincmd w
if prev_name == winnr()
split
else
call GoldenView#zl#buf#quit()
endif
endfunction
" ============================================================================
" Sort: ⟨⟨⟨1
" ============================================================================
function! GoldenView#zl#window#sort_by(...)
"--------- ------------------------------------------------
" Desc : sort buffer by size, height, or width
"
" Args :
" - opts : > ↓
" {
" 'by' : size|height|width|winnr|bufnr ,
" 'tabnr' : tabpagenr() ,
" 'width_weight' : s:golden_ratio ,
" 'height_weight' : 1 ,
" }
"
" Return : sorted list of
" {
" 'bufnr' : bufnr ,
" 'winnr' : winnr ,
" 'width' : width ,
" 'height' : height ,
" 'size' : size ,
" }
"
" Raise :
"
"--------- ------------------------------------------------
let opts = {
\ 'by' : 'size' ,
\ 'tabnr' : tabpagenr() ,
\ 'width_weight' : s:golden_ratio ,
\ 'height_weight' : 1 ,
\}
if a:0 >= 1 && type(a:1) == type({})
call extend(opts, a:1)
endif
let list = []
for bufnr in tabpagebuflist(opts['tabnr'])
let winnr = bufwinnr(bufnr)
let width = winwidth(winnr)
let height = winheight(winnr)
let size = width * opts['width_weight']
\ + height * opts['height_weight']
call add(list, {
\ 'bufnr' : bufnr ,
\ 'winnr' : winnr ,
\ 'width' : width ,
\ 'height' : height ,
\ 'size' : size ,
\ })
endfor
return GoldenView#zl#list#sort_by(list,'v:val["'.opts['by'].'"]')
endfunction
" ============================================================================
" Switch: ⟨⟨⟨1
" ============================================================================
function! GoldenView#zl#window#switch_buffer_toggle(...)
"--------- ------------------------------------------------
" Desc : toggle buffer switch
"
" Args :
" - opts : >
" {
" 'with' : 'largest' ,
" }
"
" Return :
" Raise :
"
" Example : >
" nnoremap <silent> <C-@>
" \ :<C-u>call GoldenView#zl#window#switch_buffer_toggle()<CR>
"--------- ------------------------------------------------
let opts = {
\ 'with' : 'largest',
\}
if a:0 >= 1 && type(a:1) == type({})
call extend(opts, a:1)
endif
let bufnr = bufnr('%')
if exists('b:switch_buffer')
\ && bufwinnr(b:switch_buffer['bufnr']) == b:switch_buffer['winnr']
call GoldenView#zl#window#switch_buffer(bufnr, b:switch_buffer['bufnr'])
else
try
let fn = 'GoldenView#zl#window#switch_buffer_with_'.opts['with']
exec 'call ' . fn . '()'
catch /^Vim%((a+))=:E700/
throw "zl: function " . fn . 'for ' . opts['with']
\ . ' is not implemented!'
endtry
endif
endfunction
function! GoldenView#zl#window#switch_buffer_with_sorted_by_size_index(index, ...)
"--------- ------------------------------------------------
" Desc : switch buffer with the largest window
"
" Args :
" - opts : >
" {
" 'bufnr' : bufnr('%') ,
" 'by' : 'size'|'height'|'width' ,
" 'tabnr' : tabpagenr() ,
" 'width_weight' : s:golden_ratio ,
" 'height_weight' : 1 ,
" }
"
" Return :
" Raise :
"
" Example : >
" nnoremap <silent> <C-@>
" \ :<C-u>call GoldenView#zl#window#switch_buffer_with_largest()<CR>
"--------- ------------------------------------------------
let opts = {
\ 'bufnr' : bufnr('%') ,
\ 'by' : 'size' ,
\ 'tabnr' : tabpagenr() ,
\ 'width_weight' : s:golden_ratio ,
\ 'height_weight' : 1 ,
\}
if a:0 >= 1 && type(a:1) == type({})
call extend(opts, a:1)
endif
let sorted = GoldenView#zl#window#sort_by(filter(copy(opts),'v:key != "bufnr"'))
let bufnr_to = sorted[a:index]['bufnr']
call GoldenView#zl#window#switch_buffer(opts['bufnr'], bufnr_to)
endfunction
function! GoldenView#zl#window#switch_buffer_with_largest(...)
call GoldenView#zl#window#switch_buffer_with_sorted_by_size_index(-1, a:000)
endfunction
function! GoldenView#zl#window#switch_buffer_with_smallest(...)
call GoldenView#zl#window#switch_buffer_with_sorted_by_size_index(0, a:000)
endfunction
function! GoldenView#zl#window#switch_buffer(bufnr1, bufnr2)
"--------- ------------------------------------------------
" Desc : switch buffer window if both are visible
"
" Args : bufnr1 <-> bufnr2
" Return :
" - 0 : fail
" - 1 : success
" Raise :
"
" Example : >
"
" Refer :
"--------- ------------------------------------------------
let winnr1 = bufwinnr(a:bufnr1)
let winnr2 = bufwinnr(a:bufnr2)
if winnr1 != -1 && winnr2 != -1
silent noautocmd exec winnr1 'wincmd w'
if bufnr('%') != a:bufnr2
silent noautocmd exec 'buffer' a:bufnr2
let b:switch_buffer = {
\ 'bufnr' : a:bufnr1 ,
\ 'winnr' : winnr2 ,
\ }
endif
silent noautocmd exec winnr2 'wincmd w'
if bufnr('%') != a:bufnr1
silent noautocmd exec 'buffer' a:bufnr1
" need filetype detect (maybe) because bufnr1 disappears for a
" moment
silent filetype detect
let b:switch_buffer = {
\ 'bufnr' : a:bufnr2 ,
\ 'winnr' : winnr1 ,
\ }
endif
return 1
else
return 0
endif
endfunction
function! GoldenView#zl#window#alternate_buffer()
if bufnr('%') != bufnr('#') && buflisted(bufnr('#'))
buffer #
else
let cnt = 0
let pos = 1
let current = 0
while pos <= bufnr('$')
if buflisted(pos)
if pos == bufnr('%')
let current = cnt
endif
let cnt += 1
endif
let pos += 1
endwhile
if current > cnt / 2
bprevious
else
bnext
endif
endif
endfunction
" ============================================================================
" Scroll: ⟨⟨⟨1
" ============================================================================
function! GoldenView#zl#window#scroll_other_window(direction)
execute 'wincmd' (winnr('#') == 0 ? 'w' : 'p')
execute (a:direction ? "normal! \<C-d>" : "normal! \<C-u>")
wincmd p
endfunction
" ============================================================================
" View: ⟨⟨⟨1
" ============================================================================
function! GoldenView#zl#window#save_view_command(command) range
let view = winsaveview()
let range = ''
if a:firstline != a:lastline
let range = a:firstline.','.a:lastline
endif
try
keepjumps execute range.a:command
finally
call winrestview(view)
endtry
endfunction
" ============================================================================
" Modeline: ⟨⟨⟨1
" ============================================================================
" vim: set ft=vim ts=4 sw=4 tw=78 fdm=marker fmr=⟨⟨⟨,⟩⟩⟩ fdl=1 :