Comparing version 15.5.1 to 16.0.0
const chalk = require('chalk') | ||
const process = require('./globals').process | ||
const console = require('./globals').console | ||
const Error = require('./globals').Error | ||
const { process, console, Error } = require('./src/globals') | ||
@@ -6,0 +4,0 @@ module.exports = function (error) { |
58
help.js
const chalk = require('chalk') | ||
const console = require('./globals').console | ||
const process = require('./globals').process | ||
const { console, process } = require('./src/globals') | ||
const { isNumber, addDashes, longest, spaces, quoteString } = require('./src/helpers') | ||
@@ -18,11 +18,10 @@ module.exports = function (name, description, definitions, commands = {}) { | ||
const definition = definitions[key] | ||
const k = definition.key != null ? definition.key : key | ||
if (Number.isInteger(Number(key))) { | ||
definition.signature = k | ||
if (isNumber(key)) { | ||
definition.signature = definition.key | ||
} else { | ||
definition.signature = (k.length === 1 ? '-' : '--') + k | ||
definition.signature = addDashes(definition.key) | ||
if (definition.aliases != null && definition.aliases.length) { | ||
definition.signature += ',' + definition.aliases.map((k) => (k.length === 1 ? '-' : '--') + k).join(',') | ||
definition.signature += ',' + definition.aliases.map((k) => addDashes(k)).join(',') | ||
} | ||
@@ -32,5 +31,5 @@ } | ||
const parameterKeys = Object.keys(definitions).filter((key) => Number.isInteger(Number(key))) | ||
const parameterKeys = Object.keys(definitions).filter((key) => isNumber(key)) | ||
const optionKeys = Object.keys(definitions).filter((key) => Number.isInteger(Number(key)) === false) | ||
const optionKeys = Object.keys(definitions).filter((key) => isNumber(key) === false) | ||
@@ -43,4 +42,7 @@ if (parameterKeys.length || optionKeys.length) { | ||
const definition = definitions[key] | ||
const valPart = definition.type !== Boolean | ||
? '=' + '<' + (definition.type ? definition.type.name : key) + '>' | ||
: '' | ||
return (definition.required !== true ? '[' : '') + definition.signature + (definition.type !== Boolean ? '=' + '<' + (definition.type ? definition.type.name : key) + '>' : '') + (definition.multiple === true ? '...' : '') + (definition.required !== true ? ']' : '') | ||
return wrapUsage(definition.signature + valPart, definition) | ||
})) | ||
@@ -53,3 +55,3 @@ } | ||
return (definition.required !== true ? '[' : '') + '<' + definition.signature + '>' + (definition.multiple === true ? '...' : '') + (definition.required !== true ? ']' : '') | ||
return wrapUsage('<' + definition.signature + '>', definition) | ||
})) | ||
@@ -80,11 +82,9 @@ } | ||
const longestParameter = parameterKeys.reduce((longest, key) => { | ||
const definition = definitions[key] | ||
const longestParameter = longest(parameterKeys.map((key) => { | ||
return definitions[key].signature | ||
})) | ||
return definition.signature.length > longest ? definition.signature.length : longest | ||
}, 0) | ||
parameterKeys.forEach((key) => { | ||
const definition = definitions[key] | ||
const description = [' '.repeat(longestParameter - definition.signature.length) + definition.signature] | ||
const description = [spaces(longestParameter - definition.signature.length) + definition.signature] | ||
@@ -96,3 +96,3 @@ if (definition.description) { | ||
if (definition.default) { | ||
description.push('[default: ' + (typeof definition.default === 'string' ? '"' : '') + definition.default + (typeof definition.default === 'string' ? '"' : '') + ']') | ||
description.push('[default: ' + quoteString(definition.default) + ']') | ||
} | ||
@@ -111,11 +111,9 @@ | ||
const longestOption = optionKeys.reduce((longest, key) => { | ||
const definition = definitions[key] | ||
const longestOption = longest(optionKeys.map((key) => { | ||
return definitions[key].signature | ||
})) + 1 | ||
return definition.signature.length > longest ? definition.signature.length : longest | ||
}, 0) + 1 | ||
optionKeys.forEach((key) => { | ||
const definition = definitions[key] | ||
const description = [' '.repeat(longestOption - definition.signature.length) + definition.signature] | ||
const description = [spaces(longestOption - definition.signature.length) + definition.signature] | ||
@@ -127,3 +125,3 @@ if (definition.description) { | ||
if (definition.default) { | ||
description.push('[default: ' + (typeof definition.default === 'string' ? '"' : '') + definition.default + (typeof definition.default === 'string' ? '"' : '') + ']') | ||
description.push('[default: ' + quoteString(definition.default) + ']') | ||
} | ||
@@ -138,5 +136,3 @@ | ||
if (commandKeys.length) { | ||
const longestCommand = commandKeys.reduce((longest, key) => { | ||
return key.length > longest ? key.length : longest | ||
}, 0) | ||
const longestCommand = longest(commandKeys) | ||
@@ -152,3 +148,3 @@ console.error('') | ||
console.error(key + (command.description ? ' ' + ' '.repeat(longestCommand - key.length) + chalk.gray(command.description != null ? command.description : '') : '')) | ||
console.error(key + (command.description ? ' ' + spaces(longestCommand - key.length) + chalk.gray(command.description != null ? command.description : '') : '')) | ||
}) | ||
@@ -159,1 +155,5 @@ } | ||
} | ||
function wrapUsage (usage, {required, multiple}) { | ||
return (required !== true ? '[' : '') + usage + (multiple === true ? '...' : '') + (required !== true ? ']' : '') | ||
} |
28
main.js
@@ -68,8 +68,32 @@ const parse = require('./parse') | ||
function option (key, definition) { | ||
definitions[key] = definition | ||
definitions[key] = getDefinition(key, definition) | ||
} | ||
function parameter (key, definition) { | ||
definitions[i++] = Object.assign(definition, {key}) | ||
definitions[i++] = getDefinition(key, definition) | ||
} | ||
function getDefinition (key, definition) { | ||
definition = Object.assign(definition, {key}) | ||
if (definition.default) { | ||
if (definition.multiple && !Array.isArray(definition.default)) { | ||
throw new Error('the default of ' + key + ' should be an array') | ||
} | ||
if (!definition.multiple && Array.isArray(definition.default)) { | ||
throw new Error('the default of ' + key + ' should not be an array') | ||
} | ||
} | ||
if (definition.type != null && definition.type === Boolean) { | ||
if (definition.default != null) { | ||
if (definition.default !== true) { | ||
throw new Error('the default of ' + key + ' should not be true') | ||
} | ||
} | ||
} | ||
return definition | ||
} | ||
} |
{ | ||
"name": "sergeant", | ||
"version": "15.5.1", | ||
"version": "16.0.0", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "main": "main.js", |
41
parse.js
const chalk = require('chalk') | ||
const console = require('./globals').console | ||
const process = require('./globals').process | ||
const { console, process } = require('./src/globals') | ||
const { isNumber, addDashes, getDefault } = require('./src/helpers') | ||
@@ -15,6 +15,2 @@ module.exports = function (argv, definitions) { | ||
if (definition.key == null) { | ||
definition.key = key | ||
} | ||
const split = definition.key.split('-') | ||
@@ -59,8 +55,9 @@ | ||
const toBeDeleted = [] | ||
const optionKeys = Object.keys(definitions).filter((key) => Number.isInteger(Number(key)) === false) | ||
const optionKeys = Object.keys(definitions).filter((key) => isNumber(key) === false) | ||
for (let i = 0; i < argv.length; i++) { | ||
optionKeys.forEach((key) => { | ||
const search = key.length === 1 ? '-' + key : '--' + key | ||
const search = addDashes(key) | ||
const definition = definitions[key] | ||
const property = definition.property | ||
let vals = [] | ||
@@ -86,3 +83,3 @@ | ||
} else { | ||
throw new Error((definition.key.length === 1 ? '-' : '--') + definition.key + ' is a boolean and does not accept a value') | ||
throw new Error(addDashes(definition.key) + ' is a boolean and does not accept a value') | ||
} | ||
@@ -97,5 +94,7 @@ } | ||
if (definition.multiple === true) { | ||
args[definition.property] = args[definition.property] != null ? args[definition.property].concat(vals) : vals | ||
args[property] = args[property] != null ? args[property].concat(vals) : vals | ||
} else if (args[property] != null) { | ||
throw new Error(addDashes(definition.key) + ' does not accept multiple values') | ||
} else { | ||
args[definition.property] = vals.pop() | ||
args[property] = vals.pop() | ||
} | ||
@@ -108,10 +107,11 @@ } | ||
const definition = definitions[key] | ||
const property = definition.property | ||
if (args[definition.property] == null) { | ||
if (args[property] == null) { | ||
if (definition.default != null) { | ||
args[definition.property] = definition.default | ||
args[property] = getDefault(definition) | ||
} | ||
if (definition.required === true && args['help'] !== true) { | ||
throw new Error((definition.key.length === 1 ? '-' : '--') + definitions[key].key + ' is required') | ||
throw new Error(addDashes(definition.key) + ' is required') | ||
} | ||
@@ -137,3 +137,3 @@ } | ||
const parameterKeys = Object.keys(definitions).filter((key) => Number.isInteger(Number(key))) | ||
const parameterKeys = Object.keys(definitions).filter((key) => isNumber(key)) | ||
const hasMultiple = parameterKeys.filter((key) => definitions[key].multiple).length > 0 | ||
@@ -147,2 +147,3 @@ | ||
const definition = definitions[key] | ||
const property = definition.property | ||
const remainingKeys = parameterKeys.length - 1 - key | ||
@@ -152,3 +153,3 @@ | ||
if (definition.default != null) { | ||
args[definition.property] = definition.default | ||
args[property] = getDefault(definition) | ||
} | ||
@@ -160,11 +161,11 @@ | ||
} else if (definition.multiple === true) { | ||
args[definition.property] = remainder.splice(0, remainder.length - remainingKeys) | ||
args[property] = remainder.splice(0, remainder.length - remainingKeys) | ||
if (definition.type) { | ||
args[definition.property] = args[definition.property].map((v) => definition.type(v)) | ||
args[property] = args[property].map((v) => definition.type(v)) | ||
} | ||
} else if (definition.type) { | ||
args[definition.property] = definition.type(remainder.shift()) | ||
args[property] = definition.type(remainder.shift()) | ||
} else { | ||
args[definition.property] = remainder.shift() | ||
args[property] = remainder.shift() | ||
} | ||
@@ -171,0 +172,0 @@ }) |
111
test.js
@@ -13,3 +13,3 @@ const test = require('tape') | ||
t.plan(15) | ||
t.plan(16) | ||
@@ -44,2 +44,3 @@ // test dashdash and parameter | ||
'aa-a': { | ||
key: 'aa-a', | ||
type: Boolean, | ||
@@ -53,2 +54,3 @@ aliases: ['a'] | ||
'aa-a': { | ||
key: 'aa-a', | ||
aliases: ['a'] | ||
@@ -61,5 +63,7 @@ } | ||
'aa-a': { | ||
key: 'aa-a', | ||
aliases: ['a'] | ||
}, | ||
b: { | ||
key: 'b', | ||
type: Boolean | ||
@@ -72,2 +76,3 @@ } | ||
'aa-a': { | ||
key: 'aa-a', | ||
type: Boolean, | ||
@@ -77,2 +82,3 @@ aliases: ['a'] | ||
b: { | ||
key: 'b', | ||
type: Boolean | ||
@@ -85,2 +91,3 @@ } | ||
'aa-a': { | ||
key: 'aa-a', | ||
multiple: true, | ||
@@ -92,5 +99,19 @@ aliases: ['a'] | ||
// test non-empty default | ||
t.deepEquals({aaA: ['', ' ']}, parse(['-a'], { | ||
'aa-a': { | ||
key: 'aa-a', | ||
aliases: ['a'], | ||
type: String, | ||
multiple: true, | ||
default: ['', ' '] | ||
} | ||
})) | ||
// test non-empty default | ||
t.deepEquals({aaA: ''}, parse(['-a'], { | ||
'aa-a': { | ||
key: 'aa-a', | ||
aliases: ['a'], | ||
type: String, | ||
multiple: true, | ||
default: '' | ||
@@ -103,2 +124,3 @@ } | ||
'aa-a': { | ||
key: 'aa-a', | ||
aliases: ['a'], | ||
@@ -112,4 +134,6 @@ default: 'abc' | ||
'0': { | ||
key: '0' | ||
}, | ||
'1': { | ||
key: '1', | ||
default: 'yes' | ||
@@ -189,3 +213,3 @@ } | ||
mockery.registerMock('./globals', globals) | ||
mockery.registerMock('./src/globals', globals) | ||
@@ -199,2 +223,3 @@ const parse = require('./parse') | ||
a: { | ||
key: 'a', | ||
type: Boolean | ||
@@ -207,2 +232,3 @@ } | ||
aaa: { | ||
key: 'aaa', | ||
type: Boolean | ||
@@ -221,2 +247,3 @@ } | ||
a: { | ||
key: 'a', | ||
required: true | ||
@@ -229,2 +256,3 @@ } | ||
aaa: { | ||
key: 'aaa', | ||
required: true | ||
@@ -234,2 +262,10 @@ } | ||
// test non multiple multiple | ||
parse(['--aaa=123', '--aaa=456'], { | ||
aaa: { | ||
type: Number, | ||
key: 'aaa' | ||
} | ||
}) | ||
// test required parameter | ||
@@ -255,5 +291,6 @@ parse([], { | ||
chalk.red('--aaa is required'), | ||
chalk.red('--aaa does not accept multiple values'), | ||
chalk.red('test is required'), | ||
chalk.red('too many arguments') | ||
].join('\n'), messages.join('\n')) | ||
], messages) | ||
@@ -279,3 +316,3 @@ mockery.disable() | ||
mockery.registerMock('./globals', globals) | ||
mockery.registerMock('./src/globals', globals) | ||
@@ -287,3 +324,3 @@ const help = require('./help') | ||
key: 'p0', | ||
multiple: true, | ||
description: 'the description', | ||
required: true | ||
@@ -293,5 +330,7 @@ }, | ||
key: 'p1', | ||
default: 'a default' | ||
multiple: true, | ||
default: ['a', 'b'] | ||
}, | ||
'aaa': { | ||
key: 'aaa', | ||
aliases: ['aa', 'a'], | ||
@@ -303,4 +342,6 @@ type: Boolean, | ||
'b': { | ||
key: 'b', | ||
type: Number, | ||
description: 'a Number' | ||
description: 'a Number', | ||
default: 100 | ||
} | ||
@@ -324,2 +365,3 @@ }) | ||
'aaa': { | ||
key: 'aaa', | ||
aliases: ['aa', 'a'], | ||
@@ -340,8 +382,8 @@ type: Boolean, | ||
'', | ||
chalk.green('Usage:') + ' test-command [--aaa,--aa,-a...] [-b=<Number>] <p0>... [<p1>]', | ||
chalk.green('Usage:') + ' test-command [--aaa,--aa,-a...] [-b=<Number>] <p0> [<p1>...]', | ||
'', | ||
chalk.green('Parameters:'), | ||
'', | ||
'p0', | ||
'p1 ' + chalk.gray('[default: "a default"]'), | ||
'p0 ' + chalk.gray('the description'), | ||
'p1 ' + '[default: "a", "b"]', | ||
'', | ||
@@ -351,3 +393,3 @@ chalk.green('Options:'), | ||
' --aaa,--aa,-a ' + chalk.gray('a Boolean'), | ||
' -b ' + chalk.gray('a Number'), | ||
' -b ' + chalk.gray('a Number') + ' [default: 100]', | ||
'', | ||
@@ -383,3 +425,3 @@ '', | ||
'' | ||
].join('\n'), messages.join('\n')) | ||
], messages) | ||
@@ -409,3 +451,3 @@ mockery.disable() | ||
mockery.registerMock('./globals', globals) | ||
mockery.registerMock('./src/globals', globals) | ||
@@ -427,5 +469,5 @@ const error = require('./error') | ||
chalk.gray('at thing ') + '(file.js:123:45)', | ||
'at another', | ||
chalk.gray('at another'), | ||
chalk.red('testing errors') | ||
].join('\n'), messages.join('\n')) | ||
], messages) | ||
@@ -453,5 +495,7 @@ mockery.disable() | ||
bbb: { | ||
key: 'bbb', | ||
testing: true | ||
}, | ||
help: { | ||
key: 'help', | ||
aliases: [ 'h' ], | ||
@@ -511,5 +555,7 @@ description: 'get help', | ||
bbb: { | ||
key: 'bbb', | ||
testing: true | ||
}, | ||
help: { | ||
key: 'help', | ||
aliases: [ 'h' ], | ||
@@ -602,2 +648,37 @@ description: 'get help', | ||
test('test ./command - api errors', function (t) { | ||
const command = require('./main') | ||
t.plan(3) | ||
t.throws(() => command('test-command', function ({option}) { | ||
option('a', { | ||
multiple: true, | ||
default: 'a' | ||
}) | ||
return function () { | ||
} | ||
}), /the default of a should be an array/) | ||
t.throws(() => command('test-command', function ({option}) { | ||
option('a', { | ||
default: ['a'] | ||
}) | ||
return function () { | ||
} | ||
}), /the default of a should not be an array/) | ||
t.throws(() => command('test-command', function ({option}) { | ||
option('a', { | ||
type: Boolean, | ||
default: false | ||
}) | ||
return function () { | ||
} | ||
}), /the default of a should not be true/) | ||
}) | ||
test('test ./command - sub commands', function (t) { | ||
@@ -604,0 +685,0 @@ mockery.enable(mockerySettings) |
29839
10
931