# Printing right arrow vs. a sane progressbar library

**URL:** <https://www.ruby-forum.com/t/printing-right-arrow-vs-a-sane-progressbar-library/153922>\
**Category:** Ruby\
**Created:** [November 23, 2008, 2:22am UTC](https://www.ruby-forum.com/t/printing-right-arrow-vs-a-sane-progressbar-library/153922 "2008-11-23T02:22:44Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Shot\_SPiotr\_S.S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/e79b87/32.png) [@Shot\_SPiotr\_S.S](https://www.ruby-forum.com/u/Shot_SPiotr_S.S)\
**Post date:** [November 23, 2008, 2:22am UTC](https://www.ruby-forum.com/t/printing-right-arrow-vs-a-sane-progressbar-library/153922/1 "2008-11-23T02:22:44Z")

</div>

I want to track the progress of a set of (forkoffâ€™d) processes in  
a simple way. What I have in mind is a line of dots equal in length  
to the number of processes, and once a process number X finishes,  
it prints \r, then advances X characters to the right and prints o  
â€“ so after three of eight processes finish, it could look like …o…oo.

The closest I got is the below (in one line, so easily pastable to IRB):

print ‘.’ \* 25; (0…25).sort\_by{rand}.each { |n| print “\r”; print  
“\c[[C” \* n; print ‘o’; sleep 0.5 }; print “\n”

It seems to work in IRB and in a script (after $stdout.sync = true),  
unless the number of processes is larger than the terminal windowâ€™s  
width.

Is this a sane method of doing what I want to do, or does  
it just â€˜happens to workâ€™ in GNOME Terminal on my Ubuntu?

Is there a saner way to advance by a char than printing the right arrow?

On a similar note: Is there a simple progressbar library for Ruby  
(ideally if itcan be somehow used with forkoffâ€™d processes, but Iâ€™m  
aware itâ€™d require some kind of passing of state to the outside of the  
block)?

Is there anything else than Ruby/ProgressBarÂ¹ (say, in a gemâ€¦)?

Â¹ [Ruby/ProgressBar: A Text Progress Bar Library for Ruby](http://0xcc.net/ruby-progressbar/)

(Iâ€™m aware the above is prone to a race condition if two processes  
finish at the same time and the second one of them prints its \r  
before the first one prints its o, but letâ€™s disregard this for now.)

– Shot

---

<div class="post-metadata">

**Author:** ![Shot\_SPiotr\_S.S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/e79b87/32.png) [@Shot\_SPiotr\_S.S](https://www.ruby-forum.com/u/Shot_SPiotr_S.S)\
**Post date:** [November 23, 2008, 2:57am UTC](https://www.ruby-forum.com/t/printing-right-arrow-vs-a-sane-progressbar-library/153922/2 "2008-11-23T02:57:48Z")

</div>

On Nov 22, 2008, at 8:18 PM, Shot (Piotr S.) wrote:

> print ‘.’ \* 25; (0…25).sort\_by{rand}.each { |n| print “\r”; print  
> arrow?  
> status=‘.’\*25; print status; (0…25).sort\_by{rand}.each{|n|  
> status[n]=‘o’; print “\r#{status}”; sleep(0.1+rand/10.0)};puts

While it still has trouble with more values that screen columns, it  
should be a bit better with race conditions. You could, perhaps, add  
a clear-to-EOL sequence, too.

-Rob

> (I’m aware the above is prone to a race condition if two processes  
> finish at the same time and the second one of them prints its \r  
> before the first one prints its o, but let’s disregard this for now.)
> 
> ## – Shot
> 
> If I was to use Bugzilla when I was a tester, I’d quit  
> and become a gardener. – a Syllable OS developer

Rob B. [http://agileconsultingllc.com](http://agileconsultingllc.com)  
removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![Shot\_SPiotr\_S.S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/e79b87/32.png) [@Shot\_SPiotr\_S.S](https://www.ruby-forum.com/u/Shot_SPiotr_S.S)\
**Post date:** [November 23, 2008, 6:36pm UTC](https://www.ruby-forum.com/t/printing-right-arrow-vs-a-sane-progressbar-library/153922/3 "2008-11-23T18:36:09Z")

</div>

Rob B.:

> On Nov 22, 2008, at 8:18 PM, Shot (Piotr S.) wrote:

> > I want to track the progress of a set of  
> > (forkoffâ€™d) processes in a simple way. [â€¦]

> > print ‘.’ \* 25; (0…25).sort\_by{rand}.each { |n| print “\r”; print “\c[[C” \* n; print ‘o’; sleep 0.5 }; print “\n”

> status=’.’\*25; print status; (0…25).sort\_by{rand}.each{|n| status[n]=‘o’;  
> print “\r#{status}”; sleep(0.1+rand/10.0)};puts

A very good idea, but unfortunately it doesnâ€™t work in a forkoffâ€™d  
block; every block gets its own copy of the original status and so  
generates a line with 24 dots and one o:

shot@devielle:~$ irb -rubygems

> > require ‘forkoff’  
> > =\> true
> 
> > status=’.’\*25; print status; (0…25).sort\_by{rand}.forkoff{|n| status[n]=‘o’; print “\r#{status}”; sleep(0.1+rand/10.0)};puts  
> > …o…  
> > =\> nil

Hence my need for a right arrow, or for printing a â€˜transparentâ€™  
character that doesnâ€™t overwrite whatâ€™s already under the cursor.

> You could, perhaps, add a clear-to-EOL sequence, too.

Iâ€™m sorry, but Iâ€™m a bit braindead today; where would I want to use  
this? (And, when weâ€™re at it, whatâ€™s the escape sentence for it?)

Thanks a lot for your interest in this thread and your reply!

– Shot

---

<div class="post-metadata">

**Author:** ![Shot\_SPiotr\_S.S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/e79b87/32.png) [@Shot\_SPiotr\_S.S](https://www.ruby-forum.com/u/Shot_SPiotr_S.S)\
**Post date:** [November 23, 2008, 11:27pm UTC](https://www.ruby-forum.com/t/printing-right-arrow-vs-a-sane-progressbar-library/153922/4 "2008-11-23T23:27:20Z")

</div>

On Nov 23, 2008, at 12:30 PM, Shot (Piotr S.) wrote:

> > status[n]=‘o’;
> > 
> > > status[n]=‘o’; print “\r#{status}”; sleep(0.1+rand/10.0)};puts  
> > > …o…  
> > > =\> nil
> 
> Hence my need for a right arrow, or for printing a ‘transparent’  
> character that doesn’t overwrite what’s already under the cursor.

I took a quick look at the code for forkoff and unless you’re  
increasing the processes (or just looking for one that is “slow”),  
this doesn’t seem to help much.

> > You could, perhaps, add a clear-to-EOL sequence, too.
> 
> I’m sorry, but I’m a bit braindead today; where would I want to use  
> this? (And, when we’re at it, what’s the escape sentence for it?)

That sequence and other ANSI control sequences can be found via the  
web, for example, at:  
[ANSI escape code - Wikipedia](http://en.wikipedia.org/wiki/ANSI_escape_code)

> Thanks a lot for your interest in this thread and your reply!
> 
> ## – Shot
> 
> A distributed system is one in which I cannot get something done  
> because  
> a machine I’ve never heard of is down. – Leslie  
> Lamport

Perhaps a sequence of:  
“[[s[[#{n+1}Go[[u”  
if your terminal supports the save/restore cursor position

print ‘.’ \* 25; (0…25).sort\_by{rand}.forkoff { |n| sleep(0.25+rand/  
10.0); print “\033[s\033[#{n+1}Go\033[u” }; print “\n”

Or manually go back to the “end” of the line each time:  
“\033[#{n+1}Go\033[#{25+1}G”

print ‘.’ \* 25; (0…25).sort\_by{rand}.each { |n| sleep(0.2+rand/2.0);  
print “\033[#{n+1}Go\033[26G” }; print “\n”

Perhaps get the status via some other mechanism in another process  
(but that’s going to fly away from a “simple way” even faster).

-Rob

Rob B. [http://agileconsultingllc.com](http://agileconsultingllc.com)  
removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![Shot\_SPiotr\_S.S](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/s/e79b87/32.png) [@Shot\_SPiotr\_S.S](https://www.ruby-forum.com/u/Shot_SPiotr_S.S)\
**Post date:** [November 24, 2008, 1:05am UTC](https://www.ruby-forum.com/t/printing-right-arrow-vs-a-sane-progressbar-library/153922/5 "2008-11-24T01:05:39Z")

</div>

Rob B.:

> On Nov 23, 2008, at 12:30 PM, Shot (Piotr S.) wrote:

> > A very good idea, but unfortunately it doesnâ€™t work in a forkoffâ€™d  
> > block; every block gets its own copy of the original status and so  
> > generates a line with 24 dots and one o [â€¦]

> > Hence my need for a right arrow, or for printing a â€˜transparentâ€™  
> > character that doesnâ€™t overwrite whatâ€™s already under the cursor.

> I took a quick look at the code for forkoff and unless you’re  
> increasing the processes (or just looking for one that is “slow”),  
> this doesn’t seem to help much.

Erm, Iâ€™m not sure what doesnâ€™t seem to help much. 🙂 Using the right  
arrow trick works as expected (as opposed to editing a string thatâ€™s  
unfortunately not the same object across the processes):

shot@devielle:~$ irb -rubygems

> > require ‘forkoff’  
> > =\> true  
> > print ‘.’ \* 25; (0…25).sort\_by{rand}.forkoff { |n| print “\r”; print “\c[[C” \* n; print ‘o’; sleep 0.5 }; print “\n”  
> > ooooooooooooooooooooooooo  
> > =\> nil

(Although itâ€™s more prone to race conditions than your solutions below.)

In my actual case, I want a general mechanism that runs parallel  
processes in some way (forkoff for now, maybe DRb in the future)  
and report back some kind of a visual information on how much is  
being done over time.

As I assume each of such parallel runs wonâ€™t be able to access the  
actual objects outside the forked-off block (only copies of them),  
I believe I canâ€™t employ a simple, tick-based progressbar; the above  
was my idea to side-step the need of communication with the parent  
(although I could perhaps make the code that collectsÂ¹ the returned  
values trigger/tick the progressbar as soon as a result comes inâ€¦).

Â¹ forkoff has this nice feature that it handles the collecting of the  
returned values transparently, so I simply donâ€™t _have_ any code that  
collects the results at the momentâ€¦

> That sequence and other ANSI control sequences can be found via the  
> web, for example, at: [ANSI escape code - Wikipedia](http://en.wikipedia.org/wiki/ANSI_escape_code)

Ah, thank you! I started this quest by recalling how \b and \r work,  
which led me to the ASCII control characters; I totally forgot to  
look at ANSI stuff, just recalled I can come up with the sequence  
for the right arrow by `cat`ing stdin to a file and then looking  
at it. I shouldâ€™ve thought â€˜ANSI!â€™ when I saw ^[[C. 🙂

> Perhaps a sequence of:  
> “[[s[[#{n+1}Go[[u”  
> if your terminal supports the save/restore cursor position

> Or manually go back to the “end” of the line each time:  
> “\033[#{n+1}Go\033[#{25+1}G”

Actually, a simple “\033[#{n+1}Go” works well enough; thanks! The trick  
with going to the end of the line each time makes it easier on the eyes  
if the cursor is visible, so Iâ€™ll most probably end up using it. Thanks  
again!

(And just before sending this email I found out that “\033[?25l” makes  
the cursor disappear, and so seems to be the cleanest solution without  
any output-related race conditions whatsoever.) 🙂

– Shot
