Skip to content

Commit 1b058bc

Browse files
keszybzgitster
authored andcommitted
diff --stat: use a maximum of 5/8 for the filename part
The way that available columns are divided between the filename part and the graph part is modified to use as many columns as necessary for the filenames and the rest for the graph. If there isn't enough columns to print both the filename and the graph, at least 5/8 of available space is devoted to filenames. On a standard 80 column terminal, or if not connected to a terminal and using the default of 80 columns, this gives the same partition as before. The effect of this change is visible in the patch to the test vector in t4052; with a small change with long filename, it stops truncating the name part too short, and also allocates a bit more columns to the graph for larger changes. Signed-off-by: Zbigniew Jędrzejewski-Szmek <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 7a7159a commit 1b058bc

File tree

3 files changed

+76
-44
lines changed

3 files changed

+76
-44
lines changed

Documentation/diff-options.txt

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,15 @@ endif::git-format-patch[]
5353
Generate a diff using the "patience diff" algorithm.
5454

5555
--stat[=<width>[,<name-width>[,<count>]]]::
56-
Generate a diffstat. You can override the default
57-
output width for 80-column terminal by `--stat=<width>`.
58-
The width of the filename part can be controlled by
59-
giving another width to it separated by a comma.
56+
Generate a diffstat. By default, as much space as necessary
57+
will be used for the filename part, and the rest for
58+
the graph part. Maximum width defaults to terminal width,
59+
or 80 columns if not connected to a terminal, and can be
60+
overriden by `<width>`. The width of the filename part can be
61+
limited by giving another width `<name-width>` after a comma.
6062
By giving a third parameter `<count>`, you can limit the
61-
output to the first `<count>` lines, followed by
62-
`...` if there are more.
63+
output to the first `<count>` lines, followed by `...` if
64+
there are more.
6365
+
6466
These parameters can also be set individually with `--stat-width=<width>`,
6567
`--stat-name-width=<name-width>` and `--stat-count=<count>`.

diff.c

Lines changed: 60 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,7 +1329,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
13291329
int i, len, add, del, adds = 0, dels = 0;
13301330
uintmax_t max_change = 0, max_len = 0;
13311331
int total_files = data->nr;
1332-
int width, name_width, count;
1332+
int width, name_width, graph_width, number_width = 4, count;
13331333
const char *reset, *add_c, *del_c;
13341334
const char *line_prefix = "";
13351335
int extra_shown = 0;
@@ -1343,28 +1343,15 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
13431343
line_prefix = msg->buf;
13441344
}
13451345

1346-
if (options->stat_width == -1)
1347-
width = term_columns();
1348-
else
1349-
width = options->stat_width ? options->stat_width : 80;
1350-
name_width = options->stat_name_width ? options->stat_name_width : 50;
13511346
count = options->stat_count ? options->stat_count : data->nr;
13521347

1353-
/* Sanity: give at least 5 columns to the graph,
1354-
* but leave at least 10 columns for the name.
1355-
*/
1356-
if (width < 25)
1357-
width = 25;
1358-
if (name_width < 10)
1359-
name_width = 10;
1360-
else if (width < name_width + 15)
1361-
name_width = width - 15;
1362-
1363-
/* Find the longest filename and max number of changes */
13641348
reset = diff_get_color_opt(options, DIFF_RESET);
13651349
add_c = diff_get_color_opt(options, DIFF_FILE_NEW);
13661350
del_c = diff_get_color_opt(options, DIFF_FILE_OLD);
13671351

1352+
/*
1353+
* Find the longest filename and max number of changes
1354+
*/
13681355
for (i = 0; (i < count) && (i < data->nr); i++) {
13691356
struct diffstat_file *file = data->files[i];
13701357
uintmax_t change = file->added + file->deleted;
@@ -1385,19 +1372,62 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
13851372
}
13861373
count = i; /* min(count, data->nr) */
13871374

1388-
/* Compute the width of the graph part;
1389-
* 10 is for one blank at the beginning of the line plus
1390-
* " | count " between the name and the graph.
1375+
/*
1376+
* We have width = stat_width or term_columns() columns total.
1377+
* We want a maximum of min(max_len, stat_name_width) for the name part.
1378+
* We also need 1 for " " and 4 + decimal_width(max_change)
1379+
* for " | NNNN " and one the empty column at the end, altogether
1380+
* 6 + decimal_width(max_change).
1381+
*
1382+
* If there's not enough space, we will use the smaller of
1383+
* stat_name_width (if set) and 5/8*width for the filename,
1384+
* and the rest for constant elements + graph part.
1385+
* (5/8 gives 50 for filename and 30 for the constant parts + graph
1386+
* for the standard terminal size).
13911387
*
1392-
* From here on, name_width is the width of the name area,
1393-
* and width is the width of the graph area.
1388+
* In other words: stat_width limits the maximum width, and
1389+
* stat_name_width fixes the maximum width of the filename,
1390+
* and is also used to divide available columns if there
1391+
* aren't enough.
13941392
*/
1395-
name_width = (name_width < max_len) ? name_width : max_len;
1396-
if (width < (name_width + 10) + max_change)
1397-
width = width - (name_width + 10);
1393+
1394+
if (options->stat_width == -1)
1395+
width = term_columns();
13981396
else
1399-
width = max_change;
1397+
width = options->stat_width ? options->stat_width : 80;
14001398

