@@ -219,16 +219,34 @@ public static void PrintParsedOptions<T>(T options) where T : class
219219
220220 string BuildBorder ( char left , char sep , char right , char fill )
221221 {
222- return string . Concat (
223- left ,
224- new string ( fill , nameWidth + 2 ) , sep ,
225- new string ( fill , valueWidth + 2 ) , sep ,
226- new string ( fill , requiredWidth + 2 ) , sep ,
227- new string ( fill , typeWidth + 2 ) , sep ,
228- new string ( fill , descWidth + 2 ) , sep ,
229- new string ( fill , defaultWidth + 2 ) ,
230- right
231- ) ;
222+ // 使用 string.Create 优化:单次分配创建边框字符串
223+ // Use string.Create for optimization: create border string with single allocation
224+ int totalLength = 1 + ( nameWidth + 2 ) + 1 + ( valueWidth + 2 ) + 1 + ( requiredWidth + 2 ) + 1 + ( typeWidth + 2 ) + 1 + ( descWidth + 2 ) + 1 + ( defaultWidth + 2 ) + 1 ;
225+ return string . Create ( totalLength , ( left , sep , right , fill , nameWidth , valueWidth , requiredWidth , typeWidth , descWidth , defaultWidth ) , static ( span , state ) =>
226+ {
227+ int pos = 0 ;
228+ var ( l , s , r , f , nw , vw , rw , tw , dw , dfw ) = state ;
229+
230+ span [ pos ++ ] = l ;
231+ span . Slice ( pos , nw + 2 ) . Fill ( f ) ;
232+ pos += nw + 2 ;
233+ span [ pos ++ ] = s ;
234+ span . Slice ( pos , vw + 2 ) . Fill ( f ) ;
235+ pos += vw + 2 ;
236+ span [ pos ++ ] = s ;
237+ span . Slice ( pos , rw + 2 ) . Fill ( f ) ;
238+ pos += rw + 2 ;
239+ span [ pos ++ ] = s ;
240+ span . Slice ( pos , tw + 2 ) . Fill ( f ) ;
241+ pos += tw + 2 ;
242+ span [ pos ++ ] = s ;
243+ span . Slice ( pos , dw + 2 ) . Fill ( f ) ;
244+ pos += dw + 2 ;
245+ span [ pos ++ ] = s ;
246+ span . Slice ( pos , dfw + 2 ) . Fill ( f ) ;
247+ pos += dfw + 2 ;
248+ span [ pos ] = r ;
249+ } ) ;
232250 }
233251
234252
@@ -306,19 +324,7 @@ static string TruncPadDisplay(string s, int width)
306324 var sb = new StringBuilder ( ) ;
307325 foreach ( var rune in s . EnumerateRunes ( ) )
308326 {
309- int v = rune . Value ;
310- bool wide =
311- ( v >= 0x4E00 && v <= 0x9FFF ) ||
312- ( v >= 0x3400 && v <= 0x4DBF ) ||
313- ( v >= 0x3000 && v <= 0x303F ) ||
314- ( v >= 0x3040 && v <= 0x309F ) ||
315- ( v >= 0x30A0 && v <= 0x30FF ) ||
316- ( v >= 0xAC00 && v <= 0xD7AF ) ||
317- ( v >= 0xF900 && v <= 0xFAFF ) ||
318- ( v >= 0xFF01 && v <= 0xFF60 ) ||
319- ( v >= 0xFFE0 && v <= 0xFFE6 ) ||
320- ( v >= 0x1F300 && v <= 0x1FAFF ) ;
321- int rw = wide ? 2 : 1 ;
327+ int rw = IsWideCharacter ( rune . Value ) ? 2 : 1 ;
322328 if ( w + rw > width )
323329 {
324330 if ( width > 1 )
@@ -356,19 +362,7 @@ static List<string> WrapToDisplayLines(string s, int width)
356362 int w = 0 ;
357363 foreach ( var rune in s . EnumerateRunes ( ) )
358364 {
359- int v = rune . Value ;
360- bool wide =
361- ( v >= 0x4E00 && v <= 0x9FFF ) ||
362- ( v >= 0x3400 && v <= 0x4DBF ) ||
363- ( v >= 0x3000 && v <= 0x303F ) ||
364- ( v >= 0x3040 && v <= 0x309F ) ||
365- ( v >= 0x30A0 && v <= 0x30FF ) ||
366- ( v >= 0xAC00 && v <= 0xD7AF ) ||
367- ( v >= 0xF900 && v <= 0xFAFF ) ||
368- ( v >= 0xFF01 && v <= 0xFF60 ) ||
369- ( v >= 0xFFE0 && v <= 0xFFE6 ) ||
370- ( v >= 0x1F300 && v <= 0x1FAFF ) ;
371- int rw = wide ? 2 : 1 ;
365+ int rw = IsWideCharacter ( rune . Value ) ? 2 : 1 ;
372366
373367 if ( w + rw > width )
374368 {
@@ -402,6 +396,7 @@ static List<string> WrapToDisplayLines(string s, int width)
402396 }
403397
404398 // 显示宽度相关函数:中文及全角字符按双列宽处理
399+ // Display width function: CJK and fullwidth characters are treated as double-width
405400 static int GetDisplayWidth ( string s )
406401 {
407402 if ( string . IsNullOrEmpty ( s ) )
@@ -412,24 +407,93 @@ static int GetDisplayWidth(string s)
412407 int w = 0 ;
413408 foreach ( var rune in s . EnumerateRunes ( ) )
414409 {
415- int v = rune . Value ;
416- bool wide =
417- ( v >= 0x4E00 && v <= 0x9FFF ) || // CJK Unified Ideographs
418- ( v >= 0x3400 && v <= 0x4DBF ) || // CJK Ext A
419- ( v >= 0x3000 && v <= 0x303F ) || // CJK Symbols & Punctuation
420- ( v >= 0x3040 && v <= 0x309F ) || // Hiragana
421- ( v >= 0x30A0 && v <= 0x30FF ) || // Katakana
422- ( v >= 0xAC00 && v <= 0xD7AF ) || // Hangul Syllables
423- ( v >= 0xF900 && v <= 0xFAFF ) || // CJK Compatibility Ideographs
424- ( v >= 0xFF01 && v <= 0xFF60 ) || // Fullwidth ASCII variants
425- ( v >= 0xFFE0 && v <= 0xFFE6 ) || // Fullwidth symbols
426- ( v >= 0x1F300 && v <= 0x1FAFF ) ; // Emoji & Symbols (approx)
427- w += wide ? 2 : 1 ;
410+ w += IsWideCharacter ( rune . Value ) ? 2 : 1 ;
428411 }
429412
430413 return w ;
431414 }
432415
416+ /// <summary>
417+ /// 判断字符是否为宽字符(在终端中占用两个字符宽度)
418+ /// Determines if a character is wide (occupies two character widths in terminal)
419+ /// </summary>
420+ /// <param name="codePoint">Unicode 码点 / Unicode code point</param>
421+ /// <returns>是否为宽字符 / Whether the character is wide</returns>
422+ static bool IsWideCharacter ( int codePoint )
423+ {
424+ // 基于 Unicode 标准的宽字符范围判断
425+ // Based on Unicode standard wide character ranges
426+ return codePoint switch
427+ {
428+ // CJK 统一汉字 / CJK Unified Ideographs
429+ >= 0x4E00 and <= 0x9FFF => true ,
430+ // CJK 扩展 A / CJK Extension A
431+ >= 0x3400 and <= 0x4DBF => true ,
432+ // CJK 扩展 B-F / CJK Extensions B-F
433+ >= 0x20000 and <= 0x2CEAF => true ,
434+ // CJK 扩展 G / CJK Extension G
435+ >= 0x30000 and <= 0x3134F => true ,
436+ // CJK 兼容汉字 / CJK Compatibility Ideographs
437+ >= 0xF900 and <= 0xFAFF => true ,
438+ // CJK 兼容补充 / CJK Compatibility Supplement
439+ >= 0x2F800 and <= 0x2FA1F => true ,
440+ // CJK 符号和标点 / CJK Symbols & Punctuation
441+ >= 0x3000 and <= 0x303F => true ,
442+ // 平假名 / Hiragana
443+ >= 0x3040 and <= 0x309F => true ,
444+ // 片假名 / Katakana
445+ >= 0x30A0 and <= 0x30FF => true ,
446+ // 日文兼容片假名 / Katakana Phonetic Extensions
447+ >= 0x31F0 and <= 0x31FF => true ,
448+ // 韩文字母 / Hangul
449+ >= 0xAC00 and <= 0xD7AF => true ,
450+ // 韩文兼容字母 / Hangul Jamo
451+ >= 0x1100 and <= 0x11FF => true ,
452+ // 全角 ASCII 变体 / Fullwidth ASCII variants
453+ >= 0xFF01 and <= 0xFF60 => true ,
454+ // 全角符号 / Fullwidth symbols
455+ >= 0xFFE0 and <= 0xFFE6 => true ,
456+ // 箭头符号 / Arrows
457+ >= 0x2190 and <= 0x21FF => true ,
458+ // 数学运算符 / Mathematical Operators
459+ >= 0x2200 and <= 0x22FF => true ,
460+ // 制表符 / Box Drawing
461+ >= 0x2500 and <= 0x257F => true ,
462+ // 方块元素 / Block Elements
463+ >= 0x2580 and <= 0x259F => true ,
464+ // 几何图形 / Geometric Shapes
465+ >= 0x25A0 and <= 0x25FF => true ,
466+ // 杂项符号 / Miscellaneous Symbols
467+ >= 0x2600 and <= 0x26FF => true ,
468+ // 丁贝符 / Dingbats
469+ >= 0x2700 and <= 0x27BF => true ,
470+ // 表情符号 / Emoji & Symbols
471+ >= 0x1F000 and <= 0x1FAFF => true ,
472+ // 音乐符号 / Musical Symbols
473+ >= 0x1D000 and <= 0x1D24F => true ,
474+ // 古代符号 / Ancient Symbols
475+ >= 0x10100 and <= 0x1013F => true ,
476+ // 货币符号 / Currency Symbols (部分为宽字符)
477+ >= 0x20A0 and <= 0x20CF => true ,
478+ // 字母式符号 / Letterlike Symbols
479+ >= 0x2100 and <= 0x214F => true ,
480+ // 数字形式 / Number Forms
481+ >= 0x2150 and <= 0x218F => true ,
482+ // 泰文 / Thai (部分为宽字符)
483+ >= 0x0E01 and <= 0x0E7F => true ,
484+ // 藏文 / Tibetan
485+ >= 0x0F00 and <= 0x0FFF => true ,
486+ // 蒙古文 / Mongolian
487+ >= 0x1800 and <= 0x18AF => true ,
488+ // 彝文 / Yi
489+ >= 0xA000 and <= 0xA48F => true ,
490+ // 傈僳文 / Lisu
491+ >= 0xA4D0 and <= 0xA4FF => true ,
492+ // 预设:窄字符 / Default: narrow character
493+ _ => false
494+ } ;
495+ }
496+
433497 /// <summary>
434498 /// 格式化属性值用于显示
435499 /// </summary>
0 commit comments