Preserve current position when new items are added to a buffer
All checks were successful
CI / lint (push) Successful in 5m3s
CI / Build and test (, 1.73.0) (push) Successful in 9m34s
CI / Build and test (, beta) (push) Successful in 9m34s
CI / Build and test (, nightly) (push) Successful in 8m46s

This commit is contained in:
2023-11-17 14:14:24 +01:00
parent 9b29d4d9e5
commit dd404147ab
5 changed files with 291 additions and 67 deletions

View File

@ -31,6 +31,23 @@ fn rect(x: u16, y: u16, width: u16, height: u16) -> Rect {
}
}
macro_rules! items_iter {
[ $($item: expr),* ] => {
|| vec![
$(
{
let BufferItem { content, prerender, unique_id } = &$item;
BufferItem {
content: content.clone(),
prerender,
unique_id: *unique_id,
}
},
)*
].into_iter()
}
}
#[test]
fn test_single_item() {
let mut bl = Backlog::default();
@ -38,9 +55,10 @@ fn test_single_item() {
let item = BufferItem {
content: BufferItemContent::Text(Text::raw("hello")),
prerender: &prerender,
unique_id: None,
};
let mut buf = Buffer::empty(rect(0, 0, 18, 8));
bl.draw_items(&mut buf, rect(3, 2, 12, 4), vec![item].into_iter())
bl.draw_items(&mut buf, rect(3, 2, 12, 4), items_iter![item])
.context("Failed to draw")
.unwrap();
@ -64,10 +82,11 @@ fn test_single_item_cached() {
let item = BufferItem {
content: BufferItemContent::Text(Text::raw("hello")),
prerender: &prerender,
unique_id: None,
};
let mut buf = Buffer::empty(rect(0, 0, 18, 8));
let area = rect(3, 2, 12, 4);
bl.draw_items(&mut buf, area, vec![item].into_iter())
bl.draw_items(&mut buf, area, items_iter![item])
.context("Failed to draw")
.unwrap();
@ -88,9 +107,10 @@ fn test_single_item_cached() {
let item = BufferItem {
content: BufferItemContent::Text(Text::raw("hello")),
prerender: &prerender,
unique_id: None,
};
let mut buf = Buffer::empty(rect(0, 0, 18, 8));
bl.draw_items(&mut buf, area, vec![item].into_iter())
bl.draw_items(&mut buf, area, items_iter![item])
.context("Failed to draw")
.unwrap();
assert_eq!(buf, expected);
@ -105,16 +125,18 @@ fn test_only_necessary_width() {
let item1 = BufferItem {
content: BufferItemContent::Text(Text::raw("hi\nworld")),
prerender: &prerender1,
unique_id: None,
};
let item2 = BufferItem {
content: BufferItemContent::Text(Text::raw(":)")),
prerender: &prerender2,
unique_id: None,
};
let mut cell = ratatui::buffer::Cell::default();
cell.set_char('.');
let mut buf = Buffer::filled(rect(0, 0, 18, 7), &cell); // poisoned buffer
let area = rect(3, 1, 12, 5);
bl.draw_items(&mut buf, area, vec![item2, item1].into_iter())
bl.draw_items(&mut buf, area, items_iter![item2, item1])
.context("Failed to draw")
.unwrap();
@ -134,13 +156,15 @@ fn test_only_necessary_width() {
let item1 = BufferItem {
content: BufferItemContent::Text(Text::raw("hi\nworld")),
prerender: &prerender1,
unique_id: None,
};
let item2 = BufferItem {
content: BufferItemContent::Text(Text::raw(":)")),
prerender: &prerender2,
unique_id: None,
};
let mut buf = Buffer::empty(rect(0, 0, 18, 7));
bl.draw_items(&mut buf, area, vec![item2, item1].into_iter())
bl.draw_items(&mut buf, area, items_iter![item2, item1])
.context("Failed to draw")
.unwrap();
let expected = Buffer::with_lines(vec![
@ -162,9 +186,10 @@ fn test_single_item_tight() {
let item = BufferItem {
content: BufferItemContent::Text(Text::raw("hello")),
prerender: &prerender,
unique_id: None,
};
let mut buf = Buffer::empty(rect(0, 0, 13, 7));
bl.draw_items(&mut buf, rect(3, 2, 7, 3), vec![item].into_iter())
bl.draw_items(&mut buf, rect(3, 2, 7, 3), items_iter![item])
.context("Failed to draw")
.unwrap();
@ -187,14 +212,16 @@ fn test_two_items() {
let item1 = BufferItem {
content: BufferItemContent::Text(Text::raw("hi")),
prerender: &prerender1,
unique_id: None,
};
let prerender2 = Prerender::new();
let item2 = BufferItem {
content: BufferItemContent::Text(Text::raw("world")),
prerender: &prerender2,
unique_id: None,
};
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(&mut buf, rect(1, 1, 12, 5), vec![item2, item1].into_iter())
bl.draw_items(&mut buf, rect(1, 1, 12, 5), items_iter![item2, item1])
.context("Failed to draw")
.unwrap();
@ -219,13 +246,15 @@ fn test_two_items_scroll() {
let item1 = BufferItem {
content: BufferItemContent::Text(Text::raw("hi")),
prerender: &prerender1,
unique_id: Some(123),
};
let item2 = BufferItem {
content: BufferItemContent::Text(Text::raw("world")),
prerender: &prerender2,
unique_id: Some(456),
};
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(&mut buf, rect(1, 1, 12, 5), vec![item2, item1].into_iter())
bl.draw_items(&mut buf, rect(1, 1, 12, 5), items_iter![item2, item1])
.context("Failed to draw")
.unwrap();
@ -245,13 +274,15 @@ fn test_two_items_scroll() {
let item1 = BufferItem {
content: BufferItemContent::Text(Text::raw("hi")),
prerender: &prerender1,
unique_id: Some(123),
};
let item2 = BufferItem {
content: BufferItemContent::Text(Text::raw("world")),
prerender: &prerender2,
unique_id: Some(456),
};
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(&mut buf, rect(1, 1, 12, 5), vec![item2, item1].into_iter())
bl.draw_items(&mut buf, rect(1, 1, 12, 5), items_iter![item2, item1])
.context("Failed to draw")
.unwrap();
@ -271,13 +302,15 @@ fn test_two_items_scroll() {
let item1 = BufferItem {
content: BufferItemContent::Text(Text::raw("hi")),
prerender: &prerender1,
unique_id: Some(123),
};
let item2 = BufferItem {
content: BufferItemContent::Text(Text::raw("world")),
prerender: &prerender2,
unique_id: Some(456),
};
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(&mut buf, rect(1, 1, 12, 5), vec![item2, item1].into_iter())
bl.draw_items(&mut buf, rect(1, 1, 12, 5), items_iter![item2, item1])
.context("Failed to draw")
.unwrap();
@ -300,14 +333,16 @@ fn test_two_items_multiline() {
let item1 = BufferItem {
content: BufferItemContent::Text(Text::raw("hi")),
prerender: &prerender1,
unique_id: None,
};
let prerender2 = Prerender::new();
let item2 = BufferItem {
content: BufferItemContent::Text(Text::raw("world\n!")),
prerender: &prerender2,
unique_id: None,
};
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(&mut buf, rect(1, 1, 12, 5), vec![item2, item1].into_iter())
bl.draw_items(&mut buf, rect(1, 1, 12, 5), items_iter![item2, item1])
.context("Failed to draw")
.unwrap();
@ -330,14 +365,16 @@ fn test_two_items_tight() {
let item1 = BufferItem {
content: BufferItemContent::Text(Text::raw("hi")),
prerender: &prerender1,
unique_id: None,
};
let prerender2 = Prerender::new();
let item2 = BufferItem {
content: BufferItemContent::Text(Text::raw("world")),
prerender: &prerender2,
unique_id: None,
};
let mut buf = Buffer::empty(rect(0, 0, 9, 6));
bl.draw_items(&mut buf, rect(1, 1, 7, 4), vec![item2, item1].into_iter())
bl.draw_items(&mut buf, rect(1, 1, 7, 4), items_iter![item2, item1])
.context("Failed to draw")
.unwrap();
@ -359,11 +396,12 @@ fn test_cache_moved() {
let item1 = BufferItem {
content: BufferItemContent::Text(Text::raw("hi")),
prerender: &prerender1,
unique_id: None,
};
// Draw once
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(&mut buf, rect(1, 1, 12, 5), vec![item1].into_iter())
bl.draw_items(&mut buf, rect(1, 1, 12, 5), items_iter![item1])
.context("Failed to draw")
.unwrap();
let expected = Buffer::with_lines(vec![
@ -381,14 +419,16 @@ fn test_cache_moved() {
let item1 = BufferItem {
content: BufferItemContent::Text(Text::raw("hi")),
prerender: &prerender1,
unique_id: None,
};
let prerender2 = Prerender::new();
let item2 = BufferItem {
content: BufferItemContent::Text(Text::raw("world")),
prerender: &prerender2,
unique_id: None,
};
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(&mut buf, rect(1, 1, 12, 5), vec![item2, item1].into_iter())
bl.draw_items(&mut buf, rect(1, 1, 12, 5), items_iter![item2, item1])
.context("Failed to draw")
.unwrap();
let expected = Buffer::with_lines(vec![
@ -413,20 +453,23 @@ fn test_overflow_and_scroll() {
let item1 = BufferItem {
content: BufferItemContent::Text(Text::raw("line1 x")),
prerender: &prerender1,
unique_id: None,
};
let item2 = BufferItem {
content: BufferItemContent::Text(Text::raw("line2 y\nline3 y\nline4 y")),
prerender: &prerender2,
unique_id: None,
};
let item3 = BufferItem {
content: BufferItemContent::Text(Text::raw("line5 z")),
prerender: &prerender3,
unique_id: None,
};
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(
&mut buf,
rect(1, 1, 12, 5),
vec![item3, item2, item1].into_iter(),
items_iter![item3, item2, item1],
)
.context("Failed to draw")
.unwrap();
@ -446,20 +489,23 @@ fn test_overflow_and_scroll() {
let item1 = BufferItem {
content: BufferItemContent::Text(Text::raw("line1 x")),
prerender: &prerender1,
unique_id: None,
};
let item2 = BufferItem {
content: BufferItemContent::Text(Text::raw("line2 y\nline3 y\nline4 y")),
prerender: &prerender2,
unique_id: None,
};
let item3 = BufferItem {
content: BufferItemContent::Text(Text::raw("line5 z")),
prerender: &prerender3,
unique_id: None,
};
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(
&mut buf,
rect(1, 1, 12, 5),
vec![item3, item2, item1].into_iter(),
items_iter![item3, item2, item1],
)
.context("Failed to draw")
.unwrap();
@ -479,20 +525,23 @@ fn test_overflow_and_scroll() {
let item1 = BufferItem {
content: BufferItemContent::Text(Text::raw("line1 x")),
prerender: &prerender1,
unique_id: None,
};
let item2 = BufferItem {
content: BufferItemContent::Text(Text::raw("line2 y\nline3 y\nline4 y")),
prerender: &prerender2,
unique_id: None,
};
let item3 = BufferItem {
content: BufferItemContent::Text(Text::raw("line5 z")),
prerender: &prerender3,
unique_id: None,
};
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(
&mut buf,
rect(1, 1, 12, 5),
vec![item3, item2, item1].into_iter(),
items_iter![item3, item2, item1],
)
.context("Failed to draw")
.unwrap();
@ -511,20 +560,23 @@ fn test_overflow_and_scroll() {
let item1 = BufferItem {
content: BufferItemContent::Text(Text::raw("line1 x")),
prerender: &prerender1,
unique_id: None,
};
let item2 = BufferItem {
content: BufferItemContent::Text(Text::raw("line2 y\nline3 y\nline4 y")),
prerender: &prerender2,
unique_id: None,
};
let item3 = BufferItem {
content: BufferItemContent::Text(Text::raw("line5 z")),
prerender: &prerender3,
unique_id: None,
};
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(
&mut buf,
rect(1, 1, 12, 5),
vec![item3, item2, item1].into_iter(),
items_iter![item3, item2, item1],
)
.context("Failed to draw")
.unwrap();
@ -539,3 +591,79 @@ fn test_overflow_and_scroll() {
]);
assert_eq!(buf, expected);
}
#[test]
fn test_scrolledup_new_line() {
let mut bl = Backlog::default();
let prerender1 = Prerender::new();
let item1 = BufferItem {
content: BufferItemContent::Text(Text::raw("hi\nworld")),
prerender: &prerender1,
unique_id: Some(123),
};
// Draw once
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(&mut buf, rect(1, 1, 12, 5), items_iter![item1])
.context("Failed to draw")
.unwrap();
let expected = Buffer::with_lines(vec![
" ",
" ┌──────────┐ ",
" │ │ ",
" │hi │ ",
" │world │ ",
" └──────────┘ ",
" ",
]);
assert_eq!(buf, expected);
// Scroll up one line
bl.scroll_up(1);
let item1 = BufferItem {
content: BufferItemContent::Text(Text::raw("hi\nworld")),
prerender: &prerender1,
unique_id: Some(123),
};
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(&mut buf, rect(1, 1, 12, 5), items_iter![item1])
.context("Failed to draw")
.unwrap();
let expected = Buffer::with_lines(vec![
" ",
" ┌──────────┐ ",
" │ │ ",
" │ │ ",
" │hi │ ",
" └──────────┘ ",
" ",
]);
assert_eq!(buf, expected);
// New item added at bottom, displayed paragraph should not move up
let item1 = BufferItem {
content: BufferItemContent::Text(Text::raw("hi\nworld")),
prerender: &prerender1,
unique_id: Some(123),
};
let prerender2 = Prerender::new();
let item2 = BufferItem {
content: BufferItemContent::Text(Text::raw("!")),
prerender: &prerender2,
unique_id: Some(456),
};
let mut buf = Buffer::empty(rect(0, 0, 14, 7));
bl.draw_items(&mut buf, rect(1, 1, 12, 5), items_iter![item2, item1])
.context("Failed to draw")
.unwrap();
let expected = Buffer::with_lines(vec![
" ",
" ┌──────────┐ ",
" │ │ ",
" │ │ ",
" │hi │ ",
" └──────────┘ ",
" ",
]);
assert_eq!(buf, expected);
}