Detecting stdin content in Ruby - ruby

I want to know whether or not someone is trying to give a ruby program content on stdin. I do not want ruby to fall back to allowing interactive input. How do I do this?
# When called in bash like this, I want 'cat.rb' to exit immediately:
ruby cat.rb
# When called in bash like this, I want to see the word 'hello':
echo hello | ruby cat.rb
If I just have cat.rb contain puts gets then the first example will block, waiting for an EOF on interactive stdin. I don't want to modify the calling command, but wish to support both kinds of behavior.

Look at $stdin.tty?
ruby cat.rb
# $stdin.tty? -> true
echo hello | ruby cat.rb
# $stdin.tty? -> false

Related

When specifying command-line arguments Ruby no longer waits for input using gets

When running a ruby script with command line arguments, the "gets" is no longer blocking, it doesn't work.
test.rb
#!/usr/bin/ruby
puts "should wait for input"
gets
puts "test"
and here is how I run it
$ ./test.rb test.rb
should wait for input
test
It didn't wait.
I'm running Ubuntu 16.04 desktop, and Ruby from repository ruby 2.3.1p112 (2016-04-26) [x86_64-linux-gnu]
What am I doing wrong?
In addition to STDIN.gets like others have recommended, you can use plain gets if you call ARGV.clear beforehand. The regular gets works as expected if there aren't command like arguments to the script, but if there are, then it will read them. It's not really clear why you're using ./test.rb test.rb, but the second filename is a command line argument.
More specifically, if regular gets is called when ARGV is populated, then the result will be the contents of the file.
max#max ~> echo "content" > test.txt
max#max ~> ruby -e "puts ARGV.inspect; puts gets" test.txt
["test.txt"]
content
Nevermind,
The "gets" actually takes the first line from the file I added in the cli arguments.
Very weird.

Answering a cli prompt in ruby with open3?

Apologies for lack of sample code, I'm on mobile at the moment.
I've gotten ruby+open3 to run commands and save stdout and stderr to a variable.
My question is, if the command line interface prompts the user is it possible to input text into the prompt and press enter? If so how would I go about doing this.
Example explanation
Runs program, program in terminal then asks "what is your name?" and waits for input.
I want to input a name, press enter.
Then it asks next question, I want to put to stdin and answer that as well
This is for an automation test. If anyone has a better idea than open3 I'm all ears but I'm restricted to ruby
Thanks
Consider this:
Create an input file using:
cat > test.input
bar
baz
Then press CTRL+D to terminate the input, which will cause the file test.input to be created.
In the same directory save this code as test.rb:
2.times do |i|
user_input = gets.chomp
puts "#{ i }: #{ user_input }"
end
Run the code using:
ruby test.rb < test.input
and you should see:
0: bar
1: baz
The reason this works is because gets reads the STDIN (by default) looking for a line-end, which in this case is the character trailing bar and baz. If I load the input file in IRB it's easy to see the content of the file:
input = File.read('test.input')
=> "bar\nbaz\n"
2.times says to read a line twice, so it reads both lines from the file and continues, falling out of the times loop.
This means you can create a file, pipe it into your script, and Ruby will do the right thing. If Ruby has called a sub-shell, the sub-shell will inherit Ruby's STDIN, STDOUT and STDERR streams. I can rewrite the test.rb code to:
puts `sh ./test.sh < #{ ARGV[0] }`
and create test.sh:
for i in 1 2
do
read line
echo $i $line
done
then call it using:
ruby test.rb test.input
and get:
1 bar
2 baz

Testing for pipe or console standard input with ARGF

I have written a script that I would like to take input either from a pipe or by providing a filename as an argument. ARGF makes it easy to deal with this flexibly, except in the incorrect usage cases where neither is provided, in which case STDIN is opened and it hangs until the user inputs something on the console.
I would like to catch this incorrect usage to display an error message and exit the program, but I haven't been able found a way. ARGF.eof? seemed like a possible candidate, but it also hangs until some input is received.
Is there a simple way for Ruby to discriminate between STDIN provided by a pipe and one from the console?
you can use
$stdin.tty?
for example
$ ruby -e 'puts $stdin.tty?'
> true
$ echo "hello" | ruby -e 'puts $stdin.tty?'
> false

Ruby: Keep console open after script execution

I wrote a Ruby script like the following example. The basic functionality is the same:
# get input from the user
input = gets.chomp
# do awesome stuf with this input and print the response
puts do_awesome_stuff(input)
The problem is when I run the script it prints the solution I want, but the console window closes right after. I want the console to keep open.
I'm currently on windows, but the solution should be working on every system.
One way is to run the ruby script with a .bat file and pause it, like so:
ruby script.rb
PAUSE
I hope there is a way without the additional .bat file. Does Ruby has a function like PASUE integrated?
It seems like you double click the ruby script file.
Instead issue the following command in cmd shell.
ruby filename.rb
If you don't want that, you can add gets to the end of the script.
# get input from the user
input = gets.chomp
# do awesome stuf with this input and print the response
puts do_awesome_stuff(input)
gets # <----
But this is not recommended because .. if you run the command in cmd shell or terminal you should type extra Enter to return to the shell.
Use the -r options of irb.
irb -r ./filename.rb

Ruby not showing output of internal process

I'm trying this in ruby.
I have a shell script to which I can pass a command which will be executed by the shell after some initial environment variables have been set. So in ruby code I'm doing this..
# ruby code
my_results = `some_script -allow username -cmd "perform_action"`
The issue is that since the script "some_script" runs "perform_action" in it's own environment, I'm not seeing the result when i output the variable "my_results". So a ruby puts of "my_results" just gives me some initial comments before the script processes the command "perform_action".
Any clues how I can get the output of perform_action into "my_results"?
Thanks.
The backticks will only capture stdout. If you are redirecting stdout, or writing to any other handle (like stderr), it will not show up in its output; otherwise, it should. Whether something goes into stdout or not is not dependent on an environment, only on redirection or direct writing to a different handle.
Try to see whether your script actually prints to stdout from shell:
$ some_script -allow username -cmd "perform_action" > just_stdout.log
$ cat just_stdout.log
In any case, this is not a Ruby question. (Or at least it isn't if I understood you correctly.) You would get the same answer for any language.

Resources