Encode: add comment struct tag (#711)
Similar to v1, add a `comment` struct that that makes the encoder emit a comment before the annotated element, if permitted. Unlike v1, comments are compact by default (and cannot be changed). Fixes #595.
This commit is contained in:
+34
-15
@@ -104,30 +104,31 @@ func (enc *Encoder) SetIndentTables(indent bool) *Encoder {
|
|||||||
// Intermediate tables are always printed.
|
// Intermediate tables are always printed.
|
||||||
//
|
//
|
||||||
// By default, strings are encoded as literal string, unless they contain either
|
// By default, strings are encoded as literal string, unless they contain either
|
||||||
// a newline character or a single quote. In that case they are emitted as quoted
|
// a newline character or a single quote. In that case they are emitted as
|
||||||
// strings.
|
// quoted strings.
|
||||||
//
|
//
|
||||||
// When encoding structs, fields are encoded in order of definition, with their
|
// When encoding structs, fields are encoded in order of definition, with their
|
||||||
// exact name.
|
// exact name.
|
||||||
//
|
//
|
||||||
// Struct tags
|
// Struct tags
|
||||||
//
|
//
|
||||||
// The encoding of each public struct field can be customized by the
|
// The encoding of each public struct field can be customized by the format
|
||||||
// format string in the "toml" key of the struct field's tag. This
|
// string in the "toml" key of the struct field's tag. This follows
|
||||||
// follows encoding/json's convention. The format string starts with
|
// encoding/json's convention. The format string starts with the name of the
|
||||||
// the name of the field, optionally followed by a comma-separated
|
// field, optionally followed by a comma-separated list of options. The name may
|
||||||
// list of options. The name may be empty in order to provide options
|
// be empty in order to provide options without overriding the default name.
|
||||||
// without overriding the default name.
|
|
||||||
//
|
//
|
||||||
// The "multiline" option emits strings as quoted multi-line TOML
|
// The "multiline" option emits strings as quoted multi-line TOML strings. It
|
||||||
// strings. It has no effect on fields that would not be encoded as
|
// has no effect on fields that would not be encoded as strings.
|
||||||
// strings.
|
|
||||||
//
|
//
|
||||||
// The "inline" option turns fields that would be emitted as tables
|
// The "inline" option turns fields that would be emitted as tables into inline
|
||||||
// into inline tables instead. It has no effect on other fields.
|
// tables instead. It has no effect on other fields.
|
||||||
//
|
//
|
||||||
// The "omitempty" option prevents empty values or groups from being
|
// The "omitempty" option prevents empty values or groups from being emitted.
|
||||||
// emitted.
|
//
|
||||||
|
// In addition to the "toml" tag struct tag, a "comment" tag can be used to emit
|
||||||
|
// a TOML comment before the value being annotated. Comments are ignored inside
|
||||||
|
// inline tables.
|
||||||
func (enc *Encoder) Encode(v interface{}) error {
|
func (enc *Encoder) Encode(v interface{}) error {
|
||||||
var (
|
var (
|
||||||
b []byte
|
b []byte
|
||||||
@@ -156,6 +157,7 @@ func (enc *Encoder) Encode(v interface{}) error {
|
|||||||
type valueOptions struct {
|
type valueOptions struct {
|
||||||
multiline bool
|
multiline bool
|
||||||
omitempty bool
|
omitempty bool
|
||||||
|
comment string
|
||||||
}
|
}
|
||||||
|
|
||||||
type encoderCtx struct {
|
type encoderCtx struct {
|
||||||
@@ -306,6 +308,10 @@ func (enc *Encoder) encodeKv(b []byte, ctx encoderCtx, options valueOptions, v r
|
|||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !ctx.inline {
|
||||||
|
b = enc.encodeComment(ctx.indent, options.comment, b)
|
||||||
|
}
|
||||||
|
|
||||||
b = enc.indent(ctx.indent, b)
|
b = enc.indent(ctx.indent, b)
|
||||||
|
|
||||||
b, err = enc.encodeKey(b, ctx.key)
|
b, err = enc.encodeKey(b, ctx.key)
|
||||||
@@ -441,6 +447,8 @@ func (enc *Encoder) encodeTableHeader(ctx encoderCtx, b []byte) ([]byte, error)
|
|||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b = enc.encodeComment(ctx.indent, ctx.options.comment, b)
|
||||||
|
|
||||||
b = enc.indent(ctx.indent, b)
|
b = enc.indent(ctx.indent, b)
|
||||||
|
|
||||||
b = append(b, '[')
|
b = append(b, '[')
|
||||||
@@ -590,6 +598,7 @@ func (enc *Encoder) encodeStruct(b []byte, ctx encoderCtx, v reflect.Value) ([]b
|
|||||||
options := valueOptions{
|
options := valueOptions{
|
||||||
multiline: opts.multiline,
|
multiline: opts.multiline,
|
||||||
omitempty: opts.omitempty,
|
omitempty: opts.omitempty,
|
||||||
|
comment: fieldType.Tag.Get("comment"),
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.inline || !willConvertToTableOrArrayTable(ctx, f) {
|
if opts.inline || !willConvertToTableOrArrayTable(ctx, f) {
|
||||||
@@ -602,6 +611,16 @@ func (enc *Encoder) encodeStruct(b []byte, ctx encoderCtx, v reflect.Value) ([]b
|
|||||||
return enc.encodeTable(b, ctx, t)
|
return enc.encodeTable(b, ctx, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (enc *Encoder) encodeComment(indent int, comment string, b []byte) []byte {
|
||||||
|
if comment != "" {
|
||||||
|
b = enc.indent(indent, b)
|
||||||
|
b = append(b, "# "...)
|
||||||
|
b = append(b, comment...)
|
||||||
|
b = append(b, '\n')
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
func isValidName(s string) bool {
|
func isValidName(s string) bool {
|
||||||
if s == "" {
|
if s == "" {
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -21,6 +21,12 @@ func TestMarshal(t *testing.T) {
|
|||||||
A interface{} `toml:",inline"`
|
A interface{} `toml:",inline"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type comments struct {
|
||||||
|
One int
|
||||||
|
Two int `comment:"Before kv"`
|
||||||
|
Three []int `comment:"Before array"`
|
||||||
|
}
|
||||||
|
|
||||||
examples := []struct {
|
examples := []struct {
|
||||||
desc string
|
desc string
|
||||||
v interface{}
|
v interface{}
|
||||||
@@ -535,6 +541,27 @@ J = 42
|
|||||||
K = 42
|
K = 42
|
||||||
L = 2.2`,
|
L = 2.2`,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "comments",
|
||||||
|
v: struct {
|
||||||
|
Table comments `comment:"Before table"`
|
||||||
|
}{
|
||||||
|
Table: comments{
|
||||||
|
One: 1,
|
||||||
|
Two: 2,
|
||||||
|
Three: []int{1, 2, 3},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: `
|
||||||
|
# Before table
|
||||||
|
[Table]
|
||||||
|
One = 1
|
||||||
|
# Before kv
|
||||||
|
Two = 2
|
||||||
|
# Before array
|
||||||
|
Three = [1, 2, 3]
|
||||||
|
`,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, e := range examples {
|
for _, e := range examples {
|
||||||
|
|||||||
Reference in New Issue
Block a user