Skip to content

Commit

Permalink
feat(parser): cover more cases for the command parser
Browse files Browse the repository at this point in the history
  • Loading branch information
0x61nas committed Aug 24, 2023
1 parent 5b054fb commit 1646c14
Showing 1 changed file with 49 additions and 12 deletions.
61 changes: 49 additions & 12 deletions src/helper/docs/cmd_parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::collections::HashMap;
/// Parses a command string into a HashMap that contains the command parts.
///
/// the command string is expected to be in the format:
/// `cmd <subcommand> <args>`
/// `<cmd> [<subcommand>] [<args>]`
/// the subcommand and args are optional.
///
/// # Example
Expand All @@ -24,18 +24,21 @@ use std::collections::HashMap;
/// THIS FUNCTION WILL PANIC IF THE COMMAND STRING IS EMPTY.
pub fn parse_cmd(cmd: &str) -> HashMap<String, String> {
let mut values_map = HashMap::with_capacity(3);
let cmd = cmd.to_string();
if cmd.contains(' ') {
let mut cmd = cmd.split(' ');
values_map.insert("cmd".to_string(), cmd.next().expect("The command should exist").to_string());
if let Some(subcommand) = cmd.next() {
values_map.insert("subcommand".to_string(), subcommand.to_string());
let cmd = cmd.trim().to_string();
let mut iter = cmd.split_whitespace();
// The `cmd` should be the first value.
values_map.insert("cmd".to_string(), iter.next().expect("The command should exist").to_string());
// Parse the rest of the command parts.
for part in iter {
if !part.starts_with('-') && !values_map.contains_key("subcommand") {
values_map.insert("subcommand".to_string(), part.to_string());
} else if !values_map.contains_key("args") {
values_map.insert("args".to_string(), part.to_string());
} else {
// The args already exists, so we append the part to it.
let args = values_map.get_mut("args").expect("Unreachable");
args.push_str(&format!(" {}", part));
}
if let Some(args) = cmd.next() {
values_map.insert("args".to_string(), args.to_string());
}
} else {
values_map.insert("cmd".to_string(), cmd);
}
values_map
}
Expand Down Expand Up @@ -87,4 +90,38 @@ mod tests {
assert!(!values_map.contains_key("subcommand"));
assert!(!values_map.contains_key("args"));
}

#[test]
fn test_parse_cmd_with_args_and_no_subcommand() {
let command = "ps -aux";
let values_map = parse_cmd(command);
assert!(values_map.contains_key("cmd"));
assert_eq!(values_map.get("cmd"), Some(&"ps".to_string()));
assert!(!values_map.contains_key("subcommand"));
assert!(values_map.contains_key("args"));
assert_eq!(values_map.get("args"), Some(&"-aux".to_string()));
}

#[test]
fn test_parse_cmd_with_two_args_and_no_subcommand() {
let command = "ps -aux -l";
let values_map = parse_cmd(command);
assert!(values_map.contains_key("cmd"));
assert_eq!(values_map.get("cmd"), Some(&"ps".to_string()));
assert!(!values_map.contains_key("subcommand"));
assert!(values_map.contains_key("args"));
assert_eq!(values_map.get("args"), Some(&"-aux -l".to_string()));
}

#[test]
fn test_parse_cmd_with_three_args_and_subcommand() {
let command = "git commit -a -m \"commit message\"";
let values_map = parse_cmd(command);
assert!(values_map.contains_key("cmd"));
assert_eq!(values_map.get("cmd"), Some(&"git".to_string()));
assert!(values_map.contains_key("subcommand"));
assert_eq!(values_map.get("subcommand"), Some(&"commit".to_string()));
assert!(values_map.contains_key("args"));
assert_eq!(values_map.get("args"), Some(&"-a -m \"commit message\"".to_string()));
}
}

0 comments on commit 1646c14

Please sign in to comment.