diff options
| author | sl0p <sl0p@sl0p.foo> | 2026-08-13 22:00:03 +0200 |
|---|---|---|
| committer | sl0p <sl0p@sl0p.foo> | 2026-08-13 22:00:03 +0200 |
| commit | 2c1b855c3cf8cf8841bf25cd939e478a7f0bfac8 (patch) | |
| tree | 7cd6274303ba1da1f8bd57371aec336dd687fb58 /vendor/libghostty-vt/src/simd/codepoint_width.zig | |
| download | slosh-2c1b855c3cf8cf8841bf25cd939e478a7f0bfac8.tar.gz slosh-2c1b855c3cf8cf8841bf25cd939e478a7f0bfac8.tar.xz slosh-2c1b855c3cf8cf8841bf25cd939e478a7f0bfac8.zip | |
sl0ptty: M0 — libghostty-vt vendored, one pane, compositor, diff renderer
Design contract in DESIGN.md. libghostty-vt vendored fresh from ghostty
main@bedb6f2 (zig 0.16), built to a 14MB static lib.
M0: pty spawn (no libutil), a lib-vt terminal per pane, a screen cell buffer,
a diff emitter that repaints only what changed, raw mode, SIGWINCH, and a
~120Hz frame cap that coalesces pty reads.
Also the seed of the headless harness: --headless dumps the composited screen
without a tty, so composition is testable in milliseconds.
tests/live_m0.py covers what headless cannot: raw mode, the diff emitter,
resize propagation, and the quit path. 6/6 green.
Diffstat (limited to 'vendor/libghostty-vt/src/simd/codepoint_width.zig')
| -rw-r--r-- | vendor/libghostty-vt/src/simd/codepoint_width.zig | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/src/simd/codepoint_width.zig b/vendor/libghostty-vt/src/simd/codepoint_width.zig new file mode 100644 index 0000000..c1767be --- /dev/null +++ b/vendor/libghostty-vt/src/simd/codepoint_width.zig @@ -0,0 +1,52 @@ +const std = @import("std"); +const options = @import("build_options"); + +// vt.cpp +extern "c" fn ghostty_simd_codepoint_width(u32) i8; + +pub fn codepointWidth(cp: u32) i8 { + if (comptime options.simd) return ghostty_simd_codepoint_width(cp); + const uucode = @import("uucode"); + if (cp > uucode.config.max_code_point) return 1; + return @import("uucode").get(.width, @intCast(cp)); +} + +test "codepointWidth basic" { + const testing = std.testing; + try testing.expectEqual(@as(i8, 1), codepointWidth('a')); + try testing.expectEqual(@as(i8, 1), codepointWidth(0x100)); // Ā + try testing.expectEqual(@as(i8, 2), codepointWidth(0x3400)); // 㐀 + try testing.expectEqual(@as(i8, 2), codepointWidth(0x2E3A)); // ⸺ + try testing.expectEqual(@as(i8, 2), codepointWidth(0x1F1E6)); // 🇦 + try testing.expectEqual(@as(i8, 2), codepointWidth(0x4E00)); // 一 + try testing.expectEqual(@as(i8, 2), codepointWidth(0xF900)); // 豈 + try testing.expectEqual(@as(i8, 2), codepointWidth(0x20000)); // 𠀀 + try testing.expectEqual(@as(i8, 2), codepointWidth(0x30000)); // 𠀀 + // try testing.expectEqual(@as(i8, 1), @import("uucode").get(.width, 0x100)); +} + +// This is not very fast in debug modes, so its commented by default. +// IMPORTANT: UNCOMMENT THIS WHENEVER MAKING CODEPOINTWIDTH CHANGES. +// test "codepointWidth matches uucode" { +// const testing = std.testing; +// const uucode = @import("uucode"); +// +// const min = 0xFF + 1; // start outside ascii +// const max = std.math.maxInt(u21) + 1; +// for (min..max) |cp| { +// const simd = codepointWidth(@intCast(cp)); +// const uu = if (cp > uucode.config.max_code_point) +// 1 +// else +// uucode.get(.width, @intCast(cp)); +// if (simd != uu) mismatch: { +// if (cp == 0x2E3B) { +// try testing.expectEqual(@as(i8, 2), simd); +// break :mismatch; +// } +// +// std.log.warn("mismatch cp=U+{x} simd={} uucode={}", .{ cp, simd, uu }); +// try testing.expect(false); +// } +// } +// } |
