Merge branch 'develop': control sequence

This commit is contained in:
llaoj 2022-12-13 13:53:30 +08:00
commit 9813acaff3
2 changed files with 62 additions and 52 deletions

View File

@ -175,8 +175,9 @@ visit `http://127.0.0.1:8080/?arg=without-istio&arg=sleep-7b6d569576-57sjq&arg=s
```
...
2022/11/13 10:48:12 [write-log] {"arg":["without-istio","sleep-7b6d569576-57sjq","sleep","21001713"]} lsCR
2022/11/13 10:48:14 [write-log] {"arg":["without-istio","sleep-7b6d569576-57sjq","sleep","21001713"]} pwdCR
2022/12/13 13:36:46 [write-log] map[arg:[without-istio sleep-7b6d569576-8nz7t sleep 21001713]] ls[CR]
2022/12/13 13:37:25 [write-log] map[arg:[without-istio sleep-7b6d569576-8nz7t sleep 21001713]] echo[SPACE]hello[SPACE]world;[CR]
2022/12/13 13:47:00 [write-log] map[arg:[without-istio sleep-7b6d569576-8nz7t sleep 21001713]] [CUU][CR]
...
```

View File

@ -1,8 +1,11 @@
package utils
import "fmt"
import (
"fmt"
"regexp"
)
var CtrlChar = map[byte]string{
var ControlCodes = map[byte]string{
0: "NUL",
1: "SOH",
2: "STX",
@ -39,67 +42,73 @@ var CtrlChar = map[byte]string{
127: "DEL",
}
var CtrlCharGroup = map[string]string{
"1B5B41": "UP",
"1B5B42": "DOWN",
"1B5B43": "RIGHT",
"1B5B44": "LEFT",
// shell control codes
// codes[0]+codes[1]+codes[n-1]
// for example:
// [1B(ESC) 5B([) 32(2) 3B(;) 35(5) 52(R)]: row 2 col 5
// [1B(ESC) 5B([) 31(1) 30(0) 3B(;) 35(5) 52(R)]: row 10 col 5
// [1B(ESC) 5B([) 32(2) 32(2) 3B(;) 35(5) 52(R)]: row 22 col 5
"1B5B52": "",
// maybe there will be more control char group
// ...
// 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",
}
func FormatWriteLog(codes []byte, line *string) {
n := len(codes)
// when user uses the keyboard arrow keys
// arrow keys are combination of 3 ASCII codes
if n == 3 {
if str, exist := ASCIIGroupToStr(fmt.Sprintf("%X", codes)); exist {
*line += str
return
}
}
// for some shells
// they will automatically send some control characters
// after typing the command and pressing Enter
// which indicate the current row and column.
if n >= 6 {
if str, exist := ASCIIGroupToStr(fmt.Sprintf("%X", []byte{codes[0], codes[1], codes[n-1]})); exist {
*line += str
return
}
}
str := ASCIIToStr(codes)
*line += str
return
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 ASCIIToStr(codes []byte) (str string) {
func ControlCodesToStr(codes []byte) (str string) {
for _, code := range codes {
if value, ok := CtrlChar[code]; ok {
if value, ok := ControlCodes[code]; ok {
str += value
} else {
str += string(code)
}
}
return
}
func ASCIIGroupToStr(group string) (string, bool) {
if value, ok := CtrlCharGroup[group]; ok {
return value, true
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
}
}
return "", false
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)
}