this repo has no description
13
fork

Configure Feed

Select the types of activity you want to include in your feed.

at b698a3641da7f3886bde4aeda7fcecc8d3642580 79 lines 2.9 kB view raw
1const std = @import("std"); 2const unicode = std.unicode; 3const testing = std.testing; 4const DisplayWidth = @import("DisplayWidth"); 5const code_point = @import("code_point"); 6 7/// the method to use when calculating the width of a grapheme 8pub const Method = enum { 9 unicode, 10 wcwidth, 11 no_zwj, 12}; 13 14/// returns the width of the provided string, as measured by the method chosen 15pub fn gwidth(str: []const u8, method: Method, data: *const DisplayWidth) u16 { 16 switch (method) { 17 .unicode => { 18 return @intCast(data.strWidth(str)); 19 }, 20 .wcwidth => { 21 var total: u16 = 0; 22 var iter: code_point.Iterator = .{ .bytes = str }; 23 while (iter.next()) |cp| { 24 const w: u16 = switch (cp.code) { 25 // undo an override in zg for emoji skintone selectors 26 0x1f3fb...0x1f3ff, 27 => 2, 28 else => @max(0, data.codePointWidth(cp.code)), 29 }; 30 total += w; 31 } 32 return total; 33 }, 34 .no_zwj => { 35 var iter = std.mem.splitSequence(u8, str, "\u{200D}"); 36 var result: u16 = 0; 37 while (iter.next()) |s| { 38 result += gwidth(s, .unicode, data); 39 } 40 return result; 41 }, 42 } 43} 44 45test "gwidth: a" { 46 const alloc = testing.allocator_instance.allocator(); 47 const data = try DisplayWidth.init(alloc); 48 defer data.deinit(alloc); 49 try testing.expectEqual(1, gwidth("a", .unicode, &data)); 50 try testing.expectEqual(1, gwidth("a", .wcwidth, &data)); 51 try testing.expectEqual(1, gwidth("a", .no_zwj, &data)); 52} 53 54test "gwidth: emoji with ZWJ" { 55 const alloc = testing.allocator_instance.allocator(); 56 const data = try DisplayWidth.init(alloc); 57 defer data.deinit(alloc); 58 try testing.expectEqual(2, gwidth("👩‍🚀", .unicode, &data)); 59 try testing.expectEqual(4, gwidth("👩‍🚀", .wcwidth, &data)); 60 try testing.expectEqual(4, gwidth("👩‍🚀", .no_zwj, &data)); 61} 62 63test "gwidth: emoji with VS16 selector" { 64 const alloc = testing.allocator_instance.allocator(); 65 const data = try DisplayWidth.init(alloc); 66 defer data.deinit(alloc); 67 try testing.expectEqual(2, gwidth("\xE2\x9D\xA4\xEF\xB8\x8F", .unicode, &data)); 68 try testing.expectEqual(1, gwidth("\xE2\x9D\xA4\xEF\xB8\x8F", .wcwidth, &data)); 69 try testing.expectEqual(2, gwidth("\xE2\x9D\xA4\xEF\xB8\x8F", .no_zwj, &data)); 70} 71 72test "gwidth: emoji with skin tone selector" { 73 const alloc = testing.allocator_instance.allocator(); 74 const data = try DisplayWidth.init(alloc); 75 defer data.deinit(alloc); 76 try testing.expectEqual(2, gwidth("👋🏿", .unicode, &data)); 77 try testing.expectEqual(4, gwidth("👋🏿", .wcwidth, &data)); 78 try testing.expectEqual(2, gwidth("👋🏿", .no_zwj, &data)); 79}