add (data) to config

This commit is contained in:
i do not exist 2026-10-05 16:47:07 +03:00
parent 353a20bab9
commit b6f7d2d361
6 changed files with 142 additions and 96 deletions

View file

@ -505,14 +505,15 @@ pub fn tek_vec_arc_str <'a> (_: &App, _: impl Language) -> Perhaps<Vec<Arc<str>>
} }
/// Switch to another set of contextual modes. /// Switch to another set of contextual modes.
#[command(Mode = "mode")] pub fn cmd_mode (&mut self, modes: Vec<Arc<str>>) -> Perhaps<AppCmd> { #[command(Mode = "mode")] pub fn cmd_mode (&mut self, modes: Vec<Arc<str>>) -> Perhaps<AppCmd> {
*self.mode_stack().write() = modes.into(); *self.stack().write() = modes.into_iter().map(Into::into).collect();
Ok(None) Ok(None)
} }
/// Enter a contextual mode. /// Enter a contextual mode.
#[command(Enter = "enter")] pub fn enter_mode (&mut self, mode: Arc<str>) -> Perhaps<AppCmd> { #[command(Enter = "enter")] pub fn enter_mode (&mut self, mode: Arc<str>) -> Perhaps<AppCmd> {
let mut modes = self.mode_stack().write(); let mut modes = self.stack().write();
Ok(if modes.last() != Some(&mode) { Ok(if modes.last().map(|mode|mode.name.as_ref()) != Some(mode.as_ref()) {
modes.push(mode); let data = Default::default();
modes.push(Frame::new(mode, data));
Some(AppCmd::Leave) Some(AppCmd::Leave)
} else { } else {
None None
@ -520,37 +521,35 @@ pub fn tek_vec_arc_str <'a> (_: &App, _: impl Language) -> Perhaps<Vec<Arc<str>>
} }
/// Leave a contextual mode. /// Leave a contextual mode.
#[command(Leave = "leave")] fn leave_mode (&mut self) -> Perhaps<AppCmd> { #[command(Leave = "leave")] fn leave_mode (&mut self) -> Perhaps<AppCmd> {
let mut modes = self.mode_stack().write(); let mut modes = self.stack().write();
if modes.len() > 1 { if modes.len() > 1 {
let mode = modes.pop(); let mode = modes.pop();
Ok(mode.map(|mode|AppCmd::Enter { mode })) Ok(mode.map(|mode|AppCmd::Enter { mode: mode.name }))
} else { } else {
Ok(None) Ok(None)
} }
} }
/// Increment the given data axis. /// Increment the given data axis.
#[command(Inc = "inc")] pub fn inc (&mut self, axis: Arc<str>) -> Perhaps<AppCmd> { #[command(Inc = "inc")] pub fn inc (&mut self, axis: Arc<str>) -> Perhaps<AppCmd> {
panic!("inc {axis:?}"); if let Some(mode) = self.stack().write().last_mut() {
//Ok(match (&self.dialog, axis) { if mode.data.contains_key(&axis) {
//(Dialog::None, _) => todo!(), *mode.data.get_mut(&axis).unwrap() += 1;
//(Dialog::Menu(_, _), ControlAxis::Y) => { } else {
//AppCmd::Dialog { dialog: self.dialog.menu_next() }.dispatch(self)?; return err!("invalid axis {axis} for mode {}", &mode.name)
//None }
//}, }
//_ => todo!() Ok(None)
//})
} }
/// Decrement the given data axis. /// Decrement the given data axis.
#[command(Dec = "dec")] pub fn dec (&mut self, axis: Arc<str>) -> Perhaps<AppCmd> { #[command(Dec = "dec")] pub fn dec (&mut self, axis: Arc<str>) -> Perhaps<AppCmd> {
panic!("dec {axis:?}"); if let Some(mode) = self.stack().write().last_mut() {
//Ok(match (&self.dialog, axis) { if mode.data.contains_key(&axis) {
//(Dialog::None, _) => None, *mode.data.get_mut(&axis).unwrap() -= 1;
//(Dialog::Menu(_, _), ControlAxis::Y) => { } else {
//AppCmd::Dialog { dialog: self.dialog.menu_prev() }.dispatch(self)?; return err!("invalid axis {axis} for mode {}", &mode.name)
//None }
//}, }
//_ => todo!() Ok(None)
//})
} }
/// Cancel current selection. /// Cancel current selection.
#[command(Cancel = "cancel")] pub fn cmd_cancel (&mut self) -> Perhaps<AppCmd> { #[command(Cancel = "cancel")] pub fn cmd_cancel (&mut self) -> Perhaps<AppCmd> {

View file

@ -1,20 +1,5 @@
use crate::*; use crate::*;
/// Has a stack of currently active interaction modes.
pub trait HasModeStack {
/// Stack of active modes.
fn mode_stack (&self) -> &RwLock<Vec<Arc<str>>>;
fn mode_stack_push (&self, mode: impl AsRef<str>) {
self.mode_stack().write().push(mode.as_ref().into())
}
}
impl HasModeStack for App {
fn mode_stack (&self) -> &RwLock<Vec<Arc<str>>> {
&self.stack
}
}
/// Collection of UI modes. /// Collection of UI modes.
/// ///
/// ``` /// ```
@ -37,13 +22,11 @@ pub trait HasModes {
/// ///
/// ``` /// ```
/// # use ::{std::sync::Arc, tek::*}; /// # use ::{std::sync::Arc, tek::*};
/// let config: Config = Default::default(); /// let config = Config::default();
///
/// config.modes_add(stringify!(Menu /// config.modes_add(stringify!(Menu
/// (name Menu) (info Mode selector.) (axis Y Index) (bind Confirm) /// (name Menu) (info Mode selector.) (axis Y Index) (bind Confirm)
/// (view (bg (g 30) (bar/s 7 Logo (full/xy Dialog)))) /// (view (bg (g 30) (bar/s 7 Logo (full/xy Dialog))))
/// )).unwrap(); /// )).unwrap();
///
/// let _: Arc<Mode> = config.modes_get("Menu").unwrap(); /// let _: Arc<Mode> = config.modes_get("Menu").unwrap();
/// ``` /// ```
fn modes_add <'a> (&self, expr: impl Language) -> UsuallyRef<'a, ()> { fn modes_add <'a> (&self, expr: impl Language) -> UsuallyRef<'a, ()> {
@ -104,6 +87,7 @@ pub struct Mode {
pub view: Vec<Arc<View<Tui, App>>>, pub view: Vec<Arc<View<Tui, App>>>,
pub keys: Vec<Arc<str>>, pub keys: Vec<Arc<str>>,
pub axis: BTreeMap<Arc<str>, Arc<str>>, pub axis: BTreeMap<Arc<str>, Arc<str>>,
pub data: BTreeMap<Arc<str>, usize>,
pub modes: Arc<RwLock<BTreeMap<Arc<str>, Arc<Mode>>>>, pub modes: Arc<RwLock<BTreeMap<Arc<str>, Arc<Mode>>>>,
} }
@ -128,6 +112,7 @@ impl Mode {
"self" => self.add_mode(tail)?, "self" => self.add_mode(tail)?,
"bind" => self.add_bind(tail)?, "bind" => self.add_bind(tail)?,
"axis" => self.add_axis(tail)?, "axis" => self.add_axis(tail)?,
"data" => self.add_data(tail)?,
"name" => { self.name.push(tail.into()); self }, "name" => { self.name.push(tail.into()); self },
"info" => { self.info.push(tail.into()); self }, "info" => { self.info.push(tail.into()); self },
"view" => { self.view.push(View::new(tail)?.into()); self }, "view" => { self.view.push(View::new(tail)?.into()); self },
@ -167,13 +152,33 @@ impl Mode {
param = Some(src.into()); param = Some(src.into());
Ok(2) Ok(2)
} else { } else {
err!("expected (mode (axis [Name] [command] [command])), got: {tail}") err!("mode: expected (axis Name Param), got: {tail}")
})?; })?;
if let Some(axis) = axis && let Some(param) = param { if let Some(axis) = axis && let Some(param) = param {
self.axis.insert(axis.into(), param.into()); self.axis.insert(axis.into(), param.into());
Ok(self) Ok(self)
} else { } else {
err!("mode: expected (axis X Param), got: {tail}") err!("mode: expected (axis Name Param), got: {tail}")
}
}
fn add_data (&mut self, tail: &str) -> Usually<&mut Self> {
let mut param: Option<Arc<str>> = None;
let mut value: Option<usize> = None;
tail.each(0, |index: usize, src: &str|if index == 0 {
param = Some(src.into());
Ok(1)
} else if index == 1 {
value = Some(src.parse::<usize>()?);
Ok(2)
} else {
err!("mode: expected (data Param Value), got: {tail}")
})?;
if let Some(param) = param && let Some(value) = value {
self.data.insert(param.into(), value.into());
Ok(self)
} else {
err!("mode: expected (data Param Value), got: {tail}")
} }
} }

