refactor: replace stat system with variable system
Replaces the specialized `stat` system with a more general-purpose
variable system. This includes:
- Renaming `ReactiveStatManager` to `ReactiveVariableManager`
- Changing template syntax from `${key}` to `{{$key}}`
- Replacing `StatsView` with `VariableView` to show declared, plain,
and tag-typed variables
- Updating command `/stat` to `/set`
- Refactoring the reactivity engine to support variable declarations
and tag modifiers via `csv role=declare` blocks
This commit is contained in:
@@ -12,7 +12,7 @@ export interface CompletionItem {
|
||||
}
|
||||
|
||||
export interface ParsedInput {
|
||||
type: "chat" | "roll" | "spark" | "link" | "stat";
|
||||
type: "chat" | "roll" | "spark" | "link" | "set" | "rolltag";
|
||||
payload: Record<string, unknown>;
|
||||
error?: string;
|
||||
}
|
||||
@@ -41,41 +41,35 @@ export function parseInput(raw: string): ParsedInput {
|
||||
return { type: "link", payload: { path, section } };
|
||||
}
|
||||
|
||||
if (raw.startsWith("/stat ")) {
|
||||
const arg = raw.slice("/stat ".length).trim();
|
||||
if (!arg)
|
||||
return { type: "stat", payload: {}, error: "需要 stat 命令 (set/del/roll)" };
|
||||
if (raw.startsWith("/set ")) {
|
||||
const rest = raw.slice("/set ".length).trim();
|
||||
if (!rest)
|
||||
return { type: "set", payload: {}, error: "格式: /set $key expression" };
|
||||
|
||||
if (arg.startsWith("set ")) {
|
||||
const rest = arg.slice("set ".length).trim();
|
||||
const eqIdx = rest.indexOf("=");
|
||||
if (eqIdx === -1)
|
||||
return { type: "stat", payload: {}, error: "格式: /stat set key=value" };
|
||||
const key = rest.slice(0, eqIdx).trim();
|
||||
const value = rest.slice(eqIdx + 1).trim();
|
||||
if (!key || !value)
|
||||
return { type: "stat", payload: {}, error: "key 和 value 不能为空" };
|
||||
return { type: "stat", payload: { action: "set", key, value } };
|
||||
// Split on first space to get key and expression
|
||||
const spaceIdx = rest.indexOf(" ");
|
||||
if (spaceIdx === -1)
|
||||
return { type: "set", payload: {}, error: "格式: /set $key expression" };
|
||||
|
||||
const key = rest.slice(0, spaceIdx).trim();
|
||||
const expr = rest.slice(spaceIdx + 1).trim();
|
||||
|
||||
if (!key || !expr)
|
||||
return { type: "set", payload: {}, error: "key 和 expression 不能为空" };
|
||||
|
||||
if (!key.startsWith("$"))
|
||||
return { type: "set", payload: {}, error: "key 必须以 $ 开头" };
|
||||
|
||||
// Check if expr is a rolltag (e.g. #w|#d|#s)
|
||||
if (expr.includes("|") && expr.split("|").every((t) => t.trim().startsWith("#"))) {
|
||||
const tags = expr.split("|").map((t) => t.trim());
|
||||
return { type: "rolltag", payload: { key, tags } };
|
||||
}
|
||||
|
||||
if (arg.startsWith("del ")) {
|
||||
const key = arg.slice("del ".length).trim();
|
||||
if (!key)
|
||||
return { type: "stat", payload: {}, error: "格式: /stat del key" };
|
||||
return { type: "stat", payload: { action: "del", key } };
|
||||
}
|
||||
|
||||
if (arg.startsWith("roll ")) {
|
||||
const key = arg.slice("roll ".length).trim();
|
||||
if (!key)
|
||||
return { type: "stat", payload: {}, error: "格式: /stat roll key" };
|
||||
return { type: "stat", payload: { action: "roll", key } };
|
||||
}
|
||||
|
||||
return { type: "stat", payload: {}, error: "未知 stat 子命令: set/del/roll" };
|
||||
return { type: "set", payload: { key, expr } };
|
||||
}
|
||||
|
||||
if (raw === "/roll" || raw === "/spark" || raw === "/link" || raw === "/stat") {
|
||||
if (raw === "/roll" || raw === "/spark" || raw === "/link" || raw === "/set") {
|
||||
return { type: "chat", payload: {}, error: "请补全命令" };
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user