qamp/Qrakhen.Qamp.CLI/Program.cs

234 lines
7.3 KiB
C#

using Qrakhen.Qamp.Core;
using Qrakhen.Qamp.Core.Execution;
using Qrakhen.Qamp.Core.Logging;
using System.Drawing;
using System.Runtime.CompilerServices;
using System.Text;
List<char> Ignored = [ '\0', '\b' ];
Benchmark.Active = false;
LoggerService.Default = LogLevel.Error;
List<byte[]> History = [];
int historyCursor = -1;
ConsoleKeyInfo input;
bool useSyntaxHighlighting = false;
(int x, int y) cursor = (0, 0);
ConsoleCode code = ConsoleCode.Error;
Runner runner = new(new Options());
Stream stdOut = Console.OpenStandardOutput();
Stream stdErr = Console.OpenStandardError();
Stream stdIn = Console.OpenStandardInput();
void write(string what, Stream stream) => stream.Write(Encoding.Default.GetBytes(what));
string[] flags = args.Where(x => x.StartsWith("-")).Select(x => x[1..]).ToArray();
string[] files = args.Where(x => !x.StartsWith("-")).ToArray();
if (flags.IndexOf("h") > 0)
{
write(" :: Q& Help.\n", stdOut);
write(" Basic usage: qamp {FILES} {OPTIONS}\n", stdOut);
write(" Flags:\n", stdOut);
write(" -i --interactive \n", stdOut);
write(" -n --nurture \n", stdOut);
write(" -l --log-level=<int> \n", stdOut);
write(" -d --dialect=<sqr|default>\n", stdOut);
write(" Example: qamp ~/myNiceScript.qp -i -n -l=0\n", stdOut);
return (int)QRESULT.OK;
}
if (files.Length > 0)
{
foreach (var file in files)
{
if (File.Exists(file))
{
var result = runner.Run(File.OpenRead(file));
write($" :: {file}: {result.RunnerResult} ({result.Returned})\n", stdOut);
}
else
{
write($"Could not find file located at '{file}'.\n", stdErr);
return (int)QRESULT.NOT_FOUND;
}
}
}
if (flags.IndexOf("i") < 0 && files.Length > 0)
{
return (int)QRESULT.OK;
}
if (flags.IndexOf("i") < 0)
{
write(" :: Assuming interactive mode (-i).\n :: If that is intended, use qamp -i to prevent this notification.\n", stdOut);
}
do {
Console.ForegroundColor = ConsoleColor.White;
MemoryStream stream = new MemoryStream();
write(" <: ", stdOut);
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;
//write(Colors.ColorText($"\n #: {nameof(useSyntaxHighlighting)} = {useSyntaxHighlighting}\n <: ", 30));
write($"\n #: {nameof(useSyntaxHighlighting)} = {useSyntaxHighlighting}\n <: ", stdOut);
cursor = Console.GetCursorPosition();
}
if (input.Key == ConsoleKey.B) {
Benchmark.Active = !Benchmark.Active;
//write(Colors.ColorText($"\n #: {nameof(Benchmark)}.{nameof(Benchmark.Active)} = {Benchmark.Active}\n <: ", 30));
write($"\n #: {nameof(Benchmark)}.{nameof(Benchmark.Active)} = {Benchmark.Active}\n <: ", stdOut);
cursor = Console.GetCursorPosition();
}
if (input.Key == ConsoleKey.L) {
LoggerService.Default = LoggerService.Default < LogLevel.All ? LogLevel.All : LogLevel.Info;
//write(Colors.ColorText($"\n #: LogLevel = {LoggerService.Default}\n <: ", 30));
write($"\n #: LogLevel = {LoggerService.Default}\n <: ", stdOut);
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.UpArrow) {
historyCursor = Math.Min(History.Count - 1, historyCursor + 1);
byte[] bytes = History[historyCursor];
continue;
}
if (input.Key == ConsoleKey.DownArrow) {
historyCursor = Math.Max(0, historyCursor - 1);
byte[] bytes = History[historyCursor];
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 {
History.Insert(0, stream.GetBuffer());
Console.WriteLine();
runner.Run(stream);
stream.Dispose();
} 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;
if (e.InnerException != null)
Console.WriteLine($" !? {e.InnerException.Message}");
Console.WriteLine($" !? {e.Message}");
if (e.StackTrace != null) {
Console.Write($" ! ");
Console.WriteLine(string.Join("\n ! ", e.StackTrace.Split('\n')));
}
}
} while (code != ConsoleCode.Exit);
return (int)QRESULT.OK;
// yes i'm making these up, just like anyone else
public enum QRESULT
{
OK = 0,
INVALID_ARGS = 0x14,
SYNTAX_ERROR = 0x72,
NOT_FOUND = 0x204
}
// leenux colors
public static class Colors
{
private readonly static int cBlack = 0,
cRed = 1,
cGreen = 2,
cYellow = 3,
cCyan = 4,
cPink = 5,
cCyanD = 6,
cWhite = 7;
private readonly static int fBack = 40,
fFore = 30;
private static string Wrap(int code) => @$"\e[{code}m";
// goote goute
public static string ColorText(string text, params int[] codes) =>
string.Join("", codes.Select(c => Wrap(c))) + text + Wrap(0);
public static string Red { get; } = Wrap(fFore + cRed);
}
public class Command
{
public class Parameters
{
}
public class Definition
{
public string Name { get; init; }
public string Alias { get; init; }
public class Parameter
{
public string Name { get; init; }
public string Alias { get; init; }
}
}
}
public class ArgumentAttribute(string name, string alias, string description)
{
public string Name { get; } = name;
public string Alias { get; } = alias;
public string Description { get; } = description;
}