add tengri_core; fix errors and warnings; unify deps

This commit is contained in:
🪞👃🪞 2025-05-10 15:25:09 +03:00
parent cb8fd26922
commit 8dda576c9d
18 changed files with 180 additions and 152 deletions

10
Cargo.lock generated
View file

@ -938,6 +938,7 @@ version = "0.13.0"
dependencies = [
"crossterm",
"tengri",
"tengri_core",
"tengri_dsl",
"tengri_input",
"tengri_output",
@ -945,6 +946,10 @@ dependencies = [
"tengri_tui",
]
[[package]]
name = "tengri_core"
version = "0.13.0"
[[package]]
name = "tengri_dsl"
version = "0.13.0"
@ -952,6 +957,7 @@ dependencies = [
"itertools 0.14.0",
"konst",
"proptest",
"tengri_core",
"tengri_tui",
"thiserror",
]
@ -960,6 +966,7 @@ dependencies = [
name = "tengri_input"
version = "0.13.0"
dependencies = [
"tengri_core",
"tengri_dsl",
"tengri_tui",
]
@ -971,6 +978,7 @@ dependencies = [
"proptest",
"proptest-derive",
"tengri",
"tengri_core",
"tengri_dsl",
"tengri_tui",
]
@ -983,6 +991,7 @@ dependencies = [
"proc-macro2",
"quote",
"syn",
"tengri_core",
]
[[package]]
@ -998,6 +1007,7 @@ dependencies = [
"rand",
"ratatui",
"tengri",
"tengri_core",
"tengri_dsl",
"tengri_input",
"tengri_output",

View file

@ -1,11 +1,15 @@
[workspace.package]
version = "0.13.0"
edition = "2024"
[profile.release]
lto = true
[profile.coverage]
inherits = "test"
lto = false
[workspace]
resolver = "2"
members = [
"./tengri",
"./core",
"./input",
"./output",
"./tui",
@ -13,9 +17,25 @@ members = [
"./proc",
]
[profile.release]
lto = true
[workspace.package]
version = "0.13.0"
edition = "2024"
[profile.coverage]
inherits = "test"
lto = false
[workspace.dependencies]
atomic_float = { version = "1" }
better-panic = { version = "0.3.0" }
crossterm = { version = "0.28.1" }
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" ] }
proc-macro2 = { version = "1", features = ["span-locations"] }
proptest = { version = "^1" }
proptest-derive = { version = "^0.5.1" }
quanta = { version = "0.12.3" }
quote = { version = "1" }
rand = { version = "0.8.5" }
ratatui = { version = "0.29.0", features = [ "unstable-widget-ref", "underline-color" ] }
syn = { version = "2", features = ["full", "extra-traits"] }
thiserror = { version = "2.0" }
unicode-width = { version = "0.2" }

6
core/Cargo.toml Normal file
View file

@ -0,0 +1,6 @@
[package]
name = "tengri_core"
description = "UI metaframework, core definitions."
version = { workspace = true }
edition = { workspace = true }

7
core/src/lib.rs Normal file
View file

@ -0,0 +1,7 @@
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>>;

View file

@ -5,12 +5,10 @@ version = { workspace = true }
edition = { workspace = true }
[dependencies]
konst = { version = "0.3.16", features = [ "rust_1_83" ] }
itertools = "0.14.0"
thiserror = "2.0"
[features]
default = []
tengri_core = { path = "../core" }
konst = { workspace = true }
itertools = { workspace = true }
thiserror = { workspace = true }
[dev-dependencies]
tengri_tui = { path = "../tui" }

View file

@ -1,5 +1,4 @@
use crate::*;
use thiserror::Error;
pub type ParseResult<T> = Result<T, ParseError>;
@ -16,41 +15,6 @@ pub type ParseResult<T> = Result<T, ParseError>;
Code(u8),
}
pub trait TryFromDsl<'state, T>: Sized {
fn try_from_expr <'source: 'state> (
_state: &'state T, _iter: &mut TokenIter<'source>
) -> Option<Self> {
None
}
fn try_from_atom <'source: 'state> (
state: &'state T, value: Value<'source>
) -> Option<Self> {
if let Exp(0, mut iter) = value {
return Self::try_from_expr(state, &mut iter)
}
None
}
}
/// Map EDN tokens to parameters of a given type for a given context
pub trait Context<'state, U>: Sized {
fn get <'source> (&'state self, _iter: &mut TokenIter<'source>) -> Option<U> {
None
}
}
impl<'state, T: Context<'state, U>, U> Context<'state, U> for &T {
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<U> {
(*self).get(iter)
}
}
impl<'state, T: Context<'state, U>, U> Context<'state, U> for Option<T> {
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<U> {
self.as_ref().map(|s|s.get(iter)).flatten()
}
}
/// Implement the const iterator pattern.
#[macro_export] macro_rules! const_iter {
($(<$l:lifetime>)?|$self:ident: $Struct:ty| => $Item:ty => $expr:expr) => {
@ -138,6 +102,7 @@ impl<'a> SourceIter<'a> {
}
}
}
/// Static iteration helper.
#[macro_export] macro_rules! iterate {
($expr:expr => $arg: pat => $body:expr) => {
@ -240,7 +205,9 @@ pub const fn to_digit (c: char) -> Result<usize, ParseError> {
}
impl<'source> Token<'source> {
pub const fn new (source: &'source str, start: usize, length: usize, value: Value<'source>) -> Self {
pub const fn new (
source: &'source str, start: usize, length: usize, value: Value<'source>
) -> Self {
Self { source, start, length, value }
}
pub const fn end (&self) -> usize {
@ -248,7 +215,6 @@ impl<'source> Token<'source> {
}
pub const fn slice (&'source self) -> &'source str {
self.slice_source(self.source)
//str_range(self.source, self.start, self.end())
}
pub const fn slice_source <'range> (&'source self, source: &'range str) -> &'range str {
str_range(source, self.start, self.end())
@ -256,6 +222,9 @@ impl<'source> Token<'source> {
pub const fn slice_source_exp <'range> (&'source self, source: &'range str) -> &'range str {
str_range(source, self.start.saturating_add(1), self.end())
}
pub const fn with_value (self, value: Value<'source>) -> Self {
Self { value, ..self }
}
pub const fn value (&self) -> Value {
self.value
}
@ -272,49 +241,43 @@ impl<'source> Token<'source> {
}
}
pub const fn grow_key (self) -> Self {
let mut token = self.grow();
token.value = Key(token.slice_source(self.source));
token
let token = self.grow();
token.with_value(Key(token.slice_source(self.source)))
}
pub const fn grow_sym (self) -> Self {
let mut token = self.grow();
token.value = Sym(token.slice_source(self.source));
token
let token = self.grow();
token.with_value(Sym(token.slice_source(self.source)))
}
pub const fn grow_str (self) -> Self {
let mut token = self.grow();
token.value = Str(token.slice_source(self.source));
token
let token = self.grow();
token.with_value(Str(token.slice_source(self.source)))
}
pub const fn grow_exp (self) -> Self {
let mut token = self.grow();
let token = self.grow();
if let Exp(depth, _) = token.value {
token.value = Exp(depth, TokenIter::new(token.slice_source_exp(self.source)));
token.with_value(Exp(depth, TokenIter::new(token.slice_source_exp(self.source))))
} else {
unreachable!()
}
token
}
pub const fn grow_in (self) -> Self {
let mut token = self.grow_exp();
let token = self.grow_exp();
if let Value::Exp(depth, source) = token.value {
token.value = Value::Exp(depth.saturating_add(1), source)
token.with_value(Value::Exp(depth.saturating_add(1), source))
} else {
unreachable!()
}
token
}
pub const fn grow_out (self) -> Self {
let mut token = self.grow_exp();
let token = self.grow_exp();
if let Value::Exp(depth, source) = token.value {
if depth > 0 {
token.value = Value::Exp(depth - 1, source)
token.with_value(Value::Exp(depth - 1, source))
} else {
return self.error(Unexpected(')'))
}
} else {
unreachable!()
}
token
}
}

44
dsl/src/dsl_provide.rs Normal file
View file

@ -0,0 +1,44 @@
use crate::*;
/// Map EDN tokens to parameters of a given type for a given context
pub trait Dsl<U>: Sized {
fn take <'state, 'source> (_: &'state Self, _: &mut TokenIter<'source>) -> Perhaps<U> {
Ok(None)
}
}
/// Map EDN tokens to parameters of a given type for a given context
pub trait Context<'state, U>: Sized {
fn get <'source> (&'state self, _iter: &mut TokenIter<'source>) -> Option<U> {
None
}
}
impl<'state, T: Context<'state, U>, U> Context<'state, U> for &T {
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<U> {
(*self).get(iter)
}
}
impl<'state, T: Context<'state, U>, U> Context<'state, U> for Option<T> {
fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option<U> {
self.as_ref().map(|s|s.get(iter)).flatten()
}
}
pub trait TryFromDsl<'state, T>: Sized {
fn try_from_expr <'source: 'state> (
_state: &'state T, _iter: &mut TokenIter<'source>
) -> Option<Self> {
None
}
fn try_from_atom <'source: 'state> (
state: &'state T, value: Value<'source>
) -> Option<Self> {
if let Exp(0, mut iter) = value {
return Self::try_from_expr(state, &mut iter)
}
None
}
}

View file

@ -1,3 +1,7 @@
#![feature(adt_const_params)]
#![feature(type_alias_impl_trait)]
#![feature(impl_trait_in_fn_trait_return)]
//! [Token]s are parsed substrings with an associated [Value].
//!
//! * [ ] FIXME: Value may be [Err] which may shadow [Result::Err]
@ -31,17 +35,18 @@
//! assert_eq!(view.0.0, src);
//! assert_eq!(view.peek(), view.0.peek())
//! ```
#![feature(adt_const_params)]
#![feature(type_alias_impl_trait)]
#![feature(impl_trait_in_fn_trait_return)]
pub(crate) use self::Value::*;
pub(crate) use self::ParseError::*;
pub(crate) use ::tengri_core::*;
pub(crate) use std::fmt::Debug;
pub(crate) use konst::iter::{ConstIntoIter, IsIteratorKind};
pub(crate) use konst::string::{split_at, str_range, char_indices};
pub(crate) use std::fmt::Debug;
pub(crate) use thiserror::Error;
pub(crate) use self::Value::*;
pub(crate) use self::ParseError::*;
mod dsl; pub use self::dsl::*;
mod dsl_parse; pub use self::dsl_parse::*;
mod dsl_provide; pub use self::dsl_provide::*;
#[cfg(test)] mod test_token_iter {
use crate::*;

