or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdprompt-system.mdquestion-types.mdrender-system.mdshortcuts.mdthemes.md

prompt-system.mddocs/

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

```