From 5357e832450e14ff98d814fdee0492000a296d57 Mon Sep 17 00:00:00 2001 From: i do not exist Date: Fri, 31 Jul 2026 06:59:00 +0300 Subject: [PATCH 1/2] tengri flat --- src/device/editor.rs | 2 +- src/tek.edn | 4 ++-- src/tek.rs | 38 ++++++++++++++++++++++++++++++++++++-- tengri | 2 +- 4 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/device/editor.rs b/src/device/editor.rs index bd02db77..7e130b37 100644 --- a/src/device/editor.rs +++ b/src/device/editor.rs @@ -131,7 +131,7 @@ impl MidiEditor { } /// ``` -/// use tek::{*, tengri::{*, lang::*}}; +/// use tek::{*, tengri::*}; /// /// struct Test(Option); /// impl_as_ref_opt!(MidiEditor: |self: Test|self.0.as_ref()); diff --git a/src/tek.edn b/src/tek.edn index 4dda6306..8fe0cd13 100644 --- a/src/tek.edn +++ b/src/tek.edn @@ -13,8 +13,8 @@ :transport) (mode :menu (name Menu) (info Mode selector.) (keys :axis/y :confirm) - (view (bg (g 64) - (bsp/s (max/xy 80 2 :transport) + (view (bg (g 16) + (bsp/s (fill/x (bg (g 32) (max/xy 80 2 :transport))) (bsp/s (max/y 3 (bg (g 80) :ports/out)) (bsp/n (max/y 3 (bg (g 80) :ports/in)) (bg (g 30) (bsp/s (max/y 6 :logo) :dialog/menu)))))))) diff --git a/src/tek.rs b/src/tek.rs index 4d918519..fe3b7f2c 100644 --- a/src/tek.rs +++ b/src/tek.rs @@ -25,7 +25,7 @@ pub(crate) use ::{ }, tengri::{ *, - lang::*, + dizzle::*, midly::{ Smf, TrackEventKind, MidiMessage, Error as MidiError, num::*, @@ -451,9 +451,11 @@ mod app { } } } + fn get_arc_str (&self, src: impl Language) -> Perhaps> { Ok(src.src()?.map(|x|x.into())) } + fn get_u16 (&self, src: impl Language) -> Perhaps { Ok(Some(match src.word()? { Some(":w/sidebar") => self.project.w_sidebar(self.editor().is_some()), @@ -461,6 +463,7 @@ mod app { _ => return try_to_u16(src) })) } + fn get_usize (&self, src: impl Language) -> Perhaps { Ok(Some(match src.word()? { Some(":scene-count") => self.scenes().len(), @@ -471,6 +474,7 @@ mod app { _ => return try_to_usize(src) })) } + fn get_bool (&self, src: impl Language) -> Perhaps { src.word()?.map(|word|Ok(match word { "Y" => true, @@ -491,6 +495,7 @@ mod app { _ => return Err(format!("not bool: {word}").into()) })).transpose() } + fn get_selection (&self, src: impl Language) -> Perhaps { src.word()?.map(|word|Ok(match word { ":select/scene" => self.selection().select_scene(self.tracks().len()), @@ -502,6 +507,7 @@ mod app { _ => return Err(format!("not selection: {word}").into()) })).transpose() } + fn get_color (&self, src: impl Language) -> Perhaps { if let Some(expr) = src.expr()? { match (expr.head()?, expr.tail()?) { @@ -531,6 +537,7 @@ mod app { return Err(format!("not a color: {:?}", src.src()?).into()) } } + fn get_opt_u7 (&self, src: impl Language) -> Perhaps> { src.word()?.map(|word|Ok(match word { ":editor/pitch" => Some(( @@ -539,9 +546,11 @@ mod app { _ => return Err(format!("unknown midi note: {word}").into()) })).transpose() } + fn get_opt_u16 (&self, _src: impl Language) -> Perhaps> { Ok(None) } + fn get_opt_usize (&self, src: impl Language) -> Perhaps> { src.word()?.map(|word|Ok(match word { ":selected/scene" => self.selection().scene(), @@ -549,6 +558,7 @@ mod app { _ => return Err(format!("unknown opt: {word}").into()) })).transpose() } + fn get_clip (&self, src: impl Language) -> Perhaps>>> { src.word()?.map(|word|Ok(match word { ":selected/clip" if let Selection::TrackClip { track, scene } = self.selection() => @@ -556,6 +566,7 @@ mod app { _ => return Err(format!("not a clip: {word}").into()) })).transpose() } + pub fn inc (&mut self, axis: &ControlAxis) -> Perhaps { Ok(match (&self.dialog, axis) { (Dialog::None, _) => todo!(), @@ -564,6 +575,7 @@ mod app { _ => todo!() }) } + pub fn dec (&mut self, axis: &ControlAxis) -> Perhaps { Ok(match (&self.dialog, axis) { (Dialog::None, _) => None, @@ -572,6 +584,7 @@ mod app { _ => todo!() }) } + pub fn confirm (&mut self) -> Perhaps { Ok(match &self.dialog { Dialog::Menu(index, items) => { @@ -582,6 +595,7 @@ mod app { _ => todo!(), }) } + } pub fn swap_value ( @@ -1033,6 +1047,26 @@ pub fn show_version () { //})?)? //} +/// Define an enum containing commands, and implement [Command] trait for over given `State`. +#[macro_export] macro_rules! def_command ( + ($Command:ident: |$state:ident: $State:ty| { + // FIXME: support attrs (docstrings) + $($Variant:ident$({$($arg:ident:$Arg:ty),+ $(,)?})?=>$body:expr),* $(,)? + })=>{ + #[derive(Debug)] pub enum $Command { + // FIXME: support attrs (docstrings) + $($Variant $({ $($arg: $Arg),* })?),* + } + impl ::tengri::dizzle::Act<$State> for $Command { + fn act (&self, $state: &mut $State) -> Perhaps { + match self { + $(Self::$Variant $({ $($arg),* })? => $body,)* + _ => unimplemented!("Act<{}>: {self:?}", stringify!($State)), + } + } + } + }); + pub use self::config::*; mod config { use crate::*; @@ -1456,7 +1490,7 @@ mod draw { fn tek_draw_expr (state: &App, to: &mut Tui, lang: &impl Expression) -> Drawn { Ok(Some(if let Some(area) = eval_view(state, to, lang)? { area - } else if let Some(area) = eval_view_tui(state, to, lang)? { + } else if let Some(area) = Tui::eval_view(state, to, lang)? { area } else { return Err(format!("App::interpret_expr: unexpected: {lang:?}").into()) diff --git a/tengri b/tengri index 5ca32929..fc01fd6a 160000 --- a/tengri +++ b/tengri @@ -1 +1 @@ -Subproject commit 5ca329292f808c137b6e2b7e80892e2a9e855696 +Subproject commit fc01fd6ad3a6ed4ee17d65a65b3e59df522f895a From 8de62463c08cecda9d5f469a38390a2f36fe3c50 Mon Sep 17 00:00:00 2001 From: i do not exist Date: Mon, 3 Aug 2026 09:41:07 +0300 Subject: [PATCH 2/2] thunk -> draw --- src/device/editor/piano.rs | 8 +++--- src/device/plugin.rs | 2 +- src/device/sampler.rs | 2 +- src/tek.rs | 52 ++++++++++++++++++++++---------------- tengri | 2 +- 5 files changed, 37 insertions(+), 29 deletions(-) diff --git a/src/device/editor/piano.rs b/src/device/editor/piano.rs index e3c4320a..f4a7b67d 100644 --- a/src/device/editor/piano.rs +++ b/src/device/editor/piano.rs @@ -137,7 +137,7 @@ impl PianoHorizontal { let note_lo = self.get_note_lo(); let note_hi = self.get_note_hi(); let buffer = self.buffer.clone(); - thunk(move|to: &mut Tui|{ + draw(move|to: &mut Tui|{ let xywh = to.area().into(); let XYWH(x0, y0, w, _h) = xywh; let source = buffer.read().unwrap(); @@ -175,7 +175,7 @@ impl PianoHorizontal { let time_start = self.get_time_start(); let time_zoom = self.get_time_zoom(); let style = Some(Style::default().fg(self.color.lightest.term)); - thunk(move|to: &mut Tui|{ + draw(move|to: &mut Tui|{ let xywh = to.area().into(); let XYWH(x0, y0, w, _h) = xywh; for (_area_y, screen_y, note) in note_y_iter(note_lo, note_hi, y0) { @@ -209,7 +209,7 @@ impl PianoHorizontal { let key_style = Some(Style::default().fg(Rgb(192, 192, 192)).bg(Rgb(0, 0, 0))); let off_style = Some(Style::default().fg(g(255))); let on_style = Some(Style::default().fg(Rgb(255,0,0)).bg(color.base.term).bold()); - thunk(move|to: &mut Tui|{ + draw(move|to: &mut Tui|{ let xywh = to.area().into(); let XYWH(x, y0, _w, _h) = xywh; for (_area_y, screen_y, note) in note_y_iter(note_lo, note_hi, y0) { @@ -228,7 +228,7 @@ impl PianoHorizontal { } fn timeline (&self) -> impl Draw + '_ { - thunk(move|to: &mut Tui|{ + draw(move|to: &mut Tui|{ let xywh = to.area().into(); let XYWH(x, y, w, _h) = xywh; let style = Some(Style::default().dim()); diff --git a/src/device/plugin.rs b/src/device/plugin.rs index e4d8c548..fc01cf16 100644 --- a/src/device/plugin.rs +++ b/src/device/plugin.rs @@ -141,7 +141,7 @@ impl ApplicationHandler for LV2PluginUI { } impl Draw for Lv2 { - fn draw(self, to: &mut Tui) { + fn draw (&self, to: &mut Tui) { let area = to.area(); let XYWH(x, y, _, height) = area; let mut width = 20u16; diff --git a/src/device/sampler.rs b/src/device/sampler.rs index baeae448..681f957e 100644 --- a/src/device/sampler.rs +++ b/src/device/sampler.rs @@ -257,7 +257,7 @@ fn draw_list_item (sample: &Option>>) -> String { fn draw_viewer (sample: Option<&Arc>>) -> impl Draw + use<'_> { let min_db = -64.0; - thunk(move|to: &mut Tui|{ + draw(move|to: &mut Tui|{ let xywh = to.area().into(); let XYWH(x, y, width, height) = xywh; let area = Rect { x, y, width, height }; diff --git a/src/tek.rs b/src/tek.rs index fe3b7f2c..c7640013 100644 --- a/src/tek.rs +++ b/src/tek.rs @@ -1452,12 +1452,11 @@ mod draw { /// Then, every top-level form of the DSL description is rendered. impl View for App { fn view (&self) -> impl Draw { - thunk(|to: &mut Tui|{ + draw(|to: &mut Tui|{ let xywh = to.area().into(); if let Some(e) = self.error.read().unwrap().as_ref() { - //to.show(area(xywh, format!("KYPbanica {xywh:?}").align_c()))?; - to.show(e.as_ref().align_c())?; + e.as_ref().align_c().draw(to)?; } if let Some(ref mode) = self.mode { @@ -1471,13 +1470,22 @@ mod draw { } } - to.show(ShowSize.align_se())?; + ShowSize.align_se().draw(to)?; Ok(Some(xywh)) }) } } + impl Keywords> for App { + fn keywords () -> impl Iterator Perhaps>> { + [ + kw_when, kw_either, kw_split, kw_align, + kw_exact, kw_fixed, kw_min, kw_max, kw_push + ].into_iter() + } + } + impl Interpret>> for App { fn interpret_expr <'a> (&'a self, to: &mut Tui, lang: &'a impl Expression) -> Drawn { tek_draw_expr(self, to, lang) @@ -1582,7 +1590,7 @@ mod draw { Some("menu") => if let Dialog::Menu(selected, items) = &state.dialog { let items = items.clone(); let selected = selected; - Some(thunk(move|to: &mut Tui|{ + Some(draw(move|to: &mut Tui|{ for (index, MenuItem(item, _)) in items.0.iter().enumerate() { let f = if *selected == index { Rgb(240,200,180) } else { Rgb(200, 200, 200) }; let b = if *selected == index { Rgb(80, 80, 50) } else { Rgb(30, 30, 30) }; @@ -1600,7 +1608,7 @@ mod draw { pub fn draw_templates (to: &mut Tui, _frags: std::str::Split<&str>, state: &App) -> Drawn { let height = (state.config.modes.len() * 2) as u16; - thunk(move |to: &mut Tui|{ + draw(move |to: &mut Tui|{ let mut index = 0; state.config.modes.for_each(|id, profile| { let b = if index == 0 { Rgb(70,70,70) } else { Rgb(50,50,50) }; @@ -1654,7 +1662,7 @@ mod draw { let h = 6; let w = Some(30); let f = Rgb(224, 192, 128); - thunk(move |to: &mut Tui|{ + draw(move |to: &mut Tui|{ for (index, name) in ["session1", "session2", "session3"].iter().enumerate() { let b = if index == 0 { Rgb(50,50,50) } else { Rgb(40,40,40) }; let y = (2 * index) as u16; @@ -1732,11 +1740,11 @@ mod draw { pub fn button_play_pause (playing: bool, compact: bool) -> impl Draw { bg(if playing { Rgb(0, 128, 0) } else { Rgb(128, 64, 0) }, either(compact, - thunk(move|to: &mut Tui|either(playing, + draw(move|to: &mut Tui|either(playing, fg(Rgb(0, 255, 0), " PLAYING "), fg(Rgb(255, 128, 0), " STOPPED "), ).exact_w(9).draw(to)), - thunk(move|to: &mut Tui|either(playing, + draw(move|to: &mut Tui|either(playing, fg(Rgb(0, 255, 0), south(" 🭍🭑🬽 ", " 🭞🭜🭘 ",)), fg(Rgb(255, 128, 0), south(" ▗▄▖ ", " ▝▀▘ ",)), ).exact_w(5).draw(to)), @@ -1803,7 +1811,7 @@ mod draw { } pub fn view_sample_info (sample: Option<&Arc>>) -> impl Draw + use<'_> { - when(sample.is_some(), thunk(move|to: &mut Tui|{ + when(sample.is_some(), draw(move|to: &mut Tui|{ let sample = sample.unwrap().read().unwrap(); let theme = sample.color; east!( @@ -1818,7 +1826,7 @@ mod draw { } pub fn view_sample_info_v (sample: Option<&Arc>>) -> impl Draw + use<'_> { - let a = thunk(move|to: &mut Tui|{ + let a = draw(move|to: &mut Tui|{ let sample = sample.unwrap().read().unwrap(); let theme = sample.color; south!( @@ -1831,7 +1839,7 @@ mod draw { ).exact_w(20).draw(to) }); - let b = thunk(|to: &mut Tui|fg(Red, south!( + let b = draw(|to: &mut Tui|fg(Red, south!( bold(true, "× No sample."), "[r] record", "[Shift-F9] import", @@ -1975,7 +1983,7 @@ mod draw { button_2("T", "+", false), button_2("S", "+", false)); view_track_row_section(theme, button, button_2, bg(theme.darker.term, - thunk(|to: &mut Tui|{ + draw(|to: &mut Tui|{ for (index, track, x1, _x2) in tracks { let b = if selected.track() == Some(index) { track.color.light.term @@ -2001,14 +2009,14 @@ mod draw { ) -> impl Draw { view_track_row_section(theme, south(button_2("o", "utput", false).align_w().full_w(), - thunk(|to: &mut Tui|{ + draw(|to: &mut Tui|{ for port in midi_outs { let _ = port.port_name().align_w().full_w().draw(to)?; } Ok(Some(XYWH(0, 0, 0, 0))) })), button_2("O", "+", false), - bg(theme.darker.term, thunk(|to: &mut Tui|{ + bg(theme.darker.term, draw(|to: &mut Tui|{ for (index, track, _x1, _x2) in tracks { let f = Rgb(255, 255, 255); let b = track.color.dark.term; @@ -2027,7 +2035,7 @@ mod draw { theme: ItemTheme, tracks: impl TracksSizes<'a>, height: u16, ) -> impl Draw { view_track_row_section(theme, button_2("i", "nput", false), button_2("I", "+", false), - bg(theme.darker.term, thunk(move|to: &mut Tui|{ + bg(theme.darker.term, draw(move|to: &mut Tui|{ for (index, track, _x1, _x2) in tracks { south( bg(track.color.base.term, @@ -2051,7 +2059,7 @@ mod draw { editor: Option<&MidiEditor>, editing: bool, ) -> impl Draw { - thunk(move |to: &mut Tui|{ + draw(move |to: &mut Tui|{ for (index, scene, ..) in scenes { view_scene_name(select, editor, index, scene, editing).draw(to)?; } @@ -2122,7 +2130,7 @@ mod draw { ) -> impl Draw { let title_1 = button_3("i", "nput ", format!("{}", midi_ins.len()), false).align_w().exact_wh(20, 1); let title_2 = button_2("I", "+", false).exact_wh(4, 1); - east(title_1, west(title_2, thunk(move|to: &mut Tui|{ + east(title_1, west(title_2, draw(move|to: &mut Tui|{ for (_index, track, x1, _x2) in tracks { let _ = south( bg(track.color.dark.term, east!( @@ -2130,7 +2138,7 @@ mod draw { either(track.sequencer.recording, fg(Red, "rec "), "rec "), either(track.sequencer.overdub, fg(Yellow, "dub "), "dub "), ).exact_w(track.width as u16)).align_w().push_x(x1 as u16), - thunk(move |to: &mut Tui|{ + draw(move |to: &mut Tui|{ for (index, port) in midi_ins.iter().enumerate() { let _ = east( east( @@ -2166,7 +2174,7 @@ mod draw { button_3( "o", "utput", format!("{}", midi_outs.len()), false ).align_w().full_w().exact_h(1), - thunk(|to: &mut Tui|{ + draw(|to: &mut Tui|{ for (_index, port) in midi_outs.iter().enumerate() { east( east(" ● ", fg(Rgb(255,255,255), bold(true, port.port_name()))).align_w(), @@ -2182,9 +2190,9 @@ mod draw { ); view_track_row_section(theme, list, button_2("O", "+", false), - bg(theme.darker.term, thunk(|to: &mut Tui|{ + bg(theme.darker.term, draw(|to: &mut Tui|{ for (index, track, _x1, _x2) in tracks { - let _ = thunk(|to: &mut Tui|{ + let _ = draw(|to: &mut Tui|{ east( either(true, fg(Green, "play "), "play "), either(false, fg(Yellow, "solo "), "solo "), diff --git a/tengri b/tengri index fc01fd6a..eb028c85 160000 --- a/tengri +++ b/tengri @@ -1 +1 @@ -Subproject commit fc01fd6ad3a6ed4ee17d65a65b3e59df522f895a +Subproject commit eb028c85fc94a1b86c44d4f079e5fb91667d4db2