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

Is click.MultiCommand supported? #38

Closed
nilsvu opened this issue Mar 8, 2022 · 6 comments · Fixed by #123
Closed

Is click.MultiCommand supported? #38

nilsvu opened this issue Mar 8, 2022 · 6 comments · Fixed by #123

Comments

@nilsvu
Copy link

nilsvu commented Mar 8, 2022

Here's a minimal example using click.MultiCommand for lazy loading of subcommands. Is this already supported and I just haven't figured out how to use it, or is this not supported yet?

import rich_click as click

class Cli(click.MultiCommand):
    def list_commands(self, ctx):
        return ["foo"]

    def get_command(self, ctx, name):
        if name == "foo":
            from foo import bar
            return bar
        raise NotImplementedError(f"The command '{name}' is not implemented.")

@click.group(cls=Cli)
def cli():
    pass
@nilsvu nilsvu changed the title Is click.MultiCommand supported? Is click.MultiCommand supported? Mar 8, 2022
@ewels
Copy link
Owner

ewels commented Mar 8, 2022

Rich-click works by overwriting the default cls used in the @group decorator, so if you define your own like in this example it will overwrite rich-click and use default click.

You can explicitly use the rich-click classes to get around this (see example) but yeah - we don't have a rich_click.MultiCommand yet.

I guess it should be possible to add support for this though. Need to do something similar to the Command one.

@Hollander-1908
Copy link

Hollander-1908 commented May 10, 2023

Any ETA on this? Would love to use rick-click but can't use it without .MultiCommand...

@ewels
Copy link
Owner

ewels commented May 10, 2023

No ETA sorry, no. Happy to accept PRs to tackle this though.

@hsunner
Copy link

hsunner commented Jun 8, 2023

According to click docs click.Command.format_help() method calls .format_usage(), .format_help_text(), .format_options() and .format_epilog() for the actual output. In contrast, rich_format_help(), which is used in RichCommand, appears to be a a single block of code.

class click.MultiCommand(Command) overrides .format_options() which calls the parent's .format_options() and then its own .format_commands() which does three things when outputting the subcommands:

  1. ignores empty commands (loading function returned None)
  2. ignores commands with the .hidden property
  3. Adds "extra space" between command name and the short help string

Perhaps 1. and 2. can/should be added to rich_format_help() (unless the logic already exists), but it seems that it works fine on MultiCommands as it is. A simple solution to @nilsvu's problem seems to be overriding the .format_help() of MultiCommand by the same code used in rich_click.Command (as suggested by @ewels). This solution works fine for me.

class Cli(click.MultiCommand):
    ...
    def format_help(self, ctx: click.Context, formatter: click.HelpFormatter):
        rich_format_help(self, ctx, formatter)

@nilsvu
Copy link
Author

nilsvu commented Jun 8, 2023

Thanks @hsunner, that's very helpful and works well! Sounds like simply subclassing click.MultiCommand as rich_click.MultiCommand and overriding format_help and main like for the standard command would do it.

@dwreeves
Copy link
Collaborator

dwreeves commented Oct 4, 2023

We can have a slightly better and more "official" solution for this shortly. TLDR: it should be straightforward to add a rich_click.RichMultiCommand object in 1.7.0. Stay tuned.

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

Successfully merging a pull request may close this issue.

5 participants