"============================================================================= " FILE: util.vim " AUTHOR: Shougo Matsushita <Shougo.Matsu at gmail.com> " License: MIT license {{{ " Permission is hereby granted, free of charge, to any person obtaining " a copy of this software and associated documentation files (the " "Software"), to deal in the Software without restriction, including " without limitation the rights to use, copy, modify, merge, publish, " distribute, sublicense, and/or sell copies of the Software, and to " permit persons to whom the Software is furnished to do so, subject to " the following conditions: " " The above copyright notice and this permission notice shall be included " in all copies or substantial portions of the Software. " " THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS " OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF " MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. " IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY " CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, " TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE " SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. " }}} "============================================================================= let s:save_cpo = &cpo set cpo&vim let s:is_windows = has('win32') let s:is_cygwin = has('win32unix') let s:is_mac = !s:is_windows && !s:is_cygwin \ && (has('mac') || has('macunix') || has('gui_macvim') || \ (!isdirectory('/proc') && executable('sw_vers'))) function! neobundle#util#substitute_path_separator(path) abort "{{{ return (s:is_windows && a:path =~ '\\') ? \ tr(a:path, '\', '/') : a:path endfunction"}}} function! neobundle#util#expand(path) abort "{{{ let path = (a:path =~ '^\~') ? fnamemodify(a:path, ':p') : \ (a:path =~ '^\$\h\w*') ? substitute(a:path, \ '^\$\h\w*', '\=eval(submatch(0))', '') : \ a:path return (s:is_windows && path =~ '\\') ? \ neobundle#util#substitute_path_separator(path) : path endfunction"}}} function! neobundle#util#join_paths(path1, path2) abort "{{{ " Joins two paths together, handling the case where the second path " is an absolute path. if s:is_absolute(a:path2) return a:path2 endif if a:path1 =~ (s:is_windows ? '[\\/]$' : '/$') || \ a:path2 =~ (s:is_windows ? '^[\\/]' : '^/') " the appropriate separator already exists return a:path1 . a:path2 else " note: I'm assuming here that '/' is always valid as a directory " separator on Windows. I know Windows has paths that start with \\?\ that " diasble behavior like that, but I don't know how Vim deals with that. return a:path1 . '/' . a:path2 endif endfunction "}}} if s:is_windows function! s:is_absolute(path) abort "{{{ return a:path =~ '^[\\/]\|^\a:' endfunction "}}} else function! s:is_absolute(path) abort "{{{ return a:path =~ "^/" endfunction "}}} endif function! neobundle#util#is_windows() abort "{{{ return s:is_windows endfunction"}}} function! neobundle#util#is_mac() abort "{{{ return s:is_mac endfunction"}}} function! neobundle#util#is_cygwin() abort "{{{ return s:is_cygwin endfunction"}}} " Sudo check. function! neobundle#util#is_sudo() abort "{{{ return $SUDO_USER != '' && $USER !=# $SUDO_USER \ && $HOME !=# expand('~'.$USER) \ && $HOME ==# expand('~'.$SUDO_USER) endfunction"}}} " Check vimproc. "{{{ function! neobundle#util#has_vimproc() abort "{{{ if !exists('*vimproc#version') try call vimproc#version() catch endtry endif return exists('*vimproc#version') endfunction"}}} "}}} " iconv() wrapper for safety. function! s:iconv(expr, from, to) abort "{{{ if a:from == '' || a:to == '' || a:from ==? a:to return a:expr endif let result = iconv(a:expr, a:from, a:to) return result != '' ? result : a:expr endfunction"}}} function! neobundle#util#system(str, ...) abort "{{{ let command = a:str let input = a:0 >= 1 ? a:1 : '' let command = s:iconv(command, &encoding, 'char') let input = s:iconv(input, &encoding, 'char') if a:0 == 0 let output = neobundle#util#has_vimproc() ? \ vimproc#system(command) : system(command, "\<C-d>") elseif a:0 == 1 let output = neobundle#util#has_vimproc() ? \ vimproc#system(command, input) : system(command, input) else " ignores 3rd argument unless you have vimproc. let output = neobundle#util#has_vimproc() ? \ vimproc#system(command, input, a:2) : system(command, input) endif let output = s:iconv(output, 'char', &encoding) return substitute(output, '\n$', '', '') endfunction"}}} function! neobundle#util#get_last_status() abort "{{{ return neobundle#util#has_vimproc() ? \ vimproc#get_last_status() : v:shell_error endfunction"}}} " Split a comma separated string to a list. function! neobundle#util#split_rtp(runtimepath) abort "{{{ if stridx(a:runtimepath, '\,') < 0 return split(a:runtimepath, ',') endif let split = split(a:runtimepath, '\\\@<!\%(\\\\\)*\zs,') return map(split,'substitute(v:val, ''\\\([\\,]\)'', "\\1", "g")') endfunction"}}} function! neobundle#util#join_rtp(list, runtimepath, rtp) abort "{{{ return (stridx(a:runtimepath, '\,') < 0 && stridx(a:rtp, ',') < 0) ? \ join(a:list, ',') : join(map(copy(a:list), 's:escape(v:val)'), ',') endfunction"}}} function! neobundle#util#split_envpath(path) abort "{{{ let delimiter = neobundle#util#is_windows() ? ';' : ':' if stridx(a:path, '\' . delimiter) < 0 return split(a:path, delimiter) endif let split = split(a:path, '\\\@<!\%(\\\\\)*\zs' . delimiter) return map(split,'substitute(v:val, ''\\\([\\' \ . delimiter . ']\)'', "\\1", "g")') endfunction"}}} function! neobundle#util#join_envpath(list, orig_path, add_path) abort "{{{ let delimiter = neobundle#util#is_windows() ? ';' : ':' return (stridx(a:orig_path, '\' . delimiter) < 0 \ && stridx(a:add_path, delimiter) < 0) ? \ join(a:list, delimiter) : \ join(map(copy(a:list), 's:escape(v:val)'), delimiter) endfunction"}}} " Removes duplicates from a list. function! neobundle#util#uniq(list, ...) abort "{{{ let list = a:0 ? map(copy(a:list), printf('[v:val, %s]', a:1)) : copy(a:list) let i = 0 let seen = {} while i < len(list) let key = string(a:0 ? list[i][1] : list[i]) if has_key(seen, key) call remove(list, i) else let seen[key] = 1 let i += 1 endif endwhile return a:0 ? map(list, 'v:val[0]') : list endfunction"}}} function! neobundle#util#set_default(var, val, ...) abort "{{{ if !exists(a:var) || type({a:var}) != type(a:val) let alternate_var = get(a:000, 0, '') let {a:var} = exists(alternate_var) ? \ {alternate_var} : a:val endif endfunction"}}} function! neobundle#util#set_dictionary_helper(variable, keys, pattern) abort "{{{ for key in split(a:keys, '\s*,\s*') if !has_key(a:variable, key) let a:variable[key] = a:pattern endif endfor endfunction"}}} function! neobundle#util#get_filetypes() abort "{{{ let filetype = exists('b:neocomplcache.context_filetype') ? \ b:neocomplcache.context_filetype : &filetype return split(filetype, '\.') endfunction"}}} function! neobundle#util#convert2list(expr) abort "{{{ return type(a:expr) ==# type([]) ? a:expr : \ type(a:expr) ==# type('') ? \ (a:expr == '' ? [] : split(a:expr, '\r\?\n', 1)) \ : [a:expr] endfunction"}}} function! neobundle#util#print_error(expr) abort "{{{ return s:echo(a:expr, 'error') endfunction"}}} function! neobundle#util#redraw_echo(expr) abort "{{{ return s:echo(a:expr, 'echo') endfunction"}}} function! neobundle#util#redraw_echomsg(expr) abort "{{{ return s:echo(a:expr, 'echomsg') endfunction"}}} function! s:echo(expr, mode) abort "{{{ let msg = map(neobundle#util#convert2list(a:expr), \ "'[neobundle] ' . v:val") if empty(msg) return endif if has('vim_starting') || a:mode ==# 'error' call s:echo_mode(join(msg, "\n"), a:mode) return endif let more_save = &more let showcmd_save = &showcmd let ruler_save = &ruler try set nomore set noshowcmd set noruler let height = max([1, &cmdheight]) echo '' for i in range(0, len(msg)-1, height) redraw call s:echo_mode(join(msg[i : i+height-1], "\n"), a:mode) endfor finally let &more = more_save let &showcmd = showcmd_save let &ruler = ruler_save endtry endfunction"}}} function! s:echo_mode(m, mode) abort "{{{ for m in split(a:m, '\r\?\n', 1) if !has('vim_starting') && a:mode !=# 'error' let m = neobundle#util#truncate_skipping( \ m, &columns - 1, &columns/3, '...') endif if a:mode ==# 'error' echohl WarningMsg | echomsg m | echohl None elseif a:mode ==# 'echomsg' echomsg m else echo m endif endfor endfunction"}}} function! neobundle#util#name_conversion(path) abort "{{{ return fnamemodify(split(a:path, ':')[-1], ':s?/$??:t:s?\c\.git\s*$??') endfunction"}}} function! neobundle#util#vim2json(expr) abort "{{{ return has('patch-7.4.1498') ? json_encode(a:expr) : string(a:expr) endfunction "}}} function! neobundle#util#json2vim(expr) abort "{{{ sandbox return has('patch-7.4.1498') ? json_decode(a:expr) : eval(a:expr) endfunction "}}} " Escape a path for runtimepath. function! s:escape(path) abort"{{{ return substitute(a:path, ',\|\\,\@=', '\\\0', 'g') endfunction"}}} function! neobundle#util#unify_path(path) abort "{{{ return fnamemodify(resolve(a:path), ':p:gs?\\\+?/?') endfunction"}}} function! neobundle#util#cd(path) abort "{{{ if isdirectory(a:path) execute (haslocaldir() ? 'lcd' : 'cd') fnameescape(a:path) endif endfunction"}}} function! neobundle#util#writefile(path, list) abort "{{{ let path = neobundle#get_neobundle_dir() . '/.neobundle/' . a:path let dir = fnamemodify(path, ':h') if !isdirectory(dir) call mkdir(dir, 'p') endif return writefile(a:list, path) endfunction"}}} function! neobundle#util#cleandir(path) abort "{{{ let path = neobundle#get_neobundle_dir() . '/.neobundle/' . a:path for file in filter(split(globpath(path, '*', 1), '\n'), \ '!isdirectory(v:val)') call delete(file) endfor endfunction"}}} function! neobundle#util#rmdir(path) abort "{{{ if has('patch-7.4.1120') call delete(a:path, 'rf') else let cmdline = '"' . a:path . '"' if neobundle#util#is_windows() " Note: In rm command, must use "\" instead of "/". let cmdline = substitute(cmdline, '/', '\\\\', 'g') endif " Use system instead of vimproc#system() let result = system(g:neobundle#rm_command . ' ' . cmdline) if v:shell_error call neobundle#installer#error(result) endif endif endfunction"}}} function! neobundle#util#copy_bundle_files(bundles, directory) abort "{{{ " Delete old files. call neobundle#util#cleandir(a:directory) let files = {} for bundle in a:bundles for file in filter(split(globpath( \ bundle.rtp, a:directory.'/**', 1), '\n'), \ '!isdirectory(v:val)') let filename = fnamemodify(file, ':t') let files[filename] = readfile(file) endfor endfor for [filename, list] in items(files) if filename =~# '^tags\%(-.*\)\?$' call sort(list) endif call neobundle#util#writefile(a:directory . '/' . filename, list) endfor endfunction"}}} function! neobundle#util#merge_bundle_files(bundles, directory) abort "{{{ " Delete old files. call neobundle#util#cleandir(a:directory) let files = [] for bundle in a:bundles for file in filter(split(globpath( \ bundle.rtp, a:directory.'/**', 1), '\n'), \ '!isdirectory(v:val)') let files += readfile(file, ':t') endfor endfor call neobundle#util#writefile( \ a:directory.'/'.a:directory . '.vim', files) endfunction"}}} " Sorts a list using a set of keys generated by mapping the values in the list " through the given expr. " v:val is used in {expr} function! neobundle#util#sort_by(list, expr) abort "{{{ let pairs = map(a:list, printf('[v:val, %s]', a:expr)) return map(s:sort(pairs, \ 'a:a[1] ==# a:b[1] ? 0 : a:a[1] ># a:b[1] ? 1 : -1'), 'v:val[0]') endfunction"}}} " Executes a command and returns its output. " This wraps Vim's `:redir`, and makes sure that the `verbose` settings have " no influence. function! neobundle#util#redir(cmd) abort "{{{ let [save_verbose, save_verbosefile] = [&verbose, &verbosefile] set verbose=0 verbosefile= redir => res silent! execute a:cmd redir END let [&verbose, &verbosefile] = [save_verbose, save_verbosefile] return res endfunction"}}} " Sorts a list with expression to compare each two values. " a:a and a:b can be used in {expr}. function! s:sort(list, expr) abort "{{{ if type(a:expr) == type(function('function')) return sort(a:list, a:expr) endif let s:expr = a:expr return sort(a:list, 's:_compare') endfunction"}}} function! s:_compare(a, b) abort return eval(s:expr) endfunction function! neobundle#util#print_bundles(bundles) abort "{{{ echomsg string(map(copy(a:bundles), 'v:val.name')) endfunction"}}} function! neobundle#util#sort_human(filenames) abort "{{{ return sort(a:filenames, 's:compare_filename') endfunction"}}} " Compare filename by human order. "{{{ function! s:compare_filename(i1, i2) abort let words_1 = s:get_words(a:i1) let words_2 = s:get_words(a:i2) let words_1_len = len(words_1) let words_2_len = len(words_2) for i in range(0, min([words_1_len, words_2_len])-1) if words_1[i] >? words_2[i] return 1 elseif words_1[i] <? words_2[i] return -1 endif endfor return words_1_len - words_2_len endfunction"}}} function! s:get_words(filename) abort "{{{ let words = [] for split in split(a:filename, '\d\+\zs\ze') let words += split(split, '\D\zs\ze\d\+') endfor return map(words, "v:val =~ '^\\d\\+$' ? str2nr(v:val) : v:val") endfunction"}}} function! neobundle#util#wget(uri, outpath) abort "{{{ if executable('curl') return printf('curl --fail -s -o "%s" "%s"', a:outpath, a:uri) elseif executable('wget') return printf('wget -q -O "%s" "%s"', a:outpath, a:uri) else return 'E: curl or wget command is not available!' endif endfunction"}}} function! neobundle#util#truncate_skipping(str, max, footer_width, separator) abort "{{{ let width = s:wcswidth(a:str) if width <= a:max let ret = a:str else let header_width = a:max - s:wcswidth(a:separator) - a:footer_width let ret = s:strwidthpart(a:str, header_width) . a:separator \ . s:strwidthpart_reverse(a:str, a:footer_width) endif return ret endfunction"}}} function! s:strwidthpart(str, width) abort "{{{ if a:width <= 0 return '' endif let ret = a:str let width = s:wcswidth(a:str) while width > a:width let char = matchstr(ret, '.$') let ret = ret[: -1 - len(char)] let width -= s:wcswidth(char) endwhile return ret endfunction"}}} function! s:strwidthpart_reverse(str, width) abort "{{{ if a:width <= 0 return '' endif let ret = a:str let width = s:wcswidth(a:str) while width > a:width let char = matchstr(ret, '^.') let ret = ret[len(char) :] let width -= s:wcswidth(char) endwhile return ret endfunction"}}} function! s:wcswidth(str) abort "{{{ return v:version >= 704 ? strwidth(a:str) : strlen(a:str) endfunction"}}} let &cpo = s:save_cpo unlet s:save_cpo " vim: foldmethod=marker