@@ -31,6 +31,7 @@ static const char *external_diff_cmd_cfg;
31
31
int diff_auto_refresh_index = 1 ;
32
32
static int diff_mnemonic_prefix ;
33
33
static int diff_no_prefix ;
34
+ static int diff_stat_graph_width ;
34
35
static int diff_dirstat_permille_default = 30 ;
35
36
static struct diff_options default_diff_options ;
36
37
@@ -156,6 +157,10 @@ int git_diff_ui_config(const char *var, const char *value, void *cb)
156
157
diff_no_prefix = git_config_bool (var , value );
157
158
return 0 ;
158
159
}
160
+ if (!strcmp (var , "diff.statgraphwidth" )) {
161
+ diff_stat_graph_width = git_config_int (var , value );
162
+ return 0 ;
163
+ }
159
164
if (!strcmp (var , "diff.external" ))
160
165
return git_config_string (& external_diff_cmd_cfg , var , value );
161
166
if (!strcmp (var , "diff.wordregex" ))
@@ -1375,7 +1380,7 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
1375
1380
int i , len , add , del , adds = 0 , dels = 0 ;
1376
1381
uintmax_t max_change = 0 , max_len = 0 ;
1377
1382
int total_files = data -> nr ;
1378
- int width , name_width , count ;
1383
+ int width , name_width , graph_width , number_width = 4 , count ;
1379
1384
const char * reset , * add_c , * del_c ;
1380
1385
const char * line_prefix = "" ;
1381
1386
int extra_shown = 0 ;
@@ -1389,25 +1394,15 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
1389
1394
line_prefix = msg -> buf ;
1390
1395
}
1391
1396
1392
- width = options -> stat_width ? options -> stat_width : 80 ;
1393
- name_width = options -> stat_name_width ? options -> stat_name_width : 50 ;
1394
1397
count = options -> stat_count ? options -> stat_count : data -> nr ;
1395
1398
1396
- /* Sanity: give at least 5 columns to the graph,
1397
- * but leave at least 10 columns for the name.
1398
- */
1399
- if (width < 25 )
1400
- width = 25 ;
1401
- if (name_width < 10 )
1402
- name_width = 10 ;
1403
- else if (width < name_width + 15 )
1404
- name_width = width - 15 ;
1405
-
1406
- /* Find the longest filename and max number of changes */
1407
1399
reset = diff_get_color_opt (options , DIFF_RESET );
1408
1400
add_c = diff_get_color_opt (options , DIFF_FILE_NEW );
1409
1401
del_c = diff_get_color_opt (options , DIFF_FILE_OLD );
1410
1402
1403
+ /*
1404
+ * Find the longest filename and max number of changes
1405
+ */
1411
1406
for (i = 0 ; (i < count ) && (i < data -> nr ); i ++ ) {
1412
1407
struct diffstat_file * file = data -> files [i ];
1413
1408
uintmax_t change = file -> added + file -> deleted ;
@@ -1428,19 +1423,72 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
1428
1423
}
1429
1424
count = i ; /* min(count, data->nr) */
1430
1425
1431
- /* Compute the width of the graph part;
1432
- * 10 is for one blank at the beginning of the line plus
1433
- * " | count " between the name and the graph.
1426
+ /*
1427
+ * We have width = stat_width or term_columns() columns total.
1428
+ * We want a maximum of min(max_len, stat_name_width) for the name part.
1429
+ * We want a maximum of min(max_change, stat_graph_width) for the +- part.
1430
+ * We also need 1 for " " and 4 + decimal_width(max_change)
1431
+ * for " | NNNN " and one the empty column at the end, altogether
1432
+ * 6 + decimal_width(max_change).
1433
+ *
1434
+ * If there's not enough space, we will use the smaller of
1435
+ * stat_name_width (if set) and 5/8*width for the filename,
1436
+ * and the rest for constant elements + graph part, but no more
1437
+ * than stat_graph_width for the graph part.
1438
+ * (5/8 gives 50 for filename and 30 for the constant parts + graph
1439
+ * for the standard terminal size).
1434
1440
*
1435
- * From here on, name_width is the width of the name area,
1436
- * and width is the width of the graph area.
1441
+ * In other words: stat_width limits the maximum width, and
1442
+ * stat_name_width fixes the maximum width of the filename,
1443
+ * and is also used to divide available columns if there
1444
+ * aren't enough.
1437
1445
*/
1438
- name_width = ( name_width < max_len ) ? name_width : max_len ;
1439
- if (width < ( name_width + 10 ) + max_change )
1440
- width = width - ( name_width + 10 );
1446
+
1447
+ if (options -> stat_width == -1 )
1448
+ width = term_columns ( );
1441
1449
else
1442
- width = max_change ;
1450
+ width = options -> stat_width ? options -> stat_width : 80 ;
1451
+
1452
+ if (options -> stat_graph_width == -1 )
1453
+ options -> stat_graph_width = diff_stat_graph_width ;
1443
1454
1455
+ /*
1456
+ * Guarantee 3/8*16==6 for the graph part
1457
+ * and 5/8*16==10 for the filename part
1458
+ */
1459
+ if (width < 16 + 6 + number_width )
1460
+ width = 16 + 6 + number_width ;
1461
+
1462
+ /*
1463
+ * First assign sizes that are wanted, ignoring available width.
1464
+ */
1465
+ graph_width = (options -> stat_graph_width &&
1466
+ options -> stat_graph_width < max_change ) ?
1467
+ options -> stat_graph_width : max_change ;
1468
+ name_width = (options -> stat_name_width > 0 &&
1469
+ options -> stat_name_width < max_len ) ?
1470
+ options -> stat_name_width : max_len ;
1471
+
1472
+ /*
1473
+ * Adjust adjustable widths not to exceed maximum width
1474
+ */
1475
+ if (name_width + number_width + 6 + graph_width > width ) {
1476
+ if (graph_width > width * 3 /8 - number_width - 6 )
1477
+ graph_width = width * 3 /8 - number_width - 6 ;
1478
+ if (options -> stat_graph_width &&
1479
+ graph_width > options -> stat_graph_width )
1480
+ graph_width = options -> stat_graph_width ;
1481
+ if (name_width > width - number_width - 6 - graph_width )
1482
+ name_width = width - number_width - 6 - graph_width ;
1483
+ else
1484
+ graph_width = width - number_width - 6 - name_width ;
1485
+ }
1486
+
1487
+ /*
1488
+ * From here name_width is the width of the name area,
1489
+ * and graph_width is the width of the graph area.
1490
+ * max_change is used to scale graph properly.
1491
+ */
1444
1492
for (i = 0 ; i < count ; i ++ ) {
1445
1493
const char * prefix = "" ;
1446
1494
char * name = data -> files [i ]-> print_name ;
@@ -1496,18 +1544,18 @@ static void show_stats(struct diffstat_t *data, struct diff_options *options)
1496
1544
adds += add ;
1497
1545
dels += del ;
1498
1546
1499
- if (width <= max_change ) {
1547
+ if (graph_width <= max_change ) {
1500
1548
int total = add + del ;
1501
1549
1502
- total = scale_linear (add + del , width , max_change );
1550
+ total = scale_linear (add + del , graph_width , max_change );
1503
1551
if (total < 2 && add && del )
1504
1552
/* width >= 2 due to the sanity check */
1505
1553
total = 2 ;
1506
1554
if (add < del ) {
1507
- add = scale_linear (add , width , max_change );
1555
+ add = scale_linear (add , graph_width , max_change );
1508
1556
del = total - add ;
1509
1557
} else {
1510
- del = scale_linear (del , width , max_change );
1558
+ del = scale_linear (del , graph_width , max_change );
1511
1559
add = total - del ;
1512
1560
}
1513
1561
}
@@ -3299,6 +3347,7 @@ static int stat_opt(struct diff_options *options, const char **av)
3299
3347
char * end ;
3300
3348
int width = options -> stat_width ;
3301
3349
int name_width = options -> stat_name_width ;
3350
+ int graph_width = options -> stat_graph_width ;
3302
3351
int count = options -> stat_count ;
3303
3352
int argcount = 1 ;
3304
3353
@@ -3327,6 +3376,16 @@ static int stat_opt(struct diff_options *options, const char **av)
3327
3376
name_width = strtoul (av [1 ], & end , 10 );
3328
3377
argcount = 2 ;
3329
3378
}
3379
+ } else if (!prefixcmp (arg , "-graph-width" )) {
3380
+ arg += strlen ("-graph-width" );
3381
+ if (* arg == '=' )
3382
+ graph_width = strtoul (arg + 1 , & end , 10 );
3383
+ else if (!* arg && !av [1 ])
3384
+ die ("Option '--stat-graph-width' requires a value" );
3385
+ else if (!* arg ) {
3386
+ graph_width = strtoul (av [1 ], & end , 10 );
3387
+ argcount = 2 ;
3388
+ }
3330
3389
} else if (!prefixcmp (arg , "-count" )) {
3331
3390
arg += strlen ("-count" );
3332
3391
if (* arg == '=' )
@@ -3352,6 +3411,7 @@ static int stat_opt(struct diff_options *options, const char **av)
3352
3411
return 0 ;
3353
3412
options -> output_format |= DIFF_FORMAT_DIFFSTAT ;
3354
3413
options -> stat_name_width = name_width ;
3414
+ options -> stat_graph_width = graph_width ;
3355
3415
options -> stat_width = width ;
3356
3416
options -> stat_count = count ;
3357
3417
return argcount ;
0 commit comments