@topcli/prompts 1.4.0 → 1.5.1
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/README.md +2 -0
- package/index.d.ts +1 -0
- package/package.json +7 -5
- package/src/abstract-prompt.js +14 -1
- package/src/confirm-prompt.js +11 -2
- package/src/constants.js +2 -1
- package/src/multiselect-prompt.js +79 -54
- package/src/question-prompt.js +15 -4
- package/src/select-prompt.js +55 -30
package/README.md
CHANGED
|
@@ -51,6 +51,7 @@ question(message: string, options?: PromptOptions): Promise<string>
|
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
Simple prompt, similar to `rl.question()` with an improved UI.
|
|
54
|
+
Use `options.secure` if you need to hide both input and answer.
|
|
54
55
|
Use `options.validators` to handle user input.
|
|
55
56
|
|
|
56
57
|
**Example**
|
|
@@ -156,6 +157,7 @@ export interface Validator {
|
|
|
156
157
|
export interface QuestionOptions extends SharedOptions {
|
|
157
158
|
defaultValue?: string;
|
|
158
159
|
validators?: Validator[];
|
|
160
|
+
secure?: boolean;
|
|
159
161
|
}
|
|
160
162
|
|
|
161
163
|
export interface Choice {
|
package/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@topcli/prompts",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "Node.js user input library for command-line interfaces.",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --no-warnings=ExperimentalWarning --loader=esmock --test test/",
|
|
@@ -24,13 +24,15 @@
|
|
|
24
24
|
"type": "module",
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@nodesecure/eslint-config": "^1.8.0",
|
|
27
|
-
"@types/node": "^20.8.
|
|
27
|
+
"@types/node": "^20.8.5",
|
|
28
28
|
"c8": "^8.0.1",
|
|
29
|
-
"eslint": "^8.
|
|
30
|
-
"esmock": "^2.5.
|
|
29
|
+
"eslint": "^8.51.0",
|
|
30
|
+
"esmock": "^2.5.2"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"
|
|
33
|
+
"@topcli/wcwidth": "^1.0.1",
|
|
34
|
+
"is-ci": "^3.0.1",
|
|
35
|
+
"is-unicode-supported": "^2.0.0",
|
|
34
36
|
"kleur": "^4.1.5",
|
|
35
37
|
"strip-ansi": "^7.1.0"
|
|
36
38
|
},
|
package/src/abstract-prompt.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Import Node.js Dependencies
|
|
2
2
|
import { EOL } from "node:os";
|
|
3
3
|
import { createInterface } from "node:readline";
|
|
4
|
+
import { Writable } from "node:stream";
|
|
4
5
|
|
|
5
6
|
// Import Third-party Dependencies
|
|
6
7
|
import stripAnsi from "strip-ansi";
|
|
@@ -23,11 +24,23 @@ export class AbstractPrompt {
|
|
|
23
24
|
this.message = message;
|
|
24
25
|
this.history = [];
|
|
25
26
|
this.agent = PromptAgent.agent();
|
|
27
|
+
this.mute = false;
|
|
26
28
|
|
|
27
29
|
if (this.stdout.isTTY) {
|
|
28
30
|
this.stdin.setRawMode(true);
|
|
29
31
|
}
|
|
30
|
-
this.rl = createInterface({
|
|
32
|
+
this.rl = createInterface({
|
|
33
|
+
input,
|
|
34
|
+
output: new Writable({
|
|
35
|
+
write: (chunk, encoding, callback) => {
|
|
36
|
+
if (!this.mute) {
|
|
37
|
+
this.stdout.write(chunk, encoding);
|
|
38
|
+
}
|
|
39
|
+
callback();
|
|
40
|
+
}
|
|
41
|
+
}),
|
|
42
|
+
terminal: true
|
|
43
|
+
});
|
|
31
44
|
}
|
|
32
45
|
|
|
33
46
|
write(data) {
|
package/src/confirm-prompt.js
CHANGED
|
@@ -3,6 +3,8 @@ import { EOL } from "node:os";
|
|
|
3
3
|
|
|
4
4
|
// Import Third-party Dependencies
|
|
5
5
|
import kleur from "kleur";
|
|
6
|
+
import stripAnsi from "strip-ansi";
|
|
7
|
+
import wcwidth from "@topcli/wcwidth";
|
|
6
8
|
|
|
7
9
|
// Import Internal Dependencies
|
|
8
10
|
import { AbstractPrompt } from "./abstract-prompt.js";
|
|
@@ -65,7 +67,10 @@ export class ConfirmPrompt extends AbstractPrompt {
|
|
|
65
67
|
}
|
|
66
68
|
|
|
67
69
|
#onKeypress(resolve, value, key) {
|
|
68
|
-
this.stdout.moveCursor(
|
|
70
|
+
this.stdout.moveCursor(
|
|
71
|
+
-this.stdout.columns,
|
|
72
|
+
-Math.floor(wcwidth(stripAnsi(this.#getQuestionQuery())) / this.stdout.columns)
|
|
73
|
+
);
|
|
69
74
|
this.stdout.clearScreenDown();
|
|
70
75
|
|
|
71
76
|
if (key.name === "return") {
|
|
@@ -92,7 +97,11 @@ export class ConfirmPrompt extends AbstractPrompt {
|
|
|
92
97
|
}
|
|
93
98
|
|
|
94
99
|
#onQuestionAnswer() {
|
|
95
|
-
this.
|
|
100
|
+
this.stdout.moveCursor(
|
|
101
|
+
-this.stdout.columns,
|
|
102
|
+
-(Math.floor(wcwidth(stripAnsi(this.#getQuestionQuery())) / this.stdout.columns) || 1)
|
|
103
|
+
);
|
|
104
|
+
this.stdout.clearScreenDown();
|
|
96
105
|
this.write(`${this.selectedValue ? SYMBOLS.Tick : SYMBOLS.Cross} ${kleur.bold(this.message)}${EOL}`);
|
|
97
106
|
}
|
|
98
107
|
|
package/src/constants.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Import Third-party Dependencies
|
|
2
2
|
import kleur from "kleur";
|
|
3
3
|
import isUnicodeSupported from "is-unicode-supported";
|
|
4
|
+
import isCI from "is-ci";
|
|
4
5
|
|
|
5
6
|
const kMainSymbols = {
|
|
6
7
|
tick: "✔",
|
|
@@ -20,7 +21,7 @@ const kFallbackSymbols = {
|
|
|
20
21
|
active: "(+)",
|
|
21
22
|
inactive: "(-)"
|
|
22
23
|
};
|
|
23
|
-
const kSymbols = isUnicodeSupported() ? kMainSymbols : kFallbackSymbols;
|
|
24
|
+
const kSymbols = isUnicodeSupported() || isCI ? kMainSymbols : kFallbackSymbols;
|
|
24
25
|
const kPointer = kleur.gray(kSymbols.pointer);
|
|
25
26
|
|
|
26
27
|
export const SYMBOLS = {
|
|
@@ -3,16 +3,21 @@ import { EOL } from "node:os";
|
|
|
3
3
|
|
|
4
4
|
// Import Third-party Dependencies
|
|
5
5
|
import kleur from "kleur";
|
|
6
|
+
import stripAnsi from "strip-ansi";
|
|
7
|
+
import wcwidth from "@topcli/wcwidth";
|
|
6
8
|
|
|
7
9
|
// Import Internal Dependencies
|
|
8
10
|
import { AbstractPrompt } from "./abstract-prompt.js";
|
|
9
11
|
import { SYMBOLS } from "./constants.js";
|
|
10
12
|
|
|
11
13
|
export class MultiselectPrompt extends AbstractPrompt {
|
|
14
|
+
#boundExitEvent = () => void 0;
|
|
15
|
+
#boundKeyPressEvent = () => void 0;
|
|
12
16
|
#validators;
|
|
13
17
|
|
|
14
18
|
activeIndex = 0;
|
|
15
19
|
selectedIndexes = [];
|
|
20
|
+
questionMessage;
|
|
16
21
|
|
|
17
22
|
get choices() {
|
|
18
23
|
return this.options.choices;
|
|
@@ -142,6 +147,70 @@ export class MultiselectPrompt extends AbstractPrompt {
|
|
|
142
147
|
this.write(`${prefix}${choices ? ` ${formattedChoice}` : ""}${EOL}`);
|
|
143
148
|
}
|
|
144
149
|
|
|
150
|
+
#onProcessExit() {
|
|
151
|
+
this.stdin.off("keypress", this.#boundKeyPressEvent);
|
|
152
|
+
this.stdout.moveCursor(-this.stdout.columns, 0);
|
|
153
|
+
this.stdout.clearScreenDown();
|
|
154
|
+
this.write(SYMBOLS.ShowCursor);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
#onKeypress(...args) {
|
|
158
|
+
const [resolve, render, _, key] = args;
|
|
159
|
+
|
|
160
|
+
if (key.name === "up") {
|
|
161
|
+
this.activeIndex = this.activeIndex === 0 ? this.choices.length - 1 : this.activeIndex - 1;
|
|
162
|
+
render();
|
|
163
|
+
}
|
|
164
|
+
else if (key.name === "down") {
|
|
165
|
+
this.activeIndex = this.activeIndex === this.choices.length - 1 ? 0 : this.activeIndex + 1;
|
|
166
|
+
render();
|
|
167
|
+
}
|
|
168
|
+
else if (key.name === "a") {
|
|
169
|
+
this.selectedIndexes = this.selectedIndexes.length === this.choices.length ? [] : this.choices.map((_, index) => index);
|
|
170
|
+
render();
|
|
171
|
+
}
|
|
172
|
+
else if (key.name === "space") {
|
|
173
|
+
const isChoiceSelected = this.selectedIndexes.includes(this.activeIndex);
|
|
174
|
+
|
|
175
|
+
if (isChoiceSelected) {
|
|
176
|
+
this.selectedIndexes = this.selectedIndexes.filter((index) => index !== this.activeIndex);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
this.selectedIndexes.push(this.activeIndex);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
render();
|
|
183
|
+
}
|
|
184
|
+
else if (key.name === "return") {
|
|
185
|
+
const labels = this.selectedIndexes.map((index) => this.choices[index].label ?? this.choices[index]);
|
|
186
|
+
const values = this.selectedIndexes.map((index) => this.choices[index].value ?? this.choices[index]);
|
|
187
|
+
|
|
188
|
+
for (const validator of this.#validators) {
|
|
189
|
+
if (!validator.validate(values)) {
|
|
190
|
+
const error = validator.error(values);
|
|
191
|
+
render({ error });
|
|
192
|
+
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
render({ clearRender: true });
|
|
198
|
+
|
|
199
|
+
this.#showAnsweredQuestion(labels.join(", "));
|
|
200
|
+
|
|
201
|
+
this.write(SYMBOLS.ShowCursor);
|
|
202
|
+
this.destroy();
|
|
203
|
+
|
|
204
|
+
this.#onProcessExit();
|
|
205
|
+
process.off("exit", this.#boundExitEvent);
|
|
206
|
+
|
|
207
|
+
resolve(values);
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
render();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
145
214
|
async multiselect() {
|
|
146
215
|
if (this.agent.nextAnswers.length > 0) {
|
|
147
216
|
const answer = this.agent.nextAnswers.shift();
|
|
@@ -170,7 +239,10 @@ export class MultiselectPrompt extends AbstractPrompt {
|
|
|
170
239
|
}
|
|
171
240
|
|
|
172
241
|
if (clearRender) {
|
|
173
|
-
|
|
242
|
+
const questionLineCount = Math.ceil(
|
|
243
|
+
wcwidth(stripAnsi(this.questionMessage)) / this.stdout.columns
|
|
244
|
+
);
|
|
245
|
+
this.stdout.moveCursor(-this.stdout.columns, -(1 + questionLineCount));
|
|
174
246
|
this.stdout.clearScreenDown();
|
|
175
247
|
|
|
176
248
|
return;
|
|
@@ -188,59 +260,11 @@ export class MultiselectPrompt extends AbstractPrompt {
|
|
|
188
260
|
render({ initialRender: true });
|
|
189
261
|
|
|
190
262
|
return new Promise((resolve) => {
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
this.activeIndex = this.activeIndex === 0 ? this.choices.length - 1 : this.activeIndex - 1;
|
|
194
|
-
render();
|
|
195
|
-
}
|
|
196
|
-
else if (key.name === "down") {
|
|
197
|
-
this.activeIndex = this.activeIndex === this.choices.length - 1 ? 0 : this.activeIndex + 1;
|
|
198
|
-
render();
|
|
199
|
-
}
|
|
200
|
-
else if (key.name === "a") {
|
|
201
|
-
this.selectedIndexes = this.selectedIndexes.length === this.choices.length ? [] : this.choices.map((_, index) => index);
|
|
202
|
-
render();
|
|
203
|
-
}
|
|
204
|
-
else if (key.name === "space") {
|
|
205
|
-
const isChoiceSelected = this.selectedIndexes.includes(this.activeIndex);
|
|
206
|
-
|
|
207
|
-
if (isChoiceSelected) {
|
|
208
|
-
this.selectedIndexes = this.selectedIndexes.filter((index) => index !== this.activeIndex);
|
|
209
|
-
}
|
|
210
|
-
else {
|
|
211
|
-
this.selectedIndexes.push(this.activeIndex);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
render();
|
|
215
|
-
}
|
|
216
|
-
else if (key.name === "return") {
|
|
217
|
-
const labels = this.selectedIndexes.map((index) => this.choices[index].label ?? this.choices[index]);
|
|
218
|
-
const values = this.selectedIndexes.map((index) => this.choices[index].value ?? this.choices[index]);
|
|
219
|
-
|
|
220
|
-
for (const validator of this.#validators) {
|
|
221
|
-
if (!validator.validate(values)) {
|
|
222
|
-
const error = validator.error(values);
|
|
223
|
-
render({ error });
|
|
224
|
-
|
|
225
|
-
return;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
this.stdin.off("keypress", onKeypress);
|
|
230
|
-
|
|
231
|
-
render({ clearRender: true });
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
this.#showAnsweredQuestion(labels.join(", "));
|
|
235
|
-
|
|
236
|
-
this.write(SYMBOLS.ShowCursor);
|
|
237
|
-
this.destroy();
|
|
238
|
-
|
|
239
|
-
resolve(values);
|
|
240
|
-
}
|
|
241
|
-
};
|
|
263
|
+
this.#boundKeyPressEvent = this.#onKeypress.bind(this, resolve, render);
|
|
264
|
+
this.stdin.on("keypress", this.#boundKeyPressEvent);
|
|
242
265
|
|
|
243
|
-
this.
|
|
266
|
+
this.#boundExitEvent = this.#onProcessExit.bind(this);
|
|
267
|
+
process.once("exit", this.#boundExitEvent);
|
|
244
268
|
});
|
|
245
269
|
}
|
|
246
270
|
|
|
@@ -251,7 +275,8 @@ export class MultiselectPrompt extends AbstractPrompt {
|
|
|
251
275
|
if (error) {
|
|
252
276
|
hint += ` ${kleur.red().bold(`[${error}]`)}`;
|
|
253
277
|
}
|
|
278
|
+
this.questionMessage = `${SYMBOLS.QuestionMark} ${kleur.bold(this.message)} ${hint}`;
|
|
254
279
|
|
|
255
|
-
this.write(`${
|
|
280
|
+
this.write(`${this.questionMessage}${EOL}`);
|
|
256
281
|
}
|
|
257
282
|
}
|
package/src/question-prompt.js
CHANGED
|
@@ -3,6 +3,8 @@ import { EOL } from "node:os";
|
|
|
3
3
|
|
|
4
4
|
// Import Third-party Dependencies
|
|
5
5
|
import kleur from "kleur";
|
|
6
|
+
import stripAnsi from "strip-ansi";
|
|
7
|
+
import wcwidth from "@topcli/wcwidth";
|
|
6
8
|
|
|
7
9
|
// Import Internal Dependencies
|
|
8
10
|
import { AbstractPrompt } from "./abstract-prompt.js";
|
|
@@ -10,13 +12,15 @@ import { SYMBOLS } from "./constants.js";
|
|
|
10
12
|
|
|
11
13
|
export class QuestionPrompt extends AbstractPrompt {
|
|
12
14
|
#validators;
|
|
15
|
+
#secure;
|
|
13
16
|
|
|
14
17
|
constructor(message, options = {}) {
|
|
15
18
|
const {
|
|
16
19
|
stdin = process.stdin,
|
|
17
20
|
stdout = process.stdout,
|
|
18
21
|
defaultValue,
|
|
19
|
-
validators = []
|
|
22
|
+
validators = [],
|
|
23
|
+
secure = false
|
|
20
24
|
} = options;
|
|
21
25
|
|
|
22
26
|
super(message, stdin, stdout);
|
|
@@ -28,6 +32,7 @@ export class QuestionPrompt extends AbstractPrompt {
|
|
|
28
32
|
this.defaultValue = defaultValue;
|
|
29
33
|
this.tip = this.defaultValue ? ` (${this.defaultValue})` : "";
|
|
30
34
|
this.#validators = validators;
|
|
35
|
+
this.#secure = Boolean(secure);
|
|
31
36
|
this.questionSuffixError = "";
|
|
32
37
|
}
|
|
33
38
|
|
|
@@ -37,9 +42,11 @@ export class QuestionPrompt extends AbstractPrompt {
|
|
|
37
42
|
|
|
38
43
|
this.rl.question(questionQuery, (answer) => {
|
|
39
44
|
this.history.push(questionQuery + answer);
|
|
45
|
+
this.mute = false;
|
|
40
46
|
|
|
41
47
|
resolve(answer);
|
|
42
48
|
});
|
|
49
|
+
this.mute = this.#secure;
|
|
43
50
|
});
|
|
44
51
|
}
|
|
45
52
|
|
|
@@ -54,13 +61,17 @@ export class QuestionPrompt extends AbstractPrompt {
|
|
|
54
61
|
|
|
55
62
|
#writeAnswer() {
|
|
56
63
|
const prefix = this.answer ? SYMBOLS.Tick : SYMBOLS.Cross;
|
|
57
|
-
const answer = kleur.yellow(this.answer ?? "");
|
|
58
|
-
|
|
64
|
+
const answer = kleur.yellow(this.#secure ? "CONFIDENTIAL" : this.answer ?? "");
|
|
59
65
|
this.write(`${prefix} ${kleur.bold(this.message)} ${SYMBOLS.Pointer} ${answer}${EOL}`);
|
|
60
66
|
}
|
|
61
67
|
|
|
62
68
|
#onQuestionAnswer() {
|
|
63
|
-
|
|
69
|
+
const questionLineCount = Math.ceil(
|
|
70
|
+
wcwidth(stripAnsi(this.#getQuestionQuery() + this.answer)) / this.stdout.columns
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
this.stdout.moveCursor(-this.stdout.columns, -questionLineCount);
|
|
74
|
+
this.stdout.clearScreenDown();
|
|
64
75
|
|
|
65
76
|
for (const validator of this.#validators) {
|
|
66
77
|
if (!validator.validate(this.answer)) {
|
package/src/select-prompt.js
CHANGED
|
@@ -3,12 +3,16 @@ import { EOL } from "node:os";
|
|
|
3
3
|
|
|
4
4
|
// Import Third-party Dependencies
|
|
5
5
|
import kleur from "kleur";
|
|
6
|
+
import stripAnsi from "strip-ansi";
|
|
7
|
+
import wcwidth from "@topcli/wcwidth";
|
|
6
8
|
|
|
7
9
|
// Import Internal Dependencies
|
|
8
10
|
import { AbstractPrompt } from "./abstract-prompt.js";
|
|
9
11
|
import { SYMBOLS } from "./constants.js";
|
|
10
12
|
|
|
11
13
|
export class SelectPrompt extends AbstractPrompt {
|
|
14
|
+
#boundExitEvent = () => void 0;
|
|
15
|
+
#boundKeyPressEvent = () => void 0;
|
|
12
16
|
activeIndex = 0;
|
|
13
17
|
|
|
14
18
|
get choices() {
|
|
@@ -113,6 +117,46 @@ export class SelectPrompt extends AbstractPrompt {
|
|
|
113
117
|
this.write(`${prefix} ${formattedChoice}${EOL}`);
|
|
114
118
|
}
|
|
115
119
|
|
|
120
|
+
#onProcessExit() {
|
|
121
|
+
this.stdin.off("keypress", this.#boundKeyPressEvent);
|
|
122
|
+
this.stdout.moveCursor(-this.stdout.columns, 0);
|
|
123
|
+
this.stdout.clearScreenDown();
|
|
124
|
+
this.write(SYMBOLS.ShowCursor);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
#onKeypress(...args) {
|
|
128
|
+
const [resolve, render, _, key] = args;
|
|
129
|
+
|
|
130
|
+
if (key.name === "up") {
|
|
131
|
+
this.activeIndex = this.activeIndex === 0 ? this.choices.length - 1 : this.activeIndex - 1;
|
|
132
|
+
render();
|
|
133
|
+
}
|
|
134
|
+
else if (key.name === "down") {
|
|
135
|
+
this.activeIndex = this.activeIndex === this.choices.length - 1 ? 0 : this.activeIndex + 1;
|
|
136
|
+
render();
|
|
137
|
+
}
|
|
138
|
+
else if (key.name === "return") {
|
|
139
|
+
render({ clearRender: true });
|
|
140
|
+
|
|
141
|
+
const currentChoice = this.choices[this.activeIndex];
|
|
142
|
+
const value = currentChoice.value ?? currentChoice;
|
|
143
|
+
|
|
144
|
+
if (!this.options.ignoreValues?.includes(value)) {
|
|
145
|
+
this.#showAnsweredQuestion(currentChoice);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
this.write(SYMBOLS.ShowCursor);
|
|
149
|
+
this.destroy();
|
|
150
|
+
|
|
151
|
+
this.#onProcessExit();
|
|
152
|
+
process.off("exit", this.#boundExitEvent);
|
|
153
|
+
resolve(value);
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
render();
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
116
160
|
async select() {
|
|
117
161
|
if (this.agent.nextAnswers.length > 0) {
|
|
118
162
|
const answer = this.agent.nextAnswers.shift();
|
|
@@ -140,7 +184,11 @@ export class SelectPrompt extends AbstractPrompt {
|
|
|
140
184
|
}
|
|
141
185
|
|
|
142
186
|
if (clearRender) {
|
|
143
|
-
|
|
187
|
+
const questionLineCount = Math.ceil(
|
|
188
|
+
wcwidth(stripAnsi(this.questionMessage)) / this.stdout.columns
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
this.stdout.moveCursor(-this.stdout.columns, -(1 + questionLineCount));
|
|
144
192
|
this.stdout.clearScreenDown();
|
|
145
193
|
|
|
146
194
|
return;
|
|
@@ -152,39 +200,16 @@ export class SelectPrompt extends AbstractPrompt {
|
|
|
152
200
|
render({ initialRender: true });
|
|
153
201
|
|
|
154
202
|
return new Promise((resolve) => {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
this.activeIndex = this.activeIndex === 0 ? this.choices.length - 1 : this.activeIndex - 1;
|
|
158
|
-
render();
|
|
159
|
-
}
|
|
160
|
-
else if (key.name === "down") {
|
|
161
|
-
this.activeIndex = this.activeIndex === this.choices.length - 1 ? 0 : this.activeIndex + 1;
|
|
162
|
-
render();
|
|
163
|
-
}
|
|
164
|
-
else if (key.name === "return") {
|
|
165
|
-
this.stdin.off("keypress", onKeypress);
|
|
166
|
-
|
|
167
|
-
render({ clearRender: true });
|
|
168
|
-
|
|
169
|
-
const currentChoice = this.choices[this.activeIndex];
|
|
170
|
-
const value = currentChoice.value ?? currentChoice;
|
|
171
|
-
|
|
172
|
-
if (!this.options.ignoreValues?.includes(value)) {
|
|
173
|
-
this.#showAnsweredQuestion(currentChoice);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
this.write(SYMBOLS.ShowCursor);
|
|
177
|
-
this.destroy();
|
|
178
|
-
|
|
179
|
-
resolve(value);
|
|
180
|
-
}
|
|
181
|
-
};
|
|
203
|
+
this.#boundKeyPressEvent = this.#onKeypress.bind(this, resolve, render);
|
|
204
|
+
this.stdin.on("keypress", this.#boundKeyPressEvent);
|
|
182
205
|
|
|
183
|
-
this.
|
|
206
|
+
this.#boundExitEvent = this.#onProcessExit.bind(this);
|
|
207
|
+
process.once("exit", this.#boundExitEvent);
|
|
184
208
|
});
|
|
185
209
|
}
|
|
186
210
|
|
|
187
211
|
#showQuestion() {
|
|
188
|
-
this.
|
|
212
|
+
this.questionMessage = `${SYMBOLS.QuestionMark} ${kleur.bold(this.message)}`;
|
|
213
|
+
this.write(`${this.questionMessage}${EOL}`);
|
|
189
214
|
}
|
|
190
215
|
}
|