我正在使用Ruby 2.1.5和Windows控制台。我需要能够扫描按键而不停止执行。我需要能够专门检测箭头键。我尝试了其他问题的许多方法,但没有一个在Windows控制台上工作或者没有检测到箭头键。
不显示箭头键
require 'io/console'
loop do
p STDIN.getch
end
在没有错误的情况下运行,但似乎没有从输入缓冲区读取,因为在使用Ctrl-C退出程序后,控制台上显示了所有按键
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
这个也运行没有错误,但需要按下回车键才能继续运行。我需要非阻塞输入
# read a character without pressing enter and without printing to the screen
def read_char
begin
# save previous state of stty
old_state = "stty raw -g"
# disable echoing and enable raw (not having to press enter)
system "stty raw -echo"
c = STDIN.getc.chr
# gather next two characters of special keys
if(c=="\e")
puts "checking for non alpha"
extra_thread = Thread.new{
c = c + STDIN.getc.chr
c = c + STDIN.getc.chr
}
# wait just long enough for special keys to get swallowed
extra_thread.join(0.00001)
# kill thread so not-so-long special keys don't wait on getc
extra_thread.kill
end
rescue => ex
puts "#{ex.class}: #{ex.message}"
puts ex.backtrace
ensure
# restore previous state of stty
system "stty #{old_state}"
end
return c
end
# takes a single character command
def show_single_key
c = read_char
case c
when " "
puts "SPACE"
when "\t"
puts "TAB"
when "\r"
puts "RETURN"
when "\n"
puts "LINE FEED"
when "\e"
puts "ESCAPE"
when "\e[A"
puts "UP ARROW"
when "\e[B"
puts "DOWN ARROW"
when "\e[C"
puts "RIGHT ARROW"
when "\e[D"
puts "LEFT ARROW"
when "\177"
puts "BACKSPACE"
when "\004"
puts "DELETE"
when /^.$/
puts "SINGLE CHAR HIT: #{c.inspect}"
else
puts "SOMETHING ELSE: #{c.inspect}"
end
end
show_single_key while(true)
这似乎是最后一个的变体,它对所有ASCII代表的键都有效,但不适用于箭头键,并且输入有问题。
require 'io/console'
# Reads keypresses from the user including 2 and 3 escape character sequences.
def read_char
STDIN.echo = false
STDIN.raw!
input = STDIN.getc.chr
puts input
if input == "\e" then
puts "getting additional characters"
input << STDIN.read_nonblock(3) rescue nil
input << STDIN.read_nonblock(2) rescue nil
end
ensure
#STDIN.echo = true
STDIN.cooked!
return input
end
# oringal case statement from:
# http://www.alecjacobson.com/weblog/?p=75
def show_single_key
c = read_char
case c
when " "
puts "SPACE"
when "\t"
puts "TAB"
when "\r"
puts "RETURN"
when "\n"
puts "LINE FEED"
when "\e"
puts "ESCAPE"
when "\e[A"
puts "UP ARROW"
when "\e[B"
puts "DOWN ARROW"
when "\e[C"
puts "RIGHT ARROW"
when "\e[D"
puts "LEFT ARROW"
when "\177"
puts "BACKSPACE"
when "\004"
puts "DELETE"
when "\e[3~"
puts "ALTERNATE DELETE"
when "\u0003"
puts "CONTROL-C"
exit 0
when /^.$/
puts "SINGLE CHAR HIT: #{c.inspect}"
else
puts "SOMETHING ELSE: #{c.inspect}"
end
end
show_single_key while(true)
我还试过一对有Win32API调用的人,但他们都无法正常工作,并且有关于被弃用的警告。我想要一个跨平台的解决方案,但在这一点上,我将满足它在Windows控制台上正常工作。此外,我不能使用任何Ruby Gems。
答案 0 :(得分:0)
我已经尝试解决这一问题了一段时间了,这对我有用:
require 'io/console'
while true
user_input = $stdin.getch
case user_input
when 'q'
exit
when '['
print '' # I believe that by entering this block of code user_input drops the first char. What is left can be used to determine what key has been pressed.
else
case user_input
when 'A'
puts "up"
when 'B'
puts "down"
when 'C'
puts "right"
when 'D'
puts "left"
end
end
end
我正在使用ruby 2.4.1。希望能帮助到你。