threads / discuss / 30395

broken bash completion

Subject: broken bash completion

## tl;dr

8 messages between May 2, 2012 and May 5, 2012.

replies: 7people: 5as markdown or json

Rolf Leggewie· May 2, 2012, 14:09 UTC · lore

forward from http://code.google.com/p/git-core/issues/detail?id=11 and https://bugs.launchpad.net/bugs/853081

Hello,

not sure you guys pay much attention to the issue tracker over on code.google.com so I'll try my luck here.

Current bash completion works the following way.
1) only tag-completion possible: complete tag as much as possible
2) only file/dir-completion possible: complete path as much as possible
3) all of tag/file/dir-completion possible: complete tag (!) as much as 
possible

1 and 2 are fine, but for #3 git should really stop at the lowest common denominator for all of tags, files and directories. This is explained better in above tickets, but I'll also include an example here for illustration. Let's say I had tags debian/1.4.9-1 and debian/1.4.9-2 as well as debian/changelog file (as is common when using git-buildpackage, this is a real life example). Current bash-completion behavior for "git log debiTAB" is to complete to "git log debian/1.4.9-" when it really should be "git log debian/".

Thank you for your attention.
Regards
Rolf
SZEDER Gábor· May 4, 2012, 23:32 UTC · re: Rolf Leggewie · lore

Re: broken bash completion

Hi,
On Wed, May 02, 2012 at 10:09:26PM +0800, Rolf Leggewie wrote:
Show 15 quoted lines
> Current bash completion works the following way.
> 
> 1) only tag-completion possible: complete tag as much as possible
> 2) only file/dir-completion possible: complete path as much as possible
> 3) all of tag/file/dir-completion possible: complete tag (!) as much
> as possible
> 
> 1 and 2 are fine, but for #3 git should really stop at the lowest
> common denominator for all of tags, files and directories. This is
> explained better in above tickets, but I'll also include an example
> here for illustration.  Let's say I had tags debian/1.4.9-1 and
> debian/1.4.9-2 as well as debian/changelog file (as is common when
> using git-buildpackage, this is a real life example).  Current
> bash-completion behavior for "git log debiTAB" is to complete to
> "git log debian/1.4.9-"

Yeah, there are a lot of git commands that accept refs (not just tags) and files as well. When completing a non-option word (i.e. a word that does not begin with a double dash) for such a command, git's completion script offers only refs, but when none of the refs matches the word to be completed, then COMPREPLY remains empty and Bash falls back to the default filename completion.

Now, to resolve ambiguity between options/refs and paths, the '--' separator should be used before the first path to separate options and refs from paths. The completion script recognizes this separator, and lets Bash perform filename completion for subsequent words. So if you know that you want to complete a file, then 'git log -- d<TAB>' will give you 'debian/'. Alternatively, you can just prefix './' to the path, e.g. write 'git log ./d<TAB>' to get './debian/'.

> when it really should be "git log debian/".

I understand why you think that offering 'debian/' there would be the correct behavior. However, in this case being correct is perhaps not the right thing. Currently 'git log c<TAB>' offers me a couple of completion-related branches, but with your correct behavior that would be cluttered by all files and directories starting with 'c'. I for one would find that inconvenient and annoying, especially because, while there are easy ways to get filename completion instead of refs, as shown above, there is no similarly easy way to get only refs completion.

Best, Gábor

Rolf Leggewie· May 5, 2012, 04:24 UTC · re: SZEDER Gábor · lore

Re: broken bash completion

Dear Gábor,

thank you for taking the time to write up an analysis and offer some workarounds to the bash-completion issue I reported. That is much appreciated.

After all is said and done, though, the bash-completion remains inconsistent and thus broken. It's great that your life is currently more convenient but in the end you are relying on broken behaviour.

Affected commands: git log git diff git whatchanged git branch (why offer tags OR files here at all) [...]

Unaffected programs, i.e. working correctly: git commit [...]

Some consistency would be great. In a perfect world bash-completion ought to work on all possible completion targets but at the same time it should exclude all that make no sense, too. Neither of the two seems to be currently the case.

I had a look at /etc/bash_completion.d/git to see if there was some work I could do to cook up a patch, but unfortunately, it's all greek to me in there.

Regards
Rolf
SZEDER Gábor· May 5, 2012, 12:13 UTC · re: Rolf Leggewie · lore

Re: broken bash completion

Hi Rolf,
On Sat, May 05, 2012 at 12:24:38PM +0800, Rolf Leggewie wrote:
> After all is said and done, though, the bash-completion remains
> inconsistent and thus broken.  It's great that your life is
> currently more convenient but in the end you are relying on broken
> behaviour.

Well, git's completion script is consistent with itself: whenever there is no matching subcommand, option, parameter for an option, or ref, it falls back to filename completion. I wouldn't consider this behavior as broken.

Show 5 quoted lines
> Affected commands:
> git log
> git diff
> git whatchanged
> git branch (why offer tags OR files here at all)

While files and tags make no sense for 'git branch' itself, completing them can be helpful to construct the name of a new branch. I did the following at dayjob just the other day:

# there are route_calculation.c and .h files in that project, and # there were some nasty bugs in there $ git branch ro<TAB> # which gave me $ git branch route_calculation. # just deleted the '.' and completed the new branch name by hand $ git branch route_calculation_fixes

Anyway, I see two ways to fix this if we want to be anal, but none of them is actually applicable:

- When registering _git() as the completion function for the git
  command, we specify some options to tell Bash to do filename
  completion when we can't find any matches to the word to be
  completed.  Recent Bash versions provide the 'compopt' builtin to
  allow modifying completion options for the currently executed
  completion.  We could do a 'compopt +o bashdefault +o default'
  to disable the filename completion fallback wherever we deem it
  inappropriate.
  'compopt' was introduced in Bash 4.0, but unfortunately msysgit
  still includes an older version, so this is a no go.
- We don't specify the options to ask Bash to fall back to filename
  completion when registering _git(). This will disable filename
  completion for the whole git completion script, so we must roll our
  own helper functions to do filename completion, which we would
  invoke wherever filename completion is explicitly desired.
  This should work on any Bash version, but would inherently include
  some fork()+exec()s, adding significant delays especially on
  msysgit.
> Unaffected programs, i.e. working correctly:
> git commit
> [...]
You haven't tried it hard enough ;)

$ git commit --fixup=e<TAB> editor.c entry.c environment.c exec_cmd.c exec_cmd.o editor.o entry.o environment.o exec_cmd.h

although at that point only a commit is accepted.
> Some consistency would be great.  In a perfect world bash-completion
> ought to work on all possible completion targets but at the same
> time it should exclude all that make no sense, too.  Neither of the
> two seems to be currently the case.

Yeah, in that perfect world 'git rm <TAB>', 'git bisect -- <TAB>', and 'git log -- <TAB>' whould offer only tracked files, 'git (add|commit) <TAB>' only modified or untracked files, and 'git diff <TAB>' would read your mind to find out whether you want to diff a ref or a file, etc. etc.

But you miss an important point here: users expect the completion to be pretty fast, because delays are quite noticeable and annoying while typing a command. So there's a trade-off between correctness and usability. Unfortunately, in the real world all that filtering costs a great deal, so git's completion script does that only if it can be done cheaply (e.g. 'git rebase --<TAB>' won't offer you '--abort' and '--continue' if you're not in the middle of an ongoing rebase). And as pointed out above, something might be nonsense for a command, but still be useful for the user.

Best, Gábor

Andreas Schwab· May 5, 2012, 12:22 UTC · re: SZEDER Gábor · lore

Re: broken bash completion

SZEDER Gábor <szeder@ira.uka.de> writes:
Show 7 quoted lines
> While files and tags make no sense for 'git branch' itself, completing
> them can be helpful to construct the name of a new branch.  I did the
> following at dayjob just the other day:
>
> # there are route_calculation.c and .h files in that project, and
> # there were some nasty bugs in there
> $ git branch ro<TAB>
You can force filename completion with M-/.
Andreas.
-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."
Felipe Contreras· May 5, 2012, 13:11 UTC · re: SZEDER Gábor · lore

Re: broken bash completion

On Sat, May 5, 2012 at 2:13 PM, SZEDER Gábor <szeder@ira.uka.de> wrote:
Show 9 quoted lines
> But you miss an important point here: users expect the completion to
> be pretty fast, because delays are quite noticeable and annoying while
> typing a command.  So there's a trade-off between correctness and
> usability.  Unfortunately, in the real world all that filtering costs
> a great deal, so git's completion script does that only if it can be
> done cheaply (e.g. 'git rebase --<TAB>' won't offer you '--abort' and
> '--continue' if you're not in the middle of an ongoing rebase).  And
> as pointed out above, something might be nonsense for a command, but
> still be useful for the user.
Completely agree with this.

The reason I started to use the bash completion in zsh is that the zsh completion goes for 100% correctness, that means 'git checkout <TAB>' took literally *minutes* in my machine on the Linux kernel repo. The zsh developers said that was OK, and my patch to solve the problem was not, because it would make the result less than 100% correct.

The whole point of completion is to avoid typing as much as possible, and if typing something is faster than doing the completion; the completion is pointless. It has to be fast.

Cheers.
-- 
Felipe Contreras
fREW Schmidt· May 5, 2012, 13:57 UTC · re: Felipe Contreras · lore

Re: broken bash completion

On Sat, May 5, 2012 at 8:11 AM, Felipe Contreras <felipe.contreras@gmail.com> wrote:

Show 8 quoted lines
>
> On Sat, May 5, 2012 at 2:13 PM, SZEDER Gábor <szeder@ira.uka.de> wrote:
>
> The reason I started to use the bash completion in zsh is that the zsh
> completion goes for 100% correctness, that means 'git checkout <TAB>'
> took literally *minutes* in my machine on the Linux kernel repo. The
> zsh developers said that was OK, and my patch to solve the problem was
> not, because it would make the result less than 100% correct.

Could you elaborate on how you did that? I'm suffering from the same thing and don't see an obvious way to use bash-completion in zsh.

-- fREW Schmidt http://blog.afoolishmanifesto.com

Felipe Contreras· May 5, 2012, 14:26 UTC · re: fREW Schmidt · lore

Re: broken bash completion

On Sat, May 5, 2012 at 3:57 PM, fREW Schmidt <frioux@gmail.com> wrote:
Show 13 quoted lines
> On Sat, May 5, 2012 at 8:11 AM, Felipe Contreras
> <felipe.contreras@gmail.com> wrote:
>>
>> On Sat, May 5, 2012 at 2:13 PM, SZEDER Gábor <szeder@ira.uka.de> wrote:
>>
>> The reason I started to use the bash completion in zsh is that the zsh
>> completion goes for 100% correctness, that means 'git checkout <TAB>'
>> took literally *minutes* in my machine on the Linux kernel repo. The
>> zsh developers said that was OK, and my patch to solve the problem was
>> not, because it would make the result less than 100% correct.
>
> Could you elaborate on how you did that?  I'm suffering from the same
> thing and don't see an obvious way to use bash-completion in zsh.

Just source the bash script: http://git.kernel.org/?p=git/git.git;a=blob;f=contrib/completion/git-completion.bash

Alternatively you can use my wrapper that works better than zsh's bash completion[1], but you still need the bash script anyway.

Cheers.
[1] https://github.com/felipec/git-zsh/blob/master/git-completion.zsh
-- 
Felipe Contreras

← back to recent threads