docopt / docopt.go

A command-line arguments parser that will make you smile.
http://docopt.org/
MIT License
1.43k stars 111 forks source link

Wrong optional keyword match #71

Open haamed opened 4 years ago

haamed commented 4 years ago

It seems if a command-like argument (like a keyword) is use in an optional block, it matches the wrong thing. In the following repro, "cmd" is matched with "opt1" if "keyword" is not specified. If it is specified it works fine. Note that if instead of a keyword, an option (like "--option") is specified it works fine.

package main

import (
    "fmt"
    "github.com/docopt/docopt-go"
)

func main() {
    usage := `To match optional with keyword.

Usage:
  keyword-match: [keyword <opt1>] [<args>...]
`
    args, err := docopt.ParseArgs(usage, []string{"cmd"}, "")
    fmt.Printf("%#v\n", args) // BUG prints: docopt.Opts{"<opt1>":"cmd", "keyword":false}
    fmt.Printf("%#v\n", err)  // prints: <nil>

    args, err = docopt.ParseArgs(usage, []string{"keyword", "opt1", "cmd"}, "")
    fmt.Printf("%#v\n", args) // prints: docopt.Opts{"<args>":[]string{"cmd"}, "<opt1>":"opt1", "keyword":true}
    fmt.Printf("%#v\n", err)  // prints: <nil>

    usage = `To match optional with option.

Usage:
  keyword-match: [--option=<opt1>] [<args>...]
`
    args, err = docopt.ParseArgs(usage, []string{"cmd"}, "")
    fmt.Printf("%#v\n", args) // prints: docopt.Opts{"--option":interface {}(nil), "<args>":[]string{"cmd"}}
    fmt.Printf("%#v\n", err)  // prints: <nil>

    args, err = docopt.ParseArgs(usage, []string{"--option", "opt1", "cmd"}, "")
    fmt.Printf("%#v\n", args) // prints: docopt.Opts{"--option":"opt1", "<args>":[]string{"cmd"}}
    fmt.Printf("%#v\n", err)  // prints: <nil>
}