!7 module LLtoNL > DynRecordingTextArea { S output; transient S calcedInput; transient ReliableSingleThread rstCalc; visualize { ret jvsplit( jSection("INPUT (LL)", super.visualize()), jSection("OUTPUT (NL)", dm_fieldTextArea('output))); } start { doEvery(0.5, rstCalc); } void calc enter { if (neq(text, calcedInput)) { calcedInput = text; new LS out; final new MultiMap definitions; for (S s : tlft(text)) { LS tok = javaTokWithAllBrackets(s); continue unless isSquareBracketed(second(tok)) && eq(":", get(tok, 3); S id = second(tok); tok = subList(tok, 4); clearToken(tok, 0); definitions.put(id, tok); //out.add(join(tok)); } //out.add("Keys: " + keys(definitions)); out.addAll(map joinIfStringList(getEmits(r { render(definitions) }))); setField(output := lines(out)); } } void render(MultiMap definitions) { new Map simpleDefs; definitions = mapMultiMapValues(definitions, func(LS tok) -> LS { new Matches m; if (matchStart("there is", tok, m)) ret javaTokWithAllBrackets(m.rest()); ret tok; }); LL bla = definitions.get("[1]"); if (l(bla) < 2) ret; // Make the first line LS line = concatLists( ll(dropSuffixICTrim("(definition)", join(first(bla))), " means: "), second(bla)); emit(join(line)); // Expand [2] etc. in the line new LS line2; for (S s : line) { LS def = last(definitions.get(s)); if (def != null) line2.addAll(def); else line2.add(s); } if (eq(join(line), join(line2))) ret; emit(join(line2)); } }