private static void WriteBlankLines(int count, int top) { var blanks = new CHAR_INFO[count * Console.BufferWidth]; for (int i = 0; i < blanks.Length; i++) { blanks[i].BackgroundColor = Console.BackgroundColor; blanks[i].ForegroundColor = Console.ForegroundColor; blanks[i].UnicodeChar = ' '; } WriteBufferLines(blanks, ref top); }
/// <summary> /// Turn on demo mode (display events like keys pressed) /// </summary> public static void EnableDemoMode(ConsoleKeyInfo? key = null, object arg = null) { const int windowLineCount = 4; // 1 blank line, 2 border lines, 1 line of info _singleton._captureKeys = true; _singleton._demoMode = true; _singleton._demoWindowLineCount = windowLineCount; var newBuffer = new CHAR_INFO[_singleton._consoleBuffer.Length + (windowLineCount * _singleton._bufferWidth)]; Array.Copy(_singleton._consoleBuffer, newBuffer, _singleton._initialX + (_singleton.Options.ExtraPromptLineCount * _singleton._bufferWidth)); _singleton._consoleBuffer = newBuffer; _singleton.Render(); }
private static void ScrollBuffer(int lines) { var handle = NativeMethods.GetStdHandle((uint) StandardHandleId.Output); var scrollRectangle = new SMALL_RECT { Top = (short) lines, Left = 0, Bottom = (short) (Console.BufferHeight - 1), Right = (short)Console.BufferWidth }; var destinationOrigin = new COORD {X = 0, Y = 0}; var fillChar = new CHAR_INFO(' ', Console.ForegroundColor, Console.BackgroundColor); NativeMethods.ScrollConsoleScreenBuffer(handle, ref scrollRectangle, IntPtr.Zero, destinationOrigin, ref fillChar); }
private void ClearDemoWindow() { int bufferWidth = Console.BufferWidth; var charInfoBuffer = new CHAR_INFO[bufferWidth * 3]; for (int i = 0; i < charInfoBuffer.Length; i++) { charInfoBuffer[i].UnicodeChar = ' '; charInfoBuffer[i].ForegroundColor = _initialForegroundColor; charInfoBuffer[i].BackgroundColor= _initialBackgroundColor; } int bufferLineCount = ConvertOffsetToCoordinates(_buffer.Length).Y - _initialY + 1; int y = _initialY + bufferLineCount + 1; WriteBufferLines(charInfoBuffer, ref y); }
private void InteractiveHistorySearch(int direction) { SaveCurrentLine(); // Add a status line that will contain the search prompt and string _statusLinePrompt = direction > 0 ? _forwardISearchPrompt : _backwardISearchPrompt; _statusBuffer.Append("_"); Render(); // Render prompt InteractiveHistorySearchLoop(direction); // Remove our status line _statusBuffer.Clear(); _statusLinePrompt = null; _emphasisStart = -1; _emphasisLength = 0; #if FALSE int promptStart = _bufferWidth * Options.ExtraPromptLineCount; int promptWidth = _initialX; // Copy the prompt (ignoring the possible extra lines which we'll leave alone) var savedPrompt = new CHAR_INFO[promptWidth]; Array.Copy(_consoleBuffer, promptStart, savedPrompt, 0, promptWidth); string newPrompt = "(reverse-i-search)`': "; _initialX = newPrompt.Length; int i, j; for (i = promptStart, j = 0; j < newPrompt.Length; i++, j++) { _consoleBuffer[i].UnicodeChar = newPrompt[j]; _consoleBuffer[i].BackgroundColor = Console.BackgroundColor; _consoleBuffer[i].ForegroundColor = Console.ForegroundColor; } InteractiveHistorySearchLoop(direction); // Restore the original prompt _initialX = promptWidth; Array.Copy(savedPrompt, 0, _consoleBuffer, promptStart, savedPrompt.Length); #endif Render(); }
private static CHAR_INFO[] ReadBufferLines(int top, int count) { var result = new CHAR_INFO[Console.BufferWidth * count]; var handle = NativeMethods.GetStdHandle((uint) StandardHandleId.Output); var readBufferSize = new COORD { X = (short)Console.BufferWidth, Y = (short)count}; var readBufferCoord = new COORD {X = 0, Y = 0}; var readRegion = new SMALL_RECT { Top = (short)top, Left = 0, Bottom = (short)(top + count), Right = (short)(Console.BufferWidth - 1) }; NativeMethods.ReadConsoleOutput(handle, result, readBufferSize, readBufferCoord, ref readRegion); return result; }
private void MaybeEmphasize(ref CHAR_INFO charInfo, int i, ConsoleColor foregroundColor, ConsoleColor backgroundColor) { if (i >= _emphasisStart && i < (_emphasisStart + _emphasisLength)) { backgroundColor = _options.EmphasisBackgroundColor; foregroundColor = _options.EmphasisForegroundColor; } else if (_visualSelectionCommandCount > 0 && InRegion(i)) { // We can't quite emulate real console selection because it inverts // based on actual screen colors, our pallete is limited. The choice // to invert only the lower 3 bits to change the color is somewhat // but looks best with the 2 default color schemes - starting PowerShell // from it's shortcut or from a cmd shortcut. foregroundColor = (ConsoleColor)((int)foregroundColor ^ 7); backgroundColor = (ConsoleColor)((int)backgroundColor ^ 7); } charInfo.ForegroundColor = foregroundColor; charInfo.BackgroundColor = backgroundColor; }
private void Initialize() { _buffer.Clear(); _edits = new List <EditItem>(); _undoEditIndex = 0; _editGroupCount = 0; _pushedEditGroupCount.Clear(); _current = 0; _mark = 0; _emphasisStart = -1; _emphasisLength = 0; _tokens = null; _parseErrors = null; _inputAccepted = false; _initialX = Console.CursorLeft; _initialY = Console.CursorTop - Options.ExtraPromptLineCount; _initialBackgroundColor = Console.BackgroundColor; _initialForegroundColor = Console.ForegroundColor; _space = new CHAR_INFO(' ', _initialForegroundColor, _initialBackgroundColor); _bufferWidth = Console.BufferWidth; _killCommandCount = 0; _yankCommandCount = 0; _yankLastArgCommandCount = 0; _tabCommandCount = 0; _visualSelectionCommandCount = 0; _consoleBuffer = ReadBufferLines(_initialY, 1 + Options.ExtraPromptLineCount); _lastRenderTime = Stopwatch.StartNew(); if (_getNextHistoryIndex > 0) { _currentHistoryIndex = _getNextHistoryIndex; UpdateFromHistory(moveCursor: true); _getNextHistoryIndex = 0; } }
public static extern bool ScrollConsoleScreenBuffer(IntPtr hConsoleOutput, ref SMALL_RECT lpScrollRectangle, ref SMALL_RECT lpClipRectangle, COORD dwDestinationOrigin, ref CHAR_INFO lpFill);
public static extern bool WriteConsoleOutput(IntPtr consoleOutput, CHAR_INFO[] buffer, COORD bufferSize, COORD bufferCoord, ref SMALL_RECT writeRegion);
private static void InvertSelectedCompletion(CHAR_INFO[] buffer, int selectedItem, int menuColumnWidth, int menuRows) { var selectedX = selectedItem / menuRows; var selectedY = selectedItem - (selectedX * menuRows); var start = selectedY * Console.BufferWidth + selectedX * menuColumnWidth; for (int i = 0; i < menuColumnWidth; i++) { int j = i + start; buffer[j].ForegroundColor = (ConsoleColor)((int)buffer[j].ForegroundColor ^ 7); buffer[j].BackgroundColor = (ConsoleColor)((int)buffer[j].BackgroundColor ^ 7); } }
private void ReallyRender() { _renderForDemoNeeded = false; var text = ParseInput(); int statusLineCount = GetStatusLineCount(); int bufferLineCount = ConvertOffsetToCoordinates(text.Length).Y - _initialY + 1 + _demoWindowLineCount + statusLineCount; int bufferWidth = Console.BufferWidth; if (_consoleBuffer.Length != bufferLineCount * bufferWidth) { var newBuffer = new CHAR_INFO[bufferLineCount * bufferWidth]; Array.Copy(_consoleBuffer, newBuffer, _initialX + (Options.ExtraPromptLineCount * _bufferWidth)); if (_consoleBuffer.Length > bufferLineCount * bufferWidth) { // Need to erase the extra lines that we won't draw again for (int i = bufferLineCount * bufferWidth; i < _consoleBuffer.Length; i++) { _consoleBuffer[i] = _space; } WriteBufferLines(_consoleBuffer, ref _initialY); } _consoleBuffer = newBuffer; } var tokenStack = new Stack <SavedTokenState>(); tokenStack.Push(new SavedTokenState { Tokens = _tokens, Index = 0, BackgroundColor = _initialBackgroundColor, ForegroundColor = _initialForegroundColor }); int j = _initialX + (_bufferWidth * Options.ExtraPromptLineCount); var backgroundColor = _initialBackgroundColor; var foregroundColor = _initialForegroundColor; for (int i = 0; i < text.Length; i++) { // Figure out the color of the character - if it's in a token, // use the tokens color otherwise use the initial color. var state = tokenStack.Peek(); var token = state.Tokens[state.Index]; if (i == token.Extent.EndOffset) { if (token == state.Tokens[state.Tokens.Length - 1]) { tokenStack.Pop(); state = tokenStack.Peek(); } foregroundColor = state.ForegroundColor; backgroundColor = state.BackgroundColor; token = state.Tokens[++state.Index]; } if (i == token.Extent.StartOffset) { GetTokenColors(token, out foregroundColor, out backgroundColor); var stringToken = token as StringExpandableToken; if (stringToken != null) { // We might have nested tokens. if (stringToken.NestedTokens != null && stringToken.NestedTokens.Any()) { var tokens = new Token[stringToken.NestedTokens.Count + 1]; stringToken.NestedTokens.CopyTo(tokens, 0); // NestedTokens doesn't have an "EOS" token, so we use // the string literal token for that purpose. tokens[tokens.Length - 1] = stringToken; tokenStack.Push(new SavedTokenState { Tokens = tokens, Index = 0, BackgroundColor = backgroundColor, ForegroundColor = foregroundColor }); } } } if (text[i] == '\n') { while ((j % bufferWidth) != 0) { _consoleBuffer[j++] = _space; } for (int k = 0; k < Options.ContinuationPrompt.Length; k++, j++) { _consoleBuffer[j].UnicodeChar = Options.ContinuationPrompt[k]; _consoleBuffer[j].ForegroundColor = Options.ContinuationPromptForegroundColor; _consoleBuffer[j].BackgroundColor = Options.ContinuationPromptBackgroundColor; } } else if (char.IsControl(text[i])) { _consoleBuffer[j].UnicodeChar = '^'; MaybeEmphasize(ref _consoleBuffer[j++], i, foregroundColor, backgroundColor); _consoleBuffer[j].UnicodeChar = (char)('@' + text[i]); MaybeEmphasize(ref _consoleBuffer[j++], i, foregroundColor, backgroundColor); } else { _consoleBuffer[j].UnicodeChar = text[i]; MaybeEmphasize(ref _consoleBuffer[j++], i, foregroundColor, backgroundColor); } } for (; j < (_consoleBuffer.Length - ((statusLineCount + _demoWindowLineCount) * _bufferWidth)); j++) { _consoleBuffer[j] = _space; } if (_statusLinePrompt != null) { for (int i = 0; i < _statusLinePrompt.Length; i++, j++) { _consoleBuffer[j].UnicodeChar = _statusLinePrompt[i]; _consoleBuffer[j].ForegroundColor = Console.ForegroundColor; _consoleBuffer[j].BackgroundColor = Console.BackgroundColor; } for (int i = 0; i < _statusBuffer.Length; i++, j++) { _consoleBuffer[j].UnicodeChar = _statusBuffer[i]; _consoleBuffer[j].ForegroundColor = Console.ForegroundColor; _consoleBuffer[j].BackgroundColor = Console.BackgroundColor; } for (; j < (_consoleBuffer.Length - (_demoWindowLineCount * _bufferWidth)); j++) { _consoleBuffer[j] = _space; } } if (_demoMode) { RenderDemoWindow(j); } bool rendered = false; if (_parseErrors.Length > 0) { int promptChar = _initialX - 1 + (_bufferWidth * Options.ExtraPromptLineCount); while (promptChar >= 0) { if (char.IsSymbol((char)_consoleBuffer[promptChar].UnicodeChar)) { ConsoleColor prevColor = _consoleBuffer[promptChar].ForegroundColor; _consoleBuffer[promptChar].ForegroundColor = ConsoleColor.Red; WriteBufferLines(_consoleBuffer, ref _initialY); rendered = true; _consoleBuffer[promptChar].ForegroundColor = prevColor; break; } promptChar -= 1; } } if (!rendered) { WriteBufferLines(_consoleBuffer, ref _initialY); } PlaceCursor(); if ((_initialY + bufferLineCount + (_demoMode ? 1 : 0)) > (Console.WindowTop + Console.WindowHeight)) { Console.WindowTop = _initialY + bufferLineCount + (_demoMode ? 1 : 0) - Console.WindowHeight; } _lastRenderTime.Restart(); }
private void Initialize(Runspace remoteRunspace) { _buffer.Clear(); _edits = new List<EditItem>(); _undoEditIndex = 0; _editGroupCount = 0; _pushedEditGroupCount.Clear(); _current = 0; _mark = 0; _emphasisStart = -1; _emphasisLength = 0; _tokens = null; _parseErrors = null; _inputAccepted = false; _initialX = Console.CursorLeft; _initialY = Console.CursorTop - Options.ExtraPromptLineCount; _initialBackgroundColor = Console.BackgroundColor; _initialForegroundColor = Console.ForegroundColor; _space = new CHAR_INFO(' ', _initialForegroundColor, _initialBackgroundColor); _bufferWidth = Console.BufferWidth; _killCommandCount = 0; _yankCommandCount = 0; _yankLastArgCommandCount = 0; _tabCommandCount = 0; _visualSelectionCommandCount = 0; _remoteRunspace = remoteRunspace; _consoleBuffer = ReadBufferLines(_initialY, 1 + Options.ExtraPromptLineCount); _lastRenderTime = Stopwatch.StartNew(); _killCommandCount = 0; _yankCommandCount = 0; _yankLastArgCommandCount = 0; _tabCommandCount = 0; _searchHistoryCommandCount = 0; _recallHistoryCommandCount = 0; _visualSelectionCommandCount = 0; _hashedHistory = null; if (_getNextHistoryIndex > 0) { _currentHistoryIndex = _getNextHistoryIndex; UpdateFromHistory(moveCursor: true); _getNextHistoryIndex = 0; } }
private void ReallyRender() { _renderForDemoNeeded = false; var text = ParseInput(); int statusLineCount = GetStatusLineCount(); int bufferLineCount = ConvertOffsetToCoordinates(text.Length).Y - _initialY + 1 + _demoWindowLineCount + statusLineCount; int bufferWidth = Console.BufferWidth; if (_consoleBuffer.Length != bufferLineCount * bufferWidth) { var newBuffer = new CHAR_INFO[bufferLineCount * bufferWidth]; Array.Copy(_consoleBuffer, newBuffer, _initialX + (Options.ExtraPromptLineCount * _bufferWidth)); if (_consoleBuffer.Length > bufferLineCount * bufferWidth) { // Need to erase the extra lines that we won't draw again for (int i = bufferLineCount * bufferWidth; i < _consoleBuffer.Length; i++) { _consoleBuffer[i] = _space; } WriteBufferLines(_consoleBuffer, ref _initialY); } _consoleBuffer = newBuffer; } var tokenStack = new Stack<SavedTokenState>(); tokenStack.Push(new SavedTokenState { Tokens = _tokens, Index = 0, BackgroundColor = _initialBackgroundColor, ForegroundColor = _initialForegroundColor }); int j = _initialX + (_bufferWidth * Options.ExtraPromptLineCount); var backgroundColor = _initialBackgroundColor; var foregroundColor = _initialForegroundColor; for (int i = 0; i < text.Length; i++) { // Figure out the color of the character - if it's in a token, // use the tokens color otherwise use the initial color. var state = tokenStack.Peek(); var token = state.Tokens[state.Index]; if (i == token.Extent.EndOffset) { if (token == state.Tokens[state.Tokens.Length - 1]) { tokenStack.Pop(); state = tokenStack.Peek(); } foregroundColor = state.ForegroundColor; backgroundColor = state.BackgroundColor; token = state.Tokens[++state.Index]; } if (i == token.Extent.StartOffset) { GetTokenColors(token, out foregroundColor, out backgroundColor); var stringToken = token as StringExpandableToken; if (stringToken != null) { // We might have nested tokens. if (stringToken.NestedTokens != null && stringToken.NestedTokens.Any()) { var tokens = new Token[stringToken.NestedTokens.Count + 1]; stringToken.NestedTokens.CopyTo(tokens, 0); // NestedTokens doesn't have an "EOS" token, so we use // the string literal token for that purpose. tokens[tokens.Length - 1] = stringToken; tokenStack.Push(new SavedTokenState { Tokens = tokens, Index = 0, BackgroundColor = backgroundColor, ForegroundColor = foregroundColor }); } } } if (text[i] == '\n') { while ((j % bufferWidth) != 0) { _consoleBuffer[j++] = _space; } for (int k = 0; k < Options.ContinuationPrompt.Length; k++, j++) { _consoleBuffer[j].UnicodeChar = Options.ContinuationPrompt[k]; _consoleBuffer[j].ForegroundColor = Options.ContinuationPromptForegroundColor; _consoleBuffer[j].BackgroundColor = Options.ContinuationPromptBackgroundColor; } } else if (char.IsControl(text[i])) { _consoleBuffer[j].UnicodeChar = '^'; MaybeEmphasize(ref _consoleBuffer[j++], i, foregroundColor, backgroundColor); _consoleBuffer[j].UnicodeChar = (char)('@' + text[i]); MaybeEmphasize(ref _consoleBuffer[j++], i, foregroundColor, backgroundColor); } else { _consoleBuffer[j].UnicodeChar = text[i]; MaybeEmphasize(ref _consoleBuffer[j++], i, foregroundColor, backgroundColor); } } for (; j < (_consoleBuffer.Length - ((statusLineCount + _demoWindowLineCount) * _bufferWidth)); j++) { _consoleBuffer[j] = _space; } if (_statusLinePrompt != null) { for (int i = 0; i < _statusLinePrompt.Length; i++, j++) { _consoleBuffer[j].UnicodeChar = _statusLinePrompt[i]; _consoleBuffer[j].ForegroundColor = Console.ForegroundColor; _consoleBuffer[j].BackgroundColor = Console.BackgroundColor; } for (int i = 0; i < _statusBuffer.Length; i++, j++) { _consoleBuffer[j].UnicodeChar = _statusBuffer[i]; _consoleBuffer[j].ForegroundColor = Console.ForegroundColor; _consoleBuffer[j].BackgroundColor = Console.BackgroundColor; } for (; j < (_consoleBuffer.Length - (_demoWindowLineCount * _bufferWidth)); j++) { _consoleBuffer[j] = _space; } } if (_demoMode) { RenderDemoWindow(j); } bool rendered = false; if (_parseErrors.Length > 0) { int promptChar = _initialX - 1 + (_bufferWidth * Options.ExtraPromptLineCount); while (promptChar >= 0) { if (char.IsSymbol((char)_consoleBuffer[promptChar].UnicodeChar)) { ConsoleColor prevColor = _consoleBuffer[promptChar].ForegroundColor; _consoleBuffer[promptChar].ForegroundColor = ConsoleColor.Red; WriteBufferLines(_consoleBuffer, ref _initialY); rendered = true; _consoleBuffer[promptChar].ForegroundColor = prevColor; break; } promptChar -= 1; } } if (!rendered) { WriteBufferLines(_consoleBuffer, ref _initialY); } PlaceCursor(); if ((_initialY + bufferLineCount + (_demoMode ? 1 : 0)) > (Console.WindowTop + Console.WindowHeight)) { Console.WindowTop = _initialY + bufferLineCount + (_demoMode ? 1 : 0) - Console.WindowHeight; } _lastRenderTime.Restart(); }
private static void WriteBufferLines(CHAR_INFO[] buffer, ref int top) { var handle = NativeMethods.GetStdHandle((uint) StandardHandleId.Output); int bufferWidth = Console.BufferWidth; int bufferLineCount = buffer.Length / bufferWidth; if ((top + bufferLineCount) > Console.BufferHeight) { var scrollCount = (top + bufferLineCount) - Console.BufferHeight; ScrollBuffer(scrollCount); top -= scrollCount; } var bufferSize = new COORD { X = (short) bufferWidth, Y = (short) bufferLineCount }; var bufferCoord = new COORD {X = 0, Y = 0}; var writeRegion = new SMALL_RECT { Top = (short) top, Left = 0, Bottom = (short) (top + bufferLineCount - 1), Right = (short) bufferWidth }; NativeMethods.WriteConsoleOutput(handle, buffer, bufferSize, bufferCoord, ref writeRegion); }
public static extern bool ScrollConsoleScreenBuffer(IntPtr hConsoleOutput, ref SMALL_RECT lpScrollRectangle, IntPtr lpClipRectangle, COORD dwDestinationOrigin, ref CHAR_INFO lpFill);
private static void ScrollBuffer(int lines) { var handle = NativeMethods.GetStdHandle((uint) StandardHandleId.Output); var scrollRectangle = new SMALL_RECT { Top = (short) lines, Left = 0, Bottom = (short) (lines + Console.BufferHeight - 1), Right = (short)Console.BufferWidth }; var destinationOrigin = new COORD {X = 0, Y = 0}; var fillChar = new CHAR_INFO(' ', Console.ForegroundColor, Console.BackgroundColor); NativeMethods.ScrollConsoleScreenBuffer(handle, ref scrollRectangle, IntPtr.Zero, destinationOrigin, ref fillChar); }
private void Initialize(Runspace remoteRunspace, EngineIntrinsics engineIntrinsics) { if (!_delayedOneTimeInitCompleted) { DelayedOneTimeInitialize(); _delayedOneTimeInitCompleted = true; } _engineIntrinsics = engineIntrinsics; _buffer.Clear(); _edits = new List <EditItem>(); _undoEditIndex = 0; _editGroupStart = -1; _current = 0; _mark = 0; _emphasisStart = -1; _emphasisLength = 0; _tokens = null; _parseErrors = null; _inputAccepted = false; _initialX = Console.CursorLeft; _initialY = Console.CursorTop - Options.ExtraPromptLineCount; _initialBackgroundColor = Console.BackgroundColor; _initialForegroundColor = Console.ForegroundColor; _space = new CHAR_INFO(' ', _initialForegroundColor, _initialBackgroundColor); _bufferWidth = Console.BufferWidth; _killCommandCount = 0; _yankCommandCount = 0; _yankLastArgCommandCount = 0; _tabCommandCount = 0; _visualSelectionCommandCount = 0; _remoteRunspace = remoteRunspace; _statusIsErrorMessage = false; _consoleBuffer = ReadBufferLines(_initialY, 1 + Options.ExtraPromptLineCount); _lastRenderTime = Stopwatch.StartNew(); _killCommandCount = 0; _yankCommandCount = 0; _yankLastArgCommandCount = 0; _tabCommandCount = 0; _recallHistoryCommandCount = 0; _visualSelectionCommandCount = 0; _hashedHistory = null; if (_getNextHistoryIndex > 0) { _currentHistoryIndex = _getNextHistoryIndex; UpdateFromHistory(moveCursor: true); _getNextHistoryIndex = 0; if (_searchHistoryCommandCount > 0) { _searchHistoryPrefix = ""; if (Options.HistoryNoDuplicates) { _hashedHistory = new Dictionary <string, int>(); } } } else { _searchHistoryCommandCount = 0; } }
private static void WriteBufferLines(CHAR_INFO[] buffer, ref int top) { var handle = NativeMethods.GetStdHandle((uint) StandardHandleId.Output); int bufferWidth = Console.BufferWidth; int bufferLineCount = buffer.Length / bufferWidth; if ((top + bufferLineCount) > Console.BufferHeight) { var scrollCount = (top + bufferLineCount) - Console.BufferHeight; ScrollBuffer(scrollCount); top -= scrollCount; } var bufferSize = new COORD { X = (short) bufferWidth, Y = (short) bufferLineCount }; var bufferCoord = new COORD {X = 0, Y = 0}; var bottom = top + bufferLineCount - 1; var writeRegion = new SMALL_RECT { Top = (short) top, Left = 0, Bottom = (short) bottom, Right = (short) (bufferWidth - 1) }; NativeMethods.WriteConsoleOutput(handle, buffer, bufferSize, bufferCoord, ref writeRegion); // Now make sure the bottom line is visible if (bottom >= (Console.WindowTop + Console.WindowHeight)) { Console.CursorTop = bottom; } }
static void Box(List<string> list) { int internalBoxWidth = Math.Min(Console.BufferWidth - 2, list.Max(e => e.Length)); int boxWidth = internalBoxWidth + 2; int internalBoxHeight = list.Count; int boxHeight = internalBoxHeight + 2; var buffer = new CHAR_INFO[boxWidth * boxHeight]; buffer[0].UnicodeChar = '+'; buffer[boxWidth - 1].UnicodeChar = '+'; for (int i = 1; i < boxWidth - 1; i++) { buffer[i].UnicodeChar = '-'; } for (int i = 0; i < list.Count; i++) { int rowStart = (i + 1) * boxWidth; buffer[rowStart++].UnicodeChar = '|'; buffer[rowStart + internalBoxWidth].UnicodeChar = '|'; string s = list[i]; int j; for (j = 0; j < s.Length; j++) { buffer[rowStart + j].UnicodeChar = s[j]; } for (; j < internalBoxWidth; j++) { buffer[rowStart + j].UnicodeChar = ' '; } } int lastRowStart = (boxHeight - 1) * boxWidth; buffer[lastRowStart].UnicodeChar = '+'; for (int i = 1; i < boxWidth - 1; i++) { buffer[i + lastRowStart].UnicodeChar = '-'; } buffer[lastRowStart + boxWidth - 1].UnicodeChar = '+'; for (int i = 0; i < buffer.Length; i++) { buffer[i].Attributes = (ushort)ConsoleColor.Blue | ((ushort)(ConsoleColor.DarkGreen) << 4); if (i % 2 != 0) { buffer[i].Attributes |= 0xfff0; } } var handle = NativeMethods.GetStdHandle((uint) StandardHandleId.Output); var bufferSize = new COORD {X = (short)boxWidth, Y = (short)boxHeight}; var bufferCoord = new COORD {X = 0, Y = 0}; var writeRegion = new SMALL_RECT { Top = 1, Left = 1, Bottom = (short)(1 + boxHeight), Right = (short)(1 + boxWidth)}; Console.WriteLine("some random stuff"); Console.WriteLine("and more some random stuff"); Console.WriteLine("lorem ipsum blah blah"); Console.ReadKey(); var saveBuffer = new CHAR_INFO[buffer.Length]; NativeMethods.ReadConsoleOutput(handle, saveBuffer, bufferSize, bufferCoord, ref writeRegion); unsafe { fixed (CHAR_INFO* p = &buffer[0]) fixed (CHAR_INFO* sp = &saveBuffer[0]) { NativeMethods.WriteConsoleOutput(handle, buffer, bufferSize, bufferCoord, ref writeRegion); Console.ReadKey(); NativeMethods.WriteConsoleOutput(handle, saveBuffer, bufferSize, bufferCoord, ref writeRegion); } } Console.ReadKey(); }
private void InteractiveHistorySearch(int direction) { SaveCurrentLine(); // Add a status line that will contain the search prompt and string _statusLinePrompt = direction > 0 ? _forwardISearchPrompt : _backwardISearchPrompt; _statusBuffer.Append("_"); Render(); // Render prompt InteractiveHistorySearchLoop(direction); _hashedHistory = null; // Remove our status line _statusBuffer.Clear(); _statusLinePrompt = null; _emphasisStart = -1; _emphasisLength = 0; #if FALSE int promptStart = _bufferWidth * Options.ExtraPromptLineCount; int promptWidth = _initialX; // Copy the prompt (ignoring the possible extra lines which we'll leave alone) var savedPrompt = new CHAR_INFO[promptWidth]; Array.Copy(_consoleBuffer, promptStart, savedPrompt, 0, promptWidth); string newPrompt = "(reverse-i-search)`': "; _initialX = newPrompt.Length; int i, j; for (i = promptStart, j = 0; j < newPrompt.Length; i++, j++) { _consoleBuffer[i].UnicodeChar = newPrompt[j]; _consoleBuffer[i].BackgroundColor = Console.BackgroundColor; _consoleBuffer[i].ForegroundColor = Console.ForegroundColor; } InteractiveHistorySearchLoop(direction); // Restore the original prompt _initialX = promptWidth; Array.Copy(savedPrompt, 0, _consoleBuffer, promptStart, savedPrompt.Length); #endif Render(); }
static void ClearScreen() { int bufferWidth = Console.BufferWidth; const int bufferLineCount = 10; var consoleBuffer = new CHAR_INFO[bufferWidth * bufferLineCount]; for (int i = 0; i < consoleBuffer.Length; i++) { consoleBuffer[i] = new CHAR_INFO(' ', Console.ForegroundColor, Console.BackgroundColor); } int top = 0; WriteBufferLines(consoleBuffer, ref top); }
private static void SetPrompt(string prompt) { if (string.IsNullOrEmpty(prompt)) return; var handle = NativeMethods.GetStdHandle((uint) StandardHandleId.Output); var lineCount = 1 + prompt.Count(c => c == '\n'); if (lineCount > 1) { var options = new SetPSReadlineOption {ExtraPromptLineCount = lineCount - 1}; PSConsoleReadLine.SetOptions(options); } int bufferWidth = Console.BufferWidth; var consoleBuffer = new CHAR_INFO[lineCount * bufferWidth]; int j = 0; for (int i = 0; i < prompt.Length; i++, j++) { if (prompt[i] == '\n') { for (; j % Console.BufferWidth != 0; j++) { consoleBuffer[j] = new CHAR_INFO(' ', Console.ForegroundColor, Console.BackgroundColor); } Console.CursorTop += 1; Console.CursorLeft = 0; j -= 1; // We don't actually write the newline } else { consoleBuffer[j] = new CHAR_INFO(prompt[i], Console.ForegroundColor, Console.BackgroundColor); Console.CursorLeft += 1; } } var bufferSize = new COORD { X = (short) bufferWidth, Y = (short) lineCount }; var bufferCoord = new COORD {X = 0, Y = 0}; var writeRegion = new SMALL_RECT { Top = 0, Left = 0, Bottom = (short) (lineCount - 1), Right = (short) bufferWidth }; NativeMethods.WriteConsoleOutput(handle, consoleBuffer, bufferSize, bufferCoord, ref writeRegion); }
private CHAR_INFO[] CreateCharInfoBuffer(int lines, params object[] items) { var result = new List<CHAR_INFO>(); var fg = Console.ForegroundColor; var bg = Console.BackgroundColor; foreach (var i in items) { var item = i; if (item is char) { result.Add(new CHAR_INFO((char)item, fg, bg)); continue; } if (item is InvertedToken) { fg = (ConsoleColor)((int)fg ^ 7); bg = (ConsoleColor)((int)bg ^ 7); continue; } if (item is NextLineToken) { item = new string(' ', Console.BufferWidth - (result.Count % Console.BufferWidth)); fg = Console.ForegroundColor; bg = Console.BackgroundColor; // Fallthrough to string case. } var str = item as string; if (str != null) { result.AddRange(str.Select(c => new CHAR_INFO(c, fg, bg))); continue; } if (item is TokenClassification) { fg = ForegroundColors[(int)(TokenClassification)item]; bg = BackgroundColors[(int)(TokenClassification)item]; continue; } var tuple = item as Tuple<ConsoleColor, ConsoleColor>; if (tuple != null) { fg = tuple.Item1; bg = tuple.Item2; continue; } throw new ArgumentException("Unexpected type"); } var extraSpacesNeeded = (lines * Console.BufferWidth) - result.Count; if (extraSpacesNeeded > 0) { var space = new CHAR_INFO(' ', Console.ForegroundColor, Console.BackgroundColor); result.AddRange(Enumerable.Repeat(space, extraSpacesNeeded)); } return result.ToArray(); }
private void PossibleCompletionsImpl(ConsoleKeyInfo? key, object arg, bool menuSelect) { var completions = GetCompletions(); if (completions == null || completions.CompletionMatches.Count == 0) { Ding(); return; } if (completions.CompletionMatches.Count >= _options.CompletionQueryItems) { if (!PromptYesOrNo(string.Format(PSReadLineResources.DisplayAllPossibilities, completions.CompletionMatches.Count))) { return; } } // Don't overwrite any of the line - so move to first line after the end of our buffer. var coords = ConvertOffsetToCoordinates(_buffer.Length); PlaceCursor(0, coords.Y + 1); var matches = completions.CompletionMatches; var minColWidth = matches.Max(c => c.ListItemText.Length); minColWidth += 2; var menuColumnWidth = minColWidth; CompletionResult[,] matchesMatrix; int displayColumns; int displayRows; var bufferWidth = Console.BufferWidth; var sb = new StringBuilder(bufferWidth); if (Options.ShowToolTips) { const string seperator = "- "; var maxTooltipWidth = bufferWidth - minColWidth - seperator.Length; matchesMatrix = new CompletionResult[1, matches.Count]; displayRows = matches.Count; displayColumns = 1; for (int index = 0; index < matches.Count; index++) { var match = matches[index]; matchesMatrix[0, index] = match; var listItemText = HandleNewlinesForPossibleCompletions(match.ListItemText); sb.Append(listItemText); var spacesNeeded = minColWidth - listItemText.Length; if (spacesNeeded > 0) sb.Append(' ', spacesNeeded); sb.Append(seperator); var toolTip = HandleNewlinesForPossibleCompletions(match.ToolTip); toolTip = toolTip.Length <= maxTooltipWidth ? toolTip : toolTip.Substring(0, maxTooltipWidth); sb.Append(toolTip); // Make sure we always write out exactly 1 buffer width spacesNeeded = bufferWidth - sb.Length; if (spacesNeeded > 0) { sb.Append(' ', spacesNeeded); } Console.Write(sb.ToString()); sb.Clear(); } menuColumnWidth = bufferWidth; } else { var screenColumns = bufferWidth; displayColumns = Math.Max(1, screenColumns / minColWidth); displayRows = (completions.CompletionMatches.Count + displayColumns - 1) / displayColumns; matchesMatrix = new CompletionResult[displayColumns, displayRows]; for (var row = 0; row < displayRows; row++) { for (var col = 0; col < displayColumns; col++) { var index = row + (displayRows * col); if (index >= matches.Count) break; var match = matches[index]; matchesMatrix[col, row] = match; var item = HandleNewlinesForPossibleCompletions(match.ListItemText); sb.Append(item); sb.Append(' ', minColWidth - item.Length); } // Make sure we always write out exactly 1 buffer width var spacesNeeded = bufferWidth - sb.Length; if (spacesNeeded > 0) { sb.Append(' ', spacesNeeded); } Console.Write(sb.ToString()); sb.Clear(); } } if (menuSelect) { // Move cursor back to the line. PlaceCursor(); StartEditGroup(); int top = coords.Y + 1; int selectedItem = 0; bool undo = false; InvertSelectedCompletion(top, 0, menuColumnWidth); DoReplacementForCompletion(matchesMatrix[0, 0], completions); int previousItem = selectedItem; bool processingKeys = true; while (processingKeys) { var nextKey = ReadKey(); if (nextKey == Keys.RightArrow) { selectedItem = Math.Min(selectedItem + displayRows, matches.Count - 1); } else if (nextKey == Keys.LeftArrow) { selectedItem = Math.Max(selectedItem - displayRows, 0); } else if (nextKey == Keys.DownArrow) { selectedItem = Math.Min(selectedItem + 1, matches.Count - 1); } else if (nextKey == Keys.UpArrow) { selectedItem = Math.Max(selectedItem - 1, 0); } else if (nextKey == Keys.Tab) { selectedItem = (selectedItem + 1) % matches.Count; } else if (nextKey == Keys.ShiftTab) { selectedItem = (selectedItem - 1) % matches.Count; if (selectedItem < 0) { selectedItem += matches.Count; } } else if (nextKey == Keys.CtrlG || nextKey == Keys.Escape) { undo = true; processingKeys = false; } else { PrependQueuedKeys(nextKey); processingKeys = false; } if (selectedItem != previousItem) { var selectedX = selectedItem / displayRows; var selectedY = selectedItem - (selectedX * displayRows); var completionResult = matchesMatrix[selectedX, selectedY]; if (completionResult != null) { var previousX = previousItem / displayRows; var previousY = previousItem - (previousX * displayRows); InvertSelectedCompletion(previousY + top, previousX, menuColumnWidth); InvertSelectedCompletion(selectedY + top, selectedX, menuColumnWidth); DoReplacementForCompletion(completionResult, completions); previousItem = selectedItem; } else { selectedItem = previousItem; } } } var blanks = new CHAR_INFO[displayRows * bufferWidth]; for (int i = 0; i < displayRows; i++) { blanks[i].BackgroundColor = Console.BackgroundColor; blanks[i].ForegroundColor = Console.ForegroundColor; blanks[i].UnicodeChar = ' '; } WriteBufferLines(blanks, ref top); EndEditGroup(); if (undo) { // Pretend it never happened. Undo(); } } else { _initialY = Console.CursorTop; Render(); } }