Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much

progress bars

by PetaMem (Priest)
on Jul 09, 2001 at 01:24 UTC ( [id://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? :-)


Replies are listed 'Best First'.
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 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.

(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 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.

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; } }
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.