zg: complete replacement of ziglyph with zg
This commit is contained in:
parent
9fec6f122b
commit
8a71cd4c85
11 changed files with 88 additions and 79 deletions
10
build.zig
10
build.zig
|
@ -6,10 +6,6 @@ pub fn build(b: *std.Build) void {
|
||||||
const root_source_file = b.path("src/main.zig");
|
const root_source_file = b.path("src/main.zig");
|
||||||
|
|
||||||
// Dependencies
|
// Dependencies
|
||||||
const ziglyph_dep = b.dependency("ziglyph", .{
|
|
||||||
.optimize = optimize,
|
|
||||||
.target = target,
|
|
||||||
});
|
|
||||||
const zg_dep = b.dependency("zg", .{
|
const zg_dep = b.dependency("zg", .{
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
.target = target,
|
.target = target,
|
||||||
|
@ -33,8 +29,9 @@ pub fn build(b: *std.Build) void {
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
vaxis_mod.addImport("ziglyph", ziglyph_dep.module("ziglyph"));
|
vaxis_mod.addImport("code_point", zg_dep.module("code_point"));
|
||||||
vaxis_mod.addImport("grapheme", zg_dep.module("grapheme"));
|
vaxis_mod.addImport("grapheme", zg_dep.module("grapheme"));
|
||||||
|
vaxis_mod.addImport("DisplayWidth", zg_dep.module("DisplayWidth"));
|
||||||
vaxis_mod.addImport("zigimg", zigimg_dep.module("zigimg"));
|
vaxis_mod.addImport("zigimg", zigimg_dep.module("zigimg"));
|
||||||
vaxis_mod.addImport("gap_buffer", gap_buffer_dep.module("gap_buffer"));
|
vaxis_mod.addImport("gap_buffer", gap_buffer_dep.module("gap_buffer"));
|
||||||
vaxis_mod.addImport("znvim", znvim_dep.module("znvim"));
|
vaxis_mod.addImport("znvim", znvim_dep.module("znvim"));
|
||||||
|
@ -71,8 +68,9 @@ pub fn build(b: *std.Build) void {
|
||||||
.target = target,
|
.target = target,
|
||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
tests.root_module.addImport("ziglyph", ziglyph_dep.module("ziglyph"));
|
tests.root_module.addImport("code_point", zg_dep.module("code_point"));
|
||||||
tests.root_module.addImport("grapheme", zg_dep.module("grapheme"));
|
tests.root_module.addImport("grapheme", zg_dep.module("grapheme"));
|
||||||
|
tests.root_module.addImport("DisplayWidth", zg_dep.module("DisplayWidth"));
|
||||||
tests.root_module.addImport("zigimg", zigimg_dep.module("zigimg"));
|
tests.root_module.addImport("zigimg", zigimg_dep.module("zigimg"));
|
||||||
tests.root_module.addImport("gap_buffer", gap_buffer_dep.module("gap_buffer"));
|
tests.root_module.addImport("gap_buffer", gap_buffer_dep.module("gap_buffer"));
|
||||||
tests.root_module.addImport("znvim", znvim_dep.module("znvim"));
|
tests.root_module.addImport("znvim", znvim_dep.module("znvim"));
|
||||||
|
|
|
@ -4,13 +4,9 @@
|
||||||
.paths = .{""},
|
.paths = .{""},
|
||||||
.minimum_zig_version = "0.12.0-dev.3397+43edd53c3",
|
.minimum_zig_version = "0.12.0-dev.3397+43edd53c3",
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
.ziglyph = .{
|
|
||||||
.url = "git+https://codeberg.org/dude_the_builder/ziglyph/#947ed39203bf90412e3d16cbcf936518b6f23af0",
|
|
||||||
.hash = "12208b23d1eb6dcb929e85346524db8f8b8aa1401bdf8a97dee1e0cfb55da8d5fb42",
|
|
||||||
},
|
|
||||||
.zigimg = .{
|
.zigimg = .{
|
||||||
.url = "git+https://github.com/zigimg/zigimg#8873f29fc449e1b63400e9f4ad86d3c76204f962",
|
.url = "git+https://github.com/zigimg/zigimg#637974e2d31dcdbc33f1e9cc8ffb2e46abd2e215",
|
||||||
.hash = "122019f6439545235af116d0d8eb81fde1ff05fdb070da57c723772c557f84c5bf39",
|
.hash = "122012026c3a65ff1d4acba3b3fe80785f7cee9c6b4cdaff7ed0fbf23b0a6c803989",
|
||||||
},
|
},
|
||||||
.gap_buffer = .{
|
.gap_buffer = .{
|
||||||
.url = "https://github.com/ryleelyman/GapBuffer.zig/archive/6a746497d5a2494026d0f471e42556f1f153f153.tar.gz",
|
.url = "https://github.com/ryleelyman/GapBuffer.zig/archive/6a746497d5a2494026d0f471e42556f1f153f153.tar.gz",
|
||||||
|
|
22
src/Key.zig
22
src/Key.zig
|
@ -1,6 +1,5 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const ziglyph = @import("ziglyph");
|
|
||||||
|
|
||||||
const Key = @This();
|
const Key = @This();
|
||||||
|
|
||||||
|
@ -101,25 +100,12 @@ pub fn matchText(self: Key, cp: u21, mods: Modifiers) bool {
|
||||||
|
|
||||||
var self_mods = self.mods;
|
var self_mods = self.mods;
|
||||||
self_mods.num_lock = false;
|
self_mods.num_lock = false;
|
||||||
|
self_mods.shift = false;
|
||||||
|
self_mods.caps_lock = false;
|
||||||
var arg_mods = mods;
|
var arg_mods = mods;
|
||||||
arg_mods.num_lock = false;
|
arg_mods.num_lock = false;
|
||||||
var code = cp;
|
arg_mods.shift = false;
|
||||||
// if the passed codepoint is upper, we consume all shift and caps mods for
|
arg_mods.caps_lock = false;
|
||||||
// checking
|
|
||||||
if (ziglyph.isUpper(cp)) {
|
|
||||||
// consume mods
|
|
||||||
self_mods.shift = false;
|
|
||||||
self_mods.caps_lock = false;
|
|
||||||
arg_mods.shift = false;
|
|
||||||
arg_mods.caps_lock = false;
|
|
||||||
} else if (mods.shift or mods.caps_lock) {
|
|
||||||
// uppercase the cp and consume all mods
|
|
||||||
code = ziglyph.toUpper(cp);
|
|
||||||
self_mods.shift = false;
|
|
||||||
self_mods.caps_lock = false;
|
|
||||||
arg_mods.shift = false;
|
|
||||||
arg_mods.caps_lock = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf: [4]u8 = undefined;
|
var buf: [4]u8 = undefined;
|
||||||
const n = std.unicode.utf8Encode(cp, buf[0..]) catch return false;
|
const n = std.unicode.utf8Encode(cp, buf[0..]) catch return false;
|
||||||
|
|
|
@ -20,7 +20,12 @@ pub fn Loop(comptime T: type) type {
|
||||||
pub fn run(self: *Self) !void {
|
pub fn run(self: *Self) !void {
|
||||||
if (self.thread) |_| return;
|
if (self.thread) |_| return;
|
||||||
if (self.vaxis.tty == null) self.vaxis.tty = try Tty.init();
|
if (self.vaxis.tty == null) self.vaxis.tty = try Tty.init();
|
||||||
self.thread = try std.Thread.spawn(.{}, Tty.run, .{ &self.vaxis.tty.?, T, self });
|
self.thread = try std.Thread.spawn(.{}, Tty.run, .{
|
||||||
|
&self.vaxis.tty.?,
|
||||||
|
T,
|
||||||
|
self,
|
||||||
|
&self.vaxis.unicode.grapheme_data,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// stops reading from the tty and returns it to it's initial state
|
/// stops reading from the tty and returns it to it's initial state
|
||||||
|
|
|
@ -3,8 +3,8 @@ const testing = std.testing;
|
||||||
const Event = @import("event.zig").Event;
|
const Event = @import("event.zig").Event;
|
||||||
const Key = @import("Key.zig");
|
const Key = @import("Key.zig");
|
||||||
const Mouse = @import("Mouse.zig");
|
const Mouse = @import("Mouse.zig");
|
||||||
const CodePointIterator = @import("ziglyph").CodePointIterator;
|
const code_point = @import("code_point");
|
||||||
const graphemeBreak = @import("ziglyph").graphemeBreak;
|
const grapheme = @import("grapheme");
|
||||||
|
|
||||||
const log = std.log.scoped(.parser);
|
const log = std.log.scoped(.parser);
|
||||||
|
|
||||||
|
@ -59,6 +59,8 @@ const State = enum {
|
||||||
// text-as-codepoints
|
// text-as-codepoints
|
||||||
buf: [128]u8 = undefined,
|
buf: [128]u8 = undefined,
|
||||||
|
|
||||||
|
grapheme_data: *const grapheme.GraphemeData,
|
||||||
|
|
||||||
pub fn parse(self: *Parser, input: []const u8) !Result {
|
pub fn parse(self: *Parser, input: []const u8) !Result {
|
||||||
const n = input.len;
|
const n = input.len;
|
||||||
|
|
||||||
|
@ -104,15 +106,15 @@ pub fn parse(self: *Parser, input: []const u8) !Result {
|
||||||
},
|
},
|
||||||
0x7F => .{ .codepoint = Key.backspace },
|
0x7F => .{ .codepoint = Key.backspace },
|
||||||
else => blk: {
|
else => blk: {
|
||||||
var iter: CodePointIterator = .{ .bytes = input[i..] };
|
var iter: code_point.Iterator = .{ .bytes = input[i..] };
|
||||||
// return null if we don't have a valid codepoint
|
// return null if we don't have a valid codepoint
|
||||||
var cp = iter.next() orelse return .{ .event = null, .n = 0 };
|
var cp = iter.next() orelse return .{ .event = null, .n = 0 };
|
||||||
|
|
||||||
var code = cp.code;
|
var code = cp.code;
|
||||||
i += cp.len - 1; // subtract one for the loop iter
|
i += cp.len - 1; // subtract one for the loop iter
|
||||||
var g_state: u3 = 0;
|
var g_state: grapheme.State = .{};
|
||||||
while (iter.next()) |next_cp| {
|
while (iter.next()) |next_cp| {
|
||||||
if (graphemeBreak(cp.code, next_cp.code, &g_state)) {
|
if (grapheme.graphemeBreak(cp.code, next_cp.code, self.grapheme_data, &g_state)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
code = Key.multicodepoint;
|
code = Key.multicodepoint;
|
||||||
|
|
|
@ -5,6 +5,7 @@ const Loop = @import("Loop.zig").Loop;
|
||||||
const Parser = @import("Parser.zig");
|
const Parser = @import("Parser.zig");
|
||||||
const GraphemeCache = @import("GraphemeCache.zig");
|
const GraphemeCache = @import("GraphemeCache.zig");
|
||||||
const ctlseqs = @import("ctlseqs.zig");
|
const ctlseqs = @import("ctlseqs.zig");
|
||||||
|
const grapheme = @import("grapheme");
|
||||||
|
|
||||||
const log = std.log.scoped(.tty);
|
const log = std.log.scoped(.tty);
|
||||||
|
|
||||||
|
@ -58,6 +59,7 @@ pub fn run(
|
||||||
self: *Tty,
|
self: *Tty,
|
||||||
comptime Event: type,
|
comptime Event: type,
|
||||||
loop: *Loop(Event),
|
loop: *Loop(Event),
|
||||||
|
grapheme_data: *const grapheme.GraphemeData,
|
||||||
) !void {
|
) !void {
|
||||||
|
|
||||||
// get our initial winsize
|
// get our initial winsize
|
||||||
|
@ -105,7 +107,9 @@ pub fn run(
|
||||||
// initialize a grapheme cache
|
// initialize a grapheme cache
|
||||||
var cache: GraphemeCache = .{};
|
var cache: GraphemeCache = .{};
|
||||||
|
|
||||||
var parser: Parser = .{};
|
var parser: Parser = .{
|
||||||
|
.grapheme_data = grapheme_data,
|
||||||
|
};
|
||||||
|
|
||||||
// initialize the read buffer
|
// initialize the read buffer
|
||||||
var buf: [1024]u8 = undefined;
|
var buf: [1024]u8 = undefined;
|
||||||
|
|
|
@ -1,23 +1,25 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const grapheme = @import("grapheme");
|
const grapheme = @import("grapheme");
|
||||||
|
const DisplayWidth = @import("DisplayWidth");
|
||||||
|
|
||||||
/// A thin wrapper around zg data
|
/// A thin wrapper around zg data
|
||||||
const Unicode = @This();
|
const Unicode = @This();
|
||||||
|
|
||||||
grapheme_data: grapheme.GraphemeData,
|
grapheme_data: grapheme.GraphemeData,
|
||||||
|
width_data: DisplayWidth.DisplayWidthData,
|
||||||
|
|
||||||
/// initialize all unicode data vaxis may possibly need
|
/// initialize all unicode data vaxis may possibly need
|
||||||
pub fn init(alloc: std.mem.Allocator) !Unicode {
|
pub fn init(alloc: std.mem.Allocator) !Unicode {
|
||||||
const grapheme_data = try grapheme.GraphemeData.init(alloc);
|
|
||||||
|
|
||||||
return .{
|
return .{
|
||||||
.grapheme_data = grapheme_data,
|
.grapheme_data = try grapheme.GraphemeData.init(alloc),
|
||||||
|
.width_data = try DisplayWidth.DisplayWidthData.init(alloc),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// free all data
|
/// free all data
|
||||||
pub fn deinit(self: *Unicode) void {
|
pub fn deinit(self: *const Unicode) void {
|
||||||
self.grapheme_data.deinit();
|
self.grapheme_data.deinit();
|
||||||
|
self.width_data.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// creates a grapheme iterator based on str
|
/// creates a grapheme iterator based on str
|
||||||
|
|
|
@ -261,7 +261,7 @@ pub fn render(self: *Vaxis) !void {
|
||||||
if (cell.char.width != 0) break :blk cell.char.width;
|
if (cell.char.width != 0) break :blk cell.char.width;
|
||||||
|
|
||||||
const method: gwidth.Method = self.caps.unicode;
|
const method: gwidth.Method = self.caps.unicode;
|
||||||
const width = gwidth.gwidth(cell.char.grapheme, method) catch 1;
|
const width = gwidth.gwidth(cell.char.grapheme, method, &self.unicode.width_data) catch 1;
|
||||||
break :blk @max(1, width);
|
break :blk @max(1, width);
|
||||||
};
|
};
|
||||||
std.debug.assert(w > 0);
|
std.debug.assert(w > 0);
|
||||||
|
|
|
@ -4,6 +4,7 @@ const Screen = @import("Screen.zig");
|
||||||
const Cell = @import("Cell.zig");
|
const Cell = @import("Cell.zig");
|
||||||
const Mouse = @import("Mouse.zig");
|
const Mouse = @import("Mouse.zig");
|
||||||
const Segment = @import("Cell.zig").Segment;
|
const Segment = @import("Cell.zig").Segment;
|
||||||
|
const Unicode = @import("Unicode.zig");
|
||||||
const gw = @import("gwidth.zig");
|
const gw = @import("gwidth.zig");
|
||||||
|
|
||||||
const log = std.log.scoped(.window);
|
const log = std.log.scoped(.window);
|
||||||
|
@ -200,7 +201,7 @@ pub fn clear(self: Window) void {
|
||||||
|
|
||||||
/// returns the width of the grapheme. This depends on the terminal capabilities
|
/// returns the width of the grapheme. This depends on the terminal capabilities
|
||||||
pub fn gwidth(self: Window, str: []const u8) usize {
|
pub fn gwidth(self: Window, str: []const u8) usize {
|
||||||
return gw.gwidth(str, self.screen.width_method) catch 1;
|
return gw.gwidth(str, self.screen.width_method, &self.screen.unicode.width_data) catch 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// fills the window with the provided cell
|
/// fills the window with the provided cell
|
||||||
|
@ -270,7 +271,7 @@ pub fn print(self: Window, segments: []Segment, opts: PrintOptions) !PrintResult
|
||||||
var iter = self.screen.unicode.graphemeIterator(segment.text);
|
var iter = self.screen.unicode.graphemeIterator(segment.text);
|
||||||
while (iter.next()) |grapheme| {
|
while (iter.next()) |grapheme| {
|
||||||
if (row >= self.height) break :blk true;
|
if (row >= self.height) break :blk true;
|
||||||
const s = grapheme.slice(segment.text);
|
const s = grapheme.bytes(segment.text);
|
||||||
if (std.mem.eql(u8, s, "\n")) {
|
if (std.mem.eql(u8, s, "\n")) {
|
||||||
row += 1;
|
row += 1;
|
||||||
col = 0;
|
col = 0;
|
||||||
|
@ -350,9 +351,9 @@ pub fn print(self: Window, segments: []Segment, opts: PrintOptions) !PrintResult
|
||||||
else
|
else
|
||||||
word;
|
word;
|
||||||
defer soft_wrapped = false;
|
defer soft_wrapped = false;
|
||||||
var iter = self.screen.unicode.graphemeIterator(segment.text);
|
var iter = self.screen.unicode.graphemeIterator(printed_word);
|
||||||
while (iter.next()) |grapheme| {
|
while (iter.next()) |grapheme| {
|
||||||
const s = grapheme.slice(printed_word);
|
const s = grapheme.bytes(printed_word);
|
||||||
const w = self.gwidth(s);
|
const w = self.gwidth(s);
|
||||||
if (opts.commit) self.writeCell(col, row, .{
|
if (opts.commit) self.writeCell(col, row, .{
|
||||||
.char = .{
|
.char = .{
|
||||||
|
@ -405,7 +406,7 @@ pub fn print(self: Window, segments: []Segment, opts: PrintOptions) !PrintResult
|
||||||
var iter = self.screen.unicode.graphemeIterator(segment.text);
|
var iter = self.screen.unicode.graphemeIterator(segment.text);
|
||||||
while (iter.next()) |grapheme| {
|
while (iter.next()) |grapheme| {
|
||||||
if (col >= self.width) break :blk true;
|
if (col >= self.width) break :blk true;
|
||||||
const s = grapheme.slice(segment.text);
|
const s = grapheme.bytes(segment.text);
|
||||||
if (std.mem.eql(u8, s, "\n")) break :blk true;
|
if (std.mem.eql(u8, s, "\n")) break :blk true;
|
||||||
const w = self.gwidth(s);
|
const w = self.gwidth(s);
|
||||||
if (w == 0) continue;
|
if (w == 0) continue;
|
||||||
|
@ -521,9 +522,10 @@ test "Window size nested offsets" {
|
||||||
}
|
}
|
||||||
|
|
||||||
test "print: grapheme" {
|
test "print: grapheme" {
|
||||||
var screen: Screen = .{
|
const alloc = std.testing.allocator_instance.allocator();
|
||||||
.unicode = true,
|
const unicode = try Unicode.init(alloc);
|
||||||
};
|
defer unicode.deinit();
|
||||||
|
var screen: Screen = .{ .width_method = .unicode, .unicode = &unicode };
|
||||||
const win: Window = .{
|
const win: Window = .{
|
||||||
.x_off = 0,
|
.x_off = 0,
|
||||||
.y_off = 0,
|
.y_off = 0,
|
||||||
|
@ -584,8 +586,12 @@ test "print: grapheme" {
|
||||||
}
|
}
|
||||||
|
|
||||||
test "print: word" {
|
test "print: word" {
|
||||||
|
const alloc = std.testing.allocator_instance.allocator();
|
||||||
|
const unicode = try Unicode.init(alloc);
|
||||||
|
defer unicode.deinit();
|
||||||
var screen: Screen = .{
|
var screen: Screen = .{
|
||||||
.unicode = true,
|
.width_method = .unicode,
|
||||||
|
.unicode = &unicode,
|
||||||
};
|
};
|
||||||
const win: Window = .{
|
const win: Window = .{
|
||||||
.x_off = 0,
|
.x_off = 0,
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const unicode = std.unicode;
|
const unicode = std.unicode;
|
||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
const ziglyph = @import("ziglyph");
|
const DisplayWidth = @import("DisplayWidth");
|
||||||
|
const code_point = @import("code_point");
|
||||||
|
|
||||||
/// the method to use when calculating the width of a grapheme
|
/// the method to use when calculating the width of a grapheme
|
||||||
pub const Method = enum {
|
pub const Method = enum {
|
||||||
|
@ -11,18 +12,22 @@ pub const Method = enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
/// returns the width of the provided string, as measured by the method chosen
|
/// returns the width of the provided string, as measured by the method chosen
|
||||||
pub fn gwidth(str: []const u8, method: Method) !usize {
|
pub fn gwidth(str: []const u8, method: Method, data: *const DisplayWidth.DisplayWidthData) !usize {
|
||||||
switch (method) {
|
switch (method) {
|
||||||
.unicode => {
|
.unicode => {
|
||||||
return try ziglyph.display_width.strWidth(str, .half);
|
const dw: DisplayWidth = .{ .data = data };
|
||||||
|
return dw.strWidth(str);
|
||||||
},
|
},
|
||||||
.wcwidth => {
|
.wcwidth => {
|
||||||
var total: usize = 0;
|
var total: usize = 0;
|
||||||
const utf8 = try unicode.Utf8View.init(str);
|
var iter: code_point.Iterator = .{ .bytes = str };
|
||||||
var iter = utf8.iterator();
|
while (iter.next()) |cp| {
|
||||||
|
const w = switch (cp.code) {
|
||||||
while (iter.nextCodepoint()) |cp| {
|
// undo an override in zg for emoji skintone selectors
|
||||||
const w = ziglyph.display_width.codePointWidth(cp, .half);
|
0x1f3fb...0x1f3ff,
|
||||||
|
=> 2,
|
||||||
|
else => data.codePointWidth(cp.code),
|
||||||
|
};
|
||||||
if (w < 0) continue;
|
if (w < 0) continue;
|
||||||
total += @intCast(w);
|
total += @intCast(w);
|
||||||
}
|
}
|
||||||
|
@ -33,37 +38,43 @@ pub fn gwidth(str: []const u8, method: Method) !usize {
|
||||||
if (str.len > out.len) return error.OutOfMemory;
|
if (str.len > out.len) return error.OutOfMemory;
|
||||||
const n = std.mem.replacementSize(u8, str, "\u{200D}", "");
|
const n = std.mem.replacementSize(u8, str, "\u{200D}", "");
|
||||||
_ = std.mem.replace(u8, str, "\u{200D}", "", &out);
|
_ = std.mem.replace(u8, str, "\u{200D}", "", &out);
|
||||||
return gwidth(out[0..n], .unicode);
|
return gwidth(out[0..n], .unicode, data);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test "gwidth: a" {
|
test "gwidth: a" {
|
||||||
try testing.expectEqual(1, try gwidth("a", .unicode));
|
const alloc = testing.allocator_instance.allocator();
|
||||||
try testing.expectEqual(1, try gwidth("a", .wcwidth));
|
const data = try DisplayWidth.DisplayWidthData.init(alloc);
|
||||||
try testing.expectEqual(1, try gwidth("a", .no_zwj));
|
defer data.deinit();
|
||||||
|
try testing.expectEqual(1, try gwidth("a", .unicode, &data));
|
||||||
|
try testing.expectEqual(1, try gwidth("a", .wcwidth, &data));
|
||||||
|
try testing.expectEqual(1, try gwidth("a", .no_zwj, &data));
|
||||||
}
|
}
|
||||||
|
|
||||||
test "gwidth: emoji with ZWJ" {
|
test "gwidth: emoji with ZWJ" {
|
||||||
try testing.expectEqual(2, try gwidth("👩🚀", .unicode));
|
const alloc = testing.allocator_instance.allocator();
|
||||||
try testing.expectEqual(4, try gwidth("👩🚀", .wcwidth));
|
const data = try DisplayWidth.DisplayWidthData.init(alloc);
|
||||||
try testing.expectEqual(4, try gwidth("👩🚀", .no_zwj));
|
defer data.deinit();
|
||||||
|
try testing.expectEqual(2, try gwidth("👩🚀", .unicode, &data));
|
||||||
|
try testing.expectEqual(4, try gwidth("👩🚀", .wcwidth, &data));
|
||||||
|
try testing.expectEqual(4, try gwidth("👩🚀", .no_zwj, &data));
|
||||||
}
|
}
|
||||||
|
|
||||||
test "gwidth: emoji with VS16 selector" {
|
test "gwidth: emoji with VS16 selector" {
|
||||||
try testing.expectEqual(2, try gwidth("\xE2\x9D\xA4\xEF\xB8\x8F", .unicode));
|
const alloc = testing.allocator_instance.allocator();
|
||||||
try testing.expectEqual(1, try gwidth("\xE2\x9D\xA4\xEF\xB8\x8F", .wcwidth));
|
const data = try DisplayWidth.DisplayWidthData.init(alloc);
|
||||||
try testing.expectEqual(2, try gwidth("\xE2\x9D\xA4\xEF\xB8\x8F", .no_zwj));
|
defer data.deinit();
|
||||||
|
try testing.expectEqual(2, try gwidth("\xE2\x9D\xA4\xEF\xB8\x8F", .unicode, &data));
|
||||||
|
try testing.expectEqual(1, try gwidth("\xE2\x9D\xA4\xEF\xB8\x8F", .wcwidth, &data));
|
||||||
|
try testing.expectEqual(2, try gwidth("\xE2\x9D\xA4\xEF\xB8\x8F", .no_zwj, &data));
|
||||||
}
|
}
|
||||||
|
|
||||||
test "gwidth: emoji with skin tone selector" {
|
test "gwidth: emoji with skin tone selector" {
|
||||||
try testing.expectEqual(2, try gwidth("👋🏿", .unicode));
|
const alloc = testing.allocator_instance.allocator();
|
||||||
try testing.expectEqual(4, try gwidth("👋🏿", .wcwidth));
|
const data = try DisplayWidth.DisplayWidthData.init(alloc);
|
||||||
try testing.expectEqual(2, try gwidth("👋🏿", .no_zwj));
|
defer data.deinit();
|
||||||
}
|
try testing.expectEqual(2, try gwidth("👋🏿", .unicode, &data));
|
||||||
|
try testing.expectEqual(4, try gwidth("👋🏿", .wcwidth, &data));
|
||||||
test "gwidth: invalid string" {
|
try testing.expectEqual(2, try gwidth("👋🏿", .no_zwj, &data));
|
||||||
try testing.expectError(error.InvalidUtf8, gwidth("\xc3\x28", .unicode));
|
|
||||||
try testing.expectError(error.InvalidUtf8, gwidth("\xc3\x28", .wcwidth));
|
|
||||||
try testing.expectError(error.InvalidUtf8, gwidth("\xc3\x28", .no_zwj));
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ pub const AllocatingScreen = @import("InternalScreen.zig");
|
||||||
pub const Winsize = @import("Tty.zig").Winsize;
|
pub const Winsize = @import("Tty.zig").Winsize;
|
||||||
pub const Window = @import("Window.zig");
|
pub const Window = @import("Window.zig");
|
||||||
|
|
||||||
pub const ziglyph = @import("ziglyph");
|
|
||||||
pub const widgets = @import("widgets.zig");
|
pub const widgets = @import("widgets.zig");
|
||||||
pub const gwidth = @import("gwidth.zig");
|
pub const gwidth = @import("gwidth.zig");
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue