diff --git a/cli/cli.go b/cli/cli.go index e570f074..ab40b4ce 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -237,7 +237,7 @@ Synopsis: } func slurpFile(name string) (interface{}, error) { - iter := newFilesInputIter(newSlurpInputIter(newJSONInputIter), []string{name}) + iter := newSlurpInputIter(newFilesInputIter(newJSONInputIter, []string{name})) defer iter.Close() val, _ := iter.Next() if err, ok := val.(error); ok { @@ -246,15 +246,11 @@ func slurpFile(name string) (interface{}, error) { return val, nil } -func (cli *cli) createInputIter(args []string) inputIter { +func (cli *cli) createInputIter(args []string) (iter inputIter) { var newIter func(io.Reader, string) inputIter switch { case cli.inputRaw: - if cli.inputSlurp { - newIter = newReadAllInputIter - } else { - newIter = newRawInputIter - } + newIter = newRawInputIter case cli.inputStream: newIter = newStreamInputIter case cli.inputYAML: @@ -262,8 +258,14 @@ func (cli *cli) createInputIter(args []string) inputIter { default: newIter = newJSONInputIter } - if cli.inputSlurp && !cli.inputRaw { - newIter = newSlurpInputIter(newIter) + if cli.inputSlurp { + defer func() { + if cli.inputRaw { + iter = newSlurpRawInputIter(iter) + } else { + iter = newSlurpInputIter(iter) + } + }() } if len(args) == 0 { return newIter(cli.inStream, "") diff --git a/cli/inputs.go b/cli/inputs.go index e3d566c2..f4799598 100644 --- a/cli/inputs.go +++ b/cli/inputs.go @@ -5,8 +5,8 @@ import ( "bytes" "encoding/json" "io" - "io/ioutil" "os" + "strings" "gopkg.in/yaml.v3" @@ -156,33 +156,6 @@ func (i *rawInputIter) Close() error { return nil } -type readAllInputIter struct { - r io.Reader - err error -} - -func newReadAllInputIter(r io.Reader, _ string) inputIter { - return &readAllInputIter{r: r} -} - -func (i *readAllInputIter) Next() (interface{}, bool) { - if i.err != nil { - return nil, false - } - bs, err := ioutil.ReadAll(i.r) - if err != nil { - i.err = err - return err, true - } - i.err = io.EOF - return string(bs), true -} - -func (i *readAllInputIter) Close() error { - i.err = io.EOF - return nil -} - type streamInputIter struct { stream *jsonStream buf *bytes.Buffer @@ -260,10 +233,8 @@ type slurpInputIter struct { err error } -func newSlurpInputIter(newIter func(io.Reader, string) inputIter) func(io.Reader, string) inputIter { - return func(r io.Reader, fname string) inputIter { - return &slurpInputIter{iter: newIter(r, fname)} - } +func newSlurpInputIter(iter inputIter) inputIter { + return &slurpInputIter{iter: iter} } func (i *slurpInputIter) Next() (interface{}, bool) { @@ -294,3 +265,42 @@ func (i *slurpInputIter) Close() error { } return nil } + +type slurpRawInputIter struct { + iter inputIter + err error +} + +func newSlurpRawInputIter(iter inputIter) inputIter { + return &slurpRawInputIter{iter: iter} +} + +func (i *slurpRawInputIter) Next() (interface{}, bool) { + if i.err != nil { + return nil, false + } + var s strings.Builder + var v interface{} + var ok bool + for { + v, ok = i.iter.Next() + if !ok { + i.err = io.EOF + return s.String(), true + } + if i.err, ok = v.(error); ok { + return i.err, true + } + s.WriteString(v.(string)) + s.WriteByte('\n') + } +} + +func (i *slurpRawInputIter) Close() error { + if i.iter != nil { + i.iter.Close() + i.iter = nil + i.err = io.EOF + } + return nil +} diff --git a/cli/test.yaml b/cli/test.yaml index a9b973e1..8bf621c5 100644 --- a/cli/test.yaml +++ b/cli/test.yaml @@ -4934,6 +4934,34 @@ expected: | null +- name: slurp option with multiple json files + args: + - -s + - '.' + - testdata/1.json + - testdata/2.json + expected: | + [ + { + "foo": 10 + }, + [ + { + "bar": [] + } + ] + ] + +- name: slurp and raw input option with multiple json files + args: + - -R + - -s + - '.' + - testdata/1.json + - testdata/2.json + expected: | + "{\"foo\":10}\n[{\n\"bar\"\n:\n[]\n}]\n" + - name: stream option args: - -c