How can you check for STDIN input in a Ruby script?
This is something that's done in Linux a lot:
#!/usr/bin/env ruby
str = (STDIN.tty?) ? 'not reading from stdin' : $stdin.read
puts str
>> $ ruby test.rb
>> not reading from stdin
>> $ echo "reading from stdin" | ruby test.rb
>> reading from stdin
Receiving input from STDIN in Ruby
Ruby may hold output in a buffer before writing to STDOUT
, and write once an indeterminate amount of data has been printed. If you change your code to this:
#!/usr/bin/env ruby
while line = gets.chomp do
puts line
STDOUT.flush
# $stdout.flush works too, though the difference
# is outside the scope of this question
end
You can expect to see the output before you close the input stream.
As for "^C the client before the server", closing the process immediately will disregard all of the data which has not yet been flushed.
Testing STDIN in Ruby
You can simply stub STDIN:
it "takes user's name and returns it" do
output = capture_standard_output { game.ask_for_name }
expect(output).to eq "What shall I call you today?"
allow(STDIN).to receive(:gets) { 'joe' }
expect(game.ask_for_name).to eq 'Joe'
end
Actually, you can do the same with STDOUT
, without needing to change $stdout
:
it "takes user's name and returns it" do
expect(STDOUT).to receive(:puts).with("What shall I call you today?")
allow(STDIN).to receive(:gets) { 'joe' }
expect(game.ask_for_name).to eq 'Joe'
end
What does #tty? on STDIN mean / do in ruby?
Seems like http://www.jstorimer.com/blogs/workingwithcode/7766125-writing-ruby-scripts-that-respect-pipelines supplies the most concise description of what #tty?
does:
Ruby's IO#isatty method (aliased as IO#tty?) will tell you whether or not the IO in question is attached to a terminal. Calling it on $stdout, for instance, when it's being piped will return false.
Here is some relevant info that you may find useful:
- Detecting stdin content in Ruby
- How can you check for STDIN input in a Ruby script?
- https://stackoverflow.com/a/273605
- https://gist.github.com/timuruski/6072363
Background meaning via What do pty and tty mean?:
In UNIX, /dev/tty* is any device that acts like a "teletype", ie, terminal. (Called teletype because that's what we had for terminals in those benighted days.)
In the spirit of the question, here's an example of writing to /dev/tty
from http://zetcode.com/lang/rubytutorial/io/:
#!/usr/bin/ruby
fd = IO.sysopen "/dev/tty", "w"
ios = IO.new(fd, "w")
ios.puts "ZetCode"
ios.close
How to detect if a Ruby script is running through a shell pipe?
Use $stdout.isatty
or more idiomatically, $stdout.tty?
. I created a little test.rb file to demonstrate, contents:
puts $stdout.isatty
Results:
$ ruby test.rb
true
$ ruby test.rb | cat
false
Reference: https://ruby-doc.org/core/IO.html#method-i-isatty
How do I listen to STDIN input without pausing my script?
Not sure where are the commands you want to "continue running" in your example. Try this small script:
Thread.new do
loop do
s = gets.chomp
puts "You entered #{s}"
exit if s == 'end'
end
end
i = 0
loop do
puts "And the script is still running (#{i})..."
i += 1
sleep 1
end
Reading from STDIN is done in a separate thread, while the main script continues to work.
Related Topics
Ruby Way to Group Anagrams in String Array
Rails 3 Joins -- Select Only Certain Columns
Using Gets() Gives "No Such File or Directory" Error When I Pass Arguments to My Script
In Ruby, What Is Stored on the Stack
Why Was the Object_Id for True and Nil Changed in Ruby2.0
Star Rating in Ajax with Ruby on Rails
I'm Getting "Found Character That Cannot Start Any Token While Scanning for the Next Token"
How to Convert a Ruby String Range to a Range Object
Bundler Puts My Gems in My Project Directory
How to Make Rake Tasks Run Under My Sinantra App/Environment
Rails Check_Box_Tag How to Pass Value When Checked Ajaxily
Rails 3 Validates Inclusion of When Using a Find (How to Proc or Lambda)
How to Get a List of All Available Rake Tasks in a Namespace
Remove "Www", "Http://" from String
Rails - Displaying Foreign Key References in a Form
How to Iterate Through an Array Starting from the Last Element? (Ruby)