a shockingly bad tail implementation

the version of tail.exe that exists in coreutils on scoop cannot handle
unicode at all, which is really annoying, so I wrote an in-shell tail
that handles utf-8 cleanly. It reads one byte at a time and then checks
if the whole buffer that it has read is valid utf-8 and then spits it
out of it is. There's also no way to stop it lol. It is -terrible-
parse-tree
Jordan Orelli 2 years ago
parent d2066e8526
commit ca94a86a24

@ -167,6 +167,7 @@ impl Reader {
&mut self.buf_len,
))?;
}
debug!("• {}", self.buf_len);
self.buf_idx = 0;
}
@ -263,11 +264,6 @@ impl From<Console::INPUT_RECORD> for Event {
let mstate = event.dwControlKeyState;
let c = char::from_u32(event.uChar.UnicodeChar as u32).unwrap_or('💀');
if event.bKeyDown.as_bool() {
debug!("key down {}", event.wVirtualKeyCode);
} else {
debug!("key up {}", event.wVirtualKeyCode);
}
Event::Key(key::Event {
down: event.bKeyDown.as_bool(),
repeats: event.wRepeatCount,

@ -1,4 +1,4 @@
// type Code = u16;
use std::fmt;
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct Code {
@ -33,7 +33,12 @@ pub struct Event {
pub shift: bool,
}
impl Event {}
impl fmt::Display for Event {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let down = if self.down { '↓' } else { '↑' };
write!(f, "{} {}", down, self.code.val)
}
}
/// CODES contains a lookup table for key codes. Note that this is a sparse array and not all
/// values associate to valid key codes.

@ -46,7 +46,23 @@ where
fn log(&self, record: &Record) {
if self.enabled(record.metadata()) {
if let Ok(out) = self.out.lock().as_deref_mut() {
_ = write!(out, "{} - {}\n", record.level(), record.args());
match record.level() {
log::Level::Error => {
_ = write!(out, "\x1b[31m{}\x1b[0m\n", record.args());
},
log::Level::Warn => {
_ = write!(out, "\x1b[33m{}\x1b[0m\n", record.args());
},
log::Level::Info => {
_ = write!(out, "\x1b[37m{}\x1b[0m\n", record.args());
},
log::Level::Debug => {
_ = write!(out, "\x1b[90m{}\x1b[0m\n", record.args());
},
log::Level::Trace => {
_ = write!(out, "\x1b[36m{}\x1b[0m\n", record.args());
},
}
}
}
}

@ -7,6 +7,8 @@ mod prompt;
use line::Line;
use prompt::Prompt;
use std::fs::File;
use std::io::{Read, Seek, SeekFrom};
use windows::Win32::{
Foundation::{CloseHandle, HANDLE},
System::Console,
@ -190,6 +192,38 @@ fn eval(line: String) -> Result<()> {
return Ok(());
}
}
"tail" => {
if parts.len() > 1 {
let fname = parts[1];
let stdout = stdout_handle()?;
match File::options().read(true).open(fname) {
Ok(mut f) => {
_ = f.seek(SeekFrom::End(0));
let mut one_byte: [u8; 1] = [0 ; 1];
let mut buf: Vec<u8> = vec![];
loop {
match f.read(&mut one_byte) {
Ok(n) => {
if n == 1 {
buf.push(one_byte[0]);
if let Ok(s) = std::str::from_utf8(&buf) {
unsafe {
Error::check(Console::WriteConsoleA(stdout, s.as_bytes(), None, None))?;
}
buf.clear();
}
}
},
Err(_) => {},
}
}
}
Err(e) => { println!("failed to open file: {}", e); }
}
} else {
println!("need a file name");
}
}
"echo" => {
let rest: Vec<&str> = parts[1..].to_vec();
println!("{:?}", rest);
@ -237,8 +271,10 @@ fn main() -> Result<()> {
prompt.print()?;
loop {
// debug!("----------------------------------------");
match input.next()? {
input::Event::Key(event) => {
debug!("{}", event);
if event.down {
continue;
}
@ -280,6 +316,7 @@ fn main() -> Result<()> {
}
if event.ctrl && event.code == key::D {
debug!("ctrl-d");
unsafe {
CloseHandle(stdout);
}
@ -287,6 +324,7 @@ fn main() -> Result<()> {
}
if event.ctrl && event.code == key::J {
debug!("ctrl-j");
unsafe {
// red bullet
let text = "\x1b[31m\u{2022}\x1b[0m";
@ -322,7 +360,7 @@ fn main() -> Result<()> {
continue;
}
debug!("Unhandled Keyboard Event: {:?}", event.code);
warn!("‽ {}", event);
}
input::Event::Left => {
if line.back() {

Loading…
Cancel
Save