Skip to content

Commit

Permalink
Fixed String Terminator at the end of OSC
Browse files Browse the repository at this point in the history
Change the end of OSC to (escape '\\') and ('\a').
And (escape '\a') is corrected as a mistake.
  • Loading branch information
noborus committed Nov 30, 2024
1 parent 8c512ee commit d7e3d4b
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 58 deletions.
2 changes: 1 addition & 1 deletion oviewer/content_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@ func Test_StrToContentsHyperlink(t *testing.T) {
},
{
name: "testHyperLinkfile",
args: args{line: "\x1b]8;;file:///file\afile\x1b]8;;\a", tabWidth: 8},
args: args{line: "\x1b]8;;file:///file\afile\x1b]8;;\x1b\\", tabWidth: 8},
want: contents{
{width: 1, style: tcell.StyleDefault.Url("file:///file"), mainc: rune('f'), combc: nil},
{width: 1, style: tcell.StyleDefault.Url("file:///file"), mainc: rune('i'), combc: nil},
Expand Down
50 changes: 45 additions & 5 deletions oviewer/convert_es.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,16 @@ func (es *escapeSequence) paraseEscapeSequence(st *parseState) bool {
case systemSequence:
es.parseOSC(st, mainc)
return true
case oscControlSequence:
parameter := es.parameter.String()
es.parameter.Reset()
if mainc == '\\' { // ST(String Terminator).
st.style = oscStyle(st, parameter)
es.state = ansiText
return true
}
es.state = ansiText
return true
}
switch mainc {
case 0x1b:
Expand All @@ -121,7 +131,6 @@ func (es *escapeSequence) paraseEscapeSequence(st *parseState) bool {
case '\n':
return false
}
//log.Printf("mainc: %c, %#v", mainc, st.style)
return false
}

Expand Down Expand Up @@ -454,18 +463,49 @@ func parseRGBColor(red string, green string, blue string) (string, error) {
// parseOSC parses the OSC(Operating System Command Sequence) escape sequence.
func (es *escapeSequence) parseOSC(st *parseState, mainc rune) {
switch mainc {
case '\x1b': // ESC.
return
case '\\', '\a': // ST(String Terminator) (or BEL).
st.style = oscStyle(st, es.parameter.String())
case '\a': // BEL is also interpreted as ST.
parameter := es.parameter.String()
es.parameter.Reset()
if isOSC(parameter) {
st.style = oscStyle(st, parameter)
}
es.state = ansiText
return
case 0x1b: // ESC.
if isOSC(es.parameter.String()) {
es.state = oscControlSequence
return
}
es.parameter.Reset()
es.state = ansiControlSequence
return
}

es.parameter.WriteRune(mainc)
}

// isOSC returns true if the parameter is an OSC escape sequence.
func isOSC(parameter string) bool {
if parameter == "" {
return false
}
params := strings.Split(parameter, ";")
if len(params) < 2 {
return false
}
code, err := esNumber(params[0])
if err != nil {
return false
}
switch code { // OSC code.
case 8: // Hyperlink.
return true
}
return false
}

// oscStyle returns tcell.Style from the OSC control sequence.
// oscStyle only supports hyperlinks.
func oscStyle(st *parseState, paramStr string) tcell.Style {
params := strings.Split(paramStr, ";")
if len(params) < 2 {
Expand Down
52 changes: 0 additions & 52 deletions oviewer/convert_es_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package oviewer

import (
"reflect"
"strings"
"testing"

"github.com/gdamore/tcell/v2"
Expand Down Expand Up @@ -538,54 +537,3 @@ func Test_colorName(t *testing.T) {
})
}
}

func Test_escapeSequence_parseOSC(t *testing.T) {
type fields struct {
parameter string
state int
}
type args struct {
st *parseState
mainc rune
}
type want struct {
style tcell.Style
}
tests := []struct {
name string
fields fields
args args
want want
}{
{
name: "test-OSC",
fields: fields{
parameter: "8;;http://example.com",
state: ansiControlSequence,
},
args: args{
st: &parseState{
mainc: '\\',
},
mainc: 0x07,
},
want: want{
style: tcell.StyleDefault.Url("http://example.com"),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
parameter := strings.Builder{}
parameter.WriteString(tt.fields.parameter)
es := &escapeSequence{
parameter: parameter,
state: tt.fields.state,
}
es.parseOSC(tt.args.st, tt.args.mainc)
if tt.args.st.style != tt.want.style {
t.Errorf("escapeSequence.parseOSC() = %v, want %v", tt.args.st.style, tt.want.style)
}
})
}
}

0 comments on commit d7e3d4b

Please sign in to comment.