Skip to content

Commit

Permalink
new switch --fmt for additional output formats, #764, #794
Browse files Browse the repository at this point in the history
Currently only for direct counts; --diff support in the
future.
  • Loading branch information
AlDanial committed Feb 2, 2024
1 parent 6913ed9 commit a5747ef
Show file tree
Hide file tree
Showing 2 changed files with 221 additions and 8 deletions.
32 changes: 28 additions & 4 deletions Unix/cloc
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ Usage: $script [options] <file(s)/dir(s)/git hash(es)> | <set 1> <set 2> | <repo
--autoconf Count .in files (as processed by GNU autoconf) of
recognized languages. See also --no-autogen.
--by-file Report results for every source file encountered.
See also --fmt under 'Output Options'.
--by-file-by-lang Report results for every source file encountered
in addition to reporting by language.
--config <file> Read command line switches from <file> instead of
Expand Down Expand Up @@ -614,6 +615,14 @@ Usage: $script [options] <file(s)/dir(s)/git hash(es)> | <set 1> <set 2> | <repo
'euc-kr', 'iso-8859-16'. Known encodings can be
printed with
perl -MEncode -e 'print join(\"\\n\", Encode->encodings(\":all\")), \"\\n\"'
--fmt=<N> Alternate text output format where <N> is a number
from 1 to 5. 'total lines' means the sum of code,
comment, and blank lines.
1: by language (same as cloc default output)
2: by language with an extra column for total lines
3: by file with language
4: by file with a total lines column
5: by file with language and a total lines column
--hide-rate Do not show elapsed time, line processing rate, or
file processing rates in the output header. This
makes output deterministic.
Expand Down Expand Up @@ -769,6 +778,7 @@ my (
$opt_skip_leading ,
$opt_no_recurse ,
$opt_only_count_files ,
$opt_fmt ,
);

