qamp/Qrakhen.Qamp.CLI/ConsoleWriter.cs

143 lines
4.1 KiB
C#

using System.Text;
public class ConsoleWriter
{
private const string SYMBOL_INPUT = " <: ";
private const string SYMBOL_INPUT_CONTINUE = " : ";
private readonly List<char> _buffer = [];
private readonly Stack<char[]> _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;
}
}