this repo has no description
13
fork

Configure Feed

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

at 01605eebf65be21caa85ee9d840047f864553308 80 lines 3.0 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.DisplayWidthData) u16 { 16 switch (method) { 17 .unicode => { 18 const dw: DisplayWidth = .{ .data = data }; 19 return @intCast(dw.strWidth(str)); 20 }, 21 .wcwidth => { 22 var total: u16 = 0; 23 var iter: code_point.Iterator = .{ .bytes = str }; 24 while (iter.next()) |cp| { 25 const w: u16 = switch (cp.code) { 26 // undo an override in zg for emoji skintone selectors 27 0x1f3fb...0x1f3ff, 28 => 2, 29 else => @max(0, data.codePointWidth(cp.code)), 30 }; 31 total += w; 32 } 33 return total; 34 }, 35 .no_zwj => { 36 var iter = std.mem.splitSequence(u8, str, "\u{200D}"); 37 var result: u16 = 0; 38 while (iter.next()) |s| { 39 result += gwidth(s, .unicode, data); 40 } 41 return result; 42 }, 43 } 44} 45 46test "gwidth: a" { 47 const alloc = testing.allocator_instance.allocator(); 48 const data = try DisplayWidth.DisplayWidthData.init(alloc); 49 defer data.deinit(); 50 try testing.expectEqual(1, gwidth("a", .unicode, &data)); 51 try testing.expectEqual(1, gwidth("a", .wcwidth, &data)); 52 try testing.expectEqual(1, gwidth("a", .no_zwj, &data)); 53} 54 55test "gwidth: emoji with ZWJ" { 56 const alloc = testing.allocator_instance.allocator(); 57 const data = try DisplayWidth.DisplayWidthData.init(alloc); 58 defer data.deinit(); 59 try testing.expectEqual(2, gwidth("👩‍🚀", .unicode, &data)); 60 try testing.expectEqual(4, gwidth("👩‍🚀", .wcwidth, &data)); 61 try testing.expectEqual(4, gwidth("👩‍🚀", .no_zwj, &data)); 62} 63 64test "gwidth: emoji with VS16 selector" { 65 const alloc = testing.allocator_instance.allocator(); 66 const data = try DisplayWidth.DisplayWidthData.init(alloc); 67 defer data.deinit(); 68 try testing.expectEqual(2, gwidth("\xE2\x9D\xA4\xEF\xB8\x8F", .unicode, &data)); 69 try testing.expectEqual(1, gwidth("\xE2\x9D\xA4\xEF\xB8\x8F", .wcwidth, &data)); 70 try testing.expectEqual(2, gwidth("\xE2\x9D\xA4\xEF\xB8\x8F", .no_zwj, &data)); 71} 72 73test "gwidth: emoji with skin tone selector" { 74 const alloc = testing.allocator_instance.allocator(); 75 const data = try DisplayWidth.DisplayWidthData.init(alloc); 76 defer data.deinit(); 77 try testing.expectEqual(2, gwidth("👋🏿", .unicode, &data)); 78 try testing.expectEqual(4, gwidth("👋🏿", .wcwidth, &data)); 79 try testing.expectEqual(2, gwidth("👋🏿", .no_zwj, &data)); 80}