如何获得一个单一的字符,而无需按下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做了一个很好的回答,但是有两个问题:

  1. 你可以搞砸默认的tty状态;
  2. 您忽略控制字符(^ 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