subx_cli/cli/
match_args.rs1#![allow(clippy::needless_borrows_for_generic_args)]
2use crate::cli::InputPathHandler;
5use crate::error::SubXError;
6use clap::Args;
7use std::path::PathBuf;
8
9#[derive(Args, Debug)]
11pub struct MatchArgs {
12 pub path: Option<PathBuf>,
14
15 #[arg(short = 'i', long = "input", value_name = "PATH")]
17 pub input_paths: Vec<PathBuf>,
18
19 #[arg(long)]
21 pub dry_run: bool,
22
23 #[arg(long, default_value = "80", value_parser = clap::value_parser!(u8).range(0..=100))]
25 pub confidence: u8,
26
27 #[arg(short, long)]
29 pub recursive: bool,
30
31 #[arg(long)]
33 pub backup: bool,
34
35 #[arg(long, short = 'c')]
37 pub copy: bool,
38
39 #[arg(long = "move", short = 'm')]
41 pub move_files: bool,
42}
43
44impl MatchArgs {
45 pub fn validate(&self) -> Result<(), String> {
47 if self.copy && self.move_files {
48 return Err(
49 "Cannot use --copy and --move together. Please choose one operation mode."
50 .to_string(),
51 );
52 }
53 Ok(())
54 }
55
56 pub fn get_input_handler(&self) -> Result<InputPathHandler, SubXError> {
58 let optional_paths = vec![self.path.clone()];
59 let merged_paths = InputPathHandler::merge_paths_from_multiple_sources(
60 &optional_paths,
61 &self.input_paths,
62 &[],
63 )?;
64
65 Ok(InputPathHandler::from_args(&merged_paths, self.recursive)?
66 .with_extensions(&["mp4", "mkv", "avi", "mov", "srt", "ass", "vtt", "sub"]))
67 }
68}
69
70#[cfg(test)]
72mod tests {
73 use crate::cli::{Cli, Commands};
74 use clap::Parser;
75 use std::path::PathBuf;
76
77 #[test]
78 fn test_match_args_default_values() {
79 let cli = Cli::try_parse_from(&["subx-cli", "match", "path"]).unwrap();
80 let args = match cli.command {
81 Commands::Match(m) => m,
82 _ => panic!("Expected Match command"),
83 };
84 assert_eq!(args.path, Some(PathBuf::from("path")));
85 assert!(args.input_paths.is_empty());
86 assert!(!args.dry_run);
87 assert!(!args.recursive);
88 assert!(!args.backup);
89 assert_eq!(args.confidence, 80);
90 }
91
92 #[test]
93 fn test_match_args_parsing() {
94 let cli = Cli::try_parse_from(&[
95 "subx-cli",
96 "match",
97 "path",
98 "--dry-run",
99 "--recursive",
100 "--backup",
101 "--confidence",
102 "50",
103 ])
104 .unwrap();
105 let args = match cli.command {
106 Commands::Match(m) => m,
107 _ => panic!("Expected Match command"),
108 };
109 assert_eq!(args.path, Some(PathBuf::from("path")));
110 assert!(args.input_paths.is_empty());
111 assert!(args.dry_run);
112 assert!(args.recursive);
113 assert!(args.backup);
114 assert_eq!(args.confidence, 50);
115 }
116
117 #[test]
118 fn test_match_args_invalid_confidence() {
119 let res = Cli::try_parse_from(&["subx-cli", "match", "path", "--confidence", "150"]);
120 assert!(res.is_err());
121 }
122
123 #[test]
124 fn test_match_args_copy_and_move_mutually_exclusive() {
125 let cli = Cli::try_parse_from(&["subx-cli", "match", "path", "--copy", "--move"]).unwrap();
126 let args = match cli.command {
127 Commands::Match(m) => m,
128 _ => panic!("Expected Match command"),
129 };
130 let result = args.validate();
131 assert!(result.is_err());
132 assert!(
133 result
134 .unwrap_err()
135 .contains("Cannot use --copy and --move together")
136 );
137 }
138
139 #[test]
140 fn test_match_args_copy_parameter() {
141 let cli = Cli::try_parse_from(&["subx-cli", "match", "path", "--copy"]).unwrap();
142 let args = match cli.command {
143 Commands::Match(m) => m,
144 _ => panic!("Expected Match command"),
145 };
146 assert!(args.copy);
147 assert!(!args.move_files);
148 assert!(args.validate().is_ok());
149 }
150
151 #[test]
152 fn test_match_args_move_parameter() {
153 let cli = Cli::try_parse_from(&["subx-cli", "match", "path", "--move"]).unwrap();
154 let args = match cli.command {
155 Commands::Match(m) => m,
156 _ => panic!("Expected Match command"),
157 };
158 assert!(!args.copy);
159 assert!(args.move_files);
160 assert!(args.validate().is_ok());
161 }
162
163 #[test]
164 fn test_match_args_input_paths() {
165 let cli = Cli::try_parse_from(&[
166 "subx-cli",
167 "match",
168 "-i",
169 "dir1",
170 "-i",
171 "dir2",
172 "--recursive",
173 ])
174 .unwrap();
175 let args = match cli.command {
176 Commands::Match(m) => m,
177 _ => panic!("Expected Match command"),
178 };
179 assert!(args.path.is_none());
180 assert_eq!(
181 args.input_paths,
182 vec![PathBuf::from("dir1"), PathBuf::from("dir2")]
183 );
184 assert!(args.recursive);
185 }
186}