diff --git a/CHANGES.rst b/CHANGES.rst index 057d700df..f3d398354 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,7 @@ Version 8.2.0 Unreleased +- Add support for custom ``show_default`` string in prompts. :pr:`460a142` - Drop support for Python 3.7. :pr:`2588` - Use modern packaging metadata with ``pyproject.toml`` instead of ``setup.cfg``. :pr:`326` diff --git a/src/click/core.py b/src/click/core.py index e783729c7..2d000a822 100644 --- a/src/click/core.py +++ b/src/click/core.py @@ -2927,10 +2927,10 @@ def prompt_for_value(self, ctx: Context) -> t.Any: if self.is_bool_flag: return confirm(self.prompt, default) - # If show_default is set to True/False, provide this to `prompt` as well. For - # non-bool values of `show_default`, we use `prompt`'s default behavior + # If show_default is given, provide this to `prompt` as well, + # otherwise we use `prompt`'s default behavior prompt_kwargs: t.Any = {} - if isinstance(self.show_default, bool): + if self.show_default is not None: prompt_kwargs["show_default"] = self.show_default return prompt( diff --git a/src/click/termui.py b/src/click/termui.py index dcbb22216..4a06be23c 100644 --- a/src/click/termui.py +++ b/src/click/termui.py @@ -60,7 +60,7 @@ def hidden_prompt_func(prompt: str) -> str: def _build_prompt( text: str, suffix: str, - show_default: bool = False, + show_default: bool | str = False, default: t.Any | None = None, show_choices: bool = True, type: ParamType | None = None, @@ -68,6 +68,8 @@ def _build_prompt( prompt = text if type is not None and show_choices and isinstance(type, Choice): prompt += f" ({', '.join(map(str, type.choices))})" + if isinstance(show_default, str): + default = f"({show_default})" if default is not None and show_default: prompt = f"{prompt} [{_format_default(default)}]" return f"{prompt}{suffix}" @@ -88,7 +90,7 @@ def prompt( type: ParamType | t.Any | None = None, value_proc: t.Callable[[str], t.Any] | None = None, prompt_suffix: str = ": ", - show_default: bool = True, + show_default: bool | str = True, err: bool = False, show_choices: bool = True, ) -> t.Any: @@ -112,6 +114,8 @@ def prompt( convert a value. :param prompt_suffix: a suffix that should be added to the prompt. :param show_default: shows or hides the default value in the prompt. + If this value is a string, it shows that string + in parentheses instead of the actual value. :param err: if set to true the file defaults to ``stderr`` instead of ``stdout``, the same as with echo. :param show_choices: Show or hide choices if the passed type is a Choice. @@ -119,6 +123,9 @@ def prompt( show_choices is true and text is "Group by" then the prompt will be "Group by (day, week): ". + .. versionadded:: 8.2 + ``show_default`` can be a custom string. + .. versionadded:: 8.0 ``confirmation_prompt`` can be a custom string. diff --git a/tests/test_options.py b/tests/test_options.py index b7267c182..678184dc5 100644 --- a/tests/test_options.py +++ b/tests/test_options.py @@ -856,6 +856,19 @@ def test_show_default_string(runner): assert "[default: (unlimited)]" in message +def test_string_show_default_shows_custom_string_in_prompt(runner): + @click.command() + @click.option( + "--arg1", show_default="custom", prompt=True, default="my-default-value" + ) + def cmd(arg1): + pass + + result = runner.invoke(cmd, input="my-input", standalone_mode=False) + assert "(custom)" in result.output + assert "my-default-value" not in result.output + + def test_show_default_with_empty_string(runner): """When show_default is True and default is set to an empty string.""" opt = click.Option(["--limit"], default="", show_default=True) diff --git a/tests/test_termui.py b/tests/test_termui.py index ad9d0a66c..04ac99460 100644 --- a/tests/test_termui.py +++ b/tests/test_termui.py @@ -485,3 +485,16 @@ def cmd(arg1): # is False result = runner.invoke(cmd, input="my-input", standalone_mode=False) assert "my-default-value" not in result.output + + +def test_string_show_default_shows_custom_string_in_prompt(runner): + @click.command() + @click.option( + "--arg1", show_default="custom", prompt=True, default="my-default-value" + ) + def cmd(arg1): + pass + + result = runner.invoke(cmd, input="my-input", standalone_mode=False) + assert "(custom)" in result.output + assert "my-default-value" not in result.output