From 5be7cefc3c6cffb2388eb2873a2b025d8b633e92 Mon Sep 17 00:00:00 2001 From: BDisp Date: Tue, 16 Sep 2025 12:39:10 +0100 Subject: [PATCH] Fix Ctrl being ignored in the range \u0001-\u001a --- .../AnsiResponseParser/Keyboard/EscAsAltPattern.cs | 10 ++++++++-- .../ConsoleDrivers/AnsiKeyboardParserTests.cs | 14 +++++++++++--- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/Terminal.Gui/Drivers/AnsiResponseParser/Keyboard/EscAsAltPattern.cs b/Terminal.Gui/Drivers/AnsiResponseParser/Keyboard/EscAsAltPattern.cs index 1db3e8757..3970a0a5c 100644 --- a/Terminal.Gui/Drivers/AnsiResponseParser/Keyboard/EscAsAltPattern.cs +++ b/Terminal.Gui/Drivers/AnsiResponseParser/Keyboard/EscAsAltPattern.cs @@ -8,7 +8,7 @@ internal class EscAsAltPattern : AnsiKeyboardParserPattern public EscAsAltPattern () { IsLastMinute = true; } #pragma warning disable IDE1006 // Naming Styles - private static readonly Regex _pattern = new (@"^\u001b([a-zA-Z0-9_])$"); + private static readonly Regex _pattern = new (@"^\u001b([\u0001-\u001aa-zA-Z0-9_])$"); #pragma warning restore IDE1006 // Naming Styles public override bool IsMatch (string? input) { return _pattern.IsMatch (input!); } @@ -22,7 +22,13 @@ internal class EscAsAltPattern : AnsiKeyboardParserPattern return null; } - char key = match.Groups [1].Value [0]; + char ch = match.Groups [1].Value [0]; + + Key key = ch switch + { + >= '\u0001' and <= '\u001a' => ((Key)(ch + 96)).WithCtrl, + _ => ch + }; return new Key (key).WithAlt; } diff --git a/Tests/UnitTests/ConsoleDrivers/AnsiKeyboardParserTests.cs b/Tests/UnitTests/ConsoleDrivers/AnsiKeyboardParserTests.cs index 4e178bdc6..759c598ed 100644 --- a/Tests/UnitTests/ConsoleDrivers/AnsiKeyboardParserTests.cs +++ b/Tests/UnitTests/ConsoleDrivers/AnsiKeyboardParserTests.cs @@ -103,16 +103,24 @@ public class AnsiKeyboardParserTests yield return new object [] { "\u001b[1;2P", Key.F1.WithShift }; yield return new object [] { "\u001b[1;3Q", Key.F2.WithAlt }; yield return new object [] { "\u001b[1;5R", Key.F3.WithCtrl }; - + + // Keys with Alt modifiers + yield return new object [] { "\u001ba", Key.A.WithAlt, true }; + yield return new object [] { "\u001bA", Key.A.WithShift.WithAlt, true }; + yield return new object [] { "\u001b1", Key.D1.WithAlt, true }; + + // Keys with Ctrl and Alt modifiers + yield return new object [] { "\u001b\u0001", Key.A.WithCtrl.WithAlt, true }; + yield return new object [] { "\u001b\u001a", Key.Z.WithCtrl.WithAlt, true }; } // Consolidated test for all keyboard events (e.g., arrow keys) [Theory] [MemberData (nameof (GetKeyboardTestData))] - public void ProcessKeyboardInput_ReturnsCorrectKey (string? input, Key? expectedKey) + public void ProcessKeyboardInput_ReturnsCorrectKey (string? input, Key? expectedKey, bool isLastMinute = false) { // Act - Key? result = _parser.IsKeyboard (input)?.GetKey (input); + Key? result = _parser.IsKeyboard (input, isLastMinute)?.GetKey (input); // Assert Assert.Equal (expectedKey, result); // Verify the returned key matches the expected one