Browse Source

Merge 0f936ef295 into 6545681f56

pull/425/merge
Jacobo de Vera 12 years ago
parent
commit
a8aa4d8638
6 changed files with 537 additions and 27 deletions
  1. +25
    -13
      autoload/vundle.vim
  2. +173
    -3
      autoload/vundle/config.vim
  3. +245
    -10
      autoload/vundle/installer.vim
  4. +66
    -0
      autoload/vundle/scripts.vim
  5. +21
    -1
      doc/vundle.txt
  6. +7
    -0
      test/vimrc

+ 25
- 13
autoload/vundle.vim View File

@ -14,9 +14,6 @@ com! -nargs=? -bang -complete=custom,vundle#scripts#complete PluginInstall
com! -nargs=? -bang -complete=custom,vundle#scripts#complete PluginSearch com! -nargs=? -bang -complete=custom,vundle#scripts#complete PluginSearch
\ call vundle#scripts#all('!' == '<bang>', <q-args>) \ call vundle#scripts#all('!' == '<bang>', <q-args>)
com! -nargs=? -bang -complete=custom,vundle#scripts#complete Plugins
\ call vundle#scripts#all('!' == '<bang>', <q-args>)
com! -nargs=0 -bang PluginList com! -nargs=0 -bang PluginList
\ call vundle#installer#list('!' == '<bang>') \ call vundle#installer#list('!' == '<bang>')
@ -36,27 +33,32 @@ com! -nargs=? -bang VundleClean Plugi
com! -nargs=0 VundleDocs PluginDocs com! -nargs=0 VundleDocs PluginDocs
com! VundleUpdate PluginInstall! com! VundleUpdate PluginInstall!
" deprecated
" Deprecated Commands
com! -nargs=+ Bundle call vundle#config#bundle(<args>) com! -nargs=+ Bundle call vundle#config#bundle(<args>)
com! -nargs=? -bang -complete=custom,vundle#scripts#complete BundleInstall PluginInstall<bang> <args> com! -nargs=? -bang -complete=custom,vundle#scripts#complete BundleInstall PluginInstall<bang> <args>
com! -nargs=? -bang -complete=custom,vundle#scripts#complete BundleSearch PluginSearch<bang> <args> com! -nargs=? -bang -complete=custom,vundle#scripts#complete BundleSearch PluginSearch<bang> <args>
com! -nargs=? -bang -complete=custom,vundle#scripts#complete Bundles Plugins<bang> <args>
com! -nargs=0 -bang BundleList PluginList<bang> com! -nargs=0 -bang BundleList PluginList<bang>
com! -nargs=? -bang BundleClean PluginClean<bang> com! -nargs=? -bang BundleClean PluginClean<bang>
com! -nargs=0 BundleDocs PluginDocs com! -nargs=0 BundleDocs PluginDocs
com! BundleUpdate PluginInstall! com! BundleUpdate PluginInstall!
" Set up the signs used in the installer window. (See :help signs)
if (has('signs')) if (has('signs'))
sign define Vu_error text=! texthl=Error
sign define Vu_active text=> texthl=Comment
sign define Vu_todate text=. texthl=Comment
sign define Vu_new text=+ texthl=Comment
sign define Vu_updated text=* texthl=Comment
sign define Vu_deleted text=- texthl=Comment
sign define Vu_helptags text=* texthl=Comment
sign define Vu_error text=! texthl=Error
sign define Vu_active text=> texthl=Comment
sign define Vu_todate text=. texthl=Comment
sign define Vu_new text=+ texthl=Comment
sign define Vu_updated text=* texthl=Comment
sign define Vu_deleted text=- texthl=Comment
sign define Vu_helptags text=* texthl=Comment
sign define Vu_pinned text== texthl=Comment
endif endif
" Set up Vundle. This function has to be called from the users vimrc file.
" This will force Vim to source this file as a side effect which wil define
" the :Plugin command. After calling this function the user can use the
" :Plugin command in the vimrc. It is not possible to do this automatically
" because when loading the vimrc file no plugins where loaded yet.
func! vundle#rc(...) abort func! vundle#rc(...) abort
let g:bundle_dir = len(a:000) > 0 ? expand(a:1, 1) : expand('$HOME/.vim/bundle', 1) let g:bundle_dir = len(a:000) > 0 ? expand(a:1, 1) : expand('$HOME/.vim/bundle', 1)
let g:updated_bundles = [] let g:updated_bundles = []
@ -64,3 +66,13 @@ func! vundle#rc(...) abort
let g:vundle_changelog = ['Updated Plugins:'] let g:vundle_changelog = ['Updated Plugins:']
call vundle#config#init() call vundle#config#init()
endf endf
func! vundle#begin(...) abort
let g:vundle_lazy_load = 1
call call('vundle#rc', a:000)
endf
func! vundle#end(...) abort
unlet g:vundle_lazy_load
call vundle#config#activate_bundles()
endf

+ 173
- 3
autoload/vundle/config.vim View File

