[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