A miniature Ruby shell.
Ruby
Switch branches/tags
Nothing to show
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
bin
lib
test
LICENSE
README.md
Rakefile
pal.gemspec

README.md

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.