App-sdview
view release on metacpan or search on metacpan
lib/App/sdview.pm view on Meta::CPAN
$ sdview README.md
$ sdview man/somelib.3
Various output plugins exist. By default it will output a terminal-formatted
rendering of the document via the F<less> pager, but it can also output
plaintext, Pod, Markdown.
$ sdview Some::Module -o plain > module.txt
$ sdview Some::Module -o Markdown > module.md
=cut
# Permit loaded output modules to override
our $DEFAULT_OUTPUT = "terminal";
use Module::Pluggable
search_path => "App::sdview::Parser",
sub_name => "PARSERS",
inner => 0,
require => 1;
use Module::Pluggable
search_path => "App::sdview::Output",
sub_name => "OUTPUTS",
inner => 0,
require => 1;
# Must call this *before* ->run entersub so that DEFAULT_OUTPUT is overridden properly
my @OUTPUT_CLASSES = OUTPUTS();
method run ( $file,
:$format = undef,
:$output //= $DEFAULT_OUTPUT,
:$highlight = 0,
:$output_options //= [],
%opts
) {
my @PARSER_CLASSES = sort { $a->sort_order <=> $b->sort_order } PARSERS();
if( ( $format // "" ) eq "?" ) {
say "Parser format types:";
$_->can( "format" ) and say " " . $_->format . " (provided by $_)"
for @PARSER_CLASSES;
exit 0;
}
if( ( $output // "" ) eq "?" ) {
say "Output format types:";
$_->can( "format" ) and say " " . $_->format . " (provided by $_)"
for @OUTPUT_CLASSES;
exit 0;
}
if( -f( my $configpath = "$ENV{HOME}/.sdviewrc" ) ) {
App::sdview::Style->load_config( $configpath );
}
my %output_options = map {
map { m/^(.*?)=(.*)$/ ? ( $1 => $2 ) : ( $_ => !!1 ) } split m/,/, $_;
} $output_options->@*;
my $parser_class;
if( defined $format ) {
$parser_class = first { $_->can( "format" ) and $_->format eq $format } @PARSER_CLASSES or
die "Unrecognised format name $format\n";
}
if( !defined $file ) {
die "Require a FILE to read - such as doc.md or doc.pod\n";
}
if( ! -f $file ) {
my $name = $file;
foreach my $class ( $parser_class ? ( $parser_class ) : @PARSER_CLASSES ) {
defined( $file = $class->find_file( $name ) ) and
$parser_class = $class, last;
}
defined $file or
die "Unable to find a file for '$name'\n";
}
$parser_class //= do {
first { $_->can_parse_file( $file ) } @PARSER_CLASSES or
die "Unable to find a handler for $file\n";
};
my $output_class = first { $_->can( "format" ) and $_->format eq $output } @OUTPUT_CLASSES or
die "Unrecognised output name $output\n";
my @paragraphs = $parser_class->new->parse_file( $file );
if( $highlight ) {
apply_highlights( $_ ) for @paragraphs;
}
# TODO: unrecognised output option key names will not look very neat here
$output_class->new( %output_options )->output( @paragraphs );
}
sub apply_highlights ( $para )
{
if( $para->type eq "verbatim" and defined( my $language = $para->language ) ) {
App::sdview::Highlighter->highlight_str( $para->text, $language );
}
if( $para->type =~ m/^list-/ ) {
apply_highlights( $_ ) for $para->items;
}
}
=head1 TODO
=over 4
=item *
( run in 1.509 second using v1.01-cache-2.11-cpan-39bf76dae61 )