mirror of
https://github.com/Textualize/rich.git
synced 2025-08-04 18:18:22 +00:00
Merge pull request #3052 from seapagan/case-insensitive-prompt-choices
Case insensitive prompt choices
This commit is contained in:
commit
855cdbe2ab
5 changed files with 58 additions and 6 deletions
|
@ -32,6 +32,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
### Added
|
||||
|
||||
- Adds missing parameters to Panel.fit https://github.com/Textualize/rich/issues/3142
|
||||
- Adds a `case_sensitive` parameter to `prompt.Prompt`. This determines if the
|
||||
response is treated as case-sensitive. Defaults to `True`.
|
||||
|
||||
### Fixed
|
||||
|
||||
|
@ -85,7 +87,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
- Text.tab_size now defaults to `None` to indicate that Console.tab_size should be used.
|
||||
|
||||
|
||||
## [13.4.2] - 2023-06-12
|
||||
|
||||
### Changed
|
||||
|
|
|
@ -52,6 +52,7 @@ The following people have contributed to the development of Rich:
|
|||
- [Kylian Point](https://github.com/p0lux)
|
||||
- [Kyle Pollina](https://github.com/kylepollina)
|
||||
- [Sebastián Ramírez](https://github.com/tiangolo)
|
||||
- [Grant Ramsay](https://github.com/seapagan)
|
||||
- [Felipe Guedes](https://github.com/guedesfelipe)
|
||||
- [Min RK](https://github.com/minrk)
|
||||
- [Clément Robert](https://github.com/neutrinoceros)
|
||||
|
|
|
@ -18,6 +18,13 @@ If you supply a list of choices, the prompt will loop until the user enters one
|
|||
>>> from rich.prompt import Prompt
|
||||
>>> name = Prompt.ask("Enter your name", choices=["Paul", "Jessica", "Duncan"], default="Paul")
|
||||
|
||||
By default this is case sensitive, but you can set `case_sensitive=False` to make it case insensitive::
|
||||
|
||||
>>> from rich.prompt import Prompt
|
||||
>>> name = Prompt.ask("Enter your name", choices=["Paul", "Jessica", "Duncan"], default="Paul", case_sensitive=False)
|
||||
|
||||
Now, it would accept "paul" or "Paul" as valid responses.
|
||||
|
||||
In addition to :class:`~rich.prompt.Prompt` which returns strings, you can also use :class:`~rich.prompt.IntPrompt` which asks the user for an integer, and :class:`~rich.prompt.FloatPrompt` for floats.
|
||||
|
||||
The :class:`~rich.prompt.Confirm` class is a specialized prompt which may be used to ask the user a simple yes / no question. Here's an example::
|
||||
|
@ -30,4 +37,4 @@ The Prompt class was designed to be customizable via inheritance. See `prompt.py
|
|||
|
||||
To see some of the prompts in action, run the following command from the command line::
|
||||
|
||||
python -m rich.prompt
|
||||
python -m rich.prompt
|
||||
|
|
|
@ -36,6 +36,7 @@ class PromptBase(Generic[PromptType]):
|
|||
console (Console, optional): A Console instance or None to use global console. Defaults to None.
|
||||
password (bool, optional): Enable password input. Defaults to False.
|
||||
choices (List[str], optional): A list of valid choices. Defaults to None.
|
||||
case_sensitive (bool, optional): Matching of choices should be case-sensitive. Defaults to True.
|
||||
show_default (bool, optional): Show default in prompt. Defaults to True.
|
||||
show_choices (bool, optional): Show choices in prompt. Defaults to True.
|
||||
"""
|
||||
|
@ -57,6 +58,7 @@ class PromptBase(Generic[PromptType]):
|
|||
console: Optional[Console] = None,
|
||||
password: bool = False,
|
||||
choices: Optional[List[str]] = None,
|
||||
case_sensitive: bool = True,
|
||||
show_default: bool = True,
|
||||
show_choices: bool = True,
|
||||
) -> None:
|
||||
|
@ -69,6 +71,7 @@ class PromptBase(Generic[PromptType]):
|
|||
self.password = password
|
||||
if choices is not None:
|
||||
self.choices = choices
|
||||
self.case_sensitive = case_sensitive
|
||||
self.show_default = show_default
|
||||
self.show_choices = show_choices
|
||||
|
||||
|
@ -81,6 +84,7 @@ class PromptBase(Generic[PromptType]):
|
|||
console: Optional[Console] = None,
|
||||
password: bool = False,
|
||||
choices: Optional[List[str]] = None,
|
||||
case_sensitive: bool = True,
|
||||
show_default: bool = True,
|
||||
show_choices: bool = True,
|
||||
default: DefaultType,
|
||||
|
@ -97,6 +101,7 @@ class PromptBase(Generic[PromptType]):
|
|||
console: Optional[Console] = None,
|
||||
password: bool = False,
|
||||
choices: Optional[List[str]] = None,
|
||||
case_sensitive: bool = True,
|
||||
show_default: bool = True,
|
||||
show_choices: bool = True,
|
||||
stream: Optional[TextIO] = None,
|
||||
|
@ -111,6 +116,7 @@ class PromptBase(Generic[PromptType]):
|
|||
console: Optional[Console] = None,
|
||||
password: bool = False,
|
||||
choices: Optional[List[str]] = None,
|
||||
case_sensitive: bool = True,
|
||||
show_default: bool = True,
|
||||
show_choices: bool = True,
|
||||
default: Any = ...,
|
||||
|
@ -126,6 +132,7 @@ class PromptBase(Generic[PromptType]):
|
|||
console (Console, optional): A Console instance or None to use global console. Defaults to None.
|
||||
password (bool, optional): Enable password input. Defaults to False.
|
||||
choices (List[str], optional): A list of valid choices. Defaults to None.
|
||||
case_sensitive (bool, optional): Matching of choices should be case-sensitive. Defaults to True.
|
||||
show_default (bool, optional): Show default in prompt. Defaults to True.
|
||||
show_choices (bool, optional): Show choices in prompt. Defaults to True.
|
||||
stream (TextIO, optional): Optional text file open for reading to get input. Defaults to None.
|
||||
|
@ -135,6 +142,7 @@ class PromptBase(Generic[PromptType]):
|
|||
console=console,
|
||||
password=password,
|
||||
choices=choices,
|
||||
case_sensitive=case_sensitive,
|
||||
show_default=show_default,
|
||||
show_choices=show_choices,
|
||||
)
|
||||
|
@ -212,7 +220,9 @@ class PromptBase(Generic[PromptType]):
|
|||
bool: True if choice was valid, otherwise False.
|
||||
"""
|
||||
assert self.choices is not None
|
||||
return value.strip() in self.choices
|
||||
if self.case_sensitive:
|
||||
return value.strip() in self.choices
|
||||
return value.strip().lower() in [choice.lower() for choice in self.choices]
|
||||
|
||||
def process_response(self, value: str) -> PromptType:
|
||||
"""Process response from user, convert to prompt type.
|
||||
|
@ -232,9 +242,17 @@ class PromptBase(Generic[PromptType]):
|
|||
except ValueError:
|
||||
raise InvalidResponse(self.validate_error_message)
|
||||
|
||||
if self.choices is not None and not self.check_choice(value):
|
||||
raise InvalidResponse(self.illegal_choice_message)
|
||||
if self.choices is not None:
|
||||
if not self.check_choice(value):
|
||||
raise InvalidResponse(self.illegal_choice_message)
|
||||
|
||||
if not self.case_sensitive:
|
||||
# return the original choice, not the lower case version
|
||||
return_value = self.response_type(
|
||||
self.choices[
|
||||
[choice.lower() for choice in self.choices].index(value.lower())
|
||||
]
|
||||
)
|
||||
return return_value
|
||||
|
||||
def on_validate_error(self, value: str, error: InvalidResponse) -> None:
|
||||
|
@ -371,5 +389,12 @@ if __name__ == "__main__": # pragma: no cover
|
|||
fruit = Prompt.ask("Enter a fruit", choices=["apple", "orange", "pear"])
|
||||
print(f"fruit={fruit!r}")
|
||||
|
||||
doggie = Prompt.ask(
|
||||
"What's the best Dog? (Case INSENSITIVE)",
|
||||
choices=["Border Terrier", "Collie", "Labradoodle"],
|
||||
case_sensitive=False,
|
||||
)
|
||||
print(f"doggie={doggie!r}")
|
||||
|
||||
else:
|
||||
print("[b]OK :loudly_crying_face:")
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import io
|
||||
|
||||
from rich.console import Console
|
||||
from rich.prompt import Prompt, IntPrompt, Confirm
|
||||
from rich.prompt import Confirm, IntPrompt, Prompt
|
||||
|
||||
|
||||
def test_prompt_str():
|
||||
|
@ -21,6 +21,24 @@ def test_prompt_str():
|
|||
assert output == expected
|
||||
|
||||
|
||||
def test_prompt_str_case_insensitive():
|
||||
INPUT = "egg\nFoO"
|
||||
console = Console(file=io.StringIO())
|
||||
name = Prompt.ask(
|
||||
"what is your name",
|
||||
console=console,
|
||||
choices=["foo", "bar"],
|
||||
default="baz",
|
||||
case_sensitive=False,
|
||||
stream=io.StringIO(INPUT),
|
||||
)
|
||||
assert name == "foo"
|
||||
expected = "what is your name [foo/bar] (baz): Please select one of the available options\nwhat is your name [foo/bar] (baz): "
|
||||
output = console.file.getvalue()
|
||||
print(repr(output))
|
||||
assert output == expected
|
||||
|
||||
|
||||
def test_prompt_str_default():
|
||||
INPUT = ""
|
||||
console = Console(file=io.StringIO())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue