conch_runtime_pshaw/spawn/
for_cmd.rs1use crate::env::{ArgumentsEnvironment, LastStatusEnvironment, VariableEnvironment};
2use crate::eval::WordEval;
3use crate::spawn::{ExitStatus, Spawn};
4use crate::EXIT_SUCCESS;
5use futures_core::future::BoxFuture;
6
7pub async fn for_loop<W, I, S, E>(
12 name: E::VarName,
13 words: I,
14 body: S,
15 env: &mut E,
16) -> Result<BoxFuture<'static, ExitStatus>, S::Error>
17where
18 I: IntoIterator<Item = W>,
19 W: WordEval<E>,
20 S: Spawn<E>,
21 S::Error: From<W::Error>,
22 E: ?Sized + LastStatusEnvironment + VariableEnvironment,
23 E::VarName: Clone,
24 E::Var: From<W::EvalResult>,
25{
26 do_for_loop(name, words.into_iter(), body, env).await
27}
28
29async fn do_for_loop<W, I, S, E>(
30 name: E::VarName,
31 words: I,
32 body: S,
33 env: &mut E,
34) -> Result<BoxFuture<'static, ExitStatus>, S::Error>
35where
36 I: Iterator<Item = W>,
37 W: WordEval<E>,
38 S: Spawn<E>,
39 S::Error: From<W::Error>,
40 E: ?Sized + LastStatusEnvironment + VariableEnvironment,
41 E::VarName: Clone,
42 E::Var: From<W::EvalResult>,
43{
44 let (lo, hi) = words.size_hint();
45 let mut values = Vec::with_capacity(hi.unwrap_or(lo));
46
47 for word in words {
48 let fields = word
49 .eval(env)
50 .await
51 .map_err(S::Error::from)?
52 .await
53 .into_iter()
54 .map(E::Var::from);
55
56 values.extend(fields);
57 }
58
59 do_for_with_args(name, values.into_iter(), body, env).await
60}
61
62pub async fn for_args<S, E>(
67 name: E::VarName,
68 body: S,
69 env: &mut E,
70) -> Result<BoxFuture<'static, ExitStatus>, S::Error>
71where
72 S: Spawn<E>,
73 E: ?Sized + ArgumentsEnvironment + LastStatusEnvironment + VariableEnvironment,
74 E::VarName: Clone,
75 E::Var: From<E::Arg>,
76{
77 let args = env
78 .args()
79 .iter()
80 .cloned()
81 .map(E::Var::from)
82 .collect::<Vec<_>>();
83
84 for_with_args(name, args, body, env).await
85}
86
87pub async fn for_with_args<I, S, E>(
92 name: E::VarName,
93 args: I,
94 body: S,
95 env: &mut E,
96) -> Result<BoxFuture<'static, ExitStatus>, S::Error>
97where
98 I: IntoIterator<Item = E::Var>,
99 S: Spawn<E>,
100 E: ?Sized + LastStatusEnvironment + VariableEnvironment,
101 E::VarName: Clone,
102{
103 do_for_with_args(name, args.into_iter(), body, env).await
104}
105
106async fn do_for_with_args<I, S, E>(
107 name: E::VarName,
108 mut args: I,
109 body: S,
110 env: &mut E,
111) -> Result<BoxFuture<'static, ExitStatus>, S::Error>
112where
113 I: Iterator<Item = E::Var>,
114 S: Spawn<E>,
115 E: ?Sized + LastStatusEnvironment + VariableEnvironment,
116 E::VarName: Clone,
117{
118 let mut cur_arg = match args.next() {
119 Some(a) => a,
120 None => return Ok(Box::pin(async { EXIT_SUCCESS })),
121 };
122
123 for next in args {
124 env.set_var(name.clone(), cur_arg);
125 let status = body.spawn(env).await?.await;
126 env.set_last_status(status);
127 cur_arg = next;
128 }
129
130 env.set_var(name, cur_arg);
131 body.spawn(env).await
132}