Andrew Sterling Hanenkamp > IO-NestedCapture-1.03 > IO::NestedCapture

Download:
IO-NestedCapture-1.03.tar.gz

Dependencies

Annotate this POD

Related Modules

Data::Dumper
WWW::Mechanize
Test::More
more...
By perlmonks.org

CPAN RT

Open  1
View/Report Bugs
Module Version: 1.03   Source  

NAME ^

IO::NestedCapture - module for performing nested STD* handle captures

SYNOPSIS ^

  use IO::NestedCapture qw/ :subroutines /;

  my $in = IO::NestedCapture->get_next_in;
  print $in "Harry\n";
  print $in "Ron\n";
  print $in "Hermione\n";

  capture_in_out {
      my @profs = qw( Dumbledore Flitwick McGonagall );
      while (<STDIN>) {
          my $prof = shift @prof;
          print STDOUT "$_ favors $prof";
      }
  };

  my $out = IO::NestedCapture->get_last_out;
  while (<$out>) {
          print;
  }

  # This program will output:
  # Harry favors Dumbledore
  # Ron favors Flitwick
  # Hermione favors McGonagall

DESCRIPTION ^

This module was partially inspired by IO::Capture, but is intended for a very different purpose and is not otherwise related to that package. In particular, I have a need for some pretty aggressive output/input redirection in a web project I'm working on. I'd like to be able to pipe input into a subroutine and then capture that subroutines output to be used as input on the next.

I was using a fairly clumsy, fragile, and brute force method for doing this. If you're interested, you can take a look at the code on PerlMonks.org:

  http://perlmonks.org/?node_id=459275

This module implements a much saner approach that involves only a single tie per file handle (regardless of what you want to tie it to). It works by tying the STDIN, STDOUT, and STDERR file handles. Then, uses internal tied class logic to handle any nested use or other work.

With this module you can capture any combination of STDIN, STDOUT, and STDERR. In the case of STDIN, you may feed any input into capture you want (or even set it to use another file handle). For STDOUT and STDERR you may review the full output of these or prior to capture set a file handle that will receive all the data during the capture.

As of version 1.02 of this library, there are two different interfaces to the library. The object-oriented version was first, but the new subroutine interface is a little less verbose and a little safer.

OBJECT-ORIENTED INTERFACE

The object-oriented interface is available either through the IO::NestedCapture class directly or through a single instance of the class available through the instance method.

  my $capture = IO::NestedCapture->instance;
  $capture->start(CAPTURE_STDOUT);
  
  # Is the same as...

  IO::NestedCapture->start(CAPTURE_STDOUT);

It doesn't really make much difference.

You will probably want to important one, several, or all of the capture constants to use this interface.

SUBROUTINE INTERFACE

This interface is available via the import of one of the capture subroutines (or not if you want to fully qualify the names):

  use IO::NestedCapture 'capture_out';
  capture_out {
      # your code to print to STDOUT here...
  };

  # Is similar to...
  IO::NestedCapture::capture_err {
      # your code to print to STDERR here...
  };

This interface has the advantage of being a little more concise and automatically starts and stops the capture before and after running the code block. This will help avoid typos and other mistakes in your code, such as forgetting to call stop when you are done.

NESTED CAPTURE SUBROUTINES

These subroutines are used with the subroutine interface. (See "SUBROUTINE INTERFACE".) These subroutines actually use the object-oriented interface internally, so they merely provide a convenient set of shortcuts to it that may help save you some trouble.

For each subroutine, the subroutine captures one or more file handles before running the given code block and uncaptures them after. In case of an exception, the file handles will still be uncaptured properly. Make sure to put a semi-colon after each method call.

To manipulate the input, output, and error handles before or after the capture, you will still need to use parts of the object-oriented interface.

You will want to import the subroutines you want to use when you load the IO::NestedCapture object:

  use IO::NestedCapture qw/ capture_in capture_out /;

or you can import all of the capture subroutines with the :subroutines mnemonic:

  use IO::NestedCapture ':subroutines';

In place of a block, you may also give a code reference as the argument to any of these calls:

  sub foo { print "bah\n" }

  capture_all \&foo;

This will run the subroutine foo (with no arguments) and capture the streams it reads/writes. Also, each of the capture subroutines return the return value of the block or rethrow the exceptions raised in the block after stopping the capture.

capture_in { };

This subroutine captures STDIN for the duration of the given block.

capture_out { };

This subroutine captures STDOUT for the duration of the given block.

capture_err { };

This subroutine captures STDERR for the duration of the given block.

capture_in_out { };

This subroutine captures STDIN and STDOUT for the duration of the given block.

capture_in_err { };

This subroutine captures STDIN and STDERR for the duration of the given block.

capture_out_err { };

This subroutine captures STDOUT and STDERR for the duration of the given block.

capture_all { };

This subroutine captures STDIN, STDOUT, and STDERR for the duration of the given block.

NESTED CAPTURE CONSTANTS

These constants are used with the object-oriented interface. (See "OBJECT-ORIENTED INTERFACE".)

You will want to import the constants you want when you load the IO::NestedCapture module:

  use IO::NestedCapture qw/ CAPTURE_STDIN CAPTURE_STDOUT /;

or you may import all of them with the :constants mnemonic.:

  use IO::NestedCapture ':constants';
CAPTURE_STDIN

Used to start or stop capture on STDIN.

CAPTURE_STDOUT

Used to start or stop capture on STDOUT.

CAPTURE_STDERR

Used to start or stop capture on STDERR.

CAPTURE_IN_OUT

Used to start or stop capture on STDIN and STDOUT. This is a shortcut for "CAPTURE_STDIN | CAPTURE_STDOUT".

CAPTURE_IN_ERR

Used to start or stop cpature on STDIN and STDERR. This is a shortcut for "CAPTURE_STDIN | CAPTURE_STDERR".

CAPTURE_OUT_ERR

Used to start or stop capture on STDOUT and STDERR. This is a shortcut for "CAPTURE_STDOUT | CAPTURE_STDERR".)

CAPTURE_ALL

Used to start or stop capture on STDIN, STDOUT, and STDERR. This is a shortcut for "CAPTURE_STDIN | CAPTURE_STDOUT | CAPTURE_STDERR".

OBJECT-ORIENTED CAPTURE METHODS

These are the methods used for the object-oriented interface. (See "OBJECT-ORIENTED INTERFACE".)

$capture = IO::NestedCapture->instance;

Retrieves an instance of the singleton. Use of this method is optional.

IO::NestedCapture->start($capture_what)
$capture->start($capture_what)

The $capture_what variable is a bit field that should be set to one or more of the "NESTED CAPTURE CONSTANTS" bit-or'd together. Until this method is called, the STD* handles are not tied to the IO::NestedCapture interface. The tie will only occur on the very first call to this method. After that, the nesting is handled with stacks internal to the IO::NestedCapture singleton.

If you're capturing STDIN, you should be sure to fill in the input using the in method first if you want there to be any to be read.

If you're capturing STDOUT or STDERR, you should be sure to set the file handles to output too, if you want to do that before calling this method.

IO::NestedCapture->stop($uncapture_what)
$capture->stop($uncapture_what)

The $uncapture_what variable is a bit field that should be set to one or more of the "NESTED CAPTURE CONSTANTS" bit-or'd together. If this method is called and the internal nesting state shows that this is the last layer to remove, the associated STD* handles are untied. If $uncapture_what indicates that a certain handle should be uncaptured, but it isn't currently captured, an error will be thrown.

$handle = IO::NestedCapture->get_next_in
$handle = $capture->get_next_in

This method returns the file handle that will be used for STDIN after the next call to start(CAPTURE_STDIN). If one has not been set using set_next_in, then a seekable file handle will be created. If you just use the automatically created file handle (which is created using File::Temp), then start() will seek to the top of the file handle before use.

IO::NestedCapture->set_next_in($handle)
$capture->in($handle)

The given file handle is used as the file handle to read from after start(CAPTURE_STDIN) is called. If you set a file handle yourself, you must make sure that it is ready to be read from when you call start() (i.e., the file handle pointer won't be reset to the top of the file automatically).

$handle = IO::NestedCapture->get_last_out
$handle = $capture->get_last_out

Retrieve the file handle used to capture the output prior to the previous call to stop(CAPTURE_STDOUT). If this file handle was automatically generated (i.e., not set with set_next_out(), then the file pointer will already be set to the top of the file and ready to read).

IO::NestedCapture->set_next_out($handle)
$capture->set_next_out($handle)

Install your own file handle to capture the output following the next call to start(CAPTURE_STDOUT). Make sure the file handle is in the exact state you want before calling start().

$handle = IO::NestedCapture->get_last_error
$handle = $capture->get_last_error

Retrieve the file handle used to capture the error output prior to the previous call to stop(CAPTURE_STDERR). If this file handle was automatically generated (i.e., not set with set_next_err(), then the file pointer will already be set to the top of the file and ready to read).

IO::NestedCapture->set_next_err($handle)
$capture->set_next_err($handle)

Install your own file handle to capture the error output following the next call to start(CAPTURE_STDERR). Make sure the file handle is in the exact state you want before calling start().

EXPORTS ^

This module exports all of the constants used with the object-oriented interface and the subroutines used with the subroutine interface.

See "NESTED CAPTURE CONSTANTS" for the specific constant names or use :constants to import all the constants.

See "NESTED CAPTURE SUBROUTINES" for the specific subroutine names or use :subroutines to import all the subroutines.

SEE ALSO ^

IO::Capture

AUTHOR ^

Andrew Sterling Hanenkamp, <hanenkamp@cpan.org>

COPYRIGHT AND LICENSE ^

Copyright 2005 Andrew Sterling Hanenkamp.

This code is licensed and distributed under the same terms as Perl itself.

syntax highlighting: