diff --git a/src/click/formatting.py b/src/click/formatting.py index de2ca4711..f5da95d52 100644 --- a/src/click/formatting.py +++ b/src/click/formatting.py @@ -161,14 +161,19 @@ def write_usage(self, prog: str, args: str = "", prefix: str | None = None) -> N if text_width >= (term_len(usage_prefix) + 20): # The arguments will fit to the right of the prefix. indent = " " * term_len(usage_prefix) - self.write( - wrap_text( - args, - text_width, - initial_indent=usage_prefix, - subsequent_indent=indent, + if args: + self.write( + wrap_text( + args, + text_width, + initial_indent=usage_prefix, + subsequent_indent=indent, + ) ) - ) + else: + # No args, but still need to write the "Usage: prog" prefix. + # rstrip removes the trailing space added when building usage_prefix. + self.write(usage_prefix.rstrip()) else: # The prefix is too long, put the arguments on the next line. self.write(usage_prefix) diff --git a/tests/test_formatting.py b/tests/test_formatting.py index c74b53a3d..8e001f467 100644 --- a/tests/test_formatting.py +++ b/tests/test_formatting.py @@ -433,3 +433,11 @@ def test_help_formatter_write_text(): actual = formatter.getvalue() expected = " Lorem ipsum dolor sit amet,\n consectetur adipiscing elit\n" assert actual == expected + + +def test_write_usage_no_args(): + """Regression test for issue #3360: write_usage with empty args + should still emit the 'Usage: prog' prefix, not an empty line.""" + f = click.HelpFormatter() + f.write_usage("program") + assert f.getvalue() == "Usage: program\n"