[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