Permalink
Browse files

Merge pull request #41 from hpaulj/exclusiveUsage

Exclusive usage
  • Loading branch information...
2 parents c552034 + e2fab72 commit a3f6aaf5be9832c98f73f57526cb2427c4f37247 @puzrin puzrin committed Jan 8, 2013
Showing with 93 additions and 16 deletions.
  1. +1 −1 lib/argument_parser.js
  2. +15 −15 lib/help/formatter.js
  3. +77 −0 test/testgroup.js
View
@@ -370,7 +370,7 @@ ArgumentParser.prototype._parseKnownArgs = function (argStrings, namespace) {
// error if this argument is not allowed with other previously
// seen arguments, assuming that actions that use the default
// value don't really count as "present"
- if (argumentValues !== action.default) {
+ if (argumentValues !== action.defaultValue) {
seenNonDefaultActions.push(action);
if (!!actionConflicts[actionHash(action)]) {
actionConflicts[actionHash(action)].forEach(function (actionConflict) {
View
@@ -445,7 +445,8 @@ HelpFormatter.prototype._formatActionsUsage = function (actions, groups) {
if (start >= 0) {
end = start + group._groupActions.length;
- if (actions.slice(start, end) === group._groupActions) {
+ //if (actions.slice(start, end) === group._groupActions) {
+ if (_.isEqual(actions.slice(start, end), group._groupActions)) {
group._groupActions.forEach(function (action) {
groupActions.push(action);
});
@@ -530,25 +531,24 @@ HelpFormatter.prototype._formatActionsUsage = function (actions, groups) {
});
// insert things at the necessary indices
- inserts.reverse().forEach(function (insert, insertIndex) {
- parts = parts.slice(0, insertIndex).concat(
- [insert],
- parts.slice(insertIndex + 1, parts.length - 1)
- );
- });
+ for (var i = inserts.length - 1; i >= 0; --i) {
+ if (inserts[i] !== null) {
+ parts.splice(i, 0, inserts[i]);
+ }
+ }
// join all the action items with spaces
var text = parts.filter(function (part) {
return !!part;
}).join(' ');
// clean up separators for mutually exclusive groups
- var regexpOpen = '[\\[(]';
- var regexpClose = '[\\])]';
- text = text.replace('(' + regexpOpen + ') ', '\\1');
- text = text.replace(' (' + regexpClose + ')', '\\1');
- text = text.replace(regexpOpen + ' *' + regexpClose, '');
- text = text.replace('\\(([^|]*)\\)', '\\1');
+ text = text.replace(/([\[(]) /g, '$1'); // remove spaces
+ text = text.replace(/ ([\])])/g, '$1');
+ text = text.replace(/\[ *\]/g, ''); // remove empty groups
+ text = text.replace(/\( *\)/g, '');
+ text = text.replace(/\(([^|]*)\)/g, '$1'); // remove () from single action groups
+
text = _.str.strip(text);
// return the text
@@ -701,11 +701,11 @@ HelpFormatter.prototype._formatArgs = function (action, metavarDefault) {
break;
case $$.ZERO_OR_MORE:
metavars = buildMetavar(2);
- result = '[' + metavars[0] + '[' + metavars[1] + ' ...]]';
+ result = '[' + metavars[0] + ' [' + metavars[1] + ' ...]]';
break;
case $$.ONE_OR_MORE:
metavars = buildMetavar(2);
- result = '' + metavars[0] + '[' + metavars[1] + ' ...]';
+ result = '' + metavars[0] + ' [' + metavars[1] + ' ...]';
break;
case $$.REMAINDER:
result = '...';
View
@@ -102,6 +102,83 @@ describe('ArgumentParser', function () {
/one of the arguments (.*) is required/i
);
});
+ it('mutually exclusive group usage', function () {
+ // adapted from test_argparse.py TestMutuallyExclusiveSimple
+ var usage;
+ parser = new ArgumentParser({prog: 'PROG', debug: true});
+ group = parser.addMutuallyExclusiveGroup({required: true});
+ // or should the input be {required: true}?
+ group.addArgument(['--bar'], {help: 'bar help'});
+ group.addArgument(['--baz'], {nargs: '?', constant: 'Z', help: 'baz help'});
+ args = parser.parseArgs(['--bar', 'X']);
+ assert.deepEqual(args, {bar: 'X', baz: null});
+
+ assert.throws(
+ function () {
+ args = parser.parseArgs('--bar X --baz Y'.split(' '));
+ },
+ /Not allowed with argument/i
+ );
+ usage = parser.formatUsage();
+ assert.equal(usage, 'usage: PROG [-h] (--bar BAR | --baz [BAZ])\n');
+ group.required = false;
+ usage = parser.formatUsage();
+ assert.equal(usage, 'usage: PROG [-h] [--bar BAR | --baz [BAZ]]\n');
+ // could also test all or part of parser.formatHelp()
+ });
+ it('mutually exclusive optional and positional', function () {
+ // adapted from test_argparse.py TestMutuallyExclusiveOptionalAndPositional
+ var usage;
+ parser = new ArgumentParser({prog: 'PROG', debug: true});
+ group = parser.addMutuallyExclusiveGroup({required: true});
+ // or should the input be {required: true}?
+ group.addArgument(['--foo'], {action: 'storeTrue', help: 'foo help'});
+ group.addArgument(['--spam'], {help: 'spam help'});
+ group.addArgument(['badger'], {nargs: '*', defaultValue: 'X', help: 'badger help'});
+ args = parser.parseArgs(['--spam', 'S']);
+ assert.deepEqual(args, {foo: false, spam: 'S', badger: 'X'});
+ args = parser.parseArgs(['X']);
+ assert.deepEqual(args, {"foo": false, "spam": null, "badger": ['X']});
+ args = parser.parseArgs(['--foo']);
+ assert.deepEqual(args, {foo: true, spam: null, badger: 'X'});
+ assert.throws(
+ function () {
+ args = parser.parseArgs('--foo --spam 5'.split(' '));
+ },
+ /Not allowed with argument/i
+ );
+ usage = parser.formatUsage();
+ assert.equal(usage, 'usage: PROG [-h] (--foo | --spam SPAM | badger [badger ...])\n');
+ group.required = false;
+ usage = parser.formatUsage();
+ assert.equal(usage, 'usage: PROG [-h] [--foo | --spam SPAM | badger [badger ...]]\n');
+ });
+ it('two mutually exclusive groups', function () {
+ // adapted from test_argparse.py
+ var usage, group1, group2;
+ parser = new ArgumentParser({prog: 'PROG', debug: true});
+ group1 = parser.addMutuallyExclusiveGroup({required: true});
+ group1.addArgument(['--foo'], {action: 'storeTrue'});
+ group1.addArgument(['--bar'], {action: 'storeFalse'});
+ group2 = parser.addMutuallyExclusiveGroup({required: false});
+ group2.addArgument(['--soup'], {action: 'storeTrue'});
+ group2.addArgument(['--nuts'], {action: 'storeFalse'});
+ usage = parser.formatUsage();
+ assert.equal(usage, 'usage: PROG [-h] (--foo | --bar) [--soup | --nuts]\n');
+ });
+ it('suppressed and single action groups', function () {
+ // adapted from test_argparse.py
+ var usage, group1, group2;
+ parser = new ArgumentParser({prog: 'PROG', debug: true});
+ group1 = parser.addMutuallyExclusiveGroup();
+ group1.addArgument(['--sup'], {help: '==SUPPRESS=='});
+ // should produce an empty group (), which is removed
+ group2 = parser.addMutuallyExclusiveGroup({required: true});
+ group2.addArgument(['--xxx'], {});
+ // single entry in a required group, remove group ()
+ usage = parser.formatUsage();
+ assert.equal(usage, 'usage: PROG [-h] --xxx XXX\n');
+ });
});
});

0 comments on commit a3f6aaf

Please sign in to comment.