Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change

progress bars

by PetaMem (Priest)
on Jul 09, 2001 at 01:24 UTC ( #94851=perlquestion: print w/ replies, xml ) Need Help??
PetaMem has asked for the wisdom of the Perl Monks concerning the following question:


I would like to add some nifty progress-bar-show-status information to my app, which at the moment has only a CLI (Web-frontend and other GUIs planned). How do I a simple

'|' -> '/' -> '-' -> '\'  (and then start again)

or some kind of

Donīt get me wrong, I know how to print the information (now
even using closures if you e.g. want to update only every x
actions), but I donīt know how to do it "right" and "clean" in
a terminal window.

Said that, I will try some backspace/escape-sequence hacking
but donīt consider it clean, as there can be several different
terminals and every one with itīs own escape-sequence definition
BTW: Isnīt there a module? :-)


Comment on progress bars
Re: progress bars
by cleen (Pilgrim) on Jul 09, 2001 at 01:38 UTC
    Yes, there is a pretty nifty curses based status-bar module in a package I picked up somewhere (couldnt find it on cpan) called 'Paw'. I cannot for the life of me find the homepage of this package, but if you like I have it at if you wanna grab it....Ive used the entire package on a few application frontends for work.

Re: progress bars
by clintp (Curate) on Jul 09, 2001 at 04:08 UTC
    If you're willing to stick with backspace and carriage return, this really isn't a hard hack at all. Here's a twirly-bob:
    { my $p=0; $|=1; sub tick { print substr(qq{|/-\\|/-\\}, $p++, 1), "\b"; $p=0 if ($p > 8); } }
    Just call tick repeatedly and the thing will spin. Or a percentage meter:
    { my $bar=qq{0%..........50%..........100%}; $|=1; sub bar { local $_=$bar; substr($_, $_[0]/100*length($_), 1)="|"; print "$_\r"; } }
    Just call bar with a number between 1 and 100 to indicate how complete things are.
Re: progress bars
by Seumas (Curate) on Jul 09, 2001 at 04:19 UTC
    Here is an example of spinning progress bars and whirleygigs. They may not work on every terminal and there are certainly nicer solutions, but if all you need is an indicator telling the user "I'm alive and still doin' stuff!", it might be good enough. Otherwise, cleen's suggestion may be what you want.

    Of course, doing a percentage report would require initial knowledge of the amount of 'stuff' to be done. In some situations, this is easy to ascertain. In others, it's impossible and a spinner-type solution is the best way to go.

(ar0n: tie version) Re: progress bars
by ar0n (Priest) on Jul 09, 2001 at 04:39 UTC
    I was bored, so here's a tie version:
    package Status; sub TIESCALAR { my $c = shift; my @v = @_; @v = ('|', '/', '-', '\\') unless @v; bless { vals => \@v, status => 0 }, $c; } sub FETCH { $_[0]->{status} = ($_[0]->{status} + 1) % scalar @{ $_[0]- +>{vals} }; return $_[0]->{vals}[ $_[0]->{status} ] } package main; $| = 1; tie $s, 'Status'; while (1) { print $s; select(undef,undef,undef,0.1); print "\r" x 40; }
    Just pass in the sequence when tying:
    tie $status, 'Status', qw( - + | + );
    or let it default to the one you specified above.

    ar0n ]

Re: progress bars
by John M. Dlugosz (Monsignor) on Jul 09, 2001 at 07:15 UTC
    If you are running on a GUI system but in a console window, as opposed to a text-only terminal, you might consider throwing up a GUI dialog box for progress, and not interfere with the normal text output.
Re: progress bars
by PetaMem (Priest) on Nov 04, 2001 at 13:21 UTC

    yesterday I somewhat fixed a version of my "progress bar fillup" I created after this thread. Most of the ideas came from tye.
    This version uses a closure, and might be of use for one or another of you. Usage is simple:

    my $pb = pb_fillup(<showlen>,<char>,<barlen>);
    Initializes the progress-bar. It defines how long the data to be munged are (showlen), what character should be used for progress visualization (char) and how long the progress bar shall be (barlen). All 3 are scalars. If you wish to init a progress bar with a [#######    ] look&feel, that should show progress reading a file and be 40 chars wide, you could init it like that:
    my $pb = pb_fillup(-s $file,'#',40);
    Where $file is a name of an existing file. The calls doing the actual visualization are like that:
    print $pb->(length $_);
    You either give the closure the length of data you have munged or - if you omit the parameter - pb_fillup just does an increment. Iīm sure, the code can be much optimized and beautified, but itīs pretty easy to use and does accomplish its task for me.


    Oh! The code:

    sub pb_fillup { my ($max,$char,$len) = @_; # init look&feel my $old_slen = -1; # init old showlength my $cur = 0; # init current length return sub { $cur += @_ ? shift : 1; my $slen = int $cur/$max*$len; my $bar; if($slen != $old_slen) { $bar = $char x $slen; $bar .= ' ' x ($len - $slen); $| = 1; print '[',$bar,']'; print "\b" x ($len+2); $| = 0; $old_slen = $slen; } return; } }

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://94851]
Approved by root
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (17)
As of 2014-07-24 18:42 GMT
Find Nodes?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:

    Results (165 votes), past polls