From 3a7c9d96ac4819c996917d9ff330c708cf6c6ffe Mon Sep 17 00:00:00 2001 From: ReinerBRO <593493640@qq.com> Date: Thu, 19 Mar 2026 02:28:27 +0800 Subject: [PATCH] Fix unknown single-dash multichar option error message --- src/click/parser.py | 18 ++++++++++++++++++ tests/test_options.py | 11 +++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/click/parser.py b/src/click/parser.py index 1ea1f7166e..b32d00ea44 100644 --- a/src/click/parser.py +++ b/src/click/parser.py @@ -386,6 +386,20 @@ def _match_long_opt( option.process(value, state) + def _get_single_prefix_long_opt_prefix(self, arg: str) -> str | None: + norm_arg = _normalize_opt(arg, self.ctx) + matches = [ + opt + for opt in self._long_opt + if len(opt) > 2 + and len(norm_arg) > len(opt) + and len(_split_opt(opt)[0]) == 1 + and norm_arg.startswith(opt) + ] + if not matches: + return None + return max(matches, key=len) + def _match_short_opt(self, arg: str, state: _ParsingState) -> None: stop = False i = 1 @@ -401,6 +415,10 @@ def _match_short_opt(self, arg: str, state: _ParsingState) -> None: if self.ignore_unknown_options: unknown_options.append(ch) continue + if i == 2: + long_opt_prefix = self._get_single_prefix_long_opt_prefix(arg) + if long_opt_prefix is not None: + raise NoSuchOption(long_opt_prefix, ctx=self.ctx) raise NoSuchOption(opt, ctx=self.ctx) if option.takes_value: # Any characters left in arg? Pretend they're the diff --git a/tests/test_options.py b/tests/test_options.py index f198d10183..380207949f 100644 --- a/tests/test_options.py +++ b/tests/test_options.py @@ -144,6 +144,17 @@ def cli(): assert f"No such option: {unknown_flag}" in result.output +def test_unknown_single_dash_multichar_option_shows_full_option(runner): + @click.command() + @click.option("-dbg", is_flag=True) + def cli(dbg): + click.echo(f"dbg={dbg}") + + result = runner.invoke(cli, ["-dbgwrong"]) + assert result.exception + assert "No such option: -dbg" in result.output + + @pytest.mark.parametrize( ("value", "expect"), [