subx_cli/commands/
convert_command.rs

1use crate::cli::{ConvertArgs, OutputSubtitleFormat};
2use crate::config::load_config;
3use crate::core::file_manager::FileManager;
4use crate::core::formats::converter::{ConversionConfig, FormatConverter};
5use crate::error::SubXError;
6
7/// 執行格式轉換命令
8pub async fn execute(args: ConvertArgs) -> crate::Result<()> {
9    let app_config = load_config()?;
10    let config = ConversionConfig {
11        preserve_styling: app_config.formats.preserve_styling,
12        target_encoding: args.encoding.clone(),
13        keep_original: args.keep_original,
14        validate_output: true,
15    };
16    let converter = FormatConverter::new(config);
17
18    // 預設輸出格式轉換為 enum,若配置無效則回報錯誤
19    let default_output = match app_config.formats.default_output.as_str() {
20        "srt" => OutputSubtitleFormat::Srt,
21        "ass" => OutputSubtitleFormat::Ass,
22        "vtt" => OutputSubtitleFormat::Vtt,
23        "sub" => OutputSubtitleFormat::Sub,
24        other => return Err(SubXError::config(format!("未知的預設輸出格式: {}", other))),
25    };
26    let output_format = args.format.clone().unwrap_or(default_output);
27    if args.input.is_file() {
28        // 單檔案轉換
29        let format_str = output_format.to_string();
30        let output_path = args
31            .output
32            .unwrap_or_else(|| args.input.with_extension(format_str.clone()));
33        let mut file_manager = FileManager::new();
34        match converter
35            .convert_file(&args.input, &output_path, &format_str)
36            .await
37        {
38            Ok(result) => {
39                if result.success {
40                    file_manager.record_creation(&output_path);
41                    println!(
42                        "✓ 轉換完成: {} -> {}",
43                        args.input.display(),
44                        output_path.display()
45                    );
46                    if !args.keep_original {
47                        if let Err(e) = file_manager.remove_file(&args.input) {
48                            eprintln!("⚠️  無法移除原始檔案 {}: {}", args.input.display(), e);
49                        }
50                    }
51                } else {
52                    println!("✗ 轉換失敗");
53                    for error in result.errors {
54                        println!("  錯誤: {}", error);
55                    }
56                }
57            }
58            Err(e) => {
59                eprintln!("✗ 轉換失敗: {}", e);
60                if let Err(rollback_err) = file_manager.rollback() {
61                    eprintln!("✗ 回滾失敗: {}", rollback_err);
62                }
63                return Err(e);
64            }
65        }
66    } else {
67        // 批量轉換
68        let format_str = output_format.to_string();
69        let results = converter
70            .convert_batch(&args.input, &format_str, true)
71            .await?;
72        let success_count = results.iter().filter(|r| r.success).count();
73        let total_count = results.len();
74        println!("批量轉換完成: {}/{} 成功", success_count, total_count);
75        for result in results.iter().filter(|r| !r.success) {
76            println!("失敗: {}", result.errors.join(", "));
77        }
78    }
79    Ok(())
80}