Skip to content

Commit

Permalink
add support for hcl
Browse files Browse the repository at this point in the history
add support for the hashicorp configuration language
(https://github.com/hashicorp/hcl) because this configuration language
supports hcl and json. Samples are oriented on the JSON echo sample but
based on a hcl config file
  • Loading branch information
patdhlk committed Dec 11, 2015
1 parent 9d86395 commit c2b4d25
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 0 deletions.
37 changes: 37 additions & 0 deletions example/hcl/echo.go
Original file line number Diff line number Diff line change
@@ -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"
}
3 changes: 3 additions & 0 deletions example/hcl/echo.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
amount = 10
message = "hello "
newlines = false
100 changes: 100 additions & 0 deletions hcl.go
Original file line number Diff line number Diff line change
@@ -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
}

0 comments on commit c2b4d25

Please sign in to comment.