summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Southworth <john.southworth@vyatta.com>2012-03-22 10:27:10 -0700
committerJohn Southworth <john.southworth@vyatta.com>2012-03-22 10:27:10 -0700
commit75e35444bac07e0511ed74dcdbe89a5b088c79e7 (patch)
treeeacd1799710a4d14dd2afd5099aeb815ad8c9b7a
parent08017ee0641f23b1dd501cc8567da5a6f0fdfdce (diff)
downloadvyatta-op-75e35444bac07e0511ed74dcdbe89a5b088c79e7.tar.gz
vyatta-op-75e35444bac07e0511ed74dcdbe89a5b088c79e7.zip
Make ping feel like all the other system commands
-rw-r--r--etc/bash_completion.d/vyatta-op4
-rwxr-xr-xscripts/ping110
-rw-r--r--templates/ping/node.tag/node.tag/node.def2
3 files changed, 104 insertions, 12 deletions
diff --git a/etc/bash_completion.d/vyatta-op b/etc/bash_completion.d/vyatta-op
index 65dd701..22eea12 100644
--- a/etc/bash_completion.d/vyatta-op
+++ b/etc/bash_completion.d/vyatta-op
@@ -150,6 +150,10 @@ _vyatta_op_help ()
[ -f $ndef ] && \
node_run=$( _vyatta_op_get_node_def_field $ndef run )
+ if [[ "$1" == "<nocomps>" ]]; then
+ eval "$restore_shopts"
+ return
+ fi
echo -en "\nPossible completions:"
if [ -z "$cur" -a -n "$node_run" ]; then
_vyatta_op_print_help '<Enter>' "Execute the current command"
diff --git a/scripts/ping b/scripts/ping
index 0f9b241..0f85e8f 100755
--- a/scripts/ping
+++ b/scripts/ping
@@ -43,19 +43,44 @@ use feature ":5.10";
sub get_options {
my ($opt, $args) = @_;
+ my $orig_arg = $$args[-1];
+
+ # expand the variables
+ if (scalar(@$args) > 2){
+ $args = expand_args($opt, $args);
+ }
+
my $prev = $$args[-2];
my $arg = $$args[-1];
- # print type text for arguments
- if ( exists($opt->{$arg}) && $opt->{$arg}->{type} ne "noarg" ){
- get_args($opt, $arg);
+
+ # do something similar to compgen
+ my $options = '';
+ if ($arg ne ''){
+ my @matches = grep { /^$arg/ } keys(%{$opt});
+ if (scalar(@matches) == 0){
+ if ( (exists($opt->{$prev}) && $opt->{$prev}->{type} ne "noarg") ) {
+ get_args($opt, $prev);
+ }
+ }
+ $options = join " ", @matches;
+ print $options;
+ exit 0;
}
+
+ if ( (exists($opt->{$prev}) && $opt->{$prev}->{type} ne "noarg") ) {
+ get_args($opt, $prev);
+ }
+
# only show options that we haven't used yet
- my $options = '';
foreach my $key (keys(%{$opt})){
- next if (grep $_ eq $key, @{$args});
+ next if (grep $_ eq $key, @{$args}) ;
$options .= "$key ";
}
- print $options;
+ if ($options eq '' ){
+ print '<Enter>';
+ } else {
+ print $options;
+ }
exit 0;
}
@@ -65,6 +90,66 @@ sub get_args {
exit 0;
}
+sub expand_args {
+ my ($opt, $args) = @_;
+ my @expand_args = ();
+ my $index = 0;
+ my $prev = undef;
+ foreach my $arg (@$args){
+ $index++;
+ if ($index == 1 || $index == 2) {
+ push @expand_args, $arg;
+ next;
+ }
+ if ( $arg eq '' ){
+ push @expand_args, $arg;
+ next;
+ }
+ if ( (exists($opt->{$arg}) && $opt->{$arg}->{type} ne "noarg") ) {
+ push @expand_args, $arg;
+ $prev = $arg;
+ next;
+ }
+ my ($err, @vals) = expand_arg($opt, $arg, $prev);
+ if (defined($err)) {
+ my $val = pop @$args;
+ pop @$args if ($val eq '');
+ if ( $err eq "ambiguous" ){
+ print STDERR "\n\n Ambiguous command: @{$args} [$arg]\n\n";
+ print STDERR " Possible completions:\n";
+ print STDERR " $_\n" foreach @vals;
+ print '<nocomps>';
+ } else {
+ print STDERR "\n\n Invalid command: @{$args} [$arg]\n";
+ print '<nocomps>';
+ }
+ exit 1;
+ }
+ # print type text for arguments
+ $arg = $vals[0];
+ push @expand_args, $arg;
+ $prev = $arg;
+ }
+ return \@expand_args;
+}
+
+sub expand_arg {
+ my ($opt, $arg, $prev) = @_;
+ my @opts = grep { /^$arg/ } keys(%{$opt});
+ my @prevs = grep { /^$prev/} keys(%{$opt}) if defined($prev);
+ if (scalar(@opts) == 1 ){
+ return (undef, $opts[0]);
+ } elsif ($arg eq '') {
+ return (undef, $arg);
+ } elsif (defined($prev) && defined($opt->{$prev}) && $opt->{$prev}->{type} ne 'noarg'){
+ return (undef, $arg);
+ } elsif (scalar(@opts) == 0 ) {
+ return ('invalid', undef);
+ } else {
+ return ('ambiguous', @opts);
+ }
+}
+
# Table for translating options to arguments
my %options = (
'audible' => { 'p_arg'=>'a',
@@ -136,8 +221,8 @@ my $host = shift @ARGV;
die "ping: Missing host\n"
unless defined($host);
if ($host eq "--get-options"){
- my @args = @ARGV;
- get_options(\%options, \@args);
+ my @comp_args = @ARGV;
+ get_options(\%options, \@comp_args);
}
my $ip = new NetAddr::IP $host;
die "ping: Unknown host: $host\n"
@@ -153,8 +238,10 @@ given ($ip->version) {
}
my @cmdargs = ( 'ping' );
-
-while (my $arg = shift @ARGV) {
+my $args = [ 'ping', $host, @ARGV ];
+$args = expand_args(\%options, $args);
+shift @$args; shift @$args;
+while (my $arg = shift @$args) {
my $pingarg = $options{$arg}->{p_arg};
die "ping: unknown option $arg\n"
unless $pingarg;
@@ -163,11 +250,12 @@ while (my $arg = shift @ARGV) {
push @cmdargs, $flag;
if (rindex($pingarg, ':') != -1) {
- my $optarg = shift @ARGV;
+ my $optarg = shift @$args;
die "ping: missing argument for $arg option\n"
unless defined($optarg);
push @cmdargs, $optarg;
}
}
+print "@cmdargs\n";
exec { $cmd } @cmdargs, $host;
diff --git a/templates/ping/node.tag/node.tag/node.def b/templates/ping/node.tag/node.tag/node.def
index 9452558..cca366b 100644
--- a/templates/ping/node.tag/node.tag/node.def
+++ b/templates/ping/node.tag/node.tag/node.def
@@ -1,3 +1,3 @@
help: Ping options
-allowed: /opt/vyatta/bin/ping --get-options ${COMP_WORDS[@]}
+allowed: /opt/vyatta/bin/ping --get-options "${COMP_WORDS[@]}"
run: /opt/vyatta/bin/ping ${@:2}