@@ -1329,7 +1329,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
1329
1329
int i , len , add , del , adds = 0 , dels = 0 ;
1330
1330
uintmax_t max_change = 0 , max_len = 0 ;
1331
1331
int total_files = data -> nr ;
1332
- int width , name_width , count ;
1332
+ int width , name_width , graph_width , number_width = 4 , count ;
1333
1333
const char * reset , * add_c , * del_c ;
1334
1334
const char * line_prefix = "" ;
1335
1335
int extra_shown = 0 ;
@@ -1343,28 +1343,15 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
1343
1343
line_prefix = msg -> buf ;
1344
1344
}
1345
1345
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 ;
1351
1346
count = options -> stat_count ? options -> stat_count : data -> nr ;
1352
1347
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 */
1364
1348
reset = diff_get_color_opt (options , DIFF_RESET );
1365
1349
add_c = diff_get_color_opt (options , DIFF_FILE_NEW );
1366
1350
del_c = diff_get_color_opt (options , DIFF_FILE_OLD );
1367
1351
1352
+ /*
1353
+ * Find the longest filename and max number of changes
1354
+ */
1368
1355
for (i = 0 ; (i < count ) && (i < data -> nr ); i ++ ) {
1369
1356
struct diffstat_file * file = data -> files [i ];
1370
1357
uintmax_t change = file -> added + file -> deleted ;
@@ -1385,19 +1372,62 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
1385
1372
}
1386
1373
count = i ; /* min(count, data->nr) */
1387
1374
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).
1391
1387
*
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.
1394
1392
*/
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 ( );
1398
1396
else
1399
- width = max_change ;
1397
+ width = options -> stat_width ? options -> stat_width : 80 ;
1400
1398
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
+ */
1401
1431
for (i = 0 ; i < count ; i ++ ) {
1402
1432
const char * prefix = "" ;
1403
1433
char * name = data -> files [i ]-> print_name ;
@@ -1453,18 +1483,18 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
1453
1483
adds += add ;
1454
1484
dels += del ;
1455
1485
1456
- if (width <= max_change ) {
1486
+ if (graph_width <= max_change ) {
1457
1487
int total = add + del ;
1458
1488
1459
- total = scale_linear (add + del , width , max_change );
1489
+ total = scale_linear (add + del , graph_width , max_change );
1460
1490
if (total < 2 && add && del )
1461
1491
/* width >= 2 due to the sanity check */
1462
1492
total = 2 ;
1463
1493
if (add < del ) {
1464
- add = scale_linear (add , width , max_change );
1494
+ add = scale_linear (add , graph_width , max_change );
1465
1495
del = total - add ;
1466
1496
} else {
1467
- del = scale_linear (del , width , max_change );
1497
+ del = scale_linear (del , graph_width , max_change );
1468
1498
add = total - del ;
1469
1499
}
1470
1500
}
0 commit comments