diff --git a/Justfile b/Justfile index af61a41..e17aef3 100644 --- a/Justfile +++ b/Justfile @@ -1,6 +1,8 @@ covfig := "CARGO_INCREMENTAL=0 RUSTFLAGS='-Cinstrument-coverage' RUSTDOCFLAGS='-Cinstrument-coverage' LLVM_PROFILE_FILE='cov/cargo-test-%p-%m.profraw'" grcov-binary := "--binary-path ./target/coverage/deps/" grcov-ignore := "--ignore-not-existing --ignore '../*' --ignore \"/*\" --ignore 'target/*'" +bacon: + {{covfig}} bacon -s cov: {{covfig}} time cargo test -j4 --workspace --profile coverage rm -rf target/coverage/html || true diff --git a/dsl/src/dsl_cst.rs b/dsl/src/dsl_cst.rs index 7757a70..cfae7e2 100644 --- a/dsl/src/dsl_cst.rs +++ b/dsl/src/dsl_cst.rs @@ -3,6 +3,10 @@ use crate::*; /// CST stores strings as source references and expressions as new [SourceIter] instances. pub type CstValue<'source> = Value<&'source str, SourceIter<'source>>; +/// Token sharing memory with source reference. +#[derive(Debug, Copy, Clone, Default, PartialEq)] +pub struct CstToken<'source>(pub CstValue<'source>, pub CstMeta<'source>); + /// Reference to the source slice. #[derive(Debug, Copy, Clone, Default, PartialEq)] pub struct CstMeta<'source> { pub source: &'source str, @@ -10,10 +14,6 @@ pub type CstValue<'source> = Value<&'source str, SourceIter<'source>>; pub length: usize, } -/// Token sharing memory with source reference. -#[derive(Debug, Copy, Clone, Default, PartialEq)] -pub struct CstToken<'source>(pub CstValue<'source>, pub CstMeta<'source>); - impl<'source> CstToken<'source> { pub const fn new ( source: &'source str, start: usize, length: usize, value: CstValue<'source> diff --git a/dsl/src/dsl_iter.rs b/dsl/src/dsl_iter.rs index 07cfdd7..2e0e47a 100644 --- a/dsl/src/dsl_iter.rs +++ b/dsl/src/dsl_iter.rs @@ -7,25 +7,32 @@ pub trait DslIter { fn rest (self) -> Vec; } -#[derive(Debug, Clone, Default, PartialEq)] -pub struct AstIter(std::collections::VecDeque); - -impl DslIter for AstIter { - type Token = Ast; - fn peek (&self) -> Option { - self.0.get(0).cloned() - } - fn next (&mut self) -> Option { - self.0.pop_front() - } - fn rest (self) -> Vec { - self.0.into() +/// Implement the const iterator pattern. +#[macro_export] macro_rules! const_iter { + ($(<$l:lifetime>)?|$self:ident: $Struct:ty| => $Item:ty => $expr:expr) => { + impl$(<$l>)? Iterator for $Struct { + type Item = $Item; + fn next (&mut $self) -> Option<$Item> { $expr } + } + impl$(<$l>)? ConstIntoIter for $Struct { + type Kind = IsIteratorKind; + type Item = $Item; + type IntoIter = Self; + } } } -impl<'source> From> for AstIter { - fn from (source: SourceIter<'source>) -> Self { - Self(source.map(Into::into).collect()) +/// Owns a reference to the source text. +/// [SourceConstIter::next] emits subsequent pairs of: +/// * a [CstToken] and +/// * the source text remaining +/// * [ ] TODO: maybe [SourceConstIter::next] should wrap the remaining source in `Self` ? +#[derive(Copy, Clone, Debug, Default, PartialEq)] +pub struct SourceConstIter<'source>(pub &'source str); + +impl<'source> From> for SourceIter<'source> { + fn from (source: SourceConstIter<'source>) -> Self{ + Self(source) } } @@ -71,35 +78,6 @@ impl<'source> Into> for SourceIter<'source> { } } -/// Implement the const iterator pattern. -#[macro_export] macro_rules! const_iter { - ($(<$l:lifetime>)?|$self:ident: $Struct:ty| => $Item:ty => $expr:expr) => { - impl$(<$l>)? Iterator for $Struct { - type Item = $Item; - fn next (&mut $self) -> Option<$Item> { $expr } - } - impl$(<$l>)? ConstIntoIter for $Struct { - type Kind = IsIteratorKind; - type Item = $Item; - type IntoIter = Self; - } - } -} - -/// Owns a reference to the source text. -/// [SourceConstIter::next] emits subsequent pairs of: -/// * a [CstToken] and -/// * the source text remaining -/// * [ ] TODO: maybe [SourceConstIter::next] should wrap the remaining source in `Self` ? -#[derive(Copy, Clone, Debug, Default, PartialEq)] -pub struct SourceConstIter<'source>(pub &'source str); - -impl<'source> From> for SourceIter<'source> { - fn from (source: SourceConstIter<'source>) -> Self{ - Self(source) - } -} - impl<'source> From<&'source str> for SourceConstIter<'source> { fn from (source: &'source str) -> Self{ Self::new(source) @@ -128,3 +106,25 @@ impl<'source> SourceConstIter<'source> { } const_iter!(<'source>|self: SourceConstIter<'source>| => CstToken<'source> => self.next_mut().map(|(result, _)|result)); + +#[derive(Debug, Clone, Default, PartialEq)] +pub struct AstIter(std::collections::VecDeque); + +impl DslIter for AstIter { + type Token = Ast; + fn peek (&self) -> Option { + self.0.get(0).cloned() + } + fn next (&mut self) -> Option { + self.0.pop_front() + } + fn rest (self) -> Vec { + self.0.into() + } +} + +impl<'source> From> for AstIter { + fn from (source: SourceIter<'source>) -> Self { + Self(source.map(Into::into).collect()) + } +} diff --git a/dsl/src/dsl_test.rs b/dsl/src/dsl_test.rs index 4f7c4b2..2f5ce15 100644 --- a/dsl/src/dsl_test.rs +++ b/dsl/src/dsl_test.rs @@ -1,21 +1,21 @@ +use crate::*; + #[cfg(test)] mod test_token_iter { use crate::*; //use proptest::prelude::*; #[test] fn test_iters () { let mut iter = crate::SourceIter::new(&":foo :bar"); let _ = iter.next(); - let mut iter = crate::TokenIter::new(&":foo :bar"); - let _ = iter.next(); } #[test] const fn test_const_iters () { - let mut iter = crate::SourceIter::new(&":foo :bar"); + let iter = crate::SourceConstIter::new(&":foo :bar"); let _ = iter.next(); } #[test] fn test_num () { - let digit = to_digit('0'); - let digit = to_digit('x'); - let number = to_number(&"123"); - let number = to_number(&"12asdf3"); + let _digit = to_digit('0'); + let _digit = to_digit('x'); + let _number = to_number(&"123"); + let _number = to_number(&"12asdf3"); } //proptest! { //#[test] fn proptest_source_iter ( @@ -33,67 +33,54 @@ //} } -#[cfg(test)] mod test_token_prop { - use proptest::prelude::*; - proptest! { - #[test] fn test_token_prop ( - source in "\\PC*", - start in usize::MIN..usize::MAX, - length in usize::MIN..usize::MAX, - ) { - let token = crate::Token { - source: &source, - start, - length, - value: crate::Value::Nil - }; - let _ = token.slice(); - } - } -} +//#[cfg(test)] mod test_token_prop { + //use crate::{CstToken, CstMeta, Value::*}; + //use proptest::prelude::*; + //proptest! { + //#[test] fn test_token_prop ( + //source in "\\PC*", + //start in usize::MIN..usize::MAX, + //length in usize::MIN..usize::MAX, + //) { + //let token = CstToken(Nil, CstMeta { source: &source, start, length }); + //let _ = token.slice(); + //} + //} +//} #[cfg(test)] #[test] fn test_token () -> Result<(), Box> { + use crate::Value::*; let source = ":f00"; - let mut token = Token { source, start: 0, length: 1, value: Sym(":") }; + let mut token = CstToken(Sym(":"), CstMeta { source, start: 0, length: 1 }); token = token.grow_sym(); - assert_eq!(token, Token { source, start: 0, length: 2, value: Sym(":f") }); + assert_eq!(token, CstToken(Sym(":f"), CstMeta { source, start: 0, length: 2, })); token = token.grow_sym(); - assert_eq!(token, Token { source, start: 0, length: 3, value: Sym(":f0") }); + assert_eq!(token, CstToken(Sym(":f0"), CstMeta { source, start: 0, length: 3, })); token = token.grow_sym(); - assert_eq!(token, Token { source, start: 0, length: 4, value: Sym(":f00") }); + assert_eq!(token, CstToken(Sym(":f00"), CstMeta { source, start: 0, length: 4, })); - let src = ""; - assert_eq!(None, SourceIter(src).next()); - - let src = " \n \r \t "; - assert_eq!(None, SourceIter(src).next()); - - let src = "7"; - assert_eq!(Num(7), SourceIter(src).next().unwrap().0.value); - - let src = " 100 "; - assert_eq!(Num(100), SourceIter(src).next().unwrap().0.value); - - let src = " 9a "; - assert_eq!(Err(Unexpected('a')), SourceIter(src).next().unwrap().0.value); - - let src = " :123foo "; - assert_eq!(Sym(":123foo"), SourceIter(src).next().unwrap().0.value); - - let src = " \r\r\r\n\n\n@bar456\t\t\t\t\t\t"; - assert_eq!(Sym("@bar456"), SourceIter(src).next().unwrap().0.value); - - let src = "foo123"; - assert_eq!(Key("foo123"), SourceIter(src).next().unwrap().0.value); - - let src = "foo/bar"; - assert_eq!(Key("foo/bar"), SourceIter(src).next().unwrap().0.value); - - let src = "\"foo/bar\""; - assert_eq!(Str("foo/bar"), SourceIter(src).next().unwrap().0.value); - - let src = " \"foo/bar\" "; - assert_eq!(Str("foo/bar"), SourceIter(src).next().unwrap().0.value); + assert_eq!(None, + SourceIter::new("").next()); + assert_eq!(None, + SourceIter::new(" \n \r \t ").next()); + assert_eq!(&Num(7), + SourceIter::new("7").next().unwrap().0.value()); + assert_eq!(&Num(100), + SourceIter::new(" 100 ").next().unwrap().0.value()); + assert_eq!(&Err(Unexpected('a')), + SourceIter::new(" 9a ").next().unwrap().0.value()); + assert_eq!(&Sym(":123foo"), + SourceIter::new(" :123foo ").next().unwrap().0.value()); + assert_eq!(&Sym("@bar456"), + SourceIter::new(" \r\r\r\n\n\n@bar456\t\t\t\t\t\t").next().unwrap().0.value()); + assert_eq!(&Key("foo123"), + SourceIter::new("foo123").next().unwrap().0.value()); + assert_eq!(&Key("foo/bar"), + SourceIter::new("foo/bar").next().unwrap().0.value()); + assert_eq!(&Str("foo/bar"), + SourceIter::new("\"foo/bar\"").next().unwrap().0.value()); + assert_eq!(&Str("foo/bar"), + SourceIter::new(" \"foo/bar\" ").next().unwrap().0.value()); Ok(()) } @@ -108,7 +95,7 @@ //let mut expr = view.peek(); //assert_eq!(view.0.0, source); //assert_eq!(expr, Some(Token { - //source, start: 0, length: source.len() - 1, value: Exp(0, SourceIter(&source[1..])) + //source, start: 0, length: source.len() - 1, value: Exp(0, SourceIter::new(&source[1..])) //})); ////panic!("{view:?}"); ////panic!("{:#?}", expr); diff --git a/input/src/lib.rs b/input/src/lib.rs index 4f27011..1324e15 100644 --- a/input/src/lib.rs +++ b/input/src/lib.rs @@ -33,6 +33,6 @@ mod input_handle; pub use self::input_handle::*; } #[cfg(all(test, feature = "dsl"))] #[test] fn test_dsl_keymap () -> Usually<()> { - let keymap = SourceIter::new(""); + let _keymap = SourceIter::new(""); Ok(()) } diff --git a/output/src/lib.rs b/output/src/lib.rs index 30e8fff..5407df5 100644 --- a/output/src/lib.rs +++ b/output/src/lib.rs @@ -16,3 +16,4 @@ mod ops; pub use self::ops::*; mod output; pub use self::output::*; #[cfg(test)] mod test; +#[cfg(test)] pub use proptest_derive::Arbitrary; diff --git a/output/src/test.rs b/output/src/test.rs index 517aa64..d324664 100644 --- a/output/src/test.rs +++ b/output/src/test.rs @@ -1,5 +1,5 @@ -use crate::*; -use proptest_derive::Arbitrary; +use crate::{*, Direction::*}; +//use proptest_derive::Arbitrary; use proptest::{prelude::*, option::of}; proptest! { @@ -86,7 +86,7 @@ macro_rules! test_op_transform { 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)), - (Some(y), None) => Some($Op::y(y, content)), + (None, Some(y)) => Some($Op::y(y, content)), _ => None } { assert_eq!(Content::layout(&op, [x, y, w, h]), @@ -142,7 +142,7 @@ proptest! { fn area_mut (&mut self) -> &mut [u16;4] { &mut self.0 } - fn place (&mut self, _: [u16;4], _: &impl Render) { + fn place + ?Sized> (&mut self, _: [u16;4], _: &T) { () } } @@ -162,9 +162,9 @@ proptest! { #[test] fn test_iter_map () { struct Foo; impl Content for Foo {} - fn make_map + Send + Sync> (data: &Vec) -> impl Content { - Map::new(||data.iter(), |foo, index|{}) + fn _make_map + Send + Sync> (data: &Vec) -> impl Content { + Map::new(||data.iter(), |_foo, _index|{}) } - let data = vec![Foo, Foo, Foo]; + let _data = vec![Foo, Foo, Foo]; //let map = make_map(&data); } diff --git a/proc/src/lib.rs b/proc/src/lib.rs index 02ba5de..bc39ee5 100644 --- a/proc/src/lib.rs +++ b/proc/src/lib.rs @@ -76,7 +76,7 @@ pub(crate) fn write_quote_to (out: &mut TokenStream2, quote: TokenStream2) { assert_eq!(x.output, output); // TODO - let x: crate::proc_view::ViewImpl = pq! { + let _x: crate::proc_view::ViewImpl = pq! { impl Foo { /// docstring1 #[tengri::view(":view1")] #[bar] fn a_view () {} @@ -86,7 +86,7 @@ pub(crate) fn write_quote_to (out: &mut TokenStream2, quote: TokenStream2) { #[baz] fn is_not_view () {} } }; - let expected_target: Ident = pq! { Foo }; + let _expected_target: Ident = pq! { Foo }; //assert_eq!(x.target, expected_target); //assert_eq!(x.items.len(), 2); //assert_eq!(x.items[0].item, pq! { diff --git a/proc/src/proc_command.rs b/proc/src/proc_command.rs index 340ca1f..078e794 100644 --- a/proc/src/proc_command.rs +++ b/proc/src/proc_command.rs @@ -84,7 +84,7 @@ impl ToTokens for CommandDef { let mut out = TokenStream2::new(); for (arg, _ty) in arm.args() { write_quote_to(&mut out, quote! { - #arg: Take::take_or_fail(self, words)?, + #arg: Dsl::try_provide(self, words)?, }); } out @@ -149,8 +149,8 @@ impl ToTokens for CommandDef { } } /// Generated by [tengri_proc::command]. - impl ::tengri::dsl::Take<#state> for #command_enum { - fn take (state: &#state, mut words: ::tengri::dsl::Cst) -> Perhaps { + impl ::tengri::dsl::Dsl<#state> for #command_enum { + fn try_provide (state: &#state, mut words: ::tengri::dsl::Ast) -> Perhaps { let mut words = words.clone(); let token = words.next(); todo!()//Ok(match token { #(#matchers)* _ => None }) diff --git a/proc/src/proc_expose.rs b/proc/src/proc_expose.rs index 873b639..2b64d1a 100644 --- a/proc/src/proc_expose.rs +++ b/proc/src/proc_expose.rs @@ -85,8 +85,8 @@ impl ToTokens for ExposeImpl { }); write_quote_to(out, quote! { /// Generated by [tengri_proc::expose]. - impl ::tengri::dsl::Take<#state> for #t { - fn take (state: &#state, mut words: ::tengri::dsl::Cst) -> Perhaps { + impl ::tengri::dsl::Dsl<#state> for #t { + fn try_provide (state: &#state, mut words: ::tengri::dsl::Ast) -> Perhaps { Ok(Some(match words.next().map(|x|x.value) { #predefined #(#values)* diff --git a/proc/src/proc_view.rs b/proc/src/proc_view.rs index b4ea607..ef5aa49 100644 --- a/proc/src/proc_view.rs +++ b/proc/src/proc_view.rs @@ -45,7 +45,7 @@ impl ToTokens for ViewDef { // that operate over constants and symbols. let builtin = builtins_with_boxes_output(quote! { #output }).map(|builtin|quote! { ::tengri::dsl::Value::Exp(_, expr) => return Ok(Some( - #builtin::take_or_fail(state, expr, ||"failed to load builtin")?.boxed() + #builtin::try_provide(state, expr, ||"failed to load builtin")?.boxed() )), }); // Symbols are handled by user-taked functions @@ -63,11 +63,8 @@ impl ToTokens for ViewDef { /// Makes [#self_ty] able to construct the [Render]able /// which might correspond to a given [TokenStream], /// while taking [#self_ty]'s state into consideration. - impl<'source, 'state: 'source> - Take<'state, 'source, #self_ty> - for Box + 'state> - { - fn take (state: &'state #self_ty, mut words: Cst<'source>) -> Perhaps { + impl<'state> ::tengri::dsl::Dsl + 'state>> for #self_ty { + fn try_provide (state: &'state #self_ty, mut words: ::tengri::dsl::Ast) -> Perhaps + 'state>> { Ok(if let Some(::tengri::dsl::Token { value, .. }) = words.peek() { match value { #(#builtin)* #(#exposed)* _ => None } } else { diff --git a/tengri/src/lib.rs b/tengri/src/lib.rs index d451e70..972a702 100644 --- a/tengri/src/lib.rs +++ b/tengri/src/lib.rs @@ -5,96 +5,4 @@ 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 () -> Usually<()> { - use crate::input::{Command, InputMap, KeyMap, Handle, handle}; - use crate::dsl::TokenIter; - use crate::tui::TuiIn; - use crossterm::event::{Event, KeyEvent, KeyCode, KeyModifiers, KeyEventKind, KeyEventState}; - //use crate::input::*; - //use crate::dsl::*; - struct Test { - keys: InputMap<'static, Test, TestCommand, TuiIn, TokenIter<'static>> - } - handle!(TuiIn: |self: Test, input|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 { - Ok(None) - } - fn do_thing_arg (state: &mut Test, arg: usize) -> Perhaps { - Ok(None) - } - fn do_sub (state: &mut Test, command: TestSubcommand) -> Perhaps { - Ok(command.execute(state)?.map(|command|Self::DoSub { command })) - } - } - #[tengri_proc::command(Test)] impl TestSubcommand { - fn do_other_thing (state: &mut Test) -> Perhaps { - Ok(None) - } - fn do_other_thing_arg (state: &mut Test, arg: usize) -> Perhaps { - Ok(None) - } - } - let mut test = Test { - keys: InputMap::new(" - (@a do-thing) - (@b do-thing-arg 0) - (@c do-sub do-other-thing) - (@d do-sub do-other-thing-arg 0) - ".into()) - }; - 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)); -//} +#[cfg(test)] mod test; diff --git a/tengri/src/test.rs b/tengri/src/test.rs new file mode 100644 index 0000000..817c11b --- /dev/null +++ b/tengri/src/test.rs @@ -0,0 +1,97 @@ +use crate::*; + +#[test] fn test_subcommand () -> Usually<()> { + use crate::input::{Command, Handle, handle}; + //use crate::dsl::TokenIter; + use crate::tui::TuiIn; + use crossterm::event::{Event, KeyEvent, KeyCode, KeyModifiers, KeyEventKind, KeyEventState}; + //use crate::input::*; + //use crate::dsl::*; + struct Test { + //keys: InputMap<'static, Test, TestCommand, TuiIn, TokenIter<'static>> + } + handle!(TuiIn: |self: Test, input|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 { + Ok(None) + } + fn do_thing_arg (_state: &mut Test, _arg: usize) -> Perhaps { + Ok(None) + } + fn do_sub (state: &mut Test, command: TestSubcommand) -> Perhaps { + Ok(command.execute(state)?.map(|command|Self::DoSub { command })) + } + } + #[tengri_proc::command(Test)] + impl TestSubcommand { + fn do_other_thing (_state: &mut Test) -> Perhaps { + Ok(None) + } + fn do_other_thing_arg (_state: &mut Test, _arg: usize) -> Perhaps { + Ok(None) + } + } + let mut test = Test { + keys: InputMap::new(" + (@a do-thing) + (@b do-thing-arg 0) + (@c do-sub do-other-thing) + (@d do-sub do-other-thing-arg 0) + ".into()) + }; + 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)); +//} diff --git a/tui/examples/edn01.edn b/tui/examples/edn/edn01.edn similarity index 100% rename from tui/examples/edn01.edn rename to tui/examples/edn/edn01.edn diff --git a/tui/examples/edn02.edn b/tui/examples/edn/edn02.edn similarity index 100% rename from tui/examples/edn02.edn rename to tui/examples/edn/edn02.edn diff --git a/tui/examples/edn03.edn b/tui/examples/edn/edn03.edn similarity index 100% rename from tui/examples/edn03.edn rename to tui/examples/edn/edn03.edn diff --git a/tui/examples/edn04.edn b/tui/examples/edn/edn04.edn similarity index 100% rename from tui/examples/edn04.edn rename to tui/examples/edn/edn04.edn diff --git a/tui/examples/edn05.edn b/tui/examples/edn/edn05.edn similarity index 100% rename from tui/examples/edn05.edn rename to tui/examples/edn/edn05.edn diff --git a/tui/examples/edn06.edn b/tui/examples/edn/edn06.edn similarity index 100% rename from tui/examples/edn06.edn rename to tui/examples/edn/edn06.edn diff --git a/tui/examples/edn07.edn b/tui/examples/edn/edn07.edn similarity index 100% rename from tui/examples/edn07.edn rename to tui/examples/edn/edn07.edn diff --git a/tui/examples/edn08.edn b/tui/examples/edn/edn08.edn similarity index 100% rename from tui/examples/edn08.edn rename to tui/examples/edn/edn08.edn diff --git a/tui/examples/edn09.edn b/tui/examples/edn/edn09.edn similarity index 100% rename from tui/examples/edn09.edn rename to tui/examples/edn/edn09.edn diff --git a/tui/examples/edn10.edn b/tui/examples/edn/edn10.edn similarity index 100% rename from tui/examples/edn10.edn rename to tui/examples/edn/edn10.edn diff --git a/tui/examples/edn11.edn b/tui/examples/edn/edn11.edn similarity index 100% rename from tui/examples/edn11.edn rename to tui/examples/edn/edn11.edn diff --git a/tui/examples/edn12.edn b/tui/examples/edn/edn12.edn similarity index 100% rename from tui/examples/edn12.edn rename to tui/examples/edn/edn12.edn diff --git a/tui/examples/edn13.edn b/tui/examples/edn/edn13.edn similarity index 100% rename from tui/examples/edn13.edn rename to tui/examples/edn/edn13.edn diff --git a/tui/examples/edn14.edn b/tui/examples/edn/edn14.edn similarity index 100% rename from tui/examples/edn14.edn rename to tui/examples/edn/edn14.edn diff --git a/tui/examples/edn15.edn b/tui/examples/edn/edn15.edn similarity index 100% rename from tui/examples/edn15.edn rename to tui/examples/edn/edn15.edn diff --git a/tui/examples/edn16.edn b/tui/examples/edn/edn16.edn similarity index 100% rename from tui/examples/edn16.edn rename to tui/examples/edn/edn16.edn diff --git a/tui/examples/edn17.edn b/tui/examples/edn/edn17.edn similarity index 100% rename from tui/examples/edn17.edn rename to tui/examples/edn/edn17.edn diff --git a/tui/examples/edn99.edn b/tui/examples/edn/edn99.edn similarity index 100% rename from tui/examples/edn99.edn rename to tui/examples/edn/edn99.edn diff --git a/tui/examples/tui.rs b/tui/examples/tui.rs index 066ab20..63312e8 100644 --- a/tui/examples/tui.rs +++ b/tui/examples/tui.rs @@ -1,6 +1,6 @@ use tengri::{self, Usually, Perhaps, input::*, output::*, tui::*, dsl::*}; use std::sync::{Arc, RwLock}; -use crossterm::event::{*, KeyCode::*}; +//use crossterm::event::{*, KeyCode::*}; use crate::ratatui::style::Color; fn main () -> Usually<()> { @@ -13,23 +13,23 @@ fn main () -> Usually<()> { const KEYMAP: &str = "(@left prev) (@right next)"; const EXAMPLES: &'static [&'static str] = &[ - include_str!("edn01.edn"), - include_str!("edn02.edn"), - include_str!("edn03.edn"), - include_str!("edn04.edn"), - include_str!("edn05.edn"), - include_str!("edn06.edn"), - include_str!("edn07.edn"), - include_str!("edn08.edn"), - include_str!("edn09.edn"), - include_str!("edn10.edn"), - include_str!("edn11.edn"), - include_str!("edn12.edn"), - //include_str!("edn13.edn"), - include_str!("edn14.edn"), - include_str!("edn15.edn"), - include_str!("edn16.edn"), - include_str!("edn17.edn"), + include_str!("edn/edn01.edn"), + include_str!("edn/edn02.edn"), + include_str!("edn/edn03.edn"), + include_str!("edn/edn04.edn"), + include_str!("edn/edn05.edn"), + include_str!("edn/edn06.edn"), + include_str!("edn/edn07.edn"), + include_str!("edn/edn08.edn"), + include_str!("edn/edn09.edn"), + include_str!("edn/edn10.edn"), + include_str!("edn/edn11.edn"), + include_str!("edn/edn12.edn"), + //include_str!("edn/edn13.edn"), + include_str!("edn/edn14.edn"), + include_str!("edn/edn15.edn"), + include_str!("edn/edn16.edn"), + include_str!("edn/edn17.edn"), ]; handle!(TuiIn: |self: Example, input|{ @@ -63,7 +63,7 @@ impl ExampleCommand { } } -view!(TuiOut: |self: Example|{ +content!(TuiOut: |self: Example|{ let index = self.0 + 1; let wh = self.1.wh(); let src = EXAMPLES.get(self.0).unwrap_or(&""); @@ -72,12 +72,29 @@ view!(TuiOut: |self: Example|{ 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, 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(), - ":code" => Tui::bg(Color::Rgb(10, 60, 10), Push::y(2, Align::n(format!("{}", EXAMPLES[self.0])))).boxed(), - ":hello" => Tui::bg(Color::Rgb(10, 100, 10), "Hello").boxed(), - ":world" => Tui::bg(Color::Rgb(100, 10, 10), "world").boxed(), - ":hello-world" => "Hello world!".boxed(), - ":map-e" => Map::east(5u16, ||0..5u16, |n, i|format!("{n}")).boxed(), - ":map-s" => Map::south(5u16, ||0..5u16, |n, i|format!("{n}")).boxed(), }); + +#[tengri_proc::view(TuiOut)] +impl Example { + pub fn title (&self) -> impl Content + use<'_> { + Tui::bg(Color::Rgb(60, 10, 10), Push::y(1, Align::n(format!("Example {}/{}:", self.0 + 1, EXAMPLES.len())))).boxed() + } + pub fn code (&self) -> impl Content + use<'_> { + Tui::bg(Color::Rgb(10, 60, 10), Push::y(2, Align::n(format!("{}", EXAMPLES[self.0])))).boxed() + } + pub fn hello (&self) -> impl Content + use<'_> { + Tui::bg(Color::Rgb(10, 100, 10), "Hello").boxed() + } + pub fn world (&self) -> impl Content + use<'_> { + Tui::bg(Color::Rgb(100, 10, 10), "world").boxed() + } + pub fn hello_world (&self) -> impl Content + use<'_> { + "Hello world!".boxed() + } + pub fn map_e (&self) -> impl Content + use<'_> { + Map::east(5u16, ||0..5u16, |n, _i|format!("{n}")).boxed() + } + pub fn map_s (&self) -> impl Content + use<'_> { + Map::south(5u16, ||0..5u16, |n, _i|format!("{n}")).boxed() + } +} diff --git a/tui/src/lib.rs b/tui/src/lib.rs index 79648b9..e3792f1 100644 --- a/tui/src/lib.rs +++ b/tui/src/lib.rs @@ -36,7 +36,7 @@ pub(crate) use std::io::{stdout, Stdout}; #[cfg(test)] #[test] fn test_tui_engine () -> Usually<()> { use crate::*; - use std::sync::{Arc, RwLock}; + //use std::sync::{Arc, RwLock}; struct TestComponent(String); impl Content for TestComponent { fn content (&self) -> impl Render { @@ -44,21 +44,21 @@ pub(crate) use std::io::{stdout, Stdout}; } } impl Handle for TestComponent { - fn handle (&mut self, from: &TuiIn) -> Perhaps { + fn handle (&mut self, _from: &TuiIn) -> Perhaps { 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)); + let _state = std::sync::Arc::new(std::sync::RwLock::new(state)); //engine.run(&state)?; Ok(()) } #[cfg(test)] #[test] fn test_parse_key () { - use KeyModifiers as Mods; - let test = |x: &str, y|assert_eq!(KeyMatcher::new(x).build(), Some(Event::Key(y))); + //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", diff --git a/tui/src/tui_content/tui_field.rs b/tui/src/tui_content/tui_field.rs index a60cc32..3e47e9f 100644 --- a/tui/src/tui_content/tui_field.rs +++ b/tui/src/tui_content/tui_field.rs @@ -60,7 +60,7 @@ impl Field { value_align: None, } } - fn label ( + pub fn label ( self, label: Option, align: Option, @@ -75,7 +75,7 @@ impl Field { ..self } } - fn value ( + pub fn value ( self, value: Option, align: Option, diff --git a/tui/src/tui_content/tui_number.rs b/tui/src/tui_content/tui_number.rs index 8e283ce..46c4ef1 100644 --- a/tui/src/tui_content/tui_number.rs +++ b/tui/src/tui_content/tui_number.rs @@ -1,5 +1,5 @@ use crate::*; -render!(TuiOut: |self: u64, to|todo!()); +render!(TuiOut: |self: u64, _to|todo!()); -render!(TuiOut: |self: f64, to|todo!()); +render!(TuiOut: |self: f64, _to|todo!()); diff --git a/tui/src/tui_engine/tui_input.rs b/tui/src/tui_engine/tui_input.rs index c9cd788..3bf7791 100644 --- a/tui/src/tui_engine/tui_input.rs +++ b/tui/src/tui_engine/tui_input.rs @@ -56,13 +56,13 @@ impl TuiIn { } } -#[cfg(feature = "dsl")] -impl DslInput for TuiIn { - fn matches_dsl (&self, token: &str) -> bool { - if let Some(event) = KeyMatcher::new(token).build() { - &event == self.event() - } else { - false - } - } -} +//#[cfg(feature = "dsl")] +//impl DslInput for TuiIn { + //fn matches_dsl (&self, token: &str) -> bool { + //if let Some(event) = KeyMatcher::new(token).build() { + //&event == self.event() + //} else { + //false + //} + //} +//}