From 4d480c4b0a419399dc6406b9efc681ef2d093497 Mon Sep 17 00:00:00 2001 From: HoneyHazard <8847050+HoneyHazard@users.noreply.github.com> Date: Wed, 5 Aug 2026 02:27:56 -0700 Subject: [PATCH] Add F1-F5 as default tab-switching shortcuts With 5 possible tabs (Playback/Recording/Output/Input/Configuration), cycling one at a time with H/L or Tab/Shift+Tab is slow if you want to jump straight to a specific one. This has been asked for before (#38 - closed by the reporter themselves once they found the workaround, not because it was rejected): SelectTab(N) already exists and already works exactly for this, but has no default binding, so users have to know to add it themselves via the README's own "Use F-keys to select tabs" customization example. Makes that the default instead: F1-F5 bound to SelectTab(0..4). SelectTab already silently no-ops on an out-of-range index (see Action::handle), so binding all 5 unconditionally is safe even with `tabs` configured to fewer than 5 entries - unused F-keys just do nothing rather than erroring. Updated the README's keybinding table and its now-redundant "F-keys to select tabs" example, which is rewritten to show remapping F-keys to something else (e.g. Alt+1..5) for anyone whose terminal/WM intercepts function keys, since the original example no longer demonstrates anything you don't already get by default. Tested: cargo test (145/145, including a new test asserting all 5 F-key defaults resolve to the expected SelectTab index), cargo fmt --check / cargo clippy -- -D warnings / cargo doc (matching wiremix's CI) all clean. --- README.md | 22 ++++++++++++++++------ src/config/keybinding.rs | 29 +++++++++++++++++++++++++++++ wiremix.toml | 12 +++++++++--- 3 files changed, 54 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 9d4bb10..280e564 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,7 @@ less-intuitive mouse controls are: | k/Up arrow | Move up | | H/Shift+Tab | Select previous tab | | L/Tab | Select next tab | +| F1-F5 | Select tab by position | | ` (Backtick) | Set volume 0% | | 1 | Set volume 10% | | 2 | Set volume 20% | @@ -183,14 +184,23 @@ keybindings = [ ] ``` +F1-F5 already select a tab by position by default. To remap that to +different keys instead (e.g. if F-keys are intercepted by your terminal or +window manager): + ```toml keybindings = [ - # Use F-keys to select tabs - { key = { F = 1 }, action = { SelectTab = 0 } }, - { key = { F = 2 }, action = { SelectTab = 1 } }, - { key = { F = 3 }, action = { SelectTab = 2 } }, - { key = { F = 4 }, action = { SelectTab = 3 } }, - { key = { F = 5 }, action = { SelectTab = 4 } }, + # Free up F1-F5 and use Alt+1 through Alt+5 for tab selection instead + { key = { F = 1 }, action = "Nothing" }, + { key = { F = 2 }, action = "Nothing" }, + { key = { F = 3 }, action = "Nothing" }, + { key = { F = 4 }, action = "Nothing" }, + { key = { F = 5 }, action = "Nothing" }, + { key = { Char = "1" }, modifiers = "ALT", action = { SelectTab = 0 } }, + { key = { Char = "2" }, modifiers = "ALT", action = { SelectTab = 1 } }, + { key = { Char = "3" }, modifiers = "ALT", action = { SelectTab = 2 } }, + { key = { Char = "4" }, modifiers = "ALT", action = { SelectTab = 3 } }, + { key = { Char = "5" }, modifiers = "ALT", action = { SelectTab = 4 } }, ] ``` diff --git a/src/config/keybinding.rs b/src/config/keybinding.rs index 73334e7..c0c453a 100644 --- a/src/config/keybinding.rs +++ b/src/config/keybinding.rs @@ -36,6 +36,16 @@ impl Keybinding { Action::TabLeft, ), (event(KeyCode::Tab), Action::TabRight), + // F1-F5 jump straight to a tab by position, regardless of how + // many tabs are actually configured - SelectTab already + // silently no-ops on an out-of-range index (see + // Action::handle), so binding all 5 unconditionally is safe + // even with `tabs` set to fewer than 5 entries. + (event(KeyCode::F(1)), Action::SelectTab(0)), + (event(KeyCode::F(2)), Action::SelectTab(1)), + (event(KeyCode::F(3)), Action::SelectTab(2)), + (event(KeyCode::F(4)), Action::SelectTab(3)), + (event(KeyCode::F(5)), Action::SelectTab(4)), (event(KeyCode::Char('`')), Action::SetAbsoluteVolume(0.00)), (event(KeyCode::Char('1')), Action::SetAbsoluteVolume(0.10)), (event(KeyCode::Char('2')), Action::SetAbsoluteVolume(0.20)), @@ -123,3 +133,22 @@ impl Keybinding { bindings } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn fkey_defaults_select_tabs_by_position() { + let defaults = Keybinding::defaults(); + let event = |code| KeyEvent::new(code, KeyModifiers::NONE); + + for (fkey, tab_index) in [(1, 0), (2, 1), (3, 2), (4, 3), (5, 4)] { + assert_eq!( + defaults.get(&event(KeyCode::F(fkey))), + Some(&Action::SelectTab(tab_index)), + "F{fkey} should default to selecting tab {tab_index}" + ); + } + } +} diff --git a/wiremix.toml b/wiremix.toml index 218653b..ba88a3f 100644 --- a/wiremix.toml +++ b/wiremix.toml @@ -121,9 +121,15 @@ keybindings = [ { key = { Char = "0" }, action = { SetAbsoluteVolume = 1.00 } }, # Open the help menu { key = { Char = "?" }, action = "Help" }, - # There are two actions which don't have default bindings: - # 1. "Nothing": Do nothing - can effectively delete a default keybinding - # 2. { SelectTab = N }: Open the Nth tab + # Select a tab by position (Playback/Recording/Output/Input/Configuration, + # or whatever order/subset `tabs` above is set to) + { key = { F = 1 }, action = { SelectTab = 0 } }, + { key = { F = 2 }, action = { SelectTab = 1 } }, + { key = { F = 3 }, action = { SelectTab = 2 } }, + { key = { F = 4 }, action = { SelectTab = 3 } }, + { key = { F = 5 }, action = { SelectTab = 4 } }, + # "Nothing" is an action with no default binding - it can be used to + # effectively delete a default keybinding by rebinding its key to it ]