Highlighting CLI Options
In this project, command-line options, switches, and metavariables are automatically styled in help text using specialized Rich highlighters. These highlighters use regular expressions to identify CLI patterns and apply styles defined in the global theme.
Styling CLI Elements with OptionHighlighter
The OptionHighlighter class is the primary tool for identifying standard CLI syntax. It is instantiated as a global highlighter object in typer/rich_utils.py and applied to usage strings and option lists.
from typer.rich_utils import highlighter
from rich.text import Text
# Manually highlighting a string
text = Text("Usage: my-app -s --option <name>")
highlighted_text = highlighter(text)
# The highlighter identifies:
# - 'Usage: ' (style: usage)
# - '-s' (style: switch)
# - '--option' (style: option)
# - '<name>' (style: metavar)
The highlighter uses the following regex patterns defined in typer/rich_utils.py:
class OptionHighlighter(RegexHighlighter):
"""Highlights our special options."""
highlights = [
r"(^|\W)(?P<switch>\-\w+)(?![a-zA-Z0-9])",
r"(^|\W)(?P<option>\-\-[\w\-]+)(?![a-zA-Z0-9])",
r"(?P<metavar>\<[^\>]+\>)",
r"(?P<usage>Usage: )",
]
Handling Negative Options
For secondary or "negative" options (like --no-force), the project uses NegativeOptionHighlighter. This ensures that destructive or disabling flags are visually distinct from standard options.
from typer.rich_utils import negative_highlighter
from rich.text import Text
# Applied to secondary options in the help panel
text = Text("--no-cache, -N")
highlighted = negative_highlighter(text)
# Identifies:
# - '-N' (style: negative_switch)
# - '--no-cache' (style: negative_option)
Formatting Metavariables
The MetavarHighlighter is used specifically for argument placeholders and their separators (brackets, pipes, and ellipses). It styles the separators as "dim" to keep the focus on the variable names.
from typer.rich_utils import metavar_highlighter
from rich.text import Text
# Styling a complex metavariable string
text = Text("[OPTIONS] | <name>...")
highlighted = metavar_highlighter(text)
# Identifies:
# - '[' and ']' (style: metavar_sep)
# - '|' (style: metavar_sep)
# - '...' (style: metavar_sep)
Integration in Help Generation
These highlighters are integrated into the help rendering pipeline. For example, in _print_options_panel, they are applied to different columns of the options table:
# From typer/rich_utils.py:408
options_rows.append(
[
highlighter(",".join(opt_long_strs)),
highlighter(",".join(opt_short_strs)),
negative_highlighter(",".join(secondary_opt_long_strs)),
negative_highlighter(",".join(secondary_opt_short_strs)),
metavar_highlighter(metavar),
_get_parameter_help(
param=param,
ctx=ctx,
markup_mode=markup_mode,
),
]
)
Additionally, _make_rich_text automatically applies the standard highlighter to any text processed in "rich" markup mode, including command descriptions and epilogues:
# From typer/rich_utils.py:177
else:
assert markup_mode == MARKUP_MODE_RICH
if _has_ansi_character(text):
return highlighter(Text.from_ansi(text, style=style))
else:
return highlighter(Text.from_markup(text, style=style))
Customizing Styles
The colors and formatting used by these highlighters are controlled by global constants at the top of typer/rich_utils.py. You can modify these to change the appearance of the CLI help:
| Constant | Default Style | Target Element |
|---|---|---|
STYLE_OPTION | "bold cyan" | Long options (--option) |
STYLE_SWITCH | "bold green" | Short switches (-s) |
STYLE_NEGATIVE_OPTION | "bold magenta" | Negative long options (--no-option) |
STYLE_NEGATIVE_SWITCH | "bold red" | Negative short switches (-N) |
STYLE_METAVAR | "bold yellow" | Metavariables (<name>) |
STYLE_METAVAR_SEPARATOR | "dim" | Brackets and pipes ([, ` |
STYLE_USAGE | "yellow" | The "Usage: " prefix |
Troubleshooting
- Regex Boundaries: The
OptionHighlighteruses(?![a-zA-Z0-9])lookahead. This means it will not highlight a switch if it is immediately followed by an alphanumeric character (e.g.,-f1might not highlight as expected if not separated). - Usage Prefix: The "Usage: " highlighter only matches the exact string
"Usage: ". If you translate this string or change the casing, the highlighting will fail unless the regex inOptionHighlighteris updated. - Markup Conflicts: If you use Rich markup (e.g.,
[bold]...[/]) in your help text whilemarkup_modeis set to"rich", theOptionHighlighteris applied after the markup is parsed. This can lead to nested styles if your markup overlaps with detected CLI options.