use Context instead of props. only import DisplayWidth when needed

This commit is contained in:
Jacob Sandlund
2025-07-04 15:23:34 -04:00
parent 8a218149dd
commit ca17f34d94
3 changed files with 55 additions and 51 deletions

View File

@ -416,8 +416,9 @@ pub fn add(
.optimize = optimize, .optimize = optimize,
})) |dep| { })) |dep| {
step.root_module.addImport("CaseFolding", dep.module("CaseFolding")); step.root_module.addImport("CaseFolding", dep.module("CaseFolding"));
// Only needed for table gen, but still include to have build succeeed if (self.config.emit_unicode_test) {
step.root_module.addImport("DisplayWidth", dep.module("DisplayWidth")); step.root_module.addImport("DisplayWidth", dep.module("DisplayWidth"));
}
step.root_module.addImport("Emoji", dep.module("Emoji")); step.root_module.addImport("Emoji", dep.module("Emoji"));
step.root_module.addImport("GeneralCategories", dep.module("GeneralCategories")); step.root_module.addImport("GeneralCategories", dep.module("GeneralCategories"));
step.root_module.addImport("Graphemes", dep.module("Graphemes")); step.root_module.addImport("Graphemes", dep.module("Graphemes"));

View File

@ -41,7 +41,7 @@ pub fn main() !void {
const args = try std.process.argsAlloc(alloc); const args = try std.process.argsAlloc(alloc);
defer std.process.argsFree(alloc, args); defer std.process.argsFree(alloc, args);
var zg = try props.init(alloc); var zg = try props.Context.init(alloc);
defer zg.deinit(alloc); defer zg.deinit(alloc);
const ziglyph = @import("ziglyph"); const ziglyph = @import("ziglyph");

View File

@ -1,30 +1,55 @@
const props = @This();
const std = @import("std"); const std = @import("std");
const assert = std.debug.assert; const assert = std.debug.assert;
const Graphemes = @import("Graphemes");
const DisplayWidth = @import("DisplayWidth");
const lut = @import("lut.zig"); const lut = @import("lut.zig");
const Graphemes = @import("Graphemes");
graphemes: Graphemes, /// The context needed for lut generation.
display_width: DisplayWidth, pub const Context = struct {
graphemes: Graphemes,
display_width: DisplayWidth,
// Whether to use the old implementation based on ziglyph. // Whether to use the old implementation based on ziglyph.
old: bool = false, old: bool = false,
// Public only for unicode-test const DisplayWidth = @import("DisplayWidth");
pub fn init(alloc: std.mem.Allocator) !props {
const graphemes = try Graphemes.init(alloc);
return .{
.graphemes = graphemes,
.display_width = try DisplayWidth.initWithGraphemes(alloc, graphemes),
};
}
// Public only for unicode-test // Public only for unicode-test
pub fn deinit(self: *props, alloc: std.mem.Allocator) void { pub fn init(alloc: std.mem.Allocator) !Context {
self.graphemes.deinit(alloc); const graphemes = try Graphemes.init(alloc);
self.display_width.deinit(alloc); return .{
} .graphemes = graphemes,
.display_width = try DisplayWidth.initWithGraphemes(alloc, graphemes),
};
}
// Public only for unicode-test
pub fn deinit(self: *Context, alloc: std.mem.Allocator) void {
self.graphemes.deinit(alloc);
self.display_width.deinit(alloc);
}
pub fn get(self: Context, cp: u21) !Properties {
if (cp > 0x10FFFF) {
return .{
.width = 0,
.grapheme_boundary_class = .invalid,
};
} else {
const zg_width = DisplayWidth.codePointWidth(self.display_width, cp);
return .{
.width = @intCast(@min(2, @max(0, zg_width))),
//.grapheme_boundary_class = .init(self, cp),
.grapheme_boundary_class = if (self.old) .initOld(cp) else .init(self, cp),
};
}
}
pub fn eql(self: Context, a: Properties, b: Properties) bool {
_ = self;
return a.eql(b);
}
};
/// The lookup tables for Ghostty. /// The lookup tables for Ghostty.
pub const table = table: { pub const table = table: {
@ -114,7 +139,7 @@ pub const GraphemeBoundaryClass = enum(u4) {
/// Gets the grapheme boundary class for a codepoint. This is VERY /// Gets the grapheme boundary class for a codepoint. This is VERY
/// SLOW. The use case for this is only in generating lookup tables. /// SLOW. The use case for this is only in generating lookup tables.
pub fn init(ctx: props, cp: u21) GraphemeBoundaryClass { pub fn init(ctx: Context, cp: u21) GraphemeBoundaryClass {
return switch (Graphemes.gbp(ctx.graphemes, cp)) { return switch (Graphemes.gbp(ctx.graphemes, cp)) {
.Emoji_Modifier_Base => .extended_pictographic_base, .Emoji_Modifier_Base => .extended_pictographic_base,
.Emoji_Modifier => .emoji_modifier, .Emoji_Modifier => .emoji_modifier,
@ -180,28 +205,6 @@ pub const GraphemeBoundaryClass = enum(u4) {
} }
}; };
pub fn get(ctx: props, cp: u21) !Properties {
if (cp > 0x10FFFF) {
return .{
.width = 0,
.grapheme_boundary_class = .invalid,
};
} else {
const zg_width = DisplayWidth.codePointWidth(ctx.display_width, cp);
return .{
.width = @intCast(@min(2, @max(0, zg_width))),
//.grapheme_boundary_class = .init(ctx, cp),
.grapheme_boundary_class = if (ctx.old) .initOld(cp) else .init(ctx, cp),
};
}
}
pub fn eql(ctx: props, a: Properties, b: Properties) bool {
_ = ctx;
return a.eql(b);
}
/// Runnable binary to generate the lookup tables and output to stdout. /// Runnable binary to generate the lookup tables and output to stdout.
pub fn main() !void { pub fn main() !void {
var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator); var arena_state = std.heap.ArenaAllocator.init(std.heap.page_allocator);
@ -211,17 +214,17 @@ pub fn main() !void {
const args = try std.process.argsAlloc(alloc); const args = try std.process.argsAlloc(alloc);
defer std.process.argsFree(alloc, args); defer std.process.argsFree(alloc, args);
var self = try init(alloc); var ctx = try Context.init(alloc);
defer self.deinit(alloc); defer ctx.deinit(alloc);
if (args.len > 1 and std.mem.eql(u8, args[1], "old")) { if (args.len > 1 and std.mem.eql(u8, args[1], "old")) {
self.old = true; ctx.old = true;
} }
const gen: lut.Generator( const gen: lut.Generator(
Properties, Properties,
props, Context,
) = .{ .ctx = self }; ) = .{ .ctx = ctx };
const t = try gen.generate(alloc); const t = try gen.generate(alloc);
defer alloc.free(t.stage1); defer alloc.free(t.stage1);