diff --git a/README.md b/README.md index fdfe6bc..9aa1054 100644 --- a/README.md +++ b/README.md @@ -38,8 +38,7 @@ type information and data handling behavior to the runner. #### An Example To get you started, here is a simple example where we pass a `string` to a -process and get back a `Uint8Array`. The group is hidden in the `gzip(...)` -function. +process and get back a `Uint8Array`. ```ts /** @@ -48,18 +47,13 @@ function. * @return The text compressed into bytes. */ async function gzip(text: string): Promise { - const pg = group(); - try { - /* I am using a string for input and a Uint8Array (bytes) for output. */ - const pr: Runner = runner( - stringInput(), - bytesOutput(), - )(pg); - - return await pr.run({ cmd: ["gzip", "-c"] }, text); - } finally { - pg.close(); - } + /* I am using a string for input and a Uint8Array (bytes) for output. */ + const pr: Runner = runner( + stringInput(), + bytesOutput(), + )(); + + return await pr.run({ cmd: ["gzip", "-c"] }, text); } console.dir(await gzip("Hello, world.")); @@ -222,6 +216,10 @@ try { } ``` +If you don't specify a group when running a command, the global group will be +used. This is fine if the processes you run are all "well behaved" and/or if you +are doing a short run of just a few processes. + ## Performance Considerations In general, `Uint8Array`s are faster than `string`s. This is because processes diff --git a/examples/warandpeace/countwords.ts b/examples/warandpeace/countwords.ts index 391cdeb..3a9ebc4 100755 --- a/examples/warandpeace/countwords.ts +++ b/examples/warandpeace/countwords.ts @@ -12,7 +12,6 @@ import * as proc from "../../mod.ts"; * (the lowercase conversion). */ -const pg = proc.group(); try { /* * `stdin` will be from a gzipped text file. So the first thing we need to do is @@ -24,7 +23,7 @@ try { const uncompressedDoc = proc.runner( proc.readerInput(), proc.bytesIterableOutput(), - )(pg).run( + )().run( { cmd: ["gunzip"], }, @@ -37,7 +36,7 @@ try { const rawWords = proc.runner( proc.bytesIterableInput(), proc.bytesIterableOutput(), - )(pg).run( + )().run( { cmd: ["grep", "-o", "-E", "(\\w|')+"], }, @@ -50,7 +49,7 @@ try { const nonNumericWords = proc.runner( proc.bytesIterableInput(), proc.stringIterableOutput(), - )(pg).run( + )().run( { cmd: ["grep", "-v", "-P", "^\\d"], }, @@ -75,7 +74,7 @@ try { const sortedWords = proc.runner( proc.stringIterableInput(), proc.bytesIterableOutput(), - )(pg).run( + )().run( { cmd: ["sort"] }, lowercaseWords, ); @@ -86,7 +85,7 @@ try { const uniqWords = proc.runner( proc.bytesIterableInput(), proc.bytesIterableOutput(), - )(pg).run( + )().run( { cmd: ["uniq"] }, sortedWords, ); @@ -96,7 +95,7 @@ try { * The first line of output is the count from `wc`. I grab this line and convert it to integer. */ const countOfWords = parseInt( - (await proc.runner(proc.bytesIterableInput(), proc.stringArrayOutput())(pg) + (await proc.runner(proc.bytesIterableInput(), proc.stringArrayOutput())() .run( { cmd: ["wc", "-l"] }, uniqWords, @@ -108,6 +107,4 @@ try { } catch (e) { console.dir(e); Deno.exit(1); -} finally { - pg.close(); } diff --git a/examples/warandpeace/countwords2.ts b/examples/warandpeace/countwords2.ts index 0dbf05f..392ba2c 100755 --- a/examples/warandpeace/countwords2.ts +++ b/examples/warandpeace/countwords2.ts @@ -17,7 +17,6 @@ proc.enableChaining(true); * as fast as the pure shell version. */ -const pg = proc.group(); try { /* * Bash squashes errors that occur in pipes. I really want to trap an error that @@ -29,12 +28,12 @@ try { const uncompressedText = proc.runner( proc.readerInput(), proc.bytesIterableOutput(proc.stderrLinesToErrorMessage(20)), - )(pg).run({ cmd: ["gunzip"] }, Deno.stdin); + )().run({ cmd: ["gunzip"] }, Deno.stdin); const nonNumericWords = proc.runner( proc.bytesIterableInput(), proc.stringIterableOutput(), - )(pg).run( + )().run( { cmd: [ "bash", @@ -57,7 +56,7 @@ try { await proc.runner( proc.stringIterableInput(), proc.stringArrayOutput(), - )(pg).run( + )().run( { cmd: [ "bash", @@ -75,6 +74,4 @@ try { } catch (e) { console.dir(e); Deno.exit(1); -} finally { - pg.close(); } diff --git a/examples/warandpeace/countwords3.ts b/examples/warandpeace/countwords3.ts index 13a296c..868edb0 100755 --- a/examples/warandpeace/countwords3.ts +++ b/examples/warandpeace/countwords3.ts @@ -6,14 +6,13 @@ import * as proc from "../../mod.ts"; * This is a rewrite of the first example, but using non-streaming mode, just for fun. */ -const pg = proc.group(); try { console.error(`${new Date()} Starting.`); const uncompressedDoc = await proc.runner( proc.readerInput(), proc.stringOutput(), - )(pg).run( + )().run( { cmd: ["gunzip"], }, @@ -27,7 +26,7 @@ try { const rawWords = await proc.runner( proc.stringInput(), proc.stringArrayOutput(), - )(pg).run( + )().run( { cmd: ["grep", "-o", "-E", "(\\w|')+"], }, @@ -41,7 +40,7 @@ try { const nonNumericWords = await proc.runner( proc.stringArrayInput(), proc.stringArrayOutput(), - )(pg).run( + )().run( { cmd: ["grep", "-v", "-P", "^\\d"], }, @@ -59,7 +58,7 @@ try { const sortedWords = await proc.runner( proc.stringArrayInput(), proc.stringArrayOutput(), - )(pg).run( + )().run( { cmd: ["sort"] }, lowercaseWords, ); @@ -69,7 +68,7 @@ try { const uniqWords = await proc.runner( proc.stringArrayInput(), proc.stringArrayOutput(), - )(pg).run( + )().run( { cmd: ["uniq"] }, sortedWords, ); @@ -79,7 +78,7 @@ try { ); const countOfWords = parseInt( - (await proc.runner(proc.stringArrayInput(), proc.stringArrayOutput())(pg) + (await proc.runner(proc.stringArrayInput(), proc.stringArrayOutput())() .run( { cmd: ["wc", "-l"] }, uniqWords, @@ -92,6 +91,4 @@ try { } catch (e) { console.dir(e); Deno.exit(1); -} finally { - pg.close(); } diff --git a/examples/warandpeace/read.ts b/examples/warandpeace/read.ts index 39ef316..916ae30 100755 --- a/examples/warandpeace/read.ts +++ b/examples/warandpeace/read.ts @@ -2,22 +2,17 @@ import * as proc from "../../mod.ts"; -const pg = proc.group(); -try { - for await (const text of proc.toLines(proc.readerToBytes(Deno.stdin))) { - if (text.trim().length > 0) { - console.log(); - console.log( - await proc.runner(proc.stringInput(), proc.stringOutput())(pg).run({ - cmd: ["fmt", "-w", "80"], - }, text.trim()), - ); - await proc.simpleRunner(pg).run({ - cmd: ["spd-say", "-w", "-t", "female3", text.trim()], - }); - } - await proc.sleep(500); +for await (const text of proc.toLines(proc.readerToBytes(Deno.stdin))) { + if (text.trim().length > 0) { + console.log(); + console.log( + await proc.runner(proc.stringInput(), proc.stringOutput())().run({ + cmd: ["fmt", "-w", "80"], + }, text.trim()), + ); + await proc.simpleRunner().run({ + cmd: ["spd-say", "-w", "-t", "female3", text.trim()], + }); } -} finally { - pg.close(); + await proc.sleep(500); } diff --git a/release-notes.md b/release-notes.md index d984cfd..638adb2 100644 --- a/release-notes.md +++ b/release-notes.md @@ -3,6 +3,8 @@ ## 0.13.0 - `#15` **feature** Added `simpleRunner`. +- `#21` **feature** Supports a global process group by default; allows omitting + group create/close boilerplate in most cases. ## 0.12.2 diff --git a/runner.ts b/runner.ts index 7985c41..f7162b1 100644 --- a/runner.ts +++ b/runner.ts @@ -2,11 +2,14 @@ import { RunnerImpl } from "./runner-impl.ts"; import { emptyInput, emptyOutput } from "./runners/handlers/empty.ts"; import { Group, + group, InputHandler, OutputHandler, RunOptions, } from "./runners/proc-group.ts"; +const globalGroup = group(); + /** Something that is either a promise or an iterable. */ export type PromiseOrIterable = B extends AsyncIterable ? B : Promise; @@ -32,8 +35,8 @@ export interface Runner { export function runner( input: InputHandler, output: OutputHandler, -): (group: Group) => Runner { - return (group: Group) => new RunnerImpl(group, input, output); +): (group?: Group) => Runner { + return (group?: Group) => new RunnerImpl(group || globalGroup, input, output); } /** @@ -41,6 +44,6 @@ export function runner( * Note that `stdout` is treated is assumed to be text and not byte data. * @returns A process runner. */ -export function simpleRunner(group: Group): Runner { - return new RunnerImpl(group, emptyInput(), emptyOutput()); +export function simpleRunner(group?: Group): Runner { + return new RunnerImpl(group || globalGroup, emptyInput(), emptyOutput()); }