From 496e9a7b096012573242b82c7fb8027882d7599f Mon Sep 17 00:00:00 2001 From: Don Armstrong Date: Sun, 13 Apr 2014 12:10:33 -0700 Subject: [PATCH 1/1] Add Term::ProgressBar::IO. 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 | 3 + lib/Term/ProgressBar/IO.pm | 163 +++++++++++++++++++++++++++++++++++++ t/02_term_progressbar_io.t | 32 ++++++++ t/random_file | 10 +++ 4 files changed, 208 insertions(+) create mode 100644 lib/Term/ProgressBar/IO.pm create mode 100644 t/02_term_progressbar_io.t create mode 100644 t/random_file diff --git a/Changes b/Changes index 50c66f5..d1b1500 100644 --- 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 index 0000000..b95ab6f --- /dev/null +++ b/lib/Term/ProgressBar/IO.pm @@ -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 . + +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 which corresponds +to reading from a filehandle. + +This module inherits from L 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 filehandles are +also properly handled. + +=item OTHER ARGUMENTS + +All other arguments are documented in L + +=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 index 0000000..90560f9 --- /dev/null +++ b/t/02_term_progressbar_io.t @@ -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 index 0000000..f00c965 --- /dev/null +++ b/t/random_file @@ -0,0 +1,10 @@ +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 -- 2.39.2