Acme-CPANModulesUtil-FeatureMatrix
view release on metacpan or search on metacpan
lib/Acme/CPANModulesUtil/FeatureMatrix.pm view on Meta::CPAN
sub draw_feature_matrix {
require Data::Sah::Resolve;
require Data::Sah::Util::Type;
require Markdown::To::POD;
require Text::Table::Any;
my %args = @_;
my $list;
my $mod;
if ($args{_list}) {
$list = $args{_list};
} else {
$mod = $args{cpanmodule} or return [400, "Please specify cpanmodule"];
$mod = "Acme::CPANModules::$mod" unless $mod =~ /\AAcme::CPANModules::/;
(my $mod_pm = "$mod.pm") =~ s!::!/!g;
require $mod_pm;
$list = ${"$mod\::LIST"};
}
# collect all features mentioned
my @features;
for my $e (@{ $list->{entries} }) {
next unless $e->{features};
for my $fname (sort keys %{$e->{features}}) {
push @features, $fname unless grep {$_ eq $fname} @features;
}
}
return [412, "No features mentioned in " . ($mod // "list")]
unless @features;
# generate table and collect notes
my @notes;
my %note_nums; # text => num
my $note_num = 0;
my @rows;
HEADER_ROW:
{
my @header_row = ("module");
for my $fname (@features) {
my $has_note;
if ($list->{entry_features} && $list->{entry_features}{$fname} &&
$list->{entry_features}{$fname}{summary}) {
$has_note++;
$note_num++;
my $note = "=item $note_num. $fname: " . $list->{entry_features}{$fname}{summary} . "\n\n";
if ($list->{entry_features}{$fname}{description}) {
$note .= Markdown::To::POD::markdown_to_pod($list->{entry_features}{$fname}{description}) . "\n\n";
}
push @notes, $note;
}
push @header_row, "$fname" . ($has_note ? " *$note_num)" : "");
}
push @rows, \@header_row;
}
DATA_ROW:
{
for my $e (@{ $list->{entries} }) {
my @row = ($e->{module});
for my $fname (@features) {
my $rres = Data::Sah::Resolve::resolve_schema(
$list->{entry_features}{$fname}{schema} // 'bool'
);
my $ftype = $rres->{type};
my $fvalue0;
my $fvalue;
if (!$e->{features} || !defined($e->{features}{$fname})) {
$fvalue = "N/A";
} else {
$fvalue0 = $e->{features}{$fname};
$fvalue = ref $fvalue0 eq 'HASH' ? $fvalue0->{value} : $fvalue0;
$fvalue = !defined($fvalue) ? "N/A" :
$ftype eq 'bool' ? ($fvalue ? "yes" : "no") : $fvalue;
}
my $has_note;
my $this_note_num;
if (ref $fvalue0 eq 'HASH' && $fvalue0->{summary}) {
$has_note++;
my $note_text = $fvalue0->{summary};
if ($fvalue0->{description}) {
$note_text .= Markdown::To::POD::markdown_to_pod($fvalue0->{description}) . "\n\n";
}
if ($this_note_num = $note_nums{$note_text}) {
# reuse the same text from another note
} else {
$note_num++;
push @notes, "=item $note_num. $note_text\n\n";
$note_nums{$note_text} = $this_note_num = $note_num;
}
}
push @row, $fvalue . ($has_note ? " *$this_note_num)" : "");
}
push @rows, \@row;
}
}
my $res = Text::Table::Any::table(
rows => \@rows,
header_row => 1,
); $res =~ s/^/ /gm;
if (@notes) {
$res .= join(
"",
"\n\nNotes:\n\n=over\n\n", @notes, "=back\n\n",
);
}
[200, "OK", $res];
}
1;
( run in 1.064 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )