Skip to content

Commit fde773f

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.
1 parent e5bddde commit fde773f

File tree

2 files changed

+63
-69
lines changed

2 files changed

+63
-69
lines changed

diff-so-fancy

Lines changed: 53 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,26 @@ 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");
@@ -145,13 +165,15 @@ sub do_dsf_stuff {
145165

146166
#######################################################################
147167

168+
########################
169+
# Look for commit line #
170+
########################
171+
if ($line =~ /^${ansi_color_regex}commit [0-9a-f]{40}/) {
172+
print_commit_box($line);
148173
####################################################################
149174
# Look for git index and replace it horizontal line (header later) #
150175
####################################################################
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-
176+
} elsif ($line =~ /^${ansi_color_regex}index /) {
155177
# Get the next line without incrementing counter while loop
156178
my $next = $input->[0] || "";
157179
my ($file_1,$file_2);
@@ -171,9 +193,7 @@ sub do_dsf_stuff {
171193
}
172194

173195
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);
196+
print_file_change_box(file_change_string($file_1,$file_2));
177197
}
178198
#########################
179199
# Look for the filename #
@@ -184,7 +204,6 @@ sub do_dsf_stuff {
184204
# Mercurial looks like: diff -r 82e55d328c8c hello.c
185205
if ($4 eq "-r") {
186206
$is_mercurial = 1;
187-
$meta_color ||= get_config_color("meta");
188207
# Git looks like: diff --git a/diff-so-fancy b/diff-so-fancy
189208
} else {
190209
$last_file_seen = $5;
@@ -200,8 +219,6 @@ sub do_dsf_stuff {
200219
# Find the first file: --- a/README.md #
201220
########################################
202221
} elsif (!$in_hunk && $line =~ /^$ansi_color_regex--- (\w\/)?(.+?)(\e|\t|$)/) {
203-
$meta_color ||= get_config_color("meta");
204-
205222
if ($git_strip_prefix) {
206223
my $file_dir = $4 || "";
207224
$file_1 = $file_dir . $5;
@@ -226,20 +243,7 @@ sub do_dsf_stuff {
226243
$last_file_seen = $file_2;
227244
}
228245

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);
246+
print_file_change_box(file_change_string($file_1,$file_2));
243247
########################################
244248
# Check for "@@ -3,41 +3,63 @@" syntax #
245249
########################################
@@ -309,10 +313,8 @@ sub do_dsf_stuff {
309313
# Look for binary file changes #
310314
################################
311315
} 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);
316+
my ($change,$change_length) = file_change_string($2,$4);
317+
print_file_change_box($change . " (binary)", $change_length + 9);
316318
#####################################################
317319
# Check if we're changing the permissions of a file #
318320
#####################################################
@@ -351,14 +353,7 @@ sub do_dsf_stuff {
351353
my ($file2) = $next =~ /rename to (.+?)(\e|\t|$)/;
352354

353355
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);
356+
print_file_change_box(file_change_string($file1,$file2));
362357
}
363358

364359
$i += 3; # We've consumed three lines
@@ -624,25 +619,23 @@ sub trim {
624619
return $s;
625620
}
626621

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";
622+
sub print_commit_box {
623+
my $line = shift();
624+
my $ruler = $box_horizontal x get_terminal_width();
625+
$meta_color ||= get_config_color("meta");
626+
print $meta_color,$ruler,$reset_color,"\n";
627+
print $line;
628+
print $meta_color,$ruler,$reset_color,"\n";
629+
}
644630

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

648641
sub file_change_string {
@@ -651,25 +644,26 @@ sub file_change_string {
651644

652645
# If they're the same it's a modify
653646
if ($file_1 eq $file_2) {
654-
return "modified: $file_1";
647+
return ("modified: $file_1", 10 + length($file_1));
655648
# If the first is /dev/null it's a new file
656649
} elsif ($file_1 eq "/dev/null") {
657650
my $add_color = $DiffHighlight::NEW_HIGHLIGHT[1];
658-
return "added: $add_color$file_2$reset_color";
651+
return ("added: $add_color$file_2$reset_color", 7 + length($file_2));
659652
# If the second is /dev/null it's a deletion
660653
} elsif ($file_2 eq "/dev/null") {
661654
my $del_color = $DiffHighlight::OLD_HIGHLIGHT[1];
662-
return "deleted: $del_color$file_1$reset_color";
655+
return ("deleted: $del_color$file_1$reset_color", 9 + length($file_1));
663656
# If the files aren't the same it's a rename
664657
} elsif ($file_1 ne $file_2) {
665658
my ($old, $new) = DiffHighlight::highlight_pair($file_1,$file_2,{only_diff => 1});
666659
# highlight_pair already includes reset_color, but adds newline characters that need to be trimmed off
667660
$old = trim($old);
668661
$new = trim($new);
669-
return "renamed: $old$meta_color to $new"
662+
$meta_color ||= get_config_color("meta");
663+
return ("renamed: $old$meta_color to $new", 13 + length($file_1) + length($file_2));
670664
# Something we haven't thought of yet
671665
} else {
672-
return "$file_1 -> $file_2";
666+
return ("$file_1 -> $file_2", 4 + length($file_1) + length($file_2));
673667
}
674668
}
675669

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"
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 |"
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 @@" {

0 commit comments

Comments
 (0)