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