Как получить один символ без нажатия enter?

Как я могу получить один символ клавиатуры из терминала с Ruby без нажатия enter? Я пытался!--0-->, но это не сработало для меня.

6 ответов


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 дал отличный ответ, но есть две проблемы:

  1. вы можете испортить состояние tty по умолчанию;
  2. вы игнорируете управляющие символы (^C для SIGINT и т. д.).

простое исправление для этого-сохранить предыдущее состояние tty и использовать следующие параметры:

  • -icanon - отключить канонический ввод (обработка стирания и уничтожения);
  • 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

обратите внимание, что вам не нужен специальный Обработчик SIGINT для неблокирующей версии, так как tty находится только в режиме raw в течение короткого момента.


Примечание: это и старый ответ и решение больше не работает на большинстве систем.

но ответ все равно может быть полезен для некоторых сред, где другие методы не работают. Пожалуйста, прочитайте комментарии ниже.


сначала вам нужно установить highline:

gem install highline

затем попробуйте, если метод highline работает для вас:

require "highline/system_extensions"
include HighLine::SystemExtensions

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

и если вы строите проклятие приложение, вам нужно позвонить

nocbreak

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