Compare commits

..

3 commits

Author SHA1 Message Date
facile pop culture reference
cf67185ffd allow exiting via flag
Some checks are pending
/ build (push) Waiting to run
2026-08-06 10:18:35 +03:00
facile pop culture reference
39d3dacf1f fix bsp arg2 2026-08-06 10:18:28 +03:00
facile pop culture reference
b09719993a implement iter_south with single iterator 2026-08-06 08:32:48 +03:00
6 changed files with 38 additions and 21 deletions

View file

@ -42,7 +42,9 @@ impl_keywords!(Tui, XYWH<u16>, State [
kw_push,
kw_tui_text,
kw_tui_fg,
kw_tui_bg
kw_tui_bg,
kw_color_g,
kw_color_rgb,
]);
impl Interpret<Tui, Option<XYWH<u16>>> for State {

View file

@ -38,7 +38,6 @@ fn_kw_layout!(kw_align |state, output, expr| {
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,
@ -131,7 +130,7 @@ 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 {
eval_enum!("bsp", output, state, frags.next(), Split {
"n" => North,
"s" => South,
"e" => East,
@ -140,10 +139,10 @@ fn_kw_layout!(kw_split |state, output, expr| {
"b" => Below
}).stack(
draw(move|output: &mut O|{
state.interpret(output, &expr.tail().tail().head()?)
state.interpret(output, &expr.tail().head()?)
}),
draw(move|output: &mut O|{
state.interpret(output, &expr.tail().tail().tail().head()?)
state.interpret(output, &expr.tail().tail().head()?)
}),
).draw(output)
}).transpose()?.flatten())

View file

@ -43,10 +43,23 @@ pub fn iter_east_fixed <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<S>>
draw(move|_to: &mut S|{ todo!() })
}
pub fn iter_south <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<S>> (
_iter: impl Fn()->I, _draw: impl Fn(D, usize)->U,
pub fn iter_south <'a, S: Screen, D: Draw<S>, I: Iterator<Item = D>> (
iter: impl Fn()->I
) -> impl Draw<S> {
draw(move|_to: &mut S|{ todo!() })
draw(move|to: &mut S|{
let XYWH(x, mut y, w, mut h) = to.area();
let h0 = h;
for item in iter() {
if let Some(used) = to.draw(Some(XYWH(x, y, w, h)), item)? {
y = y.add(used.y());
h = h.minus(used.y());
if h == S::Unit::zero() {
break;
}
}
}
Ok(Some(XYWH(x, y, w, h)))
})
}
pub fn iter_south_fixed <'a, S: Screen, D: 'a, I: Iterator<Item = D>, U: Draw<S>> (

View file

@ -182,7 +182,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.
/// Their handling in [eval_view] is uniform and goes like this:
macro_rules! eval_enum ((
$name:literal, $output:ident, $state:ident, $value:expr, $arg0:expr, $Enum:ident {
$name:literal, $output:ident, $state:ident, $value:expr, $Enum:ident {
$($v:literal => $V:ident),* $(,)?
}
) => {{
@ -252,10 +252,11 @@ macro_rules! eval_xy (
#[cfg(feature = "exit")] pub use self::exit::*;
#[cfg(feature = "exit")] mod exit {
use crate::*;
use std::sync::{Arc, atomic::AtomicBool};
use std::sync::{Arc, atomic::{AtomicBool, Ordering::Relaxed}};
use crossterm::event::*;
#[derive(Clone)] pub struct Exit(Arc<AtomicBool>);
#[derive(Clone, Default, Debug)]
pub struct Exit(Arc<AtomicBool>);
impl Exit {
pub fn run <T> (run: impl FnOnce(Self)->Usually<T>) -> Usually<T> {
@ -269,6 +270,9 @@ macro_rules! eval_xy (
state: KeyEventState::NONE
}))
}
pub fn exit (&self) {
self.0.store(true, Relaxed)
}
}
impl AsRef<Arc<AtomicBool>> for Exit {

View file

@ -145,16 +145,14 @@ impl Tui {
panic(info);
}));
}
pub fn run_main <T> (state: Arc<RwLock<T>>) -> Usually<()> where
pub fn run_main <T> (exit: Exit, state: Arc<RwLock<T>>) -> Usually<()> where
T: View<Tui> + Apply<TuiEvent, Usually<()>> + Send + Sync + 'static
{
Exit::run(|exit|{
let scan = Duration::from_millis(100);
let frame = Duration::from_millis(10);
let (_input, output) = Tui::io(exit.as_ref(), &state, scan, frame, std::io::stdout())?;
let _ = output.join();
Tui::teardown(&mut stdout())
})
let scan = Duration::from_millis(100);
let frame = Duration::from_millis(10);
let (_input, output) = Tui::io(exit.as_ref(), &state, scan, frame, std::io::stdout())?;
let _ = output.join();
Tui::teardown(&mut stdout())
}
/// Spawn the TUI input and output threadsl.
pub fn io <
@ -500,7 +498,7 @@ impl<T: Draw<Tui>> Draw<Tui> for ShowSizeOf<T> {
}
}
#[cfg(feature = "eval")] fn_kw_layout_tui!(kw_tui_text |state, output, expr| {
#[cfg(feature = "eval")] fn_kw_layout_tui!(kw_tui_text |_state, output, expr| {
Ok(matches!(expr.head()?, Some("text")).then(||{
if let Some(src) = expr.tail().src()? {
src.draw(output)

View file

@ -36,7 +36,8 @@ impl Tui {
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"))?;
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)) => {