diff --git a/README.md b/README.md index aea048d..3741ca4 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,40 @@ -A command parser for Discord bots. Should work with any JS library. +A command parser initially made for quickly making discord bots, but works as a standalone parser too. -You're expected to implement a string -> abstraction resolver yourself and pass it to the parser. \ No newline at end of file +Your commands are expected to inherit from the Command class + +**Example usage** +```js + +const commands: Command[] = [ + new Command({ + name: 'ping', + options: [ + { + name: 'respond', // + type: OptionType.BOOLEAN, // Boolean type expects the parser to have some kind of string -> boolean resolver, see the resolver interface for which methods are expected + required: true, // Will throw error if not provided + defaultValue: true, // The value that will be given back if no value is given, or if option is required but not provided + flag: true // The parser will look for the option in the "--respond value" form + } + ] + }) +]; // Command definitions + +const parser = new Parser({commands, prefix: ''}); // Empty prefix +const parsed = await parser.parseMessage('ping --respond'); + +/** + * Parsed will be an object cotaining properties args, command, subcommand, and subcommandgroup + * the args property is an object of the given options mapped by their names, e.g. + * { + * respond: { + * ... properties, + * value: true + * } + * } + * +*/ + +``` + +Some of the option types have built-in parsers (e.g. numbers, strings), but others will require the resolver implementation, and in some cases CommandOption extensions. \ No newline at end of file diff --git a/src/Parser.ts b/src/Parser.ts index d1c0067..1acb48c 100644 --- a/src/Parser.ts +++ b/src/Parser.ts @@ -23,7 +23,8 @@ type ParserOptions = { commands: Iterable, prefix?: string, debug?: boolean, - resolver?: IResolver + resolver?: IResolver, + allowDefaultOnRequired?: boolean } type ParseOptions = { @@ -39,14 +40,12 @@ const flagReg = /(?:^| )(?(?:--[a-z0-9]{3,})|(?:-[a-z]{1,2}))(?:$| )/iu; class Parser extends EventEmitter { private commands: ExtendedMap; - private _debug = false; - prefix: string; - resolver?: IResolver; + allowDefaultOnRequired: boolean; - constructor ({ commands, prefix, debug = false, resolver }: ParserOptions) { + constructor ({ commands, prefix, debug = false, resolver, allowDefaultOnRequired }: ParserOptions) { super(); @@ -57,6 +56,7 @@ class Parser extends EventEmitter { this.resolver = resolver; this.prefix = prefix || ''; + this.allowDefaultOnRequired = allowDefaultOnRequired ?? true; } @@ -311,9 +311,16 @@ class Parser extends EventEmitter { // } this.debug(`Making sure required options were given.`); - for (const req of options.filter((opt) => opt.required)) - if (!args[req.name]) - throw new ParseError(`${req.name} is a required option`); + for (const req of options.filter((opt) => opt.required)) { + if (!args[req.name]) { + if (req.defaultValue === null || !this.allowDefaultOnRequired) + throw new ParseError(`${req.name} is a required option`); + + const opt = req.clone(); + opt.value = req.defaultValue; + args[req.name] = opt; + } + } if (strings.length) throw new ParseError(`Unrecognised option(s): "${strings.join('", "')}"`);