diff options
Diffstat (limited to 'src/DisplayWidth.zig')
| -rw-r--r-- | src/DisplayWidth.zig | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/src/DisplayWidth.zig b/src/DisplayWidth.zig index 629087b..dee7ebd 100644 --- a/src/DisplayWidth.zig +++ b/src/DisplayWidth.zig | |||
| @@ -39,11 +39,9 @@ pub fn setupWithGraphemes(dw: *DisplayWidth, allocator: Allocator, graphemes: Gr | |||
| 39 | 39 | ||
| 40 | // Sets up the DisplayWidthData, leaving the GraphemeData undefined. | 40 | // Sets up the DisplayWidthData, leaving the GraphemeData undefined. |
| 41 | pub fn setup(dw: *DisplayWidth, allocator: Allocator) Allocator.Error!void { | 41 | pub fn setup(dw: *DisplayWidth, allocator: Allocator) Allocator.Error!void { |
| 42 | const decompressor = compress.flate.inflate.decompressor; | ||
| 43 | const in_bytes = @embedFile("dwp"); | 42 | const in_bytes = @embedFile("dwp"); |
| 44 | var in_fbs = std.io.fixedBufferStream(in_bytes); | 43 | var in_fbs = std.io.fixedBufferStream(in_bytes); |
| 45 | var in_decomp = decompressor(.raw, in_fbs.reader()); | 44 | var reader = in_fbs.reader(); |
| 46 | var reader = in_decomp.reader(); | ||
| 47 | 45 | ||
| 48 | const endian = builtin.cpu.arch.endian(); | 46 | const endian = builtin.cpu.arch.endian(); |
| 49 | 47 | ||
| @@ -118,6 +116,8 @@ pub fn graphemeClusterWidth(dw: DisplayWidth, gc: []const u8) isize { | |||
| 118 | // emoji text sequence. | 116 | // emoji text sequence. |
| 119 | if (ncp.code == 0xFE0E) w = 1; | 117 | if (ncp.code == 0xFE0E) w = 1; |
| 120 | if (ncp.code == 0xFE0F) w = 2; | 118 | if (ncp.code == 0xFE0F) w = 2; |
| 119 | // Skin tones | ||
| 120 | if (0x1F3FB <= ncp.code and ncp.code <= 0x1F3FF) w = 2; | ||
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | // Only adding width of first non-zero-width code point. | 123 | // Only adding width of first non-zero-width code point. |
| @@ -207,6 +207,9 @@ test "strWidth" { | |||
| 207 | try testing.expectEqual(@as(usize, 9), dw.strWidth("Ẓ̌á̲l͔̝̞̄̑͌g̖̘̘̔̔͢͞͝o̪̔T̢̙̫̈̍͞e̬͈͕͌̏͑x̺̍ṭ̓̓ͅ")); | 207 | try testing.expectEqual(@as(usize, 9), dw.strWidth("Ẓ̌á̲l͔̝̞̄̑͌g̖̘̘̔̔͢͞͝o̪̔T̢̙̫̈̍͞e̬͈͕͌̏͑x̺̍ṭ̓̓ͅ")); |
| 208 | try testing.expectEqual(@as(usize, 17), dw.strWidth("슬라바 우크라이나")); | 208 | try testing.expectEqual(@as(usize, 17), dw.strWidth("슬라바 우크라이나")); |
| 209 | try testing.expectEqual(@as(usize, 1), dw.strWidth("\u{378}")); | 209 | try testing.expectEqual(@as(usize, 1), dw.strWidth("\u{378}")); |
| 210 | |||
| 211 | // https://codeberg.org/atman/zg/issues/82 | ||
| 212 | try testing.expectEqual(@as(usize, 12), dw.strWidth("✍️✍🏻✍🏼✍🏽✍🏾✍🏿")); | ||
| 210 | } | 213 | } |
| 211 | 214 | ||
| 212 | /// centers `str` in a new string of width `total_width` (in display cells) using `pad` as padding. | 215 | /// centers `str` in a new string of width `total_width` (in display cells) using `pad` as padding. |
| @@ -404,7 +407,7 @@ pub fn wrap( | |||
| 404 | columns: usize, | 407 | columns: usize, |
| 405 | threshold: usize, | 408 | threshold: usize, |
| 406 | ) ![]u8 { | 409 | ) ![]u8 { |
| 407 | var result = ArrayList(u8).init(allocator); | 410 | var result = std.array_list.Managed(u8).init(allocator); |
| 408 | defer result.deinit(); | 411 | defer result.deinit(); |
| 409 | 412 | ||
| 410 | var line_iter = mem.tokenizeAny(u8, str, "\r\n"); | 413 | var line_iter = mem.tokenizeAny(u8, str, "\r\n"); |
| @@ -426,8 +429,10 @@ pub fn wrap( | |||
| 426 | } | 429 | } |
| 427 | 430 | ||
| 428 | // Remove trailing space and newline. | 431 | // Remove trailing space and newline. |
| 429 | _ = result.pop(); | 432 | if (result.items[result.items.len - 1] == '\n') |
| 430 | _ = result.pop(); | 433 | _ = result.pop(); |
| 434 | if (result.items[result.items.len - 1] == ' ') | ||
| 435 | _ = result.pop(); | ||
| 431 | 436 | ||
| 432 | return try result.toOwnedSlice(); | 437 | return try result.toOwnedSlice(); |
| 433 | } | 438 | } |
| @@ -444,6 +449,18 @@ test "wrap" { | |||
| 444 | try testing.expectEqualStrings(want, got); | 449 | try testing.expectEqualStrings(want, got); |
| 445 | } | 450 | } |
| 446 | 451 | ||
| 452 | test "zg/74" { | ||
| 453 | var debug_alloc = std.heap.DebugAllocator(.{}).init; | ||
| 454 | const allocator = debug_alloc.allocator(); | ||
| 455 | defer _ = debug_alloc.deinit(); | ||
| 456 | const dw = try DisplayWidth.init(allocator); | ||
| 457 | defer dw.deinit(allocator); | ||
| 458 | const wrapped = try dw.wrap(allocator, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam pellentesque pulvinar felis, sit amet commodo ligula feugiat sed. Sed quis malesuada elit, nec eleifend lectus. Sed tincidunt finibus aliquet. Praesent consectetur nibh libero, tempus imperdiet lorem congue eget.", 16, 1); | ||
| 459 | defer allocator.free(wrapped); | ||
| 460 | const expected_wrap = "Lorem ipsum dolor \nsit amet, consectetur \nadipiscing elit. \nNullam pellentesque \npulvinar felis, \nsit amet commodo \nligula feugiat \nsed. Sed quis malesuada \nelit, nec eleifend \nlectus. Sed tincidunt \nfinibus aliquet. \nPraesent consectetur \nnibh libero, tempus \nimperdiet lorem \ncongue eget."; | ||
| 461 | try std.testing.expectEqualStrings(expected_wrap, wrapped); | ||
| 462 | } | ||
| 463 | |||
| 447 | fn testAllocation(allocator: Allocator) !void { | 464 | fn testAllocation(allocator: Allocator) !void { |
| 448 | { | 465 | { |
| 449 | var dw = try DisplayWidth.init(allocator); | 466 | var dw = try DisplayWidth.init(allocator); |
| @@ -464,8 +481,6 @@ test "allocation test" { | |||
| 464 | const std = @import("std"); | 481 | const std = @import("std"); |
| 465 | const builtin = @import("builtin"); | 482 | const builtin = @import("builtin"); |
| 466 | const options = @import("options"); | 483 | const options = @import("options"); |
| 467 | const ArrayList = std.ArrayList; | ||
| 468 | const compress = std.compress; | ||
| 469 | const mem = std.mem; | 484 | const mem = std.mem; |
| 470 | const Allocator = mem.Allocator; | 485 | const Allocator = mem.Allocator; |
| 471 | const simd = std.simd; | 486 | const simd = std.simd; |