Skip to content

Commit aeb4b89

Browse files
committed
fix(tui): handle invisible codepoints when measuring label width
1 parent e543acf commit aeb4b89

1 file changed

Lines changed: 35 additions & 6 deletions

File tree

packages/opencode/src/util/locale.ts

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,47 @@ export function duration(input: number) {
5959
}
6060

6161
export function truncate(str: string, len: number): string {
62-
if (str.length <= len) return str
63-
return str.slice(0, len - 1) + "…"
62+
if (Bun.stringWidth(str) <= len) return str
63+
let out = ""
64+
let width = 0
65+
for (const char of str) {
66+
const w = Bun.stringWidth(char)
67+
if (width + w > len - 1) break
68+
out += char
69+
width += w
70+
}
71+
return out + "…"
6472
}
6573

6674
export function truncateMiddle(str: string, maxLength: number = 35): string {
67-
if (str.length <= maxLength) return str
75+
if (Bun.stringWidth(str) <= maxLength) return str
6876

6977
const ellipsis = "…"
70-
const keepStart = Math.ceil((maxLength - ellipsis.length) / 2)
71-
const keepEnd = Math.floor((maxLength - ellipsis.length) / 2)
78+
const budget = maxLength - ellipsis.length
79+
const keepStart = Math.ceil(budget / 2)
80+
const keepEnd = Math.floor(budget / 2)
81+
82+
let startOut = ""
83+
let startWidth = 0
84+
for (const char of str) {
85+
const w = Bun.stringWidth(char)
86+
if (startWidth + w > keepStart) break
87+
startOut += char
88+
startWidth += w
89+
}
90+
91+
const chars = Array.from(str)
92+
let endOut = ""
93+
let endWidth = 0
94+
for (let i = chars.length - 1; i >= 0; i--) {
95+
const char = chars[i]
96+
const w = Bun.stringWidth(char)
97+
if (endWidth + w > keepEnd) break
98+
endOut = char + endOut
99+
endWidth += w
100+
}
72101

73-
return str.slice(0, keepStart) + ellipsis + str.slice(-keepEnd)
102+
return startOut + ellipsis + endOut
74103
}
75104

76105
export function pluralize(count: number, singular: string, plural: string): string {

0 commit comments

Comments
 (0)