From 117f5ef5f625729e9d3b161e2810f10a74a6c2ee Mon Sep 17 00:00:00 2001 From: Michael Bridgen Date: Wed, 3 Jun 2020 09:15:27 +0100 Subject: [PATCH] Use `-` to denote reading from stdin Instead of taking --stdin-format to imply reading from stdin, use the convention of supplying `-` as an argument to denote reading from stdin, and just use the flag to alter how it's read. This will line up better with expectations; and, since --stdin-format can have a default (of "yaml"), invocations can be concise: jk transform ./script.js - .. rather than jk transform ./script.js --stdin-format=yaml Note that _no_ arguments does not imply reading from stdin. I did not want something that accidentally supplies no filenames to block, since that would make automation using `jk transform` brittle. --- std/cmd/transform.ts | 19 ++++++------- tests/test-transform-stdin.js.cmd | 1 + tests/test-transform-stdin.js.expected | 3 +++ tests/test-transform-stdin.js.in | 1 + transform.go | 37 +++++++++++++++++++------- 5 files changed, 42 insertions(+), 19 deletions(-) create mode 100644 tests/test-transform-stdin.js.cmd create mode 100644 tests/test-transform-stdin.js.expected create mode 100644 tests/test-transform-stdin.js.in diff --git a/std/cmd/transform.ts b/std/cmd/transform.ts index 0fa4180..274c64e 100644 --- a/std/cmd/transform.ts +++ b/std/cmd/transform.ts @@ -1,4 +1,4 @@ -import { Format, Overwrite, read, stdin } from '../index'; +import { Format, Overwrite, read, stdin, print } from '../index'; import * as host from '@jkcfg/std/internal/host'; // magic module import * as param from '../param'; import { generate, File, GenerateParams, maybeSetFormat } from './generate'; @@ -29,15 +29,16 @@ function transform(fn: TransformFn): void { const inputFiles = param.Object('jk.transform.input', {}); const outputs = []; - const stdinFormat = param.String('jk.transform.stdin.format', ''); - if (stdinFormat !== '') { - const format = valuesFormatFromExtension(stdinFormat); - const path = `stdin.${stdinFormat}`; // path is a stand-in - const value = read(stdin, { format }).then(v => v.map(transformOne)); - outputs.push({ path, value, format }); - } - for (const path of Object.keys(inputFiles)) { + if (path === '') { // read from stdin + const stdinFormat = param.String('jk.transform.stdin.format', 'yaml'); + const format = valuesFormatFromExtension(stdinFormat); + const path = `stdin.${stdinFormat}`; // path is a stand-in + const value = read(stdin, { format }).then(v => v.map(transformOne)); + outputs.push({ path, value, format }); + continue; + } + const format = valuesFormatFromPath(path); outputs.push(host.read(path, { format }).then((obj): File => { switch (format) { diff --git a/tests/test-transform-stdin.js.cmd b/tests/test-transform-stdin.js.cmd new file mode 100644 index 0000000..306cdcd --- /dev/null +++ b/tests/test-transform-stdin.js.cmd @@ -0,0 +1 @@ +jk transform -c "v => v + 1" --stdin-format=json - ./test-transform-files/*.json diff --git a/tests/test-transform-stdin.js.expected b/tests/test-transform-stdin.js.expected new file mode 100644 index 0000000..687d1fc --- /dev/null +++ b/tests/test-transform-stdin.js.expected @@ -0,0 +1,3 @@ +7 +2 +3 diff --git a/tests/test-transform-stdin.js.in b/tests/test-transform-stdin.js.in new file mode 100644 index 0000000..1e8b314 --- /dev/null +++ b/tests/test-transform-stdin.js.in @@ -0,0 +1 @@ +6 diff --git a/transform.go b/transform.go index c0ffd89..d8644d8 100644 --- a/transform.go +++ b/transform.go @@ -18,9 +18,19 @@ var transformCmd = &cobra.Command{ } const transformExamples = ` - running the default export of a module (or file) on each input document + + run the default export of script.js on each YAML value read from + stdin, printing the transformed values to stdout + + jk transform ./script.js - + + run the default export of a module (or file) on each input document, + and write the results back to outputdir/ + jk transform -o outputdir/ ./script.js ./inputdir/*.json - running a function on each input, and printing the results to stdout + + run a function on each input file, and print the results to stdout + jk transform --stdout -c '({ name: n, ...fields }) => ({ name: n + "-dev", ...fields })' inputdir/*.yaml ` @@ -33,17 +43,18 @@ var transformOptions struct { overwrite bool // force the format of the output format string - // read from stdin, expecting a stream of values in the format given + // when reading from stdin (`-` is supplied as an argument), + // expect a stream of values in the format given stdinFormat string } func init() { initScriptFlags(transformCmd, &transformOptions.scriptOptions) initExecFlags(transformCmd, &transformOptions.vmOptions) - transformCmd.PersistentFlags().BoolVar(&transformOptions.stdout, "stdout", false, "print the resulting values to stdout") + transformCmd.PersistentFlags().BoolVar(&transformOptions.stdout, "stdout", false, "print the resulting values to stdout (implied if reading from stdin)") transformCmd.PersistentFlags().BoolVar(&transformOptions.overwrite, "overwrite", false, "allow input file(s) to be overwritten by output file(s); otherwise, an error will be thrown") - transformCmd.PersistentFlags().StringVar(&transformOptions.format, "format", "", "force all values to this format") - transformCmd.PersistentFlags().StringVar(&transformOptions.stdinFormat, "stdin-format", "", "read values from stdin, assuming this format; implies --stdout") + transformCmd.PersistentFlags().StringVar(&transformOptions.format, "format", "", "force all output values to this format") + transformCmd.PersistentFlags().StringVar(&transformOptions.stdinFormat, "stdin-format", "yaml", "assume this format for values from stdin (either a 'yaml' stream or concatenated 'json' values)") jk.AddCommand(transformCmd) } @@ -64,11 +75,18 @@ func transform(cmd *cobra.Command, args []string) { // now). This is in part to get around the limitations of // parameters (arrays are not supported as values), and partly in // anticipation of there being more information to pass about each - // input. + // input. Stdin is encoded as an empty string, since `"-"` could + // be the name of a file. inputs := make(map[string]interface{}) for _, f := range args[1:] { - inputs[f] = f + if f == "-" { + inputs[""] = "" + transformOptions.stdout = true + } else { + inputs[f] = f + } } + vm.parameters.Set("jk.transform.input", inputs) vm.parameters.Set("jk.transform.stdout", transformOptions.stdout) vm.parameters.Set("jk.transform.overwrite", transformOptions.overwrite) @@ -77,9 +95,8 @@ func transform(cmd *cobra.Command, args []string) { switch transformOptions.stdinFormat { case "json", "yaml": vm.parameters.Set("jk.transform.stdin.format", transformOptions.stdinFormat) - vm.parameters.Set("jk.transform.stdout", true) default: - break + log.Fatal("--stdin-format must be 'json' or 'yaml'") } var module string