Feb 27

Ruby Shell as Domain Specific Language

Category: Programming, Ruby

My favorite example of a DSL is the latest jmock API just because you really have to fight the language. Fortunately Ruby makes things easier. I’ve been thinking a shell in ruby might be a nice change of pace so this is a small example of how to go about implementing one.


The Language


So basically I’d like to be able to do something like the following at a shell-like prompt:

dir1 = dir("sub1")
dir2 = dir("sub2")
dir1.list("*"){|x| cp(x, dir2)}

Eval and Binding


So the way to do this in Ruby is to use the Kernel::eval method and Ruby’s binding feature. Kernel::eval simply interprets Ruby test presented as a string. Binding allows you to execute that string within a particular namespace binding from the code. For instance:

class MyClass
    def initialize()
        @name = "bob"
    end
 
    def internal_binding
        binding //returns the name bindings in this context
    end
end
 
m = MyClass.new()
eval('@name', m) //evals to bob!
eval('@number=52', m) //sets m.@number = 52

Implementing the Language


So to create my language all I really need to do is this

class Location
    def initialize(path)
        @full_path = File.expand_path(path)
    end
 
    def dir(path)
        Location.new(File.expand_path(path, @full_path))
    end
 
    def chdir(path)
        @full_path = File.expand_path(path, @full_path)
    end
 
    def list(pattern)
        Dir.glob(@full_path + "//" + pattern).collect!{ 
            |x| Location.new(x) 
        }
    end
 
    def get_binding()
        binding
    end
 
    def full_name
        @full_path
    end
 
   def cp(source, dest)
      //...etc
   end
end
 
 
default = Location.new(".")
b = default.get_binding
STDOUT.write(">> ")
while( (line = STDIN.gets()) != "") do
    begin
        eval(line, b)
    rescue SystemExit
        raise
    rescue Exception => ex
        puts ex.message
    end
    STDOUT.write(">> ")
end

The Author

Michael Smit is a software engineer in Seattle, Washington who works for amazon

Comments are off for this post

Comments are closed.