our new resize without reflow supports scrollback so test that

This commit is contained in:
Mitchell Hashimoto
2022-08-31 21:29:28 -07:00
parent 4056f2abf9
commit 89e931e468
2 changed files with 57 additions and 22 deletions

View File

@ -554,25 +554,23 @@ fn scrollDelta(self: *Screen, delta: isize, grow: bool) !void {
}
}
// If we can fit into our capacity, then just grow to it.
if (rows_final <= self.rowsCapacity()) {
// Ensure we have "written" this data into the circular buffer.
_ = self.storage.getPtrSlice(
self.viewport * (self.cols + 1),
self.cols + 1,
);
return;
}
// If we can't fit our rows into our capacity, we delete some scrollback.
const rows_deleted = if (rows_final > self.rowsCapacity()) deleted: {
const rows_to_delete = rows_final - self.rowsCapacity();
self.viewport -= rows_to_delete;
self.storage.deleteOldest(rows_to_delete * (self.cols + 1));
// We can't fit our new rows into the capacity, so the amount
// between what we need and the capacity needs to be deleted. We
// scroll "up" by that much to offset this.
const rows_to_delete = rows_final - self.rowsCapacity();
self.viewport -= rows_to_delete;
self.storage.deleteOldest(rows_to_delete * (self.cols + 1));
// If we grew down like this, we must be at the bottom.
assert(self.viewportIsBottom());
// If we grew down like this, we must be at the bottom.
assert(self.viewportIsBottom());
break :deleted rows_to_delete;
} else 0;
// Ensure we have "written" our last row so that it shows up
_ = self.storage.getPtrSlice(
(rows_final - rows_deleted - 1) * (self.cols + 1),
self.cols + 1,
);
}
/// Returns the raw text associated with a selection. This will unwrap
@ -763,6 +761,9 @@ pub fn resizeWithoutReflow(self: *Screen, rows: usize, cols: usize) !void {
self.cursor.x = @minimum(self.cursor.x, self.cols - 1);
self.cursor.y = @minimum(self.cursor.y, self.rows - 1);
// Our viewport resets to the top because we're going to rewrite the screen
self.viewport = 0;
// Rewrite all our rows
var y: usize = 0;
var row_it = old.rowIterator(.screen);
@ -954,11 +955,6 @@ test "Screen: scrolling" {
try s.scroll(.{ .delta = 1 });
try testing.expect(s.viewportIsBottom());
// Test our row index
try testing.expectEqual(@as(usize, 0), s.rowOffset(.{ .active = 0 }));
try testing.expectEqual(@as(usize, 6), s.rowOffset(.{ .active = 1 }));
try testing.expectEqual(@as(usize, 12), s.rowOffset(.{ .active = 2 }));
{
// Test our contents rotated
var contents = try s.testString(alloc, .viewport);
@ -1378,3 +1374,38 @@ test "Screen: resize (no reflow) less cols" {
try testing.expectEqualStrings(expected, contents);
}
}
test "Screen: resize (no reflow) more rows with scrollback" {
const testing = std.testing;
const alloc = testing.allocator;
var s = try init(alloc, 3, 5, 2);
defer s.deinit();
const str = "1ABCD\n2EFGH\n3IJKL\n4ABCD\n5EFGH";
try s.testWriteString(str);
try s.resizeWithoutReflow(10, 5);
{
var contents = try s.testString(alloc, .viewport);
defer alloc.free(contents);
try testing.expectEqualStrings(str, contents);
}
}
test "Screen: resize (no reflow) less rows with scrollback" {
const testing = std.testing;
const alloc = testing.allocator;
var s = try init(alloc, 3, 5, 2);
defer s.deinit();
const str = "1ABCD\n2EFGH\n3IJKL\n4ABCD\n5EFGH";
try s.testWriteString(str);
try s.resizeWithoutReflow(2, 5);
{
var contents = try s.testString(alloc, .screen);
defer alloc.free(contents);
const expected = "2EFGH\n3IJKL\n4ABCD\n5EFGH";
try testing.expectEqualStrings(expected, contents);
}
}

View File

@ -112,6 +112,10 @@ pub fn CircBuf(comptime T: type, comptime default: T) type {
/// Delete the oldest n values from the buffer. If there are less
/// than n values in the buffer, it'll delete everything.
pub fn deleteOldest(self: *Self, n: usize) void {
// Clear the values back to default
const slices = self.getPtrSlice(0, n);
for (slices) |slice| std.mem.set(T, slice, default);
// If we're not full, we can just advance the tail. We know
// it'll be less than the length because otherwise we'd be full.
self.tail += @minimum(self.len(), n);