/if allow "rule" and "right" to be optional

aea95adf60b088bfff5e7776a023e1c171ef9144

Wolfsblvt <wolfsblvt@gmail.com>

1 files changed, +34 -16Showing whitespace changes
public/scripts/variables.js+34 -16
@@ -11,7 +11,7 @@ import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCom
1111import { SlashCommandEnumValue, enumTypes } from './slash-commands/SlashCommandEnumValue.js';
1212import { PARSER_FLAG, SlashCommandParser } from './slash-commands/SlashCommandParser.js';
1313import { SlashCommandScope } from './slash-commands/SlashCommandScope.js';
1414import { isFalseBoolean, convertValueType, isTrueBoolean } from './utils.js';
1515
1616/** @typedef {import('./slash-commands/SlashCommandParser.js').NamedArguments} NamedArguments */
1717/** @typedef {import('./slash-commands/SlashCommand.js').UnnamedArguments} UnnamedArguments */
@@ -463,7 +463,7 @@ function existsGlobalVariable(name) {
463463/**
464464 * Parses boolean operands from command arguments.
465465 * @param {object} args Command arguments
466466 * @returns {{a: string | number, b: string | number?, rule: string}} Boolean operands
467467 */
468468export function parseBooleanOperands(args) {
469469 // Resolution order: numeric literal, local variable, global variable, string literal
@@ -472,6 +472,9 @@ export function parseBooleanOperands(args) {
472472 */
473473 function getOperand(operand) {
474474 if (operand === undefined) {
475+ return undefined;
476+ }
477+ if (operand === '') {
475478 return '';
476479 }
477480
@@ -500,9 +503,9 @@ export function parseBooleanOperands(args) {
500503 return stringLiteral || '';
501504 }
502505
503506 const left = getOperand(args.a ||?? args.left ||?? args.first ||?? args.x);
504507 const right = getOperand(args.b ||?? args.right ||?? args.second ||?? args.y);
505508 const rule = args.rule ?? 'eq';
506509
507510 return { a: left, b: right, rule };
508511}
@@ -511,16 +514,22 @@ export function parseBooleanOperands(args) {
511514 * Evaluates a boolean comparison rule.
512515 * @param {string} rule Boolean comparison rule
513516 * @param {string|number} a The left operand
514517 * @param {string|number?} b The right operand
515518 * @returns {boolean} True if the rule yields true, false otherwise
516519 */
517520export function evalBoolean(rule, a, b) {
518- if (!rule) {
521+ let result = false;
519- toastr.warning('The rule must be specified for the boolean comparison.', 'Invalid command');
522+
520- throw new Error('Invalid command.');
523+ if (b === undefined && rule === 'eq') {
524+ // If right-hand side was not provided, whe just check if the left side is truthy
525+ if (isTrueBoolean(String(a))) return true;
526+ if (isFalseBoolean(String(a))) return false;
527+ return !!a;
521528 }
522529
523- let result = false;
530+ // Restore old behavior, where b cannot be undefined
531+ b = b ?? '';
532+
524533 if (typeof a === 'number' && typeof b === 'number') {
525534 // only do numeric comparison if both operands are numbers
526535 const aNumber = Number(a);
@@ -582,7 +591,7 @@ export function evalBoolean(rule, a, b) {
582591 break;
583592 default:
584593 toastr.error('Unknown boolean comparison rule for type string.', 'Invalid /if command');
585594 throw new Error('InvalidUnknown commandboolean comparison rule for type string.');
586595 }
587596 }
588597
@@ -1264,21 +1273,18 @@ export function registerVariableCommands() {
12641273 typeList: [ARGUMENT_TYPE.VARIABLE_NAME, ARGUMENT_TYPE.STRING, ARGUMENT_TYPE.NUMBER],
12651274 isRequired: true,
12661275 enumProvider: commonEnumProviders.variables('all'),
1267- forceEnum: false,
12681276 }),
12691277 SlashCommandNamedArgument.fromProps({
12701278 name: 'right',
12711279 description: 'right operand',
12721280 typeList: [ARGUMENT_TYPE.VARIABLE_NAME, ARGUMENT_TYPE.STRING, ARGUMENT_TYPE.NUMBER],
1273- isRequired: true,
12741281 enumProvider: commonEnumProviders.variables('all'),
1275- forceEnum: false,
12761282 }),
12771283 SlashCommandNamedArgument.fromProps({
12781284 name: 'rule',
12791285 description: 'comparison rule',
12801286 typeList: [ARGUMENT_TYPE.STRING],
12811287 isRequireddefaultValue: true'eq',
12821288 enumList: [
12831289 new SlashCommandEnumValue('gt', 'a > b'),
12841290 new SlashCommandEnumValue('gte', 'a >= b'),
@@ -1290,12 +1296,12 @@ export function registerVariableCommands() {
12901296 new SlashCommandEnumValue('in', 'a includes b'),
12911297 new SlashCommandEnumValue('nin', 'a not includes b'),
12921298 ],
1299+ forceEnum: true,
12931300 }),
12941301 SlashCommandNamedArgument.fromProps({
12951302 name: 'else',
12961303 description: 'command to execute if not true',
12971304 typeList: [ARGUMENT_TYPE.CLOSURE, ARGUMENT_TYPE.SUBCOMMAND],
1298- isRequired: false,
12991305 }),
13001306 ],
13011307 unnamedArgumentList: [
@@ -1314,6 +1320,11 @@ export function registerVariableCommands() {
13141320 Numeric values and string literals for left and right operands supported.
13151321 </div>
13161322 <div>
1323+ If the rule is not provided, it defaults to <code>eq</code>.<br />
1324+ If no right operand is provided, it defaults to checking the <code>left</code> value to be truthy.
1325+ A non-empty string or non-zero number is considered truthy, as is the value <code>true</code>.
1326+ </div>
1327+ <div>
13171328 <strong>Available rules:</strong>
13181329 <ul>
13191330 <li>gt => a > b</li>
@@ -1334,6 +1345,13 @@ export function registerVariableCommands() {
13341345 <pre><code class="language-stscript">/if left=score right=10 rule=gte "/speak You win"</code></pre>
13351346 triggers a /speak command if the value of "score" is greater or equals 10.
13361347 </li>
1348+ <li>
1349+ <pre><code class="language-stscript">/if left={{lastMessage}} rule=in right=surprise {: /echo SURPISE! :}</code></pre>
1350+ executes a subcommand defined as a closure if the given value contains a specified word.
1351+ <li>
1352+ <pre><code class="language-stscript">/if left=myContent {: /echo "My content had some content." :}</code></pre>
1353+ executes the defined subcommand, if the provided value of left is truthy (contains some kind of contant that is not empty or false)
1354+ </li>
13371355 </ul>
13381356 </div>
13391357 `,