♻ Move argument parsing into separate function
This commit is contained in:
parent
cb67bc6220
commit
20315cc64f
2 changed files with 70 additions and 56 deletions
60
src/index.ts
60
src/index.ts
|
@ -1,7 +1,7 @@
|
|||
import initState from './initState';
|
||||
import IOption from './IOption';
|
||||
import parseArgument from './parseArgument';
|
||||
import runPreParseHook from './runPreParseHook';
|
||||
import verifyAndStoreOptionValue from './verifyAndStoreOptionValue';
|
||||
|
||||
/**
|
||||
* Checks the command line arguments against the given specification, and returns the arguments as a JavaScript object, as well as a failure function that prints the usage instructions before terminating.
|
||||
|
@ -19,63 +19,11 @@ export default function parseArguments(
|
|||
|
||||
//Iterate through all command line arguments. When we have read both name and value, verify the argument for correctness.
|
||||
//Show error if a name has no value afterwards, or a value has no name in front of it.
|
||||
let option = '';
|
||||
for (const arg of args) {
|
||||
if (option === '') {
|
||||
/** We expect a name, must be one of:
|
||||
* - `--name value`
|
||||
* - `--name=value`
|
||||
* - `-n value`
|
||||
* - `-n=value`
|
||||
*/
|
||||
if (arg === '-' || arg === '--') {
|
||||
fail(`Empty option "-" or "--" is not supported.`);
|
||||
} else if (arg.startsWith('--')) { //long argument
|
||||
option = arg.substr(2);
|
||||
let value;
|
||||
//If there's a =, immediately read the value
|
||||
if (option.indexOf('=') !== -1) {
|
||||
[option, value] = option.split('=', 2);
|
||||
}
|
||||
//Check that argument name is valid
|
||||
if (spec[option] === undefined) {
|
||||
fail(`Unknown option "--${option}".`);
|
||||
}
|
||||
//If value was provided, check that value is correct and remove name for next loop iteration
|
||||
if (value !== undefined) {
|
||||
verifyAndStoreOptionValue({option, value, verify: spec[option].verify, message: spec[option].message, fail, outputArgs, requiredOptions});
|
||||
option = '';
|
||||
}
|
||||
} else if (arg.startsWith('-')) { //short argument
|
||||
option = arg.substr(1);
|
||||
let value;
|
||||
//If there's a =, immediately read the value
|
||||
if (option.indexOf('=') !== -1) {
|
||||
[option, value] = option.split('=', 2);
|
||||
}
|
||||
//Check that argument name is valid
|
||||
if (shortToLongLookup[option] === undefined) {
|
||||
fail(`Unknown short option "-${option}".`);
|
||||
}
|
||||
option = shortToLongLookup[option];
|
||||
//If value was provided, check that value is correct and remove name for next loop iteration
|
||||
if (value !== undefined) {
|
||||
verifyAndStoreOptionValue({option, value, verify: spec[option].verify, message: spec[option].message, fail, outputArgs, requiredOptions});
|
||||
option = '';
|
||||
}
|
||||
} else {
|
||||
fail(`Arguments must be preceded by an option but there was no option in front of "${arg}".`);
|
||||
}
|
||||
} else { //We expect a value, can be anything
|
||||
verifyAndStoreOptionValue({option, value: arg, verify: spec[option].verify, message: spec[option].message, fail, outputArgs, requiredOptions});
|
||||
option = '';
|
||||
}
|
||||
|
||||
}
|
||||
const lastOption = args.reduce(parseArgument.bind(null, { spec, fail, outputArgs, requiredOptions, shortToLongLookup }));
|
||||
|
||||
// argumentName must be cleared to '' after the value is read, so if it is not an empty string, the value was missing
|
||||
if (option !== '') {
|
||||
fail(`Option "${option}" was not followed by a value.`);
|
||||
if (lastOption !== '') {
|
||||
fail(`Option "${lastOption}" was not followed by a value.`);
|
||||
}
|
||||
|
||||
//check if any entry in requiredArguments was not set
|
||||
|
|
66
src/parseArgument.ts
Normal file
66
src/parseArgument.ts
Normal file
|
@ -0,0 +1,66 @@
|
|||
import IOption from './IOption';
|
||||
import verifyAndStoreOptionValue from './verifyAndStoreOptionValue';
|
||||
|
||||
export default function parseArgument(
|
||||
{ spec, fail, outputArgs, requiredOptions, shortToLongLookup }: {
|
||||
spec: { [key: string]: IOption },
|
||||
fail: (errorMessage: string) => void,
|
||||
outputArgs: { [key: string]: string },
|
||||
requiredOptions: { [key: string]: boolean },
|
||||
shortToLongLookup: { [key: string]: string },
|
||||
},
|
||||
option: string,
|
||||
arg: string,
|
||||
): string {
|
||||
if (option === '') {
|
||||
/** We expect a name, must be one of:
|
||||
* - `--name value`
|
||||
* - `--name=value`
|
||||
* - `-n value`
|
||||
* - `-n=value`
|
||||
*/
|
||||
if (arg === '-' || arg === '--') {
|
||||
fail(`Empty option "-" or "--" is not supported.`);
|
||||
} else if (arg.startsWith('--')) { //long argument
|
||||
option = arg.substr(2);
|
||||
let value;
|
||||
//If there's a =, immediately read the value
|
||||
if (option.indexOf('=') !== -1) {
|
||||
[option, value] = option.split('=', 2);
|
||||
}
|
||||
//Check that argument name is valid
|
||||
if (spec[option] === undefined) {
|
||||
fail(`Unknown option "--${option}".`);
|
||||
}
|
||||
//If value was provided, check that value is correct and remove name for next loop iteration
|
||||
if (value !== undefined) {
|
||||
verifyAndStoreOptionValue({option, value, verify: spec[option].verify, message: spec[option].message, fail, outputArgs, requiredOptions});
|
||||
option = '';
|
||||
}
|
||||
} else if (arg.startsWith('-')) { //short argument
|
||||
option = arg.substr(1);
|
||||
let value;
|
||||
//If there's a =, immediately read the value
|
||||
if (option.indexOf('=') !== -1) {
|
||||
[option, value] = option.split('=', 2);
|
||||
}
|
||||
//Check that argument name is valid
|
||||
if (shortToLongLookup[option] === undefined) {
|
||||
fail(`Unknown short option "-${option}".`);
|
||||
}
|
||||
option = shortToLongLookup[option];
|
||||
//If value was provided, check that value is correct and remove name for next loop iteration
|
||||
if (value !== undefined) {
|
||||
verifyAndStoreOptionValue({option, value, verify: spec[option].verify, message: spec[option].message, fail, outputArgs, requiredOptions});
|
||||
option = '';
|
||||
}
|
||||
} else {
|
||||
fail(`Arguments must be preceded by an option but there was no option in front of "${arg}".`);
|
||||
}
|
||||
} else { //We expect a value, can be anything
|
||||
verifyAndStoreOptionValue({option, value: arg, verify: spec[option].verify, message: spec[option].message, fail, outputArgs, requiredOptions});
|
||||
option = '';
|
||||
}
|
||||
|
||||
return option;
|
||||
}
|
Loading…
Reference in a new issue