mirror of
https://github.com/mikefarah/yq.git
synced 2024-12-19 20:19:04 +00:00
Deep splat!
This commit is contained in:
parent
8a6af1720d
commit
4dbdd4a805
@ -112,6 +112,24 @@ func TestReadArrayCmd(t *testing.T) {
|
|||||||
test.AssertResult(t, "b.e.1.name: sam\n", result.Output)
|
test.AssertResult(t, "b.e.1.name: sam\n", result.Output)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestReadDeepSplatCmd(t *testing.T) {
|
||||||
|
cmd := getRootCommand()
|
||||||
|
result := test.RunCmd(cmd, "read -p kv examples/sample.yaml b.**")
|
||||||
|
if result.Error != nil {
|
||||||
|
t.Error(result.Error)
|
||||||
|
}
|
||||||
|
expectedOutput := `b.c: 2
|
||||||
|
b.d.[0]: 3
|
||||||
|
b.d.[1]: 4
|
||||||
|
b.d.[2]: 5
|
||||||
|
b.e.[0].name: fred
|
||||||
|
b.e.[0].value: 3
|
||||||
|
b.e.[1].name: sam
|
||||||
|
b.e.[1].value: 4
|
||||||
|
`
|
||||||
|
test.AssertResult(t, expectedOutput, result.Output)
|
||||||
|
}
|
||||||
|
|
||||||
func TestReadWithKeyCmd(t *testing.T) {
|
func TestReadWithKeyCmd(t *testing.T) {
|
||||||
cmd := getRootCommand()
|
cmd := getRootCommand()
|
||||||
result := test.RunCmd(cmd, "read -p k examples/sample.yaml b.c")
|
result := test.RunCmd(cmd, "read -p k examples/sample.yaml b.c")
|
||||||
|
@ -31,13 +31,19 @@ func (n *navigator) Traverse(value *yaml.Node, path []string) error {
|
|||||||
return n.doTraverse(value, "", path, emptyArray)
|
return n.doTraverse(value, "", path, emptyArray)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *navigator) doTraverse(value *yaml.Node, head string, path []string, pathStack []interface{}) error {
|
func (n *navigator) doTraverse(value *yaml.Node, head string, tail []string, pathStack []interface{}) error {
|
||||||
if len(path) > 0 {
|
log.Debug("head %v", head)
|
||||||
log.Debugf("diving into %v", path[0])
|
|
||||||
DebugNode(value)
|
DebugNode(value)
|
||||||
return n.recurse(value, path[0], path[1:], pathStack)
|
if head == "**" && value.Kind != yaml.ScalarNode {
|
||||||
|
return n.recurse(value, head, tail, pathStack)
|
||||||
}
|
}
|
||||||
return n.navigationStrategy.Visit(NewNodeContext(value, head, path, pathStack))
|
|
||||||
|
if len(tail) > 0 {
|
||||||
|
log.Debugf("diving into %v", tail[0])
|
||||||
|
DebugNode(value)
|
||||||
|
return n.recurse(value, tail[0], tail[1:], pathStack)
|
||||||
|
}
|
||||||
|
return n.navigationStrategy.Visit(NewNodeContext(value, head, tail, pathStack))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *navigator) getOrReplace(original *yaml.Node, expectedKind yaml.Kind) *yaml.Node {
|
func (n *navigator) getOrReplace(original *yaml.Node, expectedKind yaml.Kind) *yaml.Node {
|
||||||
@ -56,8 +62,8 @@ func (n *navigator) recurse(value *yaml.Node, head string, tail []string, pathSt
|
|||||||
return n.recurseMap(value, head, tail, pathStack)
|
return n.recurseMap(value, head, tail, pathStack)
|
||||||
case yaml.SequenceNode:
|
case yaml.SequenceNode:
|
||||||
log.Debug("its a sequence of %v things!, %v", len(value.Content))
|
log.Debug("its a sequence of %v things!, %v", len(value.Content))
|
||||||
if head == "*" {
|
if head == "*" || head == "**" {
|
||||||
return n.splatArray(value, tail, pathStack)
|
return n.splatArray(value, head, tail, pathStack)
|
||||||
} else if head == "+" {
|
} else if head == "+" {
|
||||||
return n.appendArray(value, tail, pathStack)
|
return n.appendArray(value, tail, pathStack)
|
||||||
}
|
}
|
||||||
@ -196,11 +202,11 @@ func (n *navigator) visitAliasSequence(possibleAliasArray []*yaml.Node, head str
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *navigator) splatArray(value *yaml.Node, tail []string, pathStack []interface{}) error {
|
func (n *navigator) splatArray(value *yaml.Node, head string, tail []string, pathStack []interface{}) error {
|
||||||
for index, childValue := range value.Content {
|
for index, childValue := range value.Content {
|
||||||
log.Debug("processing")
|
log.Debug("processing")
|
||||||
DebugNode(childValue)
|
DebugNode(childValue)
|
||||||
head := fmt.Sprintf("%v", index)
|
// head = fmt.Sprintf("%v", index)
|
||||||
childValue = n.getOrReplace(childValue, guessKind(tail, childValue.Kind))
|
childValue = n.getOrReplace(childValue, guessKind(tail, childValue.Kind))
|
||||||
var err = n.doTraverse(childValue, head, tail, append(pathStack, index))
|
var err = n.doTraverse(childValue, head, tail, append(pathStack, index))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -61,7 +61,7 @@ func guessKind(tail []string, guess yaml.Kind) yaml.Kind {
|
|||||||
if tail[0] == "+" || errorParsingInt == nil {
|
if tail[0] == "+" || errorParsingInt == nil {
|
||||||
return yaml.SequenceNode
|
return yaml.SequenceNode
|
||||||
}
|
}
|
||||||
if tail[0] == "*" && (guess == yaml.SequenceNode || guess == yaml.MappingNode) {
|
if (tail[0] == "*" || tail[0] == "**") && (guess == yaml.SequenceNode || guess == yaml.MappingNode) {
|
||||||
return guess
|
return guess
|
||||||
}
|
}
|
||||||
if guess == yaml.AliasNode {
|
if guess == yaml.AliasNode {
|
||||||
|
@ -74,13 +74,12 @@ func (ns *NavigationStrategyImpl) ShouldTraverse(nodeContext NodeContext, nodeKe
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ns *NavigationStrategyImpl) shouldVisit(nodeContext NodeContext) bool {
|
func (ns *NavigationStrategyImpl) shouldVisit(nodeContext NodeContext) bool {
|
||||||
// we should traverse aliases (if enabled), but not visit them :/
|
|
||||||
pathStack := nodeContext.PathStack
|
pathStack := nodeContext.PathStack
|
||||||
if len(pathStack) == 0 {
|
if len(pathStack) == 0 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if ns.alreadyVisited(pathStack) {
|
if ns.alreadyVisited(pathStack) || len(nodeContext.Tail) != 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,7 +107,7 @@ func (ns *NavigationStrategyImpl) Visit(nodeContext NodeContext) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ns *NavigationStrategyImpl) DebugVisitedNodes() {
|
func (ns *NavigationStrategyImpl) DebugVisitedNodes() {
|
||||||
log.Debug("%v", ns.visitedNodes)
|
log.Debug("Visited Nodes:")
|
||||||
for _, candidate := range ns.visitedNodes {
|
for _, candidate := range ns.visitedNodes {
|
||||||
log.Debug(" - %v", PathStackToString(candidate.PathStack))
|
log.Debug(" - %v", PathStackToString(candidate.PathStack))
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,9 @@ func NewPathParser() PathParser {
|
|||||||
*/
|
*/
|
||||||
func (p *pathParser) MatchesNextPathElement(nodeContext NodeContext, nodeKey string) bool {
|
func (p *pathParser) MatchesNextPathElement(nodeContext NodeContext, nodeKey string) bool {
|
||||||
head := nodeContext.Head
|
head := nodeContext.Head
|
||||||
|
if head == "**" || head == "*" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
var prefixMatch = strings.TrimSuffix(head, "*")
|
var prefixMatch = strings.TrimSuffix(head, "*")
|
||||||
if prefixMatch != head {
|
if prefixMatch != head {
|
||||||
log.Debug("prefix match, %v", strings.HasPrefix(nodeKey, prefixMatch))
|
log.Debug("prefix match, %v", strings.HasPrefix(nodeKey, prefixMatch))
|
||||||
|
Loading…
Reference in New Issue
Block a user