"============================================================================= " FILE: helper.vim " AUTHOR: Shougo Matsushita " License: MIT license {{{ " Permission is hereby granted, free of charge, to any person obtaining " a copy of this software and associated documentation files (the " "Software"), to deal in the Software without restriction, including " without limitation the rights to use, copy, modify, merge, publish, " distribute, sublicense, and/or sell copies of the Software, and to " permit persons to whom the Software is furnished to do so, subject to " the following conditions: " " The above copyright notice and this permission notice shall be included " in all copies or substantial portions of the Software. " " THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS " OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF " MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. " IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY " CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, " TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE " SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. " }}} "============================================================================= function! vimshell#complete#helper#files(cur_keyword_str, ...) abort "{{{ " vimshell#complete#helper#files(cur_keyword_str [, path]) if a:0 > 1 call vimshell#echo_error('Too many arguments.') endif let path = (a:0 == 1 ? a:1 : '.') let list = vimshell#complete#helper#get_files(path, a:cur_keyword_str) " Extend pseudo files. if a:cur_keyword_str =~ '^/dev/' for word in vimshell#complete#helper#keyword_simple_filter( \ ['/dev/null', '/dev/clip', '/dev/quickfix'], \ a:cur_keyword_str) let dict = { \ 'word' : word, 'menu' : 'file' \} " Escape word. let dict.orig = vimshell#util#expand(dict.word) let dict.word = escape(dict.word, ' *?[]"={}') call add(list, dict) endfor endif return list endfunction"}}} function! vimshell#complete#helper#directories(cur_keyword_str) abort "{{{ let ret = [] for keyword in filter(vimshell#complete#helper#files(a:cur_keyword_str), \ 'isdirectory(v:val.orig) || \ (vimshell#util#is_windows() && fnamemodify(v:val.orig, ":e") ==? "LNK" \ && isdirectory(resolve(v:val.orig)))') let dict = keyword let dict.menu = 'directory' call add(ret, dict) endfor return ret endfunction"}}} function! vimshell#complete#helper#cdpath_directories(cur_keyword_str) abort "{{{ " Check dup. let check = {} for keyword in filter(vimshell#complete#helper#files(a:cur_keyword_str, &cdpath), \ 'isdirectory(v:val.orig) || (vimshell#util#is_windows() \ && fnamemodify(v:val.orig, ":e") ==? "LNK" \ && isdirectory(resolve(v:val.orig)))') if !has_key(check, keyword.word) && keyword.word =~ '/' let check[keyword.word] = keyword endif endfor let ret = [] for keyword in values(check) let dict = keyword let dict.menu = 'cdpath' call add(ret, dict) endfor return ret endfunction"}}} function! vimshell#complete#helper#directory_stack(cur_keyword_str) abort "{{{ if !exists('b:vimshell') return [] endif let ret = [] for keyword in vimshell#complete#helper#keyword_simple_filter( \ range(len(b:vimshell.directory_stack)), a:cur_keyword_str) let dict = { 'word' : keyword, 'menu' : b:vimshell.directory_stack[keyword] } call add(ret, dict) endfor return ret endfunction"}}} function! vimshell#complete#helper#aliases(cur_keyword_str) abort "{{{ if !exists('b:vimshell') return [] endif let ret = [] for keyword in vimshell#complete#helper#keyword_simple_filter( \ keys(b:vimshell.alias_table), a:cur_keyword_str) let dict = { 'word' : keyword } if len(b:vimshell.alias_table[keyword]) > 15 let dict.menu = 'alias ' . \ printf("%s..%s", \ b:vimshell.alias_table[keyword][:8], \ b:vimshell.alias_table[keyword][-4:]) else let dict.menu = 'alias ' . \ b:vimshell.alias_table[keyword] endif call add(ret, dict) endfor return ret endfunction"}}} function! vimshell#complete#helper#internals(cur_keyword_str) abort "{{{ let commands = vimshell#available_commands(a:cur_keyword_str) let ret = [] for keyword in vimshell#complete#helper#keyword_simple_filter( \ keys(commands), a:cur_keyword_str) let dict = { 'word' : keyword, 'menu' : commands[keyword].kind } call add(ret, dict) endfor return ret endfunction"}}} function! vimshell#complete#helper#executables(cur_keyword_str, ...) abort "{{{ if a:cur_keyword_str =~ '[/\\]' let files = vimshell#complete#helper#files(a:cur_keyword_str) else let path = a:0 > 1 ? a:1 : \ vimshell#util#is_windows() ? substitute($PATH, '\\\?;', ',', 'g') : \ substitute($PATH, '/\?:', ',', 'g') let files = vimshell#complete#helper#files(a:cur_keyword_str, path) endif if vimshell#util#is_windows() let exts = escape(substitute($PATHEXT, ';', '\\|', 'g'), '.') let pattern = (a:cur_keyword_str =~ '[/\\]')? \ 'isdirectory(v:val.orig) || "." . \ fnamemodify(v:val.orig, ":e") =~? '.string(exts) : \ '"." . fnamemodify(v:val.orig, ":e") =~? '.string(exts) else let pattern = (a:cur_keyword_str =~ '[/\\]')? \ 'isdirectory(v:val.orig) || executable(v:val.orig)' \ : 'executable(v:val.orig)' endif call filter(files, pattern) let ret = [] for keyword in files let dict = keyword let dict.menu = 'command' if a:cur_keyword_str !~ '[/\\]' let dict.word = fnamemodify(keyword.word, ':t') let dict.abbr = fnamemodify(keyword.abbr, ':t') endif call add(ret, dict) endfor return ret endfunction"}}} function! vimshell#complete#helper#buffers(cur_keyword_str) abort "{{{ let ret = [] let bufnumber = 1 while bufnumber <= bufnr('$') if buflisted(bufnumber) && \ vimshell#util#head_match(bufname(bufnumber), a:cur_keyword_str) let keyword = bufname(bufnumber) let dict = { 'word' : escape(keyword, ' *?[]"={}'), 'menu' : 'buffer' } call add(ret, dict) endif let bufnumber += 1 endwhile return ret endfunction"}}} function! vimshell#complete#helper#args(command, args) abort "{{{ let commands = vimshell#available_commands(a:command) " Get complete words. if has_key(get(commands, a:command, {}), 'complete') let complete_words = commands[a:command].complete(a:args) elseif empty(a:args) return [] else let complete_words = vimshell#complete#helper#files(a:args[-1]) endif if a:args[-1] =~ '^--\?[[:alnum:]._-]\+=\f\+$\|[<>]\+\f\+$' " Complete file. let prefix = matchstr(a:args[-1], \'^--[[:alnum:]._-]\+=\|^[<>]\+') let complete_words += vimshell#complete#helper#files( \ a:args[-1][len(prefix): ]) endif return complete_words endfunction"}}} function! vimshell#complete#helper#command_args(args) abort "{{{ " command args... if len(a:args) == 1 " Commands. return vimshell#complete#helper#executables(a:args[0]) else " Args. return vimshell#complete#helper#args(a:args[0], a:args[1:]) endif endfunction"}}} function! vimshell#complete#helper#variables(cur_keyword_str) abort "{{{ let _ = [] let _ += map(copy(vimshell#complete#helper#environments( \ a:cur_keyword_str[1:])), "'$' . v:val") if a:cur_keyword_str =~ '^$\l' let _ += map(keys(b:vimshell.variables), "'$' . v:val") elseif a:cur_keyword_str =~ '^$$' let _ += map(keys(b:vimshell.system_variables), "'$$' . v:val") endif return vimshell#complete#helper#keyword_simple_filter(_, a:cur_keyword_str) endfunction"}}} function! vimshell#complete#helper#environments(cur_keyword_str) abort "{{{ if !exists('s:envlist') " Get environment variables list. let s:envlist = map(split(system('set'), '\n'), \ "toupper(matchstr(v:val, '^\\h\\w*'))") endif return vimshell#complete#helper#keyword_simple_filter( \ copy(s:envlist), a:cur_keyword_str) endfunction"}}} function! vimshell#complete#helper#call_omnifunc(omnifunc) abort "{{{ " Set complete function. let &l:omnifunc = a:omnifunc return "\\\" endfunction"}}} function! vimshell#complete#helper#restore_omnifunc(omnifunc) abort "{{{ if &l:omnifunc !=# a:omnifunc let &l:omnifunc = a:omnifunc endif endfunction"}}} function! vimshell#complete#helper#compare_rank(i1, i2) abort "{{{ return a:i1.rank < a:i2.rank ? 1 : a:i1.rank == a:i2.rank ? 0 : -1 endfunction"}}} function! vimshell#complete#helper#keyword_filter(list, cur_keyword_str) abort "{{{ let cur_keyword = substitute(a:cur_keyword_str, '\\\zs.', '\0', 'g') if &ignorecase let expr = printf('stridx(tolower(v:val.word), %s) == 0', \ string(tolower(cur_keyword))) else let expr = printf('stridx(v:val.word, %s) == 0', \ string(cur_keyword)) endif return filter(a:list, expr) endfunction"}}} function! vimshell#complete#helper#keyword_simple_filter(list, cur_keyword_str) abort "{{{ let cur_keyword = substitute(a:cur_keyword_str, '\\\zs.', '\0', 'g') let expr = &ignorecase ? \ printf('stridx(tolower(v:val), %s) == 0', \ string(tolower(cur_keyword))) : \ printf('stridx(v:val, %s) == 0', \ string(cur_keyword)) return filter(a:list, expr) endfunction"}}} function! vimshell#complete#helper#get_files(path, complete_str) abort "{{{ let candidates = s:get_glob_files(a:path, a:complete_str) if a:path == '' let candidates = vimshell#complete#helper#keyword_filter( \ candidates, a:complete_str) endif return sort(filter(copy(candidates), \ 'v:val.action__is_directory')) + \ sort(filter(copy(candidates), \ '!v:val.action__is_directory')) endfunction"}}} function! s:get_glob_files(path, complete_str) abort "{{{ let path = ',,' . substitute(a:path, '\.\%(,\|$\)\|,,', '', 'g') let complete_str = vimshell#util#substitute_path_separator( \ substitute(a:complete_str, '\\\(.\)', '\1', 'g')) let glob = (complete_str !~ '\*$')? \ complete_str . '*' : complete_str if a:path == '' let files = vimshell#util#glob(glob) else try let globs = globpath(path, glob) catch return [] endtry let files = split(vimshell#util#substitute_path_separator(globs), '\n') endif let files = filter(files, "v:val !~ '/.$'") let files = map( \ files, "{ \ 'word' : v:val, \ 'orig' : v:val, \ 'action__is_directory' : isdirectory(v:val), \ }") if a:complete_str =~ '^\$\h\w*' let env = matchstr(a:complete_str, '^\$\h\w*') let env_ev = eval(env) if env_ev == '' return [] endif if vimshell#util#is_windows() let env_ev = substitute(env_ev, '\\', '/', 'g') endif let len_env = len(env_ev) else let env = '' let env_ev = '' let len_env = 0 endif let home_pattern = '^'. \ vimshell#util#substitute_path_separator( \ expand('~')).'/' let exts = escape(substitute($PATHEXT, ';', '\\|', 'g'), '.') let candidates = [] for dict in files let dict.orig = dict.word if len_env != 0 && dict.word[: len_env-1] == env_ev let dict.word = env . dict.word[len_env :] endif let abbr = dict.word if dict.action__is_directory && dict.word !~ '/$' let abbr .= '/' if vimshell#util#is_auto_delimiter() let dict.word .= '/' endif elseif vimshell#util#is_windows() if '.'.fnamemodify(dict.word, ':e') =~ exts let abbr .= '*' endif elseif executable(dict.word) let abbr .= '*' endif let dict.abbr = abbr if a:complete_str =~ '^\~/' let dict.word = substitute(dict.word, home_pattern, '\~/', '') let dict.abbr = substitute(dict.abbr, home_pattern, '\~/', '') endif " Escape word. let dict.word = escape(dict.word, ' ;*?[]"={}''') call add(candidates, dict) endfor return candidates endfunction"}}} " vim: foldmethod=marker