我使用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)
}
答案 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