@@ -160,123 +160,96 @@ func TestTruncate(t *testing.T) {
160
160
tests := []struct {
161
161
name string
162
162
input string
163
- maxWidth int // This is now totalBudgetForOutput
163
+ maxWidth int
164
164
suffix []string
165
165
eastAsian bool
166
166
expected string
167
167
}{
168
168
{
169
- name : "ASCII within width" , // sDisplayWidth (5) <= maxWidth (5). No suffix.
169
+ name : "ASCII within width" ,
170
170
input : "hello" ,
171
171
maxWidth : 5 ,
172
172
suffix : nil ,
173
173
eastAsian : false ,
174
- expected : "hello" , // CORRECT - No change.
174
+ expected : "hello" ,
175
175
},
176
176
{
177
- name : "ASCII with suffix" , // sDisplayWidth (5) + suffixWidth (3) = 8. maxWidth (8).
178
- input : "hello" , // sDisplayWidth (5) <= maxWidth (8) is true.
179
- maxWidth : 8 , // Then check sDisplayWidth+suffixDisplayWidth <= maxWidth (5+3 <= 8), true.
177
+ name : "ASCII with suffix" ,
178
+ input : "hello" ,
179
+ maxWidth : 8 ,
180
180
suffix : []string {"..." },
181
181
eastAsian : false ,
182
- expected : "hello..." , // CORRECT - No change.
182
+ expected : "hello..." ,
183
183
},
184
184
{
185
- name : "ASCII truncate" , // sDisplayWidth (5) > maxWidth (3). Truncation needed.
185
+ name : "ASCII truncate" ,
186
186
input : "hello" ,
187
- maxWidth : 3 , // totalBudgetForOutput = 3
188
- suffix : []string {"..." }, // suffixWidth = 3
187
+ maxWidth : 3 ,
188
+ suffix : []string {"..." },
189
189
eastAsian : false ,
190
- // New behavior: contentBudget = 3 - 3 = 0.
191
- // Truncate "hello" to width 0 -> "".
192
- // Append "..." -> "...".
193
- expected : "..." , // <<<< CHANGED from "hel..."
190
+ expected : "..." ,
194
191
},
195
192
{
196
- name : "Unicode with ANSI, no truncate" , // sDisplayWidth (3) <= maxWidth (3). No suffix.
193
+ name : "Unicode with ANSI, no truncate" ,
197
194
input : "\033 [31m☆あ\033 [0m" ,
198
195
maxWidth : 3 ,
199
196
suffix : nil ,
200
197
eastAsian : false ,
201
- expected : "\033 [31m☆あ\033 [0m" , // CORRECT - No change.
198
+ expected : "\033 [31m☆あ\033 [0m" ,
202
199
},
203
200
{
204
- name : "Unicode with ANSI, truncate" , // sDisplayWidth (3) > maxWidth (2). Truncation needed.
205
- input : "\033 [31m☆あ\033 [0m" , // ☆ (1), あ (2 with EA=false) -> width 3.
206
- maxWidth : 2 , // totalBudgetForOutput = 2
207
- suffix : []string {"..." }, // suffixWidth = 3
201
+ name : "Unicode with ANSI, truncate" ,
202
+ input : "\033 [31m☆あ\033 [0m" ,
203
+ maxWidth : 2 ,
204
+ suffix : []string {"..." },
208
205
eastAsian : false ,
209
- // New behavior: contentBudget = 2 - 3 = -1.
210
- // Since contentBudget < 0, check if suffix fits: suffixWidth (3) > maxWidth (2) -> No.
211
- // Returns "".
212
- expected : "" , // <<<< CHANGED from "\033[31m☆\033[0m..."
213
- // OLD logic: content budget = 2. Truncated to ☆ (width 1). Added ... -> ☆...
214
- // The previous logic might have been flawed if `maxWidth` was for content only.
215
- // If the old `expected` was correct, it implied `maxWidth=2` was budget for content, making output `☆...` width `1+3=4`.
216
- // With new logic, if `maxWidth=2` is total, and suffix is `...` (width 3), can't fit.
217
- // Let's re-evaluate: if `maxWidth` is total budget for output, including suffix.
218
- // `input`="☆あ" (width ☆=1, あ=2 -> total 3 if EA=false, or ☆=1, あ=1 -> total 2 if not counting `runewidth` on `あ` correctly)
219
- // Assuming ☆=1, あ=1 for EA=false based on original tests. So input width = 2.
220
- // If input width = 2 and maxWidth = 2, it should fit as `\033[31m☆あ\033[0m`.
221
- // Let's use the Width function values: input="\033[31m☆あ\033[0m", EA=false -> Width = 3. (☆=1, あ=2 if `runewidth` default)
222
- // Okay, Width("☆あ", EA=false) = 3 (☆=1, あ=2).
223
- // sDisplayWidth (3) > maxWidth (2). Truncation.
224
- // contentBudget = 2 (maxWidth) - 3 (suffixWidth) = -1.
225
- // Can suffix fit? suffixWidth (3) not <= maxWidth (2). So, return "". This is correct under new rule.
206
+ expected : "" ,
226
207
},
227
208
{
228
- name : "Unicode with EastAsian" , // sDisplayWidth (4 with EA=true) > maxWidth (3). Truncation.
229
- input : "\033 [31m☆あ\033 [0m" , // ☆ (2), あ (2) -> width 4
230
- maxWidth : 3 , // totalBudgetForOutput = 3
231
- suffix : []string {"..." }, // suffixWidth = 3
209
+ name : "Unicode with EastAsian" ,
210
+ input : "\033 [31m☆あ\033 [0m" ,
211
+ maxWidth : 3 ,
212
+ suffix : []string {"..." },
232
213
eastAsian : true ,
233
- // New behavior: contentBudget = 3 - 3 = 0.
234
- // Truncate to width 0 -> "".
235
- // Append "..." -> "...".
236
- // Also, there's the special EastAsian case: if currentGlobalEastAsianWidth is true,
237
- // and provisionalContentWidth (maxWidth - suffixDisplayWidth) == 0, return suffixStr.
238
- // Here, 3 - 3 == 0. So returns "..."
239
- expected : "..." , // CORRECT - This was already the expectation that drove a previous change.
214
+ expected : "..." ,
240
215
},
241
216
{
242
- name : "Zero maxWidth" , // maxWidth = 0.
217
+ name : "Zero maxWidth" ,
243
218
input : "hello" ,
244
219
maxWidth : 0 ,
245
220
suffix : []string {"..." },
246
221
eastAsian : false ,
247
- expected : "" , // CORRECT - Truncate returns "" if maxWidth is 0 and sDisplayWidth > 0.
222
+ expected : "" ,
248
223
},
249
224
{
250
- name : "Negative maxWidth" , // maxWidth = -1.
225
+ name : "Negative maxWidth" ,
251
226
input : "hello" ,
252
227
maxWidth : - 1 ,
253
228
suffix : []string {"..." },
254
229
eastAsian : false ,
255
- expected : "" , // CORRECT - Truncate returns "" if maxWidth < 0.
230
+ expected : "" ,
256
231
},
257
232
{
258
- name : "Empty string with suffix" , // sDisplayWidth = 0.
233
+ name : "Empty string with suffix" ,
259
234
input : "" ,
260
235
maxWidth : 3 ,
261
- suffix : []string {"..." }, // suffixWidth = 3.
236
+ suffix : []string {"..." },
262
237
eastAsian : false ,
263
- // Behavior: sDisplayWidth == 0. suffix exists. suffixWidth (3) <= maxWidth (3). Returns suffixStr.
264
- expected : "..." , // CORRECT.
238
+ expected : "..." ,
265
239
},
266
240
{
267
- name : "Only ANSI" , // sDisplayWidth = 0.
241
+ name : "Only ANSI" ,
268
242
input : "\033 [31m\033 [0m" ,
269
243
maxWidth : 3 ,
270
- suffix : []string {"..." }, // suffixWidth = 3.
244
+ suffix : []string {"..." },
271
245
eastAsian : false ,
272
- // Behavior: sDisplayWidth == 0. suffix exists. suffixWidth (3) <= maxWidth (3). Returns suffixStr.
273
- expected : "..." , // CORRECT.
246
+ expected : "..." ,
274
247
},
275
248
}
276
249
277
250
for _ , tt := range tests {
278
251
t .Run (tt .name , func (t * testing.T ) {
279
- SetEastAsian (tt .eastAsian ) // This sets the global state for Width() calls inside Truncate
252
+ SetEastAsian (tt .eastAsian )
280
253
got := Truncate (tt .input , tt .maxWidth , tt .suffix ... )
281
254
if got != tt .expected {
282
255
t .Errorf ("Truncate(%q, %d, %v) (EA=%v) = %q, want %q" , tt .input , tt .maxWidth , tt .suffix , tt .eastAsian , got , tt .expected )
@@ -326,7 +299,6 @@ func TestWidthWithEnvironment(t *testing.T) {
326
299
}
327
300
}
328
301
329
- // Helper to reset the cache for a clean benchmark state
330
302
func resetGlobalCache () {
331
303
mu .Lock ()
332
304
widthCache = make (map [cacheKey ]int )
@@ -338,54 +310,42 @@ var benchmarkStrings = map[string]string{
338
310
"ASCIIWithANSI" : "\033 [31mhello\033 [0m \033 [34mworld\033 [0m, this is \033 [1ma\033 [0m test string." ,
339
311
"EastAsian" : "こんにちは世界、これはテスト文字列です。" ,
340
312
"EastAsianWithANSI" : "\033 [32mこんにちは\033 [0m \033 [35m世界\033 [0m、これは\033 [4mテスト\033 [0m文字列です。" ,
341
- "LongSimpleASCII" : strings .Repeat ("abcdefghijklmnopqrstuvwxyz " , 20 ), // 27*20 = 540 chars
342
- "LongASCIIWithANSI" : strings .Repeat ("\033 [31ma\033 [32mb\033 [33mc\033 [34md\033 [35me\033 [36mf\033 [0m " , 50 ), // ~15*50 = 750 chars with ANSI
313
+ "LongSimpleASCII" : strings .Repeat ("abcdefghijklmnopqrstuvwxyz " , 20 ),
314
+ "LongASCIIWithANSI" : strings .Repeat ("\033 [31ma\033 [32mb\033 [33mc\033 [34md\033 [35me\033 [36mf\033 [0m " , 50 ),
343
315
}
344
316
345
317
func BenchmarkWidthFunction (b * testing.B ) {
346
318
eastAsianSettings := []bool {false , true }
347
319
348
320
for name , str := range benchmarkStrings {
349
321
for _ , eaSetting := range eastAsianSettings {
350
- // Ensure the global EastAsian setting is correct for the sub-benchmark
351
- // SetEastAsian also clears the cache, which is good for starting fresh.
352
322
SetEastAsian (eaSetting )
353
323
354
- // Benchmark: No Caching (using our internal non-cached version)
355
324
b .Run (fmt .Sprintf ("%s_EA%v_NoCache" , name , eaSetting ), func (b * testing.B ) {
356
325
b .ReportAllocs ()
357
326
for i := 0 ; i < b .N ; i ++ {
358
327
_ = WidthNoCache (str )
359
328
}
360
329
})
361
330
362
- // Benchmark: Cached Version - Cache Misses
363
- // We make strings unique to ensure cache misses.
364
- // SetEastAsian above already cleared the cache.
365
331
b .Run (fmt .Sprintf ("%s_EA%v_CacheMiss" , name , eaSetting ), func (b * testing.B ) {
366
332
b .ReportAllocs ()
367
333
for i := 0 ; i < b .N ; i ++ {
368
- // Make string unique for each iteration to force cache miss
369
334
_ = Width (str + strconv .Itoa (i ))
370
335
}
371
336
})
372
- resetGlobalCache () // Clear cache before the cache hit test
337
+ resetGlobalCache ()
373
338
374
- // Benchmark: Cached Version - Cache Hits
375
- // First call populates, subsequent calls hit.
376
- // SetEastAsian above (or resetGlobalCache) ensures cache is empty at start.
377
339
b .Run (fmt .Sprintf ("%s_EA%v_CacheHit" , name , eaSetting ), func (b * testing.B ) {
378
340
b .ReportAllocs ()
379
- // First call will populate the cache
380
341
if b .N > 0 {
381
342
_ = Width (str )
382
343
}
383
- // Subsequent calls should hit the cache
384
- for i := 1 ; i < b .N ; i ++ { // Start from 1 if first call is outside/setup
344
+ for i := 1 ; i < b .N ; i ++ {
385
345
_ = Width (str )
386
346
}
387
347
})
388
- resetGlobalCache () // Clean up for next iteration/test
348
+ resetGlobalCache ()
389
349
}
390
350
}
391
351
}
0 commit comments