@@ -60,7 +60,7 @@ func (a *App) ToTabularMarkdown(opts ...TabularOption) (string, error) {
60
60
Name : a .Name ,
61
61
Description : tt .PrepareMultilineString (a .Description ),
62
62
Usage : tt .PrepareMultilineString (a .Usage ),
63
- UsageText : tt . PrepareMultilineString (a .UsageText ),
63
+ UsageText : strings . FieldsFunc (a .UsageText , func ( r rune ) bool { return r == '\n' } ),
64
64
ArgsUsage : tt .PrepareMultilineString (a .ArgsUsage ),
65
65
GlobalFlags : tt .PrepareFlags (a .VisibleFlags ()),
66
66
Commands : tt .PrepareCommands (a .VisibleCommands (), o .appPath , "" , 0 ),
@@ -256,24 +256,26 @@ func prepareUsage(command *Command, usageText string) string {
256
256
257
257
type (
258
258
cliTabularAppTemplate struct {
259
- AppPath string
260
- Name string
261
- Usage , UsageText , ArgsUsage string
262
- Description string
263
- GlobalFlags []cliTabularFlagTemplate
264
- Commands []cliTabularCommandTemplate
259
+ AppPath string
260
+ Name string
261
+ Usage , ArgsUsage string
262
+ UsageText []string
263
+ Description string
264
+ GlobalFlags []cliTabularFlagTemplate
265
+ Commands []cliTabularCommandTemplate
265
266
}
266
267
267
268
cliTabularCommandTemplate struct {
268
- AppPath string
269
- Name string
270
- Aliases []string
271
- Usage , UsageText , ArgsUsage string
272
- Description string
273
- Category string
274
- Flags []cliTabularFlagTemplate
275
- SubCommands []cliTabularCommandTemplate
276
- Level uint
269
+ AppPath string
270
+ Name string
271
+ Aliases []string
272
+ Usage , ArgsUsage string
273
+ UsageText []string
274
+ Description string
275
+ Category string
276
+ Flags []cliTabularFlagTemplate
277
+ SubCommands []cliTabularCommandTemplate
278
+ Level uint
277
279
}
278
280
279
281
cliTabularFlagTemplate struct {
@@ -299,7 +301,7 @@ func (tt tabularTemplate) PrepareCommands(commands []*Command, appPath, parentCo
299
301
Name : strings .TrimSpace (strings .Join ([]string {parentCommandName , cmd .Name }, " " )),
300
302
Aliases : cmd .Aliases ,
301
303
Usage : tt .PrepareMultilineString (cmd .Usage ),
302
- UsageText : tt . PrepareMultilineString (cmd .UsageText ),
304
+ UsageText : strings . FieldsFunc (cmd .UsageText , func ( r rune ) bool { return r == '\n' } ),
303
305
ArgsUsage : tt .PrepareMultilineString (cmd .ArgsUsage ),
304
306
Description : tt .PrepareMultilineString (cmd .Description ),
305
307
Category : cmd .Category ,
@@ -375,8 +377,14 @@ func (tabularTemplate) PrepareMultilineString(s string) string {
375
377
}
376
378
377
379
func (tabularTemplate ) Prettify (s string ) string {
378
- s = regexp .MustCompile (`\n{2,}` ).ReplaceAllString (s , "\n \n " ) // normalize newlines
379
- s = strings .Trim (s , " \n " ) // trim spaces and newlines
380
+ var max = func (x , y int ) int {
381
+ if x > y {
382
+ return x
383
+ }
384
+ return y
385
+ }
386
+
387
+ var b strings.Builder
380
388
381
389
// search for tables
382
390
for _ , rawTable := range regexp .MustCompile (`(?m)^(\|[^\n]+\|\r?\n)((?:\|:?-+:?)+\|)(\n(?:\|[^\n]+\|\r?\n?)*)?$` ).FindAllString (s , - 1 ) {
@@ -406,11 +414,14 @@ func (tabularTemplate) Prettify(s string) string {
406
414
407
415
// calculate max lengths
408
416
var lengths = make ([]int , len (matrix [0 ]))
409
- const padding = 2 // 2 spaces for padding
410
- for _ , row := range matrix {
417
+ for n , row := range matrix {
411
418
for i , cell := range row {
412
- if len (cell ) > lengths [i ]- padding {
413
- lengths [i ] = utf8 .RuneCountInString (cell ) + padding
419
+ if n == 1 {
420
+ continue // skip separator
421
+ }
422
+
423
+ if l := utf8 .RuneCountInString (cell ); l > lengths [i ] {
424
+ lengths [i ] = l
414
425
}
415
426
}
416
427
}
@@ -420,37 +431,57 @@ func (tabularTemplate) Prettify(s string) string {
420
431
for j , cell := range row {
421
432
if i == 1 { // is separator
422
433
if centered [j ] {
423
- cell = ":" + strings .Repeat ("-" , lengths [j ]- 2 ) + ":"
434
+ b .Reset ()
435
+ b .WriteRune (':' )
436
+ b .WriteString (strings .Repeat ("-" , max (0 , lengths [j ])))
437
+ b .WriteRune (':' )
438
+
439
+ row [j ] = b .String ()
424
440
} else {
425
- cell = strings .Repeat ("-" , lengths [j ]+ 1 )
441
+ row [ j ] = strings .Repeat ("-" , max ( 0 , lengths [j ]+ 2 ) )
426
442
}
443
+
444
+ continue
427
445
}
428
446
429
447
var (
430
- padLeft , padRight = 1 , 1
431
448
cellWidth = utf8 .RuneCountInString (cell )
449
+ padLeft , padRight = 1 , max (1 , lengths [j ]- cellWidth + 1 ) // align to the left
432
450
)
433
451
434
452
if centered [j ] { // is centered
435
- padLeft = (lengths [j ] - cellWidth ) / 2
436
- padRight = lengths [j ] - cellWidth - padLeft
437
- } else if i == 1 { // is header
438
- padLeft , padRight = 0 , 0
439
- } else { // align to the left
440
- padRight = lengths [j ] - cellWidth
453
+ padLeft = max (1 , (lengths [j ]- cellWidth )/ 2 )
454
+ padRight = max (1 , lengths [j ]- cellWidth - (padLeft - 1 ))
441
455
}
442
456
443
- row [j ] = strings .Repeat (" " , padLeft ) + cell + strings .Repeat (" " , padRight )
457
+ b .Reset ()
458
+ b .WriteString (strings .Repeat (" " , padLeft ))
459
+
460
+ if padLeft + cellWidth + padRight <= lengths [j ]+ 1 {
461
+ b .WriteRune (' ' ) // add an extra space if the cell is not full
462
+ }
463
+
464
+ b .WriteString (cell )
465
+ b .WriteString (strings .Repeat (" " , padRight ))
466
+
467
+ row [j ] = b .String ()
444
468
}
445
469
}
446
470
447
- var newTable string
471
+ b .Reset ()
472
+
448
473
for _ , row := range matrix { // build new table
449
- newTable += "|" + strings .Join (row , "|" ) + "|\n "
474
+ b .WriteRune ('|' )
475
+ b .WriteString (strings .Join (row , "|" ))
476
+ b .WriteRune ('|' )
477
+ b .WriteRune ('\n' )
450
478
}
451
479
452
- s = strings .Replace (s , rawTable , newTable , 1 )
480
+ s = strings .Replace (s , rawTable , b . String () , 1 )
453
481
}
454
482
483
+ s = regexp .MustCompile (`\n{2,}` ).ReplaceAllString (s , "\n \n " ) // normalize newlines
484
+ s = strings .Trim (s , " \n " ) // trim spaces and newlines
485
+
455
486
return s + "\n " // add an extra newline
456
487
}
0 commit comments