public void Run() { _commands = LoadConsoleCommands(); Vt100.SwitchToAlternateBuffer(); Vt100.HideCursor(); InitializeScreen(); using (_repository) { while (!_done) { var width = Console.WindowWidth; var height = Console.WindowHeight; var key = Console.ReadKey(true); var command = _commands.FirstOrDefault(c => c.MatchesKey(key)); command?.Execute(); if (width != Console.WindowWidth || height != Console.WindowHeight) { InitializeScreen(); } } Vt100.ResetScrollMargins(); Vt100.SwitchToMainBuffer(); Vt100.ShowCursor(); } }
private void InitializeScreen() { var oldView = _view; _header = new Label(0, 0, Console.WindowWidth); _header.Foreground = ConsoleColor.Yellow; _header.Background = ConsoleColor.DarkGray; _view = new View(1, 0, Console.WindowHeight - 1, Console.WindowWidth); _view.SelectedLineChanged += delegate { UpdateHeader(); }; _footer = new Label(Console.WindowHeight - 1, 0, Console.WindowWidth); _footer.Foreground = ConsoleColor.Yellow; _footer.Background = ConsoleColor.DarkGray; Vt100.SetScrollMargins(2, Console.WindowHeight - 1); UpdateRepository(); if (oldView != null) { _view.VisibleWhitespace = oldView.VisibleWhitespace; _view.SelectedLine = oldView.SelectedLine; _view.BringIntoView(_view.SelectedLine); } }
protected void RenderLine(View view, int lineIndex, string line, ConsoleColor foregroundColor, ConsoleColor backgroundColor) { var textStart = Math.Min(view.LeftChar, line.Length); var textLength = Math.Max(Math.Min(view.Width, line.Length - view.LeftChar), 0); var text = textLength < 0 ? string.Empty : line.ToVisual(view.VisibleWhitespace).Substring(textStart, textLength); var visualLine = lineIndex - view.TopLine + view.Top; Vt100.SetCursorPosition(view.Left, visualLine); Vt100.SetForegroundColor(foregroundColor); Vt100.SetBackgroundColor(backgroundColor); Vt100.EraseRestOfCurrentLine(); Console.Write(text); if (view.SearchResults != null) { foreach (var hit in view.SearchResults.Hits) { if (hit.LineIndex == lineIndex) { var hitStart = Math.Min(Math.Max(hit.Start - view.LeftChar, 0), view.Width - 1) + view.LeftChar; var hitEnd = Math.Min(Math.Max(hit.Start + hit.Length - view.LeftChar, 0), view.Width - 1) + view.LeftChar; var hitLength = hitEnd - hitStart; if (hitLength > 0) { Vt100.SetCursorPosition(hitStart - view.LeftChar, visualLine); Vt100.NegativeColors(); Console.Write(line.Substring(hitStart, hitLength)); Vt100.PositiveColors(); } } } } }
private void RenderNonExistingLine(int visualLine) { Vt100.SetCursorPosition(0, visualLine); Vt100.SetForegroundColor(ConsoleColor.DarkGray); Vt100.SetBackgroundColor(ConsoleColor.Black); Console.Write("~"); Console.Write(_blankRow, 0, Width - 1); }
private void Render() { var textLength = Math.Min(_text.Length, _width); var text = _text.Substring(0, textLength); Vt100.SetCursorPosition(_left, _top); Vt100.SetForegroundColor(_foreground); Vt100.SetBackgroundColor(_background); Vt100.EraseRestOfCurrentLine(); Console.Write(text); }
private void UpdateTopLine(int value) { if (_topLine == value) { return; } if (value < 0 || value >= DocumentHeight) { throw new ArgumentOutOfRangeException(nameof(value)); } var delta = value - _topLine; _topLine = value; if (Math.Abs(delta) >= Height) { Render(); } else { if (delta < 0) { // We need to scroll up by -delta lines. Vt100.ScrollDown(Math.Abs(delta)); for (var i = 0; i < -delta; i++) { var line = _topLine + i; RenderLine(line); } } else { // We need to scroll down by delta lines. var visualLineCount = Height - delta; Vt100.ScrollUp(delta); for (var i = 0; i < delta; i++) { var line = _topLine + visualLineCount + i; RenderLine(line); } } } TopLineChanged?.Invoke(this, EventArgs.Empty); }
private void Search() { var sb = new StringBuilder(); while (true) { Vt100.HideCursor(); Vt100.SetCursorPosition(0, Console.WindowHeight - 1); Vt100.SetForegroundColor(ConsoleColor.Blue); Vt100.SetBackgroundColor(ConsoleColor.Gray); Console.Write("/"); Vt100.EraseRestOfCurrentLine(); Console.Write(sb); Vt100.ShowCursor(); var k = Console.ReadKey(intercept: true); if (k.Key == ConsoleKey.Enter) { break; } else if (k.Key == ConsoleKey.Escape) { sb.Clear(); break; } else if (k.Key == ConsoleKey.Backspace) { if (sb.Length > 0) { sb.Length--; } } else if (k.KeyChar >= 32) { sb.Append(k.KeyChar); if (sb.Length == Console.WindowWidth - 1) { break; } } } Vt100.HideCursor(); UpdateFooter(); if (sb.Length == 0) { return; } var searchResults = new SearchResults(_view.Document, sb.ToString()); if (searchResults.Hits.Count == 0) { Vt100.HideCursor(); Vt100.SetCursorPosition(0, Console.WindowHeight - 1); Vt100.SetForegroundColor(ConsoleColor.Blue); Vt100.SetBackgroundColor(ConsoleColor.Gray); Vt100.EraseRestOfCurrentLine(); Console.Write("<< NO RESULTS FOUND >>"); Console.ReadKey(); UpdateFooter(); return; } _view.SearchResults = searchResults; _view.SelectedLine = searchResults.Hits.First().LineIndex; }