Comparing version 0.1.2 to 0.1.3
@@ -79,3 +79,3 @@ /** | ||
console.log("\n"); // line return; | ||
charm.write("\n"); // line return; | ||
@@ -82,0 +82,0 @@ if (!self.prompts[question.type]) { |
@@ -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); | ||
} | ||
}; |
@@ -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,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)); | ||
}; |
@@ -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(); | ||
}; |
@@ -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(); | ||
}; |
{ | ||
"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", |
@@ -69,2 +69,19 @@ Inquirer.js [![Build Status](https://travis-ci.org/SBoudrias/Inquirer.js.png?branch=master)](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
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
25
982
150
69114