This patch series fixes two progress display issues by breaking progress bars longer than the width of the terminal and by properly cleaning up the previously shown progress bar. Hopefully for good this time... This "properly cleaning up" part, i.e. mainly patch 3, was buggy in previous versions, because: - It used the wrong format flag and the '\r' was padded on the right, but should have been padded to the left. - The padding was one space shorter than necessary, because I didn't account for the '\r' included in the field width as well. SZEDER Gábor (4): progress: make display_progress() return void progress: assemble percentage and counters in a strbuf before printing progress: clear previous progress update dynamically progress: break too long progress bar lines progress.c | 74 ++++++++++++++++++++++++++++++++++++++---------------- progress.h | 2 +- 2 files changed, 54 insertions(+), 22 deletions(-) Interdiff: diff --git a/progress.c b/progress.c index 97e18671e5..2d8022a622 100644 --- a/progress.c +++ b/progress.c @@ -116,23 +116,24 @@ static void display(struct progress *progress, uint64_t n, const char *done) if (is_foreground_fd(fileno(stderr)) || done) { const char *eol = done ? done : "\r"; size_t clear_len = counters_sb->len < last_count_len ? - last_count_len - counters_sb->len : 0; + last_count_len - counters_sb->len + 1 : + 0; size_t progress_line_len = progress->title_len + counters_sb->len + 2; int cols = term_columns(); if (progress->split) { - fprintf(stderr, " %s%-*s", counters_sb->buf, + fprintf(stderr, " %s%*s", counters_sb->buf, (int) clear_len, eol); } else if (!done && cols < progress_line_len) { clear_len = progress->title_len + 1 < cols ? - cols - progress->title_len - 1 : 0; + cols - progress->title_len : 0; fprintf(stderr, "%s:%*s\n %s%s", progress->title, (int) clear_len, "", counters_sb->buf, eol); progress->split = 1; } else { - fprintf(stderr, "%s: %s%-*s", progress->title, + fprintf(stderr, "%s: %s%*s", progress->title, counters_sb->buf, (int) clear_len, eol); } fflush(stderr); Range-diff: 1: cb68e5b0ec = 1: cb68e5b0ec progress: make display_progress() return void 2: 017d095142 = 2: 017d095142 progress: assemble percentage and counters in a strbuf before printing 3: c5a4def5ac ! 3: ec9c96d102 progress: clear previous progress update dynamically @@ -49,8 +49,9 @@ - counters_sb->buf, eol); + const char *eol = done ? done : "\r"; + size_t clear_len = counters_sb->len < last_count_len ? -+ last_count_len - counters_sb->len : 0; -+ fprintf(stderr, "%s: %s%-*s", progress->title, ++ last_count_len - counters_sb->len + 1 : ++ 0; ++ fprintf(stderr, "%s: %s%*s", progress->title, + counters_sb->buf, (int) clear_len, eol); fflush(stderr); } 4: 2f44dff84e ! 4: 8fc8e3cf94 progress: break too long progress bar lines @@ -69,27 +69,27 @@ static volatile sig_atomic_t progress_update; @@ - const char *eol = done ? done : "\r"; size_t clear_len = counters_sb->len < last_count_len ? - last_count_len - counters_sb->len : 0; -- fprintf(stderr, "%s: %s%-*s", progress->title, + last_count_len - counters_sb->len + 1 : + 0; +- fprintf(stderr, "%s: %s%*s", progress->title, - counters_sb->buf, (int) clear_len, eol); + size_t progress_line_len = progress->title_len + + counters_sb->len + 2; + int cols = term_columns(); + + if (progress->split) { -+ fprintf(stderr, " %s%-*s", counters_sb->buf, ++ fprintf(stderr, " %s%*s", counters_sb->buf, + (int) clear_len, eol); + } else if (!done && cols < progress_line_len) { + clear_len = progress->title_len + 1 < cols ? -+ cols - progress->title_len - 1 : 0; ++ cols - progress->title_len : 0; + fprintf(stderr, "%s:%*s\n %s%s", + progress->title, (int) clear_len, "", + counters_sb->buf, eol); + progress->split = 1; + } else { -+ fprintf(stderr, "%s: %s%-*s", progress->title, ++ fprintf(stderr, "%s: %s%*s", progress->title, + counters_sb->buf, (int) clear_len, eol); + } fflush(stderr); -- 2.21.0.746.gd74f1657d3