diff --git a/progress/progress.go b/progress/progress.go index 580d8123a..104af2c9f 100644 --- a/progress/progress.go +++ b/progress/progress.go @@ -1,6 +1,7 @@ package progress import ( + "bytes" "fmt" "io" "sync" @@ -12,8 +13,9 @@ type State interface { } type Progress struct { - mu sync.Mutex - w io.Writer + mu sync.Mutex + w io.Writer + buf bytes.Buffer pos int @@ -81,21 +83,26 @@ func (p *Progress) render() { p.mu.Lock() defer p.mu.Unlock() - fmt.Fprint(p.w, "\033[?25l") - defer fmt.Fprint(p.w, "\033[?25h") + // buffer the terminal update to minimize cursor flickering + // https://gitlab.gnome.org/GNOME/vte/-/issues/2837#note_2269501 + p.buf.Reset() + defer p.buf.WriteTo(p.w) + + fmt.Fprint(&p.buf, "\033[?25l") + defer fmt.Fprint(&p.buf, "\033[?25h") // move the cursor back to the beginning for range p.pos - 1 { - fmt.Fprint(p.w, "\033[A") + fmt.Fprint(&p.buf, "\033[A") } - fmt.Fprint(p.w, "\033[1G") + fmt.Fprint(&p.buf, "\033[1G") // render progress lines for i, state := range p.states { - fmt.Fprint(p.w, state.String()) - fmt.Fprintf(p.w, "\033[K") + fmt.Fprint(&p.buf, state.String()) + fmt.Fprintf(&p.buf, "\033[K") if i < len(p.states)-1 { - fmt.Fprint(p.w, "\n") + fmt.Fprint(&p.buf, "\n") } }