Fix reflow of empty wrapped cursor line

This bug was caused by trying to grow the terminal while the cursor line
was wrapped but entirely empty. Resizing the terminal now accounts for
the position of the deleted line and moves the cursor up only when the
line deleted was above it.

The deletion of the line was caused by the shell redrawing itself
whenever the cursor is moved.

Fixes #3583.
This commit is contained in:
Christian Duerr 2020-07-01 06:58:06 +00:00 committed by GitHub
parent 8688e47ddb
commit bc60782e42
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 20 additions and 10 deletions

View File

@ -52,6 +52,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Regression in font rendering on macOS
- Scroll down escape (`CSI Ps T`) incorrectly pulling lines from history
- Dim escape (`CSI 2 m`) support for truecolor text
- Incorrectly deleted lines when increasing width with a prompt wrapped using spaces
## 0.4.3

View File

@ -187,11 +187,6 @@ impl<T: GridCell + Default + PartialEq + Copy> Grid<T> {
Point { line: self.lines.0 + self.display_offset - point.line.0 - 1, col: point.col }
}
/// Return the cursor position in buffer coordinates.
pub fn cursor_buffer_point(&self) -> Point<usize> {
Point { line: self.lines.0 - self.cursor.point.line.0 - 1, col: self.cursor.point.col }
}
/// Update the size of the scrollback history.
pub fn update_history(&mut self, history_size: usize) {
let current_history_size = self.history_size();

View File

@ -67,10 +67,12 @@ impl<T: GridCell + Default + PartialEq + Copy> Grid<T> {
self.scroll_up(&(Line(0)..self.lines), Line(required_scrolling), T::default());
// Clamp cursors to the new viewport size.
self.saved_cursor.point.line = min(self.saved_cursor.point.line, target - 1);
self.cursor.point.line = min(self.cursor.point.line, target - 1);
}
// Clamp saved cursor, since only primary cursor is scrolled into viewport.
self.saved_cursor.point.line = min(self.saved_cursor.point.line, target - 1);
self.raw.rotate((self.lines - target).0 as isize);
self.raw.shrink_visible_lines(target);
self.lines = target;
@ -135,7 +137,8 @@ impl<T: GridCell + Default + PartialEq + Copy> Grid<T> {
// Reflow cells to previous row.
last_row.append(&mut cells);
if row.is_empty() {
let cursor_buffer_line = (self.lines - self.cursor.point.line - 1).0;
if row.is_clear() && (i != cursor_buffer_line || row.len() == 0) {
if i + reversed.len() < self.lines.0 {
// Add new line and move everything up if we can't pull from history.
self.saved_cursor.point.line.0 = self.saved_cursor.point.line.saturating_sub(1);
@ -144,6 +147,16 @@ impl<T: GridCell + Default + PartialEq + Copy> Grid<T> {
} else {
// Since we removed a line, rotate down the viewport.
self.display_offset = self.display_offset.saturating_sub(1);
// Rotate cursors down if content below them was pulled from history.
if i < cursor_buffer_line {
self.cursor.point.line += 1;
}
let saved_buffer_line = (self.lines - self.saved_cursor.point.line - 1).0;
if i < saved_buffer_line {
self.saved_cursor.point.line += 1;
}
}
// Don't push line into the new buffer.

View File

@ -130,8 +130,9 @@ impl<T> Row<T> {
self.inner = vec;
}
/// Check if all cells in the row are empty.
#[inline]
pub fn is_empty(&self) -> bool
pub fn is_clear(&self) -> bool
where
T: GridCell,
{

View File

@ -1775,7 +1775,7 @@ impl<T: EventListener> Handler for Term<T> {
},
}
let cursor_buffer_line = self.grid.cursor_buffer_point().line;
let cursor_buffer_line = (self.grid.num_lines() - self.grid.cursor.point.line - 1).0;
self.selection = self
.selection
.take()
@ -1858,7 +1858,7 @@ impl<T: EventListener> Handler for Term<T> {
let template = self.grid.cursor.template;
let num_lines = self.grid.num_lines().0;
let cursor_buffer_line = self.grid.cursor_buffer_point().line;
let cursor_buffer_line = num_lines - self.grid.cursor.point.line.0 - 1;
match mode {
ansi::ClearMode::Above => {