From 742ed978190e6271304d0a352cd31c3606b932ab Mon Sep 17 00:00:00 2001 From: mars Date: Wed, 12 Apr 2023 17:50:14 -0400 Subject: [PATCH] Defer stdout flush until end of draw --- src/buffer.rs | 10 +++++----- src/main.rs | 26 ++++++++++++++------------ src/theme.rs | 18 ++++++++---------- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/buffer.rs b/src/buffer.rs index 2b8b67c..80bf44b 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -21,7 +21,7 @@ use std::io::Write; use std::ops::Range; use std::sync::Arc; -use crossterm::{cursor, ExecutableCommand}; +use crossterm::{cursor, ExecutableCommand, QueueableCommand}; use parking_lot::Mutex; use ropey::Rope; use syntect::easy::ScopeRangeIterator; @@ -74,7 +74,7 @@ impl Buffer { cols: u16, rows: u16, scroll: Cursor, - out: &mut (impl ExecutableCommand + Write), + out: &mut impl QueueableCommand, ) -> crossterm::Result { self.parse(); @@ -84,7 +84,7 @@ impl Buffer { let gutter_width = linenr_width + 1; let text_width = cols as usize - gutter_width as usize; - out.execute(cursor::MoveTo(0, 0))?; + out.queue(cursor::MoveTo(0, 0))?; for (row, line) in (0..rows).zip(self.text.lines_at(scroll.line)) { // only the last line is empty and should be skipped @@ -117,7 +117,7 @@ impl Buffer { } } - out.execute(cursor::MoveToNextLine(1))?; + out.queue(cursor::MoveToNextLine(1))?; } Ok(gutter_width) @@ -157,7 +157,7 @@ impl Buffer { // parse the line into a sequence of stack operations let stack_ops = parser.parse_line(&line_buf, &self.syntax_set).unwrap(); - // execute the operations on the stack + // queue the operations on the stack let mut line = Vec::new(); let range_iter = ScopeRangeIterator::new(&stack_ops, &line_buf); for (range, op) in range_iter { diff --git a/src/main.rs b/src/main.rs index 4bc85a4..84e4936 100644 --- a/src/main.rs +++ b/src/main.rs @@ -31,7 +31,7 @@ use crossbeam_channel::Sender; use crossterm::{ cursor, event::{Event, KeyCode, KeyEvent}, - terminal, ExecutableCommand, Result, + terminal, Result, QueueableCommand, }; use parking_lot::Mutex; use yacexits::{exit, EX_DATAERR, EX_UNAVAILABLE}; @@ -135,8 +135,8 @@ impl State { pub fn draw(&mut self, out: &mut impl Write) -> Result<()> { // begin update let (cols, rows) = terminal::size()?; - out.execute(terminal::BeginSynchronizedUpdate)?; - out.execute(terminal::Clear(terminal::ClearType::All))?; + out.queue(terminal::BeginSynchronizedUpdate)?; + out.queue(terminal::Clear(terminal::ClearType::All))?; let mut styles = self.styles.lock(); // draw status line @@ -147,14 +147,14 @@ impl State { Mode::Command(CommandState { buf, cursor }) => { let col = *cursor as u16 + 1; let row = rows - 1; - out.execute(cursor::MoveTo(0, row))?; + out.queue(cursor::MoveTo(0, row))?; write!(out, ":{}", buf)?; set_cursor_pos = Some((col, row)); show_status_bar = true; } Mode::Normal(NormalState { error: Some(error) }) => { let error_style = styles.get_scope("error"); - out.execute(cursor::MoveTo(0, rows - 1))?; + out.queue(cursor::MoveTo(0, rows - 1))?; error_style.print_styled(out, error)?; show_status_bar = true; } @@ -178,11 +178,13 @@ impl State { (col, row) }); - out.execute(cursor::MoveTo(cursor_pos.0, cursor_pos.1))?; - out.execute(self.mode.cursor_style())?; + out.queue(cursor::MoveTo(cursor_pos.0, cursor_pos.1))?; + out.queue(self.mode.cursor_style())?; // finish update - out.execute(terminal::EndSynchronizedUpdate)?; + out.queue(terminal::EndSynchronizedUpdate)?; + out.flush()?; + Ok(()) } @@ -246,7 +248,7 @@ impl State { } KeyCode::Enter => { // TODO add to command history - let result = self.execute_command(&state.buf); + let result = self.queue_command(&state.buf); let error = result.err(); self.mode = Mode::Normal(NormalState { error }); return; @@ -347,7 +349,7 @@ impl State { self.write_buffer(handle).map_err(|err| format!("{}", err)) } - fn execute_command(&mut self, command: &str) -> std::result::Result<(), String> { + fn queue_command(&mut self, command: &str) -> std::result::Result<(), String> { let command_parts = command.split(' ').collect::>(); let command = match command_parts.get(0) { @@ -457,9 +459,9 @@ fn main() -> Result<()> { let state = State::from_str(file_name, &text)?; let mut stdout = stdout(); terminal::enable_raw_mode()?; - stdout.execute(terminal::EnterAlternateScreen)?; + stdout.queue(terminal::EnterAlternateScreen)?; let result = screen_main(&mut stdout, state); - stdout.execute(terminal::LeaveAlternateScreen)?; + stdout.queue(terminal::LeaveAlternateScreen)?; terminal::disable_raw_mode()?; result } diff --git a/src/theme.rs b/src/theme.rs index 3723a10..b9eadb4 100644 --- a/src/theme.rs +++ b/src/theme.rs @@ -17,11 +17,10 @@ * along with this program. If not, see https://www.gnu.org/licenses/. */ -use std::io::Write; use std::{collections::HashMap, fmt::Display}; -use crossterm::{style::Color, ExecutableCommand}; -use once_cell::sync::Lazy; +use crossterm::style::Color; +use crossterm::QueueableCommand; use toml::{map::Map, Value}; #[derive(Debug, Default)] @@ -110,22 +109,21 @@ pub struct Style { impl Style { pub fn print_styled( &self, - out: &mut (impl ExecutableCommand + Write), + out: &mut impl QueueableCommand, content: impl Display, ) -> crossterm::Result<()> { - use crossterm::style::{ResetColor, SetBackgroundColor, SetForegroundColor}; + use crossterm::style::{Print, ResetColor, SetBackgroundColor, SetForegroundColor}; if let Some(fg) = self.fg { - out.execute(SetForegroundColor(fg))?; + out.queue(SetForegroundColor(fg))?; } if let Some(bg) = self.bg { - out.execute(SetBackgroundColor(bg))?; + out.queue(SetBackgroundColor(bg))?; } - write!(out, "{}", content)?; - - out.execute(ResetColor)?; + out.queue(Print(content))?; + out.queue(ResetColor)?; Ok(()) }