gotty/utils/log.go
2022-12-13 13:52:15 +08:00

115 lines
2.1 KiB
Go

package utils
import (
"fmt"
"regexp"
)
var ControlCodes = map[byte]string{
0: "NUL",
1: "SOH",
2: "STX",
3: "ETX",
4: "EOT",
5: "ENQ",
6: "ACK",
7: "BEL",
8: "BS",
9: "HT",
10: "LF",
11: "VT",
12: "FF",
13: "CR",
14: "SO",
15: "SI",
16: "DLE",
17: "DCI",
18: "DC2",
19: "DC3",
20: "DC4",
21: "NAK",
22: "SYN",
23: "TB",
24: "CAN",
25: "EM",
26: "SUB",
27: "ESC",
28: "FS",
29: "GS",
30: "RS",
31: "US",
32: "SPACE",
127: "DEL",
}
// https://en.wikipedia.org/wiki/ANSI_escape_code
// https://xtermjs.org/docs/api/vtfeatures/
var ControlSequences = map[string]string{
// Cursor Up
"ESC[A": "CUU",
// Cursor Down
"ESC[B": "CUD",
// Cursor Forward
"ESC[C": "CUF",
// Cursor Back
"ESC[D": "CUB",
}
var ControlSequencePatterns = map[string]string{
// Device Status Report
// Reports the cursor position (CPR) by transmitting `ESC[n;mR`, where n is the row and m is the column.
"^ESC\\[\\d+;\\d+R$": "",
}
func ControlCodesToStr(codes []byte) (str string) {
for _, code := range codes {
if value, ok := ControlCodes[code]; ok {
str += value
} else {
str += string(code)
}
}
return
}
func ControlCodesToEscapedStr(codes []byte) (str string) {
for _, code := range codes {
if value, ok := ControlCodes[code]; ok {
str += fmt.Sprintf("[%s]", value)
} else if code == 91 || code == 92 || code == 93 {
// escaping [ ] \
str += fmt.Sprintf("\\%s", string(code))
} else {
str += string(code)
}
}
return
}
func ControlSequenceToStr(codes []byte) (string, bool) {
sequence := ControlCodesToStr(codes)
for key, value := range ControlSequences {
if key == sequence {
return fmt.Sprintf("[%s]", value), true
}
}
for key, value := range ControlSequencePatterns {
if regexp.MustCompile(key).Match([]byte(sequence)) {
return value, true
}
}
return sequence, false
}
func FormatWriteLog(codes []byte, line *string) {
n := len(codes)
if n >= 3 {
if str, exists := ControlSequenceToStr(codes); exists {
*line += str
return
}
}
*line += ControlCodesToEscapedStr(codes)
}