mirror of
https://github.com/amix/vimrc
synced 2025-07-07 08:45:00 +08:00
add vim-session
This commit is contained in:
1
sources_non_forked/vim-misc/.gitignore
vendored
Executable file
1
sources_non_forked/vim-misc/.gitignore
vendored
Executable file
@ -0,0 +1 @@
|
||||
doc/tags
|
13
sources_non_forked/vim-misc/INSTALL.md
Executable file
13
sources_non_forked/vim-misc/INSTALL.md
Executable file
@ -0,0 +1,13 @@
|
||||
# Installation instructions
|
||||
|
||||
There are two ways to install the vim-misc plug-in and it's up to you which you prefer, both options are explained below. Please note that below are generic installation instructions while some Vim plug-ins may have external dependencies, please refer to the plug-in's [readme](README.md) for details.
|
||||
|
||||
## Installation using a ZIP archive
|
||||
|
||||
Unzip the most recent ZIP archive of the [vim-misc](http://peterodding.com/code/vim/downloads/misc.zip) plug-in 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 get warnings about overwriting existing files while unpacking the ZIP archive you probably don't need to worry about this because it's most likely caused by files like `README.md`, `INSTALL.md` and `addon-info.json`. If these files bother you then you can remove them after unpacking the ZIP archive, they are not required to use the plug-in.
|
||||
|
||||
## Installation using a Vim plug-in manager
|
||||
|
||||
If you prefer you can also use [Pathogen](http://www.vim.org/scripts/script.php?script_id=2332), [Vundle](https://github.com/gmarik/vundle) or a similar tool to install and update the [vim-misc](https://github.com/xolox/vim-misc) plug-in using a local clone of the git repository. This takes a bit of work to set up the first time but it makes updating much easier, and it keeps each plug-in in its own directory which helps to keep your Vim profile uncluttered.
|
1015
sources_non_forked/vim-misc/README.md
Executable file
1015
sources_non_forked/vim-misc/README.md
Executable file
File diff suppressed because it is too large
Load Diff
1
sources_non_forked/vim-misc/addon-info.json
Executable file
1
sources_non_forked/vim-misc/addon-info.json
Executable file
@ -0,0 +1 @@
|
||||
{"vim_script_nr": 4597, "dependencies": {}, "homepage": "http://peterodding.com/code/vim/misc", "name": "vim-misc"}
|
7
sources_non_forked/vim-misc/autoload/xolox/misc.vim
Executable file
7
sources_non_forked/vim-misc/autoload/xolox/misc.vim
Executable file
@ -0,0 +1,7 @@
|
||||
" The version of my miscellaneous scripts.
|
||||
"
|
||||
" Author: Peter Odding <peter@peterodding.com>
|
||||
" Last Change: May 21, 2015
|
||||
" URL: http://peterodding.com/code/vim/misc/
|
||||
|
||||
let g:xolox#misc#version = '1.17.6'
|
261
sources_non_forked/vim-misc/autoload/xolox/misc/async.vim
Executable file
261
sources_non_forked/vim-misc/autoload/xolox/misc/async.vim
Executable file
@ -0,0 +1,261 @@
|
||||
" Asynchronous Vim script evaluation.
|
||||
"
|
||||
" Author: Peter Odding <peter@peterodding.com>
|
||||
" Last Change: September 17, 2014
|
||||
" URL: http://peterodding.com/code/vim/misc/
|
||||
"
|
||||
" The `xolox#misc#async#call()` function builds on top of `xolox#misc#os#exec()`
|
||||
" to support asynchronous evaluation of Vim scripts. The first (and for now
|
||||
" only) use case is my [vim-easytags][] plug-in which has a bunch of
|
||||
" conflicting requirements:
|
||||
"
|
||||
" 1. I want the [vim-easytags][] plug-in to be as portable as possible.
|
||||
" Ideally everything is implemented in Vim script because that's the only
|
||||
" thing I can rely on to be available for all potential users of the
|
||||
" plug-in!
|
||||
"
|
||||
" 2. Because of point one I've been forced to implement tags file reading,
|
||||
" parsing, (fold case) sorting and writing in Vim script. This is fine for
|
||||
" small tags files but once they grow to a couple of megabytes it becomes
|
||||
" annoying because Vim is unresponsive during tags file updates (key
|
||||
" presses are fortunately buffered due to Vim's input model but that
|
||||
" doesn't make it a nice user experience :-).
|
||||
"
|
||||
" 3. I could (and did in the past) come up with all sorts of hacks to speed
|
||||
" things up without switching away from Vim script, but none of them are
|
||||
" going to solve the fundamental problem that Vim's unresponsive hiccups
|
||||
" become longer as tags files grow larger.
|
||||
"
|
||||
" By now it should be clear where this is heading: _Why not handle tags file
|
||||
" updates in a Vim process that runs in the background without blocking the
|
||||
" Vim process that the user is interacting with?_ It turns out that there are
|
||||
" quite a few details to take care of, but with those out of the way, it might
|
||||
" just work! I'm actually hoping to make asynchronous updates the default mode
|
||||
" in [vim-easytags][]. This means I need this functionality to be as
|
||||
" portable and robust as possible.
|
||||
"
|
||||
" **Status:** This code has seen little testing so I wouldn't trust it too
|
||||
" much just yet. On the other hand, as I said, my intention is to make this
|
||||
" functionality as portable and robust as possible. You be the judge :-).
|
||||
"
|
||||
" [vim-easytags]: http://peterodding.com/code/vim/easytags/
|
||||
|
||||
if !exists('g:xolox#misc#async#counter')
|
||||
" Increasing integer number used to match asynchronous responses to the
|
||||
" requests that generated them.
|
||||
let g:xolox#misc#async#counter = 1
|
||||
endif
|
||||
|
||||
if !exists('g:xolox#misc#async#requests')
|
||||
" Queue of asynchronous requests that haven't received a response yet.
|
||||
let g:xolox#misc#async#requests = {}
|
||||
endif
|
||||
|
||||
function! xolox#misc#async#call(options) " {{{1
|
||||
" Call a Vim script function asynchronously by starting a hidden Vim process
|
||||
" in the background. Once the function returns the hidden Vim process
|
||||
" terminates itself. This function takes a single argument which is a
|
||||
" dictionary with the following key/value pairs:
|
||||
"
|
||||
" - **function** (required): The name of the Vim function to call inside
|
||||
" the child process (a string). I suggest using an [autoload][] function
|
||||
" for this, see below.
|
||||
"
|
||||
" - **arguments** (optional): A list of arguments to pass to the function.
|
||||
" This list is serialized to a string using [string()][] and deserialized
|
||||
" using [eval()][].
|
||||
"
|
||||
" - **callback** (optional): The name of a Vim function to call in the
|
||||
" parent process when the child process has completed (a string).
|
||||
"
|
||||
" - **clientserver** (optional): If this is true (1) the child process will
|
||||
" notify the parent process when it has finished (the default is true).
|
||||
" This works using Vim's client/server support which is not always
|
||||
" available. As a fall back Vim's [CursorHold][] automatic command is
|
||||
" also supported (although the effect is not quite as instantaneous :-).
|
||||
"
|
||||
" This functionality is experimental and non trivial to use, so consider
|
||||
" yourself warned :-).
|
||||
"
|
||||
" **Limitations**
|
||||
"
|
||||
" I'm making this functionality available in [vim-misc][] because I think it
|
||||
" can be useful to other plug-ins, however if you are going to use it you
|
||||
" should be aware of the following limitations:
|
||||
"
|
||||
" - Because of the use of multiple processes this functionality is only
|
||||
" suitable for 'heavy' tasks.
|
||||
"
|
||||
" - The function arguments are serialized to a string which is passed to
|
||||
" the hidden Vim process as a command line argument, so the amount of
|
||||
" data you can pass will be limited by your operating environment.
|
||||
"
|
||||
" - The hidden Vim process is explicitly isolated from the user in several
|
||||
" ways (see below for more details). This is to make sure that the hidden
|
||||
" Vim processes are fast and don't clobber the user's editing sessions in
|
||||
" any way.
|
||||
"
|
||||
" **Changes to how Vim normally works**
|
||||
"
|
||||
" You have to be aware that the hidden Vim process is initialized in a
|
||||
" specific way that is very different from your regular Vim editing
|
||||
" sessions:
|
||||
"
|
||||
" - Your [vimrc][] file is ignored using the `-u NONE` command line option.
|
||||
"
|
||||
" - Your [gvimrc][] file (if you even knew it existed ;-) is ignored using
|
||||
" the `-U NONE` command line option.
|
||||
"
|
||||
" - Plug-in loading is skipped using the `--noplugin` command line option.
|
||||
"
|
||||
" - Swap files (see [swap-file][]) are disabled using the `-n` command line
|
||||
" option. This makes sure asynchronous Vim processes don't disturb the
|
||||
" user's editing session.
|
||||
"
|
||||
" - Your [viminfo][] file is ignored using the `-i NONE` command line
|
||||
" option. Just like with swap files this makes sure asynchronous Vim
|
||||
" processes don't disturb the user's editing session.
|
||||
"
|
||||
" - No-compatible mode is enabled using the `-N` command line option
|
||||
" (usually the existence of your vimrc script would have achieved the
|
||||
" same effect but since we disable loading of your vimrc we need to spell
|
||||
" things out for Vim).
|
||||
"
|
||||
" **Use an auto-load function**
|
||||
"
|
||||
" The function you want to call is identified by its name which has to be
|
||||
" defined, but I just explained above that all regular initialization is
|
||||
" disabled for asynchronous Vim processes, so what gives? The answer is to
|
||||
" use an [autoload][] function. This should work fine because the
|
||||
" asynchronous Vim process 'inherits' the value of the ['runtimepath'][]
|
||||
" option from your editing session.
|
||||
"
|
||||
" ['runtimepath']: http://vimdoc.sourceforge.net/htmldoc/options.html#'runtimepath'
|
||||
" [autoload]: http://vimdoc.sourceforge.net/htmldoc/eval.html#autoload
|
||||
" [CursorHold]: http://vimdoc.sourceforge.net/htmldoc/autocmd.html#CursorHold
|
||||
" [eval()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#eval()
|
||||
" [gvimrc]: http://vimdoc.sourceforge.net/htmldoc/gui.html#gvimrc
|
||||
" [string()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#string()
|
||||
" [swap-file]: http://vimdoc.sourceforge.net/htmldoc/recover.html#swap-file
|
||||
" [vim-misc]: http://peterodding.com/code/vim/misc/
|
||||
" [viminfo]: http://vimdoc.sourceforge.net/htmldoc/starting.html#viminfo
|
||||
" [vimrc]: http://vimdoc.sourceforge.net/htmldoc/starting.html#vimrc
|
||||
let unique_number = g:xolox#misc#async#counter
|
||||
let g:xolox#misc#async#counter += 1
|
||||
let request = {'function': a:options['function']}
|
||||
let request['arguments'] = get(a:options, 'arguments', [])
|
||||
let request['starttime'] = xolox#misc#timer#start()
|
||||
let request['number'] = unique_number
|
||||
let callback = get(a:options, 'callback')
|
||||
if !empty(callback)
|
||||
let request['callback'] = callback
|
||||
endif
|
||||
if get(a:options, 'clientserver', 1) && !empty(v:servername)
|
||||
let request['servername'] = v:servername
|
||||
else
|
||||
let temporary_file = tempname()
|
||||
let request['temporary_file'] = temporary_file
|
||||
endif
|
||||
let vim_command = printf('let &rtp = %s | call xolox#misc#async#inside_child(%s)', string(&rtp), string(request))
|
||||
call xolox#misc#msg#debug("vim-misc %s: Generated asynchronous Vim command #%i: %s", g:xolox#misc#version, unique_number, vim_command)
|
||||
let quoted_program = xolox#misc#escape#shell(xolox#misc#os#find_vim('vim'))
|
||||
let quoted_command = xolox#misc#escape#shell(vim_command)
|
||||
let shell_command = printf('%s -u NONE -U NONE --noplugin -n -N -i NONE --cmd %s', quoted_program, quoted_command)
|
||||
call xolox#misc#msg#debug("vim-misc %s: Generated asynchronous shell command #%i: %s", g:xolox#misc#version, unique_number, shell_command)
|
||||
call xolox#misc#os#exec({'command': shell_command, 'async': 1})
|
||||
let g:xolox#misc#async#requests[unique_number] = request
|
||||
endfunction
|
||||
|
||||
function! xolox#misc#async#inside_child(request) " {{{1
|
||||
" Entry point inside the hidden Vim process that runs in the background.
|
||||
" Invoked indirectly by `xolox#misc#async#call()` because it runs a command
|
||||
" similar to the following:
|
||||
"
|
||||
" vim --cmd 'call xolox#misc#async#inside_child(...)'
|
||||
"
|
||||
" This function is responsible for calling the user defined function,
|
||||
" capturing exceptions and reporting the results back to the parent Vim
|
||||
" process using Vim's client/server support or a temporary file.
|
||||
try
|
||||
let response = {'number': a:request['number']}
|
||||
let starttime = xolox#misc#timer#start()
|
||||
try
|
||||
" Call the user defined function and store its result.
|
||||
let response['result'] = call(a:request['function'], a:request['arguments'])
|
||||
catch
|
||||
" Intercept errors raised by the user defined function.
|
||||
let response['exception'] = v:exception
|
||||
let response['throwpoint'] = v:throwpoint
|
||||
endtry
|
||||
" Record the elapsed time.
|
||||
let response['elapsed_time'] = xolox#misc#timer#convert(starttime)
|
||||
" Communicate the results back to the master Vim process.
|
||||
let servername = get(a:request, 'servername', '')
|
||||
if !empty(servername)
|
||||
" Actively notify the parent process using Vim's client/server support?
|
||||
call remote_expr(servername, printf('xolox#misc#async#callback_to_parent(%s)', string(response)))
|
||||
else
|
||||
" 'Passively' notify the parent process by creating the expected
|
||||
" temporary file.
|
||||
call xolox#misc#persist#save(a:request['temporary_file'], response)
|
||||
endif
|
||||
finally
|
||||
" Make sure we terminate this hidden Vim process.
|
||||
quitall!
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
function! xolox#misc#async#callback_to_parent(response) " {{{1
|
||||
" When Vim was compiled with client/server support this function (in the
|
||||
" parent process) will be called by `xolox#misc#async#inside_child()` (in
|
||||
" the child process) after the user defined function has returned. This
|
||||
" enables more or less instant callbacks after running an asynchronous
|
||||
" function.
|
||||
let unique_number = a:response['number']
|
||||
let request = g:xolox#misc#async#requests[unique_number]
|
||||
call xolox#misc#timer#stop("vim-misc %s: Processing asynchronous callback #%i after %s ..", g:xolox#misc#version, unique_number, request['starttime'])
|
||||
call remove(g:xolox#misc#async#requests, unique_number)
|
||||
let callback = get(request, 'callback')
|
||||
if !empty(callback)
|
||||
call call(callback, [a:response])
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! xolox#misc#async#periodic_callback() " {{{1
|
||||
" When client/server support is not being used the vim-misc plug-in
|
||||
" improvises: It uses Vim's [CursorHold][] event to periodically check if an
|
||||
" asynchronous process has written its results to one of the expected
|
||||
" temporary files. If a response is found the temporary file is read and
|
||||
" deleted and then `xolox#misc#async#callback_to_parent()` is called to
|
||||
" process the response.
|
||||
"
|
||||
" [CursorHold]: http://vimdoc.sourceforge.net/htmldoc/autocmd.html#CursorHold
|
||||
if !empty(g:xolox#misc#async#requests)
|
||||
let num_processed = 0
|
||||
call xolox#misc#msg#debug("vim-misc %s: Checking for asynchronous responses (%i responses not yet received) ..", g:xolox#misc#version, len(g:xolox#misc#async#requests))
|
||||
for unique_number in sort(keys(g:xolox#misc#async#requests))
|
||||
let request = g:xolox#misc#async#requests[unique_number]
|
||||
let temporary_file = get(request, 'temporary_file', '')
|
||||
if !empty(temporary_file) && getfsize(temporary_file) > 0
|
||||
try
|
||||
call xolox#misc#msg#debug("vim-misc %s: Found asynchronous response by %s in %s ..", g:xolox#misc#version, request['function'], temporary_file)
|
||||
call xolox#misc#async#callback_to_parent(xolox#misc#persist#load(temporary_file))
|
||||
let num_processed += 1
|
||||
finally
|
||||
call delete(temporary_file)
|
||||
endtry
|
||||
endif
|
||||
endfor
|
||||
call xolox#misc#msg#debug("vim-misc %s: Processed %i asynchronous responses (%i responses not yet received).", g:xolox#misc#version, num_processed, len(g:xolox#misc#async#requests))
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
" The interval in the options below is set to one (1) although the default
|
||||
" value for &updatetime is four seconds. Because vim-misc never modifies
|
||||
" &updatetime the interval will effectively default to four seconds unless the
|
||||
" user has set &updatetime to a lower value themselves.
|
||||
call xolox#misc#cursorhold#register({'function': 'xolox#misc#async#periodic_callback', 'interval': 1})
|
||||
|
||||
" vim: ts=2 sw=2 et
|
80
sources_non_forked/vim-misc/autoload/xolox/misc/buffer.vim
Executable file
80
sources_non_forked/vim-misc/autoload/xolox/misc/buffer.vim
Executable 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
|
26
sources_non_forked/vim-misc/autoload/xolox/misc/complete.vim
Executable file
26
sources_non_forked/vim-misc/autoload/xolox/misc/complete.vim
Executable file
@ -0,0 +1,26 @@
|
||||
" Tab completion for user defined commands.
|
||||
"
|
||||
" Author: Peter Odding <peter@peterodding.com>
|
||||
" Last Change: July 9, 2014
|
||||
" 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
|
||||
let arguments = [keys(filter(words, 'v:key =~# a:arglead'))]
|
||||
if &ignorecase
|
||||
call add(arguments, 1)
|
||||
endif
|
||||
return call('sort', arguments)
|
||||
endfunction
|
||||
|
||||
" vim: ts=2 sw=2 et
|
71
sources_non_forked/vim-misc/autoload/xolox/misc/cursorhold.vim
Executable file
71
sources_non_forked/vim-misc/autoload/xolox/misc/cursorhold.vim
Executable file
@ -0,0 +1,71 @@
|
||||
" Rate limiting for Vim's CursorHold event.
|
||||
"
|
||||
" Author: Peter Odding <peter@peterodding.com>
|
||||
" Last Change: June 22, 2014
|
||||
" URL: http://peterodding.com/code/vim/misc/
|
||||
"
|
||||
" Several of my Vim plug-ins (e.g. [vim-easytags][], [vim-notes][] and
|
||||
" [vim-session][]) use Vim's [CursorHold][] and [CursorHoldI][] events to
|
||||
" perform periodic tasks when the user doesn't press any keys for a couple of
|
||||
" seconds. These events by default fire after four seconds, this is
|
||||
" configurable using Vim's ['updatetime'][] option. The problem that this
|
||||
" script solves is that there are Vim plug-ins which set the ['updatetime'][]
|
||||
" option to unreasonably low values, thereby breaking my Vim plug-ins and
|
||||
" probably a lot of other Vim plug-ins out there. When users complain about
|
||||
" this I can tell them that another Vim plug-in is to blame, but users don't
|
||||
" care for the difference, their Vim is broken! So I implemented a workaround.
|
||||
" This script enables registration of [CursorHold][] event handlers with a
|
||||
" configurable interval (expressed in seconds). The event handlers will be
|
||||
" called no more than once every interval.
|
||||
"
|
||||
" ['updatetime']: http://vimdoc.sourceforge.net/htmldoc/options.html#'updatetime'
|
||||
" [CursorHold]: http://vimdoc.sourceforge.net/htmldoc/autocmd.html#CursorHold
|
||||
" [CursorHoldI]: http://vimdoc.sourceforge.net/htmldoc/autocmd.html#CursorHoldI
|
||||
" [vim-easytags]: http://peterodding.com/code/vim/easytags/
|
||||
" [vim-notes]: http://peterodding.com/code/vim/notes/
|
||||
" [vim-session]: http://peterodding.com/code/vim/session/
|
||||
|
||||
if !exists('g:xolox#misc#cursorhold#handlers')
|
||||
let g:xolox#misc#cursorhold#handlers = []
|
||||
endif
|
||||
|
||||
function! xolox#misc#cursorhold#register(options)
|
||||
" Register a [CursorHold][] event handler with a custom interval. This
|
||||
" function takes a single argument which is a dictionary with the following
|
||||
" fields:
|
||||
"
|
||||
" - **function** (required): The name of the event handler function (a
|
||||
" string).
|
||||
"
|
||||
" - **arguments** (optional): A list of arguments to pass to the event
|
||||
" handler function (defaults to an empty list).
|
||||
"
|
||||
" - **interval** (optional): The number of seconds between calls to the
|
||||
" event handler (defaults to 4).
|
||||
call add(g:xolox#misc#cursorhold#handlers, copy(a:options))
|
||||
endfunction
|
||||
|
||||
function! xolox#misc#cursorhold#autocmd()
|
||||
" The 'top level event handler' that's called by Vim whenever the
|
||||
" [CursorHold][] or [CursorHoldI][] event fires. It iterates through the
|
||||
" event handlers registered using `xolox#misc#cursorhold#register()` and
|
||||
" calls each event handler at the appropriate interval, keeping track of
|
||||
" the time when each event handler was last run.
|
||||
for handler in g:xolox#misc#cursorhold#handlers
|
||||
let function = handler['function']
|
||||
let last_run = get(handler, 'last_run', 0)
|
||||
let interval = get(handler, 'interval', 4)
|
||||
call xolox#misc#msg#debug("vim-misc %s: Checking handler %s with interval %i and last run %i ..", g:xolox#misc#version, function, interval, last_run)
|
||||
" Rate limit in case &updatetime is set (very) low.
|
||||
let time_until_next_run = (last_run + interval) - localtime()
|
||||
if time_until_next_run > 0
|
||||
call xolox#misc#msg#debug("vim-misc %s: Rate limiting handler %s (time until next run: %i seconds).", g:xolox#misc#version, function, time_until_next_run)
|
||||
else
|
||||
call xolox#misc#msg#debug("vim-misc %s: Running handler %s ..", g:xolox#misc#version, function)
|
||||
call call(function, get(handler, 'arguments', []))
|
||||
let handler['last_run'] = localtime()
|
||||
endif
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
" vim: ts=2 sw=2 et
|
BIN
sources_non_forked/vim-misc/autoload/xolox/misc/echo.exe
Executable file
BIN
sources_non_forked/vim-misc/autoload/xolox/misc/echo.exe
Executable file
Binary file not shown.
56
sources_non_forked/vim-misc/autoload/xolox/misc/escape.vim
Executable file
56
sources_non_forked/vim-misc/autoload/xolox/misc/escape.vim
Executable 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
|
46
sources_non_forked/vim-misc/autoload/xolox/misc/format.vim
Executable file
46
sources_non_forked/vim-misc/autoload/xolox/misc/format.vim
Executable 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
|
42
sources_non_forked/vim-misc/autoload/xolox/misc/list.vim
Executable file
42
sources_non_forked/vim-misc/autoload/xolox/misc/list.vim
Executable 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
|
129
sources_non_forked/vim-misc/autoload/xolox/misc/msg.vim
Executable file
129
sources_non_forked/vim-misc/autoload/xolox/misc/msg.vim
Executable file
@ -0,0 +1,129 @@
|
||||
" Functions to interact with the user.
|
||||
"
|
||||
" Author: Peter Odding <peter@peterodding.com>
|
||||
" Last Change: March 15, 2015
|
||||
" 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.
|
||||
"
|
||||
" The messages emitted by this function have no highlighting. Previously
|
||||
" these messages were highlighted using the [Title group] [hl-title], but it
|
||||
" was pointed out in [pull request 16] [pr-16] that this group shouldn't be
|
||||
" used for informational messages because it is meant for titles and because
|
||||
" of this some color schemes use colors that stand out quite a bit, causing
|
||||
" the informational messages to look like errors.
|
||||
"
|
||||
" [hl-title]: http://vimdoc.sourceforge.net/htmldoc/syntax.html#hl-Title
|
||||
" [pr-16]: https://github.com/xolox/vim-misc/pull/16
|
||||
" [printf()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#printf()
|
||||
" [string()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#string()
|
||||
call s:show_message('None', 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 the |hit-enter| prompt. We use :silent to avoid issues
|
||||
" like this one: https://github.com/xolox/vim-easytags/issues/69.
|
||||
silent! 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
|
100
sources_non_forked/vim-misc/autoload/xolox/misc/open.vim
Executable file
100
sources_non_forked/vim-misc/autoload/xolox/misc/open.vim
Executable 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', 'cygstart']
|
||||
|
||||
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
|
116
sources_non_forked/vim-misc/autoload/xolox/misc/option.vim
Executable file
116
sources_non_forked/vim-misc/autoload/xolox/misc/option.vim
Executable file
@ -0,0 +1,116 @@
|
||||
" Vim and plug-in option handling.
|
||||
"
|
||||
" Author: Peter Odding <peter@peterodding.com>
|
||||
" Last Change: April 1, 2015
|
||||
" 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 directory = (&cpoptions =~# 'd') ? getcwd() : expand('%:p:h')
|
||||
let pattern = xolox#misc#path#merge(directory, 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
|
284
sources_non_forked/vim-misc/autoload/xolox/misc/os.vim
Executable file
284
sources_non_forked/vim-misc/autoload/xolox/misc/os.vim
Executable file
@ -0,0 +1,284 @@
|
||||
" Operating system interfaces.
|
||||
"
|
||||
" Author: Peter Odding <peter@peterodding.com>
|
||||
" Last Change: May 21, 2015
|
||||
" 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
|
||||
" As pointed out in issue 17 [1] the use of `:!start' on Windows
|
||||
" requires characters like `!', `%' and `#' to be escaped with a
|
||||
" backslash [2]. Vim's shellescape() function knows how to escape
|
||||
" these special characters however the use of `:!start' is an
|
||||
" implementation detail of xolox#misc#os#exec() so I don't want to
|
||||
" bother callers (who perform the shell escaping) with such a
|
||||
" specific implementation detail. This is why I resort to manually
|
||||
" escaping characters documented to have a special meaning [2].
|
||||
"
|
||||
" [1] https://github.com/xolox/vim-misc/issues/17
|
||||
" [2] All characters interpreted specially in shell command lines
|
||||
" executed from Vim's command mode, refer to `:help :!' for
|
||||
" details.
|
||||
let cmd = printf('start /b %s', escape(cmd, "\\\n!%#"))
|
||||
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
|
278
sources_non_forked/vim-misc/autoload/xolox/misc/path.vim
Executable file
278
sources_non_forked/vim-misc/autoload/xolox/misc/path.vim
Executable file
@ -0,0 +1,278 @@
|
||||
" Pathname manipulation functions.
|
||||
"
|
||||
" Author: Peter Odding <peter@peterodding.com>
|
||||
" Last Change: July 7, 2014
|
||||
" URL: http://peterodding.com/code/vim/misc/
|
||||
|
||||
let s:windows_compatible = xolox#misc#os#is_win()
|
||||
|
||||
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 pathname we can simply split on slashes and
|
||||
" backslashes, although we should preserve a leading slash (which
|
||||
" denotes a pathname that is 'absolute to the current drive').
|
||||
let absolute = (a:path =~ '^[\/]')
|
||||
let segments = split(a:path, '[\/]\+')
|
||||
return absolute ? insert(segments, a:path[0]) : segments
|
||||
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:]
|
||||
elseif s:windows_compatible && parts[0] =~ '^[\/]$'
|
||||
" If a pathname is relative to the current drive we should add
|
||||
" the drive letter in order to make the pathname absolute.
|
||||
let parts[0] = matchstr(getcwd(), '^\a:')
|
||||
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#starts_with(a, b) " {{{1
|
||||
" Check whether the first pathname starts with the second pathname (expected
|
||||
" to be a directory). This does not perform a regular string comparison;
|
||||
" first it normalizes both pathnames, then it splits them into their
|
||||
" pathname segments and then it compares the segments.
|
||||
let a = xolox#misc#path#split(xolox#misc#path#absolute(a:a))
|
||||
let b = xolox#misc#path#split(xolox#misc#path#absolute(a:b))
|
||||
return a[0 : len(b) - 1] == b
|
||||
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 xolox#misc#os#is_mac()
|
||||
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
|
100
sources_non_forked/vim-misc/autoload/xolox/misc/perm.vim
Executable file
100
sources_non_forked/vim-misc/autoload/xolox/misc/perm.vim
Executable file
@ -0,0 +1,100 @@
|
||||
" Manipulation of UNIX file permissions.
|
||||
"
|
||||
" Author: Peter Odding <peter@peterodding.com>
|
||||
" Last Change: June 30, 2014
|
||||
" URL: http://peterodding.com/code/vim/misc/
|
||||
"
|
||||
" Vim's [writefile()][] function cannot set file permissions for newly created
|
||||
" files and although Vim script has a function to get file permissions (see
|
||||
" [getfperm()][]) there is no equivalent for changing a file's permissions.
|
||||
"
|
||||
" This omission breaks the otherwise very useful idiom of updating a file by
|
||||
" writing its new contents to a temporary file and then renaming the temporary
|
||||
" file into place (which is as close as you're going to get to atomically
|
||||
" updating a file's contents on UNIX) because the file's permissions will not
|
||||
" be preserved!
|
||||
"
|
||||
" **Here's a practical example:** My [vim-easytags][] plug-in writes tags file
|
||||
" updates to a temporary file and renames the temporary file into place. When
|
||||
" I use `sudo -s` on Ubuntu Linux it preserves my environment variables so my
|
||||
" `~/.vimrc` and the [vim-easytags][] plug-in are still loaded. Now when a
|
||||
" tags file is written the file becomes owned by root (my effective user id in
|
||||
" the `sudo` session). Once I leave the `sudo` session I can no longer update
|
||||
" my tags file because it's now owned by root … ಠ_ಠ
|
||||
"
|
||||
" [getfperm()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#getfperm()
|
||||
" [vim-easytags]: http://peterodding.com/code/vim/easytags/
|
||||
" [writefile()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#writefile()
|
||||
|
||||
function! xolox#misc#perm#update(fname, contents)
|
||||
" Atomically update a file's contents while preserving the owner, group and
|
||||
" mode. The first argument is the pathname of the file to update (a string).
|
||||
" The second argument is the list of lines to be written to the file. Writes
|
||||
" the new contents to a temporary file and renames the temporary file into
|
||||
" place, thereby preventing readers from reading a partially written file.
|
||||
" Returns 1 if the file is successfully updated, 0 otherwise.
|
||||
"
|
||||
" Note that if `xolox#misc#perm#get()` and `xolox#misc#perm#set()` cannot be
|
||||
" used to preserve the file owner/group/mode the file is still updated using
|
||||
" a rename (for compatibility with non-UNIX systems and incompatible
|
||||
" `/usr/bin/stat` implementations) so in that case you can still lose the
|
||||
" file's owner/group/mode.
|
||||
let starttime = xolox#misc#timer#start()
|
||||
let temporary_file = printf('%s.tmp', a:fname)
|
||||
call xolox#misc#msg#debug("vim-misc %s: Writing new contents of %s to temporary file %s ..", g:xolox#misc#version, a:fname, temporary_file)
|
||||
if writefile(a:contents, temporary_file) == 0
|
||||
call xolox#misc#perm#set(temporary_file, xolox#misc#perm#get(a:fname))
|
||||
call xolox#misc#msg#debug("vim-misc %s: Replacing %s with %s ..", g:xolox#misc#version, a:fname, temporary_file)
|
||||
if rename(temporary_file, a:fname) == 0
|
||||
call xolox#misc#timer#stop("vim-misc %s: Successfully updated %s using atomic rename in %s.", g:xolox#misc#version, a:fname, starttime)
|
||||
return 1
|
||||
endif
|
||||
endif
|
||||
if filereadable(temporary_file)
|
||||
call delete(temporary_file)
|
||||
endif
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
function! xolox#misc#perm#get(fname)
|
||||
" Get the owner, group and permissions of the pathname given as the first
|
||||
" argument. Returns an opaque value which you can later pass to
|
||||
" `xolox#misc#perm#set()`.
|
||||
let pathname = xolox#misc#path#absolute(a:fname)
|
||||
if filereadable(pathname)
|
||||
let command = printf('stat --format %s %s', '%U:%G:%a', shellescape(pathname))
|
||||
let result = xolox#misc#os#exec({'command': command, 'check': 0})
|
||||
if result['exit_code'] == 0 && len(result['stdout']) >= 1
|
||||
let tokens = split(result['stdout'][0], ':')
|
||||
if len(tokens) == 3
|
||||
let [owner, group, mode] = tokens
|
||||
let mode = '0' . mode
|
||||
call xolox#misc#msg#debug("vim-misc %s: File %s has owner %s, group %s, mode %s.", g:xolox#misc#version, pathname, owner, group, mode)
|
||||
return [owner, group, mode]
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
return []
|
||||
endfunction
|
||||
|
||||
function! xolox#misc#perm#set(fname, perms)
|
||||
" Set the permissions (the second argument) of the pathname given as the
|
||||
" first argument. Expects a permissions value created by
|
||||
" `xolox#misc#perm#get()`.
|
||||
if !empty(a:perms)
|
||||
let pathname = xolox#misc#path#absolute(a:fname)
|
||||
let [owner, group, mode] = a:perms
|
||||
if s:run('chown %s:%s %s', owner, group, pathname) && s:run('chmod %s %s', mode, pathname)
|
||||
call xolox#misc#msg#debug("vim-misc %s: Successfully set %s owner to %s, group to %s and permissions to %s.", g:xolox#misc#version, pathname, owner, group, mode)
|
||||
return 1
|
||||
endif
|
||||
endif
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
function! s:run(command, ...)
|
||||
let args = map(copy(a:000), 'shellescape(v:val)')
|
||||
call insert(args, a:command, 0)
|
||||
let result = xolox#misc#os#exec({'command': call('printf', args), 'check': 0})
|
||||
return result['exit_code'] == 0
|
||||
endfunction
|
50
sources_non_forked/vim-misc/autoload/xolox/misc/persist.vim
Executable file
50
sources_non_forked/vim-misc/autoload/xolox/misc/persist.vim
Executable file
@ -0,0 +1,50 @@
|
||||
" Persist/recall Vim values from/to files.
|
||||
"
|
||||
" Author: Peter Odding <peter@peterodding.com>
|
||||
" Last Change: June 30, 2014
|
||||
" URL: http://peterodding.com/code/vim/misc/
|
||||
"
|
||||
" Vim's [string()][] function can be used to serialize Vim script values like
|
||||
" numbers, strings, lists, dictionaries and composites of them to a string
|
||||
" which can later be evaluated using the [eval()][] function to turn it back
|
||||
" into the original value. This Vim script provides functions to use these
|
||||
" functions to persist and recall Vim values from/to files. This is very
|
||||
" useful for communication between (possibly concurrent) Vim processes.
|
||||
|
||||
function! xolox#misc#persist#load(filename, ...) " {{{1
|
||||
" Read a Vim value like a number, string, list or dictionary from a file
|
||||
" using [readfile()][] and [eval()][]. The first argument is the filename of
|
||||
" the file to read (a string). The optional second argument specifies the
|
||||
" default value which is returned when the file can't be loaded. This
|
||||
" function returns the loaded value or the default value (which itself
|
||||
" defaults to the integer 0).
|
||||
"
|
||||
" [eval()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#eval()
|
||||
" [readfile()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#readfile()
|
||||
let default_value = exists('a:1') ? a:1 : 0
|
||||
try
|
||||
let lines = readfile(a:filename)
|
||||
return eval(join(lines, "\n"))
|
||||
catch
|
||||
return default_value
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
function! xolox#misc#persist#save(filename, value) " {{{1
|
||||
" Write a Vim value like a number, string, list or dictionary to a file
|
||||
" using [string()][] and [writefile()][]. The first argument is the filename
|
||||
" of the file to write (a string) and the second argument is the value to
|
||||
" write (any value).
|
||||
"
|
||||
" This function writes the serialized value to an intermediate file which is
|
||||
" then renamed into place atomically. This avoids issues with concurrent
|
||||
" processes where for example a producer has written a partial file which is
|
||||
" read by a consumer before the file is complete. In this case the consumer
|
||||
" would read a corrupt value. The rename trick avoids this problem.
|
||||
"
|
||||
" [string()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#string()
|
||||
" [writefile()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#writefile()
|
||||
return xolox#misc#perm#update(a:filename, split(string(a:value), "\n"))
|
||||
endfunction
|
||||
|
||||
" vim: ts=2 sw=2 et
|
74
sources_non_forked/vim-misc/autoload/xolox/misc/str.vim
Executable file
74
sources_non_forked/vim-misc/autoload/xolox/misc/str.vim
Executable file
@ -0,0 +1,74 @@
|
||||
" String handling.
|
||||
"
|
||||
" Author: Peter Odding <peter@peterodding.com>
|
||||
" Last Change: September 17, 2014
|
||||
" 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#unescape(s) " {{{1
|
||||
" Remove back slash escapes from a string (the first argument).
|
||||
return substitute(a:s, '\\\(\_.\)', '\1', 'g')
|
||||
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
|
125
sources_non_forked/vim-misc/autoload/xolox/misc/test.vim
Executable file
125
sources_non_forked/vim-misc/autoload/xolox/misc/test.vim
Executable 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()
|
301
sources_non_forked/vim-misc/autoload/xolox/misc/tests.vim
Executable file
301
sources_non_forked/vim-misc/autoload/xolox/misc/tests.vim
Executable 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
|
130
sources_non_forked/vim-misc/autoload/xolox/misc/timer.vim
Executable file
130
sources_non_forked/vim-misc/autoload/xolox/misc/timer.vim
Executable file
@ -0,0 +1,130 @@
|
||||
" Timing of long during operations.
|
||||
"
|
||||
" Author: Peter Odding <peter@peterodding.com>
|
||||
" Last Change: July 19, 2014
|
||||
" 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#resumable() " {{{1
|
||||
" Create a resumable timer object. This returns an object (a dictionary with
|
||||
" functions) with the following "methods":
|
||||
"
|
||||
" - `start()` instructs the timer object to start counting elapsed time
|
||||
" (when a timer object is created it is not automatically started).
|
||||
"
|
||||
" - `stop()` instructs the timer object to stop counting elapsed time.
|
||||
" This adds the time elapsed since `start()` was last called to the
|
||||
" total elapsed time. This method will raise an error if called out of
|
||||
" sequence.
|
||||
"
|
||||
" - `format()` takes the total elapsed time and reports it as a string
|
||||
" containing a formatted floating point number.
|
||||
"
|
||||
" Timer objects are meant to accurately time short running operations so
|
||||
" they're dependent on Vim's [reltime()][] and [reltimestr()][] functions.
|
||||
" In order to make it possible to use timer objects in my Vim plug-ins
|
||||
" unconditionally there's a fall back to [localtime()][] when [reltime()][]
|
||||
" is not available. In this mode the timer objects are not very useful but
|
||||
" at least they shouldn't raise errors.
|
||||
"
|
||||
" [localtime()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#localtime()
|
||||
" [reltime()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#reltime()
|
||||
" [reltimestr()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#reltimestr()
|
||||
let object = {'total': [0, 0]}
|
||||
function object.start() dict
|
||||
if s:has_reltime
|
||||
let self.current = reltime()
|
||||
else
|
||||
let self.current = localtime()
|
||||
endif
|
||||
endfunction
|
||||
function object.stop() dict
|
||||
if empty(get(self, 'current'))
|
||||
throw "timer.stop() called on a timer that was never started!"
|
||||
endif
|
||||
if s:has_reltime
|
||||
let elapsed_time_string = xolox#misc#str#trim(reltimestr(reltime(self.current)))
|
||||
" This is a bit silly (converting to a string and then parsing that) but
|
||||
" the value of reltime() is documented as being platform specific...
|
||||
let [seconds, microseconds] = split(elapsed_time_string, '\.')
|
||||
let self.total[0] += substitute(seconds, '^0*', '', '')
|
||||
let self.total[1] += substitute(microseconds, '^0*', '', '')
|
||||
let self.current = []
|
||||
else
|
||||
let self.total[0] += localtime() - self.current
|
||||
let self.current = 0
|
||||
endif
|
||||
endfunction
|
||||
function object.format() dict
|
||||
let seconds = self.total[0]
|
||||
let microseconds = self.total[1]
|
||||
if microseconds >= 1000000
|
||||
let additional_seconds = microseconds / 1000000
|
||||
let seconds += additional_seconds
|
||||
let microseconds -= additional_seconds * 1000000
|
||||
endif
|
||||
return printf('%i.%06i', seconds, microseconds)
|
||||
endfunction
|
||||
return object
|
||||
endfunction
|
||||
|
||||
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), 'xolox#misc#timer#convert(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), 'xolox#misc#timer#convert(v:val)'))
|
||||
endfunction
|
||||
|
||||
function! xolox#misc#timer#convert(value) " {{{1
|
||||
" Convert the value returned by `xolox#misc#timer#start()` to a string
|
||||
" representation of the elapsed time since `xolox#misc#timer#start()` was
|
||||
" called. Other values are returned unmodified (this allows using it with
|
||||
" Vim's [map()][] function).
|
||||
"
|
||||
" [map()]: http://vimdoc.sourceforge.net/htmldoc/eval.html#map()
|
||||
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)
|
||||
endif
|
||||
return a:value
|
||||
endfunction
|
||||
|
||||
" vim: ts=2 sw=2 et
|
34
sources_non_forked/vim-misc/autoload/xolox/misc/version.vim
Executable file
34
sources_non_forked/vim-misc/autoload/xolox/misc/version.vim
Executable 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
|
1204
sources_non_forked/vim-misc/doc/misc.txt
Executable file
1204
sources_non_forked/vim-misc/doc/misc.txt
Executable file
File diff suppressed because it is too large
Load Diff
19
sources_non_forked/vim-misc/plugin/xolox/misc.vim
Executable file
19
sources_non_forked/vim-misc/plugin/xolox/misc.vim
Executable file
@ -0,0 +1,19 @@
|
||||
" Vim plug-in
|
||||
" Author: Peter Odding <peter@peterodding.com>
|
||||
" Last Change: June 21, 2014
|
||||
" URL: http://peterodding.com/code/vim/misc/
|
||||
|
||||
" Don't source the plug-in when it's already been loaded or &compatible is set.
|
||||
if &cp || exists('g:loaded_xolox_misc')
|
||||
finish
|
||||
endif
|
||||
|
||||
" Automatic commands used by the vim-misc plug-in.
|
||||
augroup PluginXoloxMisc
|
||||
autocmd! CursorHold,CursorHoldI * call xolox#misc#cursorhold#autocmd()
|
||||
augroup END
|
||||
|
||||
" Make sure the plug-in is only loaded once.
|
||||
let g:loaded_xolox_misc = 1
|
||||
|
||||
" vim: ts=2 sw=2 et
|
Reference in New Issue
Block a user