Skip to content

Commit

Permalink
Support literal multiline marshal (#485)
Browse files Browse the repository at this point in the history
Use struct tag `multiline:"true" literal:"true"` to enable it.
  • Loading branch information
pelletier authored Mar 26, 2021
1 parent b59c12a commit ce6fbd7
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 1 deletion.
7 changes: 7 additions & 0 deletions marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const (
tagFieldComment = "comment"
tagCommented = "commented"
tagMultiline = "multiline"
tagLiteral = "literal"
tagDefault = "default"
)

Expand All @@ -27,6 +28,7 @@ type tomlOpts struct {
comment string
commented bool
multiline bool
literal bool
include bool
omitempty bool
defaultValue string
Expand All @@ -46,6 +48,7 @@ type annotation struct {
comment string
commented string
multiline string
literal string
defaultValue string
}

Expand All @@ -54,6 +57,7 @@ var annotationDefault = annotation{
comment: tagFieldComment,
commented: tagCommented,
multiline: tagMultiline,
literal: tagLiteral,
defaultValue: tagDefault,
}

Expand Down Expand Up @@ -442,6 +446,7 @@ func (e *Encoder) valueToTree(mtype reflect.Type, mval reflect.Value) (*Tree, er
Comment: opts.comment,
Commented: opts.commented,
Multiline: opts.multiline,
Literal: opts.literal,
}, val)
}
}
Expand Down Expand Up @@ -1168,13 +1173,15 @@ func tomlOptions(vf reflect.StructField, an annotation) tomlOpts {
}
commented, _ := strconv.ParseBool(vf.Tag.Get(an.commented))
multiline, _ := strconv.ParseBool(vf.Tag.Get(an.multiline))
literal, _ := strconv.ParseBool(vf.Tag.Get(an.literal))
defaultValue := vf.Tag.Get(tagDefault)
result := tomlOpts{
name: vf.Name,
nameFromTag: false,
comment: comment,
commented: commented,
multiline: multiline,
literal: literal,
include: true,
omitempty: false,
defaultValue: defaultValue,
Expand Down
26 changes: 26 additions & 0 deletions marshal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1294,6 +1294,32 @@ NonCommented = "Not commented line"
}
}

func TestMarshalMultilineLiteral(t *testing.T) {
type Doc struct {
Value string `multiline:"true" literal:"true"`
}

d := Doc{
Value: "hello\nworld\ttest\nend",
}

expected := []byte(`Value = '''
hello
world test
end
'''
`)

b, err := Marshal(d)
if err != nil {
t.Fatal("unexpected error")
}

if !bytes.Equal(b, expected) {
t.Errorf("Bad marshal: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expected, b)
}
}

func TestMarshalNonPrimitiveTypeCommented(t *testing.T) {
expectedToml := []byte(`
# [CommentedMapField]
Expand Down
4 changes: 4 additions & 0 deletions toml.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type tomlValue struct {
comment string
commented bool
multiline bool
literal bool
position Position
}

Expand Down Expand Up @@ -314,6 +315,7 @@ type SetOptions struct {
Comment string
Commented bool
Multiline bool
Literal bool
}

// SetWithOptions is the same as Set, but allows you to provide formatting
Expand Down Expand Up @@ -362,12 +364,14 @@ func (t *Tree) SetPathWithOptions(keys []string, opts SetOptions, value interfac
v.comment = opts.Comment
v.commented = opts.Commented
v.multiline = opts.Multiline
v.literal = opts.Literal
toInsert = v
default:
toInsert = &tomlValue{value: value,
comment: opts.Comment,
commented: opts.Commented,
multiline: opts.Multiline,
literal: opts.Literal,
position: Position{Line: subtree.position.Line + len(subtree.values) + 1, Col: subtree.position.Col}}
}

Expand Down
10 changes: 9 additions & 1 deletion tomltree_write.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,15 @@ func tomlValueStringRepresentation(v interface{}, commented string, indent strin
return strings.ToLower(strconv.FormatFloat(value, 'f', -1, bits)), nil
case string:
if tv.multiline {
return "\"\"\"\n" + encodeMultilineTomlString(value, commented) + "\"\"\"", nil
if tv.literal {
b := strings.Builder{}
b.WriteString("'''\n")
b.Write([]byte(value))
b.WriteString("\n'''")
return b.String(), nil
} else {
return "\"\"\"\n" + encodeMultilineTomlString(value, commented) + "\"\"\"", nil
}
}
return "\"" + encodeTomlString(value) + "\"", nil
case []byte:
Expand Down

0 comments on commit ce6fbd7

Please sign in to comment.