spf13 / pflag

Drop-in replacement for Go's flag package, implementing POSIX/GNU-style --flags.
BSD 3-Clause "New" or "Revised" License
2.39k stars 347 forks source link

How to set subcommand specific flags #195

Closed sj14 closed 5 years ago

sj14 commented 5 years ago

Hi, I try to use pflag for sub commands with multiple flag sets. Please see the example below.

package main

import (
    "fmt"
    "log"
    "os"

    "github.com/spf13/pflag"
)

func main() {
    defaults := pflag.NewFlagSet("defaults for all commands", pflag.ExitOnError)
    forAll := defaults.String("all", "visible for all commands", "visible for all commands")

    cmdA := pflag.NewFlagSet("cmda", pflag.ExitOnError)
    cmdAspecific := cmdA.String("aspec", "only visible for cmd A", "only visible for cmd A")
    cmdA.AddFlagSet(defaults)

    cmdB := pflag.NewFlagSet("cmdb", pflag.ExitOnError)
    cmdBspecific := cmdA.String("bspec", "only visible for cmd B", "only visible for cmd B")
    cmdB.AddFlagSet(defaults)

    defaults.Parse(os.Args)

    if len(os.Args) == 1 {
        log.Fatal("no subcommand given")
    }

    switch os.Args[1] {
    case "cmda":
        cmdA.Parse(os.Args[2:])
        fmt.Println(*cmdAspecific)
        fmt.Println(*forAll)
    case "cmdb":
        cmdB.Parse(os.Args[2:])
        fmt.Println(*cmdBspecific)
        fmt.Println(*forAll)
    default:
        fmt.Printf("%q is no valid subcommand.\n", os.Args[1])
        os.Exit(2)
    }
}

cmda / cmdb without flags works as expected.

go run main.go cmdb
only visible for cmd B
visible for all commands

But not with flags. I thought this should be possbile, where is my mistake?

go run main.go cmdb --bspec asd
unknown flag: --bspec
Usage of defaults for all commands:
      --all string   visible for all commands (default "visible for all commands")
unknown flag: --bspec
exit status 2
eparis commented 5 years ago
    cmdBspecific := cmdA.String("bspec", "only visible for cmd B", "only visible for cmd B")

Looks like you added bpsec to cmdA...

sj14 commented 5 years ago

@eparis oh, you are right. But after changing it, it's still the same issue.

eparis commented 5 years ago

ok, i'll play with it. But it looks like you are duplicating basically exactly what github.com/spf13/cobra provides....

eparis commented 5 years ago
    defaults.Parse(os.Args)

is your problem. You are parsing os.Args on a flag set that doesn't container bspec. If you just delete that entirely it works, since you parse the default flag set and the a/b specific flags later inside the switch. (though maybe you want to put this inside the default portion of the switch.

sj14 commented 5 years ago

Ah, thanks alot!