func main() { parser := args.NewParser(args.Name("http-client"), args.Desc("Example http client client")) parser.AddOption("--verbose").Alias("-v").Count(). Help("Be verbose") parser.AddOption("--endpoint").Default("http://localhost:1234").Env("API_ENDPOINT"). Help("The HTTP endpoint our client will talk too") parser.AddCommand("super-chickens", func(subParser *args.ArgParser, data interface{}) int { subParser.AddCommand("create", createChickens) subParser.AddCommand("list", listChickens) subParser.AddCommand("delete", deleteChickens) // Apply our super metadata =) shared := data.(*SharedStruct) shared.Metadata = "super" // Run the sub-commands retCode, err := subParser.ParseAndRun(nil, data) if err != nil { fmt.Println(err.Error()) return 1 } return retCode }) // Add our non super chicken actions parser.AddCommand("create", createChickens) parser.AddCommand("list", listChickens) parser.AddCommand("delete", deleteChickens) // Parse the command line opts, err := parser.ParseArgs(nil) if err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } // Build our url from what the user passed in parts, err := url.Parse(opts.String("endpoint")) if err != nil { fmt.Fprint(os.Stderr, "url endpoint '%s' is invalid", opts.String("endpoint"), err.Error()) os.Exit(1) } // This is a shows how you can pass in arbitrary struct // data to your sub-commands allows you to share data and resources // with sub-commands with out resorting to global variables super := &SharedStruct{Metadata: "", Url: parts} // Run the command chosen by the user retCode, err := parser.RunCommand(super) if err != nil { fmt.Fprintln(os.Stderr, err.Error()) os.Exit(1) } os.Exit(retCode) }
func main() { var conf Config // Create the parser with program name 'example' // and environment variables prefixed with APP_ parser := args.NewParser(args.Name("demo"), args.EnvPrefix("APP_"), args.Desc("This is a demo app to showcase some features of args")) // Store Integers directly into a struct with a default value parser.AddOption("--power-level").Alias("-p").StoreInt(&conf.PowerLevel). Env("POWER_LEVEL").Default("10000").Help("set our power level") // Command line options can begin with -name, --name or even ++name // Most non word characters are supported parser.AddOption("++config-file").Alias("+c").IsString(). Default("/path/to/config").Help("path to config file") // Use the args.Env() function to define an environment variable // NOTE: Since the parser was passed args.EnvPrefix("APP_") the actual // environment variable name is 'APP_MESSAGE' parser.AddOption("--message").Alias("-m").StoreStr(&conf.Message). Env("MESSAGE").Default("over-ten-thousand").Help("send a message") // Pass a comma separated list of strings and get a []string slice parser.AddOption("--slice").Alias("-s").StoreStringSlice(&conf.StringSlice).Env("LIST"). Default("one,two,three").Help("list of messages") // Count the number of times an option is seen parser.AddOption("--verbose").Alias("-v").Count().StoreInt(&conf.Verbose).Help("be verbose") // Set bool to true if the option is present on the command line parser.AddOption("--debug").Alias("-d").IsTrue().Help("turn on Debug") // Specify the type of the arg with IsInt(), IsString(), IsBool() or IsTrue() parser.AddOption("--help").Alias("-h").IsTrue().Help("show this help message") // Add Required arguments parser.AddArgument("the-question").Required(). StoreStr(&conf.TheQuestion).Help("Before you have an answer") // Add Optional arguments parser.AddArgument("the-answer").IsInt().Default("42"). StoreInt(&conf.TheAnswer).Help("It must be 42") // 'Conf' options are not set via the command line but can be set // via a config file or an environment variable parser.AddConfig("twelve-factor").Env("TWELVE_FACTOR").Help("Demo of config options") // Define a 'database' subgroup db := parser.InGroup("database") // Add command line options to the subgroup db.AddOption("--host").Alias("-dH").StoreStr(&conf.DbHost). Default("localhost").Help("database hostname") // Add subgroup specific config. 'Conf' options are not set via the // command line but can be set via a config file or anything that calls parser.Apply() db.AddConfig("debug").IsTrue().Help("enable database debug") // 'Conf' option names are not allowed to start with a non word character like // '--' or '++' so they can not be confused with command line options db.AddConfig("database").IsString().Default("myDatabase").Help("name of database to use") // If no type is specified, defaults to 'IsString' db.AddConfig("user").Help("database user") db.AddConfig("pass").Help("database password") // Pass our own argument list, or nil to parse os.Args[] opt := parser.ParseArgsSimple(nil) // NOTE: ParseArgsSimple() is just a convenience, you can call // parser.ParseArgs(nil) directly and handle the errors // yourself if you have more complicated use case // Demo default variables in a struct fmt.Printf("Power '%d'\n", conf.PowerLevel) fmt.Printf("Message '%s'\n", conf.Message) fmt.Printf("String Slice '%s'\n", conf.StringSlice) fmt.Printf("DbHost '%s'\n", conf.DbHost) fmt.Printf("TheAnswer '%d'\n", conf.TheAnswer) fmt.Println("") // If user asked for --help or there were no options // passed and none where required if opt.NoArgs() || opt.Bool("help") { parser.PrintHelp() os.Exit(-1) } fmt.Println("") fmt.Println("==================") fmt.Println(" Direct Cast") fmt.Println("==================") // Fetch values by using the Cast functions fmt.Printf("Power '%d'\n", opt.Int("power-level")) fmt.Printf("Message '%s'\n", opt.String("message")) fmt.Printf("String Slice '%s'\n", opt.StringSlice("slice")) fmt.Printf("Verbose '%d'\n", opt.Int("verbose")) fmt.Printf("Debug '%t'\n", opt.Bool("debug")) fmt.Printf("TheAnswer '%d'\n", opt.Int("the-answer")) fmt.Printf("TheAnswer as String '%s'\n", opt.String("the-answer")) fmt.Println("") fmt.Println("==================") fmt.Println(" Database Group") fmt.Println("==================") // Fetch Group values dbAddOption := opt.Group("database") fmt.Printf("CAST DB Host '%s'\n", dbAddOption.String("host")) fmt.Printf("CAST DB Debug '%t'\n", dbAddOption.Bool("debug")) fmt.Printf("CAST DB User '%s'\n", dbAddOption.String("user")) fmt.Printf("CAST DB Pass '%s'\n", dbAddOption.String("pass")) fmt.Println("") iniFile := []byte(` power-level=20000 message=OVER-TEN-THOUSAND! slice=three,four,five,six verbose=5 debug=true [database] debug=false host=mysql.thrawn01.org user=my-username pass=my-password `) // Make configuration simple by reading arguments from an INI file opts, err := parser.FromINI(iniFile) if err != nil { fmt.Println(err.Error()) os.Exit(-1) } fmt.Println("") fmt.Println("==================") fmt.Println("From INI file") fmt.Println("==================") // Values from the config file are used only if the argument is not present // on the commandline fmt.Printf("INI Power '%d'\n", conf.PowerLevel) fmt.Printf("INI Message '%s'\n", conf.Message) fmt.Printf("INI Slice '%s'\n", conf.StringSlice) fmt.Printf("INI Verbose '%d'\n", conf.Verbose) fmt.Printf("INI Debug '%t'\n", opts.Bool("debug")) fmt.Println("") // Create an Options object from a map opts = parser.NewOptionsFromMap( map[string]interface{}{ "int": 1, "bool": true, "string": "one", "endpoints": map[string]interface{}{ "endpoint1": "host1", "endpoint2": "host2", "endpoint3": "host3", }, "deeply": map[string]interface{}{ "nested": map[string]interface{}{ "thing": "foo", }, "foo": "bar", }, }, ) // Small demo of how Group() works with options opts.String("string") // == "one" opts.Group("endpoints") // == *args.Options opts.Group("endpoints").String("endpoint1") // == "host1" opts.Group("endpoints").ToMap() // map[string]interface{} {"endpoint1": "host1", ...} opts.StringMap("endpoints") // map[string]string {"endpoint1": "host1", ...} opts.KeySlice("endpoints") // [ "endpoint1", "endpoint2", ] opts.StringSlice("endpoints") // [ "host1", "host2", "host3" ] // Leaves the door open for IntSlice(), IntMap(), etc.... }
It("Should generate help messages given a set of rules", func() { parser := args.NewParser(args.WrapLen(80)) parser.AddOption("--power-level").Alias("-p").Help("Specify our power level") parser.AddOption("--cat-level"). Alias("-c"). Help(`Lorem ipsum dolor sit amet, consectetur mollit anim id est laborum.`) msg := parser.GenerateHelpSection(args.IsOption) Expect(msg).To(Equal(" -p, --power-level Specify our power level" + "\n -c, --cat-level Lorem ipsum dolor sit amet, consecteturmollit anim id est" + "\n laborum.\n")) }) }) Describe("ArgParser.GenerateHelp()", func() { It("Should generate help messages given a set of rules", func() { parser := args.NewParser(args.EnvPrefix("APP_"), args.Desc("Small Description"), args.Name("dragon-ball"), args.WrapLen(80)) parser.AddOption("--environ").Default("1").Alias("-e").Env("ENV").Help("Default thing") parser.AddOption("--default").Default("0").Alias("-d").Help("Default thing") parser.AddOption("--power-level").Alias("-p").Help("Specify our power level") parser.AddOption("--cat-level").Alias("-c").Help(`Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et mollit anim id est laborum.`) msg := parser.GenerateHelp() Expect(msg).To(ContainSubstring("Usage: dragon-ball [OPTIONS]")) Expect(msg).To(ContainSubstring("-e, --environ Default thing (Default=1, Env=APP_ENV)")) Expect(msg).To(ContainSubstring("-d, --default Default thing (Default=0)")) Expect(msg).To(ContainSubstring("-p, --power-level Specify our power level")) Expect(msg).To(ContainSubstring("Small Description")) }) It("Should generate formated description if flag is set", func() {