-
Notifications
You must be signed in to change notification settings - Fork 33
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 providing a default/global option_groups
config to apply to all commands
#169
Comments
For 1.9, the main thing I want to do is an overhaul of the options/command groups stuff. The TLDR, I am in full agreement with this. Unfortunately for 1.8 (which we want to get released next month), I couldn't fit this in, as it will require a hefty amount of refactoring and building out of logic that I'm not too familiar with (option/command groups are the part of the code I'm least familiar with). I don't know what the timeline is for 1.9, but I do know an overhaul of parsing logic that includes wildcards is the main thing I want in the 1.9 release. Is this something you are willing to contribute? If so, contributions are welcome! If not, rest assured we're both on the same page with this. |
Good to hear you already have something like this in mind. Admittedly, I did find that issue but only skimmed over it so I missed the part about the wildcard. I do however like the move to defining the
If I get the time I'll take a crack at it.
At first glance, a rudimentary implementation could be to add this to the above: option_groups = formatter.config.option_groups.get(ctx.command_path).copy()
option_groups.extend(formatter.config.option_groups.get("*", [])) It would achieve the desired effect until the major overhaul with minimal effort. It would however only cover the "global options" portion, not necessarily forcing it to the bottom of the help output that I had also mentioned could be nice. Also, to add some context around forcing the global options to the bottom, it is to mimic what |
@ITProKyle Great update here, I think you'll be pleased. I stopped being lazy and implemented tons of quality of life improvements for command/option groups. I want this in for 1.8.0 because I find the command/options groups stuff to be incredibly annoying. Check out the following: pip install "rich-click==1.8.0dev5" I would really appreciate if you could help me test this out before release. 😄 If not, no worries. Notes on what's new: First thing: Second thing: Not only is wildcard support enabled, but I go a step further and implemented a "full" wildcard implementation. Check this out: # foo.py
import rich_click as click
click.rich_click.OPTION_GROUPS = {
"cli * c": [
{
"name": "foo",
"options": ["--flag1"]
}
]
}
@click.group
def cli(): ...
@cli.group("x")
@click.option("--flag1")
@click.option("--flag2")
def x(flag1, flag2): ...
@x.command("a")
@click.option("--flag1")
@click.option("--flag2")
def xa(flag1, flag2): ...
@x.command("b")
@click.option("--flag1")
@click.option("--flag2")
def xb(flag1, flag2): ...
@x.command("c")
@click.option("--flag1")
@click.option("--flag2")
def xc(flag1, flag2): ...
@cli.group("y")
@click.option("--flag1")
@click.option("--flag2")
def y(flag1, flag2): ...
@y.command("a")
@click.option("--flag1")
@click.option("--flag2")
def ya(flag1, flag2): ...
@y.command("b")
@click.option("--flag1")
@click.option("--flag2")
def yb(flag1, flag2): ...
@y.command("c")
@click.option("--flag1")
@click.option("--flag2")
def yc(flag1, flag2): ...
@cli.group("z")
@click.option("--flag1")
@click.option("--flag2")
def z(flag1, flag2): ...
@z.command("a")
@click.option("--flag1")
@click.option("--flag2")
def za(flag1, flag2): ...
@z.command("b")
@click.option("--flag1")
@click.option("--flag2")
def zb(flag1, flag2): ...
@z.command("c")
@click.option("--flag1")
@click.option("--flag2")
def zc(flag1, flag2): ...
cli() This works exactly the way you'd expect: $ python foo.py x c --help
Usage: foo.py x c [OPTIONS]
╭─ foo ──────────────────────────────────────────────────────────────────────────────────────────────────╮
│ --flag1 TEXT │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Options ──────────────────────────────────────────────────────────────────────────────────────────────╮
│ --flag2 TEXT │
│ --help Show this message and exit. │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────╯
$ python foo.py x b --help
Usage: foo.py x b [OPTIONS]
╭─ Options ──────────────────────────────────────────────────────────────────────────────────────────────╮
│ --flag1 TEXT │
│ --flag2 TEXT │
│ --help Show this message and exit. │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────╯ Third: This handles deduplication in a coherent way. Basically, non-wildcarded groups are always preferred to wildcarded groups. In a future release I still want to do a little more to overhaul this feature. I still think it has some gotchas that I really dislike, most notably:
All that said, this is a lot closer to the API I've always wanted. |
Awesome! I truly appreciate you working on this. I'll give it a try later today if possible, worst case later this week. |
Just went through some initial testing for a few commands. Test Case 1CI_CLI_OPTION: OptionGroupDict = {"options": ["--ci"]}
GLOBAL_CLI_OPTIONS: OptionGroupDict = {
"name": "Global Options",
"options": ["--debug", "--help", "--verbose"],
}
option_groups={
"*": [GLOBAL_CLI_OPTIONS],
"cli": [{"options": ["--version"]}],
"cli action": [CI_CLI_OPTION],
},
Test Case 2CI_CLI_OPTION: OptionGroupDict = {"options": ["--ci"]}
GLOBAL_CLI_OPTIONS: OptionGroupDict = {
"name": "Global Options",
"options": ["--debug", "--help", "--verbose"],
}
option_groups={
"cli": [{"options": ["--version"]}],
"cli *": [GLOBAL_CLI_OPTIONS],
"cli action": [CI_CLI_OPTION],
},
overall, it's working great.
I agree with you here. aside from your other mention of applying the config directly to
100% - i would love to be able to set this on the options themselves. However, something different would need to be done for How will sorting the option panels work with this method? |
Glad it's working!
For the current API, the way to preserve order is to not rely on wildcards. I will make sure that is clear in the docs: i.e. if you have an explicit order in mind, probably don't use wildcards. For the proposed 1.9 API: Explicit order would be defined something like this: @click.command
@click.option("--a", panel="first")
@click.option("--b", panel="second")
@click.option("--c", panel="third")
@click.rich_config(panels=[{"name": "first"}, "second", "third"]) # Takes both strings and dicts
def cli():
... If @click.command
@click.option("--a", panel="first")
@click.option("--b", panel="second")
@click.option("--c", panel="third")
@click.option("--d", panel="first") # <- The "first" panel was already defined.
def cli():
... If @click.command
@click.option("--b", panel="second")
@click.option("--c", panel="third")
@click.option("--a", panel="first") # This is first because it's specified as a panel.
@click.rich_config(panels=[{"name": "first"}])
def cli():
... I get the last one can be a little disappointing because it means if users want to apply custom style options, they also need to specify every other panel to guarantee an order. But I don't know a better solution that isn't insanely more complicated; encouraging users to be explicit is fine I think. I don't know yet exactly how this works in tandem with Also, it may be
I think just having the user do Do note that rich-click 1.9 is likely a way's away from being released, aside from the fact this is maintained as a side project, I also plan on rewriting our unit-tests before working on 1.9. So this is all far away from release, unless I get any help from anyone. (My objective is before end of 2024. ) Of course, contributions are welcome :) |
I'm closing this issue now that rich-click 1.8.0 is out. |
I often use a set of global options for my CLIs -
--help
and--verbose
. I would like to have these in a separate group after the rest of the options.Right now, I would need to do the following to achieve my desired result:
I would like to be able to do something like this to apply the group to all commands, forcing the global options to appear last:
which I would expect to output something like this:
The text was updated successfully, but these errors were encountered: