From 9faa5d3aa48f7a94ed87e61ad6ea659579f1311a Mon Sep 17 00:00:00 2001 From: mo8it Date: Thu, 5 Sep 2024 17:45:27 +0200 Subject: [PATCH] Avoid asking for terminal size on each rendering --- src/watch.rs | 8 +++++--- src/watch/state.rs | 26 ++++++++++++++++++++------ src/watch/terminal_event.rs | 4 ++-- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/watch.rs b/src/watch.rs index bca38321..900eba7c 100644 --- a/src/watch.rs +++ b/src/watch.rs @@ -29,7 +29,7 @@ mod terminal_event; enum WatchEvent { Input(InputEvent), FileChange { exercise_ind: usize }, - TerminalResize, + TerminalResize { width: u16 }, NotifyErr(notify::Error), TerminalEventErr(io::Error), } @@ -72,7 +72,7 @@ fn run_watch( None }; - let mut watch_state = WatchState::new(app_state, manual_run); + let mut watch_state = WatchState::build(app_state, manual_run)?; let mut stdout = io::stdout().lock(); watch_state.run_current_exercise(&mut stdout)?; @@ -96,7 +96,9 @@ fn run_watch( WatchEvent::FileChange { exercise_ind } => { watch_state.handle_file_change(exercise_ind, &mut stdout)?; } - WatchEvent::TerminalResize => watch_state.render(&mut stdout)?, + WatchEvent::TerminalResize { width } => { + watch_state.update_term_width(width, &mut stdout)?; + } WatchEvent::NotifyErr(e) => return Err(Error::from(e).context(NOTIFY_ERR)), WatchEvent::TerminalEventErr(e) => { return Err(Error::from(e).context("Terminal event listener failed")); diff --git a/src/watch/state.rs b/src/watch/state.rs index 75a0c9e1..e66cbeeb 100644 --- a/src/watch/state.rs +++ b/src/watch/state.rs @@ -1,4 +1,4 @@ -use anyhow::Result; +use anyhow::{Context, Result}; use crossterm::{ style::{ Attribute, Attributes, Color, ResetColor, SetAttribute, SetAttributes, SetForegroundColor, @@ -27,17 +27,23 @@ pub struct WatchState<'a> { show_hint: bool, done_status: DoneStatus, manual_run: bool, + term_width: u16, } impl<'a> WatchState<'a> { - pub fn new(app_state: &'a mut AppState, manual_run: bool) -> Self { - Self { + pub fn build(app_state: &'a mut AppState, manual_run: bool) -> Result { + let term_width = terminal::size() + .context("Failed to get the terminal size")? + .0; + + Ok(Self { app_state, output: Vec::with_capacity(OUTPUT_CAPACITY), show_hint: false, done_status: DoneStatus::Pending, manual_run, - } + term_width, + }) } pub fn run_current_exercise(&mut self, stdout: &mut StdoutLock) -> Result<()> { @@ -175,12 +181,11 @@ impl<'a> WatchState<'a> { )?; } - let line_width = terminal::size()?.0; progress_bar( stdout, self.app_state.n_done(), self.app_state.exercises().len() as u16, - line_width, + self.term_width, )?; stdout.write_all(b"\nCurrent exercise: ")?; @@ -202,4 +207,13 @@ impl<'a> WatchState<'a> { Ok(()) } + + pub fn update_term_width(&mut self, width: u16, stdout: &mut StdoutLock) -> io::Result<()> { + if self.term_width != width { + self.term_width = width; + self.render(stdout)?; + } + + Ok(()) + } } diff --git a/src/watch/terminal_event.rs b/src/watch/terminal_event.rs index 07621519..ca3a8464 100644 --- a/src/watch/terminal_event.rs +++ b/src/watch/terminal_event.rs @@ -43,8 +43,8 @@ pub fn terminal_event_handler(tx: Sender, manual_run: bool) { return; } } - Event::Resize(_, _) => { - if tx.send(WatchEvent::TerminalResize).is_err() { + Event::Resize(width, _) => { + if tx.send(WatchEvent::TerminalResize { width }).is_err() { return; } }