From f7f8bed955ac9e0d0707475f4c4eb7b27497429f Mon Sep 17 00:00:00 2001 From: Mike Farah Date: Sun, 27 Dec 2020 09:36:33 +1100 Subject: [PATCH] wip --- pkg/yqlib/doc/Add.md | 78 ++++-------- pkg/yqlib/doc/Alternative (Default value).md | 4 + pkg/yqlib/doc/Anchor and Alias Operators.md | 34 ++--- pkg/yqlib/doc/Assign.md | 44 +++---- pkg/yqlib/doc/Boolean Operators.md | 5 + pkg/yqlib/doc/Collect into Array.md | 1 + pkg/yqlib/doc/Collect into Object.md | 17 ++- pkg/yqlib/doc/Comment Operators.md | 15 ++- pkg/yqlib/doc/Delete.md | 17 ++- pkg/yqlib/doc/Document Index.md | 13 +- pkg/yqlib/doc/File Operators.md | 2 + pkg/yqlib/doc/Has.md | 6 +- pkg/yqlib/doc/Length.md | 4 +- pkg/yqlib/doc/Multiply.md | 126 +++++-------------- pkg/yqlib/doc/Path.md | 34 ++--- pkg/yqlib/doc/Pipe.md | 6 +- pkg/yqlib/doc/Recursive Descent.md | 23 ++-- pkg/yqlib/doc/Select.md | 12 +- pkg/yqlib/doc/Sort Keys.md | 34 ++--- pkg/yqlib/doc/Style.md | 68 +++++----- pkg/yqlib/doc/Tag.md | 11 +- pkg/yqlib/doc/Traverse.md | 72 ++++++----- pkg/yqlib/doc/Union.md | 1 + pkg/yqlib/lib.go | 2 +- pkg/yqlib/operator_array_traverse.go | 78 +++++++++--- pkg/yqlib/operator_array_traverse_test.go | 24 ++++ pkg/yqlib/operator_assign_test.go | 10 +- pkg/yqlib/operator_traverse_path.go | 2 +- pkg/yqlib/operator_traverse_path_test.go | 2 +- pkg/yqlib/path_parse_test.go | 5 + pkg/yqlib/path_tokeniser.go | 33 ++++- 31 files changed, 409 insertions(+), 374 deletions(-) diff --git a/pkg/yqlib/doc/Add.md b/pkg/yqlib/doc/Add.md index bb994943..8b31b208 100644 --- a/pkg/yqlib/doc/Add.md +++ b/pkg/yqlib/doc/Add.md @@ -8,11 +8,8 @@ Use `+=` as append assign for things like increment. `.a += .x` is equivalent to ## Concatenate and assign arrays Given a sample.yml file of: ```yaml -a: - val: thing - b: - - cat - - dog +a: {val: thing, b: [cat, dog]} +'': null ``` then ```bash @@ -20,23 +17,16 @@ yq eval '.a.b += ["cow"]' sample.yml ``` will output ```yaml -a: - val: thing - b: - - cat - - dog - - cow +a: {val: thing, b: [cat, dog, cow]} +'': null ``` ## Concatenate arrays Given a sample.yml file of: ```yaml -a: - - 1 - - 2 -b: - - 3 - - 4 +a: [1, 2] +b: [3, 4] +'': null ``` then ```bash @@ -44,18 +34,14 @@ yq eval '.a + .b' sample.yml ``` will output ```yaml -- 1 -- 2 -- 3 -- 4 +[1, 2, 3, 4] ``` ## Concatenate null to array Given a sample.yml file of: ```yaml -a: - - 1 - - 2 +a: [1, 2] +'': null ``` then ```bash @@ -63,18 +49,15 @@ yq eval '.a + null' sample.yml ``` will output ```yaml -- 1 -- 2 +[1, 2] ``` ## Add object to array Given a sample.yml file of: ```yaml -a: - - 1 - - 2 -c: - cat: meow +a: [1, 2] +c: {cat: meow} +'': null ``` then ```bash @@ -82,17 +65,14 @@ yq eval '.a + .c' sample.yml ``` will output ```yaml -- 1 -- 2 -- cat: meow +[1, 2, {cat: meow}] ``` ## Add string to array Given a sample.yml file of: ```yaml -a: - - 1 - - 2 +a: [1, 2] +'': null ``` then ```bash @@ -100,20 +80,15 @@ yq eval '.a + "hello"' sample.yml ``` will output ```yaml -- 1 -- 2 -- hello +[1, 2, hello] ``` ## Update array (append) Given a sample.yml file of: ```yaml -a: - - 1 - - 2 -b: - - 3 - - 4 +a: [1, 2] +b: [3, 4] +'': null ``` then ```bash @@ -121,13 +96,8 @@ yq eval '.a = .a + .b' sample.yml ``` will output ```yaml -a: - - 1 - - 2 - - 3 - - 4 -b: - - 3 - - 4 +a: [1, 2, 3, 4] +b: [3, 4] +'': null ``` diff --git a/pkg/yqlib/doc/Alternative (Default value).md b/pkg/yqlib/doc/Alternative (Default value).md index 6521c378..a861ed33 100644 --- a/pkg/yqlib/doc/Alternative (Default value).md +++ b/pkg/yqlib/doc/Alternative (Default value).md @@ -4,6 +4,7 @@ This operator is used to provide alternative (or default) values when a particul Given a sample.yml file of: ```yaml a: bridge +'': null ``` then ```bash @@ -32,6 +33,7 @@ hello Given a sample.yml file of: ```yaml a: ~ +'': null ``` then ```bash @@ -46,6 +48,7 @@ hello Given a sample.yml file of: ```yaml a: false +'': null ``` then ```bash @@ -61,6 +64,7 @@ Given a sample.yml file of: ```yaml a: false b: cat +'': null ``` then ```bash diff --git a/pkg/yqlib/doc/Anchor and Alias Operators.md b/pkg/yqlib/doc/Anchor and Alias Operators.md index b7a6c707..6ebe2062 100644 --- a/pkg/yqlib/doc/Anchor and Alias Operators.md +++ b/pkg/yqlib/doc/Anchor and Alias Operators.md @@ -7,6 +7,7 @@ Use the `alias` and `anchor` operators to read and write yaml aliases and anchor Given a sample.yml file of: ```yaml a: &billyBob cat +'': null ``` then ```bash @@ -21,6 +22,7 @@ billyBob Given a sample.yml file of: ```yaml a: cat +'': null ``` then ```bash @@ -29,6 +31,7 @@ yq eval '.a anchor = "foobar"' sample.yml will output ```yaml a: &foobar cat +'': null ``` ## Get alias @@ -36,6 +39,7 @@ Given a sample.yml file of: ```yaml b: &billyBob meow a: *billyBob +'': null ``` then ```bash @@ -51,6 +55,7 @@ Given a sample.yml file of: ```yaml b: &meow purr a: cat +'': null ``` then ```bash @@ -60,14 +65,14 @@ will output ```yaml b: &meow purr a: *meow +'': null ``` ## Explode alias and anchor Given a sample.yml file of: ```yaml -f: - a: &a cat - b: *a +f: {a: &a cat, b: *a} +'': null ``` then ```bash @@ -75,15 +80,15 @@ yq eval 'explode(.f)' sample.yml ``` will output ```yaml -f: - a: cat - b: cat +f: {a: cat, b: cat} +'': null ``` ## Explode with no aliases or anchors Given a sample.yml file of: ```yaml a: mike +'': null ``` then ```bash @@ -92,14 +97,14 @@ yq eval 'explode(.a)' sample.yml will output ```yaml a: mike +'': null ``` ## Explode with alias keys Given a sample.yml file of: ```yaml -f: - a: &a cat - *a: b +f: {a: &a cat, *a: b} +'': null ``` then ```bash @@ -107,9 +112,8 @@ yq eval 'explode(.f)' sample.yml ``` will output ```yaml -f: - a: cat - cat: b +f: {a: cat, cat: b} +'': null ``` ## Explode with merge anchors @@ -125,14 +129,13 @@ bar: &bar c: bar_c foobarList: b: foobarList_b - !!merge <<: - - *foo - - *bar + !!merge <<: [*foo, *bar] c: foobarList_c foobar: c: foobar_c !!merge <<: *foo thing: foobar_thing +'': null ``` then ```bash @@ -157,5 +160,6 @@ foobar: c: foo_c a: foo_a thing: foobar_thing +'': null ``` diff --git a/pkg/yqlib/doc/Assign.md b/pkg/yqlib/doc/Assign.md index ce549eb2..f8e8f26e 100644 --- a/pkg/yqlib/doc/Assign.md +++ b/pkg/yqlib/doc/Assign.md @@ -20,9 +20,8 @@ x: frog ## Update node to be the child value Given a sample.yml file of: ```yaml -a: - b: - g: foof +a: {b: {g: foof}} +'': null ``` then ```bash @@ -30,16 +29,16 @@ yq eval '.a |= .b' sample.yml ``` will output ```yaml -a: - g: foof +a: {g: foof} +'': null ``` ## Update node to be the sibling value Given a sample.yml file of: ```yaml -a: - b: child +a: {b: child} b: sibling +'': null ``` then ```bash @@ -49,6 +48,7 @@ will output ```yaml a: sibling b: sibling +'': null ``` ## Updated multiple paths @@ -57,6 +57,7 @@ Given a sample.yml file of: a: fieldA b: fieldB c: fieldC +'': null ``` then ```bash @@ -67,13 +68,14 @@ will output a: potatoe b: fieldB c: potatoe +'': null ``` ## Update string value Given a sample.yml file of: ```yaml -a: - b: apple +a: {b: apple} +'': null ``` then ```bash @@ -81,8 +83,8 @@ yq eval '.a.b = "frog"' sample.yml ``` will output ```yaml -a: - b: frog +a: {b: frog} +'': null ``` ## Update string value via |= @@ -90,8 +92,8 @@ Note there is no difference between `=` and `|=` when the RHS is a scalar Given a sample.yml file of: ```yaml -a: - b: apple +a: {b: apple} +'': null ``` then ```bash @@ -99,26 +101,24 @@ yq eval '.a.b |= "frog"' sample.yml ``` will output ```yaml -a: - b: frog +a: {b: frog} +'': null ``` ## Update selected results Given a sample.yml file of: ```yaml -a: - b: apple - c: cactus +a: {b: apple, c: cactus} +'': null ``` then ```bash -yq eval '(.a.[] | select(. == "apple")) = "frog"' sample.yml +yq eval '(.a[] | select(. == "apple")) = "frog"' sample.yml ``` will output ```yaml -a: - b: frog - c: cactus +a: {b: frog, c: cactus} +'': null ``` ## Update array values diff --git a/pkg/yqlib/doc/Boolean Operators.md b/pkg/yqlib/doc/Boolean Operators.md index 7955937c..aa4f6696 100644 --- a/pkg/yqlib/doc/Boolean Operators.md +++ b/pkg/yqlib/doc/Boolean Operators.md @@ -24,10 +24,13 @@ Given a sample.yml file of: ```yaml - a: bird b: dog + '': null - a: frog b: bird + '': null - a: cat b: fly + '': null ``` then ```bash @@ -37,8 +40,10 @@ will output ```yaml - a: bird b: dog + '': null - a: cat b: fly + '': null ``` ## Not true is false diff --git a/pkg/yqlib/doc/Collect into Array.md b/pkg/yqlib/doc/Collect into Array.md index 8195ee9a..70f306de 100644 --- a/pkg/yqlib/doc/Collect into Array.md +++ b/pkg/yqlib/doc/Collect into Array.md @@ -28,6 +28,7 @@ Given a sample.yml file of: ```yaml a: cat b: dog +'': null ``` then ```bash diff --git a/pkg/yqlib/doc/Collect into Object.md b/pkg/yqlib/doc/Collect into Object.md index ffbc11bf..88724981 100644 --- a/pkg/yqlib/doc/Collect into Object.md +++ b/pkg/yqlib/doc/Collect into Object.md @@ -13,6 +13,7 @@ will output Given a sample.yml file of: ```yaml name: Mike +'': null ``` then ```bash @@ -22,15 +23,15 @@ will output ```yaml wrap: name: Mike + '': null ``` ## Using splat to create multiple objects Given a sample.yml file of: ```yaml name: Mike -pets: - - cat - - dog +pets: [cat, dog] +'': null ``` then ```bash @@ -46,14 +47,12 @@ Mike: dog Given a sample.yml file of: ```yaml name: Mike -pets: - - cat - - dog +pets: [cat, dog] +'': null --- name: Rosey -pets: - - monkey - - sheep +pets: [monkey, sheep] +'': null ``` then ```bash diff --git a/pkg/yqlib/doc/Comment Operators.md b/pkg/yqlib/doc/Comment Operators.md index d6d133ca..ae24c752 100644 --- a/pkg/yqlib/doc/Comment Operators.md +++ b/pkg/yqlib/doc/Comment Operators.md @@ -3,6 +3,7 @@ Use these comment operators to set or retrieve comments. Given a sample.yml file of: ```yaml a: cat +'': null ``` then ```bash @@ -11,12 +12,14 @@ yq eval '.a lineComment="single"' sample.yml will output ```yaml a: cat # single +'': null ``` ## Set head comment Given a sample.yml file of: ```yaml a: cat +'': null ``` then ```bash @@ -27,12 +30,14 @@ will output # single a: cat +'': null ``` ## Set foot comment, using an expression Given a sample.yml file of: ```yaml a: cat +'': null ``` then ```bash @@ -41,6 +46,7 @@ yq eval '. footComment=.a' sample.yml will output ```yaml a: cat +'': null # cat ``` @@ -50,6 +56,7 @@ Given a sample.yml file of: ```yaml a: cat # comment b: dog # leave this +'': null ``` then ```bash @@ -59,12 +66,14 @@ will output ```yaml a: cat b: dog # leave this +'': null ``` ## Remove all comments Given a sample.yml file of: ```yaml a: cat # comment +'': null ``` then ```bash @@ -72,13 +81,15 @@ yq eval '.. comments=""' sample.yml ``` will output ```yaml -a: cat +a: cat # comment +'': null ``` ## Get line comment Given a sample.yml file of: ```yaml a: cat # meow +'': null ``` then ```bash @@ -93,6 +104,7 @@ meow Given a sample.yml file of: ```yaml a: cat # meow +'': null ``` then ```bash @@ -107,6 +119,7 @@ will output Given a sample.yml file of: ```yaml a: cat # meow +'': null ``` then ```bash diff --git a/pkg/yqlib/doc/Delete.md b/pkg/yqlib/doc/Delete.md index 4f214f79..9bebafef 100644 --- a/pkg/yqlib/doc/Delete.md +++ b/pkg/yqlib/doc/Delete.md @@ -4,6 +4,7 @@ Given a sample.yml file of: ```yaml a: cat b: dog +'': null ``` then ```bash @@ -12,14 +13,14 @@ yq eval 'del(.b)' sample.yml will output ```yaml a: cat +'': null ``` ## Delete nested entry in map Given a sample.yml file of: ```yaml -a: - a1: fred - a2: frood +a: {a1: fred, a2: frood} +'': null ``` then ```bash @@ -27,8 +28,8 @@ yq eval 'del(.a.a1)' sample.yml ``` will output ```yaml -a: - a2: frood +a: {a2: frood} +'': null ``` ## Delete entry in array @@ -53,6 +54,7 @@ Given a sample.yml file of: ```yaml - a: cat b: dog + '': null ``` then ```bash @@ -61,6 +63,7 @@ yq eval 'del(.[0].a)' sample.yml will output ```yaml - b: dog + '': null ``` ## Delete no matches @@ -68,6 +71,7 @@ Given a sample.yml file of: ```yaml a: cat b: dog +'': null ``` then ```bash @@ -77,6 +81,7 @@ will output ```yaml a: cat b: dog +'': null ``` ## Delete matching entries @@ -85,6 +90,7 @@ Given a sample.yml file of: a: cat b: dog c: bat +'': null ``` then ```bash @@ -93,5 +99,6 @@ yq eval 'del( .[] | select(. == "*at") )' sample.yml will output ```yaml b: dog +'': null ``` diff --git a/pkg/yqlib/doc/Document Index.md b/pkg/yqlib/doc/Document Index.md index 948e50e4..b8120419 100644 --- a/pkg/yqlib/doc/Document Index.md +++ b/pkg/yqlib/doc/Document Index.md @@ -3,8 +3,10 @@ Use the `documentIndex` operator to select nodes of a particular document. Given a sample.yml file of: ```yaml a: cat +'': null --- a: frog +'': null ``` then ```bash @@ -21,8 +23,10 @@ will output Given a sample.yml file of: ```yaml a: cat +'': null --- a: frog +'': null ``` then ```bash @@ -31,14 +35,17 @@ yq eval 'select(. | documentIndex == 1)' sample.yml will output ```yaml a: frog +'': null ``` ## Print Document Index with matches Given a sample.yml file of: ```yaml a: cat +'': null --- a: frog +'': null ``` then ```bash @@ -46,9 +53,7 @@ yq eval '.a | ({"match": ., "doc": (. | documentIndex)})' sample.yml ``` will output ```yaml -match: cat -doc: 0 -match: frog -doc: 1 +'': null +'': null ``` diff --git a/pkg/yqlib/doc/File Operators.md b/pkg/yqlib/doc/File Operators.md index 946dfee9..1e6f3e0f 100644 --- a/pkg/yqlib/doc/File Operators.md +++ b/pkg/yqlib/doc/File Operators.md @@ -9,6 +9,7 @@ yq eval-all 'select(fileIndex == 0) * select(filename == "file2.yaml")' file1.ya Given a sample.yml file of: ```yaml a: cat +'': null ``` then ```bash @@ -23,6 +24,7 @@ sample.yaml Given a sample.yml file of: ```yaml a: cat +'': null ``` then ```bash diff --git a/pkg/yqlib/doc/Has.md b/pkg/yqlib/doc/Has.md index 1f25009c..4b71ea53 100644 --- a/pkg/yqlib/doc/Has.md +++ b/pkg/yqlib/doc/Has.md @@ -2,10 +2,14 @@ This is operation that returns true if the key exists in a map (or index in an a ## Has map key Given a sample.yml file of: ```yaml -- a: yes +- a: "yes" + '': null - a: ~ + '': null - a: + '': null - b: nope + '': null ``` then ```bash diff --git a/pkg/yqlib/doc/Length.md b/pkg/yqlib/doc/Length.md index dcd76562..fb06b079 100644 --- a/pkg/yqlib/doc/Length.md +++ b/pkg/yqlib/doc/Length.md @@ -6,6 +6,7 @@ returns length of string Given a sample.yml file of: ```yaml a: cat +'': null ``` then ```bash @@ -23,6 +24,7 @@ Given a sample.yml file of: ```yaml a: cat c: dog +'': null ``` then ```bash @@ -30,7 +32,7 @@ yq eval 'length' sample.yml ``` will output ```yaml -2 +3 ``` ## Array length diff --git a/pkg/yqlib/doc/Multiply.md b/pkg/yqlib/doc/Multiply.md index 3fc98d53..d7805897 100644 --- a/pkg/yqlib/doc/Multiply.md +++ b/pkg/yqlib/doc/Multiply.md @@ -16,13 +16,9 @@ yq eval-all 'select(fileIndex == 0) * select(fileIndex == 1)' file1.yaml file2.y ## Merge objects together, returning merged result only Given a sample.yml file of: ```yaml -a: - field: me - fieldA: cat -b: - field: - g: wizz - fieldB: dog +a: {field: me, fieldA: cat} +b: {field: {g: wizz}, fieldB: dog} +'': null ``` then ```bash @@ -30,22 +26,15 @@ yq eval '.a * .b' sample.yml ``` will output ```yaml -field: - g: wizz -fieldA: cat -fieldB: dog +{'': null} ``` ## Merge objects together, returning parent object Given a sample.yml file of: ```yaml -a: - field: me - fieldA: cat -b: - field: - g: wizz - fieldB: dog +a: {field: me, fieldA: cat} +b: {field: {g: wizz}, fieldB: dog} +'': null ``` then ```bash @@ -53,15 +42,7 @@ yq eval '. * {"a":.b}' sample.yml ``` will output ```yaml -a: - field: - g: wizz - fieldA: cat - fieldB: dog -b: - field: - g: wizz - fieldB: dog +'': null ``` ## Merge keeps style of LHS @@ -78,22 +59,15 @@ yq eval '. * {"a":.b}' sample.yml ``` will output ```yaml -a: {things: great, also: "me"} -b: - also: "me" +'': null ``` ## Merge arrays Given a sample.yml file of: ```yaml -a: - - 1 - - 2 - - 3 -b: - - 3 - - 4 - - 5 +a: [1, 2, 3] +b: [3, 4, 5] +'': null ``` then ```bash @@ -101,31 +75,15 @@ yq eval '. * {"a":.b}' sample.yml ``` will output ```yaml -a: - - 3 - - 4 - - 5 -b: - - 3 - - 4 - - 5 +'': null ``` ## Merge, appending arrays Given a sample.yml file of: ```yaml -a: - array: - - 1 - - 2 - - animal: dog - value: coconut -b: - array: - - 3 - - 4 - - animal: cat - value: banana +a: {array: [1, 2, {animal: dog}], value: coconut} +b: {array: [3, 4, {animal: cat}], value: banana} +'': null ``` then ```bash @@ -133,14 +91,7 @@ yq eval '.a *+ .b' sample.yml ``` will output ```yaml -array: - - 1 - - 2 - - animal: dog - - 3 - - 4 - - animal: cat -value: banana +{'': null} ``` ## Merge to prefix an element @@ -148,6 +99,7 @@ Given a sample.yml file of: ```yaml a: cat b: dog +'': null ``` then ```bash @@ -155,20 +107,16 @@ yq eval '. * {"a": {"c": .a}}' sample.yml ``` will output ```yaml -a: - c: cat -b: dog +'': null ``` ## Merge with simple aliases Given a sample.yml file of: ```yaml -a: &cat - c: frog -b: - f: *cat -c: - g: thongs +a: &cat {c: frog} +b: {f: *cat} +c: {g: thongs} +'': null ``` then ```bash @@ -176,19 +124,16 @@ yq eval '.c * .b' sample.yml ``` will output ```yaml -g: thongs -f: *cat +{'': null} ``` ## Merge does not copy anchor names Given a sample.yml file of: ```yaml -a: - c: &cat frog -b: - f: *cat -c: - g: thongs +a: {c: &cat frog} +b: {f: *cat} +c: {g: thongs} +'': null ``` then ```bash @@ -196,8 +141,7 @@ yq eval '.c * .a' sample.yml ``` will output ```yaml -g: thongs -c: frog +{'': null} ``` ## Merge with merge anchors @@ -213,14 +157,13 @@ bar: &bar c: bar_c foobarList: b: foobarList_b - !!merge <<: - - *foo - - *bar + !!merge <<: [*foo, *bar] c: foobarList_c foobar: c: foobar_c !!merge <<: *foo thing: foobar_thing +'': null ``` then ```bash @@ -228,11 +171,6 @@ yq eval '.foobar * .foobarList' sample.yml ``` will output ```yaml -c: foobarList_c -<<: - - *foo - - *bar -thing: foobar_thing -b: foobarList_b +'': null ``` diff --git a/pkg/yqlib/doc/Path.md b/pkg/yqlib/doc/Path.md index 9bf1f404..6900d243 100644 --- a/pkg/yqlib/doc/Path.md +++ b/pkg/yqlib/doc/Path.md @@ -5,8 +5,8 @@ You can get the key/index of matching nodes by using the `path` operator to retu ## Map path Given a sample.yml file of: ```yaml -a: - b: cat +a: {b: cat} +'': null ``` then ```bash @@ -21,8 +21,8 @@ will output ## Get map key Given a sample.yml file of: ```yaml -a: - b: cat +a: {b: cat} +'': null ``` then ```bash @@ -36,9 +36,8 @@ b ## Array path Given a sample.yml file of: ```yaml -a: - - cat - - dog +a: [cat, dog] +'': null ``` then ```bash @@ -53,9 +52,8 @@ will output ## Get array index Given a sample.yml file of: ```yaml -a: - - cat - - dog +a: [cat, dog] +'': null ``` then ```bash @@ -69,10 +67,8 @@ will output ## Print path and value Given a sample.yml file of: ```yaml -a: - - cat - - dog - - frog +a: [cat, dog, frog] +'': null ``` then ```bash @@ -80,13 +76,7 @@ yq eval '.a.[] | select(. == "*og") | [{"path":path, "value":.}]' sample.yml ``` will output ```yaml -- path: - - a - - 1 - value: dog -- path: - - a - - 2 - value: frog +- '': null +- '': null ``` diff --git a/pkg/yqlib/doc/Pipe.md b/pkg/yqlib/doc/Pipe.md index b1160d29..297220bc 100644 --- a/pkg/yqlib/doc/Pipe.md +++ b/pkg/yqlib/doc/Pipe.md @@ -3,8 +3,8 @@ Pipe the results of an expression into another. Like the bash operator. ## Simple Pipe Given a sample.yml file of: ```yaml -a: - b: cat +a: {b: cat} +'': null ``` then ```bash @@ -21,6 +21,7 @@ Given a sample.yml file of: a: cow b: sheep c: same +'': null ``` then ```bash @@ -31,5 +32,6 @@ will output a: cat b: dog c: same +'': null ``` diff --git a/pkg/yqlib/doc/Recursive Descent.md b/pkg/yqlib/doc/Recursive Descent.md index 3a3390e3..82248a3e 100644 --- a/pkg/yqlib/doc/Recursive Descent.md +++ b/pkg/yqlib/doc/Recursive Descent.md @@ -6,9 +6,9 @@ yq eval '.. style= "flow"' file.yaml ## Aliases are not traversed Given a sample.yml file of: ```yaml -a: &cat - c: frog +a: &cat {c: frog} b: *cat +'': null ``` then ```bash @@ -16,13 +16,10 @@ yq eval '[..]' sample.yml ``` will output ```yaml -- a: &cat - c: frog +- a: &cat {c: frog} b: *cat -- &cat - c: frog -- frog -- *cat + '': null +- null ``` ## Merge docs are not traversed @@ -38,14 +35,13 @@ bar: &bar c: bar_c foobarList: b: foobarList_b - !!merge <<: - - *foo - - *bar + !!merge <<: [*foo, *bar] c: foobarList_c foobar: c: foobar_c !!merge <<: *foo thing: foobar_thing +'': null ``` then ```bash @@ -56,8 +52,7 @@ will output - c: foobar_c !!merge <<: *foo thing: foobar_thing -- foobar_c -- *foo -- foobar_thing + '': null +- null ``` diff --git a/pkg/yqlib/doc/Select.md b/pkg/yqlib/doc/Select.md index 0dfe2769..cecdf21d 100644 --- a/pkg/yqlib/doc/Select.md +++ b/pkg/yqlib/doc/Select.md @@ -19,10 +19,8 @@ goat ## Select and update matching values in map Given a sample.yml file of: ```yaml -a: - things: cat - bob: goat - horse: dog +a: {things: cat, bob: goat, horse: dog} +'': null ``` then ```bash @@ -30,9 +28,7 @@ yq eval '(.a.[] | select(. == "*at")) |= "rabbit"' sample.yml ``` will output ```yaml -a: - things: rabbit - bob: rabbit - horse: dog +a: {things: rabbit, bob: rabbit, horse: dog} +'': null ``` diff --git a/pkg/yqlib/doc/Sort Keys.md b/pkg/yqlib/doc/Sort Keys.md index a1a99306..ae440db3 100644 --- a/pkg/yqlib/doc/Sort Keys.md +++ b/pkg/yqlib/doc/Sort Keys.md @@ -14,6 +14,7 @@ Given a sample.yml file of: c: frog a: blah b: bing +'': null ``` then ```bash @@ -21,6 +22,7 @@ yq eval 'sortKeys(.)' sample.yml ``` will output ```yaml +'': null a: blah b: bing c: frog @@ -31,19 +33,9 @@ Note the array elements are left unsorted, but maps inside arrays are sorted Given a sample.yml file of: ```yaml -bParent: - c: dog - array: - - 3 - - 1 - - 2 -aParent: - z: donkey - x: - - c: yum - b: delish - - b: ew - a: apple +bParent: {c: dog, array: [3, 1, 2]} +aParent: {z: donkey, x: [{c: yum, b: delish}, {b: ew, a: apple}]} +'': null ``` then ```bash @@ -51,18 +43,8 @@ yq eval 'sortKeys(..)' sample.yml ``` will output ```yaml -aParent: - x: - - b: delish - c: yum - - a: apple - b: ew - z: donkey -bParent: - array: - - 3 - - 1 - - 2 - c: dog +'': null +aParent: {z: donkey, x: [{c: yum, b: delish}, {b: ew, a: apple}]} +bParent: {c: dog, array: [3, 1, 2]} ``` diff --git a/pkg/yqlib/doc/Style.md b/pkg/yqlib/doc/Style.md index d089aa4d..bea23d0f 100644 --- a/pkg/yqlib/doc/Style.md +++ b/pkg/yqlib/doc/Style.md @@ -6,6 +6,7 @@ a: cat b: 5 c: 3.2 e: true +'': null ``` then ```bash @@ -14,10 +15,11 @@ yq eval '.. style="tagged"' sample.yml will output ```yaml !!map -a: !!str cat -b: !!int 5 -c: !!float 3.2 -e: !!bool true +a: cat +b: 5 +c: 3.2 +e: true +'': !!null null ``` ## Set double quote style @@ -27,6 +29,7 @@ a: cat b: 5 c: 3.2 e: true +'': null ``` then ```bash @@ -34,10 +37,11 @@ yq eval '.. style="double"' sample.yml ``` will output ```yaml -a: "cat" -b: "5" -c: "3.2" -e: "true" +a: cat +b: 5 +c: 3.2 +e: true +'': "null" ``` ## Set single quote style @@ -47,6 +51,7 @@ a: cat b: 5 c: 3.2 e: true +'': null ``` then ```bash @@ -54,10 +59,11 @@ yq eval '.. style="single"' sample.yml ``` will output ```yaml -a: 'cat' -b: '5' -c: '3.2' -e: 'true' +a: cat +b: 5 +c: 3.2 +e: true +'': 'null' ``` ## Set literal quote style @@ -67,6 +73,7 @@ a: cat b: 5 c: 3.2 e: true +'': null ``` then ```bash @@ -74,14 +81,12 @@ yq eval '.. style="literal"' sample.yml ``` will output ```yaml -a: |- - cat -b: |- - 5 -c: |- - 3.2 -e: |- - true +a: cat +b: 5 +c: 3.2 +e: true +'': |- + null ``` ## Set folded quote style @@ -91,6 +96,7 @@ a: cat b: 5 c: 3.2 e: true +'': null ``` then ```bash @@ -98,14 +104,12 @@ yq eval '.. style="folded"' sample.yml ``` will output ```yaml -a: >- - cat -b: >- - 5 -c: >- - 3.2 -e: >- - true +a: cat +b: 5 +c: 3.2 +e: true +'': >- + null ``` ## Set flow quote style @@ -115,6 +119,7 @@ a: cat b: 5 c: 3.2 e: true +'': null ``` then ```bash @@ -122,7 +127,7 @@ yq eval '.. style="flow"' sample.yml ``` will output ```yaml -{a: cat, b: 5, c: 3.2, e: true} +{a: cat, b: 5, c: 3.2, e: true, '': null} ``` ## Pretty print @@ -134,6 +139,7 @@ a: cat b: 5 c: 3.2 e: true +'': null ``` then ```bash @@ -145,6 +151,7 @@ a: cat b: 5 c: 3.2 e: true +'': null ``` ## Read style @@ -159,7 +166,6 @@ yq eval '.. | style' sample.yml will output ```yaml flow -double -single + ``` diff --git a/pkg/yqlib/doc/Tag.md b/pkg/yqlib/doc/Tag.md index 519142fd..e3a8fc53 100644 --- a/pkg/yqlib/doc/Tag.md +++ b/pkg/yqlib/doc/Tag.md @@ -7,6 +7,7 @@ b: 5 c: 3.2 e: true f: [] +'': null ``` then ```bash @@ -15,11 +16,7 @@ yq eval '.. | tag' sample.yml will output ```yaml !!map -!!str -!!int -!!float -!!bool -!!seq +!!null ``` ## Convert numbers to strings @@ -29,6 +26,7 @@ a: cat b: 5 c: 3.2 e: true +'': null ``` then ```bash @@ -37,8 +35,9 @@ yq eval '(.. | select(tag == "!!int")) tag= "!!str"' sample.yml will output ```yaml a: cat -b: "5" +b: 5 c: 3.2 e: true +'': null ``` diff --git a/pkg/yqlib/doc/Traverse.md b/pkg/yqlib/doc/Traverse.md index 20befb25..3e4239a0 100644 --- a/pkg/yqlib/doc/Traverse.md +++ b/pkg/yqlib/doc/Traverse.md @@ -2,8 +2,8 @@ This is the simplest (and perhaps most used) operator, it is used to navigate de ## Simple map navigation Given a sample.yml file of: ```yaml -a: - b: apple +a: {b: apple} +'': null ``` then ```bash @@ -11,7 +11,7 @@ yq eval '.a' sample.yml ``` will output ```yaml -b: apple +{b: apple} ``` ## Splat @@ -20,7 +20,9 @@ Often used to pipe children into other operators Given a sample.yml file of: ```yaml - b: apple + '': null - c: banana + '': null ``` then ```bash @@ -29,7 +31,9 @@ yq eval '.[]' sample.yml will output ```yaml b: apple +'': null c: banana +'': null ``` ## Special characters @@ -38,6 +42,7 @@ Use quotes around path elements with special characters Given a sample.yml file of: ```yaml "{}": frog +'': null ``` then ```bash @@ -54,6 +59,7 @@ Nodes are added dynamically while traversing Given a sample.yml file of: ```yaml c: banana +'': null ``` then ```bash @@ -67,9 +73,8 @@ null ## Wildcard matching Given a sample.yml file of: ```yaml -a: - cat: apple - mad: things +a: {cat: apple, mad: things} +'': null ``` then ```bash @@ -84,9 +89,9 @@ things ## Aliases Given a sample.yml file of: ```yaml -a: &cat - c: frog +a: &cat {c: frog} b: *cat +'': null ``` then ```bash @@ -100,9 +105,9 @@ will output ## Traversing aliases with splat Given a sample.yml file of: ```yaml -a: &cat - c: frog +a: &cat {c: frog} b: *cat +'': null ``` then ```bash @@ -116,9 +121,9 @@ frog ## Traversing aliases explicitly Given a sample.yml file of: ```yaml -a: &cat - c: frog +a: &cat {c: frog} b: *cat +'': null ``` then ```bash @@ -149,6 +154,7 @@ will output Given a sample.yml file of: ```yaml 2: cat +'': null ``` then ```bash @@ -156,13 +162,13 @@ yq eval '.[2]' sample.yml ``` will output ```yaml -cat ``` ## Maps with non existing numeric keys Given a sample.yml file of: ```yaml a: b +'': null ``` then ```bash @@ -170,7 +176,6 @@ yq eval '.[0]' sample.yml ``` will output ```yaml -null ``` ## Traversing merge anchors @@ -186,14 +191,13 @@ bar: &bar c: bar_c foobarList: b: foobarList_b - !!merge <<: - - *foo - - *bar + !!merge <<: [*foo, *bar] c: foobarList_c foobar: c: foobar_c !!merge <<: *foo thing: foobar_thing +'': null ``` then ```bash @@ -217,14 +221,13 @@ bar: &bar c: bar_c foobarList: b: foobarList_b - !!merge <<: - - *foo - - *bar + !!merge <<: [*foo, *bar] c: foobarList_c foobar: c: foobar_c !!merge <<: *foo thing: foobar_thing +'': null ``` then ```bash @@ -248,14 +251,13 @@ bar: &bar c: bar_c foobarList: b: foobarList_b - !!merge <<: - - *foo - - *bar + !!merge <<: [*foo, *bar] c: foobarList_c foobar: c: foobar_c !!merge <<: *foo thing: foobar_thing +'': null ``` then ```bash @@ -279,14 +281,13 @@ bar: &bar c: bar_c foobarList: b: foobarList_b - !!merge <<: - - *foo - - *bar + !!merge <<: [*foo, *bar] c: foobarList_c foobar: c: foobar_c !!merge <<: *foo thing: foobar_thing +'': null ``` then ```bash @@ -294,8 +295,8 @@ yq eval '.foobar.[]' sample.yml ``` will output ```yaml -foo_c -foo_a +foobar_c +*foo foobar_thing ``` @@ -314,14 +315,13 @@ bar: &bar c: bar_c foobarList: b: foobarList_b - !!merge <<: - - *foo - - *bar + !!merge <<: [*foo, *bar] c: foobarList_c foobar: c: foobar_c !!merge <<: *foo thing: foobar_thing +'': null ``` then ```bash @@ -345,14 +345,13 @@ bar: &bar c: bar_c foobarList: b: foobarList_b - !!merge <<: - - *foo - - *bar + !!merge <<: [*foo, *bar] c: foobarList_c foobar: c: foobar_c !!merge <<: *foo thing: foobar_thing +'': null ``` then ```bash @@ -360,9 +359,8 @@ yq eval '.foobarList.[]' sample.yml ``` will output ```yaml -bar_b -foo_a -bar_thing +foobarList_b +[*foo, *bar] foobarList_c ``` diff --git a/pkg/yqlib/doc/Union.md b/pkg/yqlib/doc/Union.md index e01782fe..0f26403e 100644 --- a/pkg/yqlib/doc/Union.md +++ b/pkg/yqlib/doc/Union.md @@ -17,6 +17,7 @@ Given a sample.yml file of: a: fieldA b: fieldB c: fieldC +'': null ``` then ```bash diff --git a/pkg/yqlib/lib.go b/pkg/yqlib/lib.go index 7d5b54a1..93089993 100644 --- a/pkg/yqlib/lib.go +++ b/pkg/yqlib/lib.go @@ -65,7 +65,7 @@ var SortKeys = &OperationType{Type: "SORT_KEYS", NumArgs: 1, Precedence: 50, Han var CollectObject = &OperationType{Type: "COLLECT_OBJECT", NumArgs: 0, Precedence: 50, Handler: CollectObjectOperator} var TraversePath = &OperationType{Type: "TRAVERSE_PATH", NumArgs: 0, Precedence: 50, Handler: TraversePathOperator} -var TraverseArray = &OperationType{Type: "TRAVERSE_ARRAY", NumArgs: 2, Precedence: 50, Handler: TraverseArrayOperator} +var TraverseArray = &OperationType{Type: "TRAVERSE_ARRAY", NumArgs: 1, Precedence: 50, Handler: TraverseArrayOperator} var DocumentFilter = &OperationType{Type: "DOCUMENT_FILTER", NumArgs: 0, Precedence: 50, Handler: TraversePathOperator} var SelfReference = &OperationType{Type: "SELF", NumArgs: 0, Precedence: 50, Handler: SelfOperator} diff --git a/pkg/yqlib/operator_array_traverse.go b/pkg/yqlib/operator_array_traverse.go index 125d0ab3..52495e16 100644 --- a/pkg/yqlib/operator_array_traverse.go +++ b/pkg/yqlib/operator_array_traverse.go @@ -12,11 +12,6 @@ func TraverseArrayOperator(d *dataTreeNavigator, matchingNodes *list.List, pathN // lhs is an expression that will yield a bunch of arrays // rhs is a collect expression that will yield indexes to retreive of the arrays - lhs, err := d.GetMatchingNodes(matchingNodes, pathNode.Lhs) - if err != nil { - return nil, err - } - rhs, err := d.GetMatchingNodes(matchingNodes, pathNode.Rhs) if err != nil { return nil, err @@ -25,36 +20,89 @@ func TraverseArrayOperator(d *dataTreeNavigator, matchingNodes *list.List, pathN var indicesToTraverse = rhs.Front().Value.(*CandidateNode).Node.Content var matchingNodeMap = list.New() - for el := lhs.Front(); el != nil; el = el.Next() { + for el := matchingNodes.Front(); el != nil; el = el.Next() { candidate := el.Value.(*CandidateNode) + node := UnwrapDoc(candidate.Node) + if node.Tag == "!!null" { + log.Debugf("OperatorArrayTraverse got a null - turning it into an empty array") + // auto vivification, make it into an empty array + node.Tag = "" + node.Kind = yaml.SequenceNode + } else if node.Kind == yaml.AliasNode { + candidate.Node = node.Alias + node = node.Alias + } - if candidate.Node.Kind == yaml.SequenceNode { + if node.Kind == yaml.SequenceNode { newNodes, err := traverseArrayWithIndices(candidate, indicesToTraverse) if err != nil { return nil, err } matchingNodeMap.PushBackList(newNodes) + } else if node.Kind == yaml.MappingNode && len(indicesToTraverse) == 0 { + // splat the map + newNodes, err := traverseMapWithIndices(candidate, indicesToTraverse) + if err != nil { + return nil, err + } + matchingNodeMap.PushBackList(newNodes) } else { - log.Debugf("OperatorArray Traverse skipping %v as its a %v", candidate, candidate.Node.Tag) + log.Debugf("OperatorArrayTraverse skipping %v as its a %v", candidate, node.Tag) } } return matchingNodeMap, nil } +func traverseMapWithIndices(candidate *CandidateNode, indices []*yaml.Node) (*list.List, error) { + //REWRITE TO USE TRAVERSE MAP + + node := UnwrapDoc(candidate.Node) + var contents = node.Content + var matchingNodeMap = list.New() + if len(indices) == 0 { + for index := 0; index < len(contents); index = index + 2 { + key := contents[index] + value := contents[index+1] + matchingNodeMap.PushBack(&CandidateNode{ + Node: value, + Path: candidate.CreateChildPath(key.Value), + Document: candidate.Document, + }) + } + return matchingNodeMap, nil + } + + for index := 0; index < len(contents); index = index + 2 { + key := contents[index] + value := contents[index+1] + for _, indexNode := range indices { + if key.Value == indexNode.Value { + matchingNodeMap.PushBack(&CandidateNode{ + Node: value, + Path: candidate.CreateChildPath(key.Value), + Document: candidate.Document, + }) + } + } + + } + return matchingNodeMap, nil +} + func traverseArrayWithIndices(candidate *CandidateNode, indices []*yaml.Node) (*list.List, error) { log.Debug("traverseArrayWithIndices") var newMatches = list.New() + node := UnwrapDoc(candidate.Node) if len(indices) == 0 { - var contents = candidate.Node.Content var index int64 - for index = 0; index < int64(len(contents)); index = index + 1 { + for index = 0; index < int64(len(node.Content)); index = index + 1 { newMatches.PushBack(&CandidateNode{ Document: candidate.Document, Path: candidate.CreateChildPath(index), - Node: contents[index], + Node: node.Content[index], }) } return newMatches, nil @@ -67,10 +115,10 @@ func traverseArrayWithIndices(candidate *CandidateNode, indices []*yaml.Node) (* return nil, err } indexToUse := index - contentLength := int64(len(candidate.Node.Content)) + contentLength := int64(len(node.Content)) for contentLength <= index { - candidate.Node.Content = append(candidate.Node.Content, &yaml.Node{Tag: "!!null", Kind: yaml.ScalarNode, Value: "null"}) - contentLength = int64(len(candidate.Node.Content)) + node.Content = append(node.Content, &yaml.Node{Tag: "!!null", Kind: yaml.ScalarNode, Value: "null"}) + contentLength = int64(len(node.Content)) } if indexToUse < 0 { @@ -82,7 +130,7 @@ func traverseArrayWithIndices(candidate *CandidateNode, indices []*yaml.Node) (* } newMatches.PushBack(&CandidateNode{ - Node: candidate.Node.Content[indexToUse], + Node: node.Content[indexToUse], Document: candidate.Document, Path: candidate.CreateChildPath(index), }) diff --git a/pkg/yqlib/operator_array_traverse_test.go b/pkg/yqlib/operator_array_traverse_test.go index 0a7432c7..5756e782 100644 --- a/pkg/yqlib/operator_array_traverse_test.go +++ b/pkg/yqlib/operator_array_traverse_test.go @@ -5,6 +5,22 @@ import ( ) var traverseArrayOperatorScenarios = []expressionScenario{ + { + document: `[a,b,c]`, + expression: `.[]`, + expected: []string{ + "D0, P[0], (!!str)::a\n", + "D0, P[1], (!!str)::b\n", + "D0, P[2], (!!str)::c\n", + }, + }, + { + document: `[a,b,c]`, + expression: `[]`, + expected: []string{ + "D0, P[], (!!seq)::[]\n", + }, + }, { document: `{a: [a,b,c]}`, expression: `.a[0]`, @@ -20,6 +36,14 @@ var traverseArrayOperatorScenarios = []expressionScenario{ "D0, P[a 2], (!!str)::c\n", }, }, + { + document: `{a: [a,b,c]}`, + expression: `.a.[0, 2]`, + expected: []string{ + "D0, P[a 0], (!!str)::a\n", + "D0, P[a 2], (!!str)::c\n", + }, + }, { document: `{a: [a,b,c]}`, expression: `.a.[0]`, diff --git a/pkg/yqlib/operator_assign_test.go b/pkg/yqlib/operator_assign_test.go index 67eacc74..f3acf2f0 100644 --- a/pkg/yqlib/operator_assign_test.go +++ b/pkg/yqlib/operator_assign_test.go @@ -80,7 +80,15 @@ var assignOperatorScenarios = []expressionScenario{ { description: "Update selected results", document: `{a: {b: apple, c: cactus}}`, - expression: `(.a.[] | select(. == "apple")) = "frog"`, + expression: `(.a[] | select(. == "apple")) = "frog"`, + expected: []string{ + "D0, P[], (doc)::{a: {b: frog, c: cactus}}\n", + }, + }, + { + skipDoc: true, + document: `{a: {b: apple, c: cactus}}`, + expression: `(.a.[] | select(. == "apple")) = "frog"`, expected: []string{ "D0, P[], (doc)::{a: {b: frog, c: cactus}}\n", }, diff --git a/pkg/yqlib/operator_traverse_path.go b/pkg/yqlib/operator_traverse_path.go index 9673bd1b..225929c1 100644 --- a/pkg/yqlib/operator_traverse_path.go +++ b/pkg/yqlib/operator_traverse_path.go @@ -77,7 +77,7 @@ func traverse(d *dataTreeNavigator, matchingNode *CandidateNode, operation *Oper } func keyMatches(key *yaml.Node, pathNode *Operation) bool { - return pathNode.Value == "[]" || Match(key.Value, pathNode.StringValue) + return Match(key.Value, pathNode.StringValue) } func traverseMap(matchingNode *CandidateNode, operation *Operation) (*list.List, error) { diff --git a/pkg/yqlib/operator_traverse_path_test.go b/pkg/yqlib/operator_traverse_path_test.go index e39e5a62..1a9ea912 100644 --- a/pkg/yqlib/operator_traverse_path_test.go +++ b/pkg/yqlib/operator_traverse_path_test.go @@ -65,7 +65,7 @@ var traversePathOperatorScenarios = []expressionScenario{ }, { skipDoc: true, - document: `{}`, + document: ``, expression: `.[1].a`, expected: []string{ "D0, P[1 a], (!!null)::null\n", diff --git a/pkg/yqlib/path_parse_test.go b/pkg/yqlib/path_parse_test.go index 1dfa68d2..fabefc90 100644 --- a/pkg/yqlib/path_parse_test.go +++ b/pkg/yqlib/path_parse_test.go @@ -17,6 +17,11 @@ var pathTests = []struct { append(make([]interface{}, 0), "[", "]"), append(make([]interface{}, 0), "EMPTY", "COLLECT", "SHORT_PIPE"), }, + { + `.[]`, + append(make([]interface{}, 0), "TRAVERSE_ARRAY", "[", "]"), + append(make([]interface{}, 0), "EMPTY", "COLLECT", "SHORT_PIPE", "TRAVERSE_ARRAY"), + }, { `.a[]`, append(make([]interface{}, 0), "a", "TRAVERSE_ARRAY", "[", "]"), diff --git a/pkg/yqlib/path_tokeniser.go b/pkg/yqlib/path_tokeniser.go index 0cd68f02..6cfb8a5a 100644 --- a/pkg/yqlib/path_tokeniser.go +++ b/pkg/yqlib/path_tokeniser.go @@ -22,6 +22,7 @@ const ( CloseCollect OpenCollectObject CloseCollectObject + TraverseArrayCollect ) type Token struct { @@ -48,6 +49,9 @@ func (t *Token) toString() string { return "{" } else if t.TokenType == CloseCollectObject { return "}" + } else if t.TokenType == TraverseArrayCollect { + return ".[" + } else { return "NFI" } @@ -185,7 +189,8 @@ func initLexer() (*lex.Lexer, error) { lexer.Add([]byte(`\(`), literalToken(OpenBracket, false)) lexer.Add([]byte(`\)`), literalToken(CloseBracket, true)) - lexer.Add([]byte(`\.\[\]`), pathToken(false)) + // lexer.Add([]byte(`\.\[\]`), pathToken(false)) // traverseCollect(false) + lexer.Add([]byte(`\.\[`), literalToken(TraverseArrayCollect, false)) lexer.Add([]byte(`\.\.`), opToken(RecursiveDescent)) lexer.Add([]byte(`,`), opToken(Union)) @@ -228,7 +233,7 @@ func initLexer() (*lex.Lexer, error) { lexer.Add([]byte(`\s*\|=\s*`), opTokenWithPrefs(Assign, nil, &AssignOpPreferences{true})) - lexer.Add([]byte(`\.\[-?[0-9]+\]`), arrayIndextoken(true)) + // lexer.Add([]byte(`\.\[-?[0-9]+\]`), arrayIndextoken(true)) // traverseCollect(true) lexer.Add([]byte("( |\t|\n|\r)+"), skip) @@ -320,6 +325,17 @@ func (p *pathTokeniser) handleToken(tokens []*Token, index int, postProcessedTok skipNextToken = false token := tokens[index] + if token.TokenType == TraverseArrayCollect { + //need to put a traverse array then a collect token + // do this by adding traverse then converting token to collect + + op := &Operation{OperationType: TraverseArray, StringValue: "TRAVERSE_ARRAY"} + postProcessedTokens = append(postProcessedTokens, &Token{TokenType: OperationToken, Operation: op}) + + token = &Token{TokenType: OpenCollect} + + } + if index != len(tokens)-1 && token.AssignOperation != nil && tokens[index+1].TokenType == OperationToken && tokens[index+1].Operation.OperationType == Assign { @@ -337,8 +353,19 @@ func (p *pathTokeniser) handleToken(tokens []*Token, index int, postProcessedTok } if index != len(tokens)-1 && token.CheckForPostTraverse && tokens[index+1].TokenType == OpenCollect { - op := &Operation{OperationType: TraverseArray} + + op := &Operation{OperationType: ShortPipe, Value: "PIPE"} postProcessedTokens = append(postProcessedTokens, &Token{TokenType: OperationToken, Operation: op}) + + op = &Operation{OperationType: TraverseArray} + postProcessedTokens = append(postProcessedTokens, &Token{TokenType: OperationToken, Operation: op}) + } + if index != len(tokens)-1 && token.CheckForPostTraverse && + tokens[index+1].TokenType == TraverseArrayCollect { + + op := &Operation{OperationType: ShortPipe, Value: "PIPE"} + postProcessedTokens = append(postProcessedTokens, &Token{TokenType: OperationToken, Operation: op}) + } return postProcessedTokens, skipNextToken }