@ -1,17 +1,57 @@
" ---------------------------------------------------------------------------
" Add a plugin to the runtimepath.
"
" arg -- a string specifying the plugin
" ... -- a dictionary of options for the plugin
" return -- the return value from vundle#config#init_bundle()
" ---------------------------------------------------------------------------
func! vundle#config#bundle(arg, ...) func! vundle#config#bundle(arg, ...)
let bundle = vundle#config#init_bundle(a:arg, a:000) 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()
if !s:check_bundle_name(bundle)
return
endif
if exists('g:vundle_lazy_load') && g:vundle_lazy_load
call add(g:bundles, bundle)
else
call s:rtp_rm_a()
call add(g:bundles, bundle)
call s:rtp_add_a()
call s:rtp_add_defaults()
endif
return bundle return bundle
endf endf
" ---------------------------------------------------------------------------
" When lazy bundle load is used (begin/end functions), add all configured
" bundles to runtimepath and reorder appropriately.
" ---------------------------------------------------------------------------
func! vundle#config#activate_bundles()
call s:rtp_add_a()
call s:rtp_add_defaults()
endf
" ---------------------------------------------------------------------------
" Initialize Vundle.
"
" Start a new bundles list and make sure the runtimepath does not contain
" directories from a previous call. In theory, this should only be called
" once.
" ---------------------------------------------------------------------------
func! vundle#config#init() func! vundle#config#init()
if !exists('g:bundles') | let g:bundles = [] | endif if !exists('g:bundles') | let g:bundles = [] | endif
call s:rtp_rm_a() call s:rtp_rm_a()
let g:bundles = [] let g:bundles = []
let g:bundle_names = {}
endf endf
" ---------------------------------------------------------------------------
" Add a list of bundles to the runtimepath and source them.
"
" bundles -- a list of bundle objects
" ---------------------------------------------------------------------------
func! vundle#config#require(bundles) abort func! vundle#config#require(bundles) abort
for b in a:bundles for b in a:bundles
call s:rtp_add(b.rtpath) call s:rtp_add(b.rtpath)
@ -21,8 +61,17 @@ func! vundle#config#require(bundles) abort
exec 'runtime! '.b.name.'/after/*.vim' exec 'runtime! '.b.name.'/after/*.vim'
call s:rtp_rm(g:bundle_dir) call s:rtp_rm(g:bundle_dir)
endfor endfor
call s:rtp_add_defaults()
endf endf
" ---------------------------------------------------------------------------
" Create a bundle object from a bundle specification.
"
" name -- the bundle specification as a string
" opts -- the options dictionary from then bundle definition
" return -- an initialized bundle object
" ---------------------------------------------------------------------------
func! vundle#config#init_bundle(name, opts) func! vundle#config#init_bundle(name, opts)
if a:name != substitute(a:name, '^\s*\(.\{-}\)\s*$', '\1', '') if a:name != substitute(a:name, '^\s*\(.\{-}\)\s*$', '\1', '')
echo "Spurious leading and/or trailing whitespace found in plugin spec '" . a:name . "'" echo "Spurious leading and/or trailing whitespace found in plugin spec '" . a:name . "'"
@ -33,6 +82,35 @@ func! vundle#config#init_bundle(name, opts)
return b return b
endf endf
" ---------------------------------------------------------------------------
" Check if the current bundle name has already been used in this running
" instance and show an error to that effect.
"
" bundle -- a bundle object whose name is to be checked
" return -- 0 if the bundle's name has been seen before, 1 otherwise
" ---------------------------------------------------------------------------
funct! s:check_bundle_name(bundle)
if has_key(g:bundle_names, a:bundle.name)
echoerr 'Vundle error: Name collision for Plugin ' . a:bundle.name_spec .
\ '. Plugin ' . g:bundle_names[a:bundle.name] .
\ ' previously used the name "' . a:bundle.name . '"' .
\ '. Skipping Plugin ' . a:bundle.name_spec . '.'
return 0
endif
let g:bundle_names[a:bundle.name] = a:bundle.name_spec
return 1
endf
" ---------------------------------------------------------------------------
" Parse the options which can be supplied with the bundle specification.
" Corresponding documentation: vundle-plugins-configure
"
" opts -- a dictionary with the user supplied options for the bundle
" return -- a dictionary with the user supplied options for the bundle, this
" will be merged with a s:bundle object into one dictionary.
" ---------------------------------------------------------------------------
func! s:parse_options(opts) func! s:parse_options(opts)
" TODO: improve this " TODO: improve this
if len(a:opts) != 1 | return {} | endif if len(a:opts) != 1 | return {} | endif
@ -44,6 +122,16 @@ func! s:parse_options(opts)
endif endif
endf endf
" ---------------------------------------------------------------------------
" Parse the plugin specification. Corresponding documentation:
" vundle-plugins-uris
"
" arg -- the string supplied to identify the plugin
" return -- a dictionary with the folder name (key 'name') and the uri (key
" 'uri') for cloning the plugin and the original argument (key
" 'name_spec')
" ---------------------------------------------------------------------------
func! s:parse_name(arg) func! s:parse_name(arg)
let arg = a:arg let arg = a:arg
let git_proto = exists('g:vundle_default_git_proto') ? g:vundle_default_git_proto : 'https' let git_proto = exists('g:vundle_default_git_proto') ? g:vundle_default_git_proto : 'https'
@ -67,6 +155,32 @@ func! s:parse_name(arg)
return {'name': name, 'uri': uri, 'name_spec': arg } return {'name': name, 'uri': uri, 'name_spec': arg }
endf endf
" ---------------------------------------------------------------------------
" Modify the runtimepath, after all bundles have been added, so that the
" directories that were in the default runtimepath appear first in the list
" (with their 'after' directories last).
" ---------------------------------------------------------------------------
func! s:rtp_add_defaults()
let current = &rtp
set rtp&vim
let default = &rtp
let &rtp = current
for item in reverse(split(default, ','))
exec 'set rtp-=' . item
if fnamemodify(item, ":t") == 'after'
exec 'set rtp+=' . item
else
exec 'set rtp^=' . item
endif
endfor
endf
" ---------------------------------------------------------------------------
" Remove all paths for the plugins which are managed by Vundle from the
" runtimepath.
" ---------------------------------------------------------------------------
func! s:rtp_rm_a() func! s:rtp_rm_a()
let paths = map(copy(g:bundles), 'v:val.rtpath') let paths = map(copy(g:bundles), 'v:val.rtpath')
let prepends = join(paths, ',') let prepends = join(paths, ',')
@ -75,6 +189,11 @@ func! s:rtp_rm_a()
exec 'set rtp-='.fnameescape(appends) exec 'set rtp-='.fnameescape(appends)
endf endf
" ---------------------------------------------------------------------------
" Add all paths for the plugins which are managed by Vundle to the
" runtimepath.
" ---------------------------------------------------------------------------
func! s:rtp_add_a() func! s:rtp_add_a()
let paths = map(copy(g:bundles), 'v:val.rtpath') let paths = map(copy(g:bundles), 'v:val.rtpath')
let prepends = join(paths, ',') let prepends = join(paths, ',')
@ -83,27 +202,78 @@ func! s:rtp_add_a()
exec 'set rtp+='.fnameescape(appends) exec 'set rtp+='.fnameescape(appends)
endf endf
" ---------------------------------------------------------------------------
" Remove a directory and the corresponding 'after' directory from runtimepath.
"
" dir -- the directory name to be removed as a string. The corresponding
" 'after' directory will also be removed.
" ---------------------------------------------------------------------------
func! s:rtp_rm(dir) abort func! s:rtp_rm(dir) abort
exec 'set rtp-='.fnameescape(expand(a:dir, 1)) exec 'set rtp-='.fnameescape(expand(a:dir, 1))
exec 'set rtp-='.fnameescape(expand(a:dir.'/after', 1)) exec 'set rtp-='.fnameescape(expand(a:dir.'/after', 1))
endf endf
" ---------------------------------------------------------------------------
" Add a directory and the corresponding 'after' directory to runtimepath.
"
" dir -- the directory name to be added as a string. The corresponding
" 'after' directory will also be added.
" ---------------------------------------------------------------------------
func! s:rtp_add(dir) abort func! s:rtp_add(dir) abort
exec 'set rtp^='.fnameescape(expand(a:dir, 1)) exec 'set rtp^='.fnameescape(expand(a:dir, 1))
exec 'set rtp+='.fnameescape(expand(a:dir.'/after', 1)) exec 'set rtp+='.fnameescape(expand(a:dir.'/after', 1))
endf endf
" ---------------------------------------------------------------------------
" Expand and simplify a path.
"
" path -- the path to expand as a string
" return -- the expanded and simplified path
" ---------------------------------------------------------------------------
func! s:expand_path(path) abort func! s:expand_path(path) abort
return simplify(expand(a:path, 1)) return simplify(expand(a:path, 1))
endf endf
" ---------------------------------------------------------------------------
" Find the actual path inside a bundle directory to be added to the
" runtimepath. It might be provided by the user with the 'rtp' option.
" Corresponding documentation: vundle-plugins-configure
"
" opts -- a bundle dict
" return -- expanded path to the corresponding plugin directory
" ---------------------------------------------------------------------------
func! s:rtpath(opts) func! s:rtpath(opts)
return has_key(a:opts, 'rtp') ? s:expand_path(a:opts.path().'/'.a:opts.rtp) : a:opts.path() return has_key(a:opts, 'rtp') ? s:expand_path(a:opts.path().'/'.a:opts.rtp) : a:opts.path()
endf endf
" ---------------------------------------------------------------------------
" a bundle 'object'
" ---------------------------------------------------------------------------
let s:bundle = {} let s:bundle = {}
" ---------------------------------------------------------------------------
" Return the absolute path to the directory inside the bundle directory
" (prefix) where thr bundle will be cloned.
"
" return -- the target location to clone this bundle to
" ---------------------------------------------------------------------------
func! s:bundle.path() func! s:bundle.path()
return s:expand_path(g:bundle_dir.'/'.self.name) return s:expand_path(g:bundle_dir.'/'.self.name)
endf endf
" ---------------------------------------------------------------------------
" Determine if the bundle has the pinned attribute set in the config
"
" return -- 1 if the bundle is pinned, 0 otherwise
" ---------------------------------------------------------------------------
func! s:bundle.is_pinned()
return get(self, 'pinned')
endf

