bricks-cli
Version:
Command line tool for developing ambitious ember.js apps
193 lines (143 loc) • 4.17 kB
JavaScript
/**
* Base prompt implementation
* Should be extended by prompt types.
*/
var _ = require("lodash");
var clc = require("cli-color");
var chalk = require("chalk");
var readline = require("readline");
var utils = require("../utils/utils");
var Choices = require("../objects/choices");
var tty = require("../utils/tty");
/**
* Module exports
*/
module.exports = Prompt;
/**
* Prompt constructor
*/
function Prompt( question, rl, answers ) {
// Setup instance defaults property
_.assign( this, {
height : 0,
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 ( _.isArray(this.opt.choices) ) {
this.opt.choices = new Choices( this.opt.choices, answers );
}
this.rl = rl;
return this;
}
_.extend( Prompt.prototype, tty );
/**
* Start the Inquiry session and manage output value filtering
* @param {Function} cb Callback when prompt is done
* @return {this}
*/
Prompt.prototype.run = function( cb ) {
var self = this;
this._run(function( value ) {
self.filter( value, cb );
});
return 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");
};
/**
* Write error message
* @param {String} Error Error message
* @return {Prompt} Self
*/
Prompt.prototype.error = function( error ) {
readline.moveCursor( this.rl.output, -clc.width, 0 );
readline.clearLine( this.rl.output, 0 );
var errMsg = chalk.red(">> ") +
(error || "Please enter a valid value");
this.write( errMsg );
return this.up();
};
/**
* Write hint message
* @param {String} Hint Hint message
* @return {Prompt} Self
*/
Prompt.prototype.hint = function( hint ) {
readline.moveCursor( this.rl.output, -clc.width, 0 );
readline.clearLine( this.rl.output, 0 );
if ( hint.length ) {
var hintMsg = chalk.cyan(">> ") + hint;
this.write( hintMsg );
}
return this.up();
};
/**
* 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 ) {
utils.runAsync( this.opt.validate, cb, input );
};
/**
* 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 ) {
utils.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
*/
Prompt.prototype.suffix = function( str ) {
str || (str = "");
return (str.length < 1 || /([a-z])$/i.test(str) ? str + ":" : str).trim() + " ";
};
/**
* Generate the prompt question string
* @return {String} prompt question string
*/
Prompt.prototype.getQuestion = function() {
var message = _.compose(this.prefix, this.suffix)(this.opt.message);
// Append the default if available, and if question isn't answered
if ( this.opt.default != null && this.status !== "answered" ) {
message += "("+ this.opt.default + ") ";
}
return message;
};