Skip to content

Commit ef9abfe

Browse files
committed
support multiple output formats, #884
1 parent 71cdcba commit ef9abfe

File tree

6 files changed

+305
-143
lines changed

6 files changed

+305
-143
lines changed

Unix/cloc

+141-66
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ my (
273273
$opt_only_count_files ,
274274
$opt_fmt ,
275275
$opt_encoding ,
276+
$opt_txt , # not associated with a command line option
276277
);
277278

278279
my $getopt_success = GetOptions( # {{{1
@@ -382,6 +383,7 @@ my $getopt_success = GetOptions( # {{{1
382383
"fmt=i" => \$opt_fmt ,
383384
"encoding=s" => \$opt_encoding , # not production ready #880
384385
);
386+
$opt_txt = 0;
385387
# 1}}}
386388
$config_file = $opt_config_file if defined $opt_config_file;
387389
load_from_config_file($config_file, # {{{2
@@ -657,6 +659,33 @@ if ($opt_by_percent and $opt_by_percent !~ m/^(c|cm|cb|cmb)$/i) {
657659
}
658660
$opt_by_percent = lc $opt_by_percent;
659661

662+
$opt_txt = 1 if $opt_report_file;
663+
my $N_OUTPUT_FORMATS = 0;
664+
my %OUTFILE_EXT = (
665+
"txt" => $opt_txt ,
666+
"csv" => $opt_csv ,
667+
"xml" => 0 ,
668+
"yaml" => 0 ,
669+
"json" => 0 ,
670+
"md" => 0 ,
671+
);
672+
$OUTFILE_EXT{"xml" } = 1 if defined($opt_xml );
673+
$OUTFILE_EXT{"yaml"} = 1 if defined($opt_yaml);
674+
$OUTFILE_EXT{"json"} = 1 if defined($opt_json);
675+
$OUTFILE_EXT{"md" } = 1 if defined($opt_md );
676+
foreach my $out_style (sort keys %OUTFILE_EXT) {
677+
++$N_OUTPUT_FORMATS if $OUTFILE_EXT{$out_style};
678+
}
679+
if ($N_OUTPUT_FORMATS >= 2 and $OUTFILE_EXT{"txt"}) {
680+
--$N_OUTPUT_FORMATS;
681+
$OUTFILE_EXT{"txt"} = 0;
682+
}
683+
if (!$N_OUTPUT_FORMATS) {
684+
$N_OUTPUT_FORMATS = 1;
685+
$OUTFILE_EXT{"txt"} = 1;
686+
$opt_txt = 1;
687+
}
688+
660689
if (defined $opt_vcs) {
661690
if ($opt_vcs eq "auto") {
662691
if (is_dir(".git")) {
@@ -1057,7 +1086,8 @@ if ($opt_sum_reports) {
10571086
my $end_time = get_time();
10581087
my @results = generate_report($VERSION, $end_time - $start_time,
10591088
$type,
1060-
\%{$Results{ $type }}, \%Scale_Factor);
1089+
\%{$Results{ $type }}, \%Scale_Factor,
1090+
"txt");
10611091
if ($opt_report_file) {
10621092
my $ext = ".lang";
10631093
$ext = ".file" unless $type eq "by language";
@@ -1249,7 +1279,6 @@ my @Errors = ();
12491279
my @file_list = (); # global variable updated in files()
12501280
my %Ignored = (); # files that are not counted (language not recognized or
12511281
# problems reading the file)
1252-
my @Lines_Out = ();
12531282
my %upper_lower_map = (); # global variable (needed only on Windows) to
12541283
# track case of original filename, populated in
12551284
# make_file_list() if $ON_WINDOWS
@@ -1546,14 +1575,20 @@ generate_diff_sql($end_time - $start_time, \%Delta_by_File) if $opt_sql;
15461575

15471576
exit if $skip_generate_report;
15481577

1549-
if ($opt_by_file) {
1550-
@Lines_Out = diff_report($VERSION, get_time() - $start_time,
1551-
"by file",
1552-
\%Delta_by_File, \%Scale_Factor, \%Renamed);
1553-
} else {
1554-
@Lines_Out = diff_report($VERSION, get_time() - $start_time,
1555-
"by language",
1556-
\%Delta_by_Language, \%Scale_Factor, undef);
1578+
foreach my $out_style (sort keys %OUTFILE_EXT) {
1579+
next unless $OUTFILE_EXT{$out_style};
1580+
my @Lines_Out = ();
1581+
if ($opt_by_file) {
1582+
@Lines_Out = diff_report($VERSION, $end_time - $start_time,
1583+
"by file",
1584+
\%Delta_by_File, \%Scale_Factor, \%Renamed);
1585+
} else {
1586+
@Lines_Out = diff_report($VERSION, $end_time - $start_time,
1587+
"by language",
1588+
\%Delta_by_Language, \%Scale_Factor, undef);
1589+
}
1590+
my $outfile = $opt_report_file;
1591+
produce_output(\@Lines_Out, $opt_report_file, $out_style);
15571592
}
15581593

15591594
# 1}}}
@@ -1717,49 +1752,88 @@ if (!%Results_by_Language) {
17171752

17181753
generate_sql($end_time - $start_time,
17191754
\%Results_by_File, \%Scale_Factor) if $opt_sql;
1720-
17211755
exit if $skip_generate_report;
1722-
if ($opt_by_file_by_lang) {
1723-
push @Lines_Out, generate_report( $VERSION, $end_time - $start_time,
1724-
"by file",
1725-
\%Results_by_File, \%Scale_Factor);
1726-
push @Lines_Out, generate_report( $VERSION, $end_time - $start_time,
1727-
"by language",
1728-
\%Results_by_Language, \%Scale_Factor);
1729-
} elsif ($opt_by_file) {
1730-
push @Lines_Out, generate_report( $VERSION, $end_time - $start_time,
1731-
"by file",
1732-
\%Results_by_File, \%Scale_Factor);
1733-
} else {
1734-
push @Lines_Out, generate_report( $VERSION, $end_time - $start_time,
1735-
"by language",
1736-
\%Results_by_Language, \%Scale_Factor);
1737-
}
1738-
# 1}}}
1739-
}
1740-
if ($opt_fmt) {
1741-
my $json_string = "";
1742-
write_file(\$json_string, {}, @Lines_Out);
1743-
my ($file_len, $lang_len, $header, %contents) = load_json($json_string);
1744-
@Lines_Out = print_format_n(abs($opt_fmt), $file_len, $lang_len, $header, %contents);
1745-
}
1746-
if ($opt_report_file) {
1747-
write_file($opt_report_file, {}, @Lines_Out);
1748-
} else {
1749-
if ($opt_fmt) {
1750-
print "@Lines_Out";
1756+
1757+
foreach my $out_style (sort keys %OUTFILE_EXT) {
1758+
next unless $OUTFILE_EXT{$out_style};
1759+
my @Lines_Out = ();
1760+
1761+
if ($opt_by_file_by_lang) {
1762+
push @Lines_Out, generate_report( $VERSION, $end_time - $start_time,
1763+
"by file",
1764+
\%Results_by_File, \%Scale_Factor,
1765+
$out_style);
1766+
push @Lines_Out, generate_report( $VERSION, $end_time - $start_time,
1767+
"by language",
1768+
\%Results_by_Language, \%Scale_Factor,
1769+
$out_style);
1770+
} elsif ($opt_by_file) {
1771+
push @Lines_Out, generate_report( $VERSION, $end_time - $start_time,
1772+
"by file",
1773+
\%Results_by_File, \%Scale_Factor,
1774+
$out_style);
17511775
} else {
1752-
print "\n" unless $opt_quiet;
1753-
print join("\n", @Lines_Out), "\n";
1776+
push @Lines_Out, generate_report( $VERSION, $end_time - $start_time,
1777+
"by language",
1778+
\%Results_by_Language, \%Scale_Factor,
1779+
$out_style);
17541780
}
1781+
produce_output(\@Lines_Out, $opt_report_file, $out_style);
17551782
}
1783+
# 1}}}
1784+
}
1785+
1786+
#if ($opt_fmt) {
1787+
# my $json_string = "";
1788+
# write_file(\$json_string, {}, @Lines_Out);
1789+
# my ($file_len, $lang_len, $header, %contents) = load_json($json_string);
1790+
# @Lines_Out = print_format_n(abs($opt_fmt), $file_len, $lang_len, $header, %contents);
1791+
#}
1792+
#if ($opt_report_file) {
1793+
# write_file($opt_report_file, {}, @Lines_Out);
1794+
#} else {
1795+
# if ($opt_fmt) {
1796+
# print "@Lines_Out";
1797+
# } else {
1798+
# print "\n" unless $opt_quiet;
1799+
# print join("\n", @Lines_Out), "\n";
1800+
# }
1801+
#}
1802+
17561803
if ($opt_count_diff) {
17571804
++$opt_count_diff;
17581805
exit if $opt_count_diff > 3;
17591806
goto Top_of_Processing_Loop;
17601807
}
1808+
17611809
suggest_remedies_for_errors(\@Errors) if @Errors;
1762-
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1810+
# - - - - - - - - - - - - - - - end of main - - - - - - - - - - - - - - - #
1811+
sub produce_output { # {{{1
1812+
my ($ra_Lines_Out, $outfile, $out_style) = @_;
1813+
if ($opt_fmt) {
1814+
my $json_string = "";
1815+
write_file(\$json_string, {}, @{$ra_Lines_Out});
1816+
my ($file_len, $lang_len, $header, %contents) = load_json($json_string);
1817+
@{$ra_Lines_Out} = print_format_n(abs($opt_fmt), $file_len, $lang_len, $header, %contents);
1818+
}
1819+
if ($outfile) {
1820+
my $adjusted_outfile = $outfile;
1821+
if ($N_OUTPUT_FORMATS > 1 and
1822+
($opt_report_file !~ /\.${out_style}$/)) {
1823+
# ensure the output filename has a suitable extension
1824+
$adjusted_outfile .= "." . $out_style;
1825+
}
1826+
write_file($adjusted_outfile, {}, @{$ra_Lines_Out});
1827+
} else {
1828+
if ($opt_fmt) {
1829+
print "@{$ra_Lines_Out}";
1830+
} else {
1831+
print "\n" unless $opt_quiet;
1832+
print join("\n", @{$ra_Lines_Out}), "\n";
1833+
}
1834+
}
1835+
}
1836+
# 1}}}
17631837
sub suggest_remedies_for_errors { # {{{1
17641838
my ($raa_errors) = @_; # [ [ numeric error code, filename], .. ]
17651839
my $hit_timeout = 0;
@@ -4503,6 +4577,7 @@ sub generate_report { # {{{1
45034577
# where TYPE = name of language, source file,
45044578
# or report file
45054579
$rh_scale , # in
4580+
$out_style , # in "txt" | "xml" | "yaml" | "json" | "csv" | "md"
45064581
) = @_;
45074582

45084583
my %orig_case = ();
@@ -4519,7 +4594,7 @@ sub generate_report { # {{{1
45194594
print "-> generate_report\n" if $opt_v > 2;
45204595
my $DELIM = ",";
45214596
$DELIM = $opt_csv_delimiter if defined $opt_csv_delimiter;
4522-
$DELIM = "|" if defined $opt_md;
4597+
$DELIM = "|" if $out_style eq "md";
45234598

45244599
my @results = ();
45254600

@@ -4575,10 +4650,10 @@ sub generate_report { # {{{1
45754650
},
45764651
);
45774652
my $Style = "txt";
4578-
$Style = "xml" if $opt_xml ;
4579-
$Style = "xml" if $opt_yaml; # not a typo; just set to anything but txt
4580-
$Style = "xml" if $opt_json; # not a typo; just set to anything but txt
4581-
$Style = "xml" if $opt_csv ; # not a typo; just set to anything but txt
4653+
$Style = "xml" if $out_style eq "xml" ;
4654+
$Style = "xml" if $out_style eq "yaml"; # not a typo; just set to anything but txt
4655+
$Style = "xml" if $out_style eq "json"; # not a typo; just set to anything but txt
4656+
$Style = "xml" if $out_style eq "csv" ; # not a typo; just set to anything but txt
45824657

45834658
my $hyphen_line = sprintf "%s", '-' x (79 + $column_1_offset);
45844659
$hyphen_line = sprintf "%s", '-' x (68 + $column_1_offset)
@@ -4604,9 +4679,9 @@ sub generate_report { # {{{1
46044679
$elapsed_sec ,
46054680
$sum_files/$elapsed_sec,
46064681
$sum_lines/$elapsed_sec) unless $opt_sum_reports or $opt_hide_rate;
4607-
if ($opt_xml or $opt_yaml or $opt_json) {
4682+
if ($out_style eq "xml" or $out_style eq "yaml" or $out_style eq "json") {
46084683
if (!$ALREADY_SHOWED_HEADER) {
4609-
if ($opt_by_file_by_lang and $opt_json) {
4684+
if ($opt_by_file_by_lang and $out_style eq "json") {
46104685
push @results, '{ "by_file" : ';
46114686
}
46124687
push @results, xml_yaml_or_json_header($URL, $version, $elapsed_sec,
@@ -4615,15 +4690,15 @@ sub generate_report { # {{{1
46154690
# --sum-reports yields two xml or yaml files, one by
46164691
# language and one by report file, each of which needs a header
46174692
}
4618-
if ($opt_xml) {
4693+
if ($out_style eq "xml") {
46194694
if ($BY_FILE or ($report_type eq "by report file")) {
46204695
push @results, "<files>";
46214696
} else {
46224697
push @results, "<languages>";
46234698
}
46244699
}
46254700
} else {
4626-
$header_line =~ s/,// if $opt_csv;
4701+
$header_line =~ s/,// if $out_style eq "csv";
46274702
push @results, output_header($header_line, $hyphen_line, $BY_FILE);
46284703
}
46294704

@@ -4650,7 +4725,7 @@ sub generate_report { # {{{1
46504725
"scale" ,
46514726
"3rd gen. equiv"
46524727
if $opt_3;
4653-
if ($opt_md) {
4728+
if ($out_style eq "md") {
46544729
my @col_header = ();
46554730
if ($data_line =~ m{\s%}) {
46564731
$data_line =~ s{\s%}{_%}g;
@@ -4671,7 +4746,7 @@ sub generate_report { # {{{1
46714746
}
46724747
}
46734748

4674-
if ($opt_csv) {
4749+
if ($out_style eq "csv") {
46754750
my $header2;
46764751
if ($BY_FILE) {
46774752
$header2 = "language${DELIM}filename";
@@ -4727,7 +4802,7 @@ sub generate_report { # {{{1
47274802

47284803
if ($BY_FILE) {
47294804
my $clean_filename = rm_leading_tempdir($lang_or_file, \%TEMP_DIR);
4730-
$clean_filename = xml_metachars($clean_filename) if $opt_xml;
4805+
$clean_filename = xml_metachars($clean_filename) if $out_style eq "xml";
47314806
$data_line = sprintf $Format{'1'}{$Style}, $clean_filename;
47324807
} else {
47334808
$data_line = sprintf $Format{'2'}{$Style}, $lang_or_file;
@@ -4754,7 +4829,7 @@ sub generate_report { # {{{1
47544829
$scaled if $opt_3;
47554830
$sum_scaled += $scaled if $opt_3;
47564831

4757-
if ($opt_xml) {
4832+
if ($out_style eq "xml") {
47584833
if (defined $rhh_count->{$lang_or_file}{'lang'}) {
47594834
my $lang = $rhh_count->{$lang_or_file}{'lang'};
47604835
if (!defined $languages->{$lang}) {
@@ -4767,9 +4842,9 @@ sub generate_report { # {{{1
47674842
} else {
47684843
push @results, " <language " . $data_line . "/>";
47694844
}
4770-
} elsif ($opt_yaml or $opt_json) {
4845+
} elsif ($out_style eq "yaml" or $out_style eq "json") {
47714846
my ($Q, $open_B, $close_B, $start, $C) = yaml_to_json_separators();
4772-
if ($opt_yaml) {
4847+
if ($out_style eq "yaml") {
47734848
# YAML: force quoted language or filename in case these
47744849
# have embedded funny characters, issue #312
47754850
push @results,"'" . rm_leading_tempdir($lang_or_file, \%TEMP_DIR). "' :$open_B";
@@ -4799,16 +4874,16 @@ sub generate_report { # {{{1
47994874
push @results, " ${Q}scaled${Q}: " . $scaled . $C;
48004875
push @results, " ${Q}factor${Q}: " . $factor . $C;
48014876
}
4802-
if ($opt_json) { # replace the trailing comma with }, on the last line
4877+
if ($out_style eq "json") { # replace the trailing comma with }, on the last line
48034878
$results[-1] =~ s/,\s*$/},/;
48044879
}
4805-
} elsif ($opt_csv or $opt_md) {
4880+
} elsif ($out_style eq "csv" or $out_style eq "md") {
48064881
my $extra_3 = "";
48074882
$extra_3 = "${DELIM}$factor${DELIM}$scaled" if $opt_3;
48084883
my $first_column = undef;
48094884
my $clean_name = $lang_or_file;
48104885
my $str;
4811-
if ($opt_csv) {
4886+
if ($out_style eq "csv") {
48124887
if ($BY_FILE) {
48134888
$first_column = $rhh_count->{$lang_or_file}{'lang'};
48144889
$clean_name = rm_leading_tempdir($lang_or_file, \%TEMP_DIR);
@@ -4853,7 +4928,7 @@ sub generate_report { # {{{1
48534928
$avg_scale = sprintf("%.2f", $sum_scaled / $sum_code)
48544929
if $sum_code and $opt_3;
48554930

4856-
if ($opt_xml) {
4931+
if ($out_style eq "xml") {
48574932
$data_line = "";
48584933
if (!$BY_FILE) {
48594934
$data_line .= sprintf "sum_files=\"%d\" ", $sum_files;
@@ -4890,7 +4965,7 @@ sub generate_report { # {{{1
48904965
} else {
48914966
$ALREADY_SHOWED_XML_SECTION = 1;
48924967
}
4893-
} elsif ($opt_yaml or $opt_json) {
4968+
} elsif ($out_style eq "yaml" or $out_style eq "json") {
48944969
my ($Q, $open_B, $close_B, $start, $C) = yaml_to_json_separators();
48954970
push @results, "${Q}SUM${Q}: ${open_B}";
48964971
if ($opt_by_percent) {
@@ -4909,7 +4984,7 @@ sub generate_report { # {{{1
49094984
push @results, " ${Q}scaled${Q}: " . $sum_scaled . $C;
49104985
push @results, " ${Q}factor${Q}: " . $avg_scale . $C;
49114986
}
4912-
if ($opt_json) {
4987+
if ($out_style eq "json") {
49134988
$results[-1] =~ s/,\s*$/} }/;
49144989
if ($opt_by_file_by_lang) {
49154990
if ($ALREADY_SHOWED_HEADER) {
@@ -4919,7 +4994,7 @@ sub generate_report { # {{{1
49194994
}
49204995
}
49214996
}
4922-
} elsif ($opt_csv) {
4997+
} elsif ($out_style eq "csv") {
49234998
my @entries = ();
49244999
if ($opt_by_file) {
49255000
push @entries, "SUM";
@@ -4968,7 +5043,7 @@ sub generate_report { # {{{1
49685043
$data_line .= sprintf $Format{'6'}{$Style},
49695044
$avg_scale ,
49705045
$sum_scaled if $opt_3;
4971-
if ($opt_md) {
5046+
if ($out_style eq "md") {
49725047
my @words = split(' ', $data_line);
49735048
my $n_cols = scalar(@words);
49745049
# my $n_cols = scalar(split(' ', $data_line)); # deprecated

0 commit comments

Comments
 (0)