1
0
mirror of https://github.com/amix/vimrc synced 2025-07-06 16:05:01 +08:00

Cleaning deps.

This commit is contained in:
Maksim Pecherskiy
2014-08-07 19:42:41 -04:00
parent 4541dd93ef
commit 2deb035254
266 changed files with 26588 additions and 31 deletions

Submodule sources_non_forked/vim-misc deleted from 8551f2b9de

View File

@ -0,0 +1 @@
doc/tags

View File

@ -0,0 +1,672 @@
# Miscellaneous auto-load Vim scripts
The vim-misc plug-in contains Vim scripts that are used by most of the [Vim
plug-ins I've written] [plugins] yet don't really belong with any single one of
the plug-ins. Basically it's an extended standard library of Vim script
functions that I wrote during the development of my Vim profile and plug-ins.
In the past these scripts were bundled with each plug-in, however that turned
out to be a maintenance nightmare for me. That's why the miscellaneous scripts
are now a proper plug-in with their own page on Vim Online.
Because the miscellaneous scripts are no longer bundled with my Vim plug-ins,
users are now required to install the miscellaneous scripts separately. This is
unfortunate for users who are upgrading from a previous release that did bundle
the miscellaneous scripts, but I don't see any way around this. Sorry!
## Installation
Unzip the most recent [ZIP archive] [] file inside your Vim profile
directory (usually this is `~/.vim` on UNIX and `%USERPROFILE%\vimfiles` on
Windows), restart Vim and execute the command `:helptags ~/.vim/doc` (use
`:helptags ~\vimfiles\doc` instead on Windows).
If you prefer you can also use [Pathogen] [], [Vundle] [] or a similar tool to
install & update the plug-in using a local clone of the git repository.
## Function documentation
Below is the documentation for the functions included in the miscellaneous
scripts. Anyone is free to use these functions in their own Vim profile and/or
plug-ins. I care about backwards compatibility so won't break it without a good
reason to do so.
For those who are curious: The function descriptions given below were extracted
from the source code of the miscellaneous scripts using the Python module
`vimdoctool.py` included in [vim-tools] [].
<!-- Start of generated documentation -->
The documentation of the 80 functions below was extracted from
15 Vim scripts on July 20, 2013 at 10:41.
### Handling of special buffers
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
#### The `xolox#misc#buffer#is_empty()` function
Checks if the current buffer is an empty, unchanged buffer which can be
reused. Returns 1 if an empty buffer is found, 0 otherwise.
#### The `xolox#misc#buffer#prepare()` function
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'
#### The `xolox#misc#buffer#lock()` function
Lock a special buffer so that its contents can no longer be edited.
#### The `xolox#misc#buffer#unlock()` function
Unlock a special buffer so that its content can be updated.
### Tab completion for user defined commands
#### The `xolox#misc#complete#keywords()` function
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(<f-args>)
### String escaping functions
#### The `xolox#misc#escape#pattern()` function
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
#### The `xolox#misc#escape#substitute()` function
Takes a single string argument and converts it into a [:substitute]
[subcmd] / [substitute()] [subfun] replacement string that inserts the
given string literally.
#### The `xolox#misc#escape#shell()` function
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'
### Human friendly string formatting for Vim
#### The `xolox#misc#format#pluralize()` function
Concatenate a counter (the first argument, expected to be an integer) with
a singular or plural label (the second and third arguments, both expected
to be strings).
#### The `xolox#misc#format#timestamp()` function
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".
### List handling functions
#### The `xolox#misc#list#unique()` function
Remove duplicate values from the given list in-place (preserves order).
#### The `xolox#misc#list#binsert()` function
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()
### Functions to interact with the user
#### The `xolox#misc#msg#info()` function
Show a formatted informational message to the user.
This function has the same argument handling as Vim's [printf()] []
function with one notable difference: Any arguments which are not numbers
or strings are coerced to strings using Vim's [string()] [] function.
In the case of `xolox#misc#msg#info()`, automatic string coercion simply
makes the function a bit easier to use.
[printf()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#printf()
[string()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#string()
#### The `xolox#misc#msg#warn()` function
Show a formatted warning message to the user.
This function has the same argument handling as the
`xolox#misc#msg#info()` function.
#### The `xolox#misc#msg#debug()` function
Show a formatted debugging message to the user, *if the user has enabled
increased verbosity by setting Vim's ['verbose'] [] option to one
(1) or higher*.
This function has the same argument handling as the
`xolox#misc#msg#info()` function.
In the case of `xolox#misc#msg#debug()`, automatic string coercion
provides lazy evaluation in the sense that complex data structures are
only converted to strings when the user has enabled increased verbosity.
['verbose']: http://vimdoc.sourceforge.net/htmldoc/options.html#'verbose'
### Integration between Vim and its environment
#### The `xolox#misc#open#file()` function
Given a pathname or URL 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.
#### The `xolox#misc#open#url()` function
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)
### Vim and plug-in option handling
#### The `xolox#misc#option#get()` function
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.
#### The `xolox#misc#option#split()` function
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'
#### The `xolox#misc#option#join()` function
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.
#### The `xolox#misc#option#split_tags()` function
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'
#### The `xolox#misc#option#join_tags()` function
Customized version of `xolox#misc#option#join()` with specialized
handling for Vim's ['tags' option] [tags].
#### The `xolox#misc#option#eval_tags()` function
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.
### Operating system interfaces
#### The `xolox#misc#os#is_mac()` function
Returns 1 (true) when on Mac OS X, 0 (false) otherwise. You would expect
this to simply check the Vim feature list, but for some obscure reason the
`/usr/bin/vim` included in Mac OS X (verified on version 10.7.5) returns 0
(false) in response to `has('mac')`, so we check the output of `uname`
to avoid false negatives.
#### The `xolox#misc#os#is_win()` function
Returns 1 (true) when on Microsoft Windows, 0 (false) otherwise.
#### The `xolox#misc#os#find_vim()` function
Returns the program name of Vim as a string. On Windows and UNIX this just
[v:progname] [] as an absolute pathname while on Mac OS X there is
some special magic to find MacVim's executable even though it's usually
not on the executable search path. If you want, you can override the
value returned from this function by setting the global variable
`g:xolox#misc#os#vim_progname`.
By default the choice of console Vim vs graphical Vim is made based on
the value of [v:progname] [], but if you have a preference you can pass
the string `vim` or `gvim` as the first and only argument.
[v:progname]: http://vimdoc.sourceforge.net/htmldoc/eval.html#v:progname
#### The `xolox#misc#os#exec()` function
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/
#### The `xolox#misc#os#can_use_dll()` function
If a) we're on Microsoft Windows, b) the vim-shell plug-in is installed
and c) the compiled DLL included in vim-shell works, we can use the
vim-shell plug-in to execute external commands! Returns 1 (true)
if we can use the DLL, 0 (false) otherwise.
### Pathname manipulation functions
#### The `xolox#misc#path#which()` function
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']
#### The `xolox#misc#path#split()` function
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.
#### The `xolox#misc#path#join()` function
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()`.
#### The `xolox#misc#path#directory_separator()` function
Find the preferred directory separator for the platform and settings.
#### The `xolox#misc#path#absolute()` function
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.
#### The `xolox#misc#path#relative()` function
Make an absolute pathname (the first argument) relative to a directory
(the second argument).
#### The `xolox#misc#path#merge()` function
Join a directory pathname and filename into a single pathname.
#### The `xolox#misc#path#commonprefix()` function
Find the common prefix of path components in a list of pathnames.
#### The `xolox#misc#path#encode()` function
Encode a pathname so it can be used as a filename. This uses URL encoding
to encode special characters.
#### The `xolox#misc#path#decode()` function
Decode a pathname previously encoded with `xolox#misc#path#encode()`.
#### The `xolox#misc#path#is_relative()` function
Returns true (1) when the pathname given as the first argument is
relative, false (0) otherwise.
#### The `xolox#misc#path#tempdir()` function
Create a temporary directory and return the pathname of the directory.
### String handling
#### The `xolox#misc#str#slug()` function
Convert a string to a "slug" - something that can be safely used in
filenames and URLs without worrying about quoting/escaping of special
characters.
#### The `xolox#misc#str#ucfirst()` function
Uppercase the first character in a string (the first argument).
#### The `xolox#misc#str#compact()` function
Compact whitespace in a string (the first argument).
#### The `xolox#misc#str#trim()` function
Trim all whitespace from the start and end of a string (the first
argument).
#### The `xolox#misc#str#indent()` function
Indent all lines in a multi-line string (the first argument) with a
specific number of *space characters* (the second argument, an integer).
#### The `xolox#misc#str#dedent()` function
Remove common whitespace from a multi line string.
### Test runner & infrastructure for Vim plug-ins
The Vim auto-load script `autoload/xolox/misc/test.vim` contains
infrastructure that can be used to run an automated Vim plug-in test suite.
It provides a framework for running test functions, keeping track of the
test status, making assertions and reporting test results to the user.
#### The `xolox#misc#test#reset()` function
Reset counters for executed tests and passed/failed assertions.
#### The `xolox#misc#test#summarize()` function
Print a summary of test results, to be interpreted interactively.
#### The `xolox#misc#test#wrap()` function
Call a function in a try/catch block and prevent exceptions from bubbling.
The name of the function should be passed as the first and only argument;
it should be a string containing the name of a Vim auto-load function.
#### The `xolox#misc#test#passed()` function
Record a test which succeeded.
#### The `xolox#misc#test#failed()` function
Record a test which failed.
#### The `xolox#misc#test#assert_true()` function
Check whether an expression is true.
#### The `xolox#misc#test#assert_equals()` function
Check whether two values are the same.
#### The `xolox#misc#test#assert_same_type()` function
Check whether two values are of the same type.
### Tests for the miscellaneous Vim scripts
The Vim auto-load script `autoload/xolox/misc/tests.vim` contains the
automated test suite of the miscellaneous Vim scripts. Right now the
coverage is not very high yet, but this will improve over time.
#### The `xolox#misc#tests#run()` function
Run the automated test suite of the miscellaneous Vim scripts. To be used
interactively. Intended to be safe to execute irrespective of context.
#### The `xolox#misc#tests#pattern_escaping()` function
Test escaping of regular expression patterns with
`xolox#misc#escape#pattern()`.
#### The `xolox#misc#tests#substitute_escaping()` function
Test escaping of substitution strings with
`xolox#misc#escape#substitute()`.
#### The `xolox#misc#tests#shell_escaping()` function
Test escaping of shell arguments with `xolox#misc#escape#shell()`.
#### The `xolox#misc#tests#making_a_list_unique()` function
Test removing of duplicate values from lists with
`xolox#misc#list#unique()`.
#### The `xolox#misc#tests#binary_insertion()` function
Test the binary insertion algorithm implemented in
`xolox#misc#list#binsert()`.
#### The `xolox#misc#tests#getting_configuration_options()` function
Test getting of scoped plug-in configuration "options" with
`xolox#misc#option#get()`.
#### The `xolox#misc#tests#splitting_of_multi_valued_options()` function
Test splitting of multi-valued Vim options with
`xolox#misc#option#split()`.
#### The `xolox#misc#tests#joining_of_multi_valued_options()` function
Test joining of multi-valued Vim options with `xolox#misc#option#join()`.
#### The `xolox#misc#tests#finding_vim_on_the_search_path()` function
Test looking up Vim's executable on the search path using [v:progname] []
with `xolox#misc#os#find_vim()`.
[v:progname]: http://vimdoc.sourceforge.net/htmldoc/eval.html#v:progname
#### The `xolox#misc#tests#synchronous_command_execution()` function
Test basic functionality of synchronous command execution with
`xolox#misc#os#exec()`.
#### The `xolox#misc#tests#synchronous_command_execution_with_stderr()` function
Test basic functionality of synchronous command execution with
`xolox#misc#os#exec()` including the standard error stream (not available
on Windows when vim-shell is not installed).
#### The `xolox#misc#tests#synchronous_command_execution_with_raising_of_errors()` function
Test raising of errors during synchronous command execution with
`xolox#misc#os#exec()`.
#### The `xolox#misc#tests#synchronous_command_execution_without_raising_errors()` function
Test synchronous command execution without raising of errors with
`xolox#misc#os#exec()`.
#### The `xolox#misc#tests#asynchronous_command_execution()` function
Test the basic functionality of asynchronous command execution with
`xolox#misc#os#exec()`. This runs the external command `mkdir` and tests
that the side effect of creating the directory takes place. This might
seem like a peculiar choice, but it's one of the few 100% portable
commands (Windows + UNIX) that doesn't involve input/output streams.
#### The `xolox#misc#tests#string_case_transformation()` function
Test string case transformation with `xolox#misc#str#ucfirst()`.
#### The `xolox#misc#tests#string_whitespace_compaction()` function
Test compaction of whitespace in strings with `xolox#misc#str#compact()`.
#### The `xolox#misc#tests#string_whitespace_trimming()` function
Test trimming of whitespace in strings with `xolox#misc#str#trim()`.
#### The `xolox#misc#tests#multiline_string_dedent()` function
Test dedenting of multi-line strings with `xolox#misc#str#dedent()`.
#### The `xolox#misc#tests#version_string_parsing()` function
Test parsing of version strings with `xolox#misc#version#parse()`.
#### The `xolox#misc#tests#version_string_comparison()` function
Test comparison of version strings with `xolox#misc#version#at_least()`.
### Timing of long during operations
#### The `xolox#misc#timer#start()` function
Start a timer. This returns a list which can later be passed to
`xolox#misc#timer#stop()`.
#### The `xolox#misc#timer#stop()` function
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()
#### The `xolox#misc#timer#force()` function
Show a formatted message to the user. 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.
### Version string handling
#### The `xolox#misc#version#parse()` function
Convert a version string to a list of integers.
#### The `xolox#misc#version#at_least()` function
Check whether the second version string is equal to or greater than the
first version string. Returns 1 (true) when it is, 0 (false) otherwise.
<!-- End of generated documentation -->
## Contact
If you have questions, bug reports, suggestions, etc. the author can be
contacted at <peter@peterodding.com>. The latest version is available at
<http://peterodding.com/code/vim/misc> and <http://github.com/xolox/vim-misc>.
If you like the script please vote for it on [Vim Online] [].
## License
This software is licensed under the [MIT license] [].
© 2013 Peter Odding &lt;<peter@peterodding.com>&gt;.
[MIT license]: http://en.wikipedia.org/wiki/MIT_License
[Pathogen]: http://www.vim.org/scripts/script.php?script_id=2332
[plugins]: http://peterodding.com/code/vim/
[repository]: https://github.com/xolox/vim-misc
[Vim Online]: http://www.vim.org/scripts/script.php?script_id=4597
[vim-tools]: http://peterodding.com/code/vim/tools/
[Vundle]: https://github.com/gmarik/vundle
[ZIP archive]: http://peterodding.com/code/vim/downloads/misc.zip

