3 votes

EventMachine comment écrire un gestionnaire de clavier réagissant à la pression d'une touche

J'utilise le protocole LineText2 d'EventMachine et je voudrais déclencher la méthode receive_line à chaque fois que j'appuie sur une touche de mon clavier et pas seulement lorsque j'entre une nouvelle ligne. Y a-t-il un moyen de modifier ce comportement par défaut?

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|
    # affiche à chaque appui de touche pas sur "\n"
    puts line
    q.pop(&callback)
  end
  q.pop(&callback)

  EM.open_keyboard(KeyboardHandler, q)
}

6voto

jmkeyes Points 2621

Si vous souhaitez recevoir une saisie non tamponnée depuis le terminal, vous devez désactiver le mode canonique sur l'entrée standard. (Je désactive également l'écho pour rendre l'écran plus lisible.) Ajoutez ceci avant que votre code appelle #open_keyboard ou dans votre initialiseur de gestionnaire :

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

Par exemple :

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

1voto

Casper Points 15645

Voici une mise à jour pour Ruby 2.0+. En Ruby 2.0, nous avons io/console, ce qui rend la manipulation du clavier brut beaucoup plus facile, et c'est multiplateforme.

Voici un exemple de travail qui réagit aux événements du clavier brut en utilisant io/console:

require 'io/console'
require 'eventmachine'

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

    # CTRL-C ne fonctionnera pas en mode brut, donc nous avons besoin d'un autre moyen de sortir.    
    EM::stop if key == 'q'
  end
end

begin
  EM.run {
    # Mettre la console en mode brut (pas d'écho, pas de mise en mémoire tampon de ligne).
    IO.console.raw!
    EM.open_keyboard(KB)
  }
ensure
  # Assurez-vous de revenir en mode cuit, sinon la console sera inutilisable après la sortie.
  IO.console.cooked!
end

0voto

jordelver Points 2589

Je n'ai jamais utilisé EventMachine auparavant, mais cette page sur le wiki EventMachine semble indiquer que vous ne devriez pas utiliser le protocole LineText2 car on dirait que vous ne voulez pas de lignes tamponnées.

Ils donnent cet exemple :

module MyKeyboardHandler
  def receive_data(keystrokes)
    puts "J'ai reçu les données suivantes du clavier : #{keystrokes}"
  end
end

EM.run {
  EM.open_keyboard(MyKeyboardHandler)
}

Cela vous donne-t-il ce que vous voulez?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X