Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / inquirer / lib / prompts / rawlist.js
1 'use strict';
2 /**
3  * `rawlist` type prompt
4  */
5
6 var _ = {
7   extend: require('lodash/extend'),
8   isNumber: require('lodash/isNumber'),
9   findIndex: require('lodash/findIndex'),
10 };
11 var chalk = require('chalk');
12 var { map, takeUntil } = require('rxjs/operators');
13 var Base = require('./base');
14 var Separator = require('../objects/separator');
15 var observe = require('../utils/events');
16 var Paginator = require('../utils/paginator');
17 var incrementListIndex = require('../utils/incrementListIndex');
18
19 class RawListPrompt 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.opt.validChoices = this.opt.choices.filter(Separator.exclude);
28
29     this.selected = 0;
30     this.rawDefault = 0;
31
32     _.extend(this.opt, {
33       validate: function (val) {
34         return val != null;
35       },
36     });
37
38     var def = this.opt.default;
39     if (_.isNumber(def) && def >= 0 && def < this.opt.choices.realLength) {
40       this.selected = def;
41       this.rawDefault = def;
42     } else if (!_.isNumber(def) && def != null) {
43       let index = _.findIndex(this.opt.choices.realChoices, ({ value }) => value === def);
44       let safeIndex = Math.max(index, 0);
45       this.selected = safeIndex;
46       this.rawDefault = safeIndex;
47     }
48
49     // Make sure no default is set (so it won't be printed)
50     this.opt.default = null;
51
52     const shouldLoop = this.opt.loop === undefined ? true : this.opt.loop;
53     this.paginator = new Paginator(undefined, { isInfinite: shouldLoop });
54   }
55
56   /**
57    * Start the Inquiry session
58    * @param  {Function} cb      Callback when prompt is done
59    * @return {this}
60    */
61
62   _run(cb) {
63     this.done = cb;
64
65     // Once user confirm (enter key)
66     var events = observe(this.rl);
67     var submit = events.line.pipe(map(this.getCurrentValue.bind(this)));
68
69     var validation = this.handleSubmitEvents(submit);
70     validation.success.forEach(this.onEnd.bind(this));
71     validation.error.forEach(this.onError.bind(this));
72
73     events.normalizedUpKey.pipe(takeUntil(events.line)).forEach(this.onUpKey.bind(this));
74     events.normalizedDownKey
75       .pipe(takeUntil(events.line))
76       .forEach(this.onDownKey.bind(this));
77     events.keypress
78       .pipe(takeUntil(validation.success))
79       .forEach(this.onKeypress.bind(this));
80     // Init the prompt
81     this.render();
82
83     return this;
84   }
85
86   /**
87    * Render the prompt to screen
88    * @return {RawListPrompt} self
89    */
90
91   render(error) {
92     // Render question
93     var message = this.getQuestion();
94     var bottomContent = '';
95
96     if (this.status === 'answered') {
97       message += chalk.cyan(this.answer);
98     } else {
99       var choicesStr = renderChoices(this.opt.choices, this.selected);
100       message +=
101         '\n' + this.paginator.paginate(choicesStr, this.selected, this.opt.pageSize);
102       message += '\n  Answer: ';
103     }
104     message += this.rl.line;
105
106     if (error) {
107       bottomContent = '\n' + chalk.red('>> ') + error;
108     }
109
110     this.screen.render(message, bottomContent);
111   }
112
113   /**
114    * When user press `enter` key
115    */
116
117   getCurrentValue(index) {
118     if (index == null) {
119       index = this.rawDefault;
120     } else if (index === '') {
121       index = this.selected;
122     } else {
123       index -= 1;
124     }
125
126     var choice = this.opt.choices.getChoice(index);
127     return choice ? choice.value : null;
128   }
129
130   onEnd(state) {
131     this.status = 'answered';
132     this.answer = state.value;
133
134     // Re-render prompt
135     this.render();
136
137     this.screen.done();
138     this.done(state.value);
139   }
140
141   onError() {
142     this.render('Please enter a valid index');
143   }
144
145   /**
146    * When user press a key
147    */
148
149   onKeypress() {
150     var index = this.rl.line.length ? Number(this.rl.line) - 1 : 0;
151
152     if (this.opt.choices.getChoice(index)) {
153       this.selected = index;
154     } else {
155       this.selected = undefined;
156     }
157     this.render();
158   }
159
160   /**
161    * When user press up key
162    */
163
164   onUpKey() {
165     this.onArrowKey('up');
166   }
167
168   /**
169    * When user press down key
170    */
171
172   onDownKey() {
173     this.onArrowKey('down');
174   }
175
176   /**
177    * When user press up or down key
178    * @param {String} type Arrow type: up or down
179    */
180
181   onArrowKey(type) {
182     this.selected = incrementListIndex(this.selected, type, this.opt);
183     this.rl.line = String(this.selected + 1);
184   }
185 }
186
187 /**
188  * Function for rendering list choices
189  * @param  {Number} pointer Position of the pointer
190  * @return {String}         Rendered content
191  */
192
193 function renderChoices(choices, pointer) {
194   var output = '';
195   var separatorOffset = 0;
196
197   choices.forEach(function (choice, i) {
198     output += '\n  ';
199
200     if (choice.type === 'separator') {
201       separatorOffset++;
202       output += ' ' + choice;
203       return;
204     }
205
206     var index = i - separatorOffset;
207     var display = index + 1 + ') ' + choice.name;
208     if (index === pointer) {
209       display = chalk.cyan(display);
210     }
211
212     output += display;
213   });
214
215   return output;
216 }
217
218 module.exports = RawListPrompt;