1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
use std::error::Error;
use serenity::all::{
Context,
Message,
};
/// Pop a whitespace-separated word from the front of the arguments. Supports quotes and quote
/// escaping.
///
/// Leading whitespace will be trimmed; trailing whitespace is not consumed.
// From https://github.com/serenity-rs/poise/blob/current/src/prefix_argument/mod.rs
pub fn pop_string(args: &str) -> Result<(&str, String), poise::TooFewArguments> {
// TODO: consider changing the behavior to parse quotes literally if they're in the middle
// of the string:
// - `"hello world"` => `hello world`
// - `"hello "world"` => `"hello "world`
// - `"hello" world"` => `hello`
let args = args.trim_start();
if args.is_empty() {
return Err(poise::TooFewArguments::default());
}
let mut output = String::new();
let mut inside_string = false;
let mut escaping = false;
let mut chars = args.chars();
// .clone().next() is poor man's .peek(), but we can't do peekable because then we can't
// call as_str on the Chars iterator
while let Some(c) = chars.clone().next() {
if escaping {
output.push(c);
escaping = false;
} else if !inside_string && c.is_whitespace() {
break;
} else if c == '"' {
inside_string = !inside_string;
} else if c == '\\' {
escaping = true;
} else {
output.push(c);
}
chars.next();
}
Ok((chars.as_str(), output))
}
pub struct RestVec(Vec<String>);
impl RestVec {
#[inline]
pub fn into_inner(self) -> Vec<String> {
self.0
}
}
impl From<RestVec> for Vec<String> {
#[inline]
fn from(value: RestVec) -> Self {
value.0
}
}
#[poise::async_trait]
impl<'a> poise::PopArgument<'a> for RestVec {
async fn pop_from(
mut args: &'a str,
attachment_index: usize,
_ctx: &Context,
_msg: &Message,
) -> Result<(&'a str, usize, Self), (Box<dyn Error + Send + Sync>, Option<String>)> {
let mut v = vec![];
while let Ok((remaining, s)) = pop_string(args) {
args = remaining;
v.push(s);
}
Ok(("", attachment_index, Self(v)))
}
}
|