在Ruby中没有getc/get的情况下检测按键(非阻塞) [英] Detect key press (non-blocking) w/o getc/gets in Ruby
问题描述
我有一个简单的任务,需要等待文件系统上的某些更改(它本质上是原型的编译器).因此,在检查文件更改后,我有一个简单的无限循环,有5秒钟的睡眠时间.
I have a simple task that needs to wait for something to change on the filesystem (it's essentially a compiler for prototypes). So I've a simple infinite loop with a 5 second sleep after the check for changed files.
loop do
# if files changed
# process files
# and puts result
sleep 5
end
我希望能够测试并查看是否已按下某个键,而不会阻塞循环,而不是Ctrl+C
致敬.本质上,我只需要一种方法来判断是否有传入的按键,然后一种方法来抓住它们直到遇到Q,然后退出程序.
Instead of the Ctrl+C
salute, I'd rather be able to test and see if a key has been pressed, without blocking the loop. Essentially I just need a way to tell if there are incoming key presses, then a way to grab them until a Q is met, then exit out of the program.
我想要的是:
def wait_for_Q
key_is_pressed && get_ch == 'Q'
end
loop do
# if files changed
# process files
# and puts result
wait_for_Q or sleep 5
end
或者,这是Ruby不会做的(好)吗?
Or, is this something Ruby just doesn't do (well)?
推荐答案
这是使用IO#read_nonblock
的一种方法:
def quit?
begin
# See if a 'Q' has been typed yet
while c = STDIN.read_nonblock(1)
puts "I found a #{c}"
return true if c == 'Q'
end
# No 'Q' found
false
rescue Errno::EINTR
puts "Well, your device seems a little slow..."
false
rescue Errno::EAGAIN
# nothing was ready to be read
puts "Nothing to be read..."
false
rescue EOFError
# quit on the end of the input stream
# (user hit CTRL-D)
puts "Who hit CTRL-D, really?"
true
end
end
loop do
puts "I'm a loop!"
puts "Checking to see if I should quit..."
break if quit?
puts "Nope, let's take a nap"
sleep 5
puts "Onto the next iteration!"
end
puts "Oh, I quit."
请记住,即使它使用非阻塞IO,它仍然是缓冲 IO.
这意味着您的用户必须先按Q
然后按<Enter>
.如果你想做
无缓冲的IO,建议您检查ruby的curses库.
Bear in mind that even though this uses non-blocking IO, it's still buffered IO.
That means that your users will have to hit Q
then <Enter>
. If you want to do
unbuffered IO, I'd suggest checking out ruby's curses library.
这篇关于在Ruby中没有getc/get的情况下检测按键(非阻塞)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!