Phase 0: Referenzdokumente, Fehlerkatalog, Testkorpus, Ratatui-Spike
Entscheidungen festgehalten: TBVM bestaetigt und eingebettet in die Executables; durchgaengig UTF-8 statt CP437 (dokumentierte Abweichung). - docs/: Sprachreferenz, Forms-Referenz, Dateiformate, TBVM-Design - tb-runtime::errors: klassischer Laufzeitfehler-Katalog (implementiert) - tb-ui::screen: 80x25-Unicode-Zellenpuffer mit 16-Farben-Abbildung, Scrollbereich (VIEW PRINT), Letterboxing; Ratatui-Widget + Tests - Spike: cargo run -p tb-ui --example spike (Farben, Unicode, Tasten, Maus) - tests/compat/: erste Referenzprogramme mit byte-genauer Sollausgabe Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
90
crates/tb-ui/examples/spike.rs
Normal file
90
crates/tb-ui/examples/spike.rs
Normal file
@@ -0,0 +1,90 @@
|
||||
//! Phase-0-Spike: 80×25-Bildschirmpuffer, 16-Farben-Palette, Unicode,
|
||||
//! Tastatur- und Mausereignisse.
|
||||
//!
|
||||
//! Start: `cargo run -p tb-ui --example spike` — 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 std::time::Duration;
|
||||
use tb_ui::screen::TextScreen;
|
||||
|
||||
fn testbild(s: &mut TextScreen) {
|
||||
s.set_color(15, 1);
|
||||
s.print(&format!("{:^80}", "Terminal Basic — Phase-0-Spike (Esc beendet)"));
|
||||
|
||||
// Farbraster: alle Vordergrundfarben auf allen Hintergründen
|
||||
for bg in 0u8..8 {
|
||||
s.set_color(15, 0);
|
||||
s.locate(3 + bg as usize, 3).unwrap();
|
||||
s.print(&format!("HG {bg} "));
|
||||
for fg in 0u8..16 {
|
||||
s.set_color(fg, bg);
|
||||
s.print(&format!(" {fg:2}"));
|
||||
}
|
||||
}
|
||||
|
||||
// Unicode statt CP437: Rahmen, Umlaute, Symbole
|
||||
s.set_color(14, 0);
|
||||
s.locate(12, 3).unwrap();
|
||||
s.print("┌─ Unicode ────────────────────────────┐");
|
||||
s.locate(13, 3).unwrap();
|
||||
s.print("│ Äpfel, Öl, Übermaß, ß — ☃ ♥ ♦ ♣ ♠ π λ │");
|
||||
s.locate(14, 3).unwrap();
|
||||
s.print("└──────────────────────────────────────┘");
|
||||
|
||||
s.set_color(7, 0);
|
||||
s.locate(16, 3).unwrap();
|
||||
s.print("Eingabe (Zeichen erscheinen hier):");
|
||||
s.locate(17, 3).unwrap();
|
||||
}
|
||||
|
||||
fn status(s: &mut TextScreen, text: &str) {
|
||||
let (r, c) = (s.csrlin(), s.pos());
|
||||
s.set_color(0, 7);
|
||||
s.locate(25, 1).unwrap();
|
||||
s.print(&format!("{text:<80.80}"));
|
||||
s.set_color(7, 0);
|
||||
s.locate(r, c).unwrap();
|
||||
}
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let mut terminal = ratatui::init();
|
||||
execute!(stdout(), EnableMouseCapture)?;
|
||||
|
||||
let mut screen = TextScreen::new();
|
||||
testbild(&mut screen);
|
||||
status(&mut screen, "Bereit. Tasten/Maus testen, Esc beendet.");
|
||||
|
||||
loop {
|
||||
terminal.draw(|f| f.render_widget(&screen, f.area()))?;
|
||||
if !event::poll(Duration::from_millis(100))? {
|
||||
continue;
|
||||
}
|
||||
match event::read()? {
|
||||
Event::Key(k) if k.kind != KeyEventKind::Release => match k.code {
|
||||
KeyCode::Esc => break,
|
||||
KeyCode::Char(c) => {
|
||||
screen.print(&c.to_string());
|
||||
status(&mut screen, &format!("Taste: {:?} Modifier: {:?}", k.code, k.modifiers));
|
||||
}
|
||||
KeyCode::Enter => screen.print("\n"),
|
||||
other => status(&mut screen, &format!("Sondertaste: {other:?} Modifier: {:?}", k.modifiers)),
|
||||
},
|
||||
Event::Mouse(m) => {
|
||||
status(
|
||||
&mut screen,
|
||||
&format!("Maus: {:?} bei Spalte {}, Zeile {}", m.kind, m.column + 1, m.row + 1),
|
||||
);
|
||||
}
|
||||
Event::Resize(w, h) => status(&mut screen, &format!("Resize: {w}x{h}")),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
execute!(stdout(), DisableMouseCapture)?;
|
||||
ratatui::restore();
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user