From 6409e1f33103a9a6e7153de3f49ecf36538fd7a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Sat, 19 Feb 2022 13:58:15 +0100 Subject: [PATCH 01/14] Allow to run any Click program from the CLI --- setup.py | 2 ++ src/rich_click/__main__.py | 15 +++++++++++++ src/rich_click/cli.py | 46 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 src/rich_click/__main__.py create mode 100644 src/rich_click/cli.py diff --git a/setup.py b/setup.py index 348310f0..04559a43 100644 --- a/setup.py +++ b/setup.py @@ -2,8 +2,10 @@ setup( name="rich-click", + entry_points={"console_scripts": ["rich-click = rich_click.cli:main"]}, install_requires=[ "click", "rich", + "importlib-metadata; python_version < '3.8'", ], ) diff --git a/src/rich_click/__main__.py b/src/rich_click/__main__.py new file mode 100644 index 00000000..13d61f0f --- /dev/null +++ b/src/rich_click/__main__.py @@ -0,0 +1,15 @@ +""" +Entry-point module, in case you use `python -m griffe`. + +Why does this file exist, and why `__main__`? For more info, read: + +- https://www.python.org/dev/peps/pep-0338/ +- https://docs.python.org/3/using/cmdline.html#cmdoption-m +""" + +import sys + +from rich_click.cli import main + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) diff --git a/src/rich_click/cli.py b/src/rich_click/cli.py new file mode 100644 index 00000000..dded5cb3 --- /dev/null +++ b/src/rich_click/cli.py @@ -0,0 +1,46 @@ +"""The command line interface.""" + +import sys +from importlib import import_module +try: + from importlib.metadata import entry_points +except ImportError: + from importlib_metadata import entry_points + +import click +from rich_click import group, command + + +def main(args=None): + args = args or sys.argv[1:] + if not args: + # without args we assume we want to run rich-click on itself + # TODO: rewrite using argparse + script_name = "rich-click" + else: + script_name = args[0] + scripts = {script.name: script for script in entry_points().get("console_scripts")} + if script_name in scripts: + # a valid script was passed + script = scripts[script_name] + module_path = script.module + function_name = script.attr + prog = script_name + elif ":" in script_name: + # the path to a function was passed + module_path, function_name = args[0].split(":") + prog = module_path.split(".", 1)[0] + else: + print("usage: rich-click [SCRIPT | MODULE:FUNCTION] [-- SCRIPT_ARGS...]", file=sys.stderr) + sys.exit(1) + if len(args) > 1: + if args[1] == "--": + del args[1] + # patch click before importing the program function + click.group = group + click.command = command + # import the program function + module = import_module(module_path) + function = getattr(module, function_name) + # simply run it: it should be patched as well + return function(*args[1:]) From 7d9245a520b7302c4b3731389c61366784f1badf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Sat, 19 Feb 2022 14:07:03 +0100 Subject: [PATCH 02/14] fixup! Allow to run any Click program from the CLI --- src/rich_click/__init__.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/rich_click/__init__.py b/src/rich_click/__init__.py index 540b89e4..af0c5c97 100644 --- a/src/rich_click/__init__.py +++ b/src/rich_click/__init__.py @@ -9,6 +9,8 @@ __version__ = "1.1.0.dev0" from click import * +from click import group as click_group +from click import command as click_command from .rich_click import RichGroup from .rich_click import RichCommand @@ -18,8 +20,6 @@ def group(*args, cls=RichGroup, **kwargs): Defines the group() function so that it uses the RichGroup class by default """ - from click import group as click_group - return click_group(*args, cls=cls, **kwargs) @@ -28,6 +28,4 @@ def command(*args, cls=RichCommand, **kwargs): Defines the command() function so that it uses the RichCommand class by default """ - from click import command as click_command - return click_command(*args, cls=cls, **kwargs) From f9ab5f2d13d4af03b93e58504b8d0316f7cb6e8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Sat, 19 Feb 2022 14:17:15 +0100 Subject: [PATCH 03/14] fixup! Allow to run any Click program from the CLI --- src/rich_click/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rich_click/cli.py b/src/rich_click/cli.py index dded5cb3..90109f9e 100644 --- a/src/rich_click/cli.py +++ b/src/rich_click/cli.py @@ -43,4 +43,4 @@ def main(args=None): module = import_module(module_path) function = getattr(module, function_name) # simply run it: it should be patched as well - return function(*args[1:]) + return function(args[1:]) From 4a53eb0d41f7c271badd4421121f399d9e9795a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Sat, 19 Feb 2022 14:38:53 +0100 Subject: [PATCH 04/14] Update src/rich_click/__main__.py --- src/rich_click/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rich_click/__main__.py b/src/rich_click/__main__.py index 13d61f0f..1a20ed0d 100644 --- a/src/rich_click/__main__.py +++ b/src/rich_click/__main__.py @@ -1,5 +1,5 @@ """ -Entry-point module, in case you use `python -m griffe`. +Entry-point module, in case you use `python -m rich_click`. Why does this file exist, and why `__main__`? For more info, read: From 4f08d16fbae671aee4b81a0de7e1e2076e1e72c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Sat, 19 Feb 2022 14:39:00 +0100 Subject: [PATCH 05/14] Update src/rich_click/cli.py --- src/rich_click/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rich_click/cli.py b/src/rich_click/cli.py index 90109f9e..ee44f466 100644 --- a/src/rich_click/cli.py +++ b/src/rich_click/cli.py @@ -15,7 +15,7 @@ def main(args=None): args = args or sys.argv[1:] if not args: # without args we assume we want to run rich-click on itself - # TODO: rewrite using argparse + # TODO: rewrite using click script_name = "rich-click" else: script_name = args[0] From ef95c77d89388d46159f9d97a32e47f35af19f97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Sat, 19 Feb 2022 23:57:51 +0100 Subject: [PATCH 06/14] fixup! Allow to run any Click program from the CLI --- src/rich_click/cli.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/rich_click/cli.py b/src/rich_click/cli.py index 90109f9e..9734cd4d 100644 --- a/src/rich_click/cli.py +++ b/src/rich_click/cli.py @@ -36,6 +36,7 @@ def main(args=None): if len(args) > 1: if args[1] == "--": del args[1] + sys.argv = [prog, *args[1:]] # patch click before importing the program function click.group = group click.command = command @@ -43,4 +44,4 @@ def main(args=None): module = import_module(module_path) function = getattr(module, function_name) # simply run it: it should be patched as well - return function(args[1:]) + return function() From 109b7559fc420cf3b7c7ded4048af50399625c92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Tue, 22 Feb 2022 12:26:40 +0100 Subject: [PATCH 07/14] fixup! Allow to run any Click program from the CLI --- setup.cfg | 4 ++++ setup.py | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 751717ea..103bd5ac 100644 --- a/setup.cfg +++ b/setup.cfg @@ -29,6 +29,10 @@ package_dir = include_package_data = True python_requires = >= 3.6 +[options.entry_points] +console_scripts = + rich-click = rich_click.cli:main + [options.packages.find] where = src diff --git a/setup.py b/setup.py index 04559a43..11ace50d 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,6 @@ setup( name="rich-click", - entry_points={"console_scripts": ["rich-click = rich_click.cli:main"]}, install_requires=[ "click", "rich", From 7e75cb90cf75bb4c4df7055a4f3eabe6b6e0eddf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Tue, 22 Feb 2022 12:29:57 +0100 Subject: [PATCH 08/14] fixup! Allow to run any Click program from the CLI --- src/rich_click/__main__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/rich_click/__main__.py b/src/rich_click/__main__.py index 1a20ed0d..52aa9269 100644 --- a/src/rich_click/__main__.py +++ b/src/rich_click/__main__.py @@ -12,4 +12,5 @@ from rich_click.cli import main if __name__ == "__main__": - sys.exit(main(sys.argv[1:])) + # main will run a Click command which will either exit or raise + main(sys.argv[1:]) From a330b3b1b62120332f07cb935b18571e2dd86ee0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Tue, 22 Feb 2022 12:30:47 +0100 Subject: [PATCH 09/14] fixup! Allow to run any Click program from the CLI --- src/rich_click/cli.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/rich_click/cli.py b/src/rich_click/cli.py index 03d1bdf9..6cdfe430 100644 --- a/src/rich_click/cli.py +++ b/src/rich_click/cli.py @@ -2,6 +2,7 @@ import sys from importlib import import_module + try: from importlib.metadata import entry_points except ImportError: @@ -31,7 +32,10 @@ def main(args=None): module_path, function_name = args[0].split(":") prog = module_path.split(".", 1)[0] else: - print("usage: rich-click [SCRIPT | MODULE:FUNCTION] [-- SCRIPT_ARGS...]", file=sys.stderr) + print( + "usage: rich-click [SCRIPT | MODULE:FUNCTION] [-- SCRIPT_ARGS...]", + file=sys.stderr, + ) sys.exit(1) if len(args) > 1: if args[1] == "--": From ec4012746339cc68695e50bc90b6a0a5df49babf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Mazzucotelli?= Date: Mon, 28 Feb 2022 20:40:41 +0100 Subject: [PATCH 10/14] fixup! Allow to run any Click program from the CLI --- src/rich_click/cli.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/rich_click/cli.py b/src/rich_click/cli.py index 6cdfe430..d7d685ca 100644 --- a/src/rich_click/cli.py +++ b/src/rich_click/cli.py @@ -24,12 +24,11 @@ def main(args=None): if script_name in scripts: # a valid script was passed script = scripts[script_name] - module_path = script.module - function_name = script.attr + module_path, function_name = script.value.split(":", 1) prog = script_name elif ":" in script_name: # the path to a function was passed - module_path, function_name = args[0].split(":") + module_path, function_name = args[0].split(":", 1) prog = module_path.split(".", 1)[0] else: print( From c1d3c8e78796718576041090e708398ea2b90db0 Mon Sep 17 00:00:00 2001 From: Phil Ewels Date: Mon, 28 Feb 2022 21:13:42 +0100 Subject: [PATCH 11/14] CLI: Nicer help output --- src/rich_click/__main__.py | 2 +- src/rich_click/cli.py | 81 +++++++++++++++++++++++++++++++++++--- 2 files changed, 76 insertions(+), 7 deletions(-) diff --git a/src/rich_click/__main__.py b/src/rich_click/__main__.py index 52aa9269..b512e5b3 100644 --- a/src/rich_click/__main__.py +++ b/src/rich_click/__main__.py @@ -13,4 +13,4 @@ if __name__ == "__main__": # main will run a Click command which will either exit or raise - main(sys.argv[1:]) + main() diff --git a/src/rich_click/cli.py b/src/rich_click/cli.py index d7d685ca..6c77e28f 100644 --- a/src/rich_click/cli.py +++ b/src/rich_click/cli.py @@ -1,6 +1,7 @@ """The command line interface.""" import sys +from textwrap import dedent from importlib import import_module try: @@ -9,10 +10,44 @@ from importlib_metadata import entry_points import click -from rich_click import group, command +from rich.console import Console +from rich.padding import Padding +from rich.text import Text +from rich.theme import Theme +from rich_click import group as rich_group, command as rich_command +from rich_click.rich_click import ( + OptionHighlighter, + _make_rich_rext, + COLOR_SYSTEM, + STYLE_HELPTEXT_FIRST_LINE, + STYLE_HELPTEXT, + STYLE_METAVAR, + STYLE_OPTION, + STYLE_SWITCH, + STYLE_USAGE_COMMAND, + STYLE_USAGE, +) def main(args=None): + """ + The [link=https://github.com/ewels/rich-click]rich-click[/] CLI + provides attractive help output from any tool using [link=https://click.palletsprojects.com/]click[/], + formatted with [link=https://github.com/Textualize/rich]rich[/]. + + The rich-click command line tool can be prepended before any Python package + using native click to provide attractive richified click help output. + + For example, if you have a package called [blue]my_package[/] that uses click, + you can run: + + [blue] rich-click my_package --help [/] + + It only works if the package is using vanilla click without customised [cyan]group()[/] + or [cyan]command()[/] classes. + If in doubt, please suggest to the authors that they use rich_click within their + tool natively - this will always give a better experience. + """ args = args or sys.argv[1:] if not args: # without args we assume we want to run rich-click on itself @@ -31,9 +66,43 @@ def main(args=None): module_path, function_name = args[0].split(":", 1) prog = module_path.split(".", 1)[0] else: - print( - "usage: rich-click [SCRIPT | MODULE:FUNCTION] [-- SCRIPT_ARGS...]", - file=sys.stderr, + highlighter = OptionHighlighter() + console = Console( + theme=Theme( + { + "option": STYLE_OPTION, + "switch": STYLE_SWITCH, + "metavar": STYLE_METAVAR, + "usage": STYLE_USAGE, + } + ), + highlighter=highlighter, + color_system=COLOR_SYSTEM, + ) + console.print( + Padding( + highlighter( + "Usage: rich-click [SCRIPT | MODULE:FUNCTION] [-- SCRIPT_ARGS...]" + ), + 1, + ), + style=STYLE_USAGE_COMMAND, + ) + help_paragraphs = dedent(main.__doc__).split("\n\n") + help_paragraphs = [x.replace("\n", " ").strip() for x in help_paragraphs] + console.print( + Padding( + Text.from_markup(help_paragraphs[0].strip()), + (0, 1), + ), + style=STYLE_HELPTEXT_FIRST_LINE, + ) + console.print( + Padding( + Text.from_markup("\n\n".join(help_paragraphs[1:]).strip()), + (0, 1), + ), + style=STYLE_HELPTEXT, ) sys.exit(1) if len(args) > 1: @@ -41,8 +110,8 @@ def main(args=None): del args[1] sys.argv = [prog, *args[1:]] # patch click before importing the program function - click.group = group - click.command = command + click.group = rich_group + click.command = rich_command # import the program function module = import_module(module_path) function = getattr(module, function_name) From 211dc0d9cf9114e385bf5096c2e1db8b2effd0e9 Mon Sep 17 00:00:00 2001 From: Phil Ewels Date: Mon, 28 Feb 2022 21:21:02 +0100 Subject: [PATCH 12/14] Don't hang if no command given, split up error and usage --- src/rich_click/cli.py | 98 +++++++++++++++++++++++++++---------------- 1 file changed, 63 insertions(+), 35 deletions(-) diff --git a/src/rich_click/cli.py b/src/rich_click/cli.py index 6c77e28f..329f28c5 100644 --- a/src/rich_click/cli.py +++ b/src/rich_click/cli.py @@ -12,6 +12,7 @@ import click from rich.console import Console from rich.padding import Padding +from rich.panel import Panel from rich.text import Text from rich.theme import Theme from rich_click import group as rich_group, command as rich_command @@ -26,8 +27,56 @@ STYLE_SWITCH, STYLE_USAGE_COMMAND, STYLE_USAGE, + STYLE_ERRORS_PANEL_BORDER, + ERRORS_PANEL_TITLE, + ALIGN_ERRORS_PANEL, ) +highlighter = OptionHighlighter() +console = Console( + theme=Theme( + { + "option": STYLE_OPTION, + "switch": STYLE_SWITCH, + "metavar": STYLE_METAVAR, + "usage": STYLE_USAGE, + } + ), + highlighter=highlighter, + color_system=COLOR_SYSTEM, +) + + +def _print_usage(): + console.print( + Padding( + highlighter( + "Usage: rich-click [SCRIPT | MODULE:FUNCTION] [-- SCRIPT_ARGS...]" + ), + 1, + ), + style=STYLE_USAGE_COMMAND, + ) + + +def _print_help(): + help_paragraphs = dedent(main.__doc__).split("\n\n") + help_paragraphs = [x.replace("\n", " ").strip() for x in help_paragraphs] + console.print( + Padding( + Text.from_markup(help_paragraphs[0].strip()), + (0, 1), + ), + style=STYLE_HELPTEXT_FIRST_LINE, + ) + console.print( + Padding( + Text.from_markup("\n\n".join(help_paragraphs[1:]).strip()), + (0, 1), + ), + style=STYLE_HELPTEXT, + ) + def main(args=None): """ @@ -49,10 +98,11 @@ def main(args=None): tool natively - this will always give a better experience. """ args = args or sys.argv[1:] - if not args: - # without args we assume we want to run rich-click on itself - # TODO: rewrite using click - script_name = "rich-click" + if not args or args == ["--help"]: + # Print usage if we got no args, or only --help + _print_usage() + _print_help() + sys.exit(0) else: script_name = args[0] scripts = {script.name: script for script in entry_points().get("console_scripts")} @@ -66,43 +116,21 @@ def main(args=None): module_path, function_name = args[0].split(":", 1) prog = module_path.split(".", 1)[0] else: - highlighter = OptionHighlighter() - console = Console( - theme=Theme( - { - "option": STYLE_OPTION, - "switch": STYLE_SWITCH, - "metavar": STYLE_METAVAR, - "usage": STYLE_USAGE, - } - ), - highlighter=highlighter, - color_system=COLOR_SYSTEM, - ) - console.print( - Padding( - highlighter( - "Usage: rich-click [SCRIPT | MODULE:FUNCTION] [-- SCRIPT_ARGS...]" - ), - 1, - ), - style=STYLE_USAGE_COMMAND, - ) - help_paragraphs = dedent(main.__doc__).split("\n\n") - help_paragraphs = [x.replace("\n", " ").strip() for x in help_paragraphs] + _print_usage() console.print( - Padding( - Text.from_markup(help_paragraphs[0].strip()), - (0, 1), - ), - style=STYLE_HELPTEXT_FIRST_LINE, + Panel( + Text.from_markup(f"No such script: [bold]{script_name}[/]"), + border_style=STYLE_ERRORS_PANEL_BORDER, + title=ERRORS_PANEL_TITLE, + title_align=ALIGN_ERRORS_PANEL, + ) ) console.print( Padding( - Text.from_markup("\n\n".join(help_paragraphs[1:]).strip()), + "Please run [yellow bold]rich-click --help[/] for usage information.", (0, 1), ), - style=STYLE_HELPTEXT, + style="dim", ) sys.exit(1) if len(args) > 1: From 15133dcbcfddbe59c6c9f28e99cb08936b692fb6 Mon Sep 17 00:00:00 2001 From: Phil Ewels Date: Mon, 28 Feb 2022 21:30:18 +0100 Subject: [PATCH 13/14] Readme and changelog --- CHANGELOG.md | 18 ++++++++++-------- README.md | 23 ++++++++++++++++++++++- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index be89e088..e81ca496 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Version 1.2.0.dev0 +- New CLI functionality to richifiy via prefix any other tool using click, by @pawamoy [[#13](https://github.com/ewels/rich-click/pull/13)] + ## Version 1.1.1 (2022-02-28) Hotfix patch release to remove an accidental `from turtle import st` that crept in due to a pesky VSCode plugin. @@ -11,17 +13,17 @@ Many thanks to [@ashb](httpsd://github.com/ashb) for spotting. - Added support for `HEADER_TEXT` and `FOOTER_TEXT` to go before and after help output - Catch Abort exceptions from `cmd+c` and print nicely using `ABORTED_TEXT` -- Handle missing `click.types._NumberRangeBase` in click 7x [#16](https://github.com/ewels/rich-click/issues/16) -- Fix compatibility issue for rich 10.6 (`group` vs `render_group` import) [#16](https://github.com/ewels/rich-click/issues/16) -- Require at least click v7.0 (released 2018) [#16](https://github.com/ewels/rich-click/issues/16) -- Require at least rich v10 (released March 2021) [#16](https://github.com/ewels/rich-click/issues/16) -- Unwrap single newlines in option and group-command help texts [#23](https://github.com/ewels/rich-click/issues/23) -- Add click `\b` escape marker functionality into help text rendering [#24](https://github.com/ewels/rich-click/issues/24) -- Fix syntax in example in README file by @fridex [#15](https://github.com/ewels/rich-click/pull/15) +- Handle missing `click.types._NumberRangeBase` in click 7x [[#16](https://github.com/ewels/rich-click/issues/16)] +- Fix compatibility issue for rich 10.6 (`group` vs `render_group` import) [[#16](https://github.com/ewels/rich-click/issues/16)] +- Require at least click v7.0 (released 2018) [[#16](https://github.com/ewels/rich-click/issues/16)] +- Require at least rich v10 (released March 2021) [[#16](https://github.com/ewels/rich-click/issues/16)] +- Unwrap single newlines in option and group-command help texts [[#23](https://github.com/ewels/rich-click/issues/23)] +- Add click `\b` escape marker functionality into help text rendering [[#24](https://github.com/ewels/rich-click/issues/24)] +- Fix syntax in example in README file by @fridex [[#15](https://github.com/ewels/rich-click/pull/15)] ## Version 1.0.0 (2022-02-18) -- _**Major change:**_ New usage, so that we can avoid having to do monkey patching [#10](https://github.com/ewels/rich-click/pull/10). +- _**Major change:**_ New usage, so that we can avoid having to do monkey patching [[#10](https://github.com/ewels/rich-click/pull/10).] - Now use with `import rich_click as click` - Add ability to create groups of options with separate panels - Show positional arguments in their own panel by default diff --git a/README.md b/README.md index a52a9140..e7e6f20f 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ click, formatted with rich, with minimal customisation required. - 🌈 Rich command-line formatting of click help and error messages - 💫 Nice styles be default, usage is simply `import rich_click as click` +- 💻 CLI tool to run on other people's packages (prefix the command with `rich-click`) - 🎁 Group commands and options into named panels - ❌ Well formatted error messages - 🔢 Easily give custom sort order for options and commands @@ -31,6 +32,8 @@ python -m pip install rich-click ## Usage +### Import as click + To use `rich-click`, switch out your normal `click` import with `rich-click`, using the same namespace: ```python @@ -44,11 +47,29 @@ That's it ✨ Then continue to use `click` as you would normally. The intention is to maintain most / all of the normal click functionality and arguments. If you spot something that breaks or is missing once you start using the plugin, please create an issue about it. -Alternatively, if you prefer you can `RichGroup` or `RichCommand` with the `cls` argument in your click usage instead. +### Declarative + +If you prefer, you can `RichGroup` or `RichCommand` with the `cls` argument in your click usage instead. This means that you can continue to use the unmodified `click` package in parallel. > See [`examples/02_declarative.py`](examples/02_declarative.py) for an example. +### Command-line usage + +Rich-click comes with a CLI tool that allows you to format the click help output from _any_ package. +As long as that tool is using click and isn't already passing custom `cls` objects, it should work. +Hoever, please consider it an experimental feature at this point. + +To use, simply prefix to your normal command. +For example, to get richified click help text from a package called `awesometool`, you could run: + +```console +$ rich-click awesometool --help + +Usage: awesometool [OPTIONS] +..more richified output below.. +``` + ## Customisation There are a large number of customisation options in rich-click. From 748fff6b0bebef40e2a271cba1e24498c88f24df Mon Sep 17 00:00:00 2001 From: Phil Ewels Date: Mon, 28 Feb 2022 21:37:19 +0100 Subject: [PATCH 14/14] Prefixer: A little simplification --- src/rich_click/__main__.py | 5 ++--- src/rich_click/cli.py | 26 ++++---------------------- 2 files changed, 6 insertions(+), 25 deletions(-) diff --git a/src/rich_click/__main__.py b/src/rich_click/__main__.py index b512e5b3..0a9ccdeb 100644 --- a/src/rich_click/__main__.py +++ b/src/rich_click/__main__.py @@ -1,5 +1,6 @@ """ -Entry-point module, in case you use `python -m rich_click`. +Entry-point module for the command line prefixer, +called in case you use `python -m rich_click`. Why does this file exist, and why `__main__`? For more info, read: @@ -7,8 +8,6 @@ - https://docs.python.org/3/using/cmdline.html#cmdoption-m """ -import sys - from rich_click.cli import main if __name__ == "__main__": diff --git a/src/rich_click/cli.py b/src/rich_click/cli.py index 329f28c5..aa021368 100644 --- a/src/rich_click/cli.py +++ b/src/rich_click/cli.py @@ -7,6 +7,7 @@ try: from importlib.metadata import entry_points except ImportError: + # Support Python <3.8 from importlib_metadata import entry_points import click @@ -14,17 +15,10 @@ from rich.padding import Padding from rich.panel import Panel from rich.text import Text -from rich.theme import Theme from rich_click import group as rich_group, command as rich_command from rich_click.rich_click import ( - OptionHighlighter, - _make_rich_rext, - COLOR_SYSTEM, STYLE_HELPTEXT_FIRST_LINE, STYLE_HELPTEXT, - STYLE_METAVAR, - STYLE_OPTION, - STYLE_SWITCH, STYLE_USAGE_COMMAND, STYLE_USAGE, STYLE_ERRORS_PANEL_BORDER, @@ -32,26 +26,14 @@ ALIGN_ERRORS_PANEL, ) -highlighter = OptionHighlighter() -console = Console( - theme=Theme( - { - "option": STYLE_OPTION, - "switch": STYLE_SWITCH, - "metavar": STYLE_METAVAR, - "usage": STYLE_USAGE, - } - ), - highlighter=highlighter, - color_system=COLOR_SYSTEM, -) +console = Console() def _print_usage(): console.print( Padding( - highlighter( - "Usage: rich-click [SCRIPT | MODULE:FUNCTION] [-- SCRIPT_ARGS...]" + Text.from_markup( + f"[{STYLE_USAGE}]Usage[/]: rich-click [SCRIPT | MODULE:FUNCTION] [-- SCRIPT_ARGS...]" ), 1, ),