【问题标题】:EventMachine how to write keyboard handler reacting on keypressEventMachine如何编写对按键做出反应的键盘处理程序
【发布时间】:2013-01-06 14:39:24
【问题描述】:

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

【问题讨论】:

    标签: ruby eventmachine


    【解决方案1】:

    我以前没有使用过 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)
    }
    

    这能满足你的需求吗?

    【讨论】:

    • 不,我仍然必须插入“\n”才能receive_data。我找到了一种使用 highline gem 和 EM.defer 不制动反应器的方法,但我对这个解决方案并不完全满意。
    【解决方案2】:

    如果你想从终端接收无缓冲的输入,你应该关闭标准输入的规范模式。 (我还关闭了 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
    

    【讨论】:

    • 非常感谢这个解决方案!
    • 正是我想要的。谢谢。不过,提及这需要宝石会很有帮助。
    【解决方案3】:

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

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

    require 'io/console'
    require 'eventmachine'
    
    module KB
      def receive_data(key)
        puts "GOT: #{key}\r"
    
        # CTRL-C will not work in raw mode, so we need another way to exit.    
        EM::stop if key == '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
    

    【讨论】:

      猜你喜欢
      • 2021-09-10
      • 2015-05-17
      • 1970-01-01
      • 2012-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-27
      • 2015-01-27
      相关资源
      最近更新 更多