How to overwrite a printed line in the shell with Ruby?

20,167

Solution 1

You can use the \r escape sequence at the end of the line (the next line will overwrite this line). Following your example:

require 'time'

loop do
  time = Time.now.to_s + "\r"
  print time
  $stdout.flush
  sleep 1
end

Solution 2

Use the escape sequence \r at the end of the line - it is a carriage return without a line feed.

On most unix terminals this will do what you want: the next line will overwrite the previous line.

You may want to pad the end of your lines with spaces if they are shorter than the previous lines.

Note that this is not Ruby-specific. This trick works in any language!

Solution 3

Here is an example I just wrote up that takes an Array and outputs whitespace if needed. You can uncomment the speed variable to control the speed at runtime. Also remove the other sleep 0.2 The last part in the array must be blank to output the entire array, still working on fixing it.

#@speed = ARGV[0]

strArray = [ "First String there are also things here to backspace", "Second Stringhereare other things too ahdafadsf", "Third String", "Forth String", "Fifth String", "Sixth String", " " ]


#array = [ "/", "-", "|", "|", "-", "\\", " "]

def makeNewLine(array)
    diff = nil
    print array[0], "\r"
    for i in (1..array.count - 1)
        #sleep @speed.to_f
        sleep 0.2
        if array[i].length < array[i - 1].length
             diff = array[i - 1].length - array[i].length
        end
        print array[i]
        diff.times { print " " } if !diff.nil?
        print "\r"
        $stdout.flush

    end
end

20.times { makeNewLine(strArray) }

#20.times { makeNewLine(array)}
Share:
20,167

Related videos on Youtube

Steph Thirion
Author by

Steph Thirion

Updated on December 23, 2021

Comments

  • Steph Thirion
    Steph Thirion over 2 years

    How would I overwrite the previously printed line in a Unix shell with Ruby?

    Say I'd like to output the current time on a shell every second, but instead of stacking down each time string, I'd like to overwrite the previously displayed time.

    • Ulysse BN
      Ulysse BN over 5 years
      Came here looking for a solution for multiple lines, someone has an idea?
  • cam
    cam about 13 years
    Hmm, i like @jsegal's solution better, so choose his answer. Remember to flush your output still.
  • Steph Thirion
    Steph Thirion about 13 years
    I'm divided here, because your answer is a perfectly working snippet of code of what I asked exactly: a solution in Ruby. Yes, it could be more elegant if it used jsegal's suggestion. But a) jsegal's answer is not ruby specific and b) I'd much rather accept an answer with a working snippet. So I'm going to go ahead and edit your answer to reflect jsegal's suggestion, and when/if that edit is accepted, I'll accept your answer and reward jsegal by voting him up. It's the best I can do under this system.
  • Cody Gray
    Cody Gray about 13 years
    @Steph: Your dilemma on which answer to accept seems primarily based on the fact that jsegal's answer didn't include a code snippet. Considering Stack Overflow is not a code sharing site, that seems like a fairly arbitrary requirement. You should upvote both answers if you found them useful, and accept the one that helped you the most in finding the solution that worked for you.
  • Steph Thirion
    Steph Thirion about 13 years
    Thanks for looking into this @Cody. My dilemma is a little more than that, I think I made it pretty clear that this answer is what I asked for (a solution in Ruby). It also meets the S.O. official guidelines: it is the answer that helped me the most. I was stuck until I tried this snippet (turns out I was not flushing). But I believe Stack Overflow is not just about helping one person on a specific moment, it's about building together a reference for the future. Hence my edit. With this in perspective I'll try to submit the edit again.
  • Nathan Long
    Nathan Long about 13 years
    Note that if the text output is wider than the current terminal window, you will start seeing line after line of output again.
  • sunsations
    sunsations about 10 years
    To avoid problems with the current line being short than the previous one. Pad it with the method rjust/ljust e.g. "my output".ljust(80).
  • valk
    valk over 6 years
    I have to emphasize the importance of \r at the end of print (as @jsegal mentioned) otherwise it won't work.
  • Pezholio
    Pezholio over 5 years
    This solution works, but I find putting \r at the beginning of each line works better, otherwise the cursor covers the first character of the output (at least on my terminal). Also, make sure you're using print rather than puts, as puts automatically ends each line with a hard (\r\n) carriage return