如何在不按Enter的情况下获得单个角色?

时间:2008-10-06 16:06:21

标签: ruby getch

如何在不按Enter键的情况下从终端获取单个键盘字符? 我试过了Curses::getch,但这对我来说并没有用。

6 个答案:

答案 0 :(得分:50)

从ruby 2.0.0开始,就有了一个&io / console'在具有此功能的stdlib中

require 'io/console'
STDIN.getch

答案 1 :(得分:33)

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。

答案 2 :(得分:19)

@Jay给出了一个很好的答案,但有两个问题:

  1. 你可以搞乱默认的tty状态;
  2. 您忽略控制字符(SIGINT的^ C等)。
  3. 一个简单的解决方法是保存以前的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
    

答案 3 :(得分:14)

原始模式(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

请注意,对于非阻塞版本,您不需要特殊的SIGINT处理程序,因为tty仅在原始模式下短暂停留。

答案 4 :(得分:13)

注意:这是旧答案,解决方案不再适用于大多数系统。

但是答案对于某些环境仍然有用,其他方法不起作用。请阅读以下评论。


首先你需要安装highline:

gem install highline

然后尝试使用highline方法:

require "highline/system_extensions"
include HighLine::SystemExtensions

print "Press any key:"
k = get_character
puts k.chr

答案 5 :(得分:0)

如果您正在构建 curses 应用程序,则需要调用

nocbreak

http://www.ruby-doc.org/stdlib-1.9.3/libdoc/curses/rdoc/Curses.html#method-c-cbreak