spyne-cli 0.6.8 → 0.7.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 +661 -0
- package/README.md +80 -30
- package/index.js +123 -21
- package/package.json +24 -6
- package/src/cli/args.js +197 -0
- package/src/cli/render.js +184 -0
- package/src/core/create-app.js +232 -0
- package/src/core/generate-module.js +146 -0
- package/src/registry.js +174 -0
- package/src/spyne-file-prompt.js +77 -30
- package/src/templates/generate-prompt-input-fields.js +1 -1
- package/src/ui.js +5 -1
- package/lib/ansi.js +0 -116
- package/lib/combos.js +0 -75
- package/lib/completer.js +0 -52
- package/lib/interpolate.js +0 -266
- package/lib/keypress.js +0 -243
- package/lib/placeholder.js +0 -63
- package/lib/prompt.js +0 -485
- package/lib/prompts/autocomplete.js +0 -113
- package/lib/prompts/basicauth.js +0 -41
- package/lib/prompts/confirm.js +0 -13
- package/lib/prompts/editable.js +0 -136
- package/lib/prompts/form.js +0 -196
- package/lib/prompts/index.js +0 -28
- package/lib/prompts/input.js +0 -55
- package/lib/prompts/invisible.js +0 -11
- package/lib/prompts/list.js +0 -36
- package/lib/prompts/multiselect.js +0 -11
- package/lib/prompts/numeral.js +0 -1
- package/lib/prompts/password.js +0 -18
- package/lib/prompts/quiz.js +0 -37
- package/lib/prompts/scale.js +0 -237
- package/lib/prompts/select.js +0 -139
- package/lib/prompts/snippet.js +0 -185
- package/lib/prompts/sort.js +0 -37
- package/lib/prompts/survey.js +0 -163
- package/lib/prompts/text.js +0 -1
- package/lib/prompts/toggle.js +0 -109
- package/lib/render.js +0 -33
- package/lib/roles.js +0 -46
- package/lib/state.js +0 -69
- package/lib/styles.js +0 -144
- package/lib/symbols.js +0 -66
- package/lib/theme.js +0 -11
- package/lib/timer.js +0 -38
- package/lib/types/array.js +0 -658
- package/lib/types/auth.js +0 -29
- package/lib/types/boolean.js +0 -88
- package/lib/types/index.js +0 -7
- package/lib/types/number.js +0 -86
- package/lib/types/string.js +0 -185
- package/lib/utils.js +0 -268
- package/mocha.conf.cjs +0 -16
- package/src/app/channels/.gitkeep +0 -0
- package/src/app/channels/channel-custom.js +0 -1
- package/src/app/components/.gitkeep +0 -0
- package/src/app/traits/.gitkeep +0 -0
- package/src/hello-world-app-source/README.md +0 -15
- package/src/hello-world-app-source/apache-htaccess +0 -20
- package/src/hello-world-app-source/karma.conf.js +0 -75
- package/src/hello-world-app-source/package.json +0 -50
- package/src/hello-world-app-source/src/app/app-view.js +0 -38
- package/src/hello-world-app-source/src/app/channels/.gitkeep +0 -0
- package/src/hello-world-app-source/src/app/components/.gitkeep +0 -0
- package/src/hello-world-app-source/src/app/traits/.gitkeep +0 -0
- package/src/hello-world-app-source/src/index.js +0 -16
- package/src/hello-world-app-source/src/index.tmpl.html +0 -12
- package/src/hello-world-app-source/src/scss/01-vendors/normalize.css +0 -349
- package/src/hello-world-app-source/src/scss/02-variables/mixins.scss +0 -0
- package/src/hello-world-app-source/src/scss/03-components/.gitkeep +0 -0
- package/src/hello-world-app-source/src/scss/main.scss +0 -15
- package/src/hello-world-app-source/src/static/data/.gitkeep +0 -0
- package/src/hello-world-app-source/src/static/fonts/.gitkeep +0 -0
- package/src/hello-world-app-source/src/static/imgs/.gitkeep +0 -0
- package/src/hello-world-app-source/src/tests/unit-tests/index.test.js +0 -10
- package/src/hello-world-app-source/webpack.config.js +0 -178
- package/src/spyne-app-create.js +0 -209
- package/src/spyne-app-creator.js +0 -119
- package/src/spyne-starter-app-create.js +0 -147
- package/tests/create-spyne-app.test.js +0 -63
- package/tests/generate-file-prompt.test.js +0 -45
- package/tests/generate-file-string.test.js +0 -66
- package/tests/generate-prompt-input-fields-methods.test.js +0 -177
- package/tests/generate-prompt-input-fields.test.js +0 -179
- package/tests/generate-prompt-input-object.test.js +0 -39
- package/tests/generate-prompt-output.test.js +0 -58
- package/tests/index.test.js +0 -11
- package/tests/mocks/answers.js +0 -33
- package/tests/mocks/answers.json +0 -33
- package/tests/mocks/enquirer-data.js +0 -411
- package/tests/mocks/enquirer-data.json +0 -409
- package/tests/utils/file-utils.test.js +0 -84
package/lib/interpolate.js
DELETED
|
@@ -1,266 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const colors = require('ansi-colors');
|
|
4
|
-
const clean = (str = '') => {
|
|
5
|
-
return typeof str === 'string' ? str.replace(/^['"]|['"]$/g, '') : '';
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* This file contains the interpolation and rendering logic for
|
|
10
|
-
* the Snippet prompt.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
class Item {
|
|
14
|
-
constructor(token) {
|
|
15
|
-
this.name = token.key;
|
|
16
|
-
this.field = token.field || {};
|
|
17
|
-
this.value = clean(token.initial || this.field.initial || '');
|
|
18
|
-
this.message = token.message || this.name;
|
|
19
|
-
this.cursor = 0;
|
|
20
|
-
this.input = '';
|
|
21
|
-
this.lines = [];
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const tokenize = async(options = {}, defaults = {}, fn = token => token) => {
|
|
26
|
-
let unique = new Set();
|
|
27
|
-
let fields = options.fields || [];
|
|
28
|
-
let input = options.template;
|
|
29
|
-
let tabstops = [];
|
|
30
|
-
let items = [];
|
|
31
|
-
let keys = [];
|
|
32
|
-
let line = 1;
|
|
33
|
-
|
|
34
|
-
if (typeof input === 'function') {
|
|
35
|
-
input = await input();
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
let i = -1;
|
|
39
|
-
let next = () => input[++i];
|
|
40
|
-
let peek = () => input[i + 1];
|
|
41
|
-
let push = token => {
|
|
42
|
-
token.line = line;
|
|
43
|
-
tabstops.push(token);
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
push({ type: 'bos', value: '' });
|
|
47
|
-
|
|
48
|
-
while (i < input.length - 1) {
|
|
49
|
-
let value = next();
|
|
50
|
-
|
|
51
|
-
if (/^[^\S\n ]$/.test(value)) {
|
|
52
|
-
push({ type: 'text', value });
|
|
53
|
-
continue;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (value === '\n') {
|
|
57
|
-
push({ type: 'newline', value });
|
|
58
|
-
line++;
|
|
59
|
-
continue;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (value === '\\') {
|
|
63
|
-
value += next();
|
|
64
|
-
push({ type: 'text', value });
|
|
65
|
-
continue;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if ((value === '$' || value === '#' || value === '{') && peek() === '{') {
|
|
69
|
-
let n = next();
|
|
70
|
-
value += n;
|
|
71
|
-
|
|
72
|
-
let token = { type: 'template', open: value, inner: '', close: '', value };
|
|
73
|
-
let ch;
|
|
74
|
-
|
|
75
|
-
while ((ch = next())) {
|
|
76
|
-
if (ch === '}') {
|
|
77
|
-
if (peek() === '}') ch += next();
|
|
78
|
-
token.value += ch;
|
|
79
|
-
token.close = ch;
|
|
80
|
-
break;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (ch === ':') {
|
|
84
|
-
token.initial = '';
|
|
85
|
-
token.key = token.inner;
|
|
86
|
-
} else if (token.initial !== void 0) {
|
|
87
|
-
token.initial += ch;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
token.value += ch;
|
|
91
|
-
token.inner += ch;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
token.template = token.open + (token.initial || token.inner) + token.close;
|
|
95
|
-
token.key = token.key || token.inner;
|
|
96
|
-
|
|
97
|
-
if (defaults.hasOwnProperty(token.key)) {
|
|
98
|
-
token.initial = defaults[token.key];
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
token = fn(token);
|
|
102
|
-
push(token);
|
|
103
|
-
|
|
104
|
-
keys.push(token.key);
|
|
105
|
-
unique.add(token.key);
|
|
106
|
-
|
|
107
|
-
let item = items.find(item => item.name === token.key);
|
|
108
|
-
token.field = fields.find(ch => ch.name === token.key);
|
|
109
|
-
|
|
110
|
-
if (!item) {
|
|
111
|
-
item = new Item(token);
|
|
112
|
-
items.push(item);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
item.lines.push(token.line - 1);
|
|
116
|
-
continue;
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
let last = tabstops[tabstops.length - 1];
|
|
120
|
-
if (last.type === 'text' && last.line === line) {
|
|
121
|
-
last.value += value;
|
|
122
|
-
} else {
|
|
123
|
-
push({ type: 'text', value });
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
push({ type: 'eos', value: '' });
|
|
128
|
-
return { input, tabstops, unique, keys, items };
|
|
129
|
-
};
|
|
130
|
-
|
|
131
|
-
module.exports = async prompt => {
|
|
132
|
-
let options = prompt.options;
|
|
133
|
-
let required = new Set(options.required === true ? [] : (options.required || []));
|
|
134
|
-
let defaults = { ...options.values, ...options.initial };
|
|
135
|
-
let { tabstops, items, keys } = await tokenize(options, defaults);
|
|
136
|
-
|
|
137
|
-
let result = createFn('result', prompt, options);
|
|
138
|
-
let format = createFn('format', prompt, options);
|
|
139
|
-
let isValid = createFn('validate', prompt, options, true);
|
|
140
|
-
let isVal = prompt.isValue.bind(prompt);
|
|
141
|
-
|
|
142
|
-
return async(state = {}, submitted = false) => {
|
|
143
|
-
let index = 0;
|
|
144
|
-
|
|
145
|
-
state.required = required;
|
|
146
|
-
state.items = items;
|
|
147
|
-
state.keys = keys;
|
|
148
|
-
state.output = '';
|
|
149
|
-
|
|
150
|
-
let validate = async(value, state, item, index) => {
|
|
151
|
-
let error = await isValid(value, state, item, index);
|
|
152
|
-
if (error === false) {
|
|
153
|
-
return 'Invalid field ' + item.name;
|
|
154
|
-
}
|
|
155
|
-
return error;
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
for (let token of tabstops) {
|
|
159
|
-
let value = token.value;
|
|
160
|
-
let key = token.key;
|
|
161
|
-
|
|
162
|
-
if (token.type !== 'template') {
|
|
163
|
-
if (value) state.output += value;
|
|
164
|
-
continue;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
if (token.type === 'template') {
|
|
168
|
-
let item = items.find(ch => ch.name === key);
|
|
169
|
-
|
|
170
|
-
if (options.required === true) {
|
|
171
|
-
state.required.add(item.name);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
let val = [item.input, state.values[item.value], item.value, value].find(isVal);
|
|
175
|
-
let field = item.field || {};
|
|
176
|
-
let message = field.message || token.inner;
|
|
177
|
-
|
|
178
|
-
if (submitted) {
|
|
179
|
-
let error = await validate(state.values[key], state, item, index);
|
|
180
|
-
if ((error && typeof error === 'string') || error === false) {
|
|
181
|
-
state.invalid.set(key, error);
|
|
182
|
-
continue;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
state.invalid.delete(key);
|
|
186
|
-
let res = await result(state.values[key], state, item, index);
|
|
187
|
-
state.output += colors.unstyle(res);
|
|
188
|
-
continue;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
item.placeholder = false;
|
|
192
|
-
|
|
193
|
-
let before = value;
|
|
194
|
-
value = await format(value, state, item, index);
|
|
195
|
-
|
|
196
|
-
if (val !== value) {
|
|
197
|
-
state.values[key] = val;
|
|
198
|
-
value = prompt.styles.typing(val);
|
|
199
|
-
state.missing.delete(message);
|
|
200
|
-
|
|
201
|
-
} else {
|
|
202
|
-
state.values[key] = void 0;
|
|
203
|
-
val = `<${message}>`;
|
|
204
|
-
value = prompt.styles.primary(val);
|
|
205
|
-
item.placeholder = true;
|
|
206
|
-
|
|
207
|
-
if (state.required.has(key)) {
|
|
208
|
-
state.missing.add(message);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
if (state.missing.has(message) && state.validating) {
|
|
213
|
-
value = prompt.styles.warning(val);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
if (state.invalid.has(key) && state.validating) {
|
|
217
|
-
value = prompt.styles.danger(val);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
if (index === state.index) {
|
|
221
|
-
if (before !== value) {
|
|
222
|
-
value = prompt.styles.underline(value);
|
|
223
|
-
} else {
|
|
224
|
-
value = prompt.styles.heading(colors.unstyle(value));
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
index++;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
if (value) {
|
|
232
|
-
state.output += value;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
let lines = state.output.split('\n').map(l => ' ' + l);
|
|
237
|
-
let len = items.length;
|
|
238
|
-
let done = 0;
|
|
239
|
-
|
|
240
|
-
for (let item of items) {
|
|
241
|
-
if (state.invalid.has(item.name)) {
|
|
242
|
-
item.lines.forEach(i => {
|
|
243
|
-
if (lines[i][0] !== ' ') return;
|
|
244
|
-
lines[i] = state.styles.danger(state.symbols.bullet) + lines[i].slice(1);
|
|
245
|
-
});
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
if (prompt.isValue(state.values[item.name])) {
|
|
249
|
-
done++;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
state.completed = ((done / len) * 100).toFixed(0);
|
|
254
|
-
state.output = lines.join('\n');
|
|
255
|
-
return state.output;
|
|
256
|
-
};
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
function createFn(prop, prompt, options, fallback) {
|
|
260
|
-
return (value, state, item, index) => {
|
|
261
|
-
if (typeof item.field[prop] === 'function') {
|
|
262
|
-
return item.field[prop].call(prompt, value, state, item, index);
|
|
263
|
-
}
|
|
264
|
-
return [fallback, value].find(v => prompt.isValue(v));
|
|
265
|
-
};
|
|
266
|
-
}
|
package/lib/keypress.js
DELETED
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const readline = require('readline');
|
|
4
|
-
const combos = require('./combos');
|
|
5
|
-
|
|
6
|
-
/* eslint-disable no-control-regex */
|
|
7
|
-
const metaKeyCodeRe = /^(?:\x1b)([a-zA-Z0-9])$/;
|
|
8
|
-
const fnKeyRe = /^(?:\x1b+)(O|N|\[|\[\[)(?:(\d+)(?:;(\d+))?([~^$])|(?:1;)?(\d+)?([a-zA-Z]))/;
|
|
9
|
-
const keyName = {
|
|
10
|
-
/* xterm/gnome ESC O letter */
|
|
11
|
-
'OP': 'f1',
|
|
12
|
-
'OQ': 'f2',
|
|
13
|
-
'OR': 'f3',
|
|
14
|
-
'OS': 'f4',
|
|
15
|
-
/* xterm/rxvt ESC [ number ~ */
|
|
16
|
-
'[11~': 'f1',
|
|
17
|
-
'[12~': 'f2',
|
|
18
|
-
'[13~': 'f3',
|
|
19
|
-
'[14~': 'f4',
|
|
20
|
-
/* from Cygwin and used in libuv */
|
|
21
|
-
'[[A': 'f1',
|
|
22
|
-
'[[B': 'f2',
|
|
23
|
-
'[[C': 'f3',
|
|
24
|
-
'[[D': 'f4',
|
|
25
|
-
'[[E': 'f5',
|
|
26
|
-
/* common */
|
|
27
|
-
'[15~': 'f5',
|
|
28
|
-
'[17~': 'f6',
|
|
29
|
-
'[18~': 'f7',
|
|
30
|
-
'[19~': 'f8',
|
|
31
|
-
'[20~': 'f9',
|
|
32
|
-
'[21~': 'f10',
|
|
33
|
-
'[23~': 'f11',
|
|
34
|
-
'[24~': 'f12',
|
|
35
|
-
/* xterm ESC [ letter */
|
|
36
|
-
'[A': 'up',
|
|
37
|
-
'[B': 'down',
|
|
38
|
-
'[C': 'right',
|
|
39
|
-
'[D': 'left',
|
|
40
|
-
'[E': 'clear',
|
|
41
|
-
'[F': 'end',
|
|
42
|
-
'[H': 'home',
|
|
43
|
-
/* xterm/gnome ESC O letter */
|
|
44
|
-
'OA': 'up',
|
|
45
|
-
'OB': 'down',
|
|
46
|
-
'OC': 'right',
|
|
47
|
-
'OD': 'left',
|
|
48
|
-
'OE': 'clear',
|
|
49
|
-
'OF': 'end',
|
|
50
|
-
'OH': 'home',
|
|
51
|
-
/* xterm/rxvt ESC [ number ~ */
|
|
52
|
-
'[1~': 'home',
|
|
53
|
-
'[2~': 'insert',
|
|
54
|
-
'[3~': 'delete',
|
|
55
|
-
'[4~': 'end',
|
|
56
|
-
'[5~': 'pageup',
|
|
57
|
-
'[6~': 'pagedown',
|
|
58
|
-
/* putty */
|
|
59
|
-
'[[5~': 'pageup',
|
|
60
|
-
'[[6~': 'pagedown',
|
|
61
|
-
/* rxvt */
|
|
62
|
-
'[7~': 'home',
|
|
63
|
-
'[8~': 'end',
|
|
64
|
-
/* rxvt keys with modifiers */
|
|
65
|
-
'[a': 'up',
|
|
66
|
-
'[b': 'down',
|
|
67
|
-
'[c': 'right',
|
|
68
|
-
'[d': 'left',
|
|
69
|
-
'[e': 'clear',
|
|
70
|
-
|
|
71
|
-
'[2$': 'insert',
|
|
72
|
-
'[3$': 'delete',
|
|
73
|
-
'[5$': 'pageup',
|
|
74
|
-
'[6$': 'pagedown',
|
|
75
|
-
'[7$': 'home',
|
|
76
|
-
'[8$': 'end',
|
|
77
|
-
|
|
78
|
-
'Oa': 'up',
|
|
79
|
-
'Ob': 'down',
|
|
80
|
-
'Oc': 'right',
|
|
81
|
-
'Od': 'left',
|
|
82
|
-
'Oe': 'clear',
|
|
83
|
-
|
|
84
|
-
'[2^': 'insert',
|
|
85
|
-
'[3^': 'delete',
|
|
86
|
-
'[5^': 'pageup',
|
|
87
|
-
'[6^': 'pagedown',
|
|
88
|
-
'[7^': 'home',
|
|
89
|
-
'[8^': 'end',
|
|
90
|
-
/* misc. */
|
|
91
|
-
'[Z': 'tab',
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
function isShiftKey(code) {
|
|
95
|
-
return ['[a', '[b', '[c', '[d', '[e', '[2$', '[3$', '[5$', '[6$', '[7$', '[8$', '[Z'].includes(code)
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function isCtrlKey(code) {
|
|
99
|
-
return [ 'Oa', 'Ob', 'Oc', 'Od', 'Oe', '[2^', '[3^', '[5^', '[6^', '[7^', '[8^'].includes(code)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const keypress = (s = '', event = {}) => {
|
|
103
|
-
let parts;
|
|
104
|
-
let key = {
|
|
105
|
-
name: event.name,
|
|
106
|
-
ctrl: false,
|
|
107
|
-
meta: false,
|
|
108
|
-
shift: false,
|
|
109
|
-
option: false,
|
|
110
|
-
sequence: s,
|
|
111
|
-
raw: s,
|
|
112
|
-
...event
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
if (Buffer.isBuffer(s)) {
|
|
116
|
-
if (s[0] > 127 && s[1] === void 0) {
|
|
117
|
-
s[0] -= 128;
|
|
118
|
-
s = '\x1b' + String(s);
|
|
119
|
-
} else {
|
|
120
|
-
s = String(s);
|
|
121
|
-
}
|
|
122
|
-
} else if (s !== void 0 && typeof s !== 'string') {
|
|
123
|
-
s = String(s);
|
|
124
|
-
} else if (!s) {
|
|
125
|
-
s = key.sequence || '';
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
key.sequence = key.sequence || s || key.name;
|
|
129
|
-
|
|
130
|
-
if (s === '\r') {
|
|
131
|
-
// carriage return
|
|
132
|
-
key.raw = void 0;
|
|
133
|
-
key.name = 'return';
|
|
134
|
-
} else if (s === '\n') {
|
|
135
|
-
// enter, should have been called linefeed
|
|
136
|
-
key.name = 'enter';
|
|
137
|
-
} else if (s === '\t') {
|
|
138
|
-
// tab
|
|
139
|
-
key.name = 'tab';
|
|
140
|
-
} else if (s === '\b' || s === '\x7f' || s === '\x1b\x7f' || s === '\x1b\b') {
|
|
141
|
-
// backspace or ctrl+h
|
|
142
|
-
key.name = 'backspace';
|
|
143
|
-
key.meta = s.charAt(0) === '\x1b';
|
|
144
|
-
} else if (s === '\x1b' || s === '\x1b\x1b') {
|
|
145
|
-
// escape key
|
|
146
|
-
key.name = 'escape';
|
|
147
|
-
key.meta = s.length === 2;
|
|
148
|
-
} else if (s === ' ' || s === '\x1b ') {
|
|
149
|
-
key.name = 'space';
|
|
150
|
-
key.meta = s.length === 2;
|
|
151
|
-
} else if (s <= '\x1a') {
|
|
152
|
-
// ctrl+letter
|
|
153
|
-
key.name = String.fromCharCode(s.charCodeAt(0) + 'a'.charCodeAt(0) - 1);
|
|
154
|
-
key.ctrl = true;
|
|
155
|
-
} else if (s.length === 1 && s >= '0' && s <= '9') {
|
|
156
|
-
// number
|
|
157
|
-
key.name = 'number';
|
|
158
|
-
} else if (s.length === 1 && s >= 'a' && s <= 'z') {
|
|
159
|
-
// lowercase letter
|
|
160
|
-
key.name = s;
|
|
161
|
-
} else if (s.length === 1 && s >= 'A' && s <= 'Z') {
|
|
162
|
-
// shift+letter
|
|
163
|
-
key.name = s.toLowerCase();
|
|
164
|
-
key.shift = true;
|
|
165
|
-
} else if ((parts = metaKeyCodeRe.exec(s))) {
|
|
166
|
-
// meta+character key
|
|
167
|
-
key.meta = true;
|
|
168
|
-
key.shift = /^[A-Z]$/.test(parts[1]);
|
|
169
|
-
} else if ((parts = fnKeyRe.exec(s))) {
|
|
170
|
-
let segs = [...s];
|
|
171
|
-
|
|
172
|
-
if (segs[0] === '\u001b' && segs[1] === '\u001b') {
|
|
173
|
-
key.option = true;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// ansi escape sequence
|
|
177
|
-
// reassemble the key code leaving out leading \x1b's,
|
|
178
|
-
// the modifier key bitflag and any meaningless "1;" sequence
|
|
179
|
-
let code = [parts[1], parts[2], parts[4], parts[6]].filter(Boolean).join('');
|
|
180
|
-
let modifier = (parts[3] || parts[5] || 1) - 1;
|
|
181
|
-
|
|
182
|
-
// Parse the key modifier
|
|
183
|
-
key.ctrl = !!(modifier & 4);
|
|
184
|
-
key.meta = !!(modifier & 10);
|
|
185
|
-
key.shift = !!(modifier & 1);
|
|
186
|
-
key.code = code;
|
|
187
|
-
|
|
188
|
-
key.name = keyName[code];
|
|
189
|
-
key.shift = isShiftKey(code) || key.shift;
|
|
190
|
-
key.ctrl = isCtrlKey(code) || key.ctrl;
|
|
191
|
-
}
|
|
192
|
-
return key;
|
|
193
|
-
};
|
|
194
|
-
|
|
195
|
-
keypress.listen = (options = {}, onKeypress) => {
|
|
196
|
-
let { stdin } = options;
|
|
197
|
-
|
|
198
|
-
if (!stdin || (stdin !== process.stdin && !stdin.isTTY)) {
|
|
199
|
-
throw new Error('Invalid stream passed');
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
let rl = readline.createInterface({ terminal: true, input: stdin });
|
|
203
|
-
readline.emitKeypressEvents(stdin, rl);
|
|
204
|
-
|
|
205
|
-
let on = (buf, key) => onKeypress(buf, keypress(buf, key), rl);
|
|
206
|
-
let isRaw = stdin.isRaw;
|
|
207
|
-
|
|
208
|
-
if (stdin.isTTY) stdin.setRawMode(true);
|
|
209
|
-
stdin.on('keypress', on);
|
|
210
|
-
rl.resume();
|
|
211
|
-
|
|
212
|
-
let off = () => {
|
|
213
|
-
if (stdin.isTTY) stdin.setRawMode(isRaw);
|
|
214
|
-
stdin.removeListener('keypress', on);
|
|
215
|
-
rl.pause();
|
|
216
|
-
rl.close();
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
return off;
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
keypress.action = (buf, key, customActions) => {
|
|
223
|
-
let obj = { ...combos, ...customActions };
|
|
224
|
-
if (key.ctrl) {
|
|
225
|
-
key.action = obj.ctrl[key.name];
|
|
226
|
-
return key;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
if (key.option && obj.option) {
|
|
230
|
-
key.action = obj.option[key.name];
|
|
231
|
-
return key;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
if (key.shift) {
|
|
235
|
-
key.action = obj.shift[key.name];
|
|
236
|
-
return key;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
key.action = obj.keys[key.name];
|
|
240
|
-
return key;
|
|
241
|
-
};
|
|
242
|
-
|
|
243
|
-
module.exports = keypress;
|
package/lib/placeholder.js
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const utils = require('./utils');
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Render a placeholder value with cursor and styling based on the
|
|
7
|
-
* position of the cursor.
|
|
8
|
-
*
|
|
9
|
-
* @param {Object} `prompt` Prompt instance.
|
|
10
|
-
* @param {String} `input` Input string.
|
|
11
|
-
* @param {String} `initial` The initial user-provided value.
|
|
12
|
-
* @param {Number} `pos` Current cursor position.
|
|
13
|
-
* @param {Boolean} `showCursor` Render a simulated cursor using the inverse primary style.
|
|
14
|
-
* @return {String} Returns the styled placeholder string.
|
|
15
|
-
* @api public
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
module.exports = (prompt, options = {}) => {
|
|
19
|
-
prompt.cursorHide();
|
|
20
|
-
|
|
21
|
-
let { input = '', initial = '', pos, showCursor = true, color } = options;
|
|
22
|
-
let style = color || prompt.styles.placeholder;
|
|
23
|
-
let inverse = utils.inverse(prompt.styles.primary);
|
|
24
|
-
let blinker = str => inverse(prompt.styles.black(str));
|
|
25
|
-
let output = input;
|
|
26
|
-
let char = ' ';
|
|
27
|
-
let reverse = blinker(char);
|
|
28
|
-
|
|
29
|
-
if (prompt.blink && prompt.blink.off === true) {
|
|
30
|
-
blinker = str => str;
|
|
31
|
-
reverse = '';
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (showCursor && pos === 0 && initial === '' && input === '') {
|
|
35
|
-
return blinker(char);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (showCursor && pos === 0 && (input === initial || input === '')) {
|
|
39
|
-
return blinker(initial[0]) + style(initial.slice(1));
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
initial = utils.isPrimitive(initial) ? `${initial}` : '';
|
|
43
|
-
input = utils.isPrimitive(input) ? `${input}` : '';
|
|
44
|
-
|
|
45
|
-
let placeholder = initial && initial.startsWith(input) && initial !== input;
|
|
46
|
-
let cursor = placeholder ? blinker(initial[input.length]) : reverse;
|
|
47
|
-
|
|
48
|
-
if (pos !== input.length && showCursor === true) {
|
|
49
|
-
output = input.slice(0, pos) + blinker(input[pos]) + input.slice(pos + 1);
|
|
50
|
-
cursor = '';
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (showCursor === false) {
|
|
54
|
-
cursor = '';
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (placeholder) {
|
|
58
|
-
let raw = prompt.styles.unstyle(output + cursor);
|
|
59
|
-
return output + cursor + style(initial.slice(raw.length));
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return output + cursor;
|
|
63
|
-
};
|