├── autoload ├── vital │ ├── vital_complete.vital │ ├── _vital_complete.vim │ ├── _vital_complete │ │ ├── Vim │ │ │ ├── Message.vim │ │ │ └── ScriptLocal.vim │ │ ├── Data │ │ │ └── Dict.vim │ │ ├── System │ │ │ ├── Filepath.vim │ │ │ └── File.vim │ │ └── Prelude.vim │ ├── vital_complete.data │ └── vital_complete.vim ├── vital.vim ├── neocomplete │ └── sources │ │ └── vital.vim └── vital_complete.vim ├── README.md └── plugin └── vital_complete.vim /autoload/vital/vital_complete.vital: -------------------------------------------------------------------------------- 1 | vital_complete 2 | 234feb9acc70c239d0f7de2597067f8743fe1e7e 3 | 4 | System.File 5 | Vim.Message 6 | Vim.ScriptLocal 7 | Data.Dict 8 | -------------------------------------------------------------------------------- /autoload/vital/_vital_complete.vim: -------------------------------------------------------------------------------- 1 | let s:_plugin_name = expand(':t:r') 2 | 3 | function! vital#{s:_plugin_name}#new() abort 4 | return vital#{s:_plugin_name[1:]}#of() 5 | endfunction 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | vital-complete 2 | ============== 3 | 4 | [EXPERIMENTAL] Completion for https://github.com/vim-jp/vital.vim 5 | 6 | ![vital-complete](https://cloud.githubusercontent.com/assets/3797062/14069055/5a2e5c7e-f4cf-11e5-8d4a-503d17d03d35.gif) 7 | 8 | ## License 9 | 10 | [NYSL](http://www.kmonos.net/nysl/index.en.html) 11 | 12 | Japanese original text: 13 | -------------------------------------------------------------------------------- /autoload/vital.vim: -------------------------------------------------------------------------------- 1 | function! vital#of(name) abort 2 | let files = globpath(&runtimepath, 'autoload/vital/' . a:name . '.vital') 3 | let file = split(files, "\n") 4 | if empty(file) 5 | throw 'vital: version file not found: ' . a:name 6 | endif 7 | let ver = readfile(file[0], 'b') 8 | if empty(ver) 9 | throw 'vital: invalid version file: ' . a:name 10 | endif 11 | return vital#_{substitute(ver[0], '\W', '', 'g')}#new() 12 | endfunction 13 | -------------------------------------------------------------------------------- /plugin/vital_complete.vim: -------------------------------------------------------------------------------- 1 | scriptencoding utf-8 2 | if expand('%:p') ==# expand(':p') 3 | unlet! g:loaded_vital_complete 4 | endif 5 | if exists('g:loaded_vital_complete') 6 | finish 7 | endif 8 | let g:loaded_vital_complete = 1 9 | let s:save_cpo = &cpo 10 | set cpo&vim 11 | 12 | command! -nargs=1 VitalCompleteUpdate call vital_complete#update() 13 | 14 | inoremap (vital-complete-manual-completion) =vital_complete#manual_complete() 15 | 16 | let &cpo = s:save_cpo 17 | unlet s:save_cpo 18 | " __END__ 19 | " vim: expandtab softtabstop=2 shiftwidth=2 foldmethod=marker 20 | -------------------------------------------------------------------------------- /autoload/neocomplete/sources/vital.vim: -------------------------------------------------------------------------------- 1 | "============================================================================= 2 | " FILE: autoload/neocomplete/sources/vital.vim 3 | " AUTHOR: haya14busa 4 | " License: MIT license 5 | "============================================================================= 6 | scriptencoding utf-8 7 | let s:save_cpo = &cpo 8 | set cpo&vim 9 | 10 | let s:source = { 11 | \ 'name': 'vital', 12 | \ 'kind': 'manual', 13 | \ 'input_pattern': '\h\w*\.\?', 14 | \ 'filetypes': {'vim': 1, 'vimspec': 1}, 15 | \ } 16 | " vimspec: for https://github.com/thinca/vim-themis 17 | 18 | function! s:source.get_complete_position(context) 19 | return vital_complete#find_start_col() 20 | endfunction 21 | 22 | function! s:source.gather_candidates(context) 23 | let ctx = vital_complete#context() 24 | return vital_complete#completion_items(ctx, a:context.complete_str) 25 | endfunction 26 | 27 | function! neocomplete#sources#vital#define() abort 28 | return s:source 29 | endfunction 30 | 31 | let &cpo = s:save_cpo 32 | unlet s:save_cpo 33 | " __END__ 34 | " vim: expandtab softtabstop=2 shiftwidth=2 foldmethod=marker 35 | -------------------------------------------------------------------------------- /autoload/vital/_vital_complete/Vim/Message.vim: -------------------------------------------------------------------------------- 1 | " ___vital___ 2 | " NOTE: lines between '" ___vital___' is generated by :Vitalize. 3 | " Do not mofidify the code nor insert new lines before '" ___vital___' 4 | if v:version > 703 || v:version == 703 && has('patch1170') 5 | function! vital#_vital_complete#Vim#Message#import() abort 6 | return map({'capture': '', 'echomsg': '', 'echo': '', 'warn': '', 'get_hit_enter_max_length': '', 'error': ''}, 'function("s:" . v:key)') 7 | endfunction 8 | else 9 | function! s:_SID() abort 10 | return matchstr(expand(''), '\zs\d\+\ze__SID$') 11 | endfunction 12 | execute join(['function! vital#_vital_complete#Vim#Message#import() abort', printf("return map({'capture': '', 'echomsg': '', 'echo': '', 'warn': '', 'get_hit_enter_max_length': '', 'error': ''}, \"function('%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n") 13 | delfunction s:_SID 14 | endif 15 | " ___vital___ 16 | let s:save_cpo = &cpo 17 | set cpo&vim 18 | 19 | 20 | 21 | function! s:echo(hl, msg) abort 22 | execute 'echohl' a:hl 23 | try 24 | echo a:msg 25 | finally 26 | echohl None 27 | endtry 28 | endfunction 29 | 30 | function! s:echomsg(hl, msg) abort 31 | execute 'echohl' a:hl 32 | try 33 | for m in split(a:msg, "\n") 34 | echomsg m 35 | endfor 36 | finally 37 | echohl None 38 | endtry 39 | endfunction 40 | 41 | function! s:error(msg) abort 42 | call s:echomsg('ErrorMsg', a:msg) 43 | endfunction 44 | 45 | function! s:warn(msg) abort 46 | call s:echomsg('WarningMsg', a:msg) 47 | endfunction 48 | 49 | function! s:capture(command) abort 50 | try 51 | redir => out 52 | silent execute a:command 53 | finally 54 | redir END 55 | endtry 56 | return out 57 | endfunction 58 | 59 | " * Get max length of |hit-enter|. 60 | " If a string length of a message is greater than the max length, 61 | " Vim waits for user input according to |hit-enter|. 62 | " XXX: Those fixed values may be different between different OSes? 63 | " Currently tested on only Windows. 64 | function! s:get_hit_enter_max_length() abort 65 | let maxlen = &columns * &cmdheight - 1 66 | if &ruler 67 | " TODO 68 | endif 69 | if &showcmd 70 | let maxlen -= 11 71 | endif 72 | return maxlen 73 | endfunction 74 | 75 | 76 | 77 | let &cpo = s:save_cpo 78 | unlet s:save_cpo 79 | 80 | " vim:set et ts=2 sts=2 sw=2 tw=0: 81 | -------------------------------------------------------------------------------- /autoload/vital/_vital_complete/Data/Dict.vim: -------------------------------------------------------------------------------- 1 | " ___vital___ 2 | " NOTE: lines between '" ___vital___' is generated by :Vitalize. 3 | " Do not mofidify the code nor insert new lines before '" ___vital___' 4 | if v:version > 703 || v:version == 703 && has('patch1170') 5 | function! vital#_vital_complete#Data#Dict#import() abort 6 | return map({'pick': '', 'clear': '', 'max_by': '', 'foldl': '', 'swap': '', 'omit': '', 'min_by': '', 'foldr': '', 'make_index': '', 'make': ''}, 'function("s:" . v:key)') 7 | endfunction 8 | else 9 | function! s:_SID() abort 10 | return matchstr(expand(''), '\zs\d\+\ze__SID$') 11 | endfunction 12 | execute join(['function! vital#_vital_complete#Data#Dict#import() abort', printf("return map({'pick': '', 'clear': '', 'max_by': '', 'foldl': '', 'swap': '', 'omit': '', 'min_by': '', 'foldr': '', 'make_index': '', 'make': ''}, \"function('%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n") 13 | delfunction s:_SID 14 | endif 15 | " ___vital___ 16 | " Utilities for dictionary. 17 | 18 | let s:save_cpo = &cpo 19 | set cpo&vim 20 | 21 | " Makes a dict from keys and values 22 | function! s:make(keys, values, ...) abort 23 | let dict = {} 24 | let fill = a:0 ? a:1 : 0 25 | for i in range(len(a:keys)) 26 | let key = type(a:keys[i]) == type('') ? a:keys[i] : string(a:keys[i]) 27 | if key ==# '' 28 | throw "vital: Data.Dict: Can't use an empty string for key." 29 | endif 30 | let dict[key] = get(a:values, i, fill) 31 | endfor 32 | return dict 33 | endfunction 34 | 35 | " Swaps keys and values 36 | function! s:swap(dict) abort 37 | return s:make(values(a:dict), keys(a:dict)) 38 | endfunction 39 | 40 | " Makes a index dict from a list 41 | function! s:make_index(list, ...) abort 42 | let value = a:0 ? a:1 : 1 43 | return s:make(a:list, [], value) 44 | endfunction 45 | 46 | function! s:pick(dict, keys) abort 47 | let new_dict = {} 48 | for key in a:keys 49 | if has_key(a:dict, key) 50 | let new_dict[key] = a:dict[key] 51 | endif 52 | endfor 53 | return new_dict 54 | endfunction 55 | 56 | function! s:omit(dict, keys) abort 57 | let new_dict = copy(a:dict) 58 | for key in a:keys 59 | if has_key(a:dict, key) 60 | call remove(new_dict, key) 61 | endif 62 | endfor 63 | return new_dict 64 | endfunction 65 | 66 | function! s:clear(dict) abort 67 | for key in keys(a:dict) 68 | call remove(a:dict, key) 69 | endfor 70 | return a:dict 71 | endfunction 72 | 73 | function! s:_max_by(dict, expr) abort 74 | let dict = s:swap(map(copy(a:dict), a:expr)) 75 | let key = dict[max(keys(dict))] 76 | return [key, a:dict[key]] 77 | endfunction 78 | 79 | function! s:max_by(dict, expr) abort 80 | if empty(a:dict) 81 | throw 'vital: Data.Dict: Empty dictionary' 82 | endif 83 | return s:_max_by(a:dict, a:expr) 84 | endfunction 85 | 86 | function! s:min_by(dict, expr) abort 87 | if empty(a:dict) 88 | throw 'vital: Data.Dict: Empty dictionary' 89 | endif 90 | return s:_max_by(a:dict, '-(' . a:expr . ')') 91 | endfunction 92 | 93 | function! s:_foldl(f, init, xs) abort 94 | let memo = a:init 95 | for [k, v] in a:xs 96 | let expr = substitute(a:f, 'v:key', string(k), 'g') 97 | let expr = substitute(expr, 'v:val', string(v), 'g') 98 | let expr = substitute(expr, 'v:memo', string(memo), 'g') 99 | unlet memo 100 | let memo = eval(expr) 101 | endfor 102 | return memo 103 | endfunction 104 | 105 | function! s:foldl(f, init, dict) abort 106 | return s:_foldl(a:f, a:init, items(a:dict)) 107 | endfunction 108 | 109 | function! s:foldr(f, init, dict) abort 110 | return s:_foldl(a:f, a:init, reverse(items(a:dict))) 111 | endfunction 112 | 113 | let &cpo = s:save_cpo 114 | unlet s:save_cpo 115 | 116 | " vim:set et ts=2 sts=2 sw=2 tw=0: 117 | -------------------------------------------------------------------------------- /autoload/vital_complete.vim: -------------------------------------------------------------------------------- 1 | scriptencoding utf-8 2 | let s:save_cpo = &cpo 3 | set cpo&vim 4 | 5 | let s:V = vital#vital_complete#of() 6 | let s:File = s:V.import('System.File') 7 | let s:Message = s:V.import('Vim.Message') 8 | let s:ScriptLocal = s:V.import('Vim.ScriptLocal') 9 | let s:Dict = s:V.import('Data.Dict') 10 | 11 | let g:vital_complete#max_search_line = get(g:, 'vital_complete#max_search_line', 500) 12 | 13 | " for :h omnifunc 14 | " setlocal omnifunc=vital_complete#complete 15 | function! vital_complete#complete(findstart, base) abort 16 | if a:findstart 17 | return vital_complete#find_start_col() 18 | endif 19 | return vital_complete#completion_items(s:context(), a:base) 20 | endfunction 21 | 22 | function! vital_complete#manual_complete() 23 | let idx = vital_complete#find_start_col() 24 | if idx < 0 25 | return '' 26 | endif 27 | let col = idx + 1 28 | let base = getline('.')[idx : col('.')-1] 29 | call complete(col, vital_complete#complete(0, base)) 30 | return '' 31 | endfunction 32 | 33 | function! vital_complete#update(plugin_name) abort 34 | let data = s:update_plugin_data(a:plugin_name) 35 | if empty(data) 36 | call s:Message.error(printf('vital-complete: plugin data is empty. Run :Vitalize may fix this problem: %s', a:plugin_name)) 37 | return 38 | endif 39 | call s:Message.echomsg('MoreMsg', printf('vital-complete: update plugin data: %s', a:plugin_name)) 40 | endfunction 41 | 42 | function! vital_complete#context() abort 43 | return s:context() 44 | endfunction 45 | 46 | function! s:context() abort 47 | let line = getline('.') 48 | let col = col('.') 49 | let list = matchlist(line[: col - 1], '\(\([sg]:\)\=\(\w\+\)\)\.\(\w*\)$') 50 | if empty(list) 51 | return {} 52 | endif 53 | let [_, module_with_prefix, prefix, module, method_typed; __] = list 54 | return { 55 | \ 'module_with_prefix': module_with_prefix, 56 | \ 'start_col': col - len(method_typed) - 1, 57 | \ } 58 | endfunction 59 | 60 | function! vital_complete#find_start_col() abort 61 | let ctx = s:context() 62 | if empty(ctx) 63 | return -1 64 | endif 65 | return ctx.start_col 66 | endfunction 67 | 68 | function! vital_complete#completion_items(ctx, base) abort 69 | if empty(a:ctx) 70 | return [] 71 | endif 72 | 73 | let plugin_name = s:plugin_name_from_buffer() 74 | if plugin_name is# '' 75 | return [] 76 | endif 77 | 78 | let plugin_data = s:plugin_data(plugin_name) 79 | if empty(plugin_data) 80 | return [] 81 | endif 82 | let modules = s:list_imports() 83 | if !has_key(modules, a:ctx.module_with_prefix) 84 | return [] 85 | endif 86 | let module_name = modules[a:ctx.module_with_prefix] 87 | let module_data = get(plugin_data, module_name, {}) 88 | let funcs = keys(module_data) 89 | let matched_funcs = filter(copy(funcs), 'v:val =~# "^" . a:base') 90 | let items = [] 91 | for funcname in matched_funcs 92 | let func_data = module_data[funcname] 93 | let menu = s:menu(module_name, funcname, func_data.args, func_data.attrs) 94 | let items += [{ 95 | \ 'word': funcname, 96 | \ 'menu': menu, 97 | \ }] 98 | endfor 99 | return items 100 | endfunction 101 | 102 | function! s:menu(module_name, funcname, args, attrs) abort 103 | return printf('%s.%s(%s) %s', 104 | \ a:module_name, 105 | \ a:funcname, 106 | \ join(a:args, ', '), 107 | \ join(a:attrs, ' ') 108 | \ ) 109 | endfunction 110 | 111 | function! s:plugin_name_from_buffer() abort 112 | let pattern = 'vital#\zs\w\+\ze#\%(of\|import\)\|vital#of(["'']\zs\w\+\ze["''])' 113 | for line in getline(1, g:vital_complete#max_search_line) 114 | let name = matchstr(line, pattern) 115 | if name !=# '' 116 | return name 117 | endif 118 | endfor 119 | return '' 120 | endfunction 121 | 122 | " @returns {{: }} 123 | function! s:list_imports() abort 124 | let d = {} 125 | let pattern = '\vlet\s+(%([sg]:)?\w+)\s*\=.{-}[.#]import\(["''](\u%(\w+%(\.=))+)["'']\)' 126 | for line in filter(getline(1, g:vital_complete#max_search_line), 'v:val =~# pattern') 127 | let [_, var, module; __] = matchlist(line, pattern) 128 | let d[var] = module 129 | endfor 130 | return d 131 | endfunction 132 | 133 | let s:data_cache = {} 134 | function! s:plugin_data(plugin_name) abort 135 | if has_key(s:data_cache, a:plugin_name) 136 | return s:data_cache[a:plugin_name] 137 | endif 138 | let data_path = s:data_path(a:plugin_name) 139 | if !filereadable(data_path) 140 | " NOTE: data is not found. generate data? 141 | call s:Message.echomsg('MoreMsg', 'Generating vital completion data... hang tight') 142 | return s:update_plugin_data(a:plugin_name) 143 | endif 144 | sandbox let s:data_cache[a:plugin_name] = eval(readfile(data_path, 1)[0]) 145 | return s:data_cache[a:plugin_name] 146 | endfunction 147 | 148 | function! s:data_path(plugin_name) abort 149 | return expand(printf('~/.cache/vim/vital-complete/%s.data', a:plugin_name)) 150 | endfunction 151 | 152 | function! s:update_plugin_data(plugin_name) abort 153 | call s:File.mkdir_nothrow(expand('~/.cache/vim/vital-complete/'), 'p') 154 | let data = s:generate_plugin_data(a:plugin_name) 155 | call writefile([string(data)], s:data_path(a:plugin_name)) 156 | return data 157 | endfunction 158 | 159 | function! s:generate_plugin_data(plugin_name) abort 160 | let V = vital#of(a:plugin_name) 161 | let plugin_data = {} 162 | for module_name in V.search('**') 163 | let M = V.import(module_name) 164 | let plugin_data[module_name] = s:generate_module_data(M) 165 | endfor 166 | return plugin_data 167 | endfunction 168 | 169 | function! s:generate_module_data(Module) abort 170 | if empty(a:Module) 171 | return {} 172 | endif 173 | let sid = 0 174 | for Func in values(a:Module) 175 | let sid = s:sid_from_sfunc(Func) 176 | break 177 | endfor 178 | let info = filter(s:ScriptLocal.sid2sfuncs_info(sid), 'v:key =~# "^\\a"') 179 | return map(info, "s:Dict.pick(v:val, ['args', 'attrs'])") 180 | endfunction 181 | 182 | function! s:sid_from_sfunc(sfunc) abort 183 | return str2nr(matchstr(string(a:sfunc), 'function(''\zs\d\+\ze_\w\+'')')) 184 | endfunction 185 | 186 | let &cpo = s:save_cpo 187 | unlet s:save_cpo 188 | " __END__ 189 | " vim: expandtab softtabstop=2 shiftwidth=2 foldmethod=marker 190 | -------------------------------------------------------------------------------- /autoload/vital/vital_complete.data: -------------------------------------------------------------------------------- 1 | {'Data.Dict': {'funcsinfo': {'swap': {'args': ['dict'], 'attrs': ['abort']}, 'max_by': {'args': ['dict', 'expr'], 'attrs': ['abort']}, 'foldl': {'args': ['f', 'init', 'dict'], 'attrs': ['abort']}, 'omit': {'args': ['dict', 'keys'], 'attrs': ['abort']}, 'min_by': {'args': ['dict', 'expr'], 'attrs': ['abort']}, 'pick': {'args': ['dict', 'keys'], 'attrs': ['abort']}, 'foldr': {'args': ['f', 'init', 'dict'], 'attrs': ['abort']}, 'make_index': {'args': ['list', '...'], 'attrs': ['abort']}, 'clear': {'args': ['dict'], 'attrs': ['abort']}, 'make': {'args': ['keys', 'values', '...'], 'attrs': ['abort']}}, 'is_self_module': 0, 'autoload_import': 'vital#_vital_complete#Data#Dict#import', 'functions': ['clear', 'foldl', 'foldr', 'make', 'make_index', 'max_by', 'min_by', 'omit', 'pick', 'swap']}, 'Prelude': {'funcsinfo': {'escape_pattern': {'args': ['str'], 'attrs': ['abort']}, 'is_funcref': {'args': ['Value'], 'attrs': ['abort']}, 'path2directory': {'args': ['path'], 'attrs': ['abort']}, 'wcswidth': {'args': ['str'], 'attrs': ['abort']}, 'is_string': {'args': ['Value'], 'attrs': ['abort']}, 'input_helper': {'args': ['funcname', 'args'], 'attrs': ['abort']}, 'is_number': {'args': ['Value'], 'attrs': ['abort']}, 'is_cygwin': {'args': [], 'attrs': ['abort']}, 'path2project_directory': {'args': ['path', '...'], 'attrs': ['abort']}, 'input_safe': {'args': ['...'], 'attrs': ['abort']}, 'is_list': {'args': ['Value'], 'attrs': ['abort']}, 'truncate_skipping': {'args': ['str', 'max', 'footer_width', 'separator'], 'attrs': ['abort']}, 'glob': {'args': ['expr'], 'attrs': ['abort']}, 'is_unix': {'args': [], 'attrs': ['abort']}, 'truncate': {'args': ['str', 'width'], 'attrs': ['abort']}, 'is_dict': {'args': ['Value'], 'attrs': ['abort']}, 'set_default': {'args': ['var', 'val'], 'attrs': ['abort']}, 'is_numeric': {'args': ['Value'], 'attrs': ['abort']}, 'getchar_safe': {'args': ['...'], 'attrs': ['abort']}, 'substitute_path_separator': {'args': ['path'], 'attrs': ['abort']}, 'is_mac': {'args': [], 'attrs': ['abort']}, 'strwidthpart': {'args': ['str', 'width'], 'attrs': ['abort']}, 'getchar': {'args': ['...'], 'attrs': ['abort']}, 'strwidthpart_reverse': {'args': ['str', 'width'], 'attrs': ['abort']}, 'is_windows': {'args': [], 'attrs': ['abort']}, 'globpath': {'args': ['path', 'expr'], 'attrs': ['abort']}, 'escape_file_searching': {'args': ['buffer_name'], 'attrs': ['abort']}, 'is_float': {'args': ['Value'], 'attrs': ['abort']}, 'smart_execute_command': {'args': ['action', 'word'], 'attrs': ['abort']}}, 'is_self_module': 0, 'autoload_import': 'vital#_vital_complete#Prelude#import', 'functions': ['escape_file_searching', 'escape_pattern', 'getchar', 'getchar_safe', 'glob', 'globpath', 'input_helper', 'input_safe', 'is_cygwin', 'is_dict', 'is_float', 'is_funcref', 'is_list', 'is_mac', 'is_number', 'is_numeric', 'is_string', 'is_unix', 'is_windows', 'path2directory', 'path2project_directory', 'set_default', 'smart_execute_command', 'strwidthpart', 'strwidthpart_reverse', 'substitute_path_separator', 'truncate', 'truncate_skipping', 'wcswidth']}, 'Vim.ScriptLocal': {'funcsinfo': {'scriptnames': {'args': [], 'attrs': ['abort']}, 'sid2path': {'args': ['sid'], 'attrs': ['abort']}, 'sid2sfuncs': {'args': ['sid'], 'attrs': ['abort']}, 'sfuncs': {'args': ['path'], 'attrs': ['abort']}, 'svars': {'args': ['path'], 'attrs': ['abort']}, 'sid2sfuncs_info': {'args': ['sid'], 'attrs': ['abort']}, 'sid': {'args': ['path'], 'attrs': ['abort']}, 'sid2svars': {'args': ['sid'], 'attrs': ['abort']}}, 'is_self_module': 0, 'autoload_import': 'vital#_vital_complete#Vim#ScriptLocal#import', 'functions': ['scriptnames', 'sfuncs', 'sid', 'sid2path', 'sid2sfuncs', 'sid2sfuncs_info', 'sid2svars', 'svars']}, 'System.Filepath': {'funcsinfo': {'path_separator': {'args': [], 'attrs': ['abort']}, 'is_case_tolerant': {'args': [], 'attrs': ['abort']}, 'dirname': {'args': ['path'], 'attrs': ['abort']}, 'abspath': {'args': ['path'], 'attrs': ['abort']}, 'relpath': {'args': ['path'], 'attrs': ['abort']}, 'realpath': {'args': ['path'], 'attrs': ['abort']}, 'unify_separator': {'args': ['path'], 'attrs': ['abort']}, 'unixpath': {'args': ['path'], 'attrs': ['abort']}, 'is_root_directory': {'args': ['path'], 'attrs': ['abort']}, 'split': {'args': ['path'], 'attrs': ['abort']}, 'path_extensions': {'args': [], 'attrs': ['abort']}, 'which': {'args': ['str'], 'attrs': ['abort']}, 'winpath': {'args': ['path'], 'attrs': ['abort']}, 'join': {'args': ['...'], 'attrs': ['abort']}, 'separator': {'args': [], 'attrs': ['abort']}, 'is_relative': {'args': ['path'], 'attrs': ['abort']}, 'basename': {'args': ['path'], 'attrs': ['abort']}, 'remove_last_separator': {'args': ['path'], 'attrs': ['abort']}, 'is_absolute': {'args': ['path'], 'attrs': ['abort']}, 'contains': {'args': ['path', 'base'], 'attrs': ['abort']}}, 'is_self_module': 0, 'autoload_import': 'vital#_vital_complete#System#Filepath#import', 'functions': ['abspath', 'basename', 'contains', 'dirname', 'is_absolute', 'is_case_tolerant', 'is_relative', 'is_root_directory', 'join', 'path_extensions', 'path_separator', 'realpath', 'relpath', 'remove_last_separator', 'separator', 'split', 'unify_separator', 'unixpath', 'which', 'winpath']}, 'System.File': {'funcsinfo': {'copy_dir_vim': {'args': ['src', 'dest'], 'attrs': ['abort']}, 'move_exe': {'args': ['src', 'dest'], 'attrs': ['abort']}, 'move': {'args': ['src', 'dest'], 'attrs': ['abort']}, 'copy_exe': {'args': ['src', 'dest'], 'attrs': ['abort']}, 'copy_dir_exe': {'args': ['src', 'dest'], 'attrs': ['abort']}, 'move_vim': {'args': ['src', 'dest'], 'attrs': ['abort']}, 'copy': {'args': ['src', 'dest'], 'attrs': ['abort']}, 'open': {'args': ['filename'], 'attrs': ['abort']}, 'mkdir_nothrow': {'args': ['...'], 'attrs': ['abort']}, 'copy_vim': {'args': ['src', 'dest'], 'attrs': ['abort']}, 'rmdir': {'args': ['path', '...'], 'attrs': ['abort']}, 'copy_dir': {'args': ['src', 'dest'], 'attrs': ['abort']}}, 'is_self_module': 0, 'autoload_import': 'vital#_vital_complete#System#File#import', 'functions': ['_vital_depends', '_vital_loaded', 'copy', 'copy_dir', 'copy_dir_exe', 'copy_dir_vim', 'copy_exe', 'copy_vim', 'mkdir_nothrow', 'move', 'move_exe', 'move_vim', 'open', 'rmdir']}, 'Vim.Message': {'funcsinfo': {'capture': {'args': ['command'], 'attrs': ['abort']}, 'echomsg': {'args': ['hl', 'msg'], 'attrs': ['abort']}, 'echo': {'args': ['hl', 'msg'], 'attrs': ['abort']}, 'error': {'args': ['msg'], 'attrs': ['abort']}, 'warn': {'args': ['msg'], 'attrs': ['abort']}, 'get_hit_enter_max_length': {'args': [], 'attrs': ['abort']}}, 'is_self_module': 0, 'autoload_import': 'vital#_vital_complete#Vim#Message#import', 'functions': ['capture', 'echo', 'echomsg', 'error', 'get_hit_enter_max_length', 'warn']}} 2 | -------------------------------------------------------------------------------- /autoload/vital/_vital_complete/Vim/ScriptLocal.vim: -------------------------------------------------------------------------------- 1 | " ___vital___ 2 | " NOTE: lines between '" ___vital___' is generated by :Vitalize. 3 | " Do not mofidify the code nor insert new lines before '" ___vital___' 4 | if v:version > 703 || v:version == 703 && has('patch1170') 5 | function! vital#_vital_complete#Vim#ScriptLocal#import() abort 6 | return map({'scriptnames': '', 'sid2path': '', 'sid2sfuncs': '', 'sfuncs': '', 'svars': '', 'sid2sfuncs_info': '', 'sid': '', 'sid2svars': ''}, 'function("s:" . v:key)') 7 | endfunction 8 | else 9 | function! s:_SID() abort 10 | return matchstr(expand(''), '\zs\d\+\ze__SID$') 11 | endfunction 12 | execute join(['function! vital#_vital_complete#Vim#ScriptLocal#import() abort', printf("return map({'scriptnames': '', 'sid2path': '', 'sid2sfuncs': '', 'sfuncs': '', 'svars': '', 'sid2sfuncs_info': '', 'sid': '', 'sid2svars': ''}, \"function('%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n") 13 | delfunction s:_SID 14 | endif 15 | " ___vital___ 16 | scriptencoding utf-8 17 | let s:save_cpo = &cpo 18 | set cpo&vim 19 | 20 | """ Helper: 21 | 22 | function! s:_throw(message) abort 23 | throw printf('vital: Vim.ScriptLocal: %s', a:message) 24 | endfunction 25 | 26 | "" Capture command 27 | function! s:_capture(command) abort 28 | try 29 | let save_verbose = &verbose 30 | let &verbose = 0 31 | redir => out 32 | silent execute a:command 33 | finally 34 | redir END 35 | let &verbose = save_verbose 36 | endtry 37 | return out 38 | endfunction 39 | 40 | "" Capture command and return lines 41 | function! s:_capture_lines(command) abort 42 | return split(s:_capture(a:command), "\n") 43 | endfunction 44 | 45 | "" Return funcname of script local functions with SID 46 | function! s:_sfuncname(sid, funcname) abort 47 | return printf('%s_%s', a:sid, a:funcname) 48 | endfunction 49 | 50 | function! s:_source(path) abort 51 | try 52 | execute ':source' fnameescape(a:path) 53 | catch /^Vim\%((\a\+)\)\=:E121/ 54 | " NOTE: workaround for `E121: Undefined variable: s:save_cpo` 55 | execute ':source' fnameescape(a:path) 56 | endtry 57 | endfunction 58 | 59 | let s:_cache = { '_': {} } 60 | 61 | function! s:_cache.return(key, value) abort 62 | let self._[a:key] = a:value 63 | return a:value 64 | endfunction 65 | 66 | function! s:_cache.has(key) abort 67 | return has_key(self._, a:key) 68 | endfunction 69 | 70 | function! s:_cache.get(key) abort 71 | return self._[a:key] 72 | endfunction 73 | 74 | let s:cache = { 75 | \ 'sid': deepcopy(s:_cache), 76 | \ 'sid2path': deepcopy(s:_cache), 77 | \ 'sid2svars': deepcopy(s:_cache) 78 | \} 79 | 80 | """ Main: 81 | 82 | "" Improved scriptnames() 83 | " @return {sid1: path1, sid2: path2, ...} 84 | function! s:scriptnames() abort 85 | let sdict = {} " { sid: path } 86 | for line in s:_capture_lines(':scriptnames') 87 | let [sid, path] = split(line, '\m^\s*\d\+\zs:\s\ze') 88 | let sdict[str2nr(sid)] = s:_unify_path(path) " str2nr(): ' 1' -> 1 89 | endfor 90 | return sdict 91 | endfunction 92 | 93 | "" Return SID from the given path 94 | " return -1 if the given path is not found in scriptnames() 95 | " NOTE: it execute `:source` a given path once if the file haven't sourced yet 96 | function! s:sid(path) abort 97 | if s:cache.sid.has(a:path) 98 | return s:cache.sid.get(a:path) 99 | endif 100 | " Expand to full path 101 | let tp = fnamemodify(a:path, ':p') " target path 102 | " Relative to &runtimepath 103 | if !filereadable(tp) 104 | " NOTE: if there are more than one matched paths, use the first one. 105 | let tp = get(split(globpath(&runtimepath, a:path, 1), "\n"), 0, '') 106 | endif 107 | if !filereadable(tp) 108 | return s:_throw('file not found') 109 | endif 110 | let sid = s:_sid(tp, s:scriptnames()) 111 | if sid isnot -1 112 | " return sid 113 | return s:cache.sid.return(a:path, sid) 114 | else 115 | call s:_source(tp) 116 | " return s:_sid(tp, s:scriptnames()) 117 | return s:cache.sid.return(a:path, s:_sid(tp, s:scriptnames())) 118 | endif 119 | endfunction 120 | 121 | " Assume `a:abspath` is absolute path 122 | function! s:_sid(abspath, scriptnames) abort 123 | " Handle symbolic link here 124 | let tp = s:_unify_path(a:abspath) " target path 125 | for sid in keys(a:scriptnames) 126 | if tp is# a:scriptnames[sid] 127 | return str2nr(sid) 128 | endif 129 | endfor 130 | return -1 131 | endfunction 132 | 133 | "" Return path from SID 134 | function! s:sid2path(sid) abort 135 | if s:cache.sid2path.has(a:sid) 136 | return s:cache.sid2path.get(a:sid) 137 | endif 138 | let sn = s:scriptnames() 139 | if has_key(sn, a:sid) 140 | " return sn[a:sid] 141 | return s:cache.sid2path.return(a:sid, sn[a:sid]) 142 | else 143 | return s:_throw('sid not found') 144 | endif 145 | endfunction 146 | 147 | "" Return a dict which contains script-local functions from given path 148 | " `path` should be absolute path or relative to &runtimepath 149 | " @return {funcname: funcref, funcname2: funcref2, ...} 150 | " USAGE: 151 | " :echo s:sfuncs('~/.vim/bundle/plugname/autoload/plugname.vim') 152 | " " => { 'fname1': funcref1, 'fname2': funcref2, ...} 153 | " :echo s:sfuncs('autoload/plugname.vim') 154 | " " => { 'fname1': funcref1, 'fname2': funcref2, ...} 155 | function! s:sfuncs(path) abort 156 | return s:sid2sfuncs(s:sid(a:path)) 157 | endfunction 158 | 159 | "" Return a dict which contains script-local functions from SID 160 | " USAGE: 161 | " :echo s:sid2sfuncs(1) 162 | " " => { 'fname1': funcref1, 'fname2': funcref2, ...} 163 | " " The file whose SID is 1 may be your vimrc 164 | " NOTE: old regexpengine has a bug which returns 0 with 165 | " :echo "\" =~# "\\%#=1\x80\xfdR" | " => 0 166 | " But it matches correctly with :h /collection 167 | " :echo "\" =~# "\\%#=1[\x80][\xfd]R" | " => 1 168 | " http://lingr.com/room/vim/archives/2015/02/13#message-21261450 169 | " In MS Windows with old Vim, [] doesn't work, but [\xXX] works well. 170 | " The cause isn't being investigated. 171 | let s:SNR = join(map(range(len("\")), '"[\\x" . printf("%0x", char2nr("\"[v:val])) . "]"'), '') 172 | function! s:sid2sfuncs(sid) abort 173 | ":h :function /{pattern} 174 | " -> ^________ 175 | " function 14_functionname(args, ...) 176 | let fs = s:_capture_lines(':function ' . printf('/^%s%s_', s:SNR, a:sid)) 177 | let r = {} 178 | " -> ^--------____________- 179 | " function 14_functionname(args, ...) 180 | let pattern = printf('\m^function\s%d_\zs\w\{-}\ze(', a:sid) 181 | for fname in map(fs, 'matchstr(v:val, pattern)') 182 | let r[fname] = function(s:_sfuncname(a:sid, fname)) 183 | endfor 184 | return r 185 | endfunction 186 | 187 | function! s:sid2sfuncs_info(sid) abort 188 | ":h :function /{pattern} 189 | " -> ^________ 190 | " function 14_functionname(args, ...) 191 | let fs = s:_capture_lines(':function ' . printf('/^%s%s_', s:SNR, a:sid)) 192 | let r = {} 193 | " -> ^--------____________---------- __________ 194 | " function 14_functionname(args, ...) abort dict 195 | let pattern = printf('\m^function\s%d_\(\w\{-}\)(\([^)]\{-}\))\%( \(.*\)\)\=$', a:sid) 196 | for list in map(fs, 'matchlist(v:val, pattern)') 197 | let [_, funcname, arg_str, atr_str; __] = list 198 | let r[funcname] = { 199 | \ 'func': function(s:_sfuncname(a:sid, funcname)), 200 | \ 'args': split(arg_str, ', '), 201 | \ 'attrs': split(atr_str, ' '), 202 | \ } 203 | endfor 204 | return r 205 | endfunction 206 | 207 | let s:GETSVARSFUNCNAME = '___VITAL_VIM_SCRIPTLOCAL_GET_SVARS___' 208 | 209 | let s:_get_svars_func = [ 210 | \ printf('function! s:%s() abort', s:GETSVARSFUNCNAME), 211 | \ ' return s:', 212 | \ 'endfunction' 213 | \ ] 214 | 215 | "" Return script-local variable (s:var) dict form path 216 | function! s:svars(path) abort 217 | return s:sid2svars(s:sid(a:path)) 218 | endfunction 219 | 220 | "" Return script-local variable (s:var) dictionary form SID 221 | function! s:sid2svars(sid) abort 222 | if s:cache.sid2svars.has(a:sid) 223 | return s:cache.sid2svars.get(a:sid) 224 | endif 225 | let fullpath = fnamemodify(s:sid2path(a:sid), ':p') 226 | let lines = readfile(fullpath) 227 | try 228 | call writefile(s:_get_svars_func, fullpath) 229 | call s:_source(fullpath) 230 | let sfuncname = s:_sfuncname(a:sid, s:GETSVARSFUNCNAME) 231 | let svars = call(function(sfuncname), []) 232 | execute 'delfunction' sfuncname 233 | " return svars 234 | return s:cache.sid2svars.return(a:sid, svars) 235 | finally 236 | call writefile(lines, fullpath) 237 | endtry 238 | endfunction 239 | 240 | 241 | " This is copied from autoload/vital/__latest__.vim 242 | " FIXME: Avoid duplication. 243 | function! s:_unify_path(path) abort 244 | return resolve(fnamemodify(a:path, ':p:gs?[\\/]?/?')) 245 | endfunction 246 | 247 | 248 | let &cpo = s:save_cpo 249 | unlet s:save_cpo 250 | 251 | " vim:set et ts=2 sts=2 sw=2 tw=0: 252 | -------------------------------------------------------------------------------- /autoload/vital/_vital_complete/System/Filepath.vim: -------------------------------------------------------------------------------- 1 | " ___vital___ 2 | " NOTE: lines between '" ___vital___' is generated by :Vitalize. 3 | " Do not mofidify the code nor insert new lines before '" ___vital___' 4 | if v:version > 703 || v:version == 703 && has('patch1170') 5 | function! vital#_vital_complete#System#Filepath#import() abort 6 | return map({'path_separator': '', 'is_case_tolerant': '', 'dirname': '', 'abspath': '', 'relpath': '', 'realpath': '', 'unify_separator': '', 'is_root_directory': '', 'split': '', 'path_extensions': '', 'unixpath': '', 'which': '', 'winpath': '', 'join': '', 'separator': '', 'is_relative': '', 'basename': '', 'remove_last_separator': '', 'is_absolute': '', 'contains': ''}, 'function("s:" . v:key)') 7 | endfunction 8 | else 9 | function! s:_SID() abort 10 | return matchstr(expand(''), '\zs\d\+\ze__SID$') 11 | endfunction 12 | execute join(['function! vital#_vital_complete#System#Filepath#import() abort', printf("return map({'path_separator': '', 'is_case_tolerant': '', 'dirname': '', 'abspath': '', 'relpath': '', 'realpath': '', 'unify_separator': '', 'is_root_directory': '', 'split': '', 'path_extensions': '', 'unixpath': '', 'which': '', 'winpath': '', 'join': '', 'separator': '', 'is_relative': '', 'basename': '', 'remove_last_separator': '', 'is_absolute': '', 'contains': ''}, \"function('%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n") 13 | delfunction s:_SID 14 | endif 15 | " ___vital___ 16 | " You should check the following related builtin functions. 17 | " fnamemodify() 18 | " resolve() 19 | " simplify() 20 | 21 | let s:save_cpo = &cpo 22 | set cpo&vim 23 | 24 | let s:path_sep_pattern = (exists('+shellslash') ? '[\\/]' : '/') . '\+' 25 | let s:is_windows = has('win16') || has('win32') || has('win64') || has('win95') 26 | let s:is_cygwin = has('win32unix') 27 | let s:is_mac = !s:is_windows && !s:is_cygwin 28 | \ && (has('mac') || has('macunix') || has('gui_macvim') || 29 | \ (!isdirectory('/proc') && executable('sw_vers'))) 30 | let s:is_case_tolerant = filereadable(expand(':r') . '.VIM') 31 | 32 | " Get the directory separator. 33 | function! s:separator() abort 34 | return fnamemodify('.', ':p')[-1 :] 35 | endfunction 36 | 37 | " Get the path separator. 38 | let s:path_separator = s:is_windows ? ';' : ':' 39 | function! s:path_separator() abort 40 | return s:path_separator 41 | endfunction 42 | 43 | " Get the path extensions 44 | function! s:path_extensions() abort 45 | if !exists('s:path_extensions') 46 | if s:is_windows 47 | if exists('$PATHEXT') 48 | let pathext = $PATHEXT 49 | else 50 | " get default PATHEXT 51 | let pathext = matchstr(system('set pathext'), '\C^pathext=\zs.*\ze\n', 'i') 52 | endif 53 | let s:path_extensions = map(split(pathext, s:path_separator), 'tolower(v:val)') 54 | elseif s:is_cygwin 55 | " cygwin is not use $PATHEXT 56 | let s:path_extensions = ['', '.exe'] 57 | else 58 | let s:path_extensions = [''] 59 | endif 60 | endif 61 | return s:path_extensions 62 | endfunction 63 | 64 | " Convert all directory separators to "/". 65 | function! s:unify_separator(path) abort 66 | return substitute(a:path, s:path_sep_pattern, '/', 'g') 67 | endfunction 68 | 69 | " Get the full path of command. 70 | if exists('*exepath') 71 | function! s:which(str) abort 72 | return exepath(a:str) 73 | endfunction 74 | else 75 | function! s:which(command, ...) abort 76 | let pathlist = a:command =~# s:path_sep_pattern ? [''] : 77 | \ !a:0 ? split($PATH, s:path_separator) : 78 | \ type(a:1) == type([]) ? copy(a:1) : 79 | \ split(a:1, s:path_separator) 80 | 81 | let pathext = s:path_extensions() 82 | if index(pathext, '.' . tolower(fnamemodify(a:command, ':e'))) != -1 83 | let pathext = [''] 84 | endif 85 | 86 | let dirsep = s:separator() 87 | for dir in pathlist 88 | let head = dir ==# '' ? '' : dir . dirsep 89 | for ext in pathext 90 | let full = fnamemodify(head . a:command . ext, ':p') 91 | if filereadable(full) 92 | if s:is_case_tolerant() 93 | let full = glob(substitute( 94 | \ toupper(full), '\u:\@!', '[\0\L\0]', 'g'), 1) 95 | endif 96 | if full !=# '' 97 | return full 98 | endif 99 | endif 100 | endfor 101 | endfor 102 | 103 | return '' 104 | endfunction 105 | endif 106 | 107 | " Split the path with directory separator. 108 | " Note that this includes the drive letter of MS Windows. 109 | function! s:split(path) abort 110 | return split(a:path, s:path_sep_pattern) 111 | endfunction 112 | 113 | " Join the paths. 114 | " join('foo', 'bar') => 'foo/bar' 115 | " join('foo/', 'bar') => 'foo/bar' 116 | " join('/foo/', ['bar', 'buz/']) => '/foo/bar/buz/' 117 | function! s:join(...) abort 118 | let sep = s:separator() 119 | let path = '' 120 | for part in a:000 121 | let path .= sep . 122 | \ (type(part) is type([]) ? call('s:join', part) : 123 | \ part) 124 | unlet part 125 | endfor 126 | return substitute(path[1 :], s:path_sep_pattern, sep, 'g') 127 | endfunction 128 | 129 | " Check if the path is absolute path. 130 | if s:is_windows 131 | function! s:is_absolute(path) abort 132 | return a:path =~? '^[a-z]:[/\\]' 133 | endfunction 134 | else 135 | function! s:is_absolute(path) abort 136 | return a:path[0] ==# '/' 137 | endfunction 138 | endif 139 | 140 | function! s:is_relative(path) abort 141 | return !s:is_absolute(a:path) 142 | endfunction 143 | 144 | " Return the parent directory of the path. 145 | " NOTE: fnamemodify(path, ':h') does not return the parent directory 146 | " when path[-1] is the separator. 147 | function! s:dirname(path) abort 148 | let path = a:path 149 | let orig = a:path 150 | 151 | let path = s:remove_last_separator(path) 152 | if path ==# '' 153 | return orig " root directory 154 | endif 155 | 156 | let path = fnamemodify(path, ':h') 157 | return path 158 | endfunction 159 | 160 | " Return the basename of the path. 161 | " NOTE: fnamemodify(path, ':h') does not return basename 162 | " when path[-1] is the separator. 163 | function! s:basename(path) abort 164 | let path = a:path 165 | let orig = a:path 166 | 167 | let path = s:remove_last_separator(path) 168 | if path ==# '' 169 | return orig " root directory 170 | endif 171 | 172 | let path = fnamemodify(path, ':t') 173 | return path 174 | endfunction 175 | 176 | " Remove the separator at the end of a:path. 177 | function! s:remove_last_separator(path) abort 178 | let sep = s:separator() 179 | let pat = escape(sep, '\') . '\+$' 180 | return substitute(a:path, pat, '', '') 181 | endfunction 182 | 183 | 184 | " Return true if filesystem ignores alphabetic case of a filename. 185 | " Return false otherwise. 186 | function! s:is_case_tolerant() abort 187 | return s:is_case_tolerant 188 | endfunction 189 | 190 | 191 | function! s:abspath(path) abort 192 | if s:is_absolute(a:path) 193 | return a:path 194 | endif 195 | " Note: 196 | " the behavior of ':p' for non existing file path is not defined 197 | return filereadable(a:path) 198 | \ ? fnamemodify(a:path, ':p') 199 | \ : s:join(fnamemodify(getcwd(), ':p'), a:path) 200 | endfunction 201 | 202 | function! s:relpath(path) abort 203 | if s:is_relative(a:path) 204 | return a:path 205 | endif 206 | return fnamemodify(a:path, ':~:.') 207 | endfunction 208 | 209 | function! s:unixpath(path) abort 210 | return fnamemodify(a:path, ':gs?\\?/?') 211 | endfunction 212 | 213 | function! s:winpath(path) abort 214 | return fnamemodify(a:path, ':gs?/?\\?') 215 | endfunction 216 | 217 | if s:is_windows 218 | function! s:realpath(path) abort 219 | if exists('&shellslash') && &shellslash 220 | return s:unixpath(a:path) 221 | else 222 | return s:winpath(a:path) 223 | endif 224 | endfunction 225 | else 226 | function! s:realpath(path) abort 227 | return s:unixpath(a:path) 228 | endfunction 229 | endif 230 | 231 | if s:is_windows 232 | function! s:is_root_directory(path) abort 233 | return a:path =~# '^[a-zA-Z]:[/\\]$' 234 | endfunction 235 | else 236 | function! s:is_root_directory(path) abort 237 | return a:path ==# '/' 238 | endfunction 239 | endif 240 | 241 | function! s:contains(path, base) abort 242 | if a:path ==# '' || a:base ==# '' 243 | return 0 244 | endif 245 | let pathlist = s:split(a:path) 246 | let baselist = s:split(a:base) 247 | let pathlistlen = len(pathlist) 248 | let baselistlen = len(baselist) 249 | if pathlistlen < baselistlen 250 | return 0 251 | endif 252 | if baselistlen == 0 253 | return 1 254 | endif 255 | if s:is_case_tolerant 256 | call map(pathlist, 'tolower(v:val)') 257 | call map(baselist, 'tolower(v:val)') 258 | endif 259 | return pathlist[: baselistlen - 1] ==# baselist 260 | endfunction 261 | 262 | let &cpo = s:save_cpo 263 | unlet s:save_cpo 264 | 265 | " vim:set et ts=2 sts=2 sw=2 tw=0: 266 | -------------------------------------------------------------------------------- /autoload/vital/vital_complete.vim: -------------------------------------------------------------------------------- 1 | let s:plugin_name = expand(':t:r') 2 | let s:vital_base_dir = expand(':h') 3 | let s:project_root = expand(':h:h:h') 4 | let s:is_vital_vim = s:plugin_name is# '_latest__' 5 | 6 | let s:loaded = {} 7 | let s:cache_sid = {} 8 | 9 | " function() wrapper 10 | if v:version > 703 || v:version == 703 && has('patch1170') 11 | function! s:_function(fstr) abort 12 | return function(a:fstr) 13 | endfunction 14 | else 15 | function! s:_SID() abort 16 | return matchstr(expand(''), '\zs\d\+\ze__SID$') 17 | endfunction 18 | let s:_s = '' . s:_SID() . '_' 19 | function! s:_function(fstr) abort 20 | return function(substitute(a:fstr, 's:', s:_s, 'g')) 21 | endfunction 22 | endif 23 | 24 | function! vital#{s:plugin_name}#of() abort 25 | return s:new(s:plugin_name) 26 | endfunction 27 | 28 | function! vital#{s:plugin_name}#import(...) abort 29 | if !exists('s:V') 30 | let s:V = s:new(s:plugin_name) 31 | endif 32 | return call(s:V.import, a:000, s:V) 33 | endfunction 34 | 35 | let s:Vital = {} 36 | 37 | function! s:new(plugin_name) abort 38 | let base = deepcopy(s:Vital) 39 | let base.plugin_name = a:plugin_name 40 | return base 41 | endfunction 42 | 43 | function! s:vital_files() abort 44 | if !exists('s:vital_files') 45 | let s:vital_files = map( 46 | \ s:is_vital_vim ? s:_global_vital_files() : s:_self_vital_files(), 47 | \ 'fnamemodify(v:val, ":p:gs?[\\\\/]?/?")') 48 | endif 49 | return copy(s:vital_files) 50 | endfunction 51 | let s:Vital.vital_files = s:_function('s:vital_files') 52 | 53 | function! s:import(name, ...) abort dict 54 | let target = {} 55 | let functions = [] 56 | for a in a:000 57 | if type(a) == type({}) 58 | let target = a 59 | elseif type(a) == type([]) 60 | let functions = a 61 | endif 62 | unlet a 63 | endfor 64 | let module = self._import(a:name) 65 | if empty(functions) 66 | call extend(target, module, 'keep') 67 | else 68 | for f in functions 69 | if has_key(module, f) && !has_key(target, f) 70 | let target[f] = module[f] 71 | endif 72 | endfor 73 | endif 74 | return target 75 | endfunction 76 | let s:Vital.import = s:_function('s:import') 77 | 78 | function! s:load(...) abort dict 79 | for arg in a:000 80 | let [name; as] = type(arg) == type([]) ? arg[: 1] : [arg, arg] 81 | let target = split(join(as, ''), '\W\+') 82 | let dict = self 83 | let dict_type = type({}) 84 | while !empty(target) 85 | let ns = remove(target, 0) 86 | if !has_key(dict, ns) 87 | let dict[ns] = {} 88 | endif 89 | if type(dict[ns]) == dict_type 90 | let dict = dict[ns] 91 | else 92 | unlet dict 93 | break 94 | endif 95 | endwhile 96 | if exists('dict') 97 | call extend(dict, self._import(name)) 98 | endif 99 | unlet arg 100 | endfor 101 | return self 102 | endfunction 103 | let s:Vital.load = s:_function('s:load') 104 | 105 | function! s:unload() abort dict 106 | let s:loaded = {} 107 | let s:cache_sid = {} 108 | unlet! s:vital_files 109 | endfunction 110 | let s:Vital.unload = s:_function('s:unload') 111 | 112 | function! s:exists(name) abort dict 113 | let b = exists(printf('*vital#_%s#%s#import', self.plugin_name, substitute(a:name, '\.', '#', 'g'))) 114 | if b 115 | return b 116 | endif 117 | let name_path = substitute(a:name, '\.', '/', 'g') 118 | let path = printf('%s/_%s/%s.vim', s:vital_base_dir, self.plugin_name, name_path) 119 | let b = filereadable(path) 120 | if b 121 | return b 122 | endif 123 | let path = printf('%s/_%s/%s.vim', s:vital_base_dir, '_latest__', name_path) 124 | let b = filereadable(path) 125 | endfunction 126 | let s:Vital.exists = s:_function('s:exists') 127 | 128 | function! s:search(pattern) abort dict 129 | let paths = s:_extract_files(a:pattern, self.vital_files()) 130 | let modules = sort(map(paths, 's:_file2module(v:val)')) 131 | return s:_uniq(modules) 132 | endfunction 133 | let s:Vital.search = s:_function('s:search') 134 | 135 | function! s:_self_vital_files() abort 136 | let builtin = printf('%s/__%s__/', s:vital_base_dir, s:plugin_name) 137 | let installed = printf('%s/_%s/', s:vital_base_dir, s:plugin_name) 138 | let base = builtin . ',' . installed 139 | return split(globpath(base, '**/*.vim', 1), "\n") 140 | endfunction 141 | 142 | function! s:_global_vital_files() abort 143 | let pattern = 'autoload/vital/__*__/**/*.vim' 144 | return split(globpath(&runtimepath, pattern, 1), "\n") 145 | endfunction 146 | 147 | function! s:_extract_files(pattern, files) abort 148 | let tr = {'.': '/', '*': '[^/]*', '**': '.*'} 149 | let target = substitute(a:pattern, '\.\|\*\*\?', '\=tr[submatch(0)]', 'g') 150 | let regexp = printf('autoload/vital/[^/]\+/%s.vim$', target) 151 | return filter(a:files, 'v:val =~# regexp') 152 | endfunction 153 | 154 | function! s:_file2module(file) abort 155 | let filename = fnamemodify(a:file, ':p:gs?[\\/]?/?') 156 | let tail = matchstr(filename, 'autoload/vital/_\w\+/\zs.*\ze\.vim$') 157 | return join(split(tail, '[\\/]\+'), '.') 158 | endfunction 159 | 160 | " @param {string} name e.g. Data.List 161 | function! s:_import(name) abort dict 162 | if has_key(s:loaded, a:name) 163 | return copy(s:loaded[a:name]) 164 | endif 165 | let module = self._get_module(a:name) 166 | if has_key(module, '_vital_created') 167 | call module._vital_created(module) 168 | endif 169 | let export_module = filter(copy(module), 'v:key =~# "^\\a"') 170 | " Cache module before calling module.vital_loaded() to avoid cyclic 171 | " dependences but remove the cache if module._vital_loaded() fails. 172 | " let s:loaded[a:name] = export_module 173 | let s:loaded[a:name] = export_module 174 | if has_key(module, '_vital_loaded') 175 | try 176 | call module._vital_loaded(vital#{s:plugin_name}#of()) 177 | catch 178 | unlet s:loaded[a:name] 179 | throw 'vital: fail to call ._vital_loaded(): ' . v:exception 180 | endtry 181 | endif 182 | return copy(s:loaded[a:name]) 183 | endfunction 184 | let s:Vital._import = s:_function('s:_import') 185 | 186 | " s:_get_module() returns module object wihch has all script local functions. 187 | function! s:_get_module(name) abort dict 188 | try 189 | let module = vital#_{self.plugin_name}#{substitute(a:name, '\.', '#', 'g')}#import() 190 | catch /^Vim\%((\a\+)\)\=:E117/ 191 | " Retry to support loading self modules. 192 | let module = s:_get_builtin_module(a:name) 193 | endtry 194 | return module 195 | endfunction 196 | let s:Vital._get_module = s:_function('s:_get_module') 197 | 198 | function! s:_get_builtin_module(name) abort 199 | return s:sid2sfuncs(s:_module_sid(a:name)) 200 | endfunction 201 | 202 | let s:vital_builtin_dir = printf('autoload/vital/__%s__/', s:is_vital_vim ? '*' : s:plugin_name) 203 | 204 | function! s:_module_sid(name) abort 205 | let module_path = substitute(a:name, '\.', '/', 'g') . '.vim' 206 | let module_rel_path = s:vital_builtin_dir . module_path 207 | let path = get(split(globpath(s:_module_sid_base_dir(), module_rel_path, 1), "\n"), 0, '') 208 | if !filereadable(path) 209 | throw 'vital: module not found: ' . a:name 210 | endif 211 | let p = substitute('autoload/vital/__\w\+__/' . module_path, '/', '[/\\\\]\\+', 'g') 212 | let sid = s:_sid(path, p) 213 | if !sid 214 | call s:_source(path) 215 | let sid = s:_sid(path, p) 216 | if !sid 217 | throw 'vital: cannot get from path' 218 | endif 219 | endif 220 | return sid 221 | endfunction 222 | 223 | function! s:_module_sid_base_dir() abort 224 | return s:is_vital_vim ? &rtp : s:project_root 225 | endfunction 226 | 227 | function! s:_source(path) abort 228 | execute 'source' fnameescape(a:path) 229 | endfunction 230 | 231 | " @vimlint(EVL102, 1, l:_) 232 | " @vimlint(EVL102, 1, l:__) 233 | function! s:_sid(path, filter_pattern) abort 234 | let unified_path = s:_unify_path(a:path) 235 | if has_key(s:cache_sid, unified_path) 236 | return s:cache_sid[unified_path] 237 | endif 238 | for line in filter(split(s:_redir(':scriptnames'), "\n"), 'v:val =~# a:filter_pattern') 239 | let [_, sid, path; __] = matchlist(line, '^\s*\(\d\+\):\s\+\(.\+\)\s*$') 240 | if s:_unify_path(path) is# unified_path 241 | let s:cache_sid[unified_path] = sid 242 | return s:cache_sid[unified_path] 243 | endif 244 | endfor 245 | return 0 246 | endfunction 247 | 248 | function! s:_redir(cmd) abort 249 | let [save_verbose, save_verbosefile] = [&verbose, &verbosefile] 250 | set verbose=0 verbosefile= 251 | redir => res 252 | silent! execute a:cmd 253 | redir END 254 | let [&verbose, &verbosefile] = [save_verbose, save_verbosefile] 255 | return res 256 | endfunction 257 | 258 | if filereadable(expand(':r') . '.VIM') " is case-insensitive or not 259 | let s:_unify_path_cache = {} 260 | " resolve() is slow, so we cache results. 261 | " Note: On windows, vim can't expand path names from 8.3 formats. 262 | " So if getting full path via and $HOME was set as 8.3 format, 263 | " vital load duplicated scripts. Below's :~ avoid this issue. 264 | function! s:_unify_path(path) abort 265 | if has_key(s:_unify_path_cache, a:path) 266 | return s:_unify_path_cache[a:path] 267 | endif 268 | let value = tolower(fnamemodify(resolve(fnamemodify( 269 | \ a:path, ':p')), ':~:gs?[\\/]?/?')) 270 | let s:_unify_path_cache[a:path] = value 271 | return value 272 | endfunction 273 | else 274 | function! s:_unify_path(path) abort 275 | return resolve(fnamemodify(a:path, ':p:gs?[\\/]?/?')) 276 | endfunction 277 | endif 278 | 279 | " copied and modified from Vim.ScriptLocal 280 | let s:SNR = join(map(range(len("\")), '"[\\x" . printf("%0x", char2nr("\"[v:val])) . "]"'), '') 281 | function! s:sid2sfuncs(sid) abort 282 | let fs = split(s:_redir(printf(':function /^%s%s_', s:SNR, a:sid)), "\n") 283 | let r = {} 284 | let pattern = printf('\m^function\s%d_\zs\w\{-}\ze(', a:sid) 285 | for fname in map(fs, 'matchstr(v:val, pattern)') 286 | let r[fname] = function(s:_sfuncname(a:sid, fname)) 287 | endfor 288 | return r 289 | endfunction 290 | 291 | "" Return funcname of script local functions with SID 292 | function! s:_sfuncname(sid, funcname) abort 293 | return printf('%s_%s', a:sid, a:funcname) 294 | endfunction 295 | 296 | if exists('*uniq') 297 | function! s:_uniq(list) abort 298 | return uniq(a:list) 299 | endfunction 300 | else 301 | function! s:_uniq(list) abort 302 | let i = len(a:list) - 1 303 | while 0 < i 304 | if a:list[i] ==# a:list[i - 1] 305 | call remove(a:list, i) 306 | endif 307 | let i -= 1 308 | endwhile 309 | return a:list 310 | endfunction 311 | endif 312 | -------------------------------------------------------------------------------- /autoload/vital/_vital_complete/System/File.vim: -------------------------------------------------------------------------------- 1 | " ___vital___ 2 | " NOTE: lines between '" ___vital___' is generated by :Vitalize. 3 | " Do not mofidify the code nor insert new lines before '" ___vital___' 4 | if v:version > 703 || v:version == 703 && has('patch1170') 5 | function! vital#_vital_complete#System#File#import() abort 6 | return map({'copy_dir_vim': '', '_vital_depends': '', 'mkdir_nothrow': '', 'copy_exe': '', 'open': '', 'move_vim': '', 'copy': '', 'move': '', 'copy_dir_exe': '', 'copy_vim': '', 'move_exe': '', 'copy_dir': '', 'rmdir': '', '_vital_loaded': ''}, 'function("s:" . v:key)') 7 | endfunction 8 | else 9 | function! s:_SID() abort 10 | return matchstr(expand(''), '\zs\d\+\ze__SID$') 11 | endfunction 12 | execute join(['function! vital#_vital_complete#System#File#import() abort', printf("return map({'copy_dir_vim': '', '_vital_depends': '', 'mkdir_nothrow': '', 'copy_exe': '', 'open': '', 'move_vim': '', 'copy': '', 'move': '', 'copy_dir_exe': '', 'copy_vim': '', 'move_exe': '', 'copy_dir': '', 'rmdir': '', '_vital_loaded': ''}, \"function('%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n") 13 | delfunction s:_SID 14 | endif 15 | " ___vital___ 16 | " Utilities for file copy/move/mkdir/etc. 17 | 18 | let s:save_cpo = &cpo 19 | set cpo&vim 20 | 21 | function! s:_vital_loaded(V) abort 22 | let s:Prelude = a:V.import('Prelude') 23 | let s:Filepath = a:V.import('System.Filepath') 24 | endfunction 25 | 26 | function! s:_vital_depends() abort 27 | return ['Prelude', 'System.Filepath'] 28 | endfunction 29 | 30 | let s:is_unix = has('unix') 31 | let s:is_windows = has('win16') || has('win32') || has('win64') || has('win95') 32 | let s:is_cygwin = has('win32unix') 33 | let s:is_mac = !s:is_windows && !s:is_cygwin 34 | \ && (has('mac') || has('macunix') || has('gui_macvim') || 35 | \ (!isdirectory('/proc') && executable('sw_vers'))) 36 | " As of 7.4.122, the system()'s 1st argument is converted internally by Vim. 37 | " Note that Patch 7.4.122 does not convert system()'s 2nd argument and 38 | " return-value. We must convert them manually. 39 | let s:need_trans = v:version < 704 || (v:version == 704 && !has('patch122')) 40 | 41 | " Open a file. 42 | function! s:open(filename) abort 43 | let filename = fnamemodify(a:filename, ':p') 44 | 45 | " Detect desktop environment. 46 | if s:is_windows 47 | " For URI only. 48 | if s:need_trans 49 | let filename = iconv(filename, &encoding, 'char') 50 | endif 51 | " Note: 52 | " # and % required to be escaped (:help cmdline-special) 53 | silent execute printf( 54 | \ '!start rundll32 url.dll,FileProtocolHandler %s', 55 | \ escape(filename, '#%'), 56 | \) 57 | elseif s:is_cygwin 58 | " Cygwin. 59 | call system(printf('%s %s', 'cygstart', 60 | \ shellescape(filename))) 61 | elseif executable('xdg-open') 62 | " Linux. 63 | call system(printf('%s %s &', 'xdg-open', 64 | \ shellescape(filename))) 65 | elseif exists('$KDE_FULL_SESSION') && $KDE_FULL_SESSION ==# 'true' 66 | " KDE. 67 | call system(printf('%s %s &', 'kioclient exec', 68 | \ shellescape(filename))) 69 | elseif exists('$GNOME_DESKTOP_SESSION_ID') 70 | " GNOME. 71 | call system(printf('%s %s &', 'gnome-open', 72 | \ shellescape(filename))) 73 | elseif executable('exo-open') 74 | " Xfce. 75 | call system(printf('%s %s &', 'exo-open', 76 | \ shellescape(filename))) 77 | elseif s:is_mac && executable('open') 78 | " Mac OS. 79 | call system(printf('%s %s &', 'open', 80 | \ shellescape(filename))) 81 | else 82 | " Give up. 83 | throw 'vital: System.File: open(): Not supported.' 84 | endif 85 | endfunction 86 | 87 | 88 | " Move a file. 89 | " Dispatch s:move_exe() or s:move_vim(). 90 | " FIXME: Currently s:move_vim() does not support 91 | " moving a directory. 92 | function! s:move(src, dest) abort 93 | if s:_has_move_exe() || isdirectory(a:src) 94 | return s:move_exe(a:src, a:dest) 95 | else 96 | return s:move_vim(a:src, a:dest) 97 | endif 98 | endfunction 99 | 100 | if s:is_unix 101 | function! s:_has_move_exe() abort 102 | return executable('mv') 103 | endfunction 104 | elseif s:is_windows 105 | function! s:_has_move_exe() abort 106 | return 1 107 | endfunction 108 | else 109 | function! s:_has_move_exe() abort 110 | throw 'vital: System.File: _has_move_exe(): your platform is not supported' 111 | endfunction 112 | endif 113 | 114 | " Move a file. 115 | " Implemented by external program. 116 | if s:is_unix 117 | function! s:move_exe(src, dest) abort 118 | if !s:_has_move_exe() 119 | return 0 120 | endif 121 | let [src, dest] = [a:src, a:dest] 122 | call system('mv ' . shellescape(src) . ' ' . shellescape(dest)) 123 | return !v:shell_error 124 | endfunction 125 | elseif s:is_windows 126 | function! s:move_exe(src, dest) abort 127 | if !s:_has_move_exe() 128 | return 0 129 | endif 130 | let [src, dest] = [a:src, a:dest] 131 | " Normalize successive slashes to one slash. 132 | let src = substitute(src, '[/\\]\+', '\', 'g') 133 | let dest = substitute(dest, '[/\\]\+', '\', 'g') 134 | " src must not have trailing '\'. 135 | let src = substitute(src, '\\$', '', 'g') 136 | " All characters must be encoded to system encoding. 137 | if s:need_trans 138 | let src = iconv(src, &encoding, 'char') 139 | let dest = iconv(dest, &encoding, 'char') 140 | endif 141 | let cmd_exe = (&shell =~? 'cmd\.exe$' ? '' : 'cmd /c ') 142 | call system(cmd_exe . 'move /y ' . src . ' ' . dest) 143 | return !v:shell_error 144 | endfunction 145 | else 146 | function! s:move_exe() abort 147 | throw 'vital: System.File: move_exe(): your platform is not supported' 148 | endfunction 149 | endif 150 | 151 | " Move a file. 152 | " Implemented by pure Vim script. 153 | function! s:move_vim(src, dest) abort 154 | return !rename(a:src, a:dest) 155 | endfunction 156 | 157 | function! s:copy_dir(src, dest) abort 158 | if s:_has_copy_dir_exe() 159 | return s:copy_dir_exe(a:src, a:dest) 160 | else 161 | return s:copy_dir_vim(a:src, a:dest) 162 | endif 163 | endfunction 164 | 165 | " Copy a directory. 166 | " Implemented by external program. 167 | if s:is_unix 168 | function! s:copy_dir_exe(src, dest) abort 169 | if !s:_has_copy_dir_exe() 170 | return 0 171 | endif 172 | let [src, dest] = [a:src, a:dest] 173 | call system('cp -R ' . shellescape(src) . ' ' . shellescape(dest)) 174 | return !v:shell_error 175 | endfunction 176 | elseif s:is_windows 177 | function! s:copy_dir_exe(src, dest) abort 178 | if !s:_has_copy_dir_exe() 179 | return 0 180 | endif 181 | let src = s:_shellescape_robocopy(a:src) 182 | let dest = s:_shellescape_robocopy(a:dest) 183 | call system('robocopy /e ' . src . ' ' . dest) 184 | return v:shell_error <# 8 185 | endfunction 186 | function! s:_shellescape_robocopy(path) abort 187 | let path = tr(a:path, '/', '\') 188 | let path = escape(path, '"') 189 | return '"' . path . '"' 190 | endfunction 191 | else 192 | function! s:copy_dir_exe() abort 193 | throw 'vital: System.File: copy_dir_exe(): your platform is not supported' 194 | endfunction 195 | endif 196 | 197 | " Copy a file. 198 | " Implemented by pure Vim script. 199 | function! s:copy_dir_vim(src, dest) abort 200 | if isdirectory(a:src) 201 | for src in s:Prelude.glob(s:Filepath.join(a:src, '*')) 202 | let basename = s:Filepath.basename(src) 203 | let dest = s:Filepath.join(a:dest, basename) 204 | if !s:copy_dir_vim(src, dest) 205 | return 0 206 | endif 207 | endfor 208 | return 1 209 | elseif filereadable(a:src) 210 | return s:copy_vim(a:src, a:dest) 211 | else " XXX: ??? 212 | return 0 213 | endif 214 | endfunction 215 | 216 | if s:is_unix 217 | function! s:_has_copy_dir_exe() abort 218 | return executable('cp') 219 | endfunction 220 | elseif s:is_windows 221 | function! s:_has_copy_dir_exe() abort 222 | return executable('robocopy') 223 | endfunction 224 | else 225 | function! s:_has_copy_dir_exe() abort 226 | throw 'vital: System.File: copy_dir_exe(): ' 227 | \ . 'your platform is not supported' 228 | endfunction 229 | endif 230 | 231 | 232 | " Copy a file. 233 | " Dispatch s:copy_exe() or s:copy_vim(). 234 | function! s:copy(src, dest) abort 235 | if s:_has_copy_exe() 236 | return s:copy_exe(a:src, a:dest) 237 | else 238 | return s:copy_vim(a:src, a:dest) 239 | endif 240 | endfunction 241 | 242 | if s:is_unix 243 | function! s:_has_copy_exe() abort 244 | return executable('cp') 245 | endfunction 246 | elseif s:is_windows 247 | function! s:_has_copy_exe() abort 248 | return 1 249 | endfunction 250 | else 251 | function! s:_has_copy_exe() abort 252 | throw 'vital: System.File: _has_copy_exe(): your platform is not supported' 253 | endfunction 254 | endif 255 | 256 | " Copy a file. 257 | " Implemented by external program. 258 | if s:is_unix 259 | function! s:copy_exe(src, dest) abort 260 | if !s:_has_copy_exe() 261 | return 0 262 | endif 263 | let [src, dest] = [a:src, a:dest] 264 | call system('cp ' . shellescape(src) . ' ' . shellescape(dest)) 265 | return !v:shell_error 266 | endfunction 267 | elseif s:is_windows 268 | function! s:copy_exe(src, dest) abort 269 | if !s:_has_copy_exe() 270 | return 0 271 | endif 272 | let [src, dest] = [a:src, a:dest] 273 | let src = substitute(src, '/', '\', 'g') 274 | let dest = substitute(dest, '/', '\', 'g') 275 | let cmd_exe = (&shell =~? 'cmd\.exe$' ? '' : 'cmd /c ') 276 | call system(cmd_exe . 'copy /y ' . src . ' ' . dest) 277 | return !v:shell_error 278 | endfunction 279 | else 280 | function! s:copy_exe() abort 281 | throw 'vital: System.File: copy_exe(): your platform is not supported' 282 | endfunction 283 | endif 284 | 285 | " Copy a file. 286 | " Implemented by pure Vim script. 287 | function! s:copy_vim(src, dest) abort 288 | let ret = writefile(readfile(a:src, 'b'), a:dest, 'b') 289 | if ret == -1 290 | return 0 291 | endif 292 | return 1 293 | endfunction 294 | 295 | " mkdir() but does not throw an exception. 296 | " Returns true if success. 297 | " Returns false if failure. 298 | function! s:mkdir_nothrow(...) abort 299 | try 300 | return call('mkdir', a:000) 301 | catch 302 | return 0 303 | endtry 304 | endfunction 305 | 306 | 307 | " Delete a file/directory. 308 | if has('patch-7.4.1128') 309 | function! s:rmdir(path, ...) abort 310 | let flags = a:0 ? a:1 : '' 311 | let delete_flags = flags =~# 'r' ? 'rf' : 'd' 312 | let result = delete(a:path, delete_flags) 313 | if result == -1 314 | throw 'vital: System.File: rmdir(): cannot delete "' . a:path . '"' 315 | endif 316 | endfunction 317 | 318 | elseif s:is_unix 319 | function! s:rmdir(path, ...) abort 320 | let flags = a:0 ? a:1 : '' 321 | let cmd = flags =~# 'r' ? 'rm -rf' : 'rmdir' 322 | let ret = system(cmd . ' ' . shellescape(a:path)) 323 | if v:shell_error 324 | let ret = iconv(ret, 'char', &encoding) 325 | throw 'vital: System.File: rmdir(): ' . substitute(ret, '\n', '', 'g') 326 | endif 327 | endfunction 328 | 329 | elseif s:is_windows 330 | function! s:rmdir(path, ...) abort 331 | let flags = a:0 ? a:1 : '' 332 | if &shell =~? 'sh$' 333 | let cmd = flags =~# 'r' ? 'rm -rf' : 'rmdir' 334 | let ret = system(cmd . ' ' . shellescape(a:path)) 335 | else 336 | " 'f' flag does not make sense. 337 | let cmd = 'rmdir /Q' 338 | let cmd .= flags =~# 'r' ? ' /S' : '' 339 | let ret = system(cmd . ' "' . a:path . '"') 340 | endif 341 | if v:shell_error 342 | let ret = iconv(ret, 'char', &encoding) 343 | throw 'vital: System.File: rmdir(): ' . substitute(ret, '\n', '', 'g') 344 | endif 345 | endfunction 346 | 347 | else 348 | function! s:rmdir(...) abort 349 | throw 'vital: System.File: rmdir(): your platform is not supported' 350 | endfunction 351 | endif 352 | 353 | 354 | let &cpo = s:save_cpo 355 | unlet s:save_cpo 356 | 357 | " vim:set et ts=2 sts=2 sw=2 tw=0: 358 | -------------------------------------------------------------------------------- /autoload/vital/_vital_complete/Prelude.vim: -------------------------------------------------------------------------------- 1 | " ___vital___ 2 | " NOTE: lines between '" ___vital___' is generated by :Vitalize. 3 | " Do not mofidify the code nor insert new lines before '" ___vital___' 4 | if v:version > 703 || v:version == 703 && has('patch1170') 5 | function! vital#_vital_complete#Prelude#import() abort 6 | return map({'escape_pattern': '', 'is_funcref': '', 'path2directory': '', 'wcswidth': '', 'is_string': '', 'input_helper': '', 'is_number': '', 'is_cygwin': '', 'path2project_directory': '', 'strwidthpart_reverse': '', 'input_safe': '', 'is_list': '', 'truncate_skipping': '', 'glob': '', 'truncate': '', 'is_dict': '', 'set_default': '', 'is_numeric': '', 'getchar_safe': '', 'substitute_path_separator': '', 'is_mac': '', 'strwidthpart': '', 'getchar': '', 'is_unix': '', 'is_windows': '', 'globpath': '', 'escape_file_searching': '', 'is_float': '', 'smart_execute_command': ''}, 'function("s:" . v:key)') 7 | endfunction 8 | else 9 | function! s:_SID() abort 10 | return matchstr(expand(''), '\zs\d\+\ze__SID$') 11 | endfunction 12 | execute join(['function! vital#_vital_complete#Prelude#import() abort', printf("return map({'escape_pattern': '', 'is_funcref': '', 'path2directory': '', 'wcswidth': '', 'is_string': '', 'input_helper': '', 'is_number': '', 'is_cygwin': '', 'path2project_directory': '', 'strwidthpart_reverse': '', 'input_safe': '', 'is_list': '', 'truncate_skipping': '', 'glob': '', 'truncate': '', 'is_dict': '', 'set_default': '', 'is_numeric': '', 'getchar_safe': '', 'substitute_path_separator': '', 'is_mac': '', 'strwidthpart': '', 'getchar': '', 'is_unix': '', 'is_windows': '', 'globpath': '', 'escape_file_searching': '', 'is_float': '', 'smart_execute_command': ''}, \"function('%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n") 13 | delfunction s:_SID 14 | endif 15 | " ___vital___ 16 | let s:save_cpo = &cpo 17 | set cpo&vim 18 | 19 | if v:version ># 703 || 20 | \ (v:version is 703 && has('patch465')) 21 | function! s:glob(expr) abort 22 | return glob(a:expr, 1, 1) 23 | endfunction 24 | else 25 | function! s:glob(expr) abort 26 | let R = glob(a:expr, 1) 27 | return split(R, '\n') 28 | endfunction 29 | endif 30 | 31 | function! s:globpath(path, expr) abort 32 | let R = globpath(a:path, a:expr, 1) 33 | return split(R, '\n') 34 | endfunction 35 | 36 | " Wrapper functions for type(). 37 | let [ 38 | \ s:__TYPE_NUMBER, 39 | \ s:__TYPE_STRING, 40 | \ s:__TYPE_FUNCREF, 41 | \ s:__TYPE_LIST, 42 | \ s:__TYPE_DICT, 43 | \ s:__TYPE_FLOAT] = [ 44 | \ type(3), 45 | \ type(''), 46 | \ type(function('tr')), 47 | \ type([]), 48 | \ type({}), 49 | \ has('float') ? type(str2float('0')) : -1] 50 | " __TYPE_FLOAT = -1 when -float 51 | " This doesn't match to anything. 52 | 53 | " Number or Float 54 | function! s:is_numeric(Value) abort 55 | let _ = type(a:Value) 56 | return _ ==# s:__TYPE_NUMBER 57 | \ || _ ==# s:__TYPE_FLOAT 58 | endfunction 59 | 60 | " Number 61 | function! s:is_number(Value) abort 62 | return type(a:Value) ==# s:__TYPE_NUMBER 63 | endfunction 64 | 65 | " Float 66 | function! s:is_float(Value) abort 67 | return type(a:Value) ==# s:__TYPE_FLOAT 68 | endfunction 69 | " String 70 | function! s:is_string(Value) abort 71 | return type(a:Value) ==# s:__TYPE_STRING 72 | endfunction 73 | " Funcref 74 | function! s:is_funcref(Value) abort 75 | return type(a:Value) ==# s:__TYPE_FUNCREF 76 | endfunction 77 | " List 78 | function! s:is_list(Value) abort 79 | return type(a:Value) ==# s:__TYPE_LIST 80 | endfunction 81 | " Dictionary 82 | function! s:is_dict(Value) abort 83 | return type(a:Value) ==# s:__TYPE_DICT 84 | endfunction 85 | 86 | function! s:truncate_skipping(str, max, footer_width, separator) abort 87 | call s:_warn_deprecated('truncate_skipping', 'Data.String.truncate_skipping') 88 | 89 | let width = s:wcswidth(a:str) 90 | if width <= a:max 91 | let ret = a:str 92 | else 93 | let header_width = a:max - s:wcswidth(a:separator) - a:footer_width 94 | let ret = s:strwidthpart(a:str, header_width) . a:separator 95 | \ . s:strwidthpart_reverse(a:str, a:footer_width) 96 | endif 97 | 98 | return s:truncate(ret, a:max) 99 | endfunction 100 | 101 | function! s:truncate(str, width) abort 102 | " Original function is from mattn. 103 | " http://github.com/mattn/googlereader-vim/tree/master 104 | 105 | call s:_warn_deprecated('truncate', 'Data.String.truncate') 106 | 107 | if a:str =~# '^[\x00-\x7f]*$' 108 | return len(a:str) < a:width ? 109 | \ printf('%-'.a:width.'s', a:str) : strpart(a:str, 0, a:width) 110 | endif 111 | 112 | let ret = a:str 113 | let width = s:wcswidth(a:str) 114 | if width > a:width 115 | let ret = s:strwidthpart(ret, a:width) 116 | let width = s:wcswidth(ret) 117 | endif 118 | 119 | if width < a:width 120 | let ret .= repeat(' ', a:width - width) 121 | endif 122 | 123 | return ret 124 | endfunction 125 | 126 | function! s:strwidthpart(str, width) abort 127 | call s:_warn_deprecated('strwidthpart', 'Data.String.strwidthpart') 128 | 129 | if a:width <= 0 130 | return '' 131 | endif 132 | let ret = a:str 133 | let width = s:wcswidth(a:str) 134 | while width > a:width 135 | let char = matchstr(ret, '.$') 136 | let ret = ret[: -1 - len(char)] 137 | let width -= s:wcswidth(char) 138 | endwhile 139 | 140 | return ret 141 | endfunction 142 | function! s:strwidthpart_reverse(str, width) abort 143 | call s:_warn_deprecated('strwidthpart_reverse', 'Data.String.strwidthpart_reverse') 144 | 145 | if a:width <= 0 146 | return '' 147 | endif 148 | let ret = a:str 149 | let width = s:wcswidth(a:str) 150 | while width > a:width 151 | let char = matchstr(ret, '^.') 152 | let ret = ret[len(char) :] 153 | let width -= s:wcswidth(char) 154 | endwhile 155 | 156 | return ret 157 | endfunction 158 | 159 | if v:version >= 703 160 | " Use builtin function. 161 | function! s:wcswidth(str) abort 162 | call s:_warn_deprecated('wcswidth', 'Data.String.wcswidth') 163 | return strwidth(a:str) 164 | endfunction 165 | else 166 | function! s:wcswidth(str) abort 167 | call s:_warn_deprecated('wcswidth', 'Data.String.wcswidth') 168 | 169 | if a:str =~# '^[\x00-\x7f]*$' 170 | return strlen(a:str) 171 | end 172 | 173 | let mx_first = '^\(.\)' 174 | let str = a:str 175 | let width = 0 176 | while 1 177 | let ucs = char2nr(substitute(str, mx_first, '\1', '')) 178 | if ucs == 0 179 | break 180 | endif 181 | let width += s:_wcwidth(ucs) 182 | let str = substitute(str, mx_first, '', '') 183 | endwhile 184 | return width 185 | endfunction 186 | 187 | " UTF-8 only. 188 | function! s:_wcwidth(ucs) abort 189 | let ucs = a:ucs 190 | if (ucs >= 0x1100 191 | \ && (ucs <= 0x115f 192 | \ || ucs == 0x2329 193 | \ || ucs == 0x232a 194 | \ || (ucs >= 0x2e80 && ucs <= 0xa4cf 195 | \ && ucs != 0x303f) 196 | \ || (ucs >= 0xac00 && ucs <= 0xd7a3) 197 | \ || (ucs >= 0xf900 && ucs <= 0xfaff) 198 | \ || (ucs >= 0xfe30 && ucs <= 0xfe6f) 199 | \ || (ucs >= 0xff00 && ucs <= 0xff60) 200 | \ || (ucs >= 0xffe0 && ucs <= 0xffe6) 201 | \ || (ucs >= 0x20000 && ucs <= 0x2fffd) 202 | \ || (ucs >= 0x30000 && ucs <= 0x3fffd) 203 | \ )) 204 | return 2 205 | endif 206 | return 1 207 | endfunction 208 | endif 209 | 210 | let s:is_windows = has('win16') || has('win32') || has('win64') || has('win95') 211 | let s:is_cygwin = has('win32unix') 212 | let s:is_mac = !s:is_windows && !s:is_cygwin 213 | \ && (has('mac') || has('macunix') || has('gui_macvim') || 214 | \ (!isdirectory('/proc') && executable('sw_vers'))) 215 | let s:is_unix = has('unix') 216 | 217 | function! s:is_windows() abort 218 | return s:is_windows 219 | endfunction 220 | 221 | function! s:is_cygwin() abort 222 | return s:is_cygwin 223 | endfunction 224 | 225 | function! s:is_mac() abort 226 | return s:is_mac 227 | endfunction 228 | 229 | function! s:is_unix() abort 230 | return s:is_unix 231 | endfunction 232 | 233 | function! s:_warn_deprecated(name, alternative) abort 234 | try 235 | echohl Error 236 | echomsg 'Prelude.' . a:name . ' is deprecated! Please use ' . a:alternative . ' instead.' 237 | finally 238 | echohl None 239 | endtry 240 | endfunction 241 | 242 | function! s:smart_execute_command(action, word) abort 243 | execute a:action . ' ' . (a:word ==# '' ? '' : '`=a:word`') 244 | endfunction 245 | 246 | function! s:escape_file_searching(buffer_name) abort 247 | return escape(a:buffer_name, '*[]?{}, ') 248 | endfunction 249 | 250 | function! s:escape_pattern(str) abort 251 | call s:_warn_deprecated( 252 | \ 'escape_pattern', 253 | \ 'Data.String.escape_pattern', 254 | \) 255 | return escape(a:str, '~"\.^$[]*') 256 | endfunction 257 | 258 | function! s:getchar(...) abort 259 | let c = call('getchar', a:000) 260 | return type(c) == type(0) ? nr2char(c) : c 261 | endfunction 262 | 263 | function! s:getchar_safe(...) abort 264 | let c = s:input_helper('getchar', a:000) 265 | return type(c) == type('') ? c : nr2char(c) 266 | endfunction 267 | 268 | function! s:input_safe(...) abort 269 | return s:input_helper('input', a:000) 270 | endfunction 271 | 272 | function! s:input_helper(funcname, args) abort 273 | let success = 0 274 | if inputsave() !=# success 275 | throw 'vital: Prelude: inputsave() failed' 276 | endif 277 | try 278 | return call(a:funcname, a:args) 279 | finally 280 | if inputrestore() !=# success 281 | throw 'vital: Prelude: inputrestore() failed' 282 | endif 283 | endtry 284 | endfunction 285 | 286 | function! s:set_default(var, val) abort 287 | if !exists(a:var) || type({a:var}) != type(a:val) 288 | let {a:var} = a:val 289 | endif 290 | endfunction 291 | 292 | function! s:substitute_path_separator(path) abort 293 | return s:is_windows ? substitute(a:path, '\\', '/', 'g') : a:path 294 | endfunction 295 | 296 | function! s:path2directory(path) abort 297 | return s:substitute_path_separator(isdirectory(a:path) ? a:path : fnamemodify(a:path, ':p:h')) 298 | endfunction 299 | 300 | function! s:_path2project_directory_git(path) abort 301 | let parent = a:path 302 | 303 | while 1 304 | let path = parent . '/.git' 305 | if isdirectory(path) || filereadable(path) 306 | return parent 307 | endif 308 | let next = fnamemodify(parent, ':h') 309 | if next == parent 310 | return '' 311 | endif 312 | let parent = next 313 | endwhile 314 | endfunction 315 | 316 | function! s:_path2project_directory_svn(path) abort 317 | let search_directory = a:path 318 | let directory = '' 319 | 320 | let find_directory = s:escape_file_searching(search_directory) 321 | let d = finddir('.svn', find_directory . ';') 322 | if d ==# '' 323 | return '' 324 | endif 325 | 326 | let directory = fnamemodify(d, ':p:h:h') 327 | 328 | " Search parent directories. 329 | let parent_directory = s:path2directory( 330 | \ fnamemodify(directory, ':h')) 331 | 332 | if parent_directory !=# '' 333 | let d = finddir('.svn', parent_directory . ';') 334 | if d !=# '' 335 | let directory = s:_path2project_directory_svn(parent_directory) 336 | endif 337 | endif 338 | return directory 339 | endfunction 340 | 341 | function! s:_path2project_directory_others(vcs, path) abort 342 | let vcs = a:vcs 343 | let search_directory = a:path 344 | 345 | let find_directory = s:escape_file_searching(search_directory) 346 | let d = finddir(vcs, find_directory . ';') 347 | if d ==# '' 348 | return '' 349 | endif 350 | return fnamemodify(d, ':p:h:h') 351 | endfunction 352 | 353 | function! s:path2project_directory(path, ...) abort 354 | let is_allow_empty = get(a:000, 0, 0) 355 | let search_directory = s:path2directory(a:path) 356 | let directory = '' 357 | 358 | " Search VCS directory. 359 | for vcs in ['.git', '.bzr', '.hg', '.svn'] 360 | if vcs ==# '.git' 361 | let directory = s:_path2project_directory_git(search_directory) 362 | elseif vcs ==# '.svn' 363 | let directory = s:_path2project_directory_svn(search_directory) 364 | else 365 | let directory = s:_path2project_directory_others(vcs, search_directory) 366 | endif 367 | if directory !=# '' 368 | break 369 | endif 370 | endfor 371 | 372 | " Search project file. 373 | if directory ==# '' 374 | for d in ['build.xml', 'prj.el', '.project', 'pom.xml', 'package.json', 375 | \ 'Makefile', 'configure', 'Rakefile', 'NAnt.build', 376 | \ 'P4CONFIG', 'tags', 'gtags'] 377 | let d = findfile(d, s:escape_file_searching(search_directory) . ';') 378 | if d !=# '' 379 | let directory = fnamemodify(d, ':p:h') 380 | break 381 | endif 382 | endfor 383 | endif 384 | 385 | if directory ==# '' 386 | " Search /src/ directory. 387 | let base = s:substitute_path_separator(search_directory) 388 | if base =~# '/src/' 389 | let directory = base[: strridx(base, '/src/') + 3] 390 | endif 391 | endif 392 | 393 | if directory ==# '' && !is_allow_empty 394 | " Use original path. 395 | let directory = search_directory 396 | endif 397 | 398 | return s:substitute_path_separator(directory) 399 | endfunction 400 | 401 | let &cpo = s:save_cpo 402 | unlet s:save_cpo 403 | 404 | " vim:set et ts=2 sts=2 sw=2 tw=0: 405 | --------------------------------------------------------------------------------