!7 sS listName = "heise.de 2018/04/20 (raw)"; static L data; static JList list; static Q opThread = startQ(); p-subst { autoRestart(); L lines = trimAll(lines(mechList_raw(listName))); data = notEndingWith(".", filter containsSpace(standAloneLines(lines)); makeList(); L ops = mechLists_intersect("Operations on lists", "Safe JavaX functions"); new L buttons; buttons.add(jbutton("Drop analyzed", r { opThread.add(f dropAnalyzed) })); buttons.add(selectedRowCountListButton_min(list, 2, jbutton("Mark similar", r { opThread.add(f markSimilar) }))); buttons.addAll(map(ops, func(fS op) -> JButton { jbutton(op, r { opThread.add(r { performOp(op) }) }) })); addToWindowWithMargin(list, jcenteredLine(buttons)); } svoid performOp(S op) { O newData = callAndMake(op, data); if (isStringList(newData)) data = (L) newData; else data = lines(str(newData)); makeList(); } svoid makeList { list = showList(list, data); titleStatus_trailing(list, n2(l(data), "entry", "entries")); } svoid markSimilar { L items = selectedListItems(list); S x = "Similar lines"; x = barCombine(listName, x); int i = 1; Set set = asCISet(items); while licensed { S name = appendNumberUnlessOne(x, i++); Set s = mechCISet(name); if (eq(s, set)) ret with infoBox("List already saved"); if (empty(s)) { botEditMechList(name, items); ret with infoBox("Saved as " + name); } } } svoid dropAnalyzed { for (S list : mechListsPlusNumber(barCombine(listName, "Similar lines"))) removeSetFromList(data, mechList(list)); makeList(); }