lol tmux jumbles the input codes immensely

This commit is contained in:
🪞👃🪞 2025-01-14 20:56:48 +01:00
parent a66bc5ca5e
commit 228b4bb47c
8 changed files with 98 additions and 61 deletions

View file

@ -1,6 +1,38 @@
use crate::*;
use EdnItem::*;
pub struct EdnKeyMapToCommand<'a>(Vec<EdnItem<&'a str>>);
impl<'a> EdnKeyMapToCommand<'a> {
/// Construct keymap from source text or fail
pub fn new (keymap: &'a str) -> Usually<Self> {
Ok(Self(EdnItem::<&str>::read_all(keymap)?))
}
/// Try to find a binding matching the currently pressed key
pub fn from <T, C> (&self, state: &T, input: &impl EdnInput) -> Option<C>
where
C: Command<T> + EdnCommand<T>
{
use EdnItem::*;
let mut command: Option<C> = None;
for item in self.0.iter() {
if let Exp(e) = item {
match e.as_slice() {
[Sym(key), c, args @ ..] if input.matches_edn(key) => {
command = C::from_edn(state, c, args);
if command.is_some() {
break
}
},
_ => {}
}
} else {
panic!("invalid config")
}
}
command
}
}
pub struct EdnKeymap<'a>(pub Vec<EdnItem<&'a str>>);
impl<'a> EdnKeymap<'a> {

View file

@ -1,8 +1,8 @@
(: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)
(@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)

View file

@ -1,10 +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)
(@q clip launch)
(@c clip color)
(@g clip get)
(@p clip put)
(@delete clip del)
(@comma clip prev)
(@period clip next)
(@lt clip swap-prev)
(@gt clip swap-next)
(@l clip loop-toggle)

2
tek/src/keys_mix.edn Normal file
View file

@ -0,0 +1,2 @@
(@down select 0 1)
(@right select 1 0)

View file

@ -1,7 +1,7 @@
(q :scene-launch)
(c :scene-color)
(, :scene-prev)
(. :scene-next)
(< :scene-swap-prev)
(> :scene-swap-next)
(del :scene-delete)
(@q scene launch)
(@c scene color)
(@comma scene prev)
(@period scene next)
(@lt scene swap-prev)
(@gt scene swap-next)
(@delete scene delete)

View file

@ -1,7 +1,7 @@
(q :track-launch)
(c :track-color)
(, :track-prev)
(. :track-next)
(< :track-swap-prev)
(> :track-swap-next)
(del :track-delete)
(@q track launch)
(@c track color)
(@comma track prev)
(@period track next)
(@lt track swap-prev)
(@gt track swap-next)
(@delete track delete)

View file

@ -45,6 +45,7 @@ pub use ::tek_tui::{
pub size: Measure<TuiOut>,
pub perf: PerfModel,
pub compact: bool,
pub history: Vec<AppCommand>,
}
has_size!(<TuiOut>|self: App|&self.size);
has_clock!(|self: App|&self.clock);
@ -373,37 +374,34 @@ impl App {
}
Ok(())
}
const KEYS_APP: &str = include_str!("keys.edn");
const KEYS_CLIP: &str = include_str!("keys_clip.edn");
const KEYS_TRACK: &str = include_str!("keys_track.edn");
const KEYS_SCENE: &str = include_str!("keys_scene.edn");
}
handle!(TuiIn: |self: App, input|{
const KEYS_APP: &str = include_str!("keys.edn");
const KEYS_CLIP: &str = include_str!("keys_clip.edn");
const KEYS_TRACK: &str = include_str!("keys_track.edn");
const KEYS_SCENE: &str = include_str!("keys_scene.edn");
const KEYS_MIX: &str = include_str!("keys_mix.edn");
handle!(TuiIn: |self: App, input|Ok({
use EdnItem::*;
let mut command: Option<AppCommand> = None;
let edns: Vec<EdnItem<&str>> = EdnItem::read_all(Self::KEYS_APP)?;
for item in edns {
if let Exp(e) = item {
match e.as_slice() {
[Sym(key), c, args @ ..] if input.matches_edn(key) => {
command = AppCommand::from_edn(self, c, args);
if command.is_some() {
break
}
},
_ => {}
}
} else {
panic!("invalid config")
}
// Handle from root keymap
if let Some(command) = EdnKeyMapToCommand::new(KEYS_APP)?.from::<_, AppCommand>(self, input) {
if let Some(undo) = command.execute(self)? { self.history.push(undo); }
return Ok(Some(true))
}
Ok(if let Some(command) = command {
let _undo = command.execute(self)?;
Some(true)
} else {
None
})
});
// Handle from selection-dependent keymaps
if let Some(command) = EdnKeyMapToCommand::new(match self.selected() {
Selection::Clip(t, s) => KEYS_CLIP,
Selection::Track(t) => KEYS_TRACK,
Selection::Scene(s) => KEYS_SCENE,
Selection::Mix => KEYS_MIX,
})?.from::<_, AppCommand>(
self, input
) {
if let Some(undo) = command.execute(self)? { self.history.push(undo); }
return Ok(Some(true))
}
None
}));
#[derive(Clone, Debug)] pub enum AppCommand {
Clip(ClipCommand),
Clock(ClockCommand),
@ -427,7 +425,12 @@ edn_command!(AppCommand: |state: App| {
("undo" [d: usize] Self::History(-(d.unwrap_or(0)as isize)))
("redo" [d: usize] Self::History(d.unwrap_or(0) as isize))
("zoom" [z: usize] Self::Zoom(z))
("select" [s: Selection] Self::Select(s.expect("no selection")))
("select" [t: usize, s: usize] match (t.expect("no track"), s.expect("no scene")) {
(0, 0) => Self::Select(Selection::Mix),
(t, 0) => Self::Select(Selection::Track(t - 1)),
(0, s) => Self::Select(Selection::Scene(s - 1)),
(t, s) => Self::Select(Selection::Clip(t - 1, s - 1)),
})
("enqueue" [c: Arc<RwLock<MidiClip>>] Self::Enqueue(c))
("clip" [a, ..b] Self::Clip(

View file

@ -21,7 +21,7 @@ impl KeyMatcher {
let token = token.as_ref();
if token.len() < 2 {
Self { valid: false, key: None, mods: KeyModifiers::NONE }
} else if token.chars().next() != Some(':') {
} 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..])