!7 srecord Guesser(S regexp, S annotation) {} cmodule CLAG > DynPrintLogAndEnabled { new Map entries; // text -> annotations L guessers = litsynclist(Guesser("eval", "eval command")); sclass ByCategory { Guesser bestGuesser; } start { doEveryAndNow(5.0, r step); } void step enter { if (!enabled) ret; temp tempPrintTime(); dm_clearModulePrintLog(); // find annotator module S mod = annotator(); if (empty(mod)) ret; // get visible rows IntRange vis = cast quickImport(dm_rcall visibleRows(mod)); if (vis == null) ret; L allData = (L) dm_rcall data(mod); L visibleData = subList(allData, vis); // get all annotations (without "!") Set allClasses = asCISet(dropPrefixAll("!", (Collection) dm_rcall allAnnotations(mod))); print(+allClasses); // update entry map fOr (virtual Entry e : allData) { S text = getString text(e); LS annotations = cast rcall annotations(e); entries.put(text, annotations); } // go through classes for (S c : allClasses) { LS plusExamples = keysWhereValueContains(c, entries); LS minusExamples = keysWhereValueContains("!" + c, entries); print(c + ": " + l(plusExamples) + "/" + l(minusExamples)); } // guess visible rows bool change; fOr (virtual Entry e : visibleData) { S text = getString text(e); LS annotations = cast rcall annotations(e); Set guesses = ciSet(); for (Guesser guesser : guessers) if (regexpFindIC(guesser.regexp, text)) guesses.add(guesser.annotation); S guess = joinWithComma(guesses); if (set_trueIfChanged(e, +guess)) set change; } if (change) dm_rcall fireDataChanged(mod); } S annotator() { ret dm_moduleWithSnippetID(#1024172); } }