+ 245
- 10
autoload/vundle/installer.vim View File

@ -1,3 +1,10 @@
" ---------------------------------------------------------------------------
" Try to clone all new bundles given (or all bundles in g:bundles by default)
" to g:bundle_dir. If a:bang is 1 it will also update all plugins (git pull).
"
" bang -- 1 or 0
" ... -- any number of bundle specifications (separate arguments)
" ---------------------------------------------------------------------------
func! vundle#installer#new(bang, ...) abort func! vundle#installer#new(bang, ...) abort
let bundles = (a:1 == '') ? let bundles = (a:1 == '') ?
\ g:bundles : \ g:bundles :
@ -6,12 +13,23 @@ func! vundle#installer#new(bang, ...) abort
let names = vundle#scripts#bundle_names(map(copy(bundles), 'v:val.name_spec')) let names = vundle#scripts#bundle_names(map(copy(bundles), 'v:val.name_spec'))
call vundle#scripts#view('Installer',['" Installing plugins to '.expand(g:bundle_dir, 1)], names + ['Helptags']) call vundle#scripts#view('Installer',['" Installing plugins to '.expand(g:bundle_dir, 1)], names + ['Helptags'])
" This calls 'add' as a normal mode command. This is a buffer local mapping
" defined in vundle#scripts#view(). The mapping will call a buffer local
" command InstallPlugin which in turn will call vundle#installer#run() with
" vundle#installer#install().
call s:process(a:bang, (a:bang ? 'add!' : 'add')) call s:process(a:bang, (a:bang ? 'add!' : 'add'))
call vundle#config#require(bundles) call vundle#config#require(bundles)
endf endf
" ---------------------------------------------------------------------------
" Iterate over all lines in a Vundle window and execute the given command for
" every line. Used by the installation and cleaning functions.
"
" bang -- not used (FIXME)
" cmd -- the (normal mode) command to execute for every line as a string
" ---------------------------------------------------------------------------
func! s:process(bang, cmd) func! s:process(bang, cmd)
let msg = '' let msg = ''
@ -43,6 +61,16 @@ func! s:process(bang, cmd)
echo 'Done! '.msg echo 'Done! '.msg
endf endf
" ---------------------------------------------------------------------------
" Call another function in the different Vundle windows.
"
" func_name -- the function to call
" name -- the bundle name to call func_name for (string)
" ... -- the argument to be used when calling func_name (only the first
" optional argument will be used)
" return -- the status returned by the call to func_name
" ---------------------------------------------------------------------------
func! vundle#installer#run(func_name, name, ...) abort func! vundle#installer#run(func_name, name, ...) abort
let n = a:name let n = a:name
@ -67,6 +95,8 @@ func! vundle#installer#run(func_name, name, ...) abort
echo n.' deleted' echo n.' deleted'
elseif 'helptags' == status elseif 'helptags' == status
echo n.' regenerated' echo n.' regenerated'
elseif 'pinned' == status
echo n.' pinned'
elseif 'error' == status elseif 'error' == status
echohl Error echohl Error
echo 'Error processing '.n echo 'Error processing '.n
@ -81,6 +111,13 @@ func! vundle#installer#run(func_name, name, ...) abort
return status return status
endf endf
" ---------------------------------------------------------------------------
" Put a sign on the current line, indicating the status of the installation
" step.
"
" status -- string describing the status
" ---------------------------------------------------------------------------
func! s:sign(status) func! s:sign(status)
if (!has('signs')) if (!has('signs'))
return return
@ -89,6 +126,14 @@ func! s:sign(status)
exe ":sign place ".line('.')." line=".line('.')." name=Vu_". a:status ." buffer=" . bufnr("%") exe ":sign place ".line('.')." line=".line('.')." name=Vu_". a:status ." buffer=" . bufnr("%")
endf endf
" ---------------------------------------------------------------------------
" Install a plugin, then add it to the runtimepath and source it.
"
" bang -- 1 or 0, passed directly to vundle#installer#install()
" name -- the name of a bundle (string)
" return -- the return value from vundle#installer#install()
" ---------------------------------------------------------------------------
func! vundle#installer#install_and_require(bang, name) abort func! vundle#installer#install_and_require(bang, name) abort
let result = vundle#installer#install(a:bang, a:name) let result = vundle#installer#install(a:bang, a:name)
let b = vundle#config#bundle(a:name, {}) let b = vundle#config#bundle(a:name, {})
@ -97,6 +142,14 @@ func! vundle#installer#install_and_require(bang, name) abort
return result return result
endf endf
" ---------------------------------------------------------------------------
" Install or update a bundle given by its name.
"
" bang -- 1 or 0, passed directly to s:sync()
" name -- the name of a bundle (string)
" return -- the return value from s:sync()
" ---------------------------------------------------------------------------
func! vundle#installer#install(bang, name) abort func! vundle#installer#install(bang, name) abort
if !isdirectory(g:bundle_dir) | call mkdir(g:bundle_dir, 'p') | endif if !isdirectory(g:bundle_dir) | call mkdir(g:bundle_dir, 'p') | endif
@ -112,6 +165,12 @@ func! vundle#installer#install(bang, name) abort
return s:sync(a:bang, b) return s:sync(a:bang, b)
endf endf
" ---------------------------------------------------------------------------
" Call :helptags for all bundles in g:bundles.
"
" return -- 'error' if an error occurred, else return 'helptags'
" ---------------------------------------------------------------------------
func! vundle#installer#docs() abort func! vundle#installer#docs() abort
let error_count = vundle#installer#helptags(g:bundles) let error_count = vundle#installer#helptags(g:bundles)
if error_count > 0 if error_count > 0
@ -120,6 +179,14 @@ func! vundle#installer#docs() abort
return 'helptags' return 'helptags'
endf endf
" ---------------------------------------------------------------------------
" Call :helptags for a list of bundles.
"
" bundles -- a list of bundle dictionaries for which :helptags should be
" called.
" return -- the number of directories where :helptags failed
" ---------------------------------------------------------------------------
func! vundle#installer#helptags(bundles) abort func! vundle#installer#helptags(bundles) abort
let bundle_dirs = map(copy(a:bundles),'v:val.rtpath') let bundle_dirs = map(copy(a:bundles),'v:val.rtpath')
let help_dirs = filter(bundle_dirs, 's:has_doc(v:val)') let help_dirs = filter(bundle_dirs, 's:has_doc(v:val)')
@ -135,6 +202,13 @@ func! vundle#installer#helptags(bundles) abort
return len(errors) return len(errors)
endf endf
" ---------------------------------------------------------------------------
" List all installed plugins.
" Corresponding documentation: vundle-plugins-list
"
" bang -- not used
" ---------------------------------------------------------------------------
func! vundle#installer#list(bang) abort 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(copy(g:bundles), 'v:val.name_spec'))
call vundle#scripts#view('list', ['" My Plugins'], bundles) call vundle#scripts#view('list', ['" My Plugins'], bundles)
@ -143,6 +217,13 @@ func! vundle#installer#list(bang) abort
endf endf
" ---------------------------------------------------------------------------
" List and remove all directories in the bundle directory which are not
" activated (added to the bundle list).
"
" bang -- 0 if the user should be asked to confirm every deletion, 1 if they
" should be removed unconditionally
" ---------------------------------------------------------------------------
func! vundle#installer#clean(bang) abort func! vundle#installer#clean(bang) abort
let bundle_dirs = map(copy(g:bundles), 'v:val.path()') let bundle_dirs = map(copy(g:bundles), 'v:val.path()')
let all_dirs = (v:version > 702 || (v:version == 702 && has("patch51"))) let all_dirs = (v:version > 702 || (v:version == 702 && has("patch51")))
@ -174,6 +255,14 @@ func! vundle#installer#clean(bang) abort
endf endf
" ---------------------------------------------------------------------------
" Delete to directory for a plugin.
"
" bang -- not used
" dir_name -- the bundle directory to be deleted (as a string)
" return -- 'error' if an error occurred, 'deleted' if the plugin folder was
" successfully deleted
" ---------------------------------------------------------------------------
func! vundle#installer#delete(bang, dir_name) abort func! vundle#installer#delete(bang, dir_name) abort
let cmd = ((has('win32') || has('win64')) && empty(matchstr(&shell, 'sh'))) ? let cmd = ((has('win32') || has('win64')) && empty(matchstr(&shell, 'sh'))) ?
@ -187,8 +276,8 @@ func! vundle#installer#delete(bang, dir_name) abort
call s:log('') call s:log('')
call s:log('Plugin '.a:dir_name) call s:log('Plugin '.a:dir_name)
call s:log('$ '.cmd)
call s:log('> '.out)
call s:log(cmd, '$ ')
call s:log(out, '> ')
if 0 != v:shell_error if 0 != v:shell_error
return 'error' return 'error'
@ -197,6 +286,13 @@ func! vundle#installer#delete(bang, dir_name) abort
endif endif
endf endf
" ---------------------------------------------------------------------------
" Check if a bundled plugin has any documentation.
"
" rtp -- a path (string) where the plugin is installed
" return -- 1 if some documentation was found, 0 otherwise
" ---------------------------------------------------------------------------
func! s:has_doc(rtp) abort func! s:has_doc(rtp) abort
return isdirectory(a:rtp.'/doc') return isdirectory(a:rtp.'/doc')
\ && (!filereadable(a:rtp.'/doc/tags') || filewritable(a:rtp.'/doc/tags')) \ && (!filereadable(a:rtp.'/doc/tags') || filewritable(a:rtp.'/doc/tags'))
@ -205,6 +301,13 @@ func! s:has_doc(rtp) abort
\ : !(empty(glob(a:rtp.'/doc/*.txt')) && empty(glob(a:rtp.'/doc/*.??x'))) \ : !(empty(glob(a:rtp.'/doc/*.txt')) && empty(glob(a:rtp.'/doc/*.??x')))
endf endf
" ---------------------------------------------------------------------------
" Update the helptags for a plugin.
"
" rtp -- the path to the plugin's root directory (string)
" return -- 1 if :helptags succeeded, 0 otherwise
" ---------------------------------------------------------------------------
func! s:helptags(rtp) abort func! s:helptags(rtp) abort
" it is important to keep trailing slash here " it is important to keep trailing slash here
let doc_path = resolve(a:rtp . '/doc/') let doc_path = resolve(a:rtp . '/doc/')
@ -218,12 +321,69 @@ func! s:helptags(rtp) abort
return 1 return 1
endf endf
func! s:sync(bang, bundle) abort
" ---------------------------------------------------------------------------
" Get the URL for the remote called 'origin' on the repository that
" corresponds to a given bundle.
"
" bundle -- a bundle object to check the repository for
" return -- the URL for the origin remote (string)
" ---------------------------------------------------------------------------
func! s:get_current_origin_url(bundle) abort
let cmd = 'cd '.vundle#installer#shellesc(a:bundle.path()).' && git config --get remote.origin.url'
let cmd = g:shellesc_cd(cmd)
let out = s:strip(s:system(cmd))
return out
endf
" ---------------------------------------------------------------------------
" Create the appropriate sync command to run according to the current state of
" the local repository (clone, pull, reset, etc).
"
" In the case of a pull (update), also return the current sha, so that we can
" later check that there has been an upgrade.
"
" bang -- 0 if only new plugins should be installed, 1 if existing plugins
" should be updated
" bundle -- a bundle object to create the sync command for
" return -- A list containing the command to run and the sha for the current
" HEAD
" ---------------------------------------------------------------------------
func! s:make_sync_command(bang, bundle) abort
let git_dir = expand(a:bundle.path().'/.git/', 1) let git_dir = expand(a:bundle.path().'/.git/', 1)
if isdirectory(git_dir) || filereadable(expand(a:bundle.path().'/.git', 1)) if isdirectory(git_dir) || filereadable(expand(a:bundle.path().'/.git', 1))
if !(a:bang) | return 'todate' | endif
let cmd = 'cd '.vundle#installer#shellesc(a:bundle.path()).' && git pull && git submodule update --init --recursive'
let current_origin_url = s:get_current_origin_url(a:bundle)
if current_origin_url != a:bundle.uri
call s:log('Plugin URI change detected for Plugin ' . a:bundle.name)
call s:log('> Plugin ' . a:bundle.name . ' old URI: ' . current_origin_url)
call s:log('> Plugin ' . a:bundle.name . ' new URI: ' . a:bundle.uri)
" Directory names match but the origin remotes are not the same
let cmd_parts = [
\ 'cd '.vundle#installer#shellesc(a:bundle.path()) ,
\ 'git remote set-url origin ' . vundle#installer#shellesc(a:bundle.uri),
\ 'git fetch',
\ 'git reset --hard origin/HEAD',
\ 'git submodule update --init --recursive',
\ ]
let cmd = join(cmd_parts, ' && ')
let cmd = g:shellesc_cd(cmd)
let initial_sha = ''
return [cmd, initial_sha]
endif
if !(a:bang)
" The repo exists, and no !, so leave as it is.
return ['', '']
endif
let cmd_parts = [
\ 'cd '.vundle#installer#shellesc(a:bundle.path()),
\ 'git pull',
\ 'git submodule update --init --recursive',
\ ]
let cmd = join(cmd_parts, ' && ')
let cmd = g:shellesc_cd(cmd) let cmd = g:shellesc_cd(cmd)
let get_current_sha = 'cd '.vundle#installer#shellesc(a:bundle.path()).' && git rev-parse HEAD' let get_current_sha = 'cd '.vundle#installer#shellesc(a:bundle.path()).' && git rev-parse HEAD'
@ -233,12 +393,39 @@ func! s:sync(bang, bundle) abort
let cmd = 'git clone --recursive '.vundle#installer#shellesc(a:bundle.uri).' '.vundle#installer#shellesc(a:bundle.path()) let cmd = 'git clone --recursive '.vundle#installer#shellesc(a:bundle.uri).' '.vundle#installer#shellesc(a:bundle.path())
let initial_sha = '' let initial_sha = ''
endif endif
return [cmd, initial_sha]
endf
" ---------------------------------------------------------------------------
" Install or update a given bundle object with git.
"
" bang -- 0 if only new plugins should be installed, 1 if existing plugins
" should be updated
" bundle -- a bundle object (dictionary)
" return -- a string indicating the status of the bundle installation:
" - todate : Nothing was updated or the repository was up to date
" - new : The plugin was newly installed
" - updated : Some changes where pulled via git
" - error : An error occurred in the shell command
" - pinned : The bundle is marked as pinned
" ---------------------------------------------------------------------------
func! s:sync(bang, bundle) abort
" Do not sync if this bundle is pinned
if a:bundle.is_pinned()
return 'pinned'
endif
let [ cmd, initial_sha ] = s:make_sync_command(a:bang, a:bundle)
if empty(cmd)
return 'todate'
endif
let out = s:system(cmd) let out = s:system(cmd)
call s:log('') call s:log('')
call s:log('Plugin '.a:bundle.name_spec) call s:log('Plugin '.a:bundle.name_spec)
call s:log('$ '.cmd)
call s:log('> '.out)
call s:log(cmd, '$ ')
call s:log(out, '> ')
if 0 != v:shell_error if 0 != v:shell_error
return 'error' return 'error'
@ -258,6 +445,14 @@ func! s:sync(bang, bundle) abort
return 'updated' return 'updated'
endf endf
" ---------------------------------------------------------------------------
" Escape special characters in a string to be able to use it as a shell
" command with system().
"
" cmd -- the string holding the shell command
" return -- a string with the relevant characters escaped
" ---------------------------------------------------------------------------
func! vundle#installer#shellesc(cmd) abort func! vundle#installer#shellesc(cmd) abort
if ((has('win32') || has('win64')) && empty(matchstr(&shell, 'sh'))) if ((has('win32') || has('win64')) && empty(matchstr(&shell, 'sh')))
return '"' . substitute(a:cmd, '"', '\\"', 'g') . '"' return '"' . substitute(a:cmd, '"', '\\"', 'g') . '"'
@ -265,6 +460,13 @@ func! vundle#installer#shellesc(cmd) abort
return shellescape(a:cmd) return shellescape(a:cmd)
endf endf
" ---------------------------------------------------------------------------
" Fix a cd shell command to be used on Windows.
"
" cmd -- the command to be fixed (string)
" return -- the fixed command (string)
" ---------------------------------------------------------------------------
func! g:shellesc_cd(cmd) abort func! g:shellesc_cd(cmd) abort
if ((has('win32') || has('win64')) && empty(matchstr(&shell, 'sh'))) if ((has('win32') || has('win64')) && empty(matchstr(&shell, 'sh')))
let cmd = substitute(a:cmd, '^cd ','cd /d ','') " add /d switch to change drives let cmd = substitute(a:cmd, '^cd ','cd /d ','') " add /d switch to change drives
@ -274,12 +476,45 @@ func! g:shellesc_cd(cmd) abort
endif endif
endf endf
" ---------------------------------------------------------------------------
" Make a system call. This can be used to change the way system calls
" are made during developing, without searching the whole code base for
" actual system() calls.
"
" cmd -- the command passed to system() (string)
" return -- the return value from system()
" ---------------------------------------------------------------------------
func! s:system(cmd) abort func! s:system(cmd) abort
return system(a:cmd) return system(a:cmd)
endf endf
func! s:log(str) abort
let fmt = '%y%m%d %H:%M:%S'
call add(g:vundle_log, '['.strftime(fmt).'] '.a:str)
" ---------------------------------------------------------------------------
" Add a log message to Vundle's internal logging variable.
"
" str -- the log message (string)
" prefix -- optional prefix for multi-line entries (string)
" return -- a:str
" ---------------------------------------------------------------------------
func! s:log(str, ...) abort
let prefix = a:0 > 0 ? a:1 : ''
let fmt = '%Y-%m-%d %H:%M:%S'
let lines = split(a:str, '\n', 1)
let time = strftime(fmt)
for line in lines
call add(g:vundle_log, '['. time .'] '. prefix . line)
endfor
return a:str return a:str
endf endf
" ---------------------------------------------------------------------------
" Remove leading and trailing whitespace from a string
"
" str -- The string to rid of trailing and leading spaces
" return -- A string stripped of side spaces
" ---------------------------------------------------------------------------
func! s:strip(str)
return substitute(a:str, '\%^\_s*\(.\{-}\)\_s*\%$', '\1', '')
endf

+ 66
- 0
autoload/vundle/scripts.vim View File

@ -1,3 +1,11 @@
" ---------------------------------------------------------------------------
" Search the database from vim-script.org for a matching plugin. If no
" argument is given, list all plugins. This function is used by the :Plugins
" and :PluginSearch commands.
"
" bang -- if 1 refresh the script name cache, if 0 don't
" ... -- a plugin name to search for
" ---------------------------------------------------------------------------
func! vundle#scripts#all(bang, ...) func! vundle#scripts#all(bang, ...)
let b:match = '' let b:match = ''
let info = ['"Keymap: i - Install plugin; c - Cleanup; s - Search; R - Reload list'] let info = ['"Keymap: i - Install plugin; c - Cleanup; s - Search; R - Reload list']
@ -13,15 +21,31 @@ func! vundle#scripts#all(bang, ...)
echo len(matches).' plugins found' echo len(matches).' plugins found'
endf endf
" ---------------------------------------------------------------------------
" Repeat the search for bundles.
" ---------------------------------------------------------------------------
func! vundle#scripts#reload() abort func! vundle#scripts#reload() abort
silent exec ':PluginSearch! '.(exists('b:match') ? b:match : '') silent exec ':PluginSearch! '.(exists('b:match') ? b:match : '')
redraw redraw
endf endf
" ---------------------------------------------------------------------------
" Complete names for bundles in the command line.
"
" a, c, d -- see :h command-completion-custom
" return -- all valid plugin names from vim-scripts.org as completion
" candidates, see also :h command-completion-custom
" ---------------------------------------------------------------------------
func! vundle#scripts#complete(a,c,d) func! vundle#scripts#complete(a,c,d)
return join(s:load_scripts(0),"\n") return join(s:load_scripts(0),"\n")
endf endf
" ---------------------------------------------------------------------------
" View the logfile after an update or installation.
" ---------------------------------------------------------------------------
func! s:view_log() func! s:view_log()
if !exists('g:vundle_log_file') if !exists('g:vundle_log_file')
let g:vundle_log_file = tempname() let g:vundle_log_file = tempname()
@ -33,6 +57,11 @@ func! s:view_log()
wincmd P | wincmd H wincmd P | wincmd H
endf endf
" ---------------------------------------------------------------------------
" Parse the output from git log after an update to create a change log for the
" user.
" ---------------------------------------------------------------------------
func! s:create_changelog() abort func! s:create_changelog() abort
for bundle_data in g:updated_bundles for bundle_data in g:updated_bundles
let initial_sha = bundle_data[0] let initial_sha = bundle_data[0]
@ -61,6 +90,10 @@ func! s:create_changelog() abort
endfor endfor
endf endf
" ---------------------------------------------------------------------------
" View the change log after an update or installation.
" ---------------------------------------------------------------------------
func! s:view_changelog() func! s:view_changelog()
call s:create_changelog() call s:create_changelog()
@ -74,10 +107,27 @@ func! s:view_changelog()
wincmd P | wincmd H wincmd P | wincmd H
endf endf
" ---------------------------------------------------------------------------
" Create a list of 'Plugin ...' lines from a list of bundle names.
"
" names -- a list of names (strings) of plugins
" return -- a list of 'Plugin ...' lines suitable to be written to a buffer
" ---------------------------------------------------------------------------
func! vundle#scripts#bundle_names(names) func! vundle#scripts#bundle_names(names)
return map(copy(a:names), ' printf("Plugin ' ."'%s'".'", v:val) ') return map(copy(a:names), ' printf("Plugin ' ."'%s'".'", v:val) ')
endf endf
" ---------------------------------------------------------------------------
" Open a buffer to display information to the user. Several special commands
" are defined in the new buffer.
"
" title -- a title for the new buffer
" headers -- a list of header lines to be displayed at the top of the buffer
" results -- the main information to be displayed in the buffer (list of
" strings)
" ---------------------------------------------------------------------------
func! vundle#scripts#view(title, headers, results) func! vundle#scripts#view(title, headers, results)
if exists('g:vundle_view') && bufloaded(g:vundle_view) if exists('g:vundle_view') && bufloaded(g:vundle_view)
exec g:vundle_view.'bd!' exec g:vundle_view.'bd!'
@ -148,6 +198,13 @@ func! vundle#scripts#view(title, headers, results)
exec ':'.(len(a:headers) + 1) exec ':'.(len(a:headers) + 1)
endf endf
" ---------------------------------------------------------------------------
" Load the plugin database from vim-scripts.org .
"
" to -- the filename (string) to save the database to
" return -- 0 on success, 1 if an error occurred
" ---------------------------------------------------------------------------
func! s:fetch_scripts(to) func! s:fetch_scripts(to)
let scripts_dir = fnamemodify(expand(a:to, 1), ":h") let scripts_dir = fnamemodify(expand(a:to, 1), ":h")
if !isdirectory(scripts_dir) if !isdirectory(scripts_dir)
@ -178,6 +235,15 @@ func! s:fetch_scripts(to)
return 0 return 0
endf endf
" ---------------------------------------------------------------------------
" Load the plugin database and return a list of all plugins.
"
" bang -- if 1 download the redatabase, else only download if it is not
" readable on disk (i.e. does not exist)
" return -- a list of strings, these are the names (valid bundle
" specifications) of all plugins from vim-scripts.org
" ---------------------------------------------------------------------------
func! s:load_scripts(bang) func! s:load_scripts(bang)
let f = expand(g:bundle_dir.'/.vundle/script-names.vim-scripts.org.json', 1) let f = expand(g:bundle_dir.'/.vundle/script-names.vim-scripts.org.json', 1)
if a:bang || !filereadable(f) if a:bang || !filereadable(f)


