From e0272a8a7dc43d0008896ec4bc79ce9fd53b71f9 Mon Sep 17 00:00:00 2001 From: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Date: Sat, 17 Jan 2026 13:20:13 +0200 Subject: [PATCH] display config better --- app/tek.edn | 317 ++++++++++++++++++---------------------------------- app/tek.rs | 70 +++++------- 2 files changed, 136 insertions(+), 251 deletions(-) diff --git a/app/tek.edn b/app/tek.edn index 08376129..4e1c14a8 100644 --- a/app/tek.edn +++ b/app/tek.edn @@ -1,216 +1,111 @@ -(keys :axis/x - (@left x/dec) - (@right x/inc)) -(keys :axis/x2 - (@shift/left x2/dec) - (@shift/right x2/inc)) -(keys :axis/y - (@up y/dec) - (@down y/inc)) -(keys :axis/y2 - (@shift/up y2/dec) - (@shift/down y2/inc)) -(keys :axis/z - (@minus z/dec) - (@equal z/inc)) -(keys :axis/z2 - (@underscore z2/dec) - (@plus z2/inc)) -(keys :axis/i - (@comma i/dec) - (@period z/inc)) -(keys :axis/i2 - (@lt i2/dec) - (@gt z2/inc)) -(keys :axis/w - (@openbracket w/dec) - (@closebracket w/inc)) -(keys :axis/w2 - (@openbrace w2/dec) - (@closebrace w2/inc)) - -(mode :menu (keys :axis/y :confirm) :menu) - -(keys :confirm - (@enter confirm)) - -(view :menu (bg (g 0) (bsp/s - :ports/out - (bsp/n :ports/in (bg (g 30) (bsp/s (fixed/y 7 :logo) (fill :dialog/menu))))))) - +(keys :back (@escape back)) +(keys :confirm (@enter confirm)) +(keys :axis/x (@left x/dec) (@right x/inc)) +(keys :axis/x2 (@shift/left x2/dec) (@shift/right x2/inc)) +(keys :axis/y (@up y/dec) (@down y/inc)) +(keys :axis/y2 (@shift/up y2/dec) (@shift/down y2/inc)) +(keys :axis/z (@minus z/dec) (@equal z/inc)) +(keys :axis/z2 (@underscore z2/dec) (@plus z2/inc)) +(keys :axis/i (@comma i/dec) (@period z/inc)) +(keys :axis/i2 (@lt i2/dec) (@gt z2/inc)) +(keys :axis/w (@openbracket w/dec) (@closebracket w/inc)) +(keys :axis/w2 (@openbrace w2/dec) (@closebrace w2/inc)) +(mode :menu (name Menu) (info Mode selector.) (keys :axis/y :confirm) (bg (g 0) + (bsp/s :ports/out (bsp/n :ports/in (bg (g 30) (bsp/s (fixed/y 7 :logo) (fill :dialog/menu))))))) (view :ports/out (fill/x (fixed/y 3 (bsp/a - (fill/x (align/w (text L-AUDIO-OUT))) - (bsp/a (text MIDI-OUT) (fill/x (align/e (text AUDIO-OUT-R)))))))) - + (fill/x (align/w (text L-AUDIO-OUT))) + (bsp/a (text MIDI-OUT) (fill/x (align/e (text AUDIO-OUT-R)))))))) (view :ports/in (fill/x (fixed/y 3 (bsp/a - (fill/x (align/w (text L-AUDIO-IN))) - (bsp/a (text MIDI-IN) (fill/x (align/e (text AUDIO-IN-R)))))))) - -(view :browse (bsp/s - (padding 3 1 :browse-title) - (enclose (fg (g 96)) browser))) - -(keys :help - (@f1 dialog :help)) - -(keys :back - (@escape back)) - -(keys :page - (@pgup page/up) - (@pgdn page/down)) - -(keys :delete - (@delete delete) - (@backspace delete/back)) - -(keys :input (see :axis/x :delete) - (:char input)) - -(keys :list (see :axis/y :confirm)) - -(keys :length (see :axis/x :axis/y :confirm)) - -(keys :browse (see :list :input :focus)) - -(keys :history - (@u undo 1) - (@r redo 1)) - -(keys :clock - (@space clock/toggle 0) - (@shift/space clock/toggle 0)) - -(keys :color - (@c color)) - -(keys :launch - (@q launch)) - -(keys :saveload - (@f6 dialog :save) - (@f9 dialog :load)) - -(keys :global (see :history :saveload) - (@f8 dialog :options) - (@f10 dialog :quit)) - -(keys :focus) - -(mode :transport (name Transport) (info A JACK transport controller.) (keys :clock :global) - (view :transport)) - -(mode :arranger (name Arranger) (info A grid of launchable clips arranged by track and scene.) - (mode :editor (keys :editor)) (mode :dialog (keys :dialog)) (mode :message (keys :message)) - (mode :add-device (keys :add-device)) (mode :browse (keys :browse)) (mode :rename (keys :input)) - (mode :length (keys :rename)) (mode :clip (keys :clip)) (mode :track (keys :track)) - (mode :scene (keys :scene)) (mode :mix (keys :mix)) - (keys :clock :arranger :global) (bsp/n - :status - (bsp/w :meters/output (bsp/e :meters/input :arrangement)))) - -(view :arrangement (bsp/n - :tracks/inputs - (bsp/s :tracks/outputs (bsp/s :tracks/names (bsp/s :tracks/devices - (fill (either :mode/editor (bsp/e :scenes/names :editor) :scenes))))))) - -(keys :arranger (see :color :launch :scenes :tracks) - (@tab project/edit) (@enter project/edit) - (@shift/I project/input/add) (@shift/O project/output/add) - (@shift/S project/scene/add) (@shift/T project/track/add) - (@shift/D dialog/show :dialog/device)) - -(keys :tracks - (@t select :select/track) - (@left select :select/track/dec) - (@right select :select/track/inc)) - -(keys :scenes - (@s select :select/scene) - (@up select :select/scene/dec) - (@down select :select/scene/inc)) - + (fill/x (align/w (text L-AUDIO-IN))) + (bsp/a (text MIDI-IN) (fill/x (align/e (text AUDIO-IN-R)))))))) +(mode :transport (name Transport) (info JACK transport controller.) + (keys :clock :global) + :transport) +(mode :sequencer (name Sequencer) (info MIDI sequencer.) + (mode browse (keys :browse)) + (mode rename (keys :pool/rename)) + (mode length (keys :pool/length)) + (keys :editor :clock :global) + (bsp/s (fixed/y 1 :transport) + (bsp/n (fixed/y 1 :status) + (fill (bsp/a (fill/xy (align/e :pool)) :editor))))) +(keys :editor (see :axis/i :axis/i2 :axis/y :page :editor/view :editor/add :editor/del)) +(keys :editor/view (see :axis/x :axis/x2 :axis/z :axis/z2) (@z toggle :lock)) +(keys :editor/add (@a editor/append :true) (@enter editor/append :false)) +(keys :editor/del (@del editor/delete/note) (@shift/del editor/delete/note)) +(mode :sampler (name Sampler) (info Sample player.) + (keys :sampler/directions :sampler/record :sampler/play) + (bsp/s (fixed/y 1 :transport) (bsp/n (fixed/y 1 :status) (fill :samples/grid)))) +(keys :sampler/record + (@r sampler/record/toggle :sample/selected) + (@shift/R sampler/record/back)) +(keys :sampler/play + (@p sampler/play/sample :sample/selected) + (@P sampler/stop/sample :sample/selected)) +(keys :sampler/import-export + (@shift/f6 dialog :dialog/export/sample) + (@shift/f9 dialog :dialog/import/sample)) +(keys :sampler/directions + (@up sampler/select :sample/above) + (@down sampler/select :sample/below) + (@left sampler/select :sample/to/left) + (@right sampler/select :sample/to/right)) +(mode :groovebox (name Groovebox) (info Sequencer with sampler.) + (mode browse (keys :browse)) + (mode rename (keys :pool-rename)) + (mode length (keys :pool-length)) + (keys :clock :editor :sampler :global) + (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)))) +(view :groove/editor (bsp/n :groove/sample :groove/sequence)) +(view :groove/sample (fixed/y :h-sample-detail (bsp/e (fill/y (fixed/x 20 (align/nw :sample-status))) :sample-viewer))) +(view :groove/sequence (bsp/e (fill/y (align/n (bsp/s :status/v :editor-status))) (bsp/e :samples/keys :editor))) +(mode :arranger (name Arranger) (info Launch grid.) + (mode :editor (keys :editor)) + (mode :dialog (keys :dialog)) + (mode :message (keys :message)) + (mode :add-device (keys :add-device)) + (mode :browse (keys :browse)) + (mode :rename (keys :input)) + (mode :length (keys :rename)) + (mode :clip (keys :clip)) + (mode :track (keys :track)) + (mode :scene (keys :scene)) + (mode :mix (keys :mix)) + (keys (see :clock :color :launch :scenes :tracks :global) + (@tab project/edit) + (@shift/I project/input/add) (@shift/O project/output/add) + (@shift/D dialog/show :dialog/device)) + (bsp/n :status (bsp/w :meters/output (bsp/e :meters/input (bsp/n :tracks/inputs + (bsp/s :tracks/outputs (bsp/s :tracks/names (bsp/s :tracks/devices + (fill (either :mode/editor (bsp/e :scenes/names :editor) :scenes)))))))))) +(keys :tracks (@t select :select/track) (@shift/T project/track/add) + (@left select :select/track/dec) (@right select :select/track/inc)) (keys :track (see :color :launch :axis/z :axis/z2 :delete) - (@r toggle :rec) - (@m toggle :mon) - (@p toggle :play) - (@P toggle :solo)) + (@r toggle :rec) (@m toggle :mon) (@p toggle :play) (@P toggle :solo)) +(keys :scenes (@s select :select/scene) (@shift/S project/scene/add) + (@up select :select/scene/dec) (@down select :select/scene/inc)) (keys :scene (see :color :launch :axis/z :axis/z2 :delete)) -(keys :clip (see :color :launch :axis/z :axis/z2 :delete) - (@l toggle :loop)) - -(mode :groovebox (name Groovebox) (info A sequencer with built-in sampler.) - (mode browse (keys :browse)) - (mode rename (keys :pool-rename)) - (mode length (keys :pool-length)) - (keys :clock :editor :sampler :global) (view :groovebox)) - -(view :groovebox (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)))) - -(view :groove/editor (bsp/n - :groove/sample - :groove/sequence)) - -(view :groove/sample (fixed/y :h-sample-detail (bsp/e - (fill/y (fixed/x 20 (align/nw :sample-status))) - :sample-viewer))) - -(view :groove/sequence (bsp/e - (fill/y (align/n (bsp/s :status/v :editor-status))) - (bsp/e :samples/keys :editor))) - -(mode :sampler (name Sampler) (info A sampling soundboard.) - (keys :sampler :global) (view :sampler)) - -(view :sampler (bsp/s - (fixed/y 1 :transport) - (bsp/n (fixed/y 1 :status) (fill :samples/grid)))) - -(keys :sampler (see :sampler/directions :sampler/record :sampler/play)) - -(keys :sampler/record - (@r sampler/record/toggle :sample/selected) (@shift/R sampler/record/back)) - -(keys :sampler/play - (@p sampler/play/sample :sample/selected) (@P sampler/stop/sample :sample/selected)) - -(keys :sampler/import-export - (@shift/f6 dialog :dialog/export/sample) (@shift/f9 dialog :dialog/import/sample)) - -(keys :sampler/directions - (@up sampler/select :sample/above) - (@down sampler/select :sample/below) - (@left sampler/select :sample/to/left) - (@right sampler/select :sample/to/right)) - -(mode :sequencer (name Sequencer) (info A MIDI sequencer.) - (mode browse (keys :browse)) (mode rename (keys :pool/rename)) (mode length (keys :pool/length)) - (keys :editor :clock :global) (view :sequencer)) - -(view :sequencer (bsp/s - (fixed/y 1 :transport) - (bsp/n (fixed/y 1 :status) (fill (bsp/a (fill/xy (align/e :pool)) :editor))))) - -(keys :editor (see :editor/view :editor/note)) - -(keys :editor/view (see :axis/x :axis/x2 :axis/z :axis/z2) - (@z toggle :lock)) - -(keys :editor/note (see :axis/i :axis/i2 :axis/y :page) - (@a editor/append :true) - (@enter editor/append :false) - (@del editor/delete/note) - (@shift/del editor/delete/note)) - -(keys :pool (see :axis-y :axis-w :axis/z2 :color :delete) - (@n rename/begin) (@t length/begin) (@m import/begin) (@x export/begin) - (@shift/A clip/add :after :new/clip) (@shift/D clip/add :after :cloned/clip)) - -(keys :sequencer (see :color :launch) - (@shift/I input/add) (@shift/O output/add)) +(keys :focus) +(keys :help (@f1 dialog :help)) +(keys :page (@pgup page/up) (@pgdn page/down)) +(keys :delete (@delete delete) (@backspace delete/back)) +(keys :input (see :axis/x :delete) (:char input)) +(keys :list (see :axis/y :confirm)) +(keys :length (see :axis/x :axis/y :confirm)) +(keys :browse (see :list :input :focus)) +(keys :history (@u undo 1) (@r redo 1)) +(keys :saveload (@f6 dialog :save) (@f9 dialog :load)) +(keys :color (@c color)) +(keys :launch (@q launch)) +(keys :clock (@space clock/toggle 0) (@shift/space clock/toggle 0)) +(keys :global (see :history :saveload) (@f8 dialog :options) (@f10 dialog :quit)) +(keys :clip (see :color :launch :axis/z :axis/z2 :delete) (@l toggle :loop)) +(keys :sequencer (see :color :launch) (@shift/I input/add) (@shift/O output/add)) +(keys :pool (see :axis-y :axis-w :axis/z2 :color :delete) + (@n rename/begin) (@t length/begin) (@m import/begin) (@x export/begin) + (@shift/A clip/add :after :new/clip) (@shift/D clip/add :after :cloned/clip)) +(view :browse (bsp/s + (padding 3 1 :browse-title) + (enclose (fg (g 96)) browser))) diff --git a/app/tek.rs b/app/tek.rs index cbe9f14e..90792cbe 100644 --- a/app/tek.rs +++ b/app/tek.rs @@ -140,25 +140,21 @@ pub mod model { }, }); } - pub mod core { use super::{*, model::*, gui::*}; impl App { + /// Create a new application from a project, config, and mode pub fn new ( jack: &Jack<'static>, project: Arrangement, config: Config, mode: impl AsRef ) -> Self { - Self { - color: ItemTheme::random(), - dialog: Dialog::welcome(), - jack: jack.clone(), - mode: config.modes.clone().read().unwrap().get(mode.as_ref()).cloned().unwrap(), - config, - project, - ..Default::default() - } + let color = ItemTheme::random(); + let dialog = Dialog::welcome(); + let jack = jack.clone(); + let mode = config.get_mode(mode).unwrap(); + Self { color, dialog, jack, mode, config, project, ..Default::default() } } } impl Config { @@ -166,10 +162,8 @@ pub mod core { const DEFAULTS: &'static str = include_str!("./tek.edn"); /// Create a new app configuration from a set of XDG base directories, pub fn new (dirs: Option) -> Self { - Self { - dirs: dirs.unwrap_or_else(||BaseDirectories::with_profile("tek", "v0")), - ..Default::default() - } + let dirs = dirs.unwrap_or_else(||BaseDirectories::with_profile("tek", "v0")); + Self { dirs, ..Default::default() } } /// Write initial contents of configuration. pub fn init (&mut self) -> Usually<()> { @@ -214,6 +208,9 @@ pub mod core { return Err(format!("Config::load: expected expr, got: {item:?}").into()) } } + fn get_mode (&self, mode: impl AsRef) -> Option>>> { + self.modes.clone().read().unwrap().get(mode.as_ref()).cloned() + } } pub fn load_view (views: &Views, name: &impl AsRef, body: &impl Dsl) -> Usually<()> { views.write().unwrap().insert(name.as_ref().into(), body.src()?.unwrap_or_default().into()); @@ -259,7 +256,6 @@ pub mod core { match head { "name" => self.name.push(tail.into()), "info" => self.info.push(tail.into()), - "view" => self.view.push(tail.into()), "keys" => tail.each(|expr|{ self.keys.push(expr.trim().into()); Ok(()) @@ -269,9 +265,7 @@ pub mod core { } else { return Err(format!("Mode::add: self: incomplete: {expr:?}").into()); }, - _ => { - return Err(format!("Mode::add: unexpected expr: {head:?} {tail:?}").into()) - }, + _ => self.view.push(tail.into()) }; } else if let Ok(Some(word)) = dsl.word() { self.view.push(word.into()); @@ -851,18 +845,18 @@ pub mod glue { { MaybeHas::::get_mut(&mut self.project) }); maybe_has!(Scene: |self: App| { MaybeHas::::get(&self.project) }; { MaybeHas::::get_mut(&mut self.project) }); + impl HasJack<'static> for App { fn jack (&self) -> &Jack<'static> { &self.jack } } + impl HasClipsSize for App { fn clips_size (&self) -> &Measure { &self.project.size_inner } } + impl HasTrackScroll for App { fn track_scroll (&self) -> usize { self.project.track_scroll() } } + impl HasSceneScroll for App { fn scene_scroll (&self) -> usize { self.project.scene_scroll() } } + impl Default for AppCommand { fn default () -> Self { Self::Nop } } impl ScenesView for App { fn w_side (&self) -> u16 { 20 } fn w_mid (&self) -> u16 { (self.width() as u16).saturating_sub(self.w_side()) } fn h_scenes (&self) -> u16 { (self.height() as u16).saturating_sub(20) } } impl Default for MenuItem { fn default () -> Self { Self("".into(), Arc::new(Box::new(|_|Ok(())))) } } - impl Default for AppCommand { fn default () -> Self { Self::Nop } } impl PartialEq for MenuItem { fn eq (&self, other: &Self) -> bool { self.0 == other.0 } } - impl HasJack<'static> for App { fn jack (&self) -> &Jack<'static> { &self.jack } } - impl HasClipsSize for App { fn clips_size (&self) -> &Measure { &self.project.size_inner } } - impl HasTrackScroll for App { fn track_scroll (&self) -> usize { self.project.track_scroll() } } - impl HasSceneScroll for App { fn scene_scroll (&self) -> usize { self.project.scene_scroll() } } impl AsRef> for MenuItems { fn as_ref (&self) -> &Arc<[MenuItem]> { &self.0 } } impl_debug!(MenuItem |self, w| { write!(w, "{}", &self.0) }); impl_debug!(Condition |self, w| { write!(w, "*") }); @@ -875,15 +869,10 @@ pub mod glue { use clap::{self, Parser, Subcommand}; /// CLI banner. const HEADER: &'static str = r#" - ~ ╓─╥─╖ ╓──╖ ╥ ╖ ~~~~ ~ ~ ~~ ~ ~ ~ ~~ ~ ~ ~ ~ ~~~~~~ ~ ~~~ - ~~ ║ ~ ╟─╌ ~╟─< ~ v0.3.0, 2025 sum(m)er @ the nose of the cat. ~ - ~~~ ╨ ~ ╙──╜ ╨ ╜ ~ ~~~ ~ ~ ~ ~ ~~~ ~~~ ~ ~~ ~~ ~~ ~ ~~ - On first run, Tek will create configuration and state dirs: - * [x] ~/.config/tek - config - * [ ] ~/.local/share/tek - projects - * [ ] ~/.local/lib/tek - plugins - * [ ] ~/.cache/tek - cache - ~"#; + +~ █▀█▀█ █▀▀█ █ █ ~~~ ~ ~ ~~ ~ ~ ~ ~~ ~ ~ ~ ~ + █ █▀ █▀▀▄ ~ v0.4.0, 2026 winter (or is it) ~ + ~ ▀ █▀▀█ ▀ ▀ ~ ~~~ ~ ~ ~ ~ ~~~ ~~~ ~ ~~ "#; #[derive(Debug, Parser)] #[command(name = "tek", version, about = Some(HEADER), long_about = Some(HEADER))] pub struct Cli { @@ -1042,18 +1031,16 @@ pub mod glue { } } for (k, v) in config.modes.read().unwrap().iter() { - println!("{} {} {:?} {:?}", Green.paint("\nTOOL "), - Green.bold().paint(format!("{k:<16}")), - v.name, v.info); - print!("{}", Green.paint(" VIEW")); - for v in v.view.iter() { print!(" {}", Yellow.paint(format!("{v}"))); } println!(); - print!("{}", Green.paint(" KEYS")); - for v in v.keys.iter() { print!(" {}", Yellow.paint(format!("{v}"))); } + for v in v.name.iter() { print!("{}", Green.bold().paint(format!("{v} "))); } + for v in v.info.iter() { print!("\n{}", Green.paint(format!("{v}"))); } + print!("\n{} {}", Blue.paint("TOOL"), Green.bold().paint(format!("{k:<16}"))); + print!("\n{}", Blue.paint("KEYS")); + for v in v.keys.iter() { print!("{}", Green.paint(format!(" {v}"))); } println!(); for (k, v) in v.modes.read().unwrap().iter() { print!("{} {} {:?}", - Green.paint(" MODE"), + Blue.paint("MODE"), Green.bold().paint(format!("{k:<16}")), v.name); print!(" INFO={:?}", @@ -1063,6 +1050,9 @@ pub mod glue { println!(" KEYS={:?}", v.keys); } + print!("{}", Blue.paint("VIEW")); + for v in v.view.iter() { print!("{}", Green.paint(format!(" {v}"))); } + println!(); } } fn show_status (&self, project: &Arrangement) {