Merge pull request #2270 from LenAnderson/more-subcommand-shenanigans
More subcommand shenanigans
This commit is contained in:
commit
b32330df0f
|
@ -2708,7 +2708,7 @@ const clearCommandProgressDebounced = debounce(clearCommandProgress);
|
||||||
* @prop {boolean} [handleParserErrors] (true) Whether to handle parser errors (show toast on error) or throw.
|
* @prop {boolean} [handleParserErrors] (true) Whether to handle parser errors (show toast on error) or throw.
|
||||||
* @prop {SlashCommandScope} [scope] (null) The scope to be used when executing the commands.
|
* @prop {SlashCommandScope} [scope] (null) The scope to be used when executing the commands.
|
||||||
* @prop {boolean} [handleExecutionErrors] (false) Whether to handle execution errors (show toast on error) or throw
|
* @prop {boolean} [handleExecutionErrors] (false) Whether to handle execution errors (show toast on error) or throw
|
||||||
* @prop {PARSER_FLAG[]} [parserFlags] (null) Parser flags to apply
|
* @prop {{[id:PARSER_FLAG]:boolean}} [parserFlags] (null) Parser flags to apply
|
||||||
* @prop {SlashCommandAbortController} [abortController] (null) Controller used to abort or pause command execution
|
* @prop {SlashCommandAbortController} [abortController] (null) Controller used to abort or pause command execution
|
||||||
* @prop {(done:number, total:number)=>void} [onProgress] (null) Callback to handle progress events
|
* @prop {(done:number, total:number)=>void} [onProgress] (null) Callback to handle progress events
|
||||||
*/
|
*/
|
||||||
|
@ -2716,7 +2716,7 @@ const clearCommandProgressDebounced = debounce(clearCommandProgress);
|
||||||
/**
|
/**
|
||||||
* @typedef ExecuteSlashCommandsOnChatInputOptions
|
* @typedef ExecuteSlashCommandsOnChatInputOptions
|
||||||
* @prop {SlashCommandScope} [scope] (null) The scope to be used when executing the commands.
|
* @prop {SlashCommandScope} [scope] (null) The scope to be used when executing the commands.
|
||||||
* @prop {PARSER_FLAG[]} [parserFlags] (null) Parser flags to apply
|
* @prop {{[id:PARSER_FLAG]:boolean}} [parserFlags] (null) Parser flags to apply
|
||||||
* @prop {boolean} [clearChatInput] (false) Whether to clear the chat input textarea
|
* @prop {boolean} [clearChatInput] (false) Whether to clear the chat input textarea
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -2834,6 +2834,7 @@ async function executeSlashCommandsWithOptions(text, options = {}) {
|
||||||
const result = await closure.execute();
|
const result = await closure.execute();
|
||||||
if (result.isAborted && !result.isQuietlyAborted) {
|
if (result.isAborted && !result.isQuietlyAborted) {
|
||||||
toastr.warning(result.abortReason, 'Command execution aborted');
|
toastr.warning(result.abortReason, 'Command execution aborted');
|
||||||
|
closure.abortController.signal.isQuiet = true;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { SlashCommandScope } from './SlashCommandScope.js';
|
||||||
* _scope:SlashCommandScope,
|
* _scope:SlashCommandScope,
|
||||||
* _parserFlags:{[id:PARSER_FLAG]:boolean},
|
* _parserFlags:{[id:PARSER_FLAG]:boolean},
|
||||||
* _abortController:SlashCommandAbortController,
|
* _abortController:SlashCommandAbortController,
|
||||||
* [id:string]:string,
|
* [id:string]:string|SlashCommandClosure,
|
||||||
* }} NamedArguments
|
* }} NamedArguments
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -224,6 +224,15 @@ export class SlashCommandClosure {
|
||||||
?.replace(/\\\{/g, '{')
|
?.replace(/\\\{/g, '{')
|
||||||
?.replace(/\\\}/g, '}')
|
?.replace(/\\\}/g, '}')
|
||||||
;
|
;
|
||||||
|
} else if (Array.isArray(value)) {
|
||||||
|
value = value.map(v=>{
|
||||||
|
if (typeof v == 'string') {
|
||||||
|
return v
|
||||||
|
?.replace(/\\\{/g, '{')
|
||||||
|
?.replace(/\\\}/g, '}');
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let abortResult = await this.testAbortController();
|
let abortResult = await this.testAbortController();
|
||||||
|
|
|
@ -114,7 +114,6 @@ export class SlashCommandParser {
|
||||||
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
//TODO should not be re-registered from every instance
|
|
||||||
// add dummy commands for help strings / autocomplete
|
// add dummy commands for help strings / autocomplete
|
||||||
if (!Object.keys(this.commands).includes('parser-flag')) {
|
if (!Object.keys(this.commands).includes('parser-flag')) {
|
||||||
const help = {};
|
const help = {};
|
||||||
|
|
|
@ -316,14 +316,21 @@ function listVariablesCallback() {
|
||||||
sendSystemMessage(system_message_types.GENERIC, htmlMessage);
|
sendSystemMessage(system_message_types.GENERIC, htmlMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function whileCallback(args, command) {
|
/**
|
||||||
|
*
|
||||||
|
* @param {import('./slash-commands/SlashCommand.js').NamedArguments} args
|
||||||
|
* @param {(string|SlashCommandClosure)[]} value
|
||||||
|
*/
|
||||||
|
async function whileCallback(args, value) {
|
||||||
const isGuardOff = isFalseBoolean(args.guard);
|
const isGuardOff = isFalseBoolean(args.guard);
|
||||||
const iterations = isGuardOff ? Number.MAX_SAFE_INTEGER : MAX_LOOPS;
|
const iterations = isGuardOff ? Number.MAX_SAFE_INTEGER : MAX_LOOPS;
|
||||||
if (command) {
|
/**@type {string|SlashCommandClosure} */
|
||||||
if (command[0] instanceof SlashCommandClosure) {
|
let command;
|
||||||
command = command[0];
|
if (value) {
|
||||||
|
if (value[0] instanceof SlashCommandClosure) {
|
||||||
|
command = value[0];
|
||||||
} else {
|
} else {
|
||||||
command = command.join(' ');
|
command = value.join(' ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,11 +345,7 @@ async function whileCallback(args, command) {
|
||||||
} else {
|
} else {
|
||||||
commandResult = await executeSubCommands(command, args._scope, args._parserFlags, args._abortController);
|
commandResult = await executeSubCommands(command, args._scope, args._parserFlags, args._abortController);
|
||||||
}
|
}
|
||||||
|
if (commandResult.isAborted) break;
|
||||||
if (commandResult.isAborted) {
|
|
||||||
args._abortController.abort(commandResult.abortReason, true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -385,34 +388,43 @@ async function timesCallback(args, value) {
|
||||||
result = await command.execute();
|
result = await command.execute();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result = await executeSubCommands(command.replace(/\{\{timesIndex\}\}/g, i.toString()), args._scope, args._parserFlags);
|
result = await executeSubCommands(command.replace(/\{\{timesIndex\}\}/g, i.toString()), args._scope, args._parserFlags, args._abortController);
|
||||||
if (result.isAborted) {
|
|
||||||
args._abortController.abort(result.abortReason, true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (result.isAborted) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result?.pipe ?? '';
|
return result?.pipe ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
async function ifCallback(args, command) {
|
/**
|
||||||
|
*
|
||||||
|
* @param {import('./slash-commands/SlashCommand.js').NamedArguments} args
|
||||||
|
* @param {(string|SlashCommandClosure)[]} value
|
||||||
|
*/
|
||||||
|
async function ifCallback(args, value) {
|
||||||
const { a, b, rule } = parseBooleanOperands(args);
|
const { a, b, rule } = parseBooleanOperands(args);
|
||||||
const result = evalBoolean(rule, a, b);
|
const result = evalBoolean(rule, a, b);
|
||||||
|
|
||||||
|
/**@type {string|SlashCommandClosure} */
|
||||||
|
let command;
|
||||||
|
if (value) {
|
||||||
|
if (value[0] instanceof SlashCommandClosure) {
|
||||||
|
command = value[0];
|
||||||
|
} else {
|
||||||
|
command = value.join(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let commandResult;
|
let commandResult;
|
||||||
if (result && command) {
|
if (result && command) {
|
||||||
if (command instanceof SlashCommandClosure) return (await command.execute()).pipe;
|
if (command instanceof SlashCommandClosure) return (await command.execute()).pipe;
|
||||||
commandResult = await executeSubCommands(command, args._scope, args._parserFlags);
|
commandResult = await executeSubCommands(command, args._scope, args._parserFlags, args._abortController);
|
||||||
} else if (!result && args.else && ((typeof args.else === 'string' && args.else !== '') || args.else instanceof SlashCommandClosure)) {
|
} else if (!result && args.else && ((typeof args.else === 'string' && args.else !== '') || args.else instanceof SlashCommandClosure)) {
|
||||||
if (args.else instanceof SlashCommandClosure) return (await args.else.execute(args._scope)).pipe;
|
if (args.else instanceof SlashCommandClosure) return (await args.else.execute()).pipe;
|
||||||
commandResult = await executeSubCommands(args.else, args._scope, args._parserFlags);
|
commandResult = await executeSubCommands(args.else, args._scope, args._parserFlags, args._abortController);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (commandResult) {
|
if (commandResult) {
|
||||||
if (commandResult.isAborted) {
|
|
||||||
args._abortController.abort(commandResult.abortReason, true);
|
|
||||||
}
|
|
||||||
return commandResult.pipe;
|
return commandResult.pipe;
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
|
@ -558,7 +570,7 @@ function evalBoolean(rule, a, b) {
|
||||||
* Executes a slash command from a string (may be enclosed in quotes) and returns the result.
|
* Executes a slash command from a string (may be enclosed in quotes) and returns the result.
|
||||||
* @param {string} command Command to execute. May contain escaped macro and batch separators.
|
* @param {string} command Command to execute. May contain escaped macro and batch separators.
|
||||||
* @param {SlashCommandScope} [scope] The scope to use.
|
* @param {SlashCommandScope} [scope] The scope to use.
|
||||||
* @param {PARSER_FLAG[]} [parserFlags] The parser flags to use.
|
* @param {{[id:PARSER_FLAG]:boolean}} [parserFlags] The parser flags to use.
|
||||||
* @param {SlashCommandAbortController} [abortController] The abort controller to use.
|
* @param {SlashCommandAbortController} [abortController] The abort controller to use.
|
||||||
* @returns {Promise<SlashCommandClosureResult>} Closure execution result
|
* @returns {Promise<SlashCommandClosureResult>} Closure execution result
|
||||||
*/
|
*/
|
||||||
|
@ -1117,6 +1129,7 @@ export function registerVariableCommands() {
|
||||||
'command to execute if true', [ARGUMENT_TYPE.CLOSURE, ARGUMENT_TYPE.SUBCOMMAND], true,
|
'command to execute if true', [ARGUMENT_TYPE.CLOSURE, ARGUMENT_TYPE.SUBCOMMAND], true,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
splitUnnamedArgument: true,
|
||||||
helpString: `
|
helpString: `
|
||||||
<div>
|
<div>
|
||||||
Compares the value of the left operand <code>a</code> with the value of the right operand <code>b</code>,
|
Compares the value of the left operand <code>a</code> with the value of the right operand <code>b</code>,
|
||||||
|
|
|
@ -698,7 +698,7 @@ body .panelControlBar {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.paused {
|
&.script_paused {
|
||||||
#rightSendForm > div:not(.mes_send).stscript_btn {
|
#rightSendForm > div:not(.mes_send).stscript_btn {
|
||||||
&.stscript_pause {
|
&.stscript_pause {
|
||||||
display: none;
|
display: none;
|
||||||
|
|
Loading…
Reference in New Issue