mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2026-09-18 13:26:42 +02:00
Compare commits
No commits in common. "94c26f06ccf77bfd6dbe55665f58e87d0b0b2216" and "8b24b052caac078f6d0a9d8fde1afa1fbd3b3f56" have entirely different histories.
94c26f06cc
...
8b24b052ca
25 changed files with 402 additions and 565 deletions
14
Justfile
14
Justfile
|
|
@ -29,9 +29,11 @@ doc:
|
|||
CARGO_INCREMENTAL=0 RUSTFLAGS='-Cinstrument-coverage' RUSTDOCFLAGS='-Cinstrument-coverage' \
|
||||
cargo doc
|
||||
|
||||
mode-00:
|
||||
cargo run --example mode_00
|
||||
mode-01:
|
||||
cargo run --example mode_01
|
||||
mode-02:
|
||||
cargo run --example mode_02
|
||||
example-tui-00:
|
||||
cargo run --example mode_0
|
||||
|
||||
example-tui-01:
|
||||
cargo run --example mode_1
|
||||
|
||||
example-tui-02:
|
||||
cargo run --example mode_2
|
||||
|
|
|
|||
2
dizzle
2
dizzle
|
|
@ -1 +1 @@
|
|||
Subproject commit 0f06571f7fc7e5f87aadb82d531726d24bf769e8
|
||||
Subproject commit 4424ef7fc3fd8bfbea1fb55b4922f7a8cfd2a8ef
|
||||
|
|
@ -1,37 +1,3 @@
|
|||
//! Mode 00: Direct draw, direct control
|
||||
|
||||
use ::std::sync::{Arc, RwLock};
|
||||
use ::crossterm::event::{Event::*, KeyEvent, KeyCode::*};
|
||||
use ::ratatui::style::Color;
|
||||
use ::tengri::{*, lang::*};
|
||||
|
||||
tui_app!(State {
|
||||
/** User-controllable value. */
|
||||
cursor: usize,
|
||||
});
|
||||
|
||||
tui_view!(self: State {
|
||||
thunk(|to: &mut Tui|{
|
||||
let cursor = format!("Cursor: {}", self.cursor);
|
||||
let _ = "DEMO [MODE 00]".align_sw().draw(to);
|
||||
let _ = ShowSize.align_se().draw(to);
|
||||
let _ = format!("Cursor: {}", self.cursor).align_c().draw(to);
|
||||
Ok(Some(to.area()))
|
||||
})
|
||||
});
|
||||
|
||||
tui_keys!(self: State, input {
|
||||
Ok(if let Key(KeyEvent { code, .. }) = input.0 {
|
||||
match code {
|
||||
Up | Right => {
|
||||
self.cursor = (self.cursor + 1) % 10;
|
||||
()
|
||||
},
|
||||
Down | Left => {
|
||||
self.cursor = if self.cursor > 0 { self.cursor - 1 } else { 10 - 1 };
|
||||
()
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
})
|
||||
});
|
||||
//! Mode 0: Direct draw
|
||||
use ::{std::sync::{Arc, RwLock}, ratatui::style::Color, tengri::*};
|
||||
fn main () {}
|
||||
|
|
|
|||
|
|
@ -1,63 +1,153 @@
|
|||
//! Mode 01: Direct view, actions with history
|
||||
|
||||
//! Mode 01
|
||||
use ::std::sync::{Arc, RwLock};
|
||||
use ::crossterm::event::{Event::*, KeyEvent, KeyCode::*};
|
||||
use ::ratatui::style::Color;
|
||||
use ::tengri::{*, lang::*};
|
||||
use itertools::Itertools;
|
||||
|
||||
tui_app!(State {
|
||||
/** Command history (undo/redo). */
|
||||
history: Vec<Action>,
|
||||
/** User-controllable value. */
|
||||
cursor: usize,
|
||||
/** Rendered window size. */
|
||||
size: Sizer,
|
||||
});
|
||||
|
||||
tui_keys!(self: State, input {
|
||||
Ok(if let Key(KeyEvent { code, .. }) = input.0 {
|
||||
match code {
|
||||
Down | Right => Action::Next,
|
||||
Up | Left => Action::Prev,
|
||||
_ => { return Ok(()) }
|
||||
Up | Right => { self.next()?.map(|x|self.history.push(x)); },
|
||||
Down | Left => { self.prev()?.map(|x|self.history.push(x)); },
|
||||
_ => {}
|
||||
}
|
||||
.apply(self)?
|
||||
.map(|x|self.history.push(x));
|
||||
})
|
||||
});
|
||||
|
||||
tui_view!(self: State {
|
||||
let title = "Demo Mode 00";
|
||||
let items = self.history.iter().take(10).map(|x|format!("{x:?}")).join("\n");
|
||||
let history = format!("History: {}\n{items}", self.history.len());
|
||||
let cursor = format!("Cursor: {}", self.cursor);
|
||||
north(
|
||||
east(title.align_sw(), ShowSize.align_se()),
|
||||
east(history.align_c(), cursor.align_c()),
|
||||
)
|
||||
let index = self.cursor + 1;
|
||||
let wh = (self.size.w(), self.size.h());
|
||||
let src = VIEWS.get(self.cursor).unwrap_or(&"");
|
||||
let heading = format!("State {}/{} in {:?}", index, VIEWS.len(), &wh);
|
||||
let title = bg(Color::Rgb(60, 10, 10), heading.align_n().push_y(1));
|
||||
let code = bg(Color::Rgb(10, 60, 10), format!("{}", src).align_n().push_y(2));
|
||||
let widget = thunk(move|to: &mut Tui|self.interpret(to, &src));
|
||||
self.size.of(south(title, north(code, widget)))
|
||||
});
|
||||
|
||||
#[derive(Debug)] enum Action {
|
||||
/** Increment cursor */ Next,
|
||||
/** Decrement cursor */ Prev,
|
||||
}
|
||||
|
||||
impl Action {
|
||||
fn apply (&self, state: &mut State) -> Perhaps<Self> {
|
||||
use Action::*;
|
||||
match self {
|
||||
Next => state.next(),
|
||||
Prev => state.prev(),
|
||||
impl Interpret<Tui, Color> for State {
|
||||
fn interpret_expr (&self, to: &mut Tui, expr: &impl Language) -> Usually<Color> {
|
||||
let expr = expr.expr()?;
|
||||
match expr.head()? {
|
||||
Some("g") if let Some(tail) = expr.tail()? => {
|
||||
Color::new_g(tail.head()?, try_to_u8)
|
||||
},
|
||||
Some("rgb") if let Some(tail) = expr.tail()? => {
|
||||
Color::new_rgb(tail.head()?)
|
||||
},
|
||||
_ => Err(format!("not a color").into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Interpret<Tui, Option<XYWH<u16>>> for State {
|
||||
fn interpret_word (&self, to: &mut Tui, sym: &impl Language) -> Perhaps<XYWH<u16>> {
|
||||
match sym.src()? {
|
||||
Some(":foo") => "foo".draw(to),
|
||||
Some(":bar") => "bar".draw(to),
|
||||
Some(":foobar") => "FOOBAR".draw(to),
|
||||
_ => todo!()
|
||||
}
|
||||
}
|
||||
fn interpret_expr (&self, to: &mut Tui, src: &impl Expression) -> Perhaps<XYWH<u16>> {
|
||||
Ok(Some(if let Some(area) = eval_view(self, to, src)? {
|
||||
area
|
||||
} else if let Some(area) = eval_view_tui(self, to, src)? {
|
||||
area
|
||||
} else {
|
||||
return Err(format!("App::interpret_expr: unexpected: {src:?}").into())
|
||||
}))
|
||||
}
|
||||
}
|
||||
impl State {
|
||||
fn next (&mut self) -> Perhaps<Action> {
|
||||
self.cursor = (self.cursor + 1) % 10;
|
||||
self.cursor = (self.cursor + 1) % VIEWS.len();
|
||||
Ok(Some(Action::Prev))
|
||||
}
|
||||
fn prev (&mut self) -> Perhaps<Action> {
|
||||
self.cursor = if self.cursor > 0 { self.cursor - 1 } else { 10 - 1 };
|
||||
self.cursor = if self.cursor > 0 { self.cursor - 1 } else { VIEWS.len() - 1 };
|
||||
Ok(Some(Action::Next))
|
||||
}
|
||||
}
|
||||
#[derive(Debug)]
|
||||
enum Action {
|
||||
/** Increment cursor */ Next,
|
||||
/** Decrement cursor */ Prev,
|
||||
}
|
||||
impl Action {
|
||||
fn eval (&self, state: &mut State) -> Perhaps<Self> {
|
||||
use Action::*;
|
||||
match self { Next => state.next(), Prev => state.prev(), }
|
||||
}
|
||||
}
|
||||
const VIEWS: &'static [&'static str] = &[
|
||||
stringify! { :foobar },
|
||||
stringify! { (bg (g 8) :foobar) },
|
||||
stringify! { (fill/xy :foobar) },
|
||||
stringify! { (bsp/s :foo :bar) },
|
||||
stringify! { (fixed/xy 20 10 :foobar) },
|
||||
stringify! { (bsp/s (fixed/xy 5 6 :foo) (fixed/xy 7 8 :bar)) },
|
||||
stringify! { (bsp/e (fixed/xy 5 6 :foo) (fixed/xy 7 8 :bar)) },
|
||||
stringify! { (bsp/n (fixed/xy 5 6 :foo) (fixed/xy 7 8 :bar)) },
|
||||
stringify! { (bsp/w (fixed/xy 5 6 :foo) (fixed/xy 7 8 :bar)) },
|
||||
stringify! { (bsp/a (fixed/xy 5 6 :foo) (fixed/xy 7 8 :bar)) },
|
||||
stringify! { (bsp/b (fixed/xy 5 6 :foo) (fixed/xy 7 8 :bar)) },
|
||||
stringify! {
|
||||
(bsp/s
|
||||
(bsp/e (align/nw (fixed/xy 5 3 :foo))
|
||||
(bsp/e (align/n (fixed/xy 5 3 :foo))
|
||||
(align/ne (fixed/xy 5 3 :foo))))
|
||||
(bsp/s
|
||||
(bsp/e (align/w (fixed/xy 5 3 :foo))
|
||||
(bsp/e (align/c (fixed/xy 5 3 :foo))
|
||||
(align/e (fixed/xy 5 3 :foo))))
|
||||
(bsp/e (align/sw (fixed/xy 5 3 :foo))
|
||||
(bsp/e (align/s (fixed/xy 5 3 :foo))
|
||||
(align/se (fixed/xy 5 3 :foo))))))
|
||||
},
|
||||
stringify! {
|
||||
(bsp/s
|
||||
(bsp/e (fixed/xy 8 5 (align/nw :foo))
|
||||
(bsp/e (fixed/xy 8 5 (align/n :foo))
|
||||
(fixed/xy 8 5 (align/ne :foo))))
|
||||
(bsp/s
|
||||
(bsp/e (fixed/xy 8 5 (align/w :foo))
|
||||
(bsp/e (fixed/xy 8 5 (align/c :foo))
|
||||
(fixed/xy 8 5 (align/e :foo))))
|
||||
(bsp/e (fixed/xy 8 5 (align/sw :foo))
|
||||
(bsp/e (fixed/xy 8 5 (align/s :foo))
|
||||
(fixed/xy 8 5 (align/se :foo))))))
|
||||
},
|
||||
stringify! {
|
||||
(bsp/s
|
||||
(bsp/e (grow/xy 1 1 (fixed/xy 8 5 (align/nw :foo)))
|
||||
(bsp/e (grow/xy 1 1 (fixed/xy 8 5 (align/n :foo)))
|
||||
(grow/xy 1 1 (fixed/xy 8 5 (align/ne :foo)))))
|
||||
(bsp/s
|
||||
(bsp/e (grow/xy 1 1 (fixed/xy 8 5 (align/w :foo)))
|
||||
(bsp/e (grow/xy 1 1 (fixed/xy 8 5 (align/c :foo)))
|
||||
(grow/xy 1 1 (fixed/xy 8 5 (align/e :foo)))))
|
||||
(bsp/e (grow/xy 1 1 (fixed/xy 8 5 (align/sw :foo)))
|
||||
(bsp/e (grow/xy 1 1 (fixed/xy 8 5 (align/s :foo)))
|
||||
(grow/xy 1 1 (fixed/xy 8 5 (align/se :foo)))))))
|
||||
},
|
||||
stringify! { :map-e },
|
||||
stringify! { (align/c :map-e) },
|
||||
stringify! { :map-s },
|
||||
stringify! { (align/c :map-s) },
|
||||
stringify! {
|
||||
(align/c (bg/behind :bg0 (margin/xy 1 1 (col
|
||||
(bg/behind :bg1 (border/around :border1 (margin/xy 2 1 :label1)))
|
||||
(bg/behind :bg2 (border/around :border2 (margin/xy 4 2 :label2)))
|
||||
(bg/behind :bg3 (border/around :border3 (margin/xy 6 3 :label3)))))))
|
||||
},
|
||||
];
|
||||
//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 ]);
|
||||
//impl_from!(Action: |input: &TuiIn| todo!());
|
||||
//fn draw_example (state: &State, to: &mut Tui) {}
|
||||
|
|
|
|||
|
|
@ -1,162 +1,107 @@
|
|||
//! Mode 02: Inline Dizzle config
|
||||
//! Mode 02
|
||||
use ::{std::sync::{Arc, RwLock}, ratatui::style::Color, tengri::*};
|
||||
fn main () {}
|
||||
|
||||
use ::std::sync::{Arc, RwLock};
|
||||
use ::crossterm::event::{Event::*, KeyEvent, KeyCode::*};
|
||||
use ::ratatui::style::Color;
|
||||
use ::tengri::{*, lang::*};
|
||||
tui_app!(State {
|
||||
/** Command history (undo/redo). */
|
||||
history: Vec<Action>,
|
||||
/** User-controllable value. */
|
||||
cursor: usize,
|
||||
/** Rendered window size. */
|
||||
size: Sizer,
|
||||
});
|
||||
tui_keys!(self: State, input {
|
||||
Ok(if let Key(KeyEvent { code, .. }) = input.0 {
|
||||
match code {
|
||||
Up | Right => { self.next()?.map(|x|self.history.push(x)); },
|
||||
Down | Left => { self.prev()?.map(|x|self.history.push(x)); },
|
||||
_ => {}
|
||||
}
|
||||
})
|
||||
});
|
||||
tui_view!(self: State {
|
||||
let index = self.cursor + 1;
|
||||
let wh = (self.size.w(), self.size.h());
|
||||
let src = VIEWS.get(self.cursor).unwrap_or(&"");
|
||||
let heading = format!("State {}/{} in {:?}", index, VIEWS.len(), &wh);
|
||||
let title = bg(Color::Rgb(60, 10, 10), heading.align_n().push_y(1));
|
||||
let code = bg(Color::Rgb(10, 60, 10), format!("{}", src).align_n().push_y(2));
|
||||
let widget = thunk(move|to: &mut Tui|self.interpret(to, &src));
|
||||
self.size.of(south(title, north(code, widget)))
|
||||
});
|
||||
impl Interpret<Tui, Color> for State {
|
||||
fn interpret_expr (&self, to: &mut Tui, expr: &impl Language) -> Usually<Color> {
|
||||
let expr = expr.expr()?;
|
||||
match expr.head()? {
|
||||
Some("g") if let Some(tail) = expr.tail()? => {
|
||||
Color::new_g(tail.head()?, try_to_u8)
|
||||
},
|
||||
Some("rgb") if let Some(tail) = expr.tail()? => {
|
||||
Color::new_rgb(tail.head()?, try_to_u8)
|
||||
},
|
||||
_ => Err(format!("not a color").into())
|
||||
}
|
||||
}
|
||||
}
|
||||
fn try_to_u8 (src: Perhaps<&str>) -> Perhaps<u8> {
|
||||
use std::str::FromStr;
|
||||
if let Some(src) = src? {
|
||||
Ok(Some(u8::from_str(src)?))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
impl Interpret<Tui, Option<XYWH<u16>>> for State {
|
||||
fn interpret_word (&self, to: &mut Tui, sym: &impl Language) -> Perhaps<XYWH<u16>> {
|
||||
match sym.src()? {
|
||||
Some(":foo") => "foo".draw(to),
|
||||
Some(":bar") => "bar".draw(to),
|
||||
Some(":foobar") => "FOOBAR".draw(to),
|
||||
_ => todo!()
|
||||
}
|
||||
}
|
||||
fn interpret_expr (&self, to: &mut Tui, src: &impl Expression) -> Perhaps<XYWH<u16>> {
|
||||
Ok(Some(if let Some(area) = eval_view(self, to, src)? {
|
||||
area
|
||||
} else if let Some(area) = eval_view_tui(self, to, src)? {
|
||||
area
|
||||
} else {
|
||||
return Err(format!("App::interpret_expr: unexpected: {src:?}").into())
|
||||
}))
|
||||
}
|
||||
}
|
||||
impl State {
|
||||
fn next (&mut self) -> Perhaps<Action> {
|
||||
self.cursor = (self.cursor + 1) % VIEWS.len();
|
||||
Ok(Some(Action::Prev))
|
||||
}
|
||||
fn prev (&mut self) -> Perhaps<Action> {
|
||||
self.cursor = if self.cursor > 0 { self.cursor - 1 } else { VIEWS.len() - 1 };
|
||||
Ok(Some(Action::Next))
|
||||
}
|
||||
}
|
||||
#[derive(Debug)]
|
||||
enum Action {
|
||||
/** Increment cursor */ Next,
|
||||
/** Decrement cursor */ Prev,
|
||||
}
|
||||
impl Action {
|
||||
fn eval (&self, state: &mut State) -> Perhaps<Self> {
|
||||
use Action::*;
|
||||
match self { Next => state.next(), Prev => state.prev(), }
|
||||
}
|
||||
}
|
||||
const VIEWS: &'static [&'static str] = &[
|
||||
stringify! { :foobar },
|
||||
stringify! { (bg (g 8) :foobar) },
|
||||
stringify! { (fill/xy :foobar) },
|
||||
stringify! { (bsp/s :foo :bar) },
|
||||
stringify! { (fixed/xy 20 10 :foobar) },
|
||||
stringify! { (bsp/s (fixed/xy 5 6 :foo) (fixed/xy 7 8 :bar)) },
|
||||
stringify! { (bsp/e (fixed/xy 5 6 :foo) (fixed/xy 7 8 :bar)) },
|
||||
stringify! { (bsp/n (fixed/xy 5 6 :foo) (fixed/xy 7 8 :bar)) },
|
||||
stringify! { (bsp/w (fixed/xy 5 6 :foo) (fixed/xy 7 8 :bar)) },
|
||||
stringify! { (bsp/a (fixed/xy 5 6 :foo) (fixed/xy 7 8 :bar)) },
|
||||
stringify! { (bsp/b (fixed/xy 5 6 :foo) (fixed/xy 7 8 :bar)) },
|
||||
stringify! {
|
||||
(bsp/s
|
||||
(bsp/e (align/nw (fixed/xy 5 3 :foo))
|
||||
(bsp/e (align/n (fixed/xy 5 3 :foo))
|
||||
(align/ne (fixed/xy 5 3 :foo))))
|
||||
(bsp/s
|
||||
(bsp/e (align/w (fixed/xy 5 3 :foo))
|
||||
(bsp/e (align/c (fixed/xy 5 3 :foo))
|
||||
(align/e (fixed/xy 5 3 :foo))))
|
||||
(bsp/e (align/sw (fixed/xy 5 3 :foo))
|
||||
(bsp/e (align/s (fixed/xy 5 3 :foo))
|
||||
(align/se (fixed/xy 5 3 :foo))))))
|
||||
},
|
||||
stringify! {
|
||||
(bsp/s
|
||||
(bsp/e (fixed/xy 8 5 (align/nw :foo))
|
||||
(bsp/e (fixed/xy 8 5 (align/n :foo))
|
||||
(fixed/xy 8 5 (align/ne :foo))))
|
||||
(bsp/s
|
||||
(bsp/e (fixed/xy 8 5 (align/w :foo))
|
||||
(bsp/e (fixed/xy 8 5 (align/c :foo))
|
||||
(fixed/xy 8 5 (align/e :foo))))
|
||||
(bsp/e (fixed/xy 8 5 (align/sw :foo))
|
||||
(bsp/e (fixed/xy 8 5 (align/s :foo))
|
||||
(fixed/xy 8 5 (align/se :foo))))))
|
||||
},
|
||||
stringify! {
|
||||
(bsp/s
|
||||
(bsp/e (grow/xy 1 1 (fixed/xy 8 5 (align/nw :foo)))
|
||||
(bsp/e (grow/xy 1 1 (fixed/xy 8 5 (align/n :foo)))
|
||||
(grow/xy 1 1 (fixed/xy 8 5 (align/ne :foo)))))
|
||||
(bsp/s
|
||||
(bsp/e (grow/xy 1 1 (fixed/xy 8 5 (align/w :foo)))
|
||||
(bsp/e (grow/xy 1 1 (fixed/xy 8 5 (align/c :foo)))
|
||||
(grow/xy 1 1 (fixed/xy 8 5 (align/e :foo)))))
|
||||
(bsp/e (grow/xy 1 1 (fixed/xy 8 5 (align/sw :foo)))
|
||||
(bsp/e (grow/xy 1 1 (fixed/xy 8 5 (align/s :foo)))
|
||||
(grow/xy 1 1 (fixed/xy 8 5 (align/se :foo)))))))
|
||||
},
|
||||
stringify! { :map-e },
|
||||
stringify! { (align/c :map-e) },
|
||||
stringify! { :map-s },
|
||||
stringify! { (align/c :map-s) },
|
||||
stringify! {
|
||||
(align/c (bg/behind :bg0 (margin/xy 1 1 (col
|
||||
(bg/behind :bg1 (border/around :border1 (margin/xy 2 1 :label1)))
|
||||
(bg/behind :bg2 (border/around :border2 (margin/xy 4 2 :label2)))
|
||||
(bg/behind :bg3 (border/around :border3 (margin/xy 6 3 :label3)))))))
|
||||
},
|
||||
];
|
||||
//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 ]);
|
||||
//impl_from!(Action: |input: &TuiIn| todo!());
|
||||
//fn draw_example (state: &State, to: &mut Tui) {}
|
||||
//#[tengri_proc::expose]
|
||||
//impl Example {
|
||||
//fn _todo_u16_stub (&self) -> u16 { todo!() }
|
||||
//fn _todo_bool_stub (&self) -> bool { todo!() }
|
||||
//fn _todo_usize_stub (&self) -> usize { todo!() }
|
||||
////[bool] => {}
|
||||
////[u16] => {}
|
||||
////[usize] => {}
|
||||
//}
|
||||
|
||||
//#[tengri_proc::view(TuiOut)]
|
||||
//impl Example {
|
||||
//pub fn title (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
//Tui::bg(Color::Rgb(60, 10, 10), Push::y(1, Align::n(format!("Example {}/{}:", self.0 + 1, VIEWS.len())))).boxed()
|
||||
//}
|
||||
//pub fn code (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
//Tui::bg(Color::Rgb(10, 60, 10), Push::y(2, Align::n(format!("{}", VIEWS[self.0])))).boxed()
|
||||
//}
|
||||
//pub fn hello (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
//Tui::bg(Color::Rgb(10, 100, 10), "Hello").boxed()
|
||||
//}
|
||||
//pub fn world (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
//Tui::bg(Color::Rgb(100, 10, 10), "world").boxed()
|
||||
//}
|
||||
//pub fn hello_world (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
//"Hello world!".boxed()
|
||||
//}
|
||||
//pub fn map_e (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
//Map::east(5u16, ||0..5u16, |n, _i|format!("{n}")).boxed()
|
||||
//}
|
||||
//pub fn map_s (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
//Map::south(5u16, ||0..5u16, |n, _i|format!("{n}")).boxed()
|
||||
//}
|
||||
//}
|
||||
|
||||
//fn content (&self) -> dyn Draw<Engine = Tui> {
|
||||
//let border_style = Style::default().fg(Color::Rgb(0,0,0));
|
||||
//Align::Center(Layers::new(move|add|{
|
||||
|
||||
//add(&Background(Color::Rgb(0,128,128)))?;
|
||||
|
||||
//add(&Margin::XY(1, 1, Stack::down(|add|{
|
||||
|
||||
//add(&Layers::new(|add|{
|
||||
//add(&Background(Color::Rgb(128,96,0)))?;
|
||||
//add(&Border(Square(border_style)))?;
|
||||
//add(&Margin::XY(2, 1, "..."))?;
|
||||
//Ok(())
|
||||
//}).debug())?;
|
||||
|
||||
//add(&Layers::new(|add|{
|
||||
//add(&Background(Color::Rgb(128,64,0)))?;
|
||||
//add(&Border(Lozenge(border_style)))?;
|
||||
//add(&Margin::XY(4, 2, "---"))?;
|
||||
//Ok(())
|
||||
//}).debug())?;
|
||||
|
||||
//add(&Layers::new(|add|{
|
||||
//add(&Background(Color::Rgb(96,64,0)))?;
|
||||
//add(&Border(SquareBold(border_style)))?;
|
||||
//add(&Margin::XY(6, 3, "~~~"))?;
|
||||
//Ok(())
|
||||
//}).debug())?;
|
||||
|
||||
//Ok(())
|
||||
//})).debug())?;
|
||||
|
||||
//Ok(())
|
||||
|
||||
//}))
|
||||
////Align::Center(Margin::X(1, Layers::new(|add|{
|
||||
////add(&Background(Color::Rgb(128,0,0)))?;
|
||||
////add(&Stack::down(|add|{
|
||||
////add(&Margin::Y(1, Layers::new(|add|{
|
||||
////add(&Background(Color::Rgb(0,128,0)))?;
|
||||
////add(&Align::Center("12345"))?;
|
||||
////add(&Align::Center("FOO"))
|
||||
////})))?;
|
||||
////add(&Margin::XY(1, 1, Layers::new(|add|{
|
||||
////add(&Align::Center("1234567"))?;
|
||||
////add(&Align::Center("BAR"))?;
|
||||
////add(&Background(Color::Rgb(0,0,128)))
|
||||
////})))
|
||||
////}))
|
||||
////})))
|
||||
|
||||
////Align::Y(Layers::new(|add|{
|
||||
////add(&Background(Color::Rgb(128,0,0)))?;
|
||||
////add(&Margin::X(1, Align::Center(Stack::down(|add|{
|
||||
////add(&Align::X(Margin::Y(1, Layers::new(|add|{
|
||||
////add(&Background(Color::Rgb(0,128,0)))?;
|
||||
////add(&Align::Center("12345"))?;
|
||||
////add(&Align::Center("FOO"))
|
||||
////})))?;
|
||||
////add(&Margin::XY(1, 1, Layers::new(|add|{
|
||||
////add(&Align::Center("1234567"))?;
|
||||
////add(&Align::Center("BAR"))?;
|
||||
////add(&Background(Color::Rgb(0,0,128)))
|
||||
////})))?;
|
||||
////Ok(())
|
||||
////})))))
|
||||
////}))
|
||||
//}
|
||||
|
|
|
|||
|
|
@ -1,108 +0,0 @@
|
|||
//! Mode 03: Hot reloaded Dizzle config
|
||||
|
||||
use ::{std::sync::{Arc, RwLock}, ratatui::style::Color, tengri::*};
|
||||
fn main () {}
|
||||
|
||||
//#[tengri_proc::expose]
|
||||
//impl Example {
|
||||
//fn _todo_u16_stub (&self) -> u16 { todo!() }
|
||||
//fn _todo_bool_stub (&self) -> bool { todo!() }
|
||||
//fn _todo_usize_stub (&self) -> usize { todo!() }
|
||||
////[bool] => {}
|
||||
////[u16] => {}
|
||||
////[usize] => {}
|
||||
//}
|
||||
|
||||
//#[tengri_proc::view(TuiOut)]
|
||||
//impl Example {
|
||||
//pub fn title (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
//Tui::bg(Color::Rgb(60, 10, 10), Push::y(1, Align::n(format!("Example {}/{}:", self.0 + 1, VIEWS.len())))).boxed()
|
||||
//}
|
||||
//pub fn code (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
//Tui::bg(Color::Rgb(10, 60, 10), Push::y(2, Align::n(format!("{}", VIEWS[self.0])))).boxed()
|
||||
//}
|
||||
//pub fn hello (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
//Tui::bg(Color::Rgb(10, 100, 10), "Hello").boxed()
|
||||
//}
|
||||
//pub fn world (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
//Tui::bg(Color::Rgb(100, 10, 10), "world").boxed()
|
||||
//}
|
||||
//pub fn hello_world (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
//"Hello world!".boxed()
|
||||
//}
|
||||
//pub fn map_e (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
//Map::east(5u16, ||0..5u16, |n, _i|format!("{n}")).boxed()
|
||||
//}
|
||||
//pub fn map_s (&self) -> impl Content<TuiOut> + use<'_> {
|
||||
//Map::south(5u16, ||0..5u16, |n, _i|format!("{n}")).boxed()
|
||||
//}
|
||||
//}
|
||||
|
||||
//fn content (&self) -> dyn Draw<Engine = Tui> {
|
||||
//let border_style = Style::default().fg(Color::Rgb(0,0,0));
|
||||
//Align::Center(Layers::new(move|add|{
|
||||
|
||||
//add(&Background(Color::Rgb(0,128,128)))?;
|
||||
|
||||
//add(&Margin::XY(1, 1, Stack::down(|add|{
|
||||
|
||||
//add(&Layers::new(|add|{
|
||||
//add(&Background(Color::Rgb(128,96,0)))?;
|
||||
//add(&Border(Square(border_style)))?;
|
||||
//add(&Margin::XY(2, 1, "..."))?;
|
||||
//Ok(())
|
||||
//}).debug())?;
|
||||
|
||||
//add(&Layers::new(|add|{
|
||||
//add(&Background(Color::Rgb(128,64,0)))?;
|
||||
//add(&Border(Lozenge(border_style)))?;
|
||||
//add(&Margin::XY(4, 2, "---"))?;
|
||||
//Ok(())
|
||||
//}).debug())?;
|
||||
|
||||
//add(&Layers::new(|add|{
|
||||
//add(&Background(Color::Rgb(96,64,0)))?;
|
||||
//add(&Border(SquareBold(border_style)))?;
|
||||
//add(&Margin::XY(6, 3, "~~~"))?;
|
||||
//Ok(())
|
||||
//}).debug())?;
|
||||
|
||||
//Ok(())
|
||||
//})).debug())?;
|
||||
|
||||
//Ok(())
|
||||
|
||||
//}))
|
||||
////Align::Center(Margin::X(1, Layers::new(|add|{
|
||||
////add(&Background(Color::Rgb(128,0,0)))?;
|
||||
////add(&Stack::down(|add|{
|
||||
////add(&Margin::Y(1, Layers::new(|add|{
|
||||
////add(&Background(Color::Rgb(0,128,0)))?;
|
||||
////add(&Align::Center("12345"))?;
|
||||
////add(&Align::Center("FOO"))
|
||||
////})))?;
|
||||
////add(&Margin::XY(1, 1, Layers::new(|add|{
|
||||
////add(&Align::Center("1234567"))?;
|
||||
////add(&Align::Center("BAR"))?;
|
||||
////add(&Background(Color::Rgb(0,0,128)))
|
||||
////})))
|
||||
////}))
|
||||
////})))
|
||||
|
||||
////Align::Y(Layers::new(|add|{
|
||||
////add(&Background(Color::Rgb(128,0,0)))?;
|
||||
////add(&Margin::X(1, Align::Center(Stack::down(|add|{
|
||||
////add(&Align::X(Margin::Y(1, Layers::new(|add|{
|
||||
////add(&Background(Color::Rgb(0,128,0)))?;
|
||||
////add(&Align::Center("12345"))?;
|
||||
////add(&Align::Center("FOO"))
|
||||
////})))?;
|
||||
////add(&Margin::XY(1, 1, Layers::new(|add|{
|
||||
////add(&Align::Center("1234567"))?;
|
||||
////add(&Align::Center("BAR"))?;
|
||||
////add(&Background(Color::Rgb(0,0,128)))
|
||||
////})))?;
|
||||
////Ok(())
|
||||
////})))))
|
||||
////}))
|
||||
//}
|
||||
17
src/draw.rs
17
src/draw.rs
|
|
@ -13,20 +13,16 @@ use crate::*;
|
|||
/// }
|
||||
/// impl Screen for TestOut {
|
||||
/// type Unit = u16;
|
||||
/// fn show (&mut self, _: impl Draw<Self>) -> Perhaps<XYWH<u16>> {
|
||||
/// println!("placed");
|
||||
/// Ok(None)
|
||||
/// }
|
||||
/// fn area (&self) -> XYWH<Self::Unit> {
|
||||
/// Default::default()
|
||||
/// }
|
||||
/// fn show (&mut self, _: impl Draw<Self>) -> Perhaps<XYWH<u16>>
|
||||
/// { println!("placed"); Ok(None) }
|
||||
/// fn area (&self) -> XYWH<Self::Unit>
|
||||
/// { Default::default() }
|
||||
/// fn clip <T> (
|
||||
/// &mut self,
|
||||
/// area: impl Into<Option<XYWH<u16>>>,
|
||||
/// draw: impl FnOnce(&mut Self)->T
|
||||
/// ) -> T {
|
||||
/// draw(self)
|
||||
/// }
|
||||
/// ) -> T
|
||||
/// { draw(self }
|
||||
/// }
|
||||
///
|
||||
/// impl_draw!(|self: String, to: TestOut|{
|
||||
|
|
@ -154,6 +150,7 @@ features! {
|
|||
layout,
|
||||
lrtb,
|
||||
sizer,
|
||||
space,
|
||||
split,
|
||||
thunk,
|
||||
xywh
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ pub trait Coord: Send + Sync + Copy
|
|||
+ From<u16> + Into<u16>
|
||||
+ Into<usize>
|
||||
+ Into<f64>
|
||||
//+ std::iter::Step
|
||||
+ std::iter::Step
|
||||
{
|
||||
/// Zero in own type.
|
||||
fn zero () -> Self { 0.into() }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
#![allow(unused)]
|
||||
|
||||
use crate::*;
|
||||
|
||||
impl<S: Screen, T: Draw<S>> Layout<S> for T {}
|
||||
|
|
@ -160,14 +158,10 @@ pub trait Layout<S: Screen>: Draw<S> + Sized {
|
|||
/// Use whole drawing area along one or both axes.
|
||||
///
|
||||
/// ```
|
||||
/// # fn doctest_layout_full () -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// use tengri::{Layout, Draw, XYWH};
|
||||
/// let area = XYWH(0u16, 0, 80, 25);
|
||||
/// assert_eq!("1".layout(area)?, Some(XYWH(0u16, 0, 1, 1)));
|
||||
/// assert_eq!("1".full_w().layout(area)?, Some(XYWH(0u16, 0, 80, 1)));
|
||||
/// assert_eq!("1".full_h().layout(area)?, Some(XYWH(0u16, 0, 1, 25)));
|
||||
/// assert_eq!("1".full_wh().layout(area)?, Some(XYWH(0u16, 0, 80, 25)));
|
||||
/// # Ok(()) }
|
||||
/// use tengri::Layout;
|
||||
/// let _ = "".full_w();
|
||||
/// let _ = "".full_h();
|
||||
/// let _ = "".full_wh();
|
||||
/// ```
|
||||
pub enum Full<T: Screen, I: Draw<T>> {
|
||||
__(PhantomData<T>),
|
||||
|
|
@ -175,6 +169,7 @@ pub enum Full<T: Screen, I: Draw<T>> {
|
|||
H(I),
|
||||
WH(I),
|
||||
}
|
||||
|
||||
impl_draw!(<T: Screen, I: Draw<T>,>|self: Full<T, I>, to: T|{
|
||||
let XYWH(x0, y0, w0, h0) = to.area();
|
||||
match self {
|
||||
|
|
@ -200,14 +195,10 @@ impl_draw!(<T: Screen, I: Draw<T>,>|self: Full<T, I>, to: T|{
|
|||
/// Move content in the positive direction of one or both axes.
|
||||
///
|
||||
/// ```
|
||||
/// # fn doctest_layout_push () -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// use tengri::{Layout, Draw, XYWH};
|
||||
/// let area = XYWH(0u16, 0, 80, 25);
|
||||
/// assert_eq!("1".layout(area)?, Some(XYWH(0u16, 0, 1, 1)));
|
||||
/// assert_eq!("1".push_x(1).layout(area)?, Some(XYWH(1u16, 0, 1, 1)));
|
||||
/// assert_eq!("1".push_y(1).layout(area)?, Some(XYWH(0u16, 1, 1, 1)));
|
||||
/// assert_eq!("1".push_xy(1, 1).layout(area)?, Some(XYWH(1u16, 1, 1, 1)));
|
||||
/// # Ok(()) }
|
||||
/// use tengri::Layout;
|
||||
/// let _ = "".push_x(1);
|
||||
/// let _ = "".push_y(1);
|
||||
/// let _ = "".push_xy(1, 1);
|
||||
/// ```
|
||||
pub enum Push<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
||||
__(PhantomData<T>),
|
||||
|
|
@ -215,6 +206,7 @@ pub enum Push<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
|||
Y(I, X),
|
||||
XY(I, X, X),
|
||||
}
|
||||
|
||||
impl_draw!(<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>,>|self: Push<T, I, X>, to: T|{
|
||||
match self {
|
||||
Self::__(_) => unreachable!(),
|
||||
|
|
@ -240,14 +232,10 @@ impl_draw!(<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>,>|self: Push<T, I, X
|
|||
/// Move content in the negative direction of one or both axes.
|
||||
///
|
||||
/// ```
|
||||
/// # fn doctest_layout_pull () -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// use tengri::{Layout, Draw, XYWH};
|
||||
/// let area = XYWH(1u16, 1, 80, 25);
|
||||
/// assert_eq!("1".layout(area)?, Some(XYWH(0u16, 0, 1, 1)));
|
||||
/// assert_eq!("1".pull_x(1).layout(area)?, Some(XYWH(0u16, 1, 1, 1)));
|
||||
/// assert_eq!("1".pull_y(1).layout(area)?, Some(XYWH(1u16, 0, 1, 1)));
|
||||
/// assert_eq!("1".pull_xy(1, 1).layout(area)?, Some(XYWH(0u16, 0, 1, 1)));
|
||||
/// # Ok(()) }
|
||||
/// use tengri::Layout;
|
||||
/// let _ = "".pull_x(1);
|
||||
/// let _ = "".pull_y(1);
|
||||
/// let _ = "".pull_xy(1, 1);
|
||||
/// ```
|
||||
pub enum Pull<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
||||
__(PhantomData<T>),
|
||||
|
|
@ -255,6 +243,7 @@ pub enum Pull<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
|||
Y(I, X),
|
||||
XY(I, X, X),
|
||||
}
|
||||
|
||||
impl_draw!(<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>,>|self: Pull<T, I, X>, _to: T|{
|
||||
todo!()
|
||||
});
|
||||
|
|
@ -262,14 +251,10 @@ impl_draw!(<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>,>|self: Pull<T, I, X
|
|||
/// Only draw content if area is above a certain size.
|
||||
///
|
||||
/// ```
|
||||
/// # fn doctest_layout_min () -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// use tengri::{Layout, Draw, XYWH};
|
||||
/// let area = XYWH(1u16, 1, 80, 25);
|
||||
/// assert_eq!("1".min_w(5).layout(area)?, Some(XYWH(1u16, 1, 5, 1)));
|
||||
/// assert_eq!("1".min_h(5).layout(area)?, Some(XYWH(1u16, 1, 1, 5)));
|
||||
/// assert_eq!("1".min_wh(5, 5).layout(area)?, Some(XYWH(1u16, 1, 5, 5)));
|
||||
/// assert_eq!("123456".min_w(5).layout(area)?, Some(XYWH(1u16, 1, 6, 1)));
|
||||
/// # Ok(()) }
|
||||
/// use tengri::Layout;
|
||||
/// let _ = "".min_w(1);
|
||||
/// let _ = "".min_h(1);
|
||||
/// let _ = "".min_wh(1, 1);
|
||||
/// ```
|
||||
pub enum Min<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
||||
__(PhantomData<T>),
|
||||
|
|
@ -277,6 +262,7 @@ pub enum Min<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
|||
H(I, X),
|
||||
WH(I, X, X),
|
||||
}
|
||||
|
||||
impl_draw!(<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>,>|self: Min<T, I, X>, _to: T|{
|
||||
todo!()
|
||||
});
|
||||
|
|
@ -284,13 +270,10 @@ impl_draw!(<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>,>|self: Min<T, I, X>
|
|||
/// Set maximum size of of drawing area.
|
||||
///
|
||||
/// ```
|
||||
/// # fn doctest_layout_max () -> Result<(), Box<dyn std::error::Error>> {
|
||||
/// use tengri::{Layout, Draw, XYWH};
|
||||
/// let area = XYWH(1u16, 1, 80, 25);
|
||||
/// assert_eq!("12345".max_w(1).layout(area)?, Some(XYWH(1u16, 1, 1, 1)));
|
||||
/// assert_eq!("12345".max_h(1).layout(area)?, Some(XYWH(1u16, 1, 1, 1)));
|
||||
/// assert_eq!("12345".max_wh(1, 1).layout(area)?, Some(XYWH(1u16, 1, 5, 1)));
|
||||
/// # Ok(()) }
|
||||
/// use tengri::Layout;
|
||||
/// let _ = "".max_w(1);
|
||||
/// let _ = "".max_h(1);
|
||||
/// let _ = "".max_wh(1, 1);
|
||||
/// ```
|
||||
pub enum Max<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
||||
__(PhantomData<T>),
|
||||
|
|
@ -298,6 +281,7 @@ pub enum Max<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
|||
H(I, X),
|
||||
WH(I, X, X),
|
||||
}
|
||||
|
||||
impl_draw!(<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>,>|self: Max<T, I, X>, to: T|{
|
||||
let area: XYWH<T::Unit> = to.area();
|
||||
let (item, area) = match self {
|
||||
|
|
@ -332,6 +316,7 @@ pub enum Exact<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
|||
H(I, X),
|
||||
WH(I, X, X),
|
||||
}
|
||||
|
||||
impl_draw!(<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>,>|self: Exact<T, I, X>, to: T|{
|
||||
let area: XYWH<T::Unit> = to.area();
|
||||
let (item, area) = match self {
|
||||
|
|
@ -360,27 +345,29 @@ pub enum Pad<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
|||
H(I, X),
|
||||
WH(I, X, X),
|
||||
}
|
||||
|
||||
impl_draw!(<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>,>|self: Pad<T, I, X>, _to: T|{
|
||||
todo!()
|
||||
});
|
||||
|
||||
pub struct Align<T>(Option<Azimuth>, T);
|
||||
|
||||
impl_draw!(<S: Screen, T: Draw<S>,>|self: Align<T>, to: S|{
|
||||
use Azimuth::*;
|
||||
let XYWH(x0, y0, w0, h0) = to.area();
|
||||
if let Some(XYWH(x, y, w, h)) = self.1.layout(to.area())? {
|
||||
to.clip(match self.0 {
|
||||
Some(NW) => XYWH(x0, y0, w, h),
|
||||
Some(N) => XYWH(x0 + w0.minus(w) / 2.into(), y0, w, h),
|
||||
Some(NE) => XYWH((x0 + w0).minus(w), y0, w, h),
|
||||
Some(W) => XYWH(x0, y0 + h0.minus(h) / 2.into(), w, h),
|
||||
Some(C) => XYWH(x0 + w0.minus(w) / 2.into(), y0 + h0.minus(h) / 2.into(), w, h),
|
||||
Some(E) => XYWH((x0 + w0).minus(w), y0 + h0.minus(h) / 2.into(), w, h),
|
||||
Some(SW) => XYWH(x0, (y0 + h0).minus(h), w, h),
|
||||
Some(S) => XYWH(x0 + w0.minus(w) / 2.into(), (y0 + h0).minus(h), w, h),
|
||||
Some(SE) => XYWH((x0 + w0).minus(w), (y0 + h0).minus(h), w, h),
|
||||
Some(X) => XYWH(x0 + w0.minus(w) / 2.into(), y, w, h),
|
||||
Some(Y) => XYWH(x, y0 + h0.minus(h) / 2.into(), w, h),
|
||||
Some(NW) => XYWH(x0, y0, w, h),
|
||||
Some(N) => XYWH(x0 + w0.sub(w) / 2.into(), y0, w, h),
|
||||
Some(NE) => XYWH((x0 + w0).sub(w), y0, w, h),
|
||||
Some(W) => XYWH(x0, y0 + h0.sub(h) / 2.into(), w, h),
|
||||
Some(C) => XYWH(x0 + w0.sub(w) / 2.into(), y0 + h0.sub(h) / 2.into(), w, h),
|
||||
Some(E) => XYWH((x0 + w0).sub(w), y0 + h0.sub(h) / 2.into(), w, h),
|
||||
Some(SW) => XYWH(x0, (y0 + h0).sub(h), w, h),
|
||||
Some(S) => XYWH(x0 + w0.sub(w) / 2.into(), (y0 + h0).sub(h), w, h),
|
||||
Some(SE) => XYWH((x0 + w0).sub(w), (y0 + h0).sub(h), w, h),
|
||||
Some(X) => XYWH(x0 + w0.sub(w) / 2.into(), y, w, h),
|
||||
Some(Y) => XYWH(x, y0 + h0.sub(h) / 2.into(), w, h),
|
||||
None => to.area()
|
||||
}, |to|self.1.draw(to))
|
||||
} else {
|
||||
|
|
@ -416,11 +403,13 @@ pub struct Area<S: Screen, T: Draw<S>>(
|
|||
pub Option<XYWH<S::Unit>>,
|
||||
pub T
|
||||
);
|
||||
|
||||
impl_draw!(<S: Screen, T: Draw<S>,>|self: Area<S, T>, to: S|{
|
||||
to.clip(self.0, |to|self.1.draw(to))
|
||||
});
|
||||
|
||||
pub struct Origin<T>(Option<Azimuth>, T);
|
||||
|
||||
impl_draw!(<S: Screen, T: Draw<S>,>|self: Origin<T>, _to: S|{
|
||||
todo!()
|
||||
});
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ pub trait Lrtb<N: Coord>: Xywh<N> {
|
|||
// FIXME: factor origin
|
||||
[self.x(), self.y(), self.x()+self.w(), self.y()+self.h()]
|
||||
}
|
||||
fn iter_x (&self) -> std::ops::Range<N> where Self: HasOrigin {
|
||||
fn iter_x (&self) -> impl Iterator<Item = N> where Self: HasOrigin {
|
||||
self.x_west()..self.x_east()
|
||||
}
|
||||
fn x_west (&self) -> N where Self: HasOrigin {
|
||||
|
|
@ -26,7 +26,7 @@ pub trait Lrtb<N: Coord>: Xywh<N> {
|
|||
fn x_center (&self) -> N where Self: HasOrigin {
|
||||
todo!()
|
||||
}
|
||||
fn iter_y (&self) -> std::ops::Range<N> where Self: HasOrigin {
|
||||
fn iter_y (&self) -> impl Iterator<Item = N> where Self: HasOrigin {
|
||||
self.y_north()..self.y_south()
|
||||
}
|
||||
fn y_north (&self) -> N where Self: HasOrigin {
|
||||
|
|
|
|||
|
|
@ -29,17 +29,3 @@ impl Sizer {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ShowSize;
|
||||
|
||||
impl Draw<Tui> for ShowSize {
|
||||
fn layout (&self, area: XYWH<u16>) -> Perhaps<XYWH<u16>> {
|
||||
let info = format!("{area:?}");
|
||||
Ok(Some(XYWH(area.0, area.1, info.len() as u16, 1)))
|
||||
}
|
||||
fn draw (self, to: &mut Tui) -> Drawn<u16> {
|
||||
let area = to.area();
|
||||
let info = format!("{area:?}");
|
||||
to.text(&info, area.0, area.1, info.len() as u16)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
src/draw/space.rs
Normal file
2
src/draw/space.rs
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
use crate::*;
|
||||
|
||||
67
src/eval.rs
67
src/eval.rs
|
|
@ -190,11 +190,18 @@ pub fn eval_view <'a, O: Screen + 'a, S> (
|
|||
/// use tengri::{*, lang::*, ratatui::prelude::Color};
|
||||
///
|
||||
/// #[namespace(bool)]
|
||||
/// #[namespace(u8)]
|
||||
/// #[namespace(u16)]
|
||||
/// #[namespace(Color get_color)]
|
||||
/// #[namespace(u8 try_to_u8)]
|
||||
/// #[namespace(u16 try_to_u16)]
|
||||
/// #[namespace(Color try_to_color)]
|
||||
/// #[interpret(Tui -> Option<XYWH<u16>>: try_eval_tui)]
|
||||
/// struct State;
|
||||
///
|
||||
/// tengri::lang::primitive!(u8: try_to_u8);
|
||||
/// tengri::lang::primitive!(u16: try_to_u16);
|
||||
/// tengri::lang::interpret!(|self: State, context: Tui, lang|->Option<XYWH<u16>>{
|
||||
/// expression = {
|
||||
/// "text" (...rest) => { todo!() }
|
||||
/// }
|
||||
/// });
|
||||
/// impl Interpret<Tui, Option<XYWH<u16>>> for State {
|
||||
/// fn interpret_expr <'a> (&'a self, _: &mut Tui, lang: &'a impl Expression)
|
||||
/// -> Usually<Option<XYWH<u16>>>
|
||||
|
|
@ -203,36 +210,6 @@ pub fn eval_view <'a, O: Screen + 'a, S> (
|
|||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn get_color (state: &State, src: impl Language) -> Perhaps<Color> {
|
||||
/// if let Some(expr) = src.expr()? {
|
||||
/// match (expr.head()?, expr.tail()?) {
|
||||
/// (Some("g"), Some(tail)) => {
|
||||
/// let n: u8 = state.namespace(tail.head().map_err(Into::into))?.ok_or(LanguageError::Domain("not gray"))?;
|
||||
/// Ok(Some(Color::Rgb(n, n, n)))
|
||||
/// },
|
||||
/// (Some("rgb"), Some(tail)) => {
|
||||
/// let r: u8 = state.namespace(tail.head().map_err(Into::into))?
|
||||
/// .ok_or(LanguageError::Domain("not red"))?;
|
||||
/// let g: u8 = state.namespace(tail.tail().head().map_err(Into::into))?
|
||||
/// .ok_or(LanguageError::Domain("not green"))?;
|
||||
/// let b: u8 = state.namespace(tail.tail().tail().head().map_err(Into::into))?
|
||||
/// .ok_or(LanguageError::Domain("not blue"))?;
|
||||
/// Ok(Some(Color::Rgb(r, g, b)))
|
||||
/// },
|
||||
/// (Some(_), _) => return Err(format!("not a color expression: {expr}").into()),
|
||||
/// (None, _) => return Err(format!("not a color expression: {expr}").into()),
|
||||
/// }
|
||||
/// } else if let Ok(Some(sym)) = src.word() {
|
||||
/// Ok(match sym {
|
||||
/// ":color/bg" => Some(Color::Rgb(28, 32, 36)),
|
||||
/// ":color/fg" => Some(Color::Rgb(98, 92, 96)),
|
||||
/// _ => return Err(format!("not a color: {sym}").into())
|
||||
/// })
|
||||
/// } else {
|
||||
/// return Err(format!("not a color: {:?}", src.src()?).into())
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// # fn main () -> tengri::Usually<()> {
|
||||
/// let state = State;
|
||||
/// let mut out = Tui::new(80, 25);
|
||||
|
|
@ -244,7 +221,7 @@ pub fn eval_view <'a, O: Screen + 'a, S> (
|
|||
/// # Ok(()) }
|
||||
/// ```
|
||||
pub fn eval_view_tui <'a, S> (
|
||||
state: &S, to: &mut Tui, expr: impl Expression + 'a
|
||||
state: &S, output: &mut Tui, expr: impl Expression + 'a
|
||||
) -> Perhaps<XYWH<u16>> where
|
||||
S: Interpret<Tui, Option<XYWH<u16>>>
|
||||
+ for<'b>Namespace<'b, bool>
|
||||
|
|
@ -262,7 +239,7 @@ pub fn eval_view_tui <'a, S> (
|
|||
match frags.next() {
|
||||
Some("text") => {
|
||||
if let Some(src) = args?.src()? {
|
||||
to.show(src)
|
||||
output.show(src)
|
||||
} else {
|
||||
return Ok(None)
|
||||
}
|
||||
|
|
@ -271,10 +248,11 @@ pub fn eval_view_tui <'a, S> (
|
|||
Some("fg") => {
|
||||
let arg0 = arg0?.expect("fg: expected arg 0 (color)");
|
||||
if let Some(color) = Namespace::namespace(state, arg0)? {
|
||||
fg(color, thunk(move|to: &mut Tui|{
|
||||
state.interpret(to, &arg1)?;
|
||||
Ok(Some(to.area().into())) // FIXME?: don't max out the used area?
|
||||
})).draw(to)
|
||||
output.show(fg(color, thunk(move|output: &mut Tui|{
|
||||
state.interpret(output, &arg1)?;
|
||||
// FIXME?: don't max out the used area?
|
||||
Ok(Some(output.area().into()))
|
||||
})))
|
||||
} else {
|
||||
return Err(format!("fg: {arg0:?}: not a color").into())
|
||||
}
|
||||
|
|
@ -283,10 +261,11 @@ pub fn eval_view_tui <'a, S> (
|
|||
Some("bg") => {
|
||||
let arg0 = arg0?.expect("bg: expected arg 0 (color)");
|
||||
if let Some(color) = Namespace::namespace(state, arg0)? {
|
||||
bg(color, thunk(move|to: &mut Tui|{
|
||||
state.interpret(to, &arg1)?;
|
||||
Ok(Some(to.area().into())) // FIXME?: don't max out the used area?
|
||||
})).draw(to)
|
||||
output.show(bg(color, thunk(move|output: &mut Tui|{
|
||||
state.interpret(output, &arg1)?;
|
||||
// FIXME?: don't max out the used area?
|
||||
Ok(Some(output.area().into()))
|
||||
})))
|
||||
} else {
|
||||
return Err(format!("bg: {arg0:?}: not a color").into())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
//#![feature(anonymous_lifetime_in_impl_trait)]
|
||||
#![feature(anonymous_lifetime_in_impl_trait)]
|
||||
//#![feature(associated_type_defaults)]
|
||||
//#![feature(const_default)]
|
||||
//#![feature(const_option_ops)]
|
||||
//#![feature(const_precise_live_drops)]
|
||||
//#![feature(const_trait_impl)]
|
||||
#![feature(const_precise_live_drops)]
|
||||
#![feature(const_trait_impl)]
|
||||
//#![feature(impl_trait_in_assoc_type)]
|
||||
//#![feature(step_trait)]
|
||||
#![feature(step_trait)]
|
||||
//#![feature(trait_alias)]
|
||||
//#![feature(type_alias_impl_trait)]
|
||||
//#![feature(type_changing_struct_update)]
|
||||
|
|
|
|||
115
src/sing.rs
115
src/sing.rs
|
|
@ -803,7 +803,7 @@ pub trait AddMidiOut {
|
|||
/// Port connection manager.
|
||||
///
|
||||
/// ```
|
||||
/// let connect = tengri::Connect::default();
|
||||
/// let connect = tek::Connect::default();
|
||||
/// ```
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct Connect {
|
||||
|
|
@ -814,6 +814,7 @@ pub struct Connect {
|
|||
}
|
||||
|
||||
impl Connect {
|
||||
|
||||
pub fn new <T: AsRef<str>> (
|
||||
exact: Option<impl Iterator<Item = T>>,
|
||||
re: Option<impl Iterator<Item = T>>,
|
||||
|
|
@ -826,6 +827,62 @@ impl Connect {
|
|||
connections
|
||||
}
|
||||
|
||||
pub fn midi_ins <T: AsRef<str>> (
|
||||
jack: &Jack<'static>,
|
||||
name: &T,
|
||||
midi_from: &[T],
|
||||
midi_from_re: Option<&[T]>,
|
||||
) -> Usually<Vec<MidiInput>> {
|
||||
Ok(Connect::new(
|
||||
Some(midi_from.into_iter()),
|
||||
Some([].into_iter()),
|
||||
midi_from_re.map(|x|x.into_iter())).iter().enumerate()
|
||||
.map(|(index, connect)|jack.midi_in(&format!("{}/{index}", name.as_ref()), &[connect.clone()]))
|
||||
.collect::<Result<_, _>>()?)
|
||||
}
|
||||
|
||||
pub fn midi_outs <T: AsRef<str>> (
|
||||
jack: &Jack<'static>,
|
||||
name: &T,
|
||||
midi_to: &[T],
|
||||
midi_to_re: Option<&[T]>,
|
||||
) -> Usually<Vec<MidiOutput>> {
|
||||
Ok(Connect::new(
|
||||
Some(midi_to.into_iter()),
|
||||
Some([].into_iter()),
|
||||
midi_to_re.map(|x|x.into_iter())).iter().enumerate()
|
||||
.map(|(index, connect)|jack.midi_out(&format!("{index}/{}", name.as_ref()), &[connect.clone()]))
|
||||
.collect::<Result<_, _>>()?)
|
||||
}
|
||||
|
||||
pub fn audio_ins <T: AsRef<str>> (
|
||||
jack: &Jack<'static>,
|
||||
name: &T,
|
||||
audio_from: &[T],
|
||||
audio_from_re: Option<&[T]>,
|
||||
) -> Usually<Vec<AudioInput>> {
|
||||
Ok(Connect::new(
|
||||
Some(audio_from.into_iter()),
|
||||
Some([].into_iter()),
|
||||
audio_from_re.map(|x|x.into_iter())).iter().enumerate()
|
||||
.map(|(index, connect)|jack.audio_in(&format!("{}/{index}", name.as_ref()), &[connect.clone()]))
|
||||
.collect::<Result<_, _>>()?)
|
||||
}
|
||||
|
||||
pub fn audio_outs <T: AsRef<str>> (
|
||||
jack: &Jack<'static>,
|
||||
name: &T,
|
||||
audio_to: &[T],
|
||||
audio_to_re: Option<&[T]>,
|
||||
) -> Usually<Vec<AudioOutput>> {
|
||||
Ok(Connect::new(
|
||||
Some(audio_to.into_iter()),
|
||||
Some([].into_iter()),
|
||||
audio_to_re.map(|x|x.into_iter())).iter().enumerate()
|
||||
.map(|(index, connect)|jack.audio_out(&format!("{index}/{}", name.as_ref()), &[connect.clone()]))
|
||||
.collect::<Result<_, _>>()?)
|
||||
}
|
||||
|
||||
/// Connect to this exact port
|
||||
pub fn exact (name: impl AsRef<str>) -> Self {
|
||||
let info = format!("=:{}", name.as_ref()).into();
|
||||
|
|
@ -866,59 +923,3 @@ impl Connect {
|
|||
}).into()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn connect_midi_ins <T: AsRef<str>> (
|
||||
jack: &Jack<'static>,
|
||||
name: &T,
|
||||
midi_from: &[T],
|
||||
midi_from_re: Option<&[T]>,
|
||||
) -> Usually<Vec<MidiInput>> {
|
||||
Ok(Connect::new(
|
||||
Some(midi_from.into_iter()),
|
||||
Some([].into_iter()),
|
||||
midi_from_re.map(|x|x.into_iter())).iter().enumerate()
|
||||
.map(|(index, connect)|jack.midi_in(&format!("{}/{index}", name.as_ref()), &[connect.clone()]))
|
||||
.collect::<Result<_, _>>()?)
|
||||
}
|
||||
|
||||
pub fn connect_midi_outs <T: AsRef<str>> (
|
||||
jack: &Jack<'static>,
|
||||
name: &T,
|
||||
midi_to: &[T],
|
||||
midi_to_re: Option<&[T]>,
|
||||
) -> Usually<Vec<MidiOutput>> {
|
||||
Ok(Connect::new(
|
||||
Some(midi_to.into_iter()),
|
||||
Some([].into_iter()),
|
||||
midi_to_re.map(|x|x.into_iter())).iter().enumerate()
|
||||
.map(|(index, connect)|jack.midi_out(&format!("{index}/{}", name.as_ref()), &[connect.clone()]))
|
||||
.collect::<Result<_, _>>()?)
|
||||
}
|
||||
|
||||
pub fn connect_audio_ins <T: AsRef<str>> (
|
||||
jack: &Jack<'static>,
|
||||
name: &T,
|
||||
audio_from: &[T],
|
||||
audio_from_re: Option<&[T]>,
|
||||
) -> Usually<Vec<AudioInput>> {
|
||||
Ok(Connect::new(
|
||||
Some(audio_from.into_iter()),
|
||||
Some([].into_iter()),
|
||||
audio_from_re.map(|x|x.into_iter())).iter().enumerate()
|
||||
.map(|(index, connect)|jack.audio_in(&format!("{}/{index}", name.as_ref()), &[connect.clone()]))
|
||||
.collect::<Result<_, _>>()?)
|
||||
}
|
||||
|
||||
pub fn connect_audio_outs <T: AsRef<str>> (
|
||||
jack: &Jack<'static>,
|
||||
name: &T,
|
||||
audio_to: &[T],
|
||||
audio_to_re: Option<&[T]>,
|
||||
) -> Usually<Vec<AudioOutput>> {
|
||||
Ok(Connect::new(
|
||||
Some(audio_to.into_iter()),
|
||||
Some([].into_iter()),
|
||||
audio_to_re.map(|x|x.into_iter())).iter().enumerate()
|
||||
.map(|(index, connect)|jack.audio_out(&format!("{index}/{}", name.as_ref()), &[connect.clone()]))
|
||||
.collect::<Result<_, _>>()?)
|
||||
}
|
||||
|
|
|
|||
0
src/sing/jack.rs
Normal file
0
src/sing/jack.rs
Normal file
0
src/sing/jack_event.rs
Normal file
0
src/sing/jack_event.rs
Normal file
0
src/sing/jack_perf.rs
Normal file
0
src/sing/jack_perf.rs
Normal file
|
|
@ -1,4 +1,5 @@
|
|||
use crate::lang::*;
|
||||
use crate::*;
|
||||
use crate::{*, lang::*, draw::*, task::*, exit::*};
|
||||
use ::ratatui::buffer::Cell;
|
||||
|
||||
/// TUI buffer sized by `usize` instead of `u16`.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use crate::*;
|
||||
use ratatui::prelude::Color;
|
||||
use dizzle::{Expression, LanguageError::*};
|
||||
use dizzle::{Ostensibly, Expression, LanguageError::*};
|
||||
|
||||
pub trait ColorDsl<T>: Sized {
|
||||
fn new_g (expr: T, try_to_u8: impl Fn(Perhaps<&str>)->Perhaps<u8>) -> Usually<Self>;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,10 @@
|
|||
use ::dizzle::{Language, Symbol, Usually};
|
||||
use ::crossterm::event::{Event, KeyEvent, KeyCode, KeyModifiers, KeyEventKind, KeyEventState};
|
||||
use crate::{task::Task, term::TuiEvent};
|
||||
use ::std::sync::{Arc, RwLock, atomic::{AtomicBool, Ordering::*}};
|
||||
use ::std::time::Duration;
|
||||
use ::dizzle::{Language, Symbol, Usually, Apply};
|
||||
use ::crossterm::event::{
|
||||
read, Event, KeyEvent, KeyCode, KeyModifiers, KeyEventKind, KeyEventState
|
||||
};
|
||||
|
||||
/// TUI key spec.
|
||||
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd)]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use crate::*;
|
||||
|
||||
/// Stackably padded.
|
||||
///
|
||||
/// ```
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::*;
|
||||
use ratatui::{prelude::{Position}};
|
||||
use ratatui::{prelude::{Style, Position, Backend, Color}};
|
||||
|
||||
pub const fn x_repeat (c: &str) -> impl Draw<Tui> {
|
||||
thunk(move|to: &mut Tui|{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::*;
|
||||
use ratatui::{prelude::{Position}};
|
||||
use ratatui::{prelude::{Style, Position, Backend, Color}};
|
||||
|
||||
pub const ICON_DEC_V: &[char] = &['▲'];
|
||||
pub const ICON_INC_V: &[char] = &['▼'];
|
||||
|
|
@ -7,7 +7,7 @@ pub const ICON_DEC_H: &[char] = &[' ', '🞀', ' '];
|
|||
pub const ICON_INC_H: &[char] = &[' ', '🞂', ' '];
|
||||
|
||||
pub fn x_scroll () -> impl Draw<Tui> {
|
||||
thunk(|Tui(buf, XYWH(x1, y1, w, _h)): &mut Tui|{
|
||||
thunk(|Tui(buf, XYWH(x1, y1, w, h)): &mut Tui|{
|
||||
let x2 = *x1 + *w;
|
||||
for (i, x) in (*x1..=x2).enumerate() {
|
||||
if let Some(cell) = buf.cell_mut(Position::from((x, *y1))) {
|
||||
|
|
@ -35,7 +35,7 @@ pub fn x_scroll () -> impl Draw<Tui> {
|
|||
}
|
||||
|
||||
pub fn y_scroll () -> impl Draw<Tui> {
|
||||
thunk(|Tui(buf, XYWH(x1, y1, _w, h)): &mut Tui|{
|
||||
thunk(|Tui(buf, XYWH(x1, y1, w, h)): &mut Tui|{
|
||||
let y2 = *y1 + *h;
|
||||
for (i, y) in (*y1..=y2).enumerate() {
|
||||
if let Some(cell) = buf.cell_mut(Position::from((*x1, y))) {
|
||||
|
|
|
|||
32
src/text.rs
32
src/text.rs
|
|
@ -1,36 +1,18 @@
|
|||
#![allow(unused)]
|
||||
|
||||
use crate::*;
|
||||
pub(crate) use ::unicode_width::*;
|
||||
|
||||
#[cfg(feature = "term")] mod impl_term {
|
||||
use super::*;
|
||||
use crate::*;
|
||||
use ratatui::prelude::Position;
|
||||
|
||||
impl_draw!(|self: String, to: Tui|{self.as_str().draw(to)});
|
||||
impl_draw!(|self: std::sync::Arc<str>, to: Tui|{self.as_ref().draw(to)});
|
||||
impl_draw!(|self: &std::sync::Arc<str>, to: Tui|{self.as_ref().draw(to)});
|
||||
impl Draw<Tui> for &str {
|
||||
fn layout (&self, area: XYWH<u16>) -> Perhaps<XYWH<u16>> {
|
||||
let XYWH(x, y, ..) = area;
|
||||
let mut max_w = 0u16;
|
||||
let mut max_h = 0u16;
|
||||
for line in self.split("\n") {
|
||||
max_h += 1;
|
||||
max_w = max_w.max(line.len() as u16);
|
||||
}
|
||||
Ok(Some(XYWH(x, y, max_w, max_h)))
|
||||
}
|
||||
fn draw (self, to: &mut Tui) -> Drawn<u16> {
|
||||
let area = self.layout(to.area())?.unwrap();
|
||||
////let info = format!("{area:?}");
|
||||
//to.text(&self, area.0, area.1, self.len() as u16)
|
||||
for (index, line) in self.split("\n").enumerate() {
|
||||
let _ = to.text(&line, area.0, area.1 + index as u16, width_chars_max(area.2, line) as u16)?;
|
||||
}
|
||||
Ok(Some(area))
|
||||
}
|
||||
}
|
||||
impl_draw!(|self: &str, to: Tui|{
|
||||
let XYWH(x, y, w, ..) = to.1.centered_xy([width_chars_max(to.w(), self), 1]);
|
||||
to.text(&self, x, y, w)
|
||||
});
|
||||
|
||||
impl_draw!(<T: AsRef<str>,>|self: TrimString<T>, to: Tui|{self.as_ref().draw(to)});
|
||||
impl_draw!(<T: AsRef<str>,>|self: TrimStringRef<'_, T>, to: Tui|{
|
||||
|
|
@ -98,9 +80,7 @@ pub fn trim_string (max_width: usize, input: impl AsRef<str>) -> String {
|
|||
pub struct TrimString<T: AsRef<str>>(pub u16, pub T);
|
||||
impl<T: AsRef<str>> AsRef<str> for TrimString<T> { fn as_ref (&self) -> &str { self.1.as_ref() } }
|
||||
impl<'a, T: AsRef<str>> TrimString<T> {
|
||||
fn to_ref (&self) -> TrimStringRef<'_, T> {
|
||||
TrimStringRef(self.0, &self.1)
|
||||
}
|
||||
fn to_ref (&self) -> TrimStringRef<'_, T> { TrimStringRef(self.0, &self.1) }
|
||||
}
|
||||
|
||||
/// Displays a borrowed [str]-like with fixed maximum width
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue