Skip to content

Commit 86fdffd

Browse files
committed
Draw box around file and ruler around commit lines
The `diff-so-fancy.rulerWidth` config still applies, but to the ruler around the commit line. File lines have a box around them with just the size of the file name and prefixes/suffixes (e.g. `modified: diff-so-fancy`). This allows for a better hierarchical view of commits, with commit lines having a configurable wider ruler around them and file lines ("children" of commits) having a shorter box around them. Also fix `color.diff.meta` not being read correctly. Automated tests were not testing it correctly either: the value was being configured to 227 in test/test_helper/util.bash, but the tests are expecting `\e[1;33` (yellow bold). And fix diff-so-fancy failing with `Use of uninitialized value $less_charset in pattern match (m//) at diff-so-fancy line 524` when no less_char_vars environment variables are set, because get_less_charset was returning an empty tuple in this case.
1 parent e5bddde commit 86fdffd

File tree

3 files changed

+66
-73
lines changed

3 files changed

+66
-73
lines changed

diff-so-fancy

Lines changed: 54 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,29 @@ my $ruler_width = git_config("diff-so-fancy.rulerWidth", undef);
2828
my $git_strip_prefix = git_config_boolean("diff.noprefix","false");
2929
my $has_stdin = has_stdin();
3030

31+
my $box_horizontal;
32+
my $box_vertical;
33+
my $box_down;
34+
my $box_up;
35+
# BOX DRAWINGS LIGHT HORIZONTAL http://www.fileformat.info/info/unicode/char/2500/index.htm
36+
# BOX DRAWINGS LIGHT VERTICAL https://www.fileformat.info/info/unicode/char/2502/index.htm
37+
# BOX DRAWINGS LIGHT DOWN AND LEFT https://www.fileformat.info/info/unicode/char/2510/index.htm
38+
# BOX DRAWINGS LIGHT UP AND LEFT https://www.fileformat.info/info/unicode/char/2518/index.htm
39+
if ($use_unicode_dash_for_ruler && should_print_unicode()) {
40+
$box_horizontal = Encode::encode('UTF-8', "\x{2500}");
41+
$box_vertical = Encode::encode('UTF-8', "\x{2502}");
42+
$box_down = Encode::encode('UTF-8', "\x{2510}");
43+
$box_up = Encode::encode('UTF-8', "\x{2518}");
44+
} else {
45+
$box_horizontal = "-";
46+
$box_vertical = "|";
47+
$box_down = ".";
48+
$box_up = "'";
49+
}
50+
3151
my $ansi_color_regex = qr/(\e\[([0-9]{1,3}(;[0-9]{1,3}){0,10})[mK])?/;
3252
my $reset_color = color("reset");
3353
my $bold = color("bold");
34-
my $meta_color = "";
3554

3655
my ($file_1,$file_2);
3756
my $args = argv(); # Hashref of all the ARGV stuff
@@ -145,13 +164,15 @@ sub do_dsf_stuff {
145164

146165
#######################################################################
147166

167+
########################
168+
# Look for commit line #
169+
########################
170+
if ($line =~ /^${ansi_color_regex}commit [0-9a-f]{40}/) {
171+
print_commit_box($line);
148172
####################################################################
149173
# Look for git index and replace it horizontal line (header later) #
150174
####################################################################
151-
if ($line =~ /^${ansi_color_regex}index /) {
152-
# Print the line color and then the actual line
153-
$meta_color = $1 || get_config_color("meta");
154-
175+
} elsif ($line =~ /^${ansi_color_regex}index /) {
155176
# Get the next line without incrementing counter while loop
156177
my $next = $input->[0] || "";
157178
my ($file_1,$file_2);
@@ -171,9 +192,7 @@ sub do_dsf_stuff {
171192
}
172193

173194
if ($file_1 && $file_2) {
174-
print horizontal_rule($meta_color);
175-
print $meta_color . file_change_string($file_1,$file_2) . "\n";
176-
print horizontal_rule($meta_color);
195+
print_file_change_box(file_change_string($file_1,$file_2));
177196
}
178197
#########################
179198
# Look for the filename #
@@ -184,7 +203,6 @@ sub do_dsf_stuff {
184203
# Mercurial looks like: diff -r 82e55d328c8c hello.c
185204
if ($4 eq "-r") {
186205
$is_mercurial = 1;
187-
$meta_color ||= get_config_color("meta");
188206
# Git looks like: diff --git a/diff-so-fancy b/diff-so-fancy
189207
} else {
190208
$last_file_seen = $5;
@@ -200,8 +218,6 @@ sub do_dsf_stuff {
200218
# Find the first file: --- a/README.md #
201219
########################################
202220
} elsif (!$in_hunk && $line =~ /^$ansi_color_regex--- (\w\/)?(.+?)(\e|\t|$)/) {
203-
$meta_color ||= get_config_color("meta");
204-
205221
if ($git_strip_prefix) {
206222
my $file_dir = $4 || "";
207223
$file_1 = $file_dir . $5;
@@ -226,20 +242,7 @@ sub do_dsf_stuff {
226242
$last_file_seen = $file_2;
227243
}
228244

229-
# Print out the top horizontal line of the header
230-
print $reset_color;
231-
print horizontal_rule($meta_color);
232-
233-
# Mercurial coloring is slightly different so we need to hard reset colors
234-
if ($is_mercurial) {
235-
print $reset_color;
236-
}
237-
238-
print $meta_color;
239-
print file_change_string($file_1,$file_2) . "\n";
240-
241-
# Print out the bottom horizontal line of the header
242-
print horizontal_rule($meta_color);
245+
print_file_change_box(file_change_string($file_1,$file_2));
243246
########################################
244247
# Check for "@@ -3,41 +3,63 @@" syntax #
245248
########################################
@@ -309,10 +312,8 @@ sub do_dsf_stuff {
309312
# Look for binary file changes #
310313
################################
311314
} elsif ($line =~ /^Binary files (\w\/)?(.+?) and (\w\/)?(.+?) differ/) {
312-
my $change = file_change_string($2,$4);
313-
print horizontal_rule($meta_color);
314-
print "$meta_color$change (binary)\n";
315-
print horizontal_rule($meta_color);
315+
my ($change,$change_length) = file_change_string($2,$4);
316+
print_file_change_box($change . " (binary)", $change_length + 9);
316317
#####################################################
317318
# Check if we're changing the permissions of a file #
318319
#####################################################
@@ -351,14 +352,7 @@ sub do_dsf_stuff {
351352
my ($file2) = $next =~ /rename to (.+?)(\e|\t|$)/;
352353

353354
if ($file1 && $file2) {
354-
# We may not have extracted this yet, so we pull from the config if not
355-
$meta_color ||= get_config_color("meta");
356-
357-
my $change = file_change_string($file1,$file2);
358-
359-
print horizontal_rule($meta_color);
360-
print $meta_color . $change . "\n";
361-
print horizontal_rule($meta_color);
355+
print_file_change_box(file_change_string($file1,$file2));
362356
}
363357

364358
$i += 3; # We've consumed three lines
@@ -515,7 +509,7 @@ sub get_less_charset {
515509
}
516510
}
517511

518-
return ();
512+
return ("", "");
519513
}
520514

521515
sub should_print_unicode {
@@ -624,25 +618,23 @@ sub trim {
624618
return $s;
625619
}
626620

627-
# Print a line of em-dash or line-drawing chars the full width of the screen
628-
sub horizontal_rule {
629-
my $color = $_[0] || "";
630-
my $width = get_terminal_width();
631-
632-
# em-dash http://www.fileformat.info/info/unicode/char/2014/index.htm
633-
#my $dash = "\x{2014}";
634-
# BOX DRAWINGS LIGHT HORIZONTAL http://www.fileformat.info/info/unicode/char/2500/index.htm
635-
my $dash;
636-
if ($use_unicode_dash_for_ruler && should_print_unicode()) {
637-
$dash = Encode::encode('UTF-8', "\x{2500}");
638-
} else {
639-
$dash = "-";
640-
}
641-
642-
# Draw the line
643-
my $ret = $color . ($dash x $width) . "$reset_color\n";
621+
sub print_commit_box {
622+
my $line = shift();
623+
my $ruler = $box_horizontal x get_terminal_width();
624+
my $meta_color = get_config_color("meta");
625+
print $meta_color,$ruler,$reset_color,"\n";
626+
print $line;
627+
print $meta_color,$ruler,$reset_color,"\n";
628+
}
644629

645-
return $ret;
630+
sub print_file_change_box {
631+
my $change = shift();
632+
my $change_length = shift();
633+
my $ruler = $box_horizontal x ($change_length + 1);
634+
my $meta_color = get_config_color("meta");
635+
print $meta_color,$ruler,$box_down,$reset_color,"\n";
636+
print $meta_color,$change," ",$meta_color,$box_vertical,$reset_color,"\n";
637+
print $meta_color,$ruler,$box_up,$reset_color,"\n";
646638
}
647639

648640
sub file_change_string {
@@ -651,25 +643,26 @@ sub file_change_string {
651643

652644
# If they're the same it's a modify
653645
if ($file_1 eq $file_2) {
654-
return "modified: $file_1";
646+
return ("modified: $file_1", 10 + length($file_1));
655647
# If the first is /dev/null it's a new file
656648
} elsif ($file_1 eq "/dev/null") {
657649
my $add_color = $DiffHighlight::NEW_HIGHLIGHT[1];
658-
return "added: $add_color$file_2$reset_color";
650+
return ("added: $add_color$file_2$reset_color", 7 + length($file_2));
659651
# If the second is /dev/null it's a deletion
660652
} elsif ($file_2 eq "/dev/null") {
661653
my $del_color = $DiffHighlight::OLD_HIGHLIGHT[1];
662-
return "deleted: $del_color$file_1$reset_color";
654+
return ("deleted: $del_color$file_1$reset_color", 9 + length($file_1));
663655
# If the files aren't the same it's a rename
664656
} elsif ($file_1 ne $file_2) {
665657
my ($old, $new) = DiffHighlight::highlight_pair($file_1,$file_2,{only_diff => 1});
666658
# highlight_pair already includes reset_color, but adds newline characters that need to be trimmed off
667659
$old = trim($old);
668660
$new = trim($new);
669-
return "renamed: $old$meta_color to $new"
661+
my $meta_color = get_config_color("meta");
662+
return ("renamed: $old$meta_color to $new", 13 + length($file_1) + length($file_2));
670663
# Something we haven't thought of yet
671664
} else {
672-
return "$file_1 -> $file_2";
665+
return ("$file_1 -> $file_2", 4 + length($file_1) + length($file_2));
673666
}
674667
}
675668

test/diff-so-fancy.bats

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ output=$( load_fixture "ls-function" | $diff_so_fancy )
5353
@test "header format uses a native line-drawing character" {
5454
header=$( printf "%s" "$output" | head -n3 )
5555
run printf "%s" "$header"
56-
assert_line --index 0 --partial "[1;33m─────"
57-
assert_line --index 1 --partial "modified: fish/functions/ls.fish"
58-
assert_line --index 2 --partial "[1;33m─────"
56+
assert_line --index 0 --partial "[1;33m─────────────────────────────────┐"
57+
assert_line --index 1 --partial "modified: fish/functions/ls.fish [1;33m│"
58+
assert_line --index 2 --partial "[1;33m─────────────────────────────────┘"
5959
}
6060

6161
# see https://git.io/vrOF4
@@ -64,9 +64,9 @@ output=$( load_fixture "ls-function" | $diff_so_fancy )
6464
# pipe to cat(1) so we don't open stdout
6565
header=$( printf "%s" "$(load_fixture "ls-function" | $diff_so_fancy | cat)" | head -n3 )
6666
run printf "%s" "$header"
67-
assert_line --index 0 --partial "[1;33m-----"
68-
assert_line --index 1 --partial "modified: fish/functions/ls.fish"
69-
assert_line --index 2 --partial "[1;33m-----"
67+
assert_line --index 0 --partial "[1;33m---------------------------------."
68+
assert_line --index 1 --partial "modified: fish/functions/ls.fish [1;33m|"
69+
assert_line --index 2 --partial "[1;33m---------------------------------'"
7070
set_env # reset env
7171
}
7272

@@ -105,13 +105,13 @@ output=$( load_fixture "ls-function" | $diff_so_fancy )
105105
@test "Empty file add" {
106106
output=$( load_fixture "add_empty_file" | $diff_so_fancy )
107107
run printf "%s" "$output"
108-
assert_line --index 5 --regexp "added:.*empty_file.txt"
108+
assert_line --index 7 --regexp "added:.*empty_file.txt"
109109
}
110110

111111
@test "Empty file delete" {
112112
output=$( load_fixture "remove_empty_file" | $diff_so_fancy )
113113
run printf "%s" "$output"
114-
assert_line --index 5 --regexp "deleted:.*empty_file.txt"
114+
assert_line --index 7 --regexp "deleted:.*empty_file.txt"
115115
}
116116

117117
@test "Move with content change" {
@@ -193,8 +193,8 @@ output=$( load_fixture "ls-function" | $diff_so_fancy )
193193
output=$( load_fixture "complex-hunks" | $diff_so_fancy 2>&1 )
194194
run printf "%s" "$output"
195195

196-
assert_line --index 4 --partial "@ libs/header_clean/header_clean.pl:107 @"
197-
refute_output --partial 'Use of uninitialized value'
196+
assert_line --index 6 --partial "@ libs/header_clean/header_clean.pl:107 @"
197+
refute_output --partial 'Use of uninitialized value'
198198
}
199199

200200
@test "Hunk formatting: @@ -1,6 +1,6 @@" {

test/test_helper/util.bash

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ set_env() {
1313

1414
# applying colors so ANSI color values will match
1515
# FIXME: not everyone will have these set, so we need to test for that.
16-
git config color.diff.meta "227"
16+
git config color.diff.meta "yellow bold"
1717
git config color.diff.frag "magenta bold"
18-
git config color.diff.commit "227 bold"
18+
git config color.diff.commit "yellow bold"
1919
git config color.diff.old "red bold"
2020
git config color.diff.new "green bold"
2121
git config color.diff.whitespace "red reverse"

0 commit comments

Comments
 (0)