threads / discuss / 57285

Some sub-commands can't be completed by TAB key.

Subject: Some sub-commands can't be completed by TAB key.

## tl;dr

17 messages between Jan 22, 2022 and Feb 7, 2022.

replies: 16people: 7as markdown or json

Hongyi Zhao· Jan 22, 2022, 08:42 UTC · lore

On Ubuntu 20.04.3 LTS, I use the following git version installed from its apt repository:

$ git --version git version 2.25.1

I find that there are some  sub-commands can't be completed by TAB key:
$ git <TAB>
add               cherry-pick       fetch             latexdiff
 pull              restore           status
am                citool            format-patch      log
 push              revert            submodule
apply             clean             fsck              merge
 range-diff        rm                switch
archive           clone             gc                mergetool
 rebase            send-email        tag
bisect            commit            gitk              mv
 reflog            shortlog          whatchanged
blame             config            grep              nbdiffdriver
 remote            show              worktree
branch            deborig           gui               nbdifftool
 repack            show-branch
bundle            describe          help              nbmergedriver
 replace           sparse-checkout
checkout          diff              init              nbmergetool
 request-pull      stage
cherry            difftool          instaweb          notes
 reset             stash

As you can see, there are some sub-commands which are not listed in the above list, for example, the following ones:

$ git ls-remote $ git ls-files

Any hints for this problem?
Regards
-- 
Assoc. Prof. Hongyi Zhao <hongyi.zhao@gmail.com>
Theory and Simulation of Materials
Hebei Vocational University of Technology and Engineering
No. 473, Quannan West Street, Xindu District, Xingtai, Hebei province
Johannes Sixt· Jan 22, 2022, 14:47 UTC · re: Hongyi Zhao · lore

Re: Some sub-commands can't be completed by TAB key.

Am 22.01.22 um 09:42 schrieb Hongyi Zhao:
Show 12 quoted lines
> I find that there are some  sub-commands can't be completed by TAB key:
> 
> $ git <TAB>
> add               cherry-pick       fetch             latexdiff
> [...]
> As you can see, there are some sub-commands which are not listed in
> the above list, for example, the following ones:
> 
> $ git ls-remote
> $ git ls-files
> 
> Any hints for this problem?

Tab completion is only available for user-facing sub-commands ("porcelain"), but not for sub-commands intended for scripting ("plumbing"). The intent is to make tab completion more efficient during day-to-day work on the command line. For example,

   $ git l<TAB>
arrives at
   $ git log <cursor here>
instead of
   log     ls-files     ls-remote     ls-tree
   $ git l<cursor here>
-- Hannes
Hongyi Zhao· Jan 23, 2022, 00:38 UTC · re: Johannes Sixt · lore

Re: Some sub-commands can't be completed by TAB key.

On Sat, Jan 22, 2022 at 10:47 PM Johannes Sixt <j6t@kdbg.org> wrote:
Show 19 quoted lines
>
> Am 22.01.22 um 09:42 schrieb Hongyi Zhao:
> > I find that there are some  sub-commands can't be completed by TAB key:
> >
> > $ git <TAB>
> > add               cherry-pick       fetch             latexdiff
> > [...]
> > As you can see, there are some sub-commands which are not listed in
> > the above list, for example, the following ones:
> >
> > $ git ls-remote
> > $ git ls-files
> >
> > Any hints for this problem?
>
> Tab completion is only available for user-facing sub-commands
> ("porcelain"), but not for sub-commands intended for scripting
> ("plumbing"). The intent is to make tab completion more efficient during
> day-to-day work on the command line. For example,

But there are so many git sub-commands, so if the plumbing feature is supported, it will facilitate user to check the availability of some sub-commands.

Show 5 quoted lines
>    $ git l<TAB>
>
> arrives at
>
>    $ git log <cursor here>
I see the following:

$ git l<TAB> latexdiff log

Show 6 quoted lines
> instead of
>
>    log     ls-files     ls-remote     ls-tree
>    $ git l<cursor here>
>
> -- Hannes
Philippe Blain· Jan 23, 2022, 17:31 UTC · re: Hongyi Zhao · lore

Re: Some sub-commands can't be completed by TAB key.

Hi Hongyi,
Le 2022-01-22 à 19:38, Hongyi Zhao a écrit :
Show 24 quoted lines
> On Sat, Jan 22, 2022 at 10:47 PM Johannes Sixt <j6t@kdbg.org> wrote:
>>
>> Am 22.01.22 um 09:42 schrieb Hongyi Zhao:
>>> I find that there are some  sub-commands can't be completed by TAB key:
>>>
>>> $ git <TAB>
>>> add               cherry-pick       fetch             latexdiff
>>> [...]
>>> As you can see, there are some sub-commands which are not listed in
>>> the above list, for example, the following ones:
>>>
>>> $ git ls-remote
>>> $ git ls-files
>>>
>>> Any hints for this problem?
>>
>> Tab completion is only available for user-facing sub-commands
>> ("porcelain"), but not for sub-commands intended for scripting
>> ("plumbing"). The intent is to make tab completion more efficient during
>> day-to-day work on the command line. For example,
> 
> But there are so many git sub-commands, so if the plumbing feature is
> supported, it will facilitate user to check the availability of some
> sub-commands.

If what you want to do is "check the availability" of some sub-command, you can simply do 'git <subcommand> -h', for example, and see if Git recognizes the subcommand.

If you mean discovering Git commands, you can use 'git help -a', which will list all commands, including pluming commands.

If you want to customize the Bash completion so that some select plumbing commands do appear in the tab completion, you can use the config 'completion.commands' [1]. Setting it to "ls-files ls-remote ls-tree" would then give you your desired output below.

Show 11 quoted lines
> 
>>    $ git l<TAB>
>>
>> arrives at
>>
>>    $ git log <cursor here>
> 
> I see the following:
> 
> $ git l<TAB>
> latexdiff   log
This would mean you have a 'git-latexdiff' command somewhere in your PATH.
Hope that helps,
Philippe.
[1] https://git-scm.com/docs/git-config#Documentation/git-config.txt-completioncommands
Junio C Hamano· Jan 23, 2022, 19:51 UTC · re: Philippe Blain · lore

Re: Some sub-commands can't be completed by TAB key.

Philippe Blain <levraiphilippeblain@gmail.com> writes:
Show 6 quoted lines
>> I see the following:
>> 
>> $ git l<TAB>
>> latexdiff   log
>
> This would mean you have a 'git-latexdiff' command somewhere in your PATH.

True. On Debian-based systems, the texlive-extra-utils package has /usr/bin/git-latexdiff and that is likely where it came from.

It is also worth noting that completion will also include whatever alias. I get "lg" in the mix because I have

        [alias]
                lg = "log --oneline"
in my $HOME/.gitconfig, for example.
Hongyi Zhao· Jan 24, 2022, 01:42 UTC · re: Junio C Hamano · lore

Re: Some sub-commands can't be completed by TAB key.

On Mon, Jan 24, 2022 at 3:51 AM Junio C Hamano <gitster@pobox.com> wrote:
Show 12 quoted lines
>
> Philippe Blain <levraiphilippeblain@gmail.com> writes:
>
> >> I see the following:
> >>
> >> $ git l<TAB>
> >> latexdiff   log
> >
> > This would mean you have a 'git-latexdiff' command somewhere in your PATH.
>
> True.  On Debian-based systems, the texlive-extra-utils package has
> /usr/bin/git-latexdiff and that is likely where it came from.
Mine comes from TexLive:

$ which git-latexdiff /opt/texlive/2021/bin/x86_64-linux/git-latexdiff

Show 7 quoted lines
> It is also worth noting that completion will also include whatever
> alias.  I get "lg" in the mix because I have
>
>         [alias]
>                 lg = "log --oneline"
>
> in my $HOME/.gitconfig, for example.
Good example. Got it.
HZ
João Victor Bonfim· Jan 24, 2022, 09:18 UTC · re: Junio C Hamano · lore

Re: Some sub-commands can't be completed by TAB key.

> It is also worth noting that completion will also include whatever
> alias.  I get "lg" in the mix because I have...

That sounds like something that should be hidden, no? Like, all aliases are left unmentioned?

Junio C Hamano· Jan 25, 2022, 07:33 UTC · re: João Victor Bonfim · lore

Re: Some sub-commands can't be completed by TAB key.

João Victor Bonfim <JoaoVictorBonfim+Git-Mail-List@protonmail.com> writes:

Show 5 quoted lines
>> It is also worth noting that completion will also include whatever
>> alias.  I get "lg" in the mix because I have...
>
> That sounds like something that should be hidden, no?
> Like, all aliases are left unmentioned?

Unlike the plumbing commands that are meant to be used in writing scripts and not typed in interactive sessions, and more like Porcelain commands that are meant to be used by human end-users in their interactive sessions by getting typed from the keyboard, an aliase is often (and certainly my "lg" is) defined in order to give a short-and-sweet typesaver to a command with common initial options that the user finds useful in their interactive sessions.

I am curious to find out what makes you think it is a good idea to omit them from completion.

Ævar Arnfjörð Bjarmason· Jan 25, 2022, 12:49 UTC · re: Hongyi Zhao · lore

[PATCH] completion: add a GIT_COMPLETION_SHOW_ALL_COMMANDS

Add a GIT_COMPLETION_SHOW_ALL_COMMANDS=1 configuration setting to go with the existing GIT_COMPLETION_SHOW_ALL=1 added in c099f579b98 (completion: add GIT_COMPLETION_SHOW_ALL env var, 2020-08-19).

This will include plumbing commands such as "cat-file" in "git <TAB>" and "git c<TAB>" completion. Without/with this I have 134 and 243 completion with git <TAB>, respectively.

It was already possible to do this by tweaking GIT_COMPLETION_SHOW_ALL_COMMANDS from the outside, that testing variable was added in 84a97131065 (completion: let git provide the completable command list, 2018-05-20). Doing this before loading git-completion.bash worked:

    export GIT_TESTING_PORCELAIN_COMMAND_LIST="$(git --list-cmds=builtins,main,list-mainporcelain,others,nohelpers,alias,list-complete,config)"

But such testing variables are not meant to be used from the outside, and we make no guarantees that those internal won't change. So let's expose this as a dedicated configuration knob.

1. https://lore.kernel.org/git/CAGP6POJ9gwp+t-eP3TPkivBLLbNb2+qj=61Mehcj=1BgrVOSLA@mail.gmail.com/
Reported-by: Hongyi Zhao <hongyi.zhao@gmail.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
n Sat, Jan 22 2022, Hongyi Zhao wrote:
Show 8 quoted lines
> On Ubuntu 20.04.3 LTS, I use the following git version installed from
> its apt repository:
>
> $ git --version
> git version 2.25.1
>
> I find that there are some  sub-commands can't be completed by TAB key
> [...]

Others have explained why this happens, but as noted above an easy but undocumented workaround for this that I use, because I'd like e.g. "cat-file" to show up in this completion. In your ~/.bashrc or equivalent do something like this before it loads git-completion.bash:

    export GIT_TESTING_PORCELAIN_COMMAND_LIST="$(git --list-cmds=builtins,main,others,alias)"

But it would be even nicer to turn that into a first-class feature, this patch does so. With this you can just do:

    export GIT_COMPLETION_SHOW_ALL_COMMANDS=1
 contrib/completion/git-completion.bash | 13 ++++++++++++-
 t/t9902-completion.sh                  | 27 ++++++++++++++++++++++++++
 2 files changed, 39 insertions(+), 1 deletion(-)
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 377d6c5494a..2436b8eb6b9 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -49,6 +49,11 @@
 #     and git-switch completion (e.g., completing "foo" when "origin/foo"
 #     exists).
 #
+#   GIT_COMPLETION_SHOW_ALL_COMMANDS
+#
+#     When set to "1" suggest all commands, including plumbing commands
+#     which are hidden by default (e.g. "cat-file" on "git ca<TAB>").
+#
 #   GIT_COMPLETION_SHOW_ALL
 #
 #     When set to "1" suggest all options, including options which are
@@ -3455,7 +3460,13 @@ __git_main ()
 			then
 				__gitcomp "$GIT_TESTING_PORCELAIN_COMMAND_LIST"
 			else
-				__gitcomp "$(__git --list-cmds=list-mainporcelain,others,nohelpers,alias,list-complete,config)"
+				local list_cmds=list-mainporcelain,others,nohelpers,alias,list-complete,config
+
+				if test "${GIT_COMPLETION_SHOW_ALL_COMMANDS-}" = "1"
+				then
+					list_cmds=builtins,$list_cmds
+				fi
+				__gitcomp "$(__git --list-cmds=$list_cmds)"
 			fi
 			;;
 		esac
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index 98c62806328..e3ea6a41b00 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -2432,6 +2432,33 @@ test_expect_success 'option aliases are shown with GIT_COMPLETION_SHOW_ALL' '
 	EOF
 '
 
+test_expect_success 'plumbing commands are excluded without GIT_COMPLETION_SHOW_ALL_COMMANDS' '
+	. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
+	sane_unset GIT_TESTING_PORCELAIN_COMMAND_LIST &&
+
+	# Just mainporcelain, not plumbing commands
+	run_completion "git c" &&
+	grep checkout out &&
+	! grep cat-file out
+'
+
+test_expect_success 'all commands are shown with GIT_COMPLETION_SHOW_ALL_COMMANDS (also main non-builtin)' '
+	. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
+	GIT_COMPLETION_SHOW_ALL_COMMANDS=1 &&
+	export GIT_COMPLETION_SHOW_ALL_COMMANDS &&
+	sane_unset GIT_TESTING_PORCELAIN_COMMAND_LIST &&
+
+	# Both mainporcelain and plumbing commands
+	run_completion "git c" &&
+	grep checkout out &&
+	grep cat-file out &&
+
+	# Check "gitk", a "main" command, but not a built-in + more plumbing
+	run_completion "git g" &&
+	grep gitk out &&
+	grep get-tar-commit-id out
+'
+
 test_expect_success '__git_complete' '
 	unset -f __git_wrap__git_main &&
 
-- 
2.35.0.rc2.886.ga87834885e8
Junio C Hamano· Jan 26, 2022, 22:34 UTC · re: Ævar Arnfjörð Bjarmason · lore

Re: [PATCH] completion: add a GIT_COMPLETION_SHOW_ALL_COMMANDS

Ævar Arnfjörð Bjarmason  <avarab@gmail.com> writes:
Show 8 quoted lines
> Add a GIT_COMPLETION_SHOW_ALL_COMMANDS=1 configuration setting to go
> with the existing GIT_COMPLETION_SHOW_ALL=1 added in
> c099f579b98 (completion: add GIT_COMPLETION_SHOW_ALL env var,
> 2020-08-19).
>
> This will include plumbing commands such as "cat-file" in "git <TAB>"
> and "git c<TAB>" completion. Without/with this I have 134 and 243
> completion with git <TAB>, respectively.
OK.  This makes sense in the sense that more choice is better.
Show 5 quoted lines
> It was already possible to do this by tweaking
> GIT_COMPLETION_SHOW_ALL_COMMANDS from the outside, that testing
> variable was added in 84a97131065 (completion: let git provide the
> completable command list, 2018-05-20). Doing this before loading
> git-completion.bash worked:

Perhaps there is a typo that ruined whole the paragraph. We are adding that variable with this patch, so by definition, it did not exist before, which means we cannot "tweak" it because it did not exist.

Show 11 quoted lines
> --- a/contrib/completion/git-completion.bash
> +++ b/contrib/completion/git-completion.bash
> @@ -49,6 +49,11 @@
>  #     and git-switch completion (e.g., completing "foo" when "origin/foo"
>  #     exists).
>  #
> +#   GIT_COMPLETION_SHOW_ALL_COMMANDS
> +#
> +#     When set to "1" suggest all commands, including plumbing commands
> +#     which are hidden by default (e.g. "cat-file" on "git ca<TAB>").
> +#

Usually we frown upon inserting a new thing to the middle of a list of things that has no inherent order. In this case, I think this is OK, as the existing "all" (below) is about completing options, while the new one is about completing subcommands, and the latter is at a higher conceptual level than the former.

Show 13 quoted lines
>  #   GIT_COMPLETION_SHOW_ALL
>  #
>  #     When set to "1" suggest all options, including options which are
> @@ -3455,7 +3460,13 @@ __git_main ()
>  			then
>  				__gitcomp "$GIT_TESTING_PORCELAIN_COMMAND_LIST"
>  			else
> -				__gitcomp "$(__git --list-cmds=list-mainporcelain,others,nohelpers,alias,list-complete,config)"
> +				local list_cmds=list-mainporcelain,others,nohelpers,alias,list-complete,config
> +
> +				if test "${GIT_COMPLETION_SHOW_ALL_COMMANDS-}" = "1"
> +				then
> +					list_cmds=builtins,$list_cmds

It is sad that there is no "plumbing" class (assuming the goal is "we by default exclude plumbing, so add that to the list"), or just "everything under the sun" class. If there were a plumbing command that is not implemented as a built-in, adding buitlins to list_cmds will not show the command, will it? Also, because nohelpers is not removed from list_cmds, whatever command that were removed from exclude_helpers_from_list() will be hidden.

It looks as though help.c needs a new list_all_cmds() that can be called from git.c::list_cmds() when "all" is asked for, and dumps everything from command_list[] plus whatever load_command_list() loads.

Show 5 quoted lines
> +				fi
> +				__gitcomp "$(__git --list-cmds=$list_cmds)"
>  			fi
>  			;;
>  		esac

Having said all that, assuming that including "builtins" is a good enough approximation (which I do not have no opinion on), the implementation looks good to me.

Show 11 quoted lines
> diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
> index 98c62806328..e3ea6a41b00 100755
> --- a/t/t9902-completion.sh
> +++ b/t/t9902-completion.sh
> @@ -2432,6 +2432,33 @@ test_expect_success 'option aliases are shown with GIT_COMPLETION_SHOW_ALL' '
>  	EOF
>  '
>  
> +test_expect_success 'plumbing commands are excluded without GIT_COMPLETION_SHOW_ALL_COMMANDS' '
> +	. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
> +	sane_unset GIT_TESTING_PORCELAIN_COMMAND_LIST &&

As we've done dot-sourcing of the file at the beginning of the script already, dot-sourcing the same thing again would only overwrite what was done before, without clearing the deck. Which may not hurt for the purpose of _this_ test _right_ _now_q.

But as this is not done inside a subshell, whetever we dot-source here will persist til the end of the script. Which may be more problematic as it will affect the tests that come (and new tests that will be added) after this point.

The same comment applies to the other new test added immediately after this one.

Other than that, looks sensible to me.
Thanks.
Ævar Arnfjörð Bjarmason· Feb 2, 2022, 11:15 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v2 0/2] completion: add a GIT_COMPLETION_SHOW_ALL_COMMANDS

This series adds an opt-in configuration to make "git <TAB>" complete the likes of "cat-file" (plumbing), in addition to the existing completion for the likes of "status" (porcelain).

This v2 addresses feedback from Junio on the v1, I also added a preceding patch to change the re-sourcing of git-completion.bash in some existing tests to use a subshell, which is a pattern I'd buggily copied in the v1.

Ævar Arnfjörð Bjarmason (2):
  completion tests: re-source git-completion.bash in a subshell
  completion: add a GIT_COMPLETION_SHOW_ALL_COMMANDS
 contrib/completion/git-completion.bash | 13 ++++-
 t/t9902-completion.sh                  | 81 +++++++++++++++++++-------
 2 files changed, 72 insertions(+), 22 deletions(-)
Range-diff against v1:
-:  ----------- > 1:  cf09546e079 completion tests: re-source git-completion.bash in a subshell
1:  5f18305ca08 ! 2:  2e2e3569e02 completion: add a GIT_COMPLETION_SHOW_ALL_COMMANDS
    @@ Commit message
         completion with git <TAB>, respectively.
     
         It was already possible to do this by tweaking
    -    GIT_COMPLETION_SHOW_ALL_COMMANDS from the outside, that testing
    +    GIT_TESTING_PORCELAIN_COMMAND_LIST= from the outside, that testing
         variable was added in 84a97131065 (completion: let git provide the
         completable command list, 2018-05-20). Doing this before loading
         git-completion.bash worked:
    @@ Commit message
         and we make no guarantees that those internal won't change. So let's
         expose this as a dedicated configuration knob.
     
    +    It would be better to teach --list-cmds=* a new category which would
    +    include all of these groups, but that's a larger change that we can
    +    leave for some other time.
    +
         1. https://lore.kernel.org/git/CAGP6POJ9gwp+t-eP3TPkivBLLbNb2+qj=61Mehcj=1BgrVOSLA@mail.gmail.com/
     
         Reported-by: Hongyi Zhao <hongyi.zhao@gmail.com>
    @@ contrib/completion/git-completion.bash: __git_main ()
     
      ## t/t9902-completion.sh ##
     @@ t/t9902-completion.sh: test_expect_success 'option aliases are shown with GIT_COMPLETION_SHOW_ALL' '
    - 	EOF
    + 	)
      '
      
     +test_expect_success 'plumbing commands are excluded without GIT_COMPLETION_SHOW_ALL_COMMANDS' '
    -+	. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
    -+	sane_unset GIT_TESTING_PORCELAIN_COMMAND_LIST &&
    ++	(
    ++		. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
    ++		sane_unset GIT_TESTING_PORCELAIN_COMMAND_LIST &&
     +
    -+	# Just mainporcelain, not plumbing commands
    -+	run_completion "git c" &&
    -+	grep checkout out &&
    -+	! grep cat-file out
    ++		# Just mainporcelain, not plumbing commands
    ++		run_completion "git c" &&
    ++		grep checkout out &&
    ++		! grep cat-file out
    ++	)
     +'
     +
     +test_expect_success 'all commands are shown with GIT_COMPLETION_SHOW_ALL_COMMANDS (also main non-builtin)' '
    -+	. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
    -+	GIT_COMPLETION_SHOW_ALL_COMMANDS=1 &&
    -+	export GIT_COMPLETION_SHOW_ALL_COMMANDS &&
    -+	sane_unset GIT_TESTING_PORCELAIN_COMMAND_LIST &&
    ++	(
    ++		. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
    ++		GIT_COMPLETION_SHOW_ALL_COMMANDS=1 &&
    ++		export GIT_COMPLETION_SHOW_ALL_COMMANDS &&
    ++		sane_unset GIT_TESTING_PORCELAIN_COMMAND_LIST &&
     +
    -+	# Both mainporcelain and plumbing commands
    -+	run_completion "git c" &&
    -+	grep checkout out &&
    -+	grep cat-file out &&
    ++		# Both mainporcelain and plumbing commands
    ++		run_completion "git c" &&
    ++		grep checkout out &&
    ++		grep cat-file out &&
     +
    -+	# Check "gitk", a "main" command, but not a built-in + more plumbing
    -+	run_completion "git g" &&
    -+	grep gitk out &&
    -+	grep get-tar-commit-id out
    ++		# Check "gitk", a "main" command, but not a built-in + more plumbing
    ++		run_completion "git g" &&
    ++		grep gitk out &&
    ++		grep get-tar-commit-id out
    ++	)
     +'
     +
      test_expect_success '__git_complete' '
-- 
2.35.0.913.g12b4baa2536
Ævar Arnfjörð Bjarmason· Feb 2, 2022, 11:15 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v2 1/2] completion tests: re-source git-completion.bash in a subshell

Change tests of git-completion.bash that re-source it to do so inside a subshell. Re-sourcing it will clobber variables it sets, and in the case of the "GIT_COMPLETION_SHOW_ALL=1" test added in ca2d62b7879 (parse-options: don't complete option aliases by default, 2021-07-16) change the behavior of the completion persistently.

Aside from the addition of "(" and ")" on new lines this is an indentation-only change, only the "(" and ")" lines are changed under "git diff -w".

So let's change that test, and for good measure do the same for the three tests that precede it, which were added in 8b0eaa41f23 (completion: clear cached --options when sourcing the completion script, 2018-03-22). The may not be wrong, but doing this establishes a more reliable pattern for future tests, which might use these as a template to copy.

Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 t/t9902-completion.sh | 50 +++++++++++++++++++++++++------------------
 1 file changed, 29 insertions(+), 21 deletions(-)
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index 98c62806328..c9805f2147d 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -2396,27 +2396,33 @@ test_expect_success 'options with value' '
 '
 
 test_expect_success 'sourcing the completion script clears cached commands' '
-	__git_compute_all_commands &&
-	verbose test -n "$__git_all_commands" &&
-	. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
-	verbose test -z "$__git_all_commands"
+	(
+		__git_compute_all_commands &&
+		verbose test -n "$__git_all_commands" &&
+		. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
+		verbose test -z "$__git_all_commands"
+	)
 '
 
 test_expect_success 'sourcing the completion script clears cached merge strategies' '
-	__git_compute_merge_strategies &&
-	verbose test -n "$__git_merge_strategies" &&
-	. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
-	verbose test -z "$__git_merge_strategies"
+	(
+		__git_compute_merge_strategies &&
+		verbose test -n "$__git_merge_strategies" &&
+		. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
+		verbose test -z "$__git_merge_strategies"
+	)
 '
 
 test_expect_success 'sourcing the completion script clears cached --options' '
-	__gitcomp_builtin checkout &&
-	verbose test -n "$__gitcomp_builtin_checkout" &&
-	__gitcomp_builtin notes_edit &&
-	verbose test -n "$__gitcomp_builtin_notes_edit" &&
-	. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
-	verbose test -z "$__gitcomp_builtin_checkout" &&
-	verbose test -z "$__gitcomp_builtin_notes_edit"
+	(
+		__gitcomp_builtin checkout &&
+		verbose test -n "$__gitcomp_builtin_checkout" &&
+		__gitcomp_builtin notes_edit &&
+		verbose test -n "$__gitcomp_builtin_notes_edit" &&
+		. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
+		verbose test -z "$__gitcomp_builtin_checkout" &&
+		verbose test -z "$__gitcomp_builtin_notes_edit"
+	)
 '
 
 test_expect_success 'option aliases are not shown by default' '
@@ -2424,12 +2430,14 @@ test_expect_success 'option aliases are not shown by default' '
 '
 
 test_expect_success 'option aliases are shown with GIT_COMPLETION_SHOW_ALL' '
-	. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
-	GIT_COMPLETION_SHOW_ALL=1 && export GIT_COMPLETION_SHOW_ALL &&
-	test_completion "git clone --recurs" <<-\EOF
-	--recurse-submodules Z
-	--recursive Z
-	EOF
+	(
+		. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
+		GIT_COMPLETION_SHOW_ALL=1 && export GIT_COMPLETION_SHOW_ALL &&
+		test_completion "git clone --recurs" <<-\EOF
+		--recurse-submodules Z
+		--recursive Z
+		EOF
+	)
 '
 
 test_expect_success '__git_complete' '
-- 
2.35.0.913.g12b4baa2536
Ævar Arnfjörð Bjarmason· Feb 2, 2022, 11:15 UTC · re: Ævar Arnfjörð Bjarmason · lore

[PATCH v2 2/2] completion: add a GIT_COMPLETION_SHOW_ALL_COMMANDS

Add a GIT_COMPLETION_SHOW_ALL_COMMANDS=1 configuration setting to go with the existing GIT_COMPLETION_SHOW_ALL=1 added in c099f579b98 (completion: add GIT_COMPLETION_SHOW_ALL env var, 2020-08-19).

This will include plumbing commands such as "cat-file" in "git <TAB>" and "git c<TAB>" completion. Without/with this I have 134 and 243 completion with git <TAB>, respectively.

It was already possible to do this by tweaking GIT_TESTING_PORCELAIN_COMMAND_LIST= from the outside, that testing variable was added in 84a97131065 (completion: let git provide the completable command list, 2018-05-20). Doing this before loading git-completion.bash worked:

    export GIT_TESTING_PORCELAIN_COMMAND_LIST="$(git --list-cmds=builtins,main,list-mainporcelain,others,nohelpers,alias,list-complete,config)"

But such testing variables are not meant to be used from the outside, and we make no guarantees that those internal won't change. So let's expose this as a dedicated configuration knob.

It would be better to teach --list-cmds=* a new category which would include all of these groups, but that's a larger change that we can leave for some other time.

1. https://lore.kernel.org/git/CAGP6POJ9gwp+t-eP3TPkivBLLbNb2+qj=61Mehcj=1BgrVOSLA@mail.gmail.com/
Reported-by: Hongyi Zhao <hongyi.zhao@gmail.com>
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
---
 contrib/completion/git-completion.bash | 13 ++++++++++-
 t/t9902-completion.sh                  | 31 ++++++++++++++++++++++++++
 2 files changed, 43 insertions(+), 1 deletion(-)
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 377d6c5494a..2436b8eb6b9 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -49,6 +49,11 @@
 #     and git-switch completion (e.g., completing "foo" when "origin/foo"
 #     exists).
 #
+#   GIT_COMPLETION_SHOW_ALL_COMMANDS
+#
+#     When set to "1" suggest all commands, including plumbing commands
+#     which are hidden by default (e.g. "cat-file" on "git ca<TAB>").
+#
 #   GIT_COMPLETION_SHOW_ALL
 #
 #     When set to "1" suggest all options, including options which are
@@ -3455,7 +3460,13 @@ __git_main ()
 			then
 				__gitcomp "$GIT_TESTING_PORCELAIN_COMMAND_LIST"
 			else
-				__gitcomp "$(__git --list-cmds=list-mainporcelain,others,nohelpers,alias,list-complete,config)"
+				local list_cmds=list-mainporcelain,others,nohelpers,alias,list-complete,config
+
+				if test "${GIT_COMPLETION_SHOW_ALL_COMMANDS-}" = "1"
+				then
+					list_cmds=builtins,$list_cmds
+				fi
+				__gitcomp "$(__git --list-cmds=$list_cmds)"
 			fi
 			;;
 		esac
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index c9805f2147d..c6d6d6ef896 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -2440,6 +2440,37 @@ test_expect_success 'option aliases are shown with GIT_COMPLETION_SHOW_ALL' '
 	)
 '
 
+test_expect_success 'plumbing commands are excluded without GIT_COMPLETION_SHOW_ALL_COMMANDS' '
+	(
+		. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
+		sane_unset GIT_TESTING_PORCELAIN_COMMAND_LIST &&
+
+		# Just mainporcelain, not plumbing commands
+		run_completion "git c" &&
+		grep checkout out &&
+		! grep cat-file out
+	)
+'
+
+test_expect_success 'all commands are shown with GIT_COMPLETION_SHOW_ALL_COMMANDS (also main non-builtin)' '
+	(
+		. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
+		GIT_COMPLETION_SHOW_ALL_COMMANDS=1 &&
+		export GIT_COMPLETION_SHOW_ALL_COMMANDS &&
+		sane_unset GIT_TESTING_PORCELAIN_COMMAND_LIST &&
+
+		# Both mainporcelain and plumbing commands
+		run_completion "git c" &&
+		grep checkout out &&
+		grep cat-file out &&
+
+		# Check "gitk", a "main" command, but not a built-in + more plumbing
+		run_completion "git g" &&
+		grep gitk out &&
+		grep get-tar-commit-id out
+	)
+'
+
 test_expect_success '__git_complete' '
 	unset -f __git_wrap__git_main &&
 
-- 
2.35.0.913.g12b4baa2536
SZEDER Gábor· Feb 6, 2022, 13:30 UTC · re: Ævar Arnfjörð Bjarmason · lore

Re: [PATCH v2 2/2] completion: add a GIT_COMPLETION_SHOW_ALL_COMMANDS

On Wed, Feb 02, 2022 at 12:15:10PM +0100, Ævar Arnfjörð Bjarmason wrote:
Show 7 quoted lines
> Add a GIT_COMPLETION_SHOW_ALL_COMMANDS=1 configuration setting to go
> with the existing GIT_COMPLETION_SHOW_ALL=1 added in
> c099f579b98 (completion: add GIT_COMPLETION_SHOW_ALL env var,
> 2020-08-19).
> 
> This will include plumbing commands such as "cat-file" in "git <TAB>"
> and "git c<TAB>" completion.

I've tried this a couple of times in the last dozen years or so... and ended up hating it every single time, because it too often made completion of frequently used porcelain commands more cumbersome, and quickly reverted it.

Since 6532f3740b (completion: allow to customize the completable command list, 2018-05-20) it is possible to include and exclude certain commands from the list offered for 'git <TAB>'. So if you use some plumbing command frequently, then you can add them to the 'completion.commands' config variable, and they will show up for 'git <TAB>', too, without any of the other plumbing commands to get annoying.

To complete only rarely used plumbing commands in a non-intrusive way, in my experience, it's best to first attempt to complete only porcelains and aliases, and fall back to complete all commands, plumbing included, only when no porcelains match the current word to be completed. E.g.:

  $ git d<TAB>
  describe   diff   difftool
  $ git diff-<TAB>
  diff-files   diff-index   diff-tree
  $ git p<TAB>
  prune   pull    push    
  $ git pa<TAB>
  pack-objects     pack-redundant   pack-refs        patch-id 
  ---   >8   ---
Subject: [PATCH] completion: list all git commands as fallback
---
 contrib/completion/git-completion.bash | 3 +++
 1 file changed, 3 insertions(+)
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 3edd1cade6..67978e6f22 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -3465,6 +3465,9 @@ __git_main ()
 				__gitcomp "$GIT_TESTING_PORCELAIN_COMMAND_LIST"
 			else
 				__gitcomp "$(__git --list-cmds=list-mainporcelain,others,nohelpers,alias,list-complete,config)"
+				if [ ${#COMPREPLY[@]} -eq 0 ]; then
+					__gitcomp "$(__git --list-cmds=main,others,nohelpers,alias,list-complete,config)"
+				fi
 			fi
 			;;
 		esac
-- 
2.35.1.482.g3282949ee0

  ---   8<   ---

I've been using 'completion.commands' and the patch above for a few
years now, and this combination worked out the best so far.

> Without/with this I have 134 and 243
> completion with git <TAB>, respectively.

Those numbers include all your aliases and additional 'git-foo'
commands in your PATH; I only get 74 without this patch.  To show the
effect of this patch I think it would be more relevant to count only
Git's commands.


> It was already possible to do this by tweaking
> GIT_TESTING_PORCELAIN_COMMAND_LIST= from the outside, that testing
> variable was added in 84a97131065 (completion: let git provide the
> completable command list, 2018-05-20). Doing this before loading
> git-completion.bash worked:
> 
>     export GIT_TESTING_PORCELAIN_COMMAND_LIST="$(git --list-cmds=builtins,main,list-mainporcelain,others,nohelpers,alias,list-complete,config)"
> 
> But such testing variables are not meant to be used from the outside,
> and we make no guarantees that those internal won't change. So let's
> expose this as a dedicated configuration knob.
> 
> It would be better to teach --list-cmds=* a new category which would
> include all of these groups, but that's a larger change that we can
> leave for some other time.
> 
> 1. https://lore.kernel.org/git/CAGP6POJ9gwp+t-eP3TPkivBLLbNb2+qj=61Mehcj=1BgrVOSLA@mail.gmail.com/
> 
> Reported-by: Hongyi Zhao <hongyi.zhao@gmail.com>
> Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
> ---
>  contrib/completion/git-completion.bash | 13 ++++++++++-
>  t/t9902-completion.sh                  | 31 ++++++++++++++++++++++++++
>  2 files changed, 43 insertions(+), 1 deletion(-)
> 
> diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
> index 377d6c5494a..2436b8eb6b9 100644
> --- a/contrib/completion/git-completion.bash
> +++ b/contrib/completion/git-completion.bash
> @@ -49,6 +49,11 @@
>  #     and git-switch completion (e.g., completing "foo" when "origin/foo"
>  #     exists).
>  #
> +#   GIT_COMPLETION_SHOW_ALL_COMMANDS
> +#
> +#     When set to "1" suggest all commands, including plumbing commands
> +#     which are hidden by default (e.g. "cat-file" on "git ca<TAB>").
> +#
>  #   GIT_COMPLETION_SHOW_ALL
>  #
>  #     When set to "1" suggest all options, including options which are
> @@ -3455,7 +3460,13 @@ __git_main ()
>  			then
>  				__gitcomp "$GIT_TESTING_PORCELAIN_COMMAND_LIST"
>  			else
> -				__gitcomp "$(__git --list-cmds=list-mainporcelain,others,nohelpers,alias,list-complete,config)"
> +				local list_cmds=list-mainporcelain,others,nohelpers,alias,list-complete,config
> +
> +				if test "${GIT_COMPLETION_SHOW_ALL_COMMANDS-}" = "1"
> +				then
> +					list_cmds=builtins,$list_cmds
> +				fi
> +				__gitcomp "$(__git --list-cmds=$list_cmds)"
>  			fi
>  			;;
>  		esac
> diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
> index c9805f2147d..c6d6d6ef896 100755
> --- a/t/t9902-completion.sh
> +++ b/t/t9902-completion.sh
> @@ -2440,6 +2440,37 @@ test_expect_success 'option aliases are shown with GIT_COMPLETION_SHOW_ALL' '
>  	)
>  '
>  
> +test_expect_success 'plumbing commands are excluded without GIT_COMPLETION_SHOW_ALL_COMMANDS' '
> +	(
> +		. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
> +		sane_unset GIT_TESTING_PORCELAIN_COMMAND_LIST &&
> +
> +		# Just mainporcelain, not plumbing commands
> +		run_completion "git c" &&
> +		grep checkout out &&
> +		! grep cat-file out
> +	)
> +'
> +
> +test_expect_success 'all commands are shown with GIT_COMPLETION_SHOW_ALL_COMMANDS (also main non-builtin)' '
> +	(
> +		. "$GIT_BUILD_DIR/contrib/completion/git-completion.bash" &&
> +		GIT_COMPLETION_SHOW_ALL_COMMANDS=1 &&
> +		export GIT_COMPLETION_SHOW_ALL_COMMANDS &&

This variable only affects the completion script itself, but none of
the commands invoked by it, so the 'export' is unnecessary.

> +		sane_unset GIT_TESTING_PORCELAIN_COMMAND_LIST &&
> +
> +		# Both mainporcelain and plumbing commands
> +		run_completion "git c" &&
> +		grep checkout out &&
> +		grep cat-file out &&
> +
> +		# Check "gitk", a "main" command, but not a built-in + more plumbing
> +		run_completion "git g" &&
> +		grep gitk out &&
> +		grep get-tar-commit-id out
> +	)
> +'
> +
>  test_expect_success '__git_complete' '
>  	unset -f __git_wrap__git_main &&
>  
> -- 
> 2.35.0.913.g12b4baa2536
> 
Junio C Hamano· Feb 6, 2022, 20:09 UTC · re: SZEDER Gábor · lore

Re: [PATCH v2 2/2] completion: add a GIT_COMPLETION_SHOW_ALL_COMMANDS

SZEDER Gábor <szeder.dev@gmail.com> writes:
Show 10 quoted lines
> To complete only rarely used plumbing commands in a non-intrusive way,
> in my experience, it's best to first attempt to complete only
> porcelains and aliases, and fall back to complete all commands,
> plumbing included, only when no porcelains match the current word to
> be completed.  E.g.:
>
>   $ git d<TAB>
>   describe   diff   difftool
>   $ git diff-<TAB>
>   diff-files   diff-index   diff-tree
So after getting
    $ git diff<TAB>
    diff difftool

you _have_ to know, if you are not happy with these two, that the next letter in the name of the command you forgot is a dash, to be able to say

    $ git diff-<TAB>

which is a bit unfortunate, but I agree that it is much nicer than getting all the plumbing when trying to complete "git d<TAB>".

I wonder if we can do better, and teach the completion logic an ability to say this: "I gave 'diff and difftool' after being asked for 'git diff<TAB>' and then the user is asking the same again without choosing either. Perhaps I should add less frequent one to the mix"?

I.e. the end-user session may look like
    $ git diff<TAB>
    diff difftool
    $ git diff<TAB>
    diff difftool diff-files diff-index diff-tree
?
SZEDER Gábor· Feb 6, 2022, 22:47 UTC · re: Junio C Hamano · lore

Re: [PATCH v2 2/2] completion: add a GIT_COMPLETION_SHOW_ALL_COMMANDS

On Sun, Feb 06, 2022 at 12:09:35PM -0800, Junio C Hamano wrote:
Show 20 quoted lines
> SZEDER Gábor <szeder.dev@gmail.com> writes:
> 
> > To complete only rarely used plumbing commands in a non-intrusive way,
> > in my experience, it's best to first attempt to complete only
> > porcelains and aliases, and fall back to complete all commands,
> > plumbing included, only when no porcelains match the current word to
> > be completed.  E.g.:
> >
> >   $ git d<TAB>
> >   describe   diff   difftool
> >   $ git diff-<TAB>
> >   diff-files   diff-index   diff-tree
> 
> So after getting
> 
>     $ git diff<TAB>
>     diff difftool
> 
> you _have_ to know, if you are not happy with these two, that the
> next letter in the name of the command you forgot is a dash,

Yeah, it can only save a couple of keystrokes, but it's not really useful when you want to use it to jog your memory. I naively assumed that if you use plumbing, then you know what you are doing and which command you want to execute :)

Show 22 quoted lines
> to be
> able to say
> 
>     $ git diff-<TAB>
> 
> which is a bit unfortunate, but I agree that it is much nicer than
> getting all the plumbing when trying to complete "git d<TAB>".
> 
> I wonder if we can do better, and teach the completion logic an
> ability to say this: "I gave 'diff and difftool' after being asked
> for 'git diff<TAB>' and then the user is asking the same again
> without choosing either. Perhaps I should add less frequent one to
> the mix"?
> 
> I.e. the end-user session may look like
> 
>     $ git diff<TAB>
>     diff difftool
>     $ git diff<TAB>
>     diff difftool diff-files diff-index diff-tree
> 
> ?

Hrm, interesting, but dunno. When completing commands in __git_main() we could save the current word to be completed in a variable, and when completing commands the next time we could check whether the current word is still the same, and then include plumbing as well. However, when the current word can't be uniquely completed, then we have to press TAB twice to get the list of possible completion, so we have to preserve the last two current words, and only list plumbing when both match.

  ---   >8   ---
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 377d6c5494..cda6b48c4e 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -3455,8 +3455,17 @@ __git_main ()
 			then
 				__gitcomp "$GIT_TESTING_PORCELAIN_COMMAND_LIST"
 			else
-				__gitcomp "$(__git --list-cmds=list-mainporcelain,others,nohelpers,alias,list-complete,config)"
+				echo >>/tmp/COMPLOG "__git_main() cur: '$cur' last: '$__git_last_command_cur' last2: '$__git_last_command_cur2'"
+				if test "$cur" = "$__git_last_command_cur" &&
+				   test "$cur" = "$__git_last_command_cur2"
+				then
+					__gitcomp "$(__git --list-cmds=main,others,nohelpers,alias,list-complete)"
+				else
+					__gitcomp "$(__git --list-cmds=list-mainporcelain,others,nohelpers,alias,list-complete,config)"
+				fi
 			fi
+			__git_last_command_cur2=$__git_last_command_cur
+			__git_last_command_cur=$cur
 			;;
 		esac
 		return

  ---   8<   ---

Superficial testing shows that it appears to work in common cases, but
we'll have to think it through when and how to clear these variables.
E.g.:

  $ git d<TAB><TAB>
  describe   diff   difftool
  # Oh, but I wanted to disable the pager
  $ git --no-p<TAB>
  # this completes the option uniquely
  $ git --no-pager d<TAB><TAB>
  daemon     diff         diff-index   diff-tree
  describe   diff-files   difftool

I think here it should list only porcelains, but because both those
last_cur variables still contain 'd', it lists plumbing as well.

And, of course, 'git <TAB><TAB>' in a newly started terminal should
list only porcelains, but it lists plumbing as well.
Junio C Hamano· Feb 7, 2022, 07:03 UTC · re: SZEDER Gábor · lore

Re: [PATCH v2 2/2] completion: add a GIT_COMPLETION_SHOW_ALL_COMMANDS

SZEDER Gábor <szeder.dev@gmail.com> writes:
Show 15 quoted lines
> Superficial testing shows that it appears to work in common cases, but
> we'll have to think it through when and how to clear these variables.
> E.g.:
>
>   $ git d<TAB><TAB>
>   describe   diff   difftool
>   # Oh, but I wanted to disable the pager
>   $ git --no-p<TAB>
>   # this completes the option uniquely
>   $ git --no-pager d<TAB><TAB>
>   daemon     diff         diff-index   diff-tree
>   describe   diff-files   difftool
>
> I think here it should list only porcelains, but because both those
> last_cur variables still contain 'd', it lists plumbing as well.
Yup, it always is tricky to "invalidate" a cached value.

← back to recent threads