mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-21 19:26:09 +03:00
terminal/new: use new pagelist grow mechanism that prunes
This commit is contained in:
@ -258,7 +258,9 @@ pub fn scroll(self: *PageList, behavior: Scroll) void {
|
|||||||
/// This may allocate, but also may not if our current page has more
|
/// This may allocate, but also may not if our current page has more
|
||||||
/// capacity we can use. This will prune scrollback if necessary to
|
/// capacity we can use. This will prune scrollback if necessary to
|
||||||
/// adhere to max_size.
|
/// adhere to max_size.
|
||||||
pub fn grow2(self: *PageList) !?*List.Node {
|
///
|
||||||
|
/// This returns the newly allocated page node if there is one.
|
||||||
|
pub fn grow(self: *PageList) !?*List.Node {
|
||||||
const last = self.pages.last.?;
|
const last = self.pages.last.?;
|
||||||
if (last.data.capacity.rows > last.data.size.rows) {
|
if (last.data.capacity.rows > last.data.size.rows) {
|
||||||
// Fast path: we have capacity in the last page.
|
// Fast path: we have capacity in the last page.
|
||||||
@ -305,16 +307,6 @@ pub fn grow2(self: *PageList) !?*List.Node {
|
|||||||
return next_page;
|
return next_page;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Grow the page list by exactly one page and return the new page. The
|
|
||||||
/// newly allocated page will be size 0 (but capacity is set).
|
|
||||||
pub fn grow(self: *PageList) !*List.Node {
|
|
||||||
const next_page = try self.createPage();
|
|
||||||
// we don't errdefer this because we've added it to the linked
|
|
||||||
// list and its fine to have dangling unused pages.
|
|
||||||
self.pages.append(next_page);
|
|
||||||
return next_page;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a new page node. This does not add it to the list and this
|
/// Create a new page node. This does not add it to the list and this
|
||||||
/// does not do any memory size accounting with max_size/page_size.
|
/// does not do any memory size accounting with max_size/page_size.
|
||||||
fn createPage(self: *PageList) !*List.Node {
|
fn createPage(self: *PageList) !*List.Node {
|
||||||
@ -461,7 +453,7 @@ fn growRows(self: *PageList, n: usize) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (n_rem > 0) {
|
while (n_rem > 0) {
|
||||||
page = try self.grow();
|
page = (try self.grow()).?;
|
||||||
const add = @min(n_rem, page.data.capacity.rows);
|
const add = @min(n_rem, page.data.capacity.rows);
|
||||||
page.data.size.rows = add;
|
page.data.size.rows = add;
|
||||||
n_rem -= add;
|
n_rem -= add;
|
||||||
@ -847,7 +839,7 @@ test "PageList grow fit in capacity" {
|
|||||||
try testing.expect(last.size.rows < last.capacity.rows);
|
try testing.expect(last.size.rows < last.capacity.rows);
|
||||||
|
|
||||||
// Grow
|
// Grow
|
||||||
try testing.expect(try s.grow2() == null);
|
try testing.expect(try s.grow() == null);
|
||||||
{
|
{
|
||||||
const pt = s.getCell(.{ .active = .{} }).?.screenPoint();
|
const pt = s.getCell(.{ .active = .{} }).?.screenPoint();
|
||||||
try testing.expectEqual(point.Point{ .screen = .{
|
try testing.expectEqual(point.Point{ .screen = .{
|
||||||
@ -868,11 +860,11 @@ test "PageList grow allocate" {
|
|||||||
const last_node = s.pages.last.?;
|
const last_node = s.pages.last.?;
|
||||||
const last = &s.pages.last.?.data;
|
const last = &s.pages.last.?.data;
|
||||||
for (0..last.capacity.rows - last.size.rows) |_| {
|
for (0..last.capacity.rows - last.size.rows) |_| {
|
||||||
try testing.expect(try s.grow2() == null);
|
try testing.expect(try s.grow() == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grow, should allocate
|
// Grow, should allocate
|
||||||
const new = (try s.grow2()).?;
|
const new = (try s.grow()).?;
|
||||||
try testing.expect(s.pages.last.? == new);
|
try testing.expect(s.pages.last.? == new);
|
||||||
try testing.expect(last_node.next.? == new);
|
try testing.expect(last_node.next.? == new);
|
||||||
{
|
{
|
||||||
@ -897,14 +889,14 @@ test "PageList grow prune scrollback" {
|
|||||||
const page1_node = s.pages.last.?;
|
const page1_node = s.pages.last.?;
|
||||||
const page1 = page1_node.data;
|
const page1 = page1_node.data;
|
||||||
for (0..page1.capacity.rows - page1.size.rows) |_| {
|
for (0..page1.capacity.rows - page1.size.rows) |_| {
|
||||||
try testing.expect(try s.grow2() == null);
|
try testing.expect(try s.grow() == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Grow and allocate one more page. Then fill that page up.
|
// Grow and allocate one more page. Then fill that page up.
|
||||||
const page2_node = (try s.grow2()).?;
|
const page2_node = (try s.grow()).?;
|
||||||
const page2 = page2_node.data;
|
const page2 = page2_node.data;
|
||||||
for (0..page2.capacity.rows - page2.size.rows) |_| {
|
for (0..page2.capacity.rows - page2.size.rows) |_| {
|
||||||
try testing.expect(try s.grow2() == null);
|
try testing.expect(try s.grow() == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get our page size
|
// Get our page size
|
||||||
@ -912,7 +904,7 @@ test "PageList grow prune scrollback" {
|
|||||||
|
|
||||||
// Next should create a new page, but it should reuse our first
|
// Next should create a new page, but it should reuse our first
|
||||||
// page since we're at max size.
|
// page since we're at max size.
|
||||||
const new = (try s.grow2()).?;
|
const new = (try s.grow()).?;
|
||||||
try testing.expect(s.pages.last.? == new);
|
try testing.expect(s.pages.last.? == new);
|
||||||
try testing.expectEqual(s.page_size, old_page_size);
|
try testing.expectEqual(s.page_size, old_page_size);
|
||||||
|
|
||||||
|
@ -226,31 +226,14 @@ pub fn cursorAbsolute(self: *Screen, x: size.CellCountInt, y: size.CellCountInt)
|
|||||||
pub fn cursorDownScroll(self: *Screen) !void {
|
pub fn cursorDownScroll(self: *Screen) !void {
|
||||||
assert(self.cursor.y == self.pages.rows - 1);
|
assert(self.cursor.y == self.pages.rows - 1);
|
||||||
|
|
||||||
const cursor_page = self.cursor.page_offset.page;
|
// Grow our pages by one row. The PageList will handle if we need to
|
||||||
if (cursor_page.data.capacity.rows > cursor_page.data.size.rows) {
|
// allocate, prune scrollback, whatever.
|
||||||
// If we have cap space in our current cursor page then we can take
|
_ = try self.pages.grow();
|
||||||
// a fast path: update the size, recalculate the row/cell cursor pointers.
|
const page_offset = self.cursor.page_offset.forward(1).?;
|
||||||
cursor_page.data.size.rows += 1;
|
const page_rac = page_offset.rowAndCell(self.cursor.x);
|
||||||
|
self.cursor.page_offset = page_offset;
|
||||||
const page_offset = self.cursor.page_offset.forward(1).?;
|
self.cursor.page_row = page_rac.row;
|
||||||
const page_rac = page_offset.rowAndCell(self.cursor.x);
|
self.cursor.page_cell = page_rac.cell;
|
||||||
self.cursor.page_offset = page_offset;
|
|
||||||
self.cursor.page_row = page_rac.row;
|
|
||||||
self.cursor.page_cell = page_rac.cell;
|
|
||||||
} else {
|
|
||||||
// No space, we need to allocate a new page and move the cursor to it.
|
|
||||||
const new_page = try self.pages.grow();
|
|
||||||
assert(new_page.data.size.rows == 0);
|
|
||||||
new_page.data.size.rows = 1;
|
|
||||||
const page_offset: PageList.RowOffset = .{
|
|
||||||
.page = new_page,
|
|
||||||
.row_offset = 0,
|
|
||||||
};
|
|
||||||
const page_rac = page_offset.rowAndCell(self.cursor.x);
|
|
||||||
self.cursor.page_offset = page_offset;
|
|
||||||
self.cursor.page_row = page_rac.row;
|
|
||||||
self.cursor.page_cell = page_rac.cell;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The newly created line needs to be styled according to the bg color
|
// The newly created line needs to be styled according to the bg color
|
||||||
// if it is set.
|
// if it is set.
|
||||||
|
Reference in New Issue
Block a user