a modern tui library written in zig

gwidth: use an iterator to prevent returning error

This is a breaking change to gwidth: we no longer return an error

Changed files
+23 -22
src
+2 -2
src/Vaxis.zig
··· 368 368 if (cell.char.width != 0) break :blk cell.char.width; 369 369 370 370 const method: gwidth.Method = self.caps.unicode; 371 - const width = gwidth.gwidth(cell.char.grapheme, method, &self.unicode.width_data) catch 1; 371 + const width = gwidth.gwidth(cell.char.grapheme, method, &self.unicode.width_data); 372 372 break :blk @max(1, width); 373 373 }; 374 374 defer { ··· 994 994 if (cell.char.width != 0) break :blk cell.char.width; 995 995 996 996 const method: gwidth.Method = self.caps.unicode; 997 - const width = gwidth.gwidth(cell.char.grapheme, method, &self.unicode.width_data) catch 1; 997 + const width = gwidth.gwidth(cell.char.grapheme, method, &self.unicode.width_data); 998 998 break :blk @max(1, width); 999 999 }; 1000 1000 defer {
+1 -1
src/Window.zig
··· 206 206 207 207 /// returns the width of the grapheme. This depends on the terminal capabilities 208 208 pub fn gwidth(self: Window, str: []const u8) usize { 209 - return gw.gwidth(str, self.screen.width_method, &self.screen.unicode.width_data) catch 1; 209 + return gw.gwidth(str, self.screen.width_method, &self.screen.unicode.width_data); 210 210 } 211 211 212 212 /// fills the window with the provided cell
+19 -18
src/gwidth.zig
··· 12 12 }; 13 13 14 14 /// returns the width of the provided string, as measured by the method chosen 15 - pub fn gwidth(str: []const u8, method: Method, data: *const DisplayWidth.DisplayWidthData) !usize { 15 + pub fn gwidth(str: []const u8, method: Method, data: *const DisplayWidth.DisplayWidthData) usize { 16 16 switch (method) { 17 17 .unicode => { 18 18 const dw: DisplayWidth = .{ .data = data }; ··· 34 34 return total; 35 35 }, 36 36 .no_zwj => { 37 - var out: [256]u8 = undefined; 38 - if (str.len > out.len) return error.OutOfMemory; 39 - const n = std.mem.replacementSize(u8, str, "\u{200D}", ""); 40 - _ = std.mem.replace(u8, str, "\u{200D}", "", &out); 41 - return gwidth(out[0..n], .unicode, data); 37 + var iter = std.mem.split(u8, str, "\u{200D}"); 38 + var result: usize = 0; 39 + while (iter.next()) |s| { 40 + result += gwidth(s, .unicode, data); 41 + } 42 + return result; 42 43 }, 43 44 } 44 45 } ··· 47 48 const alloc = testing.allocator_instance.allocator(); 48 49 const data = try DisplayWidth.DisplayWidthData.init(alloc); 49 50 defer data.deinit(); 50 - try testing.expectEqual(1, try gwidth("a", .unicode, &data)); 51 - try testing.expectEqual(1, try gwidth("a", .wcwidth, &data)); 52 - try testing.expectEqual(1, try gwidth("a", .no_zwj, &data)); 51 + try testing.expectEqual(1, gwidth("a", .unicode, &data)); 52 + try testing.expectEqual(1, gwidth("a", .wcwidth, &data)); 53 + try testing.expectEqual(1, gwidth("a", .no_zwj, &data)); 53 54 } 54 55 55 56 test "gwidth: emoji with ZWJ" { 56 57 const alloc = testing.allocator_instance.allocator(); 57 58 const data = try DisplayWidth.DisplayWidthData.init(alloc); 58 59 defer data.deinit(); 59 - try testing.expectEqual(2, try gwidth("๐Ÿ‘ฉโ€๐Ÿš€", .unicode, &data)); 60 - try testing.expectEqual(4, try gwidth("๐Ÿ‘ฉโ€๐Ÿš€", .wcwidth, &data)); 61 - try testing.expectEqual(4, try gwidth("๐Ÿ‘ฉโ€๐Ÿš€", .no_zwj, &data)); 60 + try testing.expectEqual(2, gwidth("๐Ÿ‘ฉโ€๐Ÿš€", .unicode, &data)); 61 + try testing.expectEqual(4, gwidth("๐Ÿ‘ฉโ€๐Ÿš€", .wcwidth, &data)); 62 + try testing.expectEqual(4, gwidth("๐Ÿ‘ฉโ€๐Ÿš€", .no_zwj, &data)); 62 63 } 63 64 64 65 test "gwidth: emoji with VS16 selector" { 65 66 const alloc = testing.allocator_instance.allocator(); 66 67 const data = try DisplayWidth.DisplayWidthData.init(alloc); 67 68 defer data.deinit(); 68 - try testing.expectEqual(2, try gwidth("\xE2\x9D\xA4\xEF\xB8\x8F", .unicode, &data)); 69 - try testing.expectEqual(1, try gwidth("\xE2\x9D\xA4\xEF\xB8\x8F", .wcwidth, &data)); 70 - try testing.expectEqual(2, try gwidth("\xE2\x9D\xA4\xEF\xB8\x8F", .no_zwj, &data)); 69 + try testing.expectEqual(2, gwidth("\xE2\x9D\xA4\xEF\xB8\x8F", .unicode, &data)); 70 + try testing.expectEqual(1, gwidth("\xE2\x9D\xA4\xEF\xB8\x8F", .wcwidth, &data)); 71 + try testing.expectEqual(2, gwidth("\xE2\x9D\xA4\xEF\xB8\x8F", .no_zwj, &data)); 71 72 } 72 73 73 74 test "gwidth: emoji with skin tone selector" { 74 75 const alloc = testing.allocator_instance.allocator(); 75 76 const data = try DisplayWidth.DisplayWidthData.init(alloc); 76 77 defer data.deinit(); 77 - try testing.expectEqual(2, try gwidth("๐Ÿ‘‹๐Ÿฟ", .unicode, &data)); 78 - try testing.expectEqual(4, try gwidth("๐Ÿ‘‹๐Ÿฟ", .wcwidth, &data)); 79 - try testing.expectEqual(2, try gwidth("๐Ÿ‘‹๐Ÿฟ", .no_zwj, &data)); 78 + try testing.expectEqual(2, gwidth("๐Ÿ‘‹๐Ÿฟ", .unicode, &data)); 79 + try testing.expectEqual(4, gwidth("๐Ÿ‘‹๐Ÿฟ", .wcwidth, &data)); 80 + try testing.expectEqual(2, gwidth("๐Ÿ‘‹๐Ÿฟ", .no_zwj, &data)); 80 81 }
+1 -1
src/widgets/View.zig
··· 139 139 140 140 /// Returns the width of the grapheme. This depends on the terminal capabilities 141 141 pub fn gwidth(self: View, str: []const u8) usize { 142 - return gw.gwidth(str, self.screen.width_method, &self.screen.unicode.width_data) catch 1; 142 + return gw.gwidth(str, self.screen.width_method, &self.screen.unicode.width_data); 143 143 } 144 144 145 145 /// Fills the View with the provided cell