Texan has asked for the wisdom of the Perl Monks concerning the following question:
I am new to Perl, so be kind.
I am trying to generate a progress bar. I need it to be only console based. I think I have the theory worked out, but cannot get the end result. I know that I start with a number and I have the max number but, how do I get the system to generate the progress bar? I am looking for a simple:
********33%
type of bar. But I am willing to use any code willingly given.
Thanks
Re: Progress Bar
by tachyon (Chancellor) on Oct 06, 2004 at 02:33 UTC
|
do{ progress_bar( $_, 100, 25, '=' ); sleep 1 } for 1..100;
sub progress_bar {
my ( $got, $total, $width, $char ) = @_;
$width ||= 25;
$char ||= '=';
my $num_width = length $total;
local $| = 1;
printf "|%-${width}s| Got %${num_width}s bytes of %s (%.2f%%)\r",
$char x (($width-1)*$got/$total). '>', $got, $total, 100*$got/
+$total;
}
| [reply] [d/l] |
Re: Progress Bar
by giulienk (Curate) on Oct 06, 2004 at 07:10 UTC
|
Another option would be using Term::ProgressBar: i used it in the past and it's pretty easy and complete.
$|=$_="1g2i1u1l2i4e2n0k",map{print"\7",chop;select$,,$,,$,,$_/7}m{..}g
| [reply] |
Re: Progress Bar
by tmoertel (Chaplain) on Oct 06, 2004 at 03:14 UTC
|
(Updated: Something bad happened to the code portion during cut-and-paste to the site. This is now fixed.)
Here's a quick bit of code that provides a simple, object-oriented
way to draw progress bars. To use it, just create a progress bar
like so:
my $bar = ProgressBar->new( width => 40 );
(Here, our bar will be 40 characters wide.) Then, to draw the
bar, just pass in the current count of completed tasks and the
total number of tasks:
$bar->draw( 3, 10 );
So, in the above example, we have completed 3 of 10 tasks and
the following would be drawn:
============ 30%
A couple of points:
- If the total number of tasks is fixed, you can provide it at
the time you create the progress bar via the max_val
parameter and omit it in calls to
the draw() method.
- The code works properly for progress bars that go forward,
backward, or both. (See the demo.)
Here's the code:
#!/usr/bin/perl -w
{
# TGM 2004-10-05
# Progress bar code
package ProgressBar;
use Class::Struct width => '$', portion => '$', max_val => '$';
use List::Util qw( min );
sub draw {
local $| = 1;
my ($self, $x, $max_val) = @_;
$max_val ||= $self->max_val;
my $old_portion = $self->portion || 0;
my $new_portion = int( $self->width * $x / $max_val + 0.5 );
print "\b" x ( 6 + $self->width
- min( $new_portion, $old_portion ) )
if defined $self->portion;
print "=" x ( $new_portion - $old_portion ),
" " x ( $self->width - $new_portion ),
sprintf " %3d%% ", int( 100 * $x / $max_val + 0.5 );
$self->portion( $new_portion );
}
1;
}
# DEMO
my $pb = ProgressBar->new( width => 40, max_val => 10 );
# show progress 0 to 100% and then back down to 0% again
do { $pb->draw( $_ ) ; sleep 1 } for 0 .. 10;
do { $pb->draw( 9 - $_ ); sleep 1 } for 0 .. 9;
print "\n";
Hope this helps.
Cheers, Tom
| [reply] [d/l] [select] |
Re: Progress Bar
by ikegami (Patriarch) on Oct 06, 2004 at 02:36 UTC
|
sub flush {
my $h = select($_[0]); my $a=$|; $|=1; $|=$a; select($h);
}
sub show_progress {
my ($progress) = @_;
my $stars = '*' x int($progress*10);
my $percent = int($progress*100);
$percent = $percent >= 100 ? 'done.' : $percent.'%';
print("\r$stars $percent");
flush(STDOUT);
}
show_progress(1/4);
sleep(1);
show_progress(2/4);
sleep(1);
show_progress(3/4);
sleep(1);
show_progress(4/4);
| [reply] [d/l] |
Re: Progress Bar
by cosimo (Hermit) on Oct 06, 2004 at 10:53 UTC
|
Another, totally different, perhaps "strange", approach could be based on Smart::Comments...
| [reply] |
|
| [reply] |
|
Have you seen the author/maintainers for that code? Damian, Autrijus, and Ingy. Gods, talk about a trifecta of Perfect Perl Prowess!
Being right, does not endow the right to be rude; politeness costs nothing. Being unknowing, is not the same as being stupid. Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence. Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.
| [reply] |
|
Cheers for this suggestion, have never come across that module before and it looks perfect. I like to write lots of debugging friendly code in my scripts and have been using trailing "if $debug=1;" or similar. Smart::Comments makes all that so much nicer and neater.
| [reply] |
|
|