使用 Click 命令别名的常规用法输出
Regular usage output with Click command aliases
我正在为我的自定义组(来自 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
的覆盖版本,returns 也是原始命令名称。但这可能会破坏一些东西,也许有更简单的方法。
完整代码:
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')
您需要跟踪使用的别名。
别名保存在全局变量中,因为 click
使用了很多上下文实例。
并且您需要实现自己的 HelpFormatter。这涵盖了帮助结构的所有用途。
在 write_usage
中用完整的命令名称替换别名。跟踪填充的别名以涵盖 test_core a a -h
的情况作为 test_core add auto -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.
我正在为我的自定义组(来自 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
的覆盖版本,returns 也是原始命令名称。但这可能会破坏一些东西,也许有更简单的方法。
完整代码:
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')
您需要跟踪使用的别名。
别名保存在全局变量中,因为 click
使用了很多上下文实例。
并且您需要实现自己的 HelpFormatter。这涵盖了帮助结构的所有用途。
在 write_usage
中用完整的命令名称替换别名。跟踪填充的别名以涵盖 test_core a a -h
的情况作为 test_core add auto -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.