Here's a quick take on a Pod::Tests, I threw it together as part of my =also
prototype code (I hacked it in to a copy of Pod::Select, named "Pod::AlsoSelect")
since that's what Pod::Text relies on).  The =also stuff seems to work.

- Barrie

-------------8<------------8<-------------8<------------
package Pod::Tests ;

=head1 NAME

Pod::Tests - Extract test suites from POD.

=head1 SYNOPSIS

   use Pod::Tests ;

   my $p = Pod::Tests->new() ;
   $p->parse_from_file( 'podfile', 'test_directory' ) ;

Note that the destination must be a directory, and that it is not
optional.

=head1 DESCRIPTION

This module uses Pod::AlsoSelect and looks for sections marked

   =for test foo.t

and (due to Pod::AlsoSelect's devious machinations)

   =also_for test foo.t

and ignores normal text.

It does not use any functionality of Pod::Select, just what's inherited from
Pod::Parser, so in a real implementation, it would not inherit from
Pod::Select.

=cut

use strict ;
use vars qw( @ISA ) ;

use Carp ;
use File::Spec ;
use Pod::AlsoSelect ;
use Symbol ;

@ISA = qw( Pod::AlsoSelect ) ;


sub parse_from_file {
    my $self = shift;
    my ( $file_name, $dest_dir ) = @_ ;
    $self->{DEST_DIR} = $dest_dir ;
    croak "No destination directory supplied"
       unless defined $dest_dir && length $dest_dir ;
    $self->parse_from_file( $file_name ) ;
}


## Lifted from Pod::Text.  Should really go in Pod::StdParser some day.
sub command {
    my $self = shift;
    my $command = shift;
    return if $command eq 'pod';
    return if ($$self{EXCLUDE} && $command ne 'end');
    $self->item ("\n") if defined $$self{ITEM};
    $command = 'cmd_' . $command;
    $self->$command (@_) if $self->can( $command ) ;
}


sub open_test_file {
   my $self = shift ;
   my ( $fn ) = @_ ;

   # $fn eq '' means to restore normal operation
   my $ton = length $fn ? File::Spec->catfile( $self->{DEST_DIR}, $fn ) : '' ;
   if ( $self->{SAVED_HANDLE} ) {
      return if $ton eq $self->{TEST_OUT_NAME} ;
      $self->close_test_file ;
   }
   $self->{TEST_OUT_NAME} = $ton ;
   return unless length $ton ;

   $self->{SAVED_HANDLE} = $self->output_handle ;

   ## Break encapsulation here, since I see no other way defined by Pod::Parser
   $self->{_OUTPUT} = gensym ;
   open( $self->output_handle, ">$ton" ) or croak "$! opening '$ton'" ;
}


sub close_test_file {
   my $self = shift;
   close( $self->output_handle ) or croak "$! closing '$self->{TEST_OUT_NAME}'";
   $self->{_OUTPUT} = $self->{SAVED_HANDLE} ;
   $self->{SAVED_HANDLE} = undef ;
   $self->{TEST_OUT_NAME} = undef ;
}


sub output {
   my $self = shift ;
   my $fh = $self->output_handle ;
   print $fh $_[1] ;
}

# Throw away all normal text, print all others
sub verbatim  {
   my $self = shift ;
   $self->output( shift ) if $self->{TEST_OUTPUT} ;
}

*textblock = *textblock = \&verbatim ;

sub cmd_for {
   my $self = shift ;
   my ( $text, $line ) = @_ ;
   return unless $text =~ s/\Atest\s+(\S*).*\n//m ;
   local $self->{TEST_OUTPUT} = 1 ;
   $self->open_test_file( $1 ) ;
   $self->textblock( $text, $line ) ;
}

sub cmd_begin {
   my $self = shift ;
   my ( $text, $line ) = @_ ;

   $self->{TEST_OUTPUT} = ( $text =~ /\Atest\s+(\S*)/ ) ;
   $self->open_test_file( $1 ) ;
}

sub cmd_end {
   my $self = shift ;
   my ( $text, $line ) = @_ ;
   $self->{TEST_OUTPUT} = ! ( $text =~ s/\Atest// ) ;
   $self->close_test_file() ;
}

Reply via email to