| var noop = function() { return stub; }; | ||
| var stub = { | ||
| write : noop, | ||
| up : noop, | ||
| foreground : noop, | ||
| display : noop, | ||
| erase : noop, | ||
| left : noop | ||
| }; | ||
| module.exports = stub; |
+1
-0
| language: node_js | ||
| node_js: | ||
| - "0.8" | ||
| - "0.10" |
+1
-1
@@ -79,3 +79,3 @@ /** | ||
| console.log("\n"); // line return; | ||
| charm.write("\n"); // line return; | ||
@@ -82,0 +82,0 @@ if (!self.prompts[question.type]) { |
+32
-9
@@ -21,6 +21,10 @@ /** | ||
| function Prompt(question, rl) { | ||
| _.assign(this, { height : 0 }, question); | ||
| _.assign(this, { height : 0 }); | ||
| this.opt = _.defaults(question, { | ||
| validate: function() { return true; }, | ||
| filter: function(val) { return val; } | ||
| }); | ||
| if (_.isArray(this.choices)) { | ||
| this.choices = utils.normalizeChoices(this.choices); | ||
| if (_.isArray(this.opt.choices)) { | ||
| this.opt.choices = utils.normalizeChoices(this.opt.choices); | ||
| } | ||
@@ -43,4 +47,3 @@ | ||
| this._run(function(value) { | ||
| // Use `call` to allow passing `prototype` methods | ||
| cb(self.filter.call(value, value)); | ||
| self.filter(value, cb); | ||
| }); | ||
@@ -91,4 +94,14 @@ return this; | ||
| */ | ||
| Prompt.prototype.validate = function(value) { | ||
| return true; | ||
| Prompt.prototype.validate = function(input, cb) { | ||
| var async = false; | ||
| var isValid = this.opt.validate.call({ | ||
| async: function() { | ||
| async = true; | ||
| return _.once(cb); | ||
| } | ||
| }, input); | ||
| if (!async) { | ||
| cb(isValid); | ||
| } | ||
| }; | ||
@@ -101,4 +114,14 @@ | ||
| */ | ||
| Prompt.prototype.filter = function(value) { | ||
| return value; | ||
| Prompt.prototype.filter = function(input, cb) { | ||
| var async = false; | ||
| var output = this.opt.filter.call({ | ||
| async: function() { | ||
| async = true; | ||
| return _.once(cb); | ||
| } | ||
| }, input); | ||
| if (!async) { | ||
| cb(output); | ||
| } | ||
| }; |
+29
-17
@@ -24,6 +24,19 @@ /** | ||
| function Prompt() { | ||
| return Base.apply(this, arguments); | ||
| Base.apply(this, arguments); | ||
| _.extend(this.opt, { | ||
| filter: function(input) { | ||
| var value = true; | ||
| if (input != null && input !== "") { | ||
| value = /^y(es)?/i.test(input); | ||
| } | ||
| return value; | ||
| } | ||
| }); | ||
| return this; | ||
| } | ||
| util.inherits(Prompt, Base); | ||
| /** | ||
@@ -34,14 +47,11 @@ * Start the Inquiry session | ||
| */ | ||
| Prompt.prototype._run = function(cb) { | ||
| var self = this; | ||
| this.done = cb; | ||
| // Once user confirm (enter key) | ||
| this.rl.once("line", function(input) { | ||
| self.clean(1).render(); | ||
| charm.foreground("cyan").write(self.filter(input) ? "Yes" : "No").foreground("white"); | ||
| cb(input); | ||
| }); | ||
| this.rl.once("line", this.onSubmit.bind(this)); | ||
| // Init | ||
| self.render(); | ||
| this.render(); | ||
@@ -51,2 +61,3 @@ return this; | ||
| /** | ||
@@ -58,3 +69,3 @@ * Render the prompt to screen | ||
| Prompt.prototype.render = function() { | ||
| var message = this.message + " (Y/n) "; | ||
| var message = this.opt.message + " (Y/n) "; | ||
| charm.write(message); | ||
@@ -67,12 +78,13 @@ | ||
| /** | ||
| * Filter input and return a boolean | ||
| * @Note: See base.prototype.filter for complete documentation | ||
| * When user press "enter" key | ||
| */ | ||
| Prompt.prototype.filter = function(input) { | ||
| var value = true; | ||
| if (input != null && input !== "") { | ||
| value = /^y(es)?/i.test(input); | ||
| } | ||
| return value; | ||
| Prompt.prototype.onSubmit = function(input) { | ||
| this.clean(1).render(); | ||
| this.filter(input, function(output) { | ||
| charm.foreground("cyan").write(output ? "Yes" : "No").foreground("white").write("\n"); | ||
| this.done(input); | ||
| }.bind(this)); | ||
| }; |
+27
-17
@@ -27,2 +27,3 @@ /** | ||
| /** | ||
@@ -36,20 +37,9 @@ * Start the Inquiry session | ||
| Prompt.prototype._run = function(cb) { | ||
| var self = this; | ||
| this.done = cb; | ||
| // Once user confirm (enter key) | ||
| this.rl.on("line", function(input) { | ||
| var value = input || self.default || ""; | ||
| var valid = self.validate(value); | ||
| if (valid === true) { | ||
| self.clean(1).render(); | ||
| charm.foreground("cyan").write(value).foreground("white"); | ||
| self.rl.removeAllListeners("line"); | ||
| cb(value); | ||
| } else { | ||
| self.error(valid).clean().render(); | ||
| } | ||
| }); | ||
| this.rl.on("line", this.onSubmit.bind(this)); | ||
| // Init | ||
| self.render(); | ||
| this.render(); | ||
@@ -59,2 +49,3 @@ return this; | ||
| /** | ||
@@ -67,5 +58,5 @@ * Render the prompt to screen | ||
| var message = ""; | ||
| message += this.message; | ||
| if (this.default) { | ||
| message += " (default \"" + this.default + "\")"; | ||
| message += this.opt.message; | ||
| if (this.opt.default) { | ||
| message += " (default \"" + this.opt.default + "\")"; | ||
| } | ||
@@ -80,1 +71,20 @@ message += ": "; | ||
| }; | ||
| /** | ||
| * 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.clean(1).render(); | ||
| charm.foreground("cyan").write(value).foreground("white").write("\n"); | ||
| this.rl.removeAllListeners("line"); | ||
| this.done(value); | ||
| } else { | ||
| this.error(isValid).clean().render(); | ||
| } | ||
| }.bind(this)); | ||
| }; |
+41
-21
@@ -24,7 +24,12 @@ /** | ||
| function Prompt() { | ||
| Base.apply(this, arguments); | ||
| this.firstRender = true; | ||
| return Base.apply(this, arguments); | ||
| this.selected = 0; | ||
| return this; | ||
| } | ||
| util.inherits(Prompt, Base); | ||
| /** | ||
@@ -35,25 +40,11 @@ * Start the Inquiry session | ||
| */ | ||
| Prompt.prototype._run = function(cb) { | ||
| var self = this; | ||
| self.selected = 0; | ||
| this.done = cb; | ||
| // Move the selected marker on keypress | ||
| this.rl.on("keypress", function(s, key) { | ||
| if (key.name === "up" && (self.selected - 1) >= 0) { | ||
| self.selected--; | ||
| } else if (key.name === "down" && (self.selected + 1) < self.choices.length) { | ||
| self.selected++; | ||
| } else { | ||
| return; // don't render if nothing changed | ||
| } | ||
| self.clean().render(); | ||
| }); | ||
| this.rl.on("keypress", this.onKeypress.bind(this)); | ||
| // Once user confirm (enter key) | ||
| this.rl.once("line", function() { | ||
| var choice = self.choices[self.selected]; | ||
| utils.cleanLine(2); | ||
| self.rl.removeAllListeners("keypress"); | ||
| cb(choice.value); | ||
| }); | ||
| this.rl.once("line", this.onSubmit.bind(this)); | ||
@@ -66,2 +57,3 @@ // Init the prompt | ||
| /** | ||
@@ -77,7 +69,7 @@ * Render the prompt to screen | ||
| // Render question | ||
| var message = this.message + "\n"; | ||
| var message = this.opt.message + "\n"; | ||
| charm.write(message); | ||
| // Render choices | ||
| this.choices.forEach(function(choice, i) { | ||
| this.opt.choices.forEach(function(choice, i) { | ||
| charm.foreground("cyan").write(" [" + (i === self.selected ? "X" : " ") + "] "); | ||
@@ -98,1 +90,29 @@ (i !== self.selected) && charm.foreground("white"); | ||
| }; | ||
| /** | ||
| * When user press `enter` key | ||
| */ | ||
| Prompt.prototype.onSubmit = function() { | ||
| var choice = this.opt.choices[this.selected]; | ||
| utils.cleanLine(2); | ||
| this.rl.removeAllListeners("keypress"); | ||
| this.done(choice.value); | ||
| }; | ||
| /** | ||
| * When user press a key | ||
| */ | ||
| Prompt.prototype.onKeypress = function(s, key) { | ||
| if (key.name === "up" && (this.selected - 1) >= 0) { | ||
| this.selected--; | ||
| } else if (key.name === "down" && (this.selected + 1) < this.opt.choices.length) { | ||
| this.selected++; | ||
| } else { | ||
| return; // don't render if nothing changed | ||
| } | ||
| this.clean().render(); | ||
| }; |
+32
-19
@@ -11,2 +11,3 @@ /** | ||
| /** | ||
@@ -24,6 +25,11 @@ * Module exports | ||
| function Prompt() { | ||
| return Base.apply(this, arguments); | ||
| Base.apply(this, arguments); | ||
| this.selected = 0; | ||
| return this; | ||
| } | ||
| util.inherits(Prompt, Base); | ||
| /** | ||
@@ -36,20 +42,6 @@ * Start the Inquiry session | ||
| Prompt.prototype._run = function(cb) { | ||
| var self = this; | ||
| this.selected = 0; | ||
| this.done = cb; | ||
| // Save user answer and update prompt to show selected option. | ||
| this.rl.on("line", function(input) { | ||
| if (input == null || input === "") { | ||
| input = 1; | ||
| } | ||
| if (self.choices[input - 1] != null) { | ||
| self.selected = input - 1; | ||
| self.clean(1).render(); | ||
| charm.write( input + "\n"); | ||
| self.rl.removeAllListeners("line"); | ||
| cb(self.choices[input - 1].value); | ||
| return; | ||
| } | ||
| self.error("Please enter a valid index").clean().render(); | ||
| }); | ||
| this.rl.on("line", this.onSubmit.bind(this)); | ||
@@ -62,2 +54,3 @@ // Init the prompt | ||
| /** | ||
@@ -73,7 +66,7 @@ * Render the prompt to screen | ||
| // Render question | ||
| var message = this.message + "\n"; | ||
| var message = this.opt.message + "\n"; | ||
| charm.write(message); | ||
| // Render choices | ||
| this.choices.forEach(function(choice, i) { | ||
| this.opt.choices.forEach(function(choice, i) { | ||
| (i === self.selected) && charm.foreground("cyan"); | ||
@@ -89,1 +82,21 @@ charm.write(" " + (i + 1) + ") " + choice.name + "\n").foreground("white"); | ||
| }; | ||
| /** | ||
| * When user press `enter` key | ||
| */ | ||
| Prompt.prototype.onSubmit = function(input) { | ||
| if (input == null || input === "") { | ||
| input = 1; | ||
| } | ||
| if (this.opt.choices[input - 1] != null) { | ||
| this.selected = input - 1; | ||
| this.clean(1).render(); | ||
| charm.write( input + "\n"); | ||
| this.rl.removeAllListeners("line"); | ||
| this.done(this.opt.choices[this.selected].value); | ||
| return; | ||
| } | ||
| this.error("Please enter a valid index").clean().render(); | ||
| }; |
+1
-1
| { | ||
| "name": "inquirer", | ||
| "version": "0.1.2", | ||
| "version": "0.1.3", | ||
| "description": "A collection of common interactive command line user interfaces.", | ||
@@ -5,0 +5,0 @@ "main": "lib/inquirer.js", |
+18
-1
@@ -69,2 +69,19 @@ Inquirer.js [](http://travis-ci.org/SBoudrias/Inquirer.js) | ||
| `validate` and `filter` function can be asynchronous using `this.async()`. You just have to pass the value you'd normally return to the callback option. | ||
| ``` javascript | ||
| { | ||
| validate: function(input) { | ||
| var done = this.async(); | ||
| setTimeout(function() { | ||
| if (typeof input !== "number") { | ||
| done("You need to provide a number"); | ||
| return; | ||
| } | ||
| done(true); | ||
| }, 3000); | ||
| } | ||
| } | ||
| ``` | ||
| ### Answers | ||
@@ -119,3 +136,3 @@ A key/value hash containing the client answers in each prompt. | ||
| ``` prompt | ||
| Before leaving, any comments on your purchase experience? (default "Nope, all good!"): | ||
| Any comments on your purchase experience? (default "Nope, all good!"): | ||
| ``` | ||
@@ -122,0 +139,0 @@ |
@@ -5,3 +5,3 @@ var expect = require("chai").expect; | ||
| process.charm = require("charm")(process.stdout); | ||
| process.charm = require("../../helpers/charm"); | ||
| var Confirm = require("../../../lib/prompts/confirm"); | ||
@@ -18,6 +18,2 @@ | ||
| afterEach(function() { | ||
| this.confirm.clean(1); | ||
| }); | ||
| it("should default to true", function(done) { | ||
@@ -24,0 +20,0 @@ |
@@ -5,3 +5,3 @@ var expect = require("chai").expect; | ||
| process.charm = require("charm")(process.stdout); | ||
| process.charm = require("../../helpers/charm"); | ||
| var Input = require("../../../lib/prompts/input"); | ||
@@ -22,3 +22,2 @@ | ||
| expect(answer).to.equal("Inquirer"); | ||
| input.clean(1); | ||
| done(); | ||
@@ -40,3 +39,2 @@ }); | ||
| expect(answer).to.equal("pass"); | ||
| input.clean(1); | ||
| done(); | ||
@@ -48,2 +46,21 @@ }); | ||
| it("should allow filter function to be asynchronous", function(done) { | ||
| var input = new Input({ | ||
| message: "foo bar", | ||
| filter: function() { | ||
| var done = this.async(); | ||
| setTimeout(function() { | ||
| done("pass"); | ||
| }, 0); | ||
| } | ||
| }, this.rl); | ||
| input.run(function(answer) { | ||
| expect(answer).to.equal("pass"); | ||
| done(); | ||
| }); | ||
| this.rl.emit("line", "Inquirer"); | ||
| }); | ||
| it("should validate the user input", function(done) { | ||
@@ -59,3 +76,2 @@ var self = this; | ||
| if (called === 2) { | ||
| input.clean(1); | ||
| done(); | ||
@@ -76,2 +92,31 @@ } else { | ||
| it("should allow validate function to be asynchronous", function(continu) { | ||
| var self = this; | ||
| var called = 0; | ||
| var input = new Input({ | ||
| message: "foo bar", | ||
| 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); | ||
| input.run(function(answer) { | ||
| // This should NOT be called | ||
| expect(false).to.be.true; | ||
| }); | ||
| this.rl.emit("line", "Inquirer"); | ||
| }); | ||
| }); |
@@ -5,3 +5,3 @@ var expect = require("chai").expect; | ||
| process.charm = require("charm")(process.stdout); | ||
| process.charm = require("../../helpers/charm"); | ||
| var List = require("../../../lib/prompts/list"); | ||
@@ -20,6 +20,2 @@ | ||
| afterEach(function() { | ||
| this.list.clean(); | ||
| }); | ||
| it("should default to first choice", function(done) { | ||
@@ -98,3 +94,2 @@ this.list.run(function(answer) { | ||
| expect(answer).to.equal("pass"); | ||
| list.clean(1); | ||
| done(); | ||
@@ -106,2 +101,22 @@ }); | ||
| it("should allow filter to be asynchronous", function(done) { | ||
| var list = new List({ | ||
| message: "", | ||
| choices: [ "foo", "bar" ], | ||
| filter: function() { | ||
| var done = this.async(); | ||
| setTimeout(function() { | ||
| done("pass"); | ||
| }, 0); | ||
| } | ||
| }, this.rl); | ||
| list.run(function(answer) { | ||
| expect(answer).to.equal("pass"); | ||
| done(); | ||
| }); | ||
| this.rl.emit("line"); | ||
| }); | ||
| }); |
@@ -5,3 +5,3 @@ var expect = require("chai").expect; | ||
| process.charm = require("charm")(process.stdout); | ||
| process.charm = require("../../helpers/charm"); | ||
| var Rawlist = require("../../../lib/prompts/rawlist"); | ||
@@ -19,6 +19,2 @@ | ||
| afterEach(function() { | ||
| this.rawlist.clean(1); | ||
| }); | ||
| it("should default to first choice", function(done) { | ||
@@ -73,3 +69,2 @@ | ||
| expect(answer).to.equal("pass"); | ||
| rawlist.clean(1); | ||
| done(); | ||
@@ -81,2 +76,22 @@ }); | ||
| it("should allow filter function to be asynchronous", function(done) { | ||
| var rawlist = new Rawlist({ | ||
| message: "", | ||
| choices: [ "foo", "bar" ], | ||
| filter: function() { | ||
| var done = this.async(); | ||
| setTimeout(function() { | ||
| done("pass"); | ||
| }, 0); | ||
| } | ||
| }, this.rl); | ||
| rawlist.run(function(answer) { | ||
| expect(answer).to.equal("pass"); | ||
| done(); | ||
| }); | ||
| this.rl.emit("line"); | ||
| }); | ||
| }); |
Sorry, the diff of this file is not supported yet
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
25
4.17%982
13.53%150
12.78%69114
-6.39%