prompt-for
Advanced tools
Comparing version 0.1.0 to 0.2.0
0.2.0 - April 24, 2014 | ||
---------------------- | ||
* add `default` to schema | ||
* add `required` to schema | ||
0.1.0 - March 27, 2013 | ||
@@ -3,0 +8,0 @@ ---------------------- |
var chalk = require('chalk'); | ||
var debug = require('debug')('metalsmith-prompt'); | ||
var debug = require('debug')('prompt-for'); | ||
var each = require('async').eachSeries; | ||
var extend = require('extend'); | ||
var max = require('max-component'); | ||
@@ -20,3 +18,6 @@ var pad = require('pad-component').left; | ||
* | ||
* @param {Object} schema | ||
* @param {Object or Array or String} schema | ||
* @param {Object} options (optional) | ||
* @property {String} color | ||
* @property {Boolean} pad | ||
* @param {Function} fn | ||
@@ -28,7 +29,5 @@ */ | ||
options = options || {}; | ||
schema = normalize(schema); | ||
schema = normalize(schema, options); | ||
var color = options.color in chalk.styles ? options.color : null; | ||
var questions = 'array' == typeof schema ? schema : Object.keys(schema); | ||
var width = max(questions, 'length') + 4; | ||
var questions = Object.keys(schema); | ||
var answers = {}; | ||
@@ -44,7 +43,11 @@ | ||
debug('asking for "%s"', key); | ||
var type = schema[key] || 'string'; | ||
var obj = schema[key]; | ||
var type = obj.type; | ||
var fn = types[type]; | ||
var question = false !== options.pad ? pad(key, width) : key; | ||
fn(question, color, function(val){ | ||
if (!fn) return done(new Error('Unrecognized type: "' + type + '".')); | ||
fn(obj, options, function(val){ | ||
debug('answered "%s" with "%s"', key, val); | ||
if (null == val && null != obj.default) val = obj.default; | ||
if (null == val && obj.required) return ask(key, done); | ||
answers[key] = val; | ||
@@ -60,23 +63,44 @@ done(); | ||
* @param {Object or Array or String} schema | ||
* @param {Object} options | ||
* @return {Object} | ||
*/ | ||
function normalize(schema){ | ||
var ret = {}; | ||
function normalize(schema, options){ | ||
if ('string' == type(schema)) { | ||
var key = schema; | ||
schema = {}; | ||
schema[key] = {}; | ||
} | ||
switch (type(schema)) { | ||
case 'object': | ||
ret = schema; | ||
break; | ||
case 'string': | ||
ret[schema] = 'string'; | ||
break; | ||
case 'array': | ||
schema.forEach(function(key){ | ||
ret[key] = 'string'; | ||
}); | ||
break; | ||
if ('array' == type(schema)) { | ||
var arr = schema; | ||
schema = {}; | ||
arr.forEach(function(key){ | ||
schema[key] = {}; | ||
}); | ||
} | ||
return ret; | ||
if ('object' == type(schema)) { | ||
Object.keys(schema).forEach(function(key){ | ||
var val = schema[key]; | ||
if ('string' != type(val)) return; | ||
schema[key] = {}; | ||
schema[key].type = val; | ||
}); | ||
} | ||
var keys = Object.keys(schema); | ||
var width = max(keys, 'length') + 4; | ||
keys.forEach(function(key){ | ||
var obj = schema[key]; | ||
obj.type = obj.type || 'string'; | ||
obj.required = !! obj.required; | ||
obj.label = obj.label || key; | ||
if (options.pad) obj.label = pad(obj.label, width); | ||
if ('boolean' == obj.type) obj.default = obj.default || false; | ||
if ('date' == obj.type) obj.default = obj.default || 'now'; | ||
}); | ||
return schema; | ||
} |
var chalk = require('chalk'); | ||
var date = require('date.js'); | ||
var fmt = require('util').format; | ||
var prompt = require('cli-prompt'); | ||
var colors = chalk.styles; | ||
/** | ||
* Prompt for a string with `msg`. | ||
* Prompt for a string for a given `schema` and `options`. | ||
* | ||
* @param {String} msg | ||
* @param {String} color (optional) | ||
* @param {Object} schema | ||
* @param {Object} options | ||
* @param {Function} fn | ||
*/ | ||
exports.string = function(msg, color, fn){ | ||
msg += ': '; | ||
if (color) msg = chalk[color](msg); | ||
exports.string = function(schema, options, fn){ | ||
var msg = format(schema, options); | ||
prompt(msg, fn); | ||
@@ -21,12 +22,11 @@ } | ||
/** | ||
* Prompt for a password with `msg`. | ||
* Prompt for a password for a given `schema` and `options`. | ||
* | ||
* @param {String} msg | ||
* @param {String} color (optional) | ||
* @param {Object} schema | ||
* @param {Object} options | ||
* @param {Function} fn | ||
*/ | ||
exports.password = function(msg, color, fn){ | ||
msg += ': '; | ||
if (color) msg = chalk[color](msg); | ||
exports.password = function(schema, options, fn){ | ||
var msg = format(schema, options); | ||
prompt.password(msg, fn); | ||
@@ -36,14 +36,15 @@ } | ||
/** | ||
* Prompt for a number with `msg`. | ||
* Prompt for a number for a given `schema` and `options`. | ||
* | ||
* @param {String} msg | ||
* @param {String} color (optional) | ||
* @param {Object} schema | ||
* @param {Object} options | ||
* @param {Function} fn | ||
*/ | ||
exports.number = function(msg, color, fn){ | ||
msg += ': '; | ||
if (color) msg = chalk[color](msg); | ||
exports.number = function(schema, options, fn){ | ||
var msg = format(schema, options); | ||
prompt(msg, function(val){ | ||
fn(parseFloat(val, 10) || null); | ||
val = parseFloat(val, 10); | ||
if (isNaN(val)) return fn(); | ||
fn(val); | ||
}); | ||
@@ -53,15 +54,14 @@ } | ||
/** | ||
* Prompt for a boolean with `msg`. | ||
* Prompt for a boolean for a given `schema` and `options`. | ||
* | ||
* @param {String} msg | ||
* @param {String} color (optional) | ||
* @param {Object} schema | ||
* @param {Object} options | ||
* @param {Function} fn | ||
*/ | ||
exports.boolean = function(msg, color, fn){ | ||
msg += ':'; | ||
if (color) msg = chalk[color](msg); | ||
msg += ' (y/n) '; | ||
exports.boolean = function(schema, options, fn){ | ||
var msg = format(schema, options); | ||
prompt(msg, function(val){ | ||
fn(/y|yes/i.test(val)); | ||
if ('' == val) return fn(); | ||
fn(/^(y|yes|true)$/i.test(val)); | ||
}); | ||
@@ -71,17 +71,15 @@ } | ||
/** | ||
* Prompt for a date with `msg`. | ||
* Prompt for a date for a given `schema` and `options`. | ||
* | ||
* @param {String} msg | ||
* @param {String} color (optional) | ||
* @param {Object} schema | ||
* @param {Object} options | ||
* @param {Function} fn | ||
*/ | ||
exports.date = function(msg, color, fn){ | ||
msg += ': '; | ||
if (color) msg = chalk[color](msg); | ||
exports.date = function(schema, options, fn){ | ||
var msg = format(schema, options); | ||
prompt(msg, function(val){ | ||
var ret = new Date(val); | ||
if (invalid(ret)) ret = date(val); | ||
if (invalid(ret)) ret = null; | ||
fn(ret); | ||
return invalid(ret) ? fn() : fn(ret); | ||
}); | ||
@@ -91,2 +89,32 @@ } | ||
/** | ||
* Format the prompt message. | ||
* | ||
* @param {Object} schema | ||
* @param {Object} options | ||
*/ | ||
function format(schema, options){ | ||
var color = options.color; | ||
var sep = options.separator || ':'; | ||
var label = color in colors ? chalk[color](schema.label) : schema.label; | ||
return fmt('%s%s %s ', label, sep, hint(schema)); | ||
} | ||
/** | ||
* Format the default hint for a `schema`. | ||
* | ||
* @param {Object} schema | ||
* @return {String} | ||
*/ | ||
function hint(schema){ | ||
var def = schema.default; | ||
switch (schema.type) { | ||
case 'boolean': return def ? '(Y/n)' : '(y/N)'; | ||
case 'date': if (!def) return '(now)'; | ||
default: return def ? fmt('(%s)', def) : ''; | ||
} | ||
} | ||
/** | ||
* Test whether a date is invalid. | ||
@@ -93,0 +121,0 @@ * |
@@ -5,15 +5,15 @@ { | ||
"repository": "git://github.com/segmentio/prompt-for.git", | ||
"version": "0.1.0", | ||
"version": "0.2.0", | ||
"license": "MIT", | ||
"main": "lib/index.js", | ||
"dependencies": { | ||
"async": "^0.7.0", | ||
"chalk": "^0.4.0", | ||
"cli-prompt": "^0.3.2", | ||
"component-type": "^1.0.0", | ||
"date.js": "^0.2.0", | ||
"debug": "^0.8.0", | ||
"extend": "^1.2.1", | ||
"debug": "^0.7.4", | ||
"async": "^0.2.10", | ||
"chalk": "^0.4.0", | ||
"pad-component": "0.0.1", | ||
"cli-prompt": "^0.3.2", | ||
"max-component": "^1.0.0", | ||
"component-type": "^1.0.0" | ||
"pad-component": "0.0.1" | ||
}, | ||
@@ -23,2 +23,2 @@ "devDependencies": { | ||
} | ||
} | ||
} |
@@ -49,2 +49,44 @@ | ||
## Options | ||
Define or overwrite default values... | ||
* Default `boolean` value is **false** | ||
* Default `date` value is **now** | ||
```js | ||
var prompt = require('prompt-for'); | ||
var schema = { | ||
name: {type:'string', default:'Ian'}, | ||
siblings: {type:'number', default:42}, | ||
birthday: {type:'date', default:'yesterday'}, | ||
deceased: {type:'boolean', default:true}, | ||
secret: {type:'password', default:'1234'} | ||
}; | ||
prompt(schema, function(err, answers){ | ||
assert(answers.name == 'Ian'); | ||
// ... | ||
}); | ||
``` | ||
Disable required for `string` and `number`... | ||
By default, empty or incorrect answers when asked a string or a number, will be asked again. Set `required` to **false** allows you to skip the question. | ||
```js | ||
var prompt = require('prompt-for'); | ||
var schema = { | ||
name: {type:'string', required:false}, | ||
siblings: {type:'number', required:false} | ||
}; | ||
prompt(schema, function(err, answers){ | ||
assert(answers.name == null); | ||
assert(answers.number == null); | ||
}); | ||
``` | ||
## API | ||
@@ -51,0 +93,0 @@ |
@@ -67,2 +67,30 @@ | ||
}); | ||
it('should apply defaults', function(done){ | ||
prompt({ number: { type: 'number', default: 42 }}, function(err, answers){ | ||
if (err) return done(err); | ||
assert.equal(answers.number, 42); | ||
done(); | ||
}); | ||
answer(''); | ||
}); | ||
it('should wait for required values', function(done){ | ||
prompt({ number: { type: 'number', required: true }}, function(err, answers){ | ||
if (err) return done(err); | ||
assert.equal(answers.number, 42); | ||
done(); | ||
}); | ||
answer(''); | ||
answer('42'); | ||
}); | ||
it('should use a default for required values', function(done){ | ||
prompt({ number: { type: 'number', default: 42, required: true }}, function(err, answers){ | ||
if (err) return done(err); | ||
assert.equal(answers.number, 42); | ||
done(); | ||
}); | ||
answer(''); | ||
}); | ||
}); | ||
@@ -69,0 +97,0 @@ |
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
10964
292
104
+ Addedasync@0.7.0(transitive)
+ Addeddebug@0.8.1(transitive)
- Removedasync@0.2.10(transitive)
Updatedasync@^0.7.0
Updateddebug@^0.8.0