From c525fa21c4f5b0278b37fad1ba8740af23ea2695 Mon Sep 17 00:00:00 2001 From: Mike Farah Date: Sat, 15 Apr 2023 15:54:44 +1000 Subject: [PATCH] wip --- pkg/yqlib/candidate_node_yaml.go | 13 +- pkg/yqlib/doc/operators/add.md | 325 ----------- pkg/yqlib/operator_add.go | 6 +- pkg/yqlib/operator_add_test.go | 730 ++++++++++++------------- pkg/yqlib/operator_alternative_test.go | 4 +- pkg/yqlib/yaml_test.go | 6 + 6 files changed, 387 insertions(+), 697 deletions(-) diff --git a/pkg/yqlib/candidate_node_yaml.go b/pkg/yqlib/candidate_node_yaml.go index 7cd8cc14..9fea92fd 100644 --- a/pkg/yqlib/candidate_node_yaml.go +++ b/pkg/yqlib/candidate_node_yaml.go @@ -20,8 +20,10 @@ func MapYamlStyle(original yaml.Style) Style { return FoldedStyle case yaml.FlowStyle: return FlowStyle + case 0: + return 0 } - return 0 + return Style(original) } func MapToYamlStyle(original Style) yaml.Style { @@ -38,8 +40,10 @@ func MapToYamlStyle(original Style) yaml.Style { return yaml.FoldedStyle case FlowStyle: return yaml.FlowStyle + case 0: + return 0 } - return 0 + return yaml.Style(original) } func (o *CandidateNode) copyFromYamlNode(node *yaml.Node, anchorMap map[string]*CandidateNode) { @@ -161,7 +165,10 @@ func (o *CandidateNode) UnmarshalYAML(node *yaml.Node, anchorMap map[string]*Can 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 += 1 { keyNode := o.CreateChild() @@ -222,6 +229,8 @@ func (o *CandidateNode) MarshalYAML() (*yaml.Node, error) { } 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 += 1 { diff --git a/pkg/yqlib/doc/operators/add.md b/pkg/yqlib/doc/operators/add.md index 469e13d8..68c52e97 100644 --- a/pkg/yqlib/doc/operators/add.md +++ b/pkg/yqlib/doc/operators/add.md @@ -9,328 +9,3 @@ Add behaves differently according to the type of the LHS: Use `+=` as a relative append assign for things like increment. Note that `.a += .x` is equivalent to running `.a = .a + .x`. -## Concatenate arrays -Given a sample.yml file of: -```yaml -a: - - 1 - - 2 -b: - - 3 - - 4 -``` -then -```bash -yq '.a + .b' sample.yml -``` -will output -```yaml -- 1 -- 2 -- 3 -- 4 -``` - -## Concatenate to existing array -Note that the styling of `a` is kept. - -Given a sample.yml file of: -```yaml -a: [1,2] -b: - - 3 - - 4 -``` -then -```bash -yq '.a += .b' sample.yml -``` -will output -```yaml -a: [1, 2, 3, 4] -b: - - 3 - - 4 -``` - -## Concatenate null to array -Given a sample.yml file of: -```yaml -a: - - 1 - - 2 -``` -then -```bash -yq '.a + null' sample.yml -``` -will output -```yaml -- 1 -- 2 -``` - -## Append to existing array -Note that the styling is copied from existing array elements - -Given a sample.yml file of: -```yaml -a: ['dog'] -``` -then -```bash -yq '.a += "cat"' sample.yml -``` -will output -```yaml -a: ['dog', 'cat'] -``` - -## Prepend to existing array -Given a sample.yml file of: -```yaml -a: - - dog -``` -then -```bash -yq '.a = ["cat"] + .a' sample.yml -``` -will output -```yaml -a: - - cat - - dog -``` - -## Add new object to array -Given a sample.yml file of: -```yaml -a: - - dog: woof -``` -then -```bash -yq '.a + {"cat": "meow"}' sample.yml -``` -will output -```yaml -- dog: woof -- cat: meow -``` - -## Relative append -Given a sample.yml file of: -```yaml -a: - a1: - b: - - cat - a2: - b: - - dog - a3: {} -``` -then -```bash -yq '.a[].b += ["mouse"]' sample.yml -``` -will output -```yaml -a: - a1: - b: - - cat - - mouse - a2: - b: - - dog - - mouse - a3: - b: - - mouse -``` - -## String concatenation -Given a sample.yml file of: -```yaml -a: cat -b: meow -``` -then -```bash -yq '.a += .b' sample.yml -``` -will output -```yaml -a: catmeow -b: meow -``` - -## Number addition - float -If the lhs or rhs are floats then the expression will be calculated with floats. - -Given a sample.yml file of: -```yaml -a: 3 -b: 4.9 -``` -then -```bash -yq '.a = .a + .b' sample.yml -``` -will output -```yaml -a: 7.9 -b: 4.9 -``` - -## Number addition - int -If both the lhs and rhs are ints then the expression will be calculated with ints. - -Given a sample.yml file of: -```yaml -a: 3 -b: 4 -``` -then -```bash -yq '.a = .a + .b' sample.yml -``` -will output -```yaml -a: 7 -b: 4 -``` - -## Increment numbers -Given a sample.yml file of: -```yaml -a: 3 -b: 5 -``` -then -```bash -yq '.[] += 1' sample.yml -``` -will output -```yaml -a: 4 -b: 6 -``` - -## Date addition -You can add durations to dates. Assumes RFC3339 date time format, see [date-time operators](https://mikefarah.gitbook.io/yq/operators/date-time-operators) for more information. - -Given a sample.yml file of: -```yaml -a: 2021-01-01T00:00:00Z -``` -then -```bash -yq '.a += "3h10m"' sample.yml -``` -will output -```yaml -a: 2021-01-01T03:10:00Z -``` - -## Date addition - custom format -You can add durations to dates. See [date-time operators](https://mikefarah.gitbook.io/yq/operators/date-time-operators) for more information. - -Given a sample.yml file of: -```yaml -a: Saturday, 15-Dec-01 at 2:59AM GMT -``` -then -```bash -yq 'with_dtf("Monday, 02-Jan-06 at 3:04PM MST", .a += "3h1m")' sample.yml -``` -will output -```yaml -a: Saturday, 15-Dec-01 at 6:00AM GMT -``` - -## Add to null -Adding to null simply returns the rhs - -Running -```bash -yq --null-input 'null + "cat"' -``` -will output -```yaml -cat -``` - -## Add maps to shallow merge -Adding objects together shallow merges them. Use `*` to deeply merge. - -Given a sample.yml file of: -```yaml -a: - thing: - name: Astuff - value: x - a1: cool -b: - thing: - name: Bstuff - legs: 3 - b1: neat -``` -then -```bash -yq '.a += .b' sample.yml -``` -will output -```yaml -a: - thing: - name: Bstuff - legs: 3 - a1: cool - b1: neat -b: - thing: - name: Bstuff - legs: 3 - b1: neat -``` - -## Custom types: that are really strings -When custom tags are encountered, yq will try to decode the underlying type. - -Given a sample.yml file of: -```yaml -a: !horse cat -b: !goat _meow -``` -then -```bash -yq '.a += .b' sample.yml -``` -will output -```yaml -a: !horse cat_meow -b: !goat _meow -``` - -## Custom types: that are really numbers -When custom tags are encountered, yq will try to decode the underlying type. - -Given a sample.yml file of: -```yaml -a: !horse 1.2 -b: !goat 2.3 -``` -then -```bash -yq '.a += .b' sample.yml -``` -will output -```yaml -a: !horse 3.5 -b: !goat 2.3 -``` - diff --git a/pkg/yqlib/operator_add.go b/pkg/yqlib/operator_add.go index 17e16a1b..2d119495 100644 --- a/pkg/yqlib/operator_add.go +++ b/pkg/yqlib/operator_add.go @@ -51,9 +51,7 @@ func add(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *Candida return lhs.CopyAsReplacement(rhs), nil } - target := lhs.CopyAsReplacement(&CandidateNode{ - Anchor: lhs.Anchor, - }) + target := lhs.CopyWithoutContent() switch lhsNode.Kind { case MappingNode: @@ -159,8 +157,10 @@ func addDateTimes(layout string, target *CandidateNode, lhs *CandidateNode, rhs } func addSequences(target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error { + 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("copy lhs style") target.Style = lhs.Style } target.Tag = lhs.Tag diff --git a/pkg/yqlib/operator_add_test.go b/pkg/yqlib/operator_add_test.go index eeabffde..2cd5a66b 100644 --- a/pkg/yqlib/operator_add_test.go +++ b/pkg/yqlib/operator_add_test.go @@ -5,349 +5,349 @@ import ( ) var addOperatorScenarios = []expressionScenario{ - { - skipDoc: true, - document: `[{a: foo, b: bar}, {a: 1, b: 2}]`, - expression: ".[] | .a + .b", - expected: []string{ - "D0, P[0 a], (!!str)::foobar\n", - "D0, P[1 a], (!!int)::3\n", - }, - }, - { - skipDoc: true, - document: `a: key`, - expression: `. += {"key": "b"}`, - expected: []string{ - "D0, P[], (!!map)::a: key\nkey: b\n", - }, - }, - { - skipDoc: true, - document: `[[c], [b]]`, - expression: `.[] | . += "a"`, - expected: []string{ - "D0, P[0], (!!seq)::[c, a]\n", - "D0, P[1], (!!seq)::[b, a]\n", - }, - }, - { - skipDoc: true, - document: `{}`, - expression: "(.a + .b) as $x | .", - expected: []string{ - "D0, P[], (doc)::{}\n", - }, - }, - { - skipDoc: true, - document: `a: 0`, - expression: ".a += .b.c", - expected: []string{ - "D0, P[], (doc)::a: 0\n", - }, - }, + // { + // skipDoc: true, + // document: `[{a: foo, b: bar}, {a: 1, b: 2}]`, + // expression: ".[] | .a + .b", + // expected: []string{ + // "D0, P[0 a], (!!str)::foobar\n", + // "D0, P[1 a], (!!int)::3\n", + // }, + // }, + // { + // skipDoc: true, + // document: `a: key`, + // expression: `. += {"key": "b"}`, + // expected: []string{ + // "D0, P[], (!!map)::a: key\nkey: b\n", + // }, + // }, + // { + // skipDoc: true, + // document: `[[c], [b]]`, + // expression: `.[] | . += "a"`, + // expected: []string{ + // "D0, P[0], (!!seq)::[c, a]\n", + // "D0, P[1], (!!seq)::[b, a]\n", + // }, + // }, + // { + // skipDoc: true, + // document: `{}`, + // expression: "(.a + .b) as $x | .", + // expected: []string{ + // "D0, P[], (doc)::{}\n", + // }, + // }, + // { + // skipDoc: true, + // document: `a: 0`, + // expression: ".a += .b.c", + // expected: []string{ + // "D0, P[], (doc)::a: 0\n", + // }, + // }, - { - description: "Concatenate arrays", - document: `{a: [1,2], b: [3,4]}`, - expression: `.a + .b`, - expected: []string{ - "D0, P[a], (!!seq)::[1, 2, 3, 4]\n", - }, - }, - { - description: "Concatenate to existing array", - subdescription: "Note that the styling of `a` is kept.", - document: "a: [1,2]\nb:\n - 3\n - 4", - dontFormatInputForDoc: true, - expression: `.a += .b`, - expected: []string{ - "D0, P[], (doc)::a: [1, 2, 3, 4]\nb:\n - 3\n - 4\n", - }, - }, - { - skipDoc: true, - expression: `[1] + ([2], [3])`, - expected: []string{ - "D0, P[], (!!seq)::- 1\n- 2\n", - "D0, P[], (!!seq)::- 1\n- 3\n", - }, - }, - { - description: "Concatenate null to array", - document: `{a: [1,2]}`, - expression: `.a + null`, - expected: []string{ - "D0, P[a], (!!seq)::[1, 2]\n", - }, - }, - { - skipDoc: true, - description: "Concatenate to empty array", - document: `{a: []}`, - expression: `.a + "cat"`, - expected: []string{ - "D0, P[a], (!!seq)::- cat\n", - }, - }, - { - description: "Append to existing array", - subdescription: "Note that the styling is copied from existing array elements", - dontFormatInputForDoc: true, - document: `a: ['dog']`, - expression: `.a += "cat"`, - expected: []string{ - "D0, P[], (doc)::a: ['dog', 'cat']\n", - }, - }, - { - description: "Prepend to existing array", - document: `a: [dog]`, - expression: `.a = ["cat"] + .a`, - expected: []string{ - "D0, P[], (doc)::a: [cat, dog]\n", - }, - }, - { - skipDoc: true, - description: "Concatenate to existing array", - subdescription: "does not modify original", - document: `{a: ['dog'], b: cat}`, - expression: `.a = .a + .b`, - expected: []string{ - "D0, P[], (doc)::{a: ['dog', 'cat'], b: cat}\n", - }, - }, - { - skipDoc: true, - description: "Concatenate to empty array", - document: `a: []`, - expression: `.a += "cat"`, - expected: []string{ - "D0, P[], (doc)::a:\n - cat\n", - }, - }, - { - skipDoc: true, - description: "Concatenate to existing array", - document: `a: [dog]`, - expression: `.a += "cat"`, - expected: []string{ - "D0, P[], (doc)::a: [dog, cat]\n", - }, - }, - { - skipDoc: true, - description: "Concatenate to empty object", - document: `{a: {}}`, - expression: `.a + {"b": "cat"}`, - expected: []string{ - "D0, P[a], (!!map)::b: cat\n", - }, - }, - { - skipDoc: true, - description: "Concatenate to existing object", - document: `{a: {c: dog}}`, - expression: `.a + {"b": "cat"}`, - expected: []string{ - "D0, P[a], (!!map)::{c: dog, b: cat}\n", - }, - }, - { - skipDoc: true, - description: "Concatenate to existing object", - subdescription: "matches stylig", - document: "a:\n c: dog", - expression: `.a + {"b": "cat"}`, - expected: []string{ - "D0, P[a], (!!map)::c: dog\nb: cat\n", - }, - }, - { - skipDoc: true, - description: "Concatenate to empty object in place", - document: `a: {}`, - expression: `.a += {"b": "cat"}`, - expected: []string{ - "D0, P[], (doc)::a:\n b: cat\n", - }, - }, - { - skipDoc: true, - description: "Concatenate to existing object in place", - document: `a: {c: dog}`, - expression: `.a += {"b": "cat"}`, - expected: []string{ - "D0, P[], (doc)::a: {c: dog, b: cat}\n", - }, - }, - { - description: "Add new object to array", - document: `a: [{dog: woof}]`, - expression: `.a + {"cat": "meow"}`, - expected: []string{ - "D0, P[a], (!!seq)::[{dog: woof}, {cat: meow}]\n", - }, - }, - { - description: "Relative append", - 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", - }, - }, - { - description: "String concatenation", - document: `{a: cat, b: meow}`, - expression: `.a += .b`, - expected: []string{ - "D0, P[], (doc)::{a: catmeow, b: meow}\n", - }, - }, - { - description: "String concatenation - str + int", - skipDoc: true, - document: `{a: !cool cat, b: meow}`, - expression: `.a + 3`, - expected: []string{ - "D0, P[a], (!cool)::cat3\n", - }, - }, - { - description: "String concatenation - int + str", - skipDoc: true, - document: `{a: !cool cat, b: meow}`, - expression: `3 + .a`, - expected: []string{ - "D0, P[], (!cool)::3cat\n", - }, - }, - { - description: "Number addition - float", - subdescription: "If the lhs or rhs are floats then the expression will be calculated with floats.", - document: `{a: 3, b: 4.9}`, - expression: `.a = .a + .b`, - expected: []string{ - "D0, P[], (doc)::{a: 7.9, b: 4.9}\n", - }, - }, - { - description: "Number addition - int", - subdescription: "If both the lhs and rhs are ints then the expression will be calculated with ints.", - document: `{a: 3, b: 4}`, - expression: `.a = .a + .b`, - expected: []string{ - "D0, P[], (doc)::{a: 7, b: 4}\n", - }, - }, - { - description: "Increment numbers", - document: `{a: 3, b: 5}`, - expression: `.[] += 1`, - expected: []string{ - "D0, P[], (doc)::{a: 4, b: 6}\n", - }, - }, - { - description: "Date addition", - subdescription: "You can add durations to dates. Assumes RFC3339 date time format, see [date-time operators](https://mikefarah.gitbook.io/yq/operators/date-time-operators) for more information.", - document: `a: 2021-01-01T00:00:00Z`, - expression: `.a += "3h10m"`, - expected: []string{ - "D0, P[], (doc)::a: 2021-01-01T03:10:00Z\n", - }, - }, - { - description: "Date addition -date only", - skipDoc: true, - document: `a: 2021-01-01`, - expression: `.a += "24h"`, - expected: []string{ - "D0, P[], (doc)::a: 2021-01-02T00:00:00Z\n", - }, - }, - { - description: "Date addition - custom format", - subdescription: "You can add durations to dates. See [date-time operators](https://mikefarah.gitbook.io/yq/operators/date-time-operators) for more information.", - 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", - }, - }, - { - skipDoc: true, - description: "Date addition - custom format", - subdescription: "You can add durations to dates. See [date-time operators](https://mikefarah.gitbook.io/yq/operators/date-time-operators) for more information.", - 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", - }, - }, - { - description: "Add to null", - subdescription: "Adding to null simply returns the rhs", - expression: `null + "cat"`, - expected: []string{ - "D0, P[], (!!str)::cat\n", - }, - }, - { - description: "Add maps to shallow merge", - subdescription: "Adding objects together shallow merges them. Use `*` to deeply merge.", - 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", - }, - }, - { - description: "Custom types: that are really strings", - subdescription: "When custom tags are encountered, yq will try to decode the underlying type.", - document: "a: !horse cat\nb: !goat _meow", - expression: `.a += .b`, - expected: []string{ - "D0, P[], (doc)::a: !horse cat_meow\nb: !goat _meow\n", - }, - }, - { - description: "Custom types: that are really numbers", - subdescription: "When custom tags are encountered, yq will try to decode the underlying type.", - 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", - }, - }, - { - skipDoc: true, - 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", - }, - }, - { - skipDoc: true, - document: "a: 2\nb: !goat 2.3", - expression: `.a += .b`, - expected: []string{ - "D0, P[], (doc)::a: 4.3\nb: !goat 2.3\n", - }, - }, - { - skipDoc: true, - description: "Custom types: that are really ints", - document: "a: !horse 2\nb: !goat 3", - expression: `.a += .b`, - expected: []string{ - "D0, P[], (doc)::a: !horse 5\nb: !goat 3\n", - }, - }, + // { + // description: "Concatenate arrays", + // document: `{a: [1,2], b: [3,4]}`, + // expression: `.a + .b`, + // expected: []string{ + // "D0, P[a], (!!seq)::[1, 2, 3, 4]\n", + // }, + // }, + // { + // description: "Concatenate to existing array", + // subdescription: "Note that the styling of `a` is kept.", + // document: "a: [1,2]\nb:\n - 3\n - 4", + // dontFormatInputForDoc: true, + // expression: `.a += .b`, + // expected: []string{ + // "D0, P[], (doc)::a: [1, 2, 3, 4]\nb:\n - 3\n - 4\n", + // }, + // }, + // { + // skipDoc: true, + // expression: `[1] + ([2], [3])`, + // expected: []string{ + // "D0, P[], (!!seq)::- 1\n- 2\n", + // "D0, P[], (!!seq)::- 1\n- 3\n", + // }, + // }, + // { + // description: "Concatenate null to array", + // document: `{a: [1,2]}`, + // expression: `.a + null`, + // expected: []string{ + // "D0, P[a], (!!seq)::[1, 2]\n", + // }, + // }, + // { + // skipDoc: true, + // description: "Concatenate to empty array", + // document: `{a: []}`, + // expression: `.a + "cat"`, + // expected: []string{ + // "D0, P[a], (!!seq)::- cat\n", + // }, + // }, + // { + // description: "Append to existing array", + // subdescription: "Note that the styling is copied from existing array elements", + // dontFormatInputForDoc: true, + // document: `a: ['dog']`, + // expression: `.a += "cat"`, + // expected: []string{ + // "D0, P[], (doc)::a: ['dog', 'cat']\n", + // }, + // }, + // { + // description: "Prepend to existing array", + // document: `a: [dog]`, + // expression: `.a = ["cat"] + .a`, + // expected: []string{ + // "D0, P[], (doc)::a: [cat, dog]\n", + // }, + // }, + // { + // skipDoc: true, + // description: "Concatenate to existing array", + // subdescription: "does not modify original", + // document: `{a: ['dog'], b: cat}`, + // expression: `.a = .a + .b`, + // expected: []string{ + // "D0, P[], (doc)::{a: ['dog', 'cat'], b: cat}\n", + // }, + // }, + // { + // skipDoc: true, + // description: "Concatenate to empty array", + // document: `a: []`, + // expression: `.a += "cat"`, + // expected: []string{ + // "D0, P[], (doc)::a:\n - cat\n", + // }, + // }, + // { + // skipDoc: true, + // description: "Concatenate to existing array", + // document: `a: [dog]`, + // expression: `.a += "cat"`, + // expected: []string{ + // "D0, P[], (doc)::a: [dog, cat]\n", + // }, + // }, + // { + // skipDoc: true, + // description: "Concatenate to empty object", + // document: `{a: {}}`, + // expression: `.a + {"b": "cat"}`, + // expected: []string{ + // "D0, P[a], (!!map)::b: cat\n", + // }, + // }, + // { + // skipDoc: true, + // description: "Concatenate to existing object", + // document: `{a: {c: dog}}`, + // expression: `.a + {"b": "cat"}`, + // expected: []string{ + // "D0, P[a], (!!map)::{c: dog, b: cat}\n", + // }, + // }, + // { + // skipDoc: true, + // description: "Concatenate to existing object", + // subdescription: "matches stylig", + // document: "a:\n c: dog", + // expression: `.a + {"b": "cat"}`, + // expected: []string{ + // "D0, P[a], (!!map)::c: dog\nb: cat\n", + // }, + // }, + // { + // skipDoc: true, + // description: "Concatenate to empty object in place", + // document: `a: {}`, + // expression: `.a += {"b": "cat"}`, + // expected: []string{ + // "D0, P[], (doc)::a:\n b: cat\n", + // }, + // }, + // { + // skipDoc: true, + // description: "Concatenate to existing object in place", + // document: `a: {c: dog}`, + // expression: `.a += {"b": "cat"}`, + // expected: []string{ + // "D0, P[], (doc)::a: {c: dog, b: cat}\n", + // }, + // }, + // { + // description: "Add new object to array", + // document: `a: [{dog: woof}]`, + // expression: `.a + {"cat": "meow"}`, + // expected: []string{ + // "D0, P[a], (!!seq)::[{dog: woof}, {cat: meow}]\n", + // }, + // }, + // { + // description: "Relative append", + // 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", + // }, + // }, + // { + // description: "String concatenation", + // document: `{a: cat, b: meow}`, + // expression: `.a += .b`, + // expected: []string{ + // "D0, P[], (doc)::{a: catmeow, b: meow}\n", + // }, + // }, + // { + // description: "String concatenation - str + int", + // skipDoc: true, + // document: `{a: !cool cat, b: meow}`, + // expression: `.a + 3`, + // expected: []string{ + // "D0, P[a], (!cool)::cat3\n", + // }, + // }, + // { + // description: "String concatenation - int + str", + // skipDoc: true, + // document: `{a: !cool cat, b: meow}`, + // expression: `3 + .a`, + // expected: []string{ + // "D0, P[], (!cool)::3cat\n", + // }, + // }, + // { + // description: "Number addition - float", + // subdescription: "If the lhs or rhs are floats then the expression will be calculated with floats.", + // document: `{a: 3, b: 4.9}`, + // expression: `.a = .a + .b`, + // expected: []string{ + // "D0, P[], (doc)::{a: 7.9, b: 4.9}\n", + // }, + // }, + // { + // description: "Number addition - int", + // subdescription: "If both the lhs and rhs are ints then the expression will be calculated with ints.", + // document: `{a: 3, b: 4}`, + // expression: `.a = .a + .b`, + // expected: []string{ + // "D0, P[], (doc)::{a: 7, b: 4}\n", + // }, + // }, + // { + // description: "Increment numbers", + // document: `{a: 3, b: 5}`, + // expression: `.[] += 1`, + // expected: []string{ + // "D0, P[], (doc)::{a: 4, b: 6}\n", + // }, + // }, + // { + // description: "Date addition", + // subdescription: "You can add durations to dates. Assumes RFC3339 date time format, see [date-time operators](https://mikefarah.gitbook.io/yq/operators/date-time-operators) for more information.", + // document: `a: 2021-01-01T00:00:00Z`, + // expression: `.a += "3h10m"`, + // expected: []string{ + // "D0, P[], (doc)::a: 2021-01-01T03:10:00Z\n", + // }, + // }, + // { + // description: "Date addition -date only", + // skipDoc: true, + // document: `a: 2021-01-01`, + // expression: `.a += "24h"`, + // expected: []string{ + // "D0, P[], (doc)::a: 2021-01-02T00:00:00Z\n", + // }, + // }, + // { + // description: "Date addition - custom format", + // subdescription: "You can add durations to dates. See [date-time operators](https://mikefarah.gitbook.io/yq/operators/date-time-operators) for more information.", + // 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", + // }, + // }, + // { + // skipDoc: true, + // description: "Date addition - custom format", + // subdescription: "You can add durations to dates. See [date-time operators](https://mikefarah.gitbook.io/yq/operators/date-time-operators) for more information.", + // 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", + // }, + // }, + // { + // description: "Add to null", + // subdescription: "Adding to null simply returns the rhs", + // expression: `null + "cat"`, + // expected: []string{ + // "D0, P[], (!!str)::cat\n", + // }, + // }, + // { + // description: "Add maps to shallow merge", + // subdescription: "Adding objects together shallow merges them. Use `*` to deeply merge.", + // 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", + // }, + // }, + // { + // description: "Custom types: that are really strings", + // subdescription: "When custom tags are encountered, yq will try to decode the underlying type.", + // document: "a: !horse cat\nb: !goat _meow", + // expression: `.a += .b`, + // expected: []string{ + // "D0, P[], (doc)::a: !horse cat_meow\nb: !goat _meow\n", + // }, + // }, + // { + // description: "Custom types: that are really numbers", + // subdescription: "When custom tags are encountered, yq will try to decode the underlying type.", + // 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", + // }, + // }, + // { + // skipDoc: true, + // 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", + // }, + // }, + // { + // skipDoc: true, + // document: "a: 2\nb: !goat 2.3", + // expression: `.a += .b`, + // expected: []string{ + // "D0, P[], (doc)::a: 4.3\nb: !goat 2.3\n", + // }, + // }, + // { + // skipDoc: true, + // description: "Custom types: that are really ints", + // document: "a: !horse 2\nb: !goat 3", + // expression: `.a += .b`, + // expected: []string{ + // "D0, P[], (doc)::a: !horse 5\nb: !goat 3\n", + // }, + // }, { description: "Custom types: that are really arrays", skipDoc: true, @@ -358,29 +358,29 @@ var addOperatorScenarios = []expressionScenario{ "D0, P[], (doc)::a: !horse [a, b]\nb: !goat [b]\n", }, }, - { - skipDoc: true, - description: "Keep anchors", - document: "a: &horse [1]", - expression: `.a += 2`, - expected: []string{ - "D0, P[], (doc)::a: &horse [1, 2]\n", - }, - }, - { - skipDoc: true, - description: "Add sequence to map", - document: "a: {x: cool}", - expression: `.a += [2]`, - expectedError: "!!seq () cannot be added to a !!map (a)", - }, - { - skipDoc: true, - description: "Add sequence to scalar", - document: "a: cool", - expression: `.a += [2]`, - expectedError: "!!seq () cannot be added to a !!str (a)", - }, + // { + // skipDoc: true, + // description: "Keep anchors", + // document: "a: &horse [1]", + // expression: `.a += 2`, + // expected: []string{ + // "D0, P[], (doc)::a: &horse [1, 2]\n", + // }, + // }, + // { + // skipDoc: true, + // description: "Add sequence to map", + // document: "a: {x: cool}", + // expression: `.a += [2]`, + // expectedError: "!!seq () cannot be added to a !!map (a)", + // }, + // { + // skipDoc: true, + // description: "Add sequence to scalar", + // document: "a: cool", + // expression: `.a += [2]`, + // expectedError: "!!seq () cannot be added to a !!str (a)", + // }, } func TestAddOperatorScenarios(t *testing.T) { diff --git a/pkg/yqlib/operator_alternative_test.go b/pkg/yqlib/operator_alternative_test.go index e70b8b25..890fe710 100644 --- a/pkg/yqlib/operator_alternative_test.go +++ b/pkg/yqlib/operator_alternative_test.go @@ -11,7 +11,7 @@ var alternativeOperatorScenarios = []expressionScenario{ expression: `.b // .c`, document: `a: bridge`, expected: []string{ - "D0, P[c], (!!null)::null\n", + "D0, P[], (!!null)::null\n", }, }, { @@ -100,7 +100,7 @@ var alternativeOperatorScenarios = []expressionScenario{ expression: "(.a // (.a = 0)) += 1", document: `b: camel`, expected: []string{ - "D0, P[], (!!map)::b: camel\na: 1\n", + "D0, P[], (doc)::b: camel\na: 1\n", }, }, } diff --git a/pkg/yqlib/yaml_test.go b/pkg/yqlib/yaml_test.go index a2b79e40..d3010852 100644 --- a/pkg/yqlib/yaml_test.go +++ b/pkg/yqlib/yaml_test.go @@ -77,6 +77,12 @@ var yamlParseScenarios = []expressionScenario{ "D0, P[], (doc)::a: [1, 2]\n", }, }, + { + document: `a: !horse [a]`, + expected: []string{ + "D0, P[], (doc)::a: !horse [a]\n", + }, + }, } func testYamlScenario(t *testing.T, s formatScenario) {