terminal/new: copy graphemes for reflow

This commit is contained in:
Mitchell Hashimoto
2024-03-03 22:25:52 -08:00
parent e83936701d
commit ac007221b3
2 changed files with 104 additions and 2 deletions

View File

@ -6643,6 +6643,7 @@ test "Screen: resize more cols no reflow preserves semantic prompt" {
}
}
// X
test "Screen: resize more cols grapheme map" {
const testing = std.testing;
const alloc = testing.allocator;
@ -7139,6 +7140,7 @@ test "Screen: resize less cols trailing background colors" {
}
}
// X
test "Screen: resize less cols with graphemes" {
const testing = std.testing;
const alloc = testing.allocator;

View File

@ -714,12 +714,29 @@ fn reflowPage(
.codepoint => {
dst_cursor.page_cell.* = src_cursor.page_cell.*;
// TODO: style copy
},
else => @panic("TODO"),
.codepoint_grapheme => {
// We copy the cell like normal but we have to reset the
// tag because this is used for fast-path detection in
// appendGrapheme.
dst_cursor.page_cell.* = src_cursor.page_cell.*;
dst_cursor.page_cell.content_tag = .codepoint;
// Copy the graphemes
const src_cps = src_cursor.page.lookupGrapheme(src_cursor.page_cell).?;
for (src_cps) |cp| {
try dst_cursor.page.appendGrapheme(
dst_cursor.page_row,
dst_cursor.page_cell,
cp,
);
}
},
}
// TODO: style copy
// If our original cursor was on this page, this x/y then
// we need to update to the new location.
if (cursor) |c| cursor: {
@ -3253,6 +3270,89 @@ test "PageList resize reflow less cols wrapped rows" {
}
}
test "PageList resize reflow less cols wrapped rows with graphemes" {
const testing = std.testing;
const alloc = testing.allocator;
var s = try init(alloc, 4, 2, null);
defer s.deinit();
{
try testing.expect(s.pages.first == s.pages.last);
const page = &s.pages.first.?.data;
for (0..s.rows) |y| {
for (0..s.cols) |x| {
const rac = page.getRowAndCell(x, y);
rac.cell.* = .{
.content_tag = .codepoint,
.content = .{ .codepoint = @intCast(x) },
};
}
const rac = page.getRowAndCell(2, y);
try page.appendGrapheme(rac.row, rac.cell, 'A');
}
}
// Resize
try s.resize(.{ .cols = 2, .reflow = true });
try testing.expectEqual(@as(usize, 2), s.cols);
try testing.expectEqual(@as(usize, 4), s.totalRows());
// Active moves due to scrollback
{
const pt = s.getCell(.{ .active = .{} }).?.screenPoint();
try testing.expectEqual(point.Point{ .screen = .{
.x = 0,
.y = 2,
} }, pt);
}
try testing.expect(s.pages.first == s.pages.last);
const page = &s.pages.first.?.data;
var it = s.rowIterator(.{ .screen = .{} }, null);
{
// First row should be wrapped
const offset = it.next().?;
const rac = offset.rowAndCell(0);
const cells = offset.page.data.getCells(rac.row);
try testing.expect(rac.row.wrap);
try testing.expectEqual(@as(usize, 2), cells.len);
try testing.expectEqual(@as(u21, 0), cells[0].content.codepoint);
}
{
const offset = it.next().?;
const rac = offset.rowAndCell(0);
const cells = offset.page.data.getCells(rac.row);
try testing.expect(!rac.row.wrap);
try testing.expectEqual(@as(usize, 2), cells.len);
try testing.expectEqual(@as(u21, 2), cells[0].content.codepoint);
const cps = page.lookupGrapheme(rac.cell).?;
try testing.expectEqual(@as(usize, 1), cps.len);
try testing.expectEqual(@as(u21, 'A'), cps[0]);
}
{
// First row should be wrapped
const offset = it.next().?;
const rac = offset.rowAndCell(0);
const cells = offset.page.data.getCells(rac.row);
try testing.expect(rac.row.wrap);
try testing.expectEqual(@as(usize, 2), cells.len);
try testing.expectEqual(@as(u21, 0), cells[0].content.codepoint);
}
{
const offset = it.next().?;
const rac = offset.rowAndCell(0);
const cells = offset.page.data.getCells(rac.row);
try testing.expect(!rac.row.wrap);
try testing.expectEqual(@as(usize, 2), cells.len);
try testing.expectEqual(@as(u21, 2), cells[0].content.codepoint);
const cps = page.lookupGrapheme(rac.cell).?;
try testing.expectEqual(@as(usize, 1), cps.len);
try testing.expectEqual(@as(u21, 'A'), cps[0]);
}
}
test "PageList resize reflow less cols cursor in wrapped row" {
const testing = std.testing;
const alloc = testing.allocator;