From 3746f08590ea623656fb4eecbdf802be7c59c10a Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Thu, 29 Aug 2024 12:55:54 +0000 Subject: [PATCH 01/12] Add type conversion for /setvar commands with index --- .../SlashCommandCommonEnumsProvider.js | 17 +++ .../slash-commands/SlashCommandScope.js | 4 +- public/scripts/utils.js | 69 +++++++++++ public/scripts/variables.js | 115 ++++++++++++------ 4 files changed, 166 insertions(+), 39 deletions(-) diff --git a/public/scripts/slash-commands/SlashCommandCommonEnumsProvider.js b/public/scripts/slash-commands/SlashCommandCommonEnumsProvider.js index 6ef10b59b..ad064e4e1 100644 --- a/public/scripts/slash-commands/SlashCommandCommonEnumsProvider.js +++ b/public/scripts/slash-commands/SlashCommandCommonEnumsProvider.js @@ -36,6 +36,8 @@ export const enumIcons = { true: '✔️', false: '❌', + null: '🚫', + undefined: '❓', // Value types boolean: '🔲', @@ -230,4 +232,19 @@ export const commonEnumProviders = { enumTypes.enum, '💉'); }); }, + + /** + * Gets somewhat recognizable STscript types. + * + * @returns {SlashCommandEnumValue[]} + */ + types: () => [ + new SlashCommandEnumValue('string', null, enumTypes.type, enumIcons.string), + new SlashCommandEnumValue('number', null, enumTypes.type, enumIcons.number), + new SlashCommandEnumValue('boolean', null, enumTypes.type, enumIcons.boolean), + new SlashCommandEnumValue('array', null, enumTypes.type, enumIcons.array), + new SlashCommandEnumValue('object', null, enumTypes.type, enumIcons.dictionary), + new SlashCommandEnumValue('null', null, enumTypes.type, enumIcons.null), + new SlashCommandEnumValue('undefined', null, enumTypes.type, enumIcons.undefined), + ], }; diff --git a/public/scripts/slash-commands/SlashCommandScope.js b/public/scripts/slash-commands/SlashCommandScope.js index 78edb78ae..7fd573cac 100644 --- a/public/scripts/slash-commands/SlashCommandScope.js +++ b/public/scripts/slash-commands/SlashCommandScope.js @@ -1,4 +1,5 @@ import { SlashCommandClosure } from './SlashCommandClosure.js'; +import { convertValueType } from '../utils.js'; export class SlashCommandScope { /**@type {string[]}*/ variableNames = []; @@ -55,7 +56,8 @@ export class SlashCommandScope { if (this.existsVariableInScope(key)) throw new SlashCommandScopeVariableExistsError(`Variable named "${key}" already exists.`); this.variables[key] = value; } - setVariable(key, value, index = null) { + setVariable(key, value, index = null, type = null) { + value = convertValueType(value, type); if (this.existsVariableInScope(key)) { if (index !== null && index !== undefined) { let v = this.variables[key]; diff --git a/public/scripts/utils.js b/public/scripts/utils.js index dd3ff5622..cdf5ce694 100644 --- a/public/scripts/utils.js +++ b/public/scripts/utils.js @@ -4,6 +4,7 @@ import { isMobile } from './RossAscends-mods.js'; import { collapseNewlines } from './power-user.js'; import { debounce_timeout } from './constants.js'; import { Popup, POPUP_RESULT, POPUP_TYPE } from './popup.js'; +import { SlashCommandClosure } from './slash-commands/SlashCommandClosure.js'; /** * Pagination status string template. @@ -33,6 +34,74 @@ export function isValidUrl(value) { } } +/** + * Converts string to a value of a given type. Includes pythonista-friendly aliases. + * @param {string|SlashCommandClosure} value String value + * @param {string} type Type to convert to + * @returns {any} Converted value + */ +export function convertValueType(value, type) { + if (value instanceof SlashCommandClosure || typeof type !== 'string') { + return value; + } + + type = type.trim().toLowerCase(); + + switch (type) { + case 'string': + case 'str': + return String(value); + + case 'null': + return null; + + case 'undefined': + case 'none': + return undefined; + + case 'number': + return Number(value); + + case 'int': + return parseInt(value, 10); + + case 'float': + return parseFloat(value); + + case 'boolean': + case 'bool': + return isTrueBoolean(value); + + case 'list': + case 'array': + try { + const parsedArray = JSON.parse(value); + if (Array.isArray(parsedArray)) { + return parsedArray; + } + throw new Error('Value is not an array.'); + } catch { + return []; + } + + case 'object': + case 'dict': + case 'dictionary': + try { + const parsedObject = JSON.parse(value); + if (typeof parsedObject === 'object') { + return parsedObject; + } + throw new Error('Value is not an object.'); + } catch { + return {}; + } + + default: + return value; + } +} + /** * Parses ranges like 10-20 or 10. * Range is inclusive. Start must be less than end. diff --git a/public/scripts/variables.js b/public/scripts/variables.js index fa56dca5e..e4711594f 100644 --- a/public/scripts/variables.js +++ b/public/scripts/variables.js @@ -11,7 +11,7 @@ import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCom import { SlashCommandEnumValue, enumTypes } from './slash-commands/SlashCommandEnumValue.js'; import { PARSER_FLAG, SlashCommandParser } from './slash-commands/SlashCommandParser.js'; import { SlashCommandScope } from './slash-commands/SlashCommandScope.js'; -import { isFalseBoolean } from './utils.js'; +import { isFalseBoolean, convertValueType } from './utils.js'; /** @typedef {import('./slash-commands/SlashCommandParser.js').NamedArguments} NamedArguments */ /** @typedef {import('./slash-commands/SlashCommand.js').UnnamedArguments} UnnamedArguments */ @@ -51,6 +51,7 @@ function setLocalVariable(name, value, args = {}) { if (args.index !== undefined) { try { + value = convertValueType(value, args.type); let localVariable = JSON.parse(chat_metadata.variables[name] ?? 'null'); const numIndex = Number(args.index); if (Number.isNaN(numIndex)) { @@ -100,6 +101,7 @@ function getGlobalVariable(name, args = {}) { function setGlobalVariable(name, value, args = {}) { if (args.index !== undefined) { try { + value = convertValueType(value, args.type); let globalVariable = JSON.parse(extension_settings.variables.global[name] ?? 'null'); const numIndex = Number(args.index); if (Number.isNaN(numIndex)) { @@ -667,23 +669,28 @@ function parseNumericSeries(value, scope = null) { } function performOperation(value, operation, singleOperand = false, scope = null) { - if (!value) { - return 0; + function getResult() { + if (!value) { + return 0; + } + + const array = parseNumericSeries(value, scope); + + if (array.length === 0) { + return 0; + } + + const result = singleOperand ? operation(array[0]) : operation(array); + + if (isNaN(result) || !isFinite(result)) { + return 0; + } + + return result; } - const array = parseNumericSeries(value, scope); - - if (array.length === 0) { - return 0; - } - - const result = singleOperand ? operation(array[0]) : operation(array); - - if (isNaN(result) || !isFinite(result)) { - return 0; - } - - return result; + const result = getResult(); + return String(result); } function addValuesCallback(args, value) { @@ -836,7 +843,7 @@ function varCallback(args, value) { if (typeof key != 'string') throw new Error('Key must be a string'); if (args._hasUnnamedArgument) { const val = typeof value[0] == 'string' ? value.join(' ') : value[0]; - args._scope.setVariable(key, val, args.index); + args._scope.setVariable(key, val, args.index, args.type); return val; } else { return args._scope.getVariable(key, args.index); @@ -846,7 +853,7 @@ function varCallback(args, value) { if (typeof key != 'string') throw new Error('Key must be a string'); if (value.length > 0) { const val = typeof value[0] == 'string' ? value.join(' ') : value[0]; - args._scope.setVariable(key, val, args.index); + args._scope.setVariable(key, val, args.index, args.type); return val; } else { return args._scope.getVariable(key, args.index); @@ -901,6 +908,14 @@ export function registerVariableCommands() { new SlashCommandNamedArgument( 'index', 'list index', [ARGUMENT_TYPE.NUMBER, ARGUMENT_TYPE.STRING], false, ), + SlashCommandNamedArgument.fromProps({ + name: 'type', + description: 'type of the value when used with index', + forceEnum: true, + enumProvider: commonEnumProviders.types, + isRequired: false, + defaultValue: 'string', + }), ], unnamedArgumentList: [ new SlashCommandArgument( @@ -910,6 +925,7 @@ export function registerVariableCommands() { helpString: `
Set a local variable value and pass it down the pipe. The index argument is optional. + To perform a type conversion when using index, use the type argument.
Example: @@ -917,6 +933,9 @@ export function registerVariableCommands() {
  • /setvar key=color green
  • +
  • +
    /setvar key=colors index=3 type=string blue
    +
  • `, @@ -1015,6 +1034,14 @@ export function registerVariableCommands() { new SlashCommandNamedArgument( 'index', 'list index', [ARGUMENT_TYPE.NUMBER, ARGUMENT_TYPE.STRING], false, ), + SlashCommandNamedArgument.fromProps({ + name: 'type', + description: 'type of the value when used with index', + forceEnum: true, + enumProvider: commonEnumProviders.types, + isRequired: false, + defaultValue: 'string', + }), ], unnamedArgumentList: [ new SlashCommandArgument( @@ -1024,6 +1051,7 @@ export function registerVariableCommands() { helpString: `
    Set a global variable value and pass it down the pipe. The index argument is optional. + To perform a type conversion when using index, use the type argument.
    Example: @@ -1031,6 +1059,9 @@ export function registerVariableCommands() {
  • /setglobalvar key=color green
  • +
  • +
    /setglobalvar key=colors index=3 type=string blue
    +
  • `, @@ -1247,16 +1278,16 @@ export function registerVariableCommands() { }), new SlashCommandNamedArgument( 'rule', 'comparison rule', [ARGUMENT_TYPE.STRING], true, false, null, [ - new SlashCommandEnumValue('gt', 'a > b'), - new SlashCommandEnumValue('gte', 'a >= b'), - new SlashCommandEnumValue('lt', 'a < b'), - new SlashCommandEnumValue('lte', 'a <= b'), - new SlashCommandEnumValue('eq', 'a == b'), - new SlashCommandEnumValue('neq', 'a !== b'), - new SlashCommandEnumValue('not', '!a'), - new SlashCommandEnumValue('in', 'a includes b'), - new SlashCommandEnumValue('nin', 'a not includes b'), - ], + new SlashCommandEnumValue('gt', 'a > b'), + new SlashCommandEnumValue('gte', 'a >= b'), + new SlashCommandEnumValue('lt', 'a < b'), + new SlashCommandEnumValue('lte', 'a <= b'), + new SlashCommandEnumValue('eq', 'a == b'), + new SlashCommandEnumValue('neq', 'a !== b'), + new SlashCommandEnumValue('not', '!a'), + new SlashCommandEnumValue('in', 'a includes b'), + new SlashCommandEnumValue('nin', 'a not includes b'), + ], ), new SlashCommandNamedArgument( 'else', 'command to execute if not true', [ARGUMENT_TYPE.CLOSURE, ARGUMENT_TYPE.SUBCOMMAND], false, @@ -1325,16 +1356,16 @@ export function registerVariableCommands() { }), new SlashCommandNamedArgument( 'rule', 'comparison rule', [ARGUMENT_TYPE.STRING], true, false, null, [ - new SlashCommandEnumValue('gt', 'a > b'), - new SlashCommandEnumValue('gte', 'a >= b'), - new SlashCommandEnumValue('lt', 'a < b'), - new SlashCommandEnumValue('lte', 'a <= b'), - new SlashCommandEnumValue('eq', 'a == b'), - new SlashCommandEnumValue('neq', 'a !== b'), - new SlashCommandEnumValue('not', '!a'), - new SlashCommandEnumValue('in', 'a includes b'), - new SlashCommandEnumValue('nin', 'a not includes b'), - ], + new SlashCommandEnumValue('gt', 'a > b'), + new SlashCommandEnumValue('gte', 'a >= b'), + new SlashCommandEnumValue('lt', 'a < b'), + new SlashCommandEnumValue('lte', 'a <= b'), + new SlashCommandEnumValue('eq', 'a == b'), + new SlashCommandEnumValue('neq', 'a !== b'), + new SlashCommandEnumValue('not', '!a'), + new SlashCommandEnumValue('in', 'a includes b'), + new SlashCommandEnumValue('nin', 'a not includes b'), + ], ), new SlashCommandNamedArgument( 'guard', 'disable loop iteration limit', [ARGUMENT_TYPE.STRING], false, false, null, commonEnumProviders.boolean('onOff')(), @@ -2030,6 +2061,14 @@ export function registerVariableCommands() { false, // isRequired false, // acceptsMultiple ), + SlashCommandNamedArgument.fromProps({ + name: 'type', + description: 'type of the value when used with index', + forceEnum: true, + enumProvider: commonEnumProviders.types, + isRequired: false, + defaultValue: 'string', + }), ], unnamedArgumentList: [ SlashCommandArgument.fromProps({ From 9558e1408124a50e002654a47ce1865003c934cb Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Thu, 29 Aug 2024 13:04:46 +0000 Subject: [PATCH 02/12] Revert bad reformat --- public/scripts/variables.js | 40 ++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/public/scripts/variables.js b/public/scripts/variables.js index e4711594f..78317100c 100644 --- a/public/scripts/variables.js +++ b/public/scripts/variables.js @@ -1278,16 +1278,16 @@ export function registerVariableCommands() { }), new SlashCommandNamedArgument( 'rule', 'comparison rule', [ARGUMENT_TYPE.STRING], true, false, null, [ - new SlashCommandEnumValue('gt', 'a > b'), - new SlashCommandEnumValue('gte', 'a >= b'), - new SlashCommandEnumValue('lt', 'a < b'), - new SlashCommandEnumValue('lte', 'a <= b'), - new SlashCommandEnumValue('eq', 'a == b'), - new SlashCommandEnumValue('neq', 'a !== b'), - new SlashCommandEnumValue('not', '!a'), - new SlashCommandEnumValue('in', 'a includes b'), - new SlashCommandEnumValue('nin', 'a not includes b'), - ], + new SlashCommandEnumValue('gt', 'a > b'), + new SlashCommandEnumValue('gte', 'a >= b'), + new SlashCommandEnumValue('lt', 'a < b'), + new SlashCommandEnumValue('lte', 'a <= b'), + new SlashCommandEnumValue('eq', 'a == b'), + new SlashCommandEnumValue('neq', 'a !== b'), + new SlashCommandEnumValue('not', '!a'), + new SlashCommandEnumValue('in', 'a includes b'), + new SlashCommandEnumValue('nin', 'a not includes b'), + ], ), new SlashCommandNamedArgument( 'else', 'command to execute if not true', [ARGUMENT_TYPE.CLOSURE, ARGUMENT_TYPE.SUBCOMMAND], false, @@ -1356,16 +1356,16 @@ export function registerVariableCommands() { }), new SlashCommandNamedArgument( 'rule', 'comparison rule', [ARGUMENT_TYPE.STRING], true, false, null, [ - new SlashCommandEnumValue('gt', 'a > b'), - new SlashCommandEnumValue('gte', 'a >= b'), - new SlashCommandEnumValue('lt', 'a < b'), - new SlashCommandEnumValue('lte', 'a <= b'), - new SlashCommandEnumValue('eq', 'a == b'), - new SlashCommandEnumValue('neq', 'a !== b'), - new SlashCommandEnumValue('not', '!a'), - new SlashCommandEnumValue('in', 'a includes b'), - new SlashCommandEnumValue('nin', 'a not includes b'), - ], + new SlashCommandEnumValue('gt', 'a > b'), + new SlashCommandEnumValue('gte', 'a >= b'), + new SlashCommandEnumValue('lt', 'a < b'), + new SlashCommandEnumValue('lte', 'a <= b'), + new SlashCommandEnumValue('eq', 'a == b'), + new SlashCommandEnumValue('neq', 'a !== b'), + new SlashCommandEnumValue('not', '!a'), + new SlashCommandEnumValue('in', 'a includes b'), + new SlashCommandEnumValue('nin', 'a not includes b'), + ], ), new SlashCommandNamedArgument( 'guard', 'disable loop iteration limit', [ARGUMENT_TYPE.STRING], false, false, null, commonEnumProviders.boolean('onOff')(), From 5563d4918490b601606d0b21a8e7f5543d13904e Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Sun, 1 Sep 2024 11:44:56 +0300 Subject: [PATCH 03/12] Don't throw in array/dict conversion --- public/scripts/utils.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/public/scripts/utils.js b/public/scripts/utils.js index cdf5ce694..647b81ce6 100644 --- a/public/scripts/utils.js +++ b/public/scripts/utils.js @@ -79,7 +79,8 @@ export function convertValueType(value, type) { if (Array.isArray(parsedArray)) { return parsedArray; } - throw new Error('Value is not an array.'); + // The value is not an array + return []; } catch { return []; } @@ -92,7 +93,8 @@ export function convertValueType(value, type) { if (typeof parsedObject === 'object') { return parsedObject; } - throw new Error('Value is not an object.'); + // The value is not an object + return {}; } catch { return {}; } From 5d798fafdd3040c1423f4e50c337d9c5f1b5cd1f Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Sun, 1 Sep 2024 11:49:32 +0300 Subject: [PATCH 04/12] Rename type => cast --- public/scripts/variables.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/public/scripts/variables.js b/public/scripts/variables.js index 78317100c..4c6c87142 100644 --- a/public/scripts/variables.js +++ b/public/scripts/variables.js @@ -909,8 +909,8 @@ export function registerVariableCommands() { 'index', 'list index', [ARGUMENT_TYPE.NUMBER, ARGUMENT_TYPE.STRING], false, ), SlashCommandNamedArgument.fromProps({ - name: 'type', - description: 'type of the value when used with index', + name: 'cast', + description: 'change the type of the value when used with index', forceEnum: true, enumProvider: commonEnumProviders.types, isRequired: false, @@ -925,7 +925,7 @@ export function registerVariableCommands() { helpString: `
    Set a local variable value and pass it down the pipe. The index argument is optional. - To perform a type conversion when using index, use the type argument. + To convert the value to a specific JSON type when using index, use the case argument.
    Example: @@ -1035,8 +1035,8 @@ export function registerVariableCommands() { 'index', 'list index', [ARGUMENT_TYPE.NUMBER, ARGUMENT_TYPE.STRING], false, ), SlashCommandNamedArgument.fromProps({ - name: 'type', - description: 'type of the value when used with index', + name: 'cast', + description: 'change the type of the value when used with index', forceEnum: true, enumProvider: commonEnumProviders.types, isRequired: false, @@ -1051,7 +1051,7 @@ export function registerVariableCommands() { helpString: `
    Set a global variable value and pass it down the pipe. The index argument is optional. - To perform a type conversion when using index, use the type argument. + To convert the value to a specific JSON type when using index, use the cast argument.
    Example: @@ -2062,8 +2062,8 @@ export function registerVariableCommands() { false, // acceptsMultiple ), SlashCommandNamedArgument.fromProps({ - name: 'type', - description: 'type of the value when used with index', + name: 'cast', + description: 'change the type of the value when used with index', forceEnum: true, enumProvider: commonEnumProviders.types, isRequired: false, @@ -2088,7 +2088,8 @@ export function registerVariableCommands() { splitUnnamedArgumentCount: 1, helpString: `
    - Get or set a variable. + Get or set a variable. Use index to access elements of a list or dictionary. + To convert the value to a specific JSON type when using with index, use the cast argument.
    Examples: From 329e395077ab03eeaf2a19f7cea8a74950122f7c Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Sun, 1 Sep 2024 11:50:16 +0300 Subject: [PATCH 05/12] cast => as --- public/scripts/variables.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/public/scripts/variables.js b/public/scripts/variables.js index 4c6c87142..e0ccfbdc6 100644 --- a/public/scripts/variables.js +++ b/public/scripts/variables.js @@ -909,7 +909,7 @@ export function registerVariableCommands() { 'index', 'list index', [ARGUMENT_TYPE.NUMBER, ARGUMENT_TYPE.STRING], false, ), SlashCommandNamedArgument.fromProps({ - name: 'cast', + name: 'as', description: 'change the type of the value when used with index', forceEnum: true, enumProvider: commonEnumProviders.types, @@ -925,7 +925,7 @@ export function registerVariableCommands() { helpString: `
    Set a local variable value and pass it down the pipe. The index argument is optional. - To convert the value to a specific JSON type when using index, use the case argument. + To convert the value to a specific JSON type when using index, use the as argument.
    Example: @@ -1035,7 +1035,7 @@ export function registerVariableCommands() { 'index', 'list index', [ARGUMENT_TYPE.NUMBER, ARGUMENT_TYPE.STRING], false, ), SlashCommandNamedArgument.fromProps({ - name: 'cast', + name: 'as', description: 'change the type of the value when used with index', forceEnum: true, enumProvider: commonEnumProviders.types, @@ -1051,7 +1051,7 @@ export function registerVariableCommands() { helpString: `
    Set a global variable value and pass it down the pipe. The index argument is optional. - To convert the value to a specific JSON type when using index, use the cast argument. + To convert the value to a specific JSON type when using index, use the as argument.
    Example: @@ -2062,7 +2062,7 @@ export function registerVariableCommands() { false, // acceptsMultiple ), SlashCommandNamedArgument.fromProps({ - name: 'cast', + name: 'as', description: 'change the type of the value when used with index', forceEnum: true, enumProvider: commonEnumProviders.types, @@ -2089,7 +2089,7 @@ export function registerVariableCommands() { helpString: `
    Get or set a variable. Use index to access elements of a list or dictionary. - To convert the value to a specific JSON type when using with index, use the cast argument. + To convert the value to a specific JSON type when using with index, use the as argument.
    Examples: From 6f85327078e1abd841a3cba9da71d254c5984aa7 Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Sun, 1 Sep 2024 22:59:50 +0300 Subject: [PATCH 06/12] Only convert variable if needed --- public/scripts/slash-commands/SlashCommandScope.js | 9 ++++----- public/scripts/variables.js | 10 ++++------ 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/public/scripts/slash-commands/SlashCommandScope.js b/public/scripts/slash-commands/SlashCommandScope.js index 7fd573cac..e7ec2a58b 100644 --- a/public/scripts/slash-commands/SlashCommandScope.js +++ b/public/scripts/slash-commands/SlashCommandScope.js @@ -57,7 +57,6 @@ export class SlashCommandScope { this.variables[key] = value; } setVariable(key, value, index = null, type = null) { - value = convertValueType(value, type); if (this.existsVariableInScope(key)) { if (index !== null && index !== undefined) { let v = this.variables[key]; @@ -65,13 +64,13 @@ export class SlashCommandScope { v = JSON.parse(v); const numIndex = Number(index); if (Number.isNaN(numIndex)) { - v[index] = value; + v[index] = convertValueType(value, type); } else { - v[numIndex] = value; + v[numIndex] = convertValueType(value, type); } v = JSON.stringify(v); } catch { - v[index] = value; + v[index] = convertValueType(value, type); } this.variables[key] = v; } else { @@ -80,7 +79,7 @@ export class SlashCommandScope { return value; } if (this.parent) { - return this.parent.setVariable(key, value, index); + return this.parent.setVariable(key, value, index, type); } throw new SlashCommandScopeVariableNotFoundError(`No such variable: "${key}"`); } diff --git a/public/scripts/variables.js b/public/scripts/variables.js index e0ccfbdc6..c72605236 100644 --- a/public/scripts/variables.js +++ b/public/scripts/variables.js @@ -51,19 +51,18 @@ function setLocalVariable(name, value, args = {}) { if (args.index !== undefined) { try { - value = convertValueType(value, args.type); let localVariable = JSON.parse(chat_metadata.variables[name] ?? 'null'); const numIndex = Number(args.index); if (Number.isNaN(numIndex)) { if (localVariable === null) { localVariable = {}; } - localVariable[args.index] = value; + localVariable[args.index] = convertValueType(value, args.type); } else { if (localVariable === null) { localVariable = []; } - localVariable[numIndex] = value; + localVariable[numIndex] = convertValueType(value, args.type); } chat_metadata.variables[name] = JSON.stringify(localVariable); } catch { @@ -101,19 +100,18 @@ function getGlobalVariable(name, args = {}) { function setGlobalVariable(name, value, args = {}) { if (args.index !== undefined) { try { - value = convertValueType(value, args.type); let globalVariable = JSON.parse(extension_settings.variables.global[name] ?? 'null'); const numIndex = Number(args.index); if (Number.isNaN(numIndex)) { if (globalVariable === null) { globalVariable = {}; } - globalVariable[args.index] = value; + globalVariable[args.index] = convertValueType(value, args.type); } else { if (globalVariable === null) { globalVariable = []; } - globalVariable[numIndex] = value; + globalVariable[numIndex] = convertValueType(value, args.type); } extension_settings.variables.global[name] = JSON.stringify(globalVariable); } catch { From 56ae9d25b0d620892537caa1af4f47c843c0d8a5 Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Sun, 1 Sep 2024 23:02:01 +0300 Subject: [PATCH 07/12] Fix renamed argument reference --- public/scripts/variables.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/public/scripts/variables.js b/public/scripts/variables.js index c72605236..a892e2db9 100644 --- a/public/scripts/variables.js +++ b/public/scripts/variables.js @@ -57,12 +57,12 @@ function setLocalVariable(name, value, args = {}) { if (localVariable === null) { localVariable = {}; } - localVariable[args.index] = convertValueType(value, args.type); + localVariable[args.index] = convertValueType(value, args.as); } else { if (localVariable === null) { localVariable = []; } - localVariable[numIndex] = convertValueType(value, args.type); + localVariable[numIndex] = convertValueType(value, args.as); } chat_metadata.variables[name] = JSON.stringify(localVariable); } catch { @@ -106,12 +106,12 @@ function setGlobalVariable(name, value, args = {}) { if (globalVariable === null) { globalVariable = {}; } - globalVariable[args.index] = convertValueType(value, args.type); + globalVariable[args.index] = convertValueType(value, args.as); } else { if (globalVariable === null) { globalVariable = []; } - globalVariable[numIndex] = convertValueType(value, args.type); + globalVariable[numIndex] = convertValueType(value, args.as); } extension_settings.variables.global[name] = JSON.stringify(globalVariable); } catch { @@ -841,7 +841,7 @@ function varCallback(args, value) { if (typeof key != 'string') throw new Error('Key must be a string'); if (args._hasUnnamedArgument) { const val = typeof value[0] == 'string' ? value.join(' ') : value[0]; - args._scope.setVariable(key, val, args.index, args.type); + args._scope.setVariable(key, val, args.index, args.as); return val; } else { return args._scope.getVariable(key, args.index); @@ -851,7 +851,7 @@ function varCallback(args, value) { if (typeof key != 'string') throw new Error('Key must be a string'); if (value.length > 0) { const val = typeof value[0] == 'string' ? value.join(' ') : value[0]; - args._scope.setVariable(key, val, args.index, args.type); + args._scope.setVariable(key, val, args.index, args.as); return val; } else { return args._scope.getVariable(key, args.index); From a99367187341b4b3e4d4f9237d6d635f7dd03ffd Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Sun, 1 Sep 2024 23:04:15 +0300 Subject: [PATCH 08/12] Fix arg name in help string --- public/scripts/variables.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/scripts/variables.js b/public/scripts/variables.js index a892e2db9..e627da0d6 100644 --- a/public/scripts/variables.js +++ b/public/scripts/variables.js @@ -932,7 +932,7 @@ export function registerVariableCommands() {
    /setvar key=color green
  • -
    /setvar key=colors index=3 type=string blue
    +
    /setvar key=colors index=3 as=string blue
  • @@ -1058,7 +1058,7 @@ export function registerVariableCommands() {
    /setglobalvar key=color green
  • -
    /setglobalvar key=colors index=3 type=string blue
    +
    /setglobalvar key=colors index=3 as=string blue
  • From 873f25e330cc3c9eee8310eac56dd2afe99abb36 Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Sun, 1 Sep 2024 23:04:51 +0300 Subject: [PATCH 09/12] Specify JSON in /var help --- public/scripts/variables.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/scripts/variables.js b/public/scripts/variables.js index e627da0d6..f97eb82db 100644 --- a/public/scripts/variables.js +++ b/public/scripts/variables.js @@ -2086,7 +2086,7 @@ export function registerVariableCommands() { splitUnnamedArgumentCount: 1, helpString: `
    - Get or set a variable. Use index to access elements of a list or dictionary. + Get or set a variable. Use index to access elements of a JSON-serialized list or dictionary. To convert the value to a specific JSON type when using with index, use the as argument.
    From b9cd82180fb2ef442939110bb8c956ea67ccbe97 Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Sun, 1 Sep 2024 23:05:51 +0300 Subject: [PATCH 10/12] Better setvar example --- public/scripts/variables.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/scripts/variables.js b/public/scripts/variables.js index f97eb82db..ee91f29c7 100644 --- a/public/scripts/variables.js +++ b/public/scripts/variables.js @@ -932,7 +932,7 @@ export function registerVariableCommands() {
    /setvar key=color green
  • -
    /setvar key=colors index=3 as=string blue
    +
    /setvar key=ages index=John as=number 21
  • @@ -1058,7 +1058,7 @@ export function registerVariableCommands() {
    /setglobalvar key=color green
  • -
    /setglobalvar key=colors index=3 as=string blue
    +
    /setglobalvar key=ages index=John as=number 21
  • From 20e5e9eeee72c5ea8683d1e05759dfe4ae8aecdc Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Sun, 1 Sep 2024 23:07:49 +0300 Subject: [PATCH 11/12] Add example for /var with type --- public/scripts/variables.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/public/scripts/variables.js b/public/scripts/variables.js index ee91f29c7..3e9028591 100644 --- a/public/scripts/variables.js +++ b/public/scripts/variables.js @@ -2098,6 +2098,9 @@ export function registerVariableCommands() {
  • /let x foo | /var key=x foo bar | /var x | /echo
  • +
  • +
    /let x {} | /var index=cool as=number x 1337 | /echo {{var::x}}
    +
  • `, From 011f785a79cab8d2256486005c0735d8b1a39285 Mon Sep 17 00:00:00 2001 From: Cohee <18619528+Cohee1207@users.noreply.github.com> Date: Sun, 1 Sep 2024 23:25:29 +0300 Subject: [PATCH 12/12] Better switch value --- public/scripts/utils.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/public/scripts/utils.js b/public/scripts/utils.js index 647b81ce6..8f0ca59a7 100644 --- a/public/scripts/utils.js +++ b/public/scripts/utils.js @@ -45,9 +45,7 @@ export function convertValueType(value, type) { return value; } - type = type.trim().toLowerCase(); - - switch (type) { + switch (type.trim().toLowerCase()) { case 'string': case 'str': return String(value);