Fixed printer

This commit is contained in:
Mike Farah 2020-11-16 12:09:57 +11:00
parent 79867473d5
commit a57944d123
9 changed files with 96 additions and 699 deletions

View File

@ -14,6 +14,5 @@ var noDocSeparators = false
var nullInput = false
var verbose = false
var version = false
var shellCompletion = ""
// var log = logging.MustGetLogger("yq")

View File

@ -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
}

61
cmd/shell-completion.go Normal file
View File

@ -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
},
}

View File

@ -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))
// }

View File

@ -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)

View File

@ -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",
},
},
{

View File

@ -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
}

View File

@ -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 {

View File

@ -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
}