This commit is contained in:
Mike Farah 2022-10-27 16:16:00 +11:00
parent fd79ac8603
commit b87c1503f4
9 changed files with 57 additions and 11 deletions

View File

@ -9,7 +9,7 @@ EOL
testEmptyEval() { testEmptyEval() {
X=$(./yq e test.yml) X=$(./yq e test.yml)
expected=$(cat test.yml) expected="# comment"
assertEquals 0 $? assertEquals 0 $?
assertEquals "$expected" "$X" assertEquals "$expected" "$X"
} }

View File

View File

@ -15,6 +15,7 @@ type yamlDecoder struct {
// work around of various parsing issues by yaml.v3 with document headers // work around of various parsing issues by yaml.v3 with document headers
prefs YamlPreferences prefs YamlPreferences
leadingContent string leadingContent string
readAnything bool
} }
func NewYamlDecoder(prefs YamlPreferences) Decoder { func NewYamlDecoder(prefs YamlPreferences) Decoder {
@ -64,6 +65,7 @@ func (dec *yamlDecoder) Init(reader io.Reader) error {
} }
} }
dec.leadingContent = leadingContent dec.leadingContent = leadingContent
dec.readAnything = false
dec.decoder = *yaml.NewDecoder(readerToUse) dec.decoder = *yaml.NewDecoder(readerToUse)
return nil return nil
} }
@ -72,7 +74,12 @@ func (dec *yamlDecoder) Decode() (*CandidateNode, error) {
var dataBucket yaml.Node var dataBucket yaml.Node
err := dec.decoder.Decode(&dataBucket) err := dec.decoder.Decode(&dataBucket)
if err != nil { if errors.Is(err, io.EOF) && dec.leadingContent != "" && !dec.readAnything {
// force returning an empty node with a comment.
dec.readAnything = true
return dec.blankNodeWithComment(), nil
} else if err != nil {
return nil, err return nil, err
} }
@ -90,3 +97,13 @@ func (dec *yamlDecoder) Decode() (*CandidateNode, error) {
dataBucket.FootComment = "" dataBucket.FootComment = ""
return candidateNode, nil return candidateNode, nil
} }
func (dec *yamlDecoder) blankNodeWithComment() *CandidateNode {
return &CandidateNode{
Document: 0,
Filename: "",
Node: &yaml.Node{Kind: yaml.DocumentNode, Content: []*yaml.Node{{Tag: "!!null", Kind: yaml.ScalarNode}}},
FileIndex: 0,
LeadingContent: dec.leadingContent,
}
}

View File

@ -386,6 +386,7 @@ A best attempt is made to copy comments to xml.
Given a sample.yml file of: Given a sample.yml file of:
```yaml ```yaml
# header comment
# above_cat # above_cat
cat: # inline_cat cat: # inline_cat
# above_array # above_array
@ -402,7 +403,10 @@ yq -o=xml '.' sample.yml
``` ```
will output will output
```xml ```xml
<!-- inline_cat --><cat><!-- above_array inline_array --> <!--
header comment
above_cat
--><!-- inline_cat --><cat><!-- above_array inline_array -->
<array>val1<!-- inline_val1 --></array> <array>val1<!-- inline_val1 --></array>
<array><!-- above_val2 -->val2<!-- inline_val2 --></array> <array><!-- above_val2 -->val2<!-- inline_val2 --></array>
</cat><!-- below_cat --> </cat><!-- below_cat -->

View File

@ -4,24 +4,28 @@ import (
"encoding/xml" "encoding/xml"
"fmt" "fmt"
"io" "io"
"regexp"
"strings" "strings"
yaml "gopkg.in/yaml.v3" yaml "gopkg.in/yaml.v3"
) )
type xmlEncoder struct { type xmlEncoder struct {
indentString string indentString string
writer io.Writer writer io.Writer
prefs XmlPreferences prefs XmlPreferences
leadingContent string
} }
var commentPrefix = regexp.MustCompile(`(^|\n)\s*#`)
func NewXMLEncoder(indent int, prefs XmlPreferences) Encoder { func NewXMLEncoder(indent int, prefs XmlPreferences) Encoder {
var indentString = "" var indentString = ""
for index := 0; index < indent; index++ { for index := 0; index < indent; index++ {
indentString = indentString + " " indentString = indentString + " "
} }
return &xmlEncoder{indentString, nil, prefs} return &xmlEncoder{indentString, nil, prefs, ""}
} }
func (e *xmlEncoder) CanHandleAliases() bool { func (e *xmlEncoder) CanHandleAliases() bool {
@ -33,6 +37,7 @@ func (e *xmlEncoder) PrintDocumentSeparator(writer io.Writer) error {
} }
func (e *xmlEncoder) PrintLeadingContent(writer io.Writer, content string) error { func (e *xmlEncoder) PrintLeadingContent(writer io.Writer, content string) error {
e.leadingContent = commentPrefix.ReplaceAllString(content, "\n")
return nil return nil
} }
@ -42,6 +47,13 @@ func (e *xmlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
e.writer = writer e.writer = writer
encoder.Indent("", e.indentString) encoder.Indent("", e.indentString)
if e.leadingContent != "" {
err := e.encodeComment(encoder, e.leadingContent)
if err != nil {
return err
}
}
switch node.Kind { switch node.Kind {
case yaml.MappingNode: case yaml.MappingNode:
err := e.encodeTopLevelMap(encoder, node) err := e.encodeTopLevelMap(encoder, node)

View File

@ -7,8 +7,16 @@ import (
var loadScenarios = []expressionScenario{ var loadScenarios = []expressionScenario{
{ {
skipDoc: true, skipDoc: true,
description: "Load empty file", description: "Load empty file with a comment",
expression: `load("../../examples/empty.yaml")`, expression: `load("../../examples/empty.yaml")`,
expected: []string{
"D0, P[], (doc)::# comment\n\n",
},
},
{
skipDoc: true,
description: "Load empty file with no comment",
expression: `load("../../examples/empty-no-comment.yaml")`,
expected: []string{ expected: []string{
"D0, P[], (!!null)::\n", "D0, P[], (!!null)::\n",
}, },

View File

@ -111,7 +111,7 @@ func (p *resultsPrinter) PrintResults(matchingNodes *list.List) error {
mappedDoc := el.Value.(*CandidateNode) mappedDoc := el.Value.(*CandidateNode)
log.Debug("-- print sep logic: p.firstTimePrinting: %v, previousDocIndex: %v, mappedDoc.Document: %v", p.firstTimePrinting, p.previousDocIndex, mappedDoc.Document) log.Debug("-- print sep logic: p.firstTimePrinting: %v, previousDocIndex: %v, mappedDoc.Document: %v", p.firstTimePrinting, p.previousDocIndex, mappedDoc.Document)
log.Debug("%v", NodeToString(mappedDoc))
writer, errorWriting := p.printerWriter.GetWriter(mappedDoc) writer, errorWriting := p.printerWriter.GetWriter(mappedDoc)
if errorWriting != nil { if errorWriting != nil {
return errorWriting return errorWriting

View File

@ -75,6 +75,7 @@ func (s *streamEvaluator) EvaluateFiles(expression string, filenames []string, p
} }
if totalProcessDocs == 0 { if totalProcessDocs == 0 {
// problem is I've already slurped the leading content sadface
return s.EvaluateNew(expression, printer) return s.EvaluateNew(expression, printer)
} }

View File

@ -137,7 +137,8 @@ in d before -->
</cat><!-- after cat --> </cat><!-- after cat -->
` `
const yamlWithComments = `# above_cat const yamlWithComments = `# header comment
# above_cat
cat: # inline_cat cat: # inline_cat
# above_array # above_array
array: # inline_array array: # inline_array
@ -147,7 +148,10 @@ cat: # inline_cat
# below_cat # below_cat
` `
const expectedXMLWithComments = `<!-- above_cat inline_cat --><cat><!-- above_array inline_array --> const expectedXMLWithComments = `<!--
header comment
above_cat
--><!-- inline_cat --><cat><!-- above_array inline_array -->
<array>val1<!-- inline_val1 --></array> <array>val1<!-- inline_val1 --></array>
<array><!-- above_val2 -->val2<!-- inline_val2 --></array> <array><!-- above_val2 -->val2<!-- inline_val2 --></array>
</cat><!-- below_cat --> </cat><!-- below_cat -->