mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2026-01-31 10:56:41 +01:00
Compare commits
3 commits
8c54510f63
...
a933cbe285
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a933cbe285 | ||
|
|
1344967f33 | ||
|
|
b0d2fad17b |
38 changed files with 451 additions and 2317 deletions
42
Cargo.lock
generated
42
Cargo.lock
generated
|
|
@ -285,6 +285,16 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dizzle"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"const_panic",
|
||||||
|
"itertools 0.14.0",
|
||||||
|
"konst",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "document-features"
|
name = "document-features"
|
||||||
version = "0.2.11"
|
version = "0.2.11"
|
||||||
|
|
@ -1045,38 +1055,19 @@ name = "tengri"
|
||||||
version = "0.14.0"
|
version = "0.14.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossterm 0.29.0",
|
"crossterm 0.29.0",
|
||||||
|
"dizzle",
|
||||||
"tengri",
|
"tengri",
|
||||||
"tengri_core",
|
|
||||||
"tengri_dsl",
|
|
||||||
"tengri_input",
|
"tengri_input",
|
||||||
"tengri_output",
|
"tengri_output",
|
||||||
"tengri_proc",
|
"tengri_proc",
|
||||||
"tengri_tui",
|
"tengri_tui",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tengri_core"
|
|
||||||
version = "0.14.0"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tengri_dsl"
|
|
||||||
version = "0.14.0"
|
|
||||||
dependencies = [
|
|
||||||
"const_panic",
|
|
||||||
"itertools 0.14.0",
|
|
||||||
"konst",
|
|
||||||
"proptest",
|
|
||||||
"tengri_core",
|
|
||||||
"tengri_tui",
|
|
||||||
"thiserror",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tengri_input"
|
name = "tengri_input"
|
||||||
version = "0.14.0"
|
version = "0.14.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"tengri_core",
|
"dizzle",
|
||||||
"tengri_dsl",
|
|
||||||
"tengri_tui",
|
"tengri_tui",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -1085,11 +1076,10 @@ name = "tengri_output"
|
||||||
version = "0.14.0"
|
version = "0.14.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
|
"dizzle",
|
||||||
"proptest",
|
"proptest",
|
||||||
"proptest-derive",
|
"proptest-derive",
|
||||||
"tengri",
|
"tengri",
|
||||||
"tengri_core",
|
|
||||||
"tengri_dsl",
|
|
||||||
"tengri_tui",
|
"tengri_tui",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -1097,11 +1087,11 @@ dependencies = [
|
||||||
name = "tengri_proc"
|
name = "tengri_proc"
|
||||||
version = "0.14.0"
|
version = "0.14.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"dizzle",
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
"tengri_core",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -1112,14 +1102,12 @@ dependencies = [
|
||||||
"better-panic",
|
"better-panic",
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"crossterm 0.29.0",
|
"crossterm 0.29.0",
|
||||||
"konst",
|
"dizzle",
|
||||||
"palette",
|
"palette",
|
||||||
"quanta",
|
"quanta",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"ratatui",
|
"ratatui",
|
||||||
"tengri",
|
"tengri",
|
||||||
"tengri_core",
|
|
||||||
"tengri_dsl",
|
|
||||||
"tengri_input",
|
"tengri_input",
|
||||||
"tengri_output",
|
"tengri_output",
|
||||||
"tengri_proc",
|
"tengri_proc",
|
||||||
|
|
|
||||||
10
Cargo.toml
10
Cargo.toml
|
|
@ -9,11 +9,9 @@ lto = false
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
members = [
|
members = [
|
||||||
"./tengri",
|
"./tengri",
|
||||||
"./core",
|
|
||||||
"./input",
|
"./input",
|
||||||
"./output",
|
"./output",
|
||||||
"./tui",
|
"./tui",
|
||||||
"./dsl",
|
|
||||||
"./proc",
|
"./proc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
@ -22,23 +20,20 @@ version = "0.14.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
|
dizzle = { path = "../dizzle" }
|
||||||
|
|
||||||
tengri = { path = "./tengri" }
|
tengri = { path = "./tengri" }
|
||||||
tengri_core = { path = "./core" }
|
|
||||||
tengri_input = { path = "./input" }
|
tengri_input = { path = "./input" }
|
||||||
tengri_output = { path = "./output" }
|
tengri_output = { path = "./output" }
|
||||||
tengri_tui = { path = "./tui" }
|
tengri_tui = { path = "./tui" }
|
||||||
tengri_dsl = { path = "./dsl" }
|
|
||||||
tengri_proc = { path = "./proc" }
|
tengri_proc = { path = "./proc" }
|
||||||
|
|
||||||
anyhow = { version = "1.0" }
|
anyhow = { version = "1.0" }
|
||||||
atomic_float = { version = "1" }
|
atomic_float = { version = "1" }
|
||||||
better-panic = { version = "0.3.0" }
|
better-panic = { version = "0.3.0" }
|
||||||
bumpalo = { version = "3.19.0" }
|
bumpalo = { version = "3.19.0" }
|
||||||
const_panic = { version = "0.2.12", features = [ "derive" ] }
|
|
||||||
crossterm = { version = "0.29.0" }
|
crossterm = { version = "0.29.0" }
|
||||||
heck = { version = "0.5" }
|
heck = { version = "0.5" }
|
||||||
itertools = { version = "0.14.0" }
|
|
||||||
konst = { version = "0.3.16", features = [ "rust_1_83" ] }
|
|
||||||
palette = { version = "0.7.6", features = [ "random" ] }
|
palette = { version = "0.7.6", features = [ "random" ] }
|
||||||
proc-macro2 = { version = "1", features = ["span-locations"] }
|
proc-macro2 = { version = "1", features = ["span-locations"] }
|
||||||
proptest = { version = "^1" }
|
proptest = { version = "^1" }
|
||||||
|
|
@ -48,5 +43,4 @@ quote = { version = "1" }
|
||||||
rand = { version = "0.8.5" }
|
rand = { version = "0.8.5" }
|
||||||
ratatui = { version = "0.29.0", features = [ "unstable-widget-ref", "underline-color" ] }
|
ratatui = { version = "0.29.0", features = [ "unstable-widget-ref", "underline-color" ] }
|
||||||
syn = { version = "2", features = ["full", "extra-traits"] }
|
syn = { version = "2", features = ["full", "extra-traits"] }
|
||||||
thiserror = { version = "2.0" }
|
|
||||||
unicode-width = { version = "0.2" }
|
unicode-width = { version = "0.2" }
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "tengri_core"
|
|
||||||
description = "UI metaframework, core definitions."
|
|
||||||
version = { workspace = true }
|
|
||||||
edition = { workspace = true }
|
|
||||||
|
|
||||||
|
|
@ -1,137 +0,0 @@
|
||||||
/// Define and reexport submodules.
|
|
||||||
#[macro_export] macro_rules! modules(
|
|
||||||
($($($feat:literal?)? $name:ident),* $(,)?) => { $(
|
|
||||||
$(#[cfg(feature=$feat)])? mod $name;
|
|
||||||
$(#[cfg(feature=$feat)])? pub use self::$name::*;
|
|
||||||
)* };
|
|
||||||
($($($feat:literal?)? $name:ident $body:block),* $(,)?) => { $(
|
|
||||||
$(#[cfg(feature=$feat)])? mod $name $body
|
|
||||||
$(#[cfg(feature=$feat)])? pub use self::$name::*;
|
|
||||||
)* };
|
|
||||||
);
|
|
||||||
|
|
||||||
/// Define a trait and implement it for read-only wrapper types.
|
|
||||||
#[macro_export] macro_rules! flex_trait (
|
|
||||||
($Trait:ident $(<$($A:ident:$T:ident),+>)? $(:$dep:ident $(<$dtt:tt>)? $(+$dep2:ident $(<$dtt2:tt>)?)*)? {
|
|
||||||
$(fn $fn:ident $(<$($fl:lifetime),*>)? (& $($fl2:lifetime)* $self:ident $(, $arg:ident:$ty:ty)*) $(-> $ret:ty)? $body:block)*
|
|
||||||
}) => {
|
|
||||||
pub trait $Trait $(<$($A: $T),+>)? $(:$dep $(<$dtt>)? $(+$dep2 $(<$dtt2>)?)*)? {
|
|
||||||
$(fn $fn $(<$($fl),*>)? (& $($fl2)* $self $(,$arg:$ty)*) $(-> $ret)? $body)*
|
|
||||||
}
|
|
||||||
impl<$($($A: $T,)+)? _T_: $Trait $(<$($A),+>)?> $Trait $(<$($A),+>)? for &_T_ {
|
|
||||||
$(fn $fn $(<$($fl),*>)? (& $($fl2)* $self $(,$arg:$ty)*) $(-> $ret)? { (*$self).$fn($($arg),*) })*
|
|
||||||
}
|
|
||||||
impl<$($($A: $T,)+)? _T_: $Trait $(<$($A),+>)?> $Trait $(<$($A),+>)? for &mut _T_ {
|
|
||||||
$(fn $fn $(<$($fl),*>)? (& $($fl2)* $self $(,$arg:$ty)*) $(-> $ret)? { (**$self).$fn($($arg),*) })*
|
|
||||||
}
|
|
||||||
impl<$($($A: $T,)+)? _T_: $Trait $(<$($A),+>)?> $Trait $(<$($A),+>)? for ::std::sync::Arc<_T_> {
|
|
||||||
$(fn $fn $(<$($fl),*>)? (& $($fl2)* $self $(,$arg:$ty)*) $(-> $ret)? { (*$self).$fn($($arg),*) })*
|
|
||||||
}
|
|
||||||
impl<$($($A: $T,)+)?> $Trait $(<$($A),+>)? for Box<dyn $Trait $(<$($A),+>)?> {
|
|
||||||
$(fn $fn $(<$($fl),*>)? (& $($fl2)* $self $(,$arg:$ty)*) $(-> $ret)? { (**$self).$fn($($arg),*) })*
|
|
||||||
}
|
|
||||||
//impl<$($($A: $T,)+)? _T_: $Trait $(<$($A),+>)?> $Trait $(<$($A),+>)? for Option<_T_> {
|
|
||||||
//$(fn $fn (&$self $(,$arg:$ty)*) -> $ret {
|
|
||||||
//if let Some(this) = $self { this.$fn($($arg),*) } else { Ok(None) }
|
|
||||||
//})*
|
|
||||||
//}
|
|
||||||
//impl<$($($A: $T,)+)? _T_: $Trait $(<$($A),+>)?> $Trait $(<$($A),+>)? for ::std::sync::Mutex<_T_> {
|
|
||||||
//$(fn $fn (&$self $(,$arg:$ty)*) -> $ret { (*$self).lock().unwrap().$fn($($arg),*) })*
|
|
||||||
//}
|
|
||||||
//impl<$($($A: $T,)+)? _T_: $Trait $(<$($A),+>)?> $Trait $(<$($A),+>)? for ::std::sync::RwLock<_T_> {
|
|
||||||
//$(fn $fn (&$self $(,$arg:$ty)*) -> $ret { $self.read().unwrap().$fn($($arg),*) })*
|
|
||||||
//}
|
|
||||||
});
|
|
||||||
/// Define a trait an implement it for read-only wrapper types. */
|
|
||||||
#[macro_export] macro_rules! flex_trait_sized (
|
|
||||||
($Trait:ident $(<$($A:ident:$T:ident),+>)? $(:$dep:ident $(<$dtt:tt>)? $(+$dep2:ident $(<$dtt2:tt>)?)*)? {
|
|
||||||
$(fn $fn:ident (&$self:ident $(, $arg:ident:$ty:ty)*) $(-> $ret:ty)? $body:block)*
|
|
||||||
}) => {
|
|
||||||
pub trait $Trait $(<$($A: $T),+>)? : $($dep $(<$dtt>+)? $($dep2 $(<$dtt2>)?)*+)? Sized {
|
|
||||||
$(fn $fn (&$self $(,$arg:$ty)*) $(-> $ret)? $body)*
|
|
||||||
}
|
|
||||||
impl<$($($A: $T,)+)? _T_: $Trait $(<$($A),+>)?> $Trait $(<$($A),+>)? for &_T_ {
|
|
||||||
$(fn $fn (&$self $(,$arg:$ty)*) $(-> $ret)? { (*$self).$fn($($arg),*) })*
|
|
||||||
}
|
|
||||||
impl<$($($A: $T,)+)? _T_: $Trait $(<$($A),+>)?> $Trait $(<$($A),+>)? for &mut _T_ {
|
|
||||||
$(fn $fn (&$self $(,$arg:$ty)*) $(-> $ret)? { (**$self).$fn($($arg),*) })*
|
|
||||||
}
|
|
||||||
impl<$($($A: $T,)+)? _T_: $Trait $(<$($A),+>)?> $Trait $(<$($A),+>)? for ::std::sync::Arc<_T_> {
|
|
||||||
$(fn $fn (&$self $(,$arg:$ty)*) $(-> $ret)? { (*$self).$fn($($arg),*) })*
|
|
||||||
}
|
|
||||||
impl<$($($A: $T,)+)?> $Trait $(<$($A),+>)? for Box<dyn $Trait $(<$($A),+>)?> {
|
|
||||||
$(fn $fn (&$self $(,$arg:$ty)*) $(-> $ret)? { (**$self).$fn($($arg),*) })*
|
|
||||||
}
|
|
||||||
//impl<$($($A: $T,)+)? _T_: $Trait $(<$($A),+>)?> $Trait $(<$($A),+>)? for Option<_T_> {
|
|
||||||
//$(fn $fn (&$self $(,$arg:$ty)*) -> $ret {
|
|
||||||
//if let Some(this) = $self { this.$fn($($arg),*) } else { Ok(None) }
|
|
||||||
//})*
|
|
||||||
//}
|
|
||||||
//impl<$($($A: $T,)+)? _T_: $Trait $(<$($A),+>)?> $Trait $(<$($A),+>)? for ::std::sync::Mutex<_T_> {
|
|
||||||
//$(fn $fn (&$self $(,$arg:$ty)*) -> $ret { (*$self).lock().unwrap().$fn($($arg),*) })*
|
|
||||||
//}
|
|
||||||
//impl<$($($A: $T,)+)? _T_: $Trait $(<$($A),+>)?> $Trait $(<$($A),+>)? for ::std::sync::RwLock<_T_> {
|
|
||||||
//$(fn $fn (&$self $(,$arg:$ty)*) -> $ret { $self.read().unwrap().$fn($($arg),*) })*
|
|
||||||
//}
|
|
||||||
});
|
|
||||||
|
|
||||||
/// Define a trait an implement it for various mutation-enabled wrapper types. */
|
|
||||||
#[macro_export] macro_rules! flex_trait_mut (
|
|
||||||
($Trait:ident $(<$($A:ident:$T:ident),+>)? {
|
|
||||||
$(fn $fn:ident (&mut $self:ident $(, $arg:ident:$ty:ty)*) -> $ret:ty $body:block)*
|
|
||||||
})=>{
|
|
||||||
pub trait $Trait $(<$($A: $T),+>)? {
|
|
||||||
$(fn $fn (&mut $self $(,$arg:$ty)*) -> $ret $body)*
|
|
||||||
}
|
|
||||||
impl<$($($A: $T,)+)? _T_: $Trait $(<$($A),+>)?> $Trait $(<$($A),+>)? for &mut _T_ {
|
|
||||||
$(fn $fn (&mut $self $(,$arg:$ty)*) -> $ret { (*$self).$fn($($arg),*) })*
|
|
||||||
}
|
|
||||||
impl<$($($A: $T,)+)? _T_: $Trait $(<$($A),+>)?> $Trait $(<$($A),+>)? for Option<_T_> {
|
|
||||||
$(fn $fn (&mut $self $(,$arg:$ty)*) -> $ret {
|
|
||||||
if let Some(this) = $self { this.$fn($($arg),*) } else { Ok(None) }
|
|
||||||
})*
|
|
||||||
}
|
|
||||||
impl<$($($A: $T,)+)? _T_: $Trait $(<$($A),+>)?> $Trait $(<$($A),+>)? for ::std::sync::Mutex<_T_> {
|
|
||||||
$(fn $fn (&mut $self $(,$arg:$ty)*) -> $ret { $self.get_mut().unwrap().$fn($($arg),*) })*
|
|
||||||
}
|
|
||||||
impl<$($($A: $T,)+)? _T_: $Trait $(<$($A),+>)?> $Trait $(<$($A),+>)? for ::std::sync::Arc<::std::sync::Mutex<_T_>> {
|
|
||||||
$(fn $fn (&mut $self $(,$arg:$ty)*) -> $ret { $self.lock().unwrap().$fn($($arg),*) })*
|
|
||||||
}
|
|
||||||
impl<$($($A: $T,)+)? _T_: $Trait $(<$($A),+>)?> $Trait $(<$($A),+>)? for ::std::sync::RwLock<_T_> {
|
|
||||||
$(fn $fn (&mut $self $(,$arg:$ty)*) -> $ret { $self.write().unwrap().$fn($($arg),*) })*
|
|
||||||
}
|
|
||||||
impl<$($($A: $T,)+)? _T_: $Trait $(<$($A),+>)?> $Trait $(<$($A),+>)? for ::std::sync::Arc<::std::sync::RwLock<_T_>> {
|
|
||||||
$(fn $fn (&mut $self $(,$arg:$ty)*) -> $ret { $self.write().unwrap().$fn($($arg),*) })*
|
|
||||||
}
|
|
||||||
};
|
|
||||||
);
|
|
||||||
|
|
||||||
/// Implement [`Debug`] in bulk.
|
|
||||||
#[macro_export] macro_rules! impl_debug(($($S:ty|$self:ident,$w:ident|$body:block)*)=>{
|
|
||||||
$(impl std::fmt::Debug for $S {
|
|
||||||
fn fmt (&$self, $w: &mut std::fmt::Formatter) -> std::fmt::Result $body
|
|
||||||
})* });
|
|
||||||
|
|
||||||
/// Implement [`From`] in bulk.
|
|
||||||
#[macro_export] macro_rules! from(
|
|
||||||
($(<$($lt:lifetime),+>)?|$state:ident:$Source:ty|$Target:ty=$cb:expr) => {
|
|
||||||
impl $(<$($lt),+>)? From<$Source> for $Target {
|
|
||||||
fn from ($state:$Source) -> Self { $cb }}};
|
|
||||||
($($Struct:ty { $(
|
|
||||||
$(<$($l:lifetime),* $($T:ident$(:$U:ident)?),*>)? ($source:ident: $From:ty) $expr:expr
|
|
||||||
);+ $(;)? })*) => { $(
|
|
||||||
$(impl $(<$($l),* $($T$(:$U)?),*>)? From<$From> for $Struct {
|
|
||||||
fn from ($source: $From) -> Self { $expr } })+ )* }; );
|
|
||||||
|
|
||||||
/// Implement [Has].
|
|
||||||
#[macro_export] macro_rules! has(($T:ty: |$self:ident : $S:ty| $x:expr) => {
|
|
||||||
impl Has<$T> for $S {
|
|
||||||
fn get (&$self) -> &$T { &$x }
|
|
||||||
fn get_mut (&mut $self) -> &mut $T { &mut $x } } };);
|
|
||||||
|
|
||||||
/// Implement [MaybeHas].
|
|
||||||
#[macro_export] macro_rules! maybe_has(
|
|
||||||
($T:ty: |$self:ident : $S:ty| $x:block; $y:block $(;)?) => {
|
|
||||||
impl MaybeHas<$T> for $S {
|
|
||||||
fn get (&$self) -> Option<&$T> $x
|
|
||||||
fn get_mut (&mut $self) -> Option<&mut $T> $y } };);
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
mod core_macros;
|
|
||||||
pub(crate) use std::error::Error;
|
|
||||||
|
|
||||||
/// Standard result type.
|
|
||||||
pub type Usually<T> = Result<T, Box<dyn Error>>;
|
|
||||||
|
|
||||||
/// Standard optional result type.
|
|
||||||
pub type Perhaps<T> = Result<Option<T>, Box<dyn Error>>;
|
|
||||||
|
|
||||||
/// Type-dispatched `get` and `get_mut`.
|
|
||||||
pub trait Has<T>: Send + Sync { fn get (&self) -> &T; fn get_mut (&mut self) -> &mut T; }
|
|
||||||
|
|
||||||
/// Type-dispatched `get` and `get_mut` that return an [Option]-wrapped result.
|
|
||||||
pub trait MaybeHas<T>: Send + Sync { fn get (&self) -> Option<&T>; fn get_mut (&mut self) -> Option<&mut T>; }
|
|
||||||
|
|
||||||
/// May compute a `RetVal` from `Args`.
|
|
||||||
pub trait Eval<Args, RetVal> {
|
|
||||||
/// A custom operation on [Args] that may return [Result::Err] or [Option::None].
|
|
||||||
fn try_eval (&self, args: &Args) -> Perhaps<RetVal>;
|
|
||||||
/// Invoke a custom operation, converting a `None` result to a custom `Box<dyn Error>`.
|
|
||||||
fn eval <E: Into<Box<dyn std::error::Error>>> (&self, args: &Args, error: impl Fn()->E)
|
|
||||||
-> Usually<RetVal>
|
|
||||||
{
|
|
||||||
match self.try_eval(args)? {
|
|
||||||
Some(value) => Ok(value),
|
|
||||||
_ => Result::Err(format!("Eval: {}", error().into()).into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export] macro_rules! as_ref {
|
|
||||||
($T:ty: |$self:ident : $S:ty| $x:expr) => {
|
|
||||||
impl AsRef<$T> for $S {
|
|
||||||
fn as_ref (&$self) -> &$T { &$x }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn wrap_inc (index: usize, count: usize) -> usize {
|
|
||||||
if count > 0 { (index + 1) % count } else { 0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn wrap_dec (index: usize, count: usize) -> usize {
|
|
||||||
if count > 0 { index.overflowing_sub(1).0.min(count.saturating_sub(1)) } else { 0 }
|
|
||||||
}
|
|
||||||
980
dsl/Cargo.lock
generated
980
dsl/Cargo.lock
generated
|
|
@ -1,980 +0,0 @@
|
||||||
# This file is automatically @generated by Cargo.
|
|
||||||
# It is not intended for manual editing.
|
|
||||||
version = 4
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "addr2line"
|
|
||||||
version = "0.24.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
|
|
||||||
dependencies = [
|
|
||||||
"gimli",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "adler2"
|
|
||||||
version = "2.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "allocator-api2"
|
|
||||||
version = "0.2.21"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "approx"
|
|
||||||
version = "0.5.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
|
|
||||||
dependencies = [
|
|
||||||
"num-traits",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "autocfg"
|
|
||||||
version = "1.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "backtrace"
|
|
||||||
version = "0.3.74"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
|
|
||||||
dependencies = [
|
|
||||||
"addr2line",
|
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
"miniz_oxide",
|
|
||||||
"object",
|
|
||||||
"rustc-demangle",
|
|
||||||
"windows-targets",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "better-panic"
|
|
||||||
version = "0.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6fa9e1d11a268684cbd90ed36370d7577afb6c62d912ddff5c15fc34343e5036"
|
|
||||||
dependencies = [
|
|
||||||
"backtrace",
|
|
||||||
"console",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bitflags"
|
|
||||||
version = "2.6.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "by_address"
|
|
||||||
version = "1.2.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "byteorder"
|
|
||||||
version = "1.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cassowary"
|
|
||||||
version = "0.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "castaway"
|
|
||||||
version = "0.2.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0abae9be0aaf9ea96a3b1b8b1b55c602ca751eba1b1500220cea4ecbafe7c0d5"
|
|
||||||
dependencies = [
|
|
||||||
"rustversion",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cfg-if"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "clojure-reader"
|
|
||||||
version = "0.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9edf141eea627c101a97509266bc9f6ba8cd408618f5e2ac4a0cb6b64b1d4ea8"
|
|
||||||
dependencies = [
|
|
||||||
"ordered-float",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "compact_str"
|
|
||||||
version = "0.8.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3b79c4069c6cad78e2e0cdfcbd26275770669fb39fd308a752dc110e83b9af32"
|
|
||||||
dependencies = [
|
|
||||||
"castaway",
|
|
||||||
"cfg-if",
|
|
||||||
"itoa",
|
|
||||||
"rustversion",
|
|
||||||
"ryu",
|
|
||||||
"static_assertions",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "console"
|
|
||||||
version = "0.15.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ea3c6ecd8059b57859df5c69830340ed3c41d30e3da0c1cbed90a96ac853041b"
|
|
||||||
dependencies = [
|
|
||||||
"encode_unicode",
|
|
||||||
"libc",
|
|
||||||
"once_cell",
|
|
||||||
"windows-sys 0.59.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "const_panic"
|
|
||||||
version = "0.2.11"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "53857514f72ee4a2b583de67401e3ff63a5472ca4acf289d09a9ea7636dfec17"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "crossterm"
|
|
||||||
version = "0.28.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
"crossterm_winapi",
|
|
||||||
"mio",
|
|
||||||
"parking_lot",
|
|
||||||
"rustix",
|
|
||||||
"signal-hook",
|
|
||||||
"signal-hook-mio",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "crossterm_winapi"
|
|
||||||
version = "0.9.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
|
|
||||||
dependencies = [
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "darling"
|
|
||||||
version = "0.20.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
|
|
||||||
dependencies = [
|
|
||||||
"darling_core",
|
|
||||||
"darling_macro",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "darling_core"
|
|
||||||
version = "0.20.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
|
|
||||||
dependencies = [
|
|
||||||
"fnv",
|
|
||||||
"ident_case",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"strsim",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "darling_macro"
|
|
||||||
version = "0.20.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
|
|
||||||
dependencies = [
|
|
||||||
"darling_core",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "either"
|
|
||||||
version = "1.13.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "encode_unicode"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "equivalent"
|
|
||||||
version = "1.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "errno"
|
|
||||||
version = "0.3.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"windows-sys 0.59.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fast-srgb8"
|
|
||||||
version = "1.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fnv"
|
|
||||||
version = "1.0.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "foldhash"
|
|
||||||
version = "0.1.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "getrandom"
|
|
||||||
version = "0.2.15"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
"wasi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "gimli"
|
|
||||||
version = "0.31.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hashbrown"
|
|
||||||
version = "0.15.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
|
||||||
dependencies = [
|
|
||||||
"allocator-api2",
|
|
||||||
"equivalent",
|
|
||||||
"foldhash",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "heck"
|
|
||||||
version = "0.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ident_case"
|
|
||||||
version = "1.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "indoc"
|
|
||||||
version = "2.0.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "instability"
|
|
||||||
version = "0.3.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "894813a444908c0c8c0e221b041771d107c4a21de1d317dc49bcc66e3c9e5b3f"
|
|
||||||
dependencies = [
|
|
||||||
"darling",
|
|
||||||
"indoc",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "itertools"
|
|
||||||
version = "0.13.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
|
||||||
dependencies = [
|
|
||||||
"either",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "itertools"
|
|
||||||
version = "0.14.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
|
|
||||||
dependencies = [
|
|
||||||
"either",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "itoa"
|
|
||||||
version = "1.0.14"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "konst"
|
|
||||||
version = "0.3.16"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4381b9b00c55f251f2ebe9473aef7c117e96828def1a7cb3bd3f0f903c6894e9"
|
|
||||||
dependencies = [
|
|
||||||
"const_panic",
|
|
||||||
"konst_kernel",
|
|
||||||
"konst_proc_macros",
|
|
||||||
"typewit",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "konst_kernel"
|
|
||||||
version = "0.3.15"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e4b1eb7788f3824c629b1116a7a9060d6e898c358ebff59070093d51103dcc3c"
|
|
||||||
dependencies = [
|
|
||||||
"typewit",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "konst_proc_macros"
|
|
||||||
version = "0.3.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "00af7901ba50898c9e545c24d5c580c96a982298134e8037d8978b6594782c07"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "libc"
|
|
||||||
version = "0.2.169"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "linux-raw-sys"
|
|
||||||
version = "0.4.14"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lock_api"
|
|
||||||
version = "0.4.12"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg",
|
|
||||||
"scopeguard",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "log"
|
|
||||||
version = "0.4.22"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lru"
|
|
||||||
version = "0.12.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38"
|
|
||||||
dependencies = [
|
|
||||||
"hashbrown",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "memchr"
|
|
||||||
version = "2.7.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "miniz_oxide"
|
|
||||||
version = "0.8.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394"
|
|
||||||
dependencies = [
|
|
||||||
"adler2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "mio"
|
|
||||||
version = "1.0.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"log",
|
|
||||||
"wasi",
|
|
||||||
"windows-sys 0.52.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num-traits"
|
|
||||||
version = "0.2.19"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "object"
|
|
||||||
version = "0.36.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
|
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "once_cell"
|
|
||||||
version = "1.20.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ordered-float"
|
|
||||||
version = "4.6.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951"
|
|
||||||
dependencies = [
|
|
||||||
"num-traits",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "palette"
|
|
||||||
version = "0.7.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6"
|
|
||||||
dependencies = [
|
|
||||||
"approx",
|
|
||||||
"fast-srgb8",
|
|
||||||
"palette_derive",
|
|
||||||
"phf",
|
|
||||||
"rand",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "palette_derive"
|
|
||||||
version = "0.7.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f5030daf005bface118c096f510ffb781fc28f9ab6a32ab224d8631be6851d30"
|
|
||||||
dependencies = [
|
|
||||||
"by_address",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parking_lot"
|
|
||||||
version = "0.12.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
|
|
||||||
dependencies = [
|
|
||||||
"lock_api",
|
|
||||||
"parking_lot_core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parking_lot_core"
|
|
||||||
version = "0.9.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
"redox_syscall",
|
|
||||||
"smallvec",
|
|
||||||
"windows-targets",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "paste"
|
|
||||||
version = "1.0.15"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "phf"
|
|
||||||
version = "0.11.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc"
|
|
||||||
dependencies = [
|
|
||||||
"phf_macros",
|
|
||||||
"phf_shared",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "phf_generator"
|
|
||||||
version = "0.11.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0"
|
|
||||||
dependencies = [
|
|
||||||
"phf_shared",
|
|
||||||
"rand",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "phf_macros"
|
|
||||||
version = "0.11.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b"
|
|
||||||
dependencies = [
|
|
||||||
"phf_generator",
|
|
||||||
"phf_shared",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "phf_shared"
|
|
||||||
version = "0.11.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b"
|
|
||||||
dependencies = [
|
|
||||||
"siphasher",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ppv-lite86"
|
|
||||||
version = "0.2.20"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
|
|
||||||
dependencies = [
|
|
||||||
"zerocopy",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "proc-macro2"
|
|
||||||
version = "1.0.92"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
|
|
||||||
dependencies = [
|
|
||||||
"unicode-ident",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "quote"
|
|
||||||
version = "1.0.38"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand"
|
|
||||||
version = "0.8.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"rand_chacha",
|
|
||||||
"rand_core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_chacha"
|
|
||||||
version = "0.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
|
||||||
dependencies = [
|
|
||||||
"ppv-lite86",
|
|
||||||
"rand_core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rand_core"
|
|
||||||
version = "0.6.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
|
||||||
dependencies = [
|
|
||||||
"getrandom",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ratatui"
|
|
||||||
version = "0.29.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
"cassowary",
|
|
||||||
"compact_str",
|
|
||||||
"crossterm",
|
|
||||||
"indoc",
|
|
||||||
"instability",
|
|
||||||
"itertools 0.13.0",
|
|
||||||
"lru",
|
|
||||||
"paste",
|
|
||||||
"strum",
|
|
||||||
"unicode-segmentation",
|
|
||||||
"unicode-truncate",
|
|
||||||
"unicode-width 0.2.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "redox_syscall"
|
|
||||||
version = "0.5.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustc-demangle"
|
|
||||||
version = "0.1.24"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustix"
|
|
||||||
version = "0.38.42"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
"errno",
|
|
||||||
"libc",
|
|
||||||
"linux-raw-sys",
|
|
||||||
"windows-sys 0.59.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustversion"
|
|
||||||
version = "1.0.19"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ryu"
|
|
||||||
version = "1.0.18"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "scopeguard"
|
|
||||||
version = "1.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "signal-hook"
|
|
||||||
version = "0.3.17"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"signal-hook-registry",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "signal-hook-mio"
|
|
||||||
version = "0.2.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"mio",
|
|
||||||
"signal-hook",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "signal-hook-registry"
|
|
||||||
version = "1.4.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "siphasher"
|
|
||||||
version = "0.3.11"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "smallvec"
|
|
||||||
version = "1.13.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "static_assertions"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "strsim"
|
|
||||||
version = "0.11.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "strum"
|
|
||||||
version = "0.26.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
|
|
||||||
dependencies = [
|
|
||||||
"strum_macros",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "strum_macros"
|
|
||||||
version = "0.26.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
|
|
||||||
dependencies = [
|
|
||||||
"heck",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"rustversion",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "syn"
|
|
||||||
version = "2.0.95"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"unicode-ident",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tengri_dsl"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"clojure-reader",
|
|
||||||
"itertools 0.14.0",
|
|
||||||
"konst",
|
|
||||||
"tengri_tui",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tengri_input"
|
|
||||||
version = "0.2.0"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tengri_output"
|
|
||||||
version = "0.2.0"
|
|
||||||
dependencies = [
|
|
||||||
"tengri_dsl",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tengri_tui"
|
|
||||||
version = "0.2.0"
|
|
||||||
dependencies = [
|
|
||||||
"better-panic",
|
|
||||||
"crossterm",
|
|
||||||
"palette",
|
|
||||||
"rand",
|
|
||||||
"ratatui",
|
|
||||||
"tengri_dsl",
|
|
||||||
"tengri_input",
|
|
||||||
"tengri_output",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "typewit"
|
|
||||||
version = "1.11.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "cb77c29baba9e4d3a6182d51fa75e3215c7fd1dab8f4ea9d107c716878e55fc0"
|
|
||||||
dependencies = [
|
|
||||||
"typewit_proc_macros",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "typewit_proc_macros"
|
|
||||||
version = "1.8.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e36a83ea2b3c704935a01b4642946aadd445cea40b10935e3f8bd8052b8193d6"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-ident"
|
|
||||||
version = "1.0.14"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-segmentation"
|
|
||||||
version = "1.12.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-truncate"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf"
|
|
||||||
dependencies = [
|
|
||||||
"itertools 0.13.0",
|
|
||||||
"unicode-segmentation",
|
|
||||||
"unicode-width 0.1.14",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-width"
|
|
||||||
version = "0.1.14"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "unicode-width"
|
|
||||||
version = "0.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasi"
|
|
||||||
version = "0.11.0+wasi-snapshot-preview1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi"
|
|
||||||
version = "0.3.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
|
||||||
dependencies = [
|
|
||||||
"winapi-i686-pc-windows-gnu",
|
|
||||||
"winapi-x86_64-pc-windows-gnu",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi-i686-pc-windows-gnu"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winapi-x86_64-pc-windows-gnu"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-sys"
|
|
||||||
version = "0.52.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
|
||||||
dependencies = [
|
|
||||||
"windows-targets",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-sys"
|
|
||||||
version = "0.59.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
|
||||||
dependencies = [
|
|
||||||
"windows-targets",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-targets"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
|
||||||
dependencies = [
|
|
||||||
"windows_aarch64_gnullvm",
|
|
||||||
"windows_aarch64_msvc",
|
|
||||||
"windows_i686_gnu",
|
|
||||||
"windows_i686_gnullvm",
|
|
||||||
"windows_i686_msvc",
|
|
||||||
"windows_x86_64_gnu",
|
|
||||||
"windows_x86_64_gnullvm",
|
|
||||||
"windows_x86_64_msvc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_aarch64_gnullvm"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_aarch64_msvc"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_gnu"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_gnullvm"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_msvc"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_gnu"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_gnullvm"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_msvc"
|
|
||||||
version = "0.52.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "zerocopy"
|
|
||||||
version = "0.7.35"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
|
|
||||||
dependencies = [
|
|
||||||
"byteorder",
|
|
||||||
"zerocopy-derive",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "zerocopy-derive"
|
|
||||||
version = "0.7.35"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "tengri_dsl"
|
|
||||||
description = "UI metaframework, tiny S-expression-based DSL."
|
|
||||||
version = { workspace = true }
|
|
||||||
edition = { workspace = true }
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
path = "src/dsl.rs"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
tengri_core = { path = "../core" }
|
|
||||||
konst = { workspace = true }
|
|
||||||
const_panic = { workspace = true }
|
|
||||||
itertools = { workspace = true }
|
|
||||||
thiserror = { workspace = true }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
tengri_tui = { path = "../tui" }
|
|
||||||
proptest = "^1.6.0"
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
[***dizzle***](https://codeberg.org/unspeaker/tengri/src/branch/main/dsl)
|
|
||||||
is a means of adding a tiny interpreted domain-specific language to your programs.
|
|
||||||
|
|
||||||
dizzle currently provides an s-expression based syntax.
|
|
||||||
|
|
||||||
dizzle parses source code by means of the `Dsl`, `DslExpr` and `DslWord` traits.
|
|
||||||
those are implemented for basic stringy types and their `Option` and `Result` wrapped analogs.
|
|
||||||
to customize parsing, define and use your own traits on top of the provided ones.
|
|
||||||
|
|
||||||
dizzle evaluates the parsed source code by means of the `DslNs` trait. the methods of
|
|
||||||
this trait match literals, words, and expressions, against pre-defined lists. the
|
|
||||||
`dsl_words` and `dsl_exprs` macros let you define those lists slightly less verbosely.
|
|
||||||
|
|
||||||
## goals
|
|
||||||
|
|
||||||
* [x] const parse
|
|
||||||
* [ ] live reload
|
|
||||||
* [ ] serialize modified code back to original indentation
|
|
||||||
|
|
||||||
## examples
|
|
||||||
|
|
||||||
### in [`tengri_output`](../output)
|
|
||||||
|
|
||||||
```edn
|
|
||||||
(bsp/s (fixed/y 2 :toolbar)
|
|
||||||
(fill/x (align/c (bsp/w :pool
|
|
||||||
(bsp/s :outputs (bsp/s :inputs (bsp/s :tracks :scenes)))))))
|
|
||||||
```
|
|
||||||
|
|
||||||
### in [`tengri_input`](../input)
|
|
||||||
|
|
||||||
```edn
|
|
||||||
(@u undo 1)
|
|
||||||
(@shift-u redo 1)
|
|
||||||
(@e editor show :pool-clip)
|
|
||||||
(@ctrl-a scene add)
|
|
||||||
(@ctrl-t track add)
|
|
||||||
(@tab pool toggle)
|
|
||||||
```
|
|
||||||
|
|
||||||
## implementation notes
|
|
||||||
|
|
||||||
### `DslExpr` trait behavior
|
|
||||||
|
|
||||||
this is the trait which differentiates "a thing" from
|
|
||||||
"a thing that is many things".
|
|
||||||
|
|
||||||
|source |key|exp |head |tail |
|
|
||||||
|---------------|---|-------|---------|---------------|
|
|
||||||
|`a` |`a`|e0 |`a` |None |
|
|
||||||
|`(a)` |e1 |`a` |`(a)` |None |
|
|
||||||
|`a b c` |e2 |e0 |`a` |`b c` |
|
|
||||||
|`(a b c)` |e1 |`a b c`|`(a b c)`| |
|
|
||||||
|`(a b c) d e` |e1 |e3 |`(a b c)`|`d e` |
|
|
||||||
|`a (b c d) e f`|e1 |e0 |`a` |`(b c d) e f` |
|
|
||||||
|
|
||||||
* e0: Unexpected 'a'
|
|
||||||
* e1: Unexpected '('
|
|
||||||
* e2: Unexpected 'b'
|
|
||||||
* e3: Unexpected 'd'
|
|
||||||
|
|
||||||
### possible design for operator-based syntax
|
|
||||||
|
|
||||||
* replace: `(:= :name :value1 :valueN)`
|
|
||||||
* append: `(:+ :name :value2 :valueN)`
|
|
||||||
* filter: `(:- :name :value2 :valueN)`
|
|
||||||
* map: `(:* :name op)`
|
|
||||||
* reduce: `(:/ :name op)`
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
# Seeds for failure cases proptest has generated in the past. It is
|
|
||||||
# automatically read and these particular cases re-run before any
|
|
||||||
# novel cases are generated.
|
|
||||||
#
|
|
||||||
# It is recommended to check this file in to source control so that
|
|
||||||
# everyone who runs the test benefits from these saved cases.
|
|
||||||
cc bbb90b16e6106f17dbb5a4f57594f451360a2ea7e3e20c28adeb8babc98d39df # shrinks to source = "(𰀀"
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
# Seeds for failure cases proptest has generated in the past. It is
|
|
||||||
# automatically read and these particular cases re-run before any
|
|
||||||
# novel cases are generated.
|
|
||||||
#
|
|
||||||
# It is recommended to check this file in to source control so that
|
|
||||||
# everyone who runs the test benefits from these saved cases.
|
|
||||||
cc 5fb814b74ae035bdecb536817090cfb473f0a874e9acf9aaa136a4794cdb367f # shrinks to source = "", start = 10336420442936153584, length = 8110323630773398032
|
|
||||||
227
dsl/src/dsl.rs
227
dsl/src/dsl.rs
|
|
@ -1,227 +0,0 @@
|
||||||
//#![feature(adt_const_params)]
|
|
||||||
//#![feature(type_alias_impl_trait)]
|
|
||||||
#![feature(if_let_guard)]
|
|
||||||
#![feature(impl_trait_in_fn_trait_return)]
|
|
||||||
#![feature(const_precise_live_drops)]
|
|
||||||
#![feature(type_alias_impl_trait)]
|
|
||||||
extern crate const_panic;
|
|
||||||
use const_panic::PanicFmt;
|
|
||||||
use std::fmt::Debug;
|
|
||||||
pub(crate) use ::{
|
|
||||||
std::sync::Arc,
|
|
||||||
//std::error::Error,
|
|
||||||
konst::iter::for_each,
|
|
||||||
konst::string::{str_from, str_range, char_indices},
|
|
||||||
thiserror::Error,
|
|
||||||
tengri_core::*
|
|
||||||
};
|
|
||||||
pub(crate) use self::DslError::*;
|
|
||||||
mod dsl_error; pub use self::dsl_error::*;
|
|
||||||
mod dsl_ns; pub use self::dsl_ns::*;
|
|
||||||
mod dsl_word; pub use self::dsl_word::*;
|
|
||||||
mod dsl_expr; pub use self::dsl_expr::*;
|
|
||||||
mod dsl_text; pub use self::dsl_text::*;
|
|
||||||
#[cfg(test)] mod dsl_test;
|
|
||||||
|
|
||||||
// Trait that designates any string-like as potentially parsable DSL.
|
|
||||||
pub trait Dsl: Debug + Send + Sync {
|
|
||||||
fn src (&self) -> DslPerhaps<&str> { unreachable!("Dsl::src default impl") }
|
|
||||||
}
|
|
||||||
impl<'x> Dsl for &'x str {
|
|
||||||
fn src (&self) -> DslPerhaps<&str> { Ok(Some(self)) }
|
|
||||||
}
|
|
||||||
impl Dsl for Arc<str> {
|
|
||||||
fn src (&self) -> DslPerhaps<&str> { Ok(Some(self.as_ref())) }
|
|
||||||
}
|
|
||||||
impl<D: Dsl> Dsl for &D {
|
|
||||||
fn src (&self) -> DslPerhaps<&str> { (*self).src() }
|
|
||||||
}
|
|
||||||
impl<D: Dsl> Dsl for &mut D {
|
|
||||||
fn src (&self) -> DslPerhaps<&str> { (**self).src() }
|
|
||||||
}
|
|
||||||
impl<D: Dsl> Dsl for Option<D> {
|
|
||||||
fn src (&self) -> DslPerhaps<&str> {Ok(if let Some(dsl) = self { dsl.src()? } else { None })}
|
|
||||||
}
|
|
||||||
impl<D: Dsl> Dsl for Result<D, DslError> {
|
|
||||||
fn src (&self) -> DslPerhaps<&str> {match self {Ok(dsl) => Ok(dsl.src()?), Err(e) => Err(*e)}}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// DSL-specific result type.
|
|
||||||
pub type DslResult<T> = Result<T, DslError>;
|
|
||||||
|
|
||||||
/// DSL-specific optional result type.
|
|
||||||
pub type DslPerhaps<T> = Result<Option<T>, DslError>;
|
|
||||||
|
|
||||||
pub const fn peek (src: &str) -> DslPerhaps<&str> {
|
|
||||||
Ok(Some(if let Ok(Some(expr)) = expr_peek(src) { expr } else
|
|
||||||
if let Ok(Some(word)) = word_peek(src) { word } else
|
|
||||||
if let Ok(Some(text)) = text_peek(src) { text } else
|
|
||||||
if let Err(e) = no_trailing_non_space(src, 0, Some("peek")) { return Err(e) }
|
|
||||||
else { return Ok(None) }))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn seek (src: &str) -> DslPerhaps<(usize, usize)> {
|
|
||||||
Ok(Some(if let Ok(Some(expr)) = expr_seek(src) { expr } else
|
|
||||||
if let Ok(Some(word)) = word_seek(src) { word } else
|
|
||||||
if let Ok(Some(text)) = text_seek(src) { text } else
|
|
||||||
if let Err(e) = no_trailing_non_space(src, 0, Some("seek")) { return Err(e) }
|
|
||||||
else { return Ok(None) }))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn peek_tail (src: &str) -> DslPerhaps<&str> {
|
|
||||||
match seek(src) {
|
|
||||||
Err(e) => Err(e),
|
|
||||||
Ok(None) => Ok(None),
|
|
||||||
Ok(Some((start, length))) => {
|
|
||||||
let tail = str_range(src, start + length, src.len());
|
|
||||||
for_each!((_i, c) in char_indices(tail) => if !is_space(c) { return Ok(Some(tail)) });
|
|
||||||
Ok(None)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn expr_peek_inner (src: &str) -> DslPerhaps<&str> {
|
|
||||||
match expr_peek(src) {
|
|
||||||
Ok(Some(peeked)) => {
|
|
||||||
let len = peeked.len();
|
|
||||||
let start = if len > 0 { 1 } else { 0 };
|
|
||||||
Ok(Some(str_range(src, start, start + len.saturating_sub(2))))
|
|
||||||
},
|
|
||||||
e => e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn expr_peek_inner_only (src: &str) -> DslPerhaps<&str> {
|
|
||||||
match expr_seek(src) {
|
|
||||||
Err(e) => Err(e),
|
|
||||||
Ok(None) => Ok(None),
|
|
||||||
Ok(Some((start, length))) => {
|
|
||||||
if let Err(e) = no_trailing_non_space(src, start + length, Some("expr_peek_inner_only")) {
|
|
||||||
Err(e)
|
|
||||||
} else {
|
|
||||||
let peeked = str_range(src, start, start + length);
|
|
||||||
let len = peeked.len();
|
|
||||||
let start = if len > 0 { 1 } else { 0 };
|
|
||||||
Ok(Some(str_range(peeked, start, start + len.saturating_sub(2))))
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn is_space (c: char) -> bool {
|
|
||||||
matches!(c, ' '|'\n'|'\r'|'\t')
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn no_trailing_non_space (
|
|
||||||
src: &str, offset: usize, context: Option<&'static str>
|
|
||||||
) -> DslResult<()> {
|
|
||||||
Ok(for_each!((i, c) in char_indices(str_range(src, offset, src.len())) => if !is_space(c) {
|
|
||||||
return Err(Unexpected(c, Some(offset + i), if let Some(context) = context {
|
|
||||||
Some(context)
|
|
||||||
} else {
|
|
||||||
Some("trailing non-space")
|
|
||||||
}))
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn is_word_char (c: char) -> bool {
|
|
||||||
matches!(c, 'a'..='z'|'A'..='Z'|'0'..='9'|'-'|'/'|'@'|':')
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn is_word_end (c: char) -> bool {
|
|
||||||
is_space(c) || is_expr_end(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn is_text_start (c: char) -> bool {
|
|
||||||
matches!(c, '"')
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn is_text_end (c: char) -> bool {
|
|
||||||
matches!(c, '"')
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn is_expr_start (c: char) -> bool {
|
|
||||||
c == '('
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn is_expr_end (c: char) -> bool {
|
|
||||||
c == ')'
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn is_digit (c: char) -> bool {
|
|
||||||
matches!(c, '0'..='9')
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn to_number (digits: &str) -> Result<usize, DslError> {
|
|
||||||
let mut iter = char_indices(digits);
|
|
||||||
let mut value = 0;
|
|
||||||
while let Some(((_, c), next)) = iter.next() {
|
|
||||||
match to_digit(c) {
|
|
||||||
Ok(digit) => value = 10 * value + digit,
|
|
||||||
Err(e) => return Err(e),
|
|
||||||
}
|
|
||||||
iter = next;
|
|
||||||
}
|
|
||||||
Ok(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn to_digit (c: char) -> Result<usize, DslError> {
|
|
||||||
Ok(match c {
|
|
||||||
'0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4,
|
|
||||||
'5' => 5, '6' => 6, '7' => 7, '8' => 8, '9' => 9,
|
|
||||||
_ => return Err(Unexpected(c, None, Some("parse digit")))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn ok_flat <T> (x: Option<DslPerhaps<T>>) -> DslPerhaps<T> {
|
|
||||||
Ok(x.transpose()?.flatten())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export] macro_rules! dsl_type (($T:ident { $($trait:tt)* } {
|
|
||||||
pub const fn $peek:ident $($_1:tt)?;
|
|
||||||
pub const fn $peek_only:ident $($_2:tt)?;
|
|
||||||
pub const fn $seek:ident $($_3:tt)?;
|
|
||||||
pub const fn $seek_start:ident ($source1:ident) $body1:block
|
|
||||||
pub const fn $seek_length:ident ($source2:ident) $body2:block
|
|
||||||
})=>{
|
|
||||||
pub trait $T: Dsl { $($trait)* }
|
|
||||||
impl<D: Dsl + ?Sized> $T for D {}
|
|
||||||
pub const fn $seek_start ($source1: &str) -> DslPerhaps<usize> $body1
|
|
||||||
pub const fn $seek_length ($source2: &str) -> DslPerhaps<usize> $body2
|
|
||||||
/// Find a start and length corresponding to a syntax token.
|
|
||||||
pub const fn $seek (source: &str) -> DslPerhaps<(usize, usize)> {
|
|
||||||
match $seek_start(source) {
|
|
||||||
Err(e) => Err(e),
|
|
||||||
Ok(None) => Ok(None),
|
|
||||||
Ok(Some(start)) => match $seek_length(str_from(source, start)) {
|
|
||||||
Ok(Some(length)) => Ok(Some((start, length))),
|
|
||||||
Ok(None) => Ok(None),
|
|
||||||
Err(e) => Err(e),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// Find a slice corrensponding to a syntax token.
|
|
||||||
pub const fn $peek (source: &str) -> DslPerhaps<&str> {
|
|
||||||
match $seek(source) {
|
|
||||||
Err(e) => Err(e),
|
|
||||||
Ok(None) => Ok(None),
|
|
||||||
Ok(Some((start, length))) => Ok(Some(str_range(source, start, start + length))),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// Find a slice corrensponding to a syntax token
|
|
||||||
/// but return an error if it isn't the only thing
|
|
||||||
/// in the source.
|
|
||||||
pub const fn $peek_only (source: &str) -> DslPerhaps<&str> {
|
|
||||||
match $seek(source) {
|
|
||||||
Err(e) => Err(e),
|
|
||||||
Ok(None) => Ok(None),
|
|
||||||
Ok(Some((start, length))) => {
|
|
||||||
if let Err(e) = no_trailing_non_space(source, start + length, Some("peek_only")) {
|
|
||||||
Err(e)
|
|
||||||
} else {
|
|
||||||
Ok(Some(str_range(source, start, start + length)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
/// DSL-specific error codes.
|
|
||||||
#[derive(Error, Debug, Copy, Clone, PartialEq, PanicFmt)]
|
|
||||||
pub enum DslError {
|
|
||||||
|
|
||||||
#[error("parse failed: not implemented")]
|
|
||||||
Unimplemented,
|
|
||||||
|
|
||||||
#[error("parse failed: empty")]
|
|
||||||
Empty,
|
|
||||||
|
|
||||||
#[error("parse failed: incomplete")]
|
|
||||||
Incomplete,
|
|
||||||
|
|
||||||
#[error("parse failed: unexpected character '{0}'")]
|
|
||||||
Unexpected(char, Option<usize>, Option<&'static str>),
|
|
||||||
|
|
||||||
#[error("parse failed: error #{0}")]
|
|
||||||
Code(u8),
|
|
||||||
|
|
||||||
#[error("end reached")]
|
|
||||||
End
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,87 +0,0 @@
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
pub type GetDslExpr<'a, S, T> = for<'b> fn(&'a S, &'b str)->Perhaps<T>;
|
|
||||||
|
|
||||||
pub type DslExprs<'a, S, T> = &'a [(&'a str, GetDslExpr<'a, S, T>)];
|
|
||||||
|
|
||||||
dsl_type!(DslExpr {
|
|
||||||
fn expr (&self) -> DslPerhaps<&str> {ok_flat(self.src()?.map(expr_peek_inner_only))}
|
|
||||||
fn head (&self) -> DslPerhaps<&str> {ok_flat(self.src()?.map(peek))}
|
|
||||||
fn tail (&self) -> DslPerhaps<&str> {ok_flat(self.src()?.map(peek_tail))}
|
|
||||||
/// my other car is a cdr :<
|
|
||||||
fn each (&self, mut cb: impl FnMut(&str)->Usually<()>) -> Usually<()> {
|
|
||||||
Ok(if let Some(head) = self.head()? {
|
|
||||||
cb(head)?;
|
|
||||||
if let Some(tail) = self.tail()? {
|
|
||||||
tail.each(cb)?;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} {
|
|
||||||
pub const fn expr_peek [generated];
|
|
||||||
pub const fn expr_peek_only [generated];
|
|
||||||
pub const fn expr_seek [generated];
|
|
||||||
pub const fn expr_seek_start (src) {
|
|
||||||
for_each!((i, c) in char_indices(src) =>
|
|
||||||
if is_expr_start(c) { return Ok(Some(i)) } else
|
|
||||||
if !is_space(c) { return Err(Unexpected(c, Some(i), Some("expected expression start"))) });
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
pub const fn expr_seek_length (src) {
|
|
||||||
let mut depth = 0;
|
|
||||||
for_each!((i, c) in char_indices(src) =>
|
|
||||||
if is_expr_start(c) { depth += 1; } else
|
|
||||||
if is_expr_end(c) {
|
|
||||||
if depth == 0 {
|
|
||||||
return Err(Unexpected(c, Some(i), Some("expected expression end")))
|
|
||||||
} else if depth == 1 {
|
|
||||||
return Ok(Some(i + 1))
|
|
||||||
} else {
|
|
||||||
depth -= 1;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Err(Incomplete)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
#[macro_export] macro_rules!dsl_exprs(($l:lifetime |$state:ident|->$Type:ty$({
|
|
||||||
$($name:literal ($($arg:ident:$ty:ty),* $(,)?) => $body:expr),* $(,)?
|
|
||||||
})?)=>{
|
|
||||||
const EXPRS: DslExprs<$l, Self, $Type> = &[$( $({
|
|
||||||
let get: GetDslExpr<$l, Self, $Type> = |$state: &$l Self, tail_base|{
|
|
||||||
let tail = tail_base;
|
|
||||||
$(
|
|
||||||
let head = tail.head()?.unwrap_or_default();
|
|
||||||
let tail = tail.tail()?.unwrap_or_default();
|
|
||||||
let $arg: $ty = if let Some(arg) = $state.from(&head)? {
|
|
||||||
arg
|
|
||||||
} else {
|
|
||||||
return Err(format!("{}: arg \"{}\" ({}) got: {head} {tail}",
|
|
||||||
$name,
|
|
||||||
stringify!($arg),
|
|
||||||
stringify!($ty),
|
|
||||||
).into())
|
|
||||||
};
|
|
||||||
)*
|
|
||||||
Ok(Some($body/* as $Type*/))
|
|
||||||
};
|
|
||||||
($name, get)
|
|
||||||
}),* )? ];
|
|
||||||
});
|
|
||||||
|
|
||||||
pub trait DslNsExprs<'a, T: 'a>: 'a {
|
|
||||||
/// Known expressions.
|
|
||||||
const EXPRS: DslExprs<'a, Self, T> = &[];
|
|
||||||
/// Resolve an expression if known.
|
|
||||||
fn from_expr (&'a self, dsl: impl DslExpr + 'a) -> Perhaps<T> {
|
|
||||||
if let Some(dsl) = dsl.expr()? {
|
|
||||||
let head = dsl.head()?;
|
|
||||||
for (key, get) in Self::EXPRS.iter() {
|
|
||||||
if Some(*key) == head {
|
|
||||||
return get(self, dsl.tail()?.unwrap_or(""))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
pub trait DslNs<'a, T: 'a>: DslNsWords<'a, T> + DslNsExprs<'a, T> {
|
|
||||||
/// Resolve an expression or symbol.
|
|
||||||
fn from (&'a self, dsl: impl Dsl + 'a) -> Perhaps<T> {
|
|
||||||
if let Ok(Some(literal)) = self.from_literal(&dsl) {
|
|
||||||
Ok(Some(literal))
|
|
||||||
} else if let Ok(Some(meaning)) = self.from_word(&dsl) {
|
|
||||||
Ok(Some(meaning))
|
|
||||||
} else {
|
|
||||||
self.from_expr(dsl)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// Resolve as literal if valid.
|
|
||||||
fn from_literal (&self, _: impl Dsl) -> Perhaps<T> {
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export] macro_rules! dsl_ns {
|
|
||||||
($State:ty: $Type:ty {
|
|
||||||
$(literal = |$dsl:ident| $literal:expr;)?
|
|
||||||
$(word = |$state_w:ident| {
|
|
||||||
$($word:literal => $body_w:expr),* $(,)?
|
|
||||||
};)?
|
|
||||||
$(expr = |$state_e:ident| {
|
|
||||||
$($head:literal $args:tt => $body_e:expr),* $(,)?
|
|
||||||
};)?
|
|
||||||
}) => {
|
|
||||||
impl<'a> DslNs<'a, $Type> for $State {
|
|
||||||
$(fn from_literal (&self, $dsl: impl Dsl) -> Perhaps<$Type> {
|
|
||||||
$literal
|
|
||||||
})?
|
|
||||||
}
|
|
||||||
impl<'a> DslNsWords<'a, $Type> for $State {
|
|
||||||
$(dsl_words! { 'a |$state_w| -> $Type {
|
|
||||||
$($word => $body_w),*
|
|
||||||
} })?
|
|
||||||
}
|
|
||||||
impl<'a> DslNsExprs<'a, $Type> for $State {
|
|
||||||
$(dsl_exprs! { 'a |$state_e| -> $Type {
|
|
||||||
$($head $args => $body_e),*
|
|
||||||
} })?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
||||||
use crate::*;
|
|
||||||
macro_rules!is_some(($expr:expr, $val:expr)=>{assert_eq!($expr, Ok(Some($val)))};);
|
|
||||||
macro_rules!is_none(($expr:expr)=>{assert_eq!($expr, Ok(None))};);
|
|
||||||
macro_rules!is_err(($expr:expr)=>{assert!($expr.is_err())};
|
|
||||||
($expr:expr, $err:expr)=>{assert_eq!($expr, Err($err))};);
|
|
||||||
#[test] fn test_expr () -> Result<(), DslError> {
|
|
||||||
let e0 = DslError::Unexpected('a', None, None);
|
|
||||||
let e1 = DslError::Unexpected('(', None, None);
|
|
||||||
let e2 = DslError::Unexpected('b', None, None);
|
|
||||||
let e3 = DslError::Unexpected('d', None, None);
|
|
||||||
let check = |src: &str, word, expr, head, tail|{
|
|
||||||
assert_eq!(src.word(), word, "{src}");
|
|
||||||
assert_eq!(src.expr(), expr, "{src}");
|
|
||||||
assert_eq!(src.head(), head, "{src}");
|
|
||||||
assert_eq!(src.tail(), tail, "{src}");
|
|
||||||
};
|
|
||||||
check("a", Ok(Some("a")), Err(e0), Ok(Some("a")), Ok(None));
|
|
||||||
check("(a)", Err(e1), Ok(Some("a")), Ok(Some("(a)")), Ok(None));
|
|
||||||
check("a b c", Err(e2), Err(e0), Ok(Some("a")), Ok(Some("b c")));
|
|
||||||
check("(a b c)", Err(e1), Ok(Some("a b c")), Ok(Some("(a b c)")), Ok(None));
|
|
||||||
check("(a b c) d e f", Err(e1), Err(e3), Ok(Some("(a b c)")), Ok(Some("d e f")));
|
|
||||||
check("a (b c d) e f", Err(e1), Err(e0), Ok(Some("a")), Ok(Some("(b c d) e f")));
|
|
||||||
|
|
||||||
is_some!(word_peek("\n :view/transport"), ":view/transport");
|
|
||||||
|
|
||||||
assert!(is_space(' '));
|
|
||||||
assert!(!is_word_char(' '));
|
|
||||||
assert!(is_word_char('f'));
|
|
||||||
|
|
||||||
is_some!(word_seek_start("foo"), 0);
|
|
||||||
is_some!(word_seek_start("foo "), 0);
|
|
||||||
is_some!(word_seek_start(" foo "), 1);
|
|
||||||
is_some!(word_seek_length(&" foo "[1..]), 3);
|
|
||||||
is_some!(word_seek("foo"), (0, 3));
|
|
||||||
is_some!(word_peek("foo"), "foo");
|
|
||||||
is_some!(word_seek("foo "), (0, 3));
|
|
||||||
is_some!(word_peek("foo "), "foo");
|
|
||||||
is_some!(word_seek(" foo "), (1, 3));
|
|
||||||
is_some!(word_peek(" foo "), "foo");
|
|
||||||
|
|
||||||
is_err!("(foo)".word());
|
|
||||||
is_err!("foo".expr());
|
|
||||||
|
|
||||||
is_some!("(foo)".expr(), "foo");
|
|
||||||
is_some!("(foo)".head(), "(foo)");
|
|
||||||
is_none!("(foo)".tail());
|
|
||||||
|
|
||||||
is_some!("(foo bar baz)".expr(), "foo bar baz");
|
|
||||||
is_some!("(foo bar baz)".head(), "(foo bar baz)");
|
|
||||||
is_none!("(foo bar baz)".tail());
|
|
||||||
|
|
||||||
is_some!("(foo bar baz)".expr().head(), "foo");
|
|
||||||
is_some!("(foo bar baz)".expr().tail(), "bar baz");
|
|
||||||
is_some!("(foo bar baz)".expr().tail().head(), "bar");
|
|
||||||
is_some!("(foo bar baz)".expr().tail().tail(), "baz");
|
|
||||||
|
|
||||||
is_err!("foo".expr());
|
|
||||||
is_some!("foo".word(), "foo");
|
|
||||||
is_some!(" foo".word(), "foo");
|
|
||||||
is_some!(" foo ".word(), "foo");
|
|
||||||
|
|
||||||
is_some!(" foo ".head(), "foo");
|
|
||||||
//assert_eq!(" foo ".head().head(), Ok(None));
|
|
||||||
is_none!(" foo ".head().tail());
|
|
||||||
is_none!(" foo ".tail());
|
|
||||||
is_none!(" foo ".tail().head());
|
|
||||||
is_none!(" foo ".tail().tail());
|
|
||||||
|
|
||||||
assert_eq!(" foo bar ".head(), Ok(Some("foo")));
|
|
||||||
//assert_eq!(" foo bar ".head().head(), Ok(None));
|
|
||||||
assert_eq!(" foo bar ".head().tail(), Ok(None));
|
|
||||||
assert_eq!(" foo bar ".tail(), Ok(Some(" bar ")));
|
|
||||||
assert_eq!(" foo bar ".tail().head(), Ok(Some("bar")));
|
|
||||||
assert_eq!(" foo bar ".tail().tail(), Ok(None));
|
|
||||||
|
|
||||||
assert_eq!(" (foo) ".head(), Ok(Some("(foo)")));
|
|
||||||
//assert_eq!(" (foo) ".head().head(), Ok(Some("foo")));
|
|
||||||
//assert_eq!(" (foo) ".head().head().head(), Ok(None));
|
|
||||||
assert_eq!(" (foo) ".tail(), Ok(None));
|
|
||||||
|
|
||||||
assert_eq!(" (foo) (bar) ".head(), Ok(Some("(foo)")));
|
|
||||||
//assert_eq!(" (foo) (bar) ".head().head(), Ok(Some("foo")));
|
|
||||||
//assert_eq!(" (foo) (bar) ".head().head().head(), Ok(None));
|
|
||||||
is_some!(" (foo) (bar) ".tail(), " (bar) ");
|
|
||||||
is_some!(" (foo) (bar) ".tail().head(), "(bar)");
|
|
||||||
is_some!(" (foo) (bar) ".tail().head().head(), "(bar)");
|
|
||||||
is_some!(" (foo) (bar) ".tail().head().expr(), "bar");
|
|
||||||
is_some!(" (foo) (bar) ".tail().head().expr().head(), "bar");
|
|
||||||
|
|
||||||
is_some!(" (foo bar baz) ".head(), "(foo bar baz)");
|
|
||||||
is_some!(" (foo bar baz) ".head().head(), "(foo bar baz)");
|
|
||||||
is_some!(" (foo bar baz) ".expr(), "foo bar baz");
|
|
||||||
is_some!(" (foo bar baz) ".expr().head(), "foo");
|
|
||||||
is_some!(" (foo bar baz) ".expr().tail(), "bar baz");
|
|
||||||
is_some!(" (foo bar baz) ".expr().tail().head(), "bar");
|
|
||||||
is_some!(" (foo bar baz) ".expr().tail().tail(), "baz");
|
|
||||||
is_none!(" (foo bar baz) ".tail());
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
dsl_type!(DslText {
|
|
||||||
fn text (&self) -> DslPerhaps<&str> { ok_flat(self.src()?.map(text_peek_only)) }
|
|
||||||
} {
|
|
||||||
pub const fn text_peek [generated];
|
|
||||||
pub const fn text_peek_only [generated];
|
|
||||||
pub const fn text_seek [generated];
|
|
||||||
pub const fn text_seek_start (src) {
|
|
||||||
for_each!((i, c) in char_indices(src) =>
|
|
||||||
if is_text_start(c) { return Ok(Some(i)) } else
|
|
||||||
if !is_space(c) { return Err(Unexpected(c, Some(i), None)) });
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
pub const fn text_seek_length (src) {
|
|
||||||
for_each!((i, c) in char_indices(src) =>
|
|
||||||
if is_text_end(c) { return Ok(Some(i)) });
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
pub type GetDslWord<'a, S, T> = fn(&'a S)->Perhaps<T>;
|
|
||||||
|
|
||||||
pub type DslWords<'a, S, T> = &'a [(&'a str, GetDslWord<'a, S, T>)];
|
|
||||||
|
|
||||||
dsl_type!(DslWord {
|
|
||||||
fn word (&self) -> DslPerhaps<&str> {ok_flat(self.src()?.map(word_peek_only))}
|
|
||||||
} {
|
|
||||||
pub const fn word_peek [generated];
|
|
||||||
pub const fn word_peek_only [generated];
|
|
||||||
pub const fn word_seek [generated];
|
|
||||||
pub const fn word_seek_start (src) {
|
|
||||||
for_each!((i, c) in char_indices(src) => if
|
|
||||||
is_word_char(c) { return Ok(Some(i)) } else
|
|
||||||
if !is_space(c) { return Err(Unexpected(c, Some(i), Some("word_seek_start"))) });
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
pub const fn word_seek_length (src) {
|
|
||||||
for_each!((i, c) in char_indices(src) => if !is_word_char(c) { return Ok(Some(i)) });
|
|
||||||
Ok(Some(src.len()))
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
#[macro_export] macro_rules!dsl_words(($l:lifetime |$state:ident|->$Type:ty$({
|
|
||||||
$($word:literal => $body:expr),* $(,)?
|
|
||||||
})?)=>{
|
|
||||||
const WORDS: DslWords<$l, Self, $Type> = &[$( $({
|
|
||||||
let get: GetDslWord<$l, Self, $Type> = |$state: &$l Self|Ok(Some($body));
|
|
||||||
($word, get)
|
|
||||||
}),* )?];
|
|
||||||
});
|
|
||||||
|
|
||||||
pub trait DslNsWords<'a, T: 'a>: 'a {
|
|
||||||
/// Known symbols.
|
|
||||||
const WORDS: DslWords<'a, Self, T> = &[];
|
|
||||||
/// Resolve a symbol if known.
|
|
||||||
fn from_word (&'a self, dsl: impl DslWord) -> Perhaps<T> {
|
|
||||||
if let Some(dsl) = dsl.word()? {
|
|
||||||
for (key, get) in Self::WORDS.iter() {
|
|
||||||
if dsl == *key {
|
|
||||||
let value = get(self);
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Ok(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
(bsp/n (fixed/y 2 :transport) (bsp/s (fixed/y 2 :status) (fill/xy (bsp/a (fill/xy (align/e :pool)) :arranger))))
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "tengri_editor"
|
|
||||||
description = "Embeddable editor for Tengri DSL."
|
|
||||||
version = { workspace = true }
|
|
||||||
edition = { workspace = true }
|
|
||||||
|
|
@ -8,8 +8,7 @@ edition = { workspace = true }
|
||||||
path = "input.rs"
|
path = "input.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tengri_core = { path = "../core" }
|
dizzle = { path = "../../dizzle" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tengri_tui = { path = "../tui" }
|
tengri_tui = { path = "../tui" }
|
||||||
tengri_dsl = { path = "../dsl" }
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#![feature(associated_type_defaults)]
|
#![feature(associated_type_defaults)]
|
||||||
#![feature(if_let_guard)]
|
#![feature(if_let_guard)]
|
||||||
|
|
||||||
pub(crate) use tengri_core::*;
|
pub(crate) use dizzle::*;
|
||||||
|
|
||||||
#[cfg(test)] mod input_test;
|
#[cfg(test)] mod input_test;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,21 +4,16 @@ description = "UI metaframework, output layer."
|
||||||
version = { workspace = true }
|
version = { workspace = true }
|
||||||
edition = { workspace = true }
|
edition = { workspace = true }
|
||||||
|
|
||||||
[lib]
|
|
||||||
path = "src/output.rs"
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
bumpalo = [ "dep:bumpalo" ]
|
bumpalo = [ "dep:bumpalo" ]
|
||||||
dsl = [ "dep:tengri_dsl" ]
|
dsl = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tengri_core = { path = "../core" }
|
dizzle = { path = "../../dizzle" }
|
||||||
tengri_dsl = { optional = true, path = "../dsl" }
|
bumpalo = { optional = true, workspace = true }
|
||||||
bumpalo = { optional = true, workspace = true }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tengri = { path = "../tengri", features = [ "dsl", "tui" ] }
|
tengri = { path = "../tengri", features = [ "dsl", "tui" ] }
|
||||||
tengri_tui = { path = "../tui" }
|
tengri_tui = { path = "../tui" }
|
||||||
tengri_dsl = { path = "../dsl" }
|
|
||||||
proptest = { workspace = true }
|
proptest = { workspace = true }
|
||||||
proptest-derive = { workspace = true }
|
proptest-derive = { workspace = true }
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ impl<O: Out, Head: Content<O>, Tail: Content<O>> Draw<O> for Bsp<Head, Tail> {
|
||||||
fn draw (&self, to: &mut O) {
|
fn draw (&self, to: &mut O) {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
South => {
|
South => {
|
||||||
panic!("{}", self.1.h(to.area()));
|
//panic!("{}", self.1.h(to.area()));
|
||||||
let area_1 = self.1.layout(to.area());
|
let area_1 = self.1.layout(to.area());
|
||||||
let area_2 = self.2.layout([
|
let area_2 = self.2.layout([
|
||||||
to.area().x(),
|
to.area().x(),
|
||||||
|
|
@ -30,7 +30,7 @@ impl<O: Out, Head: Content<O>, Tail: Content<O>> Draw<O> for Bsp<Head, Tail> {
|
||||||
to.area().w(),
|
to.area().w(),
|
||||||
to.area().h().minus(area_1.h())
|
to.area().h().minus(area_1.h())
|
||||||
].into());
|
].into());
|
||||||
panic!("{area_1:?} {area_2:?}");
|
//panic!("{area_1:?} {area_2:?}");
|
||||||
to.place_at(area_1, &self.1);
|
to.place_at(area_1, &self.1);
|
||||||
to.place_at(area_2, &self.2);
|
to.place_at(area_2, &self.2);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
200
output/src/lib.rs
Normal file
200
output/src/lib.rs
Normal file
|
|
@ -0,0 +1,200 @@
|
||||||
|
#![feature(step_trait)]
|
||||||
|
#![feature(type_alias_impl_trait)]
|
||||||
|
#![feature(impl_trait_in_assoc_type)]
|
||||||
|
#![feature(const_precise_live_drops)]
|
||||||
|
#![feature(type_changing_struct_update)]
|
||||||
|
#![feature(anonymous_lifetime_in_impl_trait)]
|
||||||
|
#![feature(const_option_ops)]
|
||||||
|
#![feature(const_trait_impl)]
|
||||||
|
#![feature(const_default)]
|
||||||
|
#![feature(trait_alias)]
|
||||||
|
//#![feature(non_lifetime_binders)]
|
||||||
|
pub(crate) use self::Direction::*;
|
||||||
|
pub(crate) use std::fmt::{Debug, Display};
|
||||||
|
pub(crate) use std::marker::PhantomData;
|
||||||
|
pub(crate) use std::ops::{Add, Sub, Mul, Div};
|
||||||
|
pub(crate) use std::sync::{Arc, RwLock, atomic::{AtomicUsize, Ordering::Relaxed}};
|
||||||
|
pub(crate) use dizzle::*;
|
||||||
|
mod output; pub use self::output::*;
|
||||||
|
mod content; pub use self::content::*;
|
||||||
|
mod draw; pub use self::draw::*;
|
||||||
|
mod group; pub use self::group::*;
|
||||||
|
mod layout; pub use self::layout::*;
|
||||||
|
mod space; pub use self::space::*;
|
||||||
|
mod thunk; pub use self::thunk::*;
|
||||||
|
mod widget; pub use self::widget::*;
|
||||||
|
#[cfg(feature = "dsl")] mod view;
|
||||||
|
#[cfg(feature = "dsl")] pub use self::view::*;
|
||||||
|
#[cfg(test)] pub(crate) use proptest_derive::Arbitrary;
|
||||||
|
#[cfg(test)] mod test {
|
||||||
|
use crate::{*, Direction::*};
|
||||||
|
//use proptest_derive::Arbitrary;
|
||||||
|
use proptest::{prelude::*, option::of};
|
||||||
|
|
||||||
|
proptest! {
|
||||||
|
#[test] fn proptest_direction (
|
||||||
|
d in prop_oneof![
|
||||||
|
Just(North), Just(South),
|
||||||
|
Just(East), Just(West),
|
||||||
|
Just(Above), Just(Below)
|
||||||
|
],
|
||||||
|
x in u16::MIN..u16::MAX,
|
||||||
|
y in u16::MIN..u16::MAX,
|
||||||
|
w in u16::MIN..u16::MAX,
|
||||||
|
h in u16::MIN..u16::MAX,
|
||||||
|
a in u16::MIN..u16::MAX,
|
||||||
|
) {
|
||||||
|
let _ = d.split_fixed([x, y, w, h], a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
proptest! {
|
||||||
|
#[test] fn proptest_size (
|
||||||
|
x in u16::MIN..u16::MAX,
|
||||||
|
y in u16::MIN..u16::MAX,
|
||||||
|
a in u16::MIN..u16::MAX,
|
||||||
|
b in u16::MIN..u16::MAX,
|
||||||
|
) {
|
||||||
|
let size = [x, y];
|
||||||
|
let _ = size.w();
|
||||||
|
let _ = size.h();
|
||||||
|
let _ = size.wh();
|
||||||
|
let _ = size.clip_w(a);
|
||||||
|
let _ = size.clip_h(b);
|
||||||
|
let _ = size.expect_min(a, b);
|
||||||
|
let _ = size.to_area_pos();
|
||||||
|
let _ = size.to_area_size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
proptest! {
|
||||||
|
#[test] fn proptest_area (
|
||||||
|
x in u16::MIN..u16::MAX,
|
||||||
|
y in u16::MIN..u16::MAX,
|
||||||
|
w in u16::MIN..u16::MAX,
|
||||||
|
h in u16::MIN..u16::MAX,
|
||||||
|
a in u16::MIN..u16::MAX,
|
||||||
|
b in u16::MIN..u16::MAX,
|
||||||
|
) {
|
||||||
|
let _: [u16;4] = <[u16;4] as Area<u16>>::zero();
|
||||||
|
let _: [u16;4] = <[u16;4] as Area<u16>>::from_position([a, b]);
|
||||||
|
let _: [u16;4] = <[u16;4] as Area<u16>>::from_size([a, b]);
|
||||||
|
let area: [u16;4] = [x, y, w, h];
|
||||||
|
let _ = area.expect_min(a, b);
|
||||||
|
let _ = area.xy();
|
||||||
|
let _ = area.wh();
|
||||||
|
let _ = area.xywh();
|
||||||
|
let _ = area.clip_h(a);
|
||||||
|
let _ = area.clip_w(b);
|
||||||
|
let _ = area.clip([a, b]);
|
||||||
|
let _ = area.set_w(a);
|
||||||
|
let _ = area.set_h(b);
|
||||||
|
let _ = area.x2();
|
||||||
|
let _ = area.y2();
|
||||||
|
let _ = area.lrtb();
|
||||||
|
let _ = area.center();
|
||||||
|
let _ = area.center_x(a);
|
||||||
|
let _ = area.center_y(b);
|
||||||
|
let _ = area.center_xy([a, b]);
|
||||||
|
let _ = area.centered();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! test_op_transform {
|
||||||
|
($fn:ident, $Op:ident) => {
|
||||||
|
proptest! {
|
||||||
|
#[test] fn $fn (
|
||||||
|
op_x in of(u16::MIN..u16::MAX),
|
||||||
|
op_y in of(u16::MIN..u16::MAX),
|
||||||
|
content in "\\PC*",
|
||||||
|
x in u16::MIN..u16::MAX,
|
||||||
|
y in u16::MIN..u16::MAX,
|
||||||
|
w in u16::MIN..u16::MAX,
|
||||||
|
h in u16::MIN..u16::MAX,
|
||||||
|
) {
|
||||||
|
if let Some(op) = match (op_x, op_y) {
|
||||||
|
(Some(x), Some(y)) => Some($Op::XY(x, y, content)),
|
||||||
|
(Some(x), None) => Some($Op::X(x, content)),
|
||||||
|
(None, Some(y)) => Some($Op::y(y, content)),
|
||||||
|
_ => None
|
||||||
|
} {
|
||||||
|
//assert_eq!(Content::layout(&op, [x, y, w, h]),
|
||||||
|
//Draw::layout(&op, [x, y, w, h]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test_op_transform!(proptest_op_fixed, Fixed);
|
||||||
|
test_op_transform!(proptest_op_min, Min);
|
||||||
|
test_op_transform!(proptest_op_max, Max);
|
||||||
|
test_op_transform!(proptest_op_push, Push);
|
||||||
|
test_op_transform!(proptest_op_pull, Pull);
|
||||||
|
test_op_transform!(proptest_op_shrink, Shrink);
|
||||||
|
test_op_transform!(proptest_op_expand, Expand);
|
||||||
|
test_op_transform!(proptest_op_padding, Pad);
|
||||||
|
|
||||||
|
proptest! {
|
||||||
|
#[test] fn proptest_op_bsp (
|
||||||
|
d in prop_oneof![
|
||||||
|
Just(North), Just(South),
|
||||||
|
Just(East), Just(West),
|
||||||
|
Just(Above), Just(Below)
|
||||||
|
],
|
||||||
|
a in "\\PC*",
|
||||||
|
b in "\\PC*",
|
||||||
|
x in u16::MIN..u16::MAX,
|
||||||
|
y in u16::MIN..u16::MAX,
|
||||||
|
w in u16::MIN..u16::MAX,
|
||||||
|
h in u16::MIN..u16::MAX,
|
||||||
|
) {
|
||||||
|
let bsp = Bsp(d, a, b);
|
||||||
|
//assert_eq!(
|
||||||
|
//Content::layout(&bsp, [x, y, w, h]),
|
||||||
|
//Draw::layout(&bsp, [x, y, w, h]),
|
||||||
|
//);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test] fn test_stub_output () -> Usually<()> {
|
||||||
|
use crate::*;
|
||||||
|
struct TestOut([u16;4]);
|
||||||
|
impl Out for TestOut {
|
||||||
|
type Unit = u16;
|
||||||
|
type Size = [u16;2];
|
||||||
|
type Area = [u16;4];
|
||||||
|
fn area (&self) -> [u16;4] {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
fn area_mut (&mut self) -> &mut [u16;4] {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
fn place_at <T: Draw<Self> + ?Sized> (&mut self, area: [u16;4], _: &T) {
|
||||||
|
println!("place_at: {area:?}");
|
||||||
|
()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Draw<TestOut> for String {
|
||||||
|
fn draw (&self, to: &mut TestOut) {
|
||||||
|
to.area_mut().set_w(self.len() as u16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test] fn test_space () {
|
||||||
|
use crate::*;
|
||||||
|
assert_eq!(Area::center(&[10u16, 10, 20, 20]), [20, 20]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test] fn test_iter_map () {
|
||||||
|
struct Foo;
|
||||||
|
impl<T: Out> Content<T> for Foo {}
|
||||||
|
fn _make_map <T: Out, U: Content<T> + Send + Sync> (data: &Vec<U>) -> impl Draw<T> {
|
||||||
|
Map::new(||data.iter(), |_foo, _index|{})
|
||||||
|
}
|
||||||
|
let _data = vec![Foo, Foo, Foo];
|
||||||
|
//let map = make_map(&data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,21 +1,4 @@
|
||||||
#![feature(step_trait)]
|
use crate::*;
|
||||||
#![feature(type_alias_impl_trait)]
|
|
||||||
#![feature(impl_trait_in_assoc_type)]
|
|
||||||
#![feature(const_precise_live_drops)]
|
|
||||||
#![feature(type_changing_struct_update)]
|
|
||||||
#![feature(anonymous_lifetime_in_impl_trait)]
|
|
||||||
#![feature(const_option_ops)]
|
|
||||||
#![feature(const_trait_impl)]
|
|
||||||
#![feature(const_default)]
|
|
||||||
#![feature(trait_alias)]
|
|
||||||
//#![feature(non_lifetime_binders)]
|
|
||||||
|
|
||||||
pub(crate) use self::Direction::*;
|
|
||||||
pub(crate) use std::fmt::{Debug, Display};
|
|
||||||
pub(crate) use std::marker::PhantomData;
|
|
||||||
pub(crate) use std::ops::{Add, Sub, Mul, Div};
|
|
||||||
pub(crate) use std::sync::{Arc, RwLock, atomic::{AtomicUsize, Ordering::Relaxed}};
|
|
||||||
pub(crate) use tengri_core::*;
|
|
||||||
|
|
||||||
/// Drawing target.
|
/// Drawing target.
|
||||||
pub trait Out: Send + Sync + Sized {
|
pub trait Out: Send + Sync + Sized {
|
||||||
|
|
@ -49,17 +32,3 @@ pub trait Out: Send + Sync + Sized {
|
||||||
/// Mutable pointer to area.
|
/// Mutable pointer to area.
|
||||||
fn area_mut (&mut self) -> &mut Self::Area;
|
fn area_mut (&mut self) -> &mut Self::Area;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)] mod output_test;
|
|
||||||
#[cfg(test)] pub(crate) use proptest_derive::Arbitrary;
|
|
||||||
|
|
||||||
mod content; pub use self::content::*;
|
|
||||||
mod draw; pub use self::draw::*;
|
|
||||||
mod group; pub use self::group::*;
|
|
||||||
mod layout; pub use self::layout::*;
|
|
||||||
mod space; pub use self::space::*;
|
|
||||||
mod thunk; pub use self::thunk::*;
|
|
||||||
mod widget; pub use self::widget::*;
|
|
||||||
|
|
||||||
#[cfg(feature = "dsl")] mod view;
|
|
||||||
#[cfg(feature = "dsl")] pub use self::view::*;
|
|
||||||
|
|
|
||||||
|
|
@ -1,170 +0,0 @@
|
||||||
use crate::{*, Direction::*};
|
|
||||||
//use proptest_derive::Arbitrary;
|
|
||||||
use proptest::{prelude::*, option::of};
|
|
||||||
|
|
||||||
proptest! {
|
|
||||||
#[test] fn proptest_direction (
|
|
||||||
d in prop_oneof![
|
|
||||||
Just(North), Just(South),
|
|
||||||
Just(East), Just(West),
|
|
||||||
Just(Above), Just(Below)
|
|
||||||
],
|
|
||||||
x in u16::MIN..u16::MAX,
|
|
||||||
y in u16::MIN..u16::MAX,
|
|
||||||
w in u16::MIN..u16::MAX,
|
|
||||||
h in u16::MIN..u16::MAX,
|
|
||||||
a in u16::MIN..u16::MAX,
|
|
||||||
) {
|
|
||||||
let _ = d.split_fixed([x, y, w, h], a);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
proptest! {
|
|
||||||
#[test] fn proptest_size (
|
|
||||||
x in u16::MIN..u16::MAX,
|
|
||||||
y in u16::MIN..u16::MAX,
|
|
||||||
a in u16::MIN..u16::MAX,
|
|
||||||
b in u16::MIN..u16::MAX,
|
|
||||||
) {
|
|
||||||
let size = [x, y];
|
|
||||||
let _ = size.w();
|
|
||||||
let _ = size.h();
|
|
||||||
let _ = size.wh();
|
|
||||||
let _ = size.clip_w(a);
|
|
||||||
let _ = size.clip_h(b);
|
|
||||||
let _ = size.expect_min(a, b);
|
|
||||||
let _ = size.to_area_pos();
|
|
||||||
let _ = size.to_area_size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
proptest! {
|
|
||||||
#[test] fn proptest_area (
|
|
||||||
x in u16::MIN..u16::MAX,
|
|
||||||
y in u16::MIN..u16::MAX,
|
|
||||||
w in u16::MIN..u16::MAX,
|
|
||||||
h in u16::MIN..u16::MAX,
|
|
||||||
a in u16::MIN..u16::MAX,
|
|
||||||
b in u16::MIN..u16::MAX,
|
|
||||||
) {
|
|
||||||
let _: [u16;4] = <[u16;4] as Area<u16>>::zero();
|
|
||||||
let _: [u16;4] = <[u16;4] as Area<u16>>::from_position([a, b]);
|
|
||||||
let _: [u16;4] = <[u16;4] as Area<u16>>::from_size([a, b]);
|
|
||||||
let area: [u16;4] = [x, y, w, h];
|
|
||||||
let _ = area.expect_min(a, b);
|
|
||||||
let _ = area.xy();
|
|
||||||
let _ = area.wh();
|
|
||||||
let _ = area.xywh();
|
|
||||||
let _ = area.clip_h(a);
|
|
||||||
let _ = area.clip_w(b);
|
|
||||||
let _ = area.clip([a, b]);
|
|
||||||
let _ = area.set_w(a);
|
|
||||||
let _ = area.set_h(b);
|
|
||||||
let _ = area.x2();
|
|
||||||
let _ = area.y2();
|
|
||||||
let _ = area.lrtb();
|
|
||||||
let _ = area.center();
|
|
||||||
let _ = area.center_x(a);
|
|
||||||
let _ = area.center_y(b);
|
|
||||||
let _ = area.center_xy([a, b]);
|
|
||||||
let _ = area.centered();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! test_op_transform {
|
|
||||||
($fn:ident, $Op:ident) => {
|
|
||||||
proptest! {
|
|
||||||
#[test] fn $fn (
|
|
||||||
op_x in of(u16::MIN..u16::MAX),
|
|
||||||
op_y in of(u16::MIN..u16::MAX),
|
|
||||||
content in "\\PC*",
|
|
||||||
x in u16::MIN..u16::MAX,
|
|
||||||
y in u16::MIN..u16::MAX,
|
|
||||||
w in u16::MIN..u16::MAX,
|
|
||||||
h in u16::MIN..u16::MAX,
|
|
||||||
) {
|
|
||||||
if let Some(op) = match (op_x, op_y) {
|
|
||||||
(Some(x), Some(y)) => Some($Op::XY(x, y, content)),
|
|
||||||
(Some(x), None) => Some($Op::X(x, content)),
|
|
||||||
(None, Some(y)) => Some($Op::y(y, content)),
|
|
||||||
_ => None
|
|
||||||
} {
|
|
||||||
//assert_eq!(Content::layout(&op, [x, y, w, h]),
|
|
||||||
//Draw::layout(&op, [x, y, w, h]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
test_op_transform!(proptest_op_fixed, Fixed);
|
|
||||||
test_op_transform!(proptest_op_min, Min);
|
|
||||||
test_op_transform!(proptest_op_max, Max);
|
|
||||||
test_op_transform!(proptest_op_push, Push);
|
|
||||||
test_op_transform!(proptest_op_pull, Pull);
|
|
||||||
test_op_transform!(proptest_op_shrink, Shrink);
|
|
||||||
test_op_transform!(proptest_op_expand, Expand);
|
|
||||||
test_op_transform!(proptest_op_padding, Pad);
|
|
||||||
|
|
||||||
proptest! {
|
|
||||||
#[test] fn proptest_op_bsp (
|
|
||||||
d in prop_oneof![
|
|
||||||
Just(North), Just(South),
|
|
||||||
Just(East), Just(West),
|
|
||||||
Just(Above), Just(Below)
|
|
||||||
],
|
|
||||||
a in "\\PC*",
|
|
||||||
b in "\\PC*",
|
|
||||||
x in u16::MIN..u16::MAX,
|
|
||||||
y in u16::MIN..u16::MAX,
|
|
||||||
w in u16::MIN..u16::MAX,
|
|
||||||
h in u16::MIN..u16::MAX,
|
|
||||||
) {
|
|
||||||
let bsp = Bsp(d, a, b);
|
|
||||||
//assert_eq!(
|
|
||||||
//Content::layout(&bsp, [x, y, w, h]),
|
|
||||||
//Draw::layout(&bsp, [x, y, w, h]),
|
|
||||||
//);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test] fn test_stub_output () -> Usually<()> {
|
|
||||||
use crate::*;
|
|
||||||
struct TestOut([u16;4]);
|
|
||||||
impl Out for TestOut {
|
|
||||||
type Unit = u16;
|
|
||||||
type Size = [u16;2];
|
|
||||||
type Area = [u16;4];
|
|
||||||
fn area (&self) -> [u16;4] {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
fn area_mut (&mut self) -> &mut [u16;4] {
|
|
||||||
&mut self.0
|
|
||||||
}
|
|
||||||
fn place_at <T: Draw<Self> + ?Sized> (&mut self, area: [u16;4], _: &T) {
|
|
||||||
println!("place_at: {area:?}");
|
|
||||||
()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Draw<TestOut> for String {
|
|
||||||
fn draw (&self, to: &mut TestOut) {
|
|
||||||
to.area_mut().set_w(self.len() as u16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test] fn test_space () {
|
|
||||||
use crate::*;
|
|
||||||
assert_eq!(Area::center(&[10u16, 10, 20, 20]), [20, 20]);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test] fn test_iter_map () {
|
|
||||||
struct Foo;
|
|
||||||
impl<T: Out> Content<T> for Foo {}
|
|
||||||
fn _make_map <T: Out, U: Content<T> + Send + Sync> (data: &Vec<U>) -> impl Draw<T> {
|
|
||||||
Map::new(||data.iter(), |_foo, _index|{})
|
|
||||||
}
|
|
||||||
let _data = vec![Foo, Foo, Foo];
|
|
||||||
//let map = make_map(&data);
|
|
||||||
}
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use ::tengri_dsl::{Dsl, DslExpr, DslWord, DslNs};
|
use ::dizzle::{Dsl, DslExpr, DslWord, DslNs};
|
||||||
|
|
||||||
pub trait View<O, U> {
|
pub trait View<O, U> {
|
||||||
fn view_expr <'a> (&'a self, output: &mut O, expr: &'a impl DslExpr) -> Usually<U> {
|
fn view_expr <'a> (&'a self, output: &mut O, expr: &'a impl DslExpr) -> Usually<U> {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ edition = { workspace = true }
|
||||||
proc-macro = true
|
proc-macro = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tengri_core = { path = "../core" }
|
dizzle = { path = "../../dizzle" }
|
||||||
syn = { workspace = true }
|
syn = { workspace = true }
|
||||||
quote = { workspace = true }
|
quote = { workspace = true }
|
||||||
proc-macro2 = { workspace = true }
|
proc-macro2 = { workspace = true }
|
||||||
|
|
|
||||||
|
|
@ -9,18 +9,17 @@ default = [ "input", "output", "tui" ]
|
||||||
input = [ "tengri_input" ]
|
input = [ "tengri_input" ]
|
||||||
output = [ "tengri_output" ]
|
output = [ "tengri_output" ]
|
||||||
tui = [ "tengri_tui" ]
|
tui = [ "tengri_tui" ]
|
||||||
dsl = [ "tengri_dsl", "tengri_output/dsl", "tengri_tui/dsl" ]
|
dsl = [ "tengri_output/dsl", "tengri_tui/dsl" ]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tengri_core = { workspace = true }
|
dizzle = { workspace = true }
|
||||||
tengri_dsl = { optional = true, path = "../dsl" }
|
tengri_input = { workspace = true, optional = true }
|
||||||
tengri_input = { optional = true, path = "../input" }
|
tengri_output = { workspace = true, optional = true }
|
||||||
tengri_output = { optional = true, path = "../output" }
|
tengri_tui = { workspace = true, optional = true }
|
||||||
tengri_tui = { optional = true, path = "../tui" }
|
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tengri_proc = { path = "../proc" }
|
tengri_proc = { workspace = true }
|
||||||
tengri = { path = ".", features = [ "dsl" ] }
|
tengri = { workspace = true, features = [ "dsl" ] }
|
||||||
crossterm = { workspace = true }
|
crossterm = { workspace = true }
|
||||||
|
|
||||||
[target.'cfg(target_os = "linux")']
|
[target.'cfg(target_os = "linux")']
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,112 @@
|
||||||
pub use ::tengri_core::*;
|
pub use ::dizzle::*;
|
||||||
#[cfg(feature="output")] pub use ::tengri_output as output;
|
#[cfg(feature="output")] pub use ::tengri_output as output;
|
||||||
#[cfg(feature="input")] pub use ::tengri_input as input;
|
#[cfg(feature="input")] pub use ::tengri_input as input;
|
||||||
#[cfg(feature="dsl")] pub use ::tengri_dsl as dsl;
|
|
||||||
#[cfg(feature="tui")] pub use ::tengri_tui as tui;
|
#[cfg(feature="tui")] pub use ::tengri_tui as tui;
|
||||||
|
|
||||||
#[cfg(test)] extern crate tengri_proc;
|
#[cfg(test)] extern crate tengri_proc;
|
||||||
#[cfg(test)] mod test;
|
#[cfg(test)] mod test {
|
||||||
|
// FIXME
|
||||||
|
//use crate::*;
|
||||||
|
//use crate::{dsl::*, input::*, tui::TuiIn};
|
||||||
|
//use crossterm::event::{Event, KeyEvent, KeyCode, KeyModifiers, KeyEventKind, KeyEventState};
|
||||||
|
//use std::cmp::Ordering;
|
||||||
|
|
||||||
|
//#[test] fn test_subcommand () -> Usually<()> {
|
||||||
|
//#[derive(Debug)] struct Event(crossterm::event::Event);
|
||||||
|
//impl Eq for Event {}
|
||||||
|
//impl PartialEq for Event { fn eq (&self, other: &Self) -> bool { todo!() } }
|
||||||
|
//impl Ord for Event { fn cmp (&self, other: &Self) -> Ordering { todo!() } }
|
||||||
|
//impl PartialOrd for Event { fn partial_cmp (&self, other: &Self) -> Option<Ordering> { None } }
|
||||||
|
//struct Test { keys: InputMap<Event, Ast> }
|
||||||
|
|
||||||
|
//handle!(TuiIn: |self: Test, input|Ok(None));[>if let Some(command) = self.keys.command(self, input) {
|
||||||
|
//Ok(Some(true))
|
||||||
|
//} else {
|
||||||
|
//Ok(None)
|
||||||
|
//});*/
|
||||||
|
|
||||||
|
//#[tengri_proc::command(Test)]
|
||||||
|
//impl TestCommand {
|
||||||
|
//fn do_thing (_state: &mut Test) -> Perhaps<Self> {
|
||||||
|
//Ok(None)
|
||||||
|
//}
|
||||||
|
//fn do_thing_arg (_state: &mut Test, _arg: usize) -> Perhaps<Self> {
|
||||||
|
//Ok(None)
|
||||||
|
//}
|
||||||
|
//fn do_sub (state: &mut Test, command: TestSubcommand) -> Perhaps<Self> {
|
||||||
|
//Ok(command.execute(state)?.map(|command|Self::DoSub { command }))
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
|
||||||
|
//#[tengri_proc::command(Test)]
|
||||||
|
//impl TestSubcommand {
|
||||||
|
//fn do_other_thing (_state: &mut Test) -> Perhaps<Self> {
|
||||||
|
//Ok(None)
|
||||||
|
//}
|
||||||
|
//fn do_other_thing_arg (_state: &mut Test, _arg: usize) -> Perhaps<Self> {
|
||||||
|
//Ok(None)
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
|
||||||
|
//let mut test = Test {
|
||||||
|
//keys: InputMap::from_source("
|
||||||
|
//(@a do-thing)
|
||||||
|
//(@b do-thing-arg 0)
|
||||||
|
//(@c do-sub do-other-thing)
|
||||||
|
//(@d do-sub do-other-thing-arg 0)
|
||||||
|
//")?
|
||||||
|
//};
|
||||||
|
|
||||||
|
////assert_eq!(Some(true), test.handle(&TuiIn(Default::default(), Event::Key(KeyEvent {
|
||||||
|
////kind: KeyEventKind::Press,
|
||||||
|
////code: KeyCode::Char('a'),
|
||||||
|
////modifiers: KeyModifiers::NONE,
|
||||||
|
////state: KeyEventState::NONE,
|
||||||
|
////})))?);
|
||||||
|
////assert_eq!(Some(true), test.handle(&TuiIn(Default::default(), Event::Key(KeyEvent {
|
||||||
|
////kind: KeyEventKind::Press,
|
||||||
|
////code: KeyCode::Char('b'),
|
||||||
|
////modifiers: KeyModifiers::NONE,
|
||||||
|
////state: KeyEventState::NONE,
|
||||||
|
////})))?);
|
||||||
|
////assert_eq!(Some(true), test.handle(&TuiIn(Default::default(), Event::Key(KeyEvent {
|
||||||
|
////kind: KeyEventKind::Press,
|
||||||
|
////code: KeyCode::Char('c'),
|
||||||
|
////modifiers: KeyModifiers::NONE,
|
||||||
|
////state: KeyEventState::NONE,
|
||||||
|
////})))?);
|
||||||
|
////assert_eq!(Some(true), test.handle(&TuiIn(Default::default(), Event::Key(KeyEvent {
|
||||||
|
////kind: KeyEventKind::Press,
|
||||||
|
////code: KeyCode::Char('d'),
|
||||||
|
////modifiers: KeyModifiers::NONE,
|
||||||
|
////state: KeyEventState::NONE,
|
||||||
|
////})))?);
|
||||||
|
////assert_eq!(None, test.handle(&TuiIn(Default::default(), Event::Key(KeyEvent {
|
||||||
|
////kind: KeyEventKind::Press,
|
||||||
|
////code: KeyCode::Char('z'),
|
||||||
|
////modifiers: KeyModifiers::NONE,
|
||||||
|
////state: KeyEventState::NONE,
|
||||||
|
////})))?);
|
||||||
|
//Ok(())
|
||||||
|
//}
|
||||||
|
|
||||||
|
//FIXME:
|
||||||
|
//#[cfg(test)] #[test] fn test_dsl_context () {
|
||||||
|
//use crate::dsl::{Dsl, Value};
|
||||||
|
|
||||||
|
//struct Test;
|
||||||
|
//#[tengri_proc::expose]
|
||||||
|
//impl Test {
|
||||||
|
//fn some_bool (&self) -> bool {
|
||||||
|
//true
|
||||||
|
//}
|
||||||
|
//}
|
||||||
|
//assert_eq!(Dsl::get(&Test, &Value::Sym(":false")), Some(false));
|
||||||
|
//assert_eq!(Dsl::get(&Test, &Value::Sym(":true")), Some(true));
|
||||||
|
//assert_eq!(Dsl::get(&Test, &Value::Sym(":some-bool")), Some(true));
|
||||||
|
//assert_eq!(Dsl::get(&Test, &Value::Sym(":missing-bool")), None);
|
||||||
|
//assert_eq!(Dsl::get(&Test, &Value::Num(0)), Some(false));
|
||||||
|
//assert_eq!(Dsl::get(&Test, &Value::Num(1)), Some(true));
|
||||||
|
//}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,103 +0,0 @@
|
||||||
// FIXME
|
|
||||||
//use crate::*;
|
|
||||||
//use crate::{dsl::*, input::*, tui::TuiIn};
|
|
||||||
//use crossterm::event::{Event, KeyEvent, KeyCode, KeyModifiers, KeyEventKind, KeyEventState};
|
|
||||||
//use std::cmp::Ordering;
|
|
||||||
|
|
||||||
//#[test] fn test_subcommand () -> Usually<()> {
|
|
||||||
//#[derive(Debug)] struct Event(crossterm::event::Event);
|
|
||||||
//impl Eq for Event {}
|
|
||||||
//impl PartialEq for Event { fn eq (&self, other: &Self) -> bool { todo!() } }
|
|
||||||
//impl Ord for Event { fn cmp (&self, other: &Self) -> Ordering { todo!() } }
|
|
||||||
//impl PartialOrd for Event { fn partial_cmp (&self, other: &Self) -> Option<Ordering> { None } }
|
|
||||||
//struct Test { keys: InputMap<Event, Ast> }
|
|
||||||
|
|
||||||
//handle!(TuiIn: |self: Test, input|Ok(None));[>if let Some(command) = self.keys.command(self, input) {
|
|
||||||
//Ok(Some(true))
|
|
||||||
//} else {
|
|
||||||
//Ok(None)
|
|
||||||
//});*/
|
|
||||||
|
|
||||||
//#[tengri_proc::command(Test)]
|
|
||||||
//impl TestCommand {
|
|
||||||
//fn do_thing (_state: &mut Test) -> Perhaps<Self> {
|
|
||||||
//Ok(None)
|
|
||||||
//}
|
|
||||||
//fn do_thing_arg (_state: &mut Test, _arg: usize) -> Perhaps<Self> {
|
|
||||||
//Ok(None)
|
|
||||||
//}
|
|
||||||
//fn do_sub (state: &mut Test, command: TestSubcommand) -> Perhaps<Self> {
|
|
||||||
//Ok(command.execute(state)?.map(|command|Self::DoSub { command }))
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
|
|
||||||
//#[tengri_proc::command(Test)]
|
|
||||||
//impl TestSubcommand {
|
|
||||||
//fn do_other_thing (_state: &mut Test) -> Perhaps<Self> {
|
|
||||||
//Ok(None)
|
|
||||||
//}
|
|
||||||
//fn do_other_thing_arg (_state: &mut Test, _arg: usize) -> Perhaps<Self> {
|
|
||||||
//Ok(None)
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
|
|
||||||
//let mut test = Test {
|
|
||||||
//keys: InputMap::from_source("
|
|
||||||
//(@a do-thing)
|
|
||||||
//(@b do-thing-arg 0)
|
|
||||||
//(@c do-sub do-other-thing)
|
|
||||||
//(@d do-sub do-other-thing-arg 0)
|
|
||||||
//")?
|
|
||||||
//};
|
|
||||||
|
|
||||||
////assert_eq!(Some(true), test.handle(&TuiIn(Default::default(), Event::Key(KeyEvent {
|
|
||||||
////kind: KeyEventKind::Press,
|
|
||||||
////code: KeyCode::Char('a'),
|
|
||||||
////modifiers: KeyModifiers::NONE,
|
|
||||||
////state: KeyEventState::NONE,
|
|
||||||
////})))?);
|
|
||||||
////assert_eq!(Some(true), test.handle(&TuiIn(Default::default(), Event::Key(KeyEvent {
|
|
||||||
////kind: KeyEventKind::Press,
|
|
||||||
////code: KeyCode::Char('b'),
|
|
||||||
////modifiers: KeyModifiers::NONE,
|
|
||||||
////state: KeyEventState::NONE,
|
|
||||||
////})))?);
|
|
||||||
////assert_eq!(Some(true), test.handle(&TuiIn(Default::default(), Event::Key(KeyEvent {
|
|
||||||
////kind: KeyEventKind::Press,
|
|
||||||
////code: KeyCode::Char('c'),
|
|
||||||
////modifiers: KeyModifiers::NONE,
|
|
||||||
////state: KeyEventState::NONE,
|
|
||||||
////})))?);
|
|
||||||
////assert_eq!(Some(true), test.handle(&TuiIn(Default::default(), Event::Key(KeyEvent {
|
|
||||||
////kind: KeyEventKind::Press,
|
|
||||||
////code: KeyCode::Char('d'),
|
|
||||||
////modifiers: KeyModifiers::NONE,
|
|
||||||
////state: KeyEventState::NONE,
|
|
||||||
////})))?);
|
|
||||||
////assert_eq!(None, test.handle(&TuiIn(Default::default(), Event::Key(KeyEvent {
|
|
||||||
////kind: KeyEventKind::Press,
|
|
||||||
////code: KeyCode::Char('z'),
|
|
||||||
////modifiers: KeyModifiers::NONE,
|
|
||||||
////state: KeyEventState::NONE,
|
|
||||||
////})))?);
|
|
||||||
//Ok(())
|
|
||||||
//}
|
|
||||||
|
|
||||||
//FIXME:
|
|
||||||
//#[cfg(test)] #[test] fn test_dsl_context () {
|
|
||||||
//use crate::dsl::{Dsl, Value};
|
|
||||||
|
|
||||||
//struct Test;
|
|
||||||
//#[tengri_proc::expose]
|
|
||||||
//impl Test {
|
|
||||||
//fn some_bool (&self) -> bool {
|
|
||||||
//true
|
|
||||||
//}
|
|
||||||
//}
|
|
||||||
//assert_eq!(Dsl::get(&Test, &Value::Sym(":false")), Some(false));
|
|
||||||
//assert_eq!(Dsl::get(&Test, &Value::Sym(":true")), Some(true));
|
|
||||||
//assert_eq!(Dsl::get(&Test, &Value::Sym(":some-bool")), Some(true));
|
|
||||||
//assert_eq!(Dsl::get(&Test, &Value::Sym(":missing-bool")), None);
|
|
||||||
//assert_eq!(Dsl::get(&Test, &Value::Num(0)), Some(false));
|
|
||||||
//assert_eq!(Dsl::get(&Test, &Value::Num(1)), Some(true));
|
|
||||||
//}
|
|
||||||
|
|
@ -4,24 +4,20 @@ description = "UI metaframework, Ratatui backend."
|
||||||
version = { workspace = true }
|
version = { workspace = true }
|
||||||
edition = { workspace = true }
|
edition = { workspace = true }
|
||||||
|
|
||||||
[lib]
|
|
||||||
path = "src/tui.rs"
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
dsl = [ "dep:tengri_dsl", "tengri_output/dsl" ]
|
dsl = [ "tengri_output/dsl" ]
|
||||||
bumpalo = [ "dep:bumpalo" ]
|
bumpalo = [ "dep:bumpalo" ]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tengri_core = { workspace = true }
|
dizzle = { workspace = true }
|
||||||
|
|
||||||
tengri_input = { workspace = true }
|
tengri_input = { workspace = true }
|
||||||
tengri_output = { workspace = true }
|
tengri_output = { workspace = true }
|
||||||
tengri_dsl = { workspace = true, optional = true }
|
|
||||||
|
|
||||||
atomic_float = { workspace = true }
|
atomic_float = { workspace = true }
|
||||||
better-panic = { workspace = true }
|
better-panic = { workspace = true }
|
||||||
bumpalo = { workspace = true, optional = true }
|
bumpalo = { workspace = true, optional = true }
|
||||||
crossterm = { workspace = true }
|
crossterm = { workspace = true }
|
||||||
konst = { workspace = true }
|
|
||||||
palette = { workspace = true }
|
palette = { workspace = true }
|
||||||
quanta = { workspace = true }
|
quanta = { workspace = true }
|
||||||
rand = { workspace = true }
|
rand = { workspace = true }
|
||||||
|
|
@ -30,5 +26,4 @@ unicode-width = { workspace = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tengri = { workspace = true, features = [ "dsl" ] }
|
tengri = { workspace = true, features = [ "dsl" ] }
|
||||||
tengri_dsl = { workspace = true }
|
|
||||||
tengri_proc = { workspace = true }
|
tengri_proc = { workspace = true }
|
||||||
|
|
|
||||||
62
tui/src/lib.rs
Normal file
62
tui/src/lib.rs
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
#![feature(type_changing_struct_update, trait_alias)]
|
||||||
|
pub use ::{tengri_input, tengri_output, ratatui, crossterm, palette, better_panic};
|
||||||
|
pub(crate) use ::{
|
||||||
|
dizzle::*,
|
||||||
|
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},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mod tui_engine; pub use self::tui_engine::*;
|
||||||
|
mod tui_content; pub use self::tui_content::*;
|
||||||
|
#[cfg(test)] mod tui_test {
|
||||||
|
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> {
|
||||||
|
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 ));
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
@ -1,79 +0,0 @@
|
||||||
#![feature(type_changing_struct_update)]
|
|
||||||
#![feature(trait_alias)]
|
|
||||||
#[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)
|
|
||||||
}
|
|
||||||
|
|
@ -102,3 +102,47 @@ impl<T: TuiWidget + Send + Sync + 'static> TuiRun<T> for Arc<RwLock<Tui>> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd)] pub struct TuiEvent(Event);
|
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd)] pub struct TuiEvent(pub Event);
|
||||||
impl Ord for TuiEvent {
|
impl Ord for TuiEvent {
|
||||||
fn cmp (&self, other: &Self) -> std::cmp::Ordering {
|
fn cmp (&self, other: &Self) -> std::cmp::Ordering {
|
||||||
self.partial_cmp(other)
|
self.partial_cmp(other)
|
||||||
|
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
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> {
|
|
||||||
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