@topcli/prompts 1.6.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +13 -13
- package/README.md +211 -210
- package/dist/index.cjs +871 -0
- package/dist/index.d.cts +77 -0
- package/dist/index.d.ts +77 -0
- package/dist/index.js +830 -0
- package/package.json +55 -43
- package/index.d.ts +0 -76
- package/index.js +0 -30
- package/src/constants.js +0 -39
- package/src/prompt-agent.js +0 -56
- package/src/prompts/abstract.js +0 -68
- package/src/prompts/confirm.js +0 -135
- package/src/prompts/index.js +0 -12
- package/src/prompts/multiselect.js +0 -333
- package/src/prompts/question.js +0 -115
- package/src/prompts/select.js +0 -215
- package/src/utils.js +0 -43
- package/src/validators.js +0 -6
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,871 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
|
|
29
|
+
// index.ts
|
|
30
|
+
var prompts_exports = {};
|
|
31
|
+
__export(prompts_exports, {
|
|
32
|
+
PromptAgent: () => PromptAgent,
|
|
33
|
+
confirm: () => confirm,
|
|
34
|
+
multiselect: () => multiselect,
|
|
35
|
+
question: () => question,
|
|
36
|
+
required: () => required,
|
|
37
|
+
select: () => select
|
|
38
|
+
});
|
|
39
|
+
module.exports = __toCommonJS(prompts_exports);
|
|
40
|
+
|
|
41
|
+
// src/prompts/question.ts
|
|
42
|
+
var import_node_os2 = require("os");
|
|
43
|
+
var import_kleur2 = __toESM(require("kleur"), 1);
|
|
44
|
+
var import_wcwidth = __toESM(require("@topcli/wcwidth"), 1);
|
|
45
|
+
|
|
46
|
+
// src/prompts/abstract.ts
|
|
47
|
+
var import_node_os = require("os");
|
|
48
|
+
var import_node_readline = require("readline");
|
|
49
|
+
var import_node_stream = require("stream");
|
|
50
|
+
|
|
51
|
+
// src/utils.ts
|
|
52
|
+
var import_node_process = __toESM(require("process"), 1);
|
|
53
|
+
var kAnsiRegex = ansiRegex();
|
|
54
|
+
function ansiRegex({ onlyFirst = false } = {}) {
|
|
55
|
+
const pattern = [
|
|
56
|
+
// eslint-disable-next-line max-len
|
|
57
|
+
"[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)",
|
|
58
|
+
"(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))"
|
|
59
|
+
].join("|");
|
|
60
|
+
return new RegExp(pattern, onlyFirst ? void 0 : "g");
|
|
61
|
+
}
|
|
62
|
+
function stripAnsi(string) {
|
|
63
|
+
return string.replace(kAnsiRegex, "");
|
|
64
|
+
}
|
|
65
|
+
function isUnicodeSupported() {
|
|
66
|
+
if (import_node_process.default.platform !== "win32") {
|
|
67
|
+
return import_node_process.default.env.TERM !== "linux";
|
|
68
|
+
}
|
|
69
|
+
return Boolean(import_node_process.default.env.WT_SESSION) || Boolean(import_node_process.default.env.TERMINUS_SUBLIME) || import_node_process.default.env.ConEmuTask === "{cmd::Cmder}" || import_node_process.default.env.TERM_PROGRAM === "Terminus-Sublime" || import_node_process.default.env.TERM_PROGRAM === "vscode" || import_node_process.default.env.TERM === "xterm-256color" || import_node_process.default.env.TERM === "alacritty" || import_node_process.default.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// src/prompt-agent.ts
|
|
73
|
+
var kPrivateInstancier = Symbol("instancier");
|
|
74
|
+
var PromptAgent = class _PromptAgent {
|
|
75
|
+
/**
|
|
76
|
+
* The prompts answers queue.
|
|
77
|
+
* When not empty, any prompt will be answered by the first answer in this list.
|
|
78
|
+
*/
|
|
79
|
+
nextAnswers = [];
|
|
80
|
+
/**
|
|
81
|
+
* The shared PromptAgent.
|
|
82
|
+
*/
|
|
83
|
+
static #this;
|
|
84
|
+
static agent() {
|
|
85
|
+
return this.#this ??= new _PromptAgent(kPrivateInstancier);
|
|
86
|
+
}
|
|
87
|
+
constructor(instancier) {
|
|
88
|
+
if (instancier !== kPrivateInstancier) {
|
|
89
|
+
throw new Error("Cannot instanciate PromptAgent, use PromptAgent.agent() instead");
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Programmatically set the next answer for any prompt (`question()`, `confirm()`, `select()`)
|
|
94
|
+
*
|
|
95
|
+
* This is useful for testing.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```js
|
|
99
|
+
* const promptAgent = PromptAgent.agent();
|
|
100
|
+
* promptAgent.nextAnswer("toto");
|
|
101
|
+
*
|
|
102
|
+
* const input = await question("what is your name?");
|
|
103
|
+
* assert.equal(input, "toto");
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
nextAnswer(value) {
|
|
107
|
+
if (Array.isArray(value)) {
|
|
108
|
+
this.nextAnswers.push(...value);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
this.nextAnswers.push(value);
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// src/prompts/abstract.ts
|
|
116
|
+
var AbstractPrompt = class _AbstractPrompt {
|
|
117
|
+
stdin;
|
|
118
|
+
stdout;
|
|
119
|
+
message;
|
|
120
|
+
history;
|
|
121
|
+
agent;
|
|
122
|
+
mute;
|
|
123
|
+
rl;
|
|
124
|
+
constructor(message, input = process.stdin, output = process.stdout) {
|
|
125
|
+
if (this.constructor === _AbstractPrompt) {
|
|
126
|
+
throw new Error("AbstractPrompt can't be instantiated.");
|
|
127
|
+
}
|
|
128
|
+
if (typeof message !== "string") {
|
|
129
|
+
throw new TypeError(`message must be string, ${typeof message} given.`);
|
|
130
|
+
}
|
|
131
|
+
this.stdin = input;
|
|
132
|
+
this.stdout = output;
|
|
133
|
+
this.message = message;
|
|
134
|
+
this.history = [];
|
|
135
|
+
this.agent = PromptAgent.agent();
|
|
136
|
+
this.mute = false;
|
|
137
|
+
if (this.stdout.isTTY) {
|
|
138
|
+
this.stdin.setRawMode(true);
|
|
139
|
+
}
|
|
140
|
+
this.rl = (0, import_node_readline.createInterface)({
|
|
141
|
+
input,
|
|
142
|
+
output: new import_node_stream.Writable({
|
|
143
|
+
write: (chunk, encoding, callback) => {
|
|
144
|
+
if (!this.mute) {
|
|
145
|
+
this.stdout.write(chunk, encoding);
|
|
146
|
+
}
|
|
147
|
+
callback();
|
|
148
|
+
}
|
|
149
|
+
}),
|
|
150
|
+
terminal: true
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
write(data) {
|
|
154
|
+
const formattedData = stripAnsi(data).replace(import_node_os.EOL, "");
|
|
155
|
+
if (formattedData) {
|
|
156
|
+
this.history.push(formattedData);
|
|
157
|
+
}
|
|
158
|
+
return this.stdout.write(data);
|
|
159
|
+
}
|
|
160
|
+
clearLastLine() {
|
|
161
|
+
const lastLine = this.history.pop();
|
|
162
|
+
if (!lastLine) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const lastLineRows = Math.ceil(stripAnsi(lastLine).length / this.stdout.columns);
|
|
166
|
+
this.stdout.moveCursor(-this.stdout.columns, -lastLineRows);
|
|
167
|
+
this.stdout.clearScreenDown();
|
|
168
|
+
}
|
|
169
|
+
destroy() {
|
|
170
|
+
this.rl.close();
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
// src/constants.ts
|
|
175
|
+
var import_kleur = __toESM(require("kleur"), 1);
|
|
176
|
+
var kMainSymbols = {
|
|
177
|
+
tick: "\u2714",
|
|
178
|
+
cross: "\u2716",
|
|
179
|
+
pointer: "\u203A",
|
|
180
|
+
previous: "\u2B61",
|
|
181
|
+
next: "\u2B63",
|
|
182
|
+
active: "\u25CF",
|
|
183
|
+
inactive: "\u25CB"
|
|
184
|
+
};
|
|
185
|
+
var kFallbackSymbols = {
|
|
186
|
+
tick: "\u221A",
|
|
187
|
+
cross: "\xD7",
|
|
188
|
+
pointer: ">",
|
|
189
|
+
previous: "\u2191",
|
|
190
|
+
next: "\u2193",
|
|
191
|
+
active: "(+)",
|
|
192
|
+
inactive: "(-)"
|
|
193
|
+
};
|
|
194
|
+
var kSymbols = isUnicodeSupported() || process.env.CI ? kMainSymbols : kFallbackSymbols;
|
|
195
|
+
var kPointer = import_kleur.default.gray(kSymbols.pointer);
|
|
196
|
+
var SYMBOLS = {
|
|
197
|
+
QuestionMark: import_kleur.default.blue().bold("?"),
|
|
198
|
+
Tick: import_kleur.default.green().bold(kSymbols.tick),
|
|
199
|
+
Cross: import_kleur.default.red().bold(kSymbols.cross),
|
|
200
|
+
Pointer: kPointer,
|
|
201
|
+
Previous: kSymbols.previous,
|
|
202
|
+
Next: kSymbols.next,
|
|
203
|
+
ShowCursor: "\x1B[?25h",
|
|
204
|
+
HideCursor: "\x1B[?25l",
|
|
205
|
+
Active: import_kleur.default.cyan(kSymbols.active),
|
|
206
|
+
Inactive: import_kleur.default.gray(kSymbols.inactive)
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
// src/prompts/question.ts
|
|
210
|
+
var QuestionPrompt = class extends AbstractPrompt {
|
|
211
|
+
defaultValue;
|
|
212
|
+
tip;
|
|
213
|
+
questionSuffixError;
|
|
214
|
+
answer;
|
|
215
|
+
answerBuffer;
|
|
216
|
+
#validators;
|
|
217
|
+
#secure;
|
|
218
|
+
constructor(message, options = {}) {
|
|
219
|
+
const {
|
|
220
|
+
stdin = process.stdin,
|
|
221
|
+
stdout = process.stdout,
|
|
222
|
+
defaultValue,
|
|
223
|
+
validators = [],
|
|
224
|
+
secure = false
|
|
225
|
+
} = options;
|
|
226
|
+
super(message, stdin, stdout);
|
|
227
|
+
if (defaultValue && typeof defaultValue !== "string") {
|
|
228
|
+
throw new TypeError("defaultValue must be a string");
|
|
229
|
+
}
|
|
230
|
+
this.defaultValue = defaultValue;
|
|
231
|
+
this.tip = this.defaultValue ? ` (${this.defaultValue})` : "";
|
|
232
|
+
this.#validators = validators;
|
|
233
|
+
this.#secure = Boolean(secure);
|
|
234
|
+
this.questionSuffixError = "";
|
|
235
|
+
}
|
|
236
|
+
#question() {
|
|
237
|
+
return new Promise((resolve) => {
|
|
238
|
+
const questionQuery = this.#getQuestionQuery();
|
|
239
|
+
this.rl.question(questionQuery, (answer) => {
|
|
240
|
+
this.history.push(questionQuery + answer);
|
|
241
|
+
this.mute = false;
|
|
242
|
+
resolve(answer);
|
|
243
|
+
});
|
|
244
|
+
this.mute = this.#secure;
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
#getQuestionQuery() {
|
|
248
|
+
return `${import_kleur2.default.bold(`${SYMBOLS.QuestionMark} ${this.message}${this.tip}`)} ${this.questionSuffixError}`;
|
|
249
|
+
}
|
|
250
|
+
#setQuestionSuffixError(error) {
|
|
251
|
+
const suffix = import_kleur2.default.red(`[${error}] `);
|
|
252
|
+
this.questionSuffixError = suffix;
|
|
253
|
+
}
|
|
254
|
+
#writeAnswer() {
|
|
255
|
+
const prefix = this.answer ? SYMBOLS.Tick : SYMBOLS.Cross;
|
|
256
|
+
const answer = import_kleur2.default.yellow(this.#secure ? "CONFIDENTIAL" : this.answer ?? "");
|
|
257
|
+
this.write(`${prefix} ${import_kleur2.default.bold(this.message)} ${SYMBOLS.Pointer} ${answer}${import_node_os2.EOL}`);
|
|
258
|
+
}
|
|
259
|
+
#onQuestionAnswer() {
|
|
260
|
+
const questionLineCount = Math.ceil(
|
|
261
|
+
(0, import_wcwidth.default)(stripAnsi(this.#getQuestionQuery() + this.answer)) / this.stdout.columns
|
|
262
|
+
);
|
|
263
|
+
this.stdout.moveCursor(-this.stdout.columns, -questionLineCount);
|
|
264
|
+
this.stdout.clearScreenDown();
|
|
265
|
+
for (const validator of this.#validators) {
|
|
266
|
+
if (!validator.validate(this.answer)) {
|
|
267
|
+
const error = validator.error(this.answer);
|
|
268
|
+
this.#setQuestionSuffixError(error);
|
|
269
|
+
this.answerBuffer = this.#question();
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
this.answerBuffer = void 0;
|
|
274
|
+
this.#writeAnswer();
|
|
275
|
+
}
|
|
276
|
+
async question() {
|
|
277
|
+
this.answer = this.agent.nextAnswers.shift();
|
|
278
|
+
if (this.answer !== void 0) {
|
|
279
|
+
this.#writeAnswer();
|
|
280
|
+
this.destroy();
|
|
281
|
+
return this.answer;
|
|
282
|
+
}
|
|
283
|
+
this.answer = await this.#question();
|
|
284
|
+
if (this.answer === "" && this.defaultValue) {
|
|
285
|
+
this.answer = this.defaultValue;
|
|
286
|
+
}
|
|
287
|
+
this.#onQuestionAnswer();
|
|
288
|
+
while (this.answerBuffer !== void 0) {
|
|
289
|
+
this.answer = await this.answerBuffer;
|
|
290
|
+
this.#onQuestionAnswer();
|
|
291
|
+
}
|
|
292
|
+
this.destroy();
|
|
293
|
+
return this.answer;
|
|
294
|
+
}
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
// src/prompts/confirm.ts
|
|
298
|
+
var import_node_os3 = require("os");
|
|
299
|
+
var import_kleur3 = __toESM(require("kleur"), 1);
|
|
300
|
+
var import_wcwidth2 = __toESM(require("@topcli/wcwidth"), 1);
|
|
301
|
+
var kToggleKeys = /* @__PURE__ */ new Set([
|
|
302
|
+
"left",
|
|
303
|
+
"right",
|
|
304
|
+
"tab",
|
|
305
|
+
"q",
|
|
306
|
+
"a",
|
|
307
|
+
"d",
|
|
308
|
+
"h",
|
|
309
|
+
"j",
|
|
310
|
+
"k",
|
|
311
|
+
"l",
|
|
312
|
+
"space"
|
|
313
|
+
]);
|
|
314
|
+
var ConfirmPrompt = class extends AbstractPrompt {
|
|
315
|
+
initial;
|
|
316
|
+
selectedValue;
|
|
317
|
+
#boundKeyPressEvent;
|
|
318
|
+
#boundExitEvent;
|
|
319
|
+
constructor(message, options = {}) {
|
|
320
|
+
const {
|
|
321
|
+
stdin = process.stdin,
|
|
322
|
+
stdout = process.stdout,
|
|
323
|
+
initial = false
|
|
324
|
+
} = options;
|
|
325
|
+
super(message, stdin, stdout);
|
|
326
|
+
this.initial = initial;
|
|
327
|
+
this.selectedValue = initial;
|
|
328
|
+
}
|
|
329
|
+
#getHint() {
|
|
330
|
+
const Yes = import_kleur3.default.bold().underline().cyan("Yes");
|
|
331
|
+
const No = import_kleur3.default.bold().underline().cyan("No");
|
|
332
|
+
return this.selectedValue ? `${Yes}/No` : `Yes/${No}`;
|
|
333
|
+
}
|
|
334
|
+
#render() {
|
|
335
|
+
this.write(this.#getQuestionQuery());
|
|
336
|
+
}
|
|
337
|
+
#question() {
|
|
338
|
+
return new Promise((resolve) => {
|
|
339
|
+
const questionQuery = this.#getQuestionQuery();
|
|
340
|
+
this.write(questionQuery);
|
|
341
|
+
this.#boundKeyPressEvent = this.#onKeypress.bind(this, resolve);
|
|
342
|
+
this.stdin.on("keypress", this.#boundKeyPressEvent);
|
|
343
|
+
this.#boundExitEvent = this.#onProcessExit.bind(this);
|
|
344
|
+
process.once("exit", this.#boundExitEvent);
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
#onKeypress(resolve, value, key) {
|
|
348
|
+
this.stdout.moveCursor(
|
|
349
|
+
-this.stdout.columns,
|
|
350
|
+
-Math.floor((0, import_wcwidth2.default)(stripAnsi(this.#getQuestionQuery())) / this.stdout.columns)
|
|
351
|
+
);
|
|
352
|
+
this.stdout.clearScreenDown();
|
|
353
|
+
if (key.name === "return") {
|
|
354
|
+
resolve(this.selectedValue);
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
if (kToggleKeys.has(key.name ?? "")) {
|
|
358
|
+
this.selectedValue = !this.selectedValue;
|
|
359
|
+
}
|
|
360
|
+
this.#render();
|
|
361
|
+
}
|
|
362
|
+
#onProcessExit() {
|
|
363
|
+
this.stdin.off("keypress", this.#boundKeyPressEvent);
|
|
364
|
+
}
|
|
365
|
+
#getQuestionQuery() {
|
|
366
|
+
const query = import_kleur3.default.bold(`${SYMBOLS.QuestionMark} ${this.message}`);
|
|
367
|
+
return `${query} ${this.#getHint()}`;
|
|
368
|
+
}
|
|
369
|
+
#onQuestionAnswer() {
|
|
370
|
+
this.stdout.moveCursor(
|
|
371
|
+
-this.stdout.columns,
|
|
372
|
+
-(Math.floor((0, import_wcwidth2.default)(stripAnsi(this.#getQuestionQuery())) / this.stdout.columns) || 1)
|
|
373
|
+
);
|
|
374
|
+
this.stdout.clearScreenDown();
|
|
375
|
+
this.write(`${this.selectedValue ? SYMBOLS.Tick : SYMBOLS.Cross} ${import_kleur3.default.bold(this.message)}${import_node_os3.EOL}`);
|
|
376
|
+
}
|
|
377
|
+
async confirm() {
|
|
378
|
+
const answer = this.agent.nextAnswers.shift();
|
|
379
|
+
if (answer !== void 0) {
|
|
380
|
+
this.selectedValue = answer;
|
|
381
|
+
this.#onQuestionAnswer();
|
|
382
|
+
this.destroy();
|
|
383
|
+
return answer;
|
|
384
|
+
}
|
|
385
|
+
this.write(SYMBOLS.HideCursor);
|
|
386
|
+
try {
|
|
387
|
+
await this.#question();
|
|
388
|
+
this.#onQuestionAnswer();
|
|
389
|
+
return this.selectedValue;
|
|
390
|
+
} finally {
|
|
391
|
+
this.write(SYMBOLS.ShowCursor);
|
|
392
|
+
this.#onProcessExit();
|
|
393
|
+
process.off("exit", this.#boundExitEvent);
|
|
394
|
+
this.destroy();
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
// src/prompts/select.ts
|
|
400
|
+
var import_node_os4 = require("os");
|
|
401
|
+
var import_kleur4 = __toESM(require("kleur"), 1);
|
|
402
|
+
var import_wcwidth3 = __toESM(require("@topcli/wcwidth"), 1);
|
|
403
|
+
var SelectPrompt = class extends AbstractPrompt {
|
|
404
|
+
#boundExitEvent = () => void 0;
|
|
405
|
+
#boundKeyPressEvent = () => void 0;
|
|
406
|
+
activeIndex = 0;
|
|
407
|
+
selectedIndexes = [];
|
|
408
|
+
questionMessage;
|
|
409
|
+
longestChoicelength;
|
|
410
|
+
options;
|
|
411
|
+
lastRender;
|
|
412
|
+
get choices() {
|
|
413
|
+
return this.options.choices;
|
|
414
|
+
}
|
|
415
|
+
constructor(message, options) {
|
|
416
|
+
const {
|
|
417
|
+
stdin = process.stdin,
|
|
418
|
+
stdout = process.stdout,
|
|
419
|
+
choices
|
|
420
|
+
} = options ?? {};
|
|
421
|
+
super(message, stdin, stdout);
|
|
422
|
+
if (!options) {
|
|
423
|
+
this.destroy();
|
|
424
|
+
throw new TypeError("Missing required options");
|
|
425
|
+
}
|
|
426
|
+
this.options = options;
|
|
427
|
+
if (!choices?.length) {
|
|
428
|
+
this.destroy();
|
|
429
|
+
throw new TypeError("Missing required param: choices");
|
|
430
|
+
}
|
|
431
|
+
this.longestChoicelength = Math.max(...choices.map((choice) => {
|
|
432
|
+
if (typeof choice === "string") {
|
|
433
|
+
return choice.length;
|
|
434
|
+
}
|
|
435
|
+
const kRequiredChoiceProperties2 = ["label", "value"];
|
|
436
|
+
for (const prop of kRequiredChoiceProperties2) {
|
|
437
|
+
if (!choice[prop]) {
|
|
438
|
+
this.destroy();
|
|
439
|
+
throw new TypeError(`Missing ${prop} for choice ${JSON.stringify(choice)}`);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
return choice.label.length;
|
|
443
|
+
}));
|
|
444
|
+
}
|
|
445
|
+
#getFormattedChoice(choiceIndex) {
|
|
446
|
+
const choice = this.choices[choiceIndex];
|
|
447
|
+
if (typeof choice === "string") {
|
|
448
|
+
return { value: choice, label: choice };
|
|
449
|
+
}
|
|
450
|
+
return choice;
|
|
451
|
+
}
|
|
452
|
+
#getVisibleChoices() {
|
|
453
|
+
const maxVisible = this.options.maxVisible || 8;
|
|
454
|
+
let startIndex = Math.min(this.choices.length - maxVisible, this.activeIndex - Math.floor(maxVisible / 2));
|
|
455
|
+
if (startIndex < 0) {
|
|
456
|
+
startIndex = 0;
|
|
457
|
+
}
|
|
458
|
+
const endIndex = Math.min(startIndex + maxVisible, this.choices.length);
|
|
459
|
+
return { startIndex, endIndex };
|
|
460
|
+
}
|
|
461
|
+
#showChoices() {
|
|
462
|
+
const { startIndex, endIndex } = this.#getVisibleChoices();
|
|
463
|
+
this.lastRender = { startIndex, endIndex };
|
|
464
|
+
for (let choiceIndex = startIndex; choiceIndex < endIndex; choiceIndex++) {
|
|
465
|
+
const choice = this.#getFormattedChoice(choiceIndex);
|
|
466
|
+
const isChoiceSelected = choiceIndex === this.activeIndex;
|
|
467
|
+
const showPreviousChoicesArrow = startIndex > 0 && choiceIndex === startIndex;
|
|
468
|
+
const showNextChoicesArrow = endIndex < this.choices.length && choiceIndex === endIndex - 1;
|
|
469
|
+
let prefixArrow = " ";
|
|
470
|
+
if (showPreviousChoicesArrow) {
|
|
471
|
+
prefixArrow = SYMBOLS.Previous;
|
|
472
|
+
} else if (showNextChoicesArrow) {
|
|
473
|
+
prefixArrow = SYMBOLS.Next;
|
|
474
|
+
}
|
|
475
|
+
const prefix = `${prefixArrow}${isChoiceSelected ? `${SYMBOLS.Pointer} ` : " "}`;
|
|
476
|
+
const formattedLabel = choice.label.padEnd(
|
|
477
|
+
this.longestChoicelength < 10 ? this.longestChoicelength : 0
|
|
478
|
+
);
|
|
479
|
+
const formattedDescription = choice.description ? ` - ${choice.description}` : "";
|
|
480
|
+
const color = isChoiceSelected ? import_kleur4.default.white().bold : import_kleur4.default.gray;
|
|
481
|
+
const str = color(`${prefix}${formattedLabel}${formattedDescription}${import_node_os4.EOL}`);
|
|
482
|
+
this.write(str);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
#showAnsweredQuestion(choice) {
|
|
486
|
+
const prefix = `${SYMBOLS.Tick} ${import_kleur4.default.bold(this.message)} ${SYMBOLS.Pointer}`;
|
|
487
|
+
const formattedChoice = import_kleur4.default.yellow(typeof choice === "string" ? choice : choice.label);
|
|
488
|
+
this.write(`${prefix} ${formattedChoice}${import_node_os4.EOL}`);
|
|
489
|
+
}
|
|
490
|
+
#onProcessExit() {
|
|
491
|
+
this.stdin.off("keypress", this.#boundKeyPressEvent);
|
|
492
|
+
this.stdout.moveCursor(-this.stdout.columns, 0);
|
|
493
|
+
this.stdout.clearScreenDown();
|
|
494
|
+
this.write(SYMBOLS.ShowCursor);
|
|
495
|
+
}
|
|
496
|
+
#onKeypress(...args) {
|
|
497
|
+
const [resolve, render, , key] = args;
|
|
498
|
+
if (key.name === "up") {
|
|
499
|
+
this.activeIndex = this.activeIndex === 0 ? this.choices.length - 1 : this.activeIndex - 1;
|
|
500
|
+
render();
|
|
501
|
+
} else if (key.name === "down") {
|
|
502
|
+
this.activeIndex = this.activeIndex === this.choices.length - 1 ? 0 : this.activeIndex + 1;
|
|
503
|
+
render();
|
|
504
|
+
} else if (key.name === "return") {
|
|
505
|
+
render({ clearRender: true });
|
|
506
|
+
const currentChoice = this.choices[this.activeIndex];
|
|
507
|
+
const value = typeof currentChoice === "string" ? currentChoice : currentChoice.value;
|
|
508
|
+
if (!this.options.ignoreValues?.includes(value)) {
|
|
509
|
+
this.#showAnsweredQuestion(currentChoice);
|
|
510
|
+
}
|
|
511
|
+
this.write(SYMBOLS.ShowCursor);
|
|
512
|
+
this.destroy();
|
|
513
|
+
this.#onProcessExit();
|
|
514
|
+
process.off("exit", this.#boundExitEvent);
|
|
515
|
+
resolve(value);
|
|
516
|
+
} else {
|
|
517
|
+
render();
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
async select() {
|
|
521
|
+
const answer = this.agent.nextAnswers.shift();
|
|
522
|
+
if (answer !== void 0) {
|
|
523
|
+
const formatedAnser = Array.isArray(answer) ? answer.join(", ") : answer;
|
|
524
|
+
this.#showAnsweredQuestion(formatedAnser);
|
|
525
|
+
this.destroy();
|
|
526
|
+
return Array.isArray(answer) ? answer : [answer];
|
|
527
|
+
}
|
|
528
|
+
this.write(SYMBOLS.HideCursor);
|
|
529
|
+
this.#showQuestion();
|
|
530
|
+
const render = (options = {}) => {
|
|
531
|
+
const {
|
|
532
|
+
initialRender = false,
|
|
533
|
+
clearRender = false
|
|
534
|
+
} = options;
|
|
535
|
+
if (!initialRender) {
|
|
536
|
+
let linesToClear = this.lastRender.endIndex - this.lastRender.startIndex;
|
|
537
|
+
while (linesToClear > 0) {
|
|
538
|
+
this.clearLastLine();
|
|
539
|
+
linesToClear--;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
if (clearRender) {
|
|
543
|
+
const questionLineCount = Math.ceil(
|
|
544
|
+
(0, import_wcwidth3.default)(stripAnsi(this.questionMessage)) / this.stdout.columns
|
|
545
|
+
);
|
|
546
|
+
this.stdout.moveCursor(-this.stdout.columns, -(1 + questionLineCount));
|
|
547
|
+
this.stdout.clearScreenDown();
|
|
548
|
+
return;
|
|
549
|
+
}
|
|
550
|
+
this.#showChoices();
|
|
551
|
+
};
|
|
552
|
+
render({ initialRender: true });
|
|
553
|
+
return new Promise((resolve) => {
|
|
554
|
+
this.#boundKeyPressEvent = this.#onKeypress.bind(this, resolve, render);
|
|
555
|
+
this.stdin.on("keypress", this.#boundKeyPressEvent);
|
|
556
|
+
this.#boundExitEvent = this.#onProcessExit.bind(this);
|
|
557
|
+
process.once("exit", this.#boundExitEvent);
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
#showQuestion() {
|
|
561
|
+
this.questionMessage = `${SYMBOLS.QuestionMark} ${import_kleur4.default.bold(this.message)}`;
|
|
562
|
+
this.write(`${this.questionMessage}${import_node_os4.EOL}`);
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
|
|
566
|
+
// src/prompts/multiselect.ts
|
|
567
|
+
var import_node_os5 = require("os");
|
|
568
|
+
var import_kleur5 = __toESM(require("kleur"), 1);
|
|
569
|
+
var import_wcwidth4 = __toESM(require("@topcli/wcwidth"), 1);
|
|
570
|
+
var kRequiredChoiceProperties = ["label", "value"];
|
|
571
|
+
var MultiselectPrompt = class extends AbstractPrompt {
|
|
572
|
+
#boundExitEvent = () => void 0;
|
|
573
|
+
#boundKeyPressEvent = () => void 0;
|
|
574
|
+
#validators;
|
|
575
|
+
activeIndex = 0;
|
|
576
|
+
selectedIndexes = [];
|
|
577
|
+
questionMessage;
|
|
578
|
+
autocompleteValue = "";
|
|
579
|
+
options;
|
|
580
|
+
lastRender;
|
|
581
|
+
get choices() {
|
|
582
|
+
return this.options.choices;
|
|
583
|
+
}
|
|
584
|
+
get filteredChoices() {
|
|
585
|
+
if (!(this.options.autocomplete && this.autocompleteValue.length > 0)) {
|
|
586
|
+
return this.choices;
|
|
587
|
+
}
|
|
588
|
+
const isCaseSensitive = this.options.caseSensitive;
|
|
589
|
+
const autocompleteValue = isCaseSensitive ? this.autocompleteValue : this.autocompleteValue.toLowerCase();
|
|
590
|
+
return this.choices.filter((choice) => this.#filterChoice(choice, autocompleteValue, isCaseSensitive));
|
|
591
|
+
}
|
|
592
|
+
#filterChoice(choice, autocompleteValue, isCaseSensitive = false) {
|
|
593
|
+
const choiceValue = typeof choice === "string" ? isCaseSensitive ? choice : choice.toLowerCase() : isCaseSensitive ? choice.label : choice.label.toLowerCase();
|
|
594
|
+
if (autocompleteValue.includes(" ")) {
|
|
595
|
+
return this.#filterMultipleWords(choiceValue, autocompleteValue, isCaseSensitive);
|
|
596
|
+
}
|
|
597
|
+
return choiceValue.includes(autocompleteValue);
|
|
598
|
+
}
|
|
599
|
+
#filterMultipleWords(choiceValue, autocompleteValue, isCaseSensitive) {
|
|
600
|
+
return autocompleteValue.split(" ").every((word) => {
|
|
601
|
+
const wordValue = isCaseSensitive ? word : word.toLowerCase();
|
|
602
|
+
return choiceValue.includes(wordValue) || choiceValue.includes(autocompleteValue);
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
get longestChoice() {
|
|
606
|
+
return Math.max(...this.filteredChoices.map((choice) => {
|
|
607
|
+
if (typeof choice === "string") {
|
|
608
|
+
return choice.length;
|
|
609
|
+
}
|
|
610
|
+
return choice.label.length;
|
|
611
|
+
}));
|
|
612
|
+
}
|
|
613
|
+
constructor(message, options) {
|
|
614
|
+
const {
|
|
615
|
+
stdin = process.stdin,
|
|
616
|
+
stdout = process.stdout,
|
|
617
|
+
choices,
|
|
618
|
+
preSelectedChoices,
|
|
619
|
+
validators = []
|
|
620
|
+
} = options ?? {};
|
|
621
|
+
super(message, stdin, stdout);
|
|
622
|
+
if (!options) {
|
|
623
|
+
this.destroy();
|
|
624
|
+
throw new TypeError("Missing required options");
|
|
625
|
+
}
|
|
626
|
+
this.options = options;
|
|
627
|
+
if (!choices?.length) {
|
|
628
|
+
this.destroy();
|
|
629
|
+
throw new TypeError("Missing required param: choices");
|
|
630
|
+
}
|
|
631
|
+
this.#validators = validators;
|
|
632
|
+
for (const choice of choices) {
|
|
633
|
+
if (typeof choice === "string") {
|
|
634
|
+
continue;
|
|
635
|
+
}
|
|
636
|
+
for (const prop of kRequiredChoiceProperties) {
|
|
637
|
+
if (!choice[prop]) {
|
|
638
|
+
this.destroy();
|
|
639
|
+
throw new TypeError(`Missing ${prop} for choice ${JSON.stringify(choice)}`);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
if (!preSelectedChoices) {
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
for (const choice of preSelectedChoices) {
|
|
647
|
+
const choiceIndex = this.filteredChoices.findIndex((item) => {
|
|
648
|
+
if (typeof item === "string") {
|
|
649
|
+
return item === choice;
|
|
650
|
+
}
|
|
651
|
+
return item.value === choice;
|
|
652
|
+
});
|
|
653
|
+
if (choiceIndex === -1) {
|
|
654
|
+
this.destroy();
|
|
655
|
+
throw new Error(`Invalid pre-selected choice: ${typeof choice === "string" ? choice : choice.value}`);
|
|
656
|
+
}
|
|
657
|
+
this.selectedIndexes.push(choiceIndex);
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
#getFormattedChoice(choiceIndex) {
|
|
661
|
+
const choice = this.filteredChoices[choiceIndex];
|
|
662
|
+
if (typeof choice === "string") {
|
|
663
|
+
return { value: choice, label: choice };
|
|
664
|
+
}
|
|
665
|
+
return choice;
|
|
666
|
+
}
|
|
667
|
+
#getVisibleChoices() {
|
|
668
|
+
const maxVisible = this.options.maxVisible || 8;
|
|
669
|
+
let startIndex = Math.min(this.filteredChoices.length - maxVisible, this.activeIndex - Math.floor(maxVisible / 2));
|
|
670
|
+
if (startIndex < 0) {
|
|
671
|
+
startIndex = 0;
|
|
672
|
+
}
|
|
673
|
+
const endIndex = Math.min(startIndex + maxVisible, this.filteredChoices.length);
|
|
674
|
+
return { startIndex, endIndex };
|
|
675
|
+
}
|
|
676
|
+
#showChoices() {
|
|
677
|
+
const { startIndex, endIndex } = this.#getVisibleChoices();
|
|
678
|
+
this.lastRender = { startIndex, endIndex };
|
|
679
|
+
if (this.options.autocomplete) {
|
|
680
|
+
this.write(`${SYMBOLS.Pointer} ${this.autocompleteValue}${import_node_os5.EOL}`);
|
|
681
|
+
}
|
|
682
|
+
for (let choiceIndex = startIndex; choiceIndex < endIndex; choiceIndex++) {
|
|
683
|
+
const choice = this.#getFormattedChoice(choiceIndex);
|
|
684
|
+
const isChoiceActive = choiceIndex === this.activeIndex;
|
|
685
|
+
const isChoiceSelected = this.selectedIndexes.includes(choiceIndex);
|
|
686
|
+
const showPreviousChoicesArrow = startIndex > 0 && choiceIndex === startIndex;
|
|
687
|
+
const showNextChoicesArrow = endIndex < this.filteredChoices.length && choiceIndex === endIndex - 1;
|
|
688
|
+
let prefixArrow = " ";
|
|
689
|
+
if (showPreviousChoicesArrow) {
|
|
690
|
+
prefixArrow = SYMBOLS.Previous + " ";
|
|
691
|
+
} else if (showNextChoicesArrow) {
|
|
692
|
+
prefixArrow = SYMBOLS.Next + " ";
|
|
693
|
+
}
|
|
694
|
+
const prefix = `${prefixArrow}${isChoiceSelected ? SYMBOLS.Active : SYMBOLS.Inactive}`;
|
|
695
|
+
const formattedLabel = choice.label.padEnd(
|
|
696
|
+
this.longestChoice < 10 ? this.longestChoice : 0
|
|
697
|
+
);
|
|
698
|
+
const formattedDescription = choice.description ? ` - ${choice.description}` : "";
|
|
699
|
+
const color = isChoiceActive ? import_kleur5.default.white().bold : import_kleur5.default.gray;
|
|
700
|
+
const str = `${prefix} ${color(`${formattedLabel}${formattedDescription}`)}${import_node_os5.EOL}`;
|
|
701
|
+
this.write(str);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
#showAnsweredQuestion(choices, isAgentAnswer = false) {
|
|
705
|
+
const prefixSymbol = this.selectedIndexes.length === 0 && !isAgentAnswer ? SYMBOLS.Cross : SYMBOLS.Tick;
|
|
706
|
+
const prefix = `${prefixSymbol} ${import_kleur5.default.bold(this.message)} ${SYMBOLS.Pointer}`;
|
|
707
|
+
const formattedChoice = import_kleur5.default.yellow(choices);
|
|
708
|
+
this.write(`${prefix}${choices ? ` ${formattedChoice}` : ""}${import_node_os5.EOL}`);
|
|
709
|
+
}
|
|
710
|
+
#onProcessExit() {
|
|
711
|
+
this.stdin.off("keypress", this.#boundKeyPressEvent);
|
|
712
|
+
this.stdout.moveCursor(-this.stdout.columns, 0);
|
|
713
|
+
this.stdout.clearScreenDown();
|
|
714
|
+
this.write(SYMBOLS.ShowCursor);
|
|
715
|
+
}
|
|
716
|
+
#onKeypress(...args) {
|
|
717
|
+
const [resolve, render, , key] = args;
|
|
718
|
+
if (key.name === "up") {
|
|
719
|
+
this.activeIndex = this.activeIndex === 0 ? this.filteredChoices.length - 1 : this.activeIndex - 1;
|
|
720
|
+
render();
|
|
721
|
+
} else if (key.name === "down") {
|
|
722
|
+
this.activeIndex = this.activeIndex === this.filteredChoices.length - 1 ? 0 : this.activeIndex + 1;
|
|
723
|
+
render();
|
|
724
|
+
} else if (key.ctrl && key.name === "a") {
|
|
725
|
+
this.selectedIndexes = this.selectedIndexes.length === this.filteredChoices.length ? [] : this.filteredChoices.map((_, index) => index);
|
|
726
|
+
render();
|
|
727
|
+
} else if (key.name === "right") {
|
|
728
|
+
this.selectedIndexes.push(this.activeIndex);
|
|
729
|
+
render();
|
|
730
|
+
} else if (key.name === "left") {
|
|
731
|
+
this.selectedIndexes = this.selectedIndexes.filter((index) => index !== this.activeIndex);
|
|
732
|
+
render();
|
|
733
|
+
} else if (key.name === "return") {
|
|
734
|
+
const labels = this.selectedIndexes.map((index) => {
|
|
735
|
+
const choice = this.filteredChoices[index];
|
|
736
|
+
return typeof choice === "string" ? choice : choice.label;
|
|
737
|
+
});
|
|
738
|
+
const values = this.selectedIndexes.map((index) => {
|
|
739
|
+
const choice = this.filteredChoices[index];
|
|
740
|
+
return typeof choice === "string" ? choice : choice.value;
|
|
741
|
+
});
|
|
742
|
+
for (const validator of this.#validators) {
|
|
743
|
+
if (!validator.validate(values)) {
|
|
744
|
+
const error = validator.error(values);
|
|
745
|
+
render({ error });
|
|
746
|
+
return;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
render({ clearRender: true });
|
|
750
|
+
this.#showAnsweredQuestion(labels.join(", "));
|
|
751
|
+
this.write(SYMBOLS.ShowCursor);
|
|
752
|
+
this.destroy();
|
|
753
|
+
this.#onProcessExit();
|
|
754
|
+
process.off("exit", this.#boundExitEvent);
|
|
755
|
+
resolve(values);
|
|
756
|
+
} else {
|
|
757
|
+
if (!key.ctrl && this.options.autocomplete) {
|
|
758
|
+
this.selectedIndexes = [];
|
|
759
|
+
this.activeIndex = 0;
|
|
760
|
+
if (key.name === "backspace" && this.autocompleteValue.length > 0) {
|
|
761
|
+
this.autocompleteValue = this.autocompleteValue.slice(0, -1);
|
|
762
|
+
} else if (key.name !== "backspace") {
|
|
763
|
+
this.autocompleteValue += key.sequence;
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
render();
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
async multiselect() {
|
|
770
|
+
const answer = this.agent.nextAnswers.shift();
|
|
771
|
+
if (answer !== void 0) {
|
|
772
|
+
const formatedAnser = Array.isArray(answer) ? answer.join(", ") : answer;
|
|
773
|
+
this.#showAnsweredQuestion(formatedAnser, true);
|
|
774
|
+
this.destroy();
|
|
775
|
+
return Array.isArray(answer) ? answer : [answer];
|
|
776
|
+
}
|
|
777
|
+
this.write(SYMBOLS.HideCursor);
|
|
778
|
+
this.#showQuestion();
|
|
779
|
+
const render = (options = {}) => {
|
|
780
|
+
const {
|
|
781
|
+
initialRender = false,
|
|
782
|
+
clearRender = false,
|
|
783
|
+
error = null
|
|
784
|
+
} = options;
|
|
785
|
+
if (!initialRender) {
|
|
786
|
+
let linesToClear = this.lastRender.endIndex - this.lastRender.startIndex;
|
|
787
|
+
while (linesToClear > 0) {
|
|
788
|
+
this.clearLastLine();
|
|
789
|
+
linesToClear--;
|
|
790
|
+
}
|
|
791
|
+
if (this.options.autocomplete) {
|
|
792
|
+
let linesToClear2 = Math.ceil(
|
|
793
|
+
(0, import_wcwidth4.default)(`${SYMBOLS.Pointer} ${this.autocompleteValue}`) / this.stdout.columns
|
|
794
|
+
);
|
|
795
|
+
while (linesToClear2 > 0) {
|
|
796
|
+
this.clearLastLine();
|
|
797
|
+
linesToClear2--;
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
if (clearRender) {
|
|
802
|
+
const questionLineCount = Math.ceil(
|
|
803
|
+
(0, import_wcwidth4.default)(stripAnsi(this.questionMessage)) / this.stdout.columns
|
|
804
|
+
);
|
|
805
|
+
this.stdout.moveCursor(-this.stdout.columns, -(1 + questionLineCount));
|
|
806
|
+
this.stdout.clearScreenDown();
|
|
807
|
+
return;
|
|
808
|
+
}
|
|
809
|
+
if (error) {
|
|
810
|
+
const linesToClear = Math.ceil((0, import_wcwidth4.default)(this.questionMessage) / this.stdout.columns) + 1;
|
|
811
|
+
this.stdout.moveCursor(0, -linesToClear);
|
|
812
|
+
this.stdout.clearScreenDown();
|
|
813
|
+
this.#showQuestion(error);
|
|
814
|
+
}
|
|
815
|
+
this.#showChoices();
|
|
816
|
+
};
|
|
817
|
+
render({ initialRender: true });
|
|
818
|
+
return new Promise((resolve) => {
|
|
819
|
+
this.#boundKeyPressEvent = this.#onKeypress.bind(this, resolve, render);
|
|
820
|
+
this.stdin.on("keypress", this.#boundKeyPressEvent);
|
|
821
|
+
this.#boundExitEvent = this.#onProcessExit.bind(this);
|
|
822
|
+
process.once("exit", this.#boundExitEvent);
|
|
823
|
+
});
|
|
824
|
+
}
|
|
825
|
+
#showQuestion(error = null) {
|
|
826
|
+
let hint = import_kleur5.default.gray(
|
|
827
|
+
// eslint-disable-next-line max-len
|
|
828
|
+
`(Press ${import_kleur5.default.bold("<Ctrl+A>")} to toggle all, ${import_kleur5.default.bold("<Ctrl+Space>")} to select, ${import_kleur5.default.bold("<Left/Right>")} to toggle, ${import_kleur5.default.bold("<Return>")} to submit)`
|
|
829
|
+
);
|
|
830
|
+
if (error) {
|
|
831
|
+
hint += ` ${import_kleur5.default.red().bold(`[${error}]`)}`;
|
|
832
|
+
}
|
|
833
|
+
this.questionMessage = `${SYMBOLS.QuestionMark} ${import_kleur5.default.bold(this.message)} ${hint}`;
|
|
834
|
+
this.write(`${this.questionMessage}${import_node_os5.EOL}`);
|
|
835
|
+
}
|
|
836
|
+
};
|
|
837
|
+
|
|
838
|
+
// src/validators.ts
|
|
839
|
+
function required() {
|
|
840
|
+
return {
|
|
841
|
+
validate: (input) => Array.isArray(input) ? input.length > 0 : Boolean(input),
|
|
842
|
+
error: () => "required"
|
|
843
|
+
};
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
// index.ts
|
|
847
|
+
async function question(message, options = {}) {
|
|
848
|
+
const questionPrompt = new QuestionPrompt(message, options);
|
|
849
|
+
return questionPrompt.question();
|
|
850
|
+
}
|
|
851
|
+
async function select(message, options) {
|
|
852
|
+
const selectPrompt = new SelectPrompt(message, options);
|
|
853
|
+
return selectPrompt.select();
|
|
854
|
+
}
|
|
855
|
+
async function confirm(message, options) {
|
|
856
|
+
const confirmPrompt = new ConfirmPrompt(message, options);
|
|
857
|
+
return confirmPrompt.confirm();
|
|
858
|
+
}
|
|
859
|
+
async function multiselect(message, options) {
|
|
860
|
+
const multiselectPrompt = new MultiselectPrompt(message, options);
|
|
861
|
+
return multiselectPrompt.multiselect();
|
|
862
|
+
}
|
|
863
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
864
|
+
0 && (module.exports = {
|
|
865
|
+
PromptAgent,
|
|
866
|
+
confirm,
|
|
867
|
+
multiselect,
|
|
868
|
+
question,
|
|
869
|
+
required,
|
|
870
|
+
select
|
|
871
|
+
});
|