Add /regex-toggle slash command

- Add /regex-toggle command, similarly to /extension-toggle
- toggles the state of both global and character-bound scripts
- Update jsdoc being inconsistent

Closes #3613
This commit is contained in:
Wolfsblvt
2025-03-13 23:55:08 +01:00
parent eaa7b91f1d
commit 7537192c9a

View File

@@ -4,22 +4,16 @@ import { selected_group } from '../../group-chats.js';
import { callGenericPopup, POPUP_TYPE } from '../../popup.js'; import { callGenericPopup, POPUP_TYPE } from '../../popup.js';
import { SlashCommand } from '../../slash-commands/SlashCommand.js'; import { SlashCommand } from '../../slash-commands/SlashCommand.js';
import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from '../../slash-commands/SlashCommandArgument.js'; import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from '../../slash-commands/SlashCommandArgument.js';
import { enumIcons } from '../../slash-commands/SlashCommandCommonEnumsProvider.js'; import { commonEnumProviders, enumIcons } from '../../slash-commands/SlashCommandCommonEnumsProvider.js';
import { SlashCommandEnumValue, enumTypes } from '../../slash-commands/SlashCommandEnumValue.js'; import { SlashCommandEnumValue, enumTypes } from '../../slash-commands/SlashCommandEnumValue.js';
import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js'; import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js';
import { download, getFileText, getSortableDelay, regexFromString, setInfoBlock, uuidv4 } from '../../utils.js'; import { download, equalsIgnoreCaseAndAccents, getFileText, getSortableDelay, isFalseBoolean, isTrueBoolean, regexFromString, setInfoBlock, uuidv4 } from '../../utils.js';
import { regex_placement, runRegexScript, substitute_find_regex } from './engine.js'; import { regex_placement, runRegexScript, substitute_find_regex } from './engine.js';
import { t } from '../../i18n.js'; import { t } from '../../i18n.js';
import { accountStorage } from '../../util/AccountStorage.js'; import { accountStorage } from '../../util/AccountStorage.js';
/** /**
* @typedef {object} RegexScript * @typedef {import('../../char-data.js').RegexScriptData} RegexScript
* @property {string} scriptName - The name of the script
* @property {boolean} disabled - Whether the script is disabled
* @property {string} replaceString - The replace string
* @property {string[]} trimStrings - The trim strings
* @property {string?} findRegex - The find regex
* @property {number?} substituteRegex - The substitute regex
*/ */
/** /**
@@ -417,6 +411,42 @@ function runRegexCallback(args, value) {
return value; return value;
} }
/**
* /regex-toggle slash command callback
* @param {{state: string}} args Named arguments
* @param {string} scriptName The name of the script to toggle
* @returns {Promise<string>} The regexed string
*/
async function toggleRegexCallback(args, scriptName) {
if (typeof scriptName !== 'string') throw new Error('Script name must be a string.');
const action = isTrueBoolean(args?.state) ? 'enable' :
isFalseBoolean(args?.state) ? 'disable' :
'toggle';
const scripts = getRegexScripts();
const script = scripts.find(s => equalsIgnoreCaseAndAccents(s.scriptName, scriptName));
if (!script) {
toastr.warning(t`Regex script '${scriptName}' not found.`);
return;
}
script.disabled = action === 'enable' ? false : action === 'disable' ? true : !script.disabled;
const isScoped = characters[this_chid]?.data?.extensions?.regex_scripts?.some(s => s.id === script.id);
const index = isScoped ? characters[this_chid]?.data?.extensions?.regex_scripts?.indexOf(script) : scripts.indexOf(script);
await saveRegexScript(script, index, isScoped);
if (script.disabled) {
toastr.success(t`Regex script '${scriptName}' has been disabled.`);
} else {
toastr.success(t`Regex script '${scriptName}' has been enabled.`);
}
return script.scriptName || '';
}
/** /**
* Performs the import of the regex file. * Performs the import of the regex file.
* @param {File} file Input file * @param {File} file Input file
@@ -639,6 +669,43 @@ jQuery(async () => {
], ],
helpString: 'Runs a Regex extension script by name on the provided string. The script must be enabled.', helpString: 'Runs a Regex extension script by name on the provided string. The script must be enabled.',
})); }));
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
name: 'regex-toggle',
callback: toggleRegexCallback,
returns: 'The name of the script that was toggled',
namedArgumentList: [
SlashCommandNamedArgument.fromProps({
name: 'state',
description: 'Explicitly set the state of the script (true to enable, false to disable). If not provided, the state will be toggled to the opposite of the current state.',
typeList: [ARGUMENT_TYPE.BOOLEAN],
enumList: commonEnumProviders.boolean('trueFalse')(),
}),
],
unnamedArgumentList: [
SlashCommandArgument.fromProps({
description: 'script name',
typeList: [ARGUMENT_TYPE.STRING],
isRequired: true,
enumProvider: localEnumProviders.regexScripts,
}),
],
helpString: `
<div>
Toggles the state of a specified regex script.
</div>
<div>
<strong>Example:</strong>
<ul>
<li>
<pre><code class="language-stscript">/regex-toggle MyScript</code></pre>
</li>
<li>
<pre><code class="language-stscript">/regex-toggle state=off Character-specific Script</code></pre>
</li>
</ul>
</div>
`,
}));
eventSource.on(event_types.CHAT_CHANGED, checkEmbeddedRegexScripts); eventSource.on(event_types.CHAT_CHANGED, checkEmbeddedRegexScripts);
eventSource.on(event_types.CHARACTER_DELETED, purgeEmbeddedRegexScripts); eventSource.on(event_types.CHARACTER_DELETED, purgeEmbeddedRegexScripts);