★ wanayoo — archive 1999 https://github.com/python-cmd2/cmd2/issues/992Nouvelle recherche | Portail wanayoo
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for partial commands #992

Open
ralequi opened this issue Sep 3, 2020 · 4 comments
Open

Support for partial commands #992

ralequi opened this issue Sep 3, 2020 · 4 comments

Comments

@ralequi
Copy link

@ralequi ralequi commented Sep 3, 2020

Some shells accept and interpret partial commands and it would be a great feature to be included.

Let's take a look an example:
By default cmd2 includes quit command, which is used to end the cmd-session.
In many scenarios, it would be useful to allow the user just write q to get the same functionality.
Of course cmd2 support many ways of doing this, such as alias, macros or shortcuts, however, all of them should be created "manually" for each command.

Of course, there may be conflicts such not always the first letter could be used.
Let's say we have 2 different commands called stop and show (that can be found in many shells that support this kind of things).
In this scenario, it would be great to automatically cmd2 allow using sh or sho as an alias of the command show, in the same way as st or sto as alias of stop. Of course s have 2 possible candidates, so it may be considered just an invalid/incomplete command.

A possible implementation:
One possible implementation that may even work with subcommands is simple:
1 - the user input a command
2.1 - If the command exists or is an alias execute it as always
2.2 - if the commands does not exists, call autocomplete
3.1 - if the autocomplete returns none or more than 1 results, return invalid command as always
3.2 - if the autocomplete returns exactly one result, try to run that one and store it as if the user has written it down.

@ralequi ralequi closed this Sep 3, 2020
@ralequi ralequi reopened this Sep 3, 2020
@ralequi
Copy link
Author

@ralequi ralequi commented Sep 3, 2020

I've made the following hook that does that simple implementation.

# hook version 2
def hook_autocomplete(self, params: cmd2.plugin.PostparsingData) -> cmd2.plugin.PostparsingData:

    func = self.cmd_func(params.statement.command)
    if not func:
        basecmd = self.complete(params.statement.command, 0)
        nextcmd = self.complete(params.statement.command, 1)
        if(basecmd is not None and nextcmd is None):
            basecmd = basecmd[:-1]
            params.statement = Statement(params.statement.args,
                                         raw=params.statement.raw,
                                         command=basecmd,
                                         arg_list=params.statement.arg_list,
                                         multiline_command=params.statement.multiline_command,
                                         terminator=params.statement.terminator,
                                         suffix=params.statement.suffix,
                                         pipe_to=params.statement.pipe_to,
                                         output=params.statement.output,
                                         output_to=params.statement.output_to)

    return params

Seems to works great but It should also support concatenations of partial commands.
Example: we have a command show, with a subcomand interface... In order to fully support partial commands sh int should be an alias to show interface.

@anselor
Copy link
Contributor

@anselor anselor commented Sep 3, 2020

I've never actually used it but I know we have this plugin for abbreviated command support. It seems very similar to what you're describing.

https://github.com/python-cmd2/cmd2-abbrev

@kmvanbrunt
Copy link
Member

@kmvanbrunt kmvanbrunt commented Sep 3, 2020

@ralequi Calling complete() directly to resolve subcommand names will be problematic since your hook doesn't know what tokens are intended to be subcommands. cmd2.ArgparseCompleter figures this out by parsing the command line using knowledge of the command's argparser.

Since argparse only supports abbreviation of long options names, and not subcommands, there isn't an easy way to do what you're asking without writing code to examine the tokens in the same way cmd2.ArgparseCompleter does. If you are interested in writing such an approach, look at cmd2.ArgparseCompleter.complete_subcommand_help() for guidance.

If you have a known set of aliases you'd like to use for subcommands, you can take advantage of argparse subcommand aliases.

From argparse docs

Furthermore, add_parser supports an additional aliases argument, which allows multiple strings to refer to the same subparser. This example, like svn, aliases co as a shorthand for checkout:

parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
checkout = subparsers.add_parser('checkout', aliases=['co'])
checkout.add_argument('foo')
parser.parse_args(['co', 'bar'])

cmd2.ArgparseCompleter supports subcommand aliases as well, so they will tab complete.

@ralequi
Copy link
Author

@ralequi ralequi commented Sep 4, 2020

Thanks for your replies guys,

@anselor that plugin looks great but it seems to do something like I did in that hook. It should work great but unless I'm missing something it would have the same limitation that my hook has, as far as it should not be able to autocomplete sub-commands.

Thanks @kmvanbrunt , I supposed a simple hook won't be able to do what I wish. I have to finish some basic functionality on my APP, but I consider this feature very powerful (and mostly required to my clients, as they come from managing cisco/juniper like devices) so I'll look forward to it when I finish that basic func.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants
You can’t perform that action at this time.