Skip to content

Conversation

@ChangeSuger
Copy link

支持在 when 指令中进行字符串比较

背景 & 思路

发现在 setVar 支持设置字符串变量的情况下,居然不支持在 -when 指令中进行字符串比较,这使得一些条件控制逻辑的书写会特别麻烦甚至写不出来。另外目前已经支持了用户输入,相信根据用户输入进行比较的诉求也是有的。因此研究了下目前的条件执行的实现,并尝试支持字符串比较。

目前条件执行依赖 angular 的 compile,下面的条件执行语句实际输入 compile 为 Camille==Enana,实际认为两侧均为变量,但都没有定义,最后变成 undefined==undefined,结果为 true

setVar:a=Camille;
:Camille -when=a==Enana;

实际测试发现,如果将输入调整为 "Camille"=="Enana",就可以正确的输出结果 false。因此支持字符串比较的思路如下:

  1. 限定在需要进行字符串比较时,字符串应使用 '" 包裹;
  2. 在取变量的值进行条件判断时,如果为字符串类型,使用 " 包裹(考虑到字符串中可能存在 ",需要将其替换为 \\"
/**
 * 取不到时返回 {key}
 */
export function getValueFromStateElseKey(key: string, useKeyNameAsReturn = false, quoteString = false) {
  const valueFromState = getValueFromState(key);
  if (valueFromState === null || valueFromState === undefined) {
    logger.warn('valueFromState result null, key = ' + key);
    if (useKeyNameAsReturn) {
      return key;
    }
    return `{${key}}`;
  }
+  // 用 "" 包裹字符串,用于使用 compile 条件判断,处理字符串类型的变量
+  if (quoteString && typeof valueFromState === 'string') {
+    return `"${valueFromState.replaceAll('"', '\\"')}"`;
+  }
  return valueFromState;
}

测试用例

这是自测使用的用例,直接复制粘贴到 start.txt 就可以测试。

setVar:a=1;
setVar:b=true;
setVar:c=false;
setVar:d=我喜欢你;
setVar:e=white.png;
setVar:f=I'm you;
setVar:g=a"a;

:a==1->true -when=a==1;
:a==2->false -when=a==2;

:b==true->true -when=b==true;
:b==false->false -when=b==false;

:c==false->true -when=c==false;
:c==true->false -when=c==true;

:d=="我喜欢你"->true -when=d=="我喜欢你";
:d=="我不喜欢你"->false -when=d=="我不喜欢你";

:e=='white.png'->true -when=e=='white.png';
:e=='black.png'->false -when=e=='black.png';

:f=="I'm you"->true -when=f=="I'm you";
:f=="I'm me"->false -when=f=="I'm me";

:g=='a"a'->true -when=g=='a"a';
:g=='a'a'->false -when=g=="a'a";

:h=="Camille"->false -when=h=="Camille";
:h->false -when=h;
:g->true -when=g;

end;

可能存在考虑不足的点,欢迎指正。

@gemini-code-assist
Copy link

Summary of Changes

Hello @ChangeSuger, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

此拉取请求解决了 -when 指令中字符串比较功能缺失的问题。通过修改变量值获取机制,确保字符串在评估前被正确地用引号包裹,从而实现了准确的字符串比较。这一改进显著增强了系统中条件逻辑的灵活性,使其能够更好地支持用户输入和其他复杂的条件判断场景。

Highlights

  • 问题发现: 在 setVar 指令中,-when 命令不支持字符串比较,这使得一些复杂的条件控制逻辑难以实现或根本无法编写。
  • 根本原因: 条件执行依赖 Angular 的 compile。例如,Camille==Enana 会被视为未定义的变量,最终导致 undefined==undefined 评估为 true。正确的字符串比较需要将字符串用引号包裹,如 "Camille"=="Enana"
  • 解决方案: 修改了 getValueFromStateElseKey 函数,增加了一个 quoteString 参数。当此参数为 true 且值为字符串类型时,函数会将字符串用双引号包裹,并转义内部的双引号。同时,更新了 whenChecker 函数,在获取变量值进行比较时,为 quoteString 参数传递 true
  • 影响: 此更改使得 -when 指令能够进行可靠的字符串比较,从而支持用户输入和更灵活的条件控制逻辑。

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

你好,感谢你为项目增加在 when 指令中进行字符串比较的功能。这是一个非常有用的增强。

代码的整体思路是正确的,通过在 getValueFromStateElseKey 中为字符串类型的值包裹引号,使其能被 angular-expressions 正确解析。

我在 scriptExecutor.ts 中发现了一个潜在的问题。当前的变量解析逻辑可能会将包含字母的字符串字面量(例如 'some_string')错误地识别为变量,导致条件判断不符合预期。此外,对于变量名和布尔值周围的空格处理也存在一些可以改进的地方。我在代码中留下了具体的修改建议,希望能帮助你完善这个功能。

总体来说,这是一个很棒的改进,稍作调整后会更加健壮。

Comment on lines 24 to 31
.map((e) => {
if (e.match(/[a-zA-Z]/)) {
if (e.match(/true/) || e.match(/false/)) {
if (e.match(/^(true|false)$/)) {
return e;
}
return getValueFromStateElseKey(e, true);
return getValueFromStateElseKey(e, true, true);
} else return e;
})

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

你好,感谢你的贡献!

当前 -when 指令的解析逻辑存在一些问题,可能会导致意外的行为:

  1. 字符串字面量误判:当一个字符串字面量(如 'white.png')包含英文字母时,e.match(/[a-zA-Z]/) 会返回 true,导致它被错误地当作变量处理,而不是字符串本身。这会破坏字符串比较的逻辑。
  2. 变量名识别不全/[a-zA-Z]/ 这个正则表达式无法正确识别以下划线 _ 或美元符号 $ 开头的合法变量名(例如 _myVar)。
  3. 布尔值和变量名匹配问题e.match(/^(true|false)$/)getValueFromStateElseKey(e, ...) 直接作用于未经 trim() 处理的字符串 e。如果表达式中有额外的空格(如 a == true ),e 可能是 ' true ',会导致匹配或变量查找失败。

为了解决这些问题,我建议重构这部分代码:

  • 首先检查并处理字符串字面量。
  • 然后使用更准确的方式来识别可能是变量或关键字的 token。
  • 在进行所有检查和变量查找之前,先对 token 进行 trim() 操作。

这样可以使条件表达式的解析更加健壮和可预测。

Suggested change
.map((e) => {
if (e.match(/[a-zA-Z]/)) {
if (e.match(/true/) || e.match(/false/)) {
if (e.match(/^(true|false)$/)) {
return e;
}
return getValueFromStateElseKey(e, true);
return getValueFromStateElseKey(e, true, true);
} else return e;
})
.map((e) => {
const trimmed = e.trim();
if (
(trimmed.startsWith("'") && trimmed.endsWith("'")) ||
(trimmed.startsWith('"') && trimmed.endsWith('"'))
) {
return e;
}
if (trimmed.match(/^[a-zA-Z_$]/)) {
if (trimmed === 'true' || trimmed === 'false') {
return e;
}
return getValueFromStateElseKey(trimmed, true, true);
}
return e;
})

@ChangeSuger
Copy link
Author

#810

@MakinoharaShoko
Copy link
Member

请忽略上一条评论,可能是我误解了 Redux Devtools 的展示导致。

@MakinoharaShoko MakinoharaShoko merged commit 65dd43e into OpenWebGAL:dev Jan 7, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants