From 8dda576c9da991f05a73c82f1df310063e0adc7a Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sat, 10 May 2025 15:25:09 +0300 Subject: [PATCH 1/5] add tengri_core; fix errors and warnings; unify deps --- Cargo.lock | 10 +++++ Cargo.toml | 36 +++++++++++---- core/Cargo.toml | 6 +++ core/src/lib.rs | 7 +++ dsl/Cargo.toml | 10 ++--- dsl/src/{dsl.rs => dsl_parse.rs} | 75 ++++++++------------------------ dsl/src/dsl_provide.rs | 44 +++++++++++++++++++ dsl/src/lib.rs | 19 +++++--- input/Cargo.toml | 7 +-- input/src/lib.rs | 17 +++----- output/Cargo.toml | 11 ++--- output/src/lib.rs | 7 +-- proc/Cargo.toml | 9 ++-- proc/src/proc_command.rs | 27 +----------- tengri/Cargo.toml | 17 ++++---- tengri/src/lib.rs | 1 + tui/Cargo.toml | 27 ++++++------ tui/src/lib.rs | 2 + 18 files changed, 180 insertions(+), 152 deletions(-) create mode 100644 core/Cargo.toml create mode 100644 core/src/lib.rs rename dsl/src/{dsl.rs => dsl_parse.rs} (81%) create mode 100644 dsl/src/dsl_provide.rs diff --git a/Cargo.lock b/Cargo.lock index 0ba0ef4..97bf463 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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", diff --git a/Cargo.toml b/Cargo.toml index 4a6d408..a7bb2eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" } diff --git a/core/Cargo.toml b/core/Cargo.toml new file mode 100644 index 0000000..b4e9baa --- /dev/null +++ b/core/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "tengri_core" +description = "UI metaframework, core definitions." +version = { workspace = true } +edition = { workspace = true } + diff --git a/core/src/lib.rs b/core/src/lib.rs new file mode 100644 index 0000000..22288d1 --- /dev/null +++ b/core/src/lib.rs @@ -0,0 +1,7 @@ +use std::error::Error; + +/// Standard result type. +pub type Usually = Result>; + +/// Standard optional result type. +pub type Perhaps = Result, Box>; diff --git a/dsl/Cargo.toml b/dsl/Cargo.toml index 3609ada..ab0bc37 100644 --- a/dsl/Cargo.toml +++ b/dsl/Cargo.toml @@ -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" } diff --git a/dsl/src/dsl.rs b/dsl/src/dsl_parse.rs similarity index 81% rename from dsl/src/dsl.rs rename to dsl/src/dsl_parse.rs index f4eedaf..3923cd4 100644 --- a/dsl/src/dsl.rs +++ b/dsl/src/dsl_parse.rs @@ -1,5 +1,4 @@ use crate::*; -use thiserror::Error; pub type ParseResult = Result; @@ -16,41 +15,6 @@ pub type ParseResult = Result; Code(u8), } -pub trait TryFromDsl<'state, T>: Sized { - fn try_from_expr <'source: 'state> ( - _state: &'state T, _iter: &mut TokenIter<'source> - ) -> Option { - None - } - fn try_from_atom <'source: 'state> ( - state: &'state T, value: Value<'source> - ) -> Option { - 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 { - None - } -} - -impl<'state, T: Context<'state, U>, U> Context<'state, U> for &T { - fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option { - (*self).get(iter) - } -} - -impl<'state, T: Context<'state, U>, U> Context<'state, U> for Option { - fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option { - 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 { } 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 } } diff --git a/dsl/src/dsl_provide.rs b/dsl/src/dsl_provide.rs new file mode 100644 index 0000000..209b37c --- /dev/null +++ b/dsl/src/dsl_provide.rs @@ -0,0 +1,44 @@ +use crate::*; + +/// Map EDN tokens to parameters of a given type for a given context +pub trait Dsl: Sized { + fn take <'state, 'source> (_: &'state Self, _: &mut TokenIter<'source>) -> Perhaps { + 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 { + None + } +} + +impl<'state, T: Context<'state, U>, U> Context<'state, U> for &T { + fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option { + (*self).get(iter) + } +} + +impl<'state, T: Context<'state, U>, U> Context<'state, U> for Option { + fn get <'source> (&'state self, iter: &mut TokenIter<'source>) -> Option { + 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 { + None + } + fn try_from_atom <'source: 'state> ( + state: &'state T, value: Value<'source> + ) -> Option { + if let Exp(0, mut iter) = value { + return Self::try_from_expr(state, &mut iter) + } + None + } +} + diff --git a/dsl/src/lib.rs b/dsl/src/lib.rs index c685572..c72ff23 100644 --- a/dsl/src/lib.rs +++ b/dsl/src/lib.rs @@ -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::*; diff --git a/input/Cargo.toml b/input/Cargo.toml index 3b7772f..d3bf1ec 100644 --- a/input/Cargo.toml +++ b/input/Cargo.toml @@ -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" } diff --git a/input/src/lib.rs b/input/src/lib.rs index c4c230d..21035fe 100644 --- a/input/src/lib.rs +++ b/input/src/lib.rs @@ -1,18 +1,16 @@ #![feature(associated_type_defaults)] -pub(crate) use std::error::Error; -pub(crate) type Perhaps = Result, Box>; -#[cfg(test)] pub(crate) type Usually = Result>; -#[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(()) } diff --git a/output/Cargo.toml b/output/Cargo.toml index 2505df5..5172710 100644 --- a/output/Cargo.toml +++ b/output/Cargo.toml @@ -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 } diff --git a/output/src/lib.rs b/output/src/lib.rs index 45bf90a..2b12b04 100644 --- a/output/src/lib.rs +++ b/output/src/lib.rs @@ -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 = Result>; -/// Standard optional result type. -pub type Perhaps = Result, Box>; - #[cfg(test)] use proptest_derive::Arbitrary; #[cfg(test)] #[test] fn test_stub_output () -> Usually<()> { diff --git a/proc/Cargo.toml b/proc/Cargo.toml index 6001947..d7c3a9a 100644 --- a/proc/Cargo.toml +++ b/proc/Cargo.toml @@ -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 } diff --git a/proc/src/proc_command.rs b/proc/src/proc_command.rs index cc5b134..502041f 100644 --- a/proc/src/proc_command.rs +++ b/proc/src/proc_command.rs @@ -10,10 +10,7 @@ pub(crate) struct CommandMeta(Ident); pub(crate) struct CommandImpl(ItemImpl, BTreeMap, CommandArm>); #[derive(Debug, Clone)] -struct CommandArm(Ident, Vec, ReturnType); - -#[derive(Debug, Clone)] -struct CommandVariant(Ident, Vec); +struct CommandArm(Ident, Vec, #[allow(unused)] ReturnType); impl Parse for CommandMeta { fn parse (input: ParseStream) -> Result { @@ -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)); - } -} diff --git a/tengri/Cargo.toml b/tengri/Cargo.toml index 23e87f8..cd87dfc 100644 --- a/tengri/Cargo.toml +++ b/tengri/Cargo.toml @@ -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 } diff --git a/tengri/src/lib.rs b/tengri/src/lib.rs index 53850cd..5fd2870 100644 --- a/tengri/src/lib.rs +++ b/tengri/src/lib.rs @@ -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; diff --git a/tui/Cargo.toml b/tui/Cargo.toml index a9eb4d9..5fe3f34 100644 --- a/tui/Cargo.toml +++ b/tui/Cargo.toml @@ -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" ] diff --git a/tui/src/lib.rs b/tui/src/lib.rs index 8e98c58..01eb7d9 100644 --- a/tui/src/lib.rs +++ b/tui/src/lib.rs @@ -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::*; From f18e01c220e978ef2d011cc4c7c6de4a6462b792 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sat, 10 May 2025 15:28:42 +0300 Subject: [PATCH 2/5] partially fix tests and examples --- tengri/src/lib.rs | 36 ++++++++++++++++++------------------ tui/examples/tui.rs | 4 ++-- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/tengri/src/lib.rs b/tengri/src/lib.rs index 5fd2870..25d7b27 100644 --- a/tengri/src/lib.rs +++ b/tengri/src/lib.rs @@ -5,8 +5,7 @@ pub use ::tengri_core::*; #[cfg(feature="tui")] pub use ::tengri_tui as tui; #[cfg(test)] extern crate tengri_proc; -#[cfg(test)] #[test] fn test_subcommand () -> crate::output::Usually<()> { - use crate::output::Perhaps; +#[cfg(test)] #[test] fn test_subcommand () -> Usually<()> { use crate::input::{Command, InputMap, KeyMap, Handle, handle}; use crate::dsl::{TryFromDsl, TokenIter}; use crate::tui::TuiIn; @@ -81,20 +80,21 @@ pub use ::tengri_core::*; Ok(()) } -#[cfg(test)] #[test] fn test_dsl_context () { - use crate::dsl::Value; +//FIXME: +//#[cfg(test)] #[test] fn test_dsl_context () { + //use crate::dsl::{Context, Value}; - struct Test; - #[tengri_proc::expose] - impl Test { - fn some_bool (&self) -> bool { - true - } - } - assert_eq!(Test.get(&Value::Sym(":false")), Some(false)); - assert_eq!(Test.get(&Value::Sym(":true")), Some(true)); - assert_eq!(Test.get(&Value::Sym(":some-bool")), Some(true)); - assert_eq!(Test.get(&Value::Sym(":missing-bool")), None); - assert_eq!(Test.get(&Value::Num(0)), Some(false)); - assert_eq!(Test.get(&Value::Num(1)), Some(true)); -} + //struct Test; + //#[tengri_proc::expose] + //impl Test { + //fn some_bool (&self) -> bool { + //true + //} + //} + //assert_eq!(Context::get(&Test, &Value::Sym(":false")), Some(false)); + //assert_eq!(Context::get(&Test, &Value::Sym(":true")), Some(true)); + //assert_eq!(Context::get(&Test, &Value::Sym(":some-bool")), Some(true)); + //assert_eq!(Context::get(&Test, &Value::Sym(":missing-bool")), None); + //assert_eq!(Context::get(&Test, &Value::Num(0)), Some(false)); + //assert_eq!(Context::get(&Test, &Value::Num(1)), Some(true)); +//} diff --git a/tui/examples/tui.rs b/tui/examples/tui.rs index 0d3ef75..066ab20 100644 --- a/tui/examples/tui.rs +++ b/tui/examples/tui.rs @@ -1,4 +1,4 @@ -use tengri::{self, input::*, output::*, tui::*, dsl::*}; +use tengri::{self, Usually, Perhaps, input::*, output::*, tui::*, dsl::*}; use std::sync::{Arc, RwLock}; use crossterm::event::{*, KeyCode::*}; use crate::ratatui::style::Color; @@ -70,7 +70,7 @@ view!(TuiOut: |self: Example|{ let heading = format!("Example {}/{} in {:?}", index, EXAMPLES.len(), &wh); let title = Tui::bg(Color::Rgb(60, 10, 10), Push::y(1, Align::n(heading))); let code = Tui::bg(Color::Rgb(10, 60, 10), Push::y(2, Align::n(format!("{}", src)))); - let content = Tui::bg(Color::Rgb(10, 10, 60), View(self, SourceIter::new(src))); + let content = Tui::bg(Color::Rgb(10, 10, 60), View(self, TokenIter::new(src))); self.1.of(Bsp::s(title, Bsp::n(""/*code*/, content))) }; { ":title" => Tui::bg(Color::Rgb(60, 10, 10), Push::y(1, Align::n(format!("Example {}/{}:", self.0 + 1, EXAMPLES.len())))).boxed(), From ed772b9872572c39dc4afef61729a2ee068ec3a0 Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sat, 10 May 2025 15:49:33 +0300 Subject: [PATCH 3/5] dsl: extract dsl_error; ParseError -> DslError --- dsl/src/dsl_error.rs | 16 ++++++++++++++++ dsl/src/dsl_parse.rs | 23 ++++------------------- dsl/src/dsl_provide.rs | 11 +++++++++++ dsl/src/lib.rs | 5 +++-- 4 files changed, 34 insertions(+), 21 deletions(-) create mode 100644 dsl/src/dsl_error.rs diff --git a/dsl/src/dsl_error.rs b/dsl/src/dsl_error.rs new file mode 100644 index 0000000..ffb53fd --- /dev/null +++ b/dsl/src/dsl_error.rs @@ -0,0 +1,16 @@ +use crate::*; + +pub type DslResult = Result; + +#[derive(Error, Debug, Copy, Clone, PartialEq)] 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), + #[error("parse failed: error #{0}")] + Code(u8), +} diff --git a/dsl/src/dsl_parse.rs b/dsl/src/dsl_parse.rs index 3923cd4..ee06792 100644 --- a/dsl/src/dsl_parse.rs +++ b/dsl/src/dsl_parse.rs @@ -1,20 +1,5 @@ use crate::*; -pub type ParseResult = Result; - -#[derive(Error, Debug, Copy, Clone, PartialEq)] pub enum ParseError { - #[error("parse failed: not implemented")] - Unimplemented, - #[error("parse failed: empty")] - Empty, - #[error("parse failed: incomplete")] - Incomplete, - #[error("parse failed: unexpected character '{0}'")] - Unexpected(char), - #[error("parse failed: error #{0}")] - Code(u8), -} - /// Implement the const iterator pattern. #[macro_export] macro_rules! const_iter { ($(<$l:lifetime>)?|$self:ident: $Struct:ty| => $Item:ty => $expr:expr) => { @@ -170,7 +155,7 @@ pub const fn peek_src <'a> (source: &'a str) -> Option> { } } -pub const fn to_number (digits: &str) -> Result { +pub const fn to_number (digits: &str) -> DslResult { let mut value = 0; iterate!(char_indices(digits) => (_, c) => match to_digit(c) { Ok(digit) => value = 10 * value + digit, @@ -179,7 +164,7 @@ pub const fn to_number (digits: &str) -> Result { Ok(value) } -pub const fn to_digit (c: char) -> Result { +pub const fn to_digit (c: char) -> DslResult { Ok(match c { '0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, '6' => 6, '7' => 7, '8' => 8, '9' => 9, @@ -196,7 +181,7 @@ pub const fn to_digit (c: char) -> Result { #[derive(Debug, Copy, Clone, Default, PartialEq)] pub enum Value<'source> { #[default] Nil, - Err(ParseError), + Err(DslError), Num(usize), Sym(&'source str), Key(&'source str), @@ -228,7 +213,7 @@ impl<'source> Token<'source> { pub const fn value (&self) -> Value { self.value } - pub const fn error (self, error: ParseError) -> Self { + pub const fn error (self, error: DslError) -> Self { Self { value: Value::Err(error), ..self } } pub const fn grow (self) -> Self { diff --git a/dsl/src/dsl_provide.rs b/dsl/src/dsl_provide.rs index 209b37c..c22e5d6 100644 --- a/dsl/src/dsl_provide.rs +++ b/dsl/src/dsl_provide.rs @@ -1,10 +1,21 @@ use crate::*; /// Map EDN tokens to parameters of a given type for a given context +/// TODO: Replace both [Context] and [TryFromDsl] with this trait +/// which returns a [Result]. pub trait Dsl: Sized { fn take <'state, 'source> (_: &'state Self, _: &mut TokenIter<'source>) -> Perhaps { Ok(None) } + fn take_or_fail <'state, 'source> ( + state: &'state Self, iter: &mut TokenIter<'source> + ) -> Usually { + if let Some(value) = Self::take(state, iter)? { + Ok(value) + } else { + Result::Err("not found".into()) // TODO add info and error type + } + } } /// Map EDN tokens to parameters of a given type for a given context diff --git a/dsl/src/lib.rs b/dsl/src/lib.rs index c72ff23..9c9b44e 100644 --- a/dsl/src/lib.rs +++ b/dsl/src/lib.rs @@ -43,8 +43,9 @@ pub(crate) use konst::iter::{ConstIntoIter, IsIteratorKind}; pub(crate) use konst::string::{split_at, str_range, char_indices}; pub(crate) use thiserror::Error; pub(crate) use self::Value::*; -pub(crate) use self::ParseError::*; +pub(crate) use self::DslError::*; +mod dsl_error; pub use self::dsl_error::*; mod dsl_parse; pub use self::dsl_parse::*; mod dsl_provide; pub use self::dsl_provide::*; @@ -148,7 +149,7 @@ mod dsl_provide; pub use self::dsl_provide::*; Ok(()) } -//#[cfg(test)] #[test] fn test_examples () -> Result<(), ParseError> { +//#[cfg(test)] #[test] fn test_examples () -> Result<(), DslError> { //// Let's pretend to render some view. //let source = include_str!("../../tek/src/view_arranger.edn"); //// The token iterator allows you to get the tokens represented by the source text. From 18687365975c008e774707a3f42a7836794839db Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sat, 10 May 2025 15:49:46 +0300 Subject: [PATCH 4/5] proc: log parse info on give_err --- proc/src/proc_command.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/proc/src/proc_command.rs b/proc/src/proc_command.rs index 502041f..bfe9246 100644 --- a/proc/src/proc_command.rs +++ b/proc/src/proc_command.rs @@ -70,7 +70,8 @@ impl ToTokens for CommandDef { state: &'state #target, iter: &mut ::tengri::dsl::TokenIter<'source> ) -> Option { let mut iter = iter.clone(); - match iter.next() { + let token = iter.next(); + match token { #(#matchers)* _ => None } @@ -154,10 +155,12 @@ impl CommandArm { for (arg, ty) in self.args() { //let take_err = LitStr::new(&format!("{}: missing argument \"{}\" ({})", //quote!{#ident}, quote!{#arg}, quote!{#ty}), Span::call_site()); - let give_err = LitStr::new(&format!("{}: missing value for \"{}\" ({})", - quote!{#ident}, quote!{#arg}, quote!{#ty}), Span::call_site()); + let give_err = format!("{}: missing value for \"{}\" ({}): {{:#?}}", + quote!{#ident}, quote!{#arg}, quote!{#ty}); + let give_err = LitStr::new(&give_err, Span::call_site()); write_quote_to(&mut out, quote! { - #arg: ::tengri::dsl::Context::get(state, &mut iter).expect(#give_err), + #arg: ::tengri::dsl::Context::get(state, &mut iter) + .unwrap_or_else(||panic!(#give_err, token)), }); } out From faecc2c304ad2c0ebd78d21170a02c172fd356bf Mon Sep 17 00:00:00 2001 From: unspeaker Date: Sat, 10 May 2025 15:50:07 +0300 Subject: [PATCH 5/5] update dependencies --- Cargo.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 97bf463..6c5c30d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -46,9 +46,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.74" +version = "0.3.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" dependencies = [ "addr2line", "cfg-if", @@ -286,9 +286,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "libc", @@ -757,9 +757,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.11" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" +checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" dependencies = [ "bitflags", ] @@ -834,9 +834,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "signal-hook" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" dependencies = [ "libc", "signal-hook-registry", @@ -926,7 +926,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" dependencies = [ "fastrand", - "getrandom 0.3.2", + "getrandom 0.3.3", "once_cell", "rustix 1.0.7", "windows-sys 0.59.0",