git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jacob Keller <jacob.e.keller@intel.com>
To: git@vger.kernel.org
Cc: Jonathan Nieder <jrnieder@gmail.com>,
	Junio C Hamano <gitster@pobox.com>,
	Jacob Keller <jacob.keller@gmail.com>
Subject: [PATCH v3 11/16] completion: improve handling of DWIM mode for switch/checkout
Date: Thu, 28 May 2020 11:10:43 -0700	[thread overview]
Message-ID: <20200528181048.3509470-12-jacob.e.keller@intel.com> (raw)
In-Reply-To: <20200528181048.3509470-1-jacob.e.keller@intel.com>

From: Jacob Keller <jacob.keller@gmail.com>

A new helper, __git_find_last_on_cmdline is introduced, similar to the
already existing __git_find_on_cmdline, but which operates in reverse,
finding the *last* matching word of the provided wordlist.

Use this in a new __git_checkout_default_dwim_mode() function that will
determine when to enable listing of DWIM remote branches.

The __git_find_last_on_cmdline() function is used to determine which
--guess or --no-guess is in effect. If either one is provided, then we
unconditionally enable or disable the DWIM mode based on the last
provided option.

If neither --guess nor --no-guess is provided, then we check for
--no-track, and finally for GIT_COMPLETION_CHECKOUT_NO_GUESS=1.

This function is then used in _git_switch and _git_checkout to improve
the handling for when we enable listing of these DWIM remote branches.

This new logic is more robust, as we will correctly identify superseded
options, and ensure that both _git_switch and _git_checkout enable DWIM
in similar ways.

We can now update a few tests to indicate they pass. A few of the tests
previously added to highlight issues with the old DWIM logic still fail.
This is because of a separate issue related to the default completion
behavior of git switch, which will be addressed in a future change.

Additionally, due to this change, a few tests for the -b/-B handling of
git checkout now fail. This is a minor regression, and will be fixed by
a following change that improves the overall handling of -b/-B. Mark
these tests as known breakages for now.

Signed-off-by: Jacob Keller <jacob.keller@gmail.com>
---
 contrib/completion/git-completion.bash | 95 ++++++++++++++++++++------
 t/t9902-completion.sh                  | 17 ++---
 2 files changed, 83 insertions(+), 29 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 5c13d2cd0fde..54cd676fdc9d 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1135,6 +1135,40 @@ __git_find_on_cmdline ()
 	done
 }
 
+# Similar to __git_find_on_cmdline, except that it loops backwards and thus
+# prints the *last* word found. Useful for finding which of two options that
+# supersede each other came last, such as "--guess" and "--no-guess".
+#
+# Usage: __git_find_last_on_cmdline [<option>]... "<wordlist>"
+# --show-idx: Optionally show the index of the found word in the $words array.
+__git_find_last_on_cmdline ()
+{
+	local word c=$cword show_idx
+
+	while test $# -gt 1; do
+		case "$1" in
+		--show-idx)	show_idx=y ;;
+		*)		return 1 ;;
+		esac
+		shift
+	done
+	local wordlist="$1"
+
+	while [ $c -gt 1 ]; do
+		((c--))
+		for word in $wordlist; do
+			if [ "$word" = "${words[c]}" ]; then
+				if [ -n "$show_idx" ]; then
+					echo "$c $word"
+				else
+					echo "$word"
+				fi
+				return
+			fi
+		done
+	done
+}
+
 # Echo the value of an option set on the command line or config
 #
 # $1: short option name
@@ -1389,6 +1423,46 @@ _git_bundle ()
 	esac
 }
 
