[pve-devel] applied: [PATCH common 2/2] bash completion: complete fully specified command

Dietmar Maurer dietmar at proxmox.com
Fri Jun 8 06:30:40 CEST 2018


applied

> On June 7, 2018 at 11:59 AM Wolfgang Bumiller <w.bumiller at proxmox.com> wrote:
> 
> 
> This contains 2 functional changes:
> 
> First: resolve_cmd no longer keeps a hash of which arguments
> were expanded. This information is not required and not used
> properly: For one it would conflict if the same word
> appeared twice in a longer subcommand, and secondly we lose
> the information when recursing into an alias anyway. And
> lastly, we do not support tab completing multiple parameters
> simultaneously anyway (as in, `pveum u a<tab>` does not
> become `pveum user add`).
> So now we simply return the expanded version of the last
> command or undef if it was unknown in place of the hash we
> returned previously.
> 
> The second change is how we use the new returned value:
> Previously if resolve_cmd() returned a new subcommand in
> $def we skipped over finishing the last word. Of course, if
> the command was already fully specified (but no space put
> after it), we already considered it complete and returned
> the new $def.
> This condition can be detected as in this case the $prev
> command equals the $cur command. (Additionally, the $cur
> command is either '' (after the space) or also the $prev
> command (before the space), but checking this would only be
> required when the same word can actually appear multiple
> times in a row in a sub command chain...)
> This case now takes precedence over looking through the
> nested $def, so that bash will put the space after a full
> command which requires another subcommand to be added.
> 
> Signed-off-by: Wolfgang Bumiller <w.bumiller at proxmox.com>
> ---
>  src/PVE/CLIHandler.pm | 35 ++++++++++++++++++++++-------------
>  1 file changed, 22 insertions(+), 13 deletions(-)
> 
> diff --git a/src/PVE/CLIHandler.pm b/src/PVE/CLIHandler.pm
> index 62a61a7..8c911b2 100644
> --- a/src/PVE/CLIHandler.pm
> +++ b/src/PVE/CLIHandler.pm
> @@ -52,11 +52,12 @@ my $abort = sub {
>  my $expand_command_name = sub {
>      my ($def, $cmd) = @_;
>  
> -    if (!$def->{$cmd}) {
> -	my @expanded = grep { /^\Q$cmd\E/ } keys %$def;
> -	return $expanded[0] if scalar(@expanded) == 1; # enforce exact match
> -    }
> -    return $cmd;
> +    return $cmd if exists $def->{$cmd}; # command is already complete
> +
> +    my @expanded = grep { /^\Q$cmd\E/ } keys %$def;
> +    return $expanded[0] if scalar(@expanded) == 1; # enforce exact match
> +
> +    return undef;
>  };
>  
>  my $get_commands = sub {
> @@ -78,20 +79,27 @@ sub resolve_cmd {
>      my $cmdstr = $exename;
>  
>      if (ref($argv) eq 'ARRAY') {
> -	my $expanded = {};
> +	my $expanded_last_arg;
>  	my $last_arg_id = scalar(@$argv) - 1;
>  
>  	for my $i (0..$last_arg_id) {
>  	    $cmd = $expand_command_name->($def, $argv->[$i]);
> +	    if (defined($cmd)) {
> +		# If the argument was expanded (or was already complete) and it
> +		# is the final argument, tell our caller about it:
> +		$expanded_last_arg = $cmd if $i == $last_arg_id;
> +	    } else {
> +		# Otherwise continue with the unexpanded version of it.
> +		$cmd = $argv->[$i]; 
> +	    }
>  	    $cmdstr .= " $cmd";
> -	    $expanded->{$argv->[$i]} = $cmd if $cmd ne $argv->[$i];
>  	    last if !defined($def->{$cmd});
>  	    $def = $def->{$cmd};
>  
>  	    if (ref($def) eq 'ARRAY') {
>  		# could expand to a real command, rest of $argv are its arguments
>  		my $cmd_args = [ @$argv[$i+1..$last_arg_id] ];
> -		return ($cmd, $def, $cmd_args, $expanded, $cmdstr);
> +		return ($cmd, $def, $cmd_args, $expanded_last_arg, $cmdstr);
>  	    }
>  
>  	    if (defined($def->{alias})) {
> @@ -104,7 +112,7 @@ sub resolve_cmd {
>  	# got either a special command (bashcomplete, verifyapi) or an unknown
>  	# cmd, just return first entry as cmd and the rest of $argv as cmd_arg
>  	my $cmd_args = [ @$argv[1..$last_arg_id] ];
> -	return ($argv->[0], $def, $cmd_args, $expanded, $cmdstr);
> +	return ($argv->[0], $def, $cmd_args, $expanded_last_arg, $cmdstr);
>      }
>      return ($cmd, $def, undef, undef, $cmdstr);
>  }
> @@ -313,12 +321,13 @@ my $print_bash_completion = sub {
>      if (!$simple_cmd) {
>  	($cmd, $def, $args, my $expanded) = resolve_cmd($args);
>  
> -	if (ref($def) eq 'HASH') {
> -	    &$print_result(@{$get_commands->($def)});
> +	if (defined($expanded) && $prev ne $expanded) {
> +	    print "$expanded\n";
>  	    return;
>  	}
> -	if (my $expanded_cmd = $expanded->{$cur}) {
> -	    print "$expanded_cmd\n";
> +
> +	if (ref($def) eq 'HASH') {
> +	    &$print_result(@{$get_commands->($def)});
>  	    return;
>  	}
>      }
> -- 
> 2.11.0
> 
> 
> _______________________________________________
> pve-devel mailing list
> pve-devel at pve.proxmox.com
> https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel



More information about the pve-devel mailing list