Actualizacion maquina principal
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / inquirer / lib / prompts / expand.js
1 'use strict';
2 /**
3  * `rawlist` type prompt
4  */
5
6 var _ = {
7   uniq: require('lodash/uniq'),
8   isString: require('lodash/isString'),
9   isNumber: require('lodash/isNumber'),
10   findIndex: require('lodash/findIndex'),
11 };
12 var chalk = require('chalk');
13 var { map, takeUntil } = require('rxjs/operators');
14 var Base = require('./base');
15 var Separator = require('../objects/separator');
16 var observe = require('../utils/events');
17 var Paginator = require('../utils/paginator');
18
19 class ExpandPrompt extends Base {
20   constructor(questions, rl, answers) {
21     super(questions, rl, answers);
22
23     if (!this.opt.choices) {
24       this.throwParamError('choices');
25     }
26
27     this.validateChoices(this.opt.choices);
28
29     // Add the default `help` (/expand) option
30     this.opt.choices.push({
31       key: 'h',
32       name: 'Help, list all options',
33       value: 'help',
34     });
35
36     this.opt.validate = (choice) => {
37       if (choice == null) {
38         return 'Please enter a valid command';
39       }
40
41       return choice !== 'help';
42     };
43
44     // Setup the default string (capitalize the default key)
45     this.opt.default = this.generateChoicesString(this.opt.choices, this.opt.default);
46
47     this.paginator = new Paginator(this.screen);
48   }
49
50   /**
51    * Start the Inquiry session
52    * @param  {Function} cb      Callback when prompt is done
53    * @return {this}
54    */
55
56   _run(cb) {
57     this.done = cb;
58
59     // Save user answer and update prompt to show selected option.
60     var events = observe(this.rl);
61     var validation = this.handleSubmitEvents(
62       events.line.pipe(map(this.getCurrentValue.bind(this)))
63     );
64     validation.success.forEach(this.onSubmit.bind(this));
65     validation.error.forEach(this.onError.bind(this));
66     this.keypressObs = events.keypress
67       .pipe(takeUntil(validation.success))
68       .forEach(this.onKeypress.bind(this));
69
70     // Init the prompt
71     this.render();
72
73     return this;
74   }
75
76   /**
77    * Render the prompt to screen
78    * @return {ExpandPrompt} self
79    */
80
81   render(error, hint) {
82     var message = this.getQuestion();
83     var bottomContent = '';
84
85     if (this.status === 'answered') {
86       message += chalk.cyan(this.answer);
87     } else if (this.status === 'expanded') {
88       var choicesStr = renderChoices(this.opt.choices, this.selectedKey);
89       message += this.paginator.paginate(choicesStr, this.selectedKey, this.opt.pageSize);
90       message += '\n  Answer: ';
91     }
92
93     message += this.rl.line;
94
95     if (error) {
96       bottomContent = chalk.red('>> ') + error;
97     }
98
99     if (hint) {
100       bottomContent = chalk.cyan('>> ') + hint;
101     }
102
103     this.screen.render(message, bottomContent);
104   }
105
106   getCurrentValue(input) {
107     if (!input) {
108       input = this.rawDefault;
109     }
110
111     var selected = this.opt.choices.where({ key: input.toLowerCase().trim() })[0];
112     if (!selected) {
113       return null;
114     }
115
116     return selected.value;
117   }
118
119   /**
120    * Generate the prompt choices string
121    * @return {String}  Choices string
122    */
123
124   getChoices() {
125     var output = '';
126
127     this.opt.choices.forEach((choice) => {
128       output += '\n  ';
129
130       if (choice.type === 'separator') {
131         output += ' ' + choice;
132         return;
133       }
134
135       var choiceStr = choice.key + ') ' + choice.name;
136       if (this.selectedKey === choice.key) {
137         choiceStr = chalk.cyan(choiceStr);
138       }
139
140       output += choiceStr;
141     });
142
143     return output;
144   }
145
146   onError(state) {
147     if (state.value === 'help') {
148       this.selectedKey = '';
149       this.status = 'expanded';
150       this.render();
151       return;
152     }
153
154     this.render(state.isValid);
155   }
156
157   /**
158    * When user press `enter` key
159    */
160
161   onSubmit(state) {
162     this.status = 'answered';
163     var choice = this.opt.choices.where({ value: state.value })[0];
164     this.answer = choice.short || choice.name;
165
166     // Re-render prompt
167     this.render();
168     this.screen.done();
169     this.done(state.value);
170   }
171
172   /**
173    * When user press a key
174    */
175
176   onKeypress() {
177     this.selectedKey = this.rl.line.toLowerCase();
178     var selected = this.opt.choices.where({ key: this.selectedKey })[0];
179     if (this.status === 'expanded') {
180       this.render();
181     } else {
182       this.render(null, selected ? selected.name : null);
183     }
184   }
185
186   /**
187    * Validate the choices
188    * @param {Array} choices
189    */
190
191   validateChoices(choices) {
192     var formatError;
193     var errors = [];
194     var keymap = {};
195     choices.filter(Separator.exclude).forEach((choice) => {
196       if (!choice.key || choice.key.length !== 1) {
197         formatError = true;
198       }
199
200       if (keymap[choice.key]) {
201         errors.push(choice.key);
202       }
203
204       keymap[choice.key] = true;
205       choice.key = String(choice.key).toLowerCase();
206     });
207
208     if (formatError) {
209       throw new Error(
210         'Format error: `key` param must be a single letter and is required.'
211       );
212     }
213
214     if (keymap.h) {
215       throw new Error(
216         'Reserved key error: `key` param cannot be `h` - this value is reserved.'
217       );
218     }
219
220     if (errors.length) {
221       throw new Error(
222         'Duplicate key error: `key` param must be unique. Duplicates: ' +
223           _.uniq(errors).join(', ')
224       );
225     }
226   }
227
228   /**
229    * Generate a string out of the choices keys
230    * @param  {Array}  choices
231    * @param  {Number|String} default - the choice index or name to capitalize
232    * @return {String} The rendered choices key string
233    */
234   generateChoicesString(choices, defaultChoice) {
235     var defIndex = choices.realLength - 1;
236     if (_.isNumber(defaultChoice) && this.opt.choices.getChoice(defaultChoice)) {
237       defIndex = defaultChoice;
238     } else if (_.isString(defaultChoice)) {
239       let index = _.findIndex(
240         choices.realChoices,
241         ({ value }) => value === defaultChoice
242       );
243       defIndex = index === -1 ? defIndex : index;
244     }
245
246     var defStr = this.opt.choices.pluck('key');
247     this.rawDefault = defStr[defIndex];
248     defStr[defIndex] = String(defStr[defIndex]).toUpperCase();
249     return defStr.join('');
250   }
251 }
252
253 /**
254  * Function for rendering checkbox choices
255  * @param  {String} pointer Selected key
256  * @return {String}         Rendered content
257  */
258
259 function renderChoices(choices, pointer) {
260   var output = '';
261
262   choices.forEach((choice) => {
263     output += '\n  ';
264
265     if (choice.type === 'separator') {
266       output += ' ' + choice;
267       return;
268     }
269
270     var choiceStr = choice.key + ') ' + choice.name;
271     if (pointer === choice.key) {
272       choiceStr = chalk.cyan(choiceStr);
273     }
274
275     output += choiceStr;
276   });
277
278   return output;
279 }
280
281 module.exports = ExpandPrompt;