-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathansiParser.go
208 lines (176 loc) · 4.93 KB
/
ansiParser.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
package gotel
import(
"log"
)
// ForeColor Text foreground color
const ForeColor int = 30
// BackColor Text background color
const BackColor int = 40
// Color Text color
type Color uint8
const (
// Black Black
Black Color = 0
// Red Red
Red Color = 1
// Green Green
Green Color = 2
// Yellow Yellow
Yellow Color = 3
// Blue Blue
Blue Color = 4
// Magenta Megenta
Magenta Color = 5
// Cyan Cyan
Cyan Color = 6
// White White
White Color = 7
)
// TextFormat Text format
type TextFormat uint8
const (
// Normal Normal
Normal TextFormat = 0
// Bold Blod
Bold TextFormat = 1
// Faint Faint
Faint TextFormat = 2
// Italic Italic
Italic TextFormat = 3
// Underline Underline
Underline TextFormat = 4
// Blink Blink
Blink TextFormat = 5
// Reverse Reverse text color
Reverse TextFormat = 7
// NonDisplay NonDisplay
NonDisplay TextFormat = 8
)
// AnsiProperty Ansi text property for record ansi escape codes
type AnsiProperty struct {
IsBlod bool
IsFaint bool
IsUnderline bool
IsBlink bool
IsReverse bool
IsNonDisplay bool
TextForeColor uint8
TextBackColor uint8
}
// AnsiState ANSI parser state
type AnsiState uint8
const (
// StateText In text state
StateText AnsiState = 0
// StateESC In ESC state
StateESC AnsiState = 1
// StateC0 In C0 state, 2 char cmd, 00 ~ 1F
// StateC0 AnsiState = 2
// StateIntermediate In Intermediate state, 3 char cmd, 20 ~ 2F
StateIntermediate AnsiState = 2
// StateParameter In Parameter state, 2 char cmd, 30 ~ 3F
// StateParameter AnsiState = 3
// StateC1 In C1 state (Uppercase), 2 char cmd, 40 ~ 5F (CSI special)
// StateC1 AnsiState = 4
// StateLowercase In Alphabetic state, 2 char cmd, 60 ~ 7E
// StateLowercase AnsiState = 5
// StateCSI In CSI state, n char cmd, 1B
StateCSI AnsiState = 6
)
// AnsiCommand ANSI Command
type AnsiCommand uint8
const (
// CmdText This byte is text
CmdText AnsiCommand = 0
// CmdParsing This byte is do nothing
CmdParsing AnsiCommand = 1
)
// AnsiParser comment
type AnsiParser struct {
ansiCmd AnsiCommand
state AnsiState
property AnsiProperty
tempCommand []byte
}
// NewAnsiParser Create new ANSI parser
func NewAnsiParser() *AnsiParser {
a := AnsiParser {
CmdText,
StateText,
AnsiProperty{},
make([]byte, 0, 16),
}
return &a
}
// AddByte Add a byte
func (a *AnsiParser) AddByte(b byte) AnsiCommand {
switch a.state {
case StateText:
switch b {
case 27: // esc
a.state = StateESC
a.ansiCmd = CmdParsing
default:
a.ansiCmd = CmdText
}
case StateESC:
switch {
case b == 0x1B || b == 0x9B: // CSI state (n char)
a.state = StateCSI
a.ansiCmd = CmdParsing
case b >= 0x00 && b <= 0x1F: // C0 state (2 char)
a.state = StateText
a.ansiCmd = a.CommandC0(b)
case b >= 0x20 && b <= 0x2F: // Intermediate state (only support 3 word now)
a.state = StateIntermediate
a.ansiCmd = CmdParsing
case b >= 0x30 && b <= 0x3F: // Parameter state (2 char)
a.state = StateText
a.ansiCmd = a.CommandParameter(b)
case b >= 0x40 && b <= 0x5F: // C1 state (2 char)
a.state = StateText
a.ansiCmd = a.CommandC1(b)
case b >= 0x60 && b <= 0x7E: // Lowercase state (2 char)
a.state = StateText
a.ansiCmd = a.CommandLowercase(b)
case b >= 0x80 && b <= 0x9F: // C1 state (2 char)
a.state = StateText
a.ansiCmd = a.CommandC1(b)
}
case StateIntermediate:
a.tempCommand = append(a.tempCommand, b)
if len(a.tempCommand) == 2 { // TODO b >= 0x30 && b <= 0x7E or b == 0x20 ?
a.ansiCmd = a.CommandIntermediate(a.tempCommand[0], a.tempCommand[1])
a.tempCommand = a.tempCommand[:0]
a.state = StateText
}
case StateCSI:
if b >= 0x40 && b <= 0x7E {
// CSI command finish
a.ansiCmd = a.CommandCSI(a.tempCommand, b)
a.tempCommand = a.tempCommand[:0]
a.state = StateText
} else {
a.tempCommand = append(a.tempCommand, b)
}
}
return a.ansiCmd
}
// CommandCSI comment
func (a *AnsiParser) CommandCSI(param []byte, cmd byte) AnsiCommand {
}
// CommandC0 comment
func (a *AnsiParser) CommandC0(b byte) AnsiCommand {
}
// CommandIntermediate Only support 3 char command
func (a *AnsiParser) CommandIntermediate(b1 byte, b2 byte) AnsiCommand {
}
// CommandParameter comment
func (a *AnsiParser) CommandParameter(b byte) AnsiCommand {
}
// CommandC1 comment
func (a *AnsiParser) CommandC1(b byte) AnsiCommand {
}
// CommandLowercase comment
func (a *AnsiParser) CommandLowercase(b byte) AnsiCommand {
}