Skip to content

Commit 085652d

Browse files
authored
chore(progress): fix showing cursor after rendering (#1901)
Although we have a `defer cursor.Show()` statement, it wouldn't actually get written to `out` because we never called `Flush()`. This change ensures that all buffered writes get written to `out` at the end of the invocation. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
1 parent f010de9 commit 085652d

File tree

2 files changed

+23
-4
lines changed

2 files changed

+23
-4
lines changed

internal/pkg/term/progress/render.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ func NestedRenderOptions(opts RenderOptions) RenderOptions {
4040
// Render stops when there the ctx is canceled or r is done listening to new events.
4141
// While Render is executing, the terminal cursor is hidden and updates are written in-place.
4242
func Render(ctx context.Context, out FileWriteFlusher, r DynamicRenderer) error {
43+
defer out.Flush() // Make sure every buffered text in out is written before exiting.
44+
4345
cursor := cursor.NewWithWriter(out)
4446
cursor.Hide()
4547
defer cursor.Show()

internal/pkg/term/progress/render_test.go

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package progress
55

66
import (
7+
"bytes"
78
"context"
89
"io"
910
"strings"
@@ -33,17 +34,33 @@ func (m *mockDynamicRenderer) Done() <-chan struct{} {
3334
}
3435

3536
type mockFileWriteFlusher struct {
36-
io.Writer
37+
buf bytes.Buffer
38+
wrapper io.Writer
39+
}
40+
41+
func (m *mockFileWriteFlusher) Write(p []byte) (n int, err error) {
42+
return m.buf.Write(p)
3743
}
3844

3945
func (m *mockFileWriteFlusher) Fd() uintptr {
4046
return 0
4147
}
4248

4349
func (m *mockFileWriteFlusher) Flush() error {
50+
if _, err := m.buf.WriteTo(m.wrapper); err != nil {
51+
return err
52+
}
4453
return nil
4554
}
4655

56+
type mockFileWriter struct {
57+
io.Writer
58+
}
59+
60+
func (m *mockFileWriter) Fd() uintptr {
61+
return 0
62+
}
63+
4764
func TestRender(t *testing.T) {
4865
t.Run("stops the renderer when context is canceled", func(t *testing.T) {
4966
t.Parallel()
@@ -56,7 +73,7 @@ func TestRender(t *testing.T) {
5673
done: make(chan struct{}),
5774
}
5875
out := &mockFileWriteFlusher{
59-
Writer: actual,
76+
wrapper: actual,
6077
}
6178

6279
// WHEN
@@ -76,7 +93,7 @@ func TestRender(t *testing.T) {
7693
done: done,
7794
}
7895
out := &mockFileWriteFlusher{
79-
Writer: actual,
96+
wrapper: actual,
8097
}
8198
go func() {
8299
<-time.After(350 * time.Millisecond)
@@ -94,7 +111,7 @@ func TestRender(t *testing.T) {
94111
// 2. Write "hi\n", erase the line, and move the cursor up (Repeated x3 times)
95112
// 3. The <-ctx.Done() is called so we should write one last time "hi\n" and the cursor should be shown.
96113
wanted := new(strings.Builder)
97-
wantedFW := &mockFileWriteFlusher{
114+
wantedFW := &mockFileWriter{
98115
Writer: wanted,
99116
}
100117
c := cursor.NewWithWriter(wantedFW)

0 commit comments

Comments
 (0)