├── README.md ├── autoload ├── debugger.vim ├── debugger │ └── stacktrace.vim ├── vital.vim └── vital │ ├── _debugger.vim │ ├── _debugger │ ├── Data │ │ ├── List.vim │ │ ├── Set.vim │ │ └── String.vim │ ├── Prelude.vim │ └── Vim │ │ ├── Message.vim │ │ ├── ScriptLocal.vim │ │ └── SyntaxEcho.vim │ └── debugger.vital └── plugin └── debugger.vim /README.md: -------------------------------------------------------------------------------- 1 | :bug: vim-debugger 2 | ================== 3 | 4 | vim-debugger is a Vim script debugger. 5 | 6 | *[The APIs might change]* 7 | 8 | :debug improved 9 | --------------- 10 | ![https://gyazo.com/926142136e0429f032efabbc8e5e3c6c](https://i.gyazo.com/926142136e0429f032efabbc8e5e3c6c.png) 11 | 12 | ### Commands 13 | 14 | | command | description | 15 | | ------- | ----------- | 16 | | `:DebugOn` | turn on debugging commands | 17 | | `:Debugger` | add breakpoint | 18 | | `>Current` | show current line and function in debug-mode with syntax highlight | 19 | | `>Break {lnum}` | add break point to {lnum} in a current function | 20 | | `>File` | show current file in debug-mode | 21 | | `>SID` | show `` in debug-mode | 22 | | `>DebugHelp` | show help for debug-mode | 23 | | `>Sfuncs` | list script-local functions in debug-mode | 24 | 25 | :feet: StackTrace 26 | ----------------- 27 | 28 | ```vim 29 | :StackTrace function vitalizer#command[37]..vitalizer#vitalize[69]..210_search_dependence[20]..211_import[11]..211__import[20]..211__build_module[18]..218__vital_loaded[2]..211_import[11]..211__import: line 6: 30 | ``` 31 | 32 | ![https://gyazo.com/e3f70551a4ce1ab1f614542a4fac0921](https://i.gyazo.com/e3f70551a4ce1ab1f614542a4fac0921.png) 33 | 34 | | command | description | 35 | | ------- | ----------- | 36 | | `:StackTrace {throwpoint}` | show stacktrace | 37 | | `:CallStack {id}` | get callstack and save it as {id} | 38 | | `:CallStackReport {id}` | report {id} callstack | 39 | -------------------------------------------------------------------------------- /autoload/debugger.vim: -------------------------------------------------------------------------------- 1 | let s:V = vital#of('debugger') 2 | let s:Message = s:V.import('Vim.Message') 3 | let s:ScriptLocal = s:V.import('Vim.ScriptLocal') 4 | let s:String = s:V.import('Data.String') 5 | let s:SyntaxEcho = s:V.import('Vim.SyntaxEcho') 6 | 7 | function! debugger#init() abort 8 | " source this file 9 | endfunction 10 | 11 | command! Debugger execute 'breakadd' 'func' (expand('') + 1) s:current_func() 12 | 13 | command! Current call s:show_current(s:current_func(), expand(''), expand('')) 14 | 15 | command! DebugHelp echo s:help() 16 | 17 | command! -nargs=1 Break execute 'breakadd' 'func' s:current_func() 18 | 19 | command! File echo s:current_file(expand('')) 20 | command! SID echo s:sid(expand('')) 21 | command! -nargs=? Sfuncs echo PP(s:sfuncs( is# '' ? s:sid(expand('') : )) 22 | 23 | augroup debugger-breakpoint 24 | autocmd! 25 | autocmd TextChanged,TextChangedI *.vim breakdel * 26 | autocmd ColorScheme * call s:init_hl() 27 | augroup END 28 | 29 | function! s:init_hl() abort 30 | highlight DebuggerSeparator term=bold ctermfg=166 gui=bold guifg=#ef5939 31 | highlight DebuggerCallStack term=bold cterm=bold ctermfg=118 gui=bold guifg=#A6E22E 32 | highlight DebuggerCurrentLineMark term=standout cterm=bold ctermfg=199 ctermbg=16 gui=bold guifg=#F92672 guibg=#232526 33 | endfunction 34 | call s:init_hl() 35 | 36 | function! s:sid(sfile) abort 37 | let func = s:current_func(-3) 38 | if func is# '' 39 | return s:ScriptLocal.sid(a:sfile) 40 | endif 41 | return s:ScriptLocal.sid(s:last_set(func)) 42 | endfunction 43 | 44 | function! s:current_file(sfile) abort 45 | let func = s:current_func(-3) 46 | if func is# '' 47 | return a:sfile 48 | endif 49 | return s:last_set(func) 50 | endfunction 51 | 52 | function! s:current_func(...) abort 53 | let offset = get(a:, 1, -2) 54 | let sfile = substitute(expand(''), 'function ', '', '') 55 | let funcs = split(sfile, '\.\.') 56 | if len(funcs) < abs(offset) 57 | return '' 58 | endif 59 | return matchstr(funcs[offset], '.*\ze\[\d\+\]$') 60 | endfunction 61 | 62 | " -------------------- 63 | " function 655_test3[1]..655_test2[1]..Debug_test 64 | " line 7: unlet i 65 | " function Debug_test(...) abort 66 | " Last set from ~/.cache/junkfile/2016/01/2016-01-17-111024.vim 67 | " 1 " hi 68 | " 2 "hoge foo 69 | " 3 let ho = 'ge' 70 | " 4 for i in range(3) 71 | " 5 echo i 72 | " 6 Debugger 73 | " ->7 unlet i 74 | " 8 endfor 75 | " 9 let foo = 'bar' 76 | " 10 return 77 | " endfunction 78 | function! s:show_current(funcname, slnum, sfile) abort 79 | call s:Message.echo('DebuggerSeparator', repeat('-', 20)) 80 | call s:Message.echo('DebuggerCallStack', a:sfile) 81 | if a:funcname is# '' 82 | let line = '' 83 | if filereadable(a:sfile) 84 | let line = get(readfile(a:sfile), a:slnum - 1, 'End of sourced file') 85 | endif 86 | call s:_show_current_line(a:slnum, line) 87 | return a:sfile 88 | endif 89 | let name = s:is_dict_func(a:funcname) ? printf('{%d}', a:funcname) : a:funcname 90 | let lines = split(s:redir(':verbose function ' . name), "\n") 91 | let line_nr_len = len(matchstr(lines[-2], '^\d\+')) 92 | let line_dict = s:_line_dict(lines[2:-2], line_nr_len) 93 | call s:_show_current_line(a:slnum, line_dict[a:slnum]) 94 | let text = [] 95 | call s:_function(lines[0], line_nr_len) 96 | call s:Message.echo('Comment', lines[1]) 97 | for line in lines[2:-2] 98 | let lnum = matchstr(line, '^\d\+') 99 | let ltext = line[line_nr_len + 1 :] 100 | if lnum ==# a:slnum 101 | call s:Message.echo('DebuggerCurrentLineMark', '->') 102 | else 103 | echo ' ' 104 | endif 105 | call s:Message.echon('LineNr', s:String.pad_left(lnum, line_nr_len)) 106 | echon ' ' 107 | call s:SyntaxEcho.echon(ltext) 108 | endfor 109 | call s:_endfunction(line_nr_len) 110 | return join(text, "\n") 111 | endfunction 112 | 113 | function! s:_line_dict(lines, line_nr_len) abort 114 | let d = {} 115 | for line in a:lines 116 | let lnum = matchstr(line, '^\d\+') 117 | let ltext = line[a:line_nr_len + 1 :] 118 | let d[lnum] = ltext 119 | endfor 120 | return d 121 | endfunction 122 | 123 | function! s:_function(line, line_nr_len) abort 124 | echo repeat(' ', a:line_nr_len + 3) 125 | call s:Message.echon('Statement', 'function ') 126 | let [funcname, arg, after] = split(a:line, '\s*function \|(\|)') 127 | call s:Message.echon('vimFunction', funcname) 128 | call s:Message.echon('Delimiter', '(') 129 | call s:Message.echon('vimOperParen', arg) 130 | call s:Message.echon('Delimiter', ')') 131 | call s:Message.echon('vimIsCommand', after) 132 | endfunction 133 | 134 | function! s:_endfunction(line_nr_len) abort 135 | echo repeat(' ', a:line_nr_len + 3) 136 | call s:Message.echon('Statement', 'endfunction') 137 | endfunction 138 | 139 | function! s:_show_current_line(lnum, text) abort 140 | echo 'line ' 141 | call s:Message.echon('Number', a:lnum) 142 | echon ': ' 143 | call s:SyntaxEcho.echon(a:text) 144 | endfunction 145 | 146 | function! s:last_set(funcname) abort 147 | let name = s:is_dict_func(a:funcname) ? printf('{%d}', a:funcname) : a:funcname 148 | " Last set from ~/.cache/junkfile/2016/01/2016-01-17-101852.vim 149 | return matchstr(split(s:redir(':verbose function ' . name), "\n")[1], '^\tLast set from \zs.*$') 150 | endfunction 151 | 152 | function! s:sfuncs(sid) abort 153 | return s:ScriptLocal.sid2sfuncs(a:sid) 154 | endfunction 155 | 156 | function! s:is_dict_func(funcname) abort 157 | return a:funcname =~# '^\d\+$' 158 | endfunction 159 | 160 | function! s:help() abort 161 | return PP({ 162 | \ '>cont': 163 | \ 'Continue execution until the next breakpoint is hit.', 164 | \ '>quit': 165 | \ "Abort execution. This is like using CTRL-C, some things might still be executed, doesn't abort everything. Still stops at the next breakpoint.", 166 | \ '>next': 167 | \ "Execute the command and come back to debug mode when it's finished. This steps over user function calls and sourced files.", 168 | \ '>step': 169 | \ 'Execute the command and come back to debug mode for the next command. This steps into called user functions and sourced files.', 170 | \ '>interrupt': 171 | \ 'This is like using CTRL-C, but unlike ">quit" comes back to debug mode for the next command that is executed. Useful for testing |:finally| and |:catch| on interrupt exceptions.', 172 | \ '>finish': 173 | \ 'Finish the current script or user function and come back to debug mode for the command after the one that sourced or called it.', 174 | \ }) 175 | endfunction 176 | 177 | function! s:redir(cmd) abort 178 | let [save_verbose, save_verbosefile] = [&verbose, &verbosefile] 179 | set verbose=0 verbosefile= 180 | redir => res 181 | silent! execute a:cmd 182 | redir END 183 | let [&verbose, &verbosefile] = [save_verbose, save_verbosefile] 184 | return res 185 | endfunction 186 | 187 | function! s:Message.echon(hl, msg) abort 188 | execute 'echohl' a:hl 189 | try 190 | echon a:msg 191 | finally 192 | echohl None 193 | endtry 194 | endfunction 195 | 196 | -------------------------------------------------------------------------------- /autoload/debugger/stacktrace.vim: -------------------------------------------------------------------------------- 1 | let s:V = vital#of('debugger') 2 | 3 | " v:throwpoint example 4 | " - function Test_gfunc[2]..366_test_sfunc[2]..781, line 3 5 | " - /home/haya14busa/.cache/junkfile/2016/01/2016-01-17-053123.vim, line 34 6 | " - function 786, line 3 7 | function! debugger#stacktrace#report(throwpoint) abort 8 | if a:throwpoint =~# '^\%(Error detected while processing \)\=function\s' 9 | let report = s:build_func_report(a:throwpoint) 10 | call s:create_buffer('==ErrorReport==.vim') 11 | call s:draw_report(report, ['" throwpoint: ' . a:throwpoint, '']) 12 | return report 13 | endif 14 | endfunction 15 | 16 | function! s:build_func2line(func_with_line_list) abort 17 | return map(copy(a:func_with_line_list), 's:parse_funcreport(v:val)') 18 | endfunction 19 | 20 | " @param {list<{'funcname': {string}, 'line': {number}}>} func2lines 21 | function! s:build_func_report(throwpoint) abort 22 | let throwpoint = substitute(a:throwpoint, '^\%(Error detected while processing \)\=function\s', '', '') 23 | let throwpoint = substitute(throwpoint, '\m\%(, \|:\s\+\)line\s\+\(\d\+\):\=$', '[\1]', '') 24 | let report = [] 25 | for func2line in s:build_func2line(split(throwpoint, '\m\.\.')) 26 | let report += [extend(copy(func2line), {'func': s:build_func(func2line.funcname)})] 27 | endfor 28 | return report 29 | endfunction 30 | 31 | function! s:build_func(funcname) abort 32 | let name = s:is_dict_func(a:funcname) ? printf('{%d}', a:funcname) : a:funcname 33 | if !exists('*' . name) 34 | throw 'function undefined: ' . name 35 | endif 36 | let funclines = split(s:redir(':verbose function ' . name), "\n") 37 | let last_set = funclines[1] 38 | call remove(funclines, 1) 39 | return {'lines': funclines, 'last_set': last_set} 40 | endfunction 41 | 42 | function! s:is_dict_func(funcname) abort 43 | return a:funcname =~# '^\d\+$' 44 | endfunction 45 | 46 | " @param {string} funcreport 47 | " {funcname}[{lnum}] 48 | function! s:parse_funcreport(funcreport) abort 49 | let matches = matchlist(a:funcreport, '\m^\(.\{-}\)\[\(\d\+\)\]') 50 | return { 51 | \ 'funcname': matches[1], 52 | \ 'line': str2nr(matches[2]) 53 | \ } 54 | endfunction 55 | 56 | function! s:create_buffer(name, ...) abort 57 | let open_cmd = get(a:, 1, 'belowright new') 58 | execute open_cmd printf("`='%s'`", a:name) 59 | 1,$ delete 60 | setlocal buftype=nowrite 61 | setlocal noswapfile 62 | setlocal bufhidden=wipe 63 | setlocal buftype=nofile 64 | setlocal nonumber 65 | setlocal filetype=vim 66 | endfunction 67 | 68 | " @param {list<{func: {lines: list, last_set: {string}}, funcname: {string}, line: {number}}>} report 69 | function! s:draw_report(report, ...) abort 70 | let head = get(a:, 1, []) 71 | let [lines, hl_lnums] = s:report_to_text(a:report, head) 72 | put! =lines 73 | :0 74 | syntax match Error containedin=ALL /^->\d\+/ 75 | redraw 76 | endfunction 77 | 78 | function! s:report_to_text(report, ...) abort 79 | let head = get(a:, 1, []) 80 | let lines = copy(head) 81 | let lnum = len(lines) + 1 82 | let hl_lnums = [] 83 | for funcreport in a:report 84 | let lines += ['" ' . funcreport.func.last_set] 85 | let hl_lnum_offset = 1 86 | for l in funcreport.func.lines 87 | let func_lnum = matchstr(l, '^\s*\zs\d\+\ze\s\s') 88 | let prefix = func_lnum ==# funcreport.line ? '->' : ' ' 89 | if func_lnum ==# funcreport.line 90 | let hl_lnums += [lnum + hl_lnum_offset] 91 | endif 92 | let lines += [prefix . l] 93 | let hl_lnum_offset += 1 94 | endfor 95 | let lines += [''] 96 | let lnum += len(funcreport.func.lines) + 2 97 | endfor 98 | return [lines, hl_lnums] 99 | endfunction 100 | 101 | function! s:redir(cmd) abort 102 | let [save_verbose, save_verbosefile] = [&verbose, &verbosefile] 103 | set verbose=0 verbosefile= 104 | redir => res 105 | silent! execute a:cmd 106 | redir END 107 | let [&verbose, &verbosefile] = [save_verbose, save_verbosefile] 108 | return res 109 | endfunction 110 | 111 | let s:reports = {} 112 | 113 | function! debugger#stacktrace#callstack(...) abort 114 | let id = get(a:, 1, '0') 115 | let id = id is# '' ? '0' : id 116 | let sfile = substitute(expand(''), '\m\.\.[^.]\{-}debugger#stacktrace#callstack$', '', '') 117 | let report = s:build_func_report(sfile) 118 | let s:reports[id] = report 119 | return report 120 | endfunction 121 | 122 | function! debugger#stacktrace#callstackreport(...) abort 123 | let id = get(a:, 1, '0') 124 | let id = id is# '' ? '0' : id 125 | let report = s:reports[id] 126 | call s:create_buffer(printf('==CallStack: %s==.vim', id)) 127 | call s:draw_report(report, ['" callstack: ' . id, '']) 128 | endfunction 129 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /autoload/vital/_debugger.vim: -------------------------------------------------------------------------------- 1 | let s:self_version = expand(':t:r') 2 | let s:self_file = expand('') 3 | 4 | " Note: The extra argument to globpath() was added in Patch 7.2.051. 5 | let s:globpath_third_arg = v:version > 702 || v:version == 702 && has('patch51') 6 | 7 | let s:loaded = {} 8 | let s:cache_module_path = {} 9 | let s:cache_sid = {} 10 | 11 | let s:_vital_files_cache_runtimepath = '' 12 | let s:_vital_files_cache = [] 13 | let s:_unify_path_cache = {} 14 | 15 | function! s:import(name, ...) abort 16 | let target = {} 17 | let functions = [] 18 | for a in a:000 19 | if type(a) == type({}) 20 | let target = a 21 | elseif type(a) == type([]) 22 | let functions = a 23 | endif 24 | unlet a 25 | endfor 26 | let module = s:_import(a:name) 27 | if empty(functions) 28 | call extend(target, module, 'keep') 29 | else 30 | for f in functions 31 | if has_key(module, f) && !has_key(target, f) 32 | let target[f] = module[f] 33 | endif 34 | endfor 35 | endif 36 | return target 37 | endfunction 38 | 39 | function! s:load(...) dict abort 40 | for arg in a:000 41 | let [name; as] = type(arg) == type([]) ? arg[: 1] : [arg, arg] 42 | let target = split(join(as, ''), '\W\+') 43 | let dict = self 44 | let dict_type = type({}) 45 | while !empty(target) 46 | let ns = remove(target, 0) 47 | if !has_key(dict, ns) 48 | let dict[ns] = {} 49 | endif 50 | if type(dict[ns]) == dict_type 51 | let dict = dict[ns] 52 | else 53 | unlet dict 54 | break 55 | endif 56 | endwhile 57 | 58 | if exists('dict') 59 | call extend(dict, s:_import(name)) 60 | endif 61 | unlet arg 62 | endfor 63 | return self 64 | endfunction 65 | 66 | function! s:unload() abort 67 | let s:loaded = {} 68 | let s:cache_sid = {} 69 | let s:cache_module_path = {} 70 | endfunction 71 | 72 | function! s:exists(name) abort 73 | return s:_get_module_path(a:name) !=# '' 74 | endfunction 75 | 76 | function! s:search(pattern) abort 77 | let paths = s:_vital_files(a:pattern) 78 | let modules = sort(map(paths, 's:_file2module(v:val)')) 79 | return s:_uniq(modules) 80 | endfunction 81 | 82 | function! s:expand_modules(entry, all) abort 83 | if type(a:entry) == type([]) 84 | let candidates = s:_concat(map(copy(a:entry), 's:search(v:val)')) 85 | if empty(candidates) 86 | throw printf('vital: Any of module %s is not found', string(a:entry)) 87 | endif 88 | if eval(join(map(copy(candidates), 'has_key(a:all, v:val)'), '+')) 89 | let modules = [] 90 | else 91 | let modules = [candidates[0]] 92 | endif 93 | else 94 | let modules = s:search(a:entry) 95 | if empty(modules) 96 | throw printf('vital: Module %s is not found', a:entry) 97 | endif 98 | endif 99 | call filter(modules, '!has_key(a:all, v:val)') 100 | for module in modules 101 | let a:all[module] = 1 102 | endfor 103 | return modules 104 | endfunction 105 | 106 | function! s:_import(name) abort 107 | if type(a:name) == type(0) 108 | return s:_build_module(a:name) 109 | endif 110 | let path = s:_get_module_path(a:name) 111 | if path ==# '' 112 | throw 'vital: module not found: ' . a:name 113 | endif 114 | let sid = s:_get_sid_by_script(path) 115 | if !sid 116 | try 117 | execute 'source' fnameescape(path) 118 | catch /^Vim\%((\a\+)\)\?:E484/ 119 | throw 'vital: module not found: ' . a:name 120 | catch /^Vim\%((\a\+)\)\?:E127/ 121 | " Ignore. 122 | endtry 123 | 124 | let sid = s:_get_sid_by_script(path) 125 | endif 126 | return s:_build_module(sid) 127 | endfunction 128 | 129 | function! s:_get_module_path(name) abort 130 | let key = a:name . '_' 131 | if has_key(s:cache_module_path, key) 132 | return s:cache_module_path[key] 133 | endif 134 | if s:_is_absolute_path(a:name) && filereadable(a:name) 135 | return a:name 136 | endif 137 | if a:name ==# '' 138 | let paths = [s:self_file] 139 | elseif a:name =~# '\v^\u\w*%(\.\u\w*)*$' 140 | let paths = s:_vital_files(a:name) 141 | else 142 | throw 'vital: Invalid module name: ' . a:name 143 | endif 144 | 145 | call filter(paths, 'filereadable(expand(v:val, 1))') 146 | let path = get(paths, 0, '') 147 | let s:cache_module_path[key] = path 148 | return path 149 | endfunction 150 | 151 | function! s:_get_sid_by_script(path) abort 152 | if has_key(s:cache_sid, a:path) 153 | return s:cache_sid[a:path] 154 | endif 155 | 156 | let path = s:_unify_path(a:path) 157 | for line in filter(split(s:_redir('scriptnames'), "\n"), 158 | \ 'stridx(v:val, s:self_version) > 0') 159 | let list = matchlist(line, '^\s*\(\d\+\):\s\+\(.\+\)\s*$') 160 | if !empty(list) && s:_unify_path(list[2]) ==# path 161 | let s:cache_sid[a:path] = list[1] - 0 162 | return s:cache_sid[a:path] 163 | endif 164 | endfor 165 | return 0 166 | endfunction 167 | 168 | function! s:_file2module(file) abort 169 | let filename = fnamemodify(a:file, ':p:gs?[\\/]?/?') 170 | let tail = matchstr(filename, 'autoload/vital/_\w\+/\zs.*\ze\.vim$') 171 | return join(split(tail, '[\\/]\+'), '.') 172 | endfunction 173 | 174 | if filereadable(expand(':r') . '.VIM') 175 | " resolve() is slow, so we cache results. 176 | " Note: On windows, vim can't expand path names from 8.3 formats. 177 | " So if getting full path via and $HOME was set as 8.3 format, 178 | " vital load duplicated scripts. Below's :~ avoid this issue. 179 | function! s:_unify_path(path) abort 180 | if has_key(s:_unify_path_cache, a:path) 181 | return s:_unify_path_cache[a:path] 182 | endif 183 | let value = tolower(fnamemodify(resolve(fnamemodify( 184 | \ a:path, ':p')), ':~:gs?[\\/]?/?')) 185 | let s:_unify_path_cache[a:path] = value 186 | return value 187 | endfunction 188 | else 189 | function! s:_unify_path(path) abort 190 | return resolve(fnamemodify(a:path, ':p:gs?[\\/]?/?')) 191 | endfunction 192 | endif 193 | 194 | if s:globpath_third_arg 195 | function! s:_runtime_files(path) abort 196 | return split(globpath(&runtimepath, a:path, 1), "\n") 197 | endfunction 198 | else 199 | function! s:_runtime_files(path) abort 200 | return split(globpath(&runtimepath, a:path), "\n") 201 | endfunction 202 | endif 203 | 204 | function! s:_vital_files(pattern) abort 205 | if s:_vital_files_cache_runtimepath !=# &runtimepath 206 | let path = printf('autoload/vital/%s/**/*.vim', s:self_version) 207 | let s:_vital_files_cache = s:_runtime_files(path) 208 | let mod = ':p:gs?[\\/]\+?/?' 209 | call map(s:_vital_files_cache, 'fnamemodify(v:val, mod)') 210 | let s:_vital_files_cache_runtimepath = &runtimepath 211 | endif 212 | let target = substitute(a:pattern, '\.', '/', 'g') 213 | let target = substitute(target, '\*', '[^/]*', 'g') 214 | let regexp = printf('autoload/vital/%s/%s.vim', s:self_version, target) 215 | return filter(copy(s:_vital_files_cache), 'v:val =~# regexp') 216 | endfunction 217 | 218 | " Copy from System.Filepath 219 | if has('win16') || has('win32') || has('win64') 220 | function! s:_is_absolute_path(path) abort 221 | return a:path =~? '^[a-z]:[/\\]' 222 | endfunction 223 | else 224 | function! s:_is_absolute_path(path) abort 225 | return a:path[0] ==# '/' 226 | endfunction 227 | endif 228 | 229 | function! s:_build_module(sid) abort 230 | if has_key(s:loaded, a:sid) 231 | return copy(s:loaded[a:sid]) 232 | endif 233 | let functions = s:_get_functions(a:sid) 234 | 235 | let prefix = '' . a:sid . '_' 236 | let module = {} 237 | for func in functions 238 | let module[func] = function(prefix . func) 239 | endfor 240 | if has_key(module, '_vital_created') 241 | call module._vital_created(module) 242 | endif 243 | let export_module = filter(copy(module), 'v:key =~# "^\\a"') 244 | let s:loaded[a:sid] = get(g:, 'vital_debug', 0) ? module : export_module 245 | if has_key(module, '_vital_loaded') 246 | let V = vital#{s:self_version}#new() 247 | call module._vital_loaded(V) 248 | endif 249 | return copy(s:loaded[a:sid]) 250 | endfunction 251 | 252 | if exists('+regexpengine') 253 | function! s:_get_functions(sid) abort 254 | let funcs = s:_redir(printf("function /\\%%#=2^\%d_", a:sid)) 255 | let map_pat = '' . a:sid . '_\zs\w\+' 256 | return map(split(funcs, "\n"), 'matchstr(v:val, map_pat)') 257 | endfunction 258 | else 259 | function! s:_get_functions(sid) abort 260 | let prefix = '' . a:sid . '_' 261 | let funcs = s:_redir('function') 262 | let filter_pat = '^\s*function ' . prefix 263 | let map_pat = prefix . '\zs\w\+' 264 | return map(filter(split(funcs, "\n"), 265 | \ 'stridx(v:val, prefix) > 0 && v:val =~# filter_pat'), 266 | \ 'matchstr(v:val, map_pat)') 267 | endfunction 268 | endif 269 | 270 | if exists('*uniq') 271 | function! s:_uniq(list) abort 272 | return uniq(a:list) 273 | endfunction 274 | else 275 | function! s:_uniq(list) abort 276 | let i = len(a:list) - 1 277 | while 0 < i 278 | if a:list[i] ==# a:list[i - 1] 279 | call remove(a:list, i) 280 | let i -= 2 281 | else 282 | let i -= 1 283 | endif 284 | endwhile 285 | return a:list 286 | endfunction 287 | endif 288 | 289 | function! s:_concat(lists) abort 290 | let result_list = [] 291 | for list in a:lists 292 | let result_list += list 293 | endfor 294 | return result_list 295 | endfunction 296 | 297 | function! s:_redir(cmd) abort 298 | let [save_verbose, save_verbosefile] = [&verbose, &verbosefile] 299 | set verbose=0 verbosefile= 300 | redir => res 301 | silent! execute a:cmd 302 | redir END 303 | let [&verbose, &verbosefile] = [save_verbose, save_verbosefile] 304 | return res 305 | endfunction 306 | 307 | function! vital#{s:self_version}#new() abort 308 | return s:_import('') 309 | endfunction 310 | -------------------------------------------------------------------------------- /autoload/vital/_debugger/Data/List.vim: -------------------------------------------------------------------------------- 1 | " Utilities for list. 2 | 3 | let s:save_cpo = &cpo 4 | set cpo&vim 5 | 6 | function! s:pop(list) abort 7 | return remove(a:list, -1) 8 | endfunction 9 | 10 | function! s:push(list, val) abort 11 | call add(a:list, a:val) 12 | return a:list 13 | endfunction 14 | 15 | function! s:shift(list) abort 16 | return remove(a:list, 0) 17 | endfunction 18 | 19 | function! s:unshift(list, val) abort 20 | return insert(a:list, a:val) 21 | endfunction 22 | 23 | function! s:cons(x, xs) abort 24 | return [a:x] + a:xs 25 | endfunction 26 | 27 | function! s:conj(xs, x) abort 28 | return a:xs + [a:x] 29 | endfunction 30 | 31 | " Removes duplicates from a list. 32 | function! s:uniq(list) abort 33 | return s:uniq_by(a:list, 'v:val') 34 | endfunction 35 | 36 | " Removes duplicates from a list. 37 | function! s:uniq_by(list, f) abort 38 | let list = map(copy(a:list), printf('[v:val, %s]', a:f)) 39 | let i = 0 40 | let seen = {} 41 | while i < len(list) 42 | let key = string(list[i][1]) 43 | if has_key(seen, key) 44 | call remove(list, i) 45 | else 46 | let seen[key] = 1 47 | let i += 1 48 | endif 49 | endwhile 50 | return map(list, 'v:val[0]') 51 | endfunction 52 | 53 | function! s:clear(list) abort 54 | if !empty(a:list) 55 | unlet! a:list[0 : len(a:list) - 1] 56 | endif 57 | return a:list 58 | endfunction 59 | 60 | " Concatenates a list of lists. 61 | " XXX: Should we verify the input? 62 | function! s:concat(list) abort 63 | let memo = [] 64 | for Value in a:list 65 | let memo += Value 66 | endfor 67 | return memo 68 | endfunction 69 | 70 | " Take each elements from lists to a new list. 71 | function! s:flatten(list, ...) abort 72 | let limit = a:0 > 0 ? a:1 : -1 73 | let memo = [] 74 | if limit == 0 75 | return a:list 76 | endif 77 | let limit -= 1 78 | for Value in a:list 79 | let memo += 80 | \ type(Value) == type([]) ? 81 | \ s:flatten(Value, limit) : 82 | \ [Value] 83 | unlet! Value 84 | endfor 85 | return memo 86 | endfunction 87 | 88 | " Sorts a list with expression to compare each two values. 89 | " a:a and a:b can be used in {expr}. 90 | function! s:sort(list, expr) abort 91 | if type(a:expr) == type(function('function')) 92 | return sort(a:list, a:expr) 93 | endif 94 | let s:expr = a:expr 95 | return sort(a:list, 's:_compare') 96 | endfunction 97 | 98 | function! s:_compare(a, b) abort 99 | return eval(s:expr) 100 | endfunction 101 | 102 | " Sorts a list using a set of keys generated by mapping the values in the list 103 | " through the given expr. 104 | " v:val is used in {expr} 105 | function! s:sort_by(list, expr) abort 106 | let pairs = map(a:list, printf('[v:val, %s]', a:expr)) 107 | return map(s:sort(pairs, 108 | \ 'a:a[1] ==# a:b[1] ? 0 : a:a[1] ># a:b[1] ? 1 : -1'), 'v:val[0]') 109 | endfunction 110 | 111 | " Returns a maximum value in {list} through given {expr}. 112 | " Returns 0 if {list} is empty. 113 | " v:val is used in {expr} 114 | function! s:max_by(list, expr) abort 115 | if empty(a:list) 116 | return 0 117 | endif 118 | let list = map(copy(a:list), a:expr) 119 | return a:list[index(list, max(list))] 120 | endfunction 121 | 122 | " Returns a minimum value in {list} through given {expr}. 123 | " Returns 0 if {list} is empty. 124 | " v:val is used in {expr} 125 | " FIXME: -0x80000000 == 0x80000000 126 | function! s:min_by(list, expr) abort 127 | return s:max_by(a:list, '-(' . a:expr . ')') 128 | endfunction 129 | 130 | " Returns List of character sequence between [a:from, a:to] 131 | " e.g.: s:char_range('a', 'c') returns ['a', 'b', 'c'] 132 | function! s:char_range(from, to) abort 133 | return map( 134 | \ range(char2nr(a:from), char2nr(a:to)), 135 | \ 'nr2char(v:val)' 136 | \) 137 | endfunction 138 | 139 | " Returns true if a:list has a:value. 140 | " Returns false otherwise. 141 | function! s:has(list, value) abort 142 | return index(a:list, a:value) isnot -1 143 | endfunction 144 | 145 | " Returns true if a:list[a:index] exists. 146 | " Returns false otherwise. 147 | " NOTE: Returns false when a:index is negative number. 148 | function! s:has_index(list, index) abort 149 | " Return true when negative index? 150 | " let index = a:index >= 0 ? a:index : len(a:list) + a:index 151 | return 0 <= a:index && a:index < len(a:list) 152 | endfunction 153 | 154 | " similar to Haskell's Data.List.span 155 | function! s:span(f, xs) abort 156 | let border = len(a:xs) 157 | for i in range(len(a:xs)) 158 | if !eval(substitute(a:f, 'v:val', string(a:xs[i]), 'g')) 159 | let border = i 160 | break 161 | endif 162 | endfor 163 | return border == 0 ? [[], copy(a:xs)] : [a:xs[: border - 1], a:xs[border :]] 164 | endfunction 165 | 166 | " similar to Haskell's Data.List.break 167 | function! s:break(f, xs) abort 168 | return s:span(printf('!(%s)', a:f), a:xs) 169 | endfunction 170 | 171 | " similar to Haskell's Data.List.takeWhile 172 | function! s:take_while(f, xs) abort 173 | return s:span(a:f, a:xs)[0] 174 | endfunction 175 | 176 | " similar to Haskell's Data.List.partition 177 | function! s:partition(f, xs) abort 178 | return [filter(copy(a:xs), a:f), filter(copy(a:xs), '!(' . a:f . ')')] 179 | endfunction 180 | 181 | " similar to Haskell's Prelude.all 182 | function! s:all(f, xs) abort 183 | return !s:any(printf('!(%s)', a:f), a:xs) 184 | endfunction 185 | 186 | " similar to Haskell's Prelude.any 187 | function! s:any(f, xs) abort 188 | return !empty(filter(map(copy(a:xs), a:f), 'v:val')) 189 | endfunction 190 | 191 | " similar to Haskell's Prelude.and 192 | function! s:and(xs) abort 193 | return s:all('v:val', a:xs) 194 | endfunction 195 | 196 | " similar to Haskell's Prelude.or 197 | function! s:or(xs) abort 198 | return s:any('v:val', a:xs) 199 | endfunction 200 | 201 | function! s:map_accum(expr, xs, init) abort 202 | let memo = [] 203 | let init = a:init 204 | for x in a:xs 205 | let expr = substitute(a:expr, 'v:memo', init, 'g') 206 | let expr = substitute(expr, 'v:val', x, 'g') 207 | let [tmp, init] = eval(expr) 208 | call add(memo, tmp) 209 | endfor 210 | return memo 211 | endfunction 212 | 213 | " similar to Haskell's Prelude.foldl 214 | function! s:foldl(f, init, xs) abort 215 | let memo = a:init 216 | for x in a:xs 217 | let expr = substitute(a:f, 'v:val', string(x), 'g') 218 | let expr = substitute(expr, 'v:memo', string(memo), 'g') 219 | unlet memo 220 | let memo = eval(expr) 221 | endfor 222 | return memo 223 | endfunction 224 | 225 | " similar to Haskell's Prelude.foldl1 226 | function! s:foldl1(f, xs) abort 227 | if len(a:xs) == 0 228 | throw 'vital: Data.List: foldl1' 229 | endif 230 | return s:foldl(a:f, a:xs[0], a:xs[1:]) 231 | endfunction 232 | 233 | " similar to Haskell's Prelude.foldr 234 | function! s:foldr(f, init, xs) abort 235 | return s:foldl(a:f, a:init, reverse(copy(a:xs))) 236 | endfunction 237 | 238 | " similar to Haskell's Prelude.fold11 239 | function! s:foldr1(f, xs) abort 240 | if len(a:xs) == 0 241 | throw 'vital: Data.List: foldr1' 242 | endif 243 | return s:foldr(a:f, a:xs[-1], a:xs[0:-2]) 244 | endfunction 245 | 246 | " similar to python's zip() 247 | function! s:zip(...) abort 248 | return map(range(min(map(copy(a:000), 'len(v:val)'))), "map(copy(a:000), 'v:val['.v:val.']')") 249 | endfunction 250 | 251 | " similar to zip(), but goes until the longer one. 252 | function! s:zip_fill(xs, ys, filler) abort 253 | if empty(a:xs) && empty(a:ys) 254 | return [] 255 | elseif empty(a:ys) 256 | return s:cons([a:xs[0], a:filler], s:zip_fill(a:xs[1 :], [], a:filler)) 257 | elseif empty(a:xs) 258 | return s:cons([a:filler, a:ys[0]], s:zip_fill([], a:ys[1 :], a:filler)) 259 | else 260 | return s:cons([a:xs[0], a:ys[0]], s:zip_fill(a:xs[1 :], a:ys[1: ], a:filler)) 261 | endif 262 | endfunction 263 | 264 | " Inspired by Ruby's with_index method. 265 | function! s:with_index(list, ...) abort 266 | let base = a:0 > 0 ? a:1 : 0 267 | return map(copy(a:list), '[v:val, v:key + base]') 268 | endfunction 269 | 270 | " similar to Ruby's detect or Haskell's find. 271 | function! s:find(list, default, f) abort 272 | for x in a:list 273 | if eval(substitute(a:f, 'v:val', string(x), 'g')) 274 | return x 275 | endif 276 | endfor 277 | return a:default 278 | endfunction 279 | 280 | " Returns the index of the first element which satisfies the given expr. 281 | function! s:find_index(xs, f, ...) abort 282 | let len = len(a:xs) 283 | let start = a:0 > 0 ? (a:1 < 0 ? len + a:1 : a:1) : 0 284 | let default = a:0 > 1 ? a:2 : -1 285 | if start >=# len || start < 0 286 | return default 287 | endif 288 | for i in range(start, len - 1) 289 | if eval(substitute(a:f, 'v:val', string(a:xs[i]), 'g')) 290 | return i 291 | endif 292 | endfor 293 | return default 294 | endfunction 295 | 296 | " Returns the index of the last element which satisfies the given expr. 297 | function! s:find_last_index(xs, f, ...) abort 298 | let len = len(a:xs) 299 | let start = a:0 > 0 ? (a:1 < 0 ? len + a:1 : a:1) : len - 1 300 | let default = a:0 > 1 ? a:2 : -1 301 | if start >=# len || start < 0 302 | return default 303 | endif 304 | for i in range(start, 0, -1) 305 | if eval(substitute(a:f, 'v:val', string(a:xs[i]), 'g')) 306 | return i 307 | endif 308 | endfor 309 | return default 310 | endfunction 311 | 312 | " Similar to find_index but returns the list of indices satisfying the given expr. 313 | function! s:find_indices(xs, f, ...) abort 314 | let len = len(a:xs) 315 | let start = a:0 > 0 ? (a:1 < 0 ? len + a:1 : a:1) : 0 316 | let result = [] 317 | if start >=# len || start < 0 318 | return result 319 | endif 320 | for i in range(start, len - 1) 321 | if eval(substitute(a:f, 'v:val', string(a:xs[i]), 'g')) 322 | call add(result, i) 323 | endif 324 | endfor 325 | return result 326 | endfunction 327 | 328 | " Return non-zero if a:list1 and a:list2 have any common item(s). 329 | " Return zero otherwise. 330 | function! s:has_common_items(list1, list2) abort 331 | return !empty(filter(copy(a:list1), 'index(a:list2, v:val) isnot -1')) 332 | endfunction 333 | 334 | function! s:intersect(list1, list2) abort 335 | let items = [] 336 | " for funcref 337 | for X in a:list1 338 | if index(a:list2, X) != -1 && index(items, X) == -1 339 | let items += [X] 340 | endif 341 | endfor 342 | return items 343 | endfunction 344 | 345 | " similar to Ruby's group_by. 346 | function! s:group_by(xs, f) abort 347 | let result = {} 348 | let list = map(copy(a:xs), printf('[v:val, %s]', a:f)) 349 | for x in list 350 | let Val = x[0] 351 | let key = type(x[1]) !=# type('') ? string(x[1]) : x[1] 352 | if has_key(result, key) 353 | call add(result[key], Val) 354 | else 355 | let result[key] = [Val] 356 | endif 357 | unlet Val 358 | endfor 359 | return result 360 | endfunction 361 | 362 | function! s:_default_compare(a, b) abort 363 | return a:a <# a:b ? -1 : a:a ># a:b ? 1 : 0 364 | endfunction 365 | 366 | function! s:binary_search(list, value, ...) abort 367 | let Predicate = a:0 >= 1 ? a:1 : 's:_default_compare' 368 | let dic = a:0 >= 2 ? a:2 : {} 369 | let start = 0 370 | let end = len(a:list) - 1 371 | 372 | while 1 373 | if start > end 374 | return -1 375 | endif 376 | 377 | let middle = (start + end) / 2 378 | 379 | let compared = call(Predicate, [a:value, a:list[middle]], dic) 380 | 381 | if compared < 0 382 | let end = middle - 1 383 | elseif compared > 0 384 | let start = middle + 1 385 | else 386 | return middle 387 | endif 388 | endwhile 389 | endfunction 390 | 391 | function! s:product(lists) abort 392 | let result = [[]] 393 | for pool in a:lists 394 | let tmp = [] 395 | for x in result 396 | let tmp += map(copy(pool), 'x + [v:val]') 397 | endfor 398 | let result = tmp 399 | endfor 400 | return result 401 | endfunction 402 | 403 | function! s:permutations(list, ...) abort 404 | if a:0 > 1 405 | throw 'vital: Data.List: too many arguments' 406 | endif 407 | let r = a:0 == 1 ? a:1 : len(a:list) 408 | if r > len(a:list) 409 | return [] 410 | elseif r < 0 411 | throw 'vital: Data.List: {r} must be non-negative integer' 412 | endif 413 | let n = len(a:list) 414 | let result = [] 415 | for indices in s:product(map(range(r), 'range(n)')) 416 | if len(s:uniq(indices)) == r 417 | call add(result, map(indices, 'a:list[v:val]')) 418 | endif 419 | endfor 420 | return result 421 | endfunction 422 | 423 | function! s:combinations(list, r) abort 424 | if a:r > len(a:list) 425 | return [] 426 | elseif a:r < 0 427 | throw 'vital: Data:List: {r} must be non-negative integer' 428 | endif 429 | let n = len(a:list) 430 | let result = [] 431 | for indices in s:permutations(range(n), a:r) 432 | if s:sort(copy(indices), 'a:a - a:b') == indices 433 | call add(result, map(indices, 'a:list[v:val]')) 434 | endif 435 | endfor 436 | return result 437 | endfunction 438 | 439 | let &cpo = s:save_cpo 440 | unlet s:save_cpo 441 | 442 | " vim:set et ts=2 sts=2 sw=2 tw=0: 443 | -------------------------------------------------------------------------------- /autoload/vital/_debugger/Data/Set.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | let s:TRUE = !0 5 | let s:FALSE = 0 6 | 7 | function! s:set(...) abort 8 | return call(s:set._new, a:000, s:set) 9 | endfunction 10 | 11 | function! s:frozenset(...) abort 12 | return call(s:frozenset._new, a:000, s:frozenset) 13 | endfunction 14 | 15 | function! s:_hash_func(x) abort 16 | return a:x 17 | endfunction 18 | 19 | let s:_base_set = { 20 | \ '_is_set' : s:TRUE, 21 | \ '_data' : {}, 22 | \ '_hash_func' : function('s:_hash_func') 23 | \ } 24 | 25 | function! s:_base_set._new(...) abort 26 | let obj = deepcopy(self) 27 | let xs = get(a:, 1, []) 28 | let obj._hash_func = get(a:, 2, obj._hash_func) 29 | call obj._set_data(xs) 30 | return obj 31 | endfunction 32 | 33 | "" Return the union of two sets as a new set. 34 | " (I.e. all elements that are in either set.) 35 | function! s:_base_set.union(t) abort 36 | let r = deepcopy(self) 37 | call r._update(a:t) 38 | return r 39 | endfunction 40 | let s:_base_set.or = s:_base_set.union 41 | 42 | "" Return the intersection of two sets as a new set. 43 | " (I.e. all elements that are in both sets.) 44 | function! s:_base_set.intersection(t) abort 45 | let t = self._to_set(a:t) 46 | let [little, big] = self.len() <= t.len() ? [self, t] : [t, self] 47 | return self._new(filter(copy(big.to_list()), 'little.in(v:val)')) 48 | endfunction 49 | let s:_base_set.and = s:_base_set.intersection 50 | 51 | "" Return the symmetric difference of two sets as a new set. 52 | " (I.e. all elements that are in exactly one of the sets.) 53 | function! s:_base_set.symmetric_difference(t) abort 54 | let t = self._to_set(a:t) 55 | return self._new(filter(copy(self.to_list()), '!t.in(v:val)') 56 | \ + filter(copy(t.to_list()), '!self.in(v:val)')) 57 | endfunction 58 | let s:_base_set.xor = s:_base_set.symmetric_difference 59 | 60 | "" Return the difference of two sets as a new Set. 61 | function! s:_base_set.difference(t) abort 62 | let t = self._to_set(a:t) 63 | return self._new(filter(copy(self.to_list()), '!t.in(v:val)')) 64 | endfunction 65 | let s:_base_set.sub = s:_base_set.difference 66 | 67 | "" Report whether another set contains this set. 68 | function! s:_base_set.issubset(t) abort 69 | let t = self._to_set(a:t) 70 | return self.len() > t.len() ? s:FALSE 71 | \ : empty(filter(copy(self.to_list()), '!t.in(v:val)')) 72 | endfunction 73 | 74 | "" Report whether this set contains another set. 75 | function! s:_base_set.issuperset(t) abort 76 | let t = self._to_set(a:t) 77 | return self.len() < t.len() ? s:FALSE 78 | \ : empty(filter(copy(t.to_list()), '!self.in(v:val)')) 79 | endfunction 80 | 81 | " less than equal & greater than equal 82 | let s:_base_set.le = s:_base_set.issubset 83 | let s:_base_set.ge = s:_base_set.issuperset 84 | 85 | " less than 86 | function! s:_base_set.lt(t) abort 87 | let t = self._to_set(a:t) 88 | return self.len() < t.len() && self.issubset(t) 89 | endfunction 90 | 91 | " greater than 92 | function! s:_base_set.gt(t) abort 93 | let t = self._to_set(a:t) 94 | return self.len() > t.len() && self.issuperset(t) 95 | endfunction 96 | 97 | function! s:_base_set.len() abort 98 | return len(self._data) 99 | endfunction 100 | 101 | function! s:_base_set.to_list() abort 102 | return values(self._data) 103 | endfunction 104 | 105 | function! s:_base_set._update(xs) abort 106 | for X in (s:_is_set(a:xs) ? a:xs.to_list() : a:xs) 107 | call self._add(X) 108 | unlet X 109 | endfor 110 | endfunction 111 | 112 | function! s:_base_set._add(x) abort 113 | let key = self._hash(a:x) 114 | if !has_key(self._data, key) 115 | let self._data[key] = a:x 116 | endif 117 | endfunction 118 | 119 | " Report whether an element is a member of a set. 120 | function! s:_base_set.in(x) abort 121 | return has_key(self._data, self._hash(a:x)) 122 | endfunction 123 | 124 | function! s:_base_set._to_set(x) abort 125 | return s:_is_set(a:x) ? a:x : self._new(a:x) 126 | endfunction 127 | 128 | function! s:_base_set._clear() abort 129 | let self._data = {} 130 | endfunction 131 | 132 | function! s:_base_set._set_data(xs) abort 133 | call self._clear() 134 | call self._update(a:xs) 135 | endfunction 136 | 137 | function! s:_base_set._hash(x) abort 138 | return string(self._hash_func(a:x)) 139 | endfunction 140 | 141 | " frozenset: Immutable set class. 142 | 143 | let s:frozenset = deepcopy(s:_base_set) 144 | 145 | " Set: Mutable set class. 146 | 147 | let s:set = deepcopy(s:_base_set) 148 | 149 | " Update a set with the union of itself and another. 150 | function! s:set.update(iterable) abort 151 | call self._update(a:iterable) 152 | endfunction 153 | 154 | " Update a set with the union of itself and another. 155 | function! s:set.ior(t) abort 156 | call self.update(a:t) 157 | return self 158 | endfunction 159 | 160 | " Update a set with the intersection of itself and another. 161 | function! s:set.intersection_update(t) abort 162 | let r = self.and(a:t).to_list() 163 | call self.clear() 164 | call self.update(r) 165 | endfunction 166 | 167 | " Update a set with the intersection of itself and another. 168 | function! s:set.iand(t) abort 169 | call self.intersection_update(a:t) 170 | return self 171 | endfunction 172 | 173 | " Update a set with the symmetric difference of itself and another. 174 | function! s:set.symmetric_difference_update(t) abort 175 | let t = self._to_set(a:t) 176 | if self is t 177 | call self.clear() 178 | return 179 | endif 180 | for X in t.to_list() 181 | if self.in(X) 182 | call self.remove(X) 183 | else 184 | call self._add(X) 185 | endif 186 | unlet X 187 | endfor 188 | endfunction 189 | 190 | " Update a set with the symmetric difference of itself and another. 191 | function! s:set.ixor(t) abort 192 | call self.symmetric_difference_update(a:t) 193 | return self 194 | endfunction 195 | 196 | " Remove all elements of another set from this set. 197 | function! s:set.difference_update(t) abort 198 | let t = self._to_set(a:t) 199 | if self is t 200 | call self.clear() 201 | return 202 | endif 203 | for X in filter(t.to_list(), 'self.in(v:val)') 204 | call self.remove(X) 205 | unlet X 206 | endfor 207 | endfunction 208 | 209 | " Remove all elements of another set from this set. 210 | function! s:set.isub(t) abort 211 | call self.difference_update(a:t) 212 | return self 213 | endfunction 214 | 215 | " Remove all elements from this set. 216 | function! s:set.clear() abort 217 | call self._clear() 218 | endfunction 219 | 220 | "" Add an element to a set. 221 | " This has no effect if the element is already present. 222 | function! s:set.add(x) abort 223 | return self._add(a:x) 224 | endfunction 225 | 226 | "" Remove an element from a set; it must be a member. 227 | " If the element is not a member, throw Exception. 228 | function! s:set.remove(e) abort 229 | try 230 | unlet self._data[self._hash(a:e)] 231 | catch /^Vim\%((\a\+)\)\?:E716/ 232 | call s:_throw('the element is not a member') 233 | endtry 234 | endfunction 235 | 236 | "" Remove an element from a set if it is a member. 237 | " If the element is not a member, do nothing. 238 | function! s:set.discard(e) abort 239 | try 240 | call self.remove(a:e) 241 | catch /vital: Data.Set: the element is not a member/ 242 | " Do nothing 243 | endtry 244 | endfunction 245 | 246 | " Remove and return an arbitrary set element. 247 | function! s:set.pop() abort 248 | try 249 | let k = keys(self._data)[0] 250 | catch /^Vim\%((\a\+)\)\?:E684/ 251 | call s:_throw('set is empty') 252 | endtry 253 | let v = self._data[k] 254 | unlet self._data[k] 255 | return v 256 | endfunction 257 | 258 | " Helper: 259 | 260 | function! s:_is_set(x) abort 261 | return type(a:x) is type({}) && get(a:x, '_is_set', s:FALSE) 262 | endfunction 263 | 264 | function! s:_throw(message) abort 265 | throw 'vital: Data.Set: ' . a:message 266 | endfunction 267 | 268 | let &cpo = s:save_cpo 269 | unlet s:save_cpo 270 | -------------------------------------------------------------------------------- /autoload/vital/_debugger/Data/String.vim: -------------------------------------------------------------------------------- 1 | " Utilities for string. 2 | 3 | let s:save_cpo = &cpo 4 | set cpo&vim 5 | 6 | function! s:_vital_loaded(V) abort 7 | let s:V = a:V 8 | let s:P = s:V.import('Prelude') 9 | let s:L = s:V.import('Data.List') 10 | endfunction 11 | 12 | function! s:_vital_depends() abort 13 | return ['Prelude', 'Data.List'] 14 | endfunction 15 | 16 | " Substitute a:from => a:to by string. 17 | " To substitute by pattern, use substitute() instead. 18 | function! s:replace(str, from, to) abort 19 | return s:_replace(a:str, a:from, a:to, 'g') 20 | endfunction 21 | 22 | " Substitute a:from => a:to only once. 23 | " cf. s:replace() 24 | function! s:replace_first(str, from, to) abort 25 | return s:_replace(a:str, a:from, a:to, '') 26 | endfunction 27 | 28 | " implement of replace() and replace_first() 29 | function! s:_replace(str, from, to, flags) abort 30 | return substitute(a:str, '\V'.escape(a:from, '\'), escape(a:to, '\'), a:flags) 31 | endfunction 32 | 33 | function! s:scan(str, pattern) abort 34 | let list = [] 35 | call substitute(a:str, a:pattern, '\=add(list, submatch(0)) == [] ? "" : ""', 'g') 36 | return list 37 | endfunction 38 | 39 | function! s:reverse(str) abort 40 | return join(reverse(split(a:str, '.\zs')), '') 41 | endfunction 42 | 43 | function! s:starts_with(str, prefix) abort 44 | return stridx(a:str, a:prefix) == 0 45 | endfunction 46 | 47 | function! s:ends_with(str, suffix) abort 48 | let idx = strridx(a:str, a:suffix) 49 | return 0 <= idx && idx + len(a:suffix) == len(a:str) 50 | endfunction 51 | 52 | function! s:common_head(strs) abort 53 | if empty(a:strs) 54 | return '' 55 | endif 56 | let len = len(a:strs) 57 | if len == 1 58 | return a:strs[0] 59 | endif 60 | let strs = len == 2 ? a:strs : sort(copy(a:strs)) 61 | let pat = substitute(strs[0], '.', '\="[" . escape(submatch(0), "^\\") . "]"', 'g') 62 | return pat ==# '' ? '' : matchstr(strs[-1], '\C^\%[' . pat . ']') 63 | endfunction 64 | 65 | " Split to two elements of List. ([left, right]) 66 | " e.g.: s:split3('neocomplcache', 'compl') returns ['neo', 'compl', 'cache'] 67 | function! s:split_leftright(expr, pattern) abort 68 | let [left, _, right] = s:split3(a:expr, a:pattern) 69 | return [left, right] 70 | endfunction 71 | 72 | function! s:split3(expr, pattern) abort 73 | let ERROR = ['', '', ''] 74 | if a:expr ==# '' || a:pattern ==# '' 75 | return ERROR 76 | endif 77 | let begin = match(a:expr, a:pattern) 78 | if begin is -1 79 | return ERROR 80 | endif 81 | let end = matchend(a:expr, a:pattern) 82 | let left = begin <=# 0 ? '' : a:expr[: begin - 1] 83 | let right = a:expr[end :] 84 | return [left, a:expr[begin : end-1], right] 85 | endfunction 86 | 87 | " Slices into strings determines the number of substrings. 88 | " e.g.: s:nsplit("neo compl cache", 2, '\s') returns ['neo', 'compl cache'] 89 | function! s:nsplit(expr, n, ...) abort 90 | let pattern = get(a:000, 0, '\s') 91 | let keepempty = get(a:000, 1, 1) 92 | let ret = [] 93 | let expr = a:expr 94 | if a:n <= 1 95 | return [expr] 96 | endif 97 | while 1 98 | let pos = match(expr, pattern) 99 | if pos == -1 100 | if expr !~ pattern || keepempty 101 | call add(ret, expr) 102 | endif 103 | break 104 | elseif pos >= 0 105 | let left = pos > 0 ? expr[:pos-1] : '' 106 | if pos > 0 || keepempty 107 | call add(ret, left) 108 | endif 109 | let ml = len(matchstr(expr, pattern)) 110 | if pos == 0 && ml == 0 111 | let pos = 1 112 | endif 113 | let expr = expr[pos+ml :] 114 | endif 115 | if len(expr) == 0 116 | break 117 | endif 118 | if len(ret) == a:n - 1 119 | call add(ret, expr) 120 | break 121 | endif 122 | endwhile 123 | return ret 124 | endfunction 125 | 126 | " Returns the number of character in a:str. 127 | " NOTE: This returns proper value 128 | " even if a:str contains multibyte character(s). 129 | " s:strchars(str) {{{ 130 | if exists('*strchars') 131 | function! s:strchars(str) abort 132 | return strchars(a:str) 133 | endfunction 134 | else 135 | function! s:strchars(str) abort 136 | return strlen(substitute(copy(a:str), '.', 'x', 'g')) 137 | endfunction 138 | endif "}}} 139 | 140 | " Returns the bool of contains any multibyte character in s:str 141 | function! s:contains_multibyte(str) abort "{{{ 142 | return strlen(a:str) != s:strchars(a:str) 143 | endfunction "}}} 144 | 145 | " Remove last character from a:str. 146 | " NOTE: This returns proper value 147 | " even if a:str contains multibyte character(s). 148 | function! s:chop(str) abort "{{{ 149 | return substitute(a:str, '.$', '', '') 150 | endfunction "}}} 151 | 152 | " Remove last \r,\n,\r\n from a:str. 153 | function! s:chomp(str) abort "{{{ 154 | return substitute(a:str, '\%(\r\n\|[\r\n]\)$', '', '') 155 | endfunction "}}} 156 | 157 | " wrap() and its internal functions 158 | " * _split_by_wcswidth_once() 159 | " * _split_by_wcswidth() 160 | " * _concat() 161 | " * wrap() 162 | " 163 | " NOTE _concat() is just a copy of Data.List.concat(). 164 | " FIXME don't repeat yourself 165 | function! s:_split_by_wcswidth_once(body, x) abort 166 | let fst = s:strwidthpart(a:body, a:x) 167 | let snd = s:strwidthpart_reverse(a:body, s:wcswidth(a:body) - s:wcswidth(fst)) 168 | return [fst, snd] 169 | endfunction 170 | 171 | function! s:_split_by_wcswidth(body, x) abort 172 | let memo = [] 173 | let body = a:body 174 | while s:wcswidth(body) > a:x 175 | let [tmp, body] = s:_split_by_wcswidth_once(body, a:x) 176 | call add(memo, tmp) 177 | endwhile 178 | call add(memo, body) 179 | return memo 180 | endfunction 181 | 182 | function! s:trim(str) abort 183 | return matchstr(a:str,'^\s*\zs.\{-}\ze\s*$') 184 | endfunction 185 | 186 | function! s:trim_start(str) abort 187 | return matchstr(a:str,'^\s*\zs.\{-}$') 188 | endfunction 189 | 190 | function! s:trim_end(str) abort 191 | return matchstr(a:str,'^.\{-}\ze\s*$') 192 | endfunction 193 | 194 | function! s:wrap(str,...) abort 195 | let _columns = a:0 > 0 ? a:1 : &columns 196 | return s:L.concat( 197 | \ map(split(a:str, '\r\n\|[\r\n]'), 's:_split_by_wcswidth(v:val, _columns - 1)')) 198 | endfunction 199 | 200 | function! s:nr2byte(nr) abort 201 | if a:nr < 0x80 202 | return nr2char(a:nr) 203 | elseif a:nr < 0x800 204 | return nr2char(a:nr/64+192).nr2char(a:nr%64+128) 205 | else 206 | return nr2char(a:nr/4096%16+224).nr2char(a:nr/64%64+128).nr2char(a:nr%64+128) 207 | endif 208 | endfunction 209 | 210 | function! s:nr2enc_char(charcode) abort 211 | if &encoding ==# 'utf-8' 212 | return nr2char(a:charcode) 213 | endif 214 | let char = s:nr2byte(a:charcode) 215 | if strlen(char) > 1 216 | let char = strtrans(iconv(char, 'utf-8', &encoding)) 217 | endif 218 | return char 219 | endfunction 220 | 221 | function! s:nr2hex(nr) abort 222 | let n = a:nr 223 | let r = '' 224 | while n 225 | let r = '0123456789ABCDEF'[n % 16] . r 226 | let n = n / 16 227 | endwhile 228 | return r 229 | endfunction 230 | 231 | " If a ==# b, returns -1. 232 | " If a !=# b, returns first index of different character. 233 | function! s:diffidx(a, b) abort 234 | return a:a ==# a:b ? -1 : strlen(s:common_head([a:a, a:b])) 235 | endfunction 236 | 237 | function! s:substitute_last(expr, pat, sub) abort 238 | return substitute(a:expr, printf('.*\zs%s', a:pat), a:sub, '') 239 | endfunction 240 | 241 | function! s:dstring(expr) abort 242 | let x = substitute(string(a:expr), "^'\\|'$", '', 'g') 243 | let x = substitute(x, "''", "'", 'g') 244 | return printf('"%s"', escape(x, '"')) 245 | endfunction 246 | 247 | function! s:lines(str) abort 248 | return split(a:str, '\r\?\n') 249 | endfunction 250 | 251 | function! s:_pad_with_char(str, left, right, char) abort 252 | return repeat(a:char, a:left). a:str. repeat(a:char, a:right) 253 | endfunction 254 | 255 | function! s:pad_left(str, width, ...) abort 256 | let char = get(a:, 1, ' ') 257 | if strdisplaywidth(char) != 1 258 | throw "vital: Data.String: Can't use non-half-width characters for padding." 259 | endif 260 | let left = max([0, a:width - strdisplaywidth(a:str)]) 261 | return s:_pad_with_char(a:str, left, 0, char) 262 | endfunction 263 | 264 | function! s:pad_right(str, width, ...) abort 265 | let char = get(a:, 1, ' ') 266 | if strdisplaywidth(char) != 1 267 | throw "vital: Data.String: Can't use non-half-width characters for padding." 268 | endif 269 | let right = max([0, a:width - strdisplaywidth(a:str)]) 270 | return s:_pad_with_char(a:str, 0, right, char) 271 | endfunction 272 | 273 | function! s:pad_both_sides(str, width, ...) abort 274 | let char = get(a:, 1, ' ') 275 | if strdisplaywidth(char) != 1 276 | throw "vital: Data.String: Can't use non-half-width characters for padding." 277 | endif 278 | let space = max([0, a:width - strdisplaywidth(a:str)]) 279 | let left = space / 2 280 | let right = space - left 281 | return s:_pad_with_char(a:str, left, right, char) 282 | endfunction 283 | 284 | function! s:pad_between_letters(str, width, ...) abort 285 | let char = get(a:, 1, ' ') 286 | if strdisplaywidth(char) != 1 287 | throw "vital: Data.String: Can't use non-half-width characters for padding." 288 | endif 289 | let letters = split(a:str, '\zs') 290 | let each_width = a:width / len(letters) 291 | let str = join(map(letters, 's:pad_both_sides(v:val, each_width, char)'), '') 292 | if a:width - strdisplaywidth(str) > 0 293 | return char. s:pad_both_sides(str, a:width - 1, char) 294 | endif 295 | return str 296 | endfunction 297 | 298 | function! s:justify_equal_spacing(str, width, ...) abort 299 | let char = get(a:, 1, ' ') 300 | if strdisplaywidth(char) != 1 301 | throw "vital: Data.String: Can't use non-half-width characters for padding." 302 | endif 303 | let letters = split(a:str, '\zs') 304 | let first_letter = letters[0] 305 | " {width w/o the first letter} / {length w/o the first letter} 306 | let each_width = (a:width - strdisplaywidth(first_letter)) / (len(letters) - 1) 307 | let remainder = (a:width - strdisplaywidth(first_letter)) % (len(letters) - 1) 308 | return first_letter. join(s:L.concat([ 309 | \ map(letters[1:remainder], 's:pad_left(v:val, each_width + 1, char)'), 310 | \ map(letters[remainder + 1:], 's:pad_left(v:val, each_width, char)') 311 | \ ]), '') 312 | endfunction 313 | 314 | function! s:levenshtein_distance(str1, str2) abort 315 | let letters1 = split(a:str1, '\zs') 316 | let letters2 = split(a:str2, '\zs') 317 | let length1 = len(letters1) 318 | let length2 = len(letters2) 319 | let distances = map(range(1, length1 + 1), 'map(range(1, length2 + 1), "0")') 320 | 321 | for i1 in range(0, length1) 322 | let distances[i1][0] = i1 323 | endfor 324 | for i2 in range(0, length2) 325 | let distances[0][i2] = i2 326 | endfor 327 | 328 | for i1 in range(1, length1) 329 | for i2 in range(1, length2) 330 | let cost = (letters1[i1 - 1] ==# letters2[i2 - 1]) ? 0 : 1 331 | 332 | let distances[i1][i2] = min([ 333 | \ distances[i1 - 1][i2 ] + 1, 334 | \ distances[i1 ][i2 - 1] + 1, 335 | \ distances[i1 - 1][i2 - 1] + cost, 336 | \]) 337 | endfor 338 | endfor 339 | 340 | return distances[length1][length2] 341 | endfunction 342 | 343 | function! s:padding_by_displaywidth(expr, width, float) abort 344 | let padding_char = ' ' 345 | let n = a:width - strdisplaywidth(a:expr) 346 | if n <= 0 347 | let n = 0 348 | endif 349 | if a:float < 0 350 | return a:expr . repeat(padding_char, n) 351 | elseif 0 < a:float 352 | return repeat(padding_char, n) . a:expr 353 | else 354 | if n % 2 is 0 355 | return repeat(padding_char, n / 2) . a:expr . repeat(padding_char, n / 2) 356 | else 357 | return repeat(padding_char, (n - 1) / 2) . a:expr . repeat(padding_char, (n - 1) / 2) . padding_char 358 | endif 359 | endif 360 | endfunction 361 | 362 | function! s:split_by_displaywidth(expr, width, float, is_wrap) abort 363 | if a:width is 0 364 | return [''] 365 | endif 366 | 367 | let lines = [] 368 | 369 | let cs = split(a:expr, '\zs') 370 | let cs_index = 0 371 | 372 | let text = '' 373 | while cs_index < len(cs) 374 | if cs[cs_index] is# "\n" 375 | let text = s:padding_by_displaywidth(text, a:width, a:float) 376 | let lines += [text] 377 | let text = '' 378 | else 379 | let w = strdisplaywidth(text . cs[cs_index]) 380 | 381 | if w < a:width 382 | let text .= cs[cs_index] 383 | elseif a:width < w 384 | let text = s:padding_by_displaywidth(text, a:width, a:float) 385 | else 386 | let text .= cs[cs_index] 387 | endif 388 | 389 | if a:width <= w 390 | let lines += [text] 391 | let text = '' 392 | if a:is_wrap 393 | if a:width < w 394 | if a:width < strdisplaywidth(cs[cs_index]) 395 | while get(cs, cs_index, "\n") isnot# "\n" 396 | let cs_index += 1 397 | endwhile 398 | continue 399 | else 400 | let text = cs[cs_index] 401 | endif 402 | endif 403 | else 404 | while get(cs, cs_index, "\n") isnot# "\n" 405 | let cs_index += 1 406 | endwhile 407 | continue 408 | endif 409 | endif 410 | 411 | endif 412 | let cs_index += 1 413 | endwhile 414 | 415 | if !empty(text) 416 | let lines += [ s:padding_by_displaywidth(text, a:width, a:float) ] 417 | endif 418 | 419 | return lines 420 | endfunction 421 | 422 | function! s:hash(str) abort 423 | if exists('*sha256') 424 | return sha256(a:str) 425 | else 426 | " This gives up sha256ing but just adds up char with index. 427 | let sum = 0 428 | for i in range(len(a:str)) 429 | let sum += char2nr(a:str[i]) * (i + 1) 430 | endfor 431 | 432 | return printf('%x', sum) 433 | endif 434 | endfunction 435 | 436 | function! s:truncate(str, width) abort 437 | " Original function is from mattn. 438 | " http://github.com/mattn/googlereader-vim/tree/master 439 | 440 | if a:str =~# '^[\x00-\x7f]*$' 441 | return len(a:str) < a:width ? 442 | \ printf('%-'.a:width.'s', a:str) : strpart(a:str, 0, a:width) 443 | endif 444 | 445 | let ret = a:str 446 | let width = s:wcswidth(a:str) 447 | if width > a:width 448 | let ret = s:strwidthpart(ret, a:width) 449 | let width = s:wcswidth(ret) 450 | endif 451 | 452 | if width < a:width 453 | let ret .= repeat(' ', a:width - width) 454 | endif 455 | 456 | return ret 457 | endfunction 458 | 459 | function! s:truncate_skipping(str, max, footer_width, separator) abort 460 | let width = s:wcswidth(a:str) 461 | if width <= a:max 462 | let ret = a:str 463 | else 464 | let header_width = a:max - s:wcswidth(a:separator) - a:footer_width 465 | let ret = s:strwidthpart(a:str, header_width) . a:separator 466 | \ . s:strwidthpart_reverse(a:str, a:footer_width) 467 | endif 468 | return s:truncate(ret, a:max) 469 | endfunction 470 | 471 | function! s:strwidthpart(str, width) abort 472 | if a:width <= 0 473 | return '' 474 | endif 475 | let strarr = split(a:str, '\zs') 476 | let width = s:wcswidth(a:str) 477 | let index = len(strarr) 478 | let diff = (index + 1) / 2 479 | let rightindex = index - 1 480 | while width > a:width 481 | let index = max([rightindex - diff + 1, 0]) 482 | let partwidth = s:wcswidth(join(strarr[(index):(rightindex)], '')) 483 | if width - partwidth >= a:width || diff <= 1 484 | let width -= partwidth 485 | let rightindex = index - 1 486 | endif 487 | if diff > 1 488 | let diff = diff / 2 489 | endif 490 | endwhile 491 | return index ? join(strarr[:index - 1], '') : '' 492 | endfunction 493 | 494 | function! s:strwidthpart_reverse(str, width) abort 495 | if a:width <= 0 496 | return '' 497 | endif 498 | let strarr = split(a:str, '\zs') 499 | let width = s:wcswidth(a:str) 500 | let strlen = len(strarr) 501 | let diff = (strlen + 1) / 2 502 | let leftindex = 0 503 | let index = -1 504 | while width > a:width 505 | let index = min([leftindex + diff, strlen]) - 1 506 | let partwidth = s:wcswidth(join(strarr[(leftindex):(index)], '')) 507 | if width - partwidth >= a:width || diff <= 1 508 | let width -= partwidth 509 | let leftindex = index + 1 510 | endif 511 | if diff > 1 512 | let diff = diff / 2 513 | endif 514 | endwhile 515 | return index < strlen ? join(strarr[(index + 1):], '') : '' 516 | endfunction 517 | 518 | if v:version >= 703 519 | " Use builtin function. 520 | function! s:wcswidth(str) abort 521 | return strwidth(a:str) 522 | endfunction 523 | else 524 | function! s:wcswidth(str) abort 525 | if a:str =~# '^[\x00-\x7f]*$' 526 | return strlen(a:str) 527 | endif 528 | let mx_first = '^\(.\)' 529 | let str = a:str 530 | let width = 0 531 | while 1 532 | let ucs = char2nr(substitute(str, mx_first, '\1', '')) 533 | if ucs == 0 534 | break 535 | endif 536 | let width += s:_wcwidth(ucs) 537 | let str = substitute(str, mx_first, '', '') 538 | endwhile 539 | return width 540 | endfunction 541 | 542 | " UTF-8 only. 543 | function! s:_wcwidth(ucs) abort 544 | let ucs = a:ucs 545 | if (ucs >= 0x1100 546 | \ && (ucs <= 0x115f 547 | \ || ucs == 0x2329 548 | \ || ucs == 0x232a 549 | \ || (ucs >= 0x2e80 && ucs <= 0xa4cf 550 | \ && ucs != 0x303f) 551 | \ || (ucs >= 0xac00 && ucs <= 0xd7a3) 552 | \ || (ucs >= 0xf900 && ucs <= 0xfaff) 553 | \ || (ucs >= 0xfe30 && ucs <= 0xfe6f) 554 | \ || (ucs >= 0xff00 && ucs <= 0xff60) 555 | \ || (ucs >= 0xffe0 && ucs <= 0xffe6) 556 | \ || (ucs >= 0x20000 && ucs <= 0x2fffd) 557 | \ || (ucs >= 0x30000 && ucs <= 0x3fffd) 558 | \ )) 559 | return 2 560 | endif 561 | return 1 562 | endfunction 563 | endif 564 | 565 | let &cpo = s:save_cpo 566 | unlet s:save_cpo 567 | 568 | " vim:set et ts=2 sts=2 sw=2 tw=0: 569 | -------------------------------------------------------------------------------- /autoload/vital/_debugger/Prelude.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | if v:version ># 703 || 5 | \ (v:version is 703 && has('patch465')) 6 | function! s:glob(expr) abort 7 | return glob(a:expr, 1, 1) 8 | endfunction 9 | else 10 | function! s:glob(expr) abort 11 | let R = glob(a:expr, 1) 12 | return split(R, '\n') 13 | endfunction 14 | endif 15 | 16 | function! s:globpath(path, expr) abort 17 | let R = globpath(a:path, a:expr, 1) 18 | return split(R, '\n') 19 | endfunction 20 | 21 | " Wrapper functions for type(). 22 | let [ 23 | \ s:__TYPE_NUMBER, 24 | \ s:__TYPE_STRING, 25 | \ s:__TYPE_FUNCREF, 26 | \ s:__TYPE_LIST, 27 | \ s:__TYPE_DICT, 28 | \ s:__TYPE_FLOAT] = [ 29 | \ type(3), 30 | \ type(''), 31 | \ type(function('tr')), 32 | \ type([]), 33 | \ type({}), 34 | \ has('float') ? type(str2float('0')) : -1] 35 | " __TYPE_FLOAT = -1 when -float 36 | " This doesn't match to anything. 37 | 38 | " Number or Float 39 | function! s:is_numeric(Value) abort 40 | let _ = type(a:Value) 41 | return _ ==# s:__TYPE_NUMBER 42 | \ || _ ==# s:__TYPE_FLOAT 43 | endfunction 44 | 45 | " Number 46 | function! s:is_number(Value) abort 47 | return type(a:Value) ==# s:__TYPE_NUMBER 48 | endfunction 49 | 50 | " Float 51 | function! s:is_float(Value) abort 52 | return type(a:Value) ==# s:__TYPE_FLOAT 53 | endfunction 54 | " String 55 | function! s:is_string(Value) abort 56 | return type(a:Value) ==# s:__TYPE_STRING 57 | endfunction 58 | " Funcref 59 | function! s:is_funcref(Value) abort 60 | return type(a:Value) ==# s:__TYPE_FUNCREF 61 | endfunction 62 | " List 63 | function! s:is_list(Value) abort 64 | return type(a:Value) ==# s:__TYPE_LIST 65 | endfunction 66 | " Dictionary 67 | function! s:is_dict(Value) abort 68 | return type(a:Value) ==# s:__TYPE_DICT 69 | endfunction 70 | 71 | function! s:truncate_skipping(str, max, footer_width, separator) abort 72 | call s:_warn_deprecated('truncate_skipping', 'Data.String.truncate_skipping') 73 | 74 | let width = s:wcswidth(a:str) 75 | if width <= a:max 76 | let ret = a:str 77 | else 78 | let header_width = a:max - s:wcswidth(a:separator) - a:footer_width 79 | let ret = s:strwidthpart(a:str, header_width) . a:separator 80 | \ . s:strwidthpart_reverse(a:str, a:footer_width) 81 | endif 82 | 83 | return s:truncate(ret, a:max) 84 | endfunction 85 | 86 | function! s:truncate(str, width) abort 87 | " Original function is from mattn. 88 | " http://github.com/mattn/googlereader-vim/tree/master 89 | 90 | call s:_warn_deprecated('truncate', 'Data.String.truncate') 91 | 92 | if a:str =~# '^[\x00-\x7f]*$' 93 | return len(a:str) < a:width ? 94 | \ printf('%-'.a:width.'s', a:str) : strpart(a:str, 0, a:width) 95 | endif 96 | 97 | let ret = a:str 98 | let width = s:wcswidth(a:str) 99 | if width > a:width 100 | let ret = s:strwidthpart(ret, a:width) 101 | let width = s:wcswidth(ret) 102 | endif 103 | 104 | if width < a:width 105 | let ret .= repeat(' ', a:width - width) 106 | endif 107 | 108 | return ret 109 | endfunction 110 | 111 | function! s:strwidthpart(str, width) abort 112 | call s:_warn_deprecated('strwidthpart', 'Data.String.strwidthpart') 113 | 114 | if a:width <= 0 115 | return '' 116 | endif 117 | let ret = a:str 118 | let width = s:wcswidth(a:str) 119 | while width > a:width 120 | let char = matchstr(ret, '.$') 121 | let ret = ret[: -1 - len(char)] 122 | let width -= s:wcswidth(char) 123 | endwhile 124 | 125 | return ret 126 | endfunction 127 | function! s:strwidthpart_reverse(str, width) abort 128 | call s:_warn_deprecated('strwidthpart_reverse', 'Data.String.strwidthpart_reverse') 129 | 130 | if a:width <= 0 131 | return '' 132 | endif 133 | let ret = a:str 134 | let width = s:wcswidth(a:str) 135 | while width > a:width 136 | let char = matchstr(ret, '^.') 137 | let ret = ret[len(char) :] 138 | let width -= s:wcswidth(char) 139 | endwhile 140 | 141 | return ret 142 | endfunction 143 | 144 | if v:version >= 703 145 | " Use builtin function. 146 | function! s:wcswidth(str) abort 147 | call s:_warn_deprecated('wcswidth', 'Data.String.wcswidth') 148 | return strwidth(a:str) 149 | endfunction 150 | else 151 | function! s:wcswidth(str) abort 152 | call s:_warn_deprecated('wcswidth', 'Data.String.wcswidth') 153 | 154 | if a:str =~# '^[\x00-\x7f]*$' 155 | return strlen(a:str) 156 | end 157 | 158 | let mx_first = '^\(.\)' 159 | let str = a:str 160 | let width = 0 161 | while 1 162 | let ucs = char2nr(substitute(str, mx_first, '\1', '')) 163 | if ucs == 0 164 | break 165 | endif 166 | let width += s:_wcwidth(ucs) 167 | let str = substitute(str, mx_first, '', '') 168 | endwhile 169 | return width 170 | endfunction 171 | 172 | " UTF-8 only. 173 | function! s:_wcwidth(ucs) abort 174 | let ucs = a:ucs 175 | if (ucs >= 0x1100 176 | \ && (ucs <= 0x115f 177 | \ || ucs == 0x2329 178 | \ || ucs == 0x232a 179 | \ || (ucs >= 0x2e80 && ucs <= 0xa4cf 180 | \ && ucs != 0x303f) 181 | \ || (ucs >= 0xac00 && ucs <= 0xd7a3) 182 | \ || (ucs >= 0xf900 && ucs <= 0xfaff) 183 | \ || (ucs >= 0xfe30 && ucs <= 0xfe6f) 184 | \ || (ucs >= 0xff00 && ucs <= 0xff60) 185 | \ || (ucs >= 0xffe0 && ucs <= 0xffe6) 186 | \ || (ucs >= 0x20000 && ucs <= 0x2fffd) 187 | \ || (ucs >= 0x30000 && ucs <= 0x3fffd) 188 | \ )) 189 | return 2 190 | endif 191 | return 1 192 | endfunction 193 | endif 194 | 195 | let s:is_windows = has('win16') || has('win32') || has('win64') || has('win95') 196 | let s:is_cygwin = has('win32unix') 197 | let s:is_mac = !s:is_windows && !s:is_cygwin 198 | \ && (has('mac') || has('macunix') || has('gui_macvim') || 199 | \ (!isdirectory('/proc') && executable('sw_vers'))) 200 | let s:is_unix = has('unix') 201 | 202 | function! s:is_windows() abort 203 | return s:is_windows 204 | endfunction 205 | 206 | function! s:is_cygwin() abort 207 | return s:is_cygwin 208 | endfunction 209 | 210 | function! s:is_mac() abort 211 | return s:is_mac 212 | endfunction 213 | 214 | function! s:is_unix() abort 215 | return s:is_unix 216 | endfunction 217 | 218 | function! s:_warn_deprecated(name, alternative) abort 219 | try 220 | echohl Error 221 | echomsg 'Prelude.' . a:name . ' is deprecated! Please use ' . a:alternative . ' instead.' 222 | finally 223 | echohl None 224 | endtry 225 | endfunction 226 | 227 | function! s:smart_execute_command(action, word) abort 228 | execute a:action . ' ' . (a:word ==# '' ? '' : '`=a:word`') 229 | endfunction 230 | 231 | function! s:escape_file_searching(buffer_name) abort 232 | return escape(a:buffer_name, '*[]?{}, ') 233 | endfunction 234 | 235 | function! s:escape_pattern(str) abort 236 | return escape(a:str, '~"\.^$[]*') 237 | endfunction 238 | 239 | function! s:getchar(...) abort 240 | let c = call('getchar', a:000) 241 | return type(c) == type(0) ? nr2char(c) : c 242 | endfunction 243 | 244 | function! s:getchar_safe(...) abort 245 | let c = s:input_helper('getchar', a:000) 246 | return type(c) == type('') ? c : nr2char(c) 247 | endfunction 248 | 249 | function! s:input_safe(...) abort 250 | return s:input_helper('input', a:000) 251 | endfunction 252 | 253 | function! s:input_helper(funcname, args) abort 254 | let success = 0 255 | if inputsave() !=# success 256 | throw 'vital: Prelude: inputsave() failed' 257 | endif 258 | try 259 | return call(a:funcname, a:args) 260 | finally 261 | if inputrestore() !=# success 262 | throw 'vital: Prelude: inputrestore() failed' 263 | endif 264 | endtry 265 | endfunction 266 | 267 | function! s:set_default(var, val) abort 268 | if !exists(a:var) || type({a:var}) != type(a:val) 269 | let {a:var} = a:val 270 | endif 271 | endfunction 272 | 273 | function! s:substitute_path_separator(path) abort 274 | return s:is_windows ? substitute(a:path, '\\', '/', 'g') : a:path 275 | endfunction 276 | 277 | function! s:path2directory(path) abort 278 | return s:substitute_path_separator(isdirectory(a:path) ? a:path : fnamemodify(a:path, ':p:h')) 279 | endfunction 280 | 281 | function! s:_path2project_directory_git(path) abort 282 | let parent = a:path 283 | 284 | while 1 285 | let path = parent . '/.git' 286 | if isdirectory(path) || filereadable(path) 287 | return parent 288 | endif 289 | let next = fnamemodify(parent, ':h') 290 | if next == parent 291 | return '' 292 | endif 293 | let parent = next 294 | endwhile 295 | endfunction 296 | 297 | function! s:_path2project_directory_svn(path) abort 298 | let search_directory = a:path 299 | let directory = '' 300 | 301 | let find_directory = s:escape_file_searching(search_directory) 302 | let d = finddir('.svn', find_directory . ';') 303 | if d ==# '' 304 | return '' 305 | endif 306 | 307 | let directory = fnamemodify(d, ':p:h:h') 308 | 309 | " Search parent directories. 310 | let parent_directory = s:path2directory( 311 | \ fnamemodify(directory, ':h')) 312 | 313 | if parent_directory !=# '' 314 | let d = finddir('.svn', parent_directory . ';') 315 | if d !=# '' 316 | let directory = s:_path2project_directory_svn(parent_directory) 317 | endif 318 | endif 319 | return directory 320 | endfunction 321 | 322 | function! s:_path2project_directory_others(vcs, path) abort 323 | let vcs = a:vcs 324 | let search_directory = a:path 325 | 326 | let find_directory = s:escape_file_searching(search_directory) 327 | let d = finddir(vcs, find_directory . ';') 328 | if d ==# '' 329 | return '' 330 | endif 331 | return fnamemodify(d, ':p:h:h') 332 | endfunction 333 | 334 | function! s:path2project_directory(path, ...) abort 335 | let is_allow_empty = get(a:000, 0, 0) 336 | let search_directory = s:path2directory(a:path) 337 | let directory = '' 338 | 339 | " Search VCS directory. 340 | for vcs in ['.git', '.bzr', '.hg', '.svn'] 341 | if vcs ==# '.git' 342 | let directory = s:_path2project_directory_git(search_directory) 343 | elseif vcs ==# '.svn' 344 | let directory = s:_path2project_directory_svn(search_directory) 345 | else 346 | let directory = s:_path2project_directory_others(vcs, search_directory) 347 | endif 348 | if directory !=# '' 349 | break 350 | endif 351 | endfor 352 | 353 | " Search project file. 354 | if directory ==# '' 355 | for d in ['build.xml', 'prj.el', '.project', 'pom.xml', 'package.json', 356 | \ 'Makefile', 'configure', 'Rakefile', 'NAnt.build', 357 | \ 'P4CONFIG', 'tags', 'gtags'] 358 | let d = findfile(d, s:escape_file_searching(search_directory) . ';') 359 | if d !=# '' 360 | let directory = fnamemodify(d, ':p:h') 361 | break 362 | endif 363 | endfor 364 | endif 365 | 366 | if directory ==# '' 367 | " Search /src/ directory. 368 | let base = s:substitute_path_separator(search_directory) 369 | if base =~# '/src/' 370 | let directory = base[: strridx(base, '/src/') + 3] 371 | endif 372 | endif 373 | 374 | if directory ==# '' && !is_allow_empty 375 | " Use original path. 376 | let directory = search_directory 377 | endif 378 | 379 | return s:substitute_path_separator(directory) 380 | endfunction 381 | 382 | let &cpo = s:save_cpo 383 | unlet s:save_cpo 384 | 385 | " vim:set et ts=2 sts=2 sw=2 tw=0: 386 | -------------------------------------------------------------------------------- /autoload/vital/_debugger/Vim/Message.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpo 2 | set cpo&vim 3 | 4 | 5 | 6 | function! s:echo(hl, msg) abort 7 | execute 'echohl' a:hl 8 | try 9 | echo a:msg 10 | finally 11 | echohl None 12 | endtry 13 | endfunction 14 | 15 | function! s:echomsg(hl, msg) abort 16 | execute 'echohl' a:hl 17 | try 18 | for m in split(a:msg, "\n") 19 | echomsg m 20 | endfor 21 | finally 22 | echohl None 23 | endtry 24 | endfunction 25 | 26 | function! s:error(msg) abort 27 | call s:echomsg('ErrorMsg', a:msg) 28 | endfunction 29 | 30 | function! s:warn(msg) abort 31 | call s:echomsg('WarningMsg', a:msg) 32 | endfunction 33 | 34 | function! s:capture(command) abort 35 | try 36 | redir => out 37 | silent execute a:command 38 | finally 39 | redir END 40 | endtry 41 | return out 42 | endfunction 43 | 44 | " * Get max length of |hit-enter|. 45 | " If a string length of a message is greater than the max length, 46 | " Vim waits for user input according to |hit-enter|. 47 | " XXX: Those fixed values may be different between different OSes? 48 | " Currently tested on only Windows. 49 | function! s:get_hit_enter_max_length() abort 50 | let maxlen = &columns * &cmdheight - 1 51 | if &ruler 52 | " TODO 53 | endif 54 | if &showcmd 55 | let maxlen -= 11 56 | endif 57 | return maxlen 58 | endfunction 59 | 60 | 61 | 62 | let &cpo = s:save_cpo 63 | unlet s:save_cpo 64 | 65 | " vim:set et ts=2 sts=2 sw=2 tw=0: 66 | -------------------------------------------------------------------------------- /autoload/vital/_debugger/Vim/ScriptLocal.vim: -------------------------------------------------------------------------------- 1 | scriptencoding utf-8 2 | let s:save_cpo = &cpo 3 | set cpo&vim 4 | 5 | """ Helper: 6 | 7 | function! s:_throw(message) abort 8 | throw printf('vital: Vim.ScriptLocal: %s', a:message) 9 | endfunction 10 | 11 | "" Capture command 12 | function! s:_capture(command) abort 13 | try 14 | let save_verbose = &verbose 15 | let &verbose = 0 16 | redir => out 17 | silent execute a:command 18 | finally 19 | redir END 20 | let &verbose = save_verbose 21 | endtry 22 | return out 23 | endfunction 24 | 25 | "" Capture command and return lines 26 | function! s:_capture_lines(command) abort 27 | return split(s:_capture(a:command), "\n") 28 | endfunction 29 | 30 | "" Return funcname of script local functions with SID 31 | function! s:_sfuncname(sid, funcname) abort 32 | return printf('%s_%s', a:sid, a:funcname) 33 | endfunction 34 | 35 | function! s:_source(path) abort 36 | try 37 | execute ':source' fnameescape(a:path) 38 | catch /^Vim\%((\a\+)\)\=:E121/ 39 | " NOTE: workaround for `E121: Undefined variable: s:save_cpo` 40 | execute ':source' fnameescape(a:path) 41 | endtry 42 | endfunction 43 | 44 | let s:_cache = { '_': {} } 45 | 46 | function! s:_cache.return(key, value) abort 47 | let self._[a:key] = a:value 48 | return a:value 49 | endfunction 50 | 51 | function! s:_cache.has(key) abort 52 | return has_key(self._, a:key) 53 | endfunction 54 | 55 | function! s:_cache.get(key) abort 56 | return self._[a:key] 57 | endfunction 58 | 59 | let s:cache = { 60 | \ 'sid': deepcopy(s:_cache), 61 | \ 'sid2path': deepcopy(s:_cache), 62 | \ 'sid2svars': deepcopy(s:_cache) 63 | \} 64 | 65 | """ Main: 66 | 67 | "" Improved scriptnames() 68 | " @return {sid1: path1, sid2: path2, ...} 69 | function! s:scriptnames() abort 70 | let sdict = {} " { sid: path } 71 | for line in s:_capture_lines(':scriptnames') 72 | let [sid, path] = split(line, '\m^\s*\d\+\zs:\s\ze') 73 | let sdict[str2nr(sid)] = s:_unify_path(path) " str2nr(): ' 1' -> 1 74 | endfor 75 | return sdict 76 | endfunction 77 | 78 | "" Return SID from the given path 79 | " return -1 if the given path is not found in scriptnames() 80 | " NOTE: it execute `:source` a given path once if the file haven't sourced yet 81 | function! s:sid(path) abort 82 | if s:cache.sid.has(a:path) 83 | return s:cache.sid.get(a:path) 84 | endif 85 | " Expand to full path 86 | let tp = fnamemodify(a:path, ':p') " target path 87 | " Relative to &runtimepath 88 | if !filereadable(tp) 89 | " NOTE: if there are more than one matched paths, use the first one. 90 | let tp = get(split(globpath(&runtimepath, a:path, 1), "\n"), 0, '') 91 | endif 92 | if !filereadable(tp) 93 | return s:_throw('file not found') 94 | endif 95 | let sid = s:_sid(tp, s:scriptnames()) 96 | if sid isnot -1 97 | " return sid 98 | return s:cache.sid.return(a:path, sid) 99 | else 100 | call s:_source(tp) 101 | " return s:_sid(tp, s:scriptnames()) 102 | return s:cache.sid.return(a:path, s:_sid(tp, s:scriptnames())) 103 | endif 104 | endfunction 105 | 106 | " Assume `a:abspath` is absolute path 107 | function! s:_sid(abspath, scriptnames) abort 108 | " Handle symbolic link here 109 | let tp = s:_unify_path(a:abspath) " target path 110 | for sid in keys(a:scriptnames) 111 | if tp is# a:scriptnames[sid] 112 | return str2nr(sid) 113 | endif 114 | endfor 115 | return -1 116 | endfunction 117 | 118 | "" Return path from SID 119 | function! s:sid2path(sid) abort 120 | if s:cache.sid2path.has(a:sid) 121 | return s:cache.sid2path.get(a:sid) 122 | endif 123 | let sn = s:scriptnames() 124 | if has_key(sn, a:sid) 125 | " return sn[a:sid] 126 | return s:cache.sid2path.return(a:sid, sn[a:sid]) 127 | else 128 | return s:_throw('sid not found') 129 | endif 130 | endfunction 131 | 132 | "" Return a dict which contains script-local functions from given path 133 | " `path` should be absolute path or relative to &runtimepath 134 | " @return {funcname: funcref, funcname2: funcref2, ...} 135 | " USAGE: 136 | " :echo s:sfuncs('~/.vim/bundle/plugname/autoload/plugname.vim') 137 | " " => { 'fname1': funcref1, 'fname2': funcref2, ...} 138 | " :echo s:sfuncs('autoload/plugname.vim') 139 | " " => { 'fname1': funcref1, 'fname2': funcref2, ...} 140 | function! s:sfuncs(path) abort 141 | return s:sid2sfuncs(s:sid(a:path)) 142 | endfunction 143 | 144 | "" Return a dict which contains script-local functions from SID 145 | " USAGE: 146 | " :echo s:sid2sfuncs(1) 147 | " " => { 'fname1': funcref1, 'fname2': funcref2, ...} 148 | " " The file whose SID is 1 may be your vimrc 149 | " NOTE: old regexpengine has a bug which returns 0 with 150 | " :echo "\" =~# "\\%#=1\x80\xfdR" | " => 0 151 | " But it matches correctly with :h /collection 152 | " :echo "\" =~# "\\%#=1[\x80][\xfd]R" | " => 1 153 | " http://lingr.com/room/vim/archives/2015/02/13#message-21261450 154 | " In MS Windows with old Vim, [] doesn't work, but [\xXX] works well. 155 | " The cause isn't being investigated. 156 | let s:SNR = join(map(range(len("\")), '"[\\x" . printf("%0x", char2nr("\"[v:val])) . "]"'), '') 157 | function! s:sid2sfuncs(sid) abort 158 | ":h :function /{pattern} 159 | " -> ^________ 160 | " function 14_functionname(args, ...) 161 | let fs = s:_capture_lines(':function ' . printf('/^%s%s_', s:SNR, a:sid)) 162 | let r = {} 163 | " -> ^--------____________- 164 | " function 14_functionname(args, ...) 165 | let pattern = printf('\m^function\s%d_\zs\w\{-}\ze(', a:sid) 166 | for fname in map(fs, 'matchstr(v:val, pattern)') 167 | let r[fname] = function(s:_sfuncname(a:sid, fname)) 168 | endfor 169 | return r 170 | endfunction 171 | 172 | let s:GETSVARSFUNCNAME = '___VITAL_VIM_SCRIPTLOCAL_GET_SVARS___' 173 | 174 | let s:_get_svars_func = [ 175 | \ printf('function! s:%s() abort', s:GETSVARSFUNCNAME), 176 | \ ' return s:', 177 | \ 'endfunction' 178 | \ ] 179 | 180 | "" Return script-local variable (s:var) dict form path 181 | function! s:svars(path) abort 182 | return s:sid2svars(s:sid(a:path)) 183 | endfunction 184 | 185 | "" Return script-local variable (s:var) dictionary form SID 186 | function! s:sid2svars(sid) abort 187 | if s:cache.sid2svars.has(a:sid) 188 | return s:cache.sid2svars.get(a:sid) 189 | endif 190 | let fullpath = fnamemodify(s:sid2path(a:sid), ':p') 191 | let lines = readfile(fullpath) 192 | try 193 | call writefile(s:_get_svars_func, fullpath) 194 | call s:_source(fullpath) 195 | let sfuncname = s:_sfuncname(a:sid, s:GETSVARSFUNCNAME) 196 | let svars = call(function(sfuncname), []) 197 | execute 'delfunction' sfuncname 198 | " return svars 199 | return s:cache.sid2svars.return(a:sid, svars) 200 | finally 201 | call writefile(lines, fullpath) 202 | endtry 203 | endfunction 204 | 205 | 206 | " This is copied from autoload/vital/__latest__.vim 207 | " FIXME: Avoid duplication. 208 | function! s:_unify_path(path) abort 209 | return resolve(fnamemodify(a:path, ':p:gs?[\\/]?/?')) 210 | endfunction 211 | 212 | 213 | let &cpo = s:save_cpo 214 | unlet s:save_cpo 215 | 216 | " vim:set et ts=2 sts=2 sw=2 tw=0: 217 | -------------------------------------------------------------------------------- /autoload/vital/_debugger/Vim/SyntaxEcho.vim: -------------------------------------------------------------------------------- 1 | "============================================================================= 2 | " FILE: autoload/vital/__latest__/Vim/SyntaxEcho.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 | function! s:_vital_loaded(V) abort 11 | let s:String = a:V.import('Data.String') 12 | let s:Set = a:V.import('Data.Set') 13 | call s:_setup() 14 | endfunction 15 | 16 | function! s:_vital_depends() abort 17 | return [ 18 | \ 'Data.String', 19 | \ 'Data.Set', 20 | \ ] 21 | endfunction 22 | 23 | let s:TRUE = !0 24 | let s:FALSE = 0 25 | 26 | function! s:echon(string) abort 27 | let [bodies, comment] = s:_parse_comment(a:string) 28 | let is_statement = s:TRUE 29 | for body in bodies 30 | if has_key(body, 'quote') 31 | call s:_echon('String', body.quote) 32 | else 33 | call s:_echo_body(body.plain, is_statement) 34 | endif 35 | let is_statement = s:FALSE 36 | endfor 37 | call s:_echon('Comment', comment) 38 | endfunction 39 | 40 | function! s:echo(string) abort 41 | echo '' 42 | call s:echon(a:string) 43 | endfunction 44 | 45 | function! s:_test_syntax_echon() abort 46 | echo '' | call s:echon('" comment') 47 | echo '' | call s:echon('function! s:_parse_comment(string) abort') 48 | echo '' | call s:echon('let [body, comment] = s:_parse_comment(a:string)') 49 | echo '' | call s:echon(' let is_statement = s:TRUE " comment') 50 | echo '' | call s:echon("call s:Message.echon('Identifier', token)") 51 | echo '' | call s:echon("let cmd = matchstr(token, '^.\{-}\ze\(!\s*\)\=')") 52 | echo '' | call s:echon('let start_d_idx = -1') 53 | endfunction 54 | 55 | function! s:_echon(hl, msg) abort 56 | execute 'echohl' a:hl 57 | try 58 | echon a:msg 59 | finally 60 | echohl None 61 | endtry 62 | endfunction 63 | 64 | function! s:_echo_body(body, is_statement) abort 65 | let is_statement = a:is_statement 66 | for token in split(a:body, '\s\zs') 67 | if token is# ' ' 68 | echon token 69 | elseif is_statement && token =~# '\\\s*' 70 | call s:_echon('Special', token) 71 | elseif is_statement 72 | let cmd = matchstr(token, '^\l\+\ze\(!\)\=\s*') 73 | if s:command_set.in(cmd) 74 | if token =~# '!\s*$' 75 | let sp = split(token, '!\ze\s*$') 76 | let cmd = get(sp, 0, '') 77 | let spaces = get(sp, 1, '') 78 | call s:_echon('Statement', cmd) 79 | call s:_echon('vimFunction', '!') 80 | echon spaces 81 | else 82 | call s:_echon('Statement', token) 83 | endif 84 | else 85 | echon token 86 | endif 87 | let is_statement = s:FALSE 88 | else 89 | if token =~# '^[gasbwt]:\k\+\s*$' 90 | call s:_echon('Identifier', token) 91 | elseif s:_is_vim_operator(s:String.trim(token)) 92 | call s:_echon('Operator', token) 93 | elseif s:_is_vim_func(token) 94 | let [funcname, rest] = split(token, '^\k\+\zs\ze(') 95 | call s:_echon('Function', funcname) 96 | echon rest 97 | elseif token =~# '^\%(\<\|-\)\=\d\+\>$' 98 | call s:_echon('Number', token) 99 | else 100 | echon token 101 | endif 102 | let is_statement = s:FALSE 103 | endif 104 | endfor 105 | endfunction 106 | 107 | function! s:_is_vim_operator(token) abort 108 | return a:token =~# '^\(==\|!=\|>=\|<=\|=\~\|!\~\|>\|<\|=\)[?#]\{0,2}$' || 109 | \ a:token =~# '^||\|&&\|[-+.]$' 110 | endfunction 111 | 112 | function! s:_is_vim_func(token) abort 113 | let funcname = matchstr(a:token, '^\k\+\ze(') 114 | return funcname isnot# '' && s:funcnames.in(funcname) 115 | endfunction 116 | 117 | " @return [bodies, comment] 118 | function! s:_parse_comment(string) abort 119 | let quote_idx_pair = [] 120 | if a:string =~# '^\s*"' 121 | return [s:_body('', quote_idx_pair), a:string] 122 | endif 123 | 124 | " is in single quote 125 | let is_in_s = s:FALSE 126 | " is in double quote 127 | let is_in_d = s:FALSE 128 | " is now escape state 129 | let is_escape = s:FALSE 130 | " the index of start of douple quote 131 | let start_d_idx = -1 132 | " the index of start of single quote 133 | let start_s_idx = -1 134 | let idx = 0 135 | for c in map(range(len(a:string)), 'a:string[v:val]') 136 | if c is# '"' && !(is_in_d && is_escape) && !is_in_s 137 | if is_in_d 138 | " close " 139 | let is_in_d = s:FALSE 140 | let quote_idx_pair += [[start_d_idx, idx]] 141 | let start_d_idx = -1 142 | else 143 | " start " 144 | let is_in_d = s:TRUE 145 | let start_d_idx = idx 146 | endif 147 | elseif c is# "'" && !is_in_d 148 | if is_in_s 149 | let quote_idx_pair += [[start_s_idx, idx]] 150 | let start_s_idx = -1 151 | else 152 | let start_s_idx = idx 153 | endif 154 | let is_in_s = !is_in_s 155 | endif 156 | 157 | if c is# '\' && is_in_d 158 | let is_escape = !is_escape 159 | else 160 | let is_escape = s:FALSE 161 | endif 162 | 163 | let idx += 1 164 | endfor 165 | if start_d_idx is# -1 166 | return [s:_body(a:string, quote_idx_pair), ''] 167 | else 168 | if start_d_idx is# 0 169 | return [s:_body('', quote_idx_pair), a:string[start_d_idx :]] 170 | else 171 | return [s:_body(a:string[: start_d_idx - 1], quote_idx_pair), a:string[start_d_idx :]] 172 | endif 173 | endif 174 | endfunction 175 | 176 | function! s:_body(body, quote_idx_pair) abort 177 | let bodies = [] 178 | let idx = 0 179 | for pair in a:quote_idx_pair 180 | let [start, end] = pair 181 | let bodies += [{'plain': a:body[idx : start - 1]}] 182 | let bodies += [{'quote': a:body[start : end]}] 183 | let idx = end + 1 184 | endfor 185 | let bodies += [{'plain': a:body[idx :]}] 186 | return bodies 187 | endfunction 188 | 189 | let s:commands = [ 190 | \ 'a', 'arga[dd]', 'argl[ocal]', 'ba[ll]', 'bn[ext]', 'breakd[el]', 'bufdo', 'cabc[lear]', 'cat[ch]', 'ce[nter]', 'cgetb[uffer]', 'che[ckpath]', 'cmapc[lear]', 'cnf', 'com', 'cope[n]', 'cs', 'de', 'delep', 'delf', 'di', 'difft[his]', 'dj[ump]', 'dr[op]', 'ec', 'elsei[f]', 'endf[unction]', 'exi[t]', 'filetype', 'fix[del]', 'for', 'gr[ep]', 'h[elp]', 'hid[e]', 'ij[ump]', 'isp[lit]', 'keepalt', 'lad', 'la[st]', 'lcl[ose]', 'lex[pr]', 'lgete[xpr]', 'll', 'lne', 'lnf[ile]', 'loc[kmarks]', 'lr[ewind]', 'lv[imgrep]', 'marks', 'mk', 'mkv[imrc]', 'mz[scheme]', 'new', 'noswap[file]', 'o[pen]', 'ped[it]', 'pp[op]', 'profd[el]', 'ptf[irst]', 'ptN[ext]', 'py', 'python3', 're', 'redr[aw]', 'rew[ind]', 'rubyf[ile]', 'sa[rgument]', 'sbn[ext]', 'scripte[ncoding]', 'setf[iletype]', 'sh[ell]', 'sim[alt]', 'sm[ap]', 'sni[ff]', 'sor[t]', 'spelli[nfo]', 'spr[evious]', 'start', 'st[op]', 'sunmenu', 'syn', 'ta', 'tabf[ind]', 'tabnew', 'tabr[ewind]', 'tcld[o]', 'tj[ump]', 'tN', 'tr', 'tu[nmenu]', 'undoj[oin]', 'uns[ilent]', 've[rsion]', 'vimgrepa[dd]', 'vs[plit]', 'winc[md]', 'wN[ext]', 'ws[verb]', 'x[it]', 'xnoremenu', 191 | \ 'ab', 'argd', 'ar[gs]', 'bd[elete]', 'bN[ext]', 'breakl[ist]', 'b[uffer]', 'cad', 'cb[uffer]', 'cex[pr]', 'cgete[xpr]', 'checkt[ime]', 'cn', 'cNf', 'comc[lear]', 'co[py]', 'cscope', 'debug', 'd[elete]', 'delf[unction]', 'diffg[et]', 'diffu[pdate]', 'dl', 'ds[earch]', 'echoe[rr]', 'em[enu]', 'en[dif]', 'exu[sage]', 'fin', 'fo[ld]', 'fu', 'grepa[dd]', 'helpc[lose]', 'his[tory]', 'il[ist]', 'iuna[bbrev]', 'keepj[umps]', 'laddb[uffer]', 'lat', 'lcs', 'lf', 'lg[etfile]', 'lla[st]', 'lnew[er]', 'lNf[ile]', 'lockv[ar]', 'ls', 'lvimgrepa[dd]', 'mat[ch]', 'mk[exrc]', 'mo', 'n', 'n[ext]', 'nu[mber]', 'opt[ions]', 'pe[rl]', 'pr', 'prof[ile]', 'ptj[ump]', 'ptp[revious]', 'py3', 'q', 'r[ead]', 'redraws[tatus]', 'ri[ght]', 'rundo', 'sav[eas]', 'sbN[ext]', 'scrip[tnames]', 'setg[lobal]', 'si', 'sl', 'sme', 'sno[magic]', 'so[urce]', 'spellr[epall]', 'sre[wind]', 'startg[replace]', 'stopi[nsert]', 'sus[pend]', 'sync', 'tab', 'tabfir[st]', 'tabn[ext]', 'tabs', 'tclf[ile]', 'tl[ast]', 'tn[ext]', 'tr[ewind]', 'u', 'undol[ist]', 'up[date]', 'vert[ical]', 'vi[sual]', 'w', 'windo', 'wp[revious]', 'wundo', 'xmapc[lear]', 'xunme', 192 | \ 'abc[lear]', 'argd[elete]', 'argu[ment]', 'bel[owright]', 'bo[tright]', 'br[ewind]', 'buffers', 'caddb[uffer]', 'cc', 'cf', 'cg[etfile]', 'cl', 'cN', 'cnf[ile]', 'comp[iler]', 'cpf[ile]', 'cstag', 'debugg[reedy]', 'deletel', 'dell', 'diffo[ff]', 'dig', 'dli[st]', 'dsp[lit]', 'echom[sg]', 'en', 'endt[ry]', 'f', 'fina[lly]', 'foldc[lose]', 'fun', 'gui', 'helpf[ind]', 'i', 'imapc[lear]', 'j[oin]', 'kee[pmarks]', 'lad[dexpr]', 'later', 'lcscope', 'lfdo', 'lgr[ep]', 'lli[st]', 'lne[xt]', 'lo', 'lol[der]', 'lt[ag]', 'lw[indow]', 'menut', 'mks[ession]', 'mod[e]', 'nbc[lose]', 'nmapc[lear]', 'o', 'ownsyntax', 'perld[o]', 'pre[serve]', 'promptf[ind]', 'ptl[ast]', 'ptr[ewind]', 'py3do', 'qa[ll]', 'rec[over]', 'reg[isters]', 'rightb[elow]', 'ru[ntime]', 'sba[ll]', 'sbp[revious]', 'scs', 'setl[ocal]', 'sig', 'sla[st]', 'smenu', 'snoreme', 'spe', 'spellu[ndo]', 'st', 'star[tinsert]', 'sts[elect]', 'sv[iew]', 'syncbind', 'tabc[lose]', 'tabl[ast]', 'tabN[ext]', 'ta[g]', 'te[aroff]', 'tm', 'tN[ext]', 'try', 'un', 'unh[ide]', 'v', 'vi', 'viu[sage]', 'wa[ll]', 'winp[os]', 'wq', 'wv[iminfo]', 'xme', 'xunmenu', 193 | \ 'abo[veleft]', 'argdo', 'as[cii]', 'bf[irst]', 'bp[revious]', 'bro[wse]', 'bun[load]', 'cad[dexpr]', 'ccl[ose]', 'cfdo', 'c[hange]', 'cla[st]', 'cnew[er]', 'cNf[ile]', 'con', 'cp[revious]', 'cuna[bbrev]', 'del', 'deletep', 'delm[arks]', 'diffp[atch]', 'dig[raphs]', 'do', 'e', 'echon', 'endf', 'endw[hile]', 'f[ile]', 'fin[d]', 'folddoc[losed]', 'fu[nction]', 'gvim', 'helpg[rep]', 'ia', 'in', 'ju[mps]', 'keepp[atterns]', 'laddf[ile]', 'lb[uffer]', 'ld[o]', 'lf[ile]', 'lgrepa[dd]', 'lmak[e]', 'lN[ext]', 'loadk', 'lop[en]', 'lua', 'ma', 'menut[ranslate]', 'mksp[ell]', 'm[ove]', 'nb[key]', 'noa', 'ol[dfiles]', 'p', 'po[p]', 'prev[ious]', 'promptr[epl]', 'ptn', 'pts[elect]', 'pydo', 'q[uit]', 'red', 'res[ize]', 'ru', 'rv[iminfo]', 'sbf[irst]', 'sbr[ewind]', 'scscope', 'sf[ind]', 'sign', 'sl[eep]', 'sn[ext]', 'snoremenu', 'spelld[ump]', 'spellw[rong]', 'sta[g]', 'startr[eplace]', 'sun[hide]', 'sw[apname]', 'syntime', 'tabd[o]', 'tabm[ove]', 'tabo[nly]', 'tags', 'tf[irst]', 'tm[enu]', 'to[pleft]', 'ts[elect]', 'una[bbreviate]', 'unl', 've', 'vie[w]', 'vmapc[lear]', 'wh[ile]', 'win[size]', 'wqa[ll]', 'x', 'xmenu', 'xwininfo', 194 | \ 'al[l]', 'arge[dit]', 'au', 'bl[ast]', 'brea[k]', 'bu', 'bw[ipeout]', 'caddf[ile]', 'cd', 'cf[ile]', 'changes', 'cl[ist]', 'cn[ext]', 'col[der]', 'conf[irm]', 'cq[uit]', 'cw[indow]', 'delc[ommand]', 'deletl', 'delp', 'diffpu[t]', 'dir', 'doau', 'ea', 'e[dit]', 'endfo[r]', 'ene[w]', 'files', 'fini[sh]', 'foldd[oopen]', 'g', 'h', 'helpt[ags]', 'iabc[lear]', 'intro', 'k', 'l', 'lan', 'lc[d]', 'le[ft]', 'lfir[st]', 'lh[elpgrep]', 'lmapc[lear]', 'lnf', 'loadkeymap', 'lpf[ile]', 'luado', 'mak[e]', 'mes', 'mkv', 'mz', 'nbs[tart]', 'noautocmd', 'omapc[lear]', 'pc[lose]', 'popu', 'p[rint]', 'ps[earch]', 'ptN', 'pu[t]', 'pyf[ile]', 'quita[ll]', 'redi[r]', 'ret[ab]', 'rub[y]', 'sal[l]', 'sbl[ast]', 'sb[uffer]', 'se[t]', 'sfir[st]', 'sil[ent]', 'sm[agic]', 'sN[ext]', 'so', 'spe[llgood]', 'sp[lit]', 'star', 'stj[ump]', 'sunme', 'sy', 't', 'tabe[dit]', 'tabN', 'tabp[revious]', 'tc[l]', 'th[row]', 'tn', 'tp[revious]', 'tu', 'u[ndo]', 'unlo[ckvar]', 'verb[ose]', 'vim[grep]', 'vne[w]', 'win', 'wn[ext]', 'w[rite]', 'xa[ll]', 'xnoreme', 'y[ank]', 195 | \ 'ar', 'argg[lobal]', 'bad[d]', 'bm[odified]', 'breaka[dd]', 'buf', 'c', 'cal[l]', 'cdo', 'cfir[st]', 'chd[ir]', 'clo[se]', 'cN[ext]', 'colo[rscheme]', 'con[tinue]', 'cr[ewind]', 'd', 'delel', 'deletp', 'dep', 'diffs[plit]', 'di[splay]', 'dp', 'earlier', 'el[se]', 'endfun', 'ex', 'filet', 'fir[st]', 'foldo[pen]', 'go[to]', 'ha[rdcopy]', 'hi', 'if', 'is[earch]', 'keepa', 'la', 'lan[guage]', 'lch[dir]', 'lefta[bove]', 'lgetb[uffer]', 'l[ist]', 'lN', 'lNf', 'lo[adview]', 'lp[revious]', 'luafile', 'ma[rk]', 'messages', 'mkvie[w]', 'mzf[ile]', 'ne', 'noh[lsearch]', 'on[ly]', 'pe', 'popu[p]', 'pro', 'pta[g]', 'ptn[ext]', 'pw[d]', 'py[thon]', 'r', 'red[o]', 'retu[rn]', 'rubyd[o]', 'san[dbox]', 'sbm[odified]', 'scrip', 196 | \ 'let', 'unl[et]', 197 | \ 'aug[roup]', 'au[tocmd]', 'do[autocmd]', 'doautoa[ll]', 198 | \ 'ec[ho]', 'exe[cute]', 199 | \ ] 200 | 201 | function! s:_gen_set() abort 202 | let s:V = vital#of('vital') 203 | let s:Set = s:V.import('Data.Set') 204 | let commands_set = s:Set.set() 205 | for c in s:commands 206 | let pre = matchstr(c, '^\w\+\ze\[\=') 207 | let opt_chars = matchstr(c, '\[\zs\w\+\ze\]') 208 | for oc in [''] + split(opt_chars, '\zs') 209 | let pre .= oc 210 | call commands_set.add(pre) 211 | endfor 212 | endfor 213 | return sort(commands_set.to_list()) 214 | endfunction 215 | " echo PP(s:_gen_set()) 216 | 217 | function! s:_setup() abort 218 | 219 | let s:funcnames = s:Set.set([ 220 | \ 'abs', 'and', 'argidx', 'asin', 'browse', 'buflisted', 'bufnr', 'byteidx', 'ceil', 'cindent', 'complete', 'confirm', 'cosh', 'cursor', 'did_filetype', 'empty', 'eventhandler', 'exists', 'expr8', 'filereadable', 'finddir', 'floor', 'fnamemodify', 'foldlevel', 'foreground', 'get', 'getchar', 'getcmdline', 'getcmdwintype', 'getfontname', 'getftime', 'getloclist', 'getpos', 'getregtype', 'getwinposx', 'glob', 'has', 'hasmapto', 'histget', 'hlID', 'indent', 'inputdialog', 'inputsave', 'invert', 'items', 'len', 'line', 'localtime', 'luaeval', 'mapcheck', 'matchaddpos', 'matchend', 'max', 'mode', 'nr2char', 'pow', 'pumvisible', 'range', 'reltimestr', 'remote_peek', 'remove', 'resolve', 'screenattr', 'screenrow', 'searchpair', 'server2client', 'setcharsearch', 'setloclist', 'setqflist', 'settabwinvar', 'shellescape', 'sin', 'soundfold', 'split', 'str2float', 'strchars', 'strftime', 'string', 'strpart', 'strtrans', 'submatch', 'synconcealed', 'synIDattr', 'synstack', 'systemlist', 'tabpagenr', 'tagfiles', 'tan', 'tempname', 'toupper', 'trunc', 'undofile', 'uniq', 'virtcol', 'wildmenumode', 'wincol', 'winline', 'winrestcmd', 'winsaveview', 'writefile', 221 | \ 'acos', 'append', 'arglistid', 'atan', 'browsedir', 'bufloaded', 'bufwinnr', 'byteidxcomp', 'changenr', 'clearmatches', 'complete_add', 'copy', 'count', 'deepcopy', 'diff_filler', 'escape', 'executable', 'exp', 'extend', 'filewritable', 'findfile', 'fmod', 'foldclosed', 'foldtext', 'function', 'getbufline', 'getcharmod', 'getcmdpos', 'getcurpos', 'getfperm', 'getftype', 'getmatches', 'getqflist', 'gettabvar', 'getwinposy', 'glob2regpat', 'has_key', 'histadd', 'histnr', 'hostname', 'index', 'inputlist', 'inputsecret', 'isdirectory', 'join', 'libcall', 'line2byte', 'log', 'map', 'match', 'matcharg', 'matchlist', 'min', 'mzeval', 'or', 'prevnonblank', 'py3eval', 'readfile', 'remote_expr', 'remote_read', 'rename', 'reverse', 'screenchar', 'search', 'searchpairpos', 'serverlist', 'setcmdpos', 'setmatches', 'setreg', 'setwinvar', 'shiftwidth', 'sinh', 'spellbadword', 'sqrt', 'str2nr', 'strdisplaywidth', 'stridx', 'strlen', 'strridx', 'strwidth', 'substitute', 'synID', 'synIDtrans', 'system', 'tabpagebuflist', 'tabpagewinnr', 'taglist', 'tanh', 'tolower', 'tr', 'type', 'undotree', 'values', 'visualmode', 'winbufnr', 'winheight', 'winnr', 'winrestview', 'winwidth', 'xor', 222 | \ 'add', 'argc', 'argv', 'atan2', 'bufexists', 'bufname', 'byte2line', 'call', 'char2nr', 'col', 'complete_check', 'cos', 'cscope_connection', 'delete', 'diff_hlID', 'eval', 'exepath', 'expand', 'feedkeys', 'filter', 'float2nr', 'fnameescape', 'foldclosedend', 'foldtextresult', 'garbagecollect', 'getbufvar', 'getcharsearch', 'getcmdtype', 'getcwd', 'getfsize', 'getline', 'getpid', 'getreg', 'gettabwinvar', 'getwinvar', 'globpath', 'haslocaldir', 'histdel', 'hlexists', 'iconv', 'input', 'inputrestore', 'insert', 'islocked', 'keys', 'libcallnr', 'lispindent', 'log10', 'maparg', 'matchadd', 'matchdelete', 'matchstr', 'mkdir', 'nextnonblank', 'pathshorten', 'printf', 'pyeval', 'reltime', 'remote_foreground', 'remote_send', 'repeat', 'round', 'screencol', 'searchdecl', 'searchpos', 'setbufvar', 'setline', 'setpos', 'settabvar', 'sha256', 'simplify', 'sort', 'spellsuggest', 223 | \ ]) 224 | 225 | let s:command_set = s:Set.set( 226 | \ [ 227 | \ 'a', 228 | \ 'ab', 229 | \ 'abc', 230 | \ 'abcl', 231 | \ 'abcle', 232 | \ 'abclea', 233 | \ 'abclear', 234 | \ 'abo', 235 | \ 'abov', 236 | \ 'above', 237 | \ 'abovel', 238 | \ 'abovele', 239 | \ 'abovelef', 240 | \ 'aboveleft', 241 | \ 'al', 242 | \ 'all', 243 | \ 'ar', 244 | \ 'arg', 245 | \ 'arga', 246 | \ 'argad', 247 | \ 'argadd', 248 | \ 'argd', 249 | \ 'argde', 250 | \ 'argdel', 251 | \ 'argdele', 252 | \ 'argdelet', 253 | \ 'argdelete', 254 | \ 'argdo', 255 | \ 'arge', 256 | \ 'arged', 257 | \ 'argedi', 258 | \ 'argedit', 259 | \ 'argg', 260 | \ 'arggl', 261 | \ 'argglo', 262 | \ 'argglob', 263 | \ 'arggloba', 264 | \ 'argglobal', 265 | \ 'argl', 266 | \ 'arglo', 267 | \ 'argloc', 268 | \ 'argloca', 269 | \ 'arglocal', 270 | \ 'args', 271 | \ 'argu', 272 | \ 'argum', 273 | \ 'argume', 274 | \ 'argumen', 275 | \ 'argument', 276 | \ 'as', 277 | \ 'asc', 278 | \ 'asci', 279 | \ 'ascii', 280 | \ 'au', 281 | \ 'aug', 282 | \ 'augr', 283 | \ 'augro', 284 | \ 'augrou', 285 | \ 'augroup', 286 | \ 'aut', 287 | \ 'auto', 288 | \ 'autoc', 289 | \ 'autocm', 290 | \ 'autocmd', 291 | \ 'b', 292 | \ 'bN', 293 | \ 'bNe', 294 | \ 'bNex', 295 | \ 'bNext', 296 | \ 'ba', 297 | \ 'bad', 298 | \ 'badd', 299 | \ 'bal', 300 | \ 'ball', 301 | \ 'bd', 302 | \ 'bde', 303 | \ 'bdel', 304 | \ 'bdele', 305 | \ 'bdelet', 306 | \ 'bdelete', 307 | \ 'bel', 308 | \ 'belo', 309 | \ 'below', 310 | \ 'belowr', 311 | \ 'belowri', 312 | \ 'belowrig', 313 | \ 'belowrigh', 314 | \ 'belowright', 315 | \ 'bf', 316 | \ 'bfi', 317 | \ 'bfir', 318 | \ 'bfirs', 319 | \ 'bfirst', 320 | \ 'bl', 321 | \ 'bla', 322 | \ 'blas', 323 | \ 'blast', 324 | \ 'bm', 325 | \ 'bmo', 326 | \ 'bmod', 327 | \ 'bmodi', 328 | \ 'bmodif', 329 | \ 'bmodifi', 330 | \ 'bmodifie', 331 | \ 'bmodified', 332 | \ 'bn', 333 | \ 'bne', 334 | \ 'bnex', 335 | \ 'bnext', 336 | \ 'bo', 337 | \ 'bot', 338 | \ 'botr', 339 | \ 'botri', 340 | \ 'botrig', 341 | \ 'botrigh', 342 | \ 'botright', 343 | \ 'bp', 344 | \ 'bpr', 345 | \ 'bpre', 346 | \ 'bprev', 347 | \ 'bprevi', 348 | \ 'bprevio', 349 | \ 'bpreviou', 350 | \ 'bprevious', 351 | \ 'br', 352 | \ 'bre', 353 | \ 'brea', 354 | \ 'break', 355 | \ 'breaka', 356 | \ 'breakad', 357 | \ 'breakadd', 358 | \ 'breakd', 359 | \ 'breakde', 360 | \ 'breakdel', 361 | \ 'breakl', 362 | \ 'breakli', 363 | \ 'breaklis', 364 | \ 'breaklist', 365 | \ 'brew', 366 | \ 'brewi', 367 | \ 'brewin', 368 | \ 'brewind', 369 | \ 'bro', 370 | \ 'brow', 371 | \ 'brows', 372 | \ 'browse', 373 | \ 'bu', 374 | \ 'buf', 375 | \ 'bufdo', 376 | \ 'buff', 377 | \ 'buffe', 378 | \ 'buffer', 379 | \ 'buffers', 380 | \ 'bun', 381 | \ 'bunl', 382 | \ 'bunlo', 383 | \ 'bunloa', 384 | \ 'bunload', 385 | \ 'bw', 386 | \ 'bwi', 387 | \ 'bwip', 388 | \ 'bwipe', 389 | \ 'bwipeo', 390 | \ 'bwipeou', 391 | \ 'bwipeout', 392 | \ 'c', 393 | \ 'cN', 394 | \ 'cNe', 395 | \ 'cNex', 396 | \ 'cNext', 397 | \ 'cNf', 398 | \ 'cNfi', 399 | \ 'cNfil', 400 | \ 'cNfile', 401 | \ 'cabc', 402 | \ 'cabcl', 403 | \ 'cabcle', 404 | \ 'cabclea', 405 | \ 'cabclear', 406 | \ 'cad', 407 | \ 'cadd', 408 | \ 'caddb', 409 | \ 'caddbu', 410 | \ 'caddbuf', 411 | \ 'caddbuff', 412 | \ 'caddbuffe', 413 | \ 'caddbuffer', 414 | \ 'cadde', 415 | \ 'caddex', 416 | \ 'caddexp', 417 | \ 'caddexpr', 418 | \ 'caddf', 419 | \ 'caddfi', 420 | \ 'caddfil', 421 | \ 'caddfile', 422 | \ 'cal', 423 | \ 'call', 424 | \ 'cat', 425 | \ 'catc', 426 | \ 'catch', 427 | \ 'cb', 428 | \ 'cbu', 429 | \ 'cbuf', 430 | \ 'cbuff', 431 | \ 'cbuffe', 432 | \ 'cbuffer', 433 | \ 'cc', 434 | \ 'ccl', 435 | \ 'cclo', 436 | \ 'cclos', 437 | \ 'cclose', 438 | \ 'cd', 439 | \ 'cdo', 440 | \ 'ce', 441 | \ 'cen', 442 | \ 'cent', 443 | \ 'cente', 444 | \ 'center', 445 | \ 'cex', 446 | \ 'cexp', 447 | \ 'cexpr', 448 | \ 'cf', 449 | \ 'cfdo', 450 | \ 'cfi', 451 | \ 'cfil', 452 | \ 'cfile', 453 | \ 'cfir', 454 | \ 'cfirs', 455 | \ 'cfirst', 456 | \ 'cg', 457 | \ 'cge', 458 | \ 'cget', 459 | \ 'cgetb', 460 | \ 'cgetbu', 461 | \ 'cgetbuf', 462 | \ 'cgetbuff', 463 | \ 'cgetbuffe', 464 | \ 'cgetbuffer', 465 | \ 'cgete', 466 | \ 'cgetex', 467 | \ 'cgetexp', 468 | \ 'cgetexpr', 469 | \ 'cgetf', 470 | \ 'cgetfi', 471 | \ 'cgetfil', 472 | \ 'cgetfile', 473 | \ 'ch', 474 | \ 'cha', 475 | \ 'chan', 476 | \ 'chang', 477 | \ 'change', 478 | \ 'changes', 479 | \ 'chd', 480 | \ 'chdi', 481 | \ 'chdir', 482 | \ 'che', 483 | \ 'chec', 484 | \ 'check', 485 | \ 'checkp', 486 | \ 'checkpa', 487 | \ 'checkpat', 488 | \ 'checkpath', 489 | \ 'checkt', 490 | \ 'checkti', 491 | \ 'checktim', 492 | \ 'checktime', 493 | \ 'cl', 494 | \ 'cla', 495 | \ 'clas', 496 | \ 'clast', 497 | \ 'cli', 498 | \ 'clis', 499 | \ 'clist', 500 | \ 'clo', 501 | \ 'clos', 502 | \ 'close', 503 | \ 'cmapc', 504 | \ 'cmapcl', 505 | \ 'cmapcle', 506 | \ 'cmapclea', 507 | \ 'cmapclear', 508 | \ 'cn', 509 | \ 'cne', 510 | \ 'cnew', 511 | \ 'cnewe', 512 | \ 'cnewer', 513 | \ 'cnex', 514 | \ 'cnext', 515 | \ 'cnf', 516 | \ 'cnfi', 517 | \ 'cnfil', 518 | \ 'cnfile', 519 | \ 'co', 520 | \ 'col', 521 | \ 'cold', 522 | \ 'colde', 523 | \ 'colder', 524 | \ 'colo', 525 | \ 'color', 526 | \ 'colors', 527 | \ 'colorsc', 528 | \ 'colorsch', 529 | \ 'colorsche', 530 | \ 'colorschem', 531 | \ 'colorscheme', 532 | \ 'com', 533 | \ 'comc', 534 | \ 'comcl', 535 | \ 'comcle', 536 | \ 'comclea', 537 | \ 'comclear', 538 | \ 'comp', 539 | \ 'compi', 540 | \ 'compil', 541 | \ 'compile', 542 | \ 'compiler', 543 | \ 'con', 544 | \ 'conf', 545 | \ 'confi', 546 | \ 'confir', 547 | \ 'confirm', 548 | \ 'cont', 549 | \ 'conti', 550 | \ 'contin', 551 | \ 'continu', 552 | \ 'continue', 553 | \ 'cop', 554 | \ 'cope', 555 | \ 'copen', 556 | \ 'copy', 557 | \ 'cp', 558 | \ 'cpf', 559 | \ 'cpfi', 560 | \ 'cpfil', 561 | \ 'cpfile', 562 | \ 'cpr', 563 | \ 'cpre', 564 | \ 'cprev', 565 | \ 'cprevi', 566 | \ 'cprevio', 567 | \ 'cpreviou', 568 | \ 'cprevious', 569 | \ 'cq', 570 | \ 'cqu', 571 | \ 'cqui', 572 | \ 'cquit', 573 | \ 'cr', 574 | \ 'cre', 575 | \ 'crew', 576 | \ 'crewi', 577 | \ 'crewin', 578 | \ 'crewind', 579 | \ 'cs', 580 | \ 'cscope', 581 | \ 'cstag', 582 | \ 'cuna', 583 | \ 'cunab', 584 | \ 'cunabb', 585 | \ 'cunabbr', 586 | \ 'cunabbre', 587 | \ 'cunabbrev', 588 | \ 'cw', 589 | \ 'cwi', 590 | \ 'cwin', 591 | \ 'cwind', 592 | \ 'cwindo', 593 | \ 'cwindow', 594 | \ 'd', 595 | \ 'de', 596 | \ 'debug', 597 | \ 'debugg', 598 | \ 'debuggr', 599 | \ 'debuggre', 600 | \ 'debuggree', 601 | \ 'debuggreed', 602 | \ 'debuggreedy', 603 | \ 'del', 604 | \ 'delc', 605 | \ 'delco', 606 | \ 'delcom', 607 | \ 'delcomm', 608 | \ 'delcomma', 609 | \ 'delcomman', 610 | \ 'delcommand', 611 | \ 'dele', 612 | \ 'delel', 613 | \ 'delep', 614 | \ 'delet', 615 | \ 'delete', 616 | \ 'deletel', 617 | \ 'deletep', 618 | \ 'deletl', 619 | \ 'deletp', 620 | \ 'delf', 621 | \ 'delfu', 622 | \ 'delfun', 623 | \ 'delfunc', 624 | \ 'delfunct', 625 | \ 'delfuncti', 626 | \ 'delfunctio', 627 | \ 'delfunction', 628 | \ 'dell', 629 | \ 'delm', 630 | \ 'delma', 631 | \ 'delmar', 632 | \ 'delmark', 633 | \ 'delmarks', 634 | \ 'delp', 635 | \ 'dep', 636 | \ 'di', 637 | \ 'diffg', 638 | \ 'diffge', 639 | \ 'diffget', 640 | \ 'diffo', 641 | \ 'diffof', 642 | \ 'diffoff', 643 | \ 'diffp', 644 | \ 'diffpa', 645 | \ 'diffpat', 646 | \ 'diffpatc', 647 | \ 'diffpatch', 648 | \ 'diffpu', 649 | \ 'diffput', 650 | \ 'diffs', 651 | \ 'diffsp', 652 | \ 'diffspl', 653 | \ 'diffspli', 654 | \ 'diffsplit', 655 | \ 'difft', 656 | \ 'diffth', 657 | \ 'diffthi', 658 | \ 'diffthis', 659 | \ 'diffu', 660 | \ 'diffup', 661 | \ 'diffupd', 662 | \ 'diffupda', 663 | \ 'diffupdat', 664 | \ 'diffupdate', 665 | \ 'dig', 666 | \ 'digr', 667 | \ 'digra', 668 | \ 'digrap', 669 | \ 'digraph', 670 | \ 'digraphs', 671 | \ 'dir', 672 | \ 'dis', 673 | \ 'disp', 674 | \ 'displ', 675 | \ 'displa', 676 | \ 'display', 677 | \ 'dj', 678 | \ 'dju', 679 | \ 'djum', 680 | \ 'djump', 681 | \ 'dl', 682 | \ 'dli', 683 | \ 'dlis', 684 | \ 'dlist', 685 | \ 'do', 686 | \ 'doa', 687 | \ 'doau', 688 | \ 'doaut', 689 | \ 'doauto', 690 | \ 'doautoa', 691 | \ 'doautoal', 692 | \ 'doautoall', 693 | \ 'doautoc', 694 | \ 'doautocm', 695 | \ 'doautocmd', 696 | \ 'dp', 697 | \ 'dr', 698 | \ 'dro', 699 | \ 'drop', 700 | \ 'ds', 701 | \ 'dse', 702 | \ 'dsea', 703 | \ 'dsear', 704 | \ 'dsearc', 705 | \ 'dsearch', 706 | \ 'dsp', 707 | \ 'dspl', 708 | \ 'dspli', 709 | \ 'dsplit', 710 | \ 'e', 711 | \ 'ea', 712 | \ 'earlier', 713 | \ 'ec', 714 | \ 'ech', 715 | \ 'echo', 716 | \ 'echoe', 717 | \ 'echoer', 718 | \ 'echoerr', 719 | \ 'echom', 720 | \ 'echoms', 721 | \ 'echomsg', 722 | \ 'echon', 723 | \ 'ed', 724 | \ 'edi', 725 | \ 'edit', 726 | \ 'el', 727 | \ 'els', 728 | \ 'else', 729 | \ 'elsei', 730 | \ 'elseif', 731 | \ 'em', 732 | \ 'eme', 733 | \ 'emen', 734 | \ 'emenu', 735 | \ 'en', 736 | \ 'end', 737 | \ 'endf', 738 | \ 'endfo', 739 | \ 'endfor', 740 | \ 'endfu', 741 | \ 'endfun', 742 | \ 'endfunc', 743 | \ 'endfunct', 744 | \ 'endfuncti', 745 | \ 'endfunctio', 746 | \ 'endfunction', 747 | \ 'endi', 748 | \ 'endif', 749 | \ 'endt', 750 | \ 'endtr', 751 | \ 'endtry', 752 | \ 'endw', 753 | \ 'endwh', 754 | \ 'endwhi', 755 | \ 'endwhil', 756 | \ 'endwhile', 757 | \ 'ene', 758 | \ 'enew', 759 | \ 'ex', 760 | \ 'exe', 761 | \ 'exec', 762 | \ 'execu', 763 | \ 'execut', 764 | \ 'execute', 765 | \ 'exi', 766 | \ 'exit', 767 | \ 'exu', 768 | \ 'exus', 769 | \ 'exusa', 770 | \ 'exusag', 771 | \ 'exusage', 772 | \ 'f', 773 | \ 'fi', 774 | \ 'fil', 775 | \ 'file', 776 | \ 'files', 777 | \ 'filet', 778 | \ 'filetype', 779 | \ 'fin', 780 | \ 'fina', 781 | \ 'final', 782 | \ 'finall', 783 | \ 'finally', 784 | \ 'find', 785 | \ 'fini', 786 | \ 'finis', 787 | \ 'finish', 788 | \ 'fir', 789 | \ 'firs', 790 | \ 'first', 791 | \ 'fix', 792 | \ 'fixd', 793 | \ 'fixde', 794 | \ 'fixdel', 795 | \ 'fo', 796 | \ 'fol', 797 | \ 'fold', 798 | \ 'foldc', 799 | \ 'foldcl', 800 | \ 'foldclo', 801 | \ 'foldclos', 802 | \ 'foldclose', 803 | \ 'foldd', 804 | \ 'folddo', 805 | \ 'folddoc', 806 | \ 'folddocl', 807 | \ 'folddoclo', 808 | \ 'folddoclos', 809 | \ 'folddoclose', 810 | \ 'folddoclosed', 811 | \ 'folddoo', 812 | \ 'folddoop', 813 | \ 'folddoope', 814 | \ 'folddoopen', 815 | \ 'foldo', 816 | \ 'foldop', 817 | \ 'foldope', 818 | \ 'foldopen', 819 | \ 'for', 820 | \ 'fu', 821 | \ 'fun', 822 | \ 'func', 823 | \ 'funct', 824 | \ 'functi', 825 | \ 'functio', 826 | \ 'function', 827 | \ 'g', 828 | \ 'go', 829 | \ 'got', 830 | \ 'goto', 831 | \ 'gr', 832 | \ 'gre', 833 | \ 'grep', 834 | \ 'grepa', 835 | \ 'grepad', 836 | \ 'grepadd', 837 | \ 'gui', 838 | \ 'gvim', 839 | \ 'h', 840 | \ 'ha', 841 | \ 'har', 842 | \ 'hard', 843 | \ 'hardc', 844 | \ 'hardco', 845 | \ 'hardcop', 846 | \ 'hardcopy', 847 | \ 'he', 848 | \ 'hel', 849 | \ 'help', 850 | \ 'helpc', 851 | \ 'helpcl', 852 | \ 'helpclo', 853 | \ 'helpclos', 854 | \ 'helpclose', 855 | \ 'helpf', 856 | \ 'helpfi', 857 | \ 'helpfin', 858 | \ 'helpfind', 859 | \ 'helpg', 860 | \ 'helpgr', 861 | \ 'helpgre', 862 | \ 'helpgrep', 863 | \ 'helpt', 864 | \ 'helpta', 865 | \ 'helptag', 866 | \ 'helptags', 867 | \ 'hi', 868 | \ 'hid', 869 | \ 'hide', 870 | \ 'his', 871 | \ 'hist', 872 | \ 'histo', 873 | \ 'histor', 874 | \ 'history', 875 | \ 'i', 876 | \ 'ia', 877 | \ 'iabc', 878 | \ 'iabcl', 879 | \ 'iabcle', 880 | \ 'iabclea', 881 | \ 'iabclear', 882 | \ 'if', 883 | \ 'ij', 884 | \ 'iju', 885 | \ 'ijum', 886 | \ 'ijump', 887 | \ 'il', 888 | \ 'ili', 889 | \ 'ilis', 890 | \ 'ilist', 891 | \ 'imapc', 892 | \ 'imapcl', 893 | \ 'imapcle', 894 | \ 'imapclea', 895 | \ 'imapclear', 896 | \ 'in', 897 | \ 'intro', 898 | \ 'is', 899 | \ 'ise', 900 | \ 'isea', 901 | \ 'isear', 902 | \ 'isearc', 903 | \ 'isearch', 904 | \ 'isp', 905 | \ 'ispl', 906 | \ 'ispli', 907 | \ 'isplit', 908 | \ 'iuna', 909 | \ 'iunab', 910 | \ 'iunabb', 911 | \ 'iunabbr', 912 | \ 'iunabbre', 913 | \ 'iunabbrev', 914 | \ 'j', 915 | \ 'jo', 916 | \ 'joi', 917 | \ 'join', 918 | \ 'ju', 919 | \ 'jum', 920 | \ 'jump', 921 | \ 'jumps', 922 | \ 'k', 923 | \ 'kee', 924 | \ 'keep', 925 | \ 'keepa', 926 | \ 'keepalt', 927 | \ 'keepj', 928 | \ 'keepju', 929 | \ 'keepjum', 930 | \ 'keepjump', 931 | \ 'keepjumps', 932 | \ 'keepm', 933 | \ 'keepma', 934 | \ 'keepmar', 935 | \ 'keepmark', 936 | \ 'keepmarks', 937 | \ 'keepp', 938 | \ 'keeppa', 939 | \ 'keeppat', 940 | \ 'keeppatt', 941 | \ 'keeppatte', 942 | \ 'keeppatter', 943 | \ 'keeppattern', 944 | \ 'keeppatterns', 945 | \ 'l', 946 | \ 'lN', 947 | \ 'lNe', 948 | \ 'lNex', 949 | \ 'lNext', 950 | \ 'lNf', 951 | \ 'lNfi', 952 | \ 'lNfil', 953 | \ 'lNfile', 954 | \ 'la', 955 | \ 'lad', 956 | \ 'ladd', 957 | \ 'laddb', 958 | \ 'laddbu', 959 | \ 'laddbuf', 960 | \ 'laddbuff', 961 | \ 'laddbuffe', 962 | \ 'laddbuffer', 963 | \ 'ladde', 964 | \ 'laddex', 965 | \ 'laddexp', 966 | \ 'laddexpr', 967 | \ 'laddf', 968 | \ 'laddfi', 969 | \ 'laddfil', 970 | \ 'laddfile', 971 | \ 'lan', 972 | \ 'lang', 973 | \ 'langu', 974 | \ 'langua', 975 | \ 'languag', 976 | \ 'language', 977 | \ 'las', 978 | \ 'last', 979 | \ 'lat', 980 | \ 'later', 981 | \ 'lb', 982 | \ 'lbu', 983 | \ 'lbuf', 984 | \ 'lbuff', 985 | \ 'lbuffe', 986 | \ 'lbuffer', 987 | \ 'lc', 988 | \ 'lcd', 989 | \ 'lch', 990 | \ 'lchd', 991 | \ 'lchdi', 992 | \ 'lchdir', 993 | \ 'lcl', 994 | \ 'lclo', 995 | \ 'lclos', 996 | \ 'lclose', 997 | \ 'lcs', 998 | \ 'lcscope', 999 | \ 'ld', 1000 | \ 'ldo', 1001 | \ 'le', 1002 | \ 'lef', 1003 | \ 'left', 1004 | \ 'lefta', 1005 | \ 'leftab', 1006 | \ 'leftabo', 1007 | \ 'leftabov', 1008 | \ 'leftabove', 1009 | \ 'let', 1010 | \ 'lex', 1011 | \ 'lexp', 1012 | \ 'lexpr', 1013 | \ 'lf', 1014 | \ 'lfdo', 1015 | \ 'lfi', 1016 | \ 'lfil', 1017 | \ 'lfile', 1018 | \ 'lfir', 1019 | \ 'lfirs', 1020 | \ 'lfirst', 1021 | \ 'lg', 1022 | \ 'lge', 1023 | \ 'lget', 1024 | \ 'lgetb', 1025 | \ 'lgetbu', 1026 | \ 'lgetbuf', 1027 | \ 'lgetbuff', 1028 | \ 'lgetbuffe', 1029 | \ 'lgetbuffer', 1030 | \ 'lgete', 1031 | \ 'lgetex', 1032 | \ 'lgetexp', 1033 | \ 'lgetexpr', 1034 | \ 'lgetf', 1035 | \ 'lgetfi', 1036 | \ 'lgetfil', 1037 | \ 'lgetfile', 1038 | \ 'lgr', 1039 | \ 'lgre', 1040 | \ 'lgrep', 1041 | \ 'lgrepa', 1042 | \ 'lgrepad', 1043 | \ 'lgrepadd', 1044 | \ 'lh', 1045 | \ 'lhe', 1046 | \ 'lhel', 1047 | \ 'lhelp', 1048 | \ 'lhelpg', 1049 | \ 'lhelpgr', 1050 | \ 'lhelpgre', 1051 | \ 'lhelpgrep', 1052 | \ 'li', 1053 | \ 'lis', 1054 | \ 'list', 1055 | \ 'll', 1056 | \ 'lla', 1057 | \ 'llas', 1058 | \ 'llast', 1059 | \ 'lli', 1060 | \ 'llis', 1061 | \ 'llist', 1062 | \ 'lmak', 1063 | \ 'lmake', 1064 | \ 'lmapc', 1065 | \ 'lmapcl', 1066 | \ 'lmapcle', 1067 | \ 'lmapclea', 1068 | \ 'lmapclear', 1069 | \ 'lne', 1070 | \ 'lnew', 1071 | \ 'lnewe', 1072 | \ 'lnewer', 1073 | \ 'lnex', 1074 | \ 'lnext', 1075 | \ 'lnf', 1076 | \ 'lnfi', 1077 | \ 'lnfil', 1078 | \ 'lnfile', 1079 | \ 'lo', 1080 | \ 'loa', 1081 | \ 'load', 1082 | \ 'loadk', 1083 | \ 'loadkeymap', 1084 | \ 'loadv', 1085 | \ 'loadvi', 1086 | \ 'loadvie', 1087 | \ 'loadview', 1088 | \ 'loc', 1089 | \ 'lock', 1090 | \ 'lockm', 1091 | \ 'lockma', 1092 | \ 'lockmar', 1093 | \ 'lockmark', 1094 | \ 'lockmarks', 1095 | \ 'lockv', 1096 | \ 'lockva', 1097 | \ 'lockvar', 1098 | \ 'lol', 1099 | \ 'lold', 1100 | \ 'lolde', 1101 | \ 'lolder', 1102 | \ 'lop', 1103 | \ 'lope', 1104 | \ 'lopen', 1105 | \ 'lp', 1106 | \ 'lpf', 1107 | \ 'lpfi', 1108 | \ 'lpfil', 1109 | \ 'lpfile', 1110 | \ 'lpr', 1111 | \ 'lpre', 1112 | \ 'lprev', 1113 | \ 'lprevi', 1114 | \ 'lprevio', 1115 | \ 'lpreviou', 1116 | \ 'lprevious', 1117 | \ 'lr', 1118 | \ 'lre', 1119 | \ 'lrew', 1120 | \ 'lrewi', 1121 | \ 'lrewin', 1122 | \ 'lrewind', 1123 | \ 'ls', 1124 | \ 'lt', 1125 | \ 'lta', 1126 | \ 'ltag', 1127 | \ 'lua', 1128 | \ 'luado', 1129 | \ 'luafile', 1130 | \ 'lv', 1131 | \ 'lvi', 1132 | \ 'lvim', 1133 | \ 'lvimg', 1134 | \ 'lvimgr', 1135 | \ 'lvimgre', 1136 | \ 'lvimgrep', 1137 | \ 'lvimgrepa', 1138 | \ 'lvimgrepad', 1139 | \ 'lvimgrepadd', 1140 | \ 'lw', 1141 | \ 'lwi', 1142 | \ 'lwin', 1143 | \ 'lwind', 1144 | \ 'lwindo', 1145 | \ 'lwindow', 1146 | \ 'm', 1147 | \ 'ma', 1148 | \ 'mak', 1149 | \ 'make', 1150 | \ 'mar', 1151 | \ 'mark', 1152 | \ 'marks', 1153 | \ 'mat', 1154 | \ 'matc', 1155 | \ 'match', 1156 | \ 'menut', 1157 | \ 'menutr', 1158 | \ 'menutra', 1159 | \ 'menutran', 1160 | \ 'menutrans', 1161 | \ 'menutransl', 1162 | \ 'menutransla', 1163 | \ 'menutranslat', 1164 | \ 'menutranslate', 1165 | \ 'mes', 1166 | \ 'messages', 1167 | \ 'mk', 1168 | \ 'mke', 1169 | \ 'mkex', 1170 | \ 'mkexr', 1171 | \ 'mkexrc', 1172 | \ 'mks', 1173 | \ 'mkse', 1174 | \ 'mkses', 1175 | \ 'mksess', 1176 | \ 'mksessi', 1177 | \ 'mksessio', 1178 | \ 'mksession', 1179 | \ 'mksp', 1180 | \ 'mkspe', 1181 | \ 'mkspel', 1182 | \ 'mkspell', 1183 | \ 'mkv', 1184 | \ 'mkvi', 1185 | \ 'mkvie', 1186 | \ 'mkview', 1187 | \ 'mkvim', 1188 | \ 'mkvimr', 1189 | \ 'mkvimrc', 1190 | \ 'mo', 1191 | \ 'mod', 1192 | \ 'mode', 1193 | \ 'mov', 1194 | \ 'move', 1195 | \ 'mz', 1196 | \ 'mzf', 1197 | \ 'mzfi', 1198 | \ 'mzfil', 1199 | \ 'mzfile', 1200 | \ 'mzs', 1201 | \ 'mzsc', 1202 | \ 'mzsch', 1203 | \ 'mzsche', 1204 | \ 'mzschem', 1205 | \ 'mzscheme', 1206 | \ 'n', 1207 | \ 'nb', 1208 | \ 'nbc', 1209 | \ 'nbcl', 1210 | \ 'nbclo', 1211 | \ 'nbclos', 1212 | \ 'nbclose', 1213 | \ 'nbk', 1214 | \ 'nbke', 1215 | \ 'nbkey', 1216 | \ 'nbs', 1217 | \ 'nbst', 1218 | \ 'nbsta', 1219 | \ 'nbstar', 1220 | \ 'nbstart', 1221 | \ 'ne', 1222 | \ 'new', 1223 | \ 'nex', 1224 | \ 'next', 1225 | \ 'nmapc', 1226 | \ 'nmapcl', 1227 | \ 'nmapcle', 1228 | \ 'nmapclea', 1229 | \ 'nmapclear', 1230 | \ 'noa', 1231 | \ 'noautocmd', 1232 | \ 'noh', 1233 | \ 'nohl', 1234 | \ 'nohls', 1235 | \ 'nohlse', 1236 | \ 'nohlsea', 1237 | \ 'nohlsear', 1238 | \ 'nohlsearc', 1239 | \ 'nohlsearch', 1240 | \ 'noswap', 1241 | \ 'noswapf', 1242 | \ 'noswapfi', 1243 | \ 'noswapfil', 1244 | \ 'noswapfile', 1245 | \ 'nu', 1246 | \ 'num', 1247 | \ 'numb', 1248 | \ 'numbe', 1249 | \ 'number', 1250 | \ 'o', 1251 | \ 'ol', 1252 | \ 'old', 1253 | \ 'oldf', 1254 | \ 'oldfi', 1255 | \ 'oldfil', 1256 | \ 'oldfile', 1257 | \ 'oldfiles', 1258 | \ 'omapc', 1259 | \ 'omapcl', 1260 | \ 'omapcle', 1261 | \ 'omapclea', 1262 | \ 'omapclear', 1263 | \ 'on', 1264 | \ 'onl', 1265 | \ 'only', 1266 | \ 'op', 1267 | \ 'ope', 1268 | \ 'open', 1269 | \ 'opt', 1270 | \ 'opti', 1271 | \ 'optio', 1272 | \ 'option', 1273 | \ 'options', 1274 | \ 'ownsyntax', 1275 | \ 'p', 1276 | \ 'pc', 1277 | \ 'pcl', 1278 | \ 'pclo', 1279 | \ 'pclos', 1280 | \ 'pclose', 1281 | \ 'pe', 1282 | \ 'ped', 1283 | \ 'pedi', 1284 | \ 'pedit', 1285 | \ 'per', 1286 | \ 'perl', 1287 | \ 'perld', 1288 | \ 'perldo', 1289 | \ 'po', 1290 | \ 'pop', 1291 | \ 'popu', 1292 | \ 'popup', 1293 | \ 'pp', 1294 | \ 'ppo', 1295 | \ 'ppop', 1296 | \ 'pr', 1297 | \ 'pre', 1298 | \ 'pres', 1299 | \ 'prese', 1300 | \ 'preser', 1301 | \ 'preserv', 1302 | \ 'preserve', 1303 | \ 'prev', 1304 | \ 'previ', 1305 | \ 'previo', 1306 | \ 'previou', 1307 | \ 'previous', 1308 | \ 'pri', 1309 | \ 'prin', 1310 | \ 'print', 1311 | \ 'pro', 1312 | \ 'prof', 1313 | \ 'profd', 1314 | \ 'profde', 1315 | \ 'profdel', 1316 | \ 'profi', 1317 | \ 'profil', 1318 | \ 'profile', 1319 | \ 'promptf', 1320 | \ 'promptfi', 1321 | \ 'promptfin', 1322 | \ 'promptfind', 1323 | \ 'promptr', 1324 | \ 'promptre', 1325 | \ 'promptrep', 1326 | \ 'promptrepl', 1327 | \ 'ps', 1328 | \ 'pse', 1329 | \ 'psea', 1330 | \ 'psear', 1331 | \ 'psearc', 1332 | \ 'psearch', 1333 | \ 'ptN', 1334 | \ 'ptNe', 1335 | \ 'ptNex', 1336 | \ 'ptNext', 1337 | \ 'pta', 1338 | \ 'ptag', 1339 | \ 'ptf', 1340 | \ 'ptfi', 1341 | \ 'ptfir', 1342 | \ 'ptfirs', 1343 | \ 'ptfirst', 1344 | \ 'ptj', 1345 | \ 'ptju', 1346 | \ 'ptjum', 1347 | \ 'ptjump', 1348 | \ 'ptl', 1349 | \ 'ptla', 1350 | \ 'ptlas', 1351 | \ 'ptlast', 1352 | \ 'ptn', 1353 | \ 'ptne', 1354 | \ 'ptnex', 1355 | \ 'ptnext', 1356 | \ 'ptp', 1357 | \ 'ptpr', 1358 | \ 'ptpre', 1359 | \ 'ptprev', 1360 | \ 'ptprevi', 1361 | \ 'ptprevio', 1362 | \ 'ptpreviou', 1363 | \ 'ptprevious', 1364 | \ 'ptr', 1365 | \ 'ptre', 1366 | \ 'ptrew', 1367 | \ 'ptrewi', 1368 | \ 'ptrewin', 1369 | \ 'ptrewind', 1370 | \ 'pts', 1371 | \ 'ptse', 1372 | \ 'ptsel', 1373 | \ 'ptsele', 1374 | \ 'ptselec', 1375 | \ 'ptselect', 1376 | \ 'pu', 1377 | \ 'put', 1378 | \ 'pw', 1379 | \ 'pwd', 1380 | \ 'py', 1381 | \ 'py3', 1382 | \ 'py3do', 1383 | \ 'pydo', 1384 | \ 'pyf', 1385 | \ 'pyfi', 1386 | \ 'pyfil', 1387 | \ 'pyfile', 1388 | \ 'pyt', 1389 | \ 'pyth', 1390 | \ 'pytho', 1391 | \ 'python', 1392 | \ 'python3', 1393 | \ 'q', 1394 | \ 'qa', 1395 | \ 'qal', 1396 | \ 'qall', 1397 | \ 'qu', 1398 | \ 'qui', 1399 | \ 'quit', 1400 | \ 'quita', 1401 | \ 'quital', 1402 | \ 'quitall', 1403 | \ 'r', 1404 | \ 're', 1405 | \ 'rea', 1406 | \ 'read', 1407 | \ 'rec', 1408 | \ 'reco', 1409 | \ 'recov', 1410 | \ 'recove', 1411 | \ 'recover', 1412 | \ 'red', 1413 | \ 'redi', 1414 | \ 'redir', 1415 | \ 'redo', 1416 | \ 'redr', 1417 | \ 'redra', 1418 | \ 'redraw', 1419 | \ 'redraws', 1420 | \ 'redrawst', 1421 | \ 'redrawsta', 1422 | \ 'redrawstat', 1423 | \ 'redrawstatu', 1424 | \ 'redrawstatus', 1425 | \ 'reg', 1426 | \ 'regi', 1427 | \ 'regis', 1428 | \ 'regist', 1429 | \ 'registe', 1430 | \ 'register', 1431 | \ 'registers', 1432 | \ 'res', 1433 | \ 'resi', 1434 | \ 'resiz', 1435 | \ 'resize', 1436 | \ 'ret', 1437 | \ 'reta', 1438 | \ 'retab', 1439 | \ 'retu', 1440 | \ 'retur', 1441 | \ 'return', 1442 | \ 'rew', 1443 | \ 'rewi', 1444 | \ 'rewin', 1445 | \ 'rewind', 1446 | \ 'ri', 1447 | \ 'rig', 1448 | \ 'righ', 1449 | \ 'right', 1450 | \ 'rightb', 1451 | \ 'rightbe', 1452 | \ 'rightbel', 1453 | \ 'rightbelo', 1454 | \ 'rightbelow', 1455 | \ 'ru', 1456 | \ 'rub', 1457 | \ 'ruby', 1458 | \ 'rubyd', 1459 | \ 'rubydo', 1460 | \ 'rubyf', 1461 | \ 'rubyfi', 1462 | \ 'rubyfil', 1463 | \ 'rubyfile', 1464 | \ 'run', 1465 | \ 'rundo', 1466 | \ 'runt', 1467 | \ 'runti', 1468 | \ 'runtim', 1469 | \ 'runtime', 1470 | \ 'rv', 1471 | \ 'rvi', 1472 | \ 'rvim', 1473 | \ 'rvimi', 1474 | \ 'rvimin', 1475 | \ 'rviminf', 1476 | \ 'rviminfo', 1477 | \ 'sN', 1478 | \ 'sNe', 1479 | \ 'sNex', 1480 | \ 'sNext', 1481 | \ 'sa', 1482 | \ 'sal', 1483 | \ 'sall', 1484 | \ 'san', 1485 | \ 'sand', 1486 | \ 'sandb', 1487 | \ 'sandbo', 1488 | \ 'sandbox', 1489 | \ 'sar', 1490 | \ 'sarg', 1491 | \ 'sargu', 1492 | \ 'sargum', 1493 | \ 'sargume', 1494 | \ 'sargumen', 1495 | \ 'sargument', 1496 | \ 'sav', 1497 | \ 'save', 1498 | \ 'savea', 1499 | \ 'saveas', 1500 | \ 'sb', 1501 | \ 'sbN', 1502 | \ 'sbNe', 1503 | \ 'sbNex', 1504 | \ 'sbNext', 1505 | \ 'sba', 1506 | \ 'sbal', 1507 | \ 'sball', 1508 | \ 'sbf', 1509 | \ 'sbfi', 1510 | \ 'sbfir', 1511 | \ 'sbfirs', 1512 | \ 'sbfirst', 1513 | \ 'sbl', 1514 | \ 'sbla', 1515 | \ 'sblas', 1516 | \ 'sblast', 1517 | \ 'sbm', 1518 | \ 'sbmo', 1519 | \ 'sbmod', 1520 | \ 'sbmodi', 1521 | \ 'sbmodif', 1522 | \ 'sbmodifi', 1523 | \ 'sbmodifie', 1524 | \ 'sbmodified', 1525 | \ 'sbn', 1526 | \ 'sbne', 1527 | \ 'sbnex', 1528 | \ 'sbnext', 1529 | \ 'sbp', 1530 | \ 'sbpr', 1531 | \ 'sbpre', 1532 | \ 'sbprev', 1533 | \ 'sbprevi', 1534 | \ 'sbprevio', 1535 | \ 'sbpreviou', 1536 | \ 'sbprevious', 1537 | \ 'sbr', 1538 | \ 'sbre', 1539 | \ 'sbrew', 1540 | \ 'sbrewi', 1541 | \ 'sbrewin', 1542 | \ 'sbrewind', 1543 | \ 'sbu', 1544 | \ 'sbuf', 1545 | \ 'sbuff', 1546 | \ 'sbuffe', 1547 | \ 'sbuffer', 1548 | \ 'scrip', 1549 | \ 'script', 1550 | \ 'scripte', 1551 | \ 'scripten', 1552 | \ 'scriptenc', 1553 | \ 'scriptenco', 1554 | \ 'scriptencod', 1555 | \ 'scriptencodi', 1556 | \ 'scriptencodin', 1557 | \ 'scriptencoding', 1558 | \ 'scriptn', 1559 | \ 'scriptna', 1560 | \ 'scriptnam', 1561 | \ 'scriptname', 1562 | \ 'scriptnames', 1563 | \ 'scs', 1564 | \ 'scscope', 1565 | \ 'se', 1566 | \ 'set', 1567 | \ 'setf', 1568 | \ 'setfi', 1569 | \ 'setfil', 1570 | \ 'setfile', 1571 | \ 'setfilet', 1572 | \ 'setfilety', 1573 | \ 'setfiletyp', 1574 | \ 'setfiletype', 1575 | \ 'setg', 1576 | \ 'setgl', 1577 | \ 'setglo', 1578 | \ 'setglob', 1579 | \ 'setgloba', 1580 | \ 'setglobal', 1581 | \ 'setl', 1582 | \ 'setlo', 1583 | \ 'setloc', 1584 | \ 'setloca', 1585 | \ 'setlocal', 1586 | \ 'sf', 1587 | \ 'sfi', 1588 | \ 'sfin', 1589 | \ 'sfind', 1590 | \ 'sfir', 1591 | \ 'sfirs', 1592 | \ 'sfirst', 1593 | \ 'sh', 1594 | \ 'she', 1595 | \ 'shel', 1596 | \ 'shell', 1597 | \ 'si', 1598 | \ 'sig', 1599 | \ 'sign', 1600 | \ 'sil', 1601 | \ 'sile', 1602 | \ 'silen', 1603 | \ 'silent', 1604 | \ 'sim', 1605 | \ 'sima', 1606 | \ 'simal', 1607 | \ 'simalt', 1608 | \ 'sl', 1609 | \ 'sla', 1610 | \ 'slas', 1611 | \ 'slast', 1612 | \ 'sle', 1613 | \ 'slee', 1614 | \ 'sleep', 1615 | \ 'sm', 1616 | \ 'sma', 1617 | \ 'smag', 1618 | \ 'smagi', 1619 | \ 'smagic', 1620 | \ 'smap', 1621 | \ 'sme', 1622 | \ 'smenu', 1623 | \ 'sn', 1624 | \ 'sne', 1625 | \ 'snex', 1626 | \ 'snext', 1627 | \ 'sni', 1628 | \ 'snif', 1629 | \ 'sniff', 1630 | \ 'sno', 1631 | \ 'snom', 1632 | \ 'snoma', 1633 | \ 'snomag', 1634 | \ 'snomagi', 1635 | \ 'snomagic', 1636 | \ 'snoreme', 1637 | \ 'snoremenu', 1638 | \ 'so', 1639 | \ 'sor', 1640 | \ 'sort', 1641 | \ 'sou', 1642 | \ 'sour', 1643 | \ 'sourc', 1644 | \ 'source', 1645 | \ 'sp', 1646 | \ 'spe', 1647 | \ 'spel', 1648 | \ 'spell', 1649 | \ 'spelld', 1650 | \ 'spelldu', 1651 | \ 'spelldum', 1652 | \ 'spelldump', 1653 | \ 'spellg', 1654 | \ 'spellgo', 1655 | \ 'spellgoo', 1656 | \ 'spellgood', 1657 | \ 'spelli', 1658 | \ 'spellin', 1659 | \ 'spellinf', 1660 | \ 'spellinfo', 1661 | \ 'spellr', 1662 | \ 'spellre', 1663 | \ 'spellrep', 1664 | \ 'spellrepa', 1665 | \ 'spellrepal', 1666 | \ 'spellrepall', 1667 | \ 'spellu', 1668 | \ 'spellun', 1669 | \ 'spellund', 1670 | \ 'spellundo', 1671 | \ 'spellw', 1672 | \ 'spellwr', 1673 | \ 'spellwro', 1674 | \ 'spellwron', 1675 | \ 'spellwrong', 1676 | \ 'spl', 1677 | \ 'spli', 1678 | \ 'split', 1679 | \ 'spr', 1680 | \ 'spre', 1681 | \ 'sprev', 1682 | \ 'sprevi', 1683 | \ 'sprevio', 1684 | \ 'spreviou', 1685 | \ 'sprevious', 1686 | \ 'sre', 1687 | \ 'srew', 1688 | \ 'srewi', 1689 | \ 'srewin', 1690 | \ 'srewind', 1691 | \ 'st', 1692 | \ 'sta', 1693 | \ 'stag', 1694 | \ 'star', 1695 | \ 'start', 1696 | \ 'startg', 1697 | \ 'startgr', 1698 | \ 'startgre', 1699 | \ 'startgrep', 1700 | \ 'startgrepl', 1701 | \ 'startgrepla', 1702 | \ 'startgreplac', 1703 | \ 'startgreplace', 1704 | \ 'starti', 1705 | \ 'startin', 1706 | \ 'startins', 1707 | \ 'startinse', 1708 | \ 'startinser', 1709 | \ 'startinsert', 1710 | \ 'startr', 1711 | \ 'startre', 1712 | \ 'startrep', 1713 | \ 'startrepl', 1714 | \ 'startrepla', 1715 | \ 'startreplac', 1716 | \ 'startreplace', 1717 | \ 'stj', 1718 | \ 'stju', 1719 | \ 'stjum', 1720 | \ 'stjump', 1721 | \ 'sto', 1722 | \ 'stop', 1723 | \ 'stopi', 1724 | \ 'stopin', 1725 | \ 'stopins', 1726 | \ 'stopinse', 1727 | \ 'stopinser', 1728 | \ 'stopinsert', 1729 | \ 'sts', 1730 | \ 'stse', 1731 | \ 'stsel', 1732 | \ 'stsele', 1733 | \ 'stselec', 1734 | \ 'stselect', 1735 | \ 'sun', 1736 | \ 'sunh', 1737 | \ 'sunhi', 1738 | \ 'sunhid', 1739 | \ 'sunhide', 1740 | \ 'sunme', 1741 | \ 'sunmenu', 1742 | \ 'sus', 1743 | \ 'susp', 1744 | \ 'suspe', 1745 | \ 'suspen', 1746 | \ 'suspend', 1747 | \ 'sv', 1748 | \ 'svi', 1749 | \ 'svie', 1750 | \ 'sview', 1751 | \ 'sw', 1752 | \ 'swa', 1753 | \ 'swap', 1754 | \ 'swapn', 1755 | \ 'swapna', 1756 | \ 'swapnam', 1757 | \ 'swapname', 1758 | \ 'sy', 1759 | \ 'syn', 1760 | \ 'sync', 1761 | \ 'syncbind', 1762 | \ 'syntime', 1763 | \ 't', 1764 | \ 'tN', 1765 | \ 'tNe', 1766 | \ 'tNex', 1767 | \ 'tNext', 1768 | \ 'ta', 1769 | \ 'tab', 1770 | \ 'tabN', 1771 | \ 'tabNe', 1772 | \ 'tabNex', 1773 | \ 'tabNext', 1774 | \ 'tabc', 1775 | \ 'tabcl', 1776 | \ 'tabclo', 1777 | \ 'tabclos', 1778 | \ 'tabclose', 1779 | \ 'tabd', 1780 | \ 'tabdo', 1781 | \ 'tabe', 1782 | \ 'tabed', 1783 | \ 'tabedi', 1784 | \ 'tabedit', 1785 | \ 'tabf', 1786 | \ 'tabfi', 1787 | \ 'tabfin', 1788 | \ 'tabfind', 1789 | \ 'tabfir', 1790 | \ 'tabfirs', 1791 | \ 'tabfirst', 1792 | \ 'tabl', 1793 | \ 'tabla', 1794 | \ 'tablas', 1795 | \ 'tablast', 1796 | \ 'tabm', 1797 | \ 'tabmo', 1798 | \ 'tabmov', 1799 | \ 'tabmove', 1800 | \ 'tabn', 1801 | \ 'tabne', 1802 | \ 'tabnew', 1803 | \ 'tabnex', 1804 | \ 'tabnext', 1805 | \ 'tabo', 1806 | \ 'tabon', 1807 | \ 'tabonl', 1808 | \ 'tabonly', 1809 | \ 'tabp', 1810 | \ 'tabpr', 1811 | \ 'tabpre', 1812 | \ 'tabprev', 1813 | \ 'tabprevi', 1814 | \ 'tabprevio', 1815 | \ 'tabpreviou', 1816 | \ 'tabprevious', 1817 | \ 'tabr', 1818 | \ 'tabre', 1819 | \ 'tabrew', 1820 | \ 'tabrewi', 1821 | \ 'tabrewin', 1822 | \ 'tabrewind', 1823 | \ 'tabs', 1824 | \ 'tag', 1825 | \ 'tags', 1826 | \ 'tc', 1827 | \ 'tcl', 1828 | \ 'tcld', 1829 | \ 'tcldo', 1830 | \ 'tclf', 1831 | \ 'tclfi', 1832 | \ 'tclfil', 1833 | \ 'tclfile', 1834 | \ 'te', 1835 | \ 'tea', 1836 | \ 'tear', 1837 | \ 'tearo', 1838 | \ 'tearof', 1839 | \ 'tearoff', 1840 | \ 'tf', 1841 | \ 'tfi', 1842 | \ 'tfir', 1843 | \ 'tfirs', 1844 | \ 'tfirst', 1845 | \ 'th', 1846 | \ 'thr', 1847 | \ 'thro', 1848 | \ 'throw', 1849 | \ 'tj', 1850 | \ 'tju', 1851 | \ 'tjum', 1852 | \ 'tjump', 1853 | \ 'tl', 1854 | \ 'tla', 1855 | \ 'tlas', 1856 | \ 'tlast', 1857 | \ 'tm', 1858 | \ 'tme', 1859 | \ 'tmen', 1860 | \ 'tmenu', 1861 | \ 'tn', 1862 | \ 'tne', 1863 | \ 'tnex', 1864 | \ 'tnext', 1865 | \ 'to', 1866 | \ 'top', 1867 | \ 'topl', 1868 | \ 'tople', 1869 | \ 'toplef', 1870 | \ 'topleft', 1871 | \ 'tp', 1872 | \ 'tpr', 1873 | \ 'tpre', 1874 | \ 'tprev', 1875 | \ 'tprevi', 1876 | \ 'tprevio', 1877 | \ 'tpreviou', 1878 | \ 'tprevious', 1879 | \ 'tr', 1880 | \ 'tre', 1881 | \ 'trew', 1882 | \ 'trewi', 1883 | \ 'trewin', 1884 | \ 'trewind', 1885 | \ 'try', 1886 | \ 'ts', 1887 | \ 'tse', 1888 | \ 'tsel', 1889 | \ 'tsele', 1890 | \ 'tselec', 1891 | \ 'tselect', 1892 | \ 'tu', 1893 | \ 'tun', 1894 | \ 'tunm', 1895 | \ 'tunme', 1896 | \ 'tunmen', 1897 | \ 'tunmenu', 1898 | \ 'u', 1899 | \ 'un', 1900 | \ 'una', 1901 | \ 'unab', 1902 | \ 'unabb', 1903 | \ 'unabbr', 1904 | \ 'unabbre', 1905 | \ 'unabbrev', 1906 | \ 'unabbrevi', 1907 | \ 'unabbrevia', 1908 | \ 'unabbreviat', 1909 | \ 'unabbreviate', 1910 | \ 'und', 1911 | \ 'undo', 1912 | \ 'undoj', 1913 | \ 'undojo', 1914 | \ 'undojoi', 1915 | \ 'undojoin', 1916 | \ 'undol', 1917 | \ 'undoli', 1918 | \ 'undolis', 1919 | \ 'undolist', 1920 | \ 'unh', 1921 | \ 'unhi', 1922 | \ 'unhid', 1923 | \ 'unhide', 1924 | \ 'unl', 1925 | \ 'unle', 1926 | \ 'unlet', 1927 | \ 'unlo', 1928 | \ 'unloc', 1929 | \ 'unlock', 1930 | \ 'unlockv', 1931 | \ 'unlockva', 1932 | \ 'unlockvar', 1933 | \ 'uns', 1934 | \ 'unsi', 1935 | \ 'unsil', 1936 | \ 'unsile', 1937 | \ 'unsilen', 1938 | \ 'unsilent', 1939 | \ 'up', 1940 | \ 'upd', 1941 | \ 'upda', 1942 | \ 'updat', 1943 | \ 'update', 1944 | \ 'v', 1945 | \ 've', 1946 | \ 'ver', 1947 | \ 'verb', 1948 | \ 'verbo', 1949 | \ 'verbos', 1950 | \ 'verbose', 1951 | \ 'vers', 1952 | \ 'versi', 1953 | \ 'versio', 1954 | \ 'version', 1955 | \ 'vert', 1956 | \ 'verti', 1957 | \ 'vertic', 1958 | \ 'vertica', 1959 | \ 'vertical', 1960 | \ 'vi', 1961 | \ 'vie', 1962 | \ 'view', 1963 | \ 'vim', 1964 | \ 'vimg', 1965 | \ 'vimgr', 1966 | \ 'vimgre', 1967 | \ 'vimgrep', 1968 | \ 'vimgrepa', 1969 | \ 'vimgrepad', 1970 | \ 'vimgrepadd', 1971 | \ 'vis', 1972 | \ 'visu', 1973 | \ 'visua', 1974 | \ 'visual', 1975 | \ 'viu', 1976 | \ 'vius', 1977 | \ 'viusa', 1978 | \ 'viusag', 1979 | \ 'viusage', 1980 | \ 'vmapc', 1981 | \ 'vmapcl', 1982 | \ 'vmapcle', 1983 | \ 'vmapclea', 1984 | \ 'vmapclear', 1985 | \ 'vne', 1986 | \ 'vnew', 1987 | \ 'vs', 1988 | \ 'vsp', 1989 | \ 'vspl', 1990 | \ 'vspli', 1991 | \ 'vsplit', 1992 | \ 'w', 1993 | \ 'wN', 1994 | \ 'wNe', 1995 | \ 'wNex', 1996 | \ 'wNext', 1997 | \ 'wa', 1998 | \ 'wal', 1999 | \ 'wall', 2000 | \ 'wh', 2001 | \ 'whi', 2002 | \ 'whil', 2003 | \ 'while', 2004 | \ 'win', 2005 | \ 'winc', 2006 | \ 'wincm', 2007 | \ 'wincmd', 2008 | \ 'windo', 2009 | \ 'winp', 2010 | \ 'winpo', 2011 | \ 'winpos', 2012 | \ 'wins', 2013 | \ 'winsi', 2014 | \ 'winsiz', 2015 | \ 'winsize', 2016 | \ 'wn', 2017 | \ 'wne', 2018 | \ 'wnex', 2019 | \ 'wnext', 2020 | \ 'wp', 2021 | \ 'wpr', 2022 | \ 'wpre', 2023 | \ 'wprev', 2024 | \ 'wprevi', 2025 | \ 'wprevio', 2026 | \ 'wpreviou', 2027 | \ 'wprevious', 2028 | \ 'wq', 2029 | \ 'wqa', 2030 | \ 'wqal', 2031 | \ 'wqall', 2032 | \ 'wr', 2033 | \ 'wri', 2034 | \ 'writ', 2035 | \ 'write', 2036 | \ 'ws', 2037 | \ 'wsv', 2038 | \ 'wsve', 2039 | \ 'wsver', 2040 | \ 'wsverb', 2041 | \ 'wundo', 2042 | \ 'wv', 2043 | \ 'wvi', 2044 | \ 'wvim', 2045 | \ 'wvimi', 2046 | \ 'wvimin', 2047 | \ 'wviminf', 2048 | \ 'wviminfo', 2049 | \ 'x', 2050 | \ 'xa', 2051 | \ 'xal', 2052 | \ 'xall', 2053 | \ 'xi', 2054 | \ 'xit', 2055 | \ 'xmapc', 2056 | \ 'xmapcl', 2057 | \ 'xmapcle', 2058 | \ 'xmapclea', 2059 | \ 'xmapclear', 2060 | \ 'xme', 2061 | \ 'xmenu', 2062 | \ 'xnoreme', 2063 | \ 'xnoremenu', 2064 | \ 'xunme', 2065 | \ 'xunmenu', 2066 | \ 'xwininfo', 2067 | \ 'y', 2068 | \ 'ya', 2069 | \ 'yan', 2070 | \ 'yank' 2071 | \ ]) 2072 | 2073 | endfunction 2074 | 2075 | let &cpo = s:save_cpo 2076 | unlet s:save_cpo 2077 | " __END__ 2078 | " vim: expandtab softtabstop=2 shiftwidth=2 foldmethod=marker 2079 | -------------------------------------------------------------------------------- /autoload/vital/debugger.vital: -------------------------------------------------------------------------------- 1 | debugger 2 | 65c9afb0799cb950cbaf9258aefc6c3ad700a98f 3 | 4 | Vim.SyntaxEcho 5 | Vim.Message 6 | Data.String 7 | Vim.ScriptLocal 8 | -------------------------------------------------------------------------------- /plugin/debugger.vim: -------------------------------------------------------------------------------- 1 | "============================================================================= 2 | " FILE: plugin/debugger.vim 3 | " AUTHOR: haya14busa 4 | " License: MIT license 5 | "============================================================================= 6 | scriptencoding utf-8 7 | if expand('%:p') ==# expand(':p') 8 | unlet! g:loaded_debugger 9 | endif 10 | if exists('g:loaded_debugger') 11 | finish 12 | endif 13 | let g:loaded_debugger = 1 14 | let s:save_cpo = &cpo 15 | set cpo&vim 16 | 17 | command! DebuggerOn call debugger#init() 18 | 19 | " :StackTrace accepts v:throwpoint string as an argument and makes a stack trace report. 20 | command! -nargs=1 StackTrace call debugger#stacktrace#report() 21 | 22 | " :CallStack {id} save callstack 23 | " :CallStackReport {id} show callstack report 24 | command! -nargs=? CallStack call debugger#stacktrace#callstack() 25 | command! -nargs=? CallStackReport call debugger#stacktrace#callstackreport() 26 | 27 | let &cpo = s:save_cpo 28 | unlet s:save_cpo 29 | " __END__ 30 | " vim: expandtab softtabstop=2 shiftwidth=2 foldmethod=marker 31 | --------------------------------------------------------------------------------