Skip to content

Commit 3828d9c

Browse files
lzapachilleas-k
authored andcommitted
progress: allow printing after progress is done
When something needs to be printed after the progress bar is done, it was not possible to do so without messing up the terminal. This patch adds a mutex around the buffer used to store output while the progress bar is active. This allows to safely print after stopping the progress bar.
1 parent d519a76 commit 3828d9c

File tree

1 file changed

+35
-1
lines changed

1 file changed

+35
-1
lines changed

pkg/progress/progress.go

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package progress
22

33
import (
4+
"bytes"
45
"errors"
56
"fmt"
67
"io"
78
"log"
89
"os"
910
"strings"
11+
"sync"
1012
"time"
1113

1214
"github.com/cheggaaa/pb/v3"
@@ -70,6 +72,11 @@ type ProgressBar interface {
7072
// Stop will stop rendering the progress information, the
7173
// screen is not cleared, the last few lines will be visible
7274
Stop()
75+
76+
// Write implements io.Writer that is used to capture output
77+
// that is written after the progress bar is stopped via
78+
// Stop().
79+
Write(p []byte) (n int, err error)
7380
}
7481

7582
// New creates a new progressbar based on the requested type
@@ -103,7 +110,9 @@ type terminalProgressBar struct {
103110

104111
shutdownCh chan bool
105112

106-
out io.Writer
113+
out io.Writer
114+
buf bytes.Buffer
115+
bufMu sync.Mutex
107116
}
108117

109118
// NewTerminalProgressBar creates a new default pb3 based progressbar suitable for
@@ -219,6 +228,13 @@ func (b *terminalProgressBar) Err() error {
219228
return errors.Join(errs...)
220229
}
221230

231+
func (b *terminalProgressBar) Write(p []byte) (n int, err error) {
232+
b.bufMu.Lock()
233+
defer b.bufMu.Unlock()
234+
235+
return b.buf.Write(p)
236+
}
237+
222238
func (b *terminalProgressBar) Stop() {
223239
if b.shutdownCh == nil {
224240
return
@@ -242,6 +258,13 @@ func (b *terminalProgressBar) Stop() {
242258
if err := b.Err(); err != nil {
243259
fmt.Fprintf(b.out, "error from pb.ProgressBar: %v", err)
244260
}
261+
// write any buffered output
262+
if b.buf.Len() > 0 {
263+
b.bufMu.Lock()
264+
defer b.bufMu.Unlock()
265+
fmt.Fprintf(b.out, "%s%s", ERASE_LINE, b.buf.String())
266+
b.buf.Reset()
267+
}
245268
}
246269

247270
type verboseProgressBar struct {
@@ -268,6 +291,10 @@ func (b *verboseProgressBar) SetMessagef(msg string, args ...interface{}) {
268291
func (b *verboseProgressBar) Start() {
269292
}
270293

294+
func (b *verboseProgressBar) Write(p []byte) (n int, err error) {
295+
return b.w.Write(p)
296+
}
297+
271298
func (b *verboseProgressBar) Stop() {
272299
}
273300

@@ -304,6 +331,13 @@ func (b *debugProgressBar) Start() {
304331
fmt.Fprintf(b.w, "Start progressbar\n")
305332
}
306333

334+
func (b *debugProgressBar) Write(p []byte) (n int, err error) {
335+
fmt.Fprintf(b.w, "write: ")
336+
n, err = b.w.Write(p)
337+
fmt.Fprintf(b.w, "\n")
338+
return
339+
}
340+
307341
func (b *debugProgressBar) Stop() {
308342
fmt.Fprintf(b.w, "Stop progressbar\n")
309343
}

0 commit comments

Comments
 (0)