RubyでEnterキーを押さずに、ターミナルから単一のキーボード文字を取得するにはどうすればよいですか?Curses::getch
、しかしそれは私には本当にうまくいきませんでした。
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
(私のOS Xシステムでテストされていますが、すべてに移植できるわけではありませんRubyプラットフォーム)。一部については http://www.rubyquiz.com/quiz5.html を参照してくださいWindowsを含む追加の提案。
Ruby 2.0.0なので、この機能を持つstdlibには 'io/console'があります。
require 'io/console'
STDIN.getch
@Jayは素晴らしい答えを出しましたが、2つの問題があります。
そのための簡単な修正は、以前のtty状態を保存し、次のパラメーターを使用することです。
-icanon
-正規入力を無効にします(ERASEおよびKILL処理);isig
-特殊制御文字INTR、QUIT、およびSUSPに対する文字のチェックを有効にします。最終的には、次のような関数になります。
def get_char
state = `stty -g`
`stty raw -echo -icanon isig`
STDIN.getc.chr
ensure
`stty #{state}`
end
Rawモード(stty raw -echo
)残念ながら、control-CはSIGINTではなく文字として送信されます。したがって、上記のような入力をブロックしたいが、待機中にユーザーがcontrol-Cを押してプログラムを停止できるようにする場合は、次のようにしてください。
Signal.trap("INT") do # SIGINT = control-C
exit
end
そして、非ブロッキング入力が必要な場合、つまり、ユーザーがキーを押したかどうかを定期的に確認しますが、それまでの間、他のことを行ってください。これを行うことができます。
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
Ttyは一瞬だけrawモードであるため、非ブロッキングバージョン用の特別なSIGINTハンドラーは必要ありません。
しかし、他の方法が機能しない一部の環境では、答えは依然として役立つ可能性があります。以下のコメントを読んでください。
まず、highlineをインストールする必要があります。
gem install highline
次に、highlineメソッドが機能するかどうかを試します。
require "highline/system_extensions"
include HighLine::SystemExtensions
print "Press any key:"
k = get_character
puts k.chr
cursesアプリケーションを構築している場合は、
nocbreak
http://www.Ruby-doc.org/stdlib-1.9.3/libdoc/curses/rdoc/Curses.html#method-c-cbreak