Skip to content

Commit

Permalink
Replaced runewidth.StringWidth() with my own implementation. Fixes ri…
Browse files Browse the repository at this point in the history
  • Loading branch information
Oliver committed Mar 19, 2019
1 parent 2cc8258 commit 8d5eba0
Show file tree
Hide file tree
Showing 9 changed files with 38 additions and 23 deletions.
2 changes: 1 addition & 1 deletion button.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 33,7 @@ type Button struct {
// NewButton returns a new input field.
func NewButton(label string) *Button {
box := NewBox().SetBackgroundColor(Styles.ContrastBackgroundColor)
box.SetRect(0, 0, StringWidth(label) 4, 1)
box.SetRect(0, 0, TaggedStringWidth(label) 4, 1)
return &Button{
Box: box,
label: label,
Expand Down
7 changes: 3 additions & 4 deletions dropdown.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 4,6 @@ import (
"strings"

"github.com/gdamore/tcell"
runewidth "github.com/mattn/go-runewidth"
)

// dropDownOption is one option that can be selected in a drop-down primitive.
Expand Down Expand Up @@ -182,7 181,7 @@ func (d *DropDown) GetFieldWidth() int {
}
fieldWidth := 0
for _, option := range d.options {
width := StringWidth(option.Text)
width := TaggedStringWidth(option.Text)
if width > fieldWidth {
fieldWidth = width
}
Expand Down Expand Up @@ -268,7 267,7 @@ func (d *DropDown) Draw(screen tcell.Screen) {
// What's the longest option text?
maxWidth := 0
for _, option := range d.options {
strWidth := StringWidth(option.Text)
strWidth := TaggedStringWidth(option.Text)
if strWidth > maxWidth {
maxWidth = strWidth
}
Expand All @@ -294,7 293,7 @@ func (d *DropDown) Draw(screen tcell.Screen) {
if d.open && len(d.prefix) > 0 {
// Show the prefix.
Print(screen, d.prefix, x, y, fieldWidth, AlignLeft, d.prefixTextColor)
prefixWidth := runewidth.StringWidth(d.prefix)
prefixWidth := stringWidth(d.prefix)
listItemText := d.options[d.list.GetCurrentItem()].Text
if prefixWidth < fieldWidth && len(d.prefix) < len(listItemText) {
Print(screen, listItemText[len(d.prefix):], x prefixWidth, y, fieldWidth-prefixWidth, AlignLeft, d.fieldTextColor)
Expand Down
6 changes: 3 additions & 3 deletions form.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 335,7 @@ func (f *Form) Draw(screen tcell.Screen) {
// Find the longest label.
var maxLabelWidth int
for _, item := range f.items {
labelWidth := StringWidth(item.GetLabel())
labelWidth := TaggedStringWidth(item.GetLabel())
if labelWidth > maxLabelWidth {
maxLabelWidth = labelWidth
}
Expand All @@ -347,7 347,7 @@ func (f *Form) Draw(screen tcell.Screen) {
var focusedPosition struct{ x, y, width, height int }
for index, item := range f.items {
// Calculate the space needed.
labelWidth := StringWidth(item.GetLabel())
labelWidth := TaggedStringWidth(item.GetLabel())
var itemWidth int
if f.horizontal {
fieldWidth := item.GetFieldWidth()
Expand Down Expand Up @@ -401,7 401,7 @@ func (f *Form) Draw(screen tcell.Screen) {
buttonWidths := make([]int, len(f.buttons))
buttonsWidth := 0
for index, button := range f.buttons {
w := StringWidth(button.GetLabel()) 4
w := TaggedStringWidth(button.GetLabel()) 4
buttonWidths[index] = w
buttonsWidth = w 1
}
Expand Down
6 changes: 2 additions & 4 deletions inputfield.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 7,6 @@ import (
"unicode/utf8"

"github.com/gdamore/tcell"
runewidth "github.com/mattn/go-runewidth"
)

// InputField is a one-line box (three lines if there is a title) where the
Expand Down Expand Up @@ -276,8 275,7 @@ func (i *InputField) Draw(screen tcell.Screen) {
if i.maskCharacter > 0 {
text = strings.Repeat(string(i.maskCharacter), utf8.RuneCountInString(i.text))
}
stringWidth := runewidth.StringWidth(text)
if fieldWidth >= stringWidth {
if fieldWidth >= stringWidth(text) {
// We have enough space for the full text.
Print(screen, Escape(text), x, y, fieldWidth, AlignLeft, i.fieldTextColor)
i.offset = 0
Expand All @@ -299,7 297,7 @@ func (i *InputField) Draw(screen tcell.Screen) {
var shiftLeft int
if i.offset > i.cursorPos {
i.offset = i.cursorPos
} else if subWidth := runewidth.StringWidth(text[i.offset:i.cursorPos]); subWidth > fieldWidth-1 {
} else if subWidth := stringWidth(text[i.offset:i.cursorPos]); subWidth > fieldWidth-1 {
shiftLeft = subWidth - fieldWidth 1
}
currentOffset := i.offset
Expand Down
2 changes: 1 addition & 1 deletion list.go
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 426,7 @@ func (l *List) Draw(screen tcell.Screen) {
if index == l.currentItem && (!l.selectedFocusOnly || l.HasFocus()) {
textWidth := width
if !l.highlightFullLine {
if w := StringWidth(item.MainText); w < textWidth {
if w := TaggedStringWidth(item.MainText); w < textWidth {
textWidth = w
}
}
Expand Down
2 changes: 1 addition & 1 deletion modal.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 116,7 @@ func (m *Modal) Draw(screen tcell.Screen) {
// Calculate the width of this modal.
buttonsWidth := 0
for _, button := range m.form.buttons {
buttonsWidth = StringWidth(button.label) 4 2
buttonsWidth = TaggedStringWidth(button.label) 4 2
}
buttonsWidth -= 2
screenWidth, screenHeight := screen.Size()
Expand Down
2 changes: 1 addition & 1 deletion table.go
Original file line number Diff line number Diff line change
Expand Up @@ -792,7 792,7 @@ ColumnLoop:
}
cell.x, cell.y, cell.width = x columnX 1, y rowY, finalWidth
_, printed := printWithStyle(screen, cell.Text, x columnX 1, y rowY, finalWidth, cell.Align, tcell.StyleDefault.Foreground(cell.Color)|tcell.Style(cell.Attributes))
if StringWidth(cell.Text)-printed > 0 && printed > 0 {
if TaggedStringWidth(cell.Text)-printed > 0 && printed > 0 {
_, _, style, _ := screen.GetContent(x columnX 1 finalWidth-1, y rowY)
printWithStyle(screen, string(SemigraphicsHorizontalEllipsis), x columnX 1 finalWidth-1, y rowY, 1, AlignLeft, style)
}
Expand Down
6 changes: 3 additions & 3 deletions textview.go
Original file line number Diff line number Diff line change
Expand Up @@ -691,7 691,7 @@ func (t *TextView) reindexBuffer(width int) {
line := len(t.index)
if t.fromHighlight < 0 {
t.fromHighlight, t.toHighlight = line, line
t.posHighlight = runewidth.StringWidth(splitLine[:strippedTagStart])
t.posHighlight = stringWidth(splitLine[:strippedTagStart])
} else if line > t.toHighlight {
t.toHighlight = line
}
Expand All @@ -709,7 709,7 @@ func (t *TextView) reindexBuffer(width int) {

// Append this line.
line.NextPos = originalPos
line.Width = runewidth.StringWidth(splitLine)
line.Width = stringWidth(splitLine)
t.index = append(t.index, line)
}

Expand All @@ -721,7 721,7 @@ func (t *TextView) reindexBuffer(width int) {
if spaces != nil && spaces[len(spaces)-1][1] == len(str) {
oldNextPos := line.NextPos
line.NextPos -= spaces[len(spaces)-1][1] - spaces[len(spaces)-1][0]
line.Width -= runewidth.StringWidth(t.buffer[line.Line][line.NextPos:oldNextPos])
line.Width -= stringWidth(t.buffer[line.Line][line.NextPos:oldNextPos])
}
}
}
Expand Down
28 changes: 23 additions & 5 deletions util.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 171,7 @@ func overlayStyle(background tcell.Color, defaultStyle tcell.Style, fgColor, bgC
func decomposeString(text string, findColors, findRegions bool) (colorIndices [][]int, colors [][]string, regionIndices [][]int, regions [][]string, escapeIndices [][]int, stripped string, width int) {
// Shortcut for the trivial case.
if !findColors && !findRegions {
return nil, nil, nil, nil, nil, text, runewidth.StringWidth(text)
return nil, nil, nil, nil, nil, text, stringWidth(text)
}

// Get positions of any tags.
Expand Down Expand Up @@ -222,7 222,7 @@ func decomposeString(text string, findColors, findRegions bool) (colorIndices []
stripped = string(escapePattern.ReplaceAll(buf, []byte("[$1$2]")))

// Get the width of the stripped string.
width = runewidth.StringWidth(stripped)
width = stringWidth(stripped)

return
}
Expand Down Expand Up @@ -409,13 409,31 @@ func PrintSimple(screen tcell.Screen, text string, x, y int) {
Print(screen, text, x, y, math.MaxInt32, AlignLeft, Styles.PrimaryTextColor)
}

// StringWidth returns the width of the given string needed to print it on
// TaggedStringWidth returns the width of the given string needed to print it on
// screen. The text may contain color tags which are not counted.
func StringWidth(text string) int {
func TaggedStringWidth(text string) int {
_, _, _, _, _, _, width := decomposeString(text, true, false)
return width
}

// stringWidth returns the number of horizontal cells needed to print the given
// text. It splits the text into its grapheme clusters, calculates each
// cluster's width, and adds them up to a total.
func stringWidth(text string) (width int) {
g := uniseg.NewGraphemes(text)
for g.Next() {
var chWidth int
for _, r := range g.Runes() {
chWidth = runewidth.RuneWidth(r)
if chWidth > 0 {
break // Our best guess at this point is to use the width of the first non-zero-width rune.
}
}
width = chWidth
}
return
}

// WordWrap splits a text such that each resulting line does not exceed the
// given screen width. Possible split points are after any punctuation or
// whitespace. Whitespace after split points will be dropped.
Expand Down Expand Up @@ -534,7 552,7 @@ func iterateString(text string, callback func(main rune, comb []rune, textPos, t
for gr.Next() {
r := gr.Runes()
from, to := gr.Positions()
width := runewidth.StringWidth(gr.Str())
width := stringWidth(gr.Str())
var comb []rune
if len(r) > 1 {
comb = r[1:]
Expand Down

0 comments on commit 8d5eba0

Please sign in to comment.