Pal
Pal is a miniature Ruby read-evaluate-print loop for project-specific shells. It can be extended to create command-line interfaces for libraries and applications, useful for quick tests or demos. Pal can also serve as a lightweight alternative to irb
, though it lacks features such as tab completion, cross-session command history, and seamless multiline editing present in the former.
Overview
The Pal shell reads, evaluates, and prints lines of Ruby code. By default, Pal uses the Readline
library to read lines from the standard input, and prints the results using the puts
method. Both behaviors may be overridden to provide different input and output sources—for example, the Pal unit tests use the StringIO
library to simulate the standard input and output streams. Multiple lines of code may be evaluated by terminating each line with the \
character.
Next, the Ruby code is executed in an evaluation context. All instance methods defined in the context are exposed as top-level methods during evaluation. The context may be extended with additional methods to create a command-line interface for an application or create plugins for the Pal shell. The easiest way to accomplish this is to subclass Pal::Context
, which provides the _
and inspect
methods. _
is a syntactic sugar for retrieving the result of the last-evaluated expression.
Note that Ruby's semantics prohibit accessing dynamically-defined local variables from different contexts. As such, attempting to set and subsequently access a local variable in Pal will fail. You can use an instance variable to store a value for later use; alternatively, @_
and its attribute reader _
hold the last-evaluated value.
Finally, Pal prints a human-readable representation of the result, which is concurrently stored in the @_
instance variable. This allows subsequent expressions to conveniently reference the previous value. If an exception was raised while evaluating the code, an irb
-style stack trace is printed and the value of @_
is not modified.
The exit
and quit
commands, as well as the end-of-file (Control+D) and interrupt (Control+C) signals terminate the loop.
Installation
$ {sudo} gem install pal
Example Shell
The following code initializes and starts a shell for the ExecJS library:
# Define the shell commands in the evaluation context.
class Context < Pal::Context
%w{execjs pal open-uri}.each(&method(:require))
def initialize
@sources = {}
end
def coffee(source)
context = @sources[:coffee] ||= ExecJS.compile(open("http://jashkenas.github.com/coffee-script/extras/coffee-script.js").read)
context.call("CoffeeScript.compile", source, :bare => true)
end
def compile(source)
ExecJS.compile source
end
def evaluate(source)
ExecJS.eval source
end
end
# Start the shell.
Pal::REPL.new("execjs", Context.new).loop
The ExecJS shell may then be used like so:
execjs> coffee "square = (x) -> x * x"
=> "var square;\n\nsquare = function(x) {\n return x * x;\n};\n"
execjs> compile _
=> #<ExecJS::ExternalRuntime::Context ...>
execjs> _.call("square", 5)
=> 25
execjs> def square(value)\
......> value ** 2\
......> end
=> nil
execjs> square 10
=> 100
execjs> evaluate "#{_} / 4"
=> 25
Contributing
Check out a working copy of the Pal source code with Git:
$ git clone git://github.com/kitcambridge/pal.git
If you'd like to contribute a feature or bug fix, you can fork Pal, commit your changes, and send a pull request. Please make sure to update the unit tests in the tests
directory as well.
Alternatively, you can use the GitHub issue tracker to submit bug reports and feature requests.
MIT License
Copyright © 2011 Kit Cambridge.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.