View file

@ -4,12 +4,13 @@ description = "UI metaframework, input layer."
version = { workspace = true }
edition = { workspace = true }
[dependencies]
tengri_dsl = { optional = true, path = "../dsl" }
[features]
dsl = [ "tengri_dsl" ]
[dependencies]
tengri_core = { path = "../core" }
tengri_dsl = { optional = true, path = "../dsl" }
[dev-dependencies]
tengri_tui = { path = "../tui" }
tengri_dsl = { path = "../dsl" }

View file

@ -1,18 +1,16 @@
#![feature(associated_type_defaults)]
pub(crate) use std::error::Error;
pub(crate) type Perhaps<T> = Result<Option<T>, Box<dyn Error>>;
#[cfg(test)] pub(crate) type Usually<T> = Result<T, Box<dyn Error>>;
#[cfg(feature = "dsl")] pub(crate) use ::tengri_dsl::*;
#[cfg(feature = "dsl")] mod input_dsl;
#[cfg(feature = "dsl")] pub use self::input_dsl::*;
pub(crate) use tengri_core::*;
mod input_macros;
mod input_command; pub use self::input_command::*;
mod input_handle; pub use self::input_handle::*;
#[cfg(test)]
#[test] fn test_stub_input () -> Usually<()> {
#[cfg(feature = "dsl")] pub(crate) use ::tengri_dsl::*;
#[cfg(feature = "dsl")] mod input_dsl;
#[cfg(feature = "dsl")] pub use self::input_dsl::*;
#[cfg(test)] #[test] fn test_stub_input () -> Usually<()> {
use crate::*;
struct TestInput(bool);
enum TestEvent { Test1 }
@ -33,8 +31,7 @@ mod input_handle; pub use self::input_handle::*;
Ok(())
}
#[cfg(all(test, feature = "dsl"))]
#[test] fn test_dsl_keymap () -> Usually<()> {
#[cfg(all(test, feature = "dsl"))] #[test] fn test_dsl_keymap () -> Usually<()> {
let keymap = SourceIter::new("");
Ok(())
}

