Skip to content

Instantly share code, notes, and snippets.

@rybit
Created May 27, 2020 01:02
Show Gist options
  • Save rybit/6856231c83cab48ffc93e6aa174d215e to your computer and use it in GitHub Desktop.
Save rybit/6856231c83cab48ffc93e6aa174d215e to your computer and use it in GitHub Desktop.
package main
import (
"errors"
"fmt"
"os"
"reflect"
"strconv"
"strings"
"github.com/fatih/structs"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
type cmdArgs struct {
SomeString string `short:"s"`
SomeInt int `short:"i"`
}
func main() {
args := cmdArgs{
SomeString: "default string value",
SomeInt: 9,
}
cmd := cobra.Command{
Run: func(_ *cobra.Command, _ []string) {
fmt.Printf("%+v\n", args)
},
}
flags := cmd.PersistentFlags()
flags.AddFlagSet(fromStruct(&args))
if err := cmd.Execute(); err != nil {
panic(err)
}
}
func fromStruct(facePointer interface{}) *pflag.FlagSet {
set := pflag.FlagSet{}
fields := structs.Fields(facePointer)
for _, f := range fields {
if !f.IsExported() {
continue
}
name := f.Tag("cli")
if name == "" {
name = f.Name()
}
short := f.Tag("short")
if short == "" {
short = string(name[0])
}
envVarName := f.Tag("envvar")
if envVarName == "" {
// TODO split on the camel case
envVarName = strings.ToUpper(strings.Join(strings.Split(name, "-"), "_"))
}
fv := fieldValue(*f)
defaultVal := os.Getenv(envVarName)
if defaultVal != "" {
if err := fv.Set(defaultVal); err != nil {
panic(err)
}
}
fmt.Println(name, fv.Type(), fv.String())
set.AddFlag(&pflag.Flag{
Name: name,
Shorthand: short,
Value: &fv,
})
}
return &set
}
type fieldValue structs.Field
func (s *fieldValue) Set(val string) error {
v := (*structs.Field)(s)
switch v.Kind() {
case reflect.String:
return v.Set(val)
case reflect.Int:
intVal, err := strconv.Atoi(val)
if err != nil {
return err
}
return v.Set(intVal)
}
return errors.New("wtf")
}
func (s *fieldValue) Type() string {
v := (*structs.Field)(s)
return v.Kind().String()
}
func (s *fieldValue) String() string {
v := (*structs.Field)(s)
return fmt.Sprintf("%v", v.Value())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment