diff options
Diffstat (limited to 'tools/node_modules/eslint/node_modules/inquirer/lib/prompts')
9 files changed, 1434 insertions, 0 deletions
diff --git a/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/base.js b/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/base.js new file mode 100644 index 0000000000..c7fd14fbef --- /dev/null +++ b/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/base.js @@ -0,0 +1,139 @@ +/** + * Base prompt implementation + * Should be extended by prompt types. + */ + +var _ = require('lodash'); +var chalk = require('chalk'); +var runAsync = require('run-async'); +var Choices = require('../objects/choices'); +var ScreenManager = require('../utils/screen-manager'); + +var Prompt = module.exports = function (question, rl, answers) { + // Setup instance defaults property + _.assign(this, { + answers: answers, + status: 'pending' + }); + + // Set defaults prompt options + this.opt = _.defaults(_.clone(question), { + validate: function () { + return true; + }, + filter: function (val) { + return val; + }, + when: function () { + return true; + }, + suffix: '', + prefix: chalk.green('?') + }); + + // Check to make sure prompt requirements are there + if (!this.opt.message) { + this.throwParamError('message'); + } + if (!this.opt.name) { + this.throwParamError('name'); + } + + // Normalize choices + if (Array.isArray(this.opt.choices)) { + this.opt.choices = new Choices(this.opt.choices, answers); + } + + this.rl = rl; + this.screen = new ScreenManager(this.rl); +}; + +/** + * Start the Inquiry session and manage output value filtering + * @return {Promise} + */ + +Prompt.prototype.run = function () { + return new Promise(function (resolve) { + this._run(function (value) { + resolve(value); + }); + }.bind(this)); +}; + +// default noop (this one should be overwritten in prompts) +Prompt.prototype._run = function (cb) { + cb(); +}; + +/** + * Throw an error telling a required parameter is missing + * @param {String} name Name of the missing param + * @return {Throw Error} + */ + +Prompt.prototype.throwParamError = function (name) { + throw new Error('You must provide a `' + name + '` parameter'); +}; + +/** + * Called when the UI closes. Override to do any specific cleanup necessary + */ +Prompt.prototype.close = function () { + this.screen.releaseCursor(); +}; + +/** + * Run the provided validation method each time a submit event occur. + * @param {Rx.Observable} submit - submit event flow + * @return {Object} Object containing two observables: `success` and `error` + */ +Prompt.prototype.handleSubmitEvents = function (submit) { + var self = this; + var validate = runAsync(this.opt.validate); + var filter = runAsync(this.opt.filter); + var validation = submit.flatMap(function (value) { + return filter(value, self.answers).then(function (filteredValue) { + return validate(filteredValue, self.answers).then(function (isValid) { + return {isValid: isValid, value: filteredValue}; + }, function (err) { + return {isValid: err}; + }); + }, function (err) { + return {isValid: err}; + }); + }).share(); + + var success = validation + .filter(function (state) { + return state.isValid === true; + }) + .take(1); + + var error = validation + .filter(function (state) { + return state.isValid !== true; + }) + .takeUntil(success); + + return { + success: success, + error: error + }; +}; + +/** + * Generate the prompt question string + * @return {String} prompt question string + */ + +Prompt.prototype.getQuestion = function () { + var message = this.opt.prefix + ' ' + chalk.bold(this.opt.message) + this.opt.suffix + chalk.reset(' '); + + // Append the default if available, and if question isn't answered + if (this.opt.default != null && this.status !== 'answered') { + message += chalk.dim('(' + this.opt.default + ') '); + } + + return message; +}; diff --git a/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/checkbox.js b/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/checkbox.js new file mode 100644 index 0000000000..52336e3f79 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/checkbox.js @@ -0,0 +1,236 @@ +/** + * `list` type prompt + */ + +var _ = require('lodash'); +var util = require('util'); +var chalk = require('chalk'); +var cliCursor = require('cli-cursor'); +var figures = require('figures'); +var Base = require('./base'); +var observe = require('../utils/events'); +var Paginator = require('../utils/paginator'); + +/** + * Module exports + */ + +module.exports = Prompt; + +/** + * Constructor + */ + +function Prompt() { + Base.apply(this, arguments); + + if (!this.opt.choices) { + this.throwParamError('choices'); + } + + if (_.isArray(this.opt.default)) { + this.opt.choices.forEach(function (choice) { + if (this.opt.default.indexOf(choice.value) >= 0) { + choice.checked = true; + } + }, this); + } + + this.pointer = 0; + this.firstRender = true; + + // Make sure no default is set (so it won't be printed) + this.opt.default = null; + + this.paginator = new Paginator(); +} +util.inherits(Prompt, Base); + +/** + * Start the Inquiry session + * @param {Function} cb Callback when prompt is done + * @return {this} + */ + +Prompt.prototype._run = function (cb) { + this.done = cb; + + var events = observe(this.rl); + + var validation = this.handleSubmitEvents( + events.line.map(this.getCurrentValue.bind(this)) + ); + validation.success.forEach(this.onEnd.bind(this)); + validation.error.forEach(this.onError.bind(this)); + + events.normalizedUpKey.takeUntil(validation.success).forEach(this.onUpKey.bind(this)); + events.normalizedDownKey.takeUntil(validation.success).forEach(this.onDownKey.bind(this)); + events.numberKey.takeUntil(validation.success).forEach(this.onNumberKey.bind(this)); + events.spaceKey.takeUntil(validation.success).forEach(this.onSpaceKey.bind(this)); + events.aKey.takeUntil(validation.success).forEach(this.onAllKey.bind(this)); + events.iKey.takeUntil(validation.success).forEach(this.onInverseKey.bind(this)); + + // Init the prompt + cliCursor.hide(); + this.render(); + this.firstRender = false; + + return this; +}; + +/** + * Render the prompt to screen + * @return {Prompt} self + */ + +Prompt.prototype.render = function (error) { + // Render question + var message = this.getQuestion(); + var bottomContent = ''; + + if (this.firstRender) { + message += '(Press ' + chalk.cyan.bold('<space>') + ' to select, ' + chalk.cyan.bold('<a>') + ' to toggle all, ' + chalk.cyan.bold('<i>') + ' to inverse selection)'; + } + + // Render choices or answer depending on the state + if (this.status === 'answered') { + message += chalk.cyan(this.selection.join(', ')); + } else { + var choicesStr = renderChoices(this.opt.choices, this.pointer); + var indexPosition = this.opt.choices.indexOf(this.opt.choices.getChoice(this.pointer)); + message += '\n' + this.paginator.paginate(choicesStr, indexPosition, this.opt.pageSize); + } + + if (error) { + bottomContent = chalk.red('>> ') + error; + } + + this.screen.render(message, bottomContent); +}; + +/** + * When user press `enter` key + */ + +Prompt.prototype.onEnd = function (state) { + this.status = 'answered'; + + // Rerender prompt (and clean subline error) + this.render(); + + this.screen.done(); + cliCursor.show(); + this.done(state.value); +}; + +Prompt.prototype.onError = function (state) { + this.render(state.isValid); +}; + +Prompt.prototype.getCurrentValue = function () { + var choices = this.opt.choices.filter(function (choice) { + return Boolean(choice.checked) && !choice.disabled; + }); + + this.selection = _.map(choices, 'short'); + return _.map(choices, 'value'); +}; + +Prompt.prototype.onUpKey = function () { + var len = this.opt.choices.realLength; + this.pointer = (this.pointer > 0) ? this.pointer - 1 : len - 1; + this.render(); +}; + +Prompt.prototype.onDownKey = function () { + var len = this.opt.choices.realLength; + this.pointer = (this.pointer < len - 1) ? this.pointer + 1 : 0; + this.render(); +}; + +Prompt.prototype.onNumberKey = function (input) { + if (input <= this.opt.choices.realLength) { + this.pointer = input - 1; + this.toggleChoice(this.pointer); + } + this.render(); +}; + +Prompt.prototype.onSpaceKey = function () { + this.toggleChoice(this.pointer); + this.render(); +}; + +Prompt.prototype.onAllKey = function () { + var shouldBeChecked = Boolean(this.opt.choices.find(function (choice) { + return choice.type !== 'separator' && !choice.checked; + })); + + this.opt.choices.forEach(function (choice) { + if (choice.type !== 'separator') { + choice.checked = shouldBeChecked; + } + }); + + this.render(); +}; + +Prompt.prototype.onInverseKey = function () { + this.opt.choices.forEach(function (choice) { + if (choice.type !== 'separator') { + choice.checked = !choice.checked; + } + }); + + this.render(); +}; + +Prompt.prototype.toggleChoice = function (index) { + var item = this.opt.choices.getChoice(index); + if (item !== undefined) { + this.opt.choices.getChoice(index).checked = !item.checked; + } +}; + +/** + * Function for rendering checkbox choices + * @param {Number} pointer Position of the pointer + * @return {String} Rendered content + */ + +function renderChoices(choices, pointer) { + var output = ''; + var separatorOffset = 0; + + choices.forEach(function (choice, i) { + if (choice.type === 'separator') { + separatorOffset++; + output += ' ' + choice + '\n'; + return; + } + + if (choice.disabled) { + separatorOffset++; + output += ' - ' + choice.name; + output += ' (' + (_.isString(choice.disabled) ? choice.disabled : 'Disabled') + ')'; + } else { + var isSelected = (i - separatorOffset === pointer); + output += isSelected ? chalk.cyan(figures.pointer) : ' '; + output += getCheckbox(choice.checked) + ' ' + choice.name; + } + + output += '\n'; + }); + + return output.replace(/\n$/, ''); +} + +/** + * Get the checkbox + * @param {Boolean} checked - add a X or not to the checkbox + * @return {String} Composited checkbox string + */ + +function getCheckbox(checked) { + return checked ? chalk.green(figures.radioOn) : figures.radioOff; +} diff --git a/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/confirm.js b/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/confirm.js new file mode 100644 index 0000000000..542d120394 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/confirm.js @@ -0,0 +1,106 @@ +/** + * `confirm` type prompt + */ + +var _ = require('lodash'); +var util = require('util'); +var chalk = require('chalk'); +var Base = require('./base'); +var observe = require('../utils/events'); + +/** + * Module exports + */ + +module.exports = Prompt; + +/** + * Constructor + */ + +function Prompt() { + Base.apply(this, arguments); + + var rawDefault = true; + + _.extend(this.opt, { + filter: function (input) { + var value = rawDefault; + if (input != null && input !== '') { + value = /^y(es)?/i.test(input); + } + return value; + } + }); + + if (_.isBoolean(this.opt.default)) { + rawDefault = this.opt.default; + } + + this.opt.default = rawDefault ? 'Y/n' : 'y/N'; + + return this; +} +util.inherits(Prompt, Base); + +/** + * Start the Inquiry session + * @param {Function} cb Callback when prompt is done + * @return {this} + */ + +Prompt.prototype._run = function (cb) { + this.done = cb; + + // Once user confirm (enter key) + var events = observe(this.rl); + events.keypress.takeUntil(events.line).forEach(this.onKeypress.bind(this)); + + events.line.take(1).forEach(this.onEnd.bind(this)); + + // Init + this.render(); + + return this; +}; + +/** + * Render the prompt to screen + * @return {Prompt} self + */ + +Prompt.prototype.render = function (answer) { + var message = this.getQuestion(); + + if (typeof answer === 'boolean') { + message += chalk.cyan(answer ? 'Yes' : 'No'); + } else { + message += this.rl.line; + } + + this.screen.render(message); + + return this; +}; + +/** + * When user press `enter` key + */ + +Prompt.prototype.onEnd = function (input) { + this.status = 'answered'; + + var output = this.opt.filter(input); + this.render(output); + + this.screen.done(); + this.done(output); +}; + +/** + * When user press a key + */ + +Prompt.prototype.onKeypress = function () { + this.render(); +}; diff --git a/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/editor.js b/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/editor.js new file mode 100644 index 0000000000..e4bb2664a9 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/editor.js @@ -0,0 +1,111 @@ +/** + * `editor` type prompt + */ + +var util = require('util'); +var chalk = require('chalk'); +var ExternalEditor = require('external-editor'); +var Base = require('./base'); +var observe = require('../utils/events'); +var rx = require('rx-lite-aggregates'); + +/** + * Module exports + */ + +module.exports = Prompt; + +/** + * Constructor + */ + +function Prompt() { + return Base.apply(this, arguments); +} +util.inherits(Prompt, Base); + +/** + * Start the Inquiry session + * @param {Function} cb Callback when prompt is done + * @return {this} + */ + +Prompt.prototype._run = function (cb) { + this.done = cb; + + this.editorResult = new rx.Subject(); + + // Open Editor on "line" (Enter Key) + var events = observe(this.rl); + this.lineSubscription = events.line.forEach(this.startExternalEditor.bind(this)); + + // Trigger Validation when editor closes + var validation = this.handleSubmitEvents(this.editorResult); + validation.success.forEach(this.onEnd.bind(this)); + validation.error.forEach(this.onError.bind(this)); + + // Prevents default from being printed on screen (can look weird with multiple lines) + this.currentText = this.opt.default; + this.opt.default = null; + + // Init + this.render(); + + return this; +}; + +/** + * Render the prompt to screen + * @return {Prompt} self + */ + +Prompt.prototype.render = function (error) { + var bottomContent = ''; + var message = this.getQuestion(); + + if (this.status === 'answered') { + message += chalk.dim('Received'); + } else { + message += chalk.dim('Press <enter> to launch your preferred editor.'); + } + + if (error) { + bottomContent = chalk.red('>> ') + error; + } + + this.screen.render(message, bottomContent); +}; + +/** + * Launch $EDITOR on user press enter + */ + +Prompt.prototype.startExternalEditor = function () { + // Pause Readline to prevent stdin and stdout from being modified while the editor is showing + this.rl.pause(); + ExternalEditor.editAsync(this.currentText, this.endExternalEditor.bind(this)); +}; + +Prompt.prototype.endExternalEditor = function (error, result) { + this.rl.resume(); + if (error) { + this.editorResult.onError(error); + } else { + this.editorResult.onNext(result); + } +}; + +Prompt.prototype.onEnd = function (state) { + this.editorResult.dispose(); + this.lineSubscription.dispose(); + this.answer = state.value; + this.status = 'answered'; + // Re-render prompt + this.render(); + this.screen.done(); + this.done(this.answer); +}; + +Prompt.prototype.onError = function (state) { + this.render(state.isValid); +}; diff --git a/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/expand.js b/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/expand.js new file mode 100644 index 0000000000..336d98c5af --- /dev/null +++ b/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/expand.js @@ -0,0 +1,260 @@ +/** + * `rawlist` type prompt + */ + +var _ = require('lodash'); +var util = require('util'); +var chalk = require('chalk'); +var Base = require('./base'); +var Separator = require('../objects/separator'); +var observe = require('../utils/events'); +var Paginator = require('../utils/paginator'); + +/** + * Module exports + */ + +module.exports = Prompt; + +/** + * Constructor + */ + +function Prompt() { + Base.apply(this, arguments); + + if (!this.opt.choices) { + this.throwParamError('choices'); + } + + this.validateChoices(this.opt.choices); + + // Add the default `help` (/expand) option + this.opt.choices.push({ + key: 'h', + name: 'Help, list all options', + value: 'help' + }); + + this.opt.validate = function (choice) { + if (choice == null) { + return 'Please enter a valid command'; + } + + return choice !== 'help'; + }; + + // Setup the default string (capitalize the default key) + this.opt.default = this.generateChoicesString(this.opt.choices, this.opt.default); + + this.paginator = new Paginator(); +} +util.inherits(Prompt, Base); + +/** + * Start the Inquiry session + * @param {Function} cb Callback when prompt is done + * @return {this} + */ + +Prompt.prototype._run = function (cb) { + this.done = cb; + + // Save user answer and update prompt to show selected option. + var events = observe(this.rl); + var validation = this.handleSubmitEvents( + events.line.map(this.getCurrentValue.bind(this)) + ); + validation.success.forEach(this.onSubmit.bind(this)); + validation.error.forEach(this.onError.bind(this)); + this.keypressObs = events.keypress.takeUntil(validation.success) + .forEach(this.onKeypress.bind(this)); + + // Init the prompt + this.render(); + + return this; +}; + +/** + * Render the prompt to screen + * @return {Prompt} self + */ + +Prompt.prototype.render = function (error, hint) { + var message = this.getQuestion(); + var bottomContent = ''; + + if (this.status === 'answered') { + message += chalk.cyan(this.answer); + } else if (this.status === 'expanded') { + var choicesStr = renderChoices(this.opt.choices, this.selectedKey); + message += this.paginator.paginate(choicesStr, this.selectedKey, this.opt.pageSize); + message += '\n Answer: '; + } + + message += this.rl.line; + + if (error) { + bottomContent = chalk.red('>> ') + error; + } + + if (hint) { + bottomContent = chalk.cyan('>> ') + hint; + } + + this.screen.render(message, bottomContent); +}; + +Prompt.prototype.getCurrentValue = function (input) { + if (!input) { + input = this.rawDefault; + } + var selected = this.opt.choices.where({key: input.toLowerCase().trim()})[0]; + if (!selected) { + return null; + } + + return selected.value; +}; + +/** + * Generate the prompt choices string + * @return {String} Choices string + */ + +Prompt.prototype.getChoices = function () { + var output = ''; + + this.opt.choices.forEach(function (choice) { + output += '\n '; + + if (choice.type === 'separator') { + output += ' ' + choice; + return; + } + + var choiceStr = choice.key + ') ' + choice.name; + if (this.selectedKey === choice.key) { + choiceStr = chalk.cyan(choiceStr); + } + output += choiceStr; + }.bind(this)); + + return output; +}; + +Prompt.prototype.onError = function (state) { + if (state.value === 'help') { + this.selectedKey = ''; + this.status = 'expanded'; + this.render(); + return; + } + this.render(state.isValid); +}; + +/** + * When user press `enter` key + */ + +Prompt.prototype.onSubmit = function (state) { + this.status = 'answered'; + var choice = this.opt.choices.where({value: state.value})[0]; + this.answer = choice.short || choice.name; + + // Re-render prompt + this.render(); + this.screen.done(); + this.done(state.value); +}; + +/** + * When user press a key + */ + +Prompt.prototype.onKeypress = function () { + this.selectedKey = this.rl.line.toLowerCase(); + var selected = this.opt.choices.where({key: this.selectedKey})[0]; + if (this.status === 'expanded') { + this.render(); + } else { + this.render(null, selected ? selected.name : null); + } +}; + +/** + * Validate the choices + * @param {Array} choices + */ + +Prompt.prototype.validateChoices = function (choices) { + var formatError; + var errors = []; + var keymap = {}; + choices.filter(Separator.exclude).forEach(function (choice) { + if (!choice.key || choice.key.length !== 1) { + formatError = true; + } + if (keymap[choice.key]) { + errors.push(choice.key); + } + keymap[choice.key] = true; + choice.key = String(choice.key).toLowerCase(); + }); + + if (formatError) { + throw new Error('Format error: `key` param must be a single letter and is required.'); + } + if (keymap.h) { + throw new Error('Reserved key error: `key` param cannot be `h` - this value is reserved.'); + } + if (errors.length) { + throw new Error('Duplicate key error: `key` param must be unique. Duplicates: ' + + _.uniq(errors).join(', ')); + } +}; + +/** + * Generate a string out of the choices keys + * @param {Array} choices + * @param {Number} defaultIndex - the choice index to capitalize + * @return {String} The rendered choices key string + */ +Prompt.prototype.generateChoicesString = function (choices, defaultIndex) { + var defIndex = choices.realLength - 1; + if (_.isNumber(defaultIndex) && this.opt.choices.getChoice(defaultIndex)) { + defIndex = defaultIndex; + } + var defStr = this.opt.choices.pluck('key'); + this.rawDefault = defStr[defIndex]; + defStr[defIndex] = String(defStr[defIndex]).toUpperCase(); + return defStr.join(''); +}; + +/** + * Function for rendering checkbox choices + * @param {String} pointer Selected key + * @return {String} Rendered content + */ + +function renderChoices(choices, pointer) { + var output = ''; + + choices.forEach(function (choice) { + output += '\n '; + + if (choice.type === 'separator') { + output += ' ' + choice; + return; + } + + var choiceStr = choice.key + ') ' + choice.name; + if (pointer === choice.key) { + choiceStr = chalk.cyan(choiceStr); + } + output += choiceStr; + }); + + return output; +} diff --git a/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/input.js b/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/input.js new file mode 100644 index 0000000000..a1c7be2acc --- /dev/null +++ b/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/input.js @@ -0,0 +1,104 @@ +/** + * `input` type prompt + */ + +var util = require('util'); +var chalk = require('chalk'); +var Base = require('./base'); +var observe = require('../utils/events'); + +/** + * Module exports + */ + +module.exports = Prompt; + +/** + * Constructor + */ + +function Prompt() { + return Base.apply(this, arguments); +} +util.inherits(Prompt, Base); + +/** + * Start the Inquiry session + * @param {Function} cb Callback when prompt is done + * @return {this} + */ + +Prompt.prototype._run = function (cb) { + this.done = cb; + + // Once user confirm (enter key) + var events = observe(this.rl); + var submit = events.line.map(this.filterInput.bind(this)); + + var validation = this.handleSubmitEvents(submit); + validation.success.forEach(this.onEnd.bind(this)); + validation.error.forEach(this.onError.bind(this)); + + events.keypress.takeUntil(validation.success).forEach(this.onKeypress.bind(this)); + + // Init + this.render(); + + return this; +}; + +/** + * Render the prompt to screen + * @return {Prompt} self + */ + +Prompt.prototype.render = function (error) { + var bottomContent = ''; + var message = this.getQuestion(); + + if (this.status === 'answered') { + message += chalk.cyan(this.answer); + } else { + message += this.rl.line; + } + + if (error) { + bottomContent = chalk.red('>> ') + error; + } + + this.screen.render(message, bottomContent); +}; + +/** + * When user press `enter` key + */ + +Prompt.prototype.filterInput = function (input) { + if (!input) { + return this.opt.default == null ? '' : this.opt.default; + } + return input; +}; + +Prompt.prototype.onEnd = function (state) { + this.answer = state.value; + this.status = 'answered'; + + // Re-render prompt + this.render(); + + this.screen.done(); + this.done(state.value); +}; + +Prompt.prototype.onError = function (state) { + this.render(state.isValid); +}; + +/** + * When user press a key + */ + +Prompt.prototype.onKeypress = function () { + this.render(); +}; diff --git a/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/list.js b/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/list.js new file mode 100644 index 0000000000..c29542f228 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/list.js @@ -0,0 +1,184 @@ +/** + * `list` type prompt + */ + +var _ = require('lodash'); +var util = require('util'); +var chalk = require('chalk'); +var figures = require('figures'); +var cliCursor = require('cli-cursor'); +var runAsync = require('run-async'); +var Base = require('./base'); +var observe = require('../utils/events'); +var Paginator = require('../utils/paginator'); + +/** + * Module exports + */ + +module.exports = Prompt; + +/** + * Constructor + */ + +function Prompt() { + Base.apply(this, arguments); + + if (!this.opt.choices) { + this.throwParamError('choices'); + } + + this.firstRender = true; + this.selected = 0; + + var def = this.opt.default; + + // If def is a Number, then use as index. Otherwise, check for value. + if (_.isNumber(def) && def >= 0 && def < this.opt.choices.realLength) { + this.selected = def; + } else if (!_.isNumber(def) && def != null) { + this.selected = this.opt.choices.pluck('value').indexOf(def); + } + + // Make sure no default is set (so it won't be printed) + this.opt.default = null; + + this.paginator = new Paginator(); +} +util.inherits(Prompt, Base); + +/** + * Start the Inquiry session + * @param {Function} cb Callback when prompt is done + * @return {this} + */ + +Prompt.prototype._run = function (cb) { + this.done = cb; + + var self = this; + + var events = observe(this.rl); + events.normalizedUpKey.takeUntil(events.line).forEach(this.onUpKey.bind(this)); + events.normalizedDownKey.takeUntil(events.line).forEach(this.onDownKey.bind(this)); + events.numberKey.takeUntil(events.line).forEach(this.onNumberKey.bind(this)); + events.line + .take(1) + .map(this.getCurrentValue.bind(this)) + .flatMap(function (value) { + return runAsync(self.opt.filter)(value).catch(function (err) { + return err; + }); + }) + .forEach(this.onSubmit.bind(this)); + + // Init the prompt + cliCursor.hide(); + this.render(); + + return this; +}; + +/** + * Render the prompt to screen + * @return {Prompt} self + */ + +Prompt.prototype.render = function () { + // Render question + var message = this.getQuestion(); + + if (this.firstRender) { + message += chalk.dim('(Use arrow keys)'); + } + + // Render choices or answer depending on the state + if (this.status === 'answered') { + message += chalk.cyan(this.opt.choices.getChoice(this.selected).short); + } else { + var choicesStr = listRender(this.opt.choices, this.selected); + var indexPosition = this.opt.choices.indexOf(this.opt.choices.getChoice(this.selected)); + message += '\n' + this.paginator.paginate(choicesStr, indexPosition, this.opt.pageSize); + } + + this.firstRender = false; + + this.screen.render(message); +}; + +/** + * When user press `enter` key + */ + +Prompt.prototype.onSubmit = function (value) { + this.status = 'answered'; + + // Rerender prompt + this.render(); + + this.screen.done(); + cliCursor.show(); + this.done(value); +}; + +Prompt.prototype.getCurrentValue = function () { + return this.opt.choices.getChoice(this.selected).value; +}; + +/** + * When user press a key + */ +Prompt.prototype.onUpKey = function () { + var len = this.opt.choices.realLength; + this.selected = (this.selected > 0) ? this.selected - 1 : len - 1; + this.render(); +}; + +Prompt.prototype.onDownKey = function () { + var len = this.opt.choices.realLength; + this.selected = (this.selected < len - 1) ? this.selected + 1 : 0; + this.render(); +}; + +Prompt.prototype.onNumberKey = function (input) { + if (input <= this.opt.choices.realLength) { + this.selected = input - 1; + } + this.render(); +}; + +/** + * Function for rendering list choices + * @param {Number} pointer Position of the pointer + * @return {String} Rendered content + */ +function listRender(choices, pointer) { + var output = ''; + var separatorOffset = 0; + + choices.forEach(function (choice, i) { + if (choice.type === 'separator') { + separatorOffset++; + output += ' ' + choice + '\n'; + return; + } + + if (choice.disabled) { + separatorOffset++; + output += ' - ' + choice.name; + output += ' (' + (_.isString(choice.disabled) ? choice.disabled : 'Disabled') + ')'; + output += '\n'; + return; + } + + var isSelected = (i - separatorOffset === pointer); + var line = (isSelected ? figures.pointer + ' ' : ' ') + choice.name; + if (isSelected) { + line = chalk.cyan(line); + } + output += line + ' \n'; + }); + + return output.replace(/\n$/, ''); +} diff --git a/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/password.js b/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/password.js new file mode 100644 index 0000000000..2a9a5e2e6a --- /dev/null +++ b/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/password.js @@ -0,0 +1,115 @@ +/** + * `password` type prompt + */ + +var util = require('util'); +var chalk = require('chalk'); +var Base = require('./base'); +var observe = require('../utils/events'); + +function mask(input, maskChar) { + input = String(input); + maskChar = typeof maskChar === 'string' ? maskChar : '*'; + if (input.length === 0) { + return ''; + } + + return new Array(input.length + 1).join(maskChar); +} + +/** + * Module exports + */ + +module.exports = Prompt; + +/** + * Constructor + */ + +function Prompt() { + return Base.apply(this, arguments); +} +util.inherits(Prompt, Base); + +/** + * Start the Inquiry session + * @param {Function} cb Callback when prompt is done + * @return {this} + */ + +Prompt.prototype._run = function (cb) { + this.done = cb; + + var events = observe(this.rl); + + // Once user confirm (enter key) + var submit = events.line.map(this.filterInput.bind(this)); + + var validation = this.handleSubmitEvents(submit); + validation.success.forEach(this.onEnd.bind(this)); + validation.error.forEach(this.onError.bind(this)); + + if (this.opt.mask) { + events.keypress.takeUntil(validation.success).forEach(this.onKeypress.bind(this)); + } + + // Init + this.render(); + + return this; +}; + +/** + * Render the prompt to screen + * @return {Prompt} self + */ + +Prompt.prototype.render = function (error) { + var message = this.getQuestion(); + var bottomContent = ''; + + if (this.status === 'answered') { + message += this.opt.mask ? chalk.cyan(mask(this.answer, this.opt.mask)) : chalk.italic.dim('[hidden]'); + } else if (this.opt.mask) { + message += mask(this.rl.line || '', this.opt.mask); + } else { + message += chalk.italic.dim('[input is hidden] '); + } + + if (error) { + bottomContent = '\n' + chalk.red('>> ') + error; + } + + this.screen.render(message, bottomContent); +}; + +/** + * When user press `enter` key + */ + +Prompt.prototype.filterInput = function (input) { + if (!input) { + return this.opt.default == null ? '' : this.opt.default; + } + return input; +}; + +Prompt.prototype.onEnd = function (state) { + this.status = 'answered'; + this.answer = state.value; + + // Re-render prompt + this.render(); + + this.screen.done(); + this.done(state.value); +}; + +Prompt.prototype.onError = function (state) { + this.render(state.isValid); +}; + +Prompt.prototype.onKeypress = function () { + this.render(); +}; diff --git a/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/rawlist.js b/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/rawlist.js new file mode 100644 index 0000000000..15e99110b6 --- /dev/null +++ b/tools/node_modules/eslint/node_modules/inquirer/lib/prompts/rawlist.js @@ -0,0 +1,179 @@ +/** + * `rawlist` type prompt + */ + +var _ = require('lodash'); +var util = require('util'); +var chalk = require('chalk'); +var Base = require('./base'); +var Separator = require('../objects/separator'); +var observe = require('../utils/events'); +var Paginator = require('../utils/paginator'); + +/** + * Module exports + */ + +module.exports = Prompt; + +/** + * Constructor + */ + +function Prompt() { + Base.apply(this, arguments); + + if (!this.opt.choices) { + this.throwParamError('choices'); + } + + this.opt.validChoices = this.opt.choices.filter(Separator.exclude); + + this.selected = 0; + this.rawDefault = 0; + + _.extend(this.opt, { + validate: function (val) { + return val != null; + } + }); + + var def = this.opt.default; + if (_.isNumber(def) && def >= 0 && def < this.opt.choices.realLength) { + this.selected = this.rawDefault = def; + } + + // Make sure no default is set (so it won't be printed) + this.opt.default = null; + + this.paginator = new Paginator(); +} +util.inherits(Prompt, Base); + +/** + * Start the Inquiry session + * @param {Function} cb Callback when prompt is done + * @return {this} + */ + +Prompt.prototype._run = function (cb) { + this.done = cb; + + // Once user confirm (enter key) + var events = observe(this.rl); + var submit = events.line.map(this.getCurrentValue.bind(this)); + + var validation = this.handleSubmitEvents(submit); + validation.success.forEach(this.onEnd.bind(this)); + validation.error.forEach(this.onError.bind(this)); + + events.keypress.takeUntil(validation.success).forEach(this.onKeypress.bind(this)); + + // Init the prompt + this.render(); + + return this; +}; + +/** + * Render the prompt to screen + * @return {Prompt} self + */ + +Prompt.prototype.render = function (error) { + // Render question + var message = this.getQuestion(); + var bottomContent = ''; + + if (this.status === 'answered') { + message += chalk.cyan(this.answer); + } else { + var choicesStr = renderChoices(this.opt.choices, this.selected); + message += this.paginator.paginate(choicesStr, this.selected, this.opt.pageSize); + message += '\n Answer: '; + } + + message += this.rl.line; + + if (error) { + bottomContent = '\n' + chalk.red('>> ') + error; + } + + this.screen.render(message, bottomContent); +}; + +/** + * When user press `enter` key + */ + +Prompt.prototype.getCurrentValue = function (index) { + if (index == null || index === '') { + index = this.rawDefault; + } else { + index -= 1; + } + + var choice = this.opt.choices.getChoice(index); + return choice ? choice.value : null; +}; + +Prompt.prototype.onEnd = function (state) { + this.status = 'answered'; + this.answer = state.value; + + // Re-render prompt + this.render(); + + this.screen.done(); + this.done(state.value); +}; + +Prompt.prototype.onError = function () { + this.render('Please enter a valid index'); +}; + +/** + * When user press a key + */ + +Prompt.prototype.onKeypress = function () { + var index = this.rl.line.length ? Number(this.rl.line) - 1 : 0; + + if (this.opt.choices.getChoice(index)) { + this.selected = index; + } else { + this.selected = undefined; + } + + this.render(); +}; + +/** + * Function for rendering list choices + * @param {Number} pointer Position of the pointer + * @return {String} Rendered content + */ + +function renderChoices(choices, pointer) { + var output = ''; + var separatorOffset = 0; + + choices.forEach(function (choice, i) { + output += '\n '; + + if (choice.type === 'separator') { + separatorOffset++; + output += ' ' + choice; + return; + } + + var index = i - separatorOffset; + var display = (index + 1) + ') ' + choice.name; + if (index === pointer) { + display = chalk.cyan(display); + } + output += display; + }); + + return output; +} |