IO-Pager-0.35/0000755000175000017500000000000012641653472013016 5ustar belg4mitbelg4mitIO-Pager-0.35/Makefile.PL0000644000175000017500000000200212021541465014750 0ustar belg4mitbelg4mituse ExtUtils::MakeMaker; # See lib/ExtUtils/MakeMaker.pm for details of how to influence # the contents of the Makefile that is written. WriteMakefile( 'NAME' => 'IO::Pager', 'VERSION_FROM' => 'lib/IO/Pager.pm', # finds $VERSION 'BUILD_REQUIRES' => { 'Test::More' => 0, 'Config' => 0, 'Env' => 0, 'Exporter' => 0, 'File::Temp' => 0, }, 'PREREQ_PM' => { 'base' => 0, 'Env' => 0, 'File::Spec' => 0, 'File::Which' => 0, 'IO::Handle' => 0, 'PerlIO' => 0, 'SelectSaver' => 0, 'Symbol' => 0, 'Tie::Handle' => 0, }, ($] >= 5.005 ? # Add these new keywords supported since 5.005 ( ABSTRACT_FROM => 'lib/IO/Pager.pm', # retrieve abstract from module AUTHOR => 'Jerrad Pierce , Florent Angly ', ) : ()), ); IO-Pager-0.35/lib/0000755000175000017500000000000012641653472013564 5ustar belg4mitbelg4mitIO-Pager-0.35/lib/IO/0000755000175000017500000000000012641653472014073 5ustar belg4mitbelg4mitIO-Pager-0.35/lib/IO/Pager.pm0000644000175000017500000003147312641652361015473 0ustar belg4mitbelg4mitpackage IO::Pager; our $VERSION = 0.35; #Really 0.34 use 5.008; #At least, for decent perlio, and other modernisms use strict; use base qw( Tie::Handle ); use Env qw( PAGER ); use File::Spec; use PerlIO; use Symbol; use overload '+' => "PID", bool=> "PID"; our $SIGPIPE; sub find_pager { # Return the name (or path) of a pager that IO::Pager can use my $io_pager; # Use File::Which if available (strongly recommended) my $which = eval { require File::Which }; # Look for pager in PAGER first if ($PAGER) { # Strip arguments e.g. 'less --quiet' my ($pager, @options) = (split ' ', $PAGER); $pager = _check_pagers([$pager], $which); $io_pager = join ' ', ($pager, @options) if defined $pager; } # Then search pager amongst usual suspects if (not defined $io_pager) { my @pagers = ('/etc/alternatives/pager', '/usr/local/bin/less', '/usr/bin/less', '/usr/bin/more'); $io_pager = _check_pagers(\@pagers, $which) } # Then check PATH for other pagers if ( (not defined $io_pager) && $which ) { my @pagers = ('less', 'most', 'w3m', 'lv', 'pg', 'more'); $io_pager = _check_pagers(\@pagers, $which ); } # If all else fails, default to more $io_pager ||= 'more'; return $io_pager; } sub _check_pagers { my ($pagers, $which) = @_; # Return the first pager in the list that is usable. For each given pager, # given a pager name, try to finds its full path with File::Which if possible. # Given a pager path, verify that it exists. my $io_pager = undef; for my $pager (@$pagers) { # Get full path my $loc; if ( $which && (not File::Spec->file_name_is_absolute($pager)) ) { $loc = File::Which::which($pager); } else { $loc = $pager; } # Test that full path is valid (some platforms don't do -x so we use -e) if ( defined($loc) && (-e $loc) ) { $io_pager = $loc; last; } } return $io_pager; } #Should have this as first block for clarity, but not with its use of a sub :-/ BEGIN { # Set the $ENV{PAGER} to something reasonable $PAGER = find_pager(); } #Factory sub open(*;$@) { # FH, [MODE], [CLASS] my $args = {procedural=>1}; $args->{mode} = splice(@_, 1, 1) if scalar(@_) == 3; $args->{subclass} = pop if scalar(@_) == 2; &new(undef, @_, $args); } #Alternate entrance: drop class but leave FH, subclass sub new(*;$@) { # FH, [MODE], [CLASS] shift; my %args; if( ref($_[-1]) eq 'HASH' ){ %args = %{pop()}; warn "REMAINDER? (@_)", scalar @_; push(@_, $args{procedural}); } else{ $args{mode} = splice(@_, 1, 1) if $_[1] =~ /^:/; $args{subclass} = pop if exists($_[1]); } #Leave filehandle in @_ for pass by reference to allow gensym $args{subclass} ||= 'IO::Pager::Unbuffered'; $args{subclass} =~ s/^(?!IO::Pager::)/IO::Pager::/; eval "require $args{subclass}" or die "Could not load $args{subclass}: $@\n"; my $token = $args{subclass}->new(@_); if( defined($args{mode}) ){ $args{mode} =~ s/^\|-//; $token->BINMODE($args{mode}); } return $token; } sub _init{ # CLASS, [FH] ## Note reversal of order due to CLASS from new() #Assign by reference if empty scalar given as filehandle $_[1] = gensym() if !defined($_[1]); no strict 'refs'; $_[1] ||= *{select()}; # Are we on a TTY? STDOUT & STDERR are separately bound if ( defined( my $FHn = fileno($_[1]) ) ) { if ( $FHn == fileno(STDOUT) ) { die '!TTY' unless -t $_[1]; } if ( $FHn == fileno(STDERR) ) { die '!TTY' unless -t $_[1]; } } #XXX This allows us to have multiple pseudo-STDOUT #return 0 unless -t STDOUT; return ($_[0], $_[1]); } # Methods required for implementing a tied filehandle class sub TIEHANDLE { my ($class, $tied_fh) = @_; unless ( $PAGER ){ die "The PAGER environment variable is not defined, you may need to set it manually."; } my($real_fh, $child); if ( $child = CORE::open($real_fh, '|-', $PAGER) ){ my @oLayers = PerlIO::get_layers($tied_fh, details=>1, output=>1); my $layers = ''; for(my $i=0;$i<$#oLayers;$i+=3){ #An extra base layer requires more keystrokes to exit next if $oLayers[$i] =~ /unix|stdio/ && !defined($oLayers[+1]); $layers .= ":$oLayers[$i]"; $layers .= '(' . ($oLayers[$i+1]) . ')' if defined($oLayers[$i+1]); } CORE::binmode($real_fh, $layers); } else{ die "Could not pipe to PAGER ('$PAGER'): $!\n"; } return bless { 'real_fh' => $real_fh, 'child' => $child, 'pager' => $PAGER, }, $class; } sub BINMODE { my ($self, $layer) = @_; CORE::binmode($self->{real_fh}, $layer||':raw'); } sub WNOHANG(); sub EOF { my $self = shift; unless( defined($SIGPIPE) ){ eval 'use POSIX ":sys_wait_h";'; $SIGPIPE = 0; } $SIG{PIPE} = sub { $SIGPIPE = 1 unless $ENV{IP_EOF}; CORE::close($self->{real_fh}); waitpid($self->{child}, WNOHANG); CORE::open($self->{real_fh}, '>&1'); }; return $SIGPIPE; } sub PRINT { my ($self, @args) = @_; CORE::print {$self->{real_fh}} @args or die "Could not print to PAGER: $!\n"; } sub PRINTF { my ($self, $format, @args) = @_; $self->PRINT(sprintf($format, @args)); } sub say { my ($self, @args) = @_; $args[-1] .= "\n"; $self->PRINT(@args); } sub WRITE { my ($self, $scalar, $length, $offset) = @_; $self->PRINT(substr($scalar, $offset||0, $length)); } sub TELL { #Buffered classes provide their own, and others may use this in another way return undef; } sub CLOSE { my ($self) = @_; CORE::close($self->{real_fh}); } *DESTROY = \&CLOSE; #Non-IO methods sub PID{ my ($self) = @_; return $self->{child}; } #Provide lowercase aliases for accessors foreach my $method ( qw(BINMODE CLOSE EOF PRINT PRINTF TELL WRITE PID) ){ no strict 'refs'; *{lc($method)} = \&{$method}; } 1; __END__ =head1 NAME IO::Pager - Select a pager and pipe text to it if destination is a TTY =head1 SYNOPSIS # Select an appropriate pager and set the PAGER environment variable use IO::Pager; # TIMTOWTDI Object-oriented { # open() # Use all the defaults. my $object = new IO::Pager; # open FILEHANDLE # Unbuffered is default subclass my $object = new IO::Pager *STDOUT; # open FILEHANDLE,EXPR # Specify subclass my $object = new IO::Pager *STDOUT, 'Unbuffered'; # Direct subclass instantiation # FH is optional use IO::Pager::Unbuffered; my $object = new IO::Pager::Unbuffered *STDOUT; $object->print("OO shiny...\n"); print "Some other text sent to STODUT, perhaps from a foreign routine." # $object passes out of scope and filehandle is automagically closed } # TIMTOWTDI Procedural { # open FILEHANDLE # Unbuffered is default subclass my $token = IO::Pager::open *STDOUT; # open FILEHANDLE,EXPR # Specify subclass my $token = IO::Pager::open *STDOUT, 'Unbuffered'; # open FILEHANDLE,MODE,EXPR # En lieu of a separate binmode() my $token = IO::Pager::open *STDOUT, '|-:utf8', 'Unbuffered'; print <<" HEREDOC" ; ... A bunch of text later HEREDOC # $token passes out of scope and filehandle is automagically closed } { # You can also use scalar filehandles... my $token = IO::Pager::open(my $FH) or warn($!); XXX print $FH "No globs or barewords for us thanks!\n"; } =head1 DESCRIPTION IO::Pager can be used to locate an available pager and set the I environment variable (see L). It is also a factory for creating I/O objects such as L and L. IO::Pager subclasses are designed to programmatically decide whether or not to pipe a filehandle's output to a program specified in I. Subclasses may implement only the IO handle methods desired and inherit the remainder of those outlined below from IO::Pager. For anything else, YMMV. See the appropriate subclass for implementation specific details. =head1 METHODS =head2 new( FILEHANDLE, [MODE], [SUBCLASS] ) Almost identical to open, except that you will get an L back if there's no TTY to allow for IO::Pager-agnostic programming. =head2 open( FILEHANDLE, [MODE], [SUBCLASS] ) Instantiate a new IO::Pager, which will paginate output sent to FILEHANDLE if interacting with a TTY. Save the return value to check for errors, use as an object, or for implict close of OO handles when the variable passes out of scope. =over =item FILEHANDLE You may provide a glob or scalar. Defaults to currently select()-ed F. =item SUBCLASS Specifies which variety of IO::Pager to create. This accepts fully qualified packages I, or simply the third portion of the package name I for brevity. Defaults to L. Returns false and sets I<$!> on failure, same as perl's C. =back =head2 PID Call this method on the token returned by C to get the process identifier for the child process i.e; pager; if you need to perform some long term process management e.g; perl's C You can also access the PID by numifying the instantiation token like so: my $child = $token+0; =head2 close( FILEHANDLE ) Explicitly close the filehandle, this stops any redirection of output on FILEHANDLE that may have been warranted. I. Alternatively, you may rely upon the implicit close of lexical handles as they pass out of scope e.g; { IO::Pager::open local *RIBBIT; print RIBBIT "No toad sexing allowed"; ... } #The filehandle is closed to additional output { my $token = new IO::Pager::Buffered; $token->print("I like trains"); ... } #The string "I like trains" is flushed to the pager, and the handle closed =head2 binmode( FILEHANDLE, [LAYER] ) Used to set the I/O layer a.k.a. discipline of a filehandle, such as C<':utf8'> for UTF-8 encoding. =head2 eof( FILEHANDLE ) Used in the eval-until-eof idiom below, I will handle broken pipes from deceased children for you in one of two ways. If I<$ENV{IP_EOF}> is false then program flow will pass out of the loop on I, this is the default. If the variable is true, then the program continues running with output for the previously paged filehandle directed to the I stream; more accurately, the filehandle is reopened to file descriptor 1. use IO::Pager::Page; #or whichever you prefer; ... eval{ say "Producing prodigious portions of product"; ... } until( eof(*STDOUT) ); print "Cleaning up after our child before terminating." If using eof() with L, especially when IP_EOF is set, you may want to use the I<--no-init> option by setting I<$ENV{IP_EOF}='X'> to prevent the paged output from being erased when the pager exits. =head2 print( FILEHANDLE LIST ) print() to the filehandle. =head2 printf( FILEHANDLE FORMAT, LIST ) printf() to the filehandle. =head2 syswrite( FILEHANDLE, SCALAR, [LENGTH], [OFFSET] ) syswrite() to the filehandle. =head1 ENVIRONMENT =over =item IP_EOF Controls IO:Pager behavior when C is used. =item PAGER The location of the default pager. =item PATH If the location in PAGER is not absolute, PATH may be searched. See L for more information. =back =head1 FILES IO::Pager may fall back to these binaries in order if I is not executable. =over =item /etc/alternatives/pager =item /usr/local/bin/less =item /usr/bin/less =item /usr/bin/more =back See L for more information. =head1 NOTES The algorithm for determining which pager to use is as follows: =over =item 1. Defer to I If the I environment variable is set, use the pager it identifies, unless this pager is not available. =item 2. Usual suspects Try the standard, hardcoded paths in L. =item 3. File::Which If File::Which is available, use the first pager possible amongst C, C, C, C, C and L. =item 4. more Set I to C, and cross our fingers. =back Steps 1, 3 and 4 rely upon the I environment variable. =head1 SEE ALSO L, L, L, L, L =head1 AUTHOR Jerrad Pierce Florent Angly This module was inspired by Monte Mitzelfelt's IO::Page 0.02 =head1 COPYRIGHT AND LICENSE Copyright (C) 2003-2015 Jerrad Pierce =over =item * Thou shalt not claim ownership of unmodified materials. =item * Thou shalt not claim whole ownership of modified materials. =item * Thou shalt grant the indemnity of the provider of materials. =item * Thou shalt use and dispense freely without other restrictions. =back Or, if you prefer: This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.0 or, at your option, any later version of Perl 5 you may have available. =cut IO-Pager-0.35/lib/IO/Pager/0000755000175000017500000000000012641653472015131 5ustar belg4mitbelg4mitIO-Pager-0.35/lib/IO/Pager/Page.pm0000644000175000017500000000363212472372000016332 0ustar belg4mitbelg4mitpackage IO::Pager::Page; our $VERSION = 0.32; # The meat BEGIN { # Do nothing in Perl compile mode return if $^C; # Find a pager use IO::Pager; # Pipe stdout to it new IO::Pager *STDOUT, 'IO::Pager::Unbuffered'; } # Gravy sub import { my ($self, %opt) = @_; $SIG{PIPE} = 'IGNORE' if $opt{hush}; } "Badee badee badee that's all folks!"; __END__ =head1 NAME IO::Pager::Page - Emulate IO::Page, pipe STDOUT to a pager if STDOUT is a TTY =head1 SYNOPSIS Pipes STDOUT to a pager if STDOUT is a TTY =head1 DESCRIPTION IO::Pager was designed to programmatically decide whether or not to point the STDOUT file handle into a pipe to program specified in the I environment variable or one of a standard list of pagers. =head1 USAGE BEGIN { use IO::Pager::Page; # use I::P::P first, just in case another module sends output to STDOUT } print< foible resulting from the user exiting the pager prematurely, load IO::Pager::Page like so: use IO::Pager::Page hush=>1; =head1 SEE ALSO L, L, L, L =head1 AUTHOR Jerrad Pierce Florent Angly This module inspired by Monte Mitzelfelt's IO::Page 0.02 =head1 COPYRIGHT AND LICENSE Copyright (C) 2003-2015 Jerrad Pierce =over =item * Thou shalt not claim ownership of unmodified materials. =item * Thou shalt not claim whole ownership of modified materials. =item * Thou shalt grant the indemnity of the provider of materials. =item * Thou shalt use and dispense freely without other restrictions. =back Or, if you prefer: This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.0 or, at your option, any later version of Perl 5 you may have available. =cut IO-Pager-0.35/lib/IO/Pager/Buffered.pm0000644000175000017500000001111312473376702017207 0ustar belg4mitbelg4mitpackage IO::Pager::Buffered; our $VERSION = 0.30; use strict; use base qw( IO::Pager ); use SelectSaver; sub new(;$) { # [FH], procedural my($class, $tied_fh); eval { ($class, $tied_fh) = &IO::Pager::_init }; #We're not on a TTY so... if( defined($class) && $class eq '0' or $@ =~ '!TTY' ){ #...leave filehandle alone if procedural return $_[1] if defined($_[2]) && $_[2] eq 'procedural'; #...fall back to IO::Handle for transparent OO programming eval "require IO::Handle" or die $@; return IO::Handle->new_from_fd(fileno($_[1]), 'w'); } $!=$@, return 0 if $@ =~ 'pipe'; tie *$tied_fh, $class, $tied_fh or return 0; } #Punt to base, preserving FH ($_[0]) for pass by reference to gensym sub open(;$) { # [FH] # IO::Pager::open($_[0], 'IO::Pager::Buffered'); &new('IO::Pager::Buffered', $_[0], 'procedural'); } # Overload IO::Pager methods sub PRINT { my ($self, @args) = @_; $self->{buffer} .= join($,||'', @args); } sub CLOSE { my ($self) = @_; # Print buffer and close using IO::Pager's methods $self->SUPER::PRINT($self->{buffer}) if exists $self->{buffer}; $self->SUPER::CLOSE(); } *DESTROY = \&CLOSE; sub TELL { # Return the size of the buffer my ($self) = @_; use bytes; return exists($self->{buffer}) ? length($self->{buffer}) : 0; } sub flush(;*) { my ($self) = @_; if( exists $self->{buffer} ){ my $saver = SelectSaver->new($self->{real_fh}); local $|=1; ($_, $self->{buffer}) = ( $self->{buffer}, ''); $self->SUPER::PRINT($_); } } 1; __END__ =head1 NAME IO::Pager::Buffered - Pipe deferred output to PAGER if destination is a TTY =head1 SYNOPSIS use IO::Pager::Buffered; { local $token = IO::Pager::Buffered::open *STDOUT; print <<" HEREDOC" ; ... A bunch of text later HEREDOC } { # You can also use scalar filehandles... my $token = IO::Pager::Buffered::open($FH) or warn($!); print $FH "No globs or barewords for us thanks!\n"; } { # ...or an object interface my $token = new IO::Pager::Buffered; $token->print("OO shiny...\n"); } =head1 DESCRIPTION IO::Pager subclasses are designed to programmatically decide whether or not to pipe a filehandle's output to a program specified in I; determined and set by IO::Pager at runtime if not yet defined. This subclass buffers all output for display upon exiting the current scope. If this is not what you want look at another subclass such as L. While probably not common, this may be useful in some cases,such as buffering all output to STDOUT while the process occurs, showing only warnings on STDERR, then displaying the output to STDOUT after. Or alternately letting output to STDOUT slide by and defer warnings for later perusal. =head1 METHODS Class-specific method specifics below, others are inherited from IO::Pager. =head2 open( [FILEHANDLE] ) Instantiate a new IO::Pager to paginate FILEHANDLE if necessary. I. Output does not occur until all references to this variable are destroyed eg; upon leaving the current scope. See L. =head2 new( [FILEHANDLE] ) Almost identical to open, except that you will get an L back if there's no TTY to allow for IO::Pager agnostic programming. =head2 tell( FILEHANDLE ) Returns the size of the buffer in bytes. =head2 flush( FILEHANDLE ) Immediately flushes the contents of the buffer. If the last print did not end with a newline, the text from the preceding newline to the end of the buffer will be flushed but is unlikely to display until a newline is printed and flushed. =head1 CAVEATS If you mix buffered and unbuffered operations the output order is unspecified, and will probably differ for a TTY vs. a file. See L. I<$,> is used see L. =head1 SEE ALSO L, L, L, =head1 AUTHOR Jerrad Pierce Florent Angly This module was inspired by Monte Mitzelfelt's IO::Page 0.02 =head1 COPYRIGHT AND LICENSE Copyright (C) 2003-2012 Jerrad Pierce =over =item * Thou shalt not claim ownership of unmodified materials. =item * Thou shalt not claim whole ownership of modified materials. =item * Thou shalt grant the indemnity of the provider of materials. =item * Thou shalt use and dispense freely without other restrictions. =back Or, if you prefer: This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.0 or, at your option, any later version of Perl 5 you may have available. =cut IO-Pager-0.35/lib/IO/Pager/Unbuffered.pm0000644000175000017500000000567212473232504017556 0ustar belg4mitbelg4mitpackage IO::Pager::Unbuffered; our $VERSION = 0.31; use strict; use base qw( IO::Pager ); use SelectSaver; sub new(;$) { # [FH], procedural my($class, $tied_fh); eval { ($class, $tied_fh) = &IO::Pager::_init }; #We're not on a TTY so... if( defined($class) && $class eq '0' or $@ =~ '!TTY' ){ #...leave filehandle alone if procedural return $_[1] if defined($_[2]) && $_[2] eq 'procedural'; #...fall back to IO::Handle for transparent OO programming eval "require IO::Handle" or die $@; return IO::Handle->new_from_fd(fileno($_[1]), 'w'); } $!=$@, return 0 if $@ =~ 'pipe'; my $self = tie *$tied_fh, $class, $tied_fh or return 0; { # Truly unbuffered my $saver = SelectSaver->new($self->{real_fh}); $|=1; } return $self; } #Punt to base, preserving FH ($_[0]) for pass by reference to gensym sub open(;$) { # [FH] # IO::Pager::open($_[0], 'IO::Pager::Unbuffered'); &new('IO::Pager::procedural', $_[0], 'procedural'); } 1; __END__ =head1 NAME IO::Pager::Unbuffered - Pipe output to PAGER if destination is a TTY =head1 SYNOPSIS use IO::Pager::Unbuffered; { local $STDOUT = IO::Pager::Unbuffered::open *STDOUT; print <<" HEREDOC" ; ... A bunch of text later HEREDOC } { # You can also use scalar filehandles... my $token = IO::Pager::Unbuffered::open($FH) or warn($!); print $FH "No globs or barewords for us thanks!\n"; } { # ...or an object interface my $token = new IO::Pager::Unbuffered; $token->print("OO shiny...\n"); } =head1 DESCRIPTION IO::Pager subclasses are designed to programmatically decide whether or not to pipe a filehandle's output to a program specified in I; determined and set by IO::Pager at runtime if not yet defined. See L for method details. =head1 METHODS All methods are inherited from IO::Pager; except for instantiation. =head1 CAVEATS You probably want to do something with SIGPIPE eg; eval { $SIG{PIPE} = sub { die }; local $STDOUT = IO::Pager::open(*STDOUT); while (1) { # Do something } } # Do something else =head1 SEE ALSO L, L, L, =head1 AUTHOR Jerrad Pierce Florent Angly This module was inspired by Monte Mitzelfelt's IO::Page 0.02 Significant proddage provided by Tye McQueen. =head1 COPYRIGHT AND LICENSE Copyright (C) 2003-2012 Jerrad Pierce =over =item * Thou shalt not claim ownership of unmodified materials. =item * Thou shalt not claim whole ownership of modified materials. =item * Thou shalt grant the indemnity of the provider of materials. =item * Thou shalt use and dispense freely without other restrictions. =back Or, if you prefer: This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.0 or, at your option, any later version of Perl 5 you may have available. =cut IO-Pager-0.35/.proverc0000644000175000017500000000000212471375343014466 0ustar belg4mitbelg4mit-bIO-Pager-0.35/TODO0000644000175000017500000000162712641653043013506 0ustar belg4mitbelg4mitImportant things here and in code flagged with XXX 0.35 Odd failure of test 11 under tcsh and win-bash because *reference* has extra trailing newline. 0.30 Create a tee sub-class/layer? recommend PerlIO::Util's :tee in the dox, but provide a simplified (single file?) pure-perl implementation too, via a maethod to wrap an existing IO::Pager handle? (0.32) Might simplify new/open 'procedural' arg-passing mess? (0.33+) XXX Complete the ::less subclass to lump all non-interactive fallback behavior together? (See pagerless branch in git) 0.20 "Fix" multi-pseudo-STDOUT disabled in 09-open.t implementation? Alter tests to cover all invocation schemes, and document location of each in matrix OR use table-driven tests? new/open each class scalar vs. glob vs. OO (non-)fully qualified subclass name 0.02 Implement IO::Pager::Callback, just because it sounds cool? IO-Pager-0.35/t.pl0000644000175000017500000000023612473367515013622 0ustar belg4mitbelg4mituse strict; use warnings; undef($ENV{LESS}); for (sort glob "t/*interactive.t") { print "Running $_...\n"; system($^X, '-Mblib', $_); } print "Done\n"; IO-Pager-0.35/META.yml0000644000175000017500000000130612641653472014267 0ustar belg4mitbelg4mit--- abstract: 'Select a pager and pipe text to it if destination is a TTY' author: - 'Jerrad Pierce , Florent Angly ' build_requires: Config: 0 Env: 0 Exporter: 0 File::Temp: 0 Test::More: 0 configure_requires: ExtUtils::MakeMaker: 0 dynamic_config: 1 generated_by: 'ExtUtils::MakeMaker version 6.64, CPAN::Meta::Converter version 2.112621' license: unknown meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: IO-Pager no_index: directory: - t - inc requires: Env: 0 File::Spec: 0 File::Which: 0 IO::Handle: 0 PerlIO: 0 SelectSaver: 0 Symbol: 0 Tie::Handle: 0 base: 0 version: 0.35 IO-Pager-0.35/CHANGES0000644000175000017500000000730312641653173014012 0ustar belg4mitbelg4mitRevision history for Perl extension IO::Pager. 0.35 Fri Jan 01 2016 Update test 11 for Windows; okay in CMD, PowerShell and MSYS but tcsh and win-bash both fail Add .travis.yml 0.34 Wed Feb 25 2015 Fix version error in Makefile. Fix a bug in 3-arg open introduced by fix for 1-arg in 0.33. 0.33 Wed Feb 25 2005 Fix "Warning: unable to close filehandle $real_fh properly." Fixed FILEHANDLE only open(). 0.32 Tue Feb 24 2005 Add 3-arg open support. Add eof() mechanism for semi-elegant signal handling. Update documentation. Undef $ENV{LESS} in interactive tests in case -E is set. Robustify t/11 for Win32 (RT#79950). 0.31 Sat Apr 06 2013 Add missing IO::Handle fallback for ::Unbuffered (RT#82351) Bogus fix for Windoze automatic line-ending failure of t/11 (RT#79950), improvements welcomed. 0.30 Tue Sep 04 2012 Implement feature request #78270 to include support say Preserve layers of passed hilehandle on instantiation. Fixed tests under Win32 & cygwin, bug #75181. Swap IO::Pager:new and ::open, alter subclass::open to remove unnecessary level of subroutine calls Return IO::Handle objects when not connected to a TTY for transparent use of IO::Pager when programming OO. NOTE: This is broken, see ::less in TODO 0.24 Sat Feb 18 2012 Fixed bug #74691, tests fail if CPANTS folk don't have a perl in PATH! Add PID method & token overload to access pager process identifier. Remove semi-circular reference in object to fix implicit close(). 0.20 Sat Feb 11 2012 Fixed bug #74691, add File::Which as dependency / skip test if missing Fixed non-TTY/redirection behavior and added corresponding test Improve buffering sistuation in both ::Buffered and ::Unbuffered Auto-gensym scalar filehandles like perl's open Add OO interface Add alternate pagers 'lv', 'pg', and system default '/etc/alternatives/pager' (bug# 74519) Add tests for initialization failure conditions (9-open.t) 0.16 Fri Feb 3 2012 Require 5.8.0 or better Removed Perl warning 'Use of tie on a handle without * is deprecated'. No interactive questions during 'make test' (bug# 66718) Better handling of missing PAGER. Look for more pagers: 'most' and 'w3m' (bug# 74519) Documentation clean-up, light refactoring, more error checks. Do not run IO::Pager::Page automatically when in Perl compile mode. 0.10 Unreleased Added support for encodings via binmode() (bug# 67930). Test: encoding, handle (glob, scalar, OO), interactive... 0.07 Unreleased Rewrote to support scalar filehandles per user request and IO::Handle style OO support came along for the ride. Fixed several mis-coded segments that did not affect operation. Added C in IO::Pager::Unbuffered to check size of buffered output. Pager open error now sets $! instead of issuing a warning, to more closely emulate the C experience. Check return value as before. Neglected to update $VERSION in last release. Touched up the documentation. 0.06 Wed Sep 21 2005 Fixed a stupid leftover using =~ for assignment that some perls ignored (bug# 14692). Fixed other nits in t.pl and documentation. 0.05 Thu Jul 17 20:01:55 EDT 2003 Touched up documentation. Added IO::Pager::Page, a clone of IO::Page "Broken pipe" foible and all. Fixed a bug in pager selection algorithm, it failed if you did not have File::Which. It is now back to being only strongly recommended as opposed to required. 0.04 Wed Jul 16 18:53:58 EDT 2003 Removed a stupid debug message from IO::Pager::new. Improved PAGER selection algorithm. Touched up documentation. Added some tests. 0.03 Tue Jul 15 23:11:12 2003 Forked from IO::Page. 0.02 Tue Jul 15 23:11:12 2003 original version; created by h2xs 1.22 with options -X -n IO::Pager. IO-Pager-0.35/t/0000755000175000017500000000000012641653472013261 5ustar belg4mitbelg4mitIO-Pager-0.35/t/04-buffered_interactive.t0000644000175000017500000000237512021541465020043 0ustar belg4mitbelg4mituse strict; use warnings; use Test::More; use t::TestUtils; # Test buffered paging SKIP: { skip_interactive(); require IO::Pager; diag "\n". "Reading is fun! Here is some text: ABCDEFGHIJKLMNOPQRSTUVWXYZ\n". "This text should be displayed directly on screen, not within a pager.\n". "\n"; select STDERR; my $A = prompt "\nWas the text displayed directly on screen? [Yn]"; ok is_yes($A), 'Diagnostic'; { my $BOB = new IO::Pager *BOB, 'IO::Pager::Buffered'; isa_ok $BOB, 'IO::Pager::Buffered'; isa_ok $BOB, 'Tie::Handle'; for (1..10) { printf BOB "Line %06i, buffer [%06i] @ %s\n", $_, tell(BOB), scalar localtime; } print BOB "Sleeping for 2 seconds...\n"; # IO::Pager::Buffered::flush(*BOB); $BOB->flush(); sleep 2; for (reverse 1..10) { printf BOB "Line %06i, buffer [%06i] @ %s\n", $_, tell(BOB), scalar localtime; } printf BOB "\nEnd of text, try pressing 'Q' to exit. @%s\n", scalar localtime; close BOB; } $A = prompt "\nWas the text displayed in a pager? [Yn]"; ok is_yes($A), 'Buffered glob filehandle'; $A = prompt "\nWas there a pause between the two blocks of text? [Yn]"; ok is_yes($A), 'Flush buffered filehandle'; } done_testing; IO-Pager-0.35/t/11-redirect-oo.pl0000644000175000017500000000015312130115452016230 0ustar belg4mitbelg4mituse blib; use IO::Pager; our $txt; require 't/08-redirect.pl'; my $FH = new IO::Pager; $FH->print($txt); IO-Pager-0.35/t/02-which_interactive.t0000644000175000017500000000063512021541465017356 0ustar belg4mitbelg4mituse strict; use warnings; use Test::More; use t::TestUtils; use Env qw( PAGER ); # Test that a reasonable pager can be found SKIP: { skip_interactive(); diag "Current PAGER: '".($PAGER||'')."'\n"; require IO::Pager; diag "PAGER set by IO::Pager: '".($PAGER||'')."'\n"; select STDERR; my $A = prompt "\nIs this reasonable? [Yn]"; ok is_yes($A), 'Found a reasonable pager'; } done_testing; IO-Pager-0.35/t/08-redirect.t0000644000175000017500000000130312021541465015457 0ustar belg4mitbelg4mituse strict; use warnings; use File::Temp; use Test::More; use t::TestUtils; #Disable warnings for awkard test file mechanism required by Windows my(undef, $tempname) = do{ $^W=0; File::Temp::tempfile(OPEN=>0)}; END{ close(TMP); unlink $tempname or die "Could not unlink '$tempname': $!" } #Print the heredoc in 08-redirect.pl to temp file via redirection my $q = q[']; $q = q["] if $^O =~ /MSWin32/; system qq($^X -Mblib -MIO::Pager::Page -e $q require q[t/08-redirect.pl]; print \$txt $q >$tempname); open(TMP, $tempname) or die "Could not open tmpfile: $!\n"; my $slurp = do{ undef $/; }; our $txt; require 't/08-redirect.pl'; ok($txt eq $slurp, 'Redirection (IO::Pager::Page)'); done_testing; IO-Pager-0.35/t/03-bald_interactive.t0000644000175000017500000000173312021541465017157 0ustar belg4mitbelg4mituse strict; use warnings; use Test::More; use t::TestUtils; # Test unbuffered paging SKIP: { skip_interactive(); require IO::Pager; diag "\n". "Reading is fun! Here is some text: ABCDEFGHIJKLMNOPQRSTUVWXYZ\n". "This text should be displayed directly on screen, not within a pager.\n". "\n"; select STDERR; my $A = prompt "\nWas the text displayed directly on screen? [Yn]"; ok is_yes($A), 'Diagnostic'; { local $STDOUT = new IO::Pager *BOB; # IO::Pager::Unbuffered by default isa_ok $STDOUT, 'IO::Pager::Unbuffered'; isa_ok $STDOUT, 'Tie::Handle'; eval { my $i = 0; $SIG{PIPE} = sub{ "Work complete" }; while (1) { printf BOB "%06i Printing text in a pager. Exit at any time, usually by pressing 'Q'.\n", $i++; sleep 1 unless $i%400; } }; close BOB; } $A = prompt "\nWas the text displayed in a pager? [Yn]"; ok is_yes($A), 'Unbuffered glob filehandle'; } done_testing; IO-Pager-0.35/t/TestUtils.pm0000644000175000017500000000273012473242767015565 0ustar belg4mitbelg4mitpackage t::TestUtils; use strict; use warnings; use Config; use Test::More; use Env qw( HARNESS_ACTIVE ); use ExtUtils::MakeMaker qw( prompt ); use base qw( Exporter ); our @EXPORT; BEGIN { @EXPORT = qw{ skip_interactive skip_old_perl skip_no_file_which skip_not_in_path is_no is_yes perl_exe perl_path prompt }; } sub skip_interactive { skip "Run 'perl -Mblib t.pl' to perform interactive tests.", 1 if $HARNESS_ACTIVE; } sub skip_old_perl { skip "Layers requires Perl 5.8.0 or better.", 1 if $] < 5.008; } sub skip_no_file_which { skip "This test requires File::Which.", 1 if not eval { require File::Which }; } sub skip_not_in_path { # Test that the specified executable can be found in the PATH environment # variable using File::Which. my $exe = shift; my $loc = File::Which::which($exe); skip "Executable '$exe' is not in PATH.", 1 if not defined $loc; } sub is_yes { my ($val) = @_; return ($val =~ /^y(?:es)?/i || $val eq ''); } sub is_no { my ($val) = @_; return ($val =~ /^n(?:o)?/i || $val eq ''); } sub perl_exe { # Find the Perl executable name my $this_perl = $^X; $this_perl = (File::Spec->splitpath( $this_perl ))[-1]; return $this_perl; } sub perl_path { # Find the Perl full-path (taken from the perlvar documentation) my $this_perl = $^X; if ($^O ne 'VMS') { $this_perl .= $Config{_exe} unless $this_perl =~ m/$Config{_exe}$/i; } return $this_perl; } 1; IO-Pager-0.35/t/01-load.t0000644000175000017500000000036612021541465014576 0ustar belg4mitbelg4mituse strict; use warnings; use Test::More; use t::TestUtils; # Test that all modules load properly BEGIN { use_ok('IO::Pager'); use_ok('IO::Pager::Unbuffered'); use_ok('IO::Pager::Buffered'); use_ok('IO::Pager::Page'); }; done_testing; IO-Pager-0.35/t/12-preservelayers_interactive.t0000644000175000017500000000122512021541465021324 0ustar belg4mitbelg4mituse strict; use warnings; use File::Temp; use Test::More; use t::TestUtils; use 5.6.0; use utf8; use IO::Pager; SKIP: { skip_interactive(); my $fileno = fileno(STDOUT); { binmode(*STDOUT, ':encoding(UTF-8)'); my $pager = IO::Pager->new(*STDOUT); $pager->say('Bonzai Bjørn'); $pager->say("$/End of text, try pressing 'Q' to exit."); $pager->close(); } #Reinstate some order CORE::open(*BOB, ">&=$fileno"); binmode(*BOB, ':encoding(UTF-8)'); select(BOB); my $A = prompt "\nDid you see 'Bonzai Bjørn' in your pager? Note the crossed o in the second word [Yn]"; ok is_yes($A), 'layer preservation'; } done_testing; IO-Pager-0.35/t/06-scalar_interactive.t0000644000175000017500000000126112021541465017521 0ustar belg4mitbelg4mituse strict; use warnings; use Test::More; use t::TestUtils; # Test unbuffered paging SKIP: { skip_interactive(); require IO::Pager; { my $BOB; local $STDOUT = IO::Pager::open($BOB, 'IO::Pager::Buffered'); is ref($BOB), 'GLOB', 'Gensym'; isa_ok $STDOUT, 'IO::Pager::Buffered'; isa_ok $STDOUT, 'Tie::Handle'; eval { my $i = 0; for (1..20) { printf($BOB "%06i There is more than one to do it.\n", $_); } printf $BOB "\nEnd of text, try pressing 'Q' to exit.\n", $_; }; close($BOB); } my $A = prompt "\nWas the text displayed in a pager? [Yn]"; ok is_yes($A), 'Buffered scalar filehandle'; } done_testing; IO-Pager-0.35/t/13-eof_interactive.t0000644000175000017500000000067512473367344017050 0ustar belg4mitbelg4mituse strict; use warnings; use File::Temp; use Test::More; use t::TestUtils; use bignum; use IO::Pager::Page; SKIP: { skip_interactive(); $a=1; $b=1; eval{ print $a, "\n"; #Fibonacci is the golden ratio ($a,$b)=($b,$a+$b); } until( eof(*STDOUT) ); print "Pager closed, wrapping up.\n"; my $A = prompt "\nWere things wrapped up after you quit the pager? [Yn]"; ok is_yes($A), 'Signal handling EOF'; } done_testing; IO-Pager-0.35/t/05-binmode_interactive.t0000644000175000017500000000176112473241741017702 0ustar belg4mitbelg4mituse strict; use warnings; use Test::More; use t::TestUtils; # Test paging binary content SKIP: { skip_interactive(); skip_old_perl(); require IO::Pager; my $warnings; eval { # Promote warnings to errors so we can catch them local $SIG{__WARN__} = sub { $warnings .= shift }; # Stream unicode in a pager local $STDOUT = new IO::Pager *BOB, ':utf8', 'IO::Pager::Buffered'; printf BOB "Unicode Z-inverted carat: \x{17D}\n"; #Ž printf BOB "Unicode Copyright < Copyleft: \x{A9} < \x{2184}\x{20DD}\n"; #© < ↄ⃝ printf BOB "Unicode camel: \x{1f42a}\n", $_; # 🐪 printf BOB "\nEnd of text, try pressing 'Q' to exit.\n"; close BOB; }; is $warnings, undef, 'No wide character warnings'; binmode STDOUT, ":utf8"; my $A = prompt "\nWere Unicode characters like \x{17D} and \x{A9},\nor perhaps a bytecode placeholder such as displayed in the pager? [Yn]"; ok is_yes($A), 'Binmode layer selection / pager Unicode support'; } done_testing; IO-Pager-0.35/t/02-which.t0000644000175000017500000000226012021541465014755 0ustar belg4mitbelg4mituse strict; use warnings; use Test::More; use t::TestUtils; use Env qw( PAGER ); use IO::Pager; my $pager; # Find anything that looks like a pager, unspecified $PAGER = undef; $pager = IO::Pager::find_pager(); ok $pager, 'Undefined PAGER'; # Find anything that looks like a pager 2, this is redundant $PAGER = ''; $pager = IO::Pager::find_pager(); ok $pager, 'Blank PAGER'; # Find anything that looks like a pager 3, bad initial setting $PAGER = 'asdfghjk666'; $pager = IO::Pager::find_pager(); isnt $pager, 'asdfghjk666', 'PAGER does not exist'; # Perl is sure to be present, pretend it's a pager specified w/ absolute path $PAGER = perl_path(); $pager = IO::Pager::find_pager(); is $pager, perl_path(), 'PAGER referred by its full-path'; # Perl is sure to be present, pretend it's a pager specified w/o path SKIP: { skip_no_file_which(); $PAGER = perl_exe(); skip_not_in_path($PAGER); $pager = IO::Pager::find_pager(); like $pager, qr/perl/i, 'PAGER is referred by its executable name'; } # Verify that options set in the PAGER variable are preserved $PAGER = perl_path().' -w'; $pager = IO::Pager::find_pager(); is $pager, perl_path().' -w', 'PAGER with options'; done_testing; IO-Pager-0.35/t/08-redirect.pl0000644000175000017500000000465312021541465015642 0ustar belg4mitbelg4mitour $txt = <print("OO factory filehandle\n"); $BOB->print("\nEnd of text, try pressing 'Q' to exit.\n"); $BOB->close(); } my $A1 = prompt "\nDid you see 'OO factory filehandle' in your pager? [Yn]"; ok is_yes($A1), 'OO, factory instantiation'; require IO::Pager::Unbuffered; { my $BOB = new IO::Pager::Unbuffered or die "Failed to create PAGER FH $!"; isa_ok $BOB, 'IO::Pager::Unbuffered'; $BOB->say("OO subclass filehandle\n"); $BOB->say("\nEnd of text, try pressing 'Q' to exit.\n"); #XXX Close required because pager is not terminated on DESTROY $BOB->close(); } my $A2 = prompt "\nDid you see 'OO subclass filehandle' in your pager? [Yn]"; ok is_yes($A2), 'OO, subclass instantiation'; } done_testing; IO-Pager-0.35/t/11-redirect-oo.t0000644000175000017500000000156012641652700016074 0ustar belg4mitbelg4mituse strict; use warnings; use File::Temp; use Test::More; use t::TestUtils; #Disable warnings for awkard test file mechanism required by Windows my(undef, $tempname) = do{ $^W=0; File::Temp::tempfile(OPEN=>0)}; END{ close(TMP); unlink $tempname or die "Could not unlink '$tempname': $!" } #Print the heredoc in 11-redirect.pl to temp file via redirection system qq($^X t/11-redirect-oo.pl >$tempname); open(TMP, $tempname) or die "Could not open tmpfile: $!\n"; my $slurp = do{ undef $/; }; #Special case for CMD & PowerShell lameness, see diag below if( $^O =~ /MSWin32/ ){ $slurp =~ s/\n\n\z/\n/m; } our $txt; require 't/08-redirect.pl'; cmp_ok($txt, 'eq', $slurp, 'Redirection with OO') || $^O =~ /MSWin32/ && diag("If this test fails on Windows and all others pass, things are probably good. CMD appends an extra newline to redirected output."); done_testing; IO-Pager-0.35/t/10-close_interactive.t0000644000175000017500000000236412021541465017361 0ustar belg4mitbelg4mituse strict; use warnings; use Test::More; use t::TestUtils; use IO::Pager; SKIP: { skip_interactive(); my $A; PAUSE: { my $token = new IO::Pager undef, 'Buffered'; isa_ok $token, 'IO::Pager::Buffered'; my $PID = $token->PID; $token->print("Pager child '$token->{pager}' is PID $PID\n"); $token->print("\nEnd of text, try pressing 'Q' to exit.\n"); is $PID, $token->{child}, "PID($PID)"; sleep 1; } $A = prompt "\nWas there a pause before the text appeared? [Ynr] (r-epeat)"; goto PAUSE if $A eq 'r'; ok is_yes($A), 'Implicit close of buffered OO filehandle'; { IO::Pager::open local *RIBBIT, 'Buffered'; print RIBBIT "No toad sexing allowed"; print RIBBIT "\nEnd of text, try pressing 'Q' to exit.\n" } $A = prompt "\nIs toad sexing allowed? (And posted before commentary on trains) [yN]"; goto PAUSE if $A eq 'r'; ok is_no($A), 'Implicit close of buffered glob filehandle'; #Possible future test, but meanwhile is here to ensure proper destruction, #since the output of this block would appear before above if no implicit close { new IO::Pager *MARY; print MARY "I like trains\n"; print MARY "\nEnd of text, try pressing 'Q' to exit.\n"; close(MARY); } } done_testing; IO-Pager-0.35/t/09-open.t0000644000175000017500000000113612473234310014623 0ustar belg4mitbelg4mituse strict; use warnings; use File::Spec; use Test::More; use t::TestUtils; no warnings; $^W = 0; #Avoid: Can't exec "/dev/null": Permission denied use IO::Pager; SKIP: { skip("Skipping because Windows has to be different^Wdifficult", 1) if $^O =~ /MSWin32|cygwin/; undef $ENV{PAGER}; eval{ my $token = new IO::Pager }; like($@, qr/The PAGER environment variable is not defined/, 'PAGER undefined since find_pager()'); $ENV{PAGER} = File::Spec->devnull(); eval{ my $token = new IO::Pager or die $!}; like($@, qr/Could not pipe to PAGER/, 'Could not create pipe'); } done_testing; IO-Pager-0.35/README0000644000175000017500000000332612021541465013670 0ustar belg4mitbelg4mitIO::Pager version 0.30 ===================== IO::Pager - Select a pager and pipe text to it if destination is a TTY IO::Pager is lightweight and can be used to locate an available pager and set the PAGER environment variable sanely or as a factory for creating objects defined elsewhere such as IO::Pager::Buffered and IO::Pager::Unbuffered. IO::Pager subclasses are designed to programmatically decide whether or not to pipe a filehandle's output to a program specified in PAGER. Subclasses may inherit from IO::Pager, and implement the IO handle methods desired. INSTALLATION To install this module type the following: perl Makefile.PL make # Run non-interactive tests make test # Run interactive tests perl -Mblib t.pl make install DEPENDENCIES Multiple core modules are used: base, Env, File::Spec, File::Which, IO::Handle, PerlIO, SelectSaver, Symbol, Tie::Handle Test::More is used during the installation procedure. PORTABILITY IO::Pager is intended to be as portable as possible, I've tested it on numerous platform and perl version combinations. Most work fine though you may run into quirks, it tends to be happiest under perl built with perlio not stdio. COPYRIGHT AND LICENSE Copyright (C) 2003-2012 Jerrad Pierce * Thou shalt not claim ownership of unmodified materials. * Thou shalt not claim whole ownership of modified materials. * Thou shalt grant the indemnity of the provider of materials. * Thou shalt use and dispense freely without other restrictions. Or, if you prefer: This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.0 or, at your option, any later version of Perl 5 you may have available. IO-Pager-0.35/.travis.yml0000644000175000017500000000015012640032414015105 0ustar belg4mitbelg4mitsudo: false language: perl perl: - "5.22" - "5.20" - "5.18" - "5.16" - "5.14" - "5.12" - "5.10" - "5.8" IO-Pager-0.35/META.json0000644000175000017500000000235212641653472014441 0ustar belg4mitbelg4mit{ "abstract" : "Select a pager and pipe text to it if destination is a TTY", "author" : [ "Jerrad Pierce , Florent Angly " ], "dynamic_config" : 1, "generated_by" : "ExtUtils::MakeMaker version 6.64, CPAN::Meta::Converter version 2.112621", "license" : [ "unknown" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "IO-Pager", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "Config" : 0, "Env" : 0, "Exporter" : 0, "File::Temp" : 0, "Test::More" : 0 } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : 0 } }, "runtime" : { "requires" : { "Env" : 0, "File::Spec" : 0, "File::Which" : 0, "IO::Handle" : 0, "PerlIO" : 0, "SelectSaver" : 0, "Symbol" : 0, "Tie::Handle" : 0, "base" : 0 } } }, "release_status" : "stable", "version" : "0.35" } IO-Pager-0.35/MANIFEST0000644000175000017500000000125212641653472014147 0ustar belg4mitbelg4mitCHANGES Makefile.PL MANIFEST lib/IO/Pager.pm lib/IO/Pager/Buffered.pm lib/IO/Pager/Page.pm lib/IO/Pager/Unbuffered.pm README TODO .proverc .travis.yml t.pl t/01-load.t t/02-which.t t/02-which_interactive.t t/03-bald_interactive.t t/04-buffered_interactive.t t/05-binmode_interactive.t t/06-scalar_interactive.t t/07-oo_interactive.t t/08-redirect.pl t/08-redirect.t t/09-open.t t/10-close_interactive.t t/11-redirect-oo.pl t/11-redirect-oo.t t/12-preservelayers_interactive.t t/13-eof_interactive.t t/TestUtils.pm META.yml Module YAML meta-data (added by MakeMaker) META.json Module JSON meta-data (added by MakeMaker)