Cobra: How to make rootCmd behave as one of its children

Created on 9 Aug 2018  路  5Comments  路  Source: spf13/cobra

I have a, rootCmd, with two chidren, serveCmd and dbCmd. I'd like rootCmd.Run to be an alias of serveCmd, including flags. But I don't wan't flags shown when rootCmd --help is executed. So far I could make the root execute the subcommand with:

    Run: func(cmd *cobra.Command, args []string) {
        serveCmd.Run(cmd, args)
    },

However, when a flag defined in serveCmd is passed to rootCmd, it complains before reaching rootCmd.Run.

Most helpful comment

I can't think of a good way to do this....
In main() before you call rootCmd.Execute() you might be able to mess with os.Args to magically insert your subcommand into the argument list if it wasn't there?
I'll keep trying to think of something...

All 5 comments

I can't think of a good way to do this....
In main() before you call rootCmd.Execute() you might be able to mess with os.Args to magically insert your subcommand into the argument list if it wasn't there?
I'll keep trying to think of something...

It works great! As you said, I added a check. If os.Args[1] is not any of the subcommands in a list, it adds one. This is my main now:

func main() {
    checkRootAlias(os.Args[1], NonRootSubCommands)
    cmd.Execute()
}

var NonRootSubCommands = []string{"db"}

func checkRootAlias(a string, b []string) {
    for _, v := range b {
        if a == v {
            return
        }
    }
    os.Args = append([]string{os.Args[0], "serve"}, os.Args[1:]...)
}

Would it be feasible to enhance cobra in order to generate NonRootSubCommands automatically? It should be a []string containing the names and commands of all the subcommands of root, except the selected one.

You should be able to iterate over rootCmd.Commands() to get the Name() of each and use that.

Indeed, I was going to post that :). I removed everything from main, then added a Aliases field to rootCmd (with a single string), and this is my Execute() now:

func checkRootAlias(a string, b []string) {
    for _, v := range b {
        if a == v {
            return
        }
    }
    os.Args = append([]string{os.Args[0], rootCmd.Aliases[0]}, os.Args[1:]...)
}

func nonRootSubCmds() (l []string) {
    for _, c := range rootCmd.Commands() {
        isAlias := false
        for _, a := range append(c.Aliases, c.Name()) {
            if a == rootCmd.Aliases[0] {
                isAlias = true
                break
            }
        }
        if !isAlias {
            l = append(l, c.Name())
            l = append(l, c.Aliases...)
        }
    }
    return
}

func Execute() {
    checkRootAlias(os.Args[1], nonRootSubCmds())
    if err := rootCmd.Execute(); err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
}

Thanks @eparis!

Thanks @1138-4EB, I'm waiting for https://github.com/spf13/cobra/issues/823 too.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

niski84 picture niski84  路  4Comments

pjbgf picture pjbgf  路  5Comments

phanirithvij picture phanirithvij  路  5Comments

joernott picture joernott  路  6Comments

lukasmalkmus picture lukasmalkmus  路  4Comments