mirror of
https://github.com/mikefarah/yq.git
synced 2024-12-19 20:19:04 +00:00
wip
This commit is contained in:
parent
cde32c156b
commit
68df67f550
@ -180,16 +180,55 @@ func (n *CandidateNode) AsList() *list.List {
|
||||
|
||||
func (n *CandidateNode) AddKeyValueChild(rawKey *CandidateNode, rawValue *CandidateNode) {
|
||||
key := rawKey.unwrapDocument().Copy()
|
||||
key.Parent = n
|
||||
key.SetParent(n)
|
||||
key.IsMapKey = true
|
||||
|
||||
value := rawValue.unwrapDocument().Copy()
|
||||
value.Parent = n
|
||||
value.SetParent(n)
|
||||
value.Key = key
|
||||
|
||||
n.Content = append(n.Content, key, value)
|
||||
}
|
||||
|
||||
func (n *CandidateNode) SetParent(parent *CandidateNode) {
|
||||
n.Parent = parent
|
||||
n.Document = parent.Document
|
||||
n.Filename = parent.Filename
|
||||
n.FileIndex = parent.FileIndex
|
||||
}
|
||||
|
||||
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]
|
||||
|
||||
keyClone := key.Copy()
|
||||
keyClone.SetParent(n)
|
||||
|
||||
valueClone := value.Copy()
|
||||
valueClone.SetParent(n)
|
||||
valueClone.Key = keyClone
|
||||
n.Content = append(n.Content, keyClone, valueClone)
|
||||
}
|
||||
|
||||
} else {
|
||||
for _, rawChild := range children {
|
||||
value := rawChild.unwrapDocument().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
|
||||
}
|
||||
n.Content = append(n.Content, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (n *CandidateNode) GetValueRep() (interface{}, error) {
|
||||
log.Debugf("GetValueRep for %v value: %v", n.GetNicePath(), n.Value)
|
||||
realTag := n.guessTagFromCustomType()
|
||||
@ -262,14 +301,6 @@ func (n *CandidateNode) CreateReplacementWithDocWrappers(kind Kind, tag string,
|
||||
return replacement
|
||||
}
|
||||
|
||||
func (n *CandidateNode) CopyChildren() []*CandidateNode {
|
||||
clonedKids := make([]*CandidateNode, len(n.Content))
|
||||
for i, child := range n.Content {
|
||||
clonedKids[i] = child.Copy()
|
||||
}
|
||||
return clonedKids
|
||||
}
|
||||
|
||||
func (n *CandidateNode) Copy() *CandidateNode {
|
||||
return n.doCopy(true)
|
||||
}
|
||||
@ -280,9 +311,6 @@ func (n *CandidateNode) CopyWithoutContent() *CandidateNode {
|
||||
|
||||
func (n *CandidateNode) doCopy(cloneContent bool) *CandidateNode {
|
||||
var content []*CandidateNode
|
||||
if cloneContent {
|
||||
content = n.CopyChildren()
|
||||
}
|
||||
|
||||
var copyKey *CandidateNode
|
||||
if n.Key != nil {
|
||||
@ -323,8 +351,8 @@ func (n *CandidateNode) doCopy(cloneContent bool) *CandidateNode {
|
||||
IsMapKey: n.IsMapKey,
|
||||
}
|
||||
|
||||
for _, newChild := range content {
|
||||
newChild.Parent = clone
|
||||
if cloneContent {
|
||||
clone.AddChildren(n.Content)
|
||||
}
|
||||
|
||||
return clone
|
||||
@ -340,7 +368,9 @@ func (n *CandidateNode) UpdateFrom(other *CandidateNode, prefs assignPreferences
|
||||
n.Style = other.Style
|
||||
}
|
||||
|
||||
n.Content = other.CopyChildren()
|
||||
n.Content = make([]*CandidateNode, 0)
|
||||
n.AddChildren(other.Content)
|
||||
|
||||
n.Kind = other.Kind
|
||||
n.Value = other.Value
|
||||
|
||||
|
@ -5,6 +5,286 @@ Use the `alias` and `anchor` operators to read and write yaml aliases and anchor
|
||||
`yq` supports merge aliases (like `<<: *blah`) however this is no longer in the standard yaml spec (1.2) and so `yq` will automatically add the `!!merge` tag to these nodes as it is effectively a custom tag.
|
||||
|
||||
|
||||
## Merge one map
|
||||
see https://yaml.org/type/merge.html
|
||||
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
- &CENTER
|
||||
x: 1
|
||||
y: 2
|
||||
- &LEFT
|
||||
x: 0
|
||||
y: 2
|
||||
- &BIG
|
||||
r: 10
|
||||
- &SMALL
|
||||
r: 1
|
||||
- !!merge <<: *CENTER
|
||||
r: 10
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq '.[4] | explode(.)' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
x: 1
|
||||
y: 2
|
||||
r: 10
|
||||
```
|
||||
|
||||
## Merge multiple maps
|
||||
see https://yaml.org/type/merge.html
|
||||
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
- &CENTER
|
||||
x: 1
|
||||
y: 2
|
||||
- &LEFT
|
||||
x: 0
|
||||
y: 2
|
||||
- &BIG
|
||||
r: 10
|
||||
- &SMALL
|
||||
r: 1
|
||||
- !!merge <<:
|
||||
- *CENTER
|
||||
- *BIG
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq '.[4] | explode(.)' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
r: 10
|
||||
x: 1
|
||||
y: 2
|
||||
```
|
||||
|
||||
## Override
|
||||
see https://yaml.org/type/merge.html
|
||||
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
- &CENTER
|
||||
x: 1
|
||||
y: 2
|
||||
- &LEFT
|
||||
x: 0
|
||||
y: 2
|
||||
- &BIG
|
||||
r: 10
|
||||
- &SMALL
|
||||
r: 1
|
||||
- !!merge <<:
|
||||
- *BIG
|
||||
- *LEFT
|
||||
- *SMALL
|
||||
x: 1
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq '.[4] | explode(.)' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
r: 10
|
||||
x: 1
|
||||
y: 2
|
||||
```
|
||||
|
||||
## Get anchor
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a: &billyBob cat
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq '.a | anchor' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
billyBob
|
||||
```
|
||||
|
||||
## Set anchor
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a: cat
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq '.a anchor = "foobar"' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
a: &foobar cat
|
||||
```
|
||||
|
||||
## Set anchor relatively using assign-update
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a:
|
||||
b: cat
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq '.a anchor |= .b' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
a: &cat
|
||||
b: cat
|
||||
```
|
||||
|
||||
## Get alias
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
{b: &billyBob meow, a: *billyBob}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq '.a | alias' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
billyBob
|
||||
```
|
||||
|
||||
## Set alias
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
{b: &meow purr, a: cat}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq '.a alias = "meow"' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
{b: &meow purr, a: *meow}
|
||||
```
|
||||
|
||||
## Set alias to blank does nothing
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
{b: &meow purr, a: cat}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq '.a alias = ""' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
{b: &meow purr, a: cat}
|
||||
```
|
||||
|
||||
## Set alias relatively using assign-update
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
{b: &meow purr, a: {f: meow}}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq '.a alias |= .f' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
{b: &meow purr, a: *meow}
|
||||
```
|
||||
|
||||
## Explode alias and anchor
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
{f: {a: &a cat, b: *a}}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq 'explode(.f)' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
{f: {a: cat, b: cat}}
|
||||
```
|
||||
|
||||
## Explode with no aliases or anchors
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a: mike
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq 'explode(.a)' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
a: mike
|
||||
```
|
||||
|
||||
## Explode with alias keys
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
{f: {a: &a cat, *a: b}}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq 'explode(.f)' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
{f: {a: cat, cat: b}}
|
||||
```
|
||||
|
||||
## Explode with merge anchors
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
foo: &foo
|
||||
a: foo_a
|
||||
thing: foo_thing
|
||||
c: foo_c
|
||||
bar: &bar
|
||||
b: bar_b
|
||||
thing: bar_thing
|
||||
c: bar_c
|
||||
foobarList:
|
||||
b: foobarList_b
|
||||
!!merge <<:
|
||||
- *foo
|
||||
- *bar
|
||||
c: foobarList_c
|
||||
foobar:
|
||||
c: foobar_c
|
||||
!!merge <<: *foo
|
||||
thing: foobar_thing
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq 'explode(.)' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
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
|
||||
```
|
||||
|
||||
## Dereference and update a field
|
||||
Use explode with multiply to dereference an object
|
||||
|
||||
|
@ -95,10 +95,7 @@ The env variable can be any valid yq expression.
|
||||
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a:
|
||||
b:
|
||||
- name: dog
|
||||
- name: cat
|
||||
{a: {b: [{name: dog}, {name: cat}]}}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
@ -106,17 +103,13 @@ pathEnv=".a.b[0].name" valueEnv="moo" yq 'eval(strenv(pathEnv)) = strenv(valueE
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
a:
|
||||
b:
|
||||
- name: moo
|
||||
- name: cat
|
||||
{a: {b: [{name: moo}, {name: cat}]}}
|
||||
```
|
||||
|
||||
## Dynamic key lookup with environment variable
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
cat: meow
|
||||
dog: woof
|
||||
{cat: meow, dog: woof}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
@ -220,7 +213,7 @@ Error: variable ${myEmptyEnv} set but empty
|
||||
## Replace string environment variable in document
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
v: ${myenv}
|
||||
{v: '${myenv}'}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
@ -228,7 +221,7 @@ myenv="cat meow" yq '.v |= envsubst' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
v: cat meow
|
||||
{v: 'cat meow'}
|
||||
```
|
||||
|
||||
## (Default) Return all envsubst errors
|
||||
|
@ -21,113 +21,3 @@ The not equals `!=` operator returns `false` if the LHS is equal to the RHS.
|
||||
- select operator [here](https://mikefarah.gitbook.io/yq/operators/select)
|
||||
|
||||
|
||||
## Match string
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
- cat
|
||||
- goat
|
||||
- dog
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq '.[] | (. == "*at")' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
true
|
||||
true
|
||||
false
|
||||
```
|
||||
|
||||
## Don't match string
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
- cat
|
||||
- goat
|
||||
- dog
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq '.[] | (. != "*at")' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
false
|
||||
false
|
||||
true
|
||||
```
|
||||
|
||||
## Match number
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
- 3
|
||||
- 4
|
||||
- 5
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq '.[] | (. == 4)' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
false
|
||||
true
|
||||
false
|
||||
```
|
||||
|
||||
## Don't match number
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
- 3
|
||||
- 4
|
||||
- 5
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq '.[] | (. != 4)' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
true
|
||||
false
|
||||
true
|
||||
```
|
||||
|
||||
## Match nulls
|
||||
Running
|
||||
```bash
|
||||
yq --null-input 'null == ~'
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
true
|
||||
```
|
||||
|
||||
## Non existent key doesn't equal a value
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a: frog
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq 'select(.b != "thing")' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
a: frog
|
||||
```
|
||||
|
||||
## Two non existent keys are equal
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a: frog
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq 'select(.b == .c)' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
a: frog
|
||||
```
|
||||
|
||||
|
@ -9,11 +9,7 @@ Tip: This can be a useful way to parameterise complex scripts.
|
||||
## Dynamically evaluate a path
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
pathExp: .a.b[] | select(.name == "cat")
|
||||
a:
|
||||
b:
|
||||
- name: dog
|
||||
- name: cat
|
||||
{pathExp: '.a.b[] | select(.name == "cat")', a: {b: [{name: dog}, {name: cat}]}}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
@ -21,7 +17,7 @@ yq 'eval(.pathExp)' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
name: cat
|
||||
{name: cat}
|
||||
```
|
||||
|
||||
## Dynamically update a path from an environment variable
|
||||
@ -29,10 +25,7 @@ The env variable can be any valid yq expression.
|
||||
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a:
|
||||
b:
|
||||
- name: dog
|
||||
- name: cat
|
||||
{a: {b: [{name: dog}, {name: cat}]}}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
@ -40,9 +33,6 @@ pathEnv=".a.b[0].name" valueEnv="moo" yq 'eval(strenv(pathEnv)) = strenv(valueE
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
a:
|
||||
b:
|
||||
- name: moo
|
||||
- name: cat
|
||||
{a: {b: [{name: moo}, {name: cat}]}}
|
||||
```
|
||||
|
||||
|
@ -13,7 +13,7 @@ yq eval-all 'select(fi == 0) * select(filename == "file2.yaml")' file1.yaml file
|
||||
## Get filename
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a: cat
|
||||
{a: cat}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
@ -27,7 +27,7 @@ sample.yml
|
||||
## Get file index
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a: cat
|
||||
{a: cat}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
@ -41,11 +41,11 @@ will output
|
||||
## Get file indices of multiple documents
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a: cat
|
||||
{a: cat}
|
||||
```
|
||||
And another sample another.yml file of:
|
||||
```yaml
|
||||
a: cat
|
||||
{a: cat}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
@ -61,7 +61,7 @@ will output
|
||||
## Get file index alias
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a: cat
|
||||
{a: cat}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
|
@ -5,8 +5,7 @@ This is the simplest (and perhaps most used) operator. It is used to navigate de
|
||||
## Simple map navigation
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a:
|
||||
b: apple
|
||||
{a: {b: apple}}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
@ -14,7 +13,7 @@ yq '.a' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
b: apple
|
||||
{b: apple}
|
||||
```
|
||||
|
||||
## Splat
|
||||
@ -22,8 +21,7 @@ Often used to pipe children into other operators
|
||||
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
- b: apple
|
||||
- c: banana
|
||||
[{b: apple}, {c: banana}]
|
||||
```
|
||||
then
|
||||
```bash
|
||||
@ -31,8 +29,8 @@ yq '.[]' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
b: apple
|
||||
c: banana
|
||||
{b: apple}
|
||||
{c: banana}
|
||||
```
|
||||
|
||||
## Optional Splat
|
||||
@ -40,7 +38,7 @@ Just like splat, but won't error if you run it against scalars
|
||||
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
cat
|
||||
"cat"
|
||||
```
|
||||
then
|
||||
```bash
|
||||
@ -55,7 +53,7 @@ Use quotes with square brackets around path elements with special characters
|
||||
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
"{}": frog
|
||||
{"{}": frog}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
@ -87,7 +85,7 @@ Use quotes with square brackets around path elements with special characters
|
||||
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
"red rabbit": frog
|
||||
{"red rabbit": frog}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
@ -103,9 +101,7 @@ Expressions within [] can be used to dynamically lookup / calculate keys
|
||||
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
b: apple
|
||||
apple: crispy yum
|
||||
banana: soft yum
|
||||
{b: apple, apple: crispy yum, banana: soft yum}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
@ -121,7 +117,7 @@ Nodes are added dynamically while traversing
|
||||
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
c: banana
|
||||
{c: banana}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
@ -137,9 +133,7 @@ Like jq, does not output an error when the yaml is not an array or object as exp
|
||||
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
[1, 2, 3]
|
||||
```
|
||||
then
|
||||
```bash
|
||||
@ -152,9 +146,7 @@ will output
|
||||
## Wildcard matching
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a:
|
||||
cat: apple
|
||||
mad: things
|
||||
{a: {cat: apple, mad: things}}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
@ -169,9 +161,7 @@ things
|
||||
## Aliases
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a: &cat
|
||||
c: frog
|
||||
b: *cat
|
||||
{a: &cat {c: frog}, b: *cat}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
@ -185,9 +175,7 @@ will output
|
||||
## Traversing aliases with splat
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a: &cat
|
||||
c: frog
|
||||
b: *cat
|
||||
{a: &cat {c: frog}, b: *cat}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
@ -201,9 +189,7 @@ frog
|
||||
## Traversing aliases explicitly
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a: &cat
|
||||
c: frog
|
||||
b: *cat
|
||||
{a: &cat {c: frog}, b: *cat}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
@ -217,9 +203,7 @@ frog
|
||||
## Traversing arrays by index
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
[1, 2, 3]
|
||||
```
|
||||
then
|
||||
```bash
|
||||
@ -247,7 +231,7 @@ cat
|
||||
## Maps with numeric keys
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
2: cat
|
||||
{2: cat}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
@ -261,7 +245,7 @@ cat
|
||||
## Maps with non existing numeric keys
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a: b
|
||||
{a: b}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
@ -468,10 +452,7 @@ foobarList_c
|
||||
## Select multiple indices
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a:
|
||||
- a
|
||||
- b
|
||||
- c
|
||||
{a: [a, b, c]}
|
||||
```
|
||||
then
|
||||
```bash
|
||||
|
@ -170,7 +170,8 @@ func addSequences(target *CandidateNode, lhs *CandidateNode, rhs *CandidateNode)
|
||||
return err
|
||||
}
|
||||
|
||||
target.Content = append(lhs.CopyChildren(), extraNodes...)
|
||||
target.AddChildren(lhs.Content)
|
||||
target.AddChildren(extraNodes)
|
||||
return nil
|
||||
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ var alternativeOperatorScenarios = []expressionScenario{
|
||||
expression: `.b // .c`,
|
||||
document: `a: bridge`,
|
||||
expected: []string{
|
||||
"D0, P[], (!!null)::null\n",
|
||||
"D0, P[c], (!!null)::null\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -199,7 +199,7 @@ func explodeNode(node *CandidateNode, context Context) error {
|
||||
node.Kind = node.Alias.Kind
|
||||
node.Style = node.Alias.Style
|
||||
node.Tag = node.Alias.Tag
|
||||
node.Content = node.Alias.CopyChildren()
|
||||
node.AddChildren(node.Alias.Content)
|
||||
node.Value = node.Alias.Value
|
||||
node.Alias = nil
|
||||
}
|
||||
|
@ -34,198 +34,227 @@ thingTwo:
|
||||
!!merge <<: *item_value
|
||||
`
|
||||
|
||||
var explodeMergeAnchorsExpected = `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
|
||||
`
|
||||
|
||||
var anchorOperatorScenarios = []expressionScenario{
|
||||
// {
|
||||
// skipDoc: true,
|
||||
// description: "merge anchor not map",
|
||||
// document: "a: &a\n - 0\nc:\n <<: [*a]\n",
|
||||
// expectedError: "merge anchor only supports maps, got !!seq instead",
|
||||
// expression: "explode(.)",
|
||||
// },
|
||||
// {
|
||||
// description: "Merge one map",
|
||||
// subdescription: "see https://yaml.org/type/merge.html",
|
||||
// document: specDocument + "- << : *CENTER\n r: 10\n",
|
||||
// expression: ".[4] | explode(.)",
|
||||
// expected: []string{expectedSpecResult},
|
||||
// },
|
||||
// {
|
||||
// description: "Merge multiple maps",
|
||||
// subdescription: "see https://yaml.org/type/merge.html",
|
||||
// document: specDocument + "- << : [ *CENTER, *BIG ]\n",
|
||||
// expression: ".[4] | explode(.)",
|
||||
// expected: []string{"D0, P[4], (!!map)::r: 10\nx: 1\ny: 2\n"},
|
||||
// },
|
||||
// {
|
||||
// description: "Override",
|
||||
// subdescription: "see https://yaml.org/type/merge.html",
|
||||
// document: specDocument + "- << : [ *BIG, *LEFT, *SMALL ]\n x: 1\n",
|
||||
// expression: ".[4] | explode(.)",
|
||||
// expected: []string{"D0, P[4], (!!map)::r: 10\nx: 1\ny: 2\n"},
|
||||
// },
|
||||
// {
|
||||
// description: "Get anchor",
|
||||
// document: `a: &billyBob cat`,
|
||||
// expression: `.a | anchor`,
|
||||
// expected: []string{
|
||||
// "D0, P[a], (!!str)::billyBob\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// description: "Set anchor",
|
||||
// document: `a: cat`,
|
||||
// expression: `.a anchor = "foobar"`,
|
||||
// expected: []string{
|
||||
// "D0, P[], (doc)::a: &foobar cat\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// description: "Set anchor relatively using assign-update",
|
||||
// document: `a: {b: cat}`,
|
||||
// expression: `.a anchor |= .b`,
|
||||
// expected: []string{
|
||||
// "D0, P[], (doc)::a: &cat {b: cat}\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// skipDoc: true,
|
||||
// document: `a: {c: cat}`,
|
||||
// expression: `.a anchor |= .b`,
|
||||
// expected: []string{
|
||||
// "D0, P[], (doc)::a: {c: cat}\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// skipDoc: true,
|
||||
// document: `a: {c: cat}`,
|
||||
// expression: `.a anchor = .b`,
|
||||
// expected: []string{
|
||||
// "D0, P[], (doc)::a: {c: cat}\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// description: "Get alias",
|
||||
// document: `{b: &billyBob meow, a: *billyBob}`,
|
||||
// expression: `.a | alias`,
|
||||
// expected: []string{
|
||||
// "D0, P[a], (!!str)::billyBob\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// description: "Set alias",
|
||||
// document: `{b: &meow purr, a: cat}`,
|
||||
// expression: `.a alias = "meow"`,
|
||||
// expected: []string{
|
||||
// "D0, P[], (doc)::{b: &meow purr, a: *meow}\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// description: "Set alias to blank does nothing",
|
||||
// document: `{b: &meow purr, a: cat}`,
|
||||
// expression: `.a alias = ""`,
|
||||
// expected: []string{
|
||||
// "D0, P[], (doc)::{b: &meow purr, a: cat}\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// skipDoc: true,
|
||||
// document: `{b: &meow purr, a: cat}`,
|
||||
// expression: `.a alias = .c`,
|
||||
// expected: []string{
|
||||
// "D0, P[], (doc)::{b: &meow purr, a: cat}\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// skipDoc: true,
|
||||
// document: `{b: &meow purr, a: cat}`,
|
||||
// expression: `.a alias |= .c`,
|
||||
// expected: []string{
|
||||
// "D0, P[], (doc)::{b: &meow purr, a: cat}\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// description: "Set alias relatively using assign-update",
|
||||
// document: `{b: &meow purr, a: {f: meow}}`,
|
||||
// expression: `.a alias |= .f`,
|
||||
// expected: []string{
|
||||
// "D0, P[], (doc)::{b: &meow purr, a: *meow}\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// description: "Explode alias and anchor",
|
||||
// document: `{f : {a: &a cat, b: *a}}`,
|
||||
// expression: `explode(.f)`,
|
||||
// expected: []string{
|
||||
// "D0, P[], (doc)::{f: {a: cat, b: cat}}\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// description: "Explode with no aliases or anchors",
|
||||
// document: `a: mike`,
|
||||
// expression: `explode(.a)`,
|
||||
// expected: []string{
|
||||
// "D0, P[], (doc)::a: mike\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// description: "Explode with alias keys",
|
||||
// document: `{f : {a: &a cat, *a: b}}`,
|
||||
// expression: `explode(.f)`,
|
||||
// expected: []string{
|
||||
// "D0, P[], (doc)::{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
|
||||
// `},
|
||||
// },
|
||||
// {
|
||||
// skipDoc: true,
|
||||
// document: mergeDocSample,
|
||||
// expression: `.foo* | explode(.) | (. style="flow")`,
|
||||
// expected: []string{
|
||||
// "D0, P[foo], (!!map)::{a: foo_a, thing: foo_thing, c: foo_c}\n",
|
||||
// "D0, P[foobarList], (!!map)::{b: bar_b, thing: foo_thing, c: foobarList_c, a: foo_a}\n",
|
||||
// "D0, P[foobar], (!!map)::{c: foo_c, a: foo_a, thing: foobar_thing}\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// skipDoc: true,
|
||||
// document: mergeDocSample,
|
||||
// expression: `.foo* | explode(explode(.)) | (. style="flow")`,
|
||||
// expected: []string{
|
||||
// "D0, P[foo], (!!map)::{a: foo_a, thing: foo_thing, c: foo_c}\n",
|
||||
// "D0, P[foobarList], (!!map)::{b: bar_b, thing: foo_thing, c: foobarList_c, a: foo_a}\n",
|
||||
// "D0, P[foobar], (!!map)::{c: foo_c, a: foo_a, thing: foobar_thing}\n",
|
||||
// },
|
||||
// },
|
||||
{
|
||||
skipDoc: true,
|
||||
description: "merge anchor not map",
|
||||
document: "a: &a\n - 0\nc:\n <<: [*a]\n",
|
||||
expectedError: "merge anchor only supports maps, got !!seq instead",
|
||||
expression: "explode(.)",
|
||||
},
|
||||
{
|
||||
description: "Merge one map",
|
||||
subdescription: "see https://yaml.org/type/merge.html",
|
||||
document: specDocument + "- << : *CENTER\n r: 10\n",
|
||||
expression: ".[4] | explode(.)",
|
||||
expected: []string{expectedSpecResult},
|
||||
},
|
||||
{
|
||||
description: "Merge multiple maps",
|
||||
subdescription: "see https://yaml.org/type/merge.html",
|
||||
document: specDocument + "- << : [ *CENTER, *BIG ]\n",
|
||||
expression: ".[4] | explode(.)",
|
||||
expected: []string{"D0, P[4], (!!map)::r: 10\nx: 1\ny: 2\n"},
|
||||
},
|
||||
{
|
||||
description: "Override",
|
||||
subdescription: "see https://yaml.org/type/merge.html",
|
||||
document: specDocument + "- << : [ *BIG, *LEFT, *SMALL ]\n x: 1\n",
|
||||
expression: ".[4] | explode(.)",
|
||||
expected: []string{"D0, P[4], (!!map)::r: 10\nx: 1\ny: 2\n"},
|
||||
},
|
||||
{
|
||||
description: "Get anchor",
|
||||
document: `a: &billyBob cat`,
|
||||
expression: `.a | anchor`,
|
||||
expected: []string{
|
||||
"D0, P[a], (!!str)::billyBob\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Set anchor",
|
||||
document: `a: cat`,
|
||||
expression: `.a anchor = "foobar"`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::a: &foobar cat\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Set anchor relatively using assign-update",
|
||||
document: `a: {b: cat}`,
|
||||
expression: `.a anchor |= .b`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::a: &cat {b: cat}\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
document: `a: {c: cat}`,
|
||||
expression: `.a anchor |= .b`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::a: {c: cat}\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
document: `a: {c: cat}`,
|
||||
expression: `.a anchor = .b`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::a: {c: cat}\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Get alias",
|
||||
document: `{b: &billyBob meow, a: *billyBob}`,
|
||||
expression: `.a | alias`,
|
||||
expected: []string{
|
||||
"D0, P[a], (!!str)::billyBob\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Set alias",
|
||||
document: `{b: &meow purr, a: cat}`,
|
||||
expression: `.a alias = "meow"`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::{b: &meow purr, a: *meow}\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Set alias to blank does nothing",
|
||||
document: `{b: &meow purr, a: cat}`,
|
||||
expression: `.a alias = ""`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::{b: &meow purr, a: cat}\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
document: `{b: &meow purr, a: cat}`,
|
||||
expression: `.a alias = .c`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::{b: &meow purr, a: cat}\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
document: `{b: &meow purr, a: cat}`,
|
||||
expression: `.a alias |= .c`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::{b: &meow purr, a: cat}\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Set alias relatively using assign-update",
|
||||
document: `{b: &meow purr, a: {f: meow}}`,
|
||||
expression: `.a alias |= .f`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::{b: &meow purr, a: *meow}\n",
|
||||
},
|
||||
},
|
||||
// {
|
||||
// skipDoc: true,
|
||||
// document: `{f : {a: &a cat, b: &b {foo: *a}, *a: *b}}`,
|
||||
// expression: `explode(.f)`,
|
||||
// description: "Dont explode alias and anchor - check alias parent",
|
||||
// skipDoc: true,
|
||||
// document: `{a: &a [1], b: *a}`,
|
||||
// expression: `.b[]`,
|
||||
// expected: []string{
|
||||
// "D0, P[], (doc)::{f: {a: cat, b: {foo: cat}, cat: {foo: cat}}}\n",
|
||||
// "D0, P[b], (!!str)::cat\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",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Explode alias and anchor",
|
||||
document: `{f : {a: &a cat, b: *a}}`,
|
||||
expression: `explode(.f)`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::{f: {a: cat, b: cat}}\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Explode with no aliases or anchors",
|
||||
document: `a: mike`,
|
||||
expression: `explode(.a)`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::a: mike\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Explode with alias keys",
|
||||
document: `{f : {a: &a cat, *a: b}}`,
|
||||
expression: `explode(.f)`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::{f: {a: cat, cat: b}}\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Explode with merge anchors",
|
||||
document: mergeDocSample,
|
||||
expression: `explode(.)`,
|
||||
expected: []string{explodeMergeAnchorsExpected},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
document: mergeDocSample,
|
||||
expression: `.foo* | explode(.) | (. style="flow")`,
|
||||
expected: []string{
|
||||
"D0, P[foo], (!!map)::{a: foo_a, thing: foo_thing, c: foo_c}\n",
|
||||
"D0, P[foobarList], (!!map)::{b: bar_b, thing: foo_thing, c: foobarList_c, a: foo_a}\n",
|
||||
"D0, P[foobar], (!!map)::{c: foo_c, a: foo_a, thing: foobar_thing}\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
document: mergeDocSample,
|
||||
expression: `.foo* | explode(explode(.)) | (. style="flow")`,
|
||||
expected: []string{
|
||||
"D0, P[foo], (!!map)::{a: foo_a, thing: foo_thing, c: foo_c}\n",
|
||||
"D0, P[foobarList], (!!map)::{b: bar_b, thing: foo_thing, c: foobarList_c, a: foo_a}\n",
|
||||
"D0, P[foobar], (!!map)::{c: foo_c, a: foo_a, thing: foobar_thing}\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
document: `{f : {a: &a cat, b: &b {foo: *a}, *a: *b}}`,
|
||||
expression: `explode(.f)`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::{f: {a: cat, b: {foo: cat}, cat: {foo: cat}}}\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Dereference and update a field",
|
||||
subdescription: "Use explode with multiply to dereference an object",
|
||||
|
@ -15,7 +15,8 @@ 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, resultC.unwrapDocument())
|
||||
collectedNode.AddChildren([]*CandidateNode{resultC})
|
||||
// collectedNode.Content = append(collectedNode.Content, resultC.unwrapDocument())
|
||||
}
|
||||
}
|
||||
return collectedNode, nil
|
||||
@ -64,7 +65,8 @@ 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))
|
||||
collectCandidate.Content = append(collectCandidate.Content, resultC.unwrapDocument())
|
||||
collectCandidate.AddChildren([]*CandidateNode{resultC})
|
||||
// collectCandidate.Content = append(collectCandidate.Content, resultC.unwrapDocument())
|
||||
}
|
||||
log.Debugf("done collect rhs: %v", expressionNode.RHS.Operation.toString())
|
||||
|
||||
|
@ -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}]`,
|
||||
|
@ -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: ``,
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"container/list"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
parse "github.com/a8m/envsubst/parse"
|
||||
)
|
||||
@ -31,9 +32,10 @@ func envOperator(d *dataTreeNavigator, context Context, expressionNode *Expressi
|
||||
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 {
|
||||
decoder := NewYamlDecoder(ConfiguredYamlPreferences)
|
||||
decoder.Init(strings.NewReader(rawValue))
|
||||
result, err := decoder.Decode()
|
||||
|
||||
if err != nil {
|
||||
|
@ -157,7 +157,7 @@ var envOperatorScenarios = []expressionScenario{
|
||||
document: "# abc\n{v: \"${myenv}\"}\n# xyz\n",
|
||||
expression: `(.. | select(tag == "!!str")) |= envsubst`,
|
||||
expected: []string{
|
||||
"D0, P[], (!!map)::# abc\n{v: \"cat meow\"}\n# xyz\n",
|
||||
"D0, P[], (doc)::# abc\n{v: \"cat meow\"}\n# xyz\n",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ 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 {
|
||||
|
@ -12,181 +12,181 @@ var equalsOperatorScenarios = []expressionScenario{
|
||||
"D0, P[a], (!!bool)::true\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
expression: `(.k | length) == 0`,
|
||||
skipDoc: true,
|
||||
expected: []string{
|
||||
"D0, P[k], (!!bool)::true\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
document: `a: cat`,
|
||||
expression: ".a == .b",
|
||||
expected: []string{
|
||||
"D0, P[a], (!!bool)::false\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
document: `a: cat`,
|
||||
expression: ".b == .a",
|
||||
expected: []string{
|
||||
"D0, P[b], (!!bool)::false\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
document: "cat",
|
||||
document2: "dog",
|
||||
expression: "select(fi==0) == select(fi==1)",
|
||||
expected: []string{
|
||||
"D0, P[], (!!bool)::false\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
document: "{}",
|
||||
expression: "(.a == .b) as $x | .",
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::{}\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
document: "{}",
|
||||
expression: ".a == .b",
|
||||
expected: []string{
|
||||
"D0, P[a], (!!bool)::true\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
document: "{}",
|
||||
expression: "(.a != .b) as $x | .",
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::{}\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
document: "{}",
|
||||
expression: ".a != .b",
|
||||
expected: []string{
|
||||
"D0, P[], (!!bool)::false\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
document: "{a: {b: 10}}",
|
||||
expression: "select(.c != null)",
|
||||
expected: []string{},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
document: "{a: {b: 10}}",
|
||||
expression: "select(.d == .c)",
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::{a: {b: 10}}\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
document: "{a: {b: 10}}",
|
||||
expression: "select(null == .c)",
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::{a: {b: 10}}\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
document: "{a: { b: {things: \"\"}, f: [1], g: [] }}",
|
||||
expression: ".. | select(. == \"\")",
|
||||
expected: []string{
|
||||
"D0, P[a b things], (!!str)::\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Match string",
|
||||
document: `[cat,goat,dog]`,
|
||||
expression: `.[] | (. == "*at")`,
|
||||
expected: []string{
|
||||
"D0, P[0], (!!bool)::true\n",
|
||||
"D0, P[1], (!!bool)::true\n",
|
||||
"D0, P[2], (!!bool)::false\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Don't match string",
|
||||
document: `[cat,goat,dog]`,
|
||||
expression: `.[] | (. != "*at")`,
|
||||
expected: []string{
|
||||
"D0, P[0], (!!bool)::false\n",
|
||||
"D0, P[1], (!!bool)::false\n",
|
||||
"D0, P[2], (!!bool)::true\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Match number",
|
||||
document: `[3, 4, 5]`,
|
||||
expression: `.[] | (. == 4)`,
|
||||
expected: []string{
|
||||
"D0, P[0], (!!bool)::false\n",
|
||||
"D0, P[1], (!!bool)::true\n",
|
||||
"D0, P[2], (!!bool)::false\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Don't match number",
|
||||
document: `[3, 4, 5]`,
|
||||
expression: `.[] | (. != 4)`,
|
||||
expected: []string{
|
||||
"D0, P[0], (!!bool)::true\n",
|
||||
"D0, P[1], (!!bool)::false\n",
|
||||
"D0, P[2], (!!bool)::true\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
document: `a: { cat: {b: apple, c: whatever}, pat: {b: banana} }`,
|
||||
expression: `.a | (.[].b == "apple")`,
|
||||
expected: []string{
|
||||
"D0, P[a cat b], (!!bool)::true\n",
|
||||
"D0, P[a pat b], (!!bool)::false\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
skipDoc: true,
|
||||
document: ``,
|
||||
expression: `null == null`,
|
||||
expected: []string{
|
||||
"D0, P[], (!!bool)::true\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Match nulls",
|
||||
document: ``,
|
||||
expression: `null == ~`,
|
||||
expected: []string{
|
||||
"D0, P[], (!!bool)::true\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Non existent key doesn't equal a value",
|
||||
document: "a: frog",
|
||||
expression: `select(.b != "thing")`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::a: frog\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
description: "Two non existent keys are equal",
|
||||
document: "a: frog",
|
||||
expression: `select(.b == .c)`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::a: frog\n",
|
||||
},
|
||||
},
|
||||
// {
|
||||
// expression: `(.k | length) == 0`,
|
||||
// skipDoc: true,
|
||||
// expected: []string{
|
||||
// "D0, P[k], (!!bool)::true\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// skipDoc: true,
|
||||
// document: `a: cat`,
|
||||
// expression: ".a == .b",
|
||||
// expected: []string{
|
||||
// "D0, P[a], (!!bool)::false\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// skipDoc: true,
|
||||
// document: `a: cat`,
|
||||
// expression: ".b == .a",
|
||||
// expected: []string{
|
||||
// "D0, P[b], (!!bool)::false\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// skipDoc: true,
|
||||
// document: "cat",
|
||||
// document2: "dog",
|
||||
// expression: "select(fi==0) == select(fi==1)",
|
||||
// expected: []string{
|
||||
// "D0, P[], (!!bool)::false\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// skipDoc: true,
|
||||
// document: "{}",
|
||||
// expression: "(.a == .b) as $x | .",
|
||||
// expected: []string{
|
||||
// "D0, P[], (doc)::{}\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// skipDoc: true,
|
||||
// document: "{}",
|
||||
// expression: ".a == .b",
|
||||
// expected: []string{
|
||||
// "D0, P[a], (!!bool)::true\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// skipDoc: true,
|
||||
// document: "{}",
|
||||
// expression: "(.a != .b) as $x | .",
|
||||
// expected: []string{
|
||||
// "D0, P[], (doc)::{}\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// skipDoc: true,
|
||||
// document: "{}",
|
||||
// expression: ".a != .b",
|
||||
// expected: []string{
|
||||
// "D0, P[], (!!bool)::false\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// skipDoc: true,
|
||||
// document: "{a: {b: 10}}",
|
||||
// expression: "select(.c != null)",
|
||||
// expected: []string{},
|
||||
// },
|
||||
// {
|
||||
// skipDoc: true,
|
||||
// document: "{a: {b: 10}}",
|
||||
// expression: "select(.d == .c)",
|
||||
// expected: []string{
|
||||
// "D0, P[], (doc)::{a: {b: 10}}\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// skipDoc: true,
|
||||
// document: "{a: {b: 10}}",
|
||||
// expression: "select(null == .c)",
|
||||
// expected: []string{
|
||||
// "D0, P[], (doc)::{a: {b: 10}}\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// skipDoc: true,
|
||||
// document: "{a: { b: {things: \"\"}, f: [1], g: [] }}",
|
||||
// expression: ".. | select(. == \"\")",
|
||||
// expected: []string{
|
||||
// "D0, P[a b things], (!!str)::\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// description: "Match string",
|
||||
// document: `[cat,goat,dog]`,
|
||||
// expression: `.[] | (. == "*at")`,
|
||||
// expected: []string{
|
||||
// "D0, P[0], (!!bool)::true\n",
|
||||
// "D0, P[1], (!!bool)::true\n",
|
||||
// "D0, P[2], (!!bool)::false\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// description: "Don't match string",
|
||||
// document: `[cat,goat,dog]`,
|
||||
// expression: `.[] | (. != "*at")`,
|
||||
// expected: []string{
|
||||
// "D0, P[0], (!!bool)::false\n",
|
||||
// "D0, P[1], (!!bool)::false\n",
|
||||
// "D0, P[2], (!!bool)::true\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// description: "Match number",
|
||||
// document: `[3, 4, 5]`,
|
||||
// expression: `.[] | (. == 4)`,
|
||||
// expected: []string{
|
||||
// "D0, P[0], (!!bool)::false\n",
|
||||
// "D0, P[1], (!!bool)::true\n",
|
||||
// "D0, P[2], (!!bool)::false\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// description: "Don't match number",
|
||||
// document: `[3, 4, 5]`,
|
||||
// expression: `.[] | (. != 4)`,
|
||||
// expected: []string{
|
||||
// "D0, P[0], (!!bool)::true\n",
|
||||
// "D0, P[1], (!!bool)::false\n",
|
||||
// "D0, P[2], (!!bool)::true\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// skipDoc: true,
|
||||
// document: `a: { cat: {b: apple, c: whatever}, pat: {b: banana} }`,
|
||||
// expression: `.a | (.[].b == "apple")`,
|
||||
// expected: []string{
|
||||
// "D0, P[a cat b], (!!bool)::true\n",
|
||||
// "D0, P[a pat b], (!!bool)::false\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// skipDoc: true,
|
||||
// document: ``,
|
||||
// expression: `null == null`,
|
||||
// expected: []string{
|
||||
// "D0, P[], (!!bool)::true\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// description: "Match nulls",
|
||||
// document: ``,
|
||||
// expression: `null == ~`,
|
||||
// expected: []string{
|
||||
// "D0, P[], (!!bool)::true\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// description: "Non existent key doesn't equal a value",
|
||||
// document: "a: frog",
|
||||
// expression: `select(.b != "thing")`,
|
||||
// expected: []string{
|
||||
// "D0, P[], (doc)::a: frog\n",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// description: "Two non existent keys are equal",
|
||||
// document: "a: frog",
|
||||
// expression: `select(.b == .c)`,
|
||||
// expected: []string{
|
||||
// "D0, P[], (doc)::a: frog\n",
|
||||
// },
|
||||
// },
|
||||
}
|
||||
|
||||
func TestEqualOperatorScenarios(t *testing.T) {
|
||||
|
@ -203,7 +203,13 @@ func traverseArrayWithIndices(candidate *CandidateNode, indices []*CandidateNode
|
||||
node.Style = 0
|
||||
}
|
||||
|
||||
node.Content = append(node.Content, &CandidateNode{Tag: "!!null", Kind: ScalarNode, Value: "null"})
|
||||
valueNode := node.CreateChild()
|
||||
valueNode.Kind = ScalarNode
|
||||
valueNode.Tag = "!!null"
|
||||
valueNode.Value = "null"
|
||||
valueNode.Key = createScalarNode(contentLength, fmt.Sprintf("%v", contentLength))
|
||||
|
||||
node.Content = append(node.Content, valueNode)
|
||||
contentLength = len(node.Content)
|
||||
}
|
||||
|
||||
@ -235,7 +241,11 @@ func traverseMap(context Context, matchingNode *CandidateNode, keyNode *Candidat
|
||||
if !splat && !prefs.DontAutoCreate && !context.DontAutoCreate && newMatches.Len() == 0 {
|
||||
log.Debugf("no matches, creating one")
|
||||
//no matches, create one automagically
|
||||
valueNode := &CandidateNode{Tag: "!!null", Kind: ScalarNode, Value: "null"}
|
||||
valueNode := matchingNode.CreateChild()
|
||||
valueNode.Kind = ScalarNode
|
||||
valueNode.Tag = "!!null"
|
||||
valueNode.Value = "null"
|
||||
valueNode.Key = keyNode
|
||||
|
||||
if len(matchingNode.Content) == 0 {
|
||||
matchingNode.Style = 0
|
||||
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user