use keymap! in more places

This commit is contained in:
🪞👃🪞 2025-01-02 21:36:32 +01:00
parent 8dedc8fd5f
commit a82f73d475
6 changed files with 200 additions and 268 deletions

View file

@ -45,121 +45,114 @@ pub enum ArrangerClipCommand {
SetColor(usize, usize, ItemPalette),
}
input_to_command!(ArrangerCommand: |state: ArrangerTui, input: Event|match input {
key_pat!(Char('u')) => Self::History(-1),
key_pat!(Char('U')) => Self::History(1),
use ArrangerCommand as Cmd;
keymap!(KEYS_ARRANGER = |state: ArrangerTui, input: Event| ArrangerCommand {
key(Char('u')) => Cmd::History(-1),
key(Char('U')) => Cmd::History(1),
// TODO: k: toggle on-screen keyboard
key_pat!(Ctrl-Char('k')) => { todo!("keyboard") },
ctrl(key(Char('k'))) => { todo!("keyboard") },
// Transport: Play/pause
key_pat!(Char(' ')) =>
Self::Clock(if state.clock().is_stopped() { Play(None) } else { Pause(None) }),
key(Char(' ')) => Cmd::Clock(if state.clock().is_stopped() { Play(None) } else { Pause(None) }),
// Transport: Play from start or rewind to start
key_pat!(Shift-Char(' ')) =>
Self::Clock(if state.clock().is_stopped() { Play(Some(0)) } else { Pause(Some(0)) }),
key_pat!(Char('e')) =>
Self::Editor(MidiEditCommand::Show(Some(state.pool.phrase().clone()))),
key_pat!(Ctrl-Left) =>
Self::Scene(ArrangerSceneCommand::Add),
key_pat!(Ctrl-Char('t')) =>
Self::Track(ArrangerTrackCommand::Add),
shift(key(Char(' '))) => Cmd::Clock(if state.clock().is_stopped() { Play(Some(0)) } else { Pause(Some(0)) }),
key(Char('e')) => Cmd::Editor(MidiEditCommand::Show(Some(state.pool.phrase().clone()))),
ctrl(key(Char('a'))) => Cmd::Scene(ArrangerSceneCommand::Add),
ctrl(key(Char('t'))) => Cmd::Track(ArrangerTrackCommand::Add),
// Tab: Toggle visibility of phrase pool column
key_pat!(Tab) =>
Self::Phrases(PoolCommand::Show(!state.pool.visible)),
_ => {
use ArrangerCommand as Cmd;
use ArrangerSelection as Selected;
use ArrangerSceneCommand as Scene;
use ArrangerTrackCommand as Track;
use ArrangerClipCommand as Clip;
let t_len = state.tracks.len();
let s_len = state.scenes.len();
match state.selected() {
Selected::Clip(t, s) => match input {
key_pat!(Char('g')) => Some(Cmd::Phrases(PoolCommand::Select(0))),
key_pat!(Char('q')) => Some(Cmd::Clip(Clip::Enqueue(t, s))),
key_pat!(Char(',')) => Some(Cmd::Clip(Clip::Put(t, s, None))),
key_pat!(Char('.')) => Some(Cmd::Clip(Clip::Put(t, s, None))),
key_pat!(Char('<')) => Some(Cmd::Clip(Clip::Put(t, s, None))),
key_pat!(Char('>')) => Some(Cmd::Clip(Clip::Put(t, s, None))),
key_pat!(Char('p')) => Some(Cmd::Clip(Clip::Put(t, s, Some(state.pool.phrase().clone())))),
key_pat!(Char('l')) => Some(Cmd::Clip(ArrangerClipCommand::SetLoop(t, s, false))),
key_pat!(Delete) => Some(Cmd::Clip(Clip::Put(t, s, None))),
key(Tab) => Cmd::Phrases(PoolCommand::Show(!state.pool.visible)),
}, {
use ArrangerSelection as Selected;
use ArrangerSceneCommand as Scene;
use ArrangerTrackCommand as Track;
use ArrangerClipCommand as Clip;
let t_len = state.tracks.len();
let s_len = state.scenes.len();
match state.selected() {
Selected::Clip(t, s) => match input {
key_pat!(Char('g')) => Some(Cmd::Phrases(PoolCommand::Select(0))),
key_pat!(Char('q')) => Some(Cmd::Clip(Clip::Enqueue(t, s))),
key_pat!(Char(',')) => Some(Cmd::Clip(Clip::Put(t, s, None))),
key_pat!(Char('.')) => Some(Cmd::Clip(Clip::Put(t, s, None))),
key_pat!(Char('<')) => Some(Cmd::Clip(Clip::Put(t, s, None))),
key_pat!(Char('>')) => Some(Cmd::Clip(Clip::Put(t, s, None))),
key_pat!(Char('p')) => Some(Cmd::Clip(Clip::Put(t, s, Some(state.pool.phrase().clone())))),
key_pat!(Char('l')) => Some(Cmd::Clip(ArrangerClipCommand::SetLoop(t, s, false))),
key_pat!(Delete) => Some(Cmd::Clip(Clip::Put(t, s, None))),
key_pat!(Up) => Some(Cmd::Select(
if s > 0 { Selected::Clip(t, s - 1) } else { Selected::Track(t) })),
key_pat!(Down) => Some(Cmd::Select(
Selected::Clip(t, (s + 1).min(s_len.saturating_sub(1))))),
key_pat!(Left) => Some(Cmd::Select(
if t > 0 { Selected::Clip(t - 1, s) } else { Selected::Scene(s) })),
key_pat!(Right) => Some(Cmd::Select(
Selected::Clip((t + 1).min(t_len.saturating_sub(1)), s))),
key_pat!(Up) => Some(Cmd::Select(
if s > 0 { Selected::Clip(t, s - 1) } else { Selected::Track(t) })),
key_pat!(Down) => Some(Cmd::Select(
Selected::Clip(t, (s + 1).min(s_len.saturating_sub(1))))),
key_pat!(Left) => Some(Cmd::Select(
if t > 0 { Selected::Clip(t - 1, s) } else { Selected::Scene(s) })),
key_pat!(Right) => Some(Cmd::Select(
Selected::Clip((t + 1).min(t_len.saturating_sub(1)), s))),
_ => None
},
Selected::Scene(s) => match input {
key_pat!(Char(',')) => Some(Cmd::Scene(Scene::Swap(s, s - 1))),
key_pat!(Char('.')) => Some(Cmd::Scene(Scene::Swap(s, s + 1))),
key_pat!(Char('<')) => Some(Cmd::Scene(Scene::Swap(s, s - 1))),
key_pat!(Char('>')) => Some(Cmd::Scene(Scene::Swap(s, s + 1))),
key_pat!(Char('q')) => Some(Cmd::Scene(Scene::Enqueue(s))),
key_pat!(Delete) => Some(Cmd::Scene(Scene::Delete(s))),
key_pat!(Char('c')) => Some(Cmd::Scene(Scene::SetColor(s, ItemPalette::random()))),
_ => None
},
Selected::Scene(s) => match input {
key_pat!(Char(',')) => Some(Cmd::Scene(Scene::Swap(s, s - 1))),
key_pat!(Char('.')) => Some(Cmd::Scene(Scene::Swap(s, s + 1))),
key_pat!(Char('<')) => Some(Cmd::Scene(Scene::Swap(s, s - 1))),
key_pat!(Char('>')) => Some(Cmd::Scene(Scene::Swap(s, s + 1))),
key_pat!(Char('q')) => Some(Cmd::Scene(Scene::Enqueue(s))),
key_pat!(Delete) => Some(Cmd::Scene(Scene::Delete(s))),
key_pat!(Char('c')) => Some(Cmd::Scene(Scene::SetColor(s, ItemPalette::random()))),
key_pat!(Up) => Some(
Cmd::Select(if s > 0 { Selected::Scene(s - 1) } else { Selected::Mix })),
key_pat!(Down) => Some(
Cmd::Select(Selected::Scene((s + 1).min(s_len.saturating_sub(1))))),
key_pat!(Left) =>
return None,
key_pat!(Right) => Some(
Cmd::Select(Selected::Clip(0, s))),
key_pat!(Up) => Some(
Cmd::Select(if s > 0 { Selected::Scene(s - 1) } else { Selected::Mix })),
key_pat!(Down) => Some(
Cmd::Select(Selected::Scene((s + 1).min(s_len.saturating_sub(1))))),
key_pat!(Left) =>
return None,
key_pat!(Right) => Some(
Cmd::Select(Selected::Clip(0, s))),
_ => None
},
Selected::Track(t) => match input {
key_pat!(Char(',')) => Some(Cmd::Track(Track::Swap(t, t - 1))),
key_pat!(Char('.')) => Some(Cmd::Track(Track::Swap(t, t + 1))),
key_pat!(Char('<')) => Some(Cmd::Track(Track::Swap(t, t - 1))),
key_pat!(Char('>')) => Some(Cmd::Track(Track::Swap(t, t + 1))),
key_pat!(Delete) => Some(Cmd::Track(Track::Delete(t))),
key_pat!(Char('c')) => Some(Cmd::Track(Track::SetColor(t, ItemPalette::random()))),
_ => None
},
Selected::Track(t) => match input {
key_pat!(Char(',')) => Some(Cmd::Track(Track::Swap(t, t - 1))),
key_pat!(Char('.')) => Some(Cmd::Track(Track::Swap(t, t + 1))),
key_pat!(Char('<')) => Some(Cmd::Track(Track::Swap(t, t - 1))),
key_pat!(Char('>')) => Some(Cmd::Track(Track::Swap(t, t + 1))),
key_pat!(Delete) => Some(Cmd::Track(Track::Delete(t))),
key_pat!(Char('c')) => Some(Cmd::Track(Track::SetColor(t, ItemPalette::random()))),
key_pat!(Up) =>
return None,
key_pat!(Down) => Some(
Cmd::Select(Selected::Clip(t, 0))),
key_pat!(Left) => Some(
Cmd::Select(if t > 0 { Selected::Track(t - 1) } else { Selected::Mix })),
key_pat!(Right) => Some(
Cmd::Select(Selected::Track((t + 1).min(t_len.saturating_sub(1))))),
key_pat!(Up) =>
return None,
key_pat!(Down) => Some(
Cmd::Select(Selected::Clip(t, 0))),
key_pat!(Left) => Some(
Cmd::Select(if t > 0 { Selected::Track(t - 1) } else { Selected::Mix })),
key_pat!(Right) => Some(
Cmd::Select(Selected::Track((t + 1).min(t_len.saturating_sub(1))))),
_ => None
},
Selected::Mix => match input {
key_pat!(Delete) => Some(Cmd::Clear),
key_pat!(Char('0')) => Some(Cmd::StopAll),
key_pat!(Char('c')) => Some(Cmd::Color(ItemPalette::random())),
_ => None
},
Selected::Mix => match input {
key_pat!(Delete) => Some(Cmd::Clear),
key_pat!(Char('0')) => Some(Cmd::StopAll),
key_pat!(Char('c')) => Some(Cmd::Color(ItemPalette::random())),
key_pat!(Up) =>
return None,
key_pat!(Down) => Some(
Cmd::Select(Selected::Scene(0))),
key_pat!(Left) =>
return None,
key_pat!(Right) => Some(
Cmd::Select(Selected::Track(0))),
key_pat!(Up) =>
return None,
key_pat!(Down) => Some(
Cmd::Select(Selected::Scene(0))),
key_pat!(Left) =>
return None,
key_pat!(Right) => Some(
Cmd::Select(Selected::Track(0))),
_ => None
},
}
}.or_else(||if let Some(command) = MidiEditCommand::input_to_command(&state.editor, input) {
Some(Self::Editor(command))
} else if let Some(command) = PoolCommand::input_to_command(&state.pool, input) {
Some(Self::Phrases(command))
} else {
None
})?
});
_ => None
},
}
}.or_else(||if let Some(command) = MidiEditCommand::input_to_command(&state.editor, input) {
Some(Cmd::Editor(command))
} else if let Some(command) = PoolCommand::input_to_command(&state.pool, input) {
Some(Cmd::Phrases(command))
} else {
None
})?);
command!(|self: ArrangerCommand, state: ArrangerTui|match self {
Self::Clock(cmd) => cmd.delegate(state, Self::Clock)?,