ddidderr
dc110d33b6
specify a log file as 1st argument and the input will also be written to that file. timestamp will be without ansi color codes.
88 lines
2.1 KiB
Rust
88 lines
2.1 KiB
Rust
use chrono::prelude::*;
|
|
use std::{
|
|
env::args,
|
|
fs::File,
|
|
io::{stdin, stdout, Error as IoError, Read, StdoutLock, Write},
|
|
};
|
|
|
|
type LogtimesResult = Result<(), IoError>;
|
|
|
|
#[inline(always)]
|
|
fn print_time<T>(output: &mut T) -> LogtimesResult
|
|
where
|
|
T: Write,
|
|
{
|
|
let date_now = Local::now().format("%H:%M:%S%.9f");
|
|
|
|
write!(output, "[{}] ", &date_now)
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn print_time_color(output: &mut StdoutLock) -> Result<(), std::io::Error> {
|
|
let date_now = Local::now().format("%H:%M:%S%.9f");
|
|
|
|
let color_green = "\x1b\x5b\x30\x3b\x33\x32\x6d";
|
|
let color_off = "\x1b\x5b\x30\x6d";
|
|
|
|
write!(output, "{}[{}]{} ", color_green, &date_now, color_off)
|
|
}
|
|
|
|
#[inline(always)]
|
|
fn print_delete_line(output: &mut StdoutLock) -> LogtimesResult {
|
|
// tput dl1 und tput hpa 0
|
|
let bytes = "\x1b\x5b\x4d\x1b\x5b\x31\x47";
|
|
write!(output, "{}", bytes)
|
|
}
|
|
|
|
fn run() -> LogtimesResult {
|
|
let mut log_file = args().nth(1).map(|f| File::create(f).unwrap());
|
|
|
|
let out = stdout();
|
|
let mut output = out.lock();
|
|
|
|
let inp = stdin();
|
|
let mut input = inp.lock();
|
|
|
|
let mut buf = [0; 1];
|
|
|
|
let mut linebuf = Vec::with_capacity(64 * 1024);
|
|
|
|
loop {
|
|
// read 1 char
|
|
input.read_exact(&mut buf)?;
|
|
|
|
// push that char to the "current line" buffer
|
|
linebuf.push(buf[0]);
|
|
|
|
// we encounter a newline -> delete the line and write it new as:
|
|
// [timestamp] actual content\n
|
|
// also write the line to the log file if there is one
|
|
if buf[0] == 0xa {
|
|
print_delete_line(&mut output)?;
|
|
print_time_color(&mut output)?;
|
|
output.write_all(&linebuf)?;
|
|
output.flush()?;
|
|
|
|
if let Some(ref mut f) = log_file {
|
|
print_time(f)?;
|
|
f.write_all(&linebuf)?;
|
|
f.flush()?;
|
|
};
|
|
|
|
// clear line buffer so it is fresh for the next line
|
|
linebuf.clear();
|
|
continue;
|
|
}
|
|
|
|
output.write_all(&buf)?;
|
|
output.flush()?;
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
if let Err(e) = run() {
|
|
println!("{:?}", e);
|
|
std::process::exit(1);
|
|
}
|
|
}
|