feat: add field comments, local time zone decoding and in-value cancellation
Test / test (push) Successful in 1m32s
Test / test (push) Successful in 1m32s
Assisted-by: GLM 5.3 Flash
This commit is contained in:
@@ -308,6 +308,11 @@ type entry struct {
|
||||
// `,inline` tag option. An array of tables keeps the header form.
|
||||
inline bool
|
||||
|
||||
// comments are the comment lines written above this entry's line or
|
||||
// header, which the `comment=` tag option carries when
|
||||
// Encoder.EmitFieldComments is on.
|
||||
comments []string
|
||||
|
||||
// emitted records that the grouped emission wrote this table inline, so
|
||||
// the header pass that follows skips it. The representation is built
|
||||
// fresh per Marshal call.
|
||||
@@ -482,9 +487,17 @@ func walkStructDoc(v reflect.Value, doc *tomlDoc, path encPath, prefix []int, sc
|
||||
if fieldOmitted(f, v.Field(i)) {
|
||||
continue
|
||||
}
|
||||
before := len(doc.entries)
|
||||
if err := addField(doc, name, v.Field(i), path, tagHasOption(f.Tag.Get("toml"), "inline")); err != nil {
|
||||
return err
|
||||
}
|
||||
// The comment a `comment=` tag option carries lands on the entry the
|
||||
// field emitted, when the option to print field comments is on.
|
||||
if len(doc.entries) > before && doc.opts.emitFieldComments {
|
||||
if text := tagComment(f.Tag.Get("toml")); text != "" {
|
||||
doc.entries[len(doc.entries)-1].comments = strings.Split(text, "\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -514,6 +527,20 @@ func tagHasOption(tag, want string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// tagComment returns the text a `comment=` tag option carries, without the
|
||||
// option name. An unset comment comes back empty.
|
||||
func tagComment(tag string) string {
|
||||
opts := tagOptions(tag)
|
||||
for opts != "" {
|
||||
var opt string
|
||||
opt, opts, _ = strings.Cut(opts, ",")
|
||||
if text, ok := strings.CutPrefix(opt, "comment="); ok {
|
||||
return text
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// fieldOmitted reports whether the field's tag options drop it from the
|
||||
// output: omitzero skips the zero value of the field's type, omitempty skips
|
||||
// an empty value in the encoding/json sense, an empty string, a zero number,
|
||||
@@ -1140,7 +1167,7 @@ func (e *encoder) emitDoc(doc *tomlDoc, prefix []string) error {
|
||||
if kv.kind != entryScalar {
|
||||
continue
|
||||
}
|
||||
if err := e.writeKV(kv.key, kv.val); err != nil {
|
||||
if err := e.writeKV(kv); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -1165,6 +1192,7 @@ func (e *encoder) emitDoc(doc *tomlDoc, prefix []string) error {
|
||||
}
|
||||
path := append(append([]string{}, prefix...), t.key)
|
||||
e.writeBlankLine()
|
||||
e.writeComments(t.comments)
|
||||
e.buf.WriteByte('[')
|
||||
if err := e.writeKeyPath(path); err != nil {
|
||||
return err
|
||||
@@ -1180,8 +1208,11 @@ func (e *encoder) emitDoc(doc *tomlDoc, prefix []string) error {
|
||||
continue
|
||||
}
|
||||
path := append(append([]string{}, prefix...), a.key)
|
||||
for _, sub := range a.docs {
|
||||
for j, sub := range a.docs {
|
||||
e.writeBlankLine()
|
||||
if j == 0 {
|
||||
e.writeComments(a.comments)
|
||||
}
|
||||
e.buf.WriteString("[[")
|
||||
if err := e.writeKeyPath(path); err != nil {
|
||||
return err
|
||||
@@ -1203,7 +1234,7 @@ func (e *encoder) emitDoc(doc *tomlDoc, prefix []string) error {
|
||||
for _, ent := range doc.entries {
|
||||
switch ent.kind {
|
||||
case entryScalar:
|
||||
if err := e.writeKV(ent.key, ent.val); err != nil {
|
||||
if err := e.writeKV(&ent); err != nil {
|
||||
return err
|
||||
}
|
||||
case entryTable:
|
||||
@@ -1216,6 +1247,7 @@ func (e *encoder) emitDoc(doc *tomlDoc, prefix []string) error {
|
||||
}
|
||||
path := append(append([]string{}, prefix...), ent.key)
|
||||
e.writeBlankLine()
|
||||
e.writeComments(ent.comments)
|
||||
e.buf.WriteByte('[')
|
||||
if err := e.writeKeyPath(path); err != nil {
|
||||
return err
|
||||
@@ -1226,8 +1258,11 @@ func (e *encoder) emitDoc(doc *tomlDoc, prefix []string) error {
|
||||
}
|
||||
case entryArray:
|
||||
path := append(append([]string{}, prefix...), ent.key)
|
||||
for _, sub := range ent.docs {
|
||||
for j, sub := range ent.docs {
|
||||
e.writeBlankLine()
|
||||
if j == 0 {
|
||||
e.writeComments(ent.comments)
|
||||
}
|
||||
e.buf.WriteString("[[")
|
||||
if err := e.writeKeyPath(path); err != nil {
|
||||
return err
|
||||
@@ -1242,12 +1277,23 @@ func (e *encoder) emitDoc(doc *tomlDoc, prefix []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *encoder) writeKV(key string, val any) error {
|
||||
if err := e.writeKey(key); err != nil {
|
||||
// writeComments writes comment lines above an entry, each prefixed with the
|
||||
// "# " marker the parser strips on the way in.
|
||||
func (e *encoder) writeComments(lines []string) {
|
||||
for _, line := range lines {
|
||||
e.buf.WriteString("# ")
|
||||
e.buf.WriteString(line)
|
||||
e.buf.WriteByte('\n')
|
||||
}
|
||||
}
|
||||
|
||||
func (e *encoder) writeKV(ent *entry) error {
|
||||
e.writeComments(ent.comments)
|
||||
if err := e.writeKey(ent.key); err != nil {
|
||||
return err
|
||||
}
|
||||
e.buf.WriteString(" = ")
|
||||
if err := e.writeValue(val); err != nil {
|
||||
if err := e.writeValue(ent.val); err != nil {
|
||||
return err
|
||||
}
|
||||
e.buf.WriteByte('\n')
|
||||
|
||||
Reference in New Issue
Block a user