1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
# SPDX-FileCopyrightText: 2026 Dennis Fink <me+coding@dennisfink.me>
#
# SPDX-License-Identifier: BSD-3-Clause
import click_extra as click
class FlexibleColorOption(click.ColorOption):
"""Allow the color option value to be passed with or without ``=``."""
_gnu_optional_value = False
def emit(prefix: str, color: str, *message: str, enabled: bool = True) -> None:
"""Render a styled prefix and message to stdout.
Internal helper used by error(), msg(), warn(), verbose(), and debug()
to avoid duplicating the Click styling and echo logic. The first message
argument is rendered in bold, subsequent arguments are appended unstyled.
Args:
prefix: The prefix string shown before the message (e.g. "==>", "==> ERROR:").
color: A Click-compatible color name (e.g. "red", "green") applied to the prefix.
*message: One or more message parts to display. At least one is required.
enabled: If False, the function returns immediately without printing.
Defaults to True.
Raises:
TypeError: If no message arguments are provided.
"""
if not message:
raise TypeError("emit() missing 1 required positional argument: 'message'")
if not enabled:
return
click.echo(
" ".join(
[
click.style(prefix, fg=color, bold=True),
click.style(message[0], bold=True),
*message[1:],
]
)
)
def error(*message: str) -> None:
"""Print a formatted error message to stdout in red.
The first argument is rendered in bold, subsequent arguments are appended
unstyled. Always prints regardless of quiet or verbose flags.
Args:
*message: One or more message parts to display.
"""
emit("==> ERROR:", "red", *message)
@click.pass_obj
def msg(obj: dict[str, bool], *message: str) -> None:
"""Print a formatted informational message to stdout in green.
Suppressed when the quiet flag is set. The first argument is rendered
in bold, subsequent arguments are appended unstyled.
Args:
*message: One or more message parts to display.
"""
emit("==>", "green", *message, enabled=not obj.get("quiet", False))
@click.pass_obj
def warn(obj: dict[str, bool], *message: str) -> None:
"""Print a formatted warning message to stdout in yellow.
Suppressed when the quiet flag is set. The first argument is rendered
in bold, subsequent arguments are appended unstyled.
Args:
*message: One or more message parts to display.
"""
emit("==>", "yellow", *message, enabled=not obj.get("quiet", False))
@click.pass_obj
def verbose(obj: dict[str, bool], *message: str) -> None:
"""Print a formatted verbose message to stdout in blue.
Only prints when the verbose flag is set and the quiet flag is not.
The first argument is rendered in bold, subsequent arguments are
appended unstyled.
Args:
*message: One or more message parts to display.
"""
emit(
"==>",
"blue",
*message,
enabled=obj.get("verbose", False) and not obj.get("quiet", False),
)
@click.pass_obj
def debug(obj: dict[str, bool], *message: str) -> None:
"""Print a formatted debug message to stdout in magenta.
Only prints when the DEBUG environment variable is set to a truthy
value (1, true, yes). The first argument is rendered in bold,
subsequent arguments are appended unstyled.
Args:
*message: One or more message parts to display.
"""
emit("==>", "magenta", *message, enabled=obj.get("debug", False))
|