Files

88 lines
1.5 KiB
Go

package terminal
import (
"strings"
"unicode/utf8"
)
const textLimit = 64 << 10
func Text(b []byte) string {
out := strings.Builder{}
line := []rune{}
col := 0
flush := func() {
out.WriteString(strings.TrimRight(string(line), " "))
out.WriteByte('\n')
line = line[:0]
col = 0
}
for i := 0; i < len(b); {
c := b[i]
switch {
case c == 0x1b:
end, final := skipEscape(b, i)
if final == 'K' {
line = line[:min(col, len(line))]
}
i = end + 1
continue
case c == '\n':
flush()
case c == '\r':
col = 0
case c == '\b':
col = max(0, col-1)
case c == '\t' || c >= 0x20 && c != 0x7f:
r, n := utf8.DecodeRune(b[i:])
for len(line) < col {
line = append(line, ' ')
}
if col < len(line) {
line[col] = r
} else {
line = append(line, r)
}
col++
i += n
continue
}
i++
}
s := out.String() + strings.TrimRight(string(line), " ")
if len(s) > textLimit {
s = s[len(s)-textLimit:]
s = s[strings.IndexByte(s, '\n')+1:]
}
return s
}
func skipEscape(b []byte, i int) (int, byte) {
if i+1 >= len(b) {
return i, 0
}
i++
switch b[i] {
case '[':
for i++; i < len(b); i++ {
if b[i] >= 0x40 && b[i] <= 0x7e {
return i, b[i]
}
}
return len(b) - 1, 0
case ']', 'P', '_', '^':
for i++; i < len(b); i++ {
if b[i] == 0x07 {
return i, 0
}
if b[i] == 0x1b && i+1 < len(b) && b[i+1] == '\\' {
return i + 1, 0
}
}
return len(b) - 1, 0
case '(', ')', '*', '+', '#', '%':
return min(i+1, len(b)-1), 0
}
return i, 0
}