Complete the paths of existing working trees for 'git worktree's
'move', 'remove', 'lock', and 'unlock' subcommands.

Note that 'git worktree list --porcelain' shows absolute paths, so for
simplicity's sake we'll complete full absolute paths as well (as
opposed to turning them into relative paths by finding common leading
directories between $PWD and the working tree's path and removing
them, risking trouble with symbolic links or Windows drive letters; or
completing them one path component at a time).

Never list the path of the main working tree, as it cannot be moved,
removed, locked, or unlocked.

Arguably 'git worktree unlock <TAB>' should only complete locked
working trees, but 'git worktree list --porcelain' doesn't indicate
which working trees are locked.  So for now it will complete the paths
of all existing working trees, including non-locked ones as well.

Signed-off-by: SZEDER Gábor <szeder....@gmail.com>
---
 contrib/completion/git-completion.bash | 28 +++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/contrib/completion/git-completion.bash 
b/contrib/completion/git-completion.bash
index 643272eb2f..4eb13b06d6 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -2981,10 +2981,21 @@ _git_whatchanged ()
        _git_log
 }
 
+__git_complete_worktree_paths ()
+{
+       local IFS=$'\n'
+       __gitcomp_nl "$(git worktree list --porcelain |
+               sed -n -e '2,$ s/^worktree //p')"
+}
+
 _git_worktree ()
 {
        local subcommands="add list lock move prune remove unlock"
-       local subcommand="$(__git_find_on_cmdline "$subcommands")"
+       local subcommand subcommand_idx
+
+       subcommand="$(__git_find_on_cmdline --show-idx "$subcommands")"
+       subcommand_idx="${subcommand% *}"
+       subcommand="${subcommand#* }"
 
        case "$subcommand,$cur" in
        ,*)
@@ -2993,6 +3004,21 @@ _git_worktree ()
        *,--*)
                __gitcomp_builtin worktree_$subcommand
                ;;
+       lock,*|remove,*|unlock,*)
+               __git_complete_worktree_paths
+               ;;
+       move,*)
+               if [ $cword -eq $((subcommand_idx+1)) ]; then
+                       # The first parameter must be an existing working
+                       # tree to be moved.
+                       __git_complete_worktree_paths
+               else
+                       # The second parameter is the destination: it could
+                       # be any path, so don't list anything, but let Bash
+                       # fall back to filename completion.
+                       :
+               fi
+               ;;
        esac
 }
 
-- 
2.23.0.1084.gae250eaa40

Reply via email to