google / zx

A tool for writing better scripts
https://google.github.io/zx/
Apache License 2.0
42.91k stars 1.09k forks source link

feature request: shorter commands for common patterns #691

Closed Zamiell closed 11 months ago

Zamiell commented 11 months ago

Question 1

I predict that most uses of zx in the wild are people rewriting their Bash scripts into JavaScript/TypeScript. For example, I imagine a common script might look something like this:

await $`npx tsc`;
await $`npx prettier .`;
await $`npx eslint .`;

It strikes me that this could be simplified. zx could automatically await every $ invocation. If it did that, then the code could be simplified to this:

$`npx tsc`;
$`npx prettier .`;
$`npx eslint .`;

Much better! However, I presume the downside to this approach is that we lose the ability to do background tasks. For example, the previous code might want to be written like:

const promises = [];
promises.push($`npx tsc`);
promises.push($`npx prettier .`);
promises.push($`npx eslint .`);
await Promise.all(promises);

So that's a problem. One idea is to parse the command for the & symbol, which would disable the awaiting behavior, like this:

const promises = [];
promises.push($`npx tsc &`);
promises.push($`npx prettier . &`);
promises.push($`npx eslint . &`);
await Promise.all(promises);

I chose the & symbol because that is the background execution operator in bash. In this setup, we get the best of both worlds. Of course, this would be a breaking change and might disrupt the ecosystem. So, another idea is to add an option:

$.alwaysAwait = true;

Yet another idea/approach would be to use a separate symbol other than a dollar sign as an indication of "run a command like $, but always await it automatically". For example:

_`npx tsc`;
_`npx prettier .`;
_`npx eslint .`;

(Underscore and dollar sign are the only symbols that are valid as function names, so here I'll somewhat-arbitrarily choose underscore since dollar sign is taken.)

Question 2

It looks like this is a common pattern:

const foo = $(await $`foo`).toString();
const bar = $(await $`bar`).toString();

It strikes me that this could be abstracted further. Similar to my previous suggestion, it could be possible to add a symbol that is similar to $, but combines the await and toString parts. As an example, I'll arbitrarily choose the o letter, which is short for "output":

const foo = o`foo`;
const bar = o`bar`;

Another option is to use an underscore instead of o. Regardless, this would be a nice abstraction.

antongolub commented 11 months ago

A workaround for annoying await statements:

https://github.com/qiwi/thromise