mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-10-06 01:46:33 +00:00
terminal/kitty: starting virtual placement iterator
This commit is contained in:
@@ -4,10 +4,64 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const testing = std.testing;
|
||||
const terminal = @import("../main.zig");
|
||||
|
||||
/// Codepoint for the unicode placeholder character.
|
||||
pub const placeholder: u21 = 0x10EEEE;
|
||||
|
||||
/// Returns an iterator that iterates over all of the virtual placements
|
||||
/// in the given pin. If `limit` is provided, the iterator will stop
|
||||
/// when it reaches that pin (inclusive). If `limit` is not provided,
|
||||
/// the iterator will continue until the end of the page list.
|
||||
pub fn placementIterator(
|
||||
pin: terminal.Pin,
|
||||
limit: ?terminal.Pin,
|
||||
) PlacementIterator {
|
||||
var row_it = pin.rowIterator(.right_down, limit);
|
||||
const row = row_it.next();
|
||||
return .{ .row_it = row_it, .row = row };
|
||||
}
|
||||
|
||||
/// Iterator over unicode virtual placements.
|
||||
pub const PlacementIterator = struct {
|
||||
row_it: terminal.PageList.RowIterator,
|
||||
row: ?terminal.Pin,
|
||||
|
||||
pub fn next(self: *PlacementIterator) ?Placement {
|
||||
while (self.row) |*row| {
|
||||
// A row must have graphemes to possibly have virtual placements
|
||||
// since virtual placements are done via diacritics.
|
||||
if (row.rowAndCell().row.grapheme) {
|
||||
// Iterate over our remaining cells and find one with a placeholder.
|
||||
const cells = row.cells(.right);
|
||||
for (cells, row.x..) |cell, x| {
|
||||
if (cell.codepoint() != placeholder) continue;
|
||||
|
||||
if (x == cells.len - 1) {
|
||||
// We are at the end of this row so move to the next row
|
||||
self.row = self.row_it.next();
|
||||
} else {
|
||||
// We can move right to the next cell.
|
||||
row.x = @intCast(x + 1);
|
||||
}
|
||||
|
||||
// TODO
|
||||
return .{};
|
||||
}
|
||||
}
|
||||
|
||||
// We didn't find any placements. Move to the next row.
|
||||
self.row = self.row_it.next();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
/// A virtual placement in the terminal. This can represent more than
|
||||
/// one cell if the cells combine to be a run.
|
||||
pub const Placement = struct {};
|
||||
|
||||
/// Get the row/col index for a diacritic codepoint. These are 0-indexed.
|
||||
pub fn getIndex(cp: u21) ?usize {
|
||||
return std.sort.binarySearch(u21, cp, diacritics, {}, (struct {
|
||||
@@ -324,7 +378,7 @@ const diacritics: []const u21 = &.{
|
||||
0x1D244,
|
||||
};
|
||||
|
||||
test "sorted" {
|
||||
test "unicode diacritic sorted" {
|
||||
// diacritics must be sorted since we use a binary search.
|
||||
try testing.expect(std.sort.isSorted(u21, diacritics, {}, (struct {
|
||||
fn lessThan(context: void, lhs: u21, rhs: u21) bool {
|
||||
@@ -334,8 +388,44 @@ test "sorted" {
|
||||
}).lessThan));
|
||||
}
|
||||
|
||||
test "diacritic" {
|
||||
test "unicode diacritic" {
|
||||
// Some spot checks based on Kitty behavior
|
||||
try testing.expectEqual(30, getIndex(0x483).?);
|
||||
try testing.expectEqual(294, getIndex(0x1d242).?);
|
||||
}
|
||||
|
||||
test "unicode placement: none" {
|
||||
const alloc = testing.allocator;
|
||||
var t = try terminal.Terminal.init(alloc, .{ .rows = 5, .cols = 5 });
|
||||
defer t.deinit(alloc);
|
||||
t.modes.set(.grapheme_cluster, true);
|
||||
|
||||
// Single cell
|
||||
try t.printString("hello\nworld\n1\n2");
|
||||
|
||||
// No placements
|
||||
const pin = t.screen.pages.getTopLeft(.viewport);
|
||||
var it = placementIterator(pin, null);
|
||||
try testing.expect(it.next() == null);
|
||||
}
|
||||
|
||||
test "unicode placement: single" {
|
||||
const alloc = testing.allocator;
|
||||
var t = try terminal.Terminal.init(alloc, .{ .rows = 5, .cols = 5 });
|
||||
defer t.deinit(alloc);
|
||||
t.modes.set(.grapheme_cluster, true);
|
||||
|
||||
// Single cell
|
||||
try t.printString("\u{10EEEE}\u{0305}\u{0305}");
|
||||
|
||||
// Get our top left pin
|
||||
const pin = t.screen.pages.getTopLeft(.viewport);
|
||||
|
||||
// Should have exactly one placement
|
||||
var it = placementIterator(pin, null);
|
||||
{
|
||||
const p = it.next().?;
|
||||
_ = p;
|
||||
}
|
||||
try testing.expect(it.next() == null);
|
||||
}
|
||||
|
Reference in New Issue
Block a user