Phase 6: Plattformprüfungen und absolute RGB-Farben, Change 05 archivieren
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-09-07
|
||||
@@ -0,0 +1,32 @@
|
||||
## Context
|
||||
|
||||
Phase 5 verwendete crossterm-Ereignisse, ratatui-TestBackend und `tests/support/ide-execution-pty.py`. Der vorhandene PTY-Test setzt Unix voraus. Die verbindlichen Release-Targets sind Windows amd64, macOS arm64 und Linux amd64/arm64; Plattform-/Emulatornachweise fehlen noch.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:** Tatsächliche Terminalgrenzen von Produktfehlern unterscheiden und sämtliche Zielkombinationen mit reproduzierbaren Bedienfolgen abnehmen.
|
||||
|
||||
**Non-Goals:** Zweites UI-Toolkit, Emulation des historischen DOS-Programms, ein automatischer Test als Ersatz für reale Emulatorbedienung.
|
||||
|
||||
## Decisions
|
||||
|
||||
1. Eine Matrix mit Windows Terminal auf Windows amd64, Terminal.app auf macOS arm64 sowie xterm und einem VTE-Terminal auf beiden Linux-Architekturen verwenden. Konkrete installierte Versionsnummern sind Messmetadaten. Diese Kombinationen bilden den geplanten Mindestsatz, weitere Emulatoren sind keine Voraussetzung.
|
||||
2. Die vorhandenen Phase-5-Befehls-/Fokus-/Help-/Debuggerfälle zu kurzen tatsächlichen Eingabesequenzen verdichten. Screenshots/Transkripte, Eventdiagnosen und sichtbare Resultate werden je Matrixzelle festgehalten; ein Log „Prozess gestartet“ reicht nicht. F1–F12 und konfliktreiche Modifikatoren vollständig aufführen.
|
||||
3. Buildhost und Prüfsystem unterscheiden: Pakete entstehen in 06 zentral auf Linux arm64, echte Zielprüfungen laufen auf passenden Systemen; vier native Buildrunner sind keine Voraussetzung. Für 05 können Kandidaten aus lokalen Repository-Buildaufrufen verwendet werden, sodass kein Vorababschluss von 06 nötig ist. 06 prüft später die tatsächlich gepackte Revision. Die unveränderte `tests/libraries/portable.tbl` aus 03 mit `tests/support/library-abnahme.py` auf allen vier Zielen prüfen; TBL-Prüfsumme, Toolrevision, tatsächliches Host-Target und Ergebnisse einschließlich quellfreier TBC-/EXE-Nutzung und RUN festhalten.
|
||||
4. Unix-PTY-Prüfung wiederverwenden; Windows-ConPTY-/Konsolenprüfung für automatisierbare Terminalübergänge ergänzen. Dieselben nativen Releaseprogramme und eine repräsentative exportierte Forms-Anwendung verwenden. Gitea-Jobs führen automatisierbare Prüfungen aus; echte Emulatorfolgen dürfen dokumentiert manuell erfolgen.
|
||||
5. Windows-/Unix-spezifische Tests und Hilfsprozesse mit passenden Plattformzweigen führen. Keine Unix-Shell-Kommandos unverändert auf Windows als vermeintliche Produktfehler werten. Produktsemantik und Testhost-Portabilität getrennt prüfen.
|
||||
6. Fehler im gemeinsamen Terminaladapter beheben und einen fokussierten Regressionstest ergänzen. Für vom Emulator reservierte Shortcuts einen bereits vorhandenen Menü-/Mausweg prüfen. Fehlende Pflichtfunktionen werden nicht als Terminalgrenze umetikettiert.
|
||||
|
||||
7. Den ergänzenden Theme-Change 05a vor Abschluss der visuellen Matrix berücksichtigen. Dessen Referenzansichten und Kontrastprüfungen mit tatsächlicher Revision, Farbprofil und Standard-/abweichender ANSI-Palette in jeder Pflichtzelle prüfen; vor einer Theme-Korrektur erhobene betroffene Bilder erneut aufnehmen. Diese Nachweise gehen mit der bestehenden Matrix an 06/07.
|
||||
|
||||
8. Benutzerbefund vom 07.09.2026: ANSI-/256-Fallback entfernen und die vorhandene Farbabbildung in tb-ui für IDE und BASIC gemeinsam nutzen. RGB-Ausgabe auch bei fehlenden Farbfähigkeitsvariablen und NO_COLOR erzwingen. Fenster vor Block/Paragraph leeren, da diese nur Stile setzen und sonst Desktopmuster oder verdeckte Texte durchscheinen. Regressionen prüfen tatsächliche Leerzeichen, Auswahl/Neuzeichnen, absolute Farbwerte und ausgegebene Escape-Sequenzen. Frühere visuelle Nachweise gelten nicht für diesen korrigierten Stand.
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- CI ohne interaktiven Desktop → automatisierte Zieltests plus zugeordnete manuelle Emulatornachweise, keine Gleichsetzung beider Kategorien.
|
||||
- Nicht verfügbare Maschinen → benannter externer Nachweisbedarf; Change erst nach vollständiger Matrix abnehmen.
|
||||
- Globale Tastenbelegung des Benutzers beeinflusst Ergebnis → Terminalkonfiguration mitprotokollieren und Ersatzweg prüfen.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
Bestehende Headless-Regressionen erhalten. Plattformkorrekturen inkrementell anwenden; Nachweise mit geprüfter Revision ablegen. Matrix an 06 und 07 übergeben; ihre Gültigkeit bei Änderungen am Terminaladapter oder Hostpfad erneut prüfen.
|
||||
@@ -0,0 +1,7 @@
|
||||
Compiling tb-ui v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-ui)
|
||||
Compiling tb-vm v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-vm)
|
||||
Compiling tb-export v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-export)
|
||||
Compiling tb-runner v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-runner)
|
||||
Compiling tb-ide v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-ide)
|
||||
Compiling tb-cli v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-cli)
|
||||
Finished `release` profile [optimized] target(s) in 32.49s
|
||||
@@ -0,0 +1,5 @@
|
||||
Checking tb-ui v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-ui)
|
||||
Checking tb-vm v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-vm)
|
||||
Checking tb-export v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-export)
|
||||
Checking tb-ide v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-ide)
|
||||
Finished `dev` profile [unoptimized + debuginfo] target(s) in 6.81s
|
||||
@@ -0,0 +1 @@
|
||||
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.02s
|
||||
@@ -0,0 +1,3 @@
|
||||
PASS {'shell_exit': 7}
|
||||
PASS {'abort': True}
|
||||
PASS {'file_shell': True}
|
||||
@@ -0,0 +1 @@
|
||||
{"target": "aarch64-apple-darwin", "tbl_sha256": "5d25c2f8c95ae535e55a6c84c1ddd0d964358863f4f3c780c50ac4a2eb3594df", "native_execution": true, "source_free": true, "run_reset": true, "output": " 1 \n 7 3 9 1 \nTB \n"}
|
||||
@@ -0,0 +1,13 @@
|
||||
PASS native console
|
||||
PASS native restart
|
||||
PASS native stop
|
||||
PASS native error
|
||||
PASS native project
|
||||
PASS native form
|
||||
PASS native external
|
||||
PASS PTY Eingabe, Abbruch und Wiederherstellung (CLI/native)
|
||||
PASS Exportabbruch SIGINT/SIGTERM, Original und Bereinigung
|
||||
PASS corrupted length
|
||||
PASS corrupted version
|
||||
PASS corrupted truncated
|
||||
Native Abnahme bestanden: aarch64-apple-darwin
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,3 @@
|
||||
PASS {'shell_exit': 7}
|
||||
PASS {'abort': True}
|
||||
PASS {'file_shell': True}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"scope": "automated-target-checks",
|
||||
"started_utc": "2026-09-07T19:04:25.039868+00:00",
|
||||
"host_target": "aarch64-apple-darwin",
|
||||
"os_version": "macOS-26.6.2-arm64-arm-64bit-Mach-O",
|
||||
"python_version": "3.14.7",
|
||||
"checkout_revision": "5aa920b768a2ad29ed17c5da137e54675a7292d6",
|
||||
"working_tree_dirty": true,
|
||||
"working_tree_diff_sha256": "0834248d5bd0643cf959a7e6d78f74b4401d541cf65bb7226026b7eac13a136c",
|
||||
"program_sha256": {
|
||||
"tb": "7472ced2e905da8e8389bb9dafb221e39d2cd465110e982328e7076dc18817a9",
|
||||
"tbc": "52491c691507098f60524bbc078ef8e53a1883d284803427c422db42d95aa469",
|
||||
"tbrt": "4095b5412cf7c0470068c3c0b7f5ab325d0d357cd8b8fe8bbb966fdef1898df0",
|
||||
"tb-template": "a9d73ea8002b8f01bbb1fdc033a2595605ceb3b8c55d4531bf00da236351ccbf"
|
||||
},
|
||||
"tbl_sha256": "5d25c2f8c95ae535e55a6c84c1ddd0d964358863f4f3c780c50ac4a2eb3594df",
|
||||
"manual_terminal_status": "not_run",
|
||||
"matrix_complete": false,
|
||||
"checks": {
|
||||
"library": {
|
||||
"status": "passed",
|
||||
"exit_code": 0
|
||||
},
|
||||
"native": {
|
||||
"status": "passed",
|
||||
"exit_code": 0
|
||||
},
|
||||
"ide-pty": {
|
||||
"status": "passed",
|
||||
"exit_code": 0
|
||||
},
|
||||
"artifact-stability": {
|
||||
"status": "passed"
|
||||
}
|
||||
},
|
||||
"harness_sha256": {
|
||||
"library-abnahme.py": "118de32bc5a9cbb254b234b420455f75961603afb16aa94333be8c4b5b17e962",
|
||||
"platform-abnahme.py": "a5eadbd4bcabaae6c3c173ce933f83e331d03b1cf22998fe564519fe8f6b9696",
|
||||
"native-abnahme.py": "fe9f34bcc581e6230909b6277bae4768dbf6be068e4616b47aaff4390424ca14",
|
||||
"release-abnahme.py": "f77b1481913050faa321f9978d0f6cf31e8f884a1f626a861727b5393e1bea83",
|
||||
"ide-execution-pty.py": "fdbde7bf84068fe1ec8cfa037a071644add947d04930b8c73770b59f3070c985"
|
||||
},
|
||||
"all_automated_passed": true
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
- Validating...
|
||||
✓ spec/bytecode-kompilat
|
||||
ℹ [INFO] requirements[0]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[1]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
✓ spec/datei-eio
|
||||
ℹ [INFO] requirements[0]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[1]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[3]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[8]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
✓ spec/ereignissteuerung
|
||||
ℹ [INFO] requirements[0]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[1]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[2]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[4]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[5]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[10]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
✓ spec/forms-dateiformat
|
||||
ℹ [INFO] requirements[1]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
✓ spec/forms-objektmodell
|
||||
ℹ [INFO] requirements[0]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
✓ spec/forms-steuerelemente
|
||||
ℹ [INFO] requirements[1]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[3]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[4]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[6]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
✓ spec/ide-ausfuehrung
|
||||
ℹ [INFO] requirements[0]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[2]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
✓ spec/ide-debugger
|
||||
ℹ [INFO] requirements[2]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
✓ spec/ide-editor
|
||||
ℹ [INFO] requirements[2]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[3]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[5]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
✓ spec/ide-formulardesigner
|
||||
✓ spec/ide-hilfe
|
||||
✓ spec/ide-native-exporte
|
||||
✓ spec/ide-oberflaeche
|
||||
ℹ [INFO] requirements[3]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[6]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[7]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[8]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
✓ spec/ide-phasenabnahme
|
||||
ℹ [INFO] requirements[4]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
✓ spec/ide-projekte
|
||||
✓ spec/isam-datenbank
|
||||
ℹ [INFO] requirements[0]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[1]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[3]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[4]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[5]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[7]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
✓ spec/kompat-testkorpus
|
||||
ℹ [INFO] requirements[0]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[2]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[4]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[5]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[6]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[7]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[8]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
✓ spec/konsolen-basisbibliothek
|
||||
ℹ [INFO] requirements[1]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[3]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[4]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[6]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[8]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[9]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[10]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[11]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
✓ spec/laufzeitfehler
|
||||
✓ spec/native-executables
|
||||
ℹ [INFO] requirements[0]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
✓ spec/pcode-bibliotheken
|
||||
ℹ [INFO] requirements[0]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[1]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[2]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[3]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[4]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
✓ change/phase-6-05-plattformmatrix
|
||||
✓ change/phase-6-06-gitea-actions-und-releases
|
||||
✓ change/phase-6-07-dokumentation-und-phasenabnahme
|
||||
✓ spec/release-kompatibilitaet
|
||||
✓ spec/sprach-frontend
|
||||
ℹ [INFO] requirements[2]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[3]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[4]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[6]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[7]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[10]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[11]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[13]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
✓ spec/sprachinventar
|
||||
ℹ [INFO] requirements[0]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[2]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
✓ spec/textbildschirm
|
||||
ℹ [INFO] requirements[0]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[4]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[5]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[6]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[8]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[9]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[10]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
✓ spec/vm-ausfuehrung
|
||||
ℹ [INFO] requirements[0]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[3]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[5]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
ℹ [INFO] requirements[7]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
✓ spec/vm-fehlerbehandlung
|
||||
ℹ [INFO] requirements[0]: Requirement text is very long (>500 characters). Consider breaking it down.
|
||||
Totals: 30 passed, 0 failed (30 items)
|
||||
@@ -0,0 +1,18 @@
|
||||
M crates/tb-ide/src/render.rs
|
||||
M crates/tb-ide/tests/app.rs
|
||||
M crates/tb-ide/tests/execution.rs
|
||||
M crates/tb-ui/examples/spike.rs
|
||||
M crates/tb-ui/src/screen.rs
|
||||
M crates/tb-ui/src/terminal.rs
|
||||
M docs/ide-referenz.md
|
||||
M openspec/changes/phase-6-05-plattformmatrix/design.md
|
||||
M openspec/changes/phase-6-05-plattformmatrix/proposal.md
|
||||
M openspec/changes/phase-6-05-plattformmatrix/tasks.md
|
||||
M tests/support/ide-execution-pty.py
|
||||
?? docs/plattformmatrix.md
|
||||
?? openspec/changes/phase-6-05-plattformmatrix/evidence/
|
||||
?? openspec/changes/phase-6-05-plattformmatrix/specs/ide-oberflaeche/
|
||||
?? openspec/changes/phase-6-05-plattformmatrix/specs/textbildschirm/
|
||||
?? openspec/changes/phase-6-05-plattformmatrix/verification.md
|
||||
?? tests/platform/
|
||||
?? tests/support/platform-abnahme.py
|
||||
@@ -0,0 +1,12 @@
|
||||
Compiling tb-ide v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-ide)
|
||||
Finished `test` profile [unoptimized + debuginfo] target(s) in 1.46s
|
||||
Running tests/app.rs (target/debug/deps/app-d3d6e33413d63d0f)
|
||||
|
||||
running 4 tests
|
||||
test theme_color_commands_use_explicit_values_and_never_modify_terminal_palette ... ok
|
||||
test theme_windows_erase_desktop_and_underlying_windows_on_every_redraw ... ok
|
||||
test theme_designer_chrome_and_handles_preserve_program_palette ... ok
|
||||
test theme_contrast_covers_rendered_states_and_rejects_bad_pairs ... ok
|
||||
|
||||
test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 16 filtered out; finished in 0.42s
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
Checking tb-ui v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-ui)
|
||||
Checking tb-vm v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-vm)
|
||||
Checking tb-export v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-export)
|
||||
Checking tb-ide v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-ide)
|
||||
Finished `dev` profile [unoptimized + debuginfo] target(s) in 4.64s
|
||||
@@ -0,0 +1,19 @@
|
||||
M crates/tb-ide/src/render.rs
|
||||
M crates/tb-ide/tests/app.rs
|
||||
M crates/tb-ide/tests/execution.rs
|
||||
M crates/tb-ui/examples/spike.rs
|
||||
M crates/tb-ui/src/screen.rs
|
||||
M crates/tb-ui/src/terminal.rs
|
||||
M docs/ide-referenz.md
|
||||
M openspec/changes/phase-6-05-plattformmatrix/design.md
|
||||
M openspec/changes/phase-6-05-plattformmatrix/proposal.md
|
||||
M openspec/changes/phase-6-05-plattformmatrix/tasks.md
|
||||
M tests/support/ide-execution-pty.py
|
||||
?? docs/plattformmatrix.md
|
||||
?? openspec/changes/phase-6-05-plattformmatrix/evidence/
|
||||
?? openspec/changes/phase-6-05-plattformmatrix/specs/ide-oberflaeche/
|
||||
?? openspec/changes/phase-6-05-plattformmatrix/specs/textbildschirm/
|
||||
?? openspec/changes/phase-6-05-plattformmatrix/verification.md
|
||||
?? tests/platform/
|
||||
?? tests/support/__pycache__/
|
||||
?? tests/support/platform-abnahme.py
|
||||
@@ -0,0 +1,943 @@
|
||||
diff --git a/crates/tb-ide/src/render.rs b/crates/tb-ide/src/render.rs
|
||||
index 9c64b24..1ab5a4b 100644
|
||||
--- a/crates/tb-ide/src/render.rs
|
||||
+++ b/crates/tb-ide/src/render.rs
|
||||
@@ -11,74 +11,9 @@ use ratatui::{
|
||||
};
|
||||
use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};
|
||||
|
||||
-/// DOS-Farben der IDE. Die ersten 16 ANSI-Einträge gehören dem Terminalprofil.
|
||||
-/// BASIC-Ausgabe verwendet weiterhin ihre eigene Farbabbildung in tb-ui.
|
||||
+/// Feste DOS-RGB-Farben, identisch für IDE und BASIC-Ausgabe.
|
||||
pub fn dos(n: u8) -> Color {
|
||||
- static COLORS: std::sync::OnceLock<u16> = std::sync::OnceLock::new();
|
||||
- dos_color(
|
||||
- n,
|
||||
- *COLORS.get_or_init(|| {
|
||||
- let detected = crossterm::style::available_color_count();
|
||||
- // Ein generisches COLORTERM (z.B. "yes") verdeckt bei crossterm TERM.
|
||||
- if detected < 256 && std::env::var("TERM").is_ok_and(|s| s.contains("256")) {
|
||||
- 256
|
||||
- } else {
|
||||
- detected
|
||||
- }
|
||||
- }),
|
||||
- )
|
||||
-}
|
||||
-
|
||||
-pub fn dos_color(n: u8, colors: u16) -> Color {
|
||||
- let n = n.min(15) as usize;
|
||||
- const RGB: [(u8, u8, u8); 16] = [
|
||||
- (0, 0, 0),
|
||||
- (0, 0, 170),
|
||||
- (0, 170, 0),
|
||||
- (0, 170, 170),
|
||||
- (170, 0, 0),
|
||||
- (170, 0, 170),
|
||||
- (170, 85, 0),
|
||||
- (170, 170, 170),
|
||||
- (85, 85, 85),
|
||||
- (85, 85, 255),
|
||||
- (85, 255, 85),
|
||||
- (85, 255, 255),
|
||||
- (255, 85, 85),
|
||||
- (255, 85, 255),
|
||||
- (255, 255, 85),
|
||||
- (255, 255, 255),
|
||||
- ];
|
||||
- if colors > 256 {
|
||||
- let (r, g, b) = RGB[n];
|
||||
- Color::Rgb(r, g, b)
|
||||
- } else if colors >= 256 {
|
||||
- // Fester 6x6x6-Farbwürfel / Graurampe statt profilabhängiger Systemfarben.
|
||||
- Color::Indexed(
|
||||
- [
|
||||
- 16, 19, 34, 37, 124, 127, 130, 248, 240, 63, 83, 87, 203, 207, 227, 231,
|
||||
- ][n],
|
||||
- )
|
||||
- } else {
|
||||
- [
|
||||
- Color::Black,
|
||||
- Color::Blue,
|
||||
- Color::Green,
|
||||
- Color::Cyan,
|
||||
- Color::Red,
|
||||
- Color::Magenta,
|
||||
- Color::Yellow,
|
||||
- Color::Gray,
|
||||
- Color::DarkGray,
|
||||
- Color::LightBlue,
|
||||
- Color::LightGreen,
|
||||
- Color::LightCyan,
|
||||
- Color::LightRed,
|
||||
- Color::LightMagenta,
|
||||
- Color::LightYellow,
|
||||
- Color::White,
|
||||
- ][n]
|
||||
- }
|
||||
+ tb_ui::screen::basic_color(n.min(15))
|
||||
}
|
||||
|
||||
pub(crate) fn pair(fg: u8, bg: u8) -> Style {
|
||||
@@ -160,6 +95,8 @@ impl App {
|
||||
5
|
||||
},
|
||||
);
|
||||
+ // Block/Paragraph ändern Stile, löschen aber keine vorhandenen Zeichen.
|
||||
+ f.render_widget(Clear, rect);
|
||||
f.render_widget(
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
diff --git a/crates/tb-ide/tests/app.rs b/crates/tb-ide/tests/app.rs
|
||||
index 6ef2fdd..8ccd8c9 100644
|
||||
--- a/crates/tb-ide/tests/app.rs
|
||||
+++ b/crates/tb-ide/tests/app.rs
|
||||
@@ -930,21 +930,7 @@ fn theme_rgb(color: ratatui::style::Color) -> (u8, u8, u8) {
|
||||
use ratatui::style::Color;
|
||||
match color {
|
||||
Color::Rgb(r, g, b) => (r, g, b),
|
||||
- Color::Indexed(n @ 16..=231) => {
|
||||
- let n = n - 16;
|
||||
- let channel = |v: u8| if v == 0 { 0 } else { 55 + v * 40 };
|
||||
- (channel(n / 36), channel(n / 6 % 6), channel(n % 6))
|
||||
- }
|
||||
- Color::Indexed(n @ 232..=255) => {
|
||||
- let v = 8 + (n - 232) * 10;
|
||||
- (v, v, v)
|
||||
- }
|
||||
- _ => {
|
||||
- let n = (0..16)
|
||||
- .find(|n| tb_ide::render::dos_color(*n, 16) == color)
|
||||
- .unwrap_or_else(|| panic!("Unbestimmte IDE-Farbe: {color:?}"));
|
||||
- theme_rgb(tb_ide::render::dos_color(n, u16::MAX))
|
||||
- }
|
||||
+ _ => panic!("Keine absolute RGB-Farbe: {color:?}"),
|
||||
}
|
||||
}
|
||||
fn theme_contrast(fg: ratatui::style::Color, bg: ratatui::style::Color) -> f64 {
|
||||
@@ -983,23 +969,21 @@ fn assert_theme(app: &mut App, context: &str) {
|
||||
|
||||
#[test]
|
||||
fn theme_contrast_covers_rendered_states_and_rejects_bad_pairs() {
|
||||
- use tb_ide::render::dos_color;
|
||||
- for colors in [256, u16::MAX] {
|
||||
- for (fg, bg) in tb_ide::options::Options::default().colors {
|
||||
- assert!(theme_contrast(dos_color(fg, colors), dos_color(bg, colors)) >= 4.5);
|
||||
- }
|
||||
- assert!(theme_contrast(dos_color(15, colors), dos_color(7, colors)) < 4.5);
|
||||
- for n in 0..16 {
|
||||
- let fg = if matches!(n, 0 | 1 | 4 | 5 | 6 | 8 | 9) {
|
||||
- 15
|
||||
- } else {
|
||||
- 0
|
||||
- };
|
||||
- assert!(
|
||||
- theme_contrast(dos_color(fg, colors), dos_color(n, colors)) >= 4.5,
|
||||
- "Palettenbeschriftung {n}"
|
||||
- );
|
||||
- }
|
||||
+ use tb_ide::render::dos;
|
||||
+ for (fg, bg) in tb_ide::options::Options::default().colors {
|
||||
+ assert!(theme_contrast(dos(fg), dos(bg)) >= 4.5);
|
||||
+ }
|
||||
+ assert!(theme_contrast(dos(15), dos(7)) < 4.5);
|
||||
+ for n in 0..16 {
|
||||
+ let fg = if matches!(n, 0 | 1 | 4 | 5 | 6 | 8 | 9) {
|
||||
+ 15
|
||||
+ } else {
|
||||
+ 0
|
||||
+ };
|
||||
+ assert!(
|
||||
+ theme_contrast(dos(fg), dos(n)) >= 4.5,
|
||||
+ "Palettenbeschriftung {n}"
|
||||
+ );
|
||||
}
|
||||
let t = Temp::new();
|
||||
let mut app = t.app();
|
||||
@@ -1086,34 +1070,23 @@ fn theme_color_commands_use_explicit_values_and_never_modify_terminal_palette()
|
||||
buffer::Cell,
|
||||
style::Color,
|
||||
};
|
||||
- use tb_ide::render::dos_color;
|
||||
- assert_eq!(dos_color(1, u16::MAX), Color::Rgb(0, 0, 170));
|
||||
- assert_eq!(dos_color(5, u16::MAX), Color::Rgb(170, 0, 170));
|
||||
- assert_eq!(dos_color(6, u16::MAX), Color::Rgb(170, 85, 0));
|
||||
- for colors in [16, 256, u16::MAX] {
|
||||
- for n in 0..16 {
|
||||
- let color = dos_color(n, colors);
|
||||
- if let Color::Indexed(index) = color {
|
||||
- assert!(index >= 16);
|
||||
- }
|
||||
- let mut cell = Cell::default();
|
||||
- cell.set_symbol("X")
|
||||
- .set_bg(color)
|
||||
- .set_fg(dos_color(15, colors));
|
||||
- let mut output = Vec::new();
|
||||
- CrosstermBackend::new(&mut output)
|
||||
- .draw(std::iter::once((0, 0, &cell)))
|
||||
- .unwrap();
|
||||
- let sequence = String::from_utf8(output).unwrap();
|
||||
- assert!(sequence.contains('X'));
|
||||
- if colors >= 256 {
|
||||
- assert!(sequence.contains("48;"));
|
||||
- }
|
||||
- if colors > 256 {
|
||||
- assert!(sequence.contains("48;2;"));
|
||||
- }
|
||||
- assert!(!sequence.contains("\x1b]")); // Keine globale Palettenänderung.
|
||||
- }
|
||||
+ use tb_ide::render::dos;
|
||||
+ assert_eq!(dos(1), Color::Rgb(0, 0, 170));
|
||||
+ assert_eq!(dos(5), Color::Rgb(170, 0, 170));
|
||||
+ assert_eq!(dos(6), Color::Rgb(170, 85, 0));
|
||||
+ for n in 0..16 {
|
||||
+ assert_eq!(dos(n), tb_ui::screen::basic_color(n));
|
||||
+ let mut cell = Cell::default();
|
||||
+ cell.set_symbol("X").set_bg(dos(n)).set_fg(dos(15));
|
||||
+ let mut output = Vec::new();
|
||||
+ CrosstermBackend::new(&mut output)
|
||||
+ .draw(std::iter::once((0, 0, &cell)))
|
||||
+ .unwrap();
|
||||
+ let sequence = String::from_utf8(output).unwrap();
|
||||
+ assert!(sequence.contains('X'));
|
||||
+ assert!(sequence.contains("38;2;255;255;255"));
|
||||
+ assert!(sequence.contains("48;2;"));
|
||||
+ assert!(!sequence.contains("\x1b]")); // Keine globale Palettenänderung.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1149,3 +1122,61 @@ fn theme_designer_chrome_and_handles_preserve_program_palette() {
|
||||
assert_theme(&mut app, "Designer-Werkzeug");
|
||||
}
|
||||
}
|
||||
+
|
||||
+#[test]
|
||||
+fn theme_windows_erase_desktop_and_underlying_windows_on_every_redraw() {
|
||||
+ use ratatui::{
|
||||
+ layout::Rect,
|
||||
+ style::{Color, Modifier},
|
||||
+ };
|
||||
+ let t = Temp::new();
|
||||
+ let mut app = t.app();
|
||||
+ app.options.syntax_checking = false;
|
||||
+ // Ein sichtbares Zeichen macht das Durchscheinen sicher erkennbar.
|
||||
+ app.options.desktop = '@';
|
||||
+ type_text(&mut app, "PRINT 42");
|
||||
+ let mut term = Terminal::new(TestBackend::new(app.size.0, app.size.1)).unwrap();
|
||||
+ for selected in [false, true, false] {
|
||||
+ if selected {
|
||||
+ key(&mut app, K::Char('a'), M::CONTROL);
|
||||
+ } else {
|
||||
+ plain(&mut app, K::Right);
|
||||
+ }
|
||||
+ term.draw(|f| app.render(f)).unwrap();
|
||||
+ let b = term.backend().buffer();
|
||||
+ let rect = app.rect(app.windows.iter().find(|w| w.id == app.active).unwrap());
|
||||
+ let inner = Rect::new(rect.x + 1, rect.y + 1, rect.width - 2, rect.height - 2);
|
||||
+ for y in inner.y..inner.bottom() {
|
||||
+ for x in inner.x..inner.right() {
|
||||
+ let c = &b[(x, y)];
|
||||
+ assert_ne!(c.symbol(), "@", "Desktop in Fenster bei {x}/{y}");
|
||||
+ assert_eq!(c.bg, Color::Rgb(0, 0, 170));
|
||||
+ if y > inner.y {
|
||||
+ assert_eq!(c.symbol(), " ", "Restinhalt bei {x}/{y}");
|
||||
+ assert!(!c.modifier.contains(Modifier::REVERSED));
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ assert_eq!(b[(inner.x, inner.y)].symbol(), "P");
|
||||
+ assert_eq!(
|
||||
+ b[(inner.x, inner.y)].modifier.contains(Modifier::REVERSED),
|
||||
+ selected
|
||||
+ );
|
||||
+ }
|
||||
+ // Beim Aktivieren eines überlappenden Fensters müssen auch fremde Texte weg.
|
||||
+ app.execute(Command::NewModule);
|
||||
+ plain(&mut app, K::Enter);
|
||||
+ assert!(app.dialog.is_none());
|
||||
+ term.draw(|f| app.render(f)).unwrap();
|
||||
+ let b = term.backend().buffer();
|
||||
+ let rect = app.rect(app.windows.iter().find(|w| w.id == app.active).unwrap());
|
||||
+ for y in rect.y + 1..rect.bottom() - 1 {
|
||||
+ for x in rect.x + 1..rect.right() - 1 {
|
||||
+ assert_eq!(
|
||||
+ b[(x, y)].symbol(),
|
||||
+ " ",
|
||||
+ "Überdeckter Fensterinhalt bei {x}/{y}"
|
||||
+ );
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
diff --git a/crates/tb-ide/tests/execution.rs b/crates/tb-ide/tests/execution.rs
|
||||
index 237ac71..e92a0b6 100644
|
||||
--- a/crates/tb-ide/tests/execution.rs
|
||||
+++ b/crates/tb-ide/tests/execution.rs
|
||||
@@ -530,3 +530,35 @@ fn comment_only_source_change_also_requires_revision_choice() {
|
||||
DialogKind::ResumeRevision
|
||||
));
|
||||
}
|
||||
+
|
||||
+#[test]
|
||||
+fn platform_probe_records_each_basic_key_once_and_keeps_ide_keys_out() {
|
||||
+ let t = Temp::new();
|
||||
+ let log = t.0.join("platform-events.log");
|
||||
+ let source = include_str!("../../../tests/platform/input.frm")
|
||||
+ .replace("platform-events.log", &log.to_string_lossy());
|
||||
+ let path = t.0.join("input.frm");
|
||||
+ fs::write(&path, source).unwrap();
|
||||
+ let mut a = t.app("");
|
||||
+ a.load_initial_project(path).unwrap();
|
||||
+ a.execute(Command::Start);
|
||||
+ tick(&mut a);
|
||||
+ key(&mut a, K::Char('a'), M::NONE);
|
||||
+ tick(&mut a);
|
||||
+ a.handle(Event::Key(KeyEvent::new_with_kind(
|
||||
+ K::Char('a'),
|
||||
+ M::NONE,
|
||||
+ crossterm::event::KeyEventKind::Release,
|
||||
+ )));
|
||||
+ tick(&mut a);
|
||||
+ let events = fs::read_to_string(&log).unwrap();
|
||||
+ assert_eq!(
|
||||
+ events.replace('\r', ""),
|
||||
+ "Down: 97 : 0 \nPress: 97 : 0 \nUp: 97 : 0 \n"
|
||||
+ );
|
||||
+ edit_window(&mut a);
|
||||
+ key(&mut a, K::F(1), M::NONE);
|
||||
+ tick(&mut a);
|
||||
+ assert_eq!(fs::read_to_string(&log).unwrap(), events);
|
||||
+ assert!(matches!(a.active_window().unwrap().kind, WindowKind::Help));
|
||||
+}
|
||||
diff --git a/crates/tb-ui/examples/spike.rs b/crates/tb-ui/examples/spike.rs
|
||||
index b6b5ff3..38196ed 100644
|
||||
--- a/crates/tb-ui/examples/spike.rs
|
||||
+++ b/crates/tb-ui/examples/spike.rs
|
||||
@@ -1,15 +1,12 @@
|
||||
//! Phase-0-Spike: 80×25-Bildschirmpuffer, 16-Farben-Palette, Unicode,
|
||||
//! Tastatur- und Mausereignisse.
|
||||
//!
|
||||
-//! Start: `cargo run -p tb-ui --example spike` — Beenden mit Esc.
|
||||
+//! Start: `cargo run -p tb-ui --features terminal --example spike -- --log events.txt` — Beenden mit Esc.
|
||||
//! Getippte Zeichen erscheinen im Eingabebereich; Sondertasten und
|
||||
//! Mausereignisse werden in der Statuszeile angezeigt.
|
||||
|
||||
-use crossterm::event::{
|
||||
- self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyEventKind,
|
||||
-};
|
||||
-use crossterm::execute;
|
||||
-use std::io::stdout;
|
||||
+use crossterm::event::{self, Event, KeyCode, KeyEventKind};
|
||||
+use std::io::{stdout, Write};
|
||||
use std::time::Duration;
|
||||
use tb_ui::screen::{ScreenWidget, TextScreen};
|
||||
|
||||
@@ -57,8 +54,24 @@ fn status(s: &mut TextScreen, text: &str) {
|
||||
}
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
- let mut terminal = ratatui::init();
|
||||
- execute!(stdout(), EnableMouseCapture)?;
|
||||
+ let args: Vec<_> = std::env::args_os().skip(1).collect();
|
||||
+ anyhow::ensure!(
|
||||
+ args.is_empty() || (args.len() == 2 && args[0] == "--log"),
|
||||
+ "Aufruf: spike [--log neue-datei]"
|
||||
+ );
|
||||
+ let mut log = if args.len() == 2 {
|
||||
+ Some(
|
||||
+ std::fs::OpenOptions::new()
|
||||
+ .write(true)
|
||||
+ .create_new(true)
|
||||
+ .open(&args[1])?,
|
||||
+ )
|
||||
+ } else {
|
||||
+ None
|
||||
+ };
|
||||
+ let _guard = tb_ui::terminal::TerminalGuard::enter(stdout())?;
|
||||
+ let mut terminal = ratatui::Terminal::new(ratatui::backend::CrosstermBackend::new(stdout()))?;
|
||||
+ let mut sequence = 0u64;
|
||||
|
||||
let (tw, th) = crossterm::terminal::size()?;
|
||||
let mut screen = TextScreen::with_size(tw as usize, th as usize);
|
||||
@@ -70,7 +83,12 @@ fn main() -> anyhow::Result<()> {
|
||||
if !event::poll(Duration::from_millis(100))? {
|
||||
continue;
|
||||
}
|
||||
- match event::read()? {
|
||||
+ let received = event::read()?;
|
||||
+ sequence += 1;
|
||||
+ if let Some(log) = &mut log {
|
||||
+ writeln!(log, "{sequence}: {received:?}")?;
|
||||
+ }
|
||||
+ match received {
|
||||
Event::Key(k) if k.kind != KeyEventKind::Release => match k.code {
|
||||
KeyCode::Esc => break,
|
||||
KeyCode::Char(c) => {
|
||||
@@ -105,7 +123,5 @@ fn main() -> anyhow::Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
- execute!(stdout(), DisableMouseCapture)?;
|
||||
- ratatui::restore();
|
||||
Ok(())
|
||||
}
|
||||
diff --git a/crates/tb-ui/src/screen.rs b/crates/tb-ui/src/screen.rs
|
||||
index 8727b91..8297812 100644
|
||||
--- a/crates/tb-ui/src/screen.rs
|
||||
+++ b/crates/tb-ui/src/screen.rs
|
||||
@@ -12,11 +12,28 @@ use ratatui::layout::Rect;
|
||||
use ratatui::style::{Color, Style};
|
||||
use ratatui::widgets::Widget;
|
||||
|
||||
-/// Abbildung der klassischen 16-Farben-Palette auf ANSI-Indexfarben.
|
||||
-/// (Klassisch: 1 = Blau, 4 = Rot — ANSI: 1 = Rot, 4 = Blau usw.)
|
||||
+/// Klassische DOS-Farbnummern als absolute RGB-Werte, ohne Terminalprofil.
|
||||
pub fn basic_color(n: u8) -> Color {
|
||||
- const MAP: [u8; 16] = [0, 4, 2, 6, 1, 5, 3, 7, 8, 12, 10, 14, 9, 13, 11, 15];
|
||||
- Color::Indexed(MAP[(n & 0x0F) as usize])
|
||||
+ const RGB: [(u8, u8, u8); 16] = [
|
||||
+ (0, 0, 0),
|
||||
+ (0, 0, 170),
|
||||
+ (0, 170, 0),
|
||||
+ (0, 170, 170),
|
||||
+ (170, 0, 0),
|
||||
+ (170, 0, 170),
|
||||
+ (170, 85, 0),
|
||||
+ (170, 170, 170),
|
||||
+ (85, 85, 85),
|
||||
+ (85, 85, 255),
|
||||
+ (85, 255, 85),
|
||||
+ (85, 255, 255),
|
||||
+ (255, 85, 85),
|
||||
+ (255, 85, 255),
|
||||
+ (255, 255, 85),
|
||||
+ (255, 255, 255),
|
||||
+ ];
|
||||
+ let (r, g, b) = RGB[(n & 0x0F) as usize];
|
||||
+ Color::Rgb(r, g, b)
|
||||
}
|
||||
|
||||
/// Zeichenbares Gegenstück zu [`TextScreen`].
|
||||
@@ -66,9 +83,9 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn farbabbildung() {
|
||||
- assert_eq!(basic_color(1), Color::Indexed(4)); // klassisch Blau
|
||||
- assert_eq!(basic_color(4), Color::Indexed(1)); // klassisch Rot
|
||||
- assert_eq!(basic_color(14), Color::Indexed(11)); // Gelb
|
||||
- assert_eq!(basic_color(15), Color::Indexed(15)); // Weiß
|
||||
+ assert_eq!(basic_color(1), Color::Rgb(0, 0, 170)); // klassisch Blau
|
||||
+ assert_eq!(basic_color(4), Color::Rgb(170, 0, 0)); // klassisch Rot
|
||||
+ assert_eq!(basic_color(14), Color::Rgb(255, 255, 85)); // Gelb
|
||||
+ assert_eq!(basic_color(15), Color::Rgb(255, 255, 255)); // Weiß
|
||||
}
|
||||
}
|
||||
diff --git a/crates/tb-ui/src/terminal.rs b/crates/tb-ui/src/terminal.rs
|
||||
index 77493b2..67a6c8d 100644
|
||||
--- a/crates/tb-ui/src/terminal.rs
|
||||
+++ b/crates/tb-ui/src/terminal.rs
|
||||
@@ -11,23 +11,47 @@ use std::io::{self, Write};
|
||||
pub struct TerminalGuard<W: Write> {
|
||||
writer: W,
|
||||
raw: fn(bool) -> io::Result<()>,
|
||||
+ #[cfg(windows)]
|
||||
+ modes: Option<ConsoleModes>,
|
||||
}
|
||||
impl<W: Write> TerminalGuard<W> {
|
||||
pub fn enter(writer: W) -> io::Result<Self> {
|
||||
- Self::with_raw(writer, |on| {
|
||||
+ // Farben tragen UI-/BASIC-Zustand und müssen auch ohne Farberkennung
|
||||
+ // oder mit NO_COLOR als explizite RGB-Werte ausgegeben werden.
|
||||
+ crossterm::style::force_color_output(true);
|
||||
+ #[cfg(windows)]
|
||||
+ let modes = ConsoleModes::capture()?;
|
||||
+ #[cfg(windows)]
|
||||
+ modes.enable_output()?;
|
||||
+ #[allow(unused_mut)]
|
||||
+ let mut guard = Self::with_raw(writer, |on| {
|
||||
if on {
|
||||
enable_raw_mode()
|
||||
} else {
|
||||
disable_raw_mode()
|
||||
}
|
||||
- })
|
||||
+ })?;
|
||||
+ #[cfg(windows)]
|
||||
+ {
|
||||
+ guard.modes = Some(modes);
|
||||
+ }
|
||||
+ Ok(guard)
|
||||
}
|
||||
fn with_raw(writer: W, raw: fn(bool) -> io::Result<()>) -> io::Result<Self> {
|
||||
- let mut guard = Self { writer, raw };
|
||||
+ let mut guard = Self {
|
||||
+ writer,
|
||||
+ raw,
|
||||
+ #[cfg(windows)]
|
||||
+ modes: None,
|
||||
+ };
|
||||
guard.resume()?;
|
||||
Ok(guard)
|
||||
}
|
||||
fn resume(&mut self) -> io::Result<()> {
|
||||
+ #[cfg(windows)]
|
||||
+ if let Some(modes) = &self.modes {
|
||||
+ modes.enable_output()?;
|
||||
+ }
|
||||
(self.raw)(true)?;
|
||||
execute!(
|
||||
self.writer,
|
||||
@@ -38,15 +62,18 @@ impl<W: Write> TerminalGuard<W> {
|
||||
)
|
||||
}
|
||||
fn suspend(&mut self) -> io::Result<()> {
|
||||
- (self.raw)(false)?;
|
||||
- execute!(
|
||||
+ let raw = (self.raw)(false);
|
||||
+ let output = execute!(
|
||||
self.writer,
|
||||
ResetColor,
|
||||
Show,
|
||||
DisableMouseCapture,
|
||||
DisableBracketedPaste,
|
||||
LeaveAlternateScreen
|
||||
- )
|
||||
+ );
|
||||
+ #[cfg(windows)]
|
||||
+ let output = output.and(self.modes.as_ref().map_or(Ok(()), ConsoleModes::restore));
|
||||
+ raw.and(output)
|
||||
}
|
||||
/// Foreground child owns cooked terminal input. Always restore the IDE,
|
||||
/// including spawn/wait errors and a child interrupted by Ctrl+C.
|
||||
@@ -91,6 +118,10 @@ impl<W: Write> TerminalGuard<W> {
|
||||
}
|
||||
impl<W: Write> Drop for TerminalGuard<W> {
|
||||
fn drop(&mut self) {
|
||||
+ #[cfg(windows)]
|
||||
+ if let Some(modes) = &self.modes {
|
||||
+ let _ = modes.enable_output();
|
||||
+ }
|
||||
let _ = (self.raw)(false);
|
||||
let _ = execute!(
|
||||
self.writer,
|
||||
@@ -103,6 +134,58 @@ impl<W: Write> Drop for TerminalGuard<W> {
|
||||
}
|
||||
}
|
||||
|
||||
+// Crossterm stellt unter Windows Raw-/Mausflags pauschal zurück. Der Besitzer
|
||||
+// muss zusätzlich die tatsächlichen Eingabe- und Ausgabemodi wiederherstellen.
|
||||
+#[cfg(windows)]
|
||||
+#[derive(Debug)]
|
||||
+struct ConsoleModes([(std::os::windows::io::RawHandle, u32); 2]);
|
||||
+#[cfg(windows)]
|
||||
+#[link(name = "kernel32")]
|
||||
+extern "system" {
|
||||
+ fn GetStdHandle(kind: u32) -> std::os::windows::io::RawHandle;
|
||||
+ fn GetConsoleMode(handle: std::os::windows::io::RawHandle, mode: *mut u32) -> i32;
|
||||
+ fn SetConsoleMode(handle: std::os::windows::io::RawHandle, mode: u32) -> i32;
|
||||
+}
|
||||
+#[cfg(windows)]
|
||||
+impl ConsoleModes {
|
||||
+ fn capture() -> io::Result<Self> {
|
||||
+ let mut modes = [(std::ptr::null_mut(), 0); 2];
|
||||
+ for (slot, kind) in modes.iter_mut().zip([(-10i32) as u32, (-11i32) as u32]) {
|
||||
+ // Borrowed standard handles: valid until the terminal owner exits.
|
||||
+ slot.0 = unsafe { GetStdHandle(kind) };
|
||||
+ if unsafe { GetConsoleMode(slot.0, &mut slot.1) } == 0 {
|
||||
+ return Err(io::Error::last_os_error());
|
||||
+ }
|
||||
+ }
|
||||
+ Ok(Self(modes))
|
||||
+ }
|
||||
+ fn enable_output(&self) -> io::Result<()> {
|
||||
+ // Crossterm caches ANSI support, but a Shell handoff restores the old
|
||||
+ // output flags. Re-enable VT for each ownership cycle, including re-entry.
|
||||
+ if crossterm::ansi_support::supports_ansi()
|
||||
+ && unsafe { SetConsoleMode(self.0[1].0, self.0[1].1 | 0x0004) } == 0
|
||||
+ {
|
||||
+ return Err(io::Error::last_os_error());
|
||||
+ }
|
||||
+ Ok(())
|
||||
+ }
|
||||
+ fn restore(&self) -> io::Result<()> {
|
||||
+ let mut result = Ok(());
|
||||
+ for (handle, mode) in self.0 {
|
||||
+ if unsafe { SetConsoleMode(handle, mode) } == 0 && result.is_ok() {
|
||||
+ result = Err(io::Error::last_os_error());
|
||||
+ }
|
||||
+ }
|
||||
+ result
|
||||
+ }
|
||||
+}
|
||||
+#[cfg(windows)]
|
||||
+impl Drop for ConsoleModes {
|
||||
+ fn drop(&mut self) {
|
||||
+ let _ = self.restore();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -149,7 +232,7 @@ mod tests {
|
||||
("exit 7", false, 7),
|
||||
(
|
||||
if cfg!(windows) {
|
||||
- "ping -n 30 127.0.0.1 >nul"
|
||||
+ "for /L %i in (1,1,1000000000) do @rem"
|
||||
} else {
|
||||
"exec sleep 30"
|
||||
},
|
||||
@@ -160,10 +243,13 @@ mod tests {
|
||||
let out = Output(Rc::default());
|
||||
let copy = out.clone();
|
||||
let mut guard = TerminalGuard::with_raw(out, raw).unwrap();
|
||||
- assert_eq!(
|
||||
- guard.shell_with_interrupt(command, || abort).unwrap(),
|
||||
- expected
|
||||
- );
|
||||
+ let started = std::time::Instant::now();
|
||||
+ let code = guard.shell_with_interrupt(command, || abort).unwrap();
|
||||
+ if !abort {
|
||||
+ assert_eq!(code, expected);
|
||||
+ }
|
||||
+ // Windows TerminateProcess liefert einen Code; Unix ein Signal.
|
||||
+ assert!(started.elapsed() < std::time::Duration::from_secs(5));
|
||||
assert_eq!(RAW.load(Ordering::SeqCst), 1);
|
||||
let text = String::from_utf8(copy.0.borrow().clone()).unwrap();
|
||||
assert_eq!(text.matches("?1049h").count(), 2);
|
||||
@@ -187,4 +273,111 @@ mod tests {
|
||||
.unwrap()
|
||||
.contains("?25h"));
|
||||
}
|
||||
+ /// Run explicitly on Windows; never counts as a Windows Terminal UI test.
|
||||
+ #[cfg(windows)]
|
||||
+ #[test]
|
||||
+ #[ignore = "benötigt Windows mit echter Konsole; isolierter Kindprozess"]
|
||||
+ fn windows_console_restores_modes() {
|
||||
+ use std::os::windows::{io::AsRawHandle, process::CommandExt};
|
||||
+ use std::process::{Command, Stdio};
|
||||
+ use std::time::{Duration, Instant};
|
||||
+ const CHILD: &str = "TB_CONSOLE_TEST_CHILD";
|
||||
+ if std::env::var_os(CHILD).is_none() {
|
||||
+ let mut child = Command::new(std::env::current_exe().unwrap())
|
||||
+ .args([
|
||||
+ "--exact",
|
||||
+ "terminal::tests::windows_console_restores_modes",
|
||||
+ "--ignored",
|
||||
+ "--nocapture",
|
||||
+ ])
|
||||
+ .env(CHILD, "1")
|
||||
+ .creation_flags(0x00000010) // CREATE_NEW_CONSOLE: never touches the caller's console.
|
||||
+ .stdin(Stdio::null())
|
||||
+ .stdout(Stdio::null())
|
||||
+ .stderr(Stdio::null())
|
||||
+ .spawn()
|
||||
+ .unwrap();
|
||||
+ let deadline = Instant::now() + Duration::from_secs(30);
|
||||
+ loop {
|
||||
+ if let Some(status) = child.try_wait().unwrap() {
|
||||
+ assert!(
|
||||
+ status.success(),
|
||||
+ "Isolierte Windows-Konsolenprüfung: {status}"
|
||||
+ );
|
||||
+ return;
|
||||
+ }
|
||||
+ if Instant::now() >= deadline {
|
||||
+ let _ = child.kill();
|
||||
+ let _ = child.wait();
|
||||
+ panic!("Windows-Konsolenprüfung hat die Frist überschritten");
|
||||
+ }
|
||||
+ std::thread::sleep(Duration::from_millis(20));
|
||||
+ }
|
||||
+ }
|
||||
+ #[link(name = "kernel32")]
|
||||
+ extern "system" {
|
||||
+ fn SetStdHandle(kind: u32, handle: std::os::windows::io::RawHandle) -> i32;
|
||||
+ }
|
||||
+ let open = |name| {
|
||||
+ std::fs::OpenOptions::new()
|
||||
+ .read(true)
|
||||
+ .write(true)
|
||||
+ .open(name)
|
||||
+ .unwrap()
|
||||
+ };
|
||||
+ let input = open("CONIN$");
|
||||
+ let output = open("CONOUT$");
|
||||
+ // Standard streams started as NUL; bind to this child's own new console.
|
||||
+ assert_ne!(
|
||||
+ unsafe { SetStdHandle((-10i32) as u32, input.as_raw_handle()) },
|
||||
+ 0
|
||||
+ );
|
||||
+ assert_ne!(
|
||||
+ unsafe { SetStdHandle((-11i32) as u32, output.as_raw_handle()) },
|
||||
+ 0
|
||||
+ );
|
||||
+ let original = ConsoleModes::capture().unwrap();
|
||||
+ // Non-default echo flags catch a reset-to-default masquerading as restore.
|
||||
+ let mode = original.0[0].1 & !0x0004; // ENABLE_ECHO_INPUT
|
||||
+ assert_ne!(unsafe { SetConsoleMode(input.as_raw_handle(), mode) }, 0);
|
||||
+ let expected = ConsoleModes::capture().unwrap();
|
||||
+ let assert_restored = || assert_eq!(ConsoleModes::capture().unwrap().0, expected.0);
|
||||
+ for (command, abort, code) in [
|
||||
+ ("exit 0", false, 0),
|
||||
+ ("exit 7", false, 7),
|
||||
+ ("for /L %i in (1,1,1000000000) do @rem", true, 0),
|
||||
+ ] {
|
||||
+ let mut guard = TerminalGuard::enter(io::stdout()).unwrap();
|
||||
+ guard.suspend().unwrap();
|
||||
+ assert_restored();
|
||||
+ guard.resume().unwrap();
|
||||
+ if crossterm::ansi_support::supports_ansi() {
|
||||
+ assert_ne!(ConsoleModes::capture().unwrap().0[1].1 & 0x0004, 0);
|
||||
+ }
|
||||
+ let result = guard.shell_with_interrupt(command, || abort).unwrap();
|
||||
+ if !abort {
|
||||
+ assert_eq!(result, code);
|
||||
+ }
|
||||
+ assert!(crossterm::terminal::is_raw_mode_enabled().unwrap());
|
||||
+ drop(guard);
|
||||
+ assert_restored();
|
||||
+ }
|
||||
+ let error = (|| -> io::Result<()> {
|
||||
+ let _guard = TerminalGuard::enter(io::stdout())?;
|
||||
+ Err(io::Error::other("Erzwungener Renderfehler"))
|
||||
+ })();
|
||||
+ assert!(error.is_err());
|
||||
+ assert_restored();
|
||||
+ struct Broken;
|
||||
+ impl Write for Broken {
|
||||
+ fn write(&mut self, _: &[u8]) -> io::Result<usize> {
|
||||
+ Err(io::Error::other("Initialisierung"))
|
||||
+ }
|
||||
+ fn flush(&mut self) -> io::Result<()> {
|
||||
+ Ok(())
|
||||
+ }
|
||||
+ }
|
||||
+ assert!(TerminalGuard::enter(Broken).is_err());
|
||||
+ assert_restored();
|
||||
+ }
|
||||
}
|
||||
diff --git a/docs/ide-referenz.md b/docs/ide-referenz.md
|
||||
index 6cfa05d..6104316 100644
|
||||
--- a/docs/ide-referenz.md
|
||||
+++ b/docs/ide-referenz.md
|
||||
@@ -102,24 +102,23 @@ Laufzeit-Defaults kompilierter Programme weichen ab (Titel Weiß auf Schwarz).
|
||||
|
||||
## 4a. Farbabbildung und Kontrast (Phase 6)
|
||||
|
||||
-Die DOS-Farbnummern in Options→Display bleiben erhalten. Die IDE verwendet
|
||||
-bei `COLORTERM=truecolor`/`24bit` explizite RGB-Werte der klassischen
|
||||
-16-Farben-Palette; bei `TERM=…256color` feste Einträge im Farbwürfel und der
|
||||
-Graurampe außerhalb der ersten 16 ANSI-Farben. Ein generisches `COLORTERM`
|
||||
-verdeckt diese 256-Farben-Erkennung nicht. Auf Windows verwendet die IDE
|
||||
-zusätzlich die ANSI-Fähigkeitserkennung des vorhandenen Terminaladapters.
|
||||
-Die Erkennung erfolgt einmal pro Prozess; nach Profiländerungen neu starten.
|
||||
-
|
||||
-Damit hängt das Standardtheme bei expliziter Farbausgabe nicht von einer
|
||||
-pastellfarbenen ANSI-Palette ab. Beispielwerte: Codehintergrund `#0000AA`,
|
||||
-Codeschrift `#AAAAAA`, aktiver Titel `#FFFFFF` auf `#AA00AA`. DOS-Farbe 6
|
||||
-ist Braun (`#AA5500`), nicht das frei konfigurierte ANSI-Gelb. Der
|
||||
-256-Farben-Fallback nähert diese Werte an (`#0000AF`, `#A8A8A8`, `#AF00AF`).
|
||||
-Die globale Terminalpalette wird nicht verändert. Unbekannte beziehungsweise
|
||||
-reine 16-Farb-Terminals verwenden weiterhin die ANSI-Zuordnung; dort ist ein
|
||||
-geeignetes Terminalprofil nötig. `NO_COLOR`, Transparenz, Farbfilter und
|
||||
-Inaktivitätsdimmung des Emulators können die Darstellung zusätzlich verändern;
|
||||
-die IDE überschreibt solche Benutzereinstellungen nicht.
|
||||
+Die DOS-Farbnummern in Options→Display bleiben erhalten. IDE, Formularvorschau
|
||||
+und BASIC-Ausgabe verwenden dieselbe feste klassische RGB-Palette. Jede
|
||||
+Farbe wird als 24-Bit-Vorder-/Hintergrundwert ausgegeben, unabhängig von
|
||||
+`TERM`, `COLORTERM`, `NO_COLOR` oder der ANSI-Palette des Terminalprofils.
|
||||
+Es gibt keinen Rückfall auf Index- oder Profilfarben. Die globale
|
||||
+Terminalpalette wird nicht verändert; gespeichert werden weiterhin
|
||||
+DOS-Farbnummern, und BASIC bestimmt seine eigenen ForeColor/BackColor-Werte.
|
||||
+
|
||||
+Beispielwerte: Codehintergrund `#0000AA`, Codeschrift `#AAAAAA`, aktiver
|
||||
+Titel `#FFFFFF` auf `#AA00AA`. DOS-Farbe 6 ist Braun (`#AA5500`).
|
||||
+Fensterflächen werden vor dem Zeichnen geleert, damit Desktop-Füllzeichen
|
||||
+und Inhalte verdeckter Fenster keine scheinbar helleren Hintergründe erzeugen.
|
||||
+
|
||||
+Die Ausgabe setzt einen Terminalemulator mit 24-Bit-Farbunterstützung voraus.
|
||||
+Fehlende RGB-Unterstützung bleibt ein offener Zielbefund. Transparenz,
|
||||
+Farbfilter und Inaktivitätsdimmung sind nachgelagerte Emulatorfunktionen;
|
||||
+sie werden für die visuelle Farbprüfung getrennt protokolliert.
|
||||
|
||||
### Referenzfundstellen
|
||||
|
||||
@@ -144,7 +143,7 @@ Palette. Ansichten belegen Flächen und Rollen, keine heutige Terminalausgabe.
|
||||
| Deaktivierte Beschriftungen | Nicht ausreichend durch diese Ansichten belegt | Lesbares Schwarz auf Grau, Menüs zusätzlich `×` und kursiv |
|
||||
| Hilfe und Debuggermarkierungen | In diesen Ansichten nicht belegt | Dunkelblaue Hilfetitel/Links auf Grau; Fokus Weiß auf Blau; Breakpoints Weiß auf Rot, Ausführungszeile Schwarz auf Gelb |
|
||||
|
||||
-Die Standardpaare müssen bei RGB- und 256-Farben-Ausgabe mindestens 4,5:1
|
||||
+Die Standardpaare müssen bei RGB-Ausgabe mindestens 4,5:1
|
||||
Textkontrast erreichen; notwendige nichttextuelle Fokusmarkierungen mindestens
|
||||
3:1. Die Zelltests prüfen auch Rahmen und Handles auf mindestens 4,5:1
|
||||
gegen ihren eigenen Hintergrund. Benutzerauswahl in Display bleibt frei;
|
||||
@@ -154,16 +153,16 @@ Designer-Werkzeuge und Handles die IDE-Farben verwenden.
|
||||
|
||||
Die sRGB-Kontrastberechnung ergibt für die wichtigsten Standardpaare:
|
||||
|
||||
-| Rolle | RGB | 256 Farben |
|
||||
-|---|---|---|
|
||||
-| Code / Hilfelink | 5,72:1 | 5,45:1 |
|
||||
-| Aktiver Titel | 6,38:1 | 6,10:1 |
|
||||
-| Menü / Dialog / deaktivierter Text | 9,04:1 | 8,83:1 |
|
||||
-| Status / Werkzeuge | 7,33:1 | 7,75:1 |
|
||||
-| Auswahl | 21,00:1 | 21,00:1 |
|
||||
-| Linkfokus / Debugger | 13,29:1 | 12,97:1 |
|
||||
-| Breakpoint | 7,75:1 | 7,44:1 |
|
||||
-| Ausführung / Handle | 19,69:1 | 19,72:1 |
|
||||
+| Rolle | RGB-Kontrast |
|
||||
+|---|---|
|
||||
+| Code / Hilfelink | 5,72:1 |
|
||||
+| Aktiver Titel | 6,38:1 |
|
||||
+| Menü / Dialog / deaktivierter Text | 9,04:1 |
|
||||
+| Status / Werkzeuge | 7,33:1 |
|
||||
+| Auswahl | 21,00:1 |
|
||||
+| Linkfokus / Debugger | 13,29:1 |
|
||||
+| Breakpoint | 7,75:1 |
|
||||
+| Ausführung / Handle | 19,69:1 |
|
||||
|
||||
### Prüffolge für Change 05
|
||||
|
||||
@@ -188,10 +187,10 @@ Linux amd64/xterm, Linux amd64/VTE, Linux arm64/xterm und Linux arm64/VTE:
|
||||
Farbbeschriftungen und Handles; ForeColor/BackColor der Vorschau bleiben
|
||||
unabhängig vom IDE-Theme.
|
||||
6. Dieselben Ansichten mit absichtlich abweichender ANSI-Palette prüfen.
|
||||
- RGB-/256-Farben der IDE müssen stabil bleiben. Transparenz und
|
||||
+ RGB-Farben von IDE und BASIC-Ausgabe müssen stabil bleiben. Transparenz und
|
||||
Inaktivitätsdimmung getrennt ein-/ausschalten und Abweichungen als
|
||||
- Emulatorverhalten dokumentieren. Für 16-Farb-Fallback das tatsächlich
|
||||
- geeignete Profil und verbleibende Unterschiede festhalten.
|
||||
+ Emulatorverhalten dokumentieren. Auch ohne `COLORTERM`, mit `TERM=vt100`
|
||||
+ und mit `NO_COLOR=1` muss die Anwendung dieselben RGB-Werte ausgeben.
|
||||
7. Options ändern, speichern und neu starten; Auswahl muss erhalten sein.
|
||||
IDE beenden: globale Palette und normale Shell-Anzeige müssen erhalten sein.
|
||||
|
||||
diff --git a/openspec/changes/phase-6-05-plattformmatrix/design.md b/openspec/changes/phase-6-05-plattformmatrix/design.md
|
||||
index 22aa012..6e3fa4d 100644
|
||||
--- a/openspec/changes/phase-6-05-plattformmatrix/design.md
|
||||
+++ b/openspec/changes/phase-6-05-plattformmatrix/design.md
|
||||
@@ -19,6 +19,8 @@ Phase 5 verwendete crossterm-Ereignisse, ratatui-TestBackend und `tests/support/
|
||||
|
||||
7. Den ergänzenden Theme-Change 05a vor Abschluss der visuellen Matrix berücksichtigen. Dessen Referenzansichten und Kontrastprüfungen mit tatsächlicher Revision, Farbprofil und Standard-/abweichender ANSI-Palette in jeder Pflichtzelle prüfen; vor einer Theme-Korrektur erhobene betroffene Bilder erneut aufnehmen. Diese Nachweise gehen mit der bestehenden Matrix an 06/07.
|
||||
|
||||
+8. Benutzerbefund vom 07.09.2026: ANSI-/256-Fallback entfernen und die vorhandene Farbabbildung in tb-ui für IDE und BASIC gemeinsam nutzen. RGB-Ausgabe auch bei fehlenden Farbfähigkeitsvariablen und NO_COLOR erzwingen. Fenster vor Block/Paragraph leeren, da diese nur Stile setzen und sonst Desktopmuster oder verdeckte Texte durchscheinen. Regressionen prüfen tatsächliche Leerzeichen, Auswahl/Neuzeichnen, absolute Farbwerte und ausgegebene Escape-Sequenzen. Frühere visuelle Nachweise gelten nicht für diesen korrigierten Stand.
|
||||
+
|
||||
## Risks / Trade-offs
|
||||
|
||||
- CI ohne interaktiven Desktop → automatisierte Zieltests plus zugeordnete manuelle Emulatornachweise, keine Gleichsetzung beider Kategorien.
|
||||
diff --git a/openspec/changes/phase-6-05-plattformmatrix/proposal.md b/openspec/changes/phase-6-05-plattformmatrix/proposal.md
|
||||
index 0e2efa2..ca383fa 100644
|
||||
--- a/openspec/changes/phase-6-05-plattformmatrix/proposal.md
|
||||
+++ b/openspec/changes/phase-6-05-plattformmatrix/proposal.md
|
||||
@@ -18,7 +18,8 @@ Die bisherige headless Abnahme und der lokale Unix-PTY-Test beweisen nicht die e
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
-Keine. Bestehende IDE- und Host-Eingabeverträge bleiben maßgeblich.
|
||||
+- `ide-oberflaeche`: Durchgehend absolute RGB-Farben und vollständig geleerte Fensterflächen; Benutzerkorrektur vom 07.09.2026.
|
||||
+- `textbildschirm`: Dieselbe absolute DOS-RGB-Palette für programmbestimmte BASIC-Farben und Formularvorschau.
|
||||
|
||||
## Impact
|
||||
|
||||
diff --git a/openspec/changes/phase-6-05-plattformmatrix/tasks.md b/openspec/changes/phase-6-05-plattformmatrix/tasks.md
|
||||
index da2b71e..5ab64d7 100644
|
||||
--- a/openspec/changes/phase-6-05-plattformmatrix/tasks.md
|
||||
+++ b/openspec/changes/phase-6-05-plattformmatrix/tasks.md
|
||||
@@ -1,8 +1,8 @@
|
||||
## 1. Prüfpfade vorbereiten
|
||||
|
||||
-- [ ] 1.1 Verbindliche Matrix und kurze Bediensequenzen für die vier Targets anlegen; Windows Terminal, Terminal.app sowie xterm/VTE auf beiden Linux-Architekturen müssen konkrete Versions-/Revisionsfelder und erwartete Resultate besitzen.
|
||||
+- [x] 1.1 Verbindliche Matrix und kurze Bediensequenzen für die vier Targets anlegen; Windows Terminal, Terminal.app sowie xterm/VTE auf beiden Linux-Architekturen müssen konkrete Versions-/Revisionsfelder und erwartete Resultate besitzen.
|
||||
- [ ] 1.2 Bestehenden Unix-PTY-Test und passenden Windows-Konsolen-/ConPTY-Test für Shell, Abbruch und Wiederherstellung bereitstellen; positive Läufe und erzwungene Fehler dürfen keinen beschädigten Terminalmodus hinterlassen.
|
||||
-- [ ] 1.3 Die gemeinsame TBL-Verbraucherprobe aus 03 samt fester Prüfsumme in jede der vier Zielabnahmen aufnehmen (quellfreies TBC/EXE, RUN, tatsächliches Host-Target); IDE-/Programmprüfungen für F1–F12, Modifikatoren, Maus, Unicode/Attribute und Resize nachvollziehbar auflisten; jeder Fall muss sichtbaren Effekt und Ausschluss doppelter BASIC-Zustellung prüfen.
|
||||
+- [x] 1.3 Die gemeinsame TBL-Verbraucherprobe aus 03 samt fester Prüfsumme in jede der vier Zielabnahmen aufnehmen (quellfreies TBC/EXE, RUN, tatsächliches Host-Target); IDE-/Programmprüfungen für F1–F12, Modifikatoren, Maus, Unicode/Attribute und Resize nachvollziehbar auflisten; jeder Fall muss sichtbaren Effekt und Ausschluss doppelter BASIC-Zustellung prüfen.
|
||||
|
||||
## 2. Tatsächliche Zielabnahme
|
||||
|
||||
@@ -16,3 +16,11 @@
|
||||
|
||||
- [ ] 3.1 Terminalgrenzen und verifizierte Ersatzwege dokumentieren; kein Produktfehler oder fehlender Prüfrechner darf als bestandene Matrixzelle erscheinen.
|
||||
- [ ] 3.2 Automatisierbare Zielprüfungen an 06 übergeben und Matrixbericht fertigstellen; alle Pflichtzellen, Revisionen, vier Ergebnisse derselben TBL-Verbraucherprobe und tatsächlichen Ergebnisse müssen vor Abschluss vorliegen. Die weiterhin offenen Archivaufgaben 05a/1.2 (konkretes Benutzerprofil, frische/gespeicherte Optionen, Transparenz/Dimmung), 05a/3.2 (visuelle Matrix) und 05a/3.3 (befundfreie Schlussverifizierung) müssen hier tatsächlich abgeschlossen werden. Die visuellen Nachweise müssen das umgesetzte Theme aus 05a einschließlich Profil-/Farbmodus und relevanter UI-Zustände abdecken. Native Prüfsysteme dürfen separat vom zentralen Buildrunner betrieben und Nachweise dokumentiert manuell erhoben werden.
|
||||
+
|
||||
+Arbeitsstand 07.09.2026: Matrix/Bedienfolgen in `docs/plattformmatrix.md`, Eingabeprobe `tests/platform/input.frm`, gemeinsamer Aufruf `tests/support/platform-abnahme.py`. 1.2 ist implementiert und für Windows cross-geprüft, bleibt bis zum tatsächlichen Windows-Konsolenlauf offen. Automatisierte macOS-arm64-Nachweise liegen unter `evidence/2026-09-07-macos-arm64`; sie schließen keine manuelle Terminalzelle. Details und offene Befunde: `verification.md`.
|
||||
+
|
||||
+RGB-Korrektur nach Benutzerbefund vom 07.09.2026 gehört zu 2.5: keine
|
||||
+ANSI-/256-Fallbackfarben; gemeinsame feste RGB-Palette für IDE und BASIC;
|
||||
+Fensterflächen ohne durchscheinendes Desktopmuster. Neue Delta-Spezifikationen
|
||||
+in `ide-oberflaeche` und `textbildschirm` ersetzen den früheren Fallbackvertrag.
|
||||
+Die betroffene visuelle Zielprüfung bleibt bis zur echten Wiederholung offen.
|
||||
diff --git a/tests/support/ide-execution-pty.py b/tests/support/ide-execution-pty.py
|
||||
index b422070..ee369fa 100644
|
||||
--- a/tests/support/ide-execution-pty.py
|
||||
+++ b/tests/support/ide-execution-pty.py
|
||||
@@ -2,6 +2,7 @@
|
||||
"""Headless Unix PTY smoke: real terminal handoff, child Ctrl+C and IDE resume.
|
||||
Run after cargo build -p tb-ide: python3 tests/support/ide-execution-pty.py
|
||||
"""
|
||||
+import argparse
|
||||
import fcntl
|
||||
import os
|
||||
from pathlib import Path
|
||||
@@ -13,10 +14,10 @@ import tempfile
|
||||
import termios
|
||||
import time
|
||||
|
||||
-binary = Path(__file__).resolve().parents[2] / 'target/debug/tb'
|
||||
|
||||
|
||||
-def exercise(abort=False, file_shell=False):
|
||||
+
|
||||
+def exercise(binary, transcript_dir=None, abort=False, file_shell=False):
|
||||
with tempfile.TemporaryDirectory(prefix='tb-pty-') as directory:
|
||||
source = Path(directory) / 'main.bas'
|
||||
command = "printf '\\nWAITING_CHILD\\n'; exec sleep 30" if abort else "printf '\\nSHELL_PROOF\\n'; exit 7"
|
||||
@@ -32,7 +33,7 @@ def exercise(abort=False, file_shell=False):
|
||||
os.dup2(slave, fd)
|
||||
os.close(master)
|
||||
os.close(slave)
|
||||
- os.environ['TERM'] = 'xterm-256color'
|
||||
+ os.environ.setdefault('TERM', 'xterm-256color')
|
||||
os.environ['XDG_CONFIG_HOME'] = directory
|
||||
# Keep the controlling terminal alive while checking restoration.
|
||||
signal.signal(signal.SIGINT, lambda *_: None)
|
||||
@@ -83,7 +84,17 @@ def exercise(abort=False, file_shell=False):
|
||||
transcript.extend(os.read(master, 65536))
|
||||
assert transcript.count(b'?1049h') >= 2
|
||||
assert transcript.count(b'?1049l') >= 2
|
||||
+ # Tatsächliche Ausgabe muss auch bei NO_COLOR/fehlender Erkennung
|
||||
+ # dieselben absoluten IDE-Farben enthalten, ohne Palettenänderung.
|
||||
+ assert b'38;2;170;170;170' in transcript
|
||||
+ assert b'48;2;0;0;170' in transcript
|
||||
+ assert b'48;2;170;0;170' in transcript
|
||||
+ assert b'38;5;' not in transcript and b'48;5;' not in transcript
|
||||
+ assert b'\x1b]' not in transcript
|
||||
finally:
|
||||
+ if transcript_dir:
|
||||
+ name = 'file-shell' if file_shell else 'shell-abort' if abort else 'shell-exit'
|
||||
+ (transcript_dir / (name + '.ansi')).write_bytes(transcript)
|
||||
if not reaped:
|
||||
os.killpg(pid, signal.SIGKILL)
|
||||
os.waitpid(pid, 0)
|
||||
@@ -91,6 +102,18 @@ def exercise(abort=False, file_shell=False):
|
||||
os.close(slave)
|
||||
|
||||
|
||||
-for kwargs in ({}, {'abort': True}, {'file_shell': True}):
|
||||
- exercise(**kwargs)
|
||||
- print('PASS', kwargs or {'shell_exit': 7})
|
||||
+def main():
|
||||
+ parser = argparse.ArgumentParser(description=__doc__)
|
||||
+ parser.add_argument('--binary', type=Path, default=Path(__file__).resolve().parents[2] / 'target/debug/tb')
|
||||
+ parser.add_argument('--transcript-dir', type=Path)
|
||||
+ args = parser.parse_args()
|
||||
+ binary = args.binary.resolve(strict=True)
|
||||
+ if args.transcript_dir:
|
||||
+ args.transcript_dir.mkdir(parents=True, exist_ok=True)
|
||||
+ for kwargs in ({}, {'abort': True}, {'file_shell': True}):
|
||||
+ exercise(binary, args.transcript_dir, **kwargs)
|
||||
+ print('PASS', kwargs or {'shell_exit': 7})
|
||||
+
|
||||
+
|
||||
+if __name__ == '__main__':
|
||||
+ main()
|
||||
@@ -0,0 +1,899 @@
|
||||
Compiling tb-ui v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-ui)
|
||||
Compiling tb-vm v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-vm)
|
||||
Compiling tb-export v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-export)
|
||||
Compiling tb-runner v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-runner)
|
||||
Compiling tb-ide v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-ide)
|
||||
Compiling tb-cli v0.1.0 (/Users/gb/Projects/TerminalBasic/crates/tb-cli)
|
||||
Finished `test` profile [unoptimized + debuginfo] target(s) in 8.84s
|
||||
Running unittests src/main.rs (target/debug/deps/tbc-a3652d07eb423d84)
|
||||
|
||||
running 7 tests
|
||||
test ide_acceptance::real_native_ide_exports_and_source_free_cli_library_consumer ... ignored, Echter Zielnachweis: TB_IDE_RUNTIME_DIR muss geprüfte Host-tbrt-Vorlage enthalten
|
||||
test ide_acceptance::reference_matrix_is_complete_and_points_to_runnable_tests ... ok
|
||||
test ide_acceptance::function_keys_conflict_contexts_and_errors_keep_a_single_input_owner ... ok
|
||||
test ide_acceptance::partial_save_and_external_edit_recover_without_losing_documents ... ok
|
||||
test ide_acceptance::saved_project_ide_source_cli_and_tbc_have_identical_sessions ... ok
|
||||
test ide_acceptance::create_save_debug_help_exports_and_reopen ... ok
|
||||
test ide_acceptance::every_menu_command_has_native_keyboard_and_mouse_routing ... ok
|
||||
|
||||
test result: ok. 6 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 1.98s
|
||||
|
||||
Running tests/compat.rs (target/debug/deps/compat-f89983ce5e40f582)
|
||||
|
||||
running 18 tests
|
||||
test erzeuge_sollausgaben ... ignored, erzeugt Golden Files; nur bewusst aufrufen
|
||||
test uhr_direktive_wird_gelesen ... ok
|
||||
test zeilenanzahl_wird_benannt ... ok
|
||||
test fehlende_und_unerwartete_attributebene_werden_benannt ... ok
|
||||
test zeittrap_ohne_uhr_direktive_wird_abgewiesen - should panic ... ok
|
||||
test textabweichung_nennt_zeile_soll_und_ist ... ok
|
||||
test farbabweichung_nennt_zeile_spalte_soll_und_ist ... ok
|
||||
test ereignisfolge_liefert_taste_maus_und_zeit_in_reihenfolge ... ok
|
||||
test fehlende_groessenangabe_wird_abgewiesen ... ok
|
||||
test release_formular_vergleicht_zeichen_und_attribute_unabhaengig ... ok
|
||||
test prozessfrist::frist_beendet_blockierten_testprozess ... ok
|
||||
test tbc_build_erzeugt_tbc ... ok
|
||||
test tbc_run_hello ... ok
|
||||
test tbc_run_stop_exitcode ... ok
|
||||
test tbc_run_laufzeitfehler_exitcode ... ok
|
||||
test tbc_loest_include_projekt_und_run_datei_auf ... ok
|
||||
test tbc_isam_open_in_transaktion_hat_eine_harte_frist ... ok
|
||||
test korpus_laeuft_mit_korrekter_ausgabe ... ok
|
||||
|
||||
test result: ok. 17 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 1.56s
|
||||
|
||||
Running tests/convert_frm.rs (target/debug/deps/convert_frm-cba5b52e462e1f23)
|
||||
|
||||
running 1 test
|
||||
test conversion_failure_leaves_no_output ... ok
|
||||
|
||||
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
|
||||
|
||||
Running tests/foreign.rs (target/debug/deps/foreign-92ee6191b667aed6)
|
||||
|
||||
running 3 tests
|
||||
test oeffentliche_formularprogramme_sind_reproduzierbar_bedienbar ... ignored, TB_VBDOS_REPO muss auf cout/vbdos in der dokumentierten Revision zeigen
|
||||
test fehlender_oder_falscher_fremdbestand_wird_benannt ... ok
|
||||
test prozessfrist::frist_beendet_blockierten_testprozess ... ok
|
||||
|
||||
test result: ok. 2 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 0.11s
|
||||
|
||||
Running tests/inventar.rs (target/debug/deps/inventar-4656d211fa731f53)
|
||||
|
||||
running 17 tests
|
||||
test signatur_greift_ohne_laufzeitverhalten ... ok
|
||||
test bislang_signaturlose_elemente_haben_signaturen ... ok
|
||||
test dokumentierte_elemente_werden_namentlich_abgewiesen ... ok
|
||||
test offene_elemente_erzeugen_keinen_syntaxfehler ... ok
|
||||
test statusvokabular_ist_beschraenkt ... ok
|
||||
test offene_elemente_haben_keine_fundstelle ... ok
|
||||
test abdeckungsstand_wird_ausgewiesen ... ok
|
||||
test non_features_nennen_eine_fundstelle_in_der_sprachreferenz ... ok
|
||||
test implementiert_mit_unsupported_marker_faellt_durch ... ok
|
||||
test falscher_status_und_fehlende_runtimebindung_werden_namentlich_erkannt ... ok
|
||||
test falsch_gesetzte_eigenschaft_wird_erkannt ... ok
|
||||
test forms_inventar_stimmt_mit_der_klassentabelle_ueberein ... ok
|
||||
test forms_absenkung_muss_den_richtigen_member_erreichen ... ok
|
||||
test gemeinsam_dispatchte_konverter_brauchen_den_richtigen_typselektor ... ok
|
||||
test inventar_stimmt_mit_code_ueberein ... ok
|
||||
test jeder_inventareintrag_erreicht_hir_und_laufzeitziel ... ok
|
||||
test falsche_gueltige_builtinbindung_und_entfernte_absenkung_fallen_durch ... ok
|
||||
|
||||
test result: ok. 17 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.14s
|
||||
|
||||
Running tests/project.rs (target/debug/deps/project-af9c39c0e4caf174)
|
||||
|
||||
running 8 tests
|
||||
test designer_frm_is_accepted_by_the_standalone_cli_compiler ... ok
|
||||
test native_build_optionen_sind_explizit_und_tbc_bleibt_standard ... ok
|
||||
test release_projekt_prueft_anfangsdateien_dateieffekte_und_include_fehler ... ok
|
||||
test explicit_startup_order_and_form_selection_survive_tbc ... ok
|
||||
test cli_meldet_physische_quellorte_auch_nach_verschachtelten_includes ... ok
|
||||
test library_cli_links_without_sources_and_protects_all_inputs_and_outputs ... ok
|
||||
test projekt_und_formular_laufen_nach_entfernen_saemtlicher_quellen ... ok
|
||||
test erlaubte_grafik_und_benannte_nonfeatures_werden_per_cli_geprueft ... ok
|
||||
|
||||
test result: ok. 8 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.38s
|
||||
|
||||
Running unittests src/lib.rs (target/debug/deps/tb_export-740bf84213e12075)
|
||||
|
||||
running 3 tests
|
||||
test tests::fehlgeschlagene_native_finalisierung_erhaelt_das_ziel ... ok
|
||||
test tests::publication_preserves_originals_on_conflict_failure_race_and_cancel ... ok
|
||||
test tests::targets_versions_integrity_and_payload_bounds_are_enforced ... ok
|
||||
|
||||
test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.04s
|
||||
|
||||
Running unittests src/bin/tb-template.rs (target/debug/deps/tb_template-158083ae68069508)
|
||||
|
||||
running 0 tests
|
||||
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
|
||||
|
||||
Running unittests src/lib.rs (target/debug/deps/tb_frontend-668b07f10bc30f2a)
|
||||
|
||||
running 52 tests
|
||||
test lexer::tests::strings_mit_doppelten_anfuehrungszeichen ... ok
|
||||
test lexer::tests::zeilenfortsetzung ... ok
|
||||
test lexer::tests::bang_ist_suffix_oder_containeroperator_nach_folgetoken ... ok
|
||||
test lexer::tests::suffix_macht_keyword_zum_bezeichner ... ok
|
||||
test lexer::tests::bezeichner_mit_punkt_und_unterstrich ... ok
|
||||
test lexer::tests::keywords_case_insensitiv ... ok
|
||||
test parser::tests::operator_prioritaet ... ok
|
||||
test lexer::tests::kommentare_und_rem ... ok
|
||||
test parser::tests::forms_syntax ... ok
|
||||
test parser::tests::schleifen ... ok
|
||||
test lexer::tests::literal_typisierung ... ok
|
||||
test parser::tests::select_case ... ok
|
||||
test parser::tests::zuweisung_und_aufruf ... ok
|
||||
test parser::tests::print_varianten ... ok
|
||||
test parser::tests::prozeduren ... ok
|
||||
test parser::tests::if_block_und_einzeilig ... ok
|
||||
test parser::tests::fehlerbehandlung ... ok
|
||||
test parser::tests::typen_und_deklarationen ... ok
|
||||
test sema::tests::hir_select_wird_abgesenkt ... ok
|
||||
test sema::tests::hir_intdiv_rundet_operanden ... ok
|
||||
test sema::tests::hir_konvertierung_materialisiert ... ok
|
||||
test sema::tests::dreizeiler_wird_namentlich_statt_falsch_abgewiesen ... ok
|
||||
test sema::tests::datei_ea_und_events ... ok
|
||||
test sema::tests::deftype_regeln ... ok
|
||||
test sema::tests::funktionsaufruf_und_rueckgabe ... ok
|
||||
test sema::tests::hir_byref_und_byval ... ok
|
||||
test sema::tests::def_fn_blockform ... ok
|
||||
test sema::tests::argumentanzahl ... ok
|
||||
test sema::tests::byref_verlangt_exakten_typ ... ok
|
||||
test sema::tests::hardware_features_zur_compilezeit_abgelehnt ... ok
|
||||
test sema::tests::arrays_implizit_und_explizit ... ok
|
||||
test sema::tests::dialoge_listindex_und_zeichenmessung_werden_abgesenkt ... ok
|
||||
test sema::tests::ereignisprozedur_signatur_und_normale_unterstrich_sub ... ok
|
||||
test sema::tests::hir_slots_aufgeloest ... ok
|
||||
test sema::tests::createindex_ohne_obergrenze_der_spaltenzahl ... ok
|
||||
test sema::tests::isam_argumentanzahl_nennt_das_element ... ok
|
||||
test sema::tests::isam_anweisung_parst_ohne_diagnose ... ok
|
||||
test sema::tests::builtins_typen ... ok
|
||||
test sema::tests::konstantenfaltung ... ok
|
||||
test sema::tests::label_pruefung ... ok
|
||||
test sema::tests::mid_anweisung ... ok
|
||||
test sema::tests::option_explicit ... ok
|
||||
test sema::tests::eigenschaftstyp_schreibbarkeit_bang_und_hir_index ... ok
|
||||
test sema::tests::rollback_all_wird_als_sentinel_abgesenkt ... ok
|
||||
test sema::tests::isam_satzargument_wird_typgeprueft ... ok
|
||||
test sema::tests::typeof_form_control_und_form_metabefehl ... ok
|
||||
test sema::tests::objektpfade_werden_namentlich_geprueft_und_udt_bleibt_unveraendert ... ok
|
||||
test sema::tests::typkonflikt_wird_erkannt ... ok
|
||||
test sema::tests::unbekanntes_unterprogramm ... ok
|
||||
test sema::tests::shared_und_common ... ok
|
||||
test sema::tests::kein_isam_element_ist_unbekannter_bezeichner ... ok
|
||||
test sema::tests::udt_feldtypen ... ok
|
||||
|
||||
test result: ok. 52 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
|
||||
|
||||
Running tests/corpus.rs (target/debug/deps/corpus-0371f2991a3b061a)
|
||||
|
||||
running 1 test
|
||||
test korpus_parst_und_wird_typgeprueft ... ok
|
||||
|
||||
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s
|
||||
|
||||
Running tests/editing.rs (target/debug/deps/editing-01467d91310d70f2)
|
||||
|
||||
running 4 tests
|
||||
test incomplete_is_parser_context_not_a_second_grammar ... ok
|
||||
test normalization_protects_tokens_and_is_idempotent ... ok
|
||||
test deftype_context_does_not_leak_from_another_procedure ... ok
|
||||
test declaration_maintenance_and_procedure_generation_are_transactional ... ok
|
||||
|
||||
test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
|
||||
|
||||
Running unittests src/lib.rs (target/debug/deps/tb_ide-43621e6718da8b87)
|
||||
|
||||
running 3 tests
|
||||
test export::tests::delayed_result_is_published_only_after_ui_validation_and_success_stays_success ... ok
|
||||
test export::tests::replaced_library_invalidates_pending_export_even_with_same_length ... ok
|
||||
test export::tests::cancelled_superseded_changed_and_foreign_jobs_never_publish ... ok
|
||||
|
||||
test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.04s
|
||||
|
||||
Running unittests src/main.rs (target/debug/deps/tb-f285a33b6fdb6251)
|
||||
|
||||
running 0 tests
|
||||
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
|
||||
|
||||
Running tests/app.rs (target/debug/deps/app-d3d6e33413d63d0f)
|
||||
|
||||
running 20 tests
|
||||
test theme_color_commands_use_explicit_values_and_never_modify_terminal_palette ... ok
|
||||
test executable_target_validation_and_missing_template_are_honest ... ok
|
||||
test start_snapshot_and_reference_menus_have_all_commands ... ok
|
||||
test dispatcher_keeps_function_keys_and_copy_out_of_basic_input ... ok
|
||||
test designer_form_list_and_context_availability_match_the_active_window ... ok
|
||||
test windows_restore_geometry_and_resize_without_document_loss ... ok
|
||||
test theme_windows_erase_desktop_and_underlying_windows_on_every_redraw ... ok
|
||||
test modal_focus_and_dirty_project_cancel_preserve_document ... ok
|
||||
test options_apply_persist_across_bases_and_preserve_unsaved_values_on_error ... ok
|
||||
test clicking_project_members_and_dialog_choices_transfers_focus_and_applies_values ... ok
|
||||
test theme_designer_chrome_and_handles_preserve_program_palette ... ok
|
||||
test status_and_project_buttons_use_the_keyboard_command_path ... ok
|
||||
test mouse_focus_is_modal_and_program_abort_is_not_editor_copy ... ok
|
||||
test debugger_reports_absent_library_source_and_can_step_back_to_caller ... ok
|
||||
test file_picker_save_conflict_and_project_replacement_use_real_events ... ok
|
||||
test finalization_failure_is_reported_and_preserves_existing_output ... ok
|
||||
test exit_with_partial_save_retains_dialog_and_unsaved_documents ... ok
|
||||
test real_library_export_uses_dirty_include_and_mouse_without_runtime_template ... ok
|
||||
test export_dialogs_validate_and_render_all_results_without_creating_files ... ok
|
||||
test theme_contrast_covers_rendered_states_and_rejects_bad_pairs ... ok
|
||||
|
||||
test result: ok. 20 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.41s
|
||||
|
||||
Running tests/debugger.rs (target/debug/deps/debugger-18aeee8ea147e9f4)
|
||||
|
||||
running 6 tests
|
||||
test form_handler_keys_and_old_revision_cursor_guard ... ok
|
||||
test immediate_wait_run_transition_watchpoint_and_trace_are_session_owned ... ok
|
||||
test includes_and_deleted_marks_do_not_bind_to_foreign_statements ... ok
|
||||
test dispatcher_marks_edits_rebind_and_readonly_watches ... ok
|
||||
test calls_procedure_step_cursor_history_and_restart ... ok
|
||||
test calls_mouse_inspection_instant_key_delete_and_error_window ... ok
|
||||
|
||||
test result: ok. 6 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.02s
|
||||
|
||||
Running tests/designer.rs (target/debug/deps/designer-1f0dd9e883e87225)
|
||||
|
||||
running 18 tests
|
||||
test menu_indent_outdent_rename_and_field_changes_have_one_undo ... ok
|
||||
test property_bar_types_readonly_and_no_status_line ... ok
|
||||
test imported_type_shadow_is_not_an_object_reference_during_rename ... ok
|
||||
test clipboard_children_arrays_and_delete_preserve_code ... ok
|
||||
test binary_designer_import_requires_text_target_and_compiles ... ok
|
||||
test event_array_signature_twice_and_shared_form_identity ... ok
|
||||
test bound_rename_across_documents_is_atomic_and_undo_restores_all ... ok
|
||||
test container_multiselect_keyboard_drag_resize_and_undo ... ok
|
||||
test toolbox_double_click_tool_drag_grid_and_window_form_selection ... ok
|
||||
test menu_hierarchy_arrays_shortcuts_and_palette_use_events ... ok
|
||||
test rename_preserves_shadowed_names_and_handles_form_aliases_and_include_calls ... ok
|
||||
test indexed_controls_merge_atomically_with_bindings_and_undo ... ok
|
||||
test events_with_the_same_name_are_local_to_their_form ... ok
|
||||
test shared_include_ambiguity_aborts_rename_and_event_defaults_use_includes ... ok
|
||||
test property_menu_buttons_palette_drag_and_modal_mouse_are_connected ... ok
|
||||
test all_metadata_tools_persist_and_preview_matches_runtime_without_events ... ok
|
||||
test all_eight_handles_resize_transactionally_and_preserve_identity_after_structure_edits ... ok
|
||||
test existing_default_typed_event_and_all_metadata_signatures_compile ... ok
|
||||
|
||||
test result: ok. 18 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.06s
|
||||
|
||||
Running tests/documents.rs (target/debug/deps/documents-6a65482da983e004)
|
||||
|
||||
running 15 tests
|
||||
test unrepresentable_save_paths_fail_before_writing_or_changing_documents ... ok
|
||||
test save_plan_prevents_same_destination_and_project_overwrite ... ok
|
||||
test shared_views_text_import_and_undo_are_document_transactions ... ok
|
||||
test failed_open_add_and_cancel_do_not_replace_existing_documents ... ok
|
||||
test aliases_share_documents_and_form_code_offsets_match_saved_text ... ok
|
||||
test binary_import_only_saves_to_explicit_text_target_and_preserves_original_forever ... ok
|
||||
test edited_include_wins_in_both_modules_without_writing_the_expansion ... ok
|
||||
test startup_removal_requires_explicit_replacement_and_never_deletes_a_file ... ok
|
||||
test libraries_are_binary_members_with_relative_save_as_and_no_source_views ... ok
|
||||
test project_save_as_rebases_members_and_keeps_include_targets ... ok
|
||||
test external_changes_and_save_as_collisions_need_explicit_decisions ... ok
|
||||
test module_save_as_rebases_includes_and_failed_save_does_not_change_identity_or_text ... ok
|
||||
test cursor_after_shortening_uses_original_position_and_open_after_save_uses_fresh_disk ... ok
|
||||
test partial_save_preserves_unsaved_data_and_does_not_finish_close ... ok
|
||||
test project_create_save_reopen_preserves_forms_members_startup_and_cli_sources ... ok
|
||||
|
||||
test result: ok. 15 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.09s
|
||||
|
||||
Running tests/editor.rs (target/debug/deps/editor-b6dc665e95525030)
|
||||
|
||||
running 7 tests
|
||||
test search_scope_direction_wrap_and_shortening_replace_all ... ok
|
||||
test crlf_navigation_word_boundaries_readonly_and_normalization_keep_views ... ok
|
||||
test cua_unicode_overwrite_wordstar_and_shared_undo ... ok
|
||||
test line_leave_incomplete_invalid_disabled_and_current_revisions ... ok
|
||||
test includes_and_diagnostic_selection_use_original_physical_files ... ok
|
||||
test procedures_and_shared_save_hook_preserve_drafts_and_frm_code ... ok
|
||||
test external_include_revision_and_project_context_declarations ... ok
|
||||
|
||||
test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.04s
|
||||
|
||||
Running tests/execution.rs (target/debug/deps/execution-bf913fdae7aacbc3)
|
||||
|
||||
running 13 tests
|
||||
test shell_request_is_resumed_once_and_error_is_basic_error ... ok
|
||||
test named_run_of_current_target_uses_edited_sources ... ok
|
||||
test comment_only_source_change_also_requires_revision_choice ... ok
|
||||
test ide_and_cli_run_wrapper_match_input_time_and_forms_script ... ok
|
||||
test f5_input_pause_copy_and_single_delivery_keep_the_same_vm ... ok
|
||||
test output_viewports_resize_and_end_preserve_buffer_and_basic_colors ... ok
|
||||
test print_uses_utf8_protected_output_and_does_not_mutate_source ... ok
|
||||
test changed_paused_source_requires_explicit_old_revision_or_restart ... ok
|
||||
test explicit_end_and_system_end_visible_forms_but_natural_end_keeps_them_live ... ok
|
||||
test restart_command_run_targets_and_missing_target_preserve_documents ... ok
|
||||
test restart_drops_files_data_traps_and_queued_actions ... ok
|
||||
test startup_selection_matches_shared_cli_pipeline_and_legacy_mak ... ok
|
||||
test platform_probe_records_each_basic_key_once_and_keeps_ide_keys_out ... ok
|
||||
|
||||
test result: ok. 13 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.06s
|
||||
|
||||
Running tests/help.rs (target/debug/deps/help-ff16d5fb3c397804)
|
||||
|
||||
running 11 tests
|
||||
test offline_help_child ... ok
|
||||
test markdown_blocks_escapes_links_and_unicode_layout ... ok
|
||||
|
||||
running 1 test
|
||||
test catalog_links_and_missing_targets_are_checked ... ok
|
||||
test right_click_configuration_and_external_link_follow ... ok
|
||||
test links_history_resize_scroll_and_focus_use_real_events ... ok
|
||||
test every_command_and_forms_alias_resolves_and_invalid_alias_fails ... ok
|
||||
test twenty_back_steps_end_of_contents_and_all_entries ... ok
|
||||
test offline_help_child ... ok
|
||||
|
||||
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 10 filtered out; finished in 0.07s
|
||||
|
||||
test help_works_from_a_directory_without_checkout ... ok
|
||||
test help_preserves_fullscreen_and_does_not_modify_designer_or_source ... ok
|
||||
test context_functions_properties_commands_and_unknown_queries ... ok
|
||||
test code_and_tables_remain_reachable_after_resize_and_horizontal_scroll ... ok
|
||||
|
||||
test result: ok. 11 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.14s
|
||||
|
||||
Running unittests src/lib.rs (target/debug/deps/tb_runner-d3339a5a0df9c7dd)
|
||||
|
||||
running 0 tests
|
||||
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
|
||||
|
||||
Running unittests src/bin/tbrt.rs (target/debug/deps/tbrt-a6c3f62502f5f188)
|
||||
|
||||
running 0 tests
|
||||
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
|
||||
|
||||
Running unittests src/lib.rs (target/debug/deps/tb_runtime-6b2bc969f5367a62)
|
||||
|
||||
running 140 tests
|
||||
test builtins::tests::benutzertaste_ueber_key_anweisung ... ok
|
||||
test builtins::tests::nicht_getrappte_taste_bleibt_im_strom ... ok
|
||||
test builtins::tests::getrappte_taste_verlaesst_den_eingabestrom ... ok
|
||||
test builtins::tests::off_wirkt_auf_bereits_wartende_tasten ... ok
|
||||
test builtins::tests::input_s_dispatch_bewahrt_codepointreste_auch_ohne_vm ... ok
|
||||
test builtins::tests::signal_aus_dem_host_meldet_den_trap ... ok
|
||||
test builtins::tests::zonenquelle_ausfall_und_erholung_gelten_fuer_alle_zeitfunktionen ... ok
|
||||
test builtins::tests::benutzertaste_ohne_umschalt_bleibt_im_strom ... ok
|
||||
test builtins::tests::builtin_ueber_tabelle ... ok
|
||||
test builtins::tests::signal_stop_merkt_beide_quellen_und_off_verwirft ... ok
|
||||
test console::tests::volle_zone_springt_zur_uebernaechsten ... ok
|
||||
test console::tests::druckzone_folgt_dem_cursor_nach_locate ... ok
|
||||
test builtins::tests::key_stop_merkt_einmal_und_laesst_alle_tasten_auch_nach_on_lesbar ... ok
|
||||
test builtins::tests::mausereignisse_haeufen_sich_nicht_an ... ok
|
||||
test builtins::tests::sigint_ohne_aktiven_trap_bleibt_abbruch ... ok
|
||||
test console::tests::druckzonen ... ok
|
||||
test builtins::tests::setuevent_meldet_das_benutzerereignis ... ok
|
||||
test builtins::tests::stringfunktionen_randfaelle ... ok
|
||||
test console::tests::zahlen_mit_vorzeichenspalte ... ok
|
||||
test datetime::tests::fester_versatz_verschiebt_genau ... ok
|
||||
test datetime::tests::gueltigkeitspruefung ... ok
|
||||
test datetime::tests::programmversatz_kommt_hinzu ... ok
|
||||
test datetime::tests::serienwert_und_rueckumwandlung ... ok
|
||||
test datetime::tests::tageszeit ... ok
|
||||
test datetime::tests::text_in_serienwert ... ok
|
||||
test datetime::tests::wochentag_sonntag_ist_eins ... ok
|
||||
test datetime::tests::zaehlweise_des_vorbilds ... ok
|
||||
test errors::tests::bekannte_codes ... ok
|
||||
test errors::tests::forms_und_isam_codes ... ok
|
||||
test errors::tests::unbelegte_codes_sind_unprintable ... ok
|
||||
test fileio::tests::felder_einer_input_zeile ... ok
|
||||
test fileio::tests::modus_aus_kurzsyntax ... ok
|
||||
test fileio::tests::muster_mit_stern_und_fragezeichen ... ok
|
||||
test finanz::tests::abschreibungen ... ok
|
||||
test finanz::tests::barwert_und_endwert_sind_gegenlaeufig ... ok
|
||||
test fileio::tests::festes_feld_ist_inhaltsunabhaengig_gleich_lang ... ok
|
||||
test fileio::tests::rset_schneidet_ab_und_richtet_rechts_aus ... ok
|
||||
test finanz::tests::endwert_einer_rentenzahlung ... ok
|
||||
test finanz::tests::irr_ohne_vorzeichenwechsel_ist_fehler ... ok
|
||||
test finanz::tests::kapitalwert_und_interner_zinsfuss ... ok
|
||||
test finanz::tests::mirr_liegt_zwischen_den_zinsen ... ok
|
||||
test finanz::tests::nper_zaehlt_die_perioden ... ok
|
||||
test finanz::tests::ungueltige_argumente ... ok
|
||||
test finanz::tests::zins_und_tilgung_ergeben_die_zahlung ... ok
|
||||
test finanz::tests::zinssatz_wird_zurueckgerechnet ... ok
|
||||
test format::tests::currency_darstellung ... ok
|
||||
test format::tests::double_darstellung ... ok
|
||||
test format::tests::ganzzahlen ... ok
|
||||
test format::tests::single_darstellung ... ok
|
||||
test format::tests::val_parsen ... ok
|
||||
test host::tests::capture_host_haelt_zeichen_und_attribut ... ok
|
||||
test host::tests::maus_und_tasten_behalten_ihre_reihenfolge ... ok
|
||||
test host::tests::virtuelle_uhr_laeuft_nur_wenn_gestellt ... ok
|
||||
test host::tests::vorbereitete_zeile_wird_zu_tasten ... ok
|
||||
test isam::tests::absteigende_spalte_kehrt_die_ordnung_um ... ok
|
||||
test host::tests::groessenaenderung_und_abbruch_als_ereignis ... ok
|
||||
test host::tests::verzoegertes_ereignis_kommt_nach_der_anzeige ... ok
|
||||
test isam::tests::nullbyte_im_text_stoert_den_abschluss_nicht ... ok
|
||||
test isam::tests::praefix_ende_zaehlt_hoch ... ok
|
||||
test isam::tests::beschaedigte_datei_meldet_fehler_88 ... ok
|
||||
test datetime::tests::versatz_liegt_im_gueltigen_bereich ... ok
|
||||
test datetime::tests::versatz_gilt_je_zeitpunkt ... ok
|
||||
test isam::tests::kodierung_erhaelt_die_ordnung_bei_zufallspaaren ... ok
|
||||
test isam::tests::prozessfrist::frist_beendet_blockierten_testprozess ... ok
|
||||
test isam::tests::close_beendet_keine_transaktion ... ok
|
||||
test isam::tests::jede_satzoperation_erzeugt_einen_protokolleintrag ... ok
|
||||
test isam::tests::textabschluss_ordnet_praefix_vor_laengerem_text ... ok
|
||||
test isam::tests::neue_tabellen_und_aktive_indizes_verschwinden_bei_ruecknahme ... ok
|
||||
test isam::tests::ungueltige_namen_werden_abgewiesen ... ok
|
||||
test isam::tests::ohne_transaktion_kein_protokoll ... ok
|
||||
test screen::tests::blink_wird_als_hell_simuliert ... ok
|
||||
test isam::tests::saetze_nach_close_aller_bindungen_zuruecknehmen ... ok
|
||||
test screen::tests::breites_zeichen_am_rechten_rand_bricht_ganz_um ... ok
|
||||
test isam::tests::pfadaliase_teilen_transaktion_und_ruecknahme ... ok
|
||||
test isam::tests::cursor_ueberlebt_eine_satzaenderung ... ok
|
||||
test screen::tests::breites_zeichen_belegt_zwei_zellen ... ok
|
||||
test isam::tests::geloeschte_satz_id_wird_nicht_neu_vergeben ... ok
|
||||
test isam::tests::deletetable_loest_alle_betroffenen_bindungen ... ok
|
||||
test isam::tests::gescheitertes_createindex_hinterlaesst_keinen_index ... ok
|
||||
test screen::tests::dynamische_groesse_und_resize ... ok
|
||||
test isam::tests::satz_roundtrip_ueber_alle_feldtypen ... ok
|
||||
test screen::tests::locate_auf_fortsetzung_trifft_den_zeichenanfang ... ok
|
||||
test isam::tests::delete_pufferfehler_erhaelt_saetze_indizes_und_cursor ... ok
|
||||
test isam::tests::nicht_festgeschriebene_transaktion_verfaellt ... ok
|
||||
test screen::tests::locate_prueft_grenzen ... ok
|
||||
test screen::tests::print_schreibt_und_bewegt_cursor ... ok
|
||||
test isam::tests::indexeintraege_stehen_in_schluesselreihenfolge ... ok
|
||||
test isam::tests::struktur_undo_prueft_puffer_vor_dem_loeschen ... ok
|
||||
test screen::tests::resize_folgt_vollem_scrollbereich ... ok
|
||||
test isam::tests::hoehere_formatversion_wird_abgewiesen ... ok
|
||||
test screen::tests::rueckschritt_loescht_ein_breites_zeichen_ganz ... ok
|
||||
test screen::tests::resize_klemmt_nur_den_unteren_rand_wenn_der_bereich_bleibt ... ok
|
||||
test screen::tests::resize_klemmt_cursor_und_scrollbereich ... ok
|
||||
test screen::tests::scrollen_am_unteren_rand ... ok
|
||||
test screen::tests::ueberschreiben_einer_haelfte_leert_die_andere ... ok
|
||||
test screen::tests::ui_zeile_bleibt_am_rand_ohne_umbruch_oder_scrollen ... ok
|
||||
test screen::tests::umbruch_am_rechten_rand ... ok
|
||||
test screen::tests::unicode_zeichen_belegen_eine_zelle ... ok
|
||||
test screen::tests::view_print_begrenzt_scrollen ... ok
|
||||
test snapshot::tests::breites_zeichen_erscheint_einmal ... ok
|
||||
test snapshot::tests::getrimmt_auf_die_belegte_flaeche ... ok
|
||||
test snapshot::tests::leerer_bildschirm_ergibt_leeren_snapshot ... ok
|
||||
test snapshot::tests::locate_erweitert_die_flaeche ... ok
|
||||
test snapshot::tests::mit_farben_kommt_die_attributebene ... ok
|
||||
test snapshot::tests::nachgestellte_leerzeichen_bleiben_erhalten ... ok
|
||||
test snapshot::tests::ohne_farben_keine_attributebene ... ok
|
||||
test traps::tests::aus_verwirft_auch_das_gemerkte ... ok
|
||||
test traps::tests::aus_verwirft_kuenftige ... ok
|
||||
test traps::tests::beide_umschaltbits_gelten_gleich ... ok
|
||||
test traps::tests::benutzertaste_braucht_umschaltzustand_und_scancode ... ok
|
||||
test traps::tests::event_off_verwirft_ereignisse_und_laesst_die_zustaende ... ok
|
||||
test traps::tests::genauer_trap_geht_dem_sammeltrap_vor ... ok
|
||||
test traps::tests::gestoppt_merkt_genau_eines ... ok
|
||||
test traps::tests::gosub_null_schaltet_den_trap_ab ... ok
|
||||
test traps::tests::kein_wiedereintritt_waehrend_der_handler_laeuft ... ok
|
||||
test traps::tests::key_null_faengt_alle_tasten_der_tabelle ... ok
|
||||
test traps::tests::off_im_handler_ueberlebt_das_return ... ok
|
||||
test traps::tests::ohne_trap_kostet_nichts ... ok
|
||||
test traps::tests::reihenfolge_key_vor_timer_vor_uevent_vor_signal ... ok
|
||||
test traps::tests::return_schaltet_sonst_selbsttaetig_ein ... ok
|
||||
test traps::tests::uebersprungene_fristen_zaehlen_als_eine ... ok
|
||||
test traps::tests::vordefinierte_taste_wird_ueber_den_scancode_erkannt ... ok
|
||||
test traps::tests::zeit_wird_erst_nach_der_frist_faellig ... ok
|
||||
test using::tests::exponentialform ... ok
|
||||
test using::tests::feldueberlauf_bekommt_prozentzeichen ... ok
|
||||
test using::tests::format_wird_wiederverwendet ... ok
|
||||
test using::tests::literale_und_unterstrich ... ok
|
||||
test using::tests::numerisches_feld_mit_nachkommastellen ... ok
|
||||
test using::tests::ohne_feld_aber_mit_werten_ist_fehler_5 ... ok
|
||||
test using::tests::ohne_feld_und_ohne_werte_bleibt_der_text ... ok
|
||||
test using::tests::stringfelder ... ok
|
||||
test using::tests::tausendertrennung ... ok
|
||||
test using::tests::vorzeichenfuehrung ... ok
|
||||
test using::tests::waehrung_und_sterne ... ok
|
||||
test value::tests::array_indexpruefung ... ok
|
||||
test value::tests::banker_rounding ... ok
|
||||
test value::tests::currency_rundung ... ok
|
||||
test value::tests::overflow_bei_konvertierung ... ok
|
||||
test isam::tests::savepoints_nehmen_index_und_tabellenstrukturen_zurueck ... ok
|
||||
test isam::tests::symlink_neuanlage_behaelt_die_dateiidentitaet ... ok
|
||||
|
||||
test result: ok. 140 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.56s
|
||||
|
||||
Running unittests src/lib.rs (target/debug/deps/tb_ui-95ce53373c09fcd8)
|
||||
|
||||
running 66 tests
|
||||
test forms::tests::hide_entlaedt_nicht_und_unload_ist_abbrechbar ... ok
|
||||
test forms::tests::optionen_gruppieren_nach_unmittelbarem_container ... ok
|
||||
test forms::tests::screen_folgt_resize ... ok
|
||||
test forms::tests::menuregeln_weisen_separator_und_titel_shortcuts_ab ... ok
|
||||
test forms::tests::combobox_dropdown_closes_on_focus_change_and_hide ... ok
|
||||
test forms::tests::gleichzeitig_faellige_timer_laufen_nach_name ... ok
|
||||
test forms::tests::fokus_tab_access_default_und_eingabeprioritaet ... ok
|
||||
test forms::tests::screen_meldet_oberstes_formular_und_aktives_control ... ok
|
||||
test forms::tests::modalfehler_400_bis_403 ... ok
|
||||
test forms::tests::menues_zeichnen_und_navigieren_sechs_ebenen ... ok
|
||||
test forms::tests::defaults_bereich_und_implizites_laden ... ok
|
||||
test forms::tests::arrays_und_designzeitfehler ... ok
|
||||
test forms::tests::freier_formularklick_und_doppelklick_werden_zugestellt ... ok
|
||||
test forms::tests::simple_combo_zeichnet_listeninhalt_auswahl_und_begrenzung ... ok
|
||||
test forms::tests::indexed_containers_preserve_parent_geometry_and_option_groups ... ok
|
||||
test forms::tests::spin_zaehlt_zyklisch_und_wiederholt_nach_interval ... ok
|
||||
test frm::tests::binary_layout_preserves_arrays_and_container_hierarchy ... ok
|
||||
test forms::tests::timerarrays_holen_nur_aktive_zeit_nach_und_sortieren_nach_name_und_index ... ok
|
||||
test frm::tests::binary_class_specific_properties_match_the_reference_exports ... ok
|
||||
test forms::tests::zeichenbilder_aller_klassen_und_buttonhoehen ... ok
|
||||
test forms::tests::timer_neustart_verwirft_alte_fristen_und_ereignisse ... ok
|
||||
test frm::tests::binary_strings_are_decoded_from_cp437 ... ok
|
||||
test forms::tests::listenauswahl_bleibt_beim_einfuegen_und_entfernen_konsistent ... ok
|
||||
test frm::tests::binary_reader_rejects_magic_and_unknown_structure_with_offset ... ok
|
||||
test frm::tests::binary_reader_rejects_out_of_range_property_with_offset ... ok
|
||||
test frm::tests::reads_nested_form_and_preserves_source_exactly ... ok
|
||||
test frm::tests::binary_strings_and_header_flags_map_to_the_named_properties ... ok
|
||||
test frm::tests::spin_symbol_wird_als_bedienbares_control_erkannt ... ok
|
||||
test frm::tests::text_form_control_arrays_share_one_catalog_object_and_keep_indices ... ok
|
||||
test frm::tests::unsupported_binary_property_is_named_and_unclaimed_strings_still_fail ... ok
|
||||
test frm::tests::writes_read_only_boolean_only_when_it_differs_from_false ... ok
|
||||
test frm::tests::writes_no_properties_for_default_only_control ... ok
|
||||
test frm::tests::writes_documented_d1_and_roundtrips_description ... ok
|
||||
test frm::tests::rejects_version_class_property_value_and_open_block_with_location ... ok
|
||||
test frm::tests::explicit_default_is_preserved_until_canonical_write ... ok
|
||||
test frm_pcode::tests::decodes_defint_and_vbdos_isam_tokens ... ok
|
||||
test frm_pcode::tests::decodes_vbdos_declarations_without_losing_type_or_bounds ... ok
|
||||
test frm_pcode::tests::embedded_include_is_a_comment_but_literals_remain_unchanged ... ok
|
||||
test frm::tests::canonical_index_zero_remains_an_array_and_array_parents_are_preserved ... ok
|
||||
test frm::tests::unsupported_custom_control_is_named_and_not_emitted_as_screen ... ok
|
||||
test frm_pcode::tests::next_trennt_eine_vorangehende_anweisung_auch_ohne_newline_token ... ok
|
||||
test host::tests::ausserhalb_der_flaeche_wird_verworfen ... ok
|
||||
test frm_pcode::tests::resets_block_local_default_types_before_the_next_block ... ok
|
||||
test host::tests::backtab_ist_tab_mit_shift_auch_ohne_modifier ... ok
|
||||
test frm::tests::reads_real_vbdos_form_with_complete_documented_description ... ok
|
||||
test host::tests::letzte_zelle_liegt_noch_drin ... ok
|
||||
test host::tests::maus_zaehlt_ab_eins ... ok
|
||||
test host::tests::nach_groessenaenderung_gilt_die_neue_flaeche ... ok
|
||||
test forms::tests::forms_dialoge_liefern_gruppen_eingabe_und_feste_groesse ... ok
|
||||
test host::tests::rollrad_hat_keine_entsprechung ... ok
|
||||
test host::tests::sondertaste_traegt_fuehrendes_nullzeichen ... ok
|
||||
test host::tests::strg_c_ist_abbruch ... ok
|
||||
test forms::tests::tabfolge_ueberspringt_und_laeuft_rueckwaerts ... ok
|
||||
test host::tests::umschaltzustand_als_bitfeld ... ok
|
||||
test host::tests::umschaltzustand_der_taste_wird_mitgefuehrt ... ok
|
||||
test host::tests::zeichentaste_wird_zu_inkey_form ... ok
|
||||
test screen::tests::farbabbildung ... ok
|
||||
test signale::tests::marke_wird_zu_kennung_und_verfaellt_danach ... ok
|
||||
test signale::tests::sigint_hat_vorrang_vor_sigterm ... ok
|
||||
test signale::tests::echtes_signal_setzt_die_marke ... ok
|
||||
test forms::tests::z_reihenfolge_dragdrop_und_timerreihenfolge ... ok
|
||||
test forms::tests::text_liste_option_scroll_picture_und_dateisystem ... ok
|
||||
test forms::tests::sorted_wechsel_erhaelt_auch_die_auswahl_zwischen_duplikaten ... ok
|
||||
test forms::tests::zustandsfarben_laufen_fuer_alle_controls_ueber_denselben_zeichenpfad ... ok
|
||||
test terminal::tests::terminal_cleanup_on_normal_error_and_partial_initialization ... ok
|
||||
test forms::tests::listenrenderer_haelt_zellgrenzen_auch_an_bildschirmraendern_ein ... ok
|
||||
|
||||
test result: ok. 66 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.61s
|
||||
|
||||
Running unittests src/lib.rs (target/debug/deps/tb_vm-2a4538183acbb98c)
|
||||
|
||||
running 16 tests
|
||||
test codegen::tests::fehlerbehandlung_emit ... ok
|
||||
test codegen::tests::string_konkatenation ... ok
|
||||
test codegen::tests::vergleich_und_logik ... ok
|
||||
test codegen::tests::arrays_dim_und_zugriff ... ok
|
||||
test bytecode::tests::instr_roundtrip ... ok
|
||||
test codegen::tests::data_read_restore ... ok
|
||||
test codegen::tests::tbc_roundtrip_ueber_codegen ... ok
|
||||
test bytecode::tests::unbekannte_version_wird_abgelehnt ... ok
|
||||
test bytecode::tests::tbc_roundtrip ... ok
|
||||
test codegen::tests::ausdruck_monomorph_mit_conv ... ok
|
||||
test codegen::tests::gosub_und_on_goto ... ok
|
||||
test codegen::tests::for_mit_dynamischem_step ... ok
|
||||
test codegen::tests::if_mit_fixup ... ok
|
||||
test codegen::tests::prozedur_und_byref ... ok
|
||||
test codegen::tests::for_mit_konstantem_step ... ok
|
||||
test codegen::tests::function_liefert_wert ... ok
|
||||
|
||||
test result: ok. 16 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
|
||||
|
||||
Running tests/cooperative.rs (target/debug/deps/cooperative-acdd5e7adb1bd680)
|
||||
|
||||
running 7 tests
|
||||
test sleep_deadline_survives_pause_and_does_not_pop_argument_twice ... ok
|
||||
test finite_slices_preserve_events_without_clock_queries ... ok
|
||||
test common_dialog_external_call_keeps_byref_arguments_until_completion ... ok
|
||||
test partial_console_operations_keep_prompt_arguments_and_assignment ... ok
|
||||
test pending_dialog_keeps_physical_resize_and_modeless_handler_finishes_after_hide ... ok
|
||||
test dialogs_keep_partial_text_focus_and_caller_arguments ... ok
|
||||
test modal_and_modeless_forms_resume_handlers_across_tiny_budgets ... ok
|
||||
|
||||
test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s
|
||||
|
||||
Running tests/debugger.rs (target/debug/deps/debugger-2aaa51d59ed630d5)
|
||||
|
||||
running 14 tests
|
||||
test same_line_calls_and_immediate_do_not_retrigger_a_line_breakpoint ... ok
|
||||
test set_next_rejects_loop_gosub_handler_and_pending_operations_atomically ... ok
|
||||
test break_continue_loop_and_statement_steps ... ok
|
||||
test form_event_breakpoint_and_step_over_keep_the_event_frame ... ok
|
||||
test step_over_recursive_frames_history_and_safe_jump ... ok
|
||||
test immediate_handler_exit_and_cached_new_imports_are_safe ... ok
|
||||
test set_next_rejects_else_and_case_entry_but_allows_peer_statements ... ok
|
||||
test immediate_handler_resume_and_break_on_errors ... ok
|
||||
test gosub_step_over_breakpoint_priority_and_temporary_target_cleanup ... ok
|
||||
test watches_immediate_byref_and_errors_preserve_continuation ... ok
|
||||
test include_identity_qualified_globals_udts_and_older_frames ... ok
|
||||
test immediate_wait_interrupt_nested_error_end_and_run ... ok
|
||||
test watches_never_initialize_arrays_or_run_user_functions_and_keep_selected_context ... ok
|
||||
test watchpoint_history_ring_and_error_differential ... ok
|
||||
|
||||
test result: ok. 14 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s
|
||||
|
||||
Running tests/events.rs (target/debug/deps/events-2f0766815a3e98d6)
|
||||
|
||||
running 33 tests
|
||||
test lokaler_error_handler_nach_trap_verwirft_abgebrochene_teileingabe ... ok
|
||||
test handler_eingabe_und_stop_bewahren_die_aeussere_eingabe ... ok
|
||||
test fehlender_ereignispfad_wird_namentlich_erkannt ... ok
|
||||
test randomize_eingabe_teilt_den_fortsetzbaren_konsolenpfad ... ok
|
||||
test input_redo_verliert_weder_referenzen_noch_teiltext_beim_trap ... ok
|
||||
test fokus_handler_laufen_geordnet_bis_zur_rueckkehr ... ok
|
||||
test ohne_zeitbedarf_keine_uhrabfrage_und_keine_mausansammlung ... ok
|
||||
test offenes_menu_sperrt_traps_und_wartende_forms_timer_an_allen_zustellpunkten ... ok
|
||||
test doevents_verhindert_rekursion_derselben_forms_prozedur ... ok
|
||||
test formular_tastatur_fallback_fuehrt_alle_drei_basic_handler_aus ... ok
|
||||
test intervallaenderung_im_handler_verwirft_bereits_faellige_altintervalle ... ok
|
||||
test dialog_erhaelt_stop_markierung_unverbrauchter_tasten ... ok
|
||||
test eof_im_dialog_eines_formularhandlers_beendet_die_ereignispumpe ... ok
|
||||
test beide_signale_werden_zugestellt_und_beginnen_in_quellreihenfolge ... ok
|
||||
test eof_leert_angenommene_eingaben_bei_modalen_und_modellosen_forms ... ok
|
||||
test review_gleichzeitig_key_und_uevent_behalten_prioritaet ... ok
|
||||
test return_label_verwirft_abgebrochene_eingabe_und_ausdruck ... ok
|
||||
test review_menu_schliessen_stellt_pending_trap_vor_erneutem_warten_zu ... ok
|
||||
test input_fortsetzung_erhaelt_teiltext_ausdruck_und_byref_ziel ... ok
|
||||
test timer_waehrend_input_wird_vor_erneutem_warten_zugestellt ... ok
|
||||
test review_maus_vor_getrappter_taste ... ok
|
||||
test review_modale_eingabe_vor_eof_wird_zugestellt ... ok
|
||||
test review_signal_waehrend_blockierender_eingabe ... ok
|
||||
test unload_aus_unload_handler_ruft_dieselbe_prozedur_nicht_rekursiv_auf ... ok
|
||||
test spaete_timeraktivierung_nutzt_hostzeit_auch_ueber_control_parameter ... ok
|
||||
test key_on_off_stop_gelten_fuer_alle_konsoleneingaben ... ok
|
||||
test taste_maus_und_trap_behalten_die_annahmereihenfolge ... ok
|
||||
test review_objektargument_darf_gotfocus_nicht_vorziehen ... ok
|
||||
test shell_und_irr_funktionssignaturen_erreichen_die_runtime ... ok
|
||||
test registrierte_form_ereignisse_erreichen_basic_aus_realen_quellen ... ok
|
||||
test sleep_folgt_nur_der_hostfrist_und_forms_timer_beendet_es ... ok
|
||||
test prozessfrist::frist_beendet_blockierten_testprozess ... ok
|
||||
test registrierte_control_ereignisse_erreichen_basic_aus_realen_quellen ... ok
|
||||
|
||||
test result: ok. 33 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.12s
|
||||
|
||||
Running tests/incremental.rs (target/debug/deps/incremental-ef01ad977c2204da)
|
||||
|
||||
running 4 tests
|
||||
test unused_constants_do_not_invalidate_independent_units_and_declare_changes_do ... ok
|
||||
test includes_source_ids_data_and_forms_relink_without_patching_old_products ... ok
|
||||
test cached_private_edits_parse_and_compile_only_changed_modules ... ok
|
||||
test constants_types_common_removed_symbols_and_order_match_full_compiler ... ok
|
||||
|
||||
test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s
|
||||
|
||||
Running tests/library.rs (target/debug/deps/library-0b9e1b471b1e7297)
|
||||
|
||||
running 9 tests
|
||||
test source_debug_context_keeps_module_ids_when_library_is_between_sources ... ok
|
||||
test library_include_locations_keep_physical_lines_and_basic_erl ... ok
|
||||
test library_source_locations_and_run_restart_are_preserved ... ok
|
||||
test unused_declare_is_not_an_import_but_references_in_any_body_must_resolve ... ok
|
||||
test contracts_reject_result_common_bounds_and_invalid_declarations ... ok
|
||||
test source_and_library_have_identical_types_constants_common_data_byref_and_init_order ... ok
|
||||
test two_source_free_libraries_with_typed_open_imports_and_diagnostics ... ok
|
||||
test library_container_rejects_truncation_versions_lengths_and_references ... ok
|
||||
test separate_form_libraries_remap_nested_objects_initials_arrays_and_events ... ok
|
||||
|
||||
test result: ok. 9 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s
|
||||
|
||||
Running tests/project.rs (target/debug/deps/project-7ae350d75d21dcb2)
|
||||
|
||||
running 7 tests
|
||||
test diagnose_im_include_und_echte_duplikate_bleiben_sichtbar ... ok
|
||||
test typreferenzen_signaturen_und_option_base_ueber_modulgrenzen ... ok
|
||||
test module_includes_erl_breakpoints_und_inspektion_behalten_ihren_ursprung ... ok
|
||||
test lokale_prozeduren_shared_common_und_wiederholte_includes_bleiben_getrennt ... ok
|
||||
test initialisierungen_def_fn_und_modulhandler_haben_eigene_quellorte ... ok
|
||||
test beschaedigte_container_werden_vor_der_ausfuehrung_abgewiesen ... ok
|
||||
test zwei_formulare_mit_gleichen_controls_und_arrays_laufen_aus_dem_kompilat ... ok
|
||||
|
||||
test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s
|
||||
|
||||
Running tests/project_io.rs (target/debug/deps/project_io-76f82da2b295b346)
|
||||
|
||||
running 7 tests
|
||||
test case_insensitive_parent_lookup_works_from_relative_base_without_changing_cwd ... ok
|
||||
test overlays_keep_original_files_and_distinct_module_contexts ... ok
|
||||
test documented_mak_example_is_accepted_by_the_shared_loader ... ok
|
||||
test relative_include_precedes_search_paths_and_virtual_files_are_resolved ... ok
|
||||
test cycle_missing_include_and_literal_directives_are_distinguished ... ok
|
||||
test startup_metadata_roundtrip_and_invalid_contracts ... ok
|
||||
test tbl_members_move_save_as_order_startup_and_same_size_cache_replacement ... ok
|
||||
|
||||
test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s
|
||||
|
||||
Running tests/project_regressions.rs (target/debug/deps/project_regressions-88b074fd28a1a09a)
|
||||
|
||||
running 16 tests
|
||||
test diagnostik_bei_literalen_im_include_hat_die_exakte_spalte ... ok
|
||||
test spaetere_common_konflikte_und_doppelte_module_werden_am_ursprung_gemeldet ... ok
|
||||
test v6_linkerdiagnose_nennt_den_urspruenglichen_dateiort ... ok
|
||||
test debugger_unterscheidet_typisierte_scalar_und_arraynamen ... ok
|
||||
test prozedurlokaler_deftype_veraendert_keine_nachfolgende_signatur ... ok
|
||||
test v5_load_und_unload_loesen_den_expliziten_container_auf ... ok
|
||||
test v3_form_metabefehle_erzeugen_getrennte_formularobjekte ... ok
|
||||
test common_vertraege_und_linkfehler_haben_echte_quellorte ... ok
|
||||
test v4_common_behaelt_typidentitaet_und_initialisiert_arrays_einmal ... ok
|
||||
test gemischte_frm_und_form_module_haben_getrennte_ereignisbindungen ... ok
|
||||
test modulbreakpoint_rundlauf_inspektion_und_numerische_erl_bleiben_getrennt ... ok
|
||||
test v1_zweige_und_schleifen_behalten_eigene_quellorte ... ok
|
||||
test v2_importierte_deklarationen_behalten_kontext_und_abhaengigkeiten ... ok
|
||||
test common_arrays_behalten_dynamische_grenzen_und_kompatible_offene_deklarationen ... ok
|
||||
test importkontext_bleibt_auch_bei_abweichenden_lokalen_definitionen_erhalten ... ok
|
||||
test schleifengrenzen_tragen_breakpoint_include_und_resume ... ok
|
||||
|
||||
test result: ok. 16 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
|
||||
|
||||
Running tests/vm.rs (target/debug/deps/vm-4bcfa272723580f5)
|
||||
|
||||
running 114 tests
|
||||
test data_read_restore ... ok
|
||||
test doevents_liefert_null ... ok
|
||||
test data_typkonflikt_fehler_13 ... ok
|
||||
test byref_wirkt_zurueck ... ok
|
||||
test byref_auf_arrayelement ... ok
|
||||
test default_button_hat_vorrang_und_beendet_modales_formular ... ok
|
||||
test color_prueft_wertebereich ... ok
|
||||
test banker_rounding_cint ... ok
|
||||
test common_dialog_registrierung_setzt_byref_erfolg ... ok
|
||||
test clipboard_und_printer_objekte_haben_laufzeitwirkung ... ok
|
||||
test breakpoint_haelt_an_und_setzt_fort ... ok
|
||||
test division_durch_null ... ok
|
||||
test ausgabe_erscheint_vor_der_eingabe ... ok
|
||||
test def_fn_im_modulkontext ... ok
|
||||
test cls_setzt_cursor_zurueck ... ok
|
||||
test einzelschritt ... ok
|
||||
test do_loop_varianten ... ok
|
||||
test eingabe_wird_geechot_und_rueckschritt_loescht ... ok
|
||||
test doevents_stellt_zu ... ok
|
||||
test erl_liefert_zeilennummer ... ok
|
||||
test erl_null_ohne_zeilennummern ... ok
|
||||
test end_und_system ... ok
|
||||
test erl_nennt_die_fehlerzeile_nicht_die_handlerzeile ... ok
|
||||
test error_anweisung ... ok
|
||||
test exit_for_und_do ... ok
|
||||
test fehlende_ereignisprozedur_verfaellt_und_typeof_prueft_klasse ... ok
|
||||
test for_mit_dynamischem_step ... ok
|
||||
test fester_versatz_verschiebt_die_uhr ... ok
|
||||
test for_mit_negativem_step ... ok
|
||||
test for_ohne_durchlauf ... ok
|
||||
test fehler_im_handler_ist_fatal ... ok
|
||||
test fehler_im_trap_handler_erreicht_den_modulweiten_handler ... ok
|
||||
test event_off_klammert_die_zustellung ... ok
|
||||
test form_load_laeuft_vor_dem_sichtbarsetzen ... ok
|
||||
test grafik_line_paint_und_view_zeichnen_in_den_zellenpuffer ... ok
|
||||
test inkey_ohne_taste_ist_leer ... ok
|
||||
test ganzes_array_uebergeben ... ok
|
||||
test inkey_liefert_zeichen_und_sondertaste ... ok
|
||||
test form_load_laeuft_einmal_und_unload_cancel_verhindert_entladen ... ok
|
||||
test gosub_return_und_fehler_3 ... ok
|
||||
test input_mit_redo ... ok
|
||||
test groessenaenderung_wirkt_zur_laufzeit ... ok
|
||||
test gosub_null_schaltet_den_trap_ab ... ok
|
||||
test input_s_liest_genau_n_zeichen_ohne_echo ... ok
|
||||
test function_und_rekursion ... ok
|
||||
test intdiv_rundet_operanden_vor ... ok
|
||||
test gemischte_arithmetik ... ok
|
||||
test kennung_ausserhalb_des_bereichs_ist_fehler_5 ... ok
|
||||
test klammern_erzwingen_byval ... ok
|
||||
test len_liefert_die_feste_satzbreite_eines_udt ... ok
|
||||
test line_input_liest_ganze_zeile ... ok
|
||||
test input_s_liest_aus_einer_binaerdatei ... ok
|
||||
test input_s_teilt_sondertasten_und_bewahrt_rest_fuer_inkey ... ok
|
||||
test klassischer_timer_trap_ruht_solange_das_menu_offen_ist ... ok
|
||||
test logik_bitweise ... ok
|
||||
test kontrollfluss_korpusdatei ... ok
|
||||
test listenmethoden_und_indexeigenschaft_laufen_auf_control_arrays ... ok
|
||||
test leere_warteschleife_hat_eine_anweisungsgrenze ... ok
|
||||
test mid_anweisung_mutiert ... ok
|
||||
test listenmethoden_indexeigenschaft_und_picture_messung_laufen_in_der_vm ... ok
|
||||
test lokaler_handler_verdeckt_modulweiten ... ok
|
||||
test locate_ausserhalb_loest_fehler_5_aus ... ok
|
||||
test lokaler_handler_hat_vorrang ... ok
|
||||
test mausargumente_kommen_in_zellen_an ... ok
|
||||
test modales_show_setzt_nach_unload_fort ... ok
|
||||
test modulweiter_handler_faengt_prozedurfehler ... ok
|
||||
test ohne_handler_bricht_ab ... ok
|
||||
test objektcode_erzeugt_keine_zusaetzlichen_zustellopcodes ... ok
|
||||
test alle_mk_cv_paare_verlangen_exakte_bytezeichenbreite ... ok
|
||||
test modulweites_on_error_aus_prozedur ... ok
|
||||
test on_error_goto_0_deaktiviert ... ok
|
||||
test objektzugriff_laeuft_ueber_objekt_und_eigenschaftsindex ... ok
|
||||
test modelloses_formular_bleibt_nach_programmende_bedienbar ... ok
|
||||
test on_goto_berechnet ... ok
|
||||
test out_of_data_fehler_4 ... ok
|
||||
test overflow_bei_zuweisung ... ok
|
||||
test on_local_error_bleibt_prozedurlokal ... ok
|
||||
test ohne_timer_on_kein_trap ... ok
|
||||
test print_hallo_welt ... ok
|
||||
test programmversatz_wirkt_auf_alle_zeitfunktionen ... ok
|
||||
test printform_schreibt_das_textformular_in_den_druckerkanal ... ok
|
||||
test restore_mit_label ... ok
|
||||
test resume_ohne_fehler_20 ... ok
|
||||
test print_zonen_und_tab ... ok
|
||||
test resume_next_faehrt_fort ... ok
|
||||
test datei_und_elternpfadfehler_sind_am_sprachzugang_unterscheidbar ... ok
|
||||
test msgbox_und_inputbox_sind_keine_unsupported_opcodes_mehr ... ok
|
||||
test resume_wiederholt_anweisung ... ok
|
||||
test rueckfall_auf_utc_laeuft_fehlerfrei ... ok
|
||||
test run_gibt_datei_oder_zeile_an_den_runner_weiter ... ok
|
||||
test screen_controlpanel_hat_einen_indexierten_laufzeitwert ... ok
|
||||
test select_case_bereiche ... ok
|
||||
test setuevent_loest_den_uevent_trap_aus ... ok
|
||||
test screen_anweisung_bildet_grafikmodi_auf_den_zellenpuffer_ab ... ok
|
||||
test screen_funktion_ausserhalb_loest_fehler_5_aus ... ok
|
||||
test sleep_endet_durch_ein_ereignis ... ok
|
||||
test stop_liefert_zeile_und_ist_fortsetzbar ... ok
|
||||
test sondertastenrest_wird_nicht_erneut_getrappt ... ok
|
||||
test static_behaelt_werte ... ok
|
||||
test stringvergleich_und_verkettung ... ok
|
||||
test time_und_now_stimmen_ueberein ... ok
|
||||
test steuerarray_ereignis_stellt_index_voran ... ok
|
||||
test timer_zaehlt_ab_lokaler_mitternacht ... ok
|
||||
test steuerarray_eigenschaften_und_objektparameter_funktionieren ... ok
|
||||
test udt_wertsemantik_und_felder ... ok
|
||||
test width_hebt_die_groesse_an ... ok
|
||||
test timezoneknown_hat_integer_signatur_und_zeigt_aktuellen_status ... ok
|
||||
test timer_off_im_handler_ueberlebt_das_return ... ok
|
||||
test trap_aus_einer_sub_heraus_kehrt_dorthin_zurueck ... ok
|
||||
test input_datei_bewahrt_felder_und_unterscheidet_leer_von_fehlend ... ok
|
||||
test zeit_trap_laeuft_und_kehrt_zurueck ... ok
|
||||
test input_datei_alle_lesearten_teilen_utf8_cursor_und_seek ... ok
|
||||
test unicode_puffergrenzen_und_binaere_records_bleiben_getrennt ... ok
|
||||
test open_for_isam_endet_nicht_mehr_mit_fehler_73 ... ok
|
||||
|
||||
test result: ok. 114 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.08s
|
||||
|
||||
Doc-tests tb_export
|
||||
|
||||
running 0 tests
|
||||
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
|
||||
|
||||
Doc-tests tb_frontend
|
||||
|
||||
running 0 tests
|
||||
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
|
||||
|
||||
Doc-tests tb_ide
|
||||
|
||||
running 0 tests
|
||||
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
|
||||
|
||||
Doc-tests tb_runner
|
||||
|
||||
running 0 tests
|
||||
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
|
||||
|
||||
Doc-tests tb_runtime
|
||||
|
||||
running 0 tests
|
||||
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
|
||||
|
||||
Doc-tests tb_ui
|
||||
|
||||
running 0 tests
|
||||
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
|
||||
|
||||
Doc-tests tb_vm
|
||||
|
||||
running 0 tests
|
||||
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
PASS {'shell_exit': 7}
|
||||
PASS {'abort': True}
|
||||
PASS {'file_shell': True}
|
||||
@@ -0,0 +1 @@
|
||||
{"target": "aarch64-apple-darwin", "tbl_sha256": "5d25c2f8c95ae535e55a6c84c1ddd0d964358863f4f3c780c50ac4a2eb3594df", "native_execution": true, "source_free": true, "run_reset": true, "output": " 1 \n 7 3 9 1 \nTB \n"}
|
||||
@@ -0,0 +1,13 @@
|
||||
PASS native console
|
||||
PASS native restart
|
||||
PASS native stop
|
||||
PASS native error
|
||||
PASS native project
|
||||
PASS native form
|
||||
PASS native external
|
||||
PASS PTY Eingabe, Abbruch und Wiederherstellung (CLI/native)
|
||||
PASS Exportabbruch SIGINT/SIGTERM, Original und Bereinigung
|
||||
PASS corrupted length
|
||||
PASS corrupted version
|
||||
PASS corrupted truncated
|
||||
Native Abnahme bestanden: aarch64-apple-darwin
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"scope": "automated-target-checks",
|
||||
"started_utc": "2026-09-07T18:44:13.277828+00:00",
|
||||
"host_target": "aarch64-apple-darwin",
|
||||
"os_version": "macOS-26.6.2-arm64-arm-64bit-Mach-O",
|
||||
"python_version": "3.14.7",
|
||||
"checkout_revision": "5aa920b768a2ad29ed17c5da137e54675a7292d6",
|
||||
"working_tree_dirty": true,
|
||||
"working_tree_diff_sha256": "cd170b3c9923de226676c6e12a6644feaca40e048d3f750ac8935c8a2732d34d",
|
||||
"program_sha256": {
|
||||
"tb": "77b14be900039a72c2633f157c7deb2ea0c7c70d550e7b6a9490a38b996c5c5a",
|
||||
"tbc": "a51b678bca795b88fe92a9f8ce0fcdd0f488931f85fd7f1d2721c17ed665a1e9",
|
||||
"tbrt": "995a8e62454b7c4e6af2782007a4e1eda95deaca25cbacf4f3e01ac1c41ccce1",
|
||||
"tb-template": "a9d73ea8002b8f01bbb1fdc033a2595605ceb3b8c55d4531bf00da236351ccbf"
|
||||
},
|
||||
"tbl_sha256": "5d25c2f8c95ae535e55a6c84c1ddd0d964358863f4f3c780c50ac4a2eb3594df",
|
||||
"manual_terminal_status": "not_run",
|
||||
"matrix_complete": false,
|
||||
"checks": {
|
||||
"library": {
|
||||
"status": "passed",
|
||||
"exit_code": 0
|
||||
},
|
||||
"native": {
|
||||
"status": "passed",
|
||||
"exit_code": 0
|
||||
},
|
||||
"ide-pty": {
|
||||
"status": "passed",
|
||||
"exit_code": 0
|
||||
},
|
||||
"artifact-stability": {
|
||||
"status": "passed"
|
||||
}
|
||||
},
|
||||
"harness_sha256": {
|
||||
"library-abnahme.py": "118de32bc5a9cbb254b234b420455f75961603afb16aa94333be8c4b5b17e962",
|
||||
"platform-abnahme.py": "a5eadbd4bcabaae6c3c173ce933f83e331d03b1cf22998fe564519fe8f6b9696",
|
||||
"native-abnahme.py": "fe9f34bcc581e6230909b6277bae4768dbf6be068e4616b47aaff4390424ca14",
|
||||
"release-abnahme.py": "f77b1481913050faa321f9978d0f6cf31e8f884a1f626a861727b5393e1bea83",
|
||||
"ide-execution-pty.py": "751afaadc1f25639eab7d5f746bee9ad0a5c11446bab8dbd4ccdd6dfae6fe4f9"
|
||||
},
|
||||
"all_automated_passed": true
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
1: Key(KeyEvent { code: Char('x'), modifiers: KeyModifiers(0x0), kind: Press, state: KeyEventState(0x0) })
|
||||
2: Key(KeyEvent { code: Esc, modifiers: KeyModifiers(0x0), kind: Press, state: KeyEventState(0x0) })
|
||||
@@ -0,0 +1,8 @@
|
||||
M crates/tb-ide/tests/execution.rs
|
||||
M crates/tb-ui/examples/spike.rs
|
||||
M crates/tb-ui/src/terminal.rs
|
||||
M tests/support/ide-execution-pty.py
|
||||
?? docs/plattformmatrix.md
|
||||
?? tests/platform/
|
||||
?? tests/support/__pycache__/
|
||||
?? tests/support/platform-abnahme.py
|
||||
@@ -0,0 +1,452 @@
|
||||
diff --git a/crates/tb-ide/tests/execution.rs b/crates/tb-ide/tests/execution.rs
|
||||
index 237ac71..e92a0b6 100644
|
||||
--- a/crates/tb-ide/tests/execution.rs
|
||||
+++ b/crates/tb-ide/tests/execution.rs
|
||||
@@ -530,3 +530,35 @@ fn comment_only_source_change_also_requires_revision_choice() {
|
||||
DialogKind::ResumeRevision
|
||||
));
|
||||
}
|
||||
+
|
||||
+#[test]
|
||||
+fn platform_probe_records_each_basic_key_once_and_keeps_ide_keys_out() {
|
||||
+ let t = Temp::new();
|
||||
+ let log = t.0.join("platform-events.log");
|
||||
+ let source = include_str!("../../../tests/platform/input.frm")
|
||||
+ .replace("platform-events.log", &log.to_string_lossy());
|
||||
+ let path = t.0.join("input.frm");
|
||||
+ fs::write(&path, source).unwrap();
|
||||
+ let mut a = t.app("");
|
||||
+ a.load_initial_project(path).unwrap();
|
||||
+ a.execute(Command::Start);
|
||||
+ tick(&mut a);
|
||||
+ key(&mut a, K::Char('a'), M::NONE);
|
||||
+ tick(&mut a);
|
||||
+ a.handle(Event::Key(KeyEvent::new_with_kind(
|
||||
+ K::Char('a'),
|
||||
+ M::NONE,
|
||||
+ crossterm::event::KeyEventKind::Release,
|
||||
+ )));
|
||||
+ tick(&mut a);
|
||||
+ let events = fs::read_to_string(&log).unwrap();
|
||||
+ assert_eq!(
|
||||
+ events.replace('\r', ""),
|
||||
+ "Down: 97 : 0 \nPress: 97 : 0 \nUp: 97 : 0 \n"
|
||||
+ );
|
||||
+ edit_window(&mut a);
|
||||
+ key(&mut a, K::F(1), M::NONE);
|
||||
+ tick(&mut a);
|
||||
+ assert_eq!(fs::read_to_string(&log).unwrap(), events);
|
||||
+ assert!(matches!(a.active_window().unwrap().kind, WindowKind::Help));
|
||||
+}
|
||||
diff --git a/crates/tb-ui/examples/spike.rs b/crates/tb-ui/examples/spike.rs
|
||||
index b6b5ff3..38196ed 100644
|
||||
--- a/crates/tb-ui/examples/spike.rs
|
||||
+++ b/crates/tb-ui/examples/spike.rs
|
||||
@@ -1,15 +1,12 @@
|
||||
//! Phase-0-Spike: 80×25-Bildschirmpuffer, 16-Farben-Palette, Unicode,
|
||||
//! Tastatur- und Mausereignisse.
|
||||
//!
|
||||
-//! Start: `cargo run -p tb-ui --example spike` — Beenden mit Esc.
|
||||
+//! Start: `cargo run -p tb-ui --features terminal --example spike -- --log events.txt` — Beenden mit Esc.
|
||||
//! Getippte Zeichen erscheinen im Eingabebereich; Sondertasten und
|
||||
//! Mausereignisse werden in der Statuszeile angezeigt.
|
||||
|
||||
-use crossterm::event::{
|
||||
- self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyEventKind,
|
||||
-};
|
||||
-use crossterm::execute;
|
||||
-use std::io::stdout;
|
||||
+use crossterm::event::{self, Event, KeyCode, KeyEventKind};
|
||||
+use std::io::{stdout, Write};
|
||||
use std::time::Duration;
|
||||
use tb_ui::screen::{ScreenWidget, TextScreen};
|
||||
|
||||
@@ -57,8 +54,24 @@ fn status(s: &mut TextScreen, text: &str) {
|
||||
}
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
- let mut terminal = ratatui::init();
|
||||
- execute!(stdout(), EnableMouseCapture)?;
|
||||
+ let args: Vec<_> = std::env::args_os().skip(1).collect();
|
||||
+ anyhow::ensure!(
|
||||
+ args.is_empty() || (args.len() == 2 && args[0] == "--log"),
|
||||
+ "Aufruf: spike [--log neue-datei]"
|
||||
+ );
|
||||
+ let mut log = if args.len() == 2 {
|
||||
+ Some(
|
||||
+ std::fs::OpenOptions::new()
|
||||
+ .write(true)
|
||||
+ .create_new(true)
|
||||
+ .open(&args[1])?,
|
||||
+ )
|
||||
+ } else {
|
||||
+ None
|
||||
+ };
|
||||
+ let _guard = tb_ui::terminal::TerminalGuard::enter(stdout())?;
|
||||
+ let mut terminal = ratatui::Terminal::new(ratatui::backend::CrosstermBackend::new(stdout()))?;
|
||||
+ let mut sequence = 0u64;
|
||||
|
||||
let (tw, th) = crossterm::terminal::size()?;
|
||||
let mut screen = TextScreen::with_size(tw as usize, th as usize);
|
||||
@@ -70,7 +83,12 @@ fn main() -> anyhow::Result<()> {
|
||||
if !event::poll(Duration::from_millis(100))? {
|
||||
continue;
|
||||
}
|
||||
- match event::read()? {
|
||||
+ let received = event::read()?;
|
||||
+ sequence += 1;
|
||||
+ if let Some(log) = &mut log {
|
||||
+ writeln!(log, "{sequence}: {received:?}")?;
|
||||
+ }
|
||||
+ match received {
|
||||
Event::Key(k) if k.kind != KeyEventKind::Release => match k.code {
|
||||
KeyCode::Esc => break,
|
||||
KeyCode::Char(c) => {
|
||||
@@ -105,7 +123,5 @@ fn main() -> anyhow::Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
- execute!(stdout(), DisableMouseCapture)?;
|
||||
- ratatui::restore();
|
||||
Ok(())
|
||||
}
|
||||
diff --git a/crates/tb-ui/src/terminal.rs b/crates/tb-ui/src/terminal.rs
|
||||
index 77493b2..a8204d4 100644
|
||||
--- a/crates/tb-ui/src/terminal.rs
|
||||
+++ b/crates/tb-ui/src/terminal.rs
|
||||
@@ -11,23 +11,44 @@ use std::io::{self, Write};
|
||||
pub struct TerminalGuard<W: Write> {
|
||||
writer: W,
|
||||
raw: fn(bool) -> io::Result<()>,
|
||||
+ #[cfg(windows)]
|
||||
+ modes: Option<ConsoleModes>,
|
||||
}
|
||||
impl<W: Write> TerminalGuard<W> {
|
||||
pub fn enter(writer: W) -> io::Result<Self> {
|
||||
- Self::with_raw(writer, |on| {
|
||||
+ #[cfg(windows)]
|
||||
+ let modes = ConsoleModes::capture()?;
|
||||
+ #[cfg(windows)]
|
||||
+ modes.enable_output()?;
|
||||
+ #[allow(unused_mut)]
|
||||
+ let mut guard = Self::with_raw(writer, |on| {
|
||||
if on {
|
||||
enable_raw_mode()
|
||||
} else {
|
||||
disable_raw_mode()
|
||||
}
|
||||
- })
|
||||
+ })?;
|
||||
+ #[cfg(windows)]
|
||||
+ {
|
||||
+ guard.modes = Some(modes);
|
||||
+ }
|
||||
+ Ok(guard)
|
||||
}
|
||||
fn with_raw(writer: W, raw: fn(bool) -> io::Result<()>) -> io::Result<Self> {
|
||||
- let mut guard = Self { writer, raw };
|
||||
+ let mut guard = Self {
|
||||
+ writer,
|
||||
+ raw,
|
||||
+ #[cfg(windows)]
|
||||
+ modes: None,
|
||||
+ };
|
||||
guard.resume()?;
|
||||
Ok(guard)
|
||||
}
|
||||
fn resume(&mut self) -> io::Result<()> {
|
||||
+ #[cfg(windows)]
|
||||
+ if let Some(modes) = &self.modes {
|
||||
+ modes.enable_output()?;
|
||||
+ }
|
||||
(self.raw)(true)?;
|
||||
execute!(
|
||||
self.writer,
|
||||
@@ -38,15 +59,18 @@ impl<W: Write> TerminalGuard<W> {
|
||||
)
|
||||
}
|
||||
fn suspend(&mut self) -> io::Result<()> {
|
||||
- (self.raw)(false)?;
|
||||
- execute!(
|
||||
+ let raw = (self.raw)(false);
|
||||
+ let output = execute!(
|
||||
self.writer,
|
||||
ResetColor,
|
||||
Show,
|
||||
DisableMouseCapture,
|
||||
DisableBracketedPaste,
|
||||
LeaveAlternateScreen
|
||||
- )
|
||||
+ );
|
||||
+ #[cfg(windows)]
|
||||
+ let output = output.and(self.modes.as_ref().map_or(Ok(()), ConsoleModes::restore));
|
||||
+ raw.and(output)
|
||||
}
|
||||
/// Foreground child owns cooked terminal input. Always restore the IDE,
|
||||
/// including spawn/wait errors and a child interrupted by Ctrl+C.
|
||||
@@ -91,6 +115,10 @@ impl<W: Write> TerminalGuard<W> {
|
||||
}
|
||||
impl<W: Write> Drop for TerminalGuard<W> {
|
||||
fn drop(&mut self) {
|
||||
+ #[cfg(windows)]
|
||||
+ if let Some(modes) = &self.modes {
|
||||
+ let _ = modes.enable_output();
|
||||
+ }
|
||||
let _ = (self.raw)(false);
|
||||
let _ = execute!(
|
||||
self.writer,
|
||||
@@ -103,6 +131,58 @@ impl<W: Write> Drop for TerminalGuard<W> {
|
||||
}
|
||||
}
|
||||
|
||||
+// Crossterm stellt unter Windows Raw-/Mausflags pauschal zurück. Der Besitzer
|
||||
+// muss zusätzlich die tatsächlichen Eingabe- und Ausgabemodi wiederherstellen.
|
||||
+#[cfg(windows)]
|
||||
+#[derive(Debug)]
|
||||
+struct ConsoleModes([(std::os::windows::io::RawHandle, u32); 2]);
|
||||
+#[cfg(windows)]
|
||||
+#[link(name = "kernel32")]
|
||||
+extern "system" {
|
||||
+ fn GetStdHandle(kind: u32) -> std::os::windows::io::RawHandle;
|
||||
+ fn GetConsoleMode(handle: std::os::windows::io::RawHandle, mode: *mut u32) -> i32;
|
||||
+ fn SetConsoleMode(handle: std::os::windows::io::RawHandle, mode: u32) -> i32;
|
||||
+}
|
||||
+#[cfg(windows)]
|
||||
+impl ConsoleModes {
|
||||
+ fn capture() -> io::Result<Self> {
|
||||
+ let mut modes = [(std::ptr::null_mut(), 0); 2];
|
||||
+ for (slot, kind) in modes.iter_mut().zip([(-10i32) as u32, (-11i32) as u32]) {
|
||||
+ // Borrowed standard handles: valid until the terminal owner exits.
|
||||
+ slot.0 = unsafe { GetStdHandle(kind) };
|
||||
+ if unsafe { GetConsoleMode(slot.0, &mut slot.1) } == 0 {
|
||||
+ return Err(io::Error::last_os_error());
|
||||
+ }
|
||||
+ }
|
||||
+ Ok(Self(modes))
|
||||
+ }
|
||||
+ fn enable_output(&self) -> io::Result<()> {
|
||||
+ // Crossterm caches ANSI support, but a Shell handoff restores the old
|
||||
+ // output flags. Re-enable VT for each ownership cycle, including re-entry.
|
||||
+ if crossterm::ansi_support::supports_ansi()
|
||||
+ && unsafe { SetConsoleMode(self.0[1].0, self.0[1].1 | 0x0004) } == 0
|
||||
+ {
|
||||
+ return Err(io::Error::last_os_error());
|
||||
+ }
|
||||
+ Ok(())
|
||||
+ }
|
||||
+ fn restore(&self) -> io::Result<()> {
|
||||
+ let mut result = Ok(());
|
||||
+ for (handle, mode) in self.0 {
|
||||
+ if unsafe { SetConsoleMode(handle, mode) } == 0 && result.is_ok() {
|
||||
+ result = Err(io::Error::last_os_error());
|
||||
+ }
|
||||
+ }
|
||||
+ result
|
||||
+ }
|
||||
+}
|
||||
+#[cfg(windows)]
|
||||
+impl Drop for ConsoleModes {
|
||||
+ fn drop(&mut self) {
|
||||
+ let _ = self.restore();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -149,7 +229,7 @@ mod tests {
|
||||
("exit 7", false, 7),
|
||||
(
|
||||
if cfg!(windows) {
|
||||
- "ping -n 30 127.0.0.1 >nul"
|
||||
+ "for /L %i in (1,1,1000000000) do @rem"
|
||||
} else {
|
||||
"exec sleep 30"
|
||||
},
|
||||
@@ -160,10 +240,13 @@ mod tests {
|
||||
let out = Output(Rc::default());
|
||||
let copy = out.clone();
|
||||
let mut guard = TerminalGuard::with_raw(out, raw).unwrap();
|
||||
- assert_eq!(
|
||||
- guard.shell_with_interrupt(command, || abort).unwrap(),
|
||||
- expected
|
||||
- );
|
||||
+ let started = std::time::Instant::now();
|
||||
+ let code = guard.shell_with_interrupt(command, || abort).unwrap();
|
||||
+ if !abort {
|
||||
+ assert_eq!(code, expected);
|
||||
+ }
|
||||
+ // Windows TerminateProcess liefert einen Code; Unix ein Signal.
|
||||
+ assert!(started.elapsed() < std::time::Duration::from_secs(5));
|
||||
assert_eq!(RAW.load(Ordering::SeqCst), 1);
|
||||
let text = String::from_utf8(copy.0.borrow().clone()).unwrap();
|
||||
assert_eq!(text.matches("?1049h").count(), 2);
|
||||
@@ -187,4 +270,111 @@ mod tests {
|
||||
.unwrap()
|
||||
.contains("?25h"));
|
||||
}
|
||||
+ /// Run explicitly on Windows; never counts as a Windows Terminal UI test.
|
||||
+ #[cfg(windows)]
|
||||
+ #[test]
|
||||
+ #[ignore = "benötigt Windows mit echter Konsole; isolierter Kindprozess"]
|
||||
+ fn windows_console_restores_modes() {
|
||||
+ use std::os::windows::{io::AsRawHandle, process::CommandExt};
|
||||
+ use std::process::{Command, Stdio};
|
||||
+ use std::time::{Duration, Instant};
|
||||
+ const CHILD: &str = "TB_CONSOLE_TEST_CHILD";
|
||||
+ if std::env::var_os(CHILD).is_none() {
|
||||
+ let mut child = Command::new(std::env::current_exe().unwrap())
|
||||
+ .args([
|
||||
+ "--exact",
|
||||
+ "terminal::tests::windows_console_restores_modes",
|
||||
+ "--ignored",
|
||||
+ "--nocapture",
|
||||
+ ])
|
||||
+ .env(CHILD, "1")
|
||||
+ .creation_flags(0x00000010) // CREATE_NEW_CONSOLE: never touches the caller's console.
|
||||
+ .stdin(Stdio::null())
|
||||
+ .stdout(Stdio::null())
|
||||
+ .stderr(Stdio::null())
|
||||
+ .spawn()
|
||||
+ .unwrap();
|
||||
+ let deadline = Instant::now() + Duration::from_secs(30);
|
||||
+ loop {
|
||||
+ if let Some(status) = child.try_wait().unwrap() {
|
||||
+ assert!(
|
||||
+ status.success(),
|
||||
+ "Isolierte Windows-Konsolenprüfung: {status}"
|
||||
+ );
|
||||
+ return;
|
||||
+ }
|
||||
+ if Instant::now() >= deadline {
|
||||
+ let _ = child.kill();
|
||||
+ let _ = child.wait();
|
||||
+ panic!("Windows-Konsolenprüfung hat die Frist überschritten");
|
||||
+ }
|
||||
+ std::thread::sleep(Duration::from_millis(20));
|
||||
+ }
|
||||
+ }
|
||||
+ #[link(name = "kernel32")]
|
||||
+ extern "system" {
|
||||
+ fn SetStdHandle(kind: u32, handle: std::os::windows::io::RawHandle) -> i32;
|
||||
+ }
|
||||
+ let open = |name| {
|
||||
+ std::fs::OpenOptions::new()
|
||||
+ .read(true)
|
||||
+ .write(true)
|
||||
+ .open(name)
|
||||
+ .unwrap()
|
||||
+ };
|
||||
+ let input = open("CONIN$");
|
||||
+ let output = open("CONOUT$");
|
||||
+ // Standard streams started as NUL; bind to this child's own new console.
|
||||
+ assert_ne!(
|
||||
+ unsafe { SetStdHandle((-10i32) as u32, input.as_raw_handle()) },
|
||||
+ 0
|
||||
+ );
|
||||
+ assert_ne!(
|
||||
+ unsafe { SetStdHandle((-11i32) as u32, output.as_raw_handle()) },
|
||||
+ 0
|
||||
+ );
|
||||
+ let original = ConsoleModes::capture().unwrap();
|
||||
+ // Non-default echo flags catch a reset-to-default masquerading as restore.
|
||||
+ let mode = original.0[0].1 & !0x0004; // ENABLE_ECHO_INPUT
|
||||
+ assert_ne!(unsafe { SetConsoleMode(input.as_raw_handle(), mode) }, 0);
|
||||
+ let expected = ConsoleModes::capture().unwrap();
|
||||
+ let assert_restored = || assert_eq!(ConsoleModes::capture().unwrap().0, expected.0);
|
||||
+ for (command, abort, code) in [
|
||||
+ ("exit 0", false, 0),
|
||||
+ ("exit 7", false, 7),
|
||||
+ ("for /L %i in (1,1,1000000000) do @rem", true, 0),
|
||||
+ ] {
|
||||
+ let mut guard = TerminalGuard::enter(io::stdout()).unwrap();
|
||||
+ guard.suspend().unwrap();
|
||||
+ assert_restored();
|
||||
+ guard.resume().unwrap();
|
||||
+ if crossterm::ansi_support::supports_ansi() {
|
||||
+ assert_ne!(ConsoleModes::capture().unwrap().0[1].1 & 0x0004, 0);
|
||||
+ }
|
||||
+ let result = guard.shell_with_interrupt(command, || abort).unwrap();
|
||||
+ if !abort {
|
||||
+ assert_eq!(result, code);
|
||||
+ }
|
||||
+ assert!(crossterm::terminal::is_raw_mode_enabled().unwrap());
|
||||
+ drop(guard);
|
||||
+ assert_restored();
|
||||
+ }
|
||||
+ let error = (|| -> io::Result<()> {
|
||||
+ let _guard = TerminalGuard::enter(io::stdout())?;
|
||||
+ Err(io::Error::other("Erzwungener Renderfehler"))
|
||||
+ })();
|
||||
+ assert!(error.is_err());
|
||||
+ assert_restored();
|
||||
+ struct Broken;
|
||||
+ impl Write for Broken {
|
||||
+ fn write(&mut self, _: &[u8]) -> io::Result<usize> {
|
||||
+ Err(io::Error::other("Initialisierung"))
|
||||
+ }
|
||||
+ fn flush(&mut self) -> io::Result<()> {
|
||||
+ Ok(())
|
||||
+ }
|
||||
+ }
|
||||
+ assert!(TerminalGuard::enter(Broken).is_err());
|
||||
+ assert_restored();
|
||||
+ }
|
||||
}
|
||||
diff --git a/tests/support/ide-execution-pty.py b/tests/support/ide-execution-pty.py
|
||||
index b422070..d43c472 100644
|
||||
--- a/tests/support/ide-execution-pty.py
|
||||
+++ b/tests/support/ide-execution-pty.py
|
||||
@@ -2,6 +2,7 @@
|
||||
"""Headless Unix PTY smoke: real terminal handoff, child Ctrl+C and IDE resume.
|
||||
Run after cargo build -p tb-ide: python3 tests/support/ide-execution-pty.py
|
||||
"""
|
||||
+import argparse
|
||||
import fcntl
|
||||
import os
|
||||
from pathlib import Path
|
||||
@@ -13,10 +14,10 @@ import tempfile
|
||||
import termios
|
||||
import time
|
||||
|
||||
-binary = Path(__file__).resolve().parents[2] / 'target/debug/tb'
|
||||
|
||||
|
||||
-def exercise(abort=False, file_shell=False):
|
||||
+
|
||||
+def exercise(binary, transcript_dir=None, abort=False, file_shell=False):
|
||||
with tempfile.TemporaryDirectory(prefix='tb-pty-') as directory:
|
||||
source = Path(directory) / 'main.bas'
|
||||
command = "printf '\\nWAITING_CHILD\\n'; exec sleep 30" if abort else "printf '\\nSHELL_PROOF\\n'; exit 7"
|
||||
@@ -84,6 +85,9 @@ def exercise(abort=False, file_shell=False):
|
||||
assert transcript.count(b'?1049h') >= 2
|
||||
assert transcript.count(b'?1049l') >= 2
|
||||
finally:
|
||||
+ if transcript_dir:
|
||||
+ name = 'file-shell' if file_shell else 'shell-abort' if abort else 'shell-exit'
|
||||
+ (transcript_dir / (name + '.ansi')).write_bytes(transcript)
|
||||
if not reaped:
|
||||
os.killpg(pid, signal.SIGKILL)
|
||||
os.waitpid(pid, 0)
|
||||
@@ -91,6 +95,18 @@ def exercise(abort=False, file_shell=False):
|
||||
os.close(slave)
|
||||
|
||||
|
||||
-for kwargs in ({}, {'abort': True}, {'file_shell': True}):
|
||||
- exercise(**kwargs)
|
||||
- print('PASS', kwargs or {'shell_exit': 7})
|
||||
+def main():
|
||||
+ parser = argparse.ArgumentParser(description=__doc__)
|
||||
+ parser.add_argument('--binary', type=Path, default=Path(__file__).resolve().parents[2] / 'target/debug/tb')
|
||||
+ parser.add_argument('--transcript-dir', type=Path)
|
||||
+ args = parser.parse_args()
|
||||
+ binary = args.binary.resolve(strict=True)
|
||||
+ if args.transcript_dir:
|
||||
+ args.transcript_dir.mkdir(parents=True, exist_ok=True)
|
||||
+ for kwargs in ({}, {'abort': True}, {'file_shell': True}):
|
||||
+ exercise(binary, args.transcript_dir, **kwargs)
|
||||
+ print('PASS', kwargs or {'shell_exit': 7})
|
||||
+
|
||||
+
|
||||
+if __name__ == '__main__':
|
||||
+ main()
|
||||
@@ -0,0 +1,28 @@
|
||||
## Why
|
||||
|
||||
Die bisherige headless Abnahme und der lokale Unix-PTY-Test beweisen nicht die echte Terminalbedienung auf allen Release-Zielen. Phase 6 benötigt tatsächliche Zielausführung und eine nachprüfbare Matrix für Eingabe, Darstellung und Terminalwiederherstellung.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Windows amd64 mit Windows Terminal, macOS arm64 und Linux amd64/arm64 mit mindestens zwei Terminalemulatoren systematisch abnehmen.
|
||||
- IDE und native Terminalprogramme mit F1–F12, Modifikatoren, Maus, Unicode, Resize, INPUT/Break und Shell-Rückkehr prüfen.
|
||||
- Ziel-/Terminalversionen, Eingabeprotokolle, Einschränkungen und funktionierende Ersatzwege dokumentieren.
|
||||
- Dieselben TBL-Bytes aus 03 auf allen vier echten Zielen mit separaten quellfreien TBC-/EXE-Verbrauchern prüfen und Prüfsumme/Ergebnis protokollieren.
|
||||
- Automatisierbare Zieltests von manuellen Emulatornachweisen unterscheiden; fehlende Systeme bleiben fehlende Nachweise.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `terminal-plattformmatrix`: Verbindliche plattformübergreifende Terminalabnahme der vier Release-Ziele.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `ide-oberflaeche`: Durchgehend absolute RGB-Farben und vollständig geleerte Fensterflächen; Benutzerkorrektur vom 07.09.2026.
|
||||
- `textbildschirm`: Dieselbe absolute DOS-RGB-Palette für programmbestimmte BASIC-Farben und Formularvorschau.
|
||||
|
||||
## Impact
|
||||
|
||||
Terminaladapter in tb-ui/tb-ide, bisheriger PTY-Test, native Artefakttests aus 02–04 und neue Matrixdokumentation. Fachkorrekturen bleiben in bestehenden Adaptern. Abhängigkeiten: 01–04; automatisierte Aufrufe werden in 06 in Gitea Actions übernommen.
|
||||
|
||||
Der zusätzliche Change `phase-6-05a-vbdos-theme-und-kontrast` liefert Referenzfarben, Kontrastregeln und visuelle Prüffälle. Die abschließende Darstellungsmatrix umfasst diese Ergebnisse; ihre Vorbereitung kann unabhängig davon fortgesetzt werden.
|
||||
@@ -0,0 +1,24 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Farben und Statusanzeige
|
||||
Die IDE SHALL das anhand belegter VBDOS-Ansichten dokumentierte Farbschema aus docs/ide-referenz.md verwenden, insbesondere dunkelblaue Codefläche mit heller Schrift, weiße aktive Titel auf dunklem Magenta, graue Menüs und schwarze Statusschrift auf Cyan. Alle IDE-Farben SHALL als feste 24-Bit-RGB-Werte ausgegeben werden, unabhängig von TERM, COLORTERM, NO_COLOR und der ANSI-Palette. Ein Rückfall auf Index- oder Profilfarben MUST NOT erfolgen; die IDE MUST NOT die globale Terminalpalette verändern. Fensterflächen SHALL vor dem Zeichnen vorhandene Desktopzeichen und verdeckte Fensterinhalte löschen, sodass unbeschriebene Fläche und Texthintergrund dieselbe Farbe besitzen. Die Statuszeile SHALL kontextuelle klickbare Kürzel und Zeile/Spalte im Format 00001:001 zeigen. Display SHALL Vorder-/Hintergrund aus 16 Farben, Desktop-Füllzeichen und Tabweite ändern können. Bestehende gespeicherte Farbauswahlen SHALL gültig bleiben und MUST NOT stillschweigend überschrieben werden.
|
||||
|
||||
#### Scenario: Farben ändern
|
||||
- **WHEN** der Benutzer Titelhintergrund, Desktopzeichen und Tabweite im Display-Dialog ändert
|
||||
- **THEN** erscheinen die Änderungen in der IDE, während die Farbvorgaben des ausgeführten BASIC-Programms unverändert bleiben
|
||||
|
||||
#### Scenario: Abweichende ANSI-Palette
|
||||
- **WHEN** die IDE mit Standardoptionen auf einem Terminal mit expliziter Farbausgabe und einer pastellfarbenen ANSI-Palette gestartet wird
|
||||
- **THEN** bleiben Codefläche dunkelblau, Code lesbar und aktive Titel weiß auf dunklem Magenta; das Terminalprofil und die Farben nach Verlassen der IDE werden nicht verändert
|
||||
|
||||
#### Scenario: Bestehende Einstellungen laden
|
||||
- **WHEN** eine vorhandene Optionsdatei mit angepassten DOS-Farbnummern geladen wird
|
||||
- **THEN** bleiben die gewählten Nummern sowie alle weiteren Einstellungen erhalten und gelten über dieselbe definierte IDE-Farbabbildung
|
||||
|
||||
#### Scenario: Keine Farbfähigkeit gemeldet
|
||||
- **WHEN** die IDE ohne COLORTERM, mit TERM=vt100 oder NO_COLOR=1 startet
|
||||
- **THEN** gibt sie unverändert absolute RGB-Werte aus, insbesondere Codehintergrund #0000AA und Titelhintergrund #AA00AA
|
||||
|
||||
#### Scenario: Freie Fensterfläche
|
||||
- **WHEN** der Desktop ein Füllzeichen enthält oder sich Fenster überdecken und im Editor Text eingegeben, markiert und die Auswahl aufgehoben wird
|
||||
- **THEN** bleiben unbeschriebene Fensterzellen echte Leerzeichen in der jeweiligen Fensterfarbe ohne Desktopmuster oder verdeckte Inhalte
|
||||
@@ -0,0 +1,40 @@
|
||||
## Purpose
|
||||
|
||||
Belegt die tatsächliche Terminalbedienbarkeit der IDE und erzeugter Programme auf allen vereinbarten System-/Architektur-Kombinationen.
|
||||
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Vollständige Ziel- und Terminalmatrix
|
||||
Die Plattformabnahme SHALL Windows amd64 mit Windows Terminal, macOS arm64 mit einem benannten Terminal sowie Linux amd64 und arm64 jeweils mit mindestens zwei verschiedenen Terminalemulatoren prüfen. Je Matrixzelle SHALL Ziel, Betriebssystem-, Terminal- und Programmversion sowie die geprüfte Revision dokumentiert sein. Reines Cross-Kompilieren MUST NOT als Ausführungsnachweis gelten.
|
||||
|
||||
#### Scenario: Ziel wurde nur gebaut
|
||||
- **WHEN** ein Linux-arm64-Artefakt zwar kompiliert, aber auf keinem passenden Ziel ausgeführt wurde
|
||||
- **THEN** bleibt dessen Ausführungsnachweis offen und die vollständige Plattformabnahme gilt nicht als bestanden
|
||||
|
||||
### Requirement: Reale Eingabe und Darstellung
|
||||
Die Matrix SHALL F1–F12, relevante Shift-/Ctrl-/Alt-Kombinationen, Menünavigation, Mausdruck/-loslassen/-bewegung, Unicode, Farben und Größenänderung für IDE und repräsentative erzeugte Programme prüfen. Die IDE-Farbprüfung SHALL das geltende VBDOS-Theme einschließlich Kontrast und Zuständen aus `ide-oberflaeche` mit dokumentiertem Farbprofil und tatsächlichen Ansichten abdecken. Eingaben SHALL genau einmal dem zuständigen IDE- oder BASIC-Kontext zugeordnet werden. Unterhalb der Mindestgröße SHALL die Anwendung bedienbar wiederherstellbar bleiben.
|
||||
|
||||
#### Scenario: Tastenkonflikt im Terminal
|
||||
- **WHEN** der Emulator eine IDE-Tastenkombination selbst abfängt
|
||||
- **THEN** dokumentiert der Nachweis diese Grenze und prüft einen erreichbaren alternativen Bedienweg, statt die nicht zugestellte Taste als erfolgreich zu werten
|
||||
|
||||
### Requirement: Wiederherstellung nach Unterbrechung
|
||||
INPUT-Warten, Break/Continue, normaler Exit, Laufzeitfehler und Shell-Rückkehr SHALL Terminalmodus, Eingabe und Anzeige konsistent erhalten beziehungsweise wiederherstellen. Native Programme SHALL diese Regeln ebenso erfüllen wie die IDE.
|
||||
|
||||
#### Scenario: Shell-Kind abbrechen
|
||||
- **WHEN** ein Shell-Kind während einer IDE- oder Programmsitzung unterbrochen wird
|
||||
- **THEN** bleibt die übergeordnete Sitzung bedienbar und nach ihrem Ende sind Terminalmodus und Anzeige wiederhergestellt
|
||||
|
||||
### Requirement: Nachprüfbare Einschränkungen
|
||||
Einschränkungen SHALL reproduzierbar, plattformspezifisch und mit Auswirkung sowie Ersatzweg beschrieben sein. Ein Produktfehler ohne funktionsgleichen erreichbaren Weg MUST als offener Befund gelten; reine TestBackend-Ergebnisse MUST NOT manuelle Emulatorprüfungen ersetzen.
|
||||
|
||||
#### Scenario: Fehlender Prüfrechner
|
||||
- **WHEN** eine erforderliche System-/Emulatorkombination nicht verfügbar ist
|
||||
- **THEN** nennt der Bericht die fehlende Kombination und führt sie bis zum tatsächlichen Nachweis offen
|
||||
|
||||
### Requirement: Identische Bibliothek auf vier Zielsystemen
|
||||
Die Plattformabnahme SHALL dieselben unveränderten TBL-Bytes aus Change 03 auf Windows amd64, macOS arm64 und Linux amd64/arm64 mit separaten BASIC-Verbrauchern zu TBC und eigenständigem Executable verknüpfen und tatsächlich ausführen. Library-Quellen SHALL nicht benötigt werden; Resultate und RUN-Neustart SHALL dem gemeinsamen Soll entsprechen. Jeder Nachweis SHALL TBL-Prüfsumme, Toolrevision, tatsächliches Host-Target und Ergebnis enthalten. Der zentrale Cross-Build in Change 06 MUST NOT diese Zielausführung ersetzen; separate Prüfsysteme und dokumentierte manuelle Läufe sind zulässig.
|
||||
|
||||
#### Scenario: Cross-Bau erfolgreich, Bibliothekslauf fehlt
|
||||
- **WHEN** alle vier Toolpakete gebaut sind, aber die gemeinsame TBL-Probe auf Windows noch nicht ausgeführt wurde
|
||||
- **THEN** bleibt der Windows-Verbrauchernachweis offen und die Plattformabnahme ist nicht abgeschlossen
|
||||
@@ -0,0 +1,18 @@
|
||||
## MODIFIED Requirements
|
||||
|
||||
### Requirement: Klassische Farbpalette und Blink-Simulation
|
||||
Der Bildschirm SHALL die klassische Palette abbilden (Vordergrund 0–15,
|
||||
Hintergrund 0–7) als feste 24-Bit-RGB-Werte ausgeben, unabhängig von Terminalprofil
|
||||
und Farberkennung (klassisch 1 = #0000AA, 4 = #AA0000). Dieselbe
|
||||
Abbildung SHALL für IDE, Formularvorschau und BASIC-Ausgabe gelten;
|
||||
programmbestimmte Farbnummern SHALL unverändert bleiben. Blinkende Vordergrundfarben (16–31) SHALL als „hell"
|
||||
simuliert werden (Farbe − 16, Intensitätsbit gesetzt) — kein echtes
|
||||
Terminal-Blinken.
|
||||
|
||||
#### Scenario: Blink wird hell
|
||||
- **WHEN** `COLOR 17, 0` gesetzt wird (blinkend Blau)
|
||||
- **THEN** wird mit heller Vordergrundfarbe 9 gerendert
|
||||
|
||||
#### Scenario: Programmbestimmte absolute Farbe
|
||||
- **WHEN** ein Programm COLOR 7, 1 oder entsprechende ForeColor-/BackColor-Eigenschaften verwendet
|
||||
- **THEN** wird #AAAAAA auf #0000AA ausgegeben, auch bei abweichender ANSI-Palette und ohne COLORTERM
|
||||
@@ -0,0 +1,28 @@
|
||||
## 1. Prüfpfade vorbereiten
|
||||
|
||||
- [x] 1.1 Verbindliche Matrix und kurze Bediensequenzen für die vier Targets anlegen; Windows Terminal, Terminal.app sowie xterm/VTE auf beiden Linux-Architekturen müssen konkrete Versions-/Revisionsfelder und erwartete Resultate besitzen.
|
||||
- [ ] 1.2 Bestehenden Unix-PTY-Test und passenden Windows-Konsolen-/ConPTY-Test für Shell, Abbruch und Wiederherstellung bereitstellen; positive Läufe und erzwungene Fehler dürfen keinen beschädigten Terminalmodus hinterlassen.
|
||||
- [x] 1.3 Die gemeinsame TBL-Verbraucherprobe aus 03 samt fester Prüfsumme in jede der vier Zielabnahmen aufnehmen (quellfreies TBC/EXE, RUN, tatsächliches Host-Target); IDE-/Programmprüfungen für F1–F12, Modifikatoren, Maus, Unicode/Attribute und Resize nachvollziehbar auflisten; jeder Fall muss sichtbaren Effekt und Ausschluss doppelter BASIC-Zustellung prüfen.
|
||||
|
||||
## 2. Tatsächliche Zielabnahme
|
||||
|
||||
- [ ] 2.1 Windows amd64 in Windows Terminal prüfen; Protokoll muss IDE, exportiertes Forms-Programm, INPUT/Break und Shell-Rückkehr mit tatsächlicher Zielausführung belegen.
|
||||
- [ ] 2.2 macOS arm64 in Terminal.app prüfen; zusätzlich finalisierte/signierte native Ausgaben starten und die Ergebnisse mit der Matrix abgleichen.
|
||||
- [ ] 2.3 Linux amd64 in xterm und einem VTE-Terminal prüfen; beide Emulatoren müssen dieselben Pflichtfunktionen beziehungsweise dokumentierte funktionierende Ersatzwege liefern.
|
||||
- [ ] 2.4 Linux arm64 in xterm und einem VTE-Terminal prüfen; Cross-Build allein darf keinen Fall abschließen.
|
||||
- [ ] 2.5 Gefundene Produktfehler im zuständigen Adapter beheben; gezielter Regressionstest und erneuter betroffener Emulatorlauf müssen den Befund schließen.
|
||||
|
||||
## 3. Übergabe
|
||||
|
||||
- [ ] 3.1 Terminalgrenzen und verifizierte Ersatzwege dokumentieren; kein Produktfehler oder fehlender Prüfrechner darf als bestandene Matrixzelle erscheinen.
|
||||
- [ ] 3.2 Automatisierbare Zielprüfungen an 06 übergeben und Matrixbericht fertigstellen; alle Pflichtzellen, Revisionen, vier Ergebnisse derselben TBL-Verbraucherprobe und tatsächlichen Ergebnisse müssen vor Abschluss vorliegen. Die weiterhin offenen Archivaufgaben 05a/1.2 (konkretes Benutzerprofil, frische/gespeicherte Optionen, Transparenz/Dimmung), 05a/3.2 (visuelle Matrix) und 05a/3.3 (befundfreie Schlussverifizierung) müssen hier tatsächlich abgeschlossen werden. Die visuellen Nachweise müssen das umgesetzte Theme aus 05a einschließlich Profil-/Farbmodus und relevanter UI-Zustände abdecken. Native Prüfsysteme dürfen separat vom zentralen Buildrunner betrieben und Nachweise dokumentiert manuell erhoben werden.
|
||||
|
||||
Arbeitsstand 07.09.2026: Matrix/Bedienfolgen in `docs/plattformmatrix.md`, Eingabeprobe `tests/platform/input.frm`, gemeinsamer Aufruf `tests/support/platform-abnahme.py`. 1.2 ist implementiert und für Windows cross-geprüft, bleibt bis zum tatsächlichen Windows-Konsolenlauf offen. Automatisierte macOS-arm64-Nachweise liegen unter `evidence/2026-09-07-macos-arm64`; sie schließen keine manuelle Terminalzelle. Details und offene Befunde: `verification.md`.
|
||||
|
||||
RGB-Korrektur nach Benutzerbefund vom 07.09.2026 gehört zu 2.5: keine
|
||||
ANSI-/256-Fallbackfarben; gemeinsame feste RGB-Palette für IDE und BASIC;
|
||||
Fensterflächen ohne durchscheinendes Desktopmuster. Neue Delta-Spezifikationen
|
||||
in `ide-oberflaeche` und `textbildschirm` ersetzen den früheren Fallbackvertrag.
|
||||
Der Benutzer bestätigt den korrigierten Farbtest am 07.09.2026 mit „test is good“.
|
||||
Archivierung ausdrücklich beauftragt; acht unvollständige Matrixaufgaben bleiben
|
||||
als Nachweisbedarf an 06/07 übergeben, nicht als bestandene Prüfungen markiert.
|
||||
@@ -0,0 +1,163 @@
|
||||
# Verifizierung: phase-6-05-plattformmatrix
|
||||
|
||||
Stand 07.09.2026. Basis ist der auf Origin bestätigte Commit
|
||||
`5aa920b768a2ad29ed17c5da137e54675a7292d6` plus der lokale Change-05-Diff.
|
||||
05a wurde auf Benutzeranweisung synchronisiert und mit den ausdrücklich
|
||||
weiterhin offenen Nachweisen 1.2/3.2/3.3 archiviert. Diese Nachweise werden
|
||||
hier weitergeführt; Archivierung wurde nicht als bestandene Zielprüfung gewertet.
|
||||
|
||||
## Ergebnis
|
||||
|
||||
| Dimension | Stand |
|
||||
|---|---|
|
||||
| Vollständigkeit | 2/10 Aufgaben abgeschlossen; acht Aufgaben mit fehlenden echten Zielnachweisen offen |
|
||||
| Korrektheit | Lokale Workspace-, native macOS-/TBL-/PTY- und Eingabeprüfungen bestanden; Windows-Code einschließlich Konsolentest cross-geprüft, nicht auf Windows ausgeführt |
|
||||
| Kohärenz | Bestehende Prüfskripte, Formular-Engine und TerminalGuard wiederverwendet; keine neue Abhängigkeit, keine Änderung an Runnerdiensten |
|
||||
|
||||
Der Change wird am 07.09.2026 auf ausdrückliche Benutzeranweisung archiviert.
|
||||
Der Benutzer hat die RGB-/Fensterflächenkorrektur mit „test is good“ bestätigt.
|
||||
Ein vollständiger Pflichtmatrixlauf ist weiterhin nicht belegt. Die acht
|
||||
unvollständigen Aufgaben bleiben im Archiv sichtbar und werden für die
|
||||
Paketfreigabe in 06 und die Phasenabnahme in 07 weitergeführt. Archivierung
|
||||
und Benutzerbestätigung des Farbtests ersetzen diese Nachweise nicht.
|
||||
|
||||
## Umsetzung
|
||||
|
||||
- `docs/plattformmatrix.md`: sechs verbindliche Emulatorzellen für vier
|
||||
Ziele, Versions-/Revisionsfelder, gesamte F1–F12-/Modifierfolge, Eingabe,
|
||||
Maus, Unicode, Resize, INPUT/Break, Shell und Theme-Gegenprobe aus 05a.
|
||||
Nicht ausgeführte Fälle und fehlende Ersatzwege sind ausdrücklich offen.
|
||||
- `tests/support/platform-abnahme.py`: führt vorhandene native-, Library-
|
||||
und Unix-PTY-Prüfungen auf dem tatsächlich erkannten Ziel aus. Bericht
|
||||
bindet Ziel, Checkout-/Diffstand, Skript- und Executable-Prüfsummen sowie
|
||||
die unveränderte TBL-Prüfsumme. Fehlende Windows-Konsolenprobe verhindert
|
||||
ein positives automatisiertes Gesamtergebnis. Manuelle Matrix bleibt
|
||||
ausdrücklich `not_run` / `matrix_complete: false`.
|
||||
- `tests/support/ide-execution-pty.py`: bestehende drei Bedienpfade erhalten;
|
||||
jetzt mit explizitem Kandidatenpfad und gespeicherten ANSI-Transkripten.
|
||||
- `tests/platform/input.frm`: interaktive Ereignis-/Zählerprobe für IDE und
|
||||
nativen Export. `crates/tb-ide/tests/execution.rs` prüft eine normale Taste
|
||||
einschließlich zusätzlichem rohem Release genau einmal, sowie F1 im
|
||||
IDE-Codekontext ohne zusätzliche BASIC-Zustellung.
|
||||
- `crates/tb-ui/examples/spike.rs`: vorhandene Rohdiagnose um nummeriertes
|
||||
Ereignislog erweitert; keine Überschreibung bestehender Logs. Der gemeinsame
|
||||
TerminalGuard übernimmt auch hier Cleanup bei Fehlern.
|
||||
- `crates/tb-ui/src/terminal.rs`: Windows-Eingabe-/Ausgabemodi werden vor dem
|
||||
Einstieg gesichert und bei Shell-Übergabe, Fehler und Ende wiederhergestellt.
|
||||
Der vorhandene Crossterm-Code setzte Raw-Flags pauschal zurück. Zusätzlich
|
||||
wird ANSI-Verarbeitung bei erneutem Eintritt aktiviert, weil Crossterm
|
||||
die Fähigkeit zwischenspeichert. Der neue explizite Windows-Test verwendet
|
||||
eine eigene Kindkonsole, Nichtstandard-Echozustand und begrenzte Laufzeit.
|
||||
Er deckt Shell 0/7, Abbruch, Rückkehr, Renderfehler und Teilinitialisierung ab.
|
||||
Die vorhandene Abbruchprüfung verlangt nicht länger einen Unix-spezifischen
|
||||
Exitcode auf Windows und erzeugt dort keinen verbleibenden Ping-Unterprozess.
|
||||
|
||||
API-Grundlage der Windows-Korrektur:
|
||||
[GetConsoleMode](https://learn.microsoft.com/en-us/windows/console/getconsolemode),
|
||||
[SetConsoleMode](https://learn.microsoft.com/en-us/windows/console/setconsolemode).
|
||||
Der tatsächliche Windows-Lauf bleibt Voraussetzung, um den Befund zu schließen.
|
||||
|
||||
## Ausgeführte Prüfungen
|
||||
|
||||
- `cargo test --locked --workspace`: **638 bestandene Testergebnisse,
|
||||
0 Fehler, 3 bestehende ignorierte Tests**. Die zusätzliche Windows-Prüfung
|
||||
ist auf macOS nicht enthalten und wurde nicht als bestanden gezählt.
|
||||
- `cargo check --locked --target x86_64-pc-windows-msvc -p tb-ui --features terminal --tests`:
|
||||
bestanden; ebenso Cross-Checks von IDE, CLI, Export und deren Targets.
|
||||
- Clippy für tb-ui/tb-ide inklusive aller Targets sowie für die
|
||||
Windows-Konsolentests mit `-D warnings`: bestanden.
|
||||
- Release-Build von tb/tbc/tbrt/tb-template und Spike: bestanden.
|
||||
- `platform-abnahme.py --bin-dir target/release`: auf macOS arm64 bestanden.
|
||||
Aktuelle Einzelbelege nach RGB-Korrektur im Verzeichnis
|
||||
`evidence/2026-09-07-macos-arm64-rgb`: native
|
||||
Console-/Forms-/Fehler-/RUN-/Mehrmodul- und quellfreie Exporte,
|
||||
CLI/native INPUT und Abbruch in Unix-PTY, Exportabbruch und Korruptionsfälle,
|
||||
dieselbe portable.tbl mit quellfreier TBC-/EXE-Nutzung und RUN,
|
||||
IDE-Shell 7, Kindabbruch und File→Shell mit Wiederherstellung.
|
||||
- Die Probe wurde separat kompiliert; IDE-Ereignistest besteht.
|
||||
Spike wurde headless über Unix-PTY mit x/Esc geprüft: genau zwei
|
||||
nummerierte Rohereignisse und ursprüngliche Terminalattribute nach Ende.
|
||||
Wiederverwendung desselben Logpfads wurde ohne Überschreiben abgelehnt.
|
||||
- Negativprüfung des Sammelaufrufs mit fehlenden Binaries: Exit 2,
|
||||
verständlicher Fehler, kein erzeugter Erfolgsreport.
|
||||
|
||||
Der erste ad-hoc Spike-Prüfversuch mit Python-preexec blieb beim Start hängen;
|
||||
die eigenen Prüfprozesse wurden beendet. Der erfolgreiche Wiederholungslauf
|
||||
verwendete dasselbe Fork-/Sitzungsbesitzmuster wie die bestehende IDE-PTY-Probe.
|
||||
Dies ist kein visueller Emulatornachweis. Rohlogs und Testergebnisse werden
|
||||
nur für die tatsächlich ausgeführten Pfade gewertet.
|
||||
|
||||
## RGB-Korrektur nach erneutem Benutzerbefund
|
||||
|
||||
Der Screenshot vom 07.09.2026 um 20:54 zeigte zwei Produktfehler:
|
||||
Die Farbabbildung konnte weiterhin auf Terminalprofilfarben zurückfallen;
|
||||
außerdem änderten Block/Paragraph nur Zellstile, sodass das Desktopzeichen
|
||||
`▒` in unbeschriebenen Fensterflächen stehen blieb. Dieses Muster mischte
|
||||
optisch Vorder-/Hintergrund und erklärte die hellere Fläche neben dem Text.
|
||||
|
||||
- IDE und BASIC verwenden jetzt die gemeinsame feste DOS-RGB-Palette in
|
||||
`tb-ui::screen::basic_color`; keine Farberkennung oder Indexfarben mehr.
|
||||
TerminalGuard aktiviert Farbausgabe auch bei `NO_COLOR`. Gespeicherte
|
||||
DOS-Farbnummern und BASIC-ForeColor/BackColor bleiben erhalten.
|
||||
- Jedes Fenster wird vor dem Rendern geleert. Der neue Regressionstest
|
||||
scheiterte vor der Korrektur mit `Desktop in Fenster bei 9/2` und besteht
|
||||
danach einschließlich Auswahlwechsel und überlappenden Fenstern.
|
||||
- Vier Theme-Tests bestehen mit `TERM=vt100 COLORTERM= NO_COLOR=1`.
|
||||
Der echte Release-Prozess besteht zusätzlich alle drei IDE-PTY-Pfade mit
|
||||
`env -u COLORTERM TERM=vt100 NO_COLOR=1`; Transkripte enthalten explizit
|
||||
`38;2;170;170;170`, `48;2;0;0;170`, `48;2;170;0;170`, keine Indexfarben
|
||||
und keine OSC-Palettenänderungen. Auch Shell-Rückkehr besteht.
|
||||
- Workspace: 638 bestanden, 0 Fehler, 3 bestehende ignorierte Tests.
|
||||
Clippy, Windows-Cross-Check und OpenSpec (30/30) bestehen. Debug-tb und
|
||||
Release-tb/tbc/tbrt/tb-template/Spike neu gebaut. Native-, TBL- und
|
||||
IDE-PTY-Abnahme mit diesen Release-Artefakten erneut bestanden.
|
||||
- Neue Delta-Spezifikationen in diesem Change ändern `ide-oberflaeche` und
|
||||
`textbildschirm` entsprechend der verbindlichen Benutzerkorrektur.
|
||||
Frühere ANSI-/256-Fallback-Verträge im Archiv dokumentieren nur den alten
|
||||
Stand; die Synchronisierung der neuen Deltas erfolgt beim Abschluss von 05.
|
||||
|
||||
Belege: `evidence/2026-09-07-macos-arm64-rgb`. Der gespeicherte Diff stimmt
|
||||
mit dem Hash des Zielberichts überein; spätere Berichtsänderungen betreffen
|
||||
keinen geprüften Produktcode. Das ältere Verzeichnis ohne `-rgb` belegt den
|
||||
Vorgängerstand und ist kein Nachweis für die aktuelle Farbausgabe.
|
||||
Der Benutzer hat den Farbtest am 07.09.2026 als erfolgreich bestätigt.
|
||||
Diese Bestätigung schließt den gemeldeten RGB-/Fensterflächenbefund; eine
|
||||
vollständige versionsgebundene Emulatorfolge wurde damit nicht bestätigt.
|
||||
|
||||
Benutzerentscheidung: Windows-Ausführung vorerst offen lassen. DOSBox ist
|
||||
kein Windows-PE-Prüfsystem. Linux nutzt denselben ANSI-/RGB-Pfad wie macOS;
|
||||
das begründet eine Verhaltenserwartung, ersetzt aber keine xterm-/VTE-Zielprüfung.
|
||||
|
||||
## Offene Befunde
|
||||
|
||||
Jede der folgenden Aufgaben bleibt CRITICAL für die vollständige Abnahme:
|
||||
|
||||
| Aufgabe | Fehlender Nachweis / erforderliche Aktion |
|
||||
|---|---|
|
||||
| 1.2 | Windows-Konsolenprüfung auf echtem Windows ausführen; Code/Cross-Check vorhanden, die Wiederherstellung einschließlich Fehlerpfaden ist dort noch nicht bewiesen. |
|
||||
| 2.1 | Windows amd64 in Windows Terminal: IDE, natives Formular, INPUT/Break, Shell und TBL tatsächlich ausführen und protokollieren. |
|
||||
| 2.2 | Terminal.app auf macOS arm64 manuell prüfen. Native/PTY-/TBL-Läufe sind bestanden, die echte Emulatorbedienung und Theme-Gegenprobe fehlen. |
|
||||
| 2.3 | Linux amd64 in xterm und VTE einschließlich derselben TBL tatsächlich prüfen. |
|
||||
| 2.4 | Linux arm64 in xterm und VTE einschließlich derselben TBL tatsächlich prüfen. |
|
||||
| 2.5 | Windows-Wiederherstellungsbefund durch den tatsächlichen Zieltest schließen. Code und lokale Regressionen bestehen. |
|
||||
| 3.1 | Reservierte Shortcuts und gegebenenfalls funktionierende Ersatzwege in den echten Emulatoren belegen. Regeln sind dokumentiert, keine Ersatzwege ohne Versuch als erfolgreich eingetragen. |
|
||||
| 3.2 | Alle Pflichtmatrixzellen und TBL-Ergebnisse vervollständigen, 05a-Profil-/Theme-Gegenprobe und abschließende Verifizierung schließen; danach aktuelle revisions-/artefaktgebundene Nachweise an 06/07 übergeben. |
|
||||
|
||||
### Verfügbare Systeme und konkrete Grenzen
|
||||
|
||||
- Lokal bestätigt: macOS 26.6.2 (25G83), arm64; Terminal.app 2.15 ist
|
||||
installiert. Computer Use hat den Zugriff auf Terminal.app im früheren
|
||||
Versuch ausdrücklich gesperrt. Ein automatisierter PTY-Lauf ersetzt den
|
||||
erforderlichen manuellen Lauf nicht; die Sperre wird nicht umgangen.
|
||||
- Windows sowie Linux mit xterm/VTE: bislang kein nutzbarer Zugang benannt.
|
||||
- Gitea-Host: read-only als Linux aarch64 bestätigt, die benötigten
|
||||
GUI-Terminals fehlen. Der Runnercontainer meldete beim Lesezugriff
|
||||
`status=restarting`, `restarts=2319`, letzter Start
|
||||
`2026-09-07T18:49:08.081383305Z`. Es wurden keine Dienste oder
|
||||
Runnerkonfigurationen verändert. Das ist ein Infrastrukturzustand,
|
||||
keine ausgeführte Zielabnahme.
|
||||
|
||||
Für die fehlenden Systeme sind Zugänge beziehungsweise ausgefüllte manuelle
|
||||
Prüfprotokolle nötig. Nach deren Eingang die vorbereitete Folge ausführen,
|
||||
Befunde beheben und betroffene Prüfungen wiederholen; bis dahin bleiben
|
||||
Aufgaben und Matrixzellen offen.
|
||||
Reference in New Issue
Block a user