Skip to content

Commit

Permalink
Correctly account for pre-existing full-width runes in the content.
Browse files Browse the repository at this point in the history
  • Loading branch information
mum4k committed Apr 3, 2021
1 parent 18e27ec commit 6a2d2bb
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 8 deletions.
18 changes: 15 additions & 3 deletions widgets/text/text.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,16 @@ func (t *Text) reset() {
t.contentChanged = true
}

// contentCells calculates the number of cells the content takes to display on
// terminal.
func (t *Text) contentCells() int {
cells := 0
for _, c := range t.content {
cells += runeWidth(c.Rune)
}
return cells
}

// Write writes text for the widget to display. Multiple calls append
// additional text. The text contain cannot control characters
// (unicode.IsControl) or space character (unicode.IsSpace) other than:
Expand All @@ -112,10 +122,12 @@ func (t *Text) Write(text string, wOpts ...WriteOption) error {
}

truncated := truncateToCells(text, t.opts.maxTextCells)
textCells := runewidth.StringWidth(truncated)
textCells := stringWidth(truncated)
contentCells := t.contentCells()
// If MaxTextCells has been set, limit the content if needed.
if t.opts.maxTextCells > 0 && len(t.content)+textCells > t.opts.maxTextCells {
t.content = t.content[len(t.content)-textCells:]
if t.opts.maxTextCells > 0 && contentCells+textCells > t.opts.maxTextCells {
diff := contentCells + textCells - t.opts.maxTextCells
t.content = t.content[diff:]
}

for _, r := range truncated {
Expand Down
77 changes: 72 additions & 5 deletions widgets/text/text_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -810,7 +810,7 @@ func TestTextDraws(t *testing.T) {
},
},
{
desc: "tests maxContent length being applied - multiline",
desc: "tests maxTextCells length being applied - multiline",
canvas: image.Rect(0, 0, 10, 3),
opts: []Option{
MaxTextCells(10),
Expand All @@ -830,7 +830,74 @@ func TestTextDraws(t *testing.T) {
},
},
{
desc: "tests maxContent exact length of 5",
desc: "tests maxTextCells - multiple writes - first one fits",
canvas: image.Rect(0, 0, 10, 3),
opts: []Option{
MaxTextCells(10),
RollContent(),
},
writes: func(widget *Text) error {
if err := widget.Write("line0\nline"); err != nil {
return err
}
return widget.Write("1\nline2\nline3\nline4")
return nil
},
want: func(size image.Point) *faketerm.Terminal {
ft := faketerm.MustNew(size)
c := testcanvas.MustNew(ft.Area())
// \n still counts as a chacter in the string length
testdraw.MustText(c, "ine3", image.Point{0, 0})
testdraw.MustText(c, "line4", image.Point{0, 1})
testcanvas.MustApply(c, ft)
return ft
},
},
{
desc: "tests maxTextCells - multiple writes - first one does not fit",
canvas: image.Rect(0, 0, 10, 3),
opts: []Option{
MaxTextCells(10),
RollContent(),
},
writes: func(widget *Text) error {
if err := widget.Write("line0\nline123"); err != nil {
return err
}
return widget.Write("1\nline2\nline3\nline4")
},
want: func(size image.Point) *faketerm.Terminal {
ft := faketerm.MustNew(size)
c := testcanvas.MustNew(ft.Area())
testdraw.MustText(c, "ine3", image.Point{0, 0})
testdraw.MustText(c, "line4", image.Point{0, 1})
testcanvas.MustApply(c, ft)
return ft
},
},
{
desc: "tests maxTextCells - accounts for pre-existing full-width runes on the content",
canvas: image.Rect(0, 0, 10, 3),
opts: []Option{
MaxTextCells(3),
RollContent(),
},
writes: func(widget *Text) error {
if err := widget.Write("界"); err != nil {
return err
}
return widget.Write("ab")
},
want: func(size image.Point) *faketerm.Terminal {
ft := faketerm.MustNew(size)
c := testcanvas.MustNew(ft.Area())
testdraw.MustText(c, "ab", image.Point{0, 0})
testcanvas.MustApply(c, ft)
return ft
},
},
{
desc: "tests maxTextCells exact length of 5",
canvas: image.Rect(0, 0, 10, 1),
opts: []Option{
RollContent(),
Expand All @@ -853,7 +920,7 @@ func TestTextDraws(t *testing.T) {
},
},
{
desc: "tests maxContent partial bufffer replacement",
desc: "tests maxTextCells partial bufffer replacement",
canvas: image.Rect(0, 0, 10, 1),
opts: []Option{
RollContent(),
Expand All @@ -875,7 +942,7 @@ func TestTextDraws(t *testing.T) {
},
},
{
desc: "tests maxContent length not being limited",
desc: "tests maxTextCells length not being limited",
canvas: image.Rect(0, 0, 72, 1),
opts: []Option{
RollContent(),
Expand All @@ -896,7 +963,7 @@ func TestTextDraws(t *testing.T) {
},
},
{
desc: "tests maxContent length being applied - single line",
desc: "tests maxTextCells length being applied - single line",
canvas: image.Rect(0, 0, 10, 3),
opts: []Option{
MaxTextCells(5),
Expand Down

0 comments on commit 6a2d2bb

Please sign in to comment.