Compare commits

..

No commits in common. "1d5ee332861b6b237eb238e5e5e8095972e262ec" and "6d921d6dec6f7dad9d084c11d315bc06c0a42767" have entirely different histories.

5 changed files with 18 additions and 37 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "@navy.gif/commandparser", "name": "@navy.gif/commandparser",
"version": "1.7.2", "version": "1.6.8",
"description": "Parser meant to parse commands and their options for discord bots", "description": "Parser meant to parse commands and their options for discord bots",
"author": "Navy.gif", "author": "Navy.gif",
"license": "MIT", "license": "MIT",

View File

@ -14,7 +14,7 @@ type ArgsResult = {
} }
type ParseResult = { type ParseResult = {
args: CommandOption[], args: ArgsResult,
globalFlags: ArgsResult, globalFlags: ArgsResult,
command: ICommand, command: ICommand,
subcommand: string | null, subcommand: string | null,
@ -172,7 +172,7 @@ class Parser extends EventEmitter
} }
const parseResult: ParseResult = { const parseResult: ParseResult = {
args: [], args: {},
globalFlags: {}, globalFlags: {},
command, command,
subcommand: null, subcommand: null,
@ -250,14 +250,14 @@ class Parser extends EventEmitter
return parseResult; return parseResult;
} }
async parseOptions<T extends CommandOption> (params: string[], options: T[], guild?: unknown): Promise<T[]> async parseOptions (params: string[], options: CommandOption[], guild?: unknown)
{ {
const args: T[] = []; const args: ArgsResult = {};
// Parse flags // Parse flags
const flags = await this.parseFlags<T>(params, options); const flags = await this.parseFlags(params, options);
for (const flag of flags) for (const flag of flags)
args.push(flag); args[flag.name] = flag;
this.debug(`Params after flag parsing "${params.length ? params.join('", "') : 'NONE'}"`); this.debug(`Params after flag parsing "${params.length ? params.join('", "') : 'NONE'}"`);
// Non-string options // Non-string options
@ -313,7 +313,7 @@ class Parser extends EventEmitter
continue; continue;
} }
args.push(cloned as T); args[cloned.name] = cloned;
// Clean up params for string parsing // Clean up params for string parsing
for (const r of removed) for (const r of removed)
params.splice(params.indexOf(r), 1, ''); params.splice(params.indexOf(r), 1, '');
@ -353,7 +353,7 @@ class Parser extends EventEmitter
break; break;
const cloned = strOpt.clone([ val ], this.resolver); const cloned = strOpt.clone([ val ], this.resolver);
await cloned.parse(guild); await cloned.parse(guild);
args.push(cloned as T); args[cloned.name] = cloned;
} }
// This part is obsolete now, I think, the string option checks the choice value // This part is obsolete now, I think, the string option checks the choice value
@ -371,14 +371,14 @@ class Parser extends EventEmitter
this.debug('Making sure required options were given.'); this.debug('Making sure required options were given.');
for (const req of options.filter((opt) => opt.required)) for (const req of options.filter((opt) => opt.required))
{ {
if (!args.some(a => a.name === req.name)) if (!args[req.name])
{ {
if (req.defaultValue === null || !this.allowDefaultOnRequired) if (req.defaultValue === null || !this.allowDefaultOnRequired)
throw new ParserError(`${req.name} is a required option`); throw new ParserError(`${req.name} is a required option`);
const opt = req.clone(); const opt = req.clone();
opt.value = req.defaultValue; opt.value = req.defaultValue;
args.push(opt as T); args[req.name] = opt;
} }
} }
@ -387,11 +387,11 @@ class Parser extends EventEmitter
return args; return args;
} }
async parseFlags<T extends CommandOption> (params: string[], options: T[], guild?: unknown, allowUnknown?: boolean): Promise<T[]> async parseFlags (params: string[], options: CommandOption[], guild?: unknown, allowUnknown?: boolean)
{ {
const flags = options.filter((opt) => opt.flag); const flags = options.filter((opt) => opt.flag);
let currentFlag = null; let currentFlag = null;
const parsed: T[] = []; const parsed = [];
this.debug(`${params.length} params to go through: "${params.join('", "')}"`); this.debug(`${params.length} params to go through: "${params.join('", "')}"`);
for (let index = 0; index < params.length;) for (let index = 0; index < params.length;)
{ {
@ -441,17 +441,6 @@ class Parser extends EventEmitter
} }
this.debug(`Matched flag: ${flag.name} with ${_flag}`); this.debug(`Matched flag: ${flag.name} with ${_flag}`);
if (flag.instances)
{
const count = parsed.reduce((prev, curr) =>
{
if (curr.name === flag.name)
prev++;
return prev;
}, 0);
if (count === flag.instances)
throw new ParserError(`Cannot have more than ${flag.instances} instances of option "${flag.name}"`);
}
// params.splice(index, 1, ''); // Replace with empty string as to not alter the length of the params array // params.splice(index, 1, ''); // Replace with empty string as to not alter the length of the params array
params.splice(index, 1); params.splice(index, 1);
if (aliased) if (aliased)
@ -459,7 +448,7 @@ class Parser extends EventEmitter
this.debug('Aliased'); this.debug('Aliased');
const clone = flag.clone([ _flag ], this.resolver); const clone = flag.clone([ _flag ], this.resolver);
clone.aliased = true; clone.aliased = true;
parsed.push(clone as T); parsed.push(clone);
currentFlag = null; currentFlag = null;
} }
else else
@ -467,7 +456,7 @@ class Parser extends EventEmitter
this.debug('Not aliased'); this.debug('Not aliased');
// eslint-disable-next-line no-undefined // eslint-disable-next-line no-undefined
currentFlag = flag.clone(undefined, this.resolver); currentFlag = flag.clone(undefined, this.resolver);
parsed.push(currentFlag as T); parsed.push(currentFlag);
} }
// index++; // index++;
} }
@ -488,7 +477,7 @@ class Parser extends EventEmitter
params.splice(params.indexOf(r), 1); params.splice(params.indexOf(r), 1);
} }
return parsed as T[]; return parsed;
} }
private debug (message: string) private debug (message: string)

