如何获得一个单一的字符,而无需按下input?
怎样才能从terminal用Rubyinput一个单一的键盘字符? 我尝试了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系统上testing过,可能不能移植到所有的Ruby平台上)。 请参阅http://www.rubyquiz.com/quiz5.html获取一些其他build议,包括Windows。;
自从ruby 2.0.0以后,在stdlib中有一个'io / console'这个特性
require 'io/console' STDIN.getch
@Jay做了一个很好的回答,但是有两个问题:
- 你可以搞砸默认的tty状态;
- 您忽略控制字符(^ C为SIGINT等)。
一个简单的解决方法是保存以前的tty状态并使用以下参数:
-
-icanon
– 禁用规范input(ERASE和KILL处理); -
isig
– 启用对特殊控制字符INTR,QUIT和SUSP的字符检查。
最后你会有这样的function:
def get_char state = `stty -g` `stty raw -echo -icanon isig` STDIN.getc.chr ensure `stty #{state}` end
注:这是旧的答案,解决scheme不再适用于大多数系统。
但是,对于其他方法无效的情况,答案仍然有用。 请阅读下面的评论。
首先你必须安装highline:
gem install highline
然后尝试如果highline方法为您工作:
require "highline/system_extensions" include HighLine::SystemExtensions print "Press any key:" k = get_character puts k.chr
原始模式( stty raw -echo
)不幸地导致control-C作为字符被发送,而不是SIGINT。 所以,如果你想阻止上面的input,但是允许用户在等待的时候点击control-C来停止程序,一定要这样做:
Signal.trap("INT") do # SIGINT = control-C exit end
如果你想要非阻塞的input – 也就是说,定期检查用户是否按下了一个键,但在此期间,去做其他的东西 – 那么你可以这样做:
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
请注意,对于非阻塞版本,您不需要特殊的SIGINT处理程序,因为tty在短时间内只处于原始模式。
如果你正在构buildcurses应用程序,你需要打电话
nocbreak
http://www.ruby-doc.org/stdlib-1.9.3/libdoc/curses/rdoc/Curses.html#method-c-cbreak