!7 static SingleComponentPanel scp; static int startIndex; concept Sentence { S text; S action; } p-substance { unswing { useDBOf(#1008607); db(); indexConceptField(Sentence, "text"); L sentences = toLinesFullTrim(loadSnippet(#1008606)); sentences = notStartingWith("\"", sentences); time { makeUniqueConcepts(Sentence, "text", sentences); } } showFrame(centerAndSouth(scp = new SingleComponentPanel, withTopMargin(20, jcenteredline( jbutton("Prev", r { makePanel(max(startIndex-10, 0)) }), jbutton("Next", r { if (startIndex+10 < countConcepts(Sentence)) makePanel(startIndex+10) }), jbutton("Random", r { makePanel(random(countConcepts(Sentence))/10*10) }))))); makePanel(0); } svoid makePanel(int startIndex) { main.startIndex = startIndex; JPanel panel = gridLayoutPanel_trackWidth_evenlySpacedCols(2); panel.add(jlabel("Sentence")); panel.add(jlabel("Action")); for (final Sentence s : takeFirst(10, dropFirst(startIndex, list(Sentence)))) { final JTextField tfText = jtextfield_caretLeft(s.text); panel.add(tfText); new Matches m; if (jmatch("subject=* (* / *)", s.action, m)) pcall { int from = parseInt($2), len = parseInt($3); tfText.select(from, from+len); } bool hasAction = nempty(s.action); final JTextField tf = jtextfield(hasAction ? s.action : guessAction(s.text)); final new Var reviseBtn, okBtn; okBtn.set(jbutton("OK", r { cset(s, action := getTextTrim(tf)); disableTextField(tf); replaceComponent(okBtn!, reviseBtn!); })); reviseBtn.set(jbutton("Revise", r { cset(s, action := null); enableTextField(tf); replaceComponent(reviseBtn!, okBtn!); })); if (hasAction) disableTextField(tf); panel.add(centerAndEast(tf, hasAction ? reviseBtn! : okBtn!)); onCaret(tfText, r { if (s.action == null) { S a = makeSubjectAction(s.text, new IntRange(tfText.getSelectionStart(), tfText.getSelectionEnd())); if (a != null) tf.setText(a); } }); } scp.setComponent(jscroll(panel)); } static IntRange guess(S sentence) { L tok = codeTokens(nlTok5(sentence)); IntRange range = guessSubjectTokens(tok); ret tokenRangeToCharRange(tok, range); } static IntRange guessSubjectTokens(L tok) { print("tok=" + struct(tok)); ret new IntRange(0, 1); } static S guessAction(S sentence) { IntRange r = guess(sentence); ret or2(makeSubjectAction(sentence, r), "?"); } static S makeSubjectAction(S text, IntRange r) { if (r == null) null; int i = trimIndexRight(text, r.start); int j = trimIndexLeft(text, r.end); ret j <= i ? null : "subject=" + quote(substring(text, i, j)) + " (" + i + "/" + (j-i) + ")"; } static IntRange parseSubjectAction(S action) null on exception { new Matches m; if (jmatch("subject=* (* / *)", s.action, m)) ret intRangeFromStartAndLength(parseInt($2), parseInt($3)); } static L> learningMaterial() { for (Sentence s) { if (s.action != null) } }