Module Tie::Handle::Intercepted

J

John

What do y'all think of this module? Do we need it on CPAN? Is it apty
named? Other comments? Documentation included below.

=head1 NAME

Tie::Handle::Intercepted - Intercept, Filter, Reroute, and Fork File
Handles.

=head1 SYNOPSIS

###Intercept
intercept \*STDOUT, sub {
print STDERR "Luppy!\n"; #If we print to STDOUT, we will cause an
infinite loop!
}
print "Hello, World!"; #Outputs "Luppy!" to STDERR

###Filter
filter \*STDOUT, sub {uc(shift)}; #Make all output uppercase.
print "Hello, World!\n"; #Outputs "HELLO, WORLD!"

###Reroute to a file
reroute \*STDERR, ">error.log";
warn "Arghh!"; #Prints "Arghh!" to error.log

###Fork
fork_handle \*STDERR, ">>error.log";
warn "Arghh!": #Prints the warning to STDERR *and* to error.log

###Capture to a scalar, array, or file
my $myscalar;
my $filter = reroute \*STDOUT, \$myscalar;
print "Hello, World!";
release_all_handlers \*STDOUT;
print "Scalar is: $scalar\n"; #Outputs "Scalar is: Hello, World!"


=head1 DESCRIPTION

This module provides a convenient way to intercept, filter, reroute, and
fork filehandles, without using the Perl tie interface.

C<intercept> causes all output to the given handle to be intercepted and
passed to the supplied handler subroutine.

C<filter>, C<reroute>, and C<fork_handle> are implemented via C<intercept>.
Look at the definition of these methods for a good example of how to use
C<intercept>.

This module has some cool features:

- Multiple handlers can be chained.
- Handlers can uninstall themselves.
- Handler subroutines can access the handle they intercepted.

=head2 Uninstalling a Handler

If you install a hander with C<lexically_scoped> => 1 , then an object will
be returned that will release the handler when it goes out of scope. You
can also call C<release> on this object to acheive the same result.

{
my $filter = filter \*STDERR, sub { uc($_[0]) }, lexically_scoped => 1;
print "foo"; #Prints "FOO"
} #The handler uninstalls itself now that it's going out of scope.

print "foo"; #Prints "foo"

=head2 Chaining Handlers

If you install a handler on a handle that already has a handler installed,
the new handle will be installed "in front" of the original handler. For
example:

my $scalar;
reroute \*STDOUT, \$scalar;
filter \*STDOUT, sub { uc{$_[0]} };
print "Hello, World!";

#Result:
$scalar eq "Hello, World!" or die "It didn't work!";


=head2 Accessing the Original Filehandle

The package variable C<$Tie::Handle::Intercepted::eek:riginal_handle> gives you
a reference to the original handle. Examine the definition of the C<filter>
below to see how this can be useful.

sub filter {
my($handle, $sub, %args) = @_;

my $thing = intercept $handle, sub {
my $return_value = &$sub(@_);
print $original_handle $return_value;
}, %args, keep_original => 1;
}

Don't worry, $original_handle uses the magic of Perl C<local> variables to
ensure that it always contains the correct reference, even when chaining
handlers.

=cut
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,145
Latest member
web3PRAgeency
Top