initiative_core/command/token/
or.rs

1use crate::app::AppMeta;
2use crate::command::prelude::*;
3
4use std::pin::Pin;
5
6use async_stream::stream;
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    Box::pin(stream! {
18        let TokenType::Or(tokens) = &token.token_type else {
19            unreachable!();
20        };
21
22        let streams = tokens.iter().map(|token| token.match_input(input, app_meta));
23        for await fuzzy_match in stream::select_all(streams) {
24            yield fuzzy_match.map(|token_match| TokenMatch::new(token, token_match));
25        }
26    })
27}
28
29#[cfg(test)]
30mod test {
31    use super::*;
32
33    use crate::test_utils as test;
34
35    #[derive(Hash)]
36    enum Marker {
37        Or,
38        AnyWord,
39        Keyword,
40    }
41
42    #[tokio::test]
43    async fn match_input_test_simple() {
44        let tokens = [
45            any_word_m(Marker::AnyWord),
46            keyword_m(Marker::Keyword, "badger"),
47        ];
48        let [any_word_token, keyword_token] = tokens.clone();
49        let or_token = or_m(Marker::Or, tokens);
50
51        test::assert_eq_unordered!(
52            [
53                FuzzyMatch::Overflow(
54                    TokenMatch::new(&or_token, TokenMatch::new(&any_word_token, "badger")),
55                    " badger".into(),
56                ),
57                FuzzyMatch::Overflow(
58                    TokenMatch::new(&or_token, TokenMatch::from(&keyword_token)),
59                    " badger".into(),
60                ),
61            ],
62            or_token
63                .match_input("badger badger", &test::app_meta())
64                .collect::<Vec<_>>()
65                .await,
66        );
67    }
68
69    #[tokio::test]
70    async fn match_input_test_partial() {
71        let tokens = [keyword("badger"), keyword("badgering")];
72        let [badger_token, badgering_token] = tokens.clone();
73        let or_token = or(tokens);
74
75        test::assert_eq_unordered!(
76            [
77                FuzzyMatch::Exact(TokenMatch::new(&or_token, TokenMatch::from(&badger_token))),
78                FuzzyMatch::Partial(
79                    TokenMatch::new(&or_token, TokenMatch::from(&badgering_token)),
80                    Some("ing".to_string()),
81                ),
82            ],
83            or_token
84                .match_input("badger", &test::app_meta())
85                .collect::<Vec<_>>()
86                .await,
87        );
88    }
89}