!7 sclass Entry { S line; S rule; S varMap; S judgement; S matchedRuleStruct; S context; sS _fieldOrder = "line rule varMap judgement matchedRuleStruct context"; } cmodule StatementFulfillments > DynObjectTable { transient ReliableSingleThread rstSearch = dm_rst(this, r search); transient Flag cancel; start { set fieldsInOrder; dm_vmBus_onMessage_q('newDiscordLine, voidfunc(O line) { new L list; scanLines(ll(dm_discord_importLine(line)), list, 100); addAll(list); }); } visualize { ret withCenteredButtons(super.visualize(), "Search Chat", rstSearch); } void search { new Flag cancel; this.cancel = cancel; new L list; // "john doe is a guy" L lines = dm_discord_allLines(); print("Scanning " + n2(lines, "line")); scanLines(lines, list, 1000); print("Scan yielded " + n2(list, "entry", "entries")); setList(list); } void scanLines(L lines, L list_out, int maxEntries) { GazelleEvalContext ctx = dm_gazelle_stdEvalContext(dm_gazelle_rulesOnFacts()); for (GazelleLine line : lines) pcall { for (GazelleTree t : gazelle_getChildren(GazelleTree(ctx, line.text))) pcall { if (cancel! || l(list) >= maxEntries) ret with print("Cancel"); list_out.add(nu Entry( line := t.parent.line, varMap := struct(t.varMap()), rule := t.ruleID(), matchedRuleStruct := struct(t.mr), context := "discord msg " + line.msgID)); } } } // API L entriesForRule(S ruleID) { ret filterWhere(list(), rule := ruleID); } }