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

2444e9be43fe2824423716e9ae5c9a34174d70c0

Wolfsblvt <wolfsblvt@gmail.com>

2 files changed, +54 -13Ignore whitespace
public/scripts/slash-commands/SlashCommand.js+2 -2
@@ -15,13 +15,13 @@ import { SlashCommandScope } from './SlashCommandScope.js';
15 * _abortController:SlashCommandAbortController,15 * _abortController:SlashCommandAbortController,
16 * _debugController:SlashCommandDebugController,16 * _debugController:SlashCommandDebugController,
17 * _hasUnnamedArgument:boolean,17 * _hasUnnamedArgument:boolean,
18 * [id:string]:string|SlashCommandClosure,18 * [id:string]:string|SlashCommandClosure|(string|SlashCommandClosure)[],
19 * }} NamedArguments19 * }} NamedArguments
20 */20 */
2121
22/**22/**
23 * Alternative object for local JSDocs, where you don't need existing pipe, scope, etc. arguments23 * Alternative object for local JSDocs, where you don't need existing pipe, scope, etc. arguments
24 * @typedef {{[id:string]:string|SlashCommandClosure}} NamedArgumentsCapture24 * @typedef {{[id:string]:string|SlashCommandClosure|(string|SlashCommandClosure)[]}} NamedArgumentsCapture
25 */25 */
2626
27/**27/**
public/scripts/slash-commands/SlashCommandClosure.js+52 -11
@@ -2,6 +2,7 @@ import { substituteParams } from '../../script.js';
2import { delay, escapeRegex, uuidv4 } from '../utils.js';2import { delay, escapeRegex, uuidv4 } from '../utils.js';
3import { SlashCommand } from './SlashCommand.js';3import { SlashCommand } from './SlashCommand.js';
4import { SlashCommandAbortController } from './SlashCommandAbortController.js';4import { SlashCommandAbortController } from './SlashCommandAbortController.js';
5import { SlashCommandNamedArgument } from './SlashCommandArgument.js';
5import { SlashCommandBreak } from './SlashCommandBreak.js';6import { SlashCommandBreak } from './SlashCommandBreak.js';
6import { SlashCommandBreakController } from './SlashCommandBreakController.js';7import { SlashCommandBreakController } from './SlashCommandBreakController.js';
7import { SlashCommandBreakPoint } from './SlashCommandBreakPoint.js';8import { SlashCommandBreakPoint } from './SlashCommandBreakPoint.js';
@@ -53,7 +54,7 @@ export class SlashCommandClosure {
53 *54 *
54 * @param {string} text55 * @param {string} text
55 * @param {SlashCommandScope} scope56 * @param {SlashCommandScope} scope
56 * @returns57 * @returns {string|SlashCommandClosure|(string|SlashCommandClosure)[]}
57 */58 */
58 substituteParams(text, scope = null) {59 substituteParams(text, scope = null) {
59 let isList = false;60 let isList = false;
@@ -379,6 +380,52 @@ export class SlashCommandClosure {
379 * @param {import('./SlashCommand.js').NamedArguments} args380 * @param {import('./SlashCommand.js').NamedArguments} args
380 */381 */
381 async substituteNamedArguments(executor, args) {382 async substituteNamedArguments(executor, args) {
383 /**
384 * Handles the assignment of named arguments, considering if they accept multiple values
385 * @param {string} name The name of the argument, as defined for the command execution
386 * @param {string|SlashCommandClosure|(string|SlashCommandClosure)[]} value The value to be assigned
387 */
388 const assign = (name, value) => {
389 // If an array is supposed to be assigned, assign it one by one
390 if (Array.isArray(value)) {
391 for (const val of value) {
392 assign(name, val);
393 }
394 return;
395 }
396
397 const definition = executor.command.namedArgumentList.find(x => x.name == name);
398
399 // Prefer definition name if a valid named args defintion is found
400 name = definition?.name ?? name;
401
402 // Unescape named argument
403 if (value && typeof value == 'string') {
404 value = value
405 .replace(/\\\{/g, '{')
406 .replace(/\\\}/g, '}');
407 }
408
409 // If the named argument accepts multiple values, we have to make sure to build an array correctly
410 if (definition?.acceptsMultiple) {
411 if (args[name] !== undefined) {
412 // If there already is something for that named arg, make the value is an array and add to it
413 let currentValue = args[name];
414 if (!Array.isArray(currentValue)) {
415 currentValue = [currentValue];
416 }
417 currentValue.push(value);
418 args[name] = currentValue;
419 } else {
420 // If there is nothing in there, just assign it as singular value, until multiple values are found
421 args[name] = value;
422 }
423 } else {
424 args[name] !== undefined && console.debug(`Named argument assigned multiple times: ${name}`);
425 args[name] = value;
426 }
427 };
428
382 // substitute named arguments429 // substitute named arguments
383 for (const arg of executor.namedArgumentList) {430 for (const arg of executor.namedArgumentList) {
384 if (arg.value instanceof SlashCommandClosure) {431 if (arg.value instanceof SlashCommandClosure) {
@@ -390,19 +437,12 @@ export class SlashCommandClosure {
390 closure.debugController = this.debugController;437 closure.debugController = this.debugController;
391 }438 }
392 if (closure.executeNow) {439 if (closure.executeNow) {
393 args[arg.name] = (await closure.execute())?.pipe;440 assign(arg.name, (await closure.execute())?.pipe);
394 } else {441 } else {
395 args[arg.name] = closure;442 assign(arg.name, closure);
396 }443 }
397 } else {444 } else {
398 args[arg.name] = this.substituteParams(arg.value);445 assign(arg.name, this.substituteParams(arg.value));
399 }
400 // unescape named argument
401 if (typeof args[arg.name] == 'string') {
402 args[arg.name] = args[arg.name]
403 ?.replace(/\\\{/g, '{')
404 ?.replace(/\\\}/g, '}')
405 ;
406 }446 }
407 }447 }
408 }448 }
@@ -424,6 +464,7 @@ export class SlashCommandClosure {
424 } else {464 } else {
425 value = [];465 value = [];
426 for (let i = 0; i < executor.unnamedArgumentList.length; i++) {466 for (let i = 0; i < executor.unnamedArgumentList.length; i++) {
467 /** @type {string|SlashCommandClosure|(string|SlashCommandClosure)[]} */
427 let v = executor.unnamedArgumentList[i].value;468 let v = executor.unnamedArgumentList[i].value;
428 if (v instanceof SlashCommandClosure) {469 if (v instanceof SlashCommandClosure) {
429 /**@type {SlashCommandClosure}*/470 /**@type {SlashCommandClosure}*/