| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- /**
- * Base prompt implementation
- * Should be extended by prompt types.
- */
- var rx = require('rx-lite');
- var _ = require('lodash');
- var chalk = require('chalk');
- var ansiRegex = require('ansi-regex');
- var readline = require('readline');
- var cliWidth = require('cli-width');
- 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; }
- });
- // 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
- * @param {Function} cb Callback when prompt is done
- * @return {this}
- */
- Prompt.prototype.run = function( cb ) {
- this._run(function (value) {
- this.filter(value, cb);
- }.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');
- };
- /**
- * Validate a given input
- * @param {String} value Input string
- * @param {Function} callback Pass `true` (if input is valid) or an error message as
- * parameter.
- * @return {null}
- */
- Prompt.prototype.validate = function (input, cb) {
- runAsync(this.opt.validate, cb, input);
- };
- /**
- * 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 validation = submit.flatMap(function (value) {
- return rx.Observable.create(function (observer) {
- runAsync(self.opt.validate, function (isValid) {
- observer.onNext({ isValid: isValid, value: self.getCurrentValue(value) });
- observer.onCompleted();
- }, self.getCurrentValue(value), self.answers);
- });
- }).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
- };
- };
- Prompt.prototype.getCurrentValue = function (value) {
- return value;
- };
- /**
- * Filter a given input before sending back
- * @param {String} value Input string
- * @param {Function} callback Pass the filtered input as parameter.
- * @return {null}
- */
- Prompt.prototype.filter = function (input, cb) {
- runAsync(this.opt.filter, cb, input);
- };
- /**
- * Return the prompt line prefix
- * @param {String} [optionnal] String to concatenate to the prefix
- * @return {String} prompt prefix
- */
- Prompt.prototype.prefix = function (str) {
- str || (str = '');
- return chalk.green('?') + ' ' + str;
- };
- /**
- * Return the prompt line suffix
- * @param {String} [optionnal] String to concatenate to the suffix
- * @return {String} prompt suffix
- */
- var reStrEnd = new RegExp('(?:' + ansiRegex().source + ')$|$');
- Prompt.prototype.suffix = function (str) {
- str || (str = '');
- // make sure we get the `:` inside the styles
- if (str.length < 1 || /[a-z1-9]$/i.test(chalk.stripColor(str))) {
- str = str.replace(reStrEnd, ':$&');
- }
- return str.trim() + ' ';
- };
- /**
- * Generate the prompt question string
- * @return {String} prompt question string
- */
- Prompt.prototype.getQuestion = function () {
- var message = chalk.green('?') + ' ' + chalk.bold(this.opt.message) + ' ';
- // 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;
- };
|