diff --git a/midi/src/keys_pool.edn b/midi/src/keys_pool.edn index 53d127cd..ad7e00f4 100644 --- a/midi/src/keys_pool.edn +++ b/midi/src/keys_pool.edn @@ -1,8 +1,8 @@ -(@n rename/begin) -(@t length/begin) -(@m import/begin) -(@x export/begin) -(@c clip/color :current :random-color) +(@n rename begin) +(@t length begin) +(@m import begin) +(@x export begin) +(@c clip color :current :random-color) (@openbracket select :previous) (@closebracket select :next) (@lt swap :current :previous) diff --git a/tek/src/keys_clip.edn b/tek/src/keys_clip.edn index f7c63a9d..1559c363 100644 --- a/tek/src/keys_clip.edn +++ b/tek/src/keys_clip.edn @@ -1,3 +1,8 @@ +(@up select :track :scene-prev) +(@down select :track :scene-next) +(@left select :track-prev :scene) +(@right select :track-next :scene) + (@q clip launch) (@c clip color) (@g clip get) diff --git a/tek/src/keys_scene.edn b/tek/src/keys_scene.edn index 89a795e9..0f47e75b 100644 --- a/tek/src/keys_scene.edn +++ b/tek/src/keys_scene.edn @@ -1,3 +1,7 @@ +(@up select 0 :scene-prev) +(@down select 0 :scene-next) +(@right select 1 :scene) + (@q scene launch) (@c scene color) (@comma scene prev) diff --git a/tek/src/keys_track.edn b/tek/src/keys_track.edn index 623cc9e5..71436c7c 100644 --- a/tek/src/keys_track.edn +++ b/tek/src/keys_track.edn @@ -1,3 +1,7 @@ +(@left select :track-prev 0) +(@right select :track-next 0) +(@down select :track down) + (@q track launch) (@c track color) (@comma track prev) diff --git a/tek/src/lib.rs b/tek/src/lib.rs index 809a68f3..0dd56c2a 100644 --- a/tek/src/lib.rs +++ b/tek/src/lib.rs @@ -68,7 +68,14 @@ has_editor!(|self: App|{ editor_h = 15; is_editing = self.editing.load(Relaxed); }); -edn_provide!(# usize: |self: App| {}); +edn_provide!(# usize: |self: App| { + ":scene" => 0, + ":scene-next" => 0, + ":scene-prev" => 0, + ":track" => 0, + ":track-next" => 0, + ":track-prev" => 0, +}); edn_view!(TuiOut: |self: App| self.size.of(EdnView::from_source(self, self.edn.as_ref())); { bool {}; isize {}; diff --git a/tui/src/lib.rs b/tui/src/lib.rs index 372acb13..d997312a 100644 --- a/tui/src/lib.rs +++ b/tui/src/lib.rs @@ -23,7 +23,6 @@ mod tui_border; pub use self::tui_border::*; mod tui_field; pub use self::tui_field::*; mod tui_buffer; pub use self::tui_buffer::*; mod tui_file; pub use self::tui_file::*; -mod tui_edn_keymap; pub use self::tui_edn_keymap::*; pub(crate) use std::sync::{Arc, RwLock, atomic::{AtomicBool, Ordering::*}}; pub(crate) use std::io::{stdout, Stdout}; pub(crate) use std::path::PathBuf; diff --git a/tui/src/tui_edn_keymap.rs b/tui/src/tui_edn_keymap.rs deleted file mode 100644 index 3ef606c5..00000000 --- a/tui/src/tui_edn_keymap.rs +++ /dev/null @@ -1,95 +0,0 @@ -use crate::*; -impl EdnInput for TuiIn { - fn matches_edn (&self, token: &str) -> bool { - if let Some(event) = KeyMatcher::new(token).build() { - &event == self.event() - } else { - false - } - } - fn get_event > (item: &EdnItem) -> Option { - match item { EdnItem::Sym(s) => KeyMatcher::new(s).build(), _ => None } - } -} -struct KeyMatcher { - valid: bool, - key: Option, - mods: KeyModifiers, -} -impl KeyMatcher { - fn new (token: impl AsRef) -> Self { - let token = token.as_ref(); - if token.len() < 2 { - Self { valid: false, key: None, mods: KeyModifiers::NONE } - } else if token.chars().next() != Some('@') { - Self { valid: false, key: None, mods: KeyModifiers::NONE } - } else { - Self { valid: true, key: None, mods: KeyModifiers::NONE }.next(&token[1..]) - } - } - fn next (mut self, token: &str) -> Self { - let mut tokens = token.split('-').peekable(); - while let Some(token) = tokens.next() { - if tokens.peek().is_some() { - match token { - "ctrl" | "Ctrl" | "c" | "C" => self.mods |= KeyModifiers::CONTROL, - "alt" | "Alt" | "m" | "M" => self.mods |= KeyModifiers::ALT, - "shift" | "Shift" | "s" | "S" => { - self.mods |= KeyModifiers::SHIFT; - // + TODO normalize character case, BackTab, etc. - }, - _ => panic!("unknown modifier {token}"), - } - } else { - self.key = if token.len() == 1 { - Some(KeyCode::Char(token.chars().next().unwrap())) - } else { - Some(Self::named_key(token).unwrap_or_else(||panic!("unknown character {token}"))) - } - } - } - self - } - fn named_key (token: &str) -> Option { - use KeyCode::*; - Some(match token { - "up" => Up, - "down" => Down, - "left" => Left, - "right" => Right, - "enter" | "return" => Enter, - "delete" | "del" => Delete, - "tab" => Tab, - "space" => Char(' '), - "comma" => Char(','), - "period" => Char('.'), - "plus" => Char('+'), - "minus" | "dash" => Char('-'), - "equal" | "equals" => Char('='), - "underscore" => Char('_'), - "backtick" => Char('`'), - _ => return None, - }) - } - fn build (self) -> Option { - if self.valid && self.key.is_some() { - Some(Event::Key(KeyEvent::new(self.key.unwrap(), self.mods))) - } else { - None - } - } -} -#[cfg(test)] #[test] fn test_parse_key () { - use KeyModifiers as Mods; - let test = |x: &str, y|assert_eq!(KeyMatcher::new(x).build(), Some(Event::Key(y))); - test(":x", - KeyEvent::new(KeyCode::Char('x'), Mods::NONE)); - test(":ctrl-x", - KeyEvent::new(KeyCode::Char('x'), Mods::CONTROL)); - test(":alt-x", - KeyEvent::new(KeyCode::Char('x'), Mods::ALT)); - test(":shift-x", - KeyEvent::new(KeyCode::Char('x'), Mods::SHIFT)); - test(":ctrl-alt-shift-x", - KeyEvent::new(KeyCode::Char('x'), Mods::CONTROL | Mods::ALT | Mods::SHIFT )); -} diff --git a/tui/src/tui_input.rs b/tui/src/tui_input.rs index 38275ec8..31f55408 100644 --- a/tui/src/tui_input.rs +++ b/tui/src/tui_input.rs @@ -46,90 +46,101 @@ impl TuiIn { }) } } -//. -///// Define a key -//pub const fn key (code: KeyCode) -> Event { - //let modifiers = KeyModifiers::NONE; - //let kind = KeyEventKind::Press; - //let state = KeyEventState::NONE; - //Event::Key(KeyEvent { code, modifiers, kind, state }) -//} -///// Add Ctrl modifier to key -//pub const fn ctrl (event: Event) -> Event { - //match event { - //Event::Key(mut event) => { - //event.modifiers = event.modifiers.union(KeyModifiers::CONTROL) - //}, - //_ => {} - //} - //event -//} -///// Add Alt modifier to key -//pub const fn alt (event: Event) -> Event { - //match event { - //Event::Key(mut event) => { - //event.modifiers = event.modifiers.union(KeyModifiers::ALT) - //}, - //_ => {} - //} - //event -//} -///// Add Shift modifier to key -//pub const fn shift (event: Event) -> Event { - //match event { - //Event::Key(mut event) => { - //event.modifiers = event.modifiers.union(KeyModifiers::SHIFT) - //}, - //_ => {} - //} - //event -//} -//#[macro_export] macro_rules! kpat { - //(Ctrl-Alt-$code:pat) => { kpat!($code, KeyModifiers::CONTROL | KeyModifiers::ALT) }; - //(Ctrl-$code:pat) => { kpat!($code, KeyModifiers::CONTROL) }; - //(Alt-$code:pat) => { kpat!($code, KeyModifiers::ALT) }; - //(Shift-$code:pat) => { kpat!($code, KeyModifiers::SHIFT) }; - //($code:pat) => { - //crossterm::event::Event::Key(KeyEvent { - //code: $code, - //modifiers: KeyModifiers::NONE, - //kind: KeyEventKind::Press, - //state: KeyEventState::NONE - //}) - //}; - //($code:pat, $modifiers: pat) => { - //crossterm::event::Event::Key(KeyEvent { - //code: $code, - //modifiers: $modifiers, - //kind: KeyEventKind::Press, - //state: KeyEventState::NONE - //}) - //}; -//} -//#[macro_export] macro_rules! kexp { - //(Ctrl-Alt-$code:ident) => { key_event_expr!($code, KeyModifiers::from_bits(0b0000_0110).unwrap()) }; - //(Ctrl-$code:ident) => { key_event_expr!($code, KeyModifiers::CONTROL) }; - //(Alt-$code:ident) => { key_event_expr!($code, KeyModifiers::ALT) }; - //(Shift-$code:ident) => { key_event_expr!($code, KeyModifiers::SHIFT) }; - //($code:ident) => { key_event_expr!($code) }; - //($code:expr) => { key_event_expr!($code) }; -//} -//#[macro_export] macro_rules! key_event_expr { - //($code:expr, $modifiers: expr) => { - //crossterm::event::Event::Key(KeyEvent { - //code: $code, - //modifiers: $modifiers, - //kind: KeyEventKind::Press, - //state: KeyEventState::NONE - //}) - //}; - //($code:expr) => { - //crossterm::event::Event::Key(KeyEvent { - //code: $code, - //modifiers: KeyModifiers::NONE, - //kind: KeyEventKind::Press, - //state: KeyEventState::NONE - //}) - //}; -//} - +impl EdnInput for TuiIn { + fn matches_edn (&self, token: &str) -> bool { + if let Some(event) = KeyMatcher::new(token).build() { + &event == self.event() + } else { + false + } + } + fn get_event > (item: &EdnItem) -> Option { + match item { EdnItem::Sym(s) => KeyMatcher::new(s).build(), _ => None } + } +} +struct KeyMatcher { + valid: bool, + key: Option, + mods: KeyModifiers, +} +impl KeyMatcher { + fn new (token: impl AsRef) -> Self { + let token = token.as_ref(); + if token.len() < 2 { + Self { valid: false, key: None, mods: KeyModifiers::NONE } + } else if token.chars().next() != Some('@') { + Self { valid: false, key: None, mods: KeyModifiers::NONE } + } else { + Self { valid: true, key: None, mods: KeyModifiers::NONE }.next(&token[1..]) + } + } + fn next (mut self, token: &str) -> Self { + let mut tokens = token.split('-').peekable(); + while let Some(token) = tokens.next() { + if tokens.peek().is_some() { + match token { + "ctrl" | "Ctrl" | "c" | "C" => self.mods |= KeyModifiers::CONTROL, + "alt" | "Alt" | "m" | "M" => self.mods |= KeyModifiers::ALT, + "shift" | "Shift" | "s" | "S" => { + self.mods |= KeyModifiers::SHIFT; + // + TODO normalize character case, BackTab, etc. + }, + _ => panic!("unknown modifier {token}"), + } + } else { + self.key = if token.len() == 1 { + Some(KeyCode::Char(token.chars().next().unwrap())) + } else { + Some(Self::named_key(token).unwrap_or_else(||panic!("unknown character {token}"))) + } + } + } + self + } + fn named_key (token: &str) -> Option { + use KeyCode::*; + Some(match token { + "up" => Up, + "down" => Down, + "left" => Left, + "right" => Right, + "enter" | "return" => Enter, + "delete" | "del" => Delete, + "tab" => Tab, + "space" => Char(' '), + "comma" => Char(','), + "period" => Char('.'), + "plus" => Char('+'), + "minus" | "dash" => Char('-'), + "equal" | "equals" => Char('='), + "underscore" => Char('_'), + "backtick" => Char('`'), + "lt" => Char('<'), + "gt" => Char('>'), + "openbracket" => Char('['), + "closebracket" => Char(']'), + _ => return None, + }) + } + fn build (self) -> Option { + if self.valid && self.key.is_some() { + Some(Event::Key(KeyEvent::new(self.key.unwrap(), self.mods))) + } else { + None + } + } +} +#[cfg(test)] #[test] fn test_parse_key () { + use KeyModifiers as Mods; + let test = |x: &str, y|assert_eq!(KeyMatcher::new(x).build(), Some(Event::Key(y))); + test(":x", + KeyEvent::new(KeyCode::Char('x'), Mods::NONE)); + test(":ctrl-x", + KeyEvent::new(KeyCode::Char('x'), Mods::CONTROL)); + test(":alt-x", + KeyEvent::new(KeyCode::Char('x'), Mods::ALT)); + test(":shift-x", + KeyEvent::new(KeyCode::Char('x'), Mods::SHIFT)); + test(":ctrl-alt-shift-x", + KeyEvent::new(KeyCode::Char('x'), Mods::CONTROL | Mods::ALT | Mods::SHIFT )); +}