Actualizacion maquina principal
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / inquirer / lib / prompts / list.js
1 'use strict';
2 /**
3  * `list` type prompt
4  */
5
6 var _ = {
7   isNumber: require('lodash/isNumber'),
8   findIndex: require('lodash/findIndex'),
9   isString: require('lodash/isString'),
10 };
11 var chalk = require('chalk');
12 var figures = require('figures');
13 var cliCursor = require('cli-cursor');
14 var runAsync = require('run-async');
15 var { flatMap, map, take, takeUntil } = require('rxjs/operators');
16 var Base = require('./base');
17 var observe = require('../utils/events');
18 var Paginator = require('../utils/paginator');
19 var incrementListIndex = require('../utils/incrementListIndex');
20
21 class ListPrompt extends Base {
22   constructor(questions, rl, answers) {
23     super(questions, rl, answers);
24
25     if (!this.opt.choices) {
26       this.throwParamError('choices');
27     }
28
29     this.firstRender = true;
30     this.selected = 0;
31
32     var def = this.opt.default;
33
34     // If def is a Number, then use as index. Otherwise, check for value.
35     if (_.isNumber(def) && def >= 0 && def < this.opt.choices.realLength) {
36       this.selected = def;
37     } else if (!_.isNumber(def) && def != null) {
38       let index = _.findIndex(this.opt.choices.realChoices, ({ value }) => value === def);
39       this.selected = Math.max(index, 0);
40     }
41
42     // Make sure no default is set (so it won't be printed)
43     this.opt.default = null;
44
45     this.paginator = new Paginator(this.screen);
46   }
47
48   /**
49    * Start the Inquiry session
50    * @param  {Function} cb      Callback when prompt is done
51    * @return {this}
52    */
53
54   _run(cb) {
55     this.done = cb;
56
57     var self = this;
58
59     var events = observe(this.rl);
60     events.normalizedUpKey.pipe(takeUntil(events.line)).forEach(this.onUpKey.bind(this));
61     events.normalizedDownKey
62       .pipe(takeUntil(events.line))
63       .forEach(this.onDownKey.bind(this));
64     events.numberKey.pipe(takeUntil(events.line)).forEach(this.onNumberKey.bind(this));
65     events.line
66       .pipe(
67         take(1),
68         map(this.getCurrentValue.bind(this)),
69         flatMap((value) => runAsync(self.opt.filter)(value).catch((err) => err))
70       )
71       .forEach(this.onSubmit.bind(this));
72
73     // Init the prompt
74     cliCursor.hide();
75     this.render();
76
77     return this;
78   }
79
80   /**
81    * Render the prompt to screen
82    * @return {ListPrompt} self
83    */
84
85   render() {
86     // Render question
87     var message = this.getQuestion();
88
89     if (this.firstRender) {
90       message += chalk.dim('(Use arrow keys)');
91     }
92
93     // Render choices or answer depending on the state
94     if (this.status === 'answered') {
95       message += chalk.cyan(this.opt.choices.getChoice(this.selected).short);
96     } else {
97       var choicesStr = listRender(this.opt.choices, this.selected);
98       var indexPosition = this.opt.choices.indexOf(
99         this.opt.choices.getChoice(this.selected)
100       );
101       var realIndexPosition =
102         this.opt.choices.reduce(function (acc, value, i) {
103           // Dont count lines past the choice we are looking at
104           if (i > indexPosition) {
105             return acc;
106           }
107           // Add line if it's a separator
108           if (value.type === 'separator') {
109             return acc + 1;
110           }
111
112           var l = value.name;
113           // Non-strings take up one line
114           if (typeof l !== 'string') {
115             return acc + 1;
116           }
117
118           // Calculate lines taken up by string
119           l = l.split('\n');
120           return acc + l.length;
121         }, 0) - 1;
122       message +=
123         '\n' + this.paginator.paginate(choicesStr, realIndexPosition, this.opt.pageSize);
124     }
125
126     this.firstRender = false;
127
128     this.screen.render(message);
129   }
130
131   /**
132    * When user press `enter` key
133    */
134
135   onSubmit(value) {
136     this.status = 'answered';
137
138     // Rerender prompt
139     this.render();
140
141     this.screen.done();
142     cliCursor.show();
143     this.done(value);
144   }
145
146   getCurrentValue() {
147     return this.opt.choices.getChoice(this.selected).value;
148   }
149
150   /**
151    * When user press a key
152    */
153   onUpKey() {
154     this.selected = incrementListIndex(this.selected, 'up', this.opt);
155     this.render();
156   }
157
158   onDownKey() {
159     this.selected = incrementListIndex(this.selected, 'down', this.opt);
160     this.render();
161   }
162
163   onNumberKey(input) {
164     if (input <= this.opt.choices.realLength) {
165       this.selected = input - 1;
166     }
167
168     this.render();
169   }
170 }
171
172 /**
173  * Function for rendering list choices
174  * @param  {Number} pointer Position of the pointer
175  * @return {String}         Rendered content
176  */
177 function listRender(choices, pointer) {
178   var output = '';
179   var separatorOffset = 0;
180
181   choices.forEach((choice, i) => {
182     if (choice.type === 'separator') {
183       separatorOffset++;
184       output += '  ' + choice + '\n';
185       return;
186     }
187
188     if (choice.disabled) {
189       separatorOffset++;
190       output += '  - ' + choice.name;
191       output += ' (' + (_.isString(choice.disabled) ? choice.disabled : 'Disabled') + ')';
192       output += '\n';
193       return;
194     }
195
196     var isSelected = i - separatorOffset === pointer;
197     var line = (isSelected ? figures.pointer + ' ' : '  ') + choice.name;
198     if (isSelected) {
199       line = chalk.cyan(line);
200     }
201
202     output += line + ' \n';
203   });
204
205   return output.replace(/\n$/, '');
206 }
207
208 module.exports = ListPrompt;