Hi leocharre,
A method I like to use for progress meters is to create a closure that lets you define all parameters up front, and then call the closure to update.
Here's an example:
#!/usr/bin/perl -w
use strict;
use warnings;
sub progress_bar {
my ($total, $msg, $width, $off_sym, $on_sym) = @_;
$msg ||= '<count> / <total> (<percent> %) <meter>';
$width ||= 32;
$off_sym ||= "-";
$on_sym ||= "*";
my $last_msg = "";
local $| = 1;
my $psub = sub {
my ($count) = @_;
my $b_done = ($count < 0);
$b_done and $count = $total;
my $pcnt = sprintf "%5.1f", 100.0 * $count / $total;
my $used = $pcnt * $width / 100;
my $unused = $width - $used;
my $meter = ($on_sym x $used) . ($off_sym x $unused);
my $this_msg = $msg;
$this_msg =~ s/<percent>/$pcnt/g;
$this_msg =~ s/<count>/$count/g;
$this_msg =~ s/<total>/$total/g;
$this_msg =~ s/<meter>/$meter/g;
my $next_width = $width - length($msg);
if ($last_msg ne $this_msg) {
print STDERR "\r$this_msg\e[K";
}
$b_done and print STDERR "\n";
};
return $psub;
}
# Main program
my $psub = progress_bar(10000, '<meter> File <count> of <total> (<perc
+ent> %)');
for (my $i = 0; $i < 10000; $i++) {
select(undef,undef,undef,0.01);
$psub->($i);
}
$psub->(-1);
In this program, the subroutine progress_bar creates the closure, based on the following 5 parameters (of which only the first is required):
- total ..... The total number of "things" to count (eg. maximum value)
- msg ....... The message to embed within the progress bar.
(The default is a preformatted message).
It can contain any of the following tags, which are
dynamically substituted with the appropriate value:
- <count> ..... The current count
- <total> ..... The total count
- <percent> ... The current percentage complete
- <meter> ..... The progress meter itself
- width ..... The total width of the progress meter and message (default = 50)
- off_sym ... The "off" symbol (default = '-')
- on_sym .... The "on" symbol (default = '*')
Then, after creating the closure, you call it with the current count, each time you wish to display the progress meter and message. It will only update when the progress meter or message changes.
When you're done, you can call it with a negative count to signal 100% completion (and to display a newline). The main program shows an example of calling the progress meter with a file count that goes from zero to 1000.
s''(q.S:$/9=(T1';s;(..)(..);$..=substr+crypt($1,$2),2,3;eg;print$..$/
|