Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: update for 0.38 #233

Merged
merged 2 commits into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 86 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Cross platform shell tools for Deno inspired by [zx](https://github.com/google/z
- Makes more code work on Windows.
- Allows exporting the shell's environment to the current process.
- Uses [deno_task_shell](https://github.com/denoland/deno_task_shell)'s parser.
- Has common commands built-in for better Windows support.
1. Minimal globals or global configuration.
- Only a default instance of `$`, but it's not mandatory to use this.
1. No custom CLI.
Expand All @@ -27,8 +28,8 @@ import $ from "https://deno.land/x/dax/mod.ts";
// run a command
await $`echo 5`; // outputs: 5

// more complex example outputting 1 to stdout and 2 to stderr
await $`echo 1 && deno eval 'console.error(2);'`;
// outputting 1 to stdout and running a sub process
await $`echo 1 && deno run main.ts`;

// parallel
await Promise.all([
Expand Down Expand Up @@ -57,8 +58,8 @@ console.log(result.prop); // 5
Get the result of stdout as bytes (makes stdout "quiet"):

```ts
const result = await $`echo 'test'`.bytes();
console.log(result); // Uint8Array(5) [ 116, 101, 115, 116, 10 ]
const bytes = await $`gzip < file.txt`.bytes();
console.log(bytes);
```

Get the result of stdout as a list of lines (makes stdout "quiet"):
Expand Down Expand Up @@ -106,12 +107,31 @@ Piping to a `WritableStream`:
await $`echo 1`.stdout(Deno.stderr.writable, { preventClose: true });
```

Or to a file:
To a file path:

```ts
await $`echo 1`.stdout($.path("data.txt"));
```

To a file:

```ts
using file = $.path("data.txt").openSync({ write: true, create: true });
await $`echo 1`.stdout(file);
```

From one command to another:

```ts
const output = await $`echo foo && echo bar`
.pipe($`grep foo`)
.text();

// or using a pipe sequence
const output = await $`echo foo && echo bar | grep foo`
.text();
```

### Providing arguments to a command

Use an expression in a template literal to provide a single argument to a command:
Expand Down Expand Up @@ -159,6 +179,37 @@ const finalText = await $`echo ${result}`.text();
console.log(finalText); // 1
```

#### JavaScript objects to redirects

You can also provide JavaScript objects to shell output redirects:

```ts
const buffer = new Uint8Array(2);
await $`echo 1 && (echo 2 > ${buffer}) && echo 3`; // 1\n3\n
console.log(buffer); // Uint8Array(2) [ 50, 10 ] (2\n)
```

Supported objects: `Uint8Array`, `PathRef`, `WritableStream`, function that returns a `WritableStream`, any object that implements `[$.symbols.writable](): WritableStream`

Or input redirects:

```ts
// strings
const data = "my data in a string";
const bytes = await $`gzip < ${data}`;

// paths
const path = $.path("file.txt");
const bytes = await $`gzip < ${path}`;

// requests (this example does not make the request until after 5 seconds)
const request = $.request("https://plugins.dprint.dev/info.json")
.showProgress(); // show a progress bar while downloading
const bytes = await $`sleep 5 && gzip < ${request}`.bytes();
```

Supported objects: `string`, `Uint8Array`, `PathRef`, `RequestBuilder`, `ReadableStream`, function that returns a `ReadableStream`, any object that implements `[$.symbols.readable](): ReadableStream`

### Providing stdin

```ts
Expand Down Expand Up @@ -670,6 +721,17 @@ console.log(response.code);
console.log(await response.json());
```

Requests can be piped to commands:

```ts
const request = $.request("https://plugins.dprint.dev/info.json");
await $`deno run main.ts`.stdin(request);

// or as a redirect... this sleeps 5 seconds, then makes
// request and redirects the output to the command
await $`sleep 5 && deno run main.ts < ${request}`;
```

See the [documentation on `RequestBuilder`](https://deno.land/x/dax/src/request.ts?s=RequestBuilder) for more details. It should be as flexible as `fetch`, but uses a builder API (ex. set headers via `.header(...)`).

### Showing progress
Expand Down Expand Up @@ -703,6 +765,25 @@ await $`echo 1 && echo 2`;
await $`echo 1 || echo 2`;
```

Pipe sequences:

```ts
await $`echo 1 | deno run main.ts`;
```

Redirects:

```ts
await $`echo 1 > output.txt`;
const gzippedBytes = await $`gzip < input.txt`.bytes();
```

Sub shells:

```ts
await $`(echo 1 && echo 2) > output.txt`;
```

Setting env var for command in the shell (generally you can just use `.env(...)` though):

```ts
Expand Down
14 changes: 14 additions & 0 deletions mod.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1269,6 +1269,12 @@ Deno.test("input redirects with provided object", async () => {
const output = await $`cat - < ${stream}`.text();
assertEquals(output, text);
}
// string
{
const text = "testing".repeat(1000);
const output = await $`cat - < ${text}`.text();
assertEquals(output, text);
}
// bytes
{
const text = "testing".repeat(1000);
Expand Down Expand Up @@ -1361,6 +1367,14 @@ Deno.test("output redirect with provided object", async () => {
await $`echo 1 > ${() => writableStream}`;
assertEquals(chunks, [new Uint8Array([49, 10])]);
}
{
assertThrows(
() => $`echo 1 > ${"test.txt"}`,
Error,
"Failed resolving expression in command. Cannot provide strings to output " +
"redirects. Did you mean to provide a path instead via the `$.path(...)` API?",
);
}
});

Deno.test("shebang support", async (t) => {
Expand Down
11 changes: 6 additions & 5 deletions mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,15 @@ export type {
*
* Differences:
*
* 1. Minimal globals or global configuration.
* - Only a default instance of `$`, but it's not mandatory to use this.
* 1. No custom CLI.
* 1. Cross platform shell.
* - Makes more code work on Windows.
* - Uses [deno_task_shell](https://github.com/denoland/deno_task_shell)'s parser.
* - Allows exporting the shell's environment to the current process.
* 1. Good for application code in addition to use as a shell script replacement
* - Uses [deno_task_shell](https://github.com/denoland/deno_task_shell)'s parser.
* - Has common commands built-in for better Windows support.
* 1. Minimal globals or global configuration.
* - Only a default instance of `$`, but it's not mandatory to use this.
* 1. No custom CLI.
* 1. Good for application code in addition to use as a shell script replacement.
* 1. Named after my cat.
*
* ## Example
Expand Down
17 changes: 15 additions & 2 deletions src/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1252,8 +1252,17 @@ function templateInner(
const expr = exprs[i];
const inputOrOutputRedirect = detectInputOrOutputRedirect(text);
if (inputOrOutputRedirect === "<") {
if (typeof expr === "string" || expr instanceof PathRef) {
if (expr instanceof PathRef) {
text += templateLiteralExprToString(expr, escape);
} else if (typeof expr === "string") {
handleReadableStream(() =>
new ReadableStream({
start(controller) {
controller.enqueue(new TextEncoder().encode(expr));
controller.close();
},
})
);
} else if (expr instanceof ReadableStream) {
handleReadableStream(() => expr);
} else if (expr?.[symbols.readable]) {
Expand Down Expand Up @@ -1303,7 +1312,7 @@ function templateInner(
throw new Error("Unsupported object provided to input redirect.");
}
} else if (inputOrOutputRedirect === ">") {
if (typeof expr === "string" || expr instanceof PathRef) {
if (expr instanceof PathRef) {
text += templateLiteralExprToString(expr, escape);
} else if (expr instanceof WritableStream) {
handleWritableStream(() => expr);
Expand Down Expand Up @@ -1349,6 +1358,10 @@ function templateInner(
);
}
});
} else if (typeof expr === "string") {
throw new Error(
"Cannot provide strings to output redirects. Did you mean to provide a path instead via the `$.path(...)` API?",
);
} else {
throw new Error("Unsupported object provided to output redirect.");
}
Expand Down
Loading