mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 03:36:41 +01:00
refactor engine and layout into input and output
This commit is contained in:
parent
f052891473
commit
4d0f98acd2
40 changed files with 104 additions and 109 deletions
14
Cargo.lock
generated
14
Cargo.lock
generated
|
|
@ -1432,19 +1432,17 @@ dependencies = [
|
|||
"clojure-reader",
|
||||
"itertools 0.14.0",
|
||||
"konst",
|
||||
"tek_layout",
|
||||
"tek_input",
|
||||
"tek_output",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tek_engine"
|
||||
name = "tek_input"
|
||||
version = "0.2.0"
|
||||
|
||||
[[package]]
|
||||
name = "tek_layout"
|
||||
name = "tek_output"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"tek_engine",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tek_tui"
|
||||
|
|
@ -1456,8 +1454,8 @@ dependencies = [
|
|||
"rand",
|
||||
"ratatui",
|
||||
"tek_edn",
|
||||
"tek_engine",
|
||||
"tek_layout",
|
||||
"tek_input",
|
||||
"tek_output",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
|||
|
|
@ -27,8 +27,10 @@ wavers = "1.4.3"
|
|||
#winit = { version = "0.30.4", features = [ "x11" ] }
|
||||
|
||||
[features]
|
||||
default = ["edn"]
|
||||
edn = ["tek_tui/edn"]
|
||||
default = ["tek_input", "tek_output", "tek_edn"]
|
||||
tek_input = [ "tek_tui/tek_input" ]
|
||||
tek_output = [ "tek_tui/tek_output" ]
|
||||
tek_edn = [ "tek_tui/tek_edn" ]
|
||||
|
||||
[[bin]]
|
||||
name = "tek_arranger"
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
#[allow(unused_imports)] use tek::{
|
||||
*,
|
||||
jack::*,
|
||||
tek_layout::Measure,
|
||||
tek_engine::Usually,
|
||||
tek_input::*,
|
||||
tek_output::*,
|
||||
tek_tui::{Tui, TuiRun, ItemPalette, ItemColor, ratatui::prelude::Color}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -7,11 +7,12 @@ version = "0.1.0"
|
|||
clojure-reader = "0.3.0"
|
||||
konst = "0.3.16"
|
||||
itertools = "0.14.0"
|
||||
tek_layout = { optional = true, path = "../layout" }
|
||||
|
||||
tek_input = { optional = true, path = "../input" }
|
||||
tek_output = { optional = true, path = "../output" }
|
||||
|
||||
[features]
|
||||
default = ["layout"]
|
||||
layout = [ "tek_layout" ]
|
||||
default = ["tek_input", "tek_output"]
|
||||
|
||||
[dev-dependencies]
|
||||
tek_tui = { path = "../tui" }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::*;
|
||||
use std::marker::PhantomData;
|
||||
use ::tek_layout::{*, tek_engine::{Usually, Content, Render, RenderBox, Output, Thunk}};
|
||||
use ::tek_output::*;
|
||||
use EdnItem::*;
|
||||
|
||||
pub type EdnCallback<'a, Output, State> =
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
pub(crate) use std::{
|
||||
fmt::{Debug, Formatter, Error as FormatError}
|
||||
};
|
||||
pub use ::tek_layout;
|
||||
pub use ::tek_output;
|
||||
|
||||
mod edn_error; pub use self::edn_error::*;
|
||||
mod edn_item; pub use self::edn_item::*;
|
||||
|
|
@ -12,6 +12,9 @@ mod edn_iter; pub use self::edn_iter::*;
|
|||
mod edn_token; pub use self::edn_token::*;
|
||||
mod edn_view; pub use self::edn_view::*;
|
||||
|
||||
#[cfg(feature = "tek_output")]
|
||||
pub(crate) use ::tek_output::*;
|
||||
|
||||
#[cfg(test)] #[test] fn test_edn () -> Result<(), ParseError> {
|
||||
use EdnItem::*;
|
||||
assert_eq!(EdnItem::<String>::read_all("")?,
|
||||
|
|
|
|||
0
engine/Cargo.lock → input/Cargo.lock
generated
0
engine/Cargo.lock → input/Cargo.lock
generated
|
|
@ -1,5 +1,5 @@
|
|||
[package]
|
||||
name = "tek_engine"
|
||||
name = "tek_input"
|
||||
edition = "2021"
|
||||
version = "0.2.0"
|
||||
|
||||
15
input/src/engine.rs
Normal file
15
input/src/engine.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
use crate::*;
|
||||
|
||||
/// Event source
|
||||
pub trait Input: Send + Sync + Sized {
|
||||
/// Type of input event
|
||||
type Event;
|
||||
/// Result of handling input
|
||||
type Handled;
|
||||
/// Currently handled event
|
||||
fn event (&self) -> &Self::Event;
|
||||
/// Whether component should exit
|
||||
fn is_done (&self) -> bool;
|
||||
/// Mark component as done
|
||||
fn done (&self);
|
||||
}
|
||||
|
|
@ -5,30 +5,15 @@ mod engine; pub use self::engine::*;
|
|||
mod handle; pub use self::handle::*;
|
||||
mod command; pub use self::command::*;
|
||||
mod event_map; pub use self::event_map::*;
|
||||
mod coordinate; pub use self::coordinate::*;
|
||||
mod size; pub use self::size::*;
|
||||
mod area; pub use self::area::*;
|
||||
mod render; pub use self::render::*;
|
||||
mod content; pub use self::content::*;
|
||||
mod thunk; pub use self::thunk::*;
|
||||
|
||||
pub use std::error::Error;
|
||||
pub(crate) use std::marker::PhantomData;
|
||||
pub(crate) use std::error::Error;
|
||||
|
||||
/// Standard result type.
|
||||
pub type Usually<T> = Result<T, Box<dyn Error>>;
|
||||
pub(crate) type Usually<T> = Result<T, Box<dyn Error>>;
|
||||
|
||||
/// Standard optional result type.
|
||||
pub type Perhaps<T> = Result<Option<T>, Box<dyn Error>>;
|
||||
|
||||
/// Prototypal case of implementor macro.
|
||||
/// Saves 4loc per data pats.
|
||||
#[macro_export] macro_rules! from {
|
||||
($(<$($lt:lifetime),+>)?|$state:ident:$Source:ty|$Target:ty=$cb:expr) => {
|
||||
impl $(<$($lt),+>)? From<$Source> for $Target {
|
||||
fn from ($state:$Source) -> Self { $cb }
|
||||
}
|
||||
};
|
||||
}
|
||||
pub(crate) type Perhaps<T> = Result<Option<T>, Box<dyn Error>>;
|
||||
|
||||
#[cfg(test)] #[test] fn test_dimensions () {
|
||||
assert_eq!(Area::center(&[10u16, 10, 20, 20]), [20, 20]);
|
||||
0
layout/Cargo.lock → output/Cargo.lock
generated
0
layout/Cargo.lock → output/Cargo.lock
generated
|
|
@ -1,10 +1,8 @@
|
|||
[package]
|
||||
name = "tek_layout"
|
||||
name = "tek_output"
|
||||
edition = "2021"
|
||||
version = "0.2.0"
|
||||
|
||||
[dependencies]
|
||||
tek_engine = { path = "../engine" }
|
||||
|
||||
[dev-dependencies]
|
||||
tek_tui = { path = "../tui" }
|
||||
tek_engine = { path = "../engine" }
|
||||
|
|
@ -1,6 +1,15 @@
|
|||
#![feature(type_alias_impl_trait)]
|
||||
#![feature(impl_trait_in_assoc_type)]
|
||||
|
||||
mod coordinate; pub use self::coordinate::*;
|
||||
mod size; pub use self::size::*;
|
||||
mod area; pub use self::area::*;
|
||||
|
||||
mod output; pub use self::output::*;
|
||||
mod content; pub use self::content::*;
|
||||
mod render; pub use self::render::*;
|
||||
mod thunk; pub use self::thunk::*;
|
||||
|
||||
mod when; pub use self::when::*;
|
||||
mod either; pub use self::either::*;
|
||||
mod map; pub use self::map::*;
|
||||
|
|
@ -12,9 +21,24 @@ mod measure; pub use self::measure::*;
|
|||
mod transform_xy; pub use self::transform_xy::*;
|
||||
mod transform_xy_unit; pub use self::transform_xy_unit::*;
|
||||
|
||||
pub use ::tek_engine;
|
||||
pub(crate) use ::tek_engine::*;
|
||||
pub(crate) use std::marker::PhantomData;
|
||||
pub(crate) use std::error::Error;
|
||||
|
||||
/// Standard result type.
|
||||
pub type Usually<T> = Result<T, Box<dyn Error>>;
|
||||
|
||||
/// Standard optional result type.
|
||||
pub type Perhaps<T> = Result<Option<T>, Box<dyn Error>>;
|
||||
|
||||
/// Prototypal case of implementor macro.
|
||||
/// Saves 4loc per data pats.
|
||||
#[macro_export] macro_rules! from {
|
||||
($(<$($lt:lifetime),+>)?|$state:ident:$Source:ty|$Target:ty=$cb:expr) => {
|
||||
impl $(<$($lt),+>)? From<$Source> for $Target {
|
||||
fn from ($state:$Source) -> Self { $cb }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(test)] #[test] fn test_layout () -> Usually<()> {
|
||||
use ::tek_tui::Tui;
|
||||
|
|
@ -1,33 +1,5 @@
|
|||
use crate::*;
|
||||
|
||||
/// Platform backend.
|
||||
pub trait Engine: Send + Sync + Sized {
|
||||
/// Input event type
|
||||
type Input: Input;
|
||||
/// Render target
|
||||
type Output: Output;
|
||||
/// Prepare before run
|
||||
fn setup (&mut self) -> Usually<()> { Ok(()) }
|
||||
/// True if done
|
||||
fn exited (&self) -> bool;
|
||||
/// Clean up after run
|
||||
fn teardown (&mut self) -> Usually<()> { Ok(()) }
|
||||
}
|
||||
|
||||
/// Event source
|
||||
pub trait Input: Send + Sync + Sized {
|
||||
/// Type of input event
|
||||
type Event;
|
||||
/// Result of handling input
|
||||
type Handled;
|
||||
/// Currently handled event
|
||||
fn event (&self) -> &Self::Event;
|
||||
/// Whether component should exit
|
||||
fn is_done (&self) -> bool;
|
||||
/// Mark component as done
|
||||
fn done (&self);
|
||||
}
|
||||
|
||||
/// Render target
|
||||
pub trait Output: Send + Sync + Sized {
|
||||
/// Unit of length
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
use crate::*;
|
||||
use super::*;
|
||||
use std::marker::ConstParamTy;
|
||||
use tek_engine::Render;
|
||||
use EdnItem::*;
|
||||
|
||||
const EDN: &'static str = include_str!("groovebox.edn");
|
||||
|
|
|
|||
|
|
@ -5,12 +5,12 @@
|
|||
#![feature(impl_trait_in_assoc_type)]
|
||||
#![feature(associated_type_defaults)]
|
||||
|
||||
pub use ::tek_tui::{self, tek_engine, tek_layout};
|
||||
pub use ::tek_tui::{self, tek_edn, tek_input, tek_output};
|
||||
pub(crate) use ::tek_tui::{
|
||||
*,
|
||||
tek_edn::*,
|
||||
tek_layout::*,
|
||||
tek_engine::*,
|
||||
tek_input::*,
|
||||
tek_output::*,
|
||||
crossterm::{
|
||||
self,
|
||||
event::{
|
||||
|
|
|
|||
|
|
@ -4,15 +4,15 @@ edition = "2021"
|
|||
version = "0.2.0"
|
||||
|
||||
[dependencies]
|
||||
tek_engine = { path = "../engine" }
|
||||
tek_layout = { path = "../layout" }
|
||||
tek_edn = { optional = true, path = "../edn" }
|
||||
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"
|
||||
|
||||
tek_edn = { optional = true, path = "../edn" }
|
||||
tek_input = { optional = true, path = "../input" }
|
||||
tek_output = { optional = true, path = "../output" }
|
||||
|
||||
[features]
|
||||
default = ["edn"]
|
||||
edn = ["tek_edn"]
|
||||
default = ["tek_input", "tek_output", "tek_edn"]
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
pub use ::tek_engine;
|
||||
pub use ::tek_layout;
|
||||
pub use ::tek_input;
|
||||
pub use ::tek_output;
|
||||
pub use ::tek_edn;
|
||||
pub(crate) use tek_layout::*;
|
||||
pub(crate) use tek_engine::*;
|
||||
pub(crate) use tek_input::*;
|
||||
pub(crate) use tek_output::*;
|
||||
|
||||
mod tui_engine; pub use self::tui_engine::*;
|
||||
mod tui_content; pub use self::tui_content::*;
|
||||
|
|
|
|||
|
|
@ -7,31 +7,6 @@ pub struct Tui {
|
|||
pub area: [u16;4], // FIXME auto resize
|
||||
}
|
||||
|
||||
impl Engine for Tui {
|
||||
type Input = TuiIn;
|
||||
type Output = TuiOut;
|
||||
fn exited (&self) -> bool {
|
||||
self.exited.fetch_and(true, Relaxed)
|
||||
}
|
||||
fn setup (&mut self) -> Usually<()> {
|
||||
let better_panic_handler = Settings::auto().verbosity(Verbosity::Full).create_panic_handler();
|
||||
std::panic::set_hook(Box::new(move |info: &std::panic::PanicHookInfo|{
|
||||
stdout().execute(LeaveAlternateScreen).unwrap();
|
||||
CrosstermBackend::new(stdout()).show_cursor().unwrap();
|
||||
disable_raw_mode().unwrap();
|
||||
better_panic_handler(info);
|
||||
}));
|
||||
stdout().execute(EnterAlternateScreen)?;
|
||||
self.backend.hide_cursor()?;
|
||||
enable_raw_mode().map_err(Into::into)
|
||||
}
|
||||
fn teardown (&mut self) -> Usually<()> {
|
||||
stdout().execute(LeaveAlternateScreen)?;
|
||||
self.backend.show_cursor()?;
|
||||
disable_raw_mode().map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
impl Tui {
|
||||
/// Construct a new TUI engine and wrap it for shared ownership.
|
||||
pub fn new () -> Usually<Arc<RwLock<Self>>> {
|
||||
|
|
@ -44,6 +19,23 @@ impl Tui {
|
|||
backend,
|
||||
})))
|
||||
}
|
||||
/// True if done
|
||||
pub fn exited (&self) -> bool {
|
||||
self.exited.fetch_and(true, Relaxed)
|
||||
}
|
||||
/// Prepare before run
|
||||
pub fn setup (&mut self) -> Usually<()> {
|
||||
let better_panic_handler = Settings::auto().verbosity(Verbosity::Full).create_panic_handler();
|
||||
std::panic::set_hook(Box::new(move |info: &std::panic::PanicHookInfo|{
|
||||
stdout().execute(LeaveAlternateScreen).unwrap();
|
||||
CrosstermBackend::new(stdout()).show_cursor().unwrap();
|
||||
disable_raw_mode().unwrap();
|
||||
better_panic_handler(info);
|
||||
}));
|
||||
stdout().execute(EnterAlternateScreen)?;
|
||||
self.backend.hide_cursor()?;
|
||||
enable_raw_mode().map_err(Into::into)
|
||||
}
|
||||
/// Update the display buffer.
|
||||
pub fn flip (&mut self, mut buffer: Buffer, size: ratatui::prelude::Rect) -> Buffer {
|
||||
if self.buffer.area != size {
|
||||
|
|
@ -58,4 +50,10 @@ impl Tui {
|
|||
buffer.reset();
|
||||
buffer
|
||||
}
|
||||
/// Clean up after run
|
||||
pub fn teardown (&mut self) -> Usually<()> {
|
||||
stdout().execute(LeaveAlternateScreen)?;
|
||||
self.backend.show_cursor()?;
|
||||
disable_raw_mode().map_err(Into::into)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue