]> git.donarmstrong.com Git - term-progressbar.git/commitdiff
Add Term::ProgressBar::IO.
authorDon Armstrong <don@donarmstrong.com>
Sun, 13 Apr 2014 19:10:33 +0000 (12:10 -0700)
committerDon Armstrong <don@donarmstrong.com>
Sun, 13 Apr 2014 19:10:33 +0000 (12:10 -0700)
This additional module supports easily updating a progressbar based on
a seekable filehandle. It also correctly handles IO::Uncompress
handles (by examining the position in the compressed filehandle
instead of the uncompressed one.)

See POD documentation in Term::ProgressBar::IO for more details.

Changes
lib/Term/ProgressBar/IO.pm [new file with mode: 0644]
t/02_term_progressbar_io.t [new file with mode: 0644]
t/random_file [new file with mode: 0644]

diff --git a/Changes b/Changes
index 50c66f54a4a95125d418c5a8772b1bcac237fb65..d1b15000687a5640905736e0c36ea00586f98610 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,5 +1,8 @@
 Revision history for Perl extension Term-ProgressBar
 
+2.15 UNRELEASED
+    - Add Term::ProgressBar::IO (DON)
+
 2.14 2013-07-21 13:34:52
     - Document the term_width argument to the constructor (OVID)
     - Add a "silent" option to the constructor (OVID)
diff --git a/lib/Term/ProgressBar/IO.pm b/lib/Term/ProgressBar/IO.pm
new file mode 100644 (file)
index 0000000..b95ab6f
--- /dev/null
@@ -0,0 +1,163 @@
+# 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__
+
+
+
+
+
+
diff --git a/t/02_term_progressbar_io.t b/t/02_term_progressbar_io.t
new file mode 100644 (file)
index 0000000..90560f9
--- /dev/null
@@ -0,0 +1,32 @@
+# -*- 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();
diff --git a/t/random_file b/t/random_file
new file mode 100644 (file)
index 0000000..f00c965
--- /dev/null
@@ -0,0 +1,10 @@
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10