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 tied 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, like CLOSE, 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's readline, 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 is unshift @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 the OPEN 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, or EOF

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 a close 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 overriding CLOSE, 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 tied ARGV to distinguish between a regular <> operator and the newer double-diamond <<>> operator (introduced in Perl 5.22), which uses the three-argument open. 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/.