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 Ignored = [ '\0', '\b' ]; Benchmark.Active = false; LoggerService.Default = LogLevel.Error; List 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= \n", stdOut); write(" -d --dialect=\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; }