mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2026-05-30 17:23:39 +02:00
Compare commits
4 commits
a06ea2ac13
...
b0fb9f013d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b0fb9f013d | ||
|
|
c9b9ff1519 | ||
|
|
6c382e2627 | ||
|
|
a93fe92a59 |
13 changed files with 176 additions and 98 deletions
1
.envrc
Normal file
1
.envrc
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
use nix
|
||||||
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -1,3 +1,4 @@
|
||||||
target
|
|
||||||
cov
|
|
||||||
*.profraw
|
*.profraw
|
||||||
|
.direnv
|
||||||
|
cov
|
||||||
|
target
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ winit = { optional = true, version = "0.30.4", features = [ "x11" ]}
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
proptest = { version = "^1" }
|
proptest = { version = "^1" }
|
||||||
proptest-derive = { version = "^0.5.1" }
|
proptest-derive = { version = "^0.5.1" }
|
||||||
tengri = { path = ".", features = [ "dsl" ] }
|
tengri = { path = "." }
|
||||||
#tengri_proc = { path = "./proc" }
|
#tengri_proc = { path = "./proc" }
|
||||||
|
|
||||||
[profile.coverage]
|
[profile.coverage]
|
||||||
|
|
|
||||||
8
Justfile
8
Justfile
|
|
@ -2,8 +2,9 @@ export LLVM_PROFILE_FILE := "cov/cargo-test-%p-%m.profraw"
|
||||||
grcov-binary := "--binary-path ./target/coverage/deps/"
|
grcov-binary := "--binary-path ./target/coverage/deps/"
|
||||||
grcov-ignore := "--ignore-not-existing --ignore '../*' --ignore \"/*\" --ignore 'target/*'"
|
grcov-ignore := "--ignore-not-existing --ignore '../*' --ignore \"/*\" --ignore 'target/*'"
|
||||||
|
|
||||||
|
[private]
|
||||||
default:
|
default:
|
||||||
just -l
|
@just -l
|
||||||
|
|
||||||
bacon:
|
bacon:
|
||||||
bacon -s
|
bacon -s
|
||||||
|
|
@ -29,6 +30,7 @@ doc:
|
||||||
cargo doc
|
cargo doc
|
||||||
|
|
||||||
example-tui-00:
|
example-tui-00:
|
||||||
cargo run -p tengri_tui --example tui_00
|
cargo run --example tui_00
|
||||||
|
|
||||||
example-tui-01:
|
example-tui-01:
|
||||||
cargo run -p tengri_tui --example tui_01
|
cargo run --example tui_01
|
||||||
|
|
|
||||||
|
|
@ -1,46 +1,74 @@
|
||||||
use ::{std::{io::stdout, sync::{Arc, RwLock}}, ratatui::style::Color, tengri::*};
|
use ::{
|
||||||
tui_main!(State { cursor: 10, ..Default::default() });
|
std::{io::stdout, sync::{Arc, RwLock}},
|
||||||
namespace!(State: bool {});
|
tengri::{*, term::*, lang::*, keys::*, draw::*, space::*},
|
||||||
namespace!(State: u16 {});
|
ratatui::style::Color,
|
||||||
namespace!(State: Color {});
|
};
|
||||||
handle!(TuiIn: |self: State, input|Action::from(input).eval(self).map(|_|None));
|
|
||||||
view!(State: TuiOut: [ evaluate_output_expression, evaluate_output_expression_tui ]);
|
tui_main!(State { cursor: 10, ..Default::default() });
|
||||||
draw!(State: TuiOut: [ draw_example ]);
|
|
||||||
#[derive(Debug, Default)] struct State {
|
impl Apply<TuiEvent, Usually<Self>> for State {
|
||||||
/** Rendered window size */ size: Measure<TuiOut>,
|
fn apply (&mut self, input: &TuiEvent) -> Usually<Self> {
|
||||||
/** Command history (undo/redo) */ history: Vec<Action>,
|
todo!()
|
||||||
/** User-controllable value */ cursor: usize,
|
}
|
||||||
}
|
}
|
||||||
impl_from!(Action: |input: &TuiIn| todo!());
|
|
||||||
#[derive(Debug)] enum Action {
|
impl View<Tui> for State {
|
||||||
/** Increment cursor */ Next,
|
fn view (&self) -> impl Draw<Tui> {
|
||||||
/** Decrement cursor */ Prev
|
let index = self.cursor + 1;
|
||||||
}
|
let wh = (self.size.w(), self.size.h());
|
||||||
fn draw_example (state: &State, to: &mut TuiOut) {
|
let src = VIEWS.get(self.cursor).unwrap_or(&"");
|
||||||
let index = state.cursor + 1;
|
|
||||||
let wh = state.size.wh();
|
|
||||||
let src = VIEWS.get(state.cursor).unwrap_or(&"");
|
|
||||||
let heading = format!("State {}/{} in {:?}", index, VIEWS.len(), &wh);
|
let heading = format!("State {}/{} in {:?}", index, VIEWS.len(), &wh);
|
||||||
let title = Tui::bg(Color::Rgb(60, 10, 10), Push::Y(1, Align::n(heading)));
|
let title = 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 code = bg(Color::Rgb(10, 60, 10), push_y(2, align_n(format!("{}", src))));
|
||||||
//let content = ;//();//Tui::bg(Color::Rgb(10, 10, 60), View(state, CstIter::new(src)));
|
//let content = ;//();//bg(Color::Rgb(10, 10, 60), View(self, CstIter::new(src)));
|
||||||
state.size.of(Bsp::s(title, Bsp::n(code, state.understand(to, &src).unwrap()))).draw(to)
|
self.size.of(bsp_s(title, bsp_n(code, self.understand(to, &src).unwrap())))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)] struct State {
|
||||||
|
/** Command history (undo/redo). */
|
||||||
|
history: Vec<Action>,
|
||||||
|
/** User-controllable value. */
|
||||||
|
cursor: usize,
|
||||||
|
/** Rendered window size. */
|
||||||
|
size: crate::space::Size,
|
||||||
|
}
|
||||||
|
|
||||||
|
//impl_from!(Action: |input: &TuiIn| todo!());
|
||||||
|
#[derive(Debug)] enum Action {
|
||||||
|
/** Increment cursor */
|
||||||
|
Next,
|
||||||
|
/** Decrement cursor */
|
||||||
|
Prev
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw_example (state: &State, to: &mut Tui) {
|
||||||
|
}
|
||||||
|
|
||||||
impl Action {
|
impl Action {
|
||||||
const BINDS: &'static str = stringify! { (@left prev) (@right next) };
|
|
||||||
|
const BINDS: &'static str = stringify! {
|
||||||
|
(@left prev)
|
||||||
|
(@right next)
|
||||||
|
};
|
||||||
|
|
||||||
fn eval (&self, state: &mut State) -> Perhaps<Self> {
|
fn eval (&self, state: &mut State) -> Perhaps<Self> {
|
||||||
use Action::*;
|
use Action::*;
|
||||||
match self { Next => Self::next(state), Prev => Self::prev(state), }
|
match self { Next => Self::next(state), Prev => Self::prev(state), }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next (state: &mut State) -> Perhaps<Self> {
|
fn next (state: &mut State) -> Perhaps<Self> {
|
||||||
state.cursor = (state.cursor + 1) % VIEWS.len();
|
state.cursor = (state.cursor + 1) % VIEWS.len();
|
||||||
Ok(Some(Self::Prev))
|
Ok(Some(Self::Prev))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prev (state: &mut State) -> Perhaps<Self> {
|
fn prev (state: &mut State) -> Perhaps<Self> {
|
||||||
state.cursor = if state.cursor > 0 { state.cursor - 1 } else { VIEWS.len() - 1 };
|
state.cursor = if state.cursor > 0 { state.cursor - 1 } else { VIEWS.len() - 1 };
|
||||||
Ok(Some(Self::Next))
|
Ok(Some(Self::Next))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const VIEWS: &'static [&'static str] = &[
|
const VIEWS: &'static [&'static str] = &[
|
||||||
|
|
||||||
stringify! { :hello-world },
|
stringify! { :hello-world },
|
||||||
|
|
@ -121,3 +149,10 @@ const VIEWS: &'static [&'static str] = &[
|
||||||
},
|
},
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
//namespace!(State: bool {});
|
||||||
|
//namespace!(State: u16 {});
|
||||||
|
//namespace!(State: Color {});
|
||||||
|
//handle!(TuiIn: |self: State, input|Action::from(input).eval(self).map(|_|None));
|
||||||
|
//view!(State: Tui: [ evaluate_output_expression, evaluate_output_expression_tui ]);
|
||||||
|
//draw!(State: Tui: [ draw_example ]);
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
{pkgs?import<nixpkgs>{}}:let
|
{pkgs?import<nixpkgs>{}}:let
|
||||||
stdenv = pkgs.clang19Stdenv;
|
stdenv = pkgs.clang19Stdenv;
|
||||||
name = "tengri";
|
name = "tengri";
|
||||||
nativeBuildInputs = [ pkgs.pkg-config pkgs.libclang pkgs.mold ];
|
nativeBuildInputs = [ pkgs.pkg-config pkgs.clang pkgs.libclang pkgs.mold ];
|
||||||
buildInputs = [ pkgs.libclang ];
|
buildInputs = [ pkgs.libclang pkgs.jack2 ];
|
||||||
LIBCLANG_PATH = "${pkgs.libclang.lib.outPath}/lib";
|
LIBCLANG_PATH = "${pkgs.libclang.lib.outPath}/lib";
|
||||||
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath [];
|
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath [];
|
||||||
in pkgs.mkShell.override {
|
in pkgs.mkShell.override {
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,10 @@ pub fn rgb (r: u8, g: u8, b: u8) -> ItemColor {
|
||||||
ItemColor { okhsl: rgb_to_okhsl(term), term }
|
ItemColor { okhsl: rgb_to_okhsl(term), term }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn g (g: u8) -> Color {
|
||||||
|
Color::Rgb(g, g, g)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn okhsl_to_rgb (color: Okhsl<f32>) -> Color {
|
pub fn okhsl_to_rgb (color: Okhsl<f32>) -> Color {
|
||||||
let Srgb { red, green, blue, .. }: Srgb<f32> = Srgb::from_color_unclamped(color);
|
let Srgb { red, green, blue, .. }: Srgb<f32> = Srgb::from_color_unclamped(color);
|
||||||
Color::Rgb((red * 255.0) as u8, (green * 255.0) as u8, (blue * 255.0) as u8,)
|
Color::Rgb((red * 255.0) as u8, (green * 255.0) as u8, (blue * 255.0) as u8,)
|
||||||
|
|
|
||||||
37
src/draw.rs
37
src/draw.rs
|
|
@ -8,6 +8,10 @@ use crate::{*, lang::*, color::*, space::*};
|
||||||
/// Drawables are consumable, i.e. the [Draw::draw] method receives an
|
/// Drawables are consumable, i.e. the [Draw::draw] method receives an
|
||||||
/// owned `self` and does not return it, consuming the drawable.
|
/// owned `self` and does not return it, consuming the drawable.
|
||||||
///
|
///
|
||||||
|
/// To draw a thing multiple times, instead of explicitly constructing it
|
||||||
|
/// every time, implement the [View] trait instead, which will construct
|
||||||
|
/// a [Draw]able.
|
||||||
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use tengri::draw::*;
|
/// use tengri::draw::*;
|
||||||
/// struct TestScreen(bool);
|
/// struct TestScreen(bool);
|
||||||
|
|
@ -26,17 +30,22 @@ use crate::{*, lang::*, color::*, space::*};
|
||||||
pub trait Draw<T: Screen> {
|
pub trait Draw<T: Screen> {
|
||||||
fn draw (self, to: &mut T) -> Usually<XYWH<T::Unit>>;
|
fn draw (self, to: &mut T) -> Usually<XYWH<T::Unit>>;
|
||||||
}
|
}
|
||||||
|
impl<T: Screen, D: Draw<T>> Draw<T> for &D {
|
||||||
impl<T: Screen> Draw<T> for () {
|
fn draw (self, to: &mut T) -> Usually<XYWH<T::Unit>> {
|
||||||
fn draw (self, __: &mut T) -> Usually<XYWH<T::Unit>> {
|
todo!()
|
||||||
Ok(Default::default())
|
}
|
||||||
|
}
|
||||||
|
impl<T: Screen, D: Draw<T>> Draw<T> for Option<D> {
|
||||||
|
fn draw (self, to: &mut T) -> Usually<XYWH<T::Unit>> {
|
||||||
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Screen, D: Draw<T>> Draw<T> for Option<D> {
|
/// Emit a [Draw]able.
|
||||||
fn draw (self, to: &mut T) -> Usually<XYWH<T::Unit>> {
|
///
|
||||||
Ok(self.map(|draw|draw.draw(to)).transpose()?.unwrap_or_default())
|
/// Speculative. How to avoid conflicts with [Draw] proper?
|
||||||
}
|
pub trait View<T: Screen> {
|
||||||
|
fn view (&self) -> impl Draw<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn thunk <T: Screen, F: FnOnce(&mut T)->Usually<XYWH<T::Unit>>> (draw: F) -> Thunk<T, F> {
|
pub const fn thunk <T: Screen, F: FnOnce(&mut T)->Usually<XYWH<T::Unit>>> (draw: F) -> Thunk<T, F> {
|
||||||
|
|
@ -48,7 +57,6 @@ pub struct Thunk<T: Screen, F: FnOnce(&mut T)->Usually<XYWH<T::Unit>>>(
|
||||||
pub F,
|
pub F,
|
||||||
std::marker::PhantomData<T>
|
std::marker::PhantomData<T>
|
||||||
);
|
);
|
||||||
|
|
||||||
impl<T: Screen, F: FnOnce(&mut T)->Usually<XYWH<T::Unit>>> Draw<T> for Thunk<T, F> {
|
impl<T: Screen, F: FnOnce(&mut T)->Usually<XYWH<T::Unit>>> Draw<T> for Thunk<T, F> {
|
||||||
fn draw (self, to: &mut T) -> Usually<XYWH<T::Unit>> {
|
fn draw (self, to: &mut T) -> Usually<XYWH<T::Unit>> {
|
||||||
(self.0)(to)
|
(self.0)(to)
|
||||||
|
|
@ -111,14 +119,3 @@ pub trait Screen: Space<Self::Unit> + Send + Sync + Sized {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Emit a [Draw]able.
|
|
||||||
pub trait View<T: Screen> {
|
|
||||||
fn view (&self) -> impl Draw<T>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Screen, V: View<T>> Draw<T> for &V {
|
|
||||||
fn draw (self, to: &mut T) -> Usually<XYWH<T::Unit>> {
|
|
||||||
self.view().draw(to)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -8,3 +8,10 @@ impl Exit {
|
||||||
run(Self(Arc::new(AtomicBool::new(false))))
|
run(Self(Arc::new(AtomicBool::new(false))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsRef<Arc<AtomicBool>> for Exit {
|
||||||
|
fn as_ref (&self) -> &Arc<AtomicBool> {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,13 @@ use crate::task::Task;
|
||||||
|
|
||||||
use ::std::sync::{Arc, RwLock, atomic::{AtomicBool, Ordering::*}};
|
use ::std::sync::{Arc, RwLock, atomic::{AtomicBool, Ordering::*}};
|
||||||
use ::std::time::Duration;
|
use ::std::time::Duration;
|
||||||
use ::dizzle::{Usually, Do, impl_from};
|
use ::dizzle::{Usually, Apply, impl_from};
|
||||||
use ::crossterm::event::{
|
use ::crossterm::event::{
|
||||||
read, Event, KeyEvent, KeyCode, KeyModifiers, KeyEventKind, KeyEventState
|
read, Event, KeyEvent, KeyCode, KeyModifiers, KeyEventKind, KeyEventState
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Spawn the TUI input thread which reads keys from the terminal.
|
/// Spawn the TUI input thread which reads keys from the terminal.
|
||||||
pub fn tui_input <T: Do<TuiEvent, Usually<T>> + Send + Sync + 'static> (
|
pub fn tui_input <T: Apply<TuiEvent, Usually<T>> + Send + Sync + 'static> (
|
||||||
exited: &Arc<AtomicBool>, state: &Arc<RwLock<T>>, poll: Duration
|
exited: &Arc<AtomicBool>, state: &Arc<RwLock<T>>, poll: Duration
|
||||||
) -> Result<Task, std::io::Error> {
|
) -> Result<Task, std::io::Error> {
|
||||||
let exited = exited.clone();
|
let exited = exited.clone();
|
||||||
|
|
|
||||||
97
src/space.rs
97
src/space.rs
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::{*, draw::*};
|
use crate::{*, draw::*};
|
||||||
|
#[cfg(test)] use proptest_derive::Arbitrary;
|
||||||
|
|
||||||
/// Point with size.
|
/// Point with size.
|
||||||
///
|
///
|
||||||
|
|
@ -423,22 +424,26 @@ pub const fn w_full <T: Screen> (a: impl Draw<T>) -> impl Draw<T> { a }
|
||||||
pub const fn h_full <T: Screen> (a: impl Draw<T>) -> impl Draw<T> { a }
|
pub const fn h_full <T: Screen> (a: impl Draw<T>) -> impl Draw<T> { a }
|
||||||
|
|
||||||
#[macro_export] macro_rules! north {
|
#[macro_export] macro_rules! north {
|
||||||
($($tt:tt)*) => { unimplemented!() };
|
($head:expr $(,)?) => { $head };
|
||||||
|
($head:expr, $($tail:expr),* $(,)?) => { north($head, north!($($tail,)*)) };
|
||||||
}
|
}
|
||||||
#[macro_export] macro_rules! south {
|
#[macro_export] macro_rules! south {
|
||||||
($($tt:tt)*) => { unimplemented!() };
|
($head:expr $(,)?) => { $head };
|
||||||
|
($head:expr, $($tail:expr),* $(,)?) => { south($head, south!($($tail,)*)) };
|
||||||
}
|
}
|
||||||
#[macro_export] macro_rules! east {
|
#[macro_export] macro_rules! east {
|
||||||
($($tt:tt)*) => { unimplemented!() };
|
($head:expr $(,)?) => { $head };
|
||||||
|
($head:expr, $($tail:expr),* $(,)?) => { east($head, east!($($tail,)*)) };
|
||||||
}
|
}
|
||||||
#[macro_export] macro_rules! west {
|
#[macro_export] macro_rules! west {
|
||||||
($($tt:tt)*) => { unimplemented!() };
|
($head:expr $(, $tail:expr)* $(,)?) => { west($head, west!($($tail,)*)) };
|
||||||
}
|
}
|
||||||
#[macro_export] macro_rules! above {
|
#[macro_export] macro_rules! above {
|
||||||
($($tt:tt)*) => { unimplemented!() };
|
($head:expr $(, $tail:expr)* $(,)?) => { above($head, above!($($tail,)*)) };
|
||||||
}
|
}
|
||||||
#[macro_export] macro_rules! below {
|
#[macro_export] macro_rules! below {
|
||||||
($($tt:tt)*) => { unimplemented!() };
|
($head:expr $(,)?) => { $head };
|
||||||
|
($head:expr, $($tail:expr),* $(,)?) => { below($head, below!($($tail,)*)) };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over a collection of renderables:
|
/// Iterate over a collection of renderables:
|
||||||
|
|
@ -452,42 +457,56 @@ pub const fn h_full <T: Screen> (a: impl Draw<T>) -> impl Draw<T> { a }
|
||||||
/// ].iter(), |x|x);
|
/// ].iter(), |x|x);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn iter <
|
pub fn iter <
|
||||||
T: Screen,
|
S: Screen,
|
||||||
|
D: Draw<S>,
|
||||||
V: Fn()->I,
|
V: Fn()->I,
|
||||||
I: Iterator<Item = dyn Draw<T>>,
|
I: Iterator<Item = D>,
|
||||||
F: Fn(&dyn Draw<T>)->dyn Draw<T>,
|
F: Fn(&D)->dyn Draw<S>,
|
||||||
> (_items: V, _cb: F) -> impl Draw<T> {
|
> (_items: V, _cb: F) -> impl Draw<S> {
|
||||||
thunk(move|_to: &mut T|{ todo!() })
|
thunk(move|_to: &mut S|{ todo!() })
|
||||||
}
|
}
|
||||||
pub fn iter_north <
|
|
||||||
T: Screen,
|
pub fn iter_north <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<S>> (
|
||||||
V: Fn()->I,
|
_iter: impl Fn()->I, _draw: impl Fn(D)->U,
|
||||||
I: Iterator<Item = dyn Draw<T>>,
|
) -> impl Draw<S> {
|
||||||
F: Fn(&dyn Draw<T>)->dyn Draw<T>,
|
thunk(move|_to: &mut S|{ todo!() })
|
||||||
> (_items: V, _cb: F) -> impl Draw<T> {
|
|
||||||
thunk(move|_to: &mut T|{ todo!() })
|
|
||||||
}
|
}
|
||||||
pub fn iter_east <
|
|
||||||
T: Screen,
|
pub fn iter_east <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<S>> (
|
||||||
V: Fn()->I,
|
_iter: impl Fn()->I, _draw: impl Fn(D)->U,
|
||||||
I: Iterator<Item = dyn Draw<T>>,
|
) -> impl Draw<S> {
|
||||||
F: Fn(&dyn Draw<T>)->dyn Draw<T>,
|
thunk(move|_to: &mut S|{ todo!() })
|
||||||
> (_items: V, _cb: F) -> impl Draw<T> {
|
|
||||||
thunk(move|_to: &mut T|{ todo!() })
|
|
||||||
}
|
}
|
||||||
pub fn iter_south <
|
|
||||||
T: Screen,
|
pub fn iter_south <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<S>> (
|
||||||
V: Fn()->I,
|
_iter: impl Fn()->I, _draw: impl Fn(D)->U,
|
||||||
I: Iterator<Item = dyn Draw<T>>,
|
) -> impl Draw<S> {
|
||||||
F: Fn(&dyn Draw<T>)->dyn Draw<T>,
|
thunk(move|_to: &mut S|{ todo!() })
|
||||||
> (_items: V, _cb: F) -> impl Draw<T> {
|
|
||||||
thunk(move|_to: &mut T|{ todo!() })
|
|
||||||
}
|
}
|
||||||
pub fn iter_west <
|
|
||||||
T: Screen,
|
pub fn iter_west <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<S>> (
|
||||||
V: Fn()->I,
|
_iter: impl Fn()->I, _draw: impl Fn(D)->U,
|
||||||
I: Iterator<Item = dyn Draw<T>>,
|
) -> impl Draw<S> {
|
||||||
F: Fn(&dyn Draw<T>)->dyn Draw<T>,
|
thunk(move|_to: &mut S|{ todo!() })
|
||||||
> (_items: V, _cb: F) -> impl Draw<T> {
|
}
|
||||||
thunk(move|_to: &mut T|{ todo!() })
|
|
||||||
|
#[derive(Default, Debug)]
|
||||||
|
pub struct Size(AtomicUsize, AtomicUsize);
|
||||||
|
impl X<u16> for Size {
|
||||||
|
fn x (&self) -> u16 { 0 }
|
||||||
|
fn w (&self) -> u16 { self.0.load(Relaxed) as u16 }
|
||||||
|
}
|
||||||
|
impl Y<u16> for Size {
|
||||||
|
fn y (&self) -> u16 { 0 }
|
||||||
|
fn h (&self) -> u16 { self.1.load(Relaxed) as u16 }
|
||||||
|
}
|
||||||
|
impl Size {
|
||||||
|
pub const fn of <T: Screen> (&self, of: impl Draw<T>) -> impl Draw<T> {
|
||||||
|
thunk(move|to: &mut T|{
|
||||||
|
let area = of.draw(to)?;
|
||||||
|
self.0.store(area.w().into(), Relaxed);
|
||||||
|
self.1.store(area.h().into(), Relaxed);
|
||||||
|
Ok(area)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
17
src/term.rs
17
src/term.rs
|
|
@ -21,6 +21,23 @@ use ::{
|
||||||
event::{poll, read, Event, KeyEvent, KeyCode, KeyModifiers, KeyEventKind, KeyEventState},
|
event::{poll, read, Event, KeyEvent, KeyCode, KeyModifiers, KeyEventKind, KeyEventState},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
#[macro_export] macro_rules! tui_main {
|
||||||
|
($state:expr) => {
|
||||||
|
pub fn main () -> Usually<()> {
|
||||||
|
tengri::exit::Exit::run(|exit|{
|
||||||
|
let state = Arc::new(RwLock::new($state));
|
||||||
|
Ok((
|
||||||
|
::tengri::keys::tui_input(
|
||||||
|
exit.as_ref(), &state, std::time::Duration::from_millis(100)
|
||||||
|
)?,
|
||||||
|
::tengri::term::tui_output(
|
||||||
|
stdout(), exit.as_ref(), &state, std::time::Duration::from_millis(10)
|
||||||
|
)?
|
||||||
|
))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
pub struct Tui(pub Buffer, pub XYWH<u16>);
|
pub struct Tui(pub Buffer, pub XYWH<u16>);
|
||||||
impl Screen for Tui { type Unit = u16; }
|
impl Screen for Tui { type Unit = u16; }
|
||||||
impl Deref for Tui { type Target = Buffer; fn deref (&self) -> &Buffer { &self.0 } }
|
impl Deref for Tui { type Target = Buffer; fn deref (&self) -> &Buffer { &self.0 } }
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,6 @@ pub(crate) use ::unicode_width::*;
|
||||||
self.as_str().draw(to)
|
self.as_str().draw(to)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Draw<Tui> for std::sync::Arc<str> {
|
|
||||||
fn draw (self, to: &mut Tui) -> Usually<XYWH<u16>> {
|
|
||||||
self.as_ref().draw(to)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl Draw<Tui> for &std::sync::Arc<str> {
|
impl Draw<Tui> for &std::sync::Arc<str> {
|
||||||
fn draw (self, to: &mut Tui) -> Usually<XYWH<u16>> {
|
fn draw (self, to: &mut Tui) -> Usually<XYWH<u16>> {
|
||||||
self.as_ref().draw(to)
|
self.as_ref().draw(to)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue