mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2026-07-17 07:56:56 +02:00
rehash eval_xy and implement a few more modifiers
Some checks failed
/ build (push) Has been cancelled
Some checks failed
/ build (push) Has been cancelled
This commit is contained in:
parent
aa0dd37d88
commit
e398541b7e
2 changed files with 139 additions and 89 deletions
|
|
@ -167,8 +167,26 @@ pub enum Full<T: Screen, I: Draw<T>> {
|
||||||
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|{
|
||||||
todo!()
|
let XYWH(x0, y0, w0, h0) = to.area();
|
||||||
|
match self {
|
||||||
|
Self::W(item) => if let Some(XYWH(_, y, _, h)) = item.layout(to.area())? {
|
||||||
|
to.clip(XYWH(x0, y, w0, h), |to|item.draw(to))
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
},
|
||||||
|
Self::H(item) => if let Some(XYWH(x, _, w, _)) = item.layout(to.area())? {
|
||||||
|
to.clip(XYWH(x, y0, w, h0), |to|item.draw(to))
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
},
|
||||||
|
Self::WH(item) => if let Some(XYWH(..)) = item.layout(to.area())? {
|
||||||
|
to.clip(XYWH(x0, y0, w0, h0), |to|item.draw(to))
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
},
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Move content in the positive direction of one or both axes.
|
/// Move content in the positive direction of one or both axes.
|
||||||
|
|
@ -186,8 +204,26 @@ pub enum Push<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
||||||
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|{
|
||||||
todo!()
|
match self {
|
||||||
|
Self::__(_) => unreachable!(),
|
||||||
|
Self::X(item, x1) if let Some(XYWH(x, y, w, h)) = item.layout(to.area())? => {
|
||||||
|
to.clip(XYWH(
|
||||||
|
x + x1.into().unwrap_or_default(), y, w, h
|
||||||
|
), |to|item.draw(to))
|
||||||
|
},
|
||||||
|
Self::Y(item, y1) if let Some(XYWH(x, y, w, h)) = item.layout(to.area())? => {
|
||||||
|
to.clip(XYWH(
|
||||||
|
x, y + y1.into().unwrap_or_default(), w, h
|
||||||
|
), |to|item.draw(to))
|
||||||
|
},
|
||||||
|
Self::XY(item, x1, y1) if let Some(XYWH(x, y, w, h)) = item.layout(to.area())? => {
|
||||||
|
to.clip(XYWH(
|
||||||
|
x + x1.into().unwrap_or_default(), y + y1.into().unwrap_or_default(), w, h
|
||||||
|
), |to|item.draw(to))
|
||||||
|
},
|
||||||
|
_ => Ok(None)
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Move content in the negative direction of one or both axes.
|
/// Move content in the negative direction of one or both axes.
|
||||||
|
|
@ -262,8 +298,20 @@ pub enum Exact<T: Screen, I: Draw<T>, X: Into<Option<T::Unit>>> {
|
||||||
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|{
|
||||||
todo!()
|
match self {
|
||||||
|
Self::__(_) => unreachable!(),
|
||||||
|
Self::W(item, w1) if let Some(XYWH(x, y, w, h)) = item.layout(to.area())? => {
|
||||||
|
to.clip(XYWH(x, y, w1.into().unwrap_or(w), h), |to|item.draw(to))
|
||||||
|
},
|
||||||
|
Self::H(item, h1) if let Some(XYWH(x, y, w, h)) = item.layout(to.area())? => {
|
||||||
|
to.clip(XYWH(x, y, w, h1.into().unwrap_or(h)), |to|item.draw(to))
|
||||||
|
},
|
||||||
|
Self::WH(item, w1, h1) if let Some(XYWH(x, y, w, h)) = item.layout(to.area())? => {
|
||||||
|
to.clip(XYWH(x, y, w1.into().unwrap_or(w), h1.into().unwrap_or(h)), |to|item.draw(to))
|
||||||
|
},
|
||||||
|
_ => Ok(None)
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Define inner drawing area.
|
/// Define inner drawing area.
|
||||||
|
|
|
||||||
168
src/eval.rs
168
src/eval.rs
|
|
@ -1,52 +1,6 @@
|
||||||
use crate::{*, lang::*};
|
use crate::{*, lang::*};
|
||||||
use ratatui::style::Color;
|
use ratatui::style::Color;
|
||||||
|
|
||||||
/// Some layout operations exist in XY, X, and Y variants that take 3 or 2 arguments.
|
|
||||||
/// Their handling in [eval_view] is uniform and goes like this:
|
|
||||||
macro_rules! eval_xy ((
|
|
||||||
$name:expr, $expr:expr, $head:expr, $output:ident, $state:ident,
|
|
||||||
$variant:expr, $arg0: ident, $arg1: ident, $arg2: ident,
|
|
||||||
$xy:ident, $x:ident, $y:ident
|
|
||||||
) => {{
|
|
||||||
let variant = $variant;
|
|
||||||
let cb = thunk(move|output: &mut O|$state.interpret(output, &match variant {
|
|
||||||
Some("x") | Some("y") => $arg1,
|
|
||||||
Some("xy") | None => $arg2,
|
|
||||||
_ => panic!("{}: unsupported axis {variant:?}; try /x, /y, /xy", $name)
|
|
||||||
}));
|
|
||||||
|
|
||||||
match variant {
|
|
||||||
|
|
||||||
// XY variant (can be omitted)
|
|
||||||
Some("xy") | None => cb.push_xy(
|
|
||||||
$state.namespace($arg0?)?,
|
|
||||||
$state.namespace($arg1?)?,
|
|
||||||
).draw($output),
|
|
||||||
|
|
||||||
// X variant
|
|
||||||
Some("x") => cb.push_x(
|
|
||||||
$state.namespace($arg0?)?,
|
|
||||||
).draw($output),
|
|
||||||
|
|
||||||
// Y variant
|
|
||||||
Some("y") => cb.push_y(
|
|
||||||
$state.namespace($arg0?)?,
|
|
||||||
).draw($output),
|
|
||||||
|
|
||||||
// Other namespace members are invalid
|
|
||||||
frag => {
|
|
||||||
let name = $name;
|
|
||||||
let expr = $expr;
|
|
||||||
let head = $head;
|
|
||||||
unimplemented!(
|
|
||||||
"{name}/{frag:?} ({expr:?}) ({head:?}) ({:?})",
|
|
||||||
head.src()?.unwrap_or_default().split("/").next()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}});
|
|
||||||
|
|
||||||
/// 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 ((
|
||||||
|
|
@ -60,6 +14,75 @@ macro_rules! eval_enum ((
|
||||||
}
|
}
|
||||||
}});
|
}});
|
||||||
|
|
||||||
|
/// Some layout operations exist in XY, X, and Y variants that take 3 or 2 arguments.
|
||||||
|
/// Their handling in [eval_view] is uniform and goes like this:
|
||||||
|
macro_rules! eval_xy (
|
||||||
|
// Valueless variant:
|
||||||
|
// (fill/x ...)
|
||||||
|
// (fill/y ...)
|
||||||
|
// (fill/xy ...)
|
||||||
|
(
|
||||||
|
$name:expr => $expr:expr, $head:expr, $output:ident, $state:ident,
|
||||||
|
$variant:expr, $xy:ident, $x:ident, $y:ident, $arg: ident,
|
||||||
|
) => {{
|
||||||
|
// frags.next(): 2nd slash-delimited fragment: /x, /y, /xy
|
||||||
|
let variant = $variant;
|
||||||
|
let thunk = thunk(move|screen|$state.interpret(screen, &$arg));
|
||||||
|
match variant {
|
||||||
|
// X variant
|
||||||
|
Some("x") => thunk.$x().draw($output),
|
||||||
|
// Y variant
|
||||||
|
Some("y") => thunk.$y().draw($output),
|
||||||
|
// XY variant (can be omitted)
|
||||||
|
Some("xy") | None => thunk.$xy().draw($output),
|
||||||
|
// Other namespace members are invalid
|
||||||
|
frag => invalid_variant($name, frag, $expr, $head)
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
|
||||||
|
// Variadic variant:
|
||||||
|
// (push/x n ...)
|
||||||
|
// (push/y n ...)
|
||||||
|
// (push/xy n m ...)
|
||||||
|
(
|
||||||
|
$name:expr => $expr:expr, $head:expr, $output:ident, $state:ident,
|
||||||
|
$variant:expr, $xy:ident, $x:ident, $y:ident, $arg0: ident, $arg1: ident, $arg2: ident,
|
||||||
|
) => {{
|
||||||
|
// frags.next(): 2nd slash-delimited fragment: /x, /y, /xy
|
||||||
|
let variant = $variant;
|
||||||
|
let thunk = thunk(move|screen|$state.interpret(screen, &match variant {
|
||||||
|
Some("x") | Some("y") => $arg1,
|
||||||
|
Some("xy") | None => $arg2,
|
||||||
|
_ => panic!("{}: unsupported axis {variant:?}; try /x, /y, /xy", $name)
|
||||||
|
}));
|
||||||
|
match variant {
|
||||||
|
// X variant
|
||||||
|
Some("x") => thunk.$x($state.namespace($arg0?)?)
|
||||||
|
.draw($output),
|
||||||
|
// Y variant
|
||||||
|
Some("y") => thunk.$y($state.namespace($arg0?)?)
|
||||||
|
.draw($output),
|
||||||
|
// XY variant (can be omitted)
|
||||||
|
Some("xy") | None => thunk.$xy($state.namespace($arg0?)?, $state.namespace($arg1?)?)
|
||||||
|
.draw($output),
|
||||||
|
// Other namespace members are invalid
|
||||||
|
frag => invalid_variant($name, frag, $expr, $head)
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
);
|
||||||
|
|
||||||
|
fn invalid_variant <T> (
|
||||||
|
name: &str,
|
||||||
|
frag: impl Language,
|
||||||
|
expr: impl Language,
|
||||||
|
head: impl Language,
|
||||||
|
) -> Usually<T> {
|
||||||
|
unimplemented!(
|
||||||
|
"{name}/{frag:?} ({expr:?}) ({head:?}) ({:?})",
|
||||||
|
head.src()?.unwrap_or_default().split("/").next()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/// Interpret layout operation.
|
/// Interpret layout operation.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
|
|
@ -103,67 +126,46 @@ pub fn eval_view <'a, O: Screen + 'a, S> (
|
||||||
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.
|
// First `frags.next()` calls returns the namespace.
|
||||||
match frags.next() {
|
match frags.next() {
|
||||||
|
|
||||||
Some("when") => when(
|
Some("when") => when(
|
||||||
state.namespace(arg0?)?.unwrap(),
|
state.namespace(arg0?)?.unwrap(),
|
||||||
thunk(move|output: &mut O|{state.interpret(output, &arg1)})
|
thunk(move|output: &mut O|{state.interpret(output, &arg1)})
|
||||||
).draw(output),
|
).draw(output),
|
||||||
|
|
||||||
Some("either") => either(
|
Some("either") => either(
|
||||||
state.namespace(arg0?)?.unwrap(),
|
state.namespace(arg0?)?.unwrap(),
|
||||||
thunk(move|output: &mut O|{state.interpret(output, &arg1)}),
|
thunk(move|output: &mut O|{state.interpret(output, &arg1)}),
|
||||||
thunk(move|output: &mut O|{state.interpret(output, &arg2)}),
|
thunk(move|output: &mut O|{state.interpret(output, &arg2)}),
|
||||||
).draw(output),
|
).draw(output),
|
||||||
|
|
||||||
// Second `frags.next()` calls returns the namespace member.
|
|
||||||
Some("bsp") => eval_enum!("bsp", output, state, frags.next(), arg0, Split {
|
Some("bsp") => eval_enum!("bsp", output, state, frags.next(), arg0, Split {
|
||||||
"n" => North,
|
"n" => North, "s" => South, "e" => East, "w" => West, "a" => Above, "b" => Below
|
||||||
"s" => South,
|
|
||||||
"e" => East,
|
|
||||||
"w" => West,
|
|
||||||
"a" => Above,
|
|
||||||
"b" => Below
|
|
||||||
}).half(
|
}).half(
|
||||||
thunk(move|output: &mut O|{state.interpret(output, &arg0)}),
|
thunk(move|output: &mut O|{state.interpret(output, &arg0)}),
|
||||||
thunk(move|output: &mut O|{state.interpret(output, &arg1)}),
|
thunk(move|output: &mut O|{state.interpret(output, &arg1)}),
|
||||||
).draw(output),
|
).draw(output),
|
||||||
|
Some("align") => thunk(move|output: &mut O|{
|
||||||
Some("align") => {
|
state.interpret(output, &arg0)
|
||||||
let content = thunk(move|output: &mut O|{state.interpret(output, &arg0)});
|
}).align(eval_enum!("align", output, state, frags.next(), arg0, Azimuth {
|
||||||
content.align(eval_enum!("align", output, state, frags.next(), arg0, Azimuth {
|
"c" => C, "n" => N, "s" => S, "e" => E, "w" => W, "x" => X, "y" => Y
|
||||||
"c" => C,
|
})).draw(output),
|
||||||
"n" => N,
|
|
||||||
"s" => S,
|
|
||||||
"e" => E,
|
|
||||||
"w" => W,
|
|
||||||
"x" => X,
|
|
||||||
"y" => Y
|
|
||||||
})).draw(output)
|
|
||||||
},
|
|
||||||
|
|
||||||
Some("exact") => eval_xy!(
|
Some("exact") => eval_xy!(
|
||||||
"exact", expr, head, output, state, frags.next(),
|
"exact" => expr, head, output, state, frags.next(), exact_wh, exact_w, exact_h, arg0, arg1, arg2,
|
||||||
arg0, arg1, arg2, wh_exact, w_exact, h_exact
|
),
|
||||||
|
Some("fixed") => eval_xy!(
|
||||||
|
"fixed" => expr, head, output, state, frags.next(), exact_wh, exact_w, exact_h, arg0, arg1, arg2,
|
||||||
),
|
),
|
||||||
|
|
||||||
Some("min") => eval_xy!(
|
Some("min") => eval_xy!(
|
||||||
"min", expr, head, output, state, frags.next(),
|
"min" => expr, head, output, state, frags.next(), min_wh, min_w, min_h, arg0, arg1, arg2,
|
||||||
arg0, arg1, arg2, wh_min, w_min, h_min
|
|
||||||
),
|
),
|
||||||
|
|
||||||
Some("max") => eval_xy!(
|
Some("max") => eval_xy!(
|
||||||
"max", expr, head, output, state, frags.next(),
|
"max" => expr, head, output, state, frags.next(), max_wh, max_w, max_h, arg0, arg1, arg2,
|
||||||
arg0, arg1, arg2, wh_max, w_max, h_max
|
|
||||||
),
|
),
|
||||||
|
|
||||||
Some("push") => eval_xy!(
|
Some("push") => eval_xy!(
|
||||||
"push", expr, head, output, state, frags.next(),
|
"push" => expr, head, output, state, frags.next(), push_xy, push_x, push_y, arg0, arg1, arg2,
|
||||||
arg0, arg1, arg2, xy_push, x_push, y_push
|
),
|
||||||
|
Some("fill") => eval_xy!(
|
||||||
|
"fill" => expr, head, output, state, frags.next(), full_wh, full_w, full_h, arg0,
|
||||||
),
|
),
|
||||||
|
|
||||||
_ => return Ok(None)
|
_ => return Ok(None)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue