From cba1004db8d238dece7d4478d5870375d3619999 Mon Sep 17 00:00:00 2001 From: Jordan Orelli Date: Sun, 5 Mar 2023 18:43:50 -0600 Subject: [PATCH] moving output writing to one spot --- src/error.rs | 9 +++++++++ src/main.rs | 52 +++++++++++++++------------------------------------ src/output.rs | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 37 deletions(-) create mode 100644 src/output.rs diff --git a/src/error.rs b/src/error.rs index 46fcee1..67264f5 100644 --- a/src/error.rs +++ b/src/error.rs @@ -31,3 +31,12 @@ impl Error { Error::InputError(msg.into()) } } + +impl From for std::io::Error { + fn from(e: Error) -> Self { + match e { + Error::IOError(e) => e, + _ => std::io::Error::new(std::io::ErrorKind::Other, e), + } + } +} diff --git a/src/main.rs b/src/main.rs index b98f554..0e73bc9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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; } diff --git a/src/output.rs b/src/output.rs new file mode 100644 index 0000000..99d37fb --- /dev/null +++ b/src/output.rs @@ -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 { + 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 { + 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 { +// unsafe { +// Error::check(Console::WriteConsoleA(self.output, buf, None, None))?; +// } +// Ok(0) +// } +// +// fn flush(&mut self) -> io::Result<()> { +// Ok(()) +// } +// }