--- /dev/null
+# This module is part of IO, and is released
+# under the terms of the GPL version 3, or any later version at your option. See the
+# file README and COPYING for more information.
+# Copyright 2014 by Don Armstrong <don@donarmstrong.com>.
+
+package Term::ProgressBar::IO;
+
+=head1 NAME
+
+Term::ProgressBar::IO -- Display a progress bar while reading from a seekable filehandle
+
+=head1 SYNOPSIS
+
+ my $pb = Term::ProgressBar::IO->new($fh);
+
+ while (<$fh>) {
+ # do something
+ $pb->update();
+ }
+
+=head1 DESCRIPTION
+
+Displays a progress bar using L<Term::ProgressBar> which corresponds
+to reading from a filehandle.
+
+This module inherits from L<Term::ProgressBar> and has all of its
+options.
+
+=head1 BUGS
+
+None known.
+
+=cut
+
+use warnings;
+use strict;
+use vars qw($VERSION $DEBUG);
+
+use parent qw(Term::ProgressBar);
+use Carp;
+use Fcntl qw(:seek);
+
+BEGIN{
+ $VERSION = q(0.1);
+ $DEBUG = 0 unless defined $DEBUG;
+}
+
+=head1 METHODS
+
+=head2 new
+
+Create and return a new Term::ProgressBar::IO instance.
+
+=over
+
+=item ARGUMENTS
+
+=over
+
+=item count
+
+A valid filehandle or item count. L<IO::Uncompress> filehandles are
+also properly handled.
+
+=item OTHER ARGUMENTS
+
+All other arguments are documented in L<Term::ProgressBar>
+
+=back
+
+=back
+
+=cut
+
+sub init {
+ my $self = shift;
+ my $count;
+ if (@_==2) {
+ $count = $_[1];
+ } else {
+ croak
+ sprintf("Term::ProgressBar::IO::new We don't handle this many arguments: %d",
+ scalar @_)
+ if @_ != 1;
+ }
+ my %config;
+ if ( UNIVERSAL::isa ($_[0], 'HASH') ) {
+ ($count) = @{$_[0]}{qw(count)};
+ %config = %{$_[0]};
+ } else {
+ ($count) = @_;
+ }
+ if (ref($count) and $count->can("seek")) {
+ $self->{__filehandle} = $count;
+ $count = $self->__determine_max();
+ }
+ $config{count} = $count;
+ $self->SUPER::init(\%config);
+}
+
+=head2 update
+
+Automatically update the progress bar based on the position of the
+filehandle given at construction time.
+
+=over
+
+=item ARGUMENTS
+
+=over
+
+=item so_far
+
+Current progress point; this defaults to the current position of the
+filehandle. [You probably don't actually want to ever give this.]
+
+=back
+
+=back
+
+=cut
+
+sub update {
+ my $self = shift;
+ my $count = $self->__determine_count();
+ $self->SUPER::update(scalar @_? @_ : $count);
+}
+
+sub __determine_max {
+ my $self = shift;
+ # is this an IO::Uncompress handle?
+ my $max = 0;
+ if ($self->{__filehandle}->can('getHeaderInfo')) {
+ $self->{__filehandle} = *$self->{__filehandle}{FH};
+ }
+ eval {
+ my $cur_pos = $self->{__filehandle}->tell;
+ $self->{__filehandle}->seek(0,SEEK_END);
+ $max = $self->{__filehandle}->tell;
+ $self->{__filehandle}->seek($cur_pos,SEEK_SET);
+ };
+ return $max;
+}
+
+sub __determine_count {
+ my $self = shift;
+ my $count = 0;
+ eval {
+ $count = $self->{__filehandle}->tell;
+ };
+ return $count;
+}
+
+1;
+
+
+__END__
+
+
+
+
+
+
--- /dev/null
+# -*- mode: cperl; -*-
+use Test::More;
+
+use_ok('Term::ProgressBar::IO');
+
+use IO::File;
+use Capture::Tiny qw(capture_stderr);
+
+my $fh = IO::File->new('t/random_file','r') or
+ die "Unable to open t/random_file for reading: $!";
+
+Term::ProgressBar->__force_term (50);
+
+my $pb;
+my $err = capture_stderr {
+ $pb = Term::ProgressBar::IO->new($fh);
+};
+
+ok($pb->target() == 9*2+3,'Correct number of bytes in __DATA__');
+
+while (<$fh>) {
+ $err = capture_stderr {
+ $pb->update();
+ };
+}
+
+print STDERR $pb->last_update();
+ok($pb->last_update() == $pb->target(),'Last position is now target');
+
+close($fh);
+
+done_testing();