Comment obtenir un seul caractère sans appuyer sur Entrée?
Question
Comment obtenir un seul caractère du clavier du terminal avec Ruby sans appuyer sur Entrée?
J'ai essayé Curses :: getch
, mais cela n'a pas vraiment fonctionné pour moi.
La solution
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
(Testé sur mon système OS X, peut ne pas être portable sur toutes les plates-formes Ruby). Voir http://www.rubyquiz.com/quiz5.html pour des suggestions supplémentaires, y compris pour Windows.
Autres conseils
Depuis ruby ??2.0.0, il y a un 'io / console' dans la bibliothèque standard avec cette fonctionnalité
require 'io/console'
STDIN.getch
@Jay a donné une excellente réponse, mais il y a deux problèmes:
- Vous pouvez gâcher l'état du tty par défaut;
- Vous ignorez les caractères de contrôle (^ C pour SIGINT, etc.).
Une solution simple consiste à enregistrer l'état précédent et à utiliser les paramètres suivants:
-
-icanon
- désactive l'entrée canonique (traitement ERASE et KILL); -
isig
- permet de vérifier les caractères par rapport aux caractères de contrôle spéciaux INTR, QUIT et SUSP.
À la fin, vous auriez une fonction comme celle-ci:
def get_char
state = `stty -g`
`stty raw -echo -icanon isig`
STDIN.getc.chr
ensure
`stty #{state}`
end
Raw ( stty raw -echo
) entraîne malheureusement l'envoi de control-C sous forme de caractère et non de SIGINT. Donc, si vous souhaitez bloquer l'entrée comme ci-dessus, mais que vous autorisez l'utilisateur à appuyer sur Control-C pour arrêter le programme en attente, assurez-vous de procéder ainsi:
Signal.trap("INT") do # SIGINT = control-C
exit
end
Et si vous voulez une entrée non bloquante - c’est-à-dire, vérifiez périodiquement si l’utilisateur a appuyé sur une touche, mais dans l’intervalle, faites autre chose - vous pouvez le faire:
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
Notez que vous n'avez pas besoin d'un gestionnaire SIGINT spécial pour la version non bloquante car le terminal est en mode brut pendant un bref instant.
Remarque: il s'agit d'une ancienne réponse et la solution ne fonctionne plus sur la plupart des systèmes.
Mais la réponse pourrait toujours être utile pour certains environnements, où les autres méthodes ne fonctionnent pas. Veuillez lire les commentaires ci-dessous.
Vous devez d’abord installer Highline:
gem install highline
Essayez ensuite si la méthode highline fonctionne pour vous:
require "highline/system_extensions"
include HighLine::SystemExtensions
print "Press any key:"
k = get_character
puts k.chr
Et si vous construisez une malédiction , vous devez appeler
.nocbreak
http: //www.ruby-doc.org/stdlib-1.9.3/libdoc/curses/rdoc/Curses.html#method-c-cbreak