Skip to content

Commit 2553fa3

Browse files
committed
Improve key->string conversion
The strings shown for commands like Get-PSReadlineKeyHandler or shown from functions WhatIsKey and ShowKeyBindings should now match what you can use with Set-PSReadlineKeyHandler. These strings will also omit +Shift in most cases because it is usually clear from the character, e.g. the following are equivalent but the former is preferred. Ctrl+? Ctrl+Shift+/
1 parent c0059eb commit 2553fa3

File tree

2 files changed

+24
-41
lines changed

2 files changed

+24
-41
lines changed

PSReadLine/ConsoleKeyChordConverter.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ private static bool TryParseCharLiteral(char literal, ref ConsoleModifiers modif
188188
return valid;
189189
}
190190

191-
private static char GetCharFromConsoleKey(ConsoleKey key, ConsoleModifiers modifiers)
191+
internal static char GetCharFromConsoleKey(ConsoleKey key, ConsoleModifiers modifiers)
192192
{
193193
// default for unprintables and unhandled
194194
char keyChar = '\u0000';
@@ -204,12 +204,11 @@ private static char GetCharFromConsoleKey(ConsoleKey key, ConsoleModifiers modif
204204

205205
// get corresponding scan code
206206
uint scanCode = NativeMethods.MapVirtualKey(virtualKey, NativeMethods.MAPVK_VK_TO_VSC);
207-
Debug.Assert(scanCode != 0, "scanCode != 0");
208207

209208
// get corresponding character - maybe be 0, 1 or 2 in length (diacriticals)
210-
var chars = new StringBuilder();
211-
int charCount = NativeMethods.ToAscii(
212-
virtualKey, scanCode, state, chars, NativeMethods.MENU_IS_INACTIVE);
209+
var chars = new char[2];
210+
int charCount = NativeMethods.ToUnicode(
211+
virtualKey, scanCode, state, chars, chars.Length, NativeMethods.MENU_IS_INACTIVE);
213212

214213
// TODO: support diacriticals (charCount == 2)
215214
if (charCount == 1)

PSReadLine/ConsoleLib.cs

Lines changed: 20 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,9 @@ public static extern bool ScrollConsoleScreenBuffer(IntPtr hConsoleOutput,
5252
[DllImport("user32.dll", SetLastError = true)]
5353
public static extern uint MapVirtualKey(uint uCode, uint uMapType);
5454

55-
[DllImport("user32.dll")]
56-
public static extern int ToAscii(uint uVirtKey, uint uScanCode, byte[] lpKeyState, [Out] StringBuilder lpChar, uint uFlags);
55+
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
56+
public static extern int ToUnicode(uint uVirtKey, uint uScanCode, byte[] lpKeyState,
57+
[MarshalAs(UnmanagedType.LPArray)] [Out] char[] chars, int charMaxCount, uint flags);
5758

5859
[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
5960
public static extern short VkKeyScan(char @char);
@@ -179,6 +180,8 @@ public static class ConsoleKeyInfoExtension
179180
{
180181
public static string ToGestureString(this ConsoleKeyInfo key)
181182
{
183+
var mods = key.Modifiers;
184+
182185
var sb = new StringBuilder();
183186
if (key.Modifiers.HasFlag(ConsoleModifiers.Control))
184187
{
@@ -190,45 +193,26 @@ public static string ToGestureString(this ConsoleKeyInfo key)
190193
sb.Append("+");
191194
sb.Append("Alt");
192195
}
193-
if (key.Modifiers.HasFlag(ConsoleModifiers.Shift))
196+
197+
char c = ConsoleKeyChordConverter.GetCharFromConsoleKey(key.Key,
198+
(mods & ConsoleModifiers.Shift) != 0 ? ConsoleModifiers.Shift : 0);
199+
if (char.IsControl(c) || char.IsWhiteSpace(c))
194200
{
201+
if (key.Modifiers.HasFlag(ConsoleModifiers.Shift))
202+
{
203+
if (sb.Length > 0)
204+
sb.Append("+");
205+
sb.Append("Shift");
206+
}
195207
if (sb.Length > 0)
196208
sb.Append("+");
197-
sb.Append("Shift");
198-
}
199-
if (sb.Length > 0)
200-
sb.Append("+");
201-
if (key.Key >= ConsoleKey.A && key.Key <= ConsoleKey.Z)
202-
{
203-
sb.Append((char)('A' + key.Key - ConsoleKey.A));
204-
}
205-
else if (key.Key >= ConsoleKey.D0 && key.Key <= ConsoleKey.D9)
206-
{
207-
sb.Append((char)('0' + key.Key - ConsoleKey.D0));
208-
}
209-
else if (char.IsLetterOrDigit(key.KeyChar))
210-
{
211-
sb.Append(key.KeyChar);
209+
sb.Append(key.Key);
212210
}
213-
else switch (key.Key)
211+
else
214212
{
215-
case ConsoleKey.Oem1: sb.Append(';'); break;
216-
case ConsoleKey.Oem2: sb.Append('/'); break;
217-
case ConsoleKey.Oem3: sb.Append('`'); break;
218-
case ConsoleKey.Oem4: sb.Append('['); break;
219-
case ConsoleKey.Oem6: sb.Append(']'); break;
220-
case ConsoleKey.Oem7: sb.Append('`'); break;
221-
case ConsoleKey.Oem8: sb.Append('`'); break;
222-
case ConsoleKey.OemComma: sb.Append(','); break;
223-
case ConsoleKey.OemPeriod: sb.Append('.'); break;
224-
case ConsoleKey.OemMinus: sb.Append('-'); break;
225-
case ConsoleKey.OemPlus: sb.Append('+'); break;
226-
//case ConsoleKey.Oem102:
227-
//case ConsoleKey.OemClear:
228-
//case ConsoleKey.Oem5:
229-
default:
230-
sb.Append(key.Key);
231-
break;
213+
if (sb.Length > 0)
214+
sb.Append("+");
215+
sb.Append(c);
232216
}
233217
return sb.ToString();
234218
}

0 commit comments

Comments
 (0)