diff --git a/acceptance_tests/load-file.sh b/acceptance_tests/load-file.sh
index 48ebb6c8..4a64295c 100755
--- a/acceptance_tests/load-file.sh
+++ b/acceptance_tests/load-file.sh
@@ -9,7 +9,7 @@ testLoadFileNotExist() {
testLoadFileExpNotExist() {
result=$(./yq e -n 'load(.a)' 2>&1)
assertEquals 1 $?
- assertEquals "Error: Filename expression returned nil" "$result"
+ assertEquals "Error: filename expression returned nil" "$result"
}
testStrLoadFileNotExist() {
@@ -21,7 +21,7 @@ testStrLoadFileNotExist() {
testStrLoadFileExpNotExist() {
result=$(./yq e -n 'strload(.a)' 2>&1)
assertEquals 1 $?
- assertEquals "Error: Filename expression returned nil" "$result"
+ assertEquals "Error: filename expression returned nil" "$result"
}
source ./scripts/shunit2
\ No newline at end of file
diff --git a/examples/data1.yaml b/examples/data1.yaml
index 850ab075..a15395fa 100644
--- a/examples/data1.yaml
+++ b/examples/data1.yaml
@@ -1 +1,2 @@
-["foobar", "foobaz", "blarp"]
\ No newline at end of file
+a: #things
+ meow
\ No newline at end of file
diff --git a/examples/mike.xml b/examples/mike.xml
index b582fff1..df8e8c9a 100644
--- a/examples/mike.xml
+++ b/examples/mike.xml
@@ -1 +1 @@
-3
\ No newline at end of file
+boing
\ No newline at end of file
diff --git a/examples/sample.yaml b/examples/sample.yaml
index 9b925d75..8e7fa374 100644
--- a/examples/sample.yaml
+++ b/examples/sample.yaml
@@ -1,11 +1,2 @@
-# Some doc
-
-a: true
-b:
- c: 2
- d: [3, 4, 5]
- e:
- - name: fred
- value: 3
- - name: sam
- value: 4
\ No newline at end of file
+ # things
+a: apple
\ No newline at end of file
diff --git a/go.mod b/go.mod
index c755e5f0..43f71a24 100644
--- a/go.mod
+++ b/go.mod
@@ -25,9 +25,9 @@ require (
require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
- github.com/mattn/go-isatty v0.0.17 // indirect
+ github.com/mattn/go-isatty v0.0.19 // indirect
golang.org/x/sys v0.13.0 // indirect
- golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect
+ golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
)
go 1.20
diff --git a/go.sum b/go.sum
index fde4c7ca..195442fd 100644
--- a/go.sum
+++ b/go.sum
@@ -15,22 +15,27 @@ github.com/elliotchance/orderedmap v1.5.0 h1:1IsExUsjv5XNBD3ZdC7jkAAqLWOOKdbPTmk
github.com/elliotchance/orderedmap v1.5.0/go.mod h1:wsDwEaX5jEoyhbs7x93zk2H/qv0zwuhg4inXhDkYqys=
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
+github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
+github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
+github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-yaml v1.11.2 h1:joq77SxuyIs9zzxEjgyLBugMQ9NEgTWxXfz2wVqwAaQ=
github.com/goccy/go-yaml v1.11.2/go.mod h1:wKnAMd44+9JAAnGQpWVEgBzGt3YuTaQ4uXoHvE4m7WU=
+github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
+github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
-github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
-github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
+github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A=
@@ -52,15 +57,17 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/yuin/gopher-lua v1.1.0 h1:BojcDhfyDWgU2f2TOzYK/g5p2gxMrku8oupLDqlnSqE=
github.com/yuin/gopher-lua v1.1.0/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
+golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f h1:uF6paiQQebLeSXkrTqHqz0MXhXXS1KgF41eUdBNvxK0=
-golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
+golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
+golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 h1:6D+BvnJ/j6e222UW8s2qTSe3wGBtvo0MbVQG/c5k8RE=
diff --git a/pkg/yqlib/all_at_once_evaluator.go b/pkg/yqlib/all_at_once_evaluator.go
index 4dbed3d1..bdeddd20 100644
--- a/pkg/yqlib/all_at_once_evaluator.go
+++ b/pkg/yqlib/all_at_once_evaluator.go
@@ -2,8 +2,6 @@ package yqlib
import (
"container/list"
-
- yaml "gopkg.in/yaml.v3"
)
// A yaml expression evaluator that runs the expression once against all files/nodes in memory.
@@ -11,7 +9,7 @@ type Evaluator interface {
EvaluateFiles(expression string, filenames []string, printer Printer, decoder Decoder) error
// EvaluateNodes takes an expression and one or more yaml nodes, returning a list of matching candidate nodes
- EvaluateNodes(expression string, nodes ...*yaml.Node) (*list.List, error)
+ EvaluateNodes(expression string, nodes ...*CandidateNode) (*list.List, error)
// EvaluateCandidateNodes takes an expression and list of candidate nodes, returning a list of matching candidate nodes
EvaluateCandidateNodes(expression string, inputCandidateNodes *list.List) (*list.List, error)
@@ -26,10 +24,10 @@ func NewAllAtOnceEvaluator() Evaluator {
return &allAtOnceEvaluator{treeNavigator: NewDataTreeNavigator()}
}
-func (e *allAtOnceEvaluator) EvaluateNodes(expression string, nodes ...*yaml.Node) (*list.List, error) {
+func (e *allAtOnceEvaluator) EvaluateNodes(expression string, nodes ...*CandidateNode) (*list.List, error) {
inputCandidates := list.New()
for _, node := range nodes {
- inputCandidates.PushBack(&CandidateNode{Node: node})
+ inputCandidates.PushBack(node)
}
return e.EvaluateCandidateNodes(expression, inputCandidates)
}
@@ -65,13 +63,7 @@ func (e *allAtOnceEvaluator) EvaluateFiles(expression string, filenames []string
}
if allDocuments.Len() == 0 {
- candidateNode := &CandidateNode{
- Document: 0,
- Filename: "",
- Node: &yaml.Node{Kind: yaml.DocumentNode, Content: []*yaml.Node{{Tag: "!!null", Kind: yaml.ScalarNode}}},
- FileIndex: 0,
- LeadingContent: "",
- }
+ candidateNode := createScalarNode(nil, "")
allDocuments.PushBack(candidateNode)
}
diff --git a/pkg/yqlib/all_at_once_evaluator_test.go b/pkg/yqlib/all_at_once_evaluator_test.go
index 2e9abc43..c3e49c45 100644
--- a/pkg/yqlib/all_at_once_evaluator_test.go
+++ b/pkg/yqlib/all_at_once_evaluator_test.go
@@ -1,6 +1,8 @@
package yqlib
import (
+ "bufio"
+ "strings"
"testing"
"github.com/mikefarah/yq/v4/test"
@@ -18,7 +20,7 @@ var evaluateNodesScenario = []expressionScenario{
document: `a: hello`,
expression: `.`,
expected: []string{
- "D0, P[], (doc)::a: hello\n",
+ "D0, P[], (!!map)::a: hello\n",
},
},
{
@@ -32,9 +34,23 @@ var evaluateNodesScenario = []expressionScenario{
func TestAllAtOnceEvaluateNodes(t *testing.T) {
var evaluator = NewAllAtOnceEvaluator()
+ // logging.SetLevel(logging.DEBUG, "")
for _, tt := range evaluateNodesScenario {
- node := test.ParseData(tt.document)
- list, _ := evaluator.EvaluateNodes(tt.expression, &node)
+ decoder := NewYamlDecoder(NewDefaultYamlPreferences())
+ reader := bufio.NewReader(strings.NewReader(tt.document))
+ err := decoder.Init(reader)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ candidateNode, errorReading := decoder.Decode()
+
+ if errorReading != nil {
+ t.Error(errorReading)
+ return
+ }
+
+ list, _ := evaluator.EvaluateNodes(tt.expression, candidateNode)
test.AssertResultComplex(t, tt.expected, resultsToString(t, list))
}
}
diff --git a/pkg/yqlib/candidate_node.go b/pkg/yqlib/candidate_node.go
index 24a5d43f..fbee0d10 100644
--- a/pkg/yqlib/candidate_node.go
+++ b/pkg/yqlib/candidate_node.go
@@ -3,51 +3,189 @@ package yqlib
import (
"container/list"
"fmt"
+ "strconv"
"strings"
-
- "github.com/jinzhu/copier"
- yaml "gopkg.in/yaml.v3"
)
+type Kind uint32
+
+const (
+ SequenceNode Kind = 1 << iota
+ MappingNode
+ ScalarNode
+ AliasNode
+)
+
+type Style uint32
+
+const (
+ TaggedStyle Style = 1 << iota
+ DoubleQuotedStyle
+ SingleQuotedStyle
+ LiteralStyle
+ FoldedStyle
+ FlowStyle
+)
+
+func createStringScalarNode(stringValue string) *CandidateNode {
+ var node = &CandidateNode{Kind: ScalarNode}
+ node.Value = stringValue
+ node.Tag = "!!str"
+ return node
+}
+
+func createScalarNode(value interface{}, stringValue string) *CandidateNode {
+ var node = &CandidateNode{Kind: ScalarNode}
+ node.Value = stringValue
+
+ switch value.(type) {
+ case float32, float64:
+ node.Tag = "!!float"
+ case int, int64, int32:
+ node.Tag = "!!int"
+ case bool:
+ node.Tag = "!!bool"
+ case string:
+ node.Tag = "!!str"
+ case nil:
+ node.Tag = "!!null"
+ }
+ return node
+}
+
type CandidateNode struct {
- Node *yaml.Node // the actual node
+ Kind Kind
+ Style Style
+
+ Tag string
+ Value string
+ Anchor string
+ Alias *CandidateNode
+ Content []*CandidateNode
+
+ HeadComment string
+ LineComment string
+ FootComment string
+
Parent *CandidateNode // parent node
- Key *yaml.Node // node key, if this is a value from a map (or index in an array)
+ Key *CandidateNode // node key, if this is a value from a map (or index in an array)
- LeadingContent string
- TrailingContent string
+ LeadingContent string
- Path []interface{} /// the path we took to get to this node
- Document uint // the document index of this node
- Filename string
- FileIndex int
+ document uint // the document index of this node
+ filename string
+
+ Line int
+ Column int
+
+ fileIndex int
// when performing op against all nodes given, this will treat all the nodes as one
// (e.g. top level cross document merge). This property does not propagate to child nodes.
EvaluateTogether bool
IsMapKey bool
}
+func (n *CandidateNode) CreateChild() *CandidateNode {
+ return &CandidateNode{
+ Parent: n,
+ }
+}
+
+func (n *CandidateNode) SetDocument(idx uint) {
+ n.document = idx
+}
+
+func (n *CandidateNode) GetDocument() uint {
+ // defer to parent
+ if n.Parent != nil {
+ return n.Parent.GetDocument()
+ }
+ return n.document
+}
+
+func (n *CandidateNode) SetFilename(name string) {
+ n.filename = name
+}
+
+func (n *CandidateNode) GetFilename() string {
+ if n.Parent != nil {
+ return n.Parent.GetFilename()
+ }
+ return n.filename
+}
+
+func (n *CandidateNode) SetFileIndex(idx int) {
+ n.fileIndex = idx
+}
+
+func (n *CandidateNode) GetFileIndex() int {
+ if n.Parent != nil {
+ return n.Parent.GetFileIndex()
+ }
+ return n.fileIndex
+}
+
func (n *CandidateNode) GetKey() string {
keyPrefix := ""
if n.IsMapKey {
- keyPrefix = "key-"
+ keyPrefix = fmt.Sprintf("key-%v-", n.Value)
}
- return fmt.Sprintf("%v%v - %v", keyPrefix, n.Document, n.Path)
+ key := ""
+ if n.Key != nil {
+ key = n.Key.Value
+ }
+ return fmt.Sprintf("%v%v - %v", keyPrefix, n.GetDocument(), key)
}
-func (n *CandidateNode) GetNiceTag() string {
- return unwrapDoc(n.Node).Tag
+func (n *CandidateNode) getParsedKey() interface{} {
+ if n.IsMapKey {
+ return n.Value
+ }
+ if n.Key == nil {
+ return nil
+ }
+ if n.Key.Tag == "!!str" {
+ return n.Key.Value
+ }
+ index, err := parseInt(n.Key.Value)
+ if err != nil {
+ return n.Key.Value
+ }
+ return index
+
+}
+
+func (n *CandidateNode) GetPath() []interface{} {
+ key := n.getParsedKey()
+ if n.Parent != nil && key != nil {
+ return append(n.Parent.GetPath(), key)
+ }
+
+ if key != nil {
+ return []interface{}{key}
+ }
+ return make([]interface{}, 0)
}
func (n *CandidateNode) GetNicePath() string {
- if n.Path != nil && len(n.Path) >= 0 {
- pathStr := make([]string, len(n.Path))
- for i, v := range n.Path {
- pathStr[i] = fmt.Sprintf("%v", v)
+ var sb strings.Builder
+ path := n.GetPath()
+ for i, element := range path {
+ elementStr := fmt.Sprintf("%v", element)
+ switch element.(type) {
+ case int:
+ sb.WriteString("[" + elementStr + "]")
+ default:
+ if i == 0 {
+ sb.WriteString(elementStr)
+ } else if strings.ContainsRune(elementStr, '.') {
+ sb.WriteString("[" + elementStr + "]")
+ } else {
+ sb.WriteString("." + elementStr)
+ }
}
- return strings.Join(pathStr, ".")
}
- return ""
+ return sb.String()
}
func (n *CandidateNode) AsList() *list.List {
@@ -56,134 +194,233 @@ func (n *CandidateNode) AsList() *list.List {
return elMap
}
-func (n *CandidateNode) CreateChildInMap(key *yaml.Node, node *yaml.Node) *CandidateNode {
- var value interface{}
- if key != nil {
- value = key.Value
+func (n *CandidateNode) SetParent(parent *CandidateNode) {
+ n.Parent = parent
+}
+
+func (n *CandidateNode) AddKeyValueChild(rawKey *CandidateNode, rawValue *CandidateNode) (*CandidateNode, *CandidateNode) {
+ key := rawKey.Copy()
+ key.SetParent(n)
+ key.IsMapKey = true
+
+ value := rawValue.Copy()
+ value.SetParent(n)
+ value.Key = key
+
+ n.Content = append(n.Content, key, value)
+ return key, value
+}
+
+func (n *CandidateNode) AddChild(rawChild *CandidateNode) {
+ value := rawChild.Copy()
+ value.SetParent(n)
+ if value.Key != nil {
+ value.Key.SetParent(n)
+ } else {
+ index := len(n.Content)
+ keyNode := createScalarNode(index, fmt.Sprintf("%v", index))
+ keyNode.SetParent(n)
+ value.Key = keyNode
}
- return &CandidateNode{
- Node: node,
- Path: n.createChildPath(value),
- Parent: n,
- Key: key,
- Document: n.Document,
- Filename: n.Filename,
- FileIndex: n.FileIndex,
+ n.Content = append(n.Content, value)
+}
+
+func (n *CandidateNode) AddChildren(children []*CandidateNode) {
+ if n.Kind == MappingNode {
+ for i := 0; i < len(children); i += 2 {
+ key := children[i]
+ value := children[i+1]
+ n.AddKeyValueChild(key, value)
+ }
+
+ } else {
+ for _, rawChild := range children {
+ n.AddChild(rawChild)
+ }
}
}
-func (n *CandidateNode) CreateChildInArray(index int, node *yaml.Node) *CandidateNode {
- return &CandidateNode{
- Node: node,
- Path: n.createChildPath(index),
- Parent: n,
- Key: &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", index), Tag: "!!int"},
- Document: n.Document,
- Filename: n.Filename,
- FileIndex: n.FileIndex,
+func (n *CandidateNode) GetValueRep() (interface{}, error) {
+ log.Debugf("GetValueRep for %v value: %v", n.GetNicePath(), n.Value)
+ realTag := n.guessTagFromCustomType()
+
+ switch realTag {
+ case "!!int":
+ _, val, err := parseInt64(n.Value)
+ return val, err
+ case "!!float":
+ // need to test this
+ return strconv.ParseFloat(n.Value, 64)
+ case "!!bool":
+ return isTruthyNode(n), nil
+ case "!!null":
+ return nil, nil
}
+
+ return n.Value, nil
}
-func (n *CandidateNode) CreateReplacement(node *yaml.Node) *CandidateNode {
- return &CandidateNode{
- Node: node,
- Path: n.createChildPath(nil),
- Parent: n.Parent,
- Key: n.Key,
- IsMapKey: n.IsMapKey,
- Document: n.Document,
- Filename: n.Filename,
- FileIndex: n.FileIndex,
+func (n *CandidateNode) guessTagFromCustomType() string {
+ if strings.HasPrefix(n.Tag, "!!") {
+ return n.Tag
+ } else if n.Value == "" {
+ log.Debug("guessTagFromCustomType: node has no value to guess the type with")
+ return n.Tag
}
+ dataBucket, errorReading := parseSnippet(n.Value)
+
+ if errorReading != nil {
+ log.Debug("guessTagFromCustomType: could not guess underlying tag type %v", errorReading)
+ return n.Tag
+ }
+ guessedTag := dataBucket.Tag
+ log.Info("im guessing the tag %v is a %v", n.Tag, guessedTag)
+ return guessedTag
}
-func (n *CandidateNode) CreateReplacementWithDocWrappers(node *yaml.Node) *CandidateNode {
- replacement := n.CreateReplacement(node)
+func (n *CandidateNode) CreateReplacement(kind Kind, tag string, value string) *CandidateNode {
+ node := &CandidateNode{
+ Kind: kind,
+ Tag: tag,
+ Value: value,
+ }
+ return n.CopyAsReplacement(node)
+}
+
+func (n *CandidateNode) CopyAsReplacement(replacement *CandidateNode) *CandidateNode {
+ newCopy := replacement.Copy()
+ newCopy.Parent = n.Parent
+
+ if n.IsMapKey {
+ newCopy.Key = n
+ } else {
+ newCopy.Key = n.Key
+ }
+
+ return newCopy
+}
+
+func (n *CandidateNode) CreateReplacementWithComments(kind Kind, tag string, style Style) *CandidateNode {
+ replacement := n.CreateReplacement(kind, tag, "")
replacement.LeadingContent = n.LeadingContent
- replacement.TrailingContent = n.TrailingContent
+ replacement.HeadComment = n.HeadComment
+ replacement.LineComment = n.LineComment
+ replacement.FootComment = n.FootComment
+ replacement.Style = style
return replacement
}
-func (n *CandidateNode) createChildPath(path interface{}) []interface{} {
- if path == nil {
- newPath := make([]interface{}, len(n.Path))
- copy(newPath, n.Path)
- return newPath
- }
-
- //don't use append as they may actually modify the path of the original node!
- newPath := make([]interface{}, len(n.Path)+1)
- copy(newPath, n.Path)
- newPath[len(n.Path)] = path
- return newPath
+func (n *CandidateNode) Copy() *CandidateNode {
+ return n.doCopy(true)
}
-func (n *CandidateNode) Copy() (*CandidateNode, error) {
- clone := &CandidateNode{}
- err := copier.Copy(clone, n)
- if err != nil {
- return nil, err
+func (n *CandidateNode) CopyWithoutContent() *CandidateNode {
+ return n.doCopy(false)
+}
+
+func (n *CandidateNode) doCopy(cloneContent bool) *CandidateNode {
+ var content []*CandidateNode
+
+ var copyKey *CandidateNode
+ if n.Key != nil {
+ copyKey = n.Key.Copy()
}
- clone.Node = deepClone(n.Node)
- return clone, nil
+
+ clone := &CandidateNode{
+ Kind: n.Kind,
+ Style: n.Style,
+
+ Tag: n.Tag,
+ Value: n.Value,
+ Anchor: n.Anchor,
+
+ // ok not to clone this,
+ // as its a reference to somewhere else.
+ Alias: n.Alias,
+ Content: content,
+
+ HeadComment: n.HeadComment,
+ LineComment: n.LineComment,
+ FootComment: n.FootComment,
+
+ Parent: n.Parent,
+ Key: copyKey,
+
+ LeadingContent: n.LeadingContent,
+
+ document: n.document,
+ filename: n.filename,
+ fileIndex: n.fileIndex,
+
+ Line: n.Line,
+ Column: n.Column,
+
+ EvaluateTogether: n.EvaluateTogether,
+ IsMapKey: n.IsMapKey,
+ }
+
+ if cloneContent {
+ clone.AddChildren(n.Content)
+ }
+
+ return clone
}
// updates this candidate from the given candidate node
func (n *CandidateNode) UpdateFrom(other *CandidateNode, prefs assignPreferences) {
// if this is an empty map or empty array, use the style of other node.
- if (n.Node.Kind != yaml.ScalarNode && len(n.Node.Content) == 0) ||
+ if (n.Kind != ScalarNode && len(n.Content) == 0) ||
// if the tag has changed (e.g. from str to bool)
- (guessTagFromCustomType(n.Node) != guessTagFromCustomType(other.Node)) {
- n.Node.Style = other.Node.Style
+ (n.guessTagFromCustomType() != other.guessTagFromCustomType()) {
+ n.Style = other.Style
}
- n.Node.Content = deepCloneContent(other.Node.Content)
- n.Node.Kind = other.Node.Kind
- n.Node.Value = other.Node.Value
+ n.Content = make([]*CandidateNode, 0)
+ n.Kind = other.Kind
+ n.AddChildren(other.Content)
+
+ n.Value = other.Value
n.UpdateAttributesFrom(other, prefs)
}
func (n *CandidateNode) UpdateAttributesFrom(other *CandidateNode, prefs assignPreferences) {
- log.Debug("UpdateAttributesFrom: n: %v other: %v", n.GetKey(), other.GetKey())
- if n.Node.Kind != other.Node.Kind {
+ log.Debug("UpdateAttributesFrom: n: %v other: %v", NodeToString(n), NodeToString(other))
+ if n.Kind != other.Kind {
// clear out the contents when switching to a different type
// e.g. map to array
- n.Node.Content = make([]*yaml.Node, 0)
- n.Node.Value = ""
+ n.Content = make([]*CandidateNode, 0)
+ n.Value = ""
}
- n.Node.Kind = other.Node.Kind
+ n.Kind = other.Kind
// don't clobber custom tags...
- if prefs.ClobberCustomTags || strings.HasPrefix(n.Node.Tag, "!!") || n.Node.Tag == "" {
- n.Node.Tag = other.Node.Tag
+ if prefs.ClobberCustomTags || strings.HasPrefix(n.Tag, "!!") || n.Tag == "" {
+ n.Tag = other.Tag
}
- n.Node.Alias = other.Node.Alias
+ n.Alias = other.Alias
if !prefs.DontOverWriteAnchor {
- n.Node.Anchor = other.Node.Anchor
+ n.Anchor = other.Anchor
}
// merge will pickup the style of the new thing
// when autocreating nodes
- if n.Node.Style == 0 {
- n.Node.Style = other.Node.Style
+ if n.Style == 0 {
+ n.Style = other.Style
}
- if other.Node.FootComment != "" {
- n.Node.FootComment = other.Node.FootComment
+ if other.FootComment != "" {
+ n.FootComment = other.FootComment
}
- if other.TrailingContent != "" {
- n.TrailingContent = other.TrailingContent
+ if other.HeadComment != "" {
+ n.HeadComment = other.HeadComment
}
- if other.Node.HeadComment != "" {
- n.Node.HeadComment = other.Node.HeadComment
- }
- if other.Node.LineComment != "" {
- n.Node.LineComment = other.Node.LineComment
+ if other.LineComment != "" {
+ n.LineComment = other.LineComment
}
}
diff --git a/pkg/yqlib/candidate_node_goccy_yaml.go b/pkg/yqlib/candidate_node_goccy_yaml.go
new file mode 100644
index 00000000..7974c723
--- /dev/null
+++ b/pkg/yqlib/candidate_node_goccy_yaml.go
@@ -0,0 +1,180 @@
+package yqlib
+
+import (
+ "fmt"
+ "strings"
+
+ yaml "github.com/goccy/go-yaml"
+ "github.com/goccy/go-yaml/ast"
+ goccyToken "github.com/goccy/go-yaml/token"
+)
+
+func (o *CandidateNode) goccyDecodeIntoChild(childNode ast.Node, cm yaml.CommentMap) (*CandidateNode, error) {
+ newChild := o.CreateChild()
+
+ err := newChild.UnmarshalGoccyYAML(childNode, cm)
+ return newChild, err
+}
+
+func (o *CandidateNode) UnmarshalGoccyYAML(node ast.Node, cm yaml.CommentMap) error {
+ log.Debugf("UnmarshalYAML %v", node)
+ log.Debugf("UnmarshalYAML %v", node.Type().String())
+ log.Debugf("UnmarshalYAML Node Value: %v", node.String())
+ log.Debugf("UnmarshalYAML Node GetComment: %v", node.GetComment())
+
+ if node.GetComment() != nil {
+ commentMapComments := cm[node.GetPath()]
+ for _, comment := range node.GetComment().Comments {
+ // need to use the comment map to find the position :/
+ log.Debugf("%v has a comment of [%v]", node.GetPath(), comment.Token.Value)
+ for _, commentMapComment := range commentMapComments {
+ commentMapValue := strings.Join(commentMapComment.Texts, "\n")
+ if commentMapValue == comment.Token.Value {
+ log.Debug("found a matching entry in comment map")
+ // we found the comment in the comment map,
+ // now we can process the position
+ switch commentMapComment.Position {
+ case yaml.CommentHeadPosition:
+ o.HeadComment = comment.String()
+ log.Debug("its a head comment %v", comment.String())
+ case yaml.CommentLinePosition:
+ o.LineComment = comment.String()
+ log.Debug("its a line comment %v", comment.String())
+ case yaml.CommentFootPosition:
+ o.FootComment = comment.String()
+ log.Debug("its a foot comment %v", comment.String())
+ }
+ }
+ }
+
+ }
+ }
+
+ o.Value = node.String()
+ switch node.Type() {
+ case ast.IntegerType:
+ o.Kind = ScalarNode
+ o.Tag = "!!int"
+ case ast.FloatType:
+ o.Kind = ScalarNode
+ o.Tag = "!!float"
+ case ast.BoolType:
+ o.Kind = ScalarNode
+ o.Tag = "!!bool"
+ case ast.NullType:
+ o.Kind = ScalarNode
+ o.Tag = "!!null"
+ o.Value = node.GetToken().Value
+ case ast.StringType:
+ o.Kind = ScalarNode
+ o.Tag = "!!str"
+ switch node.GetToken().Type {
+ case goccyToken.SingleQuoteType:
+ o.Style = SingleQuotedStyle
+ case goccyToken.DoubleQuoteType:
+ o.Style = DoubleQuotedStyle
+ }
+ o.Value = node.(*ast.StringNode).Value
+ log.Debugf("string value %v", node.(*ast.StringNode).Value)
+ case ast.LiteralType:
+ o.Kind = ScalarNode
+ o.Tag = "!!str"
+ o.Style = LiteralStyle
+ astLiteral := node.(*ast.LiteralNode)
+ log.Debugf("astLiteral.Start.Type %v", astLiteral.Start.Type)
+ if astLiteral.Start.Type == goccyToken.FoldedType {
+ log.Debugf("folded Type %v", astLiteral.Start.Type)
+ o.Style = FoldedStyle
+ }
+ log.Debug("start value: %v ", node.(*ast.LiteralNode).Start.Value)
+ log.Debug("start value: %v ", node.(*ast.LiteralNode).Start.Type)
+ // TODO: here I could put the original value with line breaks
+ // to solve the multiline > problem
+ o.Value = astLiteral.Value.Value
+ case ast.TagType:
+ if err := o.UnmarshalGoccyYAML(node.(*ast.TagNode).Value, cm); err != nil {
+ return err
+ }
+ o.Tag = node.(*ast.TagNode).Start.Value
+ case ast.MappingType:
+ log.Debugf("UnmarshalYAML - a mapping node")
+ o.Kind = MappingNode
+ o.Tag = "!!map"
+
+ mappingNode := node.(*ast.MappingNode)
+ if mappingNode.IsFlowStyle {
+ o.Style = FlowStyle
+ }
+ for _, mappingValueNode := range mappingNode.Values {
+ err := o.goccyProcessMappingValueNode(mappingValueNode, cm)
+ if err != nil {
+ return ast.ErrInvalidAnchorName
+ }
+ }
+ if mappingNode.FootComment != nil {
+ log.Debugf("mapping node has a foot comment of: %v", mappingNode.FootComment)
+ o.FootComment = mappingNode.FootComment.String()
+ }
+ case ast.MappingValueType:
+ log.Debugf("UnmarshalYAML - a mapping node")
+ o.Kind = MappingNode
+ o.Tag = "!!map"
+ mappingValueNode := node.(*ast.MappingValueNode)
+ err := o.goccyProcessMappingValueNode(mappingValueNode, cm)
+ if err != nil {
+ return ast.ErrInvalidAnchorName
+ }
+ case ast.SequenceType:
+ log.Debugf("UnmarshalYAML - a sequence node")
+ o.Kind = SequenceNode
+ o.Tag = "!!seq"
+ sequenceNode := node.(*ast.SequenceNode)
+ if sequenceNode.IsFlowStyle {
+ o.Style = FlowStyle
+ }
+ astSeq := sequenceNode.Values
+ o.Content = make([]*CandidateNode, len(astSeq))
+ for i := 0; i < len(astSeq); i++ {
+ keyNode := o.CreateChild()
+ keyNode.IsMapKey = true
+ keyNode.Tag = "!!int"
+ keyNode.Kind = ScalarNode
+ keyNode.Value = fmt.Sprintf("%v", i)
+
+ valueNode, err := o.goccyDecodeIntoChild(astSeq[i], cm)
+ if err != nil {
+ return err
+ }
+
+ valueNode.Key = keyNode
+ o.Content[i] = valueNode
+ }
+
+ default:
+ log.Debugf("UnmarshalYAML - node idea of the type!!")
+ }
+ log.Debugf("KIND: %v", o.Kind)
+ return nil
+}
+
+func (o *CandidateNode) goccyProcessMappingValueNode(mappingEntry *ast.MappingValueNode, cm yaml.CommentMap) error {
+ log.Debug("UnmarshalYAML MAP KEY entry %v", mappingEntry.Key)
+ keyNode, err := o.goccyDecodeIntoChild(mappingEntry.Key, cm)
+ if err != nil {
+ return err
+ }
+ keyNode.IsMapKey = true
+
+ log.Debug("UnmarshalYAML MAP VALUE entry %v", mappingEntry.Value)
+ valueNode, err := o.goccyDecodeIntoChild(mappingEntry.Value, cm)
+ if err != nil {
+ return err
+ }
+
+ if mappingEntry.FootComment != nil {
+ valueNode.FootComment = mappingEntry.FootComment.String()
+ }
+ o.AddKeyValueChild(keyNode, valueNode)
+
+ return nil
+}
diff --git a/pkg/yqlib/candidate_node_test.go b/pkg/yqlib/candidate_node_test.go
new file mode 100644
index 00000000..1ca707ba
--- /dev/null
+++ b/pkg/yqlib/candidate_node_test.go
@@ -0,0 +1,149 @@
+package yqlib
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/mikefarah/yq/v4/test"
+)
+
+type valueRepScenario struct {
+ input string
+ tag string
+ expected interface{}
+}
+
+var valueRepScenarios = []valueRepScenario{
+ {
+ input: `"cat"`,
+ expected: `"cat"`,
+ },
+ {
+ input: `3`,
+ expected: int64(3),
+ },
+ {
+ input: `3.1`,
+ expected: float64(3.1),
+ },
+ {
+ input: `true`,
+ expected: true,
+ },
+ {
+ input: `y`,
+ tag: "!!bool",
+ expected: true,
+ },
+ {
+ tag: "!!null",
+ expected: nil,
+ },
+}
+
+func TestCandidateNodeGetValueRepScenarios(t *testing.T) {
+ for _, tt := range valueRepScenarios {
+ node := CandidateNode{Value: tt.input, Tag: tt.tag}
+ actual, err := node.GetValueRep()
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ test.AssertResult(t, tt.expected, actual)
+ }
+}
+
+func TestCandidateNodeChildWhenParentUpdated(t *testing.T) {
+ parent := CandidateNode{}
+ child := parent.CreateChild()
+ parent.SetDocument(1)
+ parent.SetFileIndex(2)
+ parent.SetFilename("meow")
+ test.AssertResultWithContext(t, "meow", child.GetFilename(), "filename")
+ test.AssertResultWithContext(t, 2, child.GetFileIndex(), "file index")
+ test.AssertResultWithContext(t, uint(1), child.GetDocument(), "document index")
+}
+
+type createScalarNodeScenario struct {
+ value interface{}
+ stringValue string
+ expectedTag string
+}
+
+var createScalarScenarios = []createScalarNodeScenario{
+ {
+ value: "mike",
+ stringValue: "mike",
+ expectedTag: "!!str",
+ },
+ {
+ value: 3,
+ stringValue: "3",
+ expectedTag: "!!int",
+ },
+ {
+ value: 3.1,
+ stringValue: "3.1",
+ expectedTag: "!!float",
+ },
+ {
+ value: true,
+ stringValue: "true",
+ expectedTag: "!!bool",
+ },
+ {
+ value: nil,
+ stringValue: "~",
+ expectedTag: "!!null",
+ },
+}
+
+func TestCreateScalarNodeScenarios(t *testing.T) {
+ for _, tt := range createScalarScenarios {
+ actual := createScalarNode(tt.value, tt.stringValue)
+ test.AssertResultWithContext(t, tt.stringValue, actual.Value, fmt.Sprintf("Value for: Value: [%v], String: %v", tt.value, tt.stringValue))
+ test.AssertResultWithContext(t, tt.expectedTag, actual.Tag, fmt.Sprintf("Value for: Value: [%v], String: %v", tt.value, tt.stringValue))
+ }
+}
+
+func TestGetKeyForMapValue(t *testing.T) {
+ key := createStringScalarNode("yourKey")
+ n := CandidateNode{Key: key, Value: "meow", document: 3}
+ test.AssertResult(t, "3 - yourKey", n.GetKey())
+}
+
+func TestGetKeyForMapKey(t *testing.T) {
+ key := createStringScalarNode("yourKey")
+ key.IsMapKey = true
+ key.document = 3
+ test.AssertResult(t, "key-yourKey-3 - ", key.GetKey())
+}
+
+func TestGetKeyForValue(t *testing.T) {
+ n := CandidateNode{Value: "meow", document: 3}
+ test.AssertResult(t, "3 - ", n.GetKey())
+}
+
+func TestGetParsedKeyForMapKey(t *testing.T) {
+ key := createStringScalarNode("yourKey")
+ key.IsMapKey = true
+ key.document = 3
+ test.AssertResult(t, "yourKey", key.getParsedKey())
+}
+
+func TestGetParsedKeyForLooseValue(t *testing.T) {
+ n := CandidateNode{Value: "meow", document: 3}
+ test.AssertResult(t, nil, n.getParsedKey())
+}
+
+func TestGetParsedKeyForMapValue(t *testing.T) {
+ key := createStringScalarNode("yourKey")
+ n := CandidateNode{Key: key, Value: "meow", document: 3}
+ test.AssertResult(t, "yourKey", n.getParsedKey())
+}
+
+func TestGetParsedKeyForArrayValue(t *testing.T) {
+ key := createScalarNode(4, "4")
+ n := CandidateNode{Key: key, Value: "meow", document: 3}
+ test.AssertResult(t, 4, n.getParsedKey())
+}
diff --git a/pkg/yqlib/candidate_node_yaml.go b/pkg/yqlib/candidate_node_yaml.go
new file mode 100644
index 00000000..67f57a48
--- /dev/null
+++ b/pkg/yqlib/candidate_node_yaml.go
@@ -0,0 +1,218 @@
+package yqlib
+
+import (
+ "fmt"
+
+ yaml "gopkg.in/yaml.v3"
+)
+
+func MapYamlStyle(original yaml.Style) Style {
+ switch original {
+ case yaml.TaggedStyle:
+ return TaggedStyle
+ case yaml.DoubleQuotedStyle:
+ return DoubleQuotedStyle
+ case yaml.SingleQuotedStyle:
+ return SingleQuotedStyle
+ case yaml.LiteralStyle:
+ return LiteralStyle
+ case yaml.FoldedStyle:
+ return FoldedStyle
+ case yaml.FlowStyle:
+ return FlowStyle
+ case 0:
+ return 0
+ }
+ return Style(original)
+}
+
+func MapToYamlStyle(original Style) yaml.Style {
+ switch original {
+ case TaggedStyle:
+ return yaml.TaggedStyle
+ case DoubleQuotedStyle:
+ return yaml.DoubleQuotedStyle
+ case SingleQuotedStyle:
+ return yaml.SingleQuotedStyle
+ case LiteralStyle:
+ return yaml.LiteralStyle
+ case FoldedStyle:
+ return yaml.FoldedStyle
+ case FlowStyle:
+ return yaml.FlowStyle
+ case 0:
+ return 0
+ }
+ return yaml.Style(original)
+}
+
+func (o *CandidateNode) copyFromYamlNode(node *yaml.Node, anchorMap map[string]*CandidateNode) {
+ o.Style = MapYamlStyle(node.Style)
+
+ o.Tag = node.Tag
+ o.Value = node.Value
+ o.Anchor = node.Anchor
+
+ if o.Anchor != "" {
+ anchorMap[o.Anchor] = o
+ log.Debug("set anchor %v to %v", o.Anchor, NodeToString(o))
+ }
+
+ // its a single alias
+ if node.Alias != nil && node.Alias.Anchor != "" {
+ o.Alias = anchorMap[node.Alias.Anchor]
+ log.Debug("set alias to %v", NodeToString(anchorMap[node.Alias.Anchor]))
+ }
+ o.HeadComment = node.HeadComment
+ o.LineComment = node.LineComment
+ o.FootComment = node.FootComment
+
+ o.Line = node.Line
+ o.Column = node.Column
+}
+
+func (o *CandidateNode) copyToYamlNode(node *yaml.Node) {
+ node.Style = MapToYamlStyle(o.Style)
+
+ node.Tag = o.Tag
+ node.Value = o.Value
+ node.Anchor = o.Anchor
+
+ // node.Alias = TODO - find Alias in our own structure
+ // might need to be a post process thing
+
+ node.HeadComment = o.HeadComment
+
+ node.LineComment = o.LineComment
+ node.FootComment = o.FootComment
+
+ node.Line = o.Line
+ node.Column = o.Column
+}
+
+func (o *CandidateNode) decodeIntoChild(childNode *yaml.Node, anchorMap map[string]*CandidateNode) (*CandidateNode, error) {
+ newChild := o.CreateChild()
+
+ // null yaml.Nodes to not end up calling UnmarshalYAML
+ // so we call it explicitly
+ if childNode.Tag == "!!null" {
+ newChild.Kind = ScalarNode
+ newChild.copyFromYamlNode(childNode, anchorMap)
+ return newChild, nil
+ }
+
+ err := newChild.UnmarshalYAML(childNode, anchorMap)
+ return newChild, err
+}
+
+func (o *CandidateNode) UnmarshalYAML(node *yaml.Node, anchorMap map[string]*CandidateNode) error {
+ log.Debugf("UnmarshalYAML %v", node.Tag)
+ switch node.Kind {
+ case yaml.AliasNode:
+ log.Debug("UnmarshalYAML - alias from yaml: %v", o.Tag)
+ o.Kind = AliasNode
+ o.copyFromYamlNode(node, anchorMap)
+ return nil
+ case yaml.ScalarNode:
+ log.Debugf("UnmarshalYAML - a scalar")
+ o.Kind = ScalarNode
+ o.copyFromYamlNode(node, anchorMap)
+ return nil
+ case yaml.MappingNode:
+ log.Debugf("UnmarshalYAML - a mapping node")
+ o.Kind = MappingNode
+ o.copyFromYamlNode(node, anchorMap)
+ o.Content = make([]*CandidateNode, len(node.Content))
+ for i := 0; i < len(node.Content); i += 2 {
+
+ keyNode, err := o.decodeIntoChild(node.Content[i], anchorMap)
+ if err != nil {
+ return err
+ }
+
+ keyNode.IsMapKey = true
+
+ valueNode, err := o.decodeIntoChild(node.Content[i+1], anchorMap)
+ if err != nil {
+ return err
+ }
+
+ valueNode.Key = keyNode
+
+ o.Content[i] = keyNode
+ o.Content[i+1] = valueNode
+ }
+ log.Debugf("UnmarshalYAML - finished mapping node")
+ return nil
+ case yaml.SequenceNode:
+ log.Debugf("UnmarshalYAML - a sequence: %v", len(node.Content))
+ o.Kind = SequenceNode
+
+ o.copyFromYamlNode(node, anchorMap)
+ log.Debugf("node Style: %v", node.Style)
+ log.Debugf("o Style: %v", o.Style)
+ o.Content = make([]*CandidateNode, len(node.Content))
+ for i := 0; i < len(node.Content); i++ {
+ keyNode := o.CreateChild()
+ keyNode.IsMapKey = true
+ keyNode.Tag = "!!int"
+ keyNode.Kind = ScalarNode
+ keyNode.Value = fmt.Sprintf("%v", i)
+
+ valueNode, err := o.decodeIntoChild(node.Content[i], anchorMap)
+ if err != nil {
+ return err
+ }
+
+ valueNode.Key = keyNode
+ o.Content[i] = valueNode
+ }
+ return nil
+ case 0:
+ // not sure when this happens
+ o.copyFromYamlNode(node, anchorMap)
+ log.Debugf("UnmarshalYAML - err.. %v", NodeToString(o))
+ return nil
+ default:
+ return fmt.Errorf("orderedMap: invalid yaml node")
+ }
+}
+
+func (o *CandidateNode) MarshalYAML() (*yaml.Node, error) {
+ log.Debug("MarshalYAML to yaml: %v", o.Tag)
+ switch o.Kind {
+ case AliasNode:
+ log.Debug("MarshalYAML - alias to yaml: %v", o.Tag)
+ target := &yaml.Node{Kind: yaml.AliasNode}
+ o.copyToYamlNode(target)
+ return target, nil
+ case ScalarNode:
+ log.Debug("MarshalYAML - scalar: %v", o.Value)
+ target := &yaml.Node{Kind: yaml.ScalarNode}
+ o.copyToYamlNode(target)
+ return target, nil
+ case MappingNode, SequenceNode:
+ targetKind := yaml.MappingNode
+ if o.Kind == SequenceNode {
+ targetKind = yaml.SequenceNode
+ }
+ target := &yaml.Node{Kind: targetKind}
+ o.copyToYamlNode(target)
+ log.Debugf("original style: %v", o.Style)
+ log.Debugf("original: %v, tag: %v, style: %v, kind: %v", NodeToString(o), target.Tag, target.Style, target.Kind == yaml.SequenceNode)
+ target.Content = make([]*yaml.Node, len(o.Content))
+ for i := 0; i < len(o.Content); i++ {
+
+ child, err := o.Content[i].MarshalYAML()
+
+ if err != nil {
+ return nil, err
+ }
+ target.Content[i] = child
+ }
+ return target, nil
+ }
+ target := &yaml.Node{}
+ o.copyToYamlNode(target)
+ return target, nil
+}
diff --git a/pkg/yqlib/candidiate_node_json.go b/pkg/yqlib/candidiate_node_json.go
new file mode 100644
index 00000000..728e5afb
--- /dev/null
+++ b/pkg/yqlib/candidiate_node_json.go
@@ -0,0 +1,172 @@
+package yqlib
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+
+ "github.com/goccy/go-json"
+)
+
+func (o *CandidateNode) setScalarFromJson(value interface{}) error {
+ o.Kind = ScalarNode
+ switch rawData := value.(type) {
+ case nil:
+ o.Tag = "!!null"
+ o.Value = "null"
+ case float64, float32:
+ o.Value = fmt.Sprintf("%v", value)
+ o.Tag = "!!float"
+ // json decoder returns ints as float.
+ if value == float64(int64(rawData.(float64))) {
+ // aha it's an int disguised as a float
+ o.Tag = "!!int"
+ o.Value = fmt.Sprintf("%v", int64(value.(float64)))
+ }
+ case int, int64, int32:
+ o.Value = fmt.Sprintf("%v", value)
+ o.Tag = "!!int"
+ case bool:
+ o.Value = fmt.Sprintf("%v", value)
+ o.Tag = "!!bool"
+ case string:
+ o.Value = rawData
+ o.Tag = "!!str"
+ default:
+ return fmt.Errorf("unrecognised type :( %v", rawData)
+ }
+ return nil
+}
+
+func (o *CandidateNode) UnmarshalJSON(data []byte) error {
+ log.Debug("UnmarshalJSON")
+ switch data[0] {
+ case '{':
+ log.Debug("UnmarshalJSON - its a map!")
+ // its a map
+ o.Kind = MappingNode
+ o.Tag = "!!map"
+
+ dec := json.NewDecoder(bytes.NewReader(data))
+ _, err := dec.Token() // open object
+ if err != nil {
+ return err
+ }
+
+ // cycle through k/v
+ var tok json.Token
+ for tok, err = dec.Token(); err == nil; tok, err = dec.Token() {
+ // we can expect two types: string or Delim. Delim automatically means
+ // that it is the closing bracket of the object, whereas string means
+ // that there is another key.
+ if _, ok := tok.(json.Delim); ok {
+ break
+ }
+
+ childKey := o.CreateChild()
+ childKey.IsMapKey = true
+ childKey.Value = tok.(string)
+ childKey.Kind = ScalarNode
+ childKey.Tag = "!!str"
+
+ childValue := o.CreateChild()
+ childValue.Key = childKey
+
+ if err := dec.Decode(childValue); err != nil {
+ return err
+ }
+ o.Content = append(o.Content, childKey, childValue)
+ }
+ // unexpected error
+ if err != nil && !errors.Is(err, io.EOF) {
+ return err
+ }
+ return nil
+ case '[':
+ o.Kind = SequenceNode
+ o.Tag = "!!seq"
+ log.Debug("UnmarshalJSON - its an array!")
+ var children []*CandidateNode
+ if err := json.Unmarshal(data, &children); err != nil {
+ return err
+ }
+ // now we put the children into the content, and set a key value for them
+ for i, child := range children {
+
+ if child == nil {
+ // need to represent it as a null scalar
+ child = createScalarNode(nil, "null")
+ }
+ childKey := o.CreateChild()
+ childKey.Kind = ScalarNode
+ childKey.Tag = "!!int"
+ childKey.Value = fmt.Sprintf("%v", i)
+ childKey.IsMapKey = true
+
+ child.Parent = o
+ child.Key = childKey
+ o.Content = append(o.Content, child)
+ }
+ return nil
+ }
+ log.Debug("UnmarshalJSON - its a scalar!")
+ // otherwise, must be a scalar
+ var scalar interface{}
+ err := json.Unmarshal(data, &scalar)
+
+ if err != nil {
+ return err
+ }
+ log.Debug("UnmarshalJSON - scalar is %v", scalar)
+
+ return o.setScalarFromJson(scalar)
+
+}
+
+func (o *CandidateNode) MarshalJSON() ([]byte, error) {
+ log.Debugf("MarshalJSON %v", NodeToString(o))
+ buf := new(bytes.Buffer)
+ enc := json.NewEncoder(buf)
+ enc.SetIndent("", " ")
+ enc.SetEscapeHTML(false) // do not escape html chars e.g. &, <, >
+
+ switch o.Kind {
+ case AliasNode:
+ log.Debugf("MarshalJSON AliasNode")
+ err := enc.Encode(o.Alias)
+ return buf.Bytes(), err
+ case ScalarNode:
+ log.Debugf("MarshalJSON ScalarNode")
+ value, err := o.GetValueRep()
+ if err != nil {
+ return buf.Bytes(), err
+ }
+ err = enc.Encode(value)
+ return buf.Bytes(), err
+ case MappingNode:
+ log.Debugf("MarshalJSON MappingNode")
+ buf.WriteByte('{')
+ for i := 0; i < len(o.Content); i += 2 {
+ if err := enc.Encode(o.Content[i].Value); err != nil {
+ return nil, err
+ }
+ buf.WriteByte(':')
+ if err := enc.Encode(o.Content[i+1]); err != nil {
+ return nil, err
+ }
+ if i != len(o.Content)-2 {
+ buf.WriteByte(',')
+ }
+ }
+ buf.WriteByte('}')
+ return buf.Bytes(), nil
+ case SequenceNode:
+ log.Debugf("MarshalJSON SequenceNode")
+ err := enc.Encode(o.Content)
+ return buf.Bytes(), err
+ default:
+ err := enc.Encode(nil)
+ return buf.Bytes(), err
+ }
+}
diff --git a/pkg/yqlib/context.go b/pkg/yqlib/context.go
index 17cddb3c..d2dc656b 100644
--- a/pkg/yqlib/context.go
+++ b/pkg/yqlib/context.go
@@ -83,11 +83,7 @@ func (n *Context) DeepClone() Context {
// copier doesn't do lists properly for some reason
clone.MatchingNodes = list.New()
for el := n.MatchingNodes.Front(); el != nil; el = el.Next() {
- clonedNode, err := el.Value.(*CandidateNode).Copy()
- if err != nil {
- log.Error("Error cloning context :(")
- panic(err)
- }
+ clonedNode := el.Value.(*CandidateNode).Copy()
clone.MatchingNodes.PushBack(clonedNode)
}
diff --git a/pkg/yqlib/cover.out b/pkg/yqlib/cover.out
new file mode 100644
index 00000000..6c07f264
--- /dev/null
+++ b/pkg/yqlib/cover.out
@@ -0,0 +1,3111 @@
+mode: set
+github.com/mikefarah/yq/v4/pkg/yqlib/all_at_once_evaluator.go:22.40,25.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/all_at_once_evaluator.go:27.108,29.29 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/all_at_once_evaluator.go:29.29,31.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/all_at_once_evaluator.go:32.2,32.62 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/all_at_once_evaluator.go:35.120,37.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/all_at_once_evaluator.go:37.16,39.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/all_at_once_evaluator.go:40.2,41.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/all_at_once_evaluator.go:41.16,43.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/all_at_once_evaluator.go:44.2,44.35 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/all_at_once_evaluator.go:47.123,51.37 3 0
+github.com/mikefarah/yq/v4/pkg/yqlib/all_at_once_evaluator.go:51.37,53.17 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/all_at_once_evaluator.go:53.17,55.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/all_at_once_evaluator.go:57.3,58.17 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/all_at_once_evaluator.go:58.17,60.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/all_at_once_evaluator.go:61.3,62.28 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/all_at_once_evaluator.go:65.2,65.29 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/all_at_once_evaluator.go:65.29,68.3 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/all_at_once_evaluator.go:70.2,71.16 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/all_at_once_evaluator.go:71.16,73.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/all_at_once_evaluator.go:74.2,74.38 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:30.64,35.2 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:37.77,41.22 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:42.24,43.23 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:44.25,45.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:46.12,47.22 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:48.14,49.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:50.11,51.22 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:53.2,53.13 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:88.54,92.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:94.47,96.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:98.44,100.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:100.21,102.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:103.2,103.19 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:106.50,108.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:110.46,111.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:111.21,113.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:114.2,114.19 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:117.47,119.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:121.44,122.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:122.21,124.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:125.2,125.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:128.41,130.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:130.16,132.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:133.2,134.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:134.18,136.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:137.2,137.66 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:140.57,145.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:147.45,149.2 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:151.52,152.16 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:152.16,154.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:155.2,155.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:155.18,157.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:158.2,158.26 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:158.26,160.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:161.2,162.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:162.16,164.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:165.2,165.14 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:169.49,171.35 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:171.35,173.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:175.2,175.16 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:175.16,177.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:178.2,178.31 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:181.46,184.31 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:184.31,186.25 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:187.12,188.42 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:189.11,190.14 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:190.14,192.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:192.10,192.52 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:192.52,194.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:194.10,196.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:199.2,199.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:202.45,206.2 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:208.58,210.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:212.123,223.2 8 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:225.59,228.22 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:228.22,230.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:230.8,235.3 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:236.2,236.38 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:239.64,240.27 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:240.27,241.41 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:241.41,245.4 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:247.8,248.37 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:248.37,250.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:254.60,258.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:259.15,261.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:262.17,264.41 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:265.16,266.30 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:267.16,268.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:271.2,271.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:274.57,275.36 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:275.36,277.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:277.8,277.26 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:277.26,280.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:281.2,283.25 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:283.25,286.3 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:287.2,289.19 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:292.95,299.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:301.86,305.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:305.16,307.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:307.8,309.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:311.2,311.16 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:314.106,322.2 7 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:324.47,326.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:328.61,330.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:332.66,336.18 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:336.18,338.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:340.2,373.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:373.18,375.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:377.2,377.14 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:381.83,386.66 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:386.66,388.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:390.2,396.38 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:400.93,402.26 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:402.26,407.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:408.2,411.78 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:411.78,413.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:415.2,417.32 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:417.32,419.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:424.2,424.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:424.18,426.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:428.2,428.29 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:428.29,430.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:431.2,431.29 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:431.29,433.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:434.2,434.29 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node.go:434.29,436.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:9.46,10.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:11.24,12.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:13.30,14.27 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:15.30,16.27 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:17.25,18.22 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:19.24,20.21 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:21.22,22.19 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:23.9,24.11 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:26.2,26.24 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:29.48,30.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:31.19,32.26 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:33.25,34.32 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:35.25,36.32 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:37.20,38.27 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:39.19,40.26 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:41.17,42.24 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:43.9,44.11 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:46.2,46.29 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:49.96,56.20 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:56.20,59.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:62.2,62.50 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:62.50,65.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:66.2,71.24 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:74.57,91.2 9 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:93.124,98.31 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:98.31,102.3 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:104.2,105.22 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:108.99,110.19 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:127.22,131.13 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:132.23,136.13 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:137.24,142.45 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:142.45,145.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:145.18,147.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:149.4,152.18 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:152.18,154.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:156.4,159.30 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:161.3,162.13 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:163.25,171.42 7 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:171.42,179.18 7 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:179.18,181.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:183.4,184.28 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:186.3,186.13 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:187.9,191.13 3 0
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:192.10,193.53 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:197.59,199.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:213.17,217.21 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:218.18,222.21 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:223.33,225.29 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:225.29,227.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:228.3,233.39 6 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:233.39,237.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:237.18,239.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:240.4,240.29 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:242.3,242.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidate_node_yaml.go:244.2,246.20 3 0
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:12.68,14.33 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:15.11,17.19 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:18.24,22.47 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:22.47,25.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:26.25,28.18 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:29.12,31.19 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:32.14,34.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:35.10,36.56 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:38.2,38.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:41.58,43.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:44.11,52.17 6 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:52.17,54.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:57.3,58.66 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:58.66,62.37 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:62.37,63.10 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:66.4,75.49 8 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:75.49,77.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:79.4,79.55 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:82.3,82.44 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:82.44,84.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:85.3,85.13 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:86.11,91.57 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:91.57,93.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:95.3,95.34 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:95.34,97.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:97.20,100.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:101.4,109.40 8 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:111.3,111.13 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:113.2,118.16 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:118.16,120.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:121.2,123.36 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:127.55,134.16 6 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:139.17,142.26 3 0
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:143.18,146.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:146.17,148.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:149.3,150.26 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:151.19,154.42 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:154.42,155.57 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:155.57,157.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:158.4,159.53 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:159.53,161.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:162.4,162.29 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:162.29,164.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:166.3,167.26 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:168.20,171.26 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/candidiate_node_json.go:172.10,174.26 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/chown_linux.go:11.57,12.50 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/chown_linux.go:12.50,17.17 4 0
+github.com/mikefarah/yq/v4/pkg/yqlib/chown_linux.go:17.17,22.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/chown_linux.go:24.2,24.12 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/color_print.go:16.42,18.2 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/color_print.go:20.65,23.36 3 0
+github.com/mikefarah/yq/v4/pkg/yqlib/color_print.go:23.36,28.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/color_print.go:29.2,29.38 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/color_print.go:29.38,34.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/color_print.go:35.2,35.38 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/color_print.go:35.38,40.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/color_print.go:41.2,41.38 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/color_print.go:41.38,46.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/color_print.go:47.2,47.37 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/color_print.go:47.37,52.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/color_print.go:53.2,53.38 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/color_print.go:53.38,58.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/color_print.go:59.2,60.12 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:19.80,25.2 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:27.72,31.2 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:33.63,35.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:37.46,38.28 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:38.28,40.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:41.2,41.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:44.55,45.24 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:45.24,47.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:48.2,48.26 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:51.62,52.24 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:52.24,54.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:55.2,55.27 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:58.60,61.26 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:61.26,63.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:63.17,65.14 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:68.2,69.14 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:72.37,73.38 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:73.38,75.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:76.2,77.48 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:80.39,85.63 4 0
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:85.63,88.3 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:90.2,90.16 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:90.16,92.13 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:94.2,94.14 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:97.35,101.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:101.16,103.13 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:105.2,105.14 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:108.43,112.2 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/context.go:114.43,118.2 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/data_tree_navigator.go:21.47,23.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/data_tree_navigator.go:25.118,39.2 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/data_tree_navigator.go:41.112,42.27 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/data_tree_navigator.go:42.27,45.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/data_tree_navigator.go:46.2,47.37 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/data_tree_navigator.go:47.37,48.70 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/data_tree_navigator.go:48.70,50.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/data_tree_navigator.go:52.2,53.20 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/data_tree_navigator.go:53.20,55.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/data_tree_navigator.go:56.2,56.93 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder.go:28.64,29.16 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder.go:30.26,31.30 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder.go:32.18,33.29 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder.go:34.34,35.36 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder.go:36.29,37.30 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder.go:38.18,39.35 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder.go:40.18,41.35 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder.go:42.14,43.30 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder.go:44.10,45.100 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder.go:49.49,51.20 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder.go:51.20,54.16 3 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder.go:54.16,58.4 3 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder.go:61.2,62.15 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_base64.go:15.53,20.2 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_base64.go:22.54,26.37 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_base64.go:26.37,28.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_base64.go:29.2,29.15 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_base64.go:39.33,41.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_base64.go:43.56,48.2 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_base64.go:50.60,51.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_base64.go:51.18,53.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_base64.go:54.2,57.54 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_base64.go:57.54,59.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_base64.go:60.2,60.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_base64.go:60.20,66.23 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_base64.go:66.23,68.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_base64.go:70.2,71.50 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_csv_object.go:17.50,19.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_csv_object.go:21.59,28.2 6 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_csv_object.go:30.75,32.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_csv_object.go:32.16,34.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_csv_object.go:35.2,35.13 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_csv_object.go:38.99,41.35 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_csv_object.go:41.35,43.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_csv_object.go:44.2,44.19 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_csv_object.go:47.63,48.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_csv_object.go:48.18,50.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_csv_object.go:51.2,53.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_csv_object.go:53.16,55.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_csv_object.go:57.2,61.40 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_csv_object.go:61.40,66.3 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_csv_object.go:67.2,67.29 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_csv_object.go:67.29,69.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_csv_object.go:71.2,71.23 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_json.go:15.31,17.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_json.go:19.54,22.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_json.go:24.58,28.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_json.go:28.16,30.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_json.go:32.2,32.25 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:19.37,21.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:23.60,27.2 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:29.45,32.39 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:32.39,34.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:34.17,36.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:36.9,38.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:40.2,40.13 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:43.63,44.13 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:44.13,46.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:47.2,47.17 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:50.115,72.2 7 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:74.115,79.31 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:79.31,81.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:81.17,83.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:86.2,89.51 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:92.64,93.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:93.18,95.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:96.2,98.52 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:98.52,100.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:101.2,101.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:101.20,104.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:105.2,106.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:106.16,108.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:109.2,119.40 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:119.40,120.69 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:120.69,122.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_properties.go:125.2,127.21 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:23.31,28.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:30.54,34.16 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:34.16,36.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:37.2,42.12 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:45.72,47.6 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:47.6,50.22 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:50.22,52.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:56.99,62.16 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:62.16,64.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:66.2,69.53 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:72.107,74.70 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:74.70,76.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:78.2,78.34 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:78.34,82.37 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:82.37,83.72 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:83.72,85.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:86.9,91.4 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:93.2,94.19 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:97.91,102.22 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:102.22,104.34 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:104.34,106.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:108.3,113.70 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:113.70,115.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:117.3,117.50 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:120.2,124.8 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:127.82,130.22 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:130.22,133.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:133.17,135.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:136.3,136.38 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:139.2,143.8 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:147.89,150.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:152.87,155.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:157.90,161.2 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:163.91,167.2 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:169.88,173.2 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:175.81,176.23 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:177.29,178.42 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:179.17,180.40 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:181.20,182.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:183.21,184.44 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:185.18,186.41 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:187.18,188.35 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:189.24,190.44 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:191.10,192.63 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:197.58,198.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:198.18,200.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:203.2,204.15 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:204.15,205.31 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:205.31,208.11 3 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:208.11,210.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:214.2,217.58 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:217.58,219.27 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:219.27,221.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:223.3,227.17 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:227.17,229.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:233.2,234.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:234.16,236.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:239.2,241.35 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:241.35,243.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:245.2,245.35 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:249.83,253.36 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:253.36,255.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:255.8,255.48 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:255.48,257.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:257.8,259.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:261.2,262.34 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:265.76,271.15 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:271.15,273.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:275.2,281.38 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:281.38,284.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:286.2,288.43 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:288.43,290.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:291.2,295.16 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:295.16,297.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:298.2,298.34 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:301.104,320.2 6 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:322.81,331.15 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:331.15,333.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:335.2,343.43 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:343.43,345.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_toml.go:346.2,353.34 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_uri.go:15.30,17.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_uri.go:19.53,24.2 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_uri.go:26.57,27.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_uri.go:27.18,29.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_uri.go:31.2,33.52 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_uri.go:33.52,35.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_uri.go:36.2,36.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_uri.go:36.20,42.23 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_uri.go:42.23,44.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_uri.go:46.2,47.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_uri.go:47.16,49.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_uri.go:50.2,51.46 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:24.50,29.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:31.53,36.2 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:38.81,40.30 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:40.30,42.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:42.17,44.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:45.3,45.31 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:48.2,48.22 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:53.56,54.13 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:54.13,56.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:61.2,63.20 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:66.70,70.21 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:70.21,78.3 7 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:80.2,80.42 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:80.42,87.13 6 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:87.13,91.4 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:92.3,96.24 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:96.24,98.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:98.18,100.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:101.9,105.71 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:105.71,106.34 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:106.34,111.6 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:111.11,115.6 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:117.4,118.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:118.18,120.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:122.3,122.50 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:125.2,125.22 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:128.80,129.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:130.9,131.35 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:132.9,133.48 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:134.10,136.32 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:136.32,138.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:139.3,143.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:147.78,148.25 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:148.25,150.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:152.2,157.27 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:157.27,160.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:162.2,164.20 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:167.57,168.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:168.18,170.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:171.2,175.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:175.16,177.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:178.2,180.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:180.16,182.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:182.8,182.38 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:182.38,184.23 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:184.23,186.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:188.2,191.23 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:209.50,211.23 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:211.23,213.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:214.2,216.40 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:216.40,217.24 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:217.24,222.4 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:224.2,225.73 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:238.55,252.40 6 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:252.40,253.28 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:253.28,255.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:256.3,256.24 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:259.2,259.6 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:259.6,261.40 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:261.40,263.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:264.3,264.15 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:264.15,265.9 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:268.3,268.25 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:269.25,280.30 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:280.30,281.32 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:281.32,282.28 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:282.28,284.7 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:286.5,286.95 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:288.21,292.35 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:292.35,294.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:296.4,296.23 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:296.23,300.5 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:301.23,305.26 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:305.26,307.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:310.4,310.22 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:311.20,314.31 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:314.31,317.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:317.10,317.39 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:317.39,320.5 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:320.10,323.5 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:325.21,326.31 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:326.31,328.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:329.22,330.33 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:330.33,332.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:334.3,334.17 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:337.2,337.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:340.57,343.30 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:343.30,348.60 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:348.60,351.4 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:351.9,353.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:354.8,357.3 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:360.63,362.33 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:362.33,363.16 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:363.16,365.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:367.2,367.45 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:376.38,377.13 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:377.13,379.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:381.2,383.30 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:383.30,384.50 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:384.50,385.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:388.3,388.19 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:388.19,392.4 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:392.9,394.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:398.2,398.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:398.18,400.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_xml.go:402.2,402.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:28.52,30.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:32.92,36.6 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:36.6,38.29 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:38.29,41.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:41.9,41.24 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:41.24,43.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:43.9,43.42 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:43.42,46.30 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:46.30,48.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:48.10,48.25 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:48.25,50.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:51.9,51.40 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:51.40,54.30 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:54.30,56.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:56.10,56.25 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:56.25,58.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:59.9,59.118 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:59.118,62.30 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:62.30,64.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:64.10,64.25 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:64.25,66.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:67.9,69.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:73.54,81.93 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:81.93,83.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:83.17,85.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:86.8,86.51 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:86.51,92.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:93.2,98.12 6 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:101.58,105.77 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:105.77,109.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:109.8,109.98 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:109.98,114.31 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:114.31,116.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:117.3,117.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:118.8,118.23 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:118.23,120.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:122.2,125.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:125.16,127.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:129.2,132.30 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:132.30,135.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:136.2,138.28 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/decoder_yaml.go:141.63,145.2 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder.go:14.44,16.30 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder.go:16.30,17.42 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder.go:17.42,18.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder.go:18.20,20.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder.go:24.2,24.37 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder.go:24.37,26.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_base64.go:13.33,15.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_base64.go:17.49,19.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_base64.go:21.72,23.2 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_base64.go:25.85,27.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_base64.go:29.85,31.46 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_base64.go:31.46,33.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_base64.go:34.2,35.12 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:13.44,15.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:17.46,19.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:21.69,23.2 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:25.82,27.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:29.88,32.33 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:32.33,34.31 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:34.31,36.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:37.3,37.32 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:39.2,39.38 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:42.90,43.32 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:43.32,45.33 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:45.33,47.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:48.3,49.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:49.17,51.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:53.2,53.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:56.84,57.31 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:57.31,59.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:60.2,61.29 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:64.102,66.33 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:66.33,69.21 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:69.21,71.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:72.3,72.37 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:74.2,74.17 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:78.91,80.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:80.16,82.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:84.2,85.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:85.16,87.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:89.2,89.32 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:89.32,90.32 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:90.32,92.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:93.3,95.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:95.17,97.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:100.2,100.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:103.82,104.37 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:104.37,106.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:108.2,113.31 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:113.31,115.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:115.8,115.35 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:115.35,117.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:118.2,118.40 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:118.40,120.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:122.2,122.41 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:122.41,124.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_csv.go:126.2,126.48 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_json.go:18.75,21.42 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_json.go:21.42,23.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_json.go:25.2,25.59 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_json.go:28.48,30.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_json.go:32.71,34.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_json.go:36.84,38.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_json.go:40.76,44.48 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_json.go:44.48,46.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_json.go:48.2,50.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_json.go:50.17,52.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_json.go:54.2,59.16 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_json.go:59.16,61.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_json.go:62.2,62.17 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_json.go:62.17,64.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_json.go:65.2,65.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:17.54,21.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:23.54,25.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:27.77,29.2 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:31.90,33.6 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:33.6,36.58 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:36.58,38.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:39.3,39.53 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:39.53,41.60 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:41.60,43.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:45.9,46.56 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:46.56,48.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:51.3,51.36 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:51.36,52.22 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:52.22,54.53 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:54.53,56.6 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:58.4,58.9 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:61.2,61.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:64.82,66.29 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:66.29,68.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:70.2,73.16 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:73.16,75.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:77.2,78.12 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:81.129,84.20 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:84.20,87.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:88.2,92.19 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:93.18,95.60 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:95.60,97.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:97.9,99.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:100.3,101.13 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:102.20,103.47 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:104.19,105.45 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:106.17,107.47 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:108.10,109.53 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:113.78,114.16 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:114.16,116.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:117.2,117.40 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:120.110,121.33 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:121.33,123.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:123.17,125.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:127.2,127.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:130.108,131.55 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:131.55,135.17 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:135.17,137.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_properties.go:139.2,139.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_sh.go:16.29,18.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_sh.go:20.45,22.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_sh.go:24.68,26.2 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_sh.go:28.81,30.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_sh.go:32.81,34.46 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_sh.go:34.46,36.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_sh.go:38.2,38.58 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_sh.go:42.49,48.27 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_sh.go:48.27,50.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_sh.go:50.18,51.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_sh.go:51.20,55.5 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_sh.go:57.4,57.27 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_sh.go:58.9,59.42 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_sh.go:59.42,63.5 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_sh.go:66.3,66.24 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_sh.go:69.2,69.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_sh.go:69.18,71.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_sh.go:72.2,72.25 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_sh.go:75.47,77.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:15.41,17.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:19.58,21.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:23.76,25.2 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:27.83,29.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:31.86,35.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:35.16,37.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:39.2,39.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:42.97,46.19 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:47.18,49.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:49.17,54.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:55.3,56.13 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:57.20,58.42 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:58.42,60.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:60.18,62.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:64.3,64.13 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:65.19,66.64 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:66.64,70.18 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:70.18,72.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:74.3,74.13 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:75.17,76.42 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:77.10,78.53 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:82.63,111.39 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:111.39,112.36 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:112.36,114.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:114.9,114.31 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:114.31,116.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:117.3,117.13 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:120.2,120.22 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:120.22,122.38 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:122.38,124.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:125.3,125.13 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:127.2,127.31 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:130.38,132.26 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:132.26,133.37 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:133.37,135.9 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:138.2,138.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:138.18,140.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:141.2,141.14 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:144.39,146.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_shellvariables.go:148.46,150.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_toml.go:11.31,13.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_toml.go:15.76,16.29 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_toml.go:16.29,18.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_toml.go:19.2,19.195 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_toml.go:22.71,24.2 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_toml.go:26.84,28.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_toml.go:30.48,32.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_uri.go:12.30,14.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_uri.go:16.46,18.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_uri.go:20.69,22.2 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_uri.go:24.82,26.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_uri.go:28.82,30.46 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_uri.go:30.46,32.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_uri.go:33.2,34.12 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:20.62,23.42 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:23.42,25.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:26.2,26.50 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:29.46,31.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:33.69,35.2 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:37.82,40.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:42.74,50.28 6 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:50.28,52.48 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:52.48,56.53 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:56.53,59.57 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:59.57,61.6 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:62.5,62.59 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:62.59,64.6 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:69.2,69.28 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:69.28,73.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:73.17,75.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:76.3,77.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:77.17,79.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:82.2,82.19 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:83.19,85.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:85.17,87.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:88.18,91.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:91.17,93.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:94.3,94.25 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:95.10,96.84 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:99.2,99.37 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:103.89,105.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:105.16,107.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:108.2,108.44 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:108.44,115.17 6 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:115.17,117.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:118.3,118.36 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:118.36,121.18 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:121.18,123.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:126.3,126.52 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:126.53,128.4 0 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:128.9,128.66 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:128.66,131.56 3 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:131.56,133.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:134.4,134.58 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:134.58,136.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:137.9,137.48 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:137.48,139.57 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:139.57,141.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:142.4,142.58 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:142.58,144.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:145.9,150.18 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:150.18,152.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:154.3,155.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:155.17,157.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:159.2,159.52 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:162.107,164.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:164.16,166.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:167.2,167.52 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:170.105,172.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:172.16,174.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:175.2,175.52 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:178.104,179.19 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:180.19,181.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:182.20,183.45 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:184.18,186.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:186.17,188.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:190.3,192.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:192.17,194.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:196.3,196.68 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:196.68,198.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:200.3,200.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:202.2,202.52 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:209.83,210.22 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:210.22,213.85 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:213.85,219.53 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:219.53,221.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:223.9,225.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:227.3,227.82 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:227.82,230.4 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:231.3,235.17 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:235.17,237.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:239.2,239.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:242.107,244.75 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:244.75,246.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:248.2,248.41 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:248.41,250.66 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:250.66,252.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:254.2,254.52 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:257.52,262.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:264.105,268.44 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:268.44,272.31 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:272.31,273.32 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:273.32,276.5 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:276.10,278.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:282.2,283.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:283.16,285.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:288.2,288.44 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:288.44,293.17 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:293.17,295.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:296.3,296.59 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:296.59,299.56 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:299.56,301.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:302.9,302.48 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:302.48,304.57 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:304.57,306.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:307.9,307.46 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:307.46,310.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:310.18,312.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:313.4,315.18 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:315.18,317.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:318.4,319.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:319.18,321.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:322.9,322.39 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:322.39,325.18 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:325.18,327.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:329.3,330.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:330.17,332.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_xml.go:335.2,335.42 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:20.79,21.16 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:21.16,23.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:24.2,24.46 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:27.48,29.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:31.71,32.33 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:32.33,34.54 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:34.54,36.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:38.2,38.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:41.84,47.6 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:47.6,50.58 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:50.58,52.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:53.3,53.53 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:53.53,55.60 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:55.60,57.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:59.9,60.110 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:60.110,62.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:63.4,63.56 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:63.56,65.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:68.3,68.36 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:68.36,69.22 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:69.22,71.53 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:71.53,73.6 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:75.4,75.9 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:79.2,79.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:82.76,84.54 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:84.54,86.54 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:86.54,88.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:89.3,89.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:92.2,94.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:94.17,96.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:98.2,104.16 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:104.16,106.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:108.2,111.47 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:111.47,113.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:115.2,115.77 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:115.77,117.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:119.2,119.17 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:119.17,121.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/encoder_yaml.go:122.2,122.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_parser.go:23.54,25.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_parser.go:27.92,30.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_parser.go:30.16,32.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_parser.go:33.2,35.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_parser.go:35.16,37.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_parser.go:38.2,38.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_parser.go:41.104,44.27 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_parser.go:44.27,46.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_parser.go:48.2,48.40 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_parser.go:48.40,51.42 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_parser.go:51.42,53.20 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_parser.go:53.20,54.23 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_parser.go:54.23,56.6 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_parser.go:57.5,59.22 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_parser.go:60.10,60.27 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_parser.go:60.27,61.23 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_parser.go:61.23,63.6 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_parser.go:64.5,67.22 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_parser.go:70.3,70.34 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_parser.go:72.2,72.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_parser.go:72.21,74.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_parser.go:75.2,75.22 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:17.51,19.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:21.84,26.2 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:28.47,29.36 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:29.36,31.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:31.8,31.49 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:31.49,33.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:33.8,33.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:33.43,35.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:36.2,36.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:39.96,45.38 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:45.38,47.33 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:48.52,50.70 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:51.41,54.52 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:54.52,57.5 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:59.4,59.72 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:59.72,61.38 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:61.38,63.6 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:64.5,64.53 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:66.4,66.25 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:66.25,68.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:70.4,80.55 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:80.55,82.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:83.4,85.29 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:85.29,88.5 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:92.4,92.142 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:92.142,95.5 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:97.21,98.77 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:98.77,100.38 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:100.38,102.6 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:104.5,104.53 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:106.4,106.25 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:106.25,108.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:110.4,110.41 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:112.11,117.84 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:117.84,119.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:121.4,122.70 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:126.2,127.22 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:127.22,129.33 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:129.33,131.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:133.3,133.123 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:136.2,136.37 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:136.37,138.39 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:138.39,140.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/expression_postfix.go:143.2,143.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go:9.50,10.60 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go:10.60,16.64 4 0
+github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go:16.64,18.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go:19.3,19.26 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go:21.2,21.12 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go:24.41,27.22 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go:27.22,29.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go:33.52,38.16 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go:38.16,40.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go:41.2,43.16 3 0
+github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go:43.16,45.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go:46.2,47.43 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go:47.43,49.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go:50.2,50.19 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go:53.42,54.33 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go:55.16,56.26 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go:60.37,62.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go:62.16,65.3 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go:68.41,70.24 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go:70.24,72.17 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go:72.17,74.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go:75.8,75.23 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go:75.23,77.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go:79.2,80.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go:80.16,82.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/file_utils.go:84.2,84.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go:23.72,25.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go:27.70,29.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go:31.63,33.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go:35.44,37.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go:42.48,45.31 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go:45.31,47.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go:47.8,49.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go:49.17,51.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go:52.3,52.33 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go:54.2,57.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go:57.16,59.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go:60.2,65.6 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go:65.6,67.29 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go:67.29,69.9 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go:70.9,70.24 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go:70.24,72.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go:73.3,73.50 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go:73.50,75.9 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go:77.3,79.58 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go:79.58,81.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go:83.3,85.24 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go:85.24,87.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/front_matter.go:90.2,92.12 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:33.46,34.35 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:34.35,35.13 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:35.13,37.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:38.3,38.32 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:39.8,39.39 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:39.39,41.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:41.8,41.40 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:41.40,43.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:43.8,43.39 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:43.39,45.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:45.8,45.40 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:45.40,47.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:47.8,47.45 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:47.45,49.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:49.8,49.46 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:49.46,51.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:51.8,51.48 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:51.48,54.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:54.8,56.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:59.34,61.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:63.56,67.26 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:67.26,69.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:70.2,70.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:73.59,76.23 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:76.23,78.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:79.2,81.66 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:84.50,89.28 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:89.28,90.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:90.20,92.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:92.9,94.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:97.2,97.28 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:100.62,102.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:104.119,110.52 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:110.52,125.3 7 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:127.2,127.50 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:127.50,130.56 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:130.56,134.4 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:137.2,138.48 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:138.48,143.3 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:145.2,148.50 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:148.50,151.74 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:151.74,156.4 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:159.2,161.102 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:161.102,165.3 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:167.2,170.57 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:170.57,174.3 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:175.2,176.44 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:176.44,181.3 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer.go:182.2,182.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:237.69,239.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:241.102,243.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:245.47,247.43 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:247.43,249.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:250.2,253.43 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:253.43,255.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:257.2,257.42 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:260.39,261.52 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:261.52,265.34 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:265.34,268.4 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:270.3,271.14 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:271.14,273.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:274.3,276.91 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:280.59,289.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:291.109,292.52 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:292.52,296.26 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:296.26,298.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:299.3,299.88 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:303.52,304.52 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:304.52,308.3 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:311.34,312.52 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:312.52,315.27 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:315.27,317.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:319.3,321.63 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:325.54,326.52 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:326.52,337.3 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:340.48,341.52 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:341.52,345.35 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:345.35,347.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:348.3,349.63 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:353.38,354.52 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:354.52,356.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:359.27,360.52 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:360.52,362.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:365.29,366.52 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:366.52,374.3 7 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:377.34,378.52 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:378.52,382.13 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:382.13,386.4 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:386.9,389.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:391.3,395.73 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:399.37,400.52 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:400.52,407.14 7 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:407.14,409.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:410.3,410.14 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:410.14,412.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:414.3,415.63 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:419.52,420.52 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:420.52,424.37 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:424.37,426.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:427.3,427.37 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:427.37,429.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:430.3,430.37 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:430.37,432.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:433.3,433.37 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:433.37,435.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:436.3,436.37 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:436.37,438.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:439.3,441.63 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:446.36,447.52 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:447.52,456.3 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:459.26,460.52 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:460.52,465.27 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:465.27,467.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:469.3,469.105 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:473.28,474.52 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:474.52,477.27 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:477.27,479.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:480.3,480.103 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:484.29,485.52 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:485.52,488.27 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:488.27,490.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:492.3,492.103 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:496.67,497.52 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:497.52,500.27 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:500.27,502.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:504.3,506.63 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:510.78,513.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:515.49,518.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:520.58,523.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:525.42,527.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:529.61,530.52 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:530.52,532.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:535.83,536.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:536.43,537.50 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:537.50,539.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:541.2,541.28 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:544.73,546.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:546.16,548.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:549.2,551.6 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:551.6,553.15 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:553.15,555.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:555.9,555.40 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:555.40,557.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:559.3,560.38 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:560.38,562.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:562.16,564.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/lexer_participle.go:565.4,565.34 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:16.29,17.29 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:17.29,19.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:27.34,29.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:190.73,191.42 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:191.42,193.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:195.2,195.62 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:195.62,196.66 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:196.66,198.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:200.2,200.13 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:203.65,205.64 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:205.64,206.53 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:206.53,208.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:210.2,210.11 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:213.68,215.66 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:215.66,216.55 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:216.55,218.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:220.2,220.11 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:223.74,224.42 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:224.42,226.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:228.2,228.62 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:228.62,234.80 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:234.80,236.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:238.2,238.13 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:241.57,242.17 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:242.17,247.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:248.2,250.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:250.16,252.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:253.2,254.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:254.16,256.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:257.2,260.20 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:263.70,264.26 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:264.26,266.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:268.2,268.28 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:268.28,275.23 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:275.23,277.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:280.2,280.25 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:280.25,283.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:283.8,283.35 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:283.35,285.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:285.8,285.37 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:285.37,287.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:287.8,287.36 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:287.36,289.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:290.2,290.14 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:294.61,296.41 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:296.41,299.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:300.2,301.23 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:304.49,308.41 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:308.41,310.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:310.8,312.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:314.2,314.16 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:314.16,316.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:316.8,316.57 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:316.57,318.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:320.2,320.25 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:323.53,325.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:327.46,329.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:331.46,333.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:335.46,337.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:339.77,349.2 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:352.39,353.14 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:353.14,355.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:356.2,356.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:356.43,358.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:358.8,358.51 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:358.51,360.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:360.8,360.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:360.43,362.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:362.8,364.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:368.50,369.38 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:369.38,371.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:373.2,374.58 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:374.58,376.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:377.2,377.15 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:380.47,381.38 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:381.38,383.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:384.2,384.17 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:384.17,386.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:387.2,388.28 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:388.28,390.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:391.2,392.22 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:392.22,394.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:395.2,395.125 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:398.65,399.38 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:399.38,401.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:402.2,403.37 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:403.37,404.30 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:404.30,406.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:407.3,410.54 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:412.2,412.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:415.35,416.14 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:417.18,418.22 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:419.20,420.24 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:421.19,422.23 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:423.17,424.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/lib.go:425.10,426.20 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/matchKeyString.go:3.59,4.19 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/matchKeyString.go:4.19,6.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/matchKeyString.go:7.2,7.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/matchKeyString.go:7.20,10.3 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/matchKeyString.go:11.2,11.33 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/matchKeyString.go:16.43,21.42 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/matchKeyString.go:21.42,22.24 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/matchKeyString.go:22.24,24.13 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/matchKeyString.go:25.12,26.40 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/matchKeyString.go:26.40,29.14 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/matchKeyString.go:31.13,32.23 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/matchKeyString.go:32.23,35.14 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/matchKeyString.go:37.13,44.13 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/matchKeyString.go:48.3,48.40 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/matchKeyString.go:48.40,51.12 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/matchKeyString.go:53.3,53.15 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/matchKeyString.go:56.2,56.13 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:10.76,14.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:16.112,18.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:20.77,21.31 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:21.31,23.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:25.2,27.24 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:28.20,29.23 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:30.10,31.27 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:31.27,33.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:34.3,34.33 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:39.106,43.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:45.113,51.29 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:51.29,53.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:55.2,57.22 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:58.19,59.30 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:59.30,61.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:62.3,62.28 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:63.20,64.33 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:65.18,66.29 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:66.29,68.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:69.3,71.67 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:71.67,73.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:75.2,75.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:78.103,82.38 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:82.38,86.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:88.2,91.70 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:91.70,94.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:96.2,96.16 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:96.16,99.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:99.8,99.30 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:99.30,102.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:102.8,102.30 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:102.30,105.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:105.8,105.51 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:105.51,107.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:107.17,109.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:110.3,111.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:111.17,113.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:114.3,116.42 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:117.8,117.101 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:117.101,119.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:119.17,121.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:122.3,123.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:123.17,125.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:126.3,127.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:127.18,129.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:129.9,131.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:132.3,132.40 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:133.8,135.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:136.2,136.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:139.103,142.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:142.16,144.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:146.2,147.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:147.16,149.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:151.2,153.12 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:157.82,160.27 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:160.27,163.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:164.2,169.32 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:172.79,176.27 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:176.27,179.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:181.2,184.62 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:184.62,190.21 6 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:190.21,193.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:193.9,198.4 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:200.2,201.26 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:201.26,203.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_add.go:204.2,204.22 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_alternative.go:3.114,8.68 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_alternative.go:8.68,9.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_alternative.go:9.18,11.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_alternative.go:12.4,13.14 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_alternative.go:13.14,15.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_alternative.go:16.4,16.19 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_alternative.go:19.2,19.66 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_alternative.go:22.125,23.16 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_alternative.go:23.16,25.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_alternative.go:26.2,26.16 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_alternative.go:26.16,28.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_alternative.go:30.2,31.12 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_alternative.go:31.12,33.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_alternative.go:34.2,34.17 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:8.114,13.44 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:13.44,15.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:15.17,17.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:18.3,18.39 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:18.39,20.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:23.2,25.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:25.16,27.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:29.2,29.65 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:29.65,33.44 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:33.44,35.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:35.18,37.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:38.4,38.40 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:38.40,40.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:43.3,43.22 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:43.22,46.4 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:48.2,48.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:51.111,55.69 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:55.69,59.3 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:60.2,60.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:63.115,68.44 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:68.44,70.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:70.17,72.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:74.3,74.39 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:74.39,76.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:79.2,81.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:81.16,83.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:85.2,85.65 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:85.65,89.44 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:89.44,91.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:91.18,93.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:95.4,95.40 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:95.40,97.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:100.3,100.32 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:102.2,102.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:105.112,109.69 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:109.69,114.3 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:115.2,115.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:118.110,121.69 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:121.69,126.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:126.17,128.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:129.3,129.86 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:129.86,131.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:131.18,133.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:138.2,138.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:141.72,146.63 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:146.63,150.28 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:150.28,152.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:152.18,154.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:155.9,156.38 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:156.38,158.76 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:158.76,161.20 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:161.20,163.7 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:165.10,168.19 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:168.19,170.6 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:174.2,175.70 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:175.70,177.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:178.2,178.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:181.62,184.19 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:185.20,186.48 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:186.48,189.29 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:189.29,191.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:193.3,193.13 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:194.17,196.24 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:196.24,203.4 6 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:204.3,205.13 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:206.19,209.64 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:209.64,211.29 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:211.29,213.10 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:217.3,217.15 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:217.15,220.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:222.3,222.64 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:222.64,226.18 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:226.18,228.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:229.4,230.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:230.18,232.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:234.3,234.13 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:235.10,236.13 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:240.102,242.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:242.18,244.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:245.2,246.31 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:246.31,248.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:249.2,249.64 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:249.64,254.17 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:254.17,256.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:258.2,258.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:261.125,265.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:265.16,267.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:269.2,269.84 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:269.84,273.77 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:273.77,277.4 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:278.3,278.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:281.2,281.76 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:281.76,284.57 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:284.57,287.4 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:290.2,291.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:291.16,293.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_anchors_aliases.go:294.2,297.12 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:9.73,10.117 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:10.117,11.50 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:11.50,13.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:14.3,14.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:20.70,23.41 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:24.25,25.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:26.27,27.32 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:29.2,29.14 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:32.115,34.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:34.16,36.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:38.2,42.44 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:42.44,46.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:48.2,48.65 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:48.65,53.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:53.17,55.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:58.3,60.19 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:60.19,63.4 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:66.2,66.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:70.119,73.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:73.16,75.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:76.2,76.65 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:76.65,81.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:81.17,83.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:86.3,88.19 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:88.19,90.51 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:90.51,92.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:93.4,93.57 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:93.57,95.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_assign.go:98.2,98.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:9.50,10.22 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:10.22,12.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:13.2,14.26 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:14.26,16.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:17.2,17.53 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:17.53,24.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:25.2,25.13 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:28.70,31.30 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:31.30,33.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:33.8,33.23 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:33.23,35.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:36.2,36.14 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:39.125,44.2 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:46.86,47.58 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:47.58,51.57 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:51.57,53.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:54.3,55.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:55.17,57.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:58.3,58.56 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:62.147,63.44 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:63.44,65.28 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:65.28,68.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:68.18,70.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:71.4,71.35 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:71.35,73.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:73.10,75.13 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:79.3,79.37 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:79.37,81.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:83.2,83.19 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:86.106,89.69 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:89.69,92.41 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:92.41,94.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:95.3,96.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:96.17,98.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:99.3,100.27 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:102.2,102.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:105.106,108.69 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:108.69,111.41 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:111.41,113.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:114.3,115.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:115.17,117.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:118.3,119.27 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:121.2,121.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:124.105,131.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:133.106,140.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:142.106,146.69 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:146.69,152.3 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_booleans.go:153.2,153.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect.go:7.117,9.69 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect.go:9.69,12.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect.go:12.17,14.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect.go:15.3,15.96 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect.go:15.96,19.4 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect.go:21.2,21.27 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect.go:24.110,27.38 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect.go:27.38,31.3 3 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect.go:33.2,34.89 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect.go:34.89,36.27 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect.go:36.27,37.9 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect.go:41.2,41.25 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect.go:41.25,44.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect.go:44.17,46.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect.go:47.3,47.56 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect.go:51.2,52.69 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect.go:52.69,60.17 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect.go:60.17,62.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect.go:64.3,64.96 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect.go:64.96,68.4 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect.go:69.3,71.37 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect.go:74.2,74.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go:18.124,23.38 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go:23.38,27.3 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go:28.2,31.42 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go:31.42,33.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go:35.2,35.69 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go:35.69,38.43 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go:38.43,42.4 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go:44.2,47.42 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go:47.42,49.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go:49.17,51.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go:54.3,54.72 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go:54.72,64.4 6 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go:67.2,67.45 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go:71.99,72.33 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go:72.33,74.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go:76.2,82.16 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go:82.16,84.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go:86.2,86.38 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go:86.38,89.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go:91.2,93.69 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go:93.69,95.91 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go:95.91,103.18 6 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go:103.18,105.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go:106.4,106.33 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_collect_object.go:109.2,109.67 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_column.go:8.109,13.69 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_column.go:13.69,17.3 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_column.go:19.2,19.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:16.117,22.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:22.16,24.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:26.2,29.44 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:29.44,31.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:31.17,33.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:35.3,35.39 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:35.39,37.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:40.2,42.65 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:42.65,47.44 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:47.44,49.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:49.18,51.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:53.4,53.40 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:53.40,55.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:58.3,59.30 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:59.30,62.4 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:63.3,63.30 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:63.30,66.4 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:67.3,67.30 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:67.30,69.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:72.2,72.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:75.114,87.69 9 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:87.69,90.30 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:90.30,93.4 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:93.9,93.71 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:93.71,98.88 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:98.88,100.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:101.4,101.41 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:101.41,103.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:104.4,105.55 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:106.9,106.37 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:106.37,108.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:108.9,108.37 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:108.37,110.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:111.3,115.25 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:115.25,118.4 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:119.3,119.27 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_comments.go:121.2,121.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:13.110,17.2 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:19.145,20.117 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:20.117,22.31 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:22.31,25.4 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:25.9,25.24 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:25.24,28.4 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:28.9,28.24 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:28.24,31.4 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:33.3,36.20 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:37.20,38.67 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:39.21,40.69 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:41.11,42.31 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:42.31,44.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:45.4,48.53 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:53.114,55.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:55.16,57.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:59.2,60.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:60.16,62.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:64.2,64.45 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:64.45,66.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:67.2,67.19 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:67.19,69.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:70.2,70.37 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:74.115,80.23 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:80.23,83.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:84.2,84.16 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:84.16,86.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:86.8,86.51 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:86.51,88.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:88.17,90.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:91.3,92.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:92.17,94.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:96.3,96.40 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:96.40,98.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:99.3,99.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:99.20,101.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:102.3,102.30 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:103.8,103.101 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:103.101,105.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:105.17,107.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:108.3,109.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:109.17,111.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:112.3,112.40 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:112.40,114.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:115.3,115.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:115.20,117.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:118.3,118.30 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:119.8,119.51 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:119.51,120.46 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:120.46,122.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:123.3,123.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:123.20,125.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:126.3,126.36 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:127.8,127.70 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:127.70,129.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:129.8,129.53 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:129.53,131.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_compare.go:133.2,133.74 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:8.111,10.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:12.84,13.64 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:13.64,15.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:15.17,17.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:18.3,18.23 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:18.23,20.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:22.2,22.19 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:25.74,26.30 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:26.30,28.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:29.2,29.62 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:29.62,31.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:31.17,33.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:34.3,34.19 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:34.19,36.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:38.2,38.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:41.75,42.29 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:42.29,44.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:45.2,45.62 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:45.62,51.44 6 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:51.44,53.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:54.3,59.17 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:59.17,61.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:62.3,62.19 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:62.19,64.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:66.2,66.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:69.76,70.24 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:70.24,72.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:73.2,73.36 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:76.69,77.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:78.19,79.34 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:80.20,81.33 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:82.18,83.51 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:83.51,85.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:86.3,86.26 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:86.26,88.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:89.3,89.35 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:92.2,92.72 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:95.129,99.26 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:99.26,101.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:103.2,104.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:104.16,106.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_contains.go:108.2,108.49 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_create_map.go:7.112,15.37 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_create_map.go:15.37,17.118 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_create_map.go:17.118,20.18 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_create_map.go:20.18,22.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_create_map.go:23.4,23.36 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_create_map.go:25.8,27.17 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_create_map.go:27.17,29.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_create_map.go:30.3,30.35 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_create_map.go:33.2,35.46 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_create_map.go:39.142,46.25 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_create_map.go:46.25,51.3 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_create_map.go:53.2,56.111 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_create_map.go:56.111,68.4 7 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_create_map.go:70.2,70.16 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_create_map.go:70.16,72.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_create_map.go:73.2,78.23 6 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_create_map.go:83.52,85.64 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_create_map.go:85.64,89.3 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_create_map.go:90.2,90.14 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:11.133,14.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:14.16,16.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:16.8,16.44 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:16.44,18.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:20.2,20.71 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:23.113,24.124 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:24.124,26.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:26.17,28.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:29.3,30.61 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:33.2,33.147 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:40.100,50.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:52.73,55.42 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:55.42,58.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:59.2,59.24 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:63.109,67.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:67.16,69.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:70.2,72.69 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:72.69,76.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:76.17,78.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:79.3,82.26 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:82.26,89.4 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:90.3,92.25 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:95.2,95.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:98.99,102.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:102.16,104.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:105.2,108.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:108.16,110.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:112.2,112.69 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:112.69,116.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:116.17,118.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:119.3,121.98 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:124.2,124.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:127.56,130.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:130.16,132.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:134.2,134.51 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:137.105,141.69 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:141.69,146.53 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:146.53,148.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:150.3,151.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:151.17,153.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:155.3,157.25 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:160.2,160.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:163.103,169.69 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:169.69,173.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:173.17,175.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:177.3,177.107 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_datetime.go:180.2,180.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go:8.114,11.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go:11.16,13.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go:15.2,15.74 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go:15.74,18.30 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go:18.30,21.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go:22.3,29.37 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go:29.37,31.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go:31.9,31.45 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go:31.45,33.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go:33.9,35.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go:37.2,37.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go:40.84,42.77 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go:42.77,44.33 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go:44.33,46.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go:46.9,48.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go:50.2,50.46 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go:53.69,59.59 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go:59.59,67.20 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go:67.20,69.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go:71.2,71.28 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go:74.71,80.59 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go:80.59,85.20 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go:85.20,87.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_delete.go:89.2,89.28 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_divide.go:9.109,13.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_divide.go:15.118,19.25 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_divide.go:19.25,21.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_divide.go:23.2,25.54 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_divide.go:25.54,26.57 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_divide.go:26.57,28.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_divide.go:29.8,31.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_divide.go:33.2,33.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_divide.go:36.89,40.38 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_divide.go:40.38,44.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_divide.go:46.2,46.44 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_divide.go:46.44,51.3 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_divide.go:51.8,51.101 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_divide.go:51.101,56.17 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_divide.go:56.17,58.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_divide.go:59.3,60.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_divide.go:60.17,62.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_divide.go:63.3,64.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_divide.go:64.18,66.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_divide.go:66.9,68.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_divide.go:69.3,69.45 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_divide.go:70.8,72.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_divide.go:73.2,73.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_document_index.go:8.119,11.69 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_document_index.go:11.69,15.3 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_document_index.go:16.2,16.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:12.71,13.16 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:14.24,15.46 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:16.25,17.36 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:18.23,19.28 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:20.23,21.29 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:22.24,23.66 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:24.23,25.57 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:26.26,27.28 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:28.23,29.25 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:30.22,31.24 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:33.2,33.26 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:36.89,41.20 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:41.20,43.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:45.2,47.29 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:57.109,65.69 6 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:65.69,69.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:69.17,71.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:75.3,76.98 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:76.98,81.55 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:81.55,83.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:87.3,89.42 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:89.42,91.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:93.3,93.82 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:95.2,95.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:102.48,104.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:105.23,106.29 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:107.23,108.54 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:109.22,110.52 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:111.25,112.31 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:113.29,114.35 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:115.28,116.37 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:117.28,118.38 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:119.22,120.28 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:122.2,122.16 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:126.109,131.20 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:131.20,133.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:135.2,136.69 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:136.69,144.17 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:144.17,146.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:148.3,149.26 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:149.26,151.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:153.3,157.25 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_encoder_decoder.go:159.2,159.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:8.75,17.2 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:19.68,23.59 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:23.59,28.3 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:29.2,29.17 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:32.68,36.59 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:36.59,41.3 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:42.2,42.17 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:45.112,47.69 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:47.69,51.29 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:52.20,53.49 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:55.21,56.49 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:57.11,58.37 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:58.37,60.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:64.2,64.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:67.101,72.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:72.16,74.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:74.8,74.34 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:74.34,76.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:78.2,80.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:80.16,82.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:82.8,82.36 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:82.36,84.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:86.2,86.100 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:90.72,95.59 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:95.59,97.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:97.17,99.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:101.3,101.36 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:103.2,105.18 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:108.114,110.69 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:110.69,114.29 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:115.21,117.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:117.18,119.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:120.4,120.31 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:121.11,122.73 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:126.2,126.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:129.114,133.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:133.16,135.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:137.2,139.71 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:139.71,145.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:145.17,147.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:149.3,152.17 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:152.17,154.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:156.3,158.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:158.17,160.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:161.3,172.17 9 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:172.17,174.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:175.3,175.50 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_entries.go:180.2,180.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_env.go:19.106,28.29 6 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_env.go:28.29,34.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_env.go:34.8,34.27 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_env.go:34.27,36.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_env.go:36.8,38.67 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_env.go:38.67,40.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_env.go:41.3,43.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_env.go:43.17,45.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_env.go:46.3,46.33 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_env.go:49.2,53.46 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_env.go:56.111,59.49 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_env.go:59.49,61.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_env.go:63.2,66.26 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_env.go:66.26,68.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_env.go:68.8,70.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_env.go:72.2,72.69 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_env.go:72.69,75.26 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_env.go:75.26,78.4 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_env.go:80.3,81.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_env.go:81.17,83.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_env.go:84.3,85.27 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_env.go:88.2,88.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_equals.go:3.109,6.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_equals.go:8.134,9.117 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_equals.go:9.117,12.31 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_equals.go:12.31,16.4 3 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_equals.go:16.9,16.24 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_equals.go:16.24,20.12 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_equals.go:20.12,22.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_equals.go:23.4,23.50 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_equals.go:24.9,24.24 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_equals.go:24.24,28.12 4 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_equals.go:28.12,30.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_equals.go:31.4,31.50 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_equals.go:34.3,37.30 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_equals.go:37.30,39.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_equals.go:39.9,39.70 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_equals.go:39.70,41.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_equals.go:42.3,43.11 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_equals.go:43.11,45.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_equals.go:46.3,46.49 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_equals.go:50.112,53.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_error.go:7.108,12.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_error.go:12.16,14.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_error.go:15.2,16.33 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_error.go:16.33,18.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_error.go:19.2,19.44 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_eval.go:7.107,10.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_eval.go:10.16,12.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_eval.go:14.2,17.131 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_eval.go:17.131,21.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_eval.go:21.17,23.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_eval.go:25.3,25.13 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_eval.go:28.2,30.89 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_eval.go:30.89,31.61 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_eval.go:31.61,33.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_eval.go:33.18,35.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_eval.go:36.4,36.46 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_eval.go:40.2,40.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_expression.go:7.113,11.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_expression.go:11.16,13.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_expression.go:15.2,15.45 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_file.go:8.114,13.69 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_file.go:13.69,17.3 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_file.go:19.2,19.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_file.go:22.115,27.69 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_file.go:27.69,31.3 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_file.go:33.2,33.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_filter.go:7.109,11.69 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_filter.go:11.69,15.17 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_filter.go:15.17,17.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_filter.go:18.3,19.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_filter.go:19.17,21.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_filter.go:23.3,25.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_filter.go:25.17,27.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_filter.go:28.3,29.30 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_filter.go:31.2,31.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_flatten.go:11.46,12.16 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_flatten.go:12.16,14.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_flatten.go:15.2,15.31 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_flatten.go:15.31,17.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_flatten.go:18.2,21.36 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_flatten.go:21.36,22.38 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_flatten.go:22.38,24.49 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_flatten.go:24.49,26.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_flatten.go:27.9,29.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_flatten.go:31.2,32.26 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_flatten.go:35.104,40.69 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_flatten.go:40.69,43.41 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_flatten.go:43.41,45.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_flatten.go:47.3,47.32 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_flatten.go:51.2,51.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_group_by.go:10.140,12.37 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_group_by.go:12.37,15.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_group_by.go:15.17,17.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_group_by.go:19.3,21.34 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_group_by.go:21.34,25.4 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_group_by.go:27.3,29.14 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_group_by.go:29.14,32.4 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_group_by.go:33.3,33.41 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_group_by.go:35.2,35.24 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_group_by.go:38.102,43.69 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_group_by.go:43.69,47.41 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_group_by.go:47.41,49.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_group_by.go:51.3,53.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_group_by.go:53.17,55.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_group_by.go:57.3,58.79 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_group_by.go:58.79,61.87 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_group_by.go:61.87,63.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_group_by.go:65.4,65.40 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_group_by.go:68.3,68.31 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_group_by.go:72.2,72.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_has.go:8.106,15.16 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_has.go:15.16,17.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_has.go:19.2,21.34 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_has.go:21.34,24.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_has.go:26.2,26.69 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_has.go:26.69,32.29 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_has.go:33.20,35.81 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_has.go:35.81,37.31 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_has.go:37.31,39.6 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_has.go:41.4,41.72 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_has.go:42.21,44.29 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_has.go:44.29,46.29 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_has.go:46.29,48.6 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_has.go:49.5,49.52 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_has.go:51.4,51.72 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_has.go:52.11,53.62 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_has.go:56.2,56.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_keys.go:8.108,13.69 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_keys.go:13.69,17.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_keys.go:19.2,19.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_keys.go:22.109,27.69 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_keys.go:27.69,30.27 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_keys.go:30.27,32.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_keys.go:35.2,35.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_keys.go:39.107,44.69 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_keys.go:44.69,48.36 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_keys.go:48.36,50.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_keys.go:50.9,50.44 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_keys.go:50.44,52.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_keys.go:52.9,54.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_keys.go:57.3,57.31 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_keys.go:60.2,60.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_keys.go:63.53,65.63 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_keys.go:65.63,67.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_keys.go:68.2,68.76 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_keys.go:71.54,74.34 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_keys.go:74.34,80.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_keys.go:82.2,82.76 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_length.go:8.109,12.69 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_length.go:12.69,16.26 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_length.go:17.19,18.34 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_length.go:18.34,20.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_length.go:20.10,22.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_length.go:23.20,24.40 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_length.go:25.21,26.36 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_length.go:27.11,28.14 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_length.go:31.3,32.27 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_length.go:35.2,35.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_line.go:8.107,13.69 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_line.go:13.69,17.3 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_line.go:19.2,19.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:22.58,27.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:27.16,29.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:31.2,31.86 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:34.73,35.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:35.20,37.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:39.2,40.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:40.16,42.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:43.2,46.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:46.16,48.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:50.2,50.26 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:50.26,53.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:53.8,53.33 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:53.33,57.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:57.8,59.62 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:59.62,61.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:62.3,62.27 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:66.111,76.69 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:76.69,80.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:80.17,82.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:83.3,83.39 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:83.39,85.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:86.3,92.29 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:92.29,94.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:94.9,96.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:97.3,97.17 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:97.17,99.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:101.3,101.38 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_load.go:105.2,105.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_map.go:7.112,9.69 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_map.go:9.69,14.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_map.go:14.17,16.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_map.go:18.3,23.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_map.go:23.17,25.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_map.go:29.2,29.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_map.go:32.106,36.69 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_map.go:36.69,41.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_map.go:41.17,43.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_map.go:45.3,48.17 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_map.go:48.17,50.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_map.go:52.3,54.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_map.go:54.17,56.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_map.go:57.3,59.30 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_map.go:63.2,63.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:10.109,14.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:16.118,20.25 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:20.25,22.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:24.2,26.54 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:26.54,27.57 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:27.57,29.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:30.8,32.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:34.2,34.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:37.89,41.38 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:41.38,45.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:47.2,47.44 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:47.44,52.17 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:52.17,54.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:55.3,56.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:56.17,58.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:59.3,59.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:59.18,61.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:62.3,65.48 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:66.8,66.101 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:66.101,71.17 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:71.17,73.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:74.3,75.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:75.17,77.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:78.3,79.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:79.18,81.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:81.9,83.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:84.3,84.46 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:85.8,87.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_modulo.go:88.2,88.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:17.105,18.72 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:18.72,22.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:25.117,29.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:31.111,34.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:36.122,40.55 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:40.55,43.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:45.2,45.27 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:45.27,47.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:49.2,49.49 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:52.156,53.117 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:53.117,61.26 6 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:61.26,63.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:65.3,68.54 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:68.54,77.4 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:78.3,78.35 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:82.86,86.38 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:86.38,90.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:92.2,92.44 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:92.44,94.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:94.8,94.101 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:94.101,96.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:97.2,97.72 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:100.103,104.17 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:104.17,106.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:106.8,108.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:110.2,111.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:111.16,113.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:114.2,115.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:115.16,117.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:118.2,119.20 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:122.87,129.16 6 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:129.16,131.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:132.2,133.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:133.16,135.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:136.2,137.20 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:140.155,149.16 6 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:149.16,151.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:153.2,154.28 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:154.28,157.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:159.2,159.55 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:159.55,164.33 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:164.33,165.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:168.3,169.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:169.17,171.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:173.3,173.69 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:175.2,175.17 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:178.166,185.52 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:185.52,188.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:188.8,189.53 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:189.53,196.3 6 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:196.8,198.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_multiply.go:199.2,209.12 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_parent.go:5.112,10.69 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_parent.go:10.69,12.30 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_parent.go:12.30,14.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_parent.go:17.2,17.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:8.64,9.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:10.14,11.76 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:12.10,13.95 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:17.88,18.31 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:18.31,20.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:22.2,24.41 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:24.41,25.31 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:25.31,27.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:27.9,27.38 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:27.38,29.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:29.18,31.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:32.4,32.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:33.9,35.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:38.2,38.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:42.110,45.63 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:45.63,47.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:49.2,51.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:51.16,53.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:55.2,55.45 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:55.45,57.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:58.2,62.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:62.16,64.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:66.2,70.69 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:70.69,74.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:74.17,76.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:78.3,78.50 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:78.50,80.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:82.3,92.17 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:92.17,94.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:97.2,97.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:100.111,105.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:105.16,107.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:108.2,108.48 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:108.48,110.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:111.2,113.35 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:113.35,115.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:117.2,119.47 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:119.47,121.27 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:121.27,123.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:124.3,126.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:126.17,128.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:130.3,140.17 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:140.17,142.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:146.2,146.28 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:150.110,155.69 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:155.69,162.58 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:162.58,165.4 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:166.3,167.25 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_path.go:170.2,170.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go:8.78,11.66 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go:11.66,15.22 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go:15.22,19.4 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go:22.2,25.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go:28.92,31.66 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go:31.66,33.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go:33.17,35.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go:37.3,37.64 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go:37.64,39.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go:42.2,45.21 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go:48.107,53.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go:53.16,55.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go:56.2,57.50 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go:57.50,59.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go:61.2,63.69 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go:63.69,68.31 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go:68.31,70.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go:70.9,70.39 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go:70.39,72.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go:72.18,74.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go:76.9,78.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go:80.3,81.32 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pick.go:84.2,84.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pipe.go:3.107,5.72 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pipe.go:5.72,7.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pipe.go:8.2,9.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pipe.go:9.16,11.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pipe.go:12.2,14.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pipe.go:14.16,16.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_pipe.go:17.2,17.53 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_recursive_descent.go:12.119,17.16 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_recursive_descent.go:17.16,19.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_recursive_descent.go:21.2,21.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_recursive_descent.go:24.106,25.69 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_recursive_descent.go:25.69,32.65 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_recursive_descent.go:32.65,36.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_recursive_descent.go:36.18,38.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_recursive_descent.go:39.4,40.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_recursive_descent.go:40.18,42.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_recursive_descent.go:45.2,45.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_reduce.go:8.109,18.72 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_reduce.go:18.72,20.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_reduce.go:20.8,20.70 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_reduce.go:20.70,22.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_reduce.go:24.2,27.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_reduce.go:27.16,29.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_reduce.go:31.2,36.16 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_reduce.go:36.16,38.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_reduce.go:40.2,43.67 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_reduce.go:43.67,51.17 7 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_reduce.go:51.17,53.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_reduce.go:56.2,56.19 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_reverse.go:8.110,11.69 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_reverse.go:11.69,16.41 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_reverse.go:16.41,18.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_reverse.go:20.3,23.54 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_reverse.go:23.54,25.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_reverse.go:26.3,27.32 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_reverse.go:31.2,31.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_select.go:7.109,12.69 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_select.go:12.69,16.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_select.go:16.17,18.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_select.go:21.3,23.90 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_select.go:23.90,26.21 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_select.go:26.21,27.10 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_select.go:31.3,31.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_select.go:31.20,33.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_select.go:35.2,35.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_self.go:3.107,5.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_shuffle.go:9.110,18.69 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_shuffle.go:18.69,23.41 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_shuffle.go:23.41,25.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_shuffle.go:27.3,31.41 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_shuffle.go:31.41,31.68 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_shuffle.go:33.3,33.27 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_shuffle.go:35.2,35.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_slice.go:8.126,10.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_slice.go:10.16,12.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_slice.go:13.2,13.37 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_slice.go:13.37,15.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_slice.go:16.2,16.76 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_slice.go:19.113,27.69 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_slice.go:27.69,32.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_slice.go:32.17,34.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_slice.go:35.3,36.30 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_slice.go:36.30,38.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_slice.go:40.3,41.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_slice.go:41.17,43.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_slice.go:45.3,46.31 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_slice.go:46.31,48.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_slice.go:48.9,48.57 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_slice.go:48.57,50.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_slice.go:52.3,55.63 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_slice.go:55.63,57.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_slice.go:59.3,61.35 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_slice.go:67.2,67.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:12.107,16.2 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:20.109,24.69 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:24.69,29.41 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:29.41,31.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:33.3,35.54 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:35.54,38.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:38.18,40.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:42.4,42.132 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:46.3,50.44 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:50.44,52.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:53.3,53.31 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:55.2,55.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:66.43,66.60 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:67.43,67.70 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:69.48,74.100 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:74.100,80.17 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:80.17,82.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:82.9,82.24 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:82.24,84.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:86.3,86.23 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:88.2,88.14 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:91.103,95.38 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:95.38,98.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:100.2,100.38 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:100.38,103.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:105.2,108.49 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:108.49,112.3 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:114.2,114.46 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:114.46,116.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:116.8,116.53 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:116.53,118.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:118.8,118.53 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:118.53,120.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:120.8,120.53 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:120.53,122.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:122.8,122.53 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:122.53,126.29 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:126.29,128.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:128.9,128.23 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:128.23,130.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:131.3,131.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:132.8,132.23 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:132.23,134.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:134.17,137.4 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:138.3,139.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:139.17,142.4 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:143.3,143.29 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:143.29,145.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:145.9,145.37 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:145.37,147.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:149.3,149.11 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:150.8,150.51 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:150.51,152.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:152.17,153.14 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:155.3,156.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:156.17,157.14 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:159.3,159.30 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:160.8,160.101 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:160.101,162.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:162.17,163.14 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:165.3,166.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:166.17,167.14 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:169.3,169.23 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:169.23,171.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:171.9,171.29 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:171.29,173.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:175.3,175.11 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort.go:178.2,178.46 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort_keys.go:7.111,9.69 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort_keys.go:9.69,12.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort_keys.go:12.17,14.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort_keys.go:16.3,16.86 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort_keys.go:16.86,18.32 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort_keys.go:18.32,20.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort_keys.go:21.4,21.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort_keys.go:21.18,23.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort_keys.go:27.2,27.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort_keys.go:30.36,35.59 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort_keys.go:35.59,41.3 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort_keys.go:42.2,44.55 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort_keys.go:44.55,48.3 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_sort_keys.go:52.2,52.30 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_split_document.go:3.116,7.69 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_split_document.go:7.69,12.3 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_split_document.go:14.2,14.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:14.112,16.69 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:16.69,21.47 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:21.47,23.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:25.3,27.34 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:31.2,31.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:34.113,38.69 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:38.69,43.47 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:43.47,45.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:47.3,48.24 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:48.24,50.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:50.9,52.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:53.3,55.34 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:59.2,59.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:63.116,68.16 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:68.16,70.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:71.2,71.45 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:71.45,73.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:75.2,78.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:78.16,80.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:81.2,81.51 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:81.51,83.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:85.2,85.36 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:88.99,91.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:93.119,101.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:101.16,103.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:105.2,106.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:106.16,108.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:110.2,112.69 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:112.69,116.47 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:116.47,118.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:120.3,121.27 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:124.2,124.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:128.98,133.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:133.16,138.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:138.8,142.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:144.2,150.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:150.16,155.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:156.2,156.19 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:163.104,167.23 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:167.23,170.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:170.8,173.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:175.2,176.31 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:179.123,185.52 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:185.52,187.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:189.2,189.37 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:189.37,192.39 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:192.39,196.4 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:198.3,201.25 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:207.125,213.52 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:213.52,215.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:217.2,217.37 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:217.37,221.39 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:221.39,228.18 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:228.18,230.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:230.10,232.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:233.4,233.53 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:236.3,236.33 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:242.141,248.63 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:248.63,252.17 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:252.17,254.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:255.3,256.52 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:256.52,258.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:259.3,259.39 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:259.39,262.4 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:263.3,263.39 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:263.39,265.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:266.3,266.25 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:266.25,268.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:271.2,272.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:272.16,274.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:275.2,277.45 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:277.45,279.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:280.2,282.31 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:285.108,287.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:287.16,289.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:291.2,293.69 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:293.69,297.47 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:297.47,299.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:301.3,301.59 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:304.2,304.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:307.110,309.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:309.16,311.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:313.2,315.69 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:315.69,319.47 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:319.47,321.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:322.3,322.61 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:326.2,326.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:329.107,331.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:331.16,333.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:335.2,337.69 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:337.69,341.47 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:341.47,343.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:344.3,345.72 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:349.2,349.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:352.113,357.16 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:357.16,359.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:360.2,360.38 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:360.38,362.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:364.2,366.69 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:366.69,369.32 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:369.32,371.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:372.3,373.27 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:376.2,376.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:379.76,381.31 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:381.31,383.27 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:383.27,385.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:386.3,386.45 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:389.2,389.66 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:392.114,397.16 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:397.16,399.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:400.2,400.38 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:400.38,402.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:404.2,406.69 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:406.69,409.27 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:409.27,410.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:413.3,413.47 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:413.47,415.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:416.3,419.27 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:422.2,422.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:425.75,428.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:428.17,433.38 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:433.38,435.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_strings.go:438.2,438.40 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:8.52,9.29 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:9.29,11.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:11.8,11.36 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:11.36,13.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:13.8,13.36 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:13.36,15.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:15.8,15.37 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:15.37,17.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:17.8,17.36 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:17.36,19.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:19.8,19.34 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:19.34,21.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:21.8,21.30 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:21.30,23.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:24.2,24.15 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:27.114,31.44 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:31.44,33.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:33.17,35.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:37.3,37.39 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:37.39,39.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:39.18,41.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:45.2,47.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:47.16,49.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:51.2,51.65 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:51.65,54.44 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:54.44,56.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:56.18,58.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:60.4,60.40 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:60.40,62.19 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:62.19,64.6 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:68.3,68.26 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:71.2,71.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:74.111,79.69 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:79.69,82.26 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:83.20,84.20 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:85.26,86.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:87.26,88.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:89.21,90.21 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:91.20,92.20 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:93.18,94.18 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:95.10,96.14 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:97.11,98.23 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:100.3,101.27 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_style.go:104.2,104.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:10.81,14.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:16.117,18.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:20.111,24.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:26.84,29.66 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:29.66,31.84 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:31.84,32.68 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:32.68,34.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:36.3,36.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:36.20,38.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:41.2,42.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:45.118,51.29 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:51.29,53.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:55.2,57.22 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:58.19,59.67 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:60.20,61.31 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:61.31,63.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:64.3,64.33 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:65.18,66.29 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:66.29,68.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:69.3,71.72 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:71.72,73.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:76.2,76.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:79.108,83.38 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:83.38,87.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:89.2,89.38 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:89.38,92.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:94.2,96.70 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:96.70,99.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:101.2,101.16 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:101.16,103.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:103.8,103.30 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:103.30,105.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:105.8,105.51 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:105.51,107.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:107.17,109.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:110.3,111.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:111.17,113.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:114.3,116.45 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:117.8,117.101 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:117.101,119.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:119.17,121.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:122.3,123.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:123.17,125.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:126.3,127.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:127.18,129.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:129.9,131.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:132.3,132.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:133.8,135.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:137.2,137.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:140.107,142.39 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:142.39,144.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:144.8,146.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:147.2,149.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:149.16,151.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:153.2,154.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:154.16,156.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_subtract.go:158.2,160.12 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_tag.go:7.112,12.44 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_tag.go:12.44,14.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_tag.go:14.17,16.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_tag.go:18.3,18.39 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_tag.go:18.39,20.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_tag.go:23.2,25.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_tag.go:25.16,27.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_tag.go:29.2,29.65 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_tag.go:29.65,32.44 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_tag.go:32.44,34.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_tag.go:34.18,36.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_tag.go:38.4,38.40 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_tag.go:38.40,40.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_tag.go:42.3,42.39 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_tag.go:45.2,45.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_tag.go:48.109,53.69 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_tag.go:53.69,57.3 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_tag.go:59.2,59.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:18.73,20.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:22.115,26.69 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:26.69,28.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:28.17,30.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:31.3,31.33 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:34.2,34.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:37.103,40.88 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:40.88,43.33 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:44.19,46.36 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:47.11,49.35 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:51.3,51.24 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:54.2,54.27 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:55.19,57.143 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:59.20,61.93 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:63.17,66.52 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:67.10,68.25 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:72.116,79.133 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:79.133,81.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:83.2,84.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:84.16,86.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:90.2,92.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:92.16,94.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:95.2,97.49 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:97.49,99.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:100.2,106.16 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:106.16,108.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:109.2,109.56 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:112.133,114.69 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:114.69,117.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:117.17,119.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:120.3,120.41 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:123.2,123.51 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:126.156,127.34 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:127.34,133.73 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:133.73,135.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:138.2,138.36 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:138.36,141.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:141.8,141.46 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:141.46,143.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:143.8,143.45 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:143.45,145.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:146.2,147.24 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:150.145,151.23 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:151.23,153.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:155.2,157.36 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:157.36,160.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:160.17,162.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:163.3,163.41 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:166.2,166.29 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:169.130,173.23 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:173.23,176.63 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:176.63,178.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:179.3,179.25 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:183.2,183.36 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:183.36,186.43 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:186.43,187.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:189.3,189.17 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:189.17,191.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:192.3,194.30 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:194.30,195.26 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:195.26,198.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:200.4,202.37 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:205.3,205.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:205.21,207.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:209.3,209.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:209.21,211.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:213.3,213.48 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:215.2,215.24 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:218.60,220.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:222.147,226.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:226.16,228.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:230.2,230.89 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:230.89,238.37 6 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:238.37,240.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:242.3,244.27 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:244.27,246.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:247.3,247.34 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:247.34,249.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:252.2,254.58 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:254.58,257.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:258.2,258.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:261.139,268.59 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:268.59,273.53 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:273.53,276.18 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:276.18,278.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:279.9,279.49 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:279.49,281.28 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:281.28,284.5 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:285.4,285.35 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:285.35,288.5 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:292.2,292.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:295.146,296.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:297.17,298.38 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:298.38,300.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:301.3,301.73 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:302.20,303.44 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:303.44,305.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:305.18,307.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:310.2,310.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_traverse_path.go:313.115,317.2 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_union.go:5.108,9.16 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_union.go:9.16,11.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_union.go:12.2,17.16 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_union.go:17.16,19.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_union.go:20.2,24.65 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_union.go:24.65,27.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_union.go:32.2,32.44 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_union.go:32.44,34.66 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_union.go:34.66,39.4 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_union.go:41.2,42.21 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_unique.go:10.101,15.2 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_unique.go:17.103,22.69 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_unique.go:22.69,26.41 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_unique.go:26.41,28.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_unique.go:30.3,31.47 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_unique.go:31.47,34.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_unique.go:34.18,36.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_unique.go:38.4,40.35 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_unique.go:40.35,44.5 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_unique.go:46.4,48.15 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_unique.go:48.15,50.5 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_unique.go:52.3,53.59 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_unique.go:53.59,55.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_unique.go:57.3,57.31 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_unique.go:60.2,60.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_value.go:5.112,7.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_value.go:9.108,11.38 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_value.go:11.38,14.3 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_value.go:16.2,18.69 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_value.go:18.69,21.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_value.go:23.2,23.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:8.114,12.19 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:12.19,14.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:15.2,15.42 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:22.103,24.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:28.104,32.89 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:32.89,34.27 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:34.27,35.9 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:38.2,38.25 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:38.25,40.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:42.2,42.69 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:42.69,44.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:44.17,46.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:47.3,47.45 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:49.2,49.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:52.115,56.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:56.16,58.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:59.2,59.68 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:59.68,61.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:62.2,69.65 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:69.65,72.24 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:72.24,74.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:74.9,77.4 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:78.3,83.17 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:83.17,85.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:86.3,87.42 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:91.2,91.34 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:91.34,93.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_variables.go:95.2,95.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_with.go:5.107,9.63 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_with.go:9.63,11.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_with.go:13.2,17.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_with.go:17.16,19.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_with.go:21.2,23.75 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_with.go:23.75,26.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_with.go:26.17,28.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operator_with.go:32.2,32.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:15.150,17.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:17.16,19.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:27.2,28.66 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:29.25,30.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:31.27,32.68 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:35.2,37.65 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:37.65,47.17 7 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:47.17,49.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:51.2,51.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:54.108,57.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:61.170,63.33 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:63.33,65.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:65.17,67.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:67.9,67.27 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:67.27,70.4 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:73.2,74.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:74.16,76.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:78.2,78.57 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:78.57,80.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:80.17,82.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:83.3,83.29 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:83.29,85.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:86.3,86.13 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:89.2,89.85 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:89.85,91.39 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:91.39,93.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:94.3,95.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:95.17,97.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:98.3,98.29 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:98.29,100.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:102.2,102.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:113.138,116.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:116.16,118.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:119.2,121.57 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:121.57,123.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:123.17,125.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:128.2,128.65 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:128.65,132.17 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:132.17,134.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:137.2,137.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:140.166,143.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:145.149,149.89 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:149.89,151.27 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:151.27,152.9 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:156.2,156.25 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:156.25,159.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:161.2,163.89 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:163.89,165.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:165.17,167.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:168.3,168.51 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:171.2,171.43 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:174.78,176.12 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:176.12,178.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:179.2,180.20 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:180.20,183.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:185.2,185.13 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:188.113,189.20 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:189.20,191.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:191.8,191.27 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:191.27,193.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:193.16,195.18 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:195.18,196.15 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:198.4,199.41 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:201.3,201.164 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/operators.go:204.2,208.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:36.73,37.16 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:38.26,39.31 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:40.19,41.31 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:42.34,43.32 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:44.18,45.30 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:46.18,47.30 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:48.18,49.30 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:50.14,51.31 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:52.26,53.41 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:54.10,55.106 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:71.71,79.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:81.61,85.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:87.56,89.2 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:91.49,93.2 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:95.81,99.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:101.37,104.54 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:104.54,106.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:106.8,106.63 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:106.63,108.3 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:111.71,114.30 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:114.30,117.3 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:119.2,119.35 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:119.35,123.17 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:123.17,125.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:126.3,126.40 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:129.2,129.25 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:129.25,134.3 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:136.2,136.61 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:136.61,142.26 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:142.26,144.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:146.3,149.136 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:149.136,150.67 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:150.67,152.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:155.3,157.21 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:157.21,159.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:161.3,161.94 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:161.94,163.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:165.3,165.61 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:165.61,167.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:169.3,169.21 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:169.21,172.49 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:172.49,176.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:177.4,177.59 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:177.59,179.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:180.4,180.53 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:180.53,182.5 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:185.3,186.40 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:186.40,188.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:189.3,189.38 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:193.2,193.29 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:193.29,195.17 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:195.17,197.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:199.3,202.17 4 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:202.17,204.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:205.3,205.40 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:205.40,207.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer.go:210.2,210.12 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer_writer.go:19.61,23.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer_writer.go:25.86,27.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/printer_writer.go:36.98,39.16 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer_writer.go:40.24,41.21 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer_writer.go:42.25,43.27 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer_writer.go:46.2,51.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer_writer.go:54.83,62.16 6 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer_writer.go:62.16,64.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer_writer.go:65.2,65.36 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer_writer.go:65.36,67.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer_writer.go:68.2,69.40 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer_writer.go:69.40,71.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer_writer.go:73.2,75.16 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer_writer.go:75.16,77.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/printer_writer.go:78.2,80.32 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:25.43,27.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:29.81,31.16 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:31.16,33.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:34.2,39.25 5 0
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:39.25,41.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:42.2,42.51 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:45.120,48.16 3 0
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:48.16,50.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:52.2,52.37 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:52.37,55.17 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:55.17,57.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:58.3,59.17 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:59.17,61.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:62.3,64.34 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:65.17,66.27 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:70.2,70.27 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:70.27,73.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:75.2,75.12 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:78.141,82.16 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:82.16,84.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:85.2,85.6 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:85.6,88.38 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:88.38,91.4 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:91.9,91.33 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:91.33,93.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:94.3,102.26 7 1
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:102.26,104.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:105.3,107.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:107.17,109.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/stream_evaluator.go:110.3,110.34 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/string_evaluator.go:22.43,26.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/string_evaluator.go:28.119,36.16 5 1
+github.com/mikefarah/yq/v4/pkg/yqlib/string_evaluator.go:36.16,38.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/string_evaluator.go:40.2,44.16 4 1
+github.com/mikefarah/yq/v4/pkg/yqlib/string_evaluator.go:44.16,46.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/string_evaluator.go:47.2,47.6 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/string_evaluator.go:47.6,50.38 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/string_evaluator.go:50.38,53.4 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/string_evaluator.go:53.9,53.33 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/string_evaluator.go:53.33,55.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/string_evaluator.go:56.3,63.26 6 1
+github.com/mikefarah/yq/v4/pkg/yqlib/string_evaluator.go:63.26,65.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/string_evaluator.go:66.3,68.17 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/string_evaluator.go:68.17,70.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/string_evaluator.go:71.3,71.34 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/utils.go:12.53,14.21 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/utils.go:14.21,16.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/utils.go:16.8,20.17 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/utils.go:20.17,22.4 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/utils.go:23.3,23.33 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/utils.go:25.2,25.20 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/utils.go:29.54,32.2 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/utils.go:34.107,36.16 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/utils.go:36.16,38.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/utils.go:39.2,42.6 3 1
+github.com/mikefarah/yq/v4/pkg/yqlib/utils.go:42.6,45.38 2 1
+github.com/mikefarah/yq/v4/pkg/yqlib/utils.go:45.38,46.35 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/utils.go:47.18,48.28 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/utils.go:50.4,50.25 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/utils.go:51.9,51.33 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/utils.go:51.33,53.4 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/utils.go:54.3,61.34 6 1
+github.com/mikefarah/yq/v4/pkg/yqlib/write_in_place_handler.go:17.67,20.2 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/write_in_place_handler.go:22.70,25.16 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/write_in_place_handler.go:25.16,27.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/write_in_place_handler.go:28.2,29.16 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/write_in_place_handler.go:29.16,31.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/write_in_place_handler.go:32.2,34.16 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/write_in_place_handler.go:34.16,36.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/write_in_place_handler.go:38.2,38.47 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/write_in_place_handler.go:38.47,40.3 1 0
+github.com/mikefarah/yq/v4/pkg/yqlib/write_in_place_handler.go:41.2,43.18 3 0
+github.com/mikefarah/yq/v4/pkg/yqlib/write_in_place_handler.go:46.88,49.27 3 0
+github.com/mikefarah/yq/v4/pkg/yqlib/write_in_place_handler.go:49.27,52.3 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/write_in_place_handler.go:53.2,55.12 2 0
+github.com/mikefarah/yq/v4/pkg/yqlib/xml.go:15.48,27.2 1 1
+github.com/mikefarah/yq/v4/pkg/yqlib/yaml.go:10.50,17.2 1 1
diff --git a/pkg/yqlib/csv_test.go b/pkg/yqlib/csv_test.go
index df287390..66bc5de7 100644
--- a/pkg/yqlib/csv_test.go
+++ b/pkg/yqlib/csv_test.go
@@ -119,6 +119,22 @@ var csvScenarios = []formatScenario{
expected: csvMissing,
scenarioType: "roundtrip-csv",
},
+ {
+ description: "decode csv key",
+ skipDoc: true,
+ input: csvSimple,
+ expression: ".[0].name | key",
+ expected: "name\n",
+ scenarioType: "decode-csv-object",
+ },
+ {
+ description: "decode csv parent",
+ skipDoc: true,
+ input: csvSimple,
+ expression: ".[0].name | parent | .height",
+ expected: "168.8\n",
+ scenarioType: "decode-csv-object",
+ },
{
description: "Parse CSV into an array of objects",
subdescription: "First row is assumed to be the header row.",
diff --git a/pkg/yqlib/data_tree_navigator.go b/pkg/yqlib/data_tree_navigator.go
index 986c129d..9a246027 100644
--- a/pkg/yqlib/data_tree_navigator.go
+++ b/pkg/yqlib/data_tree_navigator.go
@@ -4,7 +4,6 @@ import (
"fmt"
logging "gopkg.in/op/go-logging.v1"
- yaml "gopkg.in/yaml.v3"
)
type DataTreeNavigator interface {
@@ -13,7 +12,7 @@ type DataTreeNavigator interface {
// a new context of matching candidates
GetMatchingNodes(context Context, expressionNode *ExpressionNode) (Context, error)
- DeeplyAssign(context Context, path []interface{}, rhsNode *yaml.Node) error
+ DeeplyAssign(context Context, path []interface{}, rhsNode *CandidateNode) error
}
type dataTreeNavigator struct {
@@ -23,12 +22,7 @@ func NewDataTreeNavigator() DataTreeNavigator {
return &dataTreeNavigator{}
}
-func (d *dataTreeNavigator) DeeplyAssign(context Context, path []interface{}, rhsNode *yaml.Node) error {
-
- rhsCandidateNode := &CandidateNode{
- Path: path,
- Node: rhsNode,
- }
+func (d *dataTreeNavigator) DeeplyAssign(context Context, path []interface{}, rhsCandidateNode *CandidateNode) error {
assignmentOp := &Operation{OperationType: assignOpType, Preferences: assignPreferences{}}
@@ -55,7 +49,6 @@ func (d *dataTreeNavigator) GetMatchingNodes(context Context, expressionNode *Ex
log.Debug(NodeToString(el.Value.(*CandidateNode)))
}
}
- log.Debug(">>")
handler := expressionNode.Operation.OperationType.Handler
if handler != nil {
return handler(d, context, expressionNode)
diff --git a/pkg/yqlib/decoder_base64.go b/pkg/yqlib/decoder_base64.go
index f1cace87..50ed3507 100644
--- a/pkg/yqlib/decoder_base64.go
+++ b/pkg/yqlib/decoder_base64.go
@@ -5,8 +5,6 @@ import (
"encoding/base64"
"io"
"strings"
-
- yaml "gopkg.in/yaml.v3"
)
type base64Padder struct {
@@ -70,11 +68,5 @@ func (dec *base64Decoder) Decode() (*CandidateNode, error) {
}
}
dec.readAnything = true
- return &CandidateNode{
- Node: &yaml.Node{
- Kind: yaml.ScalarNode,
- Tag: "!!str",
- Value: buf.String(),
- },
- }, nil
+ return createStringScalarNode(buf.String()), nil
}
diff --git a/pkg/yqlib/decoder_csv_object.go b/pkg/yqlib/decoder_csv_object.go
index e8e78023..644bbfa1 100644
--- a/pkg/yqlib/decoder_csv_object.go
+++ b/pkg/yqlib/decoder_csv_object.go
@@ -6,7 +6,6 @@ import (
"io"
"github.com/dimchansky/utfbom"
- yaml "gopkg.in/yaml.v3"
)
type csvObjectDecoder struct {
@@ -28,7 +27,7 @@ func (dec *csvObjectDecoder) Init(reader io.Reader) error {
return nil
}
-func (dec *csvObjectDecoder) convertToYamlNode(content string) *yaml.Node {
+func (dec *csvObjectDecoder) convertToNode(content string) *CandidateNode {
node, err := parseSnippet(content)
if err != nil {
return createScalarNode(content, content)
@@ -36,14 +35,11 @@ func (dec *csvObjectDecoder) convertToYamlNode(content string) *yaml.Node {
return node
}
-func (dec *csvObjectDecoder) createObject(headerRow []string, contentRow []string) *yaml.Node {
- objectNode := &yaml.Node{Kind: yaml.MappingNode, Tag: "!!map"}
+func (dec *csvObjectDecoder) createObject(headerRow []string, contentRow []string) *CandidateNode {
+ objectNode := &CandidateNode{Kind: MappingNode, Tag: "!!map"}
for i, header := range headerRow {
- objectNode.Content = append(
- objectNode.Content,
- createScalarNode(header, header),
- dec.convertToYamlNode(contentRow[i]))
+ objectNode.AddKeyValueChild(createScalarNode(header, header), dec.convertToNode(contentRow[i]))
}
return objectNode
}
@@ -58,13 +54,13 @@ func (dec *csvObjectDecoder) Decode() (*CandidateNode, error) {
return nil, err
}
- rootArray := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
+ rootArray := &CandidateNode{Kind: SequenceNode, Tag: "!!seq"}
contentRow, err := dec.reader.Read()
for err == nil && len(contentRow) > 0 {
log.Debugf("Adding contentRow: %v", contentRow)
- rootArray.Content = append(rootArray.Content, dec.createObject(headerRow, contentRow))
+ rootArray.AddChild(dec.createObject(headerRow, contentRow))
contentRow, err = dec.reader.Read()
log.Debugf("Read next contentRow: %v, %v", contentRow, err)
}
@@ -72,10 +68,5 @@ func (dec *csvObjectDecoder) Decode() (*CandidateNode, error) {
return nil, err
}
- return &CandidateNode{
- Node: &yaml.Node{
- Kind: yaml.DocumentNode,
- Content: []*yaml.Node{rootArray},
- },
- }, nil
+ return rootArray, nil
}
diff --git a/pkg/yqlib/decoder_goccy_yaml.go b/pkg/yqlib/decoder_goccy_yaml.go
new file mode 100644
index 00000000..7494d7cd
--- /dev/null
+++ b/pkg/yqlib/decoder_goccy_yaml.go
@@ -0,0 +1,42 @@
+//go:build !yq_noyaml
+
+package yqlib
+
+import (
+ "io"
+
+ yaml "github.com/goccy/go-yaml"
+ "github.com/goccy/go-yaml/ast"
+)
+
+type goccyYamlDecoder struct {
+ decoder yaml.Decoder
+ cm yaml.CommentMap
+}
+
+func NewGoccyYAMLDecoder() Decoder {
+ return &goccyYamlDecoder{}
+}
+
+func (dec *goccyYamlDecoder) Init(reader io.Reader) error {
+ dec.cm = yaml.CommentMap{}
+ dec.decoder = *yaml.NewDecoder(reader, yaml.CommentToMap(dec.cm), yaml.UseOrderedMap())
+ return nil
+}
+
+func (dec *goccyYamlDecoder) Decode() (*CandidateNode, error) {
+
+ var ast ast.Node
+
+ err := dec.decoder.Decode(&ast)
+ if err != nil {
+ return nil, err
+ }
+
+ candidateNode := &CandidateNode{}
+ if err := candidateNode.UnmarshalGoccyYAML(ast, dec.cm); err != nil {
+ return nil, err
+ }
+
+ return candidateNode, nil
+}
diff --git a/pkg/yqlib/decoder_json.go b/pkg/yqlib/decoder_json.go
index ea712bfc..16a662a5 100644
--- a/pkg/yqlib/decoder_json.go
+++ b/pkg/yqlib/decoder_json.go
@@ -3,11 +3,9 @@
package yqlib
import (
- "fmt"
"io"
"github.com/goccy/go-json"
- yaml "gopkg.in/yaml.v3"
)
type jsonDecoder struct {
@@ -25,76 +23,11 @@ func (dec *jsonDecoder) Init(reader io.Reader) error {
func (dec *jsonDecoder) Decode() (*CandidateNode, error) {
- var dataBucket orderedMap
- log.Debug("going to decode")
+ var dataBucket CandidateNode
err := dec.decoder.Decode(&dataBucket)
if err != nil {
return nil, err
}
- node, err := dec.convertToYamlNode(&dataBucket)
- if err != nil {
- return nil, err
- }
-
- return &CandidateNode{
- Node: &yaml.Node{
- Kind: yaml.DocumentNode,
- Content: []*yaml.Node{node},
- },
- }, nil
-}
-
-func (dec *jsonDecoder) convertToYamlNode(data *orderedMap) (*yaml.Node, error) {
- if data == nil {
- return createScalarNode(nil, "null"), nil
- }
- if data.kv == nil {
- switch rawData := data.altVal.(type) {
- case nil:
- return createScalarNode(nil, "null"), nil
- case float64, float32:
- // json decoder returns ints as float.'
- intNum := int(rawData.(float64))
-
- // if the integer representation is the same as the original
- // then its an int.
- if float64(intNum) == rawData.(float64) {
- return createScalarNode(intNum, fmt.Sprintf("%v", intNum)), nil
- }
-
- return createScalarNode(rawData, fmt.Sprintf("%v", rawData)), nil
- case int, int64, int32, string, bool:
- return createScalarNode(rawData, fmt.Sprintf("%v", rawData)), nil
- case []*orderedMap:
- return dec.parseArray(rawData)
- default:
- return nil, fmt.Errorf("unrecognised type :( %v", rawData)
- }
- }
-
- var yamlMap = &yaml.Node{Kind: yaml.MappingNode, Tag: "!!map"}
- for i, keyValuePair := range data.kv {
- yamlValue, err := dec.convertToYamlNode(&data.kv[i].V)
- if err != nil {
- return nil, err
- }
- yamlMap.Content = append(yamlMap.Content, createScalarNode(keyValuePair.K, keyValuePair.K), yamlValue)
- }
- return yamlMap, nil
-
-}
-
-func (dec *jsonDecoder) parseArray(dataArray []*orderedMap) (*yaml.Node, error) {
-
- var yamlMap = &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
-
- for _, value := range dataArray {
- yamlValue, err := dec.convertToYamlNode(value)
- if err != nil {
- return nil, err
- }
- yamlMap.Content = append(yamlMap.Content, yamlValue)
- }
- return yamlMap, nil
+ return &dataBucket, nil
}
diff --git a/pkg/yqlib/decoder_lua.go b/pkg/yqlib/decoder_lua.go
index efc04eac..b37be846 100644
--- a/pkg/yqlib/decoder_lua.go
+++ b/pkg/yqlib/decoder_lua.go
@@ -8,7 +8,6 @@ import (
"math"
lua "github.com/yuin/gopher-lua"
- yaml "gopkg.in/yaml.v3"
)
type luaDecoder struct {
@@ -28,17 +27,17 @@ func (dec *luaDecoder) Init(reader io.Reader) error {
return nil
}
-func (dec *luaDecoder) convertToYamlNode(ls *lua.LState, lv lua.LValue) *yaml.Node {
+func (dec *luaDecoder) convertToYamlNode(ls *lua.LState, lv lua.LValue) *CandidateNode {
switch lv.Type() {
case lua.LTNil:
- return &yaml.Node{
- Kind: yaml.ScalarNode,
+ return &CandidateNode{
+ Kind: ScalarNode,
Tag: "!!null",
Value: "",
}
case lua.LTBool:
- return &yaml.Node{
- Kind: yaml.ScalarNode,
+ return &CandidateNode{
+ Kind: ScalarNode,
Tag: "!!bool",
Value: lv.String(),
}
@@ -46,22 +45,22 @@ func (dec *luaDecoder) convertToYamlNode(ls *lua.LState, lv lua.LValue) *yaml.No
n := float64(lua.LVAsNumber(lv))
// various special case floats
if math.IsNaN(n) {
- return &yaml.Node{
- Kind: yaml.ScalarNode,
+ return &CandidateNode{
+ Kind: ScalarNode,
Tag: "!!float",
Value: ".nan",
}
}
if math.IsInf(n, 1) {
- return &yaml.Node{
- Kind: yaml.ScalarNode,
+ return &CandidateNode{
+ Kind: ScalarNode,
Tag: "!!float",
Value: ".inf",
}
}
if math.IsInf(n, -1) {
- return &yaml.Node{
- Kind: yaml.ScalarNode,
+ return &CandidateNode{
+ Kind: ScalarNode,
Tag: "!!float",
Value: "-.inf",
}
@@ -69,27 +68,27 @@ func (dec *luaDecoder) convertToYamlNode(ls *lua.LState, lv lua.LValue) *yaml.No
// does it look like an integer?
if n == float64(int(n)) {
- return &yaml.Node{
- Kind: yaml.ScalarNode,
+ return &CandidateNode{
+ Kind: ScalarNode,
Tag: "!!int",
Value: lv.String(),
}
}
- return &yaml.Node{
- Kind: yaml.ScalarNode,
+ return &CandidateNode{
+ Kind: ScalarNode,
Tag: "!!float",
Value: lv.String(),
}
case lua.LTString:
- return &yaml.Node{
- Kind: yaml.ScalarNode,
+ return &CandidateNode{
+ Kind: ScalarNode,
Tag: "!!str",
Value: lv.String(),
}
case lua.LTFunction:
- return &yaml.Node{
- Kind: yaml.ScalarNode,
+ return &CandidateNode{
+ Kind: ScalarNode,
Tag: "tag:lua.org,2006,function",
Value: lv.String(),
}
@@ -97,12 +96,12 @@ func (dec *luaDecoder) convertToYamlNode(ls *lua.LState, lv lua.LValue) *yaml.No
// Simultaneously create a sequence and a map, pick which one to return
// based on whether all keys were consecutive integers
i := 1
- yaml_sequence := &yaml.Node{
- Kind: yaml.SequenceNode,
+ yaml_sequence := &CandidateNode{
+ Kind: SequenceNode,
Tag: "!!seq",
}
- yaml_map := &yaml.Node{
- Kind: yaml.MappingNode,
+ yaml_map := &CandidateNode{
+ Kind: MappingNode,
Tag: "!!map",
}
t := lv.(*lua.LTable)
@@ -113,11 +112,13 @@ func (dec *luaDecoder) convertToYamlNode(ls *lua.LState, lv lua.LValue) *yaml.No
} else {
i = 0
}
- yaml_map.Content = append(yaml_map.Content, dec.convertToYamlNode(ls, k))
+ newKey := dec.convertToYamlNode(ls, k)
+
yv := dec.convertToYamlNode(ls, v)
- yaml_map.Content = append(yaml_map.Content, yv)
+ yaml_map.AddKeyValueChild(newKey, yv)
+
if i != 0 {
- yaml_sequence.Content = append(yaml_sequence.Content, yv)
+ yaml_sequence.AddChild(yv)
}
k, v = ls.Next(t, k)
}
@@ -126,8 +127,8 @@ func (dec *luaDecoder) convertToYamlNode(ls *lua.LState, lv lua.LValue) *yaml.No
}
return yaml_map
default:
- return &yaml.Node{
- Kind: yaml.ScalarNode,
+ return &CandidateNode{
+ Kind: ScalarNode,
LineComment: fmt.Sprintf("Unhandled Lua type: %s", lv.Type().String()),
Tag: "!!null",
Value: lv.String(),
@@ -135,7 +136,7 @@ func (dec *luaDecoder) convertToYamlNode(ls *lua.LState, lv lua.LValue) *yaml.No
}
}
-func (dec *luaDecoder) decideTopLevelNode(ls *lua.LState) *yaml.Node {
+func (dec *luaDecoder) decideTopLevelNode(ls *lua.LState) *CandidateNode {
if ls.GetTop() == 0 {
// no items were explicitly returned, encode the globals table instead
return dec.convertToYamlNode(ls, ls.Get(lua.GlobalsIndex))
@@ -160,10 +161,5 @@ func (dec *luaDecoder) Decode() (*CandidateNode, error) {
}
firstNode := dec.decideTopLevelNode(ls)
dec.finished = true
- return &CandidateNode{
- Node: &yaml.Node{
- Kind: yaml.DocumentNode,
- Content: []*yaml.Node{firstNode},
- },
- }, nil
+ return firstNode, nil
}
diff --git a/pkg/yqlib/decoder_properties.go b/pkg/yqlib/decoder_properties.go
index e2438ee1..778ba7ea 100644
--- a/pkg/yqlib/decoder_properties.go
+++ b/pkg/yqlib/decoder_properties.go
@@ -8,7 +8,6 @@ import (
"strings"
"github.com/magiconair/properties"
- "gopkg.in/yaml.v3"
)
type propertiesDecoder struct {
@@ -52,16 +51,13 @@ func (dec *propertiesDecoder) applyPropertyComments(context Context, path []inte
assignmentOp := &Operation{OperationType: assignOpType, Preferences: assignPreferences{}}
rhsCandidateNode := &CandidateNode{
- Path: path,
- Node: &yaml.Node{
- Tag: "!!str",
- Value: fmt.Sprintf("%v", path[len(path)-1]),
- HeadComment: dec.processComment(strings.Join(comments, "\n")),
- Kind: yaml.ScalarNode,
- },
+ Tag: "!!str",
+ Value: fmt.Sprintf("%v", path[len(path)-1]),
+ HeadComment: dec.processComment(strings.Join(comments, "\n")),
+ Kind: ScalarNode,
}
- rhsCandidateNode.Node.Tag = guessTagFromCustomType(rhsCandidateNode.Node)
+ rhsCandidateNode.Tag = rhsCandidateNode.guessTagFromCustomType()
rhsOp := &Operation{OperationType: referenceOpType, CandidateNode: rhsCandidateNode}
@@ -87,13 +83,8 @@ func (dec *propertiesDecoder) applyProperty(context Context, properties *propert
}
}
- rhsNode := &yaml.Node{
- Value: value,
- Tag: "!!str",
- Kind: yaml.ScalarNode,
- }
-
- rhsNode.Tag = guessTagFromCustomType(rhsNode)
+ rhsNode := createStringScalarNode(value)
+ rhsNode.Tag = rhsNode.guessTagFromCustomType()
return dec.d.DeeplyAssign(context, path, rhsNode)
}
@@ -118,10 +109,8 @@ func (dec *propertiesDecoder) Decode() (*CandidateNode, error) {
properties.DisableExpansion = true
rootMap := &CandidateNode{
- Node: &yaml.Node{
- Kind: yaml.MappingNode,
- Tag: "!!map",
- },
+ Kind: MappingNode,
+ Tag: "!!map",
}
context := Context{}
@@ -135,11 +124,6 @@ func (dec *propertiesDecoder) Decode() (*CandidateNode, error) {
}
dec.finished = true
- return &CandidateNode{
- Node: &yaml.Node{
- Kind: yaml.DocumentNode,
- Content: []*yaml.Node{rootMap.Node},
- },
- }, nil
+ return rootMap, nil
}
diff --git a/pkg/yqlib/decoder_test.go b/pkg/yqlib/decoder_test.go
index d14c8a61..75269cfd 100644
--- a/pkg/yqlib/decoder_test.go
+++ b/pkg/yqlib/decoder_test.go
@@ -27,11 +27,14 @@ func processFormatScenario(s formatScenario, decoder Decoder, encoder Encoder) (
decoder = NewYamlDecoder(ConfiguredYamlPreferences)
}
+ log.Debugf("reading docs")
inputs, err := readDocuments(strings.NewReader(s.input), "sample.yml", 0, decoder)
if err != nil {
return "", err
}
+ log.Debugf("done reading the documents")
+
expression := s.expression
if expression == "" {
expression = "."
@@ -45,6 +48,8 @@ func processFormatScenario(s formatScenario, decoder Decoder, encoder Encoder) (
context, err := NewDataTreeNavigator().GetMatchingNodes(Context{MatchingNodes: inputs}, exp)
+ log.Debugf("Going to print: %v", NodesToString(context.MatchingNodes))
+
if err != nil {
return "", err
}
diff --git a/pkg/yqlib/decoder_toml.go b/pkg/yqlib/decoder_toml.go
index 166089ce..d94d1bf7 100644
--- a/pkg/yqlib/decoder_toml.go
+++ b/pkg/yqlib/decoder_toml.go
@@ -11,7 +11,6 @@ import (
"time"
toml "github.com/pelletier/go-toml/v2/unstable"
- yaml "gopkg.in/yaml.v3"
)
type tomlDecoder struct {
@@ -37,10 +36,9 @@ func (dec *tomlDecoder) Init(reader io.Reader) error {
}
dec.parser.Reset(buf.Bytes())
dec.rootMap = &CandidateNode{
- Node: &yaml.Node{
- Kind: yaml.MappingNode,
- Tag: "!!map",
- }}
+ Kind: MappingNode,
+ Tag: "!!map",
+ }
return nil
}
@@ -64,6 +62,7 @@ func (dec *tomlDecoder) processKeyValueIntoMap(rootMap *CandidateNode, tomlNode
if err != nil {
return err
}
+
context := Context{}
context = context.SingleChildContext(rootMap)
@@ -95,8 +94,8 @@ func (dec *tomlDecoder) decodeKeyValuesIntoMap(rootMap *CandidateNode, tomlNode
return false, nil
}
-func (dec *tomlDecoder) createInlineTableMap(tomlNode *toml.Node) (*yaml.Node, error) {
- content := make([]*yaml.Node, 0)
+func (dec *tomlDecoder) createInlineTableMap(tomlNode *toml.Node) (*CandidateNode, error) {
+ content := make([]*CandidateNode, 0)
log.Debug("!! createInlineTableMap")
iterator := tomlNode.Children()
@@ -107,28 +106,26 @@ func (dec *tomlDecoder) createInlineTableMap(tomlNode *toml.Node) (*yaml.Node, e
}
keyValues := &CandidateNode{
- Node: &yaml.Node{
- Kind: yaml.MappingNode,
- Tag: "!!map",
- },
+ Kind: MappingNode,
+ Tag: "!!map",
}
if err := dec.processKeyValueIntoMap(keyValues, child); err != nil {
return nil, err
}
- content = append(content, keyValues.Node.Content...)
+ content = append(content, keyValues.Content...)
}
- return &yaml.Node{
- Kind: yaml.MappingNode,
+ return &CandidateNode{
+ Kind: MappingNode,
Tag: "!!map",
Content: content,
}, nil
}
-func (dec *tomlDecoder) createArray(tomlNode *toml.Node) (*yaml.Node, error) {
- content := make([]*yaml.Node, 0)
+func (dec *tomlDecoder) createArray(tomlNode *toml.Node) (*CandidateNode, error) {
+ content := make([]*CandidateNode, 0)
iterator := tomlNode.Children()
for iterator.Next() {
child := iterator.Node()
@@ -139,43 +136,43 @@ func (dec *tomlDecoder) createArray(tomlNode *toml.Node) (*yaml.Node, error) {
content = append(content, yamlNode)
}
- return &yaml.Node{
- Kind: yaml.SequenceNode,
+ return &CandidateNode{
+ Kind: SequenceNode,
Tag: "!!seq",
Content: content,
}, nil
}
-func (dec *tomlDecoder) createStringScalar(tomlNode *toml.Node) (*yaml.Node, error) {
+func (dec *tomlDecoder) createStringScalar(tomlNode *toml.Node) (*CandidateNode, error) {
content := string(tomlNode.Data)
return createScalarNode(content, content), nil
}
-func (dec *tomlDecoder) createBoolScalar(tomlNode *toml.Node) (*yaml.Node, error) {
+func (dec *tomlDecoder) createBoolScalar(tomlNode *toml.Node) (*CandidateNode, error) {
content := string(tomlNode.Data)
return createScalarNode(content == "true", content), nil
}
-func (dec *tomlDecoder) createIntegerScalar(tomlNode *toml.Node) (*yaml.Node, error) {
+func (dec *tomlDecoder) createIntegerScalar(tomlNode *toml.Node) (*CandidateNode, error) {
content := string(tomlNode.Data)
_, num, err := parseInt64(content)
return createScalarNode(num, content), err
}
-func (dec *tomlDecoder) createDateTimeScalar(tomlNode *toml.Node) (*yaml.Node, error) {
+func (dec *tomlDecoder) createDateTimeScalar(tomlNode *toml.Node) (*CandidateNode, error) {
content := string(tomlNode.Data)
val, err := parseDateTime(time.RFC3339, content)
return createScalarNode(val, content), err
}
-func (dec *tomlDecoder) createFloatScalar(tomlNode *toml.Node) (*yaml.Node, error) {
+func (dec *tomlDecoder) createFloatScalar(tomlNode *toml.Node) (*CandidateNode, error) {
content := string(tomlNode.Data)
num, err := strconv.ParseFloat(content, 64)
return createScalarNode(num, content), err
}
-func (dec *tomlDecoder) decodeNode(tomlNode *toml.Node) (*yaml.Node, error) {
+func (dec *tomlDecoder) decodeNode(tomlNode *toml.Node) (*CandidateNode, error) {
switch tomlNode.Kind {
case toml.Key, toml.String:
return dec.createStringScalar(tomlNode)
@@ -241,16 +238,11 @@ func (dec *tomlDecoder) Decode() (*CandidateNode, error) {
// must have finished
dec.finished = true
- if len(dec.rootMap.Node.Content) == 0 {
+ if len(dec.rootMap.Content) == 0 {
return nil, io.EOF
}
- return &CandidateNode{
- Node: &yaml.Node{
- Kind: yaml.DocumentNode,
- Content: []*yaml.Node{dec.rootMap.Node},
- },
- }, deferredError
+ return dec.rootMap, deferredError
}
@@ -259,9 +251,9 @@ func (dec *tomlDecoder) processTopLevelNode(currentNode *toml.Node) (bool, error
var err error
log.Debug("!!!!!!!!!!!!Going to process %v state is current %v", currentNode.Kind, NodeToString(dec.rootMap))
if currentNode.Kind == toml.Table {
- runAgainstCurrentExp, err = dec.processTable((currentNode))
+ runAgainstCurrentExp, err = dec.processTable(currentNode)
} else if currentNode.Kind == toml.ArrayTable {
- runAgainstCurrentExp, err = dec.processArrayTable((currentNode))
+ runAgainstCurrentExp, err = dec.processArrayTable(currentNode)
} else {
runAgainstCurrentExp, err = dec.decodeKeyValuesIntoMap(dec.rootMap, currentNode)
}
@@ -281,10 +273,8 @@ func (dec *tomlDecoder) processTable(currentNode *toml.Node) (bool, error) {
}
tableNodeValue := &CandidateNode{
- Node: &yaml.Node{
- Kind: yaml.MappingNode,
- Tag: "!!map",
- },
+ Kind: MappingNode,
+ Tag: "!!map",
}
tableValue := dec.parser.Expression()
@@ -301,21 +291,18 @@ func (dec *tomlDecoder) processTable(currentNode *toml.Node) (bool, error) {
c := Context{}
c = c.SingleChildContext(dec.rootMap)
- err = dec.d.DeeplyAssign(c, fullPath, tableNodeValue.Node)
+ err = dec.d.DeeplyAssign(c, fullPath, tableNodeValue)
if err != nil {
return false, err
}
return runAgainstCurrentExp, nil
}
-func (dec *tomlDecoder) arrayAppend(context Context, path []interface{}, rhsNode *yaml.Node) error {
+func (dec *tomlDecoder) arrayAppend(context Context, path []interface{}, rhsNode *CandidateNode) error {
rhsCandidateNode := &CandidateNode{
- Path: path,
- Node: &yaml.Node{
- Kind: yaml.SequenceNode,
- Tag: "!!seq",
- Content: []*yaml.Node{rhsNode},
- },
+ Kind: SequenceNode,
+ Tag: "!!seq",
+ Content: []*CandidateNode{rhsNode},
}
assignmentOp := &Operation{OperationType: addAssignOpType}
@@ -346,10 +333,8 @@ func (dec *tomlDecoder) processArrayTable(currentNode *toml.Node) (bool, error)
}
tableNodeValue := &CandidateNode{
- Node: &yaml.Node{
- Kind: yaml.MappingNode,
- Tag: "!!map",
- },
+ Kind: MappingNode,
+ Tag: "!!map",
}
tableValue := dec.parser.Expression()
@@ -363,7 +348,7 @@ func (dec *tomlDecoder) processArrayTable(currentNode *toml.Node) (bool, error)
c = c.SingleChildContext(dec.rootMap)
// += function
- err = dec.arrayAppend(c, fullPath, tableNodeValue.Node)
+ err = dec.arrayAppend(c, fullPath, tableNodeValue)
return runAgainstCurrentExp, err
}
diff --git a/pkg/yqlib/decoder_uri.go b/pkg/yqlib/decoder_uri.go
index eabf26be..cd08d23c 100644
--- a/pkg/yqlib/decoder_uri.go
+++ b/pkg/yqlib/decoder_uri.go
@@ -4,8 +4,6 @@ import (
"bytes"
"io"
"net/url"
-
- yaml "gopkg.in/yaml.v3"
)
type uriDecoder struct {
@@ -50,11 +48,5 @@ func (dec *uriDecoder) Decode() (*CandidateNode, error) {
return nil, err
}
dec.readAnything = true
- return &CandidateNode{
- Node: &yaml.Node{
- Kind: yaml.ScalarNode,
- Tag: "!!str",
- Value: newValue,
- },
- }, nil
+ return createStringScalarNode(newValue), nil
}
diff --git a/pkg/yqlib/decoder_xml.go b/pkg/yqlib/decoder_xml.go
index 5c05b97f..c34209e2 100644
--- a/pkg/yqlib/decoder_xml.go
+++ b/pkg/yqlib/decoder_xml.go
@@ -12,7 +12,6 @@ import (
"unicode"
"golang.org/x/net/html/charset"
- yaml "gopkg.in/yaml.v3"
)
type xmlDecoder struct {
@@ -36,14 +35,14 @@ func (dec *xmlDecoder) Init(reader io.Reader) error {
return nil
}
-func (dec *xmlDecoder) createSequence(nodes []*xmlNode) (*yaml.Node, error) {
- yamlNode := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
+func (dec *xmlDecoder) createSequence(nodes []*xmlNode) (*CandidateNode, error) {
+ yamlNode := &CandidateNode{Kind: SequenceNode, Tag: "!!seq"}
for _, child := range nodes {
yamlChild, err := dec.convertToYamlNode(child)
if err != nil {
return nil, err
}
- yamlNode.Content = append(yamlNode.Content, yamlChild)
+ yamlNode.AddChild(yamlChild)
}
return yamlNode, nil
@@ -64,9 +63,9 @@ func (dec *xmlDecoder) processComment(c string) string {
return replacement
}
-func (dec *xmlDecoder) createMap(n *xmlNode) (*yaml.Node, error) {
+func (dec *xmlDecoder) createMap(n *xmlNode) (*CandidateNode, error) {
log.Debug("createMap: headC: %v, lineC: %v, footC: %v", n.HeadComment, n.LineComment, n.FootComment)
- yamlNode := &yaml.Node{Kind: yaml.MappingNode, Tag: "!!map"}
+ yamlNode := &CandidateNode{Kind: MappingNode, Tag: "!!map"}
if len(n.Data) > 0 {
log.Debugf("creating content node for map: %v", dec.prefs.ContentName)
@@ -75,14 +74,14 @@ func (dec *xmlDecoder) createMap(n *xmlNode) (*yaml.Node, error) {
labelNode.HeadComment = dec.processComment(n.HeadComment)
labelNode.LineComment = dec.processComment(n.LineComment)
labelNode.FootComment = dec.processComment(n.FootComment)
- yamlNode.Content = append(yamlNode.Content, labelNode, dec.createValueNodeFromData(n.Data))
+ yamlNode.AddKeyValueChild(labelNode, dec.createValueNodeFromData(n.Data))
}
for i, keyValuePair := range n.Children {
label := keyValuePair.K
children := keyValuePair.V
labelNode := createScalarNode(label, label)
- var valueNode *yaml.Node
+ var valueNode *CandidateNode
var err error
if i == 0 {
@@ -120,32 +119,32 @@ func (dec *xmlDecoder) createMap(n *xmlNode) (*yaml.Node, error) {
return nil, err
}
}
- yamlNode.Content = append(yamlNode.Content, labelNode, valueNode)
+ yamlNode.AddKeyValueChild(labelNode, valueNode)
}
return yamlNode, nil
}
-func (dec *xmlDecoder) createValueNodeFromData(values []string) *yaml.Node {
+func (dec *xmlDecoder) createValueNodeFromData(values []string) *CandidateNode {
switch len(values) {
case 0:
return createScalarNode(nil, "")
case 1:
return createScalarNode(values[0], values[0])
default:
- content := make([]*yaml.Node, 0)
+ content := make([]*CandidateNode, 0)
for _, value := range values {
content = append(content, createScalarNode(value, value))
}
- return &yaml.Node{
- Kind: yaml.SequenceNode,
+ return &CandidateNode{
+ Kind: SequenceNode,
Tag: "!!seq",
Content: content,
}
}
}
-func (dec *xmlDecoder) convertToYamlNode(n *xmlNode) (*yaml.Node, error) {
+func (dec *xmlDecoder) convertToYamlNode(n *xmlNode) (*CandidateNode, error) {
if len(n.Children) > 0 {
return dec.createMap(n)
}
@@ -189,12 +188,7 @@ func (dec *xmlDecoder) Decode() (*CandidateNode, error) {
dec.readAnything = true
dec.finished = true
- return &CandidateNode{
- Node: &yaml.Node{
- Kind: yaml.DocumentNode,
- Content: []*yaml.Node{firstNode},
- },
- }, nil
+ return firstNode, nil
}
type xmlNode struct {
diff --git a/pkg/yqlib/decoder_yaml.go b/pkg/yqlib/decoder_yaml.go
index c2652744..57eb3eee 100644
--- a/pkg/yqlib/decoder_yaml.go
+++ b/pkg/yqlib/decoder_yaml.go
@@ -20,8 +20,9 @@ type yamlDecoder struct {
leadingContent string
bufferRead bytes.Buffer
- readAnything bool
- firstFile bool
+ readAnything bool
+ firstFile bool
+ documentIndex uint
}
func NewYamlDecoder(prefs YamlPreferences) Decoder {
@@ -93,12 +94,14 @@ func (dec *yamlDecoder) Init(reader io.Reader) error {
dec.readAnything = false
dec.decoder = *yaml.NewDecoder(readerToUse)
dec.firstFile = false
+ dec.documentIndex = 0
return nil
}
func (dec *yamlDecoder) Decode() (*CandidateNode, error) {
- var dataBucket yaml.Node
- err := dec.decoder.Decode(&dataBucket)
+ var yamlNode yaml.Node
+ err := dec.decoder.Decode(&yamlNode)
+
if errors.Is(err, io.EOF) && dec.leadingContent != "" && !dec.readAnything {
// force returning an empty node with a comment.
dec.readAnything = true
@@ -116,28 +119,27 @@ func (dec *yamlDecoder) Decode() (*CandidateNode, error) {
return nil, err
}
- candidateNode := &CandidateNode{
- Node: &dataBucket,
+ candidateNode := CandidateNode{document: dec.documentIndex}
+ // don't bother with the DocumentNode
+ err = candidateNode.UnmarshalYAML(yamlNode.Content[0], make(map[string]*CandidateNode))
+ if err != nil {
+ return nil, err
}
+ candidateNode.HeadComment = yamlNode.HeadComment + candidateNode.HeadComment
+ candidateNode.FootComment = yamlNode.FootComment + candidateNode.FootComment
+
if dec.leadingContent != "" {
candidateNode.LeadingContent = dec.leadingContent
dec.leadingContent = ""
}
dec.readAnything = true
- // move document comments into candidate node
- // otherwise unwrap drops them.
- candidateNode.TrailingContent = dataBucket.FootComment
- dataBucket.FootComment = ""
- return candidateNode, nil
+ dec.documentIndex++
+ 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,
- }
+ node := createScalarNode(nil, "")
+ node.LeadingContent = dec.leadingContent
+ return node
}
diff --git a/pkg/yqlib/doc/operators/comment-operators.md b/pkg/yqlib/doc/operators/comment-operators.md
index 89af3b1b..414fff83 100644
--- a/pkg/yqlib/doc/operators/comment-operators.md
+++ b/pkg/yqlib/doc/operators/comment-operators.md
@@ -187,7 +187,6 @@ yq '. head_comment="single"' sample.yml
will output
```yaml
# single
-
a: cat
```
diff --git a/pkg/yqlib/doc/operators/create-collect-into-object.md b/pkg/yqlib/doc/operators/create-collect-into-object.md
index 2c132bb8..ff0c9cbe 100644
--- a/pkg/yqlib/doc/operators/create-collect-into-object.md
+++ b/pkg/yqlib/doc/operators/create-collect-into-object.md
@@ -66,6 +66,7 @@ will output
```yaml
Mike: cat
Mike: dog
+---
Rosey: monkey
Rosey: sheep
```
diff --git a/pkg/yqlib/doc/operators/document-index.md b/pkg/yqlib/doc/operators/document-index.md
index 619fd391..ebe994e5 100644
--- a/pkg/yqlib/doc/operators/document-index.md
+++ b/pkg/yqlib/doc/operators/document-index.md
@@ -85,6 +85,7 @@ will output
```yaml
match: cat
doc: 0
+---
match: frog
doc: 1
```
diff --git a/pkg/yqlib/doc/operators/file-operators.md b/pkg/yqlib/doc/operators/file-operators.md
index b1dacd78..8c331b83 100644
--- a/pkg/yqlib/doc/operators/file-operators.md
+++ b/pkg/yqlib/doc/operators/file-operators.md
@@ -54,7 +54,6 @@ yq eval-all 'file_index' sample.yml another.yml
will output
```yaml
0
----
1
```
diff --git a/pkg/yqlib/doc/usage/convert.md b/pkg/yqlib/doc/usage/convert.md
index 1f149c11..5060f8da 100644
--- a/pkg/yqlib/doc/usage/convert.md
+++ b/pkg/yqlib/doc/usage/convert.md
@@ -14,7 +14,7 @@ Given a sample.json file of:
```
then
```bash
-yq -P '.' sample.json
+yq -p=json sample.json
```
will output
```yaml
@@ -30,16 +30,16 @@ Given a sample.json file of:
```
then
```bash
-yq -P '.' sample.json
+yq -p=json sample.json
```
will output
```yaml
a: Easy! as one two three
b:
- c: 2
- d:
- - 3
- - 4
+ c: 2
+ d:
+ - 3
+ - 4
```
## Encode json: simple
diff --git a/pkg/yqlib/doc/usage/xml.md b/pkg/yqlib/doc/usage/xml.md
index 2d469450..503f9a74 100644
--- a/pkg/yqlib/doc/usage/xml.md
+++ b/pkg/yqlib/doc/usage/xml.md
@@ -129,15 +129,13 @@ zoo:
```
## Parse xml: force all as an array
-Because of the way yq works, when updating everything you need to update the children before the parents. By default `..` will match parents first, so we reverse that before updating.
-
Given a sample.xml file of:
```xml
boing
```
then
```bash
-yq -oy '([..] | reverse | .[]) |= [] + .' sample.xml
+yq -oy '.. |= [] + .' sample.xml
```
will output
```yaml
diff --git a/pkg/yqlib/encoder.go b/pkg/yqlib/encoder.go
index e0ecaccf..ee63fd47 100644
--- a/pkg/yqlib/encoder.go
+++ b/pkg/yqlib/encoder.go
@@ -2,20 +2,18 @@ package yqlib
import (
"io"
-
- yaml "gopkg.in/yaml.v3"
)
type Encoder interface {
- Encode(writer io.Writer, node *yaml.Node) error
+ Encode(writer io.Writer, node *CandidateNode) error
PrintDocumentSeparator(writer io.Writer) error
PrintLeadingContent(writer io.Writer, content string) error
CanHandleAliases() bool
}
-func mapKeysToStrings(node *yaml.Node) {
+func mapKeysToStrings(node *CandidateNode) {
- if node.Kind == yaml.MappingNode {
+ if node.Kind == MappingNode {
for index, child := range node.Content {
if index%2 == 0 { // its a map key
child.Tag = "!!str"
diff --git a/pkg/yqlib/encoder_base64.go b/pkg/yqlib/encoder_base64.go
index 635d27f7..9d7f126d 100644
--- a/pkg/yqlib/encoder_base64.go
+++ b/pkg/yqlib/encoder_base64.go
@@ -4,8 +4,6 @@ import (
"encoding/base64"
"fmt"
"io"
-
- yaml "gopkg.in/yaml.v3"
)
type base64Encoder struct {
@@ -28,11 +26,10 @@ func (e *base64Encoder) PrintLeadingContent(writer io.Writer, content string) er
return nil
}
-func (e *base64Encoder) Encode(writer io.Writer, originalNode *yaml.Node) error {
- node := unwrapDoc(originalNode)
- if guessTagFromCustomType(node) != "!!str" {
+func (e *base64Encoder) Encode(writer io.Writer, node *CandidateNode) error {
+ if node.guessTagFromCustomType() != "!!str" {
return fmt.Errorf("cannot encode %v as base64, can only operate on strings. Please first pipe through another encoding operator to convert the value to a string", node.Tag)
}
- _, err := writer.Write([]byte(e.encoding.EncodeToString([]byte(originalNode.Value))))
+ _, err := writer.Write([]byte(e.encoding.EncodeToString([]byte(node.Value))))
return err
}
diff --git a/pkg/yqlib/encoder_csv.go b/pkg/yqlib/encoder_csv.go
index 93466bd9..7904d728 100644
--- a/pkg/yqlib/encoder_csv.go
+++ b/pkg/yqlib/encoder_csv.go
@@ -4,8 +4,6 @@ import (
"encoding/csv"
"fmt"
"io"
-
- yaml "gopkg.in/yaml.v3"
)
type csvEncoder struct {
@@ -28,12 +26,12 @@ func (e *csvEncoder) PrintLeadingContent(writer io.Writer, content string) error
return nil
}
-func (e *csvEncoder) encodeRow(csvWriter *csv.Writer, contents []*yaml.Node) error {
+func (e *csvEncoder) encodeRow(csvWriter *csv.Writer, contents []*CandidateNode) error {
stringValues := make([]string, len(contents))
for i, child := range contents {
- if child.Kind != yaml.ScalarNode {
+ if child.Kind != ScalarNode {
return fmt.Errorf("csv encoding only works for arrays of scalars (string/numbers/booleans), child[%v] is a %v", i, child.Tag)
}
stringValues[i] = child.Value
@@ -41,10 +39,10 @@ func (e *csvEncoder) encodeRow(csvWriter *csv.Writer, contents []*yaml.Node) err
return csvWriter.Write(stringValues)
}
-func (e *csvEncoder) encodeArrays(csvWriter *csv.Writer, content []*yaml.Node) error {
+func (e *csvEncoder) encodeArrays(csvWriter *csv.Writer, content []*CandidateNode) error {
for i, child := range content {
- if child.Kind != yaml.SequenceNode {
+ if child.Kind != SequenceNode {
return fmt.Errorf("csv encoding only works for arrays of scalars (string/numbers/booleans), child[%v] is a %v", i, child.Tag)
}
err := e.encodeRow(csvWriter, child.Content)
@@ -55,16 +53,16 @@ func (e *csvEncoder) encodeArrays(csvWriter *csv.Writer, content []*yaml.Node) e
return nil
}
-func (e *csvEncoder) extractHeader(child *yaml.Node) ([]*yaml.Node, error) {
- if child.Kind != yaml.MappingNode {
+func (e *csvEncoder) extractHeader(child *CandidateNode) ([]*CandidateNode, error) {
+ if child.Kind != MappingNode {
return nil, fmt.Errorf("csv object encoding only works for arrays of flat objects (string key => string/numbers/boolean value), child[0] is a %v", child.Tag)
}
mapKeys := getMapKeys(child)
return mapKeys.Content, nil
}
-func (e *csvEncoder) createChildRow(child *yaml.Node, headers []*yaml.Node) []*yaml.Node {
- childRow := make([]*yaml.Node, 0)
+func (e *csvEncoder) createChildRow(child *CandidateNode, headers []*CandidateNode) []*CandidateNode {
+ childRow := make([]*CandidateNode, 0)
for _, header := range headers {
keyIndex := findKeyInMap(child, header)
value := createScalarNode(nil, "")
@@ -77,7 +75,7 @@ func (e *csvEncoder) createChildRow(child *yaml.Node, headers []*yaml.Node) []*y
}
-func (e *csvEncoder) encodeObjects(csvWriter *csv.Writer, content []*yaml.Node) error {
+func (e *csvEncoder) encodeObjects(csvWriter *csv.Writer, content []*CandidateNode) error {
headers, err := e.extractHeader(content[0])
if err != nil {
return nil
@@ -89,7 +87,7 @@ func (e *csvEncoder) encodeObjects(csvWriter *csv.Writer, content []*yaml.Node)
}
for i, child := range content {
- if child.Kind != yaml.MappingNode {
+ if child.Kind != MappingNode {
return fmt.Errorf("csv object encoding only works for arrays of flat objects (string key => string/numbers/boolean value), child[%v] is a %v", i, child.Tag)
}
row := e.createChildRow(child, headers)
@@ -102,26 +100,25 @@ func (e *csvEncoder) encodeObjects(csvWriter *csv.Writer, content []*yaml.Node)
return nil
}
-func (e *csvEncoder) Encode(writer io.Writer, originalNode *yaml.Node) error {
- if originalNode.Kind == yaml.ScalarNode {
- return writeString(writer, originalNode.Value+"\n")
+func (e *csvEncoder) Encode(writer io.Writer, node *CandidateNode) error {
+ if node.Kind == ScalarNode {
+ return writeString(writer, node.Value+"\n")
}
csvWriter := csv.NewWriter(writer)
csvWriter.Comma = e.separator
// node must be a sequence
- node := unwrapDoc(originalNode)
- if node.Kind != yaml.SequenceNode {
+ if node.Kind != SequenceNode {
return fmt.Errorf("csv encoding only works for arrays, got: %v", node.Tag)
} else if len(node.Content) == 0 {
return nil
}
- if node.Content[0].Kind == yaml.ScalarNode {
+ if node.Content[0].Kind == ScalarNode {
return e.encodeRow(csvWriter, node.Content)
}
- if node.Content[0].Kind == yaml.MappingNode {
+ if node.Content[0].Kind == MappingNode {
return e.encodeObjects(csvWriter, node.Content)
}
diff --git a/pkg/yqlib/encoder_json.go b/pkg/yqlib/encoder_json.go
index 53c6bd06..31c7b580 100644
--- a/pkg/yqlib/encoder_json.go
+++ b/pkg/yqlib/encoder_json.go
@@ -7,7 +7,6 @@ import (
"io"
"github.com/goccy/go-json"
- yaml "gopkg.in/yaml.v3"
)
type jsonEncoder struct {
@@ -38,9 +37,11 @@ func (je *jsonEncoder) PrintLeadingContent(writer io.Writer, content string) err
return nil
}
-func (je *jsonEncoder) Encode(writer io.Writer, node *yaml.Node) error {
+func (je *jsonEncoder) Encode(writer io.Writer, node *CandidateNode) error {
+ log.Debugf("I need to encode %v", NodeToString(node))
+ log.Debugf("kids %v", len(node.Content))
- if node.Kind == yaml.ScalarNode && je.UnwrapScalar {
+ if node.Kind == ScalarNode && je.UnwrapScalar {
return writeString(writer, node.Value+"\n")
}
@@ -54,14 +55,7 @@ func (je *jsonEncoder) Encode(writer io.Writer, node *yaml.Node) error {
encoder.SetEscapeHTML(false) // do not escape html chars e.g. &, <, >
encoder.SetIndent("", je.indentString)
- var dataBucket orderedMap
- // firstly, convert all map keys to strings
- mapKeysToStrings(node)
- errorDecoding := node.Decode(&dataBucket)
- if errorDecoding != nil {
- return errorDecoding
- }
- err := encoder.Encode(dataBucket)
+ err := encoder.Encode(node)
if err != nil {
return err
}
diff --git a/pkg/yqlib/encoder_lua.go b/pkg/yqlib/encoder_lua.go
index c1ac1574..b600371d 100644
--- a/pkg/yqlib/encoder_lua.go
+++ b/pkg/yqlib/encoder_lua.go
@@ -6,8 +6,6 @@ import (
"fmt"
"io"
"strings"
-
- yaml "gopkg.in/yaml.v3"
)
type luaEncoder struct {
@@ -82,10 +80,10 @@ func (le *luaEncoder) PrintLeadingContent(writer io.Writer, content string) erro
return nil
}
-func (le *luaEncoder) encodeString(writer io.Writer, node *yaml.Node) error {
+func (le *luaEncoder) encodeString(writer io.Writer, node *CandidateNode) error {
quote := "\""
switch node.Style {
- case yaml.LiteralStyle, yaml.FoldedStyle, yaml.FlowStyle:
+ case LiteralStyle, FoldedStyle, FlowStyle:
for i := 0; i < 10; i++ {
if !strings.Contains(node.Value, "]"+strings.Repeat("=", i)+"]") {
err := writeString(writer, "["+strings.Repeat("=", i)+"[\n")
@@ -99,7 +97,7 @@ func (le *luaEncoder) encodeString(writer io.Writer, node *yaml.Node) error {
return writeString(writer, "]"+strings.Repeat("=", i)+"]")
}
}
- case yaml.SingleQuotedStyle:
+ case SingleQuotedStyle:
quote = "'"
// fallthrough to regular ol' string
@@ -118,7 +116,7 @@ func (le *luaEncoder) writeIndent(writer io.Writer) error {
return writeString(writer, strings.Repeat(le.indentStr, le.indent))
}
-func (le *luaEncoder) encodeArray(writer io.Writer, node *yaml.Node) error {
+func (le *luaEncoder) encodeArray(writer io.Writer, node *CandidateNode) error {
err := writeString(writer, "{")
if err != nil {
return err
@@ -181,7 +179,7 @@ func needsQuoting(s string) bool {
return false
}
-func (le *luaEncoder) encodeMap(writer io.Writer, node *yaml.Node, global bool) error {
+func (le *luaEncoder) encodeMap(writer io.Writer, node *CandidateNode, global bool) error {
if !global {
err := writeString(writer, "{")
if err != nil {
@@ -263,14 +261,14 @@ func (le *luaEncoder) encodeMap(writer io.Writer, node *yaml.Node, global bool)
return writeString(writer, "}")
}
-func (le *luaEncoder) encodeAny(writer io.Writer, node *yaml.Node) error {
+func (le *luaEncoder) encodeAny(writer io.Writer, node *CandidateNode) error {
switch node.Kind {
- case yaml.SequenceNode:
+ case SequenceNode:
return le.encodeArray(writer, node)
- case yaml.MappingNode:
+ case MappingNode:
return le.encodeMap(writer, node, false)
- case yaml.ScalarNode:
- switch node.ShortTag() {
+ case ScalarNode:
+ switch node.Tag {
case "!!str":
return le.encodeString(writer, node)
case "!!null":
@@ -282,8 +280,7 @@ func (le *luaEncoder) encodeAny(writer io.Writer, node *yaml.Node) error {
return writeString(writer, strings.ToLower(node.Value))
case "!!int":
if strings.HasPrefix(node.Value, "0o") {
- var octalValue int
- err := node.Decode(&octalValue)
+ _, octalValue, err := parseInt64(node.Value)
if err != nil {
return err
}
@@ -302,16 +299,14 @@ func (le *luaEncoder) encodeAny(writer io.Writer, node *yaml.Node) error {
return writeString(writer, node.Value)
}
default:
- return fmt.Errorf("Lua encoder NYI -- %s", node.ShortTag())
+ return fmt.Errorf("Lua encoder NYI -- %s", node.Tag)
}
- case yaml.DocumentNode:
- return le.encodeAny(writer, node.Content[0])
default:
- return fmt.Errorf("Lua encoder NYI -- %s", node.ShortTag())
+ return fmt.Errorf("Lua encoder NYI -- %s", node.Tag)
}
}
-func (le *luaEncoder) encodeTopLevel(writer io.Writer, node *yaml.Node) error {
+func (le *luaEncoder) encodeTopLevel(writer io.Writer, node *CandidateNode) error {
err := writeString(writer, le.docPrefix)
if err != nil {
return err
@@ -323,12 +318,10 @@ func (le *luaEncoder) encodeTopLevel(writer io.Writer, node *yaml.Node) error {
return writeString(writer, le.docSuffix)
}
-func (le *luaEncoder) Encode(writer io.Writer, node *yaml.Node) error {
- if node.Kind == yaml.DocumentNode {
- return le.Encode(writer, node.Content[0])
- }
+func (le *luaEncoder) Encode(writer io.Writer, node *CandidateNode) error {
+
if le.globals {
- if node.Kind != yaml.MappingNode {
+ if node.Kind != MappingNode {
return fmt.Errorf("--lua-global requires a top level MappingNode")
}
return le.encodeMap(writer, node, true)
diff --git a/pkg/yqlib/encoder_properties.go b/pkg/yqlib/encoder_properties.go
index 575b4e89..0ebfb28a 100644
--- a/pkg/yqlib/encoder_properties.go
+++ b/pkg/yqlib/encoder_properties.go
@@ -8,7 +8,6 @@ import (
"strings"
"github.com/magiconair/properties"
- yaml "gopkg.in/yaml.v3"
)
type propertiesEncoder struct {
@@ -62,9 +61,9 @@ func (pe *propertiesEncoder) PrintLeadingContent(writer io.Writer, content strin
return nil
}
-func (pe *propertiesEncoder) Encode(writer io.Writer, node *yaml.Node) error {
+func (pe *propertiesEncoder) Encode(writer io.Writer, node *CandidateNode) error {
- if node.Kind == yaml.ScalarNode {
+ if node.Kind == ScalarNode {
return writeString(writer, node.Value+"\n")
}
@@ -79,7 +78,7 @@ func (pe *propertiesEncoder) Encode(writer io.Writer, node *yaml.Node) error {
return err
}
-func (pe *propertiesEncoder) doEncode(p *properties.Properties, node *yaml.Node, path string, keyNode *yaml.Node) error {
+func (pe *propertiesEncoder) doEncode(p *properties.Properties, node *CandidateNode, path string, keyNode *CandidateNode) error {
comments := ""
if keyNode != nil {
@@ -91,7 +90,7 @@ func (pe *propertiesEncoder) doEncode(p *properties.Properties, node *yaml.Node,
p.SetComments(path, strings.Split(commentsWithSpaces, "\n"))
switch node.Kind {
- case yaml.ScalarNode:
+ case ScalarNode:
var nodeValue string
if pe.unwrapScalar || !strings.Contains(node.Value, " ") {
nodeValue = node.Value
@@ -100,13 +99,11 @@ func (pe *propertiesEncoder) doEncode(p *properties.Properties, node *yaml.Node,
}
_, _, err := p.Set(path, nodeValue)
return err
- case yaml.DocumentNode:
- return pe.doEncode(p, node.Content[0], path, node)
- case yaml.SequenceNode:
+ case SequenceNode:
return pe.encodeArray(p, node.Content, path)
- case yaml.MappingNode:
+ case MappingNode:
return pe.encodeMap(p, node.Content, path)
- case yaml.AliasNode:
+ case AliasNode:
return pe.doEncode(p, node.Alias, path, nil)
default:
return fmt.Errorf("Unsupported node %v", node.Tag)
@@ -120,7 +117,7 @@ func (pe *propertiesEncoder) appendPath(path string, key interface{}) string {
return fmt.Sprintf("%v.%v", path, key)
}
-func (pe *propertiesEncoder) encodeArray(p *properties.Properties, kids []*yaml.Node, path string) error {
+func (pe *propertiesEncoder) encodeArray(p *properties.Properties, kids []*CandidateNode, path string) error {
for index, child := range kids {
err := pe.doEncode(p, child, pe.appendPath(path, index), nil)
if err != nil {
@@ -130,7 +127,7 @@ func (pe *propertiesEncoder) encodeArray(p *properties.Properties, kids []*yaml.
return nil
}
-func (pe *propertiesEncoder) encodeMap(p *properties.Properties, kids []*yaml.Node, path string) error {
+func (pe *propertiesEncoder) encodeMap(p *properties.Properties, kids []*CandidateNode, path string) error {
for index := 0; index < len(kids); index = index + 2 {
key := kids[index]
value := kids[index+1]
diff --git a/pkg/yqlib/encoder_properties_test.go b/pkg/yqlib/encoder_properties_test.go
index d1ed5cf6..70138fe1 100644
--- a/pkg/yqlib/encoder_properties_test.go
+++ b/pkg/yqlib/encoder_properties_test.go
@@ -18,7 +18,7 @@ func yamlToProps(sampleYaml string, unwrapScalar bool) string {
if err != nil {
panic(err)
}
- node := inputs.Front().Value.(*CandidateNode).Node
+ node := inputs.Front().Value.(*CandidateNode)
err = propsEncoder.Encode(writer, node)
if err != nil {
panic(err)
diff --git a/pkg/yqlib/encoder_sh.go b/pkg/yqlib/encoder_sh.go
index 1cee7fa0..3c540399 100644
--- a/pkg/yqlib/encoder_sh.go
+++ b/pkg/yqlib/encoder_sh.go
@@ -5,8 +5,6 @@ import (
"io"
"regexp"
"strings"
-
- yaml "gopkg.in/yaml.v3"
)
var unsafeChars = regexp.MustCompile(`[^\w@%+=:,./-]`)
@@ -31,13 +29,12 @@ func (e *shEncoder) PrintLeadingContent(writer io.Writer, content string) error
return nil
}
-func (e *shEncoder) Encode(writer io.Writer, originalNode *yaml.Node) error {
- node := unwrapDoc(originalNode)
- if guessTagFromCustomType(node) != "!!str" {
+func (e *shEncoder) Encode(writer io.Writer, node *CandidateNode) error {
+ if node.guessTagFromCustomType() != "!!str" {
return fmt.Errorf("cannot encode %v as URI, can only operate on strings. Please first pipe through another encoding operator to convert the value to a string", node.Tag)
}
- return writeString(writer, e.encode(originalNode.Value))
+ return writeString(writer, e.encode(node.Value))
}
// put any (shell-unsafe) characters into a single-quoted block, close the block lazily
diff --git a/pkg/yqlib/encoder_shellvariables.go b/pkg/yqlib/encoder_shellvariables.go
index 62d6ac8f..d725dae3 100644
--- a/pkg/yqlib/encoder_shellvariables.go
+++ b/pkg/yqlib/encoder_shellvariables.go
@@ -7,7 +7,6 @@ import (
"unicode/utf8"
"golang.org/x/text/unicode/norm"
- yaml "gopkg.in/yaml.v3"
)
type shellVariablesEncoder struct {
@@ -29,7 +28,7 @@ func (pe *shellVariablesEncoder) PrintLeadingContent(_ io.Writer, _ string) erro
return nil
}
-func (pe *shellVariablesEncoder) Encode(writer io.Writer, node *yaml.Node) error {
+func (pe *shellVariablesEncoder) Encode(writer io.Writer, node *CandidateNode) error {
mapKeysToStrings(node)
err := pe.doEncode(&writer, node, "")
@@ -40,12 +39,12 @@ func (pe *shellVariablesEncoder) Encode(writer io.Writer, node *yaml.Node) error
return err
}
-func (pe *shellVariablesEncoder) doEncode(w *io.Writer, node *yaml.Node, path string) error {
+func (pe *shellVariablesEncoder) doEncode(w *io.Writer, node *CandidateNode, path string) error {
// Note this drops all comments.
switch node.Kind {
- case yaml.ScalarNode:
+ case ScalarNode:
nonemptyPath := path
if path == "" {
// We can't assign an empty variable "=somevalue" because that would error out if sourced in a shell,
@@ -55,9 +54,7 @@ func (pe *shellVariablesEncoder) doEncode(w *io.Writer, node *yaml.Node, path st
}
_, err := io.WriteString(*w, nonemptyPath+"="+quoteValue(node.Value)+"\n")
return err
- case yaml.DocumentNode:
- return pe.doEncode(w, node.Content[0], path)
- case yaml.SequenceNode:
+ case SequenceNode:
for index, child := range node.Content {
err := pe.doEncode(w, child, appendPath(path, index))
if err != nil {
@@ -65,7 +62,7 @@ func (pe *shellVariablesEncoder) doEncode(w *io.Writer, node *yaml.Node, path st
}
}
return nil
- case yaml.MappingNode:
+ case MappingNode:
for index := 0; index < len(node.Content); index = index + 2 {
key := node.Content[index]
value := node.Content[index+1]
@@ -75,7 +72,7 @@ func (pe *shellVariablesEncoder) doEncode(w *io.Writer, node *yaml.Node, path st
}
}
return nil
- case yaml.AliasNode:
+ case AliasNode:
return pe.doEncode(w, node.Alias, path)
default:
return fmt.Errorf("Unsupported node %v", node.Tag)
diff --git a/pkg/yqlib/encoder_shellvariables_test.go b/pkg/yqlib/encoder_shellvariables_test.go
index b3259088..3d3d905f 100644
--- a/pkg/yqlib/encoder_shellvariables_test.go
+++ b/pkg/yqlib/encoder_shellvariables_test.go
@@ -18,7 +18,7 @@ func assertEncodesTo(t *testing.T, yaml string, shellvars string) {
if err != nil {
panic(err)
}
- node := inputs.Front().Value.(*CandidateNode).Node
+ node := inputs.Front().Value.(*CandidateNode)
err = encoder.Encode(writer, node)
if err != nil {
panic(err)
diff --git a/pkg/yqlib/encoder_test.go b/pkg/yqlib/encoder_test.go
index cb384562..c2fc8628 100644
--- a/pkg/yqlib/encoder_test.go
+++ b/pkg/yqlib/encoder_test.go
@@ -11,7 +11,8 @@ import (
"github.com/mikefarah/yq/v4/test"
)
-func yamlToJSON(sampleYaml string, indent int) string {
+func yamlToJSON(t *testing.T, sampleYaml string, indent int) string {
+ t.Helper()
var output bytes.Buffer
writer := bufio.NewWriter(&output)
@@ -20,7 +21,10 @@ func yamlToJSON(sampleYaml string, indent int) string {
if err != nil {
panic(err)
}
- node := inputs.Front().Value.(*CandidateNode).Node
+ node := inputs.Front().Value.(*CandidateNode)
+ log.Debugf("%v", NodeToString(node))
+ // log.Debugf("Content[0] %v", NodeToString(node.Content[0]))
+
err = jsonEncoder.Encode(writer, node)
if err != nil {
panic(err)
@@ -46,31 +50,31 @@ banana:
}
]
}`
- var actualJSON = yamlToJSON(sampleYaml, 2)
+ var actualJSON = yamlToJSON(t, sampleYaml, 2)
test.AssertResult(t, expectedJSON, actualJSON)
}
func TestJsonNullInArray(t *testing.T) {
var sampleYaml = `[null]`
- var actualJSON = yamlToJSON(sampleYaml, 0)
+ var actualJSON = yamlToJSON(t, sampleYaml, 0)
test.AssertResult(t, sampleYaml, actualJSON)
}
func TestJsonNull(t *testing.T) {
var sampleYaml = `null`
- var actualJSON = yamlToJSON(sampleYaml, 0)
+ var actualJSON = yamlToJSON(t, sampleYaml, 0)
test.AssertResult(t, sampleYaml, actualJSON)
}
func TestJsonNullInObject(t *testing.T) {
var sampleYaml = `{x: null}`
- var actualJSON = yamlToJSON(sampleYaml, 0)
+ var actualJSON = yamlToJSON(t, sampleYaml, 0)
test.AssertResult(t, `{"x":null}`, actualJSON)
}
func TestJsonEncoderDoesNotEscapeHTMLChars(t *testing.T) {
var sampleYaml = `build: "( ./lint && ./format && ./compile ) < src.code"`
var expectedJSON = `{"build":"( ./lint && ./format && ./compile ) < src.code"}`
- var actualJSON = yamlToJSON(sampleYaml, 0)
+ var actualJSON = yamlToJSON(t, sampleYaml, 0)
test.AssertResult(t, expectedJSON, actualJSON)
}
diff --git a/pkg/yqlib/encoder_toml.go b/pkg/yqlib/encoder_toml.go
index 13b4e1e3..44e4e8b5 100644
--- a/pkg/yqlib/encoder_toml.go
+++ b/pkg/yqlib/encoder_toml.go
@@ -3,8 +3,6 @@ package yqlib
import (
"fmt"
"io"
-
- yaml "gopkg.in/yaml.v3"
)
type tomlEncoder struct {
@@ -14,8 +12,8 @@ func NewTomlEncoder() Encoder {
return &tomlEncoder{}
}
-func (te *tomlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
- if node.Kind == yaml.ScalarNode {
+func (te *tomlEncoder) Encode(writer io.Writer, node *CandidateNode) error {
+ if node.Kind == ScalarNode {
return writeString(writer, node.Value+"\n")
}
return fmt.Errorf("only scalars (e.g. strings, numbers, booleans) are supported for TOML output at the moment. Please use yaml output format (-oy) until the encoder has been fully implemented")
diff --git a/pkg/yqlib/encoder_uri.go b/pkg/yqlib/encoder_uri.go
index fdf58665..194350c4 100644
--- a/pkg/yqlib/encoder_uri.go
+++ b/pkg/yqlib/encoder_uri.go
@@ -4,8 +4,6 @@ import (
"fmt"
"io"
"net/url"
-
- yaml "gopkg.in/yaml.v3"
)
type uriEncoder struct {
@@ -27,11 +25,10 @@ func (e *uriEncoder) PrintLeadingContent(writer io.Writer, content string) error
return nil
}
-func (e *uriEncoder) Encode(writer io.Writer, originalNode *yaml.Node) error {
- node := unwrapDoc(originalNode)
- if guessTagFromCustomType(node) != "!!str" {
+func (e *uriEncoder) Encode(writer io.Writer, node *CandidateNode) error {
+ if node.guessTagFromCustomType() != "!!str" {
return fmt.Errorf("cannot encode %v as URI, can only operate on strings. Please first pipe through another encoding operator to convert the value to a string", node.Tag)
}
- _, err := writer.Write([]byte(url.QueryEscape(originalNode.Value)))
+ _, err := writer.Write([]byte(url.QueryEscape(node.Value)))
return err
}
diff --git a/pkg/yqlib/encoder_xml.go b/pkg/yqlib/encoder_xml.go
index 2e48bd99..1d55d902 100644
--- a/pkg/yqlib/encoder_xml.go
+++ b/pkg/yqlib/encoder_xml.go
@@ -8,8 +8,6 @@ import (
"io"
"regexp"
"strings"
-
- yaml "gopkg.in/yaml.v3"
)
type xmlEncoder struct {
@@ -41,19 +39,18 @@ func (e *xmlEncoder) PrintLeadingContent(writer io.Writer, content string) error
return nil
}
-func (e *xmlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
+func (e *xmlEncoder) Encode(writer io.Writer, node *CandidateNode) error {
encoder := xml.NewEncoder(writer)
// hack so we can manually add newlines to procInst and directives
e.writer = writer
encoder.Indent("", e.indentString)
var newLine xml.CharData = []byte("\n")
- mapNode := unwrapDoc(node)
- if mapNode.Tag == "!!map" {
+ if node.Tag == "!!map" {
// make sure processing instructions are encoded first
- for i := 0; i < len(mapNode.Content); i += 2 {
- key := mapNode.Content[i]
- value := mapNode.Content[i+1]
+ for i := 0; i < len(node.Content); i += 2 {
+ key := node.Content[i]
+ value := node.Content[i+1]
if key.Value == (e.prefs.ProcInstPrefix + "xml") {
name := strings.Replace(key.Value, e.prefs.ProcInstPrefix, "", 1)
@@ -82,29 +79,12 @@ func (e *xmlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
}
switch node.Kind {
- case yaml.MappingNode:
+ case MappingNode:
err := e.encodeTopLevelMap(encoder, node)
if err != nil {
return err
}
- case yaml.DocumentNode:
- err := e.encodeComment(encoder, headAndLineComment(node))
- if err != nil {
- return err
- }
- unwrappedNode := unwrapDoc(node)
- if unwrappedNode.Kind != yaml.MappingNode {
- return fmt.Errorf("cannot encode %v to XML - only maps can be encoded", unwrappedNode.Tag)
- }
- err = e.encodeTopLevelMap(encoder, unwrappedNode)
- if err != nil {
- return err
- }
- err = e.encodeComment(encoder, footComment(node))
- if err != nil {
- return err
- }
- case yaml.ScalarNode:
+ case ScalarNode:
var charData xml.CharData = []byte(node.Value)
err := encoder.EncodeToken(charData)
if err != nil {
@@ -112,14 +92,14 @@ func (e *xmlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
}
return encoder.Flush()
default:
- return fmt.Errorf("unsupported type %v", node.Tag)
+ return fmt.Errorf("cannot encode %v to XML - only maps can be encoded", node.Tag)
}
return encoder.EncodeToken(newLine)
}
-func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *yaml.Node) error {
+func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *CandidateNode) error {
err := e.encodeComment(encoder, headAndLineComment(node))
if err != nil {
return err
@@ -178,7 +158,7 @@ func (e *xmlEncoder) encodeTopLevelMap(encoder *xml.Encoder, node *yaml.Node) er
return e.encodeComment(encoder, footComment(node))
}
-func (e *xmlEncoder) encodeStart(encoder *xml.Encoder, node *yaml.Node, start xml.StartElement) error {
+func (e *xmlEncoder) encodeStart(encoder *xml.Encoder, node *CandidateNode, start xml.StartElement) error {
err := encoder.EncodeToken(start)
if err != nil {
return err
@@ -186,7 +166,7 @@ func (e *xmlEncoder) encodeStart(encoder *xml.Encoder, node *yaml.Node, start xm
return e.encodeComment(encoder, headComment(node))
}
-func (e *xmlEncoder) encodeEnd(encoder *xml.Encoder, node *yaml.Node, start xml.StartElement) error {
+func (e *xmlEncoder) encodeEnd(encoder *xml.Encoder, node *CandidateNode, start xml.StartElement) error {
err := encoder.EncodeToken(start.End())
if err != nil {
return err
@@ -194,13 +174,13 @@ func (e *xmlEncoder) encodeEnd(encoder *xml.Encoder, node *yaml.Node, start xml.
return e.encodeComment(encoder, footComment(node))
}
-func (e *xmlEncoder) doEncode(encoder *xml.Encoder, node *yaml.Node, start xml.StartElement) error {
+func (e *xmlEncoder) doEncode(encoder *xml.Encoder, node *CandidateNode, start xml.StartElement) error {
switch node.Kind {
- case yaml.MappingNode:
+ case MappingNode:
return e.encodeMap(encoder, node, start)
- case yaml.SequenceNode:
+ case SequenceNode:
return e.encodeArray(encoder, node, start)
- case yaml.ScalarNode:
+ case ScalarNode:
err := e.encodeStart(encoder, node, start)
if err != nil {
return err
@@ -258,7 +238,7 @@ func (e *xmlEncoder) encodeComment(encoder *xml.Encoder, commentStr string) erro
return nil
}
-func (e *xmlEncoder) encodeArray(encoder *xml.Encoder, node *yaml.Node, start xml.StartElement) error {
+func (e *xmlEncoder) encodeArray(encoder *xml.Encoder, node *CandidateNode, start xml.StartElement) error {
if err := e.encodeComment(encoder, headAndLineComment(node)); err != nil {
return err
@@ -280,7 +260,7 @@ func (e *xmlEncoder) isAttribute(name string) bool {
!strings.HasPrefix(name, e.prefs.ProcInstPrefix)
}
-func (e *xmlEncoder) encodeMap(encoder *xml.Encoder, node *yaml.Node, start xml.StartElement) error {
+func (e *xmlEncoder) encodeMap(encoder *xml.Encoder, node *CandidateNode, start xml.StartElement) error {
log.Debug("its a map")
//first find all the attributes and put them on the start token
@@ -289,7 +269,7 @@ func (e *xmlEncoder) encodeMap(encoder *xml.Encoder, node *yaml.Node, start xml.
value := node.Content[i+1]
if e.isAttribute(key.Value) {
- if value.Kind == yaml.ScalarNode {
+ if value.Kind == ScalarNode {
attributeName := strings.Replace(key.Value, e.prefs.AttributePrefix, "", 1)
start.Attr = append(start.Attr, xml.Attr{Name: xml.Name{Local: attributeName}, Value: value.Value})
} else {
diff --git a/pkg/yqlib/encoder_yaml.go b/pkg/yqlib/encoder_yaml.go
index e2a9943c..0d26437a 100644
--- a/pkg/yqlib/encoder_yaml.go
+++ b/pkg/yqlib/encoder_yaml.go
@@ -5,6 +5,7 @@ import (
"bytes"
"errors"
"io"
+ "regexp"
"strings"
yaml "gopkg.in/yaml.v3"
@@ -40,6 +41,8 @@ func (ye *yamlEncoder) PrintDocumentSeparator(writer io.Writer) error {
func (ye *yamlEncoder) PrintLeadingContent(writer io.Writer, content string) error {
reader := bufio.NewReader(strings.NewReader(content))
+ var commentLineRegEx = regexp.MustCompile(`^\s*#`)
+
for {
readline, errReading := reader.ReadString('\n')
@@ -53,6 +56,9 @@ func (ye *yamlEncoder) PrintLeadingContent(writer io.Writer, content string) err
}
} else {
+ if len(readline) > 0 && readline != "\n" && readline[0] != '%' && !commentLineRegEx.MatchString(readline) {
+ readline = "# " + readline
+ }
if err := writeString(writer, readline); err != nil {
return err
}
@@ -72,10 +78,14 @@ func (ye *yamlEncoder) PrintLeadingContent(writer io.Writer, content string) err
return nil
}
-func (ye *yamlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
-
- if node.Kind == yaml.ScalarNode && ye.prefs.UnwrapScalar {
- return writeString(writer, node.Value+"\n")
+func (ye *yamlEncoder) Encode(writer io.Writer, node *CandidateNode) error {
+ log.Debug("encoderYaml - going to print %v", NodeToString(node))
+ if node.Kind == ScalarNode && ye.prefs.UnwrapScalar {
+ valueToPrint := node.Value
+ if node.LeadingContent == "" || valueToPrint != "" {
+ valueToPrint = valueToPrint + "\n"
+ }
+ return writeString(writer, valueToPrint)
}
destination := writer
@@ -88,7 +98,20 @@ func (ye *yamlEncoder) Encode(writer io.Writer, node *yaml.Node) error {
encoder.SetIndent(ye.indent)
- if err := encoder.Encode(node); err != nil {
+ target, err := node.MarshalYAML()
+
+ if err != nil {
+ return err
+ }
+
+ trailingContent := target.FootComment
+ target.FootComment = ""
+
+ if err := encoder.Encode(target); err != nil {
+ return err
+ }
+
+ if err := ye.PrintLeadingContent(destination, trailingContent); err != nil {
return err
}
diff --git a/pkg/yqlib/goccy_yaml_test.go b/pkg/yqlib/goccy_yaml_test.go
new file mode 100644
index 00000000..018a849a
--- /dev/null
+++ b/pkg/yqlib/goccy_yaml_test.go
@@ -0,0 +1,170 @@
+package yqlib
+
+import (
+ "testing"
+
+ "github.com/mikefarah/yq/v4/test"
+)
+
+var goccyYamlFormatScenarios = []formatScenario{
+ {
+ description: "basic - 3",
+ skipDoc: true,
+ input: "3",
+ expected: "3\n",
+ },
+ {
+ description: "basic - 3.1",
+ skipDoc: true,
+ input: "3.1",
+ expected: "3.1\n",
+ },
+ {
+ description: "basic - 3.1",
+ skipDoc: true,
+ input: "mike: 3",
+ expected: "mike: 3\n",
+ },
+ {
+ description: "basic - 3.1",
+ skipDoc: true,
+ input: "{mike: 3}",
+ expected: "{mike: 3}\n",
+ },
+ {
+ description: "basic - map multiple entries",
+ skipDoc: true,
+ input: "mike: 3\nfred: 12\n",
+ expected: "mike: 3\nfred: 12\n",
+ },
+ {
+ description: "basic - 3.1",
+ skipDoc: true,
+ input: "{\nmike: 3\n}",
+ expected: "{mike: 3}\n",
+ },
+ {
+ description: "basic - 3.1",
+ skipDoc: true,
+ input: "mike: !!cat 3",
+ expected: "mike: !!cat 3\n",
+ },
+ {
+ description: "basic - 3.1",
+ skipDoc: true,
+ input: "- 3",
+ expected: "- 3\n",
+ },
+ {
+ description: "basic - 3.1",
+ skipDoc: true,
+ input: "[3]",
+ expected: "[3]\n",
+ },
+ {
+ description: "basic - plain string",
+ skipDoc: true,
+ input: `a: meow`,
+ expected: "a: meow\n",
+ },
+ {
+ description: "basic - double quoted string",
+ skipDoc: true,
+ input: `a: "meow"`,
+ expected: "a: \"meow\"\n",
+ },
+ {
+ description: "basic - single quoted string",
+ skipDoc: true,
+ input: `a: 'meow'`,
+ expected: "a: 'meow'\n",
+ },
+ {
+ description: "basic - string block",
+ skipDoc: true,
+ input: "a: |\n meow\n",
+ expected: "a: |\n meow\n",
+ },
+ {
+ description: "basic - long string",
+ skipDoc: true,
+ input: "a: the cute cat wrote a long sentence that wasn't wrapped at all.\n",
+ expected: "a: the cute cat wrote a long sentence that wasn't wrapped at all.\n",
+ },
+ {
+ description: "basic - string block",
+ skipDoc: true,
+ input: "a: |-\n meow\n",
+ expected: "a: |-\n meow\n",
+ },
+ {
+ description: "basic - line comment",
+ skipDoc: true,
+ input: "a: meow # line comment\n",
+ expected: "a: meow # line comment\n",
+ },
+ {
+ description: "basic - line comment",
+ skipDoc: true,
+ input: "# head comment\na: #line comment\n meow\n",
+ expected: "# head comment\na: meow #line comment\n", // go-yaml does this
+ },
+ {
+ description: "basic - foot comment",
+ skipDoc: true,
+ input: "a: meow\n# foot comment\n",
+ expected: "a: meow\n# foot comment\n",
+ },
+ {
+ description: "basic - foot comment",
+ skipDoc: true,
+ input: "a: meow\nb: woof\n# foot comment\n",
+ expected: "a: meow\nb: woof\n# foot comment\n",
+ },
+ {
+ description: "basic - boolean",
+ skipDoc: true,
+ input: "true\n",
+ expected: "true\n",
+ },
+ {
+ description: "basic - null",
+ skipDoc: true,
+ input: "a: null\n",
+ expected: "a: null\n",
+ },
+ {
+ description: "basic - ~",
+ skipDoc: true,
+ input: "a: ~\n",
+ expected: "a: ~\n",
+ },
+ // {
+ // description: "basic - ~",
+ // skipDoc: true,
+ // input: "null\n",
+ // expected: "null\n",
+ // },
+ // {
+ // skipDoc: true,
+ // description: "trailing comment",
+ // input: "test:",
+ // expected: "test:",
+ // },
+ // {
+ // skipDoc: true,
+ // description: "trailing comment",
+ // input: "test:\n# this comment will be removed",
+ // expected: "test:\n# this comment will be removed",
+ // },
+}
+
+func testGoccyYamlScenario(t *testing.T, s formatScenario) {
+ test.AssertResultWithContext(t, s.expected, mustProcessFormatScenario(s, NewGoccyYAMLDecoder(), NewYamlEncoder(2, false, ConfiguredYamlPreferences)), s.description)
+}
+
+func TestGoccyYmlFormatScenarios(t *testing.T) {
+ for _, tt := range goccyYamlFormatScenarios {
+ testGoccyYamlScenario(t, tt)
+ }
+}
diff --git a/pkg/yqlib/json_test.go b/pkg/yqlib/json_test.go
index cda716ba..ab0c7225 100644
--- a/pkg/yqlib/json_test.go
+++ b/pkg/yqlib/json_test.go
@@ -11,12 +11,12 @@ import (
"github.com/mikefarah/yq/v4/test"
)
-const complexExpectYaml = `D0, P[], (!!map)::a: Easy! as one two three
+const complexExpectYaml = `a: Easy! as one two three
b:
- c: 2
- d:
- - 3
- - 4
+ c: 2
+ d:
+ - 3
+ - 4
`
const sampleNdJson = `{"this": "is a multidoc json file"}
@@ -99,13 +99,54 @@ var jsonScenarios = []formatScenario{
description: "Parse json: simple",
subdescription: "JSON is a subset of yaml, so all you need to do is prettify the output",
input: `{"cat": "meow"}`,
- expected: "D0, P[], (!!map)::cat: meow\n",
+ scenarioType: "decode-ndjson",
+ expected: "cat: meow\n",
+ },
+ {
+ skipDoc: true,
+ description: "Parse json: simple: key",
+ input: `{"cat": "meow"}`,
+ expression: ".cat | key",
+ expected: "\"cat\"\n",
+ scenarioType: "decode",
+ },
+ {
+ skipDoc: true,
+ description: "Parse json: simple: parent",
+ input: `{"cat": "meow"}`,
+ expression: ".cat | parent",
+ expected: "{\"cat\":\"meow\"}\n",
+ scenarioType: "decode",
+ },
+ {
+ skipDoc: true,
+ description: "Parse json: simple: path",
+ input: `{"cat": "meow"}`,
+ expression: ".cat | path",
+ expected: "[\"cat\"]\n",
+ scenarioType: "decode",
+ },
+ {
+ skipDoc: true,
+ description: "Parse json: deeper: path",
+ input: `{"cat": {"noises": "meow"}}`,
+ expression: ".cat.noises | path",
+ expected: "[\"cat\",\"noises\"]\n",
+ scenarioType: "decode",
+ },
+ {
+ skipDoc: true,
+ description: "Parse json: array path",
+ input: `{"cat": {"noises": ["meow"]}}`,
+ expression: ".cat.noises[0] | path",
+ expected: "[\"cat\",\"noises\",0]\n",
+ scenarioType: "decode",
},
{
description: "bad json",
skipDoc: true,
- input: `{"a": 1 "b": 2}`,
- expectedError: `bad file 'sample.yml': invalid character '"' after object key:value pair`,
+ input: `{"a": 1 b": 2}`,
+ expectedError: `bad file 'sample.yml': json: string of object unexpected end of JSON input`,
scenarioType: "decode-error",
},
{
@@ -113,6 +154,7 @@ var jsonScenarios = []formatScenario{
subdescription: "JSON is a subset of yaml, so all you need to do is prettify the output",
input: `{"a":"Easy! as one two three","b":{"c":2,"d":[3,4]}}`,
expected: complexExpectYaml,
+ scenarioType: "decode-ndjson",
},
{
description: "Encode json: simple",
@@ -213,7 +255,7 @@ var jsonScenarios = []formatScenario{
description: "empty string",
skipDoc: true,
input: `""`,
- expected: "\"\"\n",
+ expected: "\n",
scenarioType: "decode-ndjson",
},
{
@@ -316,11 +358,10 @@ func decodeJSON(t *testing.T, jsonString string) *CandidateNode {
func testJSONScenario(t *testing.T, s formatScenario) {
switch s.scenarioType {
- case "encode", "decode":
+ case "encode":
test.AssertResultWithContext(t, s.expected, mustProcessFormatScenario(s, NewYamlDecoder(ConfiguredYamlPreferences), NewJSONEncoder(s.indent, false, false)), s.description)
- case "":
- var actual = resultToString(t, decodeJSON(t, s.input))
- test.AssertResultWithContext(t, s.expected, actual, s.description)
+ case "decode":
+ test.AssertResultWithContext(t, s.expected, mustProcessFormatScenario(s, NewJSONDecoder(), NewJSONEncoder(s.indent, false, false)), s.description)
case "decode-ndjson":
test.AssertResultWithContext(t, s.expected, mustProcessFormatScenario(s, NewJSONDecoder(), NewYamlEncoder(2, false, ConfiguredYamlPreferences)), s.description)
case "roundtrip-ndjson":
diff --git a/pkg/yqlib/lexer_participle_test.go b/pkg/yqlib/lexer_participle_test.go
index 1df7fec8..a6244bb3 100644
--- a/pkg/yqlib/lexer_participle_test.go
+++ b/pkg/yqlib/lexer_participle_test.go
@@ -5,7 +5,6 @@ import (
"github.com/alecthomas/repr"
"github.com/mikefarah/yq/v4/test"
- yaml "gopkg.in/yaml.v3"
)
type participleLexerScenario struct {
@@ -64,11 +63,9 @@ var participleLexerScenarios = []participleLexerScenario{
Value: 0,
StringValue: "0",
CandidateNode: &CandidateNode{
- Node: &yaml.Node{
- Kind: yaml.ScalarNode,
- Tag: "!!int",
- Value: "0",
- },
+ Kind: ScalarNode,
+ Tag: "!!int",
+ Value: "0",
},
},
},
@@ -87,11 +84,9 @@ var participleLexerScenarios = []participleLexerScenario{
Value: int64(3),
StringValue: "3",
CandidateNode: &CandidateNode{
- Node: &yaml.Node{
- Kind: yaml.Kind(8),
- Tag: "!!int",
- Value: "3",
- },
+ Kind: ScalarNode,
+ Tag: "!!int",
+ Value: "3",
},
},
},
@@ -129,11 +124,9 @@ var participleLexerScenarios = []participleLexerScenario{
Value: int64(-2),
StringValue: "-2",
CandidateNode: &CandidateNode{
- Node: &yaml.Node{
- Kind: yaml.ScalarNode,
- Tag: "!!int",
- Value: "-2",
- },
+ Kind: ScalarNode,
+ Tag: "!!int",
+ Value: "-2",
},
},
},
@@ -654,11 +647,9 @@ var participleLexerScenarios = []participleLexerScenario{
StringValue: "string with a\n",
Preferences: nil,
CandidateNode: &CandidateNode{
- Node: &yaml.Node{
- Kind: yaml.ScalarNode,
- Tag: "!!str",
- Value: "string with a\n",
- },
+ Kind: ScalarNode,
+ Tag: "!!str",
+ Value: "string with a\n",
},
},
},
@@ -675,11 +666,9 @@ var participleLexerScenarios = []participleLexerScenario{
StringValue: `string with a "`,
Preferences: nil,
CandidateNode: &CandidateNode{
- Node: &yaml.Node{
- Kind: yaml.ScalarNode,
- Tag: "!!str",
- Value: `string with a "`,
- },
+ Kind: ScalarNode,
+ Tag: "!!str",
+ Value: `string with a "`,
},
},
},
diff --git a/pkg/yqlib/lib.go b/pkg/yqlib/lib.go
index b88b9e2d..78bd31ba 100644
--- a/pkg/yqlib/lib.go
+++ b/pkg/yqlib/lib.go
@@ -2,7 +2,6 @@
package yqlib
import (
- "bytes"
"container/list"
"fmt"
"math"
@@ -10,7 +9,6 @@ import (
"strings"
logging "gopkg.in/op/go-logging.v1"
- yaml "gopkg.in/yaml.v3"
)
var ExpressionParser ExpressionParserInterface
@@ -191,7 +189,7 @@ type Operation struct {
UpdateAssign bool // used for assign ops, when true it means we evaluate the rhs given the lhs
}
-func recurseNodeArrayEqual(lhs *yaml.Node, rhs *yaml.Node) bool {
+func recurseNodeArrayEqual(lhs *CandidateNode, rhs *CandidateNode) bool {
if len(lhs.Content) != len(rhs.Content) {
return false
}
@@ -204,7 +202,7 @@ func recurseNodeArrayEqual(lhs *yaml.Node, rhs *yaml.Node) bool {
return true
}
-func findInArray(array *yaml.Node, item *yaml.Node) int {
+func findInArray(array *CandidateNode, item *CandidateNode) int {
for index := 0; index < len(array.Content); index = index + 1 {
if recursiveNodeEqual(array.Content[index], item) {
@@ -214,7 +212,7 @@ func findInArray(array *yaml.Node, item *yaml.Node) int {
return -1
}
-func findKeyInMap(dataMap *yaml.Node, item *yaml.Node) int {
+func findKeyInMap(dataMap *CandidateNode, item *CandidateNode) int {
for index := 0; index < len(dataMap.Content); index = index + 2 {
if recursiveNodeEqual(dataMap.Content[index], item) {
@@ -224,7 +222,7 @@ func findKeyInMap(dataMap *yaml.Node, item *yaml.Node) int {
return -1
}
-func recurseNodeObjectEqual(lhs *yaml.Node, rhs *yaml.Node) bool {
+func recurseNodeObjectEqual(lhs *CandidateNode, rhs *CandidateNode) bool {
if len(lhs.Content) != len(rhs.Content) {
return false
}
@@ -242,28 +240,10 @@ func recurseNodeObjectEqual(lhs *yaml.Node, rhs *yaml.Node) bool {
return true
}
-func guessTagFromCustomType(node *yaml.Node) string {
- if strings.HasPrefix(node.Tag, "!!") {
- return node.Tag
- } else if node.Value == "" {
- log.Debug("guessTagFromCustomType: node has no value to guess the type with")
- return node.Tag
- }
- dataBucket, errorReading := parseSnippet(node.Value)
-
- if errorReading != nil {
- log.Debug("guessTagFromCustomType: could not guess underlying tag type %v", errorReading)
- return node.Tag
- }
- guessedTag := unwrapDoc(dataBucket).Tag
- log.Info("im guessing the tag %v is a %v", node.Tag, guessedTag)
- return guessedTag
-}
-
-func parseSnippet(value string) (*yaml.Node, error) {
+func parseSnippet(value string) (*CandidateNode, error) {
if value == "" {
- return &yaml.Node{
- Kind: yaml.ScalarNode,
+ return &CandidateNode{
+ Kind: ScalarNode,
Tag: "!!null",
}, nil
}
@@ -272,30 +252,26 @@ func parseSnippet(value string) (*yaml.Node, error) {
if err != nil {
return nil, err
}
- parsedNode, err := decoder.Decode()
+ result, err := decoder.Decode()
if err != nil {
return nil, err
}
- if len(parsedNode.Node.Content) == 0 {
- return nil, fmt.Errorf("bad data")
- }
- result := unwrapDoc(parsedNode.Node)
result.Line = 0
result.Column = 0
return result, err
}
-func recursiveNodeEqual(lhs *yaml.Node, rhs *yaml.Node) bool {
+func recursiveNodeEqual(lhs *CandidateNode, rhs *CandidateNode) bool {
if lhs.Kind != rhs.Kind {
return false
}
- if lhs.Kind == yaml.ScalarNode {
+ if lhs.Kind == ScalarNode {
//process custom tags of scalar nodes.
//dont worry about matching tags of maps or arrays.
- lhsTag := guessTagFromCustomType(lhs)
- rhsTag := guessTagFromCustomType(rhs)
+ lhsTag := lhs.guessTagFromCustomType()
+ rhsTag := rhs.guessTagFromCustomType()
if lhsTag != rhsTag {
return false
@@ -305,75 +281,32 @@ func recursiveNodeEqual(lhs *yaml.Node, rhs *yaml.Node) bool {
if lhs.Tag == "!!null" {
return true
- } else if lhs.Kind == yaml.ScalarNode {
+ } else if lhs.Kind == ScalarNode {
return lhs.Value == rhs.Value
- } else if lhs.Kind == yaml.SequenceNode {
+ } else if lhs.Kind == SequenceNode {
return recurseNodeArrayEqual(lhs, rhs)
- } else if lhs.Kind == yaml.MappingNode {
+ } else if lhs.Kind == MappingNode {
return recurseNodeObjectEqual(lhs, rhs)
}
return false
}
-func deepCloneContent(content []*yaml.Node) []*yaml.Node {
- clonedContent := make([]*yaml.Node, len(content))
- for i, child := range content {
- clonedContent[i] = deepClone(child)
- }
- return clonedContent
-}
-
-func deepCloneNoContent(node *yaml.Node) *yaml.Node {
- return deepCloneWithOptions(node, false)
-}
-func deepClone(node *yaml.Node) *yaml.Node {
- return deepCloneWithOptions(node, true)
-}
-
-func deepCloneWithOptions(node *yaml.Node, cloneContent bool) *yaml.Node {
- if node == nil {
- return nil
- }
- var clonedContent []*yaml.Node
- if cloneContent {
- clonedContent = deepCloneContent(node.Content)
- }
- return &yaml.Node{
- Content: clonedContent,
- Kind: node.Kind,
- Style: node.Style,
- Tag: node.Tag,
- Value: node.Value,
- Anchor: node.Anchor,
- Alias: node.Alias,
- HeadComment: node.HeadComment,
- LineComment: node.LineComment,
- FootComment: node.FootComment,
- Line: node.Line,
- Column: node.Column,
- }
-}
-
-// yaml numbers can be hex encoded...
+// yaml numbers can be hex and octal encoded...
func parseInt64(numberString string) (string, int64, error) {
if strings.HasPrefix(numberString, "0x") ||
strings.HasPrefix(numberString, "0X") {
num, err := strconv.ParseInt(numberString[2:], 16, 64)
return "0x%X", num, err
+ } else if strings.HasPrefix(numberString, "0o") {
+ num, err := strconv.ParseInt(numberString[2:], 8, 64)
+ return "0o%o", num, err
}
num, err := strconv.ParseInt(numberString, 10, 64)
return "%v", num, err
}
func parseInt(numberString string) (int, error) {
- var err error
- var parsed int64
- if strings.HasPrefix(numberString, "0x") ||
- strings.HasPrefix(numberString, "0X") {
- parsed, err = strconv.ParseInt(numberString[2:], 16, 64)
- } else {
- parsed, err = strconv.ParseInt(numberString, 10, 64)
- }
+ _, parsed, err := parseInt64(numberString)
if err != nil {
return 0, err
@@ -384,45 +317,19 @@ func parseInt(numberString string) (int, error) {
return int(parsed), err
}
-func createStringScalarNode(stringValue string) *yaml.Node {
- var node = &yaml.Node{Kind: yaml.ScalarNode}
- node.Value = stringValue
- node.Tag = "!!str"
- return node
-}
-
-func createScalarNode(value interface{}, stringValue string) *yaml.Node {
- var node = &yaml.Node{Kind: yaml.ScalarNode}
- node.Value = stringValue
-
- switch value.(type) {
- case float32, float64:
- node.Tag = "!!float"
- case int, int64, int32:
- node.Tag = "!!int"
- case bool:
- node.Tag = "!!bool"
- case string:
- node.Tag = "!!str"
- case nil:
- node.Tag = "!!null"
- }
- return node
-}
-
-func headAndLineComment(node *yaml.Node) string {
+func headAndLineComment(node *CandidateNode) string {
return headComment(node) + lineComment(node)
}
-func headComment(node *yaml.Node) string {
+func headComment(node *CandidateNode) string {
return strings.Replace(node.HeadComment, "#", "", 1)
}
-func lineComment(node *yaml.Node) string {
+func lineComment(node *CandidateNode) string {
return strings.Replace(node.LineComment, "#", "", 1)
}
-func footComment(node *yaml.Node) string {
+func footComment(node *CandidateNode) string {
return strings.Replace(node.FootComment, "#", "", 1)
}
@@ -434,7 +341,7 @@ func createValueOperation(value interface{}, stringValue string) *Operation {
OperationType: valueOpType,
Value: value,
StringValue: stringValue,
- CandidateNode: &CandidateNode{Node: node},
+ CandidateNode: node,
}
}
@@ -471,40 +378,46 @@ func NodeToString(node *CandidateNode) string {
if !log.IsEnabledFor(logging.DEBUG) {
return ""
}
- value := node.Node
- if value == nil {
+ if node == nil {
return "-- nil --"
}
- buf := new(bytes.Buffer)
- encoder := yaml.NewEncoder(buf)
- errorEncoding := encoder.Encode(value)
- if errorEncoding != nil {
- log.Error("Error debugging node, %v", errorEncoding.Error())
- }
- errorClosingEncoder := encoder.Close()
- if errorClosingEncoder != nil {
- log.Error("Error closing encoder: ", errorClosingEncoder.Error())
- }
- tag := value.Tag
- if value.Kind == yaml.DocumentNode {
- tag = "doc"
- } else if value.Kind == yaml.AliasNode {
+ tag := node.Tag
+ if node.Kind == AliasNode {
tag = "alias"
}
- return fmt.Sprintf(`D%v, P%v, (%v)::%v`, node.Document, node.Path, tag, buf.String())
+ valueToUse := node.Value
+ if valueToUse == "" {
+ valueToUse = fmt.Sprintf("%v kids", len(node.Content))
+ }
+ return fmt.Sprintf(`D%v, P%v, %v (%v)::%v`, node.GetDocument(), node.GetNicePath(), KindString(node.Kind), tag, valueToUse)
}
-func KindString(kind yaml.Kind) string {
+func NodeContentToString(node *CandidateNode, depth int) string {
+ if !log.IsEnabledFor(logging.DEBUG) {
+ return ""
+ }
+ var sb strings.Builder
+ for _, child := range node.Content {
+ for i := 0; i < depth; i++ {
+ sb.WriteString(" ")
+ }
+ sb.WriteString("- ")
+ sb.WriteString(NodeToString(child))
+ sb.WriteString("\n")
+ sb.WriteString(NodeContentToString(child, depth+1))
+ }
+ return sb.String()
+}
+
+func KindString(kind Kind) string {
switch kind {
- case yaml.ScalarNode:
+ case ScalarNode:
return "ScalarNode"
- case yaml.SequenceNode:
+ case SequenceNode:
return "SequenceNode"
- case yaml.MappingNode:
+ case MappingNode:
return "MappingNode"
- case yaml.DocumentNode:
- return "DocumentNode"
- case yaml.AliasNode:
+ case AliasNode:
return "AliasNode"
default:
return "unknown!"
diff --git a/pkg/yqlib/lib_test.go b/pkg/yqlib/lib_test.go
index c3e01009..ecd541a7 100644
--- a/pkg/yqlib/lib_test.go
+++ b/pkg/yqlib/lib_test.go
@@ -1,10 +1,10 @@
package yqlib
import (
+ "fmt"
"testing"
"github.com/mikefarah/yq/v4/test"
- yaml "gopkg.in/yaml.v3"
)
func TestGetLogger(t *testing.T) {
@@ -16,7 +16,7 @@ func TestGetLogger(t *testing.T) {
type parseSnippetScenario struct {
snippet string
- expected *yaml.Node
+ expected *CandidateNode
expectedError string
}
@@ -27,15 +27,15 @@ var parseSnippetScenarios = []parseSnippetScenario{
},
{
snippet: "",
- expected: &yaml.Node{
- Kind: yaml.ScalarNode,
+ expected: &CandidateNode{
+ Kind: ScalarNode,
Tag: "!!null",
},
},
{
snippet: "null",
- expected: &yaml.Node{
- Kind: yaml.ScalarNode,
+ expected: &CandidateNode{
+ Kind: ScalarNode,
Tag: "!!null",
Value: "null",
Line: 0,
@@ -44,8 +44,8 @@ var parseSnippetScenarios = []parseSnippetScenario{
},
{
snippet: "3",
- expected: &yaml.Node{
- Kind: yaml.ScalarNode,
+ expected: &CandidateNode{
+ Kind: ScalarNode,
Tag: "!!int",
Value: "3",
Line: 0,
@@ -54,8 +54,8 @@ var parseSnippetScenarios = []parseSnippetScenario{
},
{
snippet: "cat",
- expected: &yaml.Node{
- Kind: yaml.ScalarNode,
+ expected: &CandidateNode{
+ Kind: ScalarNode,
Tag: "!!str",
Value: "cat",
Line: 0,
@@ -64,8 +64,8 @@ var parseSnippetScenarios = []parseSnippetScenario{
},
{
snippet: "3.1",
- expected: &yaml.Node{
- Kind: yaml.ScalarNode,
+ expected: &CandidateNode{
+ Kind: ScalarNode,
Tag: "!!float",
Value: "3.1",
Line: 0,
@@ -74,8 +74,8 @@ var parseSnippetScenarios = []parseSnippetScenario{
},
{
snippet: "true",
- expected: &yaml.Node{
- Kind: yaml.ScalarNode,
+ expected: &CandidateNode{
+ Kind: ScalarNode,
Tag: "!!bool",
Value: "true",
Line: 0,
@@ -93,7 +93,7 @@ func TestParseSnippet(t *testing.T) {
} else {
test.AssertResultComplexWithContext(t, tt.expectedError, err.Error(), tt.snippet)
}
- return
+ continue
}
if err != nil {
t.Error(tt.snippet)
@@ -102,3 +102,37 @@ func TestParseSnippet(t *testing.T) {
test.AssertResultComplexWithContext(t, tt.expected, actual, tt.snippet)
}
}
+
+type parseInt64Scenario struct {
+ numberString string
+ expectedParsedNumber int64
+}
+
+var parseInt64Scenarios = []parseInt64Scenario{
+ {
+ numberString: "34",
+ expectedParsedNumber: 34,
+ },
+ {
+ numberString: "0x10",
+ expectedParsedNumber: 16,
+ },
+ {
+ numberString: "0o10",
+ expectedParsedNumber: 8,
+ },
+}
+
+func TestParseInt64(t *testing.T) {
+ for _, tt := range parseInt64Scenarios {
+ format, actualNumber, err := parseInt64(tt.numberString)
+
+ if err != nil {
+ t.Error(tt.numberString)
+ t.Error(err)
+ }
+ test.AssertResultComplexWithContext(t, tt.expectedParsedNumber, actualNumber, tt.numberString)
+
+ test.AssertResultComplexWithContext(t, tt.numberString, fmt.Sprintf(format, actualNumber), fmt.Sprintf("Formatting of: %v", tt.numberString))
+ }
+}
diff --git a/pkg/yqlib/lua_test.go b/pkg/yqlib/lua_test.go
index bb36e9cc..6e0bc8b6 100644
--- a/pkg/yqlib/lua_test.go
+++ b/pkg/yqlib/lua_test.go
@@ -31,6 +31,38 @@ cities:
- Perth
`,
},
+ {
+ skipDoc: true,
+ description: "path",
+ expression: ".cities[2] | path",
+ input: `return {
+ ["country"] = "Australia"; -- this place
+ ["cities"] = {
+ "Sydney",
+ "Melbourne",
+ "Brisbane",
+ "Perth",
+ };
+};
+`,
+ expected: "- cities\n- 2\n",
+ },
+ {
+ skipDoc: true,
+ description: "path",
+ expression: ".cities[2] | key",
+ input: `return {
+ ["country"] = "Australia"; -- this place
+ ["cities"] = {
+ "Sydney",
+ "Melbourne",
+ "Brisbane",
+ "Perth",
+ };
+};
+`,
+ expected: "2\n",
+ },
{
description: "Basic output example",
scenarioType: "encode",
diff --git a/pkg/yqlib/matchKeyString.go b/pkg/yqlib/matchKeyString.go
index bfea235e..bdfaa8dc 100644
--- a/pkg/yqlib/matchKeyString.go
+++ b/pkg/yqlib/matchKeyString.go
@@ -4,7 +4,6 @@ func matchKey(name string, pattern string) (matched bool) {
if pattern == "" {
return name == pattern
}
- log.Debug("pattern: %v", pattern)
if pattern == "*" {
log.Debug("wild!")
return true
diff --git a/pkg/yqlib/operator_add.go b/pkg/yqlib/operator_add.go
index 5b95c34b..611dfa20 100644
--- a/pkg/yqlib/operator_add.go
+++ b/pkg/yqlib/operator_add.go
@@ -5,8 +5,6 @@ import (
"strconv"
"strings"
"time"
-
- yaml "gopkg.in/yaml.v3"
)
func createAddOp(lhs *ExpressionNode, rhs *ExpressionNode) *ExpressionNode {
@@ -19,23 +17,21 @@ func addAssignOperator(d *dataTreeNavigator, context Context, expressionNode *Ex
return compoundAssignFunction(d, context, expressionNode, createAddOp)
}
-func toNodes(candidate *CandidateNode, lhs *CandidateNode) ([]*yaml.Node, error) {
- if candidate.Node.Tag == "!!null" {
- return []*yaml.Node{}, nil
- }
- clone, err := candidate.Copy()
- if err != nil {
- return nil, err
+func toNodes(candidate *CandidateNode, lhs *CandidateNode) []*CandidateNode {
+ if candidate.Tag == "!!null" {
+ return []*CandidateNode{}
}
- switch candidate.Node.Kind {
- case yaml.SequenceNode:
- return clone.Node.Content, nil
+ clone := candidate.Copy()
+
+ switch candidate.Kind {
+ case SequenceNode:
+ return clone.Content
default:
- if len(lhs.Node.Content) > 0 {
- clone.Node.Style = lhs.Node.Content[0].Style
+ if len(lhs.Content) > 0 {
+ clone.Style = lhs.Content[0].Style
}
- return []*yaml.Node{clone.Node}, nil
+ return []*CandidateNode{clone}
}
}
@@ -47,50 +43,42 @@ func addOperator(d *dataTreeNavigator, context Context, expressionNode *Expressi
}
func add(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
- lhs.Node = unwrapDoc(lhs.Node)
- rhs.Node = unwrapDoc(rhs.Node)
-
- lhsNode := lhs.Node
+ lhsNode := lhs
if lhsNode.Tag == "!!null" {
- return lhs.CreateReplacement(rhs.Node), nil
+ return lhs.CopyAsReplacement(rhs), nil
}
- target := lhs.CreateReplacement(&yaml.Node{
- Anchor: lhs.Node.Anchor,
- })
+ target := lhs.CopyWithoutContent()
switch lhsNode.Kind {
- case yaml.MappingNode:
- if rhs.Node.Kind != yaml.MappingNode {
- return nil, fmt.Errorf("%v (%v) cannot be added to a %v (%v)", rhs.Node.Tag, rhs.GetNicePath(), lhsNode.Tag, lhs.GetNicePath())
+ case MappingNode:
+ if rhs.Kind != MappingNode {
+ return nil, fmt.Errorf("%v (%v) cannot be added to a %v (%v)", rhs.Tag, rhs.GetNicePath(), lhsNode.Tag, lhs.GetNicePath())
}
addMaps(target, lhs, rhs)
- case yaml.SequenceNode:
- if err := addSequences(target, lhs, rhs); err != nil {
- return nil, err
+ case SequenceNode:
+ addSequences(target, lhs, rhs)
+ case ScalarNode:
+ if rhs.Kind != ScalarNode {
+ return nil, fmt.Errorf("%v (%v) cannot be added to a %v (%v)", rhs.Tag, rhs.GetNicePath(), lhsNode.Tag, lhs.GetNicePath())
}
-
- case yaml.ScalarNode:
- if rhs.Node.Kind != yaml.ScalarNode {
- return nil, fmt.Errorf("%v (%v) cannot be added to a %v (%v)", rhs.Node.Tag, rhs.GetNicePath(), lhsNode.Tag, lhs.GetNicePath())
- }
- target.Node.Kind = yaml.ScalarNode
- target.Node.Style = lhsNode.Style
- if err := addScalars(context, target, lhsNode, rhs.Node); err != nil {
+ target.Kind = ScalarNode
+ target.Style = lhsNode.Style
+ if err := addScalars(context, target, lhsNode, rhs); err != nil {
return nil, err
}
}
return target, nil
}
-func addScalars(context Context, target *CandidateNode, lhs *yaml.Node, rhs *yaml.Node) error {
+func addScalars(context Context, target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error {
lhsTag := lhs.Tag
- rhsTag := guessTagFromCustomType(rhs)
+ rhsTag := rhs.guessTagFromCustomType()
lhsIsCustom := false
if !strings.HasPrefix(lhsTag, "!!") {
// custom tag - we have to have a guess
- lhsTag = guessTagFromCustomType(lhs)
+ lhsTag = lhs.guessTagFromCustomType()
lhsIsCustom = true
}
@@ -106,15 +94,16 @@ func addScalars(context Context, target *CandidateNode, lhs *yaml.Node, rhs *yam
return addDateTimes(context.GetDateTimeLayout(), target, lhs, rhs)
} else if lhsTag == "!!str" {
- target.Node.Tag = lhs.Tag
+ target.Tag = lhs.Tag
if rhsTag == "!!null" {
- target.Node.Value = lhs.Value
+ target.Value = lhs.Value
} else {
- target.Node.Value = lhs.Value + rhs.Value
+ target.Value = lhs.Value + rhs.Value
}
+
} else if rhsTag == "!!str" {
- target.Node.Tag = rhs.Tag
- target.Node.Value = lhs.Value + rhs.Value
+ target.Tag = rhs.Tag
+ target.Value = lhs.Value + rhs.Value
} else if lhsTag == "!!int" && rhsTag == "!!int" {
format, lhsNum, err := parseInt64(lhs.Value)
if err != nil {
@@ -125,8 +114,8 @@ func addScalars(context Context, target *CandidateNode, lhs *yaml.Node, rhs *yam
return err
}
sum := lhsNum + rhsNum
- target.Node.Tag = lhs.Tag
- target.Node.Value = fmt.Sprintf(format, sum)
+ target.Tag = lhs.Tag
+ target.Value = fmt.Sprintf(format, sum)
} else if (lhsTag == "!!int" || lhsTag == "!!float") && (rhsTag == "!!int" || rhsTag == "!!float") {
lhsNum, err := strconv.ParseFloat(lhs.Value, 64)
if err != nil {
@@ -138,18 +127,18 @@ func addScalars(context Context, target *CandidateNode, lhs *yaml.Node, rhs *yam
}
sum := lhsNum + rhsNum
if lhsIsCustom {
- target.Node.Tag = lhs.Tag
+ target.Tag = lhs.Tag
} else {
- target.Node.Tag = "!!float"
+ target.Tag = "!!float"
}
- target.Node.Value = fmt.Sprintf("%v", sum)
+ target.Value = fmt.Sprintf("%v", sum)
} else {
return fmt.Errorf("%v cannot be added to %v", lhsTag, rhsTag)
}
return nil
}
-func addDateTimes(layout string, target *CandidateNode, lhs *yaml.Node, rhs *yaml.Node) error {
+func addDateTimes(layout string, target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error {
duration, err := time.ParseDuration(rhs.Value)
if err != nil {
@@ -162,52 +151,57 @@ func addDateTimes(layout string, target *CandidateNode, lhs *yaml.Node, rhs *yam
}
newTime := currentTime.Add(duration)
- target.Node.Value = newTime.Format(layout)
+ target.Value = newTime.Format(layout)
return nil
}
-func addSequences(target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error {
- target.Node.Kind = yaml.SequenceNode
- if len(lhs.Node.Content) > 0 {
- target.Node.Style = lhs.Node.Style
+func addSequences(target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) {
+ log.Debugf("adding sequences! target: %v; lhs %v; rhs: %v", NodeToString(target), NodeToString(lhs), NodeToString(rhs))
+ target.Kind = SequenceNode
+ if len(lhs.Content) == 0 {
+ log.Debugf("dont copy lhs style")
+ target.Style = 0
}
- target.Node.Tag = lhs.Node.Tag
+ target.Tag = lhs.Tag
- extraNodes, err := toNodes(rhs, lhs)
- if err != nil {
- return err
- }
-
- target.Node.Content = append(deepCloneContent(lhs.Node.Content), extraNodes...)
- return nil
+ extraNodes := toNodes(rhs, lhs)
+ target.AddChildren(lhs.Content)
+ target.AddChildren(extraNodes)
}
func addMaps(target *CandidateNode, lhsC *CandidateNode, rhsC *CandidateNode) {
- lhs := lhsC.Node
- rhs := rhsC.Node
+ lhs := lhsC
+ rhs := rhsC
- target.Node.Content = make([]*yaml.Node, len(lhs.Content))
- copy(target.Node.Content, lhs.Content)
+ if len(lhs.Content) == 0 {
+ log.Debugf("dont copy lhs style")
+ target.Style = 0
+ }
+
+ target.Content = make([]*CandidateNode, 0)
+ target.AddChildren(lhs.Content)
for index := 0; index < len(rhs.Content); index = index + 2 {
key := rhs.Content[index]
value := rhs.Content[index+1]
log.Debug("finding %v", key.Value)
- indexInLHS := findKeyInMap(target.Node, key)
+ indexInLHS := findKeyInMap(target, key)
log.Debug("indexInLhs %v", indexInLHS)
if indexInLHS < 0 {
// not in there, append it
- target.Node.Content = append(target.Node.Content, key, value)
+ target.AddKeyValueChild(key, value)
} else {
// it's there, replace it
- target.Node.Content[indexInLHS+1] = value
+ oldValue := target.Content[indexInLHS+1]
+ newValueCopy := oldValue.CopyAsReplacement(value)
+ target.Content[indexInLHS+1] = newValueCopy
}
}
- target.Node.Kind = yaml.MappingNode
+ target.Kind = MappingNode
if len(lhs.Content) > 0 {
- target.Node.Style = lhs.Style
+ target.Style = lhs.Style
}
- target.Node.Tag = lhs.Tag
+ target.Tag = lhs.Tag
}
diff --git a/pkg/yqlib/operator_add_test.go b/pkg/yqlib/operator_add_test.go
index 918d0d39..3478dbdd 100644
--- a/pkg/yqlib/operator_add_test.go
+++ b/pkg/yqlib/operator_add_test.go
@@ -36,7 +36,7 @@ var addOperatorScenarios = []expressionScenario{
document: `{}`,
expression: "(.a + .b) as $x | .",
expected: []string{
- "D0, P[], (doc)::{}\n",
+ "D0, P[], (!!map)::{}\n",
},
},
{
@@ -44,7 +44,7 @@ var addOperatorScenarios = []expressionScenario{
document: `a: 0`,
expression: ".a += .b.c",
expected: []string{
- "D0, P[], (doc)::a: 0\n",
+ "D0, P[], (!!map)::a: 0\n",
},
},
@@ -63,7 +63,7 @@ var addOperatorScenarios = []expressionScenario{
dontFormatInputForDoc: true,
expression: `.a += .b`,
expected: []string{
- "D0, P[], (doc)::a: [1, 2, 3, 4]\nb:\n - 3\n - 4\n",
+ "D0, P[], (!!map)::a: [1, 2, 3, 4]\nb:\n - 3\n - 4\n",
},
},
{
@@ -98,7 +98,7 @@ var addOperatorScenarios = []expressionScenario{
document: `a: ['dog']`,
expression: `.a += "cat"`,
expected: []string{
- "D0, P[], (doc)::a: ['dog', 'cat']\n",
+ "D0, P[], (!!map)::a: ['dog', 'cat']\n",
},
},
{
@@ -106,7 +106,7 @@ var addOperatorScenarios = []expressionScenario{
document: `a: [dog]`,
expression: `.a = ["cat"] + .a`,
expected: []string{
- "D0, P[], (doc)::a: [cat, dog]\n",
+ "D0, P[], (!!map)::a: [cat, dog]\n",
},
},
{
@@ -116,7 +116,7 @@ var addOperatorScenarios = []expressionScenario{
document: `{a: ['dog'], b: cat}`,
expression: `.a = .a + .b`,
expected: []string{
- "D0, P[], (doc)::{a: ['dog', 'cat'], b: cat}\n",
+ "D0, P[], (!!map)::{a: ['dog', 'cat'], b: cat}\n",
},
},
{
@@ -125,7 +125,7 @@ var addOperatorScenarios = []expressionScenario{
document: `a: []`,
expression: `.a += "cat"`,
expected: []string{
- "D0, P[], (doc)::a:\n - cat\n",
+ "D0, P[], (!!map)::a:\n - cat\n",
},
},
{
@@ -134,7 +134,7 @@ var addOperatorScenarios = []expressionScenario{
document: `a: [dog]`,
expression: `.a += "cat"`,
expected: []string{
- "D0, P[], (doc)::a: [dog, cat]\n",
+ "D0, P[], (!!map)::a: [dog, cat]\n",
},
},
{
@@ -171,7 +171,7 @@ var addOperatorScenarios = []expressionScenario{
document: `a: {}`,
expression: `.a += {"b": "cat"}`,
expected: []string{
- "D0, P[], (doc)::a:\n b: cat\n",
+ "D0, P[], (!!map)::a:\n b: cat\n",
},
},
{
@@ -180,7 +180,7 @@ var addOperatorScenarios = []expressionScenario{
document: `a: {c: dog}`,
expression: `.a += {"b": "cat"}`,
expected: []string{
- "D0, P[], (doc)::a: {c: dog, b: cat}\n",
+ "D0, P[], (!!map)::a: {c: dog, b: cat}\n",
},
},
{
@@ -196,7 +196,7 @@ var addOperatorScenarios = []expressionScenario{
document: `a: { a1: {b: [cat]}, a2: {b: [dog]}, a3: {} }`,
expression: `.a[].b += ["mouse"]`,
expected: []string{
- "D0, P[], (doc)::a: {a1: {b: [cat, mouse]}, a2: {b: [dog, mouse]}, a3: {b: [mouse]}}\n",
+ "D0, P[], (!!map)::a: {a1: {b: [cat, mouse]}, a2: {b: [dog, mouse]}, a3: {b: [mouse]}}\n",
},
},
{
@@ -204,7 +204,7 @@ var addOperatorScenarios = []expressionScenario{
document: `{a: cat, b: meow}`,
expression: `.a += .b`,
expected: []string{
- "D0, P[], (doc)::{a: catmeow, b: meow}\n",
+ "D0, P[], (!!map)::{a: catmeow, b: meow}\n",
},
},
{
@@ -245,7 +245,7 @@ var addOperatorScenarios = []expressionScenario{
document: `{a: 3, b: 4.9}`,
expression: `.a = .a + .b`,
expected: []string{
- "D0, P[], (doc)::{a: 7.9, b: 4.9}\n",
+ "D0, P[], (!!map)::{a: 7.9, b: 4.9}\n",
},
},
{
@@ -254,7 +254,7 @@ var addOperatorScenarios = []expressionScenario{
document: `{a: 3, b: 4}`,
expression: `.a = .a + .b`,
expected: []string{
- "D0, P[], (doc)::{a: 7, b: 4}\n",
+ "D0, P[], (!!map)::{a: 7, b: 4}\n",
},
},
{
@@ -262,7 +262,7 @@ var addOperatorScenarios = []expressionScenario{
document: `{a: 3, b: 5}`,
expression: `.[] += 1`,
expected: []string{
- "D0, P[], (doc)::{a: 4, b: 6}\n",
+ "D0, P[], (!!map)::{a: 4, b: 6}\n",
},
},
{
@@ -271,7 +271,7 @@ var addOperatorScenarios = []expressionScenario{
document: `a: 2021-01-01T00:00:00Z`,
expression: `.a += "3h10m"`,
expected: []string{
- "D0, P[], (doc)::a: 2021-01-01T03:10:00Z\n",
+ "D0, P[], (!!map)::a: 2021-01-01T03:10:00Z\n",
},
},
{
@@ -280,7 +280,7 @@ var addOperatorScenarios = []expressionScenario{
document: `a: 2021-01-01`,
expression: `.a += "24h"`,
expected: []string{
- "D0, P[], (doc)::a: 2021-01-02T00:00:00Z\n",
+ "D0, P[], (!!map)::a: 2021-01-02T00:00:00Z\n",
},
},
{
@@ -289,7 +289,7 @@ var addOperatorScenarios = []expressionScenario{
document: `a: Saturday, 15-Dec-01 at 2:59AM GMT`,
expression: `with_dtf("Monday, 02-Jan-06 at 3:04PM MST", .a += "3h1m")`,
expected: []string{
- "D0, P[], (doc)::a: Saturday, 15-Dec-01 at 6:00AM GMT\n",
+ "D0, P[], (!!map)::a: Saturday, 15-Dec-01 at 6:00AM GMT\n",
},
},
{
@@ -299,7 +299,7 @@ var addOperatorScenarios = []expressionScenario{
document: `a: !cat Saturday, 15-Dec-01 at 2:59AM GMT`,
expression: `with_dtf("Monday, 02-Jan-06 at 3:04PM MST", .a += "3h1m")`,
expected: []string{
- "D0, P[], (doc)::a: !cat Saturday, 15-Dec-01 at 6:00AM GMT\n",
+ "D0, P[], (!!map)::a: !cat Saturday, 15-Dec-01 at 6:00AM GMT\n",
},
},
{
@@ -316,7 +316,7 @@ var addOperatorScenarios = []expressionScenario{
document: "a: {thing: {name: Astuff, value: x}, a1: cool}\nb: {thing: {name: Bstuff, legs: 3}, b1: neat}",
expression: `.a += .b`,
expected: []string{
- "D0, P[], (doc)::a: {thing: {name: Bstuff, legs: 3}, a1: cool, b1: neat}\nb: {thing: {name: Bstuff, legs: 3}, b1: neat}\n",
+ "D0, P[], (!!map)::a: {thing: {name: Bstuff, legs: 3}, a1: cool, b1: neat}\nb: {thing: {name: Bstuff, legs: 3}, b1: neat}\n",
},
},
{
@@ -325,7 +325,7 @@ var addOperatorScenarios = []expressionScenario{
document: "a: !horse cat\nb: !goat _meow",
expression: `.a += .b`,
expected: []string{
- "D0, P[], (doc)::a: !horse cat_meow\nb: !goat _meow\n",
+ "D0, P[], (!!map)::a: !horse cat_meow\nb: !goat _meow\n",
},
},
{
@@ -334,7 +334,7 @@ var addOperatorScenarios = []expressionScenario{
document: "a: !horse 1.2\nb: !goat 2.3",
expression: `.a += .b`,
expected: []string{
- "D0, P[], (doc)::a: !horse 3.5\nb: !goat 2.3\n",
+ "D0, P[], (!!map)::a: !horse 3.5\nb: !goat 2.3\n",
},
},
{
@@ -342,7 +342,7 @@ var addOperatorScenarios = []expressionScenario{
document: "a: !horse 2\nb: !goat 2.3",
expression: `.a += .b`,
expected: []string{
- "D0, P[], (doc)::a: !horse 4.3\nb: !goat 2.3\n",
+ "D0, P[], (!!map)::a: !horse 4.3\nb: !goat 2.3\n",
},
},
{
@@ -350,7 +350,7 @@ var addOperatorScenarios = []expressionScenario{
document: "a: 2\nb: !goat 2.3",
expression: `.a += .b`,
expected: []string{
- "D0, P[], (doc)::a: 4.3\nb: !goat 2.3\n",
+ "D0, P[], (!!map)::a: 4.3\nb: !goat 2.3\n",
},
},
{
@@ -359,7 +359,7 @@ var addOperatorScenarios = []expressionScenario{
document: "a: !horse 2\nb: !goat 3",
expression: `.a += .b`,
expected: []string{
- "D0, P[], (doc)::a: !horse 5\nb: !goat 3\n",
+ "D0, P[], (!!map)::a: !horse 5\nb: !goat 3\n",
},
},
{
@@ -369,7 +369,7 @@ var addOperatorScenarios = []expressionScenario{
document: "a: !horse [a]\nb: !goat [b]",
expression: `.a += .b`,
expected: []string{
- "D0, P[], (doc)::a: !horse [a, b]\nb: !goat [b]\n",
+ "D0, P[], (!!map)::a: !horse [a, b]\nb: !goat [b]\n",
},
},
{
@@ -378,7 +378,7 @@ var addOperatorScenarios = []expressionScenario{
document: "a: &horse [1]",
expression: `.a += 2`,
expected: []string{
- "D0, P[], (doc)::a: &horse [1, 2]\n",
+ "D0, P[], (!!map)::a: &horse [1, 2]\n",
},
},
{
diff --git a/pkg/yqlib/operator_alternative.go b/pkg/yqlib/operator_alternative.go
index ca8569fc..0069d4ff 100644
--- a/pkg/yqlib/operator_alternative.go
+++ b/pkg/yqlib/operator_alternative.go
@@ -9,10 +9,7 @@ func alternativeOperator(d *dataTreeNavigator, context Context, expressionNode *
if lhs == nil {
return nil, nil
}
- truthy, err := isTruthy(lhs)
- if err != nil {
- return nil, err
- }
+ truthy := isTruthyNode(lhs)
if truthy {
return lhs, nil
}
@@ -29,15 +26,9 @@ func alternativeFunc(d *dataTreeNavigator, context Context, lhs *CandidateNode,
if rhs == nil {
return lhs, nil
}
- lhs.Node = unwrapDoc(lhs.Node)
- rhs.Node = unwrapDoc(rhs.Node)
- log.Debugf("Alternative LHS: %v", lhs.Node.Tag)
- log.Debugf("- RHS: %v", rhs.Node.Tag)
- isTrue, err := isTruthy(lhs)
- if err != nil {
- return nil, err
- } else if isTrue {
+ isTrue := isTruthyNode(lhs)
+ if isTrue {
return lhs, nil
}
return rhs, nil
diff --git a/pkg/yqlib/operator_alternative_test.go b/pkg/yqlib/operator_alternative_test.go
index e70b8b25..24470e6c 100644
--- a/pkg/yqlib/operator_alternative_test.go
+++ b/pkg/yqlib/operator_alternative_test.go
@@ -19,7 +19,7 @@ var alternativeOperatorScenarios = []expressionScenario{
expression: `(.b // "hello") as $x | .`,
document: `a: bridge`,
expected: []string{
- "D0, P[], (doc)::a: bridge\n",
+ "D0, P[], (!!map)::a: bridge\n",
},
},
{
@@ -91,7 +91,7 @@ var alternativeOperatorScenarios = []expressionScenario{
expression: "(.a // (.a = 0)) += 1",
document: `a: 1`,
expected: []string{
- "D0, P[], (doc)::a: 2\n",
+ "D0, P[], (!!map)::a: 2\n",
},
},
{
diff --git a/pkg/yqlib/operator_anchors_aliases.go b/pkg/yqlib/operator_anchors_aliases.go
index caaf364b..d9d73754 100644
--- a/pkg/yqlib/operator_anchors_aliases.go
+++ b/pkg/yqlib/operator_anchors_aliases.go
@@ -3,8 +3,6 @@ package yqlib
import (
"container/list"
"fmt"
-
- yaml "gopkg.in/yaml.v3"
)
func assignAliasOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@@ -18,7 +16,7 @@ func assignAliasOperator(d *dataTreeNavigator, context Context, expressionNode *
return Context{}, err
}
if rhs.MatchingNodes.Front() != nil {
- aliasName = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
+ aliasName = rhs.MatchingNodes.Front().Value.(*CandidateNode).Value
}
}
@@ -38,13 +36,13 @@ func assignAliasOperator(d *dataTreeNavigator, context Context, expressionNode *
return Context{}, err
}
if rhs.MatchingNodes.Front() != nil {
- aliasName = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
+ aliasName = rhs.MatchingNodes.Front().Value.(*CandidateNode).Value
}
}
if aliasName != "" {
- candidate.Node.Kind = yaml.AliasNode
- candidate.Node.Value = aliasName
+ candidate.Kind = AliasNode
+ candidate.Value = aliasName
}
}
return context, nil
@@ -56,8 +54,7 @@ func getAliasOperator(d *dataTreeNavigator, context Context, expressionNode *Exp
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- node := &yaml.Node{Kind: yaml.ScalarNode, Value: candidate.Node.Value, Tag: "!!str"}
- result := candidate.CreateReplacement(node)
+ result := candidate.CreateReplacement(ScalarNode, "!!str", candidate.Value)
results.PushBack(result)
}
return context.ChildContext(results), nil
@@ -75,7 +72,7 @@ func assignAnchorOperator(d *dataTreeNavigator, context Context, expressionNode
}
if rhs.MatchingNodes.Front() != nil {
- anchorName = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
+ anchorName = rhs.MatchingNodes.Front().Value.(*CandidateNode).Value
}
}
@@ -96,11 +93,11 @@ func assignAnchorOperator(d *dataTreeNavigator, context Context, expressionNode
}
if rhs.MatchingNodes.Front() != nil {
- anchorName = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
+ anchorName = rhs.MatchingNodes.Front().Value.(*CandidateNode).Value
}
}
- candidate.Node.Anchor = anchorName
+ candidate.Anchor = anchorName
}
return context, nil
}
@@ -111,9 +108,8 @@ func getAnchorOperator(d *dataTreeNavigator, context Context, expressionNode *Ex
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- anchor := candidate.Node.Anchor
- node := &yaml.Node{Kind: yaml.ScalarNode, Value: anchor, Tag: "!!str"}
- result := candidate.CreateReplacement(node)
+ anchor := candidate.Anchor
+ result := candidate.CreateReplacement(ScalarNode, "!!str", anchor)
results.PushBack(result)
}
return context.ChildContext(results), nil
@@ -131,7 +127,7 @@ func explodeOperator(d *dataTreeNavigator, context Context, expressionNode *Expr
return Context{}, err
}
for childEl := rhs.MatchingNodes.Front(); childEl != nil; childEl = childEl.Next() {
- err = explodeNode(childEl.Value.(*CandidateNode).Node, context)
+ err = explodeNode(childEl.Value.(*CandidateNode), context)
if err != nil {
return Context{}, err
}
@@ -142,7 +138,7 @@ func explodeOperator(d *dataTreeNavigator, context Context, expressionNode *Expr
return context, nil
}
-func reconstructAliasedMap(node *yaml.Node, context Context) error {
+func reconstructAliasedMap(node *CandidateNode, context Context) error {
var newContent = list.New()
// can I short cut here by prechecking if there's an anchor in the map?
// no it needs to recurse in overrideEntry.
@@ -157,7 +153,7 @@ func reconstructAliasedMap(node *yaml.Node, context Context) error {
return err
}
} else {
- if valueNode.Kind == yaml.SequenceNode {
+ if valueNode.Kind == SequenceNode {
log.Debugf("an alias merge list!")
for index := len(valueNode.Content) - 1; index >= 0; index = index - 1 {
aliasNode := valueNode.Content[index]
@@ -175,39 +171,39 @@ func reconstructAliasedMap(node *yaml.Node, context Context) error {
}
}
}
- node.Content = make([]*yaml.Node, newContent.Len())
- index := 0
+ node.Content = make([]*CandidateNode, 0)
for newEl := newContent.Front(); newEl != nil; newEl = newEl.Next() {
- node.Content[index] = newEl.Value.(*yaml.Node)
- index++
+ node.AddChild(newEl.Value.(*CandidateNode))
}
return nil
}
-func explodeNode(node *yaml.Node, context Context) error {
+func explodeNode(node *CandidateNode, context Context) error {
+ log.Debugf("explodeNode - %v", NodeToString(node))
node.Anchor = ""
switch node.Kind {
- case yaml.SequenceNode, yaml.DocumentNode:
+ case SequenceNode:
for index, contentNode := range node.Content {
- log.Debugf("exploding index %v", index)
+ log.Debugf("explodeNode - index %v", index)
errorInContent := explodeNode(contentNode, context)
if errorInContent != nil {
return errorInContent
}
}
return nil
- case yaml.AliasNode:
- log.Debugf("its an alias!")
+ case AliasNode:
+ log.Debugf("explodeNode - an alias to %v", NodeToString(node.Alias))
if node.Alias != nil {
node.Kind = node.Alias.Kind
node.Style = node.Alias.Style
node.Tag = node.Alias.Tag
- node.Content = deepCloneContent(node.Alias.Content)
+ node.AddChildren(node.Alias.Content)
node.Value = node.Alias.Value
node.Alias = nil
}
+ log.Debug("now I'm %v", NodeToString(node))
return nil
- case yaml.MappingNode:
+ case MappingNode:
// //check the map has an alias in it
hasAlias := false
for index := 0; index < len(node.Content); index = index + 2 {
@@ -241,11 +237,13 @@ func explodeNode(node *yaml.Node, context Context) error {
}
}
-func applyAlias(node *yaml.Node, alias *yaml.Node, aliasIndex int, newContent Context) error {
+func applyAlias(node *CandidateNode, alias *CandidateNode, aliasIndex int, newContent Context) error {
+ log.Debug("alias is nil ?")
if alias == nil {
return nil
}
- if alias.Kind != yaml.MappingNode {
+ log.Debug("alias: %v", NodeToString(alias))
+ if alias.Kind != MappingNode {
return fmt.Errorf("merge anchor only supports maps, got %v instead", alias.Tag)
}
for index := 0; index < len(alias.Content); index = index + 2 {
@@ -260,7 +258,7 @@ func applyAlias(node *yaml.Node, alias *yaml.Node, aliasIndex int, newContent Co
return nil
}
-func overrideEntry(node *yaml.Node, key *yaml.Node, value *yaml.Node, startIndex int, newContent Context) error {
+func overrideEntry(node *CandidateNode, key *CandidateNode, value *CandidateNode, startIndex int, newContent Context) error {
err := explodeNode(value, newContent)
@@ -270,8 +268,8 @@ func overrideEntry(node *yaml.Node, key *yaml.Node, value *yaml.Node, startIndex
for newEl := newContent.MatchingNodes.Front(); newEl != nil; newEl = newEl.Next() {
valueEl := newEl.Next() // move forward twice
- keyNode := newEl.Value.(*yaml.Node)
- log.Debugf("checking new content %v:%v", keyNode.Value, valueEl.Value.(*yaml.Node).Value)
+ keyNode := newEl.Value.(*CandidateNode)
+ log.Debugf("checking new content %v:%v", keyNode.Value, valueEl.Value.(*CandidateNode).Value)
if keyNode.Value == key.Value && keyNode.Alias == nil && key.Alias == nil {
log.Debugf("overridign new content")
valueEl.Value = value
diff --git a/pkg/yqlib/operator_anchors_aliases_test.go b/pkg/yqlib/operator_anchors_aliases_test.go
index 2db367b6..f866aca5 100644
--- a/pkg/yqlib/operator_anchors_aliases_test.go
+++ b/pkg/yqlib/operator_anchors_aliases_test.go
@@ -24,7 +24,7 @@ thingTwo:
<<: *item_value
`
-var expectedUpdatedArrayRef = `D0, P[], (doc)::item_value: &item_value
+var expectedUpdatedArrayRef = `D0, P[], (!!map)::item_value: &item_value
value: true
thingOne:
name: item_1
@@ -34,6 +34,25 @@ thingTwo:
!!merge <<: *item_value
`
+var explodeMergeAnchorsExpected = `D0, P[], (!!map)::foo:
+ a: foo_a
+ thing: foo_thing
+ c: foo_c
+bar:
+ b: bar_b
+ thing: bar_thing
+ c: bar_c
+foobarList:
+ b: bar_b
+ thing: foo_thing
+ c: foobarList_c
+ a: foo_a
+foobar:
+ c: foo_c
+ a: foo_a
+ thing: foobar_thing
+`
+
var anchorOperatorScenarios = []expressionScenario{
{
skipDoc: true,
@@ -76,7 +95,7 @@ var anchorOperatorScenarios = []expressionScenario{
document: `a: cat`,
expression: `.a anchor = "foobar"`,
expected: []string{
- "D0, P[], (doc)::a: &foobar cat\n",
+ "D0, P[], (!!map)::a: &foobar cat\n",
},
},
{
@@ -84,7 +103,7 @@ var anchorOperatorScenarios = []expressionScenario{
document: `a: {b: cat}`,
expression: `.a anchor |= .b`,
expected: []string{
- "D0, P[], (doc)::a: &cat {b: cat}\n",
+ "D0, P[], (!!map)::a: &cat {b: cat}\n",
},
},
{
@@ -92,7 +111,7 @@ var anchorOperatorScenarios = []expressionScenario{
document: `a: {c: cat}`,
expression: `.a anchor |= .b`,
expected: []string{
- "D0, P[], (doc)::a: {c: cat}\n",
+ "D0, P[], (!!map)::a: {c: cat}\n",
},
},
{
@@ -100,7 +119,7 @@ var anchorOperatorScenarios = []expressionScenario{
document: `a: {c: cat}`,
expression: `.a anchor = .b`,
expected: []string{
- "D0, P[], (doc)::a: {c: cat}\n",
+ "D0, P[], (!!map)::a: {c: cat}\n",
},
},
{
@@ -116,7 +135,7 @@ var anchorOperatorScenarios = []expressionScenario{
document: `{b: &meow purr, a: cat}`,
expression: `.a alias = "meow"`,
expected: []string{
- "D0, P[], (doc)::{b: &meow purr, a: *meow}\n",
+ "D0, P[], (!!map)::{b: &meow purr, a: *meow}\n",
},
},
{
@@ -124,7 +143,7 @@ var anchorOperatorScenarios = []expressionScenario{
document: `{b: &meow purr, a: cat}`,
expression: `.a alias = ""`,
expected: []string{
- "D0, P[], (doc)::{b: &meow purr, a: cat}\n",
+ "D0, P[], (!!map)::{b: &meow purr, a: cat}\n",
},
},
{
@@ -132,7 +151,7 @@ var anchorOperatorScenarios = []expressionScenario{
document: `{b: &meow purr, a: cat}`,
expression: `.a alias = .c`,
expected: []string{
- "D0, P[], (doc)::{b: &meow purr, a: cat}\n",
+ "D0, P[], (!!map)::{b: &meow purr, a: cat}\n",
},
},
{
@@ -140,7 +159,7 @@ var anchorOperatorScenarios = []expressionScenario{
document: `{b: &meow purr, a: cat}`,
expression: `.a alias |= .c`,
expected: []string{
- "D0, P[], (doc)::{b: &meow purr, a: cat}\n",
+ "D0, P[], (!!map)::{b: &meow purr, a: cat}\n",
},
},
{
@@ -148,7 +167,34 @@ var anchorOperatorScenarios = []expressionScenario{
document: `{b: &meow purr, a: {f: meow}}`,
expression: `.a alias |= .f`,
expected: []string{
- "D0, P[], (doc)::{b: &meow purr, a: *meow}\n",
+ "D0, P[], (!!map)::{b: &meow purr, a: *meow}\n",
+ },
+ },
+ {
+ description: "Dont explode alias and anchor - check alias parent",
+ skipDoc: true,
+ document: `{a: &a [1], b: *a}`,
+ expression: `.b[]`,
+ expected: []string{
+ "D0, P[a 0], (!!int)::1\n",
+ },
+ },
+ {
+ description: "Explode alias and anchor - check alias parent",
+ skipDoc: true,
+ document: `{a: &a cat, b: *a}`,
+ expression: `explode(.) | .b`,
+ expected: []string{
+ "D0, P[b], (!!str)::cat\n",
+ },
+ },
+ {
+ description: "Explode alias and anchor - check original parent",
+ skipDoc: true,
+ document: `{a: &a cat, b: *a}`,
+ expression: `explode(.) | .a`,
+ expected: []string{
+ "D0, P[a], (!!str)::cat\n",
},
},
{
@@ -156,7 +202,7 @@ var anchorOperatorScenarios = []expressionScenario{
document: `{f : {a: &a cat, b: *a}}`,
expression: `explode(.f)`,
expected: []string{
- "D0, P[], (doc)::{f: {a: cat, b: cat}}\n",
+ "D0, P[], (!!map)::{f: {a: cat, b: cat}}\n",
},
},
{
@@ -164,7 +210,7 @@ var anchorOperatorScenarios = []expressionScenario{
document: `a: mike`,
expression: `explode(.a)`,
expected: []string{
- "D0, P[], (doc)::a: mike\n",
+ "D0, P[], (!!map)::a: mike\n",
},
},
{
@@ -172,31 +218,14 @@ var anchorOperatorScenarios = []expressionScenario{
document: `{f : {a: &a cat, *a: b}}`,
expression: `explode(.f)`,
expected: []string{
- "D0, P[], (doc)::{f: {a: cat, cat: b}}\n",
+ "D0, P[], (!!map)::{f: {a: cat, cat: b}}\n",
},
},
{
description: "Explode with merge anchors",
document: mergeDocSample,
expression: `explode(.)`,
- expected: []string{`D0, P[], (doc)::foo:
- a: foo_a
- thing: foo_thing
- c: foo_c
-bar:
- b: bar_b
- thing: bar_thing
- c: bar_c
-foobarList:
- b: bar_b
- thing: foo_thing
- c: foobarList_c
- a: foo_a
-foobar:
- c: foo_c
- a: foo_a
- thing: foobar_thing
-`},
+ expected: []string{explodeMergeAnchorsExpected},
},
{
skipDoc: true,
@@ -220,10 +249,10 @@ foobar:
},
{
skipDoc: true,
- document: `{f : {a: &a cat, b: &b {f: *a}, *a: *b}}`,
+ document: `{f : {a: &a cat, b: &b {foo: *a}, *a: *b}}`,
expression: `explode(.f)`,
expected: []string{
- "D0, P[], (doc)::{f: {a: cat, b: {f: cat}, cat: {f: cat}}}\n",
+ "D0, P[], (!!map)::{f: {a: cat, b: {foo: cat}, cat: {foo: cat}}}\n",
},
},
{
diff --git a/pkg/yqlib/operator_array_to_map_test.go b/pkg/yqlib/operator_array_to_map_test.go
index 406fec1c..27259a5f 100644
--- a/pkg/yqlib/operator_array_to_map_test.go
+++ b/pkg/yqlib/operator_array_to_map_test.go
@@ -10,7 +10,7 @@ var arrayToMapScenarios = []expressionScenario{
document: `cool: [null, null, hello]`,
expression: `.cool |= array_to_map`,
expected: []string{
- "D0, P[], (doc)::cool:\n 2: hello\n",
+ "D0, P[], (!!map)::cool:\n 2: hello\n",
},
},
}
diff --git a/pkg/yqlib/operator_assign.go b/pkg/yqlib/operator_assign.go
index f21f4522..834b9f9e 100644
--- a/pkg/yqlib/operator_assign.go
+++ b/pkg/yqlib/operator_assign.go
@@ -8,8 +8,7 @@ type assignPreferences struct {
func assignUpdateFunc(prefs assignPreferences) crossFunctionCalculation {
return func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
- rhs.Node = unwrapDoc(rhs.Node)
- if !prefs.OnlyWriteNull || lhs.Node.Tag == "!!null" {
+ if !prefs.OnlyWriteNull || lhs.Tag == "!!null" {
lhs.UpdateFrom(rhs, prefs)
}
return lhs, nil
@@ -46,7 +45,11 @@ func assignUpdateOperator(d *dataTreeNavigator, context Context, expressionNode
return context, err
}
- for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() {
+ //traverse backwards through the context -
+ // like delete, we need to run against the children first.
+ // (e.g. consider when running with expression '.. |= [.]' - we need
+ // to wrap the children first
+ for el := lhs.MatchingNodes.Back(); el != nil; el = el.Prev() {
candidate := el.Value.(*CandidateNode)
rhs, err := d.GetMatchingNodes(context.SingleChildContext(candidate), expressionNode.RHS)
@@ -60,7 +63,6 @@ func assignUpdateOperator(d *dataTreeNavigator, context Context, expressionNode
if first != nil {
rhsCandidate := first.Value.(*CandidateNode)
- rhsCandidate.Node = unwrapDoc(rhsCandidate.Node)
candidate.UpdateFrom(rhsCandidate, prefs)
}
}
@@ -92,7 +94,7 @@ func assignAttributesOperator(d *dataTreeNavigator, context Context, expressionN
if expressionNode.Operation.Preferences != nil {
prefs = expressionNode.Operation.Preferences.(assignPreferences)
}
- if !prefs.OnlyWriteNull || candidate.Node.Tag == "!!null" {
+ if !prefs.OnlyWriteNull || candidate.Tag == "!!null" {
candidate.UpdateAttributesFrom(first.Value.(*CandidateNode), prefs)
}
}
diff --git a/pkg/yqlib/operator_assign_test.go b/pkg/yqlib/operator_assign_test.go
index 4fdf6da8..601223ae 100644
--- a/pkg/yqlib/operator_assign_test.go
+++ b/pkg/yqlib/operator_assign_test.go
@@ -22,7 +22,7 @@ var assignOperatorScenarios = []expressionScenario{
document: "{}",
expression: `.a |= .b`,
expected: []string{
- "D0, P[], (doc)::a: null\n",
+ "D0, P[], (!!map)::a: null\n",
},
},
{
@@ -30,7 +30,7 @@ var assignOperatorScenarios = []expressionScenario{
document: mergeAnchorAssign,
expression: `.c = .b | .a.x = "ModifiedValue" | explode(.)`,
expected: []string{
- "D0, P[], (doc)::a:\n x: ModifiedValue\nb:\n x: ModifiedValue\nc:\n x: ModifiedValue\n",
+ "D0, P[], (!!map)::a:\n x: ModifiedValue\nb:\n x: ModifiedValue\nc:\n x: ModifiedValue\n",
},
},
{
@@ -38,7 +38,7 @@ var assignOperatorScenarios = []expressionScenario{
document: "{}",
expression: `.a = .b`,
expected: []string{
- "D0, P[], (doc)::a: null\n",
+ "D0, P[], (!!map)::a: null\n",
},
},
{
@@ -47,7 +47,7 @@ var assignOperatorScenarios = []expressionScenario{
document: "a: cat",
expression: `.a = [.a]`,
expected: []string{
- "D0, P[], (doc)::a:\n - cat\n",
+ "D0, P[], (!!map)::a:\n - cat\n",
},
},
{
@@ -56,7 +56,7 @@ var assignOperatorScenarios = []expressionScenario{
document: `a: "3"`,
expression: `.a = 3`,
expected: []string{
- "D0, P[], (doc)::a: 3\n",
+ "D0, P[], (!!map)::a: 3\n",
},
},
{
@@ -65,7 +65,7 @@ var assignOperatorScenarios = []expressionScenario{
document: `a: "true"`,
expression: `.a = true`,
expected: []string{
- "D0, P[], (doc)::a: true\n",
+ "D0, P[], (!!map)::a: true\n",
},
},
{
@@ -74,7 +74,7 @@ var assignOperatorScenarios = []expressionScenario{
document: `a: !cat "meow"`,
expression: `.a = "woof"`,
expected: []string{
- "D0, P[], (doc)::a: !cat \"woof\"\n",
+ "D0, P[], (!!map)::a: !cat \"woof\"\n",
},
},
{
@@ -82,7 +82,7 @@ var assignOperatorScenarios = []expressionScenario{
document: `{a: {b: {g: foof}}}`,
expression: `.a |= .b`,
expected: []string{
- "D0, P[], (doc)::{a: {g: foof}}\n",
+ "D0, P[], (!!map)::{a: {g: foof}}\n",
},
},
{
@@ -90,7 +90,7 @@ var assignOperatorScenarios = []expressionScenario{
document: `[1,2,3]`,
expression: `.[] |= . * 2`,
expected: []string{
- "D0, P[], (doc)::[2, 4, 6]\n",
+ "D0, P[], (!!seq)::[2, 4, 6]\n",
},
},
{
@@ -100,7 +100,7 @@ var assignOperatorScenarios = []expressionScenario{
document2: "{b: bob}",
expression: `select(fileIndex==0).a = select(fileIndex==1) | select(fileIndex==0)`,
expected: []string{
- "D0, P[], (doc)::{a: {b: bob}}\n",
+ "D0, P[], (!!map)::{a: {b: bob}}\n",
},
},
{
@@ -108,7 +108,7 @@ var assignOperatorScenarios = []expressionScenario{
document: `{a: {b: child}, b: sibling}`,
expression: `.a = .b`,
expected: []string{
- "D0, P[], (doc)::{a: sibling, b: sibling}\n",
+ "D0, P[], (!!map)::{a: sibling, b: sibling}\n",
},
},
{
@@ -116,7 +116,7 @@ var assignOperatorScenarios = []expressionScenario{
document: `{a: fieldA, b: fieldB, c: fieldC}`,
expression: `(.a, .c) = "potato"`,
expected: []string{
- "D0, P[], (doc)::{a: potato, b: fieldB, c: potato}\n",
+ "D0, P[], (!!map)::{a: potato, b: fieldB, c: potato}\n",
},
},
{
@@ -124,7 +124,7 @@ var assignOperatorScenarios = []expressionScenario{
document: `{a: {b: apple}}`,
expression: `.a.b = "frog"`,
expected: []string{
- "D0, P[], (doc)::{a: {b: frog}}\n",
+ "D0, P[], (!!map)::{a: {b: frog}}\n",
},
},
{
@@ -133,7 +133,7 @@ var assignOperatorScenarios = []expressionScenario{
document: `{a: {b: apple}}`,
expression: `.a.b |= "frog"`,
expected: []string{
- "D0, P[], (doc)::{a: {b: frog}}\n",
+ "D0, P[], (!!map)::{a: {b: frog}}\n",
},
},
{
@@ -149,7 +149,7 @@ var assignOperatorScenarios = []expressionScenario{
document: `{a: {b: apple}}`,
expression: `.a.b |= 5`,
expected: []string{
- "D0, P[], (doc)::{a: {b: 5}}\n",
+ "D0, P[], (!!map)::{a: {b: 5}}\n",
},
},
{
@@ -157,7 +157,7 @@ var assignOperatorScenarios = []expressionScenario{
document: `{a: {b: apple}}`,
expression: `.a.b |= 3.142`,
expected: []string{
- "D0, P[], (doc)::{a: {b: 3.142}}\n",
+ "D0, P[], (!!map)::{a: {b: 3.142}}\n",
},
},
{
@@ -166,7 +166,7 @@ var assignOperatorScenarios = []expressionScenario{
document: `{a: {b: apple, c: cactus}}`,
expression: `(.a[] | select(. == "apple")) = "frog"`,
expected: []string{
- "D0, P[], (doc)::{a: {b: frog, c: cactus}}\n",
+ "D0, P[], (!!map)::{a: {b: frog, c: cactus}}\n",
},
},
{
@@ -174,7 +174,7 @@ var assignOperatorScenarios = []expressionScenario{
document: `{a: {b: apple, c: cactus}}`,
expression: `(.a.[] | select(. == "apple")) = "frog"`,
expected: []string{
- "D0, P[], (doc)::{a: {b: frog, c: cactus}}\n",
+ "D0, P[], (!!map)::{a: {b: frog, c: cactus}}\n",
},
},
{
@@ -182,7 +182,7 @@ var assignOperatorScenarios = []expressionScenario{
document: `[candy, apple, sandy]`,
expression: `(.[] | select(. == "*andy")) = "bogs"`,
expected: []string{
- "D0, P[], (doc)::[bogs, apple, bogs]\n",
+ "D0, P[], (!!seq)::[bogs, apple, bogs]\n",
},
},
{
@@ -191,7 +191,7 @@ var assignOperatorScenarios = []expressionScenario{
document: `{}`,
expression: `.a.b |= "bogs"`,
expected: []string{
- "D0, P[], (doc)::a:\n b: bogs\n",
+ "D0, P[], (!!map)::a:\n b: bogs\n",
},
},
{
@@ -201,7 +201,7 @@ var assignOperatorScenarios = []expressionScenario{
document: `a: &cool cat`,
expression: `.a = "dog"`,
expected: []string{
- "D0, P[], (doc)::a: &cool dog\n",
+ "D0, P[], (!!map)::a: &cool dog\n",
},
},
{
@@ -210,7 +210,7 @@ var assignOperatorScenarios = []expressionScenario{
document: `{}`,
expression: `.a.b.[0] |= "bogs"`,
expected: []string{
- "D0, P[], (doc)::a:\n b:\n - bogs\n",
+ "D0, P[], (!!map)::a:\n b:\n - bogs\n",
},
},
{
@@ -218,7 +218,7 @@ var assignOperatorScenarios = []expressionScenario{
document: `{}`,
expression: `.a.b.[1].c |= "bogs"`,
expected: []string{
- "D0, P[], (doc)::a:\n b:\n - null\n - c: bogs\n",
+ "D0, P[], (!!map)::a:\n b:\n - null\n - c: bogs\n",
},
},
{
@@ -226,7 +226,7 @@ var assignOperatorScenarios = []expressionScenario{
document: "a: !cat meow\nb: !dog woof",
expression: `.a = .b`,
expected: []string{
- "D0, P[], (doc)::a: !cat woof\nb: !dog woof\n",
+ "D0, P[], (!!map)::a: !cat woof\nb: !dog woof\n",
},
},
{
@@ -235,7 +235,7 @@ var assignOperatorScenarios = []expressionScenario{
document: "a: !cat meow\nb: !dog woof",
expression: `.a =c .b`,
expected: []string{
- "D0, P[], (doc)::a: !dog woof\nb: !dog woof\n",
+ "D0, P[], (!!map)::a: !dog woof\nb: !dog woof\n",
},
},
}
diff --git a/pkg/yqlib/operator_booleans.go b/pkg/yqlib/operator_booleans.go
index d919b9a6..07288c42 100644
--- a/pkg/yqlib/operator_booleans.go
+++ b/pkg/yqlib/operator_booleans.go
@@ -3,36 +3,25 @@ package yqlib
import (
"container/list"
"fmt"
-
- yaml "gopkg.in/yaml.v3"
+ "strings"
)
-func isTruthyNode(node *yaml.Node) (bool, error) {
- value := true
+func isTruthyNode(node *CandidateNode) bool {
+ if node == nil {
+ return false
+ }
if node.Tag == "!!null" {
- return false, nil
+ return false
}
- if node.Kind == yaml.ScalarNode && node.Tag == "!!bool" {
- errDecoding := node.Decode(&value)
- if errDecoding != nil {
- return false, errDecoding
- }
+ if node.Kind == ScalarNode && node.Tag == "!!bool" {
+ // yes/y/true/on
+ return (strings.EqualFold(node.Value, "y") ||
+ strings.EqualFold(node.Value, "yes") ||
+ strings.EqualFold(node.Value, "on") ||
+ strings.EqualFold(node.Value, "true"))
}
- return value, nil
-}
-
-func isTruthy(c *CandidateNode) (bool, error) {
- node := unwrapDoc(c.Node)
- return isTruthyNode(node)
-}
-
-func getBoolean(candidate *CandidateNode) (bool, error) {
- if candidate != nil {
- candidate.Node = unwrapDoc(candidate.Node)
- return isTruthy(candidate)
- }
- return false, nil
+ return true
}
func getOwner(lhs *CandidateNode, rhs *CandidateNode) *CandidateNode {
@@ -48,10 +37,7 @@ func getOwner(lhs *CandidateNode, rhs *CandidateNode) *CandidateNode {
func returnRhsTruthy(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
owner := getOwner(lhs, rhs)
- rhsBool, err := getBoolean(rhs)
- if err != nil {
- return nil, err
- }
+ rhsBool := isTruthyNode(rhs)
return createBooleanCandidate(owner, rhsBool), nil
}
@@ -61,7 +47,7 @@ func returnLHSWhen(targetBool bool) func(lhs *CandidateNode) (*CandidateNode, er
var err error
var lhsBool bool
- if lhsBool, err = getBoolean(lhs); err != nil || lhsBool != targetBool {
+ if lhsBool = isTruthyNode(lhs); lhsBool != targetBool {
return nil, err
}
owner := &CandidateNode{}
@@ -72,29 +58,24 @@ func returnLHSWhen(targetBool bool) func(lhs *CandidateNode) (*CandidateNode, er
}
}
-func findBoolean(wantBool bool, d *dataTreeNavigator, context Context, expressionNode *ExpressionNode, sequenceNode *yaml.Node) (bool, error) {
+func findBoolean(wantBool bool, d *dataTreeNavigator, context Context, expressionNode *ExpressionNode, sequenceNode *CandidateNode) (bool, error) {
for _, node := range sequenceNode.Content {
if expressionNode != nil {
//need to evaluate the expression against the node
- candidate := &CandidateNode{Node: node}
- rhs, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(candidate), expressionNode)
+ rhs, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(node), expressionNode)
if err != nil {
return false, err
}
if rhs.MatchingNodes.Len() > 0 {
- node = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node
+ node = rhs.MatchingNodes.Front().Value.(*CandidateNode)
} else {
// no results found, ignore this entry
continue
}
}
- truthy, err := isTruthyNode(node)
- if err != nil {
- return false, err
- }
- if truthy == wantBool {
+ if isTruthyNode(node) == wantBool {
return true, nil
}
}
@@ -106,11 +87,10 @@ func allOperator(d *dataTreeNavigator, context Context, expressionNode *Expressi
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- candidateNode := unwrapDoc(candidate.Node)
- if candidateNode.Kind != yaml.SequenceNode {
- return Context{}, fmt.Errorf("any only supports arrays, was %v", candidateNode.Tag)
+ if candidate.Kind != SequenceNode {
+ return Context{}, fmt.Errorf("any only supports arrays, was %v", candidate.Tag)
}
- booleanResult, err := findBoolean(false, d, context, expressionNode.RHS, candidateNode)
+ booleanResult, err := findBoolean(false, d, context, expressionNode.RHS, candidate)
if err != nil {
return Context{}, err
}
@@ -125,11 +105,10 @@ func anyOperator(d *dataTreeNavigator, context Context, expressionNode *Expressi
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- candidateNode := unwrapDoc(candidate.Node)
- if candidateNode.Kind != yaml.SequenceNode {
- return Context{}, fmt.Errorf("any only supports arrays, was %v", candidateNode.Tag)
+ if candidate.Kind != SequenceNode {
+ return Context{}, fmt.Errorf("any only supports arrays, was %v", candidate.Tag)
}
- booleanResult, err := findBoolean(true, d, context, expressionNode.RHS, candidateNode)
+ booleanResult, err := findBoolean(true, d, context, expressionNode.RHS, candidate)
if err != nil {
return Context{}, err
}
@@ -164,10 +143,7 @@ func notOperator(d *dataTreeNavigator, context Context, expressionNode *Expressi
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
log.Debug("notOperation checking %v", candidate)
- truthy, errDecoding := isTruthy(candidate)
- if errDecoding != nil {
- return Context{}, errDecoding
- }
+ truthy := isTruthyNode(candidate)
result := createBooleanCandidate(candidate, !truthy)
results.PushBack(result)
}
diff --git a/pkg/yqlib/operator_booleans_test.go b/pkg/yqlib/operator_booleans_test.go
index c48c5307..c999c635 100644
--- a/pkg/yqlib/operator_booleans_test.go
+++ b/pkg/yqlib/operator_booleans_test.go
@@ -43,7 +43,7 @@ var booleanOperatorScenarios = []expressionScenario{
document: "b: hi",
expression: `select(.a or .b)`,
expected: []string{
- "D0, P[], (doc)::b: hi\n",
+ "D0, P[], (!!map)::b: hi\n",
},
},
{
@@ -51,7 +51,7 @@ var booleanOperatorScenarios = []expressionScenario{
document: "b: hi",
expression: `select((.a and .b) | not)`,
expected: []string{
- "D0, P[], (doc)::b: hi\n",
+ "D0, P[], (!!map)::b: hi\n",
},
},
{
@@ -106,7 +106,7 @@ var booleanOperatorScenarios = []expressionScenario{
document: "a: [rad, awesome]\nb: [meh, whatever]",
expression: `.[] |= any_c(. == "awesome")`,
expected: []string{
- "D0, P[], (doc)::a: true\nb: false\n",
+ "D0, P[], (!!map)::a: true\nb: false\n",
},
},
{
@@ -114,7 +114,7 @@ var booleanOperatorScenarios = []expressionScenario{
document: `[{pet: cat}]`,
expression: `any_c(.name == "harry") as $c | .`,
expected: []string{
- "D0, P[], (doc)::[{pet: cat}]\n",
+ "D0, P[], (!!seq)::[{pet: cat}]\n",
},
},
{
@@ -170,7 +170,7 @@ var booleanOperatorScenarios = []expressionScenario{
document: "a: [rad, awesome]\nb: [meh, 12]",
expression: `.[] |= all_c(tag == "!!str")`,
expected: []string{
- "D0, P[], (doc)::a: true\nb: false\n",
+ "D0, P[], (!!map)::a: true\nb: false\n",
},
},
{
@@ -205,7 +205,7 @@ var booleanOperatorScenarios = []expressionScenario{
document: `{}`,
expression: `(.a.b or .c) as $x | .`,
expected: []string{
- "D0, P[], (doc)::{}\n",
+ "D0, P[], (!!map)::{}\n",
},
},
{
@@ -213,7 +213,7 @@ var booleanOperatorScenarios = []expressionScenario{
document: `{}`,
expression: `(.a.b and .c) as $x | .`,
expected: []string{
- "D0, P[], (doc)::{}\n",
+ "D0, P[], (!!map)::{}\n",
},
},
{
diff --git a/pkg/yqlib/operator_collect.go b/pkg/yqlib/operator_collect.go
index 2a114592..58284299 100644
--- a/pkg/yqlib/operator_collect.go
+++ b/pkg/yqlib/operator_collect.go
@@ -2,12 +2,10 @@ package yqlib
import (
"container/list"
-
- yaml "gopkg.in/yaml.v3"
)
func collectTogether(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (*CandidateNode, error) {
- collectedNode := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
+ collectedNode := &CandidateNode{Kind: SequenceNode, Tag: "!!seq"}
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
collectExpResults, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(candidate), expressionNode)
@@ -17,10 +15,10 @@ func collectTogether(d *dataTreeNavigator, context Context, expressionNode *Expr
for result := collectExpResults.MatchingNodes.Front(); result != nil; result = result.Next() {
resultC := result.Value.(*CandidateNode)
log.Debugf("found this: %v", NodeToString(resultC))
- collectedNode.Content = append(collectedNode.Content, unwrapDoc(resultC.Node))
+ collectedNode.AddChild(resultC)
}
}
- return &CandidateNode{Node: collectedNode}, nil
+ return collectedNode, nil
}
func collectOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@@ -28,9 +26,8 @@ func collectOperator(d *dataTreeNavigator, context Context, expressionNode *Expr
if context.MatchingNodes.Len() == 0 {
log.Debugf("nothing to collect")
- node := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq", Value: "[]"}
- candidate := &CandidateNode{Node: node}
- return context.SingleChildContext(candidate), nil
+ node := &CandidateNode{Kind: SequenceNode, Tag: "!!seq", Value: "[]"}
+ return context.SingleChildContext(node), nil
}
var evaluateAllTogether = true
@@ -55,8 +52,7 @@ func collectOperator(d *dataTreeNavigator, context Context, expressionNode *Expr
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- collectedNode := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
- collectCandidate := candidate.CreateReplacement(collectedNode)
+ collectCandidate := candidate.CreateReplacement(SequenceNode, "!!seq", "")
log.Debugf("collect rhs: %v", expressionNode.RHS.Operation.toString())
@@ -68,7 +64,7 @@ func collectOperator(d *dataTreeNavigator, context Context, expressionNode *Expr
for result := collectExpResults.MatchingNodes.Front(); result != nil; result = result.Next() {
resultC := result.Value.(*CandidateNode)
log.Debugf("found this: %v", NodeToString(resultC))
- collectedNode.Content = append(collectedNode.Content, unwrapDoc(resultC.Node))
+ collectCandidate.AddChild(resultC)
}
log.Debugf("done collect rhs: %v", expressionNode.RHS.Operation.toString())
diff --git a/pkg/yqlib/operator_collect_object.go b/pkg/yqlib/operator_collect_object.go
index 59417a62..4f2283ac 100644
--- a/pkg/yqlib/operator_collect_object.go
+++ b/pkg/yqlib/operator_collect_object.go
@@ -2,8 +2,6 @@ package yqlib
import (
"container/list"
-
- yaml "gopkg.in/yaml.v3"
)
/*
@@ -23,31 +21,47 @@ func collectObjectOperator(d *dataTreeNavigator, originalContext Context, expres
context := originalContext.WritableClone()
if context.MatchingNodes.Len() == 0 {
- node := &yaml.Node{Kind: yaml.MappingNode, Tag: "!!map", Value: "{}"}
- candidate := &CandidateNode{Node: node}
+ candidate := &CandidateNode{Kind: MappingNode, Tag: "!!map", Value: "{}"}
+ log.Debugf("-- collectObjectOperation - starting with empty map")
return context.SingleChildContext(candidate), nil
}
first := context.MatchingNodes.Front().Value.(*CandidateNode)
- var rotated = make([]*list.List, len(first.Node.Content))
+ var rotated = make([]*list.List, len(first.Content))
- for i := 0; i < len(first.Node.Content); i++ {
+ for i := 0; i < len(first.Content); i++ {
rotated[i] = list.New()
}
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidateNode := el.Value.(*CandidateNode)
- for i := 0; i < len(first.Node.Content); i++ {
- rotated[i].PushBack(candidateNode.CreateChildInArray(i, candidateNode.Node.Content[i]))
+
+ for i := 0; i < len(first.Content); i++ {
+ log.Debugf("rotate[%v] = %v", i, NodeToString(candidateNode.Content[i]))
+ log.Debugf("children:\n%v", NodeContentToString(candidateNode.Content[i], 0))
+ rotated[i].PushBack(candidateNode.Content[i])
}
}
+ log.Debugf("-- collectObjectOperation, length of rotated is %v", len(rotated))
newObject := list.New()
- for i := 0; i < len(first.Node.Content); i++ {
+ for i := 0; i < len(first.Content); i++ {
additions, err := collect(d, context.ChildContext(list.New()), rotated[i])
if err != nil {
return Context{}, err
}
- newObject.PushBackList(additions.MatchingNodes)
+ // we should reset the parents and keys of these top level nodes,
+ // as they are new
+ for el := additions.MatchingNodes.Front(); el != nil; el = el.Next() {
+ addition := el.Value.(*CandidateNode)
+ additionCopy := addition.Copy()
+
+ additionCopy.SetParent(nil)
+ additionCopy.Key = nil
+
+ log.Debugf("-- collectObjectOperation, adding result %v", NodeToString(additionCopy))
+
+ newObject.PushBack(additionCopy)
+ }
}
return context.ChildContext(newObject), nil
@@ -60,19 +74,17 @@ func collect(d *dataTreeNavigator, context Context, remainingMatches *list.List)
}
candidate := remainingMatches.Remove(remainingMatches.Front()).(*CandidateNode)
+ log.Debugf("-- collectObjectOperation - collect %v", NodeToString(candidate))
splatted, err := splat(context.SingleChildContext(candidate),
traversePreferences{DontFollowAlias: true, IncludeMapKeys: false})
- for splatEl := splatted.MatchingNodes.Front(); splatEl != nil; splatEl = splatEl.Next() {
- splatEl.Value.(*CandidateNode).Path = nil
- }
-
if err != nil {
return Context{}, err
}
if context.MatchingNodes.Len() == 0 {
+ log.Debugf("-- collectObjectOperation - collect context is empty, next")
return collect(d, splatted, remainingMatches)
}
@@ -82,14 +94,12 @@ func collect(d *dataTreeNavigator, context Context, remainingMatches *list.List)
aggCandidate := el.Value.(*CandidateNode)
for splatEl := splatted.MatchingNodes.Front(); splatEl != nil; splatEl = splatEl.Next() {
splatCandidate := splatEl.Value.(*CandidateNode)
- newCandidate, err := aggCandidate.Copy()
- if err != nil {
- return Context{}, err
- }
-
- newCandidate.Path = nil
+ log.Debugf("-- collectObjectOperation; splatCandidate: %v", NodeToString(splatCandidate))
+ newCandidate := aggCandidate.Copy()
+ log.Debugf("-- collectObjectOperation; aggCandidate: %v", NodeToString(aggCandidate))
newCandidate, err = multiply(multiplyPreferences{AppendArrays: false})(d, context, newCandidate, splatCandidate)
+
if err != nil {
return Context{}, err
}
diff --git a/pkg/yqlib/operator_collect_object_test.go b/pkg/yqlib/operator_collect_object_test.go
index 35fa555b..ff82325b 100644
--- a/pkg/yqlib/operator_collect_object_test.go
+++ b/pkg/yqlib/operator_collect_object_test.go
@@ -5,6 +5,20 @@ import (
)
var collectObjectOperatorScenarios = []expressionScenario{
+ {
+ skipDoc: true,
+ expression: `{"name": "mike"} | .name`,
+ expected: []string{
+ "D0, P[name], (!!str)::mike\n",
+ },
+ },
+ {
+ skipDoc: true,
+ expression: `{"person": {"names": ["mike"]}} | .person.names[0]`,
+ expected: []string{
+ "D0, P[person names 0], (!!str)::mike\n",
+ },
+ },
{
skipDoc: true,
document: `[{name: cat}, {name: dog}]`,
@@ -26,7 +40,7 @@ var collectObjectOperatorScenarios = []expressionScenario{
document: "a: []",
expression: `.a += [{"key": "att2", "value": "val2"}]`,
expected: []string{
- "D0, P[], (doc)::a:\n - key: att2\n value: val2\n",
+ "D0, P[], (!!map)::a:\n - key: att2\n value: val2\n",
},
},
{
@@ -62,22 +76,24 @@ var collectObjectOperatorScenarios = []expressionScenario{
},
},
{
- skipDoc: true,
- document: "{name: Mike}\n",
- document2: "{name: Bob}\n",
- expression: `{"wrap": .}`,
+ skipDoc: true,
+ description: "Two documents",
+ document: "{name: Mike}\n",
+ document2: "{name: Bob}\n",
+ expression: `{"wrap": .}`,
expected: []string{
"D0, P[], (!!map)::wrap: {name: Mike}\n",
"D0, P[], (!!map)::wrap: {name: Bob}\n",
},
},
{
- skipDoc: true,
- document: "{name: Mike}\n---\n{name: Bob}",
- expression: `{"wrap": .}`,
+ skipDoc: true,
+ description: "two embedded documents",
+ document: "{name: Mike}\n---\n{name: Bob}",
+ expression: `{"wrap": .}`,
expected: []string{
"D0, P[], (!!map)::wrap: {name: Mike}\n",
- "D0, P[], (!!map)::wrap: {name: Bob}\n",
+ "D1, P[], (!!map)::wrap: {name: Bob}\n",
},
},
{
@@ -105,8 +121,8 @@ var collectObjectOperatorScenarios = []expressionScenario{
expected: []string{
"D0, P[], (!!map)::Mike: cat\n",
"D0, P[], (!!map)::Mike: dog\n",
- "D0, P[], (!!map)::Rosey: monkey\n",
- "D0, P[], (!!map)::Rosey: sheep\n",
+ "D1, P[], (!!map)::Rosey: monkey\n",
+ "D1, P[], (!!map)::Rosey: sheep\n",
},
},
{
diff --git a/pkg/yqlib/operator_collect_test.go b/pkg/yqlib/operator_collect_test.go
index b75f95fa..b58c0dea 100644
--- a/pkg/yqlib/operator_collect_test.go
+++ b/pkg/yqlib/operator_collect_test.go
@@ -5,6 +5,13 @@ import (
)
var collectOperatorScenarios = []expressionScenario{
+ {
+ skipDoc: true,
+ expression: `["x", "y"] | .[1]`,
+ expected: []string{
+ "D0, P[1], (!!str)::y\n",
+ },
+ },
{
skipDoc: true,
document: ``,
diff --git a/pkg/yqlib/operator_column.go b/pkg/yqlib/operator_column.go
index ac7d339c..e4e92ba2 100644
--- a/pkg/yqlib/operator_column.go
+++ b/pkg/yqlib/operator_column.go
@@ -3,8 +3,6 @@ package yqlib
import (
"container/list"
"fmt"
-
- yaml "gopkg.in/yaml.v3"
)
func columnOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@@ -14,8 +12,7 @@ func columnOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- node := &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", candidate.Node.Column), Tag: "!!int"}
- result := candidate.CreateReplacement(node)
+ result := candidate.CreateReplacement(ScalarNode, "!!int", fmt.Sprintf("%v", candidate.Column))
results.PushBack(result)
}
diff --git a/pkg/yqlib/operator_comments.go b/pkg/yqlib/operator_comments.go
index ecf882af..60da4203 100644
--- a/pkg/yqlib/operator_comments.go
+++ b/pkg/yqlib/operator_comments.go
@@ -5,8 +5,6 @@ import (
"bytes"
"container/list"
"regexp"
-
- yaml "gopkg.in/yaml.v3"
)
type commentOpPreferences struct {
@@ -35,13 +33,17 @@ func assignCommentsOperator(d *dataTreeNavigator, context Context, expressionNod
}
if rhs.MatchingNodes.Front() != nil {
- comment = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
+ comment = rhs.MatchingNodes.Front().Value.(*CandidateNode).Value
}
}
+ log.Debugf("AssignComments comment is %v", comment)
+
for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
+ log.Debugf("AssignComments lhs %v", NodeToString(candidate))
+
if expressionNode.Operation.UpdateAssign {
rhs, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(candidate), expressionNode.RHS)
if err != nil {
@@ -49,26 +51,21 @@ func assignCommentsOperator(d *dataTreeNavigator, context Context, expressionNod
}
if rhs.MatchingNodes.Front() != nil {
- comment = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
+ comment = rhs.MatchingNodes.Front().Value.(*CandidateNode).Value
}
}
log.Debugf("Setting comment of : %v", candidate.GetKey())
if preferences.LineComment {
- candidate.Node.LineComment = comment
+ log.Debugf("Setting line comment of : %v to %v", candidate.GetKey(), comment)
+ candidate.LineComment = comment
}
if preferences.HeadComment {
- candidate.Node.HeadComment = comment
+ candidate.HeadComment = comment
candidate.LeadingContent = "" // clobber the leading content, if there was any.
}
- if preferences.FootComment && candidate.Node.Kind == yaml.DocumentNode && comment != "" {
- candidate.TrailingContent = "# " + comment
- } else if preferences.FootComment && candidate.Node.Kind == yaml.DocumentNode {
- candidate.TrailingContent = comment
-
- } else if preferences.FootComment && candidate.Node.Kind != yaml.DocumentNode {
- candidate.Node.FootComment = comment
- candidate.TrailingContent = ""
+ if preferences.FootComment {
+ candidate.FootComment = comment
}
}
@@ -91,7 +88,8 @@ func getCommentsOperator(d *dataTreeNavigator, context Context, expressionNode *
candidate := el.Value.(*CandidateNode)
comment := ""
if preferences.LineComment {
- comment = candidate.Node.LineComment
+ log.Debugf("Reading line comment of : %v to %v", candidate.GetKey(), candidate.LineComment)
+ comment = candidate.LineComment
} else if preferences.HeadComment && candidate.LeadingContent != "" {
var chompRegexp = regexp.MustCompile(`\n$`)
var output bytes.Buffer
@@ -106,18 +104,18 @@ func getCommentsOperator(d *dataTreeNavigator, context Context, expressionNode *
comment = output.String()
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
+ comment = candidate.HeadComment
} else if preferences.FootComment {
- comment = candidate.Node.FootComment
+ comment = candidate.FootComment
}
comment = startCommentCharacterRegExp.ReplaceAllString(comment, "")
comment = subsequentCommentCharacterRegExp.ReplaceAllString(comment, "\n")
- node := &yaml.Node{Kind: yaml.ScalarNode, Value: comment, Tag: "!!str"}
- result := candidate.CreateReplacement(node)
- result.LeadingContent = "" // don't include the leading yaml content when retrieving a comment
+ result := candidate.CreateReplacement(ScalarNode, "!!str", comment)
+ if candidate.IsMapKey {
+ result.IsMapKey = false
+ result.Key = candidate
+ }
results.PushBack(result)
}
return context.ChildContext(results), nil
diff --git a/pkg/yqlib/operator_comments_test.go b/pkg/yqlib/operator_comments_test.go
index ed7fef48..5bb35770 100644
--- a/pkg/yqlib/operator_comments_test.go
+++ b/pkg/yqlib/operator_comments_test.go
@@ -60,7 +60,7 @@ var commentOperatorScenarios = []expressionScenario{
document: `a: cat`,
expression: `.a line_comment="single"`,
expected: []string{
- "D0, P[], (doc)::a: cat # single\n",
+ "D0, P[], (!!map)::a: cat # single\n",
},
},
{
@@ -69,7 +69,7 @@ var commentOperatorScenarios = []expressionScenario{
document: "a:\n b: things",
expression: `(.a | key) line_comment="single"`,
expected: []string{
- "D0, P[], (doc)::a: # single\n b: things\n",
+ "D0, P[], (!!map)::a: # single\n b: things\n",
},
},
{
@@ -77,7 +77,7 @@ var commentOperatorScenarios = []expressionScenario{
document: "a: cat\nb: dog",
expression: `.a line_comment=.b`,
expected: []string{
- "D0, P[], (doc)::a: cat # dog\nb: dog\n",
+ "D0, P[], (!!map)::a: cat # dog\nb: dog\n",
},
},
{
@@ -85,8 +85,8 @@ var commentOperatorScenarios = []expressionScenario{
document: "a: cat\n---\na: dog",
expression: `.a line_comment |= documentIndex`,
expected: []string{
- "D0, P[], (doc)::a: cat # 0\n",
- "D1, P[], (doc)::a: dog # 1\n",
+ "D0, P[], (!!map)::a: cat # 0\n",
+ "D1, P[], (!!map)::a: dog # 1\n",
},
},
{
@@ -146,7 +146,7 @@ var commentOperatorScenarios = []expressionScenario{
document: `a: cat`,
expression: `. head_comment="single"`,
expected: []string{
- "D0, P[], (doc)::# single\n\na: cat\n",
+ "D0, P[], (!!map)::# single\na: cat\n",
},
},
{
@@ -154,7 +154,7 @@ var commentOperatorScenarios = []expressionScenario{
document: "f: foo\na:\n b: cat",
expression: `(.a | key) head_comment="single"`,
expected: []string{
- "D0, P[], (doc)::f: foo\n# single\na:\n b: cat\n",
+ "D0, P[], (!!map)::f: foo\n# single\na:\n b: cat\n",
},
},
{
@@ -162,7 +162,7 @@ var commentOperatorScenarios = []expressionScenario{
document: `a: cat`,
expression: `. foot_comment=.a`,
expected: []string{
- "D0, P[], (doc)::a: cat\n# cat\n",
+ "D0, P[], (!!map)::a: cat\n# cat\n",
},
},
{
@@ -171,7 +171,7 @@ var commentOperatorScenarios = []expressionScenario{
document: "a: cat\n\n# hi",
expression: `. foot_comment=""`,
expected: []string{
- "D0, P[], (doc)::a: cat\n",
+ "D0, P[], (!!map)::a: cat\n",
},
},
{
@@ -179,7 +179,7 @@ var commentOperatorScenarios = []expressionScenario{
document: `a: cat`,
expression: `. foot_comment=.b.d`,
expected: []string{
- "D0, P[], (doc)::a: cat\n",
+ "D0, P[], (!!map)::a: cat\n",
},
},
{
@@ -187,7 +187,7 @@ var commentOperatorScenarios = []expressionScenario{
document: `a: cat`,
expression: `. foot_comment|=.b.d`,
expected: []string{
- "D0, P[], (doc)::a: cat\n",
+ "D0, P[], (!!map)::a: cat\n",
},
},
{
@@ -195,7 +195,7 @@ var commentOperatorScenarios = []expressionScenario{
document: "a: cat # comment\nb: dog # leave this",
expression: `.a line_comment=""`,
expected: []string{
- "D0, P[], (doc)::a: cat\nb: dog # leave this\n",
+ "D0, P[], (!!map)::a: cat\nb: dog # leave this\n",
},
},
{
@@ -260,6 +260,42 @@ var commentOperatorScenarios = []expressionScenario{
"D0, P[], (!!str)::have a great day\nno really\n",
},
},
+ {
+ description: "leading spaces",
+ skipDoc: true,
+ document: " # hi",
+ expression: `.`,
+ expected: []string{
+ "D0, P[], (!!null):: # hi\n",
+ },
+ },
+ {
+ description: "string spaces",
+ skipDoc: true,
+ document: "# hi\ncat\n",
+ expression: `.`,
+ expected: []string{
+ "D0, P[], (!!str)::# hi\ncat\n",
+ },
+ },
+ {
+ description: "leading spaces with new line",
+ skipDoc: true,
+ document: " # hi\n",
+ expression: `.`,
+ expected: []string{
+ "D0, P[], (!!null):: # hi\n",
+ },
+ },
+ {
+ description: "directive",
+ skipDoc: true,
+ document: "%YAML 1.1\n# hi\n",
+ expression: `.`,
+ expected: []string{
+ "D0, P[], (!!null)::%YAML 1.1\n# hi\n",
+ },
+ },
}
func TestCommentOperatorScenarios(t *testing.T) {
diff --git a/pkg/yqlib/operator_compare.go b/pkg/yqlib/operator_compare.go
index a33cfecf..5777902b 100644
--- a/pkg/yqlib/operator_compare.go
+++ b/pkg/yqlib/operator_compare.go
@@ -3,8 +3,6 @@ package yqlib
import (
"fmt"
"strconv"
-
- yaml "gopkg.in/yaml.v3"
)
type compareTypePref struct {
@@ -32,27 +30,24 @@ func compare(prefs compareTypePref) func(d *dataTreeNavigator, context Context,
return createBooleanCandidate(lhs, false), nil
}
- lhs.Node = unwrapDoc(lhs.Node)
- rhs.Node = unwrapDoc(rhs.Node)
-
- switch lhs.Node.Kind {
- case yaml.MappingNode:
+ switch lhs.Kind {
+ case MappingNode:
return nil, fmt.Errorf("maps not yet supported for comparison")
- case yaml.SequenceNode:
+ case SequenceNode:
return nil, fmt.Errorf("arrays not yet supported for comparison")
default:
- if rhs.Node.Kind != yaml.ScalarNode {
- return nil, fmt.Errorf("%v (%v) cannot be subtracted from %v", rhs.Node.Tag, rhs.Path, lhs.Node.Tag)
+ if rhs.Kind != ScalarNode {
+ return nil, fmt.Errorf("%v (%v) cannot be subtracted from %v", rhs.Tag, rhs.GetNicePath(), lhs.Tag)
}
- target := lhs.CreateReplacement(&yaml.Node{})
- boolV, err := compareScalars(context, prefs, lhs.Node, rhs.Node)
+ target := lhs.CopyWithoutContent()
+ boolV, err := compareScalars(context, prefs, lhs, rhs)
return createBooleanCandidate(target, boolV), err
}
}
}
-func compareDateTime(layout string, prefs compareTypePref, lhs *yaml.Node, rhs *yaml.Node) (bool, error) {
+func compareDateTime(layout string, prefs compareTypePref, lhs *CandidateNode, rhs *CandidateNode) (bool, error) {
lhsTime, err := parseDateTime(layout, lhs.Value)
if err != nil {
return false, err
@@ -73,9 +68,9 @@ func compareDateTime(layout string, prefs compareTypePref, lhs *yaml.Node, rhs *
}
-func compareScalars(context Context, prefs compareTypePref, lhs *yaml.Node, rhs *yaml.Node) (bool, error) {
- lhsTag := guessTagFromCustomType(lhs)
- rhsTag := guessTagFromCustomType(rhs)
+func compareScalars(context Context, prefs compareTypePref, lhs *CandidateNode, rhs *CandidateNode) (bool, error) {
+ lhsTag := lhs.guessTagFromCustomType()
+ rhsTag := rhs.guessTagFromCustomType()
isDateTime := lhs.Tag == "!!timestamp"
// if the lhs is a string, it might be a timestamp in a custom format.
diff --git a/pkg/yqlib/operator_contains.go b/pkg/yqlib/operator_contains.go
index d07a645e..aa913d97 100644
--- a/pkg/yqlib/operator_contains.go
+++ b/pkg/yqlib/operator_contains.go
@@ -3,15 +3,13 @@ package yqlib
import (
"fmt"
"strings"
-
- yaml "gopkg.in/yaml.v3"
)
func containsOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
return crossFunction(d, context.ReadOnlyClone(), expressionNode, containsWithNodes, false)
}
-func containsArrayElement(array *yaml.Node, item *yaml.Node) (bool, error) {
+func containsArrayElement(array *CandidateNode, item *CandidateNode) (bool, error) {
for index := 0; index < len(array.Content); index = index + 1 {
containedInArray, err := contains(array.Content[index], item)
if err != nil {
@@ -24,8 +22,8 @@ func containsArrayElement(array *yaml.Node, item *yaml.Node) (bool, error) {
return false, nil
}
-func containsArray(lhs *yaml.Node, rhs *yaml.Node) (bool, error) {
- if rhs.Kind != yaml.SequenceNode {
+func containsArray(lhs *CandidateNode, rhs *CandidateNode) (bool, error) {
+ if rhs.Kind != SequenceNode {
return containsArrayElement(lhs, rhs)
}
for index := 0; index < len(rhs.Content); index = index + 1 {
@@ -40,8 +38,8 @@ func containsArray(lhs *yaml.Node, rhs *yaml.Node) (bool, error) {
return true, nil
}
-func containsObject(lhs *yaml.Node, rhs *yaml.Node) (bool, error) {
- if rhs.Kind != yaml.MappingNode {
+func containsObject(lhs *CandidateNode, rhs *CandidateNode) (bool, error) {
+ if rhs.Kind != MappingNode {
return false, nil
}
for index := 0; index < len(rhs.Content); index = index + 2 {
@@ -68,21 +66,21 @@ func containsObject(lhs *yaml.Node, rhs *yaml.Node) (bool, error) {
return true, nil
}
-func containsScalars(lhs *yaml.Node, rhs *yaml.Node) (bool, error) {
+func containsScalars(lhs *CandidateNode, rhs *CandidateNode) (bool, error) {
if lhs.Tag == "!!str" {
return strings.Contains(lhs.Value, rhs.Value), nil
}
return lhs.Value == rhs.Value, nil
}
-func contains(lhs *yaml.Node, rhs *yaml.Node) (bool, error) {
+func contains(lhs *CandidateNode, rhs *CandidateNode) (bool, error) {
switch lhs.Kind {
- case yaml.MappingNode:
+ case MappingNode:
return containsObject(lhs, rhs)
- case yaml.SequenceNode:
+ case SequenceNode:
return containsArray(lhs, rhs)
- case yaml.ScalarNode:
- if rhs.Kind != yaml.ScalarNode || lhs.Tag != rhs.Tag {
+ case ScalarNode:
+ if rhs.Kind != ScalarNode || lhs.Tag != rhs.Tag {
return false, nil
}
if lhs.Tag == "!!null" {
@@ -95,14 +93,11 @@ func contains(lhs *yaml.Node, rhs *yaml.Node) (bool, error) {
}
func containsWithNodes(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
- lhs.Node = unwrapDoc(lhs.Node)
- rhs.Node = unwrapDoc(rhs.Node)
-
- if lhs.Node.Kind != rhs.Node.Kind {
- return nil, fmt.Errorf("%v cannot check contained in %v", rhs.Node.Tag, lhs.Node.Tag)
+ if lhs.Kind != rhs.Kind {
+ return nil, fmt.Errorf("%v cannot check contained in %v", rhs.Tag, lhs.Tag)
}
- result, err := contains(lhs.Node, rhs.Node)
+ result, err := contains(lhs, rhs)
if err != nil {
return nil, err
}
diff --git a/pkg/yqlib/operator_create_map.go b/pkg/yqlib/operator_create_map.go
index 84582c9e..1b36673a 100644
--- a/pkg/yqlib/operator_create_map.go
+++ b/pkg/yqlib/operator_create_map.go
@@ -2,8 +2,6 @@ package yqlib
import (
"container/list"
-
- "gopkg.in/yaml.v3"
)
func createMapOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@@ -12,10 +10,6 @@ func createMapOperator(d *dataTreeNavigator, context Context, expressionNode *Ex
//each matchingNodes entry should turn into a sequence of keys to create.
//then collect object should do a cross function of the same index sequence for all matches.
- var path []interface{}
-
- var document uint
-
sequences := list.New()
if context.MatchingNodes.Len() > 0 {
@@ -36,50 +30,62 @@ func createMapOperator(d *dataTreeNavigator, context Context, expressionNode *Ex
sequences.PushBack(sequenceNode)
}
- return context.SingleChildContext(&CandidateNode{Node: listToNodeSeq(sequences), Document: document, Path: path}), nil
+ node := listToNodeSeq(sequences)
+
+ return context.SingleChildContext(node), nil
}
func sequenceFor(d *dataTreeNavigator, context Context, matchingNode *CandidateNode, expressionNode *ExpressionNode) (*CandidateNode, error) {
- var path []interface{}
var document uint
+ var filename string
+ var fileIndex int
+
var matches = list.New()
if matchingNode != nil {
- path = matchingNode.Path
- document = matchingNode.Document
+ document = matchingNode.GetDocument()
+ filename = matchingNode.GetFilename()
+ fileIndex = matchingNode.GetFileIndex()
matches.PushBack(matchingNode)
}
+ log.Debugf("**********sequenceFor %v", NodeToString(matchingNode))
+
mapPairs, err := crossFunction(d, context.ChildContext(matches), expressionNode,
func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
- node := yaml.Node{Kind: yaml.MappingNode, Tag: "!!map"}
- log.Debugf("LHS:", NodeToString(lhs))
- log.Debugf("RHS:", NodeToString(rhs))
- node.Content = []*yaml.Node{
- unwrapDoc(lhs.Node),
- unwrapDoc(rhs.Node),
- }
+ node := &CandidateNode{Kind: MappingNode, Tag: "!!map"}
- return &CandidateNode{Node: &node, Document: document, Path: path}, nil
+ log.Debugf("**********adding key %v and value %v", NodeToString(lhs), NodeToString(rhs))
+
+ node.AddKeyValueChild(lhs, rhs)
+
+ node.document = document
+ node.fileIndex = fileIndex
+ node.filename = filename
+
+ return node, nil
}, false)
if err != nil {
return nil, err
}
innerList := listToNodeSeq(mapPairs.MatchingNodes)
- innerList.Style = yaml.FlowStyle
- return &CandidateNode{Node: innerList, Document: document, Path: path}, nil
+ innerList.Style = FlowStyle
+ innerList.document = document
+ innerList.fileIndex = fileIndex
+ innerList.filename = filename
+ return innerList, nil
}
// NOTE: here the document index gets dropped so we
// no longer know where the node originates from.
-func listToNodeSeq(list *list.List) *yaml.Node {
- node := yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
+func listToNodeSeq(list *list.List) *CandidateNode {
+ node := CandidateNode{Kind: SequenceNode, Tag: "!!seq"}
for entry := list.Front(); entry != nil; entry = entry.Next() {
entryCandidate := entry.Value.(*CandidateNode)
log.Debugf("Collecting %v into sequence", NodeToString(entryCandidate))
- node.Content = append(node.Content, entryCandidate.Node)
+ node.AddChild(entryCandidate)
}
return &node
}
diff --git a/pkg/yqlib/operator_create_map_test.go b/pkg/yqlib/operator_create_map_test.go
index 6a972467..02d53317 100644
--- a/pkg/yqlib/operator_create_map_test.go
+++ b/pkg/yqlib/operator_create_map_test.go
@@ -12,6 +12,38 @@ var createMapOperatorScenarios = []expressionScenario{
"D0, P[], (!!seq)::- [{frog: jumps}]\n",
},
},
+ {
+ skipDoc: true,
+ description: "sets key properly",
+ expression: `("frog": "jumps") | .[0][0] | .frog`,
+ expected: []string{
+ "D0, P[0 0 frog], (!!str)::jumps\n",
+ },
+ },
+ {
+ skipDoc: true,
+ description: "sets key properly on map",
+ expression: `{"frog": "jumps"} | .frog`,
+ expected: []string{
+ "D0, P[frog], (!!str)::jumps\n",
+ },
+ },
+ {
+ document: `{name: Mike, pets: [cat, dog]}`,
+ expression: `(.name: .pets.[]) | .[0][0] | ..`,
+ expected: []string{
+ "D0, P[0 0], (!!map)::Mike: cat\n",
+ "D0, P[0 0 Mike], (!!str)::cat\n",
+ },
+ },
+ {
+ description: "check path of nested child",
+ document: "pets:\n cows: value",
+ expression: `("b":.pets) | .[0][0] | .b.cows`,
+ expected: []string{
+ "D0, P[0 0 b cows], (!!str)::value\n",
+ },
+ },
{
document: `{name: Mike, age: 32}`,
expression: `.name: .age`,
diff --git a/pkg/yqlib/operator_datetime.go b/pkg/yqlib/operator_datetime.go
index 03cdf95f..a5932c01 100644
--- a/pkg/yqlib/operator_datetime.go
+++ b/pkg/yqlib/operator_datetime.go
@@ -6,8 +6,6 @@ import (
"fmt"
"strconv"
"time"
-
- "gopkg.in/yaml.v3"
)
func getStringParameter(parameterName string, d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (string, error) {
@@ -19,7 +17,7 @@ func getStringParameter(parameterName string, d *dataTreeNavigator, context Cont
return "", fmt.Errorf("could not find %v for format_time", parameterName)
}
- return result.MatchingNodes.Front().Value.(*CandidateNode).Node.Value, nil
+ return result.MatchingNodes.Front().Value.(*CandidateNode).Value, nil
}
func withDateTimeFormat(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@@ -41,13 +39,13 @@ var Now = time.Now
func nowOp(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
- node := &yaml.Node{
+ node := &CandidateNode{
Tag: "!!timestamp",
- Kind: yaml.ScalarNode,
+ Kind: ScalarNode,
Value: Now().Format(time.RFC3339),
}
- return context.SingleChildContext(&CandidateNode{Node: node}), nil
+ return context.SingleChildContext(node), nil
}
@@ -74,7 +72,7 @@ func formatDateTime(d *dataTreeNavigator, context Context, expressionNode *Expre
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- parsedTime, err := parseDateTime(layout, candidate.Node.Value)
+ parsedTime, err := parseDateTime(layout, candidate.Value)
if err != nil {
return Context{}, fmt.Errorf("could not parse datetime of [%v]: %w", candidate.GetNicePath(), err)
}
@@ -83,14 +81,15 @@ func formatDateTime(d *dataTreeNavigator, context Context, expressionNode *Expre
node, errorReading := parseSnippet(formattedTimeStr)
if errorReading != nil {
log.Debugf("could not parse %v - lets just leave it as a string: %w", formattedTimeStr, errorReading)
- node = &yaml.Node{
- Kind: yaml.ScalarNode,
+ node = &CandidateNode{
+ Kind: ScalarNode,
Tag: "!!str",
Value: formattedTimeStr,
}
}
-
- results.PushBack(candidate.CreateReplacement(node))
+ node.Parent = candidate.Parent
+ node.Key = candidate.Key
+ results.PushBack(node)
}
return context.ChildContext(results), nil
@@ -113,19 +112,13 @@ func tzOp(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode)
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- parsedTime, err := parseDateTime(layout, candidate.Node.Value)
+ parsedTime, err := parseDateTime(layout, candidate.Value)
if err != nil {
return Context{}, fmt.Errorf("could not parse datetime of [%v] using layout [%v]: %w", candidate.GetNicePath(), layout, err)
}
tzTime := parsedTime.In(timezone)
- node := &yaml.Node{
- Kind: yaml.ScalarNode,
- Tag: candidate.Node.Tag,
- Value: tzTime.Format(layout),
- }
-
- results.PushBack(candidate.CreateReplacement(node))
+ results.PushBack(candidate.CreateReplacement(ScalarNode, candidate.Tag, tzTime.Format(layout)))
}
return context.ChildContext(results), nil
@@ -148,24 +141,20 @@ func fromUnixOp(d *dataTreeNavigator, context Context, expressionNode *Expressio
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- actualTag := guessTagFromCustomType(candidate.Node)
+ actualTag := candidate.guessTagFromCustomType()
- if actualTag != "!!int" && guessTagFromCustomType(candidate.Node) != "!!float" {
- return Context{}, fmt.Errorf("from_unix only works on numbers, found %v instead", candidate.Node.Tag)
+ if actualTag != "!!int" && actualTag != "!!float" {
+ return Context{}, fmt.Errorf("from_unix only works on numbers, found %v instead", candidate.Tag)
}
- parsedTime, err := parseUnixTime(candidate.Node.Value)
+ parsedTime, err := parseUnixTime(candidate.Value)
if err != nil {
return Context{}, err
}
- node := &yaml.Node{
- Kind: yaml.ScalarNode,
- Tag: "!!timestamp",
- Value: parsedTime.Format(time.RFC3339),
- }
+ node := candidate.CreateReplacement(ScalarNode, "!!timestamp", parsedTime.Format(time.RFC3339))
- results.PushBack(candidate.CreateReplacement(node))
+ results.PushBack(node)
}
return context.ChildContext(results), nil
@@ -180,18 +169,12 @@ func toUnixOp(d *dataTreeNavigator, context Context, expressionNode *ExpressionN
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- parsedTime, err := parseDateTime(layout, candidate.Node.Value)
+ parsedTime, err := parseDateTime(layout, candidate.Value)
if err != nil {
return Context{}, fmt.Errorf("could not parse datetime of [%v] using layout [%v]: %w", candidate.GetNicePath(), layout, err)
}
- node := &yaml.Node{
- Kind: yaml.ScalarNode,
- Tag: "!!int",
- Value: fmt.Sprintf("%v", parsedTime.Unix()),
- }
-
- results.PushBack(candidate.CreateReplacement(node))
+ results.PushBack(candidate.CreateReplacement(ScalarNode, "!!int", fmt.Sprintf("%v", parsedTime.Unix())))
}
return context.ChildContext(results), nil
diff --git a/pkg/yqlib/operator_datetime_test.go b/pkg/yqlib/operator_datetime_test.go
index a2d3ca17..f6616302 100644
--- a/pkg/yqlib/operator_datetime_test.go
+++ b/pkg/yqlib/operator_datetime_test.go
@@ -11,7 +11,7 @@ var dateTimeOperatorScenarios = []expressionScenario{
document: `a: 2001-12-15T02:59:43.1Z`,
expression: `.a |= format_datetime("Monday, 02-Jan-06 at 3:04PM")`,
expected: []string{
- "D0, P[], (doc)::a: Saturday, 15-Dec-01 at 2:59AM\n",
+ "D0, P[], (!!map)::a: Saturday, 15-Dec-01 at 2:59AM\n",
},
},
{
@@ -20,7 +20,7 @@ var dateTimeOperatorScenarios = []expressionScenario{
document: `a: Saturday, 15-Dec-01 at 2:59AM`,
expression: `.a |= with_dtf("Monday, 02-Jan-06 at 3:04PM"; format_datetime("2006-01-02"))`,
expected: []string{
- "D0, P[], (doc)::a: 2001-12-15\n",
+ "D0, P[], (!!map)::a: 2001-12-15\n",
},
},
{
@@ -36,7 +36,7 @@ var dateTimeOperatorScenarios = []expressionScenario{
document: "a: cool",
expression: `.updated = now`,
expected: []string{
- "D0, P[], (doc)::a: cool\nupdated: 2021-05-19T01:02:03Z\n",
+ "D0, P[], (!!map)::a: cool\nupdated: 2021-05-19T01:02:03Z\n",
},
},
{
@@ -62,7 +62,7 @@ var dateTimeOperatorScenarios = []expressionScenario{
document: "a: cool",
expression: `.updated = (now | tz("Australia/Sydney"))`,
expected: []string{
- "D0, P[], (doc)::a: cool\nupdated: 2021-05-19T11:02:03+10:00\n",
+ "D0, P[], (!!map)::a: cool\nupdated: 2021-05-19T11:02:03+10:00\n",
},
},
{
@@ -71,7 +71,7 @@ var dateTimeOperatorScenarios = []expressionScenario{
document: "a: Saturday, 15-Dec-01 at 2:59AM GMT",
expression: `.a |= with_dtf("Monday, 02-Jan-06 at 3:04PM MST"; tz("Australia/Sydney"))`,
expected: []string{
- "D0, P[], (doc)::a: Saturday, 15-Dec-01 at 1:59PM AEDT\n",
+ "D0, P[], (!!map)::a: Saturday, 15-Dec-01 at 1:59PM AEDT\n",
},
},
{
@@ -80,7 +80,7 @@ var dateTimeOperatorScenarios = []expressionScenario{
document: "a: Saturday, 15-Dec-01 at 2:59AM GMT",
expression: `.a |= with_dtf("Monday, 02-Jan-06 at 3:04PM MST"; tz("Australia/Sydney"))`,
expected: []string{
- "D0, P[], (doc)::a: Saturday, 15-Dec-01 at 1:59PM AEDT\n",
+ "D0, P[], (!!map)::a: Saturday, 15-Dec-01 at 1:59PM AEDT\n",
},
},
{
@@ -88,7 +88,7 @@ var dateTimeOperatorScenarios = []expressionScenario{
document: `a: 2021-01-01T00:00:00Z`,
expression: `.a += "3h10m"`,
expected: []string{
- "D0, P[], (doc)::a: 2021-01-01T03:10:00Z\n",
+ "D0, P[], (!!map)::a: 2021-01-01T03:10:00Z\n",
},
},
{
@@ -97,7 +97,7 @@ var dateTimeOperatorScenarios = []expressionScenario{
document: `a: 2021-01-01T03:10:00Z`,
expression: `.a -= "3h10m"`,
expected: []string{
- "D0, P[], (doc)::a: 2021-01-01T00:00:00Z\n",
+ "D0, P[], (!!map)::a: 2021-01-01T00:00:00Z\n",
},
},
{
@@ -105,7 +105,7 @@ var dateTimeOperatorScenarios = []expressionScenario{
document: `a: Saturday, 15-Dec-01 at 2:59AM GMT`,
expression: `with_dtf("Monday, 02-Jan-06 at 3:04PM MST"; .a += "3h1m")`,
expected: []string{
- "D0, P[], (doc)::a: Saturday, 15-Dec-01 at 6:00AM GMT\n",
+ "D0, P[], (!!map)::a: Saturday, 15-Dec-01 at 6:00AM GMT\n",
},
},
{
@@ -114,7 +114,7 @@ var dateTimeOperatorScenarios = []expressionScenario{
document: `a: Saturday, 15-Dec-01 at 2:59AM GMT`,
expression: `with_dtf("Monday, 02-Jan-06 at 3:04PM MST"; .a = (.a + "3h1m" | tz("Australia/Perth")))`,
expected: []string{
- "D0, P[], (doc)::a: Saturday, 15-Dec-01 at 2:00PM AWST\n",
+ "D0, P[], (!!map)::a: Saturday, 15-Dec-01 at 2:00PM AWST\n",
},
},
{
@@ -123,7 +123,7 @@ var dateTimeOperatorScenarios = []expressionScenario{
document: "a: Saturday, 15-Dec-01 at 2:59AM GMT",
expression: `.a |= with_dtf("Monday, 02-Jan-06 at 3:04PM MST", tz("Australia/Sydney"))`,
expected: []string{
- "D0, P[], (doc)::a: Saturday, 15-Dec-01 at 1:59PM AEDT\n",
+ "D0, P[], (!!map)::a: Saturday, 15-Dec-01 at 1:59PM AEDT\n",
},
},
}
diff --git a/pkg/yqlib/operator_delete.go b/pkg/yqlib/operator_delete.go
index eb475da5..4ca37a83 100644
--- a/pkg/yqlib/operator_delete.go
+++ b/pkg/yqlib/operator_delete.go
@@ -3,8 +3,6 @@ package yqlib
import (
"container/list"
"fmt"
-
- yaml "gopkg.in/yaml.v3"
)
func deleteChildOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@@ -17,54 +15,53 @@ func deleteChildOperator(d *dataTreeNavigator, context Context, expressionNode *
for el := nodesToDelete.MatchingNodes.Back(); el != nil; el = el.Prev() {
candidate := el.Value.(*CandidateNode)
- if candidate.Node.Kind == yaml.DocumentNode {
- //need to delete this node from context.
- newResults := list.New()
- for item := context.MatchingNodes.Front(); item != nil; item = item.Next() {
- nodeInContext := item.Value.(*CandidateNode)
- if nodeInContext.Node != candidate.Node {
- newResults.PushBack(nodeInContext)
- } else {
- log.Info("Need to delete this %v", NodeToString(nodeInContext))
- }
- }
- return context.ChildContext(newResults), nil
- } else if candidate.Parent == nil {
- //problem: context may already be '.a' and then I pass in '.a.a2'.
- // should pass in .a2.
- log.Info("Could not find parent of %v", NodeToString(candidate))
- return context, nil
+ if candidate.Parent == nil {
+ // must be a top level thing, delete it
+ return removeFromContext(context, candidate)
}
+ log.Debugf("processing deletion of candidate %v", NodeToString(candidate))
- parentNode := candidate.Parent.Node
- childPath := candidate.Path[len(candidate.Path)-1]
+ parentNode := candidate.Parent
- if parentNode.Kind == yaml.MappingNode {
+ candidatePath := candidate.GetPath()
+ childPath := candidatePath[len(candidatePath)-1]
+
+ if parentNode.Kind == MappingNode {
deleteFromMap(candidate.Parent, childPath)
- } else if parentNode.Kind == yaml.SequenceNode {
+ } else if parentNode.Kind == SequenceNode {
deleteFromArray(candidate.Parent, childPath)
} else {
- return Context{}, fmt.Errorf("Cannot delete nodes from parent of tag %v", parentNode.Tag)
+ return Context{}, fmt.Errorf("cannot delete nodes from parent of tag %v", parentNode.Tag)
}
}
return context, nil
}
-func deleteFromMap(candidate *CandidateNode, childPath interface{}) {
+func removeFromContext(context Context, candidate *CandidateNode) (Context, error) {
+ newResults := list.New()
+ for item := context.MatchingNodes.Front(); item != nil; item = item.Next() {
+ nodeInContext := item.Value.(*CandidateNode)
+ if nodeInContext != candidate {
+ newResults.PushBack(nodeInContext)
+ } else {
+ log.Info("Need to delete this %v", NodeToString(nodeInContext))
+ }
+ }
+ return context.ChildContext(newResults), nil
+}
+
+func deleteFromMap(node *CandidateNode, childPath interface{}) {
log.Debug("deleteFromMap")
- node := unwrapDoc(candidate.Node)
contents := node.Content
- newContents := make([]*yaml.Node, 0)
+ newContents := make([]*CandidateNode, 0)
for index := 0; index < len(contents); index = index + 2 {
key := contents[index]
value := contents[index+1]
- childCandidate := candidate.CreateChildInMap(key, value)
-
shouldDelete := key.Value == childPath
- log.Debugf("shouldDelete %v ? %v", childCandidate.GetKey(), shouldDelete)
+ log.Debugf("shouldDelete %v ? %v", NodeToString(value), shouldDelete)
if !shouldDelete {
newContents = append(newContents, key, value)
@@ -73,11 +70,10 @@ func deleteFromMap(candidate *CandidateNode, childPath interface{}) {
node.Content = newContents
}
-func deleteFromArray(candidate *CandidateNode, childPath interface{}) {
+func deleteFromArray(node *CandidateNode, childPath interface{}) {
log.Debug("deleteFromArray")
- node := unwrapDoc(candidate.Node)
contents := node.Content
- newContents := make([]*yaml.Node, 0)
+ newContents := make([]*CandidateNode, 0)
for index := 0; index < len(contents); index = index + 1 {
value := contents[index]
diff --git a/pkg/yqlib/operator_delete_test.go b/pkg/yqlib/operator_delete_test.go
index afc938c5..473b329a 100644
--- a/pkg/yqlib/operator_delete_test.go
+++ b/pkg/yqlib/operator_delete_test.go
@@ -10,7 +10,7 @@ var deleteOperatorScenarios = []expressionScenario{
document: `{a: cat, b: dog}`,
expression: `del(.b)`,
expected: []string{
- "D0, P[], (doc)::{a: cat}\n",
+ "D0, P[], (!!map)::{a: cat}\n",
},
},
{
@@ -18,7 +18,7 @@ var deleteOperatorScenarios = []expressionScenario{
document: `{a: {a1: fred, a2: frood}}`,
expression: `del(.a.a1)`,
expected: []string{
- "D0, P[], (doc)::{a: {a2: frood}}\n",
+ "D0, P[], (!!map)::{a: {a2: frood}}\n",
},
},
{
@@ -36,7 +36,7 @@ var deleteOperatorScenarios = []expressionScenario{
document: `a: fast`,
expression: `del(select(.a == "fast"))`,
expected: []string{
- "D0, P[], (doc)::a: slow\n",
+ "D0, P[], (!!map)::a: slow\n",
},
},
{
@@ -108,7 +108,7 @@ var deleteOperatorScenarios = []expressionScenario{
document: `[1,2,3]`,
expression: `del(.[1])`,
expected: []string{
- "D0, P[], (doc)::[1, 3]\n",
+ "D0, P[], (!!seq)::[1, 3]\n",
},
},
{
@@ -116,7 +116,7 @@ var deleteOperatorScenarios = []expressionScenario{
document: `a: [1,2,3]`,
expression: `del(.a[])`,
expected: []string{
- "D0, P[], (doc)::a: []\n",
+ "D0, P[], (!!map)::a: []\n",
},
},
{
@@ -124,16 +124,20 @@ var deleteOperatorScenarios = []expressionScenario{
document: `a: [10,x,10, 10, x, 10]`,
expression: `del(.a[] | select(. == 10))`,
expected: []string{
- "D0, P[], (doc)::a: [x, x]\n",
+ "D0, P[], (!!map)::a: [x, x]\n",
},
},
+ {
+ skipDoc: true,
+ document: `a: null`,
+ expression: `del(..)`,
+ expected: []string{},
+ },
{
skipDoc: true,
document: `a: {thing1: yep, thing2: cool, thing3: hi, b: {thing1: cool, great: huh}}`,
expression: `del(..)`,
- expected: []string{
- "D0, P[], (!!map)::{}\n",
- },
+ expected: []string{},
},
{
skipDoc: true,
@@ -148,7 +152,7 @@ var deleteOperatorScenarios = []expressionScenario{
document: `[{a: cat, b: dog}]`,
expression: `del(.[0].a)`,
expected: []string{
- "D0, P[], (doc)::[{b: dog}]\n",
+ "D0, P[], (!!seq)::[{b: dog}]\n",
},
},
{
@@ -156,7 +160,7 @@ var deleteOperatorScenarios = []expressionScenario{
document: `{a: cat, b: dog}`,
expression: `del(.c)`,
expected: []string{
- "D0, P[], (doc)::{a: cat, b: dog}\n",
+ "D0, P[], (!!map)::{a: cat, b: dog}\n",
},
},
{
@@ -164,7 +168,7 @@ var deleteOperatorScenarios = []expressionScenario{
document: `{a: cat, b: dog, c: bat}`,
expression: `del( .[] | select(. == "*at") )`,
expected: []string{
- "D0, P[], (doc)::{b: dog}\n",
+ "D0, P[], (!!map)::{b: dog}\n",
},
},
{
diff --git a/pkg/yqlib/operator_divide.go b/pkg/yqlib/operator_divide.go
index c3d5eb23..5c412150 100644
--- a/pkg/yqlib/operator_divide.go
+++ b/pkg/yqlib/operator_divide.go
@@ -4,8 +4,6 @@ import (
"fmt"
"strconv"
"strings"
-
- yaml "gopkg.in/yaml.v3"
)
func divideOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@@ -15,45 +13,40 @@ func divideOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
}
func divide(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
- lhs.Node = unwrapDoc(lhs.Node)
- rhs.Node = unwrapDoc(rhs.Node)
-
- lhsNode := lhs.Node
-
- if lhsNode.Tag == "!!null" {
- return nil, fmt.Errorf("%v (%v) cannot be divided by %v (%v)", lhsNode.Tag, lhs.GetNicePath(), rhs.Node.Tag, rhs.GetNicePath())
+ if lhs.Tag == "!!null" {
+ return nil, fmt.Errorf("%v (%v) cannot be divided by %v (%v)", lhs.Tag, lhs.GetNicePath(), rhs.Tag, rhs.GetNicePath())
}
- target := &yaml.Node{}
+ target := lhs.CopyWithoutContent()
- if lhsNode.Kind == yaml.ScalarNode && rhs.Node.Kind == yaml.ScalarNode {
- if err := divideScalars(target, lhsNode, rhs.Node); err != nil {
+ if lhs.Kind == ScalarNode && rhs.Kind == ScalarNode {
+ if err := divideScalars(target, lhs, rhs); err != nil {
return nil, err
}
} else {
- return nil, fmt.Errorf("%v (%v) cannot be divided by %v (%v)", lhsNode.Tag, lhs.GetNicePath(), rhs.Node.Tag, rhs.GetNicePath())
+ return nil, fmt.Errorf("%v (%v) cannot be divided by %v (%v)", lhs.Tag, lhs.GetNicePath(), rhs.Tag, rhs.GetNicePath())
}
- return lhs.CreateReplacement(target), nil
+ return target, nil
}
-func divideScalars(target *yaml.Node, lhs *yaml.Node, rhs *yaml.Node) error {
+func divideScalars(target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error {
lhsTag := lhs.Tag
- rhsTag := guessTagFromCustomType(rhs)
+ rhsTag := rhs.guessTagFromCustomType()
lhsIsCustom := false
if !strings.HasPrefix(lhsTag, "!!") {
// custom tag - we have to have a guess
- lhsTag = guessTagFromCustomType(lhs)
+ lhsTag = lhs.guessTagFromCustomType()
lhsIsCustom = true
}
if lhsTag == "!!str" && rhsTag == "!!str" {
- res := split(lhs.Value, rhs.Value)
- target.Kind = res.Kind
- target.Tag = res.Tag
- target.Content = res.Content
+ tKind, tTag, res := split(lhs.Value, rhs.Value)
+ target.Kind = tKind
+ target.Tag = tTag
+ target.AddChildren(res)
} else if (lhsTag == "!!int" || lhsTag == "!!float") && (rhsTag == "!!int" || rhsTag == "!!float") {
- target.Kind = yaml.ScalarNode
+ target.Kind = ScalarNode
target.Style = lhs.Style
lhsNum, err := strconv.ParseFloat(lhs.Value, 64)
diff --git a/pkg/yqlib/operator_divide_test.go b/pkg/yqlib/operator_divide_test.go
index fc7297a3..c0c9cd96 100644
--- a/pkg/yqlib/operator_divide_test.go
+++ b/pkg/yqlib/operator_divide_test.go
@@ -19,7 +19,7 @@ var divideOperatorScenarios = []expressionScenario{
document: `{}`,
expression: "(.a / .b) as $x | .",
expected: []string{
- "D0, P[], (doc)::{}\n",
+ "D0, P[], (!!map)::{}\n",
},
},
{
@@ -27,7 +27,7 @@ var divideOperatorScenarios = []expressionScenario{
document: `{a: cat_meow, b: _}`,
expression: `.c = .a / .b`,
expected: []string{
- "D0, P[], (doc)::{a: cat_meow, b: _, c: [cat, meow]}\n",
+ "D0, P[], (!!map)::{a: cat_meow, b: _, c: [cat, meow]}\n",
},
},
{
@@ -36,7 +36,7 @@ var divideOperatorScenarios = []expressionScenario{
document: `{a: 12, b: 2.5}`,
expression: `.a = .a / .b`,
expected: []string{
- "D0, P[], (doc)::{a: 4.8, b: 2.5}\n",
+ "D0, P[], (!!map)::{a: 4.8, b: 2.5}\n",
},
},
{
@@ -45,7 +45,7 @@ var divideOperatorScenarios = []expressionScenario{
document: `{a: 1, b: -1}`,
expression: `.a = .a / 0 | .b = .b / 0`,
expected: []string{
- "D0, P[], (doc)::{a: !!float +Inf, b: !!float -Inf}\n",
+ "D0, P[], (!!map)::{a: !!float +Inf, b: !!float -Inf}\n",
},
},
{
@@ -54,7 +54,7 @@ var divideOperatorScenarios = []expressionScenario{
document: "a: !horse cat_meow\nb: !goat _",
expression: `.a = .a / .b`,
expected: []string{
- "D0, P[], (doc)::a: !horse\n - cat\n - meow\nb: !goat _\n",
+ "D0, P[], (!!map)::a: !horse\n - cat\n - meow\nb: !goat _\n",
},
},
{
@@ -63,7 +63,7 @@ var divideOperatorScenarios = []expressionScenario{
document: "a: !horse 1.2\nb: !goat 2.3",
expression: `.a = .a / .b`,
expected: []string{
- "D0, P[], (doc)::a: !horse 0.5217391304347826\nb: !goat 2.3\n",
+ "D0, P[], (!!map)::a: !horse 0.5217391304347826\nb: !goat 2.3\n",
},
},
{
@@ -71,7 +71,7 @@ var divideOperatorScenarios = []expressionScenario{
document: "a: 2\nb: !goat 2.3",
expression: `.a = .a / .b`,
expected: []string{
- "D0, P[], (doc)::a: 0.8695652173913044\nb: !goat 2.3\n",
+ "D0, P[], (!!map)::a: 0.8695652173913044\nb: !goat 2.3\n",
},
},
{
@@ -80,7 +80,7 @@ var divideOperatorScenarios = []expressionScenario{
document: "a: !horse 2\nb: !goat 3",
expression: `.a = .a / .b`,
expected: []string{
- "D0, P[], (doc)::a: !horse 0.6666666666666666\nb: !goat 3\n",
+ "D0, P[], (!!map)::a: !horse 0.6666666666666666\nb: !goat 3\n",
},
},
{
@@ -89,7 +89,7 @@ var divideOperatorScenarios = []expressionScenario{
document: "a: &horse [1]",
expression: `.a[1] = .a[0] / 2`,
expected: []string{
- "D0, P[], (doc)::a: &horse [1, 0.5]\n",
+ "D0, P[], (!!map)::a: &horse [1, 0.5]\n",
},
},
{
diff --git a/pkg/yqlib/operator_document_index.go b/pkg/yqlib/operator_document_index.go
index 566fe9df..0f853d78 100644
--- a/pkg/yqlib/operator_document_index.go
+++ b/pkg/yqlib/operator_document_index.go
@@ -3,8 +3,6 @@ package yqlib
import (
"container/list"
"fmt"
-
- "gopkg.in/yaml.v3"
)
func getDocumentIndexOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@@ -12,8 +10,7 @@ func getDocumentIndexOperator(d *dataTreeNavigator, context Context, expressionN
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- node := &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", candidate.Document), Tag: "!!int"}
- scalar := candidate.CreateReplacement(node)
+ scalar := candidate.CreateReplacement(ScalarNode, "!!int", fmt.Sprintf("%v", candidate.GetDocument()))
results.PushBack(scalar)
}
return context.ChildContext(results), nil
diff --git a/pkg/yqlib/operator_document_index_test.go b/pkg/yqlib/operator_document_index_test.go
index e0d82686..bd5962de 100644
--- a/pkg/yqlib/operator_document_index_test.go
+++ b/pkg/yqlib/operator_document_index_test.go
@@ -28,7 +28,7 @@ var documentIndexScenarios = []expressionScenario{
document: "a: cat\n---\na: frog\n",
expression: `select(document_index == 1)`,
expected: []string{
- "D1, P[], (doc)::a: frog\n",
+ "D1, P[], (!!map)::a: frog\n",
},
},
{
@@ -36,7 +36,7 @@ var documentIndexScenarios = []expressionScenario{
document: "a: cat\n---\na: frog\n",
expression: `select(di == 1)`,
expected: []string{
- "D1, P[], (doc)::a: frog\n",
+ "D1, P[], (!!map)::a: frog\n",
},
},
{
@@ -45,7 +45,7 @@ var documentIndexScenarios = []expressionScenario{
expression: `.a | ({"match": ., "doc": document_index})`,
expected: []string{
"D0, P[], (!!map)::match: cat\ndoc: 0\n",
- "D0, P[], (!!map)::match: frog\ndoc: 1\n",
+ "D1, P[], (!!map)::match: frog\ndoc: 1\n",
},
},
}
diff --git a/pkg/yqlib/operator_encoder_decoder.go b/pkg/yqlib/operator_encoder_decoder.go
index 877a0902..90c0dbef 100644
--- a/pkg/yqlib/operator_encoder_decoder.go
+++ b/pkg/yqlib/operator_encoder_decoder.go
@@ -7,8 +7,6 @@ import (
"errors"
"regexp"
"strings"
-
- "gopkg.in/yaml.v3"
)
func configureEncoder(format PrinterOutputFormat, indent int) Encoder {
@@ -78,9 +76,8 @@ func encodeOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
if originalList != nil && originalList.Len() > 0 && hasOnlyOneNewLine.MatchString(stringValue) {
original := originalList.Front().Value.(*CandidateNode)
- originalNode := unwrapDoc(original.Node)
// original block did not have a newline at the end, get rid of this one too
- if !endWithNewLine.MatchString(originalNode.Value) {
+ if !endWithNewLine.MatchString(original.Value) {
stringValue = chomper.ReplaceAllString(stringValue, "")
}
}
@@ -92,8 +89,7 @@ func encodeOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
stringValue = chomper.ReplaceAllString(stringValue, "")
}
- stringContentNode := &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!str", Value: stringValue}
- results.PushBack(candidate.CreateReplacement(stringContentNode))
+ results.PushBack(candidate.CreateReplacement(ScalarNode, "!!str", stringValue))
}
return context.ChildContext(results), nil
}
@@ -141,21 +137,21 @@ func decodeOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
context.SetVariable("decoded: "+candidate.GetKey(), candidate.AsList())
- log.Debugf("got: [%v]", candidate.Node.Value)
+ log.Debugf("got: [%v]", candidate.Value)
- err := decoder.Init(strings.NewReader(unwrapDoc(candidate.Node).Value))
+ err := decoder.Init(strings.NewReader(candidate.Value))
if err != nil {
return Context{}, err
}
- decodedNode, errorReading := decoder.Decode()
+ node, errorReading := decoder.Decode()
if errorReading != nil {
return Context{}, errorReading
}
- //first node is a doc
- node := unwrapDoc(decodedNode.Node)
+ node.Key = candidate.Key
+ node.Parent = candidate.Parent
- results.PushBack(candidate.CreateReplacement(node))
+ results.PushBack(node)
}
return context.ChildContext(results), nil
}
diff --git a/pkg/yqlib/operator_encoder_decoder_test.go b/pkg/yqlib/operator_encoder_decoder_test.go
index a6eaee89..6280f0cc 100644
--- a/pkg/yqlib/operator_encoder_decoder_test.go
+++ b/pkg/yqlib/operator_encoder_decoder_test.go
@@ -4,7 +4,7 @@ import (
"testing"
)
-var prefix = "D0, P[], (doc)::a:\n cool:\n bob: dylan\n"
+var prefix = "D0, P[], (!!map)::a:\n cool:\n bob: dylan\n"
var encoderDecoderOperatorScenarios = []expressionScenario{
{
@@ -13,7 +13,7 @@ var encoderDecoderOperatorScenarios = []expressionScenario{
document: `{a: {cool: "thing"}}`,
expression: `.b = (.a | to_json)`,
expected: []string{
- `D0, P[], (doc)::{a: {cool: "thing"}, b: "{\n \"cool\": \"thing\"\n}\n"}
+ `D0, P[], (!!map)::{a: {cool: "thing"}, b: "{\n \"cool\": \"thing\"\n}\n"}
`,
},
},
@@ -24,7 +24,7 @@ var encoderDecoderOperatorScenarios = []expressionScenario{
document: `{a: {cool: "thing"}}`,
expression: `.b = (.a | to_json(0))`,
expected: []string{
- `D0, P[], (doc)::{a: {cool: "thing"}, b: '{"cool":"thing"}'}
+ `D0, P[], (!!map)::{a: {cool: "thing"}, b: '{"cool":"thing"}'}
`,
},
},
@@ -35,7 +35,7 @@ var encoderDecoderOperatorScenarios = []expressionScenario{
document: `{a: {cool: "thing"}}`,
expression: `.b = (.a | @json)`,
expected: []string{
- `D0, P[], (doc)::{a: {cool: "thing"}, b: '{"cool":"thing"}'}
+ `D0, P[], (!!map)::{a: {cool: "thing"}, b: '{"cool":"thing"}'}
`,
},
},
@@ -54,7 +54,7 @@ var encoderDecoderOperatorScenarios = []expressionScenario{
document: `{a: {cool: "thing"}}`,
expression: `.b = (.a | to_props)`,
expected: []string{
- `D0, P[], (doc)::{a: {cool: "thing"}, b: "cool = thing\n"}
+ `D0, P[], (!!map)::{a: {cool: "thing"}, b: "cool = thing\n"}
`,
},
},
@@ -63,7 +63,7 @@ var encoderDecoderOperatorScenarios = []expressionScenario{
document: `{a: {cool: "thing"}}`,
expression: `.b = (.a | @props)`,
expected: []string{
- `D0, P[], (doc)::{a: {cool: "thing"}, b: "cool = thing\n"}
+ `D0, P[], (!!map)::{a: {cool: "thing"}, b: "cool = thing\n"}
`,
},
},
@@ -72,7 +72,7 @@ var encoderDecoderOperatorScenarios = []expressionScenario{
document: `a: "cats=great\ndogs=cool as well"`,
expression: `.a |= @propsd`,
expected: []string{
- "D0, P[], (doc)::a:\n cats: great\n dogs: cool as well\n",
+ "D0, P[], (!!map)::a:\n cats: great\n dogs: cool as well\n",
},
},
{
@@ -80,7 +80,7 @@ var encoderDecoderOperatorScenarios = []expressionScenario{
document: `a: "cats,dogs\ngreat,cool as well"`,
expression: `.a |= @csvd`,
expected: []string{
- "D0, P[], (doc)::a:\n - cats: great\n dogs: cool as well\n",
+ "D0, P[], (!!map)::a:\n - cats: great\n dogs: cool as well\n",
},
},
{
@@ -88,7 +88,7 @@ var encoderDecoderOperatorScenarios = []expressionScenario{
document: `a: "cats dogs\ngreat cool as well"`,
expression: `.a |= @tsvd`,
expected: []string{
- "D0, P[], (doc)::a:\n - cats: great\n dogs: cool as well\n",
+ "D0, P[], (!!map)::a:\n - cats: great\n dogs: cool as well\n",
},
},
{
@@ -122,7 +122,7 @@ var encoderDecoderOperatorScenarios = []expressionScenario{
document: `{a: {cool: "thing"}}`,
expression: `.b = (.a | to_yaml)`,
expected: []string{
- `D0, P[], (doc)::{a: {cool: "thing"}, b: "{cool: \"thing\"}\n"}
+ `D0, P[], (!!map)::{a: {cool: "thing"}, b: "{cool: \"thing\"}\n"}
`,
},
},
@@ -131,7 +131,7 @@ var encoderDecoderOperatorScenarios = []expressionScenario{
document: `a: "foo: bar"`,
expression: `.b = (.a | from_yaml)`,
expected: []string{
- "D0, P[], (doc)::a: \"foo: bar\"\nb:\n foo: bar\n",
+ "D0, P[], (!!map)::a: \"foo: bar\"\nb:\n foo: bar\n",
},
},
{
@@ -140,7 +140,7 @@ var encoderDecoderOperatorScenarios = []expressionScenario{
document: "a: |\n foo: bar\n baz: dog\n",
expression: `.a |= (from_yaml | .foo = "cat" | to_yaml)`,
expected: []string{
- "D0, P[], (doc)::a: |\n foo: cat\n baz: dog\n",
+ "D0, P[], (!!map)::a: |\n foo: cat\n baz: dog\n",
},
},
{
@@ -149,7 +149,7 @@ var encoderDecoderOperatorScenarios = []expressionScenario{
document: "a: |-\n foo: bar\n baz: dog\n",
expression: `.a |= (from_yaml | .foo = "cat" | to_yaml)`,
expected: []string{
- "D0, P[], (doc)::a: |-\n foo: cat\n baz: dog\n",
+ "D0, P[], (!!map)::a: |-\n foo: cat\n baz: dog\n",
},
},
{
@@ -158,7 +158,7 @@ var encoderDecoderOperatorScenarios = []expressionScenario{
document: "a: 'foo: bar'",
expression: `.a |= (from_yaml | .foo = "cat" | to_yaml)`,
expected: []string{
- "D0, P[], (doc)::a: 'foo: cat'\n",
+ "D0, P[], (!!map)::a: 'foo: cat'\n",
},
},
{
@@ -193,7 +193,7 @@ var encoderDecoderOperatorScenarios = []expressionScenario{
document: "a: \"foo: bar\"",
expression: `.a |= (from_yaml | .foo = {"a": "frog"} | to_yaml)`,
expected: []string{
- "D0, P[], (doc)::a: \"foo:\\n a: frog\"\n",
+ "D0, P[], (!!map)::a: \"foo:\\n a: frog\"\n",
},
},
{
@@ -229,7 +229,7 @@ var encoderDecoderOperatorScenarios = []expressionScenario{
document: `a: "bar"`,
expression: `.b = (.a | from_xml)`,
expected: []string{
- "D0, P[], (doc)::a: \"bar\"\nb:\n foo: bar\n",
+ "D0, P[], (!!map)::a: \"bar\"\nb:\n foo: bar\n",
},
},
{
@@ -299,7 +299,7 @@ var encoderDecoderOperatorScenarios = []expressionScenario{
document: "coolData: YTogYXBwbGUK",
expression: ".coolData |= (@base64d | from_yaml)",
expected: []string{
- "D0, P[], (doc)::coolData:\n a: apple\n",
+ "D0, P[], (!!map)::coolData:\n a: apple\n",
},
},
{
diff --git a/pkg/yqlib/operator_entries.go b/pkg/yqlib/operator_entries.go
index 2af9fe94..2279d75b 100644
--- a/pkg/yqlib/operator_entries.go
+++ b/pkg/yqlib/operator_entries.go
@@ -3,64 +3,59 @@ package yqlib
import (
"container/list"
"fmt"
-
- yaml "gopkg.in/yaml.v3"
)
-func entrySeqFor(key *yaml.Node, value *yaml.Node) *yaml.Node {
- var keyKey = &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!str", Value: "key"}
- var valueKey = &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!str", Value: "value"}
+func entrySeqFor(key *CandidateNode, value *CandidateNode) *CandidateNode {
+ var keyKey = &CandidateNode{Kind: ScalarNode, Tag: "!!str", Value: "key"}
+ var valueKey = &CandidateNode{Kind: ScalarNode, Tag: "!!str", Value: "value"}
- return &yaml.Node{
- Kind: yaml.MappingNode,
+ return &CandidateNode{
+ Kind: MappingNode,
Tag: "!!map",
- Content: []*yaml.Node{keyKey, key, valueKey, value},
+ Content: []*CandidateNode{keyKey, key, valueKey, value},
}
}
func toEntriesFromMap(candidateNode *CandidateNode) *CandidateNode {
- var sequence = &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
- var entriesNode = candidateNode.CreateReplacementWithDocWrappers(sequence)
+ var sequence = candidateNode.CreateReplacementWithComments(SequenceNode, "!!seq", 0)
- var contents = unwrapDoc(candidateNode.Node).Content
+ var contents = candidateNode.Content
for index := 0; index < len(contents); index = index + 2 {
key := contents[index]
value := contents[index+1]
- sequence.Content = append(sequence.Content, entrySeqFor(key, value))
+ sequence.AddChild(entrySeqFor(key, value))
}
- return entriesNode
+ return sequence
}
func toEntriesfromSeq(candidateNode *CandidateNode) *CandidateNode {
- var sequence = &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
- var entriesNode = candidateNode.CreateReplacementWithDocWrappers(sequence)
+ var sequence = candidateNode.CreateReplacementWithComments(SequenceNode, "!!seq", 0)
- var contents = unwrapDoc(candidateNode.Node).Content
+ var contents = candidateNode.Content
for index := 0; index < len(contents); index = index + 1 {
- key := &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!int", Value: fmt.Sprintf("%v", index)}
+ key := &CandidateNode{Kind: ScalarNode, Tag: "!!int", Value: fmt.Sprintf("%v", index)}
value := contents[index]
- sequence.Content = append(sequence.Content, entrySeqFor(key, value))
+ sequence.AddChild(entrySeqFor(key, value))
}
- return entriesNode
+ return sequence
}
func toEntriesOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
var results = list.New()
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- candidateNode := unwrapDoc(candidate.Node)
- switch candidateNode.Kind {
- case yaml.MappingNode:
+ switch candidate.Kind {
+ case MappingNode:
results.PushBack(toEntriesFromMap(candidate))
- case yaml.SequenceNode:
+ case SequenceNode:
results.PushBack(toEntriesfromSeq(candidate))
default:
- if candidateNode.Tag != "!!null" {
- return Context{}, fmt.Errorf("%v has no keys", candidate.Node.Tag)
+ if candidate.Tag != "!!null" {
+ return Context{}, fmt.Errorf("%v has no keys", candidate.Tag)
}
}
}
@@ -68,9 +63,8 @@ func toEntriesOperator(d *dataTreeNavigator, context Context, expressionNode *Ex
return context.ChildContext(results), nil
}
-func parseEntry(entry *yaml.Node, position int) (*yaml.Node, *yaml.Node, error) {
+func parseEntry(candidateNode *CandidateNode, position int) (*CandidateNode, *CandidateNode, error) {
prefs := traversePreferences{DontAutoCreate: true}
- candidateNode := &CandidateNode{Node: entry}
keyResults, err := traverseMap(Context{}, candidateNode, createStringScalarNode("key"), prefs, false)
@@ -88,15 +82,14 @@ func parseEntry(entry *yaml.Node, position int) (*yaml.Node, *yaml.Node, error)
return nil, nil, fmt.Errorf("expected to find one 'value' entry but found %v in position %v", valueResults.Len(), position)
}
- return keyResults.Front().Value.(*CandidateNode).Node, valueResults.Front().Value.(*CandidateNode).Node, nil
+ return keyResults.Front().Value.(*CandidateNode), valueResults.Front().Value.(*CandidateNode), nil
}
func fromEntries(candidateNode *CandidateNode) (*CandidateNode, error) {
- var node = &yaml.Node{Kind: yaml.MappingNode, Tag: "!!map"}
- var mapCandidateNode = candidateNode.CreateReplacementWithDocWrappers(node)
+ var node = candidateNode.CopyWithoutContent()
- var contents = unwrapDoc(candidateNode.Node).Content
+ var contents = candidateNode.Content
for index := 0; index < len(contents); index = index + 1 {
key, value, err := parseEntry(contents[index], index)
@@ -104,19 +97,20 @@ func fromEntries(candidateNode *CandidateNode) (*CandidateNode, error) {
return nil, err
}
- node.Content = append(node.Content, key, value)
+ node.AddKeyValueChild(key, value)
}
- return mapCandidateNode, nil
+ node.Kind = MappingNode
+ node.Tag = "!!map"
+ return node, nil
}
func fromEntriesOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
var results = list.New()
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- candidateNode := unwrapDoc(candidate.Node)
- switch candidateNode.Kind {
- case yaml.SequenceNode:
+ switch candidate.Kind {
+ case SequenceNode:
mapResult, err := fromEntries(candidate)
if err != nil {
return Context{}, err
@@ -162,8 +156,13 @@ func withEntriesOperator(d *dataTreeNavigator, context Context, expressionNode *
if err != nil {
return Context{}, err
}
+ log.Debug("candidate %v", NodeToString(candidate))
+ log.Debug("candidate leading content: %v", candidate.LeadingContent)
collected.LeadingContent = candidate.LeadingContent
- collected.TrailingContent = candidate.TrailingContent
+ log.Debug("candidate FootComment: [%v]", candidate.FootComment)
+
+ collected.HeadComment = candidate.HeadComment
+ collected.FootComment = candidate.FootComment
log.Debugf("**** collected %v", collected.LeadingContent)
diff --git a/pkg/yqlib/operator_env.go b/pkg/yqlib/operator_env.go
index ed3f51e2..3ab10b24 100644
--- a/pkg/yqlib/operator_env.go
+++ b/pkg/yqlib/operator_env.go
@@ -7,7 +7,6 @@ import (
"strings"
parse "github.com/a8m/envsubst/parse"
- yaml "gopkg.in/yaml.v3"
)
type envOpPreferences struct {
@@ -18,39 +17,40 @@ type envOpPreferences struct {
}
func envOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
- envName := expressionNode.Operation.CandidateNode.Node.Value
+ envName := expressionNode.Operation.CandidateNode.Value
log.Debug("EnvOperator, env name:", envName)
rawValue := os.Getenv(envName)
preferences := expressionNode.Operation.Preferences.(envOpPreferences)
- var node *yaml.Node
+ var node *CandidateNode
if preferences.StringValue {
- node = &yaml.Node{
- Kind: yaml.ScalarNode,
+ node = &CandidateNode{
+ Kind: ScalarNode,
Tag: "!!str",
Value: rawValue,
}
} else if rawValue == "" {
- return Context{}, fmt.Errorf("Value for env variable '%v' not provided in env()", envName)
+ return Context{}, fmt.Errorf("value for env variable '%v' not provided in env()", envName)
} else {
- var dataBucket yaml.Node
- decoder := yaml.NewDecoder(strings.NewReader(rawValue))
- errorReading := decoder.Decode(&dataBucket)
- if errorReading != nil {
- return Context{}, errorReading
+ decoder := NewYamlDecoder(ConfiguredYamlPreferences)
+ if err := decoder.Init(strings.NewReader(rawValue)); err != nil {
+ return Context{}, err
}
- //first node is a doc
- node = unwrapDoc(&dataBucket)
+ var err error
+ node, err = decoder.Decode()
+
+ if err != nil {
+ return Context{}, err
+ }
+
}
log.Debug("ENV tag", node.Tag)
log.Debug("ENV value", node.Value)
log.Debug("ENV Kind", node.Kind)
- target := &CandidateNode{Node: node}
-
- return context.SingleChildContext(target), nil
+ return context.SingleChildContext(node), nil
}
func envsubstOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@@ -70,8 +70,7 @@ func envsubstOperator(d *dataTreeNavigator, context Context, expressionNode *Exp
}
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
- candidate := el.Value.(*CandidateNode)
- node := unwrapDoc(candidate.Node)
+ node := el.Value.(*CandidateNode)
if node.Tag != "!!str" {
log.Warning("EnvSubstOperator, env name:", node.Tag, node.Value)
return Context{}, fmt.Errorf("cannot substitute with %v, can only substitute strings. Hint: Most often you'll want to use '|=' over '=' for this operation", node.Tag)
@@ -81,8 +80,7 @@ func envsubstOperator(d *dataTreeNavigator, context Context, expressionNode *Exp
if err != nil {
return Context{}, err
}
- targetNode := &yaml.Node{Kind: yaml.ScalarNode, Value: value, Tag: "!!str"}
- result := candidate.CreateReplacement(targetNode)
+ result := node.CreateReplacement(ScalarNode, "!!str", value)
results.PushBack(result)
}
diff --git a/pkg/yqlib/operator_env_test.go b/pkg/yqlib/operator_env_test.go
index 7f403dd7..878c5bce 100644
--- a/pkg/yqlib/operator_env_test.go
+++ b/pkg/yqlib/operator_env_test.go
@@ -60,7 +60,7 @@ var envOperatorScenarios = []expressionScenario{
environmentVariables: map[string]string{"pathEnv": ".a.b[0].name", "valueEnv": "moo"},
expression: `eval(strenv(pathEnv)) = strenv(valueEnv)`,
expected: []string{
- "D0, P[], (doc)::{a: {b: [{name: moo}, {name: cat}]}}\n",
+ "D0, P[], (!!map)::{a: {b: [{name: moo}, {name: cat}]}}\n",
},
},
{
@@ -136,7 +136,7 @@ var envOperatorScenarios = []expressionScenario{
document: "{v: \"${myenv}\"}",
expression: `.v |= envsubst`,
expected: []string{
- "D0, P[], (doc)::{v: \"cat meow\"}\n",
+ "D0, P[], (!!map)::{v: \"cat meow\"}\n",
},
},
{
diff --git a/pkg/yqlib/operator_equals.go b/pkg/yqlib/operator_equals.go
index d8dc788a..9f836c9f 100644
--- a/pkg/yqlib/operator_equals.go
+++ b/pkg/yqlib/operator_equals.go
@@ -1,7 +1,5 @@
package yqlib
-import "gopkg.in/yaml.v3"
-
func equalsOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
log.Debugf("-- equalsOperation")
return crossFunction(d, context, expressionNode, isEquals(false), true)
@@ -12,33 +10,29 @@ func isEquals(flip bool) func(d *dataTreeNavigator, context Context, lhs *Candid
value := false
log.Debugf("-- isEquals cross function")
if lhs == nil && rhs == nil {
+ log.Debugf("-- both are nil")
owner := &CandidateNode{}
return createBooleanCandidate(owner, !flip), nil
} else if lhs == nil {
log.Debugf("lhs nil, but rhs is not")
- rhsNode := unwrapDoc(rhs.Node)
- value := rhsNode.Tag == "!!null"
+ value := rhs.Tag == "!!null"
if flip {
value = !value
}
return createBooleanCandidate(rhs, value), nil
} else if rhs == nil {
log.Debugf("lhs not nil, but rhs is")
- lhsNode := unwrapDoc(lhs.Node)
- value := lhsNode.Tag == "!!null"
+ value := lhs.Tag == "!!null"
if flip {
value = !value
}
return createBooleanCandidate(lhs, value), nil
}
- lhsNode := unwrapDoc(lhs.Node)
- rhsNode := unwrapDoc(rhs.Node)
-
- if lhsNode.Tag == "!!null" {
- value = (rhsNode.Tag == "!!null")
- } else if lhsNode.Kind == yaml.ScalarNode && rhsNode.Kind == yaml.ScalarNode {
- value = matchKey(lhsNode.Value, rhsNode.Value)
+ if lhs.Tag == "!!null" {
+ value = (rhs.Tag == "!!null")
+ } else if lhs.Kind == ScalarNode && rhs.Kind == ScalarNode {
+ value = matchKey(lhs.Value, rhs.Value)
}
log.Debugf("%v == %v ? %v", NodeToString(lhs), NodeToString(rhs), value)
if flip {
diff --git a/pkg/yqlib/operator_equals_test.go b/pkg/yqlib/operator_equals_test.go
index 7a821647..43a2fa86 100644
--- a/pkg/yqlib/operator_equals_test.go
+++ b/pkg/yqlib/operator_equals_test.go
@@ -49,7 +49,7 @@ var equalsOperatorScenarios = []expressionScenario{
document: "{}",
expression: "(.a == .b) as $x | .",
expected: []string{
- "D0, P[], (doc)::{}\n",
+ "D0, P[], (!!map)::{}\n",
},
},
{
@@ -65,7 +65,7 @@ var equalsOperatorScenarios = []expressionScenario{
document: "{}",
expression: "(.a != .b) as $x | .",
expected: []string{
- "D0, P[], (doc)::{}\n",
+ "D0, P[], (!!map)::{}\n",
},
},
{
@@ -87,7 +87,7 @@ var equalsOperatorScenarios = []expressionScenario{
document: "{a: {b: 10}}",
expression: "select(.d == .c)",
expected: []string{
- "D0, P[], (doc)::{a: {b: 10}}\n",
+ "D0, P[], (!!map)::{a: {b: 10}}\n",
},
},
{
@@ -95,7 +95,7 @@ var equalsOperatorScenarios = []expressionScenario{
document: "{a: {b: 10}}",
expression: "select(null == .c)",
expected: []string{
- "D0, P[], (doc)::{a: {b: 10}}\n",
+ "D0, P[], (!!map)::{a: {b: 10}}\n",
},
},
{
@@ -176,7 +176,7 @@ var equalsOperatorScenarios = []expressionScenario{
document: "a: frog",
expression: `select(.b != "thing")`,
expected: []string{
- "D0, P[], (doc)::a: frog\n",
+ "D0, P[], (!!map)::a: frog\n",
},
},
{
@@ -184,7 +184,7 @@ var equalsOperatorScenarios = []expressionScenario{
document: "a: frog",
expression: `select(.b == .c)`,
expected: []string{
- "D0, P[], (doc)::a: frog\n",
+ "D0, P[], (!!map)::a: frog\n",
},
},
}
diff --git a/pkg/yqlib/operator_error.go b/pkg/yqlib/operator_error.go
index 8b0e3a9f..ba66a8a3 100644
--- a/pkg/yqlib/operator_error.go
+++ b/pkg/yqlib/operator_error.go
@@ -14,7 +14,7 @@ func errorOperator(d *dataTreeNavigator, context Context, expressionNode *Expres
}
errorMessage := "aborted"
if rhs.MatchingNodes.Len() > 0 {
- errorMessage = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
+ errorMessage = rhs.MatchingNodes.Front().Value.(*CandidateNode).Value
}
return Context{}, fmt.Errorf(errorMessage)
}
diff --git a/pkg/yqlib/operator_error_test.go b/pkg/yqlib/operator_error_test.go
index 845686d6..3ccbbf20 100644
--- a/pkg/yqlib/operator_error_test.go
+++ b/pkg/yqlib/operator_error_test.go
@@ -27,7 +27,7 @@ var errorOperatorScenarios = []expressionScenario{
document: "name: Bob\nfavouriteAnimal: cat\n",
expression: validationExpression,
expected: []string{
- "D0, P[], (doc)::name: Bob\nfavouriteAnimal: cat\nnumPets: 3\n",
+ "D0, P[], (!!map)::name: Bob\nfavouriteAnimal: cat\nnumPets: 3\n",
},
},
}
diff --git a/pkg/yqlib/operator_eval.go b/pkg/yqlib/operator_eval.go
index 78037e97..2bba51d2 100644
--- a/pkg/yqlib/operator_eval.go
+++ b/pkg/yqlib/operator_eval.go
@@ -17,7 +17,7 @@ func evalOperator(d *dataTreeNavigator, context Context, expressionNode *Express
for pathExpStrEntry := pathExpStrResults.MatchingNodes.Front(); pathExpStrEntry != nil; pathExpStrEntry = pathExpStrEntry.Next() {
expressionStrCandidate := pathExpStrEntry.Value.(*CandidateNode)
- expressions[expIndex], err = ExpressionParser.ParseExpression(expressionStrCandidate.Node.Value)
+ expressions[expIndex], err = ExpressionParser.ParseExpression(expressionStrCandidate.Value)
if err != nil {
return Context{}, err
}
diff --git a/pkg/yqlib/operator_eval_test.go b/pkg/yqlib/operator_eval_test.go
index 3bff5a12..6726b75a 100644
--- a/pkg/yqlib/operator_eval_test.go
+++ b/pkg/yqlib/operator_eval_test.go
@@ -21,7 +21,7 @@ var evalOperatorScenarios = []expressionScenario{
environmentVariables: map[string]string{"pathEnv": ".a.b[0].name", "valueEnv": "moo"},
expression: `eval(strenv(pathEnv)) = strenv(valueEnv)`,
expected: []string{
- "D0, P[], (doc)::{a: {b: [{name: moo}, {name: cat}]}}\n",
+ "D0, P[], (!!map)::{a: {b: [{name: moo}, {name: cat}]}}\n",
},
},
}
diff --git a/pkg/yqlib/operator_file.go b/pkg/yqlib/operator_file.go
index c0ffaad8..29896719 100644
--- a/pkg/yqlib/operator_file.go
+++ b/pkg/yqlib/operator_file.go
@@ -3,8 +3,6 @@ package yqlib
import (
"container/list"
"fmt"
-
- yaml "gopkg.in/yaml.v3"
)
func getFilenameOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@@ -14,8 +12,7 @@ func getFilenameOperator(d *dataTreeNavigator, context Context, expressionNode *
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- node := &yaml.Node{Kind: yaml.ScalarNode, Value: candidate.Filename, Tag: "!!str"}
- result := candidate.CreateReplacement(node)
+ result := candidate.CreateReplacement(ScalarNode, "!!str", candidate.GetFilename())
results.PushBack(result)
}
@@ -29,8 +26,7 @@ func getFileIndexOperator(d *dataTreeNavigator, context Context, expressionNode
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- node := &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", candidate.FileIndex), Tag: "!!int"}
- result := candidate.CreateReplacement(node)
+ result := candidate.CreateReplacement(ScalarNode, "!!int", fmt.Sprintf("%v", candidate.GetFileIndex()))
results.PushBack(result)
}
diff --git a/pkg/yqlib/operator_filter.go b/pkg/yqlib/operator_filter.go
index 8cf28303..0bd5ebb0 100644
--- a/pkg/yqlib/operator_filter.go
+++ b/pkg/yqlib/operator_filter.go
@@ -25,7 +25,7 @@ func filterOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
if err != nil {
return Context{}, err
}
- collected.Node.Style = unwrapDoc(candidate.Node).Style
+ collected.Style = candidate.Style
results.PushBack(collected)
}
return context.ChildContext(results), nil
diff --git a/pkg/yqlib/operator_flatten.go b/pkg/yqlib/operator_flatten.go
index e7ccf99c..011337e6 100644
--- a/pkg/yqlib/operator_flatten.go
+++ b/pkg/yqlib/operator_flatten.go
@@ -2,26 +2,24 @@ package yqlib
import (
"fmt"
-
- yaml "gopkg.in/yaml.v3"
)
type flattenPreferences struct {
depth int
}
-func flatten(node *yaml.Node, depth int) {
+func flatten(node *CandidateNode, depth int) {
if depth == 0 {
return
}
- if node.Kind != yaml.SequenceNode {
+ if node.Kind != SequenceNode {
return
}
content := node.Content
- newSeq := make([]*yaml.Node, 0)
+ newSeq := make([]*CandidateNode, 0)
for i := 0; i < len(content); i++ {
- if content[i].Kind == yaml.SequenceNode {
+ if content[i].Kind == SequenceNode {
flatten(content[i], depth-1)
for j := 0; j < len(content[i].Content); j++ {
newSeq = append(newSeq, content[i].Content[j])
@@ -30,7 +28,8 @@ func flatten(node *yaml.Node, depth int) {
newSeq = append(newSeq, content[i])
}
}
- node.Content = newSeq
+ node.Content = make([]*CandidateNode, 0)
+ node.AddChildren(newSeq)
}
func flattenOp(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@@ -40,12 +39,11 @@ func flattenOp(d *dataTreeNavigator, context Context, expressionNode *Expression
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- candidateNode := unwrapDoc(candidate.Node)
- if candidateNode.Kind != yaml.SequenceNode {
- return Context{}, fmt.Errorf("Only arrays are supported for flatten")
+ if candidate.Kind != SequenceNode {
+ return Context{}, fmt.Errorf("only arrays are supported for flatten")
}
- flatten(candidateNode, depth)
+ flatten(candidate, depth)
}
diff --git a/pkg/yqlib/operator_flatten_test.go b/pkg/yqlib/operator_flatten_test.go
index add71e1f..fc764d30 100644
--- a/pkg/yqlib/operator_flatten_test.go
+++ b/pkg/yqlib/operator_flatten_test.go
@@ -11,7 +11,7 @@ var flattenOperatorScenarios = []expressionScenario{
document: `[1, [2], [[3]]]`,
expression: `flatten`,
expected: []string{
- "D0, P[], (doc)::[1, 2, 3]\n",
+ "D0, P[], (!!seq)::[1, 2, 3]\n",
},
},
{
@@ -19,7 +19,7 @@ var flattenOperatorScenarios = []expressionScenario{
document: `[1, [2], [[3]]]`,
expression: `flatten(1)`,
expected: []string{
- "D0, P[], (doc)::[1, 2, [3]]\n",
+ "D0, P[], (!!seq)::[1, 2, [3]]\n",
},
},
{
@@ -27,7 +27,7 @@ var flattenOperatorScenarios = []expressionScenario{
document: `[[]]`,
expression: `flatten`,
expected: []string{
- "D0, P[], (doc)::[]\n",
+ "D0, P[], (!!seq)::[]\n",
},
},
{
@@ -35,7 +35,7 @@ var flattenOperatorScenarios = []expressionScenario{
document: `[{foo: bar}, [{foo: baz}]]`,
expression: `flatten`,
expected: []string{
- "D0, P[], (doc)::[{foo: bar}, {foo: baz}]\n",
+ "D0, P[], (!!seq)::[{foo: bar}, {foo: baz}]\n",
},
},
}
diff --git a/pkg/yqlib/operator_group_by.go b/pkg/yqlib/operator_group_by.go
index 3bb70b50..779295b1 100644
--- a/pkg/yqlib/operator_group_by.go
+++ b/pkg/yqlib/operator_group_by.go
@@ -5,13 +5,11 @@ import (
"fmt"
"github.com/elliotchance/orderedmap"
- yaml "gopkg.in/yaml.v3"
)
-func processIntoGroups(d *dataTreeNavigator, context Context, rhsExp *ExpressionNode, node *yaml.Node) (*orderedmap.OrderedMap, error) {
+func processIntoGroups(d *dataTreeNavigator, context Context, rhsExp *ExpressionNode, node *CandidateNode) (*orderedmap.OrderedMap, error) {
var newMatches = orderedmap.NewOrderedMap()
- for _, node := range node.Content {
- child := &CandidateNode{Node: node}
+ for _, child := range node.Content {
rhs, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(child), rhsExp)
if err != nil {
@@ -23,7 +21,7 @@ func processIntoGroups(d *dataTreeNavigator, context Context, rhsExp *Expression
if rhs.MatchingNodes.Len() > 0 {
first := rhs.MatchingNodes.Front()
keyCandidate := first.Value.(*CandidateNode)
- keyValue = keyCandidate.Node.Value
+ keyValue = keyCandidate.Value
}
groupList, exists := newMatches.Get(keyValue)
@@ -32,7 +30,7 @@ func processIntoGroups(d *dataTreeNavigator, context Context, rhsExp *Expression
groupList = list.New()
newMatches.Set(keyValue, groupList)
}
- groupList.(*list.List).PushBack(node)
+ groupList.(*list.List).PushBack(child)
}
return newMatches, nil
}
@@ -44,30 +42,29 @@ func groupBy(d *dataTreeNavigator, context Context, expressionNode *ExpressionNo
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- candidateNode := unwrapDoc(candidate.Node)
- if candidateNode.Kind != yaml.SequenceNode {
- return Context{}, fmt.Errorf("Only arrays are supported for group by")
+ if candidate.Kind != SequenceNode {
+ return Context{}, fmt.Errorf("only arrays are supported for group by")
}
- newMatches, err := processIntoGroups(d, context, expressionNode.RHS, candidateNode)
+ newMatches, err := processIntoGroups(d, context, expressionNode.RHS, candidate)
if err != nil {
return Context{}, err
}
- resultNode := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
+ resultNode := candidate.CreateReplacement(SequenceNode, "!!seq", "")
for groupEl := newMatches.Front(); groupEl != nil; groupEl = groupEl.Next() {
- groupResultNode := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
+ groupResultNode := &CandidateNode{Kind: SequenceNode, Tag: "!!seq"}
groupList := groupEl.Value.(*list.List)
for groupItem := groupList.Front(); groupItem != nil; groupItem = groupItem.Next() {
- groupResultNode.Content = append(groupResultNode.Content, groupItem.Value.(*yaml.Node))
+ groupResultNode.AddChild(groupItem.Value.(*CandidateNode))
}
- resultNode.Content = append(resultNode.Content, groupResultNode)
+ resultNode.AddChild(groupResultNode)
}
- results.PushBack(candidate.CreateReplacement(resultNode))
+ results.PushBack(resultNode)
}
diff --git a/pkg/yqlib/operator_has.go b/pkg/yqlib/operator_has.go
index 01d7a1fe..95ab4b6d 100644
--- a/pkg/yqlib/operator_has.go
+++ b/pkg/yqlib/operator_has.go
@@ -3,8 +3,6 @@ package yqlib
import (
"container/list"
"strconv"
-
- yaml "gopkg.in/yaml.v3"
)
func hasOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@@ -19,20 +17,18 @@ func hasOperator(d *dataTreeNavigator, context Context, expressionNode *Expressi
}
wantedKey := "null"
- wanted := &yaml.Node{Tag: "!!null"}
+ wanted := &CandidateNode{Tag: "!!null"}
if rhs.MatchingNodes.Len() != 0 {
- wanted = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node
+ wanted = rhs.MatchingNodes.Front().Value.(*CandidateNode)
wantedKey = wanted.Value
}
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- // grab the first value
- candidateNode := unwrapDoc(candidate.Node)
- var contents = candidateNode.Content
- switch candidateNode.Kind {
- case yaml.MappingNode:
+ var contents = candidate.Content
+ switch candidate.Kind {
+ case MappingNode:
candidateHasKey := false
for index := 0; index < len(contents) && !candidateHasKey; index = index + 2 {
key := contents[index]
@@ -41,7 +37,7 @@ func hasOperator(d *dataTreeNavigator, context Context, expressionNode *Expressi
}
}
results.PushBack(createBooleanCandidate(candidate, candidateHasKey))
- case yaml.SequenceNode:
+ case SequenceNode:
candidateHasKey := false
if wanted.Tag == "!!int" {
var number, errParsingInt = strconv.ParseInt(wantedKey, 10, 64)
diff --git a/pkg/yqlib/operator_has_test.go b/pkg/yqlib/operator_has_test.go
index 47504048..bed11fcb 100644
--- a/pkg/yqlib/operator_has_test.go
+++ b/pkg/yqlib/operator_has_test.go
@@ -18,7 +18,7 @@ var hasOperatorScenarios = []expressionScenario{
document: `a: hello`,
expression: `has(.b) as $c | .`,
expected: []string{
- "D0, P[], (doc)::a: hello\n",
+ "D0, P[], (!!map)::a: hello\n",
},
},
{
diff --git a/pkg/yqlib/operator_keys.go b/pkg/yqlib/operator_keys.go
index 3ea4b5da..bbb9a5d8 100644
--- a/pkg/yqlib/operator_keys.go
+++ b/pkg/yqlib/operator_keys.go
@@ -3,8 +3,6 @@ package yqlib
import (
"container/list"
"fmt"
-
- "gopkg.in/yaml.v3"
)
func isKeyOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@@ -30,7 +28,7 @@ func getKeyOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
candidate := el.Value.(*CandidateNode)
if candidate.Key != nil {
- results.PushBack(candidate.CreateReplacement(candidate.Key))
+ results.PushBack(candidate.Key)
}
}
@@ -45,41 +43,40 @@ func keysOperator(d *dataTreeNavigator, context Context, expressionNode *Express
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- node := unwrapDoc(candidate.Node)
- var targetNode *yaml.Node
- if node.Kind == yaml.MappingNode {
- targetNode = getMapKeys(node)
- } else if node.Kind == yaml.SequenceNode {
- targetNode = getIndices(node)
+
+ var targetNode *CandidateNode
+ if candidate.Kind == MappingNode {
+ targetNode = getMapKeys(candidate)
+ } else if candidate.Kind == SequenceNode {
+ targetNode = getIndices(candidate)
} else {
- return Context{}, fmt.Errorf("Cannot get keys of %v, keys only works for maps and arrays", node.Tag)
+ return Context{}, fmt.Errorf("Cannot get keys of %v, keys only works for maps and arrays", candidate.Tag)
}
- result := candidate.CreateReplacement(targetNode)
- results.PushBack(result)
+ results.PushBack(targetNode)
}
return context.ChildContext(results), nil
}
-func getMapKeys(node *yaml.Node) *yaml.Node {
- contents := make([]*yaml.Node, 0)
+func getMapKeys(node *CandidateNode) *CandidateNode {
+ contents := make([]*CandidateNode, 0)
for index := 0; index < len(node.Content); index = index + 2 {
contents = append(contents, node.Content[index])
}
- return &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq", Content: contents}
+ return &CandidateNode{Kind: SequenceNode, Tag: "!!seq", Content: contents}
}
-func getIndices(node *yaml.Node) *yaml.Node {
- var contents = make([]*yaml.Node, len(node.Content))
+func getIndices(node *CandidateNode) *CandidateNode {
+ var contents = make([]*CandidateNode, len(node.Content))
for index := range node.Content {
- contents[index] = &yaml.Node{
- Kind: yaml.ScalarNode,
+ contents[index] = &CandidateNode{
+ Kind: ScalarNode,
Tag: "!!int",
Value: fmt.Sprintf("%v", index),
}
}
- return &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq", Content: contents}
+ return &CandidateNode{Kind: SequenceNode, Tag: "!!seq", Content: contents}
}
diff --git a/pkg/yqlib/operator_keys_test.go b/pkg/yqlib/operator_keys_test.go
index 3f821b51..b0936608 100644
--- a/pkg/yqlib/operator_keys_test.go
+++ b/pkg/yqlib/operator_keys_test.go
@@ -90,7 +90,7 @@ var keysOperatorScenarios = []expressionScenario{
document: "a:\n x: 3\n y: 4",
expression: `(.a.x | key) = "meow"`,
expected: []string{
- "D0, P[], (doc)::a:\n meow: 3\n y: 4\n",
+ "D0, P[], (!!map)::a:\n meow: 3\n y: 4\n",
},
},
{
diff --git a/pkg/yqlib/operator_kind.go b/pkg/yqlib/operator_kind.go
index da0892c7..1f15a9cf 100644
--- a/pkg/yqlib/operator_kind.go
+++ b/pkg/yqlib/operator_kind.go
@@ -2,21 +2,17 @@ package yqlib
import (
"container/list"
-
- yaml "gopkg.in/yaml.v3"
)
-func kindToText(kind yaml.Kind) string {
+func kindToText(kind Kind) string {
switch kind {
- case yaml.MappingNode:
+ case MappingNode:
return "map"
- case yaml.SequenceNode:
+ case SequenceNode:
return "seq"
- case yaml.DocumentNode:
- return "doc"
- case yaml.ScalarNode:
+ case ScalarNode:
return "scalar"
- case yaml.AliasNode:
+ case AliasNode:
return "alias"
default:
return "unknown"
@@ -30,8 +26,7 @@ func getKindOperator(d *dataTreeNavigator, context Context, expressionNode *Expr
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- node := &yaml.Node{Kind: yaml.ScalarNode, Value: kindToText(candidate.Node.Kind), Tag: "!!str"}
- result := candidate.CreateReplacement(node)
+ result := candidate.CreateReplacement(ScalarNode, "!!str", kindToText(candidate.Kind))
results.PushBack(result)
}
diff --git a/pkg/yqlib/operator_length.go b/pkg/yqlib/operator_length.go
index 46f1c8c8..57c5377e 100644
--- a/pkg/yqlib/operator_length.go
+++ b/pkg/yqlib/operator_length.go
@@ -3,8 +3,6 @@ package yqlib
import (
"container/list"
"fmt"
-
- yaml "gopkg.in/yaml.v3"
)
func lengthOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@@ -13,25 +11,23 @@ func lengthOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- targetNode := unwrapDoc(candidate.Node)
var length int
- switch targetNode.Kind {
- case yaml.ScalarNode:
- if targetNode.Tag == "!!null" {
+ switch candidate.Kind {
+ case ScalarNode:
+ if candidate.Tag == "!!null" {
length = 0
} else {
- length = len(targetNode.Value)
+ length = len(candidate.Value)
}
- case yaml.MappingNode:
- length = len(targetNode.Content) / 2
- case yaml.SequenceNode:
- length = len(targetNode.Content)
+ case MappingNode:
+ length = len(candidate.Content) / 2
+ case SequenceNode:
+ length = len(candidate.Content)
default:
length = 0
}
- node := &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", length), Tag: "!!int"}
- result := candidate.CreateReplacement(node)
+ result := candidate.CreateReplacement(ScalarNode, "!!int", fmt.Sprintf("%v", length))
results.PushBack(result)
}
diff --git a/pkg/yqlib/operator_line.go b/pkg/yqlib/operator_line.go
index 1535e059..cb19f221 100644
--- a/pkg/yqlib/operator_line.go
+++ b/pkg/yqlib/operator_line.go
@@ -3,8 +3,6 @@ package yqlib
import (
"container/list"
"fmt"
-
- yaml "gopkg.in/yaml.v3"
)
func lineOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@@ -14,8 +12,7 @@ func lineOperator(d *dataTreeNavigator, context Context, expressionNode *Express
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- node := &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", candidate.Node.Line), Tag: "!!int"}
- result := candidate.CreateReplacement(node)
+ result := candidate.CreateReplacement(ScalarNode, "!!int", fmt.Sprintf("%v", candidate.Line))
results.PushBack(result)
}
diff --git a/pkg/yqlib/operator_load.go b/pkg/yqlib/operator_load.go
index 678854f6..8eeec303 100644
--- a/pkg/yqlib/operator_load.go
+++ b/pkg/yqlib/operator_load.go
@@ -5,8 +5,6 @@ import (
"container/list"
"fmt"
"os"
-
- "gopkg.in/yaml.v3"
)
var LoadYamlPreferences = YamlPreferences{
@@ -30,7 +28,7 @@ func loadString(filename string) (*CandidateNode, error) {
return nil, err
}
- return &CandidateNode{Node: &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!str", Value: string(filebytes)}}, nil
+ return &CandidateNode{Kind: ScalarNode, Tag: "!!str", Value: string(filebytes)}, nil
}
func loadYaml(filename string, decoder Decoder) (*CandidateNode, error) {
@@ -51,15 +49,15 @@ func loadYaml(filename string, decoder Decoder) (*CandidateNode, error) {
if documents.Len() == 0 {
// return null candidate
- return &CandidateNode{Node: &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!null"}}, nil
+ return &CandidateNode{Kind: ScalarNode, Tag: "!!null"}, nil
} else if documents.Len() == 1 {
candidate := documents.Front().Value.(*CandidateNode)
return candidate, nil
} else {
- sequenceNode := &CandidateNode{Node: &yaml.Node{Kind: yaml.SequenceNode}}
+ sequenceNode := &CandidateNode{Kind: SequenceNode}
for doc := documents.Front(); doc != nil; doc = doc.Next() {
- sequenceNode.Node.Content = append(sequenceNode.Node.Content, unwrapDoc(doc.Value.(*CandidateNode).Node))
+ sequenceNode.AddChild(doc.Value.(*CandidateNode))
}
return sequenceNode, nil
}
@@ -83,11 +81,11 @@ func loadYamlOperator(d *dataTreeNavigator, context Context, expressionNode *Exp
return Context{}, err
}
if rhs.MatchingNodes.Front() == nil {
- return Context{}, fmt.Errorf("Filename expression returned nil")
+ return Context{}, fmt.Errorf("filename expression returned nil")
}
nameCandidateNode := rhs.MatchingNodes.Front().Value.(*CandidateNode)
- filename := nameCandidateNode.Node.Value
+ filename := nameCandidateNode.Value
var contentsCandidate *CandidateNode
diff --git a/pkg/yqlib/operator_load_test.go b/pkg/yqlib/operator_load_test.go
index 5bb30321..2b1f96f6 100644
--- a/pkg/yqlib/operator_load_test.go
+++ b/pkg/yqlib/operator_load_test.go
@@ -10,7 +10,7 @@ var loadScenarios = []expressionScenario{
description: "Load empty file with a comment",
expression: `load("../../examples/empty.yaml")`,
expected: []string{
- "D0, P[], (doc)::# comment\n\n",
+ "D0, P[], (!!null)::# comment\n",
},
},
{
@@ -19,7 +19,7 @@ var loadScenarios = []expressionScenario{
document: `- "../../examples/small.yaml"`,
expression: `.[] |= load(.)`,
expected: []string{
- "D0, P[], (doc)::- # comment\n # about things\n a: cat\n",
+ "D0, P[], (!!seq)::- # comment\n # about things\n a: cat\n",
},
},
{
@@ -43,7 +43,7 @@ var loadScenarios = []expressionScenario{
document: `{myFile: "../../examples/thing.yml"}`,
expression: `load(.myFile)`,
expected: []string{
- "D0, P[], (doc)::a: apple is included\nb: cool.\n",
+ "D0, P[], (!!map)::a: apple is included\nb: cool.\n",
},
},
{
@@ -52,7 +52,7 @@ var loadScenarios = []expressionScenario{
document: `{something: {file: "thing.yml"}}`,
expression: `.something |= load("../../examples/" + .file)`,
expected: []string{
- "D0, P[], (doc)::{something: {a: apple is included, b: cool.}}\n",
+ "D0, P[], (!!map)::{something: {a: apple is included, b: cool.}}\n",
},
},
{
@@ -70,7 +70,7 @@ var loadScenarios = []expressionScenario{
document: `{something: {file: "thing.yml"}}`,
expression: `.something |= load_str("../../examples/" + .file)`,
expected: []string{
- "D0, P[], (doc)::{something: \"a: apple is included\\nb: cool.\"}\n",
+ "D0, P[], (!!map)::{something: \"a: apple is included\\nb: cool.\"}\n",
},
},
{
@@ -79,7 +79,7 @@ var loadScenarios = []expressionScenario{
document: "cool: things",
expression: `.more_stuff = load_xml("../../examples/small.xml")`,
expected: []string{
- "D0, P[], (doc)::cool: things\nmore_stuff:\n this: is some xml\n",
+ "D0, P[], (!!map)::cool: things\nmore_stuff:\n this: is some xml\n",
},
},
{
@@ -87,7 +87,7 @@ var loadScenarios = []expressionScenario{
document: "cool: things",
expression: `.more_stuff = load_props("../../examples/small.properties")`,
expected: []string{
- "D0, P[], (doc)::cool: things\nmore_stuff:\n this:\n is: a properties file\n",
+ "D0, P[], (!!map)::cool: things\nmore_stuff:\n this:\n is: a properties file\n",
},
},
{
@@ -104,7 +104,7 @@ var loadScenarios = []expressionScenario{
document: "cool: things",
expression: `.more_stuff = load_base64("../../examples/base64.txt")`,
expected: []string{
- "D0, P[], (doc)::cool: things\nmore_stuff: my secret chilli recipe is....\n",
+ "D0, P[], (!!map)::cool: things\nmore_stuff: my secret chilli recipe is....\n",
},
},
}
diff --git a/pkg/yqlib/operator_map.go b/pkg/yqlib/operator_map.go
index ec1a5ed0..216d78ae 100644
--- a/pkg/yqlib/operator_map.go
+++ b/pkg/yqlib/operator_map.go
@@ -54,7 +54,7 @@ func mapOperator(d *dataTreeNavigator, context Context, expressionNode *Expressi
if err != nil {
return Context{}, err
}
- collected.Node.Style = unwrapDoc(candidate.Node).Style
+ collected.Style = candidate.Style
results.PushBack(collected)
diff --git a/pkg/yqlib/operator_map_test.go b/pkg/yqlib/operator_map_test.go
index 715df336..7ba25b3c 100644
--- a/pkg/yqlib/operator_map_test.go
+++ b/pkg/yqlib/operator_map_test.go
@@ -29,8 +29,8 @@ var mapOperatorScenarios = []expressionScenario{
document2: `{x: 10, y: 20, z: 30}`,
expression: `map_values(. + 1)`,
expected: []string{
- "D0, P[], (doc)::{a: 2, b: 3, c: 4}\n",
- "D0, P[], (doc)::{x: 11, y: 21, z: 31}\n",
+ "D0, P[], (!!map)::{a: 2, b: 3, c: 4}\n",
+ "D0, P[], (!!map)::{x: 11, y: 21, z: 31}\n",
},
},
{
@@ -38,7 +38,7 @@ var mapOperatorScenarios = []expressionScenario{
document: `{a: 1, b: 2, c: 3}`,
expression: `map_values(. + 1)`,
expected: []string{
- "D0, P[], (doc)::{a: 2, b: 3, c: 4}\n",
+ "D0, P[], (!!map)::{a: 2, b: 3, c: 4}\n",
},
},
}
diff --git a/pkg/yqlib/operator_modulo.go b/pkg/yqlib/operator_modulo.go
index ecb9b406..05d8f821 100644
--- a/pkg/yqlib/operator_modulo.go
+++ b/pkg/yqlib/operator_modulo.go
@@ -5,8 +5,6 @@ import (
"math"
"strconv"
"strings"
-
- yaml "gopkg.in/yaml.v3"
)
func moduloOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@@ -16,40 +14,35 @@ func moduloOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
}
func modulo(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
- lhs.Node = unwrapDoc(lhs.Node)
- rhs.Node = unwrapDoc(rhs.Node)
-
- lhsNode := lhs.Node
-
- if lhsNode.Tag == "!!null" {
- return nil, fmt.Errorf("%v (%v) cannot modulo by %v (%v)", lhsNode.Tag, lhs.GetNicePath(), rhs.Node.Tag, rhs.GetNicePath())
+ if lhs.Tag == "!!null" {
+ return nil, fmt.Errorf("%v (%v) cannot modulo by %v (%v)", lhs.Tag, lhs.GetNicePath(), rhs.Tag, rhs.GetNicePath())
}
- target := &yaml.Node{}
+ target := lhs.CopyWithoutContent()
- if lhsNode.Kind == yaml.ScalarNode && rhs.Node.Kind == yaml.ScalarNode {
- if err := moduloScalars(target, lhsNode, rhs.Node); err != nil {
+ if lhs.Kind == ScalarNode && rhs.Kind == ScalarNode {
+ if err := moduloScalars(target, lhs, rhs); err != nil {
return nil, err
}
} else {
- return nil, fmt.Errorf("%v (%v) cannot modulo by %v (%v)", lhsNode.Tag, lhs.GetNicePath(), rhs.Node.Tag, rhs.GetNicePath())
+ return nil, fmt.Errorf("%v (%v) cannot modulo by %v (%v)", lhs.Tag, lhs.GetNicePath(), rhs.Tag, rhs.GetNicePath())
}
- return lhs.CreateReplacement(target), nil
+ return target, nil
}
-func moduloScalars(target *yaml.Node, lhs *yaml.Node, rhs *yaml.Node) error {
+func moduloScalars(target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error {
lhsTag := lhs.Tag
- rhsTag := guessTagFromCustomType(rhs)
+ rhsTag := rhs.guessTagFromCustomType()
lhsIsCustom := false
if !strings.HasPrefix(lhsTag, "!!") {
// custom tag - we have to have a guess
- lhsTag = guessTagFromCustomType(lhs)
+ lhsTag = lhs.guessTagFromCustomType()
lhsIsCustom = true
}
if lhsTag == "!!int" && rhsTag == "!!int" {
- target.Kind = yaml.ScalarNode
+ target.Kind = ScalarNode
target.Style = lhs.Style
format, lhsNum, err := parseInt64(lhs.Value)
@@ -68,7 +61,7 @@ func moduloScalars(target *yaml.Node, lhs *yaml.Node, rhs *yaml.Node) error {
target.Tag = lhs.Tag
target.Value = fmt.Sprintf(format, remainder)
} else if (lhsTag == "!!int" || lhsTag == "!!float") && (rhsTag == "!!int" || rhsTag == "!!float") {
- target.Kind = yaml.ScalarNode
+ target.Kind = ScalarNode
target.Style = lhs.Style
lhsNum, err := strconv.ParseFloat(lhs.Value, 64)
diff --git a/pkg/yqlib/operator_modulo_test.go b/pkg/yqlib/operator_modulo_test.go
index ee1c9101..246db233 100644
--- a/pkg/yqlib/operator_modulo_test.go
+++ b/pkg/yqlib/operator_modulo_test.go
@@ -19,7 +19,7 @@ var moduloOperatorScenarios = []expressionScenario{
document: `{}`,
expression: "(.a / .b) as $x | .",
expected: []string{
- "D0, P[], (doc)::{}\n",
+ "D0, P[], (!!map)::{}\n",
},
},
{
@@ -28,7 +28,7 @@ var moduloOperatorScenarios = []expressionScenario{
document: `{a: 13, b: 2}`,
expression: `.a = .a % .b`,
expected: []string{
- "D0, P[], (doc)::{a: 1, b: 2}\n",
+ "D0, P[], (!!map)::{a: 1, b: 2}\n",
},
},
{
@@ -37,7 +37,7 @@ var moduloOperatorScenarios = []expressionScenario{
document: `{a: 12, b: 2.5}`,
expression: `.a = .a % .b`,
expected: []string{
- "D0, P[], (doc)::{a: !!float 2, b: 2.5}\n",
+ "D0, P[], (!!map)::{a: !!float 2, b: 2.5}\n",
},
},
{
@@ -53,7 +53,7 @@ var moduloOperatorScenarios = []expressionScenario{
document: `{a: 1.1, b: 0}`,
expression: `.a = .a % .b`,
expected: []string{
- "D0, P[], (doc)::{a: !!float NaN, b: 0}\n",
+ "D0, P[], (!!map)::{a: !!float NaN, b: 0}\n",
},
},
{
@@ -62,7 +62,7 @@ var moduloOperatorScenarios = []expressionScenario{
document: "a: !horse 333.975\nb: !goat 299.2",
expression: `.a = .a % .b`,
expected: []string{
- "D0, P[], (doc)::a: !horse 34.775000000000034\nb: !goat 299.2\n",
+ "D0, P[], (!!map)::a: !horse 34.775000000000034\nb: !goat 299.2\n",
},
},
{
@@ -70,7 +70,7 @@ var moduloOperatorScenarios = []expressionScenario{
document: "a: 2\nb: !goat 2.3",
expression: `.a = .a % .b`,
expected: []string{
- "D0, P[], (doc)::a: !!float 2\nb: !goat 2.3\n",
+ "D0, P[], (!!map)::a: !!float 2\nb: !goat 2.3\n",
},
},
{
@@ -79,7 +79,7 @@ var moduloOperatorScenarios = []expressionScenario{
document: "a: &horse [1]",
expression: `.a[1] = .a[0] % 2`,
expected: []string{
- "D0, P[], (doc)::a: &horse [1, 1]\n",
+ "D0, P[], (!!map)::a: &horse [1, 1]\n",
},
},
{
diff --git a/pkg/yqlib/operator_multiply.go b/pkg/yqlib/operator_multiply.go
index cf638015..06b2429a 100644
--- a/pkg/yqlib/operator_multiply.go
+++ b/pkg/yqlib/operator_multiply.go
@@ -5,9 +5,6 @@ import (
"fmt"
"strconv"
"strings"
-
- "github.com/jinzhu/copier"
- yaml "gopkg.in/yaml.v3"
)
type multiplyPreferences struct {
@@ -38,16 +35,17 @@ func multiplyOperator(d *dataTreeNavigator, context Context, expressionNode *Exp
func getComments(lhs *CandidateNode, rhs *CandidateNode) (leadingContent string, headComment string, footComment string) {
leadingContent = rhs.LeadingContent
- headComment = rhs.Node.HeadComment
- footComment = rhs.Node.FootComment
- if lhs.Node.HeadComment != "" || lhs.LeadingContent != "" {
- headComment = lhs.Node.HeadComment
+ headComment = rhs.HeadComment
+ footComment = rhs.FootComment
+ if lhs.HeadComment != "" || lhs.LeadingContent != "" {
+ headComment = lhs.HeadComment
leadingContent = lhs.LeadingContent
}
- if lhs.Node.FootComment != "" {
- footComment = lhs.Node.FootComment
+ if lhs.FootComment != "" {
+ footComment = lhs.FootComment
}
+
return leadingContent, headComment, footComment
}
@@ -55,41 +53,37 @@ func multiply(preferences multiplyPreferences) func(d *dataTreeNavigator, contex
return func(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
// need to do this before unWrapping the potential document node
leadingContent, headComment, footComment := getComments(lhs, rhs)
- lhs.Node = unwrapDoc(lhs.Node)
- rhs.Node = unwrapDoc(rhs.Node)
- log.Debugf("Multiplying LHS: %v", lhs.Node.Tag)
- log.Debugf("- RHS: %v", rhs.Node.Tag)
+ log.Debugf("Multiplying LHS: %v", NodeToString(lhs))
+ log.Debugf("- RHS: %v", NodeToString(rhs))
- if rhs.Node.Tag == "!!null" {
- return lhs.Copy()
+ if rhs.Tag == "!!null" {
+ return lhs.Copy(), nil
}
- if (lhs.Node.Kind == yaml.MappingNode && rhs.Node.Kind == yaml.MappingNode) ||
- (lhs.Node.Tag == "!!null" && rhs.Node.Kind == yaml.MappingNode) ||
- (lhs.Node.Kind == yaml.SequenceNode && rhs.Node.Kind == yaml.SequenceNode) ||
- (lhs.Node.Tag == "!!null" && rhs.Node.Kind == yaml.SequenceNode) {
- var newBlank = CandidateNode{}
- err := copier.CopyWithOption(&newBlank, lhs, copier.Option{IgnoreEmpty: true, DeepCopy: true})
- if err != nil {
- return nil, err
- }
- newBlank.LeadingContent = leadingContent
- newBlank.Node.HeadComment = headComment
- newBlank.Node.FootComment = footComment
+ if (lhs.Kind == MappingNode && rhs.Kind == MappingNode) ||
+ (lhs.Tag == "!!null" && rhs.Kind == MappingNode) ||
+ (lhs.Kind == SequenceNode && rhs.Kind == SequenceNode) ||
+ (lhs.Tag == "!!null" && rhs.Kind == SequenceNode) {
- return mergeObjects(d, context.WritableClone(), &newBlank, rhs, preferences)
+ var newBlank = lhs.Copy()
+
+ newBlank.LeadingContent = leadingContent
+ newBlank.HeadComment = headComment
+ newBlank.FootComment = footComment
+
+ return mergeObjects(d, context.WritableClone(), newBlank, rhs, preferences)
}
return multiplyScalars(lhs, rhs)
}
}
func multiplyScalars(lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
- lhsTag := lhs.Node.Tag
- rhsTag := guessTagFromCustomType(rhs.Node)
+ lhsTag := lhs.Tag
+ rhsTag := rhs.guessTagFromCustomType()
lhsIsCustom := false
if !strings.HasPrefix(lhsTag, "!!") {
// custom tag - we have to have a guess
- lhsTag = guessTagFromCustomType(lhs.Node)
+ lhsTag = lhs.guessTagFromCustomType()
lhsIsCustom = true
}
@@ -98,46 +92,46 @@ func multiplyScalars(lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, er
} else if (lhsTag == "!!int" || lhsTag == "!!float") && (rhsTag == "!!int" || rhsTag == "!!float") {
return multiplyFloats(lhs, rhs, lhsIsCustom)
}
- return nil, fmt.Errorf("Cannot multiply %v with %v", lhs.Node.Tag, rhs.Node.Tag)
+ return nil, fmt.Errorf("cannot multiply %v with %v", lhs.Tag, rhs.Tag)
}
func multiplyFloats(lhs *CandidateNode, rhs *CandidateNode, lhsIsCustom bool) (*CandidateNode, error) {
- target := lhs.CreateReplacement(&yaml.Node{})
- target.Node.Kind = yaml.ScalarNode
- target.Node.Style = lhs.Node.Style
+ target := lhs.CopyWithoutContent()
+ target.Kind = ScalarNode
+ target.Style = lhs.Style
if lhsIsCustom {
- target.Node.Tag = lhs.Node.Tag
+ target.Tag = lhs.Tag
} else {
- target.Node.Tag = "!!float"
+ target.Tag = "!!float"
}
- lhsNum, err := strconv.ParseFloat(lhs.Node.Value, 64)
+ lhsNum, err := strconv.ParseFloat(lhs.Value, 64)
if err != nil {
return nil, err
}
- rhsNum, err := strconv.ParseFloat(rhs.Node.Value, 64)
+ rhsNum, err := strconv.ParseFloat(rhs.Value, 64)
if err != nil {
return nil, err
}
- target.Node.Value = fmt.Sprintf("%v", lhsNum*rhsNum)
+ target.Value = fmt.Sprintf("%v", lhsNum*rhsNum)
return target, nil
}
func multiplyIntegers(lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
- target := lhs.CreateReplacement(&yaml.Node{})
- target.Node.Kind = yaml.ScalarNode
- target.Node.Style = lhs.Node.Style
- target.Node.Tag = lhs.Node.Tag
+ target := lhs.CopyWithoutContent()
+ target.Kind = ScalarNode
+ target.Style = lhs.Style
+ target.Tag = lhs.Tag
- format, lhsNum, err := parseInt64(lhs.Node.Value)
+ format, lhsNum, err := parseInt64(lhs.Value)
if err != nil {
return nil, err
}
- _, rhsNum, err := parseInt64(rhs.Node.Value)
+ _, rhsNum, err := parseInt64(rhs.Value)
if err != nil {
return nil, err
}
- target.Node.Value = fmt.Sprintf(format, lhsNum*rhsNum)
+ target.Value = fmt.Sprintf(format, lhsNum*rhsNum)
return target, nil
}
@@ -156,12 +150,16 @@ func mergeObjects(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs
var pathIndexToStartFrom int
if results.Front() != nil {
- pathIndexToStartFrom = len(results.Front().Value.(*CandidateNode).Path)
+ pathIndexToStartFrom = len(results.Front().Value.(*CandidateNode).GetPath())
+ log.Debugf("pathIndexToStartFrom: %v", pathIndexToStartFrom)
}
for el := results.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- if candidate.Node.Tag == "!!merge" {
+
+ log.Debugf("*** going to applied assignment to LHS: %v with RHS: %v", NodeToString(lhs), NodeToString(candidate))
+
+ if candidate.Tag == "!!merge" {
continue
}
@@ -169,28 +167,29 @@ func mergeObjects(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs
if err != nil {
return nil, err
}
+
+ log.Debugf("*** applied assignment to LHS: %v", NodeToString(lhs))
}
return lhs, nil
}
func applyAssignment(d *dataTreeNavigator, context Context, pathIndexToStartFrom int, lhs *CandidateNode, rhs *CandidateNode, preferences multiplyPreferences) error {
shouldAppendArrays := preferences.AppendArrays
- log.Debugf("merge - applyAssignment lhs %v, rhs: %v", lhs.GetKey(), rhs.GetKey())
- lhsPath := rhs.Path[pathIndexToStartFrom:]
+ lhsPath := rhs.GetPath()[pathIndexToStartFrom:]
log.Debugf("merge - lhsPath %v", lhsPath)
assignmentOp := &Operation{OperationType: assignAttributesOpType, Preferences: preferences.AssignPrefs}
- if shouldAppendArrays && rhs.Node.Kind == yaml.SequenceNode {
+ if shouldAppendArrays && rhs.Kind == SequenceNode {
assignmentOp.OperationType = addAssignOpType
log.Debugf("merge - assignmentOp.OperationType = addAssignOpType")
- } else if !preferences.DeepMergeArrays && rhs.Node.Kind == yaml.SequenceNode ||
- (rhs.Node.Kind == yaml.ScalarNode || rhs.Node.Kind == yaml.AliasNode) {
+ } else if !preferences.DeepMergeArrays && rhs.Kind == SequenceNode ||
+ (rhs.Kind == ScalarNode || rhs.Kind == AliasNode) {
assignmentOp.OperationType = assignOpType
assignmentOp.UpdateAssign = false
- log.Debugf("merge - rhs.Node.Kind == yaml.SequenceNode: %v", rhs.Node.Kind == yaml.SequenceNode)
- log.Debugf("merge - rhs.Node.Kind == yaml.ScalarNode: %v", rhs.Node.Kind == yaml.ScalarNode)
- log.Debugf("merge - rhs.Node.Kind == yaml.AliasNode: %v", rhs.Node.Kind == yaml.AliasNode)
+ log.Debugf("merge - rhs.Kind == SequenceNode: %v", rhs.Kind == SequenceNode)
+ log.Debugf("merge - rhs.Kind == ScalarNode: %v", rhs.Kind == ScalarNode)
+ log.Debugf("merge - rhs.Kind == AliasNode: %v", rhs.Kind == AliasNode)
log.Debugf("merge - assignmentOp.OperationType = assignOpType, no updateassign")
} else {
log.Debugf("merge - assignmentOp := &Operation{OperationType: assignAttributesOpType}")
diff --git a/pkg/yqlib/operator_multiply_test.go b/pkg/yqlib/operator_multiply_test.go
index 0844c7c7..c099ddb0 100644
--- a/pkg/yqlib/operator_multiply_test.go
+++ b/pkg/yqlib/operator_multiply_test.go
@@ -171,7 +171,7 @@ var multiplyOperatorScenarios = []expressionScenario{
document: "a: 3\nb: 4",
expression: `.a *= .b`,
expected: []string{
- "D0, P[], (doc)::a: 12\nb: 4\n",
+ "D0, P[], (!!map)::a: 12\nb: 4\n",
},
},
{
@@ -435,7 +435,7 @@ var multiplyOperatorScenarios = []expressionScenario{
environmentVariables: map[string]string{"originalPath": ".myArray", "otherPath": ".newArray", "idPath": ".a"},
expression: mergeExpression,
expected: []string{
- "D0, P[], (doc)::{myArray: [{a: apple, b: appleB2}, {a: kiwi, b: kiwiB}, {a: banana, b: bananaB, c: bananaC}, {a: dingo, c: dingoC}], something: else}\n",
+ "D0, P[], (!!map)::{myArray: [{a: apple, b: appleB2}, {a: kiwi, b: kiwiB}, {a: banana, b: bananaB, c: bananaC}, {a: dingo, c: dingoC}], something: else}\n",
},
},
{
@@ -484,7 +484,7 @@ var multiplyOperatorScenarios = []expressionScenario{
document: "a: !horse 2\nb: !goat 3",
expression: ".a = .a * .b",
expected: []string{
- "D0, P[], (doc)::a: !horse 6\nb: !goat 3\n",
+ "D0, P[], (!!map)::a: !horse 6\nb: !goat 3\n",
},
},
{
@@ -493,7 +493,7 @@ var multiplyOperatorScenarios = []expressionScenario{
document: "a: !horse 2.5\nb: !goat 3.5",
expression: ".a = .a * .b",
expected: []string{
- "D0, P[], (doc)::a: !horse 8.75\nb: !goat 3.5\n",
+ "D0, P[], (!!map)::a: !horse 8.75\nb: !goat 3.5\n",
},
},
{
@@ -502,7 +502,7 @@ var multiplyOperatorScenarios = []expressionScenario{
document: "a: 2\nb: !goat 3.5",
expression: ".a = .a * .b",
expected: []string{
- "D0, P[], (doc)::a: !!float 7\nb: !goat 3.5\n",
+ "D0, P[], (!!map)::a: !!float 7\nb: !goat 3.5\n",
},
},
{
@@ -511,7 +511,7 @@ var multiplyOperatorScenarios = []expressionScenario{
document: "a: !horse [1,2]\nb: !goat [3]",
expression: ".a = .a * .b",
expected: []string{
- "D0, P[], (doc)::a: !horse [3]\nb: !goat [3]\n",
+ "D0, P[], (!!map)::a: !horse [3]\nb: !goat [3]\n",
},
},
{
@@ -520,7 +520,7 @@ var multiplyOperatorScenarios = []expressionScenario{
document: "a: !horse {cat: meow}\nb: !goat {dog: woof}",
expression: ".a = .a * .b",
expected: []string{
- "D0, P[], (doc)::a: !horse {cat: meow, dog: woof}\nb: !goat {dog: woof}\n",
+ "D0, P[], (!!map)::a: !horse {cat: meow, dog: woof}\nb: !goat {dog: woof}\n",
},
},
{
@@ -529,7 +529,7 @@ var multiplyOperatorScenarios = []expressionScenario{
document: "a: !horse {cat: meow}\nb: !goat {dog: woof}",
expression: ".a *=c .b",
expected: []string{
- "D0, P[], (doc)::a: !goat {cat: meow, dog: woof}\nb: !goat {dog: woof}\n",
+ "D0, P[], (!!map)::a: !goat {cat: meow, dog: woof}\nb: !goat {dog: woof}\n",
},
},
{
@@ -539,7 +539,7 @@ var multiplyOperatorScenarios = []expressionScenario{
document: "a: !horse {cat: meow}\nb: !goat {dog: woof}",
expression: ".a =c .a *c .b",
expected: []string{
- "D0, P[], (doc)::a: !goat {cat: meow, dog: woof}\nb: !goat {dog: woof}\n",
+ "D0, P[], (!!map)::a: !goat {cat: meow, dog: woof}\nb: !goat {dog: woof}\n",
},
},
{
@@ -549,7 +549,7 @@ var multiplyOperatorScenarios = []expressionScenario{
document: "a: !horse {cat: meow}\nb: !goat {dog: woof}",
expression: ".a *= .b",
expected: []string{
- "D0, P[], (doc)::a: !horse {cat: meow, dog: woof}\nb: !goat {dog: woof}\n",
+ "D0, P[], (!!map)::a: !horse {cat: meow, dog: woof}\nb: !goat {dog: woof}\n",
},
},
{
@@ -558,7 +558,7 @@ var multiplyOperatorScenarios = []expressionScenario{
document: "a: {cat: !horse meow}\nb: {cat: 5}",
expression: ".a = .a * .b",
expected: []string{
- "D0, P[], (doc)::a: {cat: !horse 5}\nb: {cat: 5}\n",
+ "D0, P[], (!!map)::a: {cat: !horse 5}\nb: {cat: 5}\n",
},
},
{
@@ -567,7 +567,7 @@ var multiplyOperatorScenarios = []expressionScenario{
document: "a: {a: original}\n",
expression: `.a *=n load("../../examples/thing.yml")`,
expected: []string{
- "D0, P[], (doc)::a: {a: original, b: cool.}\n",
+ "D0, P[], (!!map)::a: {a: original, b: cool.}\n",
},
},
{
@@ -576,7 +576,7 @@ var multiplyOperatorScenarios = []expressionScenario{
document: "a: {a: original}\n",
expression: `.a *= load("../../examples/thing.yml")`,
expected: []string{
- "D0, P[], (doc)::a: {a: apple is included, b: cool.}\n",
+ "D0, P[], (!!map)::a: {a: apple is included, b: cool.}\n",
},
},
{
diff --git a/pkg/yqlib/operator_path.go b/pkg/yqlib/operator_path.go
index cdad7f1b..88a97fee 100644
--- a/pkg/yqlib/operator_path.go
+++ b/pkg/yqlib/operator_path.go
@@ -3,21 +3,19 @@ package yqlib
import (
"container/list"
"fmt"
-
- yaml "gopkg.in/yaml.v3"
)
-func createPathNodeFor(pathElement interface{}) *yaml.Node {
+func createPathNodeFor(pathElement interface{}) *CandidateNode {
switch pathElement := pathElement.(type) {
case string:
- return &yaml.Node{Kind: yaml.ScalarNode, Value: pathElement, Tag: "!!str"}
+ return &CandidateNode{Kind: ScalarNode, Value: pathElement, Tag: "!!str"}
default:
- return &yaml.Node{Kind: yaml.ScalarNode, Value: fmt.Sprintf("%v", pathElement), Tag: "!!int"}
+ return &CandidateNode{Kind: ScalarNode, Value: fmt.Sprintf("%v", pathElement), Tag: "!!int"}
}
}
-func getPathArrayFromNode(funcName string, node *yaml.Node) ([]interface{}, error) {
- if node.Kind != yaml.SequenceNode {
+func getPathArrayFromNode(funcName string, node *CandidateNode) ([]interface{}, error) {
+ if node.Kind != SequenceNode {
return nil, fmt.Errorf("%v: expected path array, but got %v instead", funcName, node.Tag)
}
@@ -59,7 +57,7 @@ func setPathOperator(d *dataTreeNavigator, context Context, expressionNode *Expr
}
lhsValue := lhsPathContext.MatchingNodes.Front().Value.(*CandidateNode)
- lhsPath, err := getPathArrayFromNode("SETPATH", lhsValue.Node)
+ lhsPath, err := getPathArrayFromNode("SETPATH", lhsValue)
if err != nil {
return Context{}, err
@@ -110,7 +108,7 @@ func delPathsOperator(d *dataTreeNavigator, context Context, expressionNode *Exp
if pathArraysContext.MatchingNodes.Len() != 1 {
return Context{}, fmt.Errorf("DELPATHS: expected single value but found %v", pathArraysContext.MatchingNodes.Len())
}
- pathArraysNode := pathArraysContext.MatchingNodes.Front().Value.(*CandidateNode).Node
+ pathArraysNode := pathArraysContext.MatchingNodes.Front().Value.(*CandidateNode)
if pathArraysNode.Tag != "!!seq" {
return Context{}, fmt.Errorf("DELPATHS: expected a sequence of sequences, but found %v", pathArraysNode.Tag)
@@ -156,16 +154,17 @@ func getPathOperator(d *dataTreeNavigator, context Context, expressionNode *Expr
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- node := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
+ node := candidate.CreateReplacement(SequenceNode, "!!seq", "")
- content := make([]*yaml.Node, len(candidate.Path))
- for pathIndex := 0; pathIndex < len(candidate.Path); pathIndex++ {
- path := candidate.Path[pathIndex]
+ path := candidate.GetPath()
+
+ content := make([]*CandidateNode, len(path))
+ for pathIndex := 0; pathIndex < len(path); pathIndex++ {
+ path := path[pathIndex]
content[pathIndex] = createPathNodeFor(path)
}
- node.Content = content
- result := candidate.CreateReplacement(node)
- results.PushBack(result)
+ node.AddChildren(content)
+ results.PushBack(node)
}
return context.ChildContext(results), nil
diff --git a/pkg/yqlib/operator_path_test.go b/pkg/yqlib/operator_path_test.go
index 225d9ac4..bb575aac 100644
--- a/pkg/yqlib/operator_path_test.go
+++ b/pkg/yqlib/operator_path_test.go
@@ -45,7 +45,7 @@ var pathOperatorScenarios = []expressionScenario{
document: `{a: {b: cat}}`,
expression: `.a.b | path | .[-1]`,
expected: []string{
- "D0, P[a b -1], (!!str)::b\n",
+ "D0, P[a b 1], (!!str)::b\n",
},
},
{
@@ -61,7 +61,7 @@ var pathOperatorScenarios = []expressionScenario{
document: `{a: [cat, dog]}`,
expression: `.a.[] | select(. == "dog") | path | .[-1]`,
expected: []string{
- "D0, P[a 1 -1], (!!int)::1\n",
+ "D0, P[a 1 1], (!!int)::1\n",
},
},
{
@@ -78,7 +78,7 @@ var pathOperatorScenarios = []expressionScenario{
document: `{a: {b: cat}}`,
expression: `setpath(["a", "b"]; "things")`,
expected: []string{
- "D0, P[], (doc)::{a: {b: things}}\n",
+ "D0, P[], (!!map)::{a: {b: things}}\n",
},
},
{
@@ -102,7 +102,7 @@ var pathOperatorScenarios = []expressionScenario{
document: `a: [cat, frog]`,
expression: `setpath(["a", 0]; "things")`,
expected: []string{
- "D0, P[], (doc)::a: [things, frog]\n",
+ "D0, P[], (!!map)::a: [things, frog]\n",
},
},
{
@@ -118,7 +118,7 @@ var pathOperatorScenarios = []expressionScenario{
document: `{a: {b: cat, c: dog, d: frog}}`,
expression: `delpaths([["a", "c"], ["a", "d"]])`,
expected: []string{
- "D0, P[], (doc)::{a: {b: cat}}\n",
+ "D0, P[], (!!map)::{a: {b: cat}}\n",
},
},
{
@@ -126,7 +126,7 @@ var pathOperatorScenarios = []expressionScenario{
document: `a: [cat, frog]`,
expression: `delpaths([["a", 0]])`,
expected: []string{
- "D0, P[], (doc)::a: [frog]\n",
+ "D0, P[], (!!map)::a: [frog]\n",
},
},
{
diff --git a/pkg/yqlib/operator_pick.go b/pkg/yqlib/operator_pick.go
index 5a6f7d2c..2e223ea0 100644
--- a/pkg/yqlib/operator_pick.go
+++ b/pkg/yqlib/operator_pick.go
@@ -3,33 +3,31 @@ package yqlib
import (
"container/list"
"fmt"
-
- yaml "gopkg.in/yaml.v3"
)
-func pickMap(original *yaml.Node, indices *yaml.Node) *yaml.Node {
+func pickMap(original *CandidateNode, indices *CandidateNode) *CandidateNode {
- filteredContent := make([]*yaml.Node, 0)
+ filteredContent := make([]*CandidateNode, 0)
for index := 0; index < len(indices.Content); index = index + 1 {
keyToFind := indices.Content[index]
indexInMap := findKeyInMap(original, keyToFind)
if indexInMap > -1 {
- clonedKey := deepClone(original.Content[indexInMap])
- clonedValue := deepClone(original.Content[indexInMap+1])
+ clonedKey := original.Content[indexInMap].Copy()
+ clonedValue := original.Content[indexInMap+1].Copy()
filteredContent = append(filteredContent, clonedKey, clonedValue)
}
}
- newNode := deepCloneNoContent(original)
- newNode.Content = filteredContent
+ newNode := original.CopyWithoutContent()
+ newNode.AddChildren(filteredContent)
return newNode
}
-func pickSequence(original *yaml.Node, indices *yaml.Node) (*yaml.Node, error) {
+func pickSequence(original *CandidateNode, indices *CandidateNode) (*CandidateNode, error) {
- filteredContent := make([]*yaml.Node, 0)
+ filteredContent := make([]*CandidateNode, 0)
for index := 0; index < len(indices.Content); index = index + 1 {
indexInArray, err := parseInt(indices.Content[index].Value)
if err != nil {
@@ -37,12 +35,12 @@ func pickSequence(original *yaml.Node, indices *yaml.Node) (*yaml.Node, error) {
}
if indexInArray > -1 && indexInArray < len(original.Content) {
- filteredContent = append(filteredContent, deepClone(original.Content[indexInArray]))
+ filteredContent = append(filteredContent, original.Content[indexInArray].Copy())
}
}
- newNode := deepCloneNoContent(original)
- newNode.Content = filteredContent
+ newNode := original.CopyWithoutContent()
+ newNode.AddChildren(filteredContent)
return newNode, nil
}
@@ -55,31 +53,31 @@ func pickOperator(d *dataTreeNavigator, context Context, expressionNode *Express
if err != nil {
return Context{}, err
}
- indicesToPick := &yaml.Node{}
+ indicesToPick := &CandidateNode{}
if contextIndicesToPick.MatchingNodes.Len() > 0 {
- indicesToPick = contextIndicesToPick.MatchingNodes.Front().Value.(*CandidateNode).Node
+ indicesToPick = contextIndicesToPick.MatchingNodes.Front().Value.(*CandidateNode)
}
var results = list.New()
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
- candidate := el.Value.(*CandidateNode)
- node := unwrapDoc(candidate.Node)
+ node := el.Value.(*CandidateNode)
- var replacement *yaml.Node
- if node.Kind == yaml.MappingNode {
+ var replacement *CandidateNode
+ if node.Kind == MappingNode {
replacement = pickMap(node, indicesToPick)
- } else if node.Kind == yaml.SequenceNode {
+ } else if node.Kind == SequenceNode {
replacement, err = pickSequence(node, indicesToPick)
if err != nil {
return Context{}, err
}
} else {
- return Context{}, fmt.Errorf("cannot pick indices from type %v (%v)", node.Tag, candidate.GetNicePath())
+ return Context{}, fmt.Errorf("cannot pick indices from type %v (%v)", node.Tag, node.GetNicePath())
}
- results.PushBack(candidate.CreateReplacementWithDocWrappers(replacement))
+ replacement.LeadingContent = node.LeadingContent
+ results.PushBack(replacement)
}
return context.ChildContext(results), nil
diff --git a/pkg/yqlib/operator_pick_test.go b/pkg/yqlib/operator_pick_test.go
index fe92f3ad..44565602 100644
--- a/pkg/yqlib/operator_pick_test.go
+++ b/pkg/yqlib/operator_pick_test.go
@@ -11,7 +11,7 @@ var pickOperatorScenarios = []expressionScenario{
document: "myMap: {cat: meow, dog: bark, thing: hamster, hamster: squeak}\n",
expression: `.myMap |= pick(["hamster", "cat", "goat"])`,
expected: []string{
- "D0, P[], (doc)::myMap: {hamster: squeak, cat: meow}\n",
+ "D0, P[], (!!map)::myMap: {hamster: squeak, cat: meow}\n",
},
},
{
@@ -20,7 +20,7 @@ var pickOperatorScenarios = []expressionScenario{
document: "!things myMap: {cat: meow, dog: bark, thing: hamster, hamster: squeak}\n",
expression: `.myMap |= pick(["hamster", "cat", "goat"])`,
expected: []string{
- "D0, P[], (doc)::!things myMap: {hamster: squeak, cat: meow}\n",
+ "D0, P[], (!!map)::!things myMap: {hamster: squeak, cat: meow}\n",
},
},
{
@@ -29,7 +29,7 @@ var pickOperatorScenarios = []expressionScenario{
document: "# abc\nmyMap: {cat: meow, dog: bark, thing: hamster, hamster: squeak}\n# xyz\n",
expression: `.myMap |= pick(["hamster", "cat", "goat"])`,
expected: []string{
- "D0, P[], (doc)::# abc\nmyMap: {hamster: squeak, cat: meow}\n# xyz\n",
+ "D0, P[], (!!map)::# abc\nmyMap: {hamster: squeak, cat: meow}\n# xyz\n",
},
},
{
diff --git a/pkg/yqlib/operator_pipe_test.go b/pkg/yqlib/operator_pipe_test.go
index 8d884689..6196d658 100644
--- a/pkg/yqlib/operator_pipe_test.go
+++ b/pkg/yqlib/operator_pipe_test.go
@@ -18,7 +18,7 @@ var pipeOperatorScenarios = []expressionScenario{
document: `{a: cow, b: sheep, c: same}`,
expression: `.a = "cat" | .b = "dog"`,
expected: []string{
- "D0, P[], (doc)::{a: cat, b: dog, c: same}\n",
+ "D0, P[], (!!map)::{a: cat, b: dog, c: same}\n",
},
},
{
diff --git a/pkg/yqlib/operator_recursive_descent.go b/pkg/yqlib/operator_recursive_descent.go
index bb583840..775bd2a6 100644
--- a/pkg/yqlib/operator_recursive_descent.go
+++ b/pkg/yqlib/operator_recursive_descent.go
@@ -2,8 +2,6 @@ package yqlib
import (
"container/list"
-
- yaml "gopkg.in/yaml.v3"
)
type recursiveDescentPreferences struct {
@@ -27,13 +25,11 @@ func recursiveDecent(results *list.List, context Context, preferences recursiveD
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- candidate.Node = unwrapDoc(candidate.Node)
-
log.Debugf("Recursive Decent, added %v", NodeToString(candidate))
results.PushBack(candidate)
- if candidate.Node.Kind != yaml.AliasNode && len(candidate.Node.Content) > 0 &&
- (preferences.RecurseArray || candidate.Node.Kind != yaml.SequenceNode) {
+ if candidate.Kind != AliasNode && len(candidate.Content) > 0 &&
+ (preferences.RecurseArray || candidate.Kind != SequenceNode) {
children, err := splat(context.SingleChildContext(candidate), preferences.TraversePreferences)
diff --git a/pkg/yqlib/operator_reverse.go b/pkg/yqlib/operator_reverse.go
index 1693308f..ef2e0a45 100644
--- a/pkg/yqlib/operator_reverse.go
+++ b/pkg/yqlib/operator_reverse.go
@@ -3,8 +3,6 @@ package yqlib
import (
"container/list"
"fmt"
-
- yaml "gopkg.in/yaml.v3"
)
func reverseOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@@ -13,19 +11,18 @@ func reverseOperator(d *dataTreeNavigator, context Context, expressionNode *Expr
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- candidateNode := unwrapDoc(candidate.Node)
-
- if candidateNode.Kind != yaml.SequenceNode {
- return context, fmt.Errorf("node at path [%v] is not an array (it's a %v)", candidate.GetNicePath(), candidate.GetNiceTag())
+ if candidate.Kind != SequenceNode {
+ return context, fmt.Errorf("node at path [%v] is not an array (it's a %v)", candidate.GetNicePath(), candidate.Tag)
}
- reverseList := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq", Style: candidateNode.Style}
- reverseList.Content = make([]*yaml.Node, len(candidateNode.Content))
+ reverseList := candidate.CreateReplacementWithComments(SequenceNode, "!!seq", candidate.Style)
+ reverseContent := make([]*CandidateNode, len(candidate.Content))
- for i, originalNode := range candidateNode.Content {
- reverseList.Content[len(candidateNode.Content)-i-1] = originalNode
+ for i, originalNode := range candidate.Content {
+ reverseContent[len(candidate.Content)-i-1] = originalNode
}
- results.PushBack(candidate.CreateReplacementWithDocWrappers(reverseList))
+ reverseList.AddChildren(reverseContent)
+ results.PushBack(reverseList)
}
diff --git a/pkg/yqlib/operator_select.go b/pkg/yqlib/operator_select.go
index 57b9e2ce..7cdb64b6 100644
--- a/pkg/yqlib/operator_select.go
+++ b/pkg/yqlib/operator_select.go
@@ -18,16 +18,11 @@ func selectOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
}
// find any truthy node
- var errDecoding error
includeResult := false
for resultEl := rhs.MatchingNodes.Front(); resultEl != nil; resultEl = resultEl.Next() {
result := resultEl.Value.(*CandidateNode)
- includeResult, errDecoding = isTruthy(result)
- log.Debugf("isTruthy %v", includeResult)
- if errDecoding != nil {
- return Context{}, errDecoding
- }
+ includeResult = isTruthyNode(result)
if includeResult {
break
}
diff --git a/pkg/yqlib/operator_select_test.go b/pkg/yqlib/operator_select_test.go
index 02357c2e..249e54b4 100644
--- a/pkg/yqlib/operator_select_test.go
+++ b/pkg/yqlib/operator_select_test.go
@@ -10,7 +10,7 @@ var selectOperatorScenarios = []expressionScenario{
document: `cat`,
expression: `select(false, true)`,
expected: []string{
- "D0, P[], (doc)::cat\n",
+ "D0, P[], (!!str)::cat\n",
},
},
{
@@ -18,7 +18,7 @@ var selectOperatorScenarios = []expressionScenario{
document: `cat`,
expression: `select(true, false)`,
expected: []string{
- "D0, P[], (doc)::cat\n",
+ "D0, P[], (!!str)::cat\n",
},
},
{
@@ -71,8 +71,8 @@ var selectOperatorScenarios = []expressionScenario{
document2: "b: world",
expression: `select(.a == "hello" or .b == "world")`,
expected: []string{
- "D0, P[], (doc)::a: hello\n",
- "D0, P[], (doc)::b: world\n",
+ "D0, P[], (!!map)::a: hello\n",
+ "D0, P[], (!!map)::b: world\n",
},
},
{
@@ -81,7 +81,7 @@ var selectOperatorScenarios = []expressionScenario{
document: `[{animal: cat, legs: {cool: true}}, {animal: fish}]`,
expression: `(.[] | select(.legs.cool == true).canWalk) = true | (.[] | .alive.things) = "yes"`,
expected: []string{
- "D0, P[], (doc)::[{animal: cat, legs: {cool: true}, canWalk: true, alive: {things: yes}}, {animal: fish, alive: {things: yes}}]\n",
+ "D0, P[], (!!seq)::[{animal: cat, legs: {cool: true}, canWalk: true, alive: {things: yes}}, {animal: fish, alive: {things: yes}}]\n",
},
},
{
@@ -121,7 +121,7 @@ var selectOperatorScenarios = []expressionScenario{
document: `a: { things: cat, bob: goat, horse: dog }`,
expression: `(.a.[] | select(. == "cat" or . == "goat")) |= "rabbit"`,
expected: []string{
- "D0, P[], (doc)::a: {things: rabbit, bob: rabbit, horse: dog}\n",
+ "D0, P[], (!!map)::a: {things: rabbit, bob: rabbit, horse: dog}\n",
},
},
{
diff --git a/pkg/yqlib/operator_shuffle.go b/pkg/yqlib/operator_shuffle.go
index 73a76965..15308728 100644
--- a/pkg/yqlib/operator_shuffle.go
+++ b/pkg/yqlib/operator_shuffle.go
@@ -4,8 +4,6 @@ import (
"container/list"
"fmt"
"math/rand"
-
- yaml "gopkg.in/yaml.v3"
)
func shuffleOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@@ -20,18 +18,17 @@ func shuffleOperator(d *dataTreeNavigator, context Context, expressionNode *Expr
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- candidateNode := unwrapDoc(candidate.Node)
-
- if candidateNode.Kind != yaml.SequenceNode {
- return context, fmt.Errorf("node at path [%v] is not an array (it's a %v)", candidate.GetNicePath(), candidate.GetNiceTag())
+ if candidate.Kind != SequenceNode {
+ return context, fmt.Errorf("node at path [%v] is not an array (it's a %v)", candidate.GetNicePath(), candidate.Tag)
}
- result := deepClone(candidateNode)
+ result := candidate.Copy()
a := result.Content
myRand.Shuffle(len(a), func(i, j int) { a[i], a[j] = a[j], a[i] })
- results.PushBack(candidate.CreateReplacement(result))
+
+ results.PushBack(result)
}
return context.ChildContext(results), nil
}
diff --git a/pkg/yqlib/operator_shuffle_test.go b/pkg/yqlib/operator_shuffle_test.go
index 23a3748b..c6c30f5f 100644
--- a/pkg/yqlib/operator_shuffle_test.go
+++ b/pkg/yqlib/operator_shuffle_test.go
@@ -17,7 +17,7 @@ var shuffleOperatorScenarios = []expressionScenario{
document: "cool: [1, 2, 3, 4, 5]",
expression: `.cool |= shuffle`,
expected: []string{
- "D0, P[], (doc)::cool: [5, 2, 4, 1, 3]\n",
+ "D0, P[], (!!map)::cool: [5, 2, 4, 1, 3]\n",
},
},
}
diff --git a/pkg/yqlib/operator_slice.go b/pkg/yqlib/operator_slice.go
index e496cf93..e4c3906c 100644
--- a/pkg/yqlib/operator_slice.go
+++ b/pkg/yqlib/operator_slice.go
@@ -3,8 +3,6 @@ package yqlib
import (
"container/list"
"fmt"
-
- yaml "gopkg.in/yaml.v3"
)
func getSliceNumber(d *dataTreeNavigator, context Context, node *CandidateNode, expressionNode *ExpressionNode) (int, error) {
@@ -15,7 +13,7 @@ func getSliceNumber(d *dataTreeNavigator, context Context, node *CandidateNode,
if result.MatchingNodes.Len() != 1 {
return 0, fmt.Errorf("expected to find 1 number, got %v instead", result.MatchingNodes.Len())
}
- return parseInt(result.MatchingNodes.Front().Value.(*CandidateNode).Node.Value)
+ return parseInt(result.MatchingNodes.Front().Value.(*CandidateNode).Value)
}
func sliceArrayOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@@ -28,7 +26,6 @@ func sliceArrayOperator(d *dataTreeNavigator, context Context, expressionNode *E
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
lhsNode := el.Value.(*CandidateNode)
- original := unwrapDoc(lhsNode.Node)
firstNumber, err := getSliceNumber(d, context, lhsNode, expressionNode.LHS)
@@ -37,7 +34,7 @@ func sliceArrayOperator(d *dataTreeNavigator, context Context, expressionNode *E
}
relativeFirstNumber := firstNumber
if relativeFirstNumber < 0 {
- relativeFirstNumber = len(original.Content) + firstNumber
+ relativeFirstNumber = len(lhsNode.Content) + firstNumber
}
secondNumber, err := getSliceNumber(d, context, lhsNode, expressionNode.RHS)
@@ -47,24 +44,21 @@ func sliceArrayOperator(d *dataTreeNavigator, context Context, expressionNode *E
relativeSecondNumber := secondNumber
if relativeSecondNumber < 0 {
- relativeSecondNumber = len(original.Content) + secondNumber
- } else if relativeSecondNumber > len(original.Content) {
- relativeSecondNumber = len(original.Content)
+ relativeSecondNumber = len(lhsNode.Content) + secondNumber
+ } else if relativeSecondNumber > len(lhsNode.Content) {
+ relativeSecondNumber = len(lhsNode.Content)
}
log.Debug("calculateIndicesToTraverse: slice from %v to %v", relativeFirstNumber, relativeSecondNumber)
- var newResults []*yaml.Node
+ var newResults []*CandidateNode
for i := relativeFirstNumber; i < relativeSecondNumber; i++ {
- newResults = append(newResults, original.Content[i])
+ newResults = append(newResults, lhsNode.Content[i])
}
- slicedArrayNode := &yaml.Node{
- Kind: yaml.SequenceNode,
- Tag: original.Tag,
- Content: newResults,
- }
- results.PushBack(lhsNode.CreateReplacement(slicedArrayNode))
+ sliceArrayNode := lhsNode.CreateReplacement(SequenceNode, lhsNode.Tag, "")
+ sliceArrayNode.AddChildren(newResults)
+ results.PushBack(sliceArrayNode)
}
diff --git a/pkg/yqlib/operator_sort.go b/pkg/yqlib/operator_sort.go
index 01070f2d..106b17ff 100644
--- a/pkg/yqlib/operator_sort.go
+++ b/pkg/yqlib/operator_sort.go
@@ -7,8 +7,6 @@ import (
"strconv"
"strings"
"time"
-
- yaml "gopkg.in/yaml.v3"
)
func sortOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@@ -26,18 +24,15 @@ func sortByOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- candidateNode := unwrapDoc(candidate.Node)
-
- if candidateNode.Kind != yaml.SequenceNode {
- return context, fmt.Errorf("node at path [%v] is not an array (it's a %v)", candidate.GetNicePath(), candidate.GetNiceTag())
+ if candidate.Kind != SequenceNode {
+ return context, fmt.Errorf("node at path [%v] is not an array (it's a %v)", candidate.GetNicePath(), candidate.Tag)
}
- sortableArray := make(sortableNodeArray, len(candidateNode.Content))
+ sortableArray := make(sortableNodeArray, len(candidate.Content))
- for i, originalNode := range candidateNode.Content {
+ for i, originalNode := range candidate.Content {
- childCandidate := candidate.CreateChildInArray(i, originalNode)
- compareContext, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(childCandidate), expressionNode.RHS)
+ compareContext, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(originalNode), expressionNode.RHS)
if err != nil {
return Context{}, err
}
@@ -48,19 +43,18 @@ func sortByOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
sort.Stable(sortableArray)
- sortedList := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq", Style: candidateNode.Style}
- sortedList.Content = make([]*yaml.Node, len(candidateNode.Content))
+ sortedList := candidate.CreateReplacementWithComments(SequenceNode, "!!seq", candidate.Style)
- for i, sortedNode := range sortableArray {
- sortedList.Content[i] = sortedNode.Node
+ for _, sortedNode := range sortableArray {
+ sortedList.AddChild(sortedNode.Node)
}
- results.PushBack(candidate.CreateReplacementWithDocWrappers(sortedList))
+ results.PushBack(sortedList)
}
return context.ChildContext(results), nil
}
type sortableNode struct {
- Node *yaml.Node
+ Node *CandidateNode
CompareContext Context
dateTimeLayout string
}
@@ -79,7 +73,7 @@ func (a sortableNodeArray) Less(i, j int) bool {
lhs := lhsEl.Value.(*CandidateNode)
rhs := rhsEl.Value.(*CandidateNode)
- result := a.compare(lhs.Node, rhs.Node, a[i].dateTimeLayout)
+ result := a.compare(lhs, rhs, a[i].dateTimeLayout)
if result < 0 {
return true
@@ -92,18 +86,18 @@ func (a sortableNodeArray) Less(i, j int) bool {
return false
}
-func (a sortableNodeArray) compare(lhs *yaml.Node, rhs *yaml.Node, dateTimeLayout string) int {
+func (a sortableNodeArray) compare(lhs *CandidateNode, rhs *CandidateNode, dateTimeLayout string) int {
lhsTag := lhs.Tag
rhsTag := rhs.Tag
if !strings.HasPrefix(lhsTag, "!!") {
// custom tag - we have to have a guess
- lhsTag = guessTagFromCustomType(lhs)
+ lhsTag = lhs.guessTagFromCustomType()
}
if !strings.HasPrefix(rhsTag, "!!") {
// custom tag - we have to have a guess
- rhsTag = guessTagFromCustomType(rhs)
+ rhsTag = rhs.guessTagFromCustomType()
}
isDateTime := lhsTag == "!!timestamp" && rhsTag == "!!timestamp"
@@ -124,15 +118,9 @@ func (a sortableNodeArray) compare(lhs *yaml.Node, rhs *yaml.Node, dateTimeLayou
} else if lhsTag != "!!bool" && rhsTag == "!!bool" {
return 1
} else if lhsTag == "!!bool" && rhsTag == "!!bool" {
- lhsTruthy, err := isTruthyNode(lhs)
- if err != nil {
- panic(fmt.Errorf("could not parse %v as boolean: %w", lhs.Value, err))
- }
+ lhsTruthy := isTruthyNode(lhs)
- rhsTruthy, err := isTruthyNode(rhs)
- if err != nil {
- panic(fmt.Errorf("could not parse %v as boolean: %w", rhs.Value, err))
- }
+ rhsTruthy := isTruthyNode(rhs)
if lhsTruthy == rhsTruthy {
return 0
} else if lhsTruthy {
diff --git a/pkg/yqlib/operator_sort_keys.go b/pkg/yqlib/operator_sort_keys.go
index 0ab1a3cb..c10da11e 100644
--- a/pkg/yqlib/operator_sort_keys.go
+++ b/pkg/yqlib/operator_sort_keys.go
@@ -2,8 +2,6 @@ package yqlib
import (
"sort"
-
- yaml "gopkg.in/yaml.v3"
)
func sortKeysOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@@ -16,8 +14,8 @@ func sortKeysOperator(d *dataTreeNavigator, context Context, expressionNode *Exp
}
for childEl := rhs.MatchingNodes.Front(); childEl != nil; childEl = childEl.Next() {
- node := unwrapDoc(childEl.Value.(*CandidateNode).Node)
- if node.Kind == yaml.MappingNode {
+ node := childEl.Value.(*CandidateNode)
+ if node.Kind == MappingNode {
sortKeys(node)
}
if err != nil {
@@ -29,10 +27,10 @@ func sortKeysOperator(d *dataTreeNavigator, context Context, expressionNode *Exp
return context, nil
}
-func sortKeys(node *yaml.Node) {
+func sortKeys(node *CandidateNode) {
keys := make([]string, len(node.Content)/2)
- keyBucket := map[string]*yaml.Node{}
- valueBucket := map[string]*yaml.Node{}
+ keyBucket := map[string]*CandidateNode{}
+ valueBucket := map[string]*CandidateNode{}
var contents = node.Content
for index := 0; index < len(contents); index = index + 2 {
key := contents[index]
@@ -42,11 +40,14 @@ func sortKeys(node *yaml.Node) {
valueBucket[key.Value] = value
}
sort.Strings(keys)
- sortedContent := make([]*yaml.Node, len(node.Content))
+ sortedContent := make([]*CandidateNode, len(node.Content))
for index := 0; index < len(keys); index = index + 1 {
keyString := keys[index]
sortedContent[index*2] = keyBucket[keyString]
sortedContent[1+(index*2)] = valueBucket[keyString]
}
+
+ // re-arranging children, no need to update their parent
+ // relationship
node.Content = sortedContent
}
diff --git a/pkg/yqlib/operator_sort_keys_test.go b/pkg/yqlib/operator_sort_keys_test.go
index 8d421556..586a1ce8 100644
--- a/pkg/yqlib/operator_sort_keys_test.go
+++ b/pkg/yqlib/operator_sort_keys_test.go
@@ -10,7 +10,7 @@ var sortKeysOperatorScenarios = []expressionScenario{
document: `{c: frog, a: blah, b: bing}`,
expression: `sort_keys(.)`,
expected: []string{
- "D0, P[], (doc)::{a: blah, b: bing, c: frog}\n",
+ "D0, P[], (!!map)::{a: blah, b: bing, c: frog}\n",
},
},
{
@@ -18,7 +18,7 @@ var sortKeysOperatorScenarios = []expressionScenario{
document: `{c: frog}`,
expression: `sort_keys(.d)`,
expected: []string{
- "D0, P[], (doc)::{c: frog}\n",
+ "D0, P[], (!!map)::{c: frog}\n",
},
},
{
diff --git a/pkg/yqlib/operator_sort_test.go b/pkg/yqlib/operator_sort_test.go
index 9a8bc84a..0b60545e 100644
--- a/pkg/yqlib/operator_sort_test.go
+++ b/pkg/yqlib/operator_sort_test.go
@@ -51,7 +51,7 @@ var sortByOperatorScenarios = []expressionScenario{
document: "cool: [{a: banana},{a: cat},{a: apple}]",
expression: `.cool |= sort_by(.a)`,
expected: []string{
- "D0, P[], (doc)::cool: [{a: apple}, {a: banana}, {a: cat}]\n",
+ "D0, P[], (!!map)::cool: [{a: apple}, {a: banana}, {a: cat}]\n",
},
},
{
@@ -60,7 +60,7 @@ var sortByOperatorScenarios = []expressionScenario{
document: "cool: [{b: banana},{a: banana},{c: banana}]",
expression: `.cool |= sort_by(keys | .[0])`,
expected: []string{
- "D0, P[], (doc)::cool: [{a: banana}, {b: banana}, {c: banana}]\n",
+ "D0, P[], (!!map)::cool: [{a: banana}, {b: banana}, {c: banana}]\n",
},
},
{
diff --git a/pkg/yqlib/operator_split_document.go b/pkg/yqlib/operator_split_document.go
index eba24964..e9fb245b 100644
--- a/pkg/yqlib/operator_split_document.go
+++ b/pkg/yqlib/operator_split_document.go
@@ -6,7 +6,8 @@ func splitDocumentOperator(d *dataTreeNavigator, context Context, expressionNode
var index uint
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- candidate.Document = index
+ candidate.SetDocument(index)
+ candidate.SetParent(nil)
index = index + 1
}
diff --git a/pkg/yqlib/operator_strings.go b/pkg/yqlib/operator_strings.go
index 716620fe..7ac6986b 100644
--- a/pkg/yqlib/operator_strings.go
+++ b/pkg/yqlib/operator_strings.go
@@ -5,8 +5,6 @@ import (
"fmt"
"regexp"
"strings"
-
- "gopkg.in/yaml.v3"
)
type changeCasePrefs struct {
@@ -16,17 +14,15 @@ type changeCasePrefs struct {
func trimSpaceOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
results := list.New()
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
- candidate := el.Value.(*CandidateNode)
+ node := el.Value.(*CandidateNode)
- node := unwrapDoc(candidate.Node)
-
- if guessTagFromCustomType(node) != "!!str" {
+ if node.guessTagFromCustomType() != "!!str" {
return Context{}, fmt.Errorf("cannot trim %v, can only operate on strings. ", node.Tag)
}
- newStringNode := &yaml.Node{Kind: yaml.ScalarNode, Tag: node.Tag, Style: node.Style}
- newStringNode.Value = strings.TrimSpace(node.Value)
- results.PushBack(candidate.CreateReplacement(newStringNode))
+ newStringNode := node.CreateReplacement(ScalarNode, node.Tag, strings.TrimSpace(node.Value))
+ newStringNode.Style = node.Style
+ results.PushBack(newStringNode)
}
@@ -38,21 +34,21 @@ func changeCaseOperator(d *dataTreeNavigator, context Context, expressionNode *E
prefs := expressionNode.Operation.Preferences.(changeCasePrefs)
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
- candidate := el.Value.(*CandidateNode)
+ node := el.Value.(*CandidateNode)
- node := unwrapDoc(candidate.Node)
-
- if guessTagFromCustomType(node) != "!!str" {
+ if node.guessTagFromCustomType() != "!!str" {
return Context{}, fmt.Errorf("cannot change case with %v, can only operate on strings. ", node.Tag)
}
- newStringNode := &yaml.Node{Kind: yaml.ScalarNode, Tag: node.Tag, Style: node.Style}
+ value := ""
if prefs.ToUpperCase {
- newStringNode.Value = strings.ToUpper(node.Value)
+ value = strings.ToUpper(node.Value)
} else {
- newStringNode.Value = strings.ToLower(node.Value)
+ value = strings.ToLower(node.Value)
}
- results.PushBack(candidate.CreateReplacement(newStringNode))
+ newStringNode := node.CreateReplacement(ScalarNode, node.Tag, value)
+ newStringNode.Style = node.Style
+ results.PushBack(newStringNode)
}
@@ -69,7 +65,7 @@ func getSubstituteParameters(d *dataTreeNavigator, block *ExpressionNode, contex
return "", "", err
}
if regExNodes.MatchingNodes.Front() != nil {
- regEx = regExNodes.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
+ regEx = regExNodes.MatchingNodes.Front().Value.(*CandidateNode).Value
}
log.Debug("regEx %v", regEx)
@@ -79,15 +75,15 @@ func getSubstituteParameters(d *dataTreeNavigator, block *ExpressionNode, contex
return "", "", err
}
if replacementNodes.MatchingNodes.Front() != nil {
- replacementText = replacementNodes.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
+ replacementText = replacementNodes.MatchingNodes.Front().Value.(*CandidateNode).Value
}
return regEx, replacementText, nil
}
-func substitute(original string, regex *regexp.Regexp, replacement string) *yaml.Node {
+func substitute(original string, regex *regexp.Regexp, replacement string) (Kind, string, string) {
replacedString := regex.ReplaceAllString(original, replacement)
- return &yaml.Node{Kind: yaml.ScalarNode, Value: replacedString, Tag: "!!str"}
+ return ScalarNode, "!!str", replacedString
}
func substituteStringOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@@ -110,15 +106,12 @@ func substituteStringOperator(d *dataTreeNavigator, context Context, expressionN
var results = list.New()
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
- candidate := el.Value.(*CandidateNode)
- node := unwrapDoc(candidate.Node)
-
- if guessTagFromCustomType(node) != "!!str" {
+ node := el.Value.(*CandidateNode)
+ if node.guessTagFromCustomType() != "!!str" {
return Context{}, fmt.Errorf("cannot substitute with %v, can only substitute strings. Hint: Most often you'll want to use '|=' over '=' for this operation", node.Tag)
}
- targetNode := substitute(node.Value, regEx, replacementText)
- result := candidate.CreateReplacement(targetNode)
+ result := node.CreateReplacement(substitute(node.Value, regEx, replacementText))
results.PushBack(result)
}
@@ -126,7 +119,7 @@ func substituteStringOperator(d *dataTreeNavigator, context Context, expressionN
}
-func addMatch(original []*yaml.Node, match string, offset int, name string) []*yaml.Node {
+func addMatch(original []*CandidateNode, match string, offset int, name string) []*CandidateNode {
newContent := append(original,
createScalarNode("string", "string"))
@@ -188,21 +181,18 @@ func match(matchPrefs matchPreferences, regEx *regexp.Regexp, candidate *Candida
}
for i, matches := range allMatches {
- capturesListNode := &yaml.Node{Kind: yaml.SequenceNode}
+ capturesListNode := &CandidateNode{Kind: SequenceNode}
match, submatches := matches[0], matches[1:]
for j, submatch := range submatches {
- captureNode := &yaml.Node{Kind: yaml.MappingNode}
- captureNode.Content = addMatch(captureNode.Content, submatch, allIndices[i][2+j*2], subNames[j+1])
- capturesListNode.Content = append(capturesListNode.Content, captureNode)
+ captureNode := &CandidateNode{Kind: MappingNode}
+ captureNode.AddChildren(addMatch(captureNode.Content, submatch, allIndices[i][2+j*2], subNames[j+1]))
+ capturesListNode.AddChild(captureNode)
}
- node := &yaml.Node{Kind: yaml.MappingNode}
- node.Content = addMatch(node.Content, match, allIndices[i][0], "")
- node.Content = append(node.Content,
- createScalarNode("captures", "captures"),
- capturesListNode,
- )
- results.PushBack(candidate.CreateReplacement(node))
+ node := candidate.CreateReplacement(MappingNode, "!!map", "")
+ node.AddChildren(addMatch(node.Content, match, allIndices[i][0], ""))
+ node.AddKeyValueChild(createScalarNode("captures", "captures"), capturesListNode)
+ results.PushBack(node)
}
@@ -219,27 +209,25 @@ func capture(matchPrefs matchPreferences, regEx *regexp.Regexp, candidate *Candi
}
for i, matches := range allMatches {
- capturesNode := &yaml.Node{Kind: yaml.MappingNode}
+ capturesNode := candidate.CreateReplacement(MappingNode, "!!map", "")
_, submatches := matches[0], matches[1:]
for j, submatch := range submatches {
- capturesNode.Content = append(capturesNode.Content,
- createScalarNode(subNames[j+1], subNames[j+1]))
+
+ keyNode := createScalarNode(subNames[j+1], subNames[j+1])
+ var valueNode *CandidateNode
offset := allIndices[i][2+j*2]
// offset of -1 means there was no match, force a null value like jq
if offset < 0 {
- capturesNode.Content = append(capturesNode.Content,
- createScalarNode(nil, "null"),
- )
+ valueNode = createScalarNode(nil, "null")
} else {
- capturesNode.Content = append(capturesNode.Content,
- createScalarNode(submatch, submatch),
- )
+ valueNode = createScalarNode(submatch, submatch)
}
+ capturesNode.AddKeyValueChild(keyNode, valueNode)
}
- results.PushBack(candidate.CreateReplacement(capturesNode))
+ results.PushBack(capturesNode)
}
@@ -260,7 +248,7 @@ func extractMatchArguments(d *dataTreeNavigator, context Context, expressionNode
}
paramText := ""
if replacementNodes.MatchingNodes.Front() != nil {
- paramText = replacementNodes.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
+ paramText = replacementNodes.MatchingNodes.Front().Value.(*CandidateNode).Value
}
if strings.Contains(paramText, "g") {
paramText = strings.ReplaceAll(paramText, "g", "")
@@ -281,7 +269,7 @@ func extractMatchArguments(d *dataTreeNavigator, context Context, expressionNode
log.Debug(NodesToString(regExNodes.MatchingNodes))
regExStr := ""
if regExNodes.MatchingNodes.Front() != nil {
- regExStr = regExNodes.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
+ regExStr = regExNodes.MatchingNodes.Front().Value.(*CandidateNode).Value
}
log.Debug("regEx %v", regExStr)
regEx, err := regexp.Compile(regExStr)
@@ -297,14 +285,12 @@ func matchOperator(d *dataTreeNavigator, context Context, expressionNode *Expres
var results = list.New()
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
- candidate := el.Value.(*CandidateNode)
- node := unwrapDoc(candidate.Node)
-
- if guessTagFromCustomType(node) != "!!str" {
+ node := el.Value.(*CandidateNode)
+ if node.guessTagFromCustomType() != "!!str" {
return Context{}, fmt.Errorf("cannot match with %v, can only match strings. Hint: Most often you'll want to use '|=' over '=' for this operation", node.Tag)
}
- match(matchPrefs, regEx, candidate, node.Value, results)
+ match(matchPrefs, regEx, node, node.Value, results)
}
return context.ChildContext(results), nil
@@ -319,13 +305,11 @@ func captureOperator(d *dataTreeNavigator, context Context, expressionNode *Expr
var results = list.New()
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
- candidate := el.Value.(*CandidateNode)
- node := unwrapDoc(candidate.Node)
-
- if guessTagFromCustomType(node) != "!!str" {
+ node := el.Value.(*CandidateNode)
+ if node.guessTagFromCustomType() != "!!str" {
return Context{}, fmt.Errorf("cannot match with %v, can only match strings. Hint: Most often you'll want to use '|=' over '=' for this operation", node.Tag)
}
- capture(matchPrefs, regEx, candidate, node.Value, results)
+ capture(matchPrefs, regEx, node, node.Value, results)
}
@@ -341,14 +325,12 @@ func testOperator(d *dataTreeNavigator, context Context, expressionNode *Express
var results = list.New()
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
- candidate := el.Value.(*CandidateNode)
- node := unwrapDoc(candidate.Node)
-
- if guessTagFromCustomType(node) != "!!str" {
+ node := el.Value.(*CandidateNode)
+ if node.guessTagFromCustomType() != "!!str" {
return Context{}, fmt.Errorf("cannot match with %v, can only match strings. Hint: Most often you'll want to use '|=' over '=' for this operation", node.Tag)
}
matches := regEx.FindStringSubmatch(node.Value)
- results.PushBack(createBooleanCandidate(candidate, len(matches) > 0))
+ results.PushBack(createBooleanCandidate(node, len(matches) > 0))
}
@@ -364,26 +346,24 @@ func joinStringOperator(d *dataTreeNavigator, context Context, expressionNode *E
return Context{}, err
}
if rhs.MatchingNodes.Front() != nil {
- joinStr = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
+ joinStr = rhs.MatchingNodes.Front().Value.(*CandidateNode).Value
}
var results = list.New()
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
- candidate := el.Value.(*CandidateNode)
- node := unwrapDoc(candidate.Node)
- if node.Kind != yaml.SequenceNode {
+ node := el.Value.(*CandidateNode)
+ if node.Kind != SequenceNode {
return Context{}, fmt.Errorf("cannot join with %v, can only join arrays of scalars", node.Tag)
}
- targetNode := join(node.Content, joinStr)
- result := candidate.CreateReplacement(targetNode)
+ result := node.CreateReplacement(join(node.Content, joinStr))
results.PushBack(result)
}
return context.ChildContext(results), nil
}
-func join(content []*yaml.Node, joinStr string) *yaml.Node {
+func join(content []*CandidateNode, joinStr string) (Kind, string, string) {
var stringsToJoin []string
for _, node := range content {
str := node.Value
@@ -393,7 +373,7 @@ func join(content []*yaml.Node, joinStr string) *yaml.Node {
stringsToJoin = append(stringsToJoin, str)
}
- return &yaml.Node{Kind: yaml.ScalarNode, Value: strings.Join(stringsToJoin, joinStr), Tag: "!!str"}
+ return ScalarNode, "!!str", strings.Join(stringsToJoin, joinStr)
}
func splitStringOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@@ -405,41 +385,41 @@ func splitStringOperator(d *dataTreeNavigator, context Context, expressionNode *
return Context{}, err
}
if rhs.MatchingNodes.Front() != nil {
- splitStr = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
+ splitStr = rhs.MatchingNodes.Front().Value.(*CandidateNode).Value
}
var results = list.New()
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
- candidate := el.Value.(*CandidateNode)
- node := unwrapDoc(candidate.Node)
+ node := el.Value.(*CandidateNode)
if node.Tag == "!!null" {
continue
}
- if guessTagFromCustomType(node) != "!!str" {
- return Context{}, fmt.Errorf("Cannot split %v, can only split strings", node.Tag)
+ if node.guessTagFromCustomType() != "!!str" {
+ return Context{}, fmt.Errorf("cannot split %v, can only split strings", node.Tag)
}
- targetNode := split(node.Value, splitStr)
- result := candidate.CreateReplacement(targetNode)
+ kind, tag, content := split(node.Value, splitStr)
+ result := node.CreateReplacement(kind, tag, "")
+ result.AddChildren(content)
results.PushBack(result)
}
return context.ChildContext(results), nil
}
-func split(value string, spltStr string) *yaml.Node {
- var contents []*yaml.Node
+func split(value string, spltStr string) (Kind, string, []*CandidateNode) {
+ var contents []*CandidateNode
if value != "" {
log.Debug("going to spltStr[%v]", spltStr)
var newStrings = strings.Split(value, spltStr)
- contents = make([]*yaml.Node, len(newStrings))
+ contents = make([]*CandidateNode, len(newStrings))
for index, str := range newStrings {
- contents[index] = &yaml.Node{Kind: yaml.ScalarNode, Tag: "!!str", Value: str}
+ contents[index] = &CandidateNode{Kind: ScalarNode, Tag: "!!str", Value: str}
}
}
- return &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq", Content: contents}
+ return SequenceNode, "!!seq", contents
}
diff --git a/pkg/yqlib/operator_strings_test.go b/pkg/yqlib/operator_strings_test.go
index 1cf4268d..169bc047 100644
--- a/pkg/yqlib/operator_strings_test.go
+++ b/pkg/yqlib/operator_strings_test.go
@@ -71,7 +71,7 @@ var stringsOperatorScenarios = []expressionScenario{
document: `foo bar foo`,
expression: `match("foo")`,
expected: []string{
- "D0, P[], ()::string: foo\noffset: 0\nlength: 3\ncaptures: []\n",
+ "D0, P[], (!!map)::string: foo\noffset: 0\nlength: 3\ncaptures: []\n",
},
},
{
@@ -79,7 +79,7 @@ var stringsOperatorScenarios = []expressionScenario{
document: `!horse foo bar foo`,
expression: `match("foo")`,
expected: []string{
- "D0, P[], ()::string: foo\noffset: 0\nlength: 3\ncaptures: []\n",
+ "D0, P[], (!!map)::string: foo\noffset: 0\nlength: 3\ncaptures: []\n",
},
},
{
@@ -111,7 +111,7 @@ var stringsOperatorScenarios = []expressionScenario{
document: `xyzzy-14`,
expression: `capture("(?P[a-z]+)-(?P[0-9]+)")`,
expected: []string{
- "D0, P[], ()::a: xyzzy\nn: \"14\"\n",
+ "D0, P[], (!!map)::a: xyzzy\nn: \"14\"\n",
},
},
{
@@ -119,7 +119,7 @@ var stringsOperatorScenarios = []expressionScenario{
document: `!horse xyzzy-14`,
expression: `capture("(?P[a-z]+)-(?P[0-9]+)")`,
expected: []string{
- "D0, P[], ()::a: xyzzy\nn: \"14\"\n",
+ "D0, P[], (!!map)::a: xyzzy\nn: \"14\"\n",
},
},
{
@@ -128,7 +128,7 @@ var stringsOperatorScenarios = []expressionScenario{
document: `xyzzy-14`,
expression: `capture("(?P[a-z]+)-(?P[0-9]+)(?Pbar)?")`,
expected: []string{
- "D0, P[], ()::a: xyzzy\nn: \"14\"\nbar123: null\n",
+ "D0, P[], (!!map)::a: xyzzy\nn: \"14\"\nbar123: null\n",
},
},
{
@@ -136,7 +136,7 @@ var stringsOperatorScenarios = []expressionScenario{
document: `cat cat`,
expression: `match("cat")`,
expected: []string{
- "D0, P[], ()::string: cat\noffset: 0\nlength: 3\ncaptures: []\n",
+ "D0, P[], (!!map)::string: cat\noffset: 0\nlength: 3\ncaptures: []\n",
},
},
{
@@ -209,7 +209,7 @@ var stringsOperatorScenarios = []expressionScenario{
document: `a: dogs are great`,
expression: `.a |= sub("dogs", "cats")`,
expected: []string{
- "D0, P[], (doc)::a: cats are great\n",
+ "D0, P[], (!!map)::a: cats are great\n",
},
},
{
@@ -218,7 +218,7 @@ var stringsOperatorScenarios = []expressionScenario{
document: "a: cat\nb: heat",
expression: `.[] |= sub("(a)", "${1}r")`,
expected: []string{
- "D0, P[], (doc)::a: cart\nb: heart\n",
+ "D0, P[], (!!map)::a: cart\nb: heart\n",
},
},
{
@@ -227,7 +227,7 @@ var stringsOperatorScenarios = []expressionScenario{
document: "a: !horse cat\nb: !goat heat",
expression: `.[] |= sub("(a)", "${1}r")`,
expected: []string{
- "D0, P[], (doc)::a: !horse cart\nb: !goat heart\n",
+ "D0, P[], (!!map)::a: !horse cart\nb: !goat heart\n",
},
},
{
diff --git a/pkg/yqlib/operator_style.go b/pkg/yqlib/operator_style.go
index ed7f6549..2db8cc16 100644
--- a/pkg/yqlib/operator_style.go
+++ b/pkg/yqlib/operator_style.go
@@ -3,23 +3,21 @@ package yqlib
import (
"container/list"
"fmt"
-
- yaml "gopkg.in/yaml.v3"
)
-func parseStyle(customStyle string) (yaml.Style, error) {
+func parseStyle(customStyle string) (Style, error) {
if customStyle == "tagged" {
- return yaml.TaggedStyle, nil
+ return TaggedStyle, nil
} else if customStyle == "double" {
- return yaml.DoubleQuotedStyle, nil
+ return DoubleQuotedStyle, nil
} else if customStyle == "single" {
- return yaml.SingleQuotedStyle, nil
+ return SingleQuotedStyle, nil
} else if customStyle == "literal" {
- return yaml.LiteralStyle, nil
+ return LiteralStyle, nil
} else if customStyle == "folded" {
- return yaml.FoldedStyle, nil
+ return FoldedStyle, nil
} else if customStyle == "flow" {
- return yaml.FlowStyle, nil
+ return FlowStyle, nil
} else if customStyle != "" {
return 0, fmt.Errorf("Unknown style %v", customStyle)
}
@@ -29,7 +27,7 @@ func parseStyle(customStyle string) (yaml.Style, error) {
func assignStyleOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
log.Debugf("AssignStyleOperator: %v")
- var style yaml.Style
+ var style Style
if !expressionNode.Operation.UpdateAssign {
rhs, err := d.GetMatchingNodes(context.ReadOnlyClone(), expressionNode.RHS)
if err != nil {
@@ -37,7 +35,7 @@ func assignStyleOperator(d *dataTreeNavigator, context Context, expressionNode *
}
if rhs.MatchingNodes.Front() != nil {
- style, err = parseStyle(rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value)
+ style, err = parseStyle(rhs.MatchingNodes.Front().Value.(*CandidateNode).Value)
if err != nil {
return Context{}, err
}
@@ -52,7 +50,7 @@ func assignStyleOperator(d *dataTreeNavigator, context Context, expressionNode *
for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- log.Debugf("Setting style of : %v", candidate.GetKey())
+ log.Debugf("Setting style of : %v", NodeToString(candidate))
if expressionNode.Operation.UpdateAssign {
rhs, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(candidate), expressionNode.RHS)
if err != nil {
@@ -60,14 +58,14 @@ func assignStyleOperator(d *dataTreeNavigator, context Context, expressionNode *
}
if rhs.MatchingNodes.Front() != nil {
- style, err = parseStyle(rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value)
+ style, err = parseStyle(rhs.MatchingNodes.Front().Value.(*CandidateNode).Value)
if err != nil {
return Context{}, err
}
}
}
- candidate.Node.Style = style
+ candidate.Style = style
}
return context, nil
@@ -81,26 +79,25 @@ func getStyleOperator(d *dataTreeNavigator, context Context, expressionNode *Exp
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
var style string
- switch candidate.Node.Style {
- case yaml.TaggedStyle:
+ switch candidate.Style {
+ case TaggedStyle:
style = "tagged"
- case yaml.DoubleQuotedStyle:
+ case DoubleQuotedStyle:
style = "double"
- case yaml.SingleQuotedStyle:
+ case SingleQuotedStyle:
style = "single"
- case yaml.LiteralStyle:
+ case LiteralStyle:
style = "literal"
- case yaml.FoldedStyle:
+ case FoldedStyle:
style = "folded"
- case yaml.FlowStyle:
+ case FlowStyle:
style = "flow"
case 0:
style = ""
default:
style = ""
}
- node := &yaml.Node{Kind: yaml.ScalarNode, Value: style, Tag: "!!str"}
- result := candidate.CreateReplacement(node)
+ result := candidate.CreateReplacement(ScalarNode, "!!str", style)
results.PushBack(result)
}
diff --git a/pkg/yqlib/operator_style_test.go b/pkg/yqlib/operator_style_test.go
index ce263a7b..9077f9a2 100644
--- a/pkg/yqlib/operator_style_test.go
+++ b/pkg/yqlib/operator_style_test.go
@@ -10,7 +10,7 @@ var styleOperatorScenarios = []expressionScenario{
document: `a: {b: thing, c: something}`,
expression: `.a.b = "new" | .a.b style="double"`,
expected: []string{
- "D0, P[], (doc)::a: {b: \"new\", c: something}\n",
+ "D0, P[], (!!map)::a: {b: \"new\", c: something}\n",
},
},
{
@@ -18,7 +18,7 @@ var styleOperatorScenarios = []expressionScenario{
document: `a: {b: thing, c: something}`,
expression: `with(.a.b ; . = "new" | . style="double")`,
expected: []string{
- "D0, P[], (doc)::a: {b: \"new\", c: something}\n",
+ "D0, P[], (!!map)::a: {b: \"new\", c: something}\n",
},
},
{
@@ -115,7 +115,7 @@ e: >-
document: `{a: single, b: double}`,
expression: `.[] style |= .`,
expected: []string{
- "D0, P[], (doc)::{a: 'single', b: \"double\"}\n",
+ "D0, P[], (!!map)::{a: 'single', b: \"double\"}\n",
},
},
{
@@ -123,7 +123,7 @@ e: >-
document: `{a: cat, b: double}`,
expression: `.a style=.b`,
expected: []string{
- "D0, P[], (doc)::{a: \"cat\", b: double}\n",
+ "D0, P[], (!!map)::{a: \"cat\", b: double}\n",
},
},
{
diff --git a/pkg/yqlib/operator_subtract.go b/pkg/yqlib/operator_subtract.go
index 90867d48..260f3cbe 100644
--- a/pkg/yqlib/operator_subtract.go
+++ b/pkg/yqlib/operator_subtract.go
@@ -5,8 +5,6 @@ import (
"strconv"
"strings"
"time"
-
- "gopkg.in/yaml.v3"
)
func createSubtractOp(lhs *ExpressionNode, rhs *ExpressionNode) *ExpressionNode {
@@ -26,50 +24,46 @@ func subtractOperator(d *dataTreeNavigator, context Context, expressionNode *Exp
}
func subtractArray(lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
- newLHSArray := make([]*yaml.Node, 0)
+ newLHSArray := make([]*CandidateNode, 0)
- for lindex := 0; lindex < len(lhs.Node.Content); lindex = lindex + 1 {
+ for lindex := 0; lindex < len(lhs.Content); lindex = lindex + 1 {
shouldInclude := true
- for rindex := 0; rindex < len(rhs.Node.Content) && shouldInclude; rindex = rindex + 1 {
- if recursiveNodeEqual(lhs.Node.Content[lindex], rhs.Node.Content[rindex]) {
+ for rindex := 0; rindex < len(rhs.Content) && shouldInclude; rindex = rindex + 1 {
+ if recursiveNodeEqual(lhs.Content[lindex], rhs.Content[rindex]) {
shouldInclude = false
}
}
if shouldInclude {
- newLHSArray = append(newLHSArray, lhs.Node.Content[lindex])
+ newLHSArray = append(newLHSArray, lhs.Content[lindex])
}
}
- lhs.Node.Content = newLHSArray
+ // removing children from LHS, parent hasn't changed
+ lhs.Content = newLHSArray
return lhs, nil
}
func subtract(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *CandidateNode) (*CandidateNode, error) {
- lhs.Node = unwrapDoc(lhs.Node)
- rhs.Node = unwrapDoc(rhs.Node)
-
- lhsNode := lhs.Node
-
- if lhsNode.Tag == "!!null" {
- return lhs.CreateReplacement(rhs.Node), nil
+ if lhs.Tag == "!!null" {
+ return lhs.CopyAsReplacement(rhs), nil
}
- target := lhs.CreateReplacement(&yaml.Node{})
+ target := lhs.CopyWithoutContent()
- switch lhsNode.Kind {
- case yaml.MappingNode:
+ switch lhs.Kind {
+ case MappingNode:
return nil, fmt.Errorf("maps not yet supported for subtraction")
- case yaml.SequenceNode:
- if rhs.Node.Kind != yaml.SequenceNode {
- return nil, fmt.Errorf("%v (%v) cannot be subtracted from %v", rhs.Node.Tag, rhs.Path, lhsNode.Tag)
+ case SequenceNode:
+ if rhs.Kind != SequenceNode {
+ return nil, fmt.Errorf("%v (%v) cannot be subtracted from %v", rhs.Tag, rhs.GetNicePath(), lhs.Tag)
}
return subtractArray(lhs, rhs)
- case yaml.ScalarNode:
- if rhs.Node.Kind != yaml.ScalarNode {
- return nil, fmt.Errorf("%v (%v) cannot be subtracted from %v", rhs.Node.Tag, rhs.Path, lhsNode.Tag)
+ case ScalarNode:
+ if rhs.Kind != ScalarNode {
+ return nil, fmt.Errorf("%v (%v) cannot be subtracted from %v", rhs.Tag, rhs.GetNicePath(), lhs.Tag)
}
- target.Node.Kind = yaml.ScalarNode
- target.Node.Style = lhsNode.Style
- if err := subtractScalars(context, target, lhsNode, rhs.Node); err != nil {
+ target.Kind = ScalarNode
+ target.Style = lhs.Style
+ if err := subtractScalars(context, target, lhs, rhs); err != nil {
return nil, err
}
}
@@ -77,19 +71,19 @@ func subtract(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *Ca
return target, nil
}
-func subtractScalars(context Context, target *CandidateNode, lhs *yaml.Node, rhs *yaml.Node) error {
+func subtractScalars(context Context, target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error {
lhsTag := lhs.Tag
rhsTag := rhs.Tag
lhsIsCustom := false
if !strings.HasPrefix(lhsTag, "!!") {
// custom tag - we have to have a guess
- lhsTag = guessTagFromCustomType(lhs)
+ lhsTag = lhs.guessTagFromCustomType()
lhsIsCustom = true
}
if !strings.HasPrefix(rhsTag, "!!") {
// custom tag - we have to have a guess
- rhsTag = guessTagFromCustomType(rhs)
+ rhsTag = rhs.guessTagFromCustomType()
}
isDateTime := lhsTag == "!!timestamp"
@@ -113,8 +107,8 @@ func subtractScalars(context Context, target *CandidateNode, lhs *yaml.Node, rhs
return err
}
result := lhsNum - rhsNum
- target.Node.Tag = lhs.Tag
- target.Node.Value = fmt.Sprintf(format, result)
+ target.Tag = lhs.Tag
+ target.Value = fmt.Sprintf(format, result)
} else if (lhsTag == "!!int" || lhsTag == "!!float") && (rhsTag == "!!int" || rhsTag == "!!float") {
lhsNum, err := strconv.ParseFloat(lhs.Value, 64)
if err != nil {
@@ -126,11 +120,11 @@ func subtractScalars(context Context, target *CandidateNode, lhs *yaml.Node, rhs
}
result := lhsNum - rhsNum
if lhsIsCustom {
- target.Node.Tag = lhs.Tag
+ target.Tag = lhs.Tag
} else {
- target.Node.Tag = "!!float"
+ target.Tag = "!!float"
}
- target.Node.Value = fmt.Sprintf("%v", result)
+ target.Value = fmt.Sprintf("%v", result)
} else {
return fmt.Errorf("%v cannot be added to %v", lhs.Tag, rhs.Tag)
}
@@ -138,7 +132,7 @@ func subtractScalars(context Context, target *CandidateNode, lhs *yaml.Node, rhs
return nil
}
-func subtractDateTime(layout string, target *CandidateNode, lhs *yaml.Node, rhs *yaml.Node) error {
+func subtractDateTime(layout string, target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error {
var durationStr string
if strings.HasPrefix(rhs.Value, "-") {
durationStr = rhs.Value[1:]
@@ -157,6 +151,6 @@ func subtractDateTime(layout string, target *CandidateNode, lhs *yaml.Node, rhs
}
newTime := currentTime.Add(duration)
- target.Node.Value = newTime.Format(layout)
+ target.Value = newTime.Format(layout)
return nil
}
diff --git a/pkg/yqlib/operator_subtract_test.go b/pkg/yqlib/operator_subtract_test.go
index b24474e9..2b365b4d 100644
--- a/pkg/yqlib/operator_subtract_test.go
+++ b/pkg/yqlib/operator_subtract_test.go
@@ -10,7 +10,7 @@ var subtractOperatorScenarios = []expressionScenario{
document: `{}`,
expression: "(.a - .b) as $x | .",
expected: []string{
- "D0, P[], (doc)::{}\n",
+ "D0, P[], (!!map)::{}\n",
},
},
{
@@ -64,7 +64,7 @@ var subtractOperatorScenarios = []expressionScenario{
document: `{a: 3, b: 4.5}`,
expression: `.a = .a - .b`,
expected: []string{
- "D0, P[], (doc)::{a: -1.5, b: 4.5}\n",
+ "D0, P[], (!!map)::{a: -1.5, b: 4.5}\n",
},
},
{
@@ -73,7 +73,7 @@ var subtractOperatorScenarios = []expressionScenario{
document: `{a: 3, b: 4}`,
expression: `.a = .a - .b`,
expected: []string{
- "D0, P[], (doc)::{a: -1, b: 4}\n",
+ "D0, P[], (!!map)::{a: -1, b: 4}\n",
},
},
{
@@ -81,7 +81,7 @@ var subtractOperatorScenarios = []expressionScenario{
document: `{a: 3, b: 5}`,
expression: `.[] -= 1`,
expected: []string{
- "D0, P[], (doc)::{a: 2, b: 4}\n",
+ "D0, P[], (!!map)::{a: 2, b: 4}\n",
},
},
{
@@ -90,7 +90,7 @@ var subtractOperatorScenarios = []expressionScenario{
document: `a: 2021-01-01T03:10:00Z`,
expression: `.a -= "3h10m"`,
expected: []string{
- "D0, P[], (doc)::a: 2021-01-01T00:00:00Z\n",
+ "D0, P[], (!!map)::a: 2021-01-01T00:00:00Z\n",
},
},
{
@@ -99,7 +99,7 @@ var subtractOperatorScenarios = []expressionScenario{
document: `a: 2021-01-01`,
expression: `.a -= "24h"`,
expected: []string{
- "D0, P[], (doc)::a: 2020-12-31T00:00:00Z\n",
+ "D0, P[], (!!map)::a: 2020-12-31T00:00:00Z\n",
},
},
{
@@ -108,7 +108,7 @@ var subtractOperatorScenarios = []expressionScenario{
document: `a: Saturday, 15-Dec-01 at 6:00AM GMT`,
expression: `with_dtf("Monday, 02-Jan-06 at 3:04PM MST", .a -= "3h1m")`,
expected: []string{
- "D0, P[], (doc)::a: Saturday, 15-Dec-01 at 2:59AM GMT\n",
+ "D0, P[], (!!map)::a: Saturday, 15-Dec-01 at 2:59AM GMT\n",
},
},
{
@@ -118,7 +118,7 @@ var subtractOperatorScenarios = []expressionScenario{
document: `a: !cat Saturday, 15-Dec-01 at 6:00AM GMT`,
expression: `with_dtf("Monday, 02-Jan-06 at 3:04PM MST", .a -= "3h1m")`,
expected: []string{
- "D0, P[], (doc)::a: !cat Saturday, 15-Dec-01 at 2:59AM GMT\n",
+ "D0, P[], (!!map)::a: !cat Saturday, 15-Dec-01 at 2:59AM GMT\n",
},
},
{
@@ -127,7 +127,7 @@ var subtractOperatorScenarios = []expressionScenario{
document: "a: !horse 2\nb: !goat 1",
expression: `.a -= .b`,
expected: []string{
- "D0, P[], (doc)::a: !horse 1\nb: !goat 1\n",
+ "D0, P[], (!!map)::a: !horse 1\nb: !goat 1\n",
},
},
{
diff --git a/pkg/yqlib/operator_tag.go b/pkg/yqlib/operator_tag.go
index 59b07d89..87f82dca 100644
--- a/pkg/yqlib/operator_tag.go
+++ b/pkg/yqlib/operator_tag.go
@@ -2,8 +2,6 @@ package yqlib
import (
"container/list"
-
- yaml "gopkg.in/yaml.v3"
)
func assignTagOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@@ -18,7 +16,7 @@ func assignTagOperator(d *dataTreeNavigator, context Context, expressionNode *Ex
}
if rhs.MatchingNodes.Front() != nil {
- tag = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
+ tag = rhs.MatchingNodes.Front().Value.(*CandidateNode).Value
}
}
@@ -38,10 +36,10 @@ func assignTagOperator(d *dataTreeNavigator, context Context, expressionNode *Ex
}
if rhs.MatchingNodes.Front() != nil {
- tag = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
+ tag = rhs.MatchingNodes.Front().Value.(*CandidateNode).Value
}
}
- unwrapDoc(candidate.Node).Tag = tag
+ candidate.Tag = tag
}
return context, nil
@@ -54,8 +52,7 @@ func getTagOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- node := &yaml.Node{Kind: yaml.ScalarNode, Value: unwrapDoc(candidate.Node).Tag, Tag: "!!str"}
- result := candidate.CreateReplacement(node)
+ result := candidate.CreateReplacement(ScalarNode, "!!str", candidate.Tag)
results.PushBack(result)
}
diff --git a/pkg/yqlib/operator_tag_test.go b/pkg/yqlib/operator_tag_test.go
index 0466e5f3..e000cd88 100644
--- a/pkg/yqlib/operator_tag_test.go
+++ b/pkg/yqlib/operator_tag_test.go
@@ -5,6 +5,16 @@ import (
)
var tagOperatorScenarios = []expressionScenario{
+ {
+ description: "tag of key is not a key",
+ subdescription: "so it should have 'a' as the path",
+ skipDoc: true,
+ document: "a: frog\n",
+ expression: `.a | key | tag`,
+ expected: []string{
+ "D0, P[a], (!!str)::!!str\n",
+ },
+ },
{
description: "Get tag",
document: `{a: cat, b: 5, c: 3.2, e: true, f: []}`,
@@ -44,7 +54,7 @@ var tagOperatorScenarios = []expressionScenario{
document: `32`,
expression: `. tag= "!!str"`,
expected: []string{
- "D0, P[], (doc)::\"32\"\n",
+ "D0, P[], (!!str)::32\n",
},
},
{
@@ -52,7 +62,7 @@ var tagOperatorScenarios = []expressionScenario{
document: `{a: str}`,
expression: `.a tag = "!!mikefarah"`,
expected: []string{
- "D0, P[], (doc)::{a: !!mikefarah str}\n",
+ "D0, P[], (!!map)::{a: !!mikefarah str}\n",
},
},
{
@@ -61,7 +71,7 @@ var tagOperatorScenarios = []expressionScenario{
document: `{a: str}`,
expression: `.a type = "!!mikefarah"`,
expected: []string{
- "D0, P[], (doc)::{a: !!mikefarah str}\n",
+ "D0, P[], (!!map)::{a: !!mikefarah str}\n",
},
},
{
@@ -77,7 +87,7 @@ var tagOperatorScenarios = []expressionScenario{
document: `{a: "!!frog", b: "!!customTag"}`,
expression: `.[] tag |= .`,
expected: []string{
- "D0, P[], (doc)::{a: !!frog \"!!frog\", b: !!customTag \"!!customTag\"}\n",
+ "D0, P[], (!!map)::{a: !!frog \"!!frog\", b: !!customTag \"!!customTag\"}\n",
},
},
}
diff --git a/pkg/yqlib/operator_to_number.go b/pkg/yqlib/operator_to_number.go
index 6c97d4ed..1b951778 100644
--- a/pkg/yqlib/operator_to_number.go
+++ b/pkg/yqlib/operator_to_number.go
@@ -4,8 +4,6 @@ import (
"container/list"
"fmt"
"strconv"
-
- yaml "gopkg.in/yaml.v3"
)
func tryConvertToNumber(value string) (string, bool) {
@@ -31,22 +29,20 @@ func toNumberOperator(d *dataTreeNavigator, context Context, expressionNode *Exp
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- if candidate.Node.Kind != yaml.ScalarNode {
- return Context{}, fmt.Errorf("cannot convert node at path %v of tag %v to number", candidate.GetNicePath(), candidate.GetNiceTag())
+ if candidate.Kind != ScalarNode {
+ return Context{}, fmt.Errorf("cannot convert node at path %v of tag %v to number", candidate.GetNicePath(), candidate.Tag)
}
- if candidate.Node.Tag == "!!int" || candidate.Node.Tag == "!!float" {
+ if candidate.Tag == "!!int" || candidate.Tag == "!!float" {
// it already is a number!
results.PushBack(candidate)
} else {
- tag, converted := tryConvertToNumber(candidate.Node.Value)
+ tag, converted := tryConvertToNumber(candidate.Value)
if converted {
- node := &yaml.Node{Kind: yaml.ScalarNode, Value: candidate.Node.Value, Tag: tag}
-
- result := candidate.CreateReplacement(node)
+ result := candidate.CreateReplacement(ScalarNode, tag, candidate.Value)
results.PushBack(result)
} else {
- return Context{}, fmt.Errorf("cannot convert node value [%v] at path %v of tag %v to number", candidate.Node.Value, candidate.GetNicePath(), candidate.GetNiceTag())
+ return Context{}, fmt.Errorf("cannot convert node value [%v] at path %v of tag %v to number", candidate.Value, candidate.GetNicePath(), candidate.Tag)
}
}
diff --git a/pkg/yqlib/operator_traverse_path.go b/pkg/yqlib/operator_traverse_path.go
index 5af781db..0d2e5f52 100644
--- a/pkg/yqlib/operator_traverse_path.go
+++ b/pkg/yqlib/operator_traverse_path.go
@@ -5,7 +5,6 @@ import (
"fmt"
"github.com/elliotchance/orderedmap"
- yaml "gopkg.in/yaml.v3"
)
type traversePreferences struct {
@@ -17,7 +16,7 @@ type traversePreferences struct {
}
func splat(context Context, prefs traversePreferences) (Context, error) {
- return traverseNodesWithArrayIndices(context, make([]*yaml.Node, 0), prefs)
+ return traverseNodesWithArrayIndices(context, make([]*CandidateNode, 0), prefs)
}
func traversePathOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@@ -37,39 +36,34 @@ func traversePathOperator(d *dataTreeNavigator, context Context, expressionNode
func traverse(context Context, matchingNode *CandidateNode, operation *Operation) (*list.List, error) {
log.Debug("Traversing %v", NodeToString(matchingNode))
- value := matchingNode.Node
- if value.Tag == "!!null" && operation.Value != "[]" && !context.DontAutoCreate {
+ if matchingNode.Tag == "!!null" && operation.Value != "[]" && !context.DontAutoCreate {
log.Debugf("Guessing kind")
// we must have added this automatically, lets guess what it should be now
switch operation.Value.(type) {
case int, int64:
log.Debugf("probably an array")
- value.Kind = yaml.SequenceNode
+ matchingNode.Kind = SequenceNode
default:
log.Debugf("probably a map")
- value.Kind = yaml.MappingNode
+ matchingNode.Kind = MappingNode
}
- value.Tag = ""
+ matchingNode.Tag = ""
}
- switch value.Kind {
- case yaml.MappingNode:
- log.Debug("its a map with %v entries", len(value.Content)/2)
+ switch matchingNode.Kind {
+ case MappingNode:
+ log.Debug("its a map with %v entries", len(matchingNode.Content)/2)
return traverseMap(context, matchingNode, createStringScalarNode(operation.StringValue), operation.Preferences.(traversePreferences), false)
- case yaml.SequenceNode:
- log.Debug("its a sequence of %v things!", len(value.Content))
+ case SequenceNode:
+ log.Debug("its a sequence of %v things!", len(matchingNode.Content))
return traverseArray(matchingNode, operation, operation.Preferences.(traversePreferences))
- case yaml.AliasNode:
+ case AliasNode:
log.Debug("its an alias!")
- matchingNode.Node = matchingNode.Node.Alias
+ matchingNode = matchingNode.Alias
return traverse(context, matchingNode, operation)
- case yaml.DocumentNode:
- log.Debug("digging into doc node")
-
- return traverse(context, matchingNode.CreateChildInMap(nil, matchingNode.Node.Content[0]), operation)
default:
return list.New(), nil
}
@@ -103,7 +97,7 @@ func traverseArrayOperator(d *dataTreeNavigator, context Context, expressionNode
if expressionNode.Operation.Preferences != nil {
prefs = expressionNode.Operation.Preferences.(traversePreferences)
}
- var indicesToTraverse = rhs.MatchingNodes.Front().Value.(*CandidateNode).Node.Content
+ var indicesToTraverse = rhs.MatchingNodes.Front().Value.(*CandidateNode).Content
log.Debugf("indicesToTraverse %v", len(indicesToTraverse))
@@ -115,7 +109,7 @@ func traverseArrayOperator(d *dataTreeNavigator, context Context, expressionNode
return context.ChildContext(result.MatchingNodes), nil
}
-func traverseNodesWithArrayIndices(context Context, indicesToTraverse []*yaml.Node, prefs traversePreferences) (Context, error) {
+func traverseNodesWithArrayIndices(context Context, indicesToTraverse []*CandidateNode, prefs traversePreferences) (Context, error) {
var matchingNodeMap = list.New()
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
@@ -129,34 +123,31 @@ func traverseNodesWithArrayIndices(context Context, indicesToTraverse []*yaml.No
return context.ChildContext(matchingNodeMap), nil
}
-func traverseArrayIndices(context Context, matchingNode *CandidateNode, indicesToTraverse []*yaml.Node, prefs traversePreferences) (*list.List, error) { // call this if doc / alias like the other traverse
- node := matchingNode.Node
- if node.Tag == "!!null" {
+func traverseArrayIndices(context Context, matchingNode *CandidateNode, indicesToTraverse []*CandidateNode, prefs traversePreferences) (*list.List, error) { // call this if doc / alias like the other traverse
+ if matchingNode.Tag == "!!null" {
log.Debugf("OperatorArrayTraverse got a null - turning it into an empty array")
// auto vivification
- node.Tag = ""
- node.Kind = yaml.SequenceNode
+ matchingNode.Tag = ""
+ matchingNode.Kind = SequenceNode
//check that the indices are numeric, if not, then we should create an object
if len(indicesToTraverse) != 0 && indicesToTraverse[0].Tag != "!!int" {
- node.Kind = yaml.MappingNode
+ matchingNode.Kind = MappingNode
}
}
- if node.Kind == yaml.AliasNode {
- matchingNode.Node = node.Alias
+ if matchingNode.Kind == AliasNode {
+ matchingNode = matchingNode.Alias
return traverseArrayIndices(context, matchingNode, indicesToTraverse, prefs)
- } else if node.Kind == yaml.SequenceNode {
+ } else if matchingNode.Kind == SequenceNode {
return traverseArrayWithIndices(matchingNode, indicesToTraverse, prefs)
- } else if node.Kind == yaml.MappingNode {
+ } else if matchingNode.Kind == MappingNode {
return traverseMapWithIndices(context, matchingNode, indicesToTraverse, prefs)
- } else if node.Kind == yaml.DocumentNode {
- return traverseArrayIndices(context, matchingNode.CreateChildInMap(nil, matchingNode.Node.Content[0]), indicesToTraverse, prefs)
}
- log.Debugf("OperatorArrayTraverse skipping %v as its a %v", matchingNode, node.Tag)
+ log.Debugf("OperatorArrayTraverse skipping %v as its a %v", matchingNode, matchingNode.Tag)
return list.New(), nil
}
-func traverseMapWithIndices(context Context, candidate *CandidateNode, indices []*yaml.Node, prefs traversePreferences) (*list.List, error) {
+func traverseMapWithIndices(context Context, candidate *CandidateNode, indices []*CandidateNode, prefs traversePreferences) (*list.List, error) {
if len(indices) == 0 {
return traverseMap(context, candidate, createStringScalarNode(""), prefs, true)
}
@@ -175,15 +166,14 @@ func traverseMapWithIndices(context Context, candidate *CandidateNode, indices [
return matchingNodeMap, nil
}
-func traverseArrayWithIndices(candidate *CandidateNode, indices []*yaml.Node, prefs traversePreferences) (*list.List, error) {
+func traverseArrayWithIndices(node *CandidateNode, indices []*CandidateNode, prefs traversePreferences) (*list.List, error) {
log.Debug("traverseArrayWithIndices")
var newMatches = list.New()
- node := unwrapDoc(candidate.Node)
if len(indices) == 0 {
log.Debug("splatting")
var index int
for index = 0; index < len(node.Content); index = index + 1 {
- newMatches.PushBack(candidate.CreateChildInArray(index, node.Content[index]))
+ newMatches.PushBack(node.Content[index])
}
return newMatches, nil
@@ -206,7 +196,8 @@ func traverseArrayWithIndices(candidate *CandidateNode, indices []*yaml.Node, pr
node.Style = 0
}
- node.Content = append(node.Content, &yaml.Node{Tag: "!!null", Kind: yaml.ScalarNode, Value: "null"})
+ valueNode := createScalarNode(nil, "null")
+ node.AddChild(valueNode)
contentLength = len(node.Content)
}
@@ -218,16 +209,16 @@ func traverseArrayWithIndices(candidate *CandidateNode, indices []*yaml.Node, pr
return nil, fmt.Errorf("index [%v] out of range, array size is %v", index, contentLength)
}
- newMatches.PushBack(candidate.CreateChildInArray(index, node.Content[indexToUse]))
+ newMatches.PushBack(node.Content[indexToUse])
}
return newMatches, nil
}
-func keyMatches(key *yaml.Node, wantedKey string) bool {
+func keyMatches(key *CandidateNode, wantedKey string) bool {
return matchKey(key.Value, wantedKey)
}
-func traverseMap(context Context, matchingNode *CandidateNode, keyNode *yaml.Node, prefs traversePreferences, splat bool) (*list.List, error) {
+func traverseMap(context Context, matchingNode *CandidateNode, keyNode *CandidateNode, prefs traversePreferences, splat bool) (*list.List, error) {
var newMatches = orderedmap.NewOrderedMap()
err := doTraverseMap(newMatches, matchingNode, keyNode.Value, prefs, splat)
@@ -236,28 +227,24 @@ func traverseMap(context Context, matchingNode *CandidateNode, keyNode *yaml.Nod
}
if !splat && !prefs.DontAutoCreate && !context.DontAutoCreate && newMatches.Len() == 0 {
- log.Debugf("no matches, creating one")
+ log.Debugf("no matches, creating one for %v", NodeToString(keyNode))
//no matches, create one automagically
- valueNode := &yaml.Node{Tag: "!!null", Kind: yaml.ScalarNode, Value: "null"}
+ valueNode := matchingNode.CreateChild()
+ valueNode.Kind = ScalarNode
+ valueNode.Tag = "!!null"
+ valueNode.Value = "null"
- node := matchingNode.Node
-
- if len(node.Content) == 0 {
- node.Style = 0
+ if len(matchingNode.Content) == 0 {
+ matchingNode.Style = 0
}
- node.Content = append(node.Content, keyNode, valueNode)
+ keyNode, valueNode = matchingNode.AddKeyValueChild(keyNode, valueNode)
if prefs.IncludeMapKeys {
- log.Debug("including key")
- candidateNode := matchingNode.CreateChildInMap(keyNode, keyNode)
- candidateNode.IsMapKey = true
- newMatches.Set(fmt.Sprintf("keyOf-%v", candidateNode.GetKey()), candidateNode)
+ newMatches.Set(keyNode.GetKey(), keyNode)
}
if !prefs.DontIncludeMapValues {
- log.Debug("including value")
- candidateNode := matchingNode.CreateChildInMap(keyNode, valueNode)
- newMatches.Set(candidateNode.GetKey(), candidateNode)
+ newMatches.Set(valueNode.GetKey(), valueNode)
}
}
@@ -270,24 +257,21 @@ func traverseMap(context Context, matchingNode *CandidateNode, keyNode *yaml.Nod
return results, nil
}
-func doTraverseMap(newMatches *orderedmap.OrderedMap, candidate *CandidateNode, wantedKey string, prefs traversePreferences, splat bool) error {
+func doTraverseMap(newMatches *orderedmap.OrderedMap, node *CandidateNode, wantedKey string, prefs traversePreferences, splat bool) error {
// value.Content is a concatenated array of key, value,
// so keys are in the even indices, values in odd.
// merge aliases are defined first, but we only want to traverse them
// if we don't find a match directly on this node first.
- node := candidate.Node
-
var contents = node.Content
for index := 0; index < len(contents); index = index + 2 {
key := contents[index]
value := contents[index+1]
- log.Debug("checking %v (%v)", key.Value, key.Tag)
//skip the 'merge' tag, find a direct match first
if key.Tag == "!!merge" && !prefs.DontFollowAlias {
log.Debug("Merge anchor")
- err := traverseMergeAnchor(newMatches, candidate, value, wantedKey, prefs, splat)
+ err := traverseMergeAnchor(newMatches, value, wantedKey, prefs, splat)
if err != nil {
return err
}
@@ -295,14 +279,11 @@ func doTraverseMap(newMatches *orderedmap.OrderedMap, candidate *CandidateNode,
log.Debug("MATCHED")
if prefs.IncludeMapKeys {
log.Debug("including key")
- candidateNode := candidate.CreateChildInMap(key, key)
- candidateNode.IsMapKey = true
- newMatches.Set(fmt.Sprintf("keyOf-%v", candidateNode.GetKey()), candidateNode)
+ newMatches.Set(key.GetKey(), key)
}
if !prefs.DontIncludeMapValues {
log.Debug("including value")
- candidateNode := candidate.CreateChildInMap(key, value)
- newMatches.Set(candidateNode.GetKey(), candidateNode)
+ newMatches.Set(value.GetKey(), value)
}
}
}
@@ -310,17 +291,16 @@ func doTraverseMap(newMatches *orderedmap.OrderedMap, candidate *CandidateNode,
return nil
}
-func traverseMergeAnchor(newMatches *orderedmap.OrderedMap, originalCandidate *CandidateNode, value *yaml.Node, wantedKey string, prefs traversePreferences, splat bool) error {
+func traverseMergeAnchor(newMatches *orderedmap.OrderedMap, value *CandidateNode, wantedKey string, prefs traversePreferences, splat bool) error {
switch value.Kind {
- case yaml.AliasNode:
- if value.Alias.Kind != yaml.MappingNode {
+ case AliasNode:
+ if value.Alias.Kind != MappingNode {
return fmt.Errorf("can only use merge anchors with maps (!!map), but got %v", value.Alias.Tag)
}
- candidateNode := originalCandidate.CreateReplacement(value.Alias)
- return doTraverseMap(newMatches, candidateNode, wantedKey, prefs, splat)
- case yaml.SequenceNode:
+ return doTraverseMap(newMatches, value.Alias, wantedKey, prefs, splat)
+ case SequenceNode:
for _, childValue := range value.Content {
- err := traverseMergeAnchor(newMatches, originalCandidate, childValue, wantedKey, prefs, splat)
+ err := traverseMergeAnchor(newMatches, childValue, wantedKey, prefs, splat)
if err != nil {
return err
}
@@ -331,6 +311,6 @@ func traverseMergeAnchor(newMatches *orderedmap.OrderedMap, originalCandidate *C
func traverseArray(candidate *CandidateNode, operation *Operation, prefs traversePreferences) (*list.List, error) {
log.Debug("operation Value %v", operation.Value)
- indices := []*yaml.Node{{Value: operation.StringValue}}
+ indices := []*CandidateNode{{Value: operation.StringValue}}
return traverseArrayWithIndices(candidate, indices, prefs)
}
diff --git a/pkg/yqlib/operator_traverse_path_test.go b/pkg/yqlib/operator_traverse_path_test.go
index 5d62447c..55887ee7 100644
--- a/pkg/yqlib/operator_traverse_path_test.go
+++ b/pkg/yqlib/operator_traverse_path_test.go
@@ -35,6 +35,30 @@ steps:
`
var traversePathOperatorScenarios = []expressionScenario{
+ {
+ skipDoc: true,
+ description: "dynamically set parent and key",
+ expression: `.a.b.c = 3 | .a.b.c`,
+ expected: []string{
+ "D0, P[a b c], (!!int)::3\n",
+ },
+ },
+ {
+ skipDoc: true,
+ description: "dynamically set parent and key in array",
+ expression: `.a.b[0] = 3 | .a.b[0]`,
+ expected: []string{
+ "D0, P[a b 0], (!!int)::3\n",
+ },
+ },
+ {
+ skipDoc: true,
+ description: "dynamically set parent and key",
+ expression: `.a.b = ["x","y"] | .a.b[1]`,
+ expected: []string{
+ "D0, P[a b 1], (!!str)::y\n",
+ },
+ },
{
skipDoc: true,
description: "splat empty map",
@@ -62,7 +86,7 @@ var traversePathOperatorScenarios = []expressionScenario{
document: `blah: {}`,
expression: `.blah.cat = "cool"`,
expected: []string{
- "D0, P[], (doc)::blah:\n cat: cool\n",
+ "D0, P[], (!!map)::blah:\n cat: cool\n",
},
},
{
@@ -70,7 +94,7 @@ var traversePathOperatorScenarios = []expressionScenario{
document: `blah: []`,
expression: `.blah.0 = "cool"`,
expected: []string{
- "D0, P[], (doc)::blah:\n - cool\n",
+ "D0, P[], (!!map)::blah:\n - cool\n",
},
},
{
@@ -160,7 +184,7 @@ var traversePathOperatorScenarios = []expressionScenario{
document: `c: dog`,
expression: `.[.a.b] as $x | .`,
expected: []string{
- "D0, P[], (doc)::c: dog\n",
+ "D0, P[], (!!map)::c: dog\n",
},
},
{
@@ -278,15 +302,7 @@ var traversePathOperatorScenarios = []expressionScenario{
document: `{a: &cat {c: frog}, b: *cat}`,
expression: `.b[]`,
expected: []string{
- "D0, P[b c], (!!str)::frog\n",
- },
- },
- {
- skipDoc: true,
- document: `{a: &cat {c: frog}, b: *cat}`,
- expression: `.b[]`,
- expected: []string{
- "D0, P[b c], (!!str)::frog\n",
+ "D0, P[a c], (!!str)::frog\n",
},
},
{
@@ -294,7 +310,7 @@ var traversePathOperatorScenarios = []expressionScenario{
document: `{a: &cat {c: frog}, b: *cat}`,
expression: `.b.c`,
expected: []string{
- "D0, P[b c], (!!str)::frog\n",
+ "D0, P[a c], (!!str)::frog\n",
},
},
{
@@ -343,7 +359,7 @@ var traversePathOperatorScenarios = []expressionScenario{
document: mergeDocSample,
expression: `.foobar.a`,
expected: []string{
- "D0, P[foobar a], (!!str)::foo_a\n",
+ "D0, P[foo a], (!!str)::foo_a\n",
},
},
{
@@ -351,7 +367,7 @@ var traversePathOperatorScenarios = []expressionScenario{
document: mergeDocSample,
expression: `.foobar.c`,
expected: []string{
- "D0, P[foobar c], (!!str)::foo_c\n",
+ "D0, P[foo c], (!!str)::foo_c\n",
},
},
{
@@ -367,18 +383,8 @@ var traversePathOperatorScenarios = []expressionScenario{
document: mergeDocSample,
expression: `.foobar[]`,
expected: []string{
- "D0, P[foobar c], (!!str)::foo_c\n",
- "D0, P[foobar a], (!!str)::foo_a\n",
- "D0, P[foobar thing], (!!str)::foobar_thing\n",
- },
- },
- {
- skipDoc: true,
- document: mergeDocSample,
- expression: `.foobar[]`,
- expected: []string{
- "D0, P[foobar c], (!!str)::foo_c\n",
- "D0, P[foobar a], (!!str)::foo_a\n",
+ "D0, P[foo c], (!!str)::foo_c\n",
+ "D0, P[foo a], (!!str)::foo_a\n",
"D0, P[foobar thing], (!!str)::foobar_thing\n",
},
},
@@ -395,7 +401,7 @@ var traversePathOperatorScenarios = []expressionScenario{
document: mergeDocSample,
expression: `.foobarList.a`,
expected: []string{
- "D0, P[foobarList a], (!!str)::foo_a\n",
+ "D0, P[foo a], (!!str)::foo_a\n",
},
},
{
@@ -404,7 +410,7 @@ var traversePathOperatorScenarios = []expressionScenario{
document: mergeDocSample,
expression: `.foobarList.thing`,
expected: []string{
- "D0, P[foobarList thing], (!!str)::bar_thing\n",
+ "D0, P[bar thing], (!!str)::bar_thing\n",
},
},
{
@@ -420,7 +426,7 @@ var traversePathOperatorScenarios = []expressionScenario{
document: mergeDocSample,
expression: `.foobarList.b`,
expected: []string{
- "D0, P[foobarList b], (!!str)::bar_b\n",
+ "D0, P[bar b], (!!str)::bar_b\n",
},
},
{
@@ -428,20 +434,9 @@ var traversePathOperatorScenarios = []expressionScenario{
document: mergeDocSample,
expression: `.foobarList[]`,
expected: []string{
- "D0, P[foobarList b], (!!str)::bar_b\n",
- "D0, P[foobarList a], (!!str)::foo_a\n",
- "D0, P[foobarList thing], (!!str)::bar_thing\n",
- "D0, P[foobarList c], (!!str)::foobarList_c\n",
- },
- },
- {
- skipDoc: true,
- document: mergeDocSample,
- expression: `.foobarList[]`,
- expected: []string{
- "D0, P[foobarList b], (!!str)::bar_b\n",
- "D0, P[foobarList a], (!!str)::foo_a\n",
- "D0, P[foobarList thing], (!!str)::bar_thing\n",
+ "D0, P[bar b], (!!str)::bar_b\n",
+ "D0, P[foo a], (!!str)::foo_a\n",
+ "D0, P[bar thing], (!!str)::bar_thing\n",
"D0, P[foobarList c], (!!str)::foobarList_c\n",
},
},
@@ -494,15 +489,7 @@ var traversePathOperatorScenarios = []expressionScenario{
document: `{a: [a,b,c]}`,
expression: `.a[-1]`,
expected: []string{
- "D0, P[a -1], (!!str)::c\n",
- },
- },
- {
- skipDoc: true,
- document: `{a: [a,b,c]}`,
- expression: `.a[-1]`,
- expected: []string{
- "D0, P[a -1], (!!str)::c\n",
+ "D0, P[a 2], (!!str)::c\n",
},
},
{
@@ -510,15 +497,7 @@ var traversePathOperatorScenarios = []expressionScenario{
document: `{a: [a,b,c]}`,
expression: `.a[-2]`,
expected: []string{
- "D0, P[a -2], (!!str)::b\n",
- },
- },
- {
- skipDoc: true,
- document: `{a: [a,b,c]}`,
- expression: `.a[-2]`,
- expected: []string{
- "D0, P[a -2], (!!str)::b\n",
+ "D0, P[a 1], (!!str)::b\n",
},
},
{
diff --git a/pkg/yqlib/operator_union.go b/pkg/yqlib/operator_union.go
index 310d827e..7190504c 100644
--- a/pkg/yqlib/operator_union.go
+++ b/pkg/yqlib/operator_union.go
@@ -3,22 +3,22 @@ package yqlib
import "container/list"
func unionOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
- log.Debug("unionOperator")
- log.Debug("context: %v", NodesToString(context.MatchingNodes))
+ log.Debug("unionOperator--")
+ log.Debug("unionOperator: context: %v", NodesToString(context.MatchingNodes))
lhs, err := d.GetMatchingNodes(context, expressionNode.LHS)
if err != nil {
return Context{}, err
}
- log.Debug("lhs: %v", NodesToString(lhs.MatchingNodes))
- log.Debug("rhs input: %v", NodesToString(context.MatchingNodes))
- log.Debug("rhs: %v", expressionNode.RHS.Operation.toString())
+ log.Debug("unionOperator: lhs: %v", NodesToString(lhs.MatchingNodes))
+ log.Debug("unionOperator: rhs input: %v", NodesToString(context.MatchingNodes))
+ log.Debug("unionOperator: rhs: %v", expressionNode.RHS.Operation.toString())
rhs, err := d.GetMatchingNodes(context, expressionNode.RHS)
if err != nil {
return Context{}, err
}
- log.Debug("lhs: %v", lhs.ToString())
- log.Debug("rhs: %v", rhs.ToString())
+ log.Debug("unionOperator: lhs: %v", lhs.ToString())
+ log.Debug("unionOperator: rhs: %v", rhs.ToString())
results := lhs.ChildContext(list.New())
for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() {
@@ -33,12 +33,11 @@ func unionOperator(d *dataTreeNavigator, context Context, expressionNode *Expres
for el := rhs.MatchingNodes.Front(); el != nil; el = el.Next() {
node := el.Value.(*CandidateNode)
- log.Debug("processing %v", NodeToString(node))
+ log.Debug("union operator rhs: processing %v", NodeToString(node))
results.MatchingNodes.PushBack(node)
}
}
- log.Debug("and lets print it out")
- log.Debug("all together: %v", results.ToString())
+ log.Debug("union operator: all together: %v", results.ToString())
return results, nil
}
diff --git a/pkg/yqlib/operator_union_test.go b/pkg/yqlib/operator_union_test.go
index 4b98ac06..87247862 100644
--- a/pkg/yqlib/operator_union_test.go
+++ b/pkg/yqlib/operator_union_test.go
@@ -10,7 +10,7 @@ var unionOperatorScenarios = []expressionScenario{
document: "{}",
expression: `(.a, .b.c) as $x | .`,
expected: []string{
- "D0, P[], (doc)::{}\n",
+ "D0, P[], (!!map)::{}\n",
},
},
{
diff --git a/pkg/yqlib/operator_unique.go b/pkg/yqlib/operator_unique.go
index a1c5216c..2ba69ce0 100644
--- a/pkg/yqlib/operator_unique.go
+++ b/pkg/yqlib/operator_unique.go
@@ -5,7 +5,6 @@ import (
"fmt"
"github.com/elliotchance/orderedmap"
- yaml "gopkg.in/yaml.v3"
)
func unique(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
@@ -22,15 +21,13 @@ func uniqueBy(d *dataTreeNavigator, context Context, expressionNode *ExpressionN
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- candidateNode := unwrapDoc(candidate.Node)
- if candidateNode.Kind != yaml.SequenceNode {
+ if candidate.Kind != SequenceNode {
return Context{}, fmt.Errorf("Only arrays are supported for unique")
}
var newMatches = orderedmap.NewOrderedMap()
- for _, node := range candidateNode.Content {
- child := &CandidateNode{Node: node}
+ for _, child := range candidate.Content {
rhs, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(child), expressionNode.RHS)
if err != nil {
@@ -42,21 +39,21 @@ func uniqueBy(d *dataTreeNavigator, context Context, expressionNode *ExpressionN
if rhs.MatchingNodes.Len() > 0 {
first := rhs.MatchingNodes.Front()
keyCandidate := first.Value.(*CandidateNode)
- keyValue = keyCandidate.Node.Value
+ keyValue = keyCandidate.Value
}
_, exists := newMatches.Get(keyValue)
if !exists {
- newMatches.Set(keyValue, child.Node)
+ newMatches.Set(keyValue, child)
}
}
- resultNode := &yaml.Node{Kind: yaml.SequenceNode, Tag: "!!seq"}
+ resultNode := candidate.CreateReplacementWithComments(SequenceNode, "!!seq", candidate.Style)
for el := newMatches.Front(); el != nil; el = el.Next() {
- resultNode.Content = append(resultNode.Content, el.Value.(*yaml.Node))
+ resultNode.AddChild(el.Value.(*CandidateNode))
}
- results.PushBack(candidate.CreateReplacementWithDocWrappers(resultNode))
+ results.PushBack(resultNode)
}
return context.ChildContext(results), nil
diff --git a/pkg/yqlib/operator_unique_test.go b/pkg/yqlib/operator_unique_test.go
index f0c44533..fe28de56 100644
--- a/pkg/yqlib/operator_unique_test.go
+++ b/pkg/yqlib/operator_unique_test.go
@@ -11,7 +11,7 @@ var uniqueOperatorScenarios = []expressionScenario{
document: `[2,1,3,2]`,
expression: `unique`,
expected: []string{
- "D0, P[], (!!seq)::- 2\n- 1\n- 3\n",
+ "D0, P[], (!!seq)::[2, 1, 3]\n",
},
},
{
@@ -20,7 +20,7 @@ var uniqueOperatorScenarios = []expressionScenario{
document: `[~,null, ~, null]`,
expression: `unique`,
expected: []string{
- "D0, P[], (!!seq)::- ~\n- null\n",
+ "D0, P[], (!!seq)::[~, null]\n",
},
},
{
@@ -29,7 +29,7 @@ var uniqueOperatorScenarios = []expressionScenario{
document: `[~,null, ~, null]`,
expression: `unique_by(tag)`,
expected: []string{
- "D0, P[], (!!seq)::- ~\n",
+ "D0, P[], (!!seq)::[~]\n",
},
},
{
@@ -37,7 +37,7 @@ var uniqueOperatorScenarios = []expressionScenario{
document: `[{name: harry, pet: cat}, {name: billy, pet: dog}, {name: harry, pet: dog}]`,
expression: `unique_by(.name)`,
expected: []string{
- "D0, P[], (!!seq)::- {name: harry, pet: cat}\n- {name: billy, pet: dog}\n",
+ "D0, P[], (!!seq)::[{name: harry, pet: cat}, {name: billy, pet: dog}]\n",
},
},
{
@@ -45,7 +45,7 @@ var uniqueOperatorScenarios = []expressionScenario{
document: `[{name: harry, pet: cat}, {pet: fish}, {name: harry, pet: dog}]`,
expression: `unique_by(.name)`,
expected: []string{
- "D0, P[], (!!seq)::- {name: harry, pet: cat}\n- {pet: fish}\n",
+ "D0, P[], (!!seq)::[{name: harry, pet: cat}, {pet: fish}]\n",
},
},
{
@@ -53,7 +53,7 @@ var uniqueOperatorScenarios = []expressionScenario{
document: `[{name: harry, pet: cat}, {pet: fish}, {name: harry, pet: dog}]`,
expression: `unique_by(.cat.dog)`,
expected: []string{
- "D0, P[], (!!seq)::- {name: harry, pet: cat}\n",
+ "D0, P[], (!!seq)::[{name: harry, pet: cat}]\n",
},
},
{
@@ -61,7 +61,7 @@ var uniqueOperatorScenarios = []expressionScenario{
document: "# abc\n[{name: harry, pet: cat}, {pet: fish}, {name: harry, pet: dog}]\n# xyz",
expression: `unique_by(.name)`,
expected: []string{
- "D0, P[], (!!seq)::# abc\n- {name: harry, pet: cat}\n- {pet: fish}\n# xyz\n",
+ "D0, P[], (!!seq)::# abc\n[{name: harry, pet: cat}, {pet: fish}]\n# xyz\n",
},
},
}
diff --git a/pkg/yqlib/operator_value.go b/pkg/yqlib/operator_value.go
index b4296acc..740893af 100644
--- a/pkg/yqlib/operator_value.go
+++ b/pkg/yqlib/operator_value.go
@@ -7,22 +7,16 @@ func referenceOperator(d *dataTreeNavigator, context Context, expressionNode *Ex
}
func valueOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
- log.Debug("value = %v", expressionNode.Operation.CandidateNode.Node.Value)
+ log.Debug("value = %v", expressionNode.Operation.CandidateNode.Value)
if context.MatchingNodes.Len() == 0 {
- clone, err := expressionNode.Operation.CandidateNode.Copy()
- if err != nil {
- return Context{}, err
- }
+ clone := expressionNode.Operation.CandidateNode.Copy()
return context.SingleChildContext(clone), nil
}
var results = list.New()
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
- clone, err := expressionNode.Operation.CandidateNode.Copy()
- if err != nil {
- return Context{}, err
- }
+ clone := expressionNode.Operation.CandidateNode.Copy()
results.PushBack(clone)
}
diff --git a/pkg/yqlib/operator_variables.go b/pkg/yqlib/operator_variables.go
index 32248ffc..01a946ec 100644
--- a/pkg/yqlib/operator_variables.go
+++ b/pkg/yqlib/operator_variables.go
@@ -72,10 +72,7 @@ func variableLoopSingleChild(d *dataTreeNavigator, context Context, originalExp
if prefs.IsReference {
variableValue.PushBack(el.Value)
} else {
- candidateCopy, err := el.Value.(*CandidateNode).Copy()
- if err != nil {
- return Context{}, err
- }
+ candidateCopy := el.Value.(*CandidateNode).Copy()
variableValue.PushBack(candidateCopy)
}
newContext := context.ChildContext(context.MatchingNodes)
diff --git a/pkg/yqlib/operator_variables_test.go b/pkg/yqlib/operator_variables_test.go
index f1555f28..bc84f604 100644
--- a/pkg/yqlib/operator_variables_test.go
+++ b/pkg/yqlib/operator_variables_test.go
@@ -10,7 +10,7 @@ var variableOperatorScenarios = []expressionScenario{
document: `{}`,
expression: `.a.b as $foo | .`,
expected: []string{
- "D0, P[], (doc)::{}\n",
+ "D0, P[], (!!map)::{}\n",
},
},
{
@@ -76,7 +76,7 @@ var variableOperatorScenarios = []expressionScenario{
document: "a: a_value\nb: b_value",
expression: `.a as $x | .b as $y | .b = $x | .a = $y`,
expected: []string{
- "D0, P[], (doc)::a: b_value\nb: a_value\n",
+ "D0, P[], (!!map)::a: b_value\nb: a_value\n",
},
},
{
@@ -85,7 +85,7 @@ var variableOperatorScenarios = []expressionScenario{
document: `a: {b: thing, c: something}`,
expression: `.a.b ref $x | $x = "new" | $x style="double"`,
expected: []string{
- "D0, P[], (doc)::a: {b: \"new\", c: something}\n",
+ "D0, P[], (!!map)::a: {b: \"new\", c: something}\n",
},
},
}
diff --git a/pkg/yqlib/operator_with_test.go b/pkg/yqlib/operator_with_test.go
index 04f184c2..36855df1 100644
--- a/pkg/yqlib/operator_with_test.go
+++ b/pkg/yqlib/operator_with_test.go
@@ -8,7 +8,7 @@ var withOperatorScenarios = []expressionScenario{
document: `a: {deeply: {nested: value}}`,
expression: `with(.a.deeply.nested; . = "newValue" | . style="single")`,
expected: []string{
- "D0, P[], (doc)::a: {deeply: {nested: 'newValue'}}\n",
+ "D0, P[], (!!map)::a: {deeply: {nested: 'newValue'}}\n",
},
},
{
@@ -16,7 +16,7 @@ var withOperatorScenarios = []expressionScenario{
document: `a: {deeply: {nested: value, other: thing}}`,
expression: `with(.a.deeply; .nested = "newValue" | .other= "newThing")`,
expected: []string{
- "D0, P[], (doc)::a: {deeply: {nested: newValue, other: newThing}}\n",
+ "D0, P[], (!!map)::a: {deeply: {nested: newValue, other: newThing}}\n",
},
},
{
@@ -25,7 +25,7 @@ var withOperatorScenarios = []expressionScenario{
document: `myArray: [{a: apple},{a: banana}]`,
expression: `with(.myArray[]; .b = .a + " yum")`,
expected: []string{
- "D0, P[], (doc)::myArray: [{a: apple, b: apple yum}, {a: banana, b: banana yum}]\n",
+ "D0, P[], (!!map)::myArray: [{a: apple, b: apple yum}, {a: banana, b: banana yum}]\n",
},
},
{
@@ -35,7 +35,7 @@ var withOperatorScenarios = []expressionScenario{
document: `myArray: [{a: apple},{a: banana}]`,
expression: `with(.myArray[]; .a += .a)`,
expected: []string{
- "D0, P[], (doc)::myArray: [{a: appleapple}, {a: bananabanana}]\n",
+ "D0, P[], (!!map)::myArray: [{a: appleapple}, {a: bananabanana}]\n",
},
},
}
diff --git a/pkg/yqlib/operators.go b/pkg/yqlib/operators.go
index ea0574d6..f4f33e55 100644
--- a/pkg/yqlib/operators.go
+++ b/pkg/yqlib/operators.go
@@ -6,7 +6,6 @@ import (
"github.com/jinzhu/copier"
logging "gopkg.in/op/go-logging.v1"
- "gopkg.in/yaml.v3"
)
type operatorHandler func(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error)
@@ -37,10 +36,7 @@ func compoundAssignFunction(d *dataTreeNavigator, context Context, expressionNod
for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() {
candidate := el.Value.(*CandidateNode)
- clone, err := candidate.Copy()
- if err != nil {
- return Context{}, err
- }
+ clone := candidate.Copy()
valueCopyExp := &ExpressionNode{Operation: &Operation{OperationType: referenceOpType, CandidateNode: clone}}
valueExpression := &ExpressionNode{Operation: &Operation{OperationType: referenceOpType, CandidateNode: candidate}}
@@ -55,13 +51,6 @@ func compoundAssignFunction(d *dataTreeNavigator, context Context, expressionNod
return context, nil
}
-func unwrapDoc(node *yaml.Node) *yaml.Node {
- if node.Kind == yaml.DocumentNode {
- return node.Content[0]
- }
- return node
-}
-
func emptyOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
context.MatchingNodes = list.New()
return context, nil
@@ -187,8 +176,13 @@ func createBooleanCandidate(owner *CandidateNode, value bool) *CandidateNode {
if !value {
valString = "false"
}
- node := &yaml.Node{Kind: yaml.ScalarNode, Value: valString, Tag: "!!bool"}
- return owner.CreateReplacement(node)
+ noob := owner.CreateReplacement(ScalarNode, "!!bool", valString)
+ if owner.IsMapKey {
+ noob.IsMapKey = false
+ noob.Key = owner
+ }
+
+ return noob
}
func createTraversalTree(path []interface{}, traversePrefs traversePreferences, targetKey bool) *ExpressionNode {
diff --git a/pkg/yqlib/operators_test.go b/pkg/yqlib/operators_test.go
index ff6e6f62..56340cbb 100644
--- a/pkg/yqlib/operators_test.go
+++ b/pkg/yqlib/operators_test.go
@@ -14,7 +14,6 @@ import (
"github.com/mikefarah/yq/v4/test"
logging "gopkg.in/op/go-logging.v1"
- yaml "gopkg.in/yaml.v3"
)
type expressionScenario struct {
@@ -81,10 +80,11 @@ func testScenario(t *testing.T, s *expressionScenario) {
}
} else {
candidateNode := &CandidateNode{
- Document: 0,
- Filename: "",
- Node: &yaml.Node{Tag: "!!null", Kind: yaml.ScalarNode},
- FileIndex: 0,
+ document: 0,
+ filename: "",
+ Tag: "!!null",
+ Kind: ScalarNode,
+ fileIndex: 0,
}
inputs.PushBack(candidateNode)
@@ -131,6 +131,7 @@ func testScenario(t *testing.T, s *expressionScenario) {
func resultToString(t *testing.T, n *CandidateNode) string {
var valueBuffer bytes.Buffer
+ log.Debugf("printing result %v", NodeToString(n))
printer := NewSimpleYamlPrinter(bufio.NewWriter(&valueBuffer), YamlOutputFormat, true, false, 4, true)
err := printer.PrintResults(n.AsList())
@@ -139,13 +140,11 @@ func resultToString(t *testing.T, n *CandidateNode) string {
return ""
}
- tag := n.Node.Tag
- if n.Node.Kind == yaml.DocumentNode {
- tag = "doc"
- } else if n.Node.Kind == yaml.AliasNode {
+ tag := n.Tag
+ if n.Kind == AliasNode {
tag = "alias"
}
- return fmt.Sprintf(`D%v, P%v, (%v)::%v`, n.Document, n.Path, tag, valueBuffer.String())
+ return fmt.Sprintf(`D%v, P%v, (%v)::%v`, n.GetDocument(), n.GetPath(), tag, valueBuffer.String())
}
func resultsToString(t *testing.T, results *list.List) []string {
@@ -359,10 +358,11 @@ func documentOutput(t *testing.T, w *bufio.Writer, s expressionScenario, formatt
}
} else {
candidateNode := &CandidateNode{
- Document: 0,
- Filename: "",
- Node: &yaml.Node{Tag: "!!null", Kind: yaml.ScalarNode},
- FileIndex: 0,
+ document: 0,
+ filename: "",
+ Tag: "!!null",
+ Kind: ScalarNode,
+ fileIndex: 0,
}
inputs.PushBack(candidateNode)
diff --git a/pkg/yqlib/ordered_map.go b/pkg/yqlib/ordered_map.go
deleted file mode 100644
index a783423b..00000000
--- a/pkg/yqlib/ordered_map.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package yqlib
-
-// orderedMap allows to marshal and unmarshal JSON and YAML values keeping the
-// order of keys and values in a map or an object.
-type orderedMap struct {
- // if this is an object, kv != nil. If this is not an object, kv == nil.
- kv []orderedMapKV
- altVal interface{}
-}
-
-type orderedMapKV struct {
- K string
- V orderedMap
-}
diff --git a/pkg/yqlib/ordered_map_json.go b/pkg/yqlib/ordered_map_json.go
deleted file mode 100644
index 94a1d780..00000000
--- a/pkg/yqlib/ordered_map_json.go
+++ /dev/null
@@ -1,83 +0,0 @@
-package yqlib
-
-import (
- "bytes"
- "encoding/json"
- "errors"
- "io"
-)
-
-func (o *orderedMap) UnmarshalJSON(data []byte) error {
- switch data[0] {
- case '{':
- // initialise so that even if the object is empty it is not nil
- o.kv = []orderedMapKV{}
-
- // create decoder
- dec := json.NewDecoder(bytes.NewReader(data))
- _, err := dec.Token() // open object
- if err != nil {
- return err
- }
-
- // cycle through k/v
- var tok json.Token
- for tok, err = dec.Token(); err == nil; tok, err = dec.Token() {
- // we can expect two types: string or Delim. Delim automatically means
- // that it is the closing bracket of the object, whereas string means
- // that there is another key.
- if _, ok := tok.(json.Delim); ok {
- break
- }
- kv := orderedMapKV{
- K: tok.(string),
- }
- if err := dec.Decode(&kv.V); err != nil {
- return err
- }
- o.kv = append(o.kv, kv)
- }
- // unexpected error
- if err != nil && !errors.Is(err, io.EOF) {
- return err
- }
- return nil
- case '[':
- var res []*orderedMap
- if err := json.Unmarshal(data, &res); err != nil {
- return err
- }
- o.altVal = res
- o.kv = nil
- return nil
- }
-
- return json.Unmarshal(data, &o.altVal)
-}
-
-func (o orderedMap) MarshalJSON() ([]byte, error) {
- buf := new(bytes.Buffer)
- enc := json.NewEncoder(buf)
- enc.SetEscapeHTML(false) // do not escape html chars e.g. &, <, >
- if o.kv == nil {
- if err := enc.Encode(o.altVal); err != nil {
- return nil, err
- }
- return buf.Bytes(), nil
- }
- buf.WriteByte('{')
- for idx, el := range o.kv {
- if err := enc.Encode(el.K); err != nil {
- return nil, err
- }
- buf.WriteByte(':')
- if err := enc.Encode(el.V); err != nil {
- return nil, err
- }
- if idx != len(o.kv)-1 {
- buf.WriteByte(',')
- }
- }
- buf.WriteByte('}')
- return buf.Bytes(), nil
-}
diff --git a/pkg/yqlib/ordered_map_yaml.go b/pkg/yqlib/ordered_map_yaml.go
deleted file mode 100644
index b3c49442..00000000
--- a/pkg/yqlib/ordered_map_yaml.go
+++ /dev/null
@@ -1,79 +0,0 @@
-package yqlib
-
-import (
- "fmt"
-
- yaml "gopkg.in/yaml.v3"
-)
-
-func (o *orderedMap) UnmarshalYAML(node *yaml.Node) error {
- switch node.Kind {
- case yaml.DocumentNode:
- if len(node.Content) == 0 {
- return nil
- }
- return o.UnmarshalYAML(node.Content[0])
- case yaml.AliasNode:
- return o.UnmarshalYAML(node.Alias)
- case yaml.ScalarNode:
- return node.Decode(&o.altVal)
- case yaml.MappingNode:
- // set kv to non-nil
- o.kv = []orderedMapKV{}
- for i := 0; i < len(node.Content); i += 2 {
- var key string
- var val orderedMap
- if err := node.Content[i].Decode(&key); err != nil {
- return err
- }
- if err := node.Content[i+1].Decode(&val); err != nil {
- return err
- }
- o.kv = append(o.kv, orderedMapKV{
- K: key,
- V: val,
- })
- }
- return nil
- case yaml.SequenceNode:
- // note that this has to be a pointer, so that nulls can be represented.
- var res []*orderedMap
- if err := node.Decode(&res); err != nil {
- return err
- }
- o.altVal = res
- o.kv = nil
- return nil
- case 0:
- // null
- o.kv = nil
- o.altVal = nil
- return nil
- default:
- return fmt.Errorf("orderedMap: invalid yaml node")
- }
-}
-
-func (o *orderedMap) MarshalYAML() (interface{}, error) {
- // fast path: kv is nil, use altVal
- if o.kv == nil {
- return o.altVal, nil
- }
- content := make([]*yaml.Node, 0, len(o.kv)*2)
- for _, val := range o.kv {
- n := new(yaml.Node)
- if err := n.Encode(val.V); err != nil {
- return nil, err
- }
- content = append(content, &yaml.Node{
- Kind: yaml.ScalarNode,
- Tag: "!!str",
- Value: val.K,
- }, n)
- }
- return &yaml.Node{
- Kind: yaml.MappingNode,
- Tag: "!!map",
- Content: content,
- }, nil
-}
diff --git a/pkg/yqlib/printer.go b/pkg/yqlib/printer.go
index 8388b0d9..decae59c 100644
--- a/pkg/yqlib/printer.go
+++ b/pkg/yqlib/printer.go
@@ -7,8 +7,6 @@ import (
"fmt"
"io"
"regexp"
-
- yaml "gopkg.in/yaml.v3"
)
type Printer interface {
@@ -97,7 +95,7 @@ func (p *resultsPrinter) PrintedAnything() bool {
return p.printedMatches
}
-func (p *resultsPrinter) printNode(node *yaml.Node, writer io.Writer) error {
+func (p *resultsPrinter) printNode(node *CandidateNode, writer io.Writer) error {
p.printedMatches = p.printedMatches || (node.Tag != "!!null" &&
(node.Tag != "!!bool" || node.Value != "false"))
return p.encoder.Encode(writer, node)
@@ -133,15 +131,15 @@ func (p *resultsPrinter) PrintResults(matchingNodes *list.List) error {
if p.firstTimePrinting {
node := matchingNodes.Front().Value.(*CandidateNode)
- p.previousDocIndex = node.Document
- p.previousFileIndex = node.FileIndex
+ p.previousDocIndex = node.GetDocument()
+ p.previousFileIndex = node.GetFileIndex()
p.firstTimePrinting = false
}
for el := matchingNodes.Front(); el != nil; el = el.Next() {
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", p.firstTimePrinting, p.previousDocIndex)
log.Debug("%v", NodeToString(mappedDoc))
writer, errorWriting := p.printerWriter.GetWriter(mappedDoc)
if errorWriting != nil {
@@ -151,7 +149,7 @@ func (p *resultsPrinter) PrintResults(matchingNodes *list.List) error {
commentsStartWithSepExp := regexp.MustCompile(`^\$yqDocSeparator\$`)
commentStartsWithSeparator := commentsStartWithSepExp.MatchString(mappedDoc.LeadingContent)
- if (p.previousDocIndex != mappedDoc.Document || p.previousFileIndex != mappedDoc.FileIndex) && !commentStartsWithSeparator {
+ if (p.previousDocIndex != mappedDoc.GetDocument() || p.previousFileIndex != mappedDoc.GetFileIndex()) && !commentStartsWithSeparator {
if err := p.encoder.PrintDocumentSeparator(writer); err != nil {
return err
}
@@ -167,11 +165,7 @@ func (p *resultsPrinter) PrintResults(matchingNodes *list.List) error {
return err
}
- if err := p.printNode(mappedDoc.Node, destination); err != nil {
- return err
- }
-
- if err := p.encoder.PrintLeadingContent(destination, mappedDoc.TrailingContent); err != nil {
+ if err := p.printNode(mappedDoc, destination); err != nil {
return err
}
@@ -191,7 +185,7 @@ func (p *resultsPrinter) PrintResults(matchingNodes *list.List) error {
}
}
- p.previousDocIndex = mappedDoc.Document
+ p.previousDocIndex = mappedDoc.GetDocument()
if err := writer.Flush(); err != nil {
return err
}
diff --git a/pkg/yqlib/printer_test.go b/pkg/yqlib/printer_test.go
index fd6068f7..75b6e5ff 100644
--- a/pkg/yqlib/printer_test.go
+++ b/pkg/yqlib/printer_test.go
@@ -125,20 +125,20 @@ func TestPrinterMultipleFilesInSequence(t *testing.T) {
el := inputs.Front()
elNode := el.Value.(*CandidateNode)
- elNode.Document = 0
- elNode.FileIndex = 0
+ elNode.document = 0
+ elNode.fileIndex = 0
sample1 := nodeToList(elNode)
el = el.Next()
elNode = el.Value.(*CandidateNode)
- elNode.Document = 0
- elNode.FileIndex = 1
+ elNode.document = 0
+ elNode.fileIndex = 1
sample2 := nodeToList(elNode)
el = el.Next()
elNode = el.Value.(*CandidateNode)
- elNode.Document = 0
- elNode.FileIndex = 2
+ elNode.document = 0
+ elNode.fileIndex = 2
sample3 := nodeToList(elNode)
err = printer.PrintResults(sample1)
@@ -172,22 +172,22 @@ func TestPrinterMultipleFilesInSequenceWithLeadingContent(t *testing.T) {
el := inputs.Front()
elNode := el.Value.(*CandidateNode)
- elNode.Document = 0
- elNode.FileIndex = 0
+ elNode.document = 0
+ elNode.fileIndex = 0
elNode.LeadingContent = "# go cats\n$yqDocSeparator$\n"
sample1 := nodeToList(elNode)
el = el.Next()
elNode = el.Value.(*CandidateNode)
- elNode.Document = 0
- elNode.FileIndex = 1
+ elNode.document = 0
+ elNode.fileIndex = 1
elNode.LeadingContent = "$yqDocSeparator$\n"
sample2 := nodeToList(elNode)
el = el.Next()
elNode = el.Value.(*CandidateNode)
- elNode.Document = 0
- elNode.FileIndex = 2
+ elNode.document = 0
+ elNode.fileIndex = 2
elNode.LeadingContent = "$yqDocSeparator$\n# cool\n"
sample3 := nodeToList(elNode)
diff --git a/pkg/yqlib/printer_writer.go b/pkg/yqlib/printer_writer.go
index daa1078e..d1b1e336 100644
--- a/pkg/yqlib/printer_writer.go
+++ b/pkg/yqlib/printer_writer.go
@@ -6,8 +6,6 @@ import (
"io"
"os"
"regexp"
-
- "gopkg.in/yaml.v3"
)
type PrinterWriter interface {
@@ -56,17 +54,16 @@ func NewMultiPrinterWriter(expression *ExpressionNode, format PrinterOutputForma
func (sp *multiPrintWriter) GetWriter(node *CandidateNode) (*bufio.Writer, error) {
name := ""
- indexVariableNode := yaml.Node{Kind: yaml.ScalarNode, Tag: "!!int", Value: fmt.Sprintf("%v", sp.index)}
- indexVariableCandidate := CandidateNode{Node: &indexVariableNode}
+ indexVariableNode := CandidateNode{Kind: ScalarNode, Tag: "!!int", Value: fmt.Sprintf("%v", sp.index)}
context := Context{MatchingNodes: node.AsList()}
- context.SetVariable("index", indexVariableCandidate.AsList())
+ context.SetVariable("index", indexVariableNode.AsList())
result, err := sp.treeNavigator.GetMatchingNodes(context, sp.nameExpression)
if err != nil {
return nil, err
}
if result.MatchingNodes.Len() > 0 {
- name = result.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
+ name = result.MatchingNodes.Front().Value.(*CandidateNode).Value
}
var extensionRegexp = regexp.MustCompile(`\.[a-zA-Z0-9]+$`)
if !extensionRegexp.MatchString(name) {
diff --git a/pkg/yqlib/properties_test.go b/pkg/yqlib/properties_test.go
index dcae4121..8ca996b0 100644
--- a/pkg/yqlib/properties_test.go
+++ b/pkg/yqlib/properties_test.go
@@ -98,6 +98,16 @@ const expectedDecodedYaml = `person:
- pizza
`
+const expectedDecodedPersonYaml = `# block comments come through
+# comments on values appear
+name: Mike Wazowski
+pets:
+ # comments on array values appear
+ - cat
+food:
+ - pizza
+`
+
const expectedPropertiesNoComments = `person.name = Mike Wazowski
person.pets.0 = cat
person.food.0 = pizza
@@ -147,6 +157,32 @@ var propertyScenarios = []formatScenario{
expected: expectedDecodedYaml,
scenarioType: "decode",
},
+
+ {
+ skipDoc: true,
+ description: "Decode properties - keeps key information",
+ input: expectedPropertiesUnwrapped,
+ expression: ".person.name | key",
+ expected: "name\n",
+ scenarioType: "decode",
+ },
+ {
+ skipDoc: true,
+ description: "Decode properties - keeps parent information",
+ input: expectedPropertiesUnwrapped,
+ expression: ".person.name | parent",
+ expected: expectedDecodedPersonYaml,
+ scenarioType: "decode",
+ },
+ {
+ skipDoc: true,
+ description: "Decode properties - keeps path information",
+ input: expectedPropertiesUnwrapped,
+ expression: ".person.name | path",
+ expected: "- person\n- name\n",
+ scenarioType: "decode",
+ },
+
{
description: "Decode properties - array should be a map",
subdescription: "If you have a numeric map key in your property files, use array_to_map to convert them to maps.",
diff --git a/pkg/yqlib/recipes_test.go b/pkg/yqlib/recipes_test.go
index c04fa1de..2040eecf 100644
--- a/pkg/yqlib/recipes_test.go
+++ b/pkg/yqlib/recipes_test.go
@@ -33,7 +33,7 @@ var recipes = []expressionScenario{
"See the [assign](https://mikefarah.gitbook.io/yq/operators/assign-update) and [add](https://mikefarah.gitbook.io/yq/operators/add) operators for more information.",
},
expected: []string{
- "D0, P[], (doc)::[{name: Foo, numBuckets: 1}, {name: Bar, numBuckets: 0}]\n",
+ "D0, P[], (!!seq)::[{name: Foo, numBuckets: 1}, {name: Bar, numBuckets: 0}]\n",
},
},
{
@@ -48,7 +48,7 @@ var recipes = []expressionScenario{
"See the [with](https://mikefarah.gitbook.io/yq/operators/with) operator for more information and examples.",
},
expected: []string{
- "D0, P[], (doc)::myArray: [{name: Foo - cat, type: cat}, {name: Bar - dog, type: dog}]\n",
+ "D0, P[], (!!map)::myArray: [{name: Foo - cat, type: cat}, {name: Bar - dog, type: dog}]\n",
},
},
{
@@ -61,7 +61,7 @@ var recipes = []expressionScenario{
"So, we use `|=` to update `.myArray`. This is the same as doing `.myArray = (.myArray | sort_by(.numBuckets))`",
},
expected: []string{
- "D0, P[], (doc)::myArray: [{name: Bar, numBuckets: 0}, {name: Foo, numBuckets: 1}]\n",
+ "D0, P[], (!!map)::myArray: [{name: Bar, numBuckets: 0}, {name: Foo, numBuckets: 1}]\n",
},
},
{
diff --git a/pkg/yqlib/stream_evaluator.go b/pkg/yqlib/stream_evaluator.go
index ef78ca98..0c9ad6dd 100644
--- a/pkg/yqlib/stream_evaluator.go
+++ b/pkg/yqlib/stream_evaluator.go
@@ -6,8 +6,6 @@ import (
"fmt"
"io"
"os"
-
- yaml "gopkg.in/yaml.v3"
)
// A yaml expression evaluator that runs the expression multiple times for each given yaml document.
@@ -33,12 +31,7 @@ func (s *streamEvaluator) EvaluateNew(expression string, printer Printer) error
if err != nil {
return err
}
- candidateNode := &CandidateNode{
- Document: 0,
- Filename: "",
- Node: &yaml.Node{Kind: yaml.DocumentNode, Content: []*yaml.Node{{Tag: "!!null", Kind: yaml.ScalarNode}}},
- FileIndex: 0,
- }
+ candidateNode := createScalarNode(nil, "")
inputList := list.New()
inputList.PushBack(candidateNode)
@@ -98,9 +91,9 @@ func (s *streamEvaluator) Evaluate(filename string, reader io.Reader, node *Expr
} else if errorReading != nil {
return currentIndex, fmt.Errorf("bad file '%v': %w", filename, errorReading)
}
- candidateNode.Document = currentIndex
- candidateNode.Filename = filename
- candidateNode.FileIndex = s.fileIndex
+ candidateNode.document = currentIndex
+ candidateNode.filename = filename
+ candidateNode.fileIndex = s.fileIndex
inputList := list.New()
inputList.PushBack(candidateNode)
diff --git a/pkg/yqlib/string_evaluator.go b/pkg/yqlib/string_evaluator.go
index 59d451ca..40970ffe 100644
--- a/pkg/yqlib/string_evaluator.go
+++ b/pkg/yqlib/string_evaluator.go
@@ -53,8 +53,8 @@ func (s *stringEvaluator) Evaluate(expression string, input string, encoder Enco
} else if errorReading != nil {
return "", fmt.Errorf("bad input '%v': %w", input, errorReading)
}
- candidateNode.Document = currentIndex
- candidateNode.FileIndex = s.fileIndex
+ candidateNode.document = currentIndex
+ candidateNode.fileIndex = s.fileIndex
inputList := list.New()
inputList.PushBack(candidateNode)
diff --git a/pkg/yqlib/toml_test.go b/pkg/yqlib/toml_test.go
index f55d2fdf..2e0765dc 100644
--- a/pkg/yqlib/toml_test.go
+++ b/pkg/yqlib/toml_test.go
@@ -94,6 +94,30 @@ var tomlScenarios = []formatScenario{
expected: "person:\n name: hello\n address: 12 cat st\n",
scenarioType: "decode",
},
+ {
+ skipDoc: true,
+ description: "Parse: include key information",
+ input: "person.name = \"hello\"\nperson.address = \"12 cat st\"\n",
+ expression: ".person.name | key",
+ expected: "name\n",
+ scenarioType: "roundtrip",
+ },
+ {
+ skipDoc: true,
+ description: "Parse: include parent information",
+ input: "person.name = \"hello\"\nperson.address = \"12 cat st\"\n",
+ expression: ".person.name | parent",
+ expected: "name: hello\naddress: 12 cat st\n",
+ scenarioType: "decode",
+ },
+ {
+ skipDoc: true,
+ description: "Parse: include path information",
+ input: "person.name = \"hello\"\nperson.address = \"12 cat st\"\n",
+ expression: ".person.name | path",
+ expected: "- person\n- name\n",
+ scenarioType: "decode",
+ },
{
description: "Encode: Scalar",
input: "person.name = \"hello\"\nperson.address = \"12 cat st\"\n",
diff --git a/pkg/yqlib/utils.go b/pkg/yqlib/utils.go
index d800e3b1..3ce2de12 100644
--- a/pkg/yqlib/utils.go
+++ b/pkg/yqlib/utils.go
@@ -51,9 +51,9 @@ func readDocuments(reader io.Reader, filename string, fileIndex int, decoder Dec
} else if errorReading != nil {
return nil, fmt.Errorf("bad file '%v': %w", filename, errorReading)
}
- candidateNode.Document = currentIndex
- candidateNode.Filename = filename
- candidateNode.FileIndex = fileIndex
+ candidateNode.document = currentIndex
+ candidateNode.filename = filename
+ candidateNode.fileIndex = fileIndex
candidateNode.EvaluateTogether = true
inputList.PushBack(candidateNode)
diff --git a/pkg/yqlib/xml_test.go b/pkg/yqlib/xml_test.go
index 0f74ab10..8194f38c 100644
--- a/pkg/yqlib/xml_test.go
+++ b/pkg/yqlib/xml_test.go
@@ -364,11 +364,10 @@ var xmlScenarios = []formatScenario{
expected: "zoo:\n animal:\n - cat\n",
},
{
- description: "Parse xml: force all as an array",
- subdescription: "Because of the way yq works, when updating everything you need to update the children before the parents. By default `..` will match parents first, so we reverse that before updating.",
- input: "boing",
- expression: "([..] | reverse | .[]) |= [] + .",
- expected: "- zoo:\n - thing:\n - frog:\n - boing\n",
+ description: "Parse xml: force all as an array",
+ input: "boing",
+ expression: ".. |= [] + .",
+ expected: "- zoo:\n - thing:\n - frog:\n - boing\n",
},
{
description: "Parse xml: attributes",
@@ -537,13 +536,6 @@ var xmlScenarios = []formatScenario{
expectedError: "cannot encode !!seq to XML - only maps can be encoded",
scenarioType: "encode-error",
},
- {
- description: "scalars cannot be encoded",
- skipDoc: true,
- input: "mike",
- expectedError: "cannot encode !!str to XML - only maps can be encoded",
- scenarioType: "encode-error",
- },
{
description: "Encode xml: attributes with content",
subdescription: "Fields with the matching xml-content-name is assumed to be content.",
diff --git a/pkg/yqlib/yaml_test.go b/pkg/yqlib/yaml_test.go
new file mode 100644
index 00000000..0d75433f
--- /dev/null
+++ b/pkg/yqlib/yaml_test.go
@@ -0,0 +1,109 @@
+package yqlib
+
+import (
+ "testing"
+
+ "github.com/mikefarah/yq/v4/test"
+)
+
+var yamlFormatScenarios = []formatScenario{
+ {
+ description: "basic - null",
+ skipDoc: true,
+ input: "null",
+ expected: "null\n",
+ },
+ {
+ description: "basic - ~",
+ skipDoc: true,
+ input: "~",
+ expected: "~\n",
+ },
+ {
+ description: "octal",
+ skipDoc: true,
+ input: "0o30",
+ expression: "tag",
+ expected: "!!int\n",
+ },
+ {
+ description: "basic - [null]",
+ skipDoc: true,
+ input: "[null]",
+ expected: "[null]\n",
+ },
+ {
+ description: "basic - [~]",
+ skipDoc: true,
+ input: "[~]",
+ expected: "[~]\n",
+ },
+ {
+ description: "basic - null map value",
+ skipDoc: true,
+ input: "a: null",
+ expected: "a: null\n",
+ },
+ {
+ description: "basic - number",
+ skipDoc: true,
+ input: "3",
+ expected: "3\n",
+ },
+ {
+ description: "basic - float",
+ skipDoc: true,
+ input: "3.1",
+ expected: "3.1\n",
+ },
+ {
+ description: "basic - float",
+ skipDoc: true,
+ input: "[1, 2]",
+ expected: "[1, 2]\n",
+ },
+}
+
+var yamlParseScenarios = []expressionScenario{
+ {
+ document: `a: hello # things`,
+ expected: []string{
+ "D0, P[], (!!map)::a: hello # things\n",
+ },
+ },
+ {
+ document: "a: &a apple\nb: *a",
+ expression: ".b | explode(.)",
+ expected: []string{
+ "D0, P[b], (!!str)::apple\n",
+ },
+ },
+ {
+ document: `a: [1,2]`,
+ expected: []string{
+ "D0, P[], (!!map)::a: [1, 2]\n",
+ },
+ },
+ {
+ document: `a: !horse [a]`,
+ expected: []string{
+ "D0, P[], (!!map)::a: !horse [a]\n",
+ },
+ },
+}
+
+func testYamlScenario(t *testing.T, s formatScenario) {
+ test.AssertResultWithContext(t, s.expected, mustProcessFormatScenario(s, NewYamlDecoder(NewDefaultYamlPreferences()), NewYamlEncoder(2, false, ConfiguredYamlPreferences)), s.description)
+}
+
+func TestYamlParseScenarios(t *testing.T) {
+ for _, tt := range yamlParseScenarios {
+ testScenario(t, &tt)
+ }
+}
+
+func TestYamlFormatScenarios(t *testing.T) {
+ for _, tt := range yamlFormatScenarios {
+ testYamlScenario(t, tt)
+ }
+}
diff --git a/project-words.txt b/project-words.txt
index 2371c1fb..a68e7542 100644
--- a/project-words.txt
+++ b/project-words.txt
@@ -249,4 +249,5 @@ yamld
yqlib
yuin
zabbix
-tonumber
\ No newline at end of file
+tonumber
+noyaml
\ No newline at end of file
diff --git a/test/utils.go b/test/utils.go
index f270c5b3..70454f73 100644
--- a/test/utils.go
+++ b/test/utils.go
@@ -4,25 +4,13 @@ import (
"bufio"
"bytes"
"fmt"
- "os"
"reflect"
"testing"
"github.com/pkg/diff"
"github.com/pkg/diff/write"
- yaml "gopkg.in/yaml.v3"
)
-func ParseData(rawData string) yaml.Node {
- var parsedData yaml.Node
- err := yaml.Unmarshal([]byte(rawData), &parsedData)
- if err != nil {
- fmt.Printf("Error parsing yaml: %v\n", err)
- os.Exit(1)
- }
- return parsedData
-}
-
func printDifference(t *testing.T, expectedValue interface{}, actualValue interface{}) {
opts := []write.Option{write.TerminalColor()}
var differenceBuffer bytes.Buffer