fix config and compilation; add arg! macro

This commit is contained in:
i do not exist 2026-08-30 22:30:30 +03:00
parent e29f8de174
commit 1082f62696
2 changed files with 70 additions and 85 deletions

View file

@ -23,7 +23,7 @@ pub fn config_init <C: AsRef<Config>> (config: C) -> Usually<C> {
pub fn config_load <C: AsRef<Config>, L: Language> (config: C, src: L) -> Usually<C> {
config.as_ref().clear();
config.as_ref().stamp.store(quanta::Clock::new().raw(), Relaxed);
src.each(config, |c, s|config_load_item(c, s))
src.each(config, |c, s|config_load_item(c, s.trim()))
}
pub fn config_load_item <C: AsRef<Config>, L: Language> (config: C, src: L) -> Usually<C> {
@ -263,9 +263,9 @@ impl View<Tui, App> {
Usually<Arc<Box<dyn Fn(&App, &mut Tui)->Drawn<u16> + Send + Sync>>>
{
let source = source.as_ref();
let layer = if let Some(expr) = source.expr()? {
let layer = if let Ok(Some(expr)) = source.expr() {
Self::compile_expr(expr.into())?
} else if let Some(word) = source.word()? {
} else if let Ok(Some(word)) = source.word() {
Self::compile_word(word.into())?
} else {
return Err(format!("not word/expr:\n{source:?}").into())
@ -276,15 +276,24 @@ impl View<Tui, App> {
fn compile_expr (expr: Arc<str>) ->
Usually<Arc<Box<dyn Fn(&App, &mut Tui)->Drawn<u16> + Send + Sync>>>
{
macro_rules! arg {
($src:expr, $head:expr, $index:expr, $name:expr) => {
$src.nth($index)?
.ok_or_else(||Box::<dyn Error>::from(format!(
"{}: no arg #{} ({}) in {}", $head, $index, $name, $src
)))?
};
}
Ok(Arc::new(if let Some(head) = expr.head()? && let Some(ns) = head.split('/').next() {
match ns {
"when" => {
let cond = Arc::from(expr.nth(1)?.ok_or_else(||Box::<dyn Error>::from("when: no arg0: condition"))?);
let cond = Arc::from(arg!(expr, head, 1, "condition"));
let cond = move|state: &App|state.namespace(&cond)?.ok_or_else(||Box::<dyn Error>::from("when: no condition value"));
let thunk = expr.nth(2)?.ok_or_else(||Box::<dyn Error>::from("when: no arg1: content"))?;
let thunk = Self::compile(thunk)?;
let thunk = Self::compile(arg!(expr, head, 2, "content"))?;
Self::boxed(move|state, screen|{
when(
cond(state)?,
@ -294,12 +303,10 @@ impl View<Tui, App> {
},
"either" => {
let cond = Arc::from(expr.nth(1)?.ok_or_else(||Box::<dyn Error>::from("either: no arg0: condition"))?);
let cond = Arc::from(arg!(expr, head, 1, "condition"));
let cond = move|state: &App|state.namespace(&cond)?.ok_or_else(||Box::<dyn Error>::from("either: no condition value"));
let a = expr.nth(2)?.ok_or_else(||Box::<dyn Error>::from("either: no arg1: content"))?;
let a = Self::compile(a)?;
let b = expr.nth(3)?.ok_or_else(||Box::<dyn Error>::from("either: no arg2: content"))?;
let b = Self::compile(b)?;
let a = Self::compile(arg!(expr, head, 2, "content A"))?;
let b = Self::compile(arg!(expr, head, 3, "content B"))?;
Self::boxed(move|state, screen|{
either(
cond(state)?,
@ -309,7 +316,7 @@ impl View<Tui, App> {
})
},
"bsp" | "split" => {
"bsp" | "split" | "stack" => {
let split = head.split('/').skip(1).next();
let split = match split {
Some("n") => Split::North,
@ -320,8 +327,8 @@ impl View<Tui, App> {
Some("b") => Split::Below,
_ => return Err(format!("invalid split: {split:?}").into())
};
let a = Self::compile(expr.nth(1)?.ok_or_else(||Box::<dyn Error>::from("either: no arg0: content"))?)?;
let b = Self::compile(expr.nth(2)?.ok_or_else(||Box::<dyn Error>::from("either: no arg1: content"))?)?;
let a = Self::compile(arg!(expr, head, 1, "content A"))?;
let b = Self::compile(arg!(expr, head, 2, "content B"))?;
Self::boxed(move|state, screen|{
split.stack(
draw(|screen|a(state, screen)),
@ -346,8 +353,7 @@ impl View<Tui, App> {
Some("y") => Azimuth::Y,
_ => return Err(format!("invalid azimuth: {azimuth:?}").into())
};
let thunk = Self::compile(expr.nth(2)?
.ok_or_else(||Box::<dyn Error>::from("either: no arg1: content"))?)?;
let thunk = Self::compile(arg!(expr, head, 1, "content"))?;
Self::boxed(move|state, screen|{
Align(
Some(azimuth),
@ -356,9 +362,8 @@ impl View<Tui, App> {
})
},
"full" => {
let thunk = Self::compile(expr.nth(2)?
.ok_or_else(||Box::<dyn Error>::from("either: no arg1: content"))?)?;
"full" | "fill" => {
let thunk = Self::compile(arg!(expr, head, 1, "content"))?;
match head.split('/').skip(1).next() {
Some("w") | Some("x") => Self::boxed(move|state, screen|{
Full::W(draw(|screen|thunk(state, screen))).draw(screen)
@ -366,83 +371,56 @@ impl View<Tui, App> {
Some("h") | Some("y") => Self::boxed(move|state, screen|{
Full::H(draw(|screen|thunk(state, screen))).draw(screen)
}),
Some("wh") | Some("xy") => Self::boxed(move|state, screen|{
Some("wh") | Some("xy") | None => Self::boxed(move|state, screen|{
Full::WH(draw(|screen|thunk(state, screen))).draw(screen)
}),
_ => unreachable!()
}
},
"exact" | "min" | "max" | "push" | "pull" => {
"exact" | "min" | "max" | "push" | "pull" | "pad" => {
match head.split('/').skip(1).next() {
Some("w") | Some("x") => {
let value = Arc::from(expr.nth(1)?.ok_or_else(||Box::<dyn Error>::from("{}: no arg1: value"))?);
let value = Arc::from(arg!(expr, head, 1, "value"));
let value = move|state: &App|state.namespace(&value);
let thunk = Self::compile(expr.nth(2)?.ok_or_else(||Box::<dyn Error>::from("either: no arg2: content"))?)?;
let thunk = Self::compile(arg!(expr, head, 2, "content"))?;
match ns {
"exact" => Self::boxed(move|state, screen|Exact::W(
draw(|screen|thunk(state, screen)), value(state)?
).draw(screen)),
"push" => Self::boxed(move|state, screen|Push::X(
draw(|screen|thunk(state, screen)), value(state)?
).draw(screen)),
"pull" => Self::boxed(move|state, screen|Pull::X(
draw(|screen|thunk(state, screen)), value(state)?
).draw(screen)),
"min" => Self::boxed(move|state, screen|Min::W(
draw(|screen|thunk(state, screen)), value(state)?
).draw(screen)),
"max" => Self::boxed(move|state, screen|Max::W(
draw(|screen|thunk(state, screen)), value(state)?
).draw(screen)),
"exact" => Self::boxed(move|state, screen|Exact::W(draw(|screen|thunk(state, screen)), value(state)?).draw(screen)),
"push" => Self::boxed(move|state, screen|Push::X(draw(|screen|thunk(state, screen)), value(state)?).draw(screen)),
"pull" => Self::boxed(move|state, screen|Pull::X(draw(|screen|thunk(state, screen)), value(state)?).draw(screen)),
"pad" => Self::boxed(move|state, screen|Pad::X(draw(|screen|thunk(state, screen)), value(state)?).draw(screen)),
"min" => Self::boxed(move|state, screen|Min::W(draw(|screen|thunk(state, screen)), value(state)?).draw(screen)),
"max" => Self::boxed(move|state, screen|Max::W(draw(|screen|thunk(state, screen)), value(state)?).draw(screen)),
_ => unreachable!()
}
},
Some("h") | Some("y") => {
let value = Arc::from(expr.nth(1)?.ok_or_else(||Box::<dyn Error>::from("{}: no arg1: value"))?);
let value = Arc::from(arg!(expr, head, 1, "value"));
let value = move|state: &App|state.namespace(&value);
let thunk = Self::compile(expr.nth(2)?.ok_or_else(||Box::<dyn Error>::from("either: no arg2: content"))?)?;
let thunk = Self::compile(arg!(expr, head, 2, "content"))?;
match ns {
"exact" => Self::boxed(move|state, screen|Exact::H(
draw(|screen|thunk(state, screen)), value(state)?
).draw(screen)),
"push" => Self::boxed(move|state, screen|Push::Y(
draw(|screen|thunk(state, screen)), value(state)?
).draw(screen)),
"pull" => Self::boxed(move|state, screen|Pull::Y(
draw(|screen|thunk(state, screen)), value(state)?
).draw(screen)),
"min" => Self::boxed(move|state, screen|Min::H(
draw(|screen|thunk(state, screen)), value(state)?
).draw(screen)),
"max" => Self::boxed(move|state, screen|Max::H(
draw(|screen|thunk(state, screen)), value(state)?
).draw(screen)),
"exact" => Self::boxed(move|state, screen|Exact::H(draw(|screen|thunk(state, screen)), value(state)?).draw(screen)),
"push" => Self::boxed(move|state, screen|Push::Y(draw(|screen|thunk(state, screen)), value(state)?).draw(screen)),
"pull" => Self::boxed(move|state, screen|Pull::Y(draw(|screen|thunk(state, screen)), value(state)?).draw(screen)),
"pad" => Self::boxed(move|state, screen|Pad::Y(draw(|screen|thunk(state, screen)), value(state)?).draw(screen)),
"min" => Self::boxed(move|state, screen|Min::H(draw(|screen|thunk(state, screen)), value(state)?).draw(screen)),
"max" => Self::boxed(move|state, screen|Max::H(draw(|screen|thunk(state, screen)), value(state)?).draw(screen)),
_ => unreachable!()
}
},
Some("wh") | Some("xy") => {
let value1 = Arc::from(expr.nth(1)?.ok_or_else(||Box::<dyn Error>::from("{}: no arg1: value"))?);
Some("wh") | Some("xy") | None => {
let value1 = Arc::from(arg!(expr, head, 1, "value"));
let value1 = move|state: &App|state.namespace(&value1);
let value2 = Arc::from(expr.nth(2)?.ok_or_else(||Box::<dyn Error>::from("{}: no arg2: value"))?);
let value2 = Arc::from(arg!(expr, head, 2, "value"));
let value2 = move|state: &App|state.namespace(&value2);
let thunk = Self::compile(expr.nth(3)?.ok_or_else(||Box::<dyn Error>::from("either: no arg3: content"))?)?;
let thunk = Self::compile(arg!(expr, head, 3, "content"))?;
match ns {
"exact" => Self::boxed(move|state, screen|Exact::WH(
draw(|screen|thunk(state, screen)), value1(state)?, value2(state)?
).draw(screen)),
"push" => Self::boxed(move|state, screen|Push::XY(
draw(|screen|thunk(state, screen)), value1(state)?, value2(state)?
).draw(screen)),
"pull" => Self::boxed(move|state, screen|Pull::XY(
draw(|screen|thunk(state, screen)), value1(state)?, value2(state)?
).draw(screen)),
"min" => Self::boxed(move|state, screen|Min::WH(
draw(|screen|thunk(state, screen)), value1(state)?, value2(state)?
).draw(screen)),
"max" => Self::boxed(move|state, screen|Max::WH(
draw(|screen|thunk(state, screen)), value1(state)?, value2(state)?
).draw(screen)),
"exact" => Self::boxed(move|state, screen|Exact::WH(draw(|screen|thunk(state, screen)), value1(state)?, value2(state)?).draw(screen)),
"push" => Self::boxed(move|state, screen|Push::XY(draw(|screen|thunk(state, screen)), value1(state)?, value2(state)?).draw(screen)),
"pull" => Self::boxed(move|state, screen|Pull::XY(draw(|screen|thunk(state, screen)), value1(state)?, value2(state)?).draw(screen)),
"pad" => Self::boxed(move|state, screen|Pad::XY(draw(|screen|thunk(state, screen)), value1(state)?, value2(state)?).draw(screen)),
"min" => Self::boxed(move|state, screen|Min::WH(draw(|screen|thunk(state, screen)), value1(state)?, value2(state)?).draw(screen)),
"max" => Self::boxed(move|state, screen|Max::WH(draw(|screen|thunk(state, screen)), value1(state)?, value2(state)?).draw(screen)),
_ => unreachable!()
}
},
@ -451,9 +429,9 @@ impl View<Tui, App> {
},
"fg" | "bg" => {
let color = Arc::from(expr.nth(1)?.ok_or_else(||Box::<dyn Error>::from("{}: no arg1: color"))?);
let color = Arc::from(arg!(expr, head, 1, "color"));
let color = move|state: &App|state.namespace(&color);
let thunk = Self::compile(expr.nth(2)?.ok_or_else(||Box::<dyn Error>::from("either: no arg2: thunk"))?)?;
let thunk = Self::compile(arg!(expr, head, 2, "content"))?;
match ns {
"fg" => Self::boxed(move|state, screen|fg(
color(state)?.unwrap_or_default(), draw(|screen|thunk(state, screen))

View file

@ -1,8 +1,8 @@
(view :logo (text tek))
(view :browse (bsp/s
(pad 3 1 :browse-title)
(fg (g 96) browser))
(pad/xy 3 1 :browse-title)
(fg (g 96) browser)))
(mode :transport
(name Transport)
@ -82,22 +82,29 @@
(mode browse (keys :browse))
(mode rename (keys :pool/rename))
(mode length (keys :pool/length))
(view
(bsp/s (exact/h 1 :transport)
(bsp/n (exact/h 1 :status)
(fill (bsp/a (fill/xy (align/e :pool)) :editor)))))
(fill/xy (bsp/a (fill/xy (align/e :pool))
:editor))))))
(mode :sampler (name Sampler) (info Sample player.)
(keys :sampler/directions :sampler/record :sampler/play)
(view
(bsp/s (exact/h 1 :transport)
(bsp/n (exact/h 1 :status)
(fill :samples/grid))))
(fill/xy :samples/grid)))))
(mode :groovebox (name Groovebox) (info Sequencer with sampler.)
(keys :clock :editor :sampler :global)
(mode browse (keys :browse))
(mode rename (keys :pool-rename))
(mode length (keys :pool-length))
(bsp/w :meters/output (bsp/e :meters/input (bsp/w :groove/meta :groove/editor))))
(view
(bsp/w :meters/output
(bsp/e :meters/input
(bsp/w :groove/meta
:groove/editor)))))
(view :groove/meta (fill/y (align/n (stack/s :midi-ins/status :midi-outs/status :audio-ins/status :audio-outs/status :pool))))