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 crate::*;
use EdnItem::*; 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>>); pub struct EdnKeymap<'a>(pub Vec<EdnItem<&'a str>>);
impl<'a> EdnKeymap<'a> { impl<'a> EdnKeymap<'a> {

View file

@ -1,8 +1,8 @@
(:u undo 1) (@u undo 1)
(:shift-u redo 1) (@shift-u redo 1)
(:space play/toggle) (@space play/toggle)
(:shift-space play/start-toggle) (@shift-space play/start-toggle)
(:e editor/show :pool-phrase) (@e editor/show :pool-phrase)
(:ctrl-a scene/add) (@ctrl-a scene add)
(:ctrl-t track/add) (@ctrl-t track add)
(:tab pool/toggle) (@tab pool/toggle)

View file

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

View file

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

View file

@ -45,6 +45,7 @@ pub use ::tek_tui::{
pub size: Measure<TuiOut>, pub size: Measure<TuiOut>,
pub perf: PerfModel, pub perf: PerfModel,
pub compact: bool, pub compact: bool,
pub history: Vec<AppCommand>,
} }
has_size!(<TuiOut>|self: App|&self.size); has_size!(<TuiOut>|self: App|&self.size);
has_clock!(|self: App|&self.clock); has_clock!(|self: App|&self.clock);
@ -373,37 +374,34 @@ impl App {
} }
Ok(()) 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::*; use EdnItem::*;
let mut command: Option<AppCommand> = None; let mut command: Option<AppCommand> = None;
let edns: Vec<EdnItem<&str>> = EdnItem::read_all(Self::KEYS_APP)?; // Handle from root keymap
for item in edns { if let Some(command) = EdnKeyMapToCommand::new(KEYS_APP)?.from::<_, AppCommand>(self, input) {
if let Exp(e) = item { if let Some(undo) = command.execute(self)? { self.history.push(undo); }
match e.as_slice() { return Ok(Some(true))
[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")
}
} }
Ok(if let Some(command) = command { // Handle from selection-dependent keymaps
let _undo = command.execute(self)?; if let Some(command) = EdnKeyMapToCommand::new(match self.selected() {
Some(true) Selection::Clip(t, s) => KEYS_CLIP,
} else { Selection::Track(t) => KEYS_TRACK,
None 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 { #[derive(Clone, Debug)] pub enum AppCommand {
Clip(ClipCommand), Clip(ClipCommand),
Clock(ClockCommand), Clock(ClockCommand),
@ -427,7 +425,12 @@ edn_command!(AppCommand: |state: App| {
("undo" [d: usize] Self::History(-(d.unwrap_or(0)as isize))) ("undo" [d: usize] Self::History(-(d.unwrap_or(0)as isize)))
("redo" [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)) ("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)) ("enqueue" [c: Arc<RwLock<MidiClip>>] Self::Enqueue(c))
("clip" [a, ..b] Self::Clip( ("clip" [a, ..b] Self::Clip(

View file

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