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}(.*)$/;
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);
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_)",