1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-24 07:46:59 +03:00

Add StableRowIndex concept

This will make it easier to manage both the viewport and the
selection in the gui layer.

refs: https://github.com/wez/wezterm/issues/106
This commit is contained in:
Wez Furlong 2020-01-02 22:49:04 -08:00
parent a0ad0d0c34
commit 1b3ced2ab3
3 changed files with 60 additions and 0 deletions

View File

@ -53,6 +53,20 @@ pub type VisibleRowIndex = i64;
/// to want to scroll back or select more than ~2billion lines of scrollback.
pub type ScrollbackOrVisibleRowIndex = i32;
/// Allows referencing a logical line in the scrollback, allowing for scrolling.
/// The StableRowIndex counts from the top of the scrollback, growing larger
/// as you move down through the display rows.
/// Initially the very first line as StableRowIndex==0. If the scrollback
/// is filled and lines are purged (say we need to purge 5 lines), then whichever
/// line is first in the scrollback (PhysRowIndex==0) will now have StableRowIndex==5
/// which is the same value that that logical line had prior to data being purged
/// out of the scrollback.
///
/// As per ScrollbackOrVisibleRowIndex above, a StableRowIndex can never
/// legally be a negative number. We're just using a differently sized type
/// to have the compiler assist us in detecting improper usage.
pub type StableRowIndex = isize;
/// Returns true if r1 intersects r2
pub fn intersects_range<T: Ord + Copy>(r1: Range<T>, r2: Range<T>) -> bool {
use std::cmp::{max, min};

View File

@ -19,6 +19,11 @@ pub struct Screen {
/// would otherwise have exceeded the line capacity
pub lines: VecDeque<Line>,
/// Whenever we scroll a line off the top of the scrollback, we
/// increment this. We use this offset to translate between
/// PhysRowIndex and StableRowIndex.
stable_row_index_offset: usize,
/// config so we can access Maximum number of lines of scrollback
config: Arc<dyn TerminalConfiguration>,
allow_scrollback: bool,
@ -62,6 +67,7 @@ impl Screen {
allow_scrollback,
physical_rows,
physical_cols,
stable_row_index_offset: 0,
}
}
@ -197,6 +203,27 @@ impl Screen {
self.phys_row(range.start)..self.phys_row(range.end)
}
#[inline]
pub fn phys_to_stable_row_index(&self, phys: PhysRowIndex) -> StableRowIndex {
(phys + self.stable_row_index_offset) as StableRowIndex
}
#[inline]
pub fn stable_row_to_phys(&self, stable: StableRowIndex) -> Option<PhysRowIndex> {
let idx = stable - self.stable_row_index_offset as isize;
if idx < 0 || idx >= self.lines.len() as isize {
// Index is no longer valid
None
} else {
Some(idx as PhysRowIndex)
}
}
#[inline]
pub fn visible_row_to_stable_row(&self, vis: VisibleRowIndex) -> StableRowIndex {
self.phys_to_stable_row_index(self.phys_row(vis))
}
/// ---------
/// |
/// |--- top
@ -268,6 +295,10 @@ impl Screen {
self.lines.remove(remove_idx);
}
if remove_idx == 0 {
self.stable_row_index_offset += lines_removed;
}
if scroll_region.end as usize == self.physical_rows {
// It's cheaper to push() than it is insert() at the end
for _ in 0..to_add {

View File

@ -529,20 +529,35 @@ fn test_scrollup() {
let mut term = TestTerm::new(2, 1, 4);
term.print("1\n");
assert_all_contents(&term, &["1", " "]);
assert_eq!(term.screen().visible_row_to_stable_row(0), 0);
term.print("2\n");
assert_all_contents(&term, &["1", "2", " "]);
assert_eq!(term.screen().visible_row_to_stable_row(0), 1);
term.print("3\n");
assert_all_contents(&term, &["1", "2", "3", " "]);
assert_eq!(term.screen().visible_row_to_stable_row(0), 2);
term.print("4\n");
assert_all_contents(&term, &["1", "2", "3", "4", " "]);
assert_eq!(term.screen().visible_row_to_stable_row(0), 3);
term.print("5\n");
assert_all_contents(&term, &["1", "2", "3", "4", "5", " "]);
assert_eq!(term.screen().visible_row_to_stable_row(0), 4);
term.print("6\n");
assert_all_contents(&term, &["2", "3", "4", "5", "6", " "]);
assert_eq!(term.screen().visible_row_to_stable_row(0), 5);
term.print("7\n");
assert_all_contents(&term, &["3", "4", "5", "6", "7", " "]);
assert_eq!(term.screen().visible_row_to_stable_row(0), 6);
term.print("8\n");
assert_all_contents(&term, &["4", "5", "6", "7", "8", " "]);
assert_eq!(term.screen().visible_row_to_stable_row(0), 7);
}
#[test]