in reply to Tab completion in a shell

Something like this?

whacl> <tab><tab>
dig          help         llocks       need_commit  rcs          unlock
exit         list         lock         perform      touch_lm     untouch_lm

whacl> help rcs
Usage: rcs <rtr>

whacl> rcs rtrA
rcs(rtrA)> <tab><tab>
exit        help        lock        publish     syncronize  unlock

rcs(rtrA)> exit 
whacl> help lock
Usage: lock <rtr> <acl>

whacl> lock rtrA external-blocks
acl(rtrA,external-blocks)> <tab><tab>
block            help             list             unlock_and_exit

acl(rtrA,external-blocks)> block 192.168.254.1/32
block(192.168.254.1/32)> <tab><tab>
case     end      freshen  insert   mac      note     priv     status
delete   exit     help     list     modify   options  show     update

block(192.168.254.1/32)> delete
block(192.168.254.1/32)> exit 
acl(rtrA,external-blocks)> unlock_and_exit 
whacl> exit 

This goes something like:

use Q::Shell; use Q::RCSShell; use Q::ACLShell; use Q::WhaclShell; Q::WhaclShell->new ( prompt => 'whacl> ' )->loop(); exit 0; ##### use Q::Shell; package Q::WhaclShell; our (@ISA) = qw( Q::Shell ); sub new { my ($class,%param) = @_; # blah blah SUPER::new $self->add_dispatch( rcs => [ \&_rcs, "short help", "long help" ], lock => [ \&_lock, "short help", "long help" ], # ... ); return $self; } sub _rcs { my ($self,@arg) = @_; Q::RCSShell->new( )->loop(@arg); } sub _lock { my ($self,@arg) = @_; Q::ACLShell->new( )->loop(@arg); } 1; # and so on for Q::RCSShell and Q::ACLShell package Q::Shell; my %default_commands = ( help => [ \&_help, "short help", "long help" ], exit => [ \&_exit, "short help", "long help" ], ); sub add_dispatch { } sub del_dispatch { } sub _cmd_list { keys %{$_[0]->{_dispatch}} } sub _help { # help - show all short help # help <cmd> - show long help for <cmd> } sub _exit { $_[0]->{done} = 1 } sub new { # setup ReadLine # copy default_commands to $self->{_dispatch} return $self; } sub dispatch { # find and do <cmd> or warn whatever } sub loop { # setup ReadLine with completions from $self->_cmd_list while ( not $self->{done} ) { # read and dispatch <cmd> <args> # reset ReadLine stuff (a command may have changed them) } } 1;