Comparing version
@@ -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 [](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
25
4.17%982
13.53%150
12.78%69114
-6.39%