!7 set flag DynModule. sclass Entry { S line; transient GazelleTree treeNode; } cmodule ListeningComprehension > DynObjectTable { S processedInput, text; transient ReliableSingleThread rstCalc = dm_rstWithPostDelay(this, r calc, 500); transient int maxResults = 500; transient bool skipBadPredictions = true; transient JTree jTree; transient GazelleTree root; transient double qualityCutOff = -0.75; transient JLabel lblInfo; transient Set linesSet; S switchableFields() { ret "skipBadPredictions maxResults"; } enhanceFrame { internalFrameIcon(f, gazelle_frameIcon()); } start { hideFields('treeNode); dm_vmBus_onMessage('gazelleRulesChanged, rstCalc); } visualize { jTree = jDynamicTree/*_concurrent*/(null, func(GazelleTree tree) -> L enter { ret dm_gazelle_getChildren(tree, +qualityCutOff, dialogHistory := tlft(text)); }, makeChildrenIsFast := false); onTreeSelectionChanged(jTree, r updateInfo); treePopupMenu(jTree, voidfunc(JPopupMenu menu, final GazelleTree e) { addMenuItem(menu, "Copy line", rThread { copyTextToClipboard(e.line) }); addMenuItem(menu, "Make rule...", rThread { S s = e.line; GazelleTree ee = e; while ((ee = ee.parent) != null) s = ee.line + "\n+ " + s; dm_gazelle_newRuleDialog_3(s, "in = dialog"); }); addMenuItem(menu, "Mark good", rMark('good)); addMenuItem(menu, "Mark bad", rMark('bad)); addMenuItem(menu, "Mark funny", rMark('funny)); addMenuItem(menu, "Enter", rThread { LS history = e.history(); /*if (oddLength(history)) setField(input := popLast(history));*/ setField(text := lines(history)); }); }); ret jvsplit(0.25, withMargin(withTitle("Input Text", onChange(dm_textArea('text), rstCalc))), northCenterAndSouthWithMargins( rightAlignedButtons( "Make rule...", rThread { dm_gazelle_newRuleDialog_2(firstLine(text)) }), jhsplit( withTitle("Gazelle Tree", jTree), withTitle("Generated Lines", super.visualize())), vstackWithSpacing( rightAlignedButtons( treeDependentButton(jTree, "Mark good", rMark('good)), treeDependentButton(jTree, "Mark bad", rMark('bad)), treeDependentButton(jTree, "Mark funny", rMark('funny)), jPopDownButton_noText( "Export Rule Engine", rThread exportEngine) ), lblInfo = jlabel() ))); } Runnable rMark(fS judgement) { ret rThread { GazelleTree e = selectedNode(); e.judgement = judgement; jTree_fireUserObjectChanged(jTree, e); saveEntry(e); }; } GazelleTree selectedNode() { ret (GazelleTree) jtree_selectedUserObject(jTree); } void calc { linesSet = syncLinkedHashSet(); root = new GazelleTree(joinLinesWithBarOrPunctuation(text)); GazelleEvalContext ctx = dm_gazelle_stdEvalContext(); clear(); ctx.onNewNode = addListener(ctx.onNewNode, voidfunc(GazelleTree t) { if (linesSet.add(t.line)) add(nu Entry(line := t.line, treeNode := t)); }); root.setContext(ctx); jTree_setRootObject(jTree, root); jtree_collapseAndOpenRootNode(jTree); dm_gazelle_expandTree(root); processedInput = text; } void saveEntry(GazelleTree e) { S modifiedRule = e.ctx.engine.formatForUser(e.mr.applyMapping().asText()); dm_gazelle_saveAppliedRule( +modifiedRule, judgement := e.judgement, matchedRuleStruct := struct(e.mr)); } void updateInfo enter { S s = " "; GazelleTree e = selectedNode(); if (e != null && e.mr != null) { RuleEngine2.Rule r = e.mr.rule; s = "Rule: " + r.globalID + " (" + newLinesToSpaces_trim(r.text) + ")"; } setText(lblInfo, s); } void exportEngine enter { showText("Rule Engine", structWordWrap(root.ctx)); } }