mirror of
https://codeberg.org/unspeaker/tek.git
synced 2026-09-18 04:46:43 +02:00
fix config and compilation; add arg! macro
This commit is contained in:
parent
e29f8de174
commit
1082f62696
2 changed files with 70 additions and 85 deletions
130
src/config.rs
130
src/config.rs
|
|
@ -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))
|
||||
|
|
|
|||
17
src/tek.edn
17
src/tek.edn
|
|
@ -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))))
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue