.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / enquirer / lib / prompts / form.js
1 'use strict';
2
3 const colors = require('ansi-colors');
4 const SelectPrompt = require('./select');
5 const placeholder = require('../placeholder');
6
7 class FormPrompt extends SelectPrompt {
8   constructor(options) {
9     super({ ...options, multiple: true });
10     this.type = 'form';
11     this.initial = this.options.initial;
12     this.align = [this.options.align, 'right'].find(v => v != null);
13     this.emptyError = '';
14     this.values = {};
15   }
16
17   async reset(first) {
18     await super.reset();
19     if (first === true) this._index = this.index;
20     this.index = this._index;
21     this.values = {};
22     this.choices.forEach(choice => choice.reset && choice.reset());
23     return this.render();
24   }
25
26   dispatch(char) {
27     return !!char && this.append(char);
28   }
29
30   append(char) {
31     let choice = this.focused;
32     if (!choice) return this.alert();
33     let { cursor, input } = choice;
34     choice.value = choice.input = input.slice(0, cursor) + char + input.slice(cursor);
35     choice.cursor++;
36     return this.render();
37   }
38
39   delete() {
40     let choice = this.focused;
41     if (!choice || choice.cursor <= 0) return this.alert();
42     let { cursor, input } = choice;
43     choice.value = choice.input = input.slice(0, cursor - 1) + input.slice(cursor);
44     choice.cursor--;
45     return this.render();
46   }
47
48   deleteForward() {
49     let choice = this.focused;
50     if (!choice) return this.alert();
51     let { cursor, input } = choice;
52     if (input[cursor] === void 0) return this.alert();
53     let str = `${input}`.slice(0, cursor) + `${input}`.slice(cursor + 1);
54     choice.value = choice.input = str;
55     return this.render();
56   }
57
58   right() {
59     let choice = this.focused;
60     if (!choice) return this.alert();
61     if (choice.cursor >= choice.input.length) return this.alert();
62     choice.cursor++;
63     return this.render();
64   }
65
66   left() {
67     let choice = this.focused;
68     if (!choice) return this.alert();
69     if (choice.cursor <= 0) return this.alert();
70     choice.cursor--;
71     return this.render();
72   }
73
74   space(ch, key) {
75     return this.dispatch(ch, key);
76   }
77
78   number(ch, key) {
79     return this.dispatch(ch, key);
80   }
81
82   next() {
83     let ch = this.focused;
84     if (!ch) return this.alert();
85     let { initial, input } = ch;
86     if (initial && initial.startsWith(input) && input !== initial) {
87       ch.value = ch.input = initial;
88       ch.cursor = ch.value.length;
89       return this.render();
90     }
91     return super.next();
92   }
93
94   prev() {
95     let ch = this.focused;
96     if (!ch) return this.alert();
97     if (ch.cursor === 0) return super.prev();
98     ch.value = ch.input = '';
99     ch.cursor = 0;
100     return this.render();
101   }
102
103   separator() {
104     return '';
105   }
106
107   format(value) {
108     return !this.state.submitted ? super.format(value) : '';
109   }
110
111   pointer() {
112     return '';
113   }
114
115   indicator(choice) {
116     return choice.input ? '⦿' : '⊙';
117   }
118
119   async choiceSeparator(choice, i) {
120     let sep = await this.resolve(choice.separator, this.state, choice, i) || ':';
121     return sep ? ' ' + this.styles.disabled(sep) : '';
122   }
123
124   async renderChoice(choice, i) {
125     await this.onChoice(choice, i);
126
127     let { state, styles } = this;
128     let { cursor, initial = '', name, hint, input = '' } = choice;
129     let { muted, submitted, primary, danger } = styles;
130
131     let help = hint;
132     let focused = this.index === i;
133     let validate = choice.validate || (() => true);
134     let sep = await this.choiceSeparator(choice, i);
135     let msg = choice.message;
136
137     if (this.align === 'right') msg = msg.padStart(this.longest + 1, ' ');
138     if (this.align === 'left') msg = msg.padEnd(this.longest + 1, ' ');
139
140     // re-populate the form values (answers) object
141     let value = this.values[name] = (input || initial);
142     let color = input ? 'success' : 'dark';
143
144     if ((await validate.call(choice, value, this.state)) !== true) {
145       color = 'danger';
146     }
147
148     let style = styles[color];
149     let indicator = style(await this.indicator(choice, i)) + (choice.pad || '');
150
151     let indent = this.indent(choice);
152     let line = () => [indent, indicator, msg + sep, input, help].filter(Boolean).join(' ');
153
154     if (state.submitted) {
155       msg = colors.unstyle(msg);
156       input = submitted(input);
157       help = '';
158       return line();
159     }
160
161     if (choice.format) {
162       input = await choice.format.call(this, input, choice, i);
163     } else {
164       let color = this.styles.muted;
165       let options = { input, initial, pos: cursor, showCursor: focused, color };
166       input = placeholder(this, options);
167     }
168
169     if (!this.isValue(input)) {
170       input = this.styles.muted(this.symbols.ellipsis);
171     }
172
173     if (choice.result) {
174       this.values[name] = await choice.result.call(this, value, choice, i);
175     }
176
177     if (focused) {
178       msg = primary(msg);
179     }
180
181     if (choice.error) {
182       input += (input ? ' ' : '') + danger(choice.error.trim());
183     } else if (choice.hint) {
184       input += (input ? ' ' : '') + muted(choice.hint.trim());
185     }
186
187     return line();
188   }
189
190   async submit() {
191     this.value = this.values;
192     return super.base.submit.call(this);
193   }
194 }
195
196 module.exports = FormPrompt;