From b09719993af0b9150b8b79c3ec08601795c5cd4e Mon Sep 17 00:00:00 2001 From: facile pop culture reference Date: Thu, 6 Aug 2026 08:32:48 +0300 Subject: [PATCH 1/3] implement iter_south with single iterator --- src/layout/iter.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/layout/iter.rs b/src/layout/iter.rs index e1cb3d9..bd80aae 100644 --- a/src/layout/iter.rs +++ b/src/layout/iter.rs @@ -43,10 +43,23 @@ pub fn iter_east_fixed <'a, S: Screen, D: 'a, I: Iterator, U: Draw> draw(move|_to: &mut S|{ todo!() }) } -pub fn iter_south <'a, S: Screen, D: 'a, I: Iterator, U: Draw> ( - _iter: impl Fn()->I, _draw: impl Fn(D, usize)->U, +pub fn iter_south <'a, S: Screen, D: Draw, I: Iterator> ( + iter: impl Fn()->I ) -> impl Draw { - 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, U: Draw> ( From 39d3dacf1f1099294ab41866b4abd6b60093e61e Mon Sep 17 00:00:00 2001 From: facile pop culture reference Date: Thu, 6 Aug 2026 10:18:28 +0300 Subject: [PATCH 2/3] fix bsp arg2 --- examples/mode_02.rs | 4 +++- src/layout/azimuth.rs | 7 +++---- src/lib.rs | 2 +- src/term.rs | 2 +- src/term/modify.rs | 3 ++- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/examples/mode_02.rs b/examples/mode_02.rs index 1ec2069..a077f20 100644 --- a/examples/mode_02.rs +++ b/examples/mode_02.rs @@ -42,7 +42,9 @@ impl_keywords!(Tui, XYWH, State [ kw_push, kw_tui_text, kw_tui_fg, - kw_tui_bg + kw_tui_bg, + kw_color_g, + kw_color_rgb, ]); impl Interpret>> for State { diff --git a/src/layout/azimuth.rs b/src/layout/azimuth.rs index ac749b8..2eeb0af 100644 --- a/src/layout/azimuth.rs +++ b/src/layout/azimuth.rs @@ -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()) diff --git a/src/lib.rs b/src/lib.rs index 119bd52..20cb81b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -182,7 +182,7 @@ pub trait AsMutOpt { 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),* $(,)? } ) => {{ diff --git a/src/term.rs b/src/term.rs index 9a66b5d..452c65f 100644 --- a/src/term.rs +++ b/src/term.rs @@ -500,7 +500,7 @@ impl> Draw for ShowSizeOf { } } -#[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) diff --git a/src/term/modify.rs b/src/term/modify.rs index 176971a..5a7512c 100644 --- a/src/term/modify.rs +++ b/src/term/modify.rs @@ -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)) => { From cf67185ffde1719bd5cc0c75cb0f9ac49d95a6d7 Mon Sep 17 00:00:00 2001 From: facile pop culture reference Date: Thu, 6 Aug 2026 10:18:35 +0300 Subject: [PATCH 3/3] allow exiting via flag --- src/lib.rs | 8 ++++++-- src/term.rs | 14 ++++++-------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 20cb81b..fd39be3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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); + #[derive(Clone, Default, Debug)] + pub struct Exit(Arc); impl Exit { pub fn run (run: impl FnOnce(Self)->Usually) -> Usually { @@ -269,6 +270,9 @@ macro_rules! eval_xy ( state: KeyEventState::NONE })) } + pub fn exit (&self) { + self.0.store(true, Relaxed) + } } impl AsRef> for Exit { diff --git a/src/term.rs b/src/term.rs index 452c65f..298dacb 100644 --- a/src/term.rs +++ b/src/term.rs @@ -145,16 +145,14 @@ impl Tui { panic(info); })); } - pub fn run_main (state: Arc>) -> Usually<()> where + pub fn run_main (exit: Exit, state: Arc>) -> Usually<()> where T: View + Apply> + 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 <