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

Scott Laird scott at sigkill.org
Mon Aug 28 16:08:47 PDT 2006


On 8/28/06, Doug Beaver <doug at beaver.net> wrote:
> 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?

Yeah.  You're missing the use case that I didn't mention.  I want  to
be able to do the equivalent of this:

$ interface FastEthernet0/0
interface$ ip 192.168.0.2
interface$ end

That is, make small incremental changes via a commandline interface.
That's kind of the point of the whole thing :-).  This little change
needs to be persisted back to a static config file *and* it needs to
trigger some action in the system.


Scott


More information about the Ruby mailing list