diff --git a/cmd/constant.go b/cmd/constant.go index 9e48f52d..dc4d01ff 100644 --- a/cmd/constant.go +++ b/cmd/constant.go @@ -14,6 +14,5 @@ var noDocSeparators = false var nullInput = false var verbose = false var version = false -var shellCompletion = "" // var log = logging.MustGetLogger("yq") diff --git a/cmd/root.go b/cmd/root.go index 4a225ef4..6836a864 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,7 +1,6 @@ package cmd import ( - "fmt" "os" "github.com/spf13/cobra" @@ -18,20 +17,6 @@ func New() *cobra.Command { cmd.Print(GetVersionDisplay()) return nil } - if shellCompletion != "" { - switch shellCompletion { - case "bash", "": - return cmd.GenBashCompletion(os.Stdout) - case "zsh": - return cmd.GenZshCompletion(os.Stdout) - case "fish": - return cmd.GenFishCompletion(os.Stdout, true) - case "powershell": - return cmd.GenPowerShellCompletion(os.Stdout) - default: - return fmt.Errorf("Unknown variant %v", shellCompletion) - } - } cmd.Println(cmd.UsageString()) return nil @@ -62,10 +47,12 @@ func New() *cobra.Command { rootCmd.PersistentFlags().IntVarP(&indent, "indent", "I", 2, "sets indent level for output") rootCmd.Flags().BoolVarP(&version, "version", "V", false, "Print version information and quit") - rootCmd.Flags().StringVarP(&shellCompletion, "shellCompletion", "", "", "[bash/zsh/powershell/fish] prints shell completion script") - rootCmd.PersistentFlags().BoolVarP(&forceColor, "colors", "C", false, "force print with colors") rootCmd.PersistentFlags().BoolVarP(&forceNoColor, "no-colors", "M", false, "force print with no colors") - rootCmd.AddCommand(createEvaluateSequenceCommand(), createEvaluateAllCommand()) + rootCmd.AddCommand( + createEvaluateSequenceCommand(), + createEvaluateAllCommand(), + completionCmd, + ) return rootCmd } diff --git a/cmd/shell-completion.go b/cmd/shell-completion.go new file mode 100644 index 00000000..0fadfb12 --- /dev/null +++ b/cmd/shell-completion.go @@ -0,0 +1,61 @@ +package cmd + +import ( + "os" + + "github.com/spf13/cobra" +) + +var completionCmd = &cobra.Command{ + Use: "shell-completion [bash|zsh|fish|powershell]", + Short: "Generate completion script", + Long: `To load completions: + +Bash: + +$ source <(yq shell-completion bash) + +# To load completions for each session, execute once: +Linux: + $ yq shell-completion bash > /etc/bash_completion.d/yq +MacOS: + $ yq shell-completion bash > /usr/local/etc/bash_completion.d/yq + +Zsh: + +# If shell completion is not already enabled in your environment you will need +# to enable it. You can execute the following once: + +$ echo "autoload -U compinit; compinit" >> ~/.zshrc + +# To load completions for each session, execute once: +$ yq shell-completion zsh > "${fpath[1]}/_yq" + +# You will need to start a new shell for this setup to take effect. + +Fish: + +$ yq shell-completion fish | source + +# To load completions for each session, execute once: +$ yq shell-completion fish > ~/.config/fish/completions/yq.fish +`, + DisableFlagsInUseLine: true, + ValidArgs: []string{"bash", "zsh", "fish", "powershell"}, + Args: cobra.ExactValidArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + var err error = nil + switch args[0] { + case "bash": + err = cmd.Root().GenBashCompletion(os.Stdout) + case "zsh": + err = cmd.Root().GenZshCompletion(os.Stdout) + case "fish": + err = cmd.Root().GenFishCompletion(os.Stdout, true) + case "powershell": + err = cmd.Root().GenPowerShellCompletion(os.Stdout) + } + return err + + }, +} diff --git a/pkg/yqlib/data_tree_navigator_test.go b/pkg/yqlib/data_tree_navigator_test.go deleted file mode 100644 index 1e2d7b91..00000000 --- a/pkg/yqlib/data_tree_navigator_test.go +++ /dev/null @@ -1,664 +0,0 @@ -package yqlib - -import ( - "container/list" -) - -func resultsToString(results *list.List) []string { - var pretty []string = make([]string, 0) - for el := results.Front(); el != nil; el = el.Next() { - n := el.Value.(*CandidateNode) - pretty = append(pretty, NodeToString(n)) - } - return pretty -} - -// func TestDataTreeNavigatorDeleteSimple(t *testing.T) { - -// nodes := readDoc(t, `a: -// b: apple -// c: camel`) - -// path, errPath := treeCreator.ParsePath("a .- b") -// if errPath != nil { -// t.Error(errPath) -// } -// results, errNav := treeNavigator.GetMatchingNodes(nodes, path) - -// if errNav != nil { -// t.Error(errNav) -// } - -// expected := ` -// -- Node -- -// Document 0, path: [a] -// Tag: !!map, Kind: MappingNode, Anchor: -// c: camel -// ` -// test.AssertResult(t, expected, resultsToString(results)) -// } - -// func TestDataTreeNavigatorDeleteTwice(t *testing.T) { - -// nodes := readDoc(t, `a: -// b: apple -// c: camel -// d: dingo`) - -// path, errPath := treeCreator.ParsePath("a .- b OR a .- c") -// if errPath != nil { -// t.Error(errPath) -// } -// results, errNav := treeNavigator.GetMatchingNodes(nodes, path) - -// if errNav != nil { -// t.Error(errNav) -// } - -// expected := ` -// -- Node -- -// Document 0, path: [a] -// Tag: !!map, Kind: MappingNode, Anchor: -// d: dingo -// ` - -// test.AssertResult(t, expected, resultsToString(results)) -// } - -// func TestDataTreeNavigatorDeleteWithUnion(t *testing.T) { - -// nodes := readDoc(t, `a: -// b: apple -// c: camel -// d: dingo`) - -// path, errPath := treeCreator.ParsePath("a .- (b OR c)") -// if errPath != nil { -// t.Error(errPath) -// } -// results, errNav := treeNavigator.GetMatchingNodes(nodes, path) - -// if errNav != nil { -// t.Error(errNav) -// } - -// expected := ` -// -- Node -- -// Document 0, path: [a] -// Tag: !!map, Kind: MappingNode, Anchor: -// d: dingo -// ` - -// test.AssertResult(t, expected, resultsToString(results)) -// } - -// func TestDataTreeNavigatorDeleteByIndex(t *testing.T) { - -// nodes := readDoc(t, `a: -// - b: apple -// - b: sdfsd -// - b: apple`) - -// path, errPath := treeCreator.ParsePath("(a .- (0 or 1))") -// if errPath != nil { -// t.Error(errPath) -// } -// results, errNav := treeNavigator.GetMatchingNodes(nodes, path) - -// if errNav != nil { -// t.Error(errNav) -// } - -// expected := ` -// -- Node -- -// Document 0, path: [a] -// Tag: !!seq, Kind: SequenceNode, Anchor: -// - b: apple -// ` - -// test.AssertResult(t, expected, resultsToString(results)) -// } - -// func TestDataTreeNavigatorDeleteByFind(t *testing.T) { - -// nodes := readDoc(t, `a: -// - b: apple -// - b: sdfsd -// - b: apple`) - -// path, errPath := treeCreator.ParsePath("(a .- (* == apple))") -// if errPath != nil { -// t.Error(errPath) -// } -// results, errNav := treeNavigator.GetMatchingNodes(nodes, path) - -// if errNav != nil { -// t.Error(errNav) -// } - -// expected := ` -// -- Node -- -// Document 0, path: [a] -// Tag: !!seq, Kind: SequenceNode, Anchor: -// - b: sdfsd -// ` - -// test.AssertResult(t, expected, resultsToString(results)) -// } - -// func TestDataTreeNavigatorDeleteArrayByFind(t *testing.T) { - -// nodes := readDoc(t, `a: -// - apple -// - sdfsd -// - apple`) - -// path, errPath := treeCreator.ParsePath("(a .- (. == apple))") -// if errPath != nil { -// t.Error(errPath) -// } -// results, errNav := treeNavigator.GetMatchingNodes(nodes, path) - -// if errNav != nil { -// t.Error(errNav) -// } - -// expected := ` -// -- Node -- -// Document 0, path: [a] -// Tag: !!seq, Kind: SequenceNode, Anchor: -// - sdfsd -// ` - -// test.AssertResult(t, expected, resultsToString(results)) -// } - -// func TestDataTreeNavigatorDeleteViaSelf(t *testing.T) { - -// nodes := readDoc(t, `- apple -// - sdfsd -// - apple`) - -// path, errPath := treeCreator.ParsePath(". .- (. == apple)") -// if errPath != nil { -// t.Error(errPath) -// } -// results, errNav := treeNavigator.GetMatchingNodes(nodes, path) - -// if errNav != nil { -// t.Error(errNav) -// } - -// expected := ` -// -- Node -- -// Document 0, path: [] -// Tag: !!seq, Kind: SequenceNode, Anchor: -// - sdfsd -// ` - -// test.AssertResult(t, expected, resultsToString(results)) -// } - -// func TestDataTreeNavigatorFilterWithSplat(t *testing.T) { - -// nodes := readDoc(t, `f: -// a: frog -// b: dally -// c: log`) - -// path, errPath := treeCreator.ParsePath(".f | .[] == \"frog\"") -// if errPath != nil { -// t.Error(errPath) -// } -// results, errNav := treeNavigator.GetMatchingNodes(nodes, path) - -// if errNav != nil { -// t.Error(errNav) -// } - -// expected := ` -// -- Node -- -// Document 0, path: [f] -// Tag: !!int, Kind: ScalarNode, Anchor: -// 2 -// ` - -// test.AssertResult(t, expected, resultsToString(results)) -// } - -// func TestDataTreeNavigatorCountAndCollectWithFilterCmd(t *testing.T) { - -// nodes := readDoc(t, `f: -// a: frog -// b: dally -// c: log`) - -// path, errPath := treeCreator.ParsePath(".f | .[] == *og ") -// if errPath != nil { -// t.Error(errPath) -// } -// results, errNav := treeNavigator.GetMatchingNodes(nodes, path) - -// if errNav != nil { -// t.Error(errNav) -// } - -// expected := ` -// -- Node -- -// Document 0, path: [f] -// Tag: !!int, Kind: ScalarNode, Anchor: -// 2 -// ` - -// test.AssertResult(t, expected, resultsToString(results)) -// } - -// func TestDataTreeNavigatorCollectWithFilter(t *testing.T) { - -// nodes := readDoc(t, `f: -// a: frog -// b: dally -// c: log`) - -// path, errPath := treeCreator.ParsePath("f(collect(. == *og))") -// if errPath != nil { -// t.Error(errPath) -// } -// results, errNav := treeNavigator.GetMatchingNodes(nodes, path) - -// if errNav != nil { -// t.Error(errNav) -// } - -// expected := ` -// -- Node -- -// Document 0, path: [f] -// Tag: , Kind: SequenceNode, Anchor: -// - frog -// - log -// ` - -// test.AssertResult(t, expected, resultsToString(results)) -// } - -// func TestDataTreeNavigatorCountWithFilter2(t *testing.T) { - -// nodes := readDoc(t, `f: -// a: frog -// b: dally -// c: log`) - -// path, errPath := treeCreator.ParsePath("count(f(. == *og))") -// if errPath != nil { -// t.Error(errPath) -// } -// results, errNav := treeNavigator.GetMatchingNodes(nodes, path) - -// if errNav != nil { -// t.Error(errNav) -// } - -// expected := ` -// -- Node -- -// Document 0, path: [] -// Tag: !!int, Kind: ScalarNode, Anchor: -// 2 -// ` - -// test.AssertResult(t, expected, resultsToString(results)) -// } - -// func TestDataTreeNavigatorCollectWithFilter2(t *testing.T) { - -// nodes := readDoc(t, `f: -// a: frog -// b: dally -// c: log`) - -// path, errPath := treeCreator.ParsePath("collect(f(. == *og))") -// if errPath != nil { -// t.Error(errPath) -// } -// results, errNav := treeNavigator.GetMatchingNodes(nodes, path) - -// if errNav != nil { -// t.Error(errNav) -// } - -// expected := ` -// -- Node -- -// Document 0, path: [] -// Tag: , Kind: SequenceNode, Anchor: -// - frog -// - log -// ` - -// test.AssertResult(t, expected, resultsToString(results)) -// } - -// func TestDataTreeNavigatorCountMultipleMatchesInside(t *testing.T) { - -// nodes := readDoc(t, `f: -// a: [1,2] -// b: dally -// c: [3,4,5]`) - -// path, errPath := treeCreator.ParsePath("f | count(a or c)") -// if errPath != nil { -// t.Error(errPath) -// } -// results, errNav := treeNavigator.GetMatchingNodes(nodes, path) - -// if errNav != nil { -// t.Error(errNav) -// } - -// expected := ` -// -- Node -- -// Document 0, path: [f] -// Tag: !!int, Kind: ScalarNode, Anchor: -// 2 -// ` - -// test.AssertResult(t, expected, resultsToString(results)) -// } - -// func TestDataTreeNavigatorCollectMultipleMatchesInside(t *testing.T) { - -// nodes := readDoc(t, `f: -// a: [1,2] -// b: dally -// c: [3,4,5]`) - -// path, errPath := treeCreator.ParsePath("f | collect(a or c)") -// if errPath != nil { -// t.Error(errPath) -// } -// results, errNav := treeNavigator.GetMatchingNodes(nodes, path) - -// if errNav != nil { -// t.Error(errNav) -// } - -// expected := ` -// -- Node -- -// Document 0, path: [f] -// Tag: , Kind: SequenceNode, Anchor: -// - [1, 2] -// - [3, 4, 5] -// ` - -// test.AssertResult(t, expected, resultsToString(results)) -// } - -// func TestDataTreeNavigatorCountMultipleMatchesInsideSplat(t *testing.T) { - -// nodes := readDoc(t, `f: -// a: [1,2,3] -// b: [1,2,3,4] -// c: [1,2,3,4,5]`) - -// path, errPath := treeCreator.ParsePath("f(count( (a or c)*))") -// if errPath != nil { -// t.Error(errPath) -// } -// results, errNav := treeNavigator.GetMatchingNodes(nodes, path) - -// if errNav != nil { -// t.Error(errNav) -// } - -// expected := ` -// -- Node -- -// Document 0, path: [f] -// Tag: !!int, Kind: ScalarNode, Anchor: -// 8 -// ` - -// test.AssertResult(t, expected, resultsToString(results)) -// } - -// func TestDataTreeNavigatorCountMultipleMatchesOutside(t *testing.T) { - -// nodes := readDoc(t, `f: -// a: [1,2,3] -// b: [1,2,3,4] -// c: [1,2,3,4,5]`) - -// path, errPath := treeCreator.ParsePath("f(a or c)(count(*))") -// if errPath != nil { -// t.Error(errPath) -// } -// results, errNav := treeNavigator.GetMatchingNodes(nodes, path) - -// if errNav != nil { -// t.Error(errNav) -// } - -// expected := ` -// -- Node -- -// Document 0, path: [f a] -// Tag: !!int, Kind: ScalarNode, Anchor: -// 3 -// -- Node -- -// Document 0, path: [f c] -// Tag: !!int, Kind: ScalarNode, Anchor: -// 5 -// ` - -// test.AssertResult(t, expected, resultsToString(results)) -// } - -// func TestDataTreeNavigatorCountOfResults(t *testing.T) { - -// nodes := readDoc(t, `- apple -// - sdfsd -// - apple`) - -// path, errPath := treeCreator.ParsePath("count(*)") -// if errPath != nil { -// t.Error(errPath) -// } -// results, errNav := treeNavigator.GetMatchingNodes(nodes, path) - -// if errNav != nil { -// t.Error(errNav) -// } - -// expected := ` -// -- Node -- -// Document 0, path: [] -// Tag: !!int, Kind: ScalarNode, Anchor: -// 3 -// ` - -// test.AssertResult(t, expected, resultsToString(results)) -// } - -// func TestDataTreeNavigatorCountNoMatches(t *testing.T) { - -// nodes := readDoc(t, `- apple -// - sdfsd -// - apple`) - -// path, errPath := treeCreator.ParsePath("count(5)") -// if errPath != nil { -// t.Error(errPath) -// } -// results, errNav := treeNavigator.GetMatchingNodes(nodes, path) - -// if errNav != nil { -// t.Error(errNav) -// } - -// expected := ` -// -- Node -- -// Document 0, path: [] -// Tag: !!int, Kind: ScalarNode, Anchor: -// 0 -// ` - -// test.AssertResult(t, expected, resultsToString(results)) -// } - -// func TestDataTreeNavigatorDeleteAndWrite(t *testing.T) { - -// nodes := readDoc(t, `a: -// - b: apple -// - b: sdfsd -// - { b: apple, c: cat }`) - -// path, errPath := treeCreator.ParsePath("(a .- (0 or 1)) or (a[0].b := frog)") -// if errPath != nil { -// t.Error(errPath) -// } -// results, errNav := treeNavigator.GetMatchingNodes(nodes, path) - -// if errNav != nil { -// t.Error(errNav) -// } - -// expected := ` -// -- Node -- -// Document 0, path: [a] -// Tag: !!seq, Kind: SequenceNode, Anchor: -// - {b: frog, c: cat} - -// -- Node -- -// Document 0, path: [a 0 b] -// Tag: !!str, Kind: ScalarNode, Anchor: -// frog -// ` - -// test.AssertResult(t, expected, resultsToString(results)) -// } - -// func TestDataTreeNavigatorDeleteArray(t *testing.T) { - -// nodes := readDoc(t, `a: -// - b: apple -// - b: sdfsd -// - b: apple`) - -// path, errPath := treeCreator.ParsePath("a .- (b == a*)") -// if errPath != nil { -// t.Error(errPath) -// } -// results, errNav := treeNavigator.GetMatchingNodes(nodes, path) - -// if errNav != nil { -// t.Error(errNav) -// } - -// expected := ` -// -- Node -- -// Document 0, path: [a] -// Tag: !!seq, Kind: SequenceNode, Anchor: -// - b: sdfsd -// ` - -// test.AssertResult(t, expected, resultsToString(results)) -// } - -// func TestDataTreeNavigatorArraySimple(t *testing.T) { - -// nodes := readDoc(t, `- b: apple`) - -// path, errPath := treeCreator.ParsePath("[0]") -// if errPath != nil { -// t.Error(errPath) -// } -// results, errNav := treeNavigator.GetMatchingNodes(nodes, path) - -// if errNav != nil { -// t.Error(errNav) -// } - -// expected := ` -// -- Node -- -// Document 0, path: [0] -// Tag: !!map, Kind: MappingNode, Anchor: -// b: apple -// ` - -// test.AssertResult(t, expected, resultsToString(results)) -// } - -// func TestDataTreeNavigatorSimpleAssignByFind(t *testing.T) { - -// nodes := readDoc(t, `a: -// b: apple`) - -// path, errPath := treeCreator.ParsePath("a(. == apple) := frog") -// if errPath != nil { -// t.Error(errPath) -// } -// results, errNav := treeNavigator.GetMatchingNodes(nodes, path) - -// if errNav != nil { -// t.Error(errNav) -// } - -// expected := ` -// -- Node -- -// Document 0, path: [a b] -// Tag: !!str, Kind: ScalarNode, Anchor: -// frog -// ` - -// test.AssertResult(t, expected, resultsToString(results)) -// } - -// func TestDataTreeNavigatorOrDeDupes(t *testing.T) { - -// nodes := readDoc(t, `a: -// cat: apple -// mad: things`) - -// path, errPath := treeCreator.ParsePath("a.(cat or cat)") -// if errPath != nil { -// t.Error(errPath) -// } -// results, errNav := treeNavigator.GetMatchingNodes(nodes, path) - -// if errNav != nil { -// t.Error(errNav) -// } - -// expected := ` -// -- Node -- -// Document 0, path: [a cat] -// Tag: !!str, Kind: ScalarNode, Anchor: -// apple -// ` - -// test.AssertResult(t, expected, resultsToString(results)) -// } - -// func TestDataTreeNavigatorAnd(t *testing.T) { - -// nodes := readDoc(t, `a: -// cat: apple -// pat: apple -// cow: apple -// mad: things`) - -// path, errPath := treeCreator.ParsePath("a.(*t and c*)") -// if errPath != nil { -// t.Error(errPath) -// } -// results, errNav := treeNavigator.GetMatchingNodes(nodes, path) - -// if errNav != nil { -// t.Error(errNav) -// } - -// expected := ` -// -- Node -- -// Document 0, path: [a cat] -// Tag: !!str, Kind: ScalarNode, Anchor: -// apple -// ` - -// test.AssertResult(t, expected, resultsToString(results)) -// } diff --git a/pkg/yqlib/lib.go b/pkg/yqlib/lib.go index c8914049..de52cc78 100644 --- a/pkg/yqlib/lib.go +++ b/pkg/yqlib/lib.go @@ -17,8 +17,9 @@ type OperationType struct { } // operators TODO: -// - generator doc from operator tests -// - slurp - stdin, read in sequence, vs read all +// - add print test, particular for streams with multilpe docs +// (one that print doc1, then doc 3) in two calls +// (one that prints doc1, then doc 3) in one call // - write in place // - get path operator (like doc index) // - get file index op (like doc index) diff --git a/pkg/yqlib/operator_collect_object_test.go b/pkg/yqlib/operator_collect_object_test.go index d02b0cf1..d03ede2a 100644 --- a/pkg/yqlib/operator_collect_object_test.go +++ b/pkg/yqlib/operator_collect_object_test.go @@ -46,15 +46,15 @@ var collectObjectOperatorScenarios = []expressionScenario{ }, }, { - description: `Working with multiple documents`, - document: "{name: Mike, pets: [cat, dog]}\n---\n{name: Rosey, pets: [monkey, sheep]}", - expression: `{.name: .pets[]}`, + description: `Working with multiple documents`, + dontFormatInputForDoc: false, + document: "{name: Mike, pets: [cat, dog]}\n---\n{name: Rosey, pets: [monkey, sheep]}", + expression: `{.name: .pets[]}`, expected: []string{ "D0, P[], (!!map)::Mike: cat\n", "D0, P[], (!!map)::Mike: dog\n", - "D1, P[], (!!map)::Rosey: monkey\n", - "D1, P[], (!!map)::Rosey: sheep\n", - "this is producing incorrect formatted yaml", + "D0, P[], (!!map)::Rosey: monkey\n", + "D0, P[], (!!map)::Rosey: sheep\n", }, }, { diff --git a/pkg/yqlib/operator_delete.go b/pkg/yqlib/operator_delete.go index e19d343c..0e01af50 100644 --- a/pkg/yqlib/operator_delete.go +++ b/pkg/yqlib/operator_delete.go @@ -51,7 +51,7 @@ func deleteFromMap(candidate *CandidateNode, nodesToDelete *list.List) { } shouldDelete := false - for el := nodesToDelete.Front(); el != nil && shouldDelete == false; el = el.Next() { + for el := nodesToDelete.Front(); el != nil && !shouldDelete; el = el.Next() { if el.Value.(*CandidateNode).GetKey() == childCandidate.GetKey() { shouldDelete = true } @@ -82,7 +82,7 @@ func deleteFromArray(candidate *CandidateNode, nodesToDelete *list.List) { } shouldDelete := false - for el := nodesToDelete.Front(); el != nil && shouldDelete == false; el = el.Next() { + for el := nodesToDelete.Front(); el != nil && !shouldDelete; el = el.Next() { if el.Value.(*CandidateNode).GetKey() == childCandidate.GetKey() { shouldDelete = true } diff --git a/pkg/yqlib/operators_test.go b/pkg/yqlib/operators_test.go index 625997b8..7d4402b6 100644 --- a/pkg/yqlib/operators_test.go +++ b/pkg/yqlib/operators_test.go @@ -50,6 +50,15 @@ func testScenario(t *testing.T, s *expressionScenario) { test.AssertResultComplexWithContext(t, s.expected, resultsToString(results), fmt.Sprintf("exp: %v\ndoc: %v", s.expression, s.document)) } +func resultsToString(results *list.List) []string { + var pretty []string = make([]string, 0) + for el := results.Front(); el != nil; el = el.Next() { + n := el.Value.(*CandidateNode) + pretty = append(pretty, NodeToString(n)) + } + return pretty +} + func writeOrPanic(w *bufio.Writer, text string) { _, err := w.WriteString(text) if err != nil { diff --git a/pkg/yqlib/printer.go b/pkg/yqlib/printer.go index 89c473dd..2e81c3b8 100644 --- a/pkg/yqlib/printer.go +++ b/pkg/yqlib/printer.go @@ -20,6 +20,7 @@ type resultsPrinter struct { printDocSeparators bool writer io.Writer firstTimePrinting bool + previousDocIndex uint } func NewPrinter(writer io.Writer, outputToJSON bool, unwrapScalar bool, colorsEnabled bool, indent int, printDocSeparators bool) Printer { @@ -53,6 +54,7 @@ func (p *resultsPrinter) writeString(writer io.Writer, txt string) error { } func (p *resultsPrinter) PrintResults(matchingNodes *list.List) error { + log.Debug("PrintResults for %v matches", matchingNodes.Len()) var err error if p.outputToJSON { explodeOp := Operation{OperationType: Explode} @@ -70,13 +72,16 @@ func (p *resultsPrinter) PrintResults(matchingNodes *list.List) error { log.Debug("no matching results, nothing to print") return nil } - - previousDocIndex := matchingNodes.Front().Value.(*CandidateNode).Document + if p.firstTimePrinting { + p.previousDocIndex = matchingNodes.Front().Value.(*CandidateNode).Document + p.firstTimePrinting = false + } for el := matchingNodes.Front(); el != nil; el = el.Next() { mappedDoc := el.Value.(*CandidateNode) - - if (!p.firstTimePrinting || (previousDocIndex != mappedDoc.Document)) && p.printDocSeparators { + log.Debug("-- print sep logic: p.firstTimePrinting: %v, previousDocIndex: %v, mappedDoc.Document: %v, printDocSeparators: %v", p.firstTimePrinting, p.previousDocIndex, mappedDoc.Document, p.printDocSeparators) + if (p.previousDocIndex != mappedDoc.Document) && p.printDocSeparators { + log.Debug("-- writing doc sep") if err := p.writeString(bufferedWriter, "---\n"); err != nil { return err } @@ -87,9 +92,8 @@ func (p *resultsPrinter) PrintResults(matchingNodes *list.List) error { return err } - previousDocIndex = mappedDoc.Document + p.previousDocIndex = mappedDoc.Document } - p.firstTimePrinting = false return nil }