1use alloc::boxed::Box;
2use alloc::string::String;
3use alloc::vec::Vec;
4use core::fmt;
5
6use crate::Result;
7use crate::io::{BoxFuture, Io};
8
9#[derive(Clone, Copy)]
12pub struct Args<'a> {
13 parts: &'a [String],
14}
15
16impl<'a> Args<'a> {
17 pub(crate) fn new(parts: &'a [String]) -> Self {
18 Args { parts }
19 }
20
21 pub fn len(&self) -> usize {
23 self.parts.len()
24 }
25
26 pub fn is_empty(&self) -> bool {
28 self.parts.is_empty()
29 }
30
31 pub fn get(&self, i: usize) -> Option<&str> {
33 self.parts.get(i).map(|s| s.as_str())
34 }
35
36 pub fn iter(&self) -> impl Iterator<Item = &str> {
38 self.parts.iter().map(|s| s.as_str())
39 }
40
41 pub fn rest(&self) -> String {
44 let mut out = String::new();
45 for (i, part) in self.parts.iter().enumerate() {
46 if i > 0 {
47 out.push(' ');
48 }
49 out.push_str(part);
50 }
51 out
52 }
53}
54
55impl fmt::Debug for Args<'_> {
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57 f.debug_list().entries(self.parts).finish()
58 }
59}
60
61pub(crate) type Handler<'a> =
63 Box<dyn for<'x> Fn(Args<'x>, Io<'x>) -> BoxFuture<'x, Result<()>> + 'a>;
64
65pub(crate) type Completer<'a> = Box<dyn Fn(usize, &str) -> Vec<String> + 'a>;
69
70pub(crate) enum CompleterKind<'a> {
74 Options(&'static [&'static str]),
75 Custom(Completer<'a>),
76}
77
78pub(crate) struct Command<'a> {
79 pub name: String,
80 pub help: &'static str,
81 pub handler: Handler<'a>,
82 pub completer: Option<CompleterKind<'a>>,
83}