App-cloc
view release on metacpan or search on metacpan
### be installed in a temp directory if necessary.
##eval "use Algorithm::Diff qw ( sdiff ) ";
##if (defined $Algorithm::Diff::VERSION) {
## $HAVE_Algorith_Diff = 1;
##} else {
## Install_Algorithm_Diff();
##}
# print "2 HAVE_Algorith_Diff = $HAVE_Algorith_Diff\n";
# test_alg_diff($ARGV[$#ARGV - 1], $ARGV[$#ARGV]); die;
# die "Hre=$HAVE_Rexexp_Common Had=$HAVE_Algorith_Diff";
# Uncomment next two lines when building Windows executable with perl2exe
# or if running on a system that already has Regexp::Common.
#use Regexp::Common;
#$HAVE_Rexexp_Common = 1;
#perl2exe_include "Regexp/Common/whitespace.pm"
#perl2exe_include "Regexp/Common/URI.pm"
#perl2exe_include "Regexp/Common/URI/fax.pm"
#perl2exe_include "Regexp/Common/URI/file.pm"
#perl2exe_include "Regexp/Common/URI/ftp.pm"
#perl2exe_include "Regexp/Common/URI/gopher.pm"
#perl2exe_include "Regexp/Common/URI/http.pm"
#perl2exe_include "Regexp/Common/URI/pop.pm"
#perl2exe_include "Regexp/Common/URI/prospero.pm"
#perl2exe_include "Regexp/Common/URI/news.pm"
#perl2exe_include "Regexp/Common/URI/tel.pm"
#perl2exe_include "Regexp/Common/URI/telnet.pm"
#perl2exe_include "Regexp/Common/URI/tv.pm"
#perl2exe_include "Regexp/Common/URI/wais.pm"
#perl2exe_include "Regexp/Common/CC.pm"
#perl2exe_include "Regexp/Common/SEN.pm"
#perl2exe_include "Regexp/Common/number.pm"
#perl2exe_include "Regexp/Common/delimited.pm"
#perl2exe_include "Regexp/Common/profanity.pm"
#perl2exe_include "Regexp/Common/net.pm"
#perl2exe_include "Regexp/Common/zip.pm"
#perl2exe_include "Regexp/Common/comment.pm"
#perl2exe_include "Regexp/Common/balanced.pm"
#perl2exe_include "Regexp/Common/lingua.pm"
#perl2exe_include "Regexp/Common/list.pm"
#perl2exe_include "File/Glob.pm"
use Text::Tabs qw { expand };
use Cwd qw { cwd };
use File::Glob;
# 1}}}
# Usage information, options processing. {{{1
my $ON_WINDOWS = 0;
$ON_WINDOWS = 1 if ($^O =~ /^MSWin/) or ($^O eq "Windows_NT");
if ($ON_WINDOWS and $ENV{'SHELL'}) {
if ($ENV{'SHELL'} =~ m{^/}) {
$ON_WINDOWS = 0; # make Cygwin look like Unix
} else {
$ON_WINDOWS = 1; # MKS defines $SHELL but still acts like Windows
}
}
my $NN = chr(27) . "[0m"; # normal
$NN = "" if $ON_WINDOWS or !(-t STDERR); # -t STDERR: is it a terminal?
my $BB = chr(27) . "[1m"; # bold
$BB = "" if $ON_WINDOWS or !(-t STDERR);
my $script = basename $0;
my $brief_usage = "
cloc -- Count Lines of Code
Usage:
$script [options] <file(s)/dir(s)/git hash(es)>
Count physical lines of source code and comments in the given files
(may be archives such as compressed tarballs or zip files) and/or
recursively below the given directories or git commit hashes.
Example: cloc src/ include/ main.c
$script [options] --diff <set1> <set2>
Compute differences of physical lines of source code and comments
between any pairwise combination of directory names, archive
files or git commit hashes.
Example: cloc --diff Python-3.5.tar.xz python-3.6/
$script --help shows full documentation on the options.
http://$URL has numerous examples and more information.
";
my $usage = "
Usage: $script [options] <file(s)/dir(s)/git hash(es)> | <set 1> <set 2> | <report files>
Count, or compute differences of, physical lines of source code in the
given files (may be archives such as compressed tarballs or zip files,
or git commit hashes or branch names) and/or recursively below the
given directories.
${BB}Input Options${NN}
--extract-with=<cmd> This option is only needed if cloc is unable
to figure out how to extract the contents of
the input file(s) by itself.
Use <cmd> to extract binary archive files (e.g.:
.tar.gz, .zip, .Z). Use the literal '>FILE<' as
a stand-in for the actual file(s) to be
extracted. For example, to count lines of code
in the input files
gcc-4.2.tar.gz perl-5.8.8.tar.gz
on Unix use
--extract-with='gzip -dc >FILE< | tar xf -'
or, if you have GNU tar,
--extract-with='tar zxf >FILE<'
and on Windows use, for example:
--extract-with=\"\\\"c:\\Program Files\\WinZip\\WinZip32.exe\\\" -e -o >FILE< .\"
(if WinZip is installed there).
--list-file=<file> Take the list of file and/or directory names to
process from <file>, which has one file/directory
name per line. Only exact matches are counted;
relative path names will be resolved starting from
the directory where cloc is invoked.
See also --exclude-list-file.
--vcs=<VCS> Invoke a system call to <VCS> to obtain a list of
files to work on. If <VCS> is 'git', then will
invoke 'git ls-files' to get a file list and
'git submodule status' to get a list of submodules
whose contents will be ignored. See also --git
which accepts git commit hashes and branch names.
If <VCS> is 'svn' then will invoke 'svn list -R'.
The primary benefit is that cloc will then skip
sub xml_metachars { # {{{1
# http://en.wikipedia.org/wiki/Character_encodings_in_HTML#XML_character_references
my ($string, ) = shift @_;
my @in_chars = split(//, $string);
my @out_chars = ();
foreach my $c (@in_chars) {
if ($c eq '&') { push @out_chars, '&'
} elsif ($c eq '<') { push @out_chars, '<'
} elsif ($c eq '>') { push @out_chars, '>'
} elsif ($c eq '"') { push @out_chars, '"'
} elsif ($c eq "'") { push @out_chars, '''
} else {
push @out_chars, $c;
}
}
return join "", @out_chars;
} # 1}}}
sub html_metachars { # {{{1
# Replace HTML metacharacters with their printable forms.
# Future: use HTML-Encoder-0.00_04/lib/HTML/Encoder.pm
# from Fabiano Reese Righetti's HTML::Encoder module if
# this subroutine proves to be too simplistic.
my ($string, ) = shift @_;
my @in_chars = split(//, $string);
my @out_chars = ();
foreach my $c (@in_chars) {
if ($c eq '<') {
push @out_chars, '<'
} elsif ($c eq '>') {
push @out_chars, '>'
} elsif ($c eq '&') {
push @out_chars, '&'
} else {
push @out_chars, $c;
}
}
return join "", @out_chars;
} # 1}}}
sub test_alg_diff { # {{{1
my ($file_1 ,
$file_2 )
= @_;
my $fh_1 = new IO::File $file_1, "r";
die "Unable to read $file_1: $!\n" unless defined $fh_1;
chomp(my @lines_1 = <$fh_1>);
$fh_1->close;
my $fh_2 = new IO::File $file_2, "r";
die "Unable to read $file_2: $!\n" unless defined $fh_2;
chomp(my @lines_2 = <$fh_2>);
$fh_2->close;
my $n_no_change = 0;
my $n_modified = 0;
my $n_added = 0;
my $n_deleted = 0;
my @min_sdiff = ();
my $NN = chr(27) . "[0m"; # normal
my $BB = chr(27) . "[1m"; # bold
my @sdiffs = sdiff( \@lines_1, \@lines_2 );
foreach my $entry (@sdiffs) {
my ($out_1, $out_2) = ('', '');
if ($entry->[0] eq 'u') {
++$n_no_change;
# $out_1 = $entry->[1];
# $out_2 = $entry->[2];
next;
}
# push @min_sdiff, $entry;
if ($entry->[0] eq 'c') {
++$n_modified;
($out_1, $out_2) = diff_two_strings($entry->[1], $entry->[2]);
$out_1 =~ s/\cA(\w)/${BB}$1${NN}/g;
$out_2 =~ s/\cA(\w)/${BB}$1${NN}/g;
# $out_1 =~ s/\cA//g;
# $out_2 =~ s/\cA//g;
} elsif ($entry->[0] eq '+') {
++$n_added;
$out_1 = $entry->[1];
$out_2 = $entry->[2];
} elsif ($entry->[0] eq '-') {
++$n_deleted;
$out_1 = $entry->[1];
$out_2 = $entry->[2];
} elsif ($entry->[0] eq 'u') {
} else { die "unknown entry->[0]=[$entry->[0]]\n"; }
printf "%-80s | %s\n", $out_1, $out_2;
}
# foreach my $entry (@min_sdiff) {
# printf "DIFF: %s %s %s\n", @{$entry};
# }
} # 1}}}
sub write_comments_to_html { # {{{1
my ($filename , # in
$rah_diff_L , # in see routine array_diff() for explanation
$rah_diff_R , # in see routine array_diff() for explanation
$rh_blank , # in location and counts of blank lines
) = @_;
print "-> write_comments_to_html($filename)\n" if $opt_v > 2;
my $file = $filename . ".html";
#use Data::Dumper;
#print Dumper("rah_diff_L", $rah_diff_L, "rah_diff_R", $rah_diff_R);
my $OUT = new IO::File $file, "w";
if (!defined $OUT) {
warn "Unable to write to $file\n";
print "<- write_comments_to_html\n" if $opt_v > 2;
return;
}
my $approx_line_count = scalar @{$rah_diff_L};
my $n_digits = 1 + int(log($approx_line_count)/2.30258509299405); # log_10
my $html_out = html_header($filename);
my $comment_line_number = 0;
for (my $i = 0; $i < scalar @{$rah_diff_R}; $i++) {
( run in 1.253 second using v1.01-cache-2.11-cpan-39bf76dae61 )