From 098c3a343a5ff4acba138efa88a1bf78818f420f Mon Sep 17 00:00:00 2001 From: JustAman62 Date: Fri, 28 Feb 2025 21:08:32 +0000 Subject: [PATCH] Support different key bindings to those displayed. Implement vim-style arrow key bindings --- OpenF1.Console/ConsoleLoop.cs | 2 +- .../Extensions/ConsoleKeyExtensions.cs | 10 +++++++--- OpenF1.Console/Input/CursorInputHandler.cs | 7 +++++-- OpenF1.Console/Input/EscapeInputHandler.cs | 16 +++++++++------- OpenF1.Console/Input/IInputHandler.cs | 11 +++++++++++ .../Session/StartSimulatedSessionInputHandler.cs | 8 ++++++-- OpenF1.Console/Input/SwitchPageInputHandler.cs | 11 ++++++++--- 7 files changed, 47 insertions(+), 18 deletions(-) diff --git a/OpenF1.Console/ConsoleLoop.cs b/OpenF1.Console/ConsoleLoop.cs index 3ce27e7..528b886 100644 --- a/OpenF1.Console/ConsoleLoop.cs +++ b/OpenF1.Console/ConsoleLoop.cs @@ -147,7 +147,7 @@ private void UpdateInputFooter(Layout layout) var commandDescriptions = inputHandlers .Where(x => x.IsEnabled && x.ApplicableScreens.Contains(state.CurrentScreen)) .OrderBy(x => x.Sort) - .Select(x => $"[{x.Keys.ToDisplayCharacters()}] {x.Description}"); + .Select(x => $"[{x.DisplayKeys.ToDisplayCharacters()}] {x.Description}"); var columns = new Columns(commandDescriptions.Select(x => new Text(x))); columns.Collapse(); diff --git a/OpenF1.Console/Extensions/ConsoleKeyExtensions.cs b/OpenF1.Console/Extensions/ConsoleKeyExtensions.cs index 07ce05a..2d373ed 100644 --- a/OpenF1.Console/Extensions/ConsoleKeyExtensions.cs +++ b/OpenF1.Console/Extensions/ConsoleKeyExtensions.cs @@ -2,6 +2,11 @@ namespace OpenF1.Console; public static class ConsoleKeyExtensions { + private static readonly ConsoleKey[] _hiddenKeys = + [ + (ConsoleKey)3, // ^C + ]; + public static string GetConsoleKeyDisplayCharacter(this ConsoleKey key) => key switch { @@ -14,13 +19,12 @@ public static string GetConsoleKeyDisplayCharacter(this ConsoleKey key) => ConsoleKey.OemComma => ",", ConsoleKey.OemPeriod => ".", ConsoleKey.Enter => "⏎", - _ => key.ToString() + _ => key.ToString(), }; public static string ToDisplayCharacters(this ConsoleKey[] keys) { - var characters = keys.Where(x => x != (ConsoleKey)3) // Remove the ^C key code - .Select(x => x.GetConsoleKeyDisplayCharacter()); + var characters = keys.Except(_hiddenKeys).Select(GetConsoleKeyDisplayCharacter); return string.Join('/', characters); } } diff --git a/OpenF1.Console/Input/CursorInputHandler.cs b/OpenF1.Console/Input/CursorInputHandler.cs index 41de3d6..889f1d9 100644 --- a/OpenF1.Console/Input/CursorInputHandler.cs +++ b/OpenF1.Console/Input/CursorInputHandler.cs @@ -6,7 +6,10 @@ public sealed class CursorInputHandler(State state) : IInputHandler public Screen[] ApplicableScreens => Enum.GetValues(); - public ConsoleKey[] Keys => [ConsoleKey.UpArrow, ConsoleKey.DownArrow]; + public ConsoleKey[] Keys => + [ConsoleKey.UpArrow, ConsoleKey.DownArrow, ConsoleKey.J, ConsoleKey.K]; + + public ConsoleKey[] DisplayKeys => [ConsoleKey.UpArrow, ConsoleKey.DownArrow]; public string Description => $"Cursor {state.CursorOffset}"; @@ -17,7 +20,7 @@ public Task ExecuteAsync( CancellationToken cancellationToken = default ) { - var changeBy = consoleKeyInfo.Key == ConsoleKey.DownArrow ? 1 : -1; + var changeBy = consoleKeyInfo.Key is ConsoleKey.DownArrow or ConsoleKey.J ? 1 : -1; if (consoleKeyInfo.Modifiers.HasFlag(ConsoleModifiers.Shift)) { changeBy *= 5; diff --git a/OpenF1.Console/Input/EscapeInputHandler.cs b/OpenF1.Console/Input/EscapeInputHandler.cs index 379bdfd..f726f4d 100644 --- a/OpenF1.Console/Input/EscapeInputHandler.cs +++ b/OpenF1.Console/Input/EscapeInputHandler.cs @@ -7,18 +7,20 @@ public class EscapeInputHandler(State state) : IInputHandler public Screen[] ApplicableScreens => Enum.GetValues(); public ConsoleKey[] Keys => - [ - state.CurrentScreen == Screen.Main ? ConsoleKey.X : ConsoleKey.Escape, - (ConsoleKey)3 // Key Code for Control+C - ]; + state.CurrentScreen == Screen.Main + ? [ConsoleKey.Q, ConsoleKey.X, (ConsoleKey)3] + : [ConsoleKey.Escape, (ConsoleKey)3]; + + public ConsoleKey[] DisplayKeys => + [state.CurrentScreen == Screen.Main ? ConsoleKey.Q : ConsoleKey.Escape]; public int Sort => 1; public string Description => state.CurrentScreen switch { - Screen.Main => "Exit", - _ => "Return" + Screen.Main => "Quit", + _ => "Back", }; public Task ExecuteAsync( @@ -30,7 +32,7 @@ public Task ExecuteAsync( { Screen.Main => Screen.Shutdown, Screen.StartSimulatedSession => Screen.ManageSession, - _ => Screen.Main + _ => Screen.Main, }; return Task.CompletedTask; diff --git a/OpenF1.Console/Input/IInputHandler.cs b/OpenF1.Console/Input/IInputHandler.cs index 1b12c95..cd9366c 100644 --- a/OpenF1.Console/Input/IInputHandler.cs +++ b/OpenF1.Console/Input/IInputHandler.cs @@ -6,8 +6,19 @@ public interface IInputHandler Screen[] ApplicableScreens { get; } + /// + /// Which keys will activate this input handler. + /// ConsoleKey[] Keys { get; } + /// + /// The keys to display to the user that would activate this input handler. + // Defaults to . Use this to have keys which will activate + // this handler without showing the user that those work will work. + // For example, for alternate bindings (e.g. HJKL instead of arrow keys). + /// + ConsoleKey[] DisplayKeys => Keys; + string Description { get; } /// diff --git a/OpenF1.Console/Input/Session/StartSimulatedSessionInputHandler.cs b/OpenF1.Console/Input/Session/StartSimulatedSessionInputHandler.cs index 33d35fe..e5d29ae 100644 --- a/OpenF1.Console/Input/Session/StartSimulatedSessionInputHandler.cs +++ b/OpenF1.Console/Input/Session/StartSimulatedSessionInputHandler.cs @@ -12,7 +12,9 @@ State state public Screen[] ApplicableScreens => [Screen.StartSimulatedSession]; - public ConsoleKey[] Keys => [ConsoleKey.Enter, ConsoleKey.RightArrow]; + public ConsoleKey[] Keys => [ConsoleKey.Enter, ConsoleKey.RightArrow, ConsoleKey.L]; + + public ConsoleKey[] DisplayKeys => [ConsoleKey.RightArrow]; public string Description => "Select"; @@ -56,7 +58,9 @@ State state public Screen[] ApplicableScreens => [Screen.StartSimulatedSession]; - public ConsoleKey[] Keys => [ConsoleKey.LeftArrow]; + public ConsoleKey[] Keys => [ConsoleKey.LeftArrow, ConsoleKey.H]; + + public ConsoleKey[] DisplayKeys => [ConsoleKey.LeftArrow]; public string Description => "Deselect"; diff --git a/OpenF1.Console/Input/SwitchPageInputHandler.cs b/OpenF1.Console/Input/SwitchPageInputHandler.cs index e3b7af8..ecde17e 100644 --- a/OpenF1.Console/Input/SwitchPageInputHandler.cs +++ b/OpenF1.Console/Input/SwitchPageInputHandler.cs @@ -15,10 +15,13 @@ public class SwitchPageInputHandler(LapCountProcessor lapCountProcessor, State s Screen.TimingTower, Screen.TimingHistory, Screen.TyreStints, - Screen.ChampionshipStats + Screen.ChampionshipStats, ]; - public ConsoleKey[] Keys => [ConsoleKey.LeftArrow, ConsoleKey.RightArrow]; + public ConsoleKey[] Keys => + [ConsoleKey.LeftArrow, ConsoleKey.H, ConsoleKey.RightArrow, ConsoleKey.L]; + + public ConsoleKey[] DisplayKeys => [ConsoleKey.LeftArrow, ConsoleKey.RightArrow]; public string Description => $"Page {GetScreenIndex() + 1}"; @@ -33,7 +36,9 @@ public async Task ExecuteAsync( // Find the index of the current screen, and move to the next one var index = GetScreenIndex(); - var newIndex = consoleKeyInfo.Key == ConsoleKey.LeftArrow ? index - 1 : index + 1; + var newIndex = consoleKeyInfo.Key is ConsoleKey.LeftArrow or ConsoleKey.H + ? index - 1 + : index + 1; var newScreen = newIndex % ApplicableScreens.Length; state.CurrentScreen = newScreen < 0 ? ApplicableScreens.Last() : ApplicableScreens[newScreen];