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() {
X=$(./yq e test.yml)
expected=$(cat test.yml)
expected="# comment"
assertEquals 0 $?
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
prefs YamlPreferences
leadingContent string
readAnything bool
}
func NewYamlDecoder(prefs YamlPreferences) Decoder {
@ -64,6 +65,7 @@ func (dec *yamlDecoder) Init(reader io.Reader) error {
}
}
dec.leadingContent = leadingContent
dec.readAnything = false
dec.decoder = *yaml.NewDecoder(readerToUse)
return nil
}
@ -72,7 +74,12 @@ func (dec *yamlDecoder) Decode() (*CandidateNode, error) {
var dataBucket yaml.Node
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
}
@ -90,3 +97,13 @@ func (dec *yamlDecoder) Decode() (*CandidateNode, error) {
dataBucket.FootComment = ""
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:
```yaml
# header comment
# above_cat
cat: # inline_cat
# above_array
@ -402,7 +403,10 @@ yq -o=xml '.' sample.yml
```
will output
```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><!-- above_val2 -->val2<!-- inline_val2 --></array>
</cat><!-- below_cat -->

View File

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

View File

@ -7,8 +7,16 @@ import (
var loadScenarios = []expressionScenario{
{
skipDoc: true,
description: "Load empty file",
description: "Load empty file with a comment",
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{
"D0, P[], (!!null)::\n",
},

View File

@ -111,7 +111,7 @@ func (p *resultsPrinter) PrintResults(matchingNodes *list.List) error {
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("%v", NodeToString(mappedDoc))
writer, errorWriting := p.printerWriter.GetWriter(mappedDoc)
if errorWriting != nil {
return errorWriting

View File

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

View File

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