akamensky / argparse

Argparse for golang. Just because `flag` sucks
MIT License
604 stars 62 forks source link

[bug] Commands not required #76

Closed mprahlkamps closed 2 years ago

mprahlkamps commented 3 years ago

Hello, I have following code

parser := argparse.NewParser("...", "...")

verbose := parser.FlagCounter("v", "verbose", &argparse.Options{})
hosts := parser.StringList("", "host", &argparse.Options{Required: true})
username := parser.String("u", "user", &argparse.Options{Required: true})
password := parser.String("p", "password", &argparse.Options{Required: true})

// preset cmd
presetCmd := parser.NewCommand("preset", "Get and modify radio presets")
// get preset cmd
getPresetCmd := presetCmd.NewCommand("get", "Get the current radio preset")
// set preset cmd
setPresetCmd := presetCmd.NewCommand("set", "Set the current radio preset")
setPresetID := setPresetCmd.Int("", "id", &argparse.Options{Required: true})

// user cmd
userCmd := parser.NewCommand("user", "User")
getUserCmd := userCmd.NewCommand("get", "Get all users")

err := parser.Parse(os.Args)
if err != nil {
    fmt.Println(parser.Usage(err))
    return
}

When I start this with no arguments, I get the expected error message [sub]Command required. When I start the program with just hosts, username and password, the subcommand is suddenly not needed.

EDIT: After reviewing your example code, the advanced-command example has the exact same bug. Start the example with just the --name argument and you reach

// This should be unreachable
log.Fatal("Uh-oh, something weird happened")
akamensky commented 3 years ago

Thanks, and sorry for the delay. Let me check and I will get back to you.

akamensky commented 2 years ago

Full code to reproduce:

package main

import (
    "fmt"
    "github.com/akamensky/argparse"
    "os"
)

func main() {
    parser := argparse.NewParser("...", "...")

    _ = parser.FlagCounter("v", "verbose", &argparse.Options{})
    _ = parser.StringList("", "host", &argparse.Options{Required: true})
    _ = parser.String("u", "user", &argparse.Options{Required: true})
    _ = parser.String("p", "password", &argparse.Options{Required: true})

    // preset cmd
    presetCmd := parser.NewCommand("preset", "Get and modify radio presets")
    // get preset cmd
    _ = presetCmd.NewCommand("get", "Get the current radio preset")
    // set preset cmd
    setPresetCmd := presetCmd.NewCommand("set", "Set the current radio preset")
    _ = setPresetCmd.Int("", "id", &argparse.Options{Required: true})

    // user cmd
    userCmd := parser.NewCommand("user", "User")
    _ = userCmd.NewCommand("get", "Get all users")

    err := parser.Parse(os.Args)
    if err != nil {
        fmt.Println(parser.Usage(err))
        return
    }
}

Test cases:

$ go run main.go --host host # Fail, should report that sub command is required, but reports that `user` is required
$ go run main.go --host host -u user  # Fail, should report that sub command is required, but reports that `password` is required
akamensky commented 2 years ago

Fixed in #104

@mprahlkamps please let me know if the issue still happens in another form, but this should have fixed it (I think).