diff --git a/autoload/xolox/misc/buffer.vim b/autoload/xolox/misc/buffer.vim index 3597cc2..01dca6e 100644 --- a/autoload/xolox/misc/buffer.vim +++ b/autoload/xolox/misc/buffer.vim @@ -1,15 +1,44 @@ -" Vim auto-load script +" Handling of special buffers +" " Author: Peter Odding -" Last Change: April 18, 2013 +" Last Change: May 19, 2013 " URL: http://peterodding.com/code/vim/misc/ +" +" The functions defined here make it easier to deal with special Vim buffers +" that contain text generated by a Vim plug-in. For example my [vim-notes +" plug-in] [vim-notes] generates several such buffers: +" +" - [:RecentNotes] [RecentNotes] lists recently modified notes +" - [:ShowTaggedNotes] [ShowTaggedNotes] lists notes grouped by tags +" - etc. +" +" Because the text in these buffers is generated, Vim shouldn't bother with +" swap files and it should never prompt the user whether to save changes to +" the generated text. +" +" [vim-notes]: http://peterodding.com/code/vim/notes/ +" [RecentNotes]: http://peterodding.com/code/vim/notes/#recentnotes_command +" [ShowTaggedNotes]: http://peterodding.com/code/vim/notes/#showtaggednotes_command function! xolox#misc#buffer#is_empty() " {{{1 - " Check if the current buffer is an empty, unchanged buffer which can be reused. + " Checks if the current buffer is an empty, unchanged buffer which can be + " reused. Returns 1 if an empty buffer is found, 0 otherwise. return !&modified && expand('%') == '' && line('$') <= 1 && getline(1) == '' endfunction function! xolox#misc#buffer#prepare(...) " {{{1 - " Open a special buffer (with generated contents, not directly edited by the user). + " Open a special buffer, i.e. a buffer that will hold generated contents, + " not directly edited by the user. The buffer can be customized by passing a + " dictionary with the following key/value pairs as the first argument: + " + " - **name** (required): The base name of the buffer (i.e. the base name of + " the file loaded in the buffer, even though it isn't really a file and + " nothing is really 'loaded' :-) + " - **path** (required): The pathname of the buffer. May be relevant if + " [:lcd] [lcd] or ['autochdir'] [acd] is being used. + " + " [lcd]: http://vimdoc.sourceforge.net/htmldoc/editing.html#:lcd + " [acd]: http://vimdoc.sourceforge.net/htmldoc/options.html#'autochdir' if a:0 == 1 && type(a:1) == type('') " Backwards compatibility with old interface. let options = {'name': a:1, 'path': a:1} @@ -41,7 +70,7 @@ function! xolox#misc#buffer#prepare(...) " {{{1 endfunction function! xolox#misc#buffer#lock() " {{{1 - " Lock a special buffer so it can no longer be edited. + " Lock a special buffer so that its contents can no longer be edited. setlocal readonly nomodifiable nomodified endfunction diff --git a/autoload/xolox/misc/compat.vim b/autoload/xolox/misc/compat.vim index 70a4287..3f3a42c 100644 --- a/autoload/xolox/misc/compat.vim +++ b/autoload/xolox/misc/compat.vim @@ -1,22 +1,36 @@ -" Vim auto-load script +" Compatibility checking. +" " Author: Peter Odding -" Last Change: May 13, 2013 +" Last Change: May 20, 2013 " URL: http://peterodding.com/code/vim/misc/ - -" The following integer will be bumped whenever a change in the miscellaneous +" +" This Vim script defines a version number for the miscellaneous scripts. Each +" of my plug-ins compares their expected version of the miscellaneous scripts +" against the version number defined inside the miscellaneous scripts. +" +" The version number is incremented whenever a change in the miscellaneous " scripts breaks backwards compatibility. This enables my Vim plug-ins to fail " early when they detect an incompatible version, instead of breaking at the " worst possible moments :-). -let g:xolox#misc#compat#version = 3 +let g:xolox#misc#compat#version = 7 " Remember the directory where the miscellaneous scripts are loaded from " so the user knows which plug-in to update if incompatibilities arise. -let s:misc_directory = fnamemodify(expand(''), ':p:h') +let s:misc_directory = fnamemodify(expand(''), ':~:h') -function! xolox#misc#compat#check(plugin_name, required_version) +function! xolox#misc#compat#check(plugin_name, plugin_version, required_version) + " Expects three arguments: + " + " 1. The name of the Vim plug-in that is using the miscellaneous scripts + " 2. The version of the Vim plug-in that is using the miscellaneous scripts + " 3. The version of the miscellaneous scripts expected by the plug-in + " + " When the loaded version of the miscellaneous scripts is different from the + " version expected by the plug-in, this function will raise an error message + " that explains what went wrong. if a:required_version != g:xolox#misc#compat#version - let msg = "The %s plug-in requires version %i of the miscellaneous scripts, however version %i was loaded from %s!" - throw printf(msg, a:plugin_name, a:required_version, g:xolox#misc#compat#version, s:misc_directory) + let msg = "The %s %s plug-in expects version %i of the miscellaneous scripts, however version %i was loaded from the directory %s! Please upgrade your plug-ins to the latest releases to resolve this problem." + throw printf(msg, a:plugin_name, a:plugin_version, a:required_version, g:xolox#misc#compat#version, s:misc_directory) endif endfunction diff --git a/autoload/xolox/misc/complete.vim b/autoload/xolox/misc/complete.vim index 2ada676..763e0b9 100644 --- a/autoload/xolox/misc/complete.vim +++ b/autoload/xolox/misc/complete.vim @@ -1,11 +1,15 @@ -" Vim auto-load script +" Tab completion for user defined commands. +" " Author: Peter Odding -" Last Change: March 15, 2011 +" Last Change: May 19, 2013 " URL: http://peterodding.com/code/vim/misc/ -" Keyword completion from the current buffer for user defined commands. - function! xolox#misc#complete#keywords(arglead, cmdline, cursorpos) + " This function can be used to perform keyword completion for user defined + " Vim commands based on the contents of the current buffer. Here's an + " example of how you would use it: + " + " :command -nargs=* -complete=customlist,xolox#misc#complete#keywords MyCmd call s:MyCmd() let words = {} for line in getline(1, '$') for word in split(line, '\W\+') diff --git a/autoload/xolox/misc/escape.vim b/autoload/xolox/misc/escape.vim index 1dd1838..29a16ca 100644 --- a/autoload/xolox/misc/escape.vim +++ b/autoload/xolox/misc/escape.vim @@ -1,11 +1,16 @@ -" Vim auto-load script +" String escaping functions. +" " Author: Peter Odding -" Last Change: November 21, 2011 +" Last Change: May 19, 2013 " URL: http://peterodding.com/code/vim/misc/ -" Convert a string into a :substitute pattern that matches the string literally. - -function! xolox#misc#escape#pattern(string) +function! xolox#misc#escape#pattern(string) " {{{1 + " Takes a single string argument and converts it into a [:substitute] + " [subcmd] / [substitute()] [subfun] pattern string that matches the given + " string literally. + " + " [subfun]: http://vimdoc.sourceforge.net/htmldoc/eval.html#substitute() + " [subcmd]: http://vimdoc.sourceforge.net/htmldoc/change.html#:substitute if type(a:string) == type('') let string = escape(a:string, '^$.*\~[]') return substitute(string, '\n', '\\n', 'g') @@ -13,9 +18,10 @@ function! xolox#misc#escape#pattern(string) return '' endfunction -" Convert a string into a :substitute replacement that inserts the string literally. - -function! xolox#misc#escape#substitute(string) +function! xolox#misc#escape#substitute(string) " {{{1 + " Takes a single string argument and converts it into a [:substitute] + " [subcmd] / [substitute()] [subfun] replacement string that inserts the + " given string literally. if type(a:string) == type('') let string = escape(a:string, '\&~%') return substitute(string, '\n', '\\r', 'g') @@ -23,13 +29,17 @@ function! xolox#misc#escape#substitute(string) return '' endfunction -" Convert a string into a quoted command line argument. I was going to add a -" long rant here about &shellslash, but really, it won't make any difference. -" Let's just suffice to say that I have yet to encounter a single person out -" there who uses this option for its intended purpose (running a UNIX-style -" shell on Windows). - -function! xolox#misc#escape#shell(string) +function! xolox#misc#escape#shell(string) " {{{1 + " Takes a single string argument and converts it into a quoted command line + " argument. + " + " I was going to add a long rant here about Vim's ['shellslash' option] + " [shellslash], but really, it won't make any difference. Let's just suffice + " to say that I have yet to encounter a single person out there who uses + " this option for its intended purpose (running a UNIX style shell on + " Microsoft Windows). + " + " [shellslash]: http://vimdoc.sourceforge.net/htmldoc/options.html#'shellslash' if xolox#misc#os#is_win() try let ssl_save = &shellslash diff --git a/autoload/xolox/misc/list.vim b/autoload/xolox/misc/list.vim index ee243d4..13dfb43 100644 --- a/autoload/xolox/misc/list.vim +++ b/autoload/xolox/misc/list.vim @@ -1,19 +1,27 @@ -" Vim auto-load script +" List handling functions. +" " Author: Peter Odding -" Last Change: August 31, 2011 +" Last Change: May 19, 2013 " URL: http://peterodding.com/code/vim/misc/ -" Remove duplicate values from {list} in-place (preserves order). - -function! xolox#misc#list#unique(list) +function! xolox#misc#list#unique(list) " {{{1 + " Remove duplicate values from the given list in-place (preserves order). call reverse(a:list) call filter(a:list, 'count(a:list, v:val) == 1') return reverse(a:list) endfunction -" Binary insertion (more efficient than calling sort() after each insertion). - -function! xolox#misc#list#binsert(list, value, ...) +function! xolox#misc#list#binsert(list, value, ...) " {{{1 + " Performs in-place binary insertion, which depending on your use case can + " be more efficient than calling Vim's [sort()] [sort] function after each + " insertion (in cases where a single, final sort is not an option). Expects + " three arguments: + " + " 1. A list + " 2. A value to insert + " 3. 1 (true) when case should be ignored, 0 (false) otherwise + " + " [sort]: http://vimdoc.sourceforge.net/htmldoc/eval.html#sort() let idx = s:binsert_r(a:list, 0, len(a:list), a:value, exists('a:1') && a:1) return insert(a:list, a:value, idx) endfunction diff --git a/autoload/xolox/misc/msg.vim b/autoload/xolox/misc/msg.vim index 9ba2b7c..38eb474 100644 --- a/autoload/xolox/misc/msg.vim +++ b/autoload/xolox/misc/msg.vim @@ -1,6 +1,7 @@ -" Vim auto-load script +" Functions to interact with the user. +" " Author: Peter Odding -" Last Change: March 15, 2011 +" Last Change: May 19, 2013 " URL: http://peterodding.com/code/vim/misc/ if !exists('g:xolox_message_buffer') @@ -12,29 +13,34 @@ if !exists('g:xolox_messages') let g:xolox_messages = [] endif -" Show a formatted informational message to the user. - -function! xolox#misc#msg#info(...) +function! xolox#misc#msg#info(...) " {{{1 + " Show a formatted informational message to the user. This function has the + " same argument handling as Vim's [printf()] [printf] function. + " + " [printf]: http://vimdoc.sourceforge.net/htmldoc/eval.html#printf() call s:show_message('title', a:000) endfunction -" Show a formatted warning message to the user. - -function! xolox#misc#msg#warn(...) +function! xolox#misc#msg#warn(...) " {{{1 + " Show a formatted warning message to the user. This function has the same + " argument handling as Vim's [printf()] [printf] function. call s:show_message('warningmsg', a:000) endfunction -" Show a formatted debugging message to the user? - -function! xolox#misc#msg#debug(...) +function! xolox#misc#msg#debug(...) " {{{1 + " Show a formatted debugging message to the user, if the user has enabled + " increased verbosity by setting Vim's ['verbose'] [verbose] option to one + " (1) or higher. This function has the same argument handling as Vim's + " [printf()] [printf] function. + " + " [verbose]: http://vimdoc.sourceforge.net/htmldoc/options.html#'verbose' if &vbs >= 1 call s:show_message('question', a:000) endif endfunction -" The implementation of info() and warn(). - -function! s:show_message(hlgroup, args) +function! s:show_message(hlgroup, args) " {{{1 + " The implementation of info() and warn(). let nargs = len(a:args) if nargs == 1 let message = a:args[0] @@ -56,7 +62,10 @@ function! s:show_message(hlgroup, args) augroup END execute 'echohl' a:hlgroup " Redraw to avoid |hit-enter| prompt. - redraw | echomsg message + redraw + for line in split(message, "\n") + echomsg line + endfor if g:xolox_message_buffer > 0 call add(g:xolox_messages, message) if len(g:xolox_messages) > g:xolox_message_buffer @@ -70,7 +79,8 @@ function! s:show_message(hlgroup, args) endif endfunction -function! s:clear_message() +function! s:clear_message() " {{{1 + " Callback to clear message after some time has passed. echo '' let &more = s:more_save let &showmode = s:smd_save diff --git a/autoload/xolox/misc/open.vim b/autoload/xolox/misc/open.vim index 1fb24e0..b369f4f 100644 --- a/autoload/xolox/misc/open.vim +++ b/autoload/xolox/misc/open.vim @@ -1,6 +1,7 @@ -" Vim auto-load script +" Integration between Vim and its environment. +" " Author: Peter Odding -" Last Change: November 21, 2011 +" Last Change: May 19, 2013 " URL: http://peterodding.com/code/vim/misc/ if !exists('s:version') @@ -9,7 +10,20 @@ if !exists('s:version') let s:handlers = ['gnome-open', 'kde-open', 'exo-open', 'xdg-open'] endif -function! xolox#misc#open#file(path, ...) +function! xolox#misc#open#file(path, ...) " {{{1 + " Given a pathname as the first argument, this opens the file with the + " program associated with the file type. So for example a text file might + " open in Vim, an `*.html` file would probably open in your web browser and + " a media file would open in a media player. + " + " This should work on Windows, Mac OS X and most Linux distributions. If + " this fails to find a file association, you can pass one or more external + " commands to try as additional arguments. For example: + " + " :call xolox#misc#open#file('/path/to/my/file', 'firefox', 'google-chrome') + " + " This generally shouldn't be necessary but it might come in handy now and + " then. if xolox#misc#os#is_win() try call xolox#shell#open_with_windows_shell(a:path) @@ -35,7 +49,15 @@ function! xolox#misc#open#file(path, ...) throw printf(s:enoimpl, s:script, 'xolox#misc#open#file') endfunction -function! xolox#misc#open#url(url) +function! xolox#misc#open#url(url) " {{{1 + " Given a URL as the first argument, this opens the URL in your preferred or + " best available web browser: + " + " - In GUI environments a graphical web browser will open (or a new tab will + " be created in an existing window) + " - In console Vim without a GUI environment, when you have any of `lynx`, + " `links` or `w3m` installed it will launch a command line web browser in + " front of Vim (temporarily suspending Vim) let url = a:url if url !~ '^\w\+://' if url !~ '@' @@ -56,7 +78,7 @@ function! xolox#misc#open#url(url) call xolox#misc#open#file(url, 'firefox', 'google-chrome') endfunction -function! s:handle_error(cmd, output) +function! s:handle_error(cmd, output) " {{{1 if v:shell_error let message = "open.vim %s: Failed to execute program! (command line: %s%s)" let output = strtrans(xolox#misc#str#trim(a:output)) diff --git a/autoload/xolox/misc/option.vim b/autoload/xolox/misc/option.vim index efaf1bc..fce155c 100644 --- a/autoload/xolox/misc/option.vim +++ b/autoload/xolox/misc/option.vim @@ -1,9 +1,18 @@ -" Vim auto-load script +" Vim and plug-in option handling. +" " Author: Peter Odding -" Last Change: August 31, 2011 +" Last Change: May 19, 2013 " URL: http://peterodding.com/code/vim/misc/ -function! xolox#misc#option#get(name, ...) +function! xolox#misc#option#get(name, ...) " {{{1 + " Expects one or two arguments: 1. The name of a variable and 2. the default + " value if the variable does not exist. + " + " Returns the value of the variable from a buffer local variable, global + " variable or the default value, depending on which is defined. + " + " This is used by some of my Vim plug-ins for option handling, so that users + " can customize options for specific buffers. if exists('b:' . a:name) " Buffer local variable. return eval('b:' . a:name) @@ -16,9 +25,17 @@ function! xolox#misc#option#get(name, ...) endif endfunction -" Functions to parse multi-valued Vim options like &tags and &runtimepath. - -function! xolox#misc#option#split(value) +function! xolox#misc#option#split(value) " {{{1 + " Given a multi-value Vim option like ['runtimepath'] [rtp] this returns a + " list of strings. For example: + " + " :echo xolox#misc#option#split(&runtimepath) + " ['/home/peter/Projects/Vim/misc', + " '/home/peter/Projects/Vim/colorscheme-switcher', + " '/home/peter/Projects/Vim/easytags', + " ...] + " + " [rtp]: http://vimdoc.sourceforge.net/htmldoc/options.html#'runtimepath' let values = split(a:value, '[^\\]\zs,') return map(values, 's:unescape(v:val)') endfunction @@ -27,7 +44,10 @@ function! s:unescape(s) return substitute(a:s, '\\\([\\,]\)', '\1', 'g') endfunction -function! xolox#misc#option#join(values) +function! xolox#misc#option#join(values) " {{{1 + " Given a list of strings like the ones returned by + " `xolox#misc#option#split()`, this joins the strings together into a + " single value that can be used to set a Vim option. let values = copy(a:values) call map(values, 's:escape(v:val)') return join(values, ',') @@ -37,7 +57,11 @@ function! s:escape(s) return escape(a:s, ',\') endfunction -function! xolox#misc#option#split_tags(value) +function! xolox#misc#option#split_tags(value) " {{{1 + " Customized version of `xolox#misc#option#split()` with specialized + " handling for Vim's ['tags' option] [tags]. + " + " [tags]: http://vimdoc.sourceforge.net/htmldoc/options.html#'tags' let values = split(a:value, '[^\\]\zs,') return map(values, 's:unescape_tags(v:val)') endfunction @@ -46,7 +70,9 @@ function! s:unescape_tags(s) return substitute(a:s, '\\\([\\, ]\)', '\1', 'g') endfunction -function! xolox#misc#option#join_tags(values) +function! xolox#misc#option#join_tags(values) " {{{1 + " Customized version of `xolox#misc#option#join()` with specialized + " handling for Vim's ['tags' option] [tags]. let values = copy(a:values) call map(values, 's:escape_tags(v:val)') return join(values, ',') @@ -56,9 +82,14 @@ function! s:escape_tags(s) return escape(a:s, ', ') endfunction -function! xolox#misc#option#eval_tags(value, ...) +function! xolox#misc#option#eval_tags(value, ...) " {{{1 + " Evaluate Vim's ['tags' option] [tags] without looking at the file + " system, i.e. this will report tags files that don't exist yet. Expects + " the value of the ['tags' option] [tags] as the first argument. If the + " optional second argument is 1 (true) only the first match is returned, + " otherwise (so by default) a list with all matches is returned. let pathnames = [] - let first_only = exists('a:1') && a:1 + let first_only = exists('a:1') ? a:1 : 0 for pattern in xolox#misc#option#split_tags(a:value) " Make buffer relative pathnames absolute. if pattern =~ '^\./' @@ -78,7 +109,7 @@ function! xolox#misc#option#eval_tags(value, ...) return pathnames[0] endif endfor - return firstonly ? '' : pathnames + return first_only ? '' : pathnames endfunction " vim: ts=2 sw=2 et diff --git a/autoload/xolox/misc/os.vim b/autoload/xolox/misc/os.vim index ef036df..4dcf64d 100644 --- a/autoload/xolox/misc/os.vim +++ b/autoload/xolox/misc/os.vim @@ -1,19 +1,44 @@ -" Vim auto-load script +" Operating system interfaces. +" " Author: Peter Odding -" Last Change: May 13, 2013 +" Last Change: May 19, 2013 " URL: http://peterodding.com/code/vim/misc/ -let g:xolox#misc#os#version = '0.2' +let g:xolox#misc#os#version = '0.3' function! xolox#misc#os#is_win() " {{{1 - " Check whether Vim is running on Microsoft Windows. + " Returns 1 (true) when on Microsoft Windows, 0 (false) otherwise. return has('win16') || has('win32') || has('win64') endfunction function! xolox#misc#os#exec(options) " {{{1 - " Execute an external command (hiding the console on Windows when possible). - " NB: Everything below is wrapped in a try/finally block to guarantee - " cleanup of temporary files. + " Execute an external command (hiding the console on Microsoft Windows when + " my [vim-shell plug-in] [vim-shell] is installed). + " + " Expects a dictionary with the following key/value pairs as the first + " argument: + " + " - **command** (required): The command line to execute + " - **async** (optional): set this to 1 (true) to execute the command in the + " background (asynchronously) + " - **stdin** (optional): a string or list of strings with the input for the + " external command + " - **check** (optional): set this to 0 (false) to disable checking of the + " exit code of the external command (by default an exception will be + " raised when the command fails) + " + " Returns a dictionary with one or more of the following key/value pairs: + " + " - **command** (always available): the generated command line that was used + " to run the external command + " - **exit_code** (only in synchronous mode): the exit status of the + " external command (an integer, zero on success) + " - **stdout** (only in synchronous mode): the output of the command on the + " standard output stream (a list of strings, one for each line) + " - **stderr** (only in synchronous mode): the output of the command on the + " standard error stream (as a list of strings, one for each line) + " + " [vim-shell]: http://peterodding.com/code/vim/shell/ try " Unpack the options. @@ -72,6 +97,14 @@ function! xolox#misc#os#exec(options) " {{{1 endif endif + " Execute the command line using 'sh' instead of the default shell, + " because we assume that standard output and standard error can be + " redirected separately, but (t)csh does not support this. + if has('unix') + call xolox#misc#msg#debug("os.vim %s: Generated shell expression: %s", g:xolox#misc#os#version, cmd) + let cmd = printf('sh -c %s', xolox#misc#escape#shell(cmd)) + endif + " Let the user know what's happening (in case they're interested). call xolox#misc#msg#debug("os.vim %s: Executing external command using system() function: %s", g:xolox#misc#os#version, cmd) call system(cmd) @@ -79,19 +112,29 @@ function! xolox#misc#os#exec(options) " {{{1 endif - let result = {} + " Return the results as a dictionary with one or more key/value pairs. + let result = {'command': cmd} if !async + let result['exit_code'] = exit_code + let result['stdout'] = s:readfile(tempout) + let result['stderr'] = s:readfile(temperr) " If we just executed a synchronous command and the caller didn't " specifically ask us *not* to check the exit code of the external " command, we'll do so now. if get(a:options, 'check', 1) && exit_code != 0 - let msg = "os.vim %s: External command failed with exit code %d: %s" - throw printf(msg, g:xolox#misc#os#version, result['exit_code'], result['command']) + " Prepare an error message with enough details so the user can investigate. + let msg = printf("os.vim %s: External command failed with exit code %d!", g:xolox#misc#os#version, result['exit_code']) + let msg .= printf("\nCommand line: %s", result['command']) + " If the external command reported an error, we'll include it in our message. + if !empty(result['stderr']) + " This is where we would normally expect to find an error message. + let msg .= printf("\nOutput on standard output stream:\n%s", join(result['stderr'], "\n")) + elseif !empty(result['stdout']) + " Exuberant Ctags on Windows XP reports errors on standard output :-x. + let msg .= printf("\nOutput on standard error stream:\n%s", join(result['stdout'], "\n")) + endif + throw msg endif - " Return the results as a dictionary with three key/value pairs. - let result['exit_code'] = exit_code - let result['stdout'] = s:readfile(tempout) - let result['stderr'] = s:readfile(temperr) endif return result diff --git a/autoload/xolox/misc/path.vim b/autoload/xolox/misc/path.vim index 6ad8be4..15e11d6 100644 --- a/autoload/xolox/misc/path.vim +++ b/autoload/xolox/misc/path.vim @@ -1,53 +1,72 @@ -" Vim auto-load script +" Pathname manipulation functions. +" " Author: Peter Odding -" Last Change: April 28, 2013 +" Last Change: May 19, 2013 " URL: http://peterodding.com/code/vim/misc/ let s:windows_compatible = has('win32') || has('win64') let s:mac_os_x_compatible = has('macunix') function! xolox#misc#path#which(...) " {{{1 - " Scan the executable search path for programs. + " Scan the executable search path (`$PATH`) for one or more external + " programs. Expects one or more string arguments with program names. Returns + " a list with the absolute pathnames of all found programs. Here's an + " example: + " + " :echo xolox#misc#path#which('gvim', 'vim') + " ['/usr/local/bin/gvim', + " '/usr/bin/gvim', + " '/usr/local/bin/vim', + " '/usr/bin/vim'] let extensions = s:windows_compatible ? split($PATHEXT, ';') : [''] let matches = [] let checked = {} - for directory in split($PATH, s:windows_compatible ? ';' : ':') - let directory = xolox#misc#path#absolute(directory) - if !has_key(checked, directory) - if isdirectory(directory) - for program in a:000 - for extension in extensions - let path = xolox#misc#path#merge(directory, program . extension) - if executable(path) - call add(matches, path) - endif - endfor - endfor - endif - let checked[directory] = 1 - endif + for program in a:000 + for extension in extensions + for directory in split($PATH, s:windows_compatible ? ';' : ':') + let directory = xolox#misc#path#absolute(directory) + if isdirectory(directory) + let path = xolox#misc#path#merge(directory, program . extension) + if executable(path) + call add(matches, path) + endif + endif + endfor + endfor endfor return matches endfunction function! xolox#misc#path#split(path) " {{{1 - " Split a pathname into a list of path components. + " Split a pathname (the first and only argument) into a list of pathname + " components. + " + " On Windows, pathnames starting with two slashes or backslashes are UNC + " paths where the leading slashes are significant... In this case we split + " like this: + " + " - Input: `'//server/share/directory'` + " - Result: `['//server', 'share', 'directory']` + " + " Everything except Windows is treated like UNIX until someone has a better + " suggestion :-). In this case we split like this: + " + " - Input: `'/foo/bar/baz'` + " - Result: `['/', 'foo', 'bar', 'baz']` + " + " To join a list of pathname components back into a single pathname string, + " use the `xolox#misc#path#join()` function. if type(a:path) == type('') if s:windows_compatible if a:path =~ '^[\/][\/]' - " On Windows, pathnames starting with two slashes or backslashes are - " UNC paths where the leading slashes are significant... In this case - " we split like this: - " '//server/share/directory' -> ['//server', 'share', 'directory'] + " UNC pathname. return split(a:path, '\%>2c[\/]\+') else " If it's not a UNC path we can simply split on slashes & backslashes. return split(a:path, '[\/]\+') endif else - " Everything except Windows is treated like UNIX until someone - " has a better suggestion :-). In this case we split like this: - " '/foo/bar/baz' -> ['/', 'foo', 'bar', 'baz'] + " Everything else is treated as UNIX. let absolute = (a:path =~ '^/') let segments = split(a:path, '/\+') return absolute ? insert(segments, '/') : segments @@ -57,7 +76,10 @@ function! xolox#misc#path#split(path) " {{{1 endfunction function! xolox#misc#path#join(parts) " {{{1 - " Join a list of pathname components into a single pathname. + " Join a list of pathname components (the first and only argument) into a + " single pathname string. This is the counterpart to the + " `xolox#misc#path#split()` function and it expects a list of pathname + " components as returned by `xolox#misc#path#split()`. if type(a:parts) == type([]) if s:windows_compatible return join(a:parts, xolox#misc#path#directory_separator()) @@ -78,9 +100,9 @@ function! xolox#misc#path#directory_separator() " {{{1 endfunction function! xolox#misc#path#absolute(path) " {{{1 - " Canonicalize and resolve a pathname, regardless of whether it exists. This - " is intended to support string comparison to determine whether two pathnames - " point to the same directory or file. + " Canonicalize and resolve a pathname, *regardless of whether it exists*. + " This is intended to support string comparison to determine whether two + " pathnames point to the same directory or file. if type(a:path) == type('') let path = a:path " Make the pathname absolute. @@ -110,7 +132,8 @@ function! xolox#misc#path#absolute(path) " {{{1 endfunction function! xolox#misc#path#relative(path, base) " {{{1 - " Make an absolute pathname relative. + " Make an absolute pathname (the first argument) relative to a directory + " (the second argument). let path = xolox#misc#path#split(a:path) let base = xolox#misc#path#split(a:base) while path != [] && base != [] && path[0] == base[0] @@ -123,9 +146,9 @@ endfunction function! xolox#misc#path#merge(parent, child, ...) " {{{1 - " Join a directory and filename into a single pathname. - " TODO Use isabs()! + " Join a directory pathname and filename into a single pathname. if type(a:parent) == type('') && type(a:child) == type('') + " TODO Use xolox#misc#path#is_relative()? if s:windows_compatible let parent = substitute(a:parent, '[\\/]\+$', '', '') let child = substitute(a:child, '^[\\/]\+', '', '') @@ -158,7 +181,8 @@ function! xolox#misc#path#commonprefix(paths) " {{{1 endfunction function! xolox#misc#path#encode(path) " {{{1 - " Encode a pathname so it can be used as a filename. + " Encode a pathname so it can be used as a filename. This uses URL encoding + " to encode special characters. if s:windows_compatible let mask = '[*|\\/:"<>?%]' elseif s:mac_os_x_compatible @@ -171,7 +195,7 @@ endfunction function! xolox#misc#path#decode(encoded_path) " {{{1 - " Decode a pathname previously encoded with xolox#misc#path#encode(). + " Decode a pathname previously encoded with `xolox#misc#path#encode()`. return substitute(a:encoded_path, '%\(\x\x\?\)', '\=nr2char("0x" . submatch(1))', 'g') endfunction @@ -188,7 +212,8 @@ else endif function! xolox#misc#path#is_relative(path) " {{{1 - " Check whether a path is relative. + " Returns true (1) when the pathname given as the first argument is + " relative, false (0) otherwise. if a:path =~ '^\w\+://' return 0 elseif s:windows_compatible @@ -199,7 +224,7 @@ function! xolox#misc#path#is_relative(path) " {{{1 endfunction function! xolox#misc#path#tempdir() " {{{1 - " Create a temporary directory and return the path. + " Create a temporary directory and return the pathname of the directory. if !exists('s:tempdir_counter') let s:tempdir_counter = 1 endif diff --git a/autoload/xolox/misc/str.vim b/autoload/xolox/misc/str.vim index 74a05aa..901696c 100644 --- a/autoload/xolox/misc/str.vim +++ b/autoload/xolox/misc/str.vim @@ -1,11 +1,17 @@ -" Vim auto-load script +" String handling. +" " Author: Peter Odding -" Last Change: June 14, 2011 +" Last Change: May 19, 2013 " URL: http://peterodding.com/code/vim/misc/ -" Trim whitespace from start and end of string. +function! xolox#misc#str#compact(s) + " Compact whitespace in the string given as the first argument. + return join(split(a:s), " ") +endfunction function! xolox#misc#str#trim(s) + " Trim all whitespace from the start and end of the string given as the + " first argument. return substitute(a:s, '^\_s*\(.\{-}\)\_s*$', '\1', '') endfunction diff --git a/autoload/xolox/misc/timer.vim b/autoload/xolox/misc/timer.vim index 151972d..d7fc32d 100644 --- a/autoload/xolox/misc/timer.vim +++ b/autoload/xolox/misc/timer.vim @@ -1,6 +1,7 @@ -" Vim auto-load script +" Timing of long during operations. +" " Author: Peter Odding -" Last Change: March 15, 2011 +" Last Change: May 19, 2013 " URL: http://peterodding.com/code/vim/misc/ if !exists('g:timer_enabled') @@ -13,24 +14,33 @@ endif let s:has_reltime = has('reltime') -" Start a timer. - -function! xolox#misc#timer#start() +function! xolox#misc#timer#start() " {{{1 + " Start a timer. This returns a list which can later be passed to + " `xolox#misc#timer#stop()`. if g:timer_enabled || &verbose >= g:timer_verbosity return s:has_reltime ? reltime() : [localtime()] endif return [] endfunction -" Stop a timer and print the elapsed time (only if the user is interested). - -function! xolox#misc#timer#stop(...) +function! xolox#misc#timer#stop(...) " {{{1 + " Show a formatted debugging message to the user, if the user has enabled + " increased verbosity by setting Vim's ['verbose'] [verbose] option to one + " (1) or higher. + " + " This function has the same argument handling as Vim's [printf()] [printf] + " function with one difference: At the point where you want the elapsed time + " to be embedded, you write `%s` and you pass the list returned by + " `xolox#misc#timer#start()` as an argument. + " + " [verbose]: http://vimdoc.sourceforge.net/htmldoc/options.html#'verbose' + " [printf]: http://vimdoc.sourceforge.net/htmldoc/eval.html#printf() if (g:timer_enabled || &verbose >= g:timer_verbosity) call call('xolox#misc#msg#info', map(copy(a:000), 's:convert_value(v:val)')) endif endfunction -function! s:convert_value(value) +function! s:convert_value(value) " {{{1 if type(a:value) != type([]) return a:value elseif !empty(a:value) @@ -49,7 +59,10 @@ endfunction let s:units = [['day', 60 * 60 * 24], ['hour', 60 * 60], ['minute', 60], ['second', 1]] -function! xolox#misc#timer#format_timespan(ts) +function! xolox#misc#timer#format_timespan(ts) " {{{1 + " Format a time stamp (a string containing a formatted floating point + " number) into a human friendly format, for example 70 seconds is phrased as + " "1 minute and 10 seconds". " Convert timespan to integer. let seconds = a:ts + 0 diff --git a/autoload/xolox/session.vim b/autoload/xolox/session.vim index 55e1520..6ce5be6 100644 --- a/autoload/xolox/session.vim +++ b/autoload/xolox/session.vim @@ -1,11 +1,11 @@ " Vim script " Author: Peter Odding -" Last Change: May 13, 2013 +" Last Change: May 20, 2013 " URL: http://peterodding.com/code/vim/session/ -let g:xolox#session#version = '2.3' +let g:xolox#session#version = '2.3.1' -call xolox#misc#compat#check('session', 3) +call xolox#misc#compat#check('session.vim', g:xolox#session#version, 7) " Public API for session persistence. {{{1 diff --git a/doc/session.txt b/doc/session.txt index 270fd63..a98d456 100644 --- a/doc/session.txt +++ b/doc/session.txt @@ -457,8 +457,8 @@ If you like the script please vote for it on Vim Online [12]. *session-license* License ~ -This software is licensed under the MIT license [13]. Copyright 2013 Peter -Odding . +This software is licensed under the MIT license [13]. Š 2013 Peter Odding +. =============================================================================== *sample-session-script*