mirror of
https://github.com/mikefarah/yq.git
synced 2024-11-12 13:48:06 +00:00
it works! wip
This commit is contained in:
parent
96955ffa9c
commit
74c7a4e027
@ -94,6 +94,15 @@ func TestReadCmd(t *testing.T) {
|
||||
test.AssertResult(t, "2", result.Output)
|
||||
}
|
||||
|
||||
func TestReadWithAdvancedFilterCmd(t *testing.T) {
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, "read examples/sample.yaml b.e(name == sam).value")
|
||||
if result.Error != nil {
|
||||
t.Error(result.Error)
|
||||
}
|
||||
test.AssertResult(t, "4", result.Output)
|
||||
}
|
||||
|
||||
func TestReadWithKeyAndValueCmd(t *testing.T) {
|
||||
cmd := getRootCommand()
|
||||
result := test.RunCmd(cmd, "read -p pv examples/sample.yaml b.c")
|
||||
|
@ -1,9 +1,4 @@
|
||||
a: true
|
||||
b:
|
||||
c: 2
|
||||
d: [3, 4, 5]
|
||||
e:
|
||||
- name: fred
|
||||
value: 3
|
||||
- name: sam
|
||||
value: 4
|
||||
- name: fred
|
||||
value: 3
|
||||
- name: sam
|
||||
value: 4
|
@ -2,6 +2,7 @@ package yqlib
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
errors "github.com/pkg/errors"
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
@ -69,7 +70,7 @@ func (n *navigator) recurse(value *yaml.Node, head string, tail []string, pathSt
|
||||
return n.recurseMap(value, head, tail, pathStack)
|
||||
case yaml.SequenceNode:
|
||||
log.Debug("its a sequence of %v things!", len(value.Content))
|
||||
if head == "*" || head == "**" {
|
||||
if head == "*" || head == "**" || strings.Contains(head, "==") {
|
||||
return n.splatArray(value, head, tail, pathStack)
|
||||
} else if head == "+" {
|
||||
return n.appendArray(value, head, tail, pathStack)
|
||||
@ -96,7 +97,7 @@ func (n *navigator) recurseMap(value *yaml.Node, head string, tail []string, pat
|
||||
newPathStack := append(pathStack, contents[indexInMap].Value)
|
||||
log.Debug("appended %v", contents[indexInMap].Value)
|
||||
n.navigationStrategy.DebugVisitedNodes()
|
||||
log.Debug("should I traverse? %v, %v", head, pathStackToString(newPathStack))
|
||||
log.Debug("should I traverse? head: %v, path: %v", head, pathStackToString(newPathStack))
|
||||
DebugNode(value)
|
||||
if n.navigationStrategy.ShouldTraverse(NewNodeContext(contents[indexInMap+1], head, tail, newPathStack), contents[indexInMap].Value) {
|
||||
log.Debug("recurseMap: Going to traverse")
|
||||
@ -214,9 +215,13 @@ func (n *navigator) splatArray(value *yaml.Node, head string, tail []string, pat
|
||||
log.Debug("processing")
|
||||
DebugNode(childValue)
|
||||
childValue = n.getOrReplace(childValue, guessKind(head, tail, childValue.Kind))
|
||||
var err = n.doTraverse(childValue, head, tail, append(pathStack, index))
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
newPathStack := append(pathStack, index)
|
||||
if n.navigationStrategy.ShouldTraverse(NewNodeContext(childValue, head, tail, newPathStack), childValue.Value) {
|
||||
var err = n.doTraverse(childValue, head, tail, newPathStack)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
20
pkg/yqlib/filter_matching_node_navigation_strategy.go
Normal file
20
pkg/yqlib/filter_matching_node_navigation_strategy.go
Normal file
@ -0,0 +1,20 @@
|
||||
package yqlib
|
||||
|
||||
func FilterMatchingNodesNavigationStrategy(value string) NavigationStrategy {
|
||||
return &NavigationStrategyImpl{
|
||||
visitedNodes: []*NodeContext{},
|
||||
followAlias: func(nodeContext NodeContext) bool {
|
||||
return true
|
||||
},
|
||||
autoCreateMap: func(nodeContext NodeContext) bool {
|
||||
return false
|
||||
},
|
||||
visit: func(nodeContext NodeContext) error {
|
||||
return nil
|
||||
},
|
||||
shouldVisitExtraFn: func(nodeContext NodeContext) bool {
|
||||
log.Debug("does %v match %v ? %v", nodeContext.Node.Value, value, nodeContext.Node.Value == value)
|
||||
return nodeContext.Node.Value == value
|
||||
},
|
||||
}
|
||||
}
|
@ -108,10 +108,10 @@ func NewYqLib() YqLib {
|
||||
|
||||
func (l *lib) Get(rootNode *yaml.Node, path string) ([]*NodeContext, error) {
|
||||
var paths = l.parser.ParsePath(path)
|
||||
NavigationStrategy := ReadNavigationStrategy()
|
||||
navigator := NewDataNavigator(NavigationStrategy)
|
||||
navigationStrategy := ReadNavigationStrategy()
|
||||
navigator := NewDataNavigator(navigationStrategy)
|
||||
error := navigator.Traverse(rootNode, paths)
|
||||
return NavigationStrategy.GetVisitedNodes(), error
|
||||
return navigationStrategy.GetVisitedNodes(), error
|
||||
|
||||
}
|
||||
|
||||
|
@ -39,10 +39,11 @@ type NavigationStrategy interface {
|
||||
}
|
||||
|
||||
type NavigationStrategyImpl struct {
|
||||
followAlias func(nodeContext NodeContext) bool
|
||||
autoCreateMap func(nodeContext NodeContext) bool
|
||||
visit func(nodeContext NodeContext) error
|
||||
visitedNodes []*NodeContext
|
||||
followAlias func(nodeContext NodeContext) bool
|
||||
autoCreateMap func(nodeContext NodeContext) bool
|
||||
visit func(nodeContext NodeContext) error
|
||||
shouldVisitExtraFn func(nodeContext NodeContext) bool
|
||||
visitedNodes []*NodeContext
|
||||
}
|
||||
|
||||
func (ns *NavigationStrategyImpl) GetVisitedNodes() []*NodeContext {
|
||||
@ -90,8 +91,8 @@ func (ns *NavigationStrategyImpl) shouldVisit(nodeContext NodeContext) bool {
|
||||
parser := NewPathParser()
|
||||
|
||||
// only visit aliases if its an exact match
|
||||
return (nodeKey == "<<" && nodeContext.Head == "<<") || (nodeKey != "<<" &&
|
||||
parser.MatchesNextPathElement(nodeContext, nodeKey))
|
||||
return ((nodeKey == "<<" && nodeContext.Head == "<<") || (nodeKey != "<<" &&
|
||||
parser.MatchesNextPathElement(nodeContext, nodeKey))) && (ns.shouldVisitExtraFn == nil || ns.shouldVisitExtraFn(nodeContext))
|
||||
}
|
||||
|
||||
func (ns *NavigationStrategyImpl) Visit(nodeContext NodeContext) error {
|
||||
|
@ -28,6 +28,26 @@ func (p *pathParser) MatchesNextPathElement(nodeContext NodeContext, nodeKey str
|
||||
if head == "**" || head == "*" {
|
||||
return true
|
||||
}
|
||||
if strings.Contains(head, "==") {
|
||||
log.Debug("ooh deep recursion time")
|
||||
result := strings.SplitN(head, "==", 2)
|
||||
path := strings.TrimSpace(result[0])
|
||||
value := strings.TrimSpace(result[1])
|
||||
log.Debug("path %v", path)
|
||||
log.Debug("value %v", value)
|
||||
DebugNode(nodeContext.Node)
|
||||
navigationStrategy := FilterMatchingNodesNavigationStrategy(value)
|
||||
|
||||
navigator := NewDataNavigator(navigationStrategy)
|
||||
err := navigator.Traverse(nodeContext.Node, p.ParsePath(path))
|
||||
if err != nil {
|
||||
log.Error(err.Error())
|
||||
}
|
||||
//crap handle error
|
||||
log.Debug("done deep recursing, found %v matches", len(navigationStrategy.GetVisitedNodes()))
|
||||
return len(navigationStrategy.GetVisitedNodes()) > 0
|
||||
}
|
||||
|
||||
if head == "+" {
|
||||
log.Debug("head is +, nodeKey is %v", nodeKey)
|
||||
var _, err = strconv.ParseInt(nodeKey, 10, 64) // nolint
|
||||
@ -66,9 +86,12 @@ func (p *pathParser) nextYamlPath(path string) (pathElement string, remaining st
|
||||
case '"':
|
||||
// e.g "a.b".blah.cat -> we need to return "a.b" and "blah.cat"
|
||||
return p.search(path[1:], []uint8{'"'}, true)
|
||||
case '(':
|
||||
// e.g "a.b".blah.cat -> we need to return "a.b" and "blah.cat"
|
||||
return p.search(path[1:], []uint8{')'}, true)
|
||||
default:
|
||||
// e.g "a.blah.cat" -> return "a" and "blah.cat"
|
||||
return p.search(path[0:], []uint8{'.', '['}, false)
|
||||
return p.search(path[0:], []uint8{'.', '[', '"', '('}, false)
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user