34 lines
1.2 KiB
TypeScript
34 lines
1.2 KiB
TypeScript
import type { CommandRule } from './contract'
|
|
|
|
/** 规则读命令时出错:记下,当它没读(命令照抄)。 */
|
|
function guarded(rule: CommandRule, report: (message: string) => void): CommandRule {
|
|
return {
|
|
...rule,
|
|
read: (command, context) => {
|
|
try {
|
|
return rule.read(command, context)
|
|
}
|
|
catch (err) {
|
|
report(`命令规则 ${rule.id} 读「${command.name.node.text}」时出错,照抄命令:${err instanceof Error ? err.message : String(err)}`)
|
|
return undefined
|
|
}
|
|
},
|
|
}
|
|
}
|
|
|
|
/** 管没有自己的规则的命令的规则写的命令名。 */
|
|
const ANY_COMMAND = '*'
|
|
|
|
/** 命令名 → 命令规则(SourceDocument.commandRule):几条规则都管同一个名字时先注册的算;没有自己的规则的交给管 '*' 的。 */
|
|
export function commandRuleLookup(rules: readonly CommandRule[], report: (message: string) => void): (name: string) => CommandRule | undefined {
|
|
const byName = new Map<string, CommandRule>()
|
|
for (const rule of rules) {
|
|
const safe = guarded(rule, report)
|
|
for (const name of rule.commands) {
|
|
if (!byName.has(name))
|
|
byName.set(name, safe)
|
|
}
|
|
}
|
|
return name => byName.get(name) ?? byName.get(ANY_COMMAND)
|
|
}
|