]> git.ipfire.org Git - thirdparty/git.git/commitdiff
completion: improve handling of -c/-C and -b/-B in switch/checkout
authorJacob Keller <jacob.keller@gmail.com>
Thu, 28 May 2020 18:10:47 +0000 (11:10 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 28 May 2020 19:57:07 +0000 (12:57 -0700)
A previous commit added several test cases highlighting the subpar
completion logic for -c/-C and -b/-B when completing git switch and git
checkout.

In order to distinguish completing the argument vs the start-point for
this option, we now use the wordlist to determine the previous full word
on the command line.

If it's -c or -C (-b/-B for checkout), then we know that we are
completing the argument for the branch name.

Given that a user who already knows the branch name they want to
complete will simply not use completion, it makes sense to complete the
small subset of local branches when completing the argument for -c/-C.

In all other cases, if -c/-C are on the command line but are not the
most recent option, then we must be completing a start-point, and should
allow completing against all references.

Update the -c/-C and -b/-B tests to indicate they now pass.

Signed-off-by: Jacob Keller <jacob.keller@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
contrib/completion/git-completion.bash
t/t9902-completion.sh

index e520dda35eca5dbfee380093497d39a67fc58369..9dd0412ecc1c5ea074aae1e8e1bcbe1ee1c3bf8a 100644 (file)
@@ -1505,8 +1505,31 @@ _git_checkout ()
                ;;
        *)
                local dwim_opt="$(__git_checkout_default_dwim_mode)"
+               local prevword prevword="${words[cword-1]}"
+
+               case "$prevword" in
+                       -b|-B)
+                               # Complete local branches (and DWIM branch
+                               # remote branch names) for an option argument
+                               # specifying a new branch name. This is for
+                               # convenience, assuming new branches are
+                               # possibly based on pre-existing branch names.
+                               __git_complete_refs $dwim_opt --mode="heads"
+                               return
+                               ;;
+                       *)
+                               ;;
+               esac
+
+               # At this point, we've already handled special completion for
+               # the arguments to -b/-B. There are 3 main things left we can
+               # possibly complete:
+               # 1) a start-point for -b/-B or -d/--detach
+               # 2) a remote head, for --track
+               # 3) an arbitrary reference, possibly including DWIM names
+               #
 
-               if [ -n "$(__git_find_on_cmdline "-d --detach")" ]; then
+               if [ -n "$(__git_find_on_cmdline "-b -B -d --detach")" ]; then
                        __git_complete_refs --mode="refs"
                elif [ -n "$(__git_find_on_cmdline "--track")" ]; then
                        __git_complete_refs --mode="remote-heads"
@@ -2361,8 +2384,30 @@ _git_switch ()
                ;;
        *)
                local dwim_opt="$(__git_checkout_default_dwim_mode)"
+               local prevword prevword="${words[cword-1]}"
+
+               case "$prevword" in
+                       -c|-C)
+                               # Complete local branches (and DWIM branch
+                               # remote branch names) for an option argument
+                               # specifying a new branch name. This is for
+                               # convenience, assuming new branches are
+                               # possibly based on pre-existing branch names.
+                               __git_complete_refs $dwim_opt --mode="heads"
+                               return
+                               ;;
+                       *)
+                               ;;
+               esac
+
+               # At this point, we've already handled special completion for
+               # -c/-C. There are 3 main things left to
+               # complete:
+               # 1) a start-point for -c/-C or -d/--detach
+               # 2) a remote head, for --track
+               # 3) a branch name, possibly including DWIM remote branches
 
-               if [ -n "$(__git_find_on_cmdline "-d --detach")" ]; then
+               if [ -n "$(__git_find_on_cmdline "-c -C -d --detach")" ]; then
                        __git_complete_refs --mode="refs"
                elif [ -n "$(__git_find_on_cmdline "--track")" ]; then
                        __git_complete_refs --mode="remote-heads"
index 227732688974e517b67e10bf8d2498164077fd3f..7a0927b51fdb9a9a9857dea5ca850438f29455db 100755 (executable)
@@ -1436,8 +1436,7 @@ test_expect_success 'git checkout - with --no-track, complete only local referen
        EOF
 '
 
-#TODO: completing the start point of -c/-C should not include DWIM references
-test_expect_failure 'git switch - with -c, complete all references' '
+test_expect_success 'git switch - with -c, complete all references' '
        test_completion "git switch -c new-branch " <<-\EOF
        HEAD Z
        master Z
@@ -1448,8 +1447,7 @@ test_expect_failure 'git switch - with -c, complete all references' '
        EOF
 '
 
-#TODO: completing the start point of -c/-C should not include DWIM references
-test_expect_failure 'git switch - with -C, complete all references' '
+test_expect_success 'git switch - with -C, complete all references' '
        test_completion "git switch -C new-branch " <<-\EOF
        HEAD Z
        master Z
@@ -1460,8 +1458,7 @@ test_expect_failure 'git switch - with -C, complete all references' '
        EOF
 '
 
-#TODO: completing the start point of -c/-C should include all references, not just local branches
-test_expect_failure 'git switch - with -c and --track, complete all references' '
+test_expect_success 'git switch - with -c and --track, complete all references' '
        test_completion "git switch -c new-branch --track " <<-EOF
        HEAD Z
        master Z
@@ -1472,8 +1469,7 @@ test_expect_failure 'git switch - with -c and --track, complete all references'
        EOF
 '
 