View file

@ -4,15 +4,16 @@ description = "UI metaframework, output layer."
version = { workspace = true }
edition = { workspace = true }
[dependencies]
tengri_dsl = { optional = true, path = "../dsl" }
[features]
dsl = [ "tengri_dsl" ]
[dependencies]
tengri_core = { path = "../core" }
tengri_dsl = { optional = true, path = "../dsl" }
[dev-dependencies]
tengri = { path = "../tengri", features = [ "dsl", "tui" ] }
tengri_tui = { path = "../tui" }
tengri_dsl = { path = "../dsl" }
proptest = "^1"
proptest-derive = "^0.5.1"
proptest = { workspace = true }
proptest-derive = { workspace = true }

View file

@ -7,18 +7,13 @@ mod space; pub use self::space::*;
mod ops; pub use self::ops::*;
mod output; pub use self::output::*;
pub(crate) use tengri_core::*;
pub(crate) use std::marker::PhantomData;
pub(crate) use std::error::Error;
#[cfg(feature = "dsl")] pub(crate) use ::tengri_dsl::*;
#[cfg(feature = "dsl")] mod view;
#[cfg(feature = "dsl")] pub use self::view::*;
/// 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>>;
#[cfg(test)] use proptest_derive::Arbitrary;
#[cfg(test)] #[test] fn test_stub_output () -> Usually<()> {

View file

@ -8,7 +8,8 @@ edition = { workspace = true }
proc-macro = true
[dependencies]
syn = { version = "2", features = ["full", "extra-traits"] }
quote = { version = "1" }
proc-macro2 = { version = "1", features = ["span-locations"] }
heck = { version = "0.5" }
tengri_core = { path = "../core" }
syn = { workspace = true }
quote = { workspace = true }
proc-macro2 = { workspace = true }
heck = { workspace = true }

View file

