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

7537192c9aff0b5756e697cf2d91b0a428312756

Wolfsblvt <wolfsblvt@gmail.com>

1 files changed, +76 -9Showing whitespace changes
public/scripts/extensions/regex/index.js+76 -9
@@ -4,22 +4,16 @@ import { selected_group } from '../../group-chats.js';
44import { callGenericPopup, POPUP_TYPE } from '../../popup.js';
55import { SlashCommand } from '../../slash-commands/SlashCommand.js';
66import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from '../../slash-commands/SlashCommandArgument.js';
77import { commonEnumProviders, enumIcons } from '../../slash-commands/SlashCommandCommonEnumsProvider.js';
88import { SlashCommandEnumValue, enumTypes } from '../../slash-commands/SlashCommandEnumValue.js';
99import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js';
1010import { download, equalsIgnoreCaseAndAccents, getFileText, getSortableDelay, isFalseBoolean, isTrueBoolean, regexFromString, setInfoBlock, uuidv4 } from '../../utils.js';
1111import { regex_placement, runRegexScript, substitute_find_regex } from './engine.js';
1212import { t } from '../../i18n.js';
1313import { accountStorage } from '../../util/AccountStorage.js';
1414
1515/**
1616 * @typedef {objectimport('../../char-data.js').RegexScriptData} RegexScript
17- * @property {string} scriptName - The name of the script
18- * @property {boolean} disabled - Whether the script is disabled
19- * @property {string} replaceString - The replace string
20- * @property {string[]} trimStrings - The trim strings
21- * @property {string?} findRegex - The find regex
22- * @property {number?} substituteRegex - The substitute regex
2317 */
2418
2519/**
@@ -418,6 +412,42 @@ function runRegexCallback(args, value) {
418412}
419413
420414/**
415+ * /regex-toggle slash command callback
416+ * @param {{state: string}} args Named arguments
417+ * @param {string} scriptName The name of the script to toggle
418+ * @returns {Promise<string>} The regexed string
419+ */
420+async function toggleRegexCallback(args, scriptName) {
421+ if (typeof scriptName !== 'string') throw new Error('Script name must be a string.');
422+
423+ const action = isTrueBoolean(args?.state) ? 'enable' :
424+ isFalseBoolean(args?.state) ? 'disable' :
425+ 'toggle';
426+
427+ const scripts = getRegexScripts();
428+ const script = scripts.find(s => equalsIgnoreCaseAndAccents(s.scriptName, scriptName));
429+
430+ if (!script) {
431+ toastr.warning(t`Regex script '${scriptName}' not found.`);
432+ return;
433+ }
434+
435+ script.disabled = action === 'enable' ? false : action === 'disable' ? true : !script.disabled;
436+
437+ const isScoped = characters[this_chid]?.data?.extensions?.regex_scripts?.some(s => s.id === script.id);
438+ const index = isScoped ? characters[this_chid]?.data?.extensions?.regex_scripts?.indexOf(script) : scripts.indexOf(script);
439+
440+ await saveRegexScript(script, index, isScoped);
441+ if (script.disabled) {
442+ toastr.success(t`Regex script '${scriptName}' has been disabled.`);
443+ } else {
444+ toastr.success(t`Regex script '${scriptName}' has been enabled.`);
445+ }
446+
447+ return script.scriptName || '';
448+}
449+
450+/**
421451 * Performs the import of the regex file.
422452 * @param {File} file Input file
423453 * @param {boolean} isScoped Is the script scoped to a character?
@@ -639,6 +669,43 @@ jQuery(async () => {
639669 ],
640670 helpString: 'Runs a Regex extension script by name on the provided string. The script must be enabled.',
641671 }));
672+ SlashCommandParser.addCommandObject(SlashCommand.fromProps({
673+ name: 'regex-toggle',
674+ callback: toggleRegexCallback,
675+ returns: 'The name of the script that was toggled',
676+ namedArgumentList: [
677+ SlashCommandNamedArgument.fromProps({
678+ name: 'state',
679+ 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.',
680+ typeList: [ARGUMENT_TYPE.BOOLEAN],
681+ enumList: commonEnumProviders.boolean('trueFalse')(),
682+ }),
683+ ],
684+ unnamedArgumentList: [
685+ SlashCommandArgument.fromProps({
686+ description: 'script name',
687+ typeList: [ARGUMENT_TYPE.STRING],
688+ isRequired: true,
689+ enumProvider: localEnumProviders.regexScripts,
690+ }),
691+ ],
692+ helpString: `
693+ <div>
694+ Toggles the state of a specified regex script.
695+ </div>
696+ <div>
697+ <strong>Example:</strong>
698+ <ul>
699+ <li>
700+ <pre><code class="language-stscript">/regex-toggle MyScript</code></pre>
701+ </li>
702+ <li>
703+ <pre><code class="language-stscript">/regex-toggle state=off Character-specific Script</code></pre>
704+ </li>
705+ </ul>
706+ </div>
707+ `,
708+ }));
642709
643710 eventSource.on(event_types.CHAT_CHANGED, checkEmbeddedRegexScripts);
644711 eventSource.on(event_types.CHARACTER_DELETED, purgeEmbeddedRegexScripts);