Comments (7)
Glad it's working!
How will sorting the option panels work with this method?
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 panels
is not specified, then each panel is added in order of its first occurrence, from top to bottom:
@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 panels
is only partially specified, then additional panels go to the bottom.
@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 command_groups
and option_groups
, since those APIs will still be supported for backwards compatibility. We'll make it work.
Also, it may be option_panels=...
instead of panels=...
for the kwarg. Unclear right now.
However, something different would need to be done for --help, -h and --version since they are built-ins.
I think just having the user do @click.rich_config(panels=[{"name": "Help panel", "options": ["--help"]}])
is the best way to go.
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 :)
from rich-click.
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 option_groups
per-command rather than needing to do it globally.
Is this something you are willing to contribute?
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.
Another potential would be to split it out into its own config field (e.g. formatter.config.global_options
|formatter.config.global_option_groups
) to make it more explicit/intuitive than a wildcard. Without digging too far into the logic, it might also be easier to force ordering the output doing it this way.
Also, to add some context around forcing the global options to the bottom, it is to mimic what pip
does with its General Options
. There are likely other CLIs that do this as well, this is just the easiest example to reference.
from rich-click.
For 1.9, the main thing I want to do is an overhaul of the options/command groups stuff.
The "*"
idea is actually exactly what I had in mind! See #157 for my longer form thoughts.
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.
from rich-click.
@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: hello.py subcommand
and hello subcommand
both work if you run python hello.py
. Previously only hello.py
worked because it pulled from the ctx.command_path
.
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:
- chaining
@rich_config(help_config={"option_groups": ...})
doesn't work well. - I dislike the name "groups" because "group" is already a concept in Click, so I'd deprecate it (but support for backwards compatibility) into a
2.0.0
release. I'd probably replace it with the name "panel". @click.option(..., panel="foo")
would be a much nicer API.
All that said, this is a lot closer to the API I've always wanted.
from rich-click.
Awesome! I truly appreciate you working on this. I'll give it a try later today if possible, worst case later this week.
from rich-click.
Just went through some initial testing for a few commands.
Test Case 1
CI_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],
},
Global Options
appeared forcli --help
along sideOptions
(in this order)- i had previously defined the second group without a name to force
Options
aboveGlobal Options
.Global Options
appears beforeOptions
with and without specifying this unnamed group.
- i had previously defined the second group without a name to force
Global Options
appeared forcli action --help
along sideOptions
(in this order)Global Options
appeared forcli child grandchild --help
(has no other options)- I commended out one of the
Global Options
and it handled not displaying it as desired
- I commended out one of the
Test Case 2
CI_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],
},
- 2
Options
appeared forcli --help
(expected),Global Options
was missing (expected) Global Options
appeared forcli action --help
along sideOptions
(in this order)Global Options
appeared forcli child grandchild --help
(has no other options)
overall, it's working great.
chaining
@rich_config(help_config={"option_groups": ...})
doesn't work well.
I agree with you here. aside from your other mention of applying the config directly to @click.option
, passing @rich_config
options into @click.group
/@click.command
would be a nice QoL to eliminate the additional decorator.
@click.option(..., panel="foo")
would be a much nicer API.
100% - i would love to be able to set this on the options themselves. However, something different would need to be done for --help, -h
and --version
since they are built-ins.
How will sorting the option panels work with this method?
from rich-click.
I'm closing this issue now that rich-click 1.8.0 is out.
from rich-click.
Related Issues (20)
- Expose a way to send usage information to stderr HOT 9
- Rich-Click does not translate the ascii codes into colors on windows 64 cmd.exe anymore HOT 3
- Unit tests should assert output to stderr on errors
- Either update or deprecate MacPorts install HOT 5
- `text_markup: Literal["rich", "markdown", "rst", None]` config option HOT 1
- Additional style options HOT 1
- `rich-click` CLI for version `1.8.0dev1` breaks backwards compatibility in edge case
- 1.9 wishlist
- 2.0 roadmap
- 'RichGroup' object has no attribute 'isolation' HOT 2
- Bugs (a) generating svg/html with decorator. (b) with root directory scripts HOT 1
- Interim blog post - "5 cool pre-made styles for your CLI" (title tentative)
- Color part of the help massage HOT 8
- OptionHighlighter is deprecated and will be removed in a future version. HOT 6
- Invalid MRO when importing rich_click HOT 4
- Continuting to receive "DeprecationWarning: OptionHighlighter is deprecated" as of 1.8.1 HOT 2
- Fix warning (again)
- Show commands before options HOT 5
- Grouped `--help` output is not shown for `__main__.py` CLIs (`python -m foo`) / add support for `prog_name` HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rich-click.