@@ -7,9 +7,11 @@ import (
7
7
"strings"
8
8
"sync"
9
9
"time"
10
+ "unicode/utf8"
10
11
11
12
"github.com/charmbracelet/lipgloss"
12
13
"github.com/charmbracelet/lipgloss/table"
14
+ "golang.org/x/term"
13
15
)
14
16
15
17
var (
@@ -68,6 +70,33 @@ func PrintStream(text string) {
68
70
func PrintHeader (text string ) {
69
71
fmt .Println (headerStyle .Render (text ))
70
72
}
73
+ func FSuccess (text string ) string {
74
+ return successStyle .Render (text )
75
+ }
76
+ func FSuccess2 (text string ) string {
77
+ return success2Style .Render (text )
78
+ }
79
+ func FError (text string ) string {
80
+ return errorStyle .Render (text )
81
+ }
82
+ func FWarning (text string ) string {
83
+ return warningStyle .Render (text )
84
+ }
85
+ func FInfo (text string ) string {
86
+ return infoStyle .Render (text )
87
+ }
88
+ func FDebug (text string ) string {
89
+ return debugStyle .Render (text )
90
+ }
91
+ func FDetail (text string ) string {
92
+ return detailStyle .Render (text )
93
+ }
94
+ func FStream (text string ) string {
95
+ return streamStyle .Render (text )
96
+ }
97
+ func FHeader (text string ) string {
98
+ return headerStyle .Render (text )
99
+ }
71
100
72
101
// ======================================== =================
73
102
// ======================================== Table Definitions
@@ -85,6 +114,12 @@ func NewTable(headers []string) *Table {
85
114
Rows : [][]string {},
86
115
}
87
116
t .table = table .New ().Headers (headers ... )
117
+ t .table = t .table .StyleFunc (func (row , col int ) lipgloss.Style {
118
+ if row == table .HeaderRow {
119
+ return lipgloss .NewStyle ().Bold (true ).Align (lipgloss .Center ).Padding (0 , 1 )
120
+ }
121
+ return lipgloss .NewStyle ().Padding (0 , 1 )
122
+ })
88
123
return t
89
124
}
90
125
@@ -106,7 +141,7 @@ func (t *Table) FormatTable(useMarkdown bool) string {
106
141
}
107
142
108
143
func (t * Table ) PrintTable (useMarkdown bool ) {
109
- os . Stdout . WriteString (t .FormatTable (useMarkdown ))
144
+ fmt . Println (t .FormatTable (useMarkdown ))
110
145
}
111
146
112
147
func (t * Table ) WriteMarkdownTableToFile (outputPath string ) error {
@@ -303,26 +338,81 @@ func (m *Manager) AddStreamLine(name string, line string) {
303
338
m .mutex .Lock ()
304
339
defer m .mutex .Unlock ()
305
340
if info , exists := m .outputs [name ]; exists {
306
- if m .unlimitedOutput { // just append
307
- info .StreamLines = append (info .StreamLines , line )
341
+ // Wrap the line with indentation
342
+ wrappedLines := wrapText (line , basePadding + 4 )
343
+ if m .unlimitedOutput { // just append all wrapped lines
344
+ info .StreamLines = append (info .StreamLines , wrappedLines ... )
308
345
} else { // enforce size limit
309
346
currentLen := len (info .StreamLines )
310
- if currentLen + 1 > m .maxStreams {
311
- info .StreamLines = append (info .StreamLines [1 :], line )
347
+ totalNewLines := len (wrappedLines )
348
+ if currentLen + totalNewLines > m .maxStreams {
349
+ startIndex := currentLen + totalNewLines - m .maxStreams
350
+ if startIndex > currentLen {
351
+ startIndex = 0
352
+ existingToKeep := m .maxStreams - totalNewLines
353
+ if existingToKeep > 0 {
354
+ info .StreamLines = info .StreamLines [currentLen - existingToKeep :]
355
+ } else {
356
+ info .StreamLines = []string {} // All existing lines will be dropped
357
+ }
358
+ } else {
359
+ info .StreamLines = info .StreamLines [startIndex :]
360
+ }
361
+ info .StreamLines = append (info .StreamLines , wrappedLines ... )
312
362
} else {
313
- info .StreamLines = append (info .StreamLines , line )
363
+ info .StreamLines = append (info .StreamLines , wrappedLines ... )
364
+ }
365
+ if len (info .StreamLines ) > m .maxStreams {
366
+ info .StreamLines = info .StreamLines [len (info .StreamLines )- m .maxStreams :]
314
367
}
315
368
}
316
369
info .LastUpdated = time .Now ()
317
370
}
318
371
}
319
372
373
+ func GetTerminalWidth () int {
374
+ width , _ , err := term .GetSize (int (os .Stdout .Fd ()))
375
+ if err != nil || width <= 0 {
376
+ return 80 // Default fallback width if terminal width can't be determined
377
+ }
378
+ return width
379
+ }
380
+
381
+ func wrapText (text string , indent int ) []string {
382
+ termWidth := GetTerminalWidth ()
383
+ maxWidth := termWidth - indent - 2 // Account for indentation
384
+ if maxWidth <= 10 {
385
+ maxWidth = 80
386
+ }
387
+ if utf8 .RuneCountInString (text ) <= maxWidth {
388
+ return []string {text }
389
+ }
390
+ var lines []string
391
+ currentLine := ""
392
+ currentWidth := 0
393
+ for _ , r := range text {
394
+ runeWidth := 1
395
+ // If adding this rune would exceed max width, flush the line
396
+ if currentWidth + runeWidth > maxWidth {
397
+ lines = append (lines , currentLine )
398
+ currentLine = string (r )
399
+ currentWidth = runeWidth
400
+ } else {
401
+ currentLine += string (r )
402
+ currentWidth += runeWidth
403
+ }
404
+ }
405
+ if currentLine != "" {
406
+ lines = append (lines , currentLine )
407
+ }
408
+ return lines
409
+ }
410
+
320
411
func (m * Manager ) AddProgressBarToStream (name string , outof , final int64 , text string ) {
321
412
m .mutex .Lock ()
322
413
defer m .mutex .Unlock ()
323
414
if info , exists := m .outputs [name ]; exists {
324
- // percentage = max(0, min(percentage, 100))
325
- progressBar := PrintProgressBar (outof , final , 30 )
415
+ progressBar := PrintProgressBar (max (0 , outof ), final , 30 )
326
416
display := progressBar + debugStyle .Render (text )
327
417
info .StreamLines = []string {display } // Set as only stream so nothing else is displayed
328
418
info .LastUpdated = time .Now ()
@@ -348,7 +438,7 @@ func (m *Manager) ClearLines(n int) {
348
438
if n <= 0 {
349
439
return
350
440
}
351
- fmt .Printf ("\033 [%dA\033 [J" , n )
441
+ fmt .Printf ("\033 [%dA\033 [J" , min ( m . numLines , n ) )
352
442
m .numLines = max (m .numLines - n , 0 )
353
443
}
354
444
0 commit comments