From 2f72f4a1b4d24bc7b18845bf6dbe28f95f162a15 Mon Sep 17 00:00:00 2001 From: Dayna Blackwell Date: Mon, 27 Apr 2026 16:30:33 -0700 Subject: [PATCH] fix: write_usage outputs usage line when args is empty When write_usage is called with no args (the default), wrap_text receives an empty string and returns an empty string, dropping the initial_indent that contains the usage prefix. The usage line vanishes entirely. Handle the empty-args case before calling wrap_text: write the usage prefix directly (stripped of trailing space) followed by a newline. Fixes #3360 --- src/click/formatting.py | 4 +++- tests/test_formatting.py | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/click/formatting.py b/src/click/formatting.py index 0b64f831b5..64a54c336a 100644 --- a/src/click/formatting.py +++ b/src/click/formatting.py @@ -158,7 +158,9 @@ def write_usage(self, prog: str, args: str = "", prefix: str | None = None) -> N usage_prefix = f"{prefix:>{self.current_indent}}{prog} " text_width = self.width - self.current_indent - if text_width >= (term_len(usage_prefix) + 20): + if not args: + self.write(usage_prefix.rstrip()) + elif text_width >= (term_len(usage_prefix) + 20): # The arguments will fit to the right of the prefix. indent = " " * term_len(usage_prefix) self.write( diff --git a/tests/test_formatting.py b/tests/test_formatting.py index c79f6577fa..d3d7e4f0fc 100644 --- a/tests/test_formatting.py +++ b/tests/test_formatting.py @@ -366,3 +366,24 @@ 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(): + """write_usage should output the usage line even when args is empty.""" + formatter = click.HelpFormatter() + formatter.write_usage("program") + assert formatter.getvalue() == "Usage: program\n" + + +def test_write_usage_with_args(): + """write_usage should still work normally with arguments.""" + formatter = click.HelpFormatter() + formatter.write_usage("program", "FILE [OPTIONS]") + assert formatter.getvalue() == "Usage: program FILE [OPTIONS]\n" + + +def test_write_usage_no_args_custom_prefix(): + """write_usage with a custom prefix and no args.""" + formatter = click.HelpFormatter() + formatter.write_usage("program", prefix="Run: ") + assert formatter.getvalue() == "Run: program\n"