thrawn01/args

View on GitHub
examples/demo/demo.go

Summary

Maintainability
A
3 hrs
Test Coverage
package main

import (
    "fmt"
    "os"

    "github.com/thrawn01/args"
)

type Config struct {
    PowerLevel  int
    Message     string
    StringSlice []string
    Verbose     int
    DbHost      string
    TheQuestion string
    TheAnswer   int
}

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.ParseOrExit(nil)

    // NOTE: ParseOrExit() is just a convenience, you can call
    // parser.Parse(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("")

    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....
}