Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations wOOdy-Soft on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Make my twirlling baton work! 3

Status
Not open for further replies.

nawlej

Programmer
Mar 26, 2004
380
US
Hey everyone! I have done it again....Run into a problem. Im trying to create a "Twirlling baton" progress indicator, but all the output from this script comes up after it runs, and prints to STDOUT> Can anyone tell me how to fix this to make it appear to be a twirlling baton?

#!/usr/local/bin/perl -w

use strict;

my $timer = 180;

printf(STDOUT "Please wait.\n This could take several minutes.\n");

#initialize the time to 1 and the twirl to 1
my $time = 1;
my $count = 1;

while($time != $timer){

if ($count == 5){$count = 1;}

for ($count){
/1/ and do { printf(STDOUT "-\b"); };
/2/ and do { printf(STDOUT "\\\b"); };
/3/ and do { printf(STDOUT "|\b"); };
/4/ and do { printf(STDOUT "\/\b"); };
}# - for ($count)
sleep 1;
$count++; #increment the count and sleep timer.
$time++;
}

print "Count done.";
 
Furthermore I suggest to use a for loop:
Code:
for (my $time=0;$timer;$time++)
{
...
}

Not that it solves the problem but you will find it sooner...
 
You probably need to flush your buffer.

try using:
flush STDOUT;
at the end of your case statement.

You will need to include:
use FileHandle;

Maybe someone else can point out better/more portable ways to do this.
 
Thats it..
Code:
#!/usr/bin/perl -w
use strict;
use FileHandle;

print "Please wait.\n This could take several minutes.\n";

#initialize the time to 1 and the twirl to 1
my $count = 1;
#print "time\tcount\n";

for(my $time =1; $time<180; $time++)
{
 #print "$time\t$count\n";

 if    ($count == 1)
 {print "\b-";}
 elsif ($count == 2)
 {print "\b\\";}
 elsif ($count == 3)
 {print "\b|";}
 elsif ($count == 4)
 {print "\b\/";}
 elsif ($count == 5)
 {$count = 0;}
 flush STDOUT;

 sleep 1;
 $count++; #increment the count
}

print "Count done.";
 
Another version :
Code:
#!/usr/bin/perl -w
use strict;
use FileHandle;

print "Please wait.\n This could take several minutes.\n";

my @twirl = ("-","\\","|","\/");

for(my $counter=1; $counter<20; $counter++)
{
  my $twirl_indx = $counter % 4;
  print "$twirl[$twirl_indx]\b";
  flush STDOUT;
  sleep 1;
}

print "Count done.";


Jean Pierre.
 
Hi uida1154

you don't really need the last if statement to catch the value of count being 5 - and when it does get to 5 it should really be set back to 1 ... not zero as then it has to go through the loop again, do nothing but increment by 1, then through the loop again

I like the end result though! :)

Code:
use FileHandle;

print "Please wait.\n This could take several minutes.\n";

my $count = 1;

for (my $time=1; $time<180; $time++) {

  if ($count==1) {
    print "\b-"
  } elsif ($count==2) {
    print "\b\\";
  } elsif ($count==3) {
    print "\b|";
  } elsif ($count==4) {
    print "\b\/";
  } else {
    $count=1;
  }
    
  flush STDOUT;
  
  sleep 1;
  
  $count++;
}

print "Count done.";


Kind Regards
Duncan
 
even neater... also removed the need to use Filehandle and flush STDOUT;

sorry uida1154 - forgot the counter was being incremented after resetting back to zero!

Code:
$| = 1;

@baton = ("\b-", "\b\\", "\b|", "\b\/");

print "Please wait.\nThis could take several minutes.\n";

for (my $time=1; $time<180; $time++) {

  print "$baton[$count]";
  $count=-1 if ($count==3);
  $count++;
  sleep 1;
  
}

print "Count done.\n";


Kind Regards
Duncan
 
Duncan

Could you replace
Code:
$count=-1 if ($count==3);
  $count++;
with
Code:
$count = $time % 3;
? The modulus operator seems like the easiest way to go here...

Steve
 
Steve - that's a beautiful solution! no if statements whatsoever!!!

a [red]*[/red] for you! :)

Code:
$| = 1;

@baton = ("\b-", "\b\\", "\b|", "\b\/");

print "Please wait.\nThis could take several minutes.\n";

for (my $time=0; $time<180; $time++) {
  $count = $time % 4;
  print "$baton[$count]";
  sleep 1;
}

print "Count done.\n";


Kind Regards
Duncan
 
Not a bad solution eh?

Only 1 for loop - no if statements and no counter incrementation ... and no need to declare the value of $count at the start of the script

Brilliant!!!


Kind Regards
Duncan
 
aigles

i've only just noticed (i promise!) that my code is almost identical to yours...

i tried yours though and it didn't work for me unless i changed it very slightly - but credit to you for your solution!

Code:
$|=1;

print "Please wait.\nThis could take several minutes.\n";

my @twirl = ("-","\\","|","\/");

for (my $counter=1; $counter<20; $counter++)
{
  print "[red]\b[/red]$twirl[$counter % 4]";
  sleep 1;
}

print "Count done.";


Kind Regards
Duncan
 
Duncan

Thanks for the star. But aigles got there before me, and I'd completely missed his post...
 
*digging up old thread* thread219-543279

Been there, done that. :)

________________________________________
Andrew - Perl Monkey
 
icrf

you are quite within your rights to shout about that one - nice work!


Kind Regards
Duncan
 
Think we may have answered the question but not solved the problem. What is the thing we are we waiting for? All we know is that we have a task that may take 'some time', and we guess how long and display a nice twirling baton for the duration. But the (presumably asynchronous) thing we are waiting for might not finish in time, or it might finish much sooner. Shouldn't we be polling something somewhere in the loop, to see if we can stop waiting? Maybe not on every iteration, but every five seconds or so?
 
Thank you for all of the help and genuine interest! I got it working with my original script using the flush STDOUT; statement. Forgot all about it....Thanx for helping me shake off the rust. Seeing some of the code examples, I decided to rewrite it, so the end result looks something like this, and works great:

Code:
#!/usr/local/bin/perl -w

use strict;
use FileHandle;

my $curr_app = "Test";
my $curr_node = "testnode";
my $timer = 180;

print "Please wait. This could take several minutes.\n";

$|=1;

my @twirl = ("-","\\","|","\/");

for (my $time=1; $time<$timer; $time++)
{
  print "\b$twirl[$time % 4]";
  sleep 1;
  flush STDOUT;
}

print "\nCount done.";
 
Think we may have answered the question but not solved the problem. What is the thing we are we waiting for? All we know is that we have a task that may take 'some time', and we guess how long and display a nice twirling baton for the duration. But the (presumably asynchronous) thing we are waiting for might not finish in time, or it might finish much sooner. Shouldn't we be polling something somewhere in the loop, to see if we can stop waiting? Maybe not on every iteration, but every five seconds or so?

In some cases, yes. In the case that I am writing the script for, no. For what I am writing the script for, it is just overkill. I appreciate the thought though, I was thinking of going that route, and decided against it because in the end it wasnt that big of a deal.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top