ruby getch

ruby - ¿Cómo obtener un solo personaje sin presionar enter?



getch (6)

Nota: Esta es una respuesta anterior y la solución ya no funciona en la mayoría de los sistemas.

Pero la respuesta aún podría ser útil para algunos entornos, donde los otros métodos no funcionan. Por favor, lea los comentarios a continuación.

Primero tienes que instalar Highline:

gem install highline

Luego intente si el método de línea superior le funciona:

require "highline/system_extensions" include HighLine::SystemExtensions print "Press any key:" k = get_character puts k.chr

¿Cómo puedo obtener un solo carácter de teclado desde la terminal con Ruby sin presionar enter? Curses::getch , pero eso realmente no funcionó para mí.


@Jay dio una gran respuesta, pero hay dos problemas:

  1. Puede estropear el estado tty predeterminado;
  2. Ignoras los caracteres de control (^ C para SIGINT, etc.).

Una solución simple para eso es guardar el estado tty anterior y usar los siguientes parámetros:

  • -icanon - deshabilita la entrada canónica (proceso de ERASE y KILL);
  • isig : permite verificar los caracteres contra los caracteres especiales de control INTR, QUIT y SUSP.

Al final tendrías una función como esta:

def get_char state = `stty -g` `stty raw -echo -icanon isig` STDIN.getc.chr ensure `stty #{state}` end


Desde ruby ​​2.0.0, hay una ''io / console'' en el stdlib con esta característica

require ''io/console'' STDIN.getch


El modo stty raw -echo ( stty raw -echo ) desafortunadamente hace que el control-C sea enviado como un caracter, no como un SIGINT. Por lo tanto, si desea bloquear la entrada como se indicó anteriormente, pero permita que el usuario presione el control C para detener el programa mientras espera, asegúrese de hacer esto:

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

Y si quiere una entrada que no sea de bloqueo, es decir, compruebe periódicamente si el usuario ha presionado una tecla, pero mientras tanto, vaya a hacer otras cosas, entonces puede hacer esto:

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

Tenga en cuenta que no necesita un controlador SIGINT especial para la versión sin bloqueo, ya que el tty solo está en modo raw durante un breve momento.