diff --git a/pkg/yqlib/lexer_participle.go b/pkg/yqlib/lexer_participle.go index 9e2d1ac1..2025a576 100644 --- a/pkg/yqlib/lexer_participle.go +++ b/pkg/yqlib/lexer_participle.go @@ -542,8 +542,8 @@ func decodeOp(format *Format) yqAction { return opTokenWithPrefs(decodeOpType, nil, prefs) } -func loadOp(decoder Decoder, loadAsString bool) yqAction { - prefs := loadPrefs{decoder: decoder, loadAsString: loadAsString} +func loadOp(decoder Decoder) yqAction { + prefs := loadPrefs{decoder} return opTokenWithPrefs(loadOpType, nil, prefs) } diff --git a/pkg/yqlib/operation.go b/pkg/yqlib/operation.go index 2350a4c1..ea29e10d 100644 --- a/pkg/yqlib/operation.go +++ b/pkg/yqlib/operation.go @@ -155,7 +155,8 @@ var trimOpType = &operationType{Type: "TRIM", NumArgs: 0, Precedence: 50, Handle var toStringOpType = &operationType{Type: "TO_STRING", NumArgs: 0, Precedence: 50, Handler: toStringOperator} var stringInterpolationOpType = &operationType{Type: "STRING_INT", NumArgs: 0, Precedence: 50, Handler: stringInterpolationOperator, ToString: valueToStringFunc} -var loadOpType = &operationType{Type: "LOAD", NumArgs: 1, Precedence: 52, Handler: loadYamlOperator} +var loadOpType = &operationType{Type: "LOAD", NumArgs: 1, Precedence: 52, Handler: loadOperator} +var loadStringOpType = &operationType{Type: "LOAD_STRING", NumArgs: 1, Precedence: 52, Handler: loadStringOperator} var keysOpType = &operationType{Type: "KEYS", NumArgs: 0, Precedence: 50, Handler: keysOperator} diff --git a/pkg/yqlib/operator_load.go b/pkg/yqlib/operator_load.go index 8f0a5003..f30ee352 100644 --- a/pkg/yqlib/operator_load.go +++ b/pkg/yqlib/operator_load.go @@ -15,8 +15,7 @@ var LoadYamlPreferences = YamlPreferences{ } type loadPrefs struct { - loadAsString bool - decoder Decoder + decoder Decoder } func loadString(filename string) (*CandidateNode, error) { @@ -31,7 +30,7 @@ func loadString(filename string) (*CandidateNode, error) { return &CandidateNode{Kind: ScalarNode, Tag: "!!str", Value: string(filebytes)}, nil } -func loadYaml(filename string, decoder Decoder) (*CandidateNode, error) { +func loadWithDecoder(filename string, decoder Decoder) (*CandidateNode, error) { if decoder == nil { return nil, fmt.Errorf("could not load %s", filename) } @@ -62,8 +61,39 @@ func loadYaml(filename string, decoder Decoder) (*CandidateNode, error) { return sequenceNode, nil } -func loadYamlOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { - log.Debugf("loadYamlOperator") +func loadStringOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { + log.Debugf("loadString") + + var results = list.New() + + for el := context.MatchingNodes.Front(); el != nil; el = el.Next() { + candidate := el.Value.(*CandidateNode) + + rhs, err := d.GetMatchingNodes(context.SingleReadonlyChildContext(candidate), expressionNode.RHS) + if err != nil { + return Context{}, err + } + if rhs.MatchingNodes.Front() == nil { + return Context{}, fmt.Errorf("filename expression returned nil") + } + nameCandidateNode := rhs.MatchingNodes.Front().Value.(*CandidateNode) + + filename := nameCandidateNode.Value + + contentsCandidate, err := loadString(filename) + if err != nil { + return Context{}, fmt.Errorf("Failed to load %v: %w", filename, err) + } + + results.PushBack(contentsCandidate) + + } + + return context.ChildContext(results), nil +} + +func loadOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { + log.Debugf("loadOperator") loadPrefs := expressionNode.Operation.Preferences.(loadPrefs) @@ -86,13 +116,7 @@ func loadYamlOperator(d *dataTreeNavigator, context Context, expressionNode *Exp filename := nameCandidateNode.Value - var contentsCandidate *CandidateNode - - if loadPrefs.loadAsString { - contentsCandidate, err = loadString(filename) - } else { - contentsCandidate, err = loadYaml(filename, loadPrefs.decoder) - } + contentsCandidate, err := loadWithDecoder(filename, loadPrefs.decoder) if err != nil { return Context{}, fmt.Errorf("Failed to load %v: %w", filename, err) }