Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 4d7ce2c

Browse files
committedDec 5, 2017
Add Encoder opt to emit arrays on multiple lines
A new Encoder option emits arrays with more than one line on multiple lines. This is off by default and toggled with `ArraysWithOneElementPerLine`. For example: ``` A = [1,2,3] ``` Becomes: ``` A = [ 1, 2, 3 ] ``` Fixes #200
1 parent 4e9e0ee commit 4d7ce2c

File tree

4 files changed

+126
-13
lines changed

4 files changed

+126
-13
lines changed
 

‎marshal.go

+26-3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ type tomlOpts struct {
2121

2222
type encOpts struct {
2323
quoteMapKeys bool
24+
arraysOneElementPerLine bool
2425
}
2526

2627
var encOptsDefaults = encOpts{
@@ -174,6 +175,25 @@ func (e *Encoder) QuoteMapKeys(v bool) *Encoder {
174175
return e
175176
}
176177

178+
// ArraysWithOneElementPerLine sets up the encoder to encode arrays
179+
// with more than one element on multiple lines instead of one.
180+
//
181+
// For example:
182+
//
183+
// A = [1,2,3]
184+
//
185+
// Becomes
186+
//
187+
// A = [
188+
// 1,
189+
// 2,
190+
// 3
191+
// ]
192+
func (e *Encoder) ArraysWithOneElementPerLine(v bool) *Encoder {
193+
e.arraysOneElementPerLine = v
194+
return e
195+
}
196+
177197
func (e *Encoder) marshal(v interface{}) ([]byte, error) {
178198
mtype := reflect.TypeOf(v)
179199
if mtype.Kind() != reflect.Struct {
@@ -187,8 +207,11 @@ func (e *Encoder) marshal(v interface{}) ([]byte, error) {
187207
if err != nil {
188208
return []byte{}, err
189209
}
190-
s, err := t.ToTomlString()
191-
return []byte(s), err
210+
211+
var buf bytes.Buffer
212+
_, err = t.writeTo(&buf, "", "", 0, e.arraysOneElementPerLine)
213+
214+
return buf.Bytes(), err
192215
}
193216

194217
// Convert given marshal struct or map value to toml tree
@@ -218,7 +241,7 @@ func (e *Encoder) valueToTree(mtype reflect.Type, mval reflect.Value) (*Tree, er
218241
return nil, err
219242
}
220243
if e.quoteMapKeys {
221-
keyStr, err := tomlValueStringRepresentation(key.String())
244+
keyStr, err := tomlValueStringRepresentation(key.String(), "", e.arraysOneElementPerLine)
222245
if err != nil {
223246
return nil, err
224247
}

‎marshal_test.go

+71
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,7 @@ func TestEncodeQuotedMapKeys(t *testing.T) {
721721
t.Errorf("Bad maps marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, result)
722722
}
723723
}
724+
724725
func TestDecodeQuotedMapKeys(t *testing.T) {
725726
result := mapsTestStruct{}
726727
err := NewDecoder(bytes.NewBuffer(mapsTestToml)).Decode(&result)
@@ -732,3 +733,73 @@ func TestDecodeQuotedMapKeys(t *testing.T) {
732733
t.Errorf("Bad maps unmarshal: expected %v, got %v", expected, result)
733734
}
734735
}
736+
737+
type structArrayNoTag struct {
738+
A struct {
739+
B []int64
740+
C []int64
741+
}
742+
}
743+
744+
func TestMarshalArray(t *testing.T) {
745+
expected := []byte(`
746+
[A]
747+
B = [1,2,3]
748+
C = [1]
749+
`)
750+
751+
m := structArrayNoTag{
752+
A: struct{
753+
B []int64
754+
C []int64}{
755+
B: []int64{1, 2, 3},
756+
C: []int64{1},
757+
},
758+
}
759+
760+
b, err := Marshal(m)
761+
762+
if err != nil {
763+
t.Fatal(err)
764+
}
765+
766+
if !bytes.Equal(b, expected) {
767+
t.Errorf("Bad arrays marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, b)
768+
}
769+
}
770+
771+
func TestMarshalArrayOnePerLine(t *testing.T) {
772+
expected := []byte(`
773+
[A]
774+
B = [
775+
1,
776+
2,
777+
3
778+
]
779+
C = [1]
780+
`)
781+
782+
m := structArrayNoTag{
783+
A: struct{
784+
B []int64
785+
C []int64
786+
}{
787+
B: []int64{1, 2, 3},
788+
C: []int64{1},
789+
},
790+
}
791+
792+
var buf bytes.Buffer
793+
encoder := NewEncoder(&buf).ArraysWithOneElementPerLine(true)
794+
err := encoder.Encode(m)
795+
796+
if err != nil {
797+
t.Fatal(err)
798+
}
799+
800+
b := buf.Bytes()
801+
802+
if !bytes.Equal(b, expected) {
803+
t.Errorf("Bad arrays marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, b)
804+
}
805+
}

‎parser_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,7 @@ func TestTomlValueStringRepresentation(t *testing.T) {
652652
"[\"gamma\",\"delta\"]"},
653653
{nil, ""},
654654
} {
655-
result, err := tomlValueStringRepresentation(item.Value)
655+
result, err := tomlValueStringRepresentation(item.Value, "",false)
656656
if err != nil {
657657
t.Errorf("Test %d - unexpected error: %s", idx, err)
658658
}

‎tomltree_write.go

+28-9
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ func encodeTomlString(value string) string {
4444
return b.String()
4545
}
4646

47-
func tomlValueStringRepresentation(v interface{}) (string, error) {
47+
func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElementPerLine bool) (string, error) {
4848
switch value := v.(type) {
4949
case uint64:
5050
return strconv.FormatUint(value, 10), nil
@@ -61,7 +61,7 @@ func tomlValueStringRepresentation(v interface{}) (string, error) {
6161
return "\"" + encodeTomlString(value) + "\"", nil
6262
case []byte:
6363
b, _ := v.([]byte)
64-
return tomlValueStringRepresentation(string(b))
64+
return tomlValueStringRepresentation(string(b), indent, arraysOneElementPerLine)
6565
case bool:
6666
if value {
6767
return "true", nil
@@ -76,21 +76,40 @@ func tomlValueStringRepresentation(v interface{}) (string, error) {
7676
rv := reflect.ValueOf(v)
7777

7878
if rv.Kind() == reflect.Slice {
79-
values := []string{}
79+
var values []string
8080
for i := 0; i < rv.Len(); i++ {
8181
item := rv.Index(i).Interface()
82-
itemRepr, err := tomlValueStringRepresentation(item)
82+
itemRepr, err := tomlValueStringRepresentation(item, indent, arraysOneElementPerLine)
8383
if err != nil {
8484
return "", err
8585
}
8686
values = append(values, itemRepr)
8787
}
88+
if arraysOneElementPerLine && len(values) > 1 {
89+
stringBuffer := bytes.Buffer{}
90+
valueIndent := indent + ` ` // TODO: move that to a shared encoder state
91+
92+
stringBuffer.WriteString("[\n")
93+
94+
for i, value := range values {
95+
stringBuffer.WriteString(valueIndent)
96+
stringBuffer.WriteString(value)
97+
if i != len(values) - 1 {
98+
stringBuffer.WriteString(`,`)
99+
}
100+
stringBuffer.WriteString("\n")
101+
}
102+
103+
stringBuffer.WriteString(indent+"]")
104+
105+
return stringBuffer.String(), nil
106+
}
88107
return "[" + strings.Join(values, ",") + "]", nil
89108
}
90109
return "", fmt.Errorf("unsupported value type %T: %v", v, v)
91110
}
92111

93-
func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64) (int64, error) {
112+
func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64, arraysOneElementPerLine bool) (int64, error) {
94113
simpleValuesKeys := make([]string, 0)
95114
complexValuesKeys := make([]string, 0)
96115

@@ -113,7 +132,7 @@ func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64) (
113132
return bytesCount, fmt.Errorf("invalid value type at %s: %T", k, t.values[k])
114133
}
115134

116-
repr, err := tomlValueStringRepresentation(v.value)
135+
repr, err := tomlValueStringRepresentation(v.value, indent, arraysOneElementPerLine)
117136
if err != nil {
118137
return bytesCount, err
119138
}
@@ -178,7 +197,7 @@ func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64) (
178197
if err != nil {
179198
return bytesCount, err
180199
}
181-
bytesCount, err = node.writeTo(w, indent+" ", combinedKey, bytesCount)
200+
bytesCount, err = node.writeTo(w, indent+" ", combinedKey, bytesCount, arraysOneElementPerLine)
182201
if err != nil {
183202
return bytesCount, err
184203
}
@@ -190,7 +209,7 @@ func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64) (
190209
return bytesCount, err
191210
}
192211

193-
bytesCount, err = subTree.writeTo(w, indent+" ", combinedKey, bytesCount)
212+
bytesCount, err = subTree.writeTo(w, indent+" ", combinedKey, bytesCount, arraysOneElementPerLine)
194213
if err != nil {
195214
return bytesCount, err
196215
}
@@ -216,7 +235,7 @@ func writeStrings(w io.Writer, s ...string) (int, error) {
216235
// WriteTo encode the Tree as Toml and writes it to the writer w.
217236
// Returns the number of bytes written in case of success, or an error if anything happened.
218237
func (t *Tree) WriteTo(w io.Writer) (int64, error) {
219-
return t.writeTo(w, "", "", 0)
238+
return t.writeTo(w, "", "", 0, false)
220239
}
221240

222241
// ToTomlString generates a human-readable representation of the current tree.

0 commit comments

Comments
 (0)
Please sign in to comment.