Reputation: 2236
Seems that Ruby IO#getc wait until receiving a \n before returning the chars.
If you try running this script:
STDOUT.sync = true
STDIN.sync = true
while data = STDIN.getc
STDOUT.puts "Char arrived"
end
It will return one "Char arrived" per char sent to stdin, but only after a \n has been sent.
Seems that all char are buffered even if I write STDIN.sync = true.
Does anyone knows how to make the script print "Char arrived" right after a char has been sent to STDIN ?
Upvotes: 3
Views: 3263
Reputation: 9192
From https://flylib.com/books/en/2.44.1/getting_input_one_character_at_a_time.html
def getch
state = `stty -g`
begin
`stty raw -echo cbreak`
$stdin.getc
ensure
`stty #{state}`
end
end
while (k = getch)
print k.chr.inspect
sleep 0.2
end
Upvotes: 0
Reputation: 9380
https://stackoverflow.com/a/27021816/203673 and its comments are the best answer in the ruby 2+ world. This will block to read a single character and exit when ctrl + c is pressed:
require 'io/console'
STDIN.getch.tap { |char| exit(1) if char == "\u0003" }
Upvotes: 0
Reputation: 1094
Adapted from from another answered question.
def get_char
begin
system("stty raw -echo")
str = STDIN.getc
ensure
system("stty -raw echo")
end
str.chr
end
p get_char # => "q"
Upvotes: 2
Reputation: 8710
There was an answer from Matz :)
UPDATE
Also, you can use gem entitled highline, because using above example may be linked with strange screen effects:
require "highline/system_extensions"
include HighLine::SystemExtensions
while k = get_character
print k.chr
end
Upvotes: 8