aboutsummaryrefslogtreecommitdiff
path: root/vendor/libghostty-vt/src/unicode/props_uucode.zig
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-04-04 19:22:04 +0300
committerCan Celik <ogulcancelik@gmail.com>2026-04-05 01:23:06 +0300
commit41dd733ca7123c9ac4bfc6c781697a660e95b052 (patch)
tree3fc91815ca139ef2e0b281bba0abda4ef15175f4 /vendor/libghostty-vt/src/unicode/props_uucode.zig
parent55c138263e190a1e79d4b997bfb9397306c0ec1f (diff)
feat: finish ghostty pane backend integration
Diffstat (limited to 'vendor/libghostty-vt/src/unicode/props_uucode.zig')
-rw-r--r--vendor/libghostty-vt/src/unicode/props_uucode.zig85
1 files changed, 85 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/src/unicode/props_uucode.zig b/vendor/libghostty-vt/src/unicode/props_uucode.zig
new file mode 100644
index 00000000..527a757e
--- /dev/null
+++ b/vendor/libghostty-vt/src/unicode/props_uucode.zig
@@ -0,0 +1,85 @@
+const props = @This();
+const std = @import("std");
+const assert = std.debug.assert;
+const uucode = @import("uucode");
+const lut = @import("lut.zig");
+const Properties = @import("props.zig").Properties;
+
+pub fn get(cp: u21) Properties {
+ if (cp > uucode.config.max_code_point) return .{
+ .width = 1,
+ .width_zero_in_grapheme = true,
+ .grapheme_break = .other,
+ .emoji_vs_base = false,
+ };
+
+ return .{
+ .width = uucode.get(.width, cp),
+ .width_zero_in_grapheme = uucode.get(.wcwidth_zero_in_grapheme, cp),
+ .grapheme_break = uucode.get(.grapheme_break_no_control, cp),
+ .emoji_vs_base = uucode.get(.is_emoji_vs_base, cp),
+ };
+}
+
+/// Runnable binary to generate the lookup tables and output to stdout.
+pub fn main() !void {
+ var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator);
+ defer arena_state.deinit();
+ const alloc = arena_state.allocator();
+
+ const gen: lut.Generator(
+ Properties,
+ struct {
+ pub fn get(ctx: @This(), cp: u21) !Properties {
+ _ = ctx;
+ return props.get(cp);
+ }
+
+ pub fn eql(ctx: @This(), a: Properties, b: Properties) bool {
+ _ = ctx;
+ return a.eql(b);
+ }
+ },
+ ) = .{};
+
+ const t = try gen.generate(alloc);
+ defer alloc.free(t.stage1);
+ defer alloc.free(t.stage2);
+ defer alloc.free(t.stage3);
+
+ var buf: [4096]u8 = undefined;
+ var stdout = std.fs.File.stdout().writer(&buf);
+ try t.writeZig(&stdout.interface);
+ // Use flush instead of end because stdout is a pipe when captured by
+ // the build system, and pipes cannot be truncated (Windows returns
+ // INVALID_PARAMETER, Linux returns EINVAL).
+ try stdout.interface.flush();
+
+ // Uncomment when manually debugging to see our table sizes.
+ // std.log.warn("stage1={} stage2={} stage3={}", .{
+ // t.stage1.len,
+ // t.stage2.len,
+ // t.stage3.len,
+ // });
+}
+
+test "unicode props: tables match uucode" {
+ if (std.valgrind.runningOnValgrind() > 0) return error.SkipZigTest;
+
+ const testing = std.testing;
+ const table = @import("props_table.zig").table;
+
+ const min = 0xFF + 1; // start outside ascii
+ const max = std.math.maxInt(u21) + 1;
+ for (min..max) |cp| {
+ const t = table.get(@intCast(cp));
+ const uu = if (cp > uucode.config.max_code_point)
+ 1
+ else
+ uucode.get(.width, @intCast(cp));
+ if (t.width != uu) {
+ std.log.warn("mismatch cp=U+{x} t={} uu={}", .{ cp, t.width, uu });
+ try testing.expect(false);
+ }
+ }
+}