Create the loading three little dots - ruby

Hello how can I make the three dot loading (...), so that it does something like this except without making a new line everytime:
Loading
Loading.
Loading...
Loading..
Loading.
and so on:
This is what I came up with, only problem is that I can't remove the dots one by one if loading continues for more than 1.5 seconds.
puts "Sending"
sleep(0.5)
print "."
sleep(0.5)
print "."
sleep(0.5)
print "."
Hopefully I am clear enough.
Thank you for your help.

10.times do |i|
print "Sending." + ("." * (i % 3)) + " \r"
$stdout.flush
sleep(0.5)
end
So, how does this work?
10.times do |i|
Repeat the following code 10 times, with the variable i indicating the current iteration (0, 1, 2, 3, 4...)
print "Sending." + ("." * (i % 3)) + " \r"
Print the phrase "Sending." followed by a couple of things:
("." * (i % 3)) repeats ("multiplies") the string "." several times, specifically i % 3, which is the remainder of i when it's divided by 3. So when i is 7, i % 3 is 1.
"\r" moves the cursor back to the beginning of the line without making a new line. If you think of a typewriter, it's like returning the carriage (the bit that types) to the beginning of the line so that you can type over the same line again. It's a carriage return.
$stdout.flush
Make sure the data prints.
sleep(0.5)
Sleep for half a sec.

You can try with $stdout.flush:
def loading number_of
number_of.times do |t|
print "Sending#{'.' * (t % 4)} \r"
$stdout.flush
sleep 0.5
end
end
Demonstration

Related

Make words move in real time in ruby on in the terminal

Is there a way words move/animate letters moving in time? For example:
LOVEX
I want to X to move between the other letters like.
LOVXE
LOXVE
LXOVE
but with one condition: I don't want to output new lines or entering new words, I want it to be on the same word in a single line so it looks kind of like a gif.
If you want this to just print on the terminal this should work. Write this in a file called lovex.rb
# lovex.rb
love = 'LOVE'
print love
[*0..4].reverse.each do |i|
sleep 1
love = love.gsub('X','')
love.insert(i, 'X')
print "\r"
if i > 0
print love
else
print 'LOVE'
end
end
Then in your terminal just run:
ruby lovex.rb
I've taken #lacostenycoder's idea and implemented it in a slightly different way.
def word_line_boogie(word, ntimes, delay)
enum = (0.upto(word.size)).map do |i|
("\r"+word.dup).insert(-i-1,'X')
end.cycle
ntimes.times do
print enum.next
sleep delay
end
end
word_line_boogie('LOVE', 10, 1)
displays
LOVEX
LOVXE
LOXVE
LXOVE
XLOVE
LOVEX
LOVXE
LOXVE
LXOVE
XLOVE
except all but the first word is overwrites the previous one.
For word = 'LOVE',
enum
#=> #<Enumerator: ["\rLOVEX", "\rLOVXE", "\rLOXVE",
# "\rLXOVE", "\rXLOVE"]:cycle>
10.times.map { enum.next }
#=> ["\rLOVEX", "\rLOVXE", "\rLOXVE", "\rLXOVE", "\rXLOVE",
# "\rLOVEX", "\rLOVXE", "\rLOXVE", "\rLXOVE", "\rXLOVE"]

Restarting a loop from the top

I have the following:
text_counter = 0
MAXTEXT_COUNTER = 10
puts "hello, this will start"
loop do
puts "hello"
text_counter += 1
sleep(2)
if text_counter >= MAXTEXT_COUNTER
break
end
end
sleep(7200)
print "ended test"
Once the break has happened, how can I get it to start again from the top?
I'm now thinking I could nest this loop in an until loop with the condition of text_counter == 1000. This would break, then sleep for 2 hours, then start again until it hits 1000.
It looks like you need a loop within a loop where you repeat one N times, the other M times:
MAXTEXT_COUNTER = 10
puts "hello, this will start"
loop do
MAXTEXT_COUNTER.times do
puts "hello"
sleep(2)
end
print "ended test"
sleep(7200)
end
The outer loop is perpetual. The inner one runs a certain number of times and stops using the times method.
You're looking for next
It functions similarly to break, but returns control back to the top of the loop. It's great for creating flat control flow.
For example
0.upto(100) do |i|
if i % 7 == 0
puts "#{i} is a multiple of 7"
next
end
puts i
end
There is a retry keyword which repeats the loop from top, just what you've asked.
Or you can wrap your loop into a method and continuously call that method.

What's wrong with the following code on ruby continuation?

New to ruby here. Tried to write a simple ruby code to do continuation, but the following code will print non-stopping integers 2,3, 4, 5, 6 ... (one number in each line). There must be an obvious bug here. Thanks.
require "continuation"
def dum ()
i = 1
callcc {|cc| $c = cc}
i += 1
puts i
end
dum() #expect to print 2
$c.call #expect to print 3
$c.call #expect to print 4
My ruby interpreter is 1.9.3p0
$c.call makes a complete jump back to the set execution context, so your script is repeatedly alternating between the call to dum() and the first line invoking $c.call, never reaching the last line. Here's the flow:
The dum() method is defined
dum() #expect to print 2: The script invokes dum() once, which sets an execution context for $c and then prints 2
$c.call #expect to print 3 jumps back into the call to dum() from the previous line -- the top level context of execution literally moves back to the previous line. This time dum() prints 3
The script now reaches the same $c.call #expect to print 3 line AGAIN, and will continue to infinitely alternate between these two lines.
The script will never reach your last line $c.call #expect to print 4.
One way to modify your script so that it produces the expected output:
require "continuation"
def dum ()
i = 1
callcc {|cc| $c = cc}
i += 1
puts i
return i
end
k = dum() #expect to print 2
$c.call unless k >= 4 # reach this line 3 times: print 3, and then 4, and then move on
I hope this helps.

Printing an ASCII spinning "cursor" in the console

I have a Ruby script that does some long taking jobs. It is command-line only and I would like to show that the script is still running and not halted. I used to like the so called "spinning cursor" in the old days and I managed to reproduce it in Ruby under Windows.
Question: does this work in the other OS's? If not, is there an OS-independent way to accomplish this?
No IRB solutions please.
10.times {
print "/"
sleep(0.1)
print "\b"
print "-"
sleep(0.1)
print "\b"
print "\\"
sleep(0.1)
print "\b"
print "|"
sleep(0.1)
print "\b"
}
Yes, this works on Windows, OS X, and Linux. Improving on Niklas' suggestion, you can make this more general like so:
def show_wait_cursor(seconds,fps=10)
chars = %w[| / - \\]
delay = 1.0/fps
(seconds*fps).round.times{ |i|
print chars[i % chars.length]
sleep delay
print "\b"
}
end
show_wait_cursor(3)
If you don't know how long the process will take, you can do this in another thread:
def show_wait_spinner(fps=10)
chars = %w[| / - \\]
delay = 1.0/fps
iter = 0
spinner = Thread.new do
while iter do # Keep spinning until told otherwise
print chars[(iter+=1) % chars.length]
sleep delay
print "\b"
end
end
yield.tap{ # After yielding to the block, save the return value
iter = false # Tell the thread to exit, cleaning up after itself…
spinner.join # …and wait for it to do so.
} # Use the block's return value as the method's
end
print "Doing something tricky..."
show_wait_spinner{
sleep rand(4)+2 # Simulate a task taking an unknown amount of time
}
puts "Done!"
This one outputs:
Doing something tricky...|
Doing something tricky.../
Doing something tricky...-
Doing something tricky...\
(et cetera)
Doing something tricky...done!
# First define your chars
pinwheel = %w{| / - \\}
# Rotate and print as often as needed to "spin"
def spin_it
print "\b" + pinwheel.rotate!.first
end
EDIT from peter: here a working version
def spin_it(times)
pinwheel = %w{| / - \\}
times.times do
print "\b" + pinwheel.rotate!.first
sleep(0.1)
end
end
spin_it 10
I wrote a gem spin_to_win that displays a spinner while yielding a block. For example:
SpinToWin.with_spinner('Zzzz') do |spinner|
spinner.banner('sleepy')
sleep 1
end
Zzzz \ [sleepy]
It can also track work pending vs. work completed:
SpinToWin.with_spinner('Zzzz') do |spinner|
spinner.increment_todo!(3)
spinner.banner('snore')
sleep 1
spinner.increment_done!
spinner.banner('dream')
sleep 1
spinner.increment_done!
spinner.banner('wake up!')
sleep 1
spinner.increment_done!
end
Zzzz \ 3 of 3 [wake up!]
I use rainbow gem to print color-changing string to indicate the code is working.
require 'rainbow'
def self.print_with_random_color
content = "I am still working on it. Please wait..."
colors = ["aqua","chartreuse","crimson","fuchsia","gold","lawngreen","palegoldenrod","powderblue","sandybrown","deepskyblue"]
loop do
print Rainbow("[#{Time.now}] " + content).send(colors.sample)
(content.length + 1).times {print "\r"}
sleep 0.3
end
end

How can I print a multiline string in the same place multiple times?

I am using Ruby.
I have a string with multiple lines. I want to print that multiple-lines-string in the same place multiple times.
The reason I want to do that is because the string represents information that is going to be updated several times.
How can I accomplish this?
As an option:
3.times do |i|
print str = "string#{i}\nstring#{i}\nstring#{i}\n"
sleep 1 # just for test
system('clear')
end
You could use uses curses to handle your output but that would probably be overkill for something simple like this.
The usual way is to print out a bunch of backspaces to reposition the output cursor at the beginning of your last string; be aware that "\b" doesn't necessarily overwrite anything so you'll have to overwrite the end with spaces to be safe. Something like this:
messages = [
'Professionally simplify seamless systems with prospective benefits.',
'Dramatically cultivate worldwide testing procedures for robust potentialities.',
'Intrinsicly provide access to future-proof testing procedures after superior supply chains.',
'Globally matrix multidisciplinary outsourcing vis-a-vis distributed paradigms.',
'Compellingly fashion visionary content via functionalized web services.',
'Phosfluorescently e-enable e-markets rather than internal or "organic" sources.'
]
reposition = ''
clear_the_end = ''
(0 ... messages.length).each do |i|
if(i > 0)
clear_the_end = ' ' * [0, messages[i - 1].length - messages[i].length].max
end
$stdout.syswrite(reposition + messages[i] + clear_the_end)
reposition = "\b" * (messages[i].length + clear_the_end.length)
sleep 1
end
puts
You'll want to use syswrite to avoid buffering and the usual "\n" that puts appends. This sort of thing should work in any terminal that you're likely to come across.
You could also use a carriage return ("\r") instead of a bunch of backspaces:
# `reposition = "\b" * (messages[i].length + clear_the_end.length)` becomes
resposition = "\r"
But you'll still need all the clear_the_end fiddling to make sure you overwrite all of the last line.
This will work however in Terminal.app on Mac OS X Lion the 1 character of each line is cleared on exit. I think this is a bug of Terminal.app.
CR = "\r"
CLEAR = "\e[0J"
RESET = CR + CLEAR
lines_count = 3
3.times do |i|
puts "First line #{i}"
puts "Second line #{i}"
puts "Third line #{i}"
sleep(1)
$stdout.flush
lines_count.times do
print "\e[1F"
print "\e[1K"
end
end
print "\e[#{lines_count}E"

Resources