View File

@ -14,7 +14,6 @@ class CommandOption implements ICommandOption
type: OptionType; type: OptionType;
minimum?: number; minimum?: number;
maximum?: number; maximum?: number;
instances: number;
flag: boolean; flag: boolean;
valueOptional: boolean; valueOptional: boolean;
defaultValue: boolean | number | string | null; defaultValue: boolean | number | string | null;
@ -81,9 +80,6 @@ class CommandOption implements ICommandOption
this.minimum = def.minimum; this.minimum = def.minimum;
this.maximum = def.maximum; this.maximum = def.maximum;
// Default to 1 to retain original behaviour
// Really only applies to flag type options, given that non-flags aren't parsed by their name, rather by their type and order
this.instances = def.instances ?? 1;
this.required = def.required || false; this.required = def.required || false;
} }

View File

@ -87,7 +87,6 @@ type CommandOptionDefinition = {
minimum?: number; minimum?: number;
maximum?: number; maximum?: number;
instances?: number
flag?: boolean; flag?: boolean;
valueOptional?: boolean; valueOptional?: boolean;
@ -110,8 +109,6 @@ interface ICommandOption {
type: OptionType; type: OptionType;
strict: boolean; strict: boolean;
// Number of times this option can be parsed, 0 being any
instances: number;
required: boolean; required: boolean;
minimum?: number; minimum?: number;

View File

@ -27,8 +27,7 @@ const commands = [
type: OptionType.INTEGER, type: OptionType.INTEGER,
defaultValue: 1, defaultValue: 1,
valueOptional: true, valueOptional: true,
required: true, required: true
instances: 2
}] }]
}] }]
}), }),
@ -80,7 +79,7 @@ const parser = new Parser({
allowIncompleteReturn: true allowIncompleteReturn: true
}); });
parser.on('debug', console.log); parser.on('debug', console.log);
console.log((await parser.parseMessage('create code -a 1 -a 6 -a 7'))); console.log((await parser.parseMessage('create code -a 1')));
console.log((await parser.parseMessage('create code --help'))); console.log((await parser.parseMessage('create code --help')));
console.log(await parser.parseMessage('create --help')); console.log(await parser.parseMessage('create --help'));
console.log((await parser.parseMessage('test sub --help'))); console.log((await parser.parseMessage('test sub --help')));