Change: Move tests to a separate file, set up exporting from arg-parser.js

This commit is contained in:
n loewen 2023-08-26 21:20:12 -04:00
parent bd2a0c300d
commit 79c5473bf0
2 changed files with 76 additions and 67 deletions

View File

@ -5,28 +5,8 @@ const test = require('node:test');
// TODO:
// - building a structured output
// - testing
// - exporting as object/library
// Testing -- constructors
let cpuArguments = new Arguments();
cpuArguments.add(
new Arg({name: 'Filename', shortFlag: 'f', requiresValue: true}),
new Arg({name: 'Clock speed', shortFlag: 'c', longFlag: 'clock', requiresValue: true, optional: true}),
new Arg({name: 'Debug', shortFlag: 'd', longFlag: 'debug', optional: true}),
new Arg({name: 'Pretty-print display', shortFlag: 'p', longFlag: 'pretty', optional: true}),
new Arg({name: 'Single-step', shortFlag: 's', longFlag: 'step', optional: true}));
// Constructors
function Arguments(argumentsObject=[], helpText='') {
this.help = helpText;
this.args = argumentsObject;
Arguments.prototype.add = (...a) => a.forEach((x) => argumentsObject.push(x));
};
function Arg({
name = 'Flag',
shortFlag = null,
@ -41,55 +21,68 @@ function Arg({
};
// MODULE
function Arguments(argumentsObject=[], helpText='') {
this.help = helpText;
this.args = argumentsObject;
const argsRequiringValues = cpuArguments.args.filter((a) => a.requiresValue);
const requiredArgs = cpuArguments.args.filter((a) => !a.optional);
Arguments.prototype.add = (...a) => a.forEach((x) => argumentsObject.push(new Arg(x)));
let argv = process.argv.slice(2);
this.parse = function() {
const argsRequiringValues = this.args.filter((a) => a.requiresValue);
const requiredArgs = this.args.filter((a) => !a.optional);
// Split up grouped short flags
let argvSplit = [].concat(...argv.map((x) => {
if (x.startsWith('-') && !x.startsWith('--')) { // short flags
let arr = x.substring(1).split('');
arr = arr.map((y) => '-' + y);
return arr;
let argv = process.argv.slice(2);
// Split up grouped short flags
let argvSplit = [].concat(...argv.map((x) => {
if (x.startsWith('-') && !x.startsWith('--')) { // short flags
let arr = x.substring(1).split('');
arr = arr.map((y) => '-' + y);
return arr;
}
return x;
}));
// Check if all the required flags have been included
requiredArgs.forEach((a) => {
if (!argvSplit.includes('-'+a.flags.short) && !argvSplit.includes('-'+a.flags.long)) {
let long = (a.flags.long) ? `--${a.flags.long}, ` : '';
throw new Error(`${a.name} flag (-${a.flags.short}${long}) is required`);
}
});
// Validate...
argvSplit.forEach((av, index) => {
// Check for attempts to use --flags that don't exist
let valid = true;
if (av.startsWith('--')) {
valid = cpuArguments.args.filter((a) => a.flags.long === av.substring(2)).length > 0;
} else if (av.startsWith('-')) {
valid = cpuArguments.args.filter((a) => a.flags.short === av.substring(1)).length > 0;
}
if (!valid) { throw new Error(`There is no ${av} option`); }
// Check if it requires a value...
// and if it does, do a cursory check to see if one is likely to be there
let shouldCheckValue = argsRequiringValues.filter((a) => {
let noDash = av.substring(1);
return (a.flags.short === noDash || a.flags.long === noDash);
}).length > 0;
if (shouldCheckValue) {
let errorMessage = `Value required for ${av}`;
// If there's nothing after this flag, error;
// Or if the next item is a flag... error:
if (typeof argvSplit[index + 1] === 'undefined') { throw new Error(errorMessage); }
else if (argvSplit[index + 1].startsWith('-')) { throw new Error(errorMessage); };
}
// TODO return something useful
});
}
return x;
}));
}
// Check if all the required flags have been included
requiredArgs.forEach((a) => {
if (!argvSplit.includes('-'+a.flags.short) && !argvSplit.includes('-'+a.flags.long)) {
let long = (a.flags.long) ? `--${a.flags.long}, ` : '';
throw new Error(`${a.name} flag (-${a.flags.short}${long}) is required`);
}
});
// Validate...
argvSplit.forEach((av, index) => {
// Check for attempts to use --flags that don't exist
let valid = true;
if (av.startsWith('--')) {
valid = cpuArguments.args.filter((a) => a.flags.long === av.substring(2)).length > 0;
} else if (av.startsWith('-')) {
valid = cpuArguments.args.filter((a) => a.flags.short === av.substring(1)).length > 0;
}
if (!valid) { throw new Error(`There is no ${av} option`); }
// Check if it requires a value...
// and if it does, do a cursory check to see if one is likely to be there
let shouldCheckValue = argsRequiringValues.filter((a) => {
let noDash = av.substring(1);
return (a.flags.short === noDash || a.flags.long === noDash);
}).length > 0;
if (shouldCheckValue) {
let errorMessage = `Value required for ${av}`;
// If there's nothing after this flag, error;
// Or if the next item is a flag... error:
if (typeof argvSplit[index + 1] === 'undefined') { throw new Error(errorMessage); }
else if (argvSplit[index + 1].startsWith('-')) { throw new Error(errorMessage); };
}
});
module.exports = {
Arguments: Arguments,
}

16
tests.js Normal file
View File

@ -0,0 +1,16 @@
const argParser = require('./arg-parser.js')
// TODO...
console.log(argParser);
let cpuArguments = new argParser.Arguments();
cpuArguments.add(
{name: 'Filename', shortFlag: 'f', requiresValue: true},
{name: 'Clock speed', shortFlag: 'c', longFlag: 'clock', requiresValue: true, optional: true},
{name: 'Debug', shortFlag: 'd', longFlag: 'debug', optional: true},
{name: 'Pretty-print display', shortFlag: 'p', longFlag: 'pretty', optional: true},
{name: 'Single-step', shortFlag: 's', longFlag: 'step', optional: true});
console.log(cpuArguments); //.parse();
console.log(cpuArguments.parse()); //.parse();