STscript allow named arguments to be an array

- Use named args definition and "acceptsMultiple" to build arrays of values, if provided
- Add a debug warning if non-multiple named args are provided multiple times
This commit is contained in:
Wolfsblvt 2024-09-28 21:59:29 +02:00
parent c47e198664
commit 2444e9be43
2 changed files with 54 additions and 13 deletions

View File

@ -15,13 +15,13 @@ import { SlashCommandScope } from './SlashCommandScope.js';
* _abortController:SlashCommandAbortController,
* _debugController:SlashCommandDebugController,
* _hasUnnamedArgument:boolean,
* [id:string]:string|SlashCommandClosure,
* [id:string]:string|SlashCommandClosure|(string|SlashCommandClosure)[],
* }} NamedArguments
*/
/**
* Alternative object for local JSDocs, where you don't need existing pipe, scope, etc. arguments
* @typedef {{[id:string]:string|SlashCommandClosure}} NamedArgumentsCapture
* @typedef {{[id:string]:string|SlashCommandClosure|(string|SlashCommandClosure)[]}} NamedArgumentsCapture
*/
/**

View File

@ -2,6 +2,7 @@ import { substituteParams } from '../../script.js';
import { delay, escapeRegex, uuidv4 } from '../utils.js';
import { SlashCommand } from './SlashCommand.js';
import { SlashCommandAbortController } from './SlashCommandAbortController.js';
import { SlashCommandNamedArgument } from './SlashCommandArgument.js';
import { SlashCommandBreak } from './SlashCommandBreak.js';
import { SlashCommandBreakController } from './SlashCommandBreakController.js';
import { SlashCommandBreakPoint } from './SlashCommandBreakPoint.js';
@ -53,7 +54,7 @@ export class SlashCommandClosure {
*
* @param {string} text
* @param {SlashCommandScope} scope
* @returns
* @returns {string|SlashCommandClosure|(string|SlashCommandClosure)[]}
*/
substituteParams(text, scope = null) {
let isList = false;
@ -379,6 +380,52 @@ export class SlashCommandClosure {
* @param {import('./SlashCommand.js').NamedArguments} args
*/
async substituteNamedArguments(executor, args) {
/**
* Handles the assignment of named arguments, considering if they accept multiple values
* @param {string} name The name of the argument, as defined for the command execution
* @param {string|SlashCommandClosure|(string|SlashCommandClosure)[]} value The value to be assigned
*/
const assign = (name, value) => {
// If an array is supposed to be assigned, assign it one by one
if (Array.isArray(value)) {
for (const val of value) {
assign(name, val);
}
return;
}
const definition = executor.command.namedArgumentList.find(x => x.name == name);
// Prefer definition name if a valid named args defintion is found
name = definition?.name ?? name;
// Unescape named argument
if (value && typeof value == 'string') {
value = value
.replace(/\\\{/g, '{')
.replace(/\\\}/g, '}');
}
// If the named argument accepts multiple values, we have to make sure to build an array correctly
if (definition?.acceptsMultiple) {
if (args[name] !== undefined) {
// If there already is something for that named arg, make the value is an array and add to it
let currentValue = args[name];
if (!Array.isArray(currentValue)) {
currentValue = [currentValue];
}
currentValue.push(value);
args[name] = currentValue;
} else {
// If there is nothing in there, just assign it as singular value, until multiple values are found
args[name] = value;
}
} else {
args[name] !== undefined && console.debug(`Named argument assigned multiple times: ${name}`);
args[name] = value;
}
};
// substitute named arguments
for (const arg of executor.namedArgumentList) {
if (arg.value instanceof SlashCommandClosure) {
@ -390,19 +437,12 @@ export class SlashCommandClosure {
closure.debugController = this.debugController;
}
if (closure.executeNow) {
args[arg.name] = (await closure.execute())?.pipe;
assign(arg.name, (await closure.execute())?.pipe);
} else {
args[arg.name] = closure;
assign(arg.name, closure);
}
} else {
args[arg.name] = this.substituteParams(arg.value);
}
// unescape named argument
if (typeof args[arg.name] == 'string') {
args[arg.name] = args[arg.name]
?.replace(/\\\{/g, '{')
?.replace(/\\\}/g, '}')
;
assign(arg.name, this.substituteParams(arg.value));
}
}
}
@ -424,6 +464,7 @@ export class SlashCommandClosure {
} else {
value = [];
for (let i = 0; i < executor.unnamedArgumentList.length; i++) {
/** @type {string|SlashCommandClosure|(string|SlashCommandClosure)[]} */
let v = executor.unnamedArgumentList[i].value;
if (v instanceof SlashCommandClosure) {
/**@type {SlashCommandClosure}*/