Nerian
Nerian

Reputation: 16197

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?

Upvotes: 1

Views: 1690

Answers (3)

Mario Uher
Mario Uher

Reputation: 12397

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"

Upvotes: 1

mu is too short
mu is too short

Reputation: 434975

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.

Upvotes: 1

Vasiliy Ermolovich
Vasiliy Ermolovich

Reputation: 24637

As an option:

3.times do |i|
  print str = "string#{i}\nstring#{i}\nstring#{i}\n"
  sleep 1 # just for test
  system('clear')
end

Upvotes: 2

Related Questions