moving output writing to one spot

parse-tree
Jordan Orelli 2 years ago
parent 1eb955b474
commit cba1004db8

@ -31,3 +31,12 @@ impl Error {
Error::InputError(msg.into()) Error::InputError(msg.into())
} }
} }
impl From<Error> for std::io::Error {
fn from(e: Error) -> Self {
match e {
Error::IOError(e) => e,
_ => std::io::Error::new(std::io::ErrorKind::Other, e),
}
}
}

@ -1,5 +1,6 @@
mod error; mod error;
mod input; mod input;
mod output;
mod key; mod key;
mod line; mod line;
mod log; mod log;
@ -8,9 +9,9 @@ mod prompt;
use line::Line; use line::Line;
use prompt::Prompt; use prompt::Prompt;
use std::fs::File; use std::fs::File;
use std::io::{Read, Seek, SeekFrom}; use std::io::{Read, Seek, SeekFrom, Write};
use windows::Win32::{ use windows::Win32::{
Foundation::{CloseHandle, HANDLE}, Foundation::HANDLE,
System::Console, System::Console,
}; };
@ -275,6 +276,7 @@ fn main() -> Result<()> {
let mut line = Line::new(); let mut line = Line::new();
let prompt = Prompt::new(); let prompt = Prompt::new();
let mut input = input::Reader::new()?; let mut input = input::Reader::new()?;
let mut output = output::Writer::new()?;
prompt.print()?; prompt.print()?;
info!("» enter"); info!("» enter");
@ -318,35 +320,21 @@ fn main() -> Result<()> {
if event.code == key::BACKSPACE { if event.code == key::BACKSPACE {
if line.backspace() { if line.backspace() {
unsafe {
// move cursor back two spaces // move cursor back two spaces
Error::check(Console::WriteConsoleA(stdout, "\x1b[2D".as_bytes(), None, None))?; output.write("\x1b[2D")?;
} // output.back(2)?;
let tail = format!("{} ", line.tail()); let tail = format!("{} ", line.tail());
let n = tail.chars().count(); let n = tail.chars().count();
unsafe { output.write(&tail)?;
// write the rest of the line plus a space to erase the last character
Error::check(Console::WriteConsoleA(
stdout,
tail.as_bytes(),
None,
None,
))?;
}
// after writing out the tail, rewind by the number of characters in // after writing out the tail, rewind by the number of characters in
// the tail // the tail
if n > 1 { if n > 1 {
let text = format!("\x1b[{}D", n-1); let text = format!("\x1b[{}D", n-1);
unsafe { output.write(&text)?;
Error::check(Console::WriteConsoleA(stdout, text.as_bytes(), None, None))?;
}
} else { } else {
// honestly I can't remember how I figured this out // honestly I can't remember how I figured this out
let text = format!(" \x1b[1D"); output.write(" \x1b[1D")?;
unsafe {
Error::check(Console::WriteConsoleA(stdout, text.as_bytes(), None, None))?;
}
} }
} }
continue; continue;
@ -355,34 +343,24 @@ fn main() -> Result<()> {
// CTRL-D to exit // CTRL-D to exit
if event.ctrl && event.code == key::D { if event.ctrl && event.code == key::D {
info!("» exit"); info!("» exit");
unsafe { output.close()?;
CloseHandle(stdout);
}
return Ok(()); return Ok(());
} }
// CTRL-J to draw a cool little dot // CTRL-J to draw a cool little dot
if event.ctrl && event.code == key::J { if event.ctrl && event.code == key::J {
debug!("⎈ j: dot"); debug!("⎈ j: dot");
unsafe {
// red bullet // red bullet
let text = "\x1b[31m\u{2022}\x1b[0m"; output.write("\x1b[31m\u{2022}\x1b[0m")?;
Error::check(Console::WriteConsoleA(stdout, text.as_bytes(), None, None))?;
}
continue; continue;
} }
// CTRL-L to clear the screen // CTRL-L to clear the screen
if event.ctrl && event.code == key::L { if event.ctrl && event.code == key::L {
info!("» clear"); info!("» clear");
let text = "\x1b[2J\x1b[0;0H"; output.write("\x1b[2J\x1b[0;0H")?;
unsafe {
Error::check(Console::WriteConsoleA(stdout, text.as_bytes(), None, None))?;
}
prompt.print()?; prompt.print()?;
unsafe { output.write(&line.show())?;
Error::check(Console::WriteConsoleA(stdout, line.show().as_bytes(), None, None))?;
}
continue; continue;
} }

@ -0,0 +1,52 @@
use anyhow::{Context, Result};
use crate::error::Error;
use windows::Win32::{Foundation::{CloseHandle, HANDLE}, System::Console};
// use std::io;
pub fn stdout_handle() -> Result<HANDLE> {
unsafe {
let handle = Console::GetStdHandle(Console::STD_OUTPUT_HANDLE)
.context("unable to get stdin handle")?;
Ok(handle)
}
}
pub struct Writer {
output: HANDLE,
}
impl Writer {
pub fn new() -> Result<Self> {
Ok(Self{
output: stdout_handle()?,
})
}
pub fn write(&mut self, s: &str) -> Result<()> {
unsafe {
Error::check(Console::WriteConsoleA(self.output, s.as_bytes(), None, None))?;
}
Ok(())
}
pub fn close(&mut self) -> Result<()> {
unsafe {
CloseHandle(self.output);
}
Ok(())
}
}
// impl std::io::Write for Writer {
// fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
// unsafe {
// Error::check(Console::WriteConsoleA(self.output, buf, None, None))?;
// }
// Ok(0)
// }
//
// fn flush(&mut self) -> io::Result<()> {
// Ok(())
// }
// }
Loading…
Cancel
Save