1use crate::{arguments::Arg, command::RawCommand};
2
3#[derive(Clone, Debug, Eq, PartialEq)]
4pub enum HelpRequest<'a> {
5 All,
7
8 Command(RawCommand<'a>),
11}
12
13impl<'a> HelpRequest<'a> {
14 pub fn from_command(command: &RawCommand<'a>) -> Option<Self> {
16 let mut args = command.args().args();
17 if command.name() == "help" {
18 match args.next() {
19 Some(Ok(Arg::Value(name))) => {
20 let command = RawCommand::new(name, args.into_args());
21 Some(HelpRequest::Command(command))
22 }
23 None => Some(HelpRequest::All),
24 _ => None,
25 }
26 }
27 else if args
29 .any(|arg| arg == Ok(Arg::LongOption("help")) || arg == Ok(Arg::ShortOption('h')))
30 {
31 Some(HelpRequest::Command(command.clone()))
32 } else {
33 None
34 }
35 }
36}
37
38#[cfg(test)]
39mod tests {
40 use rstest::rstest;
41
42 use crate::{arguments::ArgList, command::RawCommand, token::Tokens};
43
44 use super::HelpRequest;
45
46 fn help_command(name: &'static str, args: &'static str) -> HelpRequest<'static> {
47 HelpRequest::Command(RawCommand::new(
48 name,
49 ArgList::new(Tokens::from_raw(args, args.is_empty())),
50 ))
51 }
52
53 #[rstest]
54 #[case("help", HelpRequest::All)]
55 #[case("help cmd1", help_command("cmd1", ""))]
56 #[case("cmd2 --help", help_command("cmd2", "--help"))]
57 #[case(
58 "cmd3 -v --opt --help --some",
59 help_command("cmd3", "-v\0--opt\0--help\0--some")
60 )]
61 #[case("cmd3 -vh --opt --some", help_command("cmd3", "-vh\0--opt\0--some"))]
62 #[case("cmd3 -hv --opt --some", help_command("cmd3", "-hv\0--opt\0--some"))]
63 fn parsing_ok(#[case] input: &str, #[case] expected: HelpRequest<'_>) {
64 let mut input = input.as_bytes().to_vec();
65 let input = core::str::from_utf8_mut(&mut input).unwrap();
66 let tokens = Tokens::new(input);
67 let command = RawCommand::from_tokens(&tokens).unwrap();
68
69 assert_eq!(HelpRequest::from_command(&command), Some(expected));
70 }
71
72 #[rstest]
73 #[case("cmd1")]
74 #[case("cmd1 help")]
75 #[case("--help")]
76 fn parsing_err(#[case] input: &str) {
77 let mut input = input.as_bytes().to_vec();
78 let input = core::str::from_utf8_mut(&mut input).unwrap();
79 let tokens = Tokens::new(input);
80 let command = RawCommand::from_tokens(&tokens).unwrap();
81 let res = HelpRequest::from_command(&command);
82
83 assert!(res.is_none());
84 }
85}