Retool completion of subcommands

Support configured completion commands and aliases using our cached
config helpers, and support --exec-path and $PATH git-* executables by
globbing once and caching indefinitely.

References https://github.com/tpope/vim-fugitive/pull/1629
This commit is contained in:
Tim Pope
2021-03-20 07:46:00 -04:00
parent a55d6f39c8
commit 1999aef8cd

View File

@@ -2744,22 +2744,42 @@ function! s:ExecPath() abort
return s:exec_paths[g:fugitive_git_executable] return s:exec_paths[g:fugitive_git_executable]
endfunction endfunction
function! s:Subcommands() abort let s:path_subcommands = {}
let exec_path = s:ExecPath() function! s:CompletableSubcommands(dir) abort
return map(s:GlobComplete(exec_path.'/git-', '*', 1),'substitute(v:val,"\\.exe$","","")') let commands = []
endfunction for path in [s:ExecPath()] + split($PATH, has('win32') ? ';' : ':')
if path !~# '^/\|^\a:[\\/]'
let s:aliases = {} continue
function! s:Aliases(dir) abort endif
let dir_key = len(a:dir) ? a:dir : '_' let cpath = s:cpath(path)
if !has_key(s:aliases, dir_key) if !has_key(s:path_subcommands, cpath)
let s:aliases[dir_key] = {} let s:path_subcommands[cpath] = filter(map(s:GlobComplete(path.'/git-', '*', 1),'substitute(v:val,"\\.exe$","","")'), 'v:val !~# "--"')
let lines = s:NullError([a:dir, 'config', '-z', '--get-regexp', '^alias[.]'])[0] endif
for line in lines call extend(commands, s:path_subcommands[cpath])
let s:aliases[dir_key][matchstr(line, '\.\zs.\{-}\ze\n')] = matchstr(line, '\n\zs.*') endfor
endfor call extend(commands, map(filter(keys(fugitive#Config(a:dir)), 'v:val =~# "^alias\\.[^.]*$"'), 'strpart(v:val, 6)'))
let configured = split(FugitiveConfigGet('completion.commands', a:dir), '\s\+')
let rejected = {}
for command in configured
if command =~# '^-.'
let rejected[strpart(command, 1)] = 1
endif
endfor
call filter(configured, 'v:val !~# "^-"')
let results = filter(sort(commands + configured), '!has_key(rejected, v:val)')
if exists('*uniq')
return uniq(results)
else
let i = 1
while i < len(results)
if results[i] ==# results[i-1]
call remove(results, i)
else
let i += 1
endif
endwhile
return results
endif endif
return s:aliases[dir_key]
endfunction endfunction
function! fugitive#Complete(lead, ...) abort function! fugitive#Complete(lead, ...) abort
@@ -2768,7 +2788,7 @@ function! fugitive#Complete(lead, ...) abort
let pre = a:0 > 1 ? strpart(a:1, 0, a:2) : '' let pre = a:0 > 1 ? strpart(a:1, 0, a:2) : ''
let subcmd = matchstr(pre, '\u\w*[! ] *\zs[[:alnum:]-]\+\ze ') let subcmd = matchstr(pre, '\u\w*[! ] *\zs[[:alnum:]-]\+\ze ')
if empty(subcmd) if empty(subcmd)
let results = sort(s:Subcommands() + keys(s:Aliases(dir))) let results = s:CompletableSubcommands(dir)
elseif a:0 ==# 2 && subcmd =~# '^\%(commit\|revert\|push\|fetch\|pull\|merge\|rebase\)$' elseif a:0 ==# 2 && subcmd =~# '^\%(commit\|revert\|push\|fetch\|pull\|merge\|rebase\)$'
let cmdline = substitute(a:1, '\u\w*\([! ] *\)' . subcmd, 'G' . subcmd, '') let cmdline = substitute(a:1, '\u\w*\([! ] *\)' . subcmd, 'G' . subcmd, '')
let caps_subcmd = substitute(subcmd, '\%(^\|-\)\l', '\u&', 'g') let caps_subcmd = substitute(subcmd, '\%(^\|-\)\l', '\u&', 'g')