From eb7844dd1d5c4c555f2bf1f715a138874be8d512 Mon Sep 17 00:00:00 2001 From: Mike Farah Date: Tue, 11 Apr 2023 15:33:32 +1000 Subject: [PATCH] wip --- pkg/yqlib/all_at_once_evaluator_test.go | 19 +- pkg/yqlib/candidate_node.go | 70 +++---- pkg/yqlib/candidate_node_yaml.go | 205 ++++++++++++++++++ pkg/yqlib/data_tree_navigator.go | 2 +- pkg/yqlib/decoder_yaml.go | 108 +--------- pkg/yqlib/doc/operators/boolean-operators.md | 210 ------------------- pkg/yqlib/encoder_json.go | 8 +- pkg/yqlib/encoder_properties_test.go | 2 +- pkg/yqlib/encoder_test.go | 2 +- pkg/yqlib/lexer_participle_test.go | 41 ++-- pkg/yqlib/lib.go | 23 +- pkg/yqlib/operators_test.go | 15 +- pkg/yqlib/printer_writer.go | 9 +- 13 files changed, 305 insertions(+), 409 deletions(-) create mode 100644 pkg/yqlib/candidate_node_yaml.go diff --git a/pkg/yqlib/all_at_once_evaluator_test.go b/pkg/yqlib/all_at_once_evaluator_test.go index 2e9abc43..d80bbcf0 100644 --- a/pkg/yqlib/all_at_once_evaluator_test.go +++ b/pkg/yqlib/all_at_once_evaluator_test.go @@ -1,9 +1,12 @@ package yqlib import ( + "bufio" + "strings" "testing" "github.com/mikefarah/yq/v4/test" + logging "gopkg.in/op/go-logging.v1" ) var evaluateNodesScenario = []expressionScenario{ @@ -18,7 +21,7 @@ var evaluateNodesScenario = []expressionScenario{ document: `a: hello`, expression: `.`, expected: []string{ - "D0, P[], (doc)::a: hello\n", + "D0, P[], (!!map)::a: hello\n", }, }, { @@ -32,9 +35,19 @@ 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)) + decoder.Init(reader) + 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 28f9635f..577ceb9e 100644 --- a/pkg/yqlib/candidate_node.go +++ b/pkg/yqlib/candidate_node.go @@ -27,14 +27,6 @@ const ( FlowStyle ) -func createIntegerScalarNode(num int) *CandidateNode { - return &CandidateNode{ - Kind: ScalarNode, - Tag: "!!int", - Value: fmt.Sprintf("%v", num), - } -} - func createStringScalarNode(stringValue string) *CandidateNode { var node = &CandidateNode{Kind: ScalarNode} node.Value = stringValue @@ -94,6 +86,15 @@ type CandidateNode struct { IsMapKey bool } +func (n *CandidateNode) CreateChild() *CandidateNode { + return &CandidateNode{ + Parent: n, + Document: n.Document, + Filename: n.Filename, + FileIndex: n.FileIndex, + } +} + func (n *CandidateNode) GetKey() string { keyPrefix := "" if n.IsMapKey { @@ -136,7 +137,11 @@ func (n *CandidateNode) GetPath() []interface{} { if n.Parent != nil { return append(n.Parent.GetPath(), n.getParsedKey()) } - return []interface{}{n.getParsedKey()} + key := n.getParsedKey() + if key != nil { + return []interface{}{key} + } + return make([]interface{}, 0) } func (n *CandidateNode) GetNicePath() string { @@ -184,41 +189,24 @@ func (n *CandidateNode) guessTagFromCustomType() string { return guessedTag } -// func (n *CandidateNode) CreateChildInMap(key *CandidateNode) *CandidateNode { -// var value interface{} -// if key != nil { -// value = key.Value -// } -// return &CandidateNode{ -// Path: n.createChildPath(value), -// Parent: n, -// Key: key, - -// Document: n.Document, -// Filename: n.Filename, -// FileIndex: n.FileIndex, -// } -// } - func (n *CandidateNode) CreateReplacement(kind Kind, tag string, value string) *CandidateNode { node := &CandidateNode{ Kind: kind, Tag: tag, Value: value, } - n.CopyAsReplacement(node) - return node + return n.CopyAsReplacement(node) } func (n *CandidateNode) CopyAsReplacement(replacement *CandidateNode) *CandidateNode { - copy := replacement.Copy() - copy.Parent = n.Parent - copy.Key = n.Key - copy.IsMapKey = n.IsMapKey - copy.Document = n.Document - copy.Filename = n.Filename - copy.FileIndex = n.FileIndex - return copy + newCopy := replacement.Copy() + newCopy.Parent = n.Parent + newCopy.Key = n.Key + newCopy.IsMapKey = n.IsMapKey + newCopy.Document = n.Document + newCopy.Filename = n.Filename + newCopy.FileIndex = n.FileIndex + return newCopy } func (n *CandidateNode) CreateReplacementWithDocWrappers(kind Kind, tag string, style Style) *CandidateNode { @@ -230,10 +218,15 @@ func (n *CandidateNode) CreateReplacementWithDocWrappers(kind Kind, tag string, } func (n *CandidateNode) CopyChildren() []*CandidateNode { + log.Debug("n? %v", n) + log.Debug("n.Content %v", n.Content) + log.Debug("n.Content %v", len(n.Content)) clonedKids := make([]*CandidateNode, len(n.Content)) + log.Debug("created clone") for i, child := range n.Content { clonedKids[i] = child.Copy() } + log.Debug("finishing clone") return clonedKids } @@ -251,6 +244,11 @@ func (n *CandidateNode) doCopy(cloneContent bool) *CandidateNode { content = n.CopyChildren() } + var copyKey *CandidateNode + if n.Key != nil { + copyKey = n.Key.Copy() + } + return &CandidateNode{ Kind: n.Kind, Style: n.Style, @@ -269,7 +267,7 @@ func (n *CandidateNode) doCopy(cloneContent bool) *CandidateNode { FootComment: n.FootComment, Parent: n.Parent, - Key: n.Key.Copy(), + Key: copyKey, LeadingContent: n.LeadingContent, TrailingContent: n.TrailingContent, diff --git a/pkg/yqlib/candidate_node_yaml.go b/pkg/yqlib/candidate_node_yaml.go new file mode 100644 index 00000000..004067da --- /dev/null +++ b/pkg/yqlib/candidate_node_yaml.go @@ -0,0 +1,205 @@ +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 + } + return 0 +} + +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 + } + return 0 +} + +func (o *CandidateNode) copyFromYamlNode(node *yaml.Node) { + o.Style = MapYamlStyle(node.Style) + + o.Tag = node.Tag + o.Value = node.Value + o.Anchor = node.Anchor + + // o.Alias = TODO - find Alias in our own structure + // might need to be a post process thing + + 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) UnmarshalYAML(node *yaml.Node) error { + log.Debugf("unmarshalling %v", node.Tag) + switch node.Kind { + case yaml.DocumentNode: + o.Kind = DocumentNode + o.copyFromYamlNode(node) + if len(node.Content) == 0 { + return nil + } + + singleChild := &CandidateNode{ + Parent: o, + } + err := node.Content[0].Decode(singleChild) + if err != nil { + return err + } + o.Content = []*CandidateNode{singleChild} + return nil + case yaml.AliasNode: + log.Debug("decoding alias from yaml: %v", o.Tag) + o.Kind = AliasNode + o.copyFromYamlNode(node) + return nil + case yaml.ScalarNode: + o.Kind = ScalarNode + o.copyFromYamlNode(node) + return nil + case yaml.MappingNode: + o.Kind = MappingNode + o.copyFromYamlNode(node) + o.Content = make([]*CandidateNode, len(node.Content)) + for i := 0; i < len(node.Content); i += 2 { + keyNode := o.CreateChild() + keyNode.IsMapKey = true + err := node.Content[i].Decode(keyNode) + if err != nil { + return err + } + + valueNode := o.CreateChild() + valueNode.Key = keyNode + err = node.Content[i+1].Decode(valueNode) + if err != nil { + return err + } + + o.Content[i] = keyNode + o.Content[i+1] = valueNode + } + return nil + case yaml.SequenceNode: + o.Kind = SequenceNode + o.copyFromYamlNode(node) + o.Content = make([]*CandidateNode, len(node.Content)) + for i := 0; i < len(node.Content); i += 1 { + keyNode := o.CreateChild() + keyNode.IsMapKey = true // can't remember if we need this for sequences + keyNode.Tag = "!!int" + keyNode.Kind = ScalarNode + keyNode.Value = fmt.Sprintf("%v", i) + + valueNode := o.CreateChild() + valueNode.Key = keyNode + err := node.Content[i].Decode(valueNode) + if err != nil { + return err + } + o.Content[i] = valueNode + } + return nil + case 0: + // not sure when this happens + o.copyFromYamlNode(node) + return nil + default: + return fmt.Errorf("orderedMap: invalid yaml node") + } +} + +func (o *CandidateNode) MarshalYAML() (interface{}, error) { + log.Debug("encoding to yaml: %v", o.Tag) + switch o.Kind { + case DocumentNode: + target := &yaml.Node{Kind: yaml.DocumentNode} + o.copyToYamlNode(target) + + singleChild := &yaml.Node{} + err := singleChild.Encode(o.Content[0]) + if err != nil { + return nil, err + } + target.Content = []*yaml.Node{singleChild} + return target, nil + case AliasNode: + log.Debug("encoding alias to yaml: %v", o.Tag) + target := &yaml.Node{Kind: yaml.AliasNode} + o.copyToYamlNode(target) + return target, nil + case ScalarNode: + 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) + target.Content = make([]*yaml.Node, len(o.Content)) + for i := 0; i < len(o.Content); i += 1 { + child := &yaml.Node{} + err := child.Encode(o.Content[i]) + 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/data_tree_navigator.go b/pkg/yqlib/data_tree_navigator.go index c18ba2fb..9b1fc43a 100644 --- a/pkg/yqlib/data_tree_navigator.go +++ b/pkg/yqlib/data_tree_navigator.go @@ -49,7 +49,7 @@ func (d *dataTreeNavigator) GetMatchingNodes(context Context, expressionNode *Ex log.Debug(NodeToString(el.Value.(*CandidateNode))) } } - log.Debug(">>") + log.Debug("carr on>>") handler := expressionNode.Operation.OperationType.Handler if handler != nil { return handler(d, context, expressionNode) diff --git a/pkg/yqlib/decoder_yaml.go b/pkg/yqlib/decoder_yaml.go index 7c0a0dcf..3b9a1802 100644 --- a/pkg/yqlib/decoder_yaml.go +++ b/pkg/yqlib/decoder_yaml.go @@ -96,104 +96,10 @@ func (dec *yamlDecoder) Init(reader io.Reader) error { return nil } -func (dec *yamlDecoder) convertKind(oKind yaml.Kind) Kind { - switch oKind { - case yaml.DocumentNode: - return DocumentNode - case yaml.SequenceNode: - return SequenceNode - case yaml.MappingNode: - return MappingNode - case yaml.ScalarNode: - return ScalarNode - case yaml.AliasNode: - return AliasNode - } - return ScalarNode -} - -func (dec *yamlDecoder) convertStyle(oStyle yaml.Style) Style { - switch oStyle { - 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 - } - return 0 -} - -func (dec *yamlDecoder) ConvertToCandidateNode(parent *CandidateNode, path []interface{}, yamlNode *yaml.Node) *CandidateNode { - - candidateNode := &CandidateNode{ - Kind: dec.convertKind(yamlNode.Kind), - Style: dec.convertStyle(yamlNode.Style), - - Tag: yamlNode.Tag, - Value: yamlNode.Value, - Anchor: yamlNode.Anchor, - - // not sure on this - check - Alias: dec.ConvertToCandidateNode(parent, path, yamlNode.Alias), - - HeadComment: yamlNode.HeadComment, - LineComment: yamlNode.LineComment, - FootComment: yamlNode.FootComment, - Path: path, - - Parent: parent, - - Document: parent.Document, - Filename: parent.Filename, - - Line: yamlNode.Line, - Column: yamlNode.Column, - - FileIndex: parent.FileIndex, - } - - kids := make([]*CandidateNode, len(yamlNode.Content)) - - if yamlNode.Kind == yaml.MappingNode { - // children are key, values - for i := 0; i < len(yamlNode.Content); i = i + 2 { - key := yamlNode.Content[i] - value := yamlNode.Content[i+1] - - childPath := parent.createChildPath(key.Value) - keyNode := dec.ConvertToCandidateNode(parent, childPath, key) - keyNode.IsMapKey = true - - valueNode := dec.ConvertToCandidateNode(parent, childPath, value) - valueNode.Key = keyNode - - kids[i] = keyNode - kids[i+1] = valueNode - } - } else { - // its just an normal array - for i, v := range yamlNode.Content { - childPath := parent.createChildPath(i) - kids[i] = dec.ConvertToCandidateNode(parent, childPath, v) - } - } - - candidateNode.Content = kids - - return candidateNode - -} - func (dec *yamlDecoder) Decode() (*CandidateNode, error) { - var dataBucket yaml.Node - err := dec.decoder.Decode(&dataBucket) + var candidateNode CandidateNode + err := dec.decoder.Decode(&candidateNode) + log.Debugf("decoded the yaml") if errors.Is(err, io.EOF) && dec.leadingContent != "" && !dec.readAnything { // force returning an empty node with a comment. dec.readAnything = true @@ -211,8 +117,6 @@ func (dec *yamlDecoder) Decode() (*CandidateNode, error) { return nil, err } - candidateNode := dec.ConvertToCandidateNode(&CandidateNode{}, make([]interface{}, 0), &dataBucket) - if dec.leadingContent != "" { candidateNode.LeadingContent = dec.leadingContent dec.leadingContent = "" @@ -220,9 +124,9 @@ func (dec *yamlDecoder) Decode() (*CandidateNode, error) { dec.readAnything = true // move document comments into candidate node // otherwise unwrap drops them. - candidateNode.TrailingContent = dataBucket.FootComment - dataBucket.FootComment = "" - return candidateNode, nil + candidateNode.TrailingContent = candidateNode.FootComment + candidateNode.FootComment = "" + return &candidateNode, nil } func (dec *yamlDecoder) blankNodeWithComment() *CandidateNode { diff --git a/pkg/yqlib/doc/operators/boolean-operators.md b/pkg/yqlib/doc/operators/boolean-operators.md index c409445a..4f62cab6 100644 --- a/pkg/yqlib/doc/operators/boolean-operators.md +++ b/pkg/yqlib/doc/operators/boolean-operators.md @@ -16,213 +16,3 @@ These are most commonly used with the `select` operator to filter particular nod - comparison (`>=`, `<` etc) operators [here](https://mikefarah.gitbook.io/yq/operators/compare) - select operator [here](https://mikefarah.gitbook.io/yq/operators/select) -## `or` example -Running -```bash -yq --null-input 'true or false' -``` -will output -```yaml -true -``` - -## `and` example -Running -```bash -yq --null-input 'true and false' -``` -will output -```yaml -false -``` - -## Matching nodes with select, equals and or -Given a sample.yml file of: -```yaml -- a: bird - b: dog -- a: frog - b: bird -- a: cat - b: fly -``` -then -```bash -yq '[.[] | select(.a == "cat" or .b == "dog")]' sample.yml -``` -will output -```yaml -- a: bird - b: dog -- a: cat - b: fly -``` - -## `any` returns true if any boolean in a given array is true -Given a sample.yml file of: -```yaml -- false -- true -``` -then -```bash -yq 'any' sample.yml -``` -will output -```yaml -true -``` - -## `any` returns false for an empty array -Given a sample.yml file of: -```yaml -[] -``` -then -```bash -yq 'any' sample.yml -``` -will output -```yaml -false -``` - -## `any_c` returns true if any element in the array is true for the given condition. -Given a sample.yml file of: -```yaml -a: - - rad - - awesome -b: - - meh - - whatever -``` -then -```bash -yq '.[] |= any_c(. == "awesome")' sample.yml -``` -will output -```yaml -a: true -b: false -``` - -## `all` returns true if all booleans in a given array are true -Given a sample.yml file of: -```yaml -- true -- true -``` -then -```bash -yq 'all' sample.yml -``` -will output -```yaml -true -``` - -## `all` returns true for an empty array -Given a sample.yml file of: -```yaml -[] -``` -then -```bash -yq 'all' sample.yml -``` -will output -```yaml -true -``` - -## `all_c` returns true if all elements in the array are true for the given condition. -Given a sample.yml file of: -```yaml -a: - - rad - - awesome -b: - - meh - - 12 -``` -then -```bash -yq '.[] |= all_c(tag == "!!str")' sample.yml -``` -will output -```yaml -a: true -b: false -``` - -## Not true is false -Running -```bash -yq --null-input 'true | not' -``` -will output -```yaml -false -``` - -## Not false is true -Running -```bash -yq --null-input 'false | not' -``` -will output -```yaml -true -``` - -## String values considered to be true -Running -```bash -yq --null-input '"cat" | not' -``` -will output -```yaml -false -``` - -## Empty string value considered to be true -Running -```bash -yq --null-input '"" | not' -``` -will output -```yaml -false -``` - -## Numbers are considered to be true -Running -```bash -yq --null-input '1 | not' -``` -will output -```yaml -false -``` - -## Zero is considered to be true -Running -```bash -yq --null-input '0 | not' -``` -will output -```yaml -false -``` - -## Null is considered to be false -Running -```bash -yq --null-input '~ | not' -``` -will output -```yaml -true -``` - diff --git a/pkg/yqlib/encoder_json.go b/pkg/yqlib/encoder_json.go index 47a9f678..06854cc8 100644 --- a/pkg/yqlib/encoder_json.go +++ b/pkg/yqlib/encoder_json.go @@ -56,11 +56,11 @@ func (je *jsonEncoder) Encode(writer io.Writer, node *CandidateNode) error { var dataBucket orderedMap // firstly, convert all map keys to strings mapKeysToStrings(node) - errorDecoding := node.Decode(&dataBucket) + // errorDecoding := node.Decode(&dataBucket) - if errorDecoding != nil { - return errorDecoding - } + // if errorDecoding != nil { + // return errorDecoding + // } err := encoder.Encode(dataBucket) if err != nil { return err 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_test.go b/pkg/yqlib/encoder_test.go index cb384562..31d5730c 100644 --- a/pkg/yqlib/encoder_test.go +++ b/pkg/yqlib/encoder_test.go @@ -20,7 +20,7 @@ func yamlToJSON(sampleYaml string, indent int) string { if err != nil { panic(err) } - node := inputs.Front().Value.(*CandidateNode).Node + node := inputs.Front().Value.(*CandidateNode) err = jsonEncoder.Encode(writer, node) if err != nil { panic(err) diff --git a/pkg/yqlib/lexer_participle_test.go b/pkg/yqlib/lexer_participle_test.go index 2bce0ae2..c99a54d8 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 { @@ -41,11 +40,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", }, }, }, @@ -64,11 +61,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", }, }, }, @@ -106,11 +101,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", }, }, }, @@ -631,11 +624,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", }, }, }, @@ -652,11 +643,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 b488725f..7c6fee8f 100644 --- a/pkg/yqlib/lib.go +++ b/pkg/yqlib/lib.go @@ -2,7 +2,6 @@ package yqlib import ( - "bytes" "container/list" "fmt" "math" @@ -446,23 +445,23 @@ func NodeToString(node *CandidateNode) string { if node == nil { return "-- nil --" } - buf := new(bytes.Buffer) - encoder := yaml.NewEncoder(buf) - errorEncoding := encoder.Encode(node) - if errorEncoding != nil { - log.Error("Error debugging node, %v", errorEncoding.Error()) - } - errorClosingEncoder := encoder.Close() - if errorClosingEncoder != nil { - log.Error("Error closing encoder: ", errorClosingEncoder.Error()) - } + // buf := new(bytes.Buffer) + // encoder := yaml.NewEncoder(buf) + // errorEncoding := encoder.Encode(node) + // 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 := node.Tag if node.Kind == DocumentNode { tag = "doc" } else if node.Kind == AliasNode { tag = "alias" } - return fmt.Sprintf(`D%v, P%v, (%v)::%v`, node.Document, node.GetNicePath(), tag, buf.String()) + return fmt.Sprintf(`D%v, P%v, (%v)::%v`, node.Document, node.GetNicePath(), tag, node.Value) } func KindString(kind yaml.Kind) string { diff --git a/pkg/yqlib/operators_test.go b/pkg/yqlib/operators_test.go index c040cbed..3137e475 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 { @@ -82,7 +81,8 @@ func testScenario(t *testing.T, s *expressionScenario) { candidateNode := &CandidateNode{ Document: 0, Filename: "", - Node: &yaml.Node{Tag: "!!null", Kind: yaml.ScalarNode}, + Tag: "!!null", + Kind: ScalarNode, FileIndex: 0, } inputs.PushBack(candidateNode) @@ -138,13 +138,13 @@ func resultToString(t *testing.T, n *CandidateNode) string { return "" } - tag := n.Node.Tag - if n.Node.Kind == yaml.DocumentNode { + tag := n.Tag + if n.Kind == DocumentNode { tag = "doc" - } else if n.Node.Kind == yaml.AliasNode { + } else 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.Document, n.GetPath(), tag, valueBuffer.String()) } func resultsToString(t *testing.T, results *list.List) []string { @@ -352,7 +352,8 @@ func documentOutput(t *testing.T, w *bufio.Writer, s expressionScenario, formatt candidateNode := &CandidateNode{ Document: 0, Filename: "", - Node: &yaml.Node{Tag: "!!null", Kind: yaml.ScalarNode}, + Tag: "!!null", + Kind: ScalarNode, FileIndex: 0, } inputs.PushBack(candidateNode) 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) {