Ruby's irb with [what?] is equivalent to the Python Shell with IDLE? (On Windows, if relevant.) - ruby

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

Related

Ruby's output in the Windows console VS mingw64 VS cygwin64

I'm having a really weird problem here. Here's simple code that uses puts:
puts "Dale"
sleep 1
puts "Cooper"
I have 3 different terminals/consoles:
Windows console (system default)
mingw64 (UNIX-like terminal that was installed alongside with Git)
cygwin64 (UNIX-like terminal)
Here is weird thing: the code runs as expected only in the standard Windows console. UNIX-like terminals are waiting for 1 second and only then showing output (both lines at the same moment). Basically, UNIX-like terminals are waiting for the program to exit, and then they are showing the final result of output.
If I replace puts with print, it wont affect the execution process. UNIX-like terminals will still delay output until the program quits.
But the next two examples work right in all 3 terminals/consoles:
system("echo Dale")
sleep 1
system("echo Cooper")
This one adds quotes, but aside from this, the code works as expected.
p "Dale"
sleep 1
p "Cooper"
Having said this, I assume this has something to do with Ruby. I have tried different versions of Ruby.
Can someone explain why this is happening and what are possible ways to bypass this issue?
Here's me answering my own question.
Little background
If you do puts STDOUT.sync before the code then you will see that no matter if you are using Windows console or UNIX-like terminal, it will say that STDOUT.sync is set to false. That's weird thing because Windows console is flushing output immediately and UNIX-like terminals don't. I'm not sure why that's happening.
Solution
You can do STDOUT.flush (or $stdout.flush) to flush buffer or you can set STDOUT.sync (or $stdout.sync) to true. Both variants are completely friendly with Windows console. So the code will be as following:
puts "Dale"
STDOUT.flush
sleep 1
puts "Cooper"
or more recommended:
STDOUT.sync = true
puts "Dale"
sleep 1
puts "Cooper"
Determining whenever it's Windows console or UNIX-like terminal
Here is a little trick suggested by #eryksun to know if code is being run in Windows console or UNIX-like terminal. STDOUT.isatty works kind of inverted when run under Windows, but nevertheless it does the trick.
if STDOUT.isatty
# Windows console
else
# UNIX-like terminal
end
Keep in mind that this assumes that you already know that the code is being run under Windows. A good way to check OS is described here.
References
Major source for the answer can be found here. Idea for the answer belongs to #eryksun.
STDOUT.sync,
STDOUT.sync = (question about this method),
STDOUT.flush, STDOUT.isatty.

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 .gets doesn't work

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.

Ruby, pry: Can I add something to the command `pry example.rb` so pry automatically goes interactive when it finishes executing the script?

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 :)

Execute shell commands from Ruby code

Note: If you think of a better title/question, feel free to suggest it. I wasn't sure how to articulate this question in one brief sentence.
I created a command line Mastermind game. To play the game, you type play.rb at the command line.
play.rb is a Ruby script that fires up the game. Within the script, the game is sent an interface, called CommandLineInterface.
If you want to play using a GUI (I'm using a Ruby GUI called Limelight), you cd into the limelight directory and type limelight open production and the GUI opens.
There is a mastermind_game directory that contains a lib, a spec, and a limelight directory. The limelight directory contains a production directory.
Now I'm making a few changes. You can pass arguments to the script at the command line. Either you enter play.rb "command line game" or play.rb "limelight game".
ARGV is an array of the arguments passed at the command line.
if ARGV.include?("command line game")
interface = CommandLineInterface.new
elsif ARGV.include?("limelight game")
interface = LimelightInterface.new
end
If I want to play my command line game, I enter play.rb "command line game" and it works fine.
I want to be able to type play.rb "limelight game" at the command line and have that open the GUI. In ARGV, the argument "limelight game" would be found so interface would be set to LimelightInterface.new. Within my LimelightInterface class I want the initialize method to open the GUI. It should essentially have the same functionality as typing limelight open production at the command line.
I'm not sure if this is possible or how to do it, so any help would be appreciated! Thanks!
EDITED: I'm trying to execute the command rvm use jruby by including this line in my script:
system("rvm use jruby")
I get back: "RVM is not a function, selecting rubies with 'rvm use ...' will not work."
Ryan, there's several ways to call out to the system:
Backticks:
ruby -e 'p ARGV' '1 2' '3 4' # => "[\"1 2\", \"3 4\"]\n"
The %x literal (note that you can use any delimiter you like, you're not restricted to parentheses)
%x(ruby -e 'p ARGV' '1 2' '3 4') # => "[\"1 2\", \"3 4\"]\n"
The system command. The difference here is that it passes stdin / out / err on through. (the above return the stdout, this one prints it on your process' stdout).
system('ruby', '-e p ARGV', '1 2', '3 4')
# >> ["1 2", "3 4"]
And if you need more sophisticated usage, something like open3 from the stdlib has gotten me pretty far. If you really need the big guns (it doesn't sound like you do), there's a gem open4.
Edit:
It sounds like you're wanting to do something like this:
require 'open3'
bash_script = <<SCRIPT
source "$HOME/.rvm/scripts/rvm"
rvm use jruby
ruby -v
exit
SCRIPT
out, err, status = Open3.capture3 'bash', stdin_data: bash_script
puts out
# >> Using /Users/joshcheek/.rvm/gems/jruby-1.6.7
# >> jruby 1.6.7 (ruby-1.8.7-p357) (2012-02-22 3e82bc8) (Java HotSpot(TM) 64-Bit Server VM 1.6.0_29) [darwin-x86_64-java]
But honestly, I don't think it's a good solution for your situation, because there's many legitimate ways to set up jruby for your environment. I think it would be better to just check that the limelight binary exists, and tell your user to fix their environment if it doesn't.
Here's the first result from googling the title: http://tech.natemurray.com/2007/03/ruby-shell-commands.html
If that's not what you need, I don't understand the question.

Resources