1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-02-03 17:00:05 +08:00
SpaceVim/bundle/gina.vim/autoload/vital/_gina/Vim/BufferManager.vim

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: