mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-01-24 06:10:05 +08:00
271 lines
6.8 KiB
VimL
271 lines
6.8 KiB
VimL
" Vars:
|
|
let s:vim_tab_options = {
|
|
\ '&tabline': '%!choosewin#tabline()',
|
|
\ '&guitablabel': '%{choosewin#get_tablabel(v:lnum)}',
|
|
\ }
|
|
|
|
" Util::
|
|
let s:_ = choosewin#util#get()
|
|
|
|
function! s:win_all() "{{{1
|
|
return range(1, winnr('$'))
|
|
endfunction
|
|
|
|
function! s:tab_all() "{{{1
|
|
return range(1, tabpagenr('$'))
|
|
endfunction
|
|
"}}}
|
|
|
|
" Wins:
|
|
let s:wins = {}
|
|
|
|
function! s:wins.get(...) "{{{1
|
|
let amt = get(a:000, 0)
|
|
let idx = empty(amt) ? -1 : amt - 1
|
|
return self._data[0 : idx]
|
|
endfunction
|
|
|
|
function! s:wins.set(wins) "{{{1
|
|
" Filter out non-existing window before store.
|
|
let self._data = filter(a:wins, 'index(s:win_all(), v:val) isnot -1')
|
|
return self
|
|
endfunction
|
|
"}}}
|
|
|
|
" Main:
|
|
let s:cw = {}
|
|
|
|
function! s:cw.start(wins, ...) "{{{1
|
|
call self.init(a:wins, get(a:000, 0, {}))
|
|
|
|
try
|
|
let status = []
|
|
" Some status bar plugin need to know if choosewin active or not.
|
|
let g:choosewin_active = 1
|
|
|
|
if empty(self.wins.get()) ||
|
|
\ ( len(self.wins.get()) is 1 && self.conf['return_on_single_win'] )
|
|
throw 'RETURN'
|
|
endif
|
|
if len(self.wins.get()) is 1 && self.conf['auto_choose']
|
|
call self.action.do_win(self.wins.get()[0])
|
|
endif
|
|
|
|
call self.setup()
|
|
call self.choose()
|
|
|
|
catch /\v^(CHOSE \d+)$/
|
|
if self.conf['noop']
|
|
let tab = tabpagenr()
|
|
let win = str2nr(matchstr(v:exception, '\v^CHOSE \zs\d+'))
|
|
if tab isnot self.src.tab
|
|
call self.action.do_tab(self.src.tab)
|
|
endif
|
|
let status = [ tab, win ]
|
|
else
|
|
let status = [ tabpagenr(), winnr() ]
|
|
endif
|
|
let self.previous = [ self.src.tab, self.src.win ]
|
|
catch /\v^SWAP$/
|
|
let status = [ tabpagenr(), winnr() ]
|
|
if self.conf['swap_stay']
|
|
let self.previous = status
|
|
call self.action._goto_tabwin(self.src.tab, self.src.win)
|
|
else
|
|
let self.previous = [ self.src.tab, self.src.win ]
|
|
endif
|
|
catch /\v^Vim:Interrupt$/
|
|
call self.label_clear()
|
|
call self.action.do_cancel()
|
|
catch /\v^(RETURN|CANCELED)$/
|
|
catch
|
|
let self.exception = v:exception
|
|
finally
|
|
call self.finish()
|
|
let g:choosewin_active = 0
|
|
return status
|
|
endtry
|
|
endfunction
|
|
|
|
function! s:cw.init(wins, conf) "{{{1
|
|
call choosewin#color#init()
|
|
let self.wins = s:wins.set(a:wins)
|
|
let self.conf = extend(choosewin#config#get(), a:conf)
|
|
let self.action = choosewin#action#init(self)
|
|
let self.exception = ''
|
|
let self.tab_options = {}
|
|
let self.statusline = {}
|
|
let self.src = {'win': winnr(), 'tab': tabpagenr()}
|
|
endfunction
|
|
|
|
function! s:cw.setup() "{{{1
|
|
let self.label2tab = s:_.dict_create(self.conf['tablabel'], s:tab_all())
|
|
|
|
if self.conf['overlay_enable']
|
|
let self.overlay = choosewin#overlay#get()
|
|
endif
|
|
|
|
if self.conf['tabline_replace']
|
|
let self.tab_options = s:_.buffer_options_set(bufnr(''), s:vim_tab_options)
|
|
endif
|
|
endfunction
|
|
|
|
function! s:cw.choose() "{{{1
|
|
while 1
|
|
call self.label_show()
|
|
let prompt = (self.conf['swap'] ? '[swap] ' : '') . 'choose > '
|
|
let char = s:_.read_char(prompt)
|
|
|
|
call self.label_clear()
|
|
|
|
" Tab label is chosen.
|
|
let num = s:_.get_ic(self.label2tab, char)
|
|
if !empty(num)
|
|
call self.action.do_tab(num)
|
|
continue
|
|
endif
|
|
|
|
" Win label is chosen.
|
|
let num = s:_.get_ic(self.label2win, char)
|
|
if !empty(num)
|
|
if self.conf['swap']
|
|
call self.action._swap(tabpagenr(), num)
|
|
else
|
|
call self.action.do_win(num)
|
|
endif
|
|
endif
|
|
|
|
let action_name = 'do_' . get(self.conf['keymap'], char, 'cancel')
|
|
if !s:_.is_Funcref(get(self.action, action_name))
|
|
throw 'UNKNOWN_ACTION'
|
|
endif
|
|
call self.action[action_name]()
|
|
endwhile
|
|
endfunction
|
|
|
|
function! s:cw.finish() "{{{1
|
|
if !empty(self.tab_options)
|
|
call s:_.buffer_options_set(bufnr(''), self.tab_options)
|
|
endif
|
|
echo ''
|
|
redraw
|
|
if self.conf['blink_on_land']
|
|
call s:_.blink(2, "ChooseWinLand", '\k*\%#\k*')
|
|
endif
|
|
if !empty(self.exception)
|
|
call s:_.message(self.exception)
|
|
endif
|
|
endfunction
|
|
|
|
function! s:cw.call_hook(hook_point, arg) "{{{1
|
|
let HOOK = get(self.conf['hook'], a:hook_point, 0)
|
|
if s:_.is_Funcref(HOOK)
|
|
return call(HOOK, [a:arg])
|
|
else
|
|
return a:arg
|
|
endif
|
|
endfunction
|
|
"}}}
|
|
|
|
" Label:
|
|
function! s:cw.label_show() "{{{1
|
|
if self.conf['hook_enable'] && index(self.conf['hook_bypass'], 'filter_window' ) is -1
|
|
let wins_new = self.call_hook('filter_window', copy(self.wins.get()))
|
|
call self.wins.set(wins_new)
|
|
endif
|
|
|
|
let wins = self.wins.get(len(self.conf['label']))
|
|
|
|
let self.label2win = s:_.dict_create(self.conf.label, wins)
|
|
let self.win2label = s:_.dict_create(wins, self.conf.label)
|
|
|
|
if self.conf['statusline_replace']
|
|
for n in wins
|
|
let self.statusline[n] = s:_.window_options_set(n,
|
|
\ { '&statusline': self.prepare_label(n) })
|
|
endfor
|
|
endif
|
|
|
|
if self.conf['overlay_enable']
|
|
call self.overlay.start(wins, self.conf)
|
|
endif
|
|
redraw
|
|
endfunction
|
|
|
|
function! s:cw.label_clear() "{{{1
|
|
if self.conf['statusline_replace']
|
|
for n in self.wins.get(len(self.conf['label']))
|
|
call s:_.window_options_set(n, self.statusline[n])
|
|
endfor
|
|
endif
|
|
|
|
if self.conf['overlay_enable']
|
|
call self.overlay.restore()
|
|
endif
|
|
endfunction
|
|
|
|
function! s:cw.prepare_label(win) "{{{1
|
|
let align = self.conf['label_align']
|
|
let pad = repeat(' ', self.conf['label_padding'])
|
|
let label = self.win2label[a:win]
|
|
let win_s = pad . label . pad
|
|
let color = "ChooseWinLabel" . (winnr() is a:win ? "Current" : "")
|
|
|
|
if align is 'left'
|
|
return printf('%%#%s# %s %%#%s# %%= ', color, win_s, "ChooseWinOther")
|
|
endif
|
|
|
|
if align is 'right'
|
|
return printf('%%#%s# %%= %%#%s# %s ', "ChooseWinOther", color, win_s)
|
|
endif
|
|
|
|
if align is 'center'
|
|
let padding = repeat(' ', winwidth(a:win)/2-len(win_s))
|
|
return printf('%%#%s# %s %%#%s# %s %%#%s# %%= ',
|
|
\ "ChooseWinOther", padding, color, win_s, "ChooseWinOther")
|
|
endif
|
|
endfunction
|
|
"}}}
|
|
|
|
" Tabline:
|
|
function! s:cw.tabline() "{{{1
|
|
let R = ''
|
|
let pad = repeat(' ', self.conf['label_padding'])
|
|
let sepalator = printf('%%#%s# ', "ChooseWinOther")
|
|
let tab_all = s:tab_all()
|
|
for tabnum in tab_all
|
|
let color = "ChooseWinLabel" . (tabpagenr() is tabnum ? "Current" : "")
|
|
let R .= printf('%%#%s# %s ', color, pad . self.get_tablabel(tabnum) . pad)
|
|
let R .= tabnum isnot tab_all[-1] ? sepalator : ''
|
|
endfor
|
|
let R .= printf('%%#%s#', "ChooseWinOther")
|
|
return R
|
|
endfunction
|
|
|
|
function! s:cw.get_tablabel(num) "{{{1
|
|
return len(self.conf['tablabel']) > a:num
|
|
\ ? self.conf['tablabel'][a:num-1]
|
|
\ : '..'
|
|
endfunction
|
|
"}}}
|
|
|
|
" API:
|
|
function! choosewin#start(...) "{{{1
|
|
return call(s:cw.start, a:000, s:cw)
|
|
endfunction
|
|
|
|
function! choosewin#tabline() "{{{1
|
|
return s:cw.tabline()
|
|
endfunction
|
|
|
|
function! choosewin#get_tablabel(num) "{{{1
|
|
return s:cw.get_tablabel(a:num)
|
|
endfunction
|
|
|
|
function! choosewin#noop() "{{{1
|
|
return s:cw.conf['noop']
|
|
endfunction
|
|
"}}}
|
|
|
|
" vim: foldmethod=marker
|