Bugfixes in ANSI escape sequence handling as well as TextView, fixes #320, fixes #344

This commit is contained in:
Oliver 2020-05-27 21:41:21 +02:00 committed by Trevor Slocum
parent 81cfea205d
commit 06a427a43a
2 changed files with 43 additions and 23 deletions

56
ansi.go
View File

@ -24,6 +24,7 @@ type ansi struct {
// Reusable buffers.
buffer *bytes.Buffer // The entire output text of one Write().
csiParameter, csiIntermediate *bytes.Buffer // Partial CSI strings.
attributes string // The buffer's current text attributes (a tview attribute string).
// The current state of the parser. One of the ansi constants.
state int
@ -89,13 +90,12 @@ func (a *ansi) Write(text []byte) (int, error) {
}
fmt.Fprint(a.buffer, strings.Repeat("\n", count))
case 'm': // Select Graphic Rendition.
var (
background, foreground, attributes string
clearAttributes bool
)
fields := strings.Split(a.csiParameter.String(), ";")
if len(fields) == 0 || len(fields) == 1 && fields[0] == "0" {
var background, foreground string
params := a.csiParameter.String()
fields := strings.Split(params, ";")
if len(params) == 0 || len(fields) == 1 && fields[0] == "0" {
// Reset.
a.attributes = ""
if _, err := a.buffer.WriteString("[-:-:-]"); err != nil {
return 0, err
}
@ -128,17 +128,36 @@ func (a *ansi) Write(text []byte) (int, error) {
for index, field := range fields {
switch field {
case "1", "01":
attributes += "b"
if strings.IndexRune(a.attributes, 'b') < 0 {
a.attributes += "b"
}
case "2", "02":
attributes += "d"
if strings.IndexRune(a.attributes, 'd') < 0 {
a.attributes += "d"
}
case "4", "04":
attributes += "u"
if strings.IndexRune(a.attributes, 'u') < 0 {
a.attributes += "u"
}
case "5", "05":
attributes += "l"
case "7", "07":
attributes += "7"
case "22", "24", "25", "27":
clearAttributes = true
if strings.IndexRune(a.attributes, 'l') < 0 {
a.attributes += "l"
}
case "22":
if i := strings.IndexRune(a.attributes, 'b'); i >= 0 {
a.attributes = a.attributes[:i] + a.attributes[i+1:]
}
if i := strings.IndexRune(a.attributes, 'd'); i >= 0 {
a.attributes = a.attributes[:i] + a.attributes[i+1:]
}
case "24":
if i := strings.IndexRune(a.attributes, 'u'); i >= 0 {
a.attributes = a.attributes[:i] + a.attributes[i+1:]
}
case "25":
if i := strings.IndexRune(a.attributes, 'l'); i >= 0 {
a.attributes = a.attributes[:i] + a.attributes[i+1:]
}
case "30", "31", "32", "33", "34", "35", "36", "37":
colorNumber, _ := strconv.Atoi(field)
foreground = lookupColor(colorNumber - 30)
@ -188,11 +207,12 @@ func (a *ansi) Write(text []byte) (int, error) {
break FieldLoop
}
}
if len(attributes) > 0 || clearAttributes {
attributes = ":" + attributes
var colon string
if len(a.attributes) > 0 {
colon = ":"
}
if len(foreground) > 0 || len(background) > 0 || len(attributes) > 0 {
fmt.Fprintf(a.buffer, "[%s:%s%s]", foreground, background, attributes)
if len(foreground) > 0 || len(background) > 0 || len(a.attributes) > 0 {
fmt.Fprintf(a.buffer, "[%s:%s%s%s]", foreground, background, colon, a.attributes)
}
}
a.state = ansiText

View File

@ -768,7 +768,10 @@ func (t *TextView) reindexBuffer(width int) {
// Initial states.
regionID := ""
var highlighted bool
var (
highlighted bool
foregroundColor, backgroundColor, attributes string
)
// Go through each line in the buffer.
for bufferIndex, str := range t.buffer {
@ -809,10 +812,7 @@ func (t *TextView) reindexBuffer(width int) {
}
// Create index from split lines.
var (
originalPos, colorPos, regionPos, escapePos int
foregroundColor, backgroundColor, attributes string
)
var originalPos, colorPos, regionPos, escapePos int
for _, splitLine := range splitLines {
line := &textViewIndex{
Line: bufferIndex,