1399+
/*
1400+
* Guarantee 3/8*16==6 for the graph part
1401+
* and 5/8*16==10 for the filename part
1402+
*/
1403+
if (width < 16 + 6 + number_width)
1404+
width = 16 + 6 + number_width;
1405+
1406+
/*
1407+
* First assign sizes that are wanted, ignoring available width.
1408+
*/
1409+
graph_width = max_change;
1410+
name_width = (options->stat_name_width > 0 &&
1411+
options->stat_name_width < max_len) ?
1412+
options->stat_name_width : max_len;
1413+
1414+
/*
1415+
* Adjust adjustable widths not to exceed maximum width
1416+
*/
1417+
if (name_width + number_width + 6 + graph_width > width) {
1418+
if (graph_width > width * 3/8 - number_width - 6)
1419+
graph_width = width * 3/8 - number_width - 6;
1420+
if (name_width > width - number_width - 6 - graph_width)
1421+
name_width = width - number_width - 6 - graph_width;
1422+
else
1423+
graph_width = width - number_width - 6 - name_width;
1424+
}
1425+
1426+
/*
1427+
* From here name_width is the width of the name area,
1428+
* and graph_width is the width of the graph area.
1429+
* max_change is used to scale graph properly.
1430+
*/
14011431
for (i = 0; i < count; i++) {
14021432
const char *prefix = "";
14031433
char *name = data->files[i]->print_name;
@@ -1453,18 +1483,18 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
14531483
adds += add;
14541484
dels += del;
14551485

1456-
if (width <= max_change) {
1486+
if (graph_width <= max_change) {
14571487
int total = add + del;
14581488

1459-
total = scale_linear(add + del, width, max_change);
1489+
total = scale_linear(add + del, graph_width, max_change);
14601490
if (total < 2 && add && del)
14611491
/* width >= 2 due to the sanity check */
14621492
total = 2;
14631493
if (add < del) {
1464-
add = scale_linear(add, width, max_change);
1494+
add = scale_linear(add, graph_width, max_change);
14651495
del = total - add;
14661496
} else {
1467-
del = scale_linear(del, width, max_change);
1497+
del = scale_linear(del, graph_width, max_change);
14681498
add = total - del;
14691499
}
14701500
}

t/t4052-stat-output.sh

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,18 @@ test_expect_success 'preparation' '
2222
while read cmd args
2323
do
2424
cat >expect <<-'EOF'
25-
...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 +
25+
...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1 +
2626
EOF
27-
test_expect_success "$cmd: a short graph bar does not extend to the full width" '
27+
test_expect_success "$cmd: small change with long name gives more space to the name" '
2828
git $cmd $args >output &&
2929
grep " | " output >actual &&
3030
test_cmp expect actual
3131
'
3232

3333
cat >expect <<-'EOF'
34-
...aaaaaaaaaaaaaaaaaaaaaa | 1 +
34+
...aaaaaaaaaaaaaaaaaaaaaaaaaa | 1 +
3535
EOF
36-
test_expect_success "$cmd --stat=width: name is chopped to leave room to the right of a short bar" '
36+
test_expect_success "$cmd --stat=width: a long name is given more room when the bar is short" '
3737
git $cmd $args --stat=40 >output &&
3838
grep " | " output >actual &&
3939
test_cmp expect actual
@@ -131,11 +131,11 @@ test_expect_success 'preparation for long filename tests' '
131131
'
132132

133133
cat >expect <<'EOF'
134-
...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 +++++
134+
...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++
135135
EOF
136136
while read cmd args
137137
do
138-
test_expect_success "$cmd --stat=width with big change and long name favors name part" '
138+
test_expect_success "$cmd --stat=width with big change is more balanced" '
139139
git $cmd $args --stat-width=60 >output &&
140140
grep " | " output >actual &&
141141
test_cmp expect actual
@@ -151,7 +151,7 @@ cat >expect80 <<'EOF'
151151
...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++++++++++
152152
EOF
153153
cat >expect200 <<'EOF'
154-
...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
154+
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
155155
EOF
156156
while read verb expect cmd args
157157
do
@@ -178,7 +178,7 @@ test_expect_success 'merge --stat respects COLUMNS (big change)' '
178178
'
179179

180180
cat >expect <<'EOF'
181-
...aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 ++++++++++++++++++++++++++++++++++++++++
181+
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | 1000 +++++++++++++++++++++++++++++++++++++++
182182
EOF
183183
test_expect_success 'merge --stat respects COLUMNS (long filename)' '
184184
COLUMNS=100 git merge --stat --no-ff master >output &&

0 commit comments

Comments
 (0)