mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2026-08-07 22:17:07 +02:00
parent
64c83b5460
commit
eb028c85fc
12 changed files with 322 additions and 216 deletions
|
|
@ -26,28 +26,41 @@ tui_view!(self: State {
|
||||||
let widget = draw(move|to: &mut Tui|self.interpret(to, &src)); // FIXME this forcefills
|
let widget = draw(move|to: &mut Tui|self.interpret(to, &src)); // FIXME this forcefills
|
||||||
let sidebar = bg(Color::Rgb(20, 20, 20), north(code, title)).max_w(40);
|
let sidebar = bg(Color::Rgb(20, 20, 20), north(code, title)).max_w(40);
|
||||||
let content = bg(Color::Rgb(64, 64, 64), widget);
|
let content = bg(Color::Rgb(64, 64, 64), widget);
|
||||||
east(sidebar, content)
|
east(sidebar, ShowSizeOf(content))
|
||||||
//self.size.of(bg(Color::Rgb(10, 10, 10), south(east(sidebar, content), code)).full_w())
|
//self.size.of(bg(Color::Rgb(10, 10, 10), south(east(sidebar, content), code)).full_w())
|
||||||
//self.size.of(bg(Color::Rgb(10, 10, 10), east(sidebar, content)).full_w())
|
//self.size.of(bg(Color::Rgb(10, 10, 10), east(sidebar, content)).full_w())
|
||||||
});
|
});
|
||||||
|
|
||||||
|
impl_keywords!(Tui, XYWH<u16>, State [
|
||||||
|
kw_when,
|
||||||
|
kw_either,
|
||||||
|
kw_split,
|
||||||
|
kw_align,
|
||||||
|
kw_exact,
|
||||||
|
kw_fixed,
|
||||||
|
kw_min,
|
||||||
|
kw_max,
|
||||||
|
kw_push,
|
||||||
|
kw_tui_text,
|
||||||
|
kw_tui_fg,
|
||||||
|
kw_tui_bg
|
||||||
|
]);
|
||||||
|
|
||||||
impl Interpret<Tui, Option<XYWH<u16>>> for State {
|
impl Interpret<Tui, Option<XYWH<u16>>> for State {
|
||||||
fn interpret_word (&self, to: &mut Tui, sym: &impl Language) -> Perhaps<XYWH<u16>> {
|
fn interpret_word (&self, to: &mut Tui, sym: &impl Language) -> Perhaps<XYWH<u16>> {
|
||||||
match sym.src()? {
|
match sym.src()? {
|
||||||
Some(":foo") => "foo".draw(to),
|
Some(":foo") => "foo".draw(to),
|
||||||
Some(":bar") => "bar".draw(to),
|
Some(":bar") => "bar".draw(to),
|
||||||
Some(":foobar") => "FOOBAR".draw(to),
|
Some(":foobar") => "FOOBAR".draw(to),
|
||||||
_ => todo!()
|
src => todo!("src: {src:?}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn interpret_expr (&self, to: &mut Tui, src: &impl Expression) -> Perhaps<XYWH<u16>> {
|
fn interpret_expr (&self, to: &mut Tui, src: &impl Expression) -> Perhaps<XYWH<u16>> {
|
||||||
Ok(Some(if let Some(area) = eval_view(self, to, src)? {
|
if let Some(area) = self.keyword(to, src)? {
|
||||||
area
|
Ok(Some(area))
|
||||||
} else if let Some(area) = Tui::eval_view(self, to, src)? {
|
|
||||||
area
|
|
||||||
} else {
|
} else {
|
||||||
return Err(format!("App::interpret_expr: unexpected: {src:?}").into())
|
Err(format!("App::interpret_expr: unexpected: {src:?}").into())
|
||||||
}))
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -89,7 +102,7 @@ const VIEWS: &'static [&'static str] = &[
|
||||||
stringify! { :foobar },
|
stringify! { :foobar },
|
||||||
stringify! { (text FOOBAR) },
|
stringify! { (text FOOBAR) },
|
||||||
stringify! { (bg (g 8) :foobar) },
|
stringify! { (bg (g 8) :foobar) },
|
||||||
stringify! { (fill/xy :foobar) },
|
//stringify! { (fill/xy :foobar) },
|
||||||
stringify! { (bsp/s (text foo) (text bar)) },
|
stringify! { (bsp/s (text foo) (text bar)) },
|
||||||
stringify! { (bsp/s :foo :bar) },
|
stringify! { (bsp/s :foo :bar) },
|
||||||
stringify! { (bsp/s (bg (g 16) :foo) (bg (g 32) :bar)) },
|
stringify! { (bsp/s (bg (g 16) :foo) (bg (g 32) :bar)) },
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{*, draw::*, layout::*};
|
use crate::*;
|
||||||
use Azimuth::*;
|
use Azimuth::*;
|
||||||
|
|
||||||
pub struct Align<T>(
|
pub struct Align<T>(
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{*, draw::*, layout::*};
|
use crate::*;
|
||||||
|
|
||||||
pub struct Origin<T>(
|
pub struct Origin<T>(
|
||||||
pub(crate) Option<Azimuth>,
|
pub(crate) Option<Azimuth>,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{*, draw::*};
|
use crate::*;
|
||||||
|
|
||||||
/// Define inner drawing area.
|
/// Define inner drawing area.
|
||||||
///
|
///
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{*, draw::*};
|
use crate::*;
|
||||||
|
|
||||||
/// Move content in the negative direction of one or both axes.
|
/// Move content in the negative direction of one or both axes.
|
||||||
///
|
///
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{*, draw::*};
|
use crate::*;
|
||||||
|
|
||||||
/// Move content in the positive direction of one or both axes.
|
/// Move content in the positive direction of one or both axes.
|
||||||
///
|
///
|
||||||
|
|
|
||||||
447
src/lib.rs
447
src/lib.rs
|
|
@ -41,6 +41,33 @@ macro_rules! features {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! fn_kw_layout {
|
||||||
|
($name:ident |$state:ident, $output: ident, $expr:ident| $body:block) => {
|
||||||
|
pub fn $name <O: Screen, S> (
|
||||||
|
$state: &S, $output: &mut O, $expr: &str
|
||||||
|
) -> Perhaps<XYWH<O::Unit>> where
|
||||||
|
S: Interpret<O, Option<XYWH<O::Unit>>>
|
||||||
|
+ for<'b> Namespace<'b, bool>
|
||||||
|
+ for<'b> Namespace<'b, O::Unit>
|
||||||
|
+ for<'b> Namespace<'b, Option<O::Unit>>
|
||||||
|
$body
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! fn_kw_layout_tui {
|
||||||
|
($name:ident |$state:ident, $output: ident, $expr:ident| $body:block) => {
|
||||||
|
pub fn $name <S> (
|
||||||
|
$state: &S, $output: &mut Tui, $expr: &str
|
||||||
|
) -> Perhaps<XYWH<u16>> where
|
||||||
|
S: Interpret<Tui, Option<XYWH<u16>>>
|
||||||
|
+ for<'b> Namespace<'b, bool>
|
||||||
|
+ for<'b> Namespace<'b, u16>
|
||||||
|
+ for<'b> Namespace<'b, Option<u16>>
|
||||||
|
+ for<'b> Namespace<'b, Color>
|
||||||
|
$body
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(feature = "lang")] pub use ::dizzle::{Usually, Perhaps};
|
#[cfg(feature = "lang")] pub use ::dizzle::{Usually, Perhaps};
|
||||||
#[cfg(feature = "lang")] use ::dizzle::*;
|
#[cfg(feature = "lang")] use ::dizzle::*;
|
||||||
|
|
||||||
|
|
@ -168,7 +195,7 @@ pub trait AsMutOpt<T> { fn as_mut_opt (&mut self) -> Option<&mut T>; }
|
||||||
/// Some layout operations exist in multiple variants that take a single argument.
|
/// Some layout operations exist in multiple variants that take a single argument.
|
||||||
/// Their handling in [eval_view] is uniform and goes like this:
|
/// Their handling in [eval_view] is uniform and goes like this:
|
||||||
macro_rules! eval_enum ((
|
macro_rules! eval_enum ((
|
||||||
$name:literal, $output:ident, $state:ident, $value:expr, $arg0: ident, $Enum:ident {
|
$name:literal, $output:ident, $state:ident, $value:expr, $arg0:expr, $Enum:ident {
|
||||||
$($v:literal => $V:ident),* $(,)?
|
$($v:literal => $V:ident),* $(,)?
|
||||||
}
|
}
|
||||||
) => {{
|
) => {{
|
||||||
|
|
@ -187,7 +214,7 @@ macro_rules! eval_xy (
|
||||||
// (fill/xy ...)
|
// (fill/xy ...)
|
||||||
(
|
(
|
||||||
$name:expr => $expr:expr, $head:expr, $output:ident, $state:ident,
|
$name:expr => $expr:expr, $head:expr, $output:ident, $state:ident,
|
||||||
$variant:expr, $xy:ident, $x:ident, $y:ident, $arg: ident,
|
$variant:expr, $xy:ident, $x:ident, $y:ident, $arg:expr,
|
||||||
) => {{
|
) => {{
|
||||||
// frags.next(): 2nd slash-delimited fragment: /x, /y, /xy
|
// frags.next(): 2nd slash-delimited fragment: /x, /y, /xy
|
||||||
let variant = $variant;
|
let variant = $variant;
|
||||||
|
|
@ -210,7 +237,7 @@ macro_rules! eval_xy (
|
||||||
// (push/xy n m ...)
|
// (push/xy n m ...)
|
||||||
(
|
(
|
||||||
$name:expr => $expr:expr, $head:expr, $output:ident, $state:ident,
|
$name:expr => $expr:expr, $head:expr, $output:ident, $state:ident,
|
||||||
$variant:expr, $xy:ident, $x:ident, $y:ident, $arg0: ident, $arg1: ident, $arg2: ident,
|
$variant:expr, $xy:ident, $x:ident, $y:ident, $arg0:expr, $arg1:expr, $arg2:expr,
|
||||||
) => {{
|
) => {{
|
||||||
// frags.next(): 2nd slash-delimited fragment: /x, /y, /xy
|
// frags.next(): 2nd slash-delimited fragment: /x, /y, /xy
|
||||||
let variant = $variant;
|
let variant = $variant;
|
||||||
|
|
@ -483,7 +510,7 @@ macro_rules! eval_xy (
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use tengri::*;
|
/// # use tengri::*;
|
||||||
/// let _ = draw(|to: &mut Tui|Ok(Some(to.1)));
|
/// let _ = draw(|to: &mut Tui|Ok(Some(to.area()))); // draws nothing
|
||||||
/// ```
|
/// ```
|
||||||
pub const fn draw <T: Screen, F: FnOnce(&mut T)->Perhaps<XYWH<T::Unit>>> (
|
pub const fn draw <T: Screen, F: FnOnce(&mut T)->Perhaps<XYWH<T::Unit>>> (
|
||||||
item: F
|
item: F
|
||||||
|
|
@ -1550,96 +1577,6 @@ macro_rules! eval_xy (
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Interpret TUI-specific layout operation.
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use tengri::{*, dizzle::*, ratatui::prelude::Color};
|
|
||||||
///
|
|
||||||
/// #[namespace(bool)]
|
|
||||||
/// #[namespace(u8)]
|
|
||||||
/// #[namespace(u16)]
|
|
||||||
/// #[namespace(Color get_color)]
|
|
||||||
/// struct State;
|
|
||||||
///
|
|
||||||
/// impl Interpret<Tui, Option<XYWH<u16>>> for State {
|
|
||||||
/// fn interpret_expr <'a> (&'a self, _: &mut Tui, lang: &'a impl Expression)
|
|
||||||
/// -> Usually<Option<XYWH<u16>>>
|
|
||||||
/// {
|
|
||||||
/// Ok(None)
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn get_color (state: &State, src: impl Language) -> Perhaps<Color> {
|
|
||||||
/// Ok(if let Some(color) = Tui::eval_color_expr(state, &src)? {
|
|
||||||
/// Some(color)
|
|
||||||
/// } else if let Some(sym) = src.word()? {
|
|
||||||
/// Some(match sym {
|
|
||||||
/// ":color/bg" => Color::Rgb(28, 32, 36),
|
|
||||||
/// ":color/fg" => 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);
|
|
||||||
/// Tui::eval_view(&state, &mut out, "")?;
|
|
||||||
/// Tui::eval_view(&state, &mut out, "text Hello world!")?;
|
|
||||||
/// Tui::eval_view(&state, &mut out, "fg (g 0) (text Hello world!)")?;
|
|
||||||
/// Tui::eval_view(&state, &mut out, "bg (g 2) (text Hello world!)")?;
|
|
||||||
/// Tui::eval_view(&state, &mut out, "(bg (g 3) (fg (g 4) (text Hello world!)))")?;
|
|
||||||
/// # Ok(()) }
|
|
||||||
/// ```
|
|
||||||
pub fn eval_view <'a, S> (
|
|
||||||
state: &S, to: &mut Tui, expr: impl Expression + 'a
|
|
||||||
) -> Perhaps<XYWH<u16>> where
|
|
||||||
S: Interpret<Tui, Option<XYWH<u16>>>
|
|
||||||
+ for<'b>Namespace<'b, bool>
|
|
||||||
+ for<'b>Namespace<'b, u16>
|
|
||||||
+ for<'b>Namespace<'b, Color>
|
|
||||||
{
|
|
||||||
// See `tengri::eval_view`
|
|
||||||
let head = expr.head()?;
|
|
||||||
let mut frags = head.src()?.unwrap_or_default().split("/");
|
|
||||||
let args = expr.tail();
|
|
||||||
let arg0 = args.head();
|
|
||||||
let tail0 = args.tail();
|
|
||||||
let arg1 = tail0.head();
|
|
||||||
match frags.next() {
|
|
||||||
Some("text") => {
|
|
||||||
if let Some(src) = args?.src()? {
|
|
||||||
src.draw(to)
|
|
||||||
} else {
|
|
||||||
return Ok(None)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
Some("fg") => {
|
|
||||||
let arg0 = arg0?.expect("fg: expected arg 0 (color)");
|
|
||||||
if let Some(color) = Namespace::namespace(state, arg0)? {
|
|
||||||
fg(color, draw(move|to: &mut Tui|state.interpret(to, &arg1))).draw(to)
|
|
||||||
} else {
|
|
||||||
return Err(format!("fg: {arg0:?}: not a color").into())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
Some("bg") => {
|
|
||||||
let arg0 = arg0?.expect("bg: expected arg 0 (color)");
|
|
||||||
if let Some(color) = Namespace::namespace(state, arg0)? {
|
|
||||||
bg(color, draw(move|to: &mut Tui|state.interpret(to, &arg1))).draw(to)
|
|
||||||
} else {
|
|
||||||
return Err(format!("bg: {arg0:?}: not a color").into())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
_ => return Ok(None)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn eval_color_expr (state: &impl for<'a> Namespace<'a, u8>, src: impl Language)
|
pub fn eval_color_expr (state: &impl for<'a> Namespace<'a, u8>, src: impl Language)
|
||||||
-> Perhaps<Color>
|
-> Perhaps<Color>
|
||||||
{
|
{
|
||||||
|
|
@ -1971,115 +1908,271 @@ macro_rules! eval_xy (
|
||||||
#[cfg(feature = "eval")] mod eval {
|
#[cfg(feature = "eval")] mod eval {
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
/// Interpret layout operation.
|
|
||||||
///
|
|
||||||
/// ```
|
/// ```
|
||||||
/// # use tengri::{*, dizzle::*};
|
/// # use ::tengri::{*, dizzle::*, ratatui::prelude::Color};
|
||||||
///
|
///
|
||||||
/// struct State {/*app-specific*/}
|
/// #[namespace(bool)]
|
||||||
/// impl<'b> Namespace<'b, u16> for State {}
|
/// #[namespace(u8)]
|
||||||
/// impl<'b> Namespace<'b, bool> for State {}
|
/// #[namespace(u16)]
|
||||||
/// impl<'b> Namespace<'b, Option<u16>> for State {}
|
/// #[namespace(Option<u16>)]
|
||||||
/// impl Interpret<Tui, Option<XYWH<u16>>> for State {}
|
/// #[namespace(Color get_color)]
|
||||||
|
/// struct App;
|
||||||
|
///
|
||||||
|
/// fn get_color (state: &App, src: impl Language) -> Perhaps<Color> {
|
||||||
|
/// Ok(if let Some(color) = Tui::eval_color_expr(state, &src)? {
|
||||||
|
/// Some(color)
|
||||||
|
/// } else if let Some(sym) = src.word()? {
|
||||||
|
/// Some(match sym {
|
||||||
|
/// ":color/bg" => Color::Rgb(28, 32, 36),
|
||||||
|
/// ":color/fg" => Color::Rgb(98, 92, 96),
|
||||||
|
/// _ => return Err(format!("not a color: {sym}").into())
|
||||||
|
/// })
|
||||||
|
/// } else {
|
||||||
|
/// return Err(format!("not a color: {:?}", src.src()?).into())
|
||||||
|
/// })
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// impl Interpret<Tui, Option<XYWH<u16>>> for App {
|
||||||
|
/// fn interpret_expr <'a> (&'a self, _: &mut Tui, lang: &'a impl Expression)
|
||||||
|
/// -> Usually<Option<XYWH<u16>>>
|
||||||
|
/// {
|
||||||
|
/// Ok(None)
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// impl Keywords<Tui, XYWH<u16>> for App {
|
||||||
|
/// fn keywords () -> impl Iterator<Item = fn(&Self, &mut Tui, &str) -> Perhaps<XYWH<u16>>> {
|
||||||
|
/// [
|
||||||
|
/// kw_when, kw_either, kw_split, kw_align,
|
||||||
|
/// kw_exact, kw_fixed, kw_min, kw_max, kw_push,
|
||||||
|
/// kw_tui_text, kw_tui_fg, kw_tui_bg
|
||||||
|
/// ].into_iter()
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
///
|
///
|
||||||
/// # fn main () -> tengri::Usually<()> {
|
/// # fn main () -> tengri::Usually<()> {
|
||||||
/// let state = State {};
|
/// let state = App;
|
||||||
/// let mut target = Tui::new(80, 25);
|
/// let mut out = Tui::new(80, 25);
|
||||||
/// eval_view(&state, &mut target, &"")?;
|
/// Tui::eval_view(&state, &mut out, "")?;
|
||||||
/// eval_view(&state, &mut target, &"(whe true (text hello))")?;
|
/// Tui::eval_view(&state, &mut out, "text Hello world!")?;
|
||||||
/// eval_view(&state, &mut target, &"(either true (text hello) (text world))")?;
|
/// Tui::eval_view(&state, &mut out, "fg (g 0) (text Hello world!)")?;
|
||||||
/// // TODO test all
|
/// Tui::eval_view(&state, &mut out, "bg (g 2) (text Hello world!)")?;
|
||||||
|
/// Tui::eval_view(&state, &mut out, "(bg (g 3) (fg (g 4) (text Hello world!)))")?;
|
||||||
/// # Ok(()) }
|
/// # Ok(()) }
|
||||||
/// ```
|
/// ```
|
||||||
pub fn eval_view <'a, O: Screen + 'a, S> (
|
pub trait Keywords <U, V>: 'static {
|
||||||
state: &S, output: &mut O, expr: &'a impl Expression
|
fn keywords () -> impl Iterator<Item = fn(&Self, &mut U, &str) -> Perhaps<V>>;
|
||||||
) -> Perhaps<XYWH<O::Unit>> where
|
fn keyword (&self, to: &mut U, expr: &impl Expression) -> Perhaps<V> {
|
||||||
S: Interpret<O, Option<XYWH<O::Unit>>>
|
if let Some(expr) = expr.src()? {
|
||||||
+ for<'b> Namespace<'b, bool>
|
for keyword in Self::keywords() {
|
||||||
+ for<'b> Namespace<'b, O::Unit>
|
if let Some(result) = keyword(self, to, &expr)? {
|
||||||
+ for<'b> Namespace<'b, Option<O::Unit>>
|
return Ok(Some(result))
|
||||||
{
|
}
|
||||||
// First element of expression is name of the operation.
|
}
|
||||||
// These are quasi-namespaced using the separator character, `/`.
|
}
|
||||||
let head = expr.head()?;
|
Ok(None)
|
||||||
let mut frags = head.src()?.unwrap_or_default().split("/");
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The rest of the tokens in the expr are arguments.
|
#[macro_export] macro_rules! impl_keywords {
|
||||||
// Their meanings depend on the dispatched operation
|
($T:ty, $U:ty, $V:ty [ $($kw:ident),* ]) => {
|
||||||
// Here we just reference them, so that they are in scope.
|
impl Keywords<$T, $U> for $V {
|
||||||
// Dereferencing them happens in the dispatch branch.
|
fn keywords () -> impl Iterator<Item = fn(&Self, &mut $T, &str) -> Perhaps<$U>> {
|
||||||
|
[ $($kw),* ].into_iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn_kw_layout!(kw_when |state, output, expr| {
|
||||||
|
Ok(matches!(expr.head()?, Some("when")).then(||{
|
||||||
|
when(state.namespace(expr.tail().head())?.unwrap(),
|
||||||
|
draw(move|output: &mut O|{state.interpret(output, &expr.tail().tail().head())})
|
||||||
|
).draw(output)
|
||||||
|
}).transpose()?.flatten())
|
||||||
|
});
|
||||||
|
|
||||||
|
fn_kw_layout!(kw_either |state, output, expr| {
|
||||||
|
Ok(matches!(expr.head()?, Some("either")).then(||{
|
||||||
|
either(state.namespace(expr.tail().head()?)?.unwrap(),
|
||||||
|
draw(move|output: &mut O|{
|
||||||
|
state.interpret(output, &expr.tail().tail().head()?)
|
||||||
|
}),
|
||||||
|
draw(move|output: &mut O|{
|
||||||
|
state.interpret(output, &expr.tail().tail().tail().head()?)
|
||||||
|
}),
|
||||||
|
).draw(output)
|
||||||
|
}).transpose()?.flatten())
|
||||||
|
});
|
||||||
|
|
||||||
|
fn_kw_layout!(kw_split |state, output, expr| {
|
||||||
|
let head = expr.head();
|
||||||
|
let mut frags = head.src()?.unwrap_or_default().split("/");
|
||||||
|
Ok(matches!(frags.next(), Some("bsp")).then(||{
|
||||||
|
eval_enum!("bsp", output, state, frags.next(), expr.tail().head()?, Split {
|
||||||
|
"n" => North,
|
||||||
|
"s" => South,
|
||||||
|
"e" => East,
|
||||||
|
"w" => West,
|
||||||
|
"a" => Above,
|
||||||
|
"b" => Below
|
||||||
|
}).stack(
|
||||||
|
draw(move|output: &mut O|{
|
||||||
|
state.interpret(output, &expr.tail().tail().head()?)
|
||||||
|
}),
|
||||||
|
draw(move|output: &mut O|{
|
||||||
|
state.interpret(output, &expr.tail().tail().tail().head()?)
|
||||||
|
}),
|
||||||
|
).draw(output)
|
||||||
|
}).transpose()?.flatten())
|
||||||
|
});
|
||||||
|
|
||||||
|
fn_kw_layout!(kw_align |state, output, expr| {
|
||||||
|
Ok(matches!(expr.head()?, Some("align")).then(||{
|
||||||
|
draw(move|output: &mut O|{state.interpret(output, &expr.tail().head())}).align(
|
||||||
|
eval_enum!("align", output, state,
|
||||||
|
expr.head().src()?.unwrap_or_default().split("/").skip(1).next(),
|
||||||
|
expr.tail().head(),
|
||||||
|
Azimuth {
|
||||||
|
"c" => C, "x" => X, "y" => Y,
|
||||||
|
"n" => N, "s" => S, "e" => E, "w" => W,
|
||||||
|
"nw" => NW, "sw" => SW, "ne" => NE, "se" => SE,
|
||||||
|
})
|
||||||
|
).draw(output)
|
||||||
|
}).transpose()?.flatten())
|
||||||
|
});
|
||||||
|
|
||||||
|
fn_kw_layout!(kw_exact |state, output, expr| {
|
||||||
|
Ok(matches!(expr.head()?, Some("exact")).then(||{
|
||||||
|
let head = expr.head()?;
|
||||||
let args = expr.tail();
|
let args = expr.tail();
|
||||||
let arg0 = args.head();
|
let arg0 = args.head();
|
||||||
let tail0 = args.tail();
|
let tail0 = args.tail();
|
||||||
let arg1 = tail0.head();
|
let arg1 = tail0.head();
|
||||||
let tail1 = tail0.tail();
|
let tail1 = tail0.tail();
|
||||||
let arg2 = tail1.head();
|
let arg2 = tail1.head();
|
||||||
// First `frags.next()` calls returns the namespace.
|
let mut frags = head.src()?.unwrap_or_default().split("/").skip(1);
|
||||||
match frags.next() {
|
eval_xy!("exact" => expr, head, output, state, frags.next(), exact_wh, exact_w, exact_h,
|
||||||
|
arg0, arg1, arg2,)
|
||||||
|
}).transpose()?.flatten())
|
||||||
|
});
|
||||||
|
|
||||||
Some("when") => when(
|
fn_kw_layout!(kw_fixed |state, output, expr| {
|
||||||
state.namespace(arg0?)?.unwrap(),
|
Ok(matches!(expr.head()?, Some("exact")).then(||{
|
||||||
draw(move|output: &mut O|{state.interpret(output, &arg1)})
|
let head = expr.head()?;
|
||||||
).draw(output),
|
let args = expr.tail();
|
||||||
|
let arg0 = args.head();
|
||||||
|
let tail0 = args.tail();
|
||||||
|
let arg1 = tail0.head();
|
||||||
|
let tail1 = tail0.tail();
|
||||||
|
let arg2 = tail1.head();
|
||||||
|
let mut frags = head.src()?.unwrap_or_default().split("/").skip(1);
|
||||||
|
eval_xy!("fixed" => expr, head, output, state, frags.next(), exact_wh, exact_w, exact_h,
|
||||||
|
arg0, arg1, arg2,)
|
||||||
|
}).transpose()?.flatten())
|
||||||
|
});
|
||||||
|
|
||||||
Some("either") => either(
|
fn_kw_layout!(kw_min |state, output, expr| {
|
||||||
state.namespace(arg0?)?.unwrap(),
|
Ok(matches!(expr.head()?, Some("exact")).then(||{
|
||||||
draw(move|output: &mut O|{state.interpret(output, &arg1)}),
|
let head = expr.head()?;
|
||||||
draw(move|output: &mut O|{state.interpret(output, &arg2)}),
|
let args = expr.tail();
|
||||||
).draw(output),
|
let arg0 = args.head();
|
||||||
|
let tail0 = args.tail();
|
||||||
|
let arg1 = tail0.head();
|
||||||
|
let tail1 = tail0.tail();
|
||||||
|
let arg2 = tail1.head();
|
||||||
|
let mut frags = head.src()?.unwrap_or_default().split("/").skip(1);
|
||||||
|
eval_xy!("min" => expr, head, output, state, frags.next(), min_wh, min_w, min_h,
|
||||||
|
arg0, arg1, arg2,)
|
||||||
|
}).transpose()?.flatten())
|
||||||
|
});
|
||||||
|
|
||||||
Some("bsp") => eval_enum!("bsp", output, state, frags.next(), arg0, Split {
|
fn_kw_layout!(kw_max |state, output, expr| {
|
||||||
"n" => North, "s" => South, "e" => East, "w" => West, "a" => Above, "b" => Below
|
Ok(matches!(expr.head()?, Some("exact")).then(||{
|
||||||
}).stack(
|
let head = expr.head()?;
|
||||||
draw(move|output: &mut O|{state.interpret(output, &arg0)}),
|
let args = expr.tail();
|
||||||
draw(move|output: &mut O|{state.interpret(output, &arg1)}),
|
let arg0 = args.head();
|
||||||
).draw(output),
|
let tail0 = args.tail();
|
||||||
|
let arg1 = tail0.head();
|
||||||
|
let tail1 = tail0.tail();
|
||||||
|
let arg2 = tail1.head();
|
||||||
|
let mut frags = head.src()?.unwrap_or_default().split("/").skip(1);
|
||||||
|
eval_xy!("max" => expr, head, output, state, frags.next(), max_wh, max_w, max_h,
|
||||||
|
arg0, arg1, arg2,)
|
||||||
|
}).transpose()?.flatten())
|
||||||
|
});
|
||||||
|
|
||||||
Some("align") => draw(move|output: &mut O|{state.interpret(output, &arg0)})
|
fn_kw_layout!(kw_push |state, output, expr| {
|
||||||
.align(eval_enum!("align", output, state, frags.next(), arg0, Azimuth {
|
Ok(matches!(expr.head()?, Some("push")).then(||{
|
||||||
"c" => C, "x" => X, "y" => Y,
|
let head = expr.head()?;
|
||||||
"n" => N, "s" => S, "e" => E, "w" => W,
|
let args = expr.tail();
|
||||||
"nw" => NW, "sw" => SW, "ne" => NE, "se" => SE,
|
let arg0 = args.head();
|
||||||
})).draw(output),
|
let tail0 = args.tail();
|
||||||
|
let arg1 = tail0.head();
|
||||||
Some("exact") => eval_xy!(
|
let tail1 = tail0.tail();
|
||||||
"exact" => expr, head, output, state, frags.next(), exact_wh, exact_w, exact_h, arg0, arg1, arg2,
|
let arg2 = tail1.head();
|
||||||
),
|
let mut frags = head.src()?.unwrap_or_default().split("/").skip(1);
|
||||||
|
eval_xy!("push" => expr, head, output, state, frags.next(), push_xy, push_x, push_y,
|
||||||
Some("fixed") => eval_xy!(
|
arg0, arg1, arg2,)
|
||||||
"fixed" => expr, head, output, state, frags.next(), exact_wh, exact_w, exact_h, arg0, arg1, arg2,
|
}).transpose()?.flatten())
|
||||||
),
|
});
|
||||||
|
|
||||||
Some("min") => eval_xy!(
|
|
||||||
"min" => expr, head, output, state, frags.next(), min_wh, min_w, min_h, arg0, arg1, arg2,
|
|
||||||
),
|
|
||||||
|
|
||||||
Some("max") => eval_xy!(
|
|
||||||
"max" => expr, head, output, state, frags.next(), max_wh, max_w, max_h, arg0, arg1, arg2,
|
|
||||||
),
|
|
||||||
|
|
||||||
Some("push") => eval_xy!(
|
|
||||||
"push" => expr, head, output, state, frags.next(), push_xy, push_x, push_y, arg0, arg1, arg2,
|
|
||||||
),
|
|
||||||
|
|
||||||
Some("fill") => eval_xy!(
|
|
||||||
"fill" => expr, head, output, state, frags.next(), full_wh, full_w, full_h, arg0,
|
|
||||||
),
|
|
||||||
|
|
||||||
_ => return Ok(None)
|
|
||||||
|
|
||||||
|
#[cfg(feature = "term")] fn_kw_layout_tui!(kw_tui_text |state, output, expr| {
|
||||||
|
Ok(matches!(expr.head()?, Some("text")).then(||{
|
||||||
|
let args = expr.tail();
|
||||||
|
let arg0 = args.head();
|
||||||
|
let tail0 = args.tail();
|
||||||
|
let arg1 = tail0.head();
|
||||||
|
if let Some(src) = args?.src()? {
|
||||||
|
src.draw(output)
|
||||||
|
} else {
|
||||||
|
return Ok(None)
|
||||||
}
|
}
|
||||||
}
|
}).transpose()?.flatten())
|
||||||
|
});
|
||||||
|
|
||||||
fn invalid_variant <T> (
|
#[cfg(feature = "term")] fn_kw_layout_tui!(kw_tui_fg |state, output, expr| {
|
||||||
|
Ok(matches!(expr.head()?, Some("fg")).then(||{
|
||||||
|
let args = expr.tail();
|
||||||
|
let arg0 = args.head();
|
||||||
|
let tail0 = args.tail();
|
||||||
|
let arg1 = tail0.head();
|
||||||
|
if let Some(color) = Namespace::namespace(
|
||||||
|
state, arg0?.expect("fg: expected arg 0 (color)")
|
||||||
|
)? {
|
||||||
|
fg(color, draw(move|to: &mut Tui|state.interpret(to, &arg1))).draw(output)
|
||||||
|
} else {
|
||||||
|
return Err(format!("fg: {arg0:?}: not a color").into())
|
||||||
|
}
|
||||||
|
}).transpose()?.flatten())
|
||||||
|
});
|
||||||
|
|
||||||
|
#[cfg(feature = "term")] fn_kw_layout_tui!(kw_tui_bg |state, output, expr| {
|
||||||
|
Ok(matches!(expr.head()?, Some("bg")).then(||{
|
||||||
|
let head = expr.head()?;
|
||||||
|
let args = expr.tail();
|
||||||
|
let arg0 = args.head();
|
||||||
|
let tail0 = args.tail();
|
||||||
|
let arg1 = tail0.head();
|
||||||
|
let mut frags = head.src()?.unwrap_or_default().split("/");
|
||||||
|
let arg0 = arg0?.expect("bg: expected arg 0 (color)");
|
||||||
|
if let Some(color) = Namespace::namespace(state, arg0)? {
|
||||||
|
bg(color, draw(move|to: &mut Tui|state.interpret(to, &arg1))).draw(output)
|
||||||
|
} else {
|
||||||
|
return Err(format!("bg: {arg0:?}: not a color").into())
|
||||||
|
}
|
||||||
|
}).transpose()?.flatten())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn invalid_variant <T> (
|
||||||
name: &str,
|
name: &str,
|
||||||
frag: impl Language,
|
frag: impl Language,
|
||||||
expr: impl Language,
|
expr: impl Language,
|
||||||
head: impl Language,
|
head: impl Language,
|
||||||
) -> Usually<T> {
|
) -> Usually<T> {
|
||||||
unimplemented!(
|
unimplemented!(
|
||||||
"{name}/{frag:?} ({expr:?}) ({head:?}) ({:?})",
|
"{name}/{frag:?} ({expr:?}) ({head:?}) ({:?})",
|
||||||
head.src()?.unwrap_or_default().split("/").next()
|
head.src()?.unwrap_or_default().split("/").next()
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{*, draw::*};
|
use crate::*;
|
||||||
|
|
||||||
/// Draw border around item shrunk by 1 on each side.
|
/// Draw border around item shrunk by 1 on each side.
|
||||||
///
|
///
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{*, draw::*, Color::*};
|
use crate::{*, Color::*};
|
||||||
|
|
||||||
/// ```
|
/// ```
|
||||||
/// let _ = tengri::button_2("", "", true);
|
/// let _ = tengri::button_2("", "", true);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{*, draw::*, Color::*};
|
use crate::*;
|
||||||
|
|
||||||
/// Stackably padded.
|
/// Stackably padded.
|
||||||
///
|
///
|
||||||
|
|
@ -18,10 +18,10 @@ pub const HI: &'static str = "▀";
|
||||||
|
|
||||||
/// A phat line
|
/// A phat line
|
||||||
fn phat_lo (fg: Color, bg: Color) -> impl Draw<Tui> {
|
fn phat_lo (fg: Color, bg: Color) -> impl Draw<Tui> {
|
||||||
fg_bg(fg, bg, x_repeat(self::phat::LO)).exact_h(1)
|
fg_bg(fg, bg, x_repeat(LO)).exact_h(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A phat line
|
/// A phat line
|
||||||
fn phat_hi (fg: Color, bg: Color) -> impl Draw<Tui> {
|
fn phat_hi (fg: Color, bg: Color) -> impl Draw<Tui> {
|
||||||
fg_bg(fg, bg, x_repeat(self::phat::HI)).exact_h(1)
|
fg_bg(fg, bg, x_repeat(HI)).exact_h(1)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{*, draw::*};
|
use crate::*;
|
||||||
use ratatui::{prelude::{Position}};
|
use ratatui::{prelude::{Position}};
|
||||||
|
|
||||||
pub const fn x_repeat (c: &str) -> impl Draw<Tui> {
|
pub const fn x_repeat (c: &str) -> impl Draw<Tui> {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{*, draw::*, Color::*};
|
use crate::{*, Color::*};
|
||||||
use ratatui::{prelude::{Position}};
|
use ratatui::{prelude::{Position}};
|
||||||
|
|
||||||
pub const ICON_DEC_V: &[char] = &['▲'];
|
pub const ICON_DEC_V: &[char] = &['▲'];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue