python - How can command list display be categorised within a Click chained group?
问题描述
I'm starting a CLI pipe-type application project which will eventually have a rather large collection of commands (which will be further extensible with plug-in). As a result, I would like to categorise them in the --help
text:
Here is how it looks now:
Usage: my_pipe [OPTIONS] COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]...
Options:
--help Show this message and exit.
Commands:
another_filter help about that filter
another_generator help about that generator
another_sink help about that sink
some_filter help about this filter
some_generator help about this generator
some_sink help about this sink
This is more or less how I would like it to look:
Usage: my_pipe [OPTIONS] COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]...
Options:
--help Show this message and exit.
Commands:
Generators:
some_generator help about this generator
another_generator help about that generator
Filters:
some_filter help about this filter
another_filter help about that filter
Sinks:
some_sink help about this sink
another_sink help about that sink
How can this be achieved? Note that apart from the look of --help
, I'm happy with the flat logical command organisation. Also, sub-groups are not an option as they are not allowed inside a chain=True
group.
解决方案
如果您继承自click.Group
您可以添加一些代码来对命令进行分组,然后在帮助中显示这些组。
自定义类
class GroupedGroup(click.Group):
def command(self, *args, **kwargs):
"""Gather the command help groups"""
help_group = kwargs.pop('group', None)
decorator = super(GroupedGroup, self).command(*args, **kwargs)
def wrapper(f):
cmd = decorator(f)
cmd.help_group = help_group
return cmd
return wrapper
def format_commands(self, ctx, formatter):
# Modified fom the base class method
commands = []
for subcommand in self.list_commands(ctx):
cmd = self.get_command(ctx, subcommand)
if not (cmd is None or cmd.hidden):
commands.append((subcommand, cmd))
if commands:
longest = max(len(cmd[0]) for cmd in commands)
# allow for 3 times the default spacing
limit = formatter.width - 6 - longest
groups = {}
for subcommand, cmd in commands:
help_str = cmd.get_short_help_str(limit)
subcommand += ' ' * (longest - len(subcommand))
groups.setdefault(
cmd.help_group, []).append((subcommand, help_str))
with formatter.section('Commands'):
for group_name, rows in groups.items():
with formatter.section(group_name):
formatter.write_dl(rows)
使用自定义类
要使用自定义类,请使用cls
参数将类传递给click.group()
装饰器。
@click.group(cls=GroupedGroup)
def cli():
"""My awesome cli"""
然后为每个命令标记要包含的命令的帮助组,如下所示:
@cli.command(group='A Help Group')
def command():
"""This is a command"""
这是如何运作的?
这是因为 click 是一个设计良好的 OO 框架。@click.group()
装饰器通常实例化一个对象click.Group
,但允许使用cls
参数覆盖此行为。因此,从click.Group
我们自己的类中继承并覆盖所需的方法是一件相对容易的事情。
在这种情况下,我们覆盖click.Group.command()
装饰器以收集每个命令所需的帮助组。然后我们在构建帮助时覆盖click.Group.format_commands()
使用这些组的方法。
测试代码
import click
@click.group(cls=GroupedGroup)
def cli():
"""My awesome cli"""
@cli.command(group='Generators')
def some_generator():
"""This is Some Generator"""
@cli.command(group='Generators')
def another_generator():
"""This is Another Generator"""
@cli.command(group='Filters')
def some_filter():
"""This is Some Filter"""
@cli.command(group='Filters')
def another_filter():
"""This is Another Filter"""
cli()
结果
Usage: test.py [OPTIONS] COMMAND [ARGS]...
My awesome cli
Options:
--help Show this message and exit.
Commands:
Filters:
another-filter This is Another Filter
some-filter This is Some Filter
Generators:
another-generator This is Another Generator
some-generator This is Some Generator
推荐阅读
- monitoring - 如何使用 Vala 监控“trash:///”目录?
- python - 切片可迭代 - 函数不起作用(python)
- ubuntu - phpmyadmin 打不开
- node.js - no-kafka 消费产品问题
- android - 如何让 2 个 TextView 相互重叠,右侧有一个 Button?
- python - 在 Django 中获取和发布
- android - 如何在列表中仅显示一台设备?
- awk - Unix 编程 - 删除 2 个单词之间的行
- apache-spark - 使用 spark 性能问题从 cassandra 读取 5 亿条记录
- php - 获取所有变体图像(其他变体图像 woocommerce 插件)