Wie ein einzelnes Zeichen erhalten, ohne Enter-Taste?
Frage
Wie kann ich ein einzelnes Zeichen auf der Tastatur aus dem Terminal mit Rubin erhalten, ohne Enter-Taste?
Ich versuchte Curses::getch
, aber das hat für mich wirklich nicht.
Lösung
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
(getestet auf meinem OS X-System kann nicht auf alle Ruby-Plattformen portierbar sein). Siehe http://www.rubyquiz.com/quiz5.html für einige weitere Vorschläge, auch für Fenster.
Andere Tipps
Da Rubin 2.0.0 gibt es eine 'io / console' in der stdlib mit dieser Funktion
require 'io/console'
STDIN.getch
@Jay gab eine große Antwort, aber es gibt zwei Probleme:
- Sie können vermasseln Standard tty Zustand;
- Sie ignorieren Steuerzeichen (^ C für SIGINT, etc).
Eine einfache Lösung für das heißt vorherigen tty Zustand und die Verwendung folgender Parameter speichern:
-
-icanon
- deaktivieren kanonischen Eingang (ERASE und KILL-Verarbeitung); -
isig
- ermöglichen die Überprüfung von Zeichen gegen die speziellen Steuerzeichen INTR, QUIT und SUSP .
Am Ende würden Sie eine Funktion wie diese haben:
def get_char
state = `stty -g`
`stty raw -echo -icanon isig`
STDIN.getc.chr
ensure
`stty #{state}`
end
Raw-Modus (stty raw -echo
) leider verursacht Steuer-C als ein Zeichen gesendet zu bekommen, nicht als SIGINT. Also, wenn Sie eingeben möchten blockiert wie oben, aber ermöglichen dem Benutzer die Kontrolle-C zu schlagen, das Programm zu stoppen, während es wartet, stellen Sie sicher, dies zu tun:
Signal.trap("INT") do # SIGINT = control-C
exit
end
Und wenn Sie nicht blockierenden Eingang wollen - das heißt, in regelmäßigen Abständen überprüfen, ob der Benutzer einen Schlüssel, aber in der Zwischenzeit gedrückt hat, gehen andere Dinge tun - dann können Sie dies tun:
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
Beachten Sie, dass Sie nicht einen speziellen SIGINT-Handler für die nicht-blockierende Version brauchen, da die tty nur im Raw-Modus für einen kurzen Moment sind.
Hinweis: Dies ist und alte Antwort und die Lösung nicht mehr funktioniert auf den meisten Systemen
.Aber die Antwort könnte noch für einige Umgebungen nützlich sein, wo die anderen Methoden nicht funktionieren. Bitte lesen Sie die Kommentare unten.
Zuerst müssen Sie Highline installieren:
gem install highline
Dann versuchen Sie, wenn die Highline-Methode für Sie:
require "highline/system_extensions"
include HighLine::SystemExtensions
print "Press any key:"
k = get_character
puts k.chr
Und wenn Sie bauen Flüche Anwendung, müssen Sie anrufen
nocbreak
http: //www.ruby-doc.org/stdlib-1.9.3/libdoc/curses/rdoc/Curses.html#method-c-cbreak