mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2025-12-08 04:36:49 +01:00
Compare commits
No commits in common. "faecc2c304ad2c0ebd78d21170a02c172fd356bf" and "cb8fd26922fd1cfad4ceadeb89e48544531a178e" have entirely different histories.
faecc2c304
...
cb8fd26922
20 changed files with 206 additions and 250 deletions
28
Cargo.lock
generated
28
Cargo.lock
generated
|
|
@ -46,9 +46,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
|||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.75"
|
||||
version = "0.3.74"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002"
|
||||
checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cfg-if",
|
||||
|
|
@ -286,9 +286,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.3.3"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
|
||||
checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
|
|
@ -757,9 +757,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.12"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af"
|
||||
checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
|
@ -834,9 +834,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
|||
|
||||
[[package]]
|
||||
name = "signal-hook"
|
||||
version = "0.3.18"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2"
|
||||
checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
|
||||
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.3",
|
||||
"getrandom 0.3.2",
|
||||
"once_cell",
|
||||
"rustix 1.0.7",
|
||||
"windows-sys 0.59.0",
|
||||
|
|
@ -938,7 +938,6 @@ version = "0.13.0"
|
|||
dependencies = [
|
||||
"crossterm",
|
||||
"tengri",
|
||||
"tengri_core",
|
||||
"tengri_dsl",
|
||||
"tengri_input",
|
||||
"tengri_output",
|
||||
|
|
@ -946,10 +945,6 @@ dependencies = [
|
|||
"tengri_tui",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tengri_core"
|
||||
version = "0.13.0"
|
||||
|
||||
[[package]]
|
||||
name = "tengri_dsl"
|
||||
version = "0.13.0"
|
||||
|
|
@ -957,7 +952,6 @@ dependencies = [
|
|||
"itertools 0.14.0",
|
||||
"konst",
|
||||
"proptest",
|
||||
"tengri_core",
|
||||
"tengri_tui",
|
||||
"thiserror",
|
||||
]
|
||||
|
|
@ -966,7 +960,6 @@ dependencies = [
|
|||
name = "tengri_input"
|
||||
version = "0.13.0"
|
||||
dependencies = [
|
||||
"tengri_core",
|
||||
"tengri_dsl",
|
||||
"tengri_tui",
|
||||
]
|
||||
|
|
@ -978,7 +971,6 @@ dependencies = [
|
|||
"proptest",
|
||||
"proptest-derive",
|
||||
"tengri",
|
||||
"tengri_core",
|
||||
"tengri_dsl",
|
||||
"tengri_tui",
|
||||
]
|
||||
|
|
@ -991,7 +983,6 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"tengri_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1007,7 +998,6 @@ dependencies = [
|
|||
"rand",
|
||||
"ratatui",
|
||||
"tengri",
|
||||
"tengri_core",
|
||||
"tengri_dsl",
|
||||
"tengri_input",
|
||||
"tengri_output",
|
||||
|
|
|
|||
36
Cargo.toml
36
Cargo.toml
|
|
@ -1,15 +1,11 @@
|
|||
[profile.release]
|
||||
lto = true
|
||||
|
||||
[profile.coverage]
|
||||
inherits = "test"
|
||||
lto = false
|
||||
[workspace.package]
|
||||
version = "0.13.0"
|
||||
edition = "2024"
|
||||
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = [
|
||||
"./tengri",
|
||||
"./core",
|
||||
"./input",
|
||||
"./output",
|
||||
"./tui",
|
||||
|
|
@ -17,25 +13,9 @@ members = [
|
|||
"./proc",
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.13.0"
|
||||
edition = "2024"
|
||||
[profile.release]
|
||||
lto = true
|
||||
|
||||
[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" }
|
||||
[profile.coverage]
|
||||
inherits = "test"
|
||||
lto = false
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
[package]
|
||||
name = "tengri_core"
|
||||
description = "UI metaframework, core definitions."
|
||||
version = { workspace = true }
|
||||
edition = { workspace = true }
|
||||
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
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>>;
|
||||
|
|
@ -5,10 +5,12 @@ version = { workspace = true }
|
|||
edition = { workspace = true }
|
||||
|
||||
[dependencies]
|
||||
tengri_core = { path = "../core" }
|
||||
konst = { workspace = true }
|
||||
itertools = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
konst = { version = "0.3.16", features = [ "rust_1_83" ] }
|
||||
itertools = "0.14.0"
|
||||
thiserror = "2.0"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
[dev-dependencies]
|
||||
tengri_tui = { path = "../tui" }
|
||||
|
|
|
|||
|
|
@ -1,4 +1,55 @@
|
|||
use crate::*;
|
||||
use thiserror::Error;
|
||||
|
||||
pub type ParseResult<T> = Result<T, ParseError>;
|
||||
|
||||
#[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),
|
||||
}
|
||||
|
||||
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 {
|
||||
|
|
@ -87,7 +138,6 @@ impl<'a> SourceIter<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Static iteration helper.
|
||||
#[macro_export] macro_rules! iterate {
|
||||
($expr:expr => $arg: pat => $body:expr) => {
|
||||
|
|
@ -155,7 +205,7 @@ pub const fn peek_src <'a> (source: &'a str) -> Option<Token<'a>> {
|
|||
}
|
||||
}
|
||||
|
||||
pub const fn to_number (digits: &str) -> DslResult<usize> {
|
||||
pub const fn to_number (digits: &str) -> Result<usize, ParseError> {
|
||||
let mut value = 0;
|
||||
iterate!(char_indices(digits) => (_, c) => match to_digit(c) {
|
||||
Ok(digit) => value = 10 * value + digit,
|
||||
|
|
@ -164,7 +214,7 @@ pub const fn to_number (digits: &str) -> DslResult<usize> {
|
|||
Ok(value)
|
||||
}
|
||||
|
||||
pub const fn to_digit (c: char) -> DslResult<usize> {
|
||||
pub const fn to_digit (c: char) -> Result<usize, ParseError> {
|
||||
Ok(match c {
|
||||
'0' => 0, '1' => 1, '2' => 2, '3' => 3, '4' => 4,
|
||||
'5' => 5, '6' => 6, '7' => 7, '8' => 8, '9' => 9,
|
||||
|
|
@ -181,7 +231,7 @@ pub const fn to_digit (c: char) -> DslResult<usize> {
|
|||
|
||||
#[derive(Debug, Copy, Clone, Default, PartialEq)] pub enum Value<'source> {
|
||||
#[default] Nil,
|
||||
Err(DslError),
|
||||
Err(ParseError),
|
||||
Num(usize),
|
||||
Sym(&'source str),
|
||||
Key(&'source str),
|
||||
|
|
@ -190,9 +240,7 @@ pub const fn to_digit (c: char) -> DslResult<usize> {
|
|||
}
|
||||
|
||||
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 {
|
||||
|
|
@ -200,6 +248,7 @@ 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())
|
||||
|
|
@ -207,13 +256,10 @@ 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
|
||||
}
|
||||
pub const fn error (self, error: DslError) -> Self {
|
||||
pub const fn error (self, error: ParseError) -> Self {
|
||||
Self { value: Value::Err(error), ..self }
|
||||
}
|
||||
pub const fn grow (self) -> Self {
|
||||
|
|
@ -226,43 +272,49 @@ impl<'source> Token<'source> {
|
|||
}
|
||||
}
|
||||
pub const fn grow_key (self) -> Self {
|
||||
let token = self.grow();
|
||||
token.with_value(Key(token.slice_source(self.source)))
|
||||
let mut token = self.grow();
|
||||
token.value = Key(token.slice_source(self.source));
|
||||
token
|
||||
}
|
||||
pub const fn grow_sym (self) -> Self {
|
||||
let token = self.grow();
|
||||
token.with_value(Sym(token.slice_source(self.source)))
|
||||
let mut token = self.grow();
|
||||
token.value = Sym(token.slice_source(self.source));
|
||||
token
|
||||
}
|
||||
pub const fn grow_str (self) -> Self {
|
||||
let token = self.grow();
|
||||
token.with_value(Str(token.slice_source(self.source)))
|
||||
let mut token = self.grow();
|
||||
token.value = Str(token.slice_source(self.source));
|
||||
token
|
||||
}
|
||||
pub const fn grow_exp (self) -> Self {
|
||||
let token = self.grow();
|
||||
let mut token = self.grow();
|
||||
if let Exp(depth, _) = token.value {
|
||||
token.with_value(Exp(depth, TokenIter::new(token.slice_source_exp(self.source))))
|
||||
token.value = Exp(depth, TokenIter::new(token.slice_source_exp(self.source)));
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
token
|
||||
}
|
||||
pub const fn grow_in (self) -> Self {
|
||||
let token = self.grow_exp();
|
||||
let mut token = self.grow_exp();
|
||||
if let Value::Exp(depth, source) = token.value {
|
||||
token.with_value(Value::Exp(depth.saturating_add(1), source))
|
||||
token.value = Value::Exp(depth.saturating_add(1), source)
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
token
|
||||
}
|
||||
pub const fn grow_out (self) -> Self {
|
||||
let token = self.grow_exp();
|
||||
let mut token = self.grow_exp();
|
||||
if let Value::Exp(depth, source) = token.value {
|
||||
if depth > 0 {
|
||||
token.with_value(Value::Exp(depth - 1, source))
|
||||
token.value = Value::Exp(depth - 1, source)
|
||||
} else {
|
||||
return self.error(Unexpected(')'))
|
||||
}
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
token
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
use crate::*;
|
||||
|
||||
pub type DslResult<T> = Result<T, DslError>;
|
||||
|
||||
#[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),
|
||||
}
|
||||
|
|
@ -1,55 +0,0 @@
|
|||
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<U>: Sized {
|
||||
fn take <'state, 'source> (_: &'state Self, _: &mut TokenIter<'source>) -> Perhaps<U> {
|
||||
Ok(None)
|
||||
}
|
||||
fn take_or_fail <'state, 'source> (
|
||||
state: &'state Self, iter: &mut TokenIter<'source>
|
||||
) -> Usually<U> {
|
||||
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
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,7 +1,3 @@
|
|||
#![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]
|
||||
|
|
@ -35,19 +31,17 @@
|
|||
//! 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 ::tengri_core::*;
|
||||
|
||||
pub(crate) use std::fmt::Debug;
|
||||
pub(crate) use self::Value::*;
|
||||
pub(crate) use self::ParseError::*;
|
||||
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::DslError::*;
|
||||
pub(crate) use std::fmt::Debug;
|
||||
|
||||
mod dsl_error; pub use self::dsl_error::*;
|
||||
mod dsl_parse; pub use self::dsl_parse::*;
|
||||
mod dsl_provide; pub use self::dsl_provide::*;
|
||||
mod dsl; pub use self::dsl::*;
|
||||
|
||||
#[cfg(test)] mod test_token_iter {
|
||||
use crate::*;
|
||||
|
|
@ -149,7 +143,7 @@ mod dsl_provide; pub use self::dsl_provide::*;
|
|||
Ok(())
|
||||
}
|
||||
|
||||
//#[cfg(test)] #[test] fn test_examples () -> Result<(), DslError> {
|
||||
//#[cfg(test)] #[test] fn test_examples () -> Result<(), ParseError> {
|
||||
//// 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.
|
||||
|
|
|
|||
|
|
@ -4,13 +4,12 @@ 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" }
|
||||
|
|
|
|||
|
|
@ -1,16 +1,18 @@
|
|||
#![feature(associated_type_defaults)]
|
||||
|
||||
pub(crate) use tengri_core::*;
|
||||
|
||||
mod input_macros;
|
||||
mod input_command; pub use self::input_command::*;
|
||||
mod input_handle; pub use self::input_handle::*;
|
||||
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::*;
|
||||
|
||||
#[cfg(test)] #[test] fn test_stub_input () -> Usually<()> {
|
||||
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<()> {
|
||||
use crate::*;
|
||||
struct TestInput(bool);
|
||||
enum TestEvent { Test1 }
|
||||
|
|
@ -31,7 +33,8 @@ 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(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,16 +4,15 @@ 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 = { workspace = true }
|
||||
proptest-derive = { workspace = true }
|
||||
proptest = "^1"
|
||||
proptest-derive = "^0.5.1"
|
||||
|
|
|
|||
|
|
@ -7,13 +7,18 @@ 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<()> {
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@ edition = { workspace = true }
|
|||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
tengri_core = { path = "../core" }
|
||||
syn = { workspace = true }
|
||||
quote = { workspace = true }
|
||||
proc-macro2 = { workspace = true }
|
||||
heck = { workspace = true }
|
||||
syn = { version = "2", features = ["full", "extra-traits"] }
|
||||
quote = { version = "1" }
|
||||
proc-macro2 = { version = "1", features = ["span-locations"] }
|
||||
heck = { version = "0.5" }
|
||||
|
|
|
|||
|
|
@ -10,7 +10,10 @@ pub(crate) struct CommandMeta(Ident);
|
|||
pub(crate) struct CommandImpl(ItemImpl, BTreeMap<Arc<str>, CommandArm>);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct CommandArm(Ident, Vec<FnArg>, #[allow(unused)] ReturnType);
|
||||
struct CommandArm(Ident, Vec<FnArg>, ReturnType);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct CommandVariant(Ident, Vec<FnArg>);
|
||||
|
||||
impl Parse for CommandMeta {
|
||||
fn parse (input: ParseStream) -> Result<Self> {
|
||||
|
|
@ -70,8 +73,7 @@ impl ToTokens for CommandDef {
|
|||
state: &'state #target, iter: &mut ::tengri::dsl::TokenIter<'source>
|
||||
) -> Option<Self> {
|
||||
let mut iter = iter.clone();
|
||||
let token = iter.next();
|
||||
match token {
|
||||
match iter.next() {
|
||||
#(#matchers)*
|
||||
_ => None
|
||||
}
|
||||
|
|
@ -155,12 +157,10 @@ 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 = format!("{}: missing value for \"{}\" ({}): {{:#?}}",
|
||||
quote!{#ident}, quote!{#arg}, quote!{#ty});
|
||||
let give_err = LitStr::new(&give_err, Span::call_site());
|
||||
let give_err = LitStr::new(&format!("{}: missing value for \"{}\" ({})",
|
||||
quote!{#ident}, quote!{#arg}, quote!{#ty}), Span::call_site());
|
||||
write_quote_to(&mut out, quote! {
|
||||
#arg: ::tengri::dsl::Context::get(state, &mut iter)
|
||||
.unwrap_or_else(||panic!(#give_err, token)),
|
||||
#arg: ::tengri::dsl::Context::get(state, &mut iter).expect(#give_err),
|
||||
});
|
||||
}
|
||||
out
|
||||
|
|
@ -203,3 +203,25 @@ 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));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,15 +4,7 @@ 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" }
|
||||
|
|
@ -21,4 +13,11 @@ tengri_tui = { optional = true, path = "../tui" }
|
|||
[dev-dependencies]
|
||||
tengri_proc = { path = "../proc" }
|
||||
tengri = { path = ".", features = [ "dsl" ] }
|
||||
crossterm = { workspace = true }
|
||||
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" ]
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
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;
|
||||
#[cfg(feature="tui")] pub use ::tengri_tui as tui;
|
||||
|
||||
#[cfg(test)] extern crate tengri_proc;
|
||||
#[cfg(test)] #[test] fn test_subcommand () -> Usually<()> {
|
||||
#[cfg(test)] #[test] fn test_subcommand () -> crate::output::Usually<()> {
|
||||
use crate::output::Perhaps;
|
||||
use crate::input::{Command, InputMap, KeyMap, Handle, handle};
|
||||
use crate::dsl::{TryFromDsl, TokenIter};
|
||||
use crate::tui::TuiIn;
|
||||
|
|
@ -80,21 +80,20 @@ pub use ::tengri_core::*;
|
|||
Ok(())
|
||||
}
|
||||
|
||||
//FIXME:
|
||||
//#[cfg(test)] #[test] fn test_dsl_context () {
|
||||
//use crate::dsl::{Context, Value};
|
||||
#[cfg(test)] #[test] fn test_dsl_context () {
|
||||
use crate::dsl::Value;
|
||||
|
||||
//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));
|
||||
//}
|
||||
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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,26 +4,25 @@ description = "UI metaframework, Ratatui backend."
|
|||
version = { workspace = true }
|
||||
edition = { workspace = true }
|
||||
|
||||
[features]
|
||||
dsl = [ "tengri_dsl", "tengri_input/dsl", "tengri_output/dsl" ]
|
||||
|
||||
[dependencies]
|
||||
tengri_core = { path = "../core" }
|
||||
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"
|
||||
|
||||
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" ]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use tengri::{self, Usually, Perhaps, input::*, output::*, tui::*, dsl::*};
|
||||
use tengri::{self, 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, TokenIter::new(src)));
|
||||
let content = Tui::bg(Color::Rgb(10, 10, 60), View(self, SourceIter::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(),
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@
|
|||
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::*;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue