ยถ
Colored helpExtend Cloupโs own help formatter and theme to add colorization of:
Options
Choices
Metavars
Cli name
Sub-commands
Command aliases
Long and short options
Choices
Metavars
Environment variables
Defaults
Todo
Write examples and tutorial.
Why not use rich-click
?ยถ
rich-click
is a good project that aims to integrate Rich with Click. Like Click Extra, it provides a ready-to-use help formatter for Click.
But contrary to Click Extra, the help screen is rendered within a table, which takes the whole width of the terminal. This is not ideal if you try to print the output of a command somewhere else.
The typical use-case is users reporting issues on GitHub, and pasting the output of a command in the issue description. If the output is too wide, it will be akwardly wrapped, or adds a horizontal scrollbar to the page.
Without a table imposing a maximal width, the help screens from Click Extra will be rendered with the minimal width of the text, and will be more readable.
Hint
This is just a matter of preference, as nothing prevents you to use both rich-click
and Click Extra in the same project, and get the best from both.
color_option
ยถ
Todo
Write examples and tutorial.
help_option
ยถ
Todo
Write examples and tutorial.
Colors and stylesยถ
Here is a little CLI to demonstrate the rendering of colors and styles, based on cloup.styling.Style
:
from click import command
from click_extra import Color, style, Choice, option, print_table
all_styles = [
"bold",
"dim",
"underline",
"overline",
"italic",
"blink",
"reverse",
"strikethrough",
]
all_colors = sorted(Color._dict.values())
@command
@option("--matrix", type=Choice(["colors", "styles"]))
def render_matrix(matrix):
table = []
if matrix == "colors":
table_headers = ["Foreground โด \ Background โ"] + all_colors
for fg_color in all_colors:
line = [
style(fg_color, fg=fg_color)
]
for bg_color in all_colors:
line.append(
style(fg_color, fg=fg_color, bg=bg_color)
)
table.append(line)
elif matrix == "styles":
table_headers = ["Color โด \ Style โ"] + all_styles
for color_name in all_colors:
line = [
style(color_name, fg=color_name)
]
for prop in all_styles:
line.append(
style(color_name, fg=color_name, **{prop: True})
)
table.append(line)
print_table(table, headers=table_headers)
$ render-matrix --matrix=colors
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฎ
โ Foreground โด \ Background โ โ black โ blue โ bright_black โ bright_blue โ bright_cyan โ bright_green โ bright_magenta โ bright_red โ bright_white โ bright_yellow โ cyan โ green โ magenta โ red โ reset โ white โ yellow โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโค
โ black โ black โ black โ black โ black โ black โ black โ black โ black โ black โ black โ black โ black โ black โ black โ black โ black โ black โ
โ blue โ blue โ blue โ blue โ blue โ blue โ blue โ blue โ blue โ blue โ blue โ blue โ blue โ blue โ blue โ blue โ blue โ blue โ
โ bright_black โ bright_black โ bright_black โ bright_black โ bright_black โ bright_black โ bright_black โ bright_black โ bright_black โ bright_black โ bright_black โ bright_black โ bright_black โ bright_black โ bright_black โ bright_black โ bright_black โ bright_black โ
โ bright_blue โ bright_blue โ bright_blue โ bright_blue โ bright_blue โ bright_blue โ bright_blue โ bright_blue โ bright_blue โ bright_blue โ bright_blue โ bright_blue โ bright_blue โ bright_blue โ bright_blue โ bright_blue โ bright_blue โ bright_blue โ
โ bright_cyan โ bright_cyan โ bright_cyan โ bright_cyan โ bright_cyan โ bright_cyan โ bright_cyan โ bright_cyan โ bright_cyan โ bright_cyan โ bright_cyan โ bright_cyan โ bright_cyan โ bright_cyan โ bright_cyan โ bright_cyan โ bright_cyan โ bright_cyan โ
โ bright_green โ bright_green โ bright_green โ bright_green โ bright_green โ bright_green โ bright_green โ bright_green โ bright_green โ bright_green โ bright_green โ bright_green โ bright_green โ bright_green โ bright_green โ bright_green โ bright_green โ bright_green โ
โ bright_magenta โ bright_magenta โ bright_magenta โ bright_magenta โ bright_magenta โ bright_magenta โ bright_magenta โ bright_magenta โ bright_magenta โ bright_magenta โ bright_magenta โ bright_magenta โ bright_magenta โ bright_magenta โ bright_magenta โ bright_magenta โ bright_magenta โ bright_magenta โ
โ bright_red โ bright_red โ bright_red โ bright_red โ bright_red โ bright_red โ bright_red โ bright_red โ bright_red โ bright_red โ bright_red โ bright_red โ bright_red โ bright_red โ bright_red โ bright_red โ bright_red โ bright_red โ
โ bright_white โ bright_white โ bright_white โ bright_white โ bright_white โ bright_white โ bright_white โ bright_white โ bright_white โ bright_white โ bright_white โ bright_white โ bright_white โ bright_white โ bright_white โ bright_white โ bright_white โ bright_white โ
โ bright_yellow โ bright_yellow โ bright_yellow โ bright_yellow โ bright_yellow โ bright_yellow โ bright_yellow โ bright_yellow โ bright_yellow โ bright_yellow โ bright_yellow โ bright_yellow โ bright_yellow โ bright_yellow โ bright_yellow โ bright_yellow โ bright_yellow โ bright_yellow โ
โ cyan โ cyan โ cyan โ cyan โ cyan โ cyan โ cyan โ cyan โ cyan โ cyan โ cyan โ cyan โ cyan โ cyan โ cyan โ cyan โ cyan โ cyan โ
โ green โ green โ green โ green โ green โ green โ green โ green โ green โ green โ green โ green โ green โ green โ green โ green โ green โ green โ
โ magenta โ magenta โ magenta โ magenta โ magenta โ magenta โ magenta โ magenta โ magenta โ magenta โ magenta โ magenta โ magenta โ magenta โ magenta โ magenta โ magenta โ magenta โ
โ red โ red โ red โ red โ red โ red โ red โ red โ red โ red โ red โ red โ red โ red โ red โ red โ red โ red โ
โ reset โ reset โ reset โ reset โ reset โ reset โ reset โ reset โ reset โ reset โ reset โ reset โ reset โ reset โ reset โ reset โ reset โ reset โ
โ white โ white โ white โ white โ white โ white โ white โ white โ white โ white โ white โ white โ white โ white โ white โ white โ white โ white โ
โ yellow โ yellow โ yellow โ yellow โ yellow โ yellow โ yellow โ yellow โ yellow โ yellow โ yellow โ yellow โ yellow โ yellow โ yellow โ yellow โ yellow โ yellow โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโฏ
$ render-matrix --matrix=styles
โญโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโฎ
โ Color โด \ Style โ โ bold โ dim โ underline โ overline โ italic โ blink โ reverse โ strikethrough โ
โโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโค
โ black โ black โ black โ black โ black โ black โ black โ black โ black โ
โ blue โ blue โ blue โ blue โ blue โ blue โ blue โ blue โ blue โ
โ bright_black โ bright_black โ bright_black โ bright_black โ bright_black โ bright_black โ bright_black โ bright_black โ bright_black โ
โ bright_blue โ bright_blue โ bright_blue โ bright_blue โ bright_blue โ bright_blue โ bright_blue โ bright_blue โ bright_blue โ
โ bright_cyan โ bright_cyan โ bright_cyan โ bright_cyan โ bright_cyan โ bright_cyan โ bright_cyan โ bright_cyan โ bright_cyan โ
โ bright_green โ bright_green โ bright_green โ bright_green โ bright_green โ bright_green โ bright_green โ bright_green โ bright_green โ
โ bright_magenta โ bright_magenta โ bright_magenta โ bright_magenta โ bright_magenta โ bright_magenta โ bright_magenta โ bright_magenta โ bright_magenta โ
โ bright_red โ bright_red โ bright_red โ bright_red โ bright_red โ bright_red โ bright_red โ bright_red โ bright_red โ
โ bright_white โ bright_white โ bright_white โ bright_white โ bright_white โ bright_white โ bright_white โ bright_white โ bright_white โ
โ bright_yellow โ bright_yellow โ bright_yellow โ bright_yellow โ bright_yellow โ bright_yellow โ bright_yellow โ bright_yellow โ bright_yellow โ
โ cyan โ cyan โ cyan โ cyan โ cyan โ cyan โ cyan โ cyan โ cyan โ
โ green โ green โ green โ green โ green โ green โ green โ green โ green โ
โ magenta โ magenta โ magenta โ magenta โ magenta โ magenta โ magenta โ magenta โ magenta โ
โ red โ red โ red โ red โ red โ red โ red โ red โ red โ
โ reset โ reset โ reset โ reset โ reset โ reset โ reset โ reset โ reset โ
โ white โ white โ white โ white โ white โ white โ white โ white โ white โ
โ yellow โ yellow โ yellow โ yellow โ yellow โ yellow โ yellow โ yellow โ yellow โ
โฐโโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโฏ
Caution
The current rendering of colors and styles in this HTML documentation is not complete, and does not reflect the real output in a terminal.
That is because pygments-ansi-color
, the component we rely on to render ANSI code in Sphinx via Pygments, only supports a subset of the ANSI codes we use.
Tip
The code above is presented as a CLI, so you can copy and run it yourself in your environment, and see the output in your terminal. That way you can evaluate the real effect of these styles and colors for your end users.
click_extra.colorize
APIยถ
classDiagram ExtraOption <|-- ColorOption HelpFormatter <|-- HelpExtraFormatter HelpTheme <|-- HelpExtraTheme
Helpers and utilities to apply ANSI coloring to terminal content.
- class click_extra.colorize.HelpExtraTheme(invoked_command=<function identity>, command_help=<function identity>, heading=<function identity>, constraint=<function identity>, section_help=<function identity>, col1=<function identity>, col2=<function identity>, alias=<function identity>, alias_secondary=None, epilog=<function identity>, critical=<function identity>, error=<function identity>, warning=<function identity>, info=<function identity>, debug=<function identity>, option=<function identity>, subcommand=<function identity>, choice=<function identity>, metavar=<function identity>, bracket=<function identity>, envvar=<function identity>, default=<function identity>, deprecated=<function identity>, search=<function identity>, success=<function identity>, subheading=<function identity>)[source]ยถ
Bases:
HelpTheme
Extends
cloup.HelpTheme
withlogging.levels
and extra properties.- subheading()ยถ
Non-canonical Click Extra properties.
Note
Subheading is used for sub-sections, like in the help of mail-deduplicate.
Todo
Maybe this shouldnโt be in Click Extra because it is a legacy inheritance from one of my other project.
- Return type:
TypeVar
(T
)
- with_(**kwargs)[source]ยถ
Derives a new theme from the current one, with some styles overridden.
Returns the same instance if the provided styles are the same as the current.
- Return type:
- click_extra.colorize.default_theme: HelpExtraTheme = HelpExtraTheme(invoked_command=Style(fg='bright_white', bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs={'fg': 'bright_white', 'bg': None, 'bold': None, 'dim': None, 'underline': None, 'overline': None, 'italic': None, 'blink': None, 'reverse': None, 'strikethrough': None}), command_help=<function identity>, heading=Style(fg='bright_blue', bg=None, bold=True, dim=None, underline=True, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs=None), constraint=Style(fg='magenta', bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs=None), section_help=<function identity>, col1=<function identity>, col2=<function identity>, alias=Style(fg='cyan', bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs=None), alias_secondary=Style(fg='cyan', bg=None, bold=None, dim=True, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs=None), epilog=<function identity>, critical=Style(fg='red', bg=None, bold=True, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs=None), error=Style(fg='red', bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs={'fg': 'red', 'bg': None, 'bold': None, 'dim': None, 'underline': None, 'overline': None, 'italic': None, 'blink': None, 'reverse': None, 'strikethrough': None}), warning=Style(fg='yellow', bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs=None), info=<function identity>, debug=Style(fg='blue', bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs=None), option=Style(fg='cyan', bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs=None), subcommand=Style(fg='cyan', bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs=None), choice=Style(fg='magenta', bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs=None), metavar=Style(fg='cyan', bg=None, bold=None, dim=True, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs=None), bracket=Style(fg=None, bg=None, bold=None, dim=True, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs=None), envvar=Style(fg='yellow', bg=None, bold=None, dim=True, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs=None), default=Style(fg='green', bg=None, bold=None, dim=True, underline=None, overline=None, italic=True, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs=None), deprecated=Style(fg='bright_yellow', bg=None, bold=True, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs=None), search=Style(fg='green', bg=None, bold=True, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs=None), success=Style(fg='green', bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs={'fg': 'green', 'bg': None, 'bold': None, 'dim': None, 'underline': None, 'overline': None, 'italic': None, 'blink': None, 'reverse': None, 'strikethrough': None}), subheading=Style(fg='blue', bg=None, bold=None, dim=None, underline=None, overline=None, italic=None, blink=None, reverse=None, strikethrough=None, text_transform=None, _style_kwargs=None))ยถ
Default color theme for Click Extra.
- click_extra.colorize.nocolor_theme: HelpExtraTheme = HelpExtraTheme(invoked_command=<function identity>, command_help=<function identity>, heading=<function identity>, constraint=<function identity>, section_help=<function identity>, col1=<function identity>, col2=<function identity>, alias=<function identity>, alias_secondary=None, epilog=<function identity>, critical=<function identity>, error=<function identity>, warning=<function identity>, info=<function identity>, debug=<function identity>, option=<function identity>, subcommand=<function identity>, choice=<function identity>, metavar=<function identity>, bracket=<function identity>, envvar=<function identity>, default=<function identity>, deprecated=<function identity>, search=<function identity>, success=<function identity>, subheading=<function identity>)ยถ
Color theme for Click Extra to force no colors.
- click_extra.colorize.KO = '\x1b[31mโ\x1b[0m'ยถ
Pre-rendered UI-elements.
- click_extra.colorize.color_envvars = {'CLICOLOR': True, 'CLICOLORS': True, 'CLICOLORS_FORCE': True, 'CLICOLOR_FORCE': True, 'COLOR': True, 'COLORS': True, 'FORCE_COLOR': True, 'FORCE_COLORS': True, 'NOCOLOR': False, 'NOCOLORS': False, 'NO_COLOR': False, 'NO_COLORS': False}ยถ
List of environment variables recognized as flags to switch color rendering on or off.
The key is the name of the variable and the boolean value the value to pass to
--color
option flag when encountered.Source:
- class click_extra.colorize.ColorOption(param_decls=None, is_flag=True, default=True, is_eager=True, expose_value=False, help='Strip out all colors and all ANSI codes from output.', **kwargs)[source]ยถ
Bases:
ExtraOption
A pre-configured option that is adding a
--color
/--no-color
(aliased by--ansi
/--no-ansi
) to keep or strip colors and ANSI codes from CLI output.This option is eager by default to allow for other eager options (like
--version
) to be rendered colorless.Todo
Should we switch to
--color=<auto|never|always>
as GNU tools does?Also see how the isatty property defaults with this option, and how it can be implemented in Python.
Todo
Support the TERM environment variable convention?
- class click_extra.colorize.ExtraHelpColorsMixin[source]ยถ
Bases:
object
Adds extra-keywords highlighting to Click commands.
This mixin for
click.Command
-like classes intercepts the top-level helper- generation method to initialize the formatter with dynamic settings. This is implemented at this stage so we have access to the global context.
- class click_extra.colorize.HelpExtraFormatter(*args, **kwargs)[source]ยถ
Bases:
HelpFormatter
Extends Cloupโs custom HelpFormatter to highlights options, choices, metavars and default values.
This is being discussed for upstream integration at:
Forces theme to our default.
Also transform Cloupโs standard
HelpTheme
to our ownHelpExtraTheme
.-
theme:
HelpExtraTheme
ยถ
- style_aliases = {'bracket_1': 'bracket', 'bracket_2': 'bracket', 'default_label': 'bracket', 'envvar_label': 'bracket', 'label_sep_1': 'bracket', 'label_sep_2': 'bracket', 'label_sep_3': 'bracket', 'long_option': 'option', 'range': 'bracket', 'required_label': 'bracket', 'short_option': 'option'}ยถ
Map regexโs group IDs to styles.
Most of the time, the style name is the same as the group ID. But some regular expression implementations requires us to work around group IDs limitations, like
bracket_1
andbracket_2
. In which case we use this mapping to apply back the canonical style to that regex-specific group ID.
- get_style_id(group_id)[source]ยถ
Get the style ID to apply to a group.
Return the style which has the same ID as the group, unless it is defined in the
style_aliases
mapping above.- Return type:
- colorize_group(str_to_style, group_id)[source]ยถ
Colorize a string according to the style of the group ID.
- Return type:
- colorize(match)[source]ยถ
Colorize all groups with IDs in the provided matching result.
All groups without IDs are left as-is.
All groups are processed in the order they appear in the
match
object. Then all groups are concatenated to form the final string that is returned.Caution
Implementation is a bit funky here because there is no way to iterate over both unnamed and named groups, in the order they appear in the regex, while keeping track of the group ID.
So we have to iterate over the list of matching strings and pick up the corresponding group ID along the way, from the
match.groupdict()
dictionary. This also means we assume that thematch.groupdict()
is returning an ordered dictionary. Which is supposed to be true as of Python 3.7.- Return type:
- highlight_extra_keywords(help_text)[source]ยถ
Highlight extra keywords in help screens based on the theme.
It is based on regular expressions. While this is not a bullet-proof method, it is good enough. After all, help screens are not consumed by machine but are designed for humans.
Danger
All the regular expressions below are designed to match its original string into a sequence of contiguous groups.
This means each part of the matching result must be encapsulated in a group. And subgroups are not allowed (unless their are explicitly set as non-matching with
(?:...)
prefix).Groups with a name must have a corresponding style.
- Return type:
-
theme:
- click_extra.colorize.highlight(content, patterns, styling_func, ignore_case=False)[source]ยถ
Highlights parts of the
content
that matchespatterns
.Takes care of overlapping parts within the
content
, so that the styling function is applied only once to each contiguous range of matching characters.Todo
Support case-foldeing, so we can have the
Straรe
string matching theStrasse
content.This could be tricky as it messes with string length and characters index, which our logic relies on.
Danger
Roundtrip through lower-casing/upper-casing is a can of worms, because some characters change length when their case is changed:
- Return type: