public override KeyInfo ReadKey(ReadKeyOptions options) { if (this.externalRawUI == null) { this.ThrowNotInteractive(); } KeyInfo info = new KeyInfo(); try { info = this.externalRawUI.ReadKey(options); } catch (PipelineStoppedException) { LocalPipeline currentlyRunningPipeline = (LocalPipeline) ((RunspaceBase) this.parentHost.Context.CurrentRunspace).GetCurrentlyRunningPipeline(); if (currentlyRunningPipeline == null) { throw; } currentlyRunningPipeline.Stopper.Stop(); } return info; }
ReadKey(ReadKeyOptions options) { if (_externalRawUI == null) { ThrowNotInteractive(); } KeyInfo result = new KeyInfo(); try { result = _externalRawUI.ReadKey(options); } catch (PipelineStoppedException) { //PipelineStoppedException is thrown by host when it wants //to stop the pipeline. LocalPipeline lpl = (LocalPipeline)((RunspaceBase)_parentHost.Context.CurrentRunspace).GetCurrentlyRunningPipeline(); if (lpl == null) { throw; } lpl.Stopper.Stop(); } return result; }
KEY_EVENT_RECORDToKeyInfo(ConsoleControl.KEY_EVENT_RECORD keyEventRecord, out KeyInfo keyInfo) { keyInfo = new KeyInfo( keyEventRecord.VirtualKeyCode, keyEventRecord.UnicodeChar, (ControlKeyStates)keyEventRecord.ControlKeyState, keyEventRecord.KeyDown); }
/// <summary> /// Thread method invoked from <see cref="ReadKey"/> that waits for the user to press a key. /// </summary> /// <param name="state"><see cref="Tuple{T1, T2}"/> object containing a <see cref="StreamConnection"/> object and a <see cref="ReadKeyOptions"/> /// object.</param> private void ReadInput(object state) { StreamConnection connection = (state as Tuple<StreamConnection, ReadKeyOptions>).Item1; ReadKeyOptions options = (state as Tuple<StreamConnection, ReadKeyOptions>).Item2; bool inEscapeSequence = false; bool readKey = false; while (!readKey) { if (connection.OutputQueue.Count > 0) { while (connection.OutputQueue.Count > 0) { byte currentByte = connection.OutputQueue.Dequeue(); // Handle the backspace key if (currentByte == 8) { _readKey = new KeyInfo { VirtualKeyCode = 8 }; // If we're not already at the beginning of the line and we're echoing the output, move the cursor left if ((options & ReadKeyOptions.NoEcho) != ReadKeyOptions.NoEcho && CursorPosition.X > 1) CursorPosition = new Coordinates(CursorPosition.X - 1, CursorPosition.Y); readKey = true; break; } // The ^X character signifies the start of an ANSI escape sequence else if (currentByte == 27) inEscapeSequence = true; // If we're in an escape sequence, read past the "[" and "~" characters else if (currentByte == 91 && inEscapeSequence) { } else if (currentByte == 126 && inEscapeSequence) { } // ^X7 is the home key else if (currentByte == 55 && inEscapeSequence) { _readKey = new KeyInfo { VirtualKeyCode = 0x24 }; // If we're not already at the beginning of the line and we're echoing the output, move the cursor to the start of the line if ((options & ReadKeyOptions.NoEcho) != ReadKeyOptions.NoEcho) CursorPosition = new Coordinates(1, CursorPosition.Y); readKey = true; break; } // ^X8 or ^X3 is the end key else if ((currentByte == 56 || currentByte == 51) && inEscapeSequence) { _readKey = new KeyInfo { VirtualKeyCode = 0x23 }; // If we're not already at the beginning of the line and we're echoing the output, move the cursor to the end of the line if ((options & ReadKeyOptions.NoEcho) != ReadKeyOptions.NoEcho) CursorPosition = new Coordinates(BufferSize.Width, CursorPosition.Y); readKey = true; break; } // ^XD is the left arrow else if (currentByte == 68 && inEscapeSequence) { _readKey = new KeyInfo { VirtualKeyCode = 0x25 }; // If we're not already at the beginning of the line and we're echoing the output, move the cursor left if ((options & ReadKeyOptions.NoEcho) != ReadKeyOptions.NoEcho && CursorPosition.X > 1) CursorPosition = new Coordinates(CursorPosition.X - 1, CursorPosition.Y); readKey = true; break; } // ^XC is the right arrow else if (currentByte == 67 && inEscapeSequence) { _readKey = new KeyInfo { VirtualKeyCode = 0x27 }; // If we're not already at the beginning of the line and we're echoing the output, move the cursor right if ((options & ReadKeyOptions.NoEcho) != ReadKeyOptions.NoEcho && CursorPosition.X < BufferSize.Width) CursorPosition = new Coordinates(CursorPosition.X + 1, CursorPosition.Y); readKey = true; break; } // Handle the carriage return sequence else if (currentByte == 13) { _readKey = new KeyInfo { Character = '\r', VirtualKeyCode = 0x0D }; if ((options & ReadKeyOptions.NoEcho) != ReadKeyOptions.NoEcho) CursorPosition = new Coordinates(1, CursorPosition.Y); readKey = true; break; } // Otherwise, get the virtual key code and character and populate _readKey else { short virtualKey = User32.VkKeyScan((char) currentByte); int modifiers = virtualKey >> 8; ControlKeyStates controlKeys = 0; if ((modifiers & 2) != 0) controlKeys |= ControlKeyStates.LeftCtrlPressed; if ((modifiers & 4) != 0) controlKeys |= ControlKeyStates.LeftAltPressed; _readKey = new KeyInfo { Character = (char) currentByte, VirtualKeyCode = (virtualKey & 0xFF), ControlKeyState = controlKeys }; if ((options & ReadKeyOptions.NoEcho) != ReadKeyOptions.NoEcho) { _terminal.TerminalPane.ConnectionTag.Receiver.DataArrived( new byte[] { currentByte }, 0, 1); } readKey = true; break; } } } // If we didn't read a key, sleep for a bit if (!readKey) Thread.Sleep(50); } // Signal to ReadKey() that we've read a key _inputSemaphore.Set(); }