【问题标题】:Printing an ASCII spinning "cursor" in the console在控制台中打印一个 ASCII 旋转“光标”
【发布时间】:2012-05-02 23:36:46
【问题描述】:

我有一个 Ruby 脚本可以完成一些耗时的工作。它只是命令行,我想表明脚本仍在运行并且没有停止。以前我很喜欢所谓的“旋转光标”,后来在 Windows 下的 Ruby 中重现了它。

问题:这在其他操作系统中是否有效?如果没有,是否有独立于操作系统的方法来完成此操作?

请不要使用 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"
}

【问题讨论】:

  • 它适用于我所知道的所有重要操作系统,除非打印的字符碰巧导致换行。
  • 适用于 Linux、Ruby 1.8.7...
  • 顺便说一下,这相当于('/-\\|' * 10).each { |c| print c; sleep(0.1); print "\b" }
  • 嗨尼克拉斯,谢谢。但是,您的等效项中有一个错误,它必须是 each_char
  • 如果没有人报告主要操作系统中的问题,我也会接受它作为答案,但请给它几天以确定。你们有谁知道如何在 ruby​​ 中打印旧的 DOS 字符 176 到 178(填充有渐变的光标)?这种方式可能是控制台进度条

标签: ruby command-line progress


【解决方案1】:

是的,这适用于 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)

如果您不知道该过程需要多长时间,您可以在另一个线程中执行此操作:

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

这个输出:

Doing something tricky...|
Doing something tricky.../
Doing something tricky...-
Doing something tricky...\ 
(et cetera)
Doing something tricky...done!

【讨论】:

  • 哇 Phrogz,这很漂亮,已经解决了大部分的实现。你的声明在 WOL 上有效吗,你能测试一下吗?你有虚拟机或者你如何测试它?
  • @peter 你在 Windows 上测试过;我在 OS X 和 Ubuntu 上进行了测试。
  • @peter 请注意,我已将线程代码更新为更简单、更清晰。
  • yield.tap 块应该是函数的ensure 部分。此外,您可以使用 "|/-\\".chars.cycle 来获取字符流,而不是冗长的模逻辑:"|/-\\".chars.cycle.take(seconds.to_i*fps).each { |c| ... }
  • Cool 与this question on SO 结合使用可获取微调器字符,this one 可用于查找 Unicode 字符。我知道它不是 ASCII,但无论如何它很酷,因为现在很多人都有 Unicode 终端
【解决方案2】:
# First define your chars
pinwheel = %w{| / - \\}

# Rotate and print as often as needed to "spin"
def spin_it
  print "\b" + pinwheel.rotate!.first
end

彼得的编辑:这里是一个工作版本

def spin_it(times)
  pinwheel = %w{| / - \\}
  times.times do
    print "\b" + pinwheel.rotate!.first
    sleep(0.1)
  end
end

spin_it 10

【讨论】:

  • 感谢您对 Jason 的贡献,但您测试了吗?它在 W7 上的 ruby​​193 中不起作用
  • Array#rotate! 很漂亮
【解决方案3】:

我写了一个 gem spin_to_win,它在产生一个块的同时显示一个微调器。例如:

SpinToWin.with_spinner('Zzzz') do |spinner| 
  spinner.banner('sleepy')
  sleep 1 
end
Zzzz \ [sleepy]

它还可以跟踪待处理的工作与已完成的工作:

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

【讨论】:

  • Thnx,我在安装您的 gem 后尝试了您的示例(那里没有错误),但两者都出现错误(我在 win7,MRI Ruby 1.9.3)C:/../console/ spin_to_win1.rb:8: 语法错误,意外 $undefined,期待 $end Zzzz \ [sleepy] ^
  • 啊,应该明确最后一部分是微调器的输出。
猜你喜欢
  • 1970-01-01
  • 2018-08-22
  • 1970-01-01
  • 1970-01-01
  • 2011-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-14
相关资源
最近更新 更多