initiative_core/command/token/
optional.rs

1use crate::app::AppMeta;
2use crate::command::prelude::*;
3use crate::utils::quoted_words;
4
5use std::pin::Pin;
6
7use futures::prelude::*;
8
9pub fn match_input<'a, 'b>(
10    token: &'a Token,
11    input: &'a str,
12    app_meta: &'b AppMeta,
13) -> Pin<Box<dyn Stream<Item = FuzzyMatch<'a>> + 'b>>
14where
15    'a: 'b,
16{
17    let TokenType::Optional(optional_token) = &token.token_type else {
18        unreachable!();
19    };
20
21    Box::pin(
22        stream::iter([if quoted_words(input).next().is_none() {
23            FuzzyMatch::Exact(token.into())
24        } else {
25            FuzzyMatch::Overflow(token.into(), input.into())
26        }])
27        .chain(
28            optional_token
29                .match_input(input, app_meta)
30                .map(|fuzzy_match| {
31                    fuzzy_match.map(|token_match| TokenMatch::new(token, token_match))
32                }),
33        ),
34    )
35}
36
37#[cfg(test)]
38mod test {
39    use super::*;
40
41    use crate::test_utils as test;
42
43    #[derive(Hash)]
44    enum Marker {
45        Optional,
46        Keyword,
47    }
48
49    #[tokio::test]
50    async fn match_input_test_simple() {
51        let keyword_token = keyword_m(Marker::Keyword, "badger");
52        let optional_token = optional_m(Marker::Optional, keyword_token.clone());
53
54        test::assert_eq_unordered!(
55            [
56                FuzzyMatch::Exact(TokenMatch::new(
57                    &optional_token,
58                    TokenMatch::from(&keyword_token)
59                )),
60                FuzzyMatch::Overflow(TokenMatch::from(&optional_token), "badger".into()),
61            ],
62            optional_token
63                .match_input("badger", &test::app_meta())
64                .collect::<Vec<_>>()
65                .await,
66        );
67    }
68
69    #[tokio::test]
70    async fn match_input_test_empty() {
71        let token = optional(keyword("badger"));
72
73        test::assert_eq_unordered!(
74            [FuzzyMatch::Exact(TokenMatch::from(&token))],
75            token
76                .match_input("   ", &test::app_meta())
77                .collect::<Vec<_>>()
78                .await,
79        );
80    }
81}