using System.Text; public class ConsoleWriter { private const string SYMBOL_INPUT = " <: "; private const string SYMBOL_INPUT_CONTINUE = " : "; private readonly List _buffer = []; private readonly Stack _history = []; private readonly Encoding _encoding; private int _position; private (int x, int y) _origin; private (int x, int y) _cursorPosition => Console.GetCursorPosition(); private int _cursorOffset => SYMBOL_INPUT.Length; private int _cursorLeft { get => Console.CursorLeft; set => Console.CursorLeft = value; } private int _cursorTop { get => Console.CursorTop; set => Console.CursorTop = value; } public bool UseSyntaxHighlighting { get; set; } = false; public ConsoleWriter(Encoding encoding) { _encoding = encoding; } private void Write(char c) => Console.Write(c); private void Write(string str) => Console.Write(str); private void SetCursor((int x, int y) position) => Console.SetCursorPosition(position.x, position.y); private void SetColor(ConsoleColor color, ConsoleColor background = ConsoleColor.Black) { Console.ForegroundColor = color; Console.BackgroundColor = background; } private void Move(int x, int y = 0) { _position = Math.Min(_buffer.Count, Math.Max(0, _position + x)); _cursorLeft -= 1; //???? } private void ClearLine() { int left = _cursorLeft; while (_cursorLeft < Console.BufferWidth - 1) Write(' '); _cursorLeft = left; } private void Print((int x, int y) origin, (int x, int y)? remain = null) { SetColor(ConsoleColor.White); SetCursor(origin); Write(" <: "); foreach (var c in _buffer) { if (c == '\n') { ClearLine(); Write("\n : "); } else { Write(c); } } ClearLine(); if (remain.HasValue) SetCursor(remain.Value); } private Stream Dispatch() { var stream = new MemoryStream(); var data = _buffer.ToArray(); stream.Write(_encoding.GetBytes(data)); _history.Push(data); _buffer.Clear(); return stream; } public ConsoleCode Read(out Stream? stream) { stream = null; ConsoleKeyInfo input; _origin = _cursorPosition; _position = 0; Print(_origin); do { if (UseSyntaxHighlighting) new ConsoleRenderer(new MemoryStream(_encoding.GetBytes(_buffer.ToArray()))).Render(_origin); // ~ so efficient ~ XD Print(_origin, _cursorPosition); input = Console.ReadKey(true); if (input.Modifiers == ConsoleModifiers.Control) { if (input.Key == ConsoleKey.C) return ConsoleCode.Exit; if (input.Key == ConsoleKey.H) { UseSyntaxHighlighting = !UseSyntaxHighlighting; Write($"\n #: {nameof(UseSyntaxHighlighting)} = {UseSyntaxHighlighting}\n <: "); _origin = _cursorPosition; } if (input.Key == ConsoleKey.LeftArrow) { } continue; } if (input.Key == ConsoleKey.LeftArrow) { if (_position > 0) { _position--; _cursorLeft--; } continue; } if (input.Key == ConsoleKey.RightArrow) { if (_position < _buffer.Count) { _position++; _cursorLeft++; } continue; } if (input.Key == ConsoleKey.Backspace) { if (_position > 0) { _cursorLeft--; _buffer.RemoveRange(--_position, 1); } continue; } else if (input.Check(ConsoleKey.Enter, ConsoleModifiers.Shift)) { _buffer.Insert(_position++, '\n'); _cursorLeft = _cursorOffset; _cursorTop++; continue; } else { _buffer.Insert(_position++, input.KeyChar); _cursorLeft++; } } while (!input.Check(ConsoleKey.Enter, ConsoleModifiers.None, true)); stream = Dispatch(); return ConsoleCode.OK; } }