38
src/conf/stack.rs Normal file
View file

@ -0,0 +1,38 @@
use crate::*;
/// Has a stack of currently active interaction modes.
pub trait HasStack {
/// Stack of active modes.
fn stack (&self) -> &RwLock<Vec<Frame>>;
fn stack_push (&self, mode: impl AsRef<str>) {
self.stack().write().push(mode.as_ref().into())
}
}
impl HasStack for App {
fn stack (&self) -> &RwLock<Vec<Frame>> {
&self.stack
}
}
#[derive(Default, Debug)]
pub struct Frame {
pub name: Arc<str>,
pub data: BTreeMap<Arc<str>, usize>,
}
impl Frame {
pub fn new (name: impl AsRef<str>, data: Option<BTreeMap<Arc<str>, usize>>) -> Self {
Self {
name: name.as_ref().into(),
data: data.unwrap_or_default(),
}
}
}
impl<T: AsRef<str>> From<T> for Frame {
fn from (name: T) -> Self {
Self::new(name, Default::default())
}
}

View file

@ -66,7 +66,7 @@ pub fn draw_error (to: &mut Tui, error: &RwLock<Option<Arc<str>>>) -> Usually<()
} }
pub fn view_debug ( pub fn view_debug (
stack: &Vec<Arc<str>>, stack: &Vec<Frame>,
perf: &PerfModel, perf: &PerfModel,
size: &Sizer, size: &Sizer,
) -> impl Draw<Tui> { ) -> impl Draw<Tui> {
@ -81,7 +81,7 @@ pub fn view_debug (
size.1.load(Relaxed)).align_w(), size.1.load(Relaxed)).align_w(),
).align_se(), ).align_se(),
//() //()
format!("{:?}", stack).align_sw(), format!("{:?}", stack.iter().map(|mode|mode.name.as_ref()).collect::<Vec<_>>()).align_sw(),
) )
} }
@ -104,12 +104,12 @@ pub fn view_status <'a> (sel: Option<&str>, sr: &str, buf: &str, lat: &str) -> i
pub fn draw_status_bar (to: &mut Tui, state: &App) -> Drawn<u16> { pub fn draw_status_bar (to: &mut Tui, state: &App) -> Drawn<u16> {
bar(Split::South, 1u16, bar(Split::South, 1u16,
dim(true, "Mode"), dim(true, "Mode"),
bold(true, state.mode_stack().read().get(0)) bold(true, state.stack().read().get(0).map(|mode|mode.name.as_ref()))
).push_x(1).draw(to) ).push_x(1).draw(to)
} }
pub fn draw_mode_stack (to: &mut Tui, state: &App) -> Usually<()> { pub fn draw_stack (to: &mut Tui, state: &App) -> Usually<()> {
for name in state.mode_stack().read().iter() { for Frame { name, data } in state.stack().read().iter() {
let mut error = false; let mut error = false;
//if state.watch.config.modes_count() > 0 { //if state.watch.config.modes_count() > 0 {
//panic!("{name:?} {:?}", state.watch.config.modes); //panic!("{name:?} {:?}", state.watch.config.modes);
@ -181,10 +181,10 @@ pub fn view_config (app: &App) -> impl Draw<Tui> {
let area = to.area(); let area = to.area();
let XYWH(x0, y0, w, h) = area; let XYWH(x0, y0, w, h) = area;
let mut y = 0; let mut y = 0;
for key in app.stack.read().iter().rev() { for frame in app.stack.read().iter().rev() {
if let Some(mode) = app.modes_get(key) { if let Some(mode) = app.modes_get(&frame.name) {
to.clip(XYWH(x0 + 1, y0 + y, w, 1), &|to|Split::East.bar(16, to.clip(XYWH(x0 + 1, y0 + y, w, 1), &|to|Split::East.bar(16,
key, &frame.name,
mode.info.get(0)).draw(to))?; mode.info.get(0)).draw(to))?;
next_line!(h, y, 1); next_line!(h, y, 1);
for (ctrl, data) in mode.axis.iter() { for (ctrl, data) in mode.axis.iter() {
@ -197,7 +197,7 @@ pub fn view_config (app: &App) -> impl Draw<Tui> {
to.clip(XYWH(x0 + 3, y0 + y, w, 1), &|to|bind.draw(to))?; to.clip(XYWH(x0 + 3, y0 + y, w, 1), &|to|bind.draw(to))?;
next_line!(h, y, 1); next_line!(h, y, 1);
if let Some(bind) = app.binds_find(bind) { if let Some(bind) = app.binds_find(bind) {
for (key, binding) in bind.0.iter() { for (key, _binding) in bind.0.iter() {
to.clip(XYWH(x0 + 5, y0 + y, 40, 1), &|to|Split::East.bar(40, to.clip(XYWH(x0 + 5, y0 + y, 40, 1), &|to|Split::East.bar(40,
format!("{}", key), //binding.description.get(0) format!("{}", key), //binding.description.get(0)
"").draw(to))?; "").draw(to))?;
@ -672,14 +672,14 @@ fn iter_scenes_with_sizes <'s, T> (state: &'s T) -> impl ScenesSizes<'s> where T
}) })
} }
pub fn view_modes <'a, S: HasModeStack> (state: &'a S) -> impl Draw<Tui> + 'a { pub fn view_modes <'a, S: HasStack> (state: &'a S) -> impl Draw<Tui> + 'a {
draw(move|to: &mut Tui|{ draw(move|to: &mut Tui|{
let XYWH(x, y, w, h) = to.area(); let XYWH(x, y, w, h) = to.area();
let mut x_next = x; let mut x_next = x;
let mut w_used = 0u16; let mut w_used = 0u16;
for item in state.mode_stack().read().iter() { for frame in state.stack().read().iter() {
let area = XYWH(x_next, y, w.minus(w_used), h); let area = XYWH(x_next, y, w.minus(w_used), h);
if let Some(used) = to.draw(area, item)? { if let Some(used) = to.draw(area, &frame.name)? {
let used_w = used.w() + 1; let used_w = used.w() + 1;
x_next = x_next.plus(used_w); x_next = x_next.plus(used_w);
w_used = w_used.plus(used_w); w_used = w_used.plus(used_w);

View file

@ -11,22 +11,26 @@
(axis IFine @lt @gt ) (axis IFine @lt @gt )
(axis WFine @openbrace @closebrace ) (axis WFine @openbrace @closebrace )
(mode Menu (mode Menu (name Main Menu) (info Welcome to Tek!)
(name Main Menu) (axis Y Index) (data Index 1)
(info Welcome to Tek!)
(axis Y Index)
(bind Confirm) (bind Confirm)
(view (bar/s 2 Transport (bar/n 2 StatusBar (align/c (bar/s 2 (align/x Logo) Menu)))))) (view (bar/s 2 Transport (bar/n 2 StatusBar (align/c (bar/s 2 (align/x Logo) Menu))))))
(mode Help (mode Help
(axis Y Index) (axis Y Index) (data Index 0)
(axis P Page) (axis P Page) (data Page 0)
(view (bg (g 32) (fg (g 64) (full/xy (align/c (bg (g 48) (fg (g 224) (view (bg (g 32) (fg (g 64) (full/xy (align/c (bg (g 48) (fg (g 224)
(bar/s 2 (text Help yourself! ) (align/c Config)))))))))) (bar/s 2 (text Help yourself! ) (align/c Config))))))))))
(mode Options
(axis Y Index) (data Index 0)
(axis P Page) (data Page 0)
(view (bg (g 32) (fg (g 64) (full/xy
(bg (g 48) (fg (g 224) (align/c (expand/wh 2 2 (text Options ))))))))))
(mode History (mode History
(axis Y Index) (axis Y Index) (data Index 0)
(axis P Page) (axis P Page) (data Page 0)
(view (bg (g 32) (fg (g 64) (full/xy (bg (g 48) (fg (g 224) (view (bg (g 32) (fg (g 64) (full/xy (bg (g 48) (fg (g 224)
(align/c (bar/s 1 (text Project history ) HistoryList))))))))) (align/c (bar/s 1 (text Project history ) HistoryList)))))))))
@ -37,35 +41,30 @@
(bsp/e (push/x 1 (text Yes)) (align/ne (pull/x 2 (text No)))))))))))))) (bsp/e (push/x 1 (text Yes)) (align/ne (pull/x 2 (text No))))))))))))))
(mode Save (mode Save
(axis X Input) (axis X Input) (data Input 0)
(axis Y Index) (axis Y Index) (data Index 0)
(view (bg (g 32) (fg (g 64) (full/xy (bg (g 48) (fg (g 224) (view (bg (g 32) (fg (g 64) (full/xy (bg (g 48) (fg (g 224)
(align/c (bar/s 1 (expand/wh 2 2 (text Save to: )) (text <file browser here>)))))))))) (align/c (bar/s 1 (expand/wh 2 2 (text Save to: )) (text <file browser here>))))))))))
(mode Load (mode Load
(axis X Input) (axis X Input) (data Input 0)
(axis Y Index) (axis Y Index) (data Index 0)
(view (bg (g 32) (fg (g 64) (full/xy (bg (g 48) (fg (g 224) (view (bg (g 32) (fg (g 64) (full/xy (bg (g 48) (fg (g 224)
(align/c (bar/s 1 (expand/wh 2 2 (text Load from: )) (text <file browser here>)))))))))) (align/c (bar/s 1 (expand/wh 2 2 (text Load from: )) (text <file browser here>))))))))))
(mode Rename (mode Rename
(axis X Input) (axis X Input) (data Input 0)
(axis Y Index) (axis Y Index) (data Index 0)
(view (bg (g 32) (fg (g 64) (full/xy (bg (g 48) (fg (g 224) (view (bg (g 32) (fg (g 64) (full/xy (bg (g 48) (fg (g 224)
(align/c (expand/wh 2 2 (text Rename item )))))))))) (align/c (expand/wh 2 2 (text Rename item ))))))))))
(mode Options
(axis Y Index)
(view (bg (g 32) (fg (g 64) (full/xy
(bg (g 48) (fg (g 224) (align/c (expand/wh 2 2 (text Options ))))))))))
(mode Transport (name Transport) (info JACK transport controller.) (mode Transport (name Transport) (info JACK transport controller.)
(bind Clock Global) (bind Clock Global)
(view Transport)) (view Transport))
(mode Arranger (name Arranger) (info Launch grid.) (mode Arranger (name Arranger) (info Launch grid.)
(axis X Track) (axis X Track) (data Track 1)
(axis Y Scene) (axis Y Scene) (data Scene 1)
(bind Global Clock Tracks Scenes Clip Launch Color History) (bind Global Clock Tracks Scenes Clip Launch Color History)
(view (bar/n 2 StatusBar (bar/s 8 (bar/e 16 (align/nw Transport) (view (bar/n 2 StatusBar (bar/s 8 (bar/e 16 (align/nw Transport)
(bar/w 20 (bar/s 2 (bar/w 4 TracksOutputsAdd TracksOutputsCount) (bar/w 20 (bar/s 2 (bar/w 4 TracksOutputsAdd TracksOutputsCount)
@ -78,8 +77,8 @@
(bar/w 20 (text) (bar/e 16 ScenesNames ScenesClips)))))) (bar/w 20 (text) (bar/e 16 ScenesNames ScenesClips))))))
(mode Edit (info MIDI editor.) (mode Edit (info MIDI editor.)
(axis X Time) (axis X Time) (data Time 0)
(axis Y Pitch)) (axis Y Pitch) (data Pitch 36))
(mode Sequencer (info MIDI sequencer.) (mode Sequencer (info MIDI sequencer.)
(bind Global Clock I IFine Y Page EditorView EditorAdd EditorDel) (bind Global Clock I IFine Y Page EditorView EditorAdd EditorDel)

View file

@ -102,10 +102,10 @@ pub struct App {
pub size: Sizer, pub size: Sizer,
/// Performance counter /// Performance counter
pub perf: PerfModel, pub perf: PerfModel,
/// Available view modes and input bindings /// Configuration watcher
pub watch: Arc<Watch>, pub watch: Arc<Watch>,
/// Currently active modes /// Currently active modes
pub stack: Arc<RwLock<Vec<Arc<str>>>>, pub stack: Arc<RwLock<Vec<Frame>>>,
/// Undo history /// Undo history
pub history: Vec<(AppCmd, Option<AppCmd>)>, pub history: Vec<(AppCmd, Option<AppCmd>)>,
/// Dialog overlay /// Dialog overlay
@ -132,7 +132,7 @@ impl App {
exit: Option<Exit>, exit: Option<Exit>,
project: Project, project: Project,
watch: impl Into<Option<Arc<Watch>>>, watch: impl Into<Option<Arc<Watch>>>,
modes: impl Into<Option<Vec<Arc<str>>>>, modes: impl Into<Option<Vec<Frame>>>,
) -> Self { ) -> Self {
App { App {
exit: exit.unwrap_or_default(), exit: exit.unwrap_or_default(),
@ -150,11 +150,12 @@ impl App {
pub use self::conf::*; mod conf { pub use self::conf::*; mod conf {
use crate::*; use crate::*;
mod axis; pub use self::axis::*; mod axis; pub use self::axis::*;
mod bind; pub use self::bind::*; mod bind; pub use self::bind::*;
mod lang; pub use self::lang::*; mod lang; pub use self::lang::*;
mod mode; pub use self::mode::*; mod mode; pub use self::mode::*;
mod view; pub use self::view::*; mod stack; pub use self::stack::*;
mod view; pub use self::view::*;
pub trait HasError<T> { pub trait HasError<T> {
fn error (&self) -> &RwLock<Option<T>>; fn error (&self) -> &RwLock<Option<T>>;
@ -408,8 +409,12 @@ fn tek_jack_event (state: &mut App, event: JackEvent) {
PortRegistration(_id, false) => { PortRegistration(_id, false) => {
/*println!("\rport del: {id}")*/ /*println!("\rport del: {id}")*/
}, },
PortsConnected(_a, _b, true) => { /*println!("\rport conn: {a} {b}")*/ }, PortsConnected(_a, _b, true) => {
PortsConnected(_a, _b, false) => { /*println!("\rport disc: {a} {b}")*/ }, /*println!("\rport conn: {a} {b}")*/
},
PortsConnected(_a, _b, false) => {
/*println!("\rport disc: {a} {b}")*/
},
ClientRegistration(_id, true) => {}, ClientRegistration(_id, true) => {},
ClientRegistration(_id, false) => {}, ClientRegistration(_id, false) => {},
ThreadInit => {}, ThreadInit => {},
@ -863,7 +868,7 @@ impl Draw<Tui> for App {
#[cfg(feature = "prof2")] profiling::scope!("App::draw"); #[cfg(feature = "prof2")] profiling::scope!("App::draw");
self.perf.cycle(&mut |_|{ self.perf.cycle(&mut |_|{
draw_error(to, self.error.as_ref())?; draw_error(to, self.error.as_ref())?;
draw_mode_stack(to, &self)?; draw_stack(to, &self)?;
view_debug(&*self.stack.read(), &self.perf, &self.size).draw(to)?; view_debug(&*self.stack.read(), &self.perf, &self.size).draw(to)?;
#[cfg(feature = "prof2")] profiling::finish_frame!(); #[cfg(feature = "prof2")] profiling::finish_frame!();
Ok(Some(to.area().into())) Ok(Some(to.area().into()))
@ -871,7 +876,7 @@ impl Draw<Tui> for App {
} }
} }
pub trait DispatchBind<C: Clone>: HasBinds + HasModeStack + HasModes + Namespace<C> { pub trait DispatchBind<C: Clone>: HasBinds + HasStack + HasModes + Namespace<C> {
fn dispatch_bind (&mut self, input: &TuiEvent) -> Usually<()> { fn dispatch_bind (&mut self, input: &TuiEvent) -> Usually<()> {
if let Some(bindings) = self.dispatch_bind_match(input) { if let Some(bindings) = self.dispatch_bind_match(input) {
return self.dispatch_bind_exec(bindings) return self.dispatch_bind_exec(bindings)
@ -897,7 +902,7 @@ pub trait DispatchBind<C: Clone>: HasBinds + HasModeStack + HasModes + Namespace
/// assert!(app.dispatch_bind_match(&"@up".into()).is_none()); /// assert!(app.dispatch_bind_match(&"@up".into()).is_none());
/// ///
/// // Push mode onto stack: /// // Push mode onto stack:
/// app.mode_stack_push("Test"); /// app.stack_push("Test");
/// assert!(app.dispatch_bind_match(&"@left".into()).is_none()); /// assert!(app.dispatch_bind_match(&"@left".into()).is_none());
/// assert!(app.dispatch_bind_match(&"@enter".into()).is_some()); /// assert!(app.dispatch_bind_match(&"@enter".into()).is_some());
/// assert!(app.dispatch_bind_match(&"@escape".into()).is_some()); /// assert!(app.dispatch_bind_match(&"@escape".into()).is_some());
@ -905,7 +910,7 @@ pub trait DispatchBind<C: Clone>: HasBinds + HasModeStack + HasModes + Namespace
/// assert!(app.dispatch_bind_match(&"@up".into()).is_some()); /// assert!(app.dispatch_bind_match(&"@up".into()).is_some());
/// ``` /// ```
fn dispatch_bind_match (&self, input: &TuiEvent) -> Option<Arc<[Binding<Arc<str>>]>> { fn dispatch_bind_match (&self, input: &TuiEvent) -> Option<Arc<[Binding<Arc<str>>]>> {
for name in self.mode_stack().read().iter().rev() { for Frame { name, data } in self.stack().read().iter().rev() {
if let Some(mode) = self.modes_get(name).as_ref().map(Arc::clone) { if let Some(mode) = self.modes_get(name).as_ref().map(Arc::clone) {
if let Some(binds) = self.dispatch_bind_match_axis(mode.as_ref(), input) { if let Some(binds) = self.dispatch_bind_match_axis(mode.as_ref(), input) {
return Some(binds) return Some(binds)
@ -924,7 +929,7 @@ pub trait DispatchBind<C: Clone>: HasBinds + HasModeStack + HasModes + Namespace
/// )).unwrap(); /// )).unwrap();
/// assert!(app.dispatch_bind_match(&"@down".into()).is_none()); /// assert!(app.dispatch_bind_match(&"@down".into()).is_none());
/// assert!(app.dispatch_bind_match(&"@up".into()).is_none()); /// assert!(app.dispatch_bind_match(&"@up".into()).is_none());
/// app.mode_stack_push("Test"); /// app.stack_push("Test");
/// assert!(app.dispatch_bind_match(&"@down".into()).is_some()); /// assert!(app.dispatch_bind_match(&"@down".into()).is_some());
/// assert!(app.dispatch_bind_match(&"@up".into()).is_some()); /// assert!(app.dispatch_bind_match(&"@up".into()).is_some());
/// ``` /// ```
@ -950,7 +955,7 @@ pub trait DispatchBind<C: Clone>: HasBinds + HasModeStack + HasModes + Namespace
/// )).unwrap(); /// )).unwrap();
/// assert!(app.dispatch_bind_match(&"@enter".into()).is_none()); /// assert!(app.dispatch_bind_match(&"@enter".into()).is_none());
/// assert!(app.dispatch_bind_match(&"@escape".into()).is_none()); /// assert!(app.dispatch_bind_match(&"@escape".into()).is_none());
/// app.mode_stack_push("Test"); /// app.stack_push("Test");
/// assert!(app.dispatch_bind_match(&"@enter".into()).is_some()); /// assert!(app.dispatch_bind_match(&"@enter".into()).is_some());
/// assert!(app.dispatch_bind_match(&"@escape".into()).is_some()); /// assert!(app.dispatch_bind_match(&"@escape".into()).is_some());
/// ``` /// ```
@ -958,11 +963,11 @@ pub trait DispatchBind<C: Clone>: HasBinds + HasModeStack + HasModes + Namespace
-> Option<Arc<[Binding<Arc<str>>]>> -> Option<Arc<[Binding<Arc<str>>]>>
{ {
for id in mode.keys.iter() { for id in mode.keys.iter() {
println!("{input:?} {id:?}");
if let Some(event_map) = self.binds_find(id) if let Some(event_map) = self.binds_find(id)
&& let Some(bindings) = event_map.query(input) { && let Some(bindings) = event_map.query(input) {
return Some(bindings.into()) return Some(bindings.into())
} }
if let Ok(Some(expr)) = id.expr() if let Ok(Some(expr)) = id.expr()
&& let Ok(Some(head)) = expr.head() && let Ok(Some(head)) = expr.head()
&& *input == head.into() && *input == head.into()