mirror of
https://github.com/SpaceVim/SpaceVim.git
synced 2025-02-03 22:40:05 +08:00
208 lines
5.0 KiB
VimL
208 lines
5.0 KiB
VimL
" ___vital___
|
|
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
|
|
" Do not modify the code nor insert new lines before '" ___vital___'
|
|
function! s:_SID() abort
|
|
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
|
|
endfunction
|
|
execute join(['function! vital#_gina#Vim#BufferManager#import() abort', printf("return map({'_vital_depends': '', 'new': '', '_vital_loaded': ''}, \"vital#_gina#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
|
|
delfunction s:_SID
|
|
" ___vital___
|
|
let s:save_cpo = &cpo
|
|
set cpo&vim
|
|
|
|
function! s:_vital_depends() abort
|
|
return ['Prelude', 'Vim.Buffer']
|
|
endfunction
|
|
|
|
function! s:_vital_loaded(V) abort
|
|
let s:V = a:V
|
|
let s:P = s:V.import('Prelude')
|
|
let s:B = s:V.import('Vim.Buffer')
|
|
endfunction
|
|
|
|
let s:default_config = {
|
|
\ 'range': 'tabpage',
|
|
\ 'opener': 'split',
|
|
\ 'mods': '',
|
|
\ 'cmdarg': '',
|
|
\ }
|
|
let s:Manager = {
|
|
\ '_config': s:default_config,
|
|
\ '_user_config': {},
|
|
\ '_bufnrs': {},
|
|
\ }
|
|
|
|
function! s:Manager.open(bufname, ...) abort
|
|
if s:B.is_cmdwin()
|
|
" Note: Failed to open buffer in cmdline window.
|
|
return {
|
|
\ 'loaded': 0,
|
|
\ 'newwin': -1,
|
|
\ 'newbuf': 0,
|
|
\ 'bufnr': -1,
|
|
\ 'bufname': a:bufname,
|
|
\ }
|
|
endif
|
|
|
|
let lastbuf = bufnr('$')
|
|
let config = s:_make_config(self, a:000)
|
|
let moved = self.move(config.range)
|
|
|
|
let Opener = moved ? 'edit' : config.opener
|
|
while s:P.is_string(Opener) && Opener[0] ==# '='
|
|
let Opener = eval(Opener[1 :])
|
|
endwhile
|
|
|
|
let loaded = s:B.open(a:bufname, {
|
|
\ 'opener': Opener,
|
|
\ 'mods': config.mods,
|
|
\ 'cmdarg': config.cmdarg,
|
|
\})
|
|
let new_bufnr = bufnr('%')
|
|
let self._bufnrs[new_bufnr] = a:bufname
|
|
|
|
let info = {
|
|
\ 'loaded': loaded,
|
|
\ 'newwin': !moved,
|
|
\ 'newbuf': lastbuf < bufnr('%'),
|
|
\ 'bufnr': new_bufnr,
|
|
\ 'bufname': a:bufname,
|
|
\ }
|
|
call self.opened(info)
|
|
return info
|
|
endfunction
|
|
|
|
function! s:Manager.close(...) abort
|
|
if call(self.move, a:000, self)
|
|
if winnr('$') != 1
|
|
close
|
|
elseif tabpagenr('$') != 1
|
|
tabclose
|
|
else
|
|
enew
|
|
endif
|
|
endif
|
|
endfunction
|
|
|
|
function! s:Manager.opened(bufname) abort
|
|
" This is placeholder function.
|
|
endfunction
|
|
|
|
function! s:Manager.config(...) abort
|
|
if a:0 == 0
|
|
return self._config
|
|
elseif a:0 == 1 && s:P.is_dict(a:1)
|
|
call extend(self._config, a:1)
|
|
return self
|
|
elseif a:0 == 1
|
|
return get(self._config, a:1)
|
|
elseif a:0 == 2
|
|
let self._config[a:1] = a:2
|
|
return self
|
|
endif
|
|
throw 'vital: Vim.BufferManager: invalid argument for config()'
|
|
endfunction
|
|
|
|
function! s:Manager.user_config(config) abort
|
|
let self._user_config = a:config
|
|
return self
|
|
endfunction
|
|
|
|
function! s:Manager.is_managed(bufnr) abort
|
|
return has_key(self._bufnrs, a:bufnr)
|
|
endfunction
|
|
|
|
function! s:Manager.add(bufnr, ...) abort
|
|
let bufname = a:0 ? a:1 : bufname(a:bufnr)
|
|
let self._bufnrs[a:bufnr] = bufname
|
|
endfunction
|
|
|
|
function! s:Manager.list() abort
|
|
return sort(map(keys(self._bufnrs), 'v:val - 0'))
|
|
endfunction
|
|
|
|
function! s:Manager.nearest(...) abort
|
|
let range = s:_make_config(self, map(copy(a:000), '{''range'': v:val}')).range
|
|
|
|
if range ==# 'tabpage'
|
|
let tabpages = [tabpagenr()]
|
|
else
|
|
let s:base = tabpagenr()
|
|
let tabpages = sort(range(1, tabpagenr('$')), 's:_distance')
|
|
endif
|
|
|
|
for tabnr in tabpages
|
|
let s:base = tabpagewinnr(tabnr)
|
|
let buflist = tabpagebuflist(tabnr)
|
|
for winnr in sort(range(1, len(buflist)), 's:_distance')
|
|
if self.is_managed(buflist[winnr - 1])
|
|
return [tabnr, winnr, buflist[winnr - 1]]
|
|
endif
|
|
endfor
|
|
endfor
|
|
return []
|
|
endfunction
|
|
|
|
function! s:Manager.move(...) abort
|
|
let range = s:_make_config(self, map(copy(a:000), '{''range'': v:val}')).range
|
|
if range !=# 'all' && range !=# 'tabpage'
|
|
return self.is_managed(bufnr('%'))
|
|
endif
|
|
let near = self.nearest(range)
|
|
if empty(near)
|
|
return 0
|
|
endif
|
|
silent execute 'tabnext' near[0]
|
|
silent execute near[1] 'wincmd w'
|
|
return 1
|
|
endfunction
|
|
|
|
function! s:Manager.do(cmd) abort
|
|
let cmd =
|
|
\ a:cmd =~# '%s' ? a:cmd
|
|
\ : a:cmd . ' %s'
|
|
for bufnr in self.list()
|
|
execute substitute(cmd, '%s', bufnr, '')
|
|
endfor
|
|
endfunction
|
|
|
|
function! s:new(...) abort
|
|
return deepcopy(s:Manager)
|
|
\.config(a:0 ? s:_config(a:1) : {})
|
|
\.user_config(2 <= a:0 ? a:2 : {})
|
|
endfunction
|
|
|
|
function! s:_make_config(manager, configs) abort
|
|
let configs = [a:manager._config]
|
|
let user = a:manager._user_config
|
|
if s:P.is_string(user)
|
|
let configs += [exists(user) ? {user} : {}]
|
|
elseif s:P.is_dict(user)
|
|
let configs += [map(copy(user), 'exists(v:val) ? {v:val} : {}')]
|
|
endif
|
|
|
|
let config = {}
|
|
for c in configs + a:configs
|
|
call extend(config, s:_config(c))
|
|
endfor
|
|
return config
|
|
endfunction
|
|
|
|
function! s:_config(c) abort
|
|
if s:P.is_dict(a:c)
|
|
return a:c
|
|
elseif s:P.is_string(a:c) || s:P.is_funcref(a:c)
|
|
return {'opener': a:c}
|
|
endif
|
|
return {}
|
|
endfunction
|
|
|
|
function! s:_distance(a, b) abort
|
|
return abs(a:a - s:base) - abs(a:b - s:base)
|
|
endfunction
|
|
|
|
let &cpo = s:save_cpo
|
|
unlet s:save_cpo
|
|
|
|
" vim:set et ts=2 sts=2 sw=2 tw=0:
|