Add build output dependency file for mouse-test application

Add standard menu fore keybinds
This commit is contained in:
2026-03-28 03:18:41 +01:00
parent 4440ad79bd
commit 3a9e292088
203 changed files with 3797 additions and 29 deletions

98
src/log.rs Normal file
View 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)
}