mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
lol tmux jumbles the input codes immensely
This commit is contained in:
parent
a66bc5ca5e
commit
228b4bb47c
8 changed files with 98 additions and 61 deletions
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
2
tek/src/keys_mix.edn
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
(@down select 0 1)
|
||||
(@right select 1 0)
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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..])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue