mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-08-05 23:28:41 +00:00
This commit represents the majority of the work necessary to upgrade Ghostty to use Zig 0.16.0. Key parts: * In addition to its previous responsibilities, the global state now houses state for global I/O implementations and the process environment. It is now also utilized in the main application along with the C library. Where necessary, global state is isolated from key parts of the implementation (e.g., in libghostty subsystems), and it's expected that this list will grow. * We currently manage our own C translation layer where necessary. In these cases, cImport has been removed in favor of the new external translate-c package. Due to fixes that have needed be made to properly translate the dependencies that were swapped out, as mentioned, we have had to backport fixes from the current translate-c package (and the upstream Arocc dependency). We will host this ourselves until Zig 0.17.0 is released with these fixes. * Where necessary (only a small number of cases), some stdlib code from 0.15.2 (and even from 0.17.0) has been taken, adopted, and vendored in lib/compat. Co-authored-by: Leah Amelia Chen <hi@pluie.me>
139 lines
4.5 KiB
Zig
139 lines
4.5 KiB
Zig
const std = @import("std");
|
|
const assert = std.debug.assert;
|
|
const config = @import("config.zig");
|
|
|
|
const Allocator = std.mem.Allocator;
|
|
|
|
pub const fields = &config.mergeFields(config.fields, &.{
|
|
.{ .name = "width", .type = u2 },
|
|
.{ .name = "is_symbol", .type = bool },
|
|
});
|
|
pub const build_components = &config.mergeComponents(config.build_components, &.{
|
|
.{
|
|
.Impl = WidthComponent,
|
|
.inputs = &.{
|
|
"wcwidth_standalone",
|
|
"wcwidth_zero_in_grapheme",
|
|
"is_emoji_modifier",
|
|
"grapheme_break_no_control",
|
|
},
|
|
.fields = &.{"width"},
|
|
},
|
|
.{
|
|
.Impl = IsSymbolComponent,
|
|
.inputs = &.{ "block", "general_category" },
|
|
.fields = &.{"is_symbol"},
|
|
},
|
|
});
|
|
|
|
pub const get_components: []const config.Component = &.{};
|
|
|
|
pub const tables = [_]config.Table{
|
|
.{
|
|
.name = "runtime",
|
|
.fields = &.{
|
|
"is_emoji_presentation",
|
|
"case_folding_full",
|
|
},
|
|
},
|
|
.{
|
|
// Fields that libvaxis needs that aren't included in the `runtime`
|
|
// table.
|
|
.name = "libvaxis_only",
|
|
.fields = &.{
|
|
"east_asian_width",
|
|
"general_category",
|
|
"grapheme_break",
|
|
},
|
|
},
|
|
.{
|
|
.name = "buildtime",
|
|
.fields = &.{
|
|
"width",
|
|
"wcwidth_zero_in_grapheme",
|
|
"grapheme_break_no_control",
|
|
"is_symbol",
|
|
"is_emoji_vs_base",
|
|
},
|
|
},
|
|
};
|
|
|
|
const WidthComponent = struct {
|
|
pub fn build(
|
|
comptime InputRow: type,
|
|
comptime Row: type,
|
|
allocator: std.mem.Allocator,
|
|
io: std.Io,
|
|
inputs: config.MultiSlice(InputRow),
|
|
rows: *config.MultiSlice(Row),
|
|
backing: anytype,
|
|
tracking: anytype,
|
|
) !void {
|
|
_ = allocator;
|
|
_ = io;
|
|
_ = backing;
|
|
_ = tracking;
|
|
|
|
rows.len = config.num_code_points;
|
|
const items = rows.items(.width);
|
|
const standalone = inputs.items(.wcwidth_standalone);
|
|
const zero_in_grapheme = inputs.items(.wcwidth_zero_in_grapheme);
|
|
const is_emoji_modifier = inputs.items(.is_emoji_modifier);
|
|
const grapheme_break_no_control = inputs.items(.grapheme_break_no_control);
|
|
|
|
// This condition is needed as Ghostty currently has a singular concept for
|
|
// the `width` of a code point, while `uucode` splits the concept into
|
|
// `wcwidth_standalone` and `wcwidth_zero_in_grapheme`. The two cases where
|
|
// we want to use the `wcwidth_standalone` despite the code point occupying
|
|
// zero width in a grapheme (`wcwidth_zero_in_grapheme`) are emoji
|
|
// modifiers and prepend code points. For emoji modifiers we want to
|
|
// support displaying them in isolation as color patches, and if prepend
|
|
// characters were to be width 0 they would disappear from the output with
|
|
// Ghostty's current width 0 handling. Future work will take advantage of
|
|
// the new uucode `wcwidth_standalone` vs `wcwidth_zero_in_grapheme` split.
|
|
for (0..config.num_code_points) |i| {
|
|
if (zero_in_grapheme[i] and !is_emoji_modifier[i] and grapheme_break_no_control[i] != .prepend) {
|
|
items[i] = 0;
|
|
} else {
|
|
items[i] = @min(2, standalone[i]);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
const IsSymbolComponent = struct {
|
|
pub fn build(
|
|
comptime InputRow: type,
|
|
comptime Row: type,
|
|
allocator: std.mem.Allocator,
|
|
io: std.Io,
|
|
inputs: config.MultiSlice(InputRow),
|
|
rows: *config.MultiSlice(Row),
|
|
backing: anytype,
|
|
tracking: anytype,
|
|
) !void {
|
|
_ = allocator;
|
|
_ = io;
|
|
_ = backing;
|
|
_ = tracking;
|
|
|
|
rows.len = config.num_code_points;
|
|
const items = rows.items(.is_symbol);
|
|
const block = inputs.items(.block);
|
|
const general_category = inputs.items(.general_category);
|
|
|
|
for (0..config.num_code_points) |i| {
|
|
items[i] =
|
|
general_category[i] == .other_private_use or
|
|
block[i] == .arrows or
|
|
block[i] == .dingbats or
|
|
block[i] == .emoticons or
|
|
block[i] == .miscellaneous_symbols or
|
|
block[i] == .enclosed_alphanumerics or
|
|
block[i] == .enclosed_alphanumeric_supplement or
|
|
block[i] == .miscellaneous_symbols_and_pictographs or
|
|
block[i] == .transport_and_map_symbols;
|
|
}
|
|
}
|
|
};
|