diff --git a/autoload/neosnippet/commands.vim b/autoload/neosnippet/commands.vim index 001f17e..0644f05 100644 --- a/autoload/neosnippet/commands.vim +++ b/autoload/neosnippet/commands.vim @@ -31,7 +31,7 @@ let s:edit_options = [ \ '-runtime', \ '-vertical', '-horizontal', '-direction=', '-split', \] -let s:Cache = neosnippet#util#get_vital().import('System.Cache') +let s:Cache = neosnippet#util#get_vital().import('System.Cache.Deprecated') "}}} function! s:get_list() abort "{{{ diff --git a/autoload/neosnippet/parser.vim b/autoload/neosnippet/parser.vim index 02db170..31637db 100644 --- a/autoload/neosnippet/parser.vim +++ b/autoload/neosnippet/parser.vim @@ -26,7 +26,7 @@ let s:save_cpo = &cpo set cpo&vim -let s:Cache = neosnippet#util#get_vital().import('System.Cache') +let s:Cache = neosnippet#util#get_vital().import('System.Cache.Deprecated') function! neosnippet#parser#_parse_snippets(filename) abort "{{{ if !filereadable(a:filename) diff --git a/autoload/neosnippet/util.vim b/autoload/neosnippet/util.vim index 75696f6..1b45641 100644 --- a/autoload/neosnippet/util.vim +++ b/autoload/neosnippet/util.vim @@ -26,7 +26,7 @@ let s:save_cpo = &cpo set cpo&vim -let s:V = vital#of('neosnippet') +let s:V = vital#neosnippet#of() function! neosnippet#util#get_vital() abort "{{{ return s:V endfunction"}}} diff --git a/autoload/vital/_neosnippet.vim b/autoload/vital/_neosnippet.vim index 2723144..ae19f5b 100644 --- a/autoload/vital/_neosnippet.vim +++ b/autoload/vital/_neosnippet.vim @@ -1,303 +1,5 @@ -let s:self_version = expand(':t:r') -let s:self_file = expand('') +let s:_plugin_name = expand(':t:r') -" Note: The extra argument to globpath() was added in Patch 7.2.051. -let s:globpath_third_arg = v:version > 702 || v:version == 702 && has('patch51') - -let s:loaded = {} - -function! s:import(name, ...) abort - let target = {} - let functions = [] - for a in a:000 - if type(a) == type({}) - let target = a - elseif type(a) == type([]) - let functions = a - endif - unlet a - endfor - let module = s:_import(a:name) - if empty(functions) - call extend(target, module, 'keep') - else - for f in functions - if has_key(module, f) && !has_key(target, f) - let target[f] = module[f] - endif - endfor - endif - return target -endfunction - -function! s:load(...) dict abort - for arg in a:000 - let [name; as] = type(arg) == type([]) ? arg[: 1] : [arg, arg] - let target = split(join(as, ''), '\W\+') - let dict = self - while 1 <= len(target) - let ns = remove(target, 0) - if !has_key(dict, ns) - let dict[ns] = {} - endif - if type(dict[ns]) == type({}) - let dict = dict[ns] - else - unlet dict - break - endif - endwhile - - if exists('dict') - call extend(dict, s:_import(name)) - endif - unlet arg - endfor - return self -endfunction - -function! s:unload() abort - let s:loaded = {} -endfunction - -function! s:exists(name) abort - return s:_get_module_path(a:name) !=# '' -endfunction - -function! s:search(pattern) abort - let paths = s:_vital_files(a:pattern) - let modules = sort(map(paths, 's:_file2module(v:val)')) - return s:_uniq(modules) -endfunction - -function! s:expand_modules(entry, all) abort - if type(a:entry) == type([]) - let candidates = s:_concat(map(copy(a:entry), 's:search(v:val)')) - if empty(candidates) - throw printf('vital: Any of module %s is not found', string(a:entry)) - endif - if eval(join(map(copy(candidates), 'has_key(a:all, v:val)'), '+')) - let modules = [] - else - let modules = [candidates[0]] - endif - else - let modules = s:search(a:entry) - if empty(modules) - throw printf('vital: Module %s is not found', a:entry) - endif - endif - call filter(modules, '!has_key(a:all, v:val)') - for module in modules - let a:all[module] = 1 - endfor - return modules -endfunction - -function! s:_import(name) abort - if type(a:name) == type(0) - return s:_build_module(a:name) - endif - let path = s:_get_module_path(a:name) - if path ==# '' - throw 'vital: module not found: ' . a:name - endif - let sid = s:_get_sid_by_script(path) - if !sid - try - execute 'source' fnameescape(path) - catch /^Vim\%((\a\+)\)\?:E484/ - throw 'vital: module not found: ' . a:name - catch /^Vim\%((\a\+)\)\?:E127/ - " Ignore. - endtry - - let sid = s:_get_sid_by_script(path) - endif - return s:_build_module(sid) -endfunction - -function! s:_get_module_path(name) abort - if s:_is_absolute_path(a:name) && filereadable(a:name) - return a:name - endif - if a:name ==# '' - let paths = [s:self_file] - elseif a:name =~# '\v^\u\w*%(\.\u\w*)*$' - let paths = s:_vital_files(a:name) - else - throw 'vital: Invalid module name: ' . a:name - endif - - call filter(paths, 'filereadable(expand(v:val, 1))') - let path = get(paths, 0, '') - return path !=# '' ? path : '' -endfunction - -function! s:_get_sid_by_script(path) abort - let path = s:_unify_path(a:path) - for line in filter(split(s:_redir('scriptnames'), "\n"), - \ 'stridx(v:val, s:self_version) > 0') - let list = matchlist(line, '^\s*\(\d\+\):\s\+\(.\+\)\s*$') - if !empty(list) && s:_unify_path(list[2]) ==# path - return list[1] - 0 - endif - endfor - return 0 -endfunction - -function! s:_file2module(file) abort - let filename = fnamemodify(a:file, ':p:gs?[\\/]?/?') - let tail = matchstr(filename, 'autoload/vital/_\w\+/\zs.*\ze\.vim$') - return join(split(tail, '[\\/]\+'), '.') -endfunction - -if filereadable(expand(':r') . '.VIM') - " resolve() is slow, so we cache results. - let s:_unify_path_cache = {} - " Note: On windows, vim can't expand path names from 8.3 formats. - " So if getting full path via and $HOME was set as 8.3 format, - " vital load duplicated scripts. Below's :~ avoid this issue. - function! s:_unify_path(path) abort - if has_key(s:_unify_path_cache, a:path) - return s:_unify_path_cache[a:path] - endif - let value = tolower(fnamemodify(resolve(fnamemodify( - \ a:path, ':p')), ':~:gs?[\\/]?/?')) - let s:_unify_path_cache[a:path] = value - return value - endfunction -else - function! s:_unify_path(path) abort - return resolve(fnamemodify(a:path, ':p:gs?[\\/]?/?')) - endfunction -endif - -if s:globpath_third_arg - function! s:_runtime_files(path) abort - return split(globpath(&runtimepath, a:path, 1), "\n") - endfunction -else - function! s:_runtime_files(path) abort - return split(globpath(&runtimepath, a:path), "\n") - endfunction -endif - -let s:_vital_files_cache_runtimepath = '' -let s:_vital_files_cache = [] -function! s:_vital_files(pattern) abort - if s:_vital_files_cache_runtimepath !=# &runtimepath - let path = printf('autoload/vital/%s/**/*.vim', s:self_version) - let s:_vital_files_cache = s:_runtime_files(path) - let mod = ':p:gs?[\\/]\+?/?' - call map(s:_vital_files_cache, 'fnamemodify(v:val, mod)') - let s:_vital_files_cache_runtimepath = &runtimepath - endif - let target = substitute(a:pattern, '\.', '/', 'g') - let target = substitute(target, '\*', '[^/]*', 'g') - let regexp = printf('autoload/vital/%s/%s.vim', s:self_version, target) - return filter(copy(s:_vital_files_cache), 'v:val =~# regexp') -endfunction - -" Copy from System.Filepath -if has('win16') || has('win32') || has('win64') - function! s:_is_absolute_path(path) abort - return a:path =~? '^[a-z]:[/\\]' - endfunction -else - function! s:_is_absolute_path(path) abort - return a:path[0] ==# '/' - endfunction -endif - -function! s:_build_module(sid) abort - if has_key(s:loaded, a:sid) - return copy(s:loaded[a:sid]) - endif - let functions = s:_get_functions(a:sid) - - let prefix = '' . a:sid . '_' - let module = {} - for func in functions - let module[func] = function(prefix . func) - endfor - if has_key(module, '_vital_loaded') - let V = vital#{s:self_version}#new() - if has_key(module, '_vital_depends') - let all = {} - let modules = - \ s:_concat(map(module._vital_depends(), - \ 's:expand_modules(v:val, all)')) - call call(V.load, modules, V) - endif - try - call module._vital_loaded(V) - catch - " FIXME: Show an error message for debug. - endtry - endif - if !get(g:, 'vital_debug', 0) - call filter(module, 'v:key =~# "^\\a"') - endif - let s:loaded[a:sid] = module - return copy(module) -endfunction - -if exists('+regexpengine') - function! s:_get_functions(sid) abort - let funcs = s:_redir(printf("function /\\%%#=2^\%d_", a:sid)) - let map_pat = '' . a:sid . '_\zs\w\+' - return map(split(funcs, "\n"), 'matchstr(v:val, map_pat)') - endfunction -else - function! s:_get_functions(sid) abort - let prefix = '' . a:sid . '_' - let funcs = s:_redir('function') - let filter_pat = '^\s*function ' . prefix - let map_pat = prefix . '\zs\w\+' - return map(filter(split(funcs, "\n"), - \ 'stridx(v:val, prefix) > 0 && v:val =~# filter_pat'), - \ 'matchstr(v:val, map_pat)') - endfunction -endif - -if exists('*uniq') - function! s:_uniq(list) abort - return uniq(a:list) - endfunction -else - function! s:_uniq(list) abort - let i = len(a:list) - 1 - while 0 < i - if a:list[i] ==# a:list[i - 1] - call remove(a:list, i) - let i -= 2 - else - let i -= 1 - endif - endwhile - return a:list - endfunction -endif - -function! s:_concat(lists) abort - let result_list = [] - for list in a:lists - let result_list += list - endfor - return result_list -endfunction - -function! s:_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 - -function! vital#{s:self_version}#new() abort - return s:_import('') +function! vital#{s:_plugin_name}#new() abort + return vital#{s:_plugin_name[1:]}#of() endfunction diff --git a/autoload/vital/_neosnippet/Data/List.vim b/autoload/vital/_neosnippet/Data/List.vim index c8aac65..d779275 100644 --- a/autoload/vital/_neosnippet/Data/List.vim +++ b/autoload/vital/_neosnippet/Data/List.vim @@ -1,3 +1,18 @@ +" ___vital___ +" NOTE: lines between '" ___vital___' is generated by :Vitalize. +" Do not mofidify the code nor insert new lines before '" ___vital___' +if v:version > 703 || v:version == 703 && has('patch1170') + function! vital#_neosnippet#Data#List#import() abort + return map({'combinations': '', 'and': '', 'sort_by': '', 'foldr1': '', 'sort': '', 'flatten': '', 'has_index': '', 'find_indices': '', 'any': '', 'unshift': '', 'span': '', 'pop': '', 'binary_search': '', 'uniq_by': '', 'or': '', 'all': '', 'zip': '', 'find_last_index': '', 'find': '', 'partition': '', 'map_accum': '', 'permutations': '', 'break': '', 'max_by': '', 'foldl': '', 'foldr': '', 'find_index': '', 'group_by': '', 'take_while': '', 'conj': '', 'push': '', 'char_range': '', 'cons': '', 'foldl1': '', 'intersect': '', 'concat': '', 'shift': '', 'clear': '', 'has_common_items': '', 'product': '', 'zip_fill': '', 'uniq': '', 'has': '', 'min_by': '', 'with_index': ''}, 'function("s:" . v:key)') + endfunction +else + function! s:_SID() abort + return matchstr(expand(''), '\zs\d\+\ze__SID$') + endfunction + execute join(['function! vital#_neosnippet#Data#List#import() abort', printf("return map({'combinations': '', 'and': '', 'sort_by': '', 'foldr1': '', 'sort': '', 'flatten': '', 'has_index': '', 'find_indices': '', 'any': '', 'unshift': '', 'span': '', 'pop': '', 'binary_search': '', 'uniq_by': '', 'or': '', 'all': '', 'zip': '', 'find_last_index': '', 'find': '', 'partition': '', 'map_accum': '', 'permutations': '', 'break': '', 'max_by': '', 'foldl': '', 'foldr': '', 'find_index': '', 'group_by': '', 'take_while': '', 'conj': '', 'push': '', 'char_range': '', 'cons': '', 'foldl1': '', 'intersect': '', 'concat': '', 'shift': '', 'clear': '', 'has_common_items': '', 'product': '', 'zip_fill': '', 'uniq': '', 'has': '', 'min_by': '', 'with_index': ''}, \"function('%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n") + delfunction s:_SID +endif +" ___vital___ " Utilities for list. let s:save_cpo = &cpo @@ -225,7 +240,7 @@ endfunction " similar to Haskell's Prelude.foldl1 function! s:foldl1(f, xs) abort if len(a:xs) == 0 - throw 'foldl1' + throw 'vital: Data.List: foldl1' endif return s:foldl(a:f, a:xs[0], a:xs[1:]) endfunction @@ -238,7 +253,7 @@ endfunction " similar to Haskell's Prelude.fold11 function! s:foldr1(f, xs) abort if len(a:xs) == 0 - throw 'foldr1' + throw 'vital: Data.List: foldr1' endif return s:foldr(a:f, a:xs[-1], a:xs[0:-2]) endfunction @@ -264,7 +279,7 @@ endfunction " Inspired by Ruby's with_index method. function! s:with_index(list, ...) abort let base = a:0 > 0 ? a:1 : 0 - return s:zip(a:list, range(base, len(a:list)+base-1)) + return map(copy(a:list), '[v:val, v:key + base]') endfunction " similar to Ruby's detect or Haskell's find. diff --git a/autoload/vital/_neosnippet/Data/String.vim b/autoload/vital/_neosnippet/Data/String.vim index a29cc8d..2824472 100644 --- a/autoload/vital/_neosnippet/Data/String.vim +++ b/autoload/vital/_neosnippet/Data/String.vim @@ -1,3 +1,18 @@ +" ___vital___ +" NOTE: lines between '" ___vital___' is generated by :Vitalize. +" Do not mofidify the code nor insert new lines before '" ___vital___' +if v:version > 703 || v:version == 703 && has('patch1170') + function! vital#_neosnippet#Data#String#import() abort + return map({'trim': '', 'chomp': '', 'starts_with': '', 'truncate_skipping': '', 'pad_left': '', 'hash': '', 'trim_end': '', 'nr2enc_char': '', '_vital_depends': '', 'wrap': '', 'split3': '', 'strwidthpart_reverse': '', 'pad_both_sides': '', 'chop': '', 'lines': '', 'contains_multibyte': '', 'nr2byte': '', 'dstring': '', 'replace': '', 'scan': '', 'diffidx': '', 'strchars': '', 'pad_between_letters': '', 'ends_with': '', 'nsplit': '', 'justify_equal_spacing': '', 'strwidthpart': '', 'split_leftright': '', 'truncate': '', 'substitute_last': '', 'pad_right': '', 'replace_first': '', 'split_by_displaywidth': '', 'wcswidth': '', 'common_head': '', 'levenshtein_distance': '', 'reverse': '', 'trim_start': '', 'nr2hex': '', 'padding_by_displaywidth': '', '_vital_loaded': ''}, 'function("s:" . v:key)') + endfunction +else + function! s:_SID() abort + return matchstr(expand(''), '\zs\d\+\ze__SID$') + endfunction + execute join(['function! vital#_neosnippet#Data#String#import() abort', printf("return map({'trim': '', 'chomp': '', 'starts_with': '', 'truncate_skipping': '', 'pad_left': '', 'hash': '', 'trim_end': '', 'nr2enc_char': '', '_vital_depends': '', 'wrap': '', 'split3': '', 'strwidthpart_reverse': '', 'pad_both_sides': '', 'chop': '', 'lines': '', 'contains_multibyte': '', 'nr2byte': '', 'dstring': '', 'replace': '', 'scan': '', 'diffidx': '', 'strchars': '', 'pad_between_letters': '', 'ends_with': '', 'nsplit': '', 'justify_equal_spacing': '', 'strwidthpart': '', 'split_leftright': '', 'truncate': '', 'substitute_last': '', 'pad_right': '', 'replace_first': '', 'split_by_displaywidth': '', 'wcswidth': '', 'common_head': '', 'levenshtein_distance': '', 'reverse': '', 'trim_start': '', 'nr2hex': '', 'padding_by_displaywidth': '', '_vital_loaded': ''}, \"function('%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n") + delfunction s:_SID +endif +" ___vital___ " Utilities for string. let s:save_cpo = &cpo @@ -40,6 +55,15 @@ function! s:reverse(str) abort return join(reverse(split(a:str, '.\zs')), '') endfunction +function! s:starts_with(str, prefix) abort + return stridx(a:str, a:prefix) == 0 +endfunction + +function! s:ends_with(str, suffix) abort + let idx = strridx(a:str, a:suffix) + return 0 <= idx && idx + len(a:suffix) == len(a:str) +endfunction + function! s:common_head(strs) abort if empty(a:strs) return '' @@ -50,7 +74,7 @@ function! s:common_head(strs) abort endif let strs = len == 2 ? a:strs : sort(copy(a:strs)) let pat = substitute(strs[0], '.', '\="[" . escape(submatch(0), "^\\") . "]"', 'g') - return pat == '' ? '' : matchstr(strs[-1], '\C^\%[' . pat . ']') + return pat ==# '' ? '' : matchstr(strs[-1], '\C^\%[' . pat . ']') endfunction " Split to two elements of List. ([left, right]) @@ -154,15 +178,15 @@ endfunction "}}} " NOTE _concat() is just a copy of Data.List.concat(). " FIXME don't repeat yourself function! s:_split_by_wcswidth_once(body, x) abort - let fst = s:P.strwidthpart(a:body, a:x) - let snd = s:P.strwidthpart_reverse(a:body, s:P.wcswidth(a:body) - s:P.wcswidth(fst)) + let fst = s:strwidthpart(a:body, a:x) + let snd = s:strwidthpart_reverse(a:body, s:wcswidth(a:body) - s:wcswidth(fst)) return [fst, snd] endfunction function! s:_split_by_wcswidth(body, x) abort let memo = [] let body = a:body - while s:P.wcswidth(body) > a:x + while s:wcswidth(body) > a:x let [tmp, body] = s:_split_by_wcswidth_once(body, a:x) call add(memo, tmp) endwhile @@ -174,6 +198,14 @@ function! s:trim(str) abort return matchstr(a:str,'^\s*\zs.\{-}\ze\s*$') endfunction +function! s:trim_start(str) abort + return matchstr(a:str,'^\s*\zs.\{-}$') +endfunction + +function! s:trim_end(str) abort + return matchstr(a:str,'^.\{-}\ze\s*$') +endfunction + function! s:wrap(str,...) abort let _columns = a:0 > 0 ? a:1 : &columns return s:L.concat( @@ -191,7 +223,7 @@ function! s:nr2byte(nr) abort endfunction function! s:nr2enc_char(charcode) abort - if &encoding == 'utf-8' + if &encoding ==# 'utf-8' return nr2char(a:charcode) endif let char = s:nr2byte(a:charcode) @@ -203,7 +235,7 @@ endfunction function! s:nr2hex(nr) abort let n = a:nr - let r = "" + let r = '' while n let r = '0123456789ABCDEF'[n % 16] . r let n = n / 16 @@ -354,7 +386,7 @@ function! s:split_by_displaywidth(expr, width, float, is_wrap) abort let text = '' while cs_index < len(cs) - if cs[cs_index] is "\n" + if cs[cs_index] is# "\n" let text = s:padding_by_displaywidth(text, a:width, a:float) let lines += [text] let text = '' @@ -375,7 +407,7 @@ function! s:split_by_displaywidth(expr, width, float, is_wrap) abort if a:is_wrap if a:width < w if a:width < strdisplaywidth(cs[cs_index]) - while get(cs, cs_index, "\n") isnot "\n" + while get(cs, cs_index, "\n") isnot# "\n" let cs_index += 1 endwhile continue @@ -384,7 +416,7 @@ function! s:split_by_displaywidth(expr, width, float, is_wrap) abort endif endif else - while get(cs, cs_index, "\n") isnot "\n" + while get(cs, cs_index, "\n") isnot# "\n" let cs_index += 1 endwhile continue diff --git a/autoload/vital/_neosnippet/Prelude.vim b/autoload/vital/_neosnippet/Prelude.vim index 0511de7..ed80ed7 100644 --- a/autoload/vital/_neosnippet/Prelude.vim +++ b/autoload/vital/_neosnippet/Prelude.vim @@ -1,3 +1,18 @@ +" ___vital___ +" NOTE: lines between '" ___vital___' is generated by :Vitalize. +" Do not mofidify the code nor insert new lines before '" ___vital___' +if v:version > 703 || v:version == 703 && has('patch1170') + function! vital#_neosnippet#Prelude#import() abort + 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)') + endfunction +else + function! s:_SID() abort + return matchstr(expand(''), '\zs\d\+\ze__SID$') + endfunction + execute join(['function! vital#_neosnippet#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") + delfunction s:_SID +endif +" ___vital___ let s:save_cpo = &cpo set cpo&vim @@ -27,7 +42,7 @@ let [ \ s:__TYPE_DICT, \ s:__TYPE_FLOAT] = [ \ type(3), - \ type(""), + \ type(''), \ type(function('tr')), \ type([]), \ type({}), @@ -69,7 +84,7 @@ function! s:is_dict(Value) abort endfunction function! s:truncate_skipping(str, max, footer_width, separator) abort - call s:_warn_deprecated("truncate_skipping", "Data.String.truncate_skipping") + call s:_warn_deprecated('truncate_skipping', 'Data.String.truncate_skipping') let width = s:wcswidth(a:str) if width <= a:max @@ -87,7 +102,7 @@ function! s:truncate(str, width) abort " Original function is from mattn. " http://github.com/mattn/googlereader-vim/tree/master - call s:_warn_deprecated("truncate", "Data.String.truncate") + call s:_warn_deprecated('truncate', 'Data.String.truncate') if a:str =~# '^[\x00-\x7f]*$' return len(a:str) < a:width ? @@ -109,7 +124,7 @@ function! s:truncate(str, width) abort endfunction function! s:strwidthpart(str, width) abort - call s:_warn_deprecated("strwidthpart", "Data.String.strwidthpart") + call s:_warn_deprecated('strwidthpart', 'Data.String.strwidthpart') if a:width <= 0 return '' @@ -125,7 +140,7 @@ function! s:strwidthpart(str, width) abort return ret endfunction function! s:strwidthpart_reverse(str, width) abort - call s:_warn_deprecated("strwidthpart_reverse", "Data.String.strwidthpart_reverse") + call s:_warn_deprecated('strwidthpart_reverse', 'Data.String.strwidthpart_reverse') if a:width <= 0 return '' @@ -144,12 +159,12 @@ endfunction if v:version >= 703 " Use builtin function. function! s:wcswidth(str) abort - call s:_warn_deprecated("wcswidth", "Data.String.wcswidth") + call s:_warn_deprecated('wcswidth', 'Data.String.wcswidth') return strwidth(a:str) endfunction else function! s:wcswidth(str) abort - call s:_warn_deprecated("wcswidth", "Data.String.wcswidth") + call s:_warn_deprecated('wcswidth', 'Data.String.wcswidth') if a:str =~# '^[\x00-\x7f]*$' return strlen(a:str) @@ -218,14 +233,14 @@ endfunction function! s:_warn_deprecated(name, alternative) abort try echohl Error - echomsg "Prelude." . a:name . " is deprecated! Please use " . a:alternative . " instead." + echomsg 'Prelude.' . a:name . ' is deprecated! Please use ' . a:alternative . ' instead.' finally echohl None endtry endfunction function! s:smart_execute_command(action, word) abort - execute a:action . ' ' . (a:word == '' ? '' : '`=a:word`') + execute a:action . ' ' . (a:word ==# '' ? '' : '`=a:word`') endfunction function! s:escape_file_searching(buffer_name) abort @@ -243,7 +258,7 @@ endfunction function! s:getchar_safe(...) abort let c = s:input_helper('getchar', a:000) - return type(c) == type("") ? c : nr2char(c) + return type(c) == type('') ? c : nr2char(c) endfunction function! s:input_safe(...) abort @@ -253,13 +268,13 @@ endfunction function! s:input_helper(funcname, args) abort let success = 0 if inputsave() !=# success - throw 'inputsave() failed' + throw 'vital: Prelude: inputsave() failed' endif try return call(a:funcname, a:args) finally if inputrestore() !=# success - throw 'inputrestore() failed' + throw 'vital: Prelude: inputrestore() failed' endif endtry endfunction @@ -300,7 +315,7 @@ function! s:_path2project_directory_svn(path) abort let find_directory = s:escape_file_searching(search_directory) let d = finddir('.svn', find_directory . ';') - if d == '' + if d ==# '' return '' endif @@ -310,9 +325,9 @@ function! s:_path2project_directory_svn(path) abort let parent_directory = s:path2directory( \ fnamemodify(directory, ':h')) - if parent_directory != '' + if parent_directory !=# '' let d = finddir('.svn', parent_directory . ';') - if d != '' + if d !=# '' let directory = s:_path2project_directory_svn(parent_directory) endif endif @@ -325,7 +340,7 @@ function! s:_path2project_directory_others(vcs, path) abort let find_directory = s:escape_file_searching(search_directory) let d = finddir(vcs, find_directory . ';') - if d == '' + if d ==# '' return '' endif return fnamemodify(d, ':p:h:h') @@ -345,25 +360,25 @@ function! s:path2project_directory(path, ...) abort else let directory = s:_path2project_directory_others(vcs, search_directory) endif - if directory != '' + if directory !=# '' break endif endfor " Search project file. - if directory == '' + if directory ==# '' for d in ['build.xml', 'prj.el', '.project', 'pom.xml', 'package.json', \ 'Makefile', 'configure', 'Rakefile', 'NAnt.build', \ 'P4CONFIG', 'tags', 'gtags'] let d = findfile(d, s:escape_file_searching(search_directory) . ';') - if d != '' + if d !=# '' let directory = fnamemodify(d, ':p:h') break endif endfor endif - if directory == '' + if directory ==# '' " Search /src/ directory. let base = s:substitute_path_separator(search_directory) if base =~# '/src/' @@ -371,7 +386,7 @@ function! s:path2project_directory(path, ...) abort endif endif - if directory == '' && !is_allow_empty + if directory ==# '' && !is_allow_empty " Use original path. let directory = search_directory endif diff --git a/autoload/vital/_neosnippet/Process.vim b/autoload/vital/_neosnippet/Process.vim index f04699b..a3ac87c 100644 --- a/autoload/vital/_neosnippet/Process.vim +++ b/autoload/vital/_neosnippet/Process.vim @@ -1,3 +1,18 @@ +" ___vital___ +" NOTE: lines between '" ___vital___' is generated by :Vitalize. +" Do not mofidify the code nor insert new lines before '" ___vital___' +if v:version > 703 || v:version == 703 && has('patch1170') + function! vital#_neosnippet#Process#import() abort + return map({'shellescape': '', 'has_vimproc': '', 'system': '', 'iconv': '', 'spawn': '', 'get_last_status': ''}, 'function("s:" . v:key)') + endfunction +else + function! s:_SID() abort + return matchstr(expand(''), '\zs\d\+\ze__SID$') + endfunction + execute join(['function! vital#_neosnippet#Process#import() abort', printf("return map({'shellescape': '', 'has_vimproc': '', 'system': '', 'iconv': '', 'spawn': '', 'get_last_status': ''}, \"function('%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n") + delfunction s:_SID +endif +" ___vital___ " TODO: move all comments to doc file. " " @@ -19,23 +34,8 @@ let s:need_trans = v:version < 704 || (v:version == 704 && !has('patch122')) let s:TYPE_DICT = type({}) let s:TYPE_LIST = type([]) -let s:TYPE_STRING = type("") +let s:TYPE_STRING = type('') - -" Execute program in the background from Vim. -" Return an empty string always. -" -" If a:expr is a List, shellescape() each argument. -" If a:expr is a String, the arguments are passed as-is. -" -" Windows: -" Using :!start , execute program without via cmd.exe. -" Spawning 'expr' with 'noshellslash' -" keep special characters from unwanted expansion. -" (see :help shellescape()) -" -" Unix: -" using :! , execute program in the background by shell. function! s:spawn(expr, ...) abort let shellslash = 0 if s:is_windows @@ -70,11 +70,11 @@ endfunction " iconv() wrapper for safety. function! s:iconv(expr, from, to) abort - if a:from == '' || a:to == '' || a:from ==? a:to + 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 + return result !=# '' ? result : a:expr endfunction " Check vimproc. diff --git a/autoload/vital/_neosnippet/System/Cache.vim b/autoload/vital/_neosnippet/System/Cache/Deprecated.vim similarity index 66% rename from autoload/vital/_neosnippet/System/Cache.vim rename to autoload/vital/_neosnippet/System/Cache/Deprecated.vim index b7c11ad..b21d6da 100644 --- a/autoload/vital/_neosnippet/System/Cache.vim +++ b/autoload/vital/_neosnippet/System/Cache/Deprecated.vim @@ -1,4 +1,20 @@ -" Utilities for output cache. +" ___vital___ +" NOTE: lines between '" ___vital___' is generated by :Vitalize. +" Do not mofidify the code nor insert new lines before '" ___vital___' +if v:version > 703 || v:version == 703 && has('patch1170') + function! vital#_neosnippet#System#Cache#Deprecated#import() abort + return map({'filereadable': '', '_vital_depends': '', 'delete': '', 'readfile': '', 'getfilename': '', 'deletefile': '', 'check_old_cache': '', 'writefile': '', '_vital_loaded': ''}, 'function("s:" . v:key)') + endfunction +else + function! s:_SID() abort + return matchstr(expand(''), '\zs\d\+\ze__SID$') + endfunction + execute join(['function! vital#_neosnippet#System#Cache#Deprecated#import() abort', printf("return map({'filereadable': '', '_vital_depends': '', 'delete': '', 'readfile': '', 'getfilename': '', 'deletefile': '', 'check_old_cache': '', 'writefile': '', '_vital_loaded': ''}, \"function('%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n") + delfunction s:_SID +endif +" ___vital___ +" Note: +" This module is deprecated. Use a new `Syste.Cache` instead. let s:save_cpo = &cpo set cpo&vim @@ -48,7 +64,7 @@ function! s:_encode_name(cache_dir, filename) abort call mkdir(a:cache_dir, 'p') endif let cache_dir = a:cache_dir - if cache_dir !~ '/$' + if cache_dir !~# '/$' let cache_dir .= '/' endif diff --git a/autoload/vital/neosnippet.vim b/autoload/vital/neosnippet.vim new file mode 100644 index 0000000..bec6299 --- /dev/null +++ b/autoload/vital/neosnippet.vim @@ -0,0 +1,302 @@ +let s:plugin_name = expand(':t:r') +let s:vital_base_dir = expand(':h') +let s:project_root = expand(':h:h:h') +let s:has_latest_module = isdirectory(expand(':h') . '/__latest__') +let s:is_vital_vim = s:plugin_name is# '_latest__' + +let s:loaded = {} +let s:cache_sid = {} + +" function() wrapper +if v:version > 703 || v:version == 703 && has('patch1170') + function! s:_function(fstr) abort + return function(a:fstr) + endfunction +else + function! s:_SID() abort + return matchstr(expand(''), '\zs\d\+\ze__SID$') + endfunction + let s:_s = '' . s:_SID() . '_' + function! s:_function(fstr) abort + return function(substitute(a:fstr, 's:', s:_s, 'g')) + endfunction +endif + +function! vital#{s:plugin_name}#of() abort + return s:new(s:plugin_name) +endfunction + +let s:Vital = {} + +function! s:new(plugin_name) abort + let base = deepcopy(s:Vital) + let base.plugin_name = a:plugin_name + return base +endfunction + +function! s:vital_files() abort + if !exists('s:vital_files') + let s:vital_files = map( + \ s:is_vital_vim ? s:_global_vital_files() : s:_self_vital_files(), + \ 'fnamemodify(v:val, ":p:gs?[\\\\/]?/?")') + endif + return copy(s:vital_files) +endfunction +let s:Vital.vital_files = s:_function('s:vital_files') + +function! s:import(name, ...) abort dict + let target = {} + let functions = [] + for a in a:000 + if type(a) == type({}) + let target = a + elseif type(a) == type([]) + let functions = a + endif + unlet a + endfor + let module = self._import(a:name) + if empty(functions) + call extend(target, module, 'keep') + else + for f in functions + if has_key(module, f) && !has_key(target, f) + let target[f] = module[f] + endif + endfor + endif + return target +endfunction +let s:Vital.import = s:_function('s:import') + +function! s:load(...) abort dict + for arg in a:000 + let [name; as] = type(arg) == type([]) ? arg[: 1] : [arg, arg] + let target = split(join(as, ''), '\W\+') + let dict = self + let dict_type = type({}) + while !empty(target) + let ns = remove(target, 0) + if !has_key(dict, ns) + let dict[ns] = {} + endif + if type(dict[ns]) == dict_type + let dict = dict[ns] + else + unlet dict + break + endif + endwhile + if exists('dict') + call extend(dict, self._import(name)) + endif + unlet arg + endfor + return self +endfunction +let s:Vital.load = s:_function('s:load') + +function! s:unload() abort dict + let s:loaded = {} + let s:cache_sid = {} + unlet! s:vital_files +endfunction +let s:Vital.unload = s:_function('s:unload') + +function! s:exists(name) abort dict + let b = exists(printf('*vital#_%s#%s#import', self.plugin_name, substitute(a:name, '\.', '#', 'g'))) + if b + return b + endif + let name_path = substitute(a:name, '\.', '/', 'g') + let path = printf('%s/_%s/%s.vim', s:vital_base_dir, self.plugin_name, name_path) + let b = filereadable(path) + if b + return b + endif + let path = printf('%s/_%s/%s.vim', s:vital_base_dir, '_latest__', name_path) + let b = filereadable(path) +endfunction +let s:Vital.exists = s:_function('s:exists') + +function! s:search(pattern) abort dict + let paths = s:_extract_files(a:pattern, self.vital_files()) + let modules = sort(map(paths, 's:_file2module(v:val)')) + return s:_uniq(modules) +endfunction +let s:Vital.search = s:_function('s:search') + +function! s:_self_vital_files() abort + let base = s:vital_base_dir . '/*/**/*.vim' + return split(glob(base, 1), "\n") +endfunction + +function! s:_global_vital_files() abort + let pattern = 'autoload/vital/__latest__/**/*.vim' + return split(globpath(&runtimepath, pattern, 1), "\n") +endfunction + +function! s:_extract_files(pattern, files) abort + let tr = {'.': '/', '*': '[^/]*', '**': '.*'} + let target = substitute(a:pattern, '\.\|\*\*\?', '\=tr[submatch(0)]', 'g') + let regexp = printf('autoload/vital/[^/]\+/%s.vim$', target) + return filter(a:files, 'v:val =~# regexp') +endfunction + +function! s:_file2module(file) abort + let filename = fnamemodify(a:file, ':p:gs?[\\/]?/?') + let tail = matchstr(filename, 'autoload/vital/_\w\+/\zs.*\ze\.vim$') + return join(split(tail, '[\\/]\+'), '.') +endfunction + +" @param {string} name e.g. Data.List +function! s:_import(name) abort dict + if has_key(s:loaded, a:name) + return copy(s:loaded[a:name]) + endif + let module = self._get_module(a:name) + if has_key(module, '_vital_created') + call module._vital_created(module) + endif + let export_module = filter(copy(module), 'v:key =~# "^\\a"') + " Cache module before calling module.vital_loaded() to avoid cyclic + " dependences but remove the cache if module._vital_loaded() fails. + " let s:loaded[a:name] = export_module + let s:loaded[a:name] = export_module + if has_key(module, '_vital_loaded') + try + call module._vital_loaded(vital#{s:plugin_name}#of()) + catch + unlet s:loaded[a:name] + throw 'vital: fail to call ._vital_loaded(): ' . v:exception + endtry + endif + return copy(s:loaded[a:name]) +endfunction +let s:Vital._import = s:_function('s:_import') + +" s:_get_module() returns module object wihch has all script local functions. +function! s:_get_module(name) abort dict + try + let module = vital#_{self.plugin_name}#{substitute(a:name, '\.', '#', 'g')}#import() + catch /E117: Unknown function:/ + if !s:has_latest_module + throw 'vital: module not found: ' . a:name + endif + " Retry to support loading self modules. + let module = s:_get_latest_module(a:name) + endtry + return module +endfunction +let s:Vital._get_module = s:_function('s:_get_module') + +function! s:_get_latest_module(name) abort + return s:sid2sfuncs(s:_module_sid(a:name)) +endfunction + +function! s:_module_sid(name) abort + let module_rel_path = 'autoload/vital/__latest__/' . substitute(a:name, '\.', '/', 'g') . '.vim' + let module_full_path = s:_unify_path(get(split(globpath(s:_module_sid_base_dir(), module_rel_path, 0), "\n"), 0, '')) + if !filereadable(module_full_path) + throw 'vital: module not found: ' . a:name + endif + let p = substitute(module_rel_path, '/', '[/\\\\]\\+', 'g') + let sid = s:_sid(module_full_path, p) + if !sid + call s:_source(module_full_path) + let sid = s:_sid(module_full_path, p) + if !sid + throw 'vital: cannot get from path' + endif + endif + return sid +endfunction + +function! s:_module_sid_base_dir() abort + return s:is_vital_vim ? &rtp : s:project_root +endfunction + +function! s:_source(path) abort + execute 'source' fnameescape(a:path) +endfunction + +" @vimlint(EVL102, 1, l:_) +" @vimlint(EVL102, 1, l:__) +function! s:_sid(fullpath, filter_pattern) abort + if has_key(s:cache_sid, a:fullpath) + return s:cache_sid[a:fullpath] + endif + for line in filter(split(s:_redir(':scriptnames'), "\n"), 'v:val =~# a:filter_pattern') + let [_, sid, path; __] = matchlist(line, '^\s*\(\d\+\):\s\+\(.\+\)\s*$') + if s:_unify_path(path) is# a:fullpath + let s:cache_sid[a:fullpath] = sid + return s:cache_sid[a:fullpath] + endif + endfor + return 0 +endfunction + +function! s:_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 + +if filereadable(expand(':r') . '.VIM') + let s:_unify_path_cache = {} + " resolve() is slow, so we cache results. + " Note: On windows, vim can't expand path names from 8.3 formats. + " So if getting full path via and $HOME was set as 8.3 format, + " vital load duplicated scripts. Below's :~ avoid this issue. + function! s:_unify_path(path) abort + if has_key(s:_unify_path_cache, a:path) + return s:_unify_path_cache[a:path] + endif + let value = tolower(fnamemodify(resolve(fnamemodify( + \ a:path, ':p')), ':~:gs?[\\/]?/?')) + let s:_unify_path_cache[a:path] = value + return value + endfunction +else + function! s:_unify_path(path) abort + return resolve(fnamemodify(a:path, ':p:gs?[\\/]?/?')) + endfunction +endif + +" copied and modified from Vim.ScriptLocal +let s:SNR = join(map(range(len("\")), '"[\\x" . printf("%0x", char2nr("\"[v:val])) . "]"'), '') +function! s:sid2sfuncs(sid) abort + let fs = split(s:_redir(printf(':function /^%s%s_', s:SNR, a:sid)), "\n") + let r = {} + let pattern = printf('\m^function\s%d_\zs\w\{-}\ze(', a:sid) + for fname in map(fs, 'matchstr(v:val, pattern)') + let r[fname] = function(s:_sfuncname(a:sid, fname)) + endfor + return r +endfunction + +"" Return funcname of script local functions with SID +function! s:_sfuncname(sid, funcname) abort + return printf('%s_%s', a:sid, a:funcname) +endfunction + +if exists('*uniq') + function! s:_uniq(list) abort + return uniq(a:list) + endfunction +else + function! s:_uniq(list) abort + let i = len(a:list) - 1 + while 0 < i + if a:list[i] ==# a:list[i - 1] + call remove(a:list, i) + endif + let i -= 1 + endwhile + return a:list + endfunction +endif diff --git a/autoload/vital/neosnippet.vital b/autoload/vital/neosnippet.vital index 9e91d1d..c3243ed 100644 --- a/autoload/vital/neosnippet.vital +++ b/autoload/vital/neosnippet.vital @@ -1,8 +1,8 @@ neosnippet -1c73bcc +024411ba1a5f3d545899c1be6eaa40bba036ae0d Prelude Data.List Process -System.Cache Data.String +System.Cache.Deprecated