Skip to content

Commit

Permalink
Use - to denote reading from stdin
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
squaremo committed Jan 10, 2021
1 parent 45c3d12 commit 117f5ef
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 19 deletions.
19 changes: 10 additions & 9 deletions std/cmd/transform.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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) {
Expand Down
1 change: 1 addition & 0 deletions tests/test-transform-stdin.js.cmd
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
jk transform -c "v => v + 1" --stdin-format=json - ./test-transform-files/*.json
3 changes: 3 additions & 0 deletions tests/test-transform-stdin.js.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
7
2
3
1 change: 1 addition & 0 deletions tests/test-transform-stdin.js.in
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
6
37 changes: 27 additions & 10 deletions transform.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
`

Expand All @@ -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)
}

Expand All @@ -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)
Expand All @@ -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
Expand Down

0 comments on commit 117f5ef

Please sign in to comment.