Skip to content
This repository was archived by the owner on Apr 19, 2024. It is now read-only.

Fix re-rendering when prompt is exactly the width of the terminal #321

Merged
merged 3 commits into from
Dec 17, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
github.com/kr/pty v1.1.4 // indirect
github.com/kr/pty v1.1.4
github.com/mattn/go-colorable v0.1.2 // indirect
github.com/mattn/go-isatty v0.0.8
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b
Expand Down
11 changes: 9 additions & 2 deletions renderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,15 @@ func (r *Renderer) countLines(buf bytes.Buffer) int {
delim = len(bufBytes) // no new line found, read rest of text
}

// account for word wrapping
count += int(utf8.RuneCount(bufBytes[curr:delim]) / w)
if lineWidth := utf8.RuneCount(bufBytes[curr:delim]); lineWidth > w {
// account for word wrapping
count += lineWidth / w
if (lineWidth % w) == 0 {
// content whose width is exactly a multiplier of available width should not
// count as having wrapped on the last line
count -= 1
}
}
curr = delim + 1
}

Expand Down
91 changes: 91 additions & 0 deletions renderer_posix_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// +build !windows

package survey

import (
"bytes"
"strings"
"testing"

"github.com/AlecAivazis/survey/v2/terminal"
pseudotty "github.com/kr/pty"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestRenderer_countLines(t *testing.T) {
t.Parallel()

termWidth := 72
pty, tty, err := pseudotty.Open()
require.Nil(t, err)
defer pty.Close()
defer tty.Close()

err = pseudotty.Setsize(tty, &pseudotty.Winsize{
Rows: 30,
Cols: uint16(termWidth),
})
require.Nil(t, err)

r := Renderer{
stdio: terminal.Stdio{
In: tty,
Out: tty,
Err: tty,
},
}

tests := []struct {
name string
buf *bytes.Buffer
wants int
}{
{
name: "empty",
buf: new(bytes.Buffer),
wants: 0,
},
{
name: "no newline",
buf: bytes.NewBufferString("hello"),
wants: 0,
},
{
name: "short line",
buf: bytes.NewBufferString("hello\n"),
wants: 1,
},
{
name: "three short lines",
buf: bytes.NewBufferString("hello\nbeautiful\nworld\n"),
wants: 3,
},
{
name: "full line",
buf: bytes.NewBufferString(strings.Repeat("A", termWidth) + "\n"),
wants: 1,
},
{
name: "overflow",
buf: bytes.NewBufferString(strings.Repeat("A", termWidth+1) + "\n"),
wants: 2,
},
{
name: "overflow fills 2nd line",
buf: bytes.NewBufferString(strings.Repeat("A", termWidth*2) + "\n"),
wants: 2,
},
{
name: "overflow spills to 3rd line",
buf: bytes.NewBufferString(strings.Repeat("A", termWidth*2+1) + "\n"),
wants: 3,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
n := r.countLines(*tt.buf)
assert.Equal(t, tt.wants, n)
})
}
}