feat(editor): F4.6b the command line on a computer's desktop
A new oracle, TerminalWindowRun, types into Java's own command line window: the window writes each line after its prompt, takes a blank line, cls, reset and exit itself, keeps the lines for the arrow keys, and keeps its text, history and working directory over a stop and a start. The room now holds a command line window per computer for everyone (TerminalWindow), kept over stops; the protocol carries its lines and the one way to read them (terminalScreen); the core goes on in the working directory of the run before (continueIn). The desktop opens programs in Java's frame, and the command line works with keyboard and finger: grey on black, the prompt hidden while a command runs, history, chips for the commands, Ctrl+C. The room's failure is now tested in the browser. Fixed: the room handed the engine the wall clock with fractions of a millisecond, and a ping hung after its first timeout. The engine and the room count whole milliseconds, as Java's clock does. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
// Types into FILIUS' own command line window (GUIApplicationTerminalWindow on
|
||||
// a GUIDesktopPanel) of a computer without a network, key by key as its key
|
||||
// listener hears them, and writes after each key what the window shows: its
|
||||
// text, its prompt and whether the prompt is shown, the input line. Then the
|
||||
// simulation is stopped and started again (beenden, starten), as a change of
|
||||
// mode does, and the window and the working directory are read again: the
|
||||
// reference for the editor's command line window (packages/sim/test/
|
||||
// terminalWindow.test.ts).
|
||||
//
|
||||
// Usage: java -cp filius.jar:lib/*:classes TerminalWindowRun <output json>
|
||||
|
||||
import filius.gui.anwendungssicht.GUIApplicationTerminalWindow;
|
||||
import filius.gui.anwendungssicht.GUIDesktopPanel;
|
||||
import filius.hardware.knoten.Rechner;
|
||||
import filius.software.system.Betriebssystem;
|
||||
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
import java.io.FileOutputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
public class TerminalWindowRun {
|
||||
static final String TERMINAL = "filius.software.lokal.Terminal";
|
||||
|
||||
static Object field(Object owner, String name) throws Exception {
|
||||
Field field = GUIApplicationTerminalWindow.class.getDeclaredField(name);
|
||||
field.setAccessible(true);
|
||||
return field.get(owner);
|
||||
}
|
||||
|
||||
static Map<String, Object> shown(GUIApplicationTerminalWindow window, String step) throws Exception {
|
||||
Map<String, Object> result = new LinkedHashMap<>();
|
||||
result.put("step", step);
|
||||
result.put("text", ((JTextArea) field(window, "terminalField")).getText());
|
||||
JLabel label = (JLabel) field(window, "inputLabel");
|
||||
result.put("prompt", label.getText());
|
||||
result.put("promptShown", label.isVisible());
|
||||
result.put("input", ((JTextField) field(window, "inputField")).getText());
|
||||
return result;
|
||||
}
|
||||
|
||||
static void press(JTextField input, int key, int modifiers) {
|
||||
KeyEvent event = new KeyEvent(input, KeyEvent.KEY_PRESSED, System.currentTimeMillis(), modifiers, key, KeyEvent.CHAR_UNDEFINED);
|
||||
for (KeyListener listener : input.getKeyListeners()) listener.keyPressed(event);
|
||||
}
|
||||
|
||||
/** Waits until the program has answered: the prompt is shown again (or a second passed). */
|
||||
static void settle(GUIApplicationTerminalWindow window) throws Exception {
|
||||
JLabel label = (JLabel) field(window, "inputLabel");
|
||||
for (int waited = 0; waited < 2000 && !label.isVisible(); waited += 20) Thread.sleep(20);
|
||||
Thread.sleep(200);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
try {
|
||||
run(args);
|
||||
} catch (Throwable error) {
|
||||
error.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
static void run(String[] args) throws Exception {
|
||||
Rechner host = new Rechner();
|
||||
Betriebssystem system = (Betriebssystem) host.getSystemSoftware();
|
||||
system.installApp(TERMINAL, true);
|
||||
system.starten();
|
||||
GUIDesktopPanel desktop = new GUIDesktopPanel(system);
|
||||
GUIApplicationTerminalWindow window = (GUIApplicationTerminalWindow) desktop.starteAnwendung(TERMINAL);
|
||||
JTextField input = (JTextField) field(window, "inputField");
|
||||
List<Object> steps = new ArrayList<>();
|
||||
steps.add(shown(window, "open"));
|
||||
// A line typed and entered ("type:<line>"), a key ("up", "down", "ctrl+c"), a stop and start ("restart").
|
||||
String[] keys = { "enter:", "enter: ", "enter:pwd", "enter:mkdir dir", "enter:cd dir", "enter:pwd", "enter:nosuchcommand", "up", "up", "up", "down", "down", "down",
|
||||
"enter:cls", "enter:ls", "restart", "enter:pwd", "up", "enter:exit" };
|
||||
for (String key : keys) {
|
||||
if (key.startsWith("enter:")) {
|
||||
input.setText(key.substring("enter:".length()));
|
||||
press(input, KeyEvent.VK_ENTER, 0);
|
||||
settle(window);
|
||||
} else if (key.equals("up")) {
|
||||
press(input, KeyEvent.VK_UP, 0);
|
||||
} else if (key.equals("down")) {
|
||||
press(input, KeyEvent.VK_DOWN, 0);
|
||||
} else if (key.equals("restart")) {
|
||||
system.beenden();
|
||||
system.starten();
|
||||
Thread.sleep(300);
|
||||
}
|
||||
steps.add(shown(window, key));
|
||||
}
|
||||
Map<String, Object> output = new LinkedHashMap<>();
|
||||
output.put("steps", steps);
|
||||
try (FileOutputStream out = new FileOutputStream(args[0])) {
|
||||
out.write((FlsOracle.Json.write(output, "") + "\n").getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
System.out.println("terminal window steps: " + steps.size());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user