diff --git a/pkg/yqlib/data_navigator.go b/pkg/yqlib/data_navigator.go index 8dedf9a..b393216 100644 --- a/pkg/yqlib/data_navigator.go +++ b/pkg/yqlib/data_navigator.go @@ -2,7 +2,6 @@ package yqlib import ( "strconv" - "strings" errors "github.com/pkg/errors" yaml "gopkg.in/yaml.v3" @@ -70,7 +69,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 == "**" || strings.Contains(head, "==") { + if n.navigationStrategy.GetPathParser().IsPathExpression(head) { return n.splatArray(value, head, tail, pathStack) } else if head == "+" { return n.appendArray(value, head, tail, pathStack) @@ -117,7 +116,7 @@ func (n *navigator) recurseMap(value *yaml.Node, head string, tail []string, pat return errorVisiting } - if traversedEntry || head == "*" || head == "**" || !n.navigationStrategy.AutoCreateMap(NewNodeContext(value, head, tail, pathStack)) { + if traversedEntry || n.navigationStrategy.GetPathParser().IsPathExpression(head) || !n.navigationStrategy.AutoCreateMap(NewNodeContext(value, head, tail, pathStack)) { return nil } diff --git a/pkg/yqlib/delete_navigation_strategy.go b/pkg/yqlib/delete_navigation_strategy.go index fc83c9e..becad83 100644 --- a/pkg/yqlib/delete_navigation_strategy.go +++ b/pkg/yqlib/delete_navigation_strategy.go @@ -10,6 +10,7 @@ func DeleteNavigationStrategy(pathElementToDelete string) NavigationStrategy { parser := NewPathParser() return &NavigationStrategyImpl{ visitedNodes: []*NodeContext{}, + pathParser: parser, followAlias: func(nodeContext NodeContext) bool { return false }, diff --git a/pkg/yqlib/filter_matching_node_navigation_strategy.go b/pkg/yqlib/filter_matching_node_navigation_strategy.go index dde3b8a..ad4ede0 100644 --- a/pkg/yqlib/filter_matching_node_navigation_strategy.go +++ b/pkg/yqlib/filter_matching_node_navigation_strategy.go @@ -3,6 +3,7 @@ package yqlib func FilterMatchingNodesNavigationStrategy(value string) NavigationStrategy { return &NavigationStrategyImpl{ visitedNodes: []*NodeContext{}, + pathParser: NewPathParser(), followAlias: func(nodeContext NodeContext) bool { return true }, diff --git a/pkg/yqlib/lib.go b/pkg/yqlib/lib.go index 108ef3a..196e3dd 100644 --- a/pkg/yqlib/lib.go +++ b/pkg/yqlib/lib.go @@ -74,7 +74,8 @@ func guessKind(head string, tail []string, guess yaml.Kind) yaml.Kind { if tail[0] == "+" || errorParsingInt == nil { return yaml.SequenceNode } - if (tail[0] == "*" || tail[0] == "**" || head == "**") && (guess == yaml.SequenceNode || guess == yaml.MappingNode) { + pathParser := NewPathParser() + if (pathParser.IsPathExpression(tail[0]) || head == "**") && (guess == yaml.SequenceNode || guess == yaml.MappingNode) { return guess } if guess == yaml.AliasNode { diff --git a/pkg/yqlib/navigation_strategy.go b/pkg/yqlib/navigation_strategy.go index a5ae1f1..892988a 100644 --- a/pkg/yqlib/navigation_strategy.go +++ b/pkg/yqlib/navigation_strategy.go @@ -36,6 +36,7 @@ type NavigationStrategy interface { ShouldTraverse(nodeContext NodeContext, nodeKey string) bool GetVisitedNodes() []*NodeContext DebugVisitedNodes() + GetPathParser() PathParser } type NavigationStrategyImpl struct { @@ -44,6 +45,11 @@ type NavigationStrategyImpl struct { visit func(nodeContext NodeContext) error shouldVisitExtraFn func(nodeContext NodeContext) bool visitedNodes []*NodeContext + pathParser PathParser +} + +func (ns *NavigationStrategyImpl) GetPathParser() PathParser { + return ns.pathParser } func (ns *NavigationStrategyImpl) GetVisitedNodes() []*NodeContext { @@ -68,10 +74,8 @@ func (ns *NavigationStrategyImpl) ShouldTraverse(nodeContext NodeContext, nodeKe return false } - parser := NewPathParser() - return (nodeKey == "<<" && ns.FollowAlias(nodeContext)) || (nodeKey != "<<" && - parser.MatchesNextPathElement(nodeContext, nodeKey)) + ns.pathParser.MatchesNextPathElement(nodeContext, nodeKey)) } func (ns *NavigationStrategyImpl) shouldVisit(nodeContext NodeContext) bool { @@ -88,11 +92,10 @@ func (ns *NavigationStrategyImpl) shouldVisit(nodeContext NodeContext) bool { nodeKey := fmt.Sprintf("%v", pathStack[len(pathStack)-1]) log.Debug("nodeKey: %v, nodeContext.Head: %v", nodeKey, nodeContext.Head) - parser := NewPathParser() // only visit aliases if its an exact match return ((nodeKey == "<<" && nodeContext.Head == "<<") || (nodeKey != "<<" && - parser.MatchesNextPathElement(nodeContext, nodeKey))) && (ns.shouldVisitExtraFn == nil || ns.shouldVisitExtraFn(nodeContext)) + ns.pathParser.MatchesNextPathElement(nodeContext, nodeKey))) && (ns.shouldVisitExtraFn == nil || ns.shouldVisitExtraFn(nodeContext)) } func (ns *NavigationStrategyImpl) Visit(nodeContext NodeContext) error { diff --git a/pkg/yqlib/path_parser.go b/pkg/yqlib/path_parser.go index 112d791..3846452 100644 --- a/pkg/yqlib/path_parser.go +++ b/pkg/yqlib/path_parser.go @@ -8,6 +8,7 @@ import ( type PathParser interface { ParsePath(path string) []string MatchesNextPathElement(nodeContext NodeContext, nodeKey string) bool + IsPathExpression(pathElement string) bool } type pathParser struct{} @@ -16,6 +17,10 @@ func NewPathParser() PathParser { return &pathParser{} } +func (p *pathParser) IsPathExpression(pathElement string) bool { + return pathElement == "*" || pathElement == "**" || strings.Contains(pathElement, "==") +} + /** * node: node that we may traverse/visit * head: path element expression to match against diff --git a/pkg/yqlib/read_navigation_strategy.go b/pkg/yqlib/read_navigation_strategy.go index 70ecfb7..4040e50 100644 --- a/pkg/yqlib/read_navigation_strategy.go +++ b/pkg/yqlib/read_navigation_strategy.go @@ -3,6 +3,7 @@ package yqlib func ReadNavigationStrategy() NavigationStrategy { return &NavigationStrategyImpl{ visitedNodes: []*NodeContext{}, + pathParser: NewPathParser(), followAlias: func(nodeContext NodeContext) bool { return true }, diff --git a/pkg/yqlib/update_navigation_strategy.go b/pkg/yqlib/update_navigation_strategy.go index e6be8b7..9cb4ac9 100644 --- a/pkg/yqlib/update_navigation_strategy.go +++ b/pkg/yqlib/update_navigation_strategy.go @@ -3,6 +3,7 @@ package yqlib func UpdateNavigationStrategy(updateCommand UpdateCommand, autoCreate bool) NavigationStrategy { return &NavigationStrategyImpl{ visitedNodes: []*NodeContext{}, + pathParser: NewPathParser(), followAlias: func(nodeContext NodeContext) bool { return false },