wei_log/
lib.rs

1use chrono::prelude::*;
2use fs2::FileExt;
3
4use std::fs::{OpenOptions};
5use std::io::{BufReader, BufRead, Write, Seek, SeekFrom};
6use std::env;
7pub fn log(s: &str) {
8    let path = std::env::current_exe().unwrap();
9    let filename = std::path::Path::new(&path).file_name().unwrap().to_str().unwrap();
10
11    let home_dir = get_home_dir().unwrap_or_else(|| String::from("."));
12    let path;
13    if cfg!(target_os = "windows") {
14        path = format!("{}/AppData/Local/Wei/{}.log.txt", home_dir, filename);
15    } else {
16        path = format!("{}/.wei/{}.log.txt", home_dir, filename);
17    }
18
19    if !std::path::Path::new(&path).exists() {
20        match std::fs::create_dir_all(std::path::Path::new(&path).parent().unwrap()) {
21            Ok(_) => (),
22            Err(_) => return,
23        };
24    }
25
26    let local: DateTime<Local> = Local::now();
27    let data = format!("{} {}",local.format("%Y-%m-%d %H:%M"), s);
28
29    #[cfg(target_os = "windows")] 
30    match write_and_prune_file(&path, &data, 10000) {
31        Ok(_) => (),
32        Err(_) => return,
33    };
34
35    #[cfg(not(target_os = "windows"))] {
36        let mut file = match OpenOptions::new().read(true).write(true).create(true).open(&path) {
37            Ok(file) => file,
38            Err(_) => return,
39        };
40        let reader = BufReader::new(&file);
41        let mut lines: Vec<String> = match reader.lines().collect::<Result<_, _>>() {
42            Ok(lines) => lines,
43            Err(_) => return,
44        };
45        lines.push(data);
46        if lines.len() > 10000 {
47            lines.remove(0);
48        }
49        match file.seek(SeekFrom::Start(0)) {
50            Ok(_) => (),
51            Err(_) => return,
52        };
53        match file.set_len(0) {
54            Ok(_) => (),
55            Err(_) => return,
56        };  // Truncate the file
57        let mut writer = std::io::BufWriter::new(&file);
58        for line in &lines {
59            match writeln!(writer, "{}", line) {
60                Ok(_) => (),
61                Err(_) => return,
62            };
63        }
64    }
65}
66
67#[macro_export]
68macro_rules! info {
69    ($($arg:tt)*) => {{
70        let message = format!($($arg)*);
71        crate::wei_log::log(&message); // 将格式化后的字符串传递给函数
72        // println!("{}", message);
73    }}
74}
75
76#[macro_export]
77macro_rules! error {
78    ($($arg:tt)*) => {{
79        let message = format!($($arg)*);
80        let message = format!("错误: {}", message);
81        crate::wei_log::log(&message); // 将格式化后的字符串传递给函数
82        // println!("{}", message);
83    }}
84}
85
86#[macro_export]
87macro_rules! info_println {
88    ($($arg:tt)*) => {{
89        let message = format!($($arg)*);
90        crate::wei_log::log(&message); // 将格式化后的字符串传递给函数
91        // println!("{}", message);
92    }}
93}
94
95#[macro_export]
96macro_rules! info_print {
97    ($($arg:tt)*) => {{
98        let message = format!($($arg)*);
99        crate::wei_log::log(&message); // 将格式化后的字符串传递给函数
100        // print!("{}", message);
101    }}
102}
103
104
105fn get_home_dir() -> Option<String> {
106    if cfg!(target_os = "windows") {
107        env::var("USERPROFILE").ok()
108    } else {
109        env::var("HOME").ok()
110    }
111}
112
113fn write_and_prune_file(path: &str, content: &str, max_lines: usize) -> std::io::Result<()> {
114    let mut file = OpenOptions::new().read(true).write(true).create(true).open(path)?;
115
116    file.lock_exclusive()?;
117
118    // Step 1: Read all lines
119    let reader = BufReader::new(&file);
120    let mut lines: Vec<String> = reader.lines().collect::<Result<_, _>>()?;
121
122    // Step 2: Prune lines if necessary
123    if lines.len() >= max_lines {
124        lines.remove(lines.len() - 1);
125    }
126
127    // Step 3: Insert new line at the top
128    lines.insert(0, content.to_string());
129
130    // Step 4: Seek to the start of the file and write all lines
131    file.seek(SeekFrom::Start(0))?;
132    file.set_len(0)?;  // Truncate the file
133    for line in &lines {
134        writeln!(file, "{}", line)?;
135    }
136
137    file.unlock()?;
138
139    Ok(())
140}
141
142
143
144// #[cfg(test)]
145// mod tests {
146//     use super::*;
147
148//     #[test]
149//     fn it_works() {
150//         let result = add(2, 2);
151//         assert_eq!(result, 4);
152//     }
153// }