From 5d15c15cb0de8c0cccd7c17ae747bf880ec43976 Mon Sep 17 00:00:00 2001 From: DragonSlayer_14 Date: Sun, 20 Sep 2026 23:47:48 +0200 Subject: [PATCH] =?UTF-8?q?F=C3=BCgt=20farbige=20Terminalausgabe=20je=20na?= =?UTF-8?q?ch=20Log-Level=20hinzu?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Die komplette Ausgabezeile wird nun abhängig vom Schweregrad eingefärbt (Error rot, Warn gelb, Info grün, Debug cyan), aber nur wenn stdout/stderr ein echtes Terminal ist und weder NO_COLOR noch TERM=dumb gesetzt sind. Die Logdatei bleibt unverändert klartextbasiert ohne ANSI-Codes. Co-Authored-By: Claude Sonnet 5 --- .idea/Logger.iml | 1 + README.md | 1 + src/lib.rs | 37 +++++++++++++++++++++++++++++++++++-- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/.idea/Logger.iml b/.idea/Logger.iml index bbe0a70..1aed096 100644 --- a/.idea/Logger.iml +++ b/.idea/Logger.iml @@ -4,6 +4,7 @@ + diff --git a/README.md b/README.md index 1c270f3..11aa0f2 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ - `Warn` (2) — Warnungen (Ausgabe auf `stdout` mit `[?]`-Präfix) - `Info` (3) — Betriebsinformationen (Ausgabe auf `stdout` mit `[i]`-Präfix) - `Debug` (4) — Diagnoseausgaben (Ausgabe auf `stdout` mit `[d]`-Präfix) +- **Farbige Terminalausgabe**: Jede Zeile wird je nach Schweregrad eingefärbt (`Error` rot, `Warn` gelb, `Info` grün, `Debug` cyan). Farben werden nur ausgegeben, wenn `stdout`/`stderr` ein echtes Terminal ist (keine Umleitung in Datei/Pipe), `NO_COLOR` nicht gesetzt ist und `TERM` nicht `dumb` ist. Die Logdatei enthält stets reinen Text ohne ANSI-Codes. - **Threadsicherheit**: Dateischreibzugriffe und Konfiguration sind thread-sicher serialisiert. - **Einheitliches Format**: `[Präfix][DD.MM.YYYY HH:MM:SS.mmm][LEVEL][Tag]: Nachricht` - **Flexible Konfiguration**: diff --git a/src/lib.rs b/src/lib.rs index bea72bd..407afab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,7 +24,7 @@ use std::env; use std::fmt::{Display, Formatter}; use std::fs::{File, OpenOptions, create_dir_all}; -use std::io::Write; +use std::io::{IsTerminal, Write}; use std::path::PathBuf; use std::str::FromStr; use std::sync::atomic::{AtomicU8, Ordering}; @@ -156,6 +156,33 @@ pub fn set_log_dir(path: impl Into) { } } +/// ANSI-Escape-Sequenz zum Zurücksetzen der Textfarbe. +const ANSI_RESET: &str = "\x1b[0m"; + +/// Liefert die ANSI-Farbsequenz für den jeweiligen Schweregrad. +/// +/// Farben: `Error` -> Rot, `Warn` -> Gelb, `Info` -> Grün, `Debug` -> Cyan. +fn ansi_color(log_level: &LogLevel) -> &'static str { + match log_level { + LogLevel::Error => "\x1b[31m", + LogLevel::Warn => "\x1b[33m", + LogLevel::Info => "\x1b[32m", + LogLevel::Debug => "\x1b[36m", + } +} + +/// Prüft, ob Farbausgabe für den gegebenen Stream sinnvoll ist. +/// +/// Voraussetzungen: +/// - Der Stream muss ein echtes Terminal sein (`is_terminal`), keine Umleitung in eine Datei oder Pipe. +/// - Die Umgebungsvariable `NO_COLOR` darf nicht gesetzt sein (siehe ). +/// - `TERM` darf nicht auf `dumb` stehen. +fn color_supported(stream_is_terminal: bool) -> bool { + stream_is_terminal + && env::var_os("NO_COLOR").is_none() + && env::var("TERM").map(|term| term != "dumb").unwrap_or(true) +} + /// Formatiert eine Lognachricht mit Zeitstempel, Level, Tag und Präfix. /// /// Format: @@ -224,7 +251,13 @@ pub fn log(tag: &str, message: &str, log_level: LogLevel) { let formatted = format_message(tag, message, &log_level); if log_level == LogLevel::Error { - eprintln!("{}", formatted); + if color_supported(std::io::stderr().is_terminal()) { + eprintln!("{}{}{}", ansi_color(&log_level), formatted, ANSI_RESET); + } else { + eprintln!("{}", formatted); + } + } else if color_supported(std::io::stdout().is_terminal()) { + println!("{}{}{}", ansi_color(&log_level), formatted, ANSI_RESET); } else { println!("{}", formatted); }