diff --git a/docs/cli.md b/docs/cli.md index 27c3259b5d..1c00b717b2 100644 --- a/docs/cli.md +++ b/docs/cli.md @@ -44,6 +44,9 @@ Evaluate the following argument as a script. cat package.json | zx --eval 'const v = JSON.parse(await stdin()).version; echo(v)' ``` +## --repl +Starts zx in [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop) mode. + ## --install ```js @@ -67,6 +70,14 @@ the import. import sh from 'tinysh' // @^1 ``` +## --registry + +By default, `zx` uses `https://registry.npmjs.org` as a registry. Customize if needed. + +```bash +zx --registry=https://registry.yarnpkg.com script.mjs +``` + ## --quiet Suppress any outputs. @@ -83,6 +94,14 @@ Specify a custom shell binary. zx --shell=/bin/bash script.mjs ``` +## --prefer-local, -l + +Prefer locally installed packages bins. + +```bash +zx --shell=/bin/bash script.mjs +``` + ## --prefix & --postfix Attach a command to the beginning or the end of every command. @@ -99,13 +118,33 @@ Set the current working directory. zx --cwd=/foo/bar script.mjs ``` -## --version +## --ext + +Override the default (temp) script extension. Default is `.mjs`. + +## --version, -v + +Print the current `zx` version. -Print the current version of `zx`. +## --help, -h -## --help +Print help notes. -Print help. +## Environment variables +All the previously mentioned options can be set via the corresponding `ZX_`-prefixed environment variables. + +```bash +ZX_VERBOSE=true ZX_SHELL='/bin/bash' zx script.mjs +``` + +```yaml +steps: + - name: Run script + run: zx script.mjs + env: + ZX_VERBOSE: true + ZX_SHELL: '/bin/bash' +``` ## __filename & __dirname diff --git a/docs/process-promise.md b/docs/process-promise.md index bf68383daa..a709c8eb7d 100644 --- a/docs/process-promise.md +++ b/docs/process-promise.md @@ -61,7 +61,7 @@ await $`echo '{"foo": "bar"}'`.json() // {foo: 'bar'} ## `pipe()` -Redirects the stdout of the process. +Redirects the output of the process. ```js await $`echo "Hello, stdout!"` @@ -70,6 +70,7 @@ await $`echo "Hello, stdout!"` await $`cat /tmp/output.txt` ``` +`pipe()` accepts any kind `Writable`, `ProcessPromise` or a file path. You can pass a string to `pipe()` to implicitly create a receiving file. The previous example is equivalent to: ```js @@ -77,6 +78,15 @@ await $`echo "Hello, stdout!"` .pipe('/tmp/output.txt') ``` +Chained streams becomes _thenables_, so you can `await` them: + +```js +const p = $`echo "hello"` + .pipe(getUpperCaseTransform()) + .pipe(fs.createWriteStream(tempfile())) // <- stream +const o = await p +``` + Pipes can be used to show a real-time output of the process: ```js @@ -84,6 +94,19 @@ await $`echo 1; sleep 1; echo 2; sleep 1; echo 3;` .pipe(process.stdout) ``` +And the time machine is in stock! You can pipe the process at any phase: on start, in the middle, or even after the end. All chunks will be buffered and processed in the right order. + +```js +const result = $`echo 1; sleep 1; echo 2; sleep 1; echo 3` +const piped1 = result.pipe`cat` +let piped2 + +setTimeout(() => { piped2 = result.pipe`cat` }, 1500) + +(await piped1).toString() // '1\n2\n3\n' +(await piped2).toString() // '1\n2\n3\n' +``` + The `pipe()` method can combine `$` processes. Same as `|` in bash: ```js @@ -102,6 +125,64 @@ await $`find ./examples -type f -print0` .pipe($`wc -l`) ``` +And literals! Pipe does support them too: + +```js +await $`printf "hello"` + .pipe`awk '{printf $1", world!"}'` + .pipe`tr '[a-z]' '[A-Z]'` +``` + +By default, `pipe()` API operates with `stdout` stream, but you can specify `stderr` as well: + +```js +const p = $`echo foo >&2; echo bar` +const o1 = (await p.pipe.stderr`cat`).toString() // 'foo\n' +const o2 = (await p.pipe.stdout`cat`).toString() // 'bar\n' +``` + +Btw, the signal, if specified, will be transmitted through pipeline. + +```js +const ac = new AbortController() +const { signal } = ac +const p = $({ signal, nothrow: true })`echo test`.pipe`sleep 999` +setTimeout(() => ac.abort(), 50) + +try { + await p +} catch ({ message }) { + message // The operation was aborted +} +``` + +In short, combine anything you want: + +```js +const getUpperCaseTransform = () => new Transform({ + transform(chunk, encoding, callback) { + callback(null, String(chunk).toUpperCase()) + }, +}) + +// $ > stream (promisified) > $ +const o1 = await $`echo "hello"` + .pipe(getUpperCaseTransform()) + .pipe($`cat`) + +o1.stdout // 'HELLO\n' + +// stream > $ +const file = tempfile() +await fs.writeFile(file, 'test') +const o2 = await fs + .createReadStream(file) + .pipe(getUpperCaseTransform()) + .pipe($`cat`) + +o2.stdout // 'TEST' +``` + ## `kill()` Kills the process and all children.