Skip to content

Commit 545dc34

Browse files
szedergitster
authored andcommitted
progress: break too long progress bar lines
Some of the recently added progress indicators have quite long titles, which might be even longer when translated to some languages, and when they are shown while operating on bigger repositories, then the progress bar grows longer than the default 80 column terminal width. When the progress bar exceeds the width of the terminal it gets line-wrapped, and after that the CR at the end doesn't return to the beginning of the progress bar, but to the first column of its last line. Consequently, the first line of the previously shown progress bar is not overwritten by the next, and we end up with a bunch of truncated progress bar lines scrolling past: $ LANG=es_ES.UTF-8 git commit-graph write Encontrando commits para commit graph entre los objetos empaquetados: 2% (1599 Encontrando commits para commit graph entre los objetos empaquetados: 3% (1975 Encontrando commits para commit graph entre los objetos empaquetados: 4% (2633 Encontrando commits para commit graph entre los objetos empaquetados: 5% (3292 [...] Prevent this by breaking progress bars after the title once they exceed the width of the terminal, so the counter and optional percentage and throughput, i.e. all changing parts, are on the last line. Subsequent updates will from then on only refresh the changing parts, but not the title, and it will look like this: $ LANG=es_ES.UTF-8 ~/src/git/git commit-graph write Encontrando commits para commit graph entre los objetos empaquetados: 100% (6584502/6584502), listo. Calculando números de generación de commit graph: 100% (824705/824705), listo. Escribiendo commit graph en 4 pasos: 100% (3298820/3298820), listo. Note that the number of columns in the terminal is cached by term_columns(), so this might not kick in when it should when a terminal window is resized while the operation is running. Furthermore, this change won't help if the terminal is so narrow that the counters don't fit on one line, but I would put this in the "If it hurts, don't do it" box. Signed-off-by: SZEDER Gábor <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 9f1fd84 commit 545dc34

File tree

1 file changed

+24
-3
lines changed

1 file changed

+24
-3
lines changed

progress.c

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@
88
* published by the Free Software Foundation.
99
*/
1010

11-
#include "git-compat-util.h"
11+
#include "cache.h"
1212
#include "gettext.h"
1313
#include "progress.h"
1414
#include "strbuf.h"
1515
#include "trace.h"
16+
#include "utf8.h"
1617

1718
#define TP_IDX_MAX 8
1819

@@ -37,6 +38,8 @@ struct progress {
3738
struct throughput *throughput;
3839
uint64_t start_ns;
3940
struct strbuf counters_sb;
41+
int title_len;
42+
int split;
4043
};
4144

4245
static volatile sig_atomic_t progress_update;
@@ -115,8 +118,24 @@ static void display(struct progress *progress, uint64_t n, const char *done)
115118
size_t clear_len = counters_sb->len < last_count_len ?
116119
last_count_len - counters_sb->len + 1 :
117120
0;
118-
fprintf(stderr, "%s: %s%*s", progress->title,
119-
counters_sb->buf, (int) clear_len, eol);
121+
size_t progress_line_len = progress->title_len +
122+
counters_sb->len + 2;
123+
int cols = term_columns();
124+
125+
if (progress->split) {
126+
fprintf(stderr, " %s%*s", counters_sb->buf,
127+
(int) clear_len, eol);
128+
} else if (!done && cols < progress_line_len) {
129+
clear_len = progress->title_len + 1 < cols ?
130+
cols - progress->title_len : 0;
131+
fprintf(stderr, "%s:%*s\n %s%s",
132+
progress->title, (int) clear_len, "",
133+
counters_sb->buf, eol);
134+
progress->split = 1;
135+
} else {
136+
fprintf(stderr, "%s: %s%*s", progress->title,
137+
counters_sb->buf, (int) clear_len, eol);
138+
}
120139
fflush(stderr);
121140
}
122141
progress_update = 0;
@@ -220,6 +239,8 @@ static struct progress *start_progress_delay(const char *title, uint64_t total,
220239
progress->throughput = NULL;
221240
progress->start_ns = getnanotime();
222241
strbuf_init(&progress->counters_sb, 0);
242+
progress->title_len = utf8_strwidth(title);
243+
progress->split = 0;
223244
set_progress_signal();
224245
return progress;
225246
}

0 commit comments

Comments
 (0)