source: frontend/node_modules/prompts/lib/elements/text.js

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

Fix frontend appearance

  • Property mode set to 100644
File size: 5.2 KB
RevLine 
[9af201e]1const color = require('kleur');
2const Prompt = require('./prompt');
3const { erase, cursor } = require('sisteransi');
4const { style, clear, lines, figures } = require('../util');
5
6/**
7 * TextPrompt Base Element
8 * @param {Object} opts Options
9 * @param {String} opts.message Message
10 * @param {String} [opts.style='default'] Render style
11 * @param {String} [opts.initial] Default value
12 * @param {Function} [opts.validate] Validate function
13 * @param {Stream} [opts.stdin] The Readable stream to listen to
14 * @param {Stream} [opts.stdout] The Writable stream to write readline data to
15 * @param {String} [opts.error] The invalid error label
16 */
17class TextPrompt extends Prompt {
18 constructor(opts={}) {
19 super(opts);
20 this.transform = style.render(opts.style);
21 this.scale = this.transform.scale;
22 this.msg = opts.message;
23 this.initial = opts.initial || ``;
24 this.validator = opts.validate || (() => true);
25 this.value = ``;
26 this.errorMsg = opts.error || `Please Enter A Valid Value`;
27 this.cursor = Number(!!this.initial);
28 this.cursorOffset = 0;
29 this.clear = clear(``, this.out.columns);
30 this.render();
31 }
32
33 set value(v) {
34 if (!v && this.initial) {
35 this.placeholder = true;
36 this.rendered = color.gray(this.transform.render(this.initial));
37 } else {
38 this.placeholder = false;
39 this.rendered = this.transform.render(v);
40 }
41 this._value = v;
42 this.fire();
43 }
44
45 get value() {
46 return this._value;
47 }
48
49 reset() {
50 this.value = ``;
51 this.cursor = Number(!!this.initial);
52 this.cursorOffset = 0;
53 this.fire();
54 this.render();
55 }
56
57 exit() {
58 this.abort();
59 }
60
61 abort() {
62 this.value = this.value || this.initial;
63 this.done = this.aborted = true;
64 this.error = false;
65 this.red = false;
66 this.fire();
67 this.render();
68 this.out.write('\n');
69 this.close();
70 }
71
72 async validate() {
73 let valid = await this.validator(this.value);
74 if (typeof valid === `string`) {
75 this.errorMsg = valid;
76 valid = false;
77 }
78 this.error = !valid;
79 }
80
81 async submit() {
82 this.value = this.value || this.initial;
83 this.cursorOffset = 0;
84 this.cursor = this.rendered.length;
85 await this.validate();
86 if (this.error) {
87 this.red = true;
88 this.fire();
89 this.render();
90 return;
91 }
92 this.done = true;
93 this.aborted = false;
94 this.fire();
95 this.render();
96 this.out.write('\n');
97 this.close();
98 }
99
100 next() {
101 if (!this.placeholder) return this.bell();
102 this.value = this.initial;
103 this.cursor = this.rendered.length;
104 this.fire();
105 this.render();
106 }
107
108 moveCursor(n) {
109 if (this.placeholder) return;
110 this.cursor = this.cursor+n;
111 this.cursorOffset += n;
112 }
113
114 _(c, key) {
115 let s1 = this.value.slice(0, this.cursor);
116 let s2 = this.value.slice(this.cursor);
117 this.value = `${s1}${c}${s2}`;
118 this.red = false;
119 this.cursor = this.placeholder ? 0 : s1.length+1;
120 this.render();
121 }
122
123 delete() {
124 if (this.isCursorAtStart()) return this.bell();
125 let s1 = this.value.slice(0, this.cursor-1);
126 let s2 = this.value.slice(this.cursor);
127 this.value = `${s1}${s2}`;
128 this.red = false;
129 if (this.isCursorAtStart()) {
130 this.cursorOffset = 0
131 } else {
132 this.cursorOffset++;
133 this.moveCursor(-1);
134 }
135 this.render();
136 }
137
138 deleteForward() {
139 if(this.cursor*this.scale >= this.rendered.length || this.placeholder) return this.bell();
140 let s1 = this.value.slice(0, this.cursor);
141 let s2 = this.value.slice(this.cursor+1);
142 this.value = `${s1}${s2}`;
143 this.red = false;
144 if (this.isCursorAtEnd()) {
145 this.cursorOffset = 0;
146 } else {
147 this.cursorOffset++;
148 }
149 this.render();
150 }
151
152 first() {
153 this.cursor = 0;
154 this.render();
155 }
156
157 last() {
158 this.cursor = this.value.length;
159 this.render();
160 }
161
162 left() {
163 if (this.cursor <= 0 || this.placeholder) return this.bell();
164 this.moveCursor(-1);
165 this.render();
166 }
167
168 right() {
169 if (this.cursor*this.scale >= this.rendered.length || this.placeholder) return this.bell();
170 this.moveCursor(1);
171 this.render();
172 }
173
174 isCursorAtStart() {
175 return this.cursor === 0 || (this.placeholder && this.cursor === 1);
176 }
177
178 isCursorAtEnd() {
179 return this.cursor === this.rendered.length || (this.placeholder && this.cursor === this.rendered.length + 1)
180 }
181
182 render() {
183 if (this.closed) return;
184 if (!this.firstRender) {
185 if (this.outputError)
186 this.out.write(cursor.down(lines(this.outputError, this.out.columns) - 1) + clear(this.outputError, this.out.columns));
187 this.out.write(clear(this.outputText, this.out.columns));
188 }
189 super.render();
190 this.outputError = '';
191
192 this.outputText = [
193 style.symbol(this.done, this.aborted),
194 color.bold(this.msg),
195 style.delimiter(this.done),
196 this.red ? color.red(this.rendered) : this.rendered
197 ].join(` `);
198
199 if (this.error) {
200 this.outputError += this.errorMsg.split(`\n`)
201 .reduce((a, l, i) => a + `\n${i ? ' ' : figures.pointerSmall} ${color.red().italic(l)}`, ``);
202 }
203
204 this.out.write(erase.line + cursor.to(0) + this.outputText + cursor.save + this.outputError + cursor.restore + cursor.move(this.cursorOffset, 0));
205 }
206}
207
208module.exports = TextPrompt;
Note: See TracBrowser for help on using the repository browser.