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:
- Puede estropear el estado tty predeterminado;
- 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.
Y si está creando aplicaciones de curses , necesita llamar
nocbreak
http://www.ruby-doc.org/stdlib-1.9.3/libdoc/curses/rdoc/Curses.html#method-c-cbreak
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
(Probado en mi sistema OS X, puede no ser portátil para todas las plataformas Ruby). Consulte http://www.rubyquiz.com/quiz5.html para obtener algunas sugerencias adicionales, incluso para Windows.