mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
a random KeyMatcher appears
This commit is contained in:
parent
12faadef44
commit
44201ebf76
6 changed files with 152 additions and 80 deletions
|
|
@ -169,7 +169,7 @@ pub struct PoolView<'a>(pub bool, pub &'a MidiPool);
|
|||
content!(TuiOut: |self: PoolView<'a>| {
|
||||
let Self(compact, model) = self;
|
||||
let MidiPool { clips, mode, .. } = self.1;
|
||||
let color = self.1.clip().map(|c|c.read().unwrap().color).unwrap_or_else(||TuiTheme::g(32).into());
|
||||
//let color = self.1.clip().map(|c|c.read().unwrap().color).unwrap_or_else(||TuiTheme::g(32).into());
|
||||
let on_bg = |x|x;//Bsp::b(Repeat(" "), Tui::bg(color.darkest.rgb, x));
|
||||
let border = |x|x;//Outer(Style::default().fg(color.dark.rgb).bg(color.darkest.rgb)).enclose(x);
|
||||
let iter = | |model.clips().clone().into_iter();
|
||||
|
|
|
|||
|
|
@ -1,44 +1,8 @@
|
|||
(def keys
|
||||
(u :undo 1)
|
||||
(shift-u :redo 1)
|
||||
(ctrl-k :todo "keyboard")
|
||||
(space :play-toggle)
|
||||
(shift-space :play-start-toggle)
|
||||
(e :editor-show :pool-phrase)
|
||||
(ctrl-a :scene-add)
|
||||
(ctrl-t :track-add)
|
||||
(tab :pool-toggle))
|
||||
|
||||
(def keys-clip
|
||||
(q :clip-launch)
|
||||
(c :clip-color)
|
||||
(g :clip-get)
|
||||
(p :clip-put)
|
||||
(del :clip-del)
|
||||
(, :clip-prev)
|
||||
(. :clip-next)
|
||||
(< :clip-swap-prev)
|
||||
(> :clip-swap-next)
|
||||
(l :clip-loop-toggle))
|
||||
|
||||
(def keys-scene
|
||||
(q :scene-launch)
|
||||
(c :scene-color)
|
||||
(, :scene-prev)
|
||||
(. :scene-next)
|
||||
(< :scene-swap-prev)
|
||||
(> :scene-swap-next)
|
||||
(del :scene-delete))
|
||||
|
||||
(def keys-track
|
||||
(q :track-launch)
|
||||
(c :track-color)
|
||||
(, :track-prev)
|
||||
(. :track-next)
|
||||
(< :track-swap-prev)
|
||||
(> :track-swap-next)
|
||||
(del :track-delete))
|
||||
|
||||
(:q enqueue :clip)
|
||||
(:0 enqueue :stop)
|
||||
|
||||
(:u undo 1)
|
||||
(:shift-u redo 1)
|
||||
(:space play/toggle)
|
||||
(:shift-space play/start-toggle)
|
||||
(:e editor/show :pool-phrase)
|
||||
(:ctrl-a scene/add)
|
||||
(:ctrl-t track/add)
|
||||
(:tab pool/toggle)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
(q :clip-launch)
|
||||
(c :clip-color)
|
||||
(g :clip-get)
|
||||
(p :clip-put)
|
||||
(del :clip-del)
|
||||
(, :clip-prev)
|
||||
(. :clip-next)
|
||||
(< :clip-swap-prev)
|
||||
(> :clip-swap-next)
|
||||
(l :clip-loop-toggle)
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
(q :scene-launch)
|
||||
(c :scene-color)
|
||||
(, :scene-prev)
|
||||
(. :scene-next)
|
||||
(< :scene-swap-prev)
|
||||
(> :scene-swap-next)
|
||||
(del :scene-delete)
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
(q :track-launch)
|
||||
(c :track-color)
|
||||
(, :track-prev)
|
||||
(. :track-next)
|
||||
(< :track-swap-prev)
|
||||
(> :track-swap-next)
|
||||
(del :track-delete)
|
||||
|
|
@ -2,50 +2,134 @@ use crate::*;
|
|||
|
||||
impl EdnInput for TuiIn {
|
||||
fn matches_edn (&self, token: &str) -> bool {
|
||||
if let Some(event) = parse_key_spec(token.to_string(), KeyModifiers::NONE) {
|
||||
if let Some(event) = KeyMatcher::new(token).build() {
|
||||
&event == self.event()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
fn get_event <S: AsRef<str>> (item: &EdnItem<S>) -> Option<Event> {
|
||||
match item { EdnItem::Sym(s) => parse_key_spec(s.as_ref().to_string(), KeyModifiers::NONE), _ => None }
|
||||
match item { EdnItem::Sym(s) => KeyMatcher::new(s).build(), _ => None }
|
||||
}
|
||||
}
|
||||
fn parse_key_spec (spec: String, mut mods: KeyModifiers) -> Option<Event> {
|
||||
Some(Event::Key(match spec.as_str() {
|
||||
":enter" | ":return" => KeyEvent::new(KeyCode::Enter, mods),
|
||||
":delete" | ":del" => KeyEvent::new(KeyCode::Enter, mods),
|
||||
|
||||
":comma" => KeyEvent::new(KeyCode::Char(','), mods),
|
||||
":period" => KeyEvent::new(KeyCode::Char('.'), mods),
|
||||
|
||||
":plus" => KeyEvent::new(KeyCode::Char('+'), mods),
|
||||
":underscore" => KeyEvent::new(KeyCode::Char('_'), mods),
|
||||
|
||||
":up" => KeyEvent::new(KeyCode::Up, mods),
|
||||
":down" => KeyEvent::new(KeyCode::Down, mods),
|
||||
":left" => KeyEvent::new(KeyCode::Left, mods),
|
||||
":right" => KeyEvent::new(KeyCode::Right, mods),
|
||||
|
||||
_ => {
|
||||
let chars = spec.chars().collect::<Vec<_>>();
|
||||
match chars.as_slice() {
|
||||
[':', c] => KeyEvent::new(KeyCode::Char(*c), mods),
|
||||
[':', c @ ..] => {
|
||||
let mut splits = c.split(|c|*c=='-');
|
||||
while let Some(split) = splits.next() {
|
||||
match split {
|
||||
['c','t','r','l'] => mods |= KeyModifiers::CONTROL,
|
||||
['a','l','t'] => mods |= KeyModifiers::ALT,
|
||||
['s','h','i','f','t'] => mods |= KeyModifiers::SHIFT,
|
||||
_ => return parse_key_spec(split.iter().collect(), mods)
|
||||
}
|
||||
}
|
||||
panic!("invalid key event {spec:?}")
|
||||
struct KeyMatcher {
|
||||
valid: bool,
|
||||
key: Option<KeyCode>,
|
||||
mods: KeyModifiers,
|
||||
}
|
||||
impl KeyMatcher {
|
||||
fn new (token: impl AsRef<str>) -> 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}")))
|
||||
}
|
||||
_ => panic!("invalid key event {spec:?}")
|
||||
}
|
||||
}
|
||||
}))
|
||||
self
|
||||
}
|
||||
fn named_key (token: &str) -> Option<KeyCode> {
|
||||
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<Event> {
|
||||
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 ));
|
||||
}
|
||||
|
||||
//fn parse_key (spec: std::str::Chars<'_>, mut mods: KeyModifiers) -> Option<Event> {
|
||||
//Some(Event::Key(match spec.chars() {
|
||||
//":enter" | ":return" => KeyEvent::new(KeyCode::Enter, mods),
|
||||
//":delete" | ":del" => KeyEvent::new(KeyCode::Enter, mods),
|
||||
|
||||
//":comma" => KeyEvent::new(KeyCode::Char(','), mods),
|
||||
//":period" => KeyEvent::new(KeyCode::Char('.'), mods),
|
||||
|
||||
//":plus" => KeyEvent::new(KeyCode::Char('+'), mods),
|
||||
//":underscore" => KeyEvent::new(KeyCode::Char('_'), mods),
|
||||
|
||||
//":up" => KeyEvent::new(KeyCode::Up, mods),
|
||||
//":down" => KeyEvent::new(KeyCode::Down, mods),
|
||||
//":left" => KeyEvent::new(KeyCode::Left, mods),
|
||||
//":right" => KeyEvent::new(KeyCode::Right, mods),
|
||||
|
||||
//_ => {
|
||||
//let chars = spec.chars().collect::<Vec<_>>();
|
||||
//match chars.as_slice() {
|
||||
//[':', c] => KeyEvent::new(KeyCode::Char(*c), mods),
|
||||
//[':', c @ ..] => {
|
||||
//let mut splits = c.split(|c|*c=='-');
|
||||
//while let Some(split) = splits.next() {
|
||||
//match split {
|
||||
//['c','t','r','l'] => mods |= KeyModifiers::CONTROL,
|
||||
//['a','l','t'] => mods |= KeyModifiers::ALT,
|
||||
//['s','h','i','f','t'] => mods |= KeyModifiers::SHIFT,
|
||||
//_ => return parse_key(split.iter().collect(), mods)
|
||||
//}
|
||||
//}
|
||||
//panic!("invalid key event {spec:?}")
|
||||
//}
|
||||
//_ => panic!("invalid key event {spec:?}")
|
||||
//}
|
||||
//}
|
||||
//}))
|
||||
//}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue