turbo-editors/turbo-corepublic Fork 0
28d59854361aeda8541d853093e732126f3d7bff
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-core.git
git clone ssh://git@rickub.com/turbo-editors/turbo-core.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

parser_escape.go · 100 lines · 2.7 KBGo Blame HistoryRaw
🛟 Updated. 28d5985 k33g 20h ago1package terminal
2
3// stepAfterEscape decides what kind of sequence an ESC begins.
4func (p *Parser) stepAfterEscape(b byte) {
5 switch b {
6 case '[':
7 p.state = inCSI
8 case ']':
9 p.state = inOSC
10 p.osc = p.osc[:0]
11 case 'P', 'X', '^', '_':
12 // A device control, privacy message or application command. None is
13 // implemented, and all of them run to a string terminator.
14 p.state = inOSC
15 p.osc = p.osc[:0]
16 case '(', ')', '*', '+', '%', '#', ' ':
17 // A character-set or size selector: one more byte follows, and this
18 // emulator works in UTF-8 regardless.
19 p.state = ignoring
20 default:
21 p.simpleEscape(b)
22 p.state = ground
23 }
24}
25
26// simpleEscape runs the escape sequences that are one byte long.
27func (p *Parser) simpleEscape(b byte) {
28 switch b {
29 case 'D': // IND, index: down one line, scrolling if need be.
30 p.screen.LineFeed()
31 case 'M': // RI, reverse index: up one line, scrolling if need be.
32 p.screen.ReverseLineFeed()
33 case 'E': // NEL, next line.
34 p.screen.CarriageReturn()
35 p.screen.LineFeed()
36 case '7': // DECSC, save the cursor and the style.
37 p.screen.SaveCursor()
38 case '8': // DECRC, restore them.
39 p.screen.RestoreCursor()
40 case 'c': // RIS, reset to the initial state.
41 p.screen.Reset()
42 }
43 // Anything else — keypad modes, character sets — changes nothing this
44 // emulator models, and is dropped rather than printed.
45}
46
47// stepIgnoring skips the one byte that completes a sequence being ignored.
48func (p *Parser) stepIgnoring(byte) {
49 p.state = ground
50}
51
52// stepOSC collects an operating-system command until its terminator.
53func (p *Parser) stepOSC(b byte) {
54 switch {
55 case b == bell:
56 p.endOSC()
57 case b == escape:
58 p.state = inOSCEscape
59 case len(p.osc) >= maxOSC:
60 // A program that has sent this much without a terminator is not going
61 // to send one.
62 p.state = ground
63 default:
64 p.osc = append(p.osc, b)
65 }
66}
67
68// stepOSCEscape decides whether the ESC inside an OSC ended it.
69func (p *Parser) stepOSCEscape(b byte) {
70 if b == '\\' { // ST, the string terminator.
71 p.endOSC()
72 return
73 }
74
75 // It was not a terminator, so the OSC is abandoned and this byte starts
76 // whatever the ESC really began.
77 p.state = ground
78 p.step(escape)
79 p.step(b)
80}
81
82// endOSC acts on a completed operating-system command.
83//
84// Only the window title is kept. The rest — colour palettes, clipboard
85// requests, working-directory hints — is dropped, which is what a terminal
86// that does not implement them is expected to do.
87func (p *Parser) endOSC() {
88 p.state = ground
89
90 command := string(p.osc)
91 p.osc = p.osc[:0]
92
93 // "0;title" sets both the icon name and the title; "2;title" the title.
94 for _, prefix := range []string{"0;", "2;"} {
95 if len(command) >= len(prefix) && command[:len(prefix)] == prefix {
96 p.title = command[len(prefix):]
97 return
98 }
99 }
100}