spyne-cli 0.3.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-cli.js +56 -0
- package/index.js +14 -0
- package/lib/ansi.js +116 -0
- package/lib/combos.js +75 -0
- package/lib/completer.js +52 -0
- package/lib/interpolate.js +266 -0
- package/lib/keypress.js +243 -0
- package/lib/placeholder.js +63 -0
- package/lib/prompt.js +485 -0
- package/lib/prompts/autocomplete.js +113 -0
- package/lib/prompts/basicauth.js +41 -0
- package/lib/prompts/confirm.js +13 -0
- package/lib/prompts/editable.js +136 -0
- package/lib/prompts/form.js +196 -0
- package/lib/prompts/index.js +28 -0
- package/lib/prompts/input.js +55 -0
- package/lib/prompts/invisible.js +11 -0
- package/lib/prompts/list.js +36 -0
- package/lib/prompts/multiselect.js +11 -0
- package/lib/prompts/numeral.js +1 -0
- package/lib/prompts/password.js +18 -0
- package/lib/prompts/quiz.js +37 -0
- package/lib/prompts/scale.js +237 -0
- package/lib/prompts/select.js +139 -0
- package/lib/prompts/snippet.js +185 -0
- package/lib/prompts/sort.js +37 -0
- package/lib/prompts/survey.js +163 -0
- package/lib/prompts/text.js +1 -0
- package/lib/prompts/toggle.js +109 -0
- package/lib/render.js +33 -0
- package/lib/roles.js +46 -0
- package/lib/state.js +69 -0
- package/lib/styles.js +144 -0
- package/lib/symbols.js +66 -0
- package/lib/theme.js +11 -0
- package/lib/timer.js +38 -0
- package/lib/types/array.js +658 -0
- package/lib/types/auth.js +29 -0
- package/lib/types/boolean.js +88 -0
- package/lib/types/index.js +7 -0
- package/lib/types/number.js +86 -0
- package/lib/types/string.js +185 -0
- package/lib/utils.js +268 -0
- package/package.json +45 -0
- package/src/app/channels/.gitkeep +0 -0
- package/src/app/components/.gitkeep +0 -0
- package/src/app/traits/.gitkeep +0 -0
- package/src/spyne-file-prompt.js +63 -0
- package/src/spyne-template-prompts.js +171 -0
- package/src/templates/generate-file-string.js +131 -0
- package/src/templates/generate-prompt-input-fields.js +256 -0
- package/src/templates/generate-prompt-input-object.js +46 -0
- package/src/templates/generate-prompt-output.js +109 -0
- package/src/ui.js +16 -0
- package/src/utils/color-utils.js +36 -0
- package/src/utils/error-logger.js +15 -0
- package/src/utils/file-utils.js +69 -0
- package/tests/generate-file-prompt.test.js +47 -0
- package/tests/generate-file-string.test.js +68 -0
- package/tests/generate-prompt-input-fields-methods.test.js +178 -0
- package/tests/generate-prompt-input-fields.test.js +181 -0
- package/tests/generate-prompt-input-object.test.js +41 -0
- package/tests/generate-prompt-output.test.js +60 -0
- package/tests/index.test.js +13 -0
- package/tests/mocks/answers.js +33 -0
- package/tests/mocks/answers.json +33 -0
- package/tests/mocks/enquirer-data.js +411 -0
- package/tests/mocks/enquirer-data.json +409 -0
- package/tests/utils/file-utils.test.js +70 -0
package/lib/keypress.js
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
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;
|
|
@@ -0,0 +1,63 @@
|
|
|
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
|
+
};
|