mirror of
https://github.com/mikefarah/yq.git
synced 2024-12-19 20:19:04 +00:00
wip
This commit is contained in:
parent
5b30f060b2
commit
c525fa21c4
@ -20,9 +20,11 @@ func MapYamlStyle(original yaml.Style) Style {
|
|||||||
return FoldedStyle
|
return FoldedStyle
|
||||||
case yaml.FlowStyle:
|
case yaml.FlowStyle:
|
||||||
return FlowStyle
|
return FlowStyle
|
||||||
}
|
case 0:
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
return Style(original)
|
||||||
|
}
|
||||||
|
|
||||||
func MapToYamlStyle(original Style) yaml.Style {
|
func MapToYamlStyle(original Style) yaml.Style {
|
||||||
switch original {
|
switch original {
|
||||||
@ -38,9 +40,11 @@ func MapToYamlStyle(original Style) yaml.Style {
|
|||||||
return yaml.FoldedStyle
|
return yaml.FoldedStyle
|
||||||
case FlowStyle:
|
case FlowStyle:
|
||||||
return yaml.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) {
|
func (o *CandidateNode) copyFromYamlNode(node *yaml.Node, anchorMap map[string]*CandidateNode) {
|
||||||
o.Style = MapYamlStyle(node.Style)
|
o.Style = MapYamlStyle(node.Style)
|
||||||
@ -161,7 +165,10 @@ func (o *CandidateNode) UnmarshalYAML(node *yaml.Node, anchorMap map[string]*Can
|
|||||||
case yaml.SequenceNode:
|
case yaml.SequenceNode:
|
||||||
log.Debugf("UnmarshalYAML - a sequence: %v", len(node.Content))
|
log.Debugf("UnmarshalYAML - a sequence: %v", len(node.Content))
|
||||||
o.Kind = SequenceNode
|
o.Kind = SequenceNode
|
||||||
|
|
||||||
o.copyFromYamlNode(node, anchorMap)
|
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))
|
o.Content = make([]*CandidateNode, len(node.Content))
|
||||||
for i := 0; i < len(node.Content); i += 1 {
|
for i := 0; i < len(node.Content); i += 1 {
|
||||||
keyNode := o.CreateChild()
|
keyNode := o.CreateChild()
|
||||||
@ -222,6 +229,8 @@ func (o *CandidateNode) MarshalYAML() (*yaml.Node, error) {
|
|||||||
}
|
}
|
||||||
target := &yaml.Node{Kind: targetKind}
|
target := &yaml.Node{Kind: targetKind}
|
||||||
o.copyToYamlNode(target)
|
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))
|
target.Content = make([]*yaml.Node, len(o.Content))
|
||||||
for i := 0; i < len(o.Content); i += 1 {
|
for i := 0; i < len(o.Content); i += 1 {
|
||||||
|
|
||||||
|
@ -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`.
|
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
|
|
||||||
```
|
|
||||||
|
|
||||||
|
@ -51,9 +51,7 @@ func add(d *dataTreeNavigator, context Context, lhs *CandidateNode, rhs *Candida
|
|||||||
return lhs.CopyAsReplacement(rhs), nil
|
return lhs.CopyAsReplacement(rhs), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
target := lhs.CopyAsReplacement(&CandidateNode{
|
target := lhs.CopyWithoutContent()
|
||||||
Anchor: lhs.Anchor,
|
|
||||||
})
|
|
||||||
|
|
||||||
switch lhsNode.Kind {
|
switch lhsNode.Kind {
|
||||||
case MappingNode:
|
case MappingNode:
|
||||||
@ -159,8 +157,10 @@ func addDateTimes(layout string, target *CandidateNode, lhs *CandidateNode, rhs
|
|||||||
}
|
}
|
||||||
|
|
||||||
func addSequences(target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode) error {
|
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
|
target.Kind = SequenceNode
|
||||||
if len(lhs.Content) > 0 {
|
if len(lhs.Content) > 0 {
|
||||||
|
log.Debugf("copy lhs style")
|
||||||
target.Style = lhs.Style
|
target.Style = lhs.Style
|
||||||
}
|
}
|
||||||
target.Tag = lhs.Tag
|
target.Tag = lhs.Tag
|
||||||
|
@ -5,349 +5,349 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var addOperatorScenarios = []expressionScenario{
|
var addOperatorScenarios = []expressionScenario{
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
document: `[{a: foo, b: bar}, {a: 1, b: 2}]`,
|
// document: `[{a: foo, b: bar}, {a: 1, b: 2}]`,
|
||||||
expression: ".[] | .a + .b",
|
// expression: ".[] | .a + .b",
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[0 a], (!!str)::foobar\n",
|
// "D0, P[0 a], (!!str)::foobar\n",
|
||||||
"D0, P[1 a], (!!int)::3\n",
|
// "D0, P[1 a], (!!int)::3\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
document: `a: key`,
|
// document: `a: key`,
|
||||||
expression: `. += {"key": "b"}`,
|
// expression: `. += {"key": "b"}`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (!!map)::a: key\nkey: b\n",
|
// "D0, P[], (!!map)::a: key\nkey: b\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
document: `[[c], [b]]`,
|
// document: `[[c], [b]]`,
|
||||||
expression: `.[] | . += "a"`,
|
// expression: `.[] | . += "a"`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[0], (!!seq)::[c, a]\n",
|
// "D0, P[0], (!!seq)::[c, a]\n",
|
||||||
"D0, P[1], (!!seq)::[b, a]\n",
|
// "D0, P[1], (!!seq)::[b, a]\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
document: `{}`,
|
// document: `{}`,
|
||||||
expression: "(.a + .b) as $x | .",
|
// expression: "(.a + .b) as $x | .",
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::{}\n",
|
// "D0, P[], (doc)::{}\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
document: `a: 0`,
|
// document: `a: 0`,
|
||||||
expression: ".a += .b.c",
|
// expression: ".a += .b.c",
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a: 0\n",
|
// "D0, P[], (doc)::a: 0\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
|
|
||||||
{
|
// {
|
||||||
description: "Concatenate arrays",
|
// description: "Concatenate arrays",
|
||||||
document: `{a: [1,2], b: [3,4]}`,
|
// document: `{a: [1,2], b: [3,4]}`,
|
||||||
expression: `.a + .b`,
|
// expression: `.a + .b`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[a], (!!seq)::[1, 2, 3, 4]\n",
|
// "D0, P[a], (!!seq)::[1, 2, 3, 4]\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Concatenate to existing array",
|
// description: "Concatenate to existing array",
|
||||||
subdescription: "Note that the styling of `a` is kept.",
|
// subdescription: "Note that the styling of `a` is kept.",
|
||||||
document: "a: [1,2]\nb:\n - 3\n - 4",
|
// document: "a: [1,2]\nb:\n - 3\n - 4",
|
||||||
dontFormatInputForDoc: true,
|
// dontFormatInputForDoc: true,
|
||||||
expression: `.a += .b`,
|
// expression: `.a += .b`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a: [1, 2, 3, 4]\nb:\n - 3\n - 4\n",
|
// "D0, P[], (doc)::a: [1, 2, 3, 4]\nb:\n - 3\n - 4\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
expression: `[1] + ([2], [3])`,
|
// expression: `[1] + ([2], [3])`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (!!seq)::- 1\n- 2\n",
|
// "D0, P[], (!!seq)::- 1\n- 2\n",
|
||||||
"D0, P[], (!!seq)::- 1\n- 3\n",
|
// "D0, P[], (!!seq)::- 1\n- 3\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Concatenate null to array",
|
// description: "Concatenate null to array",
|
||||||
document: `{a: [1,2]}`,
|
// document: `{a: [1,2]}`,
|
||||||
expression: `.a + null`,
|
// expression: `.a + null`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[a], (!!seq)::[1, 2]\n",
|
// "D0, P[a], (!!seq)::[1, 2]\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
description: "Concatenate to empty array",
|
// description: "Concatenate to empty array",
|
||||||
document: `{a: []}`,
|
// document: `{a: []}`,
|
||||||
expression: `.a + "cat"`,
|
// expression: `.a + "cat"`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[a], (!!seq)::- cat\n",
|
// "D0, P[a], (!!seq)::- cat\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Append to existing array",
|
// description: "Append to existing array",
|
||||||
subdescription: "Note that the styling is copied from existing array elements",
|
// subdescription: "Note that the styling is copied from existing array elements",
|
||||||
dontFormatInputForDoc: true,
|
// dontFormatInputForDoc: true,
|
||||||
document: `a: ['dog']`,
|
// document: `a: ['dog']`,
|
||||||
expression: `.a += "cat"`,
|
// expression: `.a += "cat"`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a: ['dog', 'cat']\n",
|
// "D0, P[], (doc)::a: ['dog', 'cat']\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Prepend to existing array",
|
// description: "Prepend to existing array",
|
||||||
document: `a: [dog]`,
|
// document: `a: [dog]`,
|
||||||
expression: `.a = ["cat"] + .a`,
|
// expression: `.a = ["cat"] + .a`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a: [cat, dog]\n",
|
// "D0, P[], (doc)::a: [cat, dog]\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
description: "Concatenate to existing array",
|
// description: "Concatenate to existing array",
|
||||||
subdescription: "does not modify original",
|
// subdescription: "does not modify original",
|
||||||
document: `{a: ['dog'], b: cat}`,
|
// document: `{a: ['dog'], b: cat}`,
|
||||||
expression: `.a = .a + .b`,
|
// expression: `.a = .a + .b`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::{a: ['dog', 'cat'], b: cat}\n",
|
// "D0, P[], (doc)::{a: ['dog', 'cat'], b: cat}\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
description: "Concatenate to empty array",
|
// description: "Concatenate to empty array",
|
||||||
document: `a: []`,
|
// document: `a: []`,
|
||||||
expression: `.a += "cat"`,
|
// expression: `.a += "cat"`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a:\n - cat\n",
|
// "D0, P[], (doc)::a:\n - cat\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
description: "Concatenate to existing array",
|
// description: "Concatenate to existing array",
|
||||||
document: `a: [dog]`,
|
// document: `a: [dog]`,
|
||||||
expression: `.a += "cat"`,
|
// expression: `.a += "cat"`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a: [dog, cat]\n",
|
// "D0, P[], (doc)::a: [dog, cat]\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
description: "Concatenate to empty object",
|
// description: "Concatenate to empty object",
|
||||||
document: `{a: {}}`,
|
// document: `{a: {}}`,
|
||||||
expression: `.a + {"b": "cat"}`,
|
// expression: `.a + {"b": "cat"}`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[a], (!!map)::b: cat\n",
|
// "D0, P[a], (!!map)::b: cat\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
description: "Concatenate to existing object",
|
// description: "Concatenate to existing object",
|
||||||
document: `{a: {c: dog}}`,
|
// document: `{a: {c: dog}}`,
|
||||||
expression: `.a + {"b": "cat"}`,
|
// expression: `.a + {"b": "cat"}`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[a], (!!map)::{c: dog, b: cat}\n",
|
// "D0, P[a], (!!map)::{c: dog, b: cat}\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
description: "Concatenate to existing object",
|
// description: "Concatenate to existing object",
|
||||||
subdescription: "matches stylig",
|
// subdescription: "matches stylig",
|
||||||
document: "a:\n c: dog",
|
// document: "a:\n c: dog",
|
||||||
expression: `.a + {"b": "cat"}`,
|
// expression: `.a + {"b": "cat"}`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[a], (!!map)::c: dog\nb: cat\n",
|
// "D0, P[a], (!!map)::c: dog\nb: cat\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
description: "Concatenate to empty object in place",
|
// description: "Concatenate to empty object in place",
|
||||||
document: `a: {}`,
|
// document: `a: {}`,
|
||||||
expression: `.a += {"b": "cat"}`,
|
// expression: `.a += {"b": "cat"}`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a:\n b: cat\n",
|
// "D0, P[], (doc)::a:\n b: cat\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
description: "Concatenate to existing object in place",
|
// description: "Concatenate to existing object in place",
|
||||||
document: `a: {c: dog}`,
|
// document: `a: {c: dog}`,
|
||||||
expression: `.a += {"b": "cat"}`,
|
// expression: `.a += {"b": "cat"}`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a: {c: dog, b: cat}\n",
|
// "D0, P[], (doc)::a: {c: dog, b: cat}\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Add new object to array",
|
// description: "Add new object to array",
|
||||||
document: `a: [{dog: woof}]`,
|
// document: `a: [{dog: woof}]`,
|
||||||
expression: `.a + {"cat": "meow"}`,
|
// expression: `.a + {"cat": "meow"}`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[a], (!!seq)::[{dog: woof}, {cat: meow}]\n",
|
// "D0, P[a], (!!seq)::[{dog: woof}, {cat: meow}]\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Relative append",
|
// description: "Relative append",
|
||||||
document: `a: { a1: {b: [cat]}, a2: {b: [dog]}, a3: {} }`,
|
// document: `a: { a1: {b: [cat]}, a2: {b: [dog]}, a3: {} }`,
|
||||||
expression: `.a[].b += ["mouse"]`,
|
// expression: `.a[].b += ["mouse"]`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a: {a1: {b: [cat, mouse]}, a2: {b: [dog, mouse]}, a3: {b: [mouse]}}\n",
|
// "D0, P[], (doc)::a: {a1: {b: [cat, mouse]}, a2: {b: [dog, mouse]}, a3: {b: [mouse]}}\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "String concatenation",
|
// description: "String concatenation",
|
||||||
document: `{a: cat, b: meow}`,
|
// document: `{a: cat, b: meow}`,
|
||||||
expression: `.a += .b`,
|
// expression: `.a += .b`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::{a: catmeow, b: meow}\n",
|
// "D0, P[], (doc)::{a: catmeow, b: meow}\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "String concatenation - str + int",
|
// description: "String concatenation - str + int",
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
document: `{a: !cool cat, b: meow}`,
|
// document: `{a: !cool cat, b: meow}`,
|
||||||
expression: `.a + 3`,
|
// expression: `.a + 3`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[a], (!cool)::cat3\n",
|
// "D0, P[a], (!cool)::cat3\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "String concatenation - int + str",
|
// description: "String concatenation - int + str",
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
document: `{a: !cool cat, b: meow}`,
|
// document: `{a: !cool cat, b: meow}`,
|
||||||
expression: `3 + .a`,
|
// expression: `3 + .a`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (!cool)::3cat\n",
|
// "D0, P[], (!cool)::3cat\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Number addition - float",
|
// description: "Number addition - float",
|
||||||
subdescription: "If the lhs or rhs are floats then the expression will be calculated with floats.",
|
// subdescription: "If the lhs or rhs are floats then the expression will be calculated with floats.",
|
||||||
document: `{a: 3, b: 4.9}`,
|
// document: `{a: 3, b: 4.9}`,
|
||||||
expression: `.a = .a + .b`,
|
// expression: `.a = .a + .b`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::{a: 7.9, b: 4.9}\n",
|
// "D0, P[], (doc)::{a: 7.9, b: 4.9}\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Number addition - int",
|
// description: "Number addition - int",
|
||||||
subdescription: "If both the lhs and rhs are ints then the expression will be calculated with ints.",
|
// subdescription: "If both the lhs and rhs are ints then the expression will be calculated with ints.",
|
||||||
document: `{a: 3, b: 4}`,
|
// document: `{a: 3, b: 4}`,
|
||||||
expression: `.a = .a + .b`,
|
// expression: `.a = .a + .b`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::{a: 7, b: 4}\n",
|
// "D0, P[], (doc)::{a: 7, b: 4}\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Increment numbers",
|
// description: "Increment numbers",
|
||||||
document: `{a: 3, b: 5}`,
|
// document: `{a: 3, b: 5}`,
|
||||||
expression: `.[] += 1`,
|
// expression: `.[] += 1`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::{a: 4, b: 6}\n",
|
// "D0, P[], (doc)::{a: 4, b: 6}\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Date addition",
|
// 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.",
|
// 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`,
|
// document: `a: 2021-01-01T00:00:00Z`,
|
||||||
expression: `.a += "3h10m"`,
|
// expression: `.a += "3h10m"`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a: 2021-01-01T03:10:00Z\n",
|
// "D0, P[], (doc)::a: 2021-01-01T03:10:00Z\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Date addition -date only",
|
// description: "Date addition -date only",
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
document: `a: 2021-01-01`,
|
// document: `a: 2021-01-01`,
|
||||||
expression: `.a += "24h"`,
|
// expression: `.a += "24h"`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a: 2021-01-02T00:00:00Z\n",
|
// "D0, P[], (doc)::a: 2021-01-02T00:00:00Z\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Date addition - custom format",
|
// 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.",
|
// 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`,
|
// document: `a: Saturday, 15-Dec-01 at 2:59AM GMT`,
|
||||||
expression: `with_dtf("Monday, 02-Jan-06 at 3:04PM MST", .a += "3h1m")`,
|
// expression: `with_dtf("Monday, 02-Jan-06 at 3:04PM MST", .a += "3h1m")`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a: Saturday, 15-Dec-01 at 6:00AM GMT\n",
|
// "D0, P[], (doc)::a: Saturday, 15-Dec-01 at 6:00AM GMT\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
description: "Date addition - custom format",
|
// 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.",
|
// 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`,
|
// document: `a: !cat Saturday, 15-Dec-01 at 2:59AM GMT`,
|
||||||
expression: `with_dtf("Monday, 02-Jan-06 at 3:04PM MST", .a += "3h1m")`,
|
// expression: `with_dtf("Monday, 02-Jan-06 at 3:04PM MST", .a += "3h1m")`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a: !cat Saturday, 15-Dec-01 at 6:00AM GMT\n",
|
// "D0, P[], (doc)::a: !cat Saturday, 15-Dec-01 at 6:00AM GMT\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Add to null",
|
// description: "Add to null",
|
||||||
subdescription: "Adding to null simply returns the rhs",
|
// subdescription: "Adding to null simply returns the rhs",
|
||||||
expression: `null + "cat"`,
|
// expression: `null + "cat"`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (!!str)::cat\n",
|
// "D0, P[], (!!str)::cat\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Add maps to shallow merge",
|
// description: "Add maps to shallow merge",
|
||||||
subdescription: "Adding objects together shallow merges them. Use `*` to deeply 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}",
|
// document: "a: {thing: {name: Astuff, value: x}, a1: cool}\nb: {thing: {name: Bstuff, legs: 3}, b1: neat}",
|
||||||
expression: `.a += .b`,
|
// expression: `.a += .b`,
|
||||||
expected: []string{
|
// 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[], (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",
|
// description: "Custom types: that are really strings",
|
||||||
subdescription: "When custom tags are encountered, yq will try to decode the underlying type.",
|
// subdescription: "When custom tags are encountered, yq will try to decode the underlying type.",
|
||||||
document: "a: !horse cat\nb: !goat _meow",
|
// document: "a: !horse cat\nb: !goat _meow",
|
||||||
expression: `.a += .b`,
|
// expression: `.a += .b`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a: !horse cat_meow\nb: !goat _meow\n",
|
// "D0, P[], (doc)::a: !horse cat_meow\nb: !goat _meow\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Custom types: that are really numbers",
|
// description: "Custom types: that are really numbers",
|
||||||
subdescription: "When custom tags are encountered, yq will try to decode the underlying type.",
|
// subdescription: "When custom tags are encountered, yq will try to decode the underlying type.",
|
||||||
document: "a: !horse 1.2\nb: !goat 2.3",
|
// document: "a: !horse 1.2\nb: !goat 2.3",
|
||||||
expression: `.a += .b`,
|
// expression: `.a += .b`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a: !horse 3.5\nb: !goat 2.3\n",
|
// "D0, P[], (doc)::a: !horse 3.5\nb: !goat 2.3\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
document: "a: !horse 2\nb: !goat 2.3",
|
// document: "a: !horse 2\nb: !goat 2.3",
|
||||||
expression: `.a += .b`,
|
// expression: `.a += .b`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a: !horse 4.3\nb: !goat 2.3\n",
|
// "D0, P[], (doc)::a: !horse 4.3\nb: !goat 2.3\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
document: "a: 2\nb: !goat 2.3",
|
// document: "a: 2\nb: !goat 2.3",
|
||||||
expression: `.a += .b`,
|
// expression: `.a += .b`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a: 4.3\nb: !goat 2.3\n",
|
// "D0, P[], (doc)::a: 4.3\nb: !goat 2.3\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
description: "Custom types: that are really ints",
|
// description: "Custom types: that are really ints",
|
||||||
document: "a: !horse 2\nb: !goat 3",
|
// document: "a: !horse 2\nb: !goat 3",
|
||||||
expression: `.a += .b`,
|
// expression: `.a += .b`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a: !horse 5\nb: !goat 3\n",
|
// "D0, P[], (doc)::a: !horse 5\nb: !goat 3\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
description: "Custom types: that are really arrays",
|
description: "Custom types: that are really arrays",
|
||||||
skipDoc: true,
|
skipDoc: true,
|
||||||
@ -358,29 +358,29 @@ var addOperatorScenarios = []expressionScenario{
|
|||||||
"D0, P[], (doc)::a: !horse [a, b]\nb: !goat [b]\n",
|
"D0, P[], (doc)::a: !horse [a, b]\nb: !goat [b]\n",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
description: "Keep anchors",
|
// description: "Keep anchors",
|
||||||
document: "a: &horse [1]",
|
// document: "a: &horse [1]",
|
||||||
expression: `.a += 2`,
|
// expression: `.a += 2`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a: &horse [1, 2]\n",
|
// "D0, P[], (doc)::a: &horse [1, 2]\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
description: "Add sequence to map",
|
// description: "Add sequence to map",
|
||||||
document: "a: {x: cool}",
|
// document: "a: {x: cool}",
|
||||||
expression: `.a += [2]`,
|
// expression: `.a += [2]`,
|
||||||
expectedError: "!!seq () cannot be added to a !!map (a)",
|
// expectedError: "!!seq () cannot be added to a !!map (a)",
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
description: "Add sequence to scalar",
|
// description: "Add sequence to scalar",
|
||||||
document: "a: cool",
|
// document: "a: cool",
|
||||||
expression: `.a += [2]`,
|
// expression: `.a += [2]`,
|
||||||
expectedError: "!!seq () cannot be added to a !!str (a)",
|
// expectedError: "!!seq () cannot be added to a !!str (a)",
|
||||||
},
|
// },
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddOperatorScenarios(t *testing.T) {
|
func TestAddOperatorScenarios(t *testing.T) {
|
||||||
|
@ -11,7 +11,7 @@ var alternativeOperatorScenarios = []expressionScenario{
|
|||||||
expression: `.b // .c`,
|
expression: `.b // .c`,
|
||||||
document: `a: bridge`,
|
document: `a: bridge`,
|
||||||
expected: []string{
|
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",
|
expression: "(.a // (.a = 0)) += 1",
|
||||||
document: `b: camel`,
|
document: `b: camel`,
|
||||||
expected: []string{
|
expected: []string{
|
||||||
"D0, P[], (!!map)::b: camel\na: 1\n",
|
"D0, P[], (doc)::b: camel\na: 1\n",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -77,6 +77,12 @@ var yamlParseScenarios = []expressionScenario{
|
|||||||
"D0, P[], (doc)::a: [1, 2]\n",
|
"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) {
|
func testYamlScenario(t *testing.T, s formatScenario) {
|
||||||
|
Loading…
Reference in New Issue
Block a user