my $getopt_success = GetOptions( # {{{1
Expand Down Expand Up @@ -873,6 +883,7 @@ my $getopt_success = GetOptions( # {{{1
"skip_leading|skip-leading:s" => \$opt_skip_leading ,
"no_recurse|no-recurse" => \$opt_no_recurse ,
"only_count_files|only-count-files" => \$opt_only_count_files ,
"fmt=i" => \$opt_fmt ,
);
# 1}}}
$config_file = $opt_config_file if defined $opt_config_file;
Expand Down Expand Up @@ -987,6 +998,13 @@ $opt_git = 1 if defined($opt_git_diff_all) or
defined($opt_git_diff_rel) or
(defined($opt_vcs) and ($opt_vcs eq "git"));
$opt_by_file = 1 if defined $opt_by_file_by_lang;
if ($opt_fmt) {
$opt_by_file = 1;
$opt_json = 1;
my $fh;
($fh, $opt_report_file) = tempfile(UNLINK => 0, DIR => ".", SUFFIX => ".json" );
$fh->close; # will be opened later by the JSON writer
}
my $CLOC_XSL = "cloc.xsl"; # created with --xsl
$CLOC_XSL = "cloc-diff.xsl" if $opt_diff;
die "\n" unless $getopt_success;
Expand Down Expand Up @@ -1083,7 +1101,7 @@ if ($ON_WINDOWS) {
if ($opt_git) {
# PowerShell tab expansion automatically prefixes local directories
# with ".\" (now mapped to "./"). git ls-files output does not
# include this. Strip this prefix to permit clean matches.
# include this. Strip this prefix to permit clean matches.
map { s{^\./}{} } @ARGV;
}
}
Expand Down Expand Up @@ -2171,8 +2189,14 @@ if ($opt_by_file_by_lang) {
}
# 1}}}
}
if ($opt_report_file) { write_file($opt_report_file, {}, @Lines_Out); }
else {
if ($opt_report_file) {
write_file($opt_report_file, {}, @Lines_Out);
if ($opt_fmt) {
my ($file_len, $lang_len, $header, %contents) = load_json($opt_report_file);
print_format_n($opt_fmt, $file_len, $lang_len, $header, %contents);
unlink $opt_report_file;
}
} else {
print "\n" unless $opt_quiet;
print join("\n", @Lines_Out), "\n";
}
Expand Down Expand Up @@ -6773,7 +6797,7 @@ sub write_file { # {{{1
$OUT->close;

if (can_read($file)) {
print "Wrote $file" unless $opt_quiet;
print "Wrote $file" unless $opt_quiet or $opt_fmt;
print ", $CLOC_XSL" if $opt_xsl and $opt_xsl eq $CLOC_XSL;
print "\n" unless $opt_quiet;
}
Expand Down
197 changes: 193 additions & 4 deletions cloc
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,7 @@ Usage: $script [options] <file(s)/dir(s)/git hash(es)> | <set 1> <set 2> | <repo
--autoconf Count .in files (as processed by GNU autoconf) of
recognized languages. See also --no-autogen.
--by-file Report results for every source file encountered.
See also --fmt under 'Output Options'.
--by-file-by-lang Report results for every source file encountered
in addition to reporting by language.
--config <file> Read command line switches from <file> instead of
Expand Down Expand Up @@ -639,6 +640,14 @@ Usage: $script [options] <file(s)/dir(s)/git hash(es)> | <set 1> <set 2> | <repo
'euc-kr', 'iso-8859-16'. Known encodings can be
printed with
perl -MEncode -e 'print join(\"\\n\", Encode->encodings(\":all\")), \"\\n\"'
--fmt=<N> Alternate text output format where <N> is a number
from 1 to 5. 'total lines' means the sum of code,
comment, and blank lines.
1: by language (same as cloc default output)
2: by language with an extra column for total lines
3: by file with language
4: by file with a total lines column
5: by file with language and a total lines column
--hide-rate Do not show elapsed time, line processing rate, or
file processing rates in the output header. This
makes output deterministic.
Expand Down Expand Up @@ -794,6 +803,7 @@ my (
$opt_skip_leading ,
$opt_no_recurse ,
$opt_only_count_files ,
$opt_fmt ,
);

my $getopt_success = GetOptions( # {{{1
Expand Down Expand Up @@ -898,6 +908,7 @@ my $getopt_success = GetOptions( # {{{1
"skip_leading|skip-leading:s" => \$opt_skip_leading ,
"no_recurse|no-recurse" => \$opt_no_recurse ,
"only_count_files|only-count-files" => \$opt_only_count_files ,
"fmt=i" => \$opt_fmt ,
);
# 1}}}
$config_file = $opt_config_file if defined $opt_config_file;
Expand Down Expand Up @@ -1002,6 +1013,13 @@ $opt_git = 1 if defined($opt_git_diff_all) or
defined($opt_git_diff_rel) or
(defined($opt_vcs) and ($opt_vcs eq "git"));
$opt_by_file = 1 if defined $opt_by_file_by_lang;
if ($opt_fmt) {
$opt_by_file = 1;
$opt_json = 1;
my $fh;
($fh, $opt_report_file) = tempfile(UNLINK => 0, DIR => ".", SUFFIX => ".json" );
$fh->close; # will be opened later by the JSON writer
}
my $CLOC_XSL = "cloc.xsl"; # created with --xsl
$CLOC_XSL = "cloc-diff.xsl" if $opt_diff;
die "\n" unless $getopt_success;
Expand Down Expand Up @@ -1098,7 +1116,7 @@ if ($ON_WINDOWS) {
if ($opt_git) {
# PowerShell tab expansion automatically prefixes local directories
# with ".\" (now mapped to "./"). git ls-files output does not
# include this. Strip this prefix to permit clean matches.
# include this. Strip this prefix to permit clean matches.
map { s{^\./}{} } @ARGV;
}
}
Expand Down Expand Up @@ -2186,8 +2204,14 @@ if ($opt_by_file_by_lang) {
}
# 1}}}
}
if ($opt_report_file) { write_file($opt_report_file, {}, @Lines_Out); }
else {
if ($opt_report_file) {
write_file($opt_report_file, {}, @Lines_Out);
if ($opt_fmt) {
my ($file_len, $lang_len, $header, %contents) = load_json($opt_report_file);
print_format_n($opt_fmt, $file_len, $lang_len, $header, %contents);
unlink $opt_report_file;
}
} else {
print "\n" unless $opt_quiet;
print join("\n", @Lines_Out), "\n";
}
Expand Down Expand Up @@ -6788,7 +6812,7 @@ sub write_file { # {{{1
$OUT->close;

if (can_read($file)) {
print "Wrote $file" unless $opt_quiet;
print "Wrote $file" unless $opt_quiet or $opt_fmt;
print ", $CLOC_XSL" if $opt_xsl and $opt_xsl eq $CLOC_XSL;
print "\n" unless $opt_quiet;
}
Expand Down Expand Up @@ -14291,6 +14315,171 @@ sub glob2regex { # {{{
$re =~ s{\cy}{[^/]*}g;
return '^' . $re . '$';
} # }}}
sub load_json { # {{{1
#
# Load a cloc-generated JSON file into %contents
# $contents{filename}{blank|comment|code|language} = value
# then print in a variety of formats.
#
my ($file, ) = @_;

my %contents = ();
my $heading = undef;
open IN, $file or die "failed load_json($file)";
while (<IN>) {
if (/^{?"(.*?)"/) {
$heading = $1;
} else {
if (/^\s+"(.*?)"\s*:\s+(\d+(\.\d+)?)\b/) {
# numeric value
$contents{$heading}{$1} = $2;
} elsif (/^\s+"(.*?)"\s*:\s+"(.*?)"/) {
$contents{$heading}{$1} = $2;
}
}
}
close IN;
my $url = $contents{'header'}{'cloc_url'};
my $ver = $contents{'header'}{'cloc_version'};
my $sec = $contents{'header'}{'elapsed_seconds'};
my $n_file = $contents{'header'}{'n_files'};
my $n_line = $contents{'header'}{'n_lines'};
$sec = $sec == 0 ? 1.0e-3 : $sec;
my $header = sprintf "%s v %s T=%.2f s (%.1f files/s, %.1f lines/s)",
$url, $ver, $sec, $n_file/$sec, $n_line/$sec;
delete $contents{'header'};
delete $contents{'SUM'};

my @file_list = (sort { $contents{$b}{'code'} <=>
$contents{$a}{'code'} } keys %contents );
#die Dumper(\%contents);
# Determine column widths for output
my $file_len = 0;
my $lang_len = 0;
foreach my $file (keys %contents) {
my $flen = length $file;
my $llen = length $contents{$file}{'language'};
$file_len = $file_len > $flen ? $file_len : $flen;
$lang_len = $lang_len > $llen ? $lang_len : $llen;
}
return $file_len, $lang_len, $header, %contents;
} # 1}}}
sub print_format_n { # {{{1
# by file with
# format 1 : Language | files | blank | comment | code
# format 2 : Language | files | blank | comment | code | total
# format 3 : File | Language | blank | comment | code
# format 4 : File | blank | comment | code | total
# format 5 : File | Language | blank | comment | code | total
my ($format, $file_len, $lang_len, $header, %contents) = @_;

my %str_fmt = (
1 => sprintf("%%-%ds %%7s %%7s %%7s %%7s\n", $lang_len),
2 => sprintf("%%-%ds %%7s %%7s %%7s %%7s %%7s\n", $lang_len),
3 => sprintf("%%-%ds %%-%ds %%7s %%7s %%7s\n", $file_len, $lang_len),
4 => sprintf("%%-%ds %%7s %%7s %%7s %%7s\n", $file_len),
5 => sprintf("%%-%ds %%-%ds %%7s %%7s %%7s %%7s\n", $file_len, $lang_len),
);
my %val_fmt = (
1 => sprintf("%%-%ds %%7d %%7d %%7d %%7d\n", $lang_len),
2 => sprintf("%%-%ds %%7d %%7d %%7d %%7d %%7d\n", $lang_len),
3 => sprintf("%%-%ds %%-%ds %%7d %%7d %%7d\n", $file_len, $lang_len),
4 => sprintf("%%-%ds %%7d %%7d %%7d %%7d\n", $file_len),
5 => sprintf("%%-%ds %%-%ds %%7d %%7d %%7d %%7d\n", $file_len, $lang_len),
);
my %language = ();
foreach my $file (keys %contents) {
my $lang = $contents{$file}{'language'};
$language{$lang}{'files'} += 1;
foreach my $category ('blank', 'comment', 'code',) {
$language{$lang}{$category} += $contents{$file}{$category};
$language{$lang}{'total'} += $contents{$file}{$category};
}
}
my @file_list = (sort { $contents{$b}{'code'} <=>
$contents{$a}{'code'} } keys %contents );
my @lang_list = (sort { $language{$b}{'code'} <=>
$language{$a}{'code'} } keys %language );

my %hyphens = (
1 => "-" x ($lang_len + 4*9),
2 => "-" x ($lang_len + 5*9),
3 => "-" x ($lang_len + $file_len + 2 + 3*9),
4 => "-" x ($file_len + 4*9),
5 => "-" x ($lang_len + $file_len + 2 + 4*9),
);
my %col_headings = (
1 => ["Language", "files", "blank", "comment", "code"],
2 => ["Language", "files", "blank", "comment", "code", "Total"],
3 => ["File", "Language", "blank", "comment", "code"],
4 => ["File", "blank", "comment", "code", "Total"],
5 => ["File", "Language", "blank", "comment", "code", "Total"],
);

print "$header\n";
print "$hyphens{$format}\n";
printf $str_fmt{$format}, @{$col_headings{$format}};
print "$hyphens{$format}\n";
my ($n_files, $n_blank, $n_comment, $n_code, $n_total) = (0, 0, 0, 0, 0);
my @out;
if ($format < 3) {
# by language
foreach my $lang (@lang_list) {
my ($nF, $nB, $nCm, $nCo) = ($language{$lang}{'files'},
$language{$lang}{'blank'},
$language{$lang}{'comment'},
$language{$lang}{'code'});
if ($format == 1) {
@out = ($lang, $nF, $nB, $nCm, $nCo);
} else {
@out = ($lang, $nF, $nB, $nCm, $nCo, $nB + $nCm + $nCo);
}
printf $val_fmt{$format}, @out;
$n_files += $nF;
$n_blank += $nB;
$n_comment += $nCm;
$n_code += $nCo;
$n_total += $nB + $nCm + $nCo;
}
} else {
# by file
foreach my $file (@file_list) {
my ($nB, $nCm, $nCo) = ($contents{$file}{'blank'},
$contents{$file}{'comment'},
$contents{$file}{'code'});
my $lang = $contents{$file}{'language'};
if ($format == 1) {
} elsif ($format == 3) {
@out = ($file, $lang, $nB, $nCm, $nCo);
} elsif ($format == 4) {
@out = ($file, $nB, $nCm, $nCo, $nB + $nCm + $nCo);
} else {
@out = ($file, $lang, $nB, $nCm, $nCo, $nB + $nCm + $nCo);
}
printf $val_fmt{$format}, @out;
$n_blank += $nB;
$n_comment += $nCm;
$n_code += $nCo;
$n_total += $nB + $nCm + $nCo;
}
}
print "$hyphens{$format}\n";
if (scalar @file_list > 1) {
if ($format == 1) {
@out = ( "SUM", $n_files, $n_blank, $n_comment, $n_code );
} elsif ($format == 2) {
@out = ( "SUM", $n_files, $n_blank, $n_comment, $n_code, $n_total );
} elsif ($format == 3) {
@out = ( "SUM", " ", $n_blank, $n_comment, $n_code );
} elsif ($format == 4) {
@out = ( "SUM", $n_blank, $n_comment, $n_code, $n_total );
} else {
@out = ( "SUM", " ", $n_blank, $n_comment, $n_code, $n_total );
}
printf $val_fmt{$format}, @out;
print "$hyphens{$format}\n";
}
} # 1}}}
# really_is_pascal, really_is_incpascal, really_is_php from SLOCCount
my %php_files = (); # really_is_php()
sub really_is_pascal { # {{{1
Expand Down

0 comments on commit a5747ef

Please sign in to comment.