From c8f539744e69f14faaaa2a033afbbe929043aee3 Mon Sep 17 00:00:00 2001 From: Lucas Hoffmann Date: Sat, 29 Mar 2014 18:56:21 +0100 Subject: [PATCH] add comments to document the code Also add some FIXME markers in places where the code needs more explanation. --- autoload/vundle.vim | 23 +++++--- autoload/vundle/config.vim | 66 ++++++++++++++++++++++ autoload/vundle/installer.vim | 103 +++++++++++++++++++++++++++++++++- autoload/vundle/scripts.vim | 40 +++++++++++++ 4 files changed, 220 insertions(+), 12 deletions(-) diff --git a/autoload/vundle.vim b/autoload/vundle.vim index 16eebca..9702829 100644 --- a/autoload/vundle.vim +++ b/autoload/vundle.vim @@ -14,6 +14,8 @@ com! -nargs=? -bang -complete=custom,vundle#scripts#complete PluginInstall com! -nargs=? -bang -complete=custom,vundle#scripts#complete PluginSearch \ call vundle#scripts#all('!' == '', ) +" FIXME this command is not well documented in doc/vundle.txt and seems to be +" equivalent to PluginSearch. com! -nargs=? -bang -complete=custom,vundle#scripts#complete Plugins \ call vundle#scripts#all('!' == '', ) @@ -36,7 +38,7 @@ com! -nargs=? -bang VundleClean Plugi com! -nargs=0 VundleDocs PluginDocs com! VundleUpdate PluginInstall! -" deprecated +" Deprecated Commands com! -nargs=+ Bundle call vundle#config#bundle() com! -nargs=? -bang -complete=custom,vundle#scripts#complete BundleInstall PluginInstall com! -nargs=? -bang -complete=custom,vundle#scripts#complete BundleSearch PluginSearch @@ -46,17 +48,20 @@ com! -nargs=? -bang BundleClean Plugi com! -nargs=0 BundleDocs PluginDocs com! BundleUpdate PluginInstall! +" Set up the signs used in the installer window. (See :help 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 endif - +" Setup function to be called from the users vimrc file. It is not possible +" to do this automatically because when loading the vimrc file no plugins +" where loaded yet. func! vundle#rc(...) abort let g:bundle_dir = len(a:000) > 0 ? expand(a:1, 1) : expand('$HOME/.vim/bundle', 1) let g:updated_bundles = [] diff --git a/autoload/vundle/config.vim b/autoload/vundle/config.vim index 7bcf647..229f9be 100644 --- a/autoload/vundle/config.vim +++ b/autoload/vundle/config.vim @@ -1,3 +1,8 @@ +" 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, ...) let bundle = vundle#config#init_bundle(a:arg, a:000) call s:rtp_rm_a() @@ -6,12 +11,19 @@ func! vundle#config#bundle(arg, ...) return bundle endf +" Initialize Vundle. +" +" return -- 0 (unconditionally) func! vundle#config#init() if !exists('g:bundles') | let g:bundles = [] | endif call s:rtp_rm_a() let g:bundles = [] endf +" Add a list of bundles to the runtimepath source them. +" +" bundles -- a list of bundle objects +" return -- 0 (unconditionally) func! vundle#config#require(bundles) abort for b in a:bundles call s:rtp_add(b.rtpath) @@ -23,6 +35,11 @@ func! vundle#config#require(bundles) abort endfor endf +" Create a bundle object from a bundle specification. +" +" name -- the bundle specification as a string +" opts -- the options directory from then bundle definition +" return -- an initialized bundle object func! vundle#config#init_bundle(name, opts) if a:name != substitute(a:name, '^\s*\(.\{-}\)\s*$', '\1', '') echo "Spurious leading and/or trailing whitespace found in plugin spec '" . a:name . "'" @@ -33,6 +50,12 @@ func! vundle#config#init_bundle(name, opts) return b endf +" Parse the options which can be supplied with the plugin specification. +" Corresponding documentation: vundle-plugins-configure +" +" opts -- a list, holding a dictionary of options for a bundle +" return -- the dictionary holding the options for a bundle. This will be +" merged with a s:bundle object into one dictionary. func! s:parse_options(opts) " TODO: improve this if len(a:opts) != 1 | return {} | endif @@ -44,6 +67,13 @@ func! s:parse_options(opts) endif 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 +" 'arg') func! s:parse_name(arg) let arg = a:arg let git_proto = exists('g:vundle_default_git_proto') ? g:vundle_default_git_proto : 'https' @@ -67,6 +97,10 @@ func! s:parse_name(arg) return {'name': name, 'uri': uri, 'name_spec': arg } endf +" Remove all paths for the plugins which are managed by Vundle from the +" runtimepath. +" +" return -- 0 (unconditionally) func! s:rtp_rm_a() let paths = map(copy(g:bundles), 'v:val.rtpath') let prepends = join(paths, ',') @@ -75,6 +109,10 @@ func! s:rtp_rm_a() exec 'set rtp-='.fnameescape(appends) endf +" Add all paths for the plugins which are managed by Vundle to the +" runtimepath. +" +" return -- 0 (unconditionally) func! s:rtp_add_a() let paths = map(copy(g:bundles), 'v:val.rtpath') let prepends = join(paths, ',') @@ -83,26 +121,54 @@ func! s:rtp_add_a() exec 'set rtp+='.fnameescape(appends) 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. +" return -- 0 (unconditionally) func! s:rtp_rm(dir) abort exec 'set rtp-='.fnameescape(expand(a:dir, 1)) exec 'set rtp-='.fnameescape(expand(a:dir.'/after', 1)) 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. +" return -- 0 (unconditionally) func! s:rtp_add(dir) abort exec 'set rtp^='.fnameescape(expand(a:dir, 1)) exec 'set rtp+='.fnameescape(expand(a:dir.'/after', 1)) 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 return simplify(expand(a:path, 1)) 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) return has_key(a:opts, 'rtp') ? s:expand_path(a:opts.path().'/'.a:opts.rtp) : a:opts.path() endf +" a bundle 'object' let s:bundle = {} +" FIXME: This function is only called once and in most cases the return value +" is stored in the bundle object as obj.rtpath unmodfied. Is this necessary? +" +" A method of the bundle object returning the path inside the bundle directory +" where the plugin is cloned to. +" +" return -- the target location to clone this bundle to func! s:bundle.path() return s:expand_path(g:bundle_dir.'/'.self.name) endf diff --git a/autoload/vundle/installer.vim b/autoload/vundle/installer.vim index 7fdc5f3..d568064 100644 --- a/autoload/vundle/installer.vim +++ b/autoload/vundle/installer.vim @@ -1,3 +1,10 @@ +" This function is called by :PluginInstall. It will 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 (seperate arguments) +" return -- 0 (unconditionally) func! vundle#installer#new(bang, ...) abort let bundles = (a:1 == '') ? \ 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')) call vundle#scripts#view('Installer',['" Installing plugins to '.expand(g:bundle_dir, 1)], names + ['Helptags']) + " FIXME this tries to call '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(). This is very + " confusing and unclear. call s:process(a:bang, (a:bang ? 'add!' : 'add')) call vundle#config#require(bundles) endf - +" A function to iterate over all lines in a Vundle window and execute the +" given command for every line. It is used by the installation and cleaning +" functions. +" +" bang -- not used (FIXME) +" cmd -- the (normal mode) command to execute for every line as a string +" return -- 0 (unconditionally) func! s:process(bang, cmd) let msg = '' @@ -43,6 +61,13 @@ func! s:process(bang, cmd) echo 'Done! '.msg endf +" Wrapper function to 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 let n = a:name @@ -81,6 +106,11 @@ func! vundle#installer#run(func_name, name, ...) abort return status endf +" Put a sign on the current line, indicating the status of the installation +" step. +" +" status -- string describing the status +" return -- 0 (unconditionally) func! s:sign(status) if (!has('signs')) return @@ -89,6 +119,11 @@ func! s:sign(status) exe ":sign place ".line('.')." line=".line('.')." name=Vu_". a:status ." buffer=" . bufnr("%") 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 let result = vundle#installer#install(a:bang, a:name) let b = vundle#config#bundle(a:name, {}) @@ -97,6 +132,11 @@ func! vundle#installer#install_and_require(bang, name) abort return result 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 if !isdirectory(g:bundle_dir) | call mkdir(g:bundle_dir, 'p') | endif @@ -112,6 +152,9 @@ func! vundle#installer#install(bang, name) abort return s:sync(a:bang, b) endf +" Call :helptags for all bundles in g:bundles. +" +" return -- 'error' if an error occurred, else return 'helptags' func! vundle#installer#docs() abort let error_count = vundle#installer#helptags(g:bundles) if error_count > 0 @@ -120,6 +163,11 @@ func! vundle#installer#docs() abort return 'helptags' 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 let bundle_dirs = map(copy(a:bundles),'v:val.rtpath') let help_dirs = filter(bundle_dirs, 's:has_doc(v:val)') @@ -135,6 +183,11 @@ func! vundle#installer#helptags(bundles) abort return len(errors) endf +" List all installed plugins. +" Corresponding documentation: vundle-plugins-list +" +" bang -- not used +" return -- 0 (unconditionally) func! vundle#installer#list(bang) abort let bundles = vundle#scripts#bundle_names(map(copy(g:bundles), 'v:val.name_spec')) call vundle#scripts#view('list', ['" My Plugins'], bundles) @@ -142,7 +195,12 @@ func! vundle#installer#list(bang) abort echo len(g:bundles).' plugins configured' 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 +" return -- 0 (unconditionally) func! vundle#installer#clean(bang) abort let bundle_dirs = map(copy(g:bundles), 'v:val.path()') let all_dirs = (v:version > 702 || (v:version == 702 && has("patch51"))) @@ -173,7 +231,12 @@ func! vundle#installer#clean(bang) abort endif 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 let cmd = ((has('win32') || has('win64')) && empty(matchstr(&shell, 'sh'))) ? @@ -197,6 +260,10 @@ func! vundle#installer#delete(bang, dir_name) abort endif 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 return isdirectory(a:rtp.'/doc') \ && (!filereadable(a:rtp.'/doc/tags') || filewritable(a:rtp.'/doc/tags')) @@ -205,6 +272,10 @@ func! s:has_doc(rtp) abort \ : !(empty(glob(a:rtp.'/doc/*.txt')) && empty(glob(a:rtp.'/doc/*.??x'))) 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 " it is important to keep trailing slash here let doc_path = resolve(a:rtp).'/doc/' @@ -218,6 +289,15 @@ func! s:helptags(rtp) abort return 1 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 (dict) +" return -- 'todate' if nothing was updated or the repository was up to date, +" 'new' when the plugin was newly installed, 'updated' if some +" changes where pulled via git, 'error' if an error occurred in the +" shell command func! s:sync(bang, bundle) abort let git_dir = expand(a:bundle.path().'/.git/', 1) if isdirectory(git_dir) || filereadable(expand(a:bundle.path().'/.git', 1)) @@ -258,6 +338,11 @@ func! s:sync(bang, bundle) abort return 'updated' 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 if ((has('win32') || has('win64')) && empty(matchstr(&shell, 'sh'))) return '"' . substitute(a:cmd, '"', '\\"', 'g') . '"' @@ -265,6 +350,10 @@ func! vundle#installer#shellesc(cmd) abort return shellescape(a:cmd) 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 if ((has('win32') || has('win64')) && empty(matchstr(&shell, 'sh'))) let cmd = substitute(a:cmd, '^cd ','cd /d ','') " add /d switch to change drives @@ -274,10 +363,18 @@ func! g:shellesc_cd(cmd) abort endif endf +" Wrapper for system calls. FIXME: Why is this needed? +" +" cmd -- the command passed to system() (string) +" return -- the return value from system() func! s:system(cmd) abort return system(a:cmd) endf +" Add a log message to Vundle's internal logging variable. +" +" str -- the log message (string) +" return -- a:str func! s:log(str) abort let fmt = '%y%m%d %H:%M:%S' call add(g:vundle_log, '['.strftime(fmt).'] '.a:str) diff --git a/autoload/vundle/scripts.vim b/autoload/vundle/scripts.vim index 5c43547..603d9c2 100644 --- a/autoload/vundle/scripts.vim +++ b/autoload/vundle/scripts.vim @@ -1,3 +1,10 @@ +" This function searches the database from vim-script.org for a matching +" plugin. If no argument is given all plugins are listed. 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 (FIXME what about multible arguments, it +" doesn't seem to work.) func! vundle#scripts#all(bang, ...) let b:match = '' let info = ['"Keymap: i - Install plugin; c - Cleanup; s - Search; R - Reload list'] @@ -13,15 +20,22 @@ func! vundle#scripts#all(bang, ...) echo len(matches).' plugins found' endf +" Repeat the search for bundles. func! vundle#scripts#reload() abort silent exec ':PluginSearch! '.(exists('b:match') ? b:match : '') redraw 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) return join(s:load_scripts(0),"\n") endf +" View the logfile after an update or installation. func! s:view_log() if !exists('g:vundle_log_file') let g:vundle_log_file = tempname() @@ -33,6 +47,10 @@ func! s:view_log() wincmd P | wincmd H endf +" Parse the output from git log after an update to create a change log for the +" tuser. +" +" return -- 0 (unconditionally) func! s:create_changelog() abort for bundle_data in g:updated_bundles let initial_sha = bundle_data[0] @@ -61,6 +79,7 @@ func! s:create_changelog() abort endfor endf +" View the change log after an update or installation. func! s:view_changelog() call s:create_changelog() @@ -74,10 +93,21 @@ func! s:view_changelog() wincmd P | wincmd H 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) return map(copy(a:names), ' printf("Plugin ' ."'%s'".'", v:val) ') 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) if exists('g:vundle_view') && bufloaded(g:vundle_view) exec g:vundle_view.'bd!' @@ -148,6 +178,10 @@ func! vundle#scripts#view(title, headers, results) exec ':'.(len(a:headers) + 1) 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) let scripts_dir = fnamemodify(expand(a:to, 1), ":h") if !isdirectory(scripts_dir) @@ -178,6 +212,12 @@ func! s:fetch_scripts(to) return 0 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) let f = expand(g:bundle_dir.'/.vundle/script-names.vim-scripts.org.json', 1) if a:bang || !filereadable(f)