diff options
| author | 2024-02-17 11:31:52 -0400 | |
|---|---|---|
| committer | 2024-02-17 11:31:52 -0400 | |
| commit | 490fd008e29420e5b317fd5ef7526f3cc92ba2eb (patch) | |
| tree | 7864cae008cd64a881736fecedf12e5dd5611e83 /src/display_width.zig | |
| parent | GraphemeIterator ASCII optimization 3x faster (diff) | |
| download | zg-490fd008e29420e5b317fd5ef7526f3cc92ba2eb.tar.gz zg-490fd008e29420e5b317fd5ef7526f3cc92ba2eb.tar.xz zg-490fd008e29420e5b317fd5ef7526f3cc92ba2eb.zip | |
display_width tweaks
Diffstat (limited to 'src/display_width.zig')
| -rw-r--r-- | src/display_width.zig | 30 |
1 files changed, 18 insertions, 12 deletions
diff --git a/src/display_width.zig b/src/display_width.zig index aed0ef1..2ac7093 100644 --- a/src/display_width.zig +++ b/src/display_width.zig | |||
| @@ -42,17 +42,10 @@ fn isAsciiOnly(str: []const u8) bool { | |||
| 42 | pub fn strWidth(str: []const u8) usize { | 42 | pub fn strWidth(str: []const u8) usize { |
| 43 | var total: isize = 0; | 43 | var total: isize = 0; |
| 44 | 44 | ||
| 45 | // ASCII fast path | ||
| 45 | if (isAsciiOnly(str)) { | 46 | if (isAsciiOnly(str)) { |
| 46 | for (str) |b| { | 47 | for (str) |b| total += codePointWidth(b); |
| 47 | // Backspace and delete | 48 | return @intCast(@max(0, total)); |
| 48 | if (b == 0x8 or b == 0x7f) { | ||
| 49 | total -= 1; | ||
| 50 | } else if (b >= 0x20) { | ||
| 51 | total += 1; | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | return if (total > 0) @intCast(total) else 0; | ||
| 56 | } | 49 | } |
| 57 | 50 | ||
| 58 | var giter = GraphemeIterator.init(str); | 51 | var giter = GraphemeIterator.init(str); |
| @@ -72,14 +65,17 @@ pub fn strWidth(str: []const u8) usize { | |||
| 72 | } | 65 | } |
| 73 | 66 | ||
| 74 | // Only adding width of first non-zero-width code point. | 67 | // Only adding width of first non-zero-width code point. |
| 75 | if (gc_total == 0) gc_total = w; | 68 | if (gc_total == 0) { |
| 69 | gc_total = w; | ||
| 70 | break; | ||
| 71 | } | ||
| 76 | } | 72 | } |
| 77 | } | 73 | } |
| 78 | 74 | ||
| 79 | total += gc_total; | 75 | total += gc_total; |
| 80 | } | 76 | } |
| 81 | 77 | ||
| 82 | return if (total > 0) @intCast(total) else 0; | 78 | return @intCast(@max(0, total)); |
| 83 | } | 79 | } |
| 84 | 80 | ||
| 85 | test "display_width Width" { | 81 | test "display_width Width" { |
| @@ -147,4 +143,14 @@ test "display_width Width" { | |||
| 147 | // The following passes but as a mere coincidence. | 143 | // The following passes but as a mere coincidence. |
| 148 | const kannada_2 = "\u{0cb0}\u{0cbc}\u{0ccd}\u{0c9a}"; | 144 | const kannada_2 = "\u{0cb0}\u{0cbc}\u{0ccd}\u{0c9a}"; |
| 149 | try testing.expectEqual(@as(usize, 2), strWidth(kannada_2)); | 145 | try testing.expectEqual(@as(usize, 2), strWidth(kannada_2)); |
| 146 | |||
| 147 | // From Rust https://github.com/jameslanska/unicode-display-width | ||
| 148 | try testing.expectEqual(@as(usize, 15), strWidth("π₯π‘π©π©π»βπβ°ππΌπ¦ππ»")); | ||
| 149 | try testing.expectEqual(@as(usize, 2), strWidth("π¦")); | ||
| 150 | try testing.expectEqual(@as(usize, 2), strWidth("π¨βπ©βπ§βπ§")); | ||
| 151 | try testing.expectEqual(@as(usize, 2), strWidth("π©βπ¬")); | ||
| 152 | try testing.expectEqual(@as(usize, 9), strWidth("sane text")); | ||
| 153 | try testing.expectEqual(@as(usize, 9), strWidth("αΊΜΓ‘Μ²lΝΜΜΜΜΝgΜΜΜΜΜΝ’ΝΝoΜͺΜTΜ’ΜΜ«ΜΜΝeΜ¬ΝΝΝΜΝxΜΊΜαΉΜΜΝ ")); | ||
| 154 | try testing.expectEqual(@as(usize, 17), strWidth("μ¬λΌλ° μ°ν¬λΌμ΄λ")); | ||
| 155 | try testing.expectEqual(@as(usize, 1), strWidth("\u{378}")); | ||
| 150 | } | 156 | } |