jessevdk / go-flags

go command line option parser
http://godoc.org/github.com/jessevdk/go-flags
BSD 3-Clause "New" or "Revised" License
2.55k stars 306 forks source link

Is this the best (or only) way to figure out which subcommands have been used? #405

Open asdfractal opened 3 months ago

asdfractal commented 3 months ago

Say I have my app with nested subcommands

App sub1 sub2

In order to check that I have run app sub1 sub2 --someflag I've been using.

if parser.Command.Active.Name  // sub1 {
    if { parser.Command.Active.Active.Name  // sub2 {
        // do something
    }
}

Is that the best way? I couldn't find anything else in the docs.

brandon1024 commented 1 month ago

I'd like to know this too. I find the documentation/examples are a little lacking here.

brandon1024 commented 1 month ago

For future readers, the best way I found to do this was to use the Commander interface. It's not the most elegant solution, but it works fairly well.

type Options struct {
    Sub1  Subcommand1 `command:"s1"`
    Sub2  Subcommand2 `command:"s2"`
}

type Subcommand1 struct {
    Enabled bool `hidden:"true" no-ini:"true"`
}

// Detect when the subcommand is used.
func (c *Subcommand1) Execute(args []string) error {
    c.Enabled = true
    return nil
}

type Subcommand2 struct {
    Enabled bool `hidden:"true" no-ini:"true"`
}

// Detect when the subcommand is used.
func (c *Subcommand2) Execute(args []string) error {
    c.Enabled = true
    return nil
}

func main() {
    var ops Options
    args, err := flags.Parse(&ops)
    if flags.WroteHelp(err) {
        return
    }
    if err != nil {
        panic(err)
    }

    switch {
    case ops.Sub1.Enabled:
        // do thing 1
    case ops.Sub2.Enabled:
        // do thing 2
    }
}

@jessevdk this would be a good example to provide in your documentation. Additionally, it would be nice if the parser was able to recognize pointer struct types for subcommands; then it would be easy to check if a subcommand was provided with a simple nil check, as demonstrated below:

type Options struct {
    Sub1  *Subcommand1 `command:"s1"`
    Sub2  *Subcommand2 `command:"s2"`
}

type Subcommand1 struct {
    Enabled bool `hidden:"true" no-ini:"true"`
}

type Subcommand2 struct {
    Enabled bool `hidden:"true" no-ini:"true"`
}

func main() {
    var ops Options
    args, err := flags.Parse(&ops)
    if flags.WroteHelp(err) {
        return
    }
    if err != nil {
        panic(err)
    }

    switch {
    case ops.Sub1 != nil:
        // do thing 1
    case ops.Sub2 != nil:
        // do thing 2
    }
}