Merge pull request #3682 from SillyTavern/feat-add-regex-toggle-command Add `/regex-toggle` slash command
Signed| @@ -4,22 +4,16 @@ import { selected_group } from '../../group-chats.js'; | ||
| 4 | 4 | import { callGenericPopup, POPUP_TYPE } from '../../popup.js'; |
| 5 | 5 | import { SlashCommand } from '../../slash-commands/SlashCommand.js'; |
| 6 | 6 | import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from '../../slash-commands/SlashCommandArgument.js'; |
| 7 | 7 | import { commonEnumProviders, enumIcons } from '../../slash-commands/SlashCommandCommonEnumsProvider.js'; |
| 8 | 8 | import { SlashCommandEnumValue, enumTypes } from '../../slash-commands/SlashCommandEnumValue.js'; |
| 9 | 9 | import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js'; |
| 10 | 10 | import { download, equalsIgnoreCaseAndAccents, getFileText, getSortableDelay, isFalseBoolean, isTrueBoolean, regexFromString, setInfoBlock, uuidv4 } from '../../utils.js'; |
| 11 | 11 | import { regex_placement, runRegexScript, substitute_find_regex } from './engine.js'; |
| 12 | 12 | import { t } from '../../i18n.js'; |
| 13 | 13 | import { accountStorage } from '../../util/AccountStorage.js'; |
| 14 | 14 | |
| 15 | 15 | /** |
| 16 | 16 | * @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 | |
| 23 | 17 | */ |
| 24 | 18 | |
| 25 | 19 | /** |
| @@ -418,6 +412,53 @@ function runRegexCallback(args, value) { | ||
| 418 | 412 | } |
| 419 | 413 | |
| 420 | 414 | /** |
| 415 | + * /regex-toggle slash command callback | |
| 416 | + * @param {{state: string, quiet: string}} args Named arguments | |
| 417 | + * @param {string} scriptName The name of the script to toggle | |
| 418 | + * @returns {Promise<string>} The name of the script | |
| 419 | + */ | |
| 420 | +async function toggleRegexCallback(args, scriptName) { | |
| 421 | + if (typeof scriptName !== 'string') throw new Error('Script name must be a string.'); | |
| 422 | + | |
| 423 | + const quiet = isTrueBoolean(args?.quiet); | |
| 424 | + const action = isTrueBoolean(args?.state) ? 'enable' : | |
| 425 | + isFalseBoolean(args?.state) ? 'disable' : | |
| 426 | + 'toggle'; | |
| 427 | + | |
| 428 | + const scripts = getRegexScripts(); | |
| 429 | + const script = scripts.find(s => equalsIgnoreCaseAndAccents(s.scriptName, scriptName)); | |
| 430 | + | |
| 431 | + if (!script) { | |
| 432 | + toastr.warning(t`Regex script '${scriptName}' not found.`); | |
| 433 | + return ''; | |
| 434 | + } | |
| 435 | + | |
| 436 | + switch (action) { | |
| 437 | + case 'enable': | |
| 438 | + script.disabled = false; | |
| 439 | + break; | |
| 440 | + case 'disable': | |
| 441 | + script.disabled = true; | |
| 442 | + break; | |
| 443 | + default: | |
| 444 | + script.disabled = !script.disabled; | |
| 445 | + break; | |
| 446 | + } | |
| 447 | + | |
| 448 | + const isScoped = characters[this_chid]?.data?.extensions?.regex_scripts?.some(s => s.id === script.id); | |
| 449 | + const index = isScoped ? characters[this_chid]?.data?.extensions?.regex_scripts?.indexOf(script) : scripts.indexOf(script); | |
| 450 | + | |
| 451 | + await saveRegexScript(script, index, isScoped); | |
| 452 | + if (script.disabled) { | |
| 453 | + !quiet && toastr.success(t`Regex script '${scriptName}' has been disabled.`); | |
| 454 | + } else { | |
| 455 | + !quiet && toastr.success(t`Regex script '${scriptName}' has been enabled.`); | |
| 456 | + } | |
| 457 | + | |
| 458 | + return script.scriptName || ''; | |
| 459 | +} | |
| 460 | + | |
| 461 | +/** | |
| 421 | 462 | * Performs the import of the regex file. |
| 422 | 463 | * @param {File} file Input file |
| 423 | 464 | * @param {boolean} isScoped Is the script scoped to a character? |
| @@ -639,6 +680,51 @@ jQuery(async () => { | ||
| 639 | 680 | ], |
| 640 | 681 | helpString: 'Runs a Regex extension script by name on the provided string. The script must be enabled.', |
| 641 | 682 | })); |
| 683 | + SlashCommandParser.addCommandObject(SlashCommand.fromProps({ | |
| 684 | + name: 'regex-toggle', | |
| 685 | + callback: toggleRegexCallback, | |
| 686 | + returns: 'The name of the script that was toggled', | |
| 687 | + namedArgumentList: [ | |
| 688 | + SlashCommandNamedArgument.fromProps({ | |
| 689 | + name: 'state', | |
| 690 | + description: 'Explicitly set the state of the script (\'on\' to enable, \'off\' to disable). If not provided, the state will be toggled to the opposite of the current state.', | |
| 691 | + typeList: [ARGUMENT_TYPE.BOOLEAN], | |
| 692 | + defaultValue: 'toggle', | |
| 693 | + enumList: commonEnumProviders.boolean('onOffToggle')(), | |
| 694 | + }), | |
| 695 | + SlashCommandNamedArgument.fromProps({ | |
| 696 | + name: 'quiet', | |
| 697 | + description: 'Suppress the toast message script toggled', | |
| 698 | + typeList: [ARGUMENT_TYPE.BOOLEAN], | |
| 699 | + defaultValue: 'false', | |
| 700 | + enumList: commonEnumProviders.boolean('trueFalse')(), | |
| 701 | + }), | |
| 702 | + ], | |
| 703 | + unnamedArgumentList: [ | |
| 704 | + SlashCommandArgument.fromProps({ | |
| 705 | + description: 'script name', | |
| 706 | + typeList: [ARGUMENT_TYPE.STRING], | |
| 707 | + isRequired: true, | |
| 708 | + enumProvider: localEnumProviders.regexScripts, | |
| 709 | + }), | |
| 710 | + ], | |
| 711 | + helpString: ` | |
| 712 | + <div> | |
| 713 | + Toggles the state of a specified regex script. | |
| 714 | + </div> | |
| 715 | + <div> | |
| 716 | + <strong>Example:</strong> | |
| 717 | + <ul> | |
| 718 | + <li> | |
| 719 | + <pre><code class="language-stscript">/regex-toggle MyScript</code></pre> | |
| 720 | + </li> | |
| 721 | + <li> | |
| 722 | + <pre><code class="language-stscript">/regex-toggle state=off Character-specific Script</code></pre> | |
| 723 | + </li> | |
| 724 | + </ul> | |
| 725 | + </div> | |
| 726 | + `, | |
| 727 | + })); | |
| 642 | 728 | |
| 643 | 729 | eventSource.on(event_types.CHAT_CHANGED, checkEmbeddedRegexScripts); |
| 644 | 730 | eventSource.on(event_types.CHARACTER_DELETED, purgeEmbeddedRegexScripts); |