mirror of
https://github.com/sorenisanerd/gotty.git
synced 2024-11-22 12:24:25 +00:00
115 lines
2.1 KiB
Go
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)
|
|
}
|