View File

@ -0,0 +1 @@
{"vim_script_nr": 4597, "dependencies": {}, "homepage": "http://peterodding.com/code/vim/misc", "name": "vim-misc"}

View File

@ -0,0 +1,7 @@
" The version of my miscellaneous scripts.
"
" Author: Peter Odding <peter@peterodding.com>
" Last Change: July 20, 2013
" URL: http://peterodding.com/code/vim/misc/
let g:xolox#misc#version = '1.8.5'

View File

@ -0,0 +1,80 @@
" Handling of special buffers
"
" Author: Peter Odding <peter@peterodding.com>
" 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
" 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, 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}
elseif type(a:1) == type({})
let options = a:1
else
throw "Invalid arguments"
endif
let winnr = 1
let found = 0
for bufnr in tabpagebuflist()
if xolox#misc#path#equals(options['path'], bufname(bufnr))
execute winnr . 'wincmd w'
let found = 1
break
else
let winnr += 1
endif
endfor
if !(found || xolox#misc#buffer#is_empty())
vsplit
endif
silent execute 'edit' fnameescape(options['path'])
lcd " clear working directory
setlocal buftype=nofile bufhidden=hide noswapfile
let &l:statusline = '[' . options['name'] . ']'
call xolox#misc#buffer#unlock()
silent %delete
endfunction
function! xolox#misc#buffer#lock() " {{{1
" Lock a special buffer so that its contents can no longer be edited.
setlocal readonly nomodifiable nomodified
endfunction
function! xolox#misc#buffer#unlock() " {{{1
" Unlock a special buffer so that its content can be updated.
setlocal noreadonly modifiable
endfunction

View File

@ -0,0 +1,22 @@
" Tab completion for user defined commands.
"
" Author: Peter Odding <peter@peterodding.com>
" Last Change: May 19, 2013
" URL: http://peterodding.com/code/vim/misc/
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(<f-args>)
let words = {}
for line in getline(1, '$')
for word in split(line, '\W\+')
let words[word] = 1
endfor
endfor
return sort(keys(filter(words, 'v:key =~# a:arglead')))
endfunction
" vim: ts=2 sw=2 et

View File

@ -0,0 +1,56 @@
" String escaping functions.
"
" Author: Peter Odding <peter@peterodding.com>
" Last Change: May 19, 2013
" URL: http://peterodding.com/code/vim/misc/
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')
endif
return ''
endfunction
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')
endif
return ''
endfunction
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
set noshellslash
return shellescape(a:string)
finally
let &shellslash = ssl_save
endtry
else
return shellescape(a:string)
endif
endfunction
" vim: ts=2 sw=2 et

View File

@ -0,0 +1,46 @@
" Human friendly string formatting for Vim.
"
" Author: Peter Odding <peter@peterodding.com>
" Last Change: June 2, 2013
" URL: http://peterodding.com/code/vim/misc/
function! xolox#misc#format#pluralize(count, singular, plural) " {{{1
" Concatenate a counter (the first argument, expected to be an integer) with
" a singular or plural label (the second and third arguments, both expected
" to be strings).
if a:count == 0
return printf('no %s', a:plural)
else
return printf('%i %s', a:count, a:count == 1 ? a:singular : a:plural)
endif
endfunction
function! xolox#misc#format#timestamp(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".
let seconds = a:ts + 0
" Fast common case with extra precision from reltime().
if seconds < 5
let extract = matchstr(a:ts, '^\d\+\(\.0*[1-9][1-9]\?\)\?')
if extract =~ '[123456789]'
return extract . ' second' . (extract != '1' ? 's' : '')
endif
endif
" Generic but slow code.
let result = []
for [name, size] in [['day', 60 * 60 * 24], ['hour', 60 * 60], ['minute', 60], ['second', 1]]
if seconds >= size
let counter = seconds / size
let seconds = seconds % size
let suffix = counter != 1 ? 's' : ''
call add(result, printf('%i %s%s', counter, name, suffix))
endif
endfor
" Format the resulting text?
if len(result) == 1
return result[0]
else
return join(result[0:-2], ', ') . ' and ' . result[-1]
endif
endfunction

View File

@ -0,0 +1,42 @@
" List handling functions.
"
" Author: Peter Odding <peter@peterodding.com>
" Last Change: June 2, 2013
" URL: http://peterodding.com/code/vim/misc/
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
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
function! s:binsert_r(list, low, high, value, ignorecase)
let mid = a:low + (a:high - a:low) / 2
if a:low == a:high
return a:low
elseif a:ignorecase ? a:value >? a:list[mid] : a:value > a:list[mid]
return s:binsert_r(a:list, mid + 1, a:high, a:value, a:ignorecase)
elseif a:ignorecase ? a:value <? a:list[mid] : a:value < a:list[mid]
return s:binsert_r(a:list, a:low, mid, a:value, a:ignorecase)
else
return mid
endif
endfunction
" vim: ts=2 sw=2 et

View File

@ -0,0 +1,119 @@
" Functions to interact with the user.
"
" Author: Peter Odding <peter@peterodding.com>
" Last Change: June 2, 2013
" URL: http://peterodding.com/code/vim/misc/
if !exists('g:xolox_message_buffer')
" For when I lose my :messages history :-\
let g:xolox_message_buffer = 100
endif
if !exists('g:xolox_messages')
let g:xolox_messages = []
endif
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()] []
" function with one notable difference: Any arguments which are not numbers
" or strings are coerced to strings using Vim's [string()] [] function.
"
" In the case of `xolox#misc#msg#info()`, automatic string coercion simply
" makes the function a bit easier to use.
"
" [printf()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#printf()
" [string()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#string()
call s:show_message('title', a:000)
endfunction
function! xolox#misc#msg#warn(...) " {{{1
" Show a formatted warning message to the user.
"
" This function has the same argument handling as the
" `xolox#misc#msg#info()` function.
call s:show_message('warningmsg', a:000)
endfunction
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'] [] option to one
" (1) or higher*.
"
" This function has the same argument handling as the
" `xolox#misc#msg#info()` function.
"
" In the case of `xolox#misc#msg#debug()`, automatic string coercion
" provides lazy evaluation in the sense that complex data structures are
" only converted to strings when the user has enabled increased verbosity.
"
" ['verbose']: http://vimdoc.sourceforge.net/htmldoc/options.html#'verbose'
if &vbs >= 1
call s:show_message('question', a:000)
endif
endfunction
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]
elseif nargs >= 2
let args = map(copy(a:args), 's:coerce_argument(v:val)')
let message = call('printf', args)
endif
if exists('message')
try
" Temporarily disable Vim's |hit-enter| prompt and mode display.
if !exists('s:more_save')
let s:more_save = &more
let s:ruler_save = &ruler
let s:smd_save = &showmode
endif
set nomore noshowmode
if winnr('$') == 1 | set noruler | endif
augroup PluginXoloxHideMode
autocmd! CursorHold,CursorHoldI * call s:clear_message()
augroup END
execute 'echohl' a:hlgroup
" Redraw to avoid |hit-enter| prompt.
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
call remove(g:xolox_messages, 0)
endif
endif
finally
" Always clear message highlighting, even when interrupted by Ctrl-C.
echohl none
endtry
endif
endfunction
function! s:coerce_argument(value) " {{{1
" Callback to coerce printf() arguments into strings.
let value_type = type(a:value)
if value_type != type(0) && value_type != type('')
return string(a:value)
else
return a:value
endif
endfunction
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
let &ruler = s:ruler_save
unlet s:more_save s:ruler_save s:smd_save
autocmd! PluginXoloxHideMode
augroup! PluginXoloxHideMode
endfunction
" vim: ts=2 sw=2 et

View File

