mirror of
https://github.com/mikefarah/yq.git
synced 2025-01-14 20:45:36 +00:00
wip - rabbit hole :/
This commit is contained in:
parent
cd50b35787
commit
42843763ca
@ -63,7 +63,6 @@ func (o *CandidateNode) copyFromYamlNode(node *yaml.Node, anchorMap map[string]*
|
|||||||
o.Alias = anchorMap[node.Alias.Anchor]
|
o.Alias = anchorMap[node.Alias.Anchor]
|
||||||
log.Debug("set alias to %v", NodeToString(anchorMap[node.Alias.Anchor]))
|
log.Debug("set alias to %v", NodeToString(anchorMap[node.Alias.Anchor]))
|
||||||
}
|
}
|
||||||
|
|
||||||
o.HeadComment = node.HeadComment
|
o.HeadComment = node.HeadComment
|
||||||
o.LineComment = node.LineComment
|
o.LineComment = node.LineComment
|
||||||
o.FootComment = node.FootComment
|
o.FootComment = node.FootComment
|
||||||
@ -107,7 +106,6 @@ func (o *CandidateNode) decodeIntoChild(childNode *yaml.Node, anchorMap map[stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (o *CandidateNode) UnmarshalYAML(node *yaml.Node, anchorMap map[string]*CandidateNode) error {
|
func (o *CandidateNode) UnmarshalYAML(node *yaml.Node, anchorMap map[string]*CandidateNode) error {
|
||||||
|
|
||||||
log.Debugf("UnmarshalYAML %v", node.Tag)
|
log.Debugf("UnmarshalYAML %v", node.Tag)
|
||||||
switch node.Kind {
|
switch node.Kind {
|
||||||
case yaml.DocumentNode:
|
case yaml.DocumentNode:
|
||||||
|
@ -22,6 +22,7 @@ type yamlDecoder struct {
|
|||||||
|
|
||||||
readAnything bool
|
readAnything bool
|
||||||
firstFile bool
|
firstFile bool
|
||||||
|
documentIndex uint
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewYamlDecoder(prefs YamlPreferences) Decoder {
|
func NewYamlDecoder(prefs YamlPreferences) Decoder {
|
||||||
@ -93,6 +94,7 @@ func (dec *yamlDecoder) Init(reader io.Reader) error {
|
|||||||
dec.readAnything = false
|
dec.readAnything = false
|
||||||
dec.decoder = *yaml.NewDecoder(readerToUse)
|
dec.decoder = *yaml.NewDecoder(readerToUse)
|
||||||
dec.firstFile = false
|
dec.firstFile = false
|
||||||
|
dec.documentIndex = 0
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,14 +119,18 @@ func (dec *yamlDecoder) Decode() (*CandidateNode, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
candidateNode := CandidateNode{}
|
candidateNode := CandidateNode{Document: dec.documentIndex}
|
||||||
candidateNode.UnmarshalYAML(&yamlNode, make(map[string]*CandidateNode))
|
err = candidateNode.UnmarshalYAML(&yamlNode, make(map[string]*CandidateNode))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
if dec.leadingContent != "" {
|
if dec.leadingContent != "" {
|
||||||
candidateNode.LeadingContent = dec.leadingContent
|
candidateNode.LeadingContent = dec.leadingContent
|
||||||
dec.leadingContent = ""
|
dec.leadingContent = ""
|
||||||
}
|
}
|
||||||
dec.readAnything = true
|
dec.readAnything = true
|
||||||
|
dec.documentIndex++
|
||||||
// move document comments into candidate node
|
// move document comments into candidate node
|
||||||
// otherwise unwrap drops them.
|
// otherwise unwrap drops them.
|
||||||
candidateNode.TrailingContent = candidateNode.FootComment
|
candidateNode.TrailingContent = candidateNode.FootComment
|
||||||
|
@ -93,8 +93,7 @@ a:
|
|||||||
## String concatenation
|
## String concatenation
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
a: cat
|
{a: cat, b: meow}
|
||||||
b: meow
|
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
@ -102,8 +101,7 @@ yq '.a += .b' sample.yml
|
|||||||
```
|
```
|
||||||
will output
|
will output
|
||||||
```yaml
|
```yaml
|
||||||
a: catmeow
|
{a: catmeow, b: meow}
|
||||||
b: meow
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Number addition - float
|
## Number addition - float
|
||||||
@ -111,8 +109,7 @@ If the lhs or rhs are floats then the expression will be calculated with floats.
|
|||||||
|
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
a: 3
|
{a: 3, b: 4.9}
|
||||||
b: 4.9
|
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
@ -120,8 +117,7 @@ yq '.a = .a + .b' sample.yml
|
|||||||
```
|
```
|
||||||
will output
|
will output
|
||||||
```yaml
|
```yaml
|
||||||
a: 7.9
|
{a: 7.9, b: 4.9}
|
||||||
b: 4.9
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Number addition - int
|
## Number addition - int
|
||||||
@ -129,8 +125,7 @@ If both the lhs and rhs are ints then the expression will be calculated with int
|
|||||||
|
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
a: 3
|
{a: 3, b: 4}
|
||||||
b: 4
|
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
@ -138,15 +133,13 @@ yq '.a = .a + .b' sample.yml
|
|||||||
```
|
```
|
||||||
will output
|
will output
|
||||||
```yaml
|
```yaml
|
||||||
a: 7
|
{a: 7, b: 4}
|
||||||
b: 4
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Increment numbers
|
## Increment numbers
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
a: 3
|
{a: 3, b: 5}
|
||||||
b: 5
|
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
@ -154,8 +147,7 @@ yq '.[] += 1' sample.yml
|
|||||||
```
|
```
|
||||||
will output
|
will output
|
||||||
```yaml
|
```yaml
|
||||||
a: 4
|
{a: 4, b: 6}
|
||||||
b: 6
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Date addition
|
## Date addition
|
||||||
|
@ -5,7 +5,7 @@ This operator is used to provide alternative (or default) values when a particul
|
|||||||
## LHS is defined
|
## LHS is defined
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
a: bridge
|
{a: bridge}
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
@ -33,7 +33,7 @@ hello
|
|||||||
## LHS is null
|
## LHS is null
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
a: ~
|
{a: ~}
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
@ -47,7 +47,7 @@ hello
|
|||||||
## LHS is false
|
## LHS is false
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
a: false
|
{a: false}
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
@ -61,8 +61,7 @@ hello
|
|||||||
## RHS is an expression
|
## RHS is an expression
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
a: false
|
{a: false, b: cat}
|
||||||
b: cat
|
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
|
@ -27,9 +27,7 @@ x: frog
|
|||||||
## Update node to be the child value
|
## Update node to be the child value
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
a:
|
{a: {b: {g: foof}}}
|
||||||
b:
|
|
||||||
g: foof
|
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
@ -37,16 +35,13 @@ yq '.a |= .b' sample.yml
|
|||||||
```
|
```
|
||||||
will output
|
will output
|
||||||
```yaml
|
```yaml
|
||||||
a:
|
{a: {g: foof}}
|
||||||
g: foof
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Double elements in an array
|
## Double elements in an array
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
- 1
|
[1, 2, 3]
|
||||||
- 2
|
|
||||||
- 3
|
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
@ -54,9 +49,7 @@ yq '.[] |= . * 2' sample.yml
|
|||||||
```
|
```
|
||||||
will output
|
will output
|
||||||
```yaml
|
```yaml
|
||||||
- 2
|
[2, 4, 6]
|
||||||
- 4
|
|
||||||
- 6
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Update node from another file
|
## Update node from another file
|
||||||
@ -64,11 +57,11 @@ Note this will also work when the second file is a scalar (string/number)
|
|||||||
|
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
a: apples
|
{a: apples}
|
||||||
```
|
```
|
||||||
And another sample another.yml file of:
|
And another sample another.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
b: bob
|
{b: bob}
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
@ -76,16 +69,13 @@ yq eval-all 'select(fileIndex==0).a = select(fileIndex==1) | select(fileIndex==0
|
|||||||
```
|
```
|
||||||
will output
|
will output
|
||||||
```yaml
|
```yaml
|
||||||
a:
|
{a: {b: bob}}
|
||||||
b: bob
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Update node to be the sibling value
|
## Update node to be the sibling value
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
a:
|
{a: {b: child}, b: sibling}
|
||||||
b: child
|
|
||||||
b: sibling
|
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
@ -93,16 +83,13 @@ yq '.a = .b' sample.yml
|
|||||||
```
|
```
|
||||||
will output
|
will output
|
||||||
```yaml
|
```yaml
|
||||||
a: sibling
|
{a: sibling, b: sibling}
|
||||||
b: sibling
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Updated multiple paths
|
## Updated multiple paths
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
a: fieldA
|
{a: fieldA, b: fieldB, c: fieldC}
|
||||||
b: fieldB
|
|
||||||
c: fieldC
|
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
@ -110,16 +97,13 @@ yq '(.a, .c) = "potato"' sample.yml
|
|||||||
```
|
```
|
||||||
will output
|
will output
|
||||||
```yaml
|
```yaml
|
||||||
a: potato
|
{a: potato, b: fieldB, c: potato}
|
||||||
b: fieldB
|
|
||||||
c: potato
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Update string value
|
## Update string value
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
a:
|
{a: {b: apple}}
|
||||||
b: apple
|
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
@ -127,8 +111,7 @@ yq '.a.b = "frog"' sample.yml
|
|||||||
```
|
```
|
||||||
will output
|
will output
|
||||||
```yaml
|
```yaml
|
||||||
a:
|
{a: {b: frog}}
|
||||||
b: frog
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Update string value via |=
|
## Update string value via |=
|
||||||
@ -136,8 +119,7 @@ Note there is no difference between `=` and `|=` when the RHS is a scalar
|
|||||||
|
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
a:
|
{a: {b: apple}}
|
||||||
b: apple
|
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
@ -145,8 +127,7 @@ yq '.a.b |= "frog"' sample.yml
|
|||||||
```
|
```
|
||||||
will output
|
will output
|
||||||
```yaml
|
```yaml
|
||||||
a:
|
{a: {b: frog}}
|
||||||
b: frog
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Update deeply selected results
|
## Update deeply selected results
|
||||||
@ -154,9 +135,7 @@ Note that the LHS is wrapped in brackets! This is to ensure we don't first filte
|
|||||||
|
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
a:
|
{a: {b: apple, c: cactus}}
|
||||||
b: apple
|
|
||||||
c: cactus
|
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
@ -164,17 +143,13 @@ yq '(.a[] | select(. == "apple")) = "frog"' sample.yml
|
|||||||
```
|
```
|
||||||
will output
|
will output
|
||||||
```yaml
|
```yaml
|
||||||
a:
|
{a: {b: frog, c: cactus}}
|
||||||
b: frog
|
|
||||||
c: cactus
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Update array values
|
## Update array values
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
- candy
|
[candy, apple, sandy]
|
||||||
- apple
|
|
||||||
- sandy
|
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
@ -182,9 +157,7 @@ yq '(.[] | select(. == "*andy")) = "bogs"' sample.yml
|
|||||||
```
|
```
|
||||||
will output
|
will output
|
||||||
```yaml
|
```yaml
|
||||||
- bogs
|
[bogs, apple, bogs]
|
||||||
- apple
|
|
||||||
- bogs
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Update empty object
|
## Update empty object
|
||||||
|
@ -39,12 +39,7 @@ false
|
|||||||
## Matching nodes with select, equals and or
|
## Matching nodes with select, equals and or
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
- a: bird
|
[{a: bird, b: dog}, {a: frog, b: bird}, {a: cat, b: fly}]
|
||||||
b: dog
|
|
||||||
- a: frog
|
|
||||||
b: bird
|
|
||||||
- a: cat
|
|
||||||
b: fly
|
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
@ -52,17 +47,14 @@ yq '[.[] | select(.a == "cat" or .b == "dog")]' sample.yml
|
|||||||
```
|
```
|
||||||
will output
|
will output
|
||||||
```yaml
|
```yaml
|
||||||
- a: bird
|
- {a: bird, b: dog}
|
||||||
b: dog
|
- {a: cat, b: fly}
|
||||||
- a: cat
|
|
||||||
b: fly
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## `any` returns true if any boolean in a given array is true
|
## `any` returns true if any boolean in a given array is true
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
- false
|
[false, true]
|
||||||
- true
|
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
@ -110,8 +102,7 @@ b: false
|
|||||||
## `all` returns true if all booleans in a given array are true
|
## `all` returns true if all booleans in a given array are true
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
- true
|
[true, true]
|
||||||
- true
|
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
|
@ -26,8 +26,7 @@ will output
|
|||||||
## Collect many
|
## Collect many
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
a: cat
|
{a: cat, b: dog}
|
||||||
b: dog
|
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
|
@ -10,56 +10,6 @@ This will set the LHS nodes' comments equal to the expression on the RHS. The RH
|
|||||||
### relative form: `|=`
|
### relative form: `|=`
|
||||||
This is similar to the plain form, but it evaluates the RHS with _each matching LHS node as context_. This is useful if you want to set the comments as a relative expression of the node, for instance its value or path.
|
This is similar to the plain form, but it evaluates the RHS with _each matching LHS node as context_. This is useful if you want to set the comments as a relative expression of the node, for instance its value or path.
|
||||||
|
|
||||||
## Set line comment
|
|
||||||
Set the comment on the key node for more reliability (see below).
|
|
||||||
|
|
||||||
Given a sample.yml file of:
|
|
||||||
```yaml
|
|
||||||
a: cat
|
|
||||||
```
|
|
||||||
then
|
|
||||||
```bash
|
|
||||||
yq '.a line_comment="single"' sample.yml
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
a: cat # single
|
|
||||||
```
|
|
||||||
|
|
||||||
## Set line comment of a maps/arrays
|
|
||||||
For maps and arrays, you need to set the line comment on the _key_ node. This will also work for scalars.
|
|
||||||
|
|
||||||
Given a sample.yml file of:
|
|
||||||
```yaml
|
|
||||||
a:
|
|
||||||
b: things
|
|
||||||
```
|
|
||||||
then
|
|
||||||
```bash
|
|
||||||
yq '(.a | key) line_comment="single"' sample.yml
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
a:
|
|
||||||
b: things
|
|
||||||
```
|
|
||||||
|
|
||||||
## Use update assign to perform relative updates
|
|
||||||
Given a sample.yml file of:
|
|
||||||
```yaml
|
|
||||||
a: cat
|
|
||||||
b: dog
|
|
||||||
```
|
|
||||||
then
|
|
||||||
```bash
|
|
||||||
yq '.. line_comment |= .' sample.yml
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
a: cat # cat
|
|
||||||
b: dog # dog
|
|
||||||
```
|
|
||||||
|
|
||||||
## Where is the comment - map key example
|
## Where is the comment - map key example
|
||||||
The underlying yaml parser can assign comments in a document to surprising nodes. Use an expression like this to find where you comment is. 'p' indicates the path, 'isKey' is if the node is a map key (as opposed to a map value).
|
The underlying yaml parser can assign comments in a document to surprising nodes. Use an expression like this to find where you comment is. 'p' indicates the path, 'isKey' is if the node is a map key (as opposed to a map value).
|
||||||
From this, you can see the 'hello-world-comment' is actually on the 'hello' key
|
From this, you can see the 'hello-world-comment' is actually on the 'hello' key
|
||||||
@ -83,11 +33,9 @@ will output
|
|||||||
- p: hello
|
- p: hello
|
||||||
isKey: null
|
isKey: null
|
||||||
true: null
|
true: null
|
||||||
hc: null
|
hc: ""
|
||||||
"": null
|
lc: hello-world-comment
|
||||||
lc: null
|
fc: ""
|
||||||
hello-world-comment: null
|
|
||||||
fc: null
|
|
||||||
- p: hello
|
- p: hello
|
||||||
isKey: false
|
isKey: false
|
||||||
hc: ""
|
hc: ""
|
||||||
@ -96,10 +44,9 @@ will output
|
|||||||
- p: hello.message
|
- p: hello.message
|
||||||
isKey: null
|
isKey: null
|
||||||
true: null
|
true: null
|
||||||
hc: null
|
hc: ""
|
||||||
"": null
|
lc: ""
|
||||||
lc: null
|
fc: ""
|
||||||
fc: null
|
|
||||||
- p: hello.message
|
- p: hello.message
|
||||||
isKey: false
|
isKey: false
|
||||||
hc: ""
|
hc: ""
|
||||||
@ -107,242 +54,3 @@ will output
|
|||||||
fc: ""
|
fc: ""
|
||||||
```
|
```
|
||||||
|
|
||||||
## Retrieve comment - map key example
|
|
||||||
From the previous example, we know that the comment is on the 'hello' _key_ as a lineComment
|
|
||||||
|
|
||||||
Given a sample.yml file of:
|
|
||||||
```yaml
|
|
||||||
hello: # hello-world-comment
|
|
||||||
message: world
|
|
||||||
```
|
|
||||||
then
|
|
||||||
```bash
|
|
||||||
yq '.hello | key | line_comment' sample.yml
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
hello-world-comment
|
|
||||||
```
|
|
||||||
|
|
||||||
## Where is the comment - array example
|
|
||||||
The underlying yaml parser can assign comments in a document to surprising nodes. Use an expression like this to find where you comment is. 'p' indicates the path, 'isKey' is if the node is a map key (as opposed to a map value).
|
|
||||||
From this, you can see the 'under-name-comment' is actually on the first child
|
|
||||||
|
|
||||||
Given a sample.yml file of:
|
|
||||||
```yaml
|
|
||||||
name:
|
|
||||||
# under-name-comment
|
|
||||||
- first-array-child
|
|
||||||
```
|
|
||||||
then
|
|
||||||
```bash
|
|
||||||
yq '[... | {"p": path | join("."), "isKey": is_key, "hc": headComment, "lc": lineComment, "fc": footComment}]' sample.yml
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
- p: ""
|
|
||||||
isKey: false
|
|
||||||
hc: ""
|
|
||||||
lc: ""
|
|
||||||
fc: ""
|
|
||||||
- p: name
|
|
||||||
isKey: null
|
|
||||||
true: null
|
|
||||||
hc: null
|
|
||||||
"": null
|
|
||||||
lc: null
|
|
||||||
fc: null
|
|
||||||
- p: name
|
|
||||||
isKey: false
|
|
||||||
hc: ""
|
|
||||||
lc: ""
|
|
||||||
fc: ""
|
|
||||||
- p: name.0
|
|
||||||
isKey: false
|
|
||||||
hc: under-name-comment
|
|
||||||
lc: ""
|
|
||||||
fc: ""
|
|
||||||
```
|
|
||||||
|
|
||||||
## Retrieve comment - array example
|
|
||||||
From the previous example, we know that the comment is on the first child as a headComment
|
|
||||||
|
|
||||||
Given a sample.yml file of:
|
|
||||||
```yaml
|
|
||||||
name:
|
|
||||||
# under-name-comment
|
|
||||||
- first-array-child
|
|
||||||
```
|
|
||||||
then
|
|
||||||
```bash
|
|
||||||
yq '.name[0] | headComment' sample.yml
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
under-name-comment
|
|
||||||
```
|
|
||||||
|
|
||||||
## Set head comment
|
|
||||||
Given a sample.yml file of:
|
|
||||||
```yaml
|
|
||||||
a: cat
|
|
||||||
```
|
|
||||||
then
|
|
||||||
```bash
|
|
||||||
yq '. head_comment="single"' sample.yml
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
# single
|
|
||||||
|
|
||||||
a: cat
|
|
||||||
```
|
|
||||||
|
|
||||||
## Set head comment of a map entry
|
|
||||||
Given a sample.yml file of:
|
|
||||||
```yaml
|
|
||||||
f: foo
|
|
||||||
a:
|
|
||||||
b: cat
|
|
||||||
```
|
|
||||||
then
|
|
||||||
```bash
|
|
||||||
yq '(.a | key) head_comment="single"' sample.yml
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
f: foo
|
|
||||||
a:
|
|
||||||
b: cat
|
|
||||||
```
|
|
||||||
|
|
||||||
## Set foot comment, using an expression
|
|
||||||
Given a sample.yml file of:
|
|
||||||
```yaml
|
|
||||||
a: cat
|
|
||||||
```
|
|
||||||
then
|
|
||||||
```bash
|
|
||||||
yq '. foot_comment=.a' sample.yml
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
a: cat
|
|
||||||
# cat
|
|
||||||
```
|
|
||||||
|
|
||||||
## Remove comment
|
|
||||||
Given a sample.yml file of:
|
|
||||||
```yaml
|
|
||||||
a: cat # comment
|
|
||||||
b: dog # leave this
|
|
||||||
```
|
|
||||||
then
|
|
||||||
```bash
|
|
||||||
yq '.a line_comment=""' sample.yml
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
a: cat
|
|
||||||
b: dog # leave this
|
|
||||||
```
|
|
||||||
|
|
||||||
## Remove (strip) all comments
|
|
||||||
Note the use of `...` to ensure key nodes are included.
|
|
||||||
|
|
||||||
Given a sample.yml file of:
|
|
||||||
```yaml
|
|
||||||
# hi
|
|
||||||
|
|
||||||
a: cat # comment
|
|
||||||
# great
|
|
||||||
b: # key comment
|
|
||||||
```
|
|
||||||
then
|
|
||||||
```bash
|
|
||||||
yq '... comments=""' sample.yml
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
# hi
|
|
||||||
|
|
||||||
a: cat
|
|
||||||
b:
|
|
||||||
```
|
|
||||||
|
|
||||||
## Get line comment
|
|
||||||
Given a sample.yml file of:
|
|
||||||
```yaml
|
|
||||||
# welcome!
|
|
||||||
|
|
||||||
a: cat # meow
|
|
||||||
# have a great day
|
|
||||||
```
|
|
||||||
then
|
|
||||||
```bash
|
|
||||||
yq '.a | line_comment' sample.yml
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
meow
|
|
||||||
```
|
|
||||||
|
|
||||||
## Get head comment
|
|
||||||
Given a sample.yml file of:
|
|
||||||
```yaml
|
|
||||||
# welcome!
|
|
||||||
|
|
||||||
a: cat # meow
|
|
||||||
|
|
||||||
# have a great day
|
|
||||||
```
|
|
||||||
then
|
|
||||||
```bash
|
|
||||||
yq '. | head_comment' sample.yml
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
welcome!
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
## Head comment with document split
|
|
||||||
Given a sample.yml file of:
|
|
||||||
```yaml
|
|
||||||
# welcome!
|
|
||||||
---
|
|
||||||
# bob
|
|
||||||
a: cat # meow
|
|
||||||
|
|
||||||
# have a great day
|
|
||||||
```
|
|
||||||
then
|
|
||||||
```bash
|
|
||||||
yq 'head_comment' sample.yml
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
welcome!
|
|
||||||
bob
|
|
||||||
```
|
|
||||||
|
|
||||||
## Get foot comment
|
|
||||||
Given a sample.yml file of:
|
|
||||||
```yaml
|
|
||||||
# welcome!
|
|
||||||
|
|
||||||
a: cat # meow
|
|
||||||
|
|
||||||
# have a great day
|
|
||||||
# no really
|
|
||||||
```
|
|
||||||
then
|
|
||||||
```bash
|
|
||||||
yq '. | foot_comment' sample.yml
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
have a great day
|
|
||||||
no really
|
|
||||||
```
|
|
||||||
|
|
||||||
|
@ -15,9 +15,7 @@ Array is equal or subset of
|
|||||||
|
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
- foobar
|
[foobar, foobaz, blarp]
|
||||||
- foobaz
|
|
||||||
- blarp
|
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
@ -33,9 +31,7 @@ Subtract the superset array from the subset, if there's anything left, it's not
|
|||||||
|
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
- foobar
|
[foobar, foobaz, blarp]
|
||||||
- foobaz
|
|
||||||
- blarp
|
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
@ -49,12 +45,7 @@ false
|
|||||||
## Object included in array
|
## Object included in array
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
"foo": 12
|
{"foo": 12, "bar": [1, 2, {"barp": 12, "blip": 13}]}
|
||||||
"bar":
|
|
||||||
- 1
|
|
||||||
- 2
|
|
||||||
- "barp": 12
|
|
||||||
"blip": 13
|
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
@ -68,22 +59,21 @@ true
|
|||||||
## Object not included in array
|
## Object not included in array
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
"foo": 12
|
{"foo": 12, "bar": [1, 2, {"barp": 12, "blip": 13}]}
|
||||||
"bar":
|
|
||||||
- 1
|
|
||||||
- 2
|
|
||||||
- "barp": 12
|
|
||||||
"blip": 13
|
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
yq 'contains({"foo": 12, "bar": [{"barp": 15}]})' sample.yml
|
yq 'contains({"foo": 12, "bar": [{"barp": 15}]})' sample.yml
|
||||||
```
|
```
|
||||||
will output
|
will output
|
||||||
|
```yaml
|
||||||
|
false
|
||||||
|
```
|
||||||
|
|
||||||
## String contains substring
|
## String contains substring
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
foobar
|
"foobar"
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
@ -97,7 +87,7 @@ true
|
|||||||
## String equals string
|
## String equals string
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
meow
|
"meow"
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
|
@ -15,7 +15,7 @@ will output
|
|||||||
## Wrap (prefix) existing object
|
## Wrap (prefix) existing object
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
name: Mike
|
{name: Mike}
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
@ -23,17 +23,13 @@ yq '{"wrap": .}' sample.yml
|
|||||||
```
|
```
|
||||||
will output
|
will output
|
||||||
```yaml
|
```yaml
|
||||||
wrap:
|
wrap: {name: Mike}
|
||||||
name: Mike
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Using splat to create multiple objects
|
## Using splat to create multiple objects
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
name: Mike
|
{name: Mike, pets: [cat, dog]}
|
||||||
pets:
|
|
||||||
- cat
|
|
||||||
- dog
|
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
@ -48,15 +44,9 @@ Mike: dog
|
|||||||
## Working with multiple documents
|
## Working with multiple documents
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
name: Mike
|
{name: Mike, pets: [cat, dog]}
|
||||||
pets:
|
|
||||||
- cat
|
|
||||||
- dog
|
|
||||||
---
|
---
|
||||||
name: Rosey
|
{name: Rosey, pets: [monkey, sheep]}
|
||||||
pets:
|
|
||||||
- monkey
|
|
||||||
- sheep
|
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
|
@ -2,123 +2,10 @@
|
|||||||
|
|
||||||
Use the `keys` operator to return map keys or array indices.
|
Use the `keys` operator to return map keys or array indices.
|
||||||
|
|
||||||
## Map keys
|
|
||||||
Given a sample.yml file of:
|
|
||||||
```yaml
|
|
||||||
dog: woof
|
|
||||||
cat: meow
|
|
||||||
```
|
|
||||||
then
|
|
||||||
```bash
|
|
||||||
yq 'keys' sample.yml
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
- dog
|
|
||||||
- cat
|
|
||||||
```
|
|
||||||
|
|
||||||
## Array keys
|
|
||||||
Given a sample.yml file of:
|
|
||||||
```yaml
|
|
||||||
- apple
|
|
||||||
- banana
|
|
||||||
```
|
|
||||||
then
|
|
||||||
```bash
|
|
||||||
yq 'keys' sample.yml
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
- 0
|
|
||||||
- 1
|
|
||||||
```
|
|
||||||
|
|
||||||
## Retrieve array key
|
|
||||||
Given a sample.yml file of:
|
|
||||||
```yaml
|
|
||||||
- 1
|
|
||||||
- 2
|
|
||||||
- 3
|
|
||||||
```
|
|
||||||
then
|
|
||||||
```bash
|
|
||||||
yq '.[1] | key' sample.yml
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
1
|
|
||||||
```
|
|
||||||
|
|
||||||
## Retrieve map key
|
|
||||||
Given a sample.yml file of:
|
|
||||||
```yaml
|
|
||||||
a: thing
|
|
||||||
```
|
|
||||||
then
|
|
||||||
```bash
|
|
||||||
yq '.a | key' sample.yml
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
a
|
|
||||||
```
|
|
||||||
|
|
||||||
## No key
|
|
||||||
Given a sample.yml file of:
|
|
||||||
```yaml
|
|
||||||
{}
|
|
||||||
```
|
|
||||||
then
|
|
||||||
```bash
|
|
||||||
yq 'key' sample.yml
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
```
|
|
||||||
|
|
||||||
## Update map key
|
|
||||||
Given a sample.yml file of:
|
|
||||||
```yaml
|
|
||||||
a:
|
|
||||||
x: 3
|
|
||||||
y: 4
|
|
||||||
```
|
|
||||||
then
|
|
||||||
```bash
|
|
||||||
yq '(.a.x | key) = "meow"' sample.yml
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
a:
|
|
||||||
meow: 3
|
|
||||||
y: 4
|
|
||||||
```
|
|
||||||
|
|
||||||
## Get comment from map key
|
|
||||||
Given a sample.yml file of:
|
|
||||||
```yaml
|
|
||||||
a:
|
|
||||||
# comment on key
|
|
||||||
x: 3
|
|
||||||
y: 4
|
|
||||||
```
|
|
||||||
then
|
|
||||||
```bash
|
|
||||||
yq '.a.x | key | headComment' sample.yml
|
|
||||||
```
|
|
||||||
will output
|
|
||||||
```yaml
|
|
||||||
comment on key
|
|
||||||
```
|
|
||||||
|
|
||||||
## Check node is a key
|
## Check node is a key
|
||||||
Given a sample.yml file of:
|
Given a sample.yml file of:
|
||||||
```yaml
|
```yaml
|
||||||
a:
|
a: frog
|
||||||
b:
|
|
||||||
- cat
|
|
||||||
c: frog
|
|
||||||
```
|
```
|
||||||
then
|
then
|
||||||
```bash
|
```bash
|
||||||
@ -131,23 +18,9 @@ will output
|
|||||||
tag: '!!map'
|
tag: '!!map'
|
||||||
- p: a
|
- p: a
|
||||||
isKey: true
|
isKey: true
|
||||||
tag: '!!str'
|
tag: null
|
||||||
|
'!!str': null
|
||||||
- p: a
|
- p: a
|
||||||
isKey: false
|
|
||||||
tag: '!!map'
|
|
||||||
- p: a.b
|
|
||||||
isKey: true
|
|
||||||
tag: '!!str'
|
|
||||||
- p: a.b
|
|
||||||
isKey: false
|
|
||||||
tag: '!!seq'
|
|
||||||
- p: a.b.0
|
|
||||||
isKey: false
|
|
||||||
tag: '!!str'
|
|
||||||
- p: a.c
|
|
||||||
isKey: true
|
|
||||||
tag: '!!str'
|
|
||||||
- p: a.c
|
|
||||||
isKey: false
|
isKey: false
|
||||||
tag: '!!str'
|
tag: '!!str'
|
||||||
```
|
```
|
||||||
|
@ -37,9 +37,13 @@ func assignCommentsOperator(d *dataTreeNavigator, context Context, expressionNod
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Debugf("AssignComments comment is %v", comment)
|
||||||
|
|
||||||
for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() {
|
for el := lhs.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||||
candidate := el.Value.(*CandidateNode)
|
candidate := el.Value.(*CandidateNode)
|
||||||
|
|
||||||
|
log.Debugf("AssignComments lhs %v", NodeToString(candidate))
|
||||||
|
|
||||||
if expressionNode.Operation.UpdateAssign {
|
if expressionNode.Operation.UpdateAssign {
|
||||||
rhs, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(candidate), expressionNode.RHS)
|
rhs, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(candidate), expressionNode.RHS)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -53,6 +57,7 @@ func assignCommentsOperator(d *dataTreeNavigator, context Context, expressionNod
|
|||||||
|
|
||||||
log.Debugf("Setting comment of : %v", candidate.GetKey())
|
log.Debugf("Setting comment of : %v", candidate.GetKey())
|
||||||
if preferences.LineComment {
|
if preferences.LineComment {
|
||||||
|
log.Debugf("Setting line comment of : %v to %v", candidate.GetKey(), comment)
|
||||||
candidate.LineComment = comment
|
candidate.LineComment = comment
|
||||||
}
|
}
|
||||||
if preferences.HeadComment {
|
if preferences.HeadComment {
|
||||||
@ -60,10 +65,11 @@ func assignCommentsOperator(d *dataTreeNavigator, context Context, expressionNod
|
|||||||
candidate.LeadingContent = "" // clobber the leading content, if there was any.
|
candidate.LeadingContent = "" // clobber the leading content, if there was any.
|
||||||
}
|
}
|
||||||
if preferences.FootComment && candidate.Kind == DocumentNode && comment != "" {
|
if preferences.FootComment && candidate.Kind == DocumentNode && comment != "" {
|
||||||
|
log.Debugf("AssignComments - setting line comment to %v", comment)
|
||||||
candidate.TrailingContent = "# " + comment
|
candidate.TrailingContent = "# " + comment
|
||||||
} else if preferences.FootComment && candidate.Kind == DocumentNode {
|
} else if preferences.FootComment && candidate.Kind == DocumentNode {
|
||||||
|
log.Debugf("AssignComments - setting line comment to %v", comment)
|
||||||
candidate.TrailingContent = comment
|
candidate.TrailingContent = comment
|
||||||
|
|
||||||
} else if preferences.FootComment && candidate.Kind != DocumentNode {
|
} else if preferences.FootComment && candidate.Kind != DocumentNode {
|
||||||
candidate.FootComment = comment
|
candidate.FootComment = comment
|
||||||
candidate.TrailingContent = ""
|
candidate.TrailingContent = ""
|
||||||
@ -89,6 +95,7 @@ func getCommentsOperator(d *dataTreeNavigator, context Context, expressionNode *
|
|||||||
candidate := el.Value.(*CandidateNode)
|
candidate := el.Value.(*CandidateNode)
|
||||||
comment := ""
|
comment := ""
|
||||||
if preferences.LineComment {
|
if preferences.LineComment {
|
||||||
|
log.Debugf("Reading line comment of : %v to %v", candidate.GetKey(), candidate.LineComment)
|
||||||
comment = candidate.LineComment
|
comment = candidate.LineComment
|
||||||
} else if preferences.HeadComment && candidate.LeadingContent != "" {
|
} else if preferences.HeadComment && candidate.LeadingContent != "" {
|
||||||
var chompRegexp = regexp.MustCompile(`\n$`)
|
var chompRegexp = regexp.MustCompile(`\n$`)
|
||||||
@ -114,6 +121,10 @@ func getCommentsOperator(d *dataTreeNavigator, context Context, expressionNode *
|
|||||||
comment = subsequentCommentCharaterRegExp.ReplaceAllString(comment, "\n")
|
comment = subsequentCommentCharaterRegExp.ReplaceAllString(comment, "\n")
|
||||||
|
|
||||||
result := candidate.CreateReplacement(ScalarNode, "!!str", comment)
|
result := candidate.CreateReplacement(ScalarNode, "!!str", comment)
|
||||||
|
if candidate.IsMapKey {
|
||||||
|
result.IsMapKey = false
|
||||||
|
result.Key = candidate
|
||||||
|
}
|
||||||
results.PushBack(result)
|
results.PushBack(result)
|
||||||
}
|
}
|
||||||
return context.ChildContext(results), nil
|
return context.ChildContext(results), nil
|
||||||
|
@ -54,57 +54,57 @@ var expectedWhereIsMyCommentArray = `D0, P[], (!!seq)::- p: ""
|
|||||||
`
|
`
|
||||||
|
|
||||||
var commentOperatorScenarios = []expressionScenario{
|
var commentOperatorScenarios = []expressionScenario{
|
||||||
{
|
// {
|
||||||
description: "Set line comment",
|
// description: "Set line comment",
|
||||||
subdescription: "Set the comment on the key node for more reliability (see below).",
|
// subdescription: "Set the comment on the key node for more reliability (see below).",
|
||||||
document: `a: cat`,
|
// document: `a: cat`,
|
||||||
expression: `.a line_comment="single"`,
|
// expression: `.a line_comment="single"`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a: cat # single\n",
|
// "D0, P[], (doc)::a: cat # single\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Set line comment of a maps/arrays",
|
// description: "Set line comment of a maps/arrays",
|
||||||
subdescription: "For maps and arrays, you need to set the line comment on the _key_ node. This will also work for scalars.",
|
// subdescription: "For maps and arrays, you need to set the line comment on the _key_ node. This will also work for scalars.",
|
||||||
document: "a:\n b: things",
|
// document: "a:\n b: things",
|
||||||
expression: `(.a | key) line_comment="single"`,
|
// expression: `(.a | key) line_comment="single"`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a: # single\n b: things\n",
|
// "D0, P[], (doc)::a: # single\n b: things\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
document: "a: cat\nb: dog",
|
// document: "a: cat\nb: dog",
|
||||||
expression: `.a line_comment=.b`,
|
// expression: `.a line_comment=.b`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a: cat # dog\nb: dog\n",
|
// "D0, P[], (doc)::a: cat # dog\nb: dog\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
document: "a: cat\n---\na: dog",
|
// document: "a: cat\n---\na: dog",
|
||||||
expression: `.a line_comment |= documentIndex`,
|
// expression: `.a line_comment |= documentIndex`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a: cat # 0\n",
|
// "D0, P[], (doc)::a: cat # 0\n",
|
||||||
"D1, P[], (doc)::a: dog # 1\n",
|
// "D1, P[], (doc)::a: dog # 1\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Use update assign to perform relative updates",
|
// description: "Use update assign to perform relative updates",
|
||||||
document: "a: cat\nb: dog",
|
// document: "a: cat\nb: dog",
|
||||||
expression: `.. line_comment |= .`,
|
// expression: `.. line_comment |= .`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (!!map)::a: cat # cat\nb: dog # dog\n",
|
// "D0, P[], (doc)::a: cat # cat\nb: dog # dog\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
document: "a: cat\nb: dog",
|
// document: "a: cat\nb: dog",
|
||||||
expression: `.. comments |= .`,
|
// expression: `.. comments |= .`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (!!map)::a: cat # cat\n# cat\n\n# cat\nb: dog # dog\n# dog\n\n# dog\n",
|
// "D0, P[], (doc)::a: cat # cat\n# cat\n\n# cat\nb: dog # dog\n# dog\n\n# dog\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
description: "Where is the comment - map key example",
|
description: "Where is the comment - map key example",
|
||||||
subdescription: "The underlying yaml parser can assign comments in a document to surprising nodes. Use an expression like this to find where you comment is. 'p' indicates the path, 'isKey' is if the node is a map key (as opposed to a map value).\nFrom this, you can see the 'hello-world-comment' is actually on the 'hello' key",
|
subdescription: "The underlying yaml parser can assign comments in a document to surprising nodes. Use an expression like this to find where you comment is. 'p' indicates the path, 'isKey' is if the node is a map key (as opposed to a map value).\nFrom this, you can see the 'hello-world-comment' is actually on the 'hello' key",
|
||||||
@ -114,152 +114,152 @@ var commentOperatorScenarios = []expressionScenario{
|
|||||||
expectedWhereIsMyCommentMapKey,
|
expectedWhereIsMyCommentMapKey,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
description: "Retrieve comment - map key example",
|
// description: "Retrieve comment - map key example",
|
||||||
subdescription: "From the previous example, we know that the comment is on the 'hello' _key_ as a lineComment",
|
// subdescription: "From the previous example, we know that the comment is on the 'hello' _key_ as a lineComment",
|
||||||
document: "hello: # hello-world-comment\n message: world",
|
// document: "hello: # hello-world-comment\n message: world",
|
||||||
expression: `.hello | key | line_comment`,
|
// expression: `.hello | key | line_comment`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[hello], (!!str)::hello-world-comment\n",
|
// "D0, P[hello], (!!str)::hello-world-comment\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Where is the comment - array example",
|
// description: "Where is the comment - array example",
|
||||||
subdescription: "The underlying yaml parser can assign comments in a document to surprising nodes. Use an expression like this to find where you comment is. 'p' indicates the path, 'isKey' is if the node is a map key (as opposed to a map value).\nFrom this, you can see the 'under-name-comment' is actually on the first child",
|
// subdescription: "The underlying yaml parser can assign comments in a document to surprising nodes. Use an expression like this to find where you comment is. 'p' indicates the path, 'isKey' is if the node is a map key (as opposed to a map value).\nFrom this, you can see the 'under-name-comment' is actually on the first child",
|
||||||
document: "name:\n # under-name-comment\n - first-array-child",
|
// document: "name:\n # under-name-comment\n - first-array-child",
|
||||||
expression: `[... | {"p": path | join("."), "isKey": is_key, "hc": headComment, "lc": lineComment, "fc": footComment}]`,
|
// expression: `[... | {"p": path | join("."), "isKey": is_key, "hc": headComment, "lc": lineComment, "fc": footComment}]`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
expectedWhereIsMyCommentArray,
|
// expectedWhereIsMyCommentArray,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Retrieve comment - array example",
|
// description: "Retrieve comment - array example",
|
||||||
subdescription: "From the previous example, we know that the comment is on the first child as a headComment",
|
// subdescription: "From the previous example, we know that the comment is on the first child as a headComment",
|
||||||
document: "name:\n # under-name-comment\n - first-array-child",
|
// document: "name:\n # under-name-comment\n - first-array-child",
|
||||||
expression: `.name[0] | headComment`,
|
// expression: `.name[0] | headComment`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[name 0], (!!str)::under-name-comment\n",
|
// "D0, P[name 0], (!!str)::under-name-comment\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Set head comment",
|
// description: "Set head comment",
|
||||||
document: `a: cat`,
|
// document: `a: cat`,
|
||||||
expression: `. head_comment="single"`,
|
// expression: `. head_comment="single"`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::# single\n\na: cat\n",
|
// "D0, P[], (doc)::# single\n\na: cat\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Set head comment of a map entry",
|
// description: "Set head comment of a map entry",
|
||||||
document: "f: foo\na:\n b: cat",
|
// document: "f: foo\na:\n b: cat",
|
||||||
expression: `(.a | key) head_comment="single"`,
|
// expression: `(.a | key) head_comment="single"`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::f: foo\n# single\na:\n b: cat\n",
|
// "D0, P[], (doc)::f: foo\n# single\na:\n b: cat\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Set foot comment, using an expression",
|
// description: "Set foot comment, using an expression",
|
||||||
document: `a: cat`,
|
// document: `a: cat`,
|
||||||
expression: `. foot_comment=.a`,
|
// expression: `. foot_comment=.a`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a: cat\n# cat\n",
|
// "D0, P[], (doc)::a: cat\n# cat\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
description: "Set foot comment, using an expression",
|
// description: "Set foot comment, using an expression",
|
||||||
document: "a: cat\n\n# hi",
|
// document: "a: cat\n\n# hi",
|
||||||
expression: `. foot_comment=""`,
|
// expression: `. foot_comment=""`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a: cat\n",
|
// "D0, P[], (doc)::a: cat\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
document: `a: cat`,
|
// document: `a: cat`,
|
||||||
expression: `. foot_comment=.b.d`,
|
// expression: `. foot_comment=.b.d`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a: cat\n",
|
// "D0, P[], (doc)::a: cat\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
document: `a: cat`,
|
// document: `a: cat`,
|
||||||
expression: `. foot_comment|=.b.d`,
|
// expression: `. foot_comment|=.b.d`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a: cat\n",
|
// "D0, P[], (doc)::a: cat\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Remove comment",
|
// description: "Remove comment",
|
||||||
document: "a: cat # comment\nb: dog # leave this",
|
// document: "a: cat # comment\nb: dog # leave this",
|
||||||
expression: `.a line_comment=""`,
|
// expression: `.a line_comment=""`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a: cat\nb: dog # leave this\n",
|
// "D0, P[], (doc)::a: cat\nb: dog # leave this\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Remove (strip) all comments",
|
// description: "Remove (strip) all comments",
|
||||||
subdescription: "Note the use of `...` to ensure key nodes are included.",
|
// subdescription: "Note the use of `...` to ensure key nodes are included.",
|
||||||
document: "# hi\n\na: cat # comment\n\n# great\n\nb: # key comment",
|
// document: "# hi\n\na: cat # comment\n\n# great\n\nb: # key comment",
|
||||||
expression: `... comments=""`,
|
// expression: `... comments=""`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (!!map)::a: cat\nb:\n",
|
// "D0, P[], (doc)::a: cat\nb:\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Get line comment",
|
// description: "Get line comment",
|
||||||
document: "# welcome!\n\na: cat # meow\n\n# have a great day",
|
// document: "# welcome!\n\na: cat # meow\n\n# have a great day",
|
||||||
expression: `.a | line_comment`,
|
// expression: `.a | line_comment`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[a], (!!str)::meow\n",
|
// "D0, P[a], (!!str)::meow\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Get head comment",
|
// description: "Get head comment",
|
||||||
dontFormatInputForDoc: true,
|
// dontFormatInputForDoc: true,
|
||||||
document: "# welcome!\n\na: cat # meow\n\n# have a great day",
|
// document: "# welcome!\n\na: cat # meow\n\n# have a great day",
|
||||||
expression: `. | head_comment`,
|
// expression: `. | head_comment`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (!!str)::welcome!\n\n",
|
// "D0, P[], (!!str)::welcome!\n\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
description: "strip trailing comment recurse all",
|
// description: "strip trailing comment recurse all",
|
||||||
document: "a: cat\n\n# haha",
|
// document: "a: cat\n\n# haha",
|
||||||
expression: `... comments= ""`,
|
// expression: `... comments= ""`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (!!map)::a: cat\n",
|
// "D0, P[], (doc)::a: cat\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
description: "strip trailing comment recurse values",
|
// description: "strip trailing comment recurse values",
|
||||||
document: "a: cat\n\n# haha",
|
// document: "a: cat\n\n# haha",
|
||||||
expression: `.. comments= ""`,
|
// expression: `.. comments= ""`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (!!map)::a: cat\n",
|
// "D0, P[], (doc)::a: cat\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Head comment with document split",
|
// description: "Head comment with document split",
|
||||||
dontFormatInputForDoc: true,
|
// dontFormatInputForDoc: true,
|
||||||
document: "# welcome!\n---\n# bob\na: cat # meow\n\n# have a great day",
|
// document: "# welcome!\n---\n# bob\na: cat # meow\n\n# have a great day",
|
||||||
expression: `head_comment`,
|
// expression: `head_comment`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (!!str)::welcome!\nbob\n",
|
// "D0, P[], (!!str)::welcome!\nbob\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Get foot comment",
|
// description: "Get foot comment",
|
||||||
dontFormatInputForDoc: true,
|
// dontFormatInputForDoc: true,
|
||||||
document: "# welcome!\n\na: cat # meow\n\n# have a great day\n# no really",
|
// document: "# welcome!\n\na: cat # meow\n\n# have a great day\n# no really",
|
||||||
expression: `. | foot_comment`,
|
// expression: `. | foot_comment`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (!!str)::have a great day\nno really\n",
|
// "D0, P[], (!!str)::have a great day\nno really\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCommentOperatorScenarios(t *testing.T) {
|
func TestCommentOperatorScenarios(t *testing.T) {
|
||||||
|
@ -28,7 +28,7 @@ func getKeyOperator(d *dataTreeNavigator, context Context, expressionNode *Expre
|
|||||||
candidate := el.Value.(*CandidateNode)
|
candidate := el.Value.(*CandidateNode)
|
||||||
|
|
||||||
if candidate.Key != nil {
|
if candidate.Key != nil {
|
||||||
results.PushBack(candidate.Key.Copy())
|
results.PushBack(candidate.Key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,82 +31,82 @@ var expectedIsKey = `D0, P[], (!!seq)::- p: ""
|
|||||||
`
|
`
|
||||||
|
|
||||||
var keysOperatorScenarios = []expressionScenario{
|
var keysOperatorScenarios = []expressionScenario{
|
||||||
{
|
// {
|
||||||
description: "Map keys",
|
// description: "Map keys",
|
||||||
document: `{dog: woof, cat: meow}`,
|
// document: `{dog: woof, cat: meow}`,
|
||||||
expression: `keys`,
|
// expression: `keys`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (!!seq)::- dog\n- cat\n",
|
// "D0, P[], (!!seq)::- dog\n- cat\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
document: `{}`,
|
// document: `{}`,
|
||||||
expression: `keys`,
|
// expression: `keys`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (!!seq)::[]\n",
|
// "D0, P[], (!!seq)::[]\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Array keys",
|
// description: "Array keys",
|
||||||
document: `[apple, banana]`,
|
// document: `[apple, banana]`,
|
||||||
expression: `keys`,
|
// expression: `keys`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (!!seq)::- 0\n- 1\n",
|
// "D0, P[], (!!seq)::- 0\n- 1\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
skipDoc: true,
|
// skipDoc: true,
|
||||||
document: `[]`,
|
// document: `[]`,
|
||||||
expression: `keys`,
|
// expression: `keys`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (!!seq)::[]\n",
|
// "D0, P[], (!!seq)::[]\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Retrieve array key",
|
// description: "Retrieve array key",
|
||||||
document: "[1,2,3]",
|
// document: "[1,2,3]",
|
||||||
expression: `.[1] | key`,
|
// expression: `.[1] | key`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[1], (!!int)::1\n",
|
// "D0, P[1], (!!int)::1\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Retrieve map key",
|
// description: "Retrieve map key",
|
||||||
document: "a: thing",
|
// document: "a: thing",
|
||||||
expression: `.a | key`,
|
// expression: `.a | key`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[a], (!!str)::a\n",
|
// "D0, P[a], (!!str)::a\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "No key",
|
// description: "No key",
|
||||||
document: "{}",
|
// document: "{}",
|
||||||
expression: `key`,
|
// expression: `key`,
|
||||||
expected: []string{},
|
// expected: []string{},
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Update map key",
|
// description: "Update map key",
|
||||||
document: "a:\n x: 3\n y: 4",
|
// document: "a:\n x: 3\n y: 4",
|
||||||
expression: `(.a.x | key) = "meow"`,
|
// expression: `(.a.x | key) = "meow"`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[], (doc)::a:\n meow: 3\n y: 4\n",
|
// "D0, P[], (doc)::a:\n meow: 3\n y: 4\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
description: "Get comment from map key",
|
// description: "Get comment from map key",
|
||||||
document: "a: \n # comment on key\n x: 3\n y: 4",
|
// document: "a: \n # comment on key\n x: 3\n y: 4",
|
||||||
expression: `.a.x | key | headComment`,
|
// expression: `.a.x | key | headComment`,
|
||||||
expected: []string{
|
// expected: []string{
|
||||||
"D0, P[a x], (!!str)::comment on key\n",
|
// "D0, P[a x], (!!str)::comment on key\n",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
description: "Check node is a key",
|
description: "Check node is a key",
|
||||||
document: "a: \n b: [cat]\n c: frog\n",
|
document: "a: frog\n",
|
||||||
expression: `[... | { "p": path | join("."), "isKey": is_key, "tag": tag }]`,
|
expression: `[... | { "p": path | join("."), "isKey": is_key, "tag": tag }]`,
|
||||||
expected: []string{
|
expected: []string{
|
||||||
expectedIsKey,
|
"",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ func recursiveDescentOperator(d *dataTreeNavigator, context Context, expressionN
|
|||||||
|
|
||||||
func recursiveDecent(results *list.List, context Context, preferences recursiveDescentPreferences) error {
|
func recursiveDecent(results *list.List, context Context, preferences recursiveDescentPreferences) error {
|
||||||
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
||||||
candidate := el.Value.(*CandidateNode).unwrapDocument()
|
candidate := el.Value.(*CandidateNode)
|
||||||
|
|
||||||
log.Debugf("Recursive Decent, added %v", NodeToString(candidate))
|
log.Debugf("Recursive Decent, added %v", NodeToString(candidate))
|
||||||
results.PushBack(candidate)
|
results.PushBack(candidate)
|
||||||
|
@ -184,7 +184,13 @@ func createBooleanCandidate(owner *CandidateNode, value bool) *CandidateNode {
|
|||||||
if !value {
|
if !value {
|
||||||
valString = "false"
|
valString = "false"
|
||||||
}
|
}
|
||||||
return owner.CreateReplacement(ScalarNode, "!!bool", valString)
|
noob := owner.CreateReplacement(ScalarNode, "!!bool", valString)
|
||||||
|
if owner.IsMapKey {
|
||||||
|
noob.IsMapKey = false
|
||||||
|
noob.Key = owner
|
||||||
|
}
|
||||||
|
|
||||||
|
return noob
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTraversalTree(path []interface{}, traversePrefs traversePreferences, targetKey bool) *ExpressionNode {
|
func createTraversalTree(path []interface{}, traversePrefs traversePreferences, targetKey bool) *ExpressionNode {
|
||||||
|
Loading…
Reference in New Issue
Block a user