EventMachine如何在keypress上编写键盘处理程序

时间:2013-01-23 07:12:07

标签: ruby eventmachine

我使用EventMachine LineText2协议,每当我按下键盘上的字符时,我想触发receive_line方法,而不是在我输入新行时。有没有办法改变这种默认行为?

class KeyboardHandler < EM::Connection
  include EM::Protocols::LineText2

  def initialize(q)
    @queue = q
  end

  def receive_line(data)
    @queue.push(data)
  end
end

EM.run {
  q = EM::Queue.new

  callback = Proc.new do |line|
    # puts on every keypress not on "\n"
    puts line
    q.pop(&callback)
  end
  q.pop(&callback)

  EM.open_keyboard(KeyboardHandler, q)
}

3 个答案:

答案 0 :(得分:5)

如果要从终端接收无缓冲输入,则应在标准输入上关闭规范模式。 (我还关闭了echo以使屏幕更易于阅读。)在代码调用#open_keyboard之前或在处理程序初始化程序中添加:

require 'termios'
# ...
attributes = Termios.tcgetattr($stdin).dup
attributes.lflag &= ~Termios::ECHO # Optional.
attributes.lflag &= ~Termios::ICANON
Termios::tcsetattr($stdin, Termios::TCSANOW, attributes)

例如:

require 'termios'
require 'eventmachine'

module UnbufferedKeyboardHandler
  def receive_data(buffer)
    puts ">>> #{buffer}"
  end
end

EM.run do
  attributes = Termios.tcgetattr($stdin).dup
  attributes.lflag &= ~Termios::ECHO
  attributes.lflag &= ~Termios::ICANON
  Termios::tcsetattr($stdin, Termios::TCSANOW, attributes)

  EM.open_keyboard(UnbufferedKeyboardHandler)
end

答案 1 :(得分:0)

之前我没有使用过EventMachine,但是this page on the EventMachine wiki似乎表明你不应该使用LineText2协议,因为它听起来你不想要缓冲线。

他们举了这个例子:

module MyKeyboardHandler
  def receive_data(keystrokes)
    puts "I received the following data from the keyboard: #{keystrokes}"
  end
end

EM.run {
  EM.open_keyboard(MyKeyboardHandler)
}

这会给你你想要的吗?

答案 2 :(得分:0)

这是Ruby 2.0+的更新。在Ruby 2.0中,我们获得了io/console,这使得处理原始键盘变得更加容易,并且它是跨平台的。

这是一个使用io/console对原始键盘事件做出反应的工作示例:

require 'io/console'
require 'eventmachine'

module KB
  def receive_data(d)
    puts "GOT: #{d}\r"

    # CTRL-C will not work in raw mode, so we need another way to exit    
    EM::stop if d == 'q'
  end
end

begin
  EM.run {
    # Put console in raw mode (no echo, no line buffering)
    IO.console.raw!
    EM.open_keyboard(KB)
  }
ensure
  # Ensure cooked, otherwise console will be unusable after exit
  IO.console.cooked!
end