@ -0,0 +1,100 @@
" Integration between Vim and its environment.
"
" Author: Peter Odding <peter@peterodding.com>
" Last Change: June 19, 2013
" URL: http://peterodding.com/code/vim/misc/
let s:enoimpl = "vim-misc %s: %s() hasn't been implemented for your platform! If you have suggestions, please get in touch at https://github.com/xolox/vim-misc/issues"
let s:handlers = ['gnome-open', 'kde-open', 'exo-open', 'xdg-open']
function! xolox#misc#open#file(location, ...) " {{{1
" Given a pathname or URL 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:location)
catch /^Vim\%((\a\+)\)\=:E117/
let command = '!start CMD /C START "" %s'
silent execute printf(command, xolox#misc#escape#shell(a:location))
endtry
return
elseif xolox#misc#os#is_mac()
call xolox#misc#msg#debug("vim-misc %s: Detected Mac OS X, using 'open' command to open %s ..", g:xolox#misc#version, string(a:location))
let cmd = 'open ' . shellescape(a:location) . ' 2>&1'
call s:handle_error(cmd, system(cmd))
return
else
for handler in s:handlers + a:000
if executable(handler)
call xolox#misc#msg#debug("vim-misc %s: Using '%s' to open '%s'.", g:xolox#misc#version, handler, a:location)
let cmd = shellescape(handler) . ' ' . shellescape(a:location) . ' 2>&1'
call s:handle_error(cmd, system(cmd))
return
endif
endfor
endif
throw printf(s:enoimpl, g:xolox#misc#version, 'xolox#misc#open#file')
endfunction
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\+://'
call xolox#misc#msg#debug("vim-misc %s: The URL %s doesn't contain a scheme, improvising ..", g:xolox#misc#version, string(url))
if url !~ '@'
call xolox#misc#msg#debug("vim-misc %s: Defaulting to http:// URL scheme ..", g:xolox#misc#version)
let url = 'http://' . url
elseif url !~ '^mailto:'
call xolox#misc#msg#debug("vim-misc %s: Defaulting to mailto: URL scheme ..", g:xolox#misc#version)
let url = 'mailto:' . url
endif
endif
let on_unix = has('unix')
let not_on_mac = !xolox#misc#os#is_mac()
let no_gui_available = (has('gui_running') == 0 && $DISPLAY == '')
if on_unix && not_on_mac && no_gui_available
call xolox#misc#msg#debug("vim-misc %s: Using command line web browser because no GUI seems to be available ..", g:xolox#misc#version)
for browser in ['lynx', 'links', 'w3m']
call xolox#misc#msg#debug("vim-misc %s: Checking whether %s command line web browser is installed ..", g:xolox#misc#version, string(browser))
if executable(browser)
call xolox#misc#msg#debug("vim-misc %s: Found %s, using it to open %s ..", g:xolox#misc#version, string(browser), string(url))
execute '!' . browser fnameescape(url)
call s:handle_error(browser . ' ' . url, '')
return
endif
endfor
endif
call xolox#misc#msg#debug("vim-misc %s: Defaulting to GUI web browser to open %s ..", g:xolox#misc#version, string(url))
call xolox#misc#open#file(url, 'firefox', 'google-chrome')
endfunction
function! s:handle_error(cmd, output) " {{{1
if v:shell_error
let message = "vim-misc %s: Failed to execute program! (command line: %s%s)"
let output = strtrans(xolox#misc#str#trim(a:output))
if output != ''
let output = ", output: " . string(output)
endif
throw printf(message, g:xolox#misc#version, a:cmd, output)
endif
endfunction
" vim: et ts=2 sw=2 fdm=marker

View File

@ -0,0 +1,115 @@
" Vim and plug-in option handling.
"
" Author: Peter Odding <peter@peterodding.com>
" Last Change: June 2, 2013
" URL: http://peterodding.com/code/vim/misc/
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)
elseif exists('g:' . a:name)
" Global variable.
return eval('g:' . a:name)
elseif exists('a:1')
" Default value.
return a:1
endif
endfunction
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
function! s:unescape(s)
return substitute(a:s, '\\\([\\,]\)', '\1', 'g')
endfunction
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, ',')
endfunction
function! s:escape(s)
return escape(a:s, ',\')
endfunction
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
function! s:unescape_tags(s)
return substitute(a:s, '\\\([\\, ]\)', '\1', 'g')
endfunction
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, ',')
endfunction
function! s:escape_tags(s)
return escape(a:s, ', ')
endfunction
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 : 0
for pattern in xolox#misc#option#split_tags(a:value)
" Make buffer relative pathnames absolute.
if pattern =~ '^\./'
let suffix = matchstr(pattern, '^./\zs.*$')
let pattern = xolox#misc#path#merge(expand('%:p:h'), suffix)
endif
" Make working directory relative pathnames absolute.
if xolox#misc#path#is_relative(pattern)
let pattern = xolox#misc#path#merge(getcwd(), pattern)
endif
" Ignore the trailing `;' for recursive upwards searching because we
" always want the most specific pathname available.
let pattern = substitute(pattern, ';$', '', '')
" Expand the pattern.
call extend(pathnames, split(expand(pattern), "\n"))
if first_only && !empty(pathnames)
return pathnames[0]
endif
endfor
return first_only ? '' : pathnames
endfunction
" vim: ts=2 sw=2 et

View File

@ -0,0 +1,271 @@
" Operating system interfaces.
"
" Author: Peter Odding <peter@peterodding.com>
" Last Change: June , 2013
" URL: http://peterodding.com/code/vim/misc/
function! xolox#misc#os#is_mac() " {{{1
" Returns 1 (true) when on Mac OS X, 0 (false) otherwise. You would expect
" this to simply check the Vim feature list, but for some obscure reason the
" `/usr/bin/vim` included in Mac OS X (verified on version 10.7.5) returns 0
" (false) in response to `has('mac')`, so we check the output of `uname`
" to avoid false negatives.
if !exists('s:is_mac')
" By default we assume we are *not* on Mac OS X.
let s:is_mac = 0
if has('mac') || has('macunix') || has('gui_mac')
" If Vim's feature list indicates we are on Mac OS X, we have our answer :-).
let s:is_mac = 1
elseif !xolox#misc#os#is_win()
" Otherwise we check the output of `uname' to avoid false negatives.
let result = xolox#misc#os#exec({'command': 'uname', 'check': 0})
if result['exit_code'] == 0 && get(result['stdout'], 0, '') == 'Darwin'
let s:is_mac = 1
endif
endif
endif
return s:is_mac
endfunction
function! xolox#misc#os#is_win() " {{{1
" Returns 1 (true) when on Microsoft Windows, 0 (false) otherwise.
return has('win16') || has('win32') || has('win64')
endfunction
function! xolox#misc#os#find_vim(...) " {{{1
" Returns the program name of Vim as a string. On Windows and UNIX this just
" [v:progname] [] as an absolute pathname while on Mac OS X there is
" some special magic to find MacVim's executable even though it's usually
" not on the executable search path. If you want, you can override the
" value returned from this function by setting the global variable
" `g:xolox#misc#os#vim_progname`.
"
" By default the choice of console Vim vs graphical Vim is made based on
" the value of [v:progname] [], but if you have a preference you can pass
" the string `vim` or `gvim` as the first and only argument.
"
" [v:progname]: http://vimdoc.sourceforge.net/htmldoc/eval.html#v:progname
if exists('a:1')
let program_name = a:1
else
let program_name = v:progname
endif
if exists('g:xolox#misc#os#vim_progname')
let pathname = g:xolox#misc#os#vim_progname
else
let pathname = ''
endif
if empty(pathname) && xolox#misc#os#is_mac()
" Special handling for Mac OS X where MacVim is usually not on the $PATH.
" This always returns the "Vim" executable and not "MacVim" (regardless of
" the caller's preference) because "MacVim" has funky dock magic going on.
call xolox#misc#msg#debug("vim-misc %s: Trying MacVim workaround to find Vim executable ..", g:xolox#misc#version)
let segments = xolox#misc#path#split($VIMRUNTIME)
if segments[-3:] == ['Resources', 'vim', 'runtime']
let pathname = xolox#misc#path#join(segments[0:-4] + ['MacOS', 'Vim'])
call xolox#misc#msg#debug("vim-misc %s: The MacVim workaround resulted in the Vim executable %s.", g:xolox#misc#version, string(pathname))
endif
endif
if empty(pathname)
" Default logic.
call xolox#misc#msg#debug("vim-misc %s: Looking for Vim executable named %s on search path ..", g:xolox#misc#version, string(program_name))
let candidates = xolox#misc#path#which(program_name)
if !empty(candidates)
call xolox#misc#msg#debug("vim-misc %s: Found %i candidate(s) on search path: %s.", g:xolox#misc#version, len(candidates), string(candidates))
let pathname = candidates[0]
endif
endif
call xolox#misc#msg#debug("vim-misc %s: Reporting Vim executable %s.", g:xolox#misc#version, string(pathname))
return pathname
endfunction
function! xolox#misc#os#exec(options) " {{{1
" 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.
let cmd = a:options['command']
let async = get(a:options, 'async', 0)
" We need to know in a couple of places whether we are on Windows.
let is_win = xolox#misc#os#is_win()
" Use vim-shell so we don't pop up a console window on Windows? If the
" caller specifically asks us *not* to use vim-shell, we'll respect that
" choice; this is very useful for automated tests :-).
if get(a:options, 'use_dll', 1) == 0
let use_dll = 0
else
let use_dll = xolox#misc#os#can_use_dll()
endif
" Decide whether to redirect the standard output and standard error
" streams to temporary files.
let redirect_output = !async && (use_dll || !is_win)
" Write the input for the external command to a temporary file?
if has_key(a:options, 'stdin') && use_dll
let tempin = tempname()
if type(a:options['stdin']) == type([])
let lines = a:options['stdin']
else
let lines = split(a:options['stdin'], "\n")
endif
call writefile(lines, tempin)
let cmd .= ' < ' . xolox#misc#escape#shell(tempin)
endif
" Redirect the standard output and/or standard error streams of the
" external process to temporary files? (only in synchronous mode)
if redirect_output
let tempout = tempname()
let temperr = tempname()
let cmd = printf('(%s) 1>%s 2>%s', cmd, xolox#misc#escape#shell(tempout), xolox#misc#escape#shell(temperr))
endif
" Use vim-shell or system() to execute the external command?
if use_dll
call xolox#misc#msg#debug("vim-misc %s: Executing external command using compiled DLL: %s", g:xolox#misc#version, cmd)
let exit_code = xolox#shell#execute_with_dll(cmd, async)
else
" Enable asynchronous mode (very platform specific).
if async
if is_win
let cmd = printf('start /b %s', cmd)
elseif has('unix')
let cmd = printf('(%s) &', cmd)
else
call xolox#misc#msg#warn("vim-misc %s: I don't know how to execute the command %s asynchronously on your platform! Falling back to synchronous mode...", g:xolox#misc#version, cmd)
endif
endif
" On UNIX we explicitly 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
" (and it might be the default shell).
if has('unix')
call xolox#misc#msg#debug("vim-misc %s: Generated shell expression: %s", g:xolox#misc#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).
if async && is_win
call xolox#misc#msg#debug("vim-misc %s: Executing external command using !start command: %s", g:xolox#misc#version, cmd)
silent execute '!' . cmd
else
call xolox#misc#msg#debug("vim-misc %s: Executing external command using system() function: %s", g:xolox#misc#version, cmd)
let arguments = [cmd]
if has_key(a:options, 'stdin')
if type(a:options['stdin']) == type([])
call add(arguments, join(a:options['stdin'], "\n"))
else
call add(arguments, a:options['stdin'])
endif
endif
let stdout = call('system', arguments)
let exit_code = v:shell_error
endif
endif
" 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
" Get the standard output of the command.
if redirect_output
let result['stdout'] = s:readfile(tempout, 'standard output', a:options['command'])
elseif exists('stdout')
let result['stdout'] = split(stdout, "\n")
else
let result['stdout'] = []
endif
" Get the standard error of the command.
if exists('temperr')
let result['stderr'] = s:readfile(temperr, 'standard error', a:options['command'])
else
let result['stderr'] = []
endif
" 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. The idea here is that it should be easy
" to 'do the right thing'.
if get(a:options, 'check', 1) && exit_code != 0
" Prepare an error message with enough details so the user can investigate.
let msg = printf("vim-misc %s: External command failed with exit code %d!", g:xolox#misc#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
endif
return result
finally
" Cleanup any temporary files we created.
for name in ['tempin', 'tempout', 'temperr']
if exists(name)
call delete({name})
endif
endfor
endtry
endfunction
function! xolox#misc#os#can_use_dll() " {{{1
" If a) we're on Microsoft Windows, b) the vim-shell plug-in is installed
" and c) the compiled DLL included in vim-shell works, we can use the
" vim-shell plug-in to execute external commands! Returns 1 (true)
" if we can use the DLL, 0 (false) otherwise.
let can_use_dll = 0
try
let can_use_dll = xolox#shell#can_use_dll()
catch /^Vim\%((\a\+)\)\=:E117/
" Silence E117.
endtry
return can_use_dll
endfunction
function! s:readfile(fname, label, cmd) " {{{1
try
return readfile(a:fname)
catch
call xolox#misc#msg#warn("vim-misc %s: Failed to read temporary file (%s) with %s of external command: %s! (external command: %s)", g:xolox#misc#version, a:fname, a:label, v:exception, a:cmd)
return []
endtry
endfunction
" vim: ts=2 sw=2 et

View File

@ -0,0 +1,263 @@
" Pathname manipulation functions.
"
" Author: Peter Odding <peter@peterodding.com>
" Last Change: June 25, 2013
" URL: http://peterodding.com/code/vim/misc/
let s:windows_compatible = xolox#misc#os#is_win()
let s:mac_os_x_compatible = xolox#misc#os#is_mac()
function! xolox#misc#path#which(...) " {{{1
" 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 program in a:000
for directory in split($PATH, s:windows_compatible ? ';' : ':')
let directory = xolox#misc#path#absolute(directory)
if isdirectory(directory)
let found = 0
for extension in extensions
let path = xolox#misc#path#merge(directory, program . extension)
if executable(path)
call add(matches, path)
let found = 1
endif
endfor
if s:windows_compatible && ! found
" Maybe the extension is already contained in program; try without
" $PATHEXT.
let path = xolox#misc#path#merge(directory, program)
if executable(path)
call add(matches, path)
endif
endif
endif
endfor
endfor
return xolox#misc#list#unique(matches)
endfunction
function! xolox#misc#path#split(path) " {{{1
" 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 =~ '^[\/][\/]'
" 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 else is treated as UNIX.
let absolute = (a:path =~ '^/')
let segments = split(a:path, '/\+')
return absolute ? insert(segments, '/') : segments
endif
endif
return []
endfunction
function! xolox#misc#path#join(parts) " {{{1
" 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())
elseif get(a:parts, 0) == '/'
" Absolute path on UNIX (non-Windows).
return '/' . join(a:parts[1:], '/')
else
" Relative path on UNIX (non-Windows).
return join(a:parts, '/')
endif
endif
return ''
endfunction
function! xolox#misc#path#directory_separator() " {{{1
" Find the preferred directory separator for the platform and settings.
return exists('+shellslash') && &shellslash ? '/' : '\'
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.
if type(a:path) == type('')
let path = a:path
" Make the pathname absolute.
if path =~ '^\~'
" Expand ~ to $HOME.
let path = $HOME . '/' . path[1:]
elseif xolox#misc#path#is_relative(path)
" Make relative pathnames absolute.
let path = getcwd() . '/' . path
endif
" Resolve symbolic links to find the canonical pathname. In my tests this
" also removes all symbolic pathname segments (`.' and `..'), even when
" the pathname does not exist. Also there used to be a bug in resolve()
" where it wouldn't resolve pathnames ending in a directory separator.
" Since it's not much trouble to work around, that's what we do.
let path = resolve(substitute(path, s:windows_compatible ? '[\/]\+$' : '/\+$', '', ''))
" Normalize directory separators (especially relevant on Windows).
let parts = xolox#misc#path#split(path)
if s:windows_compatible && parts[0] =~ '^[\/][\/]'
" Also normalize the two leading "directory separators" (I'm not
" sure what else to call them :-) in Windows UNC pathnames.
let parts[0] = repeat(xolox#misc#path#directory_separator(), 2) . parts[0][2:]
endif
return xolox#misc#path#join(parts)
endif
return ''
endfunction
function! xolox#misc#path#relative(path, base) " {{{1
" 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]
call remove(path, 0)
call remove(base, 0)
endwhile
let distance = repeat(['..'], len(base))
return xolox#misc#path#join(distance + path)
endfunction
function! xolox#misc#path#merge(parent, child, ...) " {{{1
" 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, '^[\\/]\+', '', '')
return parent . '\' . child
else
let parent = substitute(a:parent, '/\+$', '', '')
let child = substitute(a:child, '^/\+', '', '')
return parent . '/' . child
endif
endif
return ''
endfunction
function! xolox#misc#path#commonprefix(paths) " {{{1
" Find the common prefix of path components in a list of pathnames.
let common = xolox#misc#path#split(a:paths[0])
for path in a:paths
let index = 0
for segment in xolox#misc#path#split(path)
if len(common) <= index
break
elseif common[index] != segment
call remove(common, index, -1)
break
endif
let index += 1
endfor
endfor
return xolox#misc#path#join(common)
endfunction
function! xolox#misc#path#encode(path) " {{{1
" 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
let mask = '[\\/%:]'
else
let mask = '[\\/%]'
endif
return substitute(a:path, mask, '\=printf("%%%x", char2nr(submatch(0)))', 'g')
endfunction
function! xolox#misc#path#decode(encoded_path) " {{{1
" Decode a pathname previously encoded with `xolox#misc#path#encode()`.
return substitute(a:encoded_path, '%\(\x\x\?\)', '\=nr2char("0x" . submatch(1))', 'g')
endfunction
" xolox#misc#path#equals(a, b) - Check whether two pathnames point to the same file. {{{1
if s:windows_compatible
function! xolox#misc#path#equals(a, b)
return a:a ==? a:b || xolox#misc#path#absolute(a:a) ==? xolox#misc#path#absolute(a:b)
endfunction
else
function! xolox#misc#path#equals(a, b)
return a:a ==# a:b || xolox#misc#path#absolute(a:a) ==# xolox#misc#path#absolute(a:b)
endfunction
endif
function! xolox#misc#path#is_relative(path) " {{{1
" 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
return a:path !~ '^\(\w:\|[\\/]\)'
else
return a:path !~ '^/'
endif
endfunction
function! xolox#misc#path#tempdir() " {{{1
" Create a temporary directory and return the pathname of the directory.
if !exists('s:tempdir_counter')
let s:tempdir_counter = 1
endif
if exists('*mkdir')
if s:windows_compatible
let template = $TMP . '\vim_tempdir_'
elseif filewritable('/tmp') == 2
let template = '/tmp/vim_tempdir_'
endif
endif
if !exists('template')
throw "xolox#misc#path#tempdir() hasn't been implemented on your platform!"
endif
while 1
let directory = template . s:tempdir_counter
try
call mkdir(directory, '', 0700)
return directory
catch /^Vim\%((\a\+)\)\=:E739/
" Keep looking for a non-existing directory.
endtry
let s:tempdir_counter += 1
endwhile
endfunction
" vim: ts=2 sw=2 et

View File

@ -0,0 +1,69 @@
" String handling.
"
" Author: Peter Odding <peter@peterodding.com>
" Last Change: June 23, 2013
" URL: http://peterodding.com/code/vim/misc/
function! xolox#misc#str#slug(s) " {{{1
" Convert a string to a "slug" - something that can be safely used in
" filenames and URLs without worrying about quoting/escaping of special
" characters.
return join(split(tolower(a:s), '\W\+'), '-')
endfunction
function! xolox#misc#str#ucfirst(s) " {{{1
" Uppercase the first character in a string (the first argument).
return substitute(a:s, '^.', '\U\0', '')
endfunction
function! xolox#misc#str#compact(s) " {{{1
" Compact whitespace in a string (the first argument).
return join(split(a:s), " ")
endfunction
function! xolox#misc#str#trim(s) " {{{1
" Trim all whitespace from the start and end of a string (the first
" argument).
return substitute(a:s, '^\_s*\(.\{-}\)\_s*$', '\1', '')
endfunction
function! xolox#misc#str#indent(text, num_spaces) " {{{1
" Indent all lines in a multi-line string (the first argument) with a
" specific number of *space characters* (the second argument, an integer).
let lines = split(a:text, "\n")
let indent = repeat(' ', a:num_spaces)
let [idx, limit] = [0, len(lines)]
while idx < limit
if lines[idx] =~ '\S'
let lines[idx] = indent . lines[idx]
endif
let idx += 1
endwhile
return join(lines, "\n")
endfunction
function! xolox#misc#str#dedent(text) " {{{1
" Remove common whitespace from a multi line string.
let lines = split(a:text, "\n")
" First we need to determine the common indentation of all non-empty lines.
for line in lines
if line =~ '\S'
let indent = matchstr(line, '^\s*')
if !exists('common_indent')
let common_indent = indent
elseif len(indent) < len(common_indent)
let common_indent = indent
endif
endif
endfor
" Now we will strip the common indentation.
let [idx, limit] = [0, len(lines)]
let pattern = '^' . common_indent
while idx < limit
let lines[idx] = substitute(lines[idx], pattern, '', '')
let idx += 1
endwhile
return join(lines, "\n")
endfunction
" vim: ts=2 sw=2 et

View File

@ -0,0 +1,125 @@
" Test runner & infrastructure for Vim plug-ins.
"
" Author: Peter Odding <peter@peterodding.com>
" Last Change: June 2, 2013
" URL: http://peterodding.com/code/vim/misc/
"
" The Vim auto-load script `autoload/xolox/misc/test.vim` contains
" infrastructure that can be used to run an automated Vim plug-in test suite.
" It provides a framework for running test functions, keeping track of the
" test status, making assertions and reporting test results to the user.
" The process handling tests cannot use the built-in "echo" command from the
" Windows shell because it has way too much idiosyncrasies for me to put up
" with. Seriously. Instead I'm using an "echo.exe" from the UnxUtils project.
if xolox#misc#os#is_win()
let g:xolox#misc#test#echo = xolox#misc#escape#shell(xolox#misc#path#merge(expand('<sfile>:p:h'), 'echo.exe'))
else
let g:xolox#misc#test#echo = 'echo'
endif
function! xolox#misc#test#reset() " {{{1
" Reset counters for executed tests and passed/failed assertions.
let s:num_executed = 0
let s:num_passed = 0
let s:num_failed = 0
let s:tests_started_at = xolox#misc#timer#start()
endfunction
function! xolox#misc#test#summarize() " {{{1
" Print a summary of test results, to be interpreted interactively.
call s:delimit_output()
call xolox#misc#timer#force("Took %s to run %s: %s passed, %s failed.",
\ s:tests_started_at,
\ xolox#misc#format#pluralize(s:num_executed, 'test', 'tests'),
\ xolox#misc#format#pluralize(s:num_passed, 'assertion', 'assertions'),
\ xolox#misc#format#pluralize(s:num_failed, 'assertion', 'assertions'))
endfunction
function! xolox#misc#test#wrap(function) " {{{1
" Call a function in a try/catch block and prevent exceptions from bubbling.
" The name of the function should be passed as the first and only argument;
" it should be a string containing the name of a Vim auto-load function.
let num_failed = s:num_failed
try
if s:num_passed + s:num_failed > 0
call s:delimit_output()
endif
let test_name = split(a:function, '#')[-1]
let test_name = substitute(test_name, '_', ' ', 'g')
let test_name = substitute(test_name, '^.', '\U\0', '')
call xolox#misc#msg#info("Running test #%i: %s", s:num_executed + 1, test_name)
call call(a:function, [])
catch
call xolox#misc#msg#warn("Test %s raised exception:", a:function)
call xolox#misc#msg#warn("%s", v:exception)
call xolox#misc#msg#warn("(at %s)", v:throwpoint)
if num_failed == s:num_failed
" Make sure exceptions are counted as failures, but don't inflate the
" number of failed assertions when it's not needed (it can produce
" confusing test output).
call xolox#misc#test#failed()
endif
endtry
let s:num_executed += 1
endfunction
function! xolox#misc#test#passed() " {{{1
" Record a test which succeeded.
let s:num_passed += 1
call s:print_feedback()
endfunction
function! xolox#misc#test#failed() " {{{1
" Record a test which failed.
let s:num_failed += 1
call s:print_feedback()
endfunction
function! s:delimit_output() " {{{1
" Print a delimiter between output of tests.
call xolox#misc#msg#info("%s", repeat("-", 40))
endfunction
function! s:print_feedback() " {{{1
" Let the user know the status of the test suite.
call xolox#misc#msg#info("Test status: %s passed, %s failed ..",
\ xolox#misc#format#pluralize(s:num_passed, 'assertion', 'assertions'),
\ xolox#misc#format#pluralize(s:num_failed, 'assertion', 'assertions'))
endfunction
function! xolox#misc#test#assert_true(expr) " {{{1
" Check whether an expression is true.
if a:expr
call xolox#misc#test#passed()
else
call xolox#misc#test#failed()
let msg = "Expected value to be true, got %s instead"
throw printf(msg, string(a:expr))
endif
endfunction
function! xolox#misc#test#assert_equals(expected, received) " {{{1
" Check whether two values are the same.
call xolox#misc#test#assert_same_type(a:expected, a:received)
if a:expected == a:received
call xolox#misc#test#passed()
else
call xolox#misc#test#failed()
let msg = "Expected value %s, received value %s!"
throw printf(msg, string(a:expected), string(a:received))
endif
endfunction
function! xolox#misc#test#assert_same_type(expected, received) " {{{1
" Check whether two values are of the same type.
if type(a:expected) == type(a:received)
call xolox#misc#test#passed()
else
call xolox#misc#test#failed()
let msg = "Expected value of same type as %s, got value %s!"
throw printf(msg, string(a:expected), string(a:received))
endif
endfunction
call xolox#misc#test#reset()

View File

@ -0,0 +1,301 @@
" Tests for the miscellaneous Vim scripts.
"
" Author: Peter Odding <peter@peterodding.com>
" Last Change: June , 2013
" URL: http://peterodding.com/code/vim/misc/
"
" The Vim auto-load script `autoload/xolox/misc/tests.vim` contains the
" automated test suite of the miscellaneous Vim scripts. Right now the
" coverage is not very high yet, but this will improve over time.
let s:use_dll = 0
let s:can_use_dll = xolox#misc#os#can_use_dll()
function! xolox#misc#tests#run() " {{{1
" Run the automated test suite of the miscellaneous Vim scripts. To be used
" interactively. Intended to be safe to execute irrespective of context.
call xolox#misc#test#reset()
" Run the tests.
call s:test_string_escaping()
call s:test_list_handling()
call s:test_option_handling()
call s:test_command_execution()
call s:test_string_handling()
call s:test_version_handling()
" Report a short summary to the user.
call xolox#misc#test#summarize()
endfunction
function! s:wrap_exec_test(function)
" Wrapper for tests that use xolox#misc#os#exec(). If we're on Windows and
" the vim-shell plug-in is installed, the test will be run twice: Once with
" vim-shell disabled and once with vim-shell enabled. This makes sure that
" all code paths are tested as much as possible.
call xolox#misc#msg#debug("vim-misc %s: Temporarily disabling vim-shell so we can test vim-misc ..", g:xolox#misc#version)
let s:use_dll = 0
call xolox#misc#test#wrap(a:function)
if s:can_use_dll
call xolox#misc#msg#debug("vim-misc %s: Re-enabling vim-shell so we can test that as well ..", g:xolox#misc#version)
let s:use_dll = 1
call xolox#misc#test#wrap(a:function)
endif
endfunction
" Tests for autoload/xolox/misc/escape.vim {{{1
function! s:test_string_escaping()
call xolox#misc#test#wrap('xolox#misc#tests#pattern_escaping')
call xolox#misc#test#wrap('xolox#misc#tests#substitute_escaping')
call s:wrap_exec_test('xolox#misc#tests#shell_escaping')
endfunction
function! xolox#misc#tests#pattern_escaping() " {{{2
" Test escaping of regular expression patterns with
" `xolox#misc#escape#pattern()`.
call xolox#misc#test#assert_equals('foo [qux] baz', substitute('foo [bar] baz', xolox#misc#escape#pattern('[bar]'), '[qux]', 'g'))
call xolox#misc#test#assert_equals('also very nasty', substitute('also ~ nasty', xolox#misc#escape#pattern('~'), 'very', 'g'))
endfunction
function! xolox#misc#tests#substitute_escaping() " {{{2
" Test escaping of substitution strings with
" `xolox#misc#escape#substitute()`.
call xolox#misc#test#assert_equals('nasty & tricky stuff', substitute('tricky stuff', 'tricky', xolox#misc#escape#substitute('nasty & tricky'), 'g'))
endfunction
function! xolox#misc#tests#shell_escaping() " {{{2
" Test escaping of shell arguments with `xolox#misc#escape#shell()`.
let expected_value = 'this < is > a | very " scary ^ string '' indeed'
let result = xolox#misc#os#exec({'command': g:xolox#misc#test#echo . ' ' . xolox#misc#escape#shell(expected_value), 'use_dll': s:use_dll})
call xolox#misc#test#assert_equals(0, result['exit_code'])
call xolox#misc#test#assert_equals(0, result['exit_code'])
call xolox#misc#test#assert_same_type([], result['stdout'])
call xolox#misc#test#assert_equals(1, len(result['stdout']))
" XXX On Windows using system() there's a trailing space I can't explain.
" However the point of this test was to show that all characters pass
" through unharmed, so for now I'll just ignore the space :-)
call xolox#misc#test#assert_equals(expected_value, xolox#misc#str#trim(result['stdout'][0]))
endfunction
" Tests for autoload/xolox/misc/list.vim {{{1
function! s:test_list_handling()
call xolox#misc#test#wrap('xolox#misc#tests#making_a_list_unique')
call xolox#misc#test#wrap('xolox#misc#tests#binary_insertion')
endfunction
function! xolox#misc#tests#making_a_list_unique() " {{{2
" Test removing of duplicate values from lists with
" `xolox#misc#list#unique()`.
call xolox#misc#test#assert_equals([1, 2, 3, 4, 5], xolox#misc#list#unique([1, 1, 2, 3, 3, 4, 5, 5]))
" Should work for strings just as well. And it should preserve order.
call xolox#misc#test#assert_equals(['a', 'b', 'c'], xolox#misc#list#unique(['a', 'a', 'b', 'b', 'c']))
" Just to make sure that lists without duplicate values pass through unharmed.
call xolox#misc#test#assert_equals([1, 2, 3, 4, 5], xolox#misc#list#unique([1, 2, 3, 4, 5]))
endfunction
function! xolox#misc#tests#binary_insertion() " {{{2
" Test the binary insertion algorithm implemented in
" `xolox#misc#list#binsert()`.
let list = ['a', 'B', 'e']
" Insert 'c' (should end up between 'B' and 'e').
call xolox#misc#list#binsert(list, 'c', 1)
call xolox#misc#test#assert_equals(['a', 'B', 'c', 'e'], list)
" Insert 'D' (should end up between 'c' and 'e').
call xolox#misc#list#binsert(list, 'D', 1)
call xolox#misc#test#assert_equals(['a', 'B', 'c', 'D', 'e'], list)
" Insert 'f' (should end up after 'e', at the end).
call xolox#misc#list#binsert(list, 'f', 1)
call xolox#misc#test#assert_equals(['a', 'B', 'c', 'D', 'e', 'f'], list)
endfunction
" Tests for autoload/xolox/misc/option.vim {{{1
function! s:test_option_handling()
call xolox#misc#test#wrap('xolox#misc#tests#getting_configuration_options')
call xolox#misc#test#wrap('xolox#misc#tests#splitting_of_multi_valued_options')
call xolox#misc#test#wrap('xolox#misc#tests#joining_of_multi_valued_options')
endfunction
function! xolox#misc#tests#getting_configuration_options() " {{{2
" Test getting of scoped plug-in configuration "options" with
" `xolox#misc#option#get()`.
let magic_name = 'a_variable_that_none_would_use'
call xolox#misc#test#assert_equals(0, xolox#misc#option#get(magic_name))
" Test custom default values.
call xolox#misc#test#assert_equals([], xolox#misc#option#get(magic_name, []))
" Set the option as a global variable.
let global_value = 'global variable'
let g:{magic_name} = global_value
call xolox#misc#test#assert_equals(global_value, xolox#misc#option#get(magic_name))
" Set the option as a buffer local variable, thereby shadowing the global.
let local_value = 'buffer local variable'
let b:{magic_name} = local_value
call xolox#misc#test#assert_equals(local_value, xolox#misc#option#get(magic_name))
" Sanity check that it's possible to unshadow as well.
unlet b:{magic_name}
call xolox#misc#test#assert_equals(global_value, xolox#misc#option#get(magic_name))
" Cleanup after ourselves.
unlet g:{magic_name}
call xolox#misc#test#assert_equals(0, xolox#misc#option#get(magic_name))
endfunction
function! xolox#misc#tests#splitting_of_multi_valued_options() " {{{2
" Test splitting of multi-valued Vim options with
" `xolox#misc#option#split()`.
call xolox#misc#test#assert_equals([], xolox#misc#option#split(''))
call xolox#misc#test#assert_equals(['just one value'], xolox#misc#option#split('just one value'))
call xolox#misc#test#assert_equals(['value 1', 'value 2'], xolox#misc#option#split('value 1,value 2'))
call xolox#misc#test#assert_equals(['value 1', 'value 2', 'tricky,value'], xolox#misc#option#split('value 1,value 2,tricky\,value'))
endfunction
function! xolox#misc#tests#joining_of_multi_valued_options() " {{{2
" Test joining of multi-valued Vim options with `xolox#misc#option#join()`.
call xolox#misc#test#assert_equals('', xolox#misc#option#join([]))
call xolox#misc#test#assert_equals('just one value', xolox#misc#option#join(['just one value']))
call xolox#misc#test#assert_equals('value 1,value 2', xolox#misc#option#join(['value 1', 'value 2']))
call xolox#misc#test#assert_equals('value 1,value 2,tricky\,value', xolox#misc#option#join(['value 1', 'value 2', 'tricky,value']))
endfunction
" Tests for autoload/xolox/misc/os.vim {{{1
function! s:test_command_execution()
call xolox#misc#test#wrap('xolox#misc#tests#finding_vim_on_the_search_path')
call s:wrap_exec_test('xolox#misc#tests#synchronous_command_execution')
call s:wrap_exec_test('xolox#misc#tests#synchronous_command_execution_with_stderr')
call s:wrap_exec_test('xolox#misc#tests#synchronous_command_execution_with_raising_of_errors')
call s:wrap_exec_test('xolox#misc#tests#synchronous_command_execution_without_raising_errors')
call s:wrap_exec_test('xolox#misc#tests#asynchronous_command_execution')
endfunction
function! xolox#misc#tests#finding_vim_on_the_search_path() " {{{2
" Test looking up Vim's executable on the search path using [v:progname] []
" with `xolox#misc#os#find_vim()`.
"
" [v:progname]: http://vimdoc.sourceforge.net/htmldoc/eval.html#v:progname
let pathname = xolox#misc#os#find_vim()
call xolox#misc#test#assert_same_type('', pathname)
call xolox#misc#test#assert_true(executable(pathname))
endfunction
function! xolox#misc#tests#synchronous_command_execution() " {{{2
" Test basic functionality of synchronous command execution with
" `xolox#misc#os#exec()`.
let result = xolox#misc#os#exec({'command': printf('%s output', g:xolox#misc#test#echo), 'use_dll': s:use_dll})
call xolox#misc#test#assert_same_type({}, result)
call xolox#misc#test#assert_equals(0, result['exit_code'])
call xolox#misc#test#assert_equals(['output'], result['stdout'])
endfunction
function! xolox#misc#tests#synchronous_command_execution_with_stderr() " {{{2
" Test basic functionality of synchronous command execution with
" `xolox#misc#os#exec()` including the standard error stream (not available
" on Windows when vim-shell is not installed).
if !(xolox#misc#os#is_win() && !s:use_dll)
let result = xolox#misc#os#exec({'command': printf('%s output && %s errors >&2', g:xolox#misc#test#echo, g:xolox#misc#test#echo), 'use_dll': s:use_dll})
call xolox#misc#test#assert_same_type({}, result)
call xolox#misc#test#assert_equals(0, result['exit_code'])
call xolox#misc#test#assert_equals(['output'], result['stdout'])
call xolox#misc#test#assert_equals(['errors'], result['stderr'])
endif
endfunction
function! xolox#misc#tests#synchronous_command_execution_with_raising_of_errors() " {{{2
" Test raising of errors during synchronous command execution with
" `xolox#misc#os#exec()`.
try
call xolox#misc#os#exec({'command': 'exit 1', 'use_dll': s:use_dll})
call xolox#misc#test#assert_true(0)
catch
call xolox#misc#test#assert_true(1)
endtry
endfunction
function! xolox#misc#tests#synchronous_command_execution_without_raising_errors() " {{{2
" Test synchronous command execution without raising of errors with
" `xolox#misc#os#exec()`.
try
let result = xolox#misc#os#exec({'command': 'exit 42', 'check': 0, 'use_dll': s:use_dll})
call xolox#misc#test#assert_true(1)
call xolox#misc#test#assert_equals(42, result['exit_code'])
catch
call xolox#misc#test#assert_true(0)
endtry
endfunction
function! xolox#misc#tests#asynchronous_command_execution() " {{{2
" Test the basic functionality of asynchronous command execution with
" `xolox#misc#os#exec()`. This runs the external command `mkdir` and tests
" that the side effect of creating the directory takes place. This might
" seem like a peculiar choice, but it's one of the few 100% portable
" commands (Windows + UNIX) that doesn't involve input/output streams.
let temporary_directory = xolox#misc#path#tempdir()
let random_name = printf('%i', localtime())
let expected_directory = xolox#misc#path#merge(temporary_directory, random_name)
let command = 'mkdir ' . xolox#misc#escape#shell(expected_directory)
let result = xolox#misc#os#exec({'command': command, 'async': 1, 'use_dll': s:use_dll})
call xolox#misc#test#assert_same_type({}, result)
" Make sure the command is really executed.
let timeout = localtime() + 30
while !isdirectory(expected_directory) && localtime() < timeout
sleep 500 m
endwhile
call xolox#misc#test#assert_true(isdirectory(expected_directory))
endfunction
" Tests for autoload/xolox/misc/str.vim {{{1
function! s:test_string_handling()
call xolox#misc#test#wrap('xolox#misc#tests#string_case_transformation')
call xolox#misc#test#wrap('xolox#misc#tests#string_whitespace_compaction')
call xolox#misc#test#wrap('xolox#misc#tests#string_whitespace_trimming')
call xolox#misc#test#wrap('xolox#misc#tests#multiline_string_dedent')
endfunction
function! xolox#misc#tests#string_case_transformation()
" Test string case transformation with `xolox#misc#str#ucfirst()`.
call xolox#misc#test#assert_equals('Foo', xolox#misc#str#ucfirst('foo'))
call xolox#misc#test#assert_equals('BAR', xolox#misc#str#ucfirst('BAR'))
endfunction
function! xolox#misc#tests#string_whitespace_compaction()
" Test compaction of whitespace in strings with `xolox#misc#str#compact()`.
call xolox#misc#test#assert_equals('foo bar baz', xolox#misc#str#compact(' foo bar baz '))
call xolox#misc#test#assert_equals('test', xolox#misc#str#compact("\ntest "))
endfunction
function! xolox#misc#tests#string_whitespace_trimming()
" Test trimming of whitespace in strings with `xolox#misc#str#trim()`.
call xolox#misc#test#assert_equals('foo bar baz', xolox#misc#str#trim("\nfoo bar baz "))
endfunction
function! xolox#misc#tests#multiline_string_dedent()
" Test dedenting of multi-line strings with `xolox#misc#str#dedent()`.
call xolox#misc#test#assert_equals('test', xolox#misc#str#dedent(' test'))
call xolox#misc#test#assert_equals("1\n\n2", xolox#misc#str#dedent(" 1\n\n 2"))
call xolox#misc#test#assert_equals("1\n\n 2", xolox#misc#str#dedent(" 1\n\n 2"))
endfunction
" Tests for autoload/xolox/misc/version.vim {{{1
function! s:test_version_handling()
call xolox#misc#test#wrap('xolox#misc#tests#version_string_parsing')
call xolox#misc#test#wrap('xolox#misc#tests#version_string_comparison')
endfunction
function! xolox#misc#tests#version_string_parsing() " {{{2
" Test parsing of version strings with `xolox#misc#version#parse()`.
call xolox#misc#test#assert_equals([1], xolox#misc#version#parse('1'))
call xolox#misc#test#assert_equals([1, 5], xolox#misc#version#parse('1.5'))
call xolox#misc#test#assert_equals([1, 22, 3333, 44444, 55555], xolox#misc#version#parse('1.22.3333.44444.55555'))
call xolox#misc#test#assert_equals([1, 5], xolox#misc#version#parse('1x.5y'))
endfunction
function! xolox#misc#tests#version_string_comparison() " {{{2
" Test comparison of version strings with `xolox#misc#version#at_least()`.
call xolox#misc#test#assert_true(xolox#misc#version#at_least('1', '1'))
call xolox#misc#test#assert_true(!xolox#misc#version#at_least('1', '0'))
call xolox#misc#test#assert_true(xolox#misc#version#at_least('1', '2'))
call xolox#misc#test#assert_true(xolox#misc#version#at_least('1.2.3', '1.2.3'))
call xolox#misc#test#assert_true(!xolox#misc#version#at_least('1.2.3', '1.2'))
call xolox#misc#test#assert_true(xolox#misc#version#at_least('1.2.3', '1.2.4'))
endfunction

View File

@ -0,0 +1,62 @@
" Timing of long during operations.
"
" Author: Peter Odding <peter@peterodding.com>
" Last Change: June 2, 2013
" URL: http://peterodding.com/code/vim/misc/
if !exists('g:timer_enabled')
let g:timer_enabled = 0
endif
if !exists('g:timer_verbosity')
let g:timer_verbosity = 1
endif
let s:has_reltime = has('reltime')
let s:unique_marker = 'xolox#misc#timer#value'
function! xolox#misc#timer#start() " {{{1
" Start a timer. This returns a list which can later be passed to
" `xolox#misc#timer#stop()`.
return [s:unique_marker, s:has_reltime ? reltime() : localtime()]
endfunction
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! xolox#misc#timer#force(...) " {{{1
" Show a formatted message to the user. 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.
call call('xolox#misc#msg#info', map(copy(a:000), 's:convert_value(v:val)'))
endfunction
function! s:convert_value(value) " {{{1
if type(a:value) == type([]) && len(a:value) == 2 && a:value[0] == s:unique_marker
if s:has_reltime
let ts = xolox#misc#str#trim(reltimestr(reltime(a:value[1])))
else
let ts = localtime() - a:value[1]
endif
return xolox#misc#format#timestamp(ts)
else
return a:value
endif
endfunction
" vim: ts=2 sw=2 et

View File

@ -0,0 +1,34 @@
" Version string handling.
"
" Author: Peter Odding <peter@peterodding.com>
" Last Change: June 22, 2013
" URL: http://peterodding.com/code/vim/misc/
function! xolox#misc#version#parse(version_string)
" Convert a version string to a list of integers.
let result = map(split(a:version_string, '\.'), 'v:val + 0')
call xolox#misc#msg#debug("vim-misc %s: Parsed version string %s into %s.", g:xolox#misc#version, string(a:version_string), string(result))
return result
endfunction
function! xolox#misc#version#at_least(expected_version, available_version)
" Check whether the second version string is equal to or greater than the
" first version string. Returns 1 (true) when it is, 0 (false) otherwise.
let expected_version = xolox#misc#version#parse(a:expected_version)
let available_version = xolox#misc#version#parse(a:available_version)
for idx in range(max([len(expected_version), len(available_version)]))
let expected_number = get(expected_version, idx, 0)
let available_number = get(available_version, idx, 0)
if available_number > expected_number
call xolox#misc#msg#debug("vim-misc %s: Available version (%s) is higher than expected version (%s).", g:xolox#misc#version, a:available_version, a:expected_version)
return 1
elseif available_number < expected_number
call xolox#misc#msg#debug("vim-misc %s: Available version (%s) is lower than expected version (%s).", g:xolox#misc#version, a:available_version, a:expected_version)
return 0
endif
endfor
call xolox#misc#msg#debug("vim-misc %s: Available version (%s) is equal to expected version (%s).", g:xolox#misc#version, a:available_version, a:expected_version)
return 1
endfunction
" vim: ts=2 sw=2 et

View File

@ -0,0 +1,866 @@
*misc.txt* Miscellaneous auto-load Vim scripts
===============================================================================
Contents ~
1. Introduction |misc-introduction|
2. Installation |misc-installation|
3. Function documentation |misc-function-documentation|
1. Handling of special buffers |misc-handling-of-special-buffers|
1. The |xolox#misc#buffer#is_empty()| function
2. The |xolox#misc#buffer#prepare()| function
3. The |xolox#misc#buffer#lock()| function
4. The |xolox#misc#buffer#unlock()| function
2. Tab completion for user defined commands |misc-tab-completion-for-user-defined-commands|
1. The |xolox#misc#complete#keywords()| function
3. String escaping functions |misc-string-escaping-functions|
1. The |xolox#misc#escape#pattern()| function
2. The |xolox#misc#escape#substitute()| function
3. The |xolox#misc#escape#shell()| function
4. Human friendly string formatting for Vim |misc-human-friendly-string-formatting-for-vim|
1. The |xolox#misc#format#pluralize()| function
2. The |xolox#misc#format#timestamp()| function
5. List handling functions |misc-list-handling-functions|
1. The |xolox#misc#list#unique()| function
2. The |xolox#misc#list#binsert()| function
6. Functions to interact with the user |misc-functions-to-interact-with-user|
1. The |xolox#misc#msg#info()| function
2. The |xolox#misc#msg#warn()| function
3. The |xolox#misc#msg#debug()| function
7. Integration between Vim and its environment |misc-integration-between-vim-its-environment|
1. The |xolox#misc#open#file()| function
2. The |xolox#misc#open#url()| function
8. Vim and plug-in option handling |misc-vim-plug-in-option-handling|
1. The |xolox#misc#option#get()| function
2. The |xolox#misc#option#split()| function
3. The |xolox#misc#option#join()| function
4. The |xolox#misc#option#split_tags()| function
5. The |xolox#misc#option#join_tags()| function
6. The |xolox#misc#option#eval_tags()| function
9. Operating system interfaces |misc-operating-system-interfaces|
1. The |xolox#misc#os#is_mac()| function
2. The |xolox#misc#os#is_win()| function
3. The |xolox#misc#os#find_vim()| function
4. The |xolox#misc#os#exec()| function
5. The |xolox#misc#os#can_use_dll()| function
10. Pathname manipulation functions |misc-pathname-manipulation-functions|
1. The |xolox#misc#path#which()| function
2. The |xolox#misc#path#split()| function
3. The |xolox#misc#path#join()| function
4. The |xolox#misc#path#directory_separator()| function
5. The |xolox#misc#path#absolute()| function
6. The |xolox#misc#path#relative()| function
7. The |xolox#misc#path#merge()| function
8. The |xolox#misc#path#commonprefix()| function
9. The |xolox#misc#path#encode()| function
10. The |xolox#misc#path#decode()| function
11. The |xolox#misc#path#is_relative()| function
12. The |xolox#misc#path#tempdir()| function
11. String handling |misc-string-handling|
1. The |xolox#misc#str#slug()| function
2. The |xolox#misc#str#ucfirst()| function
3. The |xolox#misc#str#compact()| function
4. The |xolox#misc#str#trim()| function
5. The |xolox#misc#str#indent()| function
6. The |xolox#misc#str#dedent()| function
12. Test runner & infrastructure for Vim plug-ins |misc-test-runner-infrastructure-for-vim-plug-ins|
1. The |xolox#misc#test#reset()| function
2. The |xolox#misc#test#summarize()| function
3. The |xolox#misc#test#wrap()| function
4. The |xolox#misc#test#passed()| function
5. The |xolox#misc#test#failed()| function
6. The |xolox#misc#test#assert_true()| function
7. The |xolox#misc#test#assert_equals()| function
8. The |xolox#misc#test#assert_same_type()| function
13. Tests for the miscellaneous Vim scripts |tests-for-miscellaneous-vim-scripts|
1. The |xolox#misc#tests#run()| function
2. The |xolox#misc#tests#pattern_escaping()| function
3. The |xolox#misc#tests#substitute_escaping()| function
4. The |xolox#misc#tests#shell_escaping()| function
5. The |xolox#misc#tests#making_a_list_unique()| function
6. The |xolox#misc#tests#binary_insertion()| function
7. The |xolox#misc#tests#getting_configuration_options()| function
8. The |xolox#misc#tests#splitting_of_multi_valued_options()| function
9. The |xolox#misc#tests#joining_of_multi_valued_options()| function
10. The |xolox#misc#tests#finding_vim_on_the_search_path()| function
11. The |xolox#misc#tests#synchronous_command_execution()| function
12. The |xolox#misc#tests#synchronous_command_execution_with_stderr()| function
13. The |xolox#misc#tests#synchronous_command_execution_with_raising_of_errors()|
function
14. The |xolox#misc#tests#synchronous_command_execution_without_raising_errors()|
function
15. The |xolox#misc#tests#asynchronous_command_execution()| function
16. The |xolox#misc#tests#string_case_transformation()| function
17. The |xolox#misc#tests#string_whitespace_compaction()| function
18. The |xolox#misc#tests#string_whitespace_trimming()| function
19. The |xolox#misc#tests#multiline_string_dedent()| function
20. The |xolox#misc#tests#version_string_parsing()| function
21. The |xolox#misc#tests#version_string_comparison()| function
14. Timing of long during operations |misc-timing-of-long-during-operations|
1. The |xolox#misc#timer#start()| function
2. The |xolox#misc#timer#stop()| function
3. The |xolox#misc#timer#force()| function
15. Version string handling |misc-version-string-handling|
1. The |xolox#misc#version#parse()| function
2. The |xolox#misc#version#at_least()| function
4. Contact |misc-contact|
5. License |misc-license|
6. References |misc-references|
===============================================================================
*misc-introduction*
Introduction ~
The vim-misc plug-in contains Vim scripts that are used by most of the Vim
plug-ins I've written [1] yet don't really belong with any single one of the
plug-ins. Basically it's an extended standard library of Vim script functions
that I wrote during the development of my Vim profile and plug-ins.
In the past these scripts were bundled with each plug-in, however that turned
out to be a maintenance nightmare for me. That's why the miscellaneous scripts
are now a proper plug-in with their own page on Vim Online.
Because the miscellaneous scripts are no longer bundled with my Vim plug-ins,
users are now required to install the miscellaneous scripts separately. This is
unfortunate for users who are upgrading from a previous release that did bundle
the miscellaneous scripts, but I don't see any way around this. Sorry!
===============================================================================
*misc-installation*
Installation ~
Unzip the most recent ZIP archive [2] file inside your Vim profile directory
(usually this is '~/.vim' on UNIX and '%USERPROFILE%\vimfiles' on Windows),
restart Vim and execute the command ':helptags ~/.vim/doc' (use ':helptags
~\vimfiles\doc' instead on Windows).
If you prefer you can also use Pathogen [3], Vundle [4] or a similar tool to
install & update the plug-in using a local clone of the git repository.
===============================================================================
*misc-function-documentation*
Function documentation ~
Below is the documentation for the functions included in the miscellaneous
scripts. Anyone is free to use these functions in their own Vim profile and/or
plug-ins. I care about backwards compatibility so won't break it without a good
reason to do so.
For those who are curious: The function descriptions given below were extracted
from the source code of the miscellaneous scripts using the Python module
'vimdoctool.py' included in vim-tools [5].
The documentation of the 80 functions below was extracted from 15 Vim scripts
on July 20, 2013 at 10:41.
-------------------------------------------------------------------------------
*misc-handling-of-special-buffers*
Handling of special buffers ~
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 [6]
generates several such buffers:
- :RecentNotes [7] lists recently modified notes
- :ShowTaggedNotes [8] 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.
-------------------------------------------------------------------------------
The *xolox#misc#buffer#is_empty()* function
Checks if the current buffer is an empty, unchanged buffer which can be reused.
Returns 1 if an empty buffer is found, 0 otherwise.
-------------------------------------------------------------------------------
The *xolox#misc#buffer#prepare()* function
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|
or |'autochdir'| is being used.
-------------------------------------------------------------------------------
The *xolox#misc#buffer#lock()* function
Lock a special buffer so that its contents can no longer be edited.
-------------------------------------------------------------------------------
The *xolox#misc#buffer#unlock()* function
Unlock a special buffer so that its content can be updated.
-------------------------------------------------------------------------------
*misc-tab-completion-for-user-defined-commands*
Tab completion for user defined commands ~
-------------------------------------------------------------------------------
The *xolox#misc#complete#keywords()* function
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(<f-args>)
<
-------------------------------------------------------------------------------
*misc-string-escaping-functions*
String escaping functions ~
-------------------------------------------------------------------------------
The *xolox#misc#escape#pattern()* function
Takes a single string argument and converts it into a |:substitute| /
|substitute()| pattern string that matches the given string literally.
-------------------------------------------------------------------------------
The *xolox#misc#escape#substitute()* function
Takes a single string argument and converts it into a |:substitute| /
|substitute()| replacement string that inserts the given string literally.
-------------------------------------------------------------------------------
The *xolox#misc#escape#shell()* function
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, 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).
-------------------------------------------------------------------------------
*misc-human-friendly-string-formatting-for-vim*
Human friendly string formatting for Vim ~
-------------------------------------------------------------------------------
The *xolox#misc#format#pluralize()* function
Concatenate a counter (the first argument, expected to be an integer) with a
singular or plural label (the second and third arguments, both expected to be
strings).
-------------------------------------------------------------------------------
The *xolox#misc#format#timestamp()* function
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".
-------------------------------------------------------------------------------
*misc-list-handling-functions*
List handling functions ~
-------------------------------------------------------------------------------
The *xolox#misc#list#unique()* function
Remove duplicate values from the given list in-place (preserves order).
-------------------------------------------------------------------------------
The *xolox#misc#list#binsert()* function
Performs in-place binary insertion, which depending on your use case can be
more efficient than calling Vim's |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
-------------------------------------------------------------------------------
*misc-functions-to-interact-with-user*
Functions to interact with the user ~
-------------------------------------------------------------------------------
The *xolox#misc#msg#info()* function
Show a formatted informational message to the user.
This function has the same argument handling as Vim's |printf()| function with
one notable difference: Any arguments which are not numbers or strings are
coerced to strings using Vim's |string()| function.
In the case of |xolox#misc#msg#info()|, automatic string coercion simply makes
the function a bit easier to use.
-------------------------------------------------------------------------------
The *xolox#misc#msg#warn()* function
Show a formatted warning message to the user.
This function has the same argument handling as the |xolox#misc#msg#info()|
function.
-------------------------------------------------------------------------------
The *xolox#misc#msg#debug()* function
Show a formatted debugging message to the user, _if the user has enabled
increased verbosity by setting Vim's |'verbose'| option to one (1) or higher_.
This function has the same argument handling as the |xolox#misc#msg#info()|
function.
In the case of |xolox#misc#msg#debug()|, automatic string coercion provides
lazy evaluation in the sense that complex data structures are only converted to
strings when the user has enabled increased verbosity.
-------------------------------------------------------------------------------
*misc-integration-between-vim-its-environment*
Integration between Vim and its environment ~
-------------------------------------------------------------------------------
The *xolox#misc#open#file()* function
Given a pathname or URL 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.
-------------------------------------------------------------------------------
The *xolox#misc#open#url()* function
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)
-------------------------------------------------------------------------------
*misc-vim-plug-in-option-handling*
Vim and plug-in option handling ~
-------------------------------------------------------------------------------
The *xolox#misc#option#get()* function
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.
-------------------------------------------------------------------------------
The *xolox#misc#option#split()* function
Given a multi-value Vim option like |'runtimepath'| 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',
...]
<
-------------------------------------------------------------------------------
The *xolox#misc#option#join()* function
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.
-------------------------------------------------------------------------------
The *xolox#misc#option#split_tags()* function
Customized version of |xolox#misc#option#split()| with specialized handling for
Vim's |'tags'| option.
-------------------------------------------------------------------------------
The *xolox#misc#option#join_tags()* function
Customized version of |xolox#misc#option#join()| with specialized handling for
Vim's |'tags'| option.
-------------------------------------------------------------------------------
The *xolox#misc#option#eval_tags()* function
Evaluate Vim's |'tags'| option 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 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.
-------------------------------------------------------------------------------
*misc-operating-system-interfaces*
Operating system interfaces ~
-------------------------------------------------------------------------------
The *xolox#misc#os#is_mac()* function
Returns 1 (true) when on Mac OS X, 0 (false) otherwise. You would expect this
to simply check the Vim feature list, but for some obscure reason the
'/usr/bin/vim' included in Mac OS X (verified on version 10.7.5) returns 0
(false) in response to "has('mac')", so we check the output of 'uname' to avoid
false negatives.
-------------------------------------------------------------------------------
The *xolox#misc#os#is_win()* function
Returns 1 (true) when on Microsoft Windows, 0 (false) otherwise.
-------------------------------------------------------------------------------
The *xolox#misc#os#find_vim()* function
Returns the program name of Vim as a string. On Windows and UNIX this just
|v:progname| as an absolute pathname while on Mac OS X there is some special
magic to find MacVim's executable even though it's usually not on the
executable search path. If you want, you can override the value returned from
this function by setting the global variable 'g:xolox#misc#os#vim_progname'.
By default the choice of console Vim vs graphical Vim is made based on the
value of |v:progname|, but if you have a preference you can pass the string
'vim' or 'gvim' as the first and only argument.
-------------------------------------------------------------------------------
The *xolox#misc#os#exec()* function
Execute an external command (hiding the console on Microsoft Windows when my
vim-shell plug-in [9] 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)
-------------------------------------------------------------------------------
The *xolox#misc#os#can_use_dll()* function
If a) we're on Microsoft Windows, b) the vim-shell plug-in is installed and c)
the compiled DLL included in vim-shell works, we can use the vim-shell plug-in
to execute external commands! Returns 1 (true) if we can use the DLL, 0 (false)
otherwise.
-------------------------------------------------------------------------------
*misc-pathname-manipulation-functions*
Pathname manipulation functions ~
-------------------------------------------------------------------------------
The *xolox#misc#path#which()* function
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']
<
-------------------------------------------------------------------------------
The *xolox#misc#path#split()* function
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.
-------------------------------------------------------------------------------
The *xolox#misc#path#join()* function
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()|.
-------------------------------------------------------------------------------
The *xolox#misc#path#directory_separator()* function
Find the preferred directory separator for the platform and settings.
-------------------------------------------------------------------------------
The *xolox#misc#path#absolute()* function
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.
-------------------------------------------------------------------------------
The *xolox#misc#path#relative()* function
Make an absolute pathname (the first argument) relative to a directory (the
second argument).
-------------------------------------------------------------------------------
The *xolox#misc#path#merge()* function
Join a directory pathname and filename into a single pathname.
-------------------------------------------------------------------------------
The *xolox#misc#path#commonprefix()* function
Find the common prefix of path components in a list of pathnames.
-------------------------------------------------------------------------------
The *xolox#misc#path#encode()* function
Encode a pathname so it can be used as a filename. This uses URL encoding to
encode special characters.
-------------------------------------------------------------------------------
The *xolox#misc#path#decode()* function
Decode a pathname previously encoded with |xolox#misc#path#encode()|.
-------------------------------------------------------------------------------
The *xolox#misc#path#is_relative()* function
Returns true (1) when the pathname given as the first argument is relative,
false (0) otherwise.
-------------------------------------------------------------------------------
The *xolox#misc#path#tempdir()* function
Create a temporary directory and return the pathname of the directory.
-------------------------------------------------------------------------------
*misc-string-handling*
String handling ~
-------------------------------------------------------------------------------
The *xolox#misc#str#slug()* function
Convert a string to a "slug" - something that can be safely used in filenames
and URLs without worrying about quoting/escaping of special characters.
-------------------------------------------------------------------------------
The *xolox#misc#str#ucfirst()* function
Uppercase the first character in a string (the first argument).
-------------------------------------------------------------------------------
The *xolox#misc#str#compact()* function
Compact whitespace in a string (the first argument).
-------------------------------------------------------------------------------
The *xolox#misc#str#trim()* function
Trim all whitespace from the start and end of a string (the first argument).
-------------------------------------------------------------------------------
The *xolox#misc#str#indent()* function
Indent all lines in a multi-line string (the first argument) with a specific
number of _space characters_ (the second argument, an integer).
-------------------------------------------------------------------------------
The *xolox#misc#str#dedent()* function
Remove common whitespace from a multi line string.
-------------------------------------------------------------------------------
*misc-test-runner-infrastructure-for-vim-plug-ins*
Test runner & infrastructure for Vim plug-ins ~
The Vim auto-load script 'autoload/xolox/misc/test.vim' contains infrastructure
that can be used to run an automated Vim plug-in test suite. It provides a
framework for running test functions, keeping track of the test status, making
assertions and reporting test results to the user.
-------------------------------------------------------------------------------
The *xolox#misc#test#reset()* function
Reset counters for executed tests and passed/failed assertions.
-------------------------------------------------------------------------------
The *xolox#misc#test#summarize()* function
Print a summary of test results, to be interpreted interactively.
-------------------------------------------------------------------------------
The *xolox#misc#test#wrap()* function
Call a function in a try/catch block and prevent exceptions from bubbling. The
name of the function should be passed as the first and only argument; it should
be a string containing the name of a Vim auto-load function.
-------------------------------------------------------------------------------
The *xolox#misc#test#passed()* function
Record a test which succeeded.
-------------------------------------------------------------------------------
The *xolox#misc#test#failed()* function
Record a test which failed.
-------------------------------------------------------------------------------
The *xolox#misc#test#assert_true()* function
Check whether an expression is true.
-------------------------------------------------------------------------------
The *xolox#misc#test#assert_equals()* function
Check whether two values are the same.
-------------------------------------------------------------------------------
The *xolox#misc#test#assert_same_type()* function
Check whether two values are of the same type.
-------------------------------------------------------------------------------
*tests-for-miscellaneous-vim-scripts*
Tests for the miscellaneous Vim scripts ~
The Vim auto-load script 'autoload/xolox/misc/tests.vim' contains the automated
test suite of the miscellaneous Vim scripts. Right now the coverage is not very
high yet, but this will improve over time.
-------------------------------------------------------------------------------
The *xolox#misc#tests#run()* function
Run the automated test suite of the miscellaneous Vim scripts. To be used
interactively. Intended to be safe to execute irrespective of context.
-------------------------------------------------------------------------------
The *xolox#misc#tests#pattern_escaping()* function
Test escaping of regular expression patterns with
|xolox#misc#escape#pattern()|.
-------------------------------------------------------------------------------
The *xolox#misc#tests#substitute_escaping()* function
Test escaping of substitution strings with |xolox#misc#escape#substitute()|.
-------------------------------------------------------------------------------
The *xolox#misc#tests#shell_escaping()* function
Test escaping of shell arguments with |xolox#misc#escape#shell()|.
-------------------------------------------------------------------------------
The *xolox#misc#tests#making_a_list_unique()* function
Test removing of duplicate values from lists with |xolox#misc#list#unique()|.
-------------------------------------------------------------------------------
The *xolox#misc#tests#binary_insertion()* function
Test the binary insertion algorithm implemented in |xolox#misc#list#binsert()|.
-------------------------------------------------------------------------------
The *xolox#misc#tests#getting_configuration_options()* function
Test getting of scoped plug-in configuration "options" with
|xolox#misc#option#get()|.
-------------------------------------------------------------------------------
The *xolox#misc#tests#splitting_of_multi_valued_options()* function
Test splitting of multi-valued Vim options with |xolox#misc#option#split()|.
-------------------------------------------------------------------------------
The *xolox#misc#tests#joining_of_multi_valued_options()* function
Test joining of multi-valued Vim options with |xolox#misc#option#join()|.
-------------------------------------------------------------------------------
The *xolox#misc#tests#finding_vim_on_the_search_path()* function
Test looking up Vim's executable on the search path using |v:progname| with
|xolox#misc#os#find_vim()|.
-------------------------------------------------------------------------------
The *xolox#misc#tests#synchronous_command_execution()* function
Test basic functionality of synchronous command execution with
|xolox#misc#os#exec()|.
-------------------------------------------------------------------------------
The *xolox#misc#tests#synchronous_command_execution_with_stderr()* function
Test basic functionality of synchronous command execution with
|xolox#misc#os#exec()| including the standard error stream (not available on
Windows when vim-shell is not installed).
-------------------------------------------------------------------------------
The *xolox#misc#tests#synchronous_command_execution_with_raising_of_errors()*
function
Test raising of errors during synchronous command execution with
|xolox#misc#os#exec()|.
-------------------------------------------------------------------------------
The *xolox#misc#tests#synchronous_command_execution_without_raising_errors()*
function
Test synchronous command execution without raising of errors with
|xolox#misc#os#exec()|.
-------------------------------------------------------------------------------
The *xolox#misc#tests#asynchronous_command_execution()* function
Test the basic functionality of asynchronous command execution with
|xolox#misc#os#exec()|. This runs the external command 'mkdir' and tests that
the side effect of creating the directory takes place. This might seem like a
peculiar choice, but it's one of the few 100% portable commands (Windows +
UNIX) that doesn't involve input/output streams.
-------------------------------------------------------------------------------
The *xolox#misc#tests#string_case_transformation()* function
Test string case transformation with |xolox#misc#str#ucfirst()|.
-------------------------------------------------------------------------------
The *xolox#misc#tests#string_whitespace_compaction()* function
Test compaction of whitespace in strings with |xolox#misc#str#compact()|.
-------------------------------------------------------------------------------
The *xolox#misc#tests#string_whitespace_trimming()* function
Test trimming of whitespace in strings with |xolox#misc#str#trim()|.
-------------------------------------------------------------------------------
The *xolox#misc#tests#multiline_string_dedent()* function
Test dedenting of multi-line strings with |xolox#misc#str#dedent()|.
-------------------------------------------------------------------------------
The *xolox#misc#tests#version_string_parsing()* function
Test parsing of version strings with |xolox#misc#version#parse()|.
-------------------------------------------------------------------------------
The *xolox#misc#tests#version_string_comparison()* function
Test comparison of version strings with |xolox#misc#version#at_least()|.
-------------------------------------------------------------------------------
*misc-timing-of-long-during-operations*
Timing of long during operations ~
-------------------------------------------------------------------------------
The *xolox#misc#timer#start()* function
Start a timer. This returns a list which can later be passed to
|xolox#misc#timer#stop()|.
-------------------------------------------------------------------------------
The *xolox#misc#timer#stop()* function
Show a formatted debugging message to the user, if the user has enabled
increased verbosity by setting Vim's |'verbose'| option to one (1) or higher.
This function has the same argument handling as Vim's |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.
-------------------------------------------------------------------------------
The *xolox#misc#timer#force()* function
Show a formatted message to the user. This function has the same argument
handling as Vim's |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.
-------------------------------------------------------------------------------
*misc-version-string-handling*
Version string handling ~
-------------------------------------------------------------------------------
The *xolox#misc#version#parse()* function
Convert a version string to a list of integers.
-------------------------------------------------------------------------------
The *xolox#misc#version#at_least()* function
Check whether the second version string is equal to or greater than the first
version string. Returns 1 (true) when it is, 0 (false) otherwise.
===============================================================================
*misc-contact*
Contact ~
If you have questions, bug reports, suggestions, etc. the author can be
contacted at peter@peterodding.com. The latest version is available at
http://peterodding.com/code/vim/misc and http://github.com/xolox/vim-misc. If
you like the script please vote for it on Vim Online [10].
===============================================================================
*misc-license*
License ~
This software is licensed under the MIT license [11]. © 2013 Peter Odding
<peter@peterodding.com>.
===============================================================================
*misc-references*
References ~
[1] http://peterodding.com/code/vim/
[2] http://peterodding.com/code/vim/downloads/misc.zip
[3] http://www.vim.org/scripts/script.php?script_id=2332
[4] https://github.com/gmarik/vundle
[5] http://peterodding.com/code/vim/tools/
[6] http://peterodding.com/code/vim/notes/
[7] http://peterodding.com/code/vim/notes/#recentnotes_command
[8] http://peterodding.com/code/vim/notes/#showtaggednotes_command
[9] http://peterodding.com/code/vim/shell/
[10] http://www.vim.org/scripts/script.php?script_id=4597
[11] http://en.wikipedia.org/wiki/MIT_License
vim: ft=help