Pergunta

Como posso obter um único caractere do teclado do terminal com Ruby sem pressionar entrar? Tentei Curses::getch, mas que realmente não trabalho para mim.

Foi útil?

Solução

http: //blade.nagaokaut. ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/2999

#!/usr/bin/ruby

begin
  system("stty raw -echo")
  str = STDIN.getc
ensure
  system("stty -raw echo")
end
p str.chr

(Testado no meu sistema OS X, pode não ser portátil para todas as plataformas Ruby). Consulte http://www.rubyquiz.com/quiz5.html para algumas sugestões adicionais, inclusive para do Windows.

Outras dicas

Desde ruby ??2.0.0, há um 'io / console' no stdlib com esse recurso

require 'io/console'
STDIN.getch

@Jay deu uma grande resposta, mas há dois problemas:

  1. Você pode atrapalhar estado tty padrão;
  2. Você ignora caracteres de controle (^ C para SIGINT, etc).

Uma solução simples para isso é para salvar estado tty anterior e uso os seguintes parâmetros:

  • -icanon - Entrada canônica disable (ERASE e processamento matar);
  • isig -. Permitir a verificação dos personagens contra os caracteres especiais de controle INTR, sair, e SUSP

No final, você teria uma função como esta:

def get_char
  state = `stty -g`
  `stty raw -echo -icanon isig`

  STDIN.getc.chr
ensure
  `stty #{state}`
end

modo RAW (stty raw -echo) infelizmente faz com control-C para se enviada em como um personagem, não como um SIGINT. Então se você quer bloquear entrada como acima, mas permitir que o usuário pressione Control-C para parar o programa enquanto ele está esperando, certifique-se de fazer isso:

Signal.trap("INT") do # SIGINT = control-C
  exit
end

E se você quiser entrada non-blocking - isto é, verificar periodicamente se o usuário pressionou uma chave, mas, entretanto, ir fazer outras coisas - então você pode fazer isso:

require 'io/wait'

def char_if_pressed
  begin
    system("stty raw -echo") # turn raw input on
    c = nil
    if $stdin.ready?
      c = $stdin.getc
    end
    c.chr if c
  ensure
    system "stty -raw echo" # turn raw input off
  end
end

while true
  c = char_if_pressed
  puts "[#{c}]" if c
  sleep 1
  puts "tick"
end

Note que você não precisa de um manipulador de SIGINT especial para a versão sem bloqueio desde o tty é apenas no modo cru por um momento breve.

Nota:. Este é e velha resposta ea solução não funciona na maioria dos sistemas

Mas a resposta ainda poderia ser útil para alguns ambientes, onde os outros métodos não funcionam. Por favor, leia os comentários abaixo.


Primeiro você tem que instalar o highline:

gem install highline

Em seguida, tente se o método highline funciona para você:

require "highline/system_extensions"
include HighLine::SystemExtensions

print "Press any key:"
k = get_character
puts k.chr

E se você está construindo maldições aplicativo, você precisa chamar

nocbreak

http: //www.ruby-doc.org/stdlib-1.9.3/libdoc/curses/rdoc/Curses.html#method-c-cbreak

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top