From 6bb51cb73f4b69f7b3e7766fbc7d6763147f659e Mon Sep 17 00:00:00 2001 From: Daniel Somerfield Date: Sun, 3 Dec 2023 11:57:08 -0800 Subject: [PATCH 1/3] First shot at resolving the resizing issues with terminals --- src/painting/painter.rs | 31 ++++++++----------------------- src/painting/prompt_lines.rs | 1 + 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/src/painting/painter.rs b/src/painting/painter.rs index e6dc79a8..44c9fb55 100644 --- a/src/painting/painter.rs +++ b/src/painting/painter.rs @@ -82,7 +82,7 @@ impl Painter { /// Returns the available lines from the prompt down pub fn remaining_lines(&self) -> u16 { - self.screen_height() - self.prompt_start_row + self.screen_height().saturating_sub(self.prompt_start_row) } /// Sets the prompt origin position and screen size for a new line editor @@ -400,31 +400,16 @@ impl Painter { /// Updates prompt origin and offset to handle a screen resize event pub(crate) fn handle_resize(&mut self, width: u16, height: u16) { - let prev_terminal_size = self.terminal_size; - let prev_prompt_row = self.prompt_start_row; - self.terminal_size = (width, height); - if prev_prompt_row < height - && height <= prev_terminal_size.1 - && width == prev_terminal_size.0 - { - // The terminal got smaller in height but the start of the prompt is still visible - // The width didn't change - return; + // `cursor::position() is blocking and can timeout. + // The question is whether we can afford it. If not, perhaps we should use it in some scenarios but not others + // The problem is trying to calculate this internally doesn't seem to be reliable because terminals might + // have additional text in their buffer that messes with the offset on scroll. + // It seems like it _should_ be ok because it only happens on resize + if let Ok(position) = cursor::position() { + self.prompt_start_row = position.1; } - - // Either: - // - The terminal got larger in height - // - Note: if the terminal doesn't have sufficient history, this will leave a trail - // of previous prompts currently. - // - Note: if the the prompt contains multiple lines, this will leave a trail of - // previous prompts currently. - // - The terminal got smaller in height and the whole prompt is no longer visible - // - Note: if the the prompt contains multiple lines, this will leave a trail of - // previous prompts currently. - // - The width changed - self.prompt_start_row = height.saturating_sub(1); } /// Writes `line` to the terminal with a following carriage return and newline diff --git a/src/painting/prompt_lines.rs b/src/painting/prompt_lines.rs index 30c1ca61..aa9c35de 100644 --- a/src/painting/prompt_lines.rs +++ b/src/painting/prompt_lines.rs @@ -7,6 +7,7 @@ use crate::{ use std::borrow::Cow; /// Aggregate of prompt and input string used by `Painter` +#[derive(Debug)] pub(crate) struct PromptLines<'prompt> { pub(crate) prompt_str_left: Cow<'prompt, str>, pub(crate) prompt_str_right: Cow<'prompt, str>, From 6f1dd80c7eea06dc6a25966557363562308a761a Mon Sep 17 00:00:00 2001 From: Daniel Somerfield Date: Sun, 3 Dec 2023 12:02:26 -0800 Subject: [PATCH 2/3] Comment for known bug --- src/painting/painter.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/painting/painter.rs b/src/painting/painter.rs index 44c9fb55..8313f010 100644 --- a/src/painting/painter.rs +++ b/src/painting/painter.rs @@ -406,7 +406,13 @@ impl Painter { // The question is whether we can afford it. If not, perhaps we should use it in some scenarios but not others // The problem is trying to calculate this internally doesn't seem to be reliable because terminals might // have additional text in their buffer that messes with the offset on scroll. - // It seems like it _should_ be ok because it only happens on resize + // It seems like it _should_ be ok because it only happens on resize. + + // Known bug: on iterm2 and kitty, clearing the screen via CMD-K doesn't reset + // the position. Might need to special-case this. + // + // I assume this is a bug with the position() call but haven't figured that + // out yet. if let Ok(position) = cursor::position() { self.prompt_start_row = position.1; } From 6f6cb9292f587cb5d5bcec3636084ced79cbfc95 Mon Sep 17 00:00:00 2001 From: Daniel Somerfield Date: Tue, 5 Dec 2023 20:33:23 -0800 Subject: [PATCH 3/3] Checking the start row repeatedly to see how it affects performance --- src/painting/painter.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/painting/painter.rs b/src/painting/painter.rs index 8313f010..bee86429 100644 --- a/src/painting/painter.rs +++ b/src/painting/painter.rs @@ -151,8 +151,14 @@ impl Painter { // Marking the painter state as larger buffer to avoid animations self.large_buffer = required_lines >= screen_height; + // This might not be terribly performant. Testing it out + let is_reset = || match cursor::position() { + Ok(position) => position.1 < self.prompt_start_row, + Err(_) => false, + }; + // Moving the start position of the cursor based on the size of the required lines - if self.large_buffer { + if self.large_buffer || is_reset() { self.prompt_start_row = 0; } else if required_lines >= remaining_lines { let extra = required_lines.saturating_sub(remaining_lines);