Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
+0
-0
@@ -0,0 +0,0 @@ # http://editorconfig.org |
+0
-0
@@ -0,0 +0,0 @@ { |
+0
-0
@@ -0,0 +0,0 @@ language: node_js |
@@ -0,0 +0,0 @@ /** |
@@ -0,0 +0,0 @@ /** |
@@ -0,0 +0,0 @@ /** |
+0
-0
@@ -0,0 +0,0 @@ /** |
@@ -0,0 +0,0 @@ /** |
@@ -0,0 +0,0 @@ /** |
@@ -0,0 +0,0 @@ /** |
+0
-0
@@ -0,0 +0,0 @@ /*jshint strict:false */ |
+4
-0
@@ -94,2 +94,6 @@ /** | ||
| if ( _.isFunction(question.default) ) { | ||
| question.default = question.default( this.answers ); | ||
| } | ||
| if ( _.isFunction(question.choices) ) { | ||
@@ -96,0 +100,0 @@ question.choices = question.choices( this.answers ); |
@@ -0,0 +0,0 @@ /** |
@@ -0,0 +0,0 @@ /** |
@@ -0,0 +0,0 @@ /** |
@@ -0,0 +0,0 @@ /** |
@@ -0,0 +0,0 @@ /** |
@@ -0,0 +0,0 @@ /** |
@@ -0,0 +0,0 @@ /** |
@@ -0,0 +0,0 @@ /** |
@@ -0,0 +0,0 @@ /** |
@@ -0,0 +0,0 @@ /** |
+1
-1
| { | ||
| "name": "inquirer", | ||
| "version": "0.2.3", | ||
| "version": "0.2.4", | ||
| "description": "A collection of common interactive command line user interfaces.", | ||
@@ -5,0 +5,0 @@ "main": "lib/inquirer.js", |
+1
-1
@@ -69,3 +69,3 @@ Inquirer.js [](http://travis-ci.org/SBoudrias/Inquirer.js) | ||
| + **message**: (String) The question to print. | ||
| + **default**: (String) Default value to use if nothing is entered | ||
| + **default**: (String|Function) Default value to use if nothing is entered, or a function that returns the default value. If defined as a function, the first parameter will be the current inquirer session answers. | ||
| + **choices**: (Array|Function) Choices array or a function returning a choices array. If defined as a function, the first parameter will be the current inquirer session answers. | ||
@@ -72,0 +72,0 @@ Array values can be simple `strings`, or `objects` containing a `name` (to display) and a `value` properties (to save in the answers hash). |
@@ -0,0 +0,0 @@ module.exports = { |
@@ -0,0 +0,0 @@ var EventEmitter = require("events").EventEmitter; |
@@ -0,0 +0,0 @@ /** |
@@ -93,2 +93,32 @@ /** | ||
| it("should parse `default` if passed as a function", function( done ) { | ||
| var stubDefault = "foo"; | ||
| inquirer.prompts.stub = function( params ) { | ||
| this.opt = { | ||
| when: function() { return true; } | ||
| }; | ||
| expect(params.default).to.equal(stubDefault); | ||
| done(); | ||
| }; | ||
| inquirer.prompts.stub.prototype.run = function() {}; | ||
| var prompts = [{ | ||
| type: "input", | ||
| name: "name1", | ||
| message: "message", | ||
| default: "bar" | ||
| }, { | ||
| type: "stub", | ||
| name: "name", | ||
| message: "message", | ||
| default: function( answers ) { | ||
| expect(answers.name1).to.equal("bar"); | ||
| return stubDefault; | ||
| } | ||
| }]; | ||
| inquirer.prompt(prompts, function() {}); | ||
| inquirer.rl.emit("line"); | ||
| }); | ||
| it("should parse `choices` if passed as a function", function( done ) { | ||
@@ -95,0 +125,0 @@ var stubChoices = [ "foo", "bar" ]; |
@@ -0,0 +0,0 @@ var expect = require("chai").expect; |
@@ -0,0 +0,0 @@ var expect = require("chai").expect; |
@@ -0,0 +0,0 @@ var expect = require("chai").expect; |
@@ -0,0 +0,0 @@ var expect = require("chai").expect; |
@@ -0,0 +0,0 @@ var expect = require("chai").expect; |
@@ -0,0 +0,0 @@ var expect = require("chai").expect; |
@@ -0,0 +0,0 @@ var expect = require("chai").expect; |
@@ -0,0 +0,0 @@ var expect = require("chai").expect; |
@@ -0,0 +0,0 @@ var expect = require("chai").expect; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
| # http://editorconfig.org | ||
| root = true | ||
| [*] | ||
| indent_style = space | ||
| indent_size = 2 | ||
| charset = utf-8 | ||
| trim_trailing_whitespace = true | ||
| insert_final_newline = true | ||
| [*.md] | ||
| trim_trailing_whitespace = false |
| { | ||
| "node" : true, | ||
| "bitwise" : true, | ||
| "boss" : true, | ||
| "browser" : true, | ||
| "camelcase" : true, | ||
| "debug" : true, | ||
| "eqeqeq" : true, | ||
| "eqnull" : true, | ||
| "esnext" : true, | ||
| "expr" : true, | ||
| "immed" : true, | ||
| "iterator" : true, | ||
| "lastsemic" : true, | ||
| "laxbreak" : true, | ||
| "laxcomma" : true, | ||
| "loopfunc" : true, | ||
| "maxlen" : 120, | ||
| "multistr" : true, | ||
| "newcap" : true, | ||
| "noarg" : true, | ||
| "onecase" : true, | ||
| "onevar" : false, | ||
| "plusplus" : false, | ||
| "proto" : true, | ||
| "quotmark" : "double", | ||
| "regexdash" : true, | ||
| "regexp" : true, | ||
| "scripturl" : true, | ||
| "shadow" : true, | ||
| "smarttabs" : true, | ||
| "strict" : false, | ||
| "sub" : true, | ||
| "supernew" : true, | ||
| "undef" : true, | ||
| "validthis" : true, | ||
| "withstmt" : true, | ||
| "globals": { | ||
| "describe": true, | ||
| "it": true, | ||
| "beforeEach": true, | ||
| "afterEach": true | ||
| } | ||
| } |
Sorry, the diff of this file is not supported yet
| language: node_js | ||
| node_js: | ||
| - "0.8" | ||
| - "0.10" |
| /** | ||
| * Nested Inquirer call | ||
| */ | ||
| "use strict"; | ||
| var inquirer = require("../lib/inquirer"); | ||
| inquirer.prompt({ | ||
| type: "input", | ||
| name: "candy", | ||
| message: "What's your favorite candy?" | ||
| }, function( answers ) { | ||
| inquirer.prompt({ | ||
| type: "input", | ||
| name: "liquor", | ||
| message: "And your favorite liquor?" | ||
| }); | ||
| }); |
| /** | ||
| * Pizza delivery prompt example | ||
| * run example by writing `node pizza.js` in your console | ||
| */ | ||
| "use strict"; | ||
| var inquirer = require("../lib/inquirer"); | ||
| console.log("Hi, welcome to Node Pizza"); | ||
| var questions = [ | ||
| { | ||
| type: "confirm", | ||
| name: "toBeDelivered", | ||
| message: "Is it for a delivery", | ||
| default: false | ||
| }, | ||
| { | ||
| type: "input", | ||
| name: "phone", | ||
| message: "What's your phone number", | ||
| validate: function( value ) { | ||
| var pass = value.match(/^([01]{1})?[\-\.\s]?\(?(\d{3})\)?[\-\.\s]?(\d{3})[\-\.\s]?(\d{4})\s?((?:#|ext\.?\s?|x\.?\s?){1}(?:\d+)?)?$/i); | ||
| if (pass) { | ||
| return true; | ||
| } else { | ||
| return "Please enter a valid phone number"; | ||
| } | ||
| } | ||
| }, | ||
| { | ||
| type: "list", | ||
| name: "size", | ||
| message: "What size do you need", | ||
| choices: [ "Large", "Medium", "Small" ], | ||
| filter: function( val ) { return val.toLowerCase(); } | ||
| }, | ||
| { | ||
| type: "input", | ||
| name: "quantity", | ||
| message: "How many do you need", | ||
| validate: function( value ) { | ||
| var valid = !isNaN(parseFloat(value)); | ||
| return valid || "Please enter a number"; | ||
| }, | ||
| filter: Number | ||
| }, | ||
| { | ||
| type: "list", | ||
| name: "toppings", | ||
| message: "What about the toping", | ||
| choices: [ | ||
| { | ||
| name: "Peperonni and chesse", | ||
| value: "PeperonniChesse" | ||
| }, | ||
| { | ||
| name: "All dressed", | ||
| value: "alldressed" | ||
| }, | ||
| { | ||
| name: "Hawaïan", | ||
| value: "hawain" | ||
| } | ||
| ], | ||
| default: 1 | ||
| }, | ||
| { | ||
| type: "rawlist", | ||
| name: "liquor", | ||
| message: "You also get a free 2L liquor", | ||
| choices: [ "Pepsi", "7up", "Coke" ] | ||
| }, | ||
| { | ||
| type: "input", | ||
| name: "comments", | ||
| message: "Any comments on your purchase experience", | ||
| default: "Nope, all good!" | ||
| }, | ||
| { | ||
| type: "list", | ||
| name: "prize", | ||
| message: "For leaving a comments, you get a freebie", | ||
| choices: [ "cake", "fries" ], | ||
| when: function( answers ) { | ||
| return answers.comments !== "Nope, all good!"; | ||
| } | ||
| } | ||
| ]; | ||
| inquirer.prompt( questions, function( answers ) { | ||
| console.log("\nOrder receipt:"); | ||
| console.log( JSON.stringify(answers, null, " ") ); | ||
| }); |
| /*jshint strict:false */ | ||
| module.exports = function( grunt ) { | ||
| grunt.initConfig({ | ||
| jshint: { | ||
| options: { | ||
| jshintrc : ".jshintrc" | ||
| }, | ||
| files: [ "lib/**/*.js" ] | ||
| }, | ||
| simplemocha: { | ||
| options: { | ||
| ui: "bdd", | ||
| reporter: "spec" | ||
| }, | ||
| all: "test/specs/**/*.js" | ||
| } | ||
| }); | ||
| grunt.loadNpmTasks("grunt-contrib-jshint"); | ||
| grunt.loadNpmTasks("grunt-simple-mocha"); | ||
| grunt.loadNpmTasks('grunt-release'); | ||
| grunt.registerTask("default", [ "jshint", "simplemocha" ]); | ||
| }; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
| /** | ||
| * Inquirer.js | ||
| * A collection of common interactive command line user interfaces. | ||
| */ | ||
| "use strict"; | ||
| var _ = require("lodash"); | ||
| var async = require("async"); | ||
| var clc = require("cli-color"); | ||
| var readlineFacade = require("./utils/readline"); | ||
| var utils = require("./utils/utils"); | ||
| /** | ||
| * Module exports | ||
| */ | ||
| var cli = module.exports; | ||
| /** | ||
| * Client interfaces | ||
| */ | ||
| cli.prompts = { | ||
| list : require("./prompts/list"), | ||
| input : require("./prompts/input"), | ||
| confirm : require("./prompts/confirm"), | ||
| rawlist : require("./prompts/rawlist") | ||
| }; | ||
| /** | ||
| * Public CLI helper interface | ||
| * @param {array} questions Questions settings array | ||
| * @param {Function} cb Callback being passed the user answers | ||
| * @return {null} | ||
| */ | ||
| cli.prompt = function( questions, allDone ) { | ||
| var self = this; | ||
| // Instantiate the Readline interface | ||
| // @Note: Don't reassign if already present (allow test to override the Stream) | ||
| this.rl || (this.rl = readlineFacade.createInterface()); | ||
| this.rl.resume(); | ||
| // Keep global reference to the answers | ||
| this.answers = {}; | ||
| // Make sure questions is an array. | ||
| if ( !_.isArray(questions) ) { | ||
| questions = [questions]; | ||
| } | ||
| // Propagate keypress events directly on the readline | ||
| process.stdin.on( "keypress", this.onKeypress ); | ||
| // Make sure new prompt start on a newline when closing | ||
| self.rl.on( "SIGINT", this.onForceClose ); | ||
| // Control flow functions | ||
| var onCompletion = function() { | ||
| // Remove events listeners | ||
| this.rl.removeListener("SIGINT", this.onForceClose); | ||
| process.stdin.removeListener( "keypress", this.onKeypress ); | ||
| // Close the readline | ||
| this.rl.close(); | ||
| this.rl = null; | ||
| if ( _.isFunction(allDone) ) { | ||
| allDone(this.answers); | ||
| } | ||
| }.bind(this); | ||
| var onEach = function( question, done ) { | ||
| // Callback to save answer and continu to next question | ||
| var after = function( answer ) { | ||
| this.answers[question.name] = answer; | ||
| done( null ); | ||
| }.bind(this); | ||
| // Default type to input | ||
| if ( !this.prompts[question.type] ) { | ||
| question.type = "input"; | ||
| } | ||
| var prompt = new this.prompts[question.type]( question, this.rl ); | ||
| // Check if prompt should be runned (if `when` return true) | ||
| utils.runAsync( prompt.opt.when, function( continu ) { | ||
| if( continu ) { | ||
| prompt.run( after ); | ||
| } else { | ||
| done( null ); | ||
| } | ||
| }, this.answers ); | ||
| }.bind(this); | ||
| // Start running the questions | ||
| async.mapSeries( questions, onEach, onCompletion ); | ||
| }; | ||
| /** | ||
| * Propagate keypress to the readline | ||
| * @return {null} | ||
| */ | ||
| cli.onKeypress = function( s, key ) { | ||
| // Ignore `enter` key (readline `line` event is the only one we care for) | ||
| if ( key && (key.name === "enter" || key.name === "return") ) return; | ||
| this.rl.emit( "keypress", s, key ); | ||
| }.bind(cli); | ||
| /** | ||
| * Handle the ^C exit | ||
| * @return {null} | ||
| */ | ||
| cli.onForceClose = function() { | ||
| this.rl.output.unmute(); | ||
| // close the readline | ||
| this.rl.close(); | ||
| this.rl = null; | ||
| console.log("\n"); // Line return | ||
| }.bind(cli); |
| /** | ||
| * Base prompt implementation | ||
| * Should be extended by prompt types. | ||
| */ | ||
| var _ = require("lodash"); | ||
| var utils = require("../utils/utils"); | ||
| var clc = require("cli-color"); | ||
| var ansiTrim = require("cli-color/lib/trim"); | ||
| var readline = require("readline"); | ||
| /** | ||
| * Module exports | ||
| */ | ||
| module.exports = Prompt; | ||
| /** | ||
| * Prompt constructor | ||
| */ | ||
| function Prompt( question, rl ) { | ||
| // Setup instance defaults property | ||
| _.assign( this, { | ||
| height : 0, | ||
| answered : false | ||
| }); | ||
| // Set defaults prompt options | ||
| this.opt = _.defaults( 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 = utils.normalizeChoices( this.opt.choices ); | ||
| } | ||
| this.rl = rl; | ||
| return this; | ||
| } | ||
| /** | ||
| * 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"); | ||
| }; | ||
| /** | ||
| * Remove the prompt from screen | ||
| * @param {Number} Extra lines to remove (probably to compensate the "enter" key line | ||
| * return) | ||
| * @return {Prompt} self | ||
| */ | ||
| Prompt.prototype.clean = function( extra ) { | ||
| _.isNumber(extra) || (extra = 0); | ||
| var len = this.height + extra; | ||
| while ( len-- ) { | ||
| readline.moveCursor(this.rl.output, -clc.width, 0); | ||
| readline.clearLine(this.rl.output, 0); | ||
| if ( len ) readline.moveCursor(this.rl.output, 0, -1); | ||
| } | ||
| return this; | ||
| }; | ||
| /** | ||
| * Move cursor down by `x` | ||
| * @param {Number} x How far to go down (default to 1) | ||
| * @return {Prompt} self | ||
| */ | ||
| Prompt.prototype.down = function( x ) { | ||
| _.isNumber(x) || (x = 1); | ||
| // @bug: Write new lines instead of moving cursor as unix system don't allocate a new | ||
| // line when the cursor is moved over there. | ||
| while ( x-- ) { | ||
| this.rl.output.write("\n"); | ||
| } | ||
| return this; | ||
| }; | ||
| /** | ||
| * Move cursor up by `x` | ||
| * @param {Number} x How far to go up (default to 1) | ||
| * @return {Prompt} self | ||
| */ | ||
| Prompt.prototype.up = function( x ) { | ||
| _.isNumber(x) || (x = 1); | ||
| readline.moveCursor( this.rl.output, 0, -x ); | ||
| return this; | ||
| }; | ||
| /** | ||
| * Write error message under the current line | ||
| * @param {String} Error Error message | ||
| * @return {Prompt} Self | ||
| */ | ||
| Prompt.prototype.error = function( error ) { | ||
| var errMsg = clc.red(">> ") + | ||
| (error || "Please enter a valid value"); | ||
| this.write( errMsg ); | ||
| this.up(); | ||
| return this; | ||
| }; | ||
| /** | ||
| * 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 "[" + clc.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 && !this.answered ) { | ||
| message += "("+ this.opt.default + ") "; | ||
| } | ||
| return message; | ||
| }; | ||
| /** | ||
| * Write a string to the stdout | ||
| * @return {Self} | ||
| */ | ||
| Prompt.prototype.write = function( str ) { | ||
| this.rl.output.write( str ); | ||
| return this; | ||
| }; |
| /** | ||
| * `confirm` type prompt | ||
| */ | ||
| var _ = require("lodash"); | ||
| var util = require("util"); | ||
| var clc = require("cli-color"); | ||
| var Base = require("./base"); | ||
| /** | ||
| * 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; | ||
| }.bind(this) | ||
| }); | ||
| 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) | ||
| this.rl.once( "line", this.onSubmit.bind(this) ); | ||
| // Init | ||
| this.render(); | ||
| return this; | ||
| }; | ||
| /** | ||
| * Render the prompt to screen | ||
| * @return {Prompt} self | ||
| */ | ||
| Prompt.prototype.render = function() { | ||
| var message = this.getQuestion(); | ||
| this.write( message ); | ||
| this.rl.setPrompt( message ); | ||
| this.height = message.split(/\n/).length; | ||
| return this; | ||
| }; | ||
| /** | ||
| * When user press "enter" key | ||
| */ | ||
| Prompt.prototype.onSubmit = function( input ) { | ||
| this.answered = true; | ||
| // Filter value to write final answer to screen | ||
| this.filter( input, function( output ) { | ||
| this.clean(1).render(); | ||
| this.write( clc.cyan(output ? "Yes" : "No") + "\n" ); | ||
| this.done( input ); // send "input" because the master class will refilter | ||
| }.bind(this)); | ||
| }; |
| /** | ||
| * `input` type prompt | ||
| */ | ||
| var _ = require("lodash"); | ||
| var util = require("util"); | ||
| var clc = require("cli-color"); | ||
| var Base = require("./base"); | ||
| /** | ||
| * 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) | ||
| this.rl.on( "line", this.onSubmit.bind(this) ); | ||
| // Init | ||
| this.render(); | ||
| return this; | ||
| }; | ||
| /** | ||
| * Render the prompt to screen | ||
| * @return {Prompt} self | ||
| */ | ||
| Prompt.prototype.render = function() { | ||
| var message = this.getQuestion(); | ||
| this.write( message ); | ||
| this.rl.setPrompt( message ); | ||
| this.height = message.split(/\n/).length; | ||
| return this; | ||
| }; | ||
| /** | ||
| * When user press `enter` key | ||
| */ | ||
| Prompt.prototype.onSubmit = function( input ) { | ||
| var value = input || this.opt.default || ""; | ||
| this.validate( value, function( isValid ) { | ||
| if ( isValid === true ) { | ||
| this.answered = true; | ||
| // Re-render prompt | ||
| this.down().clean(2).render(); | ||
| // Render answer | ||
| this.write( clc.cyan(value) + "\n" ); | ||
| this.rl.removeAllListeners("line"); | ||
| this.done( value ); | ||
| } else { | ||
| this.error(isValid).clean().render(); | ||
| } | ||
| }.bind(this)); | ||
| }; |
| /** | ||
| * `list` type prompt | ||
| */ | ||
| var _ = require("lodash"); | ||
| var util = require("util"); | ||
| var clc = require("cli-color"); | ||
| var Base = require("./base"); | ||
| /** | ||
| * 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 ( _.isNumber(def) && def >= 0 && def < this.opt.choices.length ) { | ||
| this.selected = def; | ||
| } | ||
| // Make sure no default is set (so it won't be printed) | ||
| this.opt.default = null; | ||
| 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; | ||
| // Move the selected marker on keypress | ||
| this.rl.on( "keypress", this.onKeypress.bind(this) ); | ||
| // Once user confirm (enter key) | ||
| this.rl.once( "line", this.onSubmit.bind(this) ); | ||
| // Init the prompt | ||
| this.render(); | ||
| this.rl.output.write( this.hideCursor() ); | ||
| // Prevent user from writing | ||
| this.rl.output.mute(); | ||
| return this; | ||
| }; | ||
| /** | ||
| * Render the prompt to screen | ||
| * @return {Prompt} self | ||
| */ | ||
| Prompt.prototype.render = function() { | ||
| // Render question | ||
| var message = this.getQuestion(); | ||
| var choicesStr = this.getChoices(); | ||
| if ( this.firstRender ) { | ||
| message += clc.blackBright("(Use arrow keys)"); | ||
| } | ||
| // Render choices or answer depending on the state | ||
| if ( this.answered ) { | ||
| message += clc.cyan(this.opt.choices[this.selected].name) + "\n"; | ||
| } else { | ||
| message += choicesStr; | ||
| } | ||
| this.firstRender = false; | ||
| var msgLines = message.split(/\n/); | ||
| this.height = msgLines.length; | ||
| // Write message to screen and setPrompt to control backspace | ||
| this.rl.setPrompt( _.last(msgLines) ); | ||
| this.write( message ); | ||
| return this; | ||
| }; | ||
| /** | ||
| * Generate the prompt choices string | ||
| * @return {String} Choices string | ||
| */ | ||
| Prompt.prototype.getChoices = function() { | ||
| var output = ""; | ||
| this.opt.choices.forEach(function( choice, i ) { | ||
| output += "\n "; | ||
| if ( i === this.selected ) { | ||
| output += clc.cyan("[X] " + choice.name); | ||
| } else { | ||
| output += "[ ] " + choice.name; | ||
| } | ||
| output += " "; | ||
| }.bind(this)); | ||
| return output; | ||
| }; | ||
| /** | ||
| * When user press `enter` key | ||
| */ | ||
| Prompt.prototype.onSubmit = function() { | ||
| var choice = this.opt.choices[this.selected]; | ||
| this.answered = true; | ||
| // Rerender prompt | ||
| this.rl.output.unmute(); | ||
| this.clean().render(); | ||
| this.rl.output.write( this.showCursor() ); | ||
| this.rl.removeAllListeners("keypress"); | ||
| this.done( choice.value ); | ||
| }; | ||
| /** | ||
| * When user press a key | ||
| */ | ||
| Prompt.prototype.onKeypress = function( s, key ) { | ||
| // Only process up and down key | ||
| if ( !key || (key.name !== "up" && key.name !== "down") ) return; | ||
| this.rl.output.unmute(); | ||
| var len = this.opt.choices.length; | ||
| if ( key.name === "up" ) { | ||
| (this.selected > 0) ? this.selected-- : (this.selected = len - 1); | ||
| } else if ( key.name === "down" ) { | ||
| (this.selected < len - 1) ? this.selected++ : (this.selected = 0); | ||
| } | ||
| // Rerender | ||
| this.clean().render(); | ||
| this.rl.output.mute(); | ||
| }; | ||
| /** | ||
| * Hide cursor | ||
| * @return {String} hide cursor ANSI string | ||
| */ | ||
| Prompt.prototype.hideCursor = function() { | ||
| return "\033[?25l"; | ||
| }; | ||
| /** | ||
| * Show cursor | ||
| * @return {String} show cursor ANSI string | ||
| */ | ||
| Prompt.prototype.showCursor = function() { | ||
| return "\033[?25h"; | ||
| }; |
| /** | ||
| * `rawlist` type prompt | ||
| */ | ||
| var _ = require("lodash"); | ||
| var util = require("util"); | ||
| var clc = require("cli-color"); | ||
| var Base = require("./base"); | ||
| /** | ||
| * Module exports | ||
| */ | ||
| module.exports = Prompt; | ||
| /** | ||
| * Constructor | ||
| */ | ||
| function Prompt() { | ||
| Base.apply( this, arguments ); | ||
| if (!this.opt.choices) { | ||
| this.throwParamError("choices"); | ||
| } | ||
| this.selected = 0; | ||
| this.rawDefault = 0; | ||
| var def = this.opt.default; | ||
| if ( _.isNumber(def) && def >= 0 && def < this.opt.choices.length ) { | ||
| this.selected = this.rawDefault = def; | ||
| } | ||
| // Make sure no default is set (so it won't be printed) | ||
| this.opt.default = null; | ||
| 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; | ||
| // Save user answer and update prompt to show selected option. | ||
| this.rl.on( "line", this.onSubmit.bind(this) ); | ||
| this.rl.on( "keypress", this.onKeypress.bind(this) ); | ||
| // Init the prompt | ||
| this.render(); | ||
| return this; | ||
| }; | ||
| /** | ||
| * Render the prompt to screen | ||
| * @return {Prompt} self | ||
| */ | ||
| Prompt.prototype.render = function() { | ||
| // Render question | ||
| var message = this.getQuestion(); | ||
| var choicesStr = this.getChoices(); | ||
| if ( this.answered ) { | ||
| message += clc.cyan(this.opt.choices[this.selected].name) + "\n"; | ||
| } else { | ||
| message += choicesStr; | ||
| message += "\n Answer: "; | ||
| } | ||
| var msgLines = message.split(/\n/); | ||
| this.height = msgLines.length; | ||
| this.rl.setPrompt( _.last(msgLines) ); | ||
| this.write( message ); | ||
| return this; | ||
| }; | ||
| /** | ||
| * Generate the prompt choices string | ||
| * @return {String} Choices string | ||
| */ | ||
| Prompt.prototype.getChoices = function() { | ||
| var output = ""; | ||
| this.opt.choices.forEach(function( choice, i ) { | ||
| var display = "\n " + (i + 1) + ") " + choice.name; | ||
| if ( i === this.selected ) { | ||
| display = clc.cyan( display ); | ||
| } | ||
| output += display; | ||
| }.bind(this)); | ||
| return output; | ||
| }; | ||
| /** | ||
| * When user press `enter` key | ||
| */ | ||
| Prompt.prototype.onSubmit = function( input ) { | ||
| if ( input == null || input === "" ) { | ||
| input = this.rawDefault; | ||
| } else { | ||
| input -= 1; | ||
| } | ||
| // Input is valid | ||
| if ( this.opt.choices[input] != null ) { | ||
| this.answered = true; | ||
| this.selected = input; | ||
| // Re-render prompt | ||
| this.down().clean(2).render(); | ||
| this.rl.removeAllListeners("line"); | ||
| this.rl.removeAllListeners("keypress"); | ||
| this.done( this.opt.choices[this.selected].value ); | ||
| return; | ||
| } | ||
| // Input is invalid | ||
| this | ||
| .error("Please enter a valid index") | ||
| .write( clc.bol(0, true) ) | ||
| .clean() | ||
| .render(); | ||
| }; | ||
| /** | ||
| * When user press a key | ||
| */ | ||
| Prompt.prototype.onKeypress = function( s, key ) { | ||
| var index = this.rl.line.length ? Number(this.rl.line) - 1 : 0; | ||
| if ( this.opt.choices[index] ) { | ||
| this.selected = index; | ||
| } else { | ||
| this.selected = undefined; | ||
| } | ||
| this.down().clean(1).render().write( this.rl.line ); | ||
| }; |
| /** | ||
| * Readline API façade to fix some issues | ||
| * @Note: May look a bit like Monkey patching... if you know a better way let me know. | ||
| */ | ||
| "use strict"; | ||
| var _ = require("lodash"); | ||
| var readline = require("readline"); | ||
| var MuteStream = require("mute-stream"); | ||
| var ansiTrim = require("cli-color/lib/trim"); | ||
| /** | ||
| * Module export | ||
| */ | ||
| var Interface = module.exports = {}; | ||
| /** | ||
| * Create a readline interface | ||
| * @param {Object} opt Readline option hash | ||
| * @return {readline} the new readline interface | ||
| */ | ||
| Interface.createInterface = function( opt ) { | ||
| opt || (opt = {}); | ||
| var filteredOpt = opt; | ||
| // Default `input` to stdin | ||
| filteredOpt.input = opt.input || process.stdin; | ||
| // Add mute capabilities to the output | ||
| var ms = new MuteStream(); | ||
| ms.pipe( opt.output || process.stdout ); | ||
| filteredOpt.output = ms; | ||
| // Create the readline | ||
| var rl = readline.createInterface( filteredOpt ); | ||
| // Fix bug with refreshLine | ||
| rl._refreshLine = _.wrap(rl._refreshLine, function( func ) { | ||
| func.call(rl); | ||
| var line = this._prompt + this.line; | ||
| var visualLength = ansiTrim(line).length; | ||
| readline.moveCursor(this.output, -line.length, 0); | ||
| readline.moveCursor(this.output, visualLength, 0); | ||
| }); | ||
| // Prevent arrows from breaking the question line | ||
| var origWrite = rl._ttyWrite; | ||
| rl._ttyWrite = function( s, key ) { | ||
| key || (key = {}); | ||
| if ( key.name === "up" ) return; | ||
| if ( key.name === "down" ) return; | ||
| origWrite.apply( this, arguments ); | ||
| }; | ||
| return rl; | ||
| }; |
| /** | ||
| * Utility functions | ||
| */ | ||
| "use strict"; | ||
| var _ = require("lodash"); | ||
| /** | ||
| * Module exports | ||
| */ | ||
| var utils = module.exports; | ||
| /** | ||
| * Normalize choices array | ||
| * @param {Array} choices The avaiable prompt choices | ||
| * @return {Array} Normalized choices containing `name`/`value` hash | ||
| */ | ||
| utils.normalizeChoices = function normalizeChoices( choices ) { | ||
| return _.map( choices, function( val ) { | ||
| if ( _.isString(val) ) { | ||
| return { name : val, value: val }; | ||
| } | ||
| return { | ||
| name: val.name || val.value, | ||
| value: val.value || val.name | ||
| }; | ||
| }); | ||
| }; | ||
| /** | ||
| * Run a function asynchronously or synchronously | ||
| * @param {Function} func Function to run | ||
| * @param {Function} cb Callback function passed the `func` returned value | ||
| * @...rest {Mixed} rest Arguments to pass to `func` | ||
| * @return {Null} | ||
| */ | ||
| utils.runAsync = function( func, cb ) { | ||
| var rest = []; | ||
| var len = 1; | ||
| while ( len++ < arguments.length ) { | ||
| rest.push( arguments[len] ); | ||
| } | ||
| var async = false; | ||
| var isValid = func.apply({ | ||
| async: function() { | ||
| async = true; | ||
| return _.once(cb); | ||
| } | ||
| }, rest ); | ||
| if ( !async ) { | ||
| cb(isValid); | ||
| } | ||
| }; |
Sorry, the diff of this file is not supported yet
| { | ||
| "name": "inquirer", | ||
| "version": "0.1.12", | ||
| "description": "A collection of common interactive command line user interfaces.", | ||
| "main": "lib/inquirer.js", | ||
| "scripts": { | ||
| "test": "grunt --verbose" | ||
| }, | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "git://github.com/SBoudrias/Inquirer.js.git" | ||
| }, | ||
| "keywords": [ | ||
| "command", | ||
| "prompt", | ||
| "stdin", | ||
| "cli" | ||
| ], | ||
| "author": { | ||
| "name": "Simon Boudrias", | ||
| "email": "admin@simonboudrias.com" | ||
| }, | ||
| "license": "MIT", | ||
| "dependencies": { | ||
| "lodash": "~1.2.1", | ||
| "async": "~0.2.8", | ||
| "cli-color": "~0.2.2", | ||
| "mute-stream": "0.0.3" | ||
| }, | ||
| "devDependencies": { | ||
| "grunt": "~0.4.1", | ||
| "grunt-cli": "~0.1.8", | ||
| "grunt-simple-mocha": "~0.4.0", | ||
| "mocha": "~1.9.0", | ||
| "chai": "~1.6.0", | ||
| "grunt-contrib-jshint": "~0.5.1", | ||
| "sinon": "~1.7.2", | ||
| "proxyquire": "~0.4.1", | ||
| "grunt-release": "~0.3.3" | ||
| }, | ||
| "readme": "Inquirer.js [](http://travis-ci.org/SBoudrias/Inquirer.js)\n=====================\n\nA collection of common interactive command line user interfaces.\n\n\nGoal and philosophy\n---------------------\n\nWe strive at providing easily embeddable and beatiful command line interface for Node.js ;\nsome hope in becoming the CLI Xanadu.\n\n_Inquirer_ should ease the process of asking end user questions, parsing, validating answers, and providing error feedback.\n\n_Inquirer_ provide the user interface, and the inquiry session flow. If you're searching for a full blown command line program utility, then check out [Commander.js](https://github.com/visionmedia/commander.js) (inspired by) or [Cli-color](https://github.com/medikoo/cli-color) (used internally).\n\n\nDocumentation\n=====================\n\n\nInstallation\n---------------------\n\n``` prompt\nnpm install inquirer\n```\n\n```javascript\nvar inquirer = require(\"inquirer\");\ninquirer.prompt([/* Pass your questions in here */], function( answers ) {\n\t// Use user feedback for... whatever!!\n});\n```\n\n\nExamples (Run it and see it)\n---------------------\n\nCheckout the `examples/` folder for code and interface examples.\n\n``` prompt\nnode examples/pizza.js\n# etc\n```\n\n\nMethods\n---------------------\n\n### `inquirer.prompt( questions, callback )`\n\nLaunch the prompt interface (inquiry session)\n\n+ **questions** (Array) containing [Question Object](#question)\n+ **callback** (Function) first parameter is the [Answers Object](#answers)\n\n\nObjects\n---------------------\n\n### Question\nA question object is a `hash` containing question related values:\n\n+ **type**: (String) Type of the prompt. Defaults: `input` - Possible values: `input`, `confirm`,\n`list`, `rawlist`\n+ **name**: (String) The name to use when storing the answer in the anwers hash.\n+ **message**: (String) The question to print.\n+ **default**: (String) Default value to use if nothing is entered\n+ **choices**: (Array) Choices array. \nValues can be simple `string`s, or `object`s containing a `name` (to display) and a `value` properties (to save in the answers hash).\n+ **validate**: (Function) Receive the user input and should return `true` if the value is valid, and an error message (`String`) otherwise. If `false` is returned, a default error message is provided.\n+ **filter**: (Function) Receive the user input and return the filtered value to be used inside the program. The value returned will be added to the _Answers_ hash.\n+ **when**: (Function) Receive the current user answers hash and should return `true` or `false` depending on wheter or not this question should be asked.\n\n`validate`, `filter` and `when` functions can be asynchronously using `this.async()`. You just have to pass the value you'd normally return to the callback option.\n\n``` javascript\n{\n validate: function(input) {\n\n // Declare function as asynchronous, and save the done callback\n var done = this.async();\n\n // Do async stuff\n setTimeout(function() {\n if (typeof input !== \"number\") {\n // Pass the return value in the done callback\n done(\"You need to provide a number\");\n return;\n }\n // Pass the return value in the done callback\n done(true);\n }, 3000);\n }\n}\n```\n\n### Answers\nA key/value hash containing the client answers in each prompt.\n\n+ **Key** The `name` property of the _question_ object\n+ **Value** (Depends on the prompt)\n + `confirm`: (Boolean)\n + `input` : User input (filtered if `filter` is defined) (String)\n + `rawlist`, `list` : Selected choice value (or name if no value specified) (String)\n\n\nPrompts\n---------------------\n\n### List - `{ type: \"list\" }`\n\nTake `type`, `name`, `message`, `choices`[, `default`, `filter`] properties. (Note that\ndefault must the choice `index` in the array)\n\n``` prompt\n[?] What about the toping: (Use arrow key)\n [X] Peperonni and chesse\n [ ] All dressed\n [ ] Hawaïan\n```\n\n### Raw List - `{ type: \"rawlist\" }`\n\nTake `type`, `name`, `message`, `choices`[, `default`, `filter`] properties. (Note that\ndefault must the choice `index` in the array)\n\n``` prompt\n[?] You also get a free 2L liquor: \n 1) Pepsi\n 2) 7up\n 3) Coke\n Answer: \n```\n\n### Confirm - `{ type: \"confirm\" }`\n\nTake `type`, `name`, `message`[, `default`] properties.\n\n``` prompt\n[?] Is it for a delivery: (Y/n)\n```\n\n### Input - `{ type: \"input\" }`\n\nTake `type`, `name`, `message`[, `default`, `filter`, `validate`] properties.\n\n``` prompt\n[?] Any comments on your purchase experience: (Nope, all good!)\n```\n\n\nNews on the march (Release notes)\n=====================\n\n+ **0.1.7** : Add a hierarchical prompt API with `when`, allow lists from having a default\n+ **0.1.6** : Fix bug on unix and minor enhancement\n+ **0.1.5** : Enhance visual style; prompts are now more succint. Lots of bug fixes.\n+ **0.1.3** : Add async support for validation and filtering functions.\n+ **0.1.0** : First official release. There's 4 prompt types: `input`, `confirm`, `list` and\n`rawlist`. There's functionnality to allow the validation of input, and the filtering of values.\n\n\nContributing\n=====================\n\n**Style Guide**: Please base yourself on [Idiomatic.js](https://github.com/rwldrn/idiomatic.js) style guide with two space indent \n**Unit test**: Unit test are wrote in Mocha. Please add a unit test for every new feature\nor bug fix. `npm test` to run the test suite. \n**Documentation**: Add documentation for every API change. Feel free to send corrections\nor better docs! \n\n\nLicense\n=====================\n\nCopyright (c) 2012 Simon Boudrias \nLicensed under the MIT license.\n", | ||
| "readmeFilename": "README.md", | ||
| "bugs": { | ||
| "url": "https://github.com/SBoudrias/Inquirer.js/issues" | ||
| }, | ||
| "_id": "inquirer@0.1.12", | ||
| "_from": "inquirer@~0.1" | ||
| } |
| Inquirer.js [](http://travis-ci.org/SBoudrias/Inquirer.js) | ||
| ===================== | ||
| A collection of common interactive command line user interfaces. | ||
| Goal and philosophy | ||
| --------------------- | ||
| We strive at providing easily embeddable and beatiful command line interface for Node.js ; | ||
| some hope in becoming the CLI Xanadu. | ||
| _Inquirer_ should ease the process of asking end user questions, parsing, validating answers, and providing error feedback. | ||
| _Inquirer_ provide the user interface, and the inquiry session flow. If you're searching for a full blown command line program utility, then check out [Commander.js](https://github.com/visionmedia/commander.js) (inspired by) or [Cli-color](https://github.com/medikoo/cli-color) (used internally). | ||
| Documentation | ||
| ===================== | ||
| Installation | ||
| --------------------- | ||
| ``` prompt | ||
| npm install inquirer | ||
| ``` | ||
| ```javascript | ||
| var inquirer = require("inquirer"); | ||
| inquirer.prompt([/* Pass your questions in here */], function( answers ) { | ||
| // Use user feedback for... whatever!! | ||
| }); | ||
| ``` | ||
| Examples (Run it and see it) | ||
| --------------------- | ||
| Checkout the `examples/` folder for code and interface examples. | ||
| ``` prompt | ||
| node examples/pizza.js | ||
| # etc | ||
| ``` | ||
| Methods | ||
| --------------------- | ||
| ### `inquirer.prompt( questions, callback )` | ||
| Launch the prompt interface (inquiry session) | ||
| + **questions** (Array) containing [Question Object](#question) | ||
| + **callback** (Function) first parameter is the [Answers Object](#answers) | ||
| Objects | ||
| --------------------- | ||
| ### Question | ||
| A question object is a `hash` containing question related values: | ||
| + **type**: (String) Type of the prompt. Defaults: `input` - Possible values: `input`, `confirm`, | ||
| `list`, `rawlist` | ||
| + **name**: (String) The name to use when storing the answer in the anwers hash. | ||
| + **message**: (String) The question to print. | ||
| + **default**: (String) Default value to use if nothing is entered | ||
| + **choices**: (Array) Choices array. | ||
| Values can be simple `string`s, or `object`s containing a `name` (to display) and a `value` properties (to save in the answers hash). | ||
| + **validate**: (Function) Receive the user input and should return `true` if the value is valid, and an error message (`String`) otherwise. If `false` is returned, a default error message is provided. | ||
| + **filter**: (Function) Receive the user input and return the filtered value to be used inside the program. The value returned will be added to the _Answers_ hash. | ||
| + **when**: (Function) Receive the current user answers hash and should return `true` or `false` depending on wheter or not this question should be asked. | ||
| `validate`, `filter` and `when` functions can be asynchronously using `this.async()`. You just have to pass the value you'd normally return to the callback option. | ||
| ``` javascript | ||
| { | ||
| validate: function(input) { | ||
| // Declare function as asynchronous, and save the done callback | ||
| var done = this.async(); | ||
| // Do async stuff | ||
| setTimeout(function() { | ||
| if (typeof input !== "number") { | ||
| // Pass the return value in the done callback | ||
| done("You need to provide a number"); | ||
| return; | ||
| } | ||
| // Pass the return value in the done callback | ||
| done(true); | ||
| }, 3000); | ||
| } | ||
| } | ||
| ``` | ||
| ### Answers | ||
| A key/value hash containing the client answers in each prompt. | ||
| + **Key** The `name` property of the _question_ object | ||
| + **Value** (Depends on the prompt) | ||
| + `confirm`: (Boolean) | ||
| + `input` : User input (filtered if `filter` is defined) (String) | ||
| + `rawlist`, `list` : Selected choice value (or name if no value specified) (String) | ||
| Prompts | ||
| --------------------- | ||
| ### List - `{ type: "list" }` | ||
| Take `type`, `name`, `message`, `choices`[, `default`, `filter`] properties. (Note that | ||
| default must the choice `index` in the array) | ||
| ``` prompt | ||
| [?] What about the toping: (Use arrow key) | ||
| [X] Peperonni and chesse | ||
| [ ] All dressed | ||
| [ ] Hawaïan | ||
| ``` | ||
| ### Raw List - `{ type: "rawlist" }` | ||
| Take `type`, `name`, `message`, `choices`[, `default`, `filter`] properties. (Note that | ||
| default must the choice `index` in the array) | ||
| ``` prompt | ||
| [?] You also get a free 2L liquor: | ||
| 1) Pepsi | ||
| 2) 7up | ||
| 3) Coke | ||
| Answer: | ||
| ``` | ||
| ### Confirm - `{ type: "confirm" }` | ||
| Take `type`, `name`, `message`[, `default`] properties. | ||
| ``` prompt | ||
| [?] Is it for a delivery: (Y/n) | ||
| ``` | ||
| ### Input - `{ type: "input" }` | ||
| Take `type`, `name`, `message`[, `default`, `filter`, `validate`] properties. | ||
| ``` prompt | ||
| [?] Any comments on your purchase experience: (Nope, all good!) | ||
| ``` | ||
| News on the march (Release notes) | ||
| ===================== | ||
| + **0.1.7** : Add a hierarchical prompt API with `when`, allow lists from having a default | ||
| + **0.1.6** : Fix bug on unix and minor enhancement | ||
| + **0.1.5** : Enhance visual style; prompts are now more succint. Lots of bug fixes. | ||
| + **0.1.3** : Add async support for validation and filtering functions. | ||
| + **0.1.0** : First official release. There's 4 prompt types: `input`, `confirm`, `list` and | ||
| `rawlist`. There's functionnality to allow the validation of input, and the filtering of values. | ||
| Contributing | ||
| ===================== | ||
| **Style Guide**: Please base yourself on [Idiomatic.js](https://github.com/rwldrn/idiomatic.js) style guide with two space indent | ||
| **Unit test**: Unit test are wrote in Mocha. Please add a unit test for every new feature | ||
| or bug fix. `npm test` to run the test suite. | ||
| **Documentation**: Add documentation for every API change. Feel free to send corrections | ||
| or better docs! | ||
| License | ||
| ===================== | ||
| Copyright (c) 2012 Simon Boudrias | ||
| Licensed under the MIT license. |
| var EventEmitter = require("events").EventEmitter; | ||
| var sinon = require("sinon"); | ||
| var util = require("util"); | ||
| var _ = require("lodash"); | ||
| var stub = { | ||
| write : sinon.stub().returns(stub), | ||
| moveCursor : sinon.stub().returns(stub), | ||
| setPrompt : sinon.stub().returns(stub), | ||
| close : sinon.stub().returns(stub), | ||
| pause : sinon.stub().returns(stub), | ||
| resume : sinon.stub().returns(stub), | ||
| output : { | ||
| mute : sinon.stub().returns(stub), | ||
| unmute : sinon.stub().returns(stub), | ||
| write : sinon.stub().returns(stub) | ||
| } | ||
| }; | ||
| var ReadlineStub = function() { | ||
| EventEmitter.apply( this, arguments ); | ||
| }; | ||
| util.inherits( ReadlineStub, EventEmitter ); | ||
| _.assign( ReadlineStub.prototype, stub ); | ||
| module.exports = ReadlineStub; |
| /** | ||
| * Test Prompt public APIs | ||
| */ | ||
| var expect = require("chai").expect; | ||
| var sinon = require("sinon"); | ||
| var _ = require("lodash"); | ||
| var ReadlineStub = require("../helpers/readline"); | ||
| var inquirer = require("../../lib/inquirer"); | ||
| // Define prompts and their public API | ||
| var prompts = [ | ||
| { | ||
| name: "input", | ||
| apis: [ | ||
| "filter", | ||
| "validate", | ||
| "default", | ||
| "message", | ||
| "requiredValues" | ||
| ] | ||
| }, | ||
| { | ||
| name: "confirm", | ||
| apis: [ | ||
| "message", | ||
| "requiredValues" | ||
| ] | ||
| }, | ||
| { | ||
| name: "rawlist", | ||
| apis: [ | ||
| "filter", | ||
| "message", | ||
| "choices", | ||
| "requiredValues" | ||
| ] | ||
| }, | ||
| { | ||
| name: "list", | ||
| apis: [ | ||
| "filter", | ||
| "message", | ||
| "choices", | ||
| "requiredValues" | ||
| ] | ||
| } | ||
| ]; | ||
| // Define tests | ||
| var tests = { | ||
| "filter": function() { | ||
| describe("filter API", function() { | ||
| beforeEach(function() { | ||
| this.output = ""; | ||
| }); | ||
| it("should filter the user input", function( done ) { | ||
| var prompt = new this.Prompt({ | ||
| message: "foo bar", | ||
| name: "foo", | ||
| choices: [ "foo", "bar" ], | ||
| filter: function() { | ||
| return "pass"; | ||
| } | ||
| }, this.rl); | ||
| prompt.run(function( answer ) { | ||
| expect(answer).to.equal("pass"); | ||
| done(); | ||
| }); | ||
| this.rl.emit("line", ""); | ||
| }); | ||
| it("should allow filter function to be asynchronous", function( done ) { | ||
| var prompt = new this.Prompt({ | ||
| message: "foo bar", | ||
| name: "foo", | ||
| choices: [ "foo", "bar" ], | ||
| filter: function() { | ||
| var done = this.async(); | ||
| setTimeout(function() { | ||
| done("pass"); | ||
| }, 0); | ||
| } | ||
| }, this.rl); | ||
| prompt.run(function( answer ) { | ||
| expect(answer).to.equal("pass"); | ||
| done(); | ||
| }); | ||
| this.rl.emit("line", ""); | ||
| }); | ||
| }); | ||
| }, | ||
| "validate": function() { | ||
| describe("validate API", function() { | ||
| beforeEach(function() { | ||
| this.output = ""; | ||
| }); | ||
| it("should reject input if boolean false is returned", function( done ) { | ||
| var self = this; | ||
| var called = 0; | ||
| var prompt = new this.Prompt({ | ||
| message: "foo bar", | ||
| name: "foo", | ||
| validate: function( value ) { | ||
| called++; | ||
| expect(value).to.equal("Inquirer"); | ||
| // Make sure returning false won't continue | ||
| if (called === 2) { | ||
| done(); | ||
| } else { | ||
| self.rl.emit("line", "Inquirer"); | ||
| } | ||
| return false; | ||
| } | ||
| }, this.rl); | ||
| prompt.run(function( answer ) { | ||
| // This should NOT be called | ||
| expect(false).to.be.true; | ||
| }); | ||
| this.rl.emit("line", "Inquirer"); | ||
| }); | ||
| it("should reject input if a string is returned", function( done ) { | ||
| var self = this; | ||
| var called = 0; | ||
| var errorMessage = "uh oh, error!"; | ||
| var prompt = new this.Prompt({ | ||
| message: "foo bar", | ||
| name: "foo", | ||
| validate: function( value ) { | ||
| called++; | ||
| expect(value).to.equal("Inquirer"); | ||
| // Make sure returning false won't continue | ||
| if (called === 2) { | ||
| done(); | ||
| } else { | ||
| self.rl.emit("line", "Inquirer"); | ||
| } | ||
| return errorMessage; | ||
| } | ||
| }, this.rl); | ||
| prompt.run(function( answer ) { | ||
| // This should NOT be called | ||
| expect(false).to.be.true; | ||
| }); | ||
| this.rl.emit("line", "Inquirer"); | ||
| }); | ||
| it("should accept input if boolean true is returned", function( done ) { | ||
| var called = 0; | ||
| var prompt = new this.Prompt({ | ||
| message: "foo bar", | ||
| name: "foo", | ||
| validate: function( value ) { | ||
| expect(value).to.equal("Inquirer"); | ||
| called++; | ||
| return true; | ||
| } | ||
| }, this.rl); | ||
| prompt.run(function( answer ) { | ||
| expect(called).to.equal(1); | ||
| done(); | ||
| }); | ||
| this.rl.emit("line", "Inquirer"); | ||
| }); | ||
| it("should allow validate function to be asynchronous", function( continu ) { | ||
| var self = this; | ||
| var called = 0; | ||
| var prompt = new this.Prompt({ | ||
| message: "foo bar", | ||
| name: "foo", | ||
| validate: function( value ) { | ||
| var done = this.async(); | ||
| setTimeout(function() { | ||
| called++; | ||
| expect(value).to.equal("Inquirer"); | ||
| // Make sure returning false won't continue | ||
| if (called === 2) { | ||
| continu(); | ||
| } else { | ||
| self.rl.emit("line", "Inquirer"); | ||
| } | ||
| done(false); | ||
| }, 0); | ||
| } | ||
| }, this.rl); | ||
| prompt.run(function( answer ) { | ||
| // This should NOT be called | ||
| expect(false).to.be.true; | ||
| }); | ||
| this.rl.emit("line", "Inquirer"); | ||
| }); | ||
| }); | ||
| }, | ||
| "default": function() { | ||
| describe("default API", function() { | ||
| beforeEach(function() { | ||
| this.output = ""; | ||
| }); | ||
| it("should allow a default value", function( done ) { | ||
| var self = this; | ||
| var prompt = new this.Prompt({ | ||
| message: "foo", | ||
| name: "foo", | ||
| "default": "pass" | ||
| }, this.rl); | ||
| prompt.run(function( answer ) { | ||
| expect(self.output).to.contain("(pass)"); | ||
| expect(answer).to.equal("pass"); | ||
| done(); | ||
| }); | ||
| this.rl.emit("line", ""); | ||
| }); | ||
| }); | ||
| }, | ||
| "message": function() { | ||
| describe("message API", function() { | ||
| beforeEach(function() { | ||
| this.output = ""; | ||
| }); | ||
| it("should print message on screen", function() { | ||
| var message = "Foo bar bar foo bar"; | ||
| var prompt = new this.Prompt({ | ||
| message: message, | ||
| name: "foo", | ||
| choices: [ "foo", "bar" ] | ||
| }, this.rl); | ||
| prompt.run(); | ||
| expect(this.output).to.contain(message); | ||
| }); | ||
| }); | ||
| }, | ||
| "choices": function() { | ||
| describe("choices API", function() { | ||
| beforeEach(function() { | ||
| this.output = ""; | ||
| }); | ||
| it("should print choices to screen", function() { | ||
| var choices = [ "Echo", "foo" ]; | ||
| var prompt = new this.Prompt({ | ||
| message: "m", | ||
| name: "foo", | ||
| choices: choices | ||
| }, this.rl); | ||
| prompt.run(); | ||
| _.each( choices, function( choice ) { | ||
| expect(this.output).to.contain(choice); | ||
| }, this ); | ||
| }); | ||
| }); | ||
| }, | ||
| "requiredValues": function() { | ||
| describe("Missing value", function() { | ||
| it("`message` should throw", function() { | ||
| var mkPrompt = function() { | ||
| new this.Prompt({ name : "foo" }); | ||
| }.bind(this); | ||
| expect(mkPrompt).to.throw(/message/); | ||
| }); | ||
| it("`name` should throw", function() { | ||
| var mkPrompt = function() { | ||
| new this.Prompt({ message : "foo" }); | ||
| }.bind(this); | ||
| expect(mkPrompt).to.throw(/name/); | ||
| }); | ||
| }); | ||
| } | ||
| }; | ||
| // Run tests | ||
| describe("Prompt public APIs", function() { | ||
| _.each( prompts, function( detail ) { | ||
| describe("on " + detail.name + " prompt", function() { | ||
| beforeEach(function() { | ||
| var self = this; | ||
| this.Prompt = inquirer.prompts[detail.name]; | ||
| this.rl = new ReadlineStub(); | ||
| this.output = ""; | ||
| this._write = this.Prompt.prototype.write; | ||
| this.Prompt.prototype.write = function( str ) { | ||
| self.output += str; | ||
| return this; | ||
| }; | ||
| }); | ||
| afterEach(function() { | ||
| this.Prompt.prototype.write = this._write; | ||
| }); | ||
| _.each( detail.apis, function( apiName ) { | ||
| tests[apiName]( detail.name ); | ||
| }, this); | ||
| }); | ||
| }); | ||
| }); |
| /** | ||
| * Inquirer public API test | ||
| */ | ||
| var expect = require("chai").expect; | ||
| var sinon = require("sinon"); | ||
| var _ = require("lodash"); | ||
| var ReadlineStub = require("../helpers/readline"); | ||
| var inquirer = require("../../lib/inquirer"); | ||
| describe("inquirer.prompt", function() { | ||
| beforeEach(function() { | ||
| inquirer.rl = new ReadlineStub(); | ||
| }); | ||
| it("should resume and close readline", function( done ) { | ||
| var rl = inquirer.rl; | ||
| inquirer.prompt({ | ||
| type: "confirm", | ||
| name: "q1", | ||
| message: "message" | ||
| }, function( answers ) { | ||
| expect(rl.resume.called).to.be.true; | ||
| expect(rl.close.called).to.be.true; | ||
| expect(inquirer.rl).to.be.null; | ||
| rl = inquirer.rl = new ReadlineStub(); | ||
| inquirer.prompt({ | ||
| type: "confirm", | ||
| name: "q1", | ||
| message: "message" | ||
| }, function( answers ) { | ||
| expect(rl.resume.called).to.be.true; | ||
| expect(rl.close.called).to.be.true; | ||
| expect(inquirer.rl).to.be.null; | ||
| done(); | ||
| }); | ||
| inquirer.rl.emit("line"); | ||
| }); | ||
| rl.emit("line"); | ||
| }); | ||
| it("should take a prompts array and return answers", function( done ) { | ||
| var prompts = [{ | ||
| type: "confirm", | ||
| name: "q1", | ||
| message: "message" | ||
| }, { | ||
| type: "confirm", | ||
| name: "q2", | ||
| message: "message", | ||
| default: false | ||
| }]; | ||
| inquirer.prompt( prompts, function( answers ) { | ||
| expect(answers.q1).to.be.true; | ||
| expect(answers.q2).to.be.false; | ||
| done(); | ||
| }); | ||
| inquirer.rl.emit("line"); | ||
| inquirer.rl.emit("line"); | ||
| }); | ||
| it("should take a single prompt and return answer", function( done ) { | ||
| var prompt = { | ||
| type: "input", | ||
| name: "q1", | ||
| message: "message", | ||
| default: "bar" | ||
| }; | ||
| inquirer.prompt( prompt, function( answers ) { | ||
| expect(answers.q1).to.equal("bar"); | ||
| done(); | ||
| }); | ||
| inquirer.rl.emit("line"); | ||
| }); | ||
| // Hierarchical prompts (`when`) | ||
| describe("in hierarchical mode", function() { | ||
| it("should pass current answers to `when`", function( done ) { | ||
| var prompts = [{ | ||
| type: "confirm", | ||
| name: "q1", | ||
| message: "message" | ||
| }, { | ||
| name: "q2", | ||
| message: "message", | ||
| when: function( answers ) { | ||
| expect(answers).to.be.an("object"); | ||
| expect(answers.q1).to.be.true; | ||
| done(); | ||
| } | ||
| }]; | ||
| inquirer.prompt( prompts, function( answers ) {}); | ||
| inquirer.rl.emit("line"); | ||
| }); | ||
| it("should run prompt if `when` returns true", function( done ) { | ||
| var goesInWhen = false; | ||
| var prompts = [{ | ||
| type: "confirm", | ||
| name: "q1", | ||
| message: "message" | ||
| }, { | ||
| type: "input", | ||
| name: "q2", | ||
| message: "message", | ||
| default: "bar-var", | ||
| when: function() { | ||
| goesInWhen = true; | ||
| return true; | ||
| } | ||
| }]; | ||
| inquirer.prompt( prompts, function( answers ) { | ||
| expect(goesInWhen).to.be.true; | ||
| expect(answers.q2).to.equal("bar-var"); | ||
| done(); | ||
| }); | ||
| inquirer.rl.emit("line"); | ||
| inquirer.rl.emit("line"); | ||
| }); | ||
| it("should not run prompt if `when` returns false", function( done ) { | ||
| var goesInWhen = false; | ||
| var prompts = [{ | ||
| type: "confirm", | ||
| name: "q1", | ||
| message: "message" | ||
| }, { | ||
| type: "confirm", | ||
| name: "q2", | ||
| message: "message", | ||
| when: function() { | ||
| goesInWhen = true; | ||
| return false; | ||
| } | ||
| }, { | ||
| type: "input", | ||
| name: "q3", | ||
| message: "message", | ||
| default: "foo" | ||
| }]; | ||
| inquirer.prompt( prompts, function( answers ) { | ||
| expect(goesInWhen).to.be.true; | ||
| expect(answers.q2).to.not.exist; | ||
| expect(answers.q3).to.equal("foo"); | ||
| expect(answers.q1).to.be.true; | ||
| done(); | ||
| }); | ||
| inquirer.rl.emit("line"); | ||
| inquirer.rl.emit("line"); | ||
| }); | ||
| it("should run asynchronous `when`", function( done ) { | ||
| var goesInWhen = false; | ||
| var prompts = [{ | ||
| type: "confirm", | ||
| name: "q1", | ||
| message: "message" | ||
| }, { | ||
| type: "input", | ||
| name: "q2", | ||
| message: "message", | ||
| default: "foo-bar", | ||
| when: function() { | ||
| goesInWhen = true; | ||
| var goOn = this.async(); | ||
| setTimeout(function() { goOn(true); }, 0 ); | ||
| setTimeout(function() { | ||
| inquirer.rl.emit("line"); | ||
| }, 10 ); | ||
| } | ||
| }]; | ||
| inquirer.prompt( prompts, function( answers ) { | ||
| expect(goesInWhen).to.be.true; | ||
| expect(answers.q2).to.equal("foo-bar"); | ||
| done(); | ||
| }); | ||
| inquirer.rl.emit("line"); | ||
| }); | ||
| }); | ||
| }); |
| var expect = require("chai").expect; | ||
| var sinon = require("sinon"); | ||
| var ReadlineStub = require("../../helpers/readline"); | ||
| var Base = require("../../../lib/prompts/base"); | ||
| // Prevent prompt from writing to screen | ||
| // Confirm.prototype.write = function() { return this; }; | ||
| describe("`base` prompt (e.g. prompt helpers)", function() { | ||
| beforeEach(function() { | ||
| this.rl = new ReadlineStub(); | ||
| this.base = new Base({ | ||
| message: "foo bar", | ||
| name: "name" | ||
| }, this.rl ); | ||
| }); | ||
| it("`suffix` method should only add ':' if last char is a letter", function() { | ||
| expect(this.base.suffix("m:")).to.equal("m: "); | ||
| expect(this.base.suffix("m?")).to.equal("m? "); | ||
| expect(this.base.suffix("m")).to.equal("m: "); | ||
| expect(this.base.suffix("m ")).to.equal("m "); | ||
| expect(this.base.suffix()).to.equal(": "); | ||
| }); | ||
| }); |
| var expect = require("chai").expect; | ||
| var sinon = require("sinon"); | ||
| var ReadlineStub = require("../../helpers/readline"); | ||
| var Confirm = require("../../../lib/prompts/confirm"); | ||
| // Prevent prompt from writing to screen | ||
| // Confirm.prototype.write = function() { return this; }; | ||
| describe("`confirm` prompt", function() { | ||
| beforeEach(function() { | ||
| var self = this; | ||
| this.output = ""; | ||
| this._write = Confirm.prototype.write; | ||
| Confirm.prototype.write = function( str ) { | ||
| self.output += str; | ||
| return this; | ||
| }; | ||
| this.rl = new ReadlineStub(); | ||
| this.confirm = new Confirm({ | ||
| message: "foo bar", | ||
| name: "name" | ||
| }, this.rl); | ||
| }); | ||
| afterEach(function() { | ||
| Confirm.prototype.write = this._write; | ||
| }); | ||
| it("should default to true", function(done) { | ||
| var self = this; | ||
| this.confirm.run(function(answer) { | ||
| expect(self.output).to.contain("Y/n"); | ||
| expect(answer).to.be.true; | ||
| done(); | ||
| }); | ||
| this.rl.emit("line", ""); | ||
| }); | ||
| it("should allow a default `false` value", function(done) { | ||
| var self = this; | ||
| var falseConfirm = new Confirm({ | ||
| message: "foo bar", | ||
| name: "name", | ||
| default: false | ||
| }, this.rl); | ||
| falseConfirm.run(function(answer) { | ||
| expect(self.output).to.contain("y/N"); | ||
| expect(answer).to.be.false; | ||
| done(); | ||
| }); | ||
| this.rl.emit("line", ""); | ||
| }); | ||
| it("should allow a default `true` value", function(done) { | ||
| var self = this; | ||
| var falseConfirm = new Confirm({ | ||
| message: "foo bar", | ||
| name: "name", | ||
| default: true | ||
| }, this.rl); | ||
| falseConfirm.run(function(answer) { | ||
| expect(self.output).to.contain("Y/n"); | ||
| expect(answer).to.be.true; | ||
| done(); | ||
| }); | ||
| this.rl.emit("line", ""); | ||
| }); | ||
| it("should parse 'Y' value to boolean true", function(done) { | ||
| this.confirm.run(function(answer) { | ||
| expect(answer).to.be.true; | ||
| done(); | ||
| }); | ||
| this.rl.emit("line", "Y"); | ||
| }); | ||
| it("should parse 'Yes' value to boolean true", function(done) { | ||
| this.confirm.run(function(answer) { | ||
| expect(answer).to.be.true; | ||
| done(); | ||
| }); | ||
| this.rl.emit("line", "Yes"); | ||
| }); | ||
| it("should parse 'No' value to boolean false", function(done) { | ||
| this.confirm.run(function(answer) { | ||
| expect(answer).to.be.false; | ||
| done(); | ||
| }); | ||
| this.rl.emit("line", "No"); | ||
| }); | ||
| it("should parse every other string value to boolean false", function(done) { | ||
| this.confirm.run(function(answer) { | ||
| expect(answer).to.be.false; | ||
| done(); | ||
| }); | ||
| this.rl.emit("line", "bla bla foo"); | ||
| }); | ||
| }); |
| var expect = require("chai").expect; | ||
| var sinon = require("sinon"); | ||
| var ReadlineStub = require("../../helpers/readline"); | ||
| var Input = require("../../../lib/prompts/input"); | ||
| describe("`input` prompt", function() { | ||
| beforeEach(function() { | ||
| this._write = Input.prototype.write; | ||
| Input.prototype.write = function() { return this; }; | ||
| this.rl = new ReadlineStub(); | ||
| }); | ||
| afterEach(function() { | ||
| Input.prototype.write = this._write; | ||
| }); | ||
| it("should use raw value from the user", function(done) { | ||
| var input = new Input({ | ||
| message: "foo bar", | ||
| name: "name" | ||
| }, this.rl); | ||
| input.run(function(answer) { | ||
| expect(answer).to.equal("Inquirer"); | ||
| done(); | ||
| }); | ||
| this.rl.emit("line", "Inquirer"); | ||
| }); | ||
| }); |
| var expect = require("chai").expect; | ||
| var sinon = require("sinon"); | ||
| var ReadlineStub = require("../../helpers/readline"); | ||
| var List = require("../../../lib/prompts/list"); | ||
| describe("`list` prompt", function() { | ||
| beforeEach(function() { | ||
| this._write = List.prototype.write; | ||
| List.prototype.write = function() { return this; }; | ||
| this.rl = new ReadlineStub(); | ||
| this.list = new List({ | ||
| message: "message", | ||
| name: "name", | ||
| choices: [ "foo", "bar", "bum" ] | ||
| }, this.rl); | ||
| }); | ||
| afterEach(function() { | ||
| List.prototype.write = this._write; | ||
| }); | ||
| it("should default to first choice", function(done) { | ||
| this.list.run(function(answer) { | ||
| expect(answer).to.equal("foo"); | ||
| done(); | ||
| }); | ||
| this.rl.emit("line"); | ||
| }); | ||
| it("should move selected cursor on keypress", function(done) { | ||
| this.list.run(function(answer) { | ||
| expect(answer).to.equal("bar"); | ||
| done(); | ||
| }); | ||
| this.rl.emit("keypress", "", { name : "down" }); | ||
| this.rl.emit("line"); | ||
| }); | ||
| it("should move selected cursor up and down on keypress", function(done) { | ||
| this.list.run(function(answer) { | ||
| expect(answer).to.equal("foo"); | ||
| done(); | ||
| }); | ||
| this.rl.emit("keypress", "", { name : "down" }); | ||
| this.rl.emit("keypress", "", { name : "up" }); | ||
| this.rl.emit("line"); | ||
| }); | ||
| it("should loop the choices when going out of boundaries", function(done) { | ||
| var i = 0; | ||
| function complete() { | ||
| i++; | ||
| if (i === 2) { | ||
| done(); | ||
| } | ||
| } | ||
| this.list.run(function(answer) { | ||
| expect(answer).to.equal("bar"); | ||
| complete(); | ||
| }); | ||
| this.rl.emit("keypress", "", { name : "up" }); | ||
| this.rl.emit("keypress", "", { name : "up" }); | ||
| this.rl.emit("line"); | ||
| this.list.selected = 0; //reset | ||
| this.list.run(function(answer) { | ||
| expect(answer).to.equal("foo"); | ||
| complete(); | ||
| }); | ||
| this.rl.emit("keypress", "", { name : "down" }); | ||
| this.rl.emit("keypress", "", { name : "down" }); | ||
| this.rl.emit("keypress", "", { name : "down" }); | ||
| this.rl.emit("line"); | ||
| }); | ||
| it("should require a choices array", function() { | ||
| var mkPrompt = function() { | ||
| new List({ name : "foo", message: "bar" }); | ||
| }; | ||
| expect(mkPrompt).to.throw(/choices/); | ||
| }); | ||
| it("should allow a default index", function( done ) { | ||
| var rl = new ReadlineStub(); | ||
| var list = new List({ | ||
| message: "message", | ||
| name: "name", | ||
| choices: [ "foo", "bar", "bum" ], | ||
| default: 1 | ||
| }, rl); | ||
| list.run(function( answer ) { | ||
| expect(answer).to.equal("bar"); | ||
| done(); | ||
| }); | ||
| rl.emit("line"); | ||
| }); | ||
| it("should work from a default index", function( done ) { | ||
| var rl = new ReadlineStub(); | ||
| var list = new List({ | ||
| message: "message", | ||
| name: "name", | ||
| choices: [ "foo", "bar", "bum" ], | ||
| default: 1 | ||
| }, rl); | ||
| list.run(function( answer ) { | ||
| expect(answer).to.equal("bum"); | ||
| done(); | ||
| }); | ||
| rl.emit("keypress", "", { name : "down" }); | ||
| rl.emit("line"); | ||
| }); | ||
| it("shouldn't allow an invalid index as default", function( done ) { | ||
| var rl = new ReadlineStub(); | ||
| var list = new List({ | ||
| message: "message", | ||
| name: "name", | ||
| choices: [ "foo", "bar", "bum" ], | ||
| default: 4 | ||
| }, rl); | ||
| list.run(function( answer ) { | ||
| expect(answer).to.equal("foo"); | ||
| done(); | ||
| }); | ||
| rl.emit("line"); | ||
| }); | ||
| }); |
| var expect = require("chai").expect; | ||
| var sinon = require("sinon"); | ||
| var ReadlineStub = require("../../helpers/readline"); | ||
| var Rawlist = require("../../../lib/prompts/rawlist"); | ||
| describe("`rawlist` prompt", function() { | ||
| beforeEach(function() { | ||
| this._write = Rawlist.prototype.write; | ||
| Rawlist.prototype.write = function() { return this; }; | ||
| this.rl = new ReadlineStub(); | ||
| this.rawlist = new Rawlist({ | ||
| message: "message", | ||
| name: "name", | ||
| choices: [ "foo", "bar" ] | ||
| }, this.rl); | ||
| }); | ||
| afterEach(function() { | ||
| Rawlist.prototype.write = this._write; | ||
| }); | ||
| it("should default to first choice", function(done) { | ||
| this.rawlist.run(function(answer) { | ||
| expect(answer).to.equal("foo"); | ||
| done(); | ||
| }); | ||
| this.rl.emit("line"); | ||
| }); | ||
| it("should select given index", function(done) { | ||
| this.rawlist.run(function(answer) { | ||
| expect(answer).to.equal("bar"); | ||
| done(); | ||
| }); | ||
| this.rl.emit("line", "2"); | ||
| }); | ||
| it("should not allow invalid index", function(done) { | ||
| var self = this; | ||
| var callCount = 0; | ||
| this.rawlist.run(function(answer) { | ||
| callCount++; | ||
| }); | ||
| this.rl.emit("line", "blah"); | ||
| setTimeout(function() { | ||
| self.rl.emit("line", "1"); | ||
| setTimeout(function() { | ||
| expect(callCount).to.equal(1); | ||
| done(); | ||
| }, 10); | ||
| }, 10); | ||
| }); | ||
| it("should require a choices array", function() { | ||
| var mkPrompt = function() { | ||
| new Rawlist({ name : "foo", message: "bar" }); | ||
| }; | ||
| expect(mkPrompt).to.throw(/choices/); | ||
| }); | ||
| it("should allow a default index", function( done ) { | ||
| var rl = new ReadlineStub(); | ||
| var list = new Rawlist({ | ||
| message: "message", | ||
| name: "name", | ||
| choices: [ "foo", "bar", "bum" ], | ||
| default: 1 | ||
| }, rl); | ||
| list.run(function( answer ) { | ||
| expect(answer).to.equal("bar"); | ||
| done(); | ||
| }); | ||
| rl.emit("line"); | ||
| }); | ||
| it("shouldn't allow an invalid index as default", function( done ) { | ||
| var rl = new ReadlineStub(); | ||
| var list = new Rawlist({ | ||
| message: "message", | ||
| name: "name", | ||
| choices: [ "foo", "bar", "bum" ], | ||
| default: 4 | ||
| }, rl); | ||
| list.run(function( answer ) { | ||
| expect(answer).to.equal("foo"); | ||
| done(); | ||
| }); | ||
| rl.emit("line"); | ||
| }); | ||
| }); |
| var expect = require("chai").expect; | ||
| var sinon = require("sinon"); | ||
| var utils = require("../../lib/utils/utils"); | ||
| describe("normalizeChoices", function() { | ||
| it("should normalize array containing strings", function() { | ||
| var initial = [ "foo", "bar" ]; | ||
| var normalized = utils.normalizeChoices(initial); | ||
| expect(normalized).to.eql([{ | ||
| name: "foo", | ||
| value: "foo" | ||
| }, { | ||
| name: "bar", | ||
| value: "bar" | ||
| }]); | ||
| }); | ||
| }); | ||
| describe("runAsync", function() { | ||
| it("should run synchronous functions", function( done ) { | ||
| var aFunc = function() { | ||
| return "pass1"; | ||
| }; | ||
| utils.runAsync(aFunc, function( val ) { | ||
| expect(val).to.equal("pass1"); | ||
| done(); | ||
| }); | ||
| }); | ||
| it("should run synchronous functions", function( done ) { | ||
| var aFunc = function() { | ||
| var returns = this.async(); | ||
| returns("pass2"); | ||
| }; | ||
| utils.runAsync(aFunc, function( val ) { | ||
| expect(val).to.equal("pass2"); | ||
| done(); | ||
| }); | ||
| }); | ||
| it("should pass single argument", function( done ) { | ||
| var aFunc = function( val ) { | ||
| expect(val).to.equal("a"); | ||
| done(); | ||
| }; | ||
| utils.runAsync(aFunc, function() {}, "a"); | ||
| }); | ||
| it("should apply multiple arguments", function( done ) { | ||
| var aFunc = function( val, val2 ) { | ||
| expect(val).to.equal("a"); | ||
| expect(val2).to.equal("b"); | ||
| done(); | ||
| }; | ||
| utils.runAsync(aFunc, function() {}, "a", "b"); | ||
| }); | ||
| }); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
1
-50%112957
-40.78%41
-41.43%2596
-39.81%