subx_cli/cli/mod.rs
1//! Command-line interface for the SubX subtitle processing tool.
2//!
3//! This module provides the top-level CLI application structure and subcommands
4//! for AI-powered matching, subtitle format conversion, audio synchronization,
5//! encoding detection, configuration management, cache operations, and shell
6//! completion generation.
7//!
8//! # Architecture
9//!
10//! The CLI is built using `clap` and follows a subcommand pattern:
11//! - `match` - AI-powered subtitle file matching and renaming
12//! - `convert` - Subtitle format conversion between standards
13//! - `sync` - Audio-subtitle synchronization and timing adjustment
14//! - `detect-encoding` - Character encoding detection and conversion
15//! - `config` - Configuration management and inspection
16//! - `cache` - Cache inspection and dry-run management
17//! - `generate-completion` - Shell completion script generation
18//!
19//! # Examples
20//!
21//! ```bash
22//! # Basic subtitle matching
23//! subx match /path/to/videos /path/to/subtitles
24//!
25//! # Convert SRT to ASS format
26//! subx convert --input file.srt --output file.ass --format ass
27//!
28//! # Detect file encoding
29//! subx detect-encoding *.srt
30//! ```
31
32mod cache_args;
33mod config_args;
34mod convert_args;
35mod detect_encoding_args;
36mod generate_completion_args;
37mod match_args;
38mod sync_args;
39pub mod table;
40pub mod ui;
41
42pub use cache_args::{CacheAction, CacheArgs};
43use clap::{Parser, Subcommand};
44pub use config_args::{ConfigAction, ConfigArgs};
45pub use convert_args::{ConvertArgs, OutputSubtitleFormat};
46pub use detect_encoding_args::DetectEncodingArgs;
47pub use generate_completion_args::GenerateCompletionArgs;
48pub use match_args::MatchArgs;
49pub use sync_args::{SyncArgs, SyncMethod};
50pub use ui::{
51 create_progress_bar, display_ai_usage, display_match_results, print_error, print_success,
52 print_warning,
53};
54
55/// Main CLI application structure defining the top-level interface.
56///
57/// This structure encapsulates the entire command-line interface for SubX,
58/// providing access to all available subcommands and global options.
59///
60/// # Subcommands
61///
62/// - `match` - AI-powered subtitle file matching and intelligent renaming
63/// - `convert` - Format conversion between different subtitle standards
64/// - `sync` - Audio-subtitle synchronization with timing adjustment
65/// - `detect-encoding` - Character encoding detection and conversion
66/// - `config` - Configuration management and inspection utilities
67/// - `generate-completion` - Shell completion script generation
68/// - `cache` - Cache inspection and dry-run management
69///
70/// # Examples
71///
72/// ```rust,no_run
73/// use subx_cli::cli::Cli;
74/// use clap::Parser;
75///
76/// // Parse CLI arguments from specific args instead of std::env
77/// let cli = Cli::parse_from(&["subx", "config", "show"]);
78///
79/// // Access the selected subcommand
80/// match cli.command {
81/// // Handle different commands...
82/// _ => {}
83/// }
84/// ```
85///
86/// # Global Options
87///
88/// Currently, global options are handled within individual subcommands.
89/// Future versions may include global flags such as verbosity control
90/// or configuration file overrides.
91#[derive(Parser, Debug)]
92#[command(name = "subx-cli")]
93#[command(about = "Intelligent subtitle processing CLI tool")]
94#[command(version = env!("CARGO_PKG_VERSION"))]
95pub struct Cli {
96 /// The subcommand to execute.
97 ///
98 /// Each subcommand provides specialized functionality for different
99 /// aspects of subtitle processing and management.
100 #[command(subcommand)]
101 pub command: Commands,
102}
103
104/// Available subcommands for the SubX CLI application.
105///
106/// Each variant represents a specific operation that can be performed
107/// by the SubX tool, with associated argument structures that define
108/// the parameters and options for that operation.
109///
110/// # Command Categories
111///
112/// ## Core Processing Commands
113/// - `Match` - AI-powered subtitle matching and renaming
114/// - `Convert` - Format conversion between subtitle standards
115/// - `Sync` - Audio-subtitle synchronization and timing adjustment
116///
117/// ## Utility Commands
118/// - `DetectEncoding` - Character encoding detection and conversion
119/// - `Config` - Configuration management and inspection
120/// - `Cache` - Cache management and dry-run inspection
121/// - `GenerateCompletion` - Shell completion script generation
122///
123/// # Examples
124///
125/// ```rust
126/// use subx_cli::cli::{Commands, MatchArgs};
127/// use std::path::PathBuf;
128///
129/// let match_command = Commands::Match(MatchArgs {
130/// path: PathBuf::from("videos/"),
131/// dry_run: true,
132/// confidence: 80,
133/// recursive: false,
134/// backup: false,
135/// copy: false,
136/// move_files: false,
137/// });
138/// ```
139#[derive(Subcommand, Debug)]
140pub enum Commands {
141 /// AI-powered subtitle file matching and intelligent renaming.
142 ///
143 /// Uses artificial intelligence to analyze video and subtitle files,
144 /// matching them based on content similarity and automatically
145 /// renaming subtitle files to match their corresponding videos.
146 Match(MatchArgs),
147
148 /// Convert subtitle files between different formats.
149 ///
150 /// Supports conversion between popular subtitle formats including
151 /// SRT, ASS, VTT, and others with format-specific options.
152 Convert(ConvertArgs),
153
154 /// Detect and convert character encoding of subtitle files.
155 ///
156 /// Automatically detects the character encoding of subtitle files
157 /// and optionally converts them to UTF-8 for better compatibility.
158 DetectEncoding(DetectEncodingArgs),
159
160 /// Synchronize subtitle timing with audio tracks.
161 ///
162 /// Analyzes audio content and adjusts subtitle timing to match
163 /// dialogue and speech patterns in the audio track.
164 Sync(SyncArgs),
165
166 /// Manage and inspect application configuration.
167 ///
168 /// Provides tools for viewing, validating, and managing SubX
169 /// configuration settings from various sources.
170 Config(ConfigArgs),
171
172 /// Generate shell completion scripts.
173 ///
174 /// Creates completion scripts for various shells (bash, zsh, fish)
175 /// to enable tab completion for SubX commands and arguments.
176 GenerateCompletion(GenerateCompletionArgs),
177
178 /// Manage cache and inspect dry-run results.
179 ///
180 /// Provides utilities for examining cached results, clearing cache
181 /// data, and inspecting the effects of dry-run operations.
182 Cache(CacheArgs),
183}
184
185/// Executes the SubX CLI application with parsed arguments.
186///
187/// This is the main entry point for CLI execution, routing parsed
188/// command-line arguments to their respective command handlers.
189///
190/// # Arguments Processing
191///
192/// The function takes ownership of parsed CLI arguments and dispatches
193/// them to the appropriate command implementation based on the selected
194/// subcommand.
195///
196/// # Error Handling
197///
198/// Returns a [`crate::Result<()>`] that wraps any errors encountered
199/// during command execution. Errors are propagated up to the main
200/// function for proper exit code handling.
201///
202/// # Examples
203///
204/// ```rust
205/// use subx_cli::cli::run;
206///
207/// # tokio_test::block_on(async {
208/// // This would typically be called from main()
209/// // run().await?;
210/// # Ok::<(), Box<dyn std::error::Error>>(())
211/// # });
212/// ```
213///
214/// # Async Context
215///
216/// This function is async because several subcommands perform I/O
217/// operations that benefit from async execution, particularly:
218/// - AI service API calls
219/// - Large file processing operations
220/// - Network-based configuration loading
221pub async fn run() -> crate::Result<()> {
222 // Create production configuration service
223 let config_service = std::sync::Arc::new(crate::config::ProductionConfigService::new()?);
224 run_with_config(config_service.as_ref()).await
225}
226
227/// Run the CLI with a provided configuration service.
228///
229/// This function enables dependency injection of configuration services,
230/// making it easier to test and providing better control over configuration
231/// management.
232///
233/// # Arguments
234///
235/// * `config_service` - The configuration service to use
236///
237/// # Errors
238///
239/// Returns an error if command execution fails.
240pub async fn run_with_config(
241 config_service: &dyn crate::config::ConfigService,
242) -> crate::Result<()> {
243 let cli = Cli::parse();
244
245 match cli.command {
246 Commands::Match(args) => {
247 args.validate()
248 .map_err(crate::error::SubXError::CommandExecution)?;
249 crate::commands::match_command::execute(args, config_service).await?;
250 }
251 Commands::Convert(args) => {
252 crate::commands::convert_command::execute(args, config_service).await?;
253 }
254 Commands::Sync(args) => {
255 crate::commands::sync_command::execute(&args, config_service).await?;
256 }
257 Commands::Config(args) => {
258 crate::commands::config_command::execute(args, config_service).await?;
259 }
260 Commands::GenerateCompletion(args) => {
261 let mut cmd = <Cli as clap::CommandFactory>::command();
262 let cmd_name = cmd.get_name().to_string();
263 let mut stdout = std::io::stdout();
264 clap_complete::generate(args.shell, &mut cmd, cmd_name, &mut stdout);
265 }
266 Commands::Cache(args) => {
267 crate::commands::cache_command::execute(args).await?;
268 }
269 Commands::DetectEncoding(args) => {
270 crate::commands::detect_encoding_command::detect_encoding_command(
271 &args.file_paths,
272 args.verbose,
273 )?;
274 }
275 }
276 Ok(())
277}