You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
72 lines
1.9 KiB
72 lines
1.9 KiB
#/usr/bin/perl |
|
|
|
# Given the diff output on stdin, run clang-format on the input hunks. |
|
# |
|
# Author: Bryan Tan (Technius) |
|
|
|
use strict; |
|
|
|
# Table mapping changed files to array of hunks. |
|
my %changed_files; |
|
# Array of hunks in the current file. Only stores the new location. |
|
my @hunks; |
|
# Current file |
|
my $current_file; |
|
|
|
my @CLANG_FMT_CMDS = ("clang-format", "clang-format-9"); |
|
my $clang_format_cmd = ""; |
|
for my $c (@CLANG_FMT_CMDS) { |
|
if (`$c --version`) { |
|
$clang_format_cmd = $c; |
|
last; |
|
} |
|
} |
|
|
|
if ($clang_format_cmd eq "") { |
|
printf "$0: clang-format not found\n"; |
|
exit 1; |
|
} |
|
|
|
# Push the pending hunks to the changed file table. |
|
sub push_changes { |
|
if (scalar @hunks > 0) { |
|
$changed_files{$current_file} = [@hunks]; |
|
@hunks = (); |
|
} |
|
} |
|
|
|
# Extract ranges of added lines |
|
while (my $line = <STDIN>) { |
|
if ($line =~ /^diff .* a\/(?<old_file>.*) b\/(?<new_file>.*)$/) { |
|
# New file |
|
push_changes; |
|
$current_file = $+{new_file}; |
|
} elsif ($line =~ /^@@ -([0-9]+)(,([0-9]+))? \+(?<new_pos>[0-9]+)(,(?<new_len>[0-9]+))? @@/) { |
|
my $new_len = $+{new_len}; |
|
$new_len = 1 if ($new_len eq ""); |
|
if ($new_len == 0) { |
|
# Ignore hunks with no added lines |
|
next; |
|
} |
|
push @hunks, [$+{new_pos}, $new_len]; |
|
} |
|
} |
|
push_changes; |
|
|
|
# Now, run clang format on the changed lines. |
|
while (my ($file_name, $hunks_ref) = each %changed_files) { |
|
my @ranges = (); |
|
foreach my $hunk_ref (@{$hunks_ref}) { |
|
my $start_pos = @{$hunk_ref}[0]; |
|
my $line_count = @{$hunk_ref}[1]; |
|
my $end_pos = $start_pos + $line_count - 1; |
|
if ($line_count > 0) { |
|
push @ranges, [$start_pos, $end_pos]; |
|
} |
|
} |
|
my $ranges_str = join(", ", map { "@{$_}[0]-@{$_}[1]" } @ranges); |
|
my $lines_arg = join(" ", map { "-lines=@{$_}[0]:@{$_}[1]" } @ranges); |
|
printf "Running $clang_format_cmd on %s, lines %s (inclusive)\n", $file_name, $ranges_str; |
|
`$clang_format_cmd -i -style=file $lines_arg $file_name`; |
|
die "Failed to run $clang_format_cmd: exit code $?" if $? != 0; |
|
}
|
|
|