terminal: add a test to verify our grapheme state is what we expect

This commit is contained in:
Mitchell Hashimoto
2023-08-15 13:55:35 -07:00
parent c5439ca516
commit 6a4b25714a
2 changed files with 75 additions and 1 deletions

View File

@ -489,12 +489,19 @@ pub const Row = struct {
return .{ .row = self };
}
/// Returns the number of codepoints in the cell at column x,
/// including the primary codepoint.
pub fn codepointLen(self: Row, x: usize) usize {
var it = self.codepointIterator(x);
return it.len() + 1;
}
/// Read-only iterator for the grapheme codepoints in a cell. This only
/// iterates over the EXTRA GRAPHEME codepoints and not the primary
/// codepoint in cell.char.
pub fn codepointIterator(self: Row, x: usize) CodepointIterator {
const cell = &self.storage[x + 1].cell;
assert(cell.attrs.grapheme);
if (!cell.attrs.grapheme) return .{ .data = .{ .zero = {} } };
const key = self.getId() + x + 1;
const data: GraphemeData = self.screen.graphemes.get(key) orelse data: {
@ -543,6 +550,18 @@ pub const CodepointIterator = struct {
data: GraphemeData,
i: usize = 0,
/// Returns the number of codepoints in the iterator.
pub fn len(self: CodepointIterator) usize {
switch (self.data) {
.zero => return 0,
.one => return 1,
.two => return 2,
.three => return 3,
.four => return 4,
.many => |v| return v.len,
}
}
pub fn next(self: *CodepointIterator) ?u21 {
switch (self.data) {
.zero => return null,

View File

@ -1630,6 +1630,61 @@ test "Terminal: print over wide char at 0,0" {
try testing.expectEqual(@as(usize, 1), t.screen.cursor.x);
}
test "Terminal: print multicodepoint grapheme" {
var t = try init(testing.allocator, 80, 80);
defer t.deinit(testing.allocator);
// https://github.com/mitchellh/ghostty/issues/289
// This is: 👨👩👧 (which may or may not render correctly)
try t.print(0x1F468);
try t.print(0x200D);
try t.print(0x1F469);
try t.print(0x200D);
try t.print(0x1F467);
// We should have 6 cells taken up
try testing.expectEqual(@as(usize, 0), t.screen.cursor.y);
try testing.expectEqual(@as(usize, 6), t.screen.cursor.x);
// Assert various properties about our screen to verify
// we have all expected cells.
const row = t.screen.getRow(.{ .screen = 0 });
{
const cell = row.getCell(0);
try testing.expectEqual(@as(u32, 0x1F468), cell.char);
try testing.expect(cell.attrs.wide);
try testing.expectEqual(@as(usize, 2), row.codepointLen(0));
}
{
const cell = row.getCell(1);
try testing.expectEqual(@as(u32, ' '), cell.char);
try testing.expect(cell.attrs.wide_spacer_tail);
try testing.expectEqual(@as(usize, 1), row.codepointLen(1));
}
{
const cell = row.getCell(2);
try testing.expectEqual(@as(u32, 0x1F469), cell.char);
try testing.expect(cell.attrs.wide);
try testing.expectEqual(@as(usize, 2), row.codepointLen(2));
}
{
const cell = row.getCell(3);
try testing.expectEqual(@as(u32, ' '), cell.char);
try testing.expect(cell.attrs.wide_spacer_tail);
}
{
const cell = row.getCell(4);
try testing.expectEqual(@as(u32, 0x1F467), cell.char);
try testing.expect(cell.attrs.wide);
try testing.expectEqual(@as(usize, 1), row.codepointLen(4));
}
{
const cell = row.getCell(5);
try testing.expectEqual(@as(u32, ' '), cell.char);
try testing.expect(cell.attrs.wide_spacer_tail);
}
}
test "Terminal: soft wrap" {
var t = try init(testing.allocator, 3, 80);
defer t.deinit(testing.allocator);