source: frontend/node_modules/prompts/dist/elements/autocomplete.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 13 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 8.5 KB
Line 
1'use strict';
2
3function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
4
5function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
6
7const color = require('kleur');
8
9const Prompt = require('./prompt');
10
11const _require = require('sisteransi'),
12 erase = _require.erase,
13 cursor = _require.cursor;
14
15const _require2 = require('../util'),
16 style = _require2.style,
17 clear = _require2.clear,
18 figures = _require2.figures,
19 wrap = _require2.wrap,
20 entriesToDisplay = _require2.entriesToDisplay;
21
22const getVal = (arr, i) => arr[i] && (arr[i].value || arr[i].title || arr[i]);
23
24const getTitle = (arr, i) => arr[i] && (arr[i].title || arr[i].value || arr[i]);
25
26const getIndex = (arr, valOrTitle) => {
27 const index = arr.findIndex(el => el.value === valOrTitle || el.title === valOrTitle);
28 return index > -1 ? index : undefined;
29};
30/**
31 * TextPrompt Base Element
32 * @param {Object} opts Options
33 * @param {String} opts.message Message
34 * @param {Array} opts.choices Array of auto-complete choices objects
35 * @param {Function} [opts.suggest] Filter function. Defaults to sort by title
36 * @param {Number} [opts.limit=10] Max number of results to show
37 * @param {Number} [opts.cursor=0] Cursor start position
38 * @param {String} [opts.style='default'] Render style
39 * @param {String} [opts.fallback] Fallback message - initial to default value
40 * @param {String} [opts.initial] Index of the default value
41 * @param {Boolean} [opts.clearFirst] The first ESCAPE keypress will clear the input
42 * @param {Stream} [opts.stdin] The Readable stream to listen to
43 * @param {Stream} [opts.stdout] The Writable stream to write readline data to
44 * @param {String} [opts.noMatches] The no matches found label
45 */
46
47
48class AutocompletePrompt extends Prompt {
49 constructor(opts = {}) {
50 super(opts);
51 this.msg = opts.message;
52 this.suggest = opts.suggest;
53 this.choices = opts.choices;
54 this.initial = typeof opts.initial === 'number' ? opts.initial : getIndex(opts.choices, opts.initial);
55 this.select = this.initial || opts.cursor || 0;
56 this.i18n = {
57 noMatches: opts.noMatches || 'no matches found'
58 };
59 this.fallback = opts.fallback || this.initial;
60 this.clearFirst = opts.clearFirst || false;
61 this.suggestions = [];
62 this.input = '';
63 this.limit = opts.limit || 10;
64 this.cursor = 0;
65 this.transform = style.render(opts.style);
66 this.scale = this.transform.scale;
67 this.render = this.render.bind(this);
68 this.complete = this.complete.bind(this);
69 this.clear = clear('', this.out.columns);
70 this.complete(this.render);
71 this.render();
72 }
73
74 set fallback(fb) {
75 this._fb = Number.isSafeInteger(parseInt(fb)) ? parseInt(fb) : fb;
76 }
77
78 get fallback() {
79 let choice;
80 if (typeof this._fb === 'number') choice = this.choices[this._fb];else if (typeof this._fb === 'string') choice = {
81 title: this._fb
82 };
83 return choice || this._fb || {
84 title: this.i18n.noMatches
85 };
86 }
87
88 moveSelect(i) {
89 this.select = i;
90 if (this.suggestions.length > 0) this.value = getVal(this.suggestions, i);else this.value = this.fallback.value;
91 this.fire();
92 }
93
94 complete(cb) {
95 var _this = this;
96
97 return _asyncToGenerator(function* () {
98 const p = _this.completing = _this.suggest(_this.input, _this.choices);
99
100 const suggestions = yield p;
101 if (_this.completing !== p) return;
102 _this.suggestions = suggestions.map((s, i, arr) => ({
103 title: getTitle(arr, i),
104 value: getVal(arr, i),
105 description: s.description
106 }));
107 _this.completing = false;
108 const l = Math.max(suggestions.length - 1, 0);
109
110 _this.moveSelect(Math.min(l, _this.select));
111
112 cb && cb();
113 })();
114 }
115
116 reset() {
117 this.input = '';
118 this.complete(() => {
119 this.moveSelect(this.initial !== void 0 ? this.initial : 0);
120 this.render();
121 });
122 this.render();
123 }
124
125 exit() {
126 if (this.clearFirst && this.input.length > 0) {
127 this.reset();
128 } else {
129 this.done = this.exited = true;
130 this.aborted = false;
131 this.fire();
132 this.render();
133 this.out.write('\n');
134 this.close();
135 }
136 }
137
138 abort() {
139 this.done = this.aborted = true;
140 this.exited = false;
141 this.fire();
142 this.render();
143 this.out.write('\n');
144 this.close();
145 }
146
147 submit() {
148 this.done = true;
149 this.aborted = this.exited = false;
150 this.fire();
151 this.render();
152 this.out.write('\n');
153 this.close();
154 }
155
156 _(c, key) {
157 let s1 = this.input.slice(0, this.cursor);
158 let s2 = this.input.slice(this.cursor);
159 this.input = `${s1}${c}${s2}`;
160 this.cursor = s1.length + 1;
161 this.complete(this.render);
162 this.render();
163 }
164
165 delete() {
166 if (this.cursor === 0) return this.bell();
167 let s1 = this.input.slice(0, this.cursor - 1);
168 let s2 = this.input.slice(this.cursor);
169 this.input = `${s1}${s2}`;
170 this.complete(this.render);
171 this.cursor = this.cursor - 1;
172 this.render();
173 }
174
175 deleteForward() {
176 if (this.cursor * this.scale >= this.rendered.length) return this.bell();
177 let s1 = this.input.slice(0, this.cursor);
178 let s2 = this.input.slice(this.cursor + 1);
179 this.input = `${s1}${s2}`;
180 this.complete(this.render);
181 this.render();
182 }
183
184 first() {
185 this.moveSelect(0);
186 this.render();
187 }
188
189 last() {
190 this.moveSelect(this.suggestions.length - 1);
191 this.render();
192 }
193
194 up() {
195 if (this.select === 0) {
196 this.moveSelect(this.suggestions.length - 1);
197 } else {
198 this.moveSelect(this.select - 1);
199 }
200
201 this.render();
202 }
203
204 down() {
205 if (this.select === this.suggestions.length - 1) {
206 this.moveSelect(0);
207 } else {
208 this.moveSelect(this.select + 1);
209 }
210
211 this.render();
212 }
213
214 next() {
215 if (this.select === this.suggestions.length - 1) {
216 this.moveSelect(0);
217 } else this.moveSelect(this.select + 1);
218
219 this.render();
220 }
221
222 nextPage() {
223 this.moveSelect(Math.min(this.select + this.limit, this.suggestions.length - 1));
224 this.render();
225 }
226
227 prevPage() {
228 this.moveSelect(Math.max(this.select - this.limit, 0));
229 this.render();
230 }
231
232 left() {
233 if (this.cursor <= 0) return this.bell();
234 this.cursor = this.cursor - 1;
235 this.render();
236 }
237
238 right() {
239 if (this.cursor * this.scale >= this.rendered.length) return this.bell();
240 this.cursor = this.cursor + 1;
241 this.render();
242 }
243
244 renderOption(v, hovered, isStart, isEnd) {
245 let desc;
246 let prefix = isStart ? figures.arrowUp : isEnd ? figures.arrowDown : ' ';
247 let title = hovered ? color.cyan().underline(v.title) : v.title;
248 prefix = (hovered ? color.cyan(figures.pointer) + ' ' : ' ') + prefix;
249
250 if (v.description) {
251 desc = ` - ${v.description}`;
252
253 if (prefix.length + title.length + desc.length >= this.out.columns || v.description.split(/\r?\n/).length > 1) {
254 desc = '\n' + wrap(v.description, {
255 margin: 3,
256 width: this.out.columns
257 });
258 }
259 }
260
261 return prefix + ' ' + title + color.gray(desc || '');
262 }
263
264 render() {
265 if (this.closed) return;
266 if (this.firstRender) this.out.write(cursor.hide);else this.out.write(clear(this.outputText, this.out.columns));
267 super.render();
268
269 let _entriesToDisplay = entriesToDisplay(this.select, this.choices.length, this.limit),
270 startIndex = _entriesToDisplay.startIndex,
271 endIndex = _entriesToDisplay.endIndex;
272
273 this.outputText = [style.symbol(this.done, this.aborted, this.exited), color.bold(this.msg), style.delimiter(this.completing), this.done && this.suggestions[this.select] ? this.suggestions[this.select].title : this.rendered = this.transform.render(this.input)].join(' ');
274
275 if (!this.done) {
276 const suggestions = this.suggestions.slice(startIndex, endIndex).map((item, i) => this.renderOption(item, this.select === i + startIndex, i === 0 && startIndex > 0, i + startIndex === endIndex - 1 && endIndex < this.choices.length)).join('\n');
277 this.outputText += `\n` + (suggestions || color.gray(this.fallback.title));
278 }
279
280 this.out.write(erase.line + cursor.to(0) + this.outputText);
281 }
282
283}
284
285module.exports = AutocompletePrompt;
Note: See TracBrowser for help on using the repository browser.