Add build output dependency file for mouse-test application
Add standard menu fore keybinds
This commit is contained in:
98
src/log.rs
Normal file
98
src/log.rs
Normal file
@@ -0,0 +1,98 @@
|
||||
/// Enkel fil-logger. Loggar till <exe_dir>/logs/<datum>.log
|
||||
/// Trådsäker via en global Mutex<File>.
|
||||
|
||||
use std::fs::{self, OpenOptions};
|
||||
use std::io::Write;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Mutex;
|
||||
use std::time::SystemTime;
|
||||
|
||||
static LOG: Mutex<Option<std::fs::File>> = Mutex::new(None);
|
||||
|
||||
/// Initialisera loggern. Anropas en gång från main().
|
||||
pub fn init() {
|
||||
let dir = log_dir();
|
||||
if let Err(e) = fs::create_dir_all(&dir) {
|
||||
eprintln!("log::init: kunde inte skapa logg-mapp {:?}: {}", dir, e);
|
||||
return;
|
||||
}
|
||||
let name = today_filename();
|
||||
let path = dir.join(name);
|
||||
match OpenOptions::new().create(true).append(true).open(&path) {
|
||||
Ok(f) => {
|
||||
*LOG.lock().unwrap() = Some(f);
|
||||
log(&format!("=== TUI-WM startad ==="));
|
||||
}
|
||||
Err(e) => eprintln!("log::init: kunde inte öppna {:?}: {}", path, e),
|
||||
}
|
||||
}
|
||||
|
||||
/// Skriv en logg-rad med tidsstämpel.
|
||||
pub fn log(msg: &str) {
|
||||
let ts = timestamp();
|
||||
let line = format!("[{}] {}\n", ts, msg);
|
||||
if let Ok(mut guard) = LOG.lock() {
|
||||
if let Some(f) = guard.as_mut() {
|
||||
let _ = f.write_all(line.as_bytes());
|
||||
let _ = f.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Makro för bekväm formatering — används som log!("foo {}", bar)
|
||||
#[macro_export]
|
||||
macro_rules! log {
|
||||
($($arg:tt)*) => {
|
||||
$crate::log::log(&format!($($arg)*))
|
||||
};
|
||||
}
|
||||
|
||||
// ─── Interna hjälpfunktioner ──────────────────────────────────────────────────
|
||||
|
||||
fn log_dir() -> PathBuf {
|
||||
// Lägg logs/ bredvid den körande binären
|
||||
let exe = std::env::current_exe().unwrap_or_else(|_| PathBuf::from("."));
|
||||
exe.parent().unwrap_or(std::path::Path::new(".")).join("logs")
|
||||
}
|
||||
|
||||
fn today_filename() -> String {
|
||||
// Bygg YYYY-MM-DD från SystemTime utan externa beroenden
|
||||
let secs = SystemTime::now()
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.map(|d| d.as_secs())
|
||||
.unwrap_or(0);
|
||||
let (y, mo, d) = unix_to_ymd(secs);
|
||||
format!("{:04}-{:02}-{:02}.log", y, mo, d)
|
||||
}
|
||||
|
||||
fn timestamp() -> String {
|
||||
let secs = SystemTime::now()
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.map(|d| d.as_secs())
|
||||
.unwrap_or(0);
|
||||
let subsec_ms = SystemTime::now()
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.map(|d| d.subsec_millis())
|
||||
.unwrap_or(0);
|
||||
let (y, mo, d) = unix_to_ymd(secs);
|
||||
let h = (secs % 86400) / 3600;
|
||||
let m = (secs % 3600) / 60;
|
||||
let s = secs % 60;
|
||||
format!("{:04}-{:02}-{:02} {:02}:{:02}:{:02}.{:03}", y, mo, d, h, m, s, subsec_ms)
|
||||
}
|
||||
|
||||
/// Konverterar Unix-sekunder till (år, månad, dag). Ingen extern crate nödvändig.
|
||||
fn unix_to_ymd(secs: u64) -> (u32, u32, u32) {
|
||||
// Algoritm: https://howardhinnant.github.io/date_algorithms.html
|
||||
let z = (secs / 86400) as i64 + 719468;
|
||||
let era = if z >= 0 { z } else { z - 146096 } / 146097;
|
||||
let doe = (z - era * 146097) as u32;
|
||||
let yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
|
||||
let y = yoe as i64 + era * 400;
|
||||
let doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
|
||||
let mp = (5 * doy + 2) / 153;
|
||||
let d = doy - (153 * mp + 2) / 5 + 1;
|
||||
let m = if mp < 10 { mp + 3 } else { mp - 9 };
|
||||
let y = if m <= 2 { y + 1 } else { y };
|
||||
(y as u32, m, d)
|
||||
}
|
||||
Reference in New Issue
Block a user