mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2026-01-31 19:06:41 +01:00
dsl, output, tui: add tests, examples, root dispatchers
This commit is contained in:
parent
8dfe20a58c
commit
ca862b9802
16 changed files with 637 additions and 377 deletions
|
|
@ -1,59 +0,0 @@
|
|||
#![feature(type_changing_struct_update)]
|
||||
mod tui_engine; pub use self::tui_engine::*;
|
||||
mod tui_content; pub use self::tui_content::*;
|
||||
pub(crate) use ::tengri_core::*;
|
||||
#[cfg(feature = "dsl")] pub use ::tengri_dsl::*;
|
||||
pub use ::tengri_input as input; pub(crate) use ::tengri_input::*;
|
||||
pub use ::tengri_output as output; pub(crate) use ::tengri_output::*;
|
||||
pub(crate) use atomic_float::AtomicF64;
|
||||
pub use ::better_panic; pub(crate) use ::better_panic::{Settings, Verbosity};
|
||||
pub use ::palette; pub(crate) use ::palette::{*, convert::*, okhsl::*};
|
||||
pub use ::crossterm; pub(crate) use ::crossterm::{
|
||||
ExecutableCommand,
|
||||
terminal::{EnterAlternateScreen, LeaveAlternateScreen, enable_raw_mode, disable_raw_mode},
|
||||
event::{Event, KeyEvent, KeyCode, KeyModifiers, KeyEventKind, KeyEventState},
|
||||
};
|
||||
pub use ::ratatui; pub(crate) use ratatui::{
|
||||
prelude::{Color, Style, Buffer},
|
||||
style::Modifier,
|
||||
backend::{Backend, CrosstermBackend, ClearType},
|
||||
layout::{Size, Rect},
|
||||
buffer::Cell
|
||||
};
|
||||
pub(crate) use std::sync::{Arc, RwLock, atomic::{AtomicBool, Ordering::*}};
|
||||
pub(crate) use std::io::{stdout, Stdout};
|
||||
#[cfg(test)] #[test] fn test_tui_engine () -> Usually<()> {
|
||||
use crate::*;
|
||||
//use std::sync::{Arc, RwLock};
|
||||
struct TestComponent(String);
|
||||
impl Content<TuiOut> for TestComponent {
|
||||
fn content (&self) -> impl Draw<TuiOut> {
|
||||
Some(self.0.as_str())
|
||||
}
|
||||
}
|
||||
impl Handle<TuiIn> for TestComponent {
|
||||
fn handle (&mut self, _from: &TuiIn) -> Perhaps<bool> {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
let engine = Tui::new()?;
|
||||
engine.read().unwrap().exited.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
let state = TestComponent("hello world".into());
|
||||
let _state = std::sync::Arc::new(std::sync::RwLock::new(state));
|
||||
//engine.run(&state)?;
|
||||
Ok(())
|
||||
}
|
||||
#[cfg(test)] #[test] fn test_parse_key () {
|
||||
//use KeyModifiers as Mods;
|
||||
let _test = |x: &str, y|assert_eq!(KeyMatcher::new(x).build(), Some(Event::Key(y)));
|
||||
//test(":x",
|
||||
//KeyEvent::new(KeyCode::Char('x'), Mods::NONE));
|
||||
//test(":ctrl-x",
|
||||
//KeyEvent::new(KeyCode::Char('x'), Mods::CONTROL));
|
||||
//test(":alt-x",
|
||||
//KeyEvent::new(KeyCode::Char('x'), Mods::ALT));
|
||||
//test(":shift-x",
|
||||
//KeyEvent::new(KeyCode::Char('x'), Mods::SHIFT));
|
||||
//test(":ctrl-alt-shift-x",
|
||||
//KeyEvent::new(KeyCode::Char('x'), Mods::CONTROL | Mods::ALT | Mods::SHIFT ));
|
||||
}
|
||||
78
tui/src/tui.rs
Normal file
78
tui/src/tui.rs
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
#![feature(type_changing_struct_update)]
|
||||
#[cfg(test)] mod tui_test;
|
||||
mod tui_engine; pub use self::tui_engine::*;
|
||||
mod tui_content; pub use self::tui_content::*;
|
||||
pub use ::{
|
||||
tengri_input,
|
||||
tengri_output,
|
||||
ratatui,
|
||||
crossterm,
|
||||
palette,
|
||||
better_panic
|
||||
};
|
||||
pub(crate) use ::{
|
||||
tengri_core::*,
|
||||
tengri_input::*,
|
||||
tengri_output::*,
|
||||
atomic_float::AtomicF64,
|
||||
std::{io::{stdout, Stdout}, sync::{Arc, RwLock, atomic::{AtomicBool, Ordering::*}}},
|
||||
better_panic::{Settings, Verbosity},
|
||||
palette::{*, convert::*, okhsl::*},
|
||||
ratatui::{
|
||||
prelude::{Color, Style, Buffer},
|
||||
style::Modifier,
|
||||
backend::{Backend, CrosstermBackend, ClearType},
|
||||
layout::{Size, Rect},
|
||||
buffer::Cell
|
||||
},
|
||||
crossterm::{
|
||||
ExecutableCommand,
|
||||
terminal::{EnterAlternateScreen, LeaveAlternateScreen, enable_raw_mode, disable_raw_mode},
|
||||
event::{Event, KeyEvent, KeyCode, KeyModifiers, KeyEventKind, KeyEventState},
|
||||
}
|
||||
};
|
||||
|
||||
#[cfg(feature = "dsl")] use tengri_dsl::*;
|
||||
#[cfg(feature = "dsl")]
|
||||
pub fn evaluate_output_expression_tui <'a, S> (
|
||||
state: &S, mut output: &mut TuiOut, expr: impl DslExpr + 'a
|
||||
) -> Usually<bool> where
|
||||
S: View<TuiOut, ()>
|
||||
+ for<'b>DslNs<'b, bool>
|
||||
+ for<'b>DslNs<'b, u16>
|
||||
+ for<'b>DslNs<'b, Color>
|
||||
{
|
||||
// See `tengri_output::evaluate_output_expression`
|
||||
let head = expr.head()?;
|
||||
let mut frags = head.src()?.unwrap_or_default().split("/");
|
||||
let args = expr.tail();
|
||||
let arg0 = args.head();
|
||||
let tail0 = args.tail();
|
||||
let arg1 = tail0.head();
|
||||
let tail1 = tail0.tail();
|
||||
let arg2 = tail1.head();
|
||||
match frags.next() {
|
||||
|
||||
Some("text") => if let Some(src) = args?.src()? { output.place(&src) },
|
||||
|
||||
Some("fg") => {
|
||||
let arg0 = arg0?.expect("fg: expected arg 0 (color)");
|
||||
output.place(&Tui::fg(
|
||||
DslNs::<Color>::from(state, arg0)?.unwrap_or_else(||panic!("fg: {arg0:?}: not a color")),
|
||||
Thunk::new(move|output: &mut TuiOut|state.view(output, &arg1).unwrap()),
|
||||
))
|
||||
},
|
||||
|
||||
Some("bg") => {
|
||||
let arg0 = arg0?.expect("bg: expected arg 0 (color)");
|
||||
output.place(&Tui::bg(
|
||||
DslNs::<Color>::from(state, arg0)?.unwrap_or_else(||panic!("bg: {arg0:?}: not a color")),
|
||||
Thunk::new(move|output: &mut TuiOut|state.view(output, &arg1).unwrap()),
|
||||
))
|
||||
},
|
||||
|
||||
_ => return Ok(false)
|
||||
|
||||
};
|
||||
Ok(true)
|
||||
}
|
||||
|
|
@ -37,6 +37,14 @@ impl Tui {
|
|||
}
|
||||
});
|
||||
|
||||
#[macro_export] macro_rules! tui_content ((|$self:ident:$Self:ty|$sexpr:expr)=>{
|
||||
impl Content<TuiOut> for $Self {
|
||||
fn content (&$self) -> impl Draw<TuiOut> + Layout<TuiOut> + '_ {
|
||||
$expr
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mod tui_border; pub use self::tui_border::*;
|
||||
mod tui_button; pub use self::tui_button::*;
|
||||
mod tui_color; pub use self::tui_color::*;
|
||||
|
|
|
|||
35
tui/src/tui_test.rs
Normal file
35
tui/src/tui_test.rs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
use crate::*;
|
||||
#[test] fn test_tui_engine () -> Usually<()> {
|
||||
//use std::sync::{Arc, RwLock};
|
||||
struct TestComponent(String);
|
||||
impl Content<TuiOut> for TestComponent {
|
||||
fn content (&self) -> impl Draw<TuiOut> + Layout<TuiOut> {
|
||||
Some(self.0.as_str())
|
||||
}
|
||||
}
|
||||
impl Handle<TuiIn> for TestComponent {
|
||||
fn handle (&mut self, _from: &TuiIn) -> Perhaps<bool> {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
let engine = Tui::new()?;
|
||||
engine.read().unwrap().exited.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
let state = TestComponent("hello world".into());
|
||||
let _state = std::sync::Arc::new(std::sync::RwLock::new(state));
|
||||
//engine.run(&state)?;
|
||||
Ok(())
|
||||
}
|
||||
//#[test] fn test_parse_key () {
|
||||
////use KeyModifiers as Mods;
|
||||
//let _test = |x: &str, y|assert_eq!(KeyMatcher::new(x).build(), Some(Event::Key(y)));
|
||||
////test(":x",
|
||||
////KeyEvent::new(KeyCode::Char('x'), Mods::NONE));
|
||||
////test(":ctrl-x",
|
||||
////KeyEvent::new(KeyCode::Char('x'), Mods::CONTROL));
|
||||
////test(":alt-x",
|
||||
////KeyEvent::new(KeyCode::Char('x'), Mods::ALT));
|
||||
////test(":shift-x",
|
||||
////KeyEvent::new(KeyCode::Char('x'), Mods::SHIFT));
|
||||
////test(":ctrl-alt-shift-x",
|
||||
////KeyEvent::new(KeyCode::Char('x'), Mods::CONTROL | Mods::ALT | Mods::SHIFT ));
|
||||
//}
|
||||
Loading…
Add table
Add a link
Reference in a new issue