terminal: updating render state with tests
parent
3f7cee1e99
commit
a860801323
|
|
@ -42,7 +42,7 @@ pub const RenderState = struct {
|
|||
/// area and scrolling with new output.
|
||||
viewport_is_bottom: bool,
|
||||
|
||||
/// The rows (y=0 is top) of the viewport.
|
||||
/// The rows (y=0 is top) of the viewport. Guaranteed to be `rows` length.
|
||||
///
|
||||
/// This is a MultiArrayList because only the update cares about
|
||||
/// the allocators. Callers care about all the other properties, and
|
||||
|
|
@ -75,7 +75,7 @@ pub const RenderState = struct {
|
|||
/// Arena used for any heap allocations for this row,
|
||||
arena: ArenaAllocator.State,
|
||||
|
||||
/// The cells in this row, always `cols` length.
|
||||
/// The cells in this row. Guaranteed to be `cols` length.
|
||||
cells: std.MultiArrayList(Cell),
|
||||
|
||||
/// A dirty flag that can be used by the renderer to track
|
||||
|
|
@ -113,7 +113,8 @@ pub const RenderState = struct {
|
|||
alloc: Allocator,
|
||||
t: *Terminal,
|
||||
) Allocator.Error!void {
|
||||
self.redraw = redraw: {
|
||||
const s: *Screen = t.screens.active;
|
||||
const redraw = redraw: {
|
||||
// If our screen key changed, we need to do a full rebuild
|
||||
// because our render state is viewport-specific.
|
||||
if (t.screens.active_key != self.screen) break :redraw true;
|
||||
|
|
@ -134,17 +135,23 @@ pub const RenderState = struct {
|
|||
if (v > 0) break :redraw true;
|
||||
}
|
||||
|
||||
// If our dimensions changed, we do a full rebuild.
|
||||
if (self.rows != s.pages.rows or
|
||||
self.cols != s.pages.cols)
|
||||
{
|
||||
break :redraw true;
|
||||
}
|
||||
|
||||
break :redraw false;
|
||||
};
|
||||
|
||||
// Full redraw resets our state completely.
|
||||
if (self.redraw) {
|
||||
if (redraw) {
|
||||
self.* = .empty;
|
||||
self.screen = t.screens.active_key;
|
||||
self.redraw = true;
|
||||
}
|
||||
|
||||
const s: *Screen = t.screens.active;
|
||||
|
||||
// Always set our cheap fields, its more expensive to compare
|
||||
self.rows = s.pages.rows;
|
||||
self.cols = s.pages.cols;
|
||||
|
|
@ -186,7 +193,7 @@ pub const RenderState = struct {
|
|||
var y: size.CellCountInt = 0;
|
||||
while (row_it.next()) |row_pin| : (y = y + 1) {
|
||||
// If the row isn't dirty then we assume it is unchanged.
|
||||
if (!self.redraw and !row_pin.isDirty()) continue;
|
||||
if (!redraw and !row_pin.isDirty()) continue;
|
||||
|
||||
// Promote our arena. State is copied by value so we need to
|
||||
// restore it on all exit paths so we don't leak memory.
|
||||
|
|
@ -306,3 +313,32 @@ test {
|
|||
defer state.deinit(alloc);
|
||||
try state.update(alloc, &t);
|
||||
}
|
||||
|
||||
test "basic text" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
|
||||
var t = try Terminal.init(alloc, .{
|
||||
.cols = 10,
|
||||
.rows = 3,
|
||||
});
|
||||
defer t.deinit(alloc);
|
||||
|
||||
var s = t.vtStream();
|
||||
defer s.deinit();
|
||||
try s.nextSlice("ABCD");
|
||||
|
||||
var state: RenderState = .empty;
|
||||
defer state.deinit(alloc);
|
||||
try state.update(alloc, &t);
|
||||
|
||||
// Verify we have the right number of rows
|
||||
const row_data = state.row_data.slice();
|
||||
try testing.expectEqual(3, row_data.len);
|
||||
|
||||
// All rows should have cols cells
|
||||
const cells = row_data.items(.cells);
|
||||
try testing.expectEqual(10, cells[0].len);
|
||||
try testing.expectEqual(10, cells[1].len);
|
||||
try testing.expectEqual(10, cells[2].len);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue