1 | ;
|
2 | const $ = exports;
|
3 | const el = require('./elements');
|
4 | const noop = v => v;
|
5 |
|
6 | function toPrompt(type, args, opts={}) {
|
7 | return new Promise((res, rej) => {
|
8 | const p = new el[type](args);
|
9 | const onAbort = opts.onAbort || noop;
|
10 | const onSubmit = opts.onSubmit || noop;
|
11 | const onExit = opts.onExit || noop;
|
12 | p.on('state', args.onState || noop);
|
13 | p.on('submit', x => res(onSubmit(x)));
|
14 | p.on('exit', x => res(onExit(x)));
|
15 | p.on('abort', x => rej(onAbort(x)));
|
16 | });
|
17 | }
|
18 |
|
19 | /**
|
20 | * Text prompt
|
21 | * @param {string} args.message Prompt message to display
|
22 | * @param {string} [args.initial] Default string value
|
23 | * @param {string} [args.style="default"] Render style ('default', 'password', 'invisible')
|
24 | * @param {function} [args.onState] On state change callback
|
25 | * @param {function} [args.validate] Function to validate user input
|
26 | * @param {Stream} [args.stdin] The Readable stream to listen to
|
27 | * @param {Stream} [args.stdout] The Writable stream to write readline data to
|
28 | * @returns {Promise} Promise with user input
|
29 | */
|
30 | $.text = args => toPrompt('TextPrompt', args);
|
31 |
|
32 | /**
|
33 | * Password prompt with masked input
|
34 | * @param {string} args.message Prompt message to display
|
35 | * @param {string} [args.initial] Default string value
|
36 | * @param {function} [args.onState] On state change callback
|
37 | * @param {function} [args.validate] Function to validate user input
|
38 | * @param {Stream} [args.stdin] The Readable stream to listen to
|
39 | * @param {Stream} [args.stdout] The Writable stream to write readline data to
|
40 | * @returns {Promise} Promise with user input
|
41 | */
|
42 | $.password = args => {
|
43 | args.style = 'password';
|
44 | return $.text(args);
|
45 | };
|
46 |
|
47 | /**
|
48 | * Prompt where input is invisible, like sudo
|
49 | * @param {string} args.message Prompt message to display
|
50 | * @param {string} [args.initial] Default string value
|
51 | * @param {function} [args.onState] On state change callback
|
52 | * @param {function} [args.validate] Function to validate user input
|
53 | * @param {Stream} [args.stdin] The Readable stream to listen to
|
54 | * @param {Stream} [args.stdout] The Writable stream to write readline data to
|
55 | * @returns {Promise} Promise with user input
|
56 | */
|
57 | $.invisible = args => {
|
58 | args.style = 'invisible';
|
59 | return $.text(args);
|
60 | };
|
61 |
|
62 | /**
|
63 | * Number prompt
|
64 | * @param {string} args.message Prompt message to display
|
65 | * @param {number} args.initial Default number value
|
66 | * @param {function} [args.onState] On state change callback
|
67 | * @param {number} [args.max] Max value
|
68 | * @param {number} [args.min] Min value
|
69 | * @param {string} [args.style="default"] Render style ('default', 'password', 'invisible')
|
70 | * @param {Boolean} [opts.float=false] Parse input as floats
|
71 | * @param {Number} [opts.round=2] Round floats to x decimals
|
72 | * @param {Number} [opts.increment=1] Number to increment by when using arrow-keys
|
73 | * @param {function} [args.validate] Function to validate user input
|
74 | * @param {Stream} [args.stdin] The Readable stream to listen to
|
75 | * @param {Stream} [args.stdout] The Writable stream to write readline data to
|
76 | * @returns {Promise} Promise with user input
|
77 | */
|
78 | $.number = args => toPrompt('NumberPrompt', args);
|
79 |
|
80 | /**
|
81 | * Date prompt
|
82 | * @param {string} args.message Prompt message to display
|
83 | * @param {number} args.initial Default number value
|
84 | * @param {function} [args.onState] On state change callback
|
85 | * @param {number} [args.max] Max value
|
86 | * @param {number} [args.min] Min value
|
87 | * @param {string} [args.style="default"] Render style ('default', 'password', 'invisible')
|
88 | * @param {Boolean} [opts.float=false] Parse input as floats
|
89 | * @param {Number} [opts.round=2] Round floats to x decimals
|
90 | * @param {Number} [opts.increment=1] Number to increment by when using arrow-keys
|
91 | * @param {function} [args.validate] Function to validate user input
|
92 | * @param {Stream} [args.stdin] The Readable stream to listen to
|
93 | * @param {Stream} [args.stdout] The Writable stream to write readline data to
|
94 | * @returns {Promise} Promise with user input
|
95 | */
|
96 | $.date = args => toPrompt('DatePrompt', args);
|
97 |
|
98 | /**
|
99 | * Classic yes/no prompt
|
100 | * @param {string} args.message Prompt message to display
|
101 | * @param {boolean} [args.initial=false] Default value
|
102 | * @param {function} [args.onState] On state change callback
|
103 | * @param {Stream} [args.stdin] The Readable stream to listen to
|
104 | * @param {Stream} [args.stdout] The Writable stream to write readline data to
|
105 | * @returns {Promise} Promise with user input
|
106 | */
|
107 | $.confirm = args => toPrompt('ConfirmPrompt', args);
|
108 |
|
109 | /**
|
110 | * List prompt, split intput string by `seperator`
|
111 | * @param {string} args.message Prompt message to display
|
112 | * @param {string} [args.initial] Default string value
|
113 | * @param {string} [args.style="default"] Render style ('default', 'password', 'invisible')
|
114 | * @param {string} [args.separator] String separator
|
115 | * @param {function} [args.onState] On state change callback
|
116 | * @param {Stream} [args.stdin] The Readable stream to listen to
|
117 | * @param {Stream} [args.stdout] The Writable stream to write readline data to
|
118 | * @returns {Promise} Promise with user input, in form of an `Array`
|
119 | */
|
120 | $.list = args => {
|
121 | const sep = args.separator || ',';
|
122 | return toPrompt('TextPrompt', args, {
|
123 | onSubmit: str => str.split(sep).map(s => s.trim())
|
124 | });
|
125 | };
|
126 |
|
127 | /**
|
128 | * Toggle/switch prompt
|
129 | * @param {string} args.message Prompt message to display
|
130 | * @param {boolean} [args.initial=false] Default value
|
131 | * @param {string} [args.active="on"] Text for `active` state
|
132 | * @param {string} [args.inactive="off"] Text for `inactive` state
|
133 | * @param {function} [args.onState] On state change callback
|
134 | * @param {Stream} [args.stdin] The Readable stream to listen to
|
135 | * @param {Stream} [args.stdout] The Writable stream to write readline data to
|
136 | * @returns {Promise} Promise with user input
|
137 | */
|
138 | $.toggle = args => toPrompt('TogglePrompt', args);
|
139 |
|
140 | /**
|
141 | * Interactive select prompt
|
142 | * @param {string} args.message Prompt message to display
|
143 | * @param {Array} args.choices Array of choices objects `[{ title, value }, ...]`
|
144 | * @param {number} [args.initial] Index of default value
|
145 | * @param {String} [args.hint] Hint to display
|
146 | * @param {function} [args.onState] On state change callback
|
147 | * @param {Stream} [args.stdin] The Readable stream to listen to
|
148 | * @param {Stream} [args.stdout] The Writable stream to write readline data to
|
149 | * @returns {Promise} Promise with user input
|
150 | */
|
151 | $.select = args => toPrompt('SelectPrompt', args);
|
152 |
|
153 | /**
|
154 | * Interactive multi-select / autocompleteMultiselect prompt
|
155 | * @param {string} args.message Prompt message to display
|
156 | * @param {Array} args.choices Array of choices objects `[{ title, value, [selected] }, ...]`
|
157 | * @param {number} [args.max] Max select
|
158 | * @param {string} [args.hint] Hint to display user
|
159 | * @param {Number} [args.cursor=0] Cursor start position
|
160 | * @param {function} [args.onState] On state change callback
|
161 | * @param {Stream} [args.stdin] The Readable stream to listen to
|
162 | * @param {Stream} [args.stdout] The Writable stream to write readline data to
|
163 | * @returns {Promise} Promise with user input
|
164 | */
|
165 | $.multiselect = args => {
|
166 | args.choices = [].concat(args.choices || []);
|
167 | const toSelected = items => items.filter(item => item.selected).map(item => item.value);
|
168 | return toPrompt('MultiselectPrompt', args, {
|
169 | onAbort: toSelected,
|
170 | onSubmit: toSelected
|
171 | });
|
172 | };
|
173 |
|
174 | $.autocompleteMultiselect = args => {
|
175 | args.choices = [].concat(args.choices || []);
|
176 | const toSelected = items => items.filter(item => item.selected).map(item => item.value);
|
177 | return toPrompt('AutocompleteMultiselectPrompt', args, {
|
178 | onAbort: toSelected,
|
179 | onSubmit: toSelected
|
180 | });
|
181 | };
|
182 |
|
183 | const byTitle = (input, choices) => Promise.resolve(
|
184 | choices.filter(item => item.title.slice(0, input.length).toLowerCase() === input.toLowerCase())
|
185 | );
|
186 |
|
187 | /**
|
188 | * Interactive auto-complete prompt
|
189 | * @param {string} args.message Prompt message to display
|
190 | * @param {Array} args.choices Array of auto-complete choices objects `[{ title, value }, ...]`
|
191 | * @param {Function} [args.suggest] Function to filter results based on user input. Defaults to sort by `title`
|
192 | * @param {number} [args.limit=10] Max number of results to show
|
193 | * @param {string} [args.style="default"] Render style ('default', 'password', 'invisible')
|
194 | * @param {String} [args.initial] Index of the default value
|
195 | * @param {boolean} [opts.clearFirst] The first ESCAPE keypress will clear the input
|
196 | * @param {String} [args.fallback] Fallback message - defaults to initial value
|
197 | * @param {function} [args.onState] On state change callback
|
198 | * @param {Stream} [args.stdin] The Readable stream to listen to
|
199 | * @param {Stream} [args.stdout] The Writable stream to write readline data to
|
200 | * @returns {Promise} Promise with user input
|
201 | */
|
202 | $.autocomplete = args => {
|
203 | args.suggest = args.suggest || byTitle;
|
204 | args.choices = [].concat(args.choices || []);
|
205 | return toPrompt('AutocompletePrompt', args);
|
206 | };
|