UNPKG

8.8 kBJavaScriptView Raw
1'use strict';
2const $ = exports;
3const el = require('./elements');
4const noop = v => v;
5
6function 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
183const 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};