mirror of https://github.com/rivo/tview.git
Fixed region/color tag escaping bug. Fixes #234
This commit is contained in:
parent
84fdb36408
commit
a45c8edf60
2
table.go
2
table.go
|
@ -697,7 +697,7 @@ ColumnLoop:
|
||||||
expansion := 0
|
expansion := 0
|
||||||
for _, row := range rows {
|
for _, row := range rows {
|
||||||
if cell := getCell(row, column); cell != nil {
|
if cell := getCell(row, column); cell != nil {
|
||||||
_, _, _, _, cellWidth := decomposeString(cell.Text)
|
_, _, _, _, _, _, cellWidth := decomposeString(cell.Text, true, false)
|
||||||
if cell.MaxWidth > 0 && cell.MaxWidth < cellWidth {
|
if cell.MaxWidth > 0 && cell.MaxWidth < cellWidth {
|
||||||
cellWidth = cell.MaxWidth
|
cellWidth = cell.MaxWidth
|
||||||
}
|
}
|
||||||
|
|
53
textview.go
53
textview.go
|
@ -558,33 +558,11 @@ func (t *TextView) reindexBuffer(width int) {
|
||||||
|
|
||||||
// Go through each line in the buffer.
|
// Go through each line in the buffer.
|
||||||
for bufferIndex, str := range t.buffer {
|
for bufferIndex, str := range t.buffer {
|
||||||
// Find all color tags in this line. Then remove them.
|
colorTagIndices, colorTags, regionIndices, regions, escapeIndices, strippedStr, _ := decomposeString(str, t.dynamicColors, t.regions)
|
||||||
var (
|
|
||||||
colorTagIndices [][]int
|
|
||||||
colorTags [][]string
|
|
||||||
escapeIndices [][]int
|
|
||||||
)
|
|
||||||
strippedStr := str
|
|
||||||
if t.dynamicColors {
|
|
||||||
colorTagIndices, colorTags, escapeIndices, strippedStr, _ = decomposeString(str)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find all regions in this line. Then remove them.
|
|
||||||
var (
|
|
||||||
regionIndices [][]int
|
|
||||||
regions [][]string
|
|
||||||
)
|
|
||||||
if t.regions {
|
|
||||||
regionIndices = regionPattern.FindAllStringIndex(str, -1)
|
|
||||||
regions = regionPattern.FindAllStringSubmatch(str, -1)
|
|
||||||
strippedStr = regionPattern.ReplaceAllString(strippedStr, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
// We don't need the original string anymore for now.
|
|
||||||
str = strippedStr
|
|
||||||
|
|
||||||
// Split the line if required.
|
// Split the line if required.
|
||||||
var splitLines []string
|
var splitLines []string
|
||||||
|
str = strippedStr
|
||||||
if t.wrap && len(str) > 0 {
|
if t.wrap && len(str) > 0 {
|
||||||
for len(str) > 0 {
|
for len(str) > 0 {
|
||||||
extract := runewidth.Truncate(str, width, "")
|
extract := runewidth.Truncate(str, width, "")
|
||||||
|
@ -829,31 +807,8 @@ func (t *TextView) Draw(screen tcell.Screen) {
|
||||||
attributes := index.Attributes
|
attributes := index.Attributes
|
||||||
regionID := index.Region
|
regionID := index.Region
|
||||||
|
|
||||||
// Get color tags.
|
// Process tags.
|
||||||
var (
|
colorTagIndices, colorTags, regionIndices, regions, escapeIndices, strippedText, _ := decomposeString(text, t.dynamicColors, t.regions)
|
||||||
colorTagIndices [][]int
|
|
||||||
colorTags [][]string
|
|
||||||
escapeIndices [][]int
|
|
||||||
)
|
|
||||||
strippedText := text
|
|
||||||
if t.dynamicColors {
|
|
||||||
colorTagIndices, colorTags, escapeIndices, strippedText, _ = decomposeString(text)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get regions.
|
|
||||||
var (
|
|
||||||
regionIndices [][]int
|
|
||||||
regions [][]string
|
|
||||||
)
|
|
||||||
if t.regions {
|
|
||||||
regionIndices = regionPattern.FindAllStringIndex(text, -1)
|
|
||||||
regions = regionPattern.FindAllStringSubmatch(text, -1)
|
|
||||||
strippedText = regionPattern.ReplaceAllString(strippedText, "")
|
|
||||||
if !t.dynamicColors {
|
|
||||||
escapeIndices = escapePattern.FindAllStringIndex(text, -1)
|
|
||||||
strippedText = string(escapePattern.ReplaceAllString(strippedText, "[$1$2]"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate the position of the line.
|
// Calculate the position of the line.
|
||||||
var skip, posX int
|
var skip, posX int
|
||||||
|
|
56
util.go
56
util.go
|
@ -3,6 +3,7 @@ package tview
|
||||||
import (
|
import (
|
||||||
"math"
|
"math"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
|
@ -160,15 +161,28 @@ func overlayStyle(background tcell.Color, defaultStyle tcell.Style, fgColor, bgC
|
||||||
}
|
}
|
||||||
|
|
||||||
// decomposeString returns information about a string which may contain color
|
// decomposeString returns information about a string which may contain color
|
||||||
// tags. It returns the indices of the color tags (as returned by
|
// tags or region tags, depending on which ones are requested to be found. It
|
||||||
|
// returns the indices of the color tags (as returned by
|
||||||
// re.FindAllStringIndex()), the color tags themselves (as returned by
|
// re.FindAllStringIndex()), the color tags themselves (as returned by
|
||||||
// re.FindAllStringSubmatch()), the indices of an escaped tags, the string
|
// re.FindAllStringSubmatch()), the indices of region tags and the region tags
|
||||||
// stripped by any color tags and escaped, and the screen width of the stripped
|
// themselves, the indices of an escaped tags (only if at least color tags or
|
||||||
// string.
|
// region tags are requested), the string stripped by any tags and escaped, and
|
||||||
func decomposeString(text string) (colorIndices [][]int, colors [][]string, escapeIndices [][]int, stripped string, width int) {
|
// the screen width of the stripped string.
|
||||||
// Get positions of color and escape tags.
|
func decomposeString(text string, findColors, findRegions bool) (colorIndices [][]int, colors [][]string, regionIndices [][]int, regions [][]string, escapeIndices [][]int, stripped string, width int) {
|
||||||
colorIndices = colorPattern.FindAllStringIndex(text, -1)
|
// Shortcut for the trivial case.
|
||||||
colors = colorPattern.FindAllStringSubmatch(text, -1)
|
if !findColors && !findRegions {
|
||||||
|
return nil, nil, nil, nil, nil, text, runewidth.StringWidth(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get positions of any tags.
|
||||||
|
if findColors {
|
||||||
|
colorIndices = colorPattern.FindAllStringIndex(text, -1)
|
||||||
|
colors = colorPattern.FindAllStringSubmatch(text, -1)
|
||||||
|
}
|
||||||
|
if findRegions {
|
||||||
|
regionIndices = regionPattern.FindAllStringIndex(text, -1)
|
||||||
|
regions = regionPattern.FindAllStringSubmatch(text, -1)
|
||||||
|
}
|
||||||
escapeIndices = escapePattern.FindAllStringIndex(text, -1)
|
escapeIndices = escapePattern.FindAllStringIndex(text, -1)
|
||||||
|
|
||||||
// Because the color pattern detects empty tags, we need to filter them out.
|
// Because the color pattern detects empty tags, we need to filter them out.
|
||||||
|
@ -179,10 +193,26 @@ func decomposeString(text string) (colorIndices [][]int, colors [][]string, esca
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the color tags from the original string.
|
// Make a (sorted) list of all tags.
|
||||||
|
var allIndices [][]int
|
||||||
|
if findColors && findRegions {
|
||||||
|
allIndices = colorIndices
|
||||||
|
allIndices = make([][]int, len(colorIndices)+len(regionIndices))
|
||||||
|
copy(allIndices, colorIndices)
|
||||||
|
copy(allIndices[len(colorIndices):], regionIndices)
|
||||||
|
sort.Slice(allIndices, func(i int, j int) bool {
|
||||||
|
return allIndices[i][0] < allIndices[j][0]
|
||||||
|
})
|
||||||
|
} else if findColors {
|
||||||
|
allIndices = colorIndices
|
||||||
|
} else {
|
||||||
|
allIndices = regionIndices
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the tags from the original string.
|
||||||
var from int
|
var from int
|
||||||
buf := make([]byte, 0, len(text))
|
buf := make([]byte, 0, len(text))
|
||||||
for _, indices := range colorIndices {
|
for _, indices := range allIndices {
|
||||||
buf = append(buf, []byte(text[from:indices[0]])...)
|
buf = append(buf, []byte(text[from:indices[0]])...)
|
||||||
from = indices[1]
|
from = indices[1]
|
||||||
}
|
}
|
||||||
|
@ -218,7 +248,7 @@ func printWithStyle(screen tcell.Screen, text string, x, y, maxWidth, align int,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decompose the text.
|
// Decompose the text.
|
||||||
colorIndices, colors, escapeIndices, strippedText, strippedWidth := decomposeString(text)
|
colorIndices, colors, _, _, escapeIndices, strippedText, strippedWidth := decomposeString(text, true, false)
|
||||||
|
|
||||||
// We want to reduce all alignments to AlignLeft.
|
// We want to reduce all alignments to AlignLeft.
|
||||||
if align == AlignRight {
|
if align == AlignRight {
|
||||||
|
@ -382,7 +412,7 @@ func PrintSimple(screen tcell.Screen, text string, x, y int) {
|
||||||
// StringWidth returns the width of the given string needed to print it on
|
// StringWidth returns the width of the given string needed to print it on
|
||||||
// screen. The text may contain color tags which are not counted.
|
// screen. The text may contain color tags which are not counted.
|
||||||
func StringWidth(text string) int {
|
func StringWidth(text string) int {
|
||||||
_, _, _, _, width := decomposeString(text)
|
_, _, _, _, _, _, width := decomposeString(text, true, false)
|
||||||
return width
|
return width
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,7 +424,7 @@ func StringWidth(text string) int {
|
||||||
//
|
//
|
||||||
// Text is always split at newline characters ('\n').
|
// Text is always split at newline characters ('\n').
|
||||||
func WordWrap(text string, width int) (lines []string) {
|
func WordWrap(text string, width int) (lines []string) {
|
||||||
colorTagIndices, _, escapeIndices, strippedText, _ := decomposeString(text)
|
colorTagIndices, _, _, _, escapeIndices, strippedText, _ := decomposeString(text, true, false)
|
||||||
|
|
||||||
// Find candidate breakpoints.
|
// Find candidate breakpoints.
|
||||||
breakpoints := boundaryPattern.FindAllStringSubmatchIndex(strippedText, -1)
|
breakpoints := boundaryPattern.FindAllStringSubmatchIndex(strippedText, -1)
|
||||||
|
|
Loading…
Reference in New Issue