diff --git a/pkg/yqlib/lexer_participle_test.go b/pkg/yqlib/lexer_participle_test.go index b28ab1da1d..9150bd4709 100644 --- a/pkg/yqlib/lexer_participle_test.go +++ b/pkg/yqlib/lexer_participle_test.go @@ -483,6 +483,7 @@ var participleLexerScenarios = []participleLexerScenario{ StringValue: "map_values", Preferences: nil, }, + CheckForPostTraverse: mapValuesOpType.CheckForPostTraverse, }, }, }, @@ -497,6 +498,7 @@ var participleLexerScenarios = []participleLexerScenario{ StringValue: "mapvalues", Preferences: nil, }, + CheckForPostTraverse: mapValuesOpType.CheckForPostTraverse, }, }, }, diff --git a/pkg/yqlib/operation.go b/pkg/yqlib/operation.go index 7afe11bddc..da64ce194f 100644 --- a/pkg/yqlib/operation.go +++ b/pkg/yqlib/operation.go @@ -85,16 +85,17 @@ var lengthOpType = &operationType{Type: "LENGTH", NumArgs: 0, Precedence: 50, Ha var lineOpType = &operationType{Type: "LINE", NumArgs: 0, Precedence: 50, Handler: lineOperator} var columnOpType = &operationType{Type: "LINE", NumArgs: 0, Precedence: 50, Handler: columnOperator} +// Use this expression to create alias/syntactic sugar expressions (in lexer_participle). var expressionOpType = &operationType{Type: "EXP", NumArgs: 0, Precedence: 50, Handler: expressionOperator} var collectOpType = &operationType{Type: "COLLECT", NumArgs: 1, Precedence: 50, Handler: collectOperator} -var mapOpType = &operationType{Type: "MAP", NumArgs: 1, Precedence: 50, Handler: mapOperator} +var mapOpType = &operationType{Type: "MAP", NumArgs: 1, Precedence: 52, Handler: mapOperator, CheckForPostTraverse: true} var filterOpType = &operationType{Type: "FILTER", NumArgs: 1, Precedence: 52, Handler: filterOperator, CheckForPostTraverse: true} var errorOpType = &operationType{Type: "ERROR", NumArgs: 1, Precedence: 50, Handler: errorOperator} -var pickOpType = &operationType{Type: "PICK", NumArgs: 1, Precedence: 50, Handler: pickOperator} -var omitOpType = &operationType{Type: "OMIT", NumArgs: 1, Precedence: 50, Handler: omitOperator} -var evalOpType = &operationType{Type: "EVAL", NumArgs: 1, Precedence: 50, Handler: evalOperator} -var mapValuesOpType = &operationType{Type: "MAP_VALUES", NumArgs: 1, Precedence: 50, Handler: mapValuesOperator} +var pickOpType = &operationType{Type: "PICK", NumArgs: 1, Precedence: 52, Handler: pickOperator, CheckForPostTraverse: true} +var omitOpType = &operationType{Type: "OMIT", NumArgs: 1, Precedence: 52, Handler: omitOperator, CheckForPostTraverse: true} +var evalOpType = &operationType{Type: "EVAL", NumArgs: 1, Precedence: 52, Handler: evalOperator, CheckForPostTraverse: true} +var mapValuesOpType = &operationType{Type: "MAP_VALUES", NumArgs: 1, Precedence: 52, Handler: mapValuesOperator, CheckForPostTraverse: true} var formatDateTimeOpType = &operationType{Type: "FORMAT_DATE_TIME", NumArgs: 1, Precedence: 50, Handler: formatDateTime} var withDtFormatOpType = &operationType{Type: "WITH_DATE_TIME_FORMAT", NumArgs: 1, Precedence: 50, Handler: withDateTimeFormat} @@ -135,12 +136,12 @@ var getDocumentIndexOpType = &operationType{Type: "GET_DOCUMENT_INDEX", NumArgs: var getFilenameOpType = &operationType{Type: "GET_FILENAME", NumArgs: 0, Precedence: 50, Handler: getFilenameOperator} var getFileIndexOpType = &operationType{Type: "GET_FILE_INDEX", NumArgs: 0, Precedence: 50, Handler: getFileIndexOperator} -var getPathOpType = &operationType{Type: "GET_PATH", NumArgs: 0, Precedence: 50, Handler: getPathOperator} +var getPathOpType = &operationType{Type: "GET_PATH", NumArgs: 0, Precedence: 52, Handler: getPathOperator, CheckForPostTraverse: true} var setPathOpType = &operationType{Type: "SET_PATH", NumArgs: 1, Precedence: 50, Handler: setPathOperator} var delPathsOpType = &operationType{Type: "DEL_PATHS", NumArgs: 1, Precedence: 50, Handler: delPathsOperator} var explodeOpType = &operationType{Type: "EXPLODE", NumArgs: 1, Precedence: 50, Handler: explodeOperator} -var sortByOpType = &operationType{Type: "SORT_BY", NumArgs: 1, Precedence: 52, Handler: sortByOperator, CheckForPostTraverse: true} +var sortByOpType = &operationType{Type: "SORT_BY", NumArgs: 1, Precedence: 52, Handler: sortByOperator} var reverseOpType = &operationType{Type: "REVERSE", NumArgs: 0, Precedence: 52, Handler: reverseOperator, CheckForPostTraverse: true} var sortOpType = &operationType{Type: "SORT", NumArgs: 0, Precedence: 52, Handler: sortOperator, CheckForPostTraverse: true} var shuffleOpType = &operationType{Type: "SHUFFLE", NumArgs: 0, Precedence: 52, Handler: shuffleOperator, CheckForPostTraverse: true} @@ -158,7 +159,7 @@ 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: loadOperator} +var loadOpType = &operationType{Type: "LOAD", NumArgs: 1, Precedence: 52, Handler: loadOperator, CheckForPostTraverse: true} var loadStringOpType = &operationType{Type: "LOAD_STRING", NumArgs: 1, Precedence: 52, Handler: loadStringOperator} var keysOpType = &operationType{Type: "KEYS", NumArgs: 0, Precedence: 52, Handler: keysOperator, CheckForPostTraverse: true} diff --git a/pkg/yqlib/operator_collect_test.go b/pkg/yqlib/operator_collect_test.go index b58c0dea8c..9ff63b4ed7 100644 --- a/pkg/yqlib/operator_collect_test.go +++ b/pkg/yqlib/operator_collect_test.go @@ -109,6 +109,14 @@ var collectOperatorScenarios = []expressionScenario{ "D0, P[], (!!seq)::- 1\n- 2\n- 3\n", }, }, + { + skipDoc: true, + expression: `[1,2][]`, + expected: []string{ + "D0, P[0], (!!int)::1\n", + "D0, P[1], (!!int)::2\n", + }, + }, { document: `a: {b: [1,2,3]}`, expression: `[.a.b.[]]`, diff --git a/pkg/yqlib/operator_eval_test.go b/pkg/yqlib/operator_eval_test.go index 6726b75a76..418a508717 100644 --- a/pkg/yqlib/operator_eval_test.go +++ b/pkg/yqlib/operator_eval_test.go @@ -14,6 +14,15 @@ var evalOperatorScenarios = []expressionScenario{ "D0, P[a b 1], (!!map)::{name: cat}\n", }, }, + { + description: "eval splat", + skipDoc: true, + document: `{pathExp: '.a.b[] | select(.name == "cat")', a: {b: [{name: dog}, {name: cat}]}}`, + expression: `eval(.pathExp)[]`, + expected: []string{ + "D0, P[a b 1 name], (!!str)::cat\n", + }, + }, { description: "Dynamically update a path from an environment variable", subdescription: "The env variable can be any valid yq expression.", diff --git a/pkg/yqlib/operator_map_test.go b/pkg/yqlib/operator_map_test.go index 7ba25b3c9f..94bf87c424 100644 --- a/pkg/yqlib/operator_map_test.go +++ b/pkg/yqlib/operator_map_test.go @@ -15,6 +15,15 @@ var mapOperatorScenarios = []expressionScenario{ "D0, P[], (!!seq)::[6, 7, 8]\n", }, }, + { + skipDoc: true, + document: `[1,2]`, + expression: `map(. + 1)[]`, + expected: []string{ + "D0, P[0], (!!int)::2\n", + "D0, P[1], (!!int)::3\n", + }, + }, { description: "Map array", document: `[1,2,3]`, @@ -33,6 +42,16 @@ var mapOperatorScenarios = []expressionScenario{ "D0, P[], (!!map)::{x: 11, y: 21, z: 31}\n", }, }, + { + description: "map values splat", + skipDoc: true, + document: `{a: 1, b: 2}`, + expression: `map_values(. + 1)[]`, + expected: []string{ + "D0, P[a], (!!int)::2\n", + "D0, P[b], (!!int)::3\n", + }, + }, { description: "Map object values", document: `{a: 1, b: 2, c: 3}`, diff --git a/pkg/yqlib/operator_omit_test.go b/pkg/yqlib/operator_omit_test.go index dbd6d9c02d..06d30abf91 100644 --- a/pkg/yqlib/operator_omit_test.go +++ b/pkg/yqlib/operator_omit_test.go @@ -14,6 +14,16 @@ var omitOperatorScenarios = []expressionScenario{ "D0, P[], (!!map)::myMap: {dog: bark, thing: hamster}\n", }, }, + { + description: "Omit splat", + skipDoc: true, + document: "{cat: meow, dog: bark, hamster: squeak}\n", + expression: `omit(["dog"])[]`, + expected: []string{ + "D0, P[cat], (!!str)::meow\n", + "D0, P[hamster], (!!str)::squeak\n", + }, + }, { description: "Omit keys from map", skipDoc: true, diff --git a/pkg/yqlib/operator_path_test.go b/pkg/yqlib/operator_path_test.go index bb575aac66..61f2f9d8e0 100644 --- a/pkg/yqlib/operator_path_test.go +++ b/pkg/yqlib/operator_path_test.go @@ -23,6 +23,16 @@ var pathOperatorScenarios = []expressionScenario{ "D0, P[a b], (!!seq)::- a\n- b\n", }, }, + { + description: "Map path", + document: `{a: {b: cat}}`, + skipDoc: true, + expression: `.a.b | path[]`, + expected: []string{ + "D0, P[a b 0], (!!str)::a\n", + "D0, P[a b 1], (!!str)::b\n", + }, + }, { skipDoc: true, document: `a: diff --git a/pkg/yqlib/operator_pick_test.go b/pkg/yqlib/operator_pick_test.go index 44565602cd..0111a35777 100644 --- a/pkg/yqlib/operator_pick_test.go +++ b/pkg/yqlib/operator_pick_test.go @@ -14,6 +14,16 @@ var pickOperatorScenarios = []expressionScenario{ "D0, P[], (!!map)::myMap: {hamster: squeak, cat: meow}\n", }, }, + { + description: "Pick splat", + skipDoc: true, + document: "{cat: meow, dog: bark, thing: hamster, hamster: squeak}\n", + expression: `pick(["hamster", "cat"])[]`, + expected: []string{ + "D0, P[hamster], (!!str)::squeak\n", + "D0, P[cat], (!!str)::meow\n", + }, + }, { description: "Pick keys from map", skipDoc: true,