From dfcccfac54a960e7a4dbf7181c93e14b571fd34a Mon Sep 17 00:00:00 2001 From: Apoorv Darshan Date: Thu, 9 Jul 2026 19:43:00 +0530 Subject: [PATCH 1/2] Do not offer value completions for boolean flags A click option declared with is_flag=True (including --foo/--no-foo style flags with secondary opts) does not consume a value. The completer was matching such flags against BoolParamType and offering true/false completions; selecting one inserted the value into the positional-argument slot, causing the command to error. Gate value completions in _get_completion_from_params on the param not being a flag, and add completer regression tests. Fixes #116. --- Changelog.rst | 10 ++++++ click_repl/_completer.py | 6 ++++ .../test_option_completion.py | 32 +++++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/Changelog.rst b/Changelog.rst index 02cd37e6..df091551 100644 --- a/Changelog.rst +++ b/Changelog.rst @@ -4,6 +4,16 @@ Change history ================ +.. _version-unreleased: + +Unreleased +========== + +- Do not offer true/false value completions for boolean flags (``is_flag=True``, + including ``--foo/--no-foo`` style options), which previously inserted a value + into the positional-argument slot (#116). + + .. _version-0.3.0: 0.3.0 diff --git a/click_repl/_completer.py b/click_repl/_completer.py index 73a769cd..4fc5afe1 100644 --- a/click_repl/_completer.py +++ b/click_repl/_completer.py @@ -173,6 +173,12 @@ def _get_completion_from_params( choices: list[Completion] = [] param_type = param.type + # Flags (is_flag=True, incl. secondary opts like --foo/--no-foo) do not + # consume a value, so we must not offer any value completions for them. + # See https://github.com/click-contrib/click-repl/issues/116 + if getattr(param, "is_flag", False): + return choices + # shell_complete method for click.Choice is intorduced in click-v8 if not HAS_CLICK_V8 and isinstance(param_type, click.Choice): choices.extend( diff --git a/tests/test_completion/test_common_tests/test_option_completion.py b/tests/test_completion/test_common_tests/test_option_completion.py index b4b2659d..ff8b89b4 100644 --- a/tests/test_completion/test_common_tests/test_option_completion.py +++ b/tests/test_completion/test_common_tests/test_option_completion.py @@ -38,6 +38,38 @@ def bool_option(foo): assert {x.text for x in completions} == {"true"} +def test_flag_option_offers_no_value(): + # A flag (is_flag=True) does not consume a value, so once it has been + # typed the completer must not offer true/false as if it needed one. + # See https://github.com/click-contrib/click-repl/issues/116 + @root_command.command() + @click.argument("arg1", type=click.STRING) + @click.option("-b", "--some-option", "some_option", is_flag=True) + def flag_option(arg1, some_option): + pass + + completions = list(c.get_completions(Document("flag-option -b "))) + assert {x.text for x in completions} == set() + + completions = list(c.get_completions(Document("flag-option --some-option "))) + assert {x.text for x in completions} == set() + + +def test_boolean_flag_with_secondary_opts_offers_no_value(): + # Flags declared with a secondary option (--foo/--no-foo) are also flags + # and must not trigger true/false value completions. + @root_command.command() + @click.option("--shout/--no-shout", default=False) + def toggle_flag(shout): + pass + + completions = list(c.get_completions(Document("toggle-flag --shout "))) + assert {x.text for x in completions} == set() + + completions = list(c.get_completions(Document("toggle-flag --no-shout "))) + assert {x.text for x in completions} == set() + + def test_only_unused_with_unique_option(): @root_command.command() @click.option("-u", type=click.BOOL) From 6ca347d5bd8733e91ba77111380ce4f0384c079b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Asif=20Saif=20Uddin=20=7B=22Auvi=22=3A=22=E0=A6=85?= =?UTF-8?q?=E0=A6=AD=E0=A6=BF=22=7D?= Date: Tue, 4 Aug 2026 13:29:48 +0600 Subject: [PATCH 2/2] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- click_repl/_completer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/click_repl/_completer.py b/click_repl/_completer.py index 4fc5afe1..55566075 100644 --- a/click_repl/_completer.py +++ b/click_repl/_completer.py @@ -179,7 +179,7 @@ def _get_completion_from_params( if getattr(param, "is_flag", False): return choices - # shell_complete method for click.Choice is intorduced in click-v8 + # shell_complete method for click.Choice was introduced in Click v8 if not HAS_CLICK_V8 and isinstance(param_type, click.Choice): choices.extend( self._get_completion_from_choices_click_le_7(param, incomplete)