Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added .fill() feature

.fill() method makes it easy to write multiple prompt at once.
  • Loading branch information...
commit 65862f81144271568cff30c346fe766b7ec1084e 1 parent 8e26188
@kuwabarahiroshi authored
Showing with 235 additions and 0 deletions.
  1. +51 −0 examples/fill
  2. +70 −0 lib/commander.js
  3. +114 −0 test/test.prompt.fill.js
View
51 examples/fill
@@ -0,0 +1,51 @@
+#!/usr/bin/env node
+
+/**
+ * Module dependencies.
+ */
+
+var program = require('../');
+
+function normalizeSex(sex) {
+ return sex.toLowerCase() == 'm' || sex.toLowerCase == 'male' ? 'male' : 'female';
+}
+
+program
+ .version('0.0.1')
+ .option('-n --nickname <name>', 'Your nickname.')
+ .option('-a --age <age>', 'Your age.')
+ .option('-s --sex <sex>', 'Your sex. [ male | female ]', normalizeSex, 'unknown')
+ .option('-f --favorite-song <song>', 'Your favorite <song>.')
+ .parse(process.argv);
+
+program
+ .fill({
+ 'nickname': 'What is your nickname? '
+ , 'age': 'How old are your? '
+ , 'favorite-song': 'What is your favorite song? ' // option name can be camelCase as well
+ })
+
+// Filled arguments are available on 'filled' event.
+program.on('filled', function(program) {
+ console.log(' - name: %s', program.nickname);
+ console.log(' - age: %s', program.age);
+ console.log(' - sex: %s', program.sex);
+ console.log(' - favorite song: %s', program.favoriteSong);
+});
+
+
+
+/**
+ * Miscelenious
+ */
+
+/**
+ * .fill() method takes 2nd argument as a callback
+ */
+// These two lines are synonymous.
+// program.fill({'a', 'aaa: '}, main);
+// program.fill({'a': 'aaa: '}).on('filled', main);
+//
+// function main(program) {
+// console.log(program);
+// }
View
70 lib/commander.js
@@ -946,6 +946,76 @@ Command.prototype.choose = function(list, index, fn){
};
/**
+ * Fill arguments with prompt if it isn't specified on command line.
+ *
+ * Examples:
+ *
+ * program
+ * .option('-n, --nickname <name>')
+ * .option('-a, --age <age>')
+ * .option('-s', --sex <sex>')
+ * .parse(process.argv);
+ *
+ * // .fill() should be called after .parse()
+ * program.fill({
+ * 'nickname': 'What is your nickname? '
+ * , 'age': 'How old are you? '
+ * });
+ *
+ * // if '--nickname' or '--age' aren't supplied with command line option,
+ * // those values will be filled with prompt.
+ * // '--sex' is still just an option because it isn't specified to be filled.
+ *
+ * // Filled arguments are available on 'filled' event.
+ * program.on('filled', function(program) {
+ * console.log('name: %s', program.nickname);
+ * console.log('age: %s', program.age);
+ * console.log('sex: %s', program.sex);
+ * });
+ *
+ * @param {Object} config
+ * @param {Function} callback
+ * @return {Command} for chaining
+ * @api public
+ */
+
+Command.prototype.fill = function(config, callback) {
+ var queue = [], arg, camel;
+ if ('function' === typeof callback) this.on('filled', callback);
+
+ for (arg in config) {
+ if ((camel = camelcase(arg)) in this) continue;
+ queue.push({'arg': camel, 'prompt_message': config[arg]});
+ }
+ fillWithPrompt(this, queue);
+ return this;
+};
+
+/**
+ * Fill in queued arguments with prompt
+ *
+ * @param {Command} command
+ * @param {Array} queue
+ * @api private
+ */
+
+function fillWithPrompt(command, queue) {
+ if (!queue.length) {
+ // guaranntee to execute 'filled' callback
+ // even if all arguments are supplied with command line option.
+ setTimeout(function() { command.emit('filled', command); }, 0);
+ process.stdin.pause();
+ return;
+ }
+
+ var current = queue.shift();
+ command.prompt(current['prompt_message'], function(input) {
+ command[current.arg] = input.trim();
+ fillWithPrompt(command, queue);
+ });
+}
+
+/**
* Camel-case the given `flag`
*
* @param {String} flag
View
114 test/test.prompt.fill.js
@@ -0,0 +1,114 @@
+/**
+ * Module dependencies.
+ */
+
+var events = require('events')
+ , should = require('should')
+ , Command = require('../').Command;
+
+//mock stdin on process
+var stdin = new events.EventEmitter();
+stdin.setEncoding = stdin.pause = stdin.resume = function() {};
+stdin.write = function(data) { stdin.emit('data', data); };
+process.__defineGetter__('stdin', function() { return stdin });
+
+//mock stdout on process
+var stdout = new events.EventEmitter();
+stdout.write = function(data) { this.emit('data', data) };
+stdout.expect = function(expected, fn) {
+ var actual = '';
+ this.once('data', function(data){ actual = data; });
+ fn();
+ actual.should.equal(expected);
+}
+//var realOut = process.stdout;
+process.__defineGetter__('stdout', function() { return stdout });
+
+var name_prompt = 'What is your name? '
+ , age_prompt = 'How old are your? '
+ , name_input_on_command = 'name input on command'
+ , age_input_on_command = 'age input on command'
+ , name_input_from_prompt = 'name input from prompt'
+ , age_input_from_prompt = 'age input from prompt'
+ , prompt_config = {
+ 'nickname': name_prompt
+ , 'age': age_prompt
+ };
+
+
+/**
+ * Test case that --nickname and --age aren't supplied on command line.
+ */
+program = new Command()
+ .option('-n, --nickname <name>')
+ .option('-a, --age <age>')
+ .parse(['node', 'test']);
+
+stdout.expect(name_prompt, function() {
+ program.fill(prompt_config);
+
+ stdout.expect(age_prompt, function() {
+ stdin.write(name_input_from_prompt);
+ });
+
+ stdin.write(age_input_from_prompt);
+})
+
+program.on('filled', function(program) {
+ program.should.have.property('nickname', name_input_from_prompt);
+ program.should.have.property('age', age_input_from_prompt);
+});
+
+
+/**
+ * Test case that --nickname is supplied on command line, but --age.
+ */
+program = new Command()
+ .option('-n, --nickname <name>')
+ .option('-a, --age <age>')
+ .parse(['node', 'test', '--nickname', name_input_on_command]);
+
+stdout.expect(age_prompt, function() {
+ program.fill(prompt_config);
+ stdin.write(age_input_from_prompt);
+})
+
+program.on('filled', function(program) {
+ program.should.have.property('nickname', name_input_on_command);
+ program.should.have.property('age', age_input_from_prompt);
+});
+
+
+/**
+ * Test case that --age is supplied on command line, but --nickname.
+ */
+program = new Command()
+ .option('-n, --nickname <name>')
+ .option('-a, --age <age>')
+ .parse(['node', 'test', '--age', age_input_on_command]);
+
+stdout.expect(name_prompt, function() {
+ program.fill(prompt_config);
+ stdin.write(name_input_from_prompt);
+})
+
+program.on('filled', function(program) {
+ program.should.have.property('nickname', name_input_from_prompt);
+ program.should.have.property('age', age_input_on_command);
+});
+
+
+/**
+ * Test case that --nickname and --age are supplied on command line.
+ */
+program = new Command()
+ .option('-n, --nickname <name>')
+ .option('-a, --age <age>')
+ .parse(['node', 'test', '--nickname', name_input_on_command, '--age', age_input_on_command]);
+
+program.fill(prompt_config);
+
+program.on('filled', function(program) {
+ program.should.have.property('nickname', name_input_on_command);
+ program.should.have.property('age', age_input_on_command);
+});
Please sign in to comment.
Something went wrong with that request. Please try again.