Skip to content

Instantly share code, notes, and snippets.

@tJener
Last active December 14, 2015 10:39
Show Gist options
  • Save tJener/5074083 to your computer and use it in GitHub Desktop.
Save tJener/5074083 to your computer and use it in GitHub Desktop.
A LOC tool for git repositories, grouped by language and author.
#!/usr/bin/env perl
use strict;
use warnings;
use constant LOC_FILES_CMD => q(
xargs -n1 git blame --line-porcelain |
sed -n 's/^author //p' |
sort | uniq -c |
awk -F' author ' '{for(i=1;i<=NF;++i)printf$i OFS;print""}' |
sort -nr
);
use IPC::Open2;
my %lang = (
cpp => 'C/C++',
cxx => 'C/C++',
cc => 'C/C++',
c => 'C/C++',
hpp => 'C/C++',
hxx => 'C/C++',
hh => 'C/C++',
h => 'C/C++',
json => 'JSON',
js => 'JavaScript',
sh => 'Shell',
html => 'HTML',
css => 'CSS',
styl => 'Stylus',
);
my $paths = join ' ', grep { -e $_ } @ARGV;
my @files = `git grep -I --name-only -e "" -- $paths | cut -f 2` or exit 255;
my @source_files = map {
chomp;
m|\.([^./]+)$| and my $ext = lc $1;
$ext ? { language => $lang{$ext}, path => $_, extension => $ext } : ()
} @files;
my %buckets = ();
foreach (@source_files) {
my $heading = $_->{language} ? $_->{language} : '*.' . $_->{extension};
push @{ $buckets{$heading}{files} }, $_->{path};
}
my @output = ();
foreach my $key ( keys %buckets ) {
local ( *OUT, *IN );
my $pid = open2( \*OUT, \*IN, LOC_FILES_CMD );
print IN join "\n", @{ $buckets{$key}{files} }, '';
close IN;
my $total_lines = 0;
while (<OUT>) {
if (m|(\d+)\s+(\S(?:\s?\S)*)|) {
$buckets{$key}{lines}{$2} = $1;
$total_lines += $1;
}
}
close OUT;
push @output, join(
"\n", $key,
'=' x length $key,
map { $_->[0]; } sort { $b->[1] <=> $a->[1]; } map {
my $lines = $buckets{$key}{lines}{$_};
[
sprintf( "%6.1f%% %7d %s",
$lines * 100 / $total_lines,
$lines, $_ ),
$lines
];
} keys %{$buckets{$key}{lines}}
),
'';
waitpid $pid, 0;
}
print join "\n", @output;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment