Browse Source

Change TryRemapPacketKey to map to `Key` instead of `ConsoleKey`

tznind 2 years ago
parent
commit
0b2bdb04e0
2 changed files with 43 additions and 157 deletions
  1. 34 144
      Terminal.Gui/ConsoleDrivers/WindowsDriver.cs
  2. 9 13
      UnitTests/ConsoleDriverTests.cs

+ 34 - 144
Terminal.Gui/ConsoleDrivers/WindowsDriver.cs

@@ -1244,14 +1244,21 @@ namespace Terminal.Gui {
 				keyModifiers.Scrolllock = scrolllock;
 
 			var ConsoleKeyInfo = new ConsoleKeyInfo (keyEvent.UnicodeChar, (ConsoleKey)keyEvent.wVirtualKeyCode, shift, alt, control);
-
-			ConsoleKeyInfo = RemapPacketKey (ConsoleKeyInfo);
-
+		
 			return new WindowsConsole.ConsoleKeyInfoEx (ConsoleKeyInfo, capslock, numlock);
 		}
 
 		public Key MapKey (WindowsConsole.ConsoleKeyInfoEx keyInfoEx)
 		{
+			// If keystroke is a virtual key
+			if(keyInfoEx.consoleKeyInfo.Key == ConsoleKey.Packet) {
+				
+				// try to map the 'char' that came with it into a Key
+				if(TryRemapPacketKey(keyInfoEx.consoleKeyInfo,out var result)) {
+					return result;
+				}
+			}
+
 			var keyInfo = keyInfoEx.consoleKeyInfo;
 			switch (keyInfo.Key) {
 			case ConsoleKey.Escape:
@@ -1767,157 +1774,40 @@ namespace Terminal.Gui {
 		/// returning a new <see cref="ConsoleKeyInfo"/> where key is remapped
 		/// by parsing the Unicode char data of the <see cref="ConsoleKeyInfo"/>
 		/// </summary>
-		internal static ConsoleKeyInfo RemapPacketKey (ConsoleKeyInfo original)
+		/// <exception cref="ArgumentException">Thrown if passed key was not a <see cref="ConsoleKey.Packet"/></exception>
+		internal static bool TryRemapPacketKey (ConsoleKeyInfo original, out Key result)
 		{
-			if (original.Key != ConsoleKey.Packet)
-				return original;
-
-			// If the key struck was virtual
-			// Try to parse the unicode key e.g. 'A' into a value in ConsoleKey
-			// so that other parts of the program consider it as a regular button
-			// press
-			ConsoleKey remappedkey;
-			if (TryParseConsoleKey (
-				// have to turn e.g. 'a' to something parseable as
-				// an enum value (i.e. Upper it)
-				original.KeyChar.ToString ()?.ToUpper (),
-				out remappedkey)) {
-				return new ConsoleKeyInfo (
-					original.KeyChar,
-					remappedkey,
-					original.Modifiers.HasFlag (ConsoleModifiers.Shift),
-					original.Modifiers.HasFlag (ConsoleModifiers.Alt),
-					original.Modifiers.HasFlag (ConsoleModifiers.Control)
-				);
+			result = default (Key);
+			var c = original.KeyChar;
 
-			}
-
-			return original;
-		}
+			if (original.Key != ConsoleKey.Packet)
+				throw new ArgumentException ("Expected a ConsoleKeyInfo with a Key of Packet",nameof(original));
 
-		private static bool TryParseConsoleKey (string c, out ConsoleKey remappedkey)
-		{
-			if (c == null || c == "\0") {
-				remappedkey = default (ConsoleKey);
+			if (c == '\0') {
 				return false;
 			}
 
-			// if it is a basic letter e.g. A-Z
-			if (Enum.TryParse (c, out remappedkey))
-				return true;
-
 			switch (c) {
-			case "\t":
-				remappedkey = ConsoleKey.Tab;
-				break;
-			case "\u001b":
-				remappedkey = ConsoleKey.Escape;
-				break;
-			case "\b":
-				remappedkey = ConsoleKey.Backspace;
-				break;
-			case "0":
-			case ")":
-				remappedkey = ConsoleKey.D0;
-				break;
-			case "1":
-			case "!":
-				remappedkey = ConsoleKey.D1;
-				break;
-			case "2":
-			case "@": //TODO: this is going to vary according ot keyboard layout, US = @ while UK = "
-				remappedkey = ConsoleKey.D2;
-				break;
-			case "3":
-			case "£": // UK layout has the pound symbol for '#'
-			case "#": // TODO: this is going to be 
-				remappedkey = ConsoleKey.D3;
-				break;
-			case "4":
-			case "$":
-				remappedkey = ConsoleKey.D4;
-				break;
-			case "5":
-			case "%":
-				remappedkey = ConsoleKey.D5;
-				break;
-			case "6":
-			case "^":
-				remappedkey = ConsoleKey.D6;
-				break;
-			case "7":
-			case "&":
-				remappedkey = ConsoleKey.D7;
-				break;
-			case "8":
-			case "*":
-				remappedkey = ConsoleKey.D8;
-				break;
-			case "9":
-			case "(":
-				remappedkey = ConsoleKey.D9;
-				break;
-			case ",":
-			case "<":
-				remappedkey = ConsoleKey.OemComma;
-				break;
-			case "-":
-			case "_":
-				remappedkey = ConsoleKey.OemMinus;
-				break;
-			case ".":
-			case ">":
-				remappedkey = ConsoleKey.OemPeriod;
-				break;
-			case "+":
-			case "=":
-				remappedkey = ConsoleKey.OemPlus;
-				break;
-			case " ":
-				remappedkey = ConsoleKey.Spacebar;
-				break;
-			case ":":
-			case ";":
-				remappedkey = ConsoleKey.Oem1;
-				break;
-			case "/":
-			case "?":
-				remappedkey = ConsoleKey.Oem2;
-				break;
-			case "~":
-			case "`":
-				remappedkey = ConsoleKey.Oem3;
-				break;
-			case "[":
-			case "{":
-				remappedkey = ConsoleKey.Oem3;
-				break;
-			case "|":
-			case "\\":
-				remappedkey = ConsoleKey.Oem5;
-				break;
-			case "}":
-			case "]":
-				remappedkey = ConsoleKey.Oem6;
-				break;
-			case "\"":
-			case "'":
-				remappedkey = ConsoleKey.Oem7;
-				break;
-
-			/*TODO: I'm guessing that this is not right*/
-			case "\n":
-			case "\r":
-				remappedkey = ConsoleKey.Enter;
-				break;
+			case '\t':
+				result = original.Modifiers == ConsoleModifiers.Shift ? Key.BackTab : Key.Tab;
+				return true;
+			case '\u001b':
+				result = Key.Esc;
+				return true;
+			case '\b':
+				result = Key.Backspace;
+				return true;
+			case '\n':
+			case '\r':
+				result = Key.Enter;
+				return true;
 
-			// do not have a 
+			// do not have a explicit mapping and char is nonzero so 
+			// we can just treat the `Key` as a regular unicode entry
 			default:
-				remappedkey = default (ConsoleKey);
-				return false;
+				result = (Key)c;
+				return true;
 			};
-
-			return true;
 		}
 		#endregion
 	}

+ 9 - 13
UnitTests/ConsoleDriverTests.cs

@@ -617,24 +617,20 @@ namespace Terminal.Gui.ConsoleDrivers {
 		/// see: https://github.com/gui-cs/Terminal.Gui/issues/2008
 		/// </summary>
 		[Theory]
-		[InlineData('A',true,false,false,ConsoleKey.A)]
-		[InlineData('z',false,false,false,ConsoleKey.Z)]
-		[InlineData (' ', false, false, false, ConsoleKey.Spacebar)]
-		[InlineData ('\b', false, false, false, ConsoleKey.Backspace)]
-		[InlineData ('=', false, false, false, ConsoleKey.OemPlus)]
-		[InlineData ('+', true, false, false, ConsoleKey.OemPlus)]
-		public void TestVKPacket(char unicodeCharacter,bool shift, bool alt, bool control, ConsoleKey expectedRemapping)
+		[InlineData('A',true,false,false,Key.A)]
+		[InlineData('z',false,false,false, Key.z)]
+		[InlineData (' ', false, false, false, Key.Space)]
+		[InlineData ('\b', false, false, false, Key.Backspace)]
+		[InlineData ('=', false, false, false, (Key)'=')]
+		[InlineData ('+', true, false, false, (Key)'+')]
+		public void TestVKPacket(char unicodeCharacter,bool shift, bool alt, bool control, Key expectedRemapping)
 		{
 			var before = new ConsoleKeyInfo(unicodeCharacter,ConsoleKey.Packet,shift,alt,control);
-			var after = WindowsDriver.RemapPacketKey(before);
-
-			Assert.Equal(before.KeyChar, after.KeyChar);
+			Assert.True (WindowsDriver.TryRemapPacketKey (before,out var after));
 
 			// The thing we are really interested in, did we correctly convert
 			// the input ConsoleKey.Packet to the correct physical key
-			Assert.Equal(expectedRemapping,after.Key);
-
-			Assert.Equal(after.Modifiers,before.Modifiers);
+			Assert.Equal(expectedRemapping,after);
 		}
 	}
 }