[Ruby] tools for building a "smart" command-line language

Doug Beaver doug at beaver.net
Mon Aug 28 15:58:22 PDT 2006


On Mon, Aug 28, 2006 at 01:56:46PM -0700, Scott Laird wrote:
> I'm looking for a set of Ruby tools that probably don't exist.  If
> they do, I've never been able to find them.
> 
> I'd like to write a tool that has a command-line langauge similar to
> Cisco IOS.  This would include:
>  - context-sensitive command-completion
>  - context-sensitive help
>  - ability to parse a simple language and turn it into an AST
>  - ability to turn an AST back into source code
>  - some ability to do blocks.  IOS has structures like this:
> 
> interface FastEthernet0/0
>   ip address 1.2.3.4
>   ...
> end

you may be able to make good progress by combining ParseTree with a pure
ruby DSL.  for example, i like how mongrel's configurator works:

config = Mongrel::Configurator.new :host => "127.0.0.1" do
  listener :port => 3000 do
    uri "/app", :handler => Mongrel::DirHandler.new(".", load_mime_map("mime.yaml"))
  end
  run
end

webrick uses something similar iirc.

i don't know if you could get the exact syntax IOS provides, but you
could get pretty close:

interface "FastEthernet0/0" do
  ip "192.168.0.1"
  broadcast "255.255.255.0"
end

i've seen small DSLs like this quite often in ruby land, and with a
little bit of work, you could even do things like detect when an invalid
config is applied to an interface block, etc, etc.  for example, if i
did:

interface "FastEthernet0/0" do
  ip "192.168.0.1"
  color :blue
end

it could detect that color is not a valid config option for an
interface.

the completion stuff might come from readline or a similar beast,
although if you want contextual completion, that will take extra effort,
i think.  when i say contexual completion, i mean when i type ping and
hit tab, it tabs through a list of common hostnames i like to ping.

> The 'interface' command starts a new block; inside that block a
> different set of grammar rules applies.
> 
>  - finally, you should be able to extend the grammar via plugins.  In
> a Rails context, new code in vendor/plugins would be able to add new
> commands to the language without patching the One Big Grammar File.

gem_plugin is a nice way to support plugins.  i don't think you need a
grammar if you're doing a pure ruby DSL, you just need a way to define
common modules (interface, host, listener, whatever) and declare how
they can be extended.  then it's pretty simple to hook that into
gem_plugin and let people write their own plugins for your framework.

i'm not sure why you require the language to go back and forth between
the AST, are you looking to validate it?  or is there some magic i'm
missing?

doug

-- 
"Contrary to what most people say, the most dangerous animal in the
world is not the lion or the tiger or even the elephant.  It's a shark
riding on an elephant's back, just trampling and eating everything they
see." -- Jack Handey


More information about the Ruby mailing list