Skip to content

Comments

Neue Architektur#87

Merged
RamonDevPrivate merged 54 commits intodevelopmentfrom
feature/protocol_based_communication
Sep 22, 2025
Merged

Neue Architektur#87
RamonDevPrivate merged 54 commits intodevelopmentfrom
feature/protocol_based_communication

Conversation

@RamonDevPrivate
Copy link
Collaborator

No description provided.

@RamonDevPrivate RamonDevPrivate self-assigned this Aug 8, 2025
Comment on lines +1 to +4
[
{ "path": "demo/**/demo.java", "cmd": "java --enable-preview -Dsun.stdout.encoding=UTF-8" },
{ "path": "demo/sub1/demo.bat", "cmd": "" }
] No newline at end of file
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dokumentation: Wie funktioniert die Überwachung? Welche Dateien müssen wo liegen, um eine Ausführung zu triggern?

case "--watch-filter", "-w":
watchFilter = value.isBlank() ? Optional.empty() : Optional.of(value);
break;
case "--source-only", "-s":
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Begriff "source" geglückt? unklar, ob änderungswürdig

Comment on lines +64 to 92
private static void handleServerCommands(String command) {
String[] parts = command.split(" ", 2);
if (command.isBlank() || parts.length == 0) {
System.out.println("No command entered. Type '/help' for available commands.");
return;
}

switch (parts[0].toLowerCase()) {
case "exit" -> {
System.out.println("Exiting Live View Programming...");
System.exit(0);
}
case "log" -> {
if (parts.length < 2) {
System.out.println("Usage: /log <level>");
return;
}
LogLevel level = LogLevel.fromString(parts[1]);
if (level == null) {
System.out.println("Invalid log level.");
} else {
Logger.setLogLevel(level);
System.out.println("Log level set to: " + level);
}
}
case "help" -> System.out.println("Available commands: /exit, /help, /log");
default -> System.out.println("Unknown command: " + command);
}
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Zukünftige Architektur: Über die von LVP gestartete Konsole können ganz "normal" beliebige Befehle abgesetzt werden; ein log sollte als Dienst ganz normal von jedem Service aus verändert werden können. Ebenso wie über die Konsole auch Markdown etc. abgesetzt werden können sollte.

Comment on lines 35 to 37
if (!isLatestRelease()) {
System.out.println("Warning: You are not using the latest release of Live View Programming. Please visit https://github.com/denkspuren/LiveViewProgramming/releases");
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idee: Weil das aus gemachter Erfahrung keiner liest: Vielleicht ein Laufband im Browser "There is a new version available"

Comment on lines +155 to 156
ProcessBuilder pb = new ProcessBuilder(isWindows ? new String[]{"cmd.exe", "/c", source.cmd(), source.path().toString()} : new String[]{"sh", "-c", source.cmd(), source.path().toString()})
.redirectErrorStream(true);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kann man das nicht auch betriebssystemunabhängig halten, so dass nicht zwischen cmd und sh unterschieden werden muss? Dann kümmert sich Java darum.

Comment on lines +150 to +151
private void run(Source source) {
processor.init(source.id());
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Könnte in den Kommandoprozessor wandern.

Comment on lines 28 to 29
public class FileWatcher {
private WatchService watcher;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Status quo: FileWatcher startet Programme und nicht der Kommandoprozessor.

Zukünftig:

Der FileWatcher ist ein ganz "normaler" interner Service, der Dateien auf Änderungen überwacht und den KommandoProzessor über ein Ereignis auf eine Änderung hinweist. Der KommandoProzessor entscheidet daraufhin, was gemacht wird.

Comment on lines +31 to +33
private Map<Path, Instant> lastModified = new ConcurrentHashMap<>();
private boolean isRunning = true;
Path dir;
String fileNamePattern;

public FileWatcher(Path dir, String fileNamePattern, Server server) throws IOException{
this.dir = dir;
this.fileNamePattern = fileNamePattern;

private static final Duration DEBOUNCE_DURATION = Duration.ofMillis(500);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Die Zeitschwelle ist eine interne Buchführung des FileWatchers, um Änderungen erst nach dem Ablauf einer gewissen Zeit wieder dem Kommandoprozessor zu melden.

Comment on lines 42 to 58
void process(Process process, String sourceId) {
try(BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) {

InstructionParser.parse(reader.lines()).gather(Gatherers.fold(() -> "", (prev, curr) ->
switch (curr) {
case Command cmd -> processCommands(cmd, sourceId, process);
case Pipe pipe -> processPipe(pipe, prev, sourceId, process);
case Register register -> processRegister(register);
case Unknown unknown -> processUnknown(unknown, sourceId);
default -> null;
})).forEachOrdered(_->{});
}
catch (Exception e) {
Logger.logError("Error reading process output: " + e.getMessage(), e);
}
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Das HERZSTÜCK von dem Ganzen

Comment on lines +12 to +14
public class Text {
private Text() {}
static Map<String, String> memory = new ConcurrentHashMap<>();
Copy link
Owner

@denkspuren denkspuren Aug 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Überarbeitung des Aufbaus von Kommando-Pipes

Pipes sind Textverarbeitungsfolgen aus Quellen und Wandlern, wobei Wandler Seiteneffekte haben können (die manchmal wesentlich und entscheidend sind), aber nicht haben müssen.

Quellen beginnen/initiieren eine Pipe-Verarbeitung. Quellen, die in einer Pipe vorkommen, ignorieren den durchgereichten Text und ersetzen ihn durch den Text der Quelle.

Quellen stehen in einer Textzeile immer am Anfang. Soll der Textanfang ausnahmsweise nicht als Kommando interpretiert werden, kann eventuell Abhilfe durch ein führendes Leerzeichen geschaffen werden (Markdown würde das ignorieren). Oder der Befehl wird per Alias umbenannt, so dass der Textanfang keine Kommandoausführung triggert.

Wandler können Seiteneffekte haben (z.B. Text speichern) und wandeln den Text um. Wenn nur der Seiteneffekt relevant ist, wird der Text identisch durchgereicht.

Wandler stehen in einer Textzeile immer an Anfang, ihnen ist jedoch ein Pipe-Symbol mit folgendem Leerzeichen "| " vorangestellt.

Beispiel: "Hallo Welt!" beginnt die Pipe mit dem Text. Save 23 reicht den Text durch, speichert in als Seiteneffekt im Register 23 ab. Markdown liefert den Text als Seiteneffekt zum Rendering an den Browser und reicht ihn ansonsten weiter.

"""
Hallo Welt!
| Save: 23
| Markdown
"""

Im folgenden Fall steht Guten Tag als nächste Quelle da, die eine neue Pipe eröffnet und die bisherige beendet.

"""
Hallo Welt!
| Save: 23
| Markdown
Guten Tag
| Markdown
"""

Für den Umgang mit Text, der Platzhalter enthält, gibt es das Filler-Kommando, das konfiguriert wird mit dem Fülltext und bei der Bearbeitung den Fülltext im ersten Platzhalter des übergebenen Textes einfügt. Unterwegs wird der teilausgefüllte Text in Register 23 gespeichert.

"""
Hallo ${0}${1}
| Filler: World
| Save: 23
| Filler: !
| Markdown
"""

Das teilausgefüllte Template wird mit Load geladen (Load ist eine Quelle) und der zweite Platzhalter mit einem andere Filler ausgefüllt.

"""
Load: 23
| Filler: ?
| Markdown
"""

Back to the roots: Die Turtle ist kommandogetrieben. Wer einen Wrapper braucht, bitte selber machen! Damit wird die Turtle zu einem Kommando, das durch einen internen Service realisiert wird. Die Identität bindet die Turtle auch optisch eine eine View, die die Illusion der Identität visuell unterstützt.

IO.println("alias ':::| turtle' 'turtle:'");
IO.println("turtle: new 23");
int step = 10;
int degrees = 30;
for (int i = 1; i <= 6; i = i + 1) {
    IO.println("turtle: forward " + step);
    IO.println("turtle: left " + degrees);
}
IO.println("turtle: build --with-timeline");
IO.println("alias --reset ':::| turtle')";

Idee: Auch ein Prefix: <prefix> könnte global, ähnlich einem Alias, alle Befehle mit einem Prefix versehen.

Register

Register können auch als Argumente in Befehlen verwendet werden, dem Registernamen ist ein $ voranzustellen. Der Kommandoprozessor ersetzt die Registerreferenz mit dem Text des Registers vor der Ausführung des Kommandos.

Beispiel:

"""
Register: JShell "jshell --enable-preview -R-ea` --STDOUT --STDIN --interaction-counter=1"
Start-Process: jshell --enable-preview -R-ea

2 + 3
| Save: Expr
| Jshell
| Save: Result

Das Ergebnis von ${0} ist ${1}.
| Filler: $Expr
| Filler: $Result
| Markdown
"""
"""
Register: JShell "jshell -R-ea" --STDIN=$IN --STDOUT=$OUT --STDERR=$ERR
Register: JShell "jshell -R-ea" --STDIN=$IN --STDOUT=$OUT --STDERR=$ERR

Run: JShell       // §Processid123
| Store $JShell1

Snippet
| $JShell1
| Markdown

Snippet
| JShell 
| Store: OUT

Snippet
| JShell
| Cond: !$ERR
| Markdown

Load $ERR
| Markdown: --overlay
Load $OUT
"""

Beispiel für einen konfigurierbaren Basic-Calculator (bc). Die Übergabe aus der Pipe wird standardmäßig über den Speicher $IN bereitgestellt.
In dem rechts von einem Kommando stehenden Text (der das Kommando konfiguriert) werden Speicherreferenzen (erkennbar am $) durch ihren Textwert ersetzt.

"""
Register: Calc "bc -e $IN" --STDOUT

7 + 5 | Calc
"""

Offene Fragen

Wie geht der Kommandoprocessor mit Ereignissen um, die etwas antriggern.

@RamonDevPrivate RamonDevPrivate merged commit 9e5ee6c into development Sep 22, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants