Allow OSC to be terminated by BEL
Also prevent changing streaming state unless in reset state
This commit is contained in:
parent
84cb2638d6
commit
12b0f632bd
@ -1,6 +1,9 @@
|
|||||||
package utils
|
package utils
|
||||||
|
|
||||||
import "bytes"
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
type parser_state uint8
|
type parser_state uint8
|
||||||
type csi_state uint8
|
type csi_state uint8
|
||||||
@ -13,6 +16,7 @@ const (
|
|||||||
esc
|
esc
|
||||||
csi
|
csi
|
||||||
st
|
st
|
||||||
|
st_or_bel
|
||||||
esc_st
|
esc_st
|
||||||
c1_st
|
c1_st
|
||||||
bracketed_paste
|
bracketed_paste
|
||||||
@ -40,7 +44,7 @@ type EscapeCodeParser struct {
|
|||||||
|
|
||||||
// Whether to send escape code bytes as soon as they are received or to
|
// Whether to send escape code bytes as soon as they are received or to
|
||||||
// buffer and send full escape codes
|
// buffer and send full escape codes
|
||||||
Streaming bool
|
streaming bool
|
||||||
|
|
||||||
// Callbacks
|
// Callbacks
|
||||||
HandleRune func(rune)
|
HandleRune func(rune)
|
||||||
@ -52,6 +56,18 @@ type EscapeCodeParser struct {
|
|||||||
HandleAPC func([]byte)
|
HandleAPC func([]byte)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (self *EscapeCodeParser) SetStreaming(streaming bool) error {
|
||||||
|
if self.state != normal || len(self.current_buffer) > 0 {
|
||||||
|
return fmt.Errorf("Cannot change streaming state when not in reset state")
|
||||||
|
}
|
||||||
|
self.streaming = streaming
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *EscapeCodeParser) IsStreaming() bool {
|
||||||
|
return self.streaming
|
||||||
|
}
|
||||||
|
|
||||||
func (self *EscapeCodeParser) Parse(data []byte) {
|
func (self *EscapeCodeParser) Parse(data []byte) {
|
||||||
prev := UTF8_ACCEPT
|
prev := UTF8_ACCEPT
|
||||||
codep := UTF8_ACCEPT
|
codep := UTF8_ACCEPT
|
||||||
@ -79,7 +95,7 @@ func (self *EscapeCodeParser) Reset() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (self *EscapeCodeParser) write_ch(ch byte) {
|
func (self *EscapeCodeParser) write_ch(ch byte) {
|
||||||
if self.Streaming {
|
if self.streaming {
|
||||||
if self.current_callback != nil {
|
if self.current_callback != nil {
|
||||||
var data [1]byte = [1]byte{ch}
|
var data [1]byte = [1]byte{ch}
|
||||||
self.current_callback(data[:])
|
self.current_callback(data[:])
|
||||||
@ -186,7 +202,7 @@ func (self *EscapeCodeParser) dispatch_char(ch UTF8State) {
|
|||||||
dispatch()
|
dispatch()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
} // end bracketed_paste
|
} // end self.state == bracketed_paste
|
||||||
|
|
||||||
switch ch {
|
switch ch {
|
||||||
case 0x1b:
|
case 0x1b:
|
||||||
@ -198,7 +214,7 @@ func (self *EscapeCodeParser) dispatch_char(ch UTF8State) {
|
|||||||
self.state = csi
|
self.state = csi
|
||||||
self.current_callback = self.HandleCSI
|
self.current_callback = self.HandleCSI
|
||||||
case 0x9d:
|
case 0x9d:
|
||||||
self.state = st
|
self.state = st_or_bel
|
||||||
self.current_callback = self.HandleOSC
|
self.current_callback = self.HandleOSC
|
||||||
case 0x98:
|
case 0x98:
|
||||||
self.state = st
|
self.state = st
|
||||||
@ -226,7 +242,7 @@ func (self *EscapeCodeParser) dispatch_byte(ch byte) {
|
|||||||
self.csi_state = parameter
|
self.csi_state = parameter
|
||||||
self.current_callback = self.HandleCSI
|
self.current_callback = self.HandleCSI
|
||||||
case ']':
|
case ']':
|
||||||
self.state = st
|
self.state = st_or_bel
|
||||||
self.current_callback = self.HandleOSC
|
self.current_callback = self.HandleOSC
|
||||||
case '^':
|
case '^':
|
||||||
self.state = st
|
self.state = st
|
||||||
@ -257,6 +273,12 @@ func (self *EscapeCodeParser) dispatch_byte(ch byte) {
|
|||||||
self.dispatch_esc_code()
|
self.dispatch_esc_code()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case st_or_bel:
|
||||||
|
if ch == 0x7 {
|
||||||
|
self.dispatch_esc_code()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fallthrough
|
||||||
case st:
|
case st:
|
||||||
if ch == 0x1b {
|
if ch == 0x1b {
|
||||||
self.state = esc_st
|
self.state = esc_st
|
||||||
|
|||||||
@ -29,9 +29,9 @@ func TestEscapeCodeParsing(t *testing.T) {
|
|||||||
d = test_parse_collection{}
|
d = test_parse_collection{}
|
||||||
}
|
}
|
||||||
|
|
||||||
check_test_result := func() {
|
check_test_result := func(raw string) {
|
||||||
if d.actual != d.expected {
|
if d.actual != d.expected {
|
||||||
t.Fatalf("actual != expected: %#v != %#v", string(d.actual), string(d.expected))
|
t.Fatalf("parsing: %#v actual != expected: %#v != %#v", raw, string(d.actual), string(d.expected))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,11 +39,15 @@ func TestEscapeCodeParsing(t *testing.T) {
|
|||||||
reset_test_parser()
|
reset_test_parser()
|
||||||
d.expected = "\n" + expected
|
d.expected = "\n" + expected
|
||||||
test_parser.Parse([]byte(raw))
|
test_parser.Parse([]byte(raw))
|
||||||
check_test_result()
|
check_test_result(raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
test("\x1b[31m\xc2\x9bm", "CSI: 31m\nCSI: m")
|
test("\x1b[31m\xc2\x9bm", "CSI: 31m\nCSI: m")
|
||||||
test("ab\nc", "CH: a\nCH: b\nCH: \n\nCH: c")
|
test("ab\nc", "CH: a\nCH: b\nCH: \n\nCH: c")
|
||||||
test("a\x1b[200m\x1b[mb\x1b[5:3;2;4~", "CH: a\nCSI: 200m\nCSI: m\nCH: b\nCSI: 5:3;2;4~")
|
test("a\x1b[200m\x1b[mb\x1b[5:3;2;4~", "CH: a\nCSI: 200m\nCSI: m\nCH: b\nCSI: 5:3;2;4~")
|
||||||
|
test("\x1b[200~a\x1b[201m\x1b[201~\x1b[x", "CH: a\nCH: \x1b\nCH: [\nCH: 2\nCH: 0\nCH: 1\nCH: m\nCSI: x")
|
||||||
|
test("a\x1bPb\x1b\x1bc\x1b\\d", "CH: a\nDCS: b\x1bc\nCH: d")
|
||||||
|
test("a\x1b_b\x1b\x1b\x1bc\x1b\\d", "CH: a\nAPC: b\x1b\x1bc\nCH: d")
|
||||||
|
test("\x1b]X\x07\x1b]X\x1b\x07\x1b\\", "OSC: X\nOSC: X\x1b\x07")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user