@ -10,10 +10,7 @@ pub(crate) struct CommandMeta(Ident);
pub(crate) struct CommandImpl(ItemImpl, BTreeMap<Arc<str>, CommandArm>);
#[derive(Debug, Clone)]
struct CommandArm(Ident, Vec<FnArg>, ReturnType);
#[derive(Debug, Clone)]
struct CommandVariant(Ident, Vec<FnArg>);
struct CommandArm(Ident, Vec<FnArg>, #[allow(unused)] ReturnType);
impl Parse for CommandMeta {
fn parse (input: ParseStream) -> Result<Self> {
@ -203,25 +200,3 @@ impl CommandArm {
write_quote(quote! { Self::#variant => Self::#ident(state, #(#give_args)* #give_rest), })
}
}
impl ToTokens for CommandVariant {
fn to_tokens (&self, out: &mut TokenStream2) {
let Self(ident, args) = self;
out.append(LitStr::new(&format!("{}", ident), Span::call_site())
.token());
out.append(Group::new(Delimiter::Parenthesis, {
let mut out = TokenStream2::new();
for arg in args.iter() {
if let FnArg::Typed(PatType { ty, .. }) = arg {
out.append(LitStr::new(
&format!("{}", quote! { #ty }),
Span::call_site()
).token());
out.append(Punct::new(',', Alone));
}
}
out
}));
out.append(Punct::new(',', Alone));
}
}

View file

@ -4,7 +4,15 @@ edition = "2024"
description = "UI metaframework."
version = { workspace = true }
[features]
default = [ "input", "output", "tui" ]
input = [ "tengri_input" ]
output = [ "tengri_output" ]
tui = [ "tengri_tui" ]
dsl = [ "tengri_dsl", "tengri_input/dsl", "tengri_output/dsl", "tengri_tui/dsl" ]
[dependencies]
tengri_core = { path = "../core" }
tengri_dsl = { optional = true, path = "../dsl" }
tengri_input = { optional = true, path = "../input" }
tengri_output = { optional = true, path = "../output" }
@ -13,11 +21,4 @@ tengri_tui = { optional = true, path = "../tui" }
[dev-dependencies]
tengri_proc = { path = "../proc" }
tengri = { path = ".", features = [ "dsl" ] }
crossterm = "0.28.1"
[features]
default = [ "input", "output", "tui" ]
input = [ "tengri_input" ]
output = [ "tengri_output" ]
tui = [ "tengri_tui" ]
dsl = [ "tengri_dsl", "tengri_input/dsl", "tengri_output/dsl", "tengri_tui/dsl" ]
crossterm = { workspace = true }

View file

@ -1,3 +1,4 @@
pub use ::tengri_core::*;
#[cfg(feature="output")] pub use ::tengri_output as output;
#[cfg(feature="input")] pub use ::tengri_input as input;
#[cfg(feature="dsl")] pub use ::tengri_dsl as dsl;

View file

@ -4,25 +4,26 @@ description = "UI metaframework, Ratatui backend."
version = { workspace = true }
edition = { workspace = true }
[dependencies]
palette = { version = "0.7.6", features = [ "random" ] }
rand = "0.8.5"
crossterm = "0.28.1"
ratatui = { version = "0.29.0", features = [ "unstable-widget-ref", "underline-color" ] }
better-panic = "0.3.0"
konst = { version = "0.3.16", features = [ "rust_1_83" ] }
atomic_float = "1"
quanta = "0.12.3"
unicode-width = "0.2"
[features]
dsl = [ "tengri_dsl", "tengri_input/dsl", "tengri_output/dsl" ]
[dependencies]
tengri_core = { path = "../core" }
tengri_input = { path = "../input" }
tengri_output = { path = "../output" }
tengri_dsl = { optional = true, path = "../dsl" }
palette = { workspace = true }
rand = { workspace = true }
crossterm = { workspace = true }
ratatui = { workspace = true }
better-panic = { workspace = true }
konst = { workspace = true }
atomic_float = { workspace = true }
quanta = { workspace = true }
unicode-width = { workspace = true }
[dev-dependencies]
tengri = { path = "../tengri", features = [ "dsl" ] }
tengri_dsl = { path = "../dsl" }
tengri_proc = { path = "../proc" }
[features]
dsl = [ "tengri_dsl", "tengri_input/dsl", "tengri_output/dsl" ]

View file

@ -3,6 +3,8 @@
mod tui_engine; pub use self::tui_engine::*;
mod tui_content; pub use self::tui_content::*;
pub(crate) use ::tengri_core::*;
pub use ::tengri_input as input;
pub(crate) use ::tengri_input::*;