initiative_core/command/token/
any_phrase.rs1use crate::command::prelude::*;
2use crate::utils::quoted_phrases;
3
4use std::pin::Pin;
5
6use async_stream::stream;
7use futures::prelude::*;
8
9pub fn match_input<'a>(
10 token: &'a Token,
11 input: &'a str,
12) -> Pin<Box<dyn Stream<Item = FuzzyMatch<'a>> + 'a>> {
13 assert!(matches!(token.token_type, TokenType::AnyPhrase));
14
15 Box::pin(stream! {
16 let mut phrases = quoted_phrases(input).peekable();
17
18 while let Some(phrase) = phrases.next() {
19 let token_match = TokenMatch::new(token, phrase.as_str());
20
21 if phrases.peek().is_none() {
22 yield FuzzyMatch::Exact(token_match);
23 } else {
24 yield FuzzyMatch::Overflow(token_match, phrase.after());
25 }
26 }
27 })
28}
29
30#[cfg(test)]
31mod test {
32 use super::*;
33
34 use crate::test_utils as test;
35
36 #[derive(Hash)]
37 enum Marker {
38 Token,
39 }
40
41 #[tokio::test]
42 async fn match_input_test_empty() {
43 test::assert_empty!(
44 any_phrase()
45 .match_input(" ", &test::app_meta())
46 .collect::<Vec<_>>()
47 .await,
48 );
49 }
50
51 #[tokio::test]
52 async fn match_input_test_simple() {
53 let token = any_phrase();
54
55 test::assert_eq_unordered!(
56 [
57 FuzzyMatch::Overflow(TokenMatch::new(&token, "badger"), " badger badger".into()),
58 FuzzyMatch::Overflow(TokenMatch::new(&token, "badger badger"), " badger".into()),
59 FuzzyMatch::Exact(TokenMatch::new(&token, "badger badger badger")),
60 ],
61 token
62 .match_input("badger badger badger", &test::app_meta())
63 .collect::<Vec<_>>()
64 .await,
65 );
66 }
67
68 #[tokio::test]
69 async fn match_input_test_quoted() {
70 let token = any_phrase_m(Marker::Token);
71
72 test::assert_eq_unordered!(
73 [
74 FuzzyMatch::Overflow(TokenMatch::new(&token, "Nott"), " \"The Brave\" ".into()),
75 FuzzyMatch::Exact(TokenMatch::new(&token, "Nott \"The Brave\"")),
76 ],
77 token
78 .match_input(" Nott \"The Brave\" ", &test::app_meta())
79 .collect::<Vec<_>>()
80 .await,
81 );
82 }
83}