conch_runtime_pshaw/spawn/
case.rs1use crate::env::{LastStatusEnvironment, ReportErrorEnvironment, StringWrapper};
2use crate::error::IsFatalError;
3use crate::eval::{eval_as_pattern, TildeExpansion, WordEval, WordEvalConfig};
4use crate::spawn::ExitStatus;
5use crate::{Spawn, EXIT_ERROR, EXIT_SUCCESS};
6use futures_core::future::BoxFuture;
7use glob::MatchOptions;
8
9#[derive(Debug, PartialEq, Eq, Clone)]
11pub struct PatternBodyPair<W, C> {
12 pub patterns: W,
14 pub body: C,
16}
17
18pub async fn case<'a, I, W, P, S, E>(
26 word: W,
27 arms: I,
28 env: &mut E,
29) -> Result<BoxFuture<'static, ExitStatus>, S::Error>
30where
31 I: Iterator<Item = PatternBodyPair<&'a [P], S>>,
32 W: WordEval<E>,
33 P: 'a + WordEval<E>,
34 P::Error: IsFatalError,
35 S: Spawn<E>,
36 S::Error: From<W::Error> + From<P::Error>,
37 E: ?Sized + LastStatusEnvironment + ReportErrorEnvironment,
38{
39 let cfg = WordEvalConfig {
40 tilde_expansion: TildeExpansion::First,
41 split_fields_further: false,
42 };
43
44 let match_opts = MatchOptions {
45 case_sensitive: true,
46 require_literal_separator: false,
47 require_literal_leading_dot: false,
48 };
49
50 let word = match word.eval_with_config(env, cfg).await {
51 Ok(w) => w.await.join().into_owned(),
52 Err(e) => {
53 env.set_last_status(EXIT_ERROR);
54 return Err(S::Error::from(e));
55 }
56 };
57
58 for arm in arms {
59 for pat in arm.patterns {
60 let pat = match eval_as_pattern(pat, env).await {
61 Ok(pat) => pat,
62 Err(e) => {
63 if e.is_fatal() {
64 return Err(S::Error::from(e));
65 } else {
66 env.report_error(&e).await;
67 continue;
68 }
69 }
70 };
71
72 if pat.matches_with(&word, match_opts) {
73 return arm.body.spawn(env).await;
74 }
75 }
76 }
77
78 Ok(Box::pin(async { EXIT_SUCCESS }))
79}