command_stream/zx/mod.rs
1//! A zx-compatible API (modelled on google/zx 8.x) for writing shell scripts
2//! in Rust.
3//!
4//! The core pieces mirror zx:
5//!
6//! - [`Shell`] is the `$`: a command factory carrying [`Options`] (cwd, env,
7//! shell, prefix, verbose, quiet, nothrow, timeout, ...). The [`zx!`](crate::zx!)
8//! macro interpolates arguments with zx quoting (`$'...'` for bash).
9//! - [`ProcessPromise`] is a configured command; `.await` (or
10//! [`run`](ProcessPromise::run)) yields `Ok(ProcessOutput)` on success and
11//! `Err(ProcessOutput)` on failure unless `nothrow` is set.
12//! - [`ProcessOutput`] holds stdout, stderr, stdall, the exit code, signal and
13//! duration, and formats zx-style error messages.
14//! - [`within`], [`configure`] and [`cd`] provide scoped settings, and the
15//! goods ([`sleep`], [`retry`], [`spinner`], [`tempdir`], [`parse_argv`], ...)
16//! cover the script helpers.
17//!
18//! ```no_run
19//! use command_stream::zx;
20//! use command_stream::zx::Shell;
21//!
22//! # async fn demo() -> Result<(), zx::ProcessOutput> {
23//! let name = "hello world";
24//! let out = zx!("echo {}", name).await?;
25//! assert_eq!(out.stdout, "hello world\n");
26//!
27//! let failed = zx!(Shell::new().nothrow(true), "exit 3").await?;
28//! assert_eq!(failed.exit_code, Some(3));
29//! # Ok(())
30//! # }
31//! ```
32
33pub mod argv;
34pub mod dotenv;
35pub mod error;
36pub mod goods;
37pub mod kill;
38pub mod log;
39pub mod md;
40pub mod output;
41pub mod process;
42pub mod shell;
43pub mod util;
44
45pub use argv::{minimist, parse_argv, ArgvOptions, Booleans};
46pub use error::ZxError;
47pub use goods::{
48 echo, exp_backoff, glob, retry, retry_with_backoff, retry_with_delay, sleep, spinner, tempdir,
49 tempfile, which,
50};
51pub use kill::kill;
52pub use log::{format_cmd, LogEntry, Logger};
53pub use md::transform_markdown;
54pub use output::{ErrorInfo, ProcessOutput};
55pub use process::{PipeFrom, ProcessPromise, RunningProcess, ZxResult};
56pub use shell::{
57 cd, configure, current_options, use_bash, use_powershell, use_pwsh, within, within_sync,
58 Options, PreferLocal, Shell,
59};
60pub use util::{parse_duration, quote, quote_powershell, IntoZxArg, ZxArg};
61
62/// Build a [`ProcessPromise`](crate::zx::ProcessPromise) from a format string
63/// whose `{}` placeholders are replaced by quoted arguments (`{{}}` is a
64/// literal `{}`).
65///
66/// - `zx!("echo {}", arg)` uses [`Shell::new()`](crate::zx::Shell::new), i.e.
67/// the options of the current scope;
68/// - `zx!(shell, "echo {}", arg)` uses the given [`Shell`](crate::zx::Shell).
69///
70/// Arguments may be anything implementing
71/// [`IntoZxArg`](crate::zx::IntoZxArg): strings, numbers, paths, vectors
72/// (expanded into several quoted words) and `ProcessOutput`s (their stdout
73/// without the trailing newline).
74#[macro_export]
75macro_rules! zx {
76 ($fmt:literal $(, $arg:expr)* $(,)?) => {
77 $crate::zx!($crate::zx::Shell::new(), $fmt $(, $arg)*)
78 };
79 ($sh:expr, $fmt:literal $(, $arg:expr)* $(,)?) => {
80 $sh.cmd(
81 &$crate::zx::util::split_template($fmt),
82 &[$($crate::zx::IntoZxArg::into_zx_arg($arg)),*],
83 )
84 };
85}