gitweb: Refactor diff body line classification

Simplify classification of diff line body in format_diff_line(), replacing two long if-elsif chains (one for ordinary diff and one for combined diff of a merge commit) with a single regexp match. Refactor this code into diff_line_class() function. While at it: * Fix an artifact in that $diff_class included leading space to be able to compose classes like this "class=\"diff$diff_class\"', even when $diff_class was an empty string. This made code unnecessary ugly: $diff_class is now just class name or an empty string. * Introduce "ctx" class for context lines ($diff_class was set to "" in this case before this commit). Idea and initial code by Junio C Hamano, polish and testing by Jakub Narebski. Inspired by patch adding side-by-side diff by Kato Kazuyoshi, which required $diff_class to be name of class without extra space. Signed-off-by: Junio C Hamano <gitster@pobox.com> Signed-off-by: Jakub Narebski <jnareb@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jakub Narebski committed Oct 31, 2011 at 00:36 UTC 20a864cd835d5d3f559c3cddf5ac5c259bd61171
1 file changed +37 -30
gitweb/gitweb.perl
+37 -30
@@ -2225,40 +2225,47 @@ sub format_diff_cc_simplified {
2225 return $result;
2226 }
2227
2228 +sub diff_line_class {
2229 + my ($line, $from, $to) = @_;
2230 +
2231 + # ordinary diff
2232 + my $num_sign = 1;
2233 + # combined diff
2234 + if ($from && $to && ref($from->{'href'}) eq "ARRAY") {
2235 + $num_sign = scalar @{$from->{'href'}};
2236 + }
2237 +
2238 + my @diff_line_classifier = (
2239 + { regexp => qr/^\@\@{$num_sign} /, class => "chunk_header"},
2240 + { regexp => qr/^\\/, class => "incomplete" },
2241 + { regexp => qr/^ {$num_sign}/, class => "ctx" },
2242 + # classifier for context must come before classifier add/rem,
2243 + # or we would have to use more complicated regexp, for example
2244 + # qr/(?= {0,$m}\+)[+ ]{$num_sign}/, where $m = $num_sign - 1;
2245 + { regexp => qr/^[+ ]{$num_sign}/, class => "add" },
2246 + { regexp => qr/^[- ]{$num_sign}/, class => "rem" },
2247 + );
2248 + for my $clsfy (@diff_line_classifier) {
2249 + return $clsfy->{'class'}
2250 + if ($line =~ $clsfy->{'regexp'});
2251 + }
2252 +
2253 + # fallback
2254 + return "";
2255 +}
2256 +
2257 # format patch (diff) line (not to be used for diff headers)
2258 sub format_diff_line {
2259 my $line = shift;
2260 my ($from, $to) = @_;
2232 - my $diff_class = "";
2261
2234 - chomp $line;
2262 + my $diff_class = diff_line_class($line, $from, $to);
2263 + my $diff_classes = "diff";
2264 + $diff_classes .= " $diff_class" if ($diff_class);
2265
2236 - if ($from && $to && ref($from->{'href'}) eq "ARRAY") {
2237 - # combined diff
2238 - my $prefix = substr($line, 0, scalar @{$from->{'href'}});
2239 - if ($line =~ m/^\@{3}/) {
2240 - $diff_class = " chunk_header";
2241 - } elsif ($line =~ m/^\\/) {
2242 - $diff_class = " incomplete";
2243 - } elsif ($prefix =~ tr/+/+/) {
2244 - $diff_class = " add";
2245 - } elsif ($prefix =~ tr/-/-/) {
2246 - $diff_class = " rem";
2247 - }
2248 - } else {
2249 - # assume ordinary diff
2250 - my $char = substr($line, 0, 1);
2251 - if ($char eq '+') {
2252 - $diff_class = " add";
2253 - } elsif ($char eq '-') {
2254 - $diff_class = " rem";
2255 - } elsif ($char eq '@') {
2256 - $diff_class = " chunk_header";
2257 - } elsif ($char eq "\\") {
2258 - $diff_class = " incomplete";
2259 - }
2260 - }
2266 + chomp $line;
2267 $line = untabify($line);
2268 +
2269 if ($from && $to && $line =~ m/^\@{2} /) {
2270 my ($from_text, $from_start, $from_lines, $to_text, $to_start, $to_lines, $section) =
2271 $line =~ m/^\@{2} (-(\d+)(?:,(\d+))?) (\+(\d+)(?:,(\d+))?) \@{2}(.*)$/;
@@ -2276,7 +2283,7 @@ sub format_diff_line {
2283 }
2284 $line = "<span class=\"chunk_info\">@@ $from_text $to_text @@</span>" .
2285 "<span class=\"section\">" . esc_html($section, -nbsp=>1) . "</span>";
2279 - return "<div class=\"diff$diff_class\">$line</div>\n";
2286 + return "<div class=\"$diff_classes\">$line</div>\n";
2287 } elsif ($from && $to && $line =~ m/^\@{3}/) {
2288 my ($prefix, $ranges, $section) = $line =~ m/^(\@+) (.*?) \@+(.*)$/;
2289 my (@from_text, @from_start, @from_nlines, $to_text, $to_start, $to_nlines);
@@ -2309,9 +2316,9 @@ sub format_diff_line {
2316 }
2317 $line .= " $prefix</span>" .
2318 "<span class=\"section\">" . esc_html($section, -nbsp=>1) . "</span>";
2312 - return "<div class=\"diff$diff_class\">$line</div>\n";
2319 + return "<div class=\"$diff_classes\">$line</div>\n";
2320 }
2314 - return "<div class=\"diff$diff_class\">" . esc_html($line, -nbsp=>1) . "</div>\n";
2321 + return "<div class=\"$diff_classes\">" . esc_html($line, -nbsp=>1) . "</div>\n";
2322 }
2323
2324 # Generates undef or something like "_snapshot_" or "snapshot (_tbz2_ _zip_)",