summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Lich2025-07-20 15:09:09 +0300
committerGravatar Lich2025-07-20 15:10:13 +0300
commit28aa25a86c0a1e551469ab74dda4a1636108e11b (patch)
tree7e11c2f247652e91d679401fe6727fb8fb89a5d3
parentMerge branch 'develop-next' (diff)
downloadzg-28aa25a86c0a1e551469ab74dda4a1636108e11b.tar.gz
zg-28aa25a86c0a1e551469ab74dda4a1636108e11b.tar.xz
zg-28aa25a86c0a1e551469ab74dda4a1636108e11b.zip
Moved part of the `strWidth` into its own `graphemeClusterWidth` function
-rw-r--r--src/DisplayWidth.zig50
1 files changed, 27 insertions, 23 deletions
diff --git a/src/DisplayWidth.zig b/src/DisplayWidth.zig
index 3da2d24..629087b 100644
--- a/src/DisplayWidth.zig
+++ b/src/DisplayWidth.zig
@@ -102,6 +102,32 @@ test "codePointWidth" {
102 try testing.expectEqual(@as(i4, 2), dw.codePointWidth('统')); 102 try testing.expectEqual(@as(i4, 2), dw.codePointWidth('统'));
103} 103}
104 104
105/// graphemeClusterWidth returns the total display width of `gc` as the number
106/// of cells required in a fixed-pitch font (i.e. a terminal screen).
107/// `gc` is a slice corresponding to one grapheme cluster.
108pub fn graphemeClusterWidth(dw: DisplayWidth, gc: []const u8) isize {
109 var cp_iter = CodePointIterator{ .bytes = gc };
110 var gc_total: isize = 0;
111
112 while (cp_iter.next()) |cp| {
113 var w = dw.codePointWidth(cp.code);
114
115 if (w != 0) {
116 // Handle text emoji sequence.
117 if (cp_iter.next()) |ncp| {
118 // emoji text sequence.
119 if (ncp.code == 0xFE0E) w = 1;
120 if (ncp.code == 0xFE0F) w = 2;
121 }
122
123 // Only adding width of first non-zero-width code point.
124 gc_total = w;
125 break;
126 }
127 }
128 return gc_total;
129}
130
105/// strWidth returns the total display width of `str` as the number of cells 131/// strWidth returns the total display width of `str` as the number of cells
106/// required in a fixed-pitch font (i.e. a terminal screen). 132/// required in a fixed-pitch font (i.e. a terminal screen).
107pub fn strWidth(dw: DisplayWidth, str: []const u8) usize { 133pub fn strWidth(dw: DisplayWidth, str: []const u8) usize {
@@ -116,29 +142,7 @@ pub fn strWidth(dw: DisplayWidth, str: []const u8) usize {
116 var giter = dw.graphemes.iterator(str); 142 var giter = dw.graphemes.iterator(str);
117 143
118 while (giter.next()) |gc| { 144 while (giter.next()) |gc| {
119 var cp_iter = CodePointIterator{ .bytes = gc.bytes(str) }; 145 total += dw.graphemeClusterWidth(gc.bytes(str));
120 var gc_total: isize = 0;
121
122 while (cp_iter.next()) |cp| {
123 var w = dw.codePointWidth(cp.code);
124
125 if (w != 0) {
126 // Handle text emoji sequence.
127 if (cp_iter.next()) |ncp| {
128 // emoji text sequence.
129 if (ncp.code == 0xFE0E) w = 1;
130 if (ncp.code == 0xFE0F) w = 2;
131 }
132
133 // Only adding width of first non-zero-width code point.
134 if (gc_total == 0) {
135 gc_total = w;
136 break;
137 }
138 }
139 }
140
141 total += gc_total;
142 } 146 }
143 147
144 return @intCast(@max(0, total)); 148 return @intCast(@max(0, total));