在控制台打印一个ASCII旋转的“光标”

时间:2022-10-25 07:47:49

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.

我有一个Ruby脚本,它做了一些很长的工作。它只是命令行,我希望显示脚本仍然在运行,而不是停止。我过去喜欢所谓的“旋转光标”,我设法在Windows下的Ruby中复制它。

Question: does this work in the other OS's? If not, is there an OS-independent way to accomplish this?

这个在其他操作系统中有用吗?如果没有,是否有一个独立于操作系统的方法来实现这一点?

No IRB solutions please.

请没有IRB的解决方案。

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"
}

3 个解决方案

#1


34  

Yes, this works on Windows, OS X, and Linux. Improving on Niklas' suggestion, you can make this more general like so:

是的,这适用于Windows、OS X和Linux。根据Niklas的建议进行改进,您可以使其更一般化如下:

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!

#2


4  

# 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

#3


3  

I wrote a gem spin_to_win that displays a spinner while yielding a block. For example:

我编写了一个gem spin_to_win,它在生成一个块时显示一个spinner。例如:

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!]

#1


34  

Yes, this works on Windows, OS X, and Linux. Improving on Niklas' suggestion, you can make this more general like so:

是的,这适用于Windows、OS X和Linux。根据Niklas的建议进行改进,您可以使其更一般化如下:

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!

#2


4  

# 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

#3


3  

I wrote a gem spin_to_win that displays a spinner while yielding a block. For example:

我编写了一个gem spin_to_win,它在生成一个块时显示一个spinner。例如:

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!]