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