" ___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(''), '\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('%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: