Cli: Autocomplete: subcommands are run while in autocompletion mode

Created on 25 Aug 2015  路  6Comments  路  Source: urfave/cli

It appears that when I do:

./mybinary -a arg -n <tab><tab>
-a   : a correct flag
arg : a correct arg
-n   : an incorrect flag

my client tries to run -n or whatever the last arg is, and ends up showing my app's help.
Sometimes when "-n" is a correct command, it's executed and showing in the argument selection while it should not.

I decided to take a look at cli functions:
-> codegangsta/cli/help.go

func checkCommandCompletions(c *Context, name string) bool {
        if c.Bool(BashCompletionFlag.Name) && c.App.EnableBashCompletion {
                ShowCommandCompletions(c, name)
                return true
        }
        return false
}

And I noticed that c.Bool(BashCompletionFlag.Name) was false sometimes, while I am pressing tab and not running the program.

I replaced this code by :

func checkCommandCompletions(c *Context, name string) bool {
        if c.App.EnableBashCompletion {
                for i := range os.Args {
                        if strings.Contains(os.Args[i], "generate-bash-completion") {
                                ShowCommandCompletions(c, name)
                                return true
                        }
                }
        }
        return false
}

And also here :
https://github.com/codegangsta/cli/blob/master/command.go#L53-L129

I moved the context declaration and the checkCommandCompletions call, next to the set.SetOutput call like this :

[...]
 if ctx.App.EnableBashCompletion {
                c.Flags = append(c.Flags, BashCompletionFlag)
        }

        set := flagSet(c.Name, c.Flags)
        set.SetOutput(ioutil.Discard)
// New completion check
        context := NewContext(ctx.App, set, ctx)

        if checkCommandCompletions(context, c.Name) {
                return nil
        }
// End of completion check
        firstFlagIndex := -1
        terminatorIndex := -1
[...]

That way, the cli doesn't call command or help ( if the command doesn't exist ) anymore if bash completion is enabled.
It's working very well for me but I'm sure there's a better way to do it.

Thanks in advance,

help wanted kinbug

Most helpful comment

I ran into this bug. It happens when you pass arguments like this myprog --arg-that-takes-value --generate-bash-completion

In this case --generate-bash-completion is treated as the value of --arg-that-takes-value and thus messes stuff up.

I think the best solution would be to parse --generate-bash-completion from os.Args as one of the very first things, and separate it from the rest of the logic.

All 6 comments

Anyone had the same issue?
(It should be labeled as #bug)

I ran into this bug. It happens when you pass arguments like this myprog --arg-that-takes-value --generate-bash-completion

In this case --generate-bash-completion is treated as the value of --arg-that-takes-value and thus messes stuff up.

I think the best solution would be to parse --generate-bash-completion from os.Args as one of the very first things, and separate it from the rest of the logic.

Indeed, this does seem like a bug. I'll try to find some time to address this, but I'm happy to review any pull requests to push this along.

This could be mitigated slightly by changing the script to insert --generate-bash-completion as the very first flag instead of just adding it to the end.

Based on @tianon's suggestion something like this could be done. It appears to work for regular Commands with bash completion, I haven't used for SubCommands.

if [ $COMP_CWORD -eq 1 ]; then
  opts=$( ${COMP_WORDS[@]:0:$COMP_CWORD} --generate-bash-completion )
else
  opts=$(${COMP_WORDS[@]:0:2} --generate-bash-completion ${COMP_WORDS[@]:2:$COMP_CWORD} )   
fi
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )

Given that this is from last year, I think I'm comfortable closing it 馃檪 feel free to re-open / open a new issue / comment in support if there's still interest here!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lynncyrin picture lynncyrin  路  3Comments

vschettino picture vschettino  路  5Comments

navono picture navono  路  4Comments

genieplus picture genieplus  路  5Comments

errashe picture errashe  路  3Comments