Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support combined boolean flags #18

Closed
wants to merge 8 commits into from
36 changes: 26 additions & 10 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ function arg(opts, {argv, permissive = false} = {}) {
throw new TypeError(`Argument key must start with '-' but found: '${key}'`);
}

if (key.length === 1) {
throw new Error(`Argument key must have a name; singular "-" keys are not allowed: ${key}`);
pacocoursey marked this conversation as resolved.
Show resolved Hide resolved
}

if (typeof opts[key] === 'string') {
aliases[key] = opts[key];
continue;
Expand All @@ -26,10 +30,14 @@ function arg(opts, {argv, permissive = false} = {}) {
throw new Error(`Type missing or not a function or valid array type: ${key}`);
pacocoursey marked this conversation as resolved.
Show resolved Hide resolved
}

if (key[1] !== '-' && key.length > 2) {
throw new Error(`Short argument keys (with a single hyphen) must have only one character: ${key}`);
pacocoursey marked this conversation as resolved.
Show resolved Hide resolved
}

handlers[key] = type;
}

for (let i = 0, len = argv.length; i < len; i++) {
for (let i = 0; i < argv.length; i++) {
const arg = argv[i];

if (arg.length < 2) {
Expand All @@ -51,21 +59,29 @@ function arg(opts, {argv, permissive = false} = {}) {
}

if (!(argName in handlers)) {
if (permissive) {
const shortArg = argName.substring(0, 2);
const flags = argName.substring(1);
if (shortArg in handlers && flags.length > 1) {
for (const char of flags) {
if (`-${char}` in handlers) {
argv.push(`-${char}`);
} else {
throw new Error(`Unkown or unexpected option: -${char}`);
pacocoursey marked this conversation as resolved.
Show resolved Hide resolved
}
}

continue;
} else if (permissive) {
result._.push(arg);
continue;
} else {
const err = new Error(`Unknown or unexpected option: ${originalArgName}`);
err.code = 'ARG_UNKNOWN_OPTION';
pacocoursey marked this conversation as resolved.
Show resolved Hide resolved
throw err;
throw new Error(`Unknown or unexpected option: ${originalArgName}`);
}
}

/* eslint-disable operator-linebreak */
const [type, isArray] = Array.isArray(handlers[argName])
? [handlers[argName][0], true]
: [handlers[argName], false];
/* eslint-enable operator-linebreak */
const [type, isArray] = Array.isArray(handlers[argName]) ?
[handlers[argName][0], true] :
Qix- marked this conversation as resolved.
Show resolved Hide resolved
[handlers[argName], false];

let value;
if (type === Boolean) {
Expand Down
25 changes: 25 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,3 +188,28 @@ test('ensure that all argument properties start with a hyphen', () => {
})
).to.throw(TypeError, 'Argument key must start with \'-\' but found: \'bar\'');
});

test('single hyphen cannot be key', () => {
const argv = ['--foo', '-'];
expect(() => (arg({'--foo': Boolean, '-': Boolean}, {argv})).to.throw('Argument key must have a name; singular "-" keys are not allowed: -'));
});

test('ensure single-hyphen properties are one character', () => {
const argv = ['-vv', '--foo'];
expect(() => (arg({'-vv': Boolean}, {argv, permissive: true})).to.throw('Single-hyphen properties must be one character: -vv'));
});

test('correctly parse repeating boolean flags', () => {
const argv = ['-vvvv', '-v', '--foo', '--foo'];
expect(arg({'-v': [Boolean], '--foo': Boolean}, {argv, permissive: true})).to.deep.equal({_: [], '-v': [true, true, true, true, true], '--foo': true});
});

test('expand combined boolean flags', () => {
const argv = ['-abc'];
expect(arg({'-a': Boolean, '-b': Boolean, '-c': Boolean}, {argv})).to.deep.equal({_: [], '-a': true, '-b': true, '-c': true});
});

test('combined boolean flags with boolean arrays', () => {
const argv = ['-abcddd', '-d'];
expect(arg({'-a': Boolean, '-b': Boolean, '-c': Boolean, '-d': [Boolean]}, {argv})).to.deep.equal({_: [], '-a': true, '-b': true, '-c': true, '-d': [true, true, true, true]});
});