From ae6d6bd9a6bfddf64b27ee58210122ab5d9bb671 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Fri, 28 Nov 2025 23:20:39 +0100 Subject: [PATCH] ui: only redraw status bar if it has not changed --- changelog/unreleased/issue-5383 | 1 + internal/ui/termstatus/status.go | 22 +++++++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/changelog/unreleased/issue-5383 b/changelog/unreleased/issue-5383 index 9e79e6cf0..54778a181 100644 --- a/changelog/unreleased/issue-5383 +++ b/changelog/unreleased/issue-5383 @@ -7,3 +7,4 @@ anything in the terminal with certain terminal emulators. https://github.com/restic/restic/issues/5383 https://github.com/restic/restic/pull/5551 +https://github.com/restic/restic/pull/5626 diff --git a/internal/ui/termstatus/status.go b/internal/ui/termstatus/status.go index 3265c7a04..94ea6adaa 100644 --- a/internal/ui/termstatus/status.go +++ b/internal/ui/termstatus/status.go @@ -5,6 +5,7 @@ import ( "context" "fmt" "io" + "slices" "strings" "sync" @@ -204,6 +205,7 @@ func (t *Terminal) Run(ctx context.Context) { // run listens on the channels and updates the terminal screen. func (t *Terminal) run(ctx context.Context) { var status []string + var lastWrittenStatus []string for { select { case <-ctx.Done(): @@ -240,6 +242,7 @@ func (t *Terminal) run(ctx context.Context) { } t.writeStatus(status) + lastWrittenStatus = append([]string{}, status...) case stat := <-t.status: status = append(status[:0], stat.lines...) @@ -248,7 +251,11 @@ func (t *Terminal) run(ctx context.Context) { continue } - t.writeStatus(status) + if !slices.Equal(status, lastWrittenStatus) { + t.writeStatus(status) + // Copy the status slice to avoid aliasing + lastWrittenStatus = append([]string{}, status...) + } } } } @@ -287,6 +294,7 @@ func (t *Terminal) writeStatus(status []string) { // runWithoutStatus listens on the channels and just prints out the messages, // without status lines. func (t *Terminal) runWithoutStatus(ctx context.Context) { + var lastStatus []string for { select { case <-ctx.Done(): @@ -309,11 +317,15 @@ func (t *Terminal) runWithoutStatus(ctx context.Context) { } case stat := <-t.status: - for _, line := range stat.lines { - // Ensure that each message ends with exactly one newline. - if _, err := fmt.Fprintln(t.wr, strings.TrimRight(line, "\n")); err != nil { - _, _ = fmt.Fprintf(t.errWriter, "write failed: %v\n", err) + if !slices.Equal(stat.lines, lastStatus) { + for _, line := range stat.lines { + // Ensure that each message ends with exactly one newline. + if _, err := fmt.Fprintln(t.wr, strings.TrimRight(line, "\n")); err != nil { + _, _ = fmt.Fprintf(t.errWriter, "write failed: %v\n", err) + } } + // Copy the status slice to avoid aliasing + lastStatus = append([]string{}, stat.lines...) } } }