+# Helper function to decide whether or not we should enable DWIM logic for
+# git-switch and git-checkout.
+#
+# To decide between the following rules in priority order
+# 1) the last provided of "--guess" or "--no-guess" explicitly enable or
+#    disable completion of DWIM logic respectively.
+# 2) If the --no-track option is provided, take this as a hint to disable the
+#    DWIM completion logic
+# 3) If GIT_COMPLETION_CHECKOUT_NO_GUESS is set, disable the DWIM completion
+#    logic, as requested by the user.
+# 4) Enable DWIM logic otherwise.
+#
+__git_checkout_default_dwim_mode ()
+{
+	local last_option dwim_opt="--dwim"
+
+	if [ "$GIT_COMPLETION_CHECKOUT_NO_GUESS" = "1" ]; then
+		dwim_opt=""
+	fi
+
+	# --no-track disables DWIM, but with lower priority than
+	# --guess/--no-guess
+	if [ -n "$(__git_find_on_cmdline "--no-track")" ]; then
+		dwim_opt=""
+	fi
+
+	# Find the last provided --guess or --no-guess
+	last_option="$(__git_find_last_on_cmdline "--guess --no-guess")"
+	case "$last_option" in
+		--guess)
+			dwim_opt="--dwim"
+			;;
+		--no-guess)
+			dwim_opt=""
+			;;
+	esac
+
+	echo "$dwim_opt"
+}
+
 _git_checkout ()
 {
 	__git_has_doubledash && return
@@ -1401,13 +1475,7 @@ _git_checkout ()
 		__gitcomp_builtin checkout
 		;;
 	*)
-		# check if --track, --no-track, or --no-guess was specified
-		# if so, disable DWIM mode
-		local flags="--track --no-track --no-guess" dwim_opt="--dwim"
-		if [ "$GIT_COMPLETION_CHECKOUT_NO_GUESS" = "1" ] ||
-		   [ -n "$(__git_find_on_cmdline "$flags")" ]; then
-			dwim_opt=''
-		fi
+		local dwim_opt="$(__git_checkout_default_dwim_mode)"
 		__git_complete_refs $dwim_opt
 		;;
 	esac
@@ -2257,18 +2325,7 @@ _git_switch ()
 		__gitcomp_builtin switch
 		;;
 	*)
-		# check if --track, --no-track, or --no-guess was specified
-		# if so, disable DWIM mode
-		local dwim_opt="--dwim" only_local_ref=n
-		if [ "$GIT_COMPLETION_CHECKOUT_NO_GUESS" = "1" ] ||
-		   [ -n "$(__git_find_on_cmdline "--track --no-track --no-guess")" ]; then
-			dwim_opt=''
-		fi
-		# explicit --guess enables DWIM mode regardless of
-		# $GIT_COMPLETION_CHECKOUT_NO_GUESS
-		if [ -n "$(__git_find_on_cmdline "--guess")" ]; then
-			dwim_opt='--dwim'
-		fi
+		local dwim_opt="$(__git_checkout_default_dwim_mode)" only_local_ref=n
 		if [ -z "$(__git_find_on_cmdline "-d --detach")" ]; then
 			only_local_ref=y
 		else
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index e4c48b20d39d..13d5a47e2912 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -1277,7 +1277,6 @@ test_expect_success 'git switch - with GIT_COMPLETION_CHECKOUT_NO_GUESS=1, compl
 	EOF
 '
 
-#TODO: --guess/--no-guess ordering is not taken into account
 #TODO: git switch completion includes unexpected references
 test_expect_failure 'git switch - --guess overrides GIT_COMPLETION_CHECKOUT_NO_GUESS=1, complete local branches and unique remote names for DWIM logic' '
 	GIT_COMPLETION_CHECKOUT_NO_GUESS=1 test_completion "git switch --guess " <<-\EOF
@@ -1288,7 +1287,6 @@ test_expect_failure 'git switch - --guess overrides GIT_COMPLETION_CHECKOUT_NO_G
 	EOF
 '
 
-#TODO: --guess/--no-guess ordering is not taken into account
 #TODO: git switch completion includes unexpected references
 test_expect_failure 'git switch - a later --guess overrides previous --no-guess, complete local and remote unique branches for DWIM' '
 	test_completion "git switch --no-guess --guess " <<-\EOF
@@ -1299,8 +1297,7 @@ test_expect_failure 'git switch - a later --guess overrides previous --no-guess,
 	EOF
 '
 
-#TODO: --guess/--no-guess ordering is not taken into account
-test_expect_failure 'git switch - a later --no-guess overrides previous --guess, complete only local branches' '
+test_expect_success 'git switch - a later --no-guess overrides previous --guess, complete only local branches' '
 	test_completion "git switch --guess --no-guess " <<-\EOF
 	master Z
 	matching-branch Z
@@ -1318,8 +1315,7 @@ test_expect_success 'git checkout - with GIT_COMPLETION_NO_GUESS=1 only complete
 	EOF
 '
 
-#TODO: git checkout does not override variable when --guess is provided
-test_expect_failure 'git checkout - --guess overrides GIT_COMPLETION_NO_GUESS=1, complete refs and unique remote branches for DWIM' '
+test_expect_success 'git checkout - --guess overrides GIT_COMPLETION_NO_GUESS=1, complete refs and unique remote branches for DWIM' '
 	GIT_COMPLETION_CHECKOUT_NO_GUESS=1 test_completion "git checkout --guess " <<-\EOF
 	HEAD Z
 	branch-in-other Z
@@ -1343,8 +1339,7 @@ test_expect_success 'git checkout - with --no-guess, only completes refs' '
 	EOF
 '
 
-#TODO: --guess/--no-guess ordering is not taken into account
-test_expect_failure 'git checkout - a later --guess overrides previous --no-guess, complete refs and unique remote branches for DWIM' '
+test_expect_success 'git checkout - a later --guess overrides previous --no-guess, complete refs and unique remote branches for DWIM' '
 	test_completion "git checkout --no-guess --guess " <<-\EOF
 	HEAD Z
 	branch-in-other Z
@@ -1544,7 +1539,8 @@ test_expect_failure 'git checkout - with -B, complete all references' '
 	EOF
 '
 
-test_expect_success 'git checkout - with -b and --track, complete all references' '
+#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_completion "git checkout -b new-branch --track " <<-EOF
 	HEAD Z
 	master Z
@@ -1555,7 +1551,8 @@ test_expect_success 'git checkout - with -b and --track, complete all references
 	EOF
 '
 
-test_expect_success 'git checkout - with -B and --track, complete all references' '
+#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_completion "git checkout -B new-branch --track " <<-EOF
 	HEAD Z
 	master Z
-- 
2.25.2


  parent reply	other threads:[~2020-05-28 18:11 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-05-28 18:10 [PATCH v3 00/16] improve switch/checkout completion Jacob Keller
2020-05-28 18:10 ` [PATCH v3 01/16] completion: add test showing subpar git switch completion Jacob Keller
2020-05-28 18:10 ` [PATCH v3 02/16] completion: add tests showing subpar DWIM logic for switch/checkout Jacob Keller
2020-05-28 18:10 ` [PATCH v3 03/16] completion: add tests showing subar checkout --detach logic Jacob Keller
2020-05-28 18:10 ` [PATCH v3 04/16] completion: add tests showing subpar switch/checkout --track logic Jacob Keller
2020-05-28 18:10 ` [PATCH v3 05/16] completion: add tests showing subpar -c/-C startpoint completion Jacob Keller
2020-05-28 18:10 ` [PATCH v3 06/16] completion: add tests showing subpar -c/C argument completion Jacob Keller
2020-05-28 18:10 ` [PATCH v3 07/16] completion: add tests showing subpar switch/checkout --orphan logic Jacob Keller
2020-05-28 18:10 ` [PATCH v3 08/16] completion: replace overloaded track term for __git_complete_refs Jacob Keller
2020-05-28 18:10 ` [PATCH v3 09/16] completion: extract function __git_dwim_remote_heads Jacob Keller
2020-05-28 18:10 ` [PATCH v3 10/16] completion: perform DWIM logic directly in __git_complete_refs Jacob Keller
2020-05-28 18:10 ` Jacob Keller [this message]
2020-05-28 18:10 ` [PATCH v3 12/16] completion: improve completion for git switch with no options Jacob Keller
2020-05-28 18:10 ` [PATCH v3 13/16] completion: improve handling of --detach in checkout Jacob Keller
2020-05-28 18:10 ` [PATCH v3 14/16] completion: improve handling of --track in switch/checkout Jacob Keller
2020-05-28 18:10 ` [PATCH v3 15/16] completion: improve handling of -c/-C and -b/-B " Jacob Keller
2020-05-28 18:10 ` [PATCH v3 16/16] completion: improve handling of --orphan option of switch/checkout Jacob Keller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200528181048.3509470-12-jacob.e.keller@intel.com \
    --to=jacob.e.keller@intel.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=jacob.keller@gmail.com \
    --cc=jrnieder@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).