How to get char for keystroke, knowing only enumeration and ConsoleKey modifiers?

I want to instantiate the ConsoleKeyInfocorresponding closing brace of any open curly brace entered in a PowerShell session (I use PSReadline to do key processing). For your convenience, the properties of all the keys involved are listed here.

PS> while($true){ [System.Console]::ReadKey($true) }

    KeyChar     Key    Modifiers
    -------     ---    ---------
          [    Oem4            0
          ]    Oem6            0  
          {    Oem4        Shift
          }    Oem6        Shift

In the key handler, it is assigned ConsoleKeyInfoto me for a "chord" that was pressed (and PSReadline does the filtering, so I already know that I get only Oem4or Shift+Oem4). I want to generate a match ConsoleKeyInfoso that I can send a pair to the console.

The constructor accepts ConsoleKeyInfo

  • a char
  • a System.ConsoleKey
  • a boolfor Shift, Alt and Control

ConsoleKey, int ...

PS> [System.ConsoleKey]([int]$key.Key + 2)
Oem6

Modifiers ...

PS> ($key.Modifiers -band [System.ConsoleModifiers]::Shift) -ne 0
False

, char . char ? /?

, "" char.: (

+4
3

, , ConsoleKeyInfo PSReadline.

ConsoleKeyInfo PSConsoleReadLine, PSConsoleReadLine, ConsoleKeyInfo, . Nullable.

. JaredPar , ConsoleKey/ConsoleModifiers char. ( PSReadline ), , , PSReadline:

internal static char GetCharFromConsoleKey(ConsoleKey key, ConsoleModifiers modifiers)
{
    // default for unprintables and unhandled
    char keyChar = '\u0000';

    // emulate GetKeyboardState bitmap - set high order bit for relevant modifier virtual keys
    var state = new byte[256];
    state[NativeMethods.VK_SHIFT] = (byte)(((modifiers & ConsoleModifiers.Shift) != 0) ? 0x80 : 0);
    state[NativeMethods.VK_CONTROL] = (byte)(((modifiers & ConsoleModifiers.Control) != 0) ? 0x80 : 0);
    state[NativeMethods.VK_ALT] = (byte)(((modifiers & ConsoleModifiers.Alt) != 0) ? 0x80 : 0);

    // a ConsoleKey enum value is a virtual key code
    uint virtualKey = (uint)key;

    // get corresponding scan code
    uint scanCode = NativeMethods.MapVirtualKey(virtualKey, NativeMethods.MAPVK_VK_TO_VSC);

    // get corresponding character  - maybe be 0, 1 or 2 in length (diacriticals)
    var chars = new char[2];
    int charCount = NativeMethods.ToUnicode(
        virtualKey, scanCode, state, chars, chars.Length, NativeMethods.MENU_IS_INACTIVE);

    // TODO: support diacriticals (charCount == 2)
    if (charCount == 1)
    {
        keyChar = chars[0];
    }

    return keyChar;
}
+5

, . , + = . , + = . 1, . , , , ,

,

http://www.siao2.com/2006/04/13/575500.aspx

+3

, , - :

Set-PSReadlineKeyHandler -Chord "Ctrl+'","Ctrl+Shift+'" `
                         -BriefDescription SmartInsertQuote `
                         -Description "Insert paired quotes if not already on a quote" `
                         -ScriptBlock {
    param($key, $arg)

    $line = $null
    $cursor = $null
    [PSConsoleUtilities.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)

    $keyChar = $key.KeyChar
    if ($key.Key -eq 'Oem7') {
        if ($key.Modifiers -eq 'Control') {
            $keyChar = "`'"
        }
        elseif ($key.Modifiers -eq 'Shift','Control') {
            $keyChar = '"'
        }
    }

    if ($line[$cursor] -eq $keyChar) {
        # Just move the cursor
        [PSConsoleUtilities.PSConsoleReadLine]::SetCursorPosition($cursor + 1)
    }
    else {
        # Insert matching quotes, move cursor to be in between the quotes
        [PSConsoleUtilities.PSConsoleReadLine]::Insert("$keyChar" * 2)
        [PSConsoleUtilities.PSConsoleReadLine]::GetBufferState([ref]$line, [ref]$cursor)
        [PSConsoleUtilities.PSConsoleReadLine]::SetCursorPosition($cursor - 1)
    }
}

AFAIK, , , .: -)

+3
source

Source: https://habr.com/ru/post/1529026/


All Articles