Execute program file with irb and remain interactive - ruby

Is it possible to run irb, pass it a .rb file that gets automatically executed, and have irb stay running in interactive mode?
On Windows, I have a file called checkme.bat that basically does the following:
irb checkme.rb
The problem right now is that when I run checkme.bat, irb executes the program file but then simply exits, leaving me back at the command line.

One way to do this is to use pry and add the line binding.pry at the point in your script where you want to bail out into the repl.
x = 3
puts "Hello!"
binding.pry
Then you can run your script with pry and it'll let you examine what's going on.
~> pry d.rb
Hello
[1] pry(main)> x
=> 3
[2] pry(main)>

I'm not quite sure but on Windows when you execute a .rb file it instantly closes, try using gets at the end of the program.

Related

Ruby Script that runs list of irb watir commands

I regularly use the irb for testing out cucumber watir webdriver steps on a browser. This involves opening the irb and typing in a list of the same commands. The first few commands are always
require 'watir-webdriver'
browser = Watir::Browser.new(:chrome)
b.goto 'www.foo.com'
the list of commands goes on like this. Every time I open the irb I have to go through all of these. Does anyone have any idea of a script which could be run to automate a list of commands such as the above? So that it would open the IRB and then go through the commands one by one saving me load of time.
Any help is greatly appreciated.
Probably the easiest thing to do is create a script.rb file in the root project directory (or wherever you're starting IRB), and write out the Ruby you normally run. Then when you start IRB, just load 'script.rb'
However this won't work if you need access to your browser variable after setup. In that case it would make more sense to create a class.
in ./test_browser.rb
require 'watir-webdriver'
require 'irb'
class TestBrowser < Watir::Browser
def self.build
browser = new(:chrome)
browser.goto 'www.foo.com'
# other setup steps
browser # return the browser at the end of the method
end
end
IRB.start
Then from the shell: $ ruby ./test_browser.rb
This will start up IRB with your class loaded. Then all you need to do is call the .build method and store the browser in a variable
browser = TestBrowser.build
You can always spin up irb with a particular file in mind:
irb -r./startup.rb
Where ./startup.rb is the path to whatever file you want to run first before opening the REPL shell.
It's pretty easy to make a wrapper script for this if you do it frequently enough. You can also invoke IRB manually inside a custom script of your own construction, much as rails console does.

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

Why does IRB not ignore EOF as per IRB.conf hash

I'm trying to start IRB and run a file, foo.rb, in one command,
irb foo.rb
When foo.rb is done I want another IRB prompt. Instead, it prints an IRB prompt, then exits.
I checked the IRB docs and I changed IRB.conf[:IGNORE_EOF] = true. I confirmed that hash value inside IRB. Is the behavior I want set by this hash? If so, what else could I be doing wrong?
The docs for irb say about that configuration:
**conf.ignore_eof = true/false**
Whether ^D (control-d) will be ignored or not. If false is set, ^D means quit.
So, no that setting isn't meant to do what you're looking for. As far as I can tell, there isn't a way to do what you want with irb. The closest would be to start irb without an argument, then use require './foo.rb' to run that file.

dropping user to IRB after reading from pipe

I have this script that drops the user to an IRB session when executed.
All good, but when I use *nix pipes to get the input (e.g. with cat), the IRB session ends immediately.
I could reduce the script (let's call it myscript.rb) to the following:
require 'irb'
if $stdin.stat.size > 0
#text = $stdin.read
else
#text= "nothing"
end
ARGV.clear
IRB.start
When executed like: ruby myscript.rb, I end up in the IRB session (as expected).
But (assuming foo.txt exists in the cwd): cat foo.txt | ruby myscript.rb will just print the IRB prompt and then the IRB session is closed (I'm being dropped to $bash).
Any known workarounds or ideas?
BTW: it has the same behavior on ruby 1.8.7 as well as on 1.9.2.
I think your problem is that when you pipe to your script STDIN will be the stream from your file, so when when you start IRB it will read from the same stream, but notice that it's at its end, and quit, just like it would when you type ctrl-D (which is a manual end of file signal).
You can reopen STDIN to read from the tty (i.e. the keyboard) like this:
STDIN.reopen(File.open('/dev/tty', 'r'))
but it looks a bit weird for me, I don't get the proper IRB promt. IRB works though.
#Theo identified the problem.
Also, requiring irb before IRB.start will fix missing IRB settings. In the end, the code looks like this:
if $stdin.stat.size > 0
#text = $stdin.read
$stdin.reopen(File.open("/dev/tty", "r"))
else
#text= "nothing"
end
require 'irb'
ARGV.clear
IRB.start
$stdin.read reads your input before IRB has a chance to read it (if you're trying to force IRB to execute commands from stdin).

Resources