diff --git a/src/editor.rs b/src/editor.rs index 563be90..47c0ae1 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -1,6 +1,8 @@ use crossterm::event::{read, Event, Event::Key, KeyCode::Char, KeyEvent, KeyModifiers}; +use std::io::Error; mod terminal; -use terminal::Terminal; +use terminal::{Position, Size, Terminal}; + pub struct Editor { should_quit: bool, } @@ -16,7 +18,7 @@ impl Editor { result.unwrap(); } - fn repl(&mut self) -> Result<(), std::io::Error> { + fn repl(&mut self) -> Result<(), Error> { loop { self.refresh_screen()?; if self.should_quit { @@ -40,22 +42,26 @@ impl Editor { } } } - fn refresh_screen(&self) -> Result<(), std::io::Error> { + fn refresh_screen(&self) -> Result<(), Error> { + Terminal::hide_cursor()?; if self.should_quit { Terminal::clear_screen()?; - print!("Goodbye.\r\n"); + Terminal::print("Goodbye.\r\n")?; } else { Self::draw_rows()?; - Terminal::move_cursor_to(0, 0)?; + Terminal::move_cursor_to(Position { x: 0, y: 0 })?; } + Terminal::show_cursor()?; + Terminal::execute()?; Ok(()) } - fn draw_rows() -> Result<(), std::io::Error> { - let height = Terminal::size()?.1; + fn draw_rows() -> Result<(), Error> { + let Size { height, .. } = Terminal::size()?; for current_row in 0..height { - print!("~"); + Terminal::clear_line()?; + Terminal::print("~")?; if current_row + 1 < height { - print!("\r\n"); + Terminal::print("\r\n")?; } } Ok(()) diff --git a/src/editor/terminal.rs b/src/editor/terminal.rs index 423d342..a6e8c50 100644 --- a/src/editor/terminal.rs +++ b/src/editor/terminal.rs @@ -1,30 +1,75 @@ -use crossterm::cursor::MoveTo; -use crossterm::execute; +use crossterm::cursor::{Hide, MoveTo, Show}; +use crossterm::queue; +use crossterm::style::Print; use crossterm::terminal::{disable_raw_mode, enable_raw_mode, size, Clear, ClearType}; -use std::io::stdout; +use std::io::{stdout, Error, Write}; -pub struct Terminal {} +#[derive(Copy, Clone)] +pub struct Size { + pub height: u16, + pub width: u16, +} + +#[derive(Copy, Clone)] +pub struct Position { + pub x: u16, + pub y: u16, +} + +pub struct Terminal; impl Terminal { - pub fn terminate() -> Result<(), std::io::Error> { + pub fn terminate() -> Result<(), Error> { + Self::execute()?; disable_raw_mode()?; Ok(()) } - pub fn initialize() -> Result<(), std::io::Error> { + + pub fn initialize() -> Result<(), Error> { enable_raw_mode()?; Self::clear_screen()?; - Self::move_cursor_to(0, 0)?; + Self::move_cursor_to(Position { x: 0, y: 0 })?; + Self::execute()?; + Ok(()) + } + + pub fn clear_screen() -> Result<(), Error> { + queue!(stdout(), Clear(ClearType::All))?; Ok(()) } - pub fn clear_screen() -> Result<(), std::io::Error> { - execute!(stdout(), Clear(ClearType::All))?; + + pub fn clear_line() -> Result<(), Error> { + queue!(stdout(), Clear(ClearType::CurrentLine))?; Ok(()) } - pub fn move_cursor_to(x: u16, y: u16) -> Result<(), std::io::Error> { - execute!(stdout(), MoveTo(x, y))?; + + pub fn move_cursor_to(position: Position) -> Result<(), Error> { + queue!(stdout(), MoveTo(position.x, position.y))?; Ok(()) } - pub fn size() -> Result<(u16, u16), std::io::Error> { - size() + + pub fn hide_cursor() -> Result<(), Error> { + queue!(stdout(), Hide)?; + Ok(()) + } + + pub fn show_cursor() -> Result<(), Error> { + queue!(stdout(), Show)?; + Ok(()) + } + + pub fn print(string: &str) -> Result<(), Error> { + queue!(stdout(), Print(string))?; + Ok(()) + } + + pub fn size() -> Result { + let (width, height) = size()?; + Ok(Size { height, width }) + } + + pub fn execute() -> Result<(), Error> { + stdout().flush()?; + Ok(()) } } diff --git a/src/main.rs b/src/main.rs index 8b1a322..b26814f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -#![warn(clippy::all, clippy::pedantic)] +#![warn(clippy::all, clippy::pedantic, clippy::print_stdout)] mod editor; use editor::Editor; fn main() {