YARR. Yet Another Ruby REPL
YARR (Yet Another Ruby REPL) is a Ruby REPL (it’s just a hobby, it won’t be big and professional like Pry). YARR was inspired by groovysh1, IRB2, Pry3, Bash 4 and Vim5.
A read–eval–print loop (REPL) is an interactive environment that takes user inputs, evaluates them, and returns the result to the user. A simple REPL to evaluate single valid lines of Ruby code, could be something like this:
loop do
print "ruby> "
input = gets
puts "=> #{eval(input)}"
end
I started to play with this idea and finally I build YARR that is a command-line application which allows easy access to evaluate Ruby expressions, define classes and run simple experiments.
Interesting things in the source code
This project has been a good opportunity to explore new things. I also only wanted to use the Ruby standard libraries without any external gem.
1. Method names don’t have restrictions
Method names in Ruby may contain upper-case and lower-case letters, numbers,
underscores _
and the punctation signs !
, ?
, =
.
A method name can’t begin with a number and the characters !
, ?
and =
can
only appear at the end.
That’s correct if we use the usual way of defining new methods with def
,
however there seems to be no restrictions on what can be used if we use
define_method
[code].
define_method("!") do |args|
`#{args}`
end
2. Capture STDOUT
It’s possible to redirect the standard output or store it into a variable. I captured the STDOUT for a block of code and then restore it [code].
def capture_stdout(&block)
stdout = $stdout
$stdout = StringIO.new
block.call
ensure
$stdout = stdout
end
3. Arrange-Act-Assert pattern
Arrange-Act-Assert is a pattern for arranging and formatting code in test methods. It is very popular from the Given-When-Then style of representing tests.
I used the RSpec syntax with some private methods, so each method should group these functional sections [code]:
- Arrange all necessary preconditions and inputs (
setup
). - Act on the object or method under test (
given
). - Assert that the expected results have occurred (
expect
).
it "executes multiline line declaration and invocation" do
setup("def foo", "1", "end")
given("foo")
expect(interpreter.call).to eq("\e[1m===>\e[0m 1")
end
February 23, 2015 | @ArturoHerrero