use crate::{
commands::{clear, drop, list, record, run, RunnableCommand},
errors::ReplayResult,
};
use clap::{Parser, Subcommand};
#[derive(Parser)]
#[command(version, about, long_about = None)]
pub struct CliParser {
#[command(subcommand)]
pub command: CliCommand,
}
#[derive(Subcommand, PartialEq, Eq, Debug)]
pub enum CliCommand {
Run(run::RunCommand),
Record(record::RecordCommand),
List(list::ListCommand),
Drop(drop::DropCommand),
Clear(clear::ClearCommand),
}
impl CliCommand {
pub fn run(&self) -> ReplayResult<()> {
match self {
CliCommand::Run(cmd) => cmd.run(),
CliCommand::Record(cmd) => cmd.run(),
CliCommand::List(cmd) => cmd.run(),
CliCommand::Drop(cmd) => cmd.run(),
CliCommand::Clear(cmd) => cmd.run(),
}
}
}
pub fn parse_command(args: &[String]) -> ReplayResult<CliCommand> {
let cli_command = CliParser::try_parse_from(args)?;
Ok(cli_command.command)
}
pub fn parse_session_index(s: &str) -> Result<u32, String> {
s.strip_prefix("replay@{")
.and_then(|rest| rest.strip_suffix('}'))
.ok_or_else(|| {
format!(
"Session name must be of the form replay@{{index}}, got '{}'",
s
)
})?
.parse::<u32>()
.map_err(|_| format!("Invalid session index in '{}'", s))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::errors::ReplayError;
#[test]
fn test_valid_record_command() {
let args = [
String::from("replay"),
String::from("record"),
String::from("\"test_valid_record_command\""),
];
let expected_command = CliCommand::Record(record::RecordCommand::new(
Some(String::from("\"test_valid_record_command\"")),
false,
));
assert_eq!(expected_command, parse_command(&args).unwrap())
}
#[test]
fn test_valid_run_command() {
let args = [
String::from("replay"),
String::from("run"),
String::from("replay@{0}"),
String::from("--show"),
String::from("--delay"),
String::from("10"),
];
let expected_command = CliCommand::Run(run::RunCommand::new(0, true, 10));
assert_eq!(expected_command, parse_command(&args).unwrap());
}
#[test]
fn test_invalid_run_command() {
let args = [
String::from("replay"),
String::from("run"),
String::from("invalid_session_name"),
String::from("--show"),
String::from("--delay"),
String::from("10"),
];
let res = parse_command(&args);
assert!(matches!(res, Err(ReplayError::ClapError(_))));
let args = [
String::from("replay"),
String::from("run"),
String::from("replay@{0}"),
String::from("--show"),
String::from("--delay"),
String::from("a"),
];
let res = parse_command(&args);
assert!(matches!(res, Err(ReplayError::ClapError(_))));
let args = [
String::from("replay"),
String::from("run"),
String::from("replay@{0}"),
String::from("--show"),
String::from("--delay"),
String::from("1"),
];
let res = parse_command(&args);
assert!(matches!(res, Err(ReplayError::ClapError(_))));
}
#[test]
fn test_invalid_record_command() {
let args = [
String::from("replay"),
String::from("record"),
String::from("to short"),
];
let res = parse_command(&args);
assert!(matches!(res, Err(ReplayError::ClapError(_))));
let args = [
String::from("replay"),
String::from("record"),
String::from(
"this session description is way too long and exceeds the maximum length of eighty characters",
),
];
let res = parse_command(&args);
assert!(matches!(res, Err(ReplayError::ClapError(_))));
let args = [
String::from("replay"),
String::from("record"),
String::from("1234567890"),
];
let res = parse_command(&args);
assert!(matches!(res, Err(ReplayError::ClapError(_))));
}
#[test]
fn test_invalid_command() {
let args = [
String::from("replay"),
String::from("invalid"), ];
let res = parse_command(&args);
assert!(matches!(res, Err(ReplayError::ClapError(_))));
}
}