i am building a little cli tool that boots my app in development or production.
the way i want it to work is like this:
app run --dev or app run --prod
Atm it doest parses the flags after my command but only before my command. So this works
app --dev run or app --prod run
Any idee how to fix it this so i can use it after my command? here is my code
func main() {
//flag.Usage := usage
flag.Parse()
args := flag.Args()
if len(args) == 0 {
Usage()
os.Exit(0)
}
if *dev {
os.Setenv("ENV", "development")
}
if *prod {
os.Setenv("ENV", "production")
}
switch {
// Run
case args[0] == "run" && len(args) == 1:
os.Setenv("port", *port)
log.Printf("Booting in %s", os.Getenv("ENV"))
Run()
// Help
case args[0] == "help" && len(args) == 1:
Usage()
}
}
Traditionally, the UNIX option parser getopt()
stops parsing after the first non-option. The glibc altered this behavior to support options in arbitrary positions, a controversial decision. The flag
package implements the traditional behavior.
One thing you could do is permuting the arguments array before parsing the flags. That's what the glibc does:
func permutateArgs(args []string) int {
args = args[1:]
optind := 0
for i := range args {
if args[i][0] == '-' {
tmp := args[i]
args[i] = args[optind]
args[optind] = tmp
optind++
}
}
return optind + 1
}
This code permutates args
such that options are in front, leaving the program name untouched. permutateArgs
returns the index of the first non-option after permutation. Use this code like this:
optind := permutateArgs(os.Args)
flags.Parse()
// process non-options
for i := range os.Args[optind:] {
// ...
}