0
# Prompt System
1
2
Main prompt function and question loading utilities for processing question lists, managing state, and handling user interactions. The prompt system provides the core interaction loop, answer collection, validation handling, and support for loading questions from various data formats.
3
4
## Capabilities
5
6
### Main Prompt Function
7
8
The central prompt function processes a list of questions sequentially, collecting answers and managing the interaction flow with comprehensive error handling.
9
10
```python { .api }
11
def prompt(
12
questions: list,
13
render=None,
14
answers: dict | None = None,
15
theme=themes.Default(),
16
raise_keyboard_interrupt: bool = False
17
) -> dict:
18
"""
19
Process a list of questions and collect user answers.
20
21
Args:
22
questions: List of Question instances to process
23
render: Custom render engine (defaults to ConsoleRender)
24
answers: Pre-existing answers dict to extend
25
theme: Theme for visual styling (defaults to themes.Default())
26
raise_keyboard_interrupt: Whether to raise KeyboardInterrupt or handle gracefully
27
28
Returns:
29
Dictionary mapping question names to user answers
30
31
Raises:
32
KeyboardInterrupt: If raise_keyboard_interrupt=True and user cancels
33
"""
34
```
35
36
**Usage Examples:**
37
38
```python
39
import inquirer
40
41
# Basic usage
42
questions = [
43
inquirer.Text('name', message="Your name?"),
44
inquirer.List('color', message="Favorite color?", choices=['Red', 'Blue', 'Green'])
45
]
46
answers = inquirer.prompt(questions)
47
48
# With pre-existing answers and custom theme
49
from inquirer.themes import GreenPassion
50
51
initial_answers = {'user_type': 'admin'}
52
answers = inquirer.prompt(
53
questions,
54
answers=initial_answers,
55
theme=GreenPassion(),
56
raise_keyboard_interrupt=True
57
)
58
59
# With validation and dynamic messages
60
questions = [
61
inquirer.Text('first_name', message="First name?"),
62
inquirer.Text('last_name', message="Last name?"),
63
inquirer.Confirm(
64
'confirm_name',
65
message="Is your name {first_name} {last_name}?", # Dynamic message
66
default=True
67
)
68
]
69
```
70
71
### Question Loading from Dictionary
72
73
Load individual questions from dictionary configurations, enabling dynamic question creation and serialization support.
74
75
```python { .api }
76
def load_from_dict(question_dict: dict) -> Question:
77
"""
78
Load a single question from dictionary configuration.
79
80
Args:
81
question_dict: Dictionary with question configuration.
82
Must include 'name' and 'kind' keys.
83
Additional keys depend on question type.
84
85
Returns:
86
Question instance of the appropriate type
87
88
Raises:
89
UnknownQuestionTypeError: If 'kind' value is not recognized
90
KeyError: If required keys ('name', 'kind') are missing
91
"""
92
```
93
94
**Usage Example:**
95
96
```python
97
question_config = {
98
'kind': 'text',
99
'name': 'username',
100
'message': 'Enter username',
101
'default': 'admin',
102
'validate': lambda _, x: len(x) >= 3
103
}
104
105
question = inquirer.load_from_dict(question_config)
106
```
107
108
### Question Loading from List
109
110
Load multiple questions from a list of dictionary configurations, useful for configuration-driven question generation.
111
112
```python { .api }
113
def load_from_list(question_list: list[dict]) -> list[Question]:
114
"""
115
Load multiple questions from list of dictionary configurations.
116
117
Args:
118
question_list: List of dictionaries, each with question configuration.
119
Each dict must include 'name' and 'kind' keys.
120
121
Returns:
122
List of Question instances
123
124
Raises:
125
UnknownQuestionTypeError: If any 'kind' value is not recognized
126
KeyError: If any required keys ('name', 'kind') are missing
127
"""
128
```
129
130
**Usage Example:**
131
132
```python
133
questions_config = [
134
{
135
'kind': 'text',
136
'name': 'project_name',
137
'message': 'Project name?'
138
},
139
{
140
'kind': 'list',
141
'name': 'project_type',
142
'message': 'Project type?',
143
'choices': ['web', 'api', 'cli']
144
},
145
{
146
'kind': 'checkbox',
147
'name': 'features',
148
'message': 'Select features',
149
'choices': ['auth', 'db', 'cache']
150
}
151
]
152
153
questions = inquirer.load_from_list(questions_config)
154
answers = inquirer.prompt(questions)
155
```
156
157
### Question Loading from JSON
158
159
Load questions from JSON string, supporting both single question and question list formats for configuration file integration.
160
161
```python { .api }
162
def load_from_json(question_json: str) -> list[Question] | Question:
163
"""
164
Load questions from JSON string.
165
166
Args:
167
question_json: JSON string containing question configuration(s).
168
Must be valid JSON containing dict or list.
169
170
Returns:
171
- List of Question instances if JSON contains an array
172
- Single Question instance if JSON contains an object
173
174
Raises:
175
json.JSONDecodeError: If JSON is malformed
176
TypeError: If JSON contains neither dict nor list
177
UnknownQuestionTypeError: If any 'kind' value is not recognized
178
KeyError: If any required keys ('name', 'kind') are missing
179
"""
180
```
181
182
**Usage Examples:**
183
184
```python
185
# Single question from JSON
186
json_config = '''
187
{
188
"kind": "confirm",
189
"name": "proceed",
190
"message": "Continue with installation?",
191
"default": true
192
}
193
'''
194
question = inquirer.load_from_json(json_config)
195
196
# Multiple questions from JSON
197
json_config = '''
198
[
199
{
200
"kind": "text",
201
"name": "app_name",
202
"message": "Application name?"
203
},
204
{
205
"kind": "list",
206
"name": "environment",
207
"message": "Target environment?",
208
"choices": ["development", "staging", "production"]
209
}
210
]
211
'''
212
questions = inquirer.load_from_json(json_config)
213
answers = inquirer.prompt(questions)
214
215
# Loading from file
216
with open('questions.json', 'r') as f:
217
questions = inquirer.load_from_json(f.read())
218
```
219
220
## Dynamic Question Properties
221
222
Questions support dynamic properties that are resolved at runtime based on previous answers, enabling conditional logic and dynamic content.
223
224
### Dynamic Messages
225
226
Messages can include format strings that reference previous answers:
227
228
```python
229
questions = [
230
inquirer.Text('first_name', message="First name?"),
231
inquirer.Text('last_name', message="Last name?"),
232
inquirer.Text(
233
'email',
234
message="Email for {first_name} {last_name}?",
235
default="{first_name}.{last_name}@company.com"
236
)
237
]
238
```
239
240
### Dynamic Defaults
241
242
Default values can be functions that receive the answers dictionary:
243
244
```python
245
def generate_username(answers):
246
if 'first_name' in answers and 'last_name' in answers:
247
return f"{answers['first_name']}.{answers['last_name']}".lower()
248
return "user"
249
250
questions = [
251
inquirer.Text('first_name', message="First name?"),
252
inquirer.Text('last_name', message="Last name?"),
253
inquirer.Text(
254
'username',
255
message="Username?",
256
default=generate_username # Function called with answers dict
257
)
258
]
259
```
260
261
### Dynamic Choices
262
263
Choice lists can be functions that generate options based on previous answers:
264
265
```python
266
def get_available_roles(answers):
267
if answers.get('user_type') == 'admin':
268
return ['super_admin', 'admin', 'user']
269
else:
270
return ['user', 'guest']
271
272
questions = [
273
inquirer.List('user_type', message="User type?", choices=['admin', 'regular']),
274
inquirer.List(
275
'role',
276
message="Select role",
277
choices=get_available_roles # Dynamic choices based on user_type
278
)
279
]
280
```
281
282
### Conditional Questions
283
284
Questions can be conditionally skipped using the `ignore` parameter:
285
286
```python
287
questions = [
288
inquirer.Confirm('has_database', message="Does your app use a database?"),
289
inquirer.List(
290
'db_type',
291
message="Database type?",
292
choices=['postgresql', 'mysql', 'sqlite'],
293
ignore=lambda answers: not answers.get('has_database', False) # Skip if no DB
294
)
295
]
296
```
297
298
## Validation System
299
300
The prompt system includes comprehensive validation support with custom error messages and validation functions.
301
302
### Custom Validation Functions
303
304
```python
305
def validate_email(answers, current):
306
import re
307
if not re.match(r'^[^@]+@[^@]+\.[^@]+$', current):
308
raise inquirer.errors.ValidationError(
309
current,
310
reason="Please enter a valid email address"
311
)
312
return True
313
314
def validate_port(answers, current):
315
try:
316
port = int(current)
317
if not (1 <= port <= 65535):
318
raise inquirer.errors.ValidationError(
319
current,
320
reason="Port must be between 1 and 65535"
321
)
322
return True
323
except ValueError:
324
raise inquirer.errors.ValidationError(
325
current,
326
reason="Port must be a number"
327
)
328
329
questions = [
330
inquirer.Text('email', message="Email?", validate=validate_email),
331
inquirer.Text('port', message="Port?", validate=validate_port, default="8080")
332
]
333
```