App-sdview

 view release on metacpan or  search on metacpan

lib/App/sdview/Parser/Man.pm  view on Meta::CPAN


package App::sdview::Parser::Man 0.20;
class App::sdview::Parser::Man :strict(params);

apply App::sdview::Parser;

use Sublike::Extended 0.29 'sub';

use Parse::Man::DOM 0.03;

use String::Tagged;

use constant sort_order => 30;

sub find_file ( $class, $name )
{
   open my $f, "-|", "man", "--path", $name;
   my $file = <$f>; chomp $file if defined $file;
   close $f;
   $? == 0 or return undef;
   return $file;
}

sub can_parse_file ( $class, $file )
{
   return $file =~ m/\.[0-9](pm)?(\.gz)?/n;
}

field @_paragraphs;

method parse_file ( $fh )
{
   return $self->_parse( Parse::Man::DOM->new->from_file( $fh ) );
}

method parse_string ( $str )
{
   return $self->_parse( Parse::Man::DOM->new->from_string( $str ) );
}

method _parse ( $dom )
{
   # Not much we can do with the meta sections

   @_paragraphs = ();

   foreach my $para ( $dom->paras ) {
      my $type = $para->type;
      if( my $code = $self->can( "_handle_$type" ) ) {
         $self->$code( $para );
      }
      else {
         print STDERR "TODO: para->type = $type\n";
      }
   }

   return @_paragraphs;
}

my %FONTTAGS = (
   B  => { bold => 1 },
   I  => { italic => 1 },
   CW => { monospace => 1 },
);

sub _chunklist_to_taggedstring ( $chunks, :$linefeed = " " )
{
   my $ret = String::Tagged->new;

   foreach my $chunk ( $chunks->@* ) {
      my %tags;

      my $font = $chunk->font // "";
      %tags = $FONTTAGS{$font}->%* if $FONTTAGS{$font};

      my $text = $chunk->text;
      $text = "\n"      if $chunk->is_space;
      $text = $linefeed if $chunk->is_linebreak;
      $text = "\n\n"    if $chunk->is_break;

      $ret->append_tagged( $text, %tags );
   }

   # Trim trailing space
   $ret =~ m/([ \n]+)$/ and
      $ret->set_substr( $-[1], $+[1]-$-[1], "" );

   return $ret;
}

method _handle_heading ( $para )
{
   push @_paragraphs, App::sdview::Para::Heading->new(
      level => $para->level, 
      text => String::Tagged->new( $para->text ),
   );
}

method _handle_plain ( $para )
{
   push @_paragraphs, App::sdview::Para::Plain->new(
      text => _chunklist_to_taggedstring( [ $para->body->chunks ] ),
      indent => $para->indent,
   );
}

method _handle_term ( $para )
{
   my $list;
   if( @_paragraphs and $_paragraphs[-1]->type eq "list-text" ) {
      $list = $_paragraphs[-1];
   }
   else {
      push @_paragraphs, $list = App::sdview::Para::List->new(
         listtype => "text",
         indent   => 4,
      );
   }

   $list->push_item(
      App::sdview::Para::ListItem->new(



( run in 0.539 second using v1.01-cache-2.11-cpan-39bf76dae61 )