mirror of
https://github.com/mikefarah/yq.git
synced 2026-07-07 22:35:37 +00:00
The no-filter branch returned Content[0]; for a map that is the first key. Splat to get the first value with its correct path (matches the filtered path and first.md).
63 lines
2.0 KiB
Go
63 lines
2.0 KiB
Go
package yqlib
|
|
|
|
import "container/list"
|
|
|
|
func firstOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) {
|
|
results := list.New()
|
|
|
|
for el := context.MatchingNodes.Front(); el != nil; el = el.Next() {
|
|
candidate := el.Value.(*CandidateNode)
|
|
|
|
// If no RHS expression is provided, simply return the first entry
|
|
if expressionNode == nil || expressionNode.RHS == nil {
|
|
if candidate.Kind == MappingNode {
|
|
// candidate.Content is [key0, value0, ...]; the first entry of a
|
|
// map is its first VALUE, not the key (first.md: "first matching
|
|
// value in a map"). Splat to get map values with correct paths.
|
|
splatted, err := splat(context.SingleChildContext(candidate), traversePreferences{})
|
|
if err != nil {
|
|
return Context{}, err
|
|
}
|
|
if splatted.MatchingNodes.Front() != nil {
|
|
results.PushBack(splatted.MatchingNodes.Front().Value.(*CandidateNode))
|
|
}
|
|
} else if len(candidate.Content) > 0 {
|
|
results.PushBack(candidate.Content[0])
|
|
}
|
|
continue
|
|
}
|
|
|
|
splatted, err := splat(context.SingleChildContext(candidate), traversePreferences{})
|
|
if err != nil {
|
|
return Context{}, err
|
|
}
|
|
|
|
for splatEl := splatted.MatchingNodes.Front(); splatEl != nil; splatEl = splatEl.Next() {
|
|
splatCandidate := splatEl.Value.(*CandidateNode)
|
|
// Create a new context for this splatted candidate
|
|
splatContext := context.SingleChildContext(splatCandidate)
|
|
// Evaluate the RHS expression against this splatted candidate
|
|
rhs, err := d.GetMatchingNodes(splatContext, expressionNode.RHS)
|
|
if err != nil {
|
|
return Context{}, err
|
|
}
|
|
|
|
includeResult := false
|
|
|
|
for resultEl := rhs.MatchingNodes.Front(); resultEl != nil; resultEl = resultEl.Next() {
|
|
result := resultEl.Value.(*CandidateNode)
|
|
includeResult = isTruthyNode(result)
|
|
if includeResult {
|
|
break
|
|
}
|
|
}
|
|
if includeResult {
|
|
results.PushBack(splatCandidate)
|
|
break
|
|
}
|
|
}
|
|
|
|
}
|
|
return context.ChildContext(results), nil
|
|
}
|