1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
|
# Dynamic Values
Several parameters across different prompts accepts callable/function as the argument which
allows you to perform additional logic and generate the argument dynamically.
There's mainly two categories: [Before Rendered](#before-rendered) and [After Answered](#after-answered).
## Before Rendered
Parameters/Keys in this category will be retrieved before the prompt is displayed in the terminal. The main purpose of this category
is to allow {ref}`index:Classic Syntax (PyInquirer)` users to customise the prompt based on previous prompts result.
When these parameters/keys receive function/callable as an argument, the current `InquirerPySessionResult` will be provided as an argument and you can
perform additional logic to generate and return different values.
### Classic Syntax (PyInquirer)
Let's take the `message` and `default` key as an example, in certain scenario, you may want to display different `message` and obtain different `default` values based on previous prompts result.
In the following example, the second prompt will set the `default` value based on the result from the first prompt. And the third prompt will display the `message` based on the result from second prompt.
```python
from InquirerPy import prompt
from InquirerPy.validator import NumberValidator
def get_message(result):
return f"Hi {result['confirm_name']}, enter your age:"
questions = [
{
"type": "input",
"message": "Name:",
"name": "name",
},
{
"type": "input",
"message": "Confirm Name:",
"name": 'confirm_name',
"default": lambda result: result["name"], # inline lambda to make the code shorter
},
{
"type": "input",
"message": get_message, # use a named function for more complex logic
"name": 'age',
"validate": NumberValidator(),
},
]
result = prompt(questions)
```
### Alternate Syntax
When using {ref}`pages/inquirer:inquirer`, you will receive the result immediately after the prompt execution. Hence you can directly
perform your logic to generate the parameters dynamically after each prompt execution.
```
from InquirerPy import inquirer
from InquirerPy.validator import NumberValidator
name = inquirer.text(message="Name:").execute()
confirm_name = inquirer.text(message="Confirm Name:", default=name).execute()
age_message = f"Hi {confirm_name}, enter your age:"
age = inquirer.text(message=age_message, validate=NumberValidator()).execute()
```
However for the sake of keeping code shorter and cleaner in certain scenarios, you can also provide applicable parameters with a function/callable.
```{attention}
To maintain API compatibility with [Classic Syntax](#classic-syntax-pyinquirer), the function will also receive an argument, however it will be `None`. To make your linter/IDE
happy, you should put a dummy parameter `_` in your function definition.
There are plans in place to remove the need of adding dummy parameter in future.
```
```{note}
The following is not a good example that make the code shorter or cleaner..but it just simply illustrate an alternate way of passing arguments.
```
```python
from InquirerPy import inquirer
from InquirerPy.validator import NumberValidator
name = inquirer.text(message="Name:").execute()
confirm_name = inquirer.text(message="Confirm Name:", default=lambda _:name).execute()
age = inquirer.text(
message=lambda _: f"Hi {name}, enter your age:", validate=NumberValidator()
).execute()
```
### Parameters/Keys
#### message
```
Union[str, Callable[["InquirerPySessionResult"], str]]
```
```{admonition} Category
[Before Rendered](#before-rendered)
```
```{seealso}
[Classic Syntax Example](#classic-syntax-pyinquirer)
[Alternate Syntax Example](#alternate-syntax)
```
The `message` parameter/key can either be a simple {class}`string` or a function which returns {class}`string`.
#### default
```
Union[Any, Callable[["InquirerPySessionResult"], Any]]
```
```{admonition} Category
[Before Rendered](#before-rendered)
```
```{attention}
The `default` parameter/key typing can vary between different types of prompt.
```
```{seealso}
[Classic Syntax Example](#classic-syntax-pyinquirer)
[Alternate Syntax Example](#alternate-syntax)
```
The `default` parameter/key can either be a simple value or a function which returns the `default` value.
#### choices
```
Union[List[Any], List["Choice"], List[Dict[str, Any]]]
```
```{admonition} Category
[Before Rendered](#before-rendered)
```
```{attention}
This variable only exists in the following prompts:
* {ref}`pages/prompts/list:ListPrompt`,
* {ref}`pages/prompts/rawlist:RawlistPrompt`,
* {ref}`pages/prompts/expand:ExpandPrompt`,
* {ref}`pages/prompts/checkbox:CheckboxPrompt`,
* {ref}`pages/prompts/fuzzy:FuzzyPrompt`
```
```{note}
The required keys for choices may vary between prompts. There may be additional keys required which would be documented
in individual prompt documentation with additional customised Choice classes.
```
```{seealso}
{ref}`pages/separator:Separator`
```
```{tip}
It is recommended to use the {class}`~InquirerPy.base.control.Choice` class over using {class}`dict`.
```
Each choice can be the following types:
- **Any**: Any value that have a string representation (e.g. can `str(value)`).
- {ref}`pages/separator:Separator`: An instance of the `Separator` class.
- {class}`dict`: Dictionary with the following keys:
- value (Any): The value of the choice when user selects this choice.
- name (str): The value that should be presented to the user prior/after selection of the choice.
- enabled (bool): Indicates if the choice should be pre-selected. This only has effects when the prompt has `multiselect` enabled.
- **{class}`~InquirerPy.base.control.Choice`**: An instance of the `Choice` class.
```{eval-rst}
.. autoclass:: InquirerPy.base.control.Choice
:noindex:
```
<details>
<summary>Classic Syntax (PyInquirer)</summary>
```{code-block} python
from InquirerPy import prompt
from InquirerPy.base.control import Choice
from InquirerPy.separator import Separator
questions = [
{
"type": "list",
"message": "Select regions:",
"choices": [
Choice("ap-southeast-2", name="Sydney"),
Choice("ap-southeast-1", name="Singapore"),
Separator(),
"us-east-1",
"us-east-2",
],
"multiselect": True,
"transformer": lambda result: f"{len(result)} region{'s' if len(result) > 1 else ''} selected",
},
]
result = prompt(questions=questions)
```
</details>
<details open>
<summary>Alternate Syntax</summary>
```{code-block} python
from InquirerPy import inquirer
from InquirerPy.base.control import Choice
from InquirerPy.separator import Separator
region = inquirer.select(
message="Select regions:",
choices=[
Choice("ap-southeast-2", name="Sydney"),
Choice("ap-southeast-1", name="Singapore"),
Separator(),
"us-east-1",
"us-east-2",
],
multiselect=True,
transformer=lambda result: f"{len(result)} region{'s' if len(result) > 1 else ''} selected",
).execute()
```
</details>
## After Answered
Parameters/Keys in this category will be retrieved after the question is answered. The main purpose of this category is to allow additional customisation
to the appearance of the prompt based on user answer after the prompt is answered.
### Parameters/Keys
#### filter
```
Callable[[Any], Any]
```
```{admonition} Category
[After Answered](#after-answered)
```
```{tip}
For prompts that accepts parameter `choices`, the value provided to the filter function will be the value
of the selected choice (`choice["value"]`) or a list of values of the selected choices.
```
A function which performs additional transformation on the result. This affects the actual value returned by {meth}`~InquirerPy.base.simple.BaseSimplePrompt.execute`.
Leveraging this parameter/key can potentially shorten the code and create a cleaner code base. Given a scenario you want to obtain the age from the user, however the result
from {ref}`pages/prompts/input:InputPrompt` is type of {class}`string` by default. You can use the `filter` parameter/key to convert them to {class}`int`.
<details>
<summary>Classic Syntax</summary>
```python
from InquirerPy import prompt
from InquirerPy.validator import NumberValidator
questions = [
{
"type": "input",
"message": "Age:",
"filter": lambda result: int(result),
"validate": NumberValidator()
}
]
result = prompt(questions=questions)
```
</details>
<details open>
<summary>Alternate Syntax</summary>
```python
from InquirerPy import inquirer
from InquirerPy.validator import NumberValidator
age = inquirer.text(
message="Age:", filter=lambda result: int(result), validate=NumberValidator()
).execute()
```
</details>
#### transformer
```
Callable[[Any], str]
```
```{admonition} Category
[After Answered](#after-answered)
```
```{note}
The value received by `transformer` will always be either type of {class}`str` or {class}`list` of {class}`str` depending on the prompt types.
```
```{tip}
`filter` and `transformer` run separately and won't have side effects when running both.
```
```{tip}
For prompts that accepts parameter `choices`, the value provided to the transformer function will be the name
of the selected choice (`choice["name"]`) or a list of names of the selected choices.
```
A function which performs additional transformation on the value that gets printed to the terminal.
Different than `filter` parameter, this is only visual effect and won’t affect the actual value returned by {meth}`~InquirerPy.base.simple.BaseSimplePrompt.execute`.
For example, when working with {ref}`pages/prompts/checkbox:CheckboxPrompt`, all user selected choices will be displayed in the terminal. This may create
unnecessary clutter of texts and may cause the displayed information become less useful. You can use `transformer` parameter/key to change how the result will be printed.
<details>
<summary>Classic Syntax</summary>
```python
"""
Without transformer: ? Select regions: ["us-east-1", "us-west-1"]
With transformer: ? Select regions: 2 regions selected
"""
from InquirerPy import prompt
from InquirerPy.base.control import Choice
choices = [
Choice("ap-southeast-2", name="Sydney", enabled=True),
Choice("ap-southeast-1", name="Singapore", enabled=False),
"us-east-1",
"us-east-2",
]
questions = [
{
"type": "checkbox",
"message": "Select regions:",
"choices": choices,
"cycle": False,
"transformer": lambda result: f"{len(result)} region{'s' if len(result) > 1 else ''} selected",
}
]
result = prompt(questions=questions)
```
</details>
<details open>
<summary>Alternate Syntax</summary>
```python
"""
Without transformer: ? Select regions: ["us-east-1", "us-west-1"]
With transformer: ? Select regions: 2 regions selected
"""
from InquirerPy import inquirer
from InquirerPy.base.control import Choice
choices = [
Choice("ap-southeast-2", name="Sydney", enabled=True),
Choice("ap-southeast-1", name="Singapore", enabled=False),
"us-east-1",
"us-east-2",
]
regions = inquirer.checkbox(
message="Select regions:",
choices=choices,
cycle=False,
transformer=lambda result: f"{len(result)} region{'s' if len(result) > 1 else ''} selected",
).execute()
```
</details>
|