From 6bce23d9c22e4fac7a80c684993e92ef37d01464 Mon Sep 17 00:00:00 2001 From: Mike Farah Date: Wed, 25 May 2022 10:54:03 +1000 Subject: [PATCH] Improved handling of trailing document comments --- acceptance_tests/basic.sh | 56 ++++++++++++++++++++ pkg/yqlib/candidate_node.go | 6 ++- pkg/yqlib/doc/operators/comment-operators.md | 2 +- pkg/yqlib/operator_comments.go | 6 ++- pkg/yqlib/operator_comments_test.go | 2 +- pkg/yqlib/operator_multiply_test.go | 13 ++--- pkg/yqlib/printer.go | 4 ++ pkg/yqlib/stream_evaluator.go | 5 ++ pkg/yqlib/utils.go | 5 ++ 9 files changed, 89 insertions(+), 10 deletions(-) diff --git a/acceptance_tests/basic.sh b/acceptance_tests/basic.sh index aeb453d1..597d23be 100755 --- a/acceptance_tests/basic.sh +++ b/acceptance_tests/basic.sh @@ -12,6 +12,62 @@ testBasicEvalRoundTrip() { assertEquals 123 "$X" } +testBasicTrailingContent() { + cat >test-trailing.yml <test-trailing.yml <test-trailing.yml <test-trailing.yml < test.yml X=$(cat test.yml | ./yq '.') diff --git a/pkg/yqlib/candidate_node.go b/pkg/yqlib/candidate_node.go index 26a8c637..4e6d82ec 100644 --- a/pkg/yqlib/candidate_node.go +++ b/pkg/yqlib/candidate_node.go @@ -14,7 +14,8 @@ type CandidateNode struct { Parent *CandidateNode // parent node Key *yaml.Node // node key, if this is a value from a map (or index in an array) - LeadingContent string + LeadingContent string + TrailingContent string Path []interface{} /// the path we took to get to this node Document uint // the document index of this node @@ -170,6 +171,9 @@ func (n *CandidateNode) UpdateAttributesFrom(other *CandidateNode, prefs assignP if other.Node.FootComment != "" { n.Node.FootComment = other.Node.FootComment } + if other.TrailingContent != "" { + n.TrailingContent = other.TrailingContent + } if other.Node.HeadComment != "" { n.Node.HeadComment = other.Node.HeadComment } diff --git a/pkg/yqlib/doc/operators/comment-operators.md b/pkg/yqlib/doc/operators/comment-operators.md index 9e3b61ec..e53c3fc5 100644 --- a/pkg/yqlib/doc/operators/comment-operators.md +++ b/pkg/yqlib/doc/operators/comment-operators.md @@ -74,7 +74,6 @@ yq '. foot_comment=.a' sample.yml will output ```yaml a: cat - # cat ``` @@ -117,6 +116,7 @@ b: Given a sample.yml file of: ```yaml a: cat # meow +# have a great day ``` then ```bash diff --git a/pkg/yqlib/operator_comments.go b/pkg/yqlib/operator_comments.go index ae037103..a67f2178 100644 --- a/pkg/yqlib/operator_comments.go +++ b/pkg/yqlib/operator_comments.go @@ -61,7 +61,9 @@ func assignCommentsOperator(d *dataTreeNavigator, context Context, expressionNod candidate.Node.HeadComment = comment candidate.LeadingContent = "" // clobber the leading content, if there was any. } - if preferences.FootComment { + if preferences.FootComment && candidate.Node.Kind == yaml.DocumentNode && comment != "" { + candidate.TrailingContent = "# " + comment + } else if preferences.FootComment && candidate.Node.Kind != yaml.DocumentNode { candidate.Node.FootComment = comment } @@ -97,6 +99,8 @@ func getCommentsOperator(d *dataTreeNavigator, context Context, expressionNode * comment = chompRegexp.ReplaceAllString(comment, "") } else if preferences.HeadComment { comment = candidate.Node.HeadComment + } else if preferences.FootComment && candidate.Node.Kind == yaml.DocumentNode && candidate.TrailingContent != "" { + comment = candidate.TrailingContent } else if preferences.FootComment { comment = candidate.Node.FootComment } diff --git a/pkg/yqlib/operator_comments_test.go b/pkg/yqlib/operator_comments_test.go index d27b9efd..a3fcd148 100644 --- a/pkg/yqlib/operator_comments_test.go +++ b/pkg/yqlib/operator_comments_test.go @@ -59,7 +59,7 @@ var commentOperatorScenarios = []expressionScenario{ document: `a: cat`, expression: `. foot_comment=.a`, expected: []string{ - "D0, P[], (doc)::a: cat\n\n# cat\n", + "D0, P[], (doc)::a: cat\n# cat\n", }, }, { diff --git a/pkg/yqlib/operator_multiply_test.go b/pkg/yqlib/operator_multiply_test.go index 431a98da..9924150f 100644 --- a/pkg/yqlib/operator_multiply_test.go +++ b/pkg/yqlib/operator_multiply_test.go @@ -144,7 +144,7 @@ var multiplyOperatorScenarios = []expressionScenario{ document2: docNoComments, expression: `select(fi == 0) * select(fi == 1)`, expected: []string{ - "D0, P[], (!!map)::a: apple\nb: banana\n\n# footer\n", + "D0, P[], (!!map)::a: apple\nb: banana\n# footer\n", }, }, { @@ -157,12 +157,13 @@ var multiplyOperatorScenarios = []expressionScenario{ }, }, { - skipDoc: true, - document: docNoComments, - document2: docWithFooter, - expression: `select(fi == 0) * select(fi == 1)`, + description: "doc 2 has footer", + skipDoc: true, + document: docNoComments, + document2: docWithFooter, + expression: `select(fi == 0) * select(fi == 1)`, expected: []string{ - "D0, P[], (!!map)::b: banana\na: apple\n\n# footer\n", + "D0, P[], (!!map)::b: banana\na: apple\n# footer\n", }, }, { diff --git a/pkg/yqlib/printer.go b/pkg/yqlib/printer.go index b844f8b7..78b32c50 100644 --- a/pkg/yqlib/printer.go +++ b/pkg/yqlib/printer.go @@ -134,6 +134,10 @@ func (p *resultsPrinter) PrintResults(matchingNodes *list.List) error { return err } + if err := p.encoder.PrintLeadingContent(writer, mappedDoc.TrailingContent); err != nil { + return err + } + p.previousDocIndex = mappedDoc.Document if err := writer.Flush(); err != nil { return err diff --git a/pkg/yqlib/stream_evaluator.go b/pkg/yqlib/stream_evaluator.go index 36c2a4a4..cda18624 100644 --- a/pkg/yqlib/stream_evaluator.go +++ b/pkg/yqlib/stream_evaluator.go @@ -110,6 +110,11 @@ func (s *streamEvaluator) Evaluate(filename string, reader io.Reader, node *Expr Node: &dataBucket, FileIndex: s.fileIndex, } + //move document comments into candidate node + // otherwise unwrap drops them. + candidateNode.TrailingContent = dataBucket.FootComment + dataBucket.FootComment = "" + if currentIndex == 0 { candidateNode.LeadingContent = leadingContent } diff --git a/pkg/yqlib/utils.go b/pkg/yqlib/utils.go index 47871f05..ecb00ef4 100644 --- a/pkg/yqlib/utils.go +++ b/pkg/yqlib/utils.go @@ -96,6 +96,11 @@ func readDocuments(reader io.Reader, filename string, fileIndex int, decoder Dec EvaluateTogether: true, } + //move document comments into candidate node + // otherwise unwrap drops them. + candidateNode.TrailingContent = dataBucket.FootComment + dataBucket.FootComment = "" + inputList.PushBack(candidateNode) currentIndex = currentIndex + 1