JayTarka
JayTarka

Reputation: 571

Simultaneous progress bars

This script creates a pseudo progress bar:

bar, bar2 = '', ''
10.times do |i|
  bar << '='
  bar2 << '**'
  print "#{bar} - #{i+1}0%\r"
  #print "#{bar2} - #{i+1}0%\r"
  sleep 0.3
end

10 = appear in the bottom left of the screen before it completes.

I want to create two simultaneous loading bars. So as you can see, I've created bar2 that creates 20 * before it completes.

Both work fine, but not simultaneously! If I uncomment both print commands, I print both bars, only the bar2 is shown, bar1 doesn't show up at all.

I'm guessing this is because the \r returns the "cursor" to the start of the line and overrides bar with bar2's progress.

I've tried utilizing a \n, but all text preceding the \n is not wiped. Again, this is because \r is carriage return that can't get before a new line, so while the first loop actually works perfectly, bar's progress (and a \n) stays on the screen, causing this effect:

> = - 10%
> == - 20%
> === - 30%%
> ==== - 40%0%
> ===== - 50%40%
> ====== - 60% 50%
> ======= - 70%- 60%
> ======== - 80% - 70%
> ========= - 90%* - 80%
> ========== - 100%* - 90%

So how do I create two simultaneous loading bars? Or indeed an infinite number of simultaneous loading bars? I'm testing in gnome-terminal but I'd like a solution that works in most, if not all, modern terminals.

Upvotes: 3

Views: 219

Answers (2)

Gavin Miller
Gavin Miller

Reputation: 43825

Given @ndn's answer I'm thinking that it may be system and/or shell specific. I used the control character \033[1A to move the cursor back one line:

# Tested on Mac & CentOS w/ Bash
bar, bar2 = '', ''
10.times do |i|
  bar << '='
  bar2 << '**'
  puts  "#{bar} - #{i+1}0%"
  print "#{bar2} - #{i+1}0%"
  print "\033[1A\r"
  sleep 0.3
end

You can use this page on Cursor Movement to do all sorts of things!

Upvotes: 1

ndnenkov
ndnenkov

Reputation: 36100

This is a pretty cool little problem. Basically, you got it right that you can overwrite the current line with \r. Now you just need a character, which can jump back to the previous line. You can use "\033[F" for that:

bar, bar2 = '', ''
10.times do |i|
  bar << '='
  bar2 << '**'
  puts  "#{bar} - #{i+1}0%"
  print "#{bar2} - #{i+1}0%"
  print "\033[F\r"
  sleep 0.3
end

Upvotes: 1

Related Questions