Name
Tie::Handle::Argv - A base class for tying Perl's magic ARGV handle
Synopsis
package Tie::Handle::MyDebugArgv;
use parent 'Tie::Handle::Argv';
sub OPEN {
my $self = shift;
print STDERR "Debug: Open '@_'\n";
return $self->SUPER::OPEN(@_);
}
Then use your custom tied handle:
tie *ARGV, 'Tie::Handle::MyDebugArgv';
while (<>) {
chomp;
print "<$_>\n";
}
untie *ARGV;
Description
This is a base class for tied filehandles that reproduces the behavior of Perl's ARGV
filehandle, more commonly known as the magic <>
readline
operator. By itself, this class attempts to reproduce the behavior of the magical ARGV
and its associated variables ($ARGV
, @ARGV
, and $.
) as faithfully as possible.
This documentation is somewhat sparse, because I assume that if you want to subclass this class, you will probably have to look at its code anyway. I will expand on it as necessary (patches and suggestions welcome).
Experimental Status of this Module
Warning: As of 0.16, this module was split out of the distribution of File::Replace because a tie
d ARGV
has proven to be very difficult to reliably test due to small changes in Perl's behavior across various Perl versions. For this reason, unfortunately, it may or may not work reliably on your system, independently of whether the test suite passes or not, and so I have had to declare this module experimental. Future breakages of this module may not be fixed/fixable.
Constructor
The constructor TIEHANDLE
takes several optional arguments as key/value pairs:
files
-
If you set this to an array reference, that array will be used instead of the default global
@ARGV
. filename
-
If you set this to a reference to a scalar, then that scalar will be populated with the current filename instead of the default global
$ARGV
. debug
-
Described in "Debugging"; set this to either a true value or a reference to a filehandle to enable debugging.
Subclassing
You should first study Tie::Handle::Base, of which this class is a subclass. In particular, note that this class wraps an "inner handle", which is the underlying handle which is typically the "real" filehandle that is being read from (but could in theory itself be a tied handle - hint: see the set_inner_handle
method in Tie::Handle::Base).
There are several methods that have been abstracted out so that you may override their default behavior in subclasses, as follows. When overriding methods from this class, make sure you first understand their behavior, and when you might need to call the superclass method.
inner_close
-
Override this if you want to intercept a call to Tie::Handle::Base's
CLOSE
method. Takes no arguments and, likeCLOSE
, should always return a scalar (typically true/false). inner_eof
-
Override this if you want to intercept a call to Tie::Handle::Base's
EOF
method. Takes zero or one arguments (see perltie) and should always return a scalar (typically true/false). read_one_line
-
Override this if you want to intercept a call to Tie::Handle::Base's
READLINE
method. Will only ever be called in scalar context and therefore should read one line (as with Perl'sreadline
, the definition of "line" varies depending on the current setting of the input record separator$/
). Takes no arguments and should always return a scalar. init_empty_argv
-
This method is called when the magic
ARGV
filehandle is read from the first time and@ARGV
is empty. If you want the read to succeed, this method needs to modify@ARGV
so that it is no longer empty. The default implementation is Perl's normal behavior, which isunshift @ARGV, '-';
. Takes no arguments and should return nothing ("return;
"). advance_argv
-
This method should modify
$ARGV
so that it contains the next filename to pass to theOPEN
method, and also return that filename. The default implementation is Perl's normal behavior, which is$ARGV = shift @ARGV;
. Takes no arguments and should always return a scalar (the filename). OPEN
-
You may override this method to modify its behavior. Make sure you understand its arguments and expected behavior - see "OPEN" in Tie::Handle::Base and perltie.
sequence_end
-
Override this if you want to take action after the last file in
@ARGV
has been closed. Takes no arguments and should return nothing ("return;
"). - Other methods:
TIEHANDLE
,UNTIE
,DESTROY
-
You may override these methods if needed, making sure to call the superclass methods!
- Don't override:
READLINE
,CLOSE
, orEOF
-
These methods contain much of the logic of this class. I recommend using the hooks provided above instead. If you are missing a hook, please report the issue (with sample code and expected behavior) in the issue tracker.
In particular, note the source code of
CLOSE
in this class: This method is called when the user of the tied handle explicitly calls e.g.close ARGV;
, which should have the effect of resetting the line number counter$.
, whereas aclose
operation that may occur when advancing to the next file in the sequence should not. This is why there is an internal_close
method to abstract out this behavior. If you do plan on overridingCLOSE
, then make sure you call the appropriate method in this class. - Object Storage
-
Subclasses may store whatever they like in this hashref, except that keys beginning with two underscores (
__
) are reserved for this base class and for Tie::Handle::Base.
This documentation describes version 0.18 of this module.
Warning About Perls Older Than v5.16 and Windows
Perl versions before 5.12 did not support eof()
(with an empty parameter list) on tied handles. See also "Tying FileHandles" in perltie and "Other potentially incompatible changes" in perl5120delta.
Also, Perl 5.14 had several regressions regarding, among other things, eof
on tied handles. See "Filehandle, last-accessed" in perl5160delta.
It is therefore strongly recommended to use this module on Perl 5.16 and up. On older versions, be aware of the aforementioned issues.
In addition, there are some slight behavioral differences on Windows up to and including Perl 5.16, and not all features of this module can currently be tested on Windows, in particular in regards to opening anything other than regular files, such as STDIN
via the special filename -.
Caveats and Known Differences to Perl's <>
Perl's
tie
mechanism currently does not allow a tiedARGV
to distinguish between a regular<>
operator and the newer double-diamond<<>>
operator (introduced in Perl 5.22), which uses the three-argumentopen
. When using this module,<<>>
will currently act the same as<>
.If a newer version of Perl is released which allows for tied filehandles to make use of
<<>>
, this module can be updated correspondingly. (At the time of writing, all released versions of Perl, up to and including 5.28, do not support special treatment of<<>>
on tied filehandles.)Note: On the other hand, this class can be used to change
<>
to work like<<>>
even on older Perls, for instance:package Tie::Handle::ThreeArgOpenArgv; use parent 'Tie::Handle::Argv'; sub OPEN { my $self = shift; return $self->SUPER::OPEN('<',shift); }
Debugging
This class contains a _debug
method that may be called by subclasses to provide debug output (when enabled). TIEHANDLE
takes an argument debug => $debug
, where $debug
is either a scalar with a true value, in which case debugging messages will be sent to STDERR
, or a reference to a filehandle, in which case debugging messages will be sent to that filehandle.
Author, Copyright, and License
Copyright (c) 2018-2023 Hauke Daempfling (haukex@zero-g.net) at the Leibniz Institute of Freshwater Ecology and Inland Fisheries (IGB), Berlin, Germany, http://www.igb-berlin.de/
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.