#![allow(clippy::needless_borrows_for_generic_args)]
use crate::cli::InputPathHandler;
use crate::error::SubXError;
use clap::{Args, ValueEnum};
use std::path::PathBuf;
#[derive(Args, Debug)]
pub struct ConvertArgs {
pub input: Option<PathBuf>,
#[arg(short = 'i', long = "input", value_name = "PATH")]
pub input_paths: Vec<PathBuf>,
#[arg(short, long)]
pub recursive: bool,
#[arg(long, value_enum)]
pub format: Option<OutputSubtitleFormat>,
#[arg(short, long)]
pub output: Option<PathBuf>,
#[arg(long)]
pub keep_original: bool,
#[arg(long, default_value = "utf-8")]
pub encoding: String,
#[arg(long, default_value_t = false)]
pub no_extract: bool,
}
impl ConvertArgs {
pub fn get_input_handler(&self) -> Result<InputPathHandler, SubXError> {
let optional_paths = vec![self.input.clone()];
let merged_paths = InputPathHandler::merge_paths_from_multiple_sources(
&optional_paths,
&self.input_paths,
&[],
)?;
Ok(InputPathHandler::from_args(&merged_paths, self.recursive)?
.with_extensions(&["srt", "ass", "vtt", "sub", "ssa"])
.with_no_extract(self.no_extract))
}
}
#[derive(ValueEnum, Clone, Debug, PartialEq, Eq)]
pub enum OutputSubtitleFormat {
Srt,
Ass,
Vtt,
Sub,
}
#[cfg(test)]
mod tests {
use super::*;
use crate::cli::{Cli, Commands};
use clap::Parser;
use std::path::PathBuf;
#[test]
fn test_convert_args_default_and_format() {
let cli =
Cli::try_parse_from(&["subx-cli", "convert", "movie.srt", "--format", "ass"]).unwrap();
let args = match cli.command {
Commands::Convert(a) => a,
_ => panic!("Expected Convert command"),
};
assert!(args.input_paths.is_empty());
assert_eq!(args.input, Some(PathBuf::from("movie.srt")));
assert!(!args.recursive);
assert_eq!(args.format, Some(OutputSubtitleFormat::Ass));
assert!(!args.keep_original);
assert_eq!(args.encoding, "utf-8");
}
#[test]
fn test_convert_args_multiple_input_recursive_and_keep_original() {
let cli = Cli::try_parse_from(&[
"subx-cli",
"convert",
"-i",
"d1",
"-i",
"f.srt",
"--recursive",
"--format",
"vtt",
"--encoding",
"utf-16",
"--keep-original",
])
.unwrap();
let args = match cli.command {
Commands::Convert(a) => a,
_ => panic!("Expected Convert command"),
};
assert_eq!(
args.input_paths,
vec![PathBuf::from("d1"), PathBuf::from("f.srt")]
);
assert_eq!(args.input, None);
assert!(args.recursive);
assert_eq!(args.format, Some(OutputSubtitleFormat::Vtt));
assert!(args.keep_original);
assert_eq!(args.encoding, "utf-16");
}
}
impl OutputSubtitleFormat {
pub fn as_str(&self) -> &'static str {
match self {
OutputSubtitleFormat::Srt => "srt",
OutputSubtitleFormat::Ass => "ass",
OutputSubtitleFormat::Vtt => "vtt",
OutputSubtitleFormat::Sub => "sub",
}
}
pub fn file_extension(&self) -> &'static str {
match self {
OutputSubtitleFormat::Srt => ".srt",
OutputSubtitleFormat::Ass => ".ass",
OutputSubtitleFormat::Vtt => ".vtt",
OutputSubtitleFormat::Sub => ".sub",
}
}
}
impl std::fmt::Display for OutputSubtitleFormat {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_str())
}
}
#[cfg(test)]
mod tests_parse {
use super::*;
use crate::cli::{Cli, Commands};
use clap::Parser;
use std::path::PathBuf;
#[test]
fn test_convert_args_default_values() {
let cli = Cli::try_parse_from(&["subx-cli", "convert", "in_path"]).unwrap();
let args = match cli.command {
Commands::Convert(c) => c,
_ => panic!("Expected Convert command"),
};
assert_eq!(args.input, Some(PathBuf::from("in_path")));
assert!(args.input_paths.is_empty());
assert!(!args.recursive);
assert_eq!(args.format, None);
assert_eq!(args.output, None);
assert!(!args.keep_original);
assert_eq!(args.encoding, "utf-8");
}
#[test]
fn test_convert_args_parsing() {
let cli = Cli::try_parse_from(&[
"subx-cli",
"convert",
"in",
"--format",
"vtt",
"--output",
"out",
"--keep-original",
"--encoding",
"gbk",
])
.unwrap();
let args = match cli.command {
Commands::Convert(c) => c,
_ => panic!("Expected Convert command"),
};
assert_eq!(args.input, Some(PathBuf::from("in")));
assert!(args.input_paths.is_empty());
assert!(!args.recursive);
assert_eq!(args.format.unwrap(), OutputSubtitleFormat::Vtt);
assert_eq!(args.output, Some(PathBuf::from("out")));
assert!(args.keep_original);
assert_eq!(args.encoding, "gbk");
}
}