308 lines
10 KiB
C#
308 lines
10 KiB
C#
|
|
using Qrakhen.Qamp.Core;
|
|
using Qrakhen.Qamp.Core.Execution;
|
|
using Qrakhen.Qamp.Core.Tokenization;
|
|
using System.Text;
|
|
|
|
char[] Ignored = [ '\0', '\b' ];
|
|
Stack<byte[]> History = [];
|
|
ConsoleKeyInfo input;
|
|
bool useSyntaxHighlighting = false;
|
|
(int x, int y) cursor = (0, 0);
|
|
ConsoleCode code = ConsoleCode.Error;
|
|
Runner runner = new Runner(new Options());
|
|
ConsoleInterface cli = new ConsoleInterface(Encoding.Default);
|
|
do {
|
|
/*Console.ForegroundColor = ConsoleColor.White;
|
|
MemoryStream stream = new MemoryStream();
|
|
Console.Write(" <: ");
|
|
cursor = Console.GetCursorPosition();
|
|
do {
|
|
if (useSyntaxHighlighting)
|
|
new ConsoleRenderer(stream).Render(cursor);
|
|
input = Console.ReadKey(true);
|
|
|
|
if (input.Modifiers == ConsoleModifiers.Control) {
|
|
if (input.Key == ConsoleKey.H) {
|
|
useSyntaxHighlighting = !useSyntaxHighlighting;
|
|
Console.Write($"\n #: {nameof(useSyntaxHighlighting)} = {useSyntaxHighlighting}\n <: ");
|
|
cursor = Console.GetCursorPosition();
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (input.Key == ConsoleKey.LeftArrow) {
|
|
if (stream.Position > 0) {
|
|
stream.Position--;
|
|
Console.CursorLeft--;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (input.Key == ConsoleKey.RightArrow) {
|
|
if (stream.Position < stream.Length) {
|
|
stream.Position++;
|
|
Console.CursorLeft++;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (input.Key == ConsoleKey.Backspace && stream.Position > 0) {
|
|
Console.CursorLeft -= 1;
|
|
Console.Write(' ');
|
|
if (!useSyntaxHighlighting)
|
|
Console.CursorLeft -= 1;
|
|
//stream.Position--;
|
|
//stream.SetLength(stream.Position);
|
|
stream.Remove(stream.Position - 1, 1);
|
|
} else if (input.Key == ConsoleKey.Enter && input.Modifiers == ConsoleModifiers.Shift) {
|
|
if (!useSyntaxHighlighting)
|
|
Console.Write("\n : ");
|
|
stream.Insert(Encoding.Default.GetBytes(Environment.NewLine));
|
|
} else if (Ignored.IndexOf(input.KeyChar) < 0) {
|
|
if (!useSyntaxHighlighting)
|
|
Console.Write(input.KeyChar);
|
|
stream.Insert(Encoding.Default.GetBytes([input.KeyChar], 0, 1));
|
|
}
|
|
} while (input.Key != ConsoleKey.Enter || input.Modifiers == ConsoleModifiers.Shift);*/
|
|
try {
|
|
code = cli.Read(out Stream? stream);
|
|
if (code == ConsoleCode.OK) {
|
|
if (stream == null)
|
|
throw new QampException($"Stream from CLI was null {code}");
|
|
Console.WriteLine();
|
|
runner.Run(stream);
|
|
}
|
|
if (code == ConsoleCode.Error)
|
|
throw new QampException($"CLI returned {code}");
|
|
}
|
|
catch (QampException e) {
|
|
Console.ForegroundColor = ConsoleColor.Yellow;
|
|
Console.WriteLine($" !> {e.Message}");
|
|
if (e.StackTrace != null) {
|
|
Console.Write($" ! ");
|
|
Console.WriteLine(string.Join("\n ! ", e.StackTrace.Split('\n')));
|
|
}
|
|
}
|
|
catch (Exception e) {
|
|
Console.ForegroundColor = ConsoleColor.DarkRed;
|
|
Console.WriteLine($" !? {e.Message}");
|
|
if (e.StackTrace != null) {
|
|
Console.Write($" ! ");
|
|
Console.WriteLine(string.Join("\n ! ", e.StackTrace.Split('\n')));
|
|
}
|
|
}
|
|
} while(code != ConsoleCode.Exit);
|
|
|
|
class ConsoleInterface
|
|
{
|
|
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 ConsoleInterface(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;
|
|
}
|
|
}
|
|
|
|
enum ConsoleCode
|
|
{
|
|
Error = -1,
|
|
OK = 0,
|
|
Exit = 1
|
|
}
|
|
|
|
class ConsoleRenderer
|
|
{
|
|
private readonly IReader<Token> _reader;
|
|
private readonly Stream _stream;
|
|
|
|
public ConsoleRenderer(Stream stream)
|
|
{
|
|
_stream = new MemoryStream();
|
|
stream.Position = 0;
|
|
stream.CopyTo(_stream);
|
|
_reader = new Reader(_stream);
|
|
}
|
|
|
|
public void Render((int x, int y) position)
|
|
{
|
|
Console.CursorVisible = false;
|
|
Console.SetCursorPosition(position.x, position.y);
|
|
List<Token> tokens = [];
|
|
while (!_reader.Done) {
|
|
tokens.Add(_reader.NextToken(true));
|
|
}
|
|
_stream.Position = 0;
|
|
foreach (var token in tokens) {
|
|
ConsoleColor color = ConsoleColor.Gray;
|
|
if (token.Type.IsBoolean())
|
|
color = ConsoleColor.Blue;
|
|
if (token.Type.IsString())
|
|
color = ConsoleColor.Red;
|
|
if (token.Type.IsNumber())
|
|
color = ConsoleColor.DarkCyan;
|
|
if (token.Type.IsOperator())
|
|
color = ConsoleColor.DarkGreen;
|
|
if (token.Type.IsBracket())
|
|
color = ConsoleColor.Yellow;
|
|
if (token.Type.IsIdentifier())
|
|
color = ConsoleColor.White;
|
|
if (token.Type.IsControl())
|
|
color = ConsoleColor.DarkYellow;
|
|
if (token.Type == TokenType.Error)
|
|
color = ConsoleColor.DarkRed;
|
|
Console.ForegroundColor = color;
|
|
byte[] buffer = new byte[token.Span.Length];
|
|
_stream.ReadExactly(buffer, 0, (int)token.Span.Length);
|
|
string str = Encoding.Default.GetString(buffer);
|
|
Console.Write(str);
|
|
Console.ForegroundColor = ConsoleColor.White;
|
|
if (token.Type == TokenType.NewLine)
|
|
Console.Write(" : ");
|
|
}
|
|
Console.ForegroundColor = ConsoleColor.White;
|
|
Console.CursorVisible = true;
|
|
}
|
|
}
|
|
|
|
public static class ConsoleExtensions
|
|
{
|
|
public static bool Check(this ConsoleKeyInfo keyInfo, ConsoleKey key, ConsoleModifiers modifier = default, bool exactModifier = false)
|
|
{
|
|
return ((exactModifier ?
|
|
keyInfo.Modifiers == modifier :
|
|
(keyInfo.Modifiers & modifier) == modifier)
|
|
&& keyInfo.Key == key);
|
|
}
|
|
} |