From 58d2b25836f420cf2fe20cc0b6f988165ae33782 Mon Sep 17 00:00:00 2001 From: Tim Pope Date: Sat, 20 Mar 2021 10:52:58 -0400 Subject: [PATCH] Use git --list-cmds= to complete subcommands For older Git versions, use the list of subcommands from when --list-cmds= was first added, and subtract out "worktree" for Git versions too old to have it. This one simple conditional gives us accurate completion for Git versions up to a decade old. The option is described as "internal/experimental", so make sure the exit status is successful, and filter out anything that looks like a warning or deprecation notice. In case of failure, use the commands provided by --list-cmds= as of the date of this commit. Closes https://github.com/tpope/vim-fugitive/pull/1629 --- autoload/fugitive.vim | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/autoload/fugitive.vim b/autoload/fugitive.vim index 1c25c5a..db433ee 100644 --- a/autoload/fugitive.vim +++ b/autoload/fugitive.vim @@ -2744,10 +2744,36 @@ function! s:ExecPath() abort return s:exec_paths[g:fugitive_git_executable] endfunction +let s:subcommands_before_2_5 = [ + \ 'add', 'am', 'apply', 'archive', 'bisect', 'blame', 'branch', 'bundle', + \ 'checkout', 'cherry', 'cherry-pick', 'citool', 'clean', 'clone', 'commit', 'config', + \ 'describe', 'diff', 'difftool', 'fetch', 'format-patch', 'fsck', + \ 'gc', 'grep', 'gui', 'help', 'init', 'instaweb', 'log', + \ 'merge', 'mergetool', 'mv', 'notes', 'pull', 'push', + \ 'rebase', 'reflog', 'remote', 'repack', 'replace', 'request-pull', 'reset', 'revert', 'rm', + \ 'send-email', 'shortlog', 'show', 'show-branch', 'stash', 'stage', 'status', 'submodule', + \ 'tag', 'whatchanged', + \ ] let s:path_subcommands = {} function! s:CompletableSubcommands(dir) abort - let commands = [] - for path in [s:ExecPath()] + split($PATH, has('win32') ? ';' : ':') + let c_exec_path = s:cpath(s:ExecPath()) + if !has_key(s:path_subcommands, c_exec_path) + if fugitive#GitVersion(2, 18) + let [lines, exec_error] = s:LinesError(a:dir, '--list-cmds=list-mainporcelain,nohelpers,list-complete') + call filter(lines, 'v:val =~# "^\\S\\+$"') + if !exec_error && len(lines) + let s:path_subcommands[c_exec_path] = lines + else + let s:path_subcommands[c_exec_path] = s:subcommands_before_2_5 + + \ ['maintenance', 'prune', 'range-diff', 'restore', 'sparse-checkout', 'switch', 'worktree'] + endif + else + let s:path_subcommands[c_exec_path] = s:subcommands_before_2_5 + + \ (fugitive#GitVersion(2, 5) ? ['worktree'] : []) + endif + endif + let commands = copy(s:path_subcommands[c_exec_path]) + for path in split($PATH, has('win32') ? ';' : ':') if path !~# '^/\|^\a:[\\/]' continue endif