具有单击命令别名的常规用法输出

2024-09-29 22:28:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我将此代码段用于我的自定义组(来自here),以允许使用前缀

class AliasedGroup(click.Group):
    def get_command(self, ctx, cmd_name):
        rv = click.Group.get_command(self, ctx, cmd_name)
        if rv is not None:
            return rv
        matches = [x for x in self.list_commands(ctx)
                   if x.startswith(cmd_name)]
        if not matches:
            return None
        elif len(matches) == 1:
            return click.Group.get_command(self, ctx, matches[0])
        ctx.fail('Too many matches: %s' % ', '.join(sorted(matches)))

但是,使用情况输出变得非常愚蠢:它显示命令的前缀,而不是完全显示它们:

Usage: test_core a c [OPTIONS]

我想看看

Usage: test_core add combined [OPTIONS]

甚至当我调用test_core a c -h

我已经调查过了,但似乎没有明显的解决办法。格式化程序逻辑不知道它们的原始名称。也许可以重写MultiCommand.resolve_command来处理MultiCommand/Group.get_command的重写版本,该版本也返回原始命令名。但这可能会破坏一些东西,也许有更简单的方法

完整代码:

import click

class AliasedGroup(click.Group):
    def get_command(self, ctx, cmd_name):
        rv = click.Group.get_command(self, ctx, cmd_name)
        if rv is not None:
            return rv
        matches = [x for x in self.list_commands(ctx)
                    if x.startswith(cmd_name)]
        if not matches:
            return None
        elif len(matches) == 1:
            return click.Group.get_command(self, ctx, matches[0])
        ctx.fail('Too many matches: %s' % ', '.join(sorted(matches)))

@click.group(cls=AliasedGroup, context_settings={'help_option_names': ['-h', '--help']})
def cli():
    pass

@cli.group(cls=AliasedGroup)
def add():
    pass

@add.command()
@click.option('--yarr')
def combined():
    pass

cli(['a', 'c', '-h'], prog_name='test_core')

Tags: nameselfcmdgetreturnifdefgroup
1条回答
网友
1楼 · 发布于 2024-09-29 22:28:27

您需要跟踪使用的别名

别名保存在全局变量中,因为click使用了大量上下文实例

您需要实现自己的HelpFormatter。这涵盖了帮助构造的所有用途

write_usage中,用完整的命令名替换别名。作为test_core add auto -h的命令,跟踪填充的别名以覆盖test_core a a -h的情况。如果在prog中找不到别名,请不要尝试使用下一个别名(while而不是for

import click

clickAliases = []

class AliasedGroup(click.Group):
    def get_command(self, ctx, cmd_name):
        rv = click.Group.get_command(self, ctx, cmd_name)
        if rv is not None:
            return rv
        matches = [x for x in self.list_commands(ctx)
                    if x.startswith(cmd_name)]
        if not matches:
            return None
        elif len(matches) == 1:
            clickAliases.append((cmd_name, matches[0]))
            return click.Group.get_command(self, ctx, matches[0])
        ctx.fail('Too many matches: %s' % ', '.join(sorted(matches)))

class MyHelpFormatter(click.HelpFormatter):
    def write_usage(self, prog, args="", prefix="Usage: "):
        if clickAliases:
            parts = prog.split()
            partIdx = 0
            for alias,cmd in clickAliases:
                while partIdx < len(parts):
                    if parts[partIdx] == alias:
                        parts[partIdx] = cmd
                        partIdx += 1
                        break
                    partIdx += 1
            prog = ' '.join(parts)
        click.HelpFormatter.write_usage(self, prog, args, prefix)

def make_formatter(self):
    return MyHelpFormatter(width=self.terminal_width, max_width=self.max_content_width)
click.Context.make_formatter = make_formatter
# version 8.x makes if easier with
# click.Context.formatter_class = MyHelpFormatter

@click.group(cls=AliasedGroup, context_settings={'help_option_names': ['-h', ' help']})
def cli():
    pass

@cli.group(cls=AliasedGroup)
def add():
    click.echo("add command")

@add.command()
@click.option(' yarr')
def combined(yarr):
    click.echo(f"combined command: {yarr}")

# simulate command arguments - for debugging
# cli(['a', 'c', '-h'], prog_name='test_core')

# normal start
cli(prog_name='test_core')

终端输出

$ python test_core.py a c -h
add command
Usage: test_core add combined [OPTIONS]

Options:
   yarr TEXT
  -h,  help   Show this message and exit.

相关问题 更多 >

    热门问题