+ 21
- 1
doc/vundle.txt View File

@ -166,6 +166,26 @@ This can be used to prevent name collisions between plugins that Vundle would
otherwise try to clone into the same directory. It also provides an additional otherwise try to clone into the same directory. It also provides an additional
level of customisation. level of customisation.
The 'pinned' option
-------------------
A flag that, when set to a value of 1, tells Vundle not to perform any git
operations on the plugin, while still adding the existing plugin under the
`bundles` directories to the |runtimepath|.
For example:
>
Plugin 'mylocalplugin', {'pinned': 1}
This allows the users to include, with Vundle, plugins tracked with version
control systems other than git, but the user is responsible for cloning and
keeping up to date. It also allows the users to stay in the current version of
a plugin that might have previously been updated by Vundle.
Please note that the URI will be treated the same as for any other plugins, so
only the last part of it will be added to the |runtimepath|. The user is
advised to use this flag only with single word URIs to avoid confusion.
3.2 SUPPORTED URIS ~ 3.2 SUPPORTED URIS ~
*vundle-plugins-uris* *vundle-plugins-uris*
@ -185,7 +205,7 @@ GitHub is used when a user/repo is passed to `Plugin`.
Vim Scripts Vim Scripts
----------- -----------
Any single word without a '/' is assumed to be from Vim Scripts.
Any single word without a slash '/' is assumed to be from Vim Scripts.
> >
Plugin 'ctrlp.vim' => https://github.com/vim-scripts/ctrlp.vim Plugin 'ctrlp.vim' => https://github.com/vim-scripts/ctrlp.vim


+ 7
- 0
test/vimrc View File

@ -58,6 +58,13 @@ Bundle 'vim-scripts/RubySinatra'
" syntax issue #203 " syntax issue #203
Bundle 'jimenezrick/vimerl' Bundle 'jimenezrick/vimerl'
" Static bundle: Same name as a valid vim-scripts bundle
Bundle 'latte', {'pinned' : 1}
if !isdirectory(expand(bundle_dir) . '/latte')
call mkdir(expand(bundle_dir) . '/latte', 'p')
endif
filetype plugin indent on " Automatically detect file types. filetype plugin indent on " Automatically detect file types.
set wildignore+=doc " should not break helptags set wildignore+=doc " should not break helptags


Loading…
Cancel
Save