diff --git a/autoload/vundle/config.vim b/autoload/vundle/config.vim index e8443c1..5023385 100644 --- a/autoload/vundle/config.vim +++ b/autoload/vundle/config.vim @@ -1,29 +1,46 @@ -func! vundle#config#bundle(arg, ...) - let bundle = vundle#config#init_bundle(a:arg, a:000) - call s:rtp_rm_a() - call add(g:bundles, bundle) - call s:rtp_add_a() +func! vundle#config#bundle(spec, ...) + let bundle = vundle#config#init_bundle(a:spec, a:000) + " All bundles are removed from rtp and re-added in inverse order so that + " they appear in rtp in the same order as they appear in vimrc + call g:bundles.rm_from_rtp() + call g:bundles.add(bundle) + call g:bundles.add_to_rtp() endf +" Clear all bundles from rtp, create the bundles holder +" func! vundle#config#init() - if !exists('g:bundles') | let g:bundles = [] | endif - call s:rtp_rm_a() - let g:bundles = [] + if exists('g:bundles') + call g:bundles.rm_from_rtp() + endif + let g:bundles = s:bundles.new() endf + +" Add each bundle to rtp and run their plugins, similarly to what vim does at +" startup. +" func! vundle#config#require(bundles) abort - for b in a:bundles - call s:rtp_add(b.rtpath()) + for bundle in a:bundles + call s:rtp_add(bundle.rtpath()) call s:rtp_add(g:bundle_dir) " TODO: it has to be relative rtpath, not bundle.name - exec 'runtime! '.b.name.'/plugin/*.vim' - exec 'runtime! '.b.name.'/after/*.vim' + exec 'runtime! ' . bundle.name . '/plugin/*.vim' + exec 'runtime! ' . bundle.name . '/after/*.vim' call s:rtp_rm(g:bundle_dir) endfor endf -func! vundle#config#init_bundle(name, opts) - let opts = extend(s:parse_options(a:opts), s:parse_name(substitute(a:name,"['".'"]\+','','g'))) + +" Create a bundle object based on a given spec and options +func! vundle#config#init_bundle(spec, opts) + let spec = substitute(a:spec,"['".'"]\+','','g') + + " Combine info derived from the spec with the options from the Bundle + " command. + let opts = extend(s:parse_options(a:opts), s:parse_spec(spec)) + + " Include generic bundle methods return extend(opts, copy(s:bundle)) endf @@ -38,35 +55,28 @@ func! s:parse_options(opts) endif endf -func! s:parse_name(arg) - let arg = a:arg +func! s:parse_spec(spec) + let spec = a:spec - if arg =~? '^\s*\(gh\|github\):\S\+' - \ || arg =~? '^[a-z0-9][a-z0-9-]*/[^/]\+$' - let uri = 'https://github.com/'.split(arg, ':')[-1] + if spec =~? '^\s*\(gh\|github\):\S\+' + \ || spec =~? '^[a-z0-9][a-z0-9-]*/[^/]\+$' + let uri = 'https://github.com/'.split(spec, ':')[-1] if uri !~? '\.git$' let uri .= '.git' endif let name = substitute(split(uri,'\/')[-1], '\.git\s*$','','i') - elseif arg =~? '^\s*\(git@\|git://\)\S\+' - \ || arg =~? '\(file\|https\?\)://' - \ || arg =~? '\.git\s*$' - let uri = arg + elseif spec =~? '^\s*\(git@\|git://\)\S\+' + \ || spec =~? '\(file\|https\?\)://' + \ || spec =~? '\.git\s*$' + let uri = spec let name = split( substitute(uri,'/\?\.git\s*$','','i') ,'\/')[-1] else - let name = arg + let name = spec let uri = 'https://github.com/vim-scripts/'.name.'.git' endif - return {'name': name, 'uri': uri, 'name_spec': arg } + return {'name': name, 'uri': uri, 'spec': spec } endf -func! s:rtp_rm_a() - call filter(copy(g:bundles), 's:rtp_rm(v:val.rtpath())') -endf - -func! s:rtp_add_a() - call filter(reverse(copy(g:bundles)), 's:rtp_add(v:val.rtpath())') -endf func! s:rtp_rm(dir) abort exec 'set rtp-='.fnameescape(expand(a:dir)) @@ -82,6 +92,9 @@ func! s:expand_path(path) abort return simplify(expand(a:path)) endf + +" Bundle object +" --------------------------------------------------------------------------- let s:bundle = {} func! s:bundle.path() @@ -91,3 +104,54 @@ endf func! s:bundle.rtpath() return has_key(self, 'rtp') ? s:expand_path(self.path().'/'.self.rtp) : self.path() endf + +func! s:bundle.command() + return printf("Bundle '%s'", self.spec) +endf + +" --------------------------------------------------------------------------- + + +" Bundle collection object +" --------------------------------------------------------------------------- +" +let s:bundles = { 'list' : [], 'dict' : {} } + +function! s:bundles.add(bundle) + call add(self.list, a:bundle.spec ) + let self.dict[ a:bundle.spec ] = a:bundle +endf + +func! s:bundles.new() + return deepcopy(self) +endf + +func! s:bundles.keys() + return copy(self.list) +endf + +func! s:bundles.has_bundle(spec) + return has_key(self.dict, a:spec) +endf + +func! s:bundles.get(bundle_spec) + return get(self.dict, a:bundle_spec) +endf + +func! s:bundles.rm_from_rtp() + call map(copy(self.list), 's:rtp_rm(self.dict[v:val].rtpath())') +endf + +func! s:bundles.add_to_rtp() + call map(reverse(copy(self.list)), 's:rtp_add(self.dict[v:val].rtpath())') +endf + +func! s:bundles.get_sorted_list() + return map(copy(self.list), 'self.dict[v:val]') +endf + +func! s:bundles.size() + return len(self.list) +endf + +" --------------------------------------------------------------------------- diff --git a/autoload/vundle/installer.vim b/autoload/vundle/installer.vim index 5fb371e..ab0144a 100644 --- a/autoload/vundle/installer.vim +++ b/autoload/vundle/installer.vim @@ -1,9 +1,9 @@ func! vundle#installer#new(bang, ...) abort let bundles = (a:1 == '') ? - \ g:bundles : + \ g:bundles.get_sorted_list() : \ map(copy(a:000), 'vundle#config#init_bundle(v:val, {})') - let names = vundle#scripts#bundle_names(map(copy(bundles), 'v:val.name_spec')) + let names = vundle#scripts#bundle_names(map(copy(bundles), 'v:val.spec')) call vundle#scripts#view('Installer',['" Installing bundles to '.expand(g:bundle_dir)], names + ['Helptags']) call s:process(a:bang, (a:bang ? 'add!' : 'add')) @@ -53,7 +53,7 @@ func! vundle#installer#run(func_name, name, ...) abort redraw - if 'updated' == status + if 'updated' == status echo n.' installed' elseif 'todate' == status echo n.' already installed' @@ -73,7 +73,7 @@ func! vundle#installer#run(func_name, name, ...) abort return status endf -func! s:sign(status) +func! s:sign(status) if (!has('signs')) return endif @@ -88,10 +88,12 @@ func! vundle#installer#install_and_require(bang, name) abort return result endf -func! vundle#installer#install(bang, name) abort +func! vundle#installer#install(bang, spec) abort if !isdirectory(g:bundle_dir) | call mkdir(g:bundle_dir, 'p') | endif - let b = vundle#config#init_bundle(a:name, {}) + let spec = substitute(a:spec,"['".'"]\+','','g') + + let b = g:bundles.has_bundle(spec) ? g:bundles.get(spec) : vundle#config#init_bundle(a:spec, {}) return s:sync(a:bang, b) endf @@ -102,7 +104,7 @@ func! vundle#installer#docs() abort endf func! vundle#installer#helptags(bundles) abort - let bundle_dirs = map(copy(a:bundles),'v:val.rtpath()') + let bundle_dirs = map(a:bundles.get_sorted_list(),'v:val.rtpath()') let help_dirs = filter(bundle_dirs, 's:has_doc(v:val)') call s:log('') @@ -116,15 +118,15 @@ func! vundle#installer#helptags(bundles) abort endf func! vundle#installer#list(bang) abort - let bundles = vundle#scripts#bundle_names(map(copy(g:bundles), 'v:val.name_spec')) + let bundles = vundle#scripts#bundle_names(map(g:bundles.get_sorted_list(), 'v:val.spec')) call vundle#scripts#view('list', ['" My Bundles'], bundles) redraw - echo len(g:bundles).' bundles configured' + echo g:bundles.size().' bundles configured' endf func! vundle#installer#clean(bang) abort - let bundle_dirs = map(copy(g:bundles), 'v:val.path()') + let bundle_dirs = map(copy(g:bundles.get_sorted_list()), 'v:val.path()') let all_dirs = split(globpath(g:bundle_dir, '*'), "\n") let x_dirs = filter(all_dirs, '0 > index(bundle_dirs, v:val)') @@ -207,7 +209,7 @@ func! s:sync(bang, bundle) abort let out = s:system(cmd) call s:log('') - call s:log('Bundle '.a:bundle.name_spec) + call s:log('Bundle '.a:bundle.spec) call s:log('$ '.cmd) call s:log('> '.out)