Last active
August 29, 2015 14:10
-
-
Save arnehormann/a71c9c7f0f160e585bc1 to your computer and use it in GitHub Desktop.
Just an example for envflag (soon to be expanded at github.com/confactor/envflag)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// see http://godoc.org/github.com/arnehormann/goof/envflag | |
package main | |
import ( | |
"fmt" | |
"io" | |
"os" | |
"sort" | |
"strings" | |
"text/tabwriter" | |
"github.com/arnehormann/goof/envflag" | |
) | |
// example for a custom envflag.Enumerator | |
type mode string | |
func Mode(m string) *mode { | |
// this is very, very ugly and just for demonstration purposes... | |
defaultMode := "prod" | |
result := (*mode)(&defaultMode) | |
result.Set(m) // ignore errors, keep default | |
return result | |
} | |
func (m *mode) Values() []string { | |
return []string{"prod", "dev", "test"} | |
} | |
func (m *mode) Set(v string) error { | |
switch v { | |
case "prod", "dev", "test": | |
default: | |
return fmt.Errorf("unknown mode %q", v) | |
} | |
*m = mode(v) | |
return nil | |
} | |
func (m *mode) String() string { | |
return *(*string)(m) | |
} | |
func (m *mode) Describe(v string) string { | |
switch v { | |
case "prod": | |
return "production environment" | |
case "dev": | |
return "development environment" | |
case "test": | |
return "test environment" | |
} | |
return "" | |
} | |
func main() { | |
var err error | |
// this is the whole configuration. If no optional struct tags exist, | |
// everything is inferred from the field name, type and initial value. | |
config := struct { | |
Host string `desc:"target smtp server name or ip"` | |
Port uint `desc:"smtp port (usually 25 or 587)"` | |
User string `desc:"user name"` | |
Password string `key:"pass" desc:"login password"` | |
SortArgs bool `arg:"sorthelp" tag:"help"` | |
FullHelp bool `args:"fh,v" desc:"print full help text" tag:"help"` | |
Mode *mode `desc:"program mode"` | |
}{ | |
Host: "127.0.0.1", | |
Port: 587, | |
SortArgs: true, | |
Mode: Mode("test"), | |
} | |
// create a set of parameters (environment variables prefixed with MYAPP_) | |
env := envflag.Environment("myapp/") | |
params := env.WithParameters("") // api messup, I'll get rid of this | |
// register the struct | |
params.Register(&config) | |
// seed configuration parameters from environment variables | |
// could also load from a file instead of os.Getenv | |
err = params.SetValues(os.Getenv) | |
if err != nil { | |
panic(err) | |
} | |
// parse command line arguments, overwrite existing values with ones given there | |
err = params.Parse(os.Args[1:]) | |
if err != nil { | |
panic(err) | |
} | |
// fetch available parameters and sort them by command line argument name | |
p := parameters(params.Explore()) | |
if config.SortArgs { | |
sort.Sort(p) | |
} | |
w := tabwriter.NewWriter(os.Stdout, 4, 0, 2, ' ', 0) | |
if config.FullHelp { | |
printHelp(w, p) | |
} else { | |
printArgTable(w, p) | |
} | |
w.Flush() | |
} | |
type parameters []envflag.Parameter | |
func (ps parameters) Len() int { | |
return len(ps) | |
} | |
func (ps parameters) Swap(i, j int) { | |
ps[i], ps[j] = ps[j], ps[i] | |
} | |
func (ps parameters) Less(i, j int) bool { | |
return ps[i].ArgKey < ps[j].ArgKey | |
} | |
func HasTag(tag, key string) bool { | |
parts := strings.Split(tag, " ") | |
for _, p := range parts { | |
if p == key { | |
return true | |
} | |
} | |
return false | |
} | |
func printArgTable(w io.Writer, params parameters) { | |
fmt.Fprintf(w, "Key\tArg\tEnv\tValue\tDefault\tDescription\n") | |
for i := range params { | |
p := ¶ms[i] | |
// show usage of tag | |
if HasTag(p.Tag, "help") { | |
fmt.Fprintf(w, "%s\t-%s\t%s\t%q\t%q\t[?] %s\n", | |
p.Key, p.ArgKey, p.EnvKey, p.Value, p.DefaultValue, p.Description, | |
) | |
} else { | |
fmt.Fprintf(w, "%s\t-%s\t%s\t%q\t%q\t%s\n", | |
p.Key, p.ArgKey, p.EnvKey, p.Value, p.DefaultValue, p.Description, | |
) | |
} | |
} | |
} | |
func printHelp(w io.Writer, params parameters) { | |
fmt.Fprintf(w, "List of available configuration options:\n\n") | |
for _, p := range params { | |
var defaultVal string | |
if p.Value != p.DefaultValue { | |
defaultVal = fmt.Sprintf(" (default %q)", p.DefaultValue) | |
} | |
desc := p.Description | |
if desc == "" { | |
desc = "<no description>" | |
} | |
fmt.Fprintf( | |
w, | |
"ENV: $%s\tType: %s\n"+ | |
"ARG: -%s\n"+ | |
"\t%s\n"+ | |
"\tvalue: %q%s\n", | |
p.EnvKey, p.Type, | |
strings.Join(append([]string{p.ArgKey}, p.ArgAliases...), ", -"), | |
desc, | |
p.Value, defaultVal, | |
) | |
// show usage of options | |
for _, o := range p.Options { | |
fmt.Fprintf(w, "\t[%s]\t%s\n", o.Value, o.Description) | |
} | |
fmt.Fprintln(w) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment