pocket_cli/
logging.rs

1use colored::{ColoredString, Colorize};
2use log::{Level, LevelFilter};
3use std::io::Write;
4use chrono::Local;
5use std::sync::Once;
6
7static INIT: Once = Once::new();
8
9/// Initialize the logger with the given log level
10pub fn init(level: LevelFilter) {
11    INIT.call_once(|| {
12        env_logger::Builder::new()
13            .format(|buf, record| {
14                // Format the timestamp
15                let timestamp = Local::now().format("%Y-%m-%d %H:%M:%S").to_string();
16                
17                // Format the level
18                let level_str = match record.level() {
19                    Level::Error => "ERROR".red().bold(),
20                    Level::Warn => "WARN ".yellow().bold(),
21                    Level::Info => "INFO ".green(),
22                    Level::Debug => "DEBUG".blue(),
23                    Level::Trace => "TRACE".magenta(),
24                };
25                
26                // Format the module path
27                let target = if let Some(target) = record.module_path() {
28                    if target.contains("::") {
29                        let parts: Vec<&str> = target.split("::").collect();
30                        let prefix = parts[0];
31                        let suffix = parts.last().unwrap_or(&"");
32                        format!("{}.{}", prefix, suffix)
33                    } else {
34                        target.to_string()
35                    }
36                } else {
37                    "pocket".to_string()
38                };
39                
40                // Format the message
41                writeln!(
42                    buf,
43                    "{} {} {} > {}",
44                    timestamp.dimmed(),
45                    level_str,
46                    target.dimmed(),
47                    record.args()
48                )
49            })
50            .filter(None, level)
51            .init();
52        
53        log::info!("Logger initialized at level {}", level);
54    });
55}
56
57/// Log an info message directly to terminal (not through the logger)
58pub fn info(msg: &str) {
59    println!("{} {}", "INFO".green(), msg);
60}
61
62/// Log a success message directly to terminal (not through the logger)
63pub fn success(msg: &str) {
64    println!("{} {}", "SUCCESS".green().bold(), msg);
65}
66
67/// Log a warning message directly to terminal (not through the logger)
68pub fn warning(msg: &str) {
69    println!("{} {}", "WARNING".yellow().bold(), msg);
70}
71
72/// Log an error message directly to terminal (not through the logger)
73pub fn error(msg: &str) {
74    eprintln!("{} {}", "ERROR".red().bold(), msg);
75}
76
77/// Format text for command output
78pub fn cmd_text(cmd: &str, args: &[&str]) -> ColoredString {
79    format!("{} {}", cmd, args.join(" ")).cyan()
80}
81
82/// Format a header for sections
83pub fn header(text: &str) -> ColoredString {
84    text.blue().bold()
85}
86
87/// Format a key for key-value output
88pub fn key(text: &str) -> ColoredString {
89    text.yellow()
90}
91
92/// Format a value for key-value output
93pub fn value(text: &str) -> ColoredString {
94    text.white()
95}
96
97/// Format a path for display
98pub fn path(text: &str) -> ColoredString {
99    text.underline().white()
100}
101
102/// Format an ID for display
103pub fn id(text: &str) -> ColoredString {
104    text.green()
105}
106
107/// Format a title for display
108pub fn title(text: &str) -> ColoredString {
109    text.cyan().bold()
110}