Skip to content

Commit

Permalink
Merge pull request #154 from hairyhenderson/support-toml
Browse files Browse the repository at this point in the history
Adding TOML support
  • Loading branch information
hairyhenderson authored Jun 5, 2017
2 parents 710012f + b1730c1 commit 3837f48
Show file tree
Hide file tree
Showing 44 changed files with 6,258 additions and 21 deletions.
33 changes: 15 additions & 18 deletions data.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,20 @@ import (
// logFatal is defined so log.Fatal calls can be overridden for testing
var logFatalf = log.Fatalf

func init() {
// Add some types we want to be able to handle which can be missing by default
err := mime.AddExtensionType(".json", "application/json")
if err != nil {
log.Fatal(err)
}
err = mime.AddExtensionType(".yml", "application/yaml")
if err != nil {
log.Fatal(err)
}
err = mime.AddExtensionType(".yaml", "application/yaml")
if err != nil {
log.Fatal(err)
}
err = mime.AddExtensionType(".csv", "text/csv")
func regExtension(ext, typ string) {
err := mime.AddExtensionType(ext, typ)
if err != nil {
log.Fatal(err)
}
}

func init() {
// Add some types we want to be able to handle which can be missing by default
regExtension(".json", "application/json")
regExtension(".yml", "application/yaml")
regExtension(".yaml", "application/yaml")
regExtension(".csv", "text/csv")
regExtension(".toml", "application/toml")

sourceReaders = make(map[string]func(*Source, ...string) ([]byte, error))

Expand Down Expand Up @@ -184,18 +180,19 @@ func (d *Data) Datasource(alias string, args ...string) interface{} {
log.Fatalf("Couldn't read datasource '%s': %s", alias, err)
}
s := string(b)
ty := &TypeConv{}
if source.Type == "application/json" {
ty := &TypeConv{}
return ty.JSON(s)
}
if source.Type == "application/yaml" {
ty := &TypeConv{}
return ty.YAML(s)
}
if source.Type == "text/csv" {
ty := &TypeConv{}
return ty.CSV(s)
}
if source.Type == "application/toml" {
return ty.TOML(s)
}
log.Fatalf("Datasources of type %s not yet supported", source.Type)
return nil
}
Expand Down
68 changes: 67 additions & 1 deletion docs/content/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,44 @@ $ gomplate < input.tmpl
Hello world
```

## `toml`

Converts a [TOML](https://github.com/toml-lang/toml) document into an object.
This can be used to access properties of TOML documents.

Compatible with [TOML v0.4.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md).

### Usage

```go
toml input
```

Can also be used in a pipeline:
```go
input | toml
```

### Arguments

| name | description |
|--------|-------|
| `input` | the TOML document to parse |

#### Example

_`input.tmpl`:_
```
{{ $t := `[data]
hello = "world"` -}}
Hello {{ (toml $t).hello }}
```

```console
$ gomplate -f input.tmpl
Hello world
```

## `csv`

Converts a CSV-format string into a 2-dimensional string array.
Expand Down Expand Up @@ -547,6 +585,34 @@ $ gomplate < input.tmpl
hello: world
```

## `toTOML`

Converts an object to a [TOML](https://github.com/toml-lang/toml) document.

### Usage

```go
toTOML obj
```

Can also be used in a pipeline:
```go
obj | toTOML
```

### Arguments

| name | description |
|--------|-------|
| `obj` | the object to marshal as a TOML document |

#### Example

```console
$ gomplate -i '{{ `{"foo":"bar"}` | json | toTOML }}'
foo = "bar"
```

## `toCSV`

Converts an object to a CSV document. The input object must be a 2-dimensional
Expand Down Expand Up @@ -598,7 +664,7 @@ Parses a given datasource (provided by the [`--datasource/-d`](#--datasource-d)

Currently, `file://`, `http://`, `https://`, and `vault://` URLs are supported.

Currently-supported formats are JSON, YAML, and CSV.
Currently-supported formats are JSON, YAML, TOML, and CSV.

#### Examples

Expand Down
6 changes: 4 additions & 2 deletions glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions glide.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import:
- package: github.com/ugorji/go
subpackages:
- codec
- package: github.com/hairyhenderson/toml
version: support-map-interface-keys
testImport:
- package: github.com/stretchr/testify
version: ^1.1.4
Expand Down
2 changes: 2 additions & 0 deletions gomplate.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ func NewGomplate(data *Data, leftDelim, rightDelim string) *Gomplate {
"jsonArray": typeconv.JSONArray,
"yaml": typeconv.YAML,
"yamlArray": typeconv.YAMLArray,
"toml": typeconv.TOML,
"csv": typeconv.CSV,
"csvByRow": typeconv.CSVByRow,
"csvByColumn": typeconv.CSVByColumn,
Expand All @@ -61,6 +62,7 @@ func NewGomplate(data *Data, leftDelim, rightDelim string) *Gomplate {
"toJSON": typeconv.ToJSON,
"toJSONPretty": typeconv.toJSONPretty,
"toYAML": typeconv.ToYAML,
"toTOML": typeconv.ToTOML,
"toCSV": typeconv.ToCSV,
"ec2meta": ec2meta.Meta,
"ec2dynamic": ec2meta.Dynamic,
Expand Down
19 changes: 19 additions & 0 deletions test/integration/typeconv_funcs.bats
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,22 @@ Languages are: {{ join $c.lang " and " }}'
[ "$status" -eq 0 ]
[[ "${output}" == "Languages are: C and Go and COBOL" ]]
}

@test "'toml'" {
gomplate -i '{{ $t := `# comment
foo = "bar"
[baz]
qux = "quux"` | toml -}}
{{ $t.baz.qux }}'
[ "$status" -eq 0 ]
[[ "${output}" == "quux" ]]
}

@test "'toTOML'" {
gomplate -i '{{ "foo:\n bar:\n baz: qux" | yaml | toTOML }}'
[ "$status" -eq 0 ]
[[ "${output}" == "[foo]
[foo.bar]
baz = \"qux\"" ]]
}
18 changes: 18 additions & 0 deletions typeconv.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (

yaml "gopkg.in/yaml.v2"

// XXX: replace once https://github.com/BurntSushi/toml/pull/179 is merged
"github.com/hairyhenderson/toml"
"github.com/ugorji/go/codec"
)

Expand Down Expand Up @@ -69,6 +71,12 @@ func (t *TypeConv) YAMLArray(in string) []interface{} {
return unmarshalArray(obj, in, yaml.Unmarshal)
}

// TOML - Unmarshal a TOML Object
func (t *TypeConv) TOML(in string) interface{} {
obj := make(map[string]interface{})
return unmarshalObj(obj, in, toml.Unmarshal)
}

func parseCSV(args ...string) (records [][]string, hdr []string) {
delim := ","
var in string
Expand Down Expand Up @@ -249,6 +257,16 @@ func (t *TypeConv) ToYAML(in interface{}) string {
return marshalObj(in, yaml.Marshal)
}

// ToTOML - Stringify a struct as TOML
func (t *TypeConv) ToTOML(in interface{}) string {
buf := new(bytes.Buffer)
err := toml.NewEncoder(buf).Encode(in)
if err != nil {
log.Fatalf("Unable to marshal %s: %v", in, err)
}
return string(buf.Bytes())
}

// Slice creates a slice from a bunch of arguments
func (t *TypeConv) Slice(args ...interface{}) []interface{} {
return args
Expand Down
100 changes: 100 additions & 0 deletions typeconv_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,3 +293,103 @@ func TestToCSV(t *testing.T) {

assert.Equal(t, expected, ty.ToCSV(";", in))
}

func TestTOML(t *testing.T) {
ty := new(TypeConv)
in := `# This is a TOML document. Boom.
title = "TOML Example"
[owner]
name = "Tom Preston-Werner"
organization = "GitHub"
bio = "GitHub Cofounder & CEO\nLikes tater tots and beer."
dob = 1979-05-27T07:32:00Z # First class dates? Why not?
[database]
server = "192.168.1.1"
ports = [ 8001, 8001, 8002 ]
connection_max = 5000
enabled = true
[servers]
# You can indent as you please. Tabs or spaces. TOML don't care.
[servers.alpha]
ip = "10.0.0.1"
dc = "eqdc10"
[servers.beta]
ip = "10.0.0.2"
dc = "eqdc10"
[clients]
data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it
# Line breaks are OK when inside arrays
hosts = [
"alpha",
"omega"
]
`
expected := map[string]interface{}{
"title": "TOML Example",
"owner": map[string]interface{}{
"name": "Tom Preston-Werner",
"organization": "GitHub",
"bio": "GitHub Cofounder & CEO\nLikes tater tots and beer.",
"dob": time.Date(1979, time.May, 27, 7, 32, 0, 0, time.UTC),
},
"database": map[string]interface{}{
"server": "192.168.1.1",
"ports": []interface{}{int64(8001), int64(8001), int64(8002)},
"connection_max": int64(5000),
"enabled": true,
},
"servers": map[string]interface{}{
"alpha": map[string]interface{}{
"ip": "10.0.0.1",
"dc": "eqdc10",
},
"beta": map[string]interface{}{
"ip": "10.0.0.2",
"dc": "eqdc10",
},
},
"clients": map[string]interface{}{
"data": []interface{}{
[]interface{}{"gamma", "delta"},
[]interface{}{int64(1), int64(2)},
},
"hosts": []interface{}{"alpha", "omega"},
},
}

assert.Equal(t, expected, ty.TOML(in))
}

func TestToTOML(t *testing.T) {
ty := new(TypeConv)
expected := `foo = "bar"
one = 1
true = true
[down]
[down.the]
[down.the.rabbit]
hole = true
`
in := map[string]interface{}{
"foo": "bar",
"one": 1,
"true": true,
"down": map[interface{}]interface{}{
"the": map[interface{}]interface{}{
"rabbit": map[interface{}]interface{}{
"hole": true,
},
},
},
}
assert.Equal(t, expected, ty.ToTOML(in))
}
5 changes: 5 additions & 0 deletions vendor/github.com/hairyhenderson/toml/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions vendor/github.com/hairyhenderson/toml/.travis.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions vendor/github.com/hairyhenderson/toml/COMPATIBLE

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions vendor/github.com/hairyhenderson/toml/COPYING

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 3837f48

Please sign in to comment.