如何在ruby中检测按键 w/o getc/gets?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (26)

我有一个简单的任务需要等待文件系统上的某些内容改变(它本质上是一个原型编译器)。所以我有一个简单的无限循环,检查更改后的文件后,等5秒。

loop do
  # if files changed
  #   process files
  #   and puts result
  sleep 5
end

不是Ctrl+C,我宁愿能够测试并看看是否按了一个键,而不阻止循环。从本质上讲,我只需要一种方法来判断是否有传入的按键,然后以一种方式抓住它们直到遇到Q,然后退出程序。

我想要的是:

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不能做的?

提问于
用户回答回答于

在基于unix的系统中很容易:

system("stty raw -echo") #=> Raw mode, no echo
char = STDIN.getc
system("stty -raw echo") #=> Reset terminal mode
puts char

require 'Win32API'
char = Win32API.new('crtdll','_getch', [], 'L').Call

用户回答回答于

这里有一种方法,使用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."

扫码关注云+社区