Skip to content

Commit

Permalink
Fix options key name conflict with commander object's' key (tj#404, t…
Browse files Browse the repository at this point in the history
…j#648, etc...).
  • Loading branch information
brn committed Aug 3, 2017
1 parent df3b529 commit 8e5ed7f
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 11 deletions.
20 changes: 11 additions & 9 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ function Command(name) {
this._allowUnknownOption = false;
this._args = [];
this._name = name || '';
this._optionKeyValueHolder = Object.create(null);
}

/**
Expand Down Expand Up @@ -357,6 +358,7 @@ Command.prototype.action = function(fn) {

Command.prototype.option = function(flags, description, fn, defaultValue) {
var self = this
, optionKeyValueHolder = this._optionKeyValueHolder
, option = new Option(flags, description)
, oname = option.name()
, name = camelcase(oname);
Expand All @@ -381,7 +383,7 @@ Command.prototype.option = function(flags, description, fn, defaultValue) {
// when --no-* we make sure default is true
if (false == option.bool) defaultValue = true;
// preassign only if we have a default
if (undefined !== defaultValue) self[name] = defaultValue;
if (undefined !== defaultValue) self[name] = optionKeyValueHolder[name] = defaultValue;
}

// register the option
Expand All @@ -391,23 +393,23 @@ Command.prototype.option = function(flags, description, fn, defaultValue) {
// and conditionally invoke the callback
this.on('option:' + oname, function(val) {
// coercion
if (null !== val && fn) val = fn(val, undefined === self[name]
if (null !== val && fn) val = fn(val, undefined === optionKeyValueHolder[name]
? defaultValue
: self[name]);
: optionKeyValueHolder[name]);

// unassigned or bool
if ('boolean' == typeof self[name] || 'undefined' == typeof self[name]) {
if ('boolean' == typeof optionKeyValueHolder[name] || 'undefined' == typeof optionKeyValueHolder[name]) {
// if no value, bool true, and we have a default, then use it!
if (null == val) {
self[name] = option.bool
self[name] = optionKeyValueHolder[name] = option.bool
? defaultValue || true
: false;
} else {
self[name] = val;
self[name] = optionKeyValueHolder[name] = val;
}
} else if (null !== val) {
// reassign
self[name] = val;
self[name] = optionKeyValueHolder[name] = val;
}
});

Expand Down Expand Up @@ -751,12 +753,12 @@ Command.prototype.parseOptions = function(argv) {
* @api public
*/
Command.prototype.opts = function() {
var result = {}
var result = Object.create(null)
, len = this.options.length;

for (var i = 0 ; i < len; i++) {
var key = camelcase(this.options[i].name());
result[key] = key === 'version' ? this._version : this[key];
result[key] = key === 'version' ? this._version : this._optionKeyValueHolder[key];
}
return result;
};
Expand Down
9 changes: 7 additions & 2 deletions test/test.options.func.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,23 @@ var program = require('../')
program
.version('0.0.1')
.description('sdfdsfsfsdfdsf')
.option('-n, --name', 'confliced option')
.option('-n, --toString', 'confliced option')
.option('-n, --once', 'confliced option')
.option('-f, --foo', 'add some foo')
.option('-b, --bar', 'add some bar')
.option('-M, --no-magic', 'disable magic')
.option('-c, --camel-case', 'convert to camelCase')
.option('-q, --quux <quux>', 'add some quux');

program.parse(['node', 'test', '--foo', '--bar', '--no-magic', '--camel-case', '--quux', 'value']);
program.parse(['node', 'test', '--name', '--toString', '--once', '--foo', '--bar', '--no-magic', '--camel-case', '--quux', 'value']);
program.opts.should.be.a.Function;

var opts = program.opts();
opts.should.be.an.Object;
opts.version.should.equal('0.0.1');
opts.name.should.be.true;
opts.toString.should.be.true;
opts.once.should.be.true;
opts.foo.should.be.true;
opts.bar.should.be.true;
opts.magic.should.be.false;
Expand Down

0 comments on commit 8e5ed7f

Please sign in to comment.