Skip to main content

pistonite_cu/process/
arg.rs

1use tokio::process::Command as TokioCommand;
2
3#[cfg(feature = "print")]
4use crate::cli::fmt;
5
6/// Add arguments to the command
7#[doc(hidden)]
8pub trait Config {
9    fn configure(self, command: &mut TokioCommand);
10}
11
12#[doc(hidden)]
13pub trait Preset {
14    type Output;
15
16    fn configure<O, E, I>(self, command: crate::Command<O, E, I>) -> Self::Output;
17}
18
19#[doc(hidden)]
20pub struct __ConfigFn<F>(pub F)
21where
22    F: FnOnce(&mut TokioCommand);
23impl<F: FnOnce(&mut TokioCommand)> Config for __ConfigFn<F> {
24    #[inline(always)]
25    fn configure(self, command: &mut TokioCommand) {
26        self.0(command)
27    }
28}
29
30/// Create a config to add multiple args of different types when building
31/// a subprocess.
32///
33/// See [`CommandBuilder`](crate::CommandBuilder) for more info on spawning
34/// child processes.
35///
36/// # Example
37/// ```rust,no_run
38/// # use pistonite_cu as cu;
39/// use std::path::Path;
40/// use cu::pre::*;
41///
42/// # fn main() -> cu::Result<()> {
43/// let path = Path::new("foo");
44/// cu::which("ls")?.command()
45///    // without the macros, you can't mix `&Path` and `&str`
46///    .add(cu::args![path, "-a"])
47///    // ... more config
48/// # ;
49/// # Ok(()) }
50/// ```
51#[macro_export]
52macro_rules! args {
53    ($($arg:expr),* $(,)?) => {
54        $crate::__priv::__ConfigFn(|c| {
55            $( c.arg($arg); )*
56        })
57    };
58}
59
60/// Create a config to add multiple environments of different types when building
61/// a subprocess.
62///
63/// # Example
64/// ```rust,no_run
65/// # use pistonite_cu as cu;
66/// use std::path::Path;
67/// use cu::pre::*;
68///
69/// # fn main() -> cu::Result<()> {
70/// let path = Path::new("bizbar");
71/// cu::which("foo")?.command()
72///    .add(cu::envs!{
73///         "BAR" => "true",
74///         "BIZ" => path
75///    })
76///    // ... more config
77/// # ;
78/// # Ok(()) }
79/// ```
80#[macro_export]
81macro_rules! envs {
82    ($($k:expr => $v:expr),* $(,)?) => {
83        $crate::__priv::__ConfigFn(|c| {
84            $( c.env($k, $v); )*
85        })
86    };
87}
88
89#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
90#[repr(transparent)]
91pub struct ColorFlag(bool);
92impl ColorFlag {
93    #[inline(always)]
94    pub fn use_eq_sign(self) -> bool {
95        self.0
96    }
97}
98impl std::fmt::Display for ColorFlag {
99    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
100        let flag = if crate::lv::color_enabled() {
101            "always"
102        } else {
103            "never"
104        };
105        if self.use_eq_sign() {
106            write!(f, "--color={flag}")
107        } else {
108            write!(f, "--color {flag}")
109        }
110    }
111}
112impl Config for ColorFlag {
113    fn configure(self, command: &mut TokioCommand) {
114        let flag = if crate::lv::color_enabled() {
115            "always"
116        } else {
117            "never"
118        };
119        if self.use_eq_sign() {
120            command.arg(format!("--color={flag}"));
121        } else {
122            command.args(["--color", flag]);
123        }
124    }
125}
126
127/// Create a `--color always|never` flag that can be added to a command,
128/// based on if color is enabled for the current process using
129/// this crate's cli flags
130///
131/// # Example
132/// ```rust,no_run
133/// # use pistonite_cu as cu;
134/// use cu::pre::*;
135///
136/// # fn main() -> cu::Result<()> {
137/// cu::which("git")?
138///   .command()
139///   .add(cu::color_flag());
140///    // ... more config
141/// # ;
142/// # Ok(()) }
143/// ```
144#[inline(always)]
145pub fn color_flag() -> ColorFlag {
146    ColorFlag(false)
147}
148
149/// Create a `--color=always|never` flag that can be added to a command,
150/// based on if color is enabled for the current process using
151/// this crate's cli flags
152///
153/// # Example
154/// ```rust,no_run
155/// # use pistonite_cu as cu;
156/// use cu::pre::*;
157///
158/// # fn main() -> cu::Result<()> {
159/// cu::which("git")?
160///   .command()
161///   .add(cu::color_flag_eq());
162///    // ... more config
163/// # ;
164/// # Ok(()) }
165/// ```
166#[inline(always)]
167pub fn color_flag_eq() -> ColorFlag {
168    ColorFlag(true)
169}
170
171#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
172#[repr(transparent)]
173#[cfg(feature = "print")]
174pub struct WidthFlag(bool);
175#[cfg(feature = "print")]
176impl WidthFlag {
177    #[inline(always)]
178    pub fn use_eq_sign(self) -> bool {
179        self.0
180    }
181}
182#[cfg(feature = "print")]
183impl Config for WidthFlag {
184    fn configure(self, command: &mut TokioCommand) {
185        if let Some(w) = fmt::term_width() {
186            if self.use_eq_sign() {
187                command.arg(format!("--width={w}"));
188            } else {
189                command.arg("--width");
190                command.arg(w.to_string());
191            }
192        }
193    }
194}
195
196/// Create a `--width WIDTH` flag that can be added to a command,
197/// based on the current width of the terminal
198///
199/// # Example
200/// ```rust,no_run
201/// # use pistonite_cu as cu;
202/// use cu::pre::*;
203///
204/// # fn main() -> cu::Result<()> {
205/// cu::which("ls")?
206///   .command()
207///   .add(cu::width_flag());
208///    // ... more config
209/// # ;
210/// # Ok(()) }
211/// ```
212#[inline(always)]
213#[cfg(feature = "print")]
214pub fn width_flag() -> WidthFlag {
215    WidthFlag(false)
216}
217
218/// Create a `--width=WIDTH` flag that can be added to a command,
219/// based on the current width of the terminal
220///
221/// # Example
222/// ```rust,no_run
223/// # use pistonite_cu as cu;
224/// use cu::pre::*;
225///
226/// # fn main() -> cu::Result<()> {
227/// cu::which("ls")?
228///   .command()
229///   .add(cu::width_flag_eq());
230///    // ... more config
231/// # ;
232/// # Ok(()) }
233/// ```
234#[inline(always)]
235#[cfg(feature = "print")]
236pub fn width_flag_eq() -> WidthFlag {
237    WidthFlag(true)
238}