I'm trying to get simple user input in Ruby, but I can't get it working. I'm using the gets method, but the program never stops to ask me for input. I'm using Sublime Text 2 as my text editor, and I run the program in it, too (if this makes a difference).
Here's my code:
puts "What is your name?"
name = gets
puts "Hello " + name + ". How are you?"
And here's the error (and output) given to me:
C:/Users/Sten Sootla/Desktop/Ruby workspace/exercise.rb:3:in `+': can't convert nil into String (TypeError)
from C:/Users/Sten Sootla/Desktop/Ruby workspace/exercise.rb:3:in `'
What is your name?
[Finished in 0.1s with exit code 1]
Why doesn't the program stop to ask me for input?
Try using $stdin.gets instead of just a plain gets, this will force the input to come from stdin
Here's how I understand it. gets and puts are instance methods of IO, and the default IOs are $stdout and $stdin.
Calls to gets/puts will only be effective if the translator is capable of handling stdout/in e.g. IRB
If you run a ruby file from bash it works too.
io_test.rb
puts gets
in bash
ruby io_test.rb
Then it will "put" into stdout whatever it "gets" from stdin.
If you want to run code within ST2, check out the SublimeREPL plugin, available through Package Control. While you can use IRB, its main Ruby interface is through pry, which is a lot more powerful. You can use it as a classic REPL (think Clojure or LISP), and you can also transfer your code from one tab into the running REPL in another tab by selection, line range, or block.
Interestingly, your code above works in IRB for me, but not pry for some reason - it's reading my $EDITOR environment variable, which is set to subl -w but failing with Errno::ENOENT: No such file or directory - subl -w. Strange...
At any rate, I highly highly recommend SublimeREPL, as it's a really powerful tool, and is self-contained within ST2, so you don't have to keep flipping back and forth to your terminal, saving and reloading your programs.
Related
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
I was trying to figure out how to work the command line switch -r.
My understanding is that the code is typed out as follows:
ruby -r*nameOfRequired*
I am finding that this is not the case. When I type out the above and press enter, the terminal expects an "end of input syntax" and does not continue.
What am I missing? Does there need to be a space in between the switch and the name of the required file?
Please and thank you!
EDIT:
I am currently reading "The Well Grounded Rubyist" by David A. Black, and I came up with this question while reading the section on command line switches.
Having said that, I created a "test.rb" file, containing:
puts Date.today
Then, in the terminal, I typed out:
ruby -r date
I thought this would 'require' the date module, and then enable me to run the "test.rb" file, using ruby test.rb (given that I am in the correct directory).
Instead, the terminal cursor moves to a newline, expecting more input. Let me know if I need to clarify anything else. Thanks!
If you just type ruby -rmodule, then Ruby will load the module and wait for you to type the main program that requires that module.
If you just want to run the module and do nothing else, you can do do rubyfull-path-to-module without the -r, or ruby -rmodule -e exit, or ruby -rmodule </dev/null, or similar.
In general, the ruby command does not record any state from one run to the next, so you need to tell it every thing that it needs to know whenever you run it.
Whenever you run it, you need to tell it the main program to run or else it will expect you to type that program on the standard input. The -r does not specify the main program.
Try this:
ruby -rdate test.rb
According to ruby -h:
-rlibrary require the library, before executing your script
Without giving your script file path, it read the script from stdin.
Try following (You can omit script file path when you give -e command):
ruby -r**nameOfRequired** -e ""
Pry goes into interactive mode if it encounters an exception (eg if you just put an undefined variable 'x' at the end of the script).
(Also if, inside the script itself you require 'pry' and put binding.pry at the point you want to go interactive at.)
But I'm wondering: Is there's some kind of flag/option/argument thingy that I can add to the pry example.rb command when I enter it at the command prompt, so it will go interactive when it reaches the end of executing any example.rb script, regardless of what's inside? (Assuming no exceptions before the end, of course.)
(This would obviously be especially useful for use with editors that you can run external programs from like Notepad++, see this and this.)
Not yet, but file an issue and i'll add it :)
This has been a surprisingly hard question to find an answer to.
(A few questions seem to be asking something at least similar, like:
Ruby console alternative for IRB (Windows)
IDLE like interactive console for Ruby
A recommended Ruby interactive console
But I couldn't get what I need from any of those.)
Also, I'm a bit unsure of the precise terminology I should be using, so I'll try to be really concrete here:
Say you're using IDLE with the Python shell.
You have one of IDLE's text-editor windows open with a script "example.py" in it.
You hit F5 and the Python shell comes up and does exactly what it would do if you had just entered every line in "example.py" into the shell line-by-line.
Functionally, that's exactly what it's doing is automatically entering every line, only without cluttering up the screen by displaying them. (Also it resets the shell to a fresh state every time you do this, but that's not really the important point at the moment; Sometimes it'd be nice to have the option of having it not reset the state of the shell, whatever.)
So the outcome is that now you can play around in the shell, and all the functions and variables etc that were in the script that you just ran are all there.
But with irb...
How do I get the same effect?
For instance, I tried irb example.rb (an equivalent ruby script) in the Windows console, and it just literally enters each line one-by-one into irb, spewing them down the screen, then automatically exits back to the Windows command prompt.
(Although even if that did work the way I wanted (is there some option flaggy argument thingy that would make it do more what I want here?), I'd still have to alt-tab from the text-editor to a console window, and enter the command and file name, which is inferior to just pressing F5, obvs.)
To make really sure I'm being clear in what I mean, here are concrete examples of:
1) a Python script for "example.py"
2) an example of running it in the shell then doing some things in the shell (copy-pasted from the actual shell)
3) an equivalent Ruby script to that Python one
4) an example of running it in the kludgy, slow online-interpreter at repl.it, and doing the exact same things in that irb shell (again, copy-pasted)
1) example.py :
x = "some value you don't want to keep reassigning to this variable"
y = "some other value like that"
def some_function(var):
return "do something complicated with `"+var+"`"
print("example.py just ran")
2) Python shell :
Python 3.2.3 (default, Apr 11 2012, 07:15:24) [MSC v.1500 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> ================================ RESTART ================================
>>>
example.py just ran
>>> x
"some value you don't want to keep reassigning to this variable"
>>> y
'some other value like that'
>>> print(some_function(x))
do something complicated with `some value you don't want to keep reassigning to this variable`
>>> x = "a frog"
>>> print(some_function(x))
do something complicated with `a frog`
>>> print("gonna run example.py again")
gonna run example.py again
>>> ================================ RESTART ================================
>>>
example.py just ran
>>> print("x is back to: `\""+x+"\"`")
x is back to: `"some value you don't want to keep reassigning to this variable"`
3) example.rb :
x = "some value you don't want to keep reassigning to this variable"
y = "some other value like that"
def some_function var
"do something complicated with `#{var}`"
end
puts "test.rb just ran"
4) online Ruby irb shell thing at repl.it :
Ruby 1.8.7 (2008-05-31 patchlevel 0) [x86-linux]
[GCC 4.2.1 (LLVM, Emscripten 1.5, Emscripted-Ruby)]
test.rb just ran
=> nil
x
=> "some value you don't want to keep reassigning to this variable"
y
=> "some other value like that"
puts some_function x
do something complicated with `some value you don't want to keep reassigning to this variable`
=> nil
x = "a frog"
=> "a frog"
puts some_function x
do something complicated with `a frog`
=> nil
puts "gonna run this script again..."
gonna run this script again...
=> nil
test.rb just ran
=> nil
puts "x is back to: `\"#{x}\"`"
x is back to: `"some value you don't want to keep reassigning to this variable"`
=> nil
The best answer I've found so far seems to be to install pry (enter gem install pry at the command prompt).
Now if you run a script by entering pry scriptname.rb, and it encounters an exception, it will automatically go interactive.
Furthermore, if you add require 'pry' inside the script at the top, then you can put binding.pry in the script at ay point.
Now when you run the script (simply by entering scriptname.rb at the command prompt), it will stop executing and go interactive in pry at that point.
Pressing ^D (ie, ctrl-d) will resume execution.
Getting a script to run in a command prompt window when you press F5 (or whatever) in your editor (eg, Notepad++) is apparently somewhat trickier. Solutions like this have some problems that I haven't figure out how to tweak away yet.
So currently I'm just alt-tabbing to the command prompt window and running the script from there (again, by entering pry scriptname.rb or just scriptname.rb, depending on what exactly what I want and whether I put a binding.pry in the script anywhere. Up-arrow recall, tab completion, blah blah.)
I'm working on figuring it out.
I am not 100% sure if this is what you want, but from my experience, using ruby scriptname.rb will run the code
I have an app that runs continuously, dumping output from a server and sending strings to stdout. I want to process this output with a Ruby script. The strings are \n-terminated.
For example, I'm trying to run this on the command line:
myapp.exe | my_script.rb
...with my_script.rb defined as:
while $stdin.gets
puts $_
end
I ultimately am going to process the strings using regexes and display some summary data, but for now I'm just trying to get the basic functionality hooked up. When I run the above, I get the following error:
my_script.rb:1:in `gets': Bad file descriptor (Errno::EBADF)
from my_script.rb:1
I am running this on Windows Server 2003 R2 SP2 and Ruby 1.8.6.
How do I continuously process stdin in a Ruby script? (Continuously as in not processing a file, but running until I kill it.)
EDIT:
I was able to make this work, sort of. There were several problems standing in my way. For one thing, it may be that using Ruby to process the piped-in stdin from another process doesn't work on Windows 2003R2. Another direction, suggested by Adrian below, was to run my script as the parent process and use popen to connect to myapp.exe as a forked child process. Unfortunately, fork isn't implemented in Windows, so this didn't work either.
Finally I was able to download POpen4, a RubyGem that does implement popen on Windows. Using this in combination with Adrian's suggestion, I was able to write this script which does what I really want -- processes the output from myapp.exe:
file: my_script.rb
require 'rubygems'
require 'popen4'
status =
POpen4::popen4("myapp.exe") do |stdout, stderr, stdin, pid|
puts pid
while s = stdout.gets
puts s
end
end
This script echoes the output from myapp.exe, which is exactly what I want.
Try just plain gets, without the $stdin. If that doesn't work, you might have to examine the output of myapp.exe for non-printable characters with another ruby script, using IO.popen.
gets doesn't always use stdin but instead tries to open a file.
See SO.
Try executing your Ruby script by explicitly calling ruby:
myapp.exe | ruby my_script.rb
I've experienced some odd behavior using stdin in Ruby when relying on Windows to invoke the correct program based on the file associations.