func main() { cfg := &config{} cmd := writ.New("devo", cfg) cmd.Help.Usage = usage cmd.Help.Header = header cmd.Help.Footer = footer _, positional, err := cmd.Decode(os.Args[1:]) if err != nil || cfg.HelpFlag { cmd.ExitHelp(err) } if cfg.VersionFlag { fmt.Fprintf(os.Stdout, "DeVo version %d.%d.%d\nCompiled with %s\n", devo.Version.Major, devo.Version.Minor, devo.Version.Patch, runtime.Version()) os.Exit(0) } if len(positional) != 0 { cmd.ExitHelp(fmt.Errorf("too many arguments provided")) } err = cfg.validate() if err != nil { cmd.ExitHelp(err) } defer cfg.Output.Close() check(devo.Decrypt(cfg.Output, cfg.Input, cfg.AccessKey)) }
func main() { dicod := &Dicod{} cmd := writ.New("dicod", dicod) cmd.Help.Usage = "Usage: dicod [OPTION]..." cmd.Help.Header = "Distributes tasks, collects results." _, _, err := cmd.Decode(os.Args[1:]) if err != nil || dicod.HelpFlag { cmd.ExitHelp(err) } if dicod.Verbosity > 0 { log.SetLevel(log.DebugLevel) log.WithField("verbosity", dicod.Verbosity).Debug("custom verbosity") } taskChan = make(chan *Task) retryChan = make(chan *Task, 10) // TODO go func() { for task := range retryChan { task.retries++ task.failed = false taskChan <- task } }() listen(dicod.Port) }
// This example uses writ.New() to build a command from the Greeter's // struct fields. The resulting *writ.Command decodes and updates the // Greeter's fields in-place. The Command.ExitHelp() method is used to // display help content if --help is specified, or if invalid input // arguments are received. func Example_basic() { greeter := &Greeter{} cmd := writ.New("greeter", greeter) cmd.Help.Usage = "Usage: greeter [OPTION]... MESSAGE" cmd.Help.Header = "Greet users, displaying MESSAGE" // Use cmd.Decode(os.Args[1:]) in a real application _, positional, err := cmd.Decode([]string{"-vvv", "--name", "Sam", "How's it going?"}) if err != nil || greeter.HelpFlag { cmd.ExitHelp(err) } message := strings.Join(positional, " ") fmt.Printf("Hi %s! %s\n", greeter.Name, message) if greeter.Verbosity > 0 { fmt.Printf("I'm feeling re%slly chatty today!\n", strings.Repeat("a", greeter.Verbosity)) } // Output: // Hi Sam! How's it going? // I'm feeling reaaally chatty today! // Help Output: // Usage: greeter [OPTION]... MESSAGE // Greet users, displaying MESSAGE // // Available Options: // --help Display this help message and exit // -v, --verbose Display verbose output // -n, --name=ARG The person or people to greet }
// ParseArguments should be called with something that embeds the // Arguments type and adds more command line arguments. // Be aware: If an error occurs during parsing or the HelpFlag was specified, // this method will terminate the application! func ParseArguments(args *Arguments, name string) { cmd := writ.New(name, args) // Parse command line arguments _, _, err := cmd.Decode(os.Args[1:]) if err != nil || args.HelpFlag { cmd.ExitHelp(err) } }
func main() { limes := &Limes{} cmd := writ.New("limes", limes) cmd.Help.Usage = "Usage: limes [OPTIONS]... COMMAND [OPTION]... [ARG]..." cmd.Subcommand("start").Help.Usage = "Usage: limes start" cmd.Subcommand("stop").Help.Usage = "Usage: limes stop" cmd.Subcommand("status").Help.Usage = "Usage: limes status" cmd.Subcommand("fix").Help.Usage = "Usage: limes fix [--restore]" cmd.Subcommand("assume").Help.Usage = "Usage: limes assume <profile>" cmd.Subcommand("show").Help.Usage = "Usage: limes show [component]" cmd.Subcommand("env").Help.Usage = "Usage: limes env <profile>" cmd.Subcommand("run").Help.Usage = "Usage: limes [--profile <name>] run <cmd> [arg...]" path, positional, err := cmd.Decode(os.Args[1:]) if err != nil { if path.String() != "limes run" { path.Last().ExitHelp(err) } os.Args = injectCmdBreak("run", os.Args) path, positional, err = cmd.Decode(os.Args[1:]) if err != nil { path.Last().ExitHelp(err) } } limes.Address = setDefaultSocketAddress(limes.Address) limes.ConfigFile = setDefaultConfigPath(limes.ConfigFile) if !limes.Logging { log.SetOutput(ioutil.Discard) } switch path.String() { case "limes": limes.Run(limes, path, positional) case "limes start": limes.Start.Run(limes, path, positional) case "limes stop": limes.Stop.Run(limes, path, positional) case "limes status": limes.Status.Run(limes, path, positional) case "limes fix": limes.Fix.Run(limes, path, positional) case "limes assume": limes.SwitchProfile.Run(limes, path, positional) case "limes show": limes.ShowCmd.Run(limes, path, positional) case "limes env": limes.Env.Run(limes, path, positional) case "limes run": limes.RunCmd.Run(limes, path, positional) default: log.Fatalf("bug: sub command has not been setup: %v", path.String()) } }
// This example demonstrates subcommands in a busybox style. There's no requirement // that subcommands implement the Run() method shown here. It's just an example of // how subcommands might be implemented. func Example_subcommand() { gobox := &GoBox{} cmd := writ.New("gobox", gobox) cmd.Help.Usage = "Usage: gobox COMMAND [OPTION]... [ARG]..." cmd.Subcommand("ln").Help.Usage = "Usage: gobox ln [-s] OLD NEW" cmd.Subcommand("ls").Help.Usage = "Usage: gobox ls [-l] [PATH]..." path, positional, err := cmd.Decode(os.Args[1:]) if err != nil { // Using path.Last() here ensures the user sees relevant help for their // command selection path.Last().ExitHelp(err) } // At this point, cmd.Decode() has already decoded option values into the gobox // struct, including subcommand values. We just need to dispatch the command. // path.String() is guaranteed to represent the user command selection. switch path.String() { case "gobox": gobox.Run(path, positional) case "gobox ln": gobox.Link.Run(path, positional) case "gobox ls": gobox.List.Run(path, positional) default: panic("BUG: Someone added a new command and forgot to add it's path here") } // Help output, gobox: // Usage: gobox COMMAND [OPTION]... [ARG]... // // Available Commands: // ln Create a soft or hard link // ls List directory contents // // Help output, gobox ln: // Usage: gobox ln [-s] OLD NEW // // Available Options: // -h, --help Display this message and exit // -s Create a symlink instead of a hard link // // Help output, gobox ls: // Usage: gobox ls [-l] [PATH]... // // Available Options: // -h, --help Display this message and exit // -l Use long-format output }
// This example demonstrates some of the convenience features offered by writ. // It uses writ's support for io types and default values to ensure the Input // and Output fields are initialized. These default to stdin and stdout due // to the default:"-" field tags. The user may specify -i or -o to read from // or write to a file. Similarly, the Replacements map is initialized with // key=value pairs for every -r/--replace option the user specifies. func Example_convenience() { replacer := &ReplacerCmd{} cmd := writ.New("replacer", replacer) cmd.Help.Usage = "Usage: replacer [OPTION]..." cmd.Help.Header = "Perform text replacement according to the -r/--replace option" cmd.Help.Footer = "By default, replacer reads from stdin and write to stdout. Use the -i and -o options to override." // Decode input arguments _, positional, err := cmd.Decode(os.Args[1:]) if err != nil || replacer.HelpFlag { cmd.ExitHelp(err) } if len(positional) > 0 { cmd.ExitHelp(errors.New("replacer does not accept positional arguments")) } // At this point, the ReplacerCmd's Input, Output, and Replacements fields are all // known-valid and initialized, so we can run the replacement. err = replacer.Replace() if err != nil { fmt.Fprintf(os.Stderr, "Error: %s\n", err) os.Exit(1) } }