mirror of
https://github.com/mikefarah/yq.git
synced 2025-03-09 18:35:36 +00:00
wip
This commit is contained in:
parent
b4cdcfb32e
commit
eb7844dd1d
@ -1,9 +1,12 @@
|
||||
package yqlib
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/mikefarah/yq/v4/test"
|
||||
logging "gopkg.in/op/go-logging.v1"
|
||||
)
|
||||
|
||||
var evaluateNodesScenario = []expressionScenario{
|
||||
@ -18,7 +21,7 @@ var evaluateNodesScenario = []expressionScenario{
|
||||
document: `a: hello`,
|
||||
expression: `.`,
|
||||
expected: []string{
|
||||
"D0, P[], (doc)::a: hello\n",
|
||||
"D0, P[], (!!map)::a: hello\n",
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -32,9 +35,19 @@ var evaluateNodesScenario = []expressionScenario{
|
||||
|
||||
func TestAllAtOnceEvaluateNodes(t *testing.T) {
|
||||
var evaluator = NewAllAtOnceEvaluator()
|
||||
logging.SetLevel(logging.DEBUG, "")
|
||||
for _, tt := range evaluateNodesScenario {
|
||||
node := test.ParseData(tt.document)
|
||||
list, _ := evaluator.EvaluateNodes(tt.expression, &node)
|
||||
decoder := NewYamlDecoder(NewDefaultYamlPreferences())
|
||||
reader := bufio.NewReader(strings.NewReader(tt.document))
|
||||
decoder.Init(reader)
|
||||
candidateNode, errorReading := decoder.Decode()
|
||||
|
||||
if errorReading != nil {
|
||||
t.Error(errorReading)
|
||||
return
|
||||
}
|
||||
|
||||
list, _ := evaluator.EvaluateNodes(tt.expression, candidateNode)
|
||||
test.AssertResultComplex(t, tt.expected, resultsToString(t, list))
|
||||
}
|
||||
}
|
||||
|
@ -27,14 +27,6 @@ const (
|
||||
FlowStyle
|
||||
)
|
||||
|
||||
func createIntegerScalarNode(num int) *CandidateNode {
|
||||
return &CandidateNode{
|
||||
Kind: ScalarNode,
|
||||
Tag: "!!int",
|
||||
Value: fmt.Sprintf("%v", num),
|
||||
}
|
||||
}
|
||||
|
||||
func createStringScalarNode(stringValue string) *CandidateNode {
|
||||
var node = &CandidateNode{Kind: ScalarNode}
|
||||
node.Value = stringValue
|
||||
@ -94,6 +86,15 @@ type CandidateNode struct {
|
||||
IsMapKey bool
|
||||
}
|
||||
|
||||
func (n *CandidateNode) CreateChild() *CandidateNode {
|
||||
return &CandidateNode{
|
||||
Parent: n,
|
||||
Document: n.Document,
|
||||
Filename: n.Filename,
|
||||
FileIndex: n.FileIndex,
|
||||
}
|
||||
}
|
||||
|
||||
func (n *CandidateNode) GetKey() string {
|
||||
keyPrefix := ""
|
||||
if n.IsMapKey {
|
||||
@ -136,7 +137,11 @@ func (n *CandidateNode) GetPath() []interface{} {
|
||||
if n.Parent != nil {
|
||||
return append(n.Parent.GetPath(), n.getParsedKey())
|
||||
}
|
||||
return []interface{}{n.getParsedKey()}
|
||||
key := n.getParsedKey()
|
||||
if key != nil {
|
||||
return []interface{}{key}
|
||||
}
|
||||
return make([]interface{}, 0)
|
||||
}
|
||||
|
||||
func (n *CandidateNode) GetNicePath() string {
|
||||
@ -184,41 +189,24 @@ func (n *CandidateNode) guessTagFromCustomType() string {
|
||||
return guessedTag
|
||||
}
|
||||
|
||||
// func (n *CandidateNode) CreateChildInMap(key *CandidateNode) *CandidateNode {
|
||||
// var value interface{}
|
||||
// if key != nil {
|
||||
// value = key.Value
|
||||
// }
|
||||
// return &CandidateNode{
|
||||
// Path: n.createChildPath(value),
|
||||
// Parent: n,
|
||||
// Key: key,
|
||||
|
||||
// Document: n.Document,
|
||||
// Filename: n.Filename,
|
||||
// FileIndex: n.FileIndex,
|
||||
// }
|
||||
// }
|
||||
|
||||
func (n *CandidateNode) CreateReplacement(kind Kind, tag string, value string) *CandidateNode {
|
||||
node := &CandidateNode{
|
||||
Kind: kind,
|
||||
Tag: tag,
|
||||
Value: value,
|
||||
}
|
||||
n.CopyAsReplacement(node)
|
||||
return node
|
||||
return n.CopyAsReplacement(node)
|
||||
}
|
||||
|
||||
func (n *CandidateNode) CopyAsReplacement(replacement *CandidateNode) *CandidateNode {
|
||||
copy := replacement.Copy()
|
||||
copy.Parent = n.Parent
|
||||
copy.Key = n.Key
|
||||
copy.IsMapKey = n.IsMapKey
|
||||
copy.Document = n.Document
|
||||
copy.Filename = n.Filename
|
||||
copy.FileIndex = n.FileIndex
|
||||
return copy
|
||||
newCopy := replacement.Copy()
|
||||
newCopy.Parent = n.Parent
|
||||
newCopy.Key = n.Key
|
||||
newCopy.IsMapKey = n.IsMapKey
|
||||
newCopy.Document = n.Document
|
||||
newCopy.Filename = n.Filename
|
||||
newCopy.FileIndex = n.FileIndex
|
||||
return newCopy
|
||||
}
|
||||
|
||||
func (n *CandidateNode) CreateReplacementWithDocWrappers(kind Kind, tag string, style Style) *CandidateNode {
|
||||
@ -230,10 +218,15 @@ func (n *CandidateNode) CreateReplacementWithDocWrappers(kind Kind, tag string,
|
||||
}
|
||||
|
||||
func (n *CandidateNode) CopyChildren() []*CandidateNode {
|
||||
log.Debug("n? %v", n)
|
||||
log.Debug("n.Content %v", n.Content)
|
||||
log.Debug("n.Content %v", len(n.Content))
|
||||
clonedKids := make([]*CandidateNode, len(n.Content))
|
||||
log.Debug("created clone")
|
||||
for i, child := range n.Content {
|
||||
clonedKids[i] = child.Copy()
|
||||
}
|
||||
log.Debug("finishing clone")
|
||||
return clonedKids
|
||||
}
|
||||
|
||||
@ -251,6 +244,11 @@ func (n *CandidateNode) doCopy(cloneContent bool) *CandidateNode {
|
||||
content = n.CopyChildren()
|
||||
}
|
||||
|
||||
var copyKey *CandidateNode
|
||||
if n.Key != nil {
|
||||
copyKey = n.Key.Copy()
|
||||
}
|
||||
|
||||
return &CandidateNode{
|
||||
Kind: n.Kind,
|
||||
Style: n.Style,
|
||||
@ -269,7 +267,7 @@ func (n *CandidateNode) doCopy(cloneContent bool) *CandidateNode {
|
||||
FootComment: n.FootComment,
|
||||
|
||||
Parent: n.Parent,
|
||||
Key: n.Key.Copy(),
|
||||
Key: copyKey,
|
||||
|
||||
LeadingContent: n.LeadingContent,
|
||||
TrailingContent: n.TrailingContent,
|
||||
|
205
pkg/yqlib/candidate_node_yaml.go
Normal file
205
pkg/yqlib/candidate_node_yaml.go
Normal file
@ -0,0 +1,205 @@
|
||||
package yqlib
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func MapYamlStyle(original yaml.Style) Style {
|
||||
switch original {
|
||||
case yaml.TaggedStyle:
|
||||
return TaggedStyle
|
||||
case yaml.DoubleQuotedStyle:
|
||||
return DoubleQuotedStyle
|
||||
case yaml.SingleQuotedStyle:
|
||||
return SingleQuotedStyle
|
||||
case yaml.LiteralStyle:
|
||||
return LiteralStyle
|
||||
case yaml.FoldedStyle:
|
||||
return FoldedStyle
|
||||
case yaml.FlowStyle:
|
||||
return FlowStyle
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func MapToYamlStyle(original Style) yaml.Style {
|
||||
switch original {
|
||||
case TaggedStyle:
|
||||
return yaml.TaggedStyle
|
||||
case DoubleQuotedStyle:
|
||||
return yaml.DoubleQuotedStyle
|
||||
case SingleQuotedStyle:
|
||||
return yaml.SingleQuotedStyle
|
||||
case LiteralStyle:
|
||||
return yaml.LiteralStyle
|
||||
case FoldedStyle:
|
||||
return yaml.FoldedStyle
|
||||
case FlowStyle:
|
||||
return yaml.FlowStyle
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (o *CandidateNode) copyFromYamlNode(node *yaml.Node) {
|
||||
o.Style = MapYamlStyle(node.Style)
|
||||
|
||||
o.Tag = node.Tag
|
||||
o.Value = node.Value
|
||||
o.Anchor = node.Anchor
|
||||
|
||||
// o.Alias = TODO - find Alias in our own structure
|
||||
// might need to be a post process thing
|
||||
|
||||
o.HeadComment = node.HeadComment
|
||||
o.LineComment = node.LineComment
|
||||
o.FootComment = node.FootComment
|
||||
|
||||
o.Line = node.Line
|
||||
o.Column = node.Column
|
||||
}
|
||||
|
||||
func (o *CandidateNode) copyToYamlNode(node *yaml.Node) {
|
||||
node.Style = MapToYamlStyle(o.Style)
|
||||
|
||||
node.Tag = o.Tag
|
||||
node.Value = o.Value
|
||||
node.Anchor = o.Anchor
|
||||
|
||||
// node.Alias = TODO - find Alias in our own structure
|
||||
// might need to be a post process thing
|
||||
|
||||
node.HeadComment = o.HeadComment
|
||||
node.LineComment = o.LineComment
|
||||
node.FootComment = o.FootComment
|
||||
|
||||
node.Line = o.Line
|
||||
node.Column = o.Column
|
||||
}
|
||||
|
||||
func (o *CandidateNode) UnmarshalYAML(node *yaml.Node) error {
|
||||
log.Debugf("unmarshalling %v", node.Tag)
|
||||
switch node.Kind {
|
||||
case yaml.DocumentNode:
|
||||
o.Kind = DocumentNode
|
||||
o.copyFromYamlNode(node)
|
||||
if len(node.Content) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
singleChild := &CandidateNode{
|
||||
Parent: o,
|
||||
}
|
||||
err := node.Content[0].Decode(singleChild)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.Content = []*CandidateNode{singleChild}
|
||||
return nil
|
||||
case yaml.AliasNode:
|
||||
log.Debug("decoding alias from yaml: %v", o.Tag)
|
||||
o.Kind = AliasNode
|
||||
o.copyFromYamlNode(node)
|
||||
return nil
|
||||
case yaml.ScalarNode:
|
||||
o.Kind = ScalarNode
|
||||
o.copyFromYamlNode(node)
|
||||
return nil
|
||||
case yaml.MappingNode:
|
||||
o.Kind = MappingNode
|
||||
o.copyFromYamlNode(node)
|
||||
o.Content = make([]*CandidateNode, len(node.Content))
|
||||
for i := 0; i < len(node.Content); i += 2 {
|
||||
keyNode := o.CreateChild()
|
||||
keyNode.IsMapKey = true
|
||||
err := node.Content[i].Decode(keyNode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
valueNode := o.CreateChild()
|
||||
valueNode.Key = keyNode
|
||||
err = node.Content[i+1].Decode(valueNode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.Content[i] = keyNode
|
||||
o.Content[i+1] = valueNode
|
||||
}
|
||||
return nil
|
||||
case yaml.SequenceNode:
|
||||
o.Kind = SequenceNode
|
||||
o.copyFromYamlNode(node)
|
||||
o.Content = make([]*CandidateNode, len(node.Content))
|
||||
for i := 0; i < len(node.Content); i += 1 {
|
||||
keyNode := o.CreateChild()
|
||||
keyNode.IsMapKey = true // can't remember if we need this for sequences
|
||||
keyNode.Tag = "!!int"
|
||||
keyNode.Kind = ScalarNode
|
||||
keyNode.Value = fmt.Sprintf("%v", i)
|
||||
|
||||
valueNode := o.CreateChild()
|
||||
valueNode.Key = keyNode
|
||||
err := node.Content[i].Decode(valueNode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.Content[i] = valueNode
|
||||
}
|
||||
return nil
|
||||
case 0:
|
||||
// not sure when this happens
|
||||
o.copyFromYamlNode(node)
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("orderedMap: invalid yaml node")
|
||||
}
|
||||
}
|
||||
|
||||
func (o *CandidateNode) MarshalYAML() (interface{}, error) {
|
||||
log.Debug("encoding to yaml: %v", o.Tag)
|
||||
switch o.Kind {
|
||||
case DocumentNode:
|
||||
target := &yaml.Node{Kind: yaml.DocumentNode}
|
||||
o.copyToYamlNode(target)
|
||||
|
||||
singleChild := &yaml.Node{}
|
||||
err := singleChild.Encode(o.Content[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
target.Content = []*yaml.Node{singleChild}
|
||||
return target, nil
|
||||
case AliasNode:
|
||||
log.Debug("encoding alias to yaml: %v", o.Tag)
|
||||
target := &yaml.Node{Kind: yaml.AliasNode}
|
||||
o.copyToYamlNode(target)
|
||||
return target, nil
|
||||
case ScalarNode:
|
||||
target := &yaml.Node{Kind: yaml.ScalarNode}
|
||||
o.copyToYamlNode(target)
|
||||
return target, nil
|
||||
case MappingNode, SequenceNode:
|
||||
targetKind := yaml.MappingNode
|
||||
if o.Kind == SequenceNode {
|
||||
targetKind = yaml.SequenceNode
|
||||
}
|
||||
target := &yaml.Node{Kind: targetKind}
|
||||
o.copyToYamlNode(target)
|
||||
target.Content = make([]*yaml.Node, len(o.Content))
|
||||
for i := 0; i < len(o.Content); i += 1 {
|
||||
child := &yaml.Node{}
|
||||
err := child.Encode(o.Content[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
target.Content[i] = child
|
||||
}
|
||||
return target, nil
|
||||
}
|
||||
target := &yaml.Node{}
|
||||
o.copyToYamlNode(target)
|
||||
return target, nil
|
||||
}
|
@ -49,7 +49,7 @@ func (d *dataTreeNavigator) GetMatchingNodes(context Context, expressionNode *Ex
|
||||
log.Debug(NodeToString(el.Value.(*CandidateNode)))
|
||||
}
|
||||
}
|
||||
log.Debug(">>")
|
||||
log.Debug("carr on>>")
|
||||
handler := expressionNode.Operation.OperationType.Handler
|
||||
if handler != nil {
|
||||
return handler(d, context, expressionNode)
|
||||
|
@ -96,104 +96,10 @@ func (dec *yamlDecoder) Init(reader io.Reader) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dec *yamlDecoder) convertKind(oKind yaml.Kind) Kind {
|
||||
switch oKind {
|
||||
case yaml.DocumentNode:
|
||||
return DocumentNode
|
||||
case yaml.SequenceNode:
|
||||
return SequenceNode
|
||||
case yaml.MappingNode:
|
||||
return MappingNode
|
||||
case yaml.ScalarNode:
|
||||
return ScalarNode
|
||||
case yaml.AliasNode:
|
||||
return AliasNode
|
||||
}
|
||||
return ScalarNode
|
||||
}
|
||||
|
||||
func (dec *yamlDecoder) convertStyle(oStyle yaml.Style) Style {
|
||||
switch oStyle {
|
||||
case yaml.TaggedStyle:
|
||||
return TaggedStyle
|
||||
case yaml.DoubleQuotedStyle:
|
||||
return DoubleQuotedStyle
|
||||
case yaml.SingleQuotedStyle:
|
||||
return SingleQuotedStyle
|
||||
case yaml.LiteralStyle:
|
||||
return LiteralStyle
|
||||
case yaml.FoldedStyle:
|
||||
return FoldedStyle
|
||||
case yaml.FlowStyle:
|
||||
return FlowStyle
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (dec *yamlDecoder) ConvertToCandidateNode(parent *CandidateNode, path []interface{}, yamlNode *yaml.Node) *CandidateNode {
|
||||
|
||||
candidateNode := &CandidateNode{
|
||||
Kind: dec.convertKind(yamlNode.Kind),
|
||||
Style: dec.convertStyle(yamlNode.Style),
|
||||
|
||||
Tag: yamlNode.Tag,
|
||||
Value: yamlNode.Value,
|
||||
Anchor: yamlNode.Anchor,
|
||||
|
||||
// not sure on this - check
|
||||
Alias: dec.ConvertToCandidateNode(parent, path, yamlNode.Alias),
|
||||
|
||||
HeadComment: yamlNode.HeadComment,
|
||||
LineComment: yamlNode.LineComment,
|
||||
FootComment: yamlNode.FootComment,
|
||||
Path: path,
|
||||
|
||||
Parent: parent,
|
||||
|
||||
Document: parent.Document,
|
||||
Filename: parent.Filename,
|
||||
|
||||
Line: yamlNode.Line,
|
||||
Column: yamlNode.Column,
|
||||
|
||||
FileIndex: parent.FileIndex,
|
||||
}
|
||||
|
||||
kids := make([]*CandidateNode, len(yamlNode.Content))
|
||||
|
||||
if yamlNode.Kind == yaml.MappingNode {
|
||||
// children are key, values
|
||||
for i := 0; i < len(yamlNode.Content); i = i + 2 {
|
||||
key := yamlNode.Content[i]
|
||||
value := yamlNode.Content[i+1]
|
||||
|
||||
childPath := parent.createChildPath(key.Value)
|
||||
keyNode := dec.ConvertToCandidateNode(parent, childPath, key)
|
||||
keyNode.IsMapKey = true
|
||||
|
||||
valueNode := dec.ConvertToCandidateNode(parent, childPath, value)
|
||||
valueNode.Key = keyNode
|
||||
|
||||
kids[i] = keyNode
|
||||
kids[i+1] = valueNode
|
||||
}
|
||||
} else {
|
||||
// its just an normal array
|
||||
for i, v := range yamlNode.Content {
|
||||
childPath := parent.createChildPath(i)
|
||||
kids[i] = dec.ConvertToCandidateNode(parent, childPath, v)
|
||||
}
|
||||
}
|
||||
|
||||
candidateNode.Content = kids
|
||||
|
||||
return candidateNode
|
||||
|
||||
}
|
||||
|
||||
func (dec *yamlDecoder) Decode() (*CandidateNode, error) {
|
||||
var dataBucket yaml.Node
|
||||
err := dec.decoder.Decode(&dataBucket)
|
||||
var candidateNode CandidateNode
|
||||
err := dec.decoder.Decode(&candidateNode)
|
||||
log.Debugf("decoded the yaml")
|
||||
if errors.Is(err, io.EOF) && dec.leadingContent != "" && !dec.readAnything {
|
||||
// force returning an empty node with a comment.
|
||||
dec.readAnything = true
|
||||
@ -211,8 +117,6 @@ func (dec *yamlDecoder) Decode() (*CandidateNode, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
candidateNode := dec.ConvertToCandidateNode(&CandidateNode{}, make([]interface{}, 0), &dataBucket)
|
||||
|
||||
if dec.leadingContent != "" {
|
||||
candidateNode.LeadingContent = dec.leadingContent
|
||||
dec.leadingContent = ""
|
||||
@ -220,9 +124,9 @@ func (dec *yamlDecoder) Decode() (*CandidateNode, error) {
|
||||
dec.readAnything = true
|
||||
// move document comments into candidate node
|
||||
// otherwise unwrap drops them.
|
||||
candidateNode.TrailingContent = dataBucket.FootComment
|
||||
dataBucket.FootComment = ""
|
||||
return candidateNode, nil
|
||||
candidateNode.TrailingContent = candidateNode.FootComment
|
||||
candidateNode.FootComment = ""
|
||||
return &candidateNode, nil
|
||||
}
|
||||
|
||||
func (dec *yamlDecoder) blankNodeWithComment() *CandidateNode {
|
||||
|
@ -16,213 +16,3 @@ These are most commonly used with the `select` operator to filter particular nod
|
||||
- comparison (`>=`, `<` etc) operators [here](https://mikefarah.gitbook.io/yq/operators/compare)
|
||||
- select operator [here](https://mikefarah.gitbook.io/yq/operators/select)
|
||||
|
||||
## `or` example
|
||||
Running
|
||||
```bash
|
||||
yq --null-input 'true or false'
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
true
|
||||
```
|
||||
|
||||
## `and` example
|
||||
Running
|
||||
```bash
|
||||
yq --null-input 'true and false'
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
false
|
||||
```
|
||||
|
||||
## Matching nodes with select, equals and or
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
- a: bird
|
||||
b: dog
|
||||
- a: frog
|
||||
b: bird
|
||||
- a: cat
|
||||
b: fly
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq '[.[] | select(.a == "cat" or .b == "dog")]' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
- a: bird
|
||||
b: dog
|
||||
- a: cat
|
||||
b: fly
|
||||
```
|
||||
|
||||
## `any` returns true if any boolean in a given array is true
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
- false
|
||||
- true
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq 'any' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
true
|
||||
```
|
||||
|
||||
## `any` returns false for an empty array
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
[]
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq 'any' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
false
|
||||
```
|
||||
|
||||
## `any_c` returns true if any element in the array is true for the given condition.
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a:
|
||||
- rad
|
||||
- awesome
|
||||
b:
|
||||
- meh
|
||||
- whatever
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq '.[] |= any_c(. == "awesome")' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
a: true
|
||||
b: false
|
||||
```
|
||||
|
||||
## `all` returns true if all booleans in a given array are true
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
- true
|
||||
- true
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq 'all' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
true
|
||||
```
|
||||
|
||||
## `all` returns true for an empty array
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
[]
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq 'all' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
true
|
||||
```
|
||||
|
||||
## `all_c` returns true if all elements in the array are true for the given condition.
|
||||
Given a sample.yml file of:
|
||||
```yaml
|
||||
a:
|
||||
- rad
|
||||
- awesome
|
||||
b:
|
||||
- meh
|
||||
- 12
|
||||
```
|
||||
then
|
||||
```bash
|
||||
yq '.[] |= all_c(tag == "!!str")' sample.yml
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
a: true
|
||||
b: false
|
||||
```
|
||||
|
||||
## Not true is false
|
||||
Running
|
||||
```bash
|
||||
yq --null-input 'true | not'
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
false
|
||||
```
|
||||
|
||||
## Not false is true
|
||||
Running
|
||||
```bash
|
||||
yq --null-input 'false | not'
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
true
|
||||
```
|
||||
|
||||
## String values considered to be true
|
||||
Running
|
||||
```bash
|
||||
yq --null-input '"cat" | not'
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
false
|
||||
```
|
||||
|
||||
## Empty string value considered to be true
|
||||
Running
|
||||
```bash
|
||||
yq --null-input '"" | not'
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
false
|
||||
```
|
||||
|
||||
## Numbers are considered to be true
|
||||
Running
|
||||
```bash
|
||||
yq --null-input '1 | not'
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
false
|
||||
```
|
||||
|
||||
## Zero is considered to be true
|
||||
Running
|
||||
```bash
|
||||
yq --null-input '0 | not'
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
false
|
||||
```
|
||||
|
||||
## Null is considered to be false
|
||||
Running
|
||||
```bash
|
||||
yq --null-input '~ | not'
|
||||
```
|
||||
will output
|
||||
```yaml
|
||||
true
|
||||
```
|
||||
|
||||
|
@ -56,11 +56,11 @@ func (je *jsonEncoder) Encode(writer io.Writer, node *CandidateNode) error {
|
||||
var dataBucket orderedMap
|
||||
// firstly, convert all map keys to strings
|
||||
mapKeysToStrings(node)
|
||||
errorDecoding := node.Decode(&dataBucket)
|
||||
// errorDecoding := node.Decode(&dataBucket)
|
||||
|
||||
if errorDecoding != nil {
|
||||
return errorDecoding
|
||||
}
|
||||
// if errorDecoding != nil {
|
||||
// return errorDecoding
|
||||
// }
|
||||
err := encoder.Encode(dataBucket)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -18,7 +18,7 @@ func yamlToProps(sampleYaml string, unwrapScalar bool) string {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
node := inputs.Front().Value.(*CandidateNode).Node
|
||||
node := inputs.Front().Value.(*CandidateNode)
|
||||
err = propsEncoder.Encode(writer, node)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -20,7 +20,7 @@ func yamlToJSON(sampleYaml string, indent int) string {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
node := inputs.Front().Value.(*CandidateNode).Node
|
||||
node := inputs.Front().Value.(*CandidateNode)
|
||||
err = jsonEncoder.Encode(writer, node)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -5,7 +5,6 @@ import (
|
||||
|
||||
"github.com/alecthomas/repr"
|
||||
"github.com/mikefarah/yq/v4/test"
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type participleLexerScenario struct {
|
||||
@ -41,11 +40,9 @@ var participleLexerScenarios = []participleLexerScenario{
|
||||
Value: 0,
|
||||
StringValue: "0",
|
||||
CandidateNode: &CandidateNode{
|
||||
Node: &yaml.Node{
|
||||
Kind: yaml.ScalarNode,
|
||||
Tag: "!!int",
|
||||
Value: "0",
|
||||
},
|
||||
Kind: ScalarNode,
|
||||
Tag: "!!int",
|
||||
Value: "0",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -64,11 +61,9 @@ var participleLexerScenarios = []participleLexerScenario{
|
||||
Value: int64(3),
|
||||
StringValue: "3",
|
||||
CandidateNode: &CandidateNode{
|
||||
Node: &yaml.Node{
|
||||
Kind: yaml.Kind(8),
|
||||
Tag: "!!int",
|
||||
Value: "3",
|
||||
},
|
||||
Kind: ScalarNode,
|
||||
Tag: "!!int",
|
||||
Value: "3",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -106,11 +101,9 @@ var participleLexerScenarios = []participleLexerScenario{
|
||||
Value: int64(-2),
|
||||
StringValue: "-2",
|
||||
CandidateNode: &CandidateNode{
|
||||
Node: &yaml.Node{
|
||||
Kind: yaml.ScalarNode,
|
||||
Tag: "!!int",
|
||||
Value: "-2",
|
||||
},
|
||||
Kind: ScalarNode,
|
||||
Tag: "!!int",
|
||||
Value: "-2",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -631,11 +624,9 @@ var participleLexerScenarios = []participleLexerScenario{
|
||||
StringValue: "string with a\n",
|
||||
Preferences: nil,
|
||||
CandidateNode: &CandidateNode{
|
||||
Node: &yaml.Node{
|
||||
Kind: yaml.ScalarNode,
|
||||
Tag: "!!str",
|
||||
Value: "string with a\n",
|
||||
},
|
||||
Kind: ScalarNode,
|
||||
Tag: "!!str",
|
||||
Value: "string with a\n",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -652,11 +643,9 @@ var participleLexerScenarios = []participleLexerScenario{
|
||||
StringValue: `string with a "`,
|
||||
Preferences: nil,
|
||||
CandidateNode: &CandidateNode{
|
||||
Node: &yaml.Node{
|
||||
Kind: yaml.ScalarNode,
|
||||
Tag: "!!str",
|
||||
Value: `string with a "`,
|
||||
},
|
||||
Kind: ScalarNode,
|
||||
Tag: "!!str",
|
||||
Value: `string with a "`,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -2,7 +2,6 @@
|
||||
package yqlib
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"container/list"
|
||||
"fmt"
|
||||
"math"
|
||||
@ -446,23 +445,23 @@ func NodeToString(node *CandidateNode) string {
|
||||
if node == nil {
|
||||
return "-- nil --"
|
||||
}
|
||||
buf := new(bytes.Buffer)
|
||||
encoder := yaml.NewEncoder(buf)
|
||||
errorEncoding := encoder.Encode(node)
|
||||
if errorEncoding != nil {
|
||||
log.Error("Error debugging node, %v", errorEncoding.Error())
|
||||
}
|
||||
errorClosingEncoder := encoder.Close()
|
||||
if errorClosingEncoder != nil {
|
||||
log.Error("Error closing encoder: ", errorClosingEncoder.Error())
|
||||
}
|
||||
// buf := new(bytes.Buffer)
|
||||
// encoder := yaml.NewEncoder(buf)
|
||||
// errorEncoding := encoder.Encode(node)
|
||||
// if errorEncoding != nil {
|
||||
// log.Error("Error debugging node, %v", errorEncoding.Error())
|
||||
// }
|
||||
// errorClosingEncoder := encoder.Close()
|
||||
// if errorClosingEncoder != nil {
|
||||
// log.Error("Error closing encoder: ", errorClosingEncoder.Error())
|
||||
// }
|
||||
tag := node.Tag
|
||||
if node.Kind == DocumentNode {
|
||||
tag = "doc"
|
||||
} else if node.Kind == AliasNode {
|
||||
tag = "alias"
|
||||
}
|
||||
return fmt.Sprintf(`D%v, P%v, (%v)::%v`, node.Document, node.GetNicePath(), tag, buf.String())
|
||||
return fmt.Sprintf(`D%v, P%v, (%v)::%v`, node.Document, node.GetNicePath(), tag, node.Value)
|
||||
}
|
||||
|
||||
func KindString(kind yaml.Kind) string {
|
||||
|
@ -14,7 +14,6 @@ import (
|
||||
|
||||
"github.com/mikefarah/yq/v4/test"
|
||||
logging "gopkg.in/op/go-logging.v1"
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type expressionScenario struct {
|
||||
@ -82,7 +81,8 @@ func testScenario(t *testing.T, s *expressionScenario) {
|
||||
candidateNode := &CandidateNode{
|
||||
Document: 0,
|
||||
Filename: "",
|
||||
Node: &yaml.Node{Tag: "!!null", Kind: yaml.ScalarNode},
|
||||
Tag: "!!null",
|
||||
Kind: ScalarNode,
|
||||
FileIndex: 0,
|
||||
}
|
||||
inputs.PushBack(candidateNode)
|
||||
@ -138,13 +138,13 @@ func resultToString(t *testing.T, n *CandidateNode) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
tag := n.Node.Tag
|
||||
if n.Node.Kind == yaml.DocumentNode {
|
||||
tag := n.Tag
|
||||
if n.Kind == DocumentNode {
|
||||
tag = "doc"
|
||||
} else if n.Node.Kind == yaml.AliasNode {
|
||||
} else if n.Kind == AliasNode {
|
||||
tag = "alias"
|
||||
}
|
||||
return fmt.Sprintf(`D%v, P%v, (%v)::%v`, n.Document, n.Path, tag, valueBuffer.String())
|
||||
return fmt.Sprintf(`D%v, P%v, (%v)::%v`, n.Document, n.GetPath(), tag, valueBuffer.String())
|
||||
}
|
||||
|
||||
func resultsToString(t *testing.T, results *list.List) []string {
|
||||
@ -352,7 +352,8 @@ func documentOutput(t *testing.T, w *bufio.Writer, s expressionScenario, formatt
|
||||
candidateNode := &CandidateNode{
|
||||
Document: 0,
|
||||
Filename: "",
|
||||
Node: &yaml.Node{Tag: "!!null", Kind: yaml.ScalarNode},
|
||||
Tag: "!!null",
|
||||
Kind: ScalarNode,
|
||||
FileIndex: 0,
|
||||
}
|
||||
inputs.PushBack(candidateNode)
|
||||
|
@ -6,8 +6,6 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"regexp"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type PrinterWriter interface {
|
||||
@ -56,17 +54,16 @@ func NewMultiPrinterWriter(expression *ExpressionNode, format PrinterOutputForma
|
||||
func (sp *multiPrintWriter) GetWriter(node *CandidateNode) (*bufio.Writer, error) {
|
||||
name := ""
|
||||
|
||||
indexVariableNode := yaml.Node{Kind: yaml.ScalarNode, Tag: "!!int", Value: fmt.Sprintf("%v", sp.index)}
|
||||
indexVariableCandidate := CandidateNode{Node: &indexVariableNode}
|
||||
indexVariableNode := CandidateNode{Kind: ScalarNode, Tag: "!!int", Value: fmt.Sprintf("%v", sp.index)}
|
||||
|
||||
context := Context{MatchingNodes: node.AsList()}
|
||||
context.SetVariable("index", indexVariableCandidate.AsList())
|
||||
context.SetVariable("index", indexVariableNode.AsList())
|
||||
result, err := sp.treeNavigator.GetMatchingNodes(context, sp.nameExpression)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if result.MatchingNodes.Len() > 0 {
|
||||
name = result.MatchingNodes.Front().Value.(*CandidateNode).Node.Value
|
||||
name = result.MatchingNodes.Front().Value.(*CandidateNode).Value
|
||||
}
|
||||
var extensionRegexp = regexp.MustCompile(`\.[a-zA-Z0-9]+$`)
|
||||
if !extensionRegexp.MatchString(name) {
|
||||
|
Loading…
Reference in New Issue
Block a user