diff --git a/example/hcl/echo.go b/example/hcl/echo.go new file mode 100644 index 0000000..7c4c73f --- /dev/null +++ b/example/hcl/echo.go @@ -0,0 +1,37 @@ +package main + +import ( + "fmt" + + "github.com/paked/configure" +) + +var ( + // set up a configure instance with no default stack + conf = configure.New() + // declare flags / things to configure + amount = conf.Int("amount", 0, "how many times you want the string repeated!") + message = conf.String("message", "Echo!", "a selected string") + newlines = conf.Bool("newlines", true, "whether or not you want new lines") +) + +func init() { + // add configuration middlewears to the stack + conf.Use(configure.NewHCLFromFile("echo.hcl")) +} + +func main() { + // populate the pointers + conf.Parse() + for i := 0; i < *amount; i++ { + fmt.Print(*message) + + if *newlines { + fmt.Print("\n") + } + } +} + +func usage() string { + return "Echo is the best message echo-er available in your terminal!\nUse the amount flag to set how many times you to echo\nmessage for what you want to echo\nand newlines for whether you want breaks in between messages\n" +} diff --git a/example/hcl/echo.hcl b/example/hcl/echo.hcl new file mode 100644 index 0000000..36f2cae --- /dev/null +++ b/example/hcl/echo.hcl @@ -0,0 +1,3 @@ +amount = 10 +message = "hello " +newlines = false \ No newline at end of file diff --git a/hcl.go b/hcl.go new file mode 100644 index 0000000..ab8f42c --- /dev/null +++ b/hcl.go @@ -0,0 +1,100 @@ +package configure + +import ( + "bytes" + "errors" + "fmt" + "io" + "os" + + "github.com/hashicorp/hcl" +) + +// NewHCL returns an instance of the HCL checker. It takes a function +// which returns an io.Reader which will be called when the first value +// is recalled. The contents of the io.Reader MUST be decodable into HCL or JSON. +func NewHCL(gen func() (io.Reader, error)) *HCL { + return &HCL{ + gen: gen, + } +} + +// NewHCLFromFile returns an instance of the HCL checker. It reads its +// data from a file (file content can be HCL or JSON) which its location has been specified through the path +// parameter +func NewHCLFromFile(path string) *HCL { + return NewHCL(func() (io.Reader, error) { + return os.Open(path) + }) +} + +// HCL represents the HCL Checker. It reads an io.Reader and then pulls a value out of a map[string]interface{}. +type HCL struct { + values map[string]interface{} + gen func() (io.Reader, error) +} + +func (h *HCL) Setup() error { + r, err := h.gen() + if err != nil { + return err + } + buf := new(bytes.Buffer) + buf.ReadFrom(r) + s := buf.String() + //first parse the hcl file + obj, err := hcl.Parse(s) + if err != nil { + return err + } + h.values = make(map[string]interface{}) + //then decode the object + if err = hcl.DecodeObject(&h.values, obj); err != nil { + return err + } + return nil + +} + +func (h *HCL) value(name string) (interface{}, error) { + val, ok := h.values[name] + if !ok { + return nil, errors.New("variable does not exist") + } + return val, nil +} + +//Int returns an int if it exists within the HCL io.Reader +func (h *HCL) Int(name string) (int, error) { + v, err := h.value(name) + if err != nil { + return 0, err + } + f, ok := v.(float64) + if !ok { + i, ok := v.(int) + if !ok { + return v.(int), errors.New(fmt.Sprintf("%T unable", v)) + } + return i, nil + } + return int(f), nil +} + +// Bool returns a bool if it exists within the HCL io.Reader. +func (h *HCL) Bool(name string) (bool, error) { + v, err := h.value(name) + if err != nil { + return false, err + } + return v.(bool), nil +} + +// String returns a string if it exists within the HCL io.Reader. +func (h *HCL) String(name string) (string, error) { + v, err := h.value(name) + if err != nil { + return "", err + } + return v.(string), nil +}