-
Notifications
You must be signed in to change notification settings - Fork 18
FuzzyPrompt
This page is deprecated, documentation moved to: https://inquirerpy.readthedocs.io/
A list prompt with fuzzy search capabilities.
The fuzzy
prompt can perform relatively well until the choices count reach about 300k.
class FuzzyPrompt(BaseComplexPrompt):
def __init__(
self,
message: Union[str, Callable[[SessionResult], str]],
choices: Union[Callable[[SessionResult], List[Any]], List[Any]],
default: Union[str, Callable[[SessionResult], str]] = "",
pointer: str = INQUIRERPY_POINTER_SEQUENCE,
style: InquirerPyStyle = None,
vi_mode: bool = False,
qmark: str = "?",
transformer: Callable[[Any], Any] = None,
filter: Callable[[Any], Any] = None,
instruction: str = "",
multiselect: bool = False,
prompt: str = INQUIRERPY_POINTER_SEQUENCE,
marker: str = INQUIRERPY_POINTER_SEQUENCE,
border: bool = True,
info: bool = True,
height: Union[str, int] = None,
max_height: Union[str, int] = None,
validate: Union[Callable[[Any], bool], Validator] = None,
invalid_message: str = "Invalid input",
keybindings: Dict[str, List[Dict[str, Any]]] = None,
) -> None:
The following example will download a sample file and demos the performance of the fuzzy
prompt with 100k words.
Classic Syntax (PyInquirer)
import urllib.request
from contextlib import ExitStack
from pathlib import Path
from InquirerPy import prompt
def get_choices(_):
p = Path(__file__).resolve().parent.joinpath("sample.txt")
choices = []
with ExitStack() as stack:
if not p.exists():
file = stack.enter_context(p.open("w+"))
sample = stack.enter_context(
urllib.request.urlopen(
"https://assets.kazhala.me/InquirerPy/sample.txt"
)
)
file.write(sample.read().decode())
file.seek(0, 0)
else:
file = stack.enter_context(p.open("r"))
for line in file.readlines():
choices.append(line[:-1])
return choices
questions = [
{
"type": "fuzzy",
"message": "Select actions:",
"choices": ["hello", "weather", "what", "whoa", "hey", "yo"],
"default": "he",
"max_height": "70%",
},
{
"type": "fuzzy",
"message": "Select preferred words:",
"choices": get_choices,
"multiselect": True,
"validate": lambda x: len(x) > 1,
"invalid_message": "minimum 1 selection",
"max_height": "70%",
},
]
result = prompt(questions=questions)
Alternate Syntax
import urllib.request
from contextlib import ExitStack
from pathlib import Path
from InquirerPy import inquirer, prompt
def get_choices(_):
p = Path(__file__).resolve().parent.joinpath("sample.txt")
choices = []
with ExitStack() as stack:
if not p.exists():
file = stack.enter_context(p.open("w+"))
sample = stack.enter_context(
urllib.request.urlopen(
"https://assets.kazhala.me/InquirerPy/sample.txt"
)
)
file.write(sample.read().decode())
file.seek(0, 0)
else:
file = stack.enter_context(p.open("r"))
for line in file.readlines():
choices.append(line[:-1])
return choices
action = inquirer.fuzzy(
message="Select actions:",
choices=["hello", "weather", "what", "whoa", "hey", "yo"],
default="he",
max_height="70%",
).execute()
words = inquirer.fuzzy(
message="Select preferred words:",
choices=get_choices,
multiselect=True,
validate=lambda result: len(result) > 1,
invalid_message="minimum 2 selections",
max_height="70%",
).execute()
REQUIRED
The question message to display/ask the user.
When providing as a function, the current prompt session result will be provided as a parameter. If you are using the alternate syntax (i.e. inquirer
), put a dummy parameter (_
) in your function.
from InquirerPy import inquirer
def get_message(_) -> str:
message = "Name:"
# logic ...
return message
result = inquirer.fuzzy(message=get_message, choices=[1, 2, 3]).execute()
REQUIRED
A list of choices for user to select.
When providing as a function, the current prompt session result will be provided as a parameter. If you are using the alternate syntax (i.e. inquirer
), put a dummy parameter (_
) in your function.
Each choice can be either any value that have a string representation (e.g. can str(value)
), or it can be a dictionary which consists of the following keys.
- name: (Any) The display name of the choice, user will be able to see this value.
- value: (Any) The value of the choice, can be different than the
name
, user will not be able to see this value.
fuzzy
choice cannot be a Separator
instance.
Different than other list prompts, the default value in fuzzy
won't affect the default starting point of the cursor.
This default value determines the default value in the search bar.
The pointer symbol which indicates the current selected choice. Reference Style for detailed information on prompt components.
The default symbol for fuzzy
is a unicode char ❯
.
? Question: █
❯ # search field
choice1
❯ choice2
choice3
If you are suing classic syntax (i.e.
style
), there's no need to provide this value sinceprompt
already sets the style, unless you would like to apply different style for different question.
An InquirerPyStyle
instance. Use get_style
to retrieve an instance, reference Style documentation for more information.
If you are suing classic syntax (i.e.
prompt
), there's no need to provide this value sinceprompt
already sets sets this value, unless you would like to applyvi_mode
to specific questions.
Enable vim
keybindings for the fuzzy
prompt. It will change the up navigation from ctrl-p/up
to k/up
and down navigation from ctrl-n/down
to j/down
.
Checkout Keybindings documentation for more information.
This will also allow you to use the vim
shortcuts in the search field.
The question mark symbol to display in front of the question. By default, the qmark is ?
.
? Question1
? Question2
Note:
filter
function won't affect the answer passed intotransformer
,filter
will manipulate thechoice["value"]
while thetransformer
function will manipulate thechoice["name"]
.
A callable to transform the result. This is visual effect only, meaning it doesn't affect the returned result, it only changes the result displayed in the prompt.
The value provided to the transformer is name of a choice (choice["name"]
) or a list of name of the choices. This means
that the value may be string even if the choices only consists of other types. Reference the following example.
result = inquirer.fuzzy(
message="Select one:", choices=[1, 2, 3], default=2
).execute() # UI -> ? Select one: 2
result = inquirer.fuzzy(
message="Select one:",
choices=[1, 2, 3],
default="2",
transformer=lambda result: int(result) * 2,
).execute() # UI -> ? Select one: 4
A callable to filter the result. Different than the transformer
, this affects the actual
returned result but doesn't affect the visible prompt content.
The value provided to the filter is the value of a choice (choice["value"]
) or a list of value of the choices.
result = inquirer.fuzzy(
message="Select one:", choices=[1, 2, 3], default=2
).execute() # result = 2
result = inquirer.fuzzy(
message="Select one:",
choices=[1, 2, 3],
default="2",
filter=lambda result: result * 2,
).execute() # result = 4
Optionally provide some instruction to the user such as navigation keybindings or how many choices they should select. This will be displayed right after the question message in the prompt.
Enable multiple selection of the fuzzy
prompt. This enables the keybindings such as tab
and shift-tab
to select more
choices. Visit Keybinding for detailed information on keybindings.
Setting this value to True
also change the result from a single value to a list of values.
The begining symbol of the search field. The default symbol is a unicode char ❯
.
? Question: █
❯ # search field
choice1
choice2
A symbol indicating the selected/marked choices. When a choice is selected using keybindings such as tab
or space
, this
symbol will be displayed between the pointer and choice. Reference Style for more details
on prompt components.
The default symbol is an unicode ❯
.
? Question: █
❯ # search field
❯1) choice1
❯2) choice2
❯ 3) choice3
Enable a border around the choices and search field. This is enabled by default. If you prefer
not to have border, set to False
.
Display some basic information such as total choices and selected choices count for this current fuzzy
prompt.
This is enabled by default, if you prefer to have information displayed, set to False
.
Note: for a better experience, setting the
max_height
is the preferred way of specifying the height.max_height
allow the height of the prompt to be more dynamic, prompt will only take as much space as it needs. When reaching max_height, user will be able to scroll.
Set the height of the fuzzy
prompt. This parameter can be used to control
how much height the prompt should take. The height
parameter will set the prompt
height to a fixed value no matter how much space the content requires.
When content is less than the height, height will be extended to the specified height even if the content doesn't require that much space leaving areas blank.
When content is greater than the height, user will be able to scroll through the prompt when navigating up/down.
The value of height
can be either a int
or a string
. An int
indicates an exact value in how many lines
in the terminal the prompt should take. (e.g. setting height
to 1 will cause the prompt to only display 1 choice at a time).
A str
indicates a percentile in respect to the entire visible terminal.
The following example will only display 2 choices at a time, meaning only the choice 1
and 2
will be visible.
The choice 3
will be visible when user scroll down.
result = inquirer.fuzzy(
message="Select one:",
choices=[1, 2, 3],
height=2
).execute()
The following example will cause the fuzzy
prompt to take 50% of the entire terminal.
result = inquirer.fuzzy(
message="Select one:",
choices=[1, 2, 3],
height="50%" # or just "50"
).execute()
The default max_height for all prompt is "60%" if both height and max_height is not provided.
This value controls the maximum height the prompt can grow. When reaching the maximum height, user will be able to scroll.
The value of max_height
can be either a int
or a string
. An int
indicates an exact value in how many lines
in the terminal the prompt can take. (e.g. setting height
to 1 will cause the prompt to only display 1 choice at a time).
A str
indicates a percentile in respect to the entire visible terminal.
The following example will let the fuzzy
prompt to display all of its content unless the visible terminal is less 10 lines in which
9 * 0.5 - 2
is not enough to display all 3 choices, then user will be able to scroll.
result = inquirer.fuzzy(
message="Select one:",
choices=[1, 2, 3],
max_height="50%" # or just "50"
).execute()
Provide the validator for this question. Checkout Validator documentation for full details.
An effective way of using validator against a fuzzy
prompt would be checking and enforcing the minimum choices that's required to be selected in
a multiselect scenario.
By default, when there are no choices after filter, user can still hit enter and the result will be a None
value. To prevent this from happening, you
can setup a simple validator.
The following example will not result in a None
value when user hit enter when no choices is available. It checks if the current result is empty string.
If you prefer to display some message, set the invalid_message
.
from InquirerPy import inquirer
result = inquirer.fuzzy(
message="Select one:",
choices=[1, 2, 3, 4],
default="asfasfasf",
validate=lambda result: result != "",
invalid_message="",
).execute()
In a multiselect prompt, check the length of the result.
from InquirerPy import inquirer
result = inquirer.fuzzy(
message="Select one:",
choices=[1, 2, 3, 4],
default="asfasfasf",
validate=lambda result: len(result) > 0,
invalid_message="",
).execute()
Configure the error message to display to the user when input does not meet compliance.
If the validate
parameter is a Validator
instance, then skip this parameter.
Provide a dictionary of custom keybindings to apply to this prompt. For more information of keybindings, reference Keybinding section.
By default, InquirerPy
will display cursor at the end of the fuzzy
prompt. Set to False
if you prefer
to hide the cursor.
Prompts