Comparing version 0.1.2 to 0.1.3
@@ -24,2 +24,3 @@ /* | ||
name: 'password', | ||
empty: false, | ||
hidden: true | ||
@@ -45,2 +46,2 @@ } | ||
console.log(' password: ' + result.password); | ||
}); | ||
}); |
/* | ||
* prompt.js: Simple prompt for prompting information from the command line | ||
* prompt.js: Simple prompt for prompting information from the command line | ||
* | ||
@@ -23,18 +23,19 @@ * (C) 2010, Nodejitsu Inc. | ||
// | ||
// Expose version using `pkginfo` | ||
// | ||
require('pkginfo')(module, 'version'); | ||
var stdin, stdout, history = []; | ||
var prompt = module.exports = Object.create(events.EventEmitter.prototype); | ||
var logger = prompt.logger = new winston.Logger({ | ||
transports: [ | ||
new (winston.transports.Console)() | ||
] | ||
transports: [new (winston.transports.Console)()] | ||
}); | ||
prompt.started = false; | ||
prompt.paused = false; | ||
prompt.allowEmpty = false; | ||
prompt.allowEmpty = false; | ||
var stdin, stdout; | ||
// | ||
// Create an empty object for the properties | ||
// Create an empty object for the properties | ||
// known to `node-prompt` | ||
@@ -45,3 +46,3 @@ // | ||
// | ||
// Setup the default winston logger to use | ||
// Setup the default winston logger to use | ||
// the `cli` levels and colors. | ||
@@ -55,3 +56,3 @@ // | ||
// Starts the prompt by listening to the appropriate events on `options.stdin` | ||
// and `options.stdout`. If no streams are supplied, then `process.stdin` | ||
// and `options.stdout`. If no streams are supplied, then `process.stdin` | ||
// and `process.stdout` are used, respectively. | ||
@@ -63,3 +64,3 @@ // | ||
} | ||
options = options || {}; | ||
@@ -69,9 +70,14 @@ stdin = options.stdin || process.openStdin(); | ||
// | ||
// By default: Remeber the last `10` prompt property / | ||
// answer pairs and don't allow empty responses globally. | ||
// | ||
prompt.memory = options.memory || 10; | ||
prompt.allowEmpty = options.allowEmpty || false; | ||
process.on('SIGINT', function () { | ||
stdout.write('\n'); | ||
process.exit(1); | ||
}) | ||
}); | ||
prompt.emit('start'); | ||
@@ -90,3 +96,3 @@ prompt.started = true; | ||
} | ||
stdin.pause(); | ||
@@ -100,3 +106,3 @@ prompt.emit('pause'); | ||
// ### function resume () | ||
// Resumes input coming in from stdin | ||
// Resumes input coming in from stdin | ||
// | ||
@@ -107,3 +113,3 @@ prompt.resume = function () { | ||
} | ||
stdin.resume(); | ||
@@ -116,2 +122,30 @@ prompt.emit('resume'); | ||
// | ||
// ### function history (search) | ||
// #### @search {Number|string} Index or property name to find. | ||
// Returns the `property:value` pair from within the prompts | ||
// `history` array. | ||
// | ||
prompt.history = function (search) { | ||
if (typeof search === 'number') { | ||
return history[search] || {}; | ||
} | ||
var names = history.map(function (pair) { | ||
return typeof pair.property === 'string' | ||
? pair.property | ||
: pair.property.name; | ||
}); | ||
if (~names.indexOf(search)) { | ||
return null; | ||
} | ||
return history.filter(function (name) { | ||
return typeof pair.property === 'string' | ||
? pair.property === name | ||
: pair.property.name === name; | ||
})[0]; | ||
}; | ||
// | ||
// ### function get (msg, [validator,] callback) | ||
@@ -125,3 +159,3 @@ // #### @msg {Array|Object|string} Set of variables to get input for. | ||
result = {}; | ||
vars = vars.map(function (v) { | ||
@@ -131,6 +165,6 @@ if (typeof v === 'string') { | ||
} | ||
return prompt.properties[v] || v; | ||
}); | ||
function get(target, next) { | ||
@@ -141,3 +175,3 @@ prompt.getInput(target, function (err, line) { | ||
} | ||
var name = target.name || target; | ||
@@ -148,7 +182,7 @@ result[name] = line; | ||
} | ||
async.forEachSeries(vars, get, function (err) { | ||
return err ? callback(err) : callback(null, result); | ||
}); | ||
return prompt; | ||
@@ -168,7 +202,7 @@ }; | ||
length, msg; | ||
if (prop.default) { | ||
raw.splice(2, -1, ' (' + prop.default + ')'); | ||
} | ||
// Calculate the raw length and colorize the prompt | ||
@@ -178,3 +212,3 @@ length = raw.join('').length; | ||
msg = raw.join(''); | ||
if (prop.help) { | ||
@@ -185,6 +219,6 @@ prop.help.forEach(function (line) { | ||
} | ||
stdout.write(msg); | ||
stdout.write(msg); | ||
prompt.emit('prompt', prop); | ||
read.call(null, function (err, line) { | ||
@@ -194,21 +228,27 @@ if (err) { | ||
} | ||
if (!line || line === '') { | ||
line = prop.default || line; | ||
} | ||
if (!prop.validator && prop.empty !== false) { | ||
logger.input(line.yellow); | ||
return callback(null, line); | ||
} | ||
var valid = true, | ||
validator = prop.validator; | ||
if (prop.validator || prop.empty === false) { | ||
var valid; | ||
if (prop.validator) { | ||
valid = prop.validator.test | ||
? prop.validator.test(line) | ||
: prop.validator(line); | ||
function next(valid) { | ||
if (arguments.length < 1) { | ||
valid = true; | ||
} | ||
if (prop.empty === false && valid) { | ||
valid = line.length > 0; | ||
prop.warning = prop.warning || 'You must supply a value.'; | ||
if (!valid) { | ||
prop.warning = prop.warning || 'You must supply a value.'; | ||
} | ||
} | ||
if (!valid) { | ||
@@ -219,10 +259,32 @@ logger.error('Invalid input for ' + name.grey); | ||
} | ||
prompt.emit('invalid', prop, line); | ||
return prompt.getInput(prop, callback); | ||
} | ||
// | ||
// Log the resulting line, append this `property:value` | ||
// pair to the history for `node-prompt` and respond to | ||
// the callback. | ||
// | ||
logger.input(line.yellow); | ||
prompt._remember(prop, line); | ||
callback(null, line); | ||
} | ||
logger.input(line.yellow); | ||
callback(null, line); | ||
if (validator) { | ||
if (validator.test) { | ||
valid = validator.test(line) | ||
} | ||
else if (typeof validator === 'function') { | ||
return validator.length < 2 | ||
? next(validator(line)) | ||
: validator(line, next); | ||
} | ||
else { | ||
return callback(new Error('Invalid valiator: ' + typeof validator)); | ||
} | ||
} | ||
next(valid); | ||
}); | ||
@@ -234,3 +296,3 @@ | ||
// | ||
// ### function addProperties (obj, properties, callback) | ||
// ### function addProperties (obj, properties, callback) | ||
// #### @obj {Object} Object to add properties to | ||
@@ -240,3 +302,3 @@ // #### @properties {Array} List of properties to get values for | ||
// Prompts the user for values each of the `properties` if `obj` does not already | ||
// have a value for the property. Responds with the modified object. | ||
// have a value for the property. Responds with the modified object. | ||
// | ||
@@ -247,7 +309,7 @@ prompt.addProperties = function (obj, properties, callback) { | ||
}); | ||
if (properties.length === 0) { | ||
return callback(obj); | ||
} | ||
prompt.get(properties, function (err, results) { | ||
@@ -260,6 +322,6 @@ if (err) { | ||
} | ||
function putNested (obj, path, value) { | ||
var last = obj, key; | ||
var last = obj, key; | ||
while (path.length > 1) { | ||
@@ -270,16 +332,16 @@ key = path.shift(); | ||
} | ||
last = last[key]; | ||
} | ||
last[path.shift()] = value; | ||
} | ||
Object.keys(results).forEach(function (key) { | ||
putNested(obj, key.split('.'), results[key]); | ||
}); | ||
callback(null, obj); | ||
}); | ||
return prompt; | ||
@@ -291,3 +353,3 @@ }; | ||
// #### @callback {function} Continuation to respond to when complete | ||
// Gets a single line of input from the user. | ||
// Gets a single line of input from the user. | ||
// | ||
@@ -307,3 +369,3 @@ prompt.readLine = function (callback) { | ||
} | ||
buffer = value.substr(value.indexOf('\n')); | ||
@@ -318,3 +380,3 @@ value = value.substr(0, value.indexOf('\n')); | ||
}); | ||
return prompt; | ||
@@ -326,6 +388,6 @@ }; | ||
// #### @callback {function} Continuation to respond to when complete | ||
// Gets a single line of hidden input (i.e. `rawMode = true`) from the user. | ||
// Gets a single line of hidden input (i.e. `rawMode = true`) from the user. | ||
// | ||
prompt.readLineHidden = function (callback) { | ||
var value = '', buffer = ''; | ||
var value = ''; | ||
stdio.setRawMode(true); | ||
@@ -345,3 +407,3 @@ prompt.resume(); | ||
prompt.pause(); | ||
return callback(null, value) | ||
return callback(null, value.replace(/[\s\S][\x7f\x08]/g,'')); | ||
case '\u0003': case '\0': | ||
@@ -352,9 +414,31 @@ stdout.write('\n'); | ||
default: | ||
value += buffer + c | ||
buffer = ''; | ||
value = value + c; | ||
break; | ||
} | ||
}); | ||
return prompt; | ||
}; | ||
// | ||
// ### @private function _remember (property, value) | ||
// #### @property {Object|string} Property that the value is in response to. | ||
// #### @value {string} User input captured by `node-prompt`. | ||
// Prepends the `property:value` pair into the private `history` Array | ||
// for `node-prompt` so that it can be accessed later. | ||
// | ||
prompt._remember = function (property, value) { | ||
history.unshift({ | ||
property: property, | ||
value: value | ||
}); | ||
return prompt; | ||
}; | ||
// | ||
// If the length of the `history` Array | ||
// has exceeded the specified length to remember, | ||
// `prompt.memory`, truncate it. | ||
// | ||
if (history.length > prompt.memory) { | ||
history.splice(prompt.memory, history.length - prompt.memory); | ||
} | ||
}; |
{ | ||
"name": "prompt", | ||
"description": "A beautiful command-line prompt for node.js", | ||
"version": "0.1.2", | ||
"version": "0.1.3", | ||
"author": "Nodejitsu Inc. <info@nodejitsu.com>", | ||
@@ -17,2 +17,3 @@ "contributors": [ | ||
"colors": "0.x.x", | ||
"pkginfo": "0.x.x", | ||
"winston": "0.3.x" | ||
@@ -22,3 +23,3 @@ }, | ||
"scripts": { | ||
"test": "vows test/*-test.js --spec" | ||
"test": "vows test/prompt-test.js --spec" | ||
}, | ||
@@ -25,0 +26,0 @@ "engines": { |
@@ -63,3 +63,3 @@ # node-prompt | ||
validator: /^[a-zA-Z\s\-]+$/, | ||
waring: 'Name must be only letters, spaces, or dashes', | ||
warning: 'Name must be only letters, spaces, or dashes', | ||
empty: false | ||
@@ -157,2 +157,2 @@ }, | ||
[0]: https://github.com/nodejitsu/prompt/tree/master/examples | ||
[1]: http://nodejitsu.com | ||
[1]: http://nodejitsu.com |
/* | ||
* helpers.js: Test helpers for the prompt tests. | ||
* helpers.js: Test helpers for the prompt tests. | ||
* | ||
@@ -10,3 +10,4 @@ * (C) 2010, Nodejitsu Inc. | ||
stream = require('stream'), | ||
util = require('util'); | ||
util = require('util'), | ||
prompt = require('../lib/prompt'); | ||
@@ -32,3 +33,3 @@ var helpers = exports; | ||
// | ||
// Create some mock streams for asserting against | ||
// Create some mock streams for asserting against | ||
// in our prompt tests. | ||
@@ -41,3 +42,3 @@ // | ||
// | ||
// Monkey punch `util.error` to silence console output | ||
// Monkey punch `util.error` to silence console output | ||
// and redirect to helpers.stderr for testing. | ||
@@ -60,3 +61,42 @@ // | ||
warning: 'Username can only be letters, numbers, and dashes' | ||
}, | ||
password: { | ||
name: 'password', | ||
hidden: true, | ||
empty: false | ||
}, | ||
badValidator: { | ||
name: 'bad-validator', | ||
validator: ['cant', 'use', 'array'] | ||
}, | ||
animal: { | ||
name: 'animal', | ||
description: 'Enter an animal', | ||
default: 'dog', | ||
validator: /dog|cat/ | ||
}, | ||
sound: { | ||
name: 'sound', | ||
description: 'What sound does this animal make?', | ||
validator: function (value) { | ||
var animal = prompt.history(0).value; | ||
return animal === 'dog' && value === 'woof' | ||
|| animal === 'cat' && value === 'meow'; | ||
} | ||
}, | ||
fnvalidator: { | ||
name: 'fnvalidator', | ||
validator: function (line) { | ||
return line.slice(0,2) == 'fn'; | ||
}, | ||
warning: 'fnvalidator must start with "fn"' | ||
}, | ||
cbvalidator: { | ||
name: 'cbvalidator', | ||
validator: function (line, next) { | ||
next(line.slice(0,2) == 'cb'); | ||
}, | ||
warning: 'cbvalidator must start with "cb"' | ||
} | ||
}; | ||
}; |
/* | ||
* prompt-test.js: Tests for node-prompt. | ||
* prompt-test.js: Tests for node-prompt. | ||
* | ||
@@ -7,3 +7,3 @@ * (C) 2010, Nodejitsu Inc. | ||
*/ | ||
var assert = require('assert'), | ||
@@ -18,6 +18,6 @@ vows = require('vows'), | ||
prompt.start({ | ||
stdin: helpers.stdin, | ||
stdin: helpers.stdin, | ||
stdout: helpers.stdout | ||
}); | ||
return null; | ||
@@ -36,2 +36,13 @@ }, | ||
"the readLineHidden() method": { | ||
"when given backspaces": { | ||
topic: function () { | ||
prompt.readLineHidden(this.callback); | ||
helpers.stdin.write('no-\x08backspace.\xff'); | ||
helpers.stdin.write('\n'); | ||
}, | ||
"should remove the proper characters": function (err,input) { | ||
assert.isNull(err); | ||
assert.equal(input, 'nobackspace'); | ||
} | ||
}, | ||
topic: function () { | ||
@@ -54,3 +65,3 @@ prompt.readLineHidden(this.callback); | ||
}) | ||
prompt.getInput('test input', this.callback); | ||
@@ -65,2 +76,43 @@ helpers.stdin.write('test value\n'); | ||
}, | ||
"with a hidden field that is not supposed to be empty": { | ||
"and we provide valid input": { | ||
topic: function () { | ||
var that = this; | ||
helpers.stdout.once('data', function (msg) { | ||
that.msg = msg; | ||
}); | ||
prompt.getInput('password', this.callback); | ||
helpers.stdin.write('trustno1\n'); | ||
}, | ||
"should prompt to stdout and respond with data": function (err, input) { | ||
assert.isNull(err); | ||
assert.equal(input, 'trustno1'); | ||
assert.isTrue(this.msg.indexOf('password') !== -1); | ||
} | ||
}, | ||
"and we don't provide an input": { | ||
topic: function () { | ||
var that = this; | ||
helpers.stdout.once('data', function (msg) { | ||
that.msg = msg; | ||
}); | ||
helpers.stderr.once('data', function (msg) { | ||
that.errmsg = msg; | ||
}); | ||
prompt.getInput(helpers.properties.password, function () {}); | ||
prompt.once('invalid', this.callback.bind(null, null)) | ||
helpers.stdin.write('\n'); | ||
}, | ||
"should prompt with an error": function (ign, prop, input) { | ||
assert.isObject(prop); | ||
assert.equal(input, ''); | ||
assert.isTrue(this.errmsg.indexOf('Invalid input') !== -1); | ||
assert.isTrue(this.msg.indexOf('password') !== -1); | ||
} | ||
} | ||
}, | ||
"with a complex property prompt": { | ||
@@ -112,2 +164,10 @@ "and a valid input": { | ||
} | ||
}, | ||
"with an invalid validator (array)": { | ||
topic: function () { | ||
prompt.getInput(helpers.properties.badValidator, this.callback); | ||
}, | ||
"should respond with an error": function (err, ign) { | ||
assert.isTrue(!!err); | ||
} | ||
} | ||
@@ -139,7 +199,7 @@ } | ||
var that = this; | ||
helpers.stdout.once('data', function (msg) { | ||
that.msg = msg; | ||
}); | ||
prompt.properties['riffwabbles'] = helpers.properties['riffwabbles']; | ||
@@ -156,2 +216,28 @@ prompt.get('riffwabbles', this.callback); | ||
} | ||
}, | ||
"with a sync function validator": { | ||
topic: function () { | ||
var that = this; | ||
helpers.stdout.once('data', function (msg) { | ||
that.msg = msg; | ||
}); | ||
prompt.properties['fnvalidator'] = helpers.properties['fnvalidator']; | ||
prompt.get('fnvalidator', this.callback); | ||
helpers.stdin.write('fn123\n'); | ||
} | ||
}, | ||
"with a callback validator": { | ||
topic: function () { | ||
var that = this; | ||
helpers.stdout.once('data', function (msg) { | ||
that.msg = msg; | ||
}); | ||
prompt.properties['cbvalidator'] = helpers.properties['cbvalidator']; | ||
prompt.get('cbvalidator', this.callback); | ||
helpers.stdin.write('cb123\n'); | ||
} | ||
} | ||
@@ -175,2 +261,33 @@ } | ||
} | ||
}).export(module); | ||
}).addBatch({ | ||
"When using node-prompt": { | ||
"the history() method": { | ||
"when used inside of a complex property": { | ||
"with correct value(s)": { | ||
topic: function () { | ||
prompt.get([helpers.properties.animal, helpers.properties.sound], this.callback); | ||
helpers.stdin.write('dog\n'); | ||
helpers.stdin.write('woof\n'); | ||
}, | ||
"should respond with the values entered": function (err, result) { | ||
assert.isTrue(!err); | ||
assert.equal(result.animal, 'dog'); | ||
assert.equal(result.sound, 'woof'); | ||
} | ||
}, | ||
"with an incorrect value": { | ||
topic: function () { | ||
prompt.get([helpers.properties.animal, helpers.properties.sound], function () {}); | ||
prompt.once('invalid', this.callback.bind(null, null)); | ||
helpers.stdin.write('dog\n'); | ||
helpers.stdin.write('meow\n'); | ||
}, | ||
"should prompt for the error": function (ign, property, line) { | ||
assert.equal(property.name, 'sound'); | ||
assert.equal(line, 'meow'); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
}).export(module); |
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
87249
16
1127
157
4
+ Addedpkginfo@0.x.x
+ Addedpkginfo@0.4.1(transitive)