| /** | ||
| * Checkbox list examples | ||
| */ | ||
| "use strict"; | ||
| var inquirer = require("../lib/inquirer"); | ||
| inquirer.prompt([ | ||
| { | ||
| type: "checkbox", | ||
| message: "Select toppings", | ||
| name: "toppings", | ||
| choices: [ | ||
| { | ||
| name: "Peperonni" | ||
| }, | ||
| { | ||
| name: "Cheese" | ||
| }, | ||
| { | ||
| name: "Pineapple" | ||
| }, | ||
| { | ||
| name: "Mushroom" | ||
| }, | ||
| { | ||
| name: "Bacon" | ||
| } | ||
| ], | ||
| validate: function( answer ) { | ||
| if ( answer.length < 1 ) { | ||
| return "You must choose at least one topping."; | ||
| } | ||
| return true; | ||
| } | ||
| } | ||
| ], function( answers ) { | ||
| console.log( JSON.stringify(answers, null, " ") ); | ||
| }); |
| /** | ||
| * Expand list examples | ||
| */ | ||
| "use strict"; | ||
| var inquirer = require("../lib/inquirer"); | ||
| inquirer.prompt([ | ||
| { | ||
| type: "expand", | ||
| message: "Conflict on `file.js`: ", | ||
| name: "overwrite", | ||
| choices: [ | ||
| { | ||
| key: "y", | ||
| name: "Overwrite", | ||
| value: "overwrite" | ||
| }, | ||
| { | ||
| key: "a", | ||
| name: "Overwrite this one and all next", | ||
| value: "overwrite_all" | ||
| }, | ||
| { | ||
| key: "d", | ||
| name: "Show diff", | ||
| value: "diff" | ||
| }, | ||
| { | ||
| key: "x", | ||
| name: "Abort", | ||
| value: "abort" | ||
| } | ||
| ] | ||
| } | ||
| ], function( answers ) { | ||
| console.log( JSON.stringify(answers, null, " ") ); | ||
| }); |
| /** | ||
| * Input prompt example | ||
| */ | ||
| "use strict"; | ||
| var inquirer = require("../lib/inquirer"); | ||
| var questions = [ | ||
| { | ||
| type: "input", | ||
| name: "first_name", | ||
| message: "What's your first name" | ||
| }, | ||
| { | ||
| type: "input", | ||
| name: "last_name", | ||
| message: "What's your last name" | ||
| }, | ||
| { | ||
| 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"; | ||
| } | ||
| } | ||
| } | ||
| ]; | ||
| inquirer.prompt( questions, function( answers ) { | ||
| console.log( JSON.stringify(answers, null, " ") ); | ||
| }); |
| /** | ||
| * List prompt example | ||
| */ | ||
| "use strict"; | ||
| var inquirer = require("../lib/inquirer"); | ||
| inquirer.prompt({ | ||
| type: "list", | ||
| name: "size", | ||
| message: "What size do you need", | ||
| choices: [ "Jumbo", "Large", "Standard", "Medium", "Small", "Micro" ], | ||
| filter: function( val ) { return val.toLowerCase(); } | ||
| }, function( answers ) { | ||
| console.log( JSON.stringify(answers, null, " ") ); | ||
| }); |
| /** | ||
| * Password prompt example | ||
| */ | ||
| "use strict"; | ||
| var inquirer = require("../lib/inquirer"); | ||
| inquirer.prompt([ | ||
| { | ||
| type: "password", | ||
| message: "Enter your git password", | ||
| name: "password" | ||
| } | ||
| ], function( answers ) { | ||
| console.log( JSON.stringify(answers, null, " ") ); | ||
| }); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
| /** | ||
| * `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.pointer = 0; | ||
| // 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.on( "line", this.onSubmit.bind(this) ); | ||
| // Init the prompt | ||
| this.render(); | ||
| 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("(Press <space> to select)"); | ||
| } | ||
| // Render choices or answer depending on the state | ||
| if ( this.status === "answered" ) { | ||
| message += clc.cyan( this.selection.join(", ") ) + "\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 "; | ||
| var isSelected = (i === this.pointer); | ||
| output += isSelected ? clc.cyan(this.getPointer()) : " "; | ||
| output += this.getCheckbox( choice.checked, choice.name ); | ||
| }.bind(this)); | ||
| return output; | ||
| }; | ||
| /** | ||
| * When user press `enter` key | ||
| */ | ||
| Prompt.prototype.onSubmit = function() { | ||
| var choices = _.where(this.opt.choices, { checked: true }); | ||
| this.selection = _.pluck(choices, "name"); | ||
| var answer = _.pluck(choices, "value"); | ||
| this.rl.output.unmute(); | ||
| this.showCursor(); | ||
| this.validate( answer, function( isValid ) { | ||
| if ( isValid === true ) { | ||
| this.status = "answered"; | ||
| // Rerender prompt (and clean subline error) | ||
| this.down().clean(1).render(); | ||
| this.rl.removeAllListeners("keypress"); | ||
| this.rl.removeAllListeners("line"); | ||
| this.done( answer ); | ||
| } else { | ||
| this.down().error( isValid ).clean().render(); | ||
| this.hideCursor(); | ||
| this.rl.output.mute(); | ||
| } | ||
| }.bind(this)); | ||
| }; | ||
| /** | ||
| * 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" && key.name !== "space")) return; | ||
| var len = this.opt.choices.length; | ||
| this.rl.output.unmute(); | ||
| if ( key.name === "space" ) { | ||
| var checked = this.opt.choices[ this.pointer ].checked; | ||
| this.opt.choices[ this.pointer ].checked = !checked; | ||
| } else if ( key.name === "up" ) { | ||
| (this.pointer > 0) ? this.pointer-- : (this.pointer = len - 1); | ||
| } else if ( key.name === "down" ) { | ||
| (this.pointer < len - 1) ? this.pointer++ : (this.pointer = 0); | ||
| } | ||
| // Rerender | ||
| this.clean().render(); | ||
| this.rl.output.mute(); | ||
| }; |
| /** | ||
| * `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.validate(); | ||
| // Add the default `help` (/expand) option | ||
| this.opt.choices.push({ | ||
| key : "h", | ||
| name : "Help, list all options", | ||
| value : "help" | ||
| }); | ||
| // Setup the default string (capitalize the default key) | ||
| var defIndex = 0; | ||
| if ( _.isNumber(this.opt.default) && this.opt.choices[this.opt.default] ) { | ||
| defIndex = this.opt.default; | ||
| } | ||
| var defStr = _.pluck( this.opt.choices, "key" ); | ||
| this.rawDefault = defStr[ defIndex ]; | ||
| defStr[ defIndex ] = String( defStr[defIndex] ).toUpperCase(); | ||
| this.opt.default = defStr.join(""); | ||
| 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(); | ||
| if ( this.status === "answered" ) { | ||
| message += clc.cyan( this.selected.name ) + "\n"; | ||
| } else if ( this.status === "expanded" ) { | ||
| message += this.getChoices(); | ||
| 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 choiceStr = "\n " + choice.key + ") " + choice.name; | ||
| if ( this.selectedKey === choice.key ) { | ||
| choiceStr = clc.cyan( choiceStr ); | ||
| } | ||
| output += choiceStr; | ||
| }.bind(this)); | ||
| return output; | ||
| }; | ||
| /** | ||
| * When user press `enter` key | ||
| */ | ||
| Prompt.prototype.onSubmit = function( input ) { | ||
| if ( input == null || input === "" ) { | ||
| input = this.rawDefault; | ||
| } | ||
| var selected = _.where( this.opt.choices, { key : input.toLowerCase() })[0]; | ||
| if ( selected != null && selected.key === "h" ) { | ||
| this.selectedKey = ""; | ||
| this.status = "expanded"; | ||
| this.down().clean(2).render(); | ||
| return; | ||
| } | ||
| if ( selected != null ) { | ||
| this.status = "answered"; | ||
| this.selected = selected; | ||
| // Re-render prompt | ||
| this.down().clean(2).render(); | ||
| this.rl.removeAllListeners("line"); | ||
| this.rl.removeAllListeners("keypress"); | ||
| this.done( this.selected.value ); | ||
| return; | ||
| } | ||
| // Input is invalid | ||
| this | ||
| .error("Please enter a valid command") | ||
| .clean() | ||
| .render(); | ||
| }; | ||
| /** | ||
| * When user press a key | ||
| */ | ||
| Prompt.prototype.onKeypress = function( s, key ) { | ||
| this.selectedKey = this.rl.line.toLowerCase(); | ||
| var selected = _.where( this.opt.choices, { key : this.selectedKey })[0]; | ||
| if ( this.status === "expanded" ) { | ||
| this.clean().render(); | ||
| } else { | ||
| this | ||
| .down() | ||
| .hint( selected ? selected.name : "" ) | ||
| .clean() | ||
| .render(); | ||
| } | ||
| this.write( this.rl.line ); | ||
| }; | ||
| /** | ||
| * Validate the choices | ||
| */ | ||
| Prompt.prototype.validate = function() { | ||
| var formatError; | ||
| var errors = []; | ||
| var keymap = {}; | ||
| this.opt.choices.map(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(", ") ); | ||
| } | ||
| }; |
| /** | ||
| * `password` 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) ); | ||
| this.rl.on( "keypress", this.onKeypress.bind(this) ); | ||
| // Init | ||
| this.render(); | ||
| this.rl.output.mute(); | ||
| return this; | ||
| }; | ||
| /** | ||
| * Render the prompt to screen | ||
| * @return {Prompt} self | ||
| */ | ||
| Prompt.prototype.render = function() { | ||
| var message = this.getQuestion(); | ||
| 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; | ||
| }; | ||
| /** | ||
| * When user press `enter` key | ||
| */ | ||
| Prompt.prototype.onSubmit = function( input ) { | ||
| var value = input || this.opt.default || ""; | ||
| this.rl.output.unmute(); | ||
| this.validate( value, function( isValid ) { | ||
| if ( isValid === true ) { | ||
| this.status = "answered"; | ||
| // Re-render prompt | ||
| this.down().clean(2).render(); | ||
| //Mask answer | ||
| var mask = new Array( value.length + 1 ).join("*"); | ||
| // Render answer | ||
| this.write( clc.cyan(mask) + "\n" ); | ||
| this.rl.removeAllListeners("line"); | ||
| this.done( value ); | ||
| } else { | ||
| this.down().error( isValid ).clean().render(); | ||
| this.rl.output.mute(); | ||
| } | ||
| }.bind(this)); | ||
| }; | ||
| /** | ||
| * When user type | ||
| */ | ||
| Prompt.prototype.onKeypress = function() { | ||
| this.rl.output.unmute(); | ||
| this.clean().render(); | ||
| var mask = new Array( this.rl.line.length + 1 ).join("*"); | ||
| this.write(mask); | ||
| this.rl.output.mute(); | ||
| }; |
| module.exports = { | ||
| input: { | ||
| message: "message", | ||
| name: "name" | ||
| }, | ||
| confirm: { | ||
| message: "message", | ||
| name: "name" | ||
| }, | ||
| password: { | ||
| message: "message", | ||
| name: "name" | ||
| }, | ||
| list: { | ||
| message: "message", | ||
| name: "name", | ||
| choices: [ "foo", "bar", "bum" ] | ||
| }, | ||
| rawlist: { | ||
| message: "message", | ||
| name: "name", | ||
| choices: [ "foo", "bar", "bum" ] | ||
| }, | ||
| expand: { | ||
| message: "message", | ||
| name: "name", | ||
| choices: [ | ||
| { key: "a", name: "acab" }, | ||
| { key: "b", name: "bar" }, | ||
| { key: "c", name: "chile" } | ||
| ] | ||
| }, | ||
| checkbox: { | ||
| message: "message", | ||
| name: "name", | ||
| choices: [ | ||
| "choice 1", | ||
| "choice 2", | ||
| "choice 3" | ||
| ] | ||
| } | ||
| }; |
| var expect = require("chai").expect; | ||
| var sinon = require("sinon"); | ||
| var ReadlineStub = require("../../helpers/readline"); | ||
| var Base = require("../../../lib/prompts/base"); | ||
| 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(": "); | ||
| }); | ||
| it("should not point by reference to the entry `question` object", function() { | ||
| var question = { | ||
| message: "foo bar", | ||
| name: "name" | ||
| }; | ||
| var base = new Base( question, this.rl ); | ||
| expect(question).to.not.equal(base.opt); | ||
| expect(question.name).to.equal(base.opt.name); | ||
| expect(question.message).to.equal(base.opt.message); | ||
| }); | ||
| }); |
| var expect = require("chai").expect; | ||
| var sinon = require("sinon"); | ||
| var _ = require("lodash"); | ||
| var ReadlineStub = require("../../helpers/readline"); | ||
| var fixtures = require("../../helpers/fixtures"); | ||
| var Checkbox = require("../../../lib/prompts/checkbox"); | ||
| describe("`checkbox` prompt", function() { | ||
| beforeEach(function() { | ||
| var self = this; | ||
| this.output = ""; | ||
| this.fixture = _.clone( fixtures.checkbox ); | ||
| this._write = Checkbox.prototype.write; | ||
| Checkbox.prototype.write = function( str ) { | ||
| self.output += str; | ||
| return this; | ||
| }; | ||
| this.rl = new ReadlineStub(); | ||
| this.checkbox = new Checkbox( this.fixture, this.rl ); | ||
| }); | ||
| afterEach(function() { | ||
| Checkbox.prototype.write = this._write; | ||
| }); | ||
| it("should return a single selected choice in an array", function( done ) { | ||
| this.checkbox.run(function( answer ) { | ||
| expect(answer).to.be.an("array"); | ||
| expect(answer.length).to.equal(1); | ||
| expect(answer[0]).to.equal("choice 1"); | ||
| done(); | ||
| }); | ||
| this.rl.emit("keypress", " ", { name: "space" }); | ||
| this.rl.emit("line"); | ||
| }); | ||
| it("should return multiples selected choices in an array", function( done ) { | ||
| this.checkbox.run(function( answer ) { | ||
| expect(answer).to.be.an("array"); | ||
| expect(answer.length).to.equal(2); | ||
| expect(answer[0]).to.equal("choice 1"); | ||
| expect(answer[1]).to.equal("choice 2"); | ||
| done(); | ||
| }); | ||
| this.rl.emit("keypress", " ", { name: "space" }); | ||
| this.rl.emit("keypress", null, { name: "down" }); | ||
| this.rl.emit("keypress", " ", { name: "space" }); | ||
| this.rl.emit("line"); | ||
| }); | ||
| it("should check defaults choices", function( done ) { | ||
| this.fixture.choices = [ | ||
| { name: "1", checked: true }, | ||
| { name: "2", checked: false }, | ||
| { name: "3", checked: false } | ||
| ]; | ||
| this.checkbox = new Checkbox( this.fixture, this.rl ); | ||
| this.checkbox.run(function( answer ) { | ||
| expect(answer.length).to.equal(1); | ||
| expect(answer[0]).to.equal("1"); | ||
| done(); | ||
| }); | ||
| this.rl.emit("line"); | ||
| }); | ||
| it("should toggle choice when hitting space", function( done ) { | ||
| this.checkbox.run(function( answer ) { | ||
| expect(answer.length).to.equal(1); | ||
| expect(answer[0]).to.equal("choice 1"); | ||
| done(); | ||
| }); | ||
| this.rl.emit("keypress", " ", { name: "space" }); | ||
| this.rl.emit("keypress", null, { name: "down" }); | ||
| this.rl.emit("keypress", " ", { name: "space" }); | ||
| this.rl.emit("keypress", " ", { name: "space" }); | ||
| this.rl.emit("line"); | ||
| }); | ||
| }); |
| var expect = require("chai").expect; | ||
| var sinon = require("sinon"); | ||
| var _ = require("lodash"); | ||
| var ReadlineStub = require("../../helpers/readline"); | ||
| var fixtures = require("../../helpers/fixtures"); | ||
| var Expand = require("../../../lib/prompts/expand"); | ||
| describe("`expand` prompt", function() { | ||
| beforeEach(function() { | ||
| var self = this; | ||
| this.output = ""; | ||
| this._write = Expand.prototype.write; | ||
| Expand.prototype.write = function( str ) { | ||
| self.output += str; | ||
| return this; | ||
| }; | ||
| this.fixture = _.clone( fixtures.expand ); | ||
| this.rl = new ReadlineStub(); | ||
| this.expand = new Expand( this.fixture, this.rl ); | ||
| }); | ||
| afterEach(function() { | ||
| Expand.prototype.write = this._write; | ||
| }); | ||
| it("should throw if `key` is missing", function() { | ||
| var mkPrompt = function() { | ||
| this.fixture.choices = [ "a", "a" ]; | ||
| return new Expand( this.fixture, this.rl ); | ||
| }.bind(this); | ||
| expect(mkPrompt).to.throw(/Format error/); | ||
| }); | ||
| it("should throw if `key` is duplicate", function() { | ||
| var mkPrompt = function() { | ||
| this.fixture.choices = [ | ||
| { key: "a", name: "foo" }, | ||
| { key: "a", name: "foo" } | ||
| ]; | ||
| return new Expand( this.fixture, this.rl ); | ||
| }.bind(this); | ||
| expect(mkPrompt).to.throw(/Duplicate\ key\ error/); | ||
| }); | ||
| it("should throw if `key` is `h`", function() { | ||
| var mkPrompt = function() { | ||
| this.fixture.choices = [ | ||
| { key: "h", name: "foo" } | ||
| ]; | ||
| return new Expand( this.fixture, this.rl ); | ||
| }.bind(this); | ||
| expect(mkPrompt).to.throw(/Reserved\ key\ error/); | ||
| }); | ||
| it("should take the first choice by default", function( done ) { | ||
| this.expand.run(function( answer ) { | ||
| expect(answer).to.equal("acab"); | ||
| done(); | ||
| }); | ||
| this.rl.emit("line"); | ||
| }); | ||
| it("should use the `default` argument value", function( done ) { | ||
| this.fixture.default = 1; | ||
| this.expand = new Expand( this.fixture, this.rl ); | ||
| this.expand.run(function( answer ) { | ||
| expect(answer).to.equal("bar"); | ||
| done(); | ||
| }); | ||
| this.rl.emit("line"); | ||
| }); | ||
| it("should return the user input", function( done ) { | ||
| this.expand.run(function( answer ) { | ||
| expect(answer).to.equal("bar"); | ||
| done(); | ||
| }); | ||
| this.rl.emit("line", "b"); | ||
| }); | ||
| it("should have help option", function( done ) { | ||
| var run = 0; | ||
| this.expand.run(function( answer ) { | ||
| expect(this.output).to.match(/a\)\ acab/); | ||
| expect(this.output).to.match(/b\)\ bar/); | ||
| expect(answer).to.equal("chile"); | ||
| done(); | ||
| }.bind(this)); | ||
| this.rl.emit("line", "h"); | ||
| this.rl.emit("line", "c"); | ||
| }); | ||
| it("should not allow invalid command", function( done ) { | ||
| var self = this; | ||
| var callCount = 0; | ||
| this.expand.run(function( answer ) { | ||
| callCount++; | ||
| }); | ||
| this.rl.emit( "line", "blah" ); | ||
| setTimeout(function() { | ||
| self.rl.emit( "line", "a" ); | ||
| setTimeout(function() { | ||
| expect(callCount).to.equal(1); | ||
| done(); | ||
| }, 10 ); | ||
| }, 10 ); | ||
| }); | ||
| it("should display and capitalize the default choice `key`", function() { | ||
| this.fixture.default = 1; | ||
| this.expand = new Expand( this.fixture, this.rl ); | ||
| this.expand.run(function() {}); | ||
| expect(this.output).to.contain("(aBch)"); | ||
| }); | ||
| it("should 'autocomplete' the user input", function() { | ||
| this.expand = new Expand( this.fixture, this.rl ); | ||
| this.expand.run(function() {}); | ||
| this.rl.line = "a"; | ||
| this.rl.emit("keypress"); | ||
| setTimeout(function() { | ||
| expect(this.output).to.contain("acab"); | ||
| }.bind(this), 10); | ||
| }); | ||
| }); |
| var expect = require("chai").expect; | ||
| var sinon = require("sinon"); | ||
| var _ = require("lodash"); | ||
| var ReadlineStub = require("../../helpers/readline"); | ||
| var fixtures = require("../../helpers/fixtures"); | ||
| var Password = require("../../../lib/prompts/password"); | ||
| describe("`password` prompt", function() { | ||
| beforeEach(function() { | ||
| this._write = Password.prototype.write; | ||
| Password.prototype.write = function() { return this; }; | ||
| this.fixture = _.clone( fixtures.password ); | ||
| this.rl = new ReadlineStub(); | ||
| }); | ||
| afterEach(function() { | ||
| Password.prototype.write = this._write; | ||
| }); | ||
| it("should use raw value from the user", function( done ) { | ||
| var password = new Password( this.fixture, this.rl ); | ||
| password.run(function( answer ) { | ||
| expect(answer).to.equal("Inquirer"); | ||
| done(); | ||
| }); | ||
| this.rl.emit( "line", "Inquirer" ); | ||
| }); | ||
| }); |
+0
-0
@@ -0,0 +0,0 @@ { |
+0
-0
@@ -0,0 +0,0 @@ language: node_js |
@@ -49,3 +49,3 @@ /** | ||
| { | ||
| type: "list", | ||
| type: "expand", | ||
| name: "toppings", | ||
@@ -55,2 +55,3 @@ message: "What about the toping", | ||
| { | ||
| key: "p", | ||
| name: "Peperonni and chesse", | ||
@@ -60,2 +61,3 @@ value: "PeperonniChesse" | ||
| { | ||
| key: "a", | ||
| name: "All dressed", | ||
@@ -65,7 +67,7 @@ value: "alldressed" | ||
| { | ||
| key: "w", | ||
| name: "Hawaïan", | ||
| value: "hawain" | ||
| value: "hawaian" | ||
| } | ||
| ], | ||
| default: 1 | ||
| ] | ||
| }, | ||
@@ -72,0 +74,0 @@ { |
+1
-1
@@ -10,3 +10,3 @@ /*jshint strict:false */ | ||
| }, | ||
| files: [ "lib/**/*.js" ] | ||
| files: [ "lib/**/*.js", "test/**/*.js" ] | ||
| }, | ||
@@ -13,0 +13,0 @@ |
+17
-5
@@ -6,3 +6,2 @@ /** | ||
| "use strict"; | ||
| var _ = require("lodash"); | ||
@@ -27,6 +26,9 @@ var async = require("async"); | ||
| cli.prompts = { | ||
| list : require("./prompts/list"), | ||
| input : require("./prompts/input"), | ||
| confirm : require("./prompts/confirm"), | ||
| rawlist : require("./prompts/rawlist") | ||
| list : require("./prompts/list"), | ||
| input : require("./prompts/input"), | ||
| confirm : require("./prompts/confirm"), | ||
| rawlist : require("./prompts/rawlist"), | ||
| expand : require("./prompts/expand"), | ||
| checkbox : require("./prompts/checkbox"), | ||
| password : require("./prompts/password") | ||
| }; | ||
@@ -92,2 +94,6 @@ | ||
| if ( _.isFunction(question.choices) ) { | ||
| question.choices = question.choices( this.answers ); | ||
| } | ||
| var prompt = new this.prompts[question.type]( question, this.rl ); | ||
@@ -117,2 +123,6 @@ | ||
| 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 ); | ||
@@ -128,4 +138,6 @@ }.bind(cli); | ||
| cli.onForceClose = function() { | ||
| this.rl.output.unmute(); | ||
| process.stdout.write("\033[?25h"); | ||
| this.rl.close(); | ||
| console.log("\n"); // Line return | ||
| }.bind(cli); |
+82
-10
@@ -28,8 +28,8 @@ /** | ||
| _.assign( this, { | ||
| height : 0, | ||
| answered : false | ||
| height : 0, | ||
| status : "pending" | ||
| }); | ||
| // Set defaults prompt options | ||
| this.opt = _.defaults( question, { | ||
| this.opt = _.defaults( _.clone(question), { | ||
| validate: function() { return true; }, | ||
@@ -120,3 +120,3 @@ filter: function( val ) { return val; }, | ||
| while ( x-- ) { | ||
| this.rl.output.write("\n"); | ||
| this.write("\n"); | ||
| } | ||
@@ -142,3 +142,3 @@ | ||
| /** | ||
| * Write error message under the current line | ||
| * Write error message | ||
| * @param {String} Error Error message | ||
@@ -149,2 +149,5 @@ * @return {Prompt} Self | ||
| Prompt.prototype.error = function( error ) { | ||
| readline.moveCursor( this.rl.output, -clc.width, 0 ); | ||
| readline.clearLine( this.rl.output, 0 ); | ||
| var errMsg = clc.red(">> ") + | ||
@@ -154,5 +157,22 @@ (error || "Please enter a valid value"); | ||
| this.up(); | ||
| return this.up(); | ||
| }; | ||
| return this; | ||
| /** | ||
| * 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 = clc.cyan(">> ") + hint; | ||
| this.write( hintMsg ); | ||
| } | ||
| return this.up(); | ||
| }; | ||
@@ -206,3 +226,3 @@ | ||
| str || (str = ""); | ||
| return str + ": "; | ||
| return (str.length < 1 || /([a-z])$/i.test(str) ? str + ":" : str).trim() + " "; | ||
| }; | ||
@@ -218,6 +238,6 @@ | ||
| var message = this.prefix() + this.opt.message + this.suffix(); | ||
| 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 ) { | ||
| if ( this.opt.default && this.status !== "answered" ) { | ||
| message += "("+ this.opt.default + ") "; | ||
@@ -239,1 +259,53 @@ } | ||
| }; | ||
| /** | ||
| * Hide cursor | ||
| * @return {Prompt} self | ||
| */ | ||
| Prompt.prototype.hideCursor = function() { | ||
| return this.write("\033[?25l"); | ||
| }; | ||
| /** | ||
| * Show cursor | ||
| * @return {Prompt} self | ||
| */ | ||
| Prompt.prototype.showCursor = function() { | ||
| return this.write("\033[?25h"); | ||
| }; | ||
| /** | ||
| * Get the pointer char | ||
| * @return {String} the pointer char | ||
| */ | ||
| Prompt.prototype.getPointer = function() { | ||
| if ( process.platform === "win32" ) return ">"; | ||
| if ( process.platform === "linux" ) return "‣"; | ||
| return "❯"; | ||
| }; | ||
| /** | ||
| * Get the checkbox | ||
| * @param {Boolean} checked - add a X or not to the checkbox | ||
| * @param {String} after - Text to append after the check char | ||
| * @return {String} - Composited checkbox string | ||
| */ | ||
| Prompt.prototype.getCheckbox = function( checked, after ) { | ||
| var win32 = (process.platform === "win32"); | ||
| var check = ""; | ||
| after || (after = ""); | ||
| if ( checked ) { | ||
| check = clc.green( win32 ? "[X]" : "⬢" ); | ||
| } else { | ||
| check = win32 ? "[ ]" : "⬡"; | ||
| } | ||
| return check + " " + after; | ||
| }; |
@@ -76,5 +76,6 @@ /** | ||
| this.write( message ); | ||
| this.rl.setPrompt( message ); | ||
| this.height = message.split(/\n/).length; | ||
| var msgLines = message.split(/\n/); | ||
| this.height = msgLines.length; | ||
| this.rl.setPrompt( _.last(msgLines) ); | ||
@@ -90,3 +91,3 @@ return this; | ||
| Prompt.prototype.onSubmit = function( input ) { | ||
| this.answered = true; | ||
| this.status = "answered"; | ||
@@ -93,0 +94,0 @@ // Filter value to write final answer to screen |
@@ -55,5 +55,6 @@ /** | ||
| this.write( message ); | ||
| this.rl.setPrompt( message ); | ||
| this.height = message.split(/\n/).length; | ||
| var msgLines = message.split(/\n/); | ||
| this.height = msgLines.length; | ||
| this.rl.setPrompt( _.last(msgLines) ); | ||
@@ -74,6 +75,6 @@ return this; | ||
| if ( isValid === true ) { | ||
| this.answered = true; | ||
| this.status = "answered"; | ||
| // Re-render prompt | ||
| this.down().clean(2).render(); | ||
| this.clean(1).render(); | ||
@@ -86,5 +87,5 @@ // Render answer | ||
| } else { | ||
| this.error(isValid).clean().render(); | ||
| this.error( isValid ).clean().render(); | ||
| } | ||
| }.bind(this)); | ||
| }; |
+12
-32
@@ -62,3 +62,3 @@ /** | ||
| this.render(); | ||
| this.rl.output.write( this.hideCursor() ); | ||
| this.hideCursor(); | ||
@@ -88,4 +88,4 @@ // Prevent user from writing | ||
| // Render choices or answer depending on the state | ||
| if ( this.answered ) { | ||
| message += clc.cyan(this.opt.choices[this.selected].name) + "\n"; | ||
| if ( this.status === "answered" ) { | ||
| message += clc.cyan( this.opt.choices[this.selected].name ) + "\n"; | ||
| } else { | ||
@@ -117,9 +117,9 @@ message += choicesStr; | ||
| this.opt.choices.forEach(function( choice, i ) { | ||
| output += "\n "; | ||
| if ( i === this.selected ) { | ||
| output += clc.cyan("[X] " + choice.name); | ||
| } else { | ||
| output += "[ ] " + choice.name; | ||
| output += "\n "; | ||
| var isSelected = (i === this.selected); | ||
| var line = (isSelected ? this.getPointer() + " " : " ") + choice.name; | ||
| if ( isSelected ) { | ||
| line = clc.cyan( line ); | ||
| } | ||
| output += " "; | ||
| output += line + " "; | ||
| }.bind(this)); | ||
@@ -136,4 +136,4 @@ | ||
| Prompt.prototype.onSubmit = function() { | ||
| var choice = this.opt.choices[this.selected]; | ||
| this.answered = true; | ||
| var choice = this.opt.choices[ this.selected ]; | ||
| this.status = "answered"; | ||
@@ -144,3 +144,3 @@ // Rerender prompt | ||
| this.rl.output.write( this.showCursor() ); | ||
| this.showCursor(); | ||
@@ -174,21 +174,1 @@ this.rl.removeAllListeners("keypress"); | ||
| }; | ||
| /** | ||
| * 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"; | ||
| }; |
@@ -76,3 +76,3 @@ /** | ||
| if ( this.answered ) { | ||
| if ( this.status === "answered" ) { | ||
| message += clc.cyan(this.opt.choices[this.selected].name) + "\n"; | ||
@@ -127,3 +127,3 @@ } else { | ||
| if ( this.opt.choices[input] != null ) { | ||
| this.answered = true; | ||
| this.status = "answered"; | ||
| this.selected = input; | ||
@@ -135,2 +135,3 @@ | ||
| this.rl.removeAllListeners("line"); | ||
| this.rl.removeAllListeners("keypress"); | ||
| this.done( this.opt.choices[this.selected].value ); | ||
@@ -154,9 +155,11 @@ return; | ||
| Prompt.prototype.onKeypress = function( s, key ) { | ||
| var input = Number(this.rl.line); | ||
| var index = input - 1; | ||
| var index = this.rl.line.length ? Number(this.rl.line) - 1 : 0; | ||
| if ( this.opt.choices[index] ) { | ||
| this.selected = index; | ||
| this.down().clean(1).render(); | ||
| this.rl.output.write( input.toString() ); | ||
| } else { | ||
| this.selected = undefined; | ||
| } | ||
| this.down().clean(1).render().write( this.rl.line ); | ||
| }; |
@@ -0,0 +0,0 @@ /** |
@@ -28,6 +28,6 @@ /** | ||
| return { | ||
| return _.extend(val, { | ||
| name: val.name || val.value, | ||
| value: val.value || val.name | ||
| }; | ||
| }); | ||
| }); | ||
@@ -34,0 +34,0 @@ }; |
+1
-1
| { | ||
| "name": "inquirer", | ||
| "version": "0.1.9", | ||
| "version": "0.2.0", | ||
| "description": "A collection of common interactive command line user interfaces.", | ||
@@ -5,0 +5,0 @@ "main": "lib/inquirer.js", |
+61
-24
@@ -70,4 +70,4 @@ Inquirer.js [](http://travis-ci.org/SBoudrias/Inquirer.js) | ||
| + **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). | ||
| + **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. | ||
| Array values can be simple `strings`, or `objects` 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. | ||
@@ -110,5 +110,7 @@ + **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. | ||
| Prompts | ||
| Prompts type | ||
| --------------------- | ||
| _allowed options written inside square brackets (`[]`) are optionnals. Others are required._ | ||
| ### List - `{ type: "list" }` | ||
@@ -119,8 +121,3 @@ | ||
| ``` prompt | ||
| [?] What about the toping: (Use arrow key) | ||
| [X] Peperonni and chesse | ||
| [ ] All dressed | ||
| [ ] Hawaïan | ||
| ``` | ||
|  | ||
@@ -132,17 +129,30 @@ ### Raw List - `{ type: "rawlist" }` | ||
| ``` prompt | ||
| [?] You also get a free 2L liquor: | ||
| 1) Pepsi | ||
| 2) 7up | ||
| 3) Coke | ||
| Answer: | ||
| ``` | ||
|  | ||
| ### Expand - `{ type: "expand" }` | ||
| Take `type`, `name`, `message`, `choices`[, `default`, `filter`] properties. (Note that | ||
| default must the choice `index` in the array) | ||
| Note that the `choice` object will take an extra parameter called `key` for the `expand` prompt. This parameter must be a single (lowercased) character. The `h` option is added by the prompt and shouldn't be defined by the user. | ||
| See `examples/expand.js` for a running example. | ||
|  | ||
|  | ||
| ### Checkbox - `{ type: "checkbox" }` | ||
| Take `type`, `name`, `message`, `choices`[, `filter`, `validate`] properties. | ||
| Choices marked as `{ checked: true }` will be checked by default. | ||
|  | ||
| ### Confirm - `{ type: "confirm" }` | ||
| Take `type`, `name`, `message`[, `default`] properties. | ||
| Take `type`, `name`, `message`[, `default`] properties. `default` is expected to be a boolean if used. | ||
| ``` prompt | ||
| [?] Is it for a delivery: (Y/n) | ||
| ``` | ||
|  | ||
@@ -153,7 +163,29 @@ ### Input - `{ type: "input" }` | ||
| ``` prompt | ||
| [?] Any comments on your purchase experience: (Nope, all good!) | ||
| ``` | ||
|  | ||
| ### Password - `{ type: "password" }` | ||
| Take `type`, `name`, `message`[, `default`, `filter`, `validate`] properties. | ||
|  | ||
| Support (OS - terminals) | ||
| ===================== | ||
| You should expect mostly good support for the CLI below. This does not mean we won't | ||
| look at issues found on other command line - feel free to report any! | ||
| - **Mac OS**: | ||
| - Terminal.app | ||
| - iTerm | ||
| - **Windows**: | ||
| - cmd.exe | ||
| - Powershell | ||
| - Cygwin | ||
| - **Ubuntu**: | ||
| - Terminal | ||
| News on the march (Release notes) | ||
@@ -179,7 +211,12 @@ ===================== | ||
| We're looking to offer good support for multiples prompt and environments. If you want to | ||
| help, we'd like to keep a list of testers for each terminal/OS so we can contact you and | ||
| get feedback before release; let us know if you want to be added to the list! (just tweet | ||
| to @vaxilart) | ||
| License | ||
| ===================== | ||
| Copyright (c) 2012 Simon Boudrias | ||
| Copyright (c) 2012 Simon Boudrias (twitter: @vaxilart) | ||
| Licensed under the MIT license. |
@@ -0,0 +0,0 @@ var EventEmitter = require("events").EventEmitter; |
+105
-104
@@ -8,2 +8,3 @@ /** | ||
| var _ = require("lodash"); | ||
| var fixtures = require("../helpers/fixtures"); | ||
| var ReadlineStub = require("../helpers/readline"); | ||
@@ -48,2 +49,30 @@ var inquirer = require("../../lib/inquirer"); | ||
| ] | ||
| }, | ||
| { | ||
| name: "expand", | ||
| apis: [ | ||
| "requiredValues", | ||
| "filter", | ||
| "message" | ||
| ] | ||
| }, | ||
| { | ||
| name: "checkbox", | ||
| apis: [ | ||
| "requiredValues", | ||
| "message", | ||
| "choices", | ||
| "filter", | ||
| "validate" | ||
| ] | ||
| }, | ||
| { | ||
| name: "password", | ||
| apis: [ | ||
| "requiredValues", | ||
| "message", | ||
| "filter", | ||
| "validate", | ||
| "default" | ||
| ] | ||
| } | ||
@@ -63,11 +92,7 @@ ]; | ||
| 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); | ||
| this.fixture.filter = function() { | ||
| return "pass"; | ||
| }; | ||
| var prompt = new this.Prompt( this.fixture, this.rl ); | ||
| prompt.run(function( answer ) { | ||
@@ -82,14 +107,10 @@ expect(answer).to.equal("pass"); | ||
| 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); | ||
| this.fixture.filter = function() { | ||
| var done = this.async(); | ||
| setTimeout(function() { | ||
| done("pass"); | ||
| }, 0); | ||
| }; | ||
| var prompt = new this.Prompt( this.fixture, this.rl ); | ||
| prompt.run(function( answer ) { | ||
@@ -116,18 +137,15 @@ expect(answer).to.equal("pass"); | ||
| 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.fixture.validate = function( value ) { | ||
| called++; | ||
| // Make sure returning false won't continue | ||
| if (called === 2) { | ||
| done(); | ||
| } else { | ||
| self.rl.emit("line"); | ||
| } | ||
| }, this.rl); | ||
| return false; | ||
| }; | ||
| var prompt = new this.Prompt( this.fixture, this.rl ); | ||
| prompt.run(function( answer ) { | ||
@@ -138,3 +156,3 @@ // This should NOT be called | ||
| this.rl.emit("line", "Inquirer"); | ||
| this.rl.emit("line"); | ||
| }); | ||
@@ -146,18 +164,15 @@ | ||
| 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.fixture.validate = function( value ) { | ||
| called++; | ||
| // Make sure returning false won't continue | ||
| if (called === 2) { | ||
| done(); | ||
| } else { | ||
| self.rl.emit("line"); | ||
| } | ||
| }, this.rl); | ||
| return errorMessage; | ||
| }; | ||
| var prompt = new this.Prompt( this.fixture, this.rl ); | ||
| prompt.run(function( answer ) { | ||
@@ -168,3 +183,3 @@ // This should NOT be called | ||
| this.rl.emit("line", "Inquirer"); | ||
| this.rl.emit("line"); | ||
| }); | ||
@@ -174,12 +189,9 @@ | ||
| 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); | ||
| this.fixture.validate = function( value ) { | ||
| called++; | ||
| return true; | ||
| }; | ||
| var prompt = new this.Prompt( this.fixture, this.rl ); | ||
| prompt.run(function( answer ) { | ||
@@ -190,27 +202,25 @@ expect(called).to.equal(1); | ||
| this.rl.emit("line", "Inquirer"); | ||
| this.rl.emit("line"); | ||
| }); | ||
| it("should allow validate function to be asynchronous", function( continu ) { | ||
| it("should allow validate function to be asynchronous", function( next ) { | ||
| 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); | ||
| this.fixture.validate = function( value ) { | ||
| var done = this.async(); | ||
| setTimeout(function() { | ||
| called++; | ||
| // Make sure returning false won't continue | ||
| if (called === 2) { | ||
| next(); | ||
| } else { | ||
| self.rl.emit("line"); | ||
| } | ||
| done(false); | ||
| }, 0); | ||
| }; | ||
| var prompt = new this.Prompt( this.fixture, this.rl ); | ||
| prompt.run(function( answer ) { | ||
@@ -221,3 +231,3 @@ // This should NOT be called | ||
| this.rl.emit("line", "Inquirer"); | ||
| this.rl.emit( "line" ); | ||
| }); | ||
@@ -236,14 +246,10 @@ | ||
| it("should allow a default value", function( done ) { | ||
| var self = this; | ||
| var prompt = new this.Prompt({ | ||
| message: "foo", | ||
| name: "foo", | ||
| "default": "pass" | ||
| }, this.rl); | ||
| this.fixture.default = "pass"; | ||
| var prompt = new this.Prompt( this.fixture, this.rl ); | ||
| prompt.run(function( answer ) { | ||
| expect(self.output).to.contain("(pass)"); | ||
| expect(this.output).to.contain("(pass)"); | ||
| expect(answer).to.equal("pass"); | ||
| done(); | ||
| }); | ||
| }.bind(this)); | ||
@@ -264,12 +270,8 @@ this.rl.emit("line", ""); | ||
| 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); | ||
| this.fixture.message = "Foo bar bar foo bar"; | ||
| var prompt = new this.Prompt( this.fixture, this.rl ); | ||
| prompt.run(); | ||
| expect(this.output).to.contain(message); | ||
| expect( this.output ).to.contain( this.fixture.message ); | ||
| }); | ||
@@ -288,8 +290,4 @@ | ||
| it("should print choices to screen", function() { | ||
| var choices = [ "Echo", "foo" ]; | ||
| var prompt = new this.Prompt({ | ||
| message: "m", | ||
| name: "foo", | ||
| choices: choices | ||
| }, this.rl); | ||
| var prompt = new this.Prompt( this.fixture, this.rl ); | ||
| var choices = prompt.opt.choices; | ||
@@ -299,3 +297,3 @@ prompt.run(); | ||
| _.each( choices, function( choice ) { | ||
| expect(this.output).to.contain(choice); | ||
| expect( this.output ).to.contain( choice.name ); | ||
| }, this ); | ||
@@ -312,3 +310,4 @@ }); | ||
| var mkPrompt = function() { | ||
| new this.Prompt({ name : "foo" }); | ||
| delete this.fixture.message; | ||
| new this.Prompt( this.fixture, this.rl ); | ||
| }.bind(this); | ||
@@ -320,3 +319,4 @@ expect(mkPrompt).to.throw(/message/); | ||
| var mkPrompt = function() { | ||
| new this.Prompt({ message : "foo" }); | ||
| delete this.fixture.name; | ||
| new this.Prompt( this.fixture, this.rl ); | ||
| }.bind(this); | ||
@@ -338,3 +338,4 @@ expect(mkPrompt).to.throw(/name/); | ||
| var self = this; | ||
| this.Prompt = inquirer.prompts[detail.name]; | ||
| this.fixture = _.clone(fixtures[ detail.name ]); | ||
| this.Prompt = inquirer.prompts[ detail.name ]; | ||
| this.rl = new ReadlineStub(); | ||
@@ -341,0 +342,0 @@ |
@@ -85,6 +85,35 @@ /** | ||
| it("should parse `choices` if passed as a function", function( done ) { | ||
| var stubChoices = [ "foo", "bar" ]; | ||
| inquirer.prompts.stub = function( params ) { | ||
| this.opt = { | ||
| when: function() { return true; } | ||
| }; | ||
| expect(params.choices).to.equal(stubChoices); | ||
| done(); | ||
| }; | ||
| inquirer.prompts.stub.prototype.run = function() {}; | ||
| var prompts = [{ | ||
| type: "input", | ||
| name: "name1", | ||
| message: "message", | ||
| default: "bar" | ||
| }, { | ||
| type: "stub", | ||
| name: "name", | ||
| message: "message", | ||
| choices: function( answers ) { | ||
| expect(answers.name1).to.equal("bar"); | ||
| return stubChoices; | ||
| } | ||
| }]; | ||
| inquirer.prompt(prompts, function() {}); | ||
| inquirer.rl.emit("line"); | ||
| }); | ||
| // Hierarchical prompts (`when`) | ||
| describe("hierarchical mode", function() { | ||
| describe("in hierarchical mode", function() { | ||
| it("should pass current answers to `when`", function( done ) { | ||
@@ -91,0 +120,0 @@ var prompts = [{ |
| var expect = require("chai").expect; | ||
| var sinon = require("sinon"); | ||
| var _ = require("lodash"); | ||
| var ReadlineStub = require("../../helpers/readline"); | ||
| var fixtures = require("../../helpers/fixtures"); | ||
| var Confirm = require("../../../lib/prompts/confirm"); | ||
| // Prevent prompt from writing to screen | ||
| // Confirm.prototype.write = function() { return this; }; | ||
@@ -15,2 +15,3 @@ describe("`confirm` prompt", function() { | ||
| this.output = ""; | ||
| this.fixture = _.clone( fixtures.confirm ); | ||
@@ -24,6 +25,3 @@ this._write = Confirm.prototype.write; | ||
| this.rl = new ReadlineStub(); | ||
| this.confirm = new Confirm({ | ||
| message: "foo bar", | ||
| name: "name" | ||
| }, this.rl); | ||
| this.confirm = new Confirm( this.fixture, this.rl ); | ||
| }); | ||
@@ -35,6 +33,6 @@ | ||
| it("should default to true", function(done) { | ||
| it("should default to true", function( done ) { | ||
| var self = this; | ||
| this.confirm.run(function(answer) { | ||
| this.confirm.run(function( answer ) { | ||
| expect(self.output).to.contain("Y/n"); | ||
@@ -45,15 +43,12 @@ expect(answer).to.be.true; | ||
| this.rl.emit("line", ""); | ||
| this.rl.emit( "line", "" ); | ||
| }); | ||
| it("should allow a default `false` value", function(done) { | ||
| 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); | ||
| this.fixture.default = false; | ||
| var falseConfirm = new Confirm( this.fixture, this.rl ); | ||
| falseConfirm.run(function(answer) { | ||
| falseConfirm.run(function( answer ) { | ||
| expect(self.output).to.contain("y/N"); | ||
@@ -64,15 +59,12 @@ expect(answer).to.be.false; | ||
| this.rl.emit("line", ""); | ||
| this.rl.emit( "line", "" ); | ||
| }); | ||
| it("should allow a default `true` value", function(done) { | ||
| 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); | ||
| this.fixture.default = true; | ||
| var falseConfirm = new Confirm( this.fixture, this.rl ); | ||
| falseConfirm.run(function(answer) { | ||
| falseConfirm.run(function( answer ) { | ||
| expect(self.output).to.contain("Y/n"); | ||
@@ -83,8 +75,8 @@ expect(answer).to.be.true; | ||
| this.rl.emit("line", ""); | ||
| this.rl.emit( "line", "" ); | ||
| }); | ||
| it("should parse 'Y' value to boolean true", function(done) { | ||
| it("should parse 'Y' value to boolean true", function( done ) { | ||
| this.confirm.run(function(answer) { | ||
| this.confirm.run(function( answer ) { | ||
| expect(answer).to.be.true; | ||
@@ -97,5 +89,5 @@ done(); | ||
| it("should parse 'Yes' value to boolean true", function(done) { | ||
| it("should parse 'Yes' value to boolean true", function( done ) { | ||
| this.confirm.run(function(answer) { | ||
| this.confirm.run(function( answer ) { | ||
| expect(answer).to.be.true; | ||
@@ -108,5 +100,5 @@ done(); | ||
| it("should parse 'No' value to boolean false", function(done) { | ||
| it("should parse 'No' value to boolean false", function( done ) { | ||
| this.confirm.run(function(answer) { | ||
| this.confirm.run(function( answer ) { | ||
| expect(answer).to.be.false; | ||
@@ -119,5 +111,5 @@ done(); | ||
| it("should parse every other string value to boolean false", function(done) { | ||
| it("should parse every other string value to boolean false", function( done ) { | ||
| this.confirm.run(function(answer) { | ||
| this.confirm.run(function( answer ) { | ||
| expect(answer).to.be.false; | ||
@@ -124,0 +116,0 @@ done(); |
| var expect = require("chai").expect; | ||
| var sinon = require("sinon"); | ||
| var _ = require("lodash"); | ||
| var ReadlineStub = require("../../helpers/readline"); | ||
| var fixtures = require("../../helpers/fixtures"); | ||
@@ -14,2 +16,3 @@ var Input = require("../../../lib/prompts/input"); | ||
| this.fixture = _.clone( fixtures.input ); | ||
| this.rl = new ReadlineStub(); | ||
@@ -22,10 +25,7 @@ }); | ||
| it("should use raw value from the user", function(done) { | ||
| it("should use raw value from the user", function( done ) { | ||
| var input = new Input({ | ||
| message: "foo bar", | ||
| name: "name" | ||
| }, this.rl); | ||
| var input = new Input( this.fixture, this.rl ); | ||
| input.run(function(answer) { | ||
| input.run(function( answer ) { | ||
| expect(answer).to.equal("Inquirer"); | ||
@@ -35,5 +35,5 @@ done(); | ||
| this.rl.emit("line", "Inquirer"); | ||
| this.rl.emit( "line", "Inquirer" ); | ||
| }); | ||
| }); |
| var expect = require("chai").expect; | ||
| var sinon = require("sinon"); | ||
| var _ = require("lodash"); | ||
| var ReadlineStub = require("../../helpers/readline"); | ||
| var fixtures = require("../../helpers/fixtures"); | ||
@@ -14,8 +16,5 @@ var List = require("../../../lib/prompts/list"); | ||
| this.fixture = _.clone( fixtures.list ); | ||
| this.rl = new ReadlineStub(); | ||
| this.list = new List({ | ||
| message: "message", | ||
| name: "name", | ||
| choices: [ "foo", "bar", "bum" ] | ||
| }, this.rl); | ||
| this.list = new List( this.fixture, this.rl ); | ||
| }); | ||
@@ -27,6 +26,5 @@ | ||
| it("should default to first choice", function(done) { | ||
| this.list.run(function(answer) { | ||
| it("should default to first choice", function( done ) { | ||
| this.list.run(function( answer ) { | ||
| expect(answer).to.equal("foo"); | ||
| done(); | ||
@@ -38,5 +36,5 @@ }); | ||
| it("should move selected cursor on keypress", function(done) { | ||
| it("should move selected cursor on keypress", function( done ) { | ||
| this.list.run(function(answer) { | ||
| this.list.run(function( answer ) { | ||
| expect(answer).to.equal("bar"); | ||
@@ -50,5 +48,5 @@ done(); | ||
| it("should move selected cursor up and down on keypress", function(done) { | ||
| it("should move selected cursor up and down on keypress", function( done ) { | ||
| this.list.run(function(answer) { | ||
| this.list.run(function( answer ) { | ||
| expect(answer).to.equal("foo"); | ||
@@ -63,3 +61,3 @@ done(); | ||
| it("should loop the choices when going out of boundaries", function(done) { | ||
| it("should loop the choices when going out of boundaries", function( done ) { | ||
@@ -74,3 +72,3 @@ var i = 0; | ||
| this.list.run(function(answer) { | ||
| this.list.run(function( answer ) { | ||
| expect(answer).to.equal("bar"); | ||
@@ -85,3 +83,3 @@ complete(); | ||
| this.list.selected = 0; //reset | ||
| this.list.run(function(answer) { | ||
| this.list.run(function( answer ) { | ||
| expect(answer).to.equal("foo"); | ||
@@ -105,10 +103,6 @@ complete(); | ||
| 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); | ||
| this.fixture.default = 1; | ||
| var list = new List( this.fixture, this.rl ); | ||
| list.run(function( answer ) { | ||
@@ -119,14 +113,10 @@ expect(answer).to.equal("bar"); | ||
| rl.emit("line"); | ||
| this.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); | ||
| this.fixture.default = 1; | ||
| var list = new List( this.fixture, this.rl ); | ||
| list.run(function( answer ) { | ||
@@ -137,14 +127,9 @@ expect(answer).to.equal("bum"); | ||
| rl.emit("keypress", "", { name : "down" }); | ||
| rl.emit("line"); | ||
| this.rl.emit("keypress", "", { name : "down" }); | ||
| this.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); | ||
| this.fixture.default = 4; | ||
| var list = new List( this.fixture, this.rl ); | ||
@@ -156,3 +141,3 @@ list.run(function( answer ) { | ||
| rl.emit("line"); | ||
| this.rl.emit("line"); | ||
@@ -159,0 +144,0 @@ }); |
| var expect = require("chai").expect; | ||
| var sinon = require("sinon"); | ||
| var _ = require("lodash"); | ||
| var ReadlineStub = require("../../helpers/readline"); | ||
| var fixtures = require("../../helpers/fixtures"); | ||
@@ -15,7 +17,4 @@ var Rawlist = require("../../../lib/prompts/rawlist"); | ||
| this.rl = new ReadlineStub(); | ||
| this.rawlist = new Rawlist({ | ||
| message: "message", | ||
| name: "name", | ||
| choices: [ "foo", "bar" ] | ||
| }, this.rl); | ||
| this.fixture = _.clone( fixtures.rawlist ); | ||
| this.rawlist = new Rawlist( this.fixture, this.rl ); | ||
| }); | ||
@@ -73,9 +72,4 @@ | ||
| 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); | ||
| this.fixture.default = 1; | ||
| var list = new Rawlist(this.fixture, this.rl); | ||
@@ -87,13 +81,8 @@ list.run(function( answer ) { | ||
| rl.emit("line"); | ||
| this.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); | ||
| this.fixture.default = 4; | ||
| var list = new Rawlist(this.fixture, this.rl); | ||
@@ -105,3 +94,3 @@ list.run(function( answer ) { | ||
| rl.emit("line"); | ||
| this.rl.emit("line"); | ||
@@ -108,0 +97,0 @@ }); |
+14
-0
@@ -18,2 +18,16 @@ var expect = require("chai").expect; | ||
| }); | ||
| it("should keep extra keys", function() { | ||
| var initial = [{ name: "foo", extra: "1" }, { name: "bar", key: "z" }]; | ||
| var normalized = utils.normalizeChoices(initial); | ||
| expect(normalized).to.eql([{ | ||
| name: "foo", | ||
| value: "foo", | ||
| extra: "1" | ||
| }, { | ||
| name: "bar", | ||
| value: "bar", | ||
| key: "z" | ||
| }]); | ||
| }); | ||
| }); | ||
@@ -20,0 +34,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
40
48.15%2539
49.35%217
20.56%93561
-10.45%