@topcli/prompts 1.5.1 → 1.6.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/README.md +3 -0
- package/index.d.ts +1 -0
- package/index.js +5 -8
- package/package.json +2 -5
- package/src/constants.js +4 -3
- package/src/{abstract-prompt.js → prompts/abstract.js} +2 -4
- package/src/{confirm-prompt.js → prompts/confirm.js} +3 -3
- package/src/prompts/index.js +12 -0
- package/src/{multiselect-prompt.js → prompts/multiselect.js} +87 -36
- package/src/{question-prompt.js → prompts/question.js} +3 -3
- package/src/{select-prompt.js → prompts/select.js} +3 -3
- package/src/utils.js +43 -0
package/README.md
CHANGED
|
@@ -108,6 +108,8 @@ const os = await multiselect('Choose OS', {
|
|
|
108
108
|
});
|
|
109
109
|
```
|
|
110
110
|
|
|
111
|
+
Use `autocomplete` to allow filtered choices. This can be usefull for a large list of choices.
|
|
112
|
+
|
|
111
113
|
### `confirm()`
|
|
112
114
|
|
|
113
115
|
```ts
|
|
@@ -177,6 +179,7 @@ export interface MultiselectOptions extends SharedOptions {
|
|
|
177
179
|
maxVisible?: number;
|
|
178
180
|
preSelectedChoices?: (Choice | string)[];
|
|
179
181
|
validators?: Validator[];
|
|
182
|
+
autocomplete?: boolean;
|
|
180
183
|
}
|
|
181
184
|
|
|
182
185
|
export interface ConfirmOptions extends SharedOptions {
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -1,31 +1,28 @@
|
|
|
1
1
|
// Import Internal Dependencies
|
|
2
|
-
import
|
|
3
|
-
import { SelectPrompt } from "./src/select-prompt.js";
|
|
4
|
-
import { QuestionPrompt } from "./src/question-prompt.js";
|
|
2
|
+
import * as prompts from "./src/prompts/index.js";
|
|
5
3
|
import { required } from "./src/validators.js";
|
|
6
4
|
import { PromptAgent } from "./src/prompt-agent.js";
|
|
7
|
-
import { MultiselectPrompt } from "./src/multiselect-prompt.js";
|
|
8
5
|
|
|
9
6
|
export async function question(message, options = {}) {
|
|
10
|
-
const questionPrompt = new QuestionPrompt(message, options);
|
|
7
|
+
const questionPrompt = new prompts.QuestionPrompt(message, options);
|
|
11
8
|
|
|
12
9
|
return questionPrompt.question();
|
|
13
10
|
}
|
|
14
11
|
|
|
15
12
|
export async function select(message, options) {
|
|
16
|
-
const selectPrompt = new SelectPrompt(message, options);
|
|
13
|
+
const selectPrompt = new prompts.SelectPrompt(message, options);
|
|
17
14
|
|
|
18
15
|
return selectPrompt.select();
|
|
19
16
|
}
|
|
20
17
|
|
|
21
18
|
export async function confirm(message, options) {
|
|
22
|
-
const confirmPrompt = new ConfirmPrompt(message, options);
|
|
19
|
+
const confirmPrompt = new prompts.ConfirmPrompt(message, options);
|
|
23
20
|
|
|
24
21
|
return confirmPrompt.confirm();
|
|
25
22
|
}
|
|
26
23
|
|
|
27
24
|
export async function multiselect(message, options) {
|
|
28
|
-
const multiselectPrompt = new MultiselectPrompt(message, options);
|
|
25
|
+
const multiselectPrompt = new prompts.MultiselectPrompt(message, options);
|
|
29
26
|
|
|
30
27
|
return multiselectPrompt.multiselect();
|
|
31
28
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@topcli/prompts",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
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/",
|
|
@@ -31,10 +31,7 @@
|
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@topcli/wcwidth": "^1.0.1",
|
|
34
|
-
"
|
|
35
|
-
"is-unicode-supported": "^2.0.0",
|
|
36
|
-
"kleur": "^4.1.5",
|
|
37
|
-
"strip-ansi": "^7.1.0"
|
|
34
|
+
"kleur": "^4.1.5"
|
|
38
35
|
},
|
|
39
36
|
"engines": {
|
|
40
37
|
"node": ">=14"
|
package/src/constants.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// Import Third-party Dependencies
|
|
2
2
|
import kleur from "kleur";
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
|
|
4
|
+
// Import Internal Dependencies
|
|
5
|
+
import { isUnicodeSupported } from "./utils.js";
|
|
5
6
|
|
|
6
7
|
const kMainSymbols = {
|
|
7
8
|
tick: "✔",
|
|
@@ -21,7 +22,7 @@ const kFallbackSymbols = {
|
|
|
21
22
|
active: "(+)",
|
|
22
23
|
inactive: "(-)"
|
|
23
24
|
};
|
|
24
|
-
const kSymbols = isUnicodeSupported() ||
|
|
25
|
+
const kSymbols = isUnicodeSupported() || process.env.CI ? kMainSymbols : kFallbackSymbols;
|
|
25
26
|
const kPointer = kleur.gray(kSymbols.pointer);
|
|
26
27
|
|
|
27
28
|
export const SYMBOLS = {
|
|
@@ -3,11 +3,9 @@ import { EOL } from "node:os";
|
|
|
3
3
|
import { createInterface } from "node:readline";
|
|
4
4
|
import { Writable } from "node:stream";
|
|
5
5
|
|
|
6
|
-
// Import Third-party Dependencies
|
|
7
|
-
import stripAnsi from "strip-ansi";
|
|
8
|
-
|
|
9
6
|
// Import Internal Dependencies
|
|
10
|
-
import {
|
|
7
|
+
import { stripAnsi } from "../utils.js";
|
|
8
|
+
import { PromptAgent } from "../prompt-agent.js";
|
|
11
9
|
|
|
12
10
|
export class AbstractPrompt {
|
|
13
11
|
constructor(message, input = process.stdin, output = process.stdout) {
|
|
@@ -3,12 +3,12 @@ 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
6
|
import wcwidth from "@topcli/wcwidth";
|
|
8
7
|
|
|
9
8
|
// Import Internal Dependencies
|
|
10
|
-
import { AbstractPrompt } from "./abstract
|
|
11
|
-
import {
|
|
9
|
+
import { AbstractPrompt } from "./abstract.js";
|
|
10
|
+
import { stripAnsi } from "../utils.js";
|
|
11
|
+
import { SYMBOLS } from "../constants.js";
|
|
12
12
|
|
|
13
13
|
// CONSTANTS
|
|
14
14
|
const kToggleKeys = new Set([
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Import Internal Dependencies
|
|
2
|
+
import { QuestionPrompt } from "./question.js";
|
|
3
|
+
import { ConfirmPrompt } from "./confirm.js";
|
|
4
|
+
import { SelectPrompt } from "./select.js";
|
|
5
|
+
import { MultiselectPrompt } from "./multiselect.js";
|
|
6
|
+
|
|
7
|
+
export {
|
|
8
|
+
QuestionPrompt,
|
|
9
|
+
ConfirmPrompt,
|
|
10
|
+
SelectPrompt,
|
|
11
|
+
MultiselectPrompt
|
|
12
|
+
};
|
|
@@ -3,12 +3,15 @@ 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
6
|
import wcwidth from "@topcli/wcwidth";
|
|
8
7
|
|
|
9
8
|
// Import Internal Dependencies
|
|
10
|
-
import { AbstractPrompt } from "./abstract
|
|
11
|
-
import {
|
|
9
|
+
import { AbstractPrompt } from "./abstract.js";
|
|
10
|
+
import { stripAnsi } from "../utils.js";
|
|
11
|
+
import { SYMBOLS } from "../constants.js";
|
|
12
|
+
|
|
13
|
+
// CONSTANTS
|
|
14
|
+
const kRequiredChoiceProperties = ["label", "value"];
|
|
12
15
|
|
|
13
16
|
export class MultiselectPrompt extends AbstractPrompt {
|
|
14
17
|
#boundExitEvent = () => void 0;
|
|
@@ -18,11 +21,42 @@ export class MultiselectPrompt extends AbstractPrompt {
|
|
|
18
21
|
activeIndex = 0;
|
|
19
22
|
selectedIndexes = [];
|
|
20
23
|
questionMessage;
|
|
24
|
+
autocompleteValue = "";
|
|
21
25
|
|
|
22
26
|
get choices() {
|
|
23
27
|
return this.options.choices;
|
|
24
28
|
}
|
|
25
29
|
|
|
30
|
+
get filteredChoices() {
|
|
31
|
+
return this.options.autocomplete && this.autocompleteValue.length > 0 ? this.choices.filter((choice) => {
|
|
32
|
+
if (typeof choice === "string") {
|
|
33
|
+
if (this.autocompleteValue.includes(" ")) {
|
|
34
|
+
return this.autocompleteValue.split(" ").every((word) => choice.includes(word)) ||
|
|
35
|
+
choice.includes(this.autocompleteValue);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return choice.includes(this.autocompleteValue);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (this.autocompleteValue.includes(" ")) {
|
|
42
|
+
return this.autocompleteValue.split(" ").every((word) => choice.label.includes(word)) ||
|
|
43
|
+
choice.label.includes(this.autocompleteValue);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return choice.label.includes(this.autocompleteValue);
|
|
47
|
+
}) : this.choices;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
get longestChoice() {
|
|
51
|
+
return Math.max(...this.filteredChoices.map((choice) => {
|
|
52
|
+
if (typeof choice === "string") {
|
|
53
|
+
return choice.length;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return choice.label.length;
|
|
57
|
+
}));
|
|
58
|
+
}
|
|
59
|
+
|
|
26
60
|
constructor(message, options) {
|
|
27
61
|
const {
|
|
28
62
|
stdin = process.stdin,
|
|
@@ -46,31 +80,27 @@ export class MultiselectPrompt extends AbstractPrompt {
|
|
|
46
80
|
throw new TypeError("Missing required param: choices");
|
|
47
81
|
}
|
|
48
82
|
|
|
49
|
-
this
|
|
83
|
+
this.#validators = validators;
|
|
84
|
+
|
|
85
|
+
for (const choice of choices) {
|
|
50
86
|
if (typeof choice === "string") {
|
|
51
|
-
|
|
87
|
+
continue;
|
|
52
88
|
}
|
|
53
89
|
|
|
54
|
-
const kRequiredChoiceProperties = ["label", "value"];
|
|
55
|
-
|
|
56
90
|
for (const prop of kRequiredChoiceProperties) {
|
|
57
91
|
if (!choice[prop]) {
|
|
58
92
|
this.destroy();
|
|
59
93
|
throw new TypeError(`Missing ${prop} for choice ${JSON.stringify(choice)}`);
|
|
60
94
|
}
|
|
61
95
|
}
|
|
62
|
-
|
|
63
|
-
return choice.label.length;
|
|
64
|
-
}));
|
|
65
|
-
|
|
66
|
-
this.#validators = validators;
|
|
96
|
+
}
|
|
67
97
|
|
|
68
98
|
if (!preSelectedChoices) {
|
|
69
99
|
return;
|
|
70
100
|
}
|
|
71
101
|
|
|
72
102
|
for (const choice of preSelectedChoices) {
|
|
73
|
-
const choiceIndex = this.
|
|
103
|
+
const choiceIndex = this.filteredChoices.findIndex((item) => {
|
|
74
104
|
if (typeof item === "string") {
|
|
75
105
|
return item === choice;
|
|
76
106
|
}
|
|
@@ -87,7 +117,7 @@ export class MultiselectPrompt extends AbstractPrompt {
|
|
|
87
117
|
}
|
|
88
118
|
|
|
89
119
|
#getFormattedChoice(choiceIndex) {
|
|
90
|
-
const choice = this.
|
|
120
|
+
const choice = this.filteredChoices[choiceIndex];
|
|
91
121
|
|
|
92
122
|
if (typeof choice === "string") {
|
|
93
123
|
return { value: choice, label: choice };
|
|
@@ -98,12 +128,12 @@ export class MultiselectPrompt extends AbstractPrompt {
|
|
|
98
128
|
|
|
99
129
|
#getVisibleChoices() {
|
|
100
130
|
const maxVisible = this.options.maxVisible || 8;
|
|
101
|
-
let startIndex = Math.min(this.
|
|
131
|
+
let startIndex = Math.min(this.filteredChoices.length - maxVisible, this.activeIndex - Math.floor(maxVisible / 2));
|
|
102
132
|
if (startIndex < 0) {
|
|
103
133
|
startIndex = 0;
|
|
104
134
|
}
|
|
105
135
|
|
|
106
|
-
const endIndex = Math.min(startIndex + maxVisible, this.
|
|
136
|
+
const endIndex = Math.min(startIndex + maxVisible, this.filteredChoices.length);
|
|
107
137
|
|
|
108
138
|
return { startIndex, endIndex };
|
|
109
139
|
}
|
|
@@ -112,12 +142,15 @@ export class MultiselectPrompt extends AbstractPrompt {
|
|
|
112
142
|
const { startIndex, endIndex } = this.#getVisibleChoices();
|
|
113
143
|
this.lastRender = { startIndex, endIndex };
|
|
114
144
|
|
|
145
|
+
if (this.options.autocomplete) {
|
|
146
|
+
this.write(`${SYMBOLS.Pointer} ${this.autocompleteValue}${EOL}`);
|
|
147
|
+
}
|
|
115
148
|
for (let choiceIndex = startIndex; choiceIndex < endIndex; choiceIndex++) {
|
|
116
149
|
const choice = this.#getFormattedChoice(choiceIndex);
|
|
117
150
|
const isChoiceActive = choiceIndex === this.activeIndex;
|
|
118
151
|
const isChoiceSelected = this.selectedIndexes.includes(choiceIndex);
|
|
119
152
|
const showPreviousChoicesArrow = startIndex > 0 && choiceIndex === startIndex;
|
|
120
|
-
const showNextChoicesArrow = endIndex < this.
|
|
153
|
+
const showNextChoicesArrow = endIndex < this.filteredChoices.length && choiceIndex === endIndex - 1;
|
|
121
154
|
|
|
122
155
|
let prefixArrow = " ";
|
|
123
156
|
if (showPreviousChoicesArrow) {
|
|
@@ -156,34 +189,30 @@ export class MultiselectPrompt extends AbstractPrompt {
|
|
|
156
189
|
|
|
157
190
|
#onKeypress(...args) {
|
|
158
191
|
const [resolve, render, _, key] = args;
|
|
159
|
-
|
|
160
192
|
if (key.name === "up") {
|
|
161
|
-
this.activeIndex = this.activeIndex === 0 ? this.
|
|
193
|
+
this.activeIndex = this.activeIndex === 0 ? this.filteredChoices.length - 1 : this.activeIndex - 1;
|
|
162
194
|
render();
|
|
163
195
|
}
|
|
164
196
|
else if (key.name === "down") {
|
|
165
|
-
this.activeIndex = this.activeIndex === this.
|
|
197
|
+
this.activeIndex = this.activeIndex === this.filteredChoices.length - 1 ? 0 : this.activeIndex + 1;
|
|
166
198
|
render();
|
|
167
199
|
}
|
|
168
|
-
else if (key.name === "a") {
|
|
169
|
-
|
|
200
|
+
else if (key.ctrl && key.name === "a") {
|
|
201
|
+
// eslint-disable-next-line max-len
|
|
202
|
+
this.selectedIndexes = this.selectedIndexes.length === this.filteredChoices.length ? [] : this.filteredChoices.map((_, index) => index);
|
|
170
203
|
render();
|
|
171
204
|
}
|
|
172
|
-
else if (key.name === "
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
else {
|
|
179
|
-
this.selectedIndexes.push(this.activeIndex);
|
|
180
|
-
}
|
|
181
|
-
|
|
205
|
+
else if (key.name === "right") {
|
|
206
|
+
this.selectedIndexes.push(this.activeIndex);
|
|
207
|
+
render();
|
|
208
|
+
}
|
|
209
|
+
else if (key.name === "left") {
|
|
210
|
+
this.selectedIndexes = this.selectedIndexes.filter((index) => index !== this.activeIndex);
|
|
182
211
|
render();
|
|
183
212
|
}
|
|
184
213
|
else if (key.name === "return") {
|
|
185
|
-
const labels = this.selectedIndexes.map((index) => this.
|
|
186
|
-
const values = this.selectedIndexes.map((index) => this.
|
|
214
|
+
const labels = this.selectedIndexes.map((index) => this.filteredChoices[index].label ?? this.filteredChoices[index]);
|
|
215
|
+
const values = this.selectedIndexes.map((index) => this.filteredChoices[index].value ?? this.filteredChoices[index]);
|
|
187
216
|
|
|
188
217
|
for (const validator of this.#validators) {
|
|
189
218
|
if (!validator.validate(values)) {
|
|
@@ -207,6 +236,17 @@ export class MultiselectPrompt extends AbstractPrompt {
|
|
|
207
236
|
resolve(values);
|
|
208
237
|
}
|
|
209
238
|
else {
|
|
239
|
+
if (!key.ctrl && this.options.autocomplete) {
|
|
240
|
+
// reset selected choices when user type
|
|
241
|
+
this.selectedIndexes = [];
|
|
242
|
+
this.activeIndex = 0;
|
|
243
|
+
if (key.name === "backspace" && this.autocompleteValue.length > 0) {
|
|
244
|
+
this.autocompleteValue = this.autocompleteValue.slice(0, -1);
|
|
245
|
+
}
|
|
246
|
+
else if (key.name !== "backspace") {
|
|
247
|
+
this.autocompleteValue += key.sequence;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
210
250
|
render();
|
|
211
251
|
}
|
|
212
252
|
}
|
|
@@ -236,6 +276,15 @@ export class MultiselectPrompt extends AbstractPrompt {
|
|
|
236
276
|
this.clearLastLine();
|
|
237
277
|
linesToClear--;
|
|
238
278
|
}
|
|
279
|
+
if (this.options.autocomplete) {
|
|
280
|
+
let linesToClear = Math.ceil(
|
|
281
|
+
wcwidth(`${SYMBOLS.Pointer} ${this.autocompleteValue}`) / this.stdout.columns
|
|
282
|
+
);
|
|
283
|
+
while (linesToClear > 0) {
|
|
284
|
+
this.clearLastLine();
|
|
285
|
+
linesToClear--;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
239
288
|
}
|
|
240
289
|
|
|
241
290
|
if (clearRender) {
|
|
@@ -249,7 +298,8 @@ export class MultiselectPrompt extends AbstractPrompt {
|
|
|
249
298
|
}
|
|
250
299
|
|
|
251
300
|
if (error) {
|
|
252
|
-
this.stdout.
|
|
301
|
+
const linesToClear = Math.ceil(wcwidth(this.questionMessage) / this.stdout.columns) + 1;
|
|
302
|
+
this.stdout.moveCursor(0, -linesToClear);
|
|
253
303
|
this.stdout.clearScreenDown();
|
|
254
304
|
this.#showQuestion(error);
|
|
255
305
|
}
|
|
@@ -270,7 +320,8 @@ export class MultiselectPrompt extends AbstractPrompt {
|
|
|
270
320
|
|
|
271
321
|
#showQuestion(error = null) {
|
|
272
322
|
let hint = kleur.gray(
|
|
273
|
-
|
|
323
|
+
// eslint-disable-next-line max-len
|
|
324
|
+
`(Press ${kleur.bold("<Ctrl+A>")} to toggle all, ${kleur.bold("<Ctrl+Space>")} to select, ${kleur.bold("<Left/Right>")} to toggle, ${kleur.bold("<Return>")} to submit)`
|
|
274
325
|
);
|
|
275
326
|
if (error) {
|
|
276
327
|
hint += ` ${kleur.red().bold(`[${error}]`)}`;
|
|
@@ -3,12 +3,12 @@ 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
6
|
import wcwidth from "@topcli/wcwidth";
|
|
8
7
|
|
|
9
8
|
// Import Internal Dependencies
|
|
10
|
-
import { AbstractPrompt } from "./abstract
|
|
11
|
-
import {
|
|
9
|
+
import { AbstractPrompt } from "./abstract.js";
|
|
10
|
+
import { stripAnsi } from "../utils.js";
|
|
11
|
+
import { SYMBOLS } from "../constants.js";
|
|
12
12
|
|
|
13
13
|
export class QuestionPrompt extends AbstractPrompt {
|
|
14
14
|
#validators;
|
|
@@ -3,12 +3,12 @@ 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
6
|
import wcwidth from "@topcli/wcwidth";
|
|
8
7
|
|
|
9
8
|
// Import Internal Dependencies
|
|
10
|
-
import { AbstractPrompt } from "./abstract
|
|
11
|
-
import {
|
|
9
|
+
import { AbstractPrompt } from "./abstract.js";
|
|
10
|
+
import { stripAnsi } from "../utils.js";
|
|
11
|
+
import { SYMBOLS } from "../constants.js";
|
|
12
12
|
|
|
13
13
|
export class SelectPrompt extends AbstractPrompt {
|
|
14
14
|
#boundExitEvent = () => void 0;
|
package/src/utils.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import process from "node:process";
|
|
2
|
+
|
|
3
|
+
// CONSTANTS
|
|
4
|
+
const kAnsiRegex = ansiRegex();
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @see https://github.com/chalk/ansi-regex
|
|
8
|
+
*/
|
|
9
|
+
export function ansiRegex({onlyFirst = false} = {}) {
|
|
10
|
+
const pattern = [
|
|
11
|
+
'[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)',
|
|
12
|
+
'(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))'
|
|
13
|
+
].join('|');
|
|
14
|
+
|
|
15
|
+
return new RegExp(pattern, onlyFirst ? undefined : 'g');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {!string} string
|
|
20
|
+
* @returns {string}
|
|
21
|
+
*/
|
|
22
|
+
export function stripAnsi(string) {
|
|
23
|
+
return string.replace(kAnsiRegex, "");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @see https://github.com/sindresorhus/is-unicode-supported
|
|
28
|
+
* @returns {boolean}
|
|
29
|
+
*/
|
|
30
|
+
export function isUnicodeSupported() {
|
|
31
|
+
if (process.platform !== 'win32') {
|
|
32
|
+
return process.env.TERM !== 'linux'; // Linux console (kernel)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return Boolean(process.env.WT_SESSION) // Windows Terminal
|
|
36
|
+
|| Boolean(process.env.TERMINUS_SUBLIME) // Terminus (<0.2.27)
|
|
37
|
+
|| process.env.ConEmuTask === '{cmd::Cmder}' // ConEmu and cmder
|
|
38
|
+
|| process.env.TERM_PROGRAM === 'Terminus-Sublime'
|
|
39
|
+
|| process.env.TERM_PROGRAM === 'vscode'
|
|
40
|
+
|| process.env.TERM === 'xterm-256color'
|
|
41
|
+
|| process.env.TERM === 'alacritty'
|
|
42
|
+
|| process.env.TERMINAL_EMULATOR === 'JetBrains-JediTerm';
|
|
43
|
+
}
|