@@ -78,6 +78,9 @@ func TestLibraryBehaviorComparison(t *testing.T) {
7878 },
7979
8080 // Regional Indicator Pairs (flags) - the key difference
81+ // TODO: 2 is the correct width, that's what Ghostty and iTerm do.
82+ // Sadly, Mac Terminal displays width 1. Perhaps we should special-case
83+ // it, not sure.
8184 {
8285 name : "Flags" ,
8386 input : "🇺🇸🇯🇵🇬🇧" ,
@@ -255,3 +258,153 @@ func TestFlagBehaviorDetailed(t *testing.T) {
255258 t .Logf ("%s | %d | %d | %d | %d | %d" , flag , displaywidthDefault , goRunewidthDefault , goRunewidthStrictFalse , goRunewidthStrictTrue , unisegDefault )
256259 }
257260}
261+
262+ func TestTruncateComparison (t * testing.T ) {
263+ testCases := []struct {
264+ name string
265+ input string
266+ maxWidth int
267+ tail string
268+ }{
269+ {
270+ name : "ASCII truncation" ,
271+ input : "Hello World" ,
272+ maxWidth : 5 ,
273+ tail : "..." ,
274+ },
275+ {
276+ name : "CJK truncation" ,
277+ input : "中文测试" ,
278+ maxWidth : 4 ,
279+ tail : "..." ,
280+ },
281+ {
282+ name : "Emoji truncation" ,
283+ input : "😀🚀🎉" ,
284+ maxWidth : 4 ,
285+ tail : "..." ,
286+ },
287+ {
288+ name : "Flags truncation" ,
289+ input : "🇺🇸🇯🇵🇬🇧" , // known difference
290+ maxWidth : 4 ,
291+ tail : "..." ,
292+ },
293+ {
294+ name : "Mixed content truncation" ,
295+ input : "Hello 世界! 😀🇺🇸" ,
296+ maxWidth : 10 ,
297+ tail : "..." ,
298+ },
299+ {
300+ name : "No truncation needed" ,
301+ input : "Hi" ,
302+ maxWidth : 10 ,
303+ tail : "..." ,
304+ },
305+ {
306+ name : "Empty tail" ,
307+ input : "Hello World" ,
308+ maxWidth : 5 ,
309+ tail : "" ,
310+ },
311+ {
312+ name : "Width exactly equal to string width" ,
313+ input : "Hello" ,
314+ maxWidth : 5 ,
315+ tail : "..." ,
316+ },
317+ {
318+ name : "Width exactly equal to string width with emoji" ,
319+ input : "😀🚀" ,
320+ maxWidth : 4 ,
321+ tail : "..." ,
322+ },
323+ {
324+ name : "Width exactly equal to string width with CJK" ,
325+ input : "中文" ,
326+ maxWidth : 4 ,
327+ tail : "..." ,
328+ },
329+ {
330+ name : "MaxWidth is 0" ,
331+ input : "Hello" ,
332+ maxWidth : 0 ,
333+ tail : "..." ,
334+ },
335+ {
336+ name : "MaxWidth is 1" ,
337+ input : "Hello" ,
338+ maxWidth : 1 ,
339+ tail : "..." ,
340+ },
341+ {
342+ name : "MaxWidth is 2" ,
343+ input : "Hello" ,
344+ maxWidth : 2 ,
345+ tail : "..." ,
346+ },
347+ {
348+ name : "Empty string input" ,
349+ input : "" ,
350+ maxWidth : 5 ,
351+ tail : "..." ,
352+ },
353+ {
354+ name : "Tail wider than maxWidth" ,
355+ input : "Hello" ,
356+ maxWidth : 2 ,
357+ tail : "中文" , // width 4, wider than maxWidth
358+ },
359+ {
360+ name : "Tail with emoji" ,
361+ input : "Hello" ,
362+ maxWidth : 5 ,
363+ tail : "😀" ,
364+ },
365+ {
366+ name : "MaxWidth exactly equal to tail width" ,
367+ input : "Hello World" ,
368+ maxWidth : 3 , // exactly width of "..."
369+ tail : "..." ,
370+ },
371+ {
372+ name : "Input with control characters" ,
373+ input : "hello\n world" ,
374+ maxWidth : 8 ,
375+ tail : "..." ,
376+ },
377+ {
378+ name : "Single wide character truncation" ,
379+ input : "中" ,
380+ maxWidth : 1 ,
381+ tail : "..." ,
382+ },
383+ {
384+ name : "Single emoji truncation" ,
385+ input : "😀" ,
386+ maxWidth : 1 ,
387+ tail : "..." ,
388+ },
389+ }
390+
391+ for _ , tc := range testCases {
392+ t .Run (tc .name , func (t * testing.T ) {
393+ // displaywidth
394+ displaywidthResult := displaywidth .TruncateString (tc .input , tc .maxWidth , tc .tail )
395+ displaywidthWidth := displaywidth .String (displaywidthResult )
396+
397+ // go-runewidth
398+ goRunewidthResult := runewidth .Truncate (tc .input , tc .maxWidth , tc .tail )
399+ goRunewidthWidth := runewidth .StringWidth (goRunewidthResult )
400+
401+ if displaywidthWidth != goRunewidthWidth {
402+ t .Logf ("displaywidth and go-runewidth results differ for %q: %d != %d" , tc .input , displaywidthWidth , goRunewidthWidth )
403+ }
404+
405+ if displaywidthResult != goRunewidthResult {
406+ t .Logf ("displaywidth and go-runewidth results differ for %s : %s != %s" , tc .input , displaywidthResult , goRunewidthResult )
407+ }
408+ })
409+ }
410+ }
0 commit comments