-#TODO: completing the start point of -c/-C should include all references, not just local branches
-test_expect_failure 'git switch - with -C and --track, complete all references' '
+test_expect_success 'git switch - with -C and --track, complete all references' '
        test_completion "git switch -C new-branch --track " <<-EOF
        HEAD Z
        master Z
@@ -1484,8 +1480,7 @@ test_expect_failure 'git switch - with -C and --track, complete all references'
        EOF
 '
 
-#TODO: completing the start point of -c/-C should include all references, not just local branches
-test_expect_failure 'git switch - with -c and --no-track, complete all references' '
+test_expect_success 'git switch - with -c and --no-track, complete all references' '
        test_completion "git switch -c new-branch --no-track " <<-\EOF
        HEAD Z
        master Z
@@ -1496,8 +1491,7 @@ test_expect_failure 'git switch - with -c and --no-track, complete all reference
        EOF
 '
 
-#TODO: completing the start point of -c/-C should include all references, not just local branches
-test_expect_failure 'git switch - with -C and --no-track, complete all references' '
+test_expect_success 'git switch - with -C and --no-track, complete all references' '
        test_completion "git switch -C new-branch --no-track " <<-\EOF
        HEAD Z
        master Z
@@ -1508,8 +1502,7 @@ test_expect_failure 'git switch - with -C and --no-track, complete all reference
        EOF
 '
 
-#TODO: completing the start point of -b/-B should not include DWIM references
-test_expect_failure 'git checkout - with -b, complete all references' '
+test_expect_success 'git checkout - with -b, complete all references' '
        test_completion "git checkout -b new-branch " <<-\EOF
        HEAD Z
        master Z
@@ -1520,8 +1513,7 @@ test_expect_failure 'git checkout - with -b, complete all references' '
        EOF
 '
 
-#TODO: completing the start point of -b/-B should not include DWIM references
-test_expect_failure 'git checkout - with -B, complete all references' '
+test_expect_success 'git checkout - with -B, complete all references' '
        test_completion "git checkout -B new-branch " <<-\EOF
        HEAD Z
        master Z
@@ -1532,8 +1524,7 @@ test_expect_failure 'git checkout - with -B, complete all references' '
        EOF
 '
 
-#TODO: completing the start point of -b/-B should not include DWIM references
-test_expect_failure 'git checkout - with -b and --track, complete all references' '
+test_expect_success 'git checkout - with -b and --track, complete all references' '
        test_completion "git checkout -b new-branch --track " <<-EOF
        HEAD Z
        master Z
@@ -1544,8 +1535,7 @@ test_expect_failure 'git checkout - with -b and --track, complete all references
        EOF
 '
 
-#TODO: completing the start point of -b/-B should not include DWIM references
-test_expect_failure 'git checkout - with -B and --track, complete all references' '
+test_expect_success 'git checkout - with -B and --track, complete all references' '
        test_completion "git checkout -B new-branch --track " <<-EOF
        HEAD Z
        master Z
@@ -1624,8 +1614,7 @@ test_expect_success 'git switch - for -C with --no-track, complete local branche
        EOF
 '
 
-#TODO: -b/-B argument completion should not include all references
-test_expect_failure 'git checkout - for -b, complete local branches and unique remote branches' '
+test_expect_success 'git checkout - for -b, complete local branches and unique remote branches' '
        test_completion "git checkout -b " <<-\EOF
        branch-in-other Z
        master Z
@@ -1634,8 +1623,7 @@ test_expect_failure 'git checkout - for -b, complete local branches and unique r
        EOF
 '
 
-#TODO: -b/-B argument completion should not include all references
-test_expect_failure 'git checkout - for -B, complete local branches and unique remote branches' '
+test_expect_success 'git checkout - for -B, complete local branches and unique remote branches' '
        test_completion "git checkout -B " <<-\EOF
        branch-in-other Z
        master Z
@@ -1644,32 +1632,28 @@ test_expect_failure 'git checkout - for -B, complete local branches and unique r
        EOF
 '
 
-#TODO: -b/-B argument completion should not include all references
-test_expect_failure 'git checkout - for -b with --no-guess, complete local branches only' '
+test_expect_success 'git checkout - for -b with --no-guess, complete local branches only' '
        test_completion "git checkout --no-guess -b " <<-\EOF
        master Z
        matching-branch Z
        EOF
 '
 
-#TODO: -b/-B argument completion should not include all references
-test_expect_failure 'git checkout - for -B with --no-guess, complete local branches only' '
+test_expect_success 'git checkout - for -B with --no-guess, complete local branches only' '
        test_completion "git checkout --no-guess -B " <<-\EOF
        master Z
        matching-branch Z
        EOF
 '
 
-#TODO: -b/-B argument completion should not include all references
-test_expect_failure 'git checkout - for -b with --no-track, complete local branches only' '
+test_expect_success 'git checkout - for -b with --no-track, complete local branches only' '
        test_completion "git checkout --no-track -b " <<-\EOF
        master Z
        matching-branch Z
        EOF
 '
 
-#TODO: -b/-B argument completion should not include all references
-test_expect_failure 'git checkout - for -B with --no-track, complete local branches only' '
+test_expect_success 'git checkout - for -B with --no-track, complete local branches only' '
        test_completion "git checkout --no-track -B " <<-\EOF
        master Z
        matching-branch Z