diff --git a/pkg/yqlib/doc/Mulitply Operator.md b/pkg/yqlib/doc/Mulitply Operator.md new file mode 100644 index 00000000..24c00aa2 --- /dev/null +++ b/pkg/yqlib/doc/Mulitply Operator.md @@ -0,0 +1,121 @@ +# Mulitply Operator +## Examples +### Merge objects together +sample.yml: +```yaml +{a: {also: me}, b: {also: {g: wizz}}} +``` +Expression +```bash +yq '. * {"a":.b}' < sample.yml +``` +Result +```yaml +{a: {also: {g: wizz}}, b: {also: {g: wizz}}} +``` +### Merge keeps style of LHS +sample.yml: +```yaml +a: {things: great} +b: + also: "me" + +``` +Expression +```bash +yq '. * {"a":.b}' < sample.yml +``` +Result +```yaml +a: {things: great, also: "me"} +b: + also: "me" +``` +### Merge arrays +sample.yml: +```yaml +{a: [1,2,3], b: [3,4,5]} +``` +Expression +```bash +yq '. * {"a":.b}' < sample.yml +``` +Result +```yaml +{a: [3, 4, 5], b: [3, 4, 5]} +``` +### Merge to prefix an element +sample.yml: +```yaml +{a: cat, b: dog} +``` +Expression +```bash +yq '. * {"a": {"c": .a}}' < sample.yml +``` +Result +```yaml +{a: {c: cat}, b: dog} +``` +### Merge with simple aliases +sample.yml: +```yaml +{a: &cat {c: frog}, b: {f: *cat}, c: {g: thongs}} +``` +Expression +```bash +yq '.c * .b' < sample.yml +``` +Result +```yaml +{g: thongs, f: *cat} +``` +### Merge does not copy anchor names +sample.yml: +```yaml +{a: {c: &cat frog}, b: {f: *cat}, c: {g: thongs}} +``` +Expression +```bash +yq '.c * .a' < sample.yml +``` +Result +```yaml +{g: thongs, c: frog} +``` +### Merge with merge anchors +sample.yml: +```yaml + +foo: &foo + a: foo_a + thing: foo_thing + c: foo_c + +bar: &bar + b: bar_b + thing: bar_thing + c: bar_c + +foobarList: + b: foobarList_b + <<: [*foo,*bar] + c: foobarList_c + +foobar: + c: foobar_c + <<: *foo + thing: foobar_thing + +``` +Expression +```bash +yq '.foobar * .foobarList' < sample.yml +``` +Result +```yaml +c: foobarList_c +<<: [*foo, *bar] +thing: foobar_thing +b: foobarList_b +``` diff --git a/pkg/yqlib/doc/Select Operator.md b/pkg/yqlib/doc/Select Operator.md new file mode 100644 index 00000000..3ddb6cc9 --- /dev/null +++ b/pkg/yqlib/doc/Select Operator.md @@ -0,0 +1,39 @@ +Select is used to filter arrays and maps by a boolean expression. +## Examples +### Select elements from array +Given a sample.yml file of: +```yaml +- cat +- goat +- dog +``` +then +```bash +yq eval '.[] | select(. == "*at")' sample.yml +``` +will output +```yaml +cat +goat +``` + +### Select and update matching values in map +Given a sample.yml file of: +```yaml +a: + things: cat + bob: goat + horse: dog +``` +then +```bash +yq eval '(.a[] | select(. == "*at")) |= "rabbit"' sample.yml +``` +will output +```yaml +a: + things: rabbit + bob: rabbit + horse: dog +``` + diff --git a/pkg/yqlib/doc/Traverse Operator.md b/pkg/yqlib/doc/Traverse Operator.md new file mode 100644 index 00000000..dace7ed4 --- /dev/null +++ b/pkg/yqlib/doc/Traverse Operator.md @@ -0,0 +1,353 @@ +This is the simples (and perhaps most used) operator, it is used to navigate deeply into yaml structurse. +## Examples +### Simple map navigation +Given a sample.yml file of: +```yaml +a: + b: apple +``` +then +```bash +yq eval '.a' sample.yml +``` +will output +```yaml +b: apple +``` + +### Splat +Often used to pipe children into other operators + +Given a sample.yml file of: +```yaml +- b: apple +- c: banana +``` +then +```bash +yq eval '.[]' sample.yml +``` +will output +```yaml +b: apple +c: banana +``` + +### Children don't exist +Nodes are added dynamically while traversing + +Given a sample.yml file of: +```yaml +c: banana +``` +then +```bash +yq eval '.a.b' sample.yml +``` +will output +```yaml +null +``` + +### Wildcard matching +Given a sample.yml file of: +```yaml +a: + cat: apple + mad: things +``` +then +```bash +yq eval '.a."*a*"' sample.yml +``` +will output +```yaml +apple +things +``` + +### Aliases +Given a sample.yml file of: +```yaml +a: &cat + c: frog +b: *cat +``` +then +```bash +yq eval '.b' sample.yml +``` +will output +```yaml +*cat +``` + +### Traversing aliases with splat +Given a sample.yml file of: +```yaml +a: &cat + c: frog +b: *cat +``` +then +```bash +yq eval '.b.[]' sample.yml +``` +will output +```yaml +frog +``` + +### Traversing aliases explicitly +Given a sample.yml file of: +```yaml +a: &cat + c: frog +b: *cat +``` +then +```bash +yq eval '.b.c' sample.yml +``` +will output +```yaml +frog +``` + +### Traversing arrays by index +Given a sample.yml file of: +```yaml +- 1 +- 2 +- 3 +``` +then +```bash +yq eval '[0]' sample.yml +``` +will output +```yaml +1 +``` + +### Maps with numeric keys +Given a sample.yml file of: +```yaml +2: cat +``` +then +```bash +yq eval '[2]' sample.yml +``` +will output +```yaml +cat +``` + +### Maps with non existing numeric keys +Given a sample.yml file of: +```yaml +a: b +``` +then +```bash +yq eval '[0]' sample.yml +``` +will output +```yaml +null +``` + +### Traversing merge anchors +Given a sample.yml file of: +```yaml +foo: &foo + a: foo_a + thing: foo_thing + c: foo_c +bar: &bar + b: bar_b + thing: bar_thing + c: bar_c +foobarList: + b: foobarList_b + !!merge <<: + - *foo + - *bar + c: foobarList_c +foobar: + c: foobar_c + !!merge <<: *foo + thing: foobar_thing +``` +then +```bash +yq eval '.foobar.a' sample.yml +``` +will output +```yaml +foo_a +``` + +### Traversing merge anchors with override +Given a sample.yml file of: +```yaml +foo: &foo + a: foo_a + thing: foo_thing + c: foo_c +bar: &bar + b: bar_b + thing: bar_thing + c: bar_c +foobarList: + b: foobarList_b + !!merge <<: + - *foo + - *bar + c: foobarList_c +foobar: + c: foobar_c + !!merge <<: *foo + thing: foobar_thing +``` +then +```bash +yq eval '.foobar.c' sample.yml +``` +will output +```yaml +foo_c +``` + +### Traversing merge anchors with local override +Given a sample.yml file of: +```yaml +foo: &foo + a: foo_a + thing: foo_thing + c: foo_c +bar: &bar + b: bar_b + thing: bar_thing + c: bar_c +foobarList: + b: foobarList_b + !!merge <<: + - *foo + - *bar + c: foobarList_c +foobar: + c: foobar_c + !!merge <<: *foo + thing: foobar_thing +``` +then +```bash +yq eval '.foobar.thing' sample.yml +``` +will output +```yaml +foobar_thing +``` + +### Splatting merge anchors +Given a sample.yml file of: +```yaml +foo: &foo + a: foo_a + thing: foo_thing + c: foo_c +bar: &bar + b: bar_b + thing: bar_thing + c: bar_c +foobarList: + b: foobarList_b + !!merge <<: + - *foo + - *bar + c: foobarList_c +foobar: + c: foobar_c + !!merge <<: *foo + thing: foobar_thing +``` +then +```bash +yq eval '.foobar.[]' sample.yml +``` +will output +```yaml +foo_c +foo_a +foobar_thing +``` + +### Traversing merge anchor lists +Note that the later merge anchors override previous + +Given a sample.yml file of: +```yaml +foo: &foo + a: foo_a + thing: foo_thing + c: foo_c +bar: &bar + b: bar_b + thing: bar_thing + c: bar_c +foobarList: + b: foobarList_b + !!merge <<: + - *foo + - *bar + c: foobarList_c +foobar: + c: foobar_c + !!merge <<: *foo + thing: foobar_thing +``` +then +```bash +yq eval '.foobarList.thing' sample.yml +``` +will output +```yaml +bar_thing +``` + +### Splatting merge anchor lists +Given a sample.yml file of: +```yaml +foo: &foo + a: foo_a + thing: foo_thing + c: foo_c +bar: &bar + b: bar_b + thing: bar_thing + c: bar_c +foobarList: + b: foobarList_b + !!merge <<: + - *foo + - *bar + c: foobarList_c +foobar: + c: foobar_c + !!merge <<: *foo + thing: foobar_thing +``` +then +```bash +yq eval '.foobarList.[]' sample.yml +``` +will output +```yaml +bar_b +foo_a +bar_thing +foobarList_c +``` + diff --git a/pkg/yqlib/doc/Union Operator.md b/pkg/yqlib/doc/Union Operator.md new file mode 100644 index 00000000..e1ce5fb2 --- /dev/null +++ b/pkg/yqlib/doc/Union Operator.md @@ -0,0 +1,49 @@ +This operator is used to combine different results together. +## Examples +### Combine scalars +Running +```bash +yq eval --null-input '1, true, "cat"' +``` +will output +```yaml +1 +true +cat +``` + +### Combine selected paths +Given a sample.yml file of: +```yaml +a: fieldA +b: fieldB +c: fieldC +``` +then +```bash +yq eval '.a, .c' sample.yml +``` +will output +```yaml +fieldA +fieldC +``` + +### Combine selected paths +Given a sample.yml file of: +```yaml +a: fieldA +b: fieldB +c: fieldC +``` +then +```bash +yq eval '(.a, .c) |= "potatoe"' sample.yml +``` +will output +```yaml +a: potatoe +b: fieldB +c: potatoe +``` + diff --git a/pkg/yqlib/doc/Update Assign Operator.md b/pkg/yqlib/doc/Update Assign Operator.md index 7b28878b..866d2db2 100644 --- a/pkg/yqlib/doc/Update Assign Operator.md +++ b/pkg/yqlib/doc/Update Assign Operator.md @@ -13,7 +13,26 @@ yq eval '.a |= .b' sample.yml ``` will output ```yaml -{a: {g: foof}} +a: + g: foof +``` + +### Updated multiple paths +Given a sample.yml file of: +```yaml +a: fieldA +b: fieldB +c: fieldC +``` +then +```bash +yq eval '(.a, .c) |= "potatoe"' sample.yml +``` +will output +```yaml +a: potatoe +b: fieldB +c: potatoe ``` ### Update string value @@ -28,7 +47,8 @@ yq eval '.a.b |= "frog"' sample.yml ``` will output ```yaml -{a: {b: frog}} +a: + b: frog ``` ### Update selected results @@ -44,7 +64,9 @@ yq eval '.a[] | select(. == "apple") |= "frog"' sample.yml ``` will output ```yaml -{a: {b: frog, c: cactus}} +a: + b: frog + c: cactus ``` ### Update array values @@ -60,7 +82,9 @@ yq eval '.[] | select(. == "*andy") |= "bogs"' sample.yml ``` will output ```yaml -[bogs, apple, bogs] +- bogs +- apple +- bogs ``` ### Update empty object @@ -74,7 +98,9 @@ yq eval '.a.b |= "bogs"' sample.yml ``` will output ```yaml -{a: {b: bogs}} +'': null +a: + b: bogs ``` ### Update empty object and array @@ -88,6 +114,9 @@ yq eval '.a.b[0] |= "bogs"' sample.yml ``` will output ```yaml -{a: {b: [bogs]}} +'': null +a: + b: + - bogs ``` diff --git a/pkg/yqlib/doc/headers/Select Operator.md b/pkg/yqlib/doc/headers/Select Operator.md new file mode 100644 index 00000000..3d1546f1 --- /dev/null +++ b/pkg/yqlib/doc/headers/Select Operator.md @@ -0,0 +1 @@ +Select is used to filter arrays and maps by a boolean expression. \ No newline at end of file diff --git a/pkg/yqlib/doc/headers/Traverse Operator.md b/pkg/yqlib/doc/headers/Traverse Operator.md new file mode 100644 index 00000000..ff02606c --- /dev/null +++ b/pkg/yqlib/doc/headers/Traverse Operator.md @@ -0,0 +1 @@ +This is the simples (and perhaps most used) operator, it is used to navigate deeply into yaml structurse. \ No newline at end of file diff --git a/pkg/yqlib/doc/headers/Union Operator.md b/pkg/yqlib/doc/headers/Union Operator.md new file mode 100644 index 00000000..787bda7f --- /dev/null +++ b/pkg/yqlib/doc/headers/Union Operator.md @@ -0,0 +1 @@ +This operator is used to combine different results together. \ No newline at end of file diff --git a/pkg/yqlib/lib.go b/pkg/yqlib/lib.go index 542a232d..ed1e4bf0 100644 --- a/pkg/yqlib/lib.go +++ b/pkg/yqlib/lib.go @@ -17,7 +17,6 @@ type OperationType struct { } // operators TODO: -// - get Kind // - get path operator (like doc index) // - get file index op (like doc index) // - get file name op (like doc index) diff --git a/pkg/yqlib/operator_assign_update_test.go b/pkg/yqlib/operator_assign_update_test.go index eb2018c5..1fbc5e8c 100644 --- a/pkg/yqlib/operator_assign_update_test.go +++ b/pkg/yqlib/operator_assign_update_test.go @@ -13,6 +13,14 @@ var assignOperatorScenarios = []expressionScenario{ "D0, P[], (doc)::{a: {g: foof}}\n", }, }, + { + description: "Updated multiple paths", + document: `{a: fieldA, b: fieldB, c: fieldC}`, + expression: `(.a, .c) |= "potatoe"`, + expected: []string{ + "D0, P[], (doc)::{a: potatoe, b: fieldB, c: potatoe}\n", + }, + }, { description: "Update string value", document: `{a: {b: apple}}`, diff --git a/pkg/yqlib/operator_select_test.go b/pkg/yqlib/operator_select_test.go index b7ae38f9..2d3f0966 100644 --- a/pkg/yqlib/operator_select_test.go +++ b/pkg/yqlib/operator_select_test.go @@ -13,26 +13,30 @@ var selectOperatorScenarios = []expressionScenario{ "D0, P[0], (!!str)::cat\n", "D0, P[1], (!!str)::goat\n", }, - }, { + }, + { skipDoc: true, document: `[hot, fot, dog]`, expression: `.[] | select(. == "*at")`, expected: []string{}, - }, { + }, + { skipDoc: true, document: `a: [cat,goat,dog]`, expression: `.a[] | select(. == "*at")`, expected: []string{ "D0, P[a 0], (!!str)::cat\n", "D0, P[a 1], (!!str)::goat\n"}, - }, { - description: "Select matching values in map", + }, + { + description: "Select and update matching values in map", document: `a: { things: cat, bob: goat, horse: dog }`, - expression: `.a[] | select(. == "*at")`, + expression: `(.a[] | select(. == "*at")) |= "rabbit"`, expected: []string{ - "D0, P[a things], (!!str)::cat\n", - "D0, P[a bob], (!!str)::goat\n"}, - }, { + "D0, P[], (doc)::a: {things: rabbit, bob: rabbit, horse: dog}\n", + }, + }, + { skipDoc: true, document: `a: { things: {include: true}, notMe: {include: false}, andMe: {include: fold} }`, expression: `.a[] | select(.include)`, @@ -40,7 +44,8 @@ var selectOperatorScenarios = []expressionScenario{ "D0, P[a things], (!!map)::{include: true}\n", "D0, P[a andMe], (!!map)::{include: fold}\n", }, - }, { + }, + { skipDoc: true, document: `[cat,~,dog]`, expression: `.[] | select(. == ~)`, diff --git a/pkg/yqlib/operator_traverse_path_test.go b/pkg/yqlib/operator_traverse_path_test.go index 9006ea4c..16809ea1 100644 --- a/pkg/yqlib/operator_traverse_path_test.go +++ b/pkg/yqlib/operator_traverse_path_test.go @@ -28,28 +28,34 @@ foobar: var traversePathOperatorScenarios = []expressionScenario{ { - document: `{a: {b: apple}}`, - expression: `.a`, + description: "Simple map navigation", + document: `{a: {b: apple}}`, + expression: `.a`, expected: []string{ "D0, P[a], (!!map)::{b: apple}\n", }, }, { - document: `[{b: apple}, {c: banana}]`, - expression: `.[]`, + description: "Splat", + subdescription: "Often used to pipe children into other operators", + document: `[{b: apple}, {c: banana}]`, + expression: `.[]`, expected: []string{ "D0, P[0], (!!map)::{b: apple}\n", "D0, P[1], (!!map)::{c: banana}\n", }, }, { - document: `{}`, - expression: `.a.b`, + description: "Children don't exist", + subdescription: "Nodes are added dynamically while traversing", + document: `{c: banana}`, + expression: `.a.b`, expected: []string{ "D0, P[a b], (!!null)::null\n", }, }, { + skipDoc: true, document: `{}`, expression: `.[1].a`, expected: []string{ @@ -57,6 +63,7 @@ var traversePathOperatorScenarios = []expressionScenario{ }, }, { + skipDoc: true, document: `{}`, expression: `.a.[1]`, expected: []string{ @@ -64,14 +71,16 @@ var traversePathOperatorScenarios = []expressionScenario{ }, }, { - document: `{a: {cat: apple, mad: things}}`, - expression: `.a."*a*"`, + description: "Wildcard matching", + document: `{a: {cat: apple, mad: things}}`, + expression: `.a."*a*"`, expected: []string{ "D0, P[a cat], (!!str)::apple\n", "D0, P[a mad], (!!str)::things\n", }, }, { + skipDoc: true, document: `{a: {cat: {b: 3}, mad: {b: 4}, fad: {c: t}}}`, expression: `.a."*a*".b`, expected: []string{ @@ -81,6 +90,7 @@ var traversePathOperatorScenarios = []expressionScenario{ }, }, { + skipDoc: true, document: `{a: {cat: apple, mad: things}}`, expression: `.a | (.cat, .mad)`, expected: []string{ @@ -89,6 +99,7 @@ var traversePathOperatorScenarios = []expressionScenario{ }, }, { + skipDoc: true, document: `{a: {cat: apple, mad: things}}`, expression: `.a | (.cat, .mad, .fad)`, expected: []string{ @@ -98,6 +109,7 @@ var traversePathOperatorScenarios = []expressionScenario{ }, }, { + skipDoc: true, document: `{a: {cat: apple, mad: things}}`, expression: `.a | (.cat, .mad, .fad) | select( (. == null) | not)`, expected: []string{ @@ -106,40 +118,53 @@ var traversePathOperatorScenarios = []expressionScenario{ }, }, { - document: `{a: &cat {c: frog}, b: *cat}`, - expression: `.b`, + description: "Aliases", + document: `{a: &cat {c: frog}, b: *cat}`, + expression: `.b`, expected: []string{ "D0, P[b], (alias)::*cat\n", }, }, { - document: `{a: &cat {c: frog}, b: *cat}`, - expression: `.b.[]`, + description: "Traversing aliases with splat", + document: `{a: &cat {c: frog}, b: *cat}`, + expression: `.b.[]`, expected: []string{ "D0, P[b c], (!!str)::frog\n", }, }, { - document: `{a: &cat {c: frog}, b: *cat}`, - expression: `.b.c`, + description: "Traversing aliases explicitly", + document: `{a: &cat {c: frog}, b: *cat}`, + expression: `.b.c`, expected: []string{ "D0, P[b c], (!!str)::frog\n", }, }, { + skipDoc: true, document: `[1,2,3]`, expression: `.b`, expected: []string{}, }, { - document: `[1,2,3]`, - expression: `[0]`, + description: "Traversing arrays by index", + document: `[1,2,3]`, + expression: `[0]`, expected: []string{ "D0, P[0], (!!int)::1\n", }, }, { - description: `Maps can have numbers as keys, so this default to a non-exisiting key behaviour.`, + description: "Maps with numeric keys", + document: `{2: cat}`, + expression: `[2]`, + expected: []string{ + "D0, P[2], (!!str)::cat\n", + }, + }, + { + description: "Maps with non existing numeric keys", document: `{a: b}`, expression: `[0]`, expected: []string{ @@ -147,6 +172,7 @@ var traversePathOperatorScenarios = []expressionScenario{ }, }, { + skipDoc: true, document: mergeDocSample, expression: `.foobar`, expected: []string{ @@ -154,29 +180,33 @@ var traversePathOperatorScenarios = []expressionScenario{ }, }, { - document: mergeDocSample, - expression: `.foobar.a`, + description: "Traversing merge anchors", + document: mergeDocSample, + expression: `.foobar.a`, expected: []string{ "D0, P[foobar a], (!!str)::foo_a\n", }, }, { - document: mergeDocSample, - expression: `.foobar.c`, + description: "Traversing merge anchors with override", + document: mergeDocSample, + expression: `.foobar.c`, expected: []string{ "D0, P[foobar c], (!!str)::foo_c\n", }, }, { - document: mergeDocSample, - expression: `.foobar.thing`, + description: "Traversing merge anchors with local override", + document: mergeDocSample, + expression: `.foobar.thing`, expected: []string{ "D0, P[foobar thing], (!!str)::foobar_thing\n", }, }, { - document: mergeDocSample, - expression: `.foobar.[]`, + description: "Splatting merge anchors", + document: mergeDocSample, + expression: `.foobar.[]`, expected: []string{ "D0, P[foobar c], (!!str)::foo_c\n", "D0, P[foobar a], (!!str)::foo_a\n", @@ -184,6 +214,7 @@ var traversePathOperatorScenarios = []expressionScenario{ }, }, { + skipDoc: true, document: mergeDocSample, expression: `.foobarList`, expected: []string{ @@ -191,6 +222,7 @@ var traversePathOperatorScenarios = []expressionScenario{ }, }, { + skipDoc: true, document: mergeDocSample, expression: `.foobarList.a`, expected: []string{ @@ -198,13 +230,16 @@ var traversePathOperatorScenarios = []expressionScenario{ }, }, { - document: mergeDocSample, - expression: `.foobarList.thing`, + description: "Traversing merge anchor lists", + subdescription: "Note that the later merge anchors override previous", + document: mergeDocSample, + expression: `.foobarList.thing`, expected: []string{ "D0, P[foobarList thing], (!!str)::bar_thing\n", }, }, { + skipDoc: true, document: mergeDocSample, expression: `.foobarList.c`, expected: []string{ @@ -212,6 +247,7 @@ var traversePathOperatorScenarios = []expressionScenario{ }, }, { + skipDoc: true, document: mergeDocSample, expression: `.foobarList.b`, expected: []string{ @@ -219,8 +255,9 @@ var traversePathOperatorScenarios = []expressionScenario{ }, }, { - document: mergeDocSample, - expression: `.foobarList.[]`, + description: "Splatting merge anchor lists", + document: mergeDocSample, + expression: `.foobarList.[]`, expected: []string{ "D0, P[foobarList b], (!!str)::bar_b\n", "D0, P[foobarList a], (!!str)::foo_a\n", @@ -234,4 +271,5 @@ func TestTraversePathOperatorScenarios(t *testing.T) { for _, tt := range traversePathOperatorScenarios { testScenario(t, &tt) } + documentScenarios(t, "Traverse Operator", traversePathOperatorScenarios) } diff --git a/pkg/yqlib/operator_union_test.go b/pkg/yqlib/operator_union_test.go index d28e4a98..578dd12a 100644 --- a/pkg/yqlib/operator_union_test.go +++ b/pkg/yqlib/operator_union_test.go @@ -6,20 +6,21 @@ import ( var unionOperatorScenarios = []expressionScenario{ { - document: `{}`, - expression: `"cat", "dog"`, - expected: []string{ - "D0, P[], (!!str)::cat\n", - "D0, P[], (!!str)::dog\n", - }, - }, { - document: `{a: frog}`, - expression: `1, true, "cat", .a`, + description: "Combine scalars", + expression: `1, true, "cat"`, expected: []string{ "D0, P[], (!!int)::1\n", "D0, P[], (!!bool)::true\n", "D0, P[], (!!str)::cat\n", - "D0, P[a], (!!str)::frog\n", + }, + }, + { + description: "Combine selected paths", + document: `{a: fieldA, b: fieldB, c: fieldC}`, + expression: `.a, .c`, + expected: []string{ + "D0, P[a], (!!str)::fieldA\n", + "D0, P[c], (!!str)::fieldC\n", }, }, } @@ -28,4 +29,5 @@ func TestUnionOperatorScenarios(t *testing.T) { for _, tt := range unionOperatorScenarios { testScenario(t, &tt) } + documentScenarios(t, "Union Operator", unionOperatorScenarios) } diff --git a/pkg/yqlib/operators_test.go b/pkg/yqlib/operators_test.go index 7d4402b6..8af48869 100644 --- a/pkg/yqlib/operators_test.go +++ b/pkg/yqlib/operators_test.go @@ -15,6 +15,7 @@ import ( type expressionScenario struct { description string + subdescription string document string expression string expected []string @@ -123,6 +124,10 @@ func documentScenarios(t *testing.T, title string, scenarios []expressionScenari } else { writeOrPanic(w, fmt.Sprintf("### Example %v\n", index)) } + if s.subdescription != "" { + writeOrPanic(w, s.subdescription) + writeOrPanic(w, "\n\n") + } formattedDoc := "" if s.document != "" { if s.dontFormatInputForDoc {