88 lines
1.5 KiB
Go
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
|
||
|
|
}
|