mirror of
https://github.com/abiosoft/colima.git
synced 2026-05-17 12:10:34 +00:00
chore: fix regression in terminal output (#1567)
This commit is contained in:
+38
-11
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -20,15 +21,17 @@ type verboseWriter struct {
|
||||
buf bytes.Buffer
|
||||
lines []string
|
||||
|
||||
lineHeight int
|
||||
termWidth int
|
||||
overflow int
|
||||
lineHeight int
|
||||
termWidth int
|
||||
screenHeight int
|
||||
|
||||
lastUpdate time.Time
|
||||
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
var ansiControlSequence = regexp.MustCompile(`\x1b\[[0-?]*[ -/]*[@-~]`)
|
||||
|
||||
// NewVerboseWriter creates a new verbose writer.
|
||||
// A verbose writer pipes the input received to the stdout while tailing the specified lines.
|
||||
// Calling `Close` when done is recommended to clear the last uncleared output.
|
||||
@@ -109,6 +112,8 @@ func (v *verboseWriter) sanitizeLine(line string) string {
|
||||
}
|
||||
}
|
||||
|
||||
line = normalizeDisplayText(line)
|
||||
|
||||
return "> " + line
|
||||
}
|
||||
|
||||
@@ -117,15 +122,10 @@ func (v *verboseWriter) printScreen() error {
|
||||
return err
|
||||
}
|
||||
|
||||
v.overflow = 0
|
||||
v.screenHeight = 0
|
||||
for _, line := range v.lines {
|
||||
line = v.sanitizeLine(line)
|
||||
if len(line) > v.termWidth {
|
||||
v.overflow += len(line) / v.termWidth
|
||||
if len(line)%v.termWidth == 0 {
|
||||
v.overflow -= 1
|
||||
}
|
||||
}
|
||||
v.screenHeight += countDisplayLines(line, v.termWidth)
|
||||
line = color.HiBlackString(line)
|
||||
fmt.Println(line)
|
||||
}
|
||||
@@ -133,9 +133,10 @@ func (v *verboseWriter) printScreen() error {
|
||||
}
|
||||
|
||||
func (v *verboseWriter) clearScreen() {
|
||||
for i := 0; i < len(v.lines)+v.overflow; i++ {
|
||||
for i := 0; i < v.screenHeight; i++ {
|
||||
ClearLine()
|
||||
}
|
||||
v.screenHeight = 0
|
||||
}
|
||||
|
||||
func (v *verboseWriter) updateTerm() error {
|
||||
@@ -160,3 +161,29 @@ func (v *verboseWriter) updateTerm() error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func countDisplayLines(line string, termWidth int) int {
|
||||
if termWidth <= 0 {
|
||||
termWidth = 80
|
||||
}
|
||||
|
||||
visibleWidth := len([]rune(normalizeDisplayText(line)))
|
||||
if visibleWidth == 0 {
|
||||
return 1
|
||||
}
|
||||
|
||||
return ((visibleWidth - 1) / termWidth) + 1
|
||||
}
|
||||
|
||||
func normalizeDisplayText(line string) string {
|
||||
line = ansiControlSequence.ReplaceAllString(line, "")
|
||||
line = strings.ReplaceAll(line, "\r", "")
|
||||
line = strings.ReplaceAll(line, "\n", "")
|
||||
line = strings.Map(func(r rune) rune {
|
||||
if r < 32 && r != '\t' {
|
||||
return -1
|
||||
}
|
||||
return r
|
||||
}, line)
|
||||
return line
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package terminal
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestCountDisplayLines(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
line string
|
||||
termWidth int
|
||||
want int
|
||||
}{
|
||||
{name: "short line", line: "> short", termWidth: 80, want: 1},
|
||||
{name: "wrapped line", line: "> 12345678901", termWidth: 10, want: 2},
|
||||
{name: "exact width", line: "> 12345678", termWidth: 10, want: 1},
|
||||
{name: "carriage return ignored", line: "> abc\rdef", termWidth: 80, want: 1},
|
||||
{name: "ansi ignored", line: "> \x1b[90mabcdef\x1b[0m", termWidth: 4, want: 2},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := countDisplayLines(tt.line, tt.termWidth); got != tt.want {
|
||||
t.Fatalf("countDisplayLines(%q, %d) = %d, want %d", tt.line, tt.termWidth, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeDisplayText(t *testing.T) {
|
||||
input := "\x1b[90mhello\r\n\x07world\x1b[0m"
|
||||
if got, want := normalizeDisplayText(input), "helloworld"; got != want {
|
||||
t.Fatalf("normalizeDisplayText(%q) = %q